debuggers.hg

view xen/arch/x86/hvm/vmx/vtd/utils.c @ 16380:cb6675149af8

x86, vt-d: Clean up utils code.
Signed-off-by: Weidong Han <weidong.han@intel.com>
author Keir Fraser <keir@xensource.com>
date Thu Nov 08 13:14:03 2007 +0000 (2007-11-08)
parents b544448502a4
children 8ae3f083490a
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>
35 #include <xen/inttypes.h>
37 #define VTDPREFIX "[VT-D]"
38 #define INTEL 0x8086
39 #define SEABURG 0x4000
40 #define C_STEP 2
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 }
98 void print_iommu_regs(struct acpi_drhd_unit *drhd)
99 {
100 struct iommu *iommu = drhd->iommu;
102 printk("---- print_iommu_regs ----\n");
103 printk("print_iommu_regs: drhd->address = %lx\n", drhd->address);
104 printk("print_iommu_regs: DMAR_VER_REG = %x\n",
105 dmar_readl(iommu->reg,DMAR_VER_REG));
106 printk("print_iommu_regs: DMAR_CAP_REG = %"PRIx64"\n",
107 dmar_readq(iommu->reg,DMAR_CAP_REG));
108 printk("print_iommu_regs: n_fault_reg = %"PRIx64"\n",
109 cap_num_fault_regs(dmar_readq(iommu->reg, DMAR_CAP_REG)));
110 printk("print_iommu_regs: fault_recording_offset_l = %"PRIx64"\n",
111 cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG)));
112 printk("print_iommu_regs: fault_recording_offset_h = %"PRIx64"\n",
113 cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG)) + 8);
114 printk("print_iommu_regs: fault_recording_reg_l = %"PRIx64"\n",
115 dmar_readq(iommu->reg,
116 cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG))));
117 printk("print_iommu_regs: fault_recording_reg_h = %"PRIx64"\n",
118 dmar_readq(iommu->reg,
119 cap_fault_reg_offset(dmar_readq(iommu->reg, DMAR_CAP_REG)) + 8));
120 printk("print_iommu_regs: DMAR_ECAP_REG = %"PRIx64"\n",
121 dmar_readq(iommu->reg,DMAR_ECAP_REG));
122 printk("print_iommu_regs: DMAR_GCMD_REG = %x\n",
123 dmar_readl(iommu->reg,DMAR_GCMD_REG));
124 printk("print_iommu_regs: DMAR_GSTS_REG = %x\n",
125 dmar_readl(iommu->reg,DMAR_GSTS_REG));
126 printk("print_iommu_regs: DMAR_RTADDR_REG = %"PRIx64"\n",
127 dmar_readq(iommu->reg,DMAR_RTADDR_REG));
128 printk("print_iommu_regs: DMAR_CCMD_REG = %"PRIx64"\n",
129 dmar_readq(iommu->reg,DMAR_CCMD_REG));
130 printk("print_iommu_regs: DMAR_FSTS_REG = %x\n",
131 dmar_readl(iommu->reg,DMAR_FSTS_REG));
132 printk("print_iommu_regs: DMAR_FECTL_REG = %x\n",
133 dmar_readl(iommu->reg,DMAR_FECTL_REG));
134 printk("print_iommu_regs: DMAR_FEDATA_REG = %x\n",
135 dmar_readl(iommu->reg,DMAR_FEDATA_REG));
136 printk("print_iommu_regs: DMAR_FEADDR_REG = %x\n",
137 dmar_readl(iommu->reg,DMAR_FEADDR_REG));
138 printk("print_iommu_regs: DMAR_FEUADDR_REG = %x\n",
139 dmar_readl(iommu->reg,DMAR_FEUADDR_REG));
140 }
142 u32 get_level_index(unsigned long gmfn, int level)
143 {
144 while ( --level )
145 gmfn = gmfn >> LEVEL_STRIDE;
147 return gmfn & LEVEL_MASK;
148 }
150 void print_vtd_entries(struct domain *d, int bus, int devfn,
151 unsigned long gmfn)
152 {
153 struct hvm_iommu *hd = domain_hvm_iommu(d);
154 struct acpi_drhd_unit *drhd;
155 struct iommu *iommu;
156 struct context_entry *ctxt_entry;
157 struct root_entry *root_entry;
158 u64 *l4 = NULL, *l3, *l2, *l1;
159 u32 l4_index = 0, l3_index, l2_index, l1_index;
160 u32 i = 0;
161 int level = agaw_to_level(hd->agaw);
163 printk("print_vtd_entries: domain_id = %x bdf = %x:%x:%x gmfn = %lx\n",
164 d->domain_id, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), gmfn);
166 if ( hd->pgd == NULL )
167 {
168 printk(" hg->pgd == NULL\n");
169 return;
170 }
171 printk(" d->pgd = %p virt_to_maddr(hd->pgd) = %lx\n",
172 hd->pgd, virt_to_maddr(hd->pgd));
174 for_each_drhd_unit ( drhd )
175 {
176 printk("---- print_vtd_entries %d ----\n", i++);
178 iommu = drhd->iommu;
179 root_entry = iommu->root_entry;
180 printk(" root_entry = %p\n", root_entry);
181 if ( root_entry == NULL )
182 {
183 printk(" root_entry == NULL\n");
184 continue;
185 }
187 printk(" root_entry[%x] = %"PRIx64"\n", bus, root_entry[bus].val);
188 printk(" maddr_to_virt(root_entry[%x]) = %p\n",
189 bus, maddr_to_virt(root_entry[bus].val));
191 if ( root_entry[bus].val == 0 )
192 {
193 printk(" root_entry[%x].lo == 0\n", bus);
194 continue;
195 }
197 ctxt_entry =
198 maddr_to_virt((root_entry[bus].val >> PAGE_SHIFT) << PAGE_SHIFT);
199 if ( ctxt_entry == NULL )
200 {
201 printk(" ctxt_entry == NULL\n");
202 continue;
203 }
205 if ( ctxt_entry[devfn].lo == 0 )
206 {
207 printk(" ctxt_entry[%x].lo == 0\n", devfn);
208 continue;
209 }
211 printk(" context = %p\n", ctxt_entry);
212 printk(" context[%x] = %"PRIx64" %"PRIx64"\n",
213 devfn, ctxt_entry[devfn].hi, ctxt_entry[devfn].lo);
214 printk(" maddr_to_virt(context[%x].lo) = %p\n",
215 devfn, maddr_to_virt(ctxt_entry[devfn].lo));
216 printk(" context[%x] = %"PRIx64"\n", devfn, ctxt_entry[devfn].lo);
218 switch ( level )
219 {
220 case VTD_PAGE_TABLE_LEVEL_3:
221 l3 = maddr_to_virt(ctxt_entry[devfn].lo);
222 l3 = (u64*)(((unsigned long)l3 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
223 printk(" l3 = %p\n", l3);
224 if ( l3 == NULL )
225 continue;
226 l3_index = get_level_index(gmfn, 3);
227 printk(" l3_index = %x\n", l3_index);
228 printk(" l3[%x] = %"PRIx64"\n", l3_index, l3[l3_index]);
230 break;
231 case VTD_PAGE_TABLE_LEVEL_4:
232 l4 = maddr_to_virt(ctxt_entry[devfn].lo);
233 l4 = (u64*)(((unsigned long)l4 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
234 printk(" l4 = %p\n", l4);
235 if ( l4 == NULL )
236 continue;
237 l4_index = get_level_index(gmfn, 4);
238 printk(" l4_index = %x\n", l4_index);
239 printk(" l4[%x] = %"PRIx64"\n", l4_index, l4[l4_index]);
241 l3 = maddr_to_virt(l4[l4_index]);
242 l3 = (u64*)(((unsigned long)l3 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
243 printk(" l3 = %p\n", l3);
244 if ( l3 == NULL )
245 continue;
246 l3_index = get_level_index(gmfn, 3);
247 printk(" l3_index = %x\n", l3_index);
248 printk(" l3[%x] = %"PRIx64"\n", l3_index, l3[l3_index]);
250 break;
251 default:
252 printk("Unsupported VTD page table level (%d)!\n", level);
253 continue;
254 }
256 l2 = maddr_to_virt(l3[l3_index]);
257 l2 = (u64*)(((unsigned long)l2 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
258 printk(" l2 = %p\n", l2);
259 if ( l2 == NULL )
260 continue;
261 l2_index = get_level_index(gmfn, 2);
262 printk(" l2_index = %x\n", l2_index);
263 printk(" l2[%x] = %"PRIx64"\n", l2_index, l2[l2_index]);
265 l1 = maddr_to_virt(l2[l2_index]);
266 l1 = (u64*)(((unsigned long)l1 >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K);
267 printk(" l1 = %p\n", l1);
268 if ( l1 == NULL )
269 continue;
270 l1_index = get_level_index(gmfn, 1);
271 printk(" l1_index = %x\n", l1_index);
272 printk(" l1[%x] = %"PRIx64"\n", l1_index, l1[l1_index]);
273 }
274 }