]> xenbits.xensource.com Git - people/pauldu/linux.git/commitdiff
Merge branch kvm-arm64/pmu_pmcr_n into kvmarm/next
authorOliver Upton <oliver.upton@linux.dev>
Mon, 30 Oct 2023 20:24:07 +0000 (20:24 +0000)
committerOliver Upton <oliver.upton@linux.dev>
Mon, 30 Oct 2023 20:24:19 +0000 (20:24 +0000)
* kvm-arm64/pmu_pmcr_n:
  : User-defined PMC limit, courtesy Raghavendra Rao Ananta
  :
  : Certain VMMs may want to reserve some PMCs for host use while running a
  : KVM guest. This was a bit difficult before, as KVM advertised all
  : supported counters to the guest. Userspace can now limit the number of
  : advertised PMCs by writing to PMCR_EL0.N, as KVM's sysreg and PMU
  : emulation enforce the specified limit for handling guest accesses.
  KVM: selftests: aarch64: vPMU test for validating user accesses
  KVM: selftests: aarch64: vPMU register test for unimplemented counters
  KVM: selftests: aarch64: vPMU register test for implemented counters
  KVM: selftests: aarch64: Introduce vpmu_counter_access test
  tools: Import arm_pmuv3.h
  KVM: arm64: PMU: Allow userspace to limit PMCR_EL0.N for the guest
  KVM: arm64: Sanitize PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR} before first run
  KVM: arm64: Add {get,set}_user for PM{C,I}NTEN{SET,CLR}, PMOVS{SET,CLR}
  KVM: arm64: PMU: Set PMCR_EL0.N for vCPU based on the associated PMU
  KVM: arm64: PMU: Add a helper to read a vCPU's PMCR_EL0
  KVM: arm64: Select default PMU in KVM_ARM_VCPU_INIT handler
  KVM: arm64: PMU: Introduce helpers to set the guest's PMU

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
1  2 
arch/arm64/include/asm/kvm_host.h
arch/arm64/kvm/arm.c
arch/arm64/kvm/pmu-emul.c
arch/arm64/kvm/sys_regs.c
include/kvm/arm_pmu.h
tools/testing/selftests/kvm/Makefile

Simple merge
index c6cad400490f9749890d281f77ac234f6059bb7d,f6307afc5036b5692f35bcbb104e48683b701a82..317964bad1e1654807c6eaae181ca56c3b5660e1
@@@ -1315,10 -1225,24 +1314,25 @@@ static bool kvm_vcpu_init_changed(struc
  {
        unsigned long features = init->features[0];
  
 -      return !bitmap_equal(vcpu->arch.features, &features, KVM_VCPU_MAX_FEATURES);
 +      return !bitmap_equal(vcpu->kvm->arch.vcpu_features, &features,
 +                           KVM_VCPU_MAX_FEATURES);
  }
  
+ static int kvm_setup_vcpu(struct kvm_vcpu *vcpu)
+ {
+       struct kvm *kvm = vcpu->kvm;
+       int ret = 0;
+       /*
+        * When the vCPU has a PMU, but no PMU is set for the guest
+        * yet, set the default one.
+        */
+       if (kvm_vcpu_has_pmu(vcpu) && !kvm->arch.arm_pmu)
+               ret = kvm_arm_set_default_pmu(kvm);
+       return ret;
+ }
  static int __kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
                                 const struct kvm_vcpu_init *init)
  {
        mutex_lock(&kvm->arch.config_lock);
  
        if (test_bit(KVM_ARCH_FLAG_VCPU_FEATURES_CONFIGURED, &kvm->arch.flags) &&
 -          !bitmap_equal(kvm->arch.vcpu_features, &features, KVM_VCPU_MAX_FEATURES))
 +          kvm_vcpu_init_changed(vcpu, init))
                goto out_unlock;
  
 -      bitmap_copy(vcpu->arch.features, &features, KVM_VCPU_MAX_FEATURES);
 +      bitmap_copy(kvm->arch.vcpu_features, &features, KVM_VCPU_MAX_FEATURES);
  
+       ret = kvm_setup_vcpu(vcpu);
+       if (ret)
+               goto out_unlock;
        /* Now we know what it is, we can reset it. */
 -      ret = kvm_reset_vcpu(vcpu);
 -      if (ret) {
 -              bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES);
 -              goto out_unlock;
 -      }
 +      kvm_reset_vcpu(vcpu);
  
 -      bitmap_copy(kvm->arch.vcpu_features, &features, KVM_VCPU_MAX_FEATURES);
        set_bit(KVM_ARCH_FLAG_VCPU_FEATURES_CONFIGURED, &kvm->arch.flags);
        vcpu_set_flag(vcpu, VCPU_INITIALIZED);
 +      ret = 0;
  out_unlock:
        mutex_unlock(&kvm->arch.config_lock);
        return ret;
Simple merge
Simple merge
index 4df71290b676bd4028332be1f4cdb7326200d91a,abb1e8215ca8d7b236c607c11c9468a07a5cd3af..4b9d8fb393a8496da369a9f899cee00d4bab252b
@@@ -101,8 -101,10 +101,11 @@@ void kvm_vcpu_pmu_resync_el0(void)
  })
  
  u8 kvm_arm_pmu_get_pmuver_limit(void);
 +u64 kvm_pmu_evtyper_mask(struct kvm *kvm);
+ int kvm_arm_set_default_pmu(struct kvm *kvm);
+ u8 kvm_arm_pmu_get_max_counters(struct kvm *kvm);
  
+ u64 kvm_vcpu_read_pmcr(struct kvm_vcpu *vcpu);
  #else
  struct kvm_pmu {
  };
@@@ -173,12 -176,23 +177,27 @@@ static inline u8 kvm_arm_pmu_get_pmuver
  {
        return 0;
  }
 +static inline u64 kvm_pmu_evtyper_mask(struct kvm *kvm)
 +{
 +      return 0;
 +}
  static inline void kvm_vcpu_pmu_resync_el0(void) {}
  
+ static inline int kvm_arm_set_default_pmu(struct kvm *kvm)
+ {
+       return -ENODEV;
+ }
+ static inline u8 kvm_arm_pmu_get_max_counters(struct kvm *kvm)
+ {
+       return 0;
+ }
+ static inline u64 kvm_vcpu_read_pmcr(struct kvm_vcpu *vcpu)
+ {
+       return 0;
+ }
  #endif
  
  #endif
Simple merge