|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH RFC 02/23] plat/platform: Introduce new platform bus
platform bus is a simple bus interface for many devices, including
virtio_mmio device on arm64
Signed-off-by: Jia He <justin.he@xxxxxxx>
---
plat/common/include/platform_bus.h | 100 ++++++++++++
plat/common/platform_bus.c | 236 +++++++++++++++++++++++++++++
2 files changed, 336 insertions(+)
create mode 100644 plat/common/include/platform_bus.h
create mode 100644 plat/common/platform_bus.c
diff --git a/plat/common/include/platform_bus.h
b/plat/common/include/platform_bus.h
new file mode 100644
index 00000000..b293673a
--- /dev/null
+++ b/plat/common/include/platform_bus.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Jia He <justin.he@xxxxxxx>
+ *
+ * Copyright (c) 2018, Arm Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+
+#ifndef __UKPLAT_COMMON_PF_BUS_H__
+#define __UKPLAT_COMMON_PF_BUS_H__
+
+#include <uk/bus.h>
+#include <uk/alloc.h>
+
+/**
+ * A structure describing an ID for a Platform driver. Each driver provides a
+ * table of these IDs for each device that it supports.
+ */
+#define PLATFORM_DEVICE_ID_START (0x100)
+#define VIRTIO_MMIO_ID PLATFORM_DEVICE_ID_START
+#define PLATFORM_DEVICE_ID_END (PLATFORM_DEVICE_ID_START + 0x100)
+
+#define UK_MAX_VIRTIO_MMIO_DEVICE (0x2)
+
+struct pf_device_id {
+ uint16_t device_id;
+};
+
+struct pf_device;
+
+typedef int (*pf_driver_add_func_t)(struct pf_device *);
+typedef int (*pf_driver_init_func_t)(struct uk_alloc *a);
+
+struct pf_driver {
+ UK_TAILQ_ENTRY(struct pf_driver) next;
+ const struct pf_device_id *device_ids;
+ pf_driver_init_func_t init; /* optional */
+ pf_driver_add_func_t add_dev;
+};
+UK_TAILQ_HEAD(pf_driver_list, struct pf_driver);
+
+enum pf_device_state {
+ PF_DEVICE_STATE_RESET = 0,
+ PF_DEVICE_STATE_RUNNING
+};
+
+struct pf_device {
+ UK_TAILQ_ENTRY(struct pf_device) next; /**< used by pf_bus_handler */
+ struct pf_device_id id;
+ struct pf_driver *drv;
+ enum pf_device_state state;
+
+ uint64_t base;
+ unsigned long irq;
+};
+UK_TAILQ_HEAD(pf_device_list, struct pf_device);
+
+
+#define PF_REGISTER_DRIVER(b) \
+ _PF_REGISTER_DRIVER(__LIBNAME__, b)
+
+#define _PF_REGFNNAME(x, y) x##y
+
+#define _PF_REGISTER_DRIVER(libname, b) \
+ static void __constructor_prio(105) \
+ _PF_REGFNNAME(libname, _pf_register_driver)(void) \
+ { \
+ _pf_register_driver((b)); \
+ }
+
+/* Do not use this function directly: */
+void _pf_register_driver(struct pf_driver *drv);
+
+#endif /* __UKPLAT_COMMON_PF_BUS_H__ */
diff --git a/plat/common/platform_bus.c b/plat/common/platform_bus.c
new file mode 100644
index 00000000..f4af190e
--- /dev/null
+++ b/plat/common/platform_bus.c
@@ -0,0 +1,236 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Jia He <justin.he@xxxxxxx>
+ *
+ * Copyright (c) 2018, Arm Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+
+#include <string.h>
+#include <uk/print.h>
+#include <uk/plat/common/cpu.h>
+#include <platform_bus.h>
+#include <libfdt.h>
+#include <kvm/config.h>
+#include <gic/gic-v2.h>
+#include <ofw/fdt.h>
+
+#define fdt_start (_libkvmplat_cfg.dtb)
+
+struct pf_bus_handler {
+ struct uk_bus b;
+ struct uk_alloc *a;
+ struct pf_driver_list drv_list; /**< List of platform drivers */
+ int drv_list_initialized;
+ struct pf_device_list dev_list; /**< List of platform devices */
+};
+static struct pf_bus_handler pfh;
+
+static const char * const pf_device_list[] = {
+ "virtio,mmio",
+};
+
+static inline int pf_device_id_match(const struct pf_device_id *id0,
+ const struct pf_device_id *id1)
+{
+ int rc = 0;
+
+ if (id0->device_id == id1->device_id)
+ rc = 1;
+
+ return rc;
+}
+
+static inline struct pf_driver *pf_find_driver(struct pf_device_id *id)
+{
+ struct pf_driver *drv;
+
+ UK_TAILQ_FOREACH(drv, &pfh.drv_list, next) {
+ if (pf_device_id_match(id, drv->device_ids)) {
+ uk_pr_debug("pf driver found devid=%d\n",
drv->device_ids->device_id);
+ return drv; /* driver found */
+ }
+ }
+
+ uk_pr_info("no pf driver found\n");
+
+ return NULL; /* no driver found */
+}
+
+static inline int pf_driver_add_device(struct pf_driver *drv,
+ struct pf_device_id *devid,
+ __u64 dev_base,
+ int dev_irq)
+{
+ struct pf_device *dev;
+ int ret;
+
+ UK_ASSERT(drv != NULL);
+ UK_ASSERT(drv->add_dev != NULL);
+
+ dev = (struct pf_device *) uk_calloc(pfh.a, 1, sizeof(*dev));
+ if (!dev) {
+ uk_pr_err("Platform : Failed to initialize: Out of memory!\n");
+ return -ENOMEM;
+ }
+
+ memcpy(&dev->id, devid, sizeof(dev->id));
+ uk_pr_debug("pf_driver_add_device dev->id=%d\n", dev->id.device_id);
+
+ dev->base = dev_base;
+ dev->irq = dev_irq;
+
+ ret = drv->add_dev(dev);
+ if (ret < 0) {
+ uk_pr_err("Platform Failed to initialize device driver\n");
+ uk_free(pfh.a, dev);
+ }
+
+ return ret;
+}
+
+static int pf_probe(void)
+{
+ struct pf_device_id devid;
+ struct pf_driver *drv;
+ int i;
+ int end_offset = -1;
+ int ret = -ENODEV;
+ const fdt32_t *prop;
+ int type, hwirq, prop_len;
+ __u64 reg_base;
+ __phys_addr dev_base;
+ int dev_irq;
+
+ uk_pr_info("Probe PF\n");
+
+ /* We only support virtio_mmio as a platform device here.
+ * A loop here is needed for finding drivers if more devices
+ */
+ devid.device_id = VIRTIO_MMIO_ID;
+
+ drv = pf_find_driver(&devid);
+ if (!drv) {
+ uk_pr_info("<no driver>\n");
+ return -ENODEV;
+ }
+
+ uk_pr_info("driver %p\n", drv);
+
+ /* qemu creates virtio devices in reverse order */
+ for (i = 0; i < UK_MAX_VIRTIO_MMIO_DEVICE; i++) {
+ end_offset = fdt_node_offset_by_compatible_list(fdt_start,
+ end_offset,
+ pf_device_list);
+ if (end_offset == -FDT_ERR_NOTFOUND) {
+ uk_pr_info("device not found in fdt\n");
+ goto error_exit;
+ } else {
+ prop = fdt_getprop(fdt_start, end_offset, "interrupts",
&prop_len);
+ if (!prop) {
+ uk_pr_err("irq of device not found in fdt\n");
+ goto error_exit;
+ }
+
+ type = fdt32_to_cpu(prop[0]);
+ hwirq = fdt32_to_cpu(prop[1]);
+
+ prop = fdt_getprop(fdt_start, end_offset, "reg",
&prop_len);
+ if (!prop) {
+ uk_pr_err("reg of device not found in fdt\n");
+ goto error_exit;
+ }
+
+ /* only care about base addr, ignore the size */
+ reg_base = fdt32_to_cpu(prop[0]);
+ reg_base = reg_base << 32 | fdt32_to_cpu(prop[1]);
+ }
+
+ dev_base = reg_base;
+ dev_irq = gic_irq_translate(type, hwirq);
+
+ ret = pf_driver_add_device(drv, &devid, dev_base, dev_irq);
+ }
+
+ return ret;
+
+error_exit:
+ return -ENODEV;
+}
+
+
+static int pf_init(struct uk_alloc *a)
+{
+ struct pf_driver *drv, *drv_next;
+ int ret = 0;
+
+ UK_ASSERT(a != NULL);
+
+ pfh.a = a;
+
+ if (!pfh.drv_list_initialized) {
+ UK_TAILQ_INIT(&pfh.drv_list);
+ pfh.drv_list_initialized = 1;
+ }
+ UK_TAILQ_INIT(&pfh.dev_list);
+
+ UK_TAILQ_FOREACH_SAFE(drv, &pfh.drv_list, next, drv_next) {
+ if (drv->init) {
+ ret = drv->init(a);
+ if (ret == 0)
+ continue;
+ uk_pr_err("Failed to initialize pf driver %p: %d\n",
+ drv, ret);
+ UK_TAILQ_REMOVE(&pfh.drv_list, drv, next);
+ }
+ }
+ return 0;
+}
+
+void _pf_register_driver(struct pf_driver *drv)
+{
+ UK_ASSERT(drv != NULL);
+ uk_pr_debug("_pf_register_driver %p\n", drv);
+
+ if (!pfh.drv_list_initialized) {
+ UK_TAILQ_INIT(&pfh.drv_list);
+ pfh.drv_list_initialized = 1;
+ }
+ UK_TAILQ_INSERT_TAIL(&pfh.drv_list, drv, next);
+}
+
+
+/* Register this bus driver to libukbus:
+ */
+static struct pf_bus_handler pfh = {
+ .b.init = pf_init,
+ .b.probe = pf_probe
+};
+UK_BUS_REGISTER(&pfh.b);
+
--
2.17.1
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |