ia64/xen-unstable

changeset 13296:e4088ae584b8

Enable compatibility mode operation for HYPERVISOR_mmu_update and
HYPERVISOR_mmuext_op.

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 244e46e7d021
children ee395551208d
files xen/arch/x86/mm.c xen/arch/x86/x86_64/compat/entry.S xen/arch/x86/x86_64/compat/mm.c xen/common/compat/xlat.c xen/include/asm-x86/hypercall.h xen/include/xlat.lst
line diff
     1.1 --- a/xen/arch/x86/mm.c	Fri Jan 05 17:34:31 2007 +0000
     1.2 +++ b/xen/arch/x86/mm.c	Fri Jan 05 17:34:31 2007 +0000
     1.3 @@ -106,6 +106,7 @@
     1.4  #include <asm/ldt.h>
     1.5  #include <asm/x86_emulate.h>
     1.6  #include <asm/e820.h>
     1.7 +#include <asm/hypercall.h>
     1.8  #include <public/memory.h>
     1.9  
    1.10  #define MEM_LOG(_f, _a...) gdprintk(XENLOG_WARNING , _f "\n" , ## _a)
    1.11 @@ -119,13 +120,6 @@
    1.12  #define PTE_UPDATE_WITH_CMPXCHG
    1.13  #endif
    1.14  
    1.15 -/*
    1.16 - * Both do_mmuext_op() and do_mmu_update():
    1.17 - * We steal the m.s.b. of the @count parameter to indicate whether this
    1.18 - * invocation of do_mmu_update() is resuming a previously preempted call.
    1.19 - */
    1.20 -#define MMU_UPDATE_PREEMPTED          (~(~0U>>1))
    1.21 -
    1.22  /* Used to defer flushing of memory structures. */
    1.23  struct percpu_mm_info {
    1.24  #define DOP_FLUSH_TLB      (1<<0) /* Flush the local TLB.                    */
    1.25 @@ -2033,6 +2027,8 @@ int do_mmuext_op(
    1.26              goto pin_page;
    1.27  
    1.28          case MMUEXT_PIN_L4_TABLE:
    1.29 +            if ( IS_COMPAT(FOREIGNDOM) )
    1.30 +                break;
    1.31              type = PGT_l4_page_table;
    1.32  
    1.33          pin_page:
    1.34 @@ -2096,7 +2092,11 @@ int do_mmuext_op(
    1.35          
    1.36  #ifdef __x86_64__
    1.37          case MMUEXT_NEW_USER_BASEPTR:
    1.38 -            okay = 1;
    1.39 +            if ( IS_COMPAT(FOREIGNDOM) )
    1.40 +            {
    1.41 +                okay = 0;
    1.42 +                break;
    1.43 +            }
    1.44              if (likely(mfn != 0))
    1.45              {
    1.46                  if ( shadow_mode_refcounts(d) )
     2.1 --- a/xen/arch/x86/x86_64/compat/entry.S	Fri Jan 05 17:34:31 2007 +0000
     2.2 +++ b/xen/arch/x86/x86_64/compat/entry.S	Fri Jan 05 17:34:31 2007 +0000
     2.3 @@ -279,7 +279,6 @@ CFIX14:
     2.4  .section .rodata, "a", @progbits
     2.5  
     2.6  #define compat_set_trap_table domain_crash_synchronous
     2.7 -#define compat_mmu_update domain_crash_synchronous
     2.8  #define compat_set_gdt domain_crash_synchronous
     2.9  #define compat_platform_op domain_crash_synchronous
    2.10  #define compat_multicall domain_crash_synchronous
    2.11 @@ -288,7 +287,6 @@ CFIX14:
    2.12  #define compat_physdev_op_compat domain_crash_synchronous
    2.13  #define compat_grant_table_op domain_crash_synchronous
    2.14  #define compat_vcpu_op domain_crash_synchronous
    2.15 -#define compat_mmuext_op domain_crash_synchronous
    2.16  #define compat_acm_op domain_crash_synchronous
    2.17  #define compat_arch_sched_op domain_crash_synchronous
    2.18  #define compat_xenoprof_op domain_crash_synchronous
    2.19 @@ -299,7 +297,7 @@ CFIX14:
    2.20  
    2.21  ENTRY(compat_hypercall_table)
    2.22          .quad compat_set_trap_table     /*  0 */
    2.23 -        .quad compat_mmu_update
    2.24 +        .quad do_mmu_update
    2.25          .quad compat_set_gdt
    2.26          .quad do_stack_switch
    2.27          .quad compat_set_callbacks
     3.1 --- a/xen/arch/x86/x86_64/compat/mm.c	Fri Jan 05 17:34:31 2007 +0000
     3.2 +++ b/xen/arch/x86/x86_64/compat/mm.c	Fri Jan 05 17:34:31 2007 +0000
     3.3 @@ -1,6 +1,8 @@
     3.4  #ifdef CONFIG_COMPAT
     3.5  
     3.6 +#include <xen/event.h>
     3.7  #include <compat/memory.h>
     3.8 +#include <compat/xen.h>
     3.9  
    3.10  int compat_update_descriptor(u32 pa_lo, u32 pa_hi, u32 desc_lo, u32 desc_hi)
    3.11  {
    3.12 @@ -135,6 +137,152 @@ int compat_update_va_mapping_otherdomain
    3.13  {
    3.14      return do_update_va_mapping_otherdomain(va, lo | ((u64)hi << 32), flags, domid);
    3.15  }
    3.16 +
    3.17 +DEFINE_XEN_GUEST_HANDLE(mmuext_op_compat_t);
    3.18 +
    3.19 +int compat_mmuext_op(XEN_GUEST_HANDLE(mmuext_op_compat_t) cmp_uops,
    3.20 +                     unsigned int count,
    3.21 +                     XEN_GUEST_HANDLE(uint) pdone,
    3.22 +                     unsigned int foreigndom)
    3.23 +{
    3.24 +    unsigned int i, preempt_mask;
    3.25 +    int rc = 0;
    3.26 +    XEN_GUEST_HANDLE(mmuext_op_t) nat_ops;
    3.27 +
    3.28 +    preempt_mask = count & MMU_UPDATE_PREEMPTED;
    3.29 +    count ^= preempt_mask;
    3.30 +
    3.31 +    if ( unlikely(!guest_handle_okay(cmp_uops, count)) )
    3.32 +        return -EFAULT;
    3.33 +
    3.34 +    set_xen_guest_handle(nat_ops, (void *)COMPAT_ARG_XLAT_VIRT_START(current->vcpu_id));
    3.35 +
    3.36 +    for ( ; count; count -= i )
    3.37 +    {
    3.38 +        mmuext_op_t *nat_op = nat_ops.p;
    3.39 +        unsigned int limit;
    3.40 +        int err;
    3.41 +
    3.42 +        if ( hypercall_preempt_check() )
    3.43 +        {
    3.44 +            rc = hypercall_create_continuation(
    3.45 +                __HYPERVISOR_mmuext_op, "hihi",
    3.46 +                cmp_uops, count | MMU_UPDATE_PREEMPTED, pdone, foreigndom);
    3.47 +            break;
    3.48 +        }
    3.49 +
    3.50 +        limit = COMPAT_ARG_XLAT_SIZE / sizeof(*nat_op);
    3.51 +
    3.52 +        for ( i = 0; i < min(limit, count); ++i )
    3.53 +        {
    3.54 +            mmuext_op_compat_t cmp_op;
    3.55 +            enum XLAT_mmuext_op_arg1 arg1;
    3.56 +            enum XLAT_mmuext_op_arg2 arg2;
    3.57 +
    3.58 +            if ( unlikely(__copy_from_guest(&cmp_op, cmp_uops, 1) != 0) )
    3.59 +            {
    3.60 +                rc = -EFAULT;
    3.61 +                break;
    3.62 +            }
    3.63 +
    3.64 +            switch ( cmp_op.cmd )
    3.65 +            {
    3.66 +            case MMUEXT_PIN_L1_TABLE:
    3.67 +            case MMUEXT_PIN_L2_TABLE:
    3.68 +            case MMUEXT_PIN_L3_TABLE:
    3.69 +            case MMUEXT_PIN_L4_TABLE:
    3.70 +            case MMUEXT_UNPIN_TABLE:
    3.71 +            case MMUEXT_NEW_BASEPTR:
    3.72 +                arg1 = XLAT_mmuext_op_arg1_mfn;
    3.73 +                break;
    3.74 +            default:
    3.75 +                arg1 = XLAT_mmuext_op_arg1_linear_addr;
    3.76 +                break;
    3.77 +            case MMUEXT_NEW_USER_BASEPTR:
    3.78 +                rc = -EINVAL;
    3.79 +            case MMUEXT_TLB_FLUSH_LOCAL:
    3.80 +            case MMUEXT_TLB_FLUSH_MULTI:
    3.81 +            case MMUEXT_TLB_FLUSH_ALL:
    3.82 +            case MMUEXT_FLUSH_CACHE:
    3.83 +                arg1 = -1;
    3.84 +                break;
    3.85 +            }
    3.86 +
    3.87 +            if ( rc )
    3.88 +                break;
    3.89 +
    3.90 +            switch ( cmp_op.cmd )
    3.91 +            {
    3.92 +            case MMUEXT_SET_LDT:
    3.93 +                arg2 = XLAT_mmuext_op_arg2_nr_ents;
    3.94 +                break;
    3.95 +            case MMUEXT_TLB_FLUSH_MULTI:
    3.96 +            case MMUEXT_INVLPG_MULTI:
    3.97 +                arg2 = XLAT_mmuext_op_arg2_vcpumask;
    3.98 +                break;
    3.99 +            default:
   3.100 +                arg2 = -1;
   3.101 +                break;
   3.102 +            }
   3.103 +
   3.104 +#define XLAT_mmuext_op_HNDL_arg2_vcpumask(_d_, _s_) \
   3.105 +            do \
   3.106 +            { \
   3.107 +                unsigned int vcpumask; \
   3.108 +                if ( i < --limit ) \
   3.109 +                { \
   3.110 +                    (_d_)->arg2.vcpumask.p = (void *)(nat_ops.p + limit); \
   3.111 +                    if ( copy_from_compat(&vcpumask, (_s_)->arg2.vcpumask, 1) == 0 ) \
   3.112 +                        *(unsigned long *)(_d_)->arg2.vcpumask.p = vcpumask; \
   3.113 +                    else \
   3.114 +                        rc = -EFAULT; \
   3.115 +                } \
   3.116 +            } while(0)
   3.117 +            XLAT_mmuext_op(nat_op, &cmp_op);
   3.118 +#undef XLAT_mmuext_op_HNDL_arg2_vcpumask
   3.119 +
   3.120 +            if ( rc || i >= limit )
   3.121 +                break;
   3.122 +
   3.123 +            guest_handle_add_offset(cmp_uops, 1);
   3.124 +            ++nat_op;
   3.125 +        }
   3.126 +
   3.127 +        err = do_mmuext_op(nat_ops, i | preempt_mask, pdone, foreigndom);
   3.128 +
   3.129 +        if ( err )
   3.130 +        {
   3.131 +            BUILD_BUG_ON(__HYPERVISOR_mmuext_op <= 0);
   3.132 +            if ( err == __HYPERVISOR_mmuext_op )
   3.133 +            {
   3.134 +                struct cpu_user_regs *regs = guest_cpu_user_regs();
   3.135 +                unsigned int left = regs->ecx & ~MMU_UPDATE_PREEMPTED;
   3.136 +
   3.137 +                BUG_ON(!(regs->ecx & MMU_UPDATE_PREEMPTED));
   3.138 +                BUG_ON(left > count);
   3.139 +                guest_handle_add_offset(nat_ops, count - left);
   3.140 +                BUG_ON(left + i < count);
   3.141 +                guest_handle_add_offset(cmp_uops, (signed int)(count - left - i));
   3.142 +                left = 1;
   3.143 +                BUG_ON(!hypercall_xlat_continuation(&left, 0x01, nat_ops, cmp_uops));
   3.144 +                BUG_ON(left != regs->ecx);
   3.145 +                regs->ecx += count - i;
   3.146 +            }
   3.147 +            else
   3.148 +                BUG_ON(rc > 0);
   3.149 +            rc = err;
   3.150 +        }
   3.151 +
   3.152 +        if ( rc )
   3.153 +            break;
   3.154 +
   3.155 +        /* Force do_mmuext_op() to not start counting from zero again. */
   3.156 +        preempt_mask = MMU_UPDATE_PREEMPTED;
   3.157 +    }
   3.158 +
   3.159 +    return rc;
   3.160 +}
   3.161 +
   3.162  #endif /* CONFIG_COMPAT */
   3.163  
   3.164  /*
     4.1 --- a/xen/common/compat/xlat.c	Fri Jan 05 17:34:31 2007 +0000
     4.2 +++ b/xen/common/compat/xlat.c	Fri Jan 05 17:34:31 2007 +0000
     4.3 @@ -21,6 +21,10 @@ void xlat_start_info(struct start_info *
     4.4  CHECK_dom0_vga_console_info;
     4.5  #undef dom0_vga_console_info
     4.6  
     4.7 +#define xen_mmu_update mmu_update
     4.8 +CHECK_mmu_update;
     4.9 +#undef xen_mmu_update
    4.10 +
    4.11  #define xen_vcpu_time_info vcpu_time_info
    4.12  CHECK_vcpu_time_info;
    4.13  #undef xen_vcpu_time_info
     5.1 --- a/xen/include/asm-x86/hypercall.h	Fri Jan 05 17:34:31 2007 +0000
     5.2 +++ b/xen/include/asm-x86/hypercall.h	Fri Jan 05 17:34:31 2007 +0000
     5.3 @@ -8,6 +8,13 @@
     5.4  #include <public/physdev.h>
     5.5  #include <xen/types.h>
     5.6  
     5.7 +/*
     5.8 + * Both do_mmuext_op() and do_mmu_update():
     5.9 + * We steal the m.s.b. of the @count parameter to indicate whether this
    5.10 + * invocation of do_mmu_update() is resuming a previously preempted call.
    5.11 + */
    5.12 +#define MMU_UPDATE_PREEMPTED          (~(~0U>>1))
    5.13 +
    5.14  extern long
    5.15  do_event_channel_op_compat(
    5.16      XEN_GUEST_HANDLE(evtchn_op_t) uop);
     6.1 --- a/xen/include/xlat.lst	Fri Jan 05 17:34:31 2007 +0000
     6.2 +++ b/xen/include/xlat.lst	Fri Jan 05 17:34:31 2007 +0000
     6.3 @@ -2,6 +2,8 @@
     6.4  # ! - needs translation
     6.5  # ? - needs checking
     6.6  ?	dom0_vga_console_info		xen.h
     6.7 +?	mmu_update			xen.h
     6.8 +!	mmuext_op			xen.h
     6.9  !	start_info			xen.h
    6.10  ?	vcpu_time_info			xen.h
    6.11  !	add_to_physmap			memory.h