debuggers.hg

view xen/arch/x86/hvm/vmx/vtd/utils.c @ 16366:b544448502a4

vt-d: Disable PMR on every vt-d engine.

Signed-off-by Gang Wei (Jimmy) <gang.wei@intel.com>
Signed-off-by Kevin Tian <kevin.tian@intel.com>
author Keir Fraser <keir@xensource.com>
date Wed Nov 07 09:13:48 2007 +0000 (2007-11-07)
parents 5a213170b06e
children cb6675149af8
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/init.h>
21 #include <xen/bitmap.h>
22 #include <xen/irq.h>
23 #include <xen/spinlock.h>
24 #include <xen/sched.h>
25 #include <asm/delay.h>
26 #include <asm/iommu.h>
27 #include <asm/hvm/vmx/intel-iommu.h>
28 #include "dmar.h"
29 #include "pci-direct.h"
30 #include "pci_regs.h"
31 #include "msi.h"
33 #include <xen/mm.h>
34 #include <xen/xmalloc.h>
36 #define VTDPREFIX "[VT-D]"
37 #define INTEL 0x8086
38 #define SEABURG 0x4000
39 #define C_STEP 2
41 int vtd_hw_check(void)
42 {
43 u16 vendor, device;
44 u8 revision, stepping;
46 vendor = read_pci_config_16(0, 0, 0, PCI_VENDOR_ID);
47 device = read_pci_config_16(0, 0, 0, PCI_DEVICE_ID);
48 revision = read_pci_config_byte(0, 0, 0, PCI_REVISION_ID);
49 stepping = revision & 0xf;
51 if ( (vendor == INTEL) && (device == SEABURG) )
52 {
53 if ( stepping < C_STEP )
54 {
55 dprintk(XENLOG_WARNING VTDPREFIX,
56 "*** VT-d disabled - pre C0-step Seaburg found\n");
57 dprintk(XENLOG_WARNING VTDPREFIX,
58 "*** vendor = %x device = %x revision = %x\n",
59 vendor, device, revision);
60 vtd_enabled = 0;
61 return -ENODEV;
62 }
63 }
64 return 0;
65 }
67 /* Disable vt-d protected memory registers. */
68 void disable_pmr(struct iommu *iommu)
69 {
70 unsigned long start_time;
71 unsigned int val;
73 val = dmar_readl(iommu->reg, DMAR_PMEN_REG);
74 if ( !(val & DMA_PMEN_PRS) )
75 return;
77 dmar_writel(iommu->reg, DMAR_PMEN_REG, val & ~DMA_PMEN_EPM);
78 start_time = jiffies;
80 for ( ; ; )
81 {
82 val = dmar_readl(iommu->reg, DMAR_PMEN_REG);
83 if ( (val & DMA_PMEN_PRS) == 0 )
84 break;
86 if ( time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT) )
87 panic("Disable PMRs timeout\n");
89 cpu_relax();
90 }
92 dprintk(XENLOG_INFO VTDPREFIX,
93 "Disabled protected memory registers\n");
94 }
96 #if defined(__x86_64__)
97 void print_iommu_regs(struct acpi_drhd_unit *drhd)
98 {
99 struct iommu *iommu = drhd->iommu;
101 printk("---- print_iommu_regs ----\n");
102 printk("print_iommu_regs: drhd->address = %lx\n", drhd->address);
103 printk("print_iommu_regs: DMAR_VER_REG = %x\n",
104 dmar_readl(iommu->reg,DMAR_VER_REG));
105 printk("print_iommu_regs: DMAR_CAP_REG = %lx\n",
106 dmar_readq(iommu->reg,DMAR_CAP_REG));
107 printk("print_iommu_regs: n_fault_reg = %lx\n",
108 cap_num_fault_regs(dmar_readq(iommu->reg, DMAR_CAP_REG)));
109 printk("print_iommu_regs: fault_recording_offset_l = %lx\n",
110 cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG)));
111 printk("print_iommu_regs: fault_recording_offset_h = %lx\n",
112 cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG)) + 8);
113 printk("print_iommu_regs: fault_recording_reg_l = %lx\n",
114 dmar_readq(iommu->reg, cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG))));
115 printk("print_iommu_regs: fault_recording_reg_h = %lx\n",
116 dmar_readq(iommu->reg, cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG)) + 8));
117 printk("print_iommu_regs: DMAR_ECAP_REG = %lx\n",
118 dmar_readq(iommu->reg,DMAR_ECAP_REG));
119 printk("print_iommu_regs: DMAR_GCMD_REG = %x\n",
120 dmar_readl(iommu->reg,DMAR_GCMD_REG));
121 printk("print_iommu_regs: DMAR_GSTS_REG = %x\n",
122 dmar_readl(iommu->reg,DMAR_GSTS_REG));
123 printk("print_iommu_regs: DMAR_RTADDR_REG = %lx\n",
124 dmar_readq(iommu->reg,DMAR_RTADDR_REG));
125 printk("print_iommu_regs: DMAR_CCMD_REG = %lx\n",
126 dmar_readq(iommu->reg,DMAR_CCMD_REG));
127 printk("print_iommu_regs: DMAR_FSTS_REG = %x\n",
128 dmar_readl(iommu->reg,DMAR_FSTS_REG));
129 printk("print_iommu_regs: DMAR_FECTL_REG = %x\n",
130 dmar_readl(iommu->reg,DMAR_FECTL_REG));
131 printk("print_iommu_regs: DMAR_FEDATA_REG = %x\n",
132 dmar_readl(iommu->reg,DMAR_FEDATA_REG));
133 printk("print_iommu_regs: DMAR_FEADDR_REG = %x\n",
134 dmar_readl(iommu->reg,DMAR_FEADDR_REG));
135 printk("print_iommu_regs: DMAR_FEUADDR_REG = %x\n",
136 dmar_readl(iommu->reg,DMAR_FEUADDR_REG));
137 }
139 void print_vtd_entries(struct domain *d, int bus, int devfn,
140 unsigned long gmfn)
141 {
142 struct hvm_iommu *hd = domain_hvm_iommu(d);
143 struct acpi_drhd_unit *drhd;
144 struct iommu *iommu;
145 struct context_entry *ctxt_entry;
146 struct root_entry *root_entry;
147 u64 *l3, *l2, *l1;
148 u32 l3_index, l2_index, l1_index;
149 u32 i = 0;
151 printk("print_vtd_entries: domain_id = %x bdf = %x:%x:%x devfn = %x, gmfn = %lx\n", d->domain_id, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), devfn, gmfn);
153 for_each_drhd_unit(drhd) {
154 printk("---- print_vtd_entries %d ----\n", i++);
156 if (hd->pgd == NULL) {
157 printk(" hg->pgd == NULL\n");
158 return;
159 }
161 iommu = drhd->iommu;
162 root_entry = iommu->root_entry;
163 printk(" hd->pgd = %p virt_to_maddr(hd->pgd) = %lx\n",
164 hd->pgd, virt_to_maddr(hd->pgd));
166 printk(" root_entry = %p\n", root_entry);
167 if (root_entry == NULL) {
168 printk(" root_entry == NULL\n");
169 return;
170 }
172 printk(" root_entry[%x] = %lx\n", bus, root_entry[bus].val);
173 printk(" maddr_to_virt(root_entry[%x]) = %p\n",
174 bus, maddr_to_virt(root_entry[bus].val));
176 if (root_entry[bus].val == 0) {
177 printk(" root_entry[%x].lo == 0\n", bus);
178 return;
179 }
181 ctxt_entry = maddr_to_virt((root_entry[bus].val >> PAGE_SHIFT) << PAGE_SHIFT);
182 if (ctxt_entry == NULL) {
183 printk(" ctxt_entry == NULL\n");
184 return;
185 }
187 if (ctxt_entry[devfn].lo == 0) {
188 printk(" ctxt_entry[%x].lo == 0\n", devfn);
189 return;
190 }
192 printk(" context = %p\n", ctxt_entry);
193 printk(" context[%x] = %lx %lx\n",
194 devfn, ctxt_entry[devfn].hi, ctxt_entry[devfn].lo);
195 printk(" maddr_to_virt(context[%x].lo) = %p\n",
196 devfn, maddr_to_virt(ctxt_entry[devfn].lo));
197 printk(" context[%x] = %lx\n", devfn, ctxt_entry[devfn].lo);
199 l3 = maddr_to_virt(ctxt_entry[devfn].lo);
200 l3 = (u64*)(((u64) l3 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
201 printk(" l3 = %p\n", l3);
202 if (l3 == NULL) return;
204 l3_index = (gmfn >> 9 >> 9) & 0x1ff;
205 printk(" l3_index = %x\n", l3_index);
206 printk(" l3[%x] = %lx\n", l3_index, l3[l3_index]);
208 l2 = maddr_to_virt(l3[l3_index]);
209 l2 = (u64*)(((u64) l2 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
210 printk(" l2 = %p\n", l2);
211 if (l2 == NULL) return;
213 l2_index = (gmfn >> 9) & 0x1ff;
214 printk(" gmfn = %lx\n", gmfn);
215 printk(" gmfn >> 9= %lx\n", gmfn >> 9);
216 printk(" l2_index = %x\n", l2_index);
217 printk(" l2[%x] = %lx\n", l2_index, l2[l2_index]);
219 l1 = maddr_to_virt(l2[l2_index]);
220 l1 = (u64*)(((u64) l1 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
221 if (l1 == NULL) return;
222 l1_index = gmfn & 0x1ff;
223 printk(" l1 = %p\n", l1);
224 printk(" l1_index = %x\n", l1_index);
225 printk(" l1[%x] = %lx\n", l1_index, l1[l1_index]);
226 }
227 }
229 #else // !m64
231 void print_iommu_regs(struct acpi_drhd_unit *drhd)
232 {
233 struct iommu *iommu = drhd->iommu;
235 printk("---- print_iommu_regs ----\n");
236 printk("print_iommu_regs: drhd->address = %lx\n", drhd->address);
237 printk("print_iommu_regs: DMAR_VER_REG = %x\n",
238 dmar_readl(iommu->reg,DMAR_VER_REG));
239 printk("print_iommu_regs: DMAR_CAP_REG = %llx\n",
240 dmar_readq(iommu->reg,DMAR_CAP_REG));
241 printk("print_iommu_regs: n_fault_reg = %llx\n",
242 cap_num_fault_regs(dmar_readq(iommu->reg, DMAR_CAP_REG)));
243 printk("print_iommu_regs: fault_recording_offset_l = %llx\n",
244 cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG)));
245 printk("print_iommu_regs: fault_recording_offset_h = %llx\n",
246 cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG)) + 8);
247 printk("print_iommu_regs: fault_recording_reg_l = %llx\n",
248 dmar_readq(iommu->reg, cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG))));
249 printk("print_iommu_regs: fault_recording_reg_h = %llx\n",
250 dmar_readq(iommu->reg, cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG)) + 8));
251 printk("print_iommu_regs: DMAR_ECAP_REG = %llx\n",
252 dmar_readq(iommu->reg,DMAR_ECAP_REG));
253 printk("print_iommu_regs: DMAR_GCMD_REG = %x\n",
254 dmar_readl(iommu->reg,DMAR_GCMD_REG));
255 printk("print_iommu_regs: DMAR_GSTS_REG = %x\n",
256 dmar_readl(iommu->reg,DMAR_GSTS_REG));
257 printk("print_iommu_regs: DMAR_RTADDR_REG = %llx\n",
258 dmar_readq(iommu->reg,DMAR_RTADDR_REG));
259 printk("print_iommu_regs: DMAR_CCMD_REG = %llx\n",
260 dmar_readq(iommu->reg,DMAR_CCMD_REG));
261 printk("print_iommu_regs: DMAR_FSTS_REG = %x\n",
262 dmar_readl(iommu->reg,DMAR_FSTS_REG));
263 printk("print_iommu_regs: DMAR_FECTL_REG = %x\n",
264 dmar_readl(iommu->reg,DMAR_FECTL_REG));
265 printk("print_iommu_regs: DMAR_FEDATA_REG = %x\n",
266 dmar_readl(iommu->reg,DMAR_FEDATA_REG));
267 printk("print_iommu_regs: DMAR_FEADDR_REG = %x\n",
268 dmar_readl(iommu->reg,DMAR_FEADDR_REG));
269 printk("print_iommu_regs: DMAR_FEUADDR_REG = %x\n",
270 dmar_readl(iommu->reg,DMAR_FEUADDR_REG));
271 }
273 void print_vtd_entries(struct domain *d, int bus, int devfn,
274 unsigned long gmfn)
275 {
276 struct hvm_iommu *hd = domain_hvm_iommu(d);
277 struct acpi_drhd_unit *drhd;
278 struct iommu *iommu;
279 struct context_entry *ctxt_entry;
280 struct root_entry *root_entry;
281 u64 *l3, *l2, *l1;
282 u32 l3_index, l2_index, l1_index;
283 u32 i = 0;
285 printk("print_vtd_entries: domain_id = %x bdf = %x:%x:%x devfn = %x, gmfn = %lx\n", d->domain_id, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), devfn, gmfn);
287 for_each_drhd_unit(drhd) {
288 printk("---- print_vtd_entries %d ----\n", i++);
290 if (hd->pgd == NULL) {
291 printk(" hg->pgd == NULL\n");
292 return;
293 }
295 iommu = drhd->iommu;
296 root_entry = iommu->root_entry;
297 printk(" d->pgd = %p virt_to_maddr(hd->pgd) = %lx\n",
298 hd->pgd, virt_to_maddr(hd->pgd));
300 printk(" root_entry = %p\n", root_entry);
301 if (root_entry == NULL) {
302 printk(" root_entry == NULL\n");
303 return;
304 }
306 printk(" root_entry[%x] = %llx\n", bus, root_entry[bus].val);
307 printk(" maddr_to_virt(root_entry[%x]) = %p\n",
308 bus, maddr_to_virt(root_entry[bus].val));
310 if (root_entry[bus].val == 0) {
311 printk(" root_entry[%x].lo == 0\n", bus);
312 return;
313 }
315 ctxt_entry = maddr_to_virt((root_entry[bus].val >> PAGE_SHIFT) << PAGE_SHIFT);
316 if (ctxt_entry == NULL) {
317 printk(" ctxt_entry == NULL\n");
318 return;
319 }
321 if (ctxt_entry[devfn].lo == 0) {
322 printk(" ctxt_entry[%x].lo == 0\n", devfn);
323 return;
324 }
326 printk(" context = %p\n", ctxt_entry);
327 printk(" context[%x] = %llx %llx\n",
328 devfn, ctxt_entry[devfn].hi, ctxt_entry[devfn].lo);
329 printk(" maddr_to_virt(context[%x].lo) = %p\n",
330 devfn, maddr_to_virt(ctxt_entry[devfn].lo));
331 printk(" context[%x] = %llx\n", devfn, ctxt_entry[devfn].lo);
333 l3 = maddr_to_virt(ctxt_entry[devfn].lo);
334 l3 = (u64*)(((u32) l3 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
335 printk(" l3 = %p\n", l3);
336 if (l3 == NULL) return;
338 l3_index = (gmfn >> 9 >> 9) & 0x1ff;
339 printk(" l3_index = %x\n", l3_index);
340 printk(" l3[%x] = %llx\n", l3_index, l3[l3_index]);
342 l2 = maddr_to_virt(l3[l3_index]);
343 l2 = (u64*)(((u32) l2 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
344 printk(" l2 = %p\n", l2);
345 if (l2 == NULL) return;
347 l2_index = (gmfn >> 9) & 0x1ff;
348 printk(" gmfn = %lx\n", gmfn);
349 printk(" gmfn >> 9= %lx\n", gmfn >> 9);
350 printk(" l2_index = %x\n", l2_index);
351 printk(" l2[%x] = %llx\n", l2_index, l2[l2_index]);
353 l1 = maddr_to_virt(l2[l2_index]);
354 l1 = (u64*)(((u32) l1 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
355 if (l1 == NULL) return;
356 l1_index = gmfn & 0x1ff;
357 printk(" l1 = %p\n", l1);
358 printk(" l1_index = %x\n", l1_index);
359 printk(" l1[%x] = %llx\n", l1_index, l1[l1_index]);
360 }
361 }
362 #endif // !m64