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
|
CC = clang
|
||||||
|
OBJCOPY=llvm-objcopy
|
||||||
CFLAGS = -std=c11 -O2 -g3 -Wall -Wextra --target=riscv32 -ffreestanding -nostdlib
|
CFLAGS = -std=c11 -O2 -g3 -Wall -Wextra --target=riscv32 -ffreestanding -nostdlib
|
||||||
|
|
||||||
kernel:
|
kernel: shell
|
||||||
$(CC) $(CFLAGS) -Wl,-Tkernel.ld -Wl,-Map=kernel.map -o kernel.elf kernel.c common.c
|
$(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 PAGE_SIZE 4096
|
||||||
|
|
||||||
|
#define USER_BASE 0x1000000
|
||||||
|
|
||||||
|
#define SSTATUS_SPIE (1 << 5)
|
||||||
|
|
||||||
void *memset(void *buf, char c, size_t n);
|
void *memset(void *buf, char c, size_t n);
|
||||||
void *memcpy(void *dst, const void *src, 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 =====
|
// ===== Exception handler =====
|
||||||
void kernel_entry(void) {
|
__attribute__((naked)) __attribute__((aligned(4))) void kernel_entry(void) {
|
||||||
__asm__ __volatile__("csrrw sp, sscratch, sp\n"
|
__asm__ __volatile__("csrrw sp, sscratch, sp\n"
|
||||||
|
|
||||||
"addi sp, sp, -4 * 31\n"
|
"addi sp, sp, -4 * 31\n"
|
||||||
@@ -89,9 +89,11 @@ void kernel_entry(void) {
|
|||||||
"sw s10, 4 * 28(sp)\n"
|
"sw s10, 4 * 28(sp)\n"
|
||||||
"sw s11, 4 * 29(sp)\n"
|
"sw s11, 4 * 29(sp)\n"
|
||||||
|
|
||||||
|
// Извлечение и сохранение sp в момент исключения.
|
||||||
"csrr a0, sscratch\n"
|
"csrr a0, sscratch\n"
|
||||||
"sw a0, 4 * 30(sp)\n"
|
"sw a0, 4 * 30(sp)\n"
|
||||||
|
|
||||||
|
// Сброс стека ядра.
|
||||||
"addi a0, sp, 4 * 31\n"
|
"addi a0, sp, 4 * 31\n"
|
||||||
"csrw sscratch, a0\n"
|
"csrw sscratch, a0\n"
|
||||||
|
|
||||||
@@ -182,7 +184,15 @@ __attribute__((naked)) void switch_context(uint32_t *prev_sp,
|
|||||||
"ret\n");
|
"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;
|
struct process *proc = NULL;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < PROCS_MAX; i++) {
|
for (i = 0; i < PROCS_MAX; i++) {
|
||||||
@@ -196,25 +206,36 @@ struct process *create_process(uint32_t pc) {
|
|||||||
PANIC("no free process slots");
|
PANIC("no free process slots");
|
||||||
|
|
||||||
uint32_t *sp = (uint32_t *)&proc->stack[sizeof(proc->stack)];
|
uint32_t *sp = (uint32_t *)&proc->stack[sizeof(proc->stack)];
|
||||||
*--sp = 0; // s11
|
*--sp = 0; // s11
|
||||||
*--sp = 0; // s10
|
*--sp = 0; // s10
|
||||||
*--sp = 0; // s9
|
*--sp = 0; // s9
|
||||||
*--sp = 0; // s8
|
*--sp = 0; // s8
|
||||||
*--sp = 0; // s7
|
*--sp = 0; // s7
|
||||||
*--sp = 0; // s6
|
*--sp = 0; // s6
|
||||||
*--sp = 0; // s5
|
*--sp = 0; // s5
|
||||||
*--sp = 0; // s4
|
*--sp = 0; // s4
|
||||||
*--sp = 0; // s3
|
*--sp = 0; // s3
|
||||||
*--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
|
||||||
|
|
||||||
uint32_t *page_table = (uint32_t *)alloc_pages(1);
|
uint32_t *page_table = (uint32_t *)alloc_pages(1);
|
||||||
|
|
||||||
for (paddr_t paddr = (paddr_t)__kernel_base;
|
for (paddr_t paddr = (paddr_t)__kernel_base;
|
||||||
paddr < (paddr_t)__free_ram_end; paddr += PAGE_SIZE)
|
paddr < (paddr_t)__free_ram_end; paddr += PAGE_SIZE)
|
||||||
map_page(page_table, paddr, paddr, PAGE_R | PAGE_W | PAGE_X);
|
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->pid = i + 1;
|
||||||
proc->state = PROC_RUNNABLE;
|
proc->state = PROC_RUNNABLE;
|
||||||
proc->sp = (uint32_t)sp;
|
proc->sp = (uint32_t)sp;
|
||||||
@@ -269,14 +290,15 @@ void proc_b_entry(void) {
|
|||||||
void kernel_main(void) {
|
void kernel_main(void) {
|
||||||
memset(__bss, 0, (size_t)__bss_end - (size_t)__bss);
|
memset(__bss, 0, (size_t)__bss_end - (size_t)__bss);
|
||||||
|
|
||||||
|
printf("\n\n");
|
||||||
|
|
||||||
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 = -1;
|
idle_proc->pid = -1;
|
||||||
current_proc = idle_proc;
|
current_proc = idle_proc;
|
||||||
|
|
||||||
proc_a = create_process((uint32_t)proc_a_entry);
|
create_process(_binary_shell_bin_start, (size_t)_binary_shell_bin_size);
|
||||||
proc_b = create_process((uint32_t)proc_b_entry);
|
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
PANIC("switched to idle process");
|
PANIC("switched to idle process");
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ extern char __bss[], __bss_end[];
|
|||||||
extern char __stack_top[];
|
extern char __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[];
|
||||||
|
|
||||||
// ===== SBI data ======
|
// ===== SBI data ======
|
||||||
struct sbiret {
|
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