From patchwork Tue Feb 18 01:42:00 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoffer Dall X-Patchwork-Id: 24811 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-vc0-f199.google.com (mail-vc0-f199.google.com [209.85.220.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 7E57020143 for ; Tue, 18 Feb 2014 01:44:52 +0000 (UTC) Received: by mail-vc0-f199.google.com with SMTP id hu8sf31970219vcb.2 for ; Mon, 17 Feb 2014 17:44:51 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:date :message-id:in-reply-to:references:cc:subject:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:list-subscribe :errors-to:sender:x-original-sender :x-original-authentication-results:mailing-list; bh=hLFuKVgmGZnOCfCsagoDmORxcCshn/jGDyCYIzOuMAU=; b=B/v2xatiMpCJXYAqWv1VJWySs6iNEEjLgdl+tErhMXHGM6KDgw9hzYGTNk4hHgXzfv 7u9PpVYRWbojxOMxeZEtr8OgJdu+h1ojGd0/MCJnWjf1LrZ88uNnO0OGjUs7f1Vxr4F7 r5jhWoyHBdM+7Clp1raiPBKOWq8ZKmKe7XVu+7ptZLJyjlKIAoDNfK+giHH4znvWZWyu uRSn5eLY0zndz0W/KvgliYVjRY+FTTOJTJ0DwTY9WRuJbS67XxcjjP2DZGYzP6tMhZvV z8gBeYruAN8fTvULnCQH3x+5W83iWQNHED5JDMoMNx+JN8oTtvdmTDrvLiX/kFmpI0Nq SFLA== X-Gm-Message-State: ALoCoQngGiYKU9ixjpWRb7qLLlNQ1z4uYtf2u4QCPchQMENNOddIYnHeJ1YD3I5GDce7L6IQ/REx X-Received: by 10.236.184.165 with SMTP id s25mr10401670yhm.0.1392687891616; Mon, 17 Feb 2014 17:44:51 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.93.71 with SMTP id c65ls1073541qge.4.gmail; Mon, 17 Feb 2014 17:44:51 -0800 (PST) X-Received: by 10.221.40.10 with SMTP id to10mr14771571vcb.22.1392687891446; Mon, 17 Feb 2014 17:44:51 -0800 (PST) Received: from mail-vc0-f175.google.com (mail-vc0-f175.google.com [209.85.220.175]) by mx.google.com with ESMTPS id gq1si5017848vec.137.2014.02.17.17.44.51 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 17 Feb 2014 17:44:51 -0800 (PST) Received-SPF: neutral (google.com: 209.85.220.175 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.175; Received: by mail-vc0-f175.google.com with SMTP id ij19so12383507vcb.20 for ; Mon, 17 Feb 2014 17:44:51 -0800 (PST) X-Received: by 10.221.22.71 with SMTP id qv7mr3517647vcb.34.1392687891341; Mon, 17 Feb 2014 17:44:51 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.174.196 with SMTP id u4csp180151vcz; Mon, 17 Feb 2014 17:44:51 -0800 (PST) X-Received: by 10.140.37.146 with SMTP id r18mr36872535qgr.61.1392687890863; Mon, 17 Feb 2014 17:44:50 -0800 (PST) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id h3si9510811qah.158.2014.02.17.17.44.50 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Mon, 17 Feb 2014 17:44:50 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Received: from localhost ([::1]:45596 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WFZju-0006Fo-Hs for patch@linaro.org; Mon, 17 Feb 2014 20:44:50 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35533) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WFZha-0003FJ-RA for qemu-devel@nongnu.org; Mon, 17 Feb 2014 20:42:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WFZhV-0005zV-7r for qemu-devel@nongnu.org; Mon, 17 Feb 2014 20:42:26 -0500 Received: from mail-pb0-f52.google.com ([209.85.160.52]:37564) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WFZhV-0005zP-07 for qemu-devel@nongnu.org; Mon, 17 Feb 2014 20:42:21 -0500 Received: by mail-pb0-f52.google.com with SMTP id jt11so16046634pbb.39 for ; Mon, 17 Feb 2014 17:42:20 -0800 (PST) X-Received: by 10.68.196.195 with SMTP id io3mr30270877pbc.6.1392687740110; Mon, 17 Feb 2014 17:42:20 -0800 (PST) Received: from localhost.localdomain (c-67-169-181-221.hsd1.ca.comcast.net. [67.169.181.221]) by mx.google.com with ESMTPSA id vx10sm129526828pac.17.2014.02.17.17.42.18 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 17 Feb 2014 17:42:19 -0800 (PST) From: Christoffer Dall To: qemu-devel@nongnu.org Date: Mon, 17 Feb 2014 17:42:00 -0800 Message-Id: <1392687720-26806-5-git-send-email-christoffer.dall@linaro.org> X-Mailer: git-send-email 1.8.5.2 In-Reply-To: <1392687720-26806-1-git-send-email-christoffer.dall@linaro.org> References: <1392687720-26806-1-git-send-email-christoffer.dall@linaro.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.160.52 Cc: kvmarm@lists.cs.columbia.edu, Christoffer Dall Subject: [Qemu-devel] [PATCH v6 4/4] arm: vgic device control api support 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+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: christoffer.dall@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.175 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 Support creating the ARM vgic device through the device control API and setting the base address for the distributor and cpu interfaces in KVM VMs using this API. Because the older KVM_CREATE_IRQCHIP interface needs the irq chip to be created prior to creating the VCPUs, we first test if we can use the device control API in kvm_arch_irqchip_create (using the test flag from the device control API). If we cannot, it means we have to fall back to KVM_CREATE_IRQCHIP and use the older ioctl at this point in time. If however, we can use the device control API, we don't do anything and wait until the arm_gic_kvm driver initializes and let that use the device control API. Signed-off-by: Christoffer Dall --- Changelog[v3 -> v4]: - Support creating the gic-kvm with kernels that do not even support the device control API, by checking for -ENOTSUP returns from kvm_create_device(). Changelog[v2 -> v3]: - Fixed indentation - Fixed number of parameters in kvm_arm_register_device documentation Changelog[v1 -> v2]: - Moved dev_fd into GICState - Proper error handling in kvm_arm_gic_realize - Coding style and other minor fixes hw/intc/arm_gic_kvm.c | 22 ++++++++++++++-- include/hw/intc/arm_gic_common.h | 1 + target-arm/kvm.c | 55 +++++++++++++++++++++++++++++++++++----- target-arm/kvm_arm.h | 17 ++++++++----- 4 files changed, 80 insertions(+), 15 deletions(-) diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c index 59a3da5..964d4d7 100644 --- a/hw/intc/arm_gic_kvm.c +++ b/hw/intc/arm_gic_kvm.c @@ -97,6 +97,7 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) GICState *s = KVM_ARM_GIC(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s); + int ret; kgc->parent_realize(dev, errp); if (error_is_set(errp)) { @@ -119,13 +120,27 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) for (i = 0; i < s->num_cpu; i++) { sysbus_init_irq(sbd, &s->parent_irq[i]); } + + /* Try to create the device via the device control API */ + s->dev_fd = -1; + ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V2, false); + if (ret >= 0) { + s->dev_fd = ret; + } else if (ret != -ENODEV && ret != -ENOTSUP) { + error_setg_errno(errp, -ret, "error creating in-kernel VGIC"); + return; + } + /* Distributor */ memory_region_init_reservation(&s->iomem, OBJECT(s), "kvm-gic_dist", 0x1000); sysbus_init_mmio(sbd, &s->iomem); kvm_arm_register_device(&s->iomem, (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT) - | KVM_VGIC_V2_ADDR_TYPE_DIST); + | KVM_VGIC_V2_ADDR_TYPE_DIST, + KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V2_ADDR_TYPE_DIST, + s->dev_fd); /* CPU interface for current core. Unlike arm_gic, we don't * provide the "interface for core #N" memory regions, because * cores with a VGIC don't have those. @@ -135,7 +150,10 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) sysbus_init_mmio(sbd, &s->cpuiomem[0]); kvm_arm_register_device(&s->cpuiomem[0], (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT) - | KVM_VGIC_V2_ADDR_TYPE_CPU); + | KVM_VGIC_V2_ADDR_TYPE_CPU, + KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V2_ADDR_TYPE_CPU, + s->dev_fd); } static void kvm_arm_gic_class_init(ObjectClass *klass, void *data) diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h index 89384c2..f6887ed 100644 --- a/include/hw/intc/arm_gic_common.h +++ b/include/hw/intc/arm_gic_common.h @@ -104,6 +104,7 @@ typedef struct GICState { MemoryRegion cpuiomem[GIC_NCPU + 1]; /* CPU interfaces */ uint32_t num_irq; uint32_t revision; + int dev_fd; /* kvm device fd if backed by kvm vgic support */ } GICState; #define TYPE_ARM_GIC_COMMON "arm_gic_common" diff --git a/target-arm/kvm.c b/target-arm/kvm.c index 1d2688d..39202d7 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -165,8 +165,10 @@ unsigned long kvm_arch_vcpu_id(CPUState *cpu) */ typedef struct KVMDevice { struct kvm_arm_device_addr kda; + struct kvm_device_attr kdattr; MemoryRegion *mr; QSLIST_ENTRY(KVMDevice) entries; + int dev_fd; } KVMDevice; static QSLIST_HEAD(kvm_devices_head, KVMDevice) kvm_devices_head; @@ -200,6 +202,29 @@ static MemoryListener devlistener = { .region_del = kvm_arm_devlistener_del, }; +static void kvm_arm_set_device_addr(KVMDevice *kd) +{ + struct kvm_device_attr *attr = &kd->kdattr; + int ret; + + /* If the device control API is available and we have a device fd on the + * KVMDevice struct, let's use the newer API + */ + if (kd->dev_fd >= 0) { + uint64_t addr = kd->kda.addr; + attr->addr = (uintptr_t)&addr; + ret = kvm_device_ioctl(kd->dev_fd, KVM_SET_DEVICE_ATTR, attr); + } else { + ret = kvm_vm_ioctl(kvm_state, KVM_ARM_SET_DEVICE_ADDR, &kd->kda); + } + + if (ret < 0) { + fprintf(stderr, "Failed to set device address: %s\n", + strerror(-ret)); + abort(); + } +} + static void kvm_arm_machine_init_done(Notifier *notifier, void *data) { KVMDevice *kd, *tkd; @@ -207,12 +232,7 @@ static void kvm_arm_machine_init_done(Notifier *notifier, void *data) memory_listener_unregister(&devlistener); QSLIST_FOREACH_SAFE(kd, &kvm_devices_head, entries, tkd) { if (kd->kda.addr != -1) { - if (kvm_vm_ioctl(kvm_state, KVM_ARM_SET_DEVICE_ADDR, - &kd->kda) < 0) { - fprintf(stderr, "KVM_ARM_SET_DEVICE_ADDRESS failed: %s\n", - strerror(errno)); - abort(); - } + kvm_arm_set_device_addr(kd); } memory_region_unref(kd->mr); g_free(kd); @@ -223,7 +243,8 @@ static Notifier notify = { .notify = kvm_arm_machine_init_done, }; -void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid) +void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group, + uint64_t attr, int dev_fd) { KVMDevice *kd; @@ -239,6 +260,10 @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid) kd->mr = mr; kd->kda.id = devid; kd->kda.addr = -1; + kd->kdattr.flags = 0; + kd->kdattr.group = group; + kd->kdattr.attr = attr; + kd->dev_fd = dev_fd; QSLIST_INSERT_HEAD(&kvm_devices_head, kd, entries); memory_region_ref(kd->mr); } @@ -389,3 +414,19 @@ void kvm_arch_remove_all_hw_breakpoints(void) void kvm_arch_init_irq_routing(KVMState *s) { } + +int kvm_arch_irqchip_create(KVMState *s) +{ + int ret; + + /* If we can create the VGIC using the newer device control API, we + * let the device do this when it initializes itself, otherwise we + * fall back to the old API */ + + ret = kvm_create_device(s, KVM_DEV_TYPE_ARM_VGIC_V2, true); + if (ret == 0) { + return 1; + } + + return 0; +} diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h index cd3d13c..137c567 100644 --- a/target-arm/kvm_arm.h +++ b/target-arm/kvm_arm.h @@ -18,16 +18,21 @@ * kvm_arm_register_device: * @mr: memory region for this device * @devid: the KVM device ID + * @group: device control API group for setting addresses + * @attr: device control API address type + * @dev_fd: device control device file descriptor (or -1 if not supported) * * Remember the memory region @mr, and when it is mapped by the * machine model, tell the kernel that base address using the - * KVM_SET_DEVICE_ADDRESS ioctl. @devid should be the ID of - * the device as defined by KVM_SET_DEVICE_ADDRESS. - * The machine model may map and unmap the device multiple times; - * the kernel will only be told the final address at the point - * where machine init is complete. + * KVM_ARM_SET_DEVICE_ADDRESS ioctl or the newer device control API. @devid + * should be the ID of the device as defined by KVM_ARM_SET_DEVICE_ADDRESS or + * the arm-vgic device in the device control API. + * The machine model may map + * and unmap the device multiple times; the kernel will only be told the final + * address at the point where machine init is complete. */ -void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid); +void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group, + uint64_t attr, int dev_fd); /** * write_list_to_kvmstate: