Correct procedure and memory addresses to setup a virtio-net ethernet device on a sel4 microkernel

257 Views Asked by At

In short:

I am trying to run the sel4 microkernel inside a x86_64 virtual machine and can't get the ethernet interface working. What is the correct procedure to get internet connectivity (via a vitio-net ethernet device) on a sel4 microkernel? And what are the correct (memory) addresses?

Long version:

I have tried the camkes (picoserver) examples with the e1000 netdevice but couldn't get them to work so I decided to learn some new things and start from scratch. Also I decided to use virtio-net(together with vhost) instead of an emulated e1000 device for better performance. My plan is to use ethif_virtio_pci_init to initialise a eth_driver struct and then pass the struct on to picoTCP. For now I can find the virtio PCI device in sel4 but I am unsure how to correctly access it and create the ethif_virtio_pci_config_t needed for ethif_virtio_pci_init.

Some information from libethdrivers virtio_pci.h:

typedef struct ethif_virtio_pci_config {
    uint16_t io_base;
    void *mmio_base;
} ethif_virtio_pci_config_t;

/**
 * This function initialises the hardware and conforms to the ethif_driver_init
 * type in raw.h
 * @param[out] eth_driver   Ethernet driver structure to fill out
 * @param[in] io_ops        A structure containing os specific data and
 *                          functions.
 * @param[in] config        Pointer to a ethif_virtio_pci_config struct
 */
int ethif_virtio_pci_init(struct eth_driver *eth_driver, ps_io_ops_t io_ops, void *config);

so for the ethif_virtio_pci_config_t I need an uint16_t io_base address and a pointer to the MMIO base.

This is the information I have obtained so far:

Found virtio_net_pci device
    BASE_ADDR[0] ----
        base_addr_space[0]: 0x1 [PCI_BASE_ADDRESS_SPACE_IO]
        base_addr_type[0]: 0x0 [ 32bit ]
        base_addr_prefetchable[0]: no
        base_addr[0]: 0xc000
        base_addr_size_mask[0]: 0xffffffe0
    BASE_ADDR[1] ----
        base_addr_space[1]: 0x0 [PCI_BASE_ADDRESS_SPACE_MEMORY]
        base_addr_type[1]: 0x0 [ 32bit ]
        base_addr_prefetchable[1]: no
        base_addr[1]: 0xfeb91000
        base_addr_size_mask[1]: 0xfffff000
    BASE_ADDR[2] ----
    BASE_ADDR[3] ----
    BASE_ADDR[4] ----
        base_addr_space[4]: 0x0 [PCI_BASE_ADDRESS_SPACE_MEMORY]
        base_addr_type[4]: 0x4 [ 64bit ]
        base_addr_prefetchable[4]: yes
        base_addr[4]: 0xfe000000
        base_addr_size_mask[4]: 0xffffc000
    BASE_ADDR[5] ----

As far as I understand I now need to map the pysical address to a virtual one. For that I created an IO-mapper but I am not sure what to map. The whole dma region starting at 0x8000000 or just the address of the virtio device? As far as I understand the new virtual address would be my MMIO base pointer but what is the uint16_t io_base than?

This is my code so far, the part I am unsure about is at the end:

#define ALLOCATOR_STATIC_POOL_SIZE ((1 << seL4_LargePageBits) * 10)
static simple_t simple;
static ps_io_mapper_t io_mapper;
static char allocator_mem_pool[ALLOCATOR_STATIC_POOL_SIZE];
static vka_t vka;
static vspace_t vspace;
static sel4utils_alloc_data_t data;
static ltimer_t timer;

int main() {

    PRINT_DBG("Hello World\n");
    seL4_BootInfo *info = platsupport_get_bootinfo();

    simple_default_init_bootinfo(&simple, info);

    /* print out bootinfo and other info about simple */
    // simple_print(&simple);

    allocman_t *allocman = bootstrap_use_current_simple(&simple, ALLOCATOR_STATIC_POOL_SIZE, allocator_mem_pool);
    if (allocman == NULL) {
        ZF_LOGF("Failed to create allocman");
    }
    allocman_make_vka(&vka, allocman);

    int error = sel4utils_bootstrap_vspace_with_bootinfo_leaky(&vspace,
                                                          &data, simple_get_pd(&simple),
                                                          &vka, info);
    if (error != 0) {
       PRINT_DBG("Failed to create virtual memory manager. Error: %d\n", error);
       return -1;
    }


    error = sel4platsupport_new_io_mapper(&vspace, &vka, &io_mapper);
    if (error != 0) {
        PRINT_DBG("Failed to create io mapper. Error: %d\n", error);
        return -1;
    }

    ps_io_ops_t io_ops;
    error = sel4platsupport_new_io_ops(&vspace, &vka, &simple, &io_ops);
    if (error != 0) {
        PRINT_DBG("Failed to create io ops. Error: %d\n", error);
        return -1;
    }

    ps_io_port_ops_t port_ops;
    int error = sel4platsupport_get_io_port_ops(&port_ops, &simple, &vka);
    if (error != 0) {
      PRINT_DBG("Failed to find io port ops. Error: %d\n", error);
      return -1;
    }

    printf("Start scannning\n");

    libpci_scan(port_ops);
    PRINT_DBG("Found %u devices\n", libpci_num_devices);
    for (uint32_t i = 0; i < libpci_num_devices; ++i) {
      PRINT_DBG("PCI device %u. Vendor id: %x. Device id: %x\n",
          i, libpci_device_list[i].vendor_id, libpci_device_list[i].device_id);
    }

    libpci_device_t* virtio_net_pci = libpci_find_device(0x1af4, 0x1000);
    if (!virtio_net_pci) {
      PRINT_DBG("Failed to find the virtio_net_pci device\n");
      // return -1;
    }else{
    // libpci_device_iocfg_debug_print(&virtio_net_pci->cfg,true);
        PRINT_DBG("Found virtio_net_pci device\n");
        libpci_device_iocfg_debug_print(&virtio_net_pci->cfg,false);
    }


    //Now what?

    unsigned long phys = 0x8000000; //what physical address to map?
    void *mmio_ptr = ps_io_map(&io_mapper, phys, 4096, 0, PS_MEM_NORMAL);
    memset(ptr, 0, 4096);
    if (mmio_ptr == NULL) {
        PRINT_DBG("Failed to map phys addr. Error: %p\n", ptr);
        return -1;
    }

    ethif_virtio_pci_config_t me_config;
    me_config.mmio_base = mmio_ptr; //is this correct?
    //me_config.io_base = ?

I read alot about the sel4 kernel but I am still new to most of the concepts of the sel4 microkernel (and Linux kernel) so I am very grateful for any tipps and recommendations. I am normally working with embedded, microcontrollers and more "bare metal" platforms and wanted to learn something new but for now alot is very confusing.

0

There are 0 best solutions below