mirror of
https://github.com/StepanovPlaton/OSin1000Lines.git
synced 2026-04-03 12:20:46 +04:00
User mode
This commit is contained in:
10
src/Makefile
10
src/Makefile
@@ -1,5 +1,11 @@
|
||||
CC = clang
|
||||
OBJCOPY=llvm-objcopy
|
||||
CFLAGS = -std=c11 -O2 -g3 -Wall -Wextra --target=riscv32 -ffreestanding -nostdlib
|
||||
|
||||
kernel:
|
||||
$(CC) $(CFLAGS) -Wl,-Tkernel.ld -Wl,-Map=kernel.map -o kernel.elf kernel.c common.c
|
||||
kernel: shell
|
||||
$(CC) $(CFLAGS) -Wl,-Tkernel.ld -Wl,-Map=kernel.map -o kernel.elf kernel.c common.c shell.bin.o
|
||||
|
||||
shell:
|
||||
$(CC) $(CFLAGS) -Wl,-Tuser.ld -Wl,-Map=shell.map -o shell.elf shell.c user.c common.c
|
||||
$(OBJCOPY) --set-section-flags .bss=alloc,contents -O binary shell.elf shell.bin
|
||||
$(OBJCOPY) -Ibinary -Oelf32-littleriscv shell.bin shell.bin.o
|
||||
|
||||
@@ -28,6 +28,10 @@ typedef uint32_t vaddr_t;
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
|
||||
#define USER_BASE 0x1000000
|
||||
|
||||
#define SSTATUS_SPIE (1 << 5)
|
||||
|
||||
void *memset(void *buf, char c, size_t n);
|
||||
void *memcpy(void *dst, const void *src, size_t n);
|
||||
|
||||
|
||||
58
src/kernel.c
58
src/kernel.c
@@ -54,7 +54,7 @@ void map_page(uint32_t *table1, uint32_t vaddr, paddr_t paddr, uint32_t flags) {
|
||||
}
|
||||
|
||||
// ===== Exception handler =====
|
||||
void kernel_entry(void) {
|
||||
__attribute__((naked)) __attribute__((aligned(4))) void kernel_entry(void) {
|
||||
__asm__ __volatile__("csrrw sp, sscratch, sp\n"
|
||||
|
||||
"addi sp, sp, -4 * 31\n"
|
||||
@@ -89,9 +89,11 @@ void kernel_entry(void) {
|
||||
"sw s10, 4 * 28(sp)\n"
|
||||
"sw s11, 4 * 29(sp)\n"
|
||||
|
||||
// Извлечение и сохранение sp в момент исключения.
|
||||
"csrr a0, sscratch\n"
|
||||
"sw a0, 4 * 30(sp)\n"
|
||||
|
||||
// Сброс стека ядра.
|
||||
"addi a0, sp, 4 * 31\n"
|
||||
"csrw sscratch, a0\n"
|
||||
|
||||
@@ -182,7 +184,15 @@ __attribute__((naked)) void switch_context(uint32_t *prev_sp,
|
||||
"ret\n");
|
||||
}
|
||||
|
||||
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) {
|
||||
struct process *proc = NULL;
|
||||
int i;
|
||||
for (i = 0; i < PROCS_MAX; i++) {
|
||||
@@ -196,25 +206,36 @@ struct process *create_process(uint32_t pc) {
|
||||
PANIC("no free process slots");
|
||||
|
||||
uint32_t *sp = (uint32_t *)&proc->stack[sizeof(proc->stack)];
|
||||
*--sp = 0; // s11
|
||||
*--sp = 0; // s10
|
||||
*--sp = 0; // s9
|
||||
*--sp = 0; // s8
|
||||
*--sp = 0; // s7
|
||||
*--sp = 0; // s6
|
||||
*--sp = 0; // s5
|
||||
*--sp = 0; // s4
|
||||
*--sp = 0; // s3
|
||||
*--sp = 0; // s2
|
||||
*--sp = 0; // s1
|
||||
*--sp = 0; // s0
|
||||
*--sp = (uint32_t)pc; // ra
|
||||
*--sp = 0; // s11
|
||||
*--sp = 0; // s10
|
||||
*--sp = 0; // s9
|
||||
*--sp = 0; // s8
|
||||
*--sp = 0; // s7
|
||||
*--sp = 0; // s6
|
||||
*--sp = 0; // s5
|
||||
*--sp = 0; // s4
|
||||
*--sp = 0; // s3
|
||||
*--sp = 0; // s2
|
||||
*--sp = 0; // s1
|
||||
*--sp = 0; // s0
|
||||
*--sp = (uint32_t)user_entry; // 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);
|
||||
|
||||
for (uint32_t off = 0; off < image_size; off += PAGE_SIZE) {
|
||||
paddr_t page = alloc_pages(1);
|
||||
|
||||
size_t remaining = image_size - off;
|
||||
size_t copy_size = PAGE_SIZE <= remaining ? PAGE_SIZE : remaining;
|
||||
|
||||
memcpy((void *)page, image + off, copy_size);
|
||||
map_page(page_table, USER_BASE + off, page,
|
||||
PAGE_U | PAGE_R | PAGE_W | PAGE_X);
|
||||
}
|
||||
proc->pid = i + 1;
|
||||
proc->state = PROC_RUNNABLE;
|
||||
proc->sp = (uint32_t)sp;
|
||||
@@ -269,14 +290,15 @@ void proc_b_entry(void) {
|
||||
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 = create_process(NULL, 0);
|
||||
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);
|
||||
create_process(_binary_shell_bin_start, (size_t)_binary_shell_bin_size);
|
||||
|
||||
yield();
|
||||
PANIC("switched to idle process");
|
||||
|
||||
@@ -7,6 +7,7 @@ extern char __bss[], __bss_end[];
|
||||
extern char __stack_top[];
|
||||
extern char __free_ram[], __free_ram_end[];
|
||||
extern char __kernel_base[];
|
||||
extern char _binary_shell_bin_start[], _binary_shell_bin_size[];
|
||||
|
||||
// ===== SBI data ======
|
||||
struct sbiret {
|
||||
|
||||
7
src/shell.c
Normal file
7
src/shell.c
Normal file
@@ -0,0 +1,7 @@
|
||||
#include "user.h"
|
||||
|
||||
void main(void) {
|
||||
*((volatile int *)0x80200000) = 0x1234; // new!
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
18
src/user.c
Normal file
18
src/user.c
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "user.h"
|
||||
|
||||
extern char __stack_top[];
|
||||
|
||||
__attribute__((noreturn)) void exit(void) {
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
||||
void putchar(char c) { /* Доделать*/ }
|
||||
|
||||
__attribute__((section(".text.start"))) __attribute__((naked)) void
|
||||
start(void) {
|
||||
__asm__ __volatile__(
|
||||
"mv sp, %[stack_top] \n"
|
||||
"call main \n"
|
||||
"call exit \n" ::[stack_top] "r"(__stack_top));
|
||||
}
|
||||
6
src/user.h
Normal file
6
src/user.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
__attribute__((noreturn)) void exit(void);
|
||||
void putchar(char ch);
|
||||
28
src/user.ld
Normal file
28
src/user.ld
Normal file
@@ -0,0 +1,28 @@
|
||||
ENTRY(start)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x1000000;
|
||||
|
||||
.text :{
|
||||
KEEP(*(.text.start));
|
||||
*(.text .text.*);
|
||||
}
|
||||
|
||||
.rodata : ALIGN(4) {
|
||||
*(.rodata .rodata.*);
|
||||
}
|
||||
|
||||
.data : ALIGN(4) {
|
||||
*(.data .data.*);
|
||||
}
|
||||
|
||||
.bss : ALIGN(4) {
|
||||
*(.bss .bss.* .sbss .sbss.*);
|
||||
|
||||
. = ALIGN(16);
|
||||
. += 64 * 1024; /* 64KB */
|
||||
__stack_top = .;
|
||||
|
||||
ASSERT(. < 0x1800000, "too large executable");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user