implemented user mode
This commit is contained in:
40
kernel.c
40
kernel.c
@@ -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");
|
||||
|
2
kernel.h
2
kernel.h
@@ -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
12
shell.c
@@ -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 (;;);
|
||||
}
|
||||
|
Reference in New Issue
Block a user