universalisos/kernel/src/arch/riscv/kernel_riscv.cpp

113 lines
3.6 KiB
C++

/*
* UniversalisOS RISC-V Hypervisor Entry Point
*
* Minimal boot path for the RISC-V port. Initialises the hypervisor
* foundation (CPU detection, UART, trap handling, timer, PLIC, page
* tables, scheduler, memory API, HM) and runs self-tests before halting.
*/
#include "uart.h"
#include "exceptions.h"
#include "context_switch.h"
#include "cpu.h"
#include "page_table.h"
#include "mem_pikeos.h"
#include "timer.h"
#include "plic.h"
#include "vm.h"
#include "guest_boot.h"
#include "sched_pikeos.h"
#include "hm.h"
#include "csr.h"
#include <uos/uos.h>
static void test_task(void)
{
universalisos::uart::puts("[SCHED] test task running\r\n");
riscv_sched_task_yield();
universalisos::uart::puts("[SCHED] test task returned\r\n");
while (1) {
riscv_sched_task_yield();
}
}
extern "C" void kernel_main(uint32_t hart_id, uint64_t dtb_pa)
{
(void)dtb_pa;
universalisos::uart::init();
universalisos::uart::puts("\r\n");
universalisos::uart::puts("UniversalisOS RISC-V 64-bit hypervisor booted.\r\n");
universalisos::uart::puts("=== PikeOS 5.0 parity foundation ===\r\n");
riscv_cpu_init(hart_id);
riscv_cpu_print_info();
riscv_hm_init();
riscv_exceptions_init();
riscv_timer_init();
riscv_plic_init();
universalisos::uart::puts("\r\n=== RISC-V Subsystem Tests ===\r\n");
/* Sv39 page-table smoke test */
paddr_t root = riscv_pt_alloc_frame();
if (root) {
int rc = riscv_pt_map_page(root, 0x40000000ULL, 0x80000000ULL,
PTE_PAGE_FLAGS, false);
if (rc == 0) {
universalisos::uart::puts("[OK] Sv39 page table map\r\n");
} else {
universalisos::uart::puts("[FAIL] Sv39 page table map\r\n");
}
riscv_pt_free_frame(root);
}
/* PikeOS-style address-space smoke test */
riscv_aspace_t as;
if (riscv_aspace_create(1, 0x40000000ULL, 0x40000000ULL, &as) == 0) {
if (riscv_aspace_map(&as, 0x40000000ULL, 0x80000000ULL,
0x10000ULL, RISCV_M_READ | RISCV_M_WRITE | RISCV_M_EXEC) == 0) {
universalisos::uart::puts("[OK] p4map-style aspace map\r\n");
}
riscv_aspace_destroy(&as);
}
/* Guest VM creation smoke test */
if (riscv_vm_create(0, 0x90000000ULL, 0x10000ULL) == 0) {
universalisos::uart::puts("[OK] Guest VM create\r\n");
int vcpu = riscv_vcpu_create(0, 0, hart_id);
if (vcpu >= 0) {
universalisos::uart::puts("[OK] vCPU create\r\n");
riscv_vcpu_reset(vcpu, 0x90000000ULL, 0);
}
riscv_vm_destroy(0);
} else {
universalisos::uart::puts("[FAIL] Guest VM create\r\n");
}
/* PikeOS-style scheduler smoke test */
riscv_sched_init(1000); /* 1 ms tick */
riscv_sched_schema_create(0, 10000); /* 10 ms major frame */
riscv_sched_window_add(0, 1, 5000, 4500, 0, 0, 0);
riscv_sched_window_add(0, 2, 5000, 4500, 0, 0, 1);
static uint8_t test_stack[4096] __attribute__((aligned(16)));
int tid = riscv_sched_task_create(1, 1, 16, 0, 0, 1000,
(void*)((uintptr_t)test_stack + sizeof(test_stack)),
test_task);
if (tid >= 0) {
universalisos::uart::puts("[OK] PikeOS-style scheduler task create\r\n");
}
/* Timer smoke test */
uint64_t now = riscv_timer_get_time();
riscv_timer_set(now + 1000000ULL);
universalisos::uart::puts("[OK] SBI timer armed\r\n");
riscv_print_exception_stats();
universalisos::uart::puts("\r\nHalting.\r\n");
while (1) {
__asm__ volatile("wfi");
}
}