# HG changeset patch
# User Mike Garrett <michael.garrett@xxxxxx>
# Date 1196108221 21600
# Node ID 32be7dd9fab00cf4fb9014ab235497a39593ffb4
# Parent ba69fe2dce91cd7ef633b4b21706344f6be1a6de
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@xxxxxx>
diff -r ba69fe2dce91 -r 32be7dd9fab0 xen/arch/x86/Makefile
--- a/xen/arch/x86/Makefile Tue Nov 13 20:13:50 2007 +0000
+++ b/xen/arch/x86/Makefile Mon Nov 26 14:17:01 2007 -0600
@@ -31,6 +31,7 @@ obj-y += nmi.o
obj-y += nmi.o
obj-y += numa.o
obj-y += physdev.o
+obj-y += hp_proliant.o
obj-y += rwlock.o
obj-y += setup.o
obj-y += shutdown.o
diff -r ba69fe2dce91 -r 32be7dd9fab0 xen/arch/x86/hp_proliant.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/hp_proliant.c Mon Nov 26 14:17:01 2007 -0600
@@ -0,0 +1,87 @@
+/* HP ProLiant specific code */
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/sched.h>
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/mm.h>
+#include <xen/console.h>
+#include <xen/shutdown.h>
+#include <asm/regs.h>
+#include <xen/delay.h>
+#include <xen/event.h>
+#include <xen/spinlock.h>
+#include <xen/irq.h>
+#include <xen/perfc.h>
+#include <xen/softirq.h>
+#include <xen/domain_page.h>
+#include <xen/symbols.h>
+#include <xen/iocap.h>
+#include <xen/nmi.h>
+#include <xen/version.h>
+#include <xen/kexec.h>
+#include <asm/paging.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/desc.h>
+#include <asm/debugreg.h>
+#include <asm/smp.h>
+#include <asm/flushtlb.h>
+#include <asm/uaccess.h>
+#include <asm/i387.h>
+#include <asm/debugger.h>
+#include <asm/msr.h>
+#include <asm/shared.h>
+#include <asm/x86_emulate.h>
+#include <asm/hvm/vpt.h>
+#include <xen/dmi.h>
+
+
+/* Declare access to a function pointer used to handle platform specific I/O
port emulation */
+extern u8 (*emulate_platform_specific_io_port)(u8 opcode, u16 port, u8 value,
char* io_emul_stub, struct cpu_user_regs *regs);
+
+/* Do special handling of HP ProLiant port */
+static u8 emulate_proliant_specific_io_port(u8 opcode, u16 port, u8 value,
char* io_emul_stub, struct cpu_user_regs *regs)
+{
+ /* if opcode = I/O write, and port = 0CD4 and we are writing the high
bit to 1 */
+ if (opcode == 0xee && port == 0x0cd4 && (value & 0x80))
+ {
+ void (*io_emul)(struct cpu_user_regs *)
__attribute__((__regparm__(1)));
+
+ /* Handy function-typed pointer to the stub. */
+ io_emul = (void *) io_emul_stub;
+
+ /*
+ * important offsets (from original code)
+ * +0 -> +4/+11: call host_to_guest_gpr_switch (32 bit
and 64 bit)
+ * ret is rigged to return to guest_to_host_gpr_switch via a
stack stunt
+ */
+
+ io_emul_stub[12] = 0x66; //
+ io_emul_stub[13] = 0x9c; // pushf
+ io_emul_stub[14] = 0xfa; // cli
+ io_emul_stub[15] = 0xee; // out dx, al
+ // loop:
+ io_emul_stub[16] = 0xec; // in al, dx
+ io_emul_stub[17] = 0xa8; //
+ io_emul_stub[18] = 0x80; // test al, 80h
+ io_emul_stub[19] = 0x75; // jnz short loop
+ io_emul_stub[20] = 0xfb; //
+ io_emul_stub[21] = 0x66; //
+ io_emul_stub[22] = 0x9d; // popf
+ io_emul_stub[23] = 0xc3; // ret
+
+ io_emul(regs);
+
+ return 1; // we handled
it, no need for generic handling
+ }
+ return 0; // we didn't
handle it, do generic handling
+}
+
+int __init set_proliant_io_emul(struct dmi_system_id *d)
+{
+ /* emulate_platform_specific_io_port should be NULL on entry */
+ emulate_platform_specific_io_port = emulate_proliant_specific_io_port;
+ return 0;
+}
diff -r ba69fe2dce91 -r 32be7dd9fab0 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c Tue Nov 13 20:13:50 2007 +0000
+++ b/xen/arch/x86/setup.c Mon Nov 26 14:17:01 2007 -0600
@@ -49,6 +49,7 @@
extern void generic_apic_probe(void);
extern void numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn);
+extern int __init io_emul_init(void);
extern u16 boot_edid_caps;
extern u8 boot_edid_info[128];
@@ -868,6 +869,8 @@ void __init __start_xen(unsigned long mb
acpi_boot_init();
+ io_emul_init();
+
init_cpu_to_node();
if ( smp_found_config )
diff -r ba69fe2dce91 -r 32be7dd9fab0 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c Tue Nov 13 20:13:50 2007 +0000
+++ b/xen/arch/x86/traps.c Mon Nov 26 14:17:01 2007 -0600
@@ -62,6 +62,7 @@
#include <asm/shared.h>
#include <asm/x86_emulate.h>
#include <asm/hvm/vpt.h>
+#include <xen/dmi.h>
/*
* opt_nmi: one of 'ignore', 'dom0', or 'fatal'.
@@ -110,6 +111,7 @@ DECLARE_TRAP_HANDLER(spurious_interrupt_
long do_set_debugreg(int reg, unsigned long value);
unsigned long do_get_debugreg(int reg);
+u8 (*emulate_platform_specific_io_port)(u8 opcode, u16 port, u8 value, char*
io_emul_stub, struct cpu_user_regs *regs) = NULL;
static int debug_stack_lines = 20;
integer_param("debug_stack_lines", debug_stack_lines);
@@ -1331,7 +1333,7 @@ static int emulate_privileged_op(struct
? (*(u32 *)®s->reg = (val)) \
: (*(u16 *)®s->reg = (val)))
unsigned long code_base, code_limit;
- char io_emul_stub[16];
+ char io_emul_stub[32]; /* size increased from 16 to 32 bytes to handle
platform-specific port emulation */
void (*io_emul)(struct cpu_user_regs *) __attribute__((__regparm__(1)));
u32 l, h, eax, edx;
@@ -1642,7 +1644,11 @@ static int emulate_privileged_op(struct
switch ( op_bytes )
{
case 1:
- if ( guest_outb_okay(port, v, regs) )
+ /* check and emulate platform-specific I/O ports */
+ if (emulate_platform_specific_io_port != NULL &&
+ emulate_platform_specific_io_port(opcode, port,
(u8) regs->eax, io_emul_stub, regs))
+ ; /* no more work to do, if true, the platform
specific handler emulated it fully */
+ else if ( guest_outb_okay(port, v, regs) )
{
io_emul(regs);
if ( pv_post_outb_hook )
@@ -2850,6 +2856,67 @@ unsigned long do_get_debugreg(int reg)
return current->arch.guest_context.debugreg[reg];
}
+/* This table is the set of system specific I/O emulation hooks */
+extern int __init set_proliant_io_emul(struct dmi_system_id *d);
+static struct dmi_system_id __initdata io_emul_init_tbl[] = {
+ { /* Handle I/O emulation hook for certain HP ProLiant servers */
+ .callback = set_proliant_io_emul,
+ .ident = "HP ProLiant DL3xx",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL3"),
+ },
+ },
+ { /* Handle I/O emulation hook for certain HP ProLiant servers */
+ .callback = set_proliant_io_emul,
+ .ident = "HP ProLiant DL5xx",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL5"),
+ },
+ },
+ { /* Handle I/O emulation hook for certain HP ProLiant servers */
+ .callback = set_proliant_io_emul,
+ .ident = "HP ProLiant ML3xx",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant ML3"),
+ },
+ },
+ { /* Handle I/O emulation hook for certain HP ProLiant servers */
+ .callback = set_proliant_io_emul,
+ .ident = "HP ProLiant ML5xx",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant ML5"),
+ },
+ },
+ { /* Handle I/O emulation hook for certain HP ProLiant servers */
+ .callback = set_proliant_io_emul,
+ .ident = "HP ProLiant BL4xx",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL4"),
+ },
+ },
+ { /* Handle I/O emulation hook for certain HP ProLiant servers */
+ .callback = set_proliant_io_emul,
+ .ident = "HP ProLiant BL6xx",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL6"),
+ },
+ },
+ { }
+};
+
+/* Called during setup, allows us to hook system-specific I/O emulation hooks
*/
+int __init io_emul_init(void)
+{
+ dmi_check_system(io_emul_init_tbl);
+ return 0;
+}
+
/*
* Local variables:
* mode: C
hp_proliant_support.txt
Description: hp_proliant_support.txt
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|