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_memory_op,
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 05 Jan 2007 12:55:22 -0800
Delivery-date: Fri, 05 Jan 2007 14:03:37 -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 1168018471 0
# Node ID 244e46e7d021b1942ace91440c0fdab72a6ce5e4
# Parent  3870aff51ae384163b9ba20db1b5266d89565382
Enable compatibility mode operation for HYPERVISOR_memory_op,
HYPERVISOR_update_descriptor, HYPERVISOR_update_va_mapping. This also
introduces infrastructure to do argument translation.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---
 xen/arch/x86/domain.c              |  287 +++++++++++++++++++++++++----
 xen/arch/x86/domain_build.c        |    4 
 xen/arch/x86/mm.c                  |   13 -
 xen/arch/x86/x86_64/Makefile       |    1 
 xen/arch/x86/x86_64/compat/entry.S |    4 
 xen/arch/x86/x86_64/compat/mm.c    |  148 +++++++++++++++
 xen/arch/x86/x86_64/mm.c           |    3 
 xen/common/compat/Makefile         |    1 
 xen/common/compat/memory.c         |  364 +++++++++++++++++++++++++++++++++++++
 xen/common/memory.c                |   22 --
 xen/include/asm-x86/config.h       |   22 ++
 xen/include/asm-x86/domain.h       |    1 
 xen/include/asm-x86/mm.h           |   10 +
 xen/include/xen/compat.h           |    2 
 xen/include/xen/hypercall.h        |   19 +
 xen/include/xlat.lst               |    6 
 16 files changed, 842 insertions(+), 65 deletions(-)

diff -r 3870aff51ae3 -r 244e46e7d021 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Fri Jan 05 17:34:30 2007 +0000
+++ b/xen/arch/x86/domain.c     Fri Jan 05 17:34:31 2007 +0000
@@ -128,10 +128,98 @@ void free_vcpu_struct(struct vcpu *v)
 }
 
 #ifdef CONFIG_COMPAT
+
+int setup_arg_xlat_area(struct vcpu *v, l4_pgentry_t *l4tab)
+{
+    struct domain *d = v->domain;
+    unsigned i;
+    struct page_info *pg;
+
+    if ( !d->arch.mm_arg_xlat_l3 )
+    {
+        pg = alloc_domheap_page(NULL);
+        if ( !pg )
+            return -ENOMEM;
+        d->arch.mm_arg_xlat_l3 = clear_page(page_to_virt(pg));
+    }
+
+    l4tab[l4_table_offset(COMPAT_ARG_XLAT_VIRT_BASE)] =
+        l4e_from_paddr(__pa(d->arch.mm_arg_xlat_l3), __PAGE_HYPERVISOR);
+
+    for ( i = 0; i < COMPAT_ARG_XLAT_PAGES; ++i )
+    {
+        unsigned long va = COMPAT_ARG_XLAT_VIRT_START(v->vcpu_id) + i * 
PAGE_SIZE;
+        l2_pgentry_t *l2tab;
+        l1_pgentry_t *l1tab;
+
+        if ( !l3e_get_intpte(d->arch.mm_arg_xlat_l3[l3_table_offset(va)]) )
+        {
+            pg = alloc_domheap_page(NULL);
+            if ( !pg )
+                return -ENOMEM;
+            clear_page(page_to_virt(pg));
+            d->arch.mm_arg_xlat_l3[l3_table_offset(va)] = l3e_from_page(pg, 
__PAGE_HYPERVISOR);
+        }
+        l2tab = l3e_to_l2e(d->arch.mm_arg_xlat_l3[l3_table_offset(va)]);
+        if ( !l2e_get_intpte(l2tab[l2_table_offset(va)]) )
+        {
+            pg = alloc_domheap_page(NULL);
+            if ( !pg )
+                return -ENOMEM;
+            clear_page(page_to_virt(pg));
+            l2tab[l2_table_offset(va)] = l2e_from_page(pg, __PAGE_HYPERVISOR);
+        }
+        l1tab = l2e_to_l1e(l2tab[l2_table_offset(va)]);
+        BUG_ON(l1e_get_intpte(l1tab[l1_table_offset(va)]));
+        pg = alloc_domheap_page(NULL);
+        if ( !pg )
+            return -ENOMEM;
+        l1tab[l1_table_offset(va)] = l1e_from_page(pg, PAGE_HYPERVISOR);
+    }
+
+    return 0;
+}
+
+static void release_arg_xlat_area(struct domain *d)
+{
+    if ( d->arch.mm_arg_xlat_l3 )
+    {
+        unsigned l3;
+
+        for ( l3 = 0; l3 < L3_PAGETABLE_ENTRIES; ++l3 )
+        {
+            if ( l3e_get_intpte(d->arch.mm_arg_xlat_l3[l3]) )
+            {
+                l2_pgentry_t *l2tab = l3e_to_l2e(d->arch.mm_arg_xlat_l3[l3]);
+                unsigned l2;
+
+                for ( l2 = 0; l2 < L2_PAGETABLE_ENTRIES; ++l2 )
+                {
+                    if ( l2e_get_intpte(l2tab[l2]) )
+                    {
+                        l1_pgentry_t *l1tab = l2e_to_l1e(l2tab[l2]);
+                        unsigned l1;
+
+                        for ( l1 = 0; l1 < L1_PAGETABLE_ENTRIES; ++l1 )
+                        {
+                            if ( l1e_get_intpte(l1tab[l1]) )
+                                free_domheap_page(l1e_get_page(l1tab[l1]));
+                        }
+                        free_domheap_page(l2e_get_page(l2tab[l2]));
+                    }
+                }
+                free_domheap_page(l3e_get_page(d->arch.mm_arg_xlat_l3[l3]));
+            }
+        }
+        free_domheap_page(virt_to_page(d->arch.mm_arg_xlat_l3));
+    }
+}
+
 static int setup_compat_l4(struct vcpu *v)
 {
     struct page_info *pg = alloc_domheap_page(NULL);
     l4_pgentry_t *l4tab;
+    int rc;
 
     if ( !pg )
         return -ENOMEM;
@@ -143,10 +231,26 @@ static int setup_compat_l4(struct vcpu *
     v->arch.guest_table = pagetable_from_page(pg);
     v->arch.guest_table_user = v->arch.guest_table;
 
+    if ( (rc = setup_arg_xlat_area(v, l4tab)) < 0 )
+    {
+        free_domheap_page(pg);
+        return rc;
+    }
+
     return 0;
 }
+
+static void release_compat_l4(struct vcpu *v)
+{
+    free_domheap_page(pagetable_get_page(v->arch.guest_table));
+    v->arch.guest_table = pagetable_null();
+    v->arch.guest_table_user = pagetable_null();
+}
+
 #else
+#define release_arg_xlat_area(d) ((void)0)
 #define setup_compat_l4(v) 0
+#define release_compat_l4(v) ((void)0)
 #endif
 
 int vcpu_initialise(struct vcpu *v)
@@ -192,7 +296,7 @@ void vcpu_destroy(struct vcpu *v)
 void vcpu_destroy(struct vcpu *v)
 {
     if ( IS_COMPAT(v->domain) )
-        free_domheap_page(pagetable_get_page(v->arch.guest_table));
+        release_compat_l4(v);
 }
 
 int arch_domain_create(struct domain *d)
@@ -300,6 +404,9 @@ void arch_domain_destroy(struct domain *
     free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2));
     free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
 #endif
