[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Enable compatibility mode operation for HYPERVISOR_mmu_update and



# HG changeset patch
# User Emmanuel Ackaouy <ack@xxxxxxxxxxxxx>
# Date 1168018471 0
# Node ID e4088ae584b81959999318c35bd718c21bed69f2
# Parent  244e46e7d021b1942ace91440c0fdab72a6ce5e4
Enable compatibility mode operation for HYPERVISOR_mmu_update and
HYPERVISOR_mmuext_op.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---
 xen/arch/x86/mm.c                  |   16 ++--
 xen/arch/x86/x86_64/compat/entry.S |    4 -
 xen/arch/x86/x86_64/compat/mm.c    |  148 +++++++++++++++++++++++++++++++++++++
 xen/common/compat/xlat.c           |    4 +
 xen/include/asm-x86/hypercall.h    |    7 +
 xen/include/xlat.lst               |    2 
 6 files changed, 170 insertions(+), 11 deletions(-)

diff -r 244e46e7d021 -r e4088ae584b8 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Fri Jan 05 17:34:31 2007 +0000
+++ b/xen/arch/x86/mm.c Fri Jan 05 17:34:31 2007 +0000
@@ -106,6 +106,7 @@
 #include <asm/ldt.h>
 #include <asm/x86_emulate.h>
 #include <asm/e820.h>
+#include <asm/hypercall.h>
 #include <public/memory.h>
 
 #define MEM_LOG(_f, _a...) gdprintk(XENLOG_WARNING , _f "\n" , ## _a)
@@ -118,13 +119,6 @@
 #if !defined(NDEBUG) || defined(CONFIG_X86_PAE)
 #define PTE_UPDATE_WITH_CMPXCHG
 #endif
-
-/*
- * Both do_mmuext_op() and do_mmu_update():
- * We steal the m.s.b. of the @count parameter to indicate whether this
- * invocation of do_mmu_update() is resuming a previously preempted call.
- */
-#define MMU_UPDATE_PREEMPTED          (~(~0U>>1))
 
 /* Used to defer flushing of memory structures. */
 struct percpu_mm_info {
@@ -2033,6 +2027,8 @@ int do_mmuext_op(
             goto pin_page;
 
         case MMUEXT_PIN_L4_TABLE:
+            if ( IS_COMPAT(FOREIGNDOM) )
+                break;
             type = PGT_l4_page_table;
 
         pin_page:
@@ -2096,7 +2092,11 @@ int do_mmuext_op(
         
 #ifdef __x86_64__
         case MMUEXT_NEW_USER_BASEPTR:
-            okay = 1;
+            if ( IS_COMPAT(FOREIGNDOM) )
+            {
+                okay = 0;
+                break;
+            }
             if (likely(mfn != 0))
             {
                 if ( shadow_mode_refcounts(d) )
diff -r 244e46e7d021 -r e4088ae584b8 xen/arch/x86/x86_64/compat/entry.S
--- a/xen/arch/x86/x86_64/compat/entry.S        Fri Jan 05 17:34:31 2007 +0000
+++ b/xen/arch/x86/x86_64/compat/entry.S        Fri Jan 05 17:34:31 2007 +0000
@@ -279,7 +279,6 @@ CFIX14:
 .section .rodata, "a", @progbits
 
 #define compat_set_trap_table domain_crash_synchronous
-#define compat_mmu_update domain_crash_synchronous
 #define compat_set_gdt domain_crash_synchronous
 #define compat_platform_op domain_crash_synchronous
 #define compat_multicall domain_crash_synchronous
@@ -288,7 +287,6 @@ CFIX14:
 #define compat_physdev_op_compat domain_crash_synchronous
 #define compat_grant_table_op domain_crash_synchronous
 #define compat_vcpu_op domain_crash_synchronous
-#define compat_mmuext_op domain_crash_synchronous
 #define compat_acm_op domain_crash_synchronous
 #define compat_arch_sched_op domain_crash_synchronous
 #define compat_xenoprof_op domain_crash_synchronous
@@ -299,7 +297,7 @@ CFIX14:
 
 ENTRY(compat_hypercall_table)
         .quad compat_set_trap_table     /*  0 */
-        .quad compat_mmu_update
+        .quad do_mmu_update
         .quad compat_set_gdt
         .quad do_stack_switch
         .quad compat_set_callbacks
diff -r 244e46e7d021 -r e4088ae584b8 xen/arch/x86/x86_64/compat/mm.c
--- a/xen/arch/x86/x86_64/compat/mm.c   Fri Jan 05 17:34:31 2007 +0000
+++ b/xen/arch/x86/x86_64/compat/mm.c   Fri Jan 05 17:34:31 2007 +0000
@@ -1,6 +1,8 @@
 #ifdef CONFIG_COMPAT
 
+#include <xen/event.h>
 #include <compat/memory.h>
+#include <compat/xen.h>
 
 int compat_update_descriptor(u32 pa_lo, u32 pa_hi, u32 desc_lo, u32 desc_hi)
 {
@@ -135,6 +137,152 @@ int compat_update_va_mapping_otherdomain
 {
     return do_update_va_mapping_otherdomain(va, lo | ((u64)hi << 32), flags, 
domid);
 }
+
+DEFINE_XEN_GUEST_HANDLE(mmuext_op_compat_t);
+
+int compat_mmuext_op(XEN_GUEST_HANDLE(mmuext_op_compat_t) cmp_uops,
+                     unsigned int count,
+                     XEN_GUEST_HANDLE(uint) pdone,
+                     unsigned int foreigndom)
+{
+    unsigned int i, preempt_mask;
+    int rc = 0;
+    XEN_GUEST_HANDLE(mmuext_op_t) nat_ops;
+
+    preempt_mask = count & MMU_UPDATE_PREEMPTED;
+    count ^= preempt_mask;
+
+    if ( unlikely(!guest_handle_okay(cmp_uops, count)) )
+        return -EFAULT;
+
+    set_xen_guest_handle(nat_ops, (void 
*)COMPAT_ARG_XLAT_VIRT_START(current->vcpu_id));
+
+    for ( ; count; count -= i )
+    {
+        mmuext_op_t *nat_op = nat_ops.p;
+        unsigned int limit;
+        int err;
+
+        if ( hypercall_preempt_check() )
+        {
+            rc = hypercall_create_continuation(
+                __HYPERVISOR_mmuext_op, "hihi",
+                cmp_uops, count | MMU_UPDATE_PREEMPTED, pdone, foreigndom);
+            break;
+        }
+
+        limit = COMPAT_ARG_XLAT_SIZE / sizeof(*nat_op);
+
+        for ( i = 0; i < min(limit, count); ++i )
+        {
+            mmuext_op_compat_t cmp_op;
+            enum XLAT_mmuext_op_arg1 arg1;
+            enum XLAT_mmuext_op_arg2 arg2;
+
+            if ( unlikely(__copy_from_guest(&cmp_op, cmp_uops, 1) != 0) )
+            {
+                rc = -EFAULT;
+                break;
+            }
+
+            switch ( cmp_op.cmd )
+            {
+            case MMUEXT_PIN_L1_TABLE:
+            case MMUEXT_PIN_L2_TABLE:
+            case MMUEXT_PIN_L3_TABLE:
+            case MMUEXT_PIN_L4_TABLE:
+            case MMUEXT_UNPIN_TABLE:
+            case MMUEXT_NEW_BASEPTR:
+                arg1 = XLAT_mmuext_op_arg1_mfn;
+                break;
+            default:
+                arg1 = XLAT_mmuext_op_arg1_linear_addr;
+                break;
+            case MMUEXT_NEW_USER_BASEPTR:
+                rc = -EINVAL;
+            case MMUEXT_TLB_FLUSH_LOCAL:
+            case MMUEXT_TLB_FLUSH_MULTI:
+            case MMUEXT_TLB_FLUSH_ALL:
+            case MMUEXT_FLUSH_CACHE:
+                arg1 = -1;
+                break;
+            }
+
+            if ( rc )
+                break;
+
+            switch ( cmp_op.cmd )
+            {
+            case MMUEXT_SET_LDT:
+                arg2 = XLAT_mmuext_op_arg2_nr_ents;
+                break;
+            case MMUEXT_TLB_FLUSH_MULTI:
+            case MMUEXT_INVLPG_MULTI:
+                arg2 = XLAT_mmuext_op_arg2_vcpumask;
+                break;
+            default:
+                arg2 = -1;
+                break;
+            }
+
+#define XLAT_mmuext_op_HNDL_arg2_vcpumask(_d_, _s_) \
+            do \
+            { \
+                unsigned int vcpumask; \
+                if ( i < --limit ) \
+                { \
+                    (_d_)->arg2.vcpumask.p = (void *)(nat_ops.p + limit); \
+                    if ( copy_from_compat(&vcpumask, (_s_)->arg2.vcpumask, 1) 
== 0 ) \
+                        *(unsigned long *)(_d_)->arg2.vcpumask.p = vcpumask; \
+                    else \
+                        rc = -EFAULT; \
+                } \
+            } while(0)
+            XLAT_mmuext_op(nat_op, &cmp_op);
+#undef XLAT_mmuext_op_HNDL_arg2_vcpumask
+
+            if ( rc || i >= limit )
+                break;
+
+            guest_handle_add_offset(cmp_uops, 1);
+            ++nat_op;
+        }
+
+        err = do_mmuext_op(nat_ops, i | preempt_mask, pdone, foreigndom);
+
+        if ( err )
+        {
+            BUILD_BUG_ON(__HYPERVISOR_mmuext_op <= 0);
+            if ( err == __HYPERVISOR_mmuext_op )
+            {
+                struct cpu_user_regs *regs = guest_cpu_user_regs();
+                unsigned int left = regs->ecx & ~MMU_UPDATE_PREEMPTED;
+
+                BUG_ON(!(regs->ecx & MMU_UPDATE_PREEMPTED));
+                BUG_ON(left > count);
+                guest_handle_add_offset(nat_ops, count - left);
+                BUG_ON(left + i < count);
+                guest_handle_add_offset(cmp_uops, (signed int)(count - left - 
i));
+                left = 1;
+                BUG_ON(!hypercall_xlat_continuation(&left, 0x01, nat_ops, 
cmp_uops));
+                BUG_ON(left != regs->ecx);
+                regs->ecx += count - i;
+            }
+            else
+                BUG_ON(rc > 0);
+            rc = err;
+        }
+
+        if ( rc )
+            break;
+
+        /* Force do_mmuext_op() to not start counting from zero again. */
+        preempt_mask = MMU_UPDATE_PREEMPTED;
+    }
+
+    return rc;
+}
+
 #endif /* CONFIG_COMPAT */
 
 /*
diff -r 244e46e7d021 -r e4088ae584b8 xen/common/compat/xlat.c
--- a/xen/common/compat/xlat.c  Fri Jan 05 17:34:31 2007 +0000
+++ b/xen/common/compat/xlat.c  Fri Jan 05 17:34:31 2007 +0000
@@ -21,6 +21,10 @@ CHECK_dom0_vga_console_info;
 CHECK_dom0_vga_console_info;
 #undef dom0_vga_console_info
 
+#define xen_mmu_update mmu_update
+CHECK_mmu_update;
+#undef xen_mmu_update
+
 #define xen_vcpu_time_info vcpu_time_info
 CHECK_vcpu_time_info;
 #undef xen_vcpu_time_info
diff -r 244e46e7d021 -r e4088ae584b8 xen/include/asm-x86/hypercall.h
--- a/xen/include/asm-x86/hypercall.h   Fri Jan 05 17:34:31 2007 +0000
+++ b/xen/include/asm-x86/hypercall.h   Fri Jan 05 17:34:31 2007 +0000
@@ -7,6 +7,13 @@
 
 #include <public/physdev.h>
 #include <xen/types.h>
+
+/*
+ * Both do_mmuext_op() and do_mmu_update():
+ * We steal the m.s.b. of the @count parameter to indicate whether this
+ * invocation of do_mmu_update() is resuming a previously preempted call.
+ */
+#define MMU_UPDATE_PREEMPTED          (~(~0U>>1))
 
 extern long
 do_event_channel_op_compat(
diff -r 244e46e7d021 -r e4088ae584b8 xen/include/xlat.lst
--- a/xen/include/xlat.lst      Fri Jan 05 17:34:31 2007 +0000
+++ b/xen/include/xlat.lst      Fri Jan 05 17:34:31 2007 +0000
@@ -2,6 +2,8 @@
 # ! - needs translation
 # ? - needs checking
 ?      dom0_vga_console_info           xen.h
+?      mmu_update                      xen.h
+!      mmuext_op                       xen.h
 !      start_info                      xen.h
 ?      vcpu_time_info                  xen.h
 !      add_to_physmap                  memory.h

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.