Enable compatibility mode operation for HYPERVISOR_domctl. Also add logic
authorEmmanuel Ackaouy <ack@xensource.com>
Fri, 5 Jan 2007 17:34:39 +0000 (17:34 +0000)
committerEmmanuel Ackaouy <ack@xensource.com>
Fri, 5 Jan 2007 17:34:39 +0000 (17:34 +0000)
to switch a domain to/from compatibility mode (supposed to happen early
after domain creation only).

Signed-off-by: Jan Beulich <jbeulich@novell.com>
24 files changed:
xen/arch/ia64/xen/domain.c
xen/arch/powerpc/domain.c
xen/arch/powerpc/domctl.c
xen/arch/x86/domain.c
xen/arch/x86/domctl.c
xen/arch/x86/mm/shadow/common.c
xen/arch/x86/x86_32/traps.c
xen/arch/x86/x86_64/Makefile
xen/arch/x86/x86_64/compat/entry.S
xen/arch/x86/x86_64/compat/traps.c
xen/arch/x86/x86_64/domctl.c [new file with mode: 0644]
xen/common/compat/Makefile
xen/common/compat/domain.c
xen/common/compat/domctl.c [new file with mode: 0644]
xen/common/compat/sysctl.c
xen/common/domain.c
xen/common/domctl.c
xen/common/schedule.c
xen/include/asm-x86/shadow.h
xen/include/public/domctl.h
xen/include/xen/compat.h
xen/include/xen/domain.h
xen/include/xen/sched.h
xen/include/xlat.lst

index cd43c13d35f144992384e576cc02a5c551f63386..073614f4f6544387a0d4b88744ac6d91848d0c6e 100644 (file)
@@ -522,14 +522,14 @@ void arch_domain_destroy(struct domain *d)
        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;
+       struct vcpu_extra_regs *er = &c.nat->extra_regs;
 
-       c->user_regs = *vcpu_regs (v);
-       c->privregs_pfn = get_gpfn_from_mfn(virt_to_maddr(v->arch.privregs) >>
-                                           PAGE_SHIFT);
+       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 *v, struct vcpu_guest_context *c)
        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, struct vcpu_guest_context *c)
                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,
index 45ed9599452fd86bd96888356b140ac07410fdb3..44665df19754296118bb6140c07e26c63293ed90 100644 (file)
@@ -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_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);
index c51430d1326688a1adad80ede404175aadc3b2bd..20e6e536a800f8e07b8fbf8f26716332f31a82c8 100644 (file)
@@ -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>
 #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 */
 }
 
index 2476271e569be2a1d1865785fbb2c470c1616fe6..acff71b90ff76fca48f697567908d04c06036634 100644 (file)
@@ -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 vcpu *v)
     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 *d)
 
 /* 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) )
+        if ( !IS_COMPAT(d) )
         {
-            fixup_guest_code_selector(d, c->event_callback_cs);
-            fixup_guest_code_selector(d, c->failsafe_callback_cs);
-        }
+            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->trap_ctxt[i].cs);
+            for ( i = 0; i < 256; i++ )
+                fixup_guest_code_selector(d, c.nat->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;
+            /* 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
index 59e03e086c55bc655817b19de74ee221aeb37e54..f1b63ffb66ae260c9d16bc50dee1deb28545c7f3 100644 (file)
@@ -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>
 #include <asm/hvm/support.h>
 #include <asm/processor.h>
 #include <public/hvm/e820.h>
+#ifdef CONFIG_COMPAT
+#include <compat/xen.h>
+#endif
 
-long arch_do_domctl(
+#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;
+        BUG_ON((c(user_regs.eflags) & EF_IOPL) != 0);
+        c(user_regs.eflags |= v->arch.iopl << 12);
     }
 
-    c->flags = 0;
+    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));
+        c.cmp->ctrlreg[3] = compat_pfn_to_cr3(pagetable_get_pfn(v->arch.guest_table));
 #endif
 
-    c->vm_assist = v->domain->vm_assist;
+    c(vm_assist = v->domain->vm_assist);
+#undef c
 }
+#endif
 
 /*
  * Local variables:
index baa57351c85610447ce799bafbf4187a935e989c..318f867ee9ed913a221820e46d1efde2b84722fa 100644 (file)
@@ -3260,7 +3260,7 @@ void shadow_mark_dirty(struct domain *d, mfn_t gmfn)
 
 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;
 
index 3e8c82aba355ea53a274e7b75e6c1376005f6b4a..e6cd085962cd4cf1985d039900275b70fdf29fb2 100644 (file)
@@ -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;
index fad1ca83f290c34a68103a094cef8b8314763589..a2985ff0d30828320b17f924a6d5ddfb9f092102 100644 (file)
@@ -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 @@ obj-$(CONFIG_COMPAT) += sysctl.o
 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
index 0a532d2cedf53559fc2abea0d8ae0cacdb79dc0a..0684d951bce3d51da556c6cab52205daa26a7339 100644 (file)
@@ -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
index 938732ba9fcdb69cab41e1dcd7332c4b602e697a..a7f24cecf88dfda6f63527ab099b2d6b0ec2289c 100644 (file)
@@ -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 --git a/xen/arch/x86/x86_64/domctl.c b/xen/arch/x86/x86_64/domctl.c
new file mode 100644 (file)
index 0000000..4af72ff
--- /dev/null
@@ -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:
+ */
index 2210dd05f909c58b18715c071f8e90e63d99bb2a..ad5ec1b1745805120e13a861af0139012554ecaf 100644 (file)
@@ -1,4 +1,5 @@
 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 += sysctl.o
 obj-y += xlat.o
 
 # extra dependencies
