PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/xen-4.1.2/xen/arch/x86/x86_64/mmconfig-shared.c

#
C | 466 lines | 335 code | 84 blank | 47 comment | 83 complexity | 19db9381ad80f80acba91f0b89363df8 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, LGPL-2.0, GPL-2.0
  1. /*
  2. * mmconfig-shared.c - Low-level direct PCI config space access via
  3. * MMCONFIG - common code between i386 and x86-64.
  4. *
  5. * This code does:
  6. * - known chipset handling
  7. * - ACPI decoding and validation
  8. *
  9. * Per-architecture code takes care of the mappings and accesses
  10. * themselves.
  11. *
  12. * Author: Allen Kay <allen.m.kay@intel.com> - adapted to xen from Linux
  13. */
  14. #include <xen/config.h>
  15. #include <xen/init.h>
  16. #include <xen/mm.h>
  17. #include <xen/acpi.h>
  18. #include <xen/xmalloc.h>
  19. #include <xen/pci.h>
  20. #include <xen/pci_regs.h>
  21. #include <asm/e820.h>
  22. #include <asm/msr.h>
  23. #include <asm/msr-index.h>
  24. #include "mmconfig.h"
  25. static int __initdata known_bridge;
  26. unsigned int pci_probe = PCI_PROBE_CONF1 | PCI_PROBE_MMCONF;
  27. static void __init parse_mmcfg(char *s)
  28. {
  29. char *ss;
  30. do {
  31. ss = strchr(s, ',');
  32. if ( ss )
  33. *ss = '\0';
  34. if ( !parse_bool(s) )
  35. pci_probe &= ~PCI_PROBE_MMCONF;
  36. else if ( !strcmp(s, "amd_fam10") || !strcmp(s, "amd-fam10") )
  37. pci_probe |= PCI_CHECK_ENABLE_AMD_MMCONF;
  38. s = ss + 1;
  39. } while ( ss );
  40. }
  41. custom_param("mmcfg", parse_mmcfg);
  42. static const char __init *pci_mmcfg_e7520(void)
  43. {
  44. u32 win;
  45. win = pci_conf_read16(0, 0, 0, 0xce);
  46. win = win & 0xf000;
  47. if(win == 0x0000 || win == 0xf000)
  48. pci_mmcfg_config_num = 0;
  49. else {
  50. pci_mmcfg_config_num = 1;
  51. pci_mmcfg_config = xmalloc(struct acpi_mcfg_allocation);
  52. if (!pci_mmcfg_config)
  53. return NULL;
  54. memset(pci_mmcfg_config, 0, sizeof(pci_mmcfg_config[0]));
  55. pci_mmcfg_config[0].address = win << 16;
  56. pci_mmcfg_config[0].pci_segment = 0;
  57. pci_mmcfg_config[0].start_bus_number = 0;
  58. pci_mmcfg_config[0].end_bus_number = 255;
  59. }
  60. return "Intel Corporation E7520 Memory Controller Hub";
  61. }
  62. static const char __init *pci_mmcfg_intel_945(void)
  63. {
  64. u32 pciexbar, mask = 0, len = 0;
  65. pci_mmcfg_config_num = 1;
  66. pciexbar = pci_conf_read32(0, 0, 0, 0x48);
  67. /* Enable bit */
  68. if (!(pciexbar & 1))
  69. pci_mmcfg_config_num = 0;
  70. /* Size bits */
  71. switch ((pciexbar >> 1) & 3) {
  72. case 0:
  73. mask = 0xf0000000U;
  74. len = 0x10000000U;
  75. break;
  76. case 1:
  77. mask = 0xf8000000U;
  78. len = 0x08000000U;
  79. break;
  80. case 2:
  81. mask = 0xfc000000U;
  82. len = 0x04000000U;
  83. break;
  84. default:
  85. pci_mmcfg_config_num = 0;
  86. }
  87. /* Errata #2, things break when not aligned on a 256Mb boundary */
  88. /* Can only happen in 64M/128M mode */
  89. if ((pciexbar & mask) & 0x0fffffffU)
  90. pci_mmcfg_config_num = 0;
  91. /* Don't hit the APIC registers and their friends */
  92. if ((pciexbar & mask) >= 0xf0000000U)
  93. pci_mmcfg_config_num = 0;
  94. if (pci_mmcfg_config_num) {
  95. pci_mmcfg_config = xmalloc(struct acpi_mcfg_allocation);
  96. if (!pci_mmcfg_config)
  97. return NULL;
  98. memset(pci_mmcfg_config, 0, sizeof(pci_mmcfg_config[0]));
  99. pci_mmcfg_config[0].address = pciexbar & mask;
  100. pci_mmcfg_config[0].pci_segment = 0;
  101. pci_mmcfg_config[0].start_bus_number = 0;
  102. pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1;
  103. }
  104. return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
  105. }
  106. static const char __init *pci_mmcfg_amd_fam10h(void)
  107. {
  108. uint32_t address;
  109. uint64_t base, msr_content;
  110. int i;
  111. unsigned segnbits = 0, busnbits;
  112. if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF))
  113. return NULL;
  114. address = MSR_FAM10H_MMIO_CONF_BASE;
  115. if (rdmsr_safe(address, msr_content))
  116. return NULL;
  117. /* mmconfig is not enable */
  118. if (!(msr_content & FAM10H_MMIO_CONF_ENABLE))
  119. return NULL;
  120. base = msr_content &
  121. (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT);
  122. busnbits = (msr_content >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
  123. FAM10H_MMIO_CONF_BUSRANGE_MASK;
  124. /*
  125. * only handle bus 0 ?
  126. * need to skip it
  127. */
  128. if (!busnbits)
  129. return NULL;
  130. if (busnbits > 8) {
  131. segnbits = busnbits - 8;
  132. busnbits = 8;
  133. }
  134. pci_mmcfg_config_num = (1 << segnbits);
  135. pci_mmcfg_config = xmalloc_array(struct acpi_mcfg_allocation,
  136. pci_mmcfg_config_num);
  137. if (!pci_mmcfg_config)
  138. return NULL;
  139. for (i = 0; i < (1 << segnbits); i++) {
  140. pci_mmcfg_config[i].address = base + ((unsigned long)i << 28);
  141. pci_mmcfg_config[i].pci_segment = i;
  142. pci_mmcfg_config[i].start_bus_number = 0;
  143. pci_mmcfg_config[i].end_bus_number = (1 << busnbits) - 1;
  144. }
  145. return "AMD Family 10h NB";
  146. }
  147. static const char __init *pci_mmcfg_nvidia_mcp55(void)
  148. {
  149. static bool_t __initdata mcp55_checked;
  150. int bus, i;
  151. static const u32 extcfg_regnum = 0x90;
  152. static const u32 extcfg_enable_mask = 1<<31;
  153. static const u32 extcfg_start_mask = 0xff<<16;
  154. static const int extcfg_start_shift = 16;
  155. static const u32 extcfg_size_mask = 0x3<<28;
  156. static const int extcfg_size_shift = 28;
  157. static const int extcfg_sizebus[] = {0xff, 0x7f, 0x3f, 0x1f};
  158. static const u32 extcfg_base_mask[] = {0x7ff8, 0x7ffc, 0x7ffe, 0x7fff};
  159. static const int extcfg_base_lshift = 25;
  160. /* check if amd fam10h already took over */
  161. if (!acpi_disabled || pci_mmcfg_config_num || mcp55_checked)
  162. return NULL;
  163. mcp55_checked = 1;
  164. for (i = bus = 0; bus < 256; bus++) {
  165. u32 l, extcfg;
  166. u16 vendor, device;
  167. l = pci_conf_read32(bus, 0, 0, 0);
  168. vendor = l & 0xffff;
  169. device = (l >> 16) & 0xffff;
  170. if (PCI_VENDOR_ID_NVIDIA != vendor || 0x0369 != device)
  171. continue;
  172. extcfg = pci_conf_read32(bus, 0, 0, extcfg_regnum);
  173. if (extcfg & extcfg_enable_mask)
  174. i++;
  175. }
  176. if (!i)
  177. return NULL;
  178. pci_mmcfg_config_num = i;
  179. pci_mmcfg_config = xmalloc_array(struct acpi_mcfg_allocation,
  180. pci_mmcfg_config_num);
  181. for (i = bus = 0; bus < 256; bus++) {
  182. u64 base;
  183. u32 l, extcfg;
  184. u16 vendor, device;
  185. int size_index;
  186. l = pci_conf_read32(bus, 0, 0, 0);
  187. vendor = l & 0xffff;
  188. device = (l >> 16) & 0xffff;
  189. if (PCI_VENDOR_ID_NVIDIA != vendor || 0x0369 != device)
  190. continue;
  191. extcfg = pci_conf_read32(bus, 0, 0, extcfg_regnum);
  192. if (!(extcfg & extcfg_enable_mask))
  193. continue;
  194. if (i >= pci_mmcfg_config_num)
  195. break;
  196. size_index = (extcfg & extcfg_size_mask) >> extcfg_size_shift;
  197. base = extcfg & extcfg_base_mask[size_index];
  198. /* base could be > 4G */
  199. pci_mmcfg_config[i].address = base << extcfg_base_lshift;
  200. pci_mmcfg_config[i].pci_segment = 0;
  201. pci_mmcfg_config[i].start_bus_number =
  202. (extcfg & extcfg_start_mask) >> extcfg_start_shift;
  203. pci_mmcfg_config[i].end_bus_number =
  204. pci_mmcfg_config[i].start_bus_number + extcfg_sizebus[size_index];
  205. i++;
  206. }
  207. if (bus == 256)
  208. return "nVidia MCP55";
  209. pci_mmcfg_config_num = 0;
  210. xfree(pci_mmcfg_config);
  211. pci_mmcfg_config = NULL;
  212. return NULL;
  213. }
  214. struct pci_mmcfg_hostbridge_probe {
  215. u32 bus;
  216. u32 devfn;
  217. u32 vendor;
  218. u32 device;
  219. const char *(*probe)(void);
  220. };
  221. static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
  222. { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL,
  223. PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
  224. { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL,
  225. PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
  226. { 0, PCI_DEVFN(0x18, 0), PCI_VENDOR_ID_AMD,
  227. 0x1200, pci_mmcfg_amd_fam10h },
  228. { 0xff, PCI_DEVFN(0, 0), PCI_VENDOR_ID_AMD,
  229. 0x1200, pci_mmcfg_amd_fam10h },
  230. { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_NVIDIA,
  231. 0x0369, pci_mmcfg_nvidia_mcp55 },
  232. };
  233. static int __init pci_mmcfg_check_hostbridge(void)
  234. {
  235. u32 l;
  236. u32 bus, devfn;
  237. u16 vendor, device;
  238. int i;
  239. const char *name;
  240. pci_mmcfg_config_num = 0;
  241. pci_mmcfg_config = NULL;
  242. name = NULL;
  243. for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
  244. bus = pci_mmcfg_probes[i].bus;
  245. devfn = pci_mmcfg_probes[i].devfn;
  246. l = pci_conf_read32(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), 0);
  247. vendor = l & 0xffff;
  248. device = (l >> 16) & 0xffff;
  249. if (pci_mmcfg_probes[i].vendor == vendor &&
  250. pci_mmcfg_probes[i].device == device)
  251. name = pci_mmcfg_probes[i].probe();
  252. }
  253. if (name) {
  254. printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n",
  255. name, pci_mmcfg_config_num ? "with" : "without");
  256. }
  257. return name != NULL;
  258. }
  259. typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type);
  260. static int __init is_mmconf_reserved(
  261. check_reserved_t is_reserved,
  262. u64 addr, u64 size, int i,
  263. typeof(pci_mmcfg_config[0]) *cfg, int with_e820)
  264. {
  265. u64 old_size = size;
  266. int valid = 0;
  267. while (!is_reserved(addr, addr + size - 1, E820_RESERVED)) {
  268. size >>= 1;
  269. if (size < (16UL<<20))
  270. break;
  271. }
  272. if (size >= (16UL<<20) || size == old_size) {
  273. printk(KERN_NOTICE
  274. "PCI: MCFG area at %lx reserved in %s\n",
  275. addr, with_e820?"E820":"ACPI motherboard resources");
  276. valid = 1;
  277. if (old_size != size) {
  278. /* update end_bus_number */
  279. cfg->end_bus_number = cfg->start_bus_number + ((size>>20) - 1);
  280. printk(KERN_NOTICE "PCI: updated MCFG configuration %d: base %lx "
  281. "segment %hu buses %u - %u\n",
  282. i, (unsigned long)cfg->address, cfg->pci_segment,
  283. (unsigned int)cfg->start_bus_number,
  284. (unsigned int)cfg->end_bus_number);
  285. }
  286. }
  287. return valid;
  288. }
  289. static void __init pci_mmcfg_reject_broken(void)
  290. {
  291. typeof(pci_mmcfg_config[0]) *cfg;
  292. int i;
  293. if ((pci_mmcfg_config_num == 0) ||
  294. (pci_mmcfg_config == NULL) ||
  295. (pci_mmcfg_config[0].address == 0))
  296. return;
  297. cfg = &pci_mmcfg_config[0];
  298. for (i = 0; i < pci_mmcfg_config_num; i++) {
  299. u64 addr, size;
  300. cfg = &pci_mmcfg_config[i];
  301. addr = cfg->start_bus_number;
  302. addr <<= 20;
  303. addr += cfg->address;
  304. size = cfg->end_bus_number + 1 - cfg->start_bus_number;
  305. size <<= 20;
  306. printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx "
  307. "segment %hu buses %u - %u\n",
  308. i, (unsigned long)cfg->address, cfg->pci_segment,
  309. (unsigned int)cfg->start_bus_number,
  310. (unsigned int)cfg->end_bus_number);
  311. if (!is_mmconf_reserved(e820_all_mapped, addr, size, i, cfg, 1))
  312. goto reject;
  313. }
  314. return;
  315. reject:
  316. printk(KERN_INFO "PCI: Not using MMCONFIG.\n");
  317. pci_mmcfg_arch_free();
  318. xfree(pci_mmcfg_config);
  319. pci_mmcfg_config = NULL;
  320. pci_mmcfg_config_num = 0;
  321. }
  322. void __init acpi_mmcfg_init(void)
  323. {
  324. /* MMCONFIG disabled */
  325. if ((pci_probe & PCI_PROBE_MMCONF) == 0)
  326. return;
  327. /* MMCONFIG already enabled */
  328. if (!(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
  329. return;
  330. /* for late to exit */
  331. if (known_bridge)
  332. return;
  333. if (pci_mmcfg_check_hostbridge())
  334. known_bridge = 1;
  335. if (!known_bridge) {
  336. acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
  337. pci_mmcfg_reject_broken();
  338. }
  339. if ((pci_mmcfg_config_num == 0) ||
  340. (pci_mmcfg_config == NULL) ||
  341. (pci_mmcfg_config[0].address == 0))
  342. return;
  343. if (pci_mmcfg_arch_init()) {
  344. pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
  345. }
  346. }
  347. /**
  348. * pci_find_ext_capability - Find an extended capability
  349. * @dev: PCI device to query
  350. * @cap: capability code
  351. *
  352. * Returns the address of the requested extended capability structure
  353. * within the device's PCI configuration space or 0 if the device does
  354. * not support it. Possible values for @cap:
  355. *
  356. * %PCI_EXT_CAP_ID_ERR Advanced Error Reporting
  357. * %PCI_EXT_CAP_ID_VC Virtual Channel
  358. * %PCI_EXT_CAP_ID_DSN Device Serial Number
  359. * %PCI_EXT_CAP_ID_PWR Power Budgeting
  360. */
  361. int pci_find_ext_capability(int seg, int bus, int devfn, int cap)
  362. {
  363. u32 header;
  364. int ttl = 480; /* 3840 bytes, minimum 8 bytes per capability */
  365. int pos = 0x100;
  366. header = pci_conf_read32(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos);
  367. /*
  368. * If we have no capabilities, this is indicated by cap ID,
  369. * cap version and next pointer all being 0.
  370. */
  371. if ( (header == 0) || (header == -1) )
  372. return 0;
  373. while ( ttl-- > 0 ) {
  374. if ( PCI_EXT_CAP_ID(header) == cap )
  375. return pos;
  376. pos = PCI_EXT_CAP_NEXT(header);
  377. if ( pos < 0x100 )
  378. break;
  379. header = pci_conf_read32(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos);
  380. }
  381. return 0;
  382. }