* Implement read_cr3(), HYPERCALL4() and hypercall_mmuext_op().
* Use FLAT_RING3_SS64 for __{KERN,USER}_DS.
* Set user %cr3.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
write_es(__USER_DS);
write_fs(__USER_DS);
write_gs(__USER_DS);
+
+#ifdef __x86_64__
+ /*
+ * Set the user pagetables (only applicable to 64bit PV).
+ *
+ * XTF uses a shared user/kernel address space, so register the kernel
+ * %cr3 as the user %cr3.
+ */
+ mmuext_op_t ext =
+ {
+ .cmd = MMUEXT_NEW_USER_BASEPTR,
+ .arg1.mfn = read_cr3() >> PAGE_SHIFT,
+ };
+
+ rc = hypercall_mmuext_op(&ext, 1, NULL, DOMID_SELF);
+ if ( rc )
+ panic("Failed to set user %%cr3: %d\n", rc);
+
+#endif
}
void __noreturn arch_crash_hard(void)
return val;
}
+static inline unsigned long read_cr3(void)
+{
+ unsigned long cr3;
+
+ asm volatile ("mov %%cr3, %0" : "=r" (cr3));
+
+ return cr3;
+}
+
#endif /* XTF_X86_LIB_H */
/*
* report cpl0 when interrupting kernel mode. Trim the kernel selectors down
* to rpl0 so they match the exception frames; Xen will take care of bumping
* rpl back to 3 when required.
+ *
+ * In Long mode, it is permitted to have NULL selectors for the plain data
+ * segment selectors (this is expressed in the Xen ABI), but not for %ss. As
+ * __{KERN,USER}_DS are used for all data selectors including %ss, use the
+ * FLAT_RING3_SS64 rather than FLAT_RING3_DS64.
*/
#define __KERN_CS (FLAT_RING3_CS64 & ~3)
-#define __KERN_DS (FLAT_RING3_DS64 & ~3)
+#define __KERN_DS (FLAT_RING3_SS64 & ~3)
#define __USER_CS FLAT_RING3_CS64
-#define __USER_DS FLAT_RING3_DS64
+#define __USER_DS FLAT_RING3_SS64
#elif defined(CONFIG_ENV_pv32)
(type)__res; \
})
+#define _hypercall32_4(type, hcall, a1, a2, a3, a4) \
+ ({ \
+ long __res, __ign1, __ign2, __ign3, __ign4; \
+ asm volatile ( \
+ "call hypercall_page + %c[offset]" \
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), "=d" (__ign3),\
+ "=S" (__ign4) \
+ : [offset] "i" (hcall * 32), \
+ "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3)), \
+ "4" ((long)(a4)) \
+ : "memory" ); \
+ (type)__res; \
+ })
+
#endif /* XTF_X86_32_HYPERCALL_H */
/*
(type)__res; \
})
+#define _hypercall64_4(type, hcall, a1, a2, a3, a4) \
+ ({ \
+ long __res, __ign1, __ign2, __ign3, __ign4; \
+ register long _a4 asm ("r10") = ((long)(a4)); \
+ asm volatile ( \
+ "call hypercall_page + %c[offset]" \
+ : "=a" (__res), "=D" (__ign1), "=S" (__ign2), "=d" (__ign3),\
+ "=&r" (__ign4) \
+ : [offset] "i" (hcall * 32), \
+ "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3)), \
+ "4" (_a4) \
+ : "memory" ); \
+ (type)__res; \
+ })
+
#endif /* XTF_X86_64_HYPERCALL_H */
/*
typedef struct start_info start_info_t;
#endif
+/*
+ * MMU EXTENDED OPERATIONS
+ *
+ * HYPERVISOR_mmuext_op(mmuext_op_t uops[],
+ * unsigned int count,
+ * unsigned int *pdone,
+ * unsigned int foreigndom)
+ *
+ * HYPERVISOR_mmuext_op() accepts a list of mmuext_op structures.
+ * A foreigndom (FD) can be specified (or DOMID_SELF for none).
+ * Where the FD has some effect, it is described below.
+ *
+ * cmd: MMUEXT_(UN)PIN_*_TABLE
+ * mfn: Machine frame number to be (un)pinned as a p.t. page.
+ * The frame must belong to the FD, if one is specified.
+ *
+ * cmd: MMUEXT_NEW_BASEPTR
+ * mfn: Machine frame number of new page-table base to install in MMU.
+ *
+ * cmd: MMUEXT_NEW_USER_BASEPTR [x86/64 only]
+ * mfn: Machine frame number of new page-table base to install in MMU
+ * when in user space.
+ *
+ * cmd: MMUEXT_TLB_FLUSH_LOCAL
+ * No additional arguments. Flushes local TLB.
+ *
+ * cmd: MMUEXT_INVLPG_LOCAL
+ * linear_addr: Linear address to be flushed from the local TLB.
+ *
+ * cmd: MMUEXT_TLB_FLUSH_MULTI
+ * vcpumask: Pointer to bitmap of VCPUs to be flushed.
+ *
+ * cmd: MMUEXT_INVLPG_MULTI
+ * linear_addr: Linear address to be flushed.
+ * vcpumask: Pointer to bitmap of VCPUs to be flushed.
+ *
+ * cmd: MMUEXT_TLB_FLUSH_ALL
+ * No additional arguments. Flushes all VCPUs' TLBs.
+ *
+ * cmd: MMUEXT_INVLPG_ALL
+ * linear_addr: Linear address to be flushed from all VCPUs' TLBs.
+ *
+ * cmd: MMUEXT_FLUSH_CACHE
+ * No additional arguments. Writes back and flushes cache contents.
+ *
+ * cmd: MMUEXT_FLUSH_CACHE_GLOBAL
+ * No additional arguments. Writes back and flushes cache contents
+ * on all CPUs in the system.
+ *
+ * cmd: MMUEXT_SET_LDT
+ * linear_addr: Linear address of LDT base (NB. must be page-aligned).
+ * nr_ents: Number of entries in LDT.
+ *
+ * cmd: MMUEXT_CLEAR_PAGE
+ * mfn: Machine frame number to be cleared.
+ *
+ * cmd: MMUEXT_COPY_PAGE
+ * mfn: Machine frame number of the destination page.
+ * src_mfn: Machine frame number of the source page.
+ *
+ * cmd: MMUEXT_[UN]MARK_SUPER
+ * mfn: Machine frame number of head of superpage to be [un]marked.
+ */
+#define MMUEXT_PIN_L1_TABLE 0
+#define MMUEXT_PIN_L2_TABLE 1
+#define MMUEXT_PIN_L3_TABLE 2
+#define MMUEXT_PIN_L4_TABLE 3
+#define MMUEXT_UNPIN_TABLE 4
+#define MMUEXT_NEW_BASEPTR 5
+#define MMUEXT_TLB_FLUSH_LOCAL 6
+#define MMUEXT_INVLPG_LOCAL 7
+#define MMUEXT_TLB_FLUSH_MULTI 8
+#define MMUEXT_INVLPG_MULTI 9
+#define MMUEXT_TLB_FLUSH_ALL 10
+#define MMUEXT_INVLPG_ALL 11
+#define MMUEXT_FLUSH_CACHE 12
+#define MMUEXT_SET_LDT 13
+#define MMUEXT_NEW_USER_BASEPTR 15
+#define MMUEXT_CLEAR_PAGE 16
+#define MMUEXT_COPY_PAGE 17
+#define MMUEXT_FLUSH_CACHE_GLOBAL 18
+#define MMUEXT_MARK_SUPER 19
+#define MMUEXT_UNMARK_SUPER 20
+
+#ifndef __ASSEMBLY__
+struct mmuext_op {
+ unsigned int cmd; /* => enum mmuext_cmd */
+ union {
+ /* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR
+ * CLEAR_PAGE, COPY_PAGE, [UN]MARK_SUPER */
+ xen_pfn_t mfn;
+ /* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */
+ unsigned long linear_addr;
+ } arg1;
+ union {
+ /* SET_LDT */
+ unsigned int nr_ents;
+ /* TLB_FLUSH_MULTI, INVLPG_MULTI */
+ const void *vcpumask;
+ /* COPY_PAGE */
+ xen_pfn_t src_mfn;
+ } arg2;
+};
+typedef struct mmuext_op mmuext_op_t;
+#endif
+
#endif /* XEN_PUBLIC_XEN_H */
/*
# define HYPERCALL1 _hypercall64_1
# define HYPERCALL2 _hypercall64_2
# define HYPERCALL3 _hypercall64_3
+# define HYPERCALL4 _hypercall64_4
#elif defined(__i386__)
# define HYPERCALL1 _hypercall32_1
# define HYPERCALL2 _hypercall32_2
# define HYPERCALL3 _hypercall32_3
+# define HYPERCALL4 _hypercall32_4
#else
# error Bad architecture for hypercalls
return HYPERCALL2(long, __HYPERVISOR_stack_switch, ss, sp);
}
+static inline long hypercall_mmuext_op(const mmuext_op_t ops[],
+ unsigned int count,
+ unsigned int *done,
+ unsigned int foreigndom)
+{
+ return HYPERCALL4(long, __HYPERVISOR_mmuext_op,
+ ops, count, done, foreigndom);
+}
+
static inline long hypercall_sched_op(unsigned int cmd, void *arg)
{
return HYPERCALL2(long, __HYPERVISOR_sched_op, cmd, arg);