mirror of
https://github.com/StepanovPlaton/OSin1000Lines.git
synced 2026-04-03 12:20:46 +04:00
Virtual memory
This commit is contained in:
52
src/kernel.c
52
src/kernel.c
@@ -35,6 +35,24 @@ paddr_t alloc_pages(uint32_t n) {
|
||||
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 =====
|
||||
void kernel_entry(void) {
|
||||
__asm__ __volatile__("csrrw sp, sscratch, sp\n"
|
||||
@@ -192,9 +210,15 @@ struct process *create_process(uint32_t pc) {
|
||||
*--sp = 0; // s0
|
||||
*--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->state = PROC_RUNNABLE;
|
||||
proc->sp = (uint32_t)sp;
|
||||
proc->page_table = page_table;
|
||||
return proc;
|
||||
}
|
||||
void yield(void) {
|
||||
@@ -211,9 +235,13 @@ void yield(void) {
|
||||
return;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"sfence.vma\n"
|
||||
"csrw satp, %[satp]\n"
|
||||
"sfence.vma\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;
|
||||
current_proc = next;
|
||||
@@ -221,17 +249,35 @@ void yield(void) {
|
||||
}
|
||||
|
||||
// ===== 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) {
|
||||
memset(__bss, 0, (size_t)__bss_end - (size_t)__bss);
|
||||
|
||||
printf("\n\n");
|
||||
|
||||
WRITE_CSR(stvec, (uint32_t)kernel_entry);
|
||||
|
||||
idle_proc = create_process((uint32_t)NULL);
|
||||
idle_proc->pid = -1;
|
||||
current_proc = idle_proc;
|
||||
|
||||
proc_a = create_process((uint32_t)proc_a_entry);
|
||||
proc_b = create_process((uint32_t)proc_b_entry);
|
||||
|
||||
yield();
|
||||
PANIC("switched to idle process");
|
||||
}
|
||||
|
||||
10
src/kernel.h
10
src/kernel.h
@@ -6,6 +6,7 @@
|
||||
extern char __bss[], __bss_end[];
|
||||
extern char __stack_top[];
|
||||
extern char __free_ram[], __free_ram_end[];
|
||||
extern char __kernel_base[];
|
||||
|
||||
// ===== SBI data ======
|
||||
struct sbiret {
|
||||
@@ -58,12 +59,21 @@ struct process {
|
||||
int pid;
|
||||
int state;
|
||||
vaddr_t sp;
|
||||
uint32_t *page_table;
|
||||
uint8_t stack[8192];
|
||||
};
|
||||
struct process procs[PROCS_MAX];
|
||||
struct process *current_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 =====
|
||||
#define READ_CSR(reg) \
|
||||
({ \
|
||||
|
||||
@@ -2,6 +2,7 @@ ENTRY(boot)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x80200000;
|
||||
__kernel_base = .;
|
||||
|
||||
.text :{
|
||||
KEEP(*(.text.boot));
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#!/bin/bash
|
||||
set -xue
|
||||
|
||||
make kernel
|
||||
qemu-system-riscv32 -machine virt -bios default -nographic -serial mon:stdio --no-reboot -kernel kernel.elf
|
||||
make kernel && qemu-system-riscv32 -machine virt -bios default -nographic -serial mon:stdio --no-reboot -kernel kernel.elf
|
||||
|
||||
Reference in New Issue
Block a user