From d309cb2c0ff06d0b6cbe5da4e472e562fb508266 Mon Sep 17 00:00:00 2001 From: "adrian.spycher" <adrian.spycher@etu.hesge.ch> Date: Sun, 20 Oct 2024 18:46:05 +0200 Subject: [PATCH] feat!: refactore code --- shared/hypercall_params.h | 16 +++- vmm/handler.c | 151 ++++++++++++++++++++++++++++++++++++++ vmm/handler.h | 45 ++++++++++++ vmm/vmm_main.c | 57 +++----------- 4 files changed, 219 insertions(+), 50 deletions(-) create mode 100644 vmm/handler.c create mode 100644 vmm/handler.h diff --git a/shared/hypercall_params.h b/shared/hypercall_params.h index c804f80..6916bc6 100644 --- a/shared/hypercall_params.h +++ b/shared/hypercall_params.h @@ -5,8 +5,14 @@ // --- DEFINE --- -#define HYPERCALL_SHARED_ADDR 0xC0000000 -#define HYPERCALL_BUFF_SIZE 4096 +#define HYPERCALL_PMIO_ADDR 0xABBA + +#define HYPERCALL_SHARED_ADDR 0xC0000000 +#define HYPERCALL_BUFF_SIZE 4096 + +#define HYPERCALL_CODE_CONSOLE 1 +#define HYPERCALL_CODE_TIMER 2 +#define HYPERCALL_CODE_GFX_INIT 3 // --- SHARED STRUCT --- @@ -20,6 +26,12 @@ typedef struct { uint32_t us; // delay in micro-seconds } __attribute__((packed)) hyper_timer_sleep_params_t; +typedef struct { + + uint32_t width; // horizontal resolution in pixels + uint32_t height; // vertical resolution in pixels +} __attribute__((packed)) hyper_init_gfx_params_t; + // --- FUNCTION --- // ... diff --git a/vmm/handler.c b/vmm/handler.c new file mode 100644 index 0000000..00b058b --- /dev/null +++ b/vmm/handler.c @@ -0,0 +1,151 @@ +#include "handler.h" + +#include <err.h> +#include <stdio.h> +#include <stdint.h> +#include <unistd.h> + +#include "shared/hypercall_params.h" + +// --- DEFINE --- + +state_handler_t const STATE_HANDLERS[] = { + + [KVM_EXIT_HLT] = handle_halt, + [KVM_EXIT_IO] = handle_pmio, + [KVM_EXIT_MMIO] = handle_mmio, +}; + +static state_t const STATE_TIMER[] = { + + { OP_WRITE_EQUAL, 0x43, 20, 2, NULL }, + { OP_WRITE_EQUAL, 0x40, 0, 4, NULL }, + { OP_WRITE_EQUAL, 0, 0, 0, NULL }, +}; + +static state_t const STATE_VGA[] = { + + { OP_WRITE_EQUAL, 0x3C2, 0x67, 1, NULL }, + { OP_WRITE_EQUAL, 0x3C4, 0xF02, 2, NULL }, + { OP_WRITE_EQUAL, 0x3CE, 0x506, 2, NULL }, + { OP_WRITE_EQUAL, 0x3DA, 0x80, 1, NULL }, + { OP_WRITE_EQUAL, 0x3C0, 0x20, 1, NULL }, + { OP_WRITE_EQUAL, 0x3C5, 0x0F, 1, NULL }, + { OP_WRITE_EQUAL, 0, 0, 0, NULL }, +}; + +// --- STATIC FUNCTION --- + +static uint32_t retrieve_value(uint8_t *addr, uint8_t size) { + + uint32_t value; + + switch (size) { + + case 1: + value = *(uint8_t *)addr; + break; + + case 2: + value = *(uint16_t *)addr; + break; + + case 4: + value = *(uint32_t *)addr; + break; + + default: + errx(1, "Unsupported size trying to retrieve value.\n"); + break; + } + + return value; +} + +// --- FUNCTION --- + +// - VMM EXIT REASON HANDLER - + +void handle_halt(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem) { + + // printf("KVM_EXIT_HLT\n"); +} + +void handle_pmio(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem) { + + if (run->io.direction == KVM_EXIT_IO_OUT) { + + uint32_t value = retrieve_value((uint8_t *)run + run->io.data_offset, run->io.size); + printf("PMIO guest write: \tsize=%d \tport=0x%x \tvalue=%d\n", run->io.size * 8, run->io.port, value); + + switch (run->io.port) { + + case HYPERCALL_PMIO_ADDR: + handle_hypercall(value, shared_buf, mem); + break; + + case 0x43: + break; + + case 0x40: + break; + } + } +} + +void handle_mmio(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem) { + + if (run->mmio.is_write) { + + uint32_t value = retrieve_value((uint8_t *)run->mmio.data, run->mmio.len); + printf("MMIO guest write: \taddr=0x%llx \tlen=%d \tvalue=%d\n", run->mmio.phys_addr, run->mmio.len * 8, value); + } +} + +// - HYPERCALL HANDLER - + +void handle_hypercall(uint32_t code, uint8_t *shared_buf, uint8_t *mem) { + + switch (code) { + + case HYPERCALL_CODE_CONSOLE: + handle_hypercall_console(shared_buf, mem); + break; + + case HYPERCALL_CODE_TIMER: + handle_hypercall_timer(shared_buf); + break; + + case HYPERCALL_CODE_GFX_INIT: + handle_hypercall_gfx_init(shared_buf); + break; + + default: + // TODO: + break; + } +} + +void handle_hypercall_console(uint8_t *shared_buf, uint8_t *mem) { + + hyper_virtual_console_params_t *p_consol = (hyper_virtual_console_params_t *)shared_buf; + + printf("hypercall : sending a message...\n"); + printf("%s\n", p_consol->msg + mem); +} + +void handle_hypercall_timer(uint8_t *shared_buf) { + + hyper_timer_sleep_params_t *p_timer = (hyper_timer_sleep_params_t *)shared_buf; + + printf("hypercall : setting up a %dus timer...\n", p_timer->us); + sleep(p_timer->us / 1e6); +} + +void handle_hypercall_gfx_init(uint8_t *shared_buf) { + + hyper_init_gfx_params_t *p_init_gfx = (hyper_init_gfx_params_t *)shared_buf; + + printf("hypercall : initializing gfx...\n"); + // TODO: +} diff --git a/vmm/handler.h b/vmm/handler.h new file mode 100644 index 0000000..29ada07 --- /dev/null +++ b/vmm/handler.h @@ -0,0 +1,45 @@ +#define _STATES_H_ +#ifdef _STATES_H_ + +#include <stdint.h> +#include <linux/kvm.h> + +// --- DEFINE --- + +typedef enum { + + OP_WRITE_EQUAL, + OP_READ_INJECT, + OP_EMUL_END, +} operation_t; + +typedef void (*state_handler_t)(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem); + +typedef struct { + + operation_t op; // the operation to perform + uint32_t addr; // the address written to/read from + uint32_t value; // the expected written value or value to inject + uint8_t size; // the size of the operation (8, 16 or 32 bits) + void (*callback)(); // custom function that would be executed at the end of the state +} state_t; + +extern state_handler_t const STATE_HANDLERS[]; + +// --- FUNCITON --- + +void handle_halt(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem); + +void handle_pmio(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem); + +void handle_mmio(struct kvm_run *run, uint8_t *shared_buf, uint8_t *mem); + +void handle_hypercall(uint32_t code, uint8_t *shared_buf, uint8_t *mem); + +void handle_hypercall_console(uint8_t *shared_buf, uint8_t *mem); + +void handle_hypercall_timer(uint8_t *shared_buf); + +void handle_hypercall_gfx_init(uint8_t *shared_buf); + +#endif // !_STATES_H_ diff --git a/vmm/vmm_main.c b/vmm/vmm_main.c index efcdbae..2660c38 100644 --- a/vmm/vmm_main.c +++ b/vmm/vmm_main.c @@ -12,7 +12,7 @@ #include <sys/stat.h> #include <sys/types.h> -#include "states.h" +#include "handler.h" #include "shared/hypercall_params.h" // -- DEFINE -- @@ -96,8 +96,7 @@ int main(int argc, char* argv[]) if (bytes_read < 0) err(1, "Error reading guestOS binary file"); // Check if all bytes were read - if (bytes_read != st.st_size) - err(1, "Error: Only %ld of %ld bytes read from file\n", bytes_read, st.st_size); + if (bytes_read != st.st_size) err(1, "Error: Only %ld of %ld bytes read from file\n", bytes_read, st.st_size); // Close the file descriptor close(binfd); @@ -142,56 +141,18 @@ int main(int argc, char* argv[]) bool done = false; while (!done) { - if (ioctl(vcpufd, KVM_RUN, NULL) == -1) err(1, "KVM_RUN"); - - // handle VM exits (blocking call) - switch (run->exit_reason) { - - case KVM_EXIT_HLT: // "halt" CPU instruction - - puts("KVM_EXIT_HLT"); - break; - - case KVM_EXIT_IO: // Encountered a PMIO VMexit - - if (run->io.direction == KVM_EXIT_IO_OUT) { - - uint8_t *addr = (uint8_t *)run + run->io.data_offset; - uint8_t code = *(uint8_t *)addr; - switch (code) { - - case 1: // console - - hyper_virtual_console_params_t *p_consol = (hyper_virtual_console_params_t *)shared_buf; - printf("%s\n", p_consol->msg + mem); - break; - - case 2: // timer - - hyper_timer_sleep_params_t *p_timer = (hyper_timer_sleep_params_t *)shared_buf; - printf("waiting %dus\n", p_timer->us); - sleep(p_timer->us / 1e6); - done = true; - break; - } - } + if (ioctl(vcpufd, KVM_RUN, NULL) == -1) err(1, "KVM_RUN"); - break; + state_handler_t handler = STATE_HANDLERS[run->exit_reason]; - case KVM_EXIT_MMIO: // Encountered a MMIO VMexit + if (handler) { - // !TODO! - break; + handler(run, shared_buf, mem); + } + else { - // handle errors - case KVM_EXIT_SHUTDOWN : - case KVM_EXIT_FAIL_ENTRY : - case KVM_EXIT_INTERNAL_ERROR : - default : - errx(1, "exit_reason = 0x%x", run->exit_reason); - done = true; - break; + errx(1, "exit_reason = 0x%x", run->exit_reason); } } } -- GitLab