User mode

This commit is contained in:
2026-02-15 15:34:42 +04:00
parent 10c456438b
commit c94866f688
8 changed files with 112 additions and 20 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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");

View File

@@ -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
View File

@@ -0,0 +1,7 @@
#include "user.h"
void main(void) {
*((volatile int *)0x80200000) = 0x1234; // new!
for (;;)
;
}

18
src/user.c Normal file
View 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
View 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
View 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");
}
}