# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1208336662 -3600
# Node ID 1ac2a314aa3cf10bb0e264942cdae7fda945d7b8
# Parent c777e572a4672f1ebddd95e95b94ca1e1e9e01ca
x86: Fix emulation of PCI access register at I/O port 0xcf8.
The register is only visible for DWORD accesses. Furthermore, some
chipsets place other registers in the range 0xf8-0xcfb for sub-DWORD
accesses.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/arch/x86/domain_build.c | 4 ++--
xen/arch/x86/traps.c | 32 +++++++++++++++-----------------
2 files changed, 17 insertions(+), 19 deletions(-)
diff -r c777e572a467 -r 1ac2a314aa3c xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c Wed Apr 16 09:45:44 2008 +0100
+++ b/xen/arch/x86/domain_build.c Wed Apr 16 10:04:22 2008 +0100
@@ -957,8 +957,8 @@ int __init construct_dom0(
rc |= ioports_deny_access(dom0, 0x40, 0x43);
/* PIT Channel 2 / PC Speaker Control. */
rc |= ioports_deny_access(dom0, 0x61, 0x61);
- /* PCI configuration spaces. */
- rc |= ioports_deny_access(dom0, 0xcf8, 0xcff);
+ /* PCI configuration space (NB. 0xcf8 has special treatment). */
+ rc |= ioports_deny_access(dom0, 0xcfc, 0xcff);
/* Command-line I/O ranges. */
process_dom0_ioports_disable();
diff -r c777e572a467 -r 1ac2a314aa3c xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c Wed Apr 16 09:45:44 2008 +0100
+++ b/xen/arch/x86/traps.c Wed Apr 16 10:04:22 2008 +0100
@@ -1399,6 +1399,13 @@ static int admin_io_okay(
unsigned int port, unsigned int bytes,
struct vcpu *v, struct cpu_user_regs *regs)
{
+ /*
+ * Port 0xcf8 (CONFIG_ADDRESS) is only visible for DWORD accesses.
+ * We never permit direct access to that register.
+ */
+ if ( (port == 0xcf8) && (bytes == 4) )
+ return 0;
+
return ioports_access_permitted(v->domain, port, port + bytes - 1);
}
@@ -1431,10 +1438,10 @@ static uint32_t guest_io_read(
{
sub_data = pv_pit_handler(port, 0, 0);
}
- else if ( (port & 0xfffc) == 0xcf8 )
- {
- size = min(bytes, 4 - (port & 3));
- sub_data = v->domain->arch.pci_cf8 >> ((port & 3) * 8);
+ else if ( (port == 0xcf8) && (bytes == 4) )
+ {
+ size = 4;
+ sub_data = v->domain->arch.pci_cf8;
}
else if ( ((port & 0xfffc) == 0xcfc) && IS_PRIV(v->domain) )
{
@@ -1489,19 +1496,10 @@ static void guest_io_write(
{
pv_pit_handler(port, (uint8_t)data, 1);
}
- else if ( (port & 0xfffc) == 0xcf8 )
- {
- size = min(bytes, 4 - (port & 3));
- if ( size == 4 )
- {
- v->domain->arch.pci_cf8 = data;
- }
- else
- {
- uint32_t mask = ((1u << (size * 8)) - 1) << ((port & 3) * 8);
- v->domain->arch.pci_cf8 &= ~mask;
- v->domain->arch.pci_cf8 |= (data << ((port & 3) * 8)) & mask;
- }
+ else if ( (port == 0xcf8) && (bytes == 4) )
+ {
+ size = 4;
+ v->domain->arch.pci_cf8 = data;
}
else if ( ((port & 0xfffc) == 0xcfc) && IS_PRIV(v->domain) )
{
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|