From: Julien Grall <julien.grall@citrix.com>
To: xen-devel@lists.xenproject.org
Cc: Julien Grall <julien.grall@citrix.com>,
ian.campbell@citrix.com, stefano.stabellini@eu.citrix.com
Subject: [RFC 07/10] xen/arm: Implement the code to dispatch the hypercall in assembly
Date: Tue, 15 Dec 2015 17:52:05 +0000 [thread overview]
Message-ID: <1450201928-4928-8-git-send-email-julien.grall@citrix.com> (raw)
In-Reply-To: <1450201928-4928-1-git-send-email-julien.grall@citrix.com>
Each hypercalls have different number of arguments. To avoid worry about
the number of arguments, all the hypercall handler are cast to a
5-arguments function. However, based on the C-spec (see 6.3.2.3 paragraph 8
and 6.7.5.3 paraph 2) the behavior is undefined.
This is also the first step to handle the hypercall directly in
assembly.
Signed-off-by: Julien Grall <julien.grall@citrix.com>
---
TODO:
- Implement do_dispatch_hypercall for ARM32
---
xen/arch/arm/Makefile | 1 +
xen/arch/arm/arm64/Makefile | 1 +
xen/arch/arm/arm64/hypercall.S | 27 +++++++++++++
xen/arch/arm/hypercall.S | 88 ++++++++++++++++++++++++++++++++++++++++
xen/arch/arm/traps.c | 90 ++++++-----------------------------------
xen/include/asm-arm/hypercall.h | 9 +++++
6 files changed, 139 insertions(+), 77 deletions(-)
create mode 100644 xen/arch/arm/arm64/hypercall.S
create mode 100644 xen/arch/arm/hypercall.S
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 4ac5edd..3bf7455 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -40,6 +40,7 @@ obj-y += device.o
obj-y += decode.o
obj-y += processor.o
obj-y += smc.o
+obj-y += hypercall.o
#obj-bin-y += ....o
diff --git a/xen/arch/arm/arm64/Makefile b/xen/arch/arm/arm64/Makefile
index c7243f5..1255b4b 100644
--- a/xen/arch/arm/arm64/Makefile
+++ b/xen/arch/arm/arm64/Makefile
@@ -8,5 +8,6 @@ obj-y += vfp.o
obj-y += smpboot.o
obj-y += domctl.o
obj-y += cache.o
+obj-y += hypercall.o
obj-$(EARLY_PRINTK) += debug.o
diff --git a/xen/arch/arm/arm64/hypercall.S b/xen/arch/arm/arm64/hypercall.S
new file mode 100644
index 0000000..d831181
--- /dev/null
+++ b/xen/arch/arm/arm64/hypercall.S
@@ -0,0 +1,27 @@
+#include <xen/config.h>
+#include <asm/asm_defns.h>
+
+/*
+ * int do_dispatch_hypercall(register_t arg1, register_t arg2,
+ * register_t arg3, register_t arg4,
+ * register_t arg5, register_t nr)
+ *
+ * x0 - arg1
+ * x1 - arg2
+ * x2 - arg3
+ * x3 - arg4
+ * x4 - arg5
+ * x5 - nr
+ *
+ * return the hypercall result in x0.
+ */
+ENTRY(do_dispatch_hypercall)
+ push x19, lr /* Save lr (x19 is here because the stack need to be 16 bytes aligned */
+ ldr x10, =hypercall_table
+ ldr x10, [x10, x5, lsl #3] /* x10 := pointer to hypercall function */
+
+ blr x10 /* Call the hypercall */
+
+ pop x19, lr /* Restore lr */
+
+ ret
diff --git a/xen/arch/arm/hypercall.S b/xen/arch/arm/hypercall.S
new file mode 100644
index 0000000..c8680eb
--- /dev/null
+++ b/xen/arch/arm/hypercall.S
@@ -0,0 +1,88 @@
+#include <xen/config.h>
+#include <public/xen.h>
+
+#ifdef CONFIG_ARM_64
+#define ventry .quad
+#else
+#define ventry .word
+#endif
+
+ENTRY(hypercall_table)
+ /* Hypercalls 0-5 are not implemented on ARM */
+ .rept 6
+ ventry do_ni_hypercall
+ .endr
+ ventry do_deprecated_hypercall
+ ventry do_platform_op
+ ventry do_ni_hypercall
+ ventry do_ni_hypercall
+ ventry do_ni_hypercall /* 10 */
+ ventry do_ni_hypercall
+ ventry do_memory_op
+ ventry do_multicall
+ ventry do_ni_hypercall
+ ventry do_ni_hypercall /* 15 */
+ ventry do_deprecated_hypercall
+ ventry do_xen_version
+ ventry do_console_io
+ ventry do_deprecated_hypercall
+ ventry do_grant_table_op /* 20 */
+ ventry do_ni_hypercall
+ ventry do_ni_hypercall
+ ventry do_ni_hypercall
+ ventry do_vcpu_op
+ ventry do_ni_hypercall /* 25 */
+ ventry do_ni_hypercall
+ ventry do_xsm_op
+ ventry do_ni_hypercall
+ ventry do_sched_op
+ ventry do_ni_hypercall /* 30 */
+ ventry do_ni_hypercall
+ ventry do_event_channel_op
+ ventry do_physdev_op
+ ventry do_hvm_op
+ ventry do_sysctl /* 35 */
+ ventry do_domctl
+ .rept NR_hypercalls-((.-hypercall_table)/BYTES_PER_LONG)
+ ventry do_ni_hypercall
+ .endr
+
+ENTRY(hypercall_args_table)
+ /* Hypercalls 0-5 are not implemented on ARM */
+ .rept 6
+ .byte 0 /* do_ni_hypercall */
+ .endr
+ .byte 2 /* do_deprecated_hypercall */
+ .byte 1 /* do_platform_op */
+ .byte 0 /* do_ni_hypercall */
+ .byte 0 /* do_ni_hypercall */
+ .byte 0 /* do_ni_hypercall */ /* 10 */
+ .byte 0 /* do_ni_hypercall */
+ .byte 2 /* do_memory_op */
+ .byte 2 /* do_multicall */
+ .byte 0 /* do_ni_hypercall */
+ .byte 0 /* do_ni_hypercall */
+ .byte 1 /* do_deprecated_hypercall */
+ .byte 2 /* do_xen_version */
+ .byte 3 /* do_console_io */
+ .byte 1 /* do_deprecated_hypercall */
+ .byte 3 /* do_grant_table_op */ /* 20 */
+ .byte 0 /* do_ni_hypercall */
+ .byte 0 /* do_ni_hypercall */
+ .byte 0 /* do_ni_hypercall */
+ .byte 3 /* do_vcpu_op */
+ .byte 0 /* do_ni_hypercall */ /* 25 */
+ .byte 0 /* do_ni_hypercall */
+ .byte 1 /* do_xsm_op */
+ .byte 0 /* do_ni_hypercall */
+ .byte 2 /* do_sched_op */
+ .byte 0 /* do_ni_hypercall */ /* 30 */
+ .byte 0 /* do_ni_hypercall */
+ .byte 2 /* do_event_channel_op */
+ .byte 2 /* do_physdev_op */
+ .byte 2 /* do_hvm_op */
+ .byte 1 /* do_sysctl */ /* 35 */
+ .byte 1 /* do_domctl */
+ .rept NR_hypercalls-(.-hypercall_args_table)
+ .byte 0 /* do_ni_hypercall */
+ .endr
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index f222d96..cc67d23 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -1171,7 +1171,7 @@ die:
}
#endif
-static register_t do_deprecated_hypercall(void)
+register_t do_deprecated_hypercall(void)
{
struct cpu_user_regs *regs = guest_cpu_user_regs();
const register_t op =
@@ -1187,56 +1187,6 @@ static register_t do_deprecated_hypercall(void)
return -ENOSYS;
}
-typedef register_t (*arm_hypercall_fn_t)(
- register_t, register_t, register_t, register_t, register_t);
-
-typedef struct {
- arm_hypercall_fn_t fn;
- int nr_args;
-} arm_hypercall_t;
-
-#define HYPERCALL(_name, _nr_args) \
- [ __HYPERVISOR_ ## _name ] = { \
- .fn = (arm_hypercall_fn_t) &do_ ## _name, \
- .nr_args = _nr_args, \
- }
-
-#define HYPERCALL_ARM(_name, _nr_args) \
- [ __HYPERVISOR_ ## _name ] = { \
- .fn = (arm_hypercall_fn_t) &do_arm_ ## _name, \
- .nr_args = _nr_args, \
- }
-/*
- * Only use this for hypercalls which were deprecated (i.e. replaced
- * by something else) before Xen on ARM was created, i.e. *not* for
- * hypercalls which are simply not yet used on ARM.
- */
-#define HYPERCALL_DEPRECATED(_name, _nr_args) \
- [ __HYPERVISOR_##_name ] = { \
- .fn = (arm_hypercall_fn_t) &do_deprecated_hypercall, \
- .nr_args = _nr_args, \
- }
-
-static arm_hypercall_t arm_hypercall_table[] = {
- HYPERCALL(memory_op, 2),
- HYPERCALL(domctl, 1),
- HYPERCALL(sched_op, 2),
- HYPERCALL_DEPRECATED(sched_op_compat, 2),
- HYPERCALL(console_io, 3),
- HYPERCALL(xen_version, 2),
- HYPERCALL(xsm_op, 1),
- HYPERCALL(event_channel_op, 2),
- HYPERCALL_DEPRECATED(event_channel_op_compat, 1),
- HYPERCALL(physdev_op, 2),
- HYPERCALL_DEPRECATED(physdev_op_compat, 1),
- HYPERCALL(sysctl, 2),
- HYPERCALL(hvm_op, 2),
- HYPERCALL(grant_table_op, 3),
- HYPERCALL(multicall, 2),
- HYPERCALL(platform_op, 1),
- HYPERCALL_ARM(vcpu_op, 3),
-};
-
#ifndef NDEBUG
static void do_debug_trap(struct cpu_user_regs *regs, unsigned int code)
{
@@ -1406,17 +1356,14 @@ static void do_trap_psci(struct cpu_user_regs *regs)
static void do_trap_hypercall(struct cpu_user_regs *regs, register_t *nr,
unsigned long iss)
{
- arm_hypercall_fn_t call = NULL;
#ifndef NDEBUG
register_t orig_pc = regs->pc;
#endif
- BUILD_BUG_ON(NR_hypercalls < ARRAY_SIZE(arm_hypercall_table) );
-
if ( iss != XEN_HYPERCALL_TAG )
domain_crash_synchronous();
- if ( *nr >= ARRAY_SIZE(arm_hypercall_table) )
+ if ( *nr >= NR_hypercalls )
{
perfc_incr(invalid_hypercalls);
HYPERCALL_RESULT_REG(regs) = -ENOSYS;
@@ -1424,14 +1371,9 @@ static void do_trap_hypercall(struct cpu_user_regs *regs, register_t *nr,
}
perfc_incra(hypercalls, *nr);
- call = arm_hypercall_table[*nr].fn;
- if ( call == NULL )
- {
- HYPERCALL_RESULT_REG(regs) = -ENOSYS;
- return;
- }
- HYPERCALL_RESULT_REG(regs) = call(HYPERCALL_ARGS(regs));
+ HYPERCALL_RESULT_REG(regs) = do_dispatch_hypercall(HYPERCALL_ARGS(regs),
+ *nr);
#ifndef NDEBUG
/*
@@ -1440,13 +1382,16 @@ static void do_trap_hypercall(struct cpu_user_regs *regs, register_t *nr,
*/
if ( orig_pc == regs->pc )
{
- switch ( arm_hypercall_table[*nr].nr_args ) {
+ switch ( hypercall_args_table[*nr] ) {
case 5: HYPERCALL_ARG5(regs) = 0xDEADBEEF;
case 4: HYPERCALL_ARG4(regs) = 0xDEADBEEF;
case 3: HYPERCALL_ARG3(regs) = 0xDEADBEEF;
case 2: HYPERCALL_ARG2(regs) = 0xDEADBEEF;
case 1: /* Don't clobber x0/r0 -- it's the return value */
break;
+ case 0:
+ ASSERT(hypercall_table[*nr] == do_ni_hypercall);
+ break;
default: BUG();
}
*nr = 0xDEADBEEF;
@@ -1458,7 +1403,7 @@ static bool_t check_multicall_32bit_clean(struct multicall_entry *multi)
{
int i;
- for ( i = 0; i < arm_hypercall_table[multi->op].nr_args; i++ )
+ for ( i = 0; i < hypercall_args_table[multi->op]; i++ )
{
if ( unlikely(multi->args[i] & 0xffffffff00000000ULL) )
{
@@ -1474,16 +1419,7 @@ static bool_t check_multicall_32bit_clean(struct multicall_entry *multi)
void do_multicall_call(struct multicall_entry *multi)
{
- arm_hypercall_fn_t call = NULL;
-
- if ( multi->op >= ARRAY_SIZE(arm_hypercall_table) )
- {
- multi->result = -ENOSYS;
- return;
- }
-
- call = arm_hypercall_table[multi->op].fn;
- if ( call == NULL )
+ if ( multi->op >= NR_hypercalls )
{
multi->result = -ENOSYS;
return;
@@ -1493,9 +1429,9 @@ void do_multicall_call(struct multicall_entry *multi)
!check_multicall_32bit_clean(multi) )
return;
- multi->result = call(multi->args[0], multi->args[1],
- multi->args[2], multi->args[3],
- multi->args[4]);
+ multi->result = do_dispatch_hypercall(multi->args[0], multi->args[1],
+ multi->args[2], multi->args[3],
+ multi->args[4], multi->op);
}
/*
diff --git a/xen/include/asm-arm/hypercall.h b/xen/include/asm-arm/hypercall.h
index a0c5a31..41e43ec 100644
--- a/xen/include/asm-arm/hypercall.h
+++ b/xen/include/asm-arm/hypercall.h
@@ -9,6 +9,15 @@ long do_arm_vcpu_op(int cmd, unsigned int vcpuid, XEN_GUEST_HANDLE_PARAM(void) a
long subarch_do_domctl(struct xen_domctl *domctl, struct domain *d,
XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl);
+register_t do_deprecated_hypercall(void);
+
+register_t do_dispatch_hypercall(register_t arg0, register_t arg1,
+ register_t arg2, register_t arg3,
+ register_t arg4, register_t nr);
+
+extern const uint8_t hypercall_args_table[];
+extern const void *hypercall_table[];
+
#endif /* __ASM_ARM_HYPERCALL_H__ */
/*
* Local variables:
--
2.1.4
next prev parent reply other threads:[~2015-12-15 17:54 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-12-15 17:51 [RFC 00/10] xen/arm: Implement the hypercall handling in assembly Julien Grall
2015-12-15 17:51 ` [RFC 01/10] xen/arm: move lr, push and pop in a separate header Julien Grall
2015-12-15 17:52 ` [RFC 02/10] xen/arm: Drop unused defines in asm/bug.h Julien Grall
2015-12-15 17:52 ` [RFC 03/10] xen/arm: Implement assembly version of WARN/BUG/ASSERT_FAILED Julien Grall
2015-12-15 17:52 ` [RFC 04/10] xen/arm64: Add an assembly macro for perf counter Julien Grall
2015-12-15 17:52 ` [RFC 05/10] xen/arm: gic_inject: Introduce a local variable to store current Julien Grall
2015-12-15 17:52 ` [RFC 06/10] xen/arm: gic: Allow the LRs to be cleared lazily Julien Grall
2015-12-15 17:52 ` Julien Grall [this message]
2015-12-15 17:52 ` [RFC 08/10] xen/arm64: Implement the hypercall handing fully in assembly Julien Grall
2015-12-15 17:52 ` [RFC 09/10] xen/arm: Remove the C version of do_trap_hypercall Julien Grall
2015-12-15 17:52 ` [RFC 10/10] xen/arm: Factorize the C code to dispatch HVC Julien Grall
2015-12-15 18:33 ` [RFC 00/10] xen/arm: Implement the hypercall handling in assembly Andrew Cooper
2015-12-16 11:19 ` Ian Campbell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1450201928-4928-8-git-send-email-julien.grall@citrix.com \
--to=julien.grall@citrix.com \
--cc=ian.campbell@citrix.com \
--cc=stefano.stabellini@eu.citrix.com \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).