+
+    if ( IS_COMPAT(d) )
+        release_arg_xlat_area(d);
 
     free_xenheap_page(d->shared_info);
 }
@@ -935,55 +1042,153 @@ unsigned long hypercall_create_continuat
 
         for ( i = 0; *p != '\0'; i++ )
             mcs->call.args[i] = next_arg(p, args);
+        if ( IS_COMPAT(current->domain) )
+        {
+            for ( ; i < 6; i++ )
+                mcs->call.args[i] = 0;
+        }
     }
     else
     {
         regs       = guest_cpu_user_regs();
-#if defined(__i386__)
         regs->eax  = op;
-
-        if ( supervisor_mode_kernel || is_hvm_vcpu(current) )
-            regs->eip &= ~31; /* re-execute entire hypercall entry stub */
+        regs->eip -= 2;  /* re-execute 'syscall' / 'int 0x82' */
+
+#ifdef __x86_64__
+        if ( !IS_COMPAT(current->domain) )
+        {
+            for ( i = 0; *p != '\0'; i++ )
+            {
+                arg = next_arg(p, args);
+                switch ( i )
+                {
+                case 0: regs->rdi = arg; break;
+                case 1: regs->rsi = arg; break;
+                case 2: regs->rdx = arg; break;
+                case 3: regs->r10 = arg; break;
+                case 4: regs->r8  = arg; break;
+                case 5: regs->r9  = arg; break;
+                }
+            }
+        }
         else
-            regs->eip -= 2;   /* re-execute 'int 0x82' */
-
-        for ( i = 0; *p != '\0'; i++ )
-        {
-            arg = next_arg(p, args);
+#endif
+        {
+            if ( supervisor_mode_kernel || is_hvm_vcpu(current) )
+                regs->eip &= ~31; /* re-execute entire hypercall entry stub */
+
+            for ( i = 0; *p != '\0'; i++ )
+            {
+                arg = next_arg(p, args);
+                switch ( i )
+                {
+                case 0: regs->ebx = arg; break;
+                case 1: regs->ecx = arg; break;
+                case 2: regs->edx = arg; break;
+                case 3: regs->esi = arg; break;
+                case 4: regs->edi = arg; break;
+                case 5: regs->ebp = arg; break;
+                }
+            }
+        }
+    }
+
+    va_end(args);
+
+    return op;
+}
+
+#ifdef CONFIG_COMPAT
+int hypercall_xlat_continuation(unsigned int *id, unsigned int mask, ...)
+{
+    int rc = 0;
+    struct mc_state *mcs = &this_cpu(mc_state);
+    struct cpu_user_regs *regs;
+    unsigned int i, cval = 0;
+    unsigned long nval = 0;
+    va_list args;
+
+    BUG_ON(*id > 5);
+    BUG_ON(mask & (1U << *id));
+
+    va_start(args, mask);
+
+    if ( test_bit(_MCSF_in_multicall, &mcs->flags) )
+    {
+        if ( !test_bit(_MCSF_call_preempted, &mcs->flags) )
+            return 0;
+        for ( i = 0; i < 6; ++i, mask >>= 1 )
+        {
+            if ( mask & 1 )
+            {
+                nval = va_arg(args, unsigned long);
+                cval = va_arg(args, unsigned int);
+                if ( cval == nval )
+                    mask &= ~1U;
+                else
+                    BUG_ON(nval == (unsigned int)nval);
+            }
+            else if ( id && *id == i )
+            {
+                *id = mcs->call.args[i];
+                id = NULL;
+            }
+            if ( (mask & 1) && mcs->call.args[i] == nval )
+                ++rc;
+            else
+            {
+                cval = mcs->call.args[i];
+                BUG_ON(mcs->call.args[i] != cval);
+            }
+            mcs->compat_call.args[i] = cval;
+        }
+    }
+    else
+    {
+        regs = guest_cpu_user_regs();
+        for ( i = 0; i < 6; ++i, mask >>= 1 )
+        {
+            unsigned long *reg;
+
             switch ( i )
             {
-            case 0: regs->ebx = arg; break;
-            case 1: regs->ecx = arg; break;
-            case 2: regs->edx = arg; break;
-            case 3: regs->esi = arg; break;
-            case 4: regs->edi = arg; break;
-            case 5: regs->ebp = arg; break;
-            }
-        }
-#elif defined(__x86_64__)
-        regs->rax  = op;
-        regs->rip -= 2;  /* re-execute 'syscall' */
-
-        for ( i = 0; *p != '\0'; i++ )
-        {
-            arg = next_arg(p, args);
-            switch ( i )
-            {
-            case 0: regs->rdi = arg; break;
-            case 1: regs->rsi = arg; break;
-            case 2: regs->rdx = arg; break;
-            case 3: regs->r10 = arg; break;
-            case 4: regs->r8  = arg; break;
-            case 5: regs->r9  = arg; break;
-            }
-        }
+            case 0: reg = &regs->ebx; break;
+            case 1: reg = &regs->ecx; break;
+            case 2: reg = &regs->edx; break;
+            case 3: reg = &regs->esi; break;
+            case 4: reg = &regs->edi; break;
+            case 5: reg = &regs->ebp; break;
+            default: BUG(); reg = NULL; break;
+            }
+            if ( (mask & 1) )
+            {
+                nval = va_arg(args, unsigned long);
+                cval = va_arg(args, unsigned int);
+                if ( cval == nval )
+                    mask &= ~1U;
+                else
+                    BUG_ON(nval == (unsigned int)nval);
+            }
+            else if ( id && *id == i )
+            {
+                *id = *reg;
+                id = NULL;
+            }
+            if ( (mask & 1) && *reg == nval )
+            {
+                *reg = cval;
+                ++rc;
+            }
+            else
+                BUG_ON(*reg != (unsigned int)*reg);
+        }
+    }
+
+    va_end(args);
+
+    return rc;
+}
 #endif
