From patchwork Tue Nov 19 06:16:36 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoffer Dall X-Patchwork-Id: 21595 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-qa0-f72.google.com (mail-qa0-f72.google.com [209.85.216.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 9688D20972 for ; Tue, 19 Nov 2013 06:15:50 +0000 (UTC) Received: by mail-qa0-f72.google.com with SMTP id f11sf6089673qae.11 for ; Mon, 18 Nov 2013 22:15:50 -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:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=xO1MP2oLoY/gVWa5kw0NYpMiV+KRKcnu586Wd/Qulb0=; b=OCfF1PPv+G+usG+rHUfyW2KvealfPqQKe886Czt7ilg3J6me0a6t3V2z+2Yi+9gxFj NWHl1KjunHQrk3tpsDEXKQYl2e+EXmMS6/v0d0w/n6iryYosNFUFeBcSFVs3sL51bsNp nIJFkoBVDwNwppoKNt4xzGKfw1GonQjck8QRrDJFUYDXYFMGwrCs5h/oDOFtocZ1IKT6 /SQvMQT8n0hxZy3OB6BFK3zYVsfrhnsiPENz5EzBa+RkKSNoXqtDdpKpnlFY9qsdwIky gRbu2wvagu3lZVh3m4hmD66kOddGJ8nzSOfpjOmBPbfvo00td9iGmWlwbQ1AWgc7Wzrw cKFw== X-Gm-Message-State: ALoCoQkzyrliHIz6aPubXZTJHdLldQGjX1SJfu7dKO2c+/M2emiyhBmIP45Jgu5KoyNKj5TlkrUR X-Received: by 10.58.156.70 with SMTP id wc6mr8559475veb.27.1384841750321; Mon, 18 Nov 2013 22:15:50 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.94.167 with SMTP id dd7ls2200283qeb.24.gmail; Mon, 18 Nov 2013 22:15:50 -0800 (PST) X-Received: by 10.58.133.77 with SMTP id pa13mr53452veb.21.1384841750239; Mon, 18 Nov 2013 22:15:50 -0800 (PST) Received: from mail-ve0-f182.google.com (mail-ve0-f182.google.com [209.85.128.182]) by mx.google.com with ESMTPS id sz7si7886326vdc.47.2013.11.18.22.15.50 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 18 Nov 2013 22:15:50 -0800 (PST) Received-SPF: neutral (google.com: 209.85.128.182 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.182; Received: by mail-ve0-f182.google.com with SMTP id pa12so5943418veb.27 for ; Mon, 18 Nov 2013 22:15:50 -0800 (PST) X-Received: by 10.52.120.78 with SMTP id la14mr16728095vdb.9.1384841749968; Mon, 18 Nov 2013 22:15:49 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp255295vcz; Mon, 18 Nov 2013 22:15:49 -0800 (PST) X-Received: by 10.68.215.38 with SMTP id of6mr24704315pbc.14.1384841748880; Mon, 18 Nov 2013 22:15:48 -0800 (PST) Received: from mail-pb0-f53.google.com (mail-pb0-f53.google.com [209.85.160.53]) by mx.google.com with ESMTPS id hb3si11202454pac.268.2013.11.18.22.15.48 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 18 Nov 2013 22:15:48 -0800 (PST) Received-SPF: neutral (google.com: 209.85.160.53 is neither permitted nor denied by best guess record for domain of christoffer.dall@linaro.org) client-ip=209.85.160.53; Received: by mail-pb0-f53.google.com with SMTP id ma3so7787427pbc.26 for ; Mon, 18 Nov 2013 22:15:48 -0800 (PST) X-Received: by 10.66.188.203 with SMTP id gc11mr24489636pac.63.1384841748257; Mon, 18 Nov 2013 22:15:48 -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 fk4sm31648068pab.23.2013.11.18.22.15.46 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 18 Nov 2013 22:15:47 -0800 (PST) From: Christoffer Dall To: qemu-devel@nongnu.org Cc: kvmarm@lists.cs.columbia.edu, patches@linaro.org, Christoffer Dall Subject: [RFC PATCH v3 4/4] arm: vgic device control api support Date: Mon, 18 Nov 2013 22:16:36 -0800 Message-Id: <1384841796-19437-5-git-send-email-christoffer.dall@linaro.org> X-Mailer: git-send-email 1.8.4.3 In-Reply-To: <1384841796-19437-1-git-send-email-christoffer.dall@linaro.org> References: <1384841796-19437-1-git-send-email-christoffer.dall@linaro.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.128.182 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 Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , 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. Reviewed-by: Peter Maydell Signed-off-by: Christoffer Dall --- Changelog[v3]: - Fixed indentation - Fixed number of parameters in kvm_arm_register_device documentation Changelog[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 f713975..158f047 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) { + 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 4f381bd..ed18bb8 100644 --- a/include/hw/intc/arm_gic_common.h +++ b/include/hw/intc/arm_gic_common.h @@ -70,6 +70,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 6e5cd36..d6220e3 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -190,8 +190,10 @@ out: */ 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; @@ -225,6 +227,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; @@ -232,12 +257,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); @@ -248,7 +268,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; @@ -264,6 +285,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); } @@ -653,3 +678,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 5d14887..ad63a98 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: