From: Keir Fraser Date: Sat, 8 Dec 2007 17:07:56 +0000 (+0000) Subject: x86: Fix management support on HP ProLiant systems. X-Git-Tag: 3.1.3-rc1~63 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=611026c01bab0f330cfbad534618ddbe413e321a;p=people%2Fvhanquez%2Fxen.git 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 Signed-off-by: Keir Fraser xen-unstable changeset: 16542:1936e6a79f85 xen-unstable date: Thu Dec 06 11:23:04 2007 +0000 x86: Change proliant io emulation stub to use pushf/popf instead of pushfw/popfw. Signed-off-by: Keir Fraser xen-unstable changeset: 16562:35890b260971 xen-unstable date: Fri Dec 07 17:05:15 2007 +0000 --- diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index 389987471..9fd3076e9 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -24,6 +24,7 @@ obj-y += platform_hypercall.o obj-y += i387.o obj-y += i8259.o obj-y += io_apic.o +obj-y += ioport_emulate.o obj-y += irq.o obj-y += microcode.o obj-y += mm.o diff --git a/xen/arch/x86/ioport_emulate.c b/xen/arch/x86/ioport_emulate.c new file mode 100644 index 000000000..b6df73667 --- /dev/null +++ b/xen/arch/x86/ioport_emulate.c @@ -0,0 +1,123 @@ +/****************************************************************************** + * ioport_emulate.c + * + * Handle I/O port access quirks of various platforms. + */ + +#include +#include +#include +#include + +/* 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; + + /* pushf */ + io_emul_stub[0] = 0x9c; + /* cli */ + io_emul_stub[1] = 0xfa; + /* out %al,%dx */ + io_emul_stub[2] = 0xee; + /* 1: in %dx,%al */ + io_emul_stub[3] = 0xec; + /* test $0x80,%al */ + io_emul_stub[4] = 0xa8; + io_emul_stub[5] = 0x80; + /* jnz 1b */ + io_emul_stub[6] = 0x75; + io_emul_stub[7] = 0xfb; + /* popf */ + io_emul_stub[8] = 0x9d; + /* ret */ + io_emul_stub[9] = 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: + */ diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index cea7a87f3..a5a9e965c 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -107,6 +107,8 @@ DECLARE_TRAP_HANDLER(spurious_interrupt_bug); long do_set_debugreg(int reg, unsigned long value); unsigned long do_get_debugreg(int reg); +void (*ioemul_handle_quirk)( + u8 opcode, char *io_emul_stub, struct cpu_user_regs *regs); static int debug_stack_lines = 20; integer_param("debug_stack_lines", debug_stack_lines); @@ -1217,7 +1219,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) ? (*(u32 *)®s->reg = (val)) \ : (*(u16 *)®s->reg = (val))) unsigned long code_base, code_limit; - char io_emul_stub[16]; + char io_emul_stub[32]; void (*io_emul)(struct cpu_user_regs *) __attribute__((__regparm__(1))); u32 l, h, eax, edx; @@ -1468,6 +1470,9 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) /* Handy function-typed pointer to the stub. */ io_emul = (void *)io_emul_stub; + if ( ioemul_handle_quirk ) + ioemul_handle_quirk(opcode, &io_emul_stub[12], regs); + /* I/O Port and Interrupt Flag instructions. */ switch ( opcode ) {