[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] Ping: [PATCH] Extract some reusable vGIC code
From: |
Pavel Fedin |
Subject: |
[Qemu-devel] Ping: [PATCH] Extract some reusable vGIC code |
Date: |
Thu, 04 Jun 2015 10:56:38 +0300 |
Hello! More than week ago i've done this patch but it seems to be lost. It is
a part of
my vGICv3 project and i decided to post it separately because vGICv3 code
itself waits for
Shlomo's patches.
Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia
> -----Original Message-----
> From: address@hidden [mailto:qemu-devel-
> address@hidden On Behalf Of Pavel Fedin
> Sent: Friday, May 22, 2015 5:39 PM
> To: address@hidden
> Subject: [Qemu-devel] [PATCH] Extract some reusable vGIC code
>
> These functions are useful also for vGICv3 implementation. Make them
> accessible from
> within other modules.
> Actually kvm_dist_get() and kvm_dist_put() could also be made reusable, but
> they would
> require two extra parameters (s->dev_fd and s->num_cpu) as well as lots of
> typecasts of
> 's' to DeviceState * and back to GICState *. This makes the code very ugly so
> i decided
to
> stop at this point. I tried also an approach with making a base class for al
> possible
> GICs, but it would contain only three variables (dev_fd, cpu_num and
> irq_num), and
> accessing them through the rest of the code would be again tedious (either
> ugly casts or
> another qemu-style object pointer). So i disliked it too.
> I do not post new vGICv3 implementation right now because it relies on
> Shlomo's GICv3
> code and waits for it to be integrated.
>
> Signed-off-by: Pavel Fedin <address@hidden>
> ---
> hw/intc/arm_gic_kvm.c | 84
> ++++++++++++++++++++++++---------------------------
> hw/intc/vgic_common.h | 43 ++++++++++++++++++++++++++
> 2 files changed, 82 insertions(+), 45 deletions(-)
> create mode 100644 hw/intc/vgic_common.h
>
> diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
> index 2cb7d25..d1a4f6a 100644
> --- a/hw/intc/arm_gic_kvm.c
> +++ b/hw/intc/arm_gic_kvm.c
> @@ -23,6 +23,7 @@
> #include "sysemu/kvm.h"
> #include "kvm_arm.h"
> #include "gic_internal.h"
> +#include "vgic_common.h"
>
> //#define DEBUG_GIC_KVM
>
> @@ -52,7 +53,7 @@ typedef struct KVMARMGICClass {
> void (*parent_reset)(DeviceState *dev);
> } KVMARMGICClass;
>
> -static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
> +void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level)
> {
> /* Meaning of the 'irq' parameter:
> * [0..N-1] : external interrupts
> @@ -63,10 +64,9 @@ static void kvm_arm_gic_set_irq(void *opaque, int irq, int
> level)
> * has separate fields in the irq number for type,
> * CPU number and interrupt number.
> */
> - GICState *s = (GICState *)opaque;
> int kvm_irq, irqtype, cpu;
>
> - if (irq < (s->num_irq - GIC_INTERNAL)) {
> + if (irq < (num_irq - GIC_INTERNAL)) {
> /* External interrupt. The kernel numbers these like the GIC
> * hardware, with external interrupt IDs starting after the
> * internal ones.
> @@ -77,7 +77,7 @@ static void kvm_arm_gic_set_irq(void *opaque, int irq, int
> level)
> } else {
> /* Internal interrupt: decode into (cpu, interrupt id) */
> irqtype = KVM_ARM_IRQ_TYPE_PPI;
> - irq -= (s->num_irq - GIC_INTERNAL);
> + irq -= (num_irq - GIC_INTERNAL);
> cpu = irq / GIC_INTERNAL;
> irq %= GIC_INTERNAL;
> }
> @@ -87,12 +87,19 @@ static void kvm_arm_gic_set_irq(void *opaque, int irq,
> int level)
> kvm_set_irq(kvm_state, kvm_irq, !!level);
> }
>
> +static void kvm_arm_gicv2_set_irq(void *opaque, int irq, int level)
> +{
> + GICState *s = (GICState *)opaque;
> +
> + kvm_arm_gic_set_irq(s->num_irq, irq, level);
> +}
> +
> static bool kvm_arm_gic_can_save_restore(GICState *s)
> {
> return s->dev_fd >= 0;
> }
>
> -static bool kvm_gic_supports_attr(GICState *s, int group, int attrnum)
> +bool kvm_gic_supports_attr(int dev_fd, int group, int attrnum)
> {
> struct kvm_device_attr attr = {
> .group = group,
> @@ -100,14 +107,14 @@ static bool kvm_gic_supports_attr(GICState *s, int
> group, int
> attrnum)
> .flags = 0,
> };
>
> - if (s->dev_fd == -1) {
> + if (dev_fd == -1) {
> return false;
> }
>
> - return kvm_device_ioctl(s->dev_fd, KVM_HAS_DEVICE_ATTR, &attr) == 0;
> + return kvm_device_ioctl(dev_fd, KVM_HAS_DEVICE_ATTR, &attr) == 0;
> }
>
> -static void kvm_gic_access(GICState *s, int group, int offset,
> +void kvm_gic_access(int dev_fd, int group, int offset,
> int cpu, uint32_t *val, bool write)
> {
> struct kvm_device_attr attr;
> @@ -130,7 +137,7 @@ static void kvm_gic_access(GICState *s, int group, int
> offset,
> type = KVM_GET_DEVICE_ATTR;
> }
>
> - err = kvm_device_ioctl(s->dev_fd, type, &attr);
> + err = kvm_device_ioctl(dev_fd, type, &attr);
> if (err < 0) {
> fprintf(stderr, "KVM_{SET/GET}_DEVICE_ATTR failed: %s\n",
> strerror(-err));
> @@ -138,20 +145,6 @@ static void kvm_gic_access(GICState *s, int group, int
> offset,
> }
> }
>
> -static void kvm_gicd_access(GICState *s, int offset, int cpu,
> - uint32_t *val, bool write)
> -{
> - kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
> - offset, cpu, val, write);
> -}
> -
> -static void kvm_gicc_access(GICState *s, int offset, int cpu,
> - uint32_t *val, bool write)
> -{
> - kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
> - offset, cpu, val, write);
> -}
> -
> #define for_each_irq_reg(_ctr, _max_irq, _field_width) \
> for (_ctr = 0; _ctr < ((_max_irq) / (32 / (_field_width))); _ctr++)
>
> @@ -291,7 +284,7 @@ static void kvm_dist_get(GICState *s, uint32_t offset,
> int width,
> irq = i * regsz;
> cpu = 0;
> while ((cpu < s->num_cpu && irq < GIC_INTERNAL) || cpu == 0) {
> - kvm_gicd_access(s, offset, cpu, ®, false);
> + kvm_gicd_access(s->dev_fd, offset, cpu, ®, false);
> for (j = 0; j < regsz; j++) {
> field = extract32(reg, j * width, width);
> translate_fn(s, irq + j, cpu, &field, false);
> @@ -324,7 +317,7 @@ static void kvm_dist_put(GICState *s, uint32_t offset,
> int width,
> translate_fn(s, irq + j, cpu, &field, true);
> reg = deposit32(reg, j * width, width, field);
> }
> - kvm_gicd_access(s, offset, cpu, ®, true);
> + kvm_gicd_access(s->dev_fd, offset, cpu, ®, true);
>
> cpu++;
> }
> @@ -355,10 +348,10 @@ static void kvm_arm_gic_put(GICState *s)
>
> /* s->ctlr -> GICD_CTLR */
> reg = s->ctlr;
> - kvm_gicd_access(s, 0x0, 0, ®, true);
> + kvm_gicd_access(s->dev_fd, 0x0, 0, ®, true);
>
> /* Sanity checking on GICD_TYPER and s->num_irq, s->num_cpu */
> - kvm_gicd_access(s, 0x4, 0, ®, false);
> + kvm_gicd_access(s->dev_fd, 0x4, 0, ®, false);
> num_irq = ((reg & 0x1f) + 1) * 32;
> num_cpu = ((reg & 0xe0) >> 5) + 1;
>
> @@ -416,24 +409,24 @@ static void kvm_arm_gic_put(GICState *s)
> for (cpu = 0; cpu < s->num_cpu; cpu++) {
> /* s->cpu_ctlr[cpu] -> GICC_CTLR */
> reg = s->cpu_ctlr[cpu];
> - kvm_gicc_access(s, 0x00, cpu, ®, true);
> + kvm_gicc_access(s->dev_fd, 0x00, cpu, ®, true);
>
> /* s->priority_mask[cpu] -> GICC_PMR */
> reg = (s->priority_mask[cpu] & 0xff);
> - kvm_gicc_access(s, 0x04, cpu, ®, true);
> + kvm_gicc_access(s->dev_fd, 0x04, cpu, ®, true);
>
> /* s->bpr[cpu] -> GICC_BPR */
> reg = (s->bpr[cpu] & 0x7);
> - kvm_gicc_access(s, 0x08, cpu, ®, true);
> + kvm_gicc_access(s->dev_fd, 0x08, cpu, ®, true);
>
> /* s->abpr[cpu] -> GICC_ABPR */
> reg = (s->abpr[cpu] & 0x7);
> - kvm_gicc_access(s, 0x1c, cpu, ®, true);
> + kvm_gicc_access(s->dev_fd, 0x1c, cpu, ®, true);
>
> /* s->apr[n][cpu] -> GICC_APRn */
> for (i = 0; i < 4; i++) {
> reg = s->apr[i][cpu];
> - kvm_gicc_access(s, 0xd0 + i * 4, cpu, ®, true);
> + kvm_gicc_access(s->dev_fd, 0xd0 + i * 4, cpu, ®, true);
> }
> }
> }
> @@ -454,11 +447,11 @@ static void kvm_arm_gic_get(GICState *s)
> */
>
> /* GICD_CTLR -> s->ctlr */
> - kvm_gicd_access(s, 0x0, 0, ®, false);
> + kvm_gicd_access(s->dev_fd, 0x0, 0, ®, false);
> s->ctlr = reg;
>
> /* Sanity checking on GICD_TYPER -> s->num_irq, s->num_cpu */
> - kvm_gicd_access(s, 0x4, 0, ®, false);
> + kvm_gicd_access(s->dev_fd, 0x4, 0, ®, false);
> s->num_irq = ((reg & 0x1f) + 1) * 32;
> s->num_cpu = ((reg & 0xe0) >> 5) + 1;
>
> @@ -469,7 +462,7 @@ static void kvm_arm_gic_get(GICState *s)
> }
>
> /* GICD_IIDR -> ? */
> - kvm_gicd_access(s, 0x8, 0, ®, false);
> + kvm_gicd_access(s->dev_fd, 0x8, 0, ®, false);
>
> /* Clear all the IRQ settings */
> for (i = 0; i < s->num_irq; i++) {
> @@ -507,24 +500,24 @@ static void kvm_arm_gic_get(GICState *s)
>
> for (cpu = 0; cpu < s->num_cpu; cpu++) {
> /* GICC_CTLR -> s->cpu_ctlr[cpu] */
> - kvm_gicc_access(s, 0x00, cpu, ®, false);
> + kvm_gicc_access(s->dev_fd, 0x00, cpu, ®, false);
> s->cpu_ctlr[cpu] = reg;
>
> /* GICC_PMR -> s->priority_mask[cpu] */
> - kvm_gicc_access(s, 0x04, cpu, ®, false);
> + kvm_gicc_access(s->dev_fd, 0x04, cpu, ®, false);
> s->priority_mask[cpu] = (reg & 0xff);
>
> /* GICC_BPR -> s->bpr[cpu] */
> - kvm_gicc_access(s, 0x08, cpu, ®, false);
> + kvm_gicc_access(s->dev_fd, 0x08, cpu, ®, false);
> s->bpr[cpu] = (reg & 0x7);
>
> /* GICC_ABPR -> s->abpr[cpu] */
> - kvm_gicc_access(s, 0x1c, cpu, ®, false);
> + kvm_gicc_access(s->dev_fd, 0x1c, cpu, ®, false);
> s->abpr[cpu] = (reg & 0x7);
>
> /* GICC_APRn -> s->apr[n][cpu] */
> for (i = 0; i < 4; i++) {
> - kvm_gicc_access(s, 0xd0 + i * 4, cpu, ®, false);
> + kvm_gicc_access(s->dev_fd, 0xd0 + i * 4, cpu, ®, false);
> s->apr[i][cpu] = reg;
> }
> }
> @@ -569,7 +562,7 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error
> **errp)
> * ...
> */
> i += (GIC_INTERNAL * s->num_cpu);
> - qdev_init_gpio_in(dev, kvm_arm_gic_set_irq, i);
> + qdev_init_gpio_in(dev, kvm_arm_gicv2_set_irq, i);
> /* We never use our outbound IRQ/FIQ lines but provide them so that
> * we maintain the same interface as the non-KVM GIC.
> */
> @@ -590,15 +583,16 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error
> **errp)
> return;
> }
>
> - if (kvm_gic_supports_attr(s, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0)) {
> + if (kvm_gic_supports_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0)) {
> uint32_t numirqs = s->num_irq;
> - kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, 0, &numirqs, 1);
> + kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, 0,
> + &numirqs, 1);
> }
>
> /* Tell the kernel to complete VGIC initialization now */
> - if (kvm_gic_supports_attr(s, KVM_DEV_ARM_VGIC_GRP_CTRL,
> + if (kvm_gic_supports_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
> KVM_DEV_ARM_VGIC_CTRL_INIT)) {
> - kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_CTRL,
> + kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
> KVM_DEV_ARM_VGIC_CTRL_INIT, 0, 0, 1);
> }
>
> diff --git a/hw/intc/vgic_common.h b/hw/intc/vgic_common.h
> new file mode 100644
> index 0000000..67241d3
> --- /dev/null
> +++ b/hw/intc/vgic_common.h
> @@ -0,0 +1,43 @@
> +/*
> + * ARM KVM vGIC utility functions
> + *
> + * Copyright (c) 2015 Samsung Electronics
> + * Written by Pavel Fedin
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef QEMU_ARM_VGIC_COMMON_H
> +#define QEMU_ARM_VGIC_COMMON_H
> +
> +void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level);
> +bool kvm_gic_supports_attr(int dev_fd, int group, int attrnum);
> +void kvm_gic_access(int dev_fd, int group, int offset, int cpu,
> + uint32_t *val, bool write);
> +
> +static inline void kvm_gicd_access(int dev_fd, int offset, int cpu,
> + uint32_t *val, bool write)
> +{
> + kvm_gic_access(dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
> + offset, cpu, val, write);
> +}
> +
> +static inline void kvm_gicc_access(int dev_fd, int offset, int cpu,
> + uint32_t *val, bool write)
> +{
> + kvm_gic_access(dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
> + offset, cpu, val, write);
> +}
> +
> +#endif
> --
> 1.9.5.msysgit.0
>
- [Qemu-devel] Ping: [PATCH] Extract some reusable vGIC code,
Pavel Fedin <=