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

[Xen-devel] [PATCH] x86/pv: Export pv_hypercall_table[] rather than working around it in several ways



The functions in compat.c are thing wrappers around the main hypercalls,
massaging certain parameters.  However, they second-guess the content of
pv_hypercall_table[], which is problematic for the shim case.  Instead,
arrange for them to call via function pointer, which removes the need for
pv_get_hypercall_handler().

With pv_hypercall_table[] exported, there is no need for
pv_hypercall_table_replace(), so its single callsite gets modified to cope.
The backing code behind __va(__pa()) is substantial, and there is no need to
calculate it repeatedly (Xen's .rodata is also contiguous in the directmap).

While adjusting the declarations, guard content in arch/x86/pv with CONFIG_PV.

The net difference is:
  add/remove: 0/2 grow/shrink: 4/1 up/down: 176/-321 (-145)
  function                                     old     new   delta
  pv_shim_setup_dom                           1130    1266    +136
  do_sched_op_compat                           176     192     +16
  compat_physdev_op_compat                      90     106     +16
  do_physdev_op_compat                          98     106      +8
  do_event_channel_op_compat                   145     123     -22
  pv_get_hypercall_handler                      28       -     -28
  pv_hypercall_table_replace                   271       -    -271

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Wei Liu <wei.liu2@xxxxxxxxxx>
CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>
CC: Sergey Dyasli <sergey.dyasli@xxxxxxxxxx>
---
 xen/arch/x86/compat.c           | 14 ++++++++++----
 xen/arch/x86/pv/hypercall.c     | 19 +------------------
 xen/arch/x86/pv/shim.c          | 21 +++++++++++++++------
 xen/include/asm-x86/hypercall.h |  6 +++---
 4 files changed, 29 insertions(+), 31 deletions(-)

diff --git a/xen/arch/x86/compat.c b/xen/arch/x86/compat.c
index 9d376a4..a40ec29 100644
--- a/xen/arch/x86/compat.c
+++ b/xen/arch/x86/compat.c
@@ -17,12 +17,14 @@ typedef long ret_t;
 /* Legacy hypercall (as of 0x00030202). */
 ret_t do_physdev_op_compat(XEN_GUEST_HANDLE(physdev_op_t) uop)
 {
+    typeof(do_physdev_op) *fn =
+        (void *)pv_hypercall_table[__HYPERVISOR_physdev_op].native;
     struct physdev_op op;
 
     if ( unlikely(copy_from_guest(&op, uop, 1) != 0) )
         return -EFAULT;
 
-    return do_physdev_op(op.cmd, guest_handle_from_ptr(&uop.p->u, void));
+    return fn(op.cmd, guest_handle_from_ptr(&uop.p->u, void));
 }
 
 #ifndef COMPAT
@@ -30,11 +32,14 @@ ret_t do_physdev_op_compat(XEN_GUEST_HANDLE(physdev_op_t) 
uop)
 /* Legacy hypercall (as of 0x00030101). */
 long do_sched_op_compat(int cmd, unsigned long arg)
 {
+    typeof(do_sched_op) *fn =
+        (void *)pv_hypercall_table[__HYPERVISOR_sched_op].native;
+
     switch ( cmd )
     {
     case SCHEDOP_yield:
     case SCHEDOP_block:
-        return do_sched_op(cmd, guest_handle_from_ptr(NULL, void));
+        return fn(cmd, guest_handle_from_ptr(NULL, void));
 
     case SCHEDOP_shutdown:
         TRACE_3D(TRC_SCHED_SHUTDOWN,
@@ -52,6 +57,8 @@ long do_sched_op_compat(int cmd, unsigned long arg)
 /* Legacy hypercall (as of 0x00030202). */
 long do_event_channel_op_compat(XEN_GUEST_HANDLE_PARAM(evtchn_op_t) uop)
 {
+    typeof(do_event_channel_op) *fn =
+        (void *)pv_hypercall_table[__HYPERVISOR_event_channel_op].native;
     struct evtchn_op op;
 
     if ( unlikely(copy_from_guest(&op, uop, 1) != 0) )
@@ -69,8 +76,7 @@ long 
do_event_channel_op_compat(XEN_GUEST_HANDLE_PARAM(evtchn_op_t) uop)
     case EVTCHNOP_bind_ipi:
     case EVTCHNOP_bind_vcpu:
     case EVTCHNOP_unmask:
-        return pv_get_hypercall_handler(__HYPERVISOR_event_channel_op, false)
-               (op.cmd, (unsigned long)&uop.p->u, 0, 0, 0, 0);
+        return fn(op.cmd, guest_handle_from_ptr(&uop.p->u, void));
 
     default:
         return -ENOSYS;
diff --git a/xen/arch/x86/pv/hypercall.c b/xen/arch/x86/pv/hypercall.c
index 3b72d6a..bbc3011 100644
--- a/xen/arch/x86/pv/hypercall.c
+++ b/xen/arch/x86/pv/hypercall.c
@@ -32,7 +32,7 @@
 
 #define do_arch_1             paging_domctl_continuation
 
-static const hypercall_table_t pv_hypercall_table[] = {
+const hypercall_table_t pv_hypercall_table[] = {
     COMPAT_CALL(set_trap_table),
     HYPERCALL(mmu_update),
     COMPAT_CALL(set_gdt),
@@ -320,23 +320,6 @@ void hypercall_page_initialise_ring1_kernel(void 
*hypercall_page)
     *(u16 *)(p+ 6) = (HYPERCALL_VECTOR << 8) | 0xcd; /* int  $xx */
 }
 
-void __init pv_hypercall_table_replace(unsigned int hypercall,
-                                       hypercall_fn_t * native,
-                                       hypercall_fn_t *compat)
-{
-#define HANDLER_POINTER(f) \
-    ((unsigned long *)__va(__pa(&pv_hypercall_table[hypercall].f)))
-    write_atomic(HANDLER_POINTER(native), (unsigned long)native);
-    write_atomic(HANDLER_POINTER(compat), (unsigned long)compat);
-#undef HANDLER_POINTER
-}
-
-hypercall_fn_t *pv_get_hypercall_handler(unsigned int hypercall, bool compat)
-{
-    return compat ? pv_hypercall_table[hypercall].compat
-                  : pv_hypercall_table[hypercall].native;
-}
-
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/x86/pv/shim.c b/xen/arch/x86/pv/shim.c
index d5383dc..9651952 100644
--- a/xen/arch/x86/pv/shim.c
+++ b/xen/arch/x86/pv/shim.c
@@ -160,6 +160,7 @@ void __init pv_shim_setup_dom(struct domain *d, 
l4_pgentry_t *l4start,
                               unsigned long console_va, unsigned long vphysmap,
                               start_info_t *si)
 {
+    hypercall_table_t *rw_pv_hypercall_table;
     uint64_t param = 0;
     long rc;
 
@@ -205,12 +206,20 @@ void __init pv_shim_setup_dom(struct domain *d, 
l4_pgentry_t *l4start,
                             mfn_x(console_mfn), vphysmap);
         consoled_set_ring_addr(page);
     }
-    pv_hypercall_table_replace(__HYPERVISOR_event_channel_op,
-                               (hypercall_fn_t *)pv_shim_event_channel_op,
-                               (hypercall_fn_t *)pv_shim_event_channel_op);
-    pv_hypercall_table_replace(__HYPERVISOR_grant_table_op,
-                               (hypercall_fn_t *)pv_shim_grant_table_op,
-                               (hypercall_fn_t *)pv_shim_grant_table_op);
+
+    /*
+     * Find a writeable mapping to pv_hypercall_table[] in the directmap
+     * insert some shim-specific hypercall handlers.
+     */
+    rw_pv_hypercall_table = __va(__pa(pv_hypercall_table));
+    rw_pv_hypercall_table[__HYPERVISOR_event_channel_op].native =
+        rw_pv_hypercall_table[__HYPERVISOR_event_channel_op].compat =
+        (hypercall_fn_t *)pv_shim_event_channel_op;
+
+    rw_pv_hypercall_table[__HYPERVISOR_grant_table_op].native =
+        rw_pv_hypercall_table[__HYPERVISOR_grant_table_op].compat =
+        (hypercall_fn_t *)pv_shim_grant_table_op;
+
     guest = d;
 
     /*
diff --git a/xen/include/asm-x86/hypercall.h b/xen/include/asm-x86/hypercall.h
index b9f3ecf..1cc2e37 100644
--- a/xen/include/asm-x86/hypercall.h
+++ b/xen/include/asm-x86/hypercall.h
@@ -25,12 +25,12 @@ typedef struct {
 
 extern const hypercall_args_t hypercall_args_table[NR_hypercalls];
 
+#ifdef CONFIG_PV
+extern const hypercall_table_t pv_hypercall_table[];
 void pv_hypercall(struct cpu_user_regs *regs);
 void hypercall_page_initialise_ring3_kernel(void *hypercall_page);
 void hypercall_page_initialise_ring1_kernel(void *hypercall_page);
-void pv_hypercall_table_replace(unsigned int hypercall, hypercall_fn_t * 
native,
-                                hypercall_fn_t *compat);
-hypercall_fn_t *pv_get_hypercall_handler(unsigned int hypercall, bool compat);
+#endif
 
 /*
  * Both do_mmuext_op() and do_mmu_update():
-- 
2.1.4


_______________________________________________
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®.