From fb78e3cd1ccdba2b98887e7bbe3f097f7e73cef3 Mon Sep 17 00:00:00 2001 From: Ivan Velickovic Date: Mon, 19 Aug 2024 15:20:16 +1000 Subject: [PATCH 1/9] Add support for multiple vCPUs Signed-off-by: Ivan Velickovic --- include/libvmm/arch/aarch64/vgic/vdist.h | 19 ++++++---- include/libvmm/util/util.h | 6 +++- include/libvmm/vcpu.h | 15 ++++++++ src/arch/aarch64/fault.c | 7 ++-- src/arch/aarch64/psci.c | 45 ++++++++++++++++++++---- src/arch/aarch64/vcpu.c | 20 +++++++++++ src/arch/aarch64/vgic/vgic.c | 7 ++-- src/arch/aarch64/vgic/vgic_v2.c | 37 +++++++++---------- src/arch/aarch64/vgic/vgic_v3.c | 1 + src/arch/aarch64/virq.c | 30 ++++++++-------- src/guest.c | 2 ++ 11 files changed, 136 insertions(+), 53 deletions(-) diff --git a/include/libvmm/arch/aarch64/vgic/vdist.h b/include/libvmm/arch/aarch64/vgic/vdist.h index 768f39b16..e2d07d4d3 100644 --- a/include/libvmm/arch/aarch64/vgic/vdist.h +++ b/include/libvmm/arch/aarch64/vgic/vdist.h @@ -5,6 +5,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include @@ -494,8 +495,8 @@ static bool vgic_dist_reg_write(size_t vcpu_id, vgic_t *vgic, uint64_t offset, u irq = CTZ(data); data &= ~(1U << irq); irq += (offset - GIC_DIST_ISPENDR0) * 8; - // @ivanv: should be checking this and other calls like it succeed - vgic_dist_set_pending_irq(vgic, vcpu_id, irq); + success = vgic_dist_set_pending_irq(vgic, vcpu_id, irq); + assert(success); } break; case RANGE32(GIC_DIST_ICPENDR0, GIC_DIST_ICPENDRN): @@ -571,11 +572,15 @@ static bool vgic_dist_reg_write(size_t vcpu_id, vgic_t *vgic, uint64_t offset, u LOG_VMM_ERR("Unknown SGIR Target List Filter mode"); goto ignore_fault; } - // @ivanv: Here we're making the assumption that there's only one vCPU, and - // we're also blindly injectnig the given IRQ to that vCPU. - // @ivanv: come back to this, do we have two writes to the TCB registers? - success = vgic_inject_irq(vcpu_id, virq); - assert(success); + for (int i = 0; i < GUEST_NUM_VCPUS; i++) { + if ((1 << i) & target_list && vcpu_is_on(i)) { + success = vgic_inject_irq(i, virq); + assert(success); + if (!success) { + return false; + } + } + } break; case RANGE32(0xF04, 0xF0C): /* Reserved */ diff --git a/include/libvmm/util/util.h b/include/libvmm/util/util.h index d2778323c..0cb72f280 100644 --- a/include/libvmm/util/util.h +++ b/include/libvmm/util/util.h @@ -12,9 +12,13 @@ #include #include -// @ivanv: these are here for convience, should not be here though #define GUEST_VCPU_ID 0 + +#ifndef GUEST_NUM_VCPUS #define GUEST_NUM_VCPUS 1 +#endif + +#define PAGE_SIZE_MIN 0x1000 // @ivanv: if we keep using this, make sure that we have a static assert // that sizeof seL4_UserContext is 0x24 diff --git a/include/libvmm/vcpu.h b/include/libvmm/vcpu.h index 83cf23af7..7aaa77328 100644 --- a/include/libvmm/vcpu.h +++ b/include/libvmm/vcpu.h @@ -6,7 +6,22 @@ #pragma once +#include #include +/* + * Checks whether the given vCPU is on. + * + * Returns true if the vCPU is on, otherwise false. + * Returns false if an invalid vCPU ID is given. + */ +bool vcpu_is_on(size_t vcpu_id); + +/* + * Change the state tracking for whether a given vCPU is on. + * Does nothing if an invalid vCPU ID is given. + */ +void vcpu_set_on(size_t vcpu_id, bool on); + void vcpu_reset(size_t vcpu_id); void vcpu_print_regs(size_t vcpu_id); diff --git a/src/arch/aarch64/fault.c b/src/arch/aarch64/fault.c index f40a3ded6..609083157 100644 --- a/src/arch/aarch64/fault.c +++ b/src/arch/aarch64/fault.c @@ -251,11 +251,11 @@ bool fault_handle_user_exception(size_t vcpu_id) // @ivanv: print out VM name/vCPU id when we have multiple VMs size_t fault_ip = microkit_mr_get(seL4_UserException_FaultIP); size_t number = microkit_mr_get(seL4_UserException_Number); - LOG_VMM_ERR("Invalid instruction fault at IP: 0x%lx, number: 0x%lx", fault_ip, number); + LOG_VMM_ERR("Invalid instruction fault at IP: 0x%lx, number: 0x%lx from vCPU %d\n", fault_ip, number, vcpu_id); /* All we do is dump the TCB registers. */ tcb_print_regs(vcpu_id); - return true; + return false; } // @ivanv: document where these come from @@ -312,8 +312,7 @@ bool fault_register_vm_exception_handler(uintptr_t base, size_t size, vm_excepti return false; } - // @ivanv: use a define for page size? preMAture GENeraliZAATION - if (base % 0x1000 != 0) { + if (base % PAGE_SIZE_MIN != 0) { return false; } diff --git a/src/arch/aarch64/psci.c b/src/arch/aarch64/psci.c index fb7dc36d4..1bfa85944 100644 --- a/src/arch/aarch64/psci.c +++ b/src/arch/aarch64/psci.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -44,13 +45,43 @@ bool handle_psci(size_t vcpu_id, seL4_UserContext *regs, uint64_t fn_number, uin break; } case PSCI_CPU_ON: { - uintptr_t target_cpu = smc_get_arg(regs, 1); - // Right now we only have one vCPU and so any fault for a target vCPU - // that isn't the one that's already on we consider an error on the - // guest's side. - // @ivanv: adapt for starting other vCPUs - if (target_cpu == vcpu_id) { - smc_set_return_value(regs, PSCI_ALREADY_ON); + size_t target_vcpu = smc_get_arg(regs, 1); + if (target_vcpu < GUEST_NUM_VCPUS && target_vcpu >= 0) { + /* The guest has given a valid target vCPU */ + if (vcpu_is_on(target_vcpu)) { + smc_set_return_value(regs, PSCI_ALREADY_ON); + } else { + /* We have a valid target vCPU, that is not started yet. So let's turn it on. */ + uintptr_t vcpu_entry_point = smc_get_arg(regs, 2); + size_t context_id = smc_get_arg(regs, 3); + + seL4_UserContext vcpu_regs = {0}; + vcpu_regs.x0 = context_id; + vcpu_regs.spsr = 5; // PMODE_EL1h + vcpu_regs.pc = vcpu_entry_point; + + microkit_vcpu_arm_write_reg(target_vcpu, seL4_VCPUReg_VMPIDR_EL2, target_vcpu); + + seL4_Error err = seL4_TCB_WriteRegisters( + BASE_VM_TCB_CAP + target_vcpu, + false, // We'll explcitly start the guest below rather than in this call + 0, // No flags + SEL4_USER_CONTEXT_SIZE, + &vcpu_regs + ); + assert(err == seL4_NoError); + if (err != seL4_NoError) { + return err; + } + + /* Now that we have started the vCPU, we can set is as turned on. */ + vcpu_set_on(target_vcpu, true); + + LOG_VMM("starting guest vCPU (0x%lx) with entry point 0x%lx, context ID: 0x%lx\n", target_vcpu, vcpu_regs.pc, context_id); + microkit_vcpu_restart(target_vcpu, vcpu_regs.pc); + + smc_set_return_value(regs, PSCI_SUCCESS); + } } else { // The guest has requested to turn on a virtual CPU that does // not exist. diff --git a/src/arch/aarch64/vcpu.c b/src/arch/aarch64/vcpu.c index b41ee368b..0a565611f 100644 --- a/src/arch/aarch64/vcpu.c +++ b/src/arch/aarch64/vcpu.c @@ -25,6 +25,26 @@ #define SCTLR_EL1_NATIVE (SCTLR_EL1 | SCTLR_EL1_C | SCTLR_EL1_I | SCTLR_EL1_UCI) #define SCTLR_DEFAULT SCTLR_EL1_NATIVE +bool vcpu_on_state[GUEST_NUM_VCPUS]; + +bool vcpu_is_on(size_t vcpu_id) { + assert(vcpu_id < GUEST_NUM_VCPUS); + if (vcpu_id >= GUEST_NUM_VCPUS) { + return false; + } + + return vcpu_on_state[vcpu_id]; +} + +void vcpu_set_on(size_t vcpu_id, bool on) { + assert(vcpu_id < GUEST_NUM_VCPUS); + if (vcpu_id >= GUEST_NUM_VCPUS) { + return; + } + + vcpu_on_state[vcpu_id] = on; +} + void vcpu_reset(size_t vcpu_id) { // @ivanv this is an incredible amount of system calls // Reset registers diff --git a/src/arch/aarch64/vgic/vgic.c b/src/arch/aarch64/vgic/vgic.c index fb160566c..3e55c266a 100644 --- a/src/arch/aarch64/vgic/vgic.c +++ b/src/arch/aarch64/vgic/vgic.c @@ -5,6 +5,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ #include +#include #include #include #include @@ -83,9 +84,10 @@ bool vgic_register_irq(size_t vcpu_id, int virq_num, virq_ack_fn_t ack_fn, void bool vgic_inject_irq(size_t vcpu_id, int irq) { - LOG_IRQ("Injecting IRQ %d\n", irq); + LOG_IRQ("(vCPU %d) injecting IRQ %d\n", vcpu_id, irq); - return vgic_dist_set_pending_irq(&vgic, vcpu_id, irq); + bool success = vgic_dist_set_pending_irq(&vgic, vcpu_id, irq); + assert(success); // @ivanv: explain why we don't check error before checking this fault stuff // @ivanv: seperately, it seems weird to have this fault handling code here? @@ -94,6 +96,7 @@ bool vgic_inject_irq(size_t vcpu_id, int irq) // // ignore_fault(vcpu->vcpu_arch.fault); // err = advance_vcpu_fault(regs); // } + return success; } // @ivanv: revisit this whole function diff --git a/src/arch/aarch64/vgic/vgic_v2.c b/src/arch/aarch64/vgic/vgic_v2.c index 62cec8bce..556ef0e9b 100644 --- a/src/arch/aarch64/vgic/vgic_v2.c +++ b/src/arch/aarch64/vgic/vgic_v2.c @@ -59,7 +59,7 @@ static void vgic_dist_reset(struct gic_dist_map *gic_dist) gic_dist->typer = 0x0000fce7; /* RO */ gic_dist->iidr = 0x0200043b; /* RO */ - for (int i = 0; i < CONFIG_MAX_NUM_NODES; i++) { + for (int i = 0; i < GUEST_NUM_VCPUS; i++) { gic_dist->enable_set0[i] = 0x0000ffff; /* 16bit RO */ gic_dist->enable_clr0[i] = 0x0000ffff; /* 16bit RO */ } @@ -83,7 +83,7 @@ static void vgic_dist_reset(struct gic_dist_map *gic_dist) gic_dist->config[15] = 0x55555555; /* Configure per-processor SGI/PPI target registers */ - for (int i = 0; i < CONFIG_MAX_NUM_NODES; i++) { + for (int i = 0; i < GUEST_NUM_VCPUS; i++) { for (int j = 0; j < ARRAY_SIZE(gic_dist->targets0[i]); j++) { for (int irq = 0; irq < sizeof(uint32_t); irq++) { gic_dist->targets0[i][j] |= ((1 << i) << (irq * 8)); @@ -109,23 +109,24 @@ static void vgic_dist_reset(struct gic_dist_map *gic_dist) void vgic_init() { memset(&vgic, 0, sizeof(vgic_t)); - for (int i = 0; i < NUM_SLOTS_SPI_VIRQ; i++) { - vgic.vspis[i].virq = VIRQ_INVALID; - } - for (int i = 0; i < NUM_VCPU_LOCAL_VIRQS; i++) { - vgic.vgic_vcpu[GUEST_VCPU_ID].local_virqs[i].virq = VIRQ_INVALID; - } - for (int i = 0; i < NUM_LIST_REGS; i++) { - vgic.vgic_vcpu[GUEST_VCPU_ID].lr_shadow[i].virq = VIRQ_INVALID; - } - for (int i = 0; i < MAX_IRQ_QUEUE_LEN; i++) { - vgic.vgic_vcpu[GUEST_VCPU_ID].irq_queue.irqs[i] = NULL; - } - for (int i = 0; i < NUM_SLOTS_SPI_VIRQ; i++) { - vgic.vspis[i].virq = VIRQ_INVALID; - vgic.vspis[i].ack_fn = NULL; - vgic.vspis[i].ack_data = NULL; + + for (int vcpu = 0; vcpu < GUEST_NUM_VCPUS; vcpu++) { + for (int i = 0; i < NUM_VCPU_LOCAL_VIRQS; i++) { + vgic.vgic_vcpu[vcpu].local_virqs[i].virq = VIRQ_INVALID; + } + for (int i = 0; i < NUM_LIST_REGS; i++) { + vgic.vgic_vcpu[vcpu].lr_shadow[i].virq = VIRQ_INVALID; + } + for (int i = 0; i < MAX_IRQ_QUEUE_LEN; i++) { + vgic.vgic_vcpu[vcpu].irq_queue.irqs[i] = NULL; + } + for (int i = 0; i < NUM_SLOTS_SPI_VIRQ; i++) { + vgic.vspis[i].virq = VIRQ_INVALID; + vgic.vspis[i].ack_fn = NULL; + vgic.vspis[i].ack_data = NULL; + } } + vgic.registers = &dist; memset(vgic.registers, 0, sizeof(struct gic_dist_map)); vgic_dist_reset(vgic_get_dist(vgic.registers)); diff --git a/src/arch/aarch64/vgic/vgic_v3.c b/src/arch/aarch64/vgic/vgic_v3.c index 59e6f9d87..9beed8a43 100644 --- a/src/arch/aarch64/vgic/vgic_v3.c +++ b/src/arch/aarch64/vgic/vgic_v3.c @@ -204,6 +204,7 @@ vgic_reg_t vgic_regs; void vgic_init() { // @ivanv: audit + // TODO: fix for SMP for (int i = 0; i < NUM_SLOTS_SPI_VIRQ; i++) { vgic.vspis[i].virq = VIRQ_INVALID; } diff --git a/src/arch/aarch64/virq.c b/src/arch/aarch64/virq.c index 96bccc1cb..9c4f635fe 100644 --- a/src/arch/aarch64/virq.c +++ b/src/arch/aarch64/virq.c @@ -50,20 +50,22 @@ bool virq_controller_init(size_t boot_vcpu_id) { } #endif - success = vgic_register_irq(boot_vcpu_id, PPI_VTIMER_IRQ, &vppi_event_ack, NULL); - if (!success) { - LOG_VMM_ERR("Failed to register vCPU virtual timer IRQ: 0x%lx\n", PPI_VTIMER_IRQ); - return false; - } - success = vgic_register_irq(boot_vcpu_id, SGI_RESCHEDULE_IRQ, &sgi_ack, NULL); - if (!success) { - LOG_VMM_ERR("Failed to register vCPU SGI 0 IRQ"); - return false; - } - success = vgic_register_irq(boot_vcpu_id, SGI_FUNC_CALL, &sgi_ack, NULL); - if (!success) { - LOG_VMM_ERR("Failed to register vCPU SGI 1 IRQ"); - return false; + for (int vcpu = 0; vcpu < GUEST_NUM_VCPUS; vcpu++) { + success = vgic_register_irq(vcpu, PPI_VTIMER_IRQ, &vppi_event_ack, NULL); + if (!success) { + LOG_VMM_ERR("Failed to register vCPU virtual timer IRQ: 0x%lx\n", PPI_VTIMER_IRQ); + return false; + } + success = vgic_register_irq(vcpu, SGI_RESCHEDULE_IRQ, &sgi_ack, NULL); + if (!success) { + LOG_VMM_ERR("Failed to register vCPU SGI 0 IRQ"); + return false; + } + success = vgic_register_irq(vcpu, SGI_FUNC_CALL, &sgi_ack, NULL); + if (!success) { + LOG_VMM_ERR("Failed to register vCPU SGI 1 IRQ"); + return false; + } } return true; diff --git a/src/guest.c b/src/guest.c index a3557d07e..b5096f295 100644 --- a/src/guest.c +++ b/src/guest.c @@ -34,6 +34,8 @@ bool guest_start(size_t boot_vcpu_id, uintptr_t kernel_pc, uintptr_t dtb, uintpt } LOG_VMM("starting guest at 0x%lx, DTB at 0x%lx, initial RAM disk at 0x%lx\n", regs.pc, regs.x0, initrd); + + vcpu_set_on(boot_vcpu_id, true); /* Restart the boot vCPU to the program counter of the TCB associated with it */ microkit_vcpu_restart(boot_vcpu_id, regs.pc); From 5d26bf9b4625b53c98fa10f790524568bd661449 Mon Sep 17 00:00:00 2001 From: Ivan Velickovic Date: Mon, 19 Aug 2024 15:19:49 +1000 Subject: [PATCH 2/9] Cleaning up vGIC and vIRQ interface Signed-off-by: Ivan Velickovic --- examples/rust/src/vmm.rs | 2 +- examples/simple/vmm.c | 4 +-- examples/virtio-snd/snd_driver_vmm.c | 8 ++--- examples/virtio/blk_driver_vmm.c | 2 +- examples/zig/src/vmm.zig | 4 +-- include/libvmm/arch/aarch64/vgic/vgic.h | 9 +++-- include/libvmm/virq.h | 17 ++++++++- src/arch/aarch64/fault.c | 2 +- src/arch/aarch64/vgic/vgic.c | 47 ++++++++++--------------- src/arch/aarch64/virq.c | 10 ++++-- src/virtio/block.c | 2 +- src/virtio/console.c | 4 +-- src/virtio/net.c | 2 +- src/virtio/sound.c | 2 +- 14 files changed, 63 insertions(+), 52 deletions(-) diff --git a/examples/rust/src/vmm.rs b/examples/rust/src/vmm.rs index 321b57bac..e27a789c7 100644 --- a/examples/rust/src/vmm.rs +++ b/examples/rust/src/vmm.rs @@ -100,7 +100,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"); } diff --git a/examples/simple/vmm.c b/examples/simple/vmm.c index ce260e2e8..f418617f7 100644 --- a/examples/simple/vmm.c +++ b/examples/simple/vmm.c @@ -121,9 +121,9 @@ void init(void) { void notified(microkit_channel ch) { switch (ch) { case SERIAL_IRQ_CH: { - bool success = virq_inject(GUEST_VCPU_ID, SERIAL_IRQ); + bool success = virq_inject(SERIAL_IRQ); if (!success) { - LOG_VMM_ERR("IRQ %d dropped on vCPU %d\n", SERIAL_IRQ, GUEST_VCPU_ID); + LOG_VMM_ERR("IRQ %d dropped\n", SERIAL_IRQ); } break; } diff --git a/examples/virtio-snd/snd_driver_vmm.c b/examples/virtio-snd/snd_driver_vmm.c index d408a1785..9e1b70213 100644 --- a/examples/virtio-snd/snd_driver_vmm.c +++ b/examples/virtio-snd/snd_driver_vmm.c @@ -185,16 +185,16 @@ void notified(microkit_channel ch) { virtio_console_handle_rx(&virtio_console); break; case SND_CLIENT_CH: - success = virq_inject(GUEST_VCPU_ID, UIO_SND_IRQ); + success = virq_inject(UIO_SND_IRQ); if (!success) { - LOG_VMM_ERR("IRQ %d dropped on vCPU %d\n", UIO_SND_IRQ, GUEST_VCPU_ID); + LOG_VMM_ERR("IRQ %d dropped\n", UIO_SND_IRQ); } break; default: if (passthrough_irq_map[ch]) { - success = virq_inject(GUEST_VCPU_ID, passthrough_irq_map[ch]); + success = virq_inject(passthrough_irq_map[ch]); if (!success) { - LOG_VMM_ERR("IRQ %d dropped on vCPU %d\n", passthrough_irq_map[ch], GUEST_VCPU_ID); + LOG_VMM_ERR("IRQ %d dropped\n", passthrough_irq_map[ch]); } } else { printf("Unexpected channel, ch: 0x%lx\n", ch); diff --git a/examples/virtio/blk_driver_vmm.c b/examples/virtio/blk_driver_vmm.c index b1f54f069..ad78b673a 100644 --- a/examples/virtio/blk_driver_vmm.c +++ b/examples/virtio/blk_driver_vmm.c @@ -145,7 +145,7 @@ void notified(microkit_channel ch) switch (ch) { case UIO_CH: { - int success = virq_inject(GUEST_VCPU_ID, UIO_IRQ); + int success = virq_inject(UIO_IRQ); if (!success) { LOG_VMM_ERR("Failed to inject UIO IRQ 0x%lx\n", UIO_IRQ); } diff --git a/examples/zig/src/vmm.zig b/examples/zig/src/vmm.zig index 51f9cd82c..b0d5cf9ec 100644 --- a/examples/zig/src/vmm.zig +++ b/examples/zig/src/vmm.zig @@ -118,9 +118,9 @@ export fn init() callconv(.C) void { export fn notified(ch: microkit.microkit_channel) callconv(.C) void { switch (ch) { SERIAL_IRQ_CH => { - const success = c.virq_inject(GUEST_BOOT_VCPU_ID, SERIAL_IRQ); + const success = c.virq_inject(SERIAL_IRQ); if (!success) { - log.err("IRQ {x} dropped on vCPU {x}\n", .{ SERIAL_IRQ, GUEST_BOOT_VCPU_ID }); + log.err("IRQ {x} dropped\n", .{ SERIAL_IRQ }); } }, else => log.err("Unexpected channel, ch: {x}\n", .{ ch }) diff --git a/include/libvmm/arch/aarch64/vgic/vgic.h b/include/libvmm/arch/aarch64/vgic/vgic.h index dab3759fb..c64bea7f2 100644 --- a/include/libvmm/arch/aarch64/vgic/vgic.h +++ b/include/libvmm/arch/aarch64/vgic/vgic.h @@ -50,8 +50,11 @@ #endif void vgic_init(); -bool fault_handle_vgic_maintenance(size_t vcpu_id); -bool handle_vgic_dist_fault(size_t vcpu_id, size_t offset, size_t fsr, seL4_UserContext *regs, void *data); -bool handle_vgic_redist_fault(size_t vcpu_id, size_t offset, size_t fsr, seL4_UserContext *regs, void *data); + +bool vgic_handle_fault_maintenance(size_t vcpu_id); + +bool vgic_handle_fault_dist(size_t vcpu_id, size_t offset, size_t fsr, seL4_UserContext *regs, void *data); +bool vgic_handle_fault_redist(size_t vcpu_id, size_t offset, size_t fsr, seL4_UserContext *regs, void *data); + bool vgic_register_irq(size_t vcpu_id, int virq_num, virq_ack_fn_t ack_fn, void *ack_data); bool vgic_inject_irq(size_t vcpu_id, int irq); diff --git a/include/libvmm/virq.h b/include/libvmm/virq.h index 0b9213642..363d74a84 100644 --- a/include/libvmm/virq.h +++ b/include/libvmm/virq.h @@ -14,9 +14,24 @@ typedef void (*virq_ack_fn_t)(size_t vcpu_id, int irq, void *cookie); +/* + * Initialise the architecture-depedent virtual interrupt controller. + * On ARM, this is the virtual Generic Interrupt Controller (vGIC). + */ bool virq_controller_init(size_t boot_vcpu_id); bool virq_register(size_t vcpu_id, size_t virq_num, virq_ack_fn_t ack_fn, void *ack_data); -bool virq_inject(size_t vcpu_id, int irq); + +/* + * Inject an IRQ into the boot virtual CPU. + * Note that this API requires that the IRQ has been registered (with virq_register). + */ +bool virq_inject(int irq); + +/* + * The same functionality as virq_inject, but will inject the virtual IRQ into a specific + * virtual CPU. + */ +bool virq_inject_vcpu(size_t vcpu_id, int irq); /* * These two APIs are convenient for when you want to directly passthrough an IRQ from diff --git a/src/arch/aarch64/fault.c b/src/arch/aarch64/fault.c index 609083157..2362ac901 100644 --- a/src/arch/aarch64/fault.c +++ b/src/arch/aarch64/fault.c @@ -395,7 +395,7 @@ bool fault_handle(size_t vcpu_id, microkit_msginfo msginfo) { success = fault_handle_user_exception(vcpu_id); break; case seL4_Fault_VGICMaintenance: - success = fault_handle_vgic_maintenance(vcpu_id); + success = vgic_handle_fault_maintenance(vcpu_id); break; case seL4_Fault_VCPUFault: success = fault_handle_vcpu_exception(vcpu_id); diff --git a/src/arch/aarch64/vgic/vgic.c b/src/arch/aarch64/vgic/vgic.c index 3e55c266a..4e51710f6 100644 --- a/src/arch/aarch64/vgic/vgic.c +++ b/src/arch/aarch64/vgic/vgic.c @@ -1,4 +1,4 @@ -/* @ivanv double check +/* * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) * Copyright 2022, UNSW (ABN 57 195 873 179) * @@ -24,13 +24,13 @@ /* The driver expects the VGIC state to be initialised before calling any of the driver functionality. */ extern vgic_t vgic; -bool fault_handle_vgic_maintenance(size_t vcpu_id) +bool vgic_handle_fault_maintenance(size_t vcpu_id) { // @ivanv: reivist, also inconsistency between int and bool bool success = true; int idx = microkit_mr_get(seL4_VGICMaintenance_IDX); /* Currently not handling spurious IRQs */ - // @ivanv: wtf, this comment seems irrelevant to the code. + // @ivanv: this comment seems irrelevant to the code. assert(idx >= 0); // @ivanv: Revisit and make sure it's still correct. @@ -63,14 +63,27 @@ bool fault_handle_vgic_maintenance(size_t vcpu_id) } if (!success) { - printf("VGIC|ERROR: maintenance handler failed\n"); + LOG_VMM_ERR("vGIC maintenance handler failed\n"); assert(0); } return success; } -// @ivanv: maybe this shouldn't be here? +bool vgic_handle_fault_dist(size_t vcpu_id, size_t offset, size_t fsr, seL4_UserContext *regs, void *data) +{ + bool success = false; + if (fault_is_read(fsr)) { + success = vgic_dist_reg_read(vcpu_id, &vgic, offset, fsr, regs); + assert(success); + } else { + success = vgic_dist_reg_write(vcpu_id, &vgic, offset, fsr, regs); + assert(success); + } + + return success; +} + bool vgic_register_irq(size_t vcpu_id, int virq_num, virq_ack_fn_t ack_fn, void *ack_data) { assert(virq_num >= 0 && virq_num != VIRQ_INVALID); struct virq_handle virq = { @@ -89,29 +102,5 @@ bool vgic_inject_irq(size_t vcpu_id, int irq) bool success = vgic_dist_set_pending_irq(&vgic, vcpu_id, irq); assert(success); - // @ivanv: explain why we don't check error before checking this fault stuff - // @ivanv: seperately, it seems weird to have this fault handling code here? - // @ivanv: revist - // if (!fault_handled(vcpu->vcpu_arch.fault) && fault_is_wfi(vcpu->vcpu_arch.fault)) { - // // ignore_fault(vcpu->vcpu_arch.fault); - // err = advance_vcpu_fault(regs); - // } return success; } - -// @ivanv: revisit this whole function -bool handle_vgic_dist_fault(size_t vcpu_id, size_t offset, size_t fsr, seL4_UserContext *regs, void *data) -{ - bool success = false; - if (fault_is_read(fsr)) { - // printf("VGIC|INFO: Read dist\n"); - success = vgic_dist_reg_read(vcpu_id, &vgic, offset, fsr, regs); - assert(success); - } else { - // printf("VGIC|INFO: Write dist\n"); - success = vgic_dist_reg_write(vcpu_id, &vgic, offset, fsr, regs); - assert(success); - } - - return success; -} \ No newline at end of file diff --git a/src/arch/aarch64/virq.c b/src/arch/aarch64/virq.c index 9c4f635fe..5b02c25e3 100644 --- a/src/arch/aarch64/virq.c +++ b/src/arch/aarch64/virq.c @@ -37,13 +37,13 @@ bool virq_controller_init(size_t boot_vcpu_id) { #endif /* Register the fault handler */ - success = fault_register_vm_exception_handler(GIC_DIST_PADDR, GIC_DIST_SIZE, handle_vgic_dist_fault, NULL); + success = fault_register_vm_exception_handler(GIC_DIST_PADDR, GIC_DIST_SIZE, vgic_handle_fault_dist, NULL); if (!success) { LOG_VMM_ERR("Failed to register fault handler for GIC distributor region\n"); return false; } #if defined(GIC_V3) - success = fault_register_vm_exception_handler(GIC_REDIST_PADDR, GIC_REDIST_SIZE, handle_vgic_redist_fault, NULL); + success = fault_register_vm_exception_handler(GIC_REDIST_PADDR, GIC_REDIST_SIZE, vgic_handle_fault_redist, NULL); if (!success) { LOG_VMM_ERR("Failed to register fault handler for GIC redistributor region\n"); return false; @@ -71,10 +71,14 @@ bool virq_controller_init(size_t boot_vcpu_id) { return true; } -bool virq_inject(size_t vcpu_id, int irq) { +bool virq_inject_vcpu(size_t vcpu_id, int irq) { return vgic_inject_irq(vcpu_id, irq); } +bool virq_inject(int irq) { + return vgic_inject_irq(GUEST_VCPU_ID, irq); +} + bool virq_register(size_t vcpu_id, size_t virq_num, virq_ack_fn_t ack_fn, void *ack_data) { return vgic_register_irq(vcpu_id, virq_num, ack_fn, ack_data); } diff --git a/src/virtio/block.c b/src/virtio/block.c index 4844fb74f..16077ae90 100644 --- a/src/virtio/block.c +++ b/src/virtio/block.c @@ -136,7 +136,7 @@ static void virtio_blk_used_buffer(struct virtio_device *dev, uint16_t desc) static bool virtio_blk_virq_inject(struct virtio_device *dev) { - return virq_inject(GUEST_VCPU_ID, dev->virq); + return virq_inject(dev->virq); } static void virtio_blk_set_interrupt_status(struct virtio_device *dev, diff --git a/src/virtio/console.c b/src/virtio/console.c index c21311a9a..394dceda6 100644 --- a/src/virtio/console.c +++ b/src/virtio/console.c @@ -162,7 +162,7 @@ static bool virtio_console_handle_tx(struct virtio_device *dev) * available data. In this case we do not set the IRQ status. */ if (transferred) { dev->data.InterruptStatus = BIT_LOW(0); - bool success = virq_inject(GUEST_VCPU_ID, dev->virq); + bool success = virq_inject(dev->virq); assert(success); if (serial_require_producer_signal(&console->txq)) { @@ -221,7 +221,7 @@ bool virtio_console_handle_rx(struct virtio_console_device *console) * available data. In this case we do not set the IRQ status. */ if (transferred) { console->virtio_device.data.InterruptStatus = BIT_LOW(0); - bool success = virq_inject(GUEST_VCPU_ID, console->virtio_device.virq); + bool success = virq_inject(console->virtio_device.virq); assert(success); return success; diff --git a/src/virtio/net.c b/src/virtio/net.c index a47e4c965..c75ae34a7 100644 --- a/src/virtio/net.c +++ b/src/virtio/net.c @@ -138,7 +138,7 @@ static void virtq_enqueue_used(struct virtq *virtq, uint32_t desc_head, uint32_t static bool virtio_net_respond(struct virtio_device *dev) { dev->data.InterruptStatus = BIT_LOW(0); - bool success = virq_inject(GUEST_VCPU_ID, dev->virq); + bool success = virq_inject(dev->virq); assert(success); return success; diff --git a/src/virtio/sound.c b/src/virtio/sound.c index a4b1c3985..f32f9c0a2 100644 --- a/src/virtio/sound.c +++ b/src/virtio/sound.c @@ -147,7 +147,7 @@ static const char *code_to_str(uint32_t code) static void virtio_snd_respond(struct virtio_device *dev) { dev->data.InterruptStatus = BIT_LOW(0); - bool success = virq_inject(GUEST_VCPU_ID, dev->virq); + bool success = virq_inject(dev->virq); assert(success); } From 515a4e542eeb86406d703d80b9a746aa8c5b8bc6 Mon Sep 17 00:00:00 2001 From: Ivan Velickovic Date: Mon, 19 Aug 2024 15:39:02 +1000 Subject: [PATCH 3/9] fixes Signed-off-by: Ivan Velickovic --- include/libvmm/arch/aarch64/vgic/vdist.h | 4 ++-- src/arch/aarch64/vgic/vgic.c | 4 ++-- src/arch/aarch64/vgic/vgic_v3.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/libvmm/arch/aarch64/vgic/vdist.h b/include/libvmm/arch/aarch64/vgic/vdist.h index e2d07d4d3..71bd5f194 100644 --- a/include/libvmm/arch/aarch64/vgic/vdist.h +++ b/include/libvmm/arch/aarch64/vgic/vdist.h @@ -247,7 +247,7 @@ static void vgic_dist_clr_pending_irq(struct gic_dist_map *dist, size_t vcpu_id, // @ivanv } -static bool vgic_dist_reg_read(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, seL4_UserContext *regs) +static bool vgic_handle_fault_dist_read(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, seL4_UserContext *regs) { struct gic_dist_map *gic_dist = vgic_get_dist(vgic->registers); uint32_t reg = 0; @@ -414,7 +414,7 @@ static inline void emulate_reg_write_access(seL4_UserContext *regs, uint64_t add *reg = fault_emulate(regs, *reg, addr, fsr, fault_get_data(regs, fsr)); } -static bool vgic_dist_reg_write(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, seL4_UserContext *regs) +static bool vgic_handle_fault_dist_write(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, seL4_UserContext *regs) { bool success = true; struct gic_dist_map *gic_dist = vgic_get_dist(vgic->registers); diff --git a/src/arch/aarch64/vgic/vgic.c b/src/arch/aarch64/vgic/vgic.c index 4e51710f6..debca5432 100644 --- a/src/arch/aarch64/vgic/vgic.c +++ b/src/arch/aarch64/vgic/vgic.c @@ -74,10 +74,10 @@ bool vgic_handle_fault_dist(size_t vcpu_id, size_t offset, size_t fsr, seL4_User { bool success = false; if (fault_is_read(fsr)) { - success = vgic_dist_reg_read(vcpu_id, &vgic, offset, fsr, regs); + success = vgic_handle_fault_dist_read(vcpu_id, &vgic, offset, fsr, regs); assert(success); } else { - success = vgic_dist_reg_write(vcpu_id, &vgic, offset, fsr, regs); + success = vgic_handle_fault_dist_write(vcpu_id, &vgic, offset, fsr, regs); assert(success); } diff --git a/src/arch/aarch64/vgic/vgic_v3.c b/src/arch/aarch64/vgic/vgic_v3.c index 9beed8a43..f92f78fb2 100644 --- a/src/arch/aarch64/vgic/vgic_v3.c +++ b/src/arch/aarch64/vgic/vgic_v3.c @@ -45,7 +45,7 @@ vgic_t vgic; -static bool handle_vgic_redist_read_fault(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, seL4_UserContext *regs) +static bool vgic_handle_fault_redist_read(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, seL4_UserContext *regs) { struct gic_dist_map *gic_dist = vgic_get_dist(vgic->registers); struct gic_redist_map *gic_redist = vgic_get_redist(vgic->registers); @@ -97,7 +97,7 @@ static bool handle_vgic_redist_read_fault(size_t vcpu_id, vgic_t *vgic, uint64_t } -static bool handle_vgic_redist_write_fault(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, seL4_UserContext *regs) +static bool vgic_handle_fault_redist_write(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, seL4_UserContext *regs) { // @ivanv: why is this not reading from the redist? uintptr_t fault_addr = GIC_REDIST_PADDR + offset; @@ -147,7 +147,7 @@ static bool handle_vgic_redist_write_fault(size_t vcpu_id, vgic_t *vgic, uint64_ return true; } -bool handle_vgic_redist_fault(size_t vcpu_id, size_t offset, size_t fsr, seL4_UserContext *regs, void *data) { +bool vgic_handle_fault_redist(size_t vcpu_id, size_t offset, size_t fsr, seL4_UserContext *regs, void *data) { if (fault_is_read(fsr)) { return handle_vgic_redist_read_fault(vcpu_id, &vgic, offset, fsr, regs); } else { From acdc3cb90403be224805dea49655ebaf9feaa84d Mon Sep 17 00:00:00 2001 From: Ivan Velickovic Date: Mon, 19 Aug 2024 15:40:29 +1000 Subject: [PATCH 4/9] Cleanup usage of guest boot vCPU ID Signed-off-by: Ivan Velickovic --- examples/rust/src/vmm.rs | 8 ++++---- examples/simple/vmm.c | 6 +++--- examples/virtio-snd/client_vmm.c | 4 ++-- examples/virtio-snd/snd_driver_vmm.c | 8 ++++---- examples/virtio/blk_driver_vmm.c | 10 +++++----- examples/virtio/client_vmm.c | 4 ++-- include/libvmm/guest.h | 6 +++--- include/libvmm/util/util.h | 2 +- include/libvmm/virq.h | 2 +- src/arch/aarch64/vgic/vgic_v3.c | 4 ++-- src/arch/aarch64/virq.c | 10 +++++----- src/guest.c | 22 +++++++++++----------- src/virtio/mmio.c | 2 +- 13 files changed, 44 insertions(+), 44 deletions(-) diff --git a/examples/rust/src/vmm.rs b/examples/rust/src/vmm.rs index e27a789c7..3bd44a80a 100644 --- a/examples/rust/src/vmm.rs +++ b/examples/rust/src/vmm.rs @@ -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; @@ -77,15 +77,15 @@ fn init() -> VmmHandler { 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()); + _ = virq_controller_init(); + _ = virq_register(UART_IRQ as i32, uart_irq_ack, core::ptr::null()); 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 {} diff --git a/examples/simple/vmm.c b/examples/simple/vmm.c index f418617f7..68b993b8e 100644 --- a/examples/simple/vmm.c +++ b/examples/simple/vmm.c @@ -106,16 +106,16 @@ void init(void) { 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(GUEST_BOOT_VCPU_ID, kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR); } void notified(microkit_channel ch) { diff --git a/examples/virtio-snd/client_vmm.c b/examples/virtio-snd/client_vmm.c index 5606cb071..95f4b2cb1 100644 --- a/examples/virtio-snd/client_vmm.c +++ b/examples/virtio-snd/client_vmm.c @@ -95,7 +95,7 @@ void init(void) { } /* 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; @@ -147,7 +147,7 @@ void init(void) { 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); } diff --git a/examples/virtio-snd/snd_driver_vmm.c b/examples/virtio-snd/snd_driver_vmm.c index 9e1b70213..46fc3468f 100644 --- a/examples/virtio-snd/snd_driver_vmm.c +++ b/examples/virtio-snd/snd_driver_vmm.c @@ -82,7 +82,7 @@ static void register_passthrough_irq(int irq, microkit_channel irq_ch) { assert(irq_ch < MAX_IRQ_CH); passthrough_irq_map[irq_ch] = irq; - int err = virq_register(GUEST_VCPU_ID, irq, &passthrough_device_ack, (void *)(int64_t)irq_ch); + int err = virq_register(GUEST_BOOT_VCPU_ID, irq, &passthrough_device_ack, (void *)(int64_t)irq_ch); if (!err) { LOG_VMM_ERR("Failed to register IRQ %d\n", irq); return; @@ -124,7 +124,7 @@ void init(void) { } /* Initialise the virtual GIC driver */ - bool success = virq_controller_init(GUEST_VCPU_ID); + bool success = virq_controller_init(GUEST_BOOT_VCPU_ID); if (!success) { LOG_VMM_ERR("Failed to initialise emulated interrupt controller\n"); return; @@ -148,7 +148,7 @@ void init(void) { SERIAL_TX_CH); assert(success); - success = virq_register(GUEST_VCPU_ID, UIO_SND_IRQ, &uio_sound_virq_ack, NULL); + success = virq_register(GUEST_BOOT_VCPU_ID, UIO_SND_IRQ, &uio_sound_virq_ack, NULL); assert(success); success = fault_register_vm_exception_handler(UIO_SND_FAULT_ADDRESS, @@ -172,7 +172,7 @@ void init(void) { cache_clean((uintptr_t)data_paddr, sizeof(uintptr_t)); /* Finally start the guest */ - guest_start(GUEST_VCPU_ID, kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR); + guest_start(GUEST_BOOT_VCPU_ID, kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR); } void notified(microkit_channel ch) { diff --git a/examples/virtio/blk_driver_vmm.c b/examples/virtio/blk_driver_vmm.c index ad78b673a..bd9cc4b4c 100644 --- a/examples/virtio/blk_driver_vmm.c +++ b/examples/virtio/blk_driver_vmm.c @@ -95,7 +95,7 @@ void init(void) } /* Initialise the virtual GIC driver */ - bool success = virq_controller_init(GUEST_VCPU_ID); + bool success = virq_controller_init(GUEST_BOOT_VCPU_ID); if (!success) { LOG_VMM_ERR("Failed to initialise emulated interrupt controller\n"); return; @@ -121,20 +121,20 @@ void init(void) assert(success); /* Register the UIO IRQ */ - virq_register(GUEST_VCPU_ID, UIO_IRQ, uio_ack, NULL); + virq_register(GUEST_BOOT_VCPU_ID, UIO_IRQ, uio_ack, NULL); #if defined(BOARD_odroidc4) /* Register the SD card IRQ */ - virq_register_passthrough(GUEST_VCPU_ID, SD_IRQ, BLOCK_CH); + virq_register_passthrough(GUEST_BOOT_VCPU_ID, SD_IRQ, BLOCK_CH); #endif #if defined(BOARD_qemu_virt_aarch64) /* Register the block device IRQ */ - virq_register_passthrough(GUEST_VCPU_ID, BLOCK_IRQ, BLOCK_CH); + virq_register_passthrough(GUEST_BOOT_VCPU_ID, BLOCK_IRQ, BLOCK_CH); #endif /* Finally start the guest */ - guest_start(GUEST_VCPU_ID, kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR); + guest_start(GUEST_BOOT_VCPU_ID, kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR); } void notified(microkit_channel ch) diff --git a/examples/virtio/client_vmm.c b/examples/virtio/client_vmm.c index 01225b496..23925b2b4 100644 --- a/examples/virtio/client_vmm.c +++ b/examples/virtio/client_vmm.c @@ -103,7 +103,7 @@ void init(void) } /* Initialise the virtual GIC driver */ - bool success = virq_controller_init(GUEST_VCPU_ID); + bool success = virq_controller_init(GUEST_BOOT_VCPU_ID); if (!success) { LOG_VMM_ERR("Failed to initialise emulated interrupt controller\n"); return; @@ -140,7 +140,7 @@ void init(void) assert(success); /* Finally start the guest */ - guest_start(GUEST_VCPU_ID, kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR); + guest_start(GUEST_BOOT_VCPU_ID, kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR); } void notified(microkit_channel ch) diff --git a/include/libvmm/guest.h b/include/libvmm/guest.h index 91cd03647..78c4db2e9 100644 --- a/include/libvmm/guest.h +++ b/include/libvmm/guest.h @@ -7,6 +7,6 @@ #include #include -bool guest_start(size_t boot_vcpu_id, uintptr_t kernel_pc, uintptr_t dtb, uintptr_t initrd); -void guest_stop(size_t boot_vcpu_id); -bool guest_restart(size_t boot_vcpu_id, uintptr_t guest_ram_vaddr, size_t guest_ram_size); +bool guest_start(uintptr_t kernel_pc, uintptr_t dtb, uintptr_t initrd); +void guest_stop(); +bool guest_restart(uintptr_t guest_ram_vaddr, size_t guest_ram_size); diff --git a/include/libvmm/util/util.h b/include/libvmm/util/util.h index 0cb72f280..6b808ed33 100644 --- a/include/libvmm/util/util.h +++ b/include/libvmm/util/util.h @@ -12,7 +12,7 @@ #include #include -#define GUEST_VCPU_ID 0 +#define GUEST_BOOT_VCPU_ID 0 #ifndef GUEST_NUM_VCPUS #define GUEST_NUM_VCPUS 1 diff --git a/include/libvmm/virq.h b/include/libvmm/virq.h index 363d74a84..ba6231549 100644 --- a/include/libvmm/virq.h +++ b/include/libvmm/virq.h @@ -18,7 +18,7 @@ typedef void (*virq_ack_fn_t)(size_t vcpu_id, int irq, void *cookie); * Initialise the architecture-depedent virtual interrupt controller. * On ARM, this is the virtual Generic Interrupt Controller (vGIC). */ -bool virq_controller_init(size_t boot_vcpu_id); +bool virq_controller_init(); bool virq_register(size_t vcpu_id, size_t virq_num, virq_ack_fn_t ack_fn, void *ack_data); /* diff --git a/src/arch/aarch64/vgic/vgic_v3.c b/src/arch/aarch64/vgic/vgic_v3.c index f92f78fb2..ce602366b 100644 --- a/src/arch/aarch64/vgic/vgic_v3.c +++ b/src/arch/aarch64/vgic/vgic_v3.c @@ -209,10 +209,10 @@ void vgic_init() vgic.vspis[i].virq = VIRQ_INVALID; } for (int i = 0; i < NUM_VCPU_LOCAL_VIRQS; i++) { - vgic.vgic_vcpu[GUEST_VCPU_ID].local_virqs[i].virq = VIRQ_INVALID; + vgic.vgic_vcpu[GUEST_BOOT_VCPU_ID].local_virqs[i].virq = VIRQ_INVALID; } for (int i = 0; i < NUM_LIST_REGS; i++) { - vgic.vgic_vcpu[GUEST_VCPU_ID].lr_shadow[i].virq = VIRQ_INVALID; + vgic.vgic_vcpu[GUEST_BOOT_VCPU_ID].lr_shadow[i].virq = VIRQ_INVALID; } vgic.registers = &vgic_regs; vgic_regs.dist = &dist; diff --git a/src/arch/aarch64/virq.c b/src/arch/aarch64/virq.c index 5b02c25e3..6dfa9e02e 100644 --- a/src/arch/aarch64/virq.c +++ b/src/arch/aarch64/virq.c @@ -24,7 +24,7 @@ static void vppi_event_ack(size_t vcpu_id, int irq, void *cookie) static void sgi_ack(size_t vcpu_id, int irq, void *cookie) {} -bool virq_controller_init(size_t boot_vcpu_id) { +bool virq_controller_init() { bool success; vgic_init(); @@ -76,7 +76,7 @@ bool virq_inject_vcpu(size_t vcpu_id, int irq) { } bool virq_inject(int irq) { - return vgic_inject_irq(GUEST_VCPU_ID, irq); + return vgic_inject_irq(GUEST_BOOT_VCPU_ID, irq); } bool virq_register(size_t vcpu_id, size_t virq_num, virq_ack_fn_t ack_fn, void *ack_data) { @@ -98,7 +98,7 @@ bool virq_register_passthrough(size_t vcpu_id, size_t irq, microkit_channel irq_ LOG_VMM("Register passthrough vIRQ 0x%lx on vCPU 0x%lx (IRQ channel: 0x%lx)\n", irq, vcpu_id, irq_ch); virq_passthrough_map[irq_ch] = irq; - bool success = virq_register(GUEST_VCPU_ID, irq, &virq_passthrough_ack, (void *)(size_t)irq_ch); + bool success = virq_register(GUEST_BOOT_VCPU_ID, irq, &virq_passthrough_ack, (void *)(size_t)irq_ch); assert(success); if (!success) { LOG_VMM_ERR("Failed to register passthrough vIRQ %d\n", irq); @@ -115,9 +115,9 @@ bool virq_handle_passthrough(microkit_channel irq_ch) { return false; } - bool success = vgic_inject_irq(GUEST_VCPU_ID, virq_passthrough_map[irq_ch]); + bool success = vgic_inject_irq(GUEST_BOOT_VCPU_ID, virq_passthrough_map[irq_ch]); if (!success) { - LOG_VMM_ERR("could not inject passthrough vIRQ 0x%lx, dropped on vCPU 0x%lx\n", virq_passthrough_map[irq_ch], GUEST_VCPU_ID); + LOG_VMM_ERR("could not inject passthrough vIRQ 0x%lx, dropped on vCPU 0x%lx\n", virq_passthrough_map[irq_ch], GUEST_BOOT_VCPU_ID); return false; } diff --git a/src/guest.c b/src/guest.c index b5096f295..8f94ac5df 100644 --- a/src/guest.c +++ b/src/guest.c @@ -8,7 +8,7 @@ #include #include -bool guest_start(size_t boot_vcpu_id, uintptr_t kernel_pc, uintptr_t dtb, uintptr_t initrd) { +bool guest_start(uintptr_t kernel_pc, uintptr_t dtb, uintptr_t initrd) { /* * Set the TCB registers to what the virtual machine expects to be started with. * You will note that this is currently Linux specific as we currently do not support @@ -21,7 +21,7 @@ bool guest_start(size_t boot_vcpu_id, uintptr_t kernel_pc, uintptr_t dtb, uintpt regs.pc = kernel_pc; /* Write out all the TCB registers */ seL4_Word err = seL4_TCB_WriteRegisters( - BASE_VM_TCB_CAP + boot_vcpu_id, + BASE_VM_TCB_CAP + GUEST_BOOT_VCPU_ID, false, // We'll explcitly start the guest below rather than in this call 0, // No flags 4, // Writing to x0, pc, and spsr. Due to the ordering of seL4_UserContext the count must be 4. @@ -29,29 +29,29 @@ bool guest_start(size_t boot_vcpu_id, uintptr_t kernel_pc, uintptr_t dtb, uintpt ); assert(err == seL4_NoError); if (err != seL4_NoError) { - LOG_VMM_ERR("Failed to write registers to boot vCPU's TCB (id is 0x%lx), error is: 0x%lx\n", boot_vcpu_id, err); + LOG_VMM_ERR("Failed to write registers to boot vCPU's TCB (id is 0x%lx), error is: 0x%lx\n", GUEST_BOOT_VCPU_ID, err); return false; } LOG_VMM("starting guest at 0x%lx, DTB at 0x%lx, initial RAM disk at 0x%lx\n", regs.pc, regs.x0, initrd); - vcpu_set_on(boot_vcpu_id, true); + vcpu_set_on(GUEST_BOOT_VCPU_ID, true); /* Restart the boot vCPU to the program counter of the TCB associated with it */ - microkit_vcpu_restart(boot_vcpu_id, regs.pc); + microkit_vcpu_restart(GUEST_BOOT_VCPU_ID, regs.pc); return true; } -void guest_stop(size_t boot_vcpu_id) { +void guest_stop() { LOG_VMM("Stopping guest\n"); - microkit_vcpu_stop(boot_vcpu_id); + microkit_vcpu_stop(GUEST_BOOT_VCPU_ID); LOG_VMM("Stopped guest\n"); } -bool guest_restart(size_t boot_vcpu_id, uintptr_t guest_ram_vaddr, size_t guest_ram_size) { +bool guest_restart(uintptr_t guest_ram_vaddr, size_t guest_ram_size) { LOG_VMM("Attempting to restart guest\n"); // First, stop the guest - microkit_vcpu_stop(boot_vcpu_id); + microkit_vcpu_stop(GUEST_BOOT_VCPU_ID); LOG_VMM("Stopped guest\n"); // Then, we need to clear all of RAM LOG_VMM("Clearing guest RAM\n"); @@ -62,10 +62,10 @@ bool guest_restart(size_t boot_vcpu_id, uintptr_t guest_ram_vaddr, size_t guest_ // LOG_VMM_ERR("Failed to initialise guest images\n"); // return false; // } - vcpu_reset(boot_vcpu_id); + vcpu_reset(GUEST_BOOT_VCPU_ID); // Now we need to re-initialise all the VMM state // vmm_init(); - // linux_start(GUEST_VCPU_ID, kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR); + // linux_start(GUEST_BOOT_VCPU_ID, kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR); LOG_VMM("Restarted guest\n"); return true; } diff --git a/src/virtio/mmio.c b/src/virtio/mmio.c index 9362ee7db..f59388f49 100644 --- a/src/virtio/mmio.c +++ b/src/virtio/mmio.c @@ -343,7 +343,7 @@ bool virtio_mmio_register_device(virtio_device_t *dev, /* Register the virtual IRQ that will be used to communicate from the device * to the guest. This assumes that the interrupt controller is already setup. */ // @ivanv: we should check that (on AArch64) the virq is an SPI. - success = virq_register(GUEST_VCPU_ID, virq, &virtio_virq_default_ack, NULL); + success = virq_register(GUEST_BOOT_VCPU_ID, virq, &virtio_virq_default_ack, NULL); assert(success); return success; From 6532fe77b40d9e49676692f92608e0cdbb002bff Mon Sep 17 00:00:00 2001 From: Ivan Velickovic Date: Mon, 19 Aug 2024 15:51:49 +1000 Subject: [PATCH 5/9] More fixes Signed-off-by: Ivan Velickovic --- examples/simple/vmm.c | 2 +- src/arch/aarch64/psci.c | 2 +- src/arch/aarch64/vgic/vgic_v3.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/simple/vmm.c b/examples/simple/vmm.c index 68b993b8e..7fabc883d 100644 --- a/examples/simple/vmm.c +++ b/examples/simple/vmm.c @@ -115,7 +115,7 @@ void init(void) { /* 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_BOOT_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) { diff --git a/src/arch/aarch64/psci.c b/src/arch/aarch64/psci.c index 1bfa85944..3f9577b50 100644 --- a/src/arch/aarch64/psci.c +++ b/src/arch/aarch64/psci.c @@ -124,7 +124,7 @@ bool handle_psci(size_t vcpu_id, seL4_UserContext *regs, uint64_t fn_number, uin case PSCI_SYSTEM_OFF: // @refactor, is it guaranteed that the CPU that does the vCPU request // is the boot vcpu? - guest_stop(vcpu_id); + guest_stop(); return true; default: LOG_VMM_ERR("Unhandled PSCI function ID 0x%lx\n", fn_number); diff --git a/src/arch/aarch64/vgic/vgic_v3.c b/src/arch/aarch64/vgic/vgic_v3.c index ce602366b..63efe504b 100644 --- a/src/arch/aarch64/vgic/vgic_v3.c +++ b/src/arch/aarch64/vgic/vgic_v3.c @@ -149,9 +149,9 @@ static bool vgic_handle_fault_redist_write(size_t vcpu_id, vgic_t *vgic, uint64_ bool vgic_handle_fault_redist(size_t vcpu_id, size_t offset, size_t fsr, seL4_UserContext *regs, void *data) { if (fault_is_read(fsr)) { - return handle_vgic_redist_read_fault(vcpu_id, &vgic, offset, fsr, regs); + return vgic_handle_fault_redist_read(vcpu_id, &vgic, offset, fsr, regs); } else { - return handle_vgic_redist_write_fault(vcpu_id, &vgic, offset, fsr, regs); + return vgic_handle_fault_redist_write(vcpu_id, &vgic, offset, fsr, regs); } } From e51b809ad243f219dd5e2bab917def6bbecf1fe4 Mon Sep 17 00:00:00 2001 From: Ivan Velickovic Date: Tue, 20 Aug 2024 10:54:53 +1000 Subject: [PATCH 6/9] more cleanup Signed-off-by: Ivan Velickovic --- examples/rust/src/vmm.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/examples/rust/src/vmm.rs b/examples/rust/src/vmm.rs index 3bd44a80a..0f8a6b773 100644 --- a/examples/rust/src/vmm.rs +++ b/examples/rust/src/vmm.rs @@ -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; } @@ -76,9 +76,10 @@ 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(); - _ = virq_register(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) => { From 3dac98235bf417695d9240538acedc85c3dde611 Mon Sep 17 00:00:00 2001 From: Ivan Velickovic Date: Wed, 21 Aug 2024 11:28:08 +1000 Subject: [PATCH 7/9] more fixes Signed-off-by: Ivan Velickovic --- examples/virtio/blk_driver_vmm.c | 4 ++-- examples/virtio/client_vmm.c | 4 ++-- examples/zig/src/vmm.zig | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/virtio/blk_driver_vmm.c b/examples/virtio/blk_driver_vmm.c index bd9cc4b4c..b74eb229a 100644 --- a/examples/virtio/blk_driver_vmm.c +++ b/examples/virtio/blk_driver_vmm.c @@ -95,7 +95,7 @@ void init(void) } /* Initialise the virtual GIC driver */ - bool success = virq_controller_init(GUEST_BOOT_VCPU_ID); + bool success = virq_controller_init(); if (!success) { LOG_VMM_ERR("Failed to initialise emulated interrupt controller\n"); return; @@ -134,7 +134,7 @@ void init(void) #endif /* Finally start the guest */ - guest_start(GUEST_BOOT_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) diff --git a/examples/virtio/client_vmm.c b/examples/virtio/client_vmm.c index 23925b2b4..afe85ad66 100644 --- a/examples/virtio/client_vmm.c +++ b/examples/virtio/client_vmm.c @@ -103,7 +103,7 @@ void init(void) } /* Initialise the virtual GIC driver */ - bool success = virq_controller_init(GUEST_BOOT_VCPU_ID); + bool success = virq_controller_init(); if (!success) { LOG_VMM_ERR("Failed to initialise emulated interrupt controller\n"); return; @@ -140,7 +140,7 @@ void init(void) assert(success); /* Finally start the guest */ - guest_start(GUEST_BOOT_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) diff --git a/examples/zig/src/vmm.zig b/examples/zig/src/vmm.zig index b0d5cf9ec..84476d0cc 100644 --- a/examples/zig/src/vmm.zig +++ b/examples/zig/src/vmm.zig @@ -96,7 +96,7 @@ export fn init() callconv(.C) void { return; } // Initialise the virtual interrupt controller - if (!c.virq_controller_init(GUEST_BOOT_VCPU_ID)) { + if (!c.virq_controller_init()) { log.err("Failed to initialise virtual interrupt controller\n", .{}); return; } @@ -109,7 +109,7 @@ export fn init() callconv(.C) void { // handle, we ack it here. microkit.microkit_irq_ack(SERIAL_IRQ_CH); // Finally we can start the guest - if (!c.guest_start(GUEST_BOOT_VCPU_ID, kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR)) { + if (!c.guest_start(kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR)) { log.err("Failed to start guest\n", .{}); return; } From 719fd18cf94013c38498859a8756b391a84882c7 Mon Sep 17 00:00:00 2001 From: Ivan Velickovic Date: Wed, 21 Aug 2024 11:28:19 +1000 Subject: [PATCH 8/9] ci: re-enabled disabled tests Signed-off-by: Ivan Velickovic --- ci/examples.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ci/examples.sh b/ci/examples.sh index 46ed5e437..6e2d750f6 100755 --- a/ci/examples.sh +++ b/ci/examples.sh @@ -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 @@ -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" From e536750fb2edca0b3950b5b48612849f5ab6094b Mon Sep 17 00:00:00 2001 From: Ivan Velickovic Date: Wed, 21 Aug 2024 11:39:40 +1000 Subject: [PATCH 9/9] Adhering to style check Signed-off-by: Ivan Velickovic --- examples/simple/vmm.c | 46 ++-- examples/virtio-snd/client_vmm.c | 78 ++++--- examples/virtio-snd/snd_driver_vmm.c | 55 +++-- examples/virtio/blk_driver_vmm.c | 17 +- examples/virtio/client_vmm.c | 29 +-- include/libvmm/arch/aarch64/vgic/vdist.h | 12 +- src/arch/aarch64/fault.c | 278 +++++++++++++---------- src/arch/aarch64/psci.c | 167 +++++++------- src/arch/aarch64/smc.c | 72 +++--- src/arch/aarch64/tcb.c | 3 +- src/arch/aarch64/vcpu.c | 12 +- src/arch/aarch64/vgic/vgic.c | 3 +- src/arch/aarch64/vgic/vgic_v3.c | 17 +- src/arch/aarch64/virq.c | 24 +- src/guest.c | 23 +- 15 files changed, 470 insertions(+), 366 deletions(-) diff --git a/examples/simple/vmm.c b/examples/simple/vmm.c index 7fabc883d..bb0fa4a85 100644 --- a/examples/simple/vmm.c +++ b/examples/simple/vmm.c @@ -76,7 +76,8 @@ 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. @@ -84,7 +85,8 @@ static void serial_ack(size_t vcpu_id, int irq, void *cookie) { 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 */ @@ -92,15 +94,15 @@ void init(void) { 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; @@ -118,17 +120,18 @@ void init(void) { 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(SERIAL_IRQ); - if (!success) { - LOG_VMM_ERR("IRQ %d dropped\n", SERIAL_IRQ); - } - 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); } } @@ -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 diff --git a/examples/virtio-snd/client_vmm.c b/examples/virtio-snd/client_vmm.c index 95f4b2cb1..ca8445018 100644 --- a/examples/virtio-snd/client_vmm.c +++ b/examples/virtio-snd/client_vmm.c @@ -72,7 +72,8 @@ 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 */ @@ -80,15 +81,15 @@ void init(void) { 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; @@ -103,15 +104,16 @@ void init(void) { /* 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); @@ -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_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 diff --git a/examples/virtio-snd/snd_driver_vmm.c b/examples/virtio-snd/snd_driver_vmm.c index 46fc3468f..734413962 100644 --- a/examples/virtio-snd/snd_driver_vmm.c +++ b/examples/virtio-snd/snd_driver_vmm.c @@ -72,12 +72,14 @@ uintptr_t sound_data_paddr; static struct virtio_console_device virtio_console; -static void passthrough_device_ack(size_t vcpu_id, int irq, void *cookie) { +static void passthrough_device_ack(size_t vcpu_id, int irq, void *cookie) +{ microkit_channel irq_ch = (microkit_channel)(int64_t)cookie; microkit_irq_ack(irq_ch); } -static void register_passthrough_irq(int irq, microkit_channel irq_ch) { +static void register_passthrough_irq(int irq, microkit_channel irq_ch) +{ LOG_VMM("Register passthrough IRQ %d (channel: 0x%lx)\n", irq, irq_ch); assert(irq_ch < MAX_IRQ_CH); passthrough_irq_map[irq_ch] = irq; @@ -90,17 +92,19 @@ static void register_passthrough_irq(int irq, microkit_channel irq_ch) { } static bool uio_sound_fault_handler(size_t vcpu_id, - size_t offset, - size_t fsr, - seL4_UserContext *regs, - void *data) { + size_t offset, + size_t fsr, + seL4_UserContext *regs, + void *data) +{ microkit_notify(SND_CLIENT_CH); return true; } static void uio_sound_virq_ack(size_t vcpu_id, int irq, void *cookie) {} -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 */ @@ -109,15 +113,15 @@ void init(void) { 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; @@ -137,15 +141,16 @@ void init(void) { /* 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_TX_CH); + VIRTIO_CONSOLE_BASE, + VIRTIO_CONSOLE_SIZE, + VIRTIO_CONSOLE_IRQ, + &serial_rxq, &serial_txq, + SERIAL_TX_CH); assert(success); success = virq_register(GUEST_BOOT_VCPU_ID, UIO_SND_IRQ, &uio_sound_virq_ack, NULL); @@ -175,7 +180,8 @@ void init(void) { guest_start(GUEST_BOOT_VCPU_ID, kernel_pc, GUEST_DTB_VADDR, GUEST_INIT_RAM_DISK_VADDR); } -void notified(microkit_channel ch) { +void notified(microkit_channel ch) +{ bool success; switch (ch) { @@ -202,7 +208,8 @@ void notified(microkit_channel 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 diff --git a/examples/virtio/blk_driver_vmm.c b/examples/virtio/blk_driver_vmm.c index b74eb229a..8baa6f9a9 100644 --- a/examples/virtio/blk_driver_vmm.c +++ b/examples/virtio/blk_driver_vmm.c @@ -108,16 +108,16 @@ void init(void) /* 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); /* Register the UIO IRQ */ @@ -162,7 +162,8 @@ void notified(microkit_channel 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 diff --git a/examples/virtio/client_vmm.c b/examples/virtio/client_vmm.c index afe85ad66..c65542b9c 100644 --- a/examples/virtio/client_vmm.c +++ b/examples/virtio/client_vmm.c @@ -41,7 +41,6 @@ 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; - /* Virtio Console */ #define SERIAL_VIRT_TX_CH 1 #define SERIAL_VIRT_RX_CH 2 @@ -111,15 +110,16 @@ void init(void) /* 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); /* virtIO block */ /* Initialise our sDDF queues for the block device */ @@ -131,12 +131,12 @@ void init(void) /* Initialise virtIO block device */ success = virtio_mmio_blk_init(&virtio_blk, - VIRTIO_BLK_BASE, VIRTIO_BLK_SIZE, VIRTIO_BLK_IRQ, - blk_data, - BLK_DATA_SIZE, - storage_info, - &blk_queue_h, - BLK_CH); + VIRTIO_BLK_BASE, VIRTIO_BLK_SIZE, VIRTIO_BLK_IRQ, + blk_data, + BLK_DATA_SIZE, + storage_info, + &blk_queue_h, + BLK_CH); assert(success); /* Finally start the guest */ @@ -161,7 +161,8 @@ void notified(microkit_channel 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 diff --git a/include/libvmm/arch/aarch64/vgic/vdist.h b/include/libvmm/arch/aarch64/vgic/vdist.h index 71bd5f194..5c253c9ae 100644 --- a/include/libvmm/arch/aarch64/vgic/vdist.h +++ b/include/libvmm/arch/aarch64/vgic/vdist.h @@ -247,7 +247,8 @@ static void vgic_dist_clr_pending_irq(struct gic_dist_map *dist, size_t vcpu_id, // @ivanv } -static bool vgic_handle_fault_dist_read(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, seL4_UserContext *regs) +static bool vgic_handle_fault_dist_read(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, + seL4_UserContext *regs) { struct gic_dist_map *gic_dist = vgic_get_dist(vgic->registers); uint32_t reg = 0; @@ -359,7 +360,8 @@ static bool vgic_handle_fault_dist_read(size_t vcpu_id, vgic_t *vgic, uint64_t o case RANGE32(0xDE8, 0xEFC): /* Reserved [0xDE8 - 0xE00) */ /* GIC_DIST_NSACR [0xE00 - 0xF00) - Not supported */ - break; case RANGE32(GIC_DIST_SGIR, GIC_DIST_SGIR): + break; + case RANGE32(GIC_DIST_SGIR, GIC_DIST_SGIR): reg = gic_dist->sgir; break; case RANGE32(0xF04, 0xF0C): @@ -414,7 +416,8 @@ static inline void emulate_reg_write_access(seL4_UserContext *regs, uint64_t add *reg = fault_emulate(regs, *reg, addr, fsr, fault_get_data(regs, fsr)); } -static bool vgic_handle_fault_dist_write(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, seL4_UserContext *regs) +static bool vgic_handle_fault_dist_write(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, + seL4_UserContext *regs) { bool success = true; struct gic_dist_map *gic_dist = vgic_get_dist(vgic->registers); @@ -599,7 +602,7 @@ static bool vgic_handle_fault_dist_write(size_t vcpu_id, vgic_t *vgic, uint64_t #if defined(GIC_V3) // @ivanv: explain GICv3 specific stuff, and also don't use the hardcoded valuees case RANGE32(0x6100, 0x7F00): - // @ivanv revisit + // @ivanv revisit // data = fault_get_data(fault); // ZF_LOGF_IF(data, "bad dist: 0x%x 0x%x", offset, data); break; @@ -616,4 +619,3 @@ static bool vgic_handle_fault_dist_write(size_t vcpu_id, vgic_t *vgic, uint64_t return success; } - diff --git a/src/arch/aarch64/fault.c b/src/arch/aarch64/fault.c index 2362ac901..30e03ee2f 100644 --- a/src/arch/aarch64/fault.c +++ b/src/arch/aarch64/fault.c @@ -22,7 +22,8 @@ // return !CPSR_IS_THUMB(regs->spsr); // } -bool fault_advance_vcpu(size_t vcpu_id, seL4_UserContext *regs) { +bool fault_advance_vcpu(size_t vcpu_id, seL4_UserContext *regs) +{ // For now we just ignore it and continue // Assume 32-bit instruction regs->pc += 4; @@ -32,15 +33,23 @@ bool fault_advance_vcpu(size_t vcpu_id, seL4_UserContext *regs) { return (err == seL4_NoError); } -char *fault_to_string(seL4_Word fault_label) { +char *fault_to_string(seL4_Word fault_label) +{ switch (fault_label) { - case seL4_Fault_VMFault: return "virtual memory"; - case seL4_Fault_UnknownSyscall: return "unknown syscall"; - case seL4_Fault_UserException: return "user exception"; - case seL4_Fault_VGICMaintenance: return "VGIC maintenance"; - case seL4_Fault_VCPUFault: return "VCPU"; - case seL4_Fault_VPPIEvent: return "VPPI event"; - default: return "unknown fault"; + case seL4_Fault_VMFault: + return "virtual memory"; + case seL4_Fault_UnknownSyscall: + return "unknown syscall"; + case seL4_Fault_UserException: + return "user exception"; + case seL4_Fault_VGICMaintenance: + return "VGIC maintenance"; + case seL4_Fault_VCPUFault: + return "VCPU"; + case seL4_Fault_VPPIEvent: + return "VPPI event"; + default: + return "unknown fault"; } } @@ -59,7 +68,7 @@ enum fault_width { static enum fault_width fault_get_width(uint64_t fsr) { if (HSR_IS_SYNDROME_VALID(fsr) && HSR_SYNDROME_WIDTH(fsr) <= WIDTH_DOUBLEWORD) { - return (enum fault_width) (HSR_SYNDROME_WIDTH(fsr)); + return (enum fault_width)(HSR_SYNDROME_WIDTH(fsr)); } else { LOG_VMM_ERR("Received invalid FSR: 0x%lx\n", fsr); // @ivanv: reviist @@ -74,26 +83,26 @@ uint64_t fault_get_data_mask(uint64_t addr, uint64_t fsr) { uint64_t mask = 0; switch (fault_get_width(fsr)) { - case WIDTH_BYTE: - mask = 0x000000ff; - assert(!(addr & 0x0)); - break; - case WIDTH_HALFWORD: - mask = 0x0000ffff; - assert(!(addr & 0x1)); - break; - case WIDTH_WORD: - mask = 0xffffffff; - assert(!(addr & 0x3)); - break; - case WIDTH_DOUBLEWORD: - mask = ~mask; - break; - default: - LOG_VMM_ERR("unknown width: 0x%lx, from FSR: 0x%lx, addr: 0x%lx\n", - fault_get_width(fsr), fsr, addr); - assert(0); - return 0; + case WIDTH_BYTE: + mask = 0x000000ff; + assert(!(addr & 0x0)); + break; + case WIDTH_HALFWORD: + mask = 0x0000ffff; + assert(!(addr & 0x1)); + break; + case WIDTH_WORD: + mask = 0xffffffff; + assert(!(addr & 0x3)); + break; + case WIDTH_DOUBLEWORD: + mask = ~mask; + break; + default: + LOG_VMM_ERR("unknown width: 0x%lx, from FSR: 0x%lx, addr: 0x%lx\n", + fault_get_width(fsr), fsr, addr); + assert(0); + return 0; } mask <<= (addr & 0x3) * 8; return mask; @@ -108,41 +117,73 @@ seL4_Word *decode_rt(size_t reg_idx, seL4_UserContext *regs) * encodes the Syndrome Register transfer. */ switch (reg_idx) { - case 0: return ®s->x0; - case 1: return ®s->x1; - case 2: return ®s->x2; - case 3: return ®s->x3; - case 4: return ®s->x4; - case 5: return ®s->x5; - case 6: return ®s->x6; - case 7: return ®s->x7; - case 8: return ®s->x8; - case 9: return ®s->x9; - case 10: return ®s->x10; - case 11: return ®s->x11; - case 12: return ®s->x12; - case 13: return ®s->x13; - case 14: return ®s->x14; - case 15: return ®s->x15; - case 16: return ®s->x16; - case 17: return ®s->x17; - case 18: return ®s->x18; - case 19: return ®s->x19; - case 20: return ®s->x20; - case 21: return ®s->x21; - case 22: return ®s->x22; - case 23: return ®s->x23; - case 24: return ®s->x24; - case 25: return ®s->x25; - case 26: return ®s->x26; - case 27: return ®s->x27; - case 28: return ®s->x28; - case 29: return ®s->x29; - case 30: return ®s->x30; - case 31: return &wzr; - default: - LOG_VMM_ERR("failed to decode Rt, attempted to access invalid register index 0x%lx\n", reg_idx); - return NULL; + case 0: + return ®s->x0; + case 1: + return ®s->x1; + case 2: + return ®s->x2; + case 3: + return ®s->x3; + case 4: + return ®s->x4; + case 5: + return ®s->x5; + case 6: + return ®s->x6; + case 7: + return ®s->x7; + case 8: + return ®s->x8; + case 9: + return ®s->x9; + case 10: + return ®s->x10; + case 11: + return ®s->x11; + case 12: + return ®s->x12; + case 13: + return ®s->x13; + case 14: + return ®s->x14; + case 15: + return ®s->x15; + case 16: + return ®s->x16; + case 17: + return ®s->x17; + case 18: + return ®s->x18; + case 19: + return ®s->x19; + case 20: + return ®s->x20; + case 21: + return ®s->x21; + case 22: + return ®s->x22; + case 23: + return ®s->x23; + case 24: + return ®s->x24; + case 25: + return ®s->x25; + case 26: + return ®s->x26; + case 27: + return ®s->x27; + case 28: + return ®s->x28; + case 29: + return ®s->x29; + case 30: + return ®s->x30; + case 31: + return &wzr; + default: + LOG_VMM_ERR("failed to decode Rt, attempted to access invalid register index 0x%lx\n", reg_idx); + return NULL; } } @@ -195,7 +236,8 @@ uint64_t fault_emulate(seL4_UserContext *regs, uint64_t reg, uint64_t addr, uint } } -void fault_emulate_write(seL4_UserContext *regs, size_t addr, size_t fsr, size_t reg_val) { +void fault_emulate_write(seL4_UserContext *regs, size_t addr, size_t fsr, size_t reg_val) +{ // @ivanv: audit /* Get register opearand */ int rt = get_rt(fsr); @@ -219,14 +261,14 @@ bool fault_handle_vcpu_exception(size_t vcpu_id) uint32_t hsr = microkit_mr_get(seL4_VCPUFault_HSR); uint64_t hsr_ec_class = HSR_EXCEPTION_CLASS(hsr); switch (hsr_ec_class) { - case HSR_SMC_64_EXCEPTION: - return handle_smc(vcpu_id, hsr); - case HSR_WFx_EXCEPTION: - // If we get a WFI exception, we just do nothing in the VMM. - return true; - default: - LOG_VMM_ERR("unknown SMC exception, EC class: 0x%lx, HSR: 0x%lx\n", hsr_ec_class, hsr); - return false; + case HSR_SMC_64_EXCEPTION: + return handle_smc(vcpu_id, hsr); + case HSR_WFx_EXCEPTION: + // If we get a WFI exception, we just do nothing in the VMM. + return true; + default: + LOG_VMM_ERR("unknown SMC exception, EC class: 0x%lx, HSR: 0x%lx\n", hsr_ec_class, hsr); + return false; } } @@ -270,17 +312,17 @@ bool fault_handle_unknown_syscall(size_t vcpu_id) LOG_VMM("Received syscall 0x%lx\n", syscall); switch (syscall) { - case SYSCALL_PA_TO_IPA: - // @ivanv: why do we not do anything here? - // @ivanv, how to get the physical address to translate? - LOG_VMM("Received PA translation syscall\n"); - break; - case SYSCALL_NOP: - LOG_VMM("Received NOP syscall\n"); - break; - default: - LOG_VMM_ERR("Unknown syscall: syscall number: 0x%lx, PC: 0x%lx\n", syscall, fault_ip); - return false; + case SYSCALL_PA_TO_IPA: + // @ivanv: why do we not do anything here? + // @ivanv, how to get the physical address to translate? + LOG_VMM("Received PA translation syscall\n"); + break; + case SYSCALL_NOP: + LOG_VMM("Received NOP syscall\n"); + break; + default: + LOG_VMM_ERR("Unknown syscall: syscall number: 0x%lx, PC: 0x%lx\n", syscall, fault_ip); + return false; } seL4_UserContext regs; @@ -304,7 +346,8 @@ struct vm_exception_handler { struct vm_exception_handler registered_vm_exception_handlers[MAX_VM_EXCEPTION_HANDLERS]; size_t vm_exception_handler_index = 0; -bool fault_register_vm_exception_handler(uintptr_t base, size_t size, vm_exception_handler_t callback, void *data) { +bool fault_register_vm_exception_handler(uintptr_t base, size_t size, vm_exception_handler_t callback, void *data) +{ // @ivanv audit necessary here since this code was written very quickly. Other things to check such // as the region of memory is not overlapping with other regions, also should have GIC_DIST regions // use this API. @@ -327,7 +370,8 @@ bool fault_register_vm_exception_handler(uintptr_t base, size_t size, vm_excepti return true; } -static bool fault_handle_registered_vm_exceptions(size_t vcpu_id, uintptr_t addr, size_t fsr, seL4_UserContext *regs) { +static bool fault_handle_registered_vm_exceptions(size_t vcpu_id, uintptr_t addr, size_t fsr, seL4_UserContext *regs) +{ for (int i = 0; i < MAX_VM_EXCEPTION_HANDLERS; i++) { uintptr_t base = registered_vm_exception_handlers[i].base; uintptr_t end = registered_vm_exception_handlers[i].end; @@ -337,7 +381,8 @@ static bool fault_handle_registered_vm_exceptions(size_t vcpu_id, uintptr_t addr bool success = callback(vcpu_id, addr - base, fsr, regs, data); if (!success) { // @ivanv: improve error message - LOG_VMM_ERR("registered virtual memory exception handler for region [0x%lx..0x%lx) at address 0x%lx failed\n", base, end, addr); + LOG_VMM_ERR("registered virtual memory exception handler for region [0x%lx..0x%lx) at address 0x%lx failed\n", base, + end, addr); } /* Whether or not the callback actually successfully handled the * exception, we return true to say that we at least found a handler @@ -371,7 +416,7 @@ bool fault_handle_vm_exception(size_t vcpu_id) size_t is_prefetch = seL4_GetMR(seL4_VMFault_PrefetchFault); bool is_write = fault_is_write(fsr); LOG_VMM_ERR("unexpected memory fault on address: 0x%lx, FSR: 0x%lx, IP: 0x%lx, is_prefetch: %s, is_write: %s\n", - addr, fsr, ip, is_prefetch ? "true" : "false", is_write ? "true" : "false"); + addr, fsr, ip, is_prefetch ? "true" : "false", is_write ? "true" : "false"); tcb_print_regs(vcpu_id); vcpu_print_regs(vcpu_id); } else { @@ -381,36 +426,37 @@ bool fault_handle_vm_exception(size_t vcpu_id) return success; } -bool fault_handle(size_t vcpu_id, microkit_msginfo msginfo) { +bool fault_handle(size_t vcpu_id, microkit_msginfo msginfo) +{ size_t label = microkit_msginfo_get_label(msginfo); bool success = false; switch (label) { - case seL4_Fault_VMFault: - success = fault_handle_vm_exception(vcpu_id); - break; - case seL4_Fault_UnknownSyscall: - success = fault_handle_unknown_syscall(vcpu_id); - break; - case seL4_Fault_UserException: - success = fault_handle_user_exception(vcpu_id); - break; - case seL4_Fault_VGICMaintenance: - success = vgic_handle_fault_maintenance(vcpu_id); - break; - case seL4_Fault_VCPUFault: - success = fault_handle_vcpu_exception(vcpu_id); - break; - case seL4_Fault_VPPIEvent: - success = fault_handle_vppi_event(vcpu_id); - break; - default: - /* We have reached a genuinely unexpected case, stop the guest. */ - LOG_VMM_ERR("unknown fault label 0x%lx, stopping guest with ID 0x%lx\n", label, vcpu_id); - microkit_vcpu_stop(vcpu_id); - /* Dump the TCB and vCPU registers to hopefully get information as - * to what has gone wrong. */ - tcb_print_regs(vcpu_id); - vcpu_print_regs(vcpu_id); + case seL4_Fault_VMFault: + success = fault_handle_vm_exception(vcpu_id); + break; + case seL4_Fault_UnknownSyscall: + success = fault_handle_unknown_syscall(vcpu_id); + break; + case seL4_Fault_UserException: + success = fault_handle_user_exception(vcpu_id); + break; + case seL4_Fault_VGICMaintenance: + success = vgic_handle_fault_maintenance(vcpu_id); + break; + case seL4_Fault_VCPUFault: + success = fault_handle_vcpu_exception(vcpu_id); + break; + case seL4_Fault_VPPIEvent: + success = fault_handle_vppi_event(vcpu_id); + break; + default: + /* We have reached a genuinely unexpected case, stop the guest. */ + LOG_VMM_ERR("unknown fault label 0x%lx, stopping guest with ID 0x%lx\n", label, vcpu_id); + microkit_vcpu_stop(vcpu_id); + /* Dump the TCB and vCPU registers to hopefully get information as + * to what has gone wrong. */ + tcb_print_regs(vcpu_id); + vcpu_print_regs(vcpu_id); } if (!success) { diff --git a/src/arch/aarch64/psci.c b/src/arch/aarch64/psci.c index 3f9577b50..e4e4d832a 100644 --- a/src/arch/aarch64/psci.c +++ b/src/arch/aarch64/psci.c @@ -38,97 +38,98 @@ bool handle_psci(size_t vcpu_id, seL4_UserContext *regs, uint64_t fn_number, uin // @ivanv: write a note about what convention we assume, should we be checking // the convention? switch (fn_number) { - case PSCI_VERSION: { - /* We support PSCI version 1.2 */ - uint32_t version = PSCI_MAJOR_VERSION(1) | PSCI_MINOR_VERSION(2); - smc_set_return_value(regs, version); - break; - } - case PSCI_CPU_ON: { - size_t target_vcpu = smc_get_arg(regs, 1); - if (target_vcpu < GUEST_NUM_VCPUS && target_vcpu >= 0) { - /* The guest has given a valid target vCPU */ - if (vcpu_is_on(target_vcpu)) { - smc_set_return_value(regs, PSCI_ALREADY_ON); - } else { - /* We have a valid target vCPU, that is not started yet. So let's turn it on. */ - uintptr_t vcpu_entry_point = smc_get_arg(regs, 2); - size_t context_id = smc_get_arg(regs, 3); + case PSCI_VERSION: { + /* We support PSCI version 1.2 */ + uint32_t version = PSCI_MAJOR_VERSION(1) | PSCI_MINOR_VERSION(2); + smc_set_return_value(regs, version); + break; + } + case PSCI_CPU_ON: { + size_t target_vcpu = smc_get_arg(regs, 1); + if (target_vcpu < GUEST_NUM_VCPUS && target_vcpu >= 0) { + /* The guest has given a valid target vCPU */ + if (vcpu_is_on(target_vcpu)) { + smc_set_return_value(regs, PSCI_ALREADY_ON); + } else { + /* We have a valid target vCPU, that is not started yet. So let's turn it on. */ + uintptr_t vcpu_entry_point = smc_get_arg(regs, 2); + size_t context_id = smc_get_arg(regs, 3); - seL4_UserContext vcpu_regs = {0}; - vcpu_regs.x0 = context_id; - vcpu_regs.spsr = 5; // PMODE_EL1h - vcpu_regs.pc = vcpu_entry_point; + seL4_UserContext vcpu_regs = {0}; + vcpu_regs.x0 = context_id; + vcpu_regs.spsr = 5; // PMODE_EL1h + vcpu_regs.pc = vcpu_entry_point; - microkit_vcpu_arm_write_reg(target_vcpu, seL4_VCPUReg_VMPIDR_EL2, target_vcpu); + microkit_vcpu_arm_write_reg(target_vcpu, seL4_VCPUReg_VMPIDR_EL2, target_vcpu); - seL4_Error err = seL4_TCB_WriteRegisters( - BASE_VM_TCB_CAP + target_vcpu, - false, // We'll explcitly start the guest below rather than in this call - 0, // No flags - SEL4_USER_CONTEXT_SIZE, - &vcpu_regs - ); - assert(err == seL4_NoError); - if (err != seL4_NoError) { - return err; - } + seL4_Error err = seL4_TCB_WriteRegisters( + BASE_VM_TCB_CAP + target_vcpu, + false, // We'll explcitly start the guest below rather than in this call + 0, // No flags + SEL4_USER_CONTEXT_SIZE, + &vcpu_regs + ); + assert(err == seL4_NoError); + if (err != seL4_NoError) { + return err; + } - /* Now that we have started the vCPU, we can set is as turned on. */ - vcpu_set_on(target_vcpu, true); + /* Now that we have started the vCPU, we can set is as turned on. */ + vcpu_set_on(target_vcpu, true); - LOG_VMM("starting guest vCPU (0x%lx) with entry point 0x%lx, context ID: 0x%lx\n", target_vcpu, vcpu_regs.pc, context_id); - microkit_vcpu_restart(target_vcpu, vcpu_regs.pc); + LOG_VMM("starting guest vCPU (0x%lx) with entry point 0x%lx, context ID: 0x%lx\n", target_vcpu, vcpu_regs.pc, + context_id); + microkit_vcpu_restart(target_vcpu, vcpu_regs.pc); - smc_set_return_value(regs, PSCI_SUCCESS); - } - } else { - // The guest has requested to turn on a virtual CPU that does - // not exist. - smc_set_return_value(regs, PSCI_INVALID_PARAMETERS); + smc_set_return_value(regs, PSCI_SUCCESS); } - break; + } else { + // The guest has requested to turn on a virtual CPU that does + // not exist. + smc_set_return_value(regs, PSCI_INVALID_PARAMETERS); } - case PSCI_MIGRATE_INFO_TYPE: - /* - * There are multiple possible return values for MIGRATE_INFO_TYPE. - * In this case returning 2 will tell the guest that this is a - * system that does not use a "Trusted OS" as the PSCI - * specification says. - */ - smc_set_return_value(regs, 2); - break; - case PSCI_FEATURES: - // @ivanv: seems weird that we just return nothing here. - smc_set_return_value(regs, PSCI_NOT_SUPPORTED); - break; - case PSCI_SYSTEM_RESET: { - // @refactor come back to - // bool success = guest_restart(); - // if (!success) { - // LOG_VMM_ERR("Failed to restart guest\n"); - // smc_set_return_value(regs, PSCI_INTERNAL_FAILURE); - // } else { - - // * If we've successfully restarted the guest, all we want to do - // * is reply to the fault that caused us to handle the PSCI call - // * so that the guest can continue executing. We do not need to - // * advance the vCPU program counter as we typically do when - // * handling a fault since the correct PC has been set when we - // * call guest_restart(). - - // return true; - // } - break; - } - case PSCI_SYSTEM_OFF: - // @refactor, is it guaranteed that the CPU that does the vCPU request - // is the boot vcpu? - guest_stop(); - return true; - default: - LOG_VMM_ERR("Unhandled PSCI function ID 0x%lx\n", fn_number); - return false; + break; + } + case PSCI_MIGRATE_INFO_TYPE: + /* + * There are multiple possible return values for MIGRATE_INFO_TYPE. + * In this case returning 2 will tell the guest that this is a + * system that does not use a "Trusted OS" as the PSCI + * specification says. + */ + smc_set_return_value(regs, 2); + break; + case PSCI_FEATURES: + // @ivanv: seems weird that we just return nothing here. + smc_set_return_value(regs, PSCI_NOT_SUPPORTED); + break; + case PSCI_SYSTEM_RESET: { + // @refactor come back to + // bool success = guest_restart(); + // if (!success) { + // LOG_VMM_ERR("Failed to restart guest\n"); + // smc_set_return_value(regs, PSCI_INTERNAL_FAILURE); + // } else { + + // * If we've successfully restarted the guest, all we want to do + // * is reply to the fault that caused us to handle the PSCI call + // * so that the guest can continue executing. We do not need to + // * advance the vCPU program counter as we typically do when + // * handling a fault since the correct PC has been set when we + // * call guest_restart(). + + // return true; + // } + break; + } + case PSCI_SYSTEM_OFF: + // @refactor, is it guaranteed that the CPU that does the vCPU request + // is the boot vcpu? + guest_stop(); + return true; + default: + LOG_VMM_ERR("Unhandled PSCI function ID 0x%lx\n", fn_number); + return false; } bool success = fault_advance_vcpu(vcpu_id, regs); diff --git a/src/arch/aarch64/smc.c b/src/arch/aarch64/smc.c index cd305d5be..a0c8ad6f7 100644 --- a/src/arch/aarch64/smc.c +++ b/src/arch/aarch64/smc.c @@ -63,30 +63,48 @@ inline void smc_set_return_value(seL4_UserContext *u, uint64_t val) uint64_t smc_get_arg(seL4_UserContext *u, uint64_t arg) { switch (arg) { - case 1: return u->x1; - case 2: return u->x2; - case 3: return u->x3; - case 4: return u->x4; - case 5: return u->x5; - case 6: return u->x6; - default: - LOG_VMM_ERR("trying to get SMC arg: 0x%lx, SMC only has 6 argument registers\n", arg); - // @ivanv: come back to this - return 0; + case 1: + return u->x1; + case 2: + return u->x2; + case 3: + return u->x3; + case 4: + return u->x4; + case 5: + return u->x5; + case 6: + return u->x6; + default: + LOG_VMM_ERR("trying to get SMC arg: 0x%lx, SMC only has 6 argument registers\n", arg); + // @ivanv: come back to this + return 0; } } static void smc_set_arg(seL4_UserContext *u, size_t arg, size_t val) { switch (arg) { - case 1: u->x1 = val; break; - case 2: u->x2 = val; break; - case 3: u->x3 = val; break; - case 4: u->x4 = val; break; - case 5: u->x5 = val; break; - case 6: u->x6 = val; break; - default: - LOG_VMM_ERR("trying to set SMC arg: 0x%lx, with val: 0x%lx, SMC only has 6 argument registers\n", arg, val); + case 1: + u->x1 = val; + break; + case 2: + u->x2 = val; + break; + case 3: + u->x3 = val; + break; + case 4: + u->x4 = val; + break; + case 5: + u->x5 = val; + break; + case 6: + u->x6 = val; + break; + default: + LOG_VMM_ERR("trying to set SMC arg: 0x%lx, with val: 0x%lx, SMC only has 6 argument registers\n", arg, val); } } @@ -103,15 +121,15 @@ bool handle_smc(size_t vcpu_id, uint32_t hsr) smc_call_id_t service = smc_get_call(regs.x0); switch (service) { - case SMC_CALL_STD_SERVICE: - if (fn_number < PSCI_MAX) { - return handle_psci(vcpu_id, ®s, fn_number, hsr); - } - LOG_VMM_ERR("Unhandled SMC: standard service call %lu\n", fn_number); - break; - default: - LOG_VMM_ERR("Unhandled SMC: unknown value service: 0x%lx, function number: 0x%lx\n", service, fn_number); - break; + case SMC_CALL_STD_SERVICE: + if (fn_number < PSCI_MAX) { + return handle_psci(vcpu_id, ®s, fn_number, hsr); + } + LOG_VMM_ERR("Unhandled SMC: standard service call %lu\n", fn_number); + break; + default: + LOG_VMM_ERR("Unhandled SMC: unknown value service: 0x%lx, function number: 0x%lx\n", service, fn_number); + break; } return false; diff --git a/src/arch/aarch64/tcb.c b/src/arch/aarch64/tcb.c index 2357b1025..86c896db4 100644 --- a/src/arch/aarch64/tcb.c +++ b/src/arch/aarch64/tcb.c @@ -9,7 +9,8 @@ #include #include -void tcb_print_regs(size_t vcpu_id) { +void tcb_print_regs(size_t vcpu_id) +{ /* * While we are potentially doing an extra system call in order to read the * TCB registers (as the VMM may have already read the TCB registers before diff --git a/src/arch/aarch64/vcpu.c b/src/arch/aarch64/vcpu.c index 0a565611f..eb090dfeb 100644 --- a/src/arch/aarch64/vcpu.c +++ b/src/arch/aarch64/vcpu.c @@ -27,7 +27,8 @@ bool vcpu_on_state[GUEST_NUM_VCPUS]; -bool vcpu_is_on(size_t vcpu_id) { +bool vcpu_is_on(size_t vcpu_id) +{ assert(vcpu_id < GUEST_NUM_VCPUS); if (vcpu_id >= GUEST_NUM_VCPUS) { return false; @@ -36,7 +37,8 @@ bool vcpu_is_on(size_t vcpu_id) { return vcpu_on_state[vcpu_id]; } -void vcpu_set_on(size_t vcpu_id, bool on) { +void vcpu_set_on(size_t vcpu_id, bool on) +{ assert(vcpu_id < GUEST_NUM_VCPUS); if (vcpu_id >= GUEST_NUM_VCPUS) { return; @@ -45,7 +47,8 @@ void vcpu_set_on(size_t vcpu_id, bool on) { vcpu_on_state[vcpu_id] = on; } -void vcpu_reset(size_t vcpu_id) { +void vcpu_reset(size_t vcpu_id) +{ // @ivanv this is an incredible amount of system calls // Reset registers // @ivanv: double check, shouldn't we be setting sctlr? @@ -83,7 +86,8 @@ void vcpu_reset(size_t vcpu_id) { microkit_vcpu_arm_write_reg(vcpu_id, seL4_VCPUReg_CNTKCTL_EL1, 0); } -void vcpu_print_regs(size_t vcpu_id) { +void vcpu_print_regs(size_t vcpu_id) +{ // @ivanv this is an incredible amount of system calls LOG_VMM("dumping VCPU (ID 0x%lx) registers:\n", vcpu_id); /* VM control registers EL1 */ diff --git a/src/arch/aarch64/vgic/vgic.c b/src/arch/aarch64/vgic/vgic.c index debca5432..86abdd9a9 100644 --- a/src/arch/aarch64/vgic/vgic.c +++ b/src/arch/aarch64/vgic/vgic.c @@ -84,7 +84,8 @@ bool vgic_handle_fault_dist(size_t vcpu_id, size_t offset, size_t fsr, seL4_User return success; } -bool vgic_register_irq(size_t vcpu_id, int virq_num, virq_ack_fn_t ack_fn, void *ack_data) { +bool vgic_register_irq(size_t vcpu_id, int virq_num, virq_ack_fn_t ack_fn, void *ack_data) +{ assert(virq_num >= 0 && virq_num != VIRQ_INVALID); struct virq_handle virq = { .virq = virq_num, diff --git a/src/arch/aarch64/vgic/vgic_v3.c b/src/arch/aarch64/vgic/vgic_v3.c index 63efe504b..056487e9c 100644 --- a/src/arch/aarch64/vgic/vgic_v3.c +++ b/src/arch/aarch64/vgic/vgic_v3.c @@ -45,7 +45,8 @@ vgic_t vgic; -static bool vgic_handle_fault_redist_read(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, seL4_UserContext *regs) +static bool vgic_handle_fault_redist_read(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, + seL4_UserContext *regs) { struct gic_dist_map *gic_dist = vgic_get_dist(vgic->registers); struct gic_redist_map *gic_redist = vgic_get_redist(vgic->registers); @@ -96,8 +97,8 @@ static bool vgic_handle_fault_redist_read(size_t vcpu_id, vgic_t *vgic, uint64_t return true; } - -static bool vgic_handle_fault_redist_write(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, seL4_UserContext *regs) +static bool vgic_handle_fault_redist_write(size_t vcpu_id, vgic_t *vgic, uint64_t offset, uint64_t fsr, + seL4_UserContext *regs) { // @ivanv: why is this not reading from the redist? uintptr_t fault_addr = GIC_REDIST_PADDR + offset; @@ -134,8 +135,8 @@ static bool vgic_handle_fault_redist_write(size_t vcpu_id, vgic_t *vgic, uint64_ } break; case RANGE32(GICR_ICACTIVER0, GICR_ICACTIVER0): - // @ivanv: understand, this is a comment left over from kent - // TODO fix this + // @ivanv: understand, this is a comment left over from kent + // TODO fix this emulate_reg_write_access(regs, fault_addr, fsr, &gic_dist->active0[vcpu_id]); break; case RANGE32(GICR_IPRIORITYR0, GICR_IPRIORITYRN): @@ -147,7 +148,8 @@ static bool vgic_handle_fault_redist_write(size_t vcpu_id, vgic_t *vgic, uint64_ return true; } -bool vgic_handle_fault_redist(size_t vcpu_id, size_t offset, size_t fsr, seL4_UserContext *regs, void *data) { +bool vgic_handle_fault_redist(size_t vcpu_id, size_t offset, size_t fsr, seL4_UserContext *regs, void *data) +{ if (fault_is_read(fsr)) { return vgic_handle_fault_redist_read(vcpu_id, &vgic, offset, fsr, regs); } else { @@ -179,7 +181,8 @@ static void vgic_dist_reset(struct gic_dist_map *dist) dist->cidrn[3] = 0xB1; /* RO */ } -static void vgic_redist_reset(struct gic_redist_map *redist) { +static void vgic_redist_reset(struct gic_redist_map *redist) +{ // @ivanv: come back to, right now it's a global so we don't need to init the memory to zero // memset(redist, 0, sizeof(*redist)); redist->typer = 0x11; /* RO */ diff --git a/src/arch/aarch64/virq.c b/src/arch/aarch64/virq.c index 6dfa9e02e..63b4251f0 100644 --- a/src/arch/aarch64/virq.c +++ b/src/arch/aarch64/virq.c @@ -24,7 +24,8 @@ static void vppi_event_ack(size_t vcpu_id, int irq, void *cookie) static void sgi_ack(size_t vcpu_id, int irq, void *cookie) {} -bool virq_controller_init() { +bool virq_controller_init() +{ bool success; vgic_init(); @@ -71,24 +72,29 @@ bool virq_controller_init() { return true; } -bool virq_inject_vcpu(size_t vcpu_id, int irq) { +bool virq_inject_vcpu(size_t vcpu_id, int irq) +{ return vgic_inject_irq(vcpu_id, irq); } -bool virq_inject(int irq) { +bool virq_inject(int irq) +{ return vgic_inject_irq(GUEST_BOOT_VCPU_ID, irq); } -bool virq_register(size_t vcpu_id, size_t virq_num, virq_ack_fn_t ack_fn, void *ack_data) { +bool virq_register(size_t vcpu_id, size_t virq_num, virq_ack_fn_t ack_fn, void *ack_data) +{ return vgic_register_irq(vcpu_id, virq_num, ack_fn, ack_data); } -static void virq_passthrough_ack(size_t vcpu_id, int irq, void *cookie) { +static void virq_passthrough_ack(size_t vcpu_id, int irq, void *cookie) +{ /* We are down-casting to microkit_channel so must first cast to size_t */ microkit_irq_ack((microkit_channel)(size_t)cookie); } -bool virq_register_passthrough(size_t vcpu_id, size_t irq, microkit_channel irq_ch) { +bool virq_register_passthrough(size_t vcpu_id, size_t irq, microkit_channel irq_ch) +{ assert(irq_ch < MICROKIT_MAX_CHANNELS); if (irq_ch >= MICROKIT_MAX_CHANNELS) { LOG_VMM_ERR("Invalid channel number given '0x%lx' for passthrough vIRQ 0x%lx\n", irq_ch, irq); @@ -108,7 +114,8 @@ bool virq_register_passthrough(size_t vcpu_id, size_t irq, microkit_channel irq_ return true; } -bool virq_handle_passthrough(microkit_channel irq_ch) { +bool virq_handle_passthrough(microkit_channel irq_ch) +{ assert(virq_passthrough_map[irq_ch] >= 0); if (virq_passthrough_map[irq_ch] < 0) { LOG_VMM_ERR("attempted to handle invalid passthrough IRQ channel 0x%lx\n", irq_ch); @@ -117,7 +124,8 @@ bool virq_handle_passthrough(microkit_channel irq_ch) { bool success = vgic_inject_irq(GUEST_BOOT_VCPU_ID, virq_passthrough_map[irq_ch]); if (!success) { - LOG_VMM_ERR("could not inject passthrough vIRQ 0x%lx, dropped on vCPU 0x%lx\n", virq_passthrough_map[irq_ch], GUEST_BOOT_VCPU_ID); + LOG_VMM_ERR("could not inject passthrough vIRQ 0x%lx, dropped on vCPU 0x%lx\n", virq_passthrough_map[irq_ch], + GUEST_BOOT_VCPU_ID); return false; } diff --git a/src/guest.c b/src/guest.c index 8f94ac5df..d43d8a0d2 100644 --- a/src/guest.c +++ b/src/guest.c @@ -8,7 +8,8 @@ #include #include -bool guest_start(uintptr_t kernel_pc, uintptr_t dtb, uintptr_t initrd) { +bool guest_start(uintptr_t kernel_pc, uintptr_t dtb, uintptr_t initrd) +{ /* * Set the TCB registers to what the virtual machine expects to be started with. * You will note that this is currently Linux specific as we currently do not support @@ -21,19 +22,19 @@ bool guest_start(uintptr_t kernel_pc, uintptr_t dtb, uintptr_t initrd) { regs.pc = kernel_pc; /* Write out all the TCB registers */ seL4_Word err = seL4_TCB_WriteRegisters( - BASE_VM_TCB_CAP + GUEST_BOOT_VCPU_ID, - false, // We'll explcitly start the guest below rather than in this call - 0, // No flags - 4, // Writing to x0, pc, and spsr. Due to the ordering of seL4_UserContext the count must be 4. - ®s - ); + BASE_VM_TCB_CAP + GUEST_BOOT_VCPU_ID, + false, // We'll explcitly start the guest below rather than in this call + 0, // No flags + 4, // Writing to x0, pc, and spsr. Due to the ordering of seL4_UserContext the count must be 4. + ®s + ); assert(err == seL4_NoError); if (err != seL4_NoError) { LOG_VMM_ERR("Failed to write registers to boot vCPU's TCB (id is 0x%lx), error is: 0x%lx\n", GUEST_BOOT_VCPU_ID, err); return false; } LOG_VMM("starting guest at 0x%lx, DTB at 0x%lx, initial RAM disk at 0x%lx\n", - regs.pc, regs.x0, initrd); + regs.pc, regs.x0, initrd); vcpu_set_on(GUEST_BOOT_VCPU_ID, true); /* Restart the boot vCPU to the program counter of the TCB associated with it */ @@ -42,13 +43,15 @@ bool guest_start(uintptr_t kernel_pc, uintptr_t dtb, uintptr_t initrd) { return true; } -void guest_stop() { +void guest_stop() +{ LOG_VMM("Stopping guest\n"); microkit_vcpu_stop(GUEST_BOOT_VCPU_ID); LOG_VMM("Stopped guest\n"); } -bool guest_restart(uintptr_t guest_ram_vaddr, size_t guest_ram_size) { +bool guest_restart(uintptr_t guest_ram_vaddr, size_t guest_ram_size) +{ LOG_VMM("Attempting to restart guest\n"); // First, stop the guest microkit_vcpu_stop(GUEST_BOOT_VCPU_ID);