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-11 13:50:54.000000000 +0200 +++ 2006-09-11/xen/arch/x86/domain_build.c 2006-09-13 11:05:06.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-08-28 08:32:37.000000000 +0200 +++ 2006-09-11/xen/arch/x86/sysctl.c 2006-09-13 09:47:23.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-11 13:50:54.000000000 +0200 +++ 2006-09-11/xen/arch/x86/traps.c 2006-09-13 11:05:07.000000000 +0200 @@ -1002,16 +1002,76 @@ static inline int admin_io_okay( return ioports_access_permitted(v->domain, port, port + bytes - 1); } +/* 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. */ -#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 char inb_user( + unsigned int port, int string, + struct vcpu *v, struct cpu_user_regs *regs) +{ + if ( admin_io_okay(port, 1, v, regs) ) + return string || normal_io_okay(port, 1) + ? inb(port) + : inb_special(port, regs); + return ~0; +} + +static inline unsigned short inw_user( + unsigned int port, int string, + struct vcpu *v, struct cpu_user_regs *regs) +{ + if ( admin_io_okay(port, 2, v, regs) ) + return string || normal_io_okay(port, 2) + ? inw(port) + : inw_special(port, regs); + return ~0; +} + +static inline unsigned int inl_user( + unsigned int port, int string, + struct vcpu *v, struct cpu_user_regs *regs) +{ + if ( admin_io_okay(port, 4, v, regs) ) + return string || normal_io_okay(port, 4) + ? inl(port) + : inl_special(port, regs); + return ~0; +} + +static inline void outb_user( + unsigned char value, unsigned int port, int string, + struct vcpu *v, struct cpu_user_regs *regs) +{ + if ( admin_io_okay(port, 1, v, regs) ) + string || normal_io_okay(port, 1) + ? outb(value, port) + : outb_special(value, port, regs); +} + +static inline void outw_user( + unsigned short value, unsigned int port, int string, + struct vcpu *v, struct cpu_user_regs *regs) +{ + if ( admin_io_okay(port, 2, v, regs) ) + string || normal_io_okay(port, 2) + ? outw(value, port) + : outw_special(value, port, regs); +} + +static inline void outl_user( + unsigned int value, unsigned int port, int string, + struct vcpu *v, struct cpu_user_regs *regs) +{ + if ( admin_io_okay(port, 4, v, regs) ) + string || normal_io_okay(port, 4) + ? outl(value, port) + : outl_special(value, port, regs); +} /* Instruction fetch with error handling. */ #define insn_fetch(_type, _size, _ptr) \ @@ -1087,13 +1140,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, 1, v, regs); break; case 2: - data = (u16)inw_user((u16)regs->edx, v, regs); + data = (u16)inw_user((u16)regs->edx, 1, v, regs); break; case 4: - data = (u32)inl_user((u16)regs->edx, v, regs); + data = (u32)inl_user((u16)regs->edx, 1, v, regs); break; } if ( (rc = copy_to_user((void *)regs->edi, &data, op_bytes)) != 0 ) @@ -1119,13 +1172,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, 1, v, regs); break; case 2: - outw_user((u16)data, (u16)regs->edx, v, regs); + outw_user((u16)data, (u16)regs->edx, 1, v, regs); break; case 4: - outl_user((u32)data, (u16)regs->edx, v, regs); + outl_user((u32)data, (u16)regs->edx, 1, v, regs); break; } regs->esi += (int)((regs->eflags & EF_DF) ? -op_bytes : op_bytes); @@ -1156,14 +1209,14 @@ static int emulate_privileged_op(struct { case 1: regs->eax &= ~0xffUL; - regs->eax |= (u8)inb_user(port, v, regs); + regs->eax |= (u8)inb_user(port, 0, v, regs); break; case 2: regs->eax &= ~0xffffUL; - regs->eax |= (u16)inw_user(port, v, regs); + regs->eax |= (u16)inw_user(port, 0, v, regs); break; case 4: - regs->eax = (u32)inl_user(port, v, regs); + regs->eax = (u32)inl_user(port, 0, v, regs); break; } goto done; @@ -1184,13 +1237,13 @@ static int emulate_privileged_op(struct switch ( op_bytes ) { case 1: - outb_user((u8)regs->eax, port, v, regs); + outb_user((u8)regs->eax, port, 0, v, regs); break; case 2: - outw_user((u16)regs->eax, port, v, regs); + outw_user((u16)regs->eax, port, 0, v, regs); break; case 4: - outl_user((u32)regs->eax, port, v, regs); + outl_user((u32)regs->eax, port, 0, v, regs); break; } goto done; Index: 2006-09-11/xen/arch/x86/x86_32/Makefile =================================================================== --- 2006-09-11.orig/xen/arch/x86/x86_32/Makefile 2006-09-11 13:50:54.000000000 +0200 +++ 2006-09-11/xen/arch/x86/x86_32/Makefile 2006-09-11 13:52:31.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-13 11:04:05.000000000 +0200 @@ -0,0 +1,155 @@ +/* + * Special (full-context) I/O handling routines. + * + * Copyright (c) 2006, Novell, Inc. + */ + +#include +#include + +#define PROTECTED_PORT 0x20 // must be some port no domain will ever be granted access + + .macro in_special w, a +ENTRY(in\w\(_special)) + movl 2*4(%esp), %ecx + pushl %ebx + movl UREGS_ebx(%ecx), %ebx + movl UREGS_edx(%ecx), %edx + pushl %ebp + movl UREGS_ebp(%ecx), %ebp + movl UREGS_eax(%ecx), %eax + pushl %esi + movl UREGS_esi(%ecx), %esi + movw 4*4(%esp), %dx + pushl %edi + testb %dh, %dh + movl UREGS_edi(%ecx), %edi + jz .Ltry_lock_in\w + movl UREGS_ecx(%ecx), %ecx + in\w %dx, %\a + .ifndef .Lin_restore +.Lin_restore: + movl %ecx, 5*4(%esp) + movl 6*4(%esp), %ecx + movl %edx, UREGS_edx(%ecx) + movl 5*4(%esp), %edx + movl %edi, UREGS_edi(%ecx) + popl %edi + movl %esi, UREGS_esi(%ecx) + popl %esi + movl %ebp, UREGS_ebp(%ecx) + popl %ebp + movl %ebx, UREGS_ebx(%ecx) + popl %ebx + movl %eax, UREGS_eax(%ecx) + movl %edx, UREGS_ecx(%ecx) + ret + .else + jmp .Lin_restore + .endif +.Ltry_lock_in\w: +#ifdef CONFIG_SMP + movb $PROTECTED_PORT, %al + lock cmpxchgb %dl, .Lport_in\w + jne .Lretry_in\w + movl UREGS_eax(%ecx), %eax +#else + movb %dl, .Lport_in\w +#endif + movl UREGS_edx(%ecx), %edx + movl UREGS_ecx(%ecx), %ecx + jmp .Limm_in\w + .data # .section .wtext, "axw" +.Limm_in\w: + in\w $PROTECTED_PORT, %\a + .equiv .Lport_in\w, . - 1 +#ifdef CONFIG_SMP + movb $PROTECTED_PORT, .Lport_in\w +#endif + jmp .Lin_restore + .previous +#ifdef CONFIG_SMP +.Lretry_in\w: + pause + jmp .Ltry_lock_in\w +#endif + .endm + + in_special b, al + in_special w, ax + in_special l, eax + + .macro out_special w, a +ENTRY(out\w\(_special)) + movl 3*4(%esp), %ecx + pushl %ebx + movl UREGS_ebx(%ecx), %ebx + movl UREGS_edx(%ecx), %edx + pushl %ebp + movl UREGS_ebp(%ecx), %ebp + .ifnes "\w", "l" + movl UREGS_eax(%ecx), %eax + .endif + pushl %esi + movl UREGS_esi(%ecx), %esi + movw 5*4(%esp), %dx + pushl %edi + testb %dh, %dh + movl UREGS_edi(%ecx), %edi + mov\w 5*4(%esp), %\a + jz .Llock_out\w + movl UREGS_ecx(%ecx), %ecx + out\w %\a, %dx + .ifndef .Lout_restore +.Lout_restore: + movl %ecx, 5*4(%esp) + movl 7*4(%esp), %ecx + movl %edx, UREGS_edx(%ecx) + movl 5*4(%esp), %edx + movl %edi, UREGS_edi(%ecx) + popl %edi + movl %esi, UREGS_esi(%ecx) + popl %esi + movl %ebp, UREGS_ebp(%ecx) + popl %ebp + movl %ebx, UREGS_ebx(%ecx) + popl %ebx + movl %eax, UREGS_eax(%ecx) + movl %edx, UREGS_ecx(%ecx) + ret + .else + jmp .Lout_restore + .endif +.Llock_out\w: +#ifdef CONFIG_SMP + pushl %eax +.Ltry_lock_out\w: + movb $PROTECTED_PORT, %al + lock cmpxchgb %dl, .Lport_out\w + jne .Lretry_out\w + popl %eax +#else + movb %dl, .Lport_out\w +#endif + movl UREGS_edx(%ecx), %edx + movl UREGS_ecx(%ecx), %ecx + jmp .Limm_out\w + .data # .section .wtext, "axw" +.Limm_out\w: + out\w %\a, $PROTECTED_PORT + .equiv .Lport_out\w, . - 1 +#ifdef CONFIG_SMP + movb $PROTECTED_PORT, .Lport_out\w +#endif + jmp .Lout_restore + .previous +#ifdef CONFIG_SMP +.Lretry_out\w: + pause + jmp .Ltry_lock_out\w +#endif + .endm + + out_special b, al + out_special w, ax + out_special l, eax Index: 2006-09-11/xen/arch/x86/x86_64/Makefile =================================================================== --- 2006-09-11.orig/xen/arch/x86/x86_64/Makefile 2006-09-11 13:50:54.000000000 +0200 +++ 2006-09-11/xen/arch/x86/x86_64/Makefile 2006-09-13 11:05:05.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-13 11:04:38.000000000 +0200 @@ -0,0 +1,202 @@ +/* + * Special (full-context) I/O handling routines. + * + * Copyright (c) 2006, Novell, Inc. + */ + +#include +#include + +#define PROTECTED_PORT 0x20 // must be some port no domain will ever be granted access + + .macro in_special w, a +ENTRY(in\w\(_special)) + pushq %rbx + movq UREGS_rbx(%rsi), %rbx + movq UREGS_rdx(%rsi), %rdx + pushq %rbp + movq UREGS_rbp(%rsi), %rbp + movq UREGS_rax(%rsi), %rax + pushq %r12 + movq UREGS_r12(%rsi), %r12 + movq UREGS_r8(%rsi), %r8 + pushq %r13 + movq UREGS_r13(%rsi), %r13 + movq UREGS_r9(%rsi), %r9 + pushq %r14 + movq UREGS_r14(%rsi), %r14 + movq UREGS_r10(%rsi), %r10 + movw %di, %dx + pushq %r15 + movq UREGS_r15(%rsi), %r15 + movq UREGS_r11(%rsi), %r11 + testb %dh, %dh + movq UREGS_rcx(%rsi), %rcx + movq UREGS_rdi(%rsi), %rdi + pushq %rsi + jz .Ltry_lock_in\w + movq UREGS_rsi(%rsi), %rsi + in\w %dx, %\a + .ifndef .Lin_restore +.Lin_restore: + pushq %rsi + movq 8(%rsp), %rsi + movq %rdx, UREGS_rdx(%rsi) + popq UREGS_rsi(%rsi) + movq %rdi, UREGS_rdi(%rsi) + movq %rcx, UREGS_rcx(%rsi) + popq %rdx + movq %r11, UREGS_r11(%rsi) + movq %r15, UREGS_r15(%rsi) + popq %r15 + movq %r10, UREGS_r10(%rsi) + movq %r14, UREGS_r14(%rsi) + popq %r14 + movq %r9, UREGS_r9(%rsi) + movq %r13, UREGS_r13(%rsi) + popq %r13 + movq %r8, UREGS_r8(%rsi) + movq %r12, UREGS_r12(%rsi) + popq %r12 + movq %rbp, UREGS_rbp(%rsi) + popq %rbp + movq %rbx, UREGS_rbx(%rsi) + popq %rbx + movq %rax, UREGS_rax(%rsi) + ret + .else + jmp .Lin_restore + .endif +.Ltry_lock_in\w: +#ifdef CONFIG_SMP + movb $PROTECTED_PORT, %al + lock cmpxchgb %dl, .Lport_in\w(%rip) + jne .Lretry_in\w + movb UREGS_rax(%rsi), %al +#else + movb %dl, .Lport_in\w(%rip) +#endif + movq UREGS_rdx(%rsi), %rdx + movq UREGS_rsi(%rsi), %rsi + jmp .Limm_in\w + .data # .section .wtext, "axw" +.Limm_in\w: + in\w $PROTECTED_PORT, %\a + .equiv .Lport_in\w, . - 1 +#ifdef CONFIG_SMP + movb $PROTECTED_PORT, .Lport_in\w(%rip) +#endif + jmp .Lin_restore + .previous +#ifdef CONFIG_SMP +.Lretry_in\w: + pause + jmp .Ltry_lock_in\w +#endif + .endm + + in_special b, al + in_special w, ax + in_special l, eax + + .macro out_special w, a, v +ENTRY(out\w\(_special)) + movq %rdx, %rcx + pushq %rbx + movq UREGS_rbx(%rdx), %rbx + movq UREGS_rdx(%rdx), %rdx + pushq %rbp + movq UREGS_rbp(%rcx), %rbp + movq UREGS_rax(%rcx), %rax + pushq %r12 + movq UREGS_r12(%rcx), %r12 + movq UREGS_r8(%rcx), %r8 + pushq %r13 + movq UREGS_r13(%rcx), %r13 + movq UREGS_r9(%rcx), %r9 + pushq %r14 + movq UREGS_r14(%rcx), %r14 + movq UREGS_r10(%rcx), %r10 + movw %si, %dx + pushq %r15 + movq UREGS_r15(%rcx), %r15 + movq UREGS_r11(%rcx), %r11 + .ifnes "\w", "l" + mov\w %\v, %\a + .else + .ifnes "\v", "edi" + .err + .endif + shrdq $32, %rdi, %rax + rolq $32, %rax + .endif + testb %dh, %dh + movq UREGS_rsi(%rcx), %rsi + movq UREGS_rdi(%rcx), %rdi + pushq %rcx + jz .Llock_out\w + movq UREGS_rcx(%rcx), %rcx + out\w %\a, %dx + .ifndef .Lout_restore +.Lout_restore: + pushq %rcx + movq 8(%rsp), %rcx + movq %rdx, UREGS_rdx(%rcx) + popq UREGS_rcx(%rcx) + movq %rdi, UREGS_rdi(%rcx) + movq %rsi, UREGS_rsi(%rcx) + popq %rdx + movq %r11, UREGS_r11(%rcx) + movq %r15, UREGS_r15(%rcx) + popq %r15 + movq %r10, UREGS_r10(%rcx) + movq %r14, UREGS_r14(%rcx) + popq %r14 + movq %r9, UREGS_r9(%rcx) + movq %r13, UREGS_r13(%rcx) + popq %r13 + movq %r8, UREGS_r8(%rcx) + movq %r12, UREGS_r12(%rcx) + popq %r12 + movq %rbp, UREGS_rbp(%rcx) + popq %rbp + movq %rbx, UREGS_rbx(%rcx) + popq %rbx + movq %rax, UREGS_rax(%rcx) + ret + .else + jmp .Lout_restore + .endif +.Llock_out\w: +#ifdef CONFIG_SMP + pushq %rax +.Ltry_lock_out\w: + movb $PROTECTED_PORT, %al + lock cmpxchgb %dl, .Lport_out\w(%rip) + jne .Lretry_out\w + popq %rax +#else + movb %dl, .Lport_out\w(%rip) +#endif + movq UREGS_rdx(%rcx), %rdx + movq UREGS_rcx(%rcx), %rcx + jmp .Limm_out\w + .data # .section .wtext, "axw" +.Limm_out\w: + out\w %\a, $PROTECTED_PORT + .equiv .Lport_out\w, . - 1 +#ifdef CONFIG_SMP + movb $PROTECTED_PORT, .Lport_out\w(%rip) +#endif + jmp .Lout_restore + .previous +#ifdef CONFIG_SMP +.Lretry_out\w: + pause + jmp .Ltry_lock_out\w +#endif + .endm + + out_special b, al, dil + out_special w, ax, di + out_special l, eax, edi Index: 2006-09-11/xen/include/asm-x86/io.h =================================================================== --- 2006-09-11.orig/xen/include/asm-x86/io.h 2006-09-11 13:50:54.000000000 +0200 +++ 2006-09-11/xen/include/asm-x86/io.h 2006-09-11 13:52:31.000000000 +0200 @@ -5,6 +5,8 @@ #include #include +struct cpu_user_regs; + /* We don't need real ioremap() on Xen/x86. */ #define ioremap(x,l) (__va(x)) #define iounmap(p) ((void)0) @@ -19,32 +21,34 @@ #define __OUT1(s,x) \ static inline void out##s(unsigned x value, unsigned short port) { -#define __OUT2(s,s1,s2) \ -__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" +#define __OUT2(s,s1) \ + __asm__ __volatile__ ("out" #s " %" s1 "0,%w1" : : "a" (value), "Nd" (port)); \ +} #define __OUT(s,s1,x) \ -__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \ -__OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port));} - -#define __IN1(s) \ -static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v; - -#define __IN2(s,s1,s2) \ -__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" - -#define __IN(s,s1,i...) \ -__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \ -__IN1(s##_p) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } - -#define RETURN_TYPE unsigned char -__IN(b,"") -#undef RETURN_TYPE -#define RETURN_TYPE unsigned short -__IN(w,"") -#undef RETURN_TYPE -#define RETURN_TYPE unsigned int -__IN(l,"") -#undef RETURN_TYPE +extern void out##s##_special(unsigned x value, unsigned short port, \ + struct cpu_user_regs *); \ +__OUT1(s,x) __OUT2(s,s1) \ +__OUT1(s##_p,x) __OUT2(s,s1) + +#define __IN1(s,x) \ +static inline unsigned x in##s(unsigned short port) { \ + unsigned x value; + +#define __IN2(s,s1) \ + __asm__ __volatile__ ("in" #s " %w1,%" s1 "0" : "=a" (value) : "Nd" (port)); \ + return value; \ +} + +#define __IN(s,s1,x) \ +extern unsigned x in##s##_special(unsigned short port, \ + struct cpu_user_regs *); \ +__IN1(s,x) __IN2(s,s1) \ +__IN1(s##_p,x) __IN2(s,s1) + +__IN(b,"b",char) +__IN(w,"w",short) +__IN(l,,int) __OUT(b,"b",char) __OUT(w,"w",short) Index: 2006-09-11/xen/include/asm-x86/iocap.h =================================================================== --- 2006-09-11.orig/xen/include/asm-x86/iocap.h 2006-09-11 13:50:54.000000000 +0200 +++ 2006-09-11/xen/include/asm-x86/iocap.h 2006-09-13 09:47:46.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-11 09:06:11.000000000 +0200 +++ 2006-09-11/xen/include/public/sysctl.h 2006-09-13 09:45:47.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; };