more userspace stuff
This commit is contained in:
21
deploy_programs.sh
Executable file
21
deploy_programs.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd rocklibc
|
||||
make clean
|
||||
make
|
||||
cd ..
|
||||
|
||||
cd programs
|
||||
make clean
|
||||
make
|
||||
cd ..
|
||||
|
||||
make clean
|
||||
make
|
||||
|
||||
cd initrd
|
||||
./make_img.sh
|
||||
cd ..
|
||||
|
||||
make -B
|
||||
|
||||
@@ -29,14 +29,19 @@ 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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -135,3 +135,7 @@ 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
|
||||
@@ -18,8 +18,6 @@ yield: # void yield()
|
||||
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
|
||||
|
||||
push %esp
|
||||
call syscall
|
||||
add $4, %esp
|
||||
pushl %esp
|
||||
call switch_context
|
||||
movl %eax, %esp
|
||||
|
||||
mov 28(%esp), %eax
|
||||
popal
|
||||
|
||||
pop %gs
|
||||
pop %fs
|
||||
pop %es
|
||||
pop %ds
|
||||
popl %eax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %fs
|
||||
movw %ax, %gs
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,24 +1,21 @@
|
||||
.global _start
|
||||
.intel_syntax noprefix
|
||||
|
||||
.section .text
|
||||
_start:
|
||||
xor ebp, ebp
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
xor %ebp, %ebp
|
||||
push %ebp
|
||||
mov %esp, %ebp
|
||||
|
||||
mov eax, [esp + 4]
|
||||
lea ebx, [esp + 8]
|
||||
lea ecx, [esp + 12]
|
||||
mov (%esp), %eax
|
||||
lea 4(%esp), %ebx
|
||||
lea 8(%esp, %eax, 4), %ecx
|
||||
|
||||
push ecx
|
||||
push ebx
|
||||
push eax
|
||||
push %ecx
|
||||
push %ebx
|
||||
push %eax
|
||||
|
||||
call main
|
||||
|
||||
push eax
|
||||
push %eax
|
||||
call exit
|
||||
|
||||
1: hlt
|
||||
jmp 1b
|
||||
1: jmp 1b
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
# 0 "crt0.S"
|
||||
# 0 "<built-in>"
|
||||
# 0 "<command-line>"
|
||||
# 1 "crt0.S"
|
||||
.global _start
|
||||
.intel_syntax noprefix
|
||||
|
||||
.section .text
|
||||
_start:
|
||||
xor ebp, ebp
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
mov eax, [esp + 4]
|
||||
lea ebx, [esp + 8]
|
||||
lea ecx, [esp + 12]
|
||||
|
||||
push ecx
|
||||
push ebx
|
||||
push eax
|
||||
|
||||
call main
|
||||
|
||||
push eax
|
||||
call exit
|
||||
|
||||
1: hlt
|
||||
jmp 1b
|
||||
@@ -1,8 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
printf("Hello, World from RockOS!\n");
|
||||
|
||||
int main() {
|
||||
printf("RockOS booting...\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -8,8 +8,8 @@ TARGET = origin.elf
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
crt0.o: crt0.s
|
||||
$(CC) $(CFLAGS) -c crt0.s -o crt0.o
|
||||
crt0.o: crt0.S
|
||||
$(CC) $(CFLAGS) -c crt0.S -o crt0.o
|
||||
|
||||
main.o: main.c
|
||||
$(CC) $(CFLAGS) -c main.c -o main.o
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef int _PDCLIB_fd_t;
|
||||
|
||||
@@ -14,13 +15,8 @@ static inline int32_t inline_syscall(uint32_t num, uint32_t arg1, uint32_t arg2,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void _exit(int status) {
|
||||
inline_syscall(1, (uint32_t)status, 0, 0);
|
||||
while(1) { asm volatile("hlt"); }
|
||||
}
|
||||
|
||||
void _PDCLIB_exit(int status) {
|
||||
_exit(status);
|
||||
inline_syscall(1, (uint32_t)status, 0, 0);;
|
||||
}
|
||||
|
||||
int _PDCLIB_read(_PDCLIB_fd_t fd, void *buf, size_t count) {
|
||||
@@ -112,3 +108,7 @@ void * sbrk(intptr_t increment) {
|
||||
|
||||
return (void *)-1;
|
||||
}
|
||||
|
||||
void exit(int status) {
|
||||
_PDCLIB_exit(status);
|
||||
}
|
||||
Reference in New Issue
Block a user