Virtual memory

This commit is contained in:
2026-02-09 15:13:29 +04:00
parent 8710577d42
commit 10c456438b
4 changed files with 61 additions and 5 deletions

View File

@@ -35,6 +35,24 @@ paddr_t alloc_pages(uint32_t n) {
return paddr; 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) {
uint32_t pt_paddr = alloc_pages(1);
table1[vpn1] = ((pt_paddr / PAGE_SIZE) << 10) | PAGE_V;
}
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;
}
// ===== Exception handler ===== // ===== Exception handler =====
void kernel_entry(void) { void kernel_entry(void) {
__asm__ __volatile__("csrrw sp, sscratch, sp\n" __asm__ __volatile__("csrrw sp, sscratch, sp\n"
@@ -192,9 +210,15 @@ struct process *create_process(uint32_t pc) {
*--sp = 0; // s0 *--sp = 0; // s0
*--sp = (uint32_t)pc; // ra *--sp = (uint32_t)pc; // ra
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);
proc->pid = i + 1; proc->pid = i + 1;
proc->state = PROC_RUNNABLE; proc->state = PROC_RUNNABLE;
proc->sp = (uint32_t)sp; proc->sp = (uint32_t)sp;
proc->page_table = page_table;
return proc; return proc;
} }
void yield(void) { void yield(void) {
@@ -211,9 +235,13 @@ void yield(void) {
return; return;
__asm__ __volatile__( __asm__ __volatile__(
"sfence.vma\n"
"csrw satp, %[satp]\n"
"sfence.vma\n"
"csrw sscratch, %[sscratch]\n" "csrw sscratch, %[sscratch]\n"
: :
: [sscratch] "r"((uint32_t)&next->stack[sizeof(next->stack)])); : [satp] "r"(SATP_SV32 | ((uint32_t)next->page_table / PAGE_SIZE)),
[sscratch] "r"((uint32_t)&next->stack[sizeof(next->stack)]));
struct process *prev = current_proc; struct process *prev = current_proc;
current_proc = next; current_proc = next;
@@ -221,17 +249,35 @@ void yield(void) {
} }
// ===== ENTRY POINT ===== // ===== ENTRY POINT =====
struct process *proc_a;
struct process *proc_b;
void proc_a_entry(void) {
while (1) {
putchar('A');
yield();
}
}
void proc_b_entry(void) {
while (1) {
putchar('B');
yield();
}
}
void kernel_main(void) { void kernel_main(void) {
memset(__bss, 0, (size_t)__bss_end - (size_t)__bss); memset(__bss, 0, (size_t)__bss_end - (size_t)__bss);
printf("\n\n");
WRITE_CSR(stvec, (uint32_t)kernel_entry); WRITE_CSR(stvec, (uint32_t)kernel_entry);
idle_proc = create_process((uint32_t)NULL); idle_proc = create_process((uint32_t)NULL);
idle_proc->pid = -1; idle_proc->pid = -1;
current_proc = idle_proc; current_proc = idle_proc;
proc_a = create_process((uint32_t)proc_a_entry);
proc_b = create_process((uint32_t)proc_b_entry);
yield(); yield();
PANIC("switched to idle process"); PANIC("switched to idle process");
} }

View File

@@ -6,6 +6,7 @@
extern char __bss[], __bss_end[]; extern char __bss[], __bss_end[];
extern char __stack_top[]; extern char __stack_top[];
extern char __free_ram[], __free_ram_end[]; extern char __free_ram[], __free_ram_end[];
extern char __kernel_base[];
// ===== SBI data ====== // ===== SBI data ======
struct sbiret { struct sbiret {
@@ -58,12 +59,21 @@ struct process {
int pid; int pid;
int state; int state;
vaddr_t sp; vaddr_t sp;
uint32_t *page_table;
uint8_t stack[8192]; uint8_t stack[8192];
}; };
struct process procs[PROCS_MAX]; struct process procs[PROCS_MAX];
struct process *current_proc; struct process *current_proc;
struct process *idle_proc; struct process *idle_proc;
// ===== Memory allocation =====
#define SATP_SV32 (1u << 31)
#define PAGE_V (1 << 0)
#define PAGE_R (1 << 1)
#define PAGE_W (1 << 2)
#define PAGE_X (1 << 3)
#define PAGE_U (1 << 4)
// ===== Macros ===== // ===== Macros =====
#define READ_CSR(reg) \ #define READ_CSR(reg) \
({ \ ({ \

View File

@@ -2,6 +2,7 @@ ENTRY(boot)
SECTIONS { SECTIONS {
. = 0x80200000; . = 0x80200000;
__kernel_base = .;
.text :{ .text :{
KEEP(*(.text.boot)); KEEP(*(.text.boot));

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
set -xue set -xue
make kernel make kernel && qemu-system-riscv32 -machine virt -bios default -nographic -serial mon:stdio --no-reboot -kernel kernel.elf
qemu-system-riscv32 -machine virt -bios default -nographic -serial mon:stdio --no-reboot -kernel kernel.elf