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 __bss[], __bss_end[], __stack_top[];
|
||||||
extern char __free_ram[], __free_ram_end[];
|
extern char __free_ram[], __free_ram_end[];
|
||||||
extern char __kernel_base[];
|
extern char __kernel_base[];
|
||||||
|
extern char _binary_shell_bin_start[], _binary_shell_bin_size[];
|
||||||
|
|
||||||
struct process procs[PROCS_MAX];
|
struct process procs[PROCS_MAX];
|
||||||
struct process *current_proc;
|
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
|
// Find an unused proccess control structure
|
||||||
struct process *proc = NULL;
|
struct process *proc = NULL;
|
||||||
int i;
|
int i;
|
||||||
@@ -218,7 +231,7 @@ struct process *create_process(uint32_t pc) {
|
|||||||
*--sp = 0; // s2
|
*--sp = 0; // s2
|
||||||
*--sp = 0; // s1
|
*--sp = 0; // s1
|
||||||
*--sp = 0; // s0
|
*--sp = 0; // s0
|
||||||
*--sp = (uint32_t) pc; // ra
|
*--sp = (uint32_t) user_entry; // ra (changed)
|
||||||
|
|
||||||
// Map kernel pages
|
// Map kernel pages
|
||||||
uint32_t *page_table = (uint32_t *) alloc_pages(1);
|
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_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
|
// Initialize fields
|
||||||
proc->pid = i + 1;
|
proc->pid = i + 1;
|
||||||
proc->state = PROC_RUNNABLE;
|
proc->state = PROC_RUNNABLE;
|
||||||
@@ -304,7 +331,7 @@ void kernel_main(void) {
|
|||||||
|
|
||||||
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(NULL, 0);
|
||||||
idle_proc->pid = 0; // idle
|
idle_proc->pid = 0; // idle
|
||||||
current_proc = idle_proc;
|
current_proc = idle_proc;
|
||||||
|
|
||||||
@@ -313,8 +340,11 @@ void kernel_main(void) {
|
|||||||
// printf("alloc_pages test paddr0=%x\n", paddr0);
|
// printf("alloc_pages test paddr0=%x\n", paddr0);
|
||||||
// printf("alloc_pages test paddr1=%x\n", paddr1);
|
// printf("alloc_pages test paddr1=%x\n", paddr1);
|
||||||
|
|
||||||
proc_a = create_process((uint32_t) proc_a_entry);
|
// proc_a = create_process((uint32_t) proc_a_entry);
|
||||||
proc_b = create_process((uint32_t) proc_b_entry);
|
// proc_b = create_process((uint32_t) proc_b_entry);
|
||||||
|
|
||||||
|
// NEW
|
||||||
|
create_process(_binary_shell_bin_start, (size_t) _binary_shell_bin_size);
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
PANIC("Switched to idle process");
|
PANIC("Switched to idle process");
|
||||||
|
2
kernel.h
2
kernel.h
@@ -10,6 +10,8 @@
|
|||||||
#define PAGE_W (1 << 2) // Writable
|
#define PAGE_W (1 << 2) // Writable
|
||||||
#define PAGE_X (1 << 3) // Executable
|
#define PAGE_X (1 << 3) // Executable
|
||||||
#define PAGE_U (1 << 4) // User (accessible in user mode)
|
#define PAGE_U (1 << 4) // User (accessible in user mode)
|
||||||
|
#define USER_BASE 0x1000000
|
||||||
|
#define SSTATUS_SPIE (1 << 5)
|
||||||
|
|
||||||
struct process {
|
struct process {
|
||||||
int pid; // ID of a process
|
int pid; // ID of a process
|
||||||
|
14
shell.c
14
shell.c
@@ -1,5 +1,17 @@
|
|||||||
#include "user.h"
|
#include "user.h"
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
for(;;);
|
// *((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