|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH v3 2/2] plat/kvm: Add initial PCI bus driver for x86_64
Reviewed-by: Yuri Volchkov <yuri.volchkov@xxxxxxxxx>
Simon Kuenzer <simon.kuenzer@xxxxxxxxx> writes:
> 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
>
--
Yuri Volchkov
Software Specialist
NEC Europe Ltd
Kurfürsten-Anlage 36
D-69115 Heidelberg
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |