From: "Jan Beulich" <jbeulich@novell.com>
To: xen-devel@lists.xensource.com
Subject: [PATCH] enable port accesses with (almost) full register context
Date: Mon, 11 Sep 2006 17:12:28 +0100 [thread overview]
Message-ID: <4505A70C.76E4.0078.0@novell.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 243 bytes --]
This helped HP getting certain system management software going (in
dom0) that triggers SMIs and depends upon other than port number
and data register values being visible to the SMI handler.
Signed-off-by: Jan Beulich <jbeulich@novell.com>
[-- Attachment #2: xen-x86-io-register-context.patch --]
[-- Type: text/plain, Size: 26518 bytes --]
From: Jan Beulich
Bugzilla #192150
Index: 2006-09-11/xen/arch/x86/domain.c
===================================================================
--- 2006-09-11.orig/xen/arch/x86/domain.c 2006-09-11 13:39:58.000000000 +0200
+++ 2006-09-11/xen/arch/x86/domain.c 2006-09-11 13:42:13.000000000 +0200
@@ -210,10 +210,17 @@ int arch_domain_create(struct domain *d)
if ( !is_idle_domain(d) )
{
d->arch.ioport_caps =
- rangeset_new(d, "I/O Ports", RANGESETF_prettyprint_hex);
+ rangeset_new(d, "I/O Ports access control", RANGESETF_prettyprint_hex);
if ( d->arch.ioport_caps == NULL )
goto fail_nomem;
+ d->arch.ioport_normal =
+ rangeset_new(d, "I/O Ports access mechanism", RANGESETF_prettyprint_hex);
+ if ( d->arch.ioport_normal == NULL )
+ goto fail_nomem;
+ if (ioports_set_normal(d, 0, 0xFFFF))
+ goto fail_nomem;
+
if ( (d->shared_info = alloc_xenheap_page()) == NULL )
goto fail_nomem;
Index: 2006-09-11/xen/arch/x86/domain_build.c
===================================================================
--- 2006-09-11.orig/xen/arch/x86/domain_build.c 2006-09-11 13:39:58.000000000 +0200
+++ 2006-09-11/xen/arch/x86/domain_build.c 2006-09-11 13:42:13.000000000 +0200
@@ -33,6 +33,8 @@
extern unsigned long initial_images_nrpages(void);
extern void discard_initial_images(void);
+struct rangeset *global_ioport_caps = NULL;
+
static long dom0_nrpages;
/*
@@ -64,9 +66,15 @@ integer_param("dom0_max_vcpus", opt_dom0
static unsigned int opt_dom0_shadow;
boolean_param("dom0_shadow", opt_dom0_shadow);
+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);
+static char opt_dom0_ioports_special[200] = "";
+string_param("dom0_ioports_special", opt_dom0_ioports_special);
+
#if defined(__i386__)
/* No ring-3 access in initial leaf page tables. */
#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
@@ -102,10 +110,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 +125,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_ioports_disable ? "dom0_" : "",
+ opt != opt_dom0_ioports_special ? "disable" : "special");
continue;
}
@@ -131,11 +141,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_dom0_ioports_special )
+ {
+ 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 special dom0 access for ioport range %04lx-%04lx\n",
+ io_from, io_to);
+
+ if ( ioports_set_special(dom0, io_from, io_to) != 0 )
+ BUG();
+ }
}
}
@@ -815,6 +840,13 @@ int construct_dom0(struct domain *d,
rc = 0;
+ /* Command-line I/O ranges. */
+ global_ioport_caps = rangeset_new(NULL,
+ "global I/O Port access control",
+ RANGESETF_prettyprint_hex);
+ BUG_ON(!global_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 +856,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.
@@ -853,6 +890,9 @@ int construct_dom0(struct domain *d,
BUG_ON(rc != 0);
+ /* Command-line I/O ranges that require special (full-context) access. */
+ process_ioports(opt_dom0_ioports_special);
+
return 0;
}
Index: 2006-09-11/xen/arch/x86/domctl.c
===================================================================
--- 2006-09-11.orig/xen/arch/x86/domctl.c 2006-08-29 10:46:45.000000000 +0200
+++ 2006-09-11/xen/arch/x86/domctl.c 2006-09-11 13:47:21.000000000 +0200
@@ -62,10 +62,27 @@ long arch_do_domctl(
if ( np == 0 )
ret = 0;
- else if ( domctl->u.ioport_permission.allow_access )
- ret = ioports_permit_access(d, fp, fp + np - 1);
- else
+ else switch ( domctl->u.ioport_permission.allow_access )
+ {
+ case IOPORT_ALLOW_ACCESS:
+ if ( ioports_any_access_permitted(fp, fp + np - 1) )
+ ret = ioports_permit_access(d, fp, fp + np - 1);
+ else
+ ret = -EPERM;
+ break;
+ case IOPORT_DENY_ACCESS:
ret = ioports_deny_access(d, fp, fp + np - 1);
+ break;
+ case IOPORT_SET_NORMAL:
+ ret = ioports_set_normal(d, fp, fp + np - 1);
+ break;
+ case IOPORT_SET_SPECIAL:
+ ret = ioports_set_special(d, fp, fp + np - 1);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
put_domain(d);
}
Index: 2006-09-11/xen/arch/x86/traps.c
===================================================================
--- 2006-09-11.orig/xen/arch/x86/traps.c 2006-09-11 13:42:08.000000000 +0200
+++ 2006-09-11/xen/arch/x86/traps.c 2006-09-11 13:44:18.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, struct vcpu *v)
+{
+ return ioports_normal_access(v->domain, 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, v)
+ ? 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, v)
+ ? 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, v)
+ ? 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, v)
+ ? 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, v)
+ ? 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, v)
+ ? 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:39:58.000000000 +0200
+++ 2006-09-11/xen/arch/x86/x86_32/Makefile 2006-09-11 13:42:13.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-11 13:42:13.000000000 +0200
@@ -0,0 +1,163 @@
+/*
+ * Special (full-context) I/O handling routines.
+ *
+ * Copyright (c) 2006, Novell, Inc.
+ */
+
+#include <xen/config.h>
+#include <asm/asm_defns.h>
+
+#define PROTECTED_PORT 0x20 // must be some port no domain will ever be granted access
+
+ .macro in_special w, a
+ 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
+
+ENTRY(inb_special)
+ in_special b, al
+
+ENTRY(inw_special)
+ in_special w, ax
+
+ENTRY(inl_special)
+ in_special l, eax
+
+ .macro out_special w, a
+ 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
+
+ENTRY(outb_special)
+ out_special b, al
+
+ENTRY(outw_special)
+ out_special w, ax
+
+ENTRY(outl_special)
+ 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:39:58.000000000 +0200
+++ 2006-09-11/xen/arch/x86/x86_64/Makefile 2006-09-11 13:42:13.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-11 13:42:13.000000000 +0200
@@ -0,0 +1,210 @@
+/*
+ * Special (full-context) I/O handling routines.
+ *
+ * Copyright (c) 2006, Novell, Inc.
+ */
+
+#include <xen/config.h>
+#include <asm/asm_defns.h>
+
+#define PROTECTED_PORT 0x20 // must be some port no domain will ever be granted access
+
+ .macro in_special w, a
+ 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
+
+ENTRY(inb_special)
+ in_special b, al
+
+ENTRY(inw_special)
+ in_special w, ax
+
+ENTRY(inl_special)
+ in_special l, eax
+
+ .macro out_special w, a, v
+ 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
+
+ENTRY(outb_special)
+ out_special b, al, dil
+
+ENTRY(outw_special)
+ out_special w, ax, di
+
+ENTRY(outl_special)
+ out_special l, eax, edi
Index: 2006-09-11/xen/include/asm-x86/domain.h
===================================================================
--- 2006-09-11.orig/xen/include/asm-x86/domain.h 2006-09-11 13:39:58.000000000 +0200
+++ 2006-09-11/xen/include/asm-x86/domain.h 2006-09-11 13:50:27.000000000 +0200
@@ -101,6 +101,9 @@ struct arch_domain
/* I/O-port admin-specified access capabilities. */
struct rangeset *ioport_caps;
+ /* I/O-port admin-specified non-special access requirements. */
+ struct rangeset *ioport_normal;
+
/* HVM stuff */
struct hvm_domain hvm_domain;
Index: 2006-09-11/xen/include/asm-x86/io.h
===================================================================
--- 2006-09-11.orig/xen/include/asm-x86/io.h 2006-09-11 13:39:58.000000000 +0200
+++ 2006-09-11/xen/include/asm-x86/io.h 2006-09-11 13:42:13.000000000 +0200
@@ -5,6 +5,8 @@
#include <xen/types.h>
#include <asm/page.h>
+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:39:58.000000000 +0200
+++ 2006-09-11/xen/include/asm-x86/iocap.h 2006-09-11 13:42:13.000000000 +0200
@@ -7,6 +7,15 @@
#ifndef __X86_IOCAP_H__
#define __X86_IOCAP_H__
+extern struct rangeset *global_ioport_caps;
+
+#define ioports_permit_access_all(s, e) \
+ rangeset_add_range(global_ioport_caps, s, e)
+#define ioports_deny_access_all(s, e) \
+ rangeset_remove_range(global_ioport_caps, s, e)
+#define ioports_any_access_permitted(s, e) \
+ rangeset_contains_range(global_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_normal(d, s, e) \
+ rangeset_add_range((d)->arch.ioport_normal, s, e)
+#define ioports_set_special(d, s, e) \
+ rangeset_remove_range((d)->arch.ioport_normal, s, e)
+#define ioports_normal_access(d, s, e) \
+ rangeset_contains_range((d)->arch.ioport_normal, s, e)
+
#define cache_flush_permitted(d) \
(!rangeset_is_empty((d)->iomem_caps))
Index: 2006-09-11/xen/include/public/domctl.h
===================================================================
--- 2006-09-11.orig/xen/include/public/domctl.h 2006-09-11 09:06:11.000000000 +0200
+++ 2006-09-11/xen/include/public/domctl.h 2006-09-11 13:49:41.000000000 +0200
@@ -310,6 +310,10 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_iomem
#define XEN_DOMCTL_ioport_permission 21
+#define IOPORT_DENY_ACCESS 0
+#define IOPORT_ALLOW_ACCESS 1
+#define IOPORT_SET_NORMAL 2
+#define IOPORT_SET_SPECIAL 3
struct xen_domctl_ioport_permission {
uint32_t first_port; /* first port int range */
uint32_t nr_ports; /* size of port range */
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
next reply other threads:[~2006-09-11 16:12 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-09-11 16:12 Jan Beulich [this message]
2006-09-11 16:19 ` [PATCH] enable port accesses with (almost) full register context Keir Fraser
2006-09-12 7:15 ` Jan Beulich
2006-09-12 7:53 ` Keir Fraser
2006-09-12 9:03 ` Jan Beulich
2006-09-12 9:50 ` Keir Fraser
2006-09-12 10:32 ` Jan Beulich
2006-09-12 11:28 ` Keir Fraser
2006-09-13 9:46 ` Jan Beulich
2006-09-13 12:10 ` Keir Fraser
2006-09-18 10:40 ` Jan Beulich
2006-09-18 11:05 ` Keir Fraser
2006-09-18 11:36 ` Jan Beulich
2006-09-18 12:22 ` Keir Fraser
2006-09-18 14:10 ` Jan Beulich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4505A70C.76E4.0078.0@novell.com \
--to=jbeulich@novell.com \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.