-    }
-
-    va_end(args);
-
-    return op;
-}
 
 static void relinquish_memory(struct domain *d, struct list_head *list)
 {
diff -r 3870aff51ae3 -r 244e46e7d021 xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c       Fri Jan 05 17:34:30 2007 +0000
+++ b/xen/arch/x86/domain_build.c       Fri Jan 05 17:34:31 2007 +0000
@@ -688,7 +688,11 @@ int construct_dom0(struct domain *d,
         l4e_from_paddr(__pa(d->arch.mm_perdomain_l3), __PAGE_HYPERVISOR);
     v->arch.guest_table = pagetable_from_paddr(__pa(l4start));
     if ( IS_COMPAT(d) )
+    {
         v->arch.guest_table_user = v->arch.guest_table;
+        if ( setup_arg_xlat_area(v, l4start) < 0 )
+            panic("Not enough RAM for domain 0 hypercall argument 
translation.\n");
+    }
 
     l4tab += l4_table_offset(dsi.v_start);
     mfn = alloc_spfn;
diff -r 3870aff51ae3 -r 244e46e7d021 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Fri Jan 05 17:34:30 2007 +0000
+++ b/xen/arch/x86/mm.c Fri Jan 05 17:34:31 2007 +0000
@@ -1147,9 +1147,12 @@ static int alloc_l4_table(struct page_in
     pl4e[l4_table_offset(LINEAR_PT_VIRT_START)] =
         l4e_from_pfn(pfn, __PAGE_HYPERVISOR);
     pl4e[l4_table_offset(PERDOMAIN_VIRT_START)] =
-        l4e_from_page(
-            virt_to_page(page_get_owner(page)->arch.mm_perdomain_l3),
-            __PAGE_HYPERVISOR);
+        l4e_from_page(virt_to_page(d->arch.mm_perdomain_l3),
+                      __PAGE_HYPERVISOR);
+    if ( IS_COMPAT(d) )
+        pl4e[l4_table_offset(COMPAT_ARG_XLAT_VIRT_BASE)] =
+            l4e_from_page(virt_to_page(d->arch.mm_arg_xlat_l3),
+                          __PAGE_HYPERVISOR);
 
     return 1;
 
@@ -2756,7 +2759,9 @@ int do_update_va_mapping(unsigned long v
             flush_tlb_mask(d->domain_dirty_cpumask);
             break;
         default:
-            if ( unlikely(get_user(vmask, (unsigned long *)bmap_ptr)) )
+            if ( unlikely(!IS_COMPAT(d) ?
+                          get_user(vmask, (unsigned long *)bmap_ptr) :
+                          get_user(vmask, (unsigned int *)bmap_ptr)) )
                 rc = -EFAULT;
             pmask = vcpumask_to_pcpumask(d, vmask);
             flush_tlb_mask(pmask);
diff -r 3870aff51ae3 -r 244e46e7d021 xen/arch/x86/x86_64/Makefile
--- a/xen/arch/x86/x86_64/Makefile      Fri Jan 05 17:34:30 2007 +0000
+++ b/xen/arch/x86/x86_64/Makefile      Fri Jan 05 17:34:31 2007 +0000
@@ -6,5 +6,6 @@ ifeq ($(CONFIG_COMPAT),y)
 ifeq ($(CONFIG_COMPAT),y)
 # extra dependencies
 entry.o:       compat/entry.S
+mm.o:          compat/mm.c
 traps.o:       compat/traps.c
 endif
diff -r 3870aff51ae3 -r 244e46e7d021 xen/arch/x86/x86_64/compat/entry.S
--- a/xen/arch/x86/x86_64/compat/entry.S        Fri Jan 05 17:34:30 2007 +0000
+++ b/xen/arch/x86/x86_64/compat/entry.S        Fri Jan 05 17:34:31 2007 +0000
@@ -282,15 +282,11 @@ CFIX14:
 #define compat_mmu_update domain_crash_synchronous
 #define compat_set_gdt domain_crash_synchronous
 #define compat_platform_op domain_crash_synchronous
-#define compat_update_descriptor domain_crash_synchronous
-#define compat_memory_op domain_crash_synchronous
 #define compat_multicall domain_crash_synchronous
-#define compat_update_va_mapping domain_crash_synchronous
 #define compat_set_timer_op domain_crash_synchronous
 #define compat_event_channel_op_compat domain_crash_synchronous
 #define compat_physdev_op_compat domain_crash_synchronous
 #define compat_grant_table_op domain_crash_synchronous
-#define compat_update_va_mapping_otherdomain domain_crash_synchronous
 #define compat_vcpu_op domain_crash_synchronous
 #define compat_mmuext_op domain_crash_synchronous
 #define compat_acm_op domain_crash_synchronous
diff -r 3870aff51ae3 -r 244e46e7d021 xen/arch/x86/x86_64/compat/mm.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/x86_64/compat/mm.c   Fri Jan 05 17:34:31 2007 +0000
@@ -0,0 +1,148 @@
+#ifdef CONFIG_COMPAT
+
+#include <compat/memory.h>
+
+int compat_update_descriptor(u32 pa_lo, u32 pa_hi, u32 desc_lo, u32 desc_hi)
+{
+    return do_update_descriptor(pa_lo | ((u64)pa_hi << 32),
+                                desc_lo | ((u64)desc_hi << 32));
+}
+
+int compat_arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
+{
+    struct compat_machphys_mfn_list xmml;
+    l2_pgentry_t l2e;
+    unsigned long v;
+    compat_pfn_t mfn;
+    unsigned int i;
+    int rc = 0;
+
+    switch ( op )
+    {
+    case XENMEM_add_to_physmap:
+    {
+        struct compat_add_to_physmap cmp;
+        struct xen_add_to_physmap *nat = (void 
*)COMPAT_ARG_XLAT_VIRT_START(current->vcpu_id);
+
+        if ( copy_from_guest(&cmp, arg, 1) )
+            return -EFAULT;
+
+        XLAT_add_to_physmap(nat, &cmp);
+        rc = arch_memory_op(op, guest_handle_from_ptr(nat, void));
+
+        break;
+    }
+
+    case XENMEM_set_memory_map:
+    {
+        struct compat_foreign_memory_map cmp;
+        struct xen_foreign_memory_map *nat = (void 
*)COMPAT_ARG_XLAT_VIRT_START(current->vcpu_id);
+
+        if ( copy_from_guest(&cmp, arg, 1) )
+            return -EFAULT;
+
+#define XLAT_memory_map_HNDL_buffer(_d_, _s_) \
+        guest_from_compat_handle((_d_)->buffer, (_s_)->buffer)
+        XLAT_foreign_memory_map(nat, &cmp);
+#undef XLAT_memory_map_HNDL_buffer
+
+        rc = arch_memory_op(op, guest_handle_from_ptr(nat, void));
+
+        break;
+    }
+
+    case XENMEM_memory_map:
+    case XENMEM_machine_memory_map:
+    {
+        struct compat_memory_map cmp;
+        struct xen_memory_map *nat = (void 
*)COMPAT_ARG_XLAT_VIRT_START(current->vcpu_id);
+
+        if ( copy_from_guest(&cmp, arg, 1) )
+            return -EFAULT;
+
+#define XLAT_memory_map_HNDL_buffer(_d_, _s_) \
+        guest_from_compat_handle((_d_)->buffer, (_s_)->buffer)
+        XLAT_memory_map(nat, &cmp);
+#undef XLAT_memory_map_HNDL_buffer
+
+        rc = arch_memory_op(op, guest_handle_from_ptr(nat, void));
+        if ( rc < 0 )
+            break;
+
+#define XLAT_memory_map_HNDL_buffer(_d_, _s_) ((void)0)
+        XLAT_memory_map(&cmp, nat);
+#undef XLAT_memory_map_HNDL_buffer
+        if ( copy_to_guest(arg, &cmp, 1) )
+            rc = -EFAULT;
+
+        break;
+    }
+
+    case XENMEM_machphys_mapping:
+    {
+        struct domain *d = current->domain;
+        struct compat_machphys_mapping mapping = {
+            .v_start = MACH2PHYS_COMPAT_VIRT_START(d),
+            .v_end   = MACH2PHYS_COMPAT_VIRT_END,
+            .max_mfn = MACH2PHYS_COMPAT_NR_ENTRIES(d) - 1
+        };
+
+        if ( copy_to_guest(arg, &mapping, 1) )
+            rc = -EFAULT;
+
+        break;
+    }
+
+    case XENMEM_machphys_mfn_list:
+        if ( copy_from_guest(&xmml, arg, 1) )
+            return -EFAULT;
+
+        for ( i = 0, v = RDWR_COMPAT_MPT_VIRT_START;
+              (i != xmml.max_extents) && (v != RDWR_COMPAT_MPT_VIRT_END);
+              i++, v += 1 << L2_PAGETABLE_SHIFT )
+        {
+            l2e = compat_idle_pg_table_l2[l2_table_offset(v)];
+            if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
+                break;
+            mfn = l2e_get_pfn(l2e) + l1_table_offset(v);
+            if ( copy_to_compat_offset(xmml.extent_start, i, &mfn, 1) )
+                return -EFAULT;
+        }
+
+        xmml.nr_extents = i;
+        if ( copy_to_guest(arg, &xmml, 1) )
+            rc = -EFAULT;
+
+        break;
+
+    default:
+        rc = -ENOSYS;
+        break;
+    }
+
+    return rc;
+}
+
+int compat_update_va_mapping(unsigned int va, u32 lo, u32 hi,
+                             unsigned int flags)
+{
+    return do_update_va_mapping(va, lo | ((u64)hi << 32), flags);
+}
+
+int compat_update_va_mapping_otherdomain(unsigned long va, u32 lo, u32 hi,
+                                         unsigned long flags,
+                                         domid_t domid)
+{
+    return do_update_va_mapping_otherdomain(va, lo | ((u64)hi << 32), flags, 
domid);
+}
+#endif /* CONFIG_COMPAT */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 3870aff51ae3 -r 244e46e7d021 xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c  Fri Jan 05 17:34:30 2007 +0000
+++ b/xen/arch/x86/x86_64/mm.c  Fri Jan 05 17:34:31 2007 +0000
@@ -28,6 +28,7 @@
 #include <asm/page.h>
 #include <asm/flushtlb.h>
 #include <asm/fixmap.h>
+#include <asm/hypercall.h>
 #include <asm/msr.h>
 #include <public/memory.h>
 
@@ -407,6 +408,8 @@ int check_descriptor(const struct domain
     return 0;
 }
 
+#include "compat/mm.c"
+
 /*
  * Local variables:
  * mode: C
diff -r 3870aff51ae3 -r 244e46e7d021 xen/common/compat/Makefile
--- a/xen/common/compat/Makefile        Fri Jan 05 17:34:30 2007 +0000
+++ b/xen/common/compat/Makefile        Fri Jan 05 17:34:31 2007 +0000
@@ -1,4 +1,5 @@ obj-y += kernel.o
 obj-y += kernel.o
+obj-y += memory.o
 obj-y += xlat.o
 
 # extra dependencies
diff -r 3870aff51ae3 -r 244e46e7d021 xen/common/compat/memory.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/common/compat/memory.c        Fri Jan 05 17:34:31 2007 +0000
@@ -0,0 +1,364 @@
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/hypercall.h>
+#include <xen/guest_access.h>
+#include <xen/sched.h>
+#include <xen/event.h>
+#include <asm/current.h>
+#include <compat/memory.h>
+
+int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat)
+{
+    int rc, split, op = cmd & MEMOP_CMD_MASK;
+    unsigned int start_extent = cmd >> MEMOP_EXTENT_SHIFT;
+
+    do
+    {
+        unsigned int i, end_extent = 0;
+        union {
+            XEN_GUEST_HANDLE(void) hnd;
+            struct xen_memory_reservation *rsrv;
+            struct xen_memory_exchange *xchg;
+            struct xen_translate_gpfn_list *xlat;
+        } nat;
+        union {
+            struct compat_memory_reservation rsrv;
+            struct compat_memory_exchange xchg;
+            struct compat_translate_gpfn_list xlat;
+        } cmp;
+
+        set_xen_guest_handle(nat.hnd, (void 
*)COMPAT_ARG_XLAT_VIRT_START(current->vcpu_id));
+        split = 0;
+        switch ( op )
+        {
+            xen_pfn_t *space;
+
+        case XENMEM_increase_reservation:
+        case XENMEM_decrease_reservation:
+        case XENMEM_populate_physmap:
+            if ( copy_from_guest(&cmp.rsrv, compat, 1) )
+                return start_extent;
+
+            /* Is size too large for us to encode a continuation? */
+            if ( cmp.rsrv.nr_extents > (UINT_MAX >> MEMOP_EXTENT_SHIFT) )
+                return start_extent;
+
+            if ( !compat_handle_is_null(cmp.rsrv.extent_start) &&
+                 !compat_handle_okay(cmp.rsrv.extent_start, 
cmp.rsrv.nr_extents) )
+                return start_extent;
+
+            end_extent = start_extent + (COMPAT_ARG_XLAT_SIZE - 
sizeof(*nat.rsrv)) /
+                                        sizeof(*space);
+            if ( end_extent > cmp.rsrv.nr_extents )
+                end_extent = cmp.rsrv.nr_extents;
+
+            space = (xen_pfn_t *)(nat.rsrv + 1);
+#define XLAT_memory_reservation_HNDL_extent_start(_d_, _s_) \
+            do \
+            { \
+                if ( !compat_handle_is_null((_s_)->extent_start) ) \
+                { \
+                    set_xen_guest_handle((_d_)->extent_start, space - 
start_extent); \
+                    if ( op != XENMEM_increase_reservation ) \
+                    { \
+                        for ( i = start_extent; i < end_extent; ++i ) \
+                        { \
+                            compat_pfn_t pfn; \
+                            if ( __copy_from_compat_offset(&pfn, 
(_s_)->extent_start, i, 1) ) \
+                            { \
+                                end_extent = i; \
+                                split = -1; \
+                                break; \
+                            } \
+                            *space++ = pfn; \
+                        } \
+                    } \
+                } \
+                else \
+                { \
+                    set_xen_guest_handle((_d_)->extent_start, NULL); \
+                    end_extent = cmp.rsrv.nr_extents; \
+                } \
+            } while (0)
+            XLAT_memory_reservation(nat.rsrv, &cmp.rsrv);
+#undef XLAT_memory_reservation_HNDL_extent_start
+
+            if ( end_extent < cmp.rsrv.nr_extents )
+            {
+                nat.rsrv->nr_extents = end_extent;
+                ++split;
+            }
+
+            break;
+
+        case XENMEM_exchange:
+        {
+            int order_delta;
+
+            if ( copy_from_guest(&cmp.xchg, compat, 1) )
+                return -EFAULT;
+
+            order_delta = cmp.xchg.out.extent_order - cmp.xchg.in.extent_order;
+            /* Various sanity checks. */
+            if ( (cmp.xchg.nr_exchanged > cmp.xchg.in.nr_extents) ||
+                 (order_delta > 0 && (cmp.xchg.nr_exchanged & ((1U << 
order_delta) - 1))) ||
+                 /* Sizes of input and output lists do not overflow an int? */
+                 ((~0U >> cmp.xchg.in.extent_order) < cmp.xchg.in.nr_extents) 
||
+                 ((~0U >> cmp.xchg.out.extent_order) < 
cmp.xchg.out.nr_extents) ||
+                 /* Sizes of input and output lists match? */
+                 ((cmp.xchg.in.nr_extents << cmp.xchg.in.extent_order) !=
+                  (cmp.xchg.out.nr_extents << cmp.xchg.out.extent_order)) )
+                return -EINVAL;
+
+            start_extent = cmp.xchg.nr_exchanged;
+            end_extent = (COMPAT_ARG_XLAT_SIZE - sizeof(*nat.xchg)) /
+                         (((1U << __builtin_abs(order_delta)) + 1) *
+                          sizeof(*space));
+            if ( end_extent == 0 )
+            {
+                printk("Cannot translate compatibility mode XENMEM_exchange 
extents (%u,%u)\n",
+                       cmp.xchg.in.extent_order, cmp.xchg.out.extent_order);
+                return -E2BIG;
+            }
+            if ( order_delta > 0 )
+                end_extent <<= order_delta;
+            end_extent += start_extent;
+            if ( end_extent > cmp.xchg.in.nr_extents )
+                end_extent = cmp.xchg.in.nr_extents;
+
+            space = (xen_pfn_t *)(nat.xchg + 1);
+            /* Code below depends upon .in preceding .out. */
+            BUILD_BUG_ON(offsetof(xen_memory_exchange_t, in) > 
offsetof(xen_memory_exchange_t, out));
+#define XLAT_memory_reservation_HNDL_extent_start(_d_, _s_) \
+            do \
+            { \
+                set_xen_guest_handle((_d_)->extent_start, space - 
start_extent); \
+                for ( i = start_extent; i < end_extent; ++i ) \
+                { \
+                    compat_pfn_t pfn; \
+                    if ( __copy_from_compat_offset(&pfn, (_s_)->extent_start, 
i, 1) ) \
+                        return -EFAULT; \
+                    *space++ = pfn; \
+                } \
+                if ( order_delta > 0 ) \
+                { \
+                    start_extent >>= order_delta; \
+                    end_extent >>= order_delta; \
+                } \
+                else \
+                { \
+                    start_extent <<= -order_delta; \
+                    end_extent <<= -order_delta; \
+                } \
+                order_delta = -order_delta; \
+            } while (0)
+            XLAT_memory_exchange(nat.xchg, &cmp.xchg);
+#undef XLAT_memory_reservation_HNDL_extent_start
+
+            if ( end_extent < cmp.xchg.in.nr_extents )
+            {
+                nat.xchg->in.nr_extents = end_extent;
+                if ( order_delta >= 0 )
+                    nat.xchg->out.nr_extents = end_extent >> order_delta;
+                else
+                    nat.xchg->out.nr_extents = end_extent << order_delta;
+                ++split;
+            }
+
+            break;
+        }
+
+        case XENMEM_current_reservation:
+        case XENMEM_maximum_reservation:
+        {
+#define xen_domid_t domid_t
+#define compat_domid_t domid_compat_t
+            CHECK_TYPE(domid);
+#undef compat_domid_t
+#undef xen_domid_t
+        }
+        case XENMEM_maximum_ram_page:
+            nat.hnd = compat;
+            break;
+
+        case XENMEM_translate_gpfn_list:
+            if ( copy_from_guest(&cmp.xlat, compat, 1) )
+                return -EFAULT;
+
+            /* Is size too large for us to encode a continuation? */
+            if ( cmp.xlat.nr_gpfns > (UINT_MAX >> MEMOP_EXTENT_SHIFT) )
+                return -EINVAL;
+
+            if ( !compat_handle_okay(cmp.xlat.gpfn_list, cmp.xlat.nr_gpfns) ||
+                 !compat_handle_okay(cmp.xlat.mfn_list,  cmp.xlat.nr_gpfns) )
+                return -EFAULT;
+
+            end_extent = start_extent + (COMPAT_ARG_XLAT_SIZE - 
sizeof(*nat.xlat)) /
+                                        sizeof(*space);
+            if ( end_extent > cmp.xlat.nr_gpfns )
+                end_extent = cmp.xlat.nr_gpfns;
+
+            space = (xen_pfn_t *)(nat.xlat + 1);
+            /* Code below depends upon .gpfn_list preceding .mfn_list. */
+            BUILD_BUG_ON(offsetof(xen_translate_gpfn_list_t, gpfn_list) > 
offsetof(xen_translate_gpfn_list_t, mfn_list));
+#define XLAT_translate_gpfn_list_HNDL_gpfn_list(_d_, _s_) \
+            do \
+            { \
+                set_xen_guest_handle((_d_)->gpfn_list, space - start_extent); \
+                for ( i = start_extent; i < end_extent; ++i ) \
+                { \
+                    compat_pfn_t pfn; \
+                    if ( __copy_from_compat_offset(&pfn, (_s_)->gpfn_list, i, 
1) ) \
+                        return -EFAULT; \
+                    *space++ = pfn; \
+                } \
+            } while (0)
+#define XLAT_translate_gpfn_list_HNDL_mfn_list(_d_, _s_) \
+            (_d_)->mfn_list = (_d_)->gpfn_list
+            XLAT_translate_gpfn_list(nat.xlat, &cmp.xlat);
+#undef XLAT_translate_gpfn_list_HNDL_mfn_list
+#undef XLAT_translate_gpfn_list_HNDL_gpfn_list
+
+            if ( end_extent < cmp.xlat.nr_gpfns )
+            {
+                nat.xlat->nr_gpfns = end_extent;
+                ++split;
+            }
+
+            break;
+
+        default:
+            return compat_arch_memory_op(cmd, compat);
+        }
+
+        rc = do_memory_op(cmd, nat.hnd);
+        if ( rc < 0 )
+            return rc;
+
+        cmd = 0;
+        if ( hypercall_xlat_continuation(&cmd, 0x02, nat.hnd, compat) )
+        {
+            BUG_ON(rc != __HYPERVISOR_memory_op);
+            BUG_ON((cmd & MEMOP_CMD_MASK) != op);
+            split = -1;
+        }
+
+        switch ( op )
+        {
+        case XENMEM_increase_reservation:
+        case XENMEM_decrease_reservation:
+        case XENMEM_populate_physmap:
+            end_extent = split >= 0 ? rc : cmd >> MEMOP_EXTENT_SHIFT;
+            if ( op != XENMEM_decrease_reservation &&
+                 !guest_handle_is_null(nat.rsrv->extent_start) )
+            {
+                for ( ; start_extent < end_extent; ++start_extent )
+                {
+                    compat_pfn_t pfn = nat.rsrv->extent_start.p[start_extent];
+
+                    BUG_ON(pfn != nat.rsrv->extent_start.p[start_extent]);
+                    if ( __copy_to_compat_offset(cmp.rsrv.extent_start, 
start_extent, &pfn, 1) )
+                    {
+                        if ( split >= 0 )
+                        {
+                            rc = start_extent;
+                            split = 0;
+                        }
+                        else
+                            /*
+                             * Short of being able to cancel the continuation,
+                             * force it to restart here; eventually we shall
+                             * get out of this state.
+                             */
+                            rc = (start_extent << MEMOP_EXTENT_SHIFT) | op;
+                        break;
+                    }
+                }
+            }
+            else
+                start_extent = end_extent;
+            break;
+
+        case XENMEM_exchange:
+        {
+            DEFINE_XEN_GUEST_HANDLE(compat_memory_exchange_t);
+            int order_delta;
+
+            BUG_ON(split >= 0 && rc);
+            BUG_ON(end_extent < nat.xchg->nr_exchanged);
+            end_extent = nat.xchg->nr_exchanged;
+
+            order_delta = cmp.xchg.out.extent_order - cmp.xchg.in.extent_order;
+            if ( order_delta > 0 )
+            {
+                start_extent >>= order_delta;
+                BUG_ON(end_extent & ((1U << order_delta) - 1));
+                end_extent >>= order_delta;
+            }
+            else
+            {
+                start_extent <<= -order_delta;
+                end_extent <<= -order_delta;
+            }
+
+            for ( ; start_extent < end_extent; ++start_extent )
+            {
+                compat_pfn_t pfn = nat.xchg->out.extent_start.p[start_extent];
+
+                BUG_ON(pfn != nat.xchg->out.extent_start.p[start_extent]);
+                /* Note that we ignore errors accessing the output extent 
list. */
+                __copy_to_compat_offset(cmp.xchg.out.extent_start, 
start_extent, &pfn, 1);
+            }
+
+            cmp.xchg.nr_exchanged = nat.xchg->nr_exchanged;
+            if ( copy_field_to_guest(guest_handle_cast(compat, 
compat_memory_exchange_t),
+                                     &cmp.xchg, nr_exchanged) )
+            {
+                if ( split < 0 )
+                    /* Cannot cancel the continuation... */
+                    domain_crash(current->domain);
+                return -EFAULT;
+            }
+            break;
+        }
+
+        case XENMEM_maximum_ram_page:
+        case XENMEM_current_reservation:
+        case XENMEM_maximum_reservation:
+            break;
+
+        case XENMEM_translate_gpfn_list:
+            if ( split < 0 )
+                end_extent = cmd >> MEMOP_EXTENT_SHIFT;
+            else
+                BUG_ON(rc);
+
+            for ( ; start_extent < end_extent; ++start_extent )
+            {
+                compat_pfn_t pfn = nat.xlat->mfn_list.p[start_extent];
+
+                BUG_ON(pfn != nat.xlat->mfn_list.p[start_extent]);
+                if ( __copy_to_compat_offset(cmp.xlat.mfn_list, start_extent, 
&pfn, 1) )
+                {
+                    if ( split < 0 )
+                        /* Cannot cancel the continuation... */
+                        domain_crash(current->domain);
+                    return -EFAULT;
+                }
+            }
+            break;
+
+        default:
+            domain_crash(current->domain);
+            split = 0;
+            break;
+        }
+
+        cmd = op | (start_extent << MEMOP_EXTENT_SHIFT);
+        if ( split > 0 && hypercall_preempt_check() )
+            return hypercall_create_continuation(
+                __HYPERVISOR_memory_op, "ih", cmd, compat);
+    } while ( split > 0 );
+
+    return rc;
+}
diff -r 3870aff51ae3 -r 244e46e7d021 xen/common/memory.c
--- a/xen/common/memory.c       Fri Jan 05 17:34:30 2007 +0000
+++ b/xen/common/memory.c       Fri Jan 05 17:34:31 2007 +0000
@@ -17,17 +17,11 @@
 #include <xen/shadow.h>
 #include <xen/iocap.h>
 #include <xen/guest_access.h>
+#include <xen/hypercall.h>
 #include <xen/errno.h>
 #include <asm/current.h>
 #include <asm/hardirq.h>
 #include <public/memory.h>
-
-/*
- * To allow safe resume of do_memory_op() after preemption, we need to know 
- * at what point in the page list to resume. For this purpose I steal the 
- * high-order bits of the @cmd parameter, which are otherwise unused and zero.
- */
-#define START_EXTENT_SHIFT 4 /* cmd[:4] == start_extent */
 
 struct memop_args {
     /* INPUT */
@@ -236,7 +230,7 @@ static long translate_gpfn_list(
         return -EFAULT;
 
     /* Is size too large for us to encode a continuation? */
-    if ( op.nr_gpfns > (ULONG_MAX >> START_EXTENT_SHIFT) )
+    if ( op.nr_gpfns > (ULONG_MAX >> MEMOP_EXTENT_SHIFT) )
         return -EINVAL;
 
     if ( !guest_handle_okay(op.gpfn_list, op.nr_gpfns) ||
@@ -511,20 +505,20 @@ long do_memory_op(unsigned long cmd, XEN
     struct memop_args args;
     domid_t domid;
 
-    op = cmd & ((1 << START_EXTENT_SHIFT) - 1);
+    op = cmd & MEMOP_CMD_MASK;
 
     switch ( op )
     {
     case XENMEM_increase_reservation:
     case XENMEM_decrease_reservation:
     case XENMEM_populate_physmap:
-        start_extent = cmd >> START_EXTENT_SHIFT;
+        start_extent = cmd >> MEMOP_EXTENT_SHIFT;
 
         if ( copy_from_guest(&reservation, arg, 1) )
             return start_extent;
 
         /* Is size too large for us to encode a continuation? */
-        if ( reservation.nr_extents > (ULONG_MAX >> START_EXTENT_SHIFT) )
+        if ( reservation.nr_extents > (ULONG_MAX >> MEMOP_EXTENT_SHIFT) )
             return start_extent;
 
         if ( unlikely(start_extent > reservation.nr_extents) )
@@ -574,7 +568,7 @@ long do_memory_op(unsigned long cmd, XEN
         if ( args.preempted )
             return hypercall_create_continuation(
                 __HYPERVISOR_memory_op, "lh",
-                op | (rc << START_EXTENT_SHIFT), arg);
+                op | (rc << MEMOP_EXTENT_SHIFT), arg);
 
         break;
 
@@ -606,14 +600,14 @@ long do_memory_op(unsigned long cmd, XEN
         break;
 
     case XENMEM_translate_gpfn_list:
-        progress = cmd >> START_EXTENT_SHIFT;
+        progress = cmd >> MEMOP_EXTENT_SHIFT;
         rc = translate_gpfn_list(
             guest_handle_cast(arg, xen_translate_gpfn_list_t),
             &progress);
         if ( rc == -EAGAIN )
             return hypercall_create_continuation(
                 __HYPERVISOR_memory_op, "lh",
-                op | (progress << START_EXTENT_SHIFT), arg);
+                op | (progress << MEMOP_EXTENT_SHIFT), arg);
         break;
 
     default:
diff -r 3870aff51ae3 -r 244e46e7d021 xen/include/asm-x86/config.h
--- a/xen/include/asm-x86/config.h      Fri Jan 05 17:34:30 2007 +0000
+++ b/xen/include/asm-x86/config.h      Fri Jan 05 17:34:31 2007 +0000
@@ -108,7 +108,7 @@
 /*
  * Memory layout:
  *  0x0000000000000000 - 0x00007fffffffffff [128TB, 2^47 bytes, PML4:0-255]
- *    Guest-defined use.
+ *    Guest-defined use (see below for compatibility mode guests).
  *  0x0000800000000000 - 0xffff7fffffffffff [16EB]
  *    Inaccessible: current arch only supports 48-bit sign-extended VAs.
  *  0xffff800000000000 - 0xffff803fffffffff [256GB, 2^38 bytes, PML4:256]
@@ -141,6 +141,18 @@
  *    Reserved for future use.
  *  0xffff880000000000 - 0xffffffffffffffff [120TB, PML4:272-511]
  *    Guest-defined use.
+ *
+ * Compatibility guest area layout:
+ *  0x0000000000000000 - 0x00000000f57fffff [3928MB,            PML4:0]
+ *    Guest-defined use.
+ *  0x0000000f58000000 - 0x00000000ffffffff [168MB,             PML4:0]
+ *    Read-only machine-to-phys translation table (GUEST ACCESSIBLE).
+ *  0x0000000000000000 - 0x00000000ffffffff [508GB,             PML4:0]
+ *    Unused.
+ *  0x0000008000000000 - 0x000000ffffffffff [512GB, 2^39 bytes, PML4:1]
+ *    Hypercall argument translation area.
+ *  0x0000010000000000 - 0x00007fffffffffff [127TB, 2^46 bytes, PML4:2-255]
+ *    Reserved for future use.
  */
 
 
@@ -210,6 +222,14 @@
 
 #endif
 
+#define COMPAT_ARG_XLAT_VIRT_BASE      (1UL << ROOT_PAGETABLE_SHIFT)
+#define COMPAT_ARG_XLAT_SHIFT          0
+#define COMPAT_ARG_XLAT_PAGES          (1U << COMPAT_ARG_XLAT_SHIFT)
+#define COMPAT_ARG_XLAT_SIZE           (COMPAT_ARG_XLAT_PAGES << PAGE_SHIFT)
+#define COMPAT_ARG_XLAT_VIRT_START(vcpu_id) \
+    (COMPAT_ARG_XLAT_VIRT_BASE + ((unsigned long)(vcpu_id) << \
+                                  (PAGE_SHIFT + COMPAT_ARG_XLAT_SHIFT + 1)))
+
 #define PGT_base_page_table     PGT_l4_page_table
 
 #define __HYPERVISOR_CS64 0xe008
diff -r 3870aff51ae3 -r 244e46e7d021 xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h      Fri Jan 05 17:34:30 2007 +0000
+++ b/xen/include/asm-x86/domain.h      Fri Jan 05 17:34:31 2007 +0000
@@ -100,6 +100,7 @@ struct arch_domain
 
 #ifdef CONFIG_COMPAT
     unsigned int hv_compat_vstart;
+    l3_pgentry_t *mm_arg_xlat_l3;
 #endif
 
     /* I/O-port admin-specified access capabilities. */
diff -r 3870aff51ae3 -r 244e46e7d021 xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h  Fri Jan 05 17:34:30 2007 +0000
+++ b/xen/include/asm-x86/mm.h  Fri Jan 05 17:34:31 2007 +0000
@@ -329,10 +329,20 @@ int __sync_lazy_execstate(void);
 /* Arch-specific portion of memory_op hypercall. */
 long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg);
 long subarch_memory_op(int op, XEN_GUEST_HANDLE(void) arg);
+#ifdef CONFIG_COMPAT
+int compat_arch_memory_op(int op, XEN_GUEST_HANDLE(void));
+int compat_subarch_memory_op(int op, XEN_GUEST_HANDLE(void));
+#endif
 
 int steal_page(
     struct domain *d, struct page_info *page, unsigned int memflags);
 
 int map_ldt_shadow_page(unsigned int);
 
+#ifdef CONFIG_COMPAT
+int setup_arg_xlat_area(struct vcpu *, l4_pgentry_t *);
+#else
+# define setup_arg_xlat_area(vcpu, l4tab) 0
+#endif
+
 #endif /* __ASM_X86_MM_H__ */
diff -r 3870aff51ae3 -r 244e46e7d021 xen/include/xen/compat.h
--- a/xen/include/xen/compat.h  Fri Jan 05 17:34:30 2007 +0000
+++ b/xen/include/xen/compat.h  Fri Jan 05 17:34:31 2007 +0000
@@ -158,6 +158,8 @@
 
 extern int compat_disabled;
 
+int hypercall_xlat_continuation(unsigned int *id, unsigned int mask, ...);
+
 /* In-place translation functons: */
 struct start_info;
 void xlat_start_info(struct start_info *, enum XLAT_start_info_console);
diff -r 3870aff51ae3 -r 244e46e7d021 xen/include/xen/hypercall.h
--- a/xen/include/xen/hypercall.h       Fri Jan 05 17:34:30 2007 +0000
+++ b/xen/include/xen/hypercall.h       Fri Jan 05 17:34:31 2007 +0000
@@ -42,9 +42,17 @@ do_platform_op(
 do_platform_op(
     XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op);
 
+/*
+ * To allow safe resume of do_memory_op() after preemption, we need to know
+ * at what point in the page list to resume. For this purpose I steal the
+ * high-order bits of the @cmd parameter, which are otherwise unused and zero.
+ */
+#define MEMOP_EXTENT_SHIFT 4 /* cmd[:4] == start_extent */
+#define MEMOP_CMD_MASK     ((1 << MEMOP_EXTENT_SHIFT) - 1)
+
 extern long
 do_memory_op(
-    int cmd,
+    unsigned long cmd,
     XEN_GUEST_HANDLE(void) arg);
 
 extern long
@@ -108,4 +116,13 @@ do_kexec_op(
     int arg1,
     XEN_GUEST_HANDLE(void) arg);
 
+#ifdef CONFIG_COMPAT
+
+extern int
+compat_memory_op(
+    unsigned int cmd,
+    XEN_GUEST_HANDLE(void) arg);
+
+#endif
+
 #endif /* __XEN_HYPERCALL_H__ */
diff -r 3870aff51ae3 -r 244e46e7d021 xen/include/xlat.lst
--- a/xen/include/xlat.lst      Fri Jan 05 17:34:30 2007 +0000
+++ b/xen/include/xlat.lst      Fri Jan 05 17:34:31 2007 +0000
@@ -4,3 +4,9 @@
 ?      dom0_vga_console_info           xen.h
 !      start_info                      xen.h
 ?      vcpu_time_info                  xen.h
+!      add_to_physmap                  memory.h
+!      foreign_memory_map              memory.h
+!      memory_exchange                 memory.h
+!      memory_map                      memory.h
+!      memory_reservation              memory.h
+!      translate_gpfn_list             memory.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_memory_op,, Xen patchbot-unstable <=