From: Jan Beulich Bugzilla #192150 Index: 2006-09-11/xen/arch/x86/domain_build.c =================================================================== --- 2006-09-11.orig/xen/arch/x86/domain_build.c 2006-09-18 13:58:26.000000000 +0200 +++ 2006-09-11/xen/arch/x86/domain_build.c 2006-09-18 15:15:40.000000000 +0200 @@ -33,6 +33,11 @@ extern unsigned long initial_images_nrpages(void); extern void discard_initial_images(void); +/* I/O-port Xen-enforced or admin-specified access control. */ +struct rangeset *ioport_caps = NULL; +/* I/O-port admin-specified non-special access requirements. */ +struct rangeset *ioport_emul = NULL; + static long dom0_nrpages; /* @@ -64,6 +69,12 @@ integer_param("dom0_max_vcpus", opt_dom0 static unsigned int opt_dom0_shadow; boolean_param("dom0_shadow", opt_dom0_shadow); +static char opt_ioports_noemul[200] = ""; +string_param("ioports_noemul", opt_ioports_noemul); + +static char opt_ioports_disable[200] = ""; +string_param("ioports_disable", opt_ioports_disable); + static char opt_dom0_ioports_disable[200] = ""; string_param("dom0_ioports_disable", opt_dom0_ioports_disable); @@ -102,10 +113,10 @@ static struct page_info *alloc_chunk(str return page; } -static void process_dom0_ioports_disable(void) +static void process_ioports(char *opt) { unsigned long io_from, io_to; - char *t, *u, *s = opt_dom0_ioports_disable; + char *t, *u, *s = opt; if ( *s == '\0' ) return; @@ -117,7 +128,9 @@ static void process_dom0_ioports_disable { parse_error: printk("Invalid ioport range <%s> " - "in dom0_ioports_disable, skipping\n", t); + "in %sioports_%s, skipping\n", t, + opt == opt_dom0_ioports_disable ? "dom0_" : "", + opt != opt_ioports_noemul ? "disable" : "noemul"); continue; } @@ -131,11 +144,26 @@ static void process_dom0_ioports_disable if ( (*u != '\0') || (io_to < io_from) || (io_to >= 65536) ) goto parse_error; - printk("Disabling dom0 access to ioport range %04lx-%04lx\n", - io_from, io_to); + if ( opt != opt_ioports_noemul ) + { + printk("Disabling %saccess to ioport range %04lx-%04lx\n", + opt != opt_ioports_disable ? "dom0 " : "", + io_from, io_to); - if ( ioports_deny_access(dom0, io_from, io_to) != 0 ) - BUG(); + if ( opt == opt_ioports_disable + && ioports_deny_access_all(io_from, io_to) != 0 ) + BUG(); + if ( ioports_deny_access(dom0, io_from, io_to) != 0 ) + BUG(); + } + else + { + printk("Setting non-emulated access for ioport range %04lx-%04lx\n", + io_from, io_to); + + if ( ioports_set_noemul(io_from, io_to) != 0 ) + BUG(); + } } } @@ -815,6 +843,13 @@ int construct_dom0(struct domain *d, rc = 0; + /* Command-line I/O ranges. */ + ioport_caps = rangeset_new(NULL, + "global I/O Port access control", + RANGESETF_prettyprint_hex); + BUG_ON(!ioport_caps); + rc |= ioports_permit_access_all(0, 0xFFFF); + /* DOM0 is permitted full I/O capabilities. */ rc |= ioports_permit_access(dom0, 0, 0xFFFF); rc |= iomem_permit_access(dom0, 0UL, ~0UL); @@ -824,15 +859,20 @@ int construct_dom0(struct domain *d, * Modify I/O port access permissions. */ /* Master Interrupt Controller (PIC). */ + rc |= ioports_deny_access_all(0x20, 0x21); rc |= ioports_deny_access(dom0, 0x20, 0x21); /* Slave Interrupt Controller (PIC). */ + rc |= ioports_deny_access_all(0xA0, 0xA1); rc |= ioports_deny_access(dom0, 0xA0, 0xA1); /* Interval Timer (PIT). */ + rc |= ioports_deny_access_all(0x40, 0x43); rc |= ioports_deny_access(dom0, 0x40, 0x43); /* PIT Channel 2 / PC Speaker Control. */ + rc |= ioports_deny_access_all(0x61, 0x61); rc |= ioports_deny_access(dom0, 0x61, 0x61); /* Command-line I/O ranges. */ - process_dom0_ioports_disable(); + process_ioports(opt_ioports_disable); + process_ioports(opt_dom0_ioports_disable); /* * Modify I/O memory access permissions. @@ -851,6 +891,14 @@ int construct_dom0(struct domain *d, rc |= iomem_deny_access(dom0, mfn, mfn); } + /* Command-line I/O ranges requiring full register context access. */ + ioport_emul = rangeset_new(NULL, + "I/O Port emulation control", + RANGESETF_prettyprint_hex); + BUG_ON(!ioport_emul); + rc |= ioports_set_emul(0, 0xFFFF); + process_ioports(opt_ioports_noemul); + BUG_ON(rc != 0); return 0; Index: 2006-09-11/xen/arch/x86/sysctl.c =================================================================== --- 2006-09-11.orig/xen/arch/x86/sysctl.c 2006-09-18 13:58:26.000000000 +0200 +++ 2006-09-11/xen/arch/x86/sysctl.c 2006-09-18 13:58:56.000000000 +0200 @@ -57,6 +57,23 @@ long arch_do_sysctl( } break; + case XEN_SYSCTL_ioport_emulation: + { + unsigned int fp = sysctl->u.ioport_emulation.first_port; + unsigned int np = sysctl->u.ioport_emulation.nr_ports; + + ret = -EINVAL; + if ( (fp + np) > 65536 ) + break; + + if ( np == 0 ) + ret = 0; + else if ( sysctl->u.ioport_emulation.emulate ) + ret = ioports_set_emul(fp, fp + np - 1); + else + ret = ioports_set_noemul(fp, fp + np - 1); + } + break; default: ret = -ENOSYS; Index: 2006-09-11/xen/arch/x86/traps.c =================================================================== --- 2006-09-11.orig/xen/arch/x86/traps.c 2006-09-18 13:58:26.000000000 +0200 +++ 2006-09-11/xen/arch/x86/traps.c 2006-09-18 15:15:58.000000000 +0200 @@ -1002,9 +1002,20 @@ static inline int admin_io_okay( return ioports_access_permitted(v->domain, port, port + bytes - 1); } +typedef unsigned long io_emul_stub_t(struct cpu_user_regs *) __attribute__((__regparm__(1))); +long io_emul_stub_offset = 0, io_emul_insn_offset = 0; + +/* Can the I/O access be carried out without full register context? */ +static inline int normal_io_okay( + unsigned int port, unsigned int bytes) +{ + return ioports_emul(port, port + bytes - 1); +} + /* Check admin limits. Silently fail the access if it is disallowed. */ static inline unsigned char inb_user( - unsigned int port, struct vcpu *v, struct cpu_user_regs *regs) + unsigned int port, io_emul_stub_t *stub, + struct vcpu *v, struct cpu_user_regs *regs) { /* * Allow read access to port 0x61. Bit 4 oscillates with period 30us, and @@ -1014,18 +1025,54 @@ static inline int admin_io_okay( * but there's not really a good reason to do so. */ if ( admin_io_okay(port, 1, v, regs) || (port == 0x61) ) - return inb(port); + return !stub || normal_io_okay(port, 1) ? inb(port) : stub(regs); return ~0; } -//#define inb_user(_p, _d, _r) (admin_io_okay(_p, 1, _d, _r) ? inb(_p) : ~0) -#define inw_user(_p, _d, _r) (admin_io_okay(_p, 2, _d, _r) ? inw(_p) : ~0) -#define inl_user(_p, _d, _r) (admin_io_okay(_p, 4, _d, _r) ? inl(_p) : ~0) -#define outb_user(_v, _p, _d, _r) \ - (admin_io_okay(_p, 1, _d, _r) ? outb(_v, _p) : ((void)0)) -#define outw_user(_v, _p, _d, _r) \ - (admin_io_okay(_p, 2, _d, _r) ? outw(_v, _p) : ((void)0)) -#define outl_user(_v, _p, _d, _r) \ - (admin_io_okay(_p, 4, _d, _r) ? outl(_v, _p) : ((void)0)) + +static inline unsigned short inw_user( + unsigned int port, io_emul_stub_t *stub, + struct vcpu *v, struct cpu_user_regs *regs) +{ + if ( admin_io_okay(port, 2, v, regs) ) + return !stub || normal_io_okay(port, 2) ? inw(port) : stub(regs); + return ~0; +} + +static inline unsigned int inl_user( + unsigned int port, io_emul_stub_t *stub, + struct vcpu *v, struct cpu_user_regs *regs) +{ + if ( admin_io_okay(port, 4, v, regs) ) + return !stub || normal_io_okay(port, 4) ? inl(port) : stub(regs); + return ~0; +} + +static inline void outb_user( + unsigned char value, unsigned int port, + io_emul_stub_t *stub, + struct vcpu *v, struct cpu_user_regs *regs) +{ + if ( admin_io_okay(port, 1, v, regs) ) + !stub || normal_io_okay(port, 1) ? outb(value, port) : (void)stub(regs); +} + +static inline void outw_user( + unsigned short value, unsigned int port, + io_emul_stub_t *stub, + struct vcpu *v, struct cpu_user_regs *regs) +{ + if ( admin_io_okay(port, 2, v, regs) ) + !stub || normal_io_okay(port, 2) ? outw(value, port) : (void)stub(regs); +} + +static inline void outl_user( + unsigned int value, unsigned int port, + io_emul_stub_t *stub, + struct vcpu *v, struct cpu_user_regs *regs) +{ + if ( admin_io_okay(port, 4, v, regs) ) + !stub || normal_io_okay(port, 4) ? outl(value, port) : (void)stub(regs); +} /* Instruction fetch with error handling. */ #define insn_fetch(_type, _size, _ptr) \ @@ -1044,6 +1091,8 @@ static int emulate_privileged_op(struct u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0; unsigned int port, i, op_bytes = 4, data, rc; u32 l, h; + io_emul_stub_t *stub; + char *insn; /* Legacy prefixes. */ for ( i = 0; i < 8; i++ ) @@ -1101,13 +1150,13 @@ static int emulate_privileged_op(struct switch ( op_bytes ) { case 1: - data = (u8)inb_user((u16)regs->edx, v, regs); + data = (u8)inb_user((u16)regs->edx, NULL, v, regs); break; case 2: - data = (u16)inw_user((u16)regs->edx, v, regs); + data = (u16)inw_user((u16)regs->edx, NULL, v, regs); break; case 4: - data = (u32)inl_user((u16)regs->edx, v, regs); + data = (u32)inl_user((u16)regs->edx, NULL, v, regs); break; } if ( (rc = copy_to_user((void *)regs->edi, &data, op_bytes)) != 0 ) @@ -1133,13 +1182,13 @@ static int emulate_privileged_op(struct switch ( op_bytes ) { case 1: - outb_user((u8)data, (u16)regs->edx, v, regs); + outb_user((u8)data, (u16)regs->edx, NULL, v, regs); break; case 2: - outw_user((u16)data, (u16)regs->edx, v, regs); + outw_user((u16)data, (u16)regs->edx, NULL, v, regs); break; case 4: - outl_user((u32)data, (u16)regs->edx, v, regs); + outl_user((u32)data, (u16)regs->edx, NULL, v, regs); break; } regs->esi += (int)((regs->eflags & EF_DF) ? -op_bytes : op_bytes); @@ -1157,27 +1206,33 @@ static int emulate_privileged_op(struct } /* I/O Port and Interrupt Flag instructions. */ + insn = (char *)get_stack_bottom(); + stub = (io_emul_stub_t *)(insn + io_emul_stub_offset); + insn += io_emul_insn_offset; + *insn++ = op_bytes != 2 ? 0x90 : 0x66; + *insn++ = opcode; switch ( opcode ) { case 0xe4: /* IN imm8,%al */ op_bytes = 1; case 0xe5: /* IN imm8,%eax */ port = insn_fetch(u8, 1, eip); + *insn = port; exec_in: if ( !guest_io_okay(port, op_bytes, v, regs) ) goto fail; switch ( op_bytes ) { case 1: - regs->eax &= ~0xffUL; - regs->eax |= (u8)inb_user(port, v, regs); + res = regs->eax & ~0xffUL; + regs->eax = res | (u8)inb_user(port, stub, v, regs); break; case 2: - regs->eax &= ~0xffffUL; - regs->eax |= (u16)inw_user(port, v, regs); + res = regs->eax & ~0xffffUL; + regs->eax = res | (u16)inw_user(port, stub, v, regs); break; case 4: - regs->eax = (u32)inl_user(port, v, regs); + regs->eax = (u32)inl_user(port, stub, v, regs); break; } goto done; @@ -1186,25 +1241,27 @@ static int emulate_privileged_op(struct op_bytes = 1; case 0xed: /* IN %dx,%eax */ port = (u16)regs->edx; + *insn = 0x90; goto exec_in; case 0xe6: /* OUT %al,imm8 */ op_bytes = 1; case 0xe7: /* OUT %eax,imm8 */ port = insn_fetch(u8, 1, eip); + *insn = port; exec_out: if ( !guest_io_okay(port, op_bytes, v, regs) ) goto fail; switch ( op_bytes ) { case 1: - outb_user((u8)regs->eax, port, v, regs); + outb_user((u8)regs->eax, port, stub, v, regs); break; case 2: - outw_user((u16)regs->eax, port, v, regs); + outw_user((u16)regs->eax, port, stub, v, regs); break; case 4: - outl_user((u32)regs->eax, port, v, regs); + outl_user((u32)regs->eax, port, stub, v, regs); break; } goto done; @@ -1213,6 +1270,7 @@ static int emulate_privileged_op(struct op_bytes = 1; case 0xef: /* OUT %eax,%dx */ port = (u16)regs->edx; + *insn = 0x90; goto exec_out; case 0xfa: /* CLI */ Index: 2006-09-11/xen/arch/x86/x86_32/Makefile =================================================================== --- 2006-09-11.orig/xen/arch/x86/x86_32/Makefile 2006-09-18 13:58:26.000000000 +0200 +++ 2006-09-11/xen/arch/x86/x86_32/Makefile 2006-09-18 13:58:56.000000000 +0200 @@ -1,5 +1,6 @@ obj-y += domain_page.o obj-y += entry.o +obj-y += io.o obj-y += mm.o obj-y += seg_fixup.o obj-y += traps.o Index: 2006-09-11/xen/arch/x86/x86_32/io.S =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ 2006-09-11/xen/arch/x86/x86_32/io.S 2006-09-18 14:32:37.000000000 +0200 @@ -0,0 +1,42 @@ +/* + * Special (full-context) I/O handling routines. + * + * Copyright (c) 2006, Novell, Inc. + */ + +#include +#include + +ENTRY(save_host_restore_guest) + movl (%esp), %ecx + movl %eax, (%esp) + movl UREGS_edx(%eax), %edx + pushl %ebx + movl UREGS_ebx(%eax), %ebx + pushl %ebp + movl UREGS_ebp(%eax), %ebp + pushl %esi + movl UREGS_esi(%eax), %esi + pushl %edi + movl UREGS_edi(%eax), %edi + pushl %ecx + movl UREGS_ecx(%eax), %ecx + movl UREGS_eax(%eax), %eax + ret + +ENTRY(save_guest_restore_host) + pushl %edx + movl 5*4(%esp), %edx + movl %eax, UREGS_eax(%edx) + popl UREGS_edx(%edx) + movl %edi, UREGS_edi(%edx) + popl %edi + movl %esi, UREGS_esi(%edx) + popl %esi + movl %ebp, UREGS_ebp(%edx) + popl %ebp + movl %ebx, UREGS_ebx(%edx) + popl %ebx + movl %ecx, UREGS_ecx(%edx) + popl %ecx + ret Index: 2006-09-11/xen/arch/x86/x86_32/traps.c =================================================================== --- 2006-09-11.orig/xen/arch/x86/x86_32/traps.c 2006-09-18 13:58:26.000000000 +0200 +++ 2006-09-11/xen/arch/x86/x86_32/traps.c 2006-09-18 15:15:40.000000000 +0200 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -250,6 +251,7 @@ fastcall void smp_deferred_nmi(struct cp void __init percpu_traps_init(void) { struct tss_struct *tss = &doublefault_tss; + char *stack_bottom, *stack; asmlinkage int hypercall(void); if ( smp_processor_id() != 0 ) @@ -283,6 +285,28 @@ void __init percpu_traps_init(void) (unsigned long)tss, 235, 9); set_task_gate(TRAP_double_fault, __DOUBLEFAULT_TSS_ENTRY<<3); + + /* + * Stub for full-context I/O emulation. + */ + stack_bottom = (char *)get_stack_bottom(); + stack = (char *)((unsigned long)stack_bottom & ~(STACK_SIZE - 1)); + if (!io_emul_stub_offset) + io_emul_stub_offset = stack - stack_bottom; + else + BUG_ON(io_emul_stub_offset != stack - stack_bottom); + /* call save_host_restore_guest */ + stack[0] = 0xe8; + *(s32*)&stack[1] = (char *)save_host_restore_guest - &stack[5]; + stack += 5; + if (!io_emul_insn_offset) + io_emul_insn_offset = stack - stack_bottom; + else + BUG_ON(io_emul_insn_offset != stack - stack_bottom); + stack += 3; /* operand size prefix, opcode, immediate */ + /* jmp save_guest_restore_host */ + stack[0] = 0xe9; + *(s32*)&stack[1] = (char *)save_guest_restore_host - &stack[5]; } void init_int80_direct_trap(struct vcpu *v) Index: 2006-09-11/xen/arch/x86/x86_64/Makefile =================================================================== --- 2006-09-11.orig/xen/arch/x86/x86_64/Makefile 2006-09-18 13:58:26.000000000 +0200 +++ 2006-09-11/xen/arch/x86/x86_64/Makefile 2006-09-18 15:15:40.000000000 +0200 @@ -1,3 +1,4 @@ obj-y += entry.o +obj-y += io.o obj-y += mm.o obj-y += traps.o Index: 2006-09-11/xen/arch/x86/x86_64/io.S =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ 2006-09-11/xen/arch/x86/x86_64/io.S 2006-09-18 14:41:26.000000000 +0200 @@ -0,0 +1,62 @@ +/* + * Special (full-context) I/O handling routines. + * + * Copyright (c) 2006, Novell, Inc. + */ + +#include +#include + +ENTRY(save_host_restore_guest) + movq (%rsp), %rcx + movq %rdi, (%rsp) + movq UREGS_rdx(%rdi), %rdx + pushq %rbx + movq UREGS_rax(%rdi), %rax + movq UREGS_rbx(%rdi), %rbx + pushq %rbp + movq UREGS_rsi(%rdi), %rsi + movq UREGS_rbp(%rdi), %rbp + pushq %r12 + movq UREGS_r8(%rdi), %r8 + movq UREGS_r12(%rdi), %r12 + pushq %r13 + movq UREGS_r9(%rdi), %r9 + movq UREGS_r13(%rdi), %r13 + pushq %r14 + movq UREGS_r10(%rdi), %r10 + movq UREGS_r14(%rdi), %r14 + pushq %r15 + movq UREGS_r11(%rdi), %r11 + movq UREGS_r15(%rdi), %r15 + pushq %rcx + movq UREGS_rcx(%rdi), %rcx + movq UREGS_rdi(%rdi), %rdi + ret + +ENTRY(save_guest_restore_host) + pushq %rdi + movq 7*8(%rsp), %rdi + movq %rax, UREGS_rax(%rdi) + popq UREGS_rdi(%rdi) + movq %r15, UREGS_r15(%rdi) + movq %r11, UREGS_r11(%rdi) + popq %r15 + movq %r14, UREGS_r14(%rdi) + movq %r10, UREGS_r10(%rdi) + popq %r14 + movq %r13, UREGS_r13(%rdi) + movq %r9, UREGS_r9(%rdi) + popq %r13 + movq %r12, UREGS_r12(%rdi) + movq %r8, UREGS_r8(%rdi) + popq %r12 + movq %rbp, UREGS_rbp(%rdi) + movq %rsi, UREGS_rsi(%rdi) + popq %rbp + movq %rbx, UREGS_rbx(%rdi) + movq %rdx, UREGS_rdx(%rdi) + popq %rbx + movq %rcx, UREGS_rcx(%rdi) + popq %rcx + ret Index: 2006-09-11/xen/arch/x86/x86_64/traps.c =================================================================== --- 2006-09-11.orig/xen/arch/x86/x86_64/traps.c 2006-09-18 13:58:26.000000000 +0200 +++ 2006-09-11/xen/arch/x86/x86_64/traps.c 2006-09-18 15:15:41.000000000 +0200 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -331,6 +332,29 @@ void __init percpu_traps_init(void) wrmsr(MSR_STAR, 0, (FLAT_RING3_CS32<<16) | __HYPERVISOR_CS); wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U); + + /* + * Stub for full-context I/O emulation. + */ + + /* Skip the compatibility-mode entry trampoline. */ + stack += 26; + if (!io_emul_stub_offset) + io_emul_stub_offset = stack - stack_bottom; + else + BUG_ON(io_emul_stub_offset != stack - stack_bottom); + /* call save_host_restore_guest */ + stack[0] = 0xe8; + *(s32*)&stack[1] = (char *)save_host_restore_guest - &stack[5]; + stack += 5; + if (!io_emul_insn_offset) + io_emul_insn_offset = stack - stack_bottom; + else + BUG_ON(io_emul_insn_offset != stack - stack_bottom); + stack += 3; /* operand size prefix, opcode, immediate */ + /* jmp save_guest_restore_host */ + stack[0] = 0xe9; + *(s32*)&stack[1] = (char *)save_guest_restore_host - &stack[5]; } static long register_guest_callback(struct callback_register *reg) Index: 2006-09-11/xen/include/asm-x86/io.h =================================================================== --- 2006-09-11.orig/xen/include/asm-x86/io.h 2006-09-18 13:58:26.000000000 +0200 +++ 2006-09-11/xen/include/asm-x86/io.h 2006-09-18 15:11:38.000000000 +0200 @@ -50,4 +50,10 @@ __OUT(b,"b",char) __OUT(w,"w",short) __OUT(l,,int) +struct cpu_user_regs; +void save_host_restore_guest(struct cpu_user_regs *) __attribute__((__regparm__(1))); +unsigned long save_guest_restore_host(unsigned long) __attribute__((__regparm__(1))); + +extern long io_emul_stub_offset, io_emul_insn_offset; + #endif Index: 2006-09-11/xen/include/asm-x86/iocap.h =================================================================== --- 2006-09-11.orig/xen/include/asm-x86/iocap.h 2006-09-18 13:58:26.000000000 +0200 +++ 2006-09-11/xen/include/asm-x86/iocap.h 2006-09-18 13:58:56.000000000 +0200 @@ -7,6 +7,15 @@ #ifndef __X86_IOCAP_H__ #define __X86_IOCAP_H__ +extern struct rangeset *ioport_caps, *ioport_emul; + +#define ioports_permit_access_all(s, e) \ + rangeset_add_range(ioport_caps, s, e) +#define ioports_deny_access_all(s, e) \ + rangeset_remove_range(ioport_caps, s, e) +#define ioports_any_access_permitted(s, e) \ + rangeset_contains_range(ioport_caps, s, e) + #define ioports_permit_access(d, s, e) \ rangeset_add_range((d)->arch.ioport_caps, s, e) #define ioports_deny_access(d, s, e) \ @@ -14,6 +23,13 @@ #define ioports_access_permitted(d, s, e) \ rangeset_contains_range((d)->arch.ioport_caps, s, e) +#define ioports_set_emul(s, e) \ + rangeset_add_range(ioport_emul, s, e) +#define ioports_set_noemul(s, e) \ + rangeset_remove_range(ioport_emul, s, e) +#define ioports_emul(s, e) \ + rangeset_contains_range(ioport_emul, s, e) + #define cache_flush_permitted(d) \ (!rangeset_is_empty((d)->iomem_caps)) Index: 2006-09-11/xen/include/public/sysctl.h =================================================================== --- 2006-09-11.orig/xen/include/public/sysctl.h 2006-09-18 13:58:26.000000000 +0200 +++ 2006-09-11/xen/include/public/sysctl.h 2006-09-18 13:58:56.000000000 +0200 @@ -122,6 +122,15 @@ struct xen_sysctl_getdomaininfolist { typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t; DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t); +#define XEN_SYSCTL_ioport_emulation 7 +struct xen_sysctl_ioport_emulation { + uint32_t first_port; /* first port int range */ + uint32_t nr_ports; /* size of port range */ + uint8_t emulate; /* emulate access to range? */ +}; +typedef struct xen_sysctl_ioport_emulation xen_sysctl_ioport_emulation_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_ioport_emulation_t); + struct xen_sysctl { uint32_t cmd; uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */ @@ -132,6 +141,7 @@ struct xen_sysctl { struct xen_sysctl_sched_id sched_id; struct xen_sysctl_perfc_op perfc_op; struct xen_sysctl_getdomaininfolist getdomaininfolist; + struct xen_sysctl_ioport_emulation ioport_emulation; uint8_t pad[128]; } u; };