|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] x86/hypercall: Split out PV hypercall infrastructure
commit 0c221ae9d745de138850c6903a5861e2582df863
Author: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Mon Feb 13 11:49:33 2017 +0000
Commit: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Thu Feb 16 14:15:25 2017 +0000
x86/hypercall: Split out PV hypercall infrastructure
Repurpose arch/x86/hypercall.c to be common x86 hypercall infrastructure,
and
move the PV specific routines to arch/x86/pv/hypercall.c
This is purely code motion.
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Acked-by: Jan Beulich <jbeulich@xxxxxxxx>
---
xen/arch/x86/Makefile | 1 +
xen/arch/x86/hypercall.c | 226 +-------------------------------------
xen/arch/x86/pv/Makefile | 1 +
xen/arch/x86/pv/hypercall.c | 257 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 261 insertions(+), 224 deletions(-)
diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index 007dced..10f519e 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -4,6 +4,7 @@ subdir-y += genapic
subdir-y += hvm
subdir-y += mm
subdir-$(CONFIG_XENOPROF) += oprofile
+subdir-y += pv
subdir-y += x86_64
alternative-y := alternative.init.o
diff --git a/xen/arch/x86/hypercall.c b/xen/arch/x86/hypercall.c
index c0718f8..f807332 100644
--- a/xen/arch/x86/hypercall.c
+++ b/xen/arch/x86/hypercall.c
@@ -1,6 +1,8 @@
/******************************************************************************
* arch/x86/hypercall.c
*
+ * Common x86 hypercall infrastructure.
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -17,9 +19,7 @@
* Copyright (c) 2015,2016 Citrix Systems Ltd.
*/
-#include <xen/compiler.h>
#include <xen/hypercall.h>
-#include <xen/trace.h>
#define ARGS(x, n) \
[ __HYPERVISOR_ ## x ] = { n, n }
@@ -74,228 +74,6 @@ const hypercall_args_t hypercall_args_table[NR_hypercalls] =
#undef COMP
#undef ARGS
-#define HYPERCALL(x) \
- [ __HYPERVISOR_ ## x ] = { (hypercall_fn_t *) do_ ## x, \
- (hypercall_fn_t *) do_ ## x }
-#define COMPAT_CALL(x) \
- [ __HYPERVISOR_ ## x ] = { (hypercall_fn_t *) do_ ## x, \
- (hypercall_fn_t *) compat_ ## x }
-
-#define do_arch_1 paging_domctl_continuation
-
-static const hypercall_table_t pv_hypercall_table[] = {
- COMPAT_CALL(set_trap_table),
- HYPERCALL(mmu_update),
- COMPAT_CALL(set_gdt),
- HYPERCALL(stack_switch),
- COMPAT_CALL(set_callbacks),
- HYPERCALL(fpu_taskswitch),
- HYPERCALL(sched_op_compat),
- COMPAT_CALL(platform_op),
- HYPERCALL(set_debugreg),
- HYPERCALL(get_debugreg),
- COMPAT_CALL(update_descriptor),
- COMPAT_CALL(memory_op),
- COMPAT_CALL(multicall),
- COMPAT_CALL(update_va_mapping),
- COMPAT_CALL(set_timer_op),
- HYPERCALL(event_channel_op_compat),
- COMPAT_CALL(xen_version),
- HYPERCALL(console_io),
- COMPAT_CALL(physdev_op_compat),
- COMPAT_CALL(grant_table_op),
- COMPAT_CALL(vm_assist),
- COMPAT_CALL(update_va_mapping_otherdomain),
- COMPAT_CALL(iret),
- COMPAT_CALL(vcpu_op),
- HYPERCALL(set_segment_base),
- COMPAT_CALL(mmuext_op),
- COMPAT_CALL(xsm_op),
- COMPAT_CALL(nmi_op),
- COMPAT_CALL(sched_op),
- COMPAT_CALL(callback_op),
-#ifdef CONFIG_XENOPROF
- COMPAT_CALL(xenoprof_op),
-#endif
- HYPERCALL(event_channel_op),
- COMPAT_CALL(physdev_op),
- HYPERCALL(hvm_op),
- HYPERCALL(sysctl),
- HYPERCALL(domctl),
-#ifdef CONFIG_KEXEC
- COMPAT_CALL(kexec_op),
-#endif
-#ifdef CONFIG_TMEM
- HYPERCALL(tmem_op),
-#endif
- HYPERCALL(xenpmu_op),
- COMPAT_CALL(dm_op),
- HYPERCALL(mca),
- HYPERCALL(arch_1),
-};
-
-#undef do_arch_1
-#undef COMPAT_CALL
-#undef HYPERCALL
-
-void pv_hypercall(struct cpu_user_regs *regs)
-{
- struct vcpu *curr = current;
- unsigned long eax;
-
- ASSERT(guest_kernel_mode(curr, regs));
-
- eax = is_pv_32bit_vcpu(curr) ? regs->_eax : regs->rax;
-
- BUILD_BUG_ON(ARRAY_SIZE(pv_hypercall_table) >
- ARRAY_SIZE(hypercall_args_table));
-
- if ( (eax >= ARRAY_SIZE(pv_hypercall_table)) ||
- !pv_hypercall_table[eax].native )
- {
- regs->rax = -ENOSYS;
- return;
- }
-
- curr->hcall_preempted = false;
-
- if ( !is_pv_32bit_vcpu(curr) )
- {
- unsigned long rdi = regs->rdi;
- unsigned long rsi = regs->rsi;
- unsigned long rdx = regs->rdx;
- unsigned long r10 = regs->r10;
- unsigned long r8 = regs->r8;
- unsigned long r9 = regs->r9;
-
-#ifndef NDEBUG
- /* Deliberately corrupt parameter regs not used by this hypercall. */
- switch ( hypercall_args_table[eax].native )
- {
- case 0: rdi = 0xdeadbeefdeadf00dUL;
- case 1: rsi = 0xdeadbeefdeadf00dUL;
- case 2: rdx = 0xdeadbeefdeadf00dUL;
- case 3: r10 = 0xdeadbeefdeadf00dUL;
- case 4: r8 = 0xdeadbeefdeadf00dUL;
- case 5: r9 = 0xdeadbeefdeadf00dUL;
- }
-#endif
- if ( unlikely(tb_init_done) )
- {
- unsigned long args[6] = { rdi, rsi, rdx, r10, r8, r9 };
-
- __trace_hypercall(TRC_PV_HYPERCALL_V2, eax, args);
- }
-
- regs->rax = pv_hypercall_table[eax].native(rdi, rsi, rdx, r10, r8, r9);
-
-#ifndef NDEBUG
- if ( !curr->hcall_preempted )
- {
- /* Deliberately corrupt parameter regs used by this hypercall. */
- switch ( hypercall_args_table[eax].native )
- {
- case 6: regs->r9 = 0xdeadbeefdeadf00dUL;
- case 5: regs->r8 = 0xdeadbeefdeadf00dUL;
- case 4: regs->r10 = 0xdeadbeefdeadf00dUL;
- case 3: regs->rdx = 0xdeadbeefdeadf00dUL;
- case 2: regs->rsi = 0xdeadbeefdeadf00dUL;
- case 1: regs->rdi = 0xdeadbeefdeadf00dUL;
- }
- }
-#endif
- }
- else
- {
- unsigned int ebx = regs->_ebx;
- unsigned int ecx = regs->_ecx;
- unsigned int edx = regs->_edx;
- unsigned int esi = regs->_esi;
- unsigned int edi = regs->_edi;
- unsigned int ebp = regs->_ebp;
-
-#ifndef NDEBUG
- /* Deliberately corrupt parameter regs not used by this hypercall. */
- switch ( hypercall_args_table[eax].compat )
- {
- case 0: ebx = 0xdeadf00d;
- case 1: ecx = 0xdeadf00d;
- case 2: edx = 0xdeadf00d;
- case 3: esi = 0xdeadf00d;
- case 4: edi = 0xdeadf00d;
- case 5: ebp = 0xdeadf00d;
- }
-#endif
-
- if ( unlikely(tb_init_done) )
- {
- unsigned long args[6] = { ebx, ecx, edx, esi, edi, ebp };
-
- __trace_hypercall(TRC_PV_HYPERCALL_V2, eax, args);
- }
-
- curr->hcall_compat = true;
- regs->_eax = pv_hypercall_table[eax].compat(ebx, ecx, edx, esi, edi,
ebp);
- curr->hcall_compat = false;
-
-#ifndef NDEBUG
- if ( !curr->hcall_preempted )
- {
- /* Deliberately corrupt parameter regs used by this hypercall. */
- switch ( hypercall_args_table[eax].compat )
- {
- case 6: regs->_ebp = 0xdeadf00d;
- case 5: regs->_edi = 0xdeadf00d;
- case 4: regs->_esi = 0xdeadf00d;
- case 3: regs->_edx = 0xdeadf00d;
- case 2: regs->_ecx = 0xdeadf00d;
- case 1: regs->_ebx = 0xdeadf00d;
- }
- }
-#endif
- }
-
- /*
- * PV guests use SYSCALL or INT $0x82 to make a hypercall, both of which
- * have trap semantics. If the hypercall has been preempted, rewind the
- * instruction pointer to reexecute the instruction.
- */
- if ( curr->hcall_preempted )
- regs->rip -= 2;
-
- perfc_incr(hypercalls);
-}
-
-void arch_do_multicall_call(struct mc_state *state)
-{
- if ( !is_pv_32bit_vcpu(current) )
- {
- struct multicall_entry *call = &state->call;
-
- if ( (call->op < ARRAY_SIZE(pv_hypercall_table)) &&
- pv_hypercall_table[call->op].native )
- call->result = pv_hypercall_table[call->op].native(
- call->args[0], call->args[1], call->args[2],
- call->args[3], call->args[4], call->args[5]);
- else
- call->result = -ENOSYS;
- }
-#ifdef CONFIG_COMPAT
- else
- {
- struct compat_multicall_entry *call = &state->compat_call;
-
- if ( (call->op < ARRAY_SIZE(pv_hypercall_table)) &&
- pv_hypercall_table[call->op].compat )
- call->result = pv_hypercall_table[call->op].compat(
- call->args[0], call->args[1], call->args[2],
- call->args[3], call->args[4], call->args[5]);
- else
- call->result = -ENOSYS;
- }
-#endif
-}
-
/*
* Local variables:
* mode: C
diff --git a/xen/arch/x86/pv/Makefile b/xen/arch/x86/pv/Makefile
new file mode 100644
index 0000000..de21937
--- /dev/null
+++ b/xen/arch/x86/pv/Makefile
@@ -0,0 +1 @@
+obj-y += hypercall.o
diff --git a/xen/arch/x86/pv/hypercall.c b/xen/arch/x86/pv/hypercall.c
new file mode 100644
index 0000000..9144f2e
--- /dev/null
+++ b/xen/arch/x86/pv/hypercall.c
@@ -0,0 +1,257 @@
+/******************************************************************************
+ * arch/x86/pv/hypercall.c
+ *
+ * PV hypercall dispatching routines
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (c) 2017 Citrix Systems Ltd.
+ */
+
+#include <xen/compiler.h>
+#include <xen/hypercall.h>
+#include <xen/trace.h>
+
+#define HYPERCALL(x) \
+ [ __HYPERVISOR_ ## x ] = { (hypercall_fn_t *) do_ ## x, \
+ (hypercall_fn_t *) do_ ## x }
+#define COMPAT_CALL(x) \
+ [ __HYPERVISOR_ ## x ] = { (hypercall_fn_t *) do_ ## x, \
+ (hypercall_fn_t *) compat_ ## x }
+
+#define do_arch_1 paging_domctl_continuation
+
+static const hypercall_table_t pv_hypercall_table[] = {
+ COMPAT_CALL(set_trap_table),
+ HYPERCALL(mmu_update),
+ COMPAT_CALL(set_gdt),
+ HYPERCALL(stack_switch),
+ COMPAT_CALL(set_callbacks),
+ HYPERCALL(fpu_taskswitch),
+ HYPERCALL(sched_op_compat),
+ COMPAT_CALL(platform_op),
+ HYPERCALL(set_debugreg),
+ HYPERCALL(get_debugreg),
+ COMPAT_CALL(update_descriptor),
+ COMPAT_CALL(memory_op),
+ COMPAT_CALL(multicall),
+ COMPAT_CALL(update_va_mapping),
+ COMPAT_CALL(set_timer_op),
+ HYPERCALL(event_channel_op_compat),
+ COMPAT_CALL(xen_version),
+ HYPERCALL(console_io),
+ COMPAT_CALL(physdev_op_compat),
+ COMPAT_CALL(grant_table_op),
+ COMPAT_CALL(vm_assist),
+ COMPAT_CALL(update_va_mapping_otherdomain),
+ COMPAT_CALL(iret),
+ COMPAT_CALL(vcpu_op),
+ HYPERCALL(set_segment_base),
+ COMPAT_CALL(mmuext_op),
+ COMPAT_CALL(xsm_op),
+ COMPAT_CALL(nmi_op),
+ COMPAT_CALL(sched_op),
+ COMPAT_CALL(callback_op),
+#ifdef CONFIG_XENOPROF
+ COMPAT_CALL(xenoprof_op),
+#endif
+ HYPERCALL(event_channel_op),
+ COMPAT_CALL(physdev_op),
+ HYPERCALL(hvm_op),
+ HYPERCALL(sysctl),
+ HYPERCALL(domctl),
+#ifdef CONFIG_KEXEC
+ COMPAT_CALL(kexec_op),
+#endif
+#ifdef CONFIG_TMEM
+ HYPERCALL(tmem_op),
+#endif
+ HYPERCALL(xenpmu_op),
+ COMPAT_CALL(dm_op),
+ HYPERCALL(mca),
+ HYPERCALL(arch_1),
+};
+
+#undef do_arch_1
+#undef COMPAT_CALL
+#undef HYPERCALL
+
+void pv_hypercall(struct cpu_user_regs *regs)
+{
+ struct vcpu *curr = current;
+ unsigned long eax;
+
+ ASSERT(guest_kernel_mode(curr, regs));
+
+ eax = is_pv_32bit_vcpu(curr) ? regs->_eax : regs->rax;
+
+ BUILD_BUG_ON(ARRAY_SIZE(pv_hypercall_table) >
+ ARRAY_SIZE(hypercall_args_table));
+
+ if ( (eax >= ARRAY_SIZE(pv_hypercall_table)) ||
+ !pv_hypercall_table[eax].native )
+ {
+ regs->rax = -ENOSYS;
+ return;
+ }
+
+ curr->hcall_preempted = false;
+
+ if ( !is_pv_32bit_vcpu(curr) )
+ {
+ unsigned long rdi = regs->rdi;
+ unsigned long rsi = regs->rsi;
+ unsigned long rdx = regs->rdx;
+ unsigned long r10 = regs->r10;
+ unsigned long r8 = regs->r8;
+ unsigned long r9 = regs->r9;
+
+#ifndef NDEBUG
+ /* Deliberately corrupt parameter regs not used by this hypercall. */
+ switch ( hypercall_args_table[eax].native )
+ {
+ case 0: rdi = 0xdeadbeefdeadf00dUL;
+ case 1: rsi = 0xdeadbeefdeadf00dUL;
+ case 2: rdx = 0xdeadbeefdeadf00dUL;
+ case 3: r10 = 0xdeadbeefdeadf00dUL;
+ case 4: r8 = 0xdeadbeefdeadf00dUL;
+ case 5: r9 = 0xdeadbeefdeadf00dUL;
+ }
+#endif
+ if ( unlikely(tb_init_done) )
+ {
+ unsigned long args[6] = { rdi, rsi, rdx, r10, r8, r9 };
+
+ __trace_hypercall(TRC_PV_HYPERCALL_V2, eax, args);
+ }
+
+ regs->rax = pv_hypercall_table[eax].native(rdi, rsi, rdx, r10, r8, r9);
+
+#ifndef NDEBUG
+ if ( !curr->hcall_preempted )
+ {
+ /* Deliberately corrupt parameter regs used by this hypercall. */
+ switch ( hypercall_args_table[eax].native )
+ {
+ case 6: regs->r9 = 0xdeadbeefdeadf00dUL;
+ case 5: regs->r8 = 0xdeadbeefdeadf00dUL;
+ case 4: regs->r10 = 0xdeadbeefdeadf00dUL;
+ case 3: regs->rdx = 0xdeadbeefdeadf00dUL;
+ case 2: regs->rsi = 0xdeadbeefdeadf00dUL;
+ case 1: regs->rdi = 0xdeadbeefdeadf00dUL;
+ }
+ }
+#endif
+ }
+ else
+ {
+ unsigned int ebx = regs->_ebx;
+ unsigned int ecx = regs->_ecx;
+ unsigned int edx = regs->_edx;
+ unsigned int esi = regs->_esi;
+ unsigned int edi = regs->_edi;
+ unsigned int ebp = regs->_ebp;
+
+#ifndef NDEBUG
+ /* Deliberately corrupt parameter regs not used by this hypercall. */
+ switch ( hypercall_args_table[eax].compat )
+ {
+ case 0: ebx = 0xdeadf00d;
+ case 1: ecx = 0xdeadf00d;
+ case 2: edx = 0xdeadf00d;
+ case 3: esi = 0xdeadf00d;
+ case 4: edi = 0xdeadf00d;
+ case 5: ebp = 0xdeadf00d;
+ }
+#endif
+
+ if ( unlikely(tb_init_done) )
+ {
+ unsigned long args[6] = { ebx, ecx, edx, esi, edi, ebp };
+
+ __trace_hypercall(TRC_PV_HYPERCALL_V2, eax, args);
+ }
+
+ curr->hcall_compat = true;
+ regs->_eax = pv_hypercall_table[eax].compat(ebx, ecx, edx, esi, edi,
ebp);
+ curr->hcall_compat = false;
+
+#ifndef NDEBUG
+ if ( !curr->hcall_preempted )
+ {
+ /* Deliberately corrupt parameter regs used by this hypercall. */
+ switch ( hypercall_args_table[eax].compat )
+ {
+ case 6: regs->_ebp = 0xdeadf00d;
+ case 5: regs->_edi = 0xdeadf00d;
+ case 4: regs->_esi = 0xdeadf00d;
+ case 3: regs->_edx = 0xdeadf00d;
+ case 2: regs->_ecx = 0xdeadf00d;
+ case 1: regs->_ebx = 0xdeadf00d;
+ }
+ }
+#endif
+ }
+
+ /*
+ * PV guests use SYSCALL or INT $0x82 to make a hypercall, both of which
+ * have trap semantics. If the hypercall has been preempted, rewind the
+ * instruction pointer to reexecute the instruction.
+ */
+ if ( curr->hcall_preempted )
+ regs->rip -= 2;
+
+ perfc_incr(hypercalls);
+}
+
+void arch_do_multicall_call(struct mc_state *state)
+{
+ if ( !is_pv_32bit_vcpu(current) )
+ {
+ struct multicall_entry *call = &state->call;
+
+ if ( (call->op < ARRAY_SIZE(pv_hypercall_table)) &&
+ pv_hypercall_table[call->op].native )
+ call->result = pv_hypercall_table[call->op].native(
+ call->args[0], call->args[1], call->args[2],
+ call->args[3], call->args[4], call->args[5]);
+ else
+ call->result = -ENOSYS;
+ }
+#ifdef CONFIG_COMPAT
+ else
+ {
+ struct compat_multicall_entry *call = &state->compat_call;
+
+ if ( (call->op < ARRAY_SIZE(pv_hypercall_table)) &&
+ pv_hypercall_table[call->op].compat )
+ call->result = pv_hypercall_table[call->op].compat(
+ call->args[0], call->args[1], call->args[2],
+ call->args[3], call->args[4], call->args[5]);
+ else
+ call->result = -ENOSYS;
+ }
+#endif
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
--
generated by git-patchbot for /home/xen/git/xen.git#master
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |