From patchwork Mon Mar 7 04:23:28 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Xu X-Patchwork-Id: 8515401 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 3C6BBC0553 for ; Mon, 7 Mar 2016 04:26:06 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5EE3D2013A for ; Mon, 7 Mar 2016 04:26:05 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 90FC02010F for ; Mon, 7 Mar 2016 04:26:04 +0000 (UTC) Received: from localhost ([::1]:53506 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1acmk7-0000ah-TI for patchwork-qemu-devel@patchwork.kernel.org; Sun, 06 Mar 2016 23:26:03 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60155) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1acmiO-0006kz-Qz for qemu-devel@nongnu.org; Sun, 06 Mar 2016 23:24:17 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1acmiJ-0005b8-RV for qemu-devel@nongnu.org; Sun, 06 Mar 2016 23:24:16 -0500 Received: from mx1.redhat.com ([209.132.183.28]:44194) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1acmiH-0005am-3E; Sun, 06 Mar 2016 23:24:09 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (Postfix) with ESMTPS id BE9CE63144; Mon, 7 Mar 2016 04:24:08 +0000 (UTC) Received: from pxdev.xzpeter.org.com (vpn1-5-200.pek2.redhat.com [10.72.5.200]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u274NYnU001687; Sun, 6 Mar 2016 23:24:01 -0500 From: Peter Xu To: qemu-devel@nongnu.org Date: Mon, 7 Mar 2016 12:23:28 +0800 Message-Id: <1457324608-11434-4-git-send-email-peterx@redhat.com> In-Reply-To: <1457324608-11434-1-git-send-email-peterx@redhat.com> References: <1457324608-11434-1-git-send-email-peterx@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Mon, 07 Mar 2016 04:24:08 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Cc: wei@redhat.com, peter.maydell@linaro.org, drjones@redhat.com, mdroth@linux.vnet.ibm.com, armbru@redhat.com, peterx@redhat.com, abologna@redhat.com, qemu-arm@nongnu.org Subject: [Qemu-devel] [PATCH v3 3/3] arm: implement query-gic-capability 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+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP For emulated GIC capabilities, currently only gicv2 is supported. We need to add gicv3 in when emulated gicv3 ready. For KVM accelerated ARM VM, we detect the capability bits using ioctls. When probing the KVM capabilities, we cannot leverage existing helper functions like kvm_create_device() since QEMU might be using TCG while probing (actually this is the case for libvirt probing). So, one temporary VM is created to do the probing. Signed-off-by: Peter Xu --- target-arm/machine.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/target-arm/machine.c b/target-arm/machine.c index 60bd5c1..ff50411 100644 --- a/target-arm/machine.c +++ b/target-arm/machine.c @@ -1,3 +1,5 @@ +#include +#include #include "qemu/osdep.h" #include "hw/hw.h" #include "hw/boards.h" @@ -347,7 +349,108 @@ const char *gicv3_class_name(void) exit(1); } +static GICCapability *gic_cap_new(int version) +{ + GICCapability *cap = g_new0(GICCapability, 1); + cap->version = version; + /* by default, support none */ + cap->emulated = false; + cap->kernel = false; + return cap; +} + +static GICCapabilityList *gic_cap_list_add(GICCapabilityList *head, + GICCapability *cap) +{ + GICCapabilityList *item = g_new0(GICCapabilityList, 1); + item->value = cap; + item->next = head; + return item; +} + +#ifdef CONFIG_KVM +/* + * This is merely the same as kvm_create_device(). The only + * difference is we are using raw fds rather than KVMState, so that + * we can use it even without kvm_state initialized. + */ +static int kvm_create_device_fds(int kvm_fd, int vmfd, + uint64_t type, bool test) +{ + int ret; + struct kvm_create_device create_dev; + + create_dev.type = type; + create_dev.fd = -1; + create_dev.flags = test ? KVM_CREATE_DEVICE_TEST : 0; + + if (ioctl(kvm_fd, KVM_CHECK_EXTENSION, KVM_CAP_DEVICE_CTRL) <= 0) { + return -ENOTSUP; + } + + ret = ioctl(vmfd, KVM_CREATE_DEVICE, &create_dev); + if (ret) { + return ret; + } + + return test ? 0 : create_dev.fd; +} +#endif + GICCapabilityList *qmp_query_gic_capability(Error **errp) { - return NULL; + GICCapabilityList *head = NULL; + GICCapability *v2 = gic_cap_new(2), *v3 = gic_cap_new(3); + + v2->emulated = true; + /* FIXME: we'd change to true after we get emulated GICv3. */ + v3->emulated = false; + +#ifdef CONFIG_KVM + { + /* + * HACK: here we create one temporary VM, do the probing, + * then release it properly. + */ + int kvm_fd = -1; + int vmfd = -1; + + kvm_fd = qemu_open("/dev/kvm", O_RDWR); + if (kvm_fd == -1) { + /* KVM may not enabled on host, which is fine. */ + goto out; + } + + do { + /* For ARM, VM type could only be zero now. */ + vmfd = ioctl(kvm_fd, KVM_CREATE_VM, 0); + } while (vmfd == -EINTR); + + if (vmfd < 0) { + goto kvm_fd_close; + } + + /* Test KVM GICv2 */ + if (kvm_create_device_fds(kvm_fd, vmfd, KVM_DEV_TYPE_ARM_VGIC_V2, + true) >= 0) { + v2->kernel = true; + } + + /* Test KVM GICv3 */ + if (kvm_create_device_fds(kvm_fd, vmfd, KVM_DEV_TYPE_ARM_VGIC_V3, + true) >= 0) { + v3->kernel = true; + } + + close(vmfd); +kvm_fd_close: + close(kvm_fd); + } +#endif + +out: + head = gic_cap_list_add(head, v2); + head = gic_cap_list_add(head, v3); + + return head; }