summaryrefslogtreecommitdiff
path: root/target-arm
diff options
context:
space:
mode:
Diffstat (limited to 'target-arm')
-rw-r--r--target-arm/kvm32.c6
-rw-r--r--target-arm/kvm64.c41
-rw-r--r--target-arm/kvm_arm.h7
3 files changed, 54 insertions, 0 deletions
diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c
index c03e3e526a..c35c676e14 100644
--- a/target-arm/kvm32.c
+++ b/target-arm/kvm32.c
@@ -522,3 +522,9 @@ bool kvm_arm_hw_debug_active(CPUState *cs)
{
return false;
}
+
+int kvm_arm_pmu_create(CPUState *cs, int irq)
+{
+ qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+ return 0;
+}
diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c
index 75383c84dd..2d6a310ebb 100644
--- a/target-arm/kvm64.c
+++ b/target-arm/kvm64.c
@@ -382,6 +382,47 @@ static CPUWatchpoint *find_hw_watchpoint(CPUState *cpu, target_ulong addr)
return NULL;
}
+static bool kvm_arm_pmu_support_ctrl(CPUState *cs, struct kvm_device_attr *attr)
+{
+ return kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr) == 0;
+}
+
+int kvm_arm_pmu_create(CPUState *cs, int irq)
+{
+ int err;
+
+ struct kvm_device_attr attr = {
+ .group = KVM_ARM_VCPU_PMU_V3_CTRL,
+ .addr = (intptr_t)&irq,
+ .attr = KVM_ARM_VCPU_PMU_V3_IRQ,
+ .flags = 0,
+ };
+
+ if (!kvm_arm_pmu_support_ctrl(cs, &attr)) {
+ return 0;
+ }
+
+ err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, &attr);
+ if (err < 0) {
+ fprintf(stderr, "KVM_SET_DEVICE_ATTR failed: %s\n",
+ strerror(-err));
+ abort();
+ }
+
+ attr.group = KVM_ARM_VCPU_PMU_V3_CTRL;
+ attr.attr = KVM_ARM_VCPU_PMU_V3_INIT;
+ attr.addr = 0;
+ attr.flags = 0;
+
+ err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, &attr);
+ if (err < 0) {
+ fprintf(stderr, "KVM_SET_DEVICE_ATTR failed: %s\n",
+ strerror(-err));
+ abort();
+ }
+
+ return 1;
+}
static inline void set_feature(uint64_t *features, int feature)
{
diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
index 345233c18b..a4193684a8 100644
--- a/target-arm/kvm_arm.h
+++ b/target-arm/kvm_arm.h
@@ -194,6 +194,8 @@ int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
int kvm_arm_vgic_probe(void);
+int kvm_arm_pmu_create(CPUState *cs, int irq);
+
#else
static inline int kvm_arm_vgic_probe(void)
@@ -201,6 +203,11 @@ static inline int kvm_arm_vgic_probe(void)
return 0;
}
+static inline int kvm_arm_pmu_create(CPUState *cs, int irq)
+{
+ return 0;
+}
+
#endif
static inline const char *gic_class_name(void)