arm64: hyp/kvm: Make hyp-stub extensible
authorGeoff Levand <geoff@infradead.org>
Wed, 27 Apr 2016 16:47:03 +0000 (17:47 +0100)
committerAlex Shi <alex.shi@linaro.org>
Thu, 17 Nov 2016 01:49:37 +0000 (09:49 +0800)
The existing arm64 hcall implementations are limited in that they only
allow for two distinct hcalls; with the x0 register either zero or not
zero.  Also, the API of the hyp-stub exception vector routines and the
KVM exception vector routines differ; hyp-stub uses a non-zero value in
x0 to implement __hyp_set_vectors, whereas KVM uses it to implement
kvm_call_hyp.

To allow for additional hcalls to be defined and to make the arm64 hcall
API more consistent across exception vector routines, change the hcall
implementations to reserve all x0 values below 0xfff for hcalls such
as {s,g}et_vectors().

Define two new preprocessor macros HVC_GET_VECTORS, and HVC_SET_VECTORS
to be used as hcall type specifiers and convert the existing
__hyp_get_vectors() and __hyp_set_vectors() routines to use these new
macros when executing an HVC call.  Also, change the corresponding
hyp-stub and KVM el1_sync exception vector routines to use these new
macros.

Signed-off-by: Geoff Levand <geoff@infradead.org>
[Merged two hcall patches, moved immediate value from esr to x0, use lr
 as a scratch register, changed limit to 0xfff]
Signed-off-by: James Morse <james.morse@arm.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
(cherry picked from commit ad72e59ff2bad55f6b9e7ac1fe5d824831ea2550)
Signed-off-by: Alex Shi <alex.shi@linaro.org>
arch/arm64/include/asm/virt.h
arch/arm64/kernel/hyp-stub.S
arch/arm64/kvm/hyp.S
arch/arm64/kvm/hyp/hyp-entry.S

index 9f22dd607958ad7cd673e79e91c36e28768c35f7..06e6a5238c4c47b41a9567cf7c004c7dae78b888 100644 (file)
 #ifndef __ASM__VIRT_H
 #define __ASM__VIRT_H
 
+/*
+ * The arm64 hcall implementation uses x0 to specify the hcall type. A value
+ * less than 0xfff indicates a special hcall, such as get/set vector.
+ * Any other value is used as a pointer to the function to call.
+ */
+
+/* HVC_GET_VECTORS - Return the value of the vbar_el2 register. */
+#define HVC_GET_VECTORS 0
+
+/*
+ * HVC_SET_VECTORS - Set the value of the vbar_el2 register.
+ *
+ * @x1: Physical address of the new vector table.
+ */
+#define HVC_SET_VECTORS 1
+
 #define BOOT_CPU_MODE_EL1      (0xe11)
 #define BOOT_CPU_MODE_EL2      (0xe12)
 
index 7eab8acbbbd9fa099a6d562652f83e8965fa6a72..894fb40fb378b5fcd79f66597a4bfe6c5eeff911 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/irqchip/arm-gic-v3.h>
 
 #include <asm/assembler.h>
+#include <asm/kvm_arm.h>
 #include <asm/ptrace.h>
 #include <asm/virt.h>
 
@@ -53,15 +54,26 @@ ENDPROC(__hyp_stub_vectors)
        .align 11
 
 el1_sync:
-       mrs     x1, esr_el2
-       lsr     x1, x1, #26
-       cmp     x1, #0x16
-       b.ne    2f                              // Not an HVC trap
-       cbz     x0, 1f
-       msr     vbar_el2, x0                    // Set vbar_el2
-       b       2f
-1:     mrs     x0, vbar_el2                    // Return vbar_el2
-2:     eret
+       mrs     x30, esr_el2
+       lsr     x30, x30, #ESR_ELx_EC_SHIFT
+
+       cmp     x30, #ESR_ELx_EC_HVC64
+       b.ne    9f                              // Not an HVC trap
+
+       cmp     x0, #HVC_GET_VECTORS
+       b.ne    1f
+       mrs     x0, vbar_el2
+       b       9f
+
+1:     cmp     x0, #HVC_SET_VECTORS
+       b.ne    2f
+       msr     vbar_el2, x1
+       b       9f
+
+       /* Unrecognised call type */
+2:     mov     x0, xzr
+
+9:     eret
 ENDPROC(el1_sync)
 
 .macro invalid_vector  label
@@ -102,7 +114,7 @@ ENDPROC(\label)
 
 ENTRY(__hyp_get_vectors)
        str     lr, [sp, #-16]!
-       mov     x0, xzr
+       mov     x0, #HVC_GET_VECTORS
        hvc     #0
        ldr     lr, [sp], #16
        ret
@@ -110,6 +122,8 @@ ENDPROC(__hyp_get_vectors)
 
 ENTRY(__hyp_set_vectors)
        str     lr, [sp, #-16]!
+       mov     x1, x0
+       mov     x0, #HVC_SET_VECTORS
        hvc     #0
        ldr     lr, [sp], #16
        ret
index 4ee5612f43ea5985372dcf75e357a7e24b3c820a..7ce9315651518cf88e47d4a08670b9088bfbcfa1 100644 (file)
@@ -35,8 +35,8 @@
  * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c).  Return values are
  * passed in x0.
  *
- * A function pointer with a value of 0 has a special meaning, and is
- * used to implement __hyp_get_vectors in the same way as in
+ * A function pointer with a value less than 0xfff has a special meaning,
+ * and is used to implement __hyp_get_vectors in the same way as in
  * arch/arm64/kernel/hyp_stub.S.
  * HVC behaves as a 'bl' call and will clobber lr.
  */
index ca8a8ea6960852c04461577825ce0bbd111ce4e1..44c79fd81ad1c3a5ffc71c445d89dea50a5d5ae9 100644 (file)
@@ -79,8 +79,8 @@ el1_sync:                             // Guest trapped into EL2
        /* Here, we're pretty sure the host called HVC. */
        restore_x0_to_x3
 
-       /* Check for __hyp_get_vectors */
-       cbnz    x0, 1f
+       cmp     x0, #HVC_GET_VECTORS
+       b.ne    1f
        mrs     x0, vbar_el2
        b       2f