[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Add feature flag allowing guest kernel to run in domain 0.



# HG changeset patch
# User Ian.Campbell@xxxxxxxxxxxxx
# Node ID 697fac283c9e565b4c9697c70a5529d06a488df9
# Parent  f1c75df46b46cf2b71d949b63f988d8b781302b0
Add feature flag allowing guest kernel to run in domain 0.

To support this we give kernel GDT entries DPL=0 and use kernel
segment selectors with RPL=0. Xen will crunch these to ring 1 when
they are passed in. When a segment selector is used directly or placed
in a stack frame the guest OS is reponsible for crunching the RPL.

Signed-off-by: Ian Campbell <Ian.Campbell@xxxxxxxxxxxxx>

diff -r f1c75df46b46 -r 697fac283c9e 
linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S
--- a/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S  Wed Feb 22 18:40:19 2006
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S  Wed Feb 22 19:11:23 2006
@@ -106,8 +106,8 @@
        .quad 0x0000000000000000        /* 0x53 reserved */
        .quad 0x0000000000000000        /* 0x5b reserved */
 
-       .quad 0x00cfbb000000ffff        /* 0x60 kernel 4GB code at 0x00000000 */
-       .quad 0x00cfb3000000ffff        /* 0x68 kernel 4GB data at 0x00000000 */
+       .quad 0x00cf9b000000ffff        /* 0x60 kernel 4GB code at 0x00000000 */
+       .quad 0x00cf93000000ffff        /* 0x68 kernel 4GB data at 0x00000000 */
        .quad 0x00cffb000000ffff        /* 0x73 user 4GB code at 0x00000000 */
        .quad 0x00cff3000000ffff        /* 0x7b user 4GB data at 0x00000000 */
 
@@ -182,6 +182,7 @@
        .ascii  ",FEATURES=writable_page_tables"
        .ascii           "|writable_descriptor_tables"
        .ascii           "|auto_translated_physmap"
+       .ascii           "|ring0_kernel"
 #ifdef CONFIG_X86_PAE
        .ascii  ",PAE=yes"
 #else
diff -r f1c75df46b46 -r 697fac283c9e 
linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c       Wed Feb 22 
18:40:19 2006
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c       Wed Feb 22 
19:11:23 2006
@@ -272,7 +272,7 @@
        regs.xes = __USER_DS;
        regs.orig_eax = -1;
        regs.eip = (unsigned long) kernel_thread_helper;
-       regs.xcs = __KERNEL_CS;
+       regs.xcs = GET_KERNEL_CS();
        regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
 
        /* Ok, create the new process.. */
diff -r f1c75df46b46 -r 697fac283c9e 
linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c     Wed Feb 22 18:40:19 2006
+++ b/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c     Wed Feb 22 19:11:23 2006
@@ -85,7 +85,7 @@
                return eip + (seg << 4);
        
        /* By far the most common cases. */
-       if (likely(seg == __USER_CS || seg == __KERNEL_CS))
+       if (likely(seg == __USER_CS || seg == GET_KERNEL_CS()))
                return eip;
 
        /* Check the segment exists, is within the current LDT/GDT size,
@@ -396,7 +396,7 @@
        switch (error_code & 3) {
                default:        /* 3: write, present */
 #ifdef TEST_VERIFY_AREA
-                       if (regs->cs == KERNEL_CS)
+                       if (regs->cs == GET_KERNEL_CS())
                                printk("WP fault at %08lx\n", regs->eip);
 #endif
                        /* fall through */
diff -r f1c75df46b46 -r 697fac283c9e 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/segment.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/segment.h      Wed Feb 
22 18:40:19 2006
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/segment.h      Wed Feb 
22 19:11:23 2006
@@ -60,10 +60,12 @@
 #define GDT_ENTRY_KERNEL_BASE  12
 
 #define GDT_ENTRY_KERNEL_CS            (GDT_ENTRY_KERNEL_BASE + 0)
-#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS * 8 + 1)
+#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS * 8)
+#define GET_KERNEL_CS() (__KERNEL_CS | (xen_feature(XENFEAT_ring0_kernel)?0:1) 
)
 
 #define GDT_ENTRY_KERNEL_DS            (GDT_ENTRY_KERNEL_BASE + 1)
-#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS * 8 + 1)
+#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS * 8)
+#define GET_KERNEL_DS() (__KERNEL_DS | (xen_feature(XENFEAT_ring0_kernel)?0:1) 
)
 
 #define GDT_ENTRY_TSS                  (GDT_ENTRY_KERNEL_BASE + 4)
 #define GDT_ENTRY_LDT                  (GDT_ENTRY_KERNEL_BASE + 5)
