KVM/arm64: Add NV support for ERET and PAuth
Marc Zyngier
maintainercover KVM/arm64: Add NV support for ERET and PAuth
Although the current upstream NV support has *some* support for correctly emulating ERET, that support is only partial as it doesn't support the ERETAA and ERETAB variants.
Supporting these instructions was cast aside for a long time as it involves implementing some form of PAuth emulation, something I wasn't overly keen on. But I have reached a point where enough of the infrastructure is there that it actually makes sense. So here it is!
This series completely relies on my previous VM configuration enforcement series, as it expects all shadow registers to be sanitised and to match the VM configuration.
The first 3 patches are only opportunistic cleanups and hardening.
Patch #4 adds the configuration of HCR_EL2 in the NV2 case, together with VNCR_EL2 being populated.
Patches #5, #7 and #8 add more triage and trap forwarding on the instruction side (SMC, ERET, PAC)
Patch #6 split the current ERET handling into a fixup which runs early on exit, and the core part, which is only used when a translation regime transition or an exception injection needs to take place.
The rest of the series finally adds the PAuth emulation for ERETA[AB] (and only for these two instructions), plugs it into the ERET handling, and finally advertises PAuth to the L1 guest.
Marc Zyngier (13):
KVM: arm64: Harden __ctxt_sys_reg() against out-of-range values
KVM: arm64: Clarify ESR_ELx_ERET_ISS_ERET*
KVM: arm64: nv: Drop VCPU_HYP_CONTEXT flag
KVM: arm64: nv: Configure HCR_EL2 for FEAT_NV2
KVM: arm64: nv: Add trap forwarding for ERET and SMC
KVM: arm64: nv: Fast-track 'InHost' exception returns
KVM: arm64: nv: Honor HFGITR_EL2.ERET being set
KVM: arm64: nv: Handle HCR_EL2.{API,APK} independantly
KVM: arm64: nv: Reinject PAC exceptions caused by HCR_EL2.API==0
KVM: arm64: nv: Add kvm_has_pauth() helper
KVM: arm64: nv: Add emulation for ERETAx instructions
KVM: arm64: nv: Handle ERETA[AB] instructions
KVM: arm64: nv: Advertise support for PAuth
arch/arm64/include/asm/esr.h | 4 +- arch/arm64/include/asm/kvm_emulate.h | 5 - arch/arm64/include/asm/kvm_host.h | 26 +++- arch/arm64/include/asm/kvm_nested.h | 13 ++ arch/arm64/include/asm/pgtable-hwdef.h | 1 + arch/arm64/include/asm/sysreg.h | 1 + arch/arm64/kvm/Makefile | 1 + arch/arm64/kvm/emulate-nested.c | 66 +++++--- arch/arm64/kvm/handle_exit.c | 38 ++++- arch/arm64/kvm/hyp/include/hyp/switch.h | 36 ++++- arch/arm64/kvm/hyp/nvhe/switch.c | 2 +- arch/arm64/kvm/hyp/vhe/switch.c | 95 +++++++++++- arch/arm64/kvm/nested.c | 8 +- arch/arm64/kvm/pauth.c | 196 ++++++++++++++++++++++++ 14 files changed, 434 insertions(+), 58 deletions(-) create mode 100644 arch/arm64/kvm/pauth.c
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH 1/13 KVM: arm64: Harden __ctxt_sys_reg() against out-of-range values
The unsuspecting kernel tinkerer can be easily confused into writing something that looks like this:
ikey.lo = __vcpu_sys_reg(vcpu, SYS_APIAKEYLO_EL1);
which seems vaguely sensible, until you realise that the second parameter is the encoding of a sysreg, and not the index into the vcpu sysreg file... Debugging what happens in this case is an interesting exercise in head<->wall interactions.
As they often say: "Any resemblance to actual persons, living or dead, or actual events is purely coincidental".
In order to save people's time, add some compile-time hardening that will at least weed out the "stupidly out of range" values. This will *not* catch anything that isn't a compile-time constant.
--- arch/arm64/include/asm/kvm_host.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
arch/arm64/include/asm/kvm_host.h +8 -1
@@ -895,7 +895,7 @@ struct kvm_vcpu_arch {* Don't bother with VNCR-based accesses in the nVHE code, it has no * business dealing with NV. */ -static inline u64 *__ctxt_sys_reg (const struct kvm_cpu_context *ctxt,int r) +static inline u64 *___ctxt_sys_reg (const struct kvm_cpu_context *ctxt,int r) {#if !defined (__KVM_NVHE_HYPERVISOR__) if (unlikely(cpus_have_final_cap(ARM64_HAS_NESTED_VIRT) &&
@@ -905,6 +905,13 @@ static inline u64 *__ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r)return (u64 *)&ctxt->sys_regs[r]; } +#define __ctxt_sys_reg (c,r) \ + ({ \ + BUILD_BUG_ON(__builtin_constant_p(r) && \ + (r) >= NR_SYS_REGS); \ + ___ctxt_sys_reg(c, r); \ + }) +#define ctxt_sys_reg (c,r) (*__ctxt_sys_reg(c,r))u64 kvm_vcpu_sanitise_vncr_reg (const struct kvm_vcpu *,enum vcpu_sysreg );
Signature · 1 line
2.39.2
Joey Gouly
reviewerRe: [PATCH 01/13] KVM: arm64: Harden __ctxt_sys_reg() against out-of-range values
Quoted 8 lines · Marc Zyngier
The unsuspecting kernel tinkerer can be easily confused into writing something that looks like this:
ikey.lo = __vcpu_sys_reg(vcpu, SYS_APIAKEYLO_EL1);which seems vaguely sensible, until you realise that the second parameter is the encoding of a sysreg, and not the index into the vcpu sysreg file... Debugging what happens in this case is
type safety :(
Quoted 19 lines
an interesting exercise in head<->wall interactions.
As they often say: "Any resemblance to actual persons, living or dead, or actual events is purely coincidental".
In order to save people's time, add some compile-time hardening that will at least weed out the "stupidly out of range" values. This will *not* catch anything that isn't a compile-time constant.
Signed-off-by Marc Zyngier <[email protected]>--- arch/arm64/include/asm/kvm_host.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)arch/arm64/include/asm/kvm_host.h +0
-0
arch/arm64/include/asm/kvm_host.h struct kvm_vcpu_arch { · line 898
Quoted 5 lines
arch/arm64/include/asm/kvm_host.h +1
-1@@ -895,7 +895,7 @@ struct kvm_vcpu_arch {* Don't bother with VNCR-based accesses in the nVHE code, it has no * business dealing with NV. */ -static inline u64 *__ctxt_sys_reg (const struct kvm_cpu_context *ctxt,int r) +static inline u64 *___ctxt_sys_reg (const struct kvm_cpu_context *ctxt,int r)
When in doubt, add more underscores!
arch/arm64/include/asm/kvm_host.h static inline u64 *__ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r) · line 913
Quoted 13 lines
arch/arm64/include/asm/kvm_host.h +6
-0{#if !defined (__KVM_NVHE_HYPERVISOR__) if (unlikely(cpus_have_final_cap(ARM64_HAS_NESTED_VIRT) &&@@ -905,6 +905,13 @@ static inline u64 *__ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r)return (u64 *)&ctxt->sys_regs[r]; } +#define __ctxt_sys_reg (c,r) \ + ({ \ + BUILD_BUG_ON(__builtin_constant_p(r) && \ + (r) >= NR_SYS_REGS); \ + ___ctxt_sys_reg(c, r); \ + })
I'm assuming the extra macro layer is to try make __builtin_constant_p() as effective as possible? Otherwise maybe it relies on the compiler inling the ___ctxt_sys_reg() function?
arch/arm64/include/asm/kvm_host.h static inline u64 *__ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r) · line 917
Quoted 4 lines
arch/arm64/include/asm/kvm_host.h +1
-0+#define ctxt_sys_reg (c,r) (*__ctxt_sys_reg(c,r))u64 kvm_vcpu_sanitise_vncr_reg (const struct kvm_vcpu *,enum vcpu_sysreg );
Thanks,
Joey
Marc Zyngier
maintainerRe: [PATCH 01/13] KVM: arm64: Harden __ctxt_sys_reg() against out-of-range values
Quoted 5 lines · Joey Gouly
Quoted 3 lines · Marc Zyngier
The unsuspecting kernel tinkerer can be easily confused into writing something that looks like this:
Quoted 7 lines
Quoted 5 lines
ikey.lo = __vcpu_sys_reg(vcpu, SYS_APIAKEYLO_EL1);which seems vaguely sensible, until you realise that the second parameter is the encoding of a sysreg, and not the index into the vcpu sysreg file... Debugging what happens in this case is
type safety :(
Are you advocating for making everything a struct? Or something else?
Quoted 15 lines
Quoted 15 lines
an interesting exercise in head<->wall interactions.
As they often say: "Any resemblance to actual persons, living or dead, or actual events is purely coincidental".
In order to save people's time, add some compile-time hardening that will at least weed out the "stupidly out of range" values. This will *not* catch anything that isn't a compile-time constant.
Signed-off-by Marc Zyngier <[email protected]>--- arch/arm64/include/asm/kvm_host.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
Quoted 12 lines
arch/arm64/include/asm/kvm_host.h struct kvm_vcpu_arch { · line 898
Quoted 10 lines
arch/arm64/include/asm/kvm_host.h +1
-1@@ -895,7 +895,7 @@ struct kvm_vcpu_arch {* Don't bother with VNCR-based accesses in the nVHE code, it has no * business dealing with NV. */ -static inline u64 *__ctxt_sys_reg (const struct kvm_cpu_context *ctxt,int r) +static inline u64 *___ctxt_sys_reg (const struct kvm_cpu_context *ctxt,int r)When in doubt, add more underscores!
That's the one true way.
Quoted 8 lines
Quoted 8 lines
arch/arm64/include/asm/kvm_host.h +0
-0{#if !defined (__KVM_NVHE_HYPERVISOR__) if (unlikely(cpus_have_final_cap(ARM64_HAS_NESTED_VIRT) &&@@ -905,6 +905,13 @@ static inline u64 *__ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r)return (u64 *)&ctxt->sys_regs[r]; }
Quoted 10 lines
arch/arm64/include/asm/kvm_host.h static inline u64 *__ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r) · line 913
Quoted 6 lines
arch/arm64/include/asm/kvm_host.h +6
-0+#define __ctxt_sys_reg (c,r) \ + ({ \ + BUILD_BUG_ON(__builtin_constant_p(r) && \ + (r) >= NR_SYS_REGS); \ + ___ctxt_sys_reg(c, r); \ + })I'm assuming the extra macro layer is to try make
__builtin_constant_p()as effective as possible? Otherwise maybe it relies on the compiler inling the___ctxt_sys_reg()function?
It's not about efficiency. It's about making it *work*. Otherwise, lack of inlining will screw you over, and you may not check anything.
Thanks,
M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
Re: [PATCH 01/13] KVM: arm64: Harden __ctxt_sys_reg() against out-of-range values
Quoted 9 lines · Marc Zyngier
Quoted 7 lines · Joey Gouly
Quoted 5 lines · Marc Zyngier
The unsuspecting kernel tinkerer can be easily confused into writing something that looks like this:
ikey.lo = __vcpu_sys_reg(vcpu, SYS_APIAKEYLO_EL1);
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
which seems vaguely sensible, until you realise that the second parameter is the encoding of a sysreg, and not the index into the vcpu sysreg file... Debugging what happens in this case is
type safety :(
Are you advocating for making everything a struct? Or something else?
No, merely lamenting the situation.
Quoted 50 lines
Quoted 16 lines
Quoted 16 lines
an interesting exercise in head<->wall interactions.
As they often say: "Any resemblance to actual persons, living or dead, or actual events is purely coincidental".
In order to save people's time, add some compile-time hardening that will at least weed out the "stupidly out of range" values. This will *not* catch anything that isn't a compile-time constant.
Signed-off-by Marc Zyngier <[email protected]>--- arch/arm64/include/asm/kvm_host.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)Quoted 12 lines
arch/arm64/include/asm/kvm_host.h struct kvm_vcpu_arch { · line 898
Quoted 10 lines
arch/arm64/include/asm/kvm_host.h +1
-1@@ -895,7 +895,7 @@ struct kvm_vcpu_arch {* Don't bother with VNCR-based accesses in the nVHE code, it has no * business dealing with NV. */ -static inline u64 *__ctxt_sys_reg (const struct kvm_cpu_context *ctxt,int r) +static inline u64 *___ctxt_sys_reg (const struct kvm_cpu_context *ctxt,int r)When in doubt, add more underscores!
That's the one true way.
Quoted 8 lines
Quoted 8 lines
arch/arm64/include/asm/kvm_host.h +0
-0{#if !defined (__KVM_NVHE_HYPERVISOR__) if (unlikely(cpus_have_final_cap(ARM64_HAS_NESTED_VIRT) &&@@ -905,6 +905,13 @@ static inline u64 *__ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r)return (u64 *)&ctxt->sys_regs[r]; }Quoted 10 lines
arch/arm64/include/asm/kvm_host.h static inline u64 *__ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r) · line 913
Quoted 6 lines
arch/arm64/include/asm/kvm_host.h +6
-0+#define __ctxt_sys_reg (c,r) \ + ({ \ + BUILD_BUG_ON(__builtin_constant_p(r) && \ + (r) >= NR_SYS_REGS); \ + ___ctxt_sys_reg(c, r); \ + })I'm assuming the extra macro layer is to try make
__builtin_constant_p()as effective as possible? Otherwise maybe it relies on the compiler inling the___ctxt_sys_reg()function?
Quoted 2 lines
It's not about efficiency. It's about making it *work*. Otherwise, lack of inlining will screw you over, and you may not check anything.
Thanks,
Joey
Marc Zyngier
maintainerPATCH 2/13 KVM: arm64: Clarify ESR_ELx_ERET_ISS_ERET*
In reply to Marc ZyngierThe ESR_ELx_ERET_ISS_ERET* macros are a bit confusing:
- ESR_ELx_ERET_ISS_ERET really indicates that we have trapped an ERETA* instruction, as opposed to an ERET
- ESR_ELx_ERET_ISS_ERETA reallu indicates that we have trapped an ERETAB instruction, as opposed to an ERETAA.
Repaint the two helpers such as:
- ESR_ELx_ERET_ISS_ERET becomes ESR_ELx_ERET_ISS_ERETA
- ESR_ELx_ERET_ISS_ERETA becomes ESR_ELx_ERET_ISS_ERETAB
At the same time, use BIT() instead of raw values.
--- arch/arm64/include/asm/esr.h | 4 ++-- arch/arm64/kvm/handle_exit.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
arch/arm64/include/asm/esr.h +2 -2
@@ -290,8 +290,8 @@ ESR_ELx_SYS64_ISS_OP2_SHIFT))/* ISS field definitions for ERET/ERETAA/ERETAB trapping */ -#define ESR_ELx_ERET_ISS_ERET 0x2 -#define ESR_ELx_ERET_ISS_ERETA 0x1 +#define ESR_ELx_ERET_ISS_ERETA BIT(1) +#define ESR_ELx_ERET_ISS_ERETAB BIT(0)/* * ISS field definitions for floating-point exception traps
arch/arm64/kvm/handle_exit.c +1 -1
@@ -219,7 +219,7 @@ static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu)static int kvm_handle_eret (struct kvm_vcpu *vcpu) { -if (kvm_vcpu_get_esr (vcpu) & ESR_ELx_ERET_ISS_ERET) +if (kvm_vcpu_get_esr (vcpu) & ESR_ELx_ERET_ISS_ERETA)return kvm_handle_ptrauth (vcpu);/*
Signature · 1 line
2.39.2
Joey Gouly
reviewerRe: [PATCH 02/13] KVM: arm64: Clarify ESR_ELx_ERET_ISS_ERET*
Quoted 10 lines · Marc Zyngier
The ESR_ELx_ERET_ISS_ERET* macros are a bit confusing:
-
ESR_ELx_ERET_ISS_ERETreally indicates that we have trapped an ERETA* instruction, as opposed to an ERET-
ESR_ELx_ERET_ISS_ERETAreallu indicates that we have trapped an ERETAB instruction, as opposed to an ERETAA.Repaint the two helpers such as:
Quoted 7 lines
-
ESR_ELx_ERET_ISS_ERETbecomesESR_ELx_ERET_ISS_ERETA-
ESR_ELx_ERET_ISS_ERETAbecomesESR_ELx_ERET_ISS_ERETABAt the same time, use
BIT()instead of raw values.Signed-off-by Marc Zyngier <[email protected]>
I'm somewhat against this, as the original names are what the Arm ARM specifies.
Quoted 25 lines
--- arch/arm64/include/asm/esr.h | 4 ++-- arch/arm64/kvm/handle_exit.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)arch/arm64/include/asm/esr.h +2
-2@@ -290,8 +290,8 @@ ESR_ELx_SYS64_ISS_OP2_SHIFT))/* ISS field definitions for ERET/ERETAA/ERETAB trapping */ -#define ESR_ELx_ERET_ISS_ERET 0x2 -#define ESR_ELx_ERET_ISS_ERETA 0x1 +#define ESR_ELx_ERET_ISS_ERETA BIT(1) +#define ESR_ELx_ERET_ISS_ERETAB BIT(0)/* * ISS field definitions for floating-point exception traps arch/arm64/kvm/handle_exit.c +0
-0
arch/arm64/kvm/handle_exit.c static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu) · line 222
Quoted 5 lines
arch/arm64/kvm/handle_exit.c +1
-1@@ -219,7 +219,7 @@ static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu)static int kvm_handle_eret (struct kvm_vcpu *vcpu) { -if (kvm_vcpu_get_esr (vcpu) & ESR_ELx_ERET_ISS_ERET) +if (kvm_vcpu_get_esr (vcpu) & ESR_ELx_ERET_ISS_ERETA)
If this part is confusing due to the name, maybe introduce a function in esr.h esr_is_pac_eret() (name pending bikeshedding)?
arch/arm64/kvm/handle_exit.c static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu) · line 225
Quoted 3 lines
arch/arm64/kvm/handle_exit.c +0
-0return kvm_handle_ptrauth (vcpu);/*
Thanks,
Joey
Marc Zyngier
maintainerRe: [PATCH 02/13] KVM: arm64: Clarify ESR_ELx_ERET_ISS_ERET*
Quoted 14 lines · Joey Gouly
Quoted 12 lines · Marc Zyngier
The ESR_ELx_ERET_ISS_ERET* macros are a bit confusing:
-
ESR_ELx_ERET_ISS_ERETreally indicates that we have trapped an ERETA* instruction, as opposed to an ERET-
ESR_ELx_ERET_ISS_ERETAreallu indicates that we have trapped an ERETAB instruction, as opposed to an ERETAA.Repaint the two helpers such as:
-
ESR_ELx_ERET_ISS_ERETbecomesESR_ELx_ERET_ISS_ERETA
Quoted 8 lines
Quoted 5 lines
-
ESR_ELx_ERET_ISS_ERETAbecomesESR_ELx_ERET_ISS_ERETABAt the same time, use
BIT()instead of raw values.Signed-off-by Marc Zyngier <[email protected]>I'm somewhat against this, as the original names are what the Arm ARM specifies.
I don't disagree, but that doesn't make the ARM ARM right! ;-)
Quoted 27 lines
Quoted 27 lines
--- arch/arm64/include/asm/esr.h | 4 ++-- arch/arm64/kvm/handle_exit.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)arch/arm64/include/asm/esr.h +2
-2@@ -290,8 +290,8 @@ ESR_ELx_SYS64_ISS_OP2_SHIFT))/* ISS field definitions for ERET/ERETAA/ERETAB trapping */ -#define ESR_ELx_ERET_ISS_ERET 0x2 -#define ESR_ELx_ERET_ISS_ERETA 0x1 +#define ESR_ELx_ERET_ISS_ERETA BIT(1) +#define ESR_ELx_ERET_ISS_ERETAB BIT(0)/* * ISS field definitions for floating-point exception traps arch/arm64/kvm/handle_exit.c +0
-0@@ -219,7 +219,7 @@ static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu)
Quoted 7 lines
arch/arm64/kvm/handle_exit.c static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu) · line 222
Quoted 4 lines
arch/arm64/kvm/handle_exit.c +1
-1static int kvm_handle_eret (struct kvm_vcpu *vcpu) { -if (kvm_vcpu_get_esr (vcpu) & ESR_ELx_ERET_ISS_ERET) +if (kvm_vcpu_get_esr (vcpu) & ESR_ELx_ERET_ISS_ERETA)If this part is confusing due to the name, maybe introduce a function in
esr.hesr_is_pac_eret()(name pending bikeshedding)?
That's indeed a better option. Now for the bikeshed aspect:
- esr_iss_is_eretax(): check for ESR_ELx_ERET_ISS_ERET being set
- esr_iss_is_eretab(): check for ESR_ELx_ERET_ISS_ERETA being set
Thoughts?
M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
Joey Gouly
reviewerRe: [PATCH 02/13] KVM: arm64: Clarify ESR_ELx_ERET_ISS_ERET*
Quoted 62 lines · Marc Zyngier
Quoted 14 lines · Joey Gouly
Quoted 12 lines · Marc Zyngier
The ESR_ELx_ERET_ISS_ERET* macros are a bit confusing:
-
ESR_ELx_ERET_ISS_ERETreally indicates that we have trapped an ERETA* instruction, as opposed to an ERET-
ESR_ELx_ERET_ISS_ERETAreallu indicates that we have trapped an ERETAB instruction, as opposed to an ERETAA.Repaint the two helpers such as:
-
ESR_ELx_ERET_ISS_ERETbecomesESR_ELx_ERET_ISS_ERETAQuoted 8 lines
Quoted 5 lines
-
ESR_ELx_ERET_ISS_ERETAbecomesESR_ELx_ERET_ISS_ERETABAt the same time, use
BIT()instead of raw values.Signed-off-by Marc Zyngier <[email protected]>I'm somewhat against this, as the original names are what the Arm ARM specifies.
I don't disagree, but that doesn't make the ARM ARM right! ;-)
Quoted 27 lines
Quoted 27 lines
--- arch/arm64/include/asm/esr.h | 4 ++-- arch/arm64/kvm/handle_exit.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)arch/arm64/include/asm/esr.h +2
-2@@ -290,8 +290,8 @@ ESR_ELx_SYS64_ISS_OP2_SHIFT))/* ISS field definitions for ERET/ERETAA/ERETAB trapping */ -#define ESR_ELx_ERET_ISS_ERET 0x2 -#define ESR_ELx_ERET_ISS_ERETA 0x1 +#define ESR_ELx_ERET_ISS_ERETA BIT(1) +#define ESR_ELx_ERET_ISS_ERETAB BIT(0)/* * ISS field definitions for floating-point exception traps arch/arm64/kvm/handle_exit.c +0
-0@@ -219,7 +219,7 @@ static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu)Quoted 7 lines
arch/arm64/kvm/handle_exit.c static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu) · line 222
Quoted 4 lines
arch/arm64/kvm/handle_exit.c +1
-1static int kvm_handle_eret (struct kvm_vcpu *vcpu) { -if (kvm_vcpu_get_esr (vcpu) & ESR_ELx_ERET_ISS_ERET) +if (kvm_vcpu_get_esr (vcpu) & ESR_ELx_ERET_ISS_ERETA)If this part is confusing due to the name, maybe introduce a function in
esr.hesr_is_pac_eret()(name pending bikeshedding)?
Quoted 8 lines
That's indeed a better option. Now for the bikeshed aspect:
-
esr_iss_is_eretax(): check forESR_ELx_ERET_ISS_ERETbeing set-
esr_iss_is_eretab(): check forESR_ELx_ERET_ISS_ERETAbeing setThoughts?
I was trying to avoid the ERETA* confusion by suggesting 'pac_eret', but if I were to pick between your options I'd pick esr_iss_is_eretax().
Thanks,
Joey
Marc Zyngier
maintainerRe: [PATCH 02/13] KVM: arm64: Clarify ESR_ELx_ERET_ISS_ERET*
Quoted 12 lines · Joey Gouly
Quoted 10 lines · Marc Zyngier
Quoted 3 lines · Joey Gouly
If this part is confusing due to the name, maybe introduce a function in
esr.hesr_is_pac_eret()(name pending bikeshedding)?That's indeed a better option. Now for the bikeshed aspect:
-
esr_iss_is_eretax(): check forESR_ELx_ERET_ISS_ERETbeing set
Quoted 7 lines
Quoted 4 lines
-
esr_iss_is_eretab(): check forESR_ELx_ERET_ISS_ERETAbeing setThoughts?
I was trying to avoid the ERETA* confusion by suggesting '
pac_eret', but if I were to pick between your options I'd pickesr_iss_is_eretax().
It's not an either/or situation. We actually need both:
- esr_iss_is_eretax() being true tells you that you need to authenticate the ERET
- esr_iss_is_eretab() tells you that you need to use the A or B key
Thanks,
M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
Joey Gouly
reviewerRe: [PATCH 02/13] KVM: arm64: Clarify ESR_ELx_ERET_ISS_ERET*
Quoted 22 lines · Marc Zyngier
Quoted 12 lines · Joey Gouly
Quoted 10 lines · Marc Zyngier
Quoted 3 lines · Joey Gouly
If this part is confusing due to the name, maybe introduce a function in
esr.hesr_is_pac_eret()(name pending bikeshedding)?That's indeed a better option. Now for the bikeshed aspect:
-
esr_iss_is_eretax(): check forESR_ELx_ERET_ISS_ERETbeing setQuoted 7 lines
Quoted 4 lines
-
esr_iss_is_eretab(): check forESR_ELx_ERET_ISS_ERETAbeing setThoughts?
I was trying to avoid the ERETA* confusion by suggesting '
pac_eret', but if I were to pick between your options I'd pickesr_iss_is_eretax().
Quoted 6 lines
It's not an either/or situation. We actually need both:
-
esr_iss_is_eretax()being true tells you that you need to authenticate the ERET-
esr_iss_is_eretab()tells you that you need to use the A or B key
Oh right, yes that makes sense (please add a brief comment like ^ above the functions)
Thanks,
Joey
Marc Zyngier
maintainerPATCH 3/13 KVM: arm64: nv: Drop VCPU_HYP_CONTEXT flag
In reply to Marc ZyngierIt has become obvious that HCR_EL2.NV serves the exact same use as VCPU_HYP_CONTEXT, only in an architectural way. So just drop the flag for good.
--- arch/arm64/include/asm/kvm_host.h | 2 -- arch/arm64/kvm/hyp/vhe/switch.c | 7 +------ 2 files changed, 1 insertion(+), 8 deletions(-)
arch/arm64/include/asm/kvm_host.h +0 -2
@@ -816,8 +816,6 @@ struct kvm_vcpu_arch {#define DEBUG_STATE_SAVE_SPE __vcpu_single_flag(iflags, BIT(5))/* Save TRBE context if active */ #define DEBUG_STATE_SAVE_TRBE __vcpu_single_flag(iflags, BIT(6)) -/* vcpu running in HYP context */ -#define VCPU_HYP_CONTEXT __vcpu_single_flag(iflags, BIT(7))/* SVE enabled for host EL0 */ #define HOST_SVE_ENABLED __vcpu_single_flag(sflags, BIT(0))
arch/arm64/kvm/hyp/vhe/switch.c +1 -6
@@ -197,7 +197,7 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)* If we were in HYP context on entry, adjust the PSTATE view * so that the usual helpers work correctly. */ -if (unlikely (vcpu_get_flag (vcpu,VCPU_HYP_CONTEXT ))) { +if (unlikely (read_sysreg (hcr_el2) &HCR_NV )) {u64 mode = *vcpu_cpsr (vcpu) & (PSR_MODE_MASK |PSR_MODE32_BIT );switch (mode) {
@@ -240,11 +240,6 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)sysreg_restore_guest_state_vhe (guest_ctxt);__debug_switch_to_guest (vcpu); -if (is_hyp_ctxt (vcpu)) -vcpu_set_flag (vcpu,VCPU_HYP_CONTEXT ); -else -vcpu_clear_flag (vcpu,VCPU_HYP_CONTEXT ); - do { /* Jump in the fire! */ exit_code = __guest_enter(vcpu);
Signature · 1 line
2.39.2
Re: [PATCH 03/13] KVM: arm64: nv: Drop VCPU_HYP_CONTEXT flag
Quoted 38 lines · Marc Zyngier
It has become obvious that HCR_EL2.NV serves the exact same use as
VCPU_HYP_CONTEXT, only in an architectural way. So just drop the flag for good.Signed-off-by Marc Zyngier <[email protected]>--- arch/arm64/include/asm/kvm_host.h | 2 -- arch/arm64/kvm/hyp/vhe/switch.c | 7 +------ 2 files changed, 1 insertion(+), 8 deletions(-)arch/arm64/include/asm/kvm_host.h +0
-2@@ -816,8 +816,6 @@ struct kvm_vcpu_arch {#define DEBUG_STATE_SAVE_SPE __vcpu_single_flag(iflags, BIT(5))/* Save TRBE context if active */ #define DEBUG_STATE_SAVE_TRBE __vcpu_single_flag(iflags, BIT(6)) -/* vcpu running in HYP context */ -#define VCPU_HYP_CONTEXT __vcpu_single_flag(iflags, BIT(7))/* SVE enabled for host EL0 */ #define HOST_SVE_ENABLED __vcpu_single_flag(sflags, BIT(0))arch/arm64/kvm/hyp/vhe/switch.c +1
-1@@ -197,7 +197,7 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)* If we were in HYP context on entry, adjust the PSTATE view * so that the usual helpers work correctly. */ -if (unlikely (vcpu_get_flag (vcpu,VCPU_HYP_CONTEXT ))) { +if (unlikely (read_sysreg (hcr_el2) &HCR_NV )) {u64 mode = *vcpu_cpsr (vcpu) & (PSR_MODE_MASK |PSR_MODE32_BIT );switch (mode) {@@ -240,11 +240,6 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)sysreg_restore_guest_state_vhe (guest_ctxt);
arch/arm64/kvm/hyp/vhe/switch.c static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) · line 245
Quoted 10 lines
arch/arm64/kvm/hyp/vhe/switch.c +0
-5__debug_switch_to_guest (vcpu); -if (is_hyp_ctxt (vcpu)) -vcpu_set_flag (vcpu,VCPU_HYP_CONTEXT ); -else -vcpu_clear_flag (vcpu,VCPU_HYP_CONTEXT ); - do { /* Jump in the fire! */ exit_code = __guest_enter(vcpu);
Makes sense to me.
Thanks,
Joey
Marc Zyngier
maintainerPATCH 4/13 KVM: arm64: nv: Configure HCR_EL2 for FEAT_NV2
In reply to Marc ZyngierAdd the HCR_EL2 configuration for FEAT_NV2, adding the required bits for running a guest hypervisor, and overall merging the allowed bits provided by the guest.
This heavily replies on unavaliable features being sanitised when the HCR_EL2 shadow register is accessed, and only a couple of bits must be explicitly disabled.
Non-NV guests are completely unaffected by any of this.
--- arch/arm64/include/asm/sysreg.h | 1 + arch/arm64/kvm/hyp/include/hyp/switch.h | 4 +-- arch/arm64/kvm/hyp/nvhe/switch.c | 2 +- arch/arm64/kvm/hyp/vhe/switch.c | 34 ++++++++++++++++++++++++- 4 files changed, 36 insertions(+), 5 deletions(-)
arch/arm64/include/asm/sysreg.h +1 -0
@@ -498,6 +498,7 @@#define SYS_TCR_EL2 sys_reg(3, 4, 2, 0, 2)#define SYS_VTTBR_EL2 sys_reg(3, 4, 2, 1, 0)#define SYS_VTCR_EL2 sys_reg(3, 4, 2, 1, 2) +#define SYS_VNCR_EL2 sys_reg(3, 4, 2, 2, 0)#define SYS_TRFCR_EL2 sys_reg(3, 4, 1, 2, 1)#define SYS_VNCR_EL2 sys_reg(3, 4, 2, 2, 0)
arch/arm64/kvm/hyp/include/hyp/switch.h +1 -3
@@ -271,10 +271,8 @@ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)__deactivate_traps_hfgxtr (vcpu); } -static inline void ___activate_traps (struct kvm_vcpu *vcpu) +static inline void ___activate_traps (struct kvm_vcpu *vcpu,u64 hcr) { -u64 hcr = vcpu->arch.hcr_el2; -if (cpus_have_final_cap (ARM64_WORKAROUND_CAVIUM_TX2_219_TVM )) hcr |=HCR_TVM ;
arch/arm64/kvm/hyp/nvhe/switch.c +1 -1
@@ -40,7 +40,7 @@ static void __activate_traps(struct kvm_vcpu *vcpu) {u64 val; -___activate_traps (vcpu); +___activate_traps (vcpu, vcpu->arch.hcr_el2);__activate_traps_common (vcpu); val = vcpu->arch.cptr_el2;
arch/arm64/kvm/hyp/vhe/switch.c +33 -1
@@ -33,11 +33,43 @@ DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data); DEFINE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt); DEFINE_PER_CPU(unsigned long, kvm_hyp_vector); +/* +* HCR_EL2 bits that the NV guest can freely change (no RES0/RES1 +* semantics, irrespective of the configuration), but that cannot be +* applied to the actual HW as things would otherwise break badly. +* +* - TGE: we want to use EL1, which is incompatible with it being set +* +* - API/APK: for hysterical raisins, we enable PAuth lazily, which +* means that the guest's bits cannot be directly applied (we really +* want to see the traps). Revisit this at some point. +*/ +#define NV_HCR_GUEST_EXCLUDE (HCR_TGE | HCR_API | HCR_APK) + +static u64 __compute_hcr (struct kvm_vcpu *vcpu) +{ +u64 hcr = vcpu->arch.hcr_el2; + +if (!vcpu_has_nv (vcpu)) +return hcr; + +if (is_hyp_ctxt (vcpu)) { + hcr |=HCR_NV |HCR_NV2 |HCR_AT |HCR_TTLB ; + +if (!vcpu_el2_e2h_is_set (vcpu)) + hcr |=HCR_NV1 ; + +write_sysreg_s (vcpu->arch.ctxt.vncr_array,SYS_VNCR_EL2 ); + } + +return hcr | (__vcpu_sys_reg (vcpu,HCR_EL2 ) & ~NV_HCR_GUEST_EXCLUDE ); +} +static void __activate_traps (struct kvm_vcpu *vcpu) {u64 val; -___activate_traps (vcpu); +___activate_traps (vcpu,__compute_hcr (vcpu));if (has_cntpoff ()) {struct timer_map map;
Signature · 1 line
2.39.2
Re: [PATCH 04/13] KVM: arm64: nv: Configure HCR_EL2 for FEAT_NV2
Hi,
Quoted 23 lines · Marc Zyngier
Add the
HCR_EL2configuration forFEAT_NV2, adding the required bits for running a guest hypervisor, and overall merging the allowed bits provided by the guest.This heavily replies on unavaliable features being sanitised when the
HCR_EL2shadow register is accessed, and only a couple of bits must be explicitly disabled.Non-NV guests are completely unaffected by any of this.
Signed-off-by Marc Zyngier <[email protected]>--- arch/arm64/include/asm/sysreg.h | 1 + arch/arm64/kvm/hyp/include/hyp/switch.h | 4 +-- arch/arm64/kvm/hyp/nvhe/switch.c | 2 +- arch/arm64/kvm/hyp/vhe/switch.c | 34 ++++++++++++++++++++++++- 4 files changed, 36 insertions(+), 5 deletions(-)arch/arm64/include/asm/sysreg.h +0
-0
arch/arm64/include/asm/sysreg.h line 504
Quoted 7 lines
arch/arm64/include/asm/sysreg.h +1
-0@@ -498,6 +498,7 @@#define SYS_TCR_EL2 sys_reg(3, 4, 2, 0, 2)#define SYS_VTTBR_EL2 sys_reg(3, 4, 2, 1, 0)#define SYS_VTCR_EL2 sys_reg(3, 4, 2, 1, 2) +#define SYS_VNCR_EL2 sys_reg(3, 4, 2, 2, 0)#define SYS_TRFCR_EL2 sys_reg(3, 4, 1, 2, 1)#define SYS_VNCR_EL2 sys_reg(3, 4, 2, 2, 0)
I'm seeing double! (SYS_VNCR_EL2 is already defined a few lines down)
Quoted 34 lines
arch/arm64/kvm/hyp/include/hyp/switch.h +1
-3@@ -271,10 +271,8 @@ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)__deactivate_traps_hfgxtr (vcpu); } -static inline void ___activate_traps (struct kvm_vcpu *vcpu) +static inline void ___activate_traps (struct kvm_vcpu *vcpu,u64 hcr) { -u64 hcr = vcpu->arch.hcr_el2; -if (cpus_have_final_cap (ARM64_WORKAROUND_CAVIUM_TX2_219_TVM )) hcr |=HCR_TVM ;arch/arm64/kvm/hyp/nvhe/switch.c +1
-1@@ -40,7 +40,7 @@ static void __activate_traps(struct kvm_vcpu *vcpu) {u64 val; -___activate_traps (vcpu); +___activate_traps (vcpu, vcpu->arch.hcr_el2);__activate_traps_common (vcpu); val = vcpu->arch.cptr_el2;arch/arm64/kvm/hyp/vhe/switch.c +0
-0
arch/arm64/kvm/hyp/vhe/switch.c DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data); · line 41
Quoted 9 lines
arch/arm64/kvm/hyp/vhe/switch.c +6
-0@@ -33,11 +33,43 @@ DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data); DEFINE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt); DEFINE_PER_CPU(unsigned long, kvm_hyp_vector); +/* +* HCR_EL2 bits that the NV guest can freely change (no RES0/RES1 +* semantics, irrespective of the configuration), but that cannot be +* applied to the actual HW as things would otherwise break badly. +* +* - TGE: we want to use EL1, which is incompatible with it being set
Can you make this a bit clearer:
we want the guest to use EL1
Assuming I've understood correctly. I first read it as 'we' == kvm.
Quoted 25 lines
arch/arm64/kvm/hyp/vhe/switch.c +25
-0+* +* - API/APK: for hysterical raisins, we enable PAuth lazily, which +* means that the guest's bits cannot be directly applied (we really +* want to see the traps). Revisit this at some point. +*/ +#define NV_HCR_GUEST_EXCLUDE (HCR_TGE | HCR_API | HCR_APK) + +static u64 __compute_hcr (struct kvm_vcpu *vcpu) +{ +u64 hcr = vcpu->arch.hcr_el2; + +if (!vcpu_has_nv (vcpu)) +return hcr; + +if (is_hyp_ctxt (vcpu)) { + hcr |=HCR_NV |HCR_NV2 |HCR_AT |HCR_TTLB ; + +if (!vcpu_el2_e2h_is_set (vcpu)) + hcr |=HCR_NV1 ; + +write_sysreg_s (vcpu->arch.ctxt.vncr_array,SYS_VNCR_EL2 ); + } + +return hcr | (__vcpu_sys_reg (vcpu,HCR_EL2 ) & ~NV_HCR_GUEST_EXCLUDE ); +}
arch/arm64/kvm/hyp/vhe/switch.c DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data); · line 75
Quoted 10 lines
arch/arm64/kvm/hyp/vhe/switch.c +2
-1+static void __activate_traps (struct kvm_vcpu *vcpu) {u64 val; -___activate_traps (vcpu); +___activate_traps (vcpu,__compute_hcr (vcpu));if (has_cntpoff ()) {struct timer_map map;
Otherwise,
Thanks,
Joey
Marc Zyngier
maintainerRe: [PATCH 04/13] KVM: arm64: nv: Configure HCR_EL2 for FEAT_NV2
Quoted 32 lines · Joey Gouly
Hi,
Quoted 28 lines · Marc Zyngier
Add the
HCR_EL2configuration forFEAT_NV2, adding the required bits for running a guest hypervisor, and overall merging the allowed bits provided by the guest.This heavily replies on unavaliable features being sanitised when the
HCR_EL2shadow register is accessed, and only a couple of bits must be explicitly disabled.Non-NV guests are completely unaffected by any of this.
Signed-off-by Marc Zyngier <[email protected]>--- arch/arm64/include/asm/sysreg.h | 1 + arch/arm64/kvm/hyp/include/hyp/switch.h | 4 +-- arch/arm64/kvm/hyp/nvhe/switch.c | 2 +- arch/arm64/kvm/hyp/vhe/switch.c | 34 ++++++++++++++++++++++++- 4 files changed, 36 insertions(+), 5 deletions(-)arch/arm64/include/asm/sysreg.h +1
-0@@ -498,6 +498,7 @@#define SYS_TCR_EL2 sys_reg(3, 4, 2, 0, 2)#define SYS_VTTBR_EL2 sys_reg(3, 4, 2, 1, 0)#define SYS_VTCR_EL2 sys_reg(3, 4, 2, 1, 2) +#define SYS_VNCR_EL2 sys_reg(3, 4, 2, 2, 0)
Quoted 5 lines
arch/arm64/include/asm/sysreg.h line 504
Quoted 2 lines
arch/arm64/include/asm/sysreg.h +0
-0#define SYS_TRFCR_EL2 sys_reg(3, 4, 1, 2, 1)#define SYS_VNCR_EL2 sys_reg(3, 4, 2, 2, 0)I'm seeing double! (
SYS_VNCR_EL2is already defined a few lines down)
Ah, it got added by Miguel and my rebase didn't weed it out. It also doesn't help that SYS_TRFCR_EL2 is out of sequence... Anyway, I'll drop this, thanks for spotting it.
Quoted 47 lines
Quoted 35 lines
arch/arm64/kvm/hyp/include/hyp/switch.h +1
-3@@ -271,10 +271,8 @@ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)__deactivate_traps_hfgxtr (vcpu); } -static inline void ___activate_traps (struct kvm_vcpu *vcpu) +static inline void ___activate_traps (struct kvm_vcpu *vcpu,u64 hcr) { -u64 hcr = vcpu->arch.hcr_el2; -if (cpus_have_final_cap (ARM64_WORKAROUND_CAVIUM_TX2_219_TVM )) hcr |=HCR_TVM ;arch/arm64/kvm/hyp/nvhe/switch.c +1
-1@@ -40,7 +40,7 @@ static void __activate_traps(struct kvm_vcpu *vcpu) {u64 val; -___activate_traps (vcpu); +___activate_traps (vcpu, vcpu->arch.hcr_el2);__activate_traps_common (vcpu); val = vcpu->arch.cptr_el2;arch/arm64/kvm/hyp/vhe/switch.c +0
-0arch/arm64/kvm/hyp/vhe/switch.c DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data); · line 41
Quoted 9 lines
arch/arm64/kvm/hyp/vhe/switch.c +6
-0@@ -33,11 +33,43 @@ DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data); DEFINE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt); DEFINE_PER_CPU(unsigned long, kvm_hyp_vector); +/* +* HCR_EL2 bits that the NV guest can freely change (no RES0/RES1 +* semantics, irrespective of the configuration), but that cannot be +* applied to the actual HW as things would otherwise break badly. +* +* - TGE: we want to use EL1, which is incompatible with it being set Can you make this a bit clearer:
Quoted 3 lines
we want the guest to use EL1
Assuming I've understood correctly. I first read it as 'we' == kvm.
Sure thing, happy to update that.
Quoted 33 lines
Quoted 33 lines
Quoted 1 line
+ *
+ * - API/APK: for hysterical raisins, we enable PAuth lazily, which
+ * means that the guest's bits cannot be directly applied (we really
+ * want to see the traps). Revisit this at some point.
+ */arch/arm64/kvm/hyp/vhe/switch.c +22
-1+#define NV_HCR_GUEST_EXCLUDE (HCR_TGE | HCR_API | HCR_APK) + +static u64 __compute_hcr (struct kvm_vcpu *vcpu) +{ +u64 hcr = vcpu->arch.hcr_el2; + +if (!vcpu_has_nv (vcpu)) +return hcr; + +if (is_hyp_ctxt (vcpu)) { + hcr |=HCR_NV |HCR_NV2 |HCR_AT |HCR_TTLB ; + +if (!vcpu_el2_e2h_is_set (vcpu)) + hcr |=HCR_NV1 ; + +write_sysreg_s (vcpu->arch.ctxt.vncr_array,SYS_VNCR_EL2 ); + } + +return hcr | (__vcpu_sys_reg (vcpu,HCR_EL2 ) & ~NV_HCR_GUEST_EXCLUDE ); +} +static void __activate_traps (struct kvm_vcpu *vcpu) {u64 val; -___activate_traps (vcpu); +___activate_traps (vcpu,__compute_hcr (vcpu));
Quoted 6 lines
arch/arm64/kvm/hyp/vhe/switch.c DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data); · line 75
Quoted 2 lines
arch/arm64/kvm/hyp/vhe/switch.c +0
-0if (has_cntpoff ()) {struct timer_map map;Otherwise,
Reviewed-by Joey Gouly <[email protected]>
Thanks!
M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
Marc Zyngier
maintainerPATCH 5/13 KVM: arm64: nv: Add trap forwarding for ERET and SMC
In reply to Marc ZyngierHonor the trap forwarding bits for both ERET and SMC, using a new helper that checks for common conditions.
--- arch/arm64/include/asm/kvm_nested.h | 1 + arch/arm64/kvm/emulate-nested.c | 27 +++++++++++++++++++++++++++ arch/arm64/kvm/handle_exit.c | 7 +++++++ 3 files changed, 35 insertions(+)
arch/arm64/include/asm/kvm_nested.h +1 -0
@@ -60,6 +60,7 @@ static inline u64 translate_ttbr0_el2_to_ttbr0_el1(u64 ttbr0)return ttbr0 & ~GENMASK_ULL (63 ,48 ); } +extern bool forward_smc_trap (struct kvm_vcpu *vcpu);int kvm_init_nv_sysregs (struct kvm *kvm);
arch/arm64/kvm/emulate-nested.c +27 -0
@@ -2117,6 +2117,26 @@ bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index)return true; } +static bool forward_traps (struct kvm_vcpu *vcpu,u64 control_bit) +{ +bool control_bit_set; + +if (!vcpu_has_nv (vcpu)) +return false; + + control_bit_set =__vcpu_sys_reg (vcpu,HCR_EL2 ) & control_bit; +if (!is_hyp_ctxt (vcpu) && control_bit_set) { +kvm_inject_nested_sync (vcpu,kvm_vcpu_get_esr (vcpu)); +return true; + } +return false; +} + +bool forward_smc_trap (struct kvm_vcpu *vcpu) +{ +return forward_traps (vcpu,HCR_TSC ); +} +static u64 kvm_check_illegal_exception_return (struct kvm_vcpu *vcpu,u64 spsr) {u64 mode = spsr &PSR_MODE_MASK ;
@@ -2155,6 +2175,13 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu)u64 spsr, elr, mode;bool direct_eret; +/* +* Forward this trap to the virtual EL2 if the virtual +* HCR_EL2.NV bit is set and this is coming from !EL2. +*/ +if (forward_traps (vcpu,HCR_NV )) +return ; +/* * Going through the whole put/load motions is a waste of time * if this is a VHE guest hypervisor returning to its own
arch/arm64/kvm/handle_exit.c +7 -0
@@ -55,6 +55,13 @@ static int handle_hvc(struct kvm_vcpu *vcpu)static int handle_smc (struct kvm_vcpu *vcpu) { +/* +* Forward this trapped smc instruction to the virtual EL2 if +* the guest has asked for it. +*/ +if (forward_smc_trap (vcpu)) +return 1 ; +/* * "If an SMC instruction executed at Non-secure EL1 is * trapped to EL2 because HCR_EL2.TSC is 1, the exception is a
Signature · 1 line
2.39.2
Re: [PATCH 05/13] KVM: arm64: nv: Add trap forwarding for ERET and SMC
Quoted 7 lines · Marc Zyngier
Honor the trap forwarding bits for both ERET and SMC, using a new helper that checks for common conditions.
Co-developed-by Jintack Lim <[email protected]>Signed-off-by Jintack Lim <[email protected]>Signed-off-by Marc Zyngier <[email protected]>---
Quoted 70 lines
arch/arm64/include/asm/kvm_nested.h | 1 + arch/arm64/kvm/emulate-nested.c | 27 +++++++++++++++++++++++++++ arch/arm64/kvm/handle_exit.c | 7 +++++++ 3 files changed, 35 insertions(+)arch/arm64/include/asm/kvm_nested.h +1
-0@@ -60,6 +60,7 @@ static inline u64 translate_ttbr0_el2_to_ttbr0_el1(u64 ttbr0)return ttbr0 & ~GENMASK_ULL (63 ,48 ); } +extern bool forward_smc_trap (struct kvm_vcpu *vcpu);int kvm_init_nv_sysregs (struct kvm *kvm);arch/arm64/kvm/emulate-nested.c +27
-0@@ -2117,6 +2117,26 @@ bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *sr_index)return true; } +static bool forward_traps (struct kvm_vcpu *vcpu,u64 control_bit) +{ +bool control_bit_set; + +if (!vcpu_has_nv (vcpu)) +return false; + + control_bit_set =__vcpu_sys_reg (vcpu,HCR_EL2 ) & control_bit; +if (!is_hyp_ctxt (vcpu) && control_bit_set) { +kvm_inject_nested_sync (vcpu,kvm_vcpu_get_esr (vcpu)); +return true; + } +return false; +} + +bool forward_smc_trap (struct kvm_vcpu *vcpu) +{ +return forward_traps (vcpu,HCR_TSC ); +} +static u64 kvm_check_illegal_exception_return (struct kvm_vcpu *vcpu,u64 spsr) {u64 mode = spsr &PSR_MODE_MASK ;@@ -2155,6 +2175,13 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu)u64 spsr, elr, mode;bool direct_eret; +/* +* Forward this trap to the virtual EL2 if the virtual +* HCR_EL2.NV bit is set and this is coming from !EL2. +*/ +if (forward_traps (vcpu,HCR_NV )) +return ; +/* * Going through the whole put/load motions is a waste of time * if this is a VHE guest hypervisor returning to its own arch/arm64/kvm/handle_exit.c +0
-0@@ -55,6 +55,13 @@ static int handle_hvc(struct kvm_vcpu *vcpu)static int handle_smc (struct kvm_vcpu *vcpu) {
arch/arm64/kvm/handle_exit.c static int handle_hvc(struct kvm_vcpu *vcpu) · line 67
Quoted 10 lines
arch/arm64/kvm/handle_exit.c +7
-0+/* +* Forward this trapped smc instruction to the virtual EL2 if +* the guest has asked for it. +*/ +if (forward_smc_trap (vcpu)) +return 1 ; +/* * "If an SMC instruction executed at Non-secure EL1 is * trapped to EL2 because HCR_EL2.TSC is 1, the exception is a
Thanks,
Joey
Marc Zyngier
maintainerPATCH 6/13 KVM: arm64: nv: Fast-track 'InHost' exception returns
In reply to Marc ZyngierA significant part of the FEAT_NV extension is to trap ERET instructions so that the hypervisor gets a chance to switch from a vEL2 L1 guest to an EL1 L2 guest.
But this also has the unfortunate consequence of trapping ERET in unsuspecting circumstances, such as staying at vEL2 (interrupt handling while being in the guest hypervisor), or returning to host userspace in the case of a VHE guest.
Although we already make some effort to handle these ERET quicker by not doing the put/load dance, it is still way too far down the line for it to be efficient enough.
For these cases, it would ideal to ERET directly, no question asked. Of course, we can't do that. But the next best thing is to do it as early as possible, in fixup_guest_exit(), much as we would handle FPSIMD exceptions.
--- arch/arm64/kvm/emulate-nested.c | 29 +++------------------- arch/arm64/kvm/hyp/vhe/switch.c | 44 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 26 deletions(-)
arch/arm64/kvm/emulate-nested.c +3 -26
@@ -2172,8 +2172,7 @@ static u64 kvm_check_illegal_exception_return(struct kvm_vcpu *vcpu, u64 spsr)void kvm_emulate_nested_eret (struct kvm_vcpu *vcpu) { -u64 spsr, elr, mode; -bool direct_eret; +u64 spsr, elr;/* * Forward this trap to the virtual EL2 if the virtual
@@ -2182,33 +2181,11 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu)if (forward_traps (vcpu,HCR_NV ))return ; -/* -* Going through the whole put/load motions is a waste of time -* if this is a VHE guest hypervisor returning to its own -* userspace, or the hypervisor performing a local exception -* return. No need to save/restore registers, no need to -* switch S2 MMU. Just do the canonical ERET. -*/ - spsr =vcpu_read_sys_reg (vcpu,SPSR_EL2 ); - spsr =kvm_check_illegal_exception_return (vcpu, spsr); - - mode = spsr & (PSR_MODE_MASK |PSR_MODE32_BIT ); - - direct_eret = (mode == PSR_MODE_EL0t && -vcpu_el2_e2h_is_set (vcpu) && -vcpu_el2_tge_is_set (vcpu)); - direct_eret |= (mode == PSR_MODE_EL2h || mode == PSR_MODE_EL2t); - -if (direct_eret) { - *vcpu_pc (vcpu) =vcpu_read_sys_reg (vcpu,ELR_EL2 ); - *vcpu_cpsr (vcpu) = spsr; -trace_kvm_nested_eret (vcpu, *vcpu_pc (vcpu), spsr); -return ; - } -preempt_disable ();kvm_arch_vcpu_put (vcpu); + spsr =__vcpu_sys_reg (vcpu,SPSR_EL2 ); + spsr =kvm_check_illegal_exception_return (vcpu, spsr); elr =__vcpu_sys_reg (vcpu,ELR_EL2 );trace_kvm_nested_eret (vcpu, elr, spsr);
arch/arm64/kvm/hyp/vhe/switch.c +44 -0
56 lines not on this page · raw message
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH 7/13 KVM: arm64: nv: Honor HFGITR_EL2.ERET being set
In reply to Marc ZyngierIf the L1 hypervisor decides to trap ERETs while running L2, make sure we don't try to emulate it, just like we wouldn't if it had its NV bit set.
The exception will be reinjected from the core handler.
--- arch/arm64/kvm/hyp/vhe/switch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm64/kvm/hyp/vhe/switch.c +2 -1
@@ -219,7 +219,8 @@ static bool kvm_hyp_handle_eret(struct kvm_vcpu *vcpu, u64 *exit_code)* Unless the trap has to be forwarded further down the line, * of course... */ -if (__vcpu_sys_reg (vcpu,HCR_EL2 ) &HCR_NV ) +if ((__vcpu_sys_reg (vcpu,HCR_EL2 ) &HCR_NV ) || + (__vcpu_sys_reg (vcpu,HFGITR_EL2 ) &HFGITR_EL2_ERET ))return false; spsr =read_sysreg_el1 (SYS_SPSR );
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH 8/13 KVM: arm64: nv: Handle HCR_EL2.{API,APK} independantly
In reply to Marc ZyngierAlthough KVM couples API and APK for simplicity, the architecture makes no such requirement, and the two can be independently set or cleared.
Check for which of the two possible reasons we have trapped here, and if the corresponding L1 control bit isn't set, delegate the handling for forwarding.
Otherwise, set this exact bit in HCR_EL2 and resume the guest. Of course, in the non-NV case, we keep setting both bits and be done with it. Note that the entry core already saves/restores the keys should any of the two control bits be set.
This result in a bit of rework, and the removal of the (trivial) vcpu_ptrauth_enable() helper.
--- arch/arm64/include/asm/kvm_emulate.h | 5 ---- arch/arm64/kvm/hyp/include/hyp/switch.h | 32 +++++++++++++++++++++---- 2 files changed, 27 insertions(+), 10 deletions(-)
arch/arm64/include/asm/kvm_emulate.h +0 -5
@@ -125,11 +125,6 @@ static inline void vcpu_set_wfx_traps(struct kvm_vcpu *vcpu) vcpu->arch.hcr_el2 |=HCR_TWI ; } -static inline void vcpu_ptrauth_enable (struct kvm_vcpu *vcpu) -{ - vcpu->arch.hcr_el2 |= (HCR_API |HCR_APK ); -} -static inline void vcpu_ptrauth_disable (struct kvm_vcpu *vcpu) { vcpu->arch.hcr_el2 &= ~(HCR_API |HCR_APK );
arch/arm64/kvm/hyp/include/hyp/switch.h +27 -5
@@ -480,11 +480,35 @@ DECLARE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);static bool kvm_hyp_handle_ptrauth (struct kvm_vcpu *vcpu,u64 *exit_code) {struct kvm_cpu_context *ctxt; -u64 val; +u64 enable =0 ;if (!vcpu_has_ptrauth (vcpu))return false; +/* +* NV requires us to handle API and APK independently, just in +* case the hypervisor is totally nuts. Please barf >here<. +*/ +if (vcpu_has_nv (vcpu) && !is_hyp_ctxt (vcpu)) { +switch (ESR_ELx_EC (kvm_vcpu_get_esr (vcpu))) { +case ESR_ELx_EC_PAC: +if (!(__vcpu_sys_reg (vcpu,HCR_EL2 ) &HCR_API )) +return false; + + enable |=HCR_API ; +break ; + +case ESR_ELx_EC_SYS64: +if (!(__vcpu_sys_reg (vcpu,HCR_EL2 ) &HCR_APK )) +return false; + + enable |=HCR_APK ; +break ; + } + }else { + enable =HCR_API |HCR_APK ; + } + ctxt =this_cpu_ptr (&kvm_hyp_ctxt);__ptrauth_save_key (ctxt,APIA );__ptrauth_save_key (ctxt,APIB );
@@ -492,11 +516,9 @@ static bool kvm_hyp_handle_ptrauth(struct kvm_vcpu *vcpu, u64 *exit_code)__ptrauth_save_key (ctxt,APDB );__ptrauth_save_key (ctxt,APGA ); -vcpu_ptrauth_enable (vcpu); - val =read_sysreg (hcr_el2); - val |= (HCR_API |HCR_APK ); -write_sysreg (val, hcr_el2); + vcpu->arch.hcr_el2 |= enable; +sysreg_clear_set (hcr_el2,0 , enable);return true; }
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH 9/13 KVM: arm64: nv: Reinject PAC exceptions caused by HCR_EL2.API==0
In reply to Marc ZyngierIn order for a L1 hypervisor to correctly handle PAuth instructions, it must observe traps caused by a L1 PAuth instruction when HCR_EL2.API==0. Since we already handle the case for API==1 as a fixup, only the exception injection case needs to be handled.
Rework the kvm_handle_ptrauth() callback to reinject the trap in this case. Note that APK==0 is already handled by the exising triage_sysreg_trap() helper.
--- arch/arm64/kvm/handle_exit.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-)
arch/arm64/kvm/handle_exit.c +25 -3
@@ -214,12 +214,34 @@ static int handle_sve(struct kvm_vcpu *vcpu) }/* -* Guest usage of a ptrauth instruction (which the guest EL1 did not turn into -* a NOP). If we get here, it is that we didn't fixup ptrauth on exit, and all -* that we can do is give the guest an UNDEF. +* Two possibilities to handle a trapping ptrauth instruction: +* +* - Guest usage of a ptrauth instruction (which the guest EL1 did not +* turn into a NOP). If we get here, it is that we didn't fixup +* ptrauth on exit, and all that we can do is give the guest an +* UNDEF (as the guest isn't supposed to use ptrauth without being +* told it could). +* +* - Running an L2 NV guest while L1 has left HCR_EL2.API==0, and for +* which we reinject the exception into L1. API==1 is handled as a +* fixup so the only way to get here is when API==0. +* +* Anything else is an emulation bug (hence the WARN_ON + UNDEF). */ static int kvm_handle_ptrauth (struct kvm_vcpu *vcpu) { +if (!vcpu_has_ptrauth (vcpu)) { +kvm_inject_undefined (vcpu); +return 1 ; + } + +if (vcpu_has_nv (vcpu) && !is_hyp_ctxt (vcpu)) { +kvm_inject_nested_sync (vcpu,kvm_vcpu_get_esr (vcpu)); +return 1 ; + } + +/* Really shouldn't be here! */ +WARN_ON_ONCE (1 );kvm_inject_undefined (vcpu);return 1 ; }
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH 10/13 KVM: arm64: nv: Add kvm_has_pauth() helper
In reply to Marc ZyngierPointer Authentication comes in many flavors, and a faithful emulation relies on correctly handling the flavour implemented by the HW.
For this, provide a new kvm_has_pauth() that checks whether we expose to the guest a particular level of support. This checks across all 3 possible authentication algorithms (Q5, Q3 and IMPDEF).
--- arch/arm64/include/asm/kvm_host.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
arch/arm64/include/asm/kvm_host.h +15 -0
@@ -1334,4 +1334,19 @@ bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu); (get_idreg_field ((kvm), id, fld) >=expand_field_sign (id, fld, min) && \get_idreg_field ((kvm), id, fld) <=expand_field_sign (id, fld, max)) +/* Check for a given level of PAuth support */ +#define kvm_has_pauth (k, l) \ + ({ \ + bool pa, pi, pa3; \ + \ + pa = kvm_has_feat((k), ID_AA64ISAR1_EL1, APA, l); \ + pa &= kvm_has_feat((k), ID_AA64ISAR1_EL1, GPA, IMP); \ + pi = kvm_has_feat((k), ID_AA64ISAR1_EL1, API, l); \ + pi &= kvm_has_feat((k), ID_AA64ISAR1_EL1, GPI, IMP); \ + pa3 = kvm_has_feat((k), ID_AA64ISAR2_EL1, APA3, l); \ + pa3 &= kvm_has_feat((k), ID_AA64ISAR2_EL1, GPA3, IMP); \ + \ + (pa + pi + pa3) == 1; \ + }) +#endif /* __ARM64_KVM_HOST_H__ */
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH 11/13 KVM: arm64: nv: Add emulation for ERETAx instructions
In reply to Marc ZyngierFEAT_NV has the interesting property of relying on ERET being trapped. An added complexity is that it also traps ERETAA and ERETAB, meaning that the Pointer Authentication aspect of these instruction must be emulated.
Add an emulation of Pointer Authentication, limited to ERETAx (always using SP_EL2 as the modifier and ELR_EL2 as the pointer), using the Generic Authentication instructions.
The emulation, however small, is placed in its own compilation unit so that it can be avoided if the configuration doesn't include it (or the toolchan in not up to the task).
--- arch/arm64/include/asm/kvm_nested.h | 12 ++ arch/arm64/include/asm/pgtable-hwdef.h | 1 + arch/arm64/kvm/Makefile | 1 + arch/arm64/kvm/pauth.c | 196 +++++++++++++++++++++++++ 4 files changed, 210 insertions(+) create mode 100644 arch/arm64/kvm/pauth.c
arch/arm64/include/asm/kvm_nested.h +12 -0
@@ -64,4 +64,16 @@ extern bool forward_smc_trap(struct kvm_vcpu *vcpu);int kvm_init_nv_sysregs (struct kvm *kvm); +#ifdef CONFIG_ARM64_PTR_AUTH +bool kvm_auth_eretax (struct kvm_vcpu *vcpu,u64 *elr); +#else +static inline bool kvm_auth_eretax (struct kvm_vcpu *vcpu,u64 *elr) +{ +/* We really should never execute this... */ +WARN_ON_ONCE (1 ); + *elr =0xbad9acc0debadbad ; +return false; +} +#endif +#endif /* __ARM64_KVM_NESTED_H */
arch/arm64/include/asm/pgtable-hwdef.h +1 -0
@@ -277,6 +277,7 @@#define TCR_TBI1 (UL(1) << 38)#define TCR_HA (UL(1) << 39)#define TCR_HD (UL(1) << 40) +#define TCR_TBID0 (UL(1) << 51)#define TCR_TBID1 (UL(1) << 52)#define TCR_NFD0 (UL(1) << 53)#define TCR_NFD1 (UL(1) << 54)
arch/arm64/kvm/Makefile +1 -0
@@ -23,6 +23,7 @@ kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \ vgic/vgic-its.o vgic/vgic-debug.o kvm-$(CONFIG_HW_PERF_EVENTS) += pmu-emul.o pmu.o +kvm-$(CONFIG_ARM64_PTR_AUTH) += pauth.o always-y := hyp_constants.h hyp-constants.s
arch/arm64/kvm/pauth.c new file +196 -0
196 lines not on this page · raw message
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH 12/13 KVM: arm64: nv: Handle ERETA[AB] instructions
In reply to Marc ZyngierNow that we have some emulation in place for ERETA[AB], we can plug it into the exception handling machinery.
As for a bare ERET, an "easy" ERETAx instruction is processed as a fixup, while something that requires a translation regime transition or an exception delivery is left to the slow path.
--- arch/arm64/kvm/emulate-nested.c | 22 ++++++++++++++++++++-- arch/arm64/kvm/handle_exit.c | 3 ++- arch/arm64/kvm/hyp/vhe/switch.c | 13 +++++++++++-- 3 files changed, 33 insertions(+), 5 deletions(-)
arch/arm64/kvm/emulate-nested.c +20 -2
@@ -2172,7 +2172,7 @@ static u64 kvm_check_illegal_exception_return(struct kvm_vcpu *vcpu, u64 spsr)void kvm_emulate_nested_eret (struct kvm_vcpu *vcpu) { -u64 spsr, elr; +u64 spsr, elr, esr;/* * Forward this trap to the virtual EL2 if the virtual
@@ -2181,12 +2181,30 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu)if (forward_traps (vcpu,HCR_NV ))return ; +/* Check for an ERETAx */ + esr =kvm_vcpu_get_esr (vcpu); +if ((esr & ESR_ELx_ERET_ISS_ERETA) && !kvm_auth_eretax (vcpu, &elr)) { +/* +* Oh no, ERETAx failed to authenticate. If we have +* FPACCOMBINE, deliver an exception right away. If we +* don't, then let the mangled ELR value trickle down the +* ERET handling, and the guest will have a little surprise. +*/ +if (kvm_has_pauth (vcpu->kvm,FPACCOMBINE )) { + esr &= ESR_ELx_ERET_ISS_ERETAB; + esr |=FIELD_PREP (ESR_ELx_EC_MASK, ESR_ELx_EC_FPAC); +kvm_inject_nested_sync (vcpu, esr); +return ; + } + } +preempt_disable ();kvm_arch_vcpu_put (vcpu); spsr =__vcpu_sys_reg (vcpu,SPSR_EL2 ); spsr =kvm_check_illegal_exception_return (vcpu, spsr); - elr =__vcpu_sys_reg (vcpu,ELR_EL2 ); +if (!(esr & ESR_ELx_ERET_ISS_ERETA)) + elr =__vcpu_sys_reg (vcpu,ELR_EL2 );trace_kvm_nested_eret (vcpu, elr, spsr);
arch/arm64/kvm/handle_exit.c +2 -1
@@ -248,7 +248,8 @@ static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu)static int kvm_handle_eret (struct kvm_vcpu *vcpu) { -if (kvm_vcpu_get_esr (vcpu) & ESR_ELx_ERET_ISS_ERETA) +if ((kvm_vcpu_get_esr (vcpu) & ESR_ELx_ERET_ISS_ERETA) && + !vcpu_has_ptrauth (vcpu))return kvm_handle_ptrauth (vcpu);/*
arch/arm64/kvm/hyp/vhe/switch.c +11 -2
@@ -207,7 +207,8 @@ void kvm_vcpu_put_vhe(struct kvm_vcpu *vcpu)static bool kvm_hyp_handle_eret (struct kvm_vcpu *vcpu,u64 *exit_code) { -u64 spsr, mode; +u64 esr =kvm_vcpu_get_esr (vcpu); +u64 spsr, elr, mode;/* * Going through the whole put/load motions is a waste of time
@@ -241,10 +242,18 @@ static bool kvm_hyp_handle_eret(struct kvm_vcpu *vcpu, u64 *exit_code)return false; } +/* If ERETAx fails, take the slow path */ +if (esr & ESR_ELx_ERET_ISS_ERETA) { +if (!(vcpu_has_ptrauth (vcpu) &&kvm_auth_eretax (vcpu, &elr))) +return false; + }else { + elr =read_sysreg_el1 (SYS_ELR ); + } + spsr = (spsr & ~(PSR_MODE_MASK |PSR_MODE32_BIT )) | mode;write_sysreg_el2 (spsr,SYS_SPSR ); -write_sysreg_el2 (read_sysreg_el1 (SYS_ELR ),SYS_ELR ); +write_sysreg_el2 (elr,SYS_ELR );return true; }
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH 13/13 KVM: arm64: nv: Advertise support for PAuth
In reply to Marc ZyngierNow that we (hopefully) correctly handle ERETAx, drop the masking of the PAuth feature (something that was not even complete, as APA3 and AGA3 were still exposed).
--- arch/arm64/kvm/nested.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
arch/arm64/kvm/nested.c +2 -6
@@ -35,13 +35,9 @@ static u64 limit_nv_id_reg(u32 id, u64 val)break ;case SYS_ID_AA64ISAR1_EL1 : -/* Support everything but PtrAuth and Spec Invalidation */ +/* Support everything but Spec Invalidation */ val &= ~(GENMASK_ULL (63 ,56 ) | -NV_FTR (ISAR1 ,SPECRES ) | -NV_FTR (ISAR1 ,GPI ) | -NV_FTR (ISAR1 ,GPA ) | -NV_FTR (ISAR1 ,API ) | -NV_FTR (ISAR1 ,APA )); +NV_FTR (ISAR1 ,SPECRES ));break ;case SYS_ID_AA64PFR0_EL1 :
Signature · 1 line
2.39.2