ia64/xen-unstable

changeset 13295:244e46e7d021

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@novell.com>
author Emmanuel Ackaouy <ack@xensource.com>
date Fri Jan 05 17:34:31 2007 +0000 (2007-01-05)
parents 3870aff51ae3
children e4088ae584b8
files xen/arch/x86/domain.c xen/arch/x86/domain_build.c xen/arch/x86/mm.c xen/arch/x86/x86_64/Makefile xen/arch/x86/x86_64/compat/entry.S xen/arch/x86/x86_64/compat/mm.c xen/arch/x86/x86_64/mm.c xen/common/compat/Makefile xen/common/compat/memory.c xen/common/memory.c xen/include/asm-x86/config.h xen/include/asm-x86/domain.h xen/include/asm-x86/mm.h xen/include/xen/compat.h xen/include/xen/hypercall.h xen/include/xlat.lst
line diff
     1.1 --- a/xen/arch/x86/domain.c	Fri Jan 05 17:34:30 2007 +0000
     1.2 +++ b/xen/arch/x86/domain.c	Fri Jan 05 17:34:31 2007 +0000
     1.3 @@ -128,10 +128,98 @@ void free_vcpu_struct(struct vcpu *v)
     1.4  }
     1.5  
     1.6  #ifdef CONFIG_COMPAT
     1.7 +
     1.8 +int setup_arg_xlat_area(struct vcpu *v, l4_pgentry_t *l4tab)
     1.9 +{
    1.10 +    struct domain *d = v->domain;
    1.11 +    unsigned i;
    1.12 +    struct page_info *pg;
    1.13 +
    1.14 +    if ( !d->arch.mm_arg_xlat_l3 )
    1.15 +    {
    1.16 +        pg = alloc_domheap_page(NULL);
    1.17 +        if ( !pg )
    1.18 +            return -ENOMEM;
    1.19 +        d->arch.mm_arg_xlat_l3 = clear_page(page_to_virt(pg));
    1.20 +    }
    1.21 +
    1.22 +    l4tab[l4_table_offset(COMPAT_ARG_XLAT_VIRT_BASE)] =
    1.23 +        l4e_from_paddr(__pa(d->arch.mm_arg_xlat_l3), __PAGE_HYPERVISOR);
    1.24 +
    1.25 +    for ( i = 0; i < COMPAT_ARG_XLAT_PAGES; ++i )
    1.26 +    {
    1.27 +        unsigned long va = COMPAT_ARG_XLAT_VIRT_START(v->vcpu_id) + i * PAGE_SIZE;
    1.28 +        l2_pgentry_t *l2tab;
    1.29 +        l1_pgentry_t *l1tab;
    1.30 +
    1.31 +        if ( !l3e_get_intpte(d->arch.mm_arg_xlat_l3[l3_table_offset(va)]) )
    1.32 +        {
    1.33 +            pg = alloc_domheap_page(NULL);
    1.34 +            if ( !pg )
    1.35 +                return -ENOMEM;
    1.36 +            clear_page(page_to_virt(pg));
    1.37 +            d->arch.mm_arg_xlat_l3[l3_table_offset(va)] = l3e_from_page(pg, __PAGE_HYPERVISOR);
    1.38 +        }
    1.39 +        l2tab = l3e_to_l2e(d->arch.mm_arg_xlat_l3[l3_table_offset(va)]);
    1.40 +        if ( !l2e_get_intpte(l2tab[l2_table_offset(va)]) )
    1.41 +        {
    1.42 +            pg = alloc_domheap_page(NULL);
    1.43 +            if ( !pg )
    1.44 +                return -ENOMEM;
    1.45 +            clear_page(page_to_virt(pg));
    1.46 +            l2tab[l2_table_offset(va)] = l2e_from_page(pg, __PAGE_HYPERVISOR);
    1.47 +        }
    1.48 +        l1tab = l2e_to_l1e(l2tab[l2_table_offset(va)]);
    1.49 +        BUG_ON(l1e_get_intpte(l1tab[l1_table_offset(va)]));
    1.50 +        pg = alloc_domheap_page(NULL);
    1.51 +        if ( !pg )
    1.52 +            return -ENOMEM;
    1.53 +        l1tab[l1_table_offset(va)] = l1e_from_page(pg, PAGE_HYPERVISOR);
    1.54 +    }
    1.55 +
    1.56 +    return 0;
    1.57 +}
    1.58 +
    1.59 +static void release_arg_xlat_area(struct domain *d)
    1.60 +{
    1.61 +    if ( d->arch.mm_arg_xlat_l3 )
    1.62 +    {
    1.63 +        unsigned l3;
    1.64 +
    1.65 +        for ( l3 = 0; l3 < L3_PAGETABLE_ENTRIES; ++l3 )
    1.66 +        {
    1.67 +            if ( l3e_get_intpte(d->arch.mm_arg_xlat_l3[l3]) )
    1.68 +            {
    1.69 +                l2_pgentry_t *l2tab = l3e_to_l2e(d->arch.mm_arg_xlat_l3[l3]);
    1.70 +                unsigned l2;
    1.71 +
    1.72 +                for ( l2 = 0; l2 < L2_PAGETABLE_ENTRIES; ++l2 )
    1.73 +                {
    1.74 +                    if ( l2e_get_intpte(l2tab[l2]) )
    1.75 +                    {
    1.76 +                        l1_pgentry_t *l1tab = l2e_to_l1e(l2tab[l2]);
    1.77 +                        unsigned l1;
    1.78 +
    1.79 +                        for ( l1 = 0; l1 < L1_PAGETABLE_ENTRIES; ++l1 )
    1.80 +                        {
    1.81 +                            if ( l1e_get_intpte(l1tab[l1]) )
    1.82 +                                free_domheap_page(l1e_get_page(l1tab[l1]));
    1.83 +                        }
    1.84 +                        free_domheap_page(l2e_get_page(l2tab[l2]));
    1.85 +                    }
    1.86 +                }
    1.87 +                free_domheap_page(l3e_get_page(d->arch.mm_arg_xlat_l3[l3]));
    1.88 +            }
    1.89 +        }
    1.90 +        free_domheap_page(virt_to_page(d->arch.mm_arg_xlat_l3));
    1.91 +    }
    1.92 +}
    1.93 +
    1.94  static int setup_compat_l4(struct vcpu *v)
    1.95  {
    1.96      struct page_info *pg = alloc_domheap_page(NULL);
    1.97      l4_pgentry_t *l4tab;
    1.98 +    int rc;
    1.99  
   1.100      if ( !pg )
   1.101          return -ENOMEM;
   1.102 @@ -143,10 +231,26 @@ static int setup_compat_l4(struct vcpu *
   1.103      v->arch.guest_table = pagetable_from_page(pg);
   1.104      v->arch.guest_table_user = v->arch.guest_table;
   1.105  
   1.106 +    if ( (rc = setup_arg_xlat_area(v, l4tab)) < 0 )
   1.107 +    {
   1.108 +        free_domheap_page(pg);
   1.109 +        return rc;
   1.110 +    }
   1.111 +
   1.112      return 0;
   1.113  }
   1.114 +
   1.115 +static void release_compat_l4(struct vcpu *v)
   1.116 +{
   1.117 +    free_domheap_page(pagetable_get_page(v->arch.guest_table));
   1.118 +    v->arch.guest_table = pagetable_null();
   1.119 +    v->arch.guest_table_user = pagetable_null();
   1.120 +}
   1.121 +
   1.122  #else
   1.123 +#define release_arg_xlat_area(d) ((void)0)
   1.124  #define setup_compat_l4(v) 0
   1.125 +#define release_compat_l4(v) ((void)0)
   1.126  #endif
   1.127  
   1.128  int vcpu_initialise(struct vcpu *v)
   1.129 @@ -192,7 +296,7 @@ int vcpu_initialise(struct vcpu *v)
   1.130  void vcpu_destroy(struct vcpu *v)
   1.131  {
   1.132      if ( IS_COMPAT(v->domain) )
   1.133 -        free_domheap_page(pagetable_get_page(v->arch.guest_table));
   1.134 +        release_compat_l4(v);
   1.135  }
   1.136  
   1.137  int arch_domain_create(struct domain *d)
   1.138 @@ -301,6 +405,9 @@ void arch_domain_destroy(struct domain *
   1.139      free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
   1.140  #endif
   1.141  
   1.142 +    if ( IS_COMPAT(d) )
   1.143 +        release_arg_xlat_area(d);
   1.144 +
   1.145      free_xenheap_page(d->shared_info);
   1.146  }
   1.147  
   1.148 @@ -935,49 +1042,55 @@ unsigned long hypercall_create_continuat
   1.149  
   1.150          for ( i = 0; *p != '\0'; i++ )
   1.151              mcs->call.args[i] = next_arg(p, args);
   1.152 +        if ( IS_COMPAT(current->domain) )
   1.153 +        {
   1.154 +            for ( ; i < 6; i++ )
   1.155 +                mcs->call.args[i] = 0;
   1.156 +        }
   1.157      }
   1.158      else
   1.159      {
   1.160          regs       = guest_cpu_user_regs();
   1.161 -#if defined(__i386__)
   1.162          regs->eax  = op;
   1.163 +        regs->eip -= 2;  /* re-execute 'syscall' / 'int 0x82' */
   1.164  
   1.165 -        if ( supervisor_mode_kernel || is_hvm_vcpu(current) )
   1.166 -            regs->eip &= ~31; /* re-execute entire hypercall entry stub */
   1.167 -        else
   1.168 -            regs->eip -= 2;   /* re-execute 'int 0x82' */
   1.169 -
   1.170 -        for ( i = 0; *p != '\0'; i++ )
   1.171 +#ifdef __x86_64__
   1.172 +        if ( !IS_COMPAT(current->domain) )
   1.173          {
   1.174 -            arg = next_arg(p, args);
   1.175 -            switch ( i )
   1.176 +            for ( i = 0; *p != '\0'; i++ )
   1.177              {
   1.178 -            case 0: regs->ebx = arg; break;
   1.179 -            case 1: regs->ecx = arg; break;
   1.180 -            case 2: regs->edx = arg; break;
   1.181 -            case 3: regs->esi = arg; break;
   1.182 -            case 4: regs->edi = arg; break;
   1.183 -            case 5: regs->ebp = arg; break;
   1.184 +                arg = next_arg(p, args);
   1.185 +                switch ( i )
   1.186 +                {
   1.187 +                case 0: regs->rdi = arg; break;
   1.188 +                case 1: regs->rsi = arg; break;
   1.189 +                case 2: regs->rdx = arg; break;
   1.190 +                case 3: regs->r10 = arg; break;
   1.191 +                case 4: regs->r8  = arg; break;
   1.192 +                case 5: regs->r9  = arg; break;
   1.193 +                }
   1.194              }
   1.195          }
   1.196 -#elif defined(__x86_64__)
   1.197 -        regs->rax  = op;
   1.198 -        regs->rip -= 2;  /* re-execute 'syscall' */
   1.199 -
   1.200 -        for ( i = 0; *p != '\0'; i++ )
   1.201 +        else
   1.202 +#endif
   1.203          {
   1.204 -            arg = next_arg(p, args);
   1.205 -            switch ( i )
   1.206 +            if ( supervisor_mode_kernel || is_hvm_vcpu(current) )
   1.207 +                regs->eip &= ~31; /* re-execute entire hypercall entry stub */
   1.208 +
   1.209 +            for ( i = 0; *p != '\0'; i++ )
   1.210              {
   1.211 -            case 0: regs->rdi = arg; break;
   1.212 -            case 1: regs->rsi = arg; break;
   1.213 -            case 2: regs->rdx = arg; break;
   1.214 -            case 3: regs->r10 = arg; break;
   1.215 -            case 4: regs->r8  = arg; break;
   1.216 -            case 5: regs->r9  = arg; break;
   1.217 +                arg = next_arg(p, args);
   1.218 +                switch ( i )
   1.219 +                {
   1.220 +                case 0: regs->ebx = arg; break;
   1.221 +                case 1: regs->ecx = arg; break;
   1.222 +                case 2: regs->edx = arg; break;
   1.223 +                case 3: regs->esi = arg; break;
   1.224 +                case 4: regs->edi = arg; break;
   1.225 +                case 5: regs->ebp = arg; break;
   1.226 +                }
   1.227              }
   1.228          }
   1.229 -#endif
   1.230      }
   1.231  
   1.232      va_end(args);
   1.233 @@ -985,6 +1098,98 @@ unsigned long hypercall_create_continuat
   1.234      return op;
   1.235  }
   1.236  
   1.237 +#ifdef CONFIG_COMPAT
   1.238 +int hypercall_xlat_continuation(unsigned int *id, unsigned int mask, ...)
   1.239 +{
   1.240 +    int rc = 0;
   1.241 +    struct mc_state *mcs = &this_cpu(mc_state);
   1.242 +    struct cpu_user_regs *regs;
   1.243 +    unsigned int i, cval = 0;
   1.244 +    unsigned long nval = 0;
   1.245 +    va_list args;
   1.246 +
   1.247 +    BUG_ON(*id > 5);
   1.248 +    BUG_ON(mask & (1U << *id));
   1.249 +
   1.250 +    va_start(args, mask);
   1.251 +
   1.252 +    if ( test_bit(_MCSF_in_multicall, &mcs->flags) )
   1.253 +    {
   1.254 +        if ( !test_bit(_MCSF_call_preempted, &mcs->flags) )
   1.255 +            return 0;
   1.256 +        for ( i = 0; i < 6; ++i, mask >>= 1 )
   1.257 +        {
   1.258 +            if ( mask & 1 )
   1.259 +            {
   1.260 +                nval = va_arg(args, unsigned long);
   1.261 +                cval = va_arg(args, unsigned int);
   1.262 +                if ( cval == nval )
   1.263 +                    mask &= ~1U;
   1.264 +                else
   1.265 +                    BUG_ON(nval == (unsigned int)nval);
   1.266 +            }
   1.267 +            else if ( id && *id == i )
   1.268 +            {
   1.269 +                *id = mcs->call.args[i];
   1.270 +                id = NULL;
   1.271 +            }
   1.272 +            if ( (mask & 1) && mcs->call.args[i] == nval )
   1.273 +                ++rc;
   1.274 +            else
   1.275 +            {
   1.276 +                cval = mcs->call.args[i];
   1.277 +                BUG_ON(mcs->call.args[i] != cval);
   1.278 +            }
   1.279 +            mcs->compat_call.args[i] = cval;
   1.280 +        }
   1.281 +    }
   1.282 +    else
   1.283 +    {
   1.284 +        regs = guest_cpu_user_regs();
   1.285 +        for ( i = 0; i < 6; ++i, mask >>= 1 )
   1.286 +        {
   1.287 +            unsigned long *reg;
   1.288 +
   1.289 +            switch ( i )
   1.290 +            {
   1.291 +            case 0: reg = &regs->ebx; break;
   1.292 +            case 1: reg = &regs->ecx; break;
   1.293 +            case 2: reg = &regs->edx; break;
   1.294 +            case 3: reg = &regs->esi; break;
   1.295 +            case 4: reg = &regs->edi; break;
   1.296 +            case 5: reg = &regs->ebp; break;
   1.297 +            default: BUG(); reg = NULL; break;
   1.298 +            }
   1.299 +            if ( (mask & 1) )
   1.300 +            {
   1.301 +                nval = va_arg(args, unsigned long);
   1.302 +                cval = va_arg(args, unsigned int);
   1.303 +                if ( cval == nval )
   1.304 +                    mask &= ~1U;
   1.305 +                else
   1.306 +                    BUG_ON(nval == (unsigned int)nval);
   1.307 +            }
   1.308 +            else if ( id && *id == i )
   1.309 +            {
   1.310 +                *id = *reg;
   1.311 +                id = NULL;
   1.312 +            }
   1.313 +            if ( (mask & 1) && *reg == nval )
   1.314 +            {
   1.315 +                *reg = cval;
   1.316 +                ++rc;
   1.317 +            }
   1.318 +            else
   1.319 +                BUG_ON(*reg != (unsigned int)*reg);
   1.320 +        }
   1.321 +    }
   1.322 +
   1.323 +    va_end(args);
   1.324 +
   1.325 +    return rc;
   1.326 +}
   1.327 +#endif
   1.328 +
   1.329  static void relinquish_memory(struct domain *d, struct list_head *list)
   1.330  {
   1.331      struct list_head *ent;
     2.1 --- a/xen/arch/x86/domain_build.c	Fri Jan 05 17:34:30 2007 +0000
     2.2 +++ b/xen/arch/x86/domain_build.c	Fri Jan 05 17:34:31 2007 +0000
     2.3 @@ -688,7 +688,11 @@ int construct_dom0(struct domain *d,
     2.4          l4e_from_paddr(__pa(d->arch.mm_perdomain_l3), __PAGE_HYPERVISOR);
     2.5      v->arch.guest_table = pagetable_from_paddr(__pa(l4start));
     2.6      if ( IS_COMPAT(d) )
     2.7 +    {
     2.8          v->arch.guest_table_user = v->arch.guest_table;
     2.9 +        if ( setup_arg_xlat_area(v, l4start) < 0 )
    2.10 +            panic("Not enough RAM for domain 0 hypercall argument translation.\n");
    2.11 +    }
    2.12  
    2.13      l4tab += l4_table_offset(dsi.v_start);
    2.14      mfn = alloc_spfn;
     3.1 --- a/xen/arch/x86/mm.c	Fri Jan 05 17:34:30 2007 +0000
     3.2 +++ b/xen/arch/x86/mm.c	Fri Jan 05 17:34:31 2007 +0000
     3.3 @@ -1147,9 +1147,12 @@ static int alloc_l4_table(struct page_in
     3.4      pl4e[l4_table_offset(LINEAR_PT_VIRT_START)] =
     3.5          l4e_from_pfn(pfn, __PAGE_HYPERVISOR);
     3.6      pl4e[l4_table_offset(PERDOMAIN_VIRT_START)] =
     3.7 -        l4e_from_page(
     3.8 -            virt_to_page(page_get_owner(page)->arch.mm_perdomain_l3),
     3.9 -            __PAGE_HYPERVISOR);
    3.10 +        l4e_from_page(virt_to_page(d->arch.mm_perdomain_l3),
    3.11 +                      __PAGE_HYPERVISOR);
    3.12 +    if ( IS_COMPAT(d) )
    3.13 +        pl4e[l4_table_offset(COMPAT_ARG_XLAT_VIRT_BASE)] =
    3.14 +            l4e_from_page(virt_to_page(d->arch.mm_arg_xlat_l3),
    3.15 +                          __PAGE_HYPERVISOR);
    3.16  
    3.17      return 1;
    3.18  
    3.19 @@ -2756,7 +2759,9 @@ int do_update_va_mapping(unsigned long v
    3.20              flush_tlb_mask(d->domain_dirty_cpumask);
    3.21              break;
    3.22          default:
    3.23 -            if ( unlikely(get_user(vmask, (unsigned long *)bmap_ptr)) )
    3.24 +            if ( unlikely(!IS_COMPAT(d) ?
    3.25 +                          get_user(vmask, (unsigned long *)bmap_ptr) :
    3.26 +                          get_user(vmask, (unsigned int *)bmap_ptr)) )
    3.27                  rc = -EFAULT;
    3.28              pmask = vcpumask_to_pcpumask(d, vmask);
    3.29              flush_tlb_mask(pmask);
     4.1 --- a/xen/arch/x86/x86_64/Makefile	Fri Jan 05 17:34:30 2007 +0000
     4.2 +++ b/xen/arch/x86/x86_64/Makefile	Fri Jan 05 17:34:31 2007 +0000
     4.3 @@ -6,5 +6,6 @@ obj-y += traps.o
     4.4  ifeq ($(CONFIG_COMPAT),y)
     4.5  # extra dependencies
     4.6  entry.o:	compat/entry.S
     4.7 +mm.o:		compat/mm.c
     4.8  traps.o:	compat/traps.c
     4.9  endif
     5.1 --- a/xen/arch/x86/x86_64/compat/entry.S	Fri Jan 05 17:34:30 2007 +0000
     5.2 +++ b/xen/arch/x86/x86_64/compat/entry.S	Fri Jan 05 17:34:31 2007 +0000
     5.3 @@ -282,15 +282,11 @@ CFIX14:
     5.4  #define compat_mmu_update domain_crash_synchronous
     5.5  #define compat_set_gdt domain_crash_synchronous
     5.6  #define compat_platform_op domain_crash_synchronous
     5.7 -#define compat_update_descriptor domain_crash_synchronous
     5.8 -#define compat_memory_op domain_crash_synchronous
     5.9  #define compat_multicall domain_crash_synchronous
    5.10 -#define compat_update_va_mapping domain_crash_synchronous
    5.11  #define compat_set_timer_op domain_crash_synchronous
    5.12  #define compat_event_channel_op_compat domain_crash_synchronous
    5.13  #define compat_physdev_op_compat domain_crash_synchronous
    5.14  #define compat_grant_table_op domain_crash_synchronous
    5.15 -#define compat_update_va_mapping_otherdomain domain_crash_synchronous
    5.16  #define compat_vcpu_op domain_crash_synchronous
    5.17  #define compat_mmuext_op domain_crash_synchronous
    5.18  #define compat_acm_op domain_crash_synchronous
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen/arch/x86/x86_64/compat/mm.c	Fri Jan 05 17:34:31 2007 +0000
     6.3 @@ -0,0 +1,148 @@
     6.4 +#ifdef CONFIG_COMPAT
     6.5 +
     6.6 +#include <compat/memory.h>
     6.7 +
     6.8 +int compat_update_descriptor(u32 pa_lo, u32 pa_hi, u32 desc_lo, u32 desc_hi)
     6.9 +{
    6.10 +    return do_update_descriptor(pa_lo | ((u64)pa_hi << 32),
    6.11 +                                desc_lo | ((u64)desc_hi << 32));
    6.12 +}
    6.13 +
    6.14 +int compat_arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
    6.15 +{
    6.16 +    struct compat_machphys_mfn_list xmml;
    6.17 +    l2_pgentry_t l2e;
    6.18 +    unsigned long v;
    6.19 +    compat_pfn_t mfn;
    6.20 +    unsigned int i;
    6.21 +    int rc = 0;
    6.22 +
    6.23 +    switch ( op )
    6.24 +    {
    6.25 +    case XENMEM_add_to_physmap:
    6.26 +    {
    6.27 +        struct compat_add_to_physmap cmp;
    6.28 +        struct xen_add_to_physmap *nat = (void *)COMPAT_ARG_XLAT_VIRT_START(current->vcpu_id);
    6.29 +
    6.30 +        if ( copy_from_guest(&cmp, arg, 1) )
    6.31 +            return -EFAULT;
    6.32 +
    6.33 +        XLAT_add_to_physmap(nat, &cmp);
    6.34 +        rc = arch_memory_op(op, guest_handle_from_ptr(nat, void));
    6.35 +
    6.36 +        break;
    6.37 +    }
    6.38 +
    6.39 +    case XENMEM_set_memory_map:
    6.40 +    {
    6.41 +        struct compat_foreign_memory_map cmp;
    6.42 +        struct xen_foreign_memory_map *nat = (void *)COMPAT_ARG_XLAT_VIRT_START(current->vcpu_id);
    6.43 +
    6.44 +        if ( copy_from_guest(&cmp, arg, 1) )
    6.45 +            return -EFAULT;
    6.46 +
    6.47 +#define XLAT_memory_map_HNDL_buffer(_d_, _s_) \
    6.48 +        guest_from_compat_handle((_d_)->buffer, (_s_)->buffer)
    6.49 +        XLAT_foreign_memory_map(nat, &cmp);
    6.50 +#undef XLAT_memory_map_HNDL_buffer
    6.51 +
    6.52 +        rc = arch_memory_op(op, guest_handle_from_ptr(nat, void));
    6.53 +
    6.54 +        break;
    6.55 +    }
    6.56 +
    6.57 +    case XENMEM_memory_map:
    6.58 +    case XENMEM_machine_memory_map:
    6.59 +    {
    6.60 +        struct compat_memory_map cmp;
    6.61 +        struct xen_memory_map *nat = (void *)COMPAT_ARG_XLAT_VIRT_START(current->vcpu_id);
    6.62 +
    6.63 +        if ( copy_from_guest(&cmp, arg, 1) )
    6.64 +            return -EFAULT;
    6.65 +
    6.66 +#define XLAT_memory_map_HNDL_buffer(_d_, _s_) \
    6.67 +        guest_from_compat_handle((_d_)->buffer, (_s_)->buffer)
    6.68 +        XLAT_memory_map(nat, &cmp);
    6.69 +#undef XLAT_memory_map_HNDL_buffer
    6.70 +
    6.71 +        rc = arch_memory_op(op, guest_handle_from_ptr(nat, void));
    6.72 +        if ( rc < 0 )
    6.73 +            break;
    6.74 +
    6.75 +#define XLAT_memory_map_HNDL_buffer(_d_, _s_) ((void)0)
    6.76 +        XLAT_memory_map(&cmp, nat);
    6.77 +#undef XLAT_memory_map_HNDL_buffer
    6.78 +        if ( copy_to_guest(arg, &cmp, 1) )
    6.79 +            rc = -EFAULT;
    6.80 +
    6.81 +        break;
    6.82 +    }
    6.83 +
    6.84 +    case XENMEM_machphys_mapping:
    6.85 +    {
    6.86 +        struct domain *d = current->domain;
    6.87 +        struct compat_machphys_mapping mapping = {
    6.88 +            .v_start = MACH2PHYS_COMPAT_VIRT_START(d),
    6.89 +            .v_end   = MACH2PHYS_COMPAT_VIRT_END,
    6.90 +            .max_mfn = MACH2PHYS_COMPAT_NR_ENTRIES(d) - 1
    6.91 +        };
    6.92 +
    6.93 +        if ( copy_to_guest(arg, &mapping, 1) )
    6.94 +            rc = -EFAULT;
    6.95 +
    6.96 +        break;
    6.97 +    }
    6.98 +
    6.99 +    case XENMEM_machphys_mfn_list:
   6.100 +        if ( copy_from_guest(&xmml, arg, 1) )
   6.101 +            return -EFAULT;
   6.102 +
   6.103 +        for ( i = 0, v = RDWR_COMPAT_MPT_VIRT_START;
   6.104 +              (i != xmml.max_extents) && (v != RDWR_COMPAT_MPT_VIRT_END);
   6.105 +              i++, v += 1 << L2_PAGETABLE_SHIFT )
   6.106 +        {
   6.107 +            l2e = compat_idle_pg_table_l2[l2_table_offset(v)];
   6.108 +            if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
   6.109 +                break;
   6.110 +            mfn = l2e_get_pfn(l2e) + l1_table_offset(v);
   6.111 +            if ( copy_to_compat_offset(xmml.extent_start, i, &mfn, 1) )
   6.112 +                return -EFAULT;
   6.113 +        }
   6.114 +
   6.115 +        xmml.nr_extents = i;
   6.116 +        if ( copy_to_guest(arg, &xmml, 1) )
   6.117 +            rc = -EFAULT;
   6.118 +
   6.119 +        break;
   6.120 +
   6.121 +    default:
   6.122 +        rc = -ENOSYS;
   6.123 +        break;
   6.124 +    }
   6.125 +
   6.126 +    return rc;
   6.127 +}
   6.128 +
   6.129 +int compat_update_va_mapping(unsigned int va, u32 lo, u32 hi,
   6.130 +                             unsigned int flags)
   6.131 +{
   6.132 +    return do_update_va_mapping(va, lo | ((u64)hi << 32), flags);
   6.133 +}
   6.134 +
   6.135 +int compat_update_va_mapping_otherdomain(unsigned long va, u32 lo, u32 hi,
   6.136 +                                         unsigned long flags,
   6.137 +                                         domid_t domid)
   6.138 +{
   6.139 +    return do_update_va_mapping_otherdomain(va, lo | ((u64)hi << 32), flags, domid);
   6.140 +}
   6.141 +#endif /* CONFIG_COMPAT */
   6.142 +
   6.143 +/*
   6.144 + * Local variables:
   6.145 + * mode: C
   6.146 + * c-set-style: "BSD"
   6.147 + * c-basic-offset: 4
   6.148 + * tab-width: 4
   6.149 + * indent-tabs-mode: nil
   6.150 + * End:
   6.151 + */
     7.1 --- a/xen/arch/x86/x86_64/mm.c	Fri Jan 05 17:34:30 2007 +0000
     7.2 +++ b/xen/arch/x86/x86_64/mm.c	Fri Jan 05 17:34:31 2007 +0000
     7.3 @@ -28,6 +28,7 @@
     7.4  #include <asm/page.h>
     7.5  #include <asm/flushtlb.h>
     7.6  #include <asm/fixmap.h>
     7.7 +#include <asm/hypercall.h>
     7.8  #include <asm/msr.h>
     7.9  #include <public/memory.h>
    7.10  
    7.11 @@ -407,6 +408,8 @@ int check_descriptor(const struct domain
    7.12      return 0;
    7.13  }
    7.14  
    7.15 +#include "compat/mm.c"
    7.16 +
    7.17  /*
    7.18   * Local variables:
    7.19   * mode: C
     8.1 --- a/xen/common/compat/Makefile	Fri Jan 05 17:34:30 2007 +0000
     8.2 +++ b/xen/common/compat/Makefile	Fri Jan 05 17:34:31 2007 +0000
     8.3 @@ -1,4 +1,5 @@
     8.4  obj-y += kernel.o
     8.5 +obj-y += memory.o
     8.6  obj-y += xlat.o
     8.7  
     8.8  # extra dependencies
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen/common/compat/memory.c	Fri Jan 05 17:34:31 2007 +0000
     9.3 @@ -0,0 +1,364 @@
     9.4 +#include <xen/config.h>
     9.5 +#include <xen/types.h>
     9.6 +#include <xen/hypercall.h>
     9.7 +#include <xen/guest_access.h>
     9.8 +#include <xen/sched.h>
     9.9 +#include <xen/event.h>
    9.10 +#include <asm/current.h>
    9.11 +#include <compat/memory.h>
    9.12 +
    9.13 +int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat)
    9.14 +{
    9.15 +    int rc, split, op = cmd & MEMOP_CMD_MASK;
    9.16 +    unsigned int start_extent = cmd >> MEMOP_EXTENT_SHIFT;
    9.17 +
    9.18 +    do
    9.19 +    {
    9.20 +        unsigned int i, end_extent = 0;
    9.21 +        union {
    9.22 +            XEN_GUEST_HANDLE(void) hnd;
    9.23 +            struct xen_memory_reservation *rsrv;
    9.24 +            struct xen_memory_exchange *xchg;
    9.25 +            struct xen_translate_gpfn_list *xlat;
    9.26 +        } nat;
    9.27 +        union {
    9.28 +            struct compat_memory_reservation rsrv;
    9.29 +            struct compat_memory_exchange xchg;
    9.30 +            struct compat_translate_gpfn_list xlat;
    9.31 +        } cmp;
    9.32 +
    9.33 +        set_xen_guest_handle(nat.hnd, (void *)COMPAT_ARG_XLAT_VIRT_START(current->vcpu_id));
    9.34 +        split = 0;
    9.35 +        switch ( op )
    9.36 +        {
    9.37 +            xen_pfn_t *space;
    9.38 +
    9.39 +        case XENMEM_increase_reservation:
    9.40 +        case XENMEM_decrease_reservation:
    9.41 +        case XENMEM_populate_physmap:
    9.42 +            if ( copy_from_guest(&cmp.rsrv, compat, 1) )
    9.43 +                return start_extent;
    9.44 +
    9.45 +            /* Is size too large for us to encode a continuation? */
    9.46 +            if ( cmp.rsrv.nr_extents > (UINT_MAX >> MEMOP_EXTENT_SHIFT) )
    9.47 +                return start_extent;
    9.48 +
    9.49 +            if ( !compat_handle_is_null(cmp.rsrv.extent_start) &&
    9.50 +                 !compat_handle_okay(cmp.rsrv.extent_start, cmp.rsrv.nr_extents) )
    9.51 +                return start_extent;
    9.52 +
    9.53 +            end_extent = start_extent + (COMPAT_ARG_XLAT_SIZE - sizeof(*nat.rsrv)) /
    9.54 +                                        sizeof(*space);
    9.55 +            if ( end_extent > cmp.rsrv.nr_extents )
    9.56 +                end_extent = cmp.rsrv.nr_extents;
    9.57 +
    9.58 +            space = (xen_pfn_t *)(nat.rsrv + 1);
    9.59 +#define XLAT_memory_reservation_HNDL_extent_start(_d_, _s_) \
    9.60 +            do \
    9.61 +            { \
    9.62 +                if ( !compat_handle_is_null((_s_)->extent_start) ) \
    9.63 +                { \
    9.64 +                    set_xen_guest_handle((_d_)->extent_start, space - start_extent); \
    9.65 +                    if ( op != XENMEM_increase_reservation ) \
    9.66 +                    { \
    9.67 +                        for ( i = start_extent; i < end_extent; ++i ) \
    9.68 +                        { \
    9.69 +                            compat_pfn_t pfn; \
    9.70 +                            if ( __copy_from_compat_offset(&pfn, (_s_)->extent_start, i, 1) ) \
    9.71 +                            { \
    9.72 +                                end_extent = i; \
    9.73 +                                split = -1; \
    9.74 +                                break; \
    9.75 +                            } \
    9.76 +                            *space++ = pfn; \
    9.77 +                        } \
    9.78 +                    } \
    9.79 +                } \
    9.80 +                else \
    9.81 +                { \
    9.82 +                    set_xen_guest_handle((_d_)->extent_start, NULL); \
    9.83 +                    end_extent = cmp.rsrv.nr_extents; \
    9.84 +                } \
    9.85 +            } while (0)
    9.86 +            XLAT_memory_reservation(nat.rsrv, &cmp.rsrv);
    9.87 +#undef XLAT_memory_reservation_HNDL_extent_start
    9.88 +
    9.89 +            if ( end_extent < cmp.rsrv.nr_extents )
    9.90 +            {
    9.91 +                nat.rsrv->nr_extents = end_extent;
    9.92 +                ++split;
    9.93 +            }
    9.94 +
    9.95 +            break;
    9.96 +
    9.97 +        case XENMEM_exchange:
    9.98 +        {
    9.99 +            int order_delta;
   9.100 +
   9.101 +            if ( copy_from_guest(&cmp.xchg, compat, 1) )
   9.102 +                return -EFAULT;
   9.103 +
   9.104 +            order_delta = cmp.xchg.out.extent_order - cmp.xchg.in.extent_order;
   9.105 +            /* Various sanity checks. */
   9.106 +            if ( (cmp.xchg.nr_exchanged > cmp.xchg.in.nr_extents) ||
   9.107 +                 (order_delta > 0 && (cmp.xchg.nr_exchanged & ((1U << order_delta) - 1))) ||
   9.108 +                 /* Sizes of input and output lists do not overflow an int? */
   9.109 +                 ((~0U >> cmp.xchg.in.extent_order) < cmp.xchg.in.nr_extents) ||
   9.110 +                 ((~0U >> cmp.xchg.out.extent_order) < cmp.xchg.out.nr_extents) ||
   9.111 +                 /* Sizes of input and output lists match? */
   9.112 +                 ((cmp.xchg.in.nr_extents << cmp.xchg.in.extent_order) !=
   9.113 +                  (cmp.xchg.out.nr_extents << cmp.xchg.out.extent_order)) )
   9.114 +                return -EINVAL;
   9.115 +
   9.116 +            start_extent = cmp.xchg.nr_exchanged;
   9.117 +            end_extent = (COMPAT_ARG_XLAT_SIZE - sizeof(*nat.xchg)) /
   9.118 +                         (((1U << __builtin_abs(order_delta)) + 1) *
   9.119 +                          sizeof(*space));
   9.120 +            if ( end_extent == 0 )
   9.121 +            {
   9.122 +                printk("Cannot translate compatibility mode XENMEM_exchange extents (%u,%u)\n",
   9.123 +                       cmp.xchg.in.extent_order, cmp.xchg.out.extent_order);
   9.124 +                return -E2BIG;
   9.125 +            }
   9.126 +            if ( order_delta > 0 )
   9.127 +                end_extent <<= order_delta;
   9.128 +            end_extent += start_extent;
   9.129 +            if ( end_extent > cmp.xchg.in.nr_extents )
   9.130 +                end_extent = cmp.xchg.in.nr_extents;
   9.131 +
   9.132 +            space = (xen_pfn_t *)(nat.xchg + 1);
   9.133 +            /* Code below depends upon .in preceding .out. */
   9.134 +            BUILD_BUG_ON(offsetof(xen_memory_exchange_t, in) > offsetof(xen_memory_exchange_t, out));
   9.135 +#define XLAT_memory_reservation_HNDL_extent_start(_d_, _s_) \
   9.136 +            do \
   9.137 +            { \
   9.138 +                set_xen_guest_handle((_d_)->extent_start, space - start_extent); \
   9.139 +                for ( i = start_extent; i < end_extent; ++i ) \
   9.140 +                { \
   9.141 +                    compat_pfn_t pfn; \
   9.142 +                    if ( __copy_from_compat_offset(&pfn, (_s_)->extent_start, i, 1) ) \
   9.143 +                        return -EFAULT; \
   9.144 +                    *space++ = pfn; \
   9.145 +                } \
   9.146 +                if ( order_delta > 0 ) \
   9.147 +                { \
   9.148 +                    start_extent >>= order_delta; \
   9.149 +                    end_extent >>= order_delta; \
   9.150 +                } \
   9.151 +                else \
   9.152 +                { \
   9.153 +                    start_extent <<= -order_delta; \
   9.154 +                    end_extent <<= -order_delta; \
   9.155 +                } \
   9.156 +                order_delta = -order_delta; \
   9.157 +            } while (0)
   9.158 +            XLAT_memory_exchange(nat.xchg, &cmp.xchg);
   9.159 +#undef XLAT_memory_reservation_HNDL_extent_start
   9.160 +
   9.161 +            if ( end_extent < cmp.xchg.in.nr_extents )
   9.162 +            {
   9.163 +                nat.xchg->in.nr_extents = end_extent;
   9.164 +                if ( order_delta >= 0 )
   9.165 +                    nat.xchg->out.nr_extents = end_extent >> order_delta;
   9.166 +                else
   9.167 +                    nat.xchg->out.nr_extents = end_extent << order_delta;
   9.168 +                ++split;
   9.169 +            }
   9.170 +
   9.171 +            break;
   9.172 +        }
   9.173 +
   9.174 +        case XENMEM_current_reservation:
   9.175 +        case XENMEM_maximum_reservation:
   9.176 +        {
   9.177 +#define xen_domid_t domid_t
   9.178 +#define compat_domid_t domid_compat_t
   9.179 +            CHECK_TYPE(domid);
   9.180 +#undef compat_domid_t
   9.181 +#undef xen_domid_t
   9.182 +        }
   9.183 +        case XENMEM_maximum_ram_page:
   9.184 +            nat.hnd = compat;
   9.185 +            break;
   9.186 +
   9.187 +        case XENMEM_translate_gpfn_list:
   9.188 +            if ( copy_from_guest(&cmp.xlat, compat, 1) )
   9.189 +                return -EFAULT;
   9.190 +
   9.191 +            /* Is size too large for us to encode a continuation? */
   9.192 +            if ( cmp.xlat.nr_gpfns > (UINT_MAX >> MEMOP_EXTENT_SHIFT) )
   9.193 +                return -EINVAL;
   9.194 +
   9.195 +            if ( !compat_handle_okay(cmp.xlat.gpfn_list, cmp.xlat.nr_gpfns) ||
   9.196 +                 !compat_handle_okay(cmp.xlat.mfn_list,  cmp.xlat.nr_gpfns) )
   9.197 +                return -EFAULT;
   9.198 +
   9.199 +            end_extent = start_extent + (COMPAT_ARG_XLAT_SIZE - sizeof(*nat.xlat)) /
   9.200 +                                        sizeof(*space);
   9.201 +            if ( end_extent > cmp.xlat.nr_gpfns )
   9.202 +                end_extent = cmp.xlat.nr_gpfns;
   9.203 +
   9.204 +            space = (xen_pfn_t *)(nat.xlat + 1);
   9.205 +            /* Code below depends upon .gpfn_list preceding .mfn_list. */
   9.206 +            BUILD_BUG_ON(offsetof(xen_translate_gpfn_list_t, gpfn_list) > offsetof(xen_translate_gpfn_list_t, mfn_list));
   9.207 +#define XLAT_translate_gpfn_list_HNDL_gpfn_list(_d_, _s_) \
   9.208 +            do \
   9.209 +            { \
   9.210 +                set_xen_guest_handle((_d_)->gpfn_list, space - start_extent); \
   9.211 +                for ( i = start_extent; i < end_extent; ++i ) \
   9.212 +                { \
   9.213 +                    compat_pfn_t pfn; \
   9.214 +                    if ( __copy_from_compat_offset(&pfn, (_s_)->gpfn_list, i, 1) ) \
   9.215 +                        return -EFAULT; \
   9.216 +                    *space++ = pfn; \
   9.217 +                } \
   9.218 +            } while (0)
   9.219 +#define XLAT_translate_gpfn_list_HNDL_mfn_list(_d_, _s_) \
   9.220 +            (_d_)->mfn_list = (_d_)->gpfn_list
   9.221 +            XLAT_translate_gpfn_list(nat.xlat, &cmp.xlat);
   9.222 +#undef XLAT_translate_gpfn_list_HNDL_mfn_list
   9.223 +#undef XLAT_translate_gpfn_list_HNDL_gpfn_list
   9.224 +
   9.225 +            if ( end_extent < cmp.xlat.nr_gpfns )
   9.226 +            {
   9.227 +                nat.xlat->nr_gpfns = end_extent;
   9.228 +                ++split;
   9.229 +            }
   9.230 +
   9.231 +            break;
   9.232 +
   9.233 +        default:
   9.234 +            return compat_arch_memory_op(cmd, compat);
   9.235 +        }
   9.236 +
   9.237 +        rc = do_memory_op(cmd, nat.hnd);
   9.238 +        if ( rc < 0 )
   9.239 +            return rc;
   9.240 +
   9.241 +        cmd = 0;
   9.242 +        if ( hypercall_xlat_continuation(&cmd, 0x02, nat.hnd, compat) )
   9.243 +        {
   9.244 +            BUG_ON(rc != __HYPERVISOR_memory_op);
   9.245 +            BUG_ON((cmd & MEMOP_CMD_MASK) != op);
   9.246 +            split = -1;
   9.247 +        }
   9.248 +
   9.249 +        switch ( op )
   9.250 +        {
   9.251 +        case XENMEM_increase_reservation:
   9.252 +        case XENMEM_decrease_reservation:
   9.253 +        case XENMEM_populate_physmap:
   9.254 +            end_extent = split >= 0 ? rc : cmd >> MEMOP_EXTENT_SHIFT;
   9.255 +            if ( op != XENMEM_decrease_reservation &&
   9.256 +                 !guest_handle_is_null(nat.rsrv->extent_start) )
   9.257 +            {
   9.258 +                for ( ; start_extent < end_extent; ++start_extent )
   9.259 +                {
   9.260 +                    compat_pfn_t pfn = nat.rsrv->extent_start.p[start_extent];
   9.261 +
   9.262 +                    BUG_ON(pfn != nat.rsrv->extent_start.p[start_extent]);
   9.263 +                    if ( __copy_to_compat_offset(cmp.rsrv.extent_start, start_extent, &pfn, 1) )
   9.264 +                    {
   9.265 +                        if ( split >= 0 )
   9.266 +                        {
   9.267 +                            rc = start_extent;
   9.268 +                            split = 0;
   9.269 +                        }
   9.270 +                        else
   9.271 +                            /*
   9.272 +                             * Short of being able to cancel the continuation,
   9.273 +                             * force it to restart here; eventually we shall
   9.274 +                             * get out of this state.
   9.275 +                             */
   9.276 +                            rc = (start_extent << MEMOP_EXTENT_SHIFT) | op;
   9.277 +                        break;
   9.278 +                    }
   9.279 +                }
   9.280 +            }
   9.281 +            else
   9.282 +                start_extent = end_extent;
   9.283 +            break;
   9.284 +
   9.285 +        case XENMEM_exchange:
   9.286 +        {
   9.287 +            DEFINE_XEN_GUEST_HANDLE(compat_memory_exchange_t);
   9.288 +            int order_delta;
   9.289 +
   9.290 +            BUG_ON(split >= 0 && rc);
   9.291 +            BUG_ON(end_extent < nat.xchg->nr_exchanged);
   9.292 +            end_extent = nat.xchg->nr_exchanged;
   9.293 +
   9.294 +            order_delta = cmp.xchg.out.extent_order - cmp.xchg.in.extent_order;
   9.295 +            if ( order_delta > 0 )
   9.296 +            {
   9.297 +                start_extent >>= order_delta;
   9.298 +                BUG_ON(end_extent & ((1U << order_delta) - 1));
   9.299 +                end_extent >>= order_delta;
   9.300 +            }
   9.301 +            else
   9.302 +            {
   9.303 +                start_extent <<= -order_delta;
   9.304 +                end_extent <<= -order_delta;
   9.305 +            }
   9.306 +
   9.307 +            for ( ; start_extent < end_extent; ++start_extent )
   9.308 +            {
   9.309 +                compat_pfn_t pfn = nat.xchg->out.extent_start.p[start_extent];
   9.310 +
   9.311 +                BUG_ON(pfn != nat.xchg->out.extent_start.p[start_extent]);
   9.312 +                /* Note that we ignore errors accessing the output extent list. */
   9.313 +                __copy_to_compat_offset(cmp.xchg.out.extent_start, start_extent, &pfn, 1);
   9.314 +            }
   9.315 +
   9.316 +            cmp.xchg.nr_exchanged = nat.xchg->nr_exchanged;
   9.317 +            if ( copy_field_to_guest(guest_handle_cast(compat, compat_memory_exchange_t),
   9.318 +                                     &cmp.xchg, nr_exchanged) )
   9.319 +            {
   9.320 +                if ( split < 0 )
   9.321 +                    /* Cannot cancel the continuation... */
   9.322 +                    domain_crash(current->domain);
   9.323 +                return -EFAULT;
   9.324 +            }
   9.325 +            break;
   9.326 +        }
   9.327 +
   9.328 +        case XENMEM_maximum_ram_page:
   9.329 +        case XENMEM_current_reservation:
   9.330 +        case XENMEM_maximum_reservation:
   9.331 +            break;
   9.332 +
   9.333 +        case XENMEM_translate_gpfn_list:
   9.334 +            if ( split < 0 )
   9.335 +                end_extent = cmd >> MEMOP_EXTENT_SHIFT;
   9.336 +            else
   9.337 +                BUG_ON(rc);
   9.338 +
   9.339 +            for ( ; start_extent < end_extent; ++start_extent )
   9.340 +            {
   9.341 +                compat_pfn_t pfn = nat.xlat->mfn_list.p[start_extent];
   9.342 +
   9.343 +                BUG_ON(pfn != nat.xlat->mfn_list.p[start_extent]);
   9.344 +                if ( __copy_to_compat_offset(cmp.xlat.mfn_list, start_extent, &pfn, 1) )
   9.345 +                {
   9.346 +                    if ( split < 0 )
   9.347 +                        /* Cannot cancel the continuation... */
   9.348 +                        domain_crash(current->domain);
   9.349 +                    return -EFAULT;
   9.350 +                }
   9.351 +            }
   9.352 +            break;
   9.353 +
   9.354 +        default:
   9.355 +            domain_crash(current->domain);
   9.356 +            split = 0;
   9.357 +            break;
   9.358 +        }
   9.359 +
   9.360 +        cmd = op | (start_extent << MEMOP_EXTENT_SHIFT);
   9.361 +        if ( split > 0 && hypercall_preempt_check() )
   9.362 +            return hypercall_create_continuation(
   9.363 +                __HYPERVISOR_memory_op, "ih", cmd, compat);
   9.364 +    } while ( split > 0 );
   9.365 +
   9.366 +    return rc;
   9.367 +}
    10.1 --- a/xen/common/memory.c	Fri Jan 05 17:34:30 2007 +0000
    10.2 +++ b/xen/common/memory.c	Fri Jan 05 17:34:31 2007 +0000
    10.3 @@ -17,18 +17,12 @@
    10.4  #include <xen/shadow.h>
    10.5  #include <xen/iocap.h>
    10.6  #include <xen/guest_access.h>
    10.7 +#include <xen/hypercall.h>
    10.8  #include <xen/errno.h>
    10.9  #include <asm/current.h>
   10.10  #include <asm/hardirq.h>
   10.11  #include <public/memory.h>
   10.12  
   10.13 -/*
   10.14 - * To allow safe resume of do_memory_op() after preemption, we need to know 
   10.15 - * at what point in the page list to resume. For this purpose I steal the 
   10.16 - * high-order bits of the @cmd parameter, which are otherwise unused and zero.
   10.17 - */
   10.18 -#define START_EXTENT_SHIFT 4 /* cmd[:4] == start_extent */
   10.19 -
   10.20  struct memop_args {
   10.21      /* INPUT */
   10.22      struct domain *domain;     /* Domain to be affected. */
   10.23 @@ -236,7 +230,7 @@ static long translate_gpfn_list(
   10.24          return -EFAULT;
   10.25  
   10.26      /* Is size too large for us to encode a continuation? */
   10.27 -    if ( op.nr_gpfns > (ULONG_MAX >> START_EXTENT_SHIFT) )
   10.28 +    if ( op.nr_gpfns > (ULONG_MAX >> MEMOP_EXTENT_SHIFT) )
   10.29          return -EINVAL;
   10.30  
   10.31      if ( !guest_handle_okay(op.gpfn_list, op.nr_gpfns) ||
   10.32 @@ -511,20 +505,20 @@ long do_memory_op(unsigned long cmd, XEN
   10.33      struct memop_args args;
   10.34      domid_t domid;
   10.35  
   10.36 -    op = cmd & ((1 << START_EXTENT_SHIFT) - 1);
   10.37 +    op = cmd & MEMOP_CMD_MASK;
   10.38  
   10.39      switch ( op )
   10.40      {
   10.41      case XENMEM_increase_reservation:
   10.42      case XENMEM_decrease_reservation:
   10.43      case XENMEM_populate_physmap:
   10.44 -        start_extent = cmd >> START_EXTENT_SHIFT;
   10.45 +        start_extent = cmd >> MEMOP_EXTENT_SHIFT;
   10.46  
   10.47          if ( copy_from_guest(&reservation, arg, 1) )
   10.48              return start_extent;
   10.49  
   10.50          /* Is size too large for us to encode a continuation? */
   10.51 -        if ( reservation.nr_extents > (ULONG_MAX >> START_EXTENT_SHIFT) )
   10.52 +        if ( reservation.nr_extents > (ULONG_MAX >> MEMOP_EXTENT_SHIFT) )
   10.53              return start_extent;
   10.54  
   10.55          if ( unlikely(start_extent > reservation.nr_extents) )
   10.56 @@ -574,7 +568,7 @@ long do_memory_op(unsigned long cmd, XEN
   10.57          if ( args.preempted )
   10.58              return hypercall_create_continuation(
   10.59                  __HYPERVISOR_memory_op, "lh",
   10.60 -                op | (rc << START_EXTENT_SHIFT), arg);
   10.61 +                op | (rc << MEMOP_EXTENT_SHIFT), arg);
   10.62  
   10.63          break;
   10.64  
   10.65 @@ -606,14 +600,14 @@ long do_memory_op(unsigned long cmd, XEN
   10.66          break;
   10.67  
   10.68      case XENMEM_translate_gpfn_list:
   10.69 -        progress = cmd >> START_EXTENT_SHIFT;
   10.70 +        progress = cmd >> MEMOP_EXTENT_SHIFT;
   10.71          rc = translate_gpfn_list(
   10.72              guest_handle_cast(arg, xen_translate_gpfn_list_t),
   10.73              &progress);
   10.74          if ( rc == -EAGAIN )
   10.75              return hypercall_create_continuation(
   10.76                  __HYPERVISOR_memory_op, "lh",
   10.77 -                op | (progress << START_EXTENT_SHIFT), arg);
   10.78 +                op | (progress << MEMOP_EXTENT_SHIFT), arg);
   10.79          break;
   10.80  
   10.81      default:
    11.1 --- a/xen/include/asm-x86/config.h	Fri Jan 05 17:34:30 2007 +0000
    11.2 +++ b/xen/include/asm-x86/config.h	Fri Jan 05 17:34:31 2007 +0000
    11.3 @@ -108,7 +108,7 @@
    11.4  /*
    11.5   * Memory layout:
    11.6   *  0x0000000000000000 - 0x00007fffffffffff [128TB, 2^47 bytes, PML4:0-255]
    11.7 - *    Guest-defined use.
    11.8 + *    Guest-defined use (see below for compatibility mode guests).
    11.9   *  0x0000800000000000 - 0xffff7fffffffffff [16EB]
   11.10   *    Inaccessible: current arch only supports 48-bit sign-extended VAs.
   11.11   *  0xffff800000000000 - 0xffff803fffffffff [256GB, 2^38 bytes, PML4:256]
   11.12 @@ -141,6 +141,18 @@
   11.13   *    Reserved for future use.
   11.14   *  0xffff880000000000 - 0xffffffffffffffff [120TB, PML4:272-511]
   11.15   *    Guest-defined use.
   11.16 + *
   11.17 + * Compatibility guest area layout:
   11.18 + *  0x0000000000000000 - 0x00000000f57fffff [3928MB,            PML4:0]
   11.19 + *    Guest-defined use.
   11.20 + *  0x0000000f58000000 - 0x00000000ffffffff [168MB,             PML4:0]
   11.21 + *    Read-only machine-to-phys translation table (GUEST ACCESSIBLE).
   11.22 + *  0x0000000000000000 - 0x00000000ffffffff [508GB,             PML4:0]
   11.23 + *    Unused.
   11.24 + *  0x0000008000000000 - 0x000000ffffffffff [512GB, 2^39 bytes, PML4:1]
   11.25 + *    Hypercall argument translation area.
   11.26 + *  0x0000010000000000 - 0x00007fffffffffff [127TB, 2^46 bytes, PML4:2-255]
   11.27 + *    Reserved for future use.
   11.28   */
   11.29  
   11.30  
   11.31 @@ -210,6 +222,14 @@
   11.32  
   11.33  #endif
   11.34  
   11.35 +#define COMPAT_ARG_XLAT_VIRT_BASE      (1UL << ROOT_PAGETABLE_SHIFT)
   11.36 +#define COMPAT_ARG_XLAT_SHIFT          0
   11.37 +#define COMPAT_ARG_XLAT_PAGES          (1U << COMPAT_ARG_XLAT_SHIFT)
   11.38 +#define COMPAT_ARG_XLAT_SIZE           (COMPAT_ARG_XLAT_PAGES << PAGE_SHIFT)
   11.39 +#define COMPAT_ARG_XLAT_VIRT_START(vcpu_id) \
   11.40 +    (COMPAT_ARG_XLAT_VIRT_BASE + ((unsigned long)(vcpu_id) << \
   11.41 +                                  (PAGE_SHIFT + COMPAT_ARG_XLAT_SHIFT + 1)))
   11.42 +
   11.43  #define PGT_base_page_table     PGT_l4_page_table
   11.44  
   11.45  #define __HYPERVISOR_CS64 0xe008
    12.1 --- a/xen/include/asm-x86/domain.h	Fri Jan 05 17:34:30 2007 +0000
    12.2 +++ b/xen/include/asm-x86/domain.h	Fri Jan 05 17:34:31 2007 +0000
    12.3 @@ -100,6 +100,7 @@ struct arch_domain
    12.4  
    12.5  #ifdef CONFIG_COMPAT
    12.6      unsigned int hv_compat_vstart;
    12.7 +    l3_pgentry_t *mm_arg_xlat_l3;
    12.8  #endif
    12.9  
   12.10      /* I/O-port admin-specified access capabilities. */
    13.1 --- a/xen/include/asm-x86/mm.h	Fri Jan 05 17:34:30 2007 +0000
    13.2 +++ b/xen/include/asm-x86/mm.h	Fri Jan 05 17:34:31 2007 +0000
    13.3 @@ -329,10 +329,20 @@ int __sync_lazy_execstate(void);
    13.4  /* Arch-specific portion of memory_op hypercall. */
    13.5  long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg);
    13.6  long subarch_memory_op(int op, XEN_GUEST_HANDLE(void) arg);
    13.7 +#ifdef CONFIG_COMPAT
    13.8 +int compat_arch_memory_op(int op, XEN_GUEST_HANDLE(void));
    13.9 +int compat_subarch_memory_op(int op, XEN_GUEST_HANDLE(void));
   13.10 +#endif
   13.11  
   13.12  int steal_page(
   13.13      struct domain *d, struct page_info *page, unsigned int memflags);
   13.14  
   13.15  int map_ldt_shadow_page(unsigned int);
   13.16  
   13.17 +#ifdef CONFIG_COMPAT
   13.18 +int setup_arg_xlat_area(struct vcpu *, l4_pgentry_t *);
   13.19 +#else
   13.20 +# define setup_arg_xlat_area(vcpu, l4tab) 0
   13.21 +#endif
   13.22 +
   13.23  #endif /* __ASM_X86_MM_H__ */
    14.1 --- a/xen/include/xen/compat.h	Fri Jan 05 17:34:30 2007 +0000
    14.2 +++ b/xen/include/xen/compat.h	Fri Jan 05 17:34:31 2007 +0000
    14.3 @@ -158,6 +158,8 @@
    14.4  
    14.5  extern int compat_disabled;
    14.6  
    14.7 +int hypercall_xlat_continuation(unsigned int *id, unsigned int mask, ...);
    14.8 +
    14.9  /* In-place translation functons: */
   14.10  struct start_info;
   14.11  void xlat_start_info(struct start_info *, enum XLAT_start_info_console);
    15.1 --- a/xen/include/xen/hypercall.h	Fri Jan 05 17:34:30 2007 +0000
    15.2 +++ b/xen/include/xen/hypercall.h	Fri Jan 05 17:34:31 2007 +0000
    15.3 @@ -42,9 +42,17 @@ extern long
    15.4  do_platform_op(
    15.5      XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op);
    15.6  
    15.7 +/*
    15.8 + * To allow safe resume of do_memory_op() after preemption, we need to know
    15.9 + * at what point in the page list to resume. For this purpose I steal the
   15.10 + * high-order bits of the @cmd parameter, which are otherwise unused and zero.
   15.11 + */
   15.12 +#define MEMOP_EXTENT_SHIFT 4 /* cmd[:4] == start_extent */
   15.13 +#define MEMOP_CMD_MASK     ((1 << MEMOP_EXTENT_SHIFT) - 1)
   15.14 +
   15.15  extern long
   15.16  do_memory_op(
   15.17 -    int cmd,
   15.18 +    unsigned long cmd,
   15.19      XEN_GUEST_HANDLE(void) arg);
   15.20  
   15.21  extern long
   15.22 @@ -108,4 +116,13 @@ do_kexec_op(
   15.23      int arg1,
   15.24      XEN_GUEST_HANDLE(void) arg);
   15.25  
   15.26 +#ifdef CONFIG_COMPAT
   15.27 +
   15.28 +extern int
   15.29 +compat_memory_op(
   15.30 +    unsigned int cmd,
   15.31 +    XEN_GUEST_HANDLE(void) arg);
   15.32 +
   15.33 +#endif
   15.34 +
   15.35  #endif /* __XEN_HYPERCALL_H__ */
    16.1 --- a/xen/include/xlat.lst	Fri Jan 05 17:34:30 2007 +0000
    16.2 +++ b/xen/include/xlat.lst	Fri Jan 05 17:34:31 2007 +0000
    16.3 @@ -4,3 +4,9 @@
    16.4  ?	dom0_vga_console_info		xen.h
    16.5  !	start_info			xen.h
    16.6  ?	vcpu_time_info			xen.h
    16.7 +!	add_to_physmap			memory.h
    16.8 +!	foreign_memory_map		memory.h
    16.9 +!	memory_exchange			memory.h
   16.10 +!	memory_map			memory.h
   16.11 +!	memory_reservation		memory.h
   16.12 +!	translate_gpfn_list		memory.h