@@ -18,6 +18,33 @@
#ifndef __ASM__VIRT_H
#define __ASM__VIRT_H
+/*
+ * The arm64 hcall implementation uses the ISS field of the ESR_EL2 register to
+ * specify the hcall type. The exception handlers are allowed to use registers
+ * x17 and x18 in their implementation. Any routine issuing an hcall must not
+ * expect these registers to be preserved.
+ */
+
+/*
+ * HVC_CALL_HYP - Execute a hyp routine.
+ */
+
+#define HVC_CALL_HYP 0
+
+/*
+ * HVC_GET_VECTORS - Return the value of the vbar_el2 register.
+ */
+
+#define HVC_GET_VECTORS 1
+
+/*
+ * HVC_SET_VECTORS - Set the value of the vbar_el2 register.
+ *
+ * @x0: Physical address of the new vector table.
+ */
+
+#define HVC_SET_VECTORS 2
+
#define BOOT_CPU_MODE_EL1 (0xe11)
#define BOOT_CPU_MODE_EL2 (0xe12)
@@ -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,14 +54,22 @@ ENDPROC(__hyp_stub_vectors)
.align 11
el1_sync:
- mrs x1, esr_el2
- lsr x1, x1, #26
- cmp x1, #0x16
+ mrs x18, esr_el2
+ lsr x17, x18, #ESR_ELx_EC_SHIFT
+ and x18, x18, #ESR_ELx_ISS_MASK
+
+ cmp x17, #ESR_ELx_EC_HVC64
b.ne 2f // Not an HVC trap
- cbz x0, 1f
- msr vbar_el2, x0 // Set vbar_el2
+
+ cmp x18, #HVC_GET_VECTORS
+ b.ne 1f
+ mrs x0, vbar_el2
b 2f
-1: mrs x0, vbar_el2 // Return vbar_el2
+
+1: cmp x18, #HVC_SET_VECTORS
+ b.ne 2f
+ msr vbar_el2, x0
+
2: eret
ENDPROC(el1_sync)
@@ -100,11 +109,12 @@ ENDPROC(\label)
* initialisation entry point.
*/
-ENTRY(__hyp_get_vectors)
- mov x0, xzr
- // fall through
ENTRY(__hyp_set_vectors)
- hvc #0
+ hvc #HVC_SET_VECTORS
ret
-ENDPROC(__hyp_get_vectors)
ENDPROC(__hyp_set_vectors)
+
+ENTRY(__hyp_get_vectors)
+ hvc #HVC_GET_VECTORS
+ ret
+ENDPROC(__hyp_get_vectors)
@@ -18,6 +18,7 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
+#include <asm/virt.h>
/*
* u64 __kvm_call_hyp(void *hypfn, ...);
@@ -38,6 +39,6 @@
* arch/arm64/kernel/hyp_stub.S.
*/
ENTRY(__kvm_call_hyp)
- hvc #0
+ hvc #HVC_CALL_HYP
ret
ENDPROC(__kvm_call_hyp)
@@ -43,6 +43,7 @@ el1_sync: // Guest trapped into EL2
mrs x1, esr_el2
lsr x2, x1, #ESR_ELx_EC_SHIFT
+ and x0, x1, #ESR_ELx_ISS_MASK
cmp x2, #ESR_ELx_EC_HVC64
b.ne el1_trap
@@ -51,14 +52,16 @@ el1_sync: // Guest trapped into EL2
cbnz x3, el1_trap // called HVC
/* Here, we're pretty sure the host called HVC. */
+ mov x18, x0
restore_x0_to_x3
- /* Check for __hyp_get_vectors */
- cbnz x0, 1f
+ cmp x18, #HVC_GET_VECTORS
+ b.ne 1f
mrs x0, vbar_el2
b 2f
-1: stp lr, xzr, [sp, #-16]!
+1: /* Default to HVC_CALL_HYP. */
+ push lr, xzr
/*
* Compute the function address in EL2, and shuffle the parameters.