@@ -255,3 +255,19 @@ Returns:
Specifies the Profiling Buffer management interrupt number. The interrupt number
must be a PPI and the interrupt number must be the same for each VCPU. SPE
emulation requires an in-kernel vGIC implementation.
+
+5.2 ATTRIBUTE: KVM_ARM_VCPU_SPE_INIT
+-----------------------------------
+
+:Parameters: no additional parameter in kvm_device_attr.addr
+
+Returns:
+
+ ======= ============================================
+ -EBUSY SPE already initialized for this VCPU
+ -ENXIO SPE not supported or not properly configured
+ ======= ============================================
+
+Request initialization of the Statistical Profiling Extension for this VCPU.
+Must be done after initializaing the in-kernel irqchip and after setting the
+Profiling Buffer management interrupt number for the VCPU.
@@ -22,6 +22,7 @@ struct kvm_vcpu_spe {
};
int kvm_spe_vcpu_enable_spe(struct kvm_vcpu *vcpu);
+int kvm_spe_vcpu_first_run_init(struct kvm_vcpu *vcpu);
int kvm_spe_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr);
int kvm_spe_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr);
@@ -37,6 +38,11 @@ static inline int kvm_spe_vcpu_enable_spe(struct kvm_vcpu *vcpu)
return 0;
}
+static inline int kvm_spe_vcpu_first_run_init(struct kvm_vcpu *vcpu)
+{
+ return 0;
+}
+
static inline int kvm_spe_set_attr(struct kvm_vcpu *vcpu,
struct kvm_device_attr *attr)
{
@@ -370,6 +370,7 @@ struct kvm_arm_copy_mte_tags {
#define KVM_ARM_VCPU_PVTIME_IPA 0
#define KVM_ARM_VCPU_SPE_CTRL 3
#define KVM_ARM_VCPU_SPE_IRQ 0
+#define KVM_ARM_VCPU_SPE_INIT 1
/* KVM_IRQ_LINE irq field index values */
#define KVM_ARM_IRQ_VCPU2_SHIFT 28
@@ -652,6 +652,10 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
return ret;
ret = kvm_arm_pmu_v3_enable(vcpu);
+ if (ret)
+ return ret;
+
+ ret = kvm_spe_vcpu_first_run_init(vcpu);
/*
* Initialize traps for protected VMs.
@@ -45,6 +45,17 @@ int kvm_spe_vcpu_enable_spe(struct kvm_vcpu *vcpu)
return 0;
}
+int kvm_spe_vcpu_first_run_init(struct kvm_vcpu *vcpu)
+{
+ if (!kvm_vcpu_has_spe(vcpu))
+ return 0;
+
+ if (!vcpu->arch.spe.initialized)
+ return -EINVAL;
+
+ return 0;
+}
+
static bool kvm_vcpu_supports_spe(struct kvm_vcpu *vcpu)
{
if (!kvm_supports_spe())
@@ -104,6 +115,18 @@ int kvm_spe_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
vcpu->arch.spe.irq_num = irq;
return 0;
}
+ case KVM_ARM_VCPU_SPE_INIT:
+ if (!vcpu->arch.spe.irq_num)
+ return -ENXIO;
+
+ if (!vgic_initialized(vcpu->kvm))
+ return -ENXIO;
+
+ if (kvm_vgic_set_owner(vcpu, vcpu->arch.spe.irq_num, &vcpu->arch.spe))
+ return -ENXIO;
+
+ vcpu->arch.spe.initialized = true;
+ return 0;
}
return -ENXIO;
@@ -140,6 +163,7 @@ int kvm_spe_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
switch(attr->attr) {
case KVM_ARM_VCPU_SPE_IRQ:
+ case KVM_ARM_VCPU_SPE_INIT:
return 0;
}