From patchwork Wed Jun 11 14:01:27 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jones X-Patchwork-Id: 4336321 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 21038BEEAA for ; Wed, 11 Jun 2014 14:02:14 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2FE5820218 for ; Wed, 11 Jun 2014 14:02:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D5A312028D for ; Wed, 11 Jun 2014 14:02:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932254AbaFKOB7 (ORCPT ); Wed, 11 Jun 2014 10:01:59 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53940 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932235AbaFKOB6 (ORCPT ); Wed, 11 Jun 2014 10:01:58 -0400 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 s5BE1tXU020975 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 11 Jun 2014 10:01:55 -0400 Received: from dhcp-27-201.brq.redhat.com (dhcp-1-235.brq.redhat.com [10.34.1.235]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s5BE1Zbc014365; Wed, 11 Jun 2014 10:01:54 -0400 From: Andrew Jones To: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org Cc: christoffer.dall@linaro.org, pbonzini@redhat.com Subject: [PATCH v5 12/19] Introduce virtio-testdev Date: Wed, 11 Jun 2014 16:01:27 +0200 Message-Id: <1402495294-30737-13-git-send-email-drjones@redhat.com> In-Reply-To: <1402495294-30737-1-git-send-email-drjones@redhat.com> References: <1402495294-30737-1-git-send-email-drjones@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, 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 virtio-testdev is a communication channel to qemu through virtio that can be used by test code to send commands. The only command currently implemented is EXIT, which allows the test code to exit with a given status code. Signed-off-by: Andrew Jones Reviewed-by: Christoffer Dall --- v4: couple tweaks (added spinlock), no functional changes --- lib/virtio-testdev.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/virtio-testdev.h | 18 +++++++ 2 files changed, 155 insertions(+) create mode 100644 lib/virtio-testdev.c create mode 100644 lib/virtio-testdev.h diff --git a/lib/virtio-testdev.c b/lib/virtio-testdev.c new file mode 100644 index 0000000000000..422e0bf4fc35a --- /dev/null +++ b/lib/virtio-testdev.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2014, Red Hat Inc, Andrew Jones + * + * This work is licensed under the terms of the GNU LGPL, version 2. + */ +#include "libcflat.h" +#include "asm/spinlock.h" +#include "virtio.h" + +#define TESTDEV_NAME "virtio-testdev" +#define VIRTIO_ID_TESTDEV 0xffff +#define TESTDEV_MAJOR_VER 1 +#define TESTDEV_MINOR_VER 1 + +#define VIRTIO_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) + +static struct spinlock lock; +static struct virtio_device *vdev; + +static u32 testdev_readl(unsigned offset) +{ + assert(offset <= (VIRTIO_CONFIG_SIZE - 4)); + return virtio_config_readl(vdev, offset); +} + +static void testdev_writel(unsigned offset, u32 val) +{ + assert(offset <= (VIRTIO_CONFIG_SIZE - 4)); + virtio_config_writel(vdev, offset, val); +} + +/* + * We have to write all args; nargs, nrets, ... first to avoid executing + * the token's operation until all args are in place. Then issue the op, + * and then read the return values. Reading the return values (or just + * sanity checking by reading token) will read a zero into qemu's copy + * of the token, which allows us to prepare additional ops without + * re-executing the last one. + */ +void virtio_testdev(u32 token, u32 nargs, u32 nrets, ...) +{ + va_list va; + unsigned off; + u32 n; + + if (!vdev) + return; + + spin_lock(&lock); + + testdev_writel(NARGS_OFFSET, nargs); + testdev_writel(NRETS_OFFSET, nrets); + + va_start(va, nrets); + + off = ARG_OFFSET(0); + n = nargs; + while (n--) { + testdev_writel(off, va_arg(va, unsigned)); + off += 4; + } + + /* this runs the op, but then resets token to zero */ + testdev_writel(TOKEN_OFFSET, token); + assert(testdev_readl(TOKEN_OFFSET) == 0); + + off = __RET_OFFSET(nargs, 0); + n = nrets; + while (n--) { + u32 *r = va_arg(va, unsigned *); + *r = testdev_readl(off); + off += 4; + } + + spin_unlock(&lock); + va_end(va); +} + +void virtio_testdev_version(u32 *version) +{ + virtio_testdev(VERSION, 0, 1, version); +} + +void virtio_testdev_clear(void) +{ + virtio_testdev(CLEAR, 0, 0); +} + +void virtio_testdev_exit(int code) +{ + virtio_testdev(EXIT, 1, 0, code); +} + +void virtio_testdev_init(void) +{ + u16 major, minor; + u32 version; + + vdev = virtio_bind(VIRTIO_ID_TESTDEV); + if (vdev == NULL) { + printf("%s: can't find " TESTDEV_NAME ". " + "Is '-device " TESTDEV_NAME "' " + "on the qemu command line?\n", __func__); + abort(); + } + + virtio_testdev_version(&version); + major = version >> 16; + minor = version & 0xffff; + + if (major != TESTDEV_MAJOR_VER || minor < TESTDEV_MINOR_VER) { + char *u = "qemu"; + if (major > TESTDEV_MAJOR_VER) + u = "kvm-unit-tests"; + printf("%s: incompatible version of " TESTDEV_NAME ": " + "major = %d, minor = %d. Update %s\n", + __func__, major, minor, u); + abort(); + } + + if (minor > TESTDEV_MINOR_VER) + printf("%s: " TESTDEV_NAME " has new features. " + "An update of kvm-unit-tests may be possible.\n", + __func__); +} diff --git a/lib/virtio-testdev.h b/lib/virtio-testdev.h new file mode 100644 index 0000000000000..bed9eaf4aca4b --- /dev/null +++ b/lib/virtio-testdev.h @@ -0,0 +1,18 @@ +#ifndef _VIRTIO_TESTDEV_H_ +#define _VIRTIO_TESTDEV_H_ +/* + * virtio-testdev is a driver for the virtio-testdev qemu device. + * The virtio-testdev device exposes a simple control interface to + * qemu for kvm-unit-tests through virtio. + * + * Copyright (C) 2014, Red Hat Inc, Andrew Jones + * + * This work is licensed under the terms of the GNU LGPL, version 2. + */ +#include "libcflat.h" + +extern void virtio_testdev_init(void); +extern void virtio_testdev_version(u32 *version); +extern void virtio_testdev_clear(void); +extern void virtio_testdev_exit(int code); +#endif