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

[Xen-changelog] [xen-unstable] Enable compatibility mode operation for HYPERVISOR_domctl. Also add logic



# HG changeset patch
# User Emmanuel Ackaouy <ack@xxxxxxxxxxxxx>
# Date 1168018479 0
# Node ID 5442b2458e1b2d07e6ae06ebbbc1071c8fd544cb
# Parent  d80684d19ef4abff8658d762be4303fe2cfe01d0
Enable compatibility mode operation for HYPERVISOR_domctl. Also add logic
to switch a domain to/from compatibility mode (supposed to happen early
after domain creation only).

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---
 xen/arch/ia64/xen/domain.c         |   20 ++--
 xen/arch/powerpc/domain.c          |    4 
 xen/arch/powerpc/domctl.c          |    6 -
 xen/arch/x86/domain.c              |  171 +++++++++++++++++++++++++++++++------
 xen/arch/x86/domctl.c              |  107 ++++++++++++++++-------
 xen/arch/x86/mm/shadow/common.c    |    2 
 xen/arch/x86/x86_32/traps.c        |    2 
 xen/arch/x86/x86_64/Makefile       |    2 
 xen/arch/x86/x86_64/compat/entry.S |    2 
 xen/arch/x86/x86_64/compat/traps.c |    2 
 xen/arch/x86/x86_64/domctl.c       |  111 ++++++++++++++++++++++++
 xen/common/compat/Makefile         |    2 
 xen/common/compat/domain.c         |   15 ---
 xen/common/compat/domctl.c         |  137 +++++++++++++++++++++++++++++
 xen/common/compat/sysctl.c         |    7 -
 xen/common/domain.c                |   51 +++++++++--
 xen/common/domctl.c                |   98 ++++++++++++++++++---
 xen/common/schedule.c              |    2 
 xen/include/asm-x86/shadow.h       |    2 
 xen/include/public/domctl.h        |    5 +
 xen/include/xen/compat.h           |    3 
 xen/include/xen/domain.h           |   13 ++
 xen/include/xen/sched.h            |    8 +
 xen/include/xlat.lst               |    4 
 24 files changed, 648 insertions(+), 128 deletions(-)

diff -r d80684d19ef4 -r 5442b2458e1b xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c        Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/arch/ia64/xen/domain.c        Fri Jan 05 17:34:39 2007 +0000
@@ -522,14 +522,14 @@ void arch_domain_destroy(struct domain *
        deallocate_rid_range(d);
 }
 
