WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] Introduce _DOMF_compat and infrastructure

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Introduce _DOMF_compat and infrastructure as well as several conditionals
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 05 Jan 2007 12:55:16 -0800
Delivery-date: Fri, 05 Jan 2007 12:56:26 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Emmanuel Ackaouy <ack@xxxxxxxxxxxxx>
# Date 1168018320 0
# Node ID 7c5eea5feebd78eb314a87338e8632ce206d6634
# Parent  c75883680f28f9815a683b18402c50c0ab2438b4
Introduce _DOMF_compat and infrastructure as well as several conditionals
dealing with operations that need to distinguish between native and
compatibility mode guests.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---
 config/x86_64.mk                         |    1 
 tools/libxc/xc_linux_build.c             |    2 
 xen/arch/x86/boot/x86_64.S               |   27 +++++-
 xen/arch/x86/domain.c                    |  138 +++++++++++++++++++++++--------
 xen/arch/x86/domain_build.c              |   97 ++++++++++++++++++---
 xen/arch/x86/mm.c                        |    4 
 xen/arch/x86/setup.c                     |    3 
 xen/arch/x86/traps.c                     |   13 ++
 xen/arch/x86/x86_32/mm.c                 |   12 +-
 xen/arch/x86/x86_32/traps.c              |    4 
 xen/arch/x86/x86_64/asm-offsets.c        |    8 +
 xen/arch/x86/x86_64/mm.c                 |   12 +-
 xen/arch/x86/x86_64/traps.c              |    2 
 xen/common/Makefile                      |    1 
 xen/common/elf.c                         |    2 
 xen/common/elf32.c                       |   19 ++++
 xen/include/asm-x86/config.h             |   15 ++-
 xen/include/asm-x86/desc.h               |   90 ++++++++++++++------
 xen/include/asm-x86/ldt.h                |    3 
 xen/include/asm-x86/mm.h                 |    2 
 xen/include/asm-x86/regs.h               |    3 
 xen/include/asm-x86/x86_32/regs.h        |    2 
 xen/include/asm-x86/x86_64/regs.h        |    7 +
 xen/include/public/arch-x86/xen-x86_64.h |    5 -
 xen/include/public/arch-x86/xen.h        |   10 ++
 xen/include/xen/elf.h                    |    9 ++
 xen/include/xen/sched.h                  |   10 ++
 27 files changed, 394 insertions(+), 107 deletions(-)

diff -r c75883680f28 -r 7c5eea5feebd config/x86_64.mk
--- a/config/x86_64.mk  Fri Jan 05 17:24:55 2007 +0000
+++ b/config/x86_64.mk  Fri Jan 05 17:32:00 2007 +0000
@@ -2,6 +2,7 @@ CONFIG_X86_64 := y
 CONFIG_X86_64 := y
 CONFIG_X86_$(XEN_OS) := y
 
+CONFIG_COMPAT := y
 CONFIG_HVM := y
 CONFIG_MIGRATE := y
 CONFIG_XCUTILS := y
diff -r c75883680f28 -r 7c5eea5feebd tools/libxc/xc_linux_build.c
--- a/tools/libxc/xc_linux_build.c      Fri Jan 05 17:24:55 2007 +0000
+++ b/tools/libxc/xc_linux_build.c      Fri Jan 05 17:32:00 2007 +0000
@@ -595,6 +595,7 @@ static int compat_check(int xc_handle, s
         return 0;
     }
 
+#ifndef __x86_64__//temp
     if (strstr(xen_caps, "xen-3.0-x86_32p")) {
         if (dsi->pae_kernel == PAEKERN_bimodal) {
             dsi->pae_kernel = PAEKERN_extended_cr3;
@@ -612,6 +613,7 @@ static int compat_check(int xc_handle, s
             return 0;
         }
     }
+#endif
 
     return 1;
 }
diff -r c75883680f28 -r 7c5eea5feebd xen/arch/x86/boot/x86_64.S
--- a/xen/arch/x86/boot/x86_64.S        Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/arch/x86/boot/x86_64.S        Fri Jan 05 17:32:00 2007 +0000
@@ -224,14 +224,33 @@ high_start:
         .align PAGE_SIZE, 0
 ENTRY(gdt_table)
         .quad 0x0000000000000000     /* unused */
-        .quad 0x00cf9a000000ffff     /* 0xe008 ring 0 code, compatibility */
-        .quad 0x00af9a000000ffff     /* 0xe010 ring 0 code, 64-bit mode   */
-        .quad 0x00cf92000000ffff     /* 0xe018 ring 0 data                */
+        .quad 0x00af9a000000ffff     /* 0xe008 ring 0 code, 64-bit mode   */
+        .quad 0x00cf92000000ffff     /* 0xe010 ring 0 data                */
+        .quad 0x0000000000000000     /* reserved                          */
         .quad 0x00cffa000000ffff     /* 0xe023 ring 3 code, compatibility */
         .quad 0x00cff2000000ffff     /* 0xe02b ring 3 data                */
         .quad 0x00affa000000ffff     /* 0xe033 ring 3 code, 64-bit mode   */
-        .quad 0x0000000000000000     /* unused                            */
+        .quad 0x00cf9a000000ffff     /* 0xe038 ring 0 code, compatibility */
+        .org gdt_table - FIRST_RESERVED_GDT_BYTE + __TSS(0) * 8
         .fill 4*NR_CPUS,8,0          /* space for TSS and LDT per CPU     */
+
+#ifdef CONFIG_COMPAT
+        .align PAGE_SIZE, 0
+/* NB. Even rings != 0 get access to the full 4Gb, as only the            */
+/*     (compatibility) machine->physical mapping table lives there.       */
+ENTRY(compat_gdt_table)
+        .quad 0x0000000000000000     /* unused */
+        .quad 0x00af9a000000ffff     /* 0xe008 ring 0 code, 64-bit mode   */
+        .quad 0x00cf92000000ffff     /* 0xe010 ring 0 data                */
+        .quad 0x00cfba000000ffff     /* 0xe019 ring 1 code, compatibility */
+        .quad 0x00cfb2000000ffff     /* 0xe021 ring 1 data                */
+        .quad 0x00cffa000000ffff     /* 0xe02b ring 3 code, compatibility */
+        .quad 0x00cff2000000ffff     /* 0xe033 ring 3 data                */
+        .quad 0x00cf9a000000ffff     /* 0xe038 ring 0 code, compatibility */
+        .org compat_gdt_table - FIRST_RESERVED_GDT_BYTE + __TSS(0) * 8
+        .fill 4*NR_CPUS,8,0          /* space for TSS and LDT per CPU     */
+# undef LIMIT
+#endif
 
 /* Initial PML4 -- level-4 page table. */
         .align PAGE_SIZE, 0
