* [RFC 00/10] xen/arm: Implement the hypercall handling in assembly
@ 2015-12-15 17:51 Julien Grall
2015-12-15 17:51 ` [RFC 01/10] xen/arm: move lr, push and pop in a separate header Julien Grall
` (10 more replies)
0 siblings, 11 replies; 13+ messages in thread
From: Julien Grall @ 2015-12-15 17:51 UTC (permalink / raw)
To: xen-devel; +Cc: Julien Grall, ian.campbell, stefano.stabellini
Hi all,
This patch aims is a first attempt to write the hypercall dispatch in assembly
in order to avoid reloading the hypercall arguments from the stack.
I've posted an early version to get comments and only the ARM64 side has been
implemented.
A branch with the code can be found here:
git://xenbits.xen.org/people/julieng/xen-unstable.git branch asm-hypercall-rfc
Sincerely yours,
Julien Grall (10):
xen/arm: move lr, push and pop in a separate header
xen/arm: Drop unused defines in asm/bug.h
xen/arm: Implement assembly version of WARN/BUG/ASSERT_FAILED...
xen/arm64: Add an assembly macro for perf counter
xen/arm: gic_inject: Introduce a local variable to store current
xen/arm: gic: Allow the LRs to be cleared lazily
xen/arm: Implement the code to dispatch the hypercall in assembly
xen/arm64: Implement the hypercall handing fully in assembly
xen/arm: Remove the C version of do_trap_hypercall
xen/arm: Factorize the C code to dispatch HVC
xen/arch/arm/Makefile | 1 +
xen/arch/arm/arm64/Makefile | 1 +
xen/arch/arm/arm64/asm-offsets.c | 11 +++
xen/arch/arm/arm64/entry.S | 165 +++++++++++++++++++++++++++++----
xen/arch/arm/arm64/hypercall.S | 27 ++++++
xen/arch/arm/gic.c | 17 +++-
xen/arch/arm/hypercall.S | 88 ++++++++++++++++++
xen/arch/arm/traps.c | 167 +++++-----------------------------
xen/include/asm-arm/arm64/asm_defns.h | 62 +++++++++++++
xen/include/asm-arm/arm64/bug.h | 4 +
xen/include/asm-arm/asm_defns.h | 3 +
xen/include/asm-arm/bug.h | 39 ++++++--
xen/include/asm-arm/domain.h | 7 +-
xen/include/asm-arm/hypercall.h | 9 ++
xen/include/asm-arm/processor.h | 3 +
15 files changed, 432 insertions(+), 172 deletions(-)
create mode 100644 xen/arch/arm/arm64/hypercall.S
create mode 100644 xen/arch/arm/hypercall.S
create mode 100644 xen/include/asm-arm/arm64/asm_defns.h
--
2.1.4
^ permalink raw reply [flat|nested] 13+ messages in thread
* [RFC 01/10] xen/arm: move lr, push and pop in a separate header
2015-12-15 17:51 [RFC 00/10] xen/arm: Implement the hypercall handling in assembly Julien Grall
@ 2015-12-15 17:51 ` Julien Grall
2015-12-15 17:52 ` [RFC 02/10] xen/arm: Drop unused defines in asm/bug.h Julien Grall
` (9 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Julien Grall @ 2015-12-15 17:51 UTC (permalink / raw)
To: xen-devel; +Cc: Julien Grall, ian.campbell, stefano.stabellini
The shorthand lr and the macros push/pop are useful for any assembly
code.
Move them in asm/arm64/asm_defns.h
Signed-off-by: Julien Grall <julien.grall@citrix.com>
---
xen/arch/arm/arm64/entry.S | 17 -----------------
xen/include/asm-arm/arm64/asm_defns.h | 26 ++++++++++++++++++++++++++
xen/include/asm-arm/asm_defns.h | 3 +++
3 files changed, 29 insertions(+), 17 deletions(-)
create mode 100644 xen/include/asm-arm/arm64/asm_defns.h
diff --git a/xen/arch/arm/arm64/entry.S b/xen/arch/arm/arm64/entry.S
index 9cda8f1..2b9d4cd 100644
--- a/xen/arch/arm/arm64/entry.S
+++ b/xen/arch/arm/arm64/entry.S
@@ -4,23 +4,6 @@
#include <public/xen.h>
/*
- * Register aliases.
- */
-lr .req x30 // link register
-
-/*
- * Stack pushing/popping (register pairs only). Equivalent to store decrement
- * before, load increment after.
- */
- .macro push, xreg1, xreg2
- stp \xreg1, \xreg2, [sp, #-16]!
- .endm
-
- .macro pop, xreg1, xreg2
- ldp \xreg1, \xreg2, [sp], #16
- .endm
-
-/*
* Save/restore guest mode specific state, outer stack frame
*/
.macro entry_guest, compat
diff --git a/xen/include/asm-arm/arm64/asm_defns.h b/xen/include/asm-arm/arm64/asm_defns.h
new file mode 100644
index 0000000..7085c26
--- /dev/null
+++ b/xen/include/asm-arm/arm64/asm_defns.h
@@ -0,0 +1,26 @@
+#ifndef __ASM_ARM_ARM64_DEFNS_H__
+#define __ASM_ARM_ARM64_DEFNS_H__
+
+#ifdef __ASSEMBLY__
+
+/*
+ * Register aliases.
+ */
+lr .req x30 // link register
+
+/*
+ * Stack pushing/popping (register pairs only). Equivalent to store decrement
+ * before, load increment after.
+ */
+.macro push, xreg1, xreg2
+stp \xreg1, \xreg2, [sp, #-16]!
+.endm
+
+.macro pop, xreg1, xreg2
+ldp \xreg1, \xreg2, [sp], #16
+.endm
+
+#endif /* !__ASSEMBLY__ */
+
+
+#endif /* __ASM_ARM_ARM64_DEFNS_H__ */
diff --git a/xen/include/asm-arm/asm_defns.h b/xen/include/asm-arm/asm_defns.h
index 02be83e..365263b 100644
--- a/xen/include/asm-arm/asm_defns.h
+++ b/xen/include/asm-arm/asm_defns.h
@@ -12,6 +12,9 @@
# define __OP32
#elif defined(CONFIG_ARM_64)
# define __OP32 "w"
+
+# include <asm/arm64/asm_defns.h>
+
#else
# error "unknown ARM variant"
#endif
--
2.1.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFC 02/10] xen/arm: Drop unused defines in asm/bug.h
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 ` Julien Grall
2015-12-15 17:52 ` [RFC 03/10] xen/arm: Implement assembly version of WARN/BUG/ASSERT_FAILED Julien Grall
` (8 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Julien Grall @ 2015-12-15 17:52 UTC (permalink / raw)
To: xen-devel; +Cc: Julien Grall, ian.campbell, stefano.stabellini
The defines BUG_DISP_WIDTH, BUG_LINE_LO_WIDTH and BUG_LINE_HI_WIDTH have
been introduced by mistake in a previous patch. They are not used at all
so drop them.
Signed-off-by: Julien Grall <julien.grall@citrix.com>
---
xen/include/asm-arm/bug.h | 4 ----
1 file changed, 4 deletions(-)
diff --git a/xen/include/asm-arm/bug.h b/xen/include/asm-arm/bug.h
index ab9e811..fd3e95e 100644
--- a/xen/include/asm-arm/bug.h
+++ b/xen/include/asm-arm/bug.h
@@ -11,10 +11,6 @@
# error "unknown ARM variant"
#endif
-#define BUG_DISP_WIDTH 24
-#define BUG_LINE_LO_WIDTH (31 - BUG_DISP_WIDTH)
-#define BUG_LINE_HI_WIDTH (31 - BUG_DISP_WIDTH)
-
struct bug_frame {
signed int loc_disp; /* Relative address to the bug address */
signed int file_disp; /* Relative address to the filename */
--
2.1.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFC 03/10] xen/arm: Implement assembly version of WARN/BUG/ASSERT_FAILED...
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 ` Julien Grall
2015-12-15 17:52 ` [RFC 04/10] xen/arm64: Add an assembly macro for perf counter Julien Grall
` (7 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Julien Grall @ 2015-12-15 17:52 UTC (permalink / raw)
To: xen-devel; +Cc: Julien Grall, ian.campbell, stefano.stabellini
... to produce clear error message in assembly code.
Signed-off-by: Julien Grall <julien.grall@citrix.com>
---
TODO:
- Implement the arm32 bits
---
xen/arch/arm/arm64/entry.S | 1 +
xen/include/asm-arm/arm64/bug.h | 4 ++++
xen/include/asm-arm/bug.h | 37 +++++++++++++++++++++++++++++++++----
3 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/xen/arch/arm/arm64/entry.S b/xen/arch/arm/arm64/entry.S
index 2b9d4cd..93c80ff 100644
--- a/xen/arch/arm/arm64/entry.S
+++ b/xen/arch/arm/arm64/entry.S
@@ -1,5 +1,6 @@
#include <xen/config.h>
#include <asm/asm_defns.h>
+#include <asm/bug.h>
#include <asm/regs.h>
#include <public/xen.h>
diff --git a/xen/include/asm-arm/arm64/bug.h b/xen/include/asm-arm/arm64/bug.h
index 42b0e4f..9670505 100644
--- a/xen/include/asm-arm/arm64/bug.h
+++ b/xen/include/asm-arm/arm64/bug.h
@@ -5,6 +5,10 @@
#define BRK_BUG_FRAME 1
+#ifndef __ASSEMBLY__
#define BUG_INSTR "brk " __stringify(BRK_BUG_FRAME)
+#else
+#define BUG_INSTR brk BRK_BUG_FRAME
+#endif
#endif /* __ARM_ARM64_BUG_H__ */
diff --git a/xen/include/asm-arm/bug.h b/xen/include/asm-arm/bug.h
index fd3e95e..ffd7f6c 100644
--- a/xen/include/asm-arm/bug.h
+++ b/xen/include/asm-arm/bug.h
@@ -11,6 +11,12 @@
# error "unknown ARM variant"
#endif
+#define BUGFRAME_warn 0
+#define BUGFRAME_bug 1
+#define BUGFRAME_assert 2
+
+#ifndef __ASSEMBLY__
+
struct bug_frame {
signed int loc_disp; /* Relative address to the bug address */
signed int file_disp; /* Relative address to the filename */
@@ -24,10 +30,6 @@ struct bug_frame {
#define bug_line(b) ((b)->line)
#define bug_msg(b) ((const char *)(b) + (b)->msg_disp)
-#define BUGFRAME_warn 0
-#define BUGFRAME_bug 1
-#define BUGFRAME_assert 2
-
/* Many versions of GCC doesn't support the asm %c parameter which would
* be preferable to this unpleasantness. We use mergeable string
* sections to avoid multiple copies of the string appearing in the
@@ -71,6 +73,33 @@ extern const struct bug_frame __start_bug_frames[],
int do_bug_frame(struct cpu_user_regs *regs, vaddr_t pc);
+#else /* !__ASSEMBLY__ */
+
+.macro BUG_FRAME type, line , file, has_msg, msg
+.L\@bug:BUG_INSTR
+.pushsection .rodata.str, "aMS", %progbits, 1
+ .L\@s1:.asciz "\file"
+ .L\@s2:
+ .if \has_msg
+ .asciz "\msg"
+ .endif
+.popsection
+.pushsection .bug_frames.\type, "a", %progbits
+ .L\@bf:
+ .long (.L\@bug - .L\@bf)
+ .long (.L\@s1 - .L\@bf)
+ .long (.L\@s2 - .L\@bf)
+ .hword \line, 0
+.popsection
+.endm
+
+#define WARN BUG_FRAME BUGFRAME_warn, __LINE__, __FILE__, 0, 0
+#define BUG BUG_FRAME BUGFRAME_bug, __LINE__, __FILE__, 0, 0
+#define ASSERT_FAILED(msg) \
+ BUG_FRAME BUGFRAME_assert, __LINE__, __FILE__, 1, msg
+
+#endif
+
#endif /* __ARM_BUG_H__ */
/*
* Local variables:
--
2.1.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFC 04/10] xen/arm64: Add an assembly macro for perf counter
2015-12-15 17:51 [RFC 00/10] xen/arm: Implement the hypercall handling in assembly Julien Grall
` (2 preceding siblings ...)
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 ` Julien Grall
2015-12-15 17:52 ` [RFC 05/10] xen/arm: gic_inject: Introduce a local variable to store current Julien Grall
` (6 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Julien Grall @ 2015-12-15 17:52 UTC (permalink / raw)
To: xen-devel; +Cc: Julien Grall, ian.campbell, stefano.stabellini
Allow assembly code to use performance counter.
Signed-off-by: Julien Grall <julien.grall@citrix.com>
---
xen/include/asm-arm/arm64/asm_defns.h | 36 +++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/xen/include/asm-arm/arm64/asm_defns.h b/xen/include/asm-arm/arm64/asm_defns.h
index 7085c26..36442b8 100644
--- a/xen/include/asm-arm/arm64/asm_defns.h
+++ b/xen/include/asm-arm/arm64/asm_defns.h
@@ -20,6 +20,42 @@ stp \xreg1, \xreg2, [sp, #-16]!
ldp \xreg1, \xreg2, [sp], #16
.endm
+#ifdef PERF_COUNTERS
+
+.macro perfc_incr, name, idx
+push x0, x1 /* x0 and x1 are used by the macro -> save them */
+
+/*
+ * Compute the address of the perf counters
+ *
+ * Note that each perf counters are 4 bytes and stored percpu.
+ */
+mov x0, \idx /* x0 <- index from ASM_PERFC_* */
+add x0, x0, #\name /* x0 <- index in the percpu array */
+lsl x0, x0, 2 /* x0 <- offset from per_cpu__perfcounters. */
+ldr x1, =per_cpu__perfcounters
+add x0, x0, x1 /* x0 <- offset in the percpu area */
+mrs x1, TPIDR_EL2 /* x1 <- per cpu offset */
+add x0, x0, x1 /* x0 <- address of the perf counter for this cpu */
+
+/*
+ * Increment the perf counters.
+ *
+ * Note it's not atomic so does the C version.
+ */
+ldr x1, [x0] /* x1 <- current value of the counter */
+add x1, x1, 1 /* x1 <- increment the counter */
+str x1, [x0] /* Store the counters incremented */
+
+pop x0, x1 /* Restore x0, x1 */
+.endm
+
+#define PERFC_INCR(_name, _idx) perfc_incr ASM_PERFC_##_name, _idx
+
+#else
+#define PERFC_INCR(_name, _idx)
+#endif
+
#endif /* !__ASSEMBLY__ */
--
2.1.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFC 05/10] xen/arm: gic_inject: Introduce a local variable to store current
2015-12-15 17:51 [RFC 00/10] xen/arm: Implement the hypercall handling in assembly Julien Grall
` (3 preceding siblings ...)
2015-12-15 17:52 ` [RFC 04/10] xen/arm64: Add an assembly macro for perf counter Julien Grall
@ 2015-12-15 17:52 ` Julien Grall
2015-12-15 17:52 ` [RFC 06/10] xen/arm: gic: Allow the LRs to be cleared lazily Julien Grall
` (5 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Julien Grall @ 2015-12-15 17:52 UTC (permalink / raw)
To: xen-devel; +Cc: Julien Grall, ian.campbell, stefano.stabellini
current is a define which is replaced by a read to a system register.
Rather than reading the system registers multiple store the result in a
local variable.
Signed-off-by: Julien Grall <julien.grall@citrix.com>
---
xen/arch/arm/gic.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 1e1e5ba..37e579b 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -596,11 +596,13 @@ out:
void gic_inject(void)
{
+ struct vcpu *v = current;
+
ASSERT(!local_irq_is_enabled());
- gic_restore_pending_irqs(current);
+ gic_restore_pending_irqs(v);
- if ( !list_empty(¤t->arch.vgic.lr_pending) && lr_all_full() )
+ if ( !list_empty(&v->arch.vgic.lr_pending) && lr_all_full() )
gic_hw_ops->update_hcr_status(GICH_HCR_UIE, 1);
}
--
2.1.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFC 06/10] xen/arm: gic: Allow the LRs to be cleared lazily
2015-12-15 17:51 [RFC 00/10] xen/arm: Implement the hypercall handling in assembly Julien Grall
` (4 preceding siblings ...)
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 ` Julien Grall
2015-12-15 17:52 ` [RFC 07/10] xen/arm: Implement the code to dispatch the hypercall in assembly Julien Grall
` (4 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Julien Grall @ 2015-12-15 17:52 UTC (permalink / raw)
To: xen-devel; +Cc: Julien Grall, ian.campbell, stefano.stabellini
Currently the LRs are cleared every time we entered in Xen from a guest
before any action is taken by the hypervisor. This requiring to reload
the guest registers from the stack when an hypercall is handled for
instance.
However, we only need to clear the LRs for the following actions:
- An interrupt is received and injected
- Checking hypercall preemption
- Before re-entering in the guest
A new flag has been introduced per vCPU in vgic.flags to know whether
the LRs has been cleared since the vCPU has been running. The flag is
always cleared before switching back to the guest vCPU.
As clearing the LRs is now lazy, we have to check if they are cleared
every time we enter in the hypervisor and not only when we entered from
a lower exception state.
Note that actually no one is taking advantage of clearing the LRs
lazily. A follow-up patch will enable this possibility.
Signed-off-by: Julien Grall <julien.grall@citrix.com>
---
xen/arch/arm/gic.c | 11 +++++++++++
xen/arch/arm/traps.c | 9 ++++++++-
xen/include/asm-arm/domain.h | 7 ++++++-
3 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 37e579b..5d70251 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -476,6 +476,13 @@ void gic_clear_lrs(struct vcpu *v)
if ( is_idle_vcpu(v) )
return;
+ /*
+ * Check the LRs has already been cleared for this vCPU since the
+ * last time it has running.
+ */
+ if ( test_and_set_bit(_VGIC_LRS_CLEARED, &v->arch.vgic.flags) )
+ return;
+
gic_hw_ops->update_hcr_status(GICH_HCR_UIE, 0);
spin_lock_irqsave(&v->arch.vgic.lock, flags);
@@ -566,6 +573,8 @@ int gic_events_need_delivery(void)
int active_priority;
int rc = 0;
+ gic_clear_lrs(v);
+
mask_priority = gic_hw_ops->read_vmcr_priority();
active_priority = find_next_bit(&apr, 32, 0);
@@ -602,6 +611,8 @@ void gic_inject(void)
gic_restore_pending_irqs(v);
+ clear_bit(_VGIC_LRS_CLEARED, &v->arch.vgic.flags);
+
if ( !list_empty(&v->arch.vgic.lr_pending) && lr_all_full() )
gic_hw_ops->update_hcr_status(GICH_HCR_UIE, 1);
}
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index c49bd3f..f222d96 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -2451,7 +2451,12 @@ bad_data_abort:
static void enter_hypervisor_head(struct cpu_user_regs *regs)
{
- if ( guest_mode(regs) )
+ /*
+ * enter_hypervisor_head is called by most of the traps generated by the
+ * processor. It could be taken from the hypervisor or the guest.
+ * However current is only valid after Xen has finished to boot.
+ */
+ if ( likely(system_state > SYS_STATE_active) )
gic_clear_lrs(current);
}
@@ -2602,6 +2607,8 @@ asmlinkage void do_trap_fiq(struct cpu_user_regs *regs)
asmlinkage void leave_hypervisor_tail(void)
{
+ gic_clear_lrs(current);
+
while (1)
{
local_irq_disable();
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index e7e40da..401b4d0 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -245,7 +245,12 @@ struct arch_vcpu
/* GICv3: redistributor base and flags for this vCPU */
paddr_t rdist_base;
-#define VGIC_V3_RDIST_LAST (1 << 0) /* last vCPU of the rdist */
+/* Last vCPU of the rdist */
+#define _VGIC_V3_RDIST_LAST (0)
+#define VGIC_V3_RDIST_LAST (1 << _VGIC_V3_RDIST_LAST)
+/* LRs have been cleared for this vCPU */
+#define _VGIC_LRS_CLEARED (1)
+#define VGIC_LRS_CLEARED (1 << _VGIC_LRS_CLEARED)
uint8_t flags;
} vgic;
--
2.1.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFC 07/10] xen/arm: Implement the code to dispatch the hypercall in assembly
2015-12-15 17:51 [RFC 00/10] xen/arm: Implement the hypercall handling in assembly Julien Grall
` (5 preceding siblings ...)
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
2015-12-15 17:52 ` [RFC 08/10] xen/arm64: Implement the hypercall handing fully " Julien Grall
` (3 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Julien Grall @ 2015-12-15 17:52 UTC (permalink / raw)
To: xen-devel; +Cc: Julien Grall, ian.campbell, stefano.stabellini
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
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFC 08/10] xen/arm64: Implement the hypercall handing fully in assembly
2015-12-15 17:51 [RFC 00/10] xen/arm: Implement the hypercall handling in assembly Julien Grall
` (6 preceding siblings ...)
2015-12-15 17:52 ` [RFC 07/10] xen/arm: Implement the code to dispatch the hypercall in assembly Julien Grall
@ 2015-12-15 17:52 ` Julien Grall
2015-12-15 17:52 ` [RFC 09/10] xen/arm: Remove the C version of do_trap_hypercall Julien Grall
` (2 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Julien Grall @ 2015-12-15 17:52 UTC (permalink / raw)
To: xen-devel; +Cc: Julien Grall, ian.campbell, stefano.stabellini
Currently when the guest is issuing an hypercall, all the registers are
saved in the stack and then later reload from the stack before calling
the hypercall dispatcher.
To avoid spending time loading from the stack the arguments, the
hypercall handler can be implemented in assembly.
This patch implements the assembly version of do_trap_hypercall for
AArch64.
Note that the C version of do_trap_hypercall will be dropped in a
follow-up patch.
Signed-off-by: Julien Grall <julien.grall@citrix.com>
---
xen/arch/arm/arm64/asm-offsets.c | 11 +++
xen/arch/arm/arm64/entry.S | 147 ++++++++++++++++++++++++++++++++++++++-
xen/include/asm-arm/processor.h | 3 +
3 files changed, 159 insertions(+), 2 deletions(-)
diff --git a/xen/arch/arm/arm64/asm-offsets.c b/xen/arch/arm/arm64/asm-offsets.c
index a3ce816..6f0e8f1 100644
--- a/xen/arch/arm/arm64/asm-offsets.c
+++ b/xen/arch/arm/arm64/asm-offsets.c
@@ -23,6 +23,12 @@
void __dummy__(void)
{
OFFSET(UREGS_X0, struct cpu_user_regs, x0);
+ OFFSET(UREGS_X1, struct cpu_user_regs, x1);
+ OFFSET(UREGS_X2, struct cpu_user_regs, x2);
+ OFFSET(UREGS_X3, struct cpu_user_regs, x3);
+ OFFSET(UREGS_X4, struct cpu_user_regs, x4);
+ OFFSET(UREGS_X12, struct cpu_user_regs, x12);
+ OFFSET(UREGS_X16, struct cpu_user_regs, x16);
OFFSET(UREGS_LR, struct cpu_user_regs, lr);
OFFSET(UREGS_SP, struct cpu_user_regs, sp);
@@ -50,6 +56,11 @@ void __dummy__(void)
BLANK();
OFFSET(INITINFO_stack, struct init_info, stack);
+
+#ifdef PERF_COUNTERS
+ BLANK();
+ DEFINE(ASM_PERFC_hypercalls, PERFC_hypercalls);
+#endif
}
/*
diff --git a/xen/arch/arm/arm64/entry.S b/xen/arch/arm/arm64/entry.S
index 93c80ff..5092533 100644
--- a/xen/arch/arm/arm64/entry.S
+++ b/xen/arch/arm/arm64/entry.S
@@ -1,4 +1,5 @@
#include <xen/config.h>
+#include <xen/errno.h>
#include <asm/asm_defns.h>
#include <asm/bug.h>
#include <asm/regs.h>
@@ -174,8 +175,9 @@ hyp_irq:
guest_sync:
entry hyp=0, compat=0
msr daifclr, #2
+ mov x7, x0
mov x0, sp
- bl do_trap_hypervisor
+ bl do_trap_guest_sync
exit hyp=0, compat=0
guest_irq:
@@ -195,8 +197,9 @@ guest_error_invalid:
guest_sync_compat:
entry hyp=0, compat=1
msr daifclr, #2
+ mov x7, x0
mov x0, sp
- bl do_trap_hypervisor
+ bl do_trap_guest_sync
exit hyp=0, compat=1
guest_irq_compat:
@@ -277,6 +280,146 @@ ENTRY(hyp_traps_vector)
ventry guest_fiq_invalid_compat // FIQ 32-bit EL0/EL1
ventry guest_error_invalid_compat // Error 32-bit EL0/EL1
+
+/*
+ * x0/sp - cpu_user_regs
+ * x7 - x0 of the guest (possible arg1 of an hypercall)
+ * x12 - hypercall number for HVC32
+ * x16 - hypercall number for HVC64
+ *
+ * Callee-saved register used within the function for specific purpose:
+ *
+ * x19 - save x30 (lr)
+ * x20 - save the guest pc (only for debug build)
+ * x21 - save the hypercall number
+ * x22 - ESR_EL2.EC
+ *
+ * Note that x1 - x4 shouldn't be clobbered as they contain the
+ * arguments of the hypercall if the guest issued an hypercall.
+ */
+do_trap_guest_sync:
+ mrs x5, ESR_EL2
+ lsr x22, x5, #HSR_EC_SHIFT /* x22 <- ESR.EL2.EC */
+ /* The trap may be an hypercall if EC == HVC32 || HVC64 */
+ cmp x22, #HSR_EC_HVC32
+ beq do_trap_hvc32 /* EC == HVC32 -> HVC call */
+ cmp x22, #HSR_EC_HVC64
+ beq do_trap_hvc /* EC == HVC64 -> HVC call */
+
+ b do_trap_hypervisor /* Not an HVC call -> generic dispatch */
+
+do_trap_hvc32:
+ /*
+ * For HVC32, the hypercall number is in x12, load it in x16
+ * to have the HVC dispatcher common.
+ */
+ mov x16, x12
+
+do_trap_hvc:
+ /*
+ * Only HVC call with ISS == XEN_HYPERCALL_TAG is handled in
+ * assembly, the rest is handled in C by the generic dispatch.
+ */
+ and x6, x5, #HSR_ISS_MASK /* x6 <- ESR_EL2.ISS */
+ cmp x6, #XEN_HYPERCALL_TAG
+ bne do_trap_hypervisor /* Not an hypercall -> generic dispatch */
+
+do_trap_hypercall:
+ /* The guest issued an hypercall */
+
+ /* Check if the hypercall number is valid */
+ cmp x16, #(NR_hypercalls-1)
+ bhi invalid_hypercall /* Hypercall number invalid -> bail out */
+
+ PERFC_INCR(hypercalls, x16)
+
+#ifndef NDEBUG
+ /* Save guest PC to detect hypercall continuation */
+ ldr x20, [sp, #UREGS_PC] /* x20 <- regs->pc */
+#endif
+
+ /*
+ * Call the hypercall dispatcher
+ * The arguments arg2 - arg5 are already in the correct
+ * registers (i.e x1 - x4).
+ */
+ mov x19, lr /* save LR in x19 */
+ mov x21, x16 /* save the hypercall number in x21 */
+ mov x0, x7 /* x0 <- arg1 */
+ mov x5, x16 /* x5 <- Hypercall number */
+ bl do_dispatch_hypercall
+ mov lr, x19 /* Restore LR from x19 */
+
+ str x0, [sp, #UREGS_X0] /* regs->x0 <- do_dispatch_hypercall(...) */
+
+#ifndef NDEBUG
+ /*
+ * Clobber arguments register only if pc is unchanged, otherwise
+ * this is a hypercall continuation.
+ */
+ ldr x0, [sp, #UREGS_PC] /* x0 <- regs->pc */
+ cmp x0, x20 /* Compare regs->pc (x0) with orig_pc (x20) */
+ bne clobber_done /* different => no need to clobber */
+
+ ldr x6, =0xdeadbeefdeadbeef /* x6 <- poison for registers */
+
+ ldr x5, =hypercall_args_table
+ ldr x5, [x5, x21] /* x5 <- number of args */
+ cmp x5, #5; b .Largs5
+ cmp x5, #4; b .Largs4
+ cmp x5, #3; b .Largs3
+ cmp x5, #2; b .Largs2
+ cmp x5, #1; b .Largs1
+ cmp x5, #0; b .Largs0 /* Only for hypercall not implemented */
+ BUG /* Number of arguments invalid */
+.Largs5:
+ ldr x6, [sp, #UREGS_X4]
+.Largs4:
+ ldr x6, [sp, #UREGS_X3]
+.Largs3:
+ ldr x6, [sp, #UREGS_X2]
+.Largs2:
+ ldr x6, [sp, #UREGS_X1]
+.Largs1:
+ /* Don't clobber x0 -- it's the return value */
+ b .Lclobber_nr
+.Largs0:
+ /*
+ * Can only happen when the hypercall is not implemented.
+ * i.e hypercall_table[*nr] == do_ni_hypercall
+ */
+ ldr x6, =hypercall_table
+ ldr x6, [x6, x21, lsl #3] /* x10 := pointer to hypercall function */
+ ldr x5, do_ni_hypercall
+ cmp x5, x6
+ beq .Lclobber_nr /* Hypercall function == do_ni_hypercall => Good */
+ ASSERT_FAILED("hypercall_table[*nr] == do_ni_hypercall")
+
+.Lclobber_nr:
+ /*
+ * Clobber the hypercall number register. The register depends
+ * on HSR.EL2 (stored in x22):
+ * HSR_EC_HVC32 -> x12
+ * HSR_EC_HVC64 -> x16
+ */
+ cmp x22, #HSR_EC_HVC32
+ beq .Lclobber_hvc32
+.Lclobber_hvc64:
+ str x6, [sp, #UREGS_X16]
+ b clobber_done
+.Lclobber_hvc32:
+ str x6, [sp, #UREGS_X12]
+
+clobber_done:
+#endif
+
+ ret
+
+invalid_hypercall:
+ mov x0, #-ENOSYS
+ str x0, [sp, #UREGS_X0] /* regs->x0 <- -ENOSYS */
+ ret
+
/*
* struct vcpu *__context_switch(struct vcpu *prev, struct vcpu *next)
*
diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h
index 7e6eb66..da02599 100644
--- a/xen/include/asm-arm/processor.h
+++ b/xen/include/asm-arm/processor.h
@@ -483,6 +483,9 @@ union hsr {
};
#endif
+#define HSR_EC_SHIFT 26
+#define HSR_ISS_MASK 0x00ffffff
+
/* HSR.EC == HSR_CP{15,14,10}_32 */
#define HSR_CP32_OP2_MASK (0x000e0000)
#define HSR_CP32_OP2_SHIFT (17)
--
2.1.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFC 09/10] xen/arm: Remove the C version of do_trap_hypercall
2015-12-15 17:51 [RFC 00/10] xen/arm: Implement the hypercall handling in assembly Julien Grall
` (7 preceding siblings ...)
2015-12-15 17:52 ` [RFC 08/10] xen/arm64: Implement the hypercall handing fully " Julien Grall
@ 2015-12-15 17:52 ` 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
10 siblings, 0 replies; 13+ messages in thread
From: Julien Grall @ 2015-12-15 17:52 UTC (permalink / raw)
To: xen-devel; +Cc: Julien Grall, ian.campbell, stefano.stabellini
This has been fully implemented in assembly so it's not necessary to
keep it anymore.
Signed-off-by: Julien Grall <julien.grall@citrix.com>
---
It's possible to factorize the code to handle HVC32/HVC64, but this will
be done in the next patch.
---
xen/arch/arm/traps.c | 74 ++++++----------------------------------------------
1 file changed, 8 insertions(+), 66 deletions(-)
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index cc67d23..3cd8992 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -1335,70 +1335,6 @@ static void do_trap_psci(struct cpu_user_regs *regs)
}
}
-#ifdef CONFIG_ARM_64
-#define HYPERCALL_RESULT_REG(r) (r)->x0
-#define HYPERCALL_ARG1(r) (r)->x0
-#define HYPERCALL_ARG2(r) (r)->x1
-#define HYPERCALL_ARG3(r) (r)->x2
-#define HYPERCALL_ARG4(r) (r)->x3
-#define HYPERCALL_ARG5(r) (r)->x4
-#define HYPERCALL_ARGS(r) (r)->x0, (r)->x1, (r)->x2, (r)->x3, (r)->x4
-#else
-#define HYPERCALL_RESULT_REG(r) (r)->r0
-#define HYPERCALL_ARG1(r) (r)->r0
-#define HYPERCALL_ARG2(r) (r)->r1
-#define HYPERCALL_ARG3(r) (r)->r2
-#define HYPERCALL_ARG4(r) (r)->r3
-#define HYPERCALL_ARG5(r) (r)->r4
-#define HYPERCALL_ARGS(r) (r)->r0, (r)->r1, (r)->r2, (r)->r3, (r)->r4
-#endif
-
-static void do_trap_hypercall(struct cpu_user_regs *regs, register_t *nr,
- unsigned long iss)
-{
-#ifndef NDEBUG
- register_t orig_pc = regs->pc;
-#endif
-
- if ( iss != XEN_HYPERCALL_TAG )
- domain_crash_synchronous();
-
- if ( *nr >= NR_hypercalls )
- {
- perfc_incr(invalid_hypercalls);
- HYPERCALL_RESULT_REG(regs) = -ENOSYS;
- return;
- }
-
- perfc_incra(hypercalls, *nr);
-
- HYPERCALL_RESULT_REG(regs) = do_dispatch_hypercall(HYPERCALL_ARGS(regs),
- *nr);
-
-#ifndef NDEBUG
- /*
- * Clobber argument registers only if pc is unchanged, otherwise
- * this is a hypercall continuation.
- */
- if ( orig_pc == regs->pc )
- {
- 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;
- }
-#endif
-}
-
static bool_t check_multicall_32bit_clean(struct multicall_entry *multi)
{
int i;
@@ -2476,7 +2412,10 @@ asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
#endif
if ( hsr.iss == 0 )
return do_trap_psci(regs);
- do_trap_hypercall(regs, (register_t *)®s->r12, hsr.iss);
+
+ /* The ISS is not supported */
+ domain_crash_synchronous();
+
break;
#ifdef CONFIG_ARM_64
case HSR_EC_HVC64:
@@ -2488,7 +2427,10 @@ asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
#endif
if ( hsr.iss == 0 )
return do_trap_psci(regs);
- do_trap_hypercall(regs, ®s->x16, hsr.iss);
+
+ /* The ISS is not supported */
+ domain_crash_synchronous();
+
break;
case HSR_EC_SMC64:
/*
--
2.1.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFC 10/10] xen/arm: Factorize the C code to dispatch HVC
2015-12-15 17:51 [RFC 00/10] xen/arm: Implement the hypercall handling in assembly Julien Grall
` (8 preceding siblings ...)
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 ` Julien Grall
2015-12-15 18:33 ` [RFC 00/10] xen/arm: Implement the hypercall handling in assembly Andrew Cooper
10 siblings, 0 replies; 13+ messages in thread
From: Julien Grall @ 2015-12-15 17:52 UTC (permalink / raw)
To: xen-devel; +Cc: Julien Grall, ian.campbell, stefano.stabellini
Now that Xen hypercall is fully dispatched in assembly, the code to
handle HVC32/HVC64 is mostly the same.
Create an helper to avoid duplicating the code.
Signed-off-by: Julien Grall <julien.grall@citrix.com>
---
xen/arch/arm/traps.c | 36 ++++++++++++++++--------------------
1 file changed, 16 insertions(+), 20 deletions(-)
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 3cd8992..a49530a 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -1335,6 +1335,20 @@ static void do_trap_psci(struct cpu_user_regs *regs)
}
}
+static void do_trap_hvc(struct cpu_user_regs *regs, uint32_t iss)
+{
+
+#ifndef NDEBUG
+ if ( (iss & 0xff00) == 0xff00 )
+ return do_debug_trap(regs, iss & 0x00ff);
+#endif
+ if ( iss == 0 )
+ return do_trap_psci(regs);
+
+ /* The ISS is not supported */
+ domain_crash_synchronous();
+}
+
static bool_t check_multicall_32bit_clean(struct multicall_entry *multi)
{
int i;
@@ -2406,31 +2420,13 @@ asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
case HSR_EC_HVC32:
GUEST_BUG_ON(!psr_mode_is_32bit(regs->cpsr));
perfc_incr(trap_hvc32);
-#ifndef NDEBUG
- if ( (hsr.iss & 0xff00) == 0xff00 )
- return do_debug_trap(regs, hsr.iss & 0x00ff);
-#endif
- if ( hsr.iss == 0 )
- return do_trap_psci(regs);
-
- /* The ISS is not supported */
- domain_crash_synchronous();
-
+ do_trap_hvc(regs, hsr.iss);
break;
#ifdef CONFIG_ARM_64
case HSR_EC_HVC64:
GUEST_BUG_ON(psr_mode_is_32bit(regs->cpsr));
perfc_incr(trap_hvc64);
-#ifndef NDEBUG
- if ( (hsr.iss & 0xff00) == 0xff00 )
- return do_debug_trap(regs, hsr.iss & 0x00ff);
-#endif
- if ( hsr.iss == 0 )
- return do_trap_psci(regs);
-
- /* The ISS is not supported */
- domain_crash_synchronous();
-
+ do_trap_hvc(regs, hsr.iss);
break;
case HSR_EC_SMC64:
/*
--
2.1.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [RFC 00/10] xen/arm: Implement the hypercall handling in assembly
2015-12-15 17:51 [RFC 00/10] xen/arm: Implement the hypercall handling in assembly Julien Grall
` (9 preceding siblings ...)
2015-12-15 17:52 ` [RFC 10/10] xen/arm: Factorize the C code to dispatch HVC Julien Grall
@ 2015-12-15 18:33 ` Andrew Cooper
2015-12-16 11:19 ` Ian Campbell
10 siblings, 1 reply; 13+ messages in thread
From: Andrew Cooper @ 2015-12-15 18:33 UTC (permalink / raw)
To: Julien Grall, xen-devel; +Cc: ian.campbell, stefano.stabellini
On 15/12/15 17:51, Julien Grall wrote:
> Hi all,
>
> This patch aims is a first attempt to write the hypercall dispatch in assembly
> in order to avoid reloading the hypercall arguments from the stack.
Why? A couple of stack operations are in the noise, performance wise.
I have half a patch series to do exactly the opposite for x86 PV guests,
as C is far more maintainable than asm.
~Andrew
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFC 00/10] xen/arm: Implement the hypercall handling in assembly
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
0 siblings, 0 replies; 13+ messages in thread
From: Ian Campbell @ 2015-12-16 11:19 UTC (permalink / raw)
To: Andrew Cooper, Julien Grall, xen-devel; +Cc: stefano.stabellini
On Tue, 2015-12-15 at 18:33 +0000, Andrew Cooper wrote:
> On 15/12/15 17:51, Julien Grall wrote:
> > Hi all,
> >
> > This patch aims is a first attempt to write the hypercall dispatch in
> > assembly
> > in order to avoid reloading the hypercall arguments from the stack.
>
> Why? A couple of stack operations are in the noise, performance wise.
At least on ARM It's quite a bit more than a couple (dozens but not
hundreds I would say, and I've not looked at the patch yet to see how much
it saves out of those), but clearly it would need to be measured at some
point before taking it too much further than an RFC.
There's a second issue which is that the current C dispatch table approach
which uses a common typedef is not strictly speaking valid C, since it is
undefined behaviour to call a function through a typedef which has a
different prototype (Ian J can probably explain it better than I, with
chapter and verse etc).
Ian.
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2015-12-16 11:20 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [RFC 07/10] xen/arm: Implement the code to dispatch the hypercall in assembly Julien Grall
2015-12-15 17:52 ` [RFC 08/10] xen/arm64: Implement the hypercall handing fully " 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
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.