From patchwork Wed Jan 29 15:19:54 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jones X-Patchwork-Id: 23879 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pb0-f69.google.com (mail-pb0-f69.google.com [209.85.160.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id D3A0320300 for ; Wed, 29 Jan 2014 15:21:10 +0000 (UTC) Received: by mail-pb0-f69.google.com with SMTP id md12sf4170858pbc.4 for ; Wed, 29 Jan 2014 07:21:10 -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: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=j2h2uexkLOKwVb2AWY8s2SplzYgehFSgfwHtNV8LpkE=; b=TSHsYDmsFDGa9uinejWxEKWQT1MR4JewWlIJU2CDPVdiFIfMR1cPewomIdbhYb0ef7 nGsHtMh0g/eWtfHMHa7WpmHLTbTbpD+mp16oYbEPGwgm2rB9p3yRhWRh4lpqfH0Z29Ca bWa4mgSlayShlJVG8E+MKutVJfe0bC3YYDtw/wdu9/YCU5l3KJ1IoBfSq4ZigQuJDH1J 99bsF3vvU/O6Ppt1Yok7Sk4t6RcHPl+8N6Uo3tj3zVuc5opRvge5fssuMpjXp8e37iFj LLBZRrGmao2gvAGEtgZdDvk8wEow/DRw7GbxJD0UoTgP9Rev6iLMdRV5qOeKtVXcBzVu LNyA== X-Gm-Message-State: ALoCoQmh4QcNEFibpYclaWCsv3JTvZgSCsQSY4z7ubASPYTaEsVtrUE+/U+XHI5vV74TguU72ErQ X-Received: by 10.66.66.109 with SMTP id e13mr3014494pat.1.1391008870132; Wed, 29 Jan 2014 07:21:10 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.36.7 with SMTP id o7ls155438qgo.15.gmail; Wed, 29 Jan 2014 07:21:09 -0800 (PST) X-Received: by 10.220.186.202 with SMTP id ct10mr7164086vcb.14.1391008869948; Wed, 29 Jan 2014 07:21:09 -0800 (PST) Received: from mail-vb0-f49.google.com (mail-vb0-f49.google.com [209.85.212.49]) by mx.google.com with ESMTPS id n8si871654vdv.146.2014.01.29.07.21.09 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 29 Jan 2014 07:21:09 -0800 (PST) Received-SPF: neutral (google.com: 209.85.212.49 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.212.49; Received: by mail-vb0-f49.google.com with SMTP id x14so1207295vbb.22 for ; Wed, 29 Jan 2014 07:21:09 -0800 (PST) X-Received: by 10.220.124.65 with SMTP id t1mr1542795vcr.26.1391008869813; Wed, 29 Jan 2014 07:21:09 -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 u4csp121114vcz; Wed, 29 Jan 2014 07:21:09 -0800 (PST) X-Received: by 10.140.101.104 with SMTP id t95mr12177935qge.106.1391008869263; Wed, 29 Jan 2014 07:21:09 -0800 (PST) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id 7si1993233qal.77.2014.01.29.07.21.08 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 29 Jan 2014 07:21:09 -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]:43345 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W8Wwu-00068h-MU for patch@linaro.org; Wed, 29 Jan 2014 10:21:08 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51295) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W8WwM-0005qU-Nv for qemu-devel@nongnu.org; Wed, 29 Jan 2014 10:20:40 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1W8WwG-0003ML-Ad for qemu-devel@nongnu.org; Wed, 29 Jan 2014 10:20:34 -0500 Received: from mx1.redhat.com ([209.132.183.28]:47091) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W8WwG-0003Ic-1Q for qemu-devel@nongnu.org; Wed, 29 Jan 2014 10:20:28 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s0TFKCQi013712 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 29 Jan 2014 10:20:13 -0500 Received: from hawk.usersys.redhat.com.com (dhcp-1-245.brq.redhat.com [10.34.1.245]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s0TFK4Lc028874; Wed, 29 Jan 2014 10:20:04 -0500 From: Andrew Jones To: qemu-devel@nongnu.org Date: Wed, 29 Jan 2014 16:19:54 +0100 Message-Id: <1391008794-18777-1-git-send-email-drjones@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: peter.maydell@linaro.org, kvmarm@lists.cs.columbia.edu, christoffer.dall@linaro.org Subject: [Qemu-devel] [PATCH v3] virtio: Introduce virtio-testdev 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: drjones@redhat.com X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.49 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 This is a virtio version of hw/misc/debugexit and should evolve into a virtio version of pc-testdev. pc-testdev uses the PC's ISA bus, whereas this testdev can be plugged into a virtio-mmio transport, which is needed for kvm-unit-tests/arm. virtio-testdev uses the virtio device config space as a communication channel, and implements an RTAS-like protocol through it allowing guests to execute commands. Only three commands are currently implemented; 1) VERSION: for version compatibility checks 2) CLEAR: set all the config space back to zero 3) EXIT: exit() from qemu with a status code --- v3: Convert to QOM realize v2: - No real functional changes, just added some comments and changed register bank accesses to use byte offsets, allowing the driver implementation to better mirror this device's implementation. Signed-off-by: Andrew Jones --- hw/virtio/Makefile.objs | 1 + hw/virtio/virtio-testdev.c | 154 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 hw/virtio/virtio-testdev.c diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs index 1ba53d9cc316c..b63fea4a175f0 100644 --- a/hw/virtio/Makefile.objs +++ b/hw/virtio/Makefile.objs @@ -3,6 +3,7 @@ common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o common-obj-y += virtio-bus.o common-obj-y += virtio-mmio.o common-obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += dataplane/ +common-obj-y += virtio-testdev.o obj-y += virtio.o virtio-balloon.o obj-$(CONFIG_LINUX) += vhost.o diff --git a/hw/virtio/virtio-testdev.c b/hw/virtio/virtio-testdev.c new file mode 100644 index 0000000000000..495639a66d3bc --- /dev/null +++ b/hw/virtio/virtio-testdev.c @@ -0,0 +1,154 @@ +/* + * Virtio Test Device + * + * Copyright (C) 2013 Red Hat, Inc. + * Copyright (C) 2013 Andrew Jones + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ +#include "hw/virtio/virtio-bus.h" + +#define VIRTIO_ID_TESTDEV 0xffff + +#define TYPE_VIRTIO_TESTDEV "virtio-testdev" +#define VIRTIO_TESTDEV(obj) \ + OBJECT_CHECK(VirtIOTestdev, (obj), TYPE_VIRTIO_TESTDEV) + +#define TESTDEV_MAJOR_VER 1 +#define TESTDEV_MINOR_VER 1 + +/* + * Size of the register bank in bytes. The max is determined + * by the device's config space. For virtio-mmio devices we + * only have 256 bytes, so that's our max, but we don't need + * that much anyway. 64 bytes gives us token, nargs, nrets, + * and an additional 13 4-byte registers for input/output. + * That'll do. + */ +#define CONFIG_SIZE 64 + +enum { + VERSION = 1, + CLEAR, + EXIT, +}; + +#define TOKEN_OFFSET 0x0 +#define NARGS_OFFSET 0x4 +#define NRETS_OFFSET 0x8 +#define ARG_OFFSET(n) (0xc + (n) * 4) +#define __RET_OFFSET(nargs, n) (ARG_OFFSET(nargs) + (n) * 4) +#define RET_OFFSET(d, n) __RET_OFFSET(config_readl(d, NARGS_OFFSET), n) + +typedef struct VirtIOTestdev { + VirtIODevice parent_obj; + uint8_t config[CONFIG_SIZE]; +} VirtIOTestdev; + +static uint32_t config_readl(VirtIOTestdev *dev, unsigned offset) +{ + uint32_t *config = (uint32_t *)&dev->config[0]; + + if (offset > (CONFIG_SIZE - 4)) { + return 0; + } + + return le32_to_cpu(config[offset / 4]); +} + +static void config_writel(VirtIOTestdev *dev, unsigned offset, uint32_t val) +{ + uint32_t *config = (uint32_t *)&dev->config[0]; + + if (offset <= (CONFIG_SIZE - 4)) { + config[offset / 4] = cpu_to_le32(val); + } +} + +static void virtio_testdev_get_config(VirtIODevice *vdev, uint8_t *config_data) +{ + VirtIOTestdev *dev = VIRTIO_TESTDEV(vdev); + memcpy(config_data, &dev->config[0], CONFIG_SIZE); +} + +static void virtio_testdev_set_config(VirtIODevice *vdev, + const uint8_t *config_data) +{ + VirtIOTestdev *dev = VIRTIO_TESTDEV(vdev); + uint32_t token; + + memcpy(&dev->config[0], config_data, CONFIG_SIZE); + + token = config_readl(dev, TOKEN_OFFSET); + + /* + * The token register must always remain zero in order to + * avoid re-executing operations while new operation + * arguments are being filled in. + */ + config_writel(dev, TOKEN_OFFSET, 0); + + switch (token) { + case 0: + /* + * No token yet, so we were just filling in arguments, and + * now there's nothing left to do. + */ + return; + case VERSION: + config_writel(dev, RET_OFFSET(dev, 0), + (TESTDEV_MAJOR_VER << 16) | TESTDEV_MINOR_VER); + break; + case EXIT: + exit((config_readl(dev, ARG_OFFSET(0)) << 1) | 1); + case CLEAR: + default: + /* The CLEAR op and unknown ops reset all registers */ + memset(&dev->config[0], 0, CONFIG_SIZE); + } +} + +static uint32_t virtio_testdev_get_features(VirtIODevice *vdev, uint32_t f) +{ + return f; +} + +static void virtio_testdev_realize(DeviceState *dev, Error **errp) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + virtio_init(vdev, "virtio-testdev", VIRTIO_ID_TESTDEV, CONFIG_SIZE); +} + +static int virtio_testdev_exit(DeviceState *qdev) +{ + virtio_cleanup(VIRTIO_DEVICE(qdev)); + return 0; +} + +static void virtio_testdev_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + dc->exit = virtio_testdev_exit; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + vdc->realize = virtio_testdev_realize; + vdc->get_config = virtio_testdev_get_config; + vdc->set_config = virtio_testdev_set_config; + vdc->get_features = virtio_testdev_get_features; +} + +static const TypeInfo virtio_testdev_info = { + .name = TYPE_VIRTIO_TESTDEV, + .parent = TYPE_VIRTIO_DEVICE, + .instance_size = sizeof(VirtIOTestdev), + .class_init = virtio_testdev_class_init, +}; + +static void virtio_register_types(void) +{ + type_register_static(&virtio_testdev_info); +} + +type_init(virtio_register_types)