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"
|
-ex "continue"
|
||||||
|
|
||||||
fs.img: kernel.bin tools/mkfs user/false
|
fs.img: kernel.bin tools/mkfs user/false
|
||||||
tools/mkfs $@ $<
|
tools/mkfs $@ $< user/false
|
||||||
|
|
||||||
LDFLAGS=-m elf_i386
|
LDFLAGS=-m elf_i386
|
||||||
|
|
||||||
user/%: user/%.o user/crt.o
|
user/%: user/%.o user/crt.o
|
||||||
$(LD) $(LDFLAGS) -o $@ -Ttext 0x101000 $^
|
$(LD) $(LDFLAGS) -o $@ -Ttext 0x1000 $^
|
||||||
|
|
||||||
image.bin: mbr.bin fs.img
|
image.bin: mbr.bin fs.img
|
||||||
cat $^ >$@
|
cat $^ >$@
|
||||||
|
|
||||||
kernel.bin: kernel.o console.o drivers/vga.o drivers/keyboard.o \
|
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 \
|
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 $^
|
$(LD) $(LDFLAGS) -o $@ -Ttext 0x1000 $^
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
|
|||||||
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#define DPL_USER 3
|
#define DPL_USER 3
|
||||||
|
|
||||||
|
#define FL_IF 0x00000200
|
||||||
|
|
||||||
#define SEG_KCODE 1
|
#define SEG_KCODE 1
|
||||||
#define SEG_KDATA 2
|
#define SEG_KDATA 2
|
||||||
#define SEG_UCODE 3
|
#define SEG_UCODE 3
|
||||||
@ -22,8 +24,9 @@
|
|||||||
.byte (((base) >> 16) & 0xff), (0x90 | (type)), \
|
.byte (((base) >> 16) & 0xff), (0x90 | (type)), \
|
||||||
(0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
|
(0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
|
||||||
|
|
||||||
#define USER_BASE 0x400000 // 4 MB
|
#define USER_BASE 0x400000 // 4 MB
|
||||||
#define KERN_STACK_BASE 0x90000
|
#define USER_STACK_BASE 0xf00000 // 15 MB
|
||||||
|
#define KERN_STACK_BASE 0x90000
|
||||||
|
|
||||||
#ifndef __ASSEMBLER__
|
#ifndef __ASSEMBLER__
|
||||||
void load_gdt();
|
void load_gdt();
|
||||||
|
|||||||
38
cpu/idt.c
38
cpu/idt.c
@ -42,27 +42,27 @@ void init_idt() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char * const exception_messages[] = {
|
const char * const exception_messages[] = {
|
||||||
"Division By Zero",
|
[0] = "Division By Zero",
|
||||||
"Debug",
|
[1] = "Debug",
|
||||||
"Non Maskable Interrupt",
|
[2] = "Non Maskable Interrupt",
|
||||||
"Breakpoint",
|
[3] = "Breakpoint",
|
||||||
"Into Detected Overflow",
|
[4] = "Into Detected Overflow",
|
||||||
"Out of Bounds",
|
[5] = "Out of Bounds",
|
||||||
"Invalid Opcode",
|
[6] = "Invalid Opcode",
|
||||||
"No Coprocessor",
|
[7] = "No Coprocessor",
|
||||||
|
|
||||||
"Double Fault",
|
[8] = "Double Fault",
|
||||||
"Coprocessor Segment Overrun",
|
[9] = "Coprocessor Segment Overrun",
|
||||||
"Bad TSS",
|
[10] = "Bad TSS",
|
||||||
"Segment Not Present",
|
[11] = "Segment Not Present",
|
||||||
"Stack Fault",
|
[12] = "Stack Fault",
|
||||||
"General Protection Fault",
|
[13] = "General Protection Fault",
|
||||||
"Page Fault",
|
[14] = "Page Fault",
|
||||||
"Unknown Interrupt",
|
[15] = "Unknown Interrupt",
|
||||||
|
|
||||||
"Coprocessor Fault",
|
[16] = "Coprocessor Fault",
|
||||||
"Alignment Check",
|
[17] = "Alignment Check",
|
||||||
"Machine Check",
|
[18] = "Machine Check",
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ARRLEN(a) (sizeof(a) / sizeof(a[0]))
|
#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:
|
alltraps:
|
||||||
# Build trap frame.
|
# Build trap frame.
|
||||||
pushl %ds
|
pushl %ds
|
||||||
@ -13,7 +15,9 @@ alltraps:
|
|||||||
pushl %esp
|
pushl %esp
|
||||||
call trap
|
call trap
|
||||||
add $4, %esp
|
add $4, %esp
|
||||||
|
// execution falls through to trapret
|
||||||
|
|
||||||
|
trapret:
|
||||||
popal
|
popal
|
||||||
popl %gs
|
popl %gs
|
||||||
popl %fs
|
popl %fs
|
||||||
|
|||||||
13
kernel.c
13
kernel.c
@ -10,6 +10,8 @@ asm(".asciz \"kernel start\\n\"");
|
|||||||
#include "drivers/uart.h"
|
#include "drivers/uart.h"
|
||||||
#include "fs/fs.h"
|
#include "fs/fs.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
|
#include "proc.h"
|
||||||
|
|
||||||
|
|
||||||
void _start() {
|
void _start() {
|
||||||
load_gdt();
|
load_gdt();
|
||||||
@ -28,20 +30,19 @@ void _start() {
|
|||||||
} else {
|
} else {
|
||||||
printk("failed to read file\n");
|
printk("failed to read file\n");
|
||||||
}
|
}
|
||||||
printk("\n> ");
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (kbd_buf_size > 0 && kbd_buf[kbd_buf_size-1] == '\n') {
|
if (kbd_buf_size > 0 && kbd_buf[kbd_buf_size-1] == '\n') {
|
||||||
if (!strncmp("halt\n", kbd_buf, kbd_buf_size)) {
|
if (!strncmp("halt\n", kbd_buf, kbd_buf_size)) {
|
||||||
qemu_shutdown();
|
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';
|
kbd_buf[kbd_buf_size-1] = '\0';
|
||||||
// const char* cmd = kbd_buf + 4;
|
const char* cmd = kbd_buf + 4;
|
||||||
// run_elf(cmd);
|
run_elf(cmd);
|
||||||
} else {
|
} else {
|
||||||
printk("unknown command, try: halt\n> ");
|
printk("unknown command, try: halt");
|
||||||
}
|
}
|
||||||
kbd_buf_size = 0;
|
kbd_buf_size = 0;
|
||||||
|
printk("\n> ");
|
||||||
}
|
}
|
||||||
asm("hlt");
|
asm("hlt");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,3 +26,10 @@ int strncmp(const char* s1, const char* s2, size_t size) {
|
|||||||
}
|
}
|
||||||
return (unsigned char)(*s1) - (unsigned char)(*s2);
|
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);
|
void kmemmove(char* dst, char* src, size_t size);
|
||||||
int strncmp(const char* s1, const char* s2, 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