From patchwork Thu Aug 13 11:02:13 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Fedin X-Patchwork-Id: 506975 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id B3B3614010F for ; Thu, 13 Aug 2015 21:12:10 +1000 (AEST) Received: from localhost ([::1]:41891 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZPqQa-0001r0-Rt for incoming@patchwork.ozlabs.org; Thu, 13 Aug 2015 07:12:08 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43709) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZPqHC-0002ik-0Q for qemu-devel@nongnu.org; Thu, 13 Aug 2015 07:02:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZPqH7-0006EK-4Q for qemu-devel@nongnu.org; Thu, 13 Aug 2015 07:02:25 -0400 Received: from mailout4.w1.samsung.com ([210.118.77.14]:34184) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZPqH6-0006B2-Vn for qemu-devel@nongnu.org; Thu, 13 Aug 2015 07:02:21 -0400 Received: from eucpsbgm2.samsung.com (unknown [203.254.199.245]) by mailout4.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0NT000KVLPBUMW00@mailout4.w1.samsung.com> for qemu-devel@nongnu.org; Thu, 13 Aug 2015 12:02:18 +0100 (BST) X-AuditID: cbfec7f5-f794b6d000001495-45-55cc793a81ef Received: from eusync4.samsung.com ( [203.254.199.214]) by eucpsbgm2.samsung.com (EUCPMTA) with SMTP id 73.98.05269.A397CC55; Thu, 13 Aug 2015 12:02:18 +0100 (BST) Received: from localhost ([106.109.131.169]) by eusync4.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0NT0001F1PBUM590@eusync4.samsung.com>; Thu, 13 Aug 2015 12:02:18 +0100 (BST) From: Pavel Fedin To: qemu-devel@nongnu.org Date: Thu, 13 Aug 2015 14:02:13 +0300 Message-id: <3fa361f2cdd10c2bd66054d25ac6272312e87348.1439462433.git.p.fedin@samsung.com> X-Mailer: git-send-email 1.9.5.msysgit.0 In-reply-to: References: In-reply-to: References: X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrMLMWRmVeSWpSXmKPExsVy+t/xa7pWlWdCDea0Gli8eP2P0WL+ljOs FnPOPGCxON67g8Wi7fN3dou7rz+zOLB57Jx1l92j5chbVo871/aweTy5tpkpgCWKyyYlNSez LLVI3y6BK+NOU2XBFtuK7p45TA2M3/W6GDk5JARMJP7fPcgIYYtJXLi3nq2LkYtDSGApo0T3 suesEM43RomlG1aygFSxCahLnP76AcwWEZCU+N11mhmkiFngEaPE161nmEESwgKOEuf7d4GN ZRFQlXjc0MIGYvMKREvcevaaHWKdhsSiL3PA4pwC5hJb38wGGyokYCZxe8NjJlziExj5FzAy rGIUTS1NLihOSs810itOzC0uzUvXS87P3cQICbqvOxiXHrM6xCjAwajEw7vh0elQIdbEsuLK 3EOMEhzMSiK899LOhArxpiRWVqUW5ccXleakFh9ilOZgURLnnbnrfYiQQHpiSWp2ampBahFM lomDU6qBse+/k890tYzZ0vrvSmdOvKvL9OurSvrm11nvntj8m8z9KsO46EW6neT2JdGLJpq8 2R6csGq1Ff9UttVe5yXm7n90u+ubOJPqstbfVoeebhQ32yi/bFdJ/Pxzrj/8dLZNnXPuNYv/ ktOfH81smuC+m5u15DrnyVezvExvntYVePWabV/26WVLt4UqsRRnJBpqMRcVJwIAARUoeDYC AAA= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 210.118.77.14 Cc: Peter Maydell , Shlomo Pongratz , Shlomo Pongratz , Christoffer Dall , Eric Auger Subject: [Qemu-devel] [PATCH v9 2/5] intc/gic: Extract some reusable vGIC code X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 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. Signed-off-by: Pavel Fedin --- hw/intc/arm_gic_kvm.c | 40 ++++++++++++++++--------------------- hw/intc/vgic_common.h | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 23 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..e12296e 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) +{ + 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,7 +114,7 @@ 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, +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++) @@ -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..98a4720 --- /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 . + */ + +#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, + uint32_t *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) + +#endif