ia64/xen-unstable

changeset 17470:1ac2a314aa3c

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@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Apr 16 10:04:22 2008 +0100 (2008-04-16)
parents c777e572a467
children 681cfd0eda78
files xen/arch/x86/domain_build.c xen/arch/x86/traps.c
line diff
     1.1 --- a/xen/arch/x86/domain_build.c	Wed Apr 16 09:45:44 2008 +0100
     1.2 +++ b/xen/arch/x86/domain_build.c	Wed Apr 16 10:04:22 2008 +0100
     1.3 @@ -957,8 +957,8 @@ int __init construct_dom0(
     1.4      rc |= ioports_deny_access(dom0, 0x40, 0x43);
     1.5      /* PIT Channel 2 / PC Speaker Control. */
     1.6      rc |= ioports_deny_access(dom0, 0x61, 0x61);
     1.7 -    /* PCI configuration spaces. */
     1.8 -    rc |= ioports_deny_access(dom0, 0xcf8, 0xcff);
     1.9 +    /* PCI configuration space (NB. 0xcf8 has special treatment). */
    1.10 +    rc |= ioports_deny_access(dom0, 0xcfc, 0xcff);
    1.11      /* Command-line I/O ranges. */
    1.12      process_dom0_ioports_disable();
    1.13  
     2.1 --- a/xen/arch/x86/traps.c	Wed Apr 16 09:45:44 2008 +0100
     2.2 +++ b/xen/arch/x86/traps.c	Wed Apr 16 10:04:22 2008 +0100
     2.3 @@ -1399,6 +1399,13 @@ static int admin_io_okay(
     2.4      unsigned int port, unsigned int bytes,
     2.5      struct vcpu *v, struct cpu_user_regs *regs)
     2.6  {
     2.7 +    /*
     2.8 +     * Port 0xcf8 (CONFIG_ADDRESS) is only visible for DWORD accesses.
     2.9 +     * We never permit direct access to that register.
    2.10 +     */
    2.11 +    if ( (port == 0xcf8) && (bytes == 4) )
    2.12 +        return 0;
    2.13 +
    2.14      return ioports_access_permitted(v->domain, port, port + bytes - 1);
    2.15  }
    2.16  
    2.17 @@ -1431,10 +1438,10 @@ static uint32_t guest_io_read(
    2.18          {
    2.19              sub_data = pv_pit_handler(port, 0, 0);
    2.20          }
    2.21 -        else if ( (port & 0xfffc) == 0xcf8 )
    2.22 +        else if ( (port == 0xcf8) && (bytes == 4) )
    2.23          {
    2.24 -            size = min(bytes, 4 - (port & 3));
    2.25 -            sub_data = v->domain->arch.pci_cf8 >> ((port & 3) * 8);
    2.26 +            size = 4;
    2.27 +            sub_data = v->domain->arch.pci_cf8;
    2.28          }
    2.29          else if ( ((port & 0xfffc) == 0xcfc) && IS_PRIV(v->domain) )
    2.30          {
    2.31 @@ -1489,19 +1496,10 @@ static void guest_io_write(
    2.32          {
    2.33              pv_pit_handler(port, (uint8_t)data, 1);
    2.34          }
    2.35 -        else if ( (port & 0xfffc) == 0xcf8 )
    2.36 +        else if ( (port == 0xcf8) && (bytes == 4) )
    2.37          {
    2.38 -            size = min(bytes, 4 - (port & 3));
    2.39 -            if ( size == 4 )
    2.40 -            {
    2.41 -                v->domain->arch.pci_cf8 = data;
    2.42 -            }
    2.43 -            else
    2.44 -            {
    2.45 -                uint32_t mask = ((1u << (size * 8)) - 1) << ((port & 3) * 8);
    2.46 -                v->domain->arch.pci_cf8 &= ~mask;
    2.47 -                v->domain->arch.pci_cf8 |= (data << ((port & 3) * 8)) & mask;
    2.48 -            }
    2.49 +            size = 4;
    2.50 +            v->domain->arch.pci_cf8 = data;
    2.51          }
    2.52          else if ( ((port & 0xfffc) == 0xcfc) && IS_PRIV(v->domain) )
    2.53          {