diff -r c75883680f28 -r 7c5eea5feebd xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/arch/x86/domain.c     Fri Jan 05 17:32:00 2007 +0000
@@ -283,17 +283,18 @@ int arch_set_info_guest(
 
     if ( !is_hvm_vcpu(v) )
     {
-        fixup_guest_stack_selector(c->user_regs.ss);
-        fixup_guest_stack_selector(c->kernel_ss);
-        fixup_guest_code_selector(c->user_regs.cs);
-
-#ifdef __i386__
-        fixup_guest_code_selector(c->event_callback_cs);
-        fixup_guest_code_selector(c->failsafe_callback_cs);
-#endif
+        fixup_guest_stack_selector(d, c->user_regs.ss);
+        fixup_guest_stack_selector(d, c->kernel_ss);
+        fixup_guest_code_selector(d, c->user_regs.cs);
+
+        if ( CONFIG_PAGING_LEVELS < 4 || IS_COMPAT(d) )
+        {
+            fixup_guest_code_selector(d, c->event_callback_cs);
+            fixup_guest_code_selector(d, c->failsafe_callback_cs);
+        }
 
         for ( i = 0; i < 256; i++ )
-            fixup_guest_code_selector(c->trap_ctxt[i].cs);
+            fixup_guest_code_selector(d, c->trap_ctxt[i].cs);
 
         /* LDT safety checks. */
         if ( ((c->ldt_base & (PAGE_SIZE-1)) != 0) || 
@@ -489,27 +490,30 @@ static void load_segments(struct vcpu *n
             all_segs_okay &= loadsegment(gs, nctxt->user_regs.gs);
     }
 
-    /* This can only be non-zero if selector is NULL. */
-    if ( nctxt->fs_base )
-        wrmsr(MSR_FS_BASE,
-              nctxt->fs_base,
-              nctxt->fs_base>>32);
-
-    /* Most kernels have non-zero GS base, so don't bother testing. */
-    /* (This is also a serialising instruction, avoiding AMD erratum #88.) */
-    wrmsr(MSR_SHADOW_GS_BASE,
-          nctxt->gs_base_kernel,
-          nctxt->gs_base_kernel>>32);
-
-    /* This can only be non-zero if selector is NULL. */
-    if ( nctxt->gs_base_user )
-        wrmsr(MSR_GS_BASE,
-              nctxt->gs_base_user,
-              nctxt->gs_base_user>>32);
-
-    /* If in kernel mode then switch the GS bases around. */
-    if ( n->arch.flags & TF_kernel_mode )
-        __asm__ __volatile__ ( "swapgs" );
+    if ( !IS_COMPAT(n->domain) )
+    {
+        /* This can only be non-zero if selector is NULL. */
+        if ( nctxt->fs_base )
+            wrmsr(MSR_FS_BASE,
+                  nctxt->fs_base,
+                  nctxt->fs_base>>32);
+
+        /* Most kernels have non-zero GS base, so don't bother testing. */
+        /* (This is also a serialising instruction, avoiding AMD erratum #88.) 
*/
+        wrmsr(MSR_SHADOW_GS_BASE,
+              nctxt->gs_base_kernel,
+              nctxt->gs_base_kernel>>32);
+
+        /* This can only be non-zero if selector is NULL. */
+        if ( nctxt->gs_base_user )
+            wrmsr(MSR_GS_BASE,
+                  nctxt->gs_base_user,
+                  nctxt->gs_base_user>>32);
+
+        /* If in kernel mode then switch the GS bases around. */
+        if ( (n->arch.flags & TF_kernel_mode) )
+            __asm__ __volatile__ ( "swapgs" );
+    }
 
     if ( unlikely(!all_segs_okay) )
     {
@@ -519,6 +523,55 @@ static void load_segments(struct vcpu *n
             (unsigned long *)regs->rsp :
             (unsigned long *)nctxt->kernel_sp;
         unsigned long cs_and_mask, rflags;
+
+        if ( IS_COMPAT(n->domain) )
+        {
+            unsigned int *esp = ring_1(regs) ?
+                                (unsigned int *)regs->rsp :
+                                (unsigned int *)nctxt->kernel_sp;
+            unsigned int cs_and_mask, eflags;
+            int ret = 0;
+
+            /* CS longword also contains full evtchn_upcall_mask. */
+            cs_and_mask = (unsigned short)regs->cs |
+                ((unsigned int)n->vcpu_info->evtchn_upcall_mask << 16);
+            /* Fold upcall mask into RFLAGS.IF. */
+            eflags  = regs->_eflags & ~X86_EFLAGS_IF;
+            eflags |= !n->vcpu_info->evtchn_upcall_mask << 9;
+
+            if ( !ring_1(regs) )
+            {
+                ret  = put_user(regs->ss,       esp-1);
+                ret |= put_user(regs->_esp,     esp-2);
+                esp -= 2;
+            }
+
+            if ( ret |
+                 put_user(eflags,              esp-1) |
+                 put_user(cs_and_mask,         esp-2) |
+                 put_user(regs->_eip,          esp-3) |
+                 put_user(nctxt->user_regs.gs, esp-4) |
+                 put_user(nctxt->user_regs.fs, esp-5) |
+                 put_user(nctxt->user_regs.es, esp-6) |
+                 put_user(nctxt->user_regs.ds, esp-7) )
+            {
+                gdprintk(XENLOG_ERR, "Error while creating compat "
+                         "failsafe callback frame.\n");
+                domain_crash(n->domain);
+            }
+
+            if ( test_bit(_VGCF_failsafe_disables_events,
+                          &n->arch.guest_context.flags) )
+                n->vcpu_info->evtchn_upcall_mask = 1;
+
+            regs->entry_vector  = TRAP_syscall;
+            regs->_eflags      &= 0xFFFCBEFFUL;
+            regs->ss            = FLAT_COMPAT_KERNEL_SS;
+            regs->_esp          = (unsigned long)(esp-7);
+            regs->cs            = FLAT_COMPAT_KERNEL_CS;
+            regs->_eip          = nctxt->failsafe_callback_eip;
+            return;
+        }
 
         if ( !(n->arch.flags & TF_kernel_mode) )
             toggle_guest_mode(n);
@@ -581,7 +634,7 @@ static void save_segments(struct vcpu *v
     if ( regs->es )
         dirty_segment_mask |= DIRTY_ES;
 
-    if ( regs->fs )
+    if ( regs->fs || IS_COMPAT(v->domain) )
     {
         dirty_segment_mask |= DIRTY_FS;
         ctxt->fs_base = 0; /* != 0 selector kills fs_base */
@@ -591,7 +644,7 @@ static void save_segments(struct vcpu *v
         dirty_segment_mask |= DIRTY_FS_BASE;
     }
 
-    if ( regs->gs )
+    if ( regs->gs || IS_COMPAT(v->domain) )
     {
         dirty_segment_mask |= DIRTY_GS;
         ctxt->gs_base_user = 0; /* != 0 selector kills gs_base_user */
@@ -725,6 +778,23 @@ void context_switch(struct vcpu *prev, s
     else
     {
         __context_switch();
+
+#ifdef CONFIG_COMPAT
+        if ( is_idle_vcpu(prev)
+             || IS_COMPAT(prev->domain) != IS_COMPAT(next->domain) )
+        {
+            uint32_t efer_lo, efer_hi;
+
+            local_flush_tlb_one(GDT_VIRT_START(next) + 
FIRST_RESERVED_GDT_BYTE);
+
+            rdmsr(MSR_EFER, efer_lo, efer_hi);
+            if ( !IS_COMPAT(next->domain) == !(efer_lo & EFER_SCE) )
+            {
+                efer_lo ^= EFER_SCE;
+                wrmsr(MSR_EFER, efer_lo, efer_hi);
+            }
+        }
+#endif
 
         /* Re-enable interrupts before restoring state which may fault. */
         local_irq_enable();
@@ -938,6 +1008,10 @@ void domain_relinquish_resources(struct 
                 put_page(mfn_to_page(pfn));
             else
                 put_page_and_type(mfn_to_page(pfn));
+#ifdef __x86_64__
+            if ( pfn == pagetable_get_pfn(v->arch.guest_table_user) )
+                v->arch.guest_table_user = pagetable_null();
+#endif
             v->arch.guest_table = pagetable_null();
         }
 
diff -r c75883680f28 -r 7c5eea5feebd xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c       Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/arch/x86/domain_build.c       Fri Jan 05 17:32:00 2007 +0000
@@ -319,10 +319,38 @@ int construct_dom0(struct domain *d,
 
     nr_pages = compute_dom0_nr_pages();
 
-    if ( (rc = parseelfimage(&dsi)) != 0 )
-        return rc;
-
-    xen_pae  = (CONFIG_PAGING_LEVELS == 3);
+    rc = parseelfimage(&dsi);
+#ifdef CONFIG_COMPAT
+    if ( rc == -ENOSYS
+         && (rc = parseelf32image(&dsi)) == 0 )
+    {
+        l1_pgentry_t gdt_l1e;
+
+        set_bit(_DOMF_compat, &d->domain_flags);
+
+        if ( nr_pages != (unsigned int)nr_pages )
+            nr_pages = UINT_MAX;
+
+        /*
+         * Map compatibility Xen segments into every VCPU's GDT. See
+         * arch_domain_create() for further comments.
+         */
+        gdt_l1e = l1e_from_page(virt_to_page(compat_gdt_table),
+                                PAGE_HYPERVISOR);
+        for ( i = 0; i < MAX_VIRT_CPUS; i++ )
+            d->arch.mm_perdomain_pt[((i << GDT_LDT_VCPU_SHIFT) +
+                                     FIRST_RESERVED_GDT_PAGE)] = gdt_l1e;
+        local_flush_tlb_one(GDT_LDT_VIRT_START + FIRST_RESERVED_GDT_BYTE);
+    }
+#endif
+    if ( rc != 0)
+    {
+        if ( rc == -ENOSYS )
+            printk("DOM0 image is not a Xen-compatible Elf image.\n");
+       return rc;
+    }
+
+    xen_pae  = (CONFIG_PAGING_LEVELS == 3) || IS_COMPAT(d);
     if (dsi.pae_kernel == PAEKERN_bimodal)
         dom0_pae = xen_pae; 
     else
@@ -338,7 +366,13 @@ int construct_dom0(struct domain *d,
             dsi.pae_kernel == PAEKERN_bimodal) )
             set_bit(VMASST_TYPE_pae_extended_cr3, &d->vm_assist);
 
-    if ( (p = xen_elfnote_string(&dsi, XEN_ELFNOTE_FEATURES)) != NULL )
+#ifdef CONFIG_COMPAT
+    if ( IS_COMPAT(d) )
+        p = xen_elf32note_string(&dsi, XEN_ELFNOTE_FEATURES);
+    else
+#endif
+        p = xen_elfnote_string(&dsi, XEN_ELFNOTE_FEATURES);
+    if ( p != NULL )
     {
         parse_features(p,
                        dom0_features_supported,
@@ -590,6 +624,12 @@ int construct_dom0(struct domain *d,
         return -EINVAL;
     }
 
+    if ( IS_COMPAT(d) )
+    {
+        v->arch.guest_context.failsafe_callback_cs = FLAT_COMPAT_KERNEL_CS;
+        v->arch.guest_context.event_callback_cs    = FLAT_COMPAT_KERNEL_CS;
+    }
+
     /* WARNING: The new domain must have its 'processor' field filled in! */
     maddr_to_page(mpt_alloc)->u.inuse.type_info = PGT_l4_page_table;
     l4start = l4tab = __va(mpt_alloc); mpt_alloc += PAGE_SIZE;
@@ -599,6 +639,8 @@ int construct_dom0(struct domain *d,
     l4tab[l4_table_offset(PERDOMAIN_VIRT_START)] =
         l4e_from_paddr(__pa(d->arch.mm_perdomain_l3), __PAGE_HYPERVISOR);
     v->arch.guest_table = pagetable_from_paddr(__pa(l4start));
+    if ( IS_COMPAT(d) )
+        v->arch.guest_table_user = v->arch.guest_table;
 
     l4tab += l4_table_offset(dsi.v_start);
     mfn = alloc_spfn;
@@ -711,10 +753,20 @@ int construct_dom0(struct domain *d,
     write_ptbase(v);
 
     /* Copy the OS image and free temporary buffer. */
-    (void)loadelfimage(&dsi);
-
-    hypercall_page =
-        xen_elfnote_numeric(&dsi, XEN_ELFNOTE_HYPERCALL_PAGE, 
&hypercall_page_defined);
+#ifdef CONFIG_COMPAT
+    if ( IS_COMPAT(d) )
+    {
+        (void)loadelf32image(&dsi);
+        hypercall_page =
+            xen_elf32note_numeric(&dsi, XEN_ELFNOTE_HYPERCALL_PAGE, 
&hypercall_page_defined);
+    }
+    else
+#endif
+    {
+        (void)loadelfimage(&dsi);
+        hypercall_page =
+            xen_elfnote_numeric(&dsi, XEN_ELFNOTE_HYPERCALL_PAGE, 
&hypercall_page_defined);
+    }
     if ( hypercall_page_defined )
     {
         if ( (hypercall_page < dsi.v_start) || (hypercall_page >= v_end) )
@@ -747,7 +799,7 @@ int construct_dom0(struct domain *d,
     si->mfn_list     = vphysmap_start;
     sprintf(si->magic, "xen-%i.%i-x86_%d%s",
             xen_major_version(), xen_minor_version(),
-            BITS_PER_LONG, xen_pae ? "p" : "");
+            !IS_COMPAT(d) ? BITS_PER_LONG : 32, xen_pae ? "p" : "");
 
     /* Write the phys->machine and machine->phys table entries. */
     for ( pfn = 0; pfn < d->tot_pages; pfn++ )
@@ -819,9 +871,11 @@ int construct_dom0(struct domain *d,
      *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
      */
     regs = &v->arch.guest_context.user_regs;
-    regs->ds = regs->es = regs->fs = regs->gs = FLAT_KERNEL_DS;
-    regs->ss = FLAT_KERNEL_SS;
-    regs->cs = FLAT_KERNEL_CS;
+    regs->ds = regs->es = regs->fs = regs->gs = !IS_COMPAT(d)
+                                                ? FLAT_KERNEL_DS
+                                                : FLAT_COMPAT_KERNEL_DS;
+    regs->ss = !IS_COMPAT(d) ? FLAT_KERNEL_SS : FLAT_COMPAT_KERNEL_SS;
+    regs->cs = !IS_COMPAT(d) ? FLAT_KERNEL_CS : FLAT_COMPAT_KERNEL_CS;
     regs->eip = dsi.v_kernentry;
     regs->esp = vstack_end;
     regs->esi = vstartinfo_start;
@@ -906,12 +960,27 @@ int elf_sanity_check(const Elf_Ehdr *ehd
          (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) ||
          (ehdr->e_type != ET_EXEC) )
     {
-        printk("DOM0 image is not a Xen-compatible Elf image.\n");
         return 0;
     }
 
     return 1;
 }
+
+#ifdef CONFIG_COMPAT
+int elf32_sanity_check(const Elf32_Ehdr *ehdr)
+{
+    if ( !IS_ELF(*ehdr) ||
+         (ehdr->e_ident[EI_CLASS] != ELFCLASS32) ||
+         (ehdr->e_machine != EM_386) ||
+         (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) ||
+         (ehdr->e_type != ET_EXEC) )
+    {
+        return 0;
+    }
+
+    return 1;
+}
+#endif
 
 /*
  * Local variables:
diff -r c75883680f28 -r 7c5eea5feebd xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/arch/x86/mm.c Fri Jan 05 17:32:00 2007 +0000
@@ -433,7 +433,7 @@ static int alloc_segdesc_page(struct pag
     descs = map_domain_page(page_to_mfn(page));
 
     for ( i = 0; i < 512; i++ )
-        if ( unlikely(!check_descriptor(&descs[i])) )
+        if ( unlikely(!check_descriptor(page_get_owner(page), &descs[i])) )
             goto fail;
 
     unmap_domain_page(descs);
@@ -2835,7 +2835,7 @@ long do_update_descriptor(u64 pa, u64 de
     mfn = gmfn_to_mfn(dom, gmfn);
     if ( (((unsigned int)pa % sizeof(struct desc_struct)) != 0) ||
          !mfn_valid(mfn) ||
-         !check_descriptor(&d) )
+         !check_descriptor(dom, &d) )
     {
         UNLOCK_BIGLOCK(dom);
         return -EINVAL;
diff -r c75883680f28 -r 7c5eea5feebd xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/arch/x86/setup.c      Fri Jan 05 17:32:00 2007 +0000
@@ -791,6 +791,9 @@ void arch_get_xen_caps(xen_capabilities_
 #elif defined(CONFIG_X86_64)
 
     p += sprintf(p, "xen-%d.%d-x86_64 ", major, minor);
+#ifdef CONFIG_COMPAT
+    p += sprintf(p, "xen-%d.%d-x86_32p ", major, minor);
+#endif
     if ( hvm_enabled )
     {
         p += sprintf(p, "hvm-%d.%d-x86_32 ", major, minor);
diff -r c75883680f28 -r 7c5eea5feebd xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/arch/x86/traps.c      Fri Jan 05 17:32:00 2007 +0000
@@ -382,7 +382,7 @@ static int do_guest_trap(
     if ( TI_GET_IF(ti) )
         tb->flags |= TBF_INTERRUPT;
 
-    if ( unlikely(null_trap_bounce(tb)) )
+    if ( unlikely(null_trap_bounce(v, tb)) )
         gdprintk(XENLOG_WARNING, "Unhandled %s fault/trap [#%d] in "
                  "domain %d on VCPU %d [ec=%04x]\n",
                  trapstr(trapnr), trapnr, v->domain->domain_id, v->vcpu_id,
@@ -673,7 +673,7 @@ void propagate_page_fault(unsigned long 
     tb->eip        = ti->address;
     if ( TI_GET_IF(ti) )
         tb->flags |= TBF_INTERRUPT;
-    if ( unlikely(null_trap_bounce(tb)) )
+    if ( unlikely(null_trap_bounce(v, tb)) )
     {
         printk("Unhandled page fault in domain %d on VCPU %d (ec=%04X)\n",
                v->domain->domain_id, v->vcpu_id, error_code);
@@ -1785,6 +1785,13 @@ void set_tss_desc(unsigned int n, void *
         (unsigned long)addr,
         offsetof(struct tss_struct, __cacheline_filler) - 1,
         9);
+#ifdef CONFIG_COMPAT
+    _set_tssldt_desc(
+        compat_gdt_table + __TSS(n) - FIRST_RESERVED_GDT_ENTRY,
+        (unsigned long)addr,
+        offsetof(struct tss_struct, __cacheline_filler) - 1,
+        11);
+#endif
 }
 
 void __init trap_init(void)
@@ -1859,7 +1866,7 @@ long do_set_trap_table(XEN_GUEST_HANDLE(
         if ( cur.address == 0 )
             break;
 
-        fixup_guest_code_selector(cur.cs);
+        fixup_guest_code_selector(current->domain, cur.cs);
 
         memcpy(&dst[cur.vector], &cur, sizeof(cur));
 
diff -r c75883680f28 -r 7c5eea5feebd xen/arch/x86/x86_32/mm.c
--- a/xen/arch/x86/x86_32/mm.c  Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/arch/x86/x86_32/mm.c  Fri Jan 05 17:32:00 2007 +0000
@@ -230,7 +230,7 @@ long do_stack_switch(unsigned long ss, u
     int nr = smp_processor_id();
     struct tss_struct *t = &init_tss[nr];
 
-    fixup_guest_stack_selector(ss);
+    fixup_guest_stack_selector(current->domain, ss);
 
     current->arch.guest_context.kernel_ss = ss;
     current->arch.guest_context.kernel_sp = esp;
@@ -241,7 +241,7 @@ long do_stack_switch(unsigned long ss, u
 }
 
 /* Returns TRUE if given descriptor is valid for GDT or LDT. */
-int check_descriptor(struct desc_struct *d)
+int check_descriptor(const struct domain *dom, struct desc_struct *d)
 {
     unsigned long base, limit;
     u32 a = d->a, b = d->b;
@@ -261,8 +261,8 @@ int check_descriptor(struct desc_struct 
      * gates (consider a call gate pointing at another kernel descriptor with 
      * DPL 0 -- this would get the OS ring-0 privileges).
      */
-    if ( (b & _SEGMENT_DPL) < (GUEST_KERNEL_RPL << 13) )
-        d->b = b = (b & ~_SEGMENT_DPL) | (GUEST_KERNEL_RPL << 13);
+    if ( (b & _SEGMENT_DPL) < (GUEST_KERNEL_RPL(dom) << 13) )
+        d->b = b = (b & ~_SEGMENT_DPL) | (GUEST_KERNEL_RPL(dom) << 13);
 
     if ( !(b & _SEGMENT_S) )
     {
@@ -284,8 +284,8 @@ int check_descriptor(struct desc_struct 
 
         /* Validate and fix up the target code selector. */
         cs = a >> 16;
-        fixup_guest_code_selector(cs);
-        if ( !guest_gate_selector_okay(cs) )
+        fixup_guest_code_selector(dom, cs);
+        if ( !guest_gate_selector_okay(dom, cs) )
             goto bad;
         a = d->a = (d->a & 0xffffU) | (cs << 16);
 
diff -r c75883680f28 -r 7c5eea5feebd xen/arch/x86/x86_32/traps.c
--- a/xen/arch/x86/x86_32/traps.c       Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/arch/x86/x86_32/traps.c       Fri Jan 05 17:32:00 2007 +0000
@@ -296,7 +296,7 @@ void init_int80_direct_trap(struct vcpu 
      * switch to the Xen stack and we need to swap back to the guest
      * kernel stack before passing control to the system call entry point.
      */
-    if ( TI_GET_IF(ti) || !guest_gate_selector_okay(ti->cs) ||
+    if ( TI_GET_IF(ti) || !guest_gate_selector_okay(v->domain, ti->cs) ||
          supervisor_mode_kernel )
     {
         v->arch.int80_desc.a = v->arch.int80_desc.b = 0;
@@ -326,7 +326,7 @@ static long register_guest_callback(stru
     long ret = 0;
     struct vcpu *v = current;
 
-    fixup_guest_code_selector(reg->address.cs);
+    fixup_guest_code_selector(v->domain, reg->address.cs);
 
     switch ( reg->type )
     {
diff -r c75883680f28 -r 7c5eea5feebd xen/arch/x86/x86_64/asm-offsets.c
--- a/xen/arch/x86/x86_64/asm-offsets.c Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/arch/x86/x86_64/asm-offsets.c Fri Jan 05 17:32:00 2007 +0000
@@ -58,12 +58,16 @@ void __dummy__(void)
     OFFSET(VCPU_thread_flags, struct vcpu, arch.flags);
     OFFSET(VCPU_event_addr, struct vcpu,
            arch.guest_context.event_callback_eip);
+    OFFSET(VCPU_event_sel, struct vcpu,
+           arch.guest_context.event_callback_cs);
     OFFSET(VCPU_failsafe_addr, struct vcpu,
            arch.guest_context.failsafe_callback_eip);
+    OFFSET(VCPU_failsafe_sel, struct vcpu,
+           arch.guest_context.failsafe_callback_cs);
     OFFSET(VCPU_syscall_addr, struct vcpu,
            arch.guest_context.syscall_callback_eip);
-    OFFSET(VCPU_kernel_sp, struct vcpu,
-           arch.guest_context.kernel_sp);
+    OFFSET(VCPU_kernel_sp, struct vcpu, arch.guest_context.kernel_sp);
+    OFFSET(VCPU_kernel_ss, struct vcpu, arch.guest_context.kernel_ss);
     OFFSET(VCPU_guest_context_flags, struct vcpu, arch.guest_context.flags);
     OFFSET(VCPU_arch_guest_fpu_ctxt, struct vcpu, arch.guest_context.fpu_ctxt);
     OFFSET(VCPU_flags, struct vcpu, vcpu_flags);
diff -r c75883680f28 -r 7c5eea5feebd xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c  Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/arch/x86/x86_64/mm.c  Fri Jan 05 17:32:00 2007 +0000
@@ -231,7 +231,7 @@ long subarch_memory_op(int op, XEN_GUEST
 
 long do_stack_switch(unsigned long ss, unsigned long esp)
 {
-    fixup_guest_stack_selector(ss);
+    fixup_guest_stack_selector(current->domain, ss);
     current->arch.guest_context.kernel_ss = ss;
     current->arch.guest_context.kernel_sp = esp;
     return 0;
@@ -291,7 +291,7 @@ long do_set_segment_base(unsigned int wh
 
 
 /* Returns TRUE if given descriptor is valid for GDT or LDT. */
-int check_descriptor(struct desc_struct *d)
+int check_descriptor(const struct domain *dom, struct desc_struct *d)
 {
     u32 a = d->a, b = d->b;
     u16 cs;
@@ -301,8 +301,8 @@ int check_descriptor(struct desc_struct 
         goto good;
 
     /* Check and fix up the DPL. */
-    if ( (b & _SEGMENT_DPL) < (GUEST_KERNEL_RPL << 13) )
-        d->b = b = (b & ~_SEGMENT_DPL) | (GUEST_KERNEL_RPL << 13);
+    if ( (b & _SEGMENT_DPL) < (GUEST_KERNEL_RPL(dom) << 13) )
+        d->b = b = (b & ~_SEGMENT_DPL) | (GUEST_KERNEL_RPL(dom) << 13);
 
     /* All code and data segments are okay. No base/limit checking. */
     if ( (b & _SEGMENT_S) )
@@ -318,8 +318,8 @@ int check_descriptor(struct desc_struct 
 
     /* Validate and fix up the target code selector. */
     cs = a >> 16;
-    fixup_guest_code_selector(cs);
-    if ( !guest_gate_selector_okay(cs) )
+    fixup_guest_code_selector(dom, cs);
+    if ( !guest_gate_selector_okay(dom, cs) )
         goto bad;
     a = d->a = (d->a & 0xffffU) | (cs << 16);
 
diff -r c75883680f28 -r 7c5eea5feebd xen/arch/x86/x86_64/traps.c
--- a/xen/arch/x86/x86_64/traps.c       Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/arch/x86/x86_64/traps.c       Fri Jan 05 17:32:00 2007 +0000
@@ -178,6 +178,8 @@ asmlinkage void do_double_fault(struct c
 
 void toggle_guest_mode(struct vcpu *v)
 {
+    if ( IS_COMPAT(v->domain) )
+        return;
     v->arch.flags ^= TF_kernel_mode;
     __asm__ __volatile__ ( "swapgs" );
     update_cr3(v);
diff -r c75883680f28 -r 7c5eea5feebd xen/common/Makefile
--- a/xen/common/Makefile       Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/common/Makefile       Fri Jan 05 17:32:00 2007 +0000
@@ -3,6 +3,7 @@ obj-y += domctl.o
 obj-y += domctl.o
 obj-y += domain.o
 obj-y += elf.o
+obj-$(CONFIG_COMPAT) += elf32.o
 obj-y += event_channel.o
 obj-y += grant_table.o
 obj-y += kernel.o
diff -r c75883680f28 -r 7c5eea5feebd xen/common/elf.c
--- a/xen/common/elf.c  Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/common/elf.c  Fri Jan 05 17:32:00 2007 +0000
@@ -203,7 +203,7 @@ int parseelfimage(struct domain_setup_in
     int h, virt_base_defined, elf_pa_off_defined, virt_entry_defined;
 
     if ( !elf_sanity_check(ehdr) )
-        return -EINVAL;
+        return -ENOSYS;
 
     if ( (ehdr->e_phoff + (ehdr->e_phnum*ehdr->e_phentsize)) > image_len )
     {
diff -r c75883680f28 -r 7c5eea5feebd xen/common/elf32.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/common/elf32.c        Fri Jan 05 17:32:00 2007 +0000
@@ -0,0 +1,19 @@
+/******************************************************************************
+ * elf32.c
+ *
+ * Stub to support 32-bit ELF images on 64-bit platforms.
+ */
+
+#include <xen/config.h>
+#undef ELFSIZE
+#define ELFSIZE 32
+#include <xen/types.h>
+#include <xen/elf.h>
+
+#define xen_elfnote_string xen_elf32note_string
+#define xen_elfnote_numeric xen_elf32note_numeric
+#define parseelfimage parseelf32image
+#define loadelfimage loadelf32image
+#define elf_sanity_check elf32_sanity_check
+
+#include "elf.c"
diff -r c75883680f28 -r 7c5eea5feebd xen/include/asm-x86/config.h
--- a/xen/include/asm-x86/config.h      Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/include/asm-x86/config.h      Fri Jan 05 17:32:00 2007 +0000
@@ -87,6 +87,7 @@
 #if defined(__x86_64__)
 
 #define CONFIG_X86_64 1
+#define CONFIG_COMPAT 1
 
 #define asmlinkage
 
@@ -181,13 +182,21 @@
 #define DIRECTMAP_VIRT_START    (PML4_ADDR(262))
 #define DIRECTMAP_VIRT_END      (DIRECTMAP_VIRT_START + PML4_ENTRY_BYTES*2)
 
+#define __HYPERVISOR_COMPAT_VIRT_START 0xF5800000
+#define HYPERVISOR_COMPAT_VIRT_START   \
+    mk_unsigned_long(__HYPERVISOR_COMPAT_VIRT_START)
+#define MACH2PHYS_COMPAT_VIRT_START    HYPERVISOR_COMPAT_VIRT_START
+#define MACH2PHYS_COMPAT_VIRT_END      0xFFE00000
+#define MACH2PHYS_COMPAT_NR_ENTRIES    \
+    ((MACH2PHYS_COMPAT_VIRT_END-MACH2PHYS_COMPAT_VIRT_START)>>2)
+
 #define PGT_base_page_table     PGT_l4_page_table
 
-#define __HYPERVISOR_CS64 0xe010
-#define __HYPERVISOR_CS32 0xe008
+#define __HYPERVISOR_CS64 0xe008
+#define __HYPERVISOR_CS32 0xe038
 #define __HYPERVISOR_CS   __HYPERVISOR_CS64
 #define __HYPERVISOR_DS64 0x0000
-#define __HYPERVISOR_DS32 0xe018
+#define __HYPERVISOR_DS32 0xe010
 #define __HYPERVISOR_DS   __HYPERVISOR_DS64
 
 /* For generic assembly code: use macros to define operation/operand sizes. */
diff -r c75883680f28 -r 7c5eea5feebd xen/include/asm-x86/desc.h
--- a/xen/include/asm-x86/desc.h        Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/include/asm-x86/desc.h        Fri Jan 05 17:32:00 2007 +0000
@@ -18,31 +18,76 @@
 
 #define LDT_ENTRY_SIZE 8
 
+#if defined(__x86_64__)
+
+#define FLAT_COMPAT_RING1_CS 0xe019  /* GDT index 259 */
+#define FLAT_COMPAT_RING1_DS 0xe021  /* GDT index 260 */
+#define FLAT_COMPAT_RING1_SS 0xe021  /* GDT index 260 */
+#define FLAT_COMPAT_RING3_CS 0xe02b  /* GDT index 261 */
+#define FLAT_COMPAT_RING3_DS 0xe033  /* GDT index 262 */
+#define FLAT_COMPAT_RING3_SS 0xe033  /* GDT index 262 */
+
+#define FLAT_COMPAT_KERNEL_DS FLAT_COMPAT_RING1_DS
+#define FLAT_COMPAT_KERNEL_CS FLAT_COMPAT_RING1_CS
+#define FLAT_COMPAT_KERNEL_SS FLAT_COMPAT_RING1_SS
+#define FLAT_COMPAT_USER_DS   FLAT_COMPAT_RING3_DS
+#define FLAT_COMPAT_USER_CS   FLAT_COMPAT_RING3_CS
+#define FLAT_COMPAT_USER_SS   FLAT_COMPAT_RING3_SS
+
+#define __FIRST_TSS_ENTRY (FIRST_RESERVED_GDT_ENTRY + 8)
+#define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY + 2)
+
+#define __TSS(n) (((n)<<2) + __FIRST_TSS_ENTRY)
+#define __LDT(n) (((n)<<2) + __FIRST_LDT_ENTRY)
+
+#elif defined(__i386__)
+
+#define FLAT_COMPAT_KERNEL_CS FLAT_KERNEL_CS
+#define FLAT_COMPAT_KERNEL_DS FLAT_KERNEL_DS
+#define FLAT_COMPAT_KERNEL_SS FLAT_KERNEL_SS
+#define FLAT_COMPAT_USER_CS   FLAT_USER_CS
+#define FLAT_COMPAT_USER_DS   FLAT_USER_DS
+#define FLAT_COMPAT_USER_SS   FLAT_USER_SS
+
+#define __DOUBLEFAULT_TSS_ENTRY FIRST_RESERVED_GDT_ENTRY
+
+#define __FIRST_TSS_ENTRY (FIRST_RESERVED_GDT_ENTRY + 8)
+#define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY + 1)
+
+#define __TSS(n) (((n)<<1) + __FIRST_TSS_ENTRY)
+#define __LDT(n) (((n)<<1) + __FIRST_LDT_ENTRY)
+
+#endif
+
+#ifndef __ASSEMBLY__
+
 #define load_TR(n)  __asm__ __volatile__ ("ltr  %%ax" : : "a" (__TSS(n)<<3) )
 
 #if defined(__x86_64__)
-#define GUEST_KERNEL_RPL 3
-#elif defined(__i386__)
-#define GUEST_KERNEL_RPL 1
+#define GUEST_KERNEL_RPL(d) (!IS_COMPAT(d) ? 3 : 1)
+#elif defined(__i386__)
+#define GUEST_KERNEL_RPL(d) ((void)(d), 1)
 #endif
 
 /* Fix up the RPL of a guest segment selector. */
-#define __fixup_guest_selector(sel)                             \
-    ((sel) = (((sel) & 3) >= GUEST_KERNEL_RPL) ? (sel) :        \
-     (((sel) & ~3) | GUEST_KERNEL_RPL))
+#define __fixup_guest_selector(d, sel)                             \
+({                                                                 \
+    uint16_t _rpl = GUEST_KERNEL_RPL(d);                           \
+    (sel) = (((sel) & 3) >= _rpl) ? (sel) : (((sel) & ~3) | _rpl); \
+})
 
 /* Stack selectors don't need fixing up if the kernel runs in ring 0. */
 #ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL
-#define fixup_guest_stack_selector(ss) ((void)0)
+#define fixup_guest_stack_selector(d, ss) ((void)0)
 #else
-#define fixup_guest_stack_selector(ss) __fixup_guest_selector(ss)
+#define fixup_guest_stack_selector(d, ss) __fixup_guest_selector(d, ss)
 #endif
 
 /*
  * Code selectors are always fixed up. It allows the Xen exit stub to detect
  * return to guest context, even when the guest kernel runs in ring 0.
  */
-#define fixup_guest_code_selector(cs)  __fixup_guest_selector(cs)
+#define fixup_guest_code_selector(d, cs)  __fixup_guest_selector(d, cs)
 
 /*
  * We need this function because enforcing the correct guest kernel RPL is
@@ -57,10 +102,14 @@
  * DPL < CPL then they'll be cleared automatically. If SS RPL or DPL differs
  * from CS RPL then we'll #GP.
  */
-#define guest_gate_selector_okay(sel)                                   \
+#define guest_gate_selector_okay(d, sel)                                \
     ((((sel)>>3) < FIRST_RESERVED_GDT_ENTRY) || /* Guest seg? */        \
-     ((sel) == FLAT_KERNEL_CS) ||               /* Xen default seg? */  \
+     ((sel) == (!IS_COMPAT(d) ?                                         \
+                FLAT_KERNEL_CS :                /* Xen default seg? */  \
+                FLAT_COMPAT_KERNEL_CS)) ||      /* Xen default compat seg? */  
\
      ((sel) & 4))                               /* LDT seg? */
+
+#endif /* __ASSEMBLY__ */
 
 /* These are bitmasks for the high 32 bits of a descriptor table entry. */
 #define _SEGMENT_TYPE    (15<< 8)
@@ -80,12 +129,6 @@ struct desc_struct {
 };
 
 #if defined(__x86_64__)
-
-#define __FIRST_TSS_ENTRY (FIRST_RESERVED_GDT_ENTRY + 8)
-#define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY + 2)
-
-#define __TSS(n) (((n)<<2) + __FIRST_TSS_ENTRY)
-#define __LDT(n) (((n)<<2) + __FIRST_LDT_ENTRY)
 
 typedef struct {
     u64 a, b;
@@ -118,14 +161,6 @@ do {                                    
 
 #elif defined(__i386__)
 
-#define __DOUBLEFAULT_TSS_ENTRY FIRST_RESERVED_GDT_ENTRY
-
-#define __FIRST_TSS_ENTRY (FIRST_RESERVED_GDT_ENTRY + 8)
-#define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY + 1)
-
-#define __TSS(n) (((n)<<1) + __FIRST_TSS_ENTRY)
-#define __LDT(n) (((n)<<1) + __FIRST_LDT_ENTRY)
-
 typedef struct desc_struct idt_entry_t;
 
 #define _set_gate(gate_addr,type,dpl,addr) \
@@ -155,6 +190,11 @@ __asm__ __volatile__ ("movw %w3,0(%2)\n\
 #endif
 
 extern struct desc_struct gdt_table[];
+#ifdef CONFIG_COMPAT
+extern struct desc_struct compat_gdt_table[];
+#else
+# define compat_gdt_table gdt_table
+#endif
 
 struct Xgt_desc_struct {
     unsigned short size;
diff -r c75883680f28 -r 7c5eea5feebd xen/include/asm-x86/ldt.h
--- a/xen/include/asm-x86/ldt.h Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/include/asm-x86/ldt.h Fri Jan 05 17:32:00 2007 +0000
@@ -17,7 +17,8 @@ static inline void load_LDT(struct vcpu 
     else
     {
         cpu = smp_processor_id();
-        desc = gdt_table + __LDT(cpu) - FIRST_RESERVED_GDT_ENTRY;
+        desc = (!IS_COMPAT(v->domain) ? gdt_table : compat_gdt_table)
+               + __LDT(cpu) - FIRST_RESERVED_GDT_ENTRY;
         _set_tssldt_desc(desc, LDT_VIRT_START(v), ents*8-1, 2);
         __asm__ __volatile__ ( "lldt %%ax" : : "a" (__LDT(cpu)<<3) );
     }
diff -r c75883680f28 -r 7c5eea5feebd xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h  Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/include/asm-x86/mm.h  Fri Jan 05 17:32:00 2007 +0000
@@ -244,7 +244,7 @@ pae_copy_root(struct vcpu *v, l3_pgentry
 pae_copy_root(struct vcpu *v, l3_pgentry_t *l3tab);
 #endif /* CONFIG_PAGING_LEVELS == 3 */
 
-int check_descriptor(struct desc_struct *d);
+int check_descriptor(const struct domain *, struct desc_struct *d);
 
 /*
  * The MPT (machine->physical mapping table) is an array of word-sized
diff -r c75883680f28 -r 7c5eea5feebd xen/include/asm-x86/regs.h
--- a/xen/include/asm-x86/regs.h        Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/include/asm-x86/regs.h        Fri Jan 05 17:32:00 2007 +0000
@@ -38,7 +38,8 @@ enum EFLAGS {
     ASSERT(diff < STACK_SIZE);                                                \
     /* If a guest frame, it must be have guest privs (unless HVM guest).   */ \
     /* We permit CS==0 which can come from an uninitialised trap entry. */    \
-    ASSERT((diff != 0) || vm86_mode(r) || ((r->cs&3) >= GUEST_KERNEL_RPL) ||  \
+    ASSERT((diff != 0) || vm86_mode(r) ||                                     \
+           ((r->cs&3) >= GUEST_KERNEL_RPL(current->domain)) ||                \
            (r->cs == 0) || is_hvm_vcpu(current));                             \
     /* If not a guest frame, it must be a hypervisor frame. */                \
     ASSERT((diff == 0) || (!vm86_mode(r) && (r->cs == __HYPERVISOR_CS)));     \
diff -r c75883680f28 -r 7c5eea5feebd xen/include/asm-x86/x86_32/regs.h
--- a/xen/include/asm-x86/x86_32/regs.h Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/include/asm-x86/x86_32/regs.h Fri Jan 05 17:32:00 2007 +0000
@@ -17,7 +17,7 @@
     ((dpl) >= (vm86_mode(r) ? 3 : ((r)->cs & 3)))
 
 /* Check for null trap callback handler: Is the selector null (0-3)? */
-#define null_trap_bounce(tb) (((tb)->cs & ~3) == 0)
+#define null_trap_bounce(v, tb) (((tb)->cs & ~3) == 0)
 
 /* Number of bytes of on-stack execution state to be context-switched. */
 #define CTXT_SWITCH_STACK_BYTES (sizeof(struct cpu_user_regs))
diff -r c75883680f28 -r 7c5eea5feebd xen/include/asm-x86/x86_64/regs.h
--- a/xen/include/asm-x86/x86_64/regs.h Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/include/asm-x86/x86_64/regs.h Fri Jan 05 17:32:00 2007 +0000
@@ -11,13 +11,16 @@
 #define ring_3(r)    (((r)->cs & 3) == 3)
 
 #define guest_kernel_mode(v, r)   \
-    (ring_3(r) && ((v)->arch.flags & TF_kernel_mode))
+    (!IS_COMPAT((v)->domain) ? \
+     ring_3(r) && ((v)->arch.flags & TF_kernel_mode) : \
+     ring_1(r))
 
 #define permit_softint(dpl, v, r) \
     ((dpl) >= (guest_kernel_mode(v, r) ? 1 : 3))
 
 /* Check for null trap callback handler: Is the EIP null? */
-#define null_trap_bounce(tb) ((tb)->eip == 0)
+#define null_trap_bounce(v, tb) \
+    (!IS_COMPAT((v)->domain) ? (tb)->eip == 0 : ((tb)->cs & ~3) == 0)
 
 /* Number of bytes of on-stack execution state to be context-switched. */
 /* NB. Segment registers and bases are not saved/restored on x86/64 stack. */
diff -r c75883680f28 -r 7c5eea5feebd xen/include/public/arch-x86/xen-x86_64.h
--- a/xen/include/public/arch-x86/xen-x86_64.h  Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/include/public/arch-x86/xen-x86_64.h  Fri Jan 05 17:32:00 2007 +0000
@@ -141,7 +141,10 @@ struct iret_context {
 
 #ifdef __GNUC__
 /* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */
-#define __DECL_REG(name) union { uint64_t r ## name, e ## name; }
+#define __DECL_REG(name) union { \
+    uint64_t r ## name, e ## name; \
+    uint32_t _e ## name; \
+}
 #else
 /* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */
 #define __DECL_REG(name) uint64_t r ## name
diff -r c75883680f28 -r 7c5eea5feebd xen/include/public/arch-x86/xen.h
--- a/xen/include/public/arch-x86/xen.h Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/include/public/arch-x86/xen.h Fri Jan 05 17:32:00 2007 +0000
@@ -141,7 +141,17 @@ struct vcpu_guest_context {
 #else
     unsigned long event_callback_eip;
     unsigned long failsafe_callback_eip;
+#ifdef __XEN__
+    union {
+        unsigned long syscall_callback_eip;
+        struct {
+            unsigned int event_callback_cs;    /* compat CS of event cb     */
+            unsigned int failsafe_callback_cs; /* compat CS of failsafe cb  */
+        };
+    };
+#else
     unsigned long syscall_callback_eip;
+#endif
 #endif
     unsigned long vm_assist;                /* VMASST_TYPE_* bitmap */
 #ifdef __x86_64__
diff -r c75883680f28 -r 7c5eea5feebd xen/include/xen/elf.h
--- a/xen/include/xen/elf.h     Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/include/xen/elf.h     Fri Jan 05 17:32:00 2007 +0000
@@ -525,6 +525,15 @@ extern unsigned long long xen_elfnote_nu
                                              int type, int *defined);
 extern const char *xen_elfnote_string(struct domain_setup_info *dsi, int type);
 
+#ifdef CONFIG_COMPAT
+extern int elf32_sanity_check(const Elf32_Ehdr *ehdr);
+extern int loadelf32image(struct domain_setup_info *);
+extern int parseelf32image(struct domain_setup_info *);
+extern unsigned long long xen_elf32note_numeric(struct domain_setup_info *,
+                                               int type, int *defined);
+extern const char *xen_elf32note_string(struct domain_setup_info *, int type);
+#endif
+
 #ifdef Elf_Ehdr
 extern int elf_sanity_check(const Elf_Ehdr *ehdr);
 #endif
diff -r c75883680f28 -r 7c5eea5feebd xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Fri Jan 05 17:24:55 2007 +0000
+++ b/xen/include/xen/sched.h   Fri Jan 05 17:32:00 2007 +0000
@@ -422,6 +422,9 @@ extern struct domain *domain_list;
  /* Domain is paused by the hypervisor? */
 #define _DOMF_paused           5
 #define DOMF_paused            (1UL<<_DOMF_paused)
+ /* Domain is a compatibility one? */
+#define _DOMF_compat           6
+#define DOMF_compat            (1UL<<_DOMF_compat)
 
 static inline int vcpu_runnable(struct vcpu *v)
 {
@@ -458,6 +461,13 @@ static inline void vcpu_unblock(struct v
 
 #define IS_PRIV(_d) ((_d)->is_privileged)
 
+#ifdef CONFIG_COMPAT
+#define IS_COMPAT(_d)                                       \
+    (test_bit(_DOMF_compat, &(_d)->domain_flags))
+#else
+#define IS_COMPAT(_d) 0
+#endif
+
 #define VM_ASSIST(_d,_t) (test_bit((_t), &(_d)->vm_assist))
 
 #define is_hvm_domain(d) ((d)->is_hvm)

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Introduce _DOMF_compat and infrastructure as well as several conditionals, Xen patchbot-unstable <=