]> xenbits.xensource.com Git - people/vhanquez/xen.git/commitdiff
x86: Fix management support on HP ProLiant systems.
authorKeir Fraser <keir.fraser@citrix.com>
Sat, 8 Dec 2007 17:07:56 +0000 (17:07 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Sat, 8 Dec 2007 17:07:56 +0000 (17:07 +0000)
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>
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 <keir.fraser@citrix.com>
xen-unstable changeset:   16562:35890b260971
xen-unstable date:        Fri Dec 07 17:05:15 2007 +0000

xen/arch/x86/Makefile
xen/arch/x86/ioport_emulate.c [new file with mode: 0644]
xen/arch/x86/traps.c

index 3899874714aecdf3ce974d6e51ecc036a58114a6..9fd3076e9a65efe3280f7730b5771c776f582fc9 100644 (file)
@@ -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 (file)
index 0000000..b6df736
--- /dev/null
@@ -0,0 +1,123 @@
+/******************************************************************************
+ * 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;
+
+    /*    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:
+ */
index cea7a87f310f94cefee379733ddbe729c2d9000b..a5a9e965cb5ff6113decece8ace9b946793a6920 100644 (file)
@@ -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 *)&regs->reg = (val)) \
                            : (*(u16 *)&regs->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 )
     {