From 9a1f78200a9b7f51306347b04631b08ac7d3f77b Mon Sep 17 00:00:00 2001 From: Atheria Date: Thu, 11 Sep 2025 19:04:54 +0700 Subject: [PATCH 1/2] register dump --- arch/x86_64/cpu/Cpu.c | 125 ++++++++++++++++++++++++++++ arch/x86_64/cpu/Cpu.h | 27 +++++- arch/x86_64/interrupts/Interrupts.c | 4 +- docs/ARCHITECTURE.md | 2 +- kernel/core/Kernel.c | 2 +- kernel/etc/Shell.c | 19 ++++- kernel/execf/ExecLoader.c | 4 +- kernel/execf/elf/ELFloader.c | 2 +- kernel/execf/elf/ELFloader.h | 2 +- kernel/execf/pe/PEloader.c | 2 +- kernel/sched/MLFQ.c | 5 +- kernel/sched/MLFQ.h | 4 +- 12 files changed, 182 insertions(+), 16 deletions(-) diff --git a/arch/x86_64/cpu/Cpu.c b/arch/x86_64/cpu/Cpu.c index 19be572..a27a40b 100644 --- a/arch/x86_64/cpu/Cpu.c +++ b/arch/x86_64/cpu/Cpu.c @@ -1,5 +1,6 @@ #include "Cpu.h" #include "Console.h" +#include "Io.h" #include "stdbool.h" static CpuFeatures cpu_features = {0}; @@ -74,3 +75,127 @@ void CpuInit(void) { CpuFeatures* GetCpuFeatures(void) { return &cpu_features; } + +static void DumpGP(RegistersDumpT* dump) { + // General purpose (tricky - we're using some of these!) + asm volatile ( + "movq %%rax, %0\n" + "movq %%rbx, %1\n" + "movq %%rcx, %2\n" + "movq %%rdx, %3\n" + "movq %%rsi, %4\n" + "movq %%rdi, %5\n" + "movq %%rbp, %6\n" + "movq %%rsp, %7\n" + "movq %%r8, %8\n" + "movq %%r9, %9\n" + "movq %%r10, %10\n" + "movq %%r11, %11\n" + "movq %%r12, %12\n" + "movq %%r13, %13\n" + "movq %%r14, %14\n" + "movq %%r15, %15\n" + : "=m"(dump->rax), "=m"(dump->rbx), "=m"(dump->rcx), "=m"(dump->rdx), + "=m"(dump->rsi), "=m"(dump->rdi), "=m"(dump->rbp), "=m"(dump->rsp), + "=m"(dump->r8), "=m"(dump->r9), "=m"(dump->r10), "=m"(dump->r11), + "=m"(dump->r12), "=m"(dump->r13), "=m"(dump->r14), "=m"(dump->r15) + : + : "memory" + ); + + // Get RIP (tricky - need to use a call trick) + asm volatile ( + "call 1f\n" + "1: popq %0\n" + : "=r"(dump->rip) + ); + + // Get RFLAGS + asm volatile ( + "pushfq\n" + "popq %0\n" + : "=r"(dump->rflags) + ); + + // Segment registers + asm volatile ( + "movw %%cs, %0\n" + "movw %%ds, %1\n" + "movw %%es, %2\n" + "movw %%fs, %3\n" + "movw %%gs, %4\n" + "movw %%ss, %5\n" + : "=m"(dump->cs), "=m"(dump->ds), "=m"(dump->es), + "=m"(dump->fs), "=m"(dump->gs), "=m"(dump->ss) + ); +} + +// Control registers (DANGEROUS - save/restore interrupts) +static void DumpCR(RegistersDumpT* dump) { + unsigned long flags = save_irq_flags(); + cli(); // Critical section + + asm volatile ("movq %%cr0, %0" : "=r"(dump->cr0)); + asm volatile ("movq %%cr2, %0" : "=r"(dump->cr2)); // Page fault address + asm volatile ("movq %%cr3, %0" : "=r"(dump->cr3)); // Page directory + asm volatile ("movq %%cr4, %0" : "=r"(dump->cr4)); + + // CR8 (TPR - Task Priority Register) only in x64 + asm volatile ("movq %%cr8, %0" : "=r"(dump->cr8)); + + restore_irq_flags(flags); +} + +// Debug registers +static void DumpDR(RegistersDumpT* dump) { + asm volatile ("movq %%dr0, %0" : "=r"(dump->dr0)); + asm volatile ("movq %%dr1, %0" : "=r"(dump->dr1)); + asm volatile ("movq %%dr2, %0" : "=r"(dump->dr2)); + asm volatile ("movq %%dr3, %0" : "=r"(dump->dr3)); + asm volatile ("movq %%dr6, %0" : "=r"(dump->dr6)); // Debug status + asm volatile ("movq %%dr7, %0" : "=r"(dump->dr7)); // Debug control +} + +// MSRs (Model Specific Registers) +static void DumpMSR(RegistersDumpT* dump) { + dump->efer = rdmsr(0xC0000080); // Extended features + dump->star = rdmsr(0xC0000081); // Syscall target + dump->lstar = rdmsr(0xC0000082); // Long mode syscall target + dump->cstar = rdmsr(0xC0000083); // Compat mode syscall + dump->sfmask = rdmsr(0xC0000084); // Syscall flag mask + dump->fs_base = rdmsr(0xC0000100); // FS base + dump->gs_base = rdmsr(0xC0000101); // GS base + dump->kernel_gs_base = rdmsr(0xC0000102); // Kernel GS base +} + +void DumpRegisters(RegistersDumpT* dump) { + DumpGP(dump); + DumpCR(dump); + DumpDR(dump); + DumpMSR(dump); +} + +void PrintRegisters(const RegistersDumpT* dump) { + PrintKernelF("=== VoidFrame registers dump x64 ===\n"); + PrintKernelF("RAX: 0x%016lx RBX: 0x%016lx\n", dump->rax, dump->rbx); + PrintKernelF("RCX: 0x%016lx RDX: 0x%016lx\n", dump->rcx, dump->rdx); + PrintKernelF("RSI: 0x%016lx RDI: 0x%016lx\n", dump->rsi, dump->rdi); + PrintKernelF("RBP: 0x%016lx RSP: 0x%016lx\n", dump->rbp, dump->rsp); + PrintKernelF("R8: 0x%016lx R9: 0x%016lx\n", dump->r8, dump->r9); + PrintKernelF("R10: 0x%016lx R11: 0x%016lx\n", dump->r10, dump->r11); + PrintKernelF("R12: 0x%016lx R13: 0x%016lx\n", dump->r12, dump->r13); + PrintKernelF("R14: 0x%016lx R15: 0x%016lx\n", dump->r14, dump->r15); + PrintKernelF("RIP: 0x%016lx CR0: 0x%016lx\n", dump->rip, dump->cr0); + PrintKernelF("CR2: 0x%016lx CR3: 0x%016lx\n", dump->cr2, dump->cr3); + PrintKernelF("CR4: 0x%016lx CR8: 0x%016lx\n", dump->cr4, dump->cr8); + PrintKernelF("DR0: 0x%016lx DR1: 0x%016lx\n", dump->dr0, dump->dr1); + PrintKernelF("DR2: 0x%016lx DR3: 0x%016lx\n", dump->dr2, dump->dr3); + PrintKernelF("DR6: 0x%016lx DR7: 0x%016lx\n", dump->dr6, dump->dr7); + PrintKernelF("FS: 0x%016lx GS: 0x%016lx\n", dump->fs, dump->gs); + PrintKernelF("ES: 0x%016lx DS: 0x%016lx\n", dump->es, dump->ds); + PrintKernelF("SS: 0x%016lx CS: 0x%016lx\n", dump->ss, dump->cs); + PrintKernelF("EFER: 0x%016lx STAR: 0x%016lx\n", dump->efer, dump->star); + PrintKernelF("LSTAR: 0x%016lx CSTAR: 0x%016lx\n", dump->lstar, dump->cstar); + PrintKernelF("SFMASK:0x%016lx KGSBASE:0x%016lx\n", dump->sfmask, dump->kernel_gs_base); + PrintKernelF("FSBASE:0x%016lx GSBASE:0x%016lx\n", dump->fs_base, dump->gs_base); +} diff --git a/arch/x86_64/cpu/Cpu.h b/arch/x86_64/cpu/Cpu.h index 6e44860..69d7c7c 100644 --- a/arch/x86_64/cpu/Cpu.h +++ b/arch/x86_64/cpu/Cpu.h @@ -2,7 +2,7 @@ #define CPU_H #include "stdint.h" -#include // For bool type +#include "stdbool.h" typedef struct { bool sse; @@ -23,6 +23,28 @@ typedef struct Registers { uint64_t rsp, ss; } __attribute__((packed)) Registers; +typedef struct { + // General purpose registers + uint64_t rax, rbx, rcx, rdx; + uint64_t rsi, rdi, rbp, rsp; + uint64_t r8, r9, r10, r11, r12, r13, r14, r15; + uint64_t rip, rflags; + + // Segment registers + uint16_t cs, ds, es, fs, gs, ss; + + // Control registers + uint64_t cr0, cr2, cr3, cr4; + uint64_t cr8; // Only in 64-bit mode + + // Debug registers + uint64_t dr0, dr1, dr2, dr3, dr6, dr7; + + // MSRs (selected important ones) + uint64_t efer, star, lstar, cstar, sfmask; + uint64_t fs_base, gs_base, kernel_gs_base; +} RegistersDumpT; + void CpuInit(void); CpuFeatures* GetCpuFeatures(void); @@ -36,4 +58,7 @@ static inline void __attribute__((always_inline)) delay(uint64_t cycles) { while (cycles--) __asm__ volatile ("nop"); } +void DumpRegisters(RegistersDumpT* dump); +void PrintRegisters(const RegistersDumpT* dump); + #endif // CPU_H \ No newline at end of file diff --git a/arch/x86_64/interrupts/Interrupts.c b/arch/x86_64/interrupts/Interrupts.c index 3279e37..372c1fc 100644 --- a/arch/x86_64/interrupts/Interrupts.c +++ b/arch/x86_64/interrupts/Interrupts.c @@ -71,7 +71,9 @@ asmlinkage void InterruptHandler(Registers* regs) { // Print detailed information PrintDetailedFaultInfo(&ctx, regs); - delay(100000000); + RegistersDumpT dump = {0}; + DumpRegisters(&dump); + PrintRegisters(&dump); // Still panic, but now with much more info PanicFromInterrupt(ctx.fault_reason, regs); break; diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 3d807c6..abd35db 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -203,7 +203,7 @@ typedef struct { | `context` | Stores the CPU register state (`rip`, `rsp`, etc.) when the process is not running. This is crucial for context switching. | | `priority` | The process's current priority level in the scheduler. This value can change dynamically. | | `base_priority` | The initial priority assigned at creation, used to reset a process's priority. | -| `privilege_level` | The security privilege level (`PROC_PRIV_SYSTEM` or `PROC_PRIV_USER`). | +| `privilege_level` | The security privilege level (`PROC_PRIV_SYSTEM` or `PROC_PRIV_NORM`). | | `token` | A `SecurityToken` structure used by the Astra security system to verify the process's integrity. | | `scheduler_node` | A pointer to the node that links this PCB into the scheduler's priority queues. | | `cpu_time_accumulated` | Total system ticks this process has spent running on the CPU. | diff --git a/kernel/core/Kernel.c b/kernel/core/Kernel.c index 314fe45..ad9b2ad 100644 --- a/kernel/core/Kernel.c +++ b/kernel/core/Kernel.c @@ -803,7 +803,7 @@ void KernelMainHigherHalf(void) { // Initialize core systems PXS2(); - + PrintKernelF("PCB size: %d\n", sizeof(MLFQProcessControlBlock)); PrintKernelSuccess("System: Kernel initialization complete\n"); PrintKernelSuccess("System: Initializing interrupts...\n"); diff --git a/kernel/etc/Shell.c b/kernel/etc/Shell.c index 66d1e88..bd40a14 100644 --- a/kernel/etc/Shell.c +++ b/kernel/etc/Shell.c @@ -212,6 +212,7 @@ static const HelpEntry dev_cmds[] = { {"panic ", "Trigger panic"}, {"vmemfreelist", "Show VMem free list"}, {"heapvallvl <0/1/2>", "Set heap validation level"}, + {"regdump", "Dump CPU registers"}, {"fstest", "Run filesystem tests"}, {"arptest", "Perform ARP test"}, {"setup", "Copy system files"}, @@ -367,7 +368,9 @@ static void PanicHandler(const char * args) { FaultContext ctx = {0}; ctx.fault_reason = str; PrintDetailedFaultInfo(&ctx, regs); - delay(10000000); + RegistersDumpT dump = {0}; + DumpRegisters(&dump); + PrintRegisters(&dump); PanicFromInterrupt(ctx.fault_reason, regs); } @@ -635,7 +638,7 @@ static void execveHandler(const char * args) { ResolvePath(name, full_path, 256); const ExecLoadOptions opts = { - .privilege_level = PROC_PRIV_USER, + .privilege_level = PROC_PRIV_NORM, .security_flags = 0, .max_memory = 16 * 1024 * 1024, .process_name = full_path @@ -1124,6 +1127,15 @@ static void PcBeepHandler(const char * args) { KernelFree(size_str); } +static void RegDumpHandler(const char * args) { + (void)args; + PrintKernel("Info: Dumping registers...\n"); + RegistersDumpT dump = {0}; + DumpRegisters(&dump); + PrintRegisters(&dump); + PrintKernelSuccess("Registers dumped.\n"); +} + static const ShellCommand commands[] = { {"help", HelpHandler}, {"ps", PSHandler}, @@ -1171,6 +1183,7 @@ static const ShellCommand commands[] = { {"setup", CloneSystemFiles}, {"pcbeep", PcBeepHandler}, {"6502", Entry6502}, + {"regdump", RegDumpHandler}, }; void ExecuteCommand(const char* cmd) { @@ -1180,7 +1193,7 @@ void ExecuteCommand(const char* cmd) { if (VfsIsFile(FormatS("%s/%s", DataDir, cmd_name))) { const char* full = FormatS("%s/%s", DataDir, cmd_name); const ExecLoadOptions opts = { - .privilege_level = PROC_PRIV_USER, + .privilege_level = PROC_PRIV_NORM, .security_flags = 0, .max_memory = 16 * 1024 * 1024, .process_name = full diff --git a/kernel/execf/ExecLoader.c b/kernel/execf/ExecLoader.c index 8022297..2fda1b1 100644 --- a/kernel/execf/ExecLoader.c +++ b/kernel/execf/ExecLoader.c @@ -50,7 +50,7 @@ uint32_t LoadExecutable(const char* filename, const ExecLoadOptions* options) { switch (format) { case EXEC_FORMAT_ELF64: { ElfLoadOptions elf_opts = { - .privilege_level = options ? options->privilege_level : PROC_PRIV_USER, + .privilege_level = options ? options->privilege_level : PROC_PRIV_NORM, .security_flags = options ? options->security_flags : 0, .max_memory = options ? options->max_memory : (16 * 1024 * 1024), .process_name = options ? options->process_name : filename @@ -60,7 +60,7 @@ uint32_t LoadExecutable(const char* filename, const ExecLoadOptions* options) { case EXEC_FORMAT_PE32PLUS: { PELoadOptions pe_opts = { - .privilege_level = options ? options->privilege_level : PROC_PRIV_USER, + .privilege_level = options ? options->privilege_level : PROC_PRIV_NORM, .security_flags = options ? options->security_flags : 0, .max_memory = options ? options->max_memory : (16 * 1024 * 1024), .process_name = options ? options->process_name : filename diff --git a/kernel/execf/elf/ELFloader.c b/kernel/execf/elf/ELFloader.c index 034bb9e..2622694 100644 --- a/kernel/execf/elf/ELFloader.c +++ b/kernel/execf/elf/ELFloader.c @@ -109,7 +109,7 @@ uint32_t CreateProcessFromElf(const char* filename, const ElfLoadOptions* option // Set default options if none provided ElfLoadOptions default_opts = { - .privilege_level = PROC_PRIV_USER, + .privilege_level = PROC_PRIV_NORM, .security_flags = 0, .max_memory = DEFAULT_PROCESS_MEMORY_LIMIT, .process_name = filename diff --git a/kernel/execf/elf/ELFloader.h b/kernel/execf/elf/ELFloader.h index c6211ee..89d78ec 100644 --- a/kernel/execf/elf/ELFloader.h +++ b/kernel/execf/elf/ELFloader.h @@ -64,7 +64,7 @@ typedef struct { // Enhanced API typedef struct { - uint8_t privilege_level; // PROC_PRIV_USER or PROC_PRIV_SYSTEM + uint8_t privilege_level; // PROC_PRIV_NORM or PROC_PRIV_SYSTEM uint32_t security_flags; // Additional security flags uint64_t max_memory; // Memory limit for sched const char* process_name; // Optional sched name for debugging diff --git a/kernel/execf/pe/PEloader.c b/kernel/execf/pe/PEloader.c index f3fe8f4..a6ceee6 100644 --- a/kernel/execf/pe/PEloader.c +++ b/kernel/execf/pe/PEloader.c @@ -99,7 +99,7 @@ uint32_t CreateProcessFromPE(const char* filename, const PELoadOptions* options) // Default options PELoadOptions default_opts = { - .privilege_level = PROC_PRIV_USER, + .privilege_level = PROC_PRIV_NORM, .security_flags = 0, .max_memory = DEFAULT_PROCESS_MEMORY_LIMIT, .process_name = filename diff --git a/kernel/sched/MLFQ.c b/kernel/sched/MLFQ.c index 4f09103..2fabfd1 100644 --- a/kernel/sched/MLFQ.c +++ b/kernel/sched/MLFQ.c @@ -26,6 +26,7 @@ #define offsetof(type, member) ((uint64_t)&(((type*)0)->member)) // Security flags +#define PROC_FLAG_NONE 0U #define PROC_FLAG_IMMUNE (1U << 0) #define PROC_FLAG_CRITICAL (1U << 1) #define PROC_FLAG_SUPERVISOR (1U << 3) @@ -1170,7 +1171,7 @@ static __attribute__((visibility("hidden"))) uint32_t CreateSecureProcess(const } uint32_t MLFQCreateProcess(const char * name, void (*entry_point)(void)) { - return CreateSecureProcess(name, entry_point, PROC_PRIV_USER, 0); + return CreateSecureProcess(name, entry_point, PROC_PRIV_NORM, PROC_FLAG_NONE); } void MLFQCleanupTerminatedProcess(void) { @@ -1811,7 +1812,7 @@ void VFCompositorRequestInit(const char * str) { cached_vfc_pid = 0; } PrintKernel("System: Creating VFCompositor...\n"); - uint32_t vfc_pid = CreateSecureProcess("VFCompositor", VFCompositor, PROC_PRIV_USER, 0); + uint32_t vfc_pid = CreateSecureProcess("VFCompositor", VFCompositor, PROC_PRIV_NORM, 0); if (!vfc_pid) { #ifndef VF_CONFIG_PANIC_OVERRIDE PANIC("CRITICAL: Failed to create VFCompositor process"); diff --git a/kernel/sched/MLFQ.h b/kernel/sched/MLFQ.h index 6a9302c..9b37fc5 100644 --- a/kernel/sched/MLFQ.h +++ b/kernel/sched/MLFQ.h @@ -86,8 +86,8 @@ #define FAIRNESS_BOOST_ACTUAL_INTERVAL (FAIRNESS_BOOST_INTERVAL * FAIRNESS_BOOST_MULTIPLIER) #define LOAD_BALANCE_ACTUAL_THRESHOLD (LOAD_BALANCE_THRESHOLD * LOAD_BALANCE_MULTIPLIER) -#define PROC_PRIV_SYSTEM 0 // Highest privilege (kernel services) -#define PROC_PRIV_USER 1 // User processes +#define PROC_PRIV_SYSTEM 0 // Highest privilege (kernel services) +#define PROC_PRIV_NORM 1 // Normal processes #define PROC_PRIV_RESTRICTED 2 // Restricted processes // ============================================================================= From c86e50c2b8d9eb577ce7451c358196c899fef42c Mon Sep 17 00:00:00 2001 From: Atheria Date: Fri, 12 Sep 2025 18:39:58 +0700 Subject: [PATCH 2/2] POST test included --- .github/workflows/main.yaml | 6 +-- arch/x86_64/interrupts/Interrupts.c | 6 +++ kernel/core/Kernel.c | 5 +- kernel/etc/POST.c | 77 +++++++++++++++++++++++++++++ kernel/etc/POST.h | 6 +++ kernel/etc/Shell.c | 5 +- meson.build | 7 +++ meson_options.txt | 3 +- 8 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 kernel/etc/POST.c create mode 100644 kernel/etc/POST.h diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 3182702..4a422d9 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -31,15 +31,15 @@ jobs: - name: Compile & Link run: | - meson setup build + meson setup build -Dexclude_extra_objects=true -Dautomatic_post=true ninja -C build - name: Artifact Analysis run: | - timeout 10s ninja -C build runmin || true + timeout 30s ninja -C build runmin || true grep -q "1KCSWF23Z456789" build/bootstrap.log - ! grep -i "panic\|fault\|crash\|oops\|error" build/serial.log + ! grep -i "panic\|fault\|crash\|oops\|error\|failed" build/serial.log ls -la build/voidframe.krnl test -s build/voidframe.krnl diff --git a/arch/x86_64/interrupts/Interrupts.c b/arch/x86_64/interrupts/Interrupts.c index 372c1fc..ffd5374 100644 --- a/arch/x86_64/interrupts/Interrupts.c +++ b/arch/x86_64/interrupts/Interrupts.c @@ -73,6 +73,12 @@ asmlinkage void InterruptHandler(Registers* regs) { PrintDetailedFaultInfo(&ctx, regs); RegistersDumpT dump = {0}; DumpRegisters(&dump); + // Override with fault context where applicable + dump.rip = regs->rip; + dump.cs = regs->cs; + dump.rflags = regs->rflags; + dump.rsp = regs->rsp; + dump.ss = regs->ss; PrintRegisters(&dump); // Still panic, but now with much more info PanicFromInterrupt(ctx.fault_reason, regs); diff --git a/kernel/core/Kernel.c b/kernel/core/Kernel.c index ad9b2ad..382d7d3 100644 --- a/kernel/core/Kernel.c +++ b/kernel/core/Kernel.c @@ -803,7 +803,6 @@ void KernelMainHigherHalf(void) { // Initialize core systems PXS2(); - PrintKernelF("PCB size: %d\n", sizeof(MLFQProcessControlBlock)); PrintKernelSuccess("System: Kernel initialization complete\n"); PrintKernelSuccess("System: Initializing interrupts...\n"); @@ -814,6 +813,10 @@ void KernelMainHigherHalf(void) { g_HasKernelStarted = true; +#ifdef VF_CONFIG_AUTOMATIC_POST + ExecuteCommand("post"); +#endif + sti(); while (1) { diff --git a/kernel/etc/POST.c b/kernel/etc/POST.c new file mode 100644 index 0000000..82b3754 --- /dev/null +++ b/kernel/etc/POST.c @@ -0,0 +1,77 @@ +#include "POST.h" +#include "Console.h" +#include "KernelHeap.h" +#include "PMem.h" +#include "Panic.h" +#include "Serial.h" +#include "VMem.h" +#include "stdbool.h" + +#define N 512 +void * ptrs[N] = {0}; + +uint64_t seed = 0x12345; +uint64_t rnd() { seed = seed * 6364136223846793005ULL + 1; return seed; } + +bool SerialTest() { + for (int i = 0; i < 128; i++) { + if (SerialWrite(".") < 0) return false; + } + return true; +} + +bool MemoryTest() { + for (int i = 1; i < 1000; i++) { + size_t sz = (i % 7 == 0) ? 4096 : (i % 100 + 1); + void *ptr = KernelMemoryAlloc(sz); + if (!ptr) return false; + KernelFree(ptr); + } + // + for (int i = 0; i < N; i++) ptrs[i] = KernelMemoryAlloc(128); + + // free every other block + for (int i = 0; i < N; i += 2) KernelFree(ptrs[i]); + + // re-allocate in different sizes + for (int i = 0; i < N/2; i++) { + ptrs[i] = KernelMemoryAlloc((i % 2) ? 64 : 256); + } + + for (int iter = 0; iter < 100000; iter++) { + int idx = rnd() % N; + if (ptrs[idx]) { + KernelFree(ptrs[idx]); + ptrs[idx] = NULL; + } else { + size_t sz = (rnd() % 8192) + 1; // 1–8K + ptrs[idx] = KernelMemoryAlloc(sz); + if (!ptrs[idx]) PANIC("OOM during fuzz"); + } + } + + for (uintptr_t addr = 0x400000; addr < 0x800000; addr += 0x1000) { + void* frame = AllocPage(); + VMemMap(addr, (uint64_t)frame, PAGE_PRESENT | PAGE_WRITABLE); + VMemUnmap(addr, PAGE_SIZE); + FreePage(frame); + } + + for (int i = 0; i < 1000; i++) { + size_t sz = (i % 500) + 1; + uint8_t *p = (uint8_t*)KernelMemoryAlloc(sz); + for (size_t j = 0; j < sz; j++) p[j] = (uint8_t)(i ^ j); + for (size_t j = 0; j < sz; j++) + if (p[j] != (uint8_t)(i ^ j)) PANIC("Memory corruption!"); + KernelFree(p); + } + + return true; +} + +void POSTHandler(const char * args) { + (void)args; + if (!SerialTest()) PrintKernelWarning("Serial test failed\n"); + if (!MemoryTest()) PrintKernelWarning("Memory test failed\n"); + PrintKernelSuccess("POST test passed\n"); +} \ No newline at end of file diff --git a/kernel/etc/POST.h b/kernel/etc/POST.h new file mode 100644 index 0000000..8921ff5 --- /dev/null +++ b/kernel/etc/POST.h @@ -0,0 +1,6 @@ +#ifndef VOIDFRAME_POST_H +#define VOIDFRAME_POST_H + +void POSTHandler(const char * args); + +#endif // VOIDFRAME_POST_H diff --git a/kernel/etc/Shell.c b/kernel/etc/Shell.c index bd40a14..43c6e4b 100644 --- a/kernel/etc/Shell.c +++ b/kernel/etc/Shell.c @@ -30,6 +30,7 @@ #include "stdlib.h" #include "xHCI/xHCI.h" #include "ExecLoader.h" +#include "POST.h" #define DATE __DATE__ #define TIME __TIME__ @@ -216,7 +217,8 @@ static const HelpEntry dev_cmds[] = { {"fstest", "Run filesystem tests"}, {"arptest", "Perform ARP test"}, {"setup", "Copy system files"}, - {"isocp ", "Copy from ISO to VFS"} + {"isocp ", "Copy from ISO to VFS"}, + {"post", "Perform POST"} }; static const HelpCategory help_categories[] = { @@ -1184,6 +1186,7 @@ static const ShellCommand commands[] = { {"pcbeep", PcBeepHandler}, {"6502", Entry6502}, {"regdump", RegDumpHandler}, + {"post", POSTHandler}, }; void ExecuteCommand(const char* cmd) { diff --git a/meson.build b/meson.build index 9cb50c4..1de1874 100644 --- a/meson.build +++ b/meson.build @@ -19,6 +19,7 @@ mkfs_ext2 = find_program('mkfs.ext2') qemu_system_x86_64 = find_program('qemu-system-x86_64') exclude_extra_objects = get_option('exclude_extra_objects') +automatic_post = get_option('automatic_post') # Source root src_root = './' @@ -117,6 +118,7 @@ c_sources = [ src_root + '/kernel/etc/VBEConsole.c', src_root + '/kernel/etc/Editor.c', src_root + '/kernel/etc/StringOps.c', + src_root + '/kernel/etc/POST.c', src_root + '/kernel/atomic/Atomics.c', src_root + '/kernel/ipc/Ipc.c', src_root + '/kernel/execf/elf/ELFloader.c', @@ -204,6 +206,10 @@ if exclude_extra_objects vf_config_flags += ['-DVF_CONFIG_EXCLUDE_EXTRA_OBJECTS'] endif +if automatic_post + vf_config_flags += ['-DVF_CONFIG_AUTOMATIC_POST'] +endif + cfg_flags = [] foreach flag : vf_config_flags cfg_flags += flag @@ -289,6 +295,7 @@ iso = custom_target('VoidFrame.iso', run_target('run', command : [qemu_system_x86_64.full_path(), '-cpu', 'max', + '-device', 'vmware-svga', '-enable-kvm', '-cdrom', 'VoidFrame.iso', '-debugcon', 'file:bootstrap.log', diff --git a/meson_options.txt b/meson_options.txt index 9061403..2c7f56a 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1 +1,2 @@ -option('exclude_extra_objects', type : 'boolean', value : false, description : 'Exclude extra objects from the build') # MASSIVE effect! \ No newline at end of file +option('exclude_extra_objects', type : 'boolean', value : false, description : 'Exclude extra objects from the build') # MASSIVE effect! +option('automatic_post', type : 'boolean', value : false, description : 'Perform automatic power on self-test after kernel initialization') \ No newline at end of file