implemented user mode

This commit is contained in:
2025-07-29 11:31:47 +03:00
parent 2a6266566a
commit bc9fa4eac7
4 changed files with 51 additions and 7 deletions

View File

@@ -4,6 +4,7 @@
extern char __bss[], __bss_end[], __stack_top[];
extern char __free_ram[], __free_ram_end[];
extern char __kernel_base[];
extern char _binary_shell_bin_start[], _binary_shell_bin_size[];
struct process procs[PROCS_MAX];
struct process *current_proc;
@@ -190,7 +191,19 @@ __attribute__((naked)) void switch_context(uint32_t *prev_sp,
);
}
struct process *create_process(uint32_t pc) {
__attribute__((naked)) void user_entry(void) {
__asm__ __volatile__(
"csrw sepc, %[sepc] \n"
"csrw sstatus, %[sstatus] \n"
"sret \n"
:
: [sepc] "r" (USER_BASE),
[sstatus] "r" (SSTATUS_SPIE)
);
}
struct process *create_process(const void *image, size_t image_size) {
// Find an unused proccess control structure
struct process *proc = NULL;
int i;
@@ -218,7 +231,7 @@ struct process *create_process(uint32_t pc) {
*--sp = 0; // s2
*--sp = 0; // s1
*--sp = 0; // s0
*--sp = (uint32_t) pc; // ra
*--sp = (uint32_t) user_entry; // ra (changed)
// Map kernel pages
uint32_t *page_table = (uint32_t *) alloc_pages(1);
@@ -226,6 +239,20 @@ struct process *create_process(uint32_t pc) {
map_page(page_table, paddr, paddr, PAGE_R | PAGE_W | PAGE_X);
}
// Map user pages
for (uint32_t off = 0; off < image_size; off += PAGE_SIZE) {
paddr_t page = alloc_pages(1);
// Case where data to be copied is smaller than the page size
size_t remaining = image_size - off;
size_t copy_size = PAGE_SIZE <= remaining ? PAGE_SIZE : remaining;
// Fill and map the page
memcpy((void *) page, image + off, copy_size);
map_page(page_table, USER_BASE + off, page,
PAGE_U | PAGE_R | PAGE_W | PAGE_X);
}
// Initialize fields
proc->pid = i + 1;
proc->state = PROC_RUNNABLE;
@@ -304,7 +331,7 @@ void kernel_main(void) {
WRITE_CSR(stvec, (uint32_t) kernel_entry);
idle_proc = create_process((uint32_t) NULL);
idle_proc = create_process(NULL, 0);
idle_proc->pid = 0; // idle
current_proc = idle_proc;
@@ -313,8 +340,11 @@ void kernel_main(void) {
// printf("alloc_pages test paddr0=%x\n", paddr0);
// printf("alloc_pages test paddr1=%x\n", paddr1);
proc_a = create_process((uint32_t) proc_a_entry);
proc_b = create_process((uint32_t) proc_b_entry);
// proc_a = create_process((uint32_t) proc_a_entry);
// proc_b = create_process((uint32_t) proc_b_entry);
// NEW
create_process(_binary_shell_bin_start, (size_t) _binary_shell_bin_size);
yield();
PANIC("Switched to idle process");

View File

@@ -10,6 +10,8 @@
#define PAGE_W (1 << 2) // Writable
#define PAGE_X (1 << 3) // Executable
#define PAGE_U (1 << 4) // User (accessible in user mode)
#define USER_BASE 0x1000000
#define SSTATUS_SPIE (1 << 5)
struct process {
int pid; // ID of a process

12
shell.c
View File

@@ -1,5 +1,17 @@
#include "user.h"
void main(void) {
// *((volatile int *) 0x80200000) = 0x1234;
// printf(" ___ ___ ___ ___ ___ ___ ___ \\n");
// printf(" /\\ \\ /\\__\\ /\\ \\ /\\ \\ /\\__\\ /\\ \\ /\\ \\ \\n");
// printf(" /::\\ \\ /::| | /::\\ \\ /::\\ \\ /:/ / /::\\ \\ /::\\ \\ \\n");
// printf(" /:/\\:\\ \\ /:|:| | /:/\\:\\ \\ /:/\\:\\ \\ /:/ / /:/\\:\\ \\ /:/\\ \\ \\ \\n");
// printf(" /::\\~\\:\\ \\ /:/|:|__|__ /:/ \\:\\ \\ /::\\~\\:\\ \\ /:/ / /:/ \\:\\ \\ _\\:\\~\\ \\ \\ \\n");
// printf(" /:/\\:\\ \\:\\__\\ /:/ |::::\\__\\ /:/__/ \\:\\__\\ /:/\\:\\ \\:\\__\\ /:/__/ /:/__/ \\:\\__\\ /\\ \\:\\ \\ \\__\\\\n");
// printf(" \\/__\\:\\/:/ / \\/__/~~/:/ / \\:\\ \\ /:/ / \\:\\~\\:\\ \\/__/ \\:\\ \\ \\:\\ \\ /:/ / \\:\\ \\:\\ \\/__/\\n");
// printf(" \\::/ / /:/ / \\:\\ /:/ / \\:\\ \\:\\__\\ \\:\\ \\ \\:\\ /:/ / \\:\\ \\:\\__\\ \\n");
// printf(" /:/ / /:/ / \\:\\/:/ / \\:\\ \\/__/ \\:\\ \\ \\:\\/:/ / \\:\\/:/ / \\n");
// printf(" /:/ / /:/ / \\::/ / \\:\\__\\ \\:\\__\\ \\::/ / \\::/ / \\n");
// printf(" \\/__/ \\/__/ \\/__/ \\/__/ \\/__/ \\/__/ \\/__/ \\n");
for (;;);
}

View File

@@ -1,7 +1,7 @@
ENTRY(start)
SECTIONS {
. = 0x10000000;
. = 0x1000000;
/* machine code */
.text :{