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

feat(core/remio): add Remote I/O infrastructure #176

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
17 changes: 17 additions & 0 deletions scripts/config_defs_gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@
#include <stdio.h>
#include <config.h>

static size_t remio_dev_num(void)
{
size_t dev_num = 0;
for (size_t vm_id = 0; vm_id < config.vmlist_size; vm_id++) {
struct vm_config* vm_config = &config.vmlist[vm_id];
for (size_t i = 0; i < vm_config->platform.remio_dev_num; i++) {
struct remio_dev* dev = &vm_config->platform.remio_devs[i];
if (dev->type == REMIO_DEV_BACKEND) {
dev_num++;
}
}
}
return dev_num;
}

int main() {
size_t vcpu_num = 0;
for (size_t i = 0; i < config.vmlist_size; i++) {
Expand All @@ -21,5 +36,7 @@ int main() {
printf("#define CONFIG_HYP_BASE_ADDR PLAT_BASE_ADDR\n");
}

printf("#define CONFIG_REMIO_DEV_NUM %ld\n", remio_dev_num());

return 0;
}
3 changes: 3 additions & 0 deletions src/arch/armv8/aborts.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ void aborts_sync_handler(void)
abort_handler_t handler = abort_handlers[ec];
if (handler) {
handler(iss, ipa_fault_addr, il, ec);
if (vcpu_arch_is_on(cpu()->vcpu) && !cpu()->vcpu->active) {
cpu_standby();
}
} else {
ERROR("no handler for abort ec = 0x%x", ec); // unknown guest exception
}
Expand Down
3 changes: 2 additions & 1 deletion src/arch/armv8/inc/arch/hypercall.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#ifndef ARCH_HYPERCALL_H
#define ARCH_HYPERCALL_H

#define HYPCALL_ARG_REG(ARG) ((ARG) + 1)
#define HYPCALL_IN_ARG_REG(ARG) ((ARG) + 1)
#define HYPCALL_OUT_ARG_REG(ARG) (HYPCALL_IN_ARG_REG(ARG))

#endif /* ARCH_HYPERCALL_H */
3 changes: 2 additions & 1 deletion src/arch/riscv/inc/arch/hypercall.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#ifndef ARCH_HYPERCALL_H
#define ARCH_HYPERCALL_H

#define HYPCALL_ARG_REG(ARG) ((ARG) + REG_A0)
#define HYPCALL_IN_ARG_REG(ARG) ((ARG) + REG_A0)
#define HYPCALL_OUT_ARG_REG(ARG) (HYPCALL_IN_ARG_REG((ARG) + 2))

#endif /* ARCH_HYPERCALL_H */
5 changes: 4 additions & 1 deletion src/arch/riscv/sync_exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,5 +152,8 @@ void sync_exception_handler(void)
ERROR("unkown synchronous exception (%d)", _scause);
}

