All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Jones <drjones@redhat.com>
To: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org
Cc: christoffer.dall@linaro.org
Subject: [PATCH v4 11/19] add minimal virtio support for devtree virtio-mmio
Date: Thu, 10 Apr 2014 18:56:52 +0200	[thread overview]
Message-ID: <1397149020-3501-12-git-send-email-drjones@redhat.com> (raw)
In-Reply-To: <1397149020-3501-1-git-send-email-drjones@redhat.com>

Support the bare minimum of virtio to enable access to the virtio-mmio
config space of a device. Currently this implementation must use a
device tree to find the device.

Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v4:
 - split from the virtio-testdev patch
 - search a table to "discover" that the device must be DT/virtio-mmio,
   which doesn't change anything, but looks less hacky than comments
   saying the device must be DT/virtio-mmio...
 - manage own pool of virtio-mmio pre-allocated device structures in
   order to avoid needing access to the heap
---
 lib/libcflat.h |   3 ++
 lib/virtio.c   | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/virtio.h   |  89 +++++++++++++++++++++++++++++++
 3 files changed, 258 insertions(+)
 create mode 100644 lib/virtio.c
 create mode 100644 lib/virtio.h

diff --git a/lib/libcflat.h b/lib/libcflat.h
index c7c31be1cc8e5..5bb66d01dfc53 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -62,6 +62,9 @@ extern long atol(const char *ptr);
 #define ARRAY_SIZE(_a)  (sizeof(_a)/sizeof((_a)[0]))
 
 #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
+#define container_of(ptr, type, member) ({				\
+	const typeof( ((type *)0)->member ) *__mptr = (ptr);		\
+	(type *)( (char *)__mptr - offsetof(type,member) );})
 
 #define NULL ((void *)0UL)
 