diff -r f1c75df46b46 -r 697fac283c9e xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Wed Feb 22 18:40:19 2006
+++ b/xen/arch/x86/domain.c     Wed Feb 22 19:11:23 2006
@@ -356,7 +356,8 @@
      */
     if ( !(c->flags & VGCF_HVM_GUEST) )
     {
-        if ( ((c->user_regs.ss & 3) == 0) ||
+        if ( !VALID_STACKSEL(c->user_regs.ss) ||
+             !VALID_STACKSEL(c->kernel_ss) ||
              !VALID_CODESEL(c->user_regs.cs) )
             return -EINVAL;
 
diff -r f1c75df46b46 -r 697fac283c9e xen/arch/x86/x86_32/mm.c
--- a/xen/arch/x86/x86_32/mm.c  Wed Feb 22 18:40:19 2006
+++ b/xen/arch/x86/x86_32/mm.c  Wed Feb 22 19:11:23 2006
@@ -223,7 +223,7 @@
     int nr = smp_processor_id();
     struct tss_struct *t = &init_tss[nr];
 
-    if ( (ss & 3) != 1 )
+    if ( !VALID_STACKSEL(ss) )
         return -EPERM;
 
     current->arch.guest_context.kernel_ss = ss;
@@ -239,6 +239,7 @@
 {
     unsigned long base, limit;
     u32 a = d->a, b = d->b;
+    u16 cs = a>>16;
 
     /* A not-present descriptor will always fault, so is safe. */
     if ( !(b & _SEGMENT_P) ) 
@@ -251,7 +252,7 @@
      * DPL 0 -- this would get the OS ring-0 privileges).
      */
     if ( (b & _SEGMENT_DPL) == 0 )
-        goto bad;
+        d->b = b = b | (0x01<<13); /* Force DPL == 1 */
 
     if ( !(b & _SEGMENT_S) )
     {
@@ -272,8 +273,16 @@
             goto bad;
 
         /* Can't allow far jump to a Xen-private segment. */
-        if ( !VALID_CODESEL(a>>16) )
+        if ( !VALID_CODESEL(cs) )
             goto bad;
+
+        /*
+         * VALID_CODESEL might have fixed up the RPL for us. So be sure to
+         * update the descriptor.
+         *
+         */
+        d->a &= 0x0000ffff;
+        d->a |= cs<<16;
 
         /* Reserved bits must be zero. */
         if ( (b & 0xe0) != 0 )
diff -r f1c75df46b46 -r 697fac283c9e xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c  Wed Feb 22 18:40:19 2006
+++ b/xen/arch/x86/x86_64/mm.c  Wed Feb 22 19:11:23 2006
@@ -292,6 +292,7 @@
 int check_descriptor(struct desc_struct *d)
 {
     u32 a = d->a, b = d->b;
+    u16 cs = a>>16;
 
     /* A not-present descriptor will always fault, so is safe. */
     if ( !(b & _SEGMENT_P) ) 
@@ -314,8 +315,16 @@
         goto bad;
 
     /* Can't allow far jump to a Xen-private segment. */
-    if ( !VALID_CODESEL(a>>16) )
+    if ( !VALID_CODESEL(cs) )
         goto bad;
+
+    /*
+     * VALID_CODESEL might have fixed up the RPL for us. So be sure to
+     * update the descriptor.
+     *
+     */
+    d->a &= 0x0000ffff;
+    d->a |= cs<<16;
 
     /* Reserved bits must be zero. */
     if ( (b & 0xe0) != 0 )
diff -r f1c75df46b46 -r 697fac283c9e xen/include/asm-x86/desc.h
--- a/xen/include/asm-x86/desc.h        Wed Feb 22 18:40:19 2006
+++ b/xen/include/asm-x86/desc.h        Wed Feb 22 19:11:23 2006
@@ -35,7 +35,14 @@
 #define VALID_SEL(_s)                                                      \
     (((((_s)>>3) < FIRST_RESERVED_GDT_ENTRY) || ((_s)&4)) &&               \
      (((_s)&3) == GUEST_KERNEL_RPL))
-#define VALID_CODESEL(_s) ((_s) == FLAT_KERNEL_CS || VALID_SEL(_s))
+#define VALID_CODESEL(_s) ({                                               \
+    if ( ((_s) & 3) == 0 )                                                 \
+        (_s) |= GUEST_KERNEL_RPL;                                          \
+    (_s) == FLAT_KERNEL_CS || VALID_SEL(_s); })
+#define VALID_STACKSEL(_s) ({                                              \
+    if ( ((_s) & 3) == 0 )                                                 \
+        (_s) |= GUEST_KERNEL_RPL;                                          \
+    (_s) == FLAT_KERNEL_SS || VALID_SEL(_s); })
 
 /* These are bitmasks for the high 32 bits of a descriptor table entry. */
 #define _SEGMENT_TYPE    (15<< 8)
diff -r f1c75df46b46 -r 697fac283c9e xen/include/public/version.h
--- a/xen/include/public/version.h      Wed Feb 22 18:40:19 2006
+++ b/xen/include/public/version.h      Wed Feb 22 19:11:23 2006
@@ -51,6 +51,7 @@
 #define XENFEAT_writable_page_tables       0
 #define XENFEAT_writable_descriptor_tables 1
 #define XENFEAT_auto_translated_physmap    2
+#define XENFEAT_ring0_kernel               3
 
 #define XENFEAT_NR_SUBMAPS 1
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.