cpu()->vcpu->regs.sepc += pc_step;
vcpu_writepc(cpu()->vcpu, vcpu_readpc(cpu()->vcpu) + pc_step);
josecm marked this conversation as resolved.
Show resolved Hide resolved
if (vcpu_arch_is_on(cpu()->vcpu) && !cpu()->vcpu->active) {
cpu_standby();
}
}
11 changes: 7 additions & 4 deletions src/core/hypercall.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@ long int hypercall(unsigned long id)
{
long int ret = -HC_E_INVAL_ID;

unsigned long ipc_id = vcpu_readreg(cpu()->vcpu, HYPCALL_ARG_REG(0));
unsigned long arg1 = vcpu_readreg(cpu()->vcpu, HYPCALL_ARG_REG(1));
unsigned long arg2 = vcpu_readreg(cpu()->vcpu, HYPCALL_ARG_REG(2));
unsigned long arg0 = vcpu_readreg(cpu()->vcpu, HYPCALL_IN_ARG_REG(0));
unsigned long arg1 = vcpu_readreg(cpu()->vcpu, HYPCALL_IN_ARG_REG(1));
unsigned long arg2 = vcpu_readreg(cpu()->vcpu, HYPCALL_IN_ARG_REG(2));

switch (id) {
case HC_IPC:
ret = ipc_hypercall(ipc_id, arg1, arg2);
ret = ipc_hypercall(arg0, arg1, arg2);
break;
case HC_REMIO:
ret = remio_hypercall(arg0, arg1, arg2);
break;
default:
WARNING("Unknown hypercall id %d", id);
Expand Down
1 change: 1 addition & 0 deletions src/core/inc/config_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#define CONFIG_VCPU_NUM 1
#define CONFIG_VM_NUM 1
#define CONFIG_HYP_BASE_ADDR 0
#define CONFIG_REMIO_DEV_NUM 0
DavidMCerdeira marked this conversation as resolved.
Show resolved Hide resolved

#else /* GENERATING_DEFS */

Expand Down
2 changes: 1 addition & 1 deletion src/core/inc/hypercall.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include <bao.h>
#include <arch/hypercall.h>

enum { HC_INVAL = 0, HC_IPC = 1 };
enum { HC_INVAL = 0, HC_IPC = 1, HC_REMIO = 2 };

enum { HC_E_SUCCESS = 0, HC_E_FAILURE = 1, HC_E_INVAL_ID = 2, HC_E_INVAL_ARGS = 3 };

Expand Down
9 changes: 9 additions & 0 deletions src/core/inc/objpool.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ struct objpool {

void objpool_init(struct objpool* objpool);
void* objpool_alloc(struct objpool* objpool);
void* objpool_alloc_with_id(struct objpool* objpool, objpool_id_t* id);
void objpool_free(struct objpool* objpool, void* obj);

inline void* objpool_get_by_id(struct objpool* objpool, objpool_id_t id)
{
if (id < objpool->num) {
return (void*)((uintptr_t)objpool->pool + (objpool->objsize * id));
}
return NULL;
}

#endif /* OBJPOOL_H */
86 changes: 86 additions & 0 deletions src/core/inc/remio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* SPDX-License-Identifier: Apache-2.0
* Copyright (c) Bao Project and Contributors. All rights reserved.
*/

/**
* @file remio.h
* @brief This header file contains the Remote I/O device interface
*/

#ifndef REMIO_H
#define REMIO_H

#include <bao.h>
#include <emul.h>
#include <list.h>
#include <vm.h>

/**
* @struct remio_shmem
* @brief This structure represents a shared memory region used by a Remote I/O device
*/
struct remio_shmem {
paddr_t base; /**< Shared memory base address */
size_t size; /**< Shared memory size */
size_t shmem_id; /**< Shared memory ID */
};

/**
* @enum REMIO_DEV_TYPE
* @brief This enum represents the Remote I/O device type
*/
enum REMIO_DEV_TYPE {
REMIO_DEV_FRONTEND = 0, /**< Remote I/O frontend device */
REMIO_DEV_BACKEND /**< Remote I/O backend device */
};

/**
* @struct remio_dev
* @brief This structure represents a Remote I/O device
* @note The device can be either a frontend (driver) or a backend (device)
*/
struct remio_dev {
vaddr_t va; /**< Frontend MMIO base virtual address */
size_t size; /**< Frontend MMIO size */
irqid_t interrupt; /**< Frontend/backend interrupt number */
remio_bind_key_t bind_key; /**< Remote I/O bind key */
enum REMIO_DEV_TYPE type; /**< Type of the Remote I/O device */
struct remio_shmem shmem; /**< Shared memory region */
};

/**
* @brief Remote I/O device initialization routine
* @note Executed only once by the master CPU
*/
void remio_init(void);

/**
* @brief Remote I/O device VM CPU assignment routine
* @note Executed by each VM that holds a Remote I/O device, it is responsible for
* assigning the frontend or backend CPU ID for the respective Remote I/O device
* If the VM was alloacted with more than one CPU the assigned CPU will be the
* one with the lowest ID, since only one CPU is required to inject VM interrupts
* @param vm Pointer to the VM structure
*/
void remio_assign_vm_cpus(struct vm* vm);

/**
* @brief Remote I/O hypercall callback
* @note Used to exchange information between the Remote I/O system and the backend VM
* @param arg0 First argument of the hypercall
* @param arg1 Second argument of the hypercall
* @param arg2 Third argument of the hypercall
* @return Returns the number of pending I/O requests
*/
long int remio_hypercall(unsigned long arg0, unsigned long arg1, unsigned long arg2);

/**
* @brief Remote I/O MMIO emulation handler
* @note Executed by the frontend VM when a MMIO access is performed
* @param emul_access Holds the information about the MMIO access
* @return Returns true if handled successfully, false otherwise
*/
bool remio_mmio_emul_handler(struct emul_access* emul_access);

#endif /* __REMIO_H__ */
4 changes: 4 additions & 0 deletions src/core/inc/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ typedef unsigned irqid_t;

typedef unsigned deviceid_t;

typedef size_t objpool_id_t;

typedef size_t remio_bind_key_t;

typedef enum AS_SEC {
/*--- HYP AS SECTIONS -----*/
SEC_HYP_GLOBAL = 0,
Expand Down
4 changes: 4 additions & 0 deletions src/core/inc/vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <bitmap.h>
#include <io.h>
#include <ipc.h>
#include <remio.h>

struct vm_mem_region {
paddr_t base;
Expand Down Expand Up @@ -47,6 +48,9 @@ struct vm_platform {
size_t dev_num;
struct vm_dev_region* devs;

size_t remio_dev_num;
struct remio_dev* remio_devs;

// /**
// * In MPU-based platforms which might also support virtual memory
// * (i.e. aarch64 cortex-r) the hypervisor sets up the VM using an MPU by
Expand Down
1 change: 1 addition & 0 deletions src/core/objects.mk
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ core-objs-y+=ipc.o
core-objs-y+=objpool.o
core-objs-y+=hypercall.o
core-objs-y+=shmem.o
core-objs-y+=remio.o
10 changes: 9 additions & 1 deletion src/core/objpool.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ void objpool_init(struct objpool* objpool)
memset(objpool->bitmap, 0, BITMAP_SIZE(objpool->num));
}

void* objpool_alloc(struct objpool* objpool)
void* objpool_alloc_with_id(struct objpool* objpool, objpool_id_t* id)
{
void* obj = NULL;
spin_lock(&objpool->lock);
Expand All @@ -21,10 +21,18 @@ void* objpool_alloc(struct objpool* objpool)
bitmap_set(objpool->bitmap, (size_t)n);
obj = (void*)((uintptr_t)objpool->pool + (objpool->objsize * (size_t)n));
}
if (id != NULL) {
*id = (objpool_id_t)n;
}
spin_unlock(&objpool->lock);
return obj;
}

void* objpool_alloc(struct objpool* objpool)
{
return objpool_alloc_with_id(objpool, NULL);
}

void objpool_free(struct objpool* objpool, void* obj)
{
vaddr_t obj_addr = (vaddr_t)obj;
Expand Down
Loading