[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 |