more userspace stuff
This commit is contained in:
@@ -20,8 +20,8 @@ io_wait:
|
||||
liftoff:
|
||||
cli
|
||||
|
||||
mov 4(%esp), %ecx
|
||||
mov 8(%esp), %ebx
|
||||
mov 4(%esp), %ecx
|
||||
mov 8(%esp), %ebx
|
||||
|
||||
mov $0x23, %ax
|
||||
mov %ax, %ds
|
||||
@@ -29,15 +29,20 @@ liftoff:
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
|
||||
push $0x23
|
||||
push %ebx
|
||||
push $0x202
|
||||
push $0x1B
|
||||
push %ecx
|
||||
pushl $0x23 # User Data Segment (SS)
|
||||
pushl %ebx # User Stack Pointer (ESP)
|
||||
pushl $0x202 # EFLAGS (Interrupts enabled, bit 1 standard)
|
||||
pushl $0x1B # User Code Segment (CS)
|
||||
pushl %ecx # User Entry Point (EIP)
|
||||
|
||||
xor %eax, %eax
|
||||
xor %ebx, %ebx
|
||||
xor %ecx, %ecx
|
||||
xor %edx, %edx
|
||||
|
||||
xor %esi, %esi
|
||||
xor %edi, %edi
|
||||
xor %ebp, %ebp
|
||||
|
||||
iret
|
||||
|
||||
.global outb
|
||||
@@ -121,5 +126,3 @@ outsw:
|
||||
fetch_cr3:
|
||||
mov %cr3, %eax
|
||||
ret
|
||||
|
||||
.global set_cr3
|
||||
|
||||
@@ -7,4 +7,6 @@ void enable_interrupts();
|
||||
void disable_interrupts();
|
||||
uint32_t fetch_cr3();
|
||||
|
||||
void liftoff(uint32_t entry_point, uint32_t user_stack) __attribute__((noreturn));
|
||||
|
||||
#endif
|
||||
@@ -33,9 +33,9 @@ init_pic:
|
||||
outb %al, $PIC2_DATA
|
||||
|
||||
# mask
|
||||
mov $0xF8, %al
|
||||
mov $0xFF, %al
|
||||
outb %al, $PIC1_DATA
|
||||
mov $0x3F, %al
|
||||
mov $0xFF, %al
|
||||
outb %al, $PIC2_DATA
|
||||
|
||||
ret
|
||||
|
||||
@@ -34,6 +34,7 @@ typedef struct __attribute__((packed)) {
|
||||
} tss_entry_t;
|
||||
|
||||
void init_gdt();
|
||||
void tss_flush();
|
||||
|
||||
extern tss_entry_t tss;
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ void common_interrupt_handler(registers *args) {
|
||||
case 13:
|
||||
case 15:
|
||||
case 16:
|
||||
kprintf("CPU Error: %s", err_messages[args->int_no]);
|
||||
kprintf("CPU Error: %s, %d\n", err_messages[args->int_no], args->error_code);
|
||||
break;
|
||||
case 14:{
|
||||
uint32_t faulting_address;
|
||||
@@ -119,6 +119,9 @@ void common_interrupt_handler(registers *args) {
|
||||
kprintf("Faulted Virtual Address: 0x%x\n", faulting_address);
|
||||
kprintf("Error Code: 0x%x\n", args->error_code);
|
||||
kprintf("Instruction Pointer: 0x%x\n", args->eip);
|
||||
kprintf("Stack Pointer: 0x%x\n", args->useresp);
|
||||
kprintf("EAX: 0x%x\n", args->eax);
|
||||
kprintf("EFLAGS: 0x%x\n", args->eflags);
|
||||
kprintf("Caused by: %s, %s, running in %s mode\n",
|
||||
(args->error_code & 0x01) ? "Protection Violation" : "Page Not Present",
|
||||
(args->error_code & 0x02) ? "Write" : "Read",
|
||||
@@ -127,15 +130,18 @@ void common_interrupt_handler(registers *args) {
|
||||
break;
|
||||
}
|
||||
case 33: {
|
||||
kprintf("ps2 keyboard interrupt\n");
|
||||
uint8_t data = ps2_read_data();
|
||||
send_eoi_master();
|
||||
break;
|
||||
}
|
||||
case 46: { // IDE PRIMARY
|
||||
kprintf("IDE PRIMARY interrupt\n");
|
||||
send_eoi_slave();
|
||||
break;
|
||||
}
|
||||
case 47: { // IDE SLAVE
|
||||
kprintf("IDE SLAVE interrupt\n");
|
||||
send_eoi_slave();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#include "multiboot.h"
|
||||
#include "interrupts.h"
|
||||
#include "gdt.h"
|
||||
#include "scheduler.h"
|
||||
#include "common.h"
|
||||
#include "scheduler.h"
|
||||
#include "vfs.h"
|
||||
#include "elf.h"
|
||||
#include "gdt.h"
|
||||
|
||||
#include <lib/print.h>
|
||||
#include <lib/stream.h>
|
||||
@@ -26,6 +27,9 @@
|
||||
extern char __kernel_start;
|
||||
extern char __kernel_end;
|
||||
|
||||
extern uint32_t page_directory[1024];
|
||||
void* kernel_cr3 = page_directory;
|
||||
|
||||
void parse_multiboot_modules(uint32_t mbi_vaddr) {
|
||||
// find where grub put the boot module containing initrd
|
||||
multiboot_info* mbi = (multiboot_info*)mbi_vaddr;
|
||||
@@ -52,7 +56,8 @@ vfs_node_t* load_initrd() {
|
||||
return cpio_read_fs(initrd_module->mod_start);
|
||||
}
|
||||
|
||||
void load_program(const char* path) {
|
||||
void load_root_program(const char* path) {
|
||||
uint32_t kernel_cr3 = fetch_cr3();
|
||||
void* cr3 = create_task_pd();
|
||||
load_pd(cr3);
|
||||
flush_tlb();
|
||||
@@ -93,12 +98,12 @@ void load_program(const char* path) {
|
||||
|
||||
for (uint32_t v = page_start; v < page_end; v += PAGE_SIZE) {
|
||||
void* phys_frame = p_alloc_frame();
|
||||
map_page(v, (uint32_t)phys_frame, 0x07);
|
||||
map_page(v, (uint32_t)phys_frame, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER);
|
||||
}
|
||||
|
||||
uint32_t data_ptr = ph->p_offset;
|
||||
fseek(fd, data_ptr);
|
||||
read(fd, (void*)vstart, ph->p_memsz);
|
||||
read(fd, (void*)vstart, ph->p_filesz);
|
||||
|
||||
// 0 out bss
|
||||
if (ph->p_memsz > ph->p_filesz) {
|
||||
@@ -110,15 +115,24 @@ void load_program(const char* path) {
|
||||
ph_table_ptr += sizeof(elf_program_header_t);
|
||||
}
|
||||
|
||||
uint32_t esp = 0xBFFF0000;
|
||||
void* pesp = p_alloc_frame();
|
||||
map_page(esp - PAGE_SIZE, (uint32_t)pesp, 0x07);
|
||||
uint32_t stack_sz = PAGE_SIZE * 16;
|
||||
uint32_t stack_top = 0xBFFF0000;
|
||||
uint32_t stack_bottom = stack_top - stack_sz;
|
||||
for (uint32_t vaddr = stack_bottom; vaddr < stack_top; vaddr += PAGE_SIZE) {
|
||||
void* phys_frame = p_alloc_frame();
|
||||
map_page(vaddr, (uint32_t)phys_frame, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER);
|
||||
}
|
||||
|
||||
create_task(e_hdr->e_entry, fetch_cr3(), 1);
|
||||
}
|
||||
uint32_t* u_esp = (uint32_t*)stack_top;
|
||||
*(--u_esp) = 0; // envp = NULL
|
||||
*(--u_esp) = 0; // argv = NULL
|
||||
*(--u_esp) = 0; // argc = 0
|
||||
|
||||
void start_origin() {
|
||||
load_program("/origin.elf");
|
||||
create_task(e_hdr->e_entry, (uint32_t)cr3, 1, (uint32_t)u_esp);
|
||||
load_pd((void*)kernel_cr3);
|
||||
flush_tlb();
|
||||
|
||||
kprintf("task created for origin program %s\n", path);
|
||||
}
|
||||
|
||||
void kmain(uint32_t magic, multiboot_info* mbi) {
|
||||
@@ -150,13 +164,14 @@ void kmain(uint32_t magic, multiboot_info* mbi) {
|
||||
if (!initrd_root) {
|
||||
kprintf("failed to load initrd\n");
|
||||
}
|
||||
|
||||
mount(vfs_root, initrd_root);
|
||||
kprintf("initrd read, mounted @ /\n");
|
||||
|
||||
disable_interrupts();
|
||||
init_scheduler();
|
||||
enable_interrupts();
|
||||
|
||||
kprintf("loading user program\n");
|
||||
start_origin();
|
||||
kprintf("loading origin program\n");
|
||||
load_root_program("/origin.elf");
|
||||
yield();
|
||||
}
|
||||
|
||||
@@ -134,4 +134,8 @@ void* kalloc(size_t sz) {
|
||||
}
|
||||
|
||||
return kalloc(sz);
|
||||
}
|
||||
|
||||
void kfree(void* ptr) {
|
||||
|
||||
}
|
||||
@@ -14,6 +14,6 @@ char* strcpy(char* dest, const char* src);
|
||||
|
||||
void kgrow(size_t pages);
|
||||
void* kalloc(size_t sz);
|
||||
|
||||
void kfree(void* ptr);
|
||||
|
||||
#endif
|
||||
@@ -18,6 +18,9 @@ extern uint32_t page_directory[1024];
|
||||
|
||||
#define TEMP_MAPPING_VADDR 0xDFFF0000
|
||||
|
||||
#define USR_PAGE 0x07
|
||||
#define SUP_PAGE 0x03
|
||||
|
||||
static uint32_t max_address = 0;
|
||||
static uint32_t total_available_memory = 0;
|
||||
static uint8_t memory_bitmap[BITMAP_SIZE];
|
||||
|
||||
@@ -10,15 +10,21 @@ typedef enum {
|
||||
STATE_DEAD
|
||||
} process_state_t;
|
||||
|
||||
typedef enum {
|
||||
PROCESS_FLAG_NONE = 0,
|
||||
PROCESS_FLAG_KERNEL = 1 << 0,
|
||||
PROCESS_FLAG_USER = 1 << 1
|
||||
} process_flags_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t pid;
|
||||
uint32_t esp;
|
||||
uint32_t esp0;
|
||||
uint32_t kstack_top;
|
||||
uint32_t cr3;
|
||||
process_state_t state;
|
||||
uint32_t sleep;
|
||||
void* next;
|
||||
uint32_t heap_end;
|
||||
uint32_t flags;
|
||||
} __attribute__((packed)) process_t;
|
||||
|
||||
#endif
|
||||
@@ -17,9 +17,7 @@ yield: # void yield()
|
||||
movl 0(%esp), %ebx # Get Return EIP
|
||||
movl %ebx, 4(%esp) # Move Return EIP over CS
|
||||
addl $4, %esp # Adjust stack pointer up.
|
||||
|
||||
# the stack now looks like a hardware interrupt just happened, even though we never called one.
|
||||
|
||||
|
||||
pushal
|
||||
|
||||
pushl %esp
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <lib/tasks.h>
|
||||
#include <lib/print.h>
|
||||
#include <lib/memory.h>
|
||||
|
||||
#include <memory/mm.h>
|
||||
@@ -69,7 +70,9 @@ uint32_t switch_context(uint32_t current_esp) {
|
||||
|
||||
current_process = next_process;
|
||||
|
||||
tss.esp0 = process_table[current_process].esp0;
|
||||
if (process_table[current_process].flags & PROCESS_FLAG_USER ) {
|
||||
tss.esp0 = process_table[current_process].kstack_top;
|
||||
}
|
||||
|
||||
if (fetch_cr3() != process_table[current_process].cr3) {
|
||||
load_pd((void*)process_table[current_process].cr3);
|
||||
@@ -88,14 +91,15 @@ void init_scheduler() {
|
||||
process->cr3 = fetch_cr3();
|
||||
process->state = STATE_READY;
|
||||
process->sleep = 0;
|
||||
process->flags = PROCESS_FLAG_KERNEL;
|
||||
total_processes++;
|
||||
|
||||
create_task((uint32_t)idle_task, fetch_cr3(), 0);
|
||||
create_task((uint32_t)idle_task, fetch_cr3(), 0, 0);
|
||||
|
||||
current_process = 0;
|
||||
}
|
||||
|
||||
int create_task(uint32_t entry_point, uint32_t cr3, int user) {
|
||||
int create_task(uint32_t entry_point, uint32_t cr3, int user, uint32_t u_esp) {
|
||||
if (total_processes >= 16) {
|
||||
return 0;
|
||||
}
|
||||
@@ -103,12 +107,14 @@ int create_task(uint32_t entry_point, uint32_t cr3, int user) {
|
||||
lock_scheduler();
|
||||
|
||||
// default to a new task, but if we find a dead one, re use it
|
||||
int reuse = 0;
|
||||
process_t* process = &process_table[total_processes];
|
||||
uint32_t pid = total_processes;
|
||||
for (uint32_t i = 0; i < total_processes; i++) {
|
||||
if (process_table[i].state == STATE_DEAD) {
|
||||
process = &process_table[i];
|
||||
pid = i;
|
||||
reuse = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,22 +122,26 @@ int create_task(uint32_t entry_point, uint32_t cr3, int user) {
|
||||
process->cr3 = cr3;
|
||||
process->state = STATE_READY;
|
||||
process->sleep = 0;
|
||||
process->flags = user ? PROCESS_FLAG_USER : PROCESS_FLAG_KERNEL;
|
||||
|
||||
void* stack_bottom = kalloc(4096);
|
||||
uint32_t* esp = (uint32_t*)((uint32_t)stack_bottom + 4096);
|
||||
process->esp0 = (uint32_t)esp;
|
||||
void* kstack_bottom = kalloc(PAGE_SIZE);
|
||||
uint32_t kstack_top = (uint32_t)kstack_bottom + PAGE_SIZE;
|
||||
process->kstack_top = kstack_top;
|
||||
|
||||
uint32_t* esp = (uint32_t*)kstack_top;
|
||||
if (user) {
|
||||
*(--esp) = 0x23; // User Data Segment (SS) with RPL 3 (0x20 | 3)
|
||||
*(--esp) = 0xBFFFF000; // User Stack Pointer (ESP) - location mapped in user space
|
||||
*(--esp) = u_esp; // User Stack Pointer (ESP) - location mapped in user space
|
||||
*(--esp) = 0x0202; // EFLAGS (Interrupts enabled)
|
||||
*(--esp) = 0x1B; // User Code Segment (CS) with RPL 3 (0x18 | 3)
|
||||
*(--esp) = entry_point; // EIP
|
||||
*(--esp) = 0x23;
|
||||
} else {
|
||||
// IRET values for Ring 0
|
||||
*(--esp) = 0x0202; // EFLAGS
|
||||
*(--esp) = 0x08; // Kernel Code Segment (CS)
|
||||
*(--esp) = entry_point; // EIP
|
||||
*(--esp) = 0x10;
|
||||
}
|
||||
|
||||
*(--esp) = 0; // EAX
|
||||
@@ -144,7 +154,9 @@ int create_task(uint32_t entry_point, uint32_t cr3, int user) {
|
||||
*(--esp) = 0; // EDI
|
||||
|
||||
process->esp = (uint32_t)esp;
|
||||
total_processes++;
|
||||
if (!reuse) {
|
||||
total_processes++;
|
||||
}
|
||||
unlock_scheduler();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
void init_scheduler();
|
||||
|
||||
int create_task(uint32_t entry_point, uint32_t cr3, int user);
|
||||
int create_task(uint32_t entry_point, uint32_t cr3, int user, uint32_t u_esp);
|
||||
process_t* current_task();
|
||||
|
||||
void sleep(uint32_t ms);
|
||||
|
||||
@@ -4,33 +4,33 @@
|
||||
syscall_handler:
|
||||
cli
|
||||
|
||||
push $0
|
||||
push $0x80
|
||||
pushfl
|
||||
pushl %cs
|
||||
|
||||
pusha
|
||||
movl 8(%esp), %eax
|
||||
pushl %eax
|
||||
movl 4(%esp), %ebx # Get CS
|
||||
movl %ebx, 8(%esp) # Move CS over Old EIP
|
||||
movl 0(%esp), %ebx # Get Return EIP
|
||||
movl %ebx, 4(%esp) # Move Return EIP over CS
|
||||
addl $4, %esp # Adjust stack pointer
|
||||
|
||||
push %ds
|
||||
push %es
|
||||
push %fs
|
||||
push %gs
|
||||
movw %ds, %ax
|
||||
pushl %eax
|
||||
|
||||
mov $0x10, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
pushal
|
||||
|
||||
pushl %esp
|
||||
call switch_context
|
||||
movl %eax, %esp
|
||||
|
||||
popal
|
||||
|
||||
push %esp
|
||||
call syscall
|
||||
add $4, %esp
|
||||
|
||||
mov 28(%esp), %eax
|
||||
popl %eax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %fs
|
||||
movw %ax, %gs
|
||||
|
||||
pop %gs
|
||||
pop %fs
|
||||
pop %es
|
||||
pop %ds
|
||||
|
||||
popa
|
||||
add $8, %esp
|
||||
sti
|
||||
iret
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <drivers/vga/vga.h>
|
||||
|
||||
#include <lib/print.h>
|
||||
|
||||
typedef struct registers {
|
||||
uint32_t gs, fs, es, ds; // Pushed manually
|
||||
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha
|
||||
@@ -16,7 +18,7 @@ typedef struct registers {
|
||||
|
||||
|
||||
static int32_t sys_exit(int status) {
|
||||
exit();
|
||||
asm volatile("hlt");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user