From patchwork Thu Apr 10 16:56:53 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jones X-Patchwork-Id: 3963561 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 1CD489F3D5 for ; Thu, 10 Apr 2014 16:57:45 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2849320823 for ; Thu, 10 Apr 2014 16:57:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 206C520819 for ; Thu, 10 Apr 2014 16:57:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758783AbaDJQ5j (ORCPT ); Thu, 10 Apr 2014 12:57:39 -0400 Received: from mx1.redhat.com ([209.132.183.28]:38760 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758751AbaDJQ51 (ORCPT ); Thu, 10 Apr 2014 12:57:27 -0400 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s3AGvPOU029156 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 10 Apr 2014 12:57:25 -0400 Received: from hawk.usersys.redhat.com.com (dhcp-1-170.brq.redhat.com [10.34.1.170]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id s3AGv4Ut021128; Thu, 10 Apr 2014 12:57:23 -0400 From: Andrew Jones To: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org Cc: christoffer.dall@linaro.org Subject: [PATCH v4 12/19] Introduce virtio-testdev Date: Thu, 10 Apr 2014 18:56:53 +0200 Message-Id: <1397149020-3501-13-git-send-email-drjones@redhat.com> In-Reply-To: <1397149020-3501-1-git-send-email-drjones@redhat.com> References: <1397149020-3501-1-git-send-email-drjones@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 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..3ece6ae58fdc5 --- /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_dev *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