+domctl.o:      ../domctl.c
 kernel.o:      ../kernel.c
 multicall.o:   ../multicall.c
 sysctl.o:      ../sysctl.c
index fbe7602e8d3399d497f0dd7ab99a11df2e8d5e4d..3f5426031695163fec06ecdca142dbe3750efd80 100644 (file)
@@ -28,7 +28,6 @@ int compat_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE(void) arg)
     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, XEN_GUEST_HANDLE(void) arg)
             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 --git a/xen/common/compat/domctl.c b/xen/common/compat/domctl.c
new file mode 100644 (file)
index 0000000..e04e3aa
--- /dev/null
@@ -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:
+ */
index 9aa5fba7832c50e6d5de178579c6fb3d44e9e204..60724435663dc560e6741f21c0c8d875965c7896 100644 (file)
@@ -40,13 +40,6 @@ static int compat_tb_control(struct compat_sysctl_tbuf_op *cmp_tbc)
 #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
index 8afab95a3126cbd61af6eb158639376c65d701ad..28530c40d5bb3c2cb0fbd2a9bd6423e4175aebca 100644 (file)
@@ -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(struct domain *d)
  * the userspace dom0 domain builder.
  */
 int set_info_guest(struct domain *d,
-                   xen_domctl_vcpucontext_t *vcpucontext)
+                   xen_domctl_vcpucontext_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];
 
index b05ecd1099b604cece4bf8276fd7217039b4eff2..b9cd57e9495570e78c37a4f8c0f1e990ea548777 100644 (file)
 #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)
@@ -65,6 +73,8 @@ void xenctl_cpumap_to_cpumask(
                     copy_bytes);
 }
 
+#endif /* COMPAT */
+
 static inline int is_free_domid(domid_t dom)
 {
     struct domain *d;
@@ -169,9 +179,9 @@ static unsigned int default_vcpu0_location(void)
     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,11 +293,36 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         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) )
             ret = -EFAULT;
@@ -446,7 +481,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
 
     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_domctl_t) u_domctl)
         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;
+        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);
+        xfree(c.nat);
 
         if ( copy_to_guest(u_domctl, op, 1) )
             ret = -EFAULT;
@@ -646,6 +706,16 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
     }
     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);
         break;
index 69fbb02634a40e74fece36c32e0ccf843cf02698..55abd5f5caebaff765a37c7dd25bf63b56c9d96b 100644 (file)
@@ -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);
index d9c94010c0443d0d3750a891b9141097fa3cf917..68ae3cb01138d192784f1c2fa8cb6726254d2d14 100644 (file)
@@ -192,7 +192,7 @@ int shadow_enable(struct domain *d, u32 mode);
  * 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);
index 588d4305116eeb1f4cef2a3fd556db29e3ad7f96..d9b23d5b75b28575d29986707e78f3c60ac6729d 100644 (file)
@@ -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 @@ 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 */
index d5b733ec5889f1b415cf99ca129edeb1a7dc604c..06771a1c23cbace76b6f437b6b503af9c373fc23 100644 (file)
@@ -166,6 +166,9 @@ void xlat_start_info(struct start_info *, enum XLAT_start_info_console);
 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
index fd0b3ab0ff5f0bb868eeed426d0c22a1cb01223a..26b2047f5a041fef67c29e7bd2eb0a8d00c0fbac 100644 (file)
@@ -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 @@ void free_domain(struct domain *d);
 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);
 
index 81bb634f205307e635370214c8c3ae75eac1cf14..3e72ea9b31492e2f95d0fbdf5ad2247ebab13adc 100644 (file)
@@ -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);
index 18e0d0c21b6586baf768d4c885efbeb4a307e1f4..566dcc277f7abd2aa73873192401562e1e0d0a3b 100644 (file)
@@ -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