ia64/xen-unstable

view xen/drivers/passthrough/vtd/utils.c @ 17265:70f9a2110421

Intel VTD: Ignore USB RMRR for HVM guest

USB controller RMRR (0xed000 - 0xeffff) conflicts with HVM guest bios
region. Setting identity mapping for it will cover the guest bios
region in p2m table. This causes system crash.

As VT-d spec says, USB controller RMRR is used in case of DMA
performed by a USB controller under BIOS SMM control for legacy
keyboard emulation. Whereas, current guest BIOS doesn't support
emulating stardand Keyboard/mouse, and it also doesn't support SMM
mode. Actually it is no chance to use USB controller RMRR now.

This patch ignores the USB controller RMRR for HVM guest.

Signed-off-by: Weidong Han <weidong.han@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Mar 19 10:22:49 2008 +0000 (2008-03-19)
parents bf8a3fc79093
children 1d3aaa6a8b87
line source
1 /*
2 * Copyright (c) 2006, Intel Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15 * Place - Suite 330, Boston, MA 02111-1307 USA.
16 *
17 * Copyright (C) Allen Kay <allen.m.kay@intel.com>
18 */
20 #include <xen/sched.h>
21 #include <xen/delay.h>
22 #include <xen/iommu.h>
23 #include "iommu.h"
24 #include "dmar.h"
25 #include "../pci-direct.h"
26 #include "../pci_regs.h"
27 #include "msi.h"
29 #define INTEL 0x8086
30 #define SEABURG 0x4000
31 #define C_STEP 2
33 int is_usb_device(struct pci_dev *pdev)
34 {
35 u8 bus = pdev->bus;
36 u8 dev = PCI_SLOT(pdev->devfn);
37 u8 func = PCI_FUNC(pdev->devfn);
38 u16 class = read_pci_config_16(bus, dev, func, PCI_CLASS_DEVICE);
39 return (class == 0xc03);
40 }
42 int vtd_hw_check(void)
43 {
44 u16 vendor, device;
45 u8 revision, stepping;
47 vendor = read_pci_config_16(0, 0, 0, PCI_VENDOR_ID);
48 device = read_pci_config_16(0, 0, 0, PCI_DEVICE_ID);
49 revision = read_pci_config_byte(0, 0, 0, PCI_REVISION_ID);
50 stepping = revision & 0xf;
52 if ( (vendor == INTEL) && (device == SEABURG) )
53 {
54 if ( stepping < C_STEP )
55 {
56 dprintk(XENLOG_WARNING VTDPREFIX,
57 "*** VT-d disabled - pre C0-step Seaburg found\n");
58 dprintk(XENLOG_WARNING VTDPREFIX,
59 "*** vendor = %x device = %x revision = %x\n",
60 vendor, device, revision);
61 vtd_enabled = 0;
62 return -ENODEV;
63 }
64 }
65 return 0;
66 }
68 /* Disable vt-d protected memory registers. */
69 void disable_pmr(struct iommu *iommu)
70 {
71 unsigned long start_time;
72 unsigned int val;
74 val = dmar_readl(iommu->reg, DMAR_PMEN_REG);
75 if ( !(val & DMA_PMEN_PRS) )
76 return;
78 dmar_writel(iommu->reg, DMAR_PMEN_REG, val & ~DMA_PMEN_EPM);
79 start_time = jiffies;
81 for ( ; ; )
82 {
83 val = dmar_readl(iommu->reg, DMAR_PMEN_REG);
84 if ( (val & DMA_PMEN_PRS) == 0 )
85 break;
87 if ( time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT) )
88 panic("Disable PMRs timeout\n");
90 cpu_relax();
91 }
93 dprintk(XENLOG_INFO VTDPREFIX,
94 "Disabled protected memory registers\n");
95 }
97 static u8 find_cap_offset(u8 bus, u8 dev, u8 func, u8 cap)
98 {
99 u8 id;
100 int max_cap = 48;
101 u8 pos = PCI_CAPABILITY_LIST;
102 u16 status;
104 status = read_pci_config_16(bus, dev, func, PCI_STATUS);
105 if ( (status & PCI_STATUS_CAP_LIST) == 0 )
106 return 0;
108 while ( max_cap-- )
109 {
110 pos = read_pci_config_byte(bus, dev, func, pos);
111 if ( pos < 0x40 )
112 break;
114 pos &= ~3;
115 id = read_pci_config_byte(bus, dev, func, pos + PCI_CAP_LIST_ID);
117 if ( id == 0xff )
118 break;
119 else if ( id == cap )
120 return pos;
122 pos += PCI_CAP_LIST_NEXT;
123 }
125 return 0;
126 }
128 #define PCI_D3hot (3)
129 #define PCI_CONFIG_DWORD_SIZE (64)
130 #define PCI_EXP_DEVCAP_FLR (1 << 28)
131 #define PCI_EXP_DEVCTL_FLR (1 << 15)
133 void pdev_flr(u8 bus, u8 devfn)
134 {
135 u8 pos;
136 u32 dev_cap, dev_status, pm_ctl;
137 int flr = 0;
138 u8 dev = PCI_SLOT(devfn);
139 u8 func = PCI_FUNC(devfn);
141 pos = find_cap_offset(bus, dev, func, PCI_CAP_ID_EXP);
142 if ( pos != 0 )
143 {
144 dev_cap = read_pci_config(bus, dev, func, pos + PCI_EXP_DEVCAP);
145 if ( dev_cap & PCI_EXP_DEVCAP_FLR )
146 {
147 write_pci_config(bus, dev, func,
148 pos + PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_FLR);
149 do {
150 dev_status = read_pci_config(bus, dev, func,
151 pos + PCI_EXP_DEVSTA);
152 } while ( dev_status & PCI_EXP_DEVSTA_TRPND );
154 flr = 1;
155 }
156 }
158 /* If this device doesn't support function level reset,
159 * program device from D0 t0 D3hot, and then return to D0
160 * to implement function level reset
161 */
162 if ( flr == 0 )
163 {
164 pos = find_cap_offset(bus, dev, func, PCI_CAP_ID_PM);
165 if ( pos != 0 )
166 {
167 int i;
168 u32 config[PCI_CONFIG_DWORD_SIZE];
169 for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ )
170 config[i] = read_pci_config(bus, dev, func, i*4);
172 /* Enter D3hot without soft reset */
173 pm_ctl = read_pci_config(bus, dev, func, pos + PCI_PM_CTRL);
174 pm_ctl |= PCI_PM_CTRL_NO_SOFT_RESET;
175 pm_ctl &= ~PCI_PM_CTRL_STATE_MASK;
176 pm_ctl |= PCI_D3hot;
177 write_pci_config(bus, dev, func, pos + PCI_PM_CTRL, pm_ctl);
178 mdelay(10);
180 /* From D3hot to D0 */
181 write_pci_config(bus, dev, func, pos + PCI_PM_CTRL, 0);
182 mdelay(10);
184 /* Write saved configurations to device */
185 for ( i = 0; i < PCI_CONFIG_DWORD_SIZE; i++ )
186 write_pci_config(bus, dev, func, i*4, config[i]);
188 flr = 1;
189 }
190 }
191 }
193 void print_iommu_regs(struct acpi_drhd_unit *drhd)
194 {
195 struct iommu *iommu = drhd->iommu;
197 printk("---- print_iommu_regs ----\n");
198 printk("print_iommu_regs: drhd->address = %lx\n", drhd->address);
199 printk("print_iommu_regs: DMAR_VER_REG = %x\n",
200 dmar_readl(iommu->reg,DMAR_VER_REG));
201 printk("print_iommu_regs: DMAR_CAP_REG = %"PRIx64"\n",
202 dmar_readq(iommu->reg,DMAR_CAP_REG));
203 printk("print_iommu_regs: n_fault_reg = %"PRIx64"\n",
204 cap_num_fault_regs(dmar_readq(iommu->reg, DMAR_CAP_REG)));
205 printk("print_iommu_regs: fault_recording_offset_l = %"PRIx64"\n",
206 cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG)));
207 printk("print_iommu_regs: fault_recording_offset_h = %"PRIx64"\n",
208 cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG)) + 8);
209 printk("print_iommu_regs: fault_recording_reg_l = %"PRIx64"\n",
210 dmar_readq(iommu->reg,
211 cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG))));
212 printk("print_iommu_regs: fault_recording_reg_h = %"PRIx64"\n",
213 dmar_readq(iommu->reg,
214 cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG)) + 8));
215 printk("print_iommu_regs: DMAR_ECAP_REG = %"PRIx64"\n",
216 dmar_readq(iommu->reg,DMAR_ECAP_REG));
217 printk("print_iommu_regs: DMAR_GCMD_REG = %x\n",
218 dmar_readl(iommu->reg,DMAR_GCMD_REG));
219 printk("print_iommu_regs: DMAR_GSTS_REG = %x\n",
220 dmar_readl(iommu->reg,DMAR_GSTS_REG));
221 printk("print_iommu_regs: DMAR_RTADDR_REG = %"PRIx64"\n",
222 dmar_readq(iommu->reg,DMAR_RTADDR_REG));
223 printk("print_iommu_regs: DMAR_CCMD_REG = %"PRIx64"\n",
224 dmar_readq(iommu->reg,DMAR_CCMD_REG));
225 printk("print_iommu_regs: DMAR_FSTS_REG = %x\n",
226 dmar_readl(iommu->reg,DMAR_FSTS_REG));
227 printk("print_iommu_regs: DMAR_FECTL_REG = %x\n",
228 dmar_readl(iommu->reg,DMAR_FECTL_REG));
229 printk("print_iommu_regs: DMAR_FEDATA_REG = %x\n",
230 dmar_readl(iommu->reg,DMAR_FEDATA_REG));
231 printk("print_iommu_regs: DMAR_FEADDR_REG = %x\n",
232 dmar_readl(iommu->reg,DMAR_FEADDR_REG));
233 printk("print_iommu_regs: DMAR_FEUADDR_REG = %x\n",
234 dmar_readl(iommu->reg,DMAR_FEUADDR_REG));
235 }
237 u32 get_level_index(unsigned long gmfn, int level)
238 {
239 while ( --level )
240 gmfn = gmfn >> LEVEL_STRIDE;
242 return gmfn & LEVEL_MASK;
243 }
245 void print_vtd_entries(
246 struct domain *d,
247 struct iommu *iommu,
248 int bus, int devfn,
249 unsigned long gmfn)
250 {
251 struct hvm_iommu *hd = domain_hvm_iommu(d);
252 struct acpi_drhd_unit *drhd;
253 struct context_entry *ctxt_entry;
254 struct root_entry *root_entry;
255 struct dma_pte pte;
256 u64 *l;
257 u32 l_index;
258 u32 i = 0;
259 int level = agaw_to_level(hd->agaw);
261 printk("print_vtd_entries: domain_id = %x bdf = %x:%x:%x gmfn = %lx\n",
262 d->domain_id, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), gmfn);
264 if ( hd->pgd == NULL )
265 {
266 printk(" hg->pgd == NULL\n");
267 return;
268 }
269 printk(" d->pgd = %p virt_to_maddr(hd->pgd) = %lx\n",
270 hd->pgd, virt_to_maddr(hd->pgd));
272 for_each_drhd_unit ( drhd )
273 {
274 printk("---- print_vtd_entries %d ----\n", i++);
276 root_entry = iommu->root_entry;
277 if ( root_entry == NULL )
278 {
279 printk(" root_entry == NULL\n");
280 continue;
281 }
283 printk(" root_entry = %p\n", root_entry);
284 printk(" root_entry[%x] = %"PRIx64"\n", bus, root_entry[bus].val);
285 if ( !root_present(root_entry[bus]) )
286 {
287 printk(" root_entry[%x] not present\n", bus);
288 continue;
289 }
291 ctxt_entry =
292 maddr_to_virt((root_entry[bus].val >> PAGE_SHIFT) << PAGE_SHIFT);
293 if ( ctxt_entry == NULL )
294 {
295 printk(" ctxt_entry == NULL\n");
296 continue;
297 }
299 printk(" context = %p\n", ctxt_entry);
300 printk(" context[%x] = %"PRIx64" %"PRIx64"\n",
301 devfn, ctxt_entry[devfn].hi, ctxt_entry[devfn].lo);
302 if ( !context_present(ctxt_entry[devfn]) )
303 {
304 printk(" ctxt_entry[%x] not present\n", devfn);
305 continue;
306 }
308 if ( level != VTD_PAGE_TABLE_LEVEL_3 &&
309 level != VTD_PAGE_TABLE_LEVEL_4)
310 {
311 printk("Unsupported VTD page table level (%d)!\n", level);
312 continue;
313 }
315 l = maddr_to_virt(ctxt_entry[devfn].lo);
316 do
317 {
318 l = (u64*)(((unsigned long)l >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
319 printk(" l%d = %p\n", level, l);
320 if ( l == NULL )
321 {
322 printk(" l%d == NULL\n", level);
323 break;
324 }
325 l_index = get_level_index(gmfn, level);
326 printk(" l%d_index = %x\n", level, l_index);
327 printk(" l%d[%x] = %"PRIx64"\n", level, l_index, l[l_index]);
329 pte.val = l[l_index];
330 if ( !dma_pte_present(pte) )
331 {
332 printk(" l%d[%x] not present\n", level, l_index);
333 break;
334 }
336 l = maddr_to_virt(l[l_index]);
337 } while ( --level );
338 }
339 }