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 initial support for multiple vCPUs #116

Open
wants to merge 9 commits into
base: main
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
8 changes: 4 additions & 4 deletions ci/examples.sh
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ build_simple_zig "maaxboard" "release"

build_rust "debug"
simulate_rust "debug"
# build_rust "release"
# simulate_rust "release"
build_rust "release"
simulate_rust "release"

# Here there are two kinds of configuration that we need to test. There is the
# configuration of Microkit itself for which we test debug and release. This
Expand All @@ -153,8 +153,8 @@ simulate_zig "release" "ReleaseSmall"

build_virtio "qemu_virt_aarch64" "debug"
build_virtio "qemu_virt_aarch64" "release"
# build_virtio "odroidc4" "debug"
# build_virtio "odroidc4" "release"
build_virtio "odroidc4" "debug"
build_virtio "odroidc4" "release"

echo ""
echo "CI|INFO: Passed all VMM tests"
19 changes: 10 additions & 9 deletions examples/rust/src/vmm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use sel4_microkit::{protection_domain, MessageInfo, Channel, Child, Handler, deb
const GUEST_RAM_VADDR: usize = 0x40000000;
const GUEST_DTB_VADDR: usize = 0x4f000000;
const GUEST_INIT_RAM_DISK_VADDR: usize = 0x4d700000;
const GUEST_VCPU_ID: usize = 0;
const GUEST_BOOT_VCPU_ID: usize = 0;

/// On the QEMU virt AArch64 platform the UART we are using has an IRQ number of 33.
const UART_IRQ: usize = 33;
Expand All @@ -37,10 +37,10 @@ extern "C" {
kernel: usize, kernel_size: usize,
dtb_src: usize, dtb_dest: usize, dtb_size: usize,
initrd_src: usize, initrd_dest: usize, initrd_size: usize) -> usize;
fn virq_controller_init(boot_vpcu_id: usize) -> bool;
fn virq_controller_init() -> bool;
fn virq_register(vcpu_id: usize, irq: i32, ack_fn: extern fn(usize, i32, *const c_void), ack_data: *const c_void) -> bool;
fn virq_inject(vcpu_id: usize, irq: i32) -> bool;
fn guest_start(boot_vpcu_id: usize, kernel_pc: usize, dtb: usize, initrd: usize) -> bool;
fn virq_inject(irq: i32) -> bool;
fn guest_start(kernel_pc: usize, dtb: usize, initrd: usize) -> bool;
fn fault_handle(vcpu_id: usize, msginfo: MessageInfo) -> bool;
}

Expand Down Expand Up @@ -76,16 +76,17 @@ fn init() -> VmmHandler {
dtb_addr, GUEST_DTB_VADDR, dtb.len(),
initrd_addr, GUEST_INIT_RAM_DISK_VADDR, initrd.len()
);
// @ivanv, deal with unused vars
_ = virq_controller_init(GUEST_VCPU_ID);
_ = virq_register(GUEST_VCPU_ID, UART_IRQ as i32, uart_irq_ack, core::ptr::null());
let success = virq_controller_init();
assert!(success);
let success = virq_register(GUEST_BOOT_VCPU_ID, UART_IRQ as i32, uart_irq_ack, core::ptr::null());
assert!(success);
match UART_CH.irq_ack() {
Ok(()) => {}
Err(_e) => {
debug_println!("VMM|ERROR: could not ack UART IRQ channel: {_e}");
}
}
guest_start(GUEST_VCPU_ID, guest_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR);
guest_start(guest_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR);
}

VmmHandler {}
Expand All @@ -100,7 +101,7 @@ impl Handler for VmmHandler {
match channel {
UART_CH => {
unsafe {
let success = virq_inject(GUEST_VCPU_ID, UART_IRQ as i32);
let success = virq_inject(UART_IRQ as i32);
if !success {
debug_println!("VMM|ERROR: could not inject UART IRQ");
}
Expand Down
52 changes: 28 additions & 24 deletions examples/simple/vmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,59 +76,62 @@ extern char _guest_initrd_image_end[];
/* Microkit will set this variable to the start of the guest RAM memory region. */
uintptr_t guest_ram_vaddr;

static void serial_ack(size_t vcpu_id, int irq, void *cookie) {
static void serial_ack(size_t vcpu_id, int irq, void *cookie)
{
/*
* For now we by default simply ack the serial IRQ, we have not
* come across a case yet where more than this needs to be done.
*/
microkit_irq_ack(SERIAL_IRQ_CH);
}

void init(void) {
void init(void)
{
/* Initialise the VMM, the VCPU(s), and start the guest */
LOG_VMM("starting \"%s\"\n", microkit_name);
/* Place all the binaries in the right locations before starting the guest */
size_t kernel_size = _guest_kernel_image_end - _guest_kernel_image;
size_t dtb_size = _guest_dtb_image_end - _guest_dtb_image;
size_t initrd_size = _guest_initrd_image_end - _guest_initrd_image;
uintptr_t kernel_pc = linux_setup_images(guest_ram_vaddr,
(uintptr_t) _guest_kernel_image,
kernel_size,
(uintptr_t) _guest_dtb_image,
GUEST_DTB_VADDR,
dtb_size,
(uintptr_t) _guest_initrd_image,
GUEST_INIT_RAM_DISK_VADDR,
initrd_size
);
(uintptr_t) _guest_kernel_image,
kernel_size,
(uintptr_t) _guest_dtb_image,
GUEST_DTB_VADDR,
dtb_size,
(uintptr_t) _guest_initrd_image,
GUEST_INIT_RAM_DISK_VADDR,
initrd_size
);
if (!kernel_pc) {
LOG_VMM_ERR("Failed to initialise guest images\n");
return;
}
/* Initialise the virtual GIC driver */
bool success = virq_controller_init(GUEST_VCPU_ID);
bool success = virq_controller_init();
if (!success) {
LOG_VMM_ERR("Failed to initialise emulated interrupt controller\n");
return;
}
success = virq_register(GUEST_VCPU_ID, SERIAL_IRQ, &serial_ack, NULL);
success = virq_register(GUEST_BOOT_VCPU_ID, SERIAL_IRQ, &serial_ack, NULL);
/* Just in case there is already an interrupt available to handle, we ack it here. */
microkit_irq_ack(SERIAL_IRQ_CH);
/* Finally start the guest */
guest_start(GUEST_VCPU_ID, kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR);
guest_start(kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR);
}

void notified(microkit_channel ch) {
void notified(microkit_channel ch)
{
switch (ch) {
case SERIAL_IRQ_CH: {
bool success = virq_inject(GUEST_VCPU_ID, SERIAL_IRQ);
if (!success) {
LOG_VMM_ERR("IRQ %d dropped on vCPU %d\n", SERIAL_IRQ, GUEST_VCPU_ID);
}
break;
case SERIAL_IRQ_CH: {
bool success = virq_inject(SERIAL_IRQ);
if (!success) {
LOG_VMM_ERR("IRQ %d dropped\n", SERIAL_IRQ);
}
default:
printf("Unexpected channel, ch: 0x%lx\n", ch);
break;
}
default:
printf("Unexpected channel, ch: 0x%lx\n", ch);
}
}

Expand All @@ -137,7 +140,8 @@ void notified(microkit_channel ch) {
* Whenever our guest causes an exception, it gets delivered to this entry point for
* the VMM to handle.
*/
seL4_Bool fault(microkit_child child, microkit_msginfo msginfo, microkit_msginfo *reply_msginfo) {
seL4_Bool fault(microkit_child child, microkit_msginfo msginfo, microkit_msginfo *reply_msginfo)
{
bool success = fault_handle(child, msginfo);
if (success) {
/* Now that we have handled the fault successfully, we reply to it so
Expand Down
82 changes: 43 additions & 39 deletions examples/virtio-snd/client_vmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,46 +72,48 @@ static struct virtio_snd_device virtio_sound;

uintptr_t kernel_pc = 0;

void init(void) {
void init(void)
{
/* Initialise the VMM, the VCPU(s), and start the guest */
LOG_VMM("starting \"%s\"\n", microkit_name);
/* Place all the binaries in the right locations before starting the guest */
size_t kernel_size = _guest_kernel_image_end - _guest_kernel_image;
size_t dtb_size = _guest_dtb_image_end - _guest_dtb_image;
size_t initrd_size = _guest_initrd_image_end - _guest_initrd_image;
kernel_pc = linux_setup_images(guest_ram_vaddr,
(uintptr_t) _guest_kernel_image,
kernel_size,
(uintptr_t) _guest_dtb_image,
GUEST_DTB_VADDR,
dtb_size,
(uintptr_t) _guest_initrd_image,
GUEST_INIT_RAM_DISK_VADDR,
initrd_size
);
(uintptr_t) _guest_kernel_image,
kernel_size,
(uintptr_t) _guest_dtb_image,
GUEST_DTB_VADDR,
dtb_size,
(uintptr_t) _guest_initrd_image,
GUEST_INIT_RAM_DISK_VADDR,
initrd_size
);
if (!kernel_pc) {
LOG_VMM_ERR("Failed to initialise guest images\n");
return;
}

/* Initialise the virtual GIC driver */
bool success = virq_controller_init(GUEST_VCPU_ID);
bool success = virq_controller_init();
if (!success) {
LOG_VMM_ERR("Failed to initialise emulated interrupt controller\n");
return;
}

/* Initialise our sDDF ring buffers for the serial device */
serial_queue_handle_t serial_rxq, serial_txq;
serial_cli_queue_init_sys(microkit_name, &serial_rxq, serial_rx_queue, serial_rx_data, &serial_txq, serial_tx_queue, serial_tx_data);
serial_cli_queue_init_sys(microkit_name, &serial_rxq, serial_rx_queue, serial_rx_data, &serial_txq, serial_tx_queue,
serial_tx_data);

/* Initialise virtIO console device */
success = virtio_mmio_console_init(&virtio_console,
VIRTIO_CONSOLE_BASE,
VIRTIO_CONSOLE_SIZE,
VIRTIO_CONSOLE_IRQ,
&serial_rxq, &serial_txq,
SERIAL_VIRT_TX_CH);
VIRTIO_CONSOLE_BASE,
VIRTIO_CONSOLE_SIZE,
VIRTIO_CONSOLE_IRQ,
&serial_rxq, &serial_txq,
SERIAL_VIRT_TX_CH);
assert(success);

assert(sound_cmd_req);
Expand All @@ -138,37 +140,39 @@ void init(void) {
while (!ATOMIC_LOAD(&shared_state->ready, __ATOMIC_ACQUIRE));

success = virtio_mmio_snd_init(&virtio_sound,
VIRTIO_SOUND_BASE,
VIRTIO_SOUND_SIZE,
VIRTIO_SOUND_IRQ,
shared_state,
&sound_queues,
sound_data,
SOUND_DRIVER_CH);
VIRTIO_SOUND_BASE,
VIRTIO_SOUND_SIZE,
VIRTIO_SOUND_IRQ,
shared_state,
&sound_queues,
sound_data,
SOUND_DRIVER_CH);
assert(success);

success = guest_start(GUEST_VCPU_ID, kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR);
success = guest_start(GUEST_BOOT_VCPU_ID, kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR);
assert(success);
}

void notified(microkit_channel ch) {
void notified(microkit_channel ch)
{
switch (ch) {
case SERIAL_VIRT_RX_CH: {
/* We have received an event from the serial virtualiser, so we
* call the virtIO console handling */
virtio_console_handle_rx(&virtio_console);
break;
}
case SOUND_DRIVER_CH: {
virtio_snd_notified(&virtio_sound);
break;
}
default:
printf("Unexpected channel, ch: 0x%lx\n", ch);
case SERIAL_VIRT_RX_CH: {
/* We have received an event from the serial virtualiser, so we
* call the virtIO console handling */
virtio_console_handle_rx(&virtio_console);
break;
}
case SOUND_DRIVER_CH: {
virtio_snd_notified(&virtio_sound);
break;
}
default:
printf("Unexpected channel, ch: 0x%lx\n", ch);
}
}

seL4_Bool fault(microkit_child child, microkit_msginfo msginfo, microkit_msginfo *reply_msginfo) {
seL4_Bool fault(microkit_child child, microkit_msginfo msginfo, microkit_msginfo *reply_msginfo)
{
bool success = fault_handle(child, msginfo);
if (success) {
/* Now that we have handled the fault successfully, we reply to it so
Expand Down
Loading
Loading