]> www.infradead.org Git - nvme.git/commitdiff
Merge branch kvm-arm64/nv-eret-pauth into kvmarm-master/next
authorMarc Zyngier <maz@kernel.org>
Fri, 3 May 2024 10:39:19 +0000 (11:39 +0100)
committerMarc Zyngier <maz@kernel.org>
Fri, 3 May 2024 10:39:19 +0000 (11:39 +0100)
* kvm-arm64/nv-eret-pauth:
  : .
  : Add NV support for the ERETAA/ERETAB instructions. From the cover letter:
  :
  : "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!"
  : .
  KVM: arm64: nv: Work around lack of pauth support in old toolchains
  KVM: arm64: Drop trapping of PAuth instructions/keys
  KVM: arm64: nv: Advertise support for PAuth
  KVM: arm64: nv: Handle ERETA[AB] instructions
  KVM: arm64: nv: Add emulation for ERETAx instructions
  KVM: arm64: nv: Add kvm_has_pauth() helper
  KVM: arm64: nv: Reinject PAC exceptions caused by HCR_EL2.API==0
  KVM: arm64: nv: Handle HCR_EL2.{API,APK} independently
  KVM: arm64: nv: Honor HFGITR_EL2.ERET being set
  KVM: arm64: nv: Fast-track 'InHost' exception returns
  KVM: arm64: nv: Add trap forwarding for ERET and SMC
  KVM: arm64: nv: Configure HCR_EL2 for FEAT_NV2
  KVM: arm64: nv: Drop VCPU_HYP_CONTEXT flag
  KVM: arm64: Constraint PAuth support to consistent implementations
  KVM: arm64: Add helpers for ESR_ELx_ERET_ISS_ERET*
  KVM: arm64: Harden __ctxt_sys_reg() against out-of-range values

Signed-off-by: Marc Zyngier <maz@kernel.org>
1  2 
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/kvm/arm.c
arch/arm64/kvm/hyp/include/hyp/switch.h
arch/arm64/kvm/hyp/nvhe/switch.c
arch/arm64/kvm/hyp/vhe/switch.c

Simple merge
Simple merge
Simple merge
Simple merge
index 0027cc9b985eb7bf65886423ba61f9b820755016,f374bcdab4d4552aa1f9118490f75c3a508850d0..23794589c52ea2a72d4d36a744355f7a4464130b
@@@ -173,10 -203,61 +205,63 @@@ void kvm_vcpu_put_vhe(struct kvm_vcpu *
  {
        __vcpu_put_deactivate_traps(vcpu);
        __vcpu_put_switch_sysregs(vcpu);
 +
 +      host_data_ptr(host_ctxt)->__hyp_running_vcpu = NULL;
  }
  
+ static bool kvm_hyp_handle_eret(struct kvm_vcpu *vcpu, u64 *exit_code)
+ {
+       u64 esr = kvm_vcpu_get_esr(vcpu);
+       u64 spsr, elr, mode;
+       /*
+        * 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.
+        *
+        * Unless the trap has to be forwarded further down the line,
+        * of course...
+        */
+       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);
+       mode = spsr & (PSR_MODE_MASK | PSR_MODE32_BIT);
+       switch (mode) {
+       case PSR_MODE_EL0t:
+               if (!(vcpu_el2_e2h_is_set(vcpu) && vcpu_el2_tge_is_set(vcpu)))
+                       return false;
+               break;
+       case PSR_MODE_EL2t:
+               mode = PSR_MODE_EL1t;
+               break;
+       case PSR_MODE_EL2h:
+               mode = PSR_MODE_EL1h;
+               break;
+       default:
+               return false;
+       }
+       /* If ERETAx fails, take the slow path */
+       if (esr_iss_is_eretax(esr)) {
+               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(elr, SYS_ELR);
+       return true;
+ }
  static const exit_handler_fn hyp_exit_handlers[] = {
        [0 ... ESR_ELx_EC_MAX]          = NULL,
        [ESR_ELx_EC_CP15_32]            = kvm_hyp_handle_cp15_32,