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

[Xen-changelog] [xen-unstable] Introduce _DOMF_compat and infrastructure as well as several conditionals



# 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


 


Rackspace

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