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] Enable compatibility mode operation for H

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Enable compatibility mode operation for HYPERVISOR_domctl. Also add logic
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 05 Jan 2007 12:55:32 -0800
Delivery-date: Fri, 05 Jan 2007 13:58:33 -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 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Enable compatibility mode operation for HYPERVISOR_domctl. Also add logic, Xen patchbot-unstable <=