]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
Merge branch kvm-arm64/pkvm-fixed-features-6.14 into kvmarm-master/next
authorMarc Zyngier <maz@kernel.org>
Sun, 12 Jan 2025 10:40:10 +0000 (10:40 +0000)
committerMarc Zyngier <maz@kernel.org>
Sun, 12 Jan 2025 10:40:10 +0000 (10:40 +0000)
* kvm-arm64/pkvm-fixed-features-6.14: (24 commits)
  : .
  : Complete rework of the pKVM handling of features, catching up
  : with the rest of the code deals with it these days.
  : Patches courtesy of Fuad Tabba. From the cover letter:
  :
  : "This patch series uses the vm's feature id registers to track the
  : supported features, a framework similar to nested virt to set the
  : trap values, and removes the need to store cptr_el2 per vcpu in
  : favor of setting its value when traps are activated, as VHE mode
  : does."
  :
  : This branch drags the arm64/for-next/cpufeature branch to solve
  : ugly conflicts in -next.
  : .
  KVM: arm64: Fix FEAT_MTE in pKVM
  KVM: arm64: Use kvm_vcpu_has_feature() directly for struct kvm
  KVM: arm64: Convert the SVE guest vcpu flag to a vm flag
  KVM: arm64: Remove PtrAuth guest vcpu flag
  KVM: arm64: Fix the value of the CPTR_EL2 RES1 bitmask for nVHE
  KVM: arm64: Refactor kvm_reset_cptr_el2()
  KVM: arm64: Calculate cptr_el2 traps on activating traps
  KVM: arm64: Remove redundant setting of HCR_EL2 trap bit
  KVM: arm64: Remove fixed_config.h header
  KVM: arm64: Rework specifying restricted features for protected VMs
  KVM: arm64: Set protected VM traps based on its view of feature registers
  KVM: arm64: Fix RAS trapping in pKVM for protected VMs
  KVM: arm64: Initialize feature id registers for protected VMs
  KVM: arm64: Use KVM extension checks for allowed protected VM capabilities
  KVM: arm64: Remove KVM_ARM_VCPU_POWER_OFF from protected VMs allowed features in pKVM
  KVM: arm64: Move checking protected vcpu features to a separate function
  KVM: arm64: Group setting traps for protected VMs by control register
  KVM: arm64: Consolidate allowed and restricted VM feature checks
  arm64/sysreg: Get rid of CPACR_ELx SysregFields
  arm64/sysreg: Convert *_EL12 accessors to Mapping
  ...

Signed-off-by: Marc Zyngier <maz@kernel.org>
# Conflicts:
# arch/arm64/kvm/fpsimd.c
# arch/arm64/kvm/hyp/nvhe/pkvm.c

1  2 
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_nested.h
arch/arm64/include/asm/kvm_pkvm.h
arch/arm64/kvm/arm.c
arch/arm64/kvm/emulate-nested.c
arch/arm64/kvm/fpsimd.c
arch/arm64/kvm/hyp/include/nvhe/pkvm.h
arch/arm64/kvm/hyp/nvhe/hyp-main.c
arch/arm64/kvm/hyp/nvhe/pkvm.c
arch/arm64/kvm/hyp/nvhe/setup.c

Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0e0f37d1990a34af023f48f4357a6c0b4927e7cb,98718bd65bf15edeef281da3e84a2f03480f070a..4d3d1a2eb157047b4b2488e9c4ffaabc6f5a0818
@@@ -168,8 -168,8 +168,8 @@@ void kvm_arch_vcpu_put_fp(struct kvm_vc
         */
        if (has_vhe() && system_supports_sme()) {
                /* Also restore EL0 state seen on entry */
 -              if (vcpu_get_flag(vcpu, HOST_SME_ENABLED))
 +              if (host_data_test_flag(HOST_SME_ENABLED))
-                       sysreg_clear_set(CPACR_EL1, 0, CPACR_ELx_SMEN);
+                       sysreg_clear_set(CPACR_EL1, 0, CPACR_EL1_SMEN);
                else
                        sysreg_clear_set(CPACR_EL1,
                                         CPACR_EL1_SMEN_EL0EN,
index 0cc2a429f1fb61b72c24dfedfbcfa5653c58a6c3,3888aabd78f3db459b8d833f4f8175c9a5d962d7..e42bf68c88482c207951f9fc69756d907b69f39e
@@@ -80,10 -71,10 +82,15 @@@ int __pkvm_teardown_vm(pkvm_handle_t ha
  struct pkvm_hyp_vcpu *pkvm_load_hyp_vcpu(pkvm_handle_t handle,
                                         unsigned int vcpu_idx);
  void pkvm_put_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu);
 +struct pkvm_hyp_vcpu *pkvm_get_loaded_hyp_vcpu(void);
 +
 +struct pkvm_hyp_vm *get_pkvm_hyp_vm(pkvm_handle_t handle);
 +struct pkvm_hyp_vm *get_np_pkvm_hyp_vm(pkvm_handle_t handle);
 +void put_pkvm_hyp_vm(struct pkvm_hyp_vm *hyp_vm);
  
+ bool kvm_handle_pvm_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code);
+ bool kvm_handle_pvm_restricted(struct kvm_vcpu *vcpu, u64 *exit_code);
+ void kvm_init_pvm_id_regs(struct kvm_vcpu *vcpu);
+ int kvm_check_pvm_sysreg_table(void);
  #endif /* __ARM64_KVM_NVHE_PKVM_H__ */
Simple merge
index 2c618f2f2769084430a96f6e9d64395a0ec3e173,f76adddc52de849914ad814036331b757ce1e16a..3927fe52a3dde8f59ddb996d674dd252630613a3
@@@ -23,152 -22,102 +22,108 @@@ unsigned int kvm_arm_vmid_bits
  
  unsigned int kvm_host_sve_max_vl;
  
- /*
-  * Set trap register values based on features in ID_AA64PFR0.
-  */
- static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu)
 +/*
 + * The currently loaded hyp vCPU for each physical CPU. Used only when
 + * protected KVM is enabled, but for both protected and non-protected VMs.
 + */
 +static DEFINE_PER_CPU(struct pkvm_hyp_vcpu *, loaded_hyp_vcpu);
 +
+ static void pkvm_vcpu_reset_hcr(struct kvm_vcpu *vcpu)
  {
-       const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64PFR0_EL1);
-       u64 hcr_set = HCR_RW;
-       u64 hcr_clear = 0;
-       u64 cptr_set = 0;
-       u64 cptr_clear = 0;
-       /* Protected KVM does not support AArch32 guests. */
-       BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0),
-               PVM_ID_AA64PFR0_RESTRICT_UNSIGNED) != ID_AA64PFR0_EL1_EL0_IMP);
-       BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL1),
-               PVM_ID_AA64PFR0_RESTRICT_UNSIGNED) != ID_AA64PFR0_EL1_EL1_IMP);
-       /*
-        * Linux guests assume support for floating-point and Advanced SIMD. Do
-        * not change the trapping behavior for these from the KVM default.
-        */
-       BUILD_BUG_ON(!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_FP),
-                               PVM_ID_AA64PFR0_ALLOW));
-       BUILD_BUG_ON(!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AdvSIMD),
-                               PVM_ID_AA64PFR0_ALLOW));
+       vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS;
  
        if (has_hvhe())
