diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2007-12-06 11:23:04 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2007-12-06 11:23:04 +0000 |
commit | 37f5ccfb57bc748ac51f1948e107079ee001d7d8 (patch) | |
tree | bef26afe5c2f112fe571cb54743e7fbd28241fde /xen/arch/x86/ioport_emulate.c | |
parent | 5048bfb26073bffccc96a0cd2eee8306caa8e82e (diff) | |
download | xen-37f5ccfb57bc748ac51f1948e107079ee001d7d8.tar.gz xen-37f5ccfb57bc748ac51f1948e107079ee001d7d8.tar.bz2 xen-37f5ccfb57bc748ac51f1948e107079ee001d7d8.zip |
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>
Diffstat (limited to 'xen/arch/x86/ioport_emulate.c')
-rw-r--r-- | xen/arch/x86/ioport_emulate.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/xen/arch/x86/ioport_emulate.c b/xen/arch/x86/ioport_emulate.c new file mode 100644 index 0000000000..2180b6027b --- /dev/null +++ b/xen/arch/x86/ioport_emulate.c @@ -0,0 +1,125 @@ +/****************************************************************************** + * ioport_emulate.c + * + * Handle I/O port access quirks of various platforms. + */ + +#include <xen/config.h> +#include <xen/init.h> +#include <xen/sched.h> +#include <xen/dmi.h> + +/* Function pointer used to handle platform specific I/O port emulation. */ +extern void (*ioemul_handle_quirk)( + u8 opcode, char *io_emul_stub, struct cpu_user_regs *regs); + +static void ioemul_handle_proliant_quirk( + u8 opcode, char *io_emul_stub, struct cpu_user_regs *regs) +{ + uint16_t port = regs->edx; + uint8_t value = regs->eax; + + if ( (opcode != 0xee) || (port != 0xcd4) || !(value & 0x80) ) + return; + + /* pushfw */ + io_emul_stub[ 0] = 0x66; + io_emul_stub[ 1] = 0x9c; + /* cli */ + io_emul_stub[ 2] = 0xfa; + /* out %al,%dx */ + io_emul_stub[ 3] = 0xee; + /* 1: in %dx,%al */ + io_emul_stub[ 4] = 0xec; + /* test $0x80,%al */ + io_emul_stub[ 5] = 0xa8; + io_emul_stub[ 6] = 0x80; + /* jnz 1b */ + io_emul_stub[ 7] = 0x75; + io_emul_stub[ 8] = 0xfb; + /* popfw */ + io_emul_stub[ 9] = 0x66; + io_emul_stub[10] = 0x9d; + /* ret */ + io_emul_stub[11] = 0xc3; +} + +int __init proliant_quirk(struct dmi_system_id *d) +{ + ioemul_handle_quirk = ioemul_handle_proliant_quirk; + return 0; +} + +/* This table is the set of system-specific I/O emulation hooks. */ +static struct dmi_system_id __initdata ioport_quirks_tbl[] = { + /* + * I/O emulation hook for certain HP ProLiant servers with + * 'special' SMM goodness. + */ + { + .callback = proliant_quirk, + .ident = "HP ProLiant DL3xx", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL3"), + }, + }, + { + .callback = proliant_quirk, + .ident = "HP ProLiant DL5xx", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL5"), + }, + }, + { + .callback = proliant_quirk, + .ident = "HP ProLiant ML3xx", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant ML3"), + }, + }, + { + .callback = proliant_quirk, + .ident = "HP ProLiant ML5xx", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant ML5"), + }, + }, + { + .callback = proliant_quirk, + .ident = "HP ProLiant BL4xx", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL4"), + }, + }, + { + .callback = proliant_quirk, + .ident = "HP ProLiant BL6xx", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL6"), + }, + }, + { } +}; + +int __init ioport_quirks_init(void) +{ + dmi_check_system(ioport_quirks_tbl); + return 0; +} +__initcall(ioport_quirks_init); + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ |