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/remote_io): add Remote I/O infrastructure #123

Closed
wants to merge 15 commits into from
Closed
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
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"files.associations": {
"emul.h": "c",
"interrupts.h": "c",
"spinlock.h": "c"
}
}
2 changes: 1 addition & 1 deletion src/arch/armv8/armv8-a/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void cpu_arch_profile_init(cpuid_t cpuid, paddr_t load_addr)

void cpu_arch_profile_idle()
{
int64_t err = psci_power_down(PSCI_WAKEUP_IDLE);
int64_t err = PSCI_E_NOT_SUPPORTED;
if (err) {
switch (err) {
case PSCI_E_NOT_SUPPORTED:
Expand Down
8 changes: 6 additions & 2 deletions src/core/hypercall.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@
#include <cpu.h>
#include <vm.h>
#include <ipc.h>
#include <remote_io.h>

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 hc_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));

switch (id) {
case HC_IPC:
ret = ipc_hypercall(ipc_id, arg1, arg2);
ret = ipc_hypercall(hc_id, arg1, arg2);
break;
case HC_REMOTE_IO:
ret = remote_io_hypercall(hc_id, arg1, arg2);
break;
default:
WARNING("Unknown hypercall id %d", id);
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_REMOTE_IO = 2 };

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

Expand Down
2 changes: 0 additions & 2 deletions src/core/inc/ipc.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,5 @@ struct ipc {
struct vm_config;

unsigned long ipc_hypercall(unsigned long arg0, unsigned long arg1, unsigned long arg2);
void ipc_init();
struct shmem* ipc_get_shmem(size_t shmem_id);

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

#ifndef __REMOTE_IO_H__
#define __REMOTE_IO_H__

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

/*!
* @enum remote_io_shmem
* @brief Contains all the information of a Remote I/O shared memory region
*/
struct remote_io_shmem {
paddr_t base;
size_t size;
size_t shmem_id;
};

/*!
* @struct remote_io_dev
* @brief Contains all the information of a Remote I/O device
*/
struct remote_io_dev {
vaddr_t va; // Virtual address for device MMIO register access
size_t size; // MMIO region size
irqid_t interrupt; // Interrupt
uint64_t id; // Unique Remote I/O ID linking each frontend driver to the backend
// device
bool is_backend; // True if the device is a backend device
struct remote_io_shmem shmem; // Shared memory region
};

/*!
* @fn remote_io_init
* @brief Responsible for Remote I/O device initialization
* @return void
*/
void remote_io_init();

/*!
* @fn remote_io_assign_cpus
* @brief Assigns frontend and backend CPUs to VMs containing Remote I/O instances
* @return void
*/
void remote_io_assign_cpus(struct vm* vm);

/*!
* @fn remote_io_hypercall
* @brief Handle the Remote I/O hypercall
* @note The Remote I/O hypercall is used by the backend to request or send information
* @param arg0 First argument of the hypercall
* @param arg1 Second argument of the hypercall
* @param arg2 Third argument of the hypercall
* @return unsigned long
*/
unsigned long remote_io_hypercall(unsigned long arg0, unsigned long arg1, unsigned long arg2);

/*!
* @fn remote_io_mmio_emul_handler
* @brief Manages all MMIO register accesses for a Remote I/O driver
* @param emul_access Structure holding details for MMIO register access
* @return bool
*/
bool remote_io_mmio_emul_handler(struct emul_access* emul_access);

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

#ifndef SHMEM_H
#define SHMEM_H

#include <mem.h>

void shmem_init();
struct shmem* shmem_get(size_t shmem_id);

#endif /* SHMEM_H */
11 changes: 11 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 <remote_io.h>

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

/* Remote I/O devices */
size_t remote_io_dev_num;
bool remote_io_pooling;
struct remote_io_dev* remote_io_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 Expand Up @@ -84,6 +90,11 @@ struct vm {

size_t ipc_num;
struct ipc* ipcs;

/* Remote I/O devices */
size_t remote_io_dev_num;
bool remote_io_pooling;
struct remote_io_dev* remote_io_devs;
};

struct vcpu {
Expand Down
43 changes: 2 additions & 41 deletions src/core/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <vmm.h>
#include <hypercall.h>
#include <config.h>
#include <shmem.h>

enum { IPC_NOTIFY };

Expand All @@ -20,18 +21,6 @@ union ipc_msg_data {
uint64_t raw;
};

static size_t shmem_table_size;
static struct shmem* shmem_table;

struct shmem* ipc_get_shmem(size_t shmem_id)
{
if (shmem_id < shmem_table_size) {
return &shmem_table[shmem_id];
} else {
return NULL;
}
}

static struct ipc* ipc_find_by_shmemid(struct vm* vm, size_t shmem_id)
{
struct ipc* ipc_obj = NULL;
Expand Down Expand Up @@ -73,7 +62,7 @@ unsigned long ipc_hypercall(unsigned long ipc_id, unsigned long ipc_event, unsig
struct shmem* shmem = NULL;
bool valid_ipc_obj = ipc_id < cpu()->vcpu->vm->ipc_num;
if (valid_ipc_obj) {
shmem = ipc_get_shmem(cpu()->vcpu->vm->ipcs[ipc_id].shmem_id);
shmem = shmem_get(cpu()->vcpu->vm->ipcs[ipc_id].shmem_id);
}
bool valid_shmem = shmem != NULL;

Expand All @@ -98,31 +87,3 @@ unsigned long ipc_hypercall(unsigned long ipc_id, unsigned long ipc_event, unsig

return ret;
}

static void ipc_alloc_shmem()
{
for (size_t i = 0; i < shmem_table_size; i++) {
struct shmem* shmem = &shmem_table[i];
if (!shmem->place_phys) {
size_t n_pg = NUM_PAGES(shmem->size);
struct ppages ppages = mem_alloc_ppages(shmem->colors, n_pg, false);
if (ppages.num_pages < n_pg) {
ERROR("failed to allocate shared memory");
}
shmem->phys = ppages.base;
}
}
}

void ipc_init()
{
if (cpu_is_master()) {
shmem_table_size = config.shmemlist_size;
shmem_table = config.shmemlist;
ipc_alloc_shmem();

for (size_t i = 0; i < config.shmemlist_size; i++) {
config.shmemlist[i].cpu_masters = 0;
}
}
}
2 changes: 2 additions & 0 deletions src/core/objects.mk
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ core-objs-y+=console.o
core-objs-y+=ipc.o
core-objs-y+=objpool.o
core-objs-y+=hypercall.o
core-objs-y+=shmem.o
core-objs-y+=remote_io.o
Loading