All of lore.kernel.org
 help / color / mirror / Atom feed
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

             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.