lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20190509172540.12398-5-ankur.a.arora@oracle.com>
Date:   Thu,  9 May 2019 10:25:28 -0700
From:   Ankur Arora <ankur.a.arora@...cle.com>
To:     linux-kernel@...r.kernel.org, xen-devel@...ts.xenproject.org
Cc:     jgross@...e.com, pbonzini@...hat.com, boris.ostrovsky@...cle.com,
        konrad.wilk@...cle.com, sstabellini@...nel.org,
        joao.m.martins@...cle.com, ankur.a.arora@...cle.com
Subject: [RFC PATCH 04/16] x86/xen: hypercall support for xenhost_t

Allow for different hypercall implementations for different xenhost types.
Nested xenhost, which has two underlying xenhosts, can use both
simultaneously.

The hypercall macros (HYPERVISOR_*) implicitly use the default xenhost.x
A new macro (hypervisor_*) takes xenhost_t * as a parameter and does the
right thing.

TODO:
  - Multicalls for now assume the default xenhost
  - xen_hypercall_* symbols are only generated for the default xenhost.

Signed-off-by: Ankur Arora <ankur.a.arora@...cle.com>
---
 arch/x86/include/asm/xen/hypercall.h | 233 ++++++++++++++++++---------
 arch/x86/xen/enlighten.c             |   3 -
 arch/x86/xen/enlighten_hvm.c         |  23 ++-
 arch/x86/xen/enlighten_pv.c          |  13 +-
 arch/x86/xen/enlighten_pvh.c         |   9 +-
 arch/x86/xen/xen-head.S              |   3 +
 drivers/xen/fallback.c               |   8 +-
 include/xen/xenhost.h                |  23 +++
 8 files changed, 218 insertions(+), 97 deletions(-)

diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
index 1a3cd6680e6f..e138f9c36a5a 100644
--- a/arch/x86/include/asm/xen/hypercall.h
+++ b/arch/x86/include/asm/xen/hypercall.h
@@ -51,6 +51,7 @@
 #include <xen/interface/physdev.h>
 #include <xen/interface/platform.h>
 #include <xen/interface/xen-mca.h>
+#include <xen/xenhost.h>
 
 struct xen_dm_op_buf;
 
@@ -88,11 +89,11 @@ struct xen_dm_op_buf;
 
 struct hypercall_entry { char _entry[32]; };
 extern struct hypercall_entry xen_hypercall_page[128];
-extern struct hypercall_entry *hypercall_page;
+extern struct hypercall_entry xen_hypercall_page2[128];
 
 #define __HYPERCALL	CALL_NOSPEC