diff --git a/lib/virtio.c b/lib/virtio.c
new file mode 100644
index 0000000000000..e7161ff591e4c
--- /dev/null
+++ b/lib/virtio.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "libcflat.h"
+#include "devicetree.h"
+#include "asm/spinlock.h"
+#include "asm/io.h"
+#include "virtio.h"
+
+enum virtio_hwdesc_type {
+	VIRTIO_HWDESC_TYPE_DT = 0,	/* device tree */
+	NR_VIRTIO_HWDESC_TYPES,
+};
+
+enum virtio_bus_type {
+	VIRTIO_BUS_TYPE_MMIO = 0,	/* virtio-mmio */
+	NR_VIRTIO_BUS_TYPES,
+};
+
+struct virtio_bind_bus {
+	bool (*hwdesc_probe)(void);
+	struct virtio_dev *(*device_bind)(u32 devid);
+};
+
+static struct virtio_dev *vm_dt_device_bind(u32 devid);
+
+static struct virtio_bind_bus
+virtio_bind_busses[NR_VIRTIO_HWDESC_TYPES][NR_VIRTIO_BUS_TYPES] = {
+
+[VIRTIO_HWDESC_TYPE_DT] = {
+
+	[VIRTIO_BUS_TYPE_MMIO] = {
+		.hwdesc_probe = dt_available,
+		.device_bind = vm_dt_device_bind,
+	},
+},
+};
+
+struct virtio_dev *virtio_bind(u32 devid)
+{
+	struct virtio_bind_bus *bus;
+	struct virtio_dev *dev;
+	int i, j;
+
+	for (i = 0; i < NR_VIRTIO_HWDESC_TYPES; ++i) {
+		for (j = 0; j < NR_VIRTIO_BUS_TYPES; ++j) {
+
+			bus = &virtio_bind_busses[i][j];
+
+			if (!bus->hwdesc_probe())
+				continue;
+
+			dev = bus->device_bind(devid);
+			if (dev)
+				return dev;
+		}
+	}
+
+	return NULL;
+}
+
+/******************************************************
+ * virtio-mmio support (config space only)
+ ******************************************************/
+
+static void vm_get(struct virtio_dev *vdev, unsigned offset,
+		   void *buf, unsigned len)
+{
+	struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
+	u8 *p = buf;
+	unsigned i;
+
+	for (i = 0; i < len; ++i)
+		p[i] = readb(vmdev->base + VIRTIO_MMIO_CONFIG + offset + i);
+}
+
+static void vm_set(struct virtio_dev *vdev, unsigned offset,
+		   const void *buf, unsigned len)
+{
+	struct virtio_mmio_dev *vmdev = to_virtio_mmio_dev(vdev);
+	const u8 *p = buf;
+	unsigned i;
+
+	for (i = 0; i < len; ++i)
+		writeb(p[i], vmdev->base + VIRTIO_MMIO_CONFIG + offset + i);
+}
+
+#define NR_VM_DEVICES 32
+static struct spinlock vm_lock;
+static struct virtio_mmio_dev vm_devs[NR_VM_DEVICES];
+static struct virtio_conf_ops vm_confs[NR_VM_DEVICES];
+static int nr_vm_devs;
+
+static struct virtio_mmio_dev *vm_new_device(u32 devid)
+{
+	struct virtio_mmio_dev *vmdev;
+
+	if (nr_vm_devs >= NR_VM_DEVICES)
+		return NULL;
+
+	spin_lock(&vm_lock);
+	vmdev = &vm_devs[nr_vm_devs];
+	vmdev->vdev.config = &vm_confs[nr_vm_devs];
+	++nr_vm_devs;
+	spin_unlock(&vm_lock);
+
+	vmdev->vdev.id.device = devid;
+	vmdev->vdev.id.vendor = -1;
+	vmdev->vdev.config->get = vm_get;
+	vmdev->vdev.config->set = vm_set;
+
+	return vmdev;
+}
+
+/******************************************************
+ * virtio-mmio device tree support
+ ******************************************************/
+
+struct vm_dt_info {
+	u32 devid;
+	void *base;
+};
+
+static int vm_dt_match(const struct dt_device *dev, int fdtnode)
+{
+	struct vm_dt_info *info = (struct vm_dt_info *)dev->info;
+	dt_pbus_addr_t base;
+
+	dt_device_bind_node((struct dt_device *)dev, fdtnode);
+
+	assert(dt_pbus_get_baseaddr(dev, &base) == 0);
+	assert(sizeof(long) == 8 || !(base >> 32));
+
+	info->base = (void *)(unsigned long)base;
+
+	return readl(info->base + VIRTIO_MMIO_DEVICE_ID) == info->devid;
+}
+
+static struct virtio_dev *vm_dt_device_bind(u32 devid)
+{
+	struct virtio_mmio_dev *vmdev;
+	struct dt_device dt_dev;
+	struct dt_bus dt_bus;
+	struct vm_dt_info info;
+	int node;
+
+	dt_bus_init_defaults(&dt_bus);
+	dt_bus.match = vm_dt_match;
+
+	info.devid = devid;
+
+	dt_device_init(&dt_dev, &dt_bus, &info);
+
+	node = dt_device_find_compatible(&dt_dev, "virtio,mmio");
+	assert(node >= 0 || node == -FDT_ERR_NOTFOUND);
+
+	if (node == -FDT_ERR_NOTFOUND)
+		return NULL;
+
+	vmdev = vm_new_device(devid);
+	vmdev->base = info.base;
+
+	return &vmdev->vdev;
+}
diff --git a/lib/virtio.h b/lib/virtio.h
new file mode 100644
index 0000000000000..163b9912c4e05
--- /dev/null
+++ b/lib/virtio.h
@@ -0,0 +1,89 @@
+#ifndef _VIRTIO_H_
+#define _VIRTIO_H_
+/*
+ * A minimal implementation of virtio for virtio-mmio config space
+ * access.
+ *
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "libcflat.h"
+
+struct virtio_devid {
+	u32 device;
+	u32 vendor;
+};
+
+struct virtio_dev {
+	struct virtio_devid id;
+	struct virtio_conf_ops *config;
+};
+
+struct virtio_conf_ops {
+	void (*get)(struct virtio_dev *vdev, unsigned offset,
+		    void *buf, unsigned len);
+	void (*set)(struct virtio_dev *vdev, unsigned offset,
+		    const void *buf, unsigned len);
+};
+
+extern struct virtio_dev *virtio_bind(u32 devid);
+
+static inline u8
+virtio_config_readb(struct virtio_dev *vdev, unsigned offset)
+{
+	u8 val;
+	vdev->config->get(vdev, offset, &val, 1);
+	return val;
+}
+
+static inline u16
+virtio_config_readw(struct virtio_dev *vdev, unsigned offset)
+{
+	u16 val;
+	vdev->config->get(vdev, offset, &val, 2);
+	return val;
+}
+
+static inline u32
+virtio_config_readl(struct virtio_dev *vdev, unsigned offset)
+{
+	u32 val;
+	vdev->config->get(vdev, offset, &val, 4);
+	return val;
+}
+
+static inline void
+virtio_config_writeb(struct virtio_dev *vdev, unsigned offset, u8 val)
+{
+	vdev->config->set(vdev, offset, &val, 1);
+}
+
+static inline void
+virtio_config_writew(struct virtio_dev *vdev, unsigned offset, u16 val)
+{
+	vdev->config->set(vdev, offset, &val, 2);
+}
+
+static inline void
+virtio_config_writel(struct virtio_dev *vdev, unsigned offset, u32 val)
+{
+	vdev->config->set(vdev, offset, &val, 4);
+}
+
+/******************************************************
+ * virtio-mmio
+ ******************************************************/
+
+#define VIRTIO_MMIO_DEVICE_ID	0x008
+#define VIRTIO_MMIO_CONFIG	0x100
+
+#define to_virtio_mmio_dev(vdev_ptr) \
+	container_of(vdev_ptr, struct virtio_mmio_dev, vdev)
+
+struct virtio_mmio_dev {
+	struct virtio_dev vdev;
+	void *base;
+};
+
+#endif /* _VIRTIO_H_ */
-- 
1.8.1.4


  parent reply	other threads:[~2014-04-10 16:57 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-10 16:56 [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Andrew Jones
2014-04-10 16:56 ` [PATCH v4 01/19] remove unused files Andrew Jones
2014-06-06 18:37   ` Christoffer Dall
2014-06-09  8:11     ` Andrew Jones
2014-06-25 12:14       ` Alexander Graf
2014-04-10 16:56 ` [PATCH v4 02/19] makefile and run_tests tweaks Andrew Jones
2014-06-06 18:37   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 03/19] clean root dir of all x86-ness Andrew Jones
2014-06-06 18:37   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 04/19] add distclean target and gitignore more Andrew Jones
2014-06-06 18:37   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 05/19] add 'make cscope' support Andrew Jones
2014-06-06 18:38   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 07/19] libfdt: get libfdt to build Andrew Jones
2014-06-06 18:38   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 08/19] add support for Linux device trees Andrew Jones
2014-06-06 18:38   ` Christoffer Dall
2014-06-09 10:18     ` Andrew Jones
2014-06-09 10:45       ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 09/19] libcflat: add abort() and assert() Andrew Jones
2014-06-06 18:38   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 10/19] Introduce asm-generic/*.h files Andrew Jones
2014-06-06 18:39   ` Christoffer Dall
2014-06-09  8:23     ` Andrew Jones
2014-06-09  9:08       ` Christoffer Dall
2014-06-09  9:54         ` Andrew Jones
2014-06-09 11:39           ` Andrew Jones
2014-06-09 12:34             ` Christoffer Dall
2014-06-09 13:52               ` Andrew Jones
2014-06-09 15:34                 ` Christoffer Dall
2014-04-10 16:56 ` Andrew Jones [this message]
2014-06-06 18:39   ` [PATCH v4 11/19] add minimal virtio support for devtree virtio-mmio Christoffer Dall
2014-06-09  9:02     ` Andrew Jones
2014-06-09  9:14       ` Christoffer Dall
2014-06-09 10:21         ` Andrew Jones
2014-04-10 16:56 ` [PATCH v4 12/19] Introduce virtio-testdev Andrew Jones
2014-06-06 18:39   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 13/19] libcflat: clean up libcflat.h and add string.h Andrew Jones
2014-06-06 18:39   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 14/19] printf: support field padding Andrew Jones
2014-06-06 18:39   ` Christoffer Dall
2014-04-10 16:56 ` [PATCH v4 15/19] arm: initial drop Andrew Jones
2014-06-06 18:39   ` Christoffer Dall
2014-06-09  9:44     ` Andrew Jones
2014-04-10 16:56 ` [PATCH v4 16/19] arm: Add spinlock implementation Andrew Jones
2014-04-10 16:56 ` [PATCH v4 17/19] arm: Add IO accessors to avoid register-writeback Andrew Jones
2014-04-10 16:56 ` [PATCH v4 18/19] arm: add useful headers from the Linux kernel Andrew Jones
2014-06-06 18:40   ` Christoffer Dall
2014-04-10 16:57 ` [PATCH v4 19/19] arm: vectors support Andrew Jones
2014-06-06 18:40   ` Christoffer Dall
     [not found] ` <1397149020-3501-7-git-send-email-drjones@redhat.com>
2014-06-06 18:38   ` [PATCH v4 06/19] libfdt: Import libfdt source Christoffer Dall
2014-06-06 18:41 ` [PATCH v4 00/19] kvm-unit-tests/arm: initial drop Christoffer Dall
2014-06-09  9:51   ` Andrew Jones
2014-06-09  9:57     ` Christoffer Dall

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1397149020-3501-12-git-send-email-drjones@redhat.com \
    --to=drjones@redhat.com \
    --cc=christoffer.dall@linaro.org \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.cs.columbia.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.