-               hcr_set |= HCR_E2H;
+               vcpu->arch.hcr_el2 |= HCR_E2H;
  
-       /* Trap RAS unless all current versions are supported */
-       if (FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_RAS), feature_ids) <
-           ID_AA64PFR0_EL1_RAS_V1P1) {
-               hcr_set |= HCR_TERR | HCR_TEA;
-               hcr_clear |= HCR_FIEN;
+       if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN)) {
+               /* route synchronous external abort exceptions to EL2 */
+               vcpu->arch.hcr_el2 |= HCR_TEA;
+               /* trap error record accesses */
+               vcpu->arch.hcr_el2 |= HCR_TERR;
        }
  
-       /* Trap AMU */
-       if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AMU), feature_ids)) {
-               hcr_clear |= HCR_AMVOFFEN;
-               cptr_set |= CPTR_EL2_TAM;
-       }
+       if (cpus_have_final_cap(ARM64_HAS_STAGE2_FWB))
+               vcpu->arch.hcr_el2 |= HCR_FWB;
  
-       /* Trap SVE */
-       if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_SVE), feature_ids)) {
-               if (has_hvhe())
-                       cptr_clear |= CPACR_ELx_ZEN;
-               else
-                       cptr_set |= CPTR_EL2_TZ;
-       }
+       if (cpus_have_final_cap(ARM64_HAS_EVT) &&
+           !cpus_have_final_cap(ARM64_MISMATCHED_CACHE_TYPE))
+               vcpu->arch.hcr_el2 |= HCR_TID4;
+       else
+               vcpu->arch.hcr_el2 |= HCR_TID2;
  
-       vcpu->arch.hcr_el2 |= hcr_set;
-       vcpu->arch.hcr_el2 &= ~hcr_clear;
-       vcpu->arch.cptr_el2 |= cptr_set;
-       vcpu->arch.cptr_el2 &= ~cptr_clear;
+       if (vcpu_has_ptrauth(vcpu))
+               vcpu->arch.hcr_el2 |= (HCR_API | HCR_APK);
+       if (kvm_has_mte(vcpu->kvm))
+               vcpu->arch.hcr_el2 |= HCR_ATA;
  }
  
- /*
-  * Set trap register values based on features in ID_AA64PFR1.
-  */
- static void pvm_init_traps_aa64pfr1(struct kvm_vcpu *vcpu)
+ static void pvm_init_traps_hcr(struct kvm_vcpu *vcpu)
  {
-       const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64PFR1_EL1);
-       u64 hcr_set = 0;
-       u64 hcr_clear = 0;
+       struct kvm *kvm = vcpu->kvm;
+       u64 val = vcpu->arch.hcr_el2;
  