-#define __HYPERCALL_ENTRY(x)						\
-	[thunk_target] "0" (hypercall_page + __HYPERVISOR_##x)
+#define __HYPERCALL_ENTRY(xh, x)						\
+	[thunk_target] "0" (xh->hypercall_page + __HYPERVISOR_##x)
 
 #ifdef CONFIG_X86_32
 #define __HYPERCALL_RETREG	"eax"
@@ -144,57 +145,57 @@ extern struct hypercall_entry *hypercall_page;
 #define __HYPERCALL_CLOBBER1	__HYPERCALL_CLOBBER2, __HYPERCALL_ARG2REG
 #define __HYPERCALL_CLOBBER0	__HYPERCALL_CLOBBER1, __HYPERCALL_ARG1REG
 
-#define _hypercall0(type, name)						\
+#define _hypercall0(xh, type, name)					\
 ({									\
 	__HYPERCALL_DECLS;						\
 	__HYPERCALL_0ARG();						\
 	asm volatile (__HYPERCALL					\
 		      : __HYPERCALL_0PARAM				\
-		      : __HYPERCALL_ENTRY(name)				\
+		      : __HYPERCALL_ENTRY(xh, name)			\
 		      : __HYPERCALL_CLOBBER0);				\
 	(type)__res;							\
 })
 
-#define _hypercall1(type, name, a1)					\
+#define _hypercall1(xh, type, name, a1)					\
 ({									\
 	__HYPERCALL_DECLS;						\
 	__HYPERCALL_1ARG(a1);						\
 	asm volatile (__HYPERCALL					\
 		      : __HYPERCALL_1PARAM				\
-		      : __HYPERCALL_ENTRY(name)				\
+		      : __HYPERCALL_ENTRY(xh, name)			\
 		      : __HYPERCALL_CLOBBER1);				\
 	(type)__res;							\
 })
 
-#define _hypercall2(type, name, a1, a2)					\
+#define _hypercall2(xh, type, name, a1, a2)				\
 ({									\
 	__HYPERCALL_DECLS;						\
 	__HYPERCALL_2ARG(a1, a2);					\
 	asm volatile (__HYPERCALL					\
 		      : __HYPERCALL_2PARAM				\
-		      : __HYPERCALL_ENTRY(name)				\
+		      : __HYPERCALL_ENTRY(xh, name)			\
 		      : __HYPERCALL_CLOBBER2);				\
 	(type)__res;							\
 })
 
-#define _hypercall3(type, name, a1, a2, a3)				\
+#define _hypercall3(xh, type, name, a1, a2, a3)				\
 ({									\
 	__HYPERCALL_DECLS;						\
 	__HYPERCALL_3ARG(a1, a2, a3);					\
 	asm volatile (__HYPERCALL					\
 		      : __HYPERCALL_3PARAM				\
-		      : __HYPERCALL_ENTRY(name)				\
+		      : __HYPERCALL_ENTRY(xh, name)			\
 		      : __HYPERCALL_CLOBBER3);				\
 	(type)__res;							\
 })
 
-#define _hypercall4(type, name, a1, a2, a3, a4)				\
+#define _hypercall4(xh, type, name, a1, a2, a3, a4)			\
 ({									\
 	__HYPERCALL_DECLS;						\
 	__HYPERCALL_4ARG(a1, a2, a3, a4);				\
 	asm volatile (__HYPERCALL					\
 		      : __HYPERCALL_4PARAM				\
-		      : __HYPERCALL_ENTRY(name)				\
+		      : __HYPERCALL_ENTRY(xh, name)			\
 		      : __HYPERCALL_CLOBBER4);				\
 	(type)__res;							\
 })
@@ -210,7 +211,7 @@ xen_single_call(unsigned int call,
 
 	asm volatile(CALL_NOSPEC
 		     : __HYPERCALL_5PARAM
-		     : [thunk_target] "0" (hypercall_page + call)
+		     : [thunk_target] "0" (xh_default->hypercall_page + call)
 		     : __HYPERCALL_CLOBBER5);
 
 	return (long)__res;
@@ -232,170 +233,235 @@ privcmd_call(unsigned int call,
 }
 
 static inline int
-HYPERVISOR_set_trap_table(struct trap_info *table)
+hypervisor_set_trap_table(xenhost_t *xh, struct trap_info *table)
 {
-	return _hypercall1(int, set_trap_table, table);
+	return _hypercall1(xh, int, set_trap_table, table);
 }
 
+#define HYPERVISOR_set_trap_table(table) \
+	hypervisor_set_trap_table(xh_default, table)
+
 static inline int
-HYPERVISOR_mmu_update(struct mmu_update *req, int count,
+hypervisor_mmu_update(xenhost_t *xh, struct mmu_update *req, int count,
 		      int *success_count, domid_t domid)
 {
-	return _hypercall4(int, mmu_update, req, count, success_count, domid);
+	return _hypercall4(xh, int, mmu_update, req, count, success_count, domid);
 }
+#define HYPERVISOR_mmu_update(req, count, success_count, domid)	\
+	hypervisor_mmu_update(xh_default, req, count, success_count, domid)
 
 static inline int
-HYPERVISOR_mmuext_op(struct mmuext_op *op, int count,
+hypervisor_mmuext_op(xenhost_t *xh, struct mmuext_op *op, int count,
 		     int *success_count, domid_t domid)
 {
-	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
+	return _hypercall4(xh, int, mmuext_op, op, count, success_count, domid);
 }
 
+#define HYPERVISOR_mmuext_op(op, count, success_count, domid)	\
+	hypervisor_mmuext_op(xh_default, op, count, success_count, domid)
+
 static inline int
-HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
+hypervisor_set_gdt(xenhost_t *xh, unsigned long *frame_list, int entries)
 {
-	return _hypercall2(int, set_gdt, frame_list, entries);
+	return _hypercall2(xh, int, set_gdt, frame_list, entries);
 }
 
+#define HYPERVISOR_set_gdt(frame_list, entries)		\
+	hypervisor_set_gdt(xh_default, frame_list, entries)
+
 static inline int
-HYPERVISOR_callback_op(int cmd, void *arg)
+hypervisor_callback_op(xenhost_t *xh, int cmd, void *arg)
 {
-	return _hypercall2(int, callback_op, cmd, arg);
+	return _hypercall2(xh, int, callback_op, cmd, arg);
 }
 
+#define HYPERVISOR_callback_op(cmd, arg)	\
+	hypervisor_callback_op(xh_default, cmd, arg)
+
 static inline int
-HYPERVISOR_sched_op(int cmd, void *arg)
+hypervisor_sched_op(xenhost_t *xh, int cmd, void *arg)
 {
-	return _hypercall2(int, sched_op, cmd, arg);
+	return _hypercall2(xh, int, sched_op, cmd, arg);
 }
 
+#define HYPERVISOR_sched_op(cmd, arg)		\
+	 hypervisor_sched_op(xh_default, cmd, arg)
+
 static inline long
-HYPERVISOR_set_timer_op(u64 timeout)
+hypervisor_set_timer_op(xenhost_t *xh, u64 timeout)
 {
 	unsigned long timeout_hi = (unsigned long)(timeout>>32);
 	unsigned long timeout_lo = (unsigned long)timeout;
-	return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
+	return _hypercall2(xh, long, set_timer_op, timeout_lo, timeout_hi);
 }
 
+#define HYPERVISOR_set_timer_op(timeout)	\
+	hypervisor_set_timer_op(xh_default, timeout)
+
 static inline int
-HYPERVISOR_mca(struct xen_mc *mc_op)
+hypervisor_mca(xenhost_t *xh, struct xen_mc *mc_op)
 {
 	mc_op->interface_version = XEN_MCA_INTERFACE_VERSION;
-	return _hypercall1(int, mca, mc_op);
+	return _hypercall1(xh, int, mca, mc_op);
 }
 
+#define HYPERVISOR_mca(mc_op)	\
+	hypervisor_mca(xh_default, mc_op)
+
 static inline int
-HYPERVISOR_platform_op(struct xen_platform_op *op)
+hypervisor_platform_op(xenhost_t *xh, struct xen_platform_op *op)
 {
 	op->interface_version = XENPF_INTERFACE_VERSION;
-	return _hypercall1(int, platform_op, op);
+	return _hypercall1(xh, int, platform_op, op);
 }
 
+#define HYPERVISOR_platform_op(op)	\
+	hypervisor_platform_op(xh_default, op)
+
 static inline int
-HYPERVISOR_set_debugreg(int reg, unsigned long value)
+hypervisor_set_debugreg(xenhost_t *xh, int reg, unsigned long value)
 {
-	return _hypercall2(int, set_debugreg, reg, value);
+	return _hypercall2(xh, int, set_debugreg, reg, value);
 }
 
+#define HYPERVISOR_set_debugreg(reg, value)	\
+	hypervisor_set_debugreg(xh_default, reg, value)
+
 static inline unsigned long
-HYPERVISOR_get_debugreg(int reg)
+hypervisor_get_debugreg(xenhost_t *xh, int reg)
 {
-	return _hypercall1(unsigned long, get_debugreg, reg);
+	return _hypercall1(xh, unsigned long, get_debugreg, reg);
 }
+#define HYPERVISOR_get_debugreg(reg)	\
+	hypervisor_get_debugreg(xh_default, reg)
 
 static inline int
-HYPERVISOR_update_descriptor(u64 ma, u64 desc)
+hypervisor_update_descriptor(xenhost_t *xh, u64 ma, u64 desc)
 {
 	if (sizeof(u64) == sizeof(long))
-		return _hypercall2(int, update_descriptor, ma, desc);
-	return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
+		return _hypercall2(xh, int, update_descriptor, ma, desc);
+	return _hypercall4(xh, int, update_descriptor, ma, ma>>32, desc, desc>>32);
 }
 
+#define HYPERVISOR_update_descriptor(ma, desc)	\
+	hypervisor_update_descriptor(xh_default, ma, desc)
+
 static inline long
-HYPERVISOR_memory_op(unsigned int cmd, void *arg)
+hypervisor_memory_op(xenhost_t *xh, unsigned int cmd, void *arg)
 {
-	return _hypercall2(long, memory_op, cmd, arg);
+	return _hypercall2(xh, long, memory_op, cmd, arg);
 }
 
+#define HYPERVISOR_memory_op(cmd, arg)	\
+	hypervisor_memory_op(xh_default, cmd, arg)	\
+
 static inline int
-HYPERVISOR_multicall(void *call_list, uint32_t nr_calls)
+hypervisor_multicall(xenhost_t *xh, void *call_list, uint32_t nr_calls)
 {
-	return _hypercall2(int, multicall, call_list, nr_calls);
+	return _hypercall2(xh, int, multicall, call_list, nr_calls);
 }
 
+#define HYPERVISOR_multicall(call_list, nr_calls)	\
+	hypervisor_multicall(xh_default, call_list, nr_calls)
+
 static inline int
-HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
+hypervisor_update_va_mapping(xenhost_t *xh, unsigned long va, pte_t new_val,
 			     unsigned long flags)
 {
 	if (sizeof(new_val) == sizeof(long))
-		return _hypercall3(int, update_va_mapping, va,
+		return _hypercall3(xh, int, update_va_mapping, va,
 				   new_val.pte, flags);
 	else
-		return _hypercall4(int, update_va_mapping, va,
+		return _hypercall4(xh, int, update_va_mapping, va,
 				   new_val.pte, new_val.pte >> 32, flags);
 }
-extern int __must_check xen_event_channel_op_compat(int, void *);
+
+#define HYPERVISOR_update_va_mapping(va, new_val, flags)	\
+	hypervisor_update_va_mapping(xh_default, va, new_val, flags)
+
+extern int __must_check xen_event_channel_op_compat(xenhost_t *xh, int, void *);
 
 static inline int
-HYPERVISOR_event_channel_op(int cmd, void *arg)
+hypervisor_event_channel_op(xenhost_t *xh, int cmd, void *arg)
 {
-	int rc = _hypercall2(int, event_channel_op, cmd, arg);
+	int rc = _hypercall2(xh, int, event_channel_op, cmd, arg);
 	if (unlikely(rc == -ENOSYS))
-		rc = xen_event_channel_op_compat(cmd, arg);
+		rc = xen_event_channel_op_compat(xh, cmd, arg);
 	return rc;
 }
 
+#define HYPERVISOR_event_channel_op(cmd, arg)		\
+	hypervisor_event_channel_op(xh_default, cmd, arg)
+
 static inline int
-HYPERVISOR_xen_version(int cmd, void *arg)
+hypervisor_xen_version(xenhost_t *xh, int cmd, void *arg)
 {
-	return _hypercall2(int, xen_version, cmd, arg);
+	return _hypercall2(xh, int, xen_version, cmd, arg);
 }
 
+#define HYPERVISOR_xen_version(cmd, arg)	\
+	hypervisor_xen_version(xh_default, cmd, arg)
+
 static inline int
-HYPERVISOR_console_io(int cmd, int count, char *str)
+hypervisor_console_io(xenhost_t *xh, int cmd, int count, char *str)
 {
-	return _hypercall3(int, console_io, cmd, count, str);
+	return _hypercall3(xh, int, console_io, cmd, count, str);
 }
+#define HYPERVISOR_console_io(cmd, count, str) \
+	hypervisor_console_io(xh_default, cmd, count, str)
 
-extern int __must_check xen_physdev_op_compat(int, void *);
+extern int __must_check xen_physdev_op_compat(xenhost_t *xh, int, void *);
 
 static inline int
-HYPERVISOR_physdev_op(int cmd, void *arg)
+hypervisor_physdev_op(xenhost_t *xh, int cmd, void *arg)
 {
-	int rc = _hypercall2(int, physdev_op, cmd, arg);
+	int rc = _hypercall2(xh, int, physdev_op, cmd, arg);
 	if (unlikely(rc == -ENOSYS))
-		rc = xen_physdev_op_compat(cmd, arg);
+		rc = xen_physdev_op_compat(xh, cmd, arg);
 	return rc;
 }
+#define HYPERVISOR_physdev_op(cmd, arg)	\
+	hypervisor_physdev_op(xh_default, cmd, arg)
 
 static inline int
-HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
+hypervisor_grant_table_op(xenhost_t *xh, unsigned int cmd, void *uop, unsigned int count)
 {
-	return _hypercall3(int, grant_table_op, cmd, uop, count);
+	return _hypercall3(xh, int, grant_table_op, cmd, uop, count);
 }
 
+#define HYPERVISOR_grant_table_op(cmd, uop, count)	\
+	hypervisor_grant_table_op(xh_default, cmd, uop, count)
+
 static inline int
-HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
+hypervisor_vm_assist(xenhost_t *xh, unsigned int cmd, unsigned int type)
 {
-	return _hypercall2(int, vm_assist, cmd, type);
+	return _hypercall2(xh, int, vm_assist, cmd, type);
 }
 
+#define HYPERVISOR_vm_assist(cmd, type)		\
+	hypervisor_vm_assist(xh_default, cmd, type)
+
 static inline int
-HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
+hypervisor_vcpu_op(xenhost_t *xh, int cmd, int vcpuid, void *extra_args)
 {
-	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
+	return _hypercall3(xh, int, vcpu_op, cmd, vcpuid, extra_args);
 }
 
+#define HYPERVISOR_vcpu_op(cmd, vcpuid, extra_args)	\
+	hypervisor_vcpu_op(xh_default, cmd, vcpuid, extra_args)
+
 #ifdef CONFIG_X86_64
 static inline int
-HYPERVISOR_set_segment_base(int reg, unsigned long value)
+hypervisor_set_segment_base(xenhost_t *xh, int reg, unsigned long value)
 {
-	return _hypercall2(int, set_segment_base, reg, value);
+	return _hypercall2(xh, int, set_segment_base, reg, value);
 }
+#define HYPERVISOR_set_segment_base(reg, value)		\
+	hypervisor_set_segment_base(xh_default, reg, value)
 #endif
 
 static inline int
-HYPERVISOR_suspend(unsigned long start_info_mfn)
+hypervisor_suspend(xenhost_t *xh, unsigned long start_info_mfn)
 {
 	struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
 
@@ -405,38 +471,53 @@ HYPERVISOR_suspend(unsigned long start_info_mfn)
 	 * hypercall calling convention this is the third hypercall
 	 * argument, which is start_info_mfn here.
 	 */
-	return _hypercall3(int, sched_op, SCHEDOP_shutdown, &r, start_info_mfn);
+	return _hypercall3(xh, int, sched_op, SCHEDOP_shutdown, &r, start_info_mfn);
 }
+#define HYPERVISOR_suspend(start_info_mfn)	\
+	hypervisor_suspend(xh_default, start_info_mfn)
 
 static inline unsigned long __must_check
-HYPERVISOR_hvm_op(int op, void *arg)
+hypervisor_hvm_op(xenhost_t *xh, int op, void *arg)
 {
-       return _hypercall2(unsigned long, hvm_op, op, arg);
+       return _hypercall2(xh, unsigned long, hvm_op, op, arg);
 }
 
+#define HYPERVISOR_hvm_op(op, arg)	\
+	hypervisor_hvm_op(xh_default, op, arg)
+
 static inline int
-HYPERVISOR_tmem_op(
+hypervisor_tmem_op(
+	xenhost_t *xh,
 	struct tmem_op *op)
 {
-	return _hypercall1(int, tmem_op, op);
+	return _hypercall1(xh, int, tmem_op, op);
 }
 
+#define HYPERVISOR_tmem_op(op)	\
+	hypervisor_tmem_op(xh_default, op)
+
 static inline int
-HYPERVISOR_xenpmu_op(unsigned int op, void *arg)
+hypervisor_xenpmu_op(xenhost_t *xh, unsigned int op, void *arg)
 {
-	return _hypercall2(int, xenpmu_op, op, arg);
+	return _hypercall2(xh, int, xenpmu_op, op, arg);
 }
 
+#define HYPERVISOR_xenpmu_op(op, arg) \
+	hypervisor_xenpmu_op(xh_default, op, arg)
+
 static inline int
-HYPERVISOR_dm_op(
+hypervisor_dm_op(
+	xenhost_t *xh,
 	domid_t dom, unsigned int nr_bufs, struct xen_dm_op_buf *bufs)
 {
 	int ret;
 	stac();
-	ret = _hypercall3(int, dm_op, dom, nr_bufs, bufs);
+	ret = _hypercall3(xh, int, dm_op, dom, nr_bufs, bufs);
 	clac();
 	return ret;
 }
+#define HYPERVISOR_dm_op(dom, nr_bufs, bufs)	\
+	hypervisor_dm_op(xh_default, dom, nr_bufs, bufs)
 
 static inline void
 MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index e9dc92e79afa..f88bb14da3f2 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -20,9 +20,6 @@
 #include "smp.h"
 #include "pmu.h"
 
-struct hypercall_entry *hypercall_page;
-EXPORT_SYMBOL_GPL(hypercall_page);
-
 /*
  * Pointer to the xen_vcpu_info structure or
  * &HYPERVISOR_shared_info->vcpu_info[cpu]. See xen_hvm_init_shared_info
diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
index 4d85cd2ff261..f84941d6944e 100644
--- a/arch/x86/xen/enlighten_hvm.c
+++ b/arch/x86/xen/enlighten_hvm.c
@@ -85,8 +85,20 @@ static void __init xen_hvm_init_mem_mapping(void)
 
 extern uint32_t xen_pv_cpuid_base(xenhost_t *xh);
 
+void xen_hvm_setup_hypercall_page(xenhost_t *xh)
+{
+	u32 msr;
+	u64 pfn;
+
+	msr = cpuid_ebx(xenhost_cpuid_base(xh) + 2);
+	pfn = __pa(xen_hypercall_page);
+	wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
+	xh->hypercall_page = xen_hypercall_page;
+}
+
 xenhost_ops_t xh_hvm_ops = {
 	.cpuid_base = xen_pv_cpuid_base,
+	.setup_hypercall_page = xen_hvm_setup_hypercall_page,
 };
 
 xenhost_ops_t xh_hvm_nested_ops = {
@@ -96,6 +108,7 @@ static void __init init_hvm_pv_info(void)
 {
 	int major, minor;
 	uint32_t eax, ebx, ecx, edx, base;
+	xenhost_t **xh;
 
 	base = xenhost_cpuid_base(xh_default);
 	eax = cpuid_eax(base + 1);
@@ -110,14 +123,10 @@ static void __init init_hvm_pv_info(void)
 	if (xen_pvh_domain())
 		pv_info.name = "Xen PVH";
 	else {
-		u64 pfn;
-		uint32_t msr;
-
 		pv_info.name = "Xen HVM";
-		msr = cpuid_ebx(base + 2);
-		pfn = __pa(xen_hypercall_page);
-		wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
-		hypercall_page = xen_hypercall_page;
+
+		for_each_xenhost(xh)
+			xenhost_setup_hypercall_page(*xh);
 	}
 
 	xen_setup_features();
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index 3239e8452ede..a2c07cc71498 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -1200,12 +1200,20 @@ uint32_t xen_pv_nested_cpuid_base(xenhost_t *xh)
 				2 /* nested specific leaf? */);
 }
 
+static void xen_pv_setup_hypercall_page(xenhost_t *xh)
+{
+	xh->hypercall_page = xen_hypercall_page;
+}
+
 xenhost_ops_t xh_pv_ops = {
 	.cpuid_base = xen_pv_cpuid_base,
+
+	.setup_hypercall_page = xen_pv_setup_hypercall_page,
 };
 
 xenhost_ops_t xh_pv_nested_ops = {
 	.cpuid_base = xen_pv_nested_cpuid_base,
+	.setup_hypercall_page = NULL,
 };
 
 /* First C function to be called on Xen boot */
@@ -1213,11 +1221,11 @@ asmlinkage __visible void __init xen_start_kernel(void)
 {
 	struct physdev_set_iopl set_iopl;
 	unsigned long initrd_start = 0;
+	xenhost_t **xh;
 	int rc;
 
 	if (!xen_start_info)
 		return;
-	hypercall_page = xen_hypercall_page;
 
 	xenhost_register(xenhost_r1, &xh_pv_ops);
 
@@ -1228,6 +1236,9 @@ asmlinkage __visible void __init xen_start_kernel(void)
 	if (xen_driver_domain() && xen_nested())
 		xenhost_register(xenhost_r2, &xh_pv_nested_ops);
 
+	for_each_xenhost(xh)
+		xenhost_setup_hypercall_page(*xh);
+
 	xen_domain_type = XEN_PV_DOMAIN;
 	xen_start_flags = xen_start_info->flags;
 
diff --git a/arch/x86/xen/enlighten_pvh.c b/arch/x86/xen/enlighten_pvh.c
index e47866fcb7ea..50277dfbdf30 100644
--- a/arch/x86/xen/enlighten_pvh.c
+++ b/arch/x86/xen/enlighten_pvh.c
@@ -26,8 +26,7 @@ extern xenhost_ops_t xh_hvm_ops, xh_hvm_nested_ops;
 
 void __init xen_pvh_init(void)
 {
-	u32 msr;
-	u64 pfn;
+	xenhost_t **xh;
 
 	/*
 	 * Note: we have already called xen_cpuid_base() in
@@ -45,10 +44,8 @@ void __init xen_pvh_init(void)
 	xen_pvh = 1;
 	xen_start_flags = pvh_start_info.flags;
 
-	msr = cpuid_ebx(xen_cpuid_base() + 2);
-	pfn = __pa(xen_hypercall_page);
-	wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
-	hypercall_page = xen_hypercall_page;
+	for_each_xenhost(xh)
+		xenhost_setup_hypercall_page(*xh);
 }
 
 void __init mem_map_via_hcall(struct boot_params *boot_params_p)
diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S
index 7ff5437bd83f..6bbf4ff700d6 100644
--- a/arch/x86/xen/xen-head.S
+++ b/arch/x86/xen/xen-head.S
@@ -70,6 +70,9 @@ ENTRY(xen_hypercall_page)
 #include <asm/xen-hypercalls.h>
 #undef HYPERCALL
 END(xen_hypercall_page)
+/*
+ * Add xen_hypercall_page2 for remote xenhost?
+ */
 .popsection
 
 	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz "linux")
diff --git a/drivers/xen/fallback.c b/drivers/xen/fallback.c
index b04fb64c5a91..ae81cf75ae5f 100644
--- a/drivers/xen/fallback.c
+++ b/drivers/xen/fallback.c
@@ -5,14 +5,14 @@
 #include <asm/hypervisor.h>
 #include <asm/xen/hypercall.h>
 
-int xen_event_channel_op_compat(int cmd, void *arg)
+int xen_event_channel_op_compat(xenhost_t *xh, int cmd, void *arg)
 {
 	struct evtchn_op op;
 	int rc;
 
 	op.cmd = cmd;
 	memcpy(&op.u, arg, sizeof(op.u));
-	rc = _hypercall1(int, event_channel_op_compat, &op);
+	rc = _hypercall1(xh, int, event_channel_op_compat, &op);
 
 	switch (cmd) {
 	case EVTCHNOP_close:
@@ -44,14 +44,14 @@ int xen_event_channel_op_compat(int cmd, void *arg)
 }
 EXPORT_SYMBOL_GPL(xen_event_channel_op_compat);
 
-int xen_physdev_op_compat(int cmd, void *arg)
+int xen_physdev_op_compat(xenhost_t *xh, int cmd, void *arg)
 {
 	struct physdev_op op;
 	int rc;
 
 	op.cmd = cmd;
 	memcpy(&op.u, arg, sizeof(op.u));
-	rc = _hypercall1(int, physdev_op_compat, &op);
+	rc = _hypercall1(xh, int, physdev_op_compat, &op);
 
 	switch (cmd) {
 	case PHYSDEVOP_IRQ_UNMASK_NOTIFY:
diff --git a/include/xen/xenhost.h b/include/xen/xenhost.h
index 13a70bdadfd2..d9bc1fb6cce4 100644
--- a/include/xen/xenhost.h
+++ b/include/xen/xenhost.h
@@ -70,6 +70,8 @@ typedef struct {
 	enum xenhost_type type;
 
 	struct xenhost_ops *ops;
+
+	struct hypercall_entry *hypercall_page;
 } xenhost_t;
 
 typedef struct xenhost_ops {
@@ -83,6 +85,22 @@ typedef struct xenhost_ops {
 	 *   Separate cpuid-leafs?
 	 */
 	uint32_t (*cpuid_base)(xenhost_t *xenhost);
+
+	/*
+	 * Hypercall page is setup as the first thing once the PV/PVH/PVHVM
+	 * code detects that it is selected. The first use is in
+	 * xen_setup_features().
+	 *
+	 * PV/PVH/PVHVM set this up in different ways: hypervisor takes
+	 * care of this for PV, PVH and PVHVM use xen_cpuid.
+	 *
+	 *  xenhost_r0: point hypercall_page to external hypercall_page.
+	 *  xenhost_r1: what we do now.
+	 *  xenhost_r2: hypercall interface that bypasses L1-Xen to go from
+	 *    L1-guest to L0-Xen. The interface would allow L0-Xen to be able
+	 *    to decide which particular L1-guest was the caller.
+	 */
+	void (*setup_hypercall_page)(xenhost_t *xenhost);
 } xenhost_ops_t;
 
 extern xenhost_t *xh_default, *xh_remote;
@@ -113,4 +131,9 @@ static inline uint32_t xenhost_cpuid_base(xenhost_t *xh)
 		return xen_cpuid_base();
 }
 
+static inline void xenhost_setup_hypercall_page(xenhost_t *xh)
+{
+	(xh->ops->setup_hypercall_page)(xh);
+}
+
 #endif /* __XENHOST_H */
-- 
2.20.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