2 * mmconfig-shared.c - Low-level direct PCI config space access via
3 * MMCONFIG - common code between i386 and x86-64.
6 * - known chipset handling
7 * - ACPI decoding and validation
9 * Per-architecture code takes care of the mappings and accesses
13 #include <linux/pci.h>
14 #include <linux/init.h>
15 #include <linux/acpi.h>
16 #include <linux/bitmap.h>
18 #include <asm/pci_x86.h>
20 /* aperture is up to 256MB but BIOS may reserve less */
21 #define MMCONFIG_APER_MIN (2 * 1024*1024)
22 #define MMCONFIG_APER_MAX (256 * 1024*1024)
24 /* Indicate if the mmcfg resources have been placed into the resource table. */
25 static int __initdata pci_mmcfg_resources_inserted
;
27 static const char __init
*pci_mmcfg_e7520(void)
30 raw_pci_ops
->read(0, 0, PCI_DEVFN(0, 0), 0xce, 2, &win
);
33 if(win
== 0x0000 || win
== 0xf000)
34 pci_mmcfg_config_num
= 0;
36 pci_mmcfg_config_num
= 1;
37 pci_mmcfg_config
= kzalloc(sizeof(pci_mmcfg_config
[0]), GFP_KERNEL
);
38 if (!pci_mmcfg_config
)
40 pci_mmcfg_config
[0].address
= win
<< 16;
41 pci_mmcfg_config
[0].pci_segment
= 0;
42 pci_mmcfg_config
[0].start_bus_number
= 0;
43 pci_mmcfg_config
[0].end_bus_number
= 255;
46 return "Intel Corporation E7520 Memory Controller Hub";
49 static const char __init
*pci_mmcfg_intel_945(void)
51 u32 pciexbar
, mask
= 0, len
= 0;
53 pci_mmcfg_config_num
= 1;
55 raw_pci_ops
->read(0, 0, PCI_DEVFN(0, 0), 0x48, 4, &pciexbar
);
59 pci_mmcfg_config_num
= 0;
62 switch ((pciexbar
>> 1) & 3) {
76 pci_mmcfg_config_num
= 0;
79 /* Errata #2, things break when not aligned on a 256Mb boundary */
80 /* Can only happen in 64M/128M mode */
82 if ((pciexbar
& mask
) & 0x0fffffffU
)
83 pci_mmcfg_config_num
= 0;
85 /* Don't hit the APIC registers and their friends */
86 if ((pciexbar
& mask
) >= 0xf0000000U
)
87 pci_mmcfg_config_num
= 0;
89 if (pci_mmcfg_config_num
) {
90 pci_mmcfg_config
= kzalloc(sizeof(pci_mmcfg_config
[0]), GFP_KERNEL
);
91 if (!pci_mmcfg_config
)
93 pci_mmcfg_config
[0].address
= pciexbar
& mask
;
94 pci_mmcfg_config
[0].pci_segment
= 0;
95 pci_mmcfg_config
[0].start_bus_number
= 0;
96 pci_mmcfg_config
[0].end_bus_number
= (len
>> 20) - 1;
99 return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
102 static const char __init
*pci_mmcfg_amd_fam10h(void)
104 u32 low
, high
, address
;
107 unsigned segnbits
= 0, busnbits
;
109 if (!(pci_probe
& PCI_CHECK_ENABLE_AMD_MMCONF
))
112 address
= MSR_FAM10H_MMIO_CONF_BASE
;
113 if (rdmsr_safe(address
, &low
, &high
))
120 /* mmconfig is not enable */
121 if (!(msr
& FAM10H_MMIO_CONF_ENABLE
))
124 base
= msr
& (FAM10H_MMIO_CONF_BASE_MASK
<<FAM10H_MMIO_CONF_BASE_SHIFT
);
126 busnbits
= (msr
>> FAM10H_MMIO_CONF_BUSRANGE_SHIFT
) &
127 FAM10H_MMIO_CONF_BUSRANGE_MASK
;
130 * only handle bus 0 ?
137 segnbits
= busnbits
- 8;
141 pci_mmcfg_config_num
= (1 << segnbits
);
142 pci_mmcfg_config
= kzalloc(sizeof(pci_mmcfg_config
[0]) *
143 pci_mmcfg_config_num
, GFP_KERNEL
);
144 if (!pci_mmcfg_config
)
147 for (i
= 0; i
< (1 << segnbits
); i
++) {
148 pci_mmcfg_config
[i
].address
= base
+ (1<<28) * i
;
149 pci_mmcfg_config
[i
].pci_segment
= i
;
150 pci_mmcfg_config
[i
].start_bus_number
= 0;
151 pci_mmcfg_config
[i
].end_bus_number
= (1 << busnbits
) - 1;
154 return "AMD Family 10h NB";
157 struct pci_mmcfg_hostbridge_probe
{
162 const char *(*probe
)(void);
165 static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes
[] __initdata
= {
166 { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL
,
167 PCI_DEVICE_ID_INTEL_E7520_MCH
, pci_mmcfg_e7520
},
168 { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL
,
169 PCI_DEVICE_ID_INTEL_82945G_HB
, pci_mmcfg_intel_945
},
170 { 0, PCI_DEVFN(0x18, 0), PCI_VENDOR_ID_AMD
,
171 0x1200, pci_mmcfg_amd_fam10h
},
172 { 0xff, PCI_DEVFN(0, 0), PCI_VENDOR_ID_AMD
,
173 0x1200, pci_mmcfg_amd_fam10h
},
176 static int __init
pci_mmcfg_check_hostbridge(void)
187 pci_mmcfg_config_num
= 0;
188 pci_mmcfg_config
= NULL
;
191 for (i
= 0; !name
&& i
< ARRAY_SIZE(pci_mmcfg_probes
); i
++) {
192 bus
= pci_mmcfg_probes
[i
].bus
;
193 devfn
= pci_mmcfg_probes
[i
].devfn
;
194 raw_pci_ops
->read(0, bus
, devfn
, 0, 4, &l
);
196 device
= (l
>> 16) & 0xffff;
198 if (pci_mmcfg_probes
[i
].vendor
== vendor
&&
199 pci_mmcfg_probes
[i
].device
== device
)
200 name
= pci_mmcfg_probes
[i
].probe();
204 printk(KERN_INFO
"PCI: Found %s %s MMCONFIG support.\n",
205 name
, pci_mmcfg_config_num
? "with" : "without");
211 static void __init
pci_mmcfg_insert_resources(void)
213 #define PCI_MMCFG_RESOURCE_NAME_LEN 19
215 struct resource
*res
;
219 res
= kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN
+ sizeof(*res
),
220 pci_mmcfg_config_num
, GFP_KERNEL
);
222 printk(KERN_ERR
"PCI: Unable to allocate MMCONFIG resources\n");
226 names
= (void *)&res
[pci_mmcfg_config_num
];
227 for (i
= 0; i
< pci_mmcfg_config_num
; i
++, res
++) {
228 struct acpi_mcfg_allocation
*cfg
= &pci_mmcfg_config
[i
];
229 num_buses
= cfg
->end_bus_number
- cfg
->start_bus_number
+ 1;
231 snprintf(names
, PCI_MMCFG_RESOURCE_NAME_LEN
, "PCI MMCONFIG %u",
233 res
->start
= cfg
->address
;
234 res
->end
= res
->start
+ (num_buses
<< 20) - 1;
235 res
->flags
= IORESOURCE_MEM
| IORESOURCE_BUSY
;
236 insert_resource(&iomem_resource
, res
);
237 names
+= PCI_MMCFG_RESOURCE_NAME_LEN
;
240 /* Mark that the resources have been inserted. */
241 pci_mmcfg_resources_inserted
= 1;
244 static acpi_status __init
check_mcfg_resource(struct acpi_resource
*res
,
247 struct resource
*mcfg_res
= data
;
248 struct acpi_resource_address64 address
;
251 if (res
->type
== ACPI_RESOURCE_TYPE_FIXED_MEMORY32
) {
252 struct acpi_resource_fixed_memory32
*fixmem32
=
253 &res
->data
.fixed_memory32
;
256 if ((mcfg_res
->start
>= fixmem32
->address
) &&
257 (mcfg_res
->end
< (fixmem32
->address
+
258 fixmem32
->address_length
))) {
260 return AE_CTRL_TERMINATE
;
263 if ((res
->type
!= ACPI_RESOURCE_TYPE_ADDRESS32
) &&
264 (res
->type
!= ACPI_RESOURCE_TYPE_ADDRESS64
))
267 status
= acpi_resource_to_address64(res
, &address
);
268 if (ACPI_FAILURE(status
) ||
269 (address
.address_length
<= 0) ||
270 (address
.resource_type
!= ACPI_MEMORY_RANGE
))
273 if ((mcfg_res
->start
>= address
.minimum
) &&
274 (mcfg_res
->end
< (address
.minimum
+ address
.address_length
))) {
276 return AE_CTRL_TERMINATE
;
281 static acpi_status __init
find_mboard_resource(acpi_handle handle
, u32 lvl
,
282 void *context
, void **rv
)
284 struct resource
*mcfg_res
= context
;
286 acpi_walk_resources(handle
, METHOD_NAME__CRS
,
287 check_mcfg_resource
, context
);
290 return AE_CTRL_TERMINATE
;
295 static int __init
is_acpi_reserved(u64 start
, u64 end
, unsigned not_used
)
297 struct resource mcfg_res
;
299 mcfg_res
.start
= start
;
300 mcfg_res
.end
= end
- 1;
303 acpi_get_devices("PNP0C01", find_mboard_resource
, &mcfg_res
, NULL
);
306 acpi_get_devices("PNP0C02", find_mboard_resource
, &mcfg_res
,
309 return mcfg_res
.flags
;
312 typedef int (*check_reserved_t
)(u64 start
, u64 end
, unsigned type
);
314 static int __init
is_mmconf_reserved(check_reserved_t is_reserved
,
315 u64 addr
, u64 size
, int i
,
316 typeof(pci_mmcfg_config
[0]) *cfg
, int with_e820
)
321 while (!is_reserved(addr
, addr
+ size
, E820_RESERVED
)) {
323 if (size
< (16UL<<20))
327 if (size
>= (16UL<<20) || size
== old_size
) {
329 "PCI: MCFG area at %Lx reserved in %s\n",
330 addr
, with_e820
?"E820":"ACPI motherboard resources");
333 if (old_size
!= size
) {
334 /* update end_bus_number */
335 cfg
->end_bus_number
= cfg
->start_bus_number
+ ((size
>>20) - 1);
336 printk(KERN_NOTICE
"PCI: updated MCFG configuration %d: base %lx "
337 "segment %hu buses %u - %u\n",
338 i
, (unsigned long)cfg
->address
, cfg
->pci_segment
,
339 (unsigned int)cfg
->start_bus_number
,
340 (unsigned int)cfg
->end_bus_number
);
347 static void __init
pci_mmcfg_reject_broken(int early
)
349 typeof(pci_mmcfg_config
[0]) *cfg
;
352 if ((pci_mmcfg_config_num
== 0) ||
353 (pci_mmcfg_config
== NULL
) ||
354 (pci_mmcfg_config
[0].address
== 0))
357 cfg
= &pci_mmcfg_config
[0];
359 for (i
= 0; i
< pci_mmcfg_config_num
; i
++) {
363 cfg
= &pci_mmcfg_config
[i
];
364 addr
= cfg
->start_bus_number
;
366 addr
+= cfg
->address
;
367 size
= cfg
->end_bus_number
+ 1 - cfg
->start_bus_number
;
369 printk(KERN_NOTICE
"PCI: MCFG configuration %d: base %lx "
370 "segment %hu buses %u - %u\n",
371 i
, (unsigned long)cfg
->address
, cfg
->pci_segment
,
372 (unsigned int)cfg
->start_bus_number
,
373 (unsigned int)cfg
->end_bus_number
);
376 valid
= is_mmconf_reserved(is_acpi_reserved
, addr
, size
, i
, cfg
, 0);
382 printk(KERN_ERR
"PCI: BIOS Bug: MCFG area at %Lx is not"
383 " reserved in ACPI motherboard resources\n",
386 /* Don't try to do this check unless configuration
387 type 1 is available. how about type 2 ?*/
389 valid
= is_mmconf_reserved(e820_all_mapped
, addr
, size
, i
, cfg
, 1);
398 printk(KERN_INFO
"PCI: Not using MMCONFIG.\n");
399 pci_mmcfg_arch_free();
400 kfree(pci_mmcfg_config
);
401 pci_mmcfg_config
= NULL
;
402 pci_mmcfg_config_num
= 0;
405 static int __initdata known_bridge
;
407 static void __init
__pci_mmcfg_init(int early
)
409 /* MMCONFIG disabled */
410 if ((pci_probe
& PCI_PROBE_MMCONF
) == 0)
413 /* MMCONFIG already enabled */
414 if (!early
&& !(pci_probe
& PCI_PROBE_MASK
& ~PCI_PROBE_MMCONF
))
417 /* for late to exit */
422 if (pci_mmcfg_check_hostbridge())
427 acpi_table_parse(ACPI_SIG_MCFG
, acpi_parse_mcfg
);
428 pci_mmcfg_reject_broken(early
);
431 if ((pci_mmcfg_config_num
== 0) ||
432 (pci_mmcfg_config
== NULL
) ||
433 (pci_mmcfg_config
[0].address
== 0))
436 if (pci_mmcfg_arch_init())
437 pci_probe
= (pci_probe
& ~PCI_PROBE_MASK
) | PCI_PROBE_MMCONF
;
440 * Signal not to attempt to insert mmcfg resources because
441 * the architecture mmcfg setup could not initialize.
443 pci_mmcfg_resources_inserted
= 1;
447 void __init
pci_mmcfg_early_init(void)
452 void __init
pci_mmcfg_late_init(void)
457 static int __init
pci_mmcfg_late_insert_resources(void)
460 * If resources are already inserted or we are not using MMCONFIG,
461 * don't insert the resources.
463 if ((pci_mmcfg_resources_inserted
== 1) ||
464 (pci_probe
& PCI_PROBE_MMCONF
) == 0 ||
465 (pci_mmcfg_config_num
== 0) ||
466 (pci_mmcfg_config
== NULL
) ||
467 (pci_mmcfg_config
[0].address
== 0))
471 * Attempt to insert the mmcfg resources but not with the busy flag
472 * marked so it won't cause request errors when __request_region is
475 pci_mmcfg_insert_resources();
481 * Perform MMCONFIG resource insertion after PCI initialization to allow for
482 * misprogrammed MCFG tables that state larger sizes but actually conflict
483 * with other system resources.
485 late_initcall(pci_mmcfg_late_insert_resources
);