From: christoffer.dall@linaro.org (Christoffer Dall)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v11 21/21] KVM: ARM64: Add a new vcpu device control group for PMUv3
Date: Mon, 8 Feb 2016 13:52:47 +0100 [thread overview]
Message-ID: <20160208125247.GG620@cbox> (raw)
In-Reply-To: <1454656456-11640-22-git-send-email-zhaoshenglong@huawei.com>
On Fri, Feb 05, 2016 at 03:14:16PM +0800, Shannon Zhao wrote:
> From: Shannon Zhao <shannon.zhao@linaro.org>
>
> To configure the virtual PMUv3 overflow interrupt number, we use the
> vcpu kvm_device ioctl, encapsulating the KVM_ARM_VCPU_PMU_V3_IRQ
> attribute within the KVM_ARM_VCPU_PMU_V3_CTRL group.
>
> After configuring the PMUv3, call the vcpu ioctl with attribute
> KVM_ARM_VCPU_PMU_V3_INIT to initialize the PMUv3.
>
> Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
> Acked-by: Peter Maydell <peter.maydell@linaro.org>
> Reviewed-by: Andrew Jones <drjones@redhat.com>
> ---
> CC: Peter Maydell <peter.maydell@linaro.org>
> ---
> Documentation/virtual/kvm/devices/vcpu.txt | 24 ++++++
> arch/arm/include/asm/kvm_host.h | 15 ++++
> arch/arm/kvm/arm.c | 3 +
> arch/arm64/include/asm/kvm_host.h | 6 ++
> arch/arm64/include/uapi/asm/kvm.h | 5 ++
> arch/arm64/kvm/guest.c | 51 ++++++++++++
> include/kvm/arm_pmu.h | 23 ++++++
> virt/kvm/arm/pmu.c | 128 +++++++++++++++++++++++++++++
> 8 files changed, 255 insertions(+)
>
> diff --git a/Documentation/virtual/kvm/devices/vcpu.txt b/Documentation/virtual/kvm/devices/vcpu.txt
> index 3cc59c5..d626237 100644
> --- a/Documentation/virtual/kvm/devices/vcpu.txt
> +++ b/Documentation/virtual/kvm/devices/vcpu.txt
> @@ -6,3 +6,27 @@ KVM_GET_DEVICE_ATTR, and KVM_HAS_DEVICE_ATTR. The interface uses the same struct
> kvm_device_attr as other devices, but targets VCPU-wide settings and controls.
>
> The groups and attributes per virtual cpu, if any, are architecture specific.
> +
> +1. GROUP: KVM_ARM_VCPU_PMU_V3_CTRL
> +Architectures: ARM64
> +
> +1.1. ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_IRQ
> +Parameters: in kvm_device_attr.addr the address for PMU overflow interrupt
so kvm_device_attr.addr is a pointer to an unsigned long or an int, or?
> +Returns: -EBUSY: The PMU overflow interrupt is already set
> + -ENXIO: The overflow interrupt not set when attempting to get it
> + -ENODEV: PMUv3 not supported
> + -EINVAL: Invalid PMU overflow interrupt number supplied
> +
> +A value describing the PMUv3 (Performance Monitor Unit v3) overflow interrupt
> +number for this vcpu. This interrupt could be a PPI or SPI, but the interrupt
> +type must be same for each vcpu. As a PPI, the interrupt number is same for all
nit: s/is same/is the same/
> +vcpus, while as an SPI it must be different for each vcpu.
nit: s/it must be different for each vcpu/
it must be a separate number per vcpu/
> +
> +1.2 ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_INIT
> +Parameters: no additional parameter in kvm_device_attr.addr
> +Returns: -ENODEV: PMUv3 not supported
> + -ENXIO: PMUv3 not properly configured as required prior to calling this
> + attribute
> + -EBUSY: PMUv3 already initialized
> +
> +Request the initialization of the PMUv3.
> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> index f9f2779..6dd0992 100644
> --- a/arch/arm/include/asm/kvm_host.h
> +++ b/arch/arm/include/asm/kvm_host.h
> @@ -242,5 +242,20 @@ static inline void kvm_arm_init_debug(void) {}
> static inline void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) {}
> static inline void kvm_arm_clear_debug(struct kvm_vcpu *vcpu) {}
> static inline void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu) {}
> +static inline int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr)
> +{
> + return -ENXIO;
> +}
> +static inline int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr)
> +{
> + return -ENXIO;
> +}
> +static inline int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr)
> +{
> + return -ENXIO;
> +}
>
> #endif /* __ARM_KVM_HOST_H__ */
> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> index 34d7395..dc8644f 100644
> --- a/arch/arm/kvm/arm.c
> +++ b/arch/arm/kvm/arm.c
> @@ -833,6 +833,7 @@ static int kvm_arm_vcpu_set_attr(struct kvm_vcpu *vcpu,
>
> switch (attr->group) {
> default:
> + ret = kvm_arm_vcpu_arch_set_attr(vcpu, attr);
> break;
> }
>
> @@ -846,6 +847,7 @@ static int kvm_arm_vcpu_get_attr(struct kvm_vcpu *vcpu,
>
> switch (attr->group) {
> default:
> + ret = kvm_arm_vcpu_arch_get_attr(vcpu, attr);
> break;
> }
>
> @@ -859,6 +861,7 @@ static int kvm_arm_vcpu_has_attr(struct kvm_vcpu *vcpu,
>
> switch (attr->group) {
> default:
> + ret = kvm_arm_vcpu_arch_has_attr(vcpu, attr);
> break;
> }
>
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index cb220b7..a855a30 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -359,5 +359,11 @@ void kvm_arm_init_debug(void);
> void kvm_arm_setup_debug(struct kvm_vcpu *vcpu);
> void kvm_arm_clear_debug(struct kvm_vcpu *vcpu);
> void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu);
> +int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr);
> +int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr);
> +int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr);
>
> #endif /* __ARM64_KVM_HOST_H__ */
> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index 6aedbe3..f209ea1 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -205,6 +205,11 @@ struct kvm_arch_memory_slot {
> #define KVM_DEV_ARM_VGIC_GRP_CTRL 4
> #define KVM_DEV_ARM_VGIC_CTRL_INIT 0
>
> +/* Device Control API on vcpu fd */
> +#define KVM_ARM_VCPU_PMU_V3_CTRL 0
> +#define KVM_ARM_VCPU_PMU_V3_IRQ 0
> +#define KVM_ARM_VCPU_PMU_V3_INIT 1
> +
> /* KVM_IRQ_LINE irq field index values */
> #define KVM_ARM_IRQ_TYPE_SHIFT 24
> #define KVM_ARM_IRQ_TYPE_MASK 0xff
> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index fcb7788..dbe45c3 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -380,3 +380,54 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
> }
> return 0;
> }
> +
> +int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr)
> +{
> + int ret;
> +
> + switch (attr->group) {
> + case KVM_ARM_VCPU_PMU_V3_CTRL:
> + ret = kvm_arm_pmu_v3_set_attr(vcpu, attr);
> + break;
> + default:
> + ret = -ENXIO;
> + break;
> + }
> +
> + return ret;
> +}
> +
> +int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr)
> +{
> + int ret;
> +
> + switch (attr->group) {
> + case KVM_ARM_VCPU_PMU_V3_CTRL:
> + ret = kvm_arm_pmu_v3_get_attr(vcpu, attr);
> + break;
> + default:
> + ret = -ENXIO;
> + break;
> + }
> +
> + return ret;
> +}
> +
> +int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr)
> +{
> + int ret;
> +
> + switch (attr->group) {
> + case KVM_ARM_VCPU_PMU_V3_CTRL:
> + ret = kvm_arm_pmu_v3_has_attr(vcpu, attr);
> + break;
> + default:
> + ret = -ENXIO;
> + break;
> + }
> +
> + return ret;
> +}
> diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
> index 5f86e1d..f09abf6 100644
> --- a/include/kvm/arm_pmu.h
> +++ b/include/kvm/arm_pmu.h
> @@ -38,6 +38,7 @@ struct kvm_pmu {
> };
>
> #define kvm_arm_pmu_v3_ready(v) ((v)->arch.pmu.ready)
> +#define kvm_arm_pmu_irq_initialized(v) ((v)->arch.pmu.irq_num >= VGIC_NR_SGIS)
> u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx);
> void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
> u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu);
> @@ -52,11 +53,18 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val);
> void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data,
> u64 select_idx);
> bool kvm_arm_support_pmu_v3(void);
> +int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr);
> +int kvm_arm_pmu_v3_get_attr(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr);
> +int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr);
> #else
> struct kvm_pmu {
> };
>
> #define kvm_arm_pmu_v3_ready(v) (false)
> +#define kvm_arm_pmu_irq_initialized(v) (false)
> static inline u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu,
> u64 select_idx)
> {
> @@ -79,6 +87,21 @@ static inline void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val) {}
> static inline void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu,
> u64 data, u64 select_idx) {}
> static inline bool kvm_arm_support_pmu_v3(void) { return false; }
> +static inline int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr)
> +{
> + return -ENXIO;
> +}
> +static inline int kvm_arm_pmu_v3_get_attr(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr)
> +{
> + return -ENXIO;
> +}
> +static inline int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr)
> +{
> + return -ENXIO;
> +}
> #endif
>
> #endif
> diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
> index 2467d62..06b7cb3 100644
> --- a/virt/kvm/arm/pmu.c
> +++ b/virt/kvm/arm/pmu.c
> @@ -19,6 +19,7 @@
> #include <linux/kvm.h>
> #include <linux/kvm_host.h>
> #include <linux/perf_event.h>
> +#include <linux/uaccess.h>
> #include <asm/kvm_emulate.h>
> #include <kvm/arm_pmu.h>
> #include <kvm/arm_vgic.h>
> @@ -393,3 +394,130 @@ bool kvm_arm_support_pmu_v3(void)
> */
> return (perf_num_counters() > 0);
> }
> +
> +static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
> +{
> + if (!kvm_arm_support_pmu_v3())
> + return -ENODEV;
> +
> + if (!test_bit(KVM_ARM_VCPU_PMU_V3, vcpu->arch.features) ||
> + !kvm_arm_pmu_irq_initialized(vcpu))
> + return -ENXIO;
> +
> + if (kvm_arm_pmu_v3_ready(vcpu))
> + return -EBUSY;
> +
> + kvm_pmu_vcpu_reset(vcpu);
> + vcpu->arch.pmu.ready = true;
> +
> + return 0;
> +}
> +
> +static int kvm_arm_pmu_irq_access(struct kvm_vcpu *vcpu,
> + struct kvm_device_attr *attr,
> + int *irq, bool is_set)
> +{
> + if (!is_set) {
> + if (!kvm_arm_pmu_irq_initialized(vcpu))
> + return -ENXIO;
> +
> + *irq = vcpu->arch.pmu.irq_num;
> + } else {
> + if (kvm_arm_pmu_irq_initialized(vcpu))
> + return -EBUSY;
> +
> + kvm_debug("Set kvm ARM PMU irq: %d\n", *irq);
> + vcpu->arch.pmu.irq_num = *irq;
> + }
> +
> + return 0;
> +}
are you going to be reusing this function in later patches? If not, I
don't see the benefit of having this indirection over simply including
it directly in the callers below.
> +
> +static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
> +{
> + int i;
> + struct kvm_vcpu *vcpu;
> +
> + kvm_for_each_vcpu(i, vcpu, kvm) {
> + if (!kvm_arm_pmu_irq_initialized(vcpu))
> + continue;
> +
> + if (is_ppi) {
> + if (vcpu->arch.pmu.irq_num != irq)
> + return false;
> + } else {
> + if (vcpu->arch.pmu.irq_num == irq)
> + return false;
> + }
> + }
> +
> + return true;
> +}
> +
> +
> +int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
> +{
> + switch (attr->attr) {
> + case KVM_ARM_VCPU_PMU_V3_IRQ: {
> + int __user *uaddr = (int __user *)(long)attr->addr;
> + int reg;
> +
> + if (!test_bit(KVM_ARM_VCPU_PMU_V3, vcpu->arch.features))
> + return -ENODEV;
> +
> + if (get_user(reg, uaddr))
> + return -EFAULT;
> +
> + /*
> + * The PMU overflow interrupt could be a PPI or SPI, but for one
> + * VM the interrupt type must be same for each vcpu. As a PPI,
> + * the interrupt number is same for all vcpus, while as an SPI
> + * it must be different for each vcpu.
> + */
> + if (reg < VGIC_NR_SGIS || reg >= vcpu->kvm->arch.vgic.nr_irqs ||
> + !irq_is_valid(vcpu->kvm, reg, reg < VGIC_NR_PRIVATE_IRQS))
> + return -EINVAL;
> +
> + return kvm_arm_pmu_irq_access(vcpu, attr, ®, true);
> + }
> + case KVM_ARM_VCPU_PMU_V3_INIT:
> + return kvm_arm_pmu_v3_init(vcpu);
> + }
> +
> + return -ENXIO;
> +}
> +
> +int kvm_arm_pmu_v3_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
> +{
> + int ret;
> +
> + switch (attr->attr) {
> + case KVM_ARM_VCPU_PMU_V3_IRQ: {
> + int __user *uaddr = (int __user *)(long)attr->addr;
> + int reg = -1;
> +
> + if (!test_bit(KVM_ARM_VCPU_PMU_V3, vcpu->arch.features))
> + return -ENODEV;
> +
> + ret = kvm_arm_pmu_irq_access(vcpu, attr, ®, false);
> + if (ret)
> + return ret;
> + return put_user(reg, uaddr);
> + }
> + }
> +
> + return -ENXIO;
> +}
> +
> +int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
> +{
> + switch (attr->attr) {
> + case KVM_ARM_VCPU_PMU_V3_IRQ:
> + case KVM_ARM_VCPU_PMU_V3_INIT:
> + if (kvm_arm_support_pmu_v3() &&
> + test_bit(KVM_ARM_VCPU_PMU_V3, vcpu->arch.features))
> + return 0;
> + }
> +
> + return -ENXIO;
> +}
> --
> 2.0.4
>
>
Besides the style and wording comments:
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
next prev parent reply other threads:[~2016-02-08 12:52 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-05 7:13 [PATCH v11 00/21] KVM: ARM64: Add guest PMU support Shannon Zhao
2016-02-05 7:13 ` [PATCH v11 01/21] ARM64: Move PMU register related defines to asm/pmu.h Shannon Zhao
2016-02-05 7:13 ` [PATCH v11 02/21] KVM: ARM64: Define PMU data structure for each vcpu Shannon Zhao
2016-02-05 7:13 ` [PATCH v11 03/21] KVM: ARM64: Add offset defines for PMU registers Shannon Zhao
2016-02-05 7:13 ` [PATCH v11 04/21] KVM: ARM64: Add access handler for PMCR register Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 05/21] KVM: ARM64: Add access handler for PMSELR register Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 06/21] KVM: ARM64: Add access handler for PMCEID0 and PMCEID1 register Shannon Zhao
2016-02-08 12:09 ` Christoffer Dall
2016-02-20 13:15 ` Shannon Zhao
2016-02-20 13:30 ` Peter Maydell
2016-02-20 13:34 ` Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 07/21] KVM: ARM64: PMU: Add perf event map and introduce perf event creating function Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 08/21] KVM: ARM64: Add access handler for event type register Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 09/21] KVM: ARM64: Add access handler for event counter register Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 10/21] KVM: ARM64: Add access handler for PMCNTENSET and PMCNTENCLR register Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 11/21] KVM: ARM64: Add access handler for PMINTENSET and PMINTENCLR register Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 12/21] KVM: ARM64: Add access handler for PMOVSSET and PMOVSCLR register Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 13/21] KVM: ARM64: Add access handler for PMSWINC register Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 14/21] KVM: ARM64: Add helper to handle PMCR register bits Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 15/21] KVM: ARM64: Add access handler for PMUSERENR register Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 16/21] KVM: ARM64: Add PMU overflow interrupt routing Shannon Zhao
2016-02-08 12:26 ` Christoffer Dall
2016-02-20 13:32 ` Shannon Zhao
2016-02-22 7:35 ` Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 17/21] KVM: ARM64: Reset PMU state when resetting vcpu Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 18/21] KVM: ARM64: Free perf event of PMU when destroying vcpu Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 19/21] KVM: ARM64: Add a new feature bit for PMUv3 Shannon Zhao
2016-02-08 12:29 ` Christoffer Dall
2016-02-22 7:43 ` Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 20/21] KVM: ARM: Introduce per-vcpu kvm device controls Shannon Zhao
2016-02-08 12:40 ` Christoffer Dall
2016-02-20 13:38 ` Shannon Zhao
2016-02-05 7:14 ` [PATCH v11 21/21] KVM: ARM64: Add a new vcpu device control group for PMUv3 Shannon Zhao
2016-02-08 12:52 ` Christoffer Dall [this message]
2016-02-22 7:45 ` Shannon Zhao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160208125247.GG620@cbox \
--to=christoffer.dall@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).