Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add PCIe support #469

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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