Run user process.
This commit is contained in:
parent
529ba03e50
commit
dd9f5786c2
6
Makefile
6
Makefile
@ -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
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
|
||||
#define DPL_USER 3
|
||||
|
||||
#define FL_IF 0x00000200
|
||||
|
||||
#define SEG_KCODE 1
|
||||
#define SEG_KDATA 2
|
||||
#define SEG_UCODE 3
|
||||
@ -22,8 +24,9 @@
|
||||
.byte (((base) >> 16) & 0xff), (0x90 | (type)), \
|
||||
(0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
|
||||
|
||||
#define USER_BASE 0x400000 // 4 MB
|
||||
#define KERN_STACK_BASE 0x90000
|
||||
#define USER_BASE 0x400000 // 4 MB
|
||||
#define USER_STACK_BASE 0xf00000 // 15 MB
|
||||
#define KERN_STACK_BASE 0x90000
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
void load_gdt();
|
||||
|
||||
38
cpu/idt.c
38
cpu/idt.c
@ -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
20
cpu/swtch.S
Normal 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
|
||||
@ -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
|
||||
|
||||
13
kernel.c
13
kernel.c
@ -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");
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
62
proc.c
Normal 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
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user