From f742d1fe9b74b9a2f17902f3d5185f6c2ea1dfb2 Mon Sep 17 00:00:00 2001 From: Amoelle Date: Sun, 27 Jul 2025 11:35:47 +0300 Subject: [PATCH] map kernel memory area --- kernel.c | 72 ++++++++++++++++++++++++++++++------------------------- kernel.h | 17 +++++++------ kernel.ld | 1 + 3 files changed, 50 insertions(+), 40 deletions(-) diff --git a/kernel.c b/kernel.c index 95561fe..79e3c58 100644 --- a/kernel.c +++ b/kernel.c @@ -1,9 +1,41 @@ #include "kernel.h" #include "common.h" -#include extern char __bss[], __bss_end[], __stack_top[]; extern char __free_ram[], __free_ram_end[]; +extern char __kernel_base[]; + +paddr_t alloc_pages(uint32_t n) { + static paddr_t next_paddr = (paddr_t) __free_ram; + paddr_t paddr = next_paddr; + next_paddr += n * PAGE_SIZE; + + if (next_paddr > (paddr_t) __free_ram_end) + PANIC("Out ow memowy~ :(("); + + memset((void *) paddr, 0, n * PAGE_SIZE); + return paddr; +} + +void map_page(uint32_t *table1, uint32_t vaddr, paddr_t paddr, uint32_t flags) { + if (!is_aligned(vaddr, PAGE_SIZE)) + PANIC("Unaligned vaddr %x", vaddr); + + if (!is_aligned(paddr, PAGE_SIZE)) + PANIC("Unaligned paddr %x", paddr); + + uint32_t vpn1 = (vaddr >> 22) & 0x3ff; + if ((table1[vpn1] & PAGE_V) == 0) { + // Create the first level page + uint32_t pt_paddr = alloc_pages(1); + table1[vpn1] = ((pt_paddr / PAGE_SIZE) << 10) | PAGE_V; + } + + // Set the second level page table entry to map the physical page + uint32_t vpn0 = (vaddr >> 12) & 0x3ff; + uint32_t *table0 = (uint32_t *) ((table1[vpn1] >> 10) * PAGE_SIZE); + table0[vpn0] = ((paddr / PAGE_SIZE) << 10) | flags | PAGE_V; +} struct sbiret sbi_call(long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long fid, long eid) { @@ -24,18 +56,6 @@ struct sbiret sbi_call(long arg0, long arg1, long arg2, long arg3, long arg4, return (struct sbiret){.error = a0, .value = a1}; } -paddr_t alloc_pages(uint32_t n) { - static paddr_t next_paddr = (paddr_t) __free_ram; - paddr_t paddr = next_paddr; - next_paddr += n * PAGE_SIZE; - - if (next_paddr > (paddr_t) __free_ram_end) - PANIC("Out ow memowy~ :(("); - - memset((void *) paddr, 0, n * PAGE_SIZE); - return paddr; -} - void putchar(char ch) { sbi_call(ch, 0, 0, 0, 0, 0, 0, 1 /* Console Putchar */); } @@ -204,11 +224,17 @@ struct process *create_process(uint32_t pc) { *--sp = 0; // s0 *--sp = (uint32_t) pc; // ra + // Map kernel pages + uint32_t *page_table = (uint32_t *) alloc_pages(1); + for (paddr_t paddr = (paddr_t) __kernel_base; paddr < (paddr_t) __free_ram_end; paddr += PAGE_SIZE) { + map_page(page_table, paddr, paddr, PAGE_R | PAGE_W | PAGE_X); + } // Initialize fields proc->pid = i + 1; proc->state = PROC_RUNNABLE; proc->sp = (uint32_t) sp; + proc->page_table = page_table; return proc; } @@ -266,26 +292,6 @@ void proc_b_entry(void) { } } -void map_page(uint32_t *table1, uint32_t vaddr, paddr_t paddr, uint32_t flags) { - if (!is_aligned(vaddr, PAGE_SIZE)) - PANIC("Unaligned vaddr %x", vaddr); - - if (!is_aligned(paddr, PAGE_SIZE)) - PANIC("Unaligned paddr %x", paddr); - - uint32_t vpn1 = (vaddr >> 22) & 0x3ff; - if ((table1[vpn1] & PAGE_V) == 0) { - // Create the first level page - uint32_t pt_paddr = alloc_pages(1); - table1[vpn1] = ((pt_paddr / PAGE_SIZE) << 10) | PAGE_V; - } - - // Set the second level page table entry to map the physical page - uint32_t vpn0 = (vaddr >> 12) & 0x3ff; - uint32_t *table0 = (uint32_t *) ((table1[vpn1] >> 10) * PAGE_SIZE); - table0[vpn0] = ((paddr / PAGE_SIZE) << 10) | flags | PAGE_V; -} - void kernel_main(void) { // printf("\n\nHello %s\n", "friend :3"); // printf("60 + 9 = %d, %x\n", 60 + 9, 0x1234abcd); diff --git a/kernel.h b/kernel.h index 44ed420..02a6147 100644 --- a/kernel.h +++ b/kernel.h @@ -64,16 +64,19 @@ struct trap_frame { #define PROC_UNUSED 0 // Unused processes control structure #define PROC_RUNNABLE 1 // Runnable proccess -struct process { - int pid; // ID of a process - int state; // State of the process: either PROC_UNUSED or PROC_RUNNABLE - vaddr_t sp; // Stack pointer - uint8_t stack[8192]; // Kernel stack -}; - +// Page table #define SATP_SV32 (1u << 32) #define PAGE_V (1 << 0) // "Valid" bit (entry is allowed) #define PAGE_R (1 << 1) // Readable #define PAGE_W (1 << 2) // Writable #define PAGE_X (1 << 3) // Executable #define PAGE_U (1 << 4) // User (accessible in user mode) + +struct process { + int pid; // ID of a process + int state; // State of the process: either PROC_UNUSED or PROC_RUNNABLE + vaddr_t sp; // Stack pointer + uint32_t *page_table; + uint8_t stack[8192]; // Kernel stack +}; + diff --git a/kernel.ld b/kernel.ld index d20d134..5dd450a 100644 --- a/kernel.ld +++ b/kernel.ld @@ -2,6 +2,7 @@ ENTRY(BOOT) SECTIONS { . = 0x80200000; + __kernel_base = .; .text :{ KEEP(*(.text.boot));