direct-io.hg

view patches/linux-2.6.16.29/pci-mmconfig-fix-from-2.6.17.patch @ 11750:d845c9522d9e

[HVM][SVM] Check if SVM is disabled by the BIOS before enabling it.

Newer BIOS implementations will be able to disable the SVM feature,
although an additional test of an MSR (VMCR 0xC0010114 bit 4) is
necessary (set equals disabled). Bit 4 of MSR 0xc0010114 returns 0
(SVM enabled) on machines with older BIOS' without the SVM disable
feature support.

Signed-off-by: Wei Huang <wei.huang2@amd.com>=20
Signed-off-by: Tom Woller <thomas.woller@amd.com>=20
author kfraser@localhost.localdomain
date Thu Oct 12 16:12:10 2006 +0100 (2006-10-12)
parents e50872355390
children
line source
1 diff -pruN ../orig-linux-2.6.16.29/arch/i386/pci/mmconfig.c ./arch/i386/pci/mmconfig.c
2 --- ../orig-linux-2.6.16.29/arch/i386/pci/mmconfig.c 2006-09-12 19:02:10.000000000 +0100
3 +++ ./arch/i386/pci/mmconfig.c 2006-09-21 09:35:27.000000000 +0100
4 @@ -12,14 +12,22 @@
5 #include <linux/pci.h>
6 #include <linux/init.h>
7 #include <linux/acpi.h>
8 +#include <asm/e820.h>
9 #include "pci.h"
11 +/* aperture is up to 256MB but BIOS may reserve less */
12 +#define MMCONFIG_APER_MIN (2 * 1024*1024)
13 +#define MMCONFIG_APER_MAX (256 * 1024*1024)
14 +
15 +/* Assume systems with more busses have correct MCFG */
16 +#define MAX_CHECK_BUS 16
17 +
18 #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
20 /* The base address of the last MMCONFIG device accessed */
21 static u32 mmcfg_last_accessed_device;
23 -static DECLARE_BITMAP(fallback_slots, 32);
24 +static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
26 /*
27 * Functions for accessing PCI configuration space with MMCONFIG accesses
28 @@ -29,8 +37,8 @@ static u32 get_base_addr(unsigned int se
29 int cfg_num = -1;
30 struct acpi_table_mcfg_config *cfg;
32 - if (seg == 0 && bus == 0 &&
33 - test_bit(PCI_SLOT(devfn), fallback_slots))
34 + if (seg == 0 && bus < MAX_CHECK_BUS &&
35 + test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
36 return 0;
38 while (1) {
39 @@ -74,8 +82,10 @@ static int pci_mmcfg_read(unsigned int s
40 unsigned long flags;
41 u32 base;
43 - if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
44 + if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
45 + *value = -1;
46 return -EINVAL;
47 + }
49 base = get_base_addr(seg, bus, devfn);
50 if (!base)
51 @@ -146,30 +156,66 @@ static struct pci_raw_ops pci_mmcfg = {
52 Normally this can be expressed in the MCFG by not listing them
53 and assigning suitable _SEGs, but this isn't implemented in some BIOS.
54 Instead try to discover all devices on bus 0 that are unreachable using MM
55 - and fallback for them.
56 - We only do this for bus 0/seg 0 */
57 + and fallback for them. */
58 static __init void unreachable_devices(void)
59 {
60 - int i;
61 + int i, k;
62 unsigned long flags;
64 - for (i = 0; i < 32; i++) {
65 - u32 val1;
66 - u32 addr;
67 + for (k = 0; k < MAX_CHECK_BUS; k++) {
68 + for (i = 0; i < 32; i++) {
69 + u32 val1;
70 + u32 addr;
71 +
72 + pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1);
73 + if (val1 == 0xffffffff)
74 + continue;
75 +
76 + /* Locking probably not needed, but safer */
77 + spin_lock_irqsave(&pci_config_lock, flags);
78 + addr = get_base_addr(0, k, PCI_DEVFN(i, 0));
79 + if (addr != 0)
80 + pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
81 + if (addr == 0 ||
82 + readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
83 + set_bit(i, fallback_slots);
84 + printk(KERN_NOTICE
85 + "PCI: No mmconfig possible on %x:%x\n", k, i);
86 + }
87 + spin_unlock_irqrestore(&pci_config_lock, flags);
88 + }
89 + }
90 +}
92 - pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1);
93 - if (val1 == 0xffffffff)
94 +/* NB. Ripped from arch/i386/kernel/setup.c for this Xen bugfix patch. */
95 +#ifdef CONFIG_XEN
96 +extern struct e820map machine_e820;
97 +#define e820 machine_e820
98 +#endif
99 +static int __init
100 +e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
101 +{
102 + u64 start = s;
103 + u64 end = e;
104 + int i;
105 + for (i = 0; i < e820.nr_map; i++) {
106 + struct e820entry *ei = &e820.map[i];
107 + if (type && ei->type != type)
108 continue;
109 -
110 - /* Locking probably not needed, but safer */
111 - spin_lock_irqsave(&pci_config_lock, flags);
112 - addr = get_base_addr(0, 0, PCI_DEVFN(i, 0));
113 - if (addr != 0)
114 - pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0));
115 - if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1)
116 - set_bit(i, fallback_slots);
117 - spin_unlock_irqrestore(&pci_config_lock, flags);
118 + /* is the region (part) in overlap with the current region ?*/
119 + if (ei->addr >= end || ei->addr + ei->size <= start)
120 + continue;
121 + /* if the region is at the beginning of <start,end> we move
122 + * start to the end of the region since it's ok until there
123 + */
124 + if (ei->addr <= start)
125 + start = ei->addr + ei->size;
126 + /* if start is now at or beyond end, we're done, full
127 + * coverage */
128 + if (start >= end)
129 + return 1; /* we're done */
130 }
131 + return 0;
132 }
134 static int __init pci_mmcfg_init(void)
135 @@ -183,6 +229,15 @@ static int __init pci_mmcfg_init(void)
136 (pci_mmcfg_config[0].base_address == 0))
137 goto out;
139 + if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
140 + pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
141 + E820_RESERVED)) {
142 + printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
143 + pci_mmcfg_config[0].base_address);
144 + printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
145 + goto out;
146 + }
147 +
148 printk(KERN_INFO "PCI: Using MMCONFIG\n");
149 raw_pci_ops = &pci_mmcfg;
150 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
151 diff -pruN ../orig-linux-2.6.16.29/arch/x86_64/pci/mmconfig.c ./arch/x86_64/pci/mmconfig.c
152 --- ../orig-linux-2.6.16.29/arch/x86_64/pci/mmconfig.c 2006-09-12 19:02:10.000000000 +0100
153 +++ ./arch/x86_64/pci/mmconfig.c 2006-09-21 09:35:40.000000000 +0100
154 @@ -9,11 +9,19 @@
155 #include <linux/init.h>
156 #include <linux/acpi.h>
157 #include <linux/bitmap.h>
158 +#include <asm/e820.h>
159 +
160 #include "pci.h"
162 -#define MMCONFIG_APER_SIZE (256*1024*1024)
163 +/* aperture is up to 256MB but BIOS may reserve less */
164 +#define MMCONFIG_APER_MIN (2 * 1024*1024)
165 +#define MMCONFIG_APER_MAX (256 * 1024*1024)
166 +
167 +/* Verify the first 16 busses. We assume that systems with more busses
168 + get MCFG right. */
169 +#define MAX_CHECK_BUS 16
171 -static DECLARE_BITMAP(fallback_slots, 32);
172 +static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);
174 /* Static virtual mapping of the MMCONFIG aperture */
175 struct mmcfg_virt {
176 @@ -55,7 +63,8 @@ static char __iomem *get_virt(unsigned i
177 static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
178 {
179 char __iomem *addr;
180 - if (seg == 0 && bus == 0 && test_bit(PCI_SLOT(devfn), &fallback_slots))
181 + if (seg == 0 && bus < MAX_CHECK_BUS &&
182 + test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
183 return NULL;
184 addr = get_virt(seg, bus);
185 if (!addr)
186 @@ -69,8 +78,10 @@ static int pci_mmcfg_read(unsigned int s
187 char __iomem *addr;
189 /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
190 - if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095)))
191 + if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
192 + *value = -1;
193 return -EINVAL;
194 + }
196 addr = pci_dev_base(seg, bus, devfn);
197 if (!addr)
198 @@ -129,23 +140,56 @@ static struct pci_raw_ops pci_mmcfg = {
199 Normally this can be expressed in the MCFG by not listing them
200 and assigning suitable _SEGs, but this isn't implemented in some BIOS.
201 Instead try to discover all devices on bus 0 that are unreachable using MM
202 - and fallback for them.
203 - We only do this for bus 0/seg 0 */
204 + and fallback for them. */
205 static __init void unreachable_devices(void)
206 {
207 - int i;
208 - for (i = 0; i < 32; i++) {
209 - u32 val1;
210 - char __iomem *addr;
211 + int i, k;
212 + /* Use the max bus number from ACPI here? */
213 + for (k = 0; k < MAX_CHECK_BUS; k++) {
214 + for (i = 0; i < 32; i++) {
215 + u32 val1;
216 + char __iomem *addr;
217 +
218 + pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
219 + if (val1 == 0xffffffff)
220 + continue;
221 + addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
222 + if (addr == NULL|| readl(addr) != val1) {
223 + set_bit(i + 32*k, fallback_slots);
224 + printk(KERN_NOTICE
225 + "PCI: No mmconfig possible on device %x:%x\n",
226 + k, i);
227 + }
228 + }
229 + }
230 +}
232 - pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1);
233 - if (val1 == 0xffffffff)
234 +/* NB. Ripped from arch/x86_64/kernel/e820.c for this Xen bugfix patch. */
235 +#ifdef CONFIG_XEN
236 +extern struct e820map machine_e820;
237 +#define e820 machine_e820
238 +#endif
239 +static int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
240 +{
241 + int i;
242 + for (i = 0; i < e820.nr_map; i++) {
243 + struct e820entry *ei = &e820.map[i];
244 + if (type && ei->type != type)
245 continue;
246 - addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0));
247 - if (addr == NULL|| readl(addr) != val1) {
248 - set_bit(i, &fallback_slots);
249 - }
250 + /* is the region (part) in overlap with the current region ?*/
251 + if (ei->addr >= end || ei->addr + ei->size <= start)
252 + continue;
253 +
254 + /* if the region is at the beginning of <start,end> we move
255 + * start to the end of the region since it's ok until there
256 + */
257 + if (ei->addr <= start)
258 + start = ei->addr + ei->size;
259 + /* if start is now at or beyond end, we're done, full coverage */
260 + if (start >= end)
261 + return 1; /* we're done */
262 }
263 + return 0;
264 }
266 static int __init pci_mmcfg_init(void)
267 @@ -161,6 +205,15 @@ static int __init pci_mmcfg_init(void)
268 (pci_mmcfg_config[0].base_address == 0))
269 return 0;
271 + if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
272 + pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
273 + E820_RESERVED)) {
274 + printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
275 + pci_mmcfg_config[0].base_address);
276 + printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
277 + return 0;
278 + }
279 +
280 /* RED-PEN i386 doesn't do _nocache right now */
281 pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
282 if (pci_mmcfg_virt == NULL) {
283 @@ -169,7 +222,8 @@ static int __init pci_mmcfg_init(void)
284 }
285 for (i = 0; i < pci_mmcfg_config_num; ++i) {
286 pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
287 - pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_SIZE);
288 + pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address,
289 + MMCONFIG_APER_MAX);
290 if (!pci_mmcfg_virt[i].virt) {
291 printk("PCI: Cannot map mmconfig aperture for segment %d\n",
292 pci_mmcfg_config[i].pci_segment_group_number);