Multiprocessing

This commit is contained in:
2026-02-09 12:52:53 +04:00
parent 6043cc0d5c
commit 8710577d42
4 changed files with 168 additions and 17 deletions

View File

@@ -26,10 +26,12 @@ typedef uint32_t vaddr_t;
#define va_end __builtin_va_end #define va_end __builtin_va_end
#define va_arg __builtin_va_arg #define va_arg __builtin_va_arg
#define PAGE_SIZE 4096
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);
char *strcpy(char *dst, const char *src); char *strcpy(char *dst, const char *src);
int strcmp(const char *s1, const char *s2); int strcmp(const char *s1, const char *s2);
void printf(const char *fmt, ...); void printf(const char *fmt, ...);

View File

@@ -1,5 +1,6 @@
#include "kernel.h" #include "kernel.h"
// ===== SBI CALLS =====
struct sbiret sbi_call(long arg0, long arg1, long arg2, long arg3, long arg4, struct sbiret sbi_call(long arg0, long arg1, long arg2, long arg3, long arg4,
long arg5, long fid, long eid) { long arg5, long fid, long eid) {
register long a0 __asm__("a0") = arg0; register long a0 __asm__("a0") = arg0;
@@ -21,8 +22,23 @@ struct sbiret sbi_call(long arg0, long arg1, long arg2, long arg3, long arg4,
void putchar(char ch) { sbi_call(ch, 0, 0, 0, 0, 0, 0, 1); } void putchar(char ch) { sbi_call(ch, 0, 0, 0, 0, 0, 0, 1); }
__attribute__((naked)) __attribute__((aligned(4))) void kernel_entry(void) { // ===== MEMORY ALLOCATION =====
__asm__ __volatile__("csrw sscratch, sp\n" paddr_t alloc_pages(uint32_t n) {
static paddr_t next_paddr = (paddr_t)__free_ram;
paddr_t paddr = next_paddr;
next_paddr += n * PAGE_SIZE;
if (next_paddr > (paddr_t)__free_ram_end)
PANIC("out of memory");
memset((void *)paddr, 0, n * PAGE_SIZE);
return paddr;
}
// ===== Exception handler =====
void kernel_entry(void) {
__asm__ __volatile__("csrrw sp, sscratch, sp\n"
"addi sp, sp, -4 * 31\n" "addi sp, sp, -4 * 31\n"
"sw ra, 4 * 0(sp)\n" "sw ra, 4 * 0(sp)\n"
"sw gp, 4 * 1(sp)\n" "sw gp, 4 * 1(sp)\n"
@@ -56,7 +72,10 @@ __attribute__((naked)) __attribute__((aligned(4))) void kernel_entry(void) {
"sw s11, 4 * 29(sp)\n" "sw s11, 4 * 29(sp)\n"
"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"
"csrw sscratch, a0\n"
"mv a0, sp\n" "mv a0, sp\n"
"call handle_trap\n" "call handle_trap\n"
@@ -104,14 +123,117 @@ void handle_trap(struct trap_frame *f) {
user_pc); user_pc);
} }
// ===== Multiprocessing =====
__attribute__((naked)) void switch_context(uint32_t *prev_sp,
uint32_t *next_sp) {
__asm__ __volatile__("addi sp, sp, -13 * 4\n"
"sw ra, 0 * 4(sp)\n"
"sw s0, 1 * 4(sp)\n"
"sw s1, 2 * 4(sp)\n"
"sw s2, 3 * 4(sp)\n"
"sw s3, 4 * 4(sp)\n"
"sw s4, 5 * 4(sp)\n"
"sw s5, 6 * 4(sp)\n"
"sw s6, 7 * 4(sp)\n"
"sw s7, 8 * 4(sp)\n"
"sw s8, 9 * 4(sp)\n"
"sw s9, 10 * 4(sp)\n"
"sw s10, 11 * 4(sp)\n"
"sw s11, 12 * 4(sp)\n"
"sw sp, (a0)\n"
"lw sp, (a1)\n"
"lw ra, 0 * 4(sp)\n"
"lw s0, 1 * 4(sp)\n"
"lw s1, 2 * 4(sp)\n"
"lw s2, 3 * 4(sp)\n"
"lw s3, 4 * 4(sp)\n"
"lw s4, 5 * 4(sp)\n"
"lw s5, 6 * 4(sp)\n"
"lw s6, 7 * 4(sp)\n"
"lw s7, 8 * 4(sp)\n"
"lw s8, 9 * 4(sp)\n"
"lw s9, 10 * 4(sp)\n"
"lw s10, 11 * 4(sp)\n"
"lw s11, 12 * 4(sp)\n"
"addi sp, sp, 13 * 4\n"
"ret\n");
}
struct process *create_process(uint32_t pc) {
struct process *proc = NULL;
int i;
for (i = 0; i < PROCS_MAX; i++) {
if (procs[i].state == PROC_UNUSED) {
proc = &procs[i];
break;
}
}
if (!proc)
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
proc->pid = i + 1;
proc->state = PROC_RUNNABLE;
proc->sp = (uint32_t)sp;
return proc;
}
void yield(void) {
struct process *next = idle_proc;
for (int i = 0; i < PROCS_MAX; i++) {
struct process *proc = &procs[(current_proc->pid + i) % PROCS_MAX];
if (proc->state == PROC_RUNNABLE && proc->pid > 0) {
next = proc;
break;
}
}
if (next == current_proc)
return;
__asm__ __volatile__(
"csrw sscratch, %[sscratch]\n"
:
: [sscratch] "r"((uint32_t)&next->stack[sizeof(next->stack)]));
struct process *prev = current_proc;
current_proc = next;
switch_context(&prev->sp, &next->sp);
}
// ===== ENTRY POINT =====
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);
WRITE_CSR(stvec, (uint32_t)kernel_entry); printf("\n\n");
__asm__ __volatile__("unimp");
PANIC("booted!"); WRITE_CSR(stvec, (uint32_t)kernel_entry);
printf("unreachable here!\n");
idle_proc = create_process((uint32_t)NULL);
idle_proc->pid = -1;
current_proc = idle_proc;
yield();
PANIC("switched to idle process");
} }
__attribute__((section(".text.boot"))) __attribute__((naked)) void boot(void) { __attribute__((section(".text.boot"))) __attribute__((naked)) void boot(void) {

View File

@@ -2,20 +2,18 @@
#include "common.h" #include "common.h"
extern char __bss[], __bss_end[], __stack_top[]; // ===== Linker data =====
extern char __bss[], __bss_end[];
extern char __stack_top[];
extern char __free_ram[], __free_ram_end[];
// ===== SBI data ======
struct sbiret { struct sbiret {
long error; long error;
long value; long value;
}; };
#define PANIC(fmt, ...) \ // ===== Exception handler =====
do { \
printf("PANIC: %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
while (1) { \
} \
} while (0)
struct trap_frame { struct trap_frame {
uint32_t ra; uint32_t ra;
uint32_t gp; uint32_t gp;
@@ -50,6 +48,23 @@ struct trap_frame {
uint32_t sp; uint32_t sp;
} __attribute__((packed)); } __attribute__((packed));
// ===== Multiprocessing =====
#define PROCS_MAX 8
#define PROC_UNUSED 0
#define PROC_RUNNABLE 1
struct process {
int pid;
int state;
vaddr_t sp;
uint8_t stack[8192];
};
struct process procs[PROCS_MAX];
struct process *current_proc;
struct process *idle_proc;
// ===== Macros =====
#define READ_CSR(reg) \ #define READ_CSR(reg) \
({ \ ({ \
unsigned long __tmp; \ unsigned long __tmp; \
@@ -62,3 +77,10 @@ struct trap_frame {
uint32_t __tmp = (value); \ uint32_t __tmp = (value); \
__asm__ __volatile__("csrw " #reg ", %0" ::"r"(__tmp)); \ __asm__ __volatile__("csrw " #reg ", %0" ::"r"(__tmp)); \
} while (0) } while (0)
#define PANIC(fmt, ...) \
do { \
printf("PANIC: %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
while (1) { \
} \
} while (0)

View File

@@ -25,4 +25,9 @@ SECTIONS {
. = ALIGN(4); . = ALIGN(4);
. += 128 * 1024; /* 128KB */ . += 128 * 1024; /* 128KB */
__stack_top = .; __stack_top = .;
}
. = ALIGN(4096);
__free_ram = .;
. += 64 * 1024 * 1024; /* 64MB */
__free_ram_end = .;
}