293 lines
9.7 KiB
Diff
293 lines
9.7 KiB
Diff
|
Enable compatibility mode operation for HYPERVISOR_mmu_update and
|
||
|
HYPERVISOR_mmuext_op.
|
||
|
|
||
|
Index: 2006-12-18/xen/arch/x86/mm.c
|
||
|
===================================================================
|
||
|
--- 2006-12-18.orig/xen/arch/x86/mm.c 2006-12-18 09:49:30.000000000 +0100
|
||
|
+++ 2006-12-18/xen/arch/x86/mm.c 2006-12-18 09:49:35.000000000 +0100
|
||
|
@@ -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)
|
||
|
@@ -119,13 +120,6 @@
|
||
|
#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 {
|
||
|
#define DOP_FLUSH_TLB (1<<0) /* Flush the local TLB. */
|
||
|
@@ -2027,6 +2021,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:
|
||
|
@@ -2090,7 +2086,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) )
|
||
|
Index: 2006-12-18/xen/arch/x86/x86_64/compat/entry.S
|
||
|
===================================================================
|
||
|
--- 2006-12-18.orig/xen/arch/x86/x86_64/compat/entry.S 2006-12-18 09:49:30.000000000 +0100
|
||
|
+++ 2006-12-18/xen/arch/x86/x86_64/compat/entry.S 2006-12-18 09:49:35.000000000 +0100
|
||
|
@@ -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
|
||
|
Index: 2006-12-18/xen/arch/x86/x86_64/compat/mm.c
|
||
|
===================================================================
|
||
|
--- 2006-12-18.orig/xen/arch/x86/x86_64/compat/mm.c 2006-12-18 09:49:30.000000000 +0100
|
||
|
+++ 2006-12-18/xen/arch/x86/x86_64/compat/mm.c 2006-12-18 09:49:35.000000000 +0100
|
||
|
@@ -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 */
|
||
|
|
||
|
/*
|
||
|
Index: 2006-12-18/xen/common/compat/xlat.c
|
||
|
===================================================================
|
||
|
--- 2006-12-18.orig/xen/common/compat/xlat.c 2006-12-18 09:46:14.000000000 +0100
|
||
|
+++ 2006-12-18/xen/common/compat/xlat.c 2006-12-18 09:49:35.000000000 +0100
|
||
|
@@ -21,6 +21,10 @@ void xlat_start_info(struct start_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
|
||
|
Index: 2006-12-18/xen/include/asm-x86/hypercall.h
|
||
|
===================================================================
|
||
|
--- 2006-12-18.orig/xen/include/asm-x86/hypercall.h 2006-12-13 11:15:56.000000000 +0100
|
||
|
+++ 2006-12-18/xen/include/asm-x86/hypercall.h 2006-12-18 09:49:35.000000000 +0100
|
||
|
@@ -8,6 +8,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(
|
||
|
XEN_GUEST_HANDLE(evtchn_op_t) uop);
|
||
|
Index: 2006-12-18/xen/include/xlat.lst
|
||
|
===================================================================
|
||
|
--- 2006-12-18.orig/xen/include/xlat.lst 2006-12-18 09:49:30.000000000 +0100
|
||
|
+++ 2006-12-18/xen/include/xlat.lst 2006-12-18 09:49:35.000000000 +0100
|
||
|
@@ -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
|