-void arch_getdomaininfo_ctxt(struct vcpu *v, struct vcpu_guest_context *c)
+void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c)
 {
        int i;
-       struct vcpu_extra_regs *er = &c->extra_regs;
-
-       c->user_regs = *vcpu_regs (v);
-       c->privregs_pfn = get_gpfn_from_mfn(virt_to_maddr(v->arch.privregs) >>
-                                           PAGE_SHIFT);
+       struct vcpu_extra_regs *er = &c.nat->extra_regs;
+
+       c.nat->user_regs = *vcpu_regs(v);
+       c.nat->privregs_pfn = get_gpfn_from_mfn(virt_to_maddr(v->arch.privregs) 
>>
+                                                PAGE_SHIFT);
 
        /* Fill extra regs.  */
        for (i = 0; i < 8; i++) {
@@ -549,12 +549,12 @@ void arch_getdomaininfo_ctxt(struct vcpu
        er->iva = v->arch.iva;
 }
 
-int arch_set_info_guest(struct vcpu *v, struct vcpu_guest_context *c)
+int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c)
 {
        struct pt_regs *regs = vcpu_regs (v);
        struct domain *d = v->domain;
        
-       *regs = c->user_regs;
+       *regs = c.nat->user_regs;
        
        if (!d->arch.is_vti) {
                /* domain runs at PL2/3 */
@@ -562,9 +562,9 @@ int arch_set_info_guest(struct vcpu *v, 
                regs->ar_rsc |= (2 << 2); /* force PL2/3 */
        }
 
-       if (c->flags & VGCF_EXTRA_REGS) {
+       if (c.nat->flags & VGCF_EXTRA_REGS) {
                int i;
-               struct vcpu_extra_regs *er = &c->extra_regs;
+               struct vcpu_extra_regs *er = &c.nat->extra_regs;
 
                for (i = 0; i < 8; i++) {
                        vcpu_set_itr(v, i, er->itrs[i].pte,
diff -r d80684d19ef4 -r 5442b2458e1b xen/arch/powerpc/domain.c
--- a/xen/arch/powerpc/domain.c Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/arch/powerpc/domain.c Fri Jan 05 17:34:39 2007 +0000
@@ -150,9 +150,9 @@ void vcpu_destroy(struct vcpu *v)
 {
 }
 
-int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_t *c)
+int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c)
 { 
-    memcpy(&v->arch.ctxt, &c->user_regs, sizeof(c->user_regs));
+    memcpy(&v->arch.ctxt, &c.nat->user_regs, sizeof(c.nat->user_regs));
 
     printk("Domain[%d].%d: initializing\n",
            v->domain->domain_id, v->vcpu_id);
diff -r d80684d19ef4 -r 5442b2458e1b xen/arch/powerpc/domctl.c
--- a/xen/arch/powerpc/domctl.c Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/arch/powerpc/domctl.c Fri Jan 05 17:34:39 2007 +0000
@@ -22,6 +22,7 @@
 #include <xen/types.h>
 #include <xen/lib.h>
 #include <xen/sched.h>
+#include <xen/domain.h>
 #include <xen/guest_access.h>
 #include <xen/shadow.h>
 #include <public/xen.h>
@@ -29,10 +30,9 @@
 #include <public/sysctl.h>
 #include <asm/processor.h>
 
-void arch_getdomaininfo_ctxt(struct vcpu *, vcpu_guest_context_t *);
-void arch_getdomaininfo_ctxt(struct vcpu *v, vcpu_guest_context_t *c)
+void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c)
 { 
-    memcpy(&c->user_regs, &v->arch.ctxt, sizeof(struct cpu_user_regs));
+    memcpy(&c.nat->user_regs, &v->arch.ctxt, sizeof(struct cpu_user_regs));
     /* XXX fill in rest of vcpu_guest_context_t */
 }
 
diff -r d80684d19ef4 -r 5442b2458e1b xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/arch/x86/domain.c     Fri Jan 05 17:34:39 2007 +0000
@@ -16,6 +16,7 @@
 #include <xen/lib.h>
 #include <xen/errno.h>
 #include <xen/sched.h>
+#include <xen/domain.h>
 #include <xen/smp.h>
 #include <xen/delay.h>
 #include <xen/softirq.h>
@@ -250,6 +251,69 @@ static void release_compat_l4(struct vcp
     v->arch.guest_table_user = pagetable_null();
 }
 
+static inline int may_switch_mode(struct domain *d)
+{
+    return 1; /* XXX */
+}
+
+int switch_native(struct domain *d)
+{
+    l1_pgentry_t gdt_l1e;
+    unsigned int vcpuid;
+
+    if ( !d )
+        return -EINVAL;
+    if ( !may_switch_mode(d) )
+        return -EACCES;
+    if ( !IS_COMPAT(d) )
+        return 0;
+
+    clear_bit(_DOMF_compat, &d->domain_flags);
+    release_arg_xlat_area(d);
+
+    /* switch gdt */
+    gdt_l1e = l1e_from_page(virt_to_page(gdt_table), PAGE_HYPERVISOR);
+    for ( vcpuid = 0; vcpuid < MAX_VIRT_CPUS; vcpuid++ )
+    {
+        d->arch.mm_perdomain_pt[((vcpuid << GDT_LDT_VCPU_SHIFT) +
+                                 FIRST_RESERVED_GDT_PAGE)] = gdt_l1e;
+        if (d->vcpu[vcpuid])
+            release_compat_l4(d->vcpu[vcpuid]);
+    }
+
+    return 0;
+}
+
+int switch_compat(struct domain *d)
+{
+    l1_pgentry_t gdt_l1e;
+    unsigned int vcpuid;
+
+    if ( !d )
+        return -EINVAL;
+    if ( compat_disabled )
+        return -ENOSYS;
+    if ( !may_switch_mode(d) )
+        return -EACCES;
+    if ( IS_COMPAT(d) )
+        return 0;
+
+    set_bit(_DOMF_compat, &d->domain_flags);
+
+    /* switch gdt */
+    gdt_l1e = l1e_from_page(virt_to_page(compat_gdt_table), PAGE_HYPERVISOR);
+    for ( vcpuid = 0; vcpuid < MAX_VIRT_CPUS; vcpuid++ )
+    {
+        d->arch.mm_perdomain_pt[((vcpuid << GDT_LDT_VCPU_SHIFT) +
+                                 FIRST_RESERVED_GDT_PAGE)] = gdt_l1e;
+        if (d->vcpu[vcpuid]
+            && setup_compat_l4(d->vcpu[vcpuid]) != 0)
+            return -ENOMEM;
+    }
+
+    return 0;
+}
+
 #else
 #define release_arg_xlat_area(d) ((void)0)
 #define setup_compat_l4(v) 0
@@ -416,43 +480,80 @@ void arch_domain_destroy(struct domain *
 
 /* This is called by arch_final_setup_guest and do_boot_vcpu */
 int arch_set_info_guest(
-    struct vcpu *v, struct vcpu_guest_context *c)
+    struct vcpu *v, vcpu_guest_context_u c)
 {
     struct domain *d = v->domain;
+#ifdef CONFIG_COMPAT
+#define c(fld) (!IS_COMPAT(d) ? (c.nat->fld) : (c.cmp->fld))
+#else
+#define c(fld) (c.nat->fld)
+#endif
     unsigned long cr3_pfn = INVALID_MFN;
+    unsigned long flags = c(flags);
     int i, rc;
 
     if ( !is_hvm_vcpu(v) )
     {
-        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(d, c->trap_ctxt[i].cs);
-
-        /* LDT safety checks. */
-        if ( ((c->ldt_base & (PAGE_SIZE-1)) != 0) || 
-             (c->ldt_ents > 8192) ||
-             !array_access_ok(c->ldt_base, c->ldt_ents, LDT_ENTRY_SIZE) )
-            return -EINVAL;
+        if ( !IS_COMPAT(d) )
+        {
+            fixup_guest_stack_selector(d, c.nat->user_regs.ss);
+            fixup_guest_stack_selector(d, c.nat->kernel_ss);
+            fixup_guest_code_selector(d, c.nat->user_regs.cs);
+#ifdef __i386__
+            fixup_guest_code_selector(d, c.nat->event_callback_cs);
+            fixup_guest_code_selector(d, c.nat->failsafe_callback_cs);
+#endif
+
+            for ( i = 0; i < 256; i++ )
+                fixup_guest_code_selector(d, c.nat->trap_ctxt[i].cs);
+
+            /* LDT safety checks. */
+            if ( ((c.nat->ldt_base & (PAGE_SIZE-1)) != 0) ||
+                 (c.nat->ldt_ents > 8192) ||
+                 !array_access_ok(c.nat->ldt_base,
+                                  c.nat->ldt_ents,
+                                  LDT_ENTRY_SIZE) )
+                return -EINVAL;
+        }
+#ifdef CONFIG_COMPAT
+        else
+        {
+            fixup_guest_stack_selector(d, c.cmp->user_regs.ss);
+            fixup_guest_stack_selector(d, c.cmp->kernel_ss);
+            fixup_guest_code_selector(d, c.cmp->user_regs.cs);
+            fixup_guest_code_selector(d, c.cmp->event_callback_cs);
+            fixup_guest_code_selector(d, c.cmp->failsafe_callback_cs);
+
+            for ( i = 0; i < 256; i++ )
+                fixup_guest_code_selector(d, c.cmp->trap_ctxt[i].cs);
+
+            /* LDT safety checks. */
+            if ( ((c.cmp->ldt_base & (PAGE_SIZE-1)) != 0) ||
+                 (c.cmp->ldt_ents > 8192) ||
+                 !compat_array_access_ok(c.cmp->ldt_base,
+                                         c.cmp->ldt_ents,
+                                         LDT_ENTRY_SIZE) )
+                return -EINVAL;
+        }
+#endif
     }
 
     clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags);
-    if ( c->flags & VGCF_i387_valid )
+    if ( flags & VGCF_I387_VALID )
         set_bit(_VCPUF_fpu_initialised, &v->vcpu_flags);
 
     v->arch.flags &= ~TF_kernel_mode;
-    if ( (c->flags & VGCF_in_kernel) || is_hvm_vcpu(v)/*???*/ )
+    if ( (flags & VGCF_in_kernel) || is_hvm_vcpu(v)/*???*/ )
         v->arch.flags |= TF_kernel_mode;
 
-    memcpy(&v->arch.guest_context, c, sizeof(*c));
+    if ( !IS_COMPAT(v->domain) )
+        memcpy(&v->arch.guest_context, c.nat, sizeof(*c.nat));
+#ifdef CONFIG_COMPAT
+    else
+    {
+        XLAT_vcpu_guest_context(&v->arch.guest_context, c.cmp);
+    }
+#endif
 
     /* Only CR0.TS is modifiable by guest or admin. */
     v->arch.guest_context.ctrlreg[0] &= X86_CR0_TS;
@@ -480,19 +581,34 @@ int arch_set_info_guest(
     memset(v->arch.guest_context.debugreg, 0,
            sizeof(v->arch.guest_context.debugreg));
     for ( i = 0; i < 8; i++ )
-        (void)set_debugreg(v, i, c->debugreg[i]);
+        (void)set_debugreg(v, i, c(debugreg[i]));
 
     if ( v->vcpu_id == 0 )
-        d->vm_assist = c->vm_assist;
+        d->vm_assist = c(vm_assist);
 
     if ( !is_hvm_vcpu(v) )
     {
-        if ( (rc = (int)set_gdt(v, c->gdt_frames, c->gdt_ents)) != 0 )
+        if ( !IS_COMPAT(d) )
+            rc = (int)set_gdt(v, c.nat->gdt_frames, c.nat->gdt_ents);
+#ifdef CONFIG_COMPAT
+        else
+        {
+            unsigned long gdt_frames[ARRAY_SIZE(c.cmp->gdt_frames)];
+            unsigned int i, n = (c.cmp->gdt_ents + 511) / 512;
+
+            if ( n > ARRAY_SIZE(c.cmp->gdt_frames) )
+                return -EINVAL;
+            for ( i = 0; i < n; ++i )
+                gdt_frames[i] = c.cmp->gdt_frames[i];
+            rc = (int)set_gdt(v, gdt_frames, c.cmp->gdt_ents);
+        }
+#endif
+        if ( rc != 0 )
             return rc;
 
         if ( !IS_COMPAT(d) )
         {
-            cr3_pfn = gmfn_to_mfn(d, xen_cr3_to_pfn(c->ctrlreg[3]));
+            cr3_pfn = gmfn_to_mfn(d, xen_cr3_to_pfn(c.nat->ctrlreg[3]));
 
             if ( shadow_mode_refcounts(d)
                  ? !get_page(mfn_to_page(cr3_pfn), d)
@@ -510,7 +626,7 @@ int arch_set_info_guest(
         {
             l4_pgentry_t *l4tab;
 
-            cr3_pfn = gmfn_to_mfn(d, compat_cr3_to_pfn(c->ctrlreg[3]));
+            cr3_pfn = gmfn_to_mfn(d, compat_cr3_to_pfn(c.cmp->ctrlreg[3]));
 
             if ( shadow_mode_refcounts(d)
                  ? !get_page(mfn_to_page(cr3_pfn), d)
@@ -539,6 +655,7 @@ int arch_set_info_guest(
     update_cr3(v);
 
     return 0;
+#undef c
 }
 
 long
diff -r d80684d19ef4 -r 5442b2458e1b xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c     Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/arch/x86/domctl.c     Fri Jan 05 17:34:39 2007 +0000
@@ -11,6 +11,7 @@
 #include <xen/guest_access.h>
 #include <public/domctl.h>
 #include <xen/sched.h>
+#include <xen/domain.h>
 #include <xen/event.h>
 #include <xen/domain_page.h>
 #include <asm/msr.h>
@@ -23,12 +24,21 @@
 #include <asm/hvm/support.h>
 #include <asm/processor.h>
 #include <public/hvm/e820.h>
-
-long arch_do_domctl(
+#ifdef CONFIG_COMPAT
+#include <compat/xen.h>
+#endif
+
+#ifndef COMPAT
+#define _long                long
+#define copy_from_xxx_offset copy_from_guest_offset
+#define copy_to_xxx_offset   copy_to_guest_offset
+#endif
+
+_long arch_do_domctl(
     struct xen_domctl *domctl,
     XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
 {
-    long ret = 0;
+    _long ret = 0;
 
     switch ( domctl->cmd )
     {
@@ -40,7 +50,9 @@ long arch_do_domctl(
         d = find_domain_by_id(domctl->domain);
         if ( d != NULL )
         {
-            ret = shadow_domctl(d, &domctl->u.shadow_op, u_domctl);
+            ret = shadow_domctl(d,
+                                &domctl->u.shadow_op,
+                                guest_handle_cast(u_domctl, void));
             put_domain(d);
             copy_to_guest(u_domctl, domctl, 1);
         } 
@@ -123,12 +135,12 @@ long arch_do_domctl(
 
     case XEN_DOMCTL_getpageframeinfo2:
     {
-#define GPF2_BATCH (PAGE_SIZE / sizeof(long))
+#define GPF2_BATCH (PAGE_SIZE / sizeof(_long))
         int n,j;
         int num = domctl->u.getpageframeinfo2.num;
         domid_t dom = domctl->domain;
         struct domain *d;
-        unsigned long *l_arr;
+        unsigned _long *l_arr;
         ret = -ESRCH;
 
         if ( unlikely((d = find_domain_by_id(dom)) == NULL) )
@@ -148,9 +160,9 @@ long arch_do_domctl(
         {
             int k = ((num-n)>GPF2_BATCH)?GPF2_BATCH:(num-n);
 
-            if ( copy_from_guest_offset(l_arr,
-                                        domctl->u.getpageframeinfo2.array,
-                                        n, k) )
+            if ( copy_from_xxx_offset(l_arr,
+                                      domctl->u.getpageframeinfo2.array,
+                                      n, k) )
             {
                 ret = -EINVAL;
                 break;
@@ -159,13 +171,13 @@ long arch_do_domctl(
             for ( j = 0; j < k; j++ )
             {      
                 struct page_info *page;
-                unsigned long mfn = l_arr[j];
+                unsigned _long mfn = l_arr[j];
 
                 page = mfn_to_page(mfn);
 
                 if ( likely(mfn_valid(mfn) && get_page(page, d)) ) 
                 {
-                    unsigned long type = 0;
+                    unsigned _long type = 0;
 
                     switch( page->u.inuse.type_info & PGT_type_mask )
                     {
@@ -193,8 +205,8 @@ long arch_do_domctl(
 
             }
 
-            if ( copy_to_guest_offset(domctl->u.getpageframeinfo2.array,
-                                      n, l_arr, k) )
+            if ( copy_to_xxx_offset(domctl->u.getpageframeinfo2.array,
+                                    n, l_arr, k) )
             {
                 ret = -EINVAL;
                 break;
@@ -214,7 +226,7 @@ long arch_do_domctl(
         int i;
         struct domain *d = find_domain_by_id(domctl->domain);
         unsigned long max_pfns = domctl->u.getmemlist.max_pfns;
-        unsigned long mfn;
+        xen_pfn_t mfn;
         struct list_head *list_ent;
 
         ret = -EINVAL;
@@ -229,8 +241,8 @@ long arch_do_domctl(
             {
                 mfn = page_to_mfn(list_entry(
                     list_ent, struct page_info, list));
-                if ( copy_to_guest_offset(domctl->u.getmemlist.buffer,
-                                          i, &mfn, 1) )
+                if ( copy_to_xxx_offset(domctl->u.getmemlist.buffer,
+                                        i, &mfn, 1) )
                 {
                     ret = -EFAULT;
                     break;
@@ -289,37 +301,68 @@ long arch_do_domctl(
     return ret;
 }
 
-void arch_getdomaininfo_ctxt(
-    struct vcpu *v, struct vcpu_guest_context *c)
+#ifndef COMPAT
+void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c)
 {
-    memcpy(c, &v->arch.guest_context, sizeof(*c));
+#ifdef CONFIG_COMPAT
+#define c(fld) (!IS_COMPAT(v->domain) ? (c.nat->fld) : (c.cmp->fld))
+#else
+#define c(fld) (c.nat->fld)
+#endif
+    unsigned long flags;
+
+    if ( !IS_COMPAT(v->domain) )
+        memcpy(c.nat, &v->arch.guest_context, sizeof(*c.nat));
+#ifdef CONFIG_COMPAT
+    else
+    {
+        XLAT_vcpu_guest_context(c.cmp, &v->arch.guest_context);
+    }
+#endif
 
     if ( is_hvm_vcpu(v) )
     {
-        hvm_store_cpu_guest_regs(v, &c->user_regs, c->ctrlreg);
+        if ( !IS_COMPAT(v->domain) )
+            hvm_store_cpu_guest_regs(v, &c.nat->user_regs, c.nat->ctrlreg);
+#ifdef CONFIG_COMPAT
+        else
+        {
+            struct cpu_user_regs user_regs;
+            typeof(c.nat->ctrlreg) ctrlreg;
+            unsigned i;
+
+            hvm_store_cpu_guest_regs(v, &user_regs, ctrlreg);
+            XLAT_cpu_user_regs(&c.cmp->user_regs, &user_regs);
+            for ( i = 0; i < ARRAY_SIZE(c.cmp->ctrlreg); ++i )
+                c.cmp->ctrlreg[i] = ctrlreg[i];
+        }
+#endif
     }
     else
     {
         /* IOPL privileges are virtualised: merge back into returned eflags. */
-        BUG_ON((c->user_regs.eflags & EF_IOPL) != 0);
-        c->user_regs.eflags |= v->arch.iopl << 12;
-    }
-
-    c->flags = 0;
+        BUG_ON((c(user_regs.eflags) & EF_IOPL) != 0);
+        c(user_regs.eflags |= v->arch.iopl << 12);
+    }
+
+    flags = 0;
     if ( test_bit(_VCPUF_fpu_initialised, &v->vcpu_flags) )
-        c->flags |= VGCF_i387_valid;
+        flags |= VGCF_i387_valid;
     if ( guest_kernel_mode(v, &v->arch.guest_context.user_regs) )
-        c->flags |= VGCF_in_kernel;
+        flags |= VGCF_in_kernel;
+    c(flags = flags);
 
     if ( !IS_COMPAT(v->domain) )
-        c->ctrlreg[3] = xen_pfn_to_cr3(pagetable_get_pfn(v->arch.guest_table));
+        c.nat->ctrlreg[3] = 
xen_pfn_to_cr3(pagetable_get_pfn(v->arch.guest_table));
 #ifdef CONFIG_COMPAT
     else
-        c->ctrlreg[3] = 
compat_pfn_to_cr3(pagetable_get_pfn(v->arch.guest_table));
-#endif
-
-    c->vm_assist = v->domain->vm_assist;
+        c.cmp->ctrlreg[3] = 
compat_pfn_to_cr3(pagetable_get_pfn(v->arch.guest_table));
+#endif
+
+    c(vm_assist = v->domain->vm_assist);
+#undef c
 }
+#endif
 
 /*
  * Local variables:
diff -r d80684d19ef4 -r 5442b2458e1b xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/arch/x86/mm/shadow/common.c   Fri Jan 05 17:34:39 2007 +0000
@@ -3260,7 +3260,7 @@ void shadow_mark_dirty(struct domain *d,
 
 int shadow_domctl(struct domain *d, 
                   xen_domctl_shadow_op_t *sc,
-                  XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
+                  XEN_GUEST_HANDLE(void) u_domctl)
 {
     int rc, preempted = 0;
 
diff -r d80684d19ef4 -r 5442b2458e1b xen/arch/x86/x86_32/traps.c
--- a/xen/arch/x86/x86_32/traps.c       Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/arch/x86/x86_32/traps.c       Fri Jan 05 17:34:39 2007 +0000
@@ -193,7 +193,7 @@ unsigned long do_iret(void)
 
     /*
      * Pop, fix up and restore EFLAGS. We fix up in a local staging area
-     * to avoid firing the BUG_ON(IOPL) check in arch_getdomaininfo_ctxt.
+     * to avoid firing the BUG_ON(IOPL) check in arch_get_info_guest.
      */
     if ( unlikely(__copy_from_user(&eflags, (void __user *)regs->esp, 4)) )
         goto exit_and_crash;
diff -r d80684d19ef4 -r 5442b2458e1b xen/arch/x86/x86_64/Makefile
--- a/xen/arch/x86/x86_64/Makefile      Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/arch/x86/x86_64/Makefile      Fri Jan 05 17:34:39 2007 +0000
@@ -5,6 +5,7 @@ obj-y += traps.o
 
 obj-$(CONFIG_COMPAT) += compat.o
 obj-$(CONFIG_COMPAT) += domain.o
+obj-$(CONFIG_COMPAT) += domctl.o
 obj-$(CONFIG_COMPAT) += physdev.o
 obj-$(CONFIG_COMPAT) += platform_hypercall.o
 obj-$(CONFIG_COMPAT) += sysctl.o
@@ -12,6 +13,7 @@ ifeq ($(CONFIG_COMPAT),y)
 ifeq ($(CONFIG_COMPAT),y)
 # extra dependencies
 compat.o:      ../compat.c
+domctl.o:      ../domctl.c
 entry.o:       compat/entry.S
 mm.o:          compat/mm.c
 physdev.o:     ../physdev.c
diff -r d80684d19ef4 -r 5442b2458e1b xen/arch/x86/x86_64/compat/entry.S
--- a/xen/arch/x86/x86_64/compat/entry.S        Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/arch/x86/x86_64/compat/entry.S        Fri Jan 05 17:34:39 2007 +0000
@@ -278,8 +278,6 @@ CFIX14:
 
 .section .rodata, "a", @progbits
 
-#define compat_domctl domain_crash_synchronous
-
 ENTRY(compat_hypercall_table)
         .quad compat_set_trap_table     /*  0 */
         .quad do_mmu_update
diff -r d80684d19ef4 -r 5442b2458e1b xen/arch/x86/x86_64/compat/traps.c
--- a/xen/arch/x86/x86_64/compat/traps.c        Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/arch/x86/x86_64/compat/traps.c        Fri Jan 05 17:34:39 2007 +0000
@@ -49,7 +49,7 @@ unsigned int compat_iret(void)
 
     /*
      * Fix up and restore EFLAGS. We fix up in a local staging area
-     * to avoid firing the BUG_ON(IOPL) check in arch_getdomaininfo_ctxt.
+     * to avoid firing the BUG_ON(IOPL) check in arch_get_info_guest.
      */
     if ( unlikely(__get_user(eflags, (u32 __user *)regs->rsp + 3)) )
         goto exit_and_crash;
diff -r d80684d19ef4 -r 5442b2458e1b xen/arch/x86/x86_64/domctl.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/x86_64/domctl.c      Fri Jan 05 17:34:39 2007 +0000
@@ -0,0 +1,111 @@
+/******************************************************************************
+ * Arch-specific compatibility domctl.c
+ */
+
+#include <xen/config.h>
+#include <compat/domctl.h>
+#include <xen/guest_access.h>
+#include <asm/shadow.h>
+
+DEFINE_XEN_GUEST_HANDLE(compat_domctl_t);
+#define xen_domctl                     compat_domctl
+#define xen_domctl_t                   compat_domctl_t
+#define arch_do_domctl(x, h)           arch_compat_domctl(x, _##h)
+
+static int compat_shadow_domctl(struct domain *d,
+                                compat_domctl_shadow_op_t *csc,
+                                XEN_GUEST_HANDLE(void) u_domctl)
+{
+    xen_domctl_shadow_op_t nsc;
+    int rc, mode;
+
+#define XLAT_domctl_shadow_op_HNDL_dirty_bitmap(_d_, _s_) \
+    do \
+    { \
+        if ( (_s_)->op != XEN_DOMCTL_SHADOW_OP_CLEAN \
+             && (_s_)->op != XEN_DOMCTL_SHADOW_OP_PEEK ) \
+        { \
+            set_xen_guest_handle((_d_)->dirty_bitmap, NULL); \
+            mode = -1; \
+        } \
+        else if ( compat_handle_is_null((_s_)->dirty_bitmap) \
+                  || (((_s_)->pages - 1) \
+                      & (BITS_PER_LONG - COMPAT_BITS_PER_LONG)) \
+                     == BITS_PER_LONG - COMPAT_BITS_PER_LONG ) \
+        { \
+            XEN_GUEST_HANDLE(void) tmp; \
+            guest_from_compat_handle(tmp, (_s_)->dirty_bitmap); \
+            (_d_)->dirty_bitmap = guest_handle_cast(tmp, ulong); \
+            mode = 0; \
+        } \
+        else if ( (_s_)->pages > COMPAT_ARG_XLAT_SIZE * 8 ) \
+        { \
+            printk("Cannot translate compatibility mode 
XEN_DOMCTL_SHADOW_OP_{CLEAN,PEEK} (0x%lX)\n", \
+                   (_s_)->pages); \
+            return -E2BIG; \
+        } \
+        else \
+        { \
+            set_xen_guest_handle((_d_)->dirty_bitmap, \
+                                 (void 
*)COMPAT_ARG_XLAT_VIRT_START(current->vcpu_id)); \
+            mode = 1; \
+        } \
+    } while (0)
+    XLAT_domctl_shadow_op(&nsc, csc);
+#undef XLAT_domctl_shadow_op_HNDL_dirty_bitmap
+    rc = shadow_domctl(d, &nsc, u_domctl);
+    if ( rc != __HYPERVISOR_domctl )
+    {
+        BUG_ON(rc > 0);
+#define XLAT_domctl_shadow_op_HNDL_dirty_bitmap(_d_, _s_) \
+        do \
+        { \
+            if ( rc == 0 \
+                 && mode > 0 \
+                 && copy_to_compat((_d_)->dirty_bitmap, \
+                                   (unsigned int *)(_s_)->dirty_bitmap.p, \
+                                   ((_s_)->pages + COMPAT_BITS_PER_LONG - 1) / 
COMPAT_BITS_PER_LONG) ) \
+                rc = -EFAULT; \
+        } while (0)
+        XLAT_domctl_shadow_op(csc, &nsc);
+#undef XLAT_domctl_shadow_op_HNDL_dirty_bitmap
+    }
+    return rc;
+}
+#define xen_domctl_shadow_op           compat_domctl_shadow_op
+#define xen_domctl_shadow_op_t         compat_domctl_shadow_op_t
+#define shadow_domctl(d, sc, u)        compat_shadow_domctl(d, sc, u)
+
+#define xen_domctl_ioport_permission   compat_domctl_ioport_permission
+#define xen_domctl_ioport_permission_t compat_domctl_ioport_permission_t
+
+#define xen_domctl_getpageframeinfo    compat_domctl_getpageframeinfo
+#define xen_domctl_getpageframeinfo_t  compat_domctl_getpageframeinfo_t
+
+#define xen_domctl_getpageframeinfo2   compat_domctl_getpageframeinfo2
+#define xen_domctl_getpageframeinfo2_t compat_domctl_getpageframeinfo2_t
+
+#define xen_domctl_getmemlist          compat_domctl_getmemlist
+#define xen_domctl_getmemlist_t        compat_domctl_getmemlist_t
+#define xen_pfn_t                      compat_pfn_t
+
+#define xen_domctl_hypercall_init      compat_domctl_hypercall_init
+#define xen_domctl_hypercall_init_t    compat_domctl_hypercall_init_t
+
+#define COMPAT
+#define _XEN_GUEST_HANDLE(t)           XEN_GUEST_HANDLE(t)
+#define _long                          int
+#define copy_from_xxx_offset           copy_from_compat_offset
+#define copy_to_xxx_offset             copy_to_compat_offset
+
+#include "../domctl.c"
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d80684d19ef4 -r 5442b2458e1b xen/common/compat/Makefile
--- a/xen/common/compat/Makefile        Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/common/compat/Makefile        Fri Jan 05 17:34:39 2007 +0000
@@ -1,4 +1,5 @@ obj-y += domain.o
 obj-y += domain.o
+obj-y += domctl.o
 obj-y += kernel.o
 obj-y += memory.o
 obj-y += multicall.o
@@ -6,6 +7,7 @@ obj-y += xlat.o
 obj-y += xlat.o
 
 # extra dependencies
+domctl.o:      ../domctl.c
 kernel.o:      ../kernel.c
 multicall.o:   ../multicall.c
 sysctl.o:      ../sysctl.c
diff -r d80684d19ef4 -r 5442b2458e1b xen/common/compat/domain.c
--- a/xen/common/compat/domain.c        Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/common/compat/domain.c        Fri Jan 05 17:34:39 2007 +0000
@@ -28,7 +28,6 @@ int compat_vcpu_op(int cmd, int vcpuid, 
     case VCPUOP_initialise:
     {
         struct compat_vcpu_guest_context *cmp_ctxt;
-        struct vcpu_guest_context *nat_ctxt;
 
         if ( (cmp_ctxt = xmalloc(struct compat_vcpu_guest_context)) == NULL )
         {
@@ -43,23 +42,13 @@ int compat_vcpu_op(int cmd, int vcpuid, 
             break;
         }
 
-        if ( (nat_ctxt = xmalloc(struct vcpu_guest_context)) == NULL )
-        {
-            rc = -ENOMEM;
-            break;
-        }
-
-        memset(nat_ctxt, 0, sizeof(*nat_ctxt));
-        XLAT_vcpu_guest_context(nat_ctxt, cmp_ctxt);
-        xfree(cmp_ctxt);
-
         LOCK_BIGLOCK(d);
         rc = -EEXIST;
         if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
-            rc = boot_vcpu(d, vcpuid, nat_ctxt);
+            rc = boot_vcpu(d, vcpuid, cmp_ctxt);
         UNLOCK_BIGLOCK(d);
 
-        xfree(nat_ctxt);
+        xfree(cmp_ctxt);
         break;
     }
 
diff -r d80684d19ef4 -r 5442b2458e1b xen/common/compat/domctl.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/common/compat/domctl.c        Fri Jan 05 17:34:39 2007 +0000
@@ -0,0 +1,137 @@
+/******************************************************************************
+ * compat/domctl.c
+ */
+
+#include <xen/config.h>
+#include <compat/domctl.h>
+#include <xen/sched.h>
+#include <xen/cpumask.h>
+#include <asm/uaccess.h>
+
+DEFINE_XEN_GUEST_HANDLE(compat_domctl_t);
+#define xen_domctl                     compat_domctl
+#define xen_domctl_t                   compat_domctl_t
+#define do_domctl(h)                   compat_domctl(_##h)
+#define arch_do_domctl(x, h)           arch_compat_domctl(x, _##h)
+
+#define xen_domain_handle_t            compat_domain_handle_t
+
+#define xen_domctl_vcpucontext         compat_domctl_vcpucontext
+#define xen_domctl_vcpucontext_t       compat_domctl_vcpucontext_t
+
+#define xen_domctl_createdomain        compat_domctl_createdomain
+#define xen_domctl_createdomain_t      compat_domctl_createdomain_t
+
+#define xen_domctl_max_vcpus           compat_domctl_max_vcpus
+#define xen_domctl_max_vcpus_t         compat_domctl_max_vcpus_t
+
+static void cpumask_to_compat_ctl_cpumap(
+    struct compat_ctl_cpumap *cmpctl_cpumap, cpumask_t *cpumask)
+{
+    unsigned int guest_bytes, copy_bytes, i;
+    /*static const*/ uint8_t zero = 0;
+
+    if ( compat_handle_is_null(cmpctl_cpumap->bitmap) )
+        return;
+
+    guest_bytes = (cmpctl_cpumap->nr_cpus + 7) / 8;
+    copy_bytes  = min_t(unsigned int, guest_bytes, (NR_CPUS + 7) / 8);
+
+    copy_to_compat(cmpctl_cpumap->bitmap,
+                   (uint8_t *)cpus_addr(*cpumask),
+                   copy_bytes);
+
+    for ( i = copy_bytes; i < guest_bytes; i++ )
+        copy_to_compat_offset(cmpctl_cpumap->bitmap, i, &zero, 1);
+}
+#define cpumask_to_xenctl_cpumap       cpumask_to_compat_ctl_cpumap
+
+void compat_ctl_cpumap_to_cpumask(
+    cpumask_t *cpumask, struct compat_ctl_cpumap *cmpctl_cpumap)
+{
+    unsigned int guest_bytes, copy_bytes;
+
+    guest_bytes = (cmpctl_cpumap->nr_cpus + 7) / 8;
+    copy_bytes  = min_t(unsigned int, guest_bytes, (NR_CPUS + 7) / 8);
+
+    cpus_clear(*cpumask);
+
+    if ( compat_handle_is_null(cmpctl_cpumap->bitmap) )
+        return;
+
+    copy_from_compat((uint8_t *)cpus_addr(*cpumask),
+                     cmpctl_cpumap->bitmap,
+                     copy_bytes);
+}
+#define xenctl_cpumap_to_cpumask       compat_ctl_cpumap_to_cpumask
+
+#define xen_domctl_vcpuaffinity        compat_domctl_vcpuaffinity
+#define xen_domctl_vcpuaffinity_t      compat_domctl_vcpuaffinity_t
+
+static int compat_sched_adjust(struct domain *d,
+                               struct compat_domctl_scheduler_op *cop)
+{
+    struct xen_domctl_scheduler_op nop;
+    int ret;
+    enum XLAT_domctl_scheduler_op_u u;
+
+    switch ( cop->sched_id )
+    {
+    case XEN_SCHEDULER_SEDF:   u = XLAT_domctl_scheduler_op_u_sedf;   break;
+    case XEN_SCHEDULER_CREDIT: u = XLAT_domctl_scheduler_op_u_credit; break;
+    default: return -EINVAL;
+    }
+    XLAT_domctl_scheduler_op(&nop, cop);
+    ret = sched_adjust(d, &nop);
+    XLAT_domctl_scheduler_op(cop, &nop);
+
+    return ret;
+}
+#define sched_adjust(d, op)            compat_sched_adjust(d, op)
+#define xen_domctl_scheduler_op        compat_domctl_scheduler_op
+#define xen_domctl_scheduler_op_t      compat_domctl_scheduler_op_t
+
+#define xen_domctl_getdomaininfo       compat_domctl_getdomaininfo
+#define xen_domctl_getdomaininfo_t     compat_domctl_getdomaininfo_t
+#define getdomaininfo(d, i)            compat_getdomaininfo(d, i)
+
+#define xen_domctl_getvcpuinfo         compat_domctl_getvcpuinfo
+#define xen_domctl_getvcpuinfo_t       compat_domctl_getvcpuinfo_t
+
+#define xen_domctl_max_mem             compat_domctl_max_mem
+#define xen_domctl_max_mem_t           compat_domctl_max_mem_t
+
+#define xen_domctl_setdomainhandle     compat_domctl_setdomainhandle
+#define xen_domctl_setdomainhandle_t   compat_domctl_setdomainhandle_t
+
+#define xen_domctl_setdebugging        compat_domctl_setdebugging
+#define xen_domctl_setdebugging_t      compat_domctl_setdebugging_t
+
+#define xen_domctl_irq_permission      compat_domctl_irq_permission
+#define xen_domctl_irq_permission_t    compat_domctl_irq_permission_t
+
+#define xen_domctl_iomem_permission    compat_domctl_iomem_permission
+#define xen_domctl_iomem_permission_t  compat_domctl_iomem_permission_t
+
+#define xen_domctl_settimeoffset       compat_domctl_settimeoffset
+#define xen_domctl_settimeoffset_t     compat_domctl_settimeoffset_t
+
+#define COMPAT
+#define _XEN_GUEST_HANDLE(t)           XEN_GUEST_HANDLE(t)
+#define _u_domctl                      u_domctl
+//#undef guest_handle_cast
+//#define guest_handle_cast              compat_handle_cast
+//#define copy_to_xxx_offset             copy_to_compat_offset
+typedef int ret_t;
+
+#include "../domctl.c"
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d80684d19ef4 -r 5442b2458e1b xen/common/compat/sysctl.c
--- a/xen/common/compat/sysctl.c        Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/common/compat/sysctl.c        Fri Jan 05 17:34:39 2007 +0000
@@ -40,13 +40,6 @@ static int compat_tb_control(struct comp
 #define xen_sysctl_sched_id            compat_sysctl_sched_id
 #define xen_sysctl_sched_id_t          compat_sysctl_sched_id_t
 
-static void compat_getdomaininfo(struct domain *d, struct 
compat_domctl_getdomaininfo *ci)
-{
-    struct xen_domctl_getdomaininfo ni;
-
-    getdomaininfo(d, &ni);
-    XLAT_domctl_getdomaininfo(ci, &ni);
-}
 #define xen_sysctl_getdomaininfolist   compat_sysctl_getdomaininfolist
 #define xen_sysctl_getdomaininfolist_t compat_sysctl_getdomaininfolist_t
 #define xen_domctl_getdomaininfo       compat_domctl_getdomaininfo
diff -r d80684d19ef4 -r 5442b2458e1b xen/common/domain.c
--- a/xen/common/domain.c       Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/common/domain.c       Fri Jan 05 17:34:39 2007 +0000
@@ -26,6 +26,9 @@
 #include <asm/debugger.h>
 #include <public/sched.h>
 #include <public/vcpu.h>
+#ifdef CONFIG_COMPAT
+#include <compat/domctl.h>
+#endif
 
 /* Both these structures are protected by the domlist_lock. */
 DEFINE_RWLOCK(domlist_lock);
@@ -451,32 +454,64 @@ void domain_unpause_by_systemcontroller(
  * the userspace dom0 domain builder.
  */
 int set_info_guest(struct domain *d,
-                   xen_domctl_vcpucontext_t *vcpucontext)
+                   xen_domctl_vcpucontext_u vcpucontext)
 {
     int rc = 0;
-    struct vcpu_guest_context *c = NULL;
-    unsigned long vcpu = vcpucontext->vcpu;
+    vcpu_guest_context_u c;
+#ifdef CONFIG_COMPAT
+    CHECK_FIELD(domctl_vcpucontext, vcpu);
+#endif
+    unsigned long vcpu = vcpucontext.nat->vcpu;
     struct vcpu *v;
 
     if ( (vcpu >= MAX_VIRT_CPUS) || ((v = d->vcpu[vcpu]) == NULL) )
         return -EINVAL;
     
-    if ( (c = xmalloc(struct vcpu_guest_context)) == NULL )
+#ifdef CONFIG_COMPAT
+    BUILD_BUG_ON(sizeof(struct vcpu_guest_context)
+                 < sizeof(struct compat_vcpu_guest_context));
+#endif
+    if ( (c.nat = xmalloc(struct vcpu_guest_context)) == NULL )
         return -ENOMEM;
 
     domain_pause(d);
 
-    rc = -EFAULT;
-    if ( copy_from_guest(c, vcpucontext->ctxt, 1) == 0 )
+    if ( !IS_COMPAT(v->domain) )
+    {
+        if ( !IS_COMPAT(current->domain)
+             ? copy_from_guest(c.nat, vcpucontext.nat->ctxt, 1)
+#ifndef CONFIG_COMPAT
+             : 0 )
+#else
+             : copy_from_guest(c.nat,
+                               compat_handle_cast(vcpucontext.cmp->ctxt,
+                                                  void),
+                               1) )
+#endif
+            rc = -EFAULT;
+    }
+#ifdef CONFIG_COMPAT
+    else
+    {
+        if ( !IS_COMPAT(current->domain)
+             ? copy_from_guest(c.cmp,
+                               guest_handle_cast(vcpucontext.nat->ctxt, void),
+                               1)
+             : copy_from_compat(c.cmp, vcpucontext.cmp->ctxt, 1) )
+            rc = -EFAULT;
+    }
+#endif
+
+    if ( rc == 0 )
         rc = arch_set_info_guest(v, c);
 
     domain_unpause(d);
 
-    xfree(c);
+    xfree(c.nat);
     return rc;
 }
 
-int boot_vcpu(struct domain *d, int vcpuid, struct vcpu_guest_context *ctxt) 
+int boot_vcpu(struct domain *d, int vcpuid, vcpu_guest_context_u ctxt)
 {
     struct vcpu *v = d->vcpu[vcpuid];
 
diff -r d80684d19ef4 -r 5442b2458e1b xen/common/domctl.c
--- a/xen/common/domctl.c       Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/common/domctl.c       Fri Jan 05 17:34:39 2007 +0000
@@ -18,14 +18,22 @@
 #include <xen/console.h>
 #include <xen/iocap.h>
 #include <xen/guest_access.h>
+#ifdef CONFIG_COMPAT
+#include <xen/compat.h>
+#endif
 #include <asm/current.h>
 #include <public/domctl.h>
 #include <acm/acm_hooks.h>
 
-extern long arch_do_domctl(
+#ifndef COMPAT
+typedef long ret_t;
+#define copy_to_xxx_offset copy_to_guest_offset
+#endif
+
+extern ret_t arch_do_domctl(
     struct xen_domctl *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl);
-extern void arch_getdomaininfo_ctxt(
-    struct vcpu *, struct vcpu_guest_context *);
+
+#ifndef COMPAT
 
 void cpumask_to_xenctl_cpumap(
     struct xenctl_cpumap *xenctl_cpumap, cpumask_t *cpumask)
@@ -64,6 +72,8 @@ void xenctl_cpumap_to_cpumask(
                     xenctl_cpumap->bitmap,
                     copy_bytes);
 }
+
+#endif /* COMPAT */
 
 static inline int is_free_domid(domid_t dom)
 {
@@ -169,9 +179,9 @@ static unsigned int default_vcpu0_locati
     return cpu;
 }
 
-long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
+ret_t do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
 {
-    long ret = 0;
+    ret_t ret = 0;
     struct xen_domctl curop, *op = &curop;
     void *ssid = NULL; /* save security ptr between pre and post/fail hooks */
     static DEFINE_SPINLOCK(domctl_lock);
@@ -283,10 +293,35 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
         if ( (d = domain_create(dom, domcr_flags)) == NULL )
             break;
 
+        ret = 0;
+        switch ( (op->u.createdomain.flags >> XEN_DOMCTL_CDF_WORDSIZE_SHIFT)
+                 & XEN_DOMCTL_CDF_WORDSIZE_MASK )
+        {
+        case 0:
+            if ( !IS_COMPAT(current->domain) )
+                op->u.createdomain.flags |= BITS_PER_LONG
+                                            << XEN_DOMCTL_CDF_WORDSIZE_SHIFT;
+#ifdef CONFIG_COMPAT
+            else
+            {
+                op->u.createdomain.flags |= COMPAT_BITS_PER_LONG
+                                            << XEN_DOMCTL_CDF_WORDSIZE_SHIFT;
+        case COMPAT_BITS_PER_LONG:
+                ret = switch_compat(d);
+            }
+#endif
+            break;
+        case BITS_PER_LONG:
+            break;
+        default:
+            ret = -EINVAL;
+            break;
+        }
+        if ( ret )
+            break;
+
         memcpy(d->handle, op->u.createdomain.handle,
                sizeof(xen_domain_handle_t));
-
-        ret = 0;
 
         op->domain = d->domain_id;
         if ( copy_to_guest(u_domctl, op, 1) )
@@ -446,7 +481,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
 
     case XEN_DOMCTL_getvcpucontext:
     { 
-        struct vcpu_guest_context *c;
+        vcpu_guest_context_u       c;
         struct domain             *d;
         struct vcpu               *v;
 
@@ -466,23 +501,48 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
         if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
             goto getvcpucontext_out;
 
+#ifdef CONFIG_COMPAT
+        BUILD_BUG_ON(sizeof(struct vcpu_guest_context)
+                     < sizeof(struct compat_vcpu_guest_context));
+#endif
         ret = -ENOMEM;
-        if ( (c = xmalloc(struct vcpu_guest_context)) == NULL )
+        if ( (c.nat = xmalloc(struct vcpu_guest_context)) == NULL )
             goto getvcpucontext_out;
 
         if ( v != current )
             vcpu_pause(v);
 
-        arch_getdomaininfo_ctxt(v,c);
+        arch_get_info_guest(v, c);
         ret = 0;
 
         if ( v != current )
             vcpu_unpause(v);
 
-        if ( copy_to_guest(op->u.vcpucontext.ctxt, c, 1) )
-            ret = -EFAULT;
-
-        xfree(c);
+        if ( !IS_COMPAT(v->domain) )
+        {
+#ifndef COMPAT
+            if ( copy_to_guest(op->u.vcpucontext.ctxt, c.nat, 1) )
+#else
+            if ( copy_to_guest(compat_handle_cast(op->u.vcpucontext.ctxt,
+                                                  void),
+                               c.nat, 1) )
+#endif
+                ret = -EFAULT;
+        }
+#ifdef CONFIG_COMPAT
+        else
+        {
+#ifndef COMPAT
+            if ( copy_to_guest(guest_handle_cast(op->u.vcpucontext.ctxt, void),
+                               c.cmp, 1) )
+#else
+            if ( copy_to_compat(op->u.vcpucontext.ctxt, c.cmp, 1) )
+#endif
+                ret = -EFAULT;
+        }
+#endif
+
+        xfree(c.nat);
 
         if ( copy_to_guest(u_domctl, op, 1) )
             ret = -EFAULT;
@@ -645,6 +705,16 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
         }
     }
     break;
+
+#ifdef CONFIG_COMPAT
+    case XEN_DOMCTL_set_compat:
+        ret = switch_compat(find_domain_by_id(op->domain));
+        break;
+
+    case XEN_DOMCTL_set_native:
+        ret = switch_native(find_domain_by_id(op->domain));
+        break;
+#endif
 
     default:
         ret = arch_do_domctl(op, u_domctl);
diff -r d80684d19ef4 -r 5442b2458e1b xen/common/schedule.c
--- a/xen/common/schedule.c     Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/common/schedule.c     Fri Jan 05 17:34:39 2007 +0000
@@ -33,8 +33,6 @@
 #include <xen/multicall.h>
 #include <public/sched.h>
 
-extern void arch_getdomaininfo_ctxt(struct vcpu *,
-                                    struct vcpu_guest_context *);
 /* opt_sched: scheduler - default to credit */
 static char opt_sched[10] = "credit";
 string_param("sched", opt_sched);
diff -r d80684d19ef4 -r 5442b2458e1b xen/include/asm-x86/shadow.h
--- a/xen/include/asm-x86/shadow.h      Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/include/asm-x86/shadow.h      Fri Jan 05 17:34:39 2007 +0000
@@ -192,7 +192,7 @@ int shadow_enable(struct domain *d, u32 
  * manipulate the log-dirty bitmap. */
 int shadow_domctl(struct domain *d, 
                   xen_domctl_shadow_op_t *sc,
-                  XEN_GUEST_HANDLE(xen_domctl_t) u_domctl);
+                  XEN_GUEST_HANDLE(void) u_domctl);
 
 /* Call when destroying a domain */
 void shadow_teardown(struct domain *d);
diff -r d80684d19ef4 -r 5442b2458e1b xen/include/public/domctl.h
--- a/xen/include/public/domctl.h       Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/include/public/domctl.h       Fri Jan 05 17:34:39 2007 +0000
@@ -53,6 +53,8 @@ struct xen_domctl_createdomain {
  /* Is this an HVM guest (as opposed to a PV guest)? */
 #define _XEN_DOMCTL_CDF_hvm_guest 0
 #define XEN_DOMCTL_CDF_hvm_guest  (1U<<_XEN_DOMCTL_CDF_hvm_guest)
+#define XEN_DOMCTL_CDF_WORDSIZE_MASK 255
+#define XEN_DOMCTL_CDF_WORDSIZE_SHIFT 24
     uint32_t flags;
 };
 typedef struct xen_domctl_createdomain xen_domctl_createdomain_t;
@@ -392,6 +394,9 @@ typedef struct xen_domctl_real_mode_area
 typedef struct xen_domctl_real_mode_area xen_domctl_real_mode_area_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_real_mode_area_t);
 
+#define XEN_DOMCTL_set_compat        42
+#define XEN_DOMCTL_set_native        43
+
 struct xen_domctl {
     uint32_t cmd;
     uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */
diff -r d80684d19ef4 -r 5442b2458e1b xen/include/xen/compat.h
--- a/xen/include/xen/compat.h  Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/include/xen/compat.h  Fri Jan 05 17:34:39 2007 +0000
@@ -166,6 +166,9 @@ struct vcpu_runstate_info;
 struct vcpu_runstate_info;
 void xlat_vcpu_runstate_info(struct vcpu_runstate_info *);
 
+int switch_compat(struct domain *);
+int switch_native(struct domain *);
+
 #define BITS_PER_GUEST_LONG(d) (!IS_COMPAT(d) ? BITS_PER_LONG : 
COMPAT_BITS_PER_LONG)
 
 #else
diff -r d80684d19ef4 -r 5442b2458e1b xen/include/xen/domain.h
--- a/xen/include/xen/domain.h  Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/include/xen/domain.h  Fri Jan 05 17:34:39 2007 +0000
@@ -2,10 +2,15 @@
 #ifndef __XEN_DOMAIN_H__
 #define __XEN_DOMAIN_H__
 
+typedef union {
+    struct vcpu_guest_context *nat;
+    struct compat_vcpu_guest_context *cmp;
+} vcpu_guest_context_u __attribute__((__transparent_union__));
+
 struct vcpu *alloc_vcpu(
     struct domain *d, unsigned int vcpu_id, unsigned int cpu_id);
 int boot_vcpu(
-    struct domain *d, int vcpuid, struct vcpu_guest_context *ctxt);
+    struct domain *d, int vcpuid, vcpu_guest_context_u ctxt);
 struct vcpu *alloc_idle_vcpu(unsigned int cpu_id);
 
 struct domain *alloc_domain(domid_t domid);
@@ -14,6 +19,9 @@ struct xen_domctl_getdomaininfo;
 struct xen_domctl_getdomaininfo;
 void getdomaininfo(
     struct domain *d, struct xen_domctl_getdomaininfo *info);
+struct compat_domctl_getdomaininfo;
+void compat_getdomaininfo(
+    struct domain *d, struct compat_domctl_getdomaininfo *info);
 
 /*
  * Arch-specifics.
@@ -37,7 +45,8 @@ int arch_domain_create(struct domain *d)
 
 void arch_domain_destroy(struct domain *d);
 
-int arch_set_info_guest(struct vcpu *v, struct vcpu_guest_context *c);
+int arch_set_info_guest(struct vcpu *, vcpu_guest_context_u);
+void arch_get_info_guest(struct vcpu *, vcpu_guest_context_u);
 
 void domain_relinquish_resources(struct domain *d);
 
diff -r d80684d19ef4 -r 5442b2458e1b xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/include/xen/sched.h   Fri Jan 05 17:34:39 2007 +0000
@@ -275,7 +275,13 @@ int construct_dom0(
     unsigned long image_start, unsigned long image_len, 
     unsigned long initrd_start, unsigned long initrd_len,
     char *cmdline);
-int set_info_guest(struct domain *d, xen_domctl_vcpucontext_t *);
+
+typedef union {
+    struct xen_domctl_vcpucontext *nat;
+    struct compat_domctl_vcpucontext *cmp;
+} xen_domctl_vcpucontext_u __attribute__((__transparent_union__));
+
+int set_info_guest(struct domain *d, xen_domctl_vcpucontext_u);
 
 struct domain *find_domain_by_id(domid_t dom);
 void domain_destroy(struct domain *d);
diff -r d80684d19ef4 -r 5442b2458e1b xen/include/xlat.lst
--- a/xen/include/xlat.lst      Fri Jan 05 17:34:38 2007 +0000
+++ b/xen/include/xlat.lst      Fri Jan 05 17:34:39 2007 +0000
@@ -11,7 +11,9 @@
 !      vcpu_guest_context              arch-x86/xen.h
 ?      acm_getdecision                 acm_ops.h
 !      ctl_cpumap                      domctl.h
-!      domctl_getdomaininfo            domctl.h
+!      domctl_scheduler_op             domctl.h
+!      domctl_shadow_op                domctl.h
+!      domctl_shadow_op_stats          domctl.h
 ?      evtchn_alloc_unbound            event_channel.h
 ?      evtchn_bind_interdomain         event_channel.h
 ?      evtchn_bind_ipi                 event_channel.h

_______________________________________________
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®.