Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm64: hyp/kvm: Make hyp-stub extensible

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>

authored by

Geoff Levand and committed by
Will Deacon
ad72e59f 00a44cda

+44 -14
+16
arch/arm64/include/asm/virt.h
··· 18 18 #ifndef __ASM__VIRT_H 19 19 #define __ASM__VIRT_H 20 20 21 + /* 22 + * The arm64 hcall implementation uses x0 to specify the hcall type. A value 23 + * less than 0xfff indicates a special hcall, such as get/set vector. 24 + * Any other value is used as a pointer to the function to call. 25 + */ 26 + 27 + /* HVC_GET_VECTORS - Return the value of the vbar_el2 register. */ 28 + #define HVC_GET_VECTORS 0 29 + 30 + /* 31 + * HVC_SET_VECTORS - Set the value of the vbar_el2 register. 32 + * 33 + * @x1: Physical address of the new vector table. 34 + */ 35 + #define HVC_SET_VECTORS 1 36 + 21 37 #define BOOT_CPU_MODE_EL1 (0xe11) 22 38 #define BOOT_CPU_MODE_EL2 (0xe12) 23 39
+24 -10
arch/arm64/kernel/hyp-stub.S
··· 22 22 #include <linux/irqchip/arm-gic-v3.h> 23 23 24 24 #include <asm/assembler.h> 25 + #include <asm/kvm_arm.h> 25 26 #include <asm/ptrace.h> 26 27 #include <asm/virt.h> 27 28 ··· 54 53 .align 11 55 54 56 55 el1_sync: 57 - mrs x1, esr_el2 58 - lsr x1, x1, #26 59 - cmp x1, #0x16 60 - b.ne 2f // Not an HVC trap 61 - cbz x0, 1f 62 - msr vbar_el2, x0 // Set vbar_el2 63 - b 2f 64 - 1: mrs x0, vbar_el2 // Return vbar_el2 65 - 2: eret 56 + mrs x30, esr_el2 57 + lsr x30, x30, #ESR_ELx_EC_SHIFT 58 + 59 + cmp x30, #ESR_ELx_EC_HVC64 60 + b.ne 9f // Not an HVC trap 61 + 62 + cmp x0, #HVC_GET_VECTORS 63 + b.ne 1f 64 + mrs x0, vbar_el2 65 + b 9f 66 + 67 + 1: cmp x0, #HVC_SET_VECTORS 68 + b.ne 2f 69 + msr vbar_el2, x1 70 + b 9f 71 + 72 + /* Unrecognised call type */ 73 + 2: mov x0, xzr 74 + 75 + 9: eret 66 76 ENDPROC(el1_sync) 67 77 68 78 .macro invalid_vector label ··· 114 102 115 103 ENTRY(__hyp_get_vectors) 116 104 str lr, [sp, #-16]! 117 - mov x0, xzr 105 + mov x0, #HVC_GET_VECTORS 118 106 hvc #0 119 107 ldr lr, [sp], #16 120 108 ret ··· 122 110 123 111 ENTRY(__hyp_set_vectors) 124 112 str lr, [sp, #-16]! 113 + mov x1, x0 114 + mov x0, #HVC_SET_VECTORS 125 115 hvc #0 126 116 ldr lr, [sp], #16 127 117 ret
+2 -2
arch/arm64/kvm/hyp.S
··· 35 35 * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c). Return values are 36 36 * passed in x0. 37 37 * 38 - * A function pointer with a value of 0 has a special meaning, and is 39 - * used to implement __hyp_get_vectors in the same way as in 38 + * A function pointer with a value less than 0xfff has a special meaning, 39 + * and is used to implement __hyp_get_vectors in the same way as in 40 40 * arch/arm64/kernel/hyp_stub.S. 41 41 * HVC behaves as a 'bl' call and will clobber lr. 42 42 */
+2 -2
arch/arm64/kvm/hyp/hyp-entry.S
··· 82 82 /* Here, we're pretty sure the host called HVC. */ 83 83 restore_x0_to_x3 84 84 85 - /* Check for __hyp_get_vectors */ 86 - cbnz x0, 1f 85 + cmp x0, #HVC_GET_VECTORS 86 + b.ne 1f 87 87 mrs x0, vbar_el2 88 88 b 2f 89 89