Run user process.

This commit is contained in:
Alexander Myltsev 2022-12-14 09:00:32 +03:00
parent 529ba03e50
commit dd9f5786c2
10 changed files with 131 additions and 30 deletions

View File

@ -48,19 +48,19 @@ debug-nox: image.bin
-ex "continue"
fs.img: kernel.bin tools/mkfs user/false
tools/mkfs $@ $<
tools/mkfs $@ $< user/false
LDFLAGS=-m elf_i386
user/%: user/%.o user/crt.o
$(LD) $(LDFLAGS) -o $@ -Ttext 0x101000 $^
$(LD) $(LDFLAGS) -o $@ -Ttext 0x1000 $^
image.bin: mbr.bin fs.img
cat $^ >$@
kernel.bin: kernel.o console.o drivers/vga.o drivers/keyboard.o \
drivers/ata.o cpu/vectors.o cpu/idt.o cpu/gdt.o drivers/uart.o \
fs/fs.o lib/mem.o lib/string.o
fs/fs.o lib/mem.o lib/string.o proc.o cpu/swtch.o
$(LD) $(LDFLAGS) -o $@ -Ttext 0x1000 $^
%.o: %.c

View File

@ -11,6 +11,8 @@
#define DPL_USER 3
#define FL_IF 0x00000200
#define SEG_KCODE 1
#define SEG_KDATA 2
#define SEG_UCODE 3
@ -23,6 +25,7 @@
(0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
#define USER_BASE 0x400000 // 4 MB
#define USER_STACK_BASE 0xf00000 // 15 MB
#define KERN_STACK_BASE 0x90000
#ifndef __ASSEMBLER__

View File

@ -42,27 +42,27 @@ void init_idt() {
}
const char * const exception_messages[] = {
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"No Coprocessor",
[0] = "Division By Zero",
[1] = "Debug",
[2] = "Non Maskable Interrupt",
[3] = "Breakpoint",
[4] = "Into Detected Overflow",
[5] = "Out of Bounds",
[6] = "Invalid Opcode",
[7] = "No Coprocessor",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",
[8] = "Double Fault",
[9] = "Coprocessor Segment Overrun",
[10] = "Bad TSS",
[11] = "Segment Not Present",
[12] = "Stack Fault",
[13] = "General Protection Fault",
[14] = "Page Fault",
[15] = "Unknown Interrupt",
"Coprocessor Fault",
"Alignment Check",
"Machine Check",
[16] = "Coprocessor Fault",
[17] = "Alignment Check",
[18] = "Machine Check",
};
#define ARRLEN(a) (sizeof(a) / sizeof(a[0]))

20
cpu/swtch.S Normal file
View File

@ -0,0 +1,20 @@
// swtch(void** oldstack, void* newstack)
.global swtch
swtch:
mov 4(%esp), %eax // eax holds "oldstack"
mov 8(%esp), %ecx
push %ebx
push %ebp
push %esi
push %edi
mov %esp, (%eax) // save stack ptr to "oldstack"
mov %ecx, %esp // use "newstack" as stack ptr
pop %edi
pop %esi
pop %ebp
pop %ebx
ret

View File

@ -1,3 +1,5 @@
.global trapret
alltraps:
# Build trap frame.
pushl %ds
@ -13,7 +15,9 @@ alltraps:
pushl %esp
call trap
add $4, %esp
// execution falls through to trapret
trapret:
popal
popl %gs
popl %fs

View File

@ -10,6 +10,8 @@ asm(".asciz \"kernel start\\n\"");
#include "drivers/uart.h"
#include "fs/fs.h"
#include "lib/string.h"
#include "proc.h"
void _start() {
load_gdt();
@ -28,20 +30,19 @@ void _start() {
} else {
printk("failed to read file\n");
}
printk("\n> ");
while (1) {
if (kbd_buf_size > 0 && kbd_buf[kbd_buf_size-1] == '\n') {
if (!strncmp("halt\n", kbd_buf, kbd_buf_size)) {
qemu_shutdown();
} else if (!strncmp("run ", kbd_buf, kbd_buf_size)) {
} else if (!strncmp("run ", kbd_buf, 4)) {
kbd_buf[kbd_buf_size-1] = '\0';
// const char* cmd = kbd_buf + 4;
// run_elf(cmd);
const char* cmd = kbd_buf + 4;
run_elf(cmd);
} else {
printk("unknown command, try: halt\n> ");
printk("unknown command, try: halt");
}
kbd_buf_size = 0;
printk("\n> ");
}
asm("hlt");
}

View File

@ -26,3 +26,10 @@ int strncmp(const char* s1, const char* s2, size_t size) {
}
return (unsigned char)(*s1) - (unsigned char)(*s2);
}
void memset(void* b, char c, size_t len) {
char* p = b;
for (size_t i = 0; i < len; ++i) {
p[i] = c;
}
}

View File

@ -4,3 +4,4 @@ typedef unsigned size_t;
void kmemmove(char* dst, char* src, size_t size);
int strncmp(const char* s1, const char* s2, size_t size);
void memset(void* b, char c, size_t len);

62
proc.c Normal file
View File

@ -0,0 +1,62 @@
#include "elf.h"
#include "proc.h"
#include "fs/fs.h"
#include "cpu/gdt.h"
#include "cpu/isr.h"
#include "lib/mem.h"
#include "lib/string.h"
#include "console.h"
struct context {
// matches the behavior of swtch()
uint32_t edi, esi, ebp, ebx;
uint32_t eip; // return address for swtch()
};
struct kstack {
uint32_t space[400];
struct context context;
registers_t trapframe;
};
struct vm {
void *kernel_thread;
void *user_thread;
struct kstack *user_kstack;
} *vm;
void trapret();
void swtch(void** oldstack, void* newstack);
void run_elf(const char* name) {
if (!vm) {
vm = kmalloc(sizeof(struct vm));
vm->user_kstack = kmalloc(sizeof(struct kstack));
}
if (read_file(name, (void*)USER_BASE, 100 << 20) <= 0) {
printk(name);
printk(": file not found\n");
return;
}
Elf32_Ehdr *hdr = (void*)USER_BASE;
struct kstack *u = vm->user_kstack;
memset(u, 0, sizeof(*u));
u->context.eip = (uint32_t)trapret;
registers_t *tf = &u->trapframe;
tf->eip = hdr->e_entry;
tf->cs = (SEG_UCODE << 3) | DPL_USER;
tf->ds = (SEG_UDATA << 3) | DPL_USER;
tf->es = tf->ds;
tf->fs = tf->ds;
tf->gs = tf->ds;
tf->ss = tf->ds;
tf->eflags = FL_IF;
tf->useresp = USER_STACK_BASE;
// initialization done, now switch to the process
swtch(&vm->kernel_thread, &u->context);
// process has finished
}

3
proc.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
void run_elf(const char* name);