aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/traps.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2012-06-22 13:43:00 +0200
committerJan Beulich <jbeulich@suse.com>2012-06-22 13:43:00 +0200
commit56b3130c1a4ffc3c1a045559240261b892b9b880 (patch)
treecfa39d69fc251380e7358e1230c3a1c3c654cf0a /xen/arch/x86/traps.c
parent7f15d8540d2ea880170194700a8fb4600da8643b (diff)
downloadxen-56b3130c1a4ffc3c1a045559240261b892b9b880.tar.gz
xen-56b3130c1a4ffc3c1a045559240261b892b9b880.tar.bz2
xen-56b3130c1a4ffc3c1a045559240261b892b9b880.zip
AMD IOMMU: add mechanism to protect their PCI devices' config spaces
Recent Dom0 kernels want to disable PCI MSI on all devices, yet doing so on AMD IOMMUs (which get represented by a PCI device) disables part of the functionality set up by the hypervisor. Add a mechanism to mark certain PCI devices as having write protected config spaces (both through port based [method 1] accesses and, for x86-64, mmconfig), and use that for AMD's IOMMUs. Note that due to ptwr_do_page_fault() being run first, there'll be a MEM_LOG() issued for each such mmconfig based write attempt. If that's undesirable, the order of the calls in fixup_page_fault() would need to be swapped. Signed-off-by: Jan Beulich <jbeulich@suse.com> Tested-by: Wei Wang <wei.wang2@amd.com> Acked-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/arch/x86/traps.c')
-rw-r--r--xen/arch/x86/traps.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index dc80c6f506..f0ef7626f8 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -1349,20 +1349,23 @@ static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs)
return 0;
}
- if ( VM_ASSIST(d, VMASST_TYPE_writable_pagetables) &&
- guest_kernel_mode(v, regs) )
- {
- unsigned int mbs = PFEC_write_access;
- unsigned int mbz = PFEC_reserved_bit | PFEC_insn_fetch;
-
- /* Do not check if access-protection fault since the page may
- legitimately be not present in shadow page tables */
- if ( !paging_mode_enabled(d) )
- mbs |= PFEC_page_present;
-
- if ( ((regs->error_code & (mbs | mbz)) == mbs) &&
+ if ( guest_kernel_mode(v, regs) &&
+ !(regs->error_code & (PFEC_reserved_bit | PFEC_insn_fetch)) &&
+ (regs->error_code & PFEC_write_access) )
+ {
+ if ( VM_ASSIST(d, VMASST_TYPE_writable_pagetables) &&
+ /* Do not check if access-protection fault since the page may
+ legitimately be not present in shadow page tables */
+ (paging_mode_enabled(d) ||
+ (regs->error_code & PFEC_page_present)) &&
ptwr_do_page_fault(v, addr, regs) )
return EXCRET_fault_fixed;
+
+#ifdef __x86_64__
+ if ( IS_PRIV(d) && (regs->error_code & PFEC_page_present) &&
+ mmio_ro_do_page_fault(v, addr, regs) )
+ return EXCRET_fault_fixed;
+#endif
}
/* For non-external shadowed guests, we fix up both their own
@@ -1690,6 +1693,13 @@ static int pci_cfg_ok(struct domain *d, int write, int size)
return 0;
machine_bdf = (d->arch.pci_cf8 >> 8) & 0xFFFF;
+ if ( write )
+ {
+ const unsigned long *ro_map = pci_get_ro_map(0);
+
+ if ( ro_map && test_bit(machine_bdf, ro_map) )
+ return 0;
+ }
start = d->arch.pci_cf8 & 0xFF;
end = start + size - 1;
if (xsm_pci_config_permission(d, machine_bdf, start, end, write))