-       /* Memory Tagging: Trap and Treat as Untagged if not supported. */
-       if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE), feature_ids)) {
-               hcr_set |= HCR_TID5;
-               hcr_clear |= HCR_DCT | HCR_ATA;
+       /* No support for AArch32. */
+       val |= HCR_RW;
+       /*
+        * Always trap:
+        * - Feature id registers: to control features exposed to guests
+        * - Implementation-defined features
+        */
+       val |= HCR_TACR | HCR_TIDCP | HCR_TID3 | HCR_TID1;
+       if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, RAS, IMP)) {
+               val |= HCR_TERR | HCR_TEA;
+               val &= ~(HCR_FIEN);
        }
  
-       vcpu->arch.hcr_el2 |= hcr_set;
-       vcpu->arch.hcr_el2 &= ~hcr_clear;
- }
+       if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, AMU, IMP))
+               val &= ~(HCR_AMVOFFEN);
  
- /*
-  * Set trap register values based on features in ID_AA64DFR0.
-  */
- static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu)
- {
-       const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64DFR0_EL1);
-       u64 mdcr_set = 0;
-       u64 mdcr_clear = 0;
-       u64 cptr_set = 0;
-       /* Trap/constrain PMU */
-       if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), feature_ids)) {
-               mdcr_set |= MDCR_EL2_TPM | MDCR_EL2_TPMCR;
-               mdcr_clear |= MDCR_EL2_HPME | MDCR_EL2_MTPME |
-                             MDCR_EL2_HPMN_MASK;
+       if (!kvm_has_feat(kvm, ID_AA64PFR1_EL1, MTE, IMP)) {
+               val |= HCR_TID5;
+               val &= ~(HCR_DCT | HCR_ATA);
        }
  
-       /* Trap Debug */
-       if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_DebugVer), feature_ids))
-               mdcr_set |= MDCR_EL2_TDRA | MDCR_EL2_TDA | MDCR_EL2_TDE;
+       if (!kvm_has_feat(kvm, ID_AA64MMFR1_EL1, LO, IMP))
+               val |= HCR_TLOR;
+       vcpu->arch.hcr_el2 = val;
+ }
  
-       /* Trap OS Double Lock */
-       if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_DoubleLock), feature_ids))
-               mdcr_set |= MDCR_EL2_TDOSA;
+ static void pvm_init_traps_mdcr(struct kvm_vcpu *vcpu)
+ {
+       struct kvm *kvm = vcpu->kvm;
+       u64 val = vcpu->arch.mdcr_el2;
  
-       /* Trap SPE */
-       if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMSVer), feature_ids)) {
-               mdcr_set |= MDCR_EL2_TPMS;
-               mdcr_clear |= MDCR_EL2_E2PB_MASK;
+       if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMUVer, IMP)) {
+               val |= MDCR_EL2_TPM | MDCR_EL2_TPMCR;
+               val &= ~(MDCR_EL2_HPME | MDCR_EL2_MTPME | MDCR_EL2_HPMN_MASK);
        }
  
-       /* Trap Trace Filter */
-       if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceFilt), feature_ids))
-               mdcr_set |= MDCR_EL2_TTRF;
+       if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, DebugVer, IMP))
+               val |= MDCR_EL2_TDRA | MDCR_EL2_TDA;
+       if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, DoubleLock, IMP))
+               val |= MDCR_EL2_TDOSA;
  
-       /* Trap Trace */
-       if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceVer), feature_ids)) {
-               if (has_hvhe())
-                       cptr_set |= CPACR_EL1_TTA;
-               else
-                       cptr_set |= CPTR_EL2_TTA;
+       if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, PMSVer, IMP)) {
+               val |= MDCR_EL2_TPMS;
+               val &= ~MDCR_EL2_E2PB_MASK;
        }
  
-       /* Trap External Trace */
-       if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_ExtTrcBuff), feature_ids))
-               mdcr_clear |= MDCR_EL2_E2TB_MASK;
+       if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, TraceFilt, IMP))
+               val |= MDCR_EL2_TTRF;
  
-       vcpu->arch.mdcr_el2 |= mdcr_set;
-       vcpu->arch.mdcr_el2 &= ~mdcr_clear;
-       vcpu->arch.cptr_el2 |= cptr_set;
- }
- /*
-  * Set trap register values based on features in ID_AA64MMFR0.
-  */
- static void pvm_init_traps_aa64mmfr0(struct kvm_vcpu *vcpu)
- {
-       const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64MMFR0_EL1);
-       u64 mdcr_set = 0;
+       if (!kvm_has_feat(kvm, ID_AA64DFR0_EL1, ExtTrcBuff, IMP))
+               val |= MDCR_EL2_E2TB_MASK;
  
        /* Trap Debug Communications Channel registers */
-       if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64MMFR0_EL1_FGT), feature_ids))
-               mdcr_set |= MDCR_EL2_TDCC;
+       if (!kvm_has_feat(kvm, ID_AA64MMFR0_EL1, FGT, IMP))
+               val |= MDCR_EL2_TDCC;
  
-       vcpu->arch.mdcr_el2 |= mdcr_set;
+       vcpu->arch.mdcr_el2 = val;
  }
  
  /*
Simple merge