mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-08-17 18:55:22 +00:00
KVM: arm64: Allow userspace to limit the number of PMU counters for EL2 VMs
As long as we had purely EL1 VMs, we could easily update the number of guest-visible counters by letting userspace write to PMCR_EL0.N. With VMs started at EL2, PMCR_EL1.N only reflects MDCR_EL2.HPMN, and we don't have a good way to limit it. For this purpose, introduce a new PMUv3 attribute that allows limiting the maximum number of counters. This requires the explicit selection of a PMU. Suggested-by: Oliver Upton <oliver.upton@linux.dev> Reviewed-by: Oliver Upton <oliver.upton@linux.dev> Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
parent
0224353343
commit
b7628c7973
@ -137,6 +137,30 @@ exit_reason = KVM_EXIT_FAIL_ENTRY and populate the fail_entry struct by setting
|
||||
hardare_entry_failure_reason field to KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED and
|
||||
the cpu field to the processor id.
|
||||
|
||||
1.5 ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_SET_NR_COUNTERS
|
||||
--------------------------------------------------
|
||||
|
||||
:Parameters: in kvm_device_attr.addr the address to an unsigned int
|
||||
representing the maximum value taken by PMCR_EL0.N
|
||||
|
||||
:Returns:
|
||||
|
||||
======= ====================================================
|
||||
-EBUSY PMUv3 already initialized, a VCPU has already run or
|
||||
an event filter has already been set
|
||||
-EFAULT Error accessing the value pointed to by addr
|
||||
-ENODEV PMUv3 not supported or GIC not initialized
|
||||
-EINVAL No PMUv3 explicitly selected, or value of N out of
|
||||
range
|
||||
======= ====================================================
|
||||
|
||||
Set the number of implemented event counters in the virtual PMU. This
|
||||
mandates that a PMU has explicitly been selected via
|
||||
KVM_ARM_VCPU_PMU_V3_SET_PMU, and will fail when no PMU has been
|
||||
explicitly selected, or the number of counters is out of range for the
|
||||
selected PMU. Selecting a new PMU cancels the effect of setting this
|
||||
attribute.
|
||||
|
||||
2. GROUP: KVM_ARM_VCPU_TIMER_CTRL
|
||||
=================================
|
||||
|
||||
|
@ -435,6 +435,7 @@ enum {
|
||||
#define KVM_ARM_VCPU_PMU_V3_INIT 1
|
||||
#define KVM_ARM_VCPU_PMU_V3_FILTER 2
|
||||
#define KVM_ARM_VCPU_PMU_V3_SET_PMU 3
|
||||
#define KVM_ARM_VCPU_PMU_V3_SET_NR_COUNTERS 4
|
||||
#define KVM_ARM_VCPU_TIMER_CTRL 1
|
||||
#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
|
||||
#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
|
||||
|
@ -1104,6 +1104,20 @@ static int kvm_arm_pmu_v3_set_pmu(struct kvm_vcpu *vcpu, int pmu_id)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kvm_arm_pmu_v3_set_nr_counters(struct kvm_vcpu *vcpu, unsigned int n)
|
||||
{
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
|
||||
if (!kvm->arch.arm_pmu)
|
||||
return -EINVAL;
|
||||
|
||||
if (n > kvm_arm_pmu_get_max_counters(kvm))
|
||||
return -EINVAL;
|
||||
|
||||
kvm_arm_set_nr_counters(kvm, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
|
||||
{
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
@ -1200,6 +1214,15 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
|
||||
|
||||
return kvm_arm_pmu_v3_set_pmu(vcpu, pmu_id);
|
||||
}
|
||||
case KVM_ARM_VCPU_PMU_V3_SET_NR_COUNTERS: {
|
||||
unsigned int __user *uaddr = (unsigned int __user *)(long)attr->addr;
|
||||
unsigned int n;
|
||||
|
||||
if (get_user(n, uaddr))
|
||||
return -EFAULT;
|
||||
|
||||
return kvm_arm_pmu_v3_set_nr_counters(vcpu, n);
|
||||
}
|
||||
case KVM_ARM_VCPU_PMU_V3_INIT:
|
||||
return kvm_arm_pmu_v3_init(vcpu);
|
||||
}
|
||||
@ -1238,6 +1261,7 @@ int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
|
||||
case KVM_ARM_VCPU_PMU_V3_INIT:
|
||||
case KVM_ARM_VCPU_PMU_V3_FILTER:
|
||||
case KVM_ARM_VCPU_PMU_V3_SET_PMU:
|
||||
case KVM_ARM_VCPU_PMU_V3_SET_NR_COUNTERS:
|
||||
if (kvm_vcpu_has_pmu(vcpu))
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user