ia64/xen-unstable

changeset 16542:1936e6a79f85

x86: Fix management support on HP ProLiant systems.

Adds support to allow host-platform-specific handling of I/O port
traps. Specifically adds support to handle an HP ProLiant I/O port in a
special way.

Signed-off-by: Mike Garrett <michael.garrett@hp.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Dec 06 11:23:04 2007 +0000 (2007-12-06)
parents 90f02ca76244
children 46776e65e679
files xen/arch/x86/Makefile xen/arch/x86/ioport_emulate.c xen/arch/x86/traps.c
line diff
     1.1 --- a/xen/arch/x86/Makefile	Thu Dec 06 10:41:10 2007 +0000
     1.2 +++ b/xen/arch/x86/Makefile	Thu Dec 06 11:23:04 2007 +0000
     1.3 @@ -24,6 +24,7 @@ obj-y += platform_hypercall.o
     1.4  obj-y += i387.o
     1.5  obj-y += i8259.o
     1.6  obj-y += io_apic.o
     1.7 +obj-y += ioport_emulate.o
     1.8  obj-y += irq.o
     1.9  obj-y += microcode.o
    1.10  obj-y += mm.o
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/xen/arch/x86/ioport_emulate.c	Thu Dec 06 11:23:04 2007 +0000
     2.3 @@ -0,0 +1,125 @@
     2.4 +/******************************************************************************
     2.5 + * ioport_emulate.c
     2.6 + * 
     2.7 + * Handle I/O port access quirks of various platforms.
     2.8 + */
     2.9 +
    2.10 +#include <xen/config.h>
    2.11 +#include <xen/init.h>
    2.12 +#include <xen/sched.h>
    2.13 +#include <xen/dmi.h>
    2.14 +
    2.15 +/* Function pointer used to handle platform specific I/O port emulation. */
    2.16 +extern void (*ioemul_handle_quirk)(
    2.17 +    u8 opcode, char *io_emul_stub, struct cpu_user_regs *regs);
    2.18 +
    2.19 +static void ioemul_handle_proliant_quirk(
    2.20 +    u8 opcode, char *io_emul_stub, struct cpu_user_regs *regs)
    2.21 +{
    2.22 +    uint16_t port = regs->edx;
    2.23 +    uint8_t value = regs->eax;
    2.24 +
    2.25 +    if ( (opcode != 0xee) || (port != 0xcd4) || !(value & 0x80) )
    2.26 +        return;
    2.27 +
    2.28 +    /*    pushfw */
    2.29 +    io_emul_stub[ 0] = 0x66;
    2.30 +    io_emul_stub[ 1] = 0x9c;
    2.31 +    /*    cli */
    2.32 +    io_emul_stub[ 2] = 0xfa;
    2.33 +    /*    out %al,%dx */
    2.34 +    io_emul_stub[ 3] = 0xee;
    2.35 +    /* 1: in %dx,%al */
    2.36 +    io_emul_stub[ 4] = 0xec;
    2.37 +    /*    test $0x80,%al */
    2.38 +    io_emul_stub[ 5] = 0xa8;
    2.39 +    io_emul_stub[ 6] = 0x80;
    2.40 +    /*    jnz 1b */
    2.41 +    io_emul_stub[ 7] = 0x75;
    2.42 +    io_emul_stub[ 8] = 0xfb;
    2.43 +    /*    popfw */
    2.44 +    io_emul_stub[ 9] = 0x66;
    2.45 +    io_emul_stub[10] = 0x9d;
    2.46 +    /*    ret */
    2.47 +    io_emul_stub[11] = 0xc3;
    2.48 +}
    2.49 +
    2.50 +int __init proliant_quirk(struct dmi_system_id *d)
    2.51 +{
    2.52 +    ioemul_handle_quirk = ioemul_handle_proliant_quirk;
    2.53 +    return 0;
    2.54 +}
    2.55 +
    2.56 +/* This table is the set of system-specific I/O emulation hooks. */
    2.57 +static struct dmi_system_id __initdata ioport_quirks_tbl[] = {
    2.58 +    /*
    2.59 +     * I/O emulation hook for certain HP ProLiant servers with
    2.60 +     * 'special' SMM goodness.
    2.61 +     */
    2.62 +    {
    2.63 +        .callback = proliant_quirk,
    2.64 +        .ident = "HP ProLiant DL3xx",
    2.65 +        .matches = {
    2.66 +            DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
    2.67 +            DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL3"),
    2.68 +        },
    2.69 +    },
    2.70 +    {
    2.71 +        .callback = proliant_quirk,
    2.72 +        .ident = "HP ProLiant DL5xx",
    2.73 +        .matches = {
    2.74 +            DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
    2.75 +            DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL5"),
    2.76 +        },
    2.77 +    },
    2.78 +    {
    2.79 +        .callback = proliant_quirk,
    2.80 +        .ident = "HP ProLiant ML3xx",
    2.81 +        .matches = {
    2.82 +            DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
    2.83 +            DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant ML3"),
    2.84 +        },
    2.85 +    },
    2.86 +    {
    2.87 +        .callback = proliant_quirk,
    2.88 +        .ident = "HP ProLiant ML5xx",
    2.89 +        .matches = {
    2.90 +            DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
    2.91 +            DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant ML5"),
    2.92 +        },
    2.93 +    },
    2.94 +    {
    2.95 +        .callback = proliant_quirk,
    2.96 +        .ident = "HP ProLiant BL4xx",
    2.97 +        .matches = {
    2.98 +            DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
    2.99 +            DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL4"),
   2.100 +        },
   2.101 +    },
   2.102 +    {
   2.103 +        .callback = proliant_quirk,
   2.104 +        .ident = "HP ProLiant BL6xx",
   2.105 +        .matches = {
   2.106 +            DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
   2.107 +            DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL6"),
   2.108 +        },
   2.109 +    },
   2.110 +    { }
   2.111 +};
   2.112 +
   2.113 +int __init ioport_quirks_init(void)
   2.114 +{
   2.115 +    dmi_check_system(ioport_quirks_tbl);
   2.116 +    return 0;
   2.117 +}
   2.118 +__initcall(ioport_quirks_init);
   2.119 +
   2.120 +/*
   2.121 + * Local variables:
   2.122 + * mode: C
   2.123 + * c-set-style: "BSD"
   2.124 + * c-basic-offset: 4
   2.125 + * tab-width: 4
   2.126 + * indent-tabs-mode: nil
   2.127 + * End:
   2.128 + */
     3.1 --- a/xen/arch/x86/traps.c	Thu Dec 06 10:41:10 2007 +0000
     3.2 +++ b/xen/arch/x86/traps.c	Thu Dec 06 11:23:04 2007 +0000
     3.3 @@ -110,6 +110,8 @@ DECLARE_TRAP_HANDLER(spurious_interrupt_
     3.4  
     3.5  long do_set_debugreg(int reg, unsigned long value);
     3.6  unsigned long do_get_debugreg(int reg);
     3.7 +void (*ioemul_handle_quirk)(
     3.8 +    u8 opcode, char *io_emul_stub, struct cpu_user_regs *regs);
     3.9  
    3.10  static int debug_stack_lines = 20;
    3.11  integer_param("debug_stack_lines", debug_stack_lines);
    3.12 @@ -1379,7 +1381,7 @@ static int emulate_privileged_op(struct 
    3.13                             ? (*(u32 *)&regs->reg = (val)) \
    3.14                             : (*(u16 *)&regs->reg = (val)))
    3.15      unsigned long code_base, code_limit;
    3.16 -    char io_emul_stub[16];
    3.17 +    char io_emul_stub[32];
    3.18      void (*io_emul)(struct cpu_user_regs *) __attribute__((__regparm__(1)));
    3.19      u32 l, h, eax, edx;
    3.20  
    3.21 @@ -1636,6 +1638,9 @@ static int emulate_privileged_op(struct 
    3.22      /* Handy function-typed pointer to the stub. */
    3.23      io_emul = (void *)io_emul_stub;
    3.24  
    3.25 +    if ( ioemul_handle_quirk )
    3.26 +        ioemul_handle_quirk(opcode, &io_emul_stub[12], regs);
    3.27 +
    3.28      /* I/O Port and Interrupt Flag instructions. */
    3.29      switch ( opcode )
    3.30      {