aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/ioport_emulate.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2007-12-06 11:23:04 +0000
committerKeir Fraser <keir.fraser@citrix.com>2007-12-06 11:23:04 +0000
commit37f5ccfb57bc748ac51f1948e107079ee001d7d8 (patch)
treebef26afe5c2f112fe571cb54743e7fbd28241fde /xen/arch/x86/ioport_emulate.c
parent5048bfb26073bffccc96a0cd2eee8306caa8e82e (diff)
downloadxen-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.c125
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:
+ */