|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH v3 2/2] plat/kvm: Add initial PCI bus driver for x86_64
From: Sharan Santhanam <sharan.santhanam@xxxxxxxxx>
Introduces the first & initial version of PCI bus driver.
It is able to iterate over PCI devices and detect
if an driver is available. It is going to call a driver
callback function to handover initialization for each
found device.
Although the code is put to `plat/common` it has some
dependency to KVM x86_64 with the I/O functions. These
functions should be moved to the appropriate place on
successive patches for PCI.
Signed-off-by: Simon Kuenzer <simon.kuenzer@xxxxxxxxx>
Signed-off-by: Sharan Santhanam <sharan.santhanam@xxxxxxxxx>
---
plat/common/include/pci/pci_bus.h | 227 ++++++++++++++++++++++++++
plat/common/pci_bus.c | 324 ++++++++++++++++++++++++++++++++++++++
plat/kvm/Config.uk | 11 +-
plat/kvm/Makefile.uk | 5 +
4 files changed, 565 insertions(+), 2 deletions(-)
create mode 100644 plat/common/include/pci/pci_bus.h
create mode 100644 plat/common/pci_bus.c
diff --git a/plat/common/include/pci/pci_bus.h
b/plat/common/include/pci/pci_bus.h
new file mode 100644
index 0000000..b03bcfd
--- /dev/null
+++ b/plat/common/include/pci/pci_bus.h
@@ -0,0 +1,227 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Simon Kuenzer <simon.kuenzer@xxxxxxxxx>
+ *
+ * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation. 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.
+ */
+/*
+ * Copyright(c) 2010-2015 Intel Corporation.
+ * Copyright 2013-2014 6WIND S.A.
+ *
+ * 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.
+ */
+
+#ifndef __UKPLAT_COMMON_PCI_BUS_H__
+#define __UKPLAT_COMMON_PCI_BUS_H__
+
+#include <uk/bus.h>
+#include <uk/alloc.h>
+
+/**
+ * A structure describing an ID for a PCI driver. Each driver provides a
+ * table of these IDs for each device that it supports.
+ * * Derived from: lib/librte_pci/rte_pci.h
+ */
+struct pci_device_id {
+ /**< Class ID or PCI_CLASS_ANY_ID. */
+ uint32_t class_id;
+ /**< Vendor ID or PCI_ANY_ID. */
+ uint16_t vendor_id;
+ /**< Device ID or PCI_ANY_ID. */
+ uint16_t device_id;
+ /**< Subsystem vendor ID or PCI_ANY_ID. */
+ uint16_t subsystem_vendor_id;
+ /**< Subsystem device ID or PCI_ANY_ID. */
+ uint16_t subsystem_device_id;
+};
+
+/** Any PCI device identifier (vendor, device, ...) */
+#define PCI_ANY_ID (0xffff)
+#define PCI_CLASS_ANY_ID (0xffffff)
+
+/**
+ * Macros used to help building up tables of device IDs
+ * Derived from: lib/librte_pci/rte_pci.h
+ */
+#define PCI_DEVICE_ID(vend, dev) \
+ .class_id = PCI_CLASS_ANY_ID, \
+ .vendor_id = (vend), \
+ .device_id = (dev), \
+ .subsystem_vendor_id = PCI_ANY_ID, \
+ .subsystem_device_id = PCI_ANY_ID
+
+#define PCI_ANY_DEVICE_ID \
+ .class_id = PCI_CLASS_ANY_ID, \
+ .vendor_id = PCI_ANY_ID, \
+ .device_id = PCI_ANY_ID, \
+ .subsystem_vendor_id = PCI_ANY_ID, \
+ .subsystem_device_id = PCI_ANY_ID
+
+/**
+ * A structure describing the location of a PCI device.
+ * Derived from: lib/librte_pci/rte_pci.h
+ */
+struct pci_address {
+ /**< Device domain */
+ uint32_t domain;
+ /**< Device bus */
+ uint8_t bus;
+ /**< Device ID */
+ uint8_t devid;
+ /**< Device function. */
+ uint8_t function;
+};
+
+struct pci_device;
+
+typedef int (*pci_driver_add_func_t)(struct pci_device *);
+typedef int (*pci_driver_init_func_t)(struct uk_alloc *a);
+
+struct pci_driver {
+ UK_TAILQ_ENTRY(struct pci_driver) next;
+ /**< ANY-ID terminated list of device IDs that the driver handles */
+ const struct pci_device_id *device_ids;
+ pci_driver_init_func_t init; /* optional */
+ pci_driver_add_func_t add_dev;
+};
+UK_TAILQ_HEAD(pci_driver_list, struct pci_driver);
+
+enum pci_device_state {
+ PCI_DEVICE_STATE_RESET = 0,
+ PCI_DEVICE_STATE_RUNNING
+};
+
+struct pci_device {
+ UK_TAILQ_ENTRY(struct pci_device) next; /**< used by pci_bus_handler */
+ struct pci_device_id id;
+ struct pci_address addr;
+ struct pci_driver *drv;
+ enum pci_device_state state;
+
+ uint16_t base;
+ unsigned long irq;
+};
+UK_TAILQ_HEAD(pci_device_list, struct pci_device);
+
+
+#define PCI_REGISTER_DRIVER(b) \
+ _PCI_REGISTER_DRIVER(__LIBNAME__, b)
+
+#define _PCI_REGFNNAME(x, y) x##y
+
+#define _PCI_REGISTER_DRIVER(libname, b) \
+ static void __constructor_prio(103) \
+ PCI_REGFNNAME(libname, _pci_register_driver)(void) \
+ { \
+ _pci_register_driver((b)); \
+ }
+
+/* Do not use this function directly: */
+void _pci_register_driver(struct pci_driver *drv);
+
+
+/* TODO: Move these I/O functions to architecture/platform specific
+ * implementation. They are used to interact with the PCI bus.
+ * They work for x86_64 only for now
+ */
+static inline uint8_t inb(uint16_t port)
+{
+ uint8_t v;
+
+ __asm__ __volatile__("inb %1,%0" : "=a" (v) : "dN" (port));
+ return v;
+}
+static inline uint16_t inw(uint16_t port)
+{
+ uint16_t v;
+
+ __asm__ __volatile__("inw %1,%0" : "=a" (v) : "dN" (port));
+ return v;
+}
+static inline uint32_t inl(uint16_t port)
+{
+ uint32_t v;
+
+ __asm__ __volatile__("inl %1,%0" : "=a" (v) : "dN" (port));
+ return v;
+}
+
+static inline uint64_t inq(uint16_t port_lo)
+{
+ uint16_t port_hi = port_lo + 4;
+ uint32_t lo, hi;
+
+ __asm__ __volatile__("inl %1,%0" : "=a" (lo) : "dN" (port_lo));
+ __asm__ __volatile__("inl %1,%0" : "=a" (hi) : "dN" (port_hi));
+
+ return ((uint64_t)lo) | ((uint64_t)hi << 32);
+}
+
+static inline void outb(uint16_t port, uint8_t v)
+{
+ __asm__ __volatile__("outb %0,%1" : : "a" (v), "dN" (port));
+}
+
+static inline void outw(uint16_t port, uint16_t v)
+{
+ __asm__ __volatile__("outw %0,%1" : : "a" (v), "dN" (port));
+}
+
+static inline void outl(uint16_t port, uint32_t v)
+{
+ __asm__ __volatile__("outl %0,%1" : : "a" (v), "dN" (port));
+}
+
+#endif /* __UKPLAT_COMMON_PCI_BUS_H__ */
diff --git a/plat/common/pci_bus.c b/plat/common/pci_bus.c
new file mode 100644
index 0000000..c19545e
--- /dev/null
+++ b/plat/common/pci_bus.c
@@ -0,0 +1,324 @@
+/* TODO: SPDX Header */
+/*
+ * Authors: Simon Kuenzer <simon.kuenzer@xxxxxxxxx>
+ *
+ * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation. 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.
+ */
+/* Some code was derived from Solo5: */
+/*
+ * Copyright (c) 2015-2017 Contributors as noted in the AUTHORS file
+ *
+ * This file is part of Solo5, a unikernel base layer.
+ *
+ * Permission to use, copy, modify, and/or distribute this software
+ * for any purpose with or without fee is hereby granted, provided
+ * that the above copyright notice and this permission notice appear
+ * in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <string.h>
+#include <uk/print.h>
+#include <pci_bus.h>
+
+struct pci_bus_handler {
+ struct uk_bus b;
+ struct uk_alloc *a;
+ struct pci_driver_list drv_list; /**< List of PCI drivers */
+ int drv_list_initialized;
+ struct pci_device_list dev_list; /**< List of PCI devices */
+};
+static struct pci_bus_handler ph;
+
+#define FOREACH_DRIVER(drv) \
+ UK_TAILQ_FOREACH(drv, &ph.drv_list, next)
+
+#define FOREACH_DRIVER_SAFE(drv, drv_next) \
+ UK_TAILQ_FOREACH_SAFE(drv, &ph.drv_list, next, drv_next)
+
+#define FOREACH_DEVICE(dev) \
+ UK_TAILQ_FOREACH(dev, &ph.dev_list, ph_next)
+
+#define PCI_INVALID_ID (0xFFFF)
+#define PCI_DEVICE_ID_MASK (0xFFFF)
+
+#define PCI_CONFIG_ADDR (0xCF8)
+#define PCI_CONFIG_DATA (0xCFC)
+
+/* 8 bits for bus number, 5 bits for devices */
+#define PCI_MAX_BUSES (1 << 8)
+#define PCI_MAX_DEVICES (1 << 5)
+
+#define PCI_BUS_SHIFT (16)
+#define PCI_DEVICE_SHIFT (11)
+#define PCI_ENABLE_BIT (1 << 31)
+
+#define PCI_CONF_SUBSYS_ID (0x2c)
+#define PCI_CONF_SUBSYS_ID_SHFT (16)
+#define PCI_CONF_SUBSYS_ID_MASK (0xFFFF)
+
+#define PCI_CONF_IRQ (0X3C)
+#define PCI_CONF_IRQ_SHFT (0x0)
+#define PCI_CONF_IRQ_MASK (0XFF)
+
+#define PCI_CONF_IOBAR (0x10)
+#define PCI_CONF_IOBAR_SHFT (0x0)
+#define PCI_CONF_IOBAR_MASK (~0x3)
+
+#define PCI_CONF_READ(type, ret, a, s) \
+ do { \
+ uint32_t _conf_data; \
+ outl(PCI_CONFIG_ADDR, (a) | PCI_CONF_##s); \
+ _conf_data = ((inl(PCI_CONFIG_DATA) >> PCI_CONF_##s##_SHFT) \
+ & PCI_CONF_##s##_MASK); \
+ *(ret) = (type) _conf_data; \
+ } while (0)
+
+static inline int pci_device_id_match(const struct pci_device_id *id0,
+ const struct pci_device_id *id1)
+{
+ if ((id0->class_id != PCI_CLASS_ANY_ID) &&
+ (id1->class_id != PCI_CLASS_ANY_ID) &&
+ (id0->class_id != id1->class_id)) {
+ return 0;
+ }
+ if ((id0->vendor_id != PCI_ANY_ID) &&
+ (id1->vendor_id != PCI_ANY_ID) &&
+ (id0->vendor_id != id1->vendor_id)) {
+ return 0;
+ }
+ if ((id0->device_id != PCI_ANY_ID) &&
+ (id1->device_id != PCI_ANY_ID) &&
+ (id0->device_id != id1->device_id)) {
+ return 0;
+ }
+ if ((id0->subsystem_vendor_id != PCI_ANY_ID) &&
+ (id1->subsystem_vendor_id != PCI_ANY_ID) &&
+ (id0->subsystem_vendor_id != id1->subsystem_vendor_id)) {
+ return 0;
+ }
+ if ((id0->subsystem_device_id != PCI_ANY_ID) &&
+ (id1->subsystem_device_id != PCI_ANY_ID) &&
+ (id0->subsystem_device_id != id1->subsystem_device_id)) {
+ return 0;
+ }
+ return 1;
+}
+
+static inline int pci_device_id_is_any(const struct pci_device_id *id)
+{
+ if ((id->class_id == PCI_CLASS_ANY_ID) &&
+ (id->vendor_id == PCI_ANY_ID) &&
+ (id->device_id == PCI_ANY_ID) &&
+ (id->subsystem_vendor_id == PCI_ANY_ID) &&
+ (id->subsystem_device_id == PCI_ANY_ID)) {
+ return 1;
+ }
+ return 0;
+}
+
+static inline struct pci_driver *pci_find_driver(struct pci_device_id *id)
+{
+ struct pci_driver *drv;
+ const struct pci_device_id *drv_id;
+
+ FOREACH_DRIVER(drv) {
+ for (drv_id = drv->device_ids;
+ !pci_device_id_is_any(drv_id);
+ drv_id++) {
+ if (pci_device_id_match(id, drv_id))
+ return drv;
+ }
+ }
+ return NULL; /* no driver found */
+}
+
+static inline int pci_driver_add_device(struct pci_driver *drv,
+ struct pci_address *addr,
+ struct pci_device_id *devid)
+{
+ struct pci_device *dev;
+ uint32_t config_addr;
+ int ret;
+
+ UK_ASSERT(drv != NULL);
+ UK_ASSERT(drv->add_dev != NULL);
+ UK_ASSERT(addr != NULL);
+ UK_ASSERT(devid != NULL);
+
+ dev = (struct pci_device *) uk_calloc(ph.a, 1, sizeof(*dev));
+ if (!dev) {
+ uk_printd(DLVL_ERR,
+ "PCI %02x:%02x.%02x: Failed to initialize: Out
of memory!\n",
+ (int) addr->bus,
+ (int) addr->devid,
+ (int) addr->function);
+ return -ENOMEM;
+ }
+
+ memcpy(&dev->id, devid, sizeof(dev->id));
+ memcpy(&dev->addr, addr, sizeof(dev->addr));
+ dev->drv = drv;
+
+ config_addr = (PCI_ENABLE_BIT)
+ | (addr->bus << PCI_BUS_SHIFT)
+ | (addr->devid << PCI_DEVICE_SHIFT);
+ PCI_CONF_READ(uint16_t, &dev->base, config_addr, IOBAR);
+ PCI_CONF_READ(uint8_t, &dev->irq, config_addr, IRQ);
+
+ ret = drv->add_dev(dev);
+ if (ret < 0) {
+ uk_printd(DLVL_ERR,
+ "PCI %02x:%02x.%02x: Failed to initialize device
driver\n",
+ (int) addr->bus,
+ (int) addr->devid,
+ (int) addr->function);
+ uk_free(ph.a, dev);
+ }
+ return 0;
+}
+
+static int pci_probe(void)
+{
+ struct pci_address addr;
+ struct pci_device_id devid;
+ struct pci_driver *drv;
+ uint32_t config_addr, config_data;
+ uint32_t bus;
+ uint8_t dev;
+
+ uk_printd(DLVL_EXTRA, "Probe PCI\n");
+
+ for (bus = 0; bus < PCI_MAX_BUSES; ++bus) {
+ for (dev = 0; dev < PCI_MAX_DEVICES; ++dev) {
+ config_addr = (PCI_ENABLE_BIT)
+ | (bus << PCI_BUS_SHIFT)
+ | (dev << PCI_DEVICE_SHIFT);
+
+ outl(PCI_CONFIG_ADDR, config_addr);
+ config_data = inl(PCI_CONFIG_DATA);
+
+ /* TODO: Retrieve the device identfier */
+ addr.domain = 0x0;
+ addr.bus = bus;
+ addr.devid = dev;
+ /* TODO: Retrieve the function */
+ addr.function = 0x0;
+
+ devid.vendor_id = config_data & PCI_DEVICE_ID_MASK;
+ if (devid.vendor_id == PCI_INVALID_ID) {
+ /* Device doesn't exist */
+ continue;
+ }
+
+ /* TODO: Implement fetch more information from PCI */
+ devid.class_id = PCI_CLASS_ANY_ID;
+ /* TODO: Implement fetch more information from PCI */
+ devid.device_id = PCI_ANY_ID;
+ /* TODO: Implement fetch more information from PCI */
+ devid.subsystem_vendor_id = PCI_ANY_ID;
+ PCI_CONF_READ(uint16_t, &devid.subsystem_device_id,
+ config_addr, SUBSYS_ID);
+
+ uk_printd(DLVL_INFO, "PCI %02x:%02x.%02x (%04x
%04x:%04x): ",
+ (int) addr.bus,
+ (int) addr.devid,
+ (int) addr.function,
+ (int) devid.class_id,
+ (int) devid.vendor_id,
+ (int) devid.device_id);
+ drv = pci_find_driver(&devid);
+ if (!drv) {
+ uk_printd(DLVL_INFO, "<no driver>\n");
+ continue;
+ }
+ uk_printd(DLVL_INFO, "driver %p\n", drv);
+ pci_driver_add_device(drv, &addr, &devid);
+ }
+ }
+ return 0;
+}
+
+
+static int pci_init(struct uk_alloc *a)
+{
+ struct pci_driver *drv, *drv_next;
+ int ret = 0;
+
+ UK_ASSERT(a != NULL);
+
+ ph.a = a;
+
+ if (!ph.drv_list_initialized) {
+ UK_TAILQ_INIT(&ph.drv_list);
+ ph.drv_list_initialized = 1;
+ }
+ UK_TAILQ_INIT(&ph.dev_list);
+
+ FOREACH_DRIVER_SAFE(drv, drv_next) {
+ if (drv->init) {
+ ret = drv->init(a);
+ if (ret == 0)
+ continue;
+ uk_printd(DLVL_ERR, "Failed to initialize driver %p:
%d\n",
+ drv, ret);
+ UK_TAILQ_REMOVE(&ph.drv_list, drv, next);
+ }
+ }
+ return 0;
+}
+
+void _pci_register_driver(struct pci_driver *drv)
+{
+ UK_ASSERT(drv != NULL);
+
+ if (!ph.drv_list_initialized) {
+ UK_TAILQ_INIT(&ph.drv_list);
+ ph.drv_list_initialized = 1;
+ }
+ UK_TAILQ_INSERT_TAIL(&ph.drv_list, drv, next);
+}
+
+
+/* Register this bus driver to libukbus:
+ */
+static struct pci_bus_handler ph = {
+ .b.init = pci_init,
+ .b.probe = pci_probe
+};
+UK_BUS_REGISTER(&ph.b);
diff --git a/plat/kvm/Config.uk b/plat/kvm/Config.uk
index 622c4eb..967a07b 100644
--- a/plat/kvm/Config.uk
+++ b/plat/kvm/Config.uk
@@ -9,5 +9,12 @@ menuconfig PLAT_KVM
help
Create a Unikraft image that runs as a KVM guest
-#if (PLAT_KVM)
-#endif
+if (PLAT_KVM)
+config KVM_PCI
+ bool "PCI Bus Driver"
+ default y
+ depends on (ARCH_X86_64)
+ select LIBUKBUS
+ help
+ PCI bus driver for probing and operating PCI devices
+endif
diff --git a/plat/kvm/Makefile.uk b/plat/kvm/Makefile.uk
index b840c2f..2705fd1 100644
--- a/plat/kvm/Makefile.uk
+++ b/plat/kvm/Makefile.uk
@@ -7,14 +7,17 @@ $(eval $(call addplat_s,kvm,$(CONFIG_PLAT_KVM)))
## KVM platform library registration
##
$(eval $(call addplatlib,kvm,libkvmplat))
+$(eval $(call addplatlib_s,kvm,libkvmpci,$(CONFIG_KVM_PCI)))
##
## Platform library definitions
##
LIBKVMPLAT_ASINCLUDES-y += -I$(LIBKVMPLAT_BASE)/include
LIBKVMPLAT_ASINCLUDES-y += -I$(UK_PLAT_COMMON_BASE)/include
+LIBKVMPCI_ASINCLUDES-$(CONFIG_ARCH_X86_64) +=
-I$(UK_PLAT_COMMON_BASE)/include/pci
LIBKVMPLAT_CINCLUDES-y += -I$(LIBKVMPLAT_BASE)/include
LIBKVMPLAT_CINCLUDES-y += -I$(UK_PLAT_COMMON_BASE)/include
+LIBKVMPCI_CINCLUDES-$(CONFIG_ARCH_X86_64) +=
-I$(UK_PLAT_COMMON_BASE)/include/pci
LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) +=
$(UK_PLAT_COMMON_BASE)/x86/trace.c|common
LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) +=
$(UK_PLAT_COMMON_BASE)/x86/traps.c|common
@@ -37,3 +40,5 @@ LIBKVMPLAT_SRCS-y += $(LIBKVMPLAT_BASE)/irq.c
LIBKVMPLAT_SRCS-y += $(LIBKVMPLAT_BASE)/time.c
LIBKVMPLAT_SRCS-y += $(LIBKVMPLAT_BASE)/tscclock.c
LIBKVMPLAT_SRCS-y += $(UK_PLAT_COMMON_BASE)/lcpu.c|common
+
+LIBKVMPCI_SRCS-y += $(UK_PLAT_COMMON_BASE)/pci_bus.c|common
--
2.7.4
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |