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

[Xen-devel] [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@xxxxxxxxxx>
---
 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


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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