Skip to content
Snippets Groups Projects
Commit d309cb2c authored by adrian.spycher's avatar adrian.spycher
Browse files

feat!: refactore code

parent ba113a08
No related branches found
No related tags found
No related merge requests found
......@@ -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 ---
// ...
......
#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:
}
#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_
......@@ -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);
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment