qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v10 2/5] intc/gic: Extract some reusable vGIC co


From: Eric Auger
Subject: Re: [Qemu-devel] [PATCH v10 2/5] intc/gic: Extract some reusable vGIC code
Date: Tue, 18 Aug 2015 17:53:54 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.8.0

Hi Pavel,
On 08/18/2015 03:33 PM, Pavel Fedin wrote:
> These functions are useful also for vGICv3 implementation. Make them 
> accessible
> from within other modules.

I think it would be worth justifying the changes in signature:
removal of GICState* due to the introduction of  GICV3State and also
justify replacement of uint32_t *val into void*.
> 
> 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 all 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 qemu-style
> separate object pointer). So i disliked it too.
I would put the above paragraph below "---"
> 
> Signed-off-by: Pavel Fedin <address@hidden>
> ---
>  hw/intc/arm_gic_kvm.c | 42 +++++++++++++++++----------------------
>  hw/intc/vgic_common.h | 55 
> +++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 73 insertions(+), 24 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 e5d0f67..0c71ef8 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,6 +87,13 @@ 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)
inline?
> +{
> +    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;
> @@ -107,8 +114,8 @@ static bool kvm_gic_supports_attr(GICState *s, int group, 
> int attrnum)
>      return kvm_device_ioctl(s->dev_fd, KVM_HAS_DEVICE_ATTR, &attr) == 0;
>  }
>  
> -static void kvm_gic_access(GICState *s, int group, int offset,
> -                                   int cpu, uint32_t *val, bool write)
> +void kvm_gic_access(int dev_fd, int group, int offset,
> +                    int cpu, void *val, bool write)
>  {
>      struct kvm_device_attr attr;
>      int type;
> @@ -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++)
>  
> @@ -559,7 +552,7 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error 
> **errp)
>          return;
>      }
>  
> -    gic_init_irqs_and_mmio(s, kvm_arm_gic_set_irq, NULL);
> +    gic_init_irqs_and_mmio(s, kvm_arm_gicv2_set_irq, NULL);
>  
>      for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
>          qemu_irq irq = qdev_get_gpio_in(dev, i);
> @@ -578,13 +571,14 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error 
> **errp)
>  
>      if (kvm_gic_supports_attr(s, 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,
>                                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..130ea64
> --- /dev/null
> +++ b/hw/intc/vgic_common.h
> @@ -0,0 +1,55 @@
> +/*
> + * 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
> +
> +/**
> + * kvm_arm_gic_set_irq - Send an IRQ to the in-kernel vGIC
> + * @num_irq: Total number of IRQs configured for the GIC instance
> + * @irq: qemu internal IRQ line number:
> + *  [0..N-1] : external interrupts
> + *  [N..N+31] : PPI (internal) interrupts for CPU 0
> + *  [N+32..N+63] : PPI (internal interrupts for CPU 1
> + * @level: level of the IRQ line.
> + */
> +void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level);
> +
> +/**
> + * kvm_gic_access - Read or write vGIC memory-mapped register
> + * @dev_fd: fd of the device to act on
> + * @group: ID of the memory-mapped region
> + * @offset: offset within the region
> + * @cpu: vCPU number
> + * @val: pointer to the storage area for the data
> + * @write - true for writing and false for reading
> + */
> +void kvm_gic_access(int dev_fd, int group, int offset, int cpu,
> +                    void *val, bool write);
> +
> +#define kvm_gicd_access(s, offset, cpu, val, write) \
> +    kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS, \
> +                   offset, cpu, val, write)
> +
> +#define kvm_gicc_access(s, offset, cpu, val, write) \
> +    kvm_gic_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS, \
> +                   offset, cpu, val, write)

what is the point of moving kvm_gicd_access and kvm_gicc_access here? If
I am not mistaken, they only are used in arm_gic_kvm.c? I think they can
stay static in arm_gic_kvm.c?

Best Regards

Eric
> +
> +#endif
> 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]