Skip to content

Commit

Permalink
add PCIe support
Browse files Browse the repository at this point in the history
  • Loading branch information
bonkf committed Jun 7, 2020
1 parent 26bc7f2 commit cf49ed3
Show file tree
Hide file tree
Showing 43 changed files with 989 additions and 22 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ tenders/spt/solo5-spt
elftool/solo5-elftool
opam/release
solo5-*.tar.gz
.vscode
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Adrian-Ken Rueegsegger
Adam Steen
Dan Williams (IBM)
Emery Hemingway (Genode Labs)
Fabian Bonk
Gabriel Jaldon
Hannes Mehnert
Ian Campbell (Docker, Inc.)
Expand Down
14 changes: 10 additions & 4 deletions bindings/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,22 @@ common_hvt_SRCS := hvt/platform.c hvt/platform_intr.c hvt/time.c
#
hvt_SRCS := hvt/start.c $(common_SRCS) $(common_hvt_SRCS) \
hvt/platform_lifecycle.c hvt/yield.c hvt/tscclock.c hvt/console.c \
hvt/net.c hvt/block.c
hvt/net.c hvt/block.c hvt/pci.c

spt_SRCS := spt/start.c \
abort.c crt.c printf.c lib.c mem.c exit.c log.c cmdline.c tls.c mft.c \
spt/bindings.c spt/block.c spt/net.c spt/platform.c \
spt/bindings.c spt/block.c spt/net.c spt/pci.c spt/platform.c \
spt/sys_linux_$(CONFIG_ARCH).c

virtio_SRCS := virtio/boot.S virtio/start.c $(common_SRCS) \
virtio/platform.c virtio/platform_intr.c \
virtio/pci.c virtio/serial.c virtio/time.c virtio/virtio_ring.c \
virtio/virtio_net.c virtio/virtio_blk.c virtio/tscclock.c \
virtio/clock_subr.c virtio/pvclock.c
virtio/clock_subr.c virtio/pvclock.c virtio/pci-stubs.c

muen_SRCS := muen/start.c $(common_SRCS) $(common_hvt_SRCS) \
muen/channel.c muen/reader.c muen/writer.c muen/muen-block.c \
muen/muen-clock.c muen/muen-console.c muen/muen-net.c \
muen/muen-clock.c muen/muen-console.c muen/muen-net.c muen/muen-pci.c \
muen/muen-platform_lifecycle.c muen/muen-yield.c muen/muen-sinfo.c

genode_SRCS := genode/stubs.c
Expand Down Expand Up @@ -108,6 +108,8 @@ endif
ifdef CONFIG_SPT
spt_OBJS := $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(spt_SRCS)))

spt/pci.o: CFLAGS += -Wno-unused-parameter

spt/solo5_spt.o: $(spt_OBJS)
$(LINK.bindings)

Expand All @@ -119,6 +121,8 @@ endif
ifdef CONFIG_VIRTIO
virtio_OBJS := $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(virtio_SRCS)))

virtio/pci-stubs.o: CFLAGS += -Wno-unused-parameter

virtio/solo5_virtio.o: $(virtio_OBJS)
$(LINK.bindings)

Expand All @@ -130,6 +134,8 @@ endif
ifdef CONFIG_MUEN
muen_OBJS := $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(muen_SRCS)))

muen/muen-pci.o: CFLAGS += -Wno-unused-parameter

muen/solo5_muen.o: $(muen_OBJS)
$(LINK.bindings)

Expand Down
3 changes: 3 additions & 0 deletions bindings/genode/stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,8 @@ solo5_result_t solo5_block_read(solo5_handle_t handle, solo5_off_t offset, uint8

solo5_result_t solo5_set_tls_base(uintptr_t base) { return SOLO5_R_EUNSPEC; }

solo5_result_t solo5_pci_acquire(const char *name, struct solo5_pci_info *info) { return SOLO5_R_EUNSPEC; }
solo5_result_t solo5_dma_acquire(uint8_t **buffer, size_t *size) { return SOLO5_R_EUNSPEC; }

uintptr_t SSP_GUARD;
void SSP_FAIL (void) { }
1 change: 1 addition & 0 deletions bindings/hvt/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ void time_init(const struct hvt_boot_info *bi);
void console_init(void);
void net_init(const struct hvt_boot_info *bi);
void block_init(const struct hvt_boot_info *bi);
void pci_init(const struct hvt_boot_info *bi);

/* tscclock.c: TSC-based clock */
uint64_t tscclock_monotonic(void);
Expand Down
61 changes: 61 additions & 0 deletions bindings/hvt/pci.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include "bindings.h"

static const struct mft *mft;

#define setup_bar(index, n) \
do { \
if (e->u.pci_basic.map_bar ## n) { \
info->bar ## n = (uint8_t *) HVT_REGION(index, n); \
info->bar ## n ## _size = e->u.pci_basic.bar ## n ## _size; \
} else { \
info->bar ## n = NULL; \
info->bar ## n ## _size = 0; \
} \
} while (0)

solo5_result_t solo5_pci_acquire(const char *name, struct solo5_pci_info *info)
{
unsigned mft_index;
const struct mft_entry *e =
mft_get_by_name(mft, name, MFT_DEV_PCI_BASIC, &mft_index);
if (e == NULL)
return SOLO5_R_EINVAL;
assert(e->attached);

info->bus_master_enable = e->u.pci_basic.bus_master_enable;
info->class_code = e->u.pci_basic.class_code;
info->subclass_code = e->u.pci_basic.subclass_code;
info->progif = e->u.pci_basic.progif;
info->vendor_id = e->u.pci_basic.vendor;
info->device_id = e->u.pci_basic.device_id;

uint8_t index = e->u.pci_basic.device_index;
setup_bar(index, 0);
setup_bar(index, 1);
setup_bar(index, 2);
setup_bar(index, 3);
setup_bar(index, 4);
setup_bar(index, 5);

assert(info->bar0_size != 0);

return SOLO5_R_OK;
}

solo5_result_t solo5_dma_acquire(uint8_t **buffer, size_t *size)
{
if (mft->dma_size > 0) {
*buffer = (uint8_t *) HVT_DMA_BASE;
*size = mft->dma_size;
return SOLO5_R_OK;
} else {
*buffer = NULL;
*size = 0;
return SOLO5_R_EINVAL;
}
}

void pci_init(const struct hvt_boot_info *bi)
{
mft = bi->mft;
}
1 change: 1 addition & 0 deletions bindings/hvt/start.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ void _start(const void *arg)
time_init(arg);
block_init(arg);
net_init(arg);
pci_init(arg);

mem_lock_heap(&si.heap_start, &si.heap_size);
solo5_exit(solo5_app_main(&si));
Expand Down
11 changes: 11 additions & 0 deletions bindings/muen/muen-pci.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "bindings.h"

solo5_result_t solo5_pci_acquire(const char *name, struct solo5_pci_info *info)
{
return SOLO5_R_EUNSPEC;
}

solo5_result_t solo5_dma_acquire(uint8_t **buffer, size_t *size)
{
return SOLO5_R_EUNSPEC;
}
11 changes: 11 additions & 0 deletions bindings/spt/pci.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "bindings.h"

solo5_result_t solo5_pci_acquire(const char *name, struct solo5_pci_info *info)
{
return SOLO5_R_EUNSPEC;
}

solo5_result_t solo5_dma_acquire(uint8_t **buffer, size_t *size)
{
return SOLO5_R_EUNSPEC;
}
11 changes: 11 additions & 0 deletions bindings/virtio/pci-stubs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "bindings.h"

solo5_result_t solo5_pci_acquire(const char *name, struct solo5_pci_info *info)
{
return SOLO5_R_EUNSPEC;
}

solo5_result_t solo5_dma_acquire(uint8_t **buffer, size_t *size)
{
return SOLO5_R_EUNSPEC;
}
40 changes: 36 additions & 4 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,32 @@ Solo5 introduces the concept of an _application manifest_, which is defined by
the developer at unikernel build time, using the following JSON format and
customarily named `manifest.json`:

```jsonc
```json
{
"type": "solo5.manifest",
"version": 1,
"dma_size": 16777216,
"devices": [
{ "name": "NAME", "type": "TYPE" }
{
"name": "NAME",
"type": "TYPE"
},
{
"name": "pci0",
"type": "PCI_BASIC",
"class": 2,
"subclass": 0,
"progif": 0,
"vendor": 32902,
"device_id": 4347,
"bus_master_enable": true,
"map_bar0": true,
"map_bar1": false,
"map_bar2": false,
"map_bar3": false,
"map_bar4": false,
"map_bar5": false
}
// ... up to 63 user-specified devices ...
]
}
Expand All @@ -115,8 +135,20 @@ of the device, eg. `frontend` for a network or `storage` for a block device.
_NAME_ must be composed of alphanumeric characters only, and within 1..67
characters in length.

_TYPE_ is the type of device being declared, currently `BLOCK_BASIC` or
`NET_BASIC`.
_TYPE_ is the type of device being declared, currently `BLOCK_BASIC`,
`NET_BASIC`, `PCI_BASIC` or `DMA_BASIC`.

`dma_size` is the amount of required DMA-ready memory to be mapped into the
unikernel in bytes.

`PCI_BASIC` contains additional fields besides `name` and `type`:
* `class` - PCI device's expected class code
* `subclass` - PCI device's expected subclass code
* `progif` - PCI device's expected programming interface
* `vendor` - PCI device's expected vendor
* `device_id` - PCI device's expected device ID
* `bus_master_enable` - `true` if the device should be a bus master
* `map_barN` - `true` if the `N`th `BAR` should be mapped into the unikernel

Note that there is a maximum limit of 63 user-specified devices in the manifest.

Expand Down
Loading

0 comments on commit cf49ed3

Please sign in to comment.