[PATCH 02/10] PARAVIRTUALIZATION: Add support for a bus abstraction

Gregory Haskins
2007-08-16T23:14:07Z

PV usually comes in two flavors: device PV, and "core" PV. The existing PV
ops deal in terms of the latter. However, it would be useful to add an
interface for a virtual bus with provisions for discovery/configuration of
backend PV devices. Often times it is desirable to run PV devices even if the
entire core is not operating with PVOPS. Therefore, we introduce a separate
interface to deal with the devices.

Signed-off-by: Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
---

arch/i386/Kconfig | 2 +
arch/x86_64/Kconfig | 2 +
drivers/Makefile | 1
drivers/pvbus/Kconfig | 7 ++
drivers/pvbus/Makefile | 6 ++
drivers/pvbus/pvbus-driver.c | 120 ++++++++++++++++++++++++++++++++++++++++++
include/linux/pvbus.h | 59 +++++++++++++++++++++
7 files changed, 197 insertions(+), 0 deletions(-)

diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index c2d54b8..acf4506 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -1125,6 +1125,8 @@ source "drivers/pci/pcie/Kconfig"

source "drivers/pci/Kconfig"

+source "drivers/pvbus/Kconfig"
+
config ISA_DMA_API
bool
default y
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 145bb82..17d6c78 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -721,6 +721,8 @@ source "drivers/pcmcia/Kconfig"

source "drivers/pci/hotplug/Kconfig"

+source "drivers/pvbus/Kconfig"
+
endmenu

diff --git a/drivers/Makefile b/drivers/Makefile
index adad2f3..179e669 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -81,3 +81,4 @@ obj-$(CONFIG_GENERIC_TIME) += clocksource/
obj-$(CONFIG_DMA_ENGINE) += dma/
obj-$(CONFIG_HID) += hid/
obj-$(CONFIG_PPC_PS3) += ps3/
+obj-$(CONFIG_PVBUS) += pvbus/
diff --git a/drivers/pvbus/Kconfig b/drivers/pvbus/Kconfig
new file mode 100644
index 0000000..1ca094d
--- /dev/null
+++ b/drivers/pvbus/Kconfig
@@ -0,0 +1,7 @@
+#
+# PVBUS configuration
+#
+
+config PVBUS
+ bool "Paravirtual Bus"
+
diff --git a/drivers/pvbus/Makefile b/drivers/pvbus/Makefile
new file mode 100644
index 0000000..0df2c2e
--- /dev/null
+++ b/drivers/pvbus/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the PVBUS bus specific drivers.
+#
+
+obj-y += pvbus-driver.o
+
diff --git a/drivers/pvbus/pvbus-driver.c b/drivers/pvbus/pvbus-driver.c
new file mode 100644
index 0000000..3f6687d
--- /dev/null
+++ b/drivers/pvbus/pvbus-driver.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2007 Novell. All Rights Reserved.
+ *
+ * Paravirtualized-Bus - This is a generic infrastructure for virtual devices
+ * and their drivers. It is inspired by Rusty Russell's lguest_bus, but with
+ * the key difference that the bus is decoupled from the underlying hypervisor
+ * in both name and function.
+ *
+ * Instead, it is intended that external hypervisor support will register
+ * arbitrary devices. Generic drivers can then monitor this bus for
+ * compatible devices regardless of the hypervisor implementation.
+ *
+ * Author:
+ * Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/pvbus.h>
+
+#define PVBUS_NAME "pvbus"
+
+/*
+ * This function is invoked whenever a new driver and/or device is added
+ * to check if there is a match
+ */
+static int pvbus_dev_match(struct device *_dev, struct device_driver *_drv)
+{
+ struct pvbus_device *dev = container_of(_dev,struct pvbus_device,dev);
+ struct pvbus_driver *drv = container_of(_drv,struct pvbus_driver,drv);
+
+ return !strcmp(dev->name, drv->name);
+}
+
+/*
+ * This function is invoked after the bus infrastructure has already made a
+ * match. The device will contain a reference to the paired driver which
+ * we will extract.
+ */
+static int pvbus_dev_probe(struct device *_dev)
+{
+ int ret = 0;
+ struct pvbus_device*dev = container_of(_dev,struct pvbus_device, dev);
+ struct pvbus_driver*drv = container_of(_dev->driver,
+ struct pvbus_driver, drv);
+
+ if (drv->probe)
+ ret = drv->probe(dev);
+
+ return ret;
+}
+
+static struct bus_type pv_bus = {
+ .name = PVBUS_NAME,
+ .match = pvbus_dev_match,
+};
+
+static struct device pvbus_rootdev = {
+ .parent = NULL,
+ .bus_id = PVBUS_NAME,
+};
+
+static int __init pvbus_init(void)
+{
+ int ret;
+
+ ret = bus_register(&pv_bus);
+ BUG_ON(ret < 0);
+
+ ret = device_register(&pvbus_rootdev);
+ BUG_ON(ret < 0);
+
+ return 0;
+}
+
+postcore_initcall(pvbus_init);
+
+int pvbus_device_register(struct pvbus_device *new)
+{
+ new->dev.parent = &pvbus_rootdev;
+ new->dev.bus = &pv_bus;
+
+ return device_register(&new->dev);
+}
+EXPORT_SYMBOL(pvbus_device_register);
+
+void pvbus_device_unregister(struct pvbus_device *dev)
+{
+ device_unregister(&dev->dev);
+}
+EXPORT_SYMBOL(pvbus_device_unregister);
+
+int pvbus_driver_register(struct pvbus_driver *new)
+{
+ new->drv.bus = &pv_bus;
+ new->drv.name = new->name;
+ new->drv.owner = new->owner;
+ new->drv.probe = pvbus_dev_probe;
+
+ return driver_register(&new->drv);
+}
+EXPORT_SYMBOL(pvbus_driver_register);
+
+void pvbus_driver_unregister(struct pvbus_driver *drv)
+{
+ driver_unregister(&drv->drv);
+}
+EXPORT_SYMBOL(pvbus_driver_unregister);
+
diff --git a/include/linux/pvbus.h b/include/linux/pvbus.h
new file mode 100644
index 0000000..471f500
--- /dev/null
+++ b/include/linux/pvbus.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2007 Novell. All Rights Reserved.
+ *
+ * Paravirtualized-Bus
+ *
+ * Author:
+ * Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _LINUX_PVBUS_H
+#define _LINUX_PVBUS_H
+
+#include <linux/device.h>
+#include <linux/ioq.h>
+
+struct pvbus_device {
+ char *name;
+ u64 id;
+
+ void *priv; /* Used by drivers that allocated the dev */
+
+ int (*createqueue)(struct pvbus_device *dev, struct ioq **ioq,
+ size_t ringsize, int flags);
+ int (*call)(struct pvbus_device *dev, u32 func,
+ void *data, size_t len, int flags);
+
+ struct device dev;
+};
+
+int pvbus_device_register(struct pvbus_device *dev);
+void pvbus_device_unregister(struct pvbus_device *dev);
+
+struct pvbus_driver {
+ char *name;
+ struct module *owner;
+
+ int (*probe)(struct pvbus_device *pdev);
+ int (*remove)(struct pvbus_device *pdev);
+
+ struct device_driver drv;
+};
+
+int pvbus_driver_register(struct pvbus_driver *drv);
+void pvbus_driver_unregister(struct pvbus_driver *drv);
+
+#endif /* _LINUX_PVBUS_H */