diff options
-rw-r--r-- | include/typedefs.h | 2 | ||||
-rw-r--r-- | kernel/Makefile | 8 | ||||
-rw-r--r-- | kernel/arch/i386/mmu.c | 26 | ||||
-rw-r--r-- | kernel/cpu/idt.c | 37 | ||||
-rw-r--r-- | kernel/cpu/idt.h | 10 | ||||
-rw-r--r-- | kernel/cpu/int_syscall.s | 3 | ||||
-rw-r--r-- | kernel/cpu/syscall.c | 20 | ||||
-rw-r--r-- | kernel/drivers/pit.c | 15 | ||||
-rw-r--r-- | kernel/drivers/rtl8139.c | 6 | ||||
-rw-r--r-- | kernel/fs/ext2.c | 26 | ||||
-rw-r--r-- | kernel/halts.c | 2 | ||||
-rw-r--r-- | kernel/includes/mmu.h | 1 | ||||
-rw-r--r-- | kernel/includes/syscalls.h | 7 | ||||
-rw-r--r-- | kernel/init/kernel.c | 8 | ||||
-rw-r--r-- | kernel/ipc.c | 7 | ||||
-rw-r--r-- | kernel/poll.c | 2 | ||||
-rw-r--r-- | kernel/process.s | 114 | ||||
-rw-r--r-- | kernel/sched/scheduler.c | 116 | ||||
-rw-r--r-- | kernel/sched/scheduler.h | 15 | ||||
-rw-r--r-- | kernel/syscalls/msleep.c | 2 | ||||
-rwxr-xr-x | meta/debug.sh | 3 | ||||
-rwxr-xr-x | meta/userland.sh | 2 | ||||
-rw-r--r-- | userland/libc/include/syscall.h | 7 | ||||
-rw-r--r-- | userland/libppm/ppm.c | 29 |
24 files changed, 368 insertions, 100 deletions
diff --git a/include/typedefs.h b/include/typedefs.h index e290716..e2226fd 100644 --- a/include/typedefs.h +++ b/include/typedefs.h @@ -9,3 +9,5 @@ typedef int8_t i8; typedef int16_t i16; typedef int32_t i32; typedef int64_t i64; + +#define U32_MAX 4294967295 diff --git a/kernel/Makefile b/kernel/Makefile index a36e84c..4ac7368 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,7 +1,9 @@ CC="i686-sb-gcc" AS="i686-sb-as" -OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o cpu/int_syscall.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o halts.o syscalls/ppoll.o syscalls/ftruncate.o kubsan.o syscalls/mmap.o drivers/serial.o syscalls/accept.o syscalls/bind.o syscalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o syscalls/shm.o elf.o ksbrk.o sched/scheduler.o syscalls/stat.o libc/string/copy.o libc/string/strncpy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o syscalls/msleep.o syscalls/uptime.o syscalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o syscalls/recvfrom.o math.o syscalls/sendto.o signal.o syscalls/kill.o syscalls/sigaction.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o syscalls/chdir.o syscalls/getcwd.o syscalls/isatty.o syscalls/randomfill.o syscalls/open.o syscalls/write.o syscalls/pwrite.o ipc.o syscalls/ipc.o -CFLAGS = -O3 -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL +OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o cpu/int_syscall.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o halts.o syscalls/ppoll.o syscalls/ftruncate.o kubsan.o syscalls/mmap.o drivers/serial.o syscalls/accept.o syscalls/bind.o syscalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o syscalls/shm.o elf.o ksbrk.o sched/scheduler.o syscalls/stat.o libc/string/copy.o libc/string/strncpy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o syscalls/msleep.o syscalls/uptime.o syscalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o syscalls/recvfrom.o math.o syscalls/sendto.o signal.o syscalls/kill.o syscalls/sigaction.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o syscalls/chdir.o syscalls/getcwd.o syscalls/isatty.o syscalls/randomfill.o syscalls/open.o syscalls/write.o syscalls/pwrite.o ipc.o syscalls/ipc.o syscalls/port.o syscalls/map_frames.o syscalls/virtual_to_physical.o syscalls/install_irq.o switch_task.o +CFLAGS = -O0 -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL +#LDFLAGS=-flto -Ofast +LDFLAGS= INCLUDE=-I./includes/ -I../include/ -I./libc/include/ all: myos.iso @@ -13,7 +15,7 @@ all: myos.iso $(AS) $< -o $@ myos.bin: $(OBJ) - $(CC) $(INCLUDE) -shared -T linker.ld -o myos.bin -ffreestanding -nostdlib $(CFLAGS) $^ -lgcc + $(CC) $(INCLUDE) $(LDFLAGS) -shared -T linker.ld -o myos.bin -ffreestanding -nostdlib $(CFLAGS) $^ -lgcc myos.iso: myos.bin cp myos.bin isodir/boot diff --git a/kernel/arch/i386/mmu.c b/kernel/arch/i386/mmu.c index 288e12a..f958455 100644 --- a/kernel/arch/i386/mmu.c +++ b/kernel/arch/i386/mmu.c @@ -332,6 +332,24 @@ int mmu_allocate_region(void *ptr, size_t n, mmu_flags flags, return 1; } +void *mmu_map_user_frames(void *const ptr, size_t s) { + void *const r = get_free_virtual_memory(s); + size_t num_pages = s / 0x1000; + for (size_t i = 0; i <= num_pages; i++) { + Page *p = get_page((void *)(r + i * 0x1000), NULL, PAGE_ALLOCATE, 0); + assert(p); + int rw = 1; + int is_kernel = 0; + p->present = 1; + p->rw = rw; + p->user = !is_kernel; + p->frame = (uintptr_t)(ptr + i * 0x1000) / 0x1000; + kprintf("mapped user frame: %x\n", p->frame); + write_to_frame((uintptr_t)ptr + i * 0x1000, 1); + } + return r; +} + void *mmu_map_frames(void *const ptr, size_t s) { void *const r = mmu_find_unallocated_virtual_range((void *)0xEF000000, s); size_t num_pages = s / 0x1000; @@ -457,10 +475,8 @@ void *physical_to_virtual(void *address) { void *virtual_to_physical(void *address, PageDirectory *directory) { if (0 == directory) directory = get_active_pagedirectory(); - return (void *)((get_page((void *)address, directory, PAGE_NO_ALLOCATE, 0) - ->frame * - 0x1000) + - (((uintptr_t)address) & 0xFFF)); + Page *p = get_page((void *)address, directory, PAGE_NO_ALLOCATE, 0); + return (void *)((u32)p->frame * 0x1000) + (((uintptr_t)address) & 0xFFF); } extern u32 inital_esp; @@ -595,7 +611,7 @@ void paging_init(u64 memsize) { switch_page_directory(kernel_directory); // Make null dereferences crash. get_page(NULL, kernel_directory, PAGE_ALLOCATE, 0)->present = 0; - for (int i = 0; i < 16; i++) + for (int i = 0; i < 25; i++) create_table(770 + i); kernel_directory = clone_directory(kernel_directory); diff --git a/kernel/cpu/idt.c b/kernel/cpu/idt.c index 46782b5..f4d025a 100644 --- a/kernel/cpu/idt.c +++ b/kernel/cpu/idt.c @@ -69,11 +69,36 @@ __attribute__((interrupt)) void double_fault(registers_t *regs) { for (;;) ; } + +void tmp_jump_process(u32, u32, u32, u32); +void jump_process(const process_t *p) { + // tmp_jump_process(p->eip, p->cr3->physical_address, p->ebp, p->esp); +} + +void none_save_switch(void); +extern PageDirectory *active_directory; __attribute__((interrupt)) void page_fault(registers_t *regs) { - if (0xFFFFDEAD == regs->eip) { - asm("sti"); - for (;;) - switch_task(); + volatile uint32_t cr2; + asm volatile("mov %%cr2, %0" : "=r"(cr2)); + kprintf("CR2: %x\n", cr2); + if (0xFFFFDEAD == cr2) { + /* + process_t *current = get_current_task(); + if (!current) { + kprintf("WHYYYYYY!\n"); + for (;;) + asm("cli"); + } + current->useresp = regs->esp;*/ + // active_directory = current->cr3; +// get_current_task()->esp = get_current_task()->saved_esp; +// get_current_task()->ebp = get_current_task()->saved_ebp; +// get_current_task()->eip = get_current_task()->saved_eip; + for (;;) { + switch_task(0); + } + // jump_process(current); + return; } klog("Page Fault", LOG_ERROR); if (get_current_task()) { @@ -83,10 +108,6 @@ __attribute__((interrupt)) void page_fault(registers_t *regs) { kprintf("Error Code: %x\n", regs->error_code); kprintf("Instruction Pointer: %x\n", regs->eip); - volatile uint32_t cr2; - asm volatile("mov %%cr2, %0" : "=r"(cr2)); - kprintf("CR2: %x\n", cr2); - if (regs->error_code & (1 << 0)) kprintf("page-protection violation\n"); else diff --git a/kernel/cpu/idt.h b/kernel/cpu/idt.h index 9341887..fdd6a3e 100644 --- a/kernel/cpu/idt.h +++ b/kernel/cpu/idt.h @@ -55,13 +55,9 @@ typedef struct registers registers_t; struct interrupt_frame; struct registers { - u32 error_code; - u32 eip; - u32 cs; - u32 eflags; - u32 esp; - u32 ss; -}; + uintptr_t error_code; + uintptr_t eip, cs, eflags, esp, ss; +} __attribute__((packed)); void idt_init(void); __attribute__((no_caller_saved_registers)) void EOI(unsigned char irq); diff --git a/kernel/cpu/int_syscall.s b/kernel/cpu/int_syscall.s index 8c3c25f..ec7693a 100644 --- a/kernel/cpu/int_syscall.s +++ b/kernel/cpu/int_syscall.s @@ -2,6 +2,7 @@ .global int_syscall .extern syscall_function_handler int_syscall: + push esp push ebp push edi push esi @@ -10,7 +11,7 @@ int_syscall: push ebx push eax call syscall_function_handler - add esp, 4 + add esp, 8 pop ebx pop ecx pop edx diff --git a/kernel/cpu/syscall.c b/kernel/cpu/syscall.c index 3a2b1ca..5e51d53 100644 --- a/kernel/cpu/syscall.c +++ b/kernel/cpu/syscall.c @@ -7,6 +7,7 @@ #include <fs/tmpfs.h> #include <fs/vfs.h> #include <kmalloc.h> +#include <network/ethernet.h> #include <string.h> #include <syscalls.h> #include <typedefs.h> @@ -35,6 +36,11 @@ int syscall_exec(SYS_EXEC_PARAMS *args) { return -1; } +void syscall_tmp_handle_packet(void *packet, u32 len) { + kprintf("syscall tmp handle packet\n"); + handle_ethernet((u8 *)packet, len); +} + int syscall_pipe(int fd[2]) { pipe(fd); // FIXME: Error checking return 0; @@ -75,7 +81,7 @@ void syscall_wait(int *status) { return; } get_current_task()->halts[WAIT_CHILD_HALT] = 1; - switch_task(); + switch_task(1); if (status) *status = get_current_task()->child_rc; } @@ -159,10 +165,20 @@ void (*syscall_functions[])() = { (void(*))syscall_ipc_read, (void(*))syscall_ipc_write, (void(*))syscall_ipc_write_to_process, + (void(*))syscall_outw, + (void(*))syscall_inl, + (void(*))syscall_outl, + (void(*))syscall_map_frames, + (void(*))syscall_virtual_to_physical, + (void(*))syscall_install_irq, + (void(*))syscall_tmp_handle_packet, }; void syscall_function_handler(u32 eax, u32 arg1, u32 arg2, u32 arg3, u32 arg4, - u32 arg5) { + u32 arg5, u32 ebp, u32 esp) { + if (esp <= 0x90000000) { + get_current_task()->useresp = esp; + } assert(eax < sizeof(syscall_functions) / sizeof(syscall_functions[0])); syscall_functions[eax](arg1, arg2, arg3, arg4, arg5); } diff --git a/kernel/drivers/pit.c b/kernel/drivers/pit.c index 567ac2d..8f9c35c 100644 --- a/kernel/drivers/pit.c +++ b/kernel/drivers/pit.c @@ -41,17 +41,24 @@ void set_pit_count(u16 hertz) { outb(PIT_IO_CHANNEL_0, (divisor & 0xFF00) >> 8); } -__attribute__((interrupt)) void -int_clock(__attribute__((unused)) struct interrupt_frame *frame) { +__attribute__((interrupt)) void int_clock(registers_t *regs) { + process_t *p = get_current_task(); + if (p) { + // FIXME: For some reason eflags is the esp? I have read the + // manual multilpe times and still can't figure out why. + if (regs->eflags <= 0x90000000 && regs->eflags) { + p->useresp = regs->eflags; + } + } outb(0x20, 0x20); pit_counter++; if (pit_counter >= hertz / 1000) { pit_counter = 0; clock_num_ms_ticks++; } - switch_task(); + switch_task(1); } void pit_install(void) { - install_handler(int_clock, INT_32_INTERRUPT_GATE(0x0), 0x20); + install_handler(int_clock, INT_32_INTERRUPT_GATE(0x3), 0x20); } diff --git a/kernel/drivers/rtl8139.c b/kernel/drivers/rtl8139.c index dd81533..b07ccef 100644 --- a/kernel/drivers/rtl8139.c +++ b/kernel/drivers/rtl8139.c @@ -3,6 +3,7 @@ #include <cpu/io.h> #include <drivers/pci.h> #include <drivers/rtl8139.h> +#include <ipc.h> #include <mmu.h> #include <network/arp.h> #include <network/ethernet.h> @@ -104,6 +105,9 @@ __attribute__((interrupt)) void rtl8139_handler(void *regs) { } void rtl8139_send_data(u8 *data, u16 data_size) { + kprintf("ipc_write\n"); + ipc_write(0, data, data_size); + /* const struct PCI_DEVICE *device = &rtl8139; // FIXME: It should block or fail if there is too little space for the // buffer @@ -120,7 +124,7 @@ void rtl8139_send_data(u8 *data, u16 data_size) { outl(device->gen.base_mem_io + 0x20 + send_buffers_loop * 4, (u32)virtual_to_physical(send_buffers[send_buffers_loop], NULL)); outl(device->gen.base_mem_io + 0x10 + send_buffers_loop * 4, data_size); - send_buffers_loop += 1; + send_buffers_loop += 1;*/ } void get_mac_address(u8 mac[6]) { diff --git a/kernel/fs/ext2.c b/kernel/fs/ext2.c index cb4a0d4..60800a9 100644 --- a/kernel/fs/ext2.c +++ b/kernel/fs/ext2.c @@ -30,30 +30,39 @@ void get_inode_data_size(int inode_num, u64 *file_size) { } struct BLOCK_CACHE { + u32 usage; u32 block_num; u8 block[1024]; }; -#define NUM_BLOCK_CACHE 30 -struct BLOCK_CACHE cache[NUM_BLOCK_CACHE] = {0}; -u8 last_taken_cache = 0; +#define NUM_BLOCK_CACHE 3000 +struct BLOCK_CACHE *cache; + +u32 cold_cache_hits = 0; void cached_read_block(u32 block, void *address, size_t size, size_t offset) { int free_found = -1; for (int i = 0; i < NUM_BLOCK_CACHE; i++) { if (cache[i].block_num == block) { + cache[i].usage += 1; memcpy(address, cache[i].block + offset, size); return; } - if (0 == cache[i].block_num) + if (0 == cache[i].block_num) { free_found = i; + } } if (-1 == free_found) { - free_found = last_taken_cache; - last_taken_cache++; - if (last_taken_cache >= NUM_BLOCK_CACHE) - last_taken_cache = 0; + u32 min_usage_value = U32_MAX; + int min_index = 0; + for (int i = 0; i < NUM_BLOCK_CACHE; i++) { + if (cache[i].usage < min_usage_value) { + min_usage_value = cache[i].usage; + min_index = i; + } + } + free_found = min_index; } struct BLOCK_CACHE *c = &cache[free_found]; @@ -763,6 +772,7 @@ int ext2_create_file(const char *path, int mode) { vfs_inode_t *ext2_mount(void) { int fd = vfs_open("/dev/sda", O_RDWR, 0); + cache = kcalloc(3000, sizeof(struct BLOCK_CACHE)); // TODO: Can this be done better? Maybe create a seperate function in // the VFS? mount_fd = get_current_task()->file_descriptors[fd]; diff --git a/kernel/halts.c b/kernel/halts.c index b70a4ef..6f60a79 100644 --- a/kernel/halts.c +++ b/kernel/halts.c @@ -13,7 +13,6 @@ int create_disconnect_inode_halt(vfs_inode_t *inode) { return -1; p->disconnect_halt_inode[i] = inode; - return i; } @@ -53,7 +52,6 @@ int create_write_inode_halt(vfs_inode_t *inode) { return -1; p->write_halt_inode[i] = inode; - return i; } diff --git a/kernel/includes/mmu.h b/kernel/includes/mmu.h index 8990bdf..49b4886 100644 --- a/kernel/includes/mmu.h +++ b/kernel/includes/mmu.h @@ -44,6 +44,7 @@ void *mmu_map_frames(void *ptr, size_t s); void mmu_map_physical(void *dst, PageDirectory *d, void *physical, size_t length); void mmu_free_pages(void *a, u32 n); +void *mmu_map_user_frames(void *const ptr, size_t s); void flush_tlb(void); void paging_init(u64 memsize); diff --git a/kernel/includes/syscalls.h b/kernel/includes/syscalls.h index cdf4f5a..ee3e417 100644 --- a/kernel/includes/syscalls.h +++ b/kernel/includes/syscalls.h @@ -7,10 +7,17 @@ #include <typedefs.h> #include <types.h> +void syscall_outw(u16 port, u16 word); +u32 syscall_inl(u16 port); +void syscall_outl(u16 port, u32 l); + int syscall_ipc_register_endpoint(u32 endpoint); int syscall_ipc_read(u8 *buffer, u32 length, u32 *sender_pid); int syscall_ipc_write(int ipc_id, u8 *buffer, u32 length); int syscall_ipc_write_to_process(int pid, u8 *buffer, u32 length); +u32 syscall_map_frames(u32 address, u32 size); +u32 syscall_virtual_to_physical(u32 virtual); +int syscall_install_irq(void (*irq_handler)(), u8 irq); typedef struct SYS_ACCEPT_PARAMS { int socket; diff --git a/kernel/init/kernel.c b/kernel/init/kernel.c index 24da680..67aab12 100644 --- a/kernel/init/kernel.c +++ b/kernel/init/kernel.c @@ -94,7 +94,7 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr, add_keyboard(); add_mouse(); - rtl8139_init(); + // rtl8139_init(); display_driver_init(mb); add_vbe_device(); @@ -105,6 +105,8 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr, kprintf("exec() failed\n"); } } - for (;;) - ; + for (;;) { + asm("sti"); + switch_task(0); + } } diff --git a/kernel/ipc.c b/kernel/ipc.c index 3422cc7..6367511 100644 --- a/kernel/ipc.c +++ b/kernel/ipc.c @@ -47,9 +47,12 @@ int ipc_read(u8 *buffer, u32 length, u32 *sender_pid) { for (;;) { ipc_message = &handler->data[read_ptr]; if (!ipc_message->is_used) { - asm("sti"); - continue; + return 0; +// kprintf("switch\n"); +// switch_task(); +// continue; } + kprintf("breaking out\n"); break; } ipc_message->is_used = 0; diff --git a/kernel/poll.c b/kernel/poll.c index 211faf7..ee92a8c 100644 --- a/kernel/poll.c +++ b/kernel/poll.c @@ -21,7 +21,7 @@ int poll(struct pollfd *fds, size_t nfds, int timeout) { disconnect_locks[i] = create_disconnect_fdhalt(f); } - switch_task(); + switch_task(1); for (size_t i = 0; i < nfds; i++) { if (fds[i].fd < 0) diff --git a/kernel/process.s b/kernel/process.s index 24e1869..9f8ee71 100644 --- a/kernel/process.s +++ b/kernel/process.s @@ -31,3 +31,117 @@ copy_page_physical: popf pop ebx ret + + +.extern current_task_TCB +.global TCB + +.section .data + + .struct 0 +TCB: +TCB.ESP: + .space 4 +TCB.CR3: + .space 4 +TCB.ESP0: + .space 4 + +.global switch_to_task +.global insert_eip_on_stack +.global internal_fork +.extern create_process + +.section .text + +internal_fork: + push ebp + mov ecx, esp + mov ebp, esp + + mov eax, [ebp+8] # current_task + + lea edx, after_internal_fork + push edx + push ecx + push eax + call create_process + add esp, 0xC + + pop ebp + ret +after_internal_fork: + pop ebp + mov eax, 0 + ret + +insert_eip_on_stack: + push ebp + mov ebp, esp + mov eax, [ebp+8] # cr3 + mov ecx, [ebp+8+4] # address + mov edx, [ebp+8+4+4] # value + + push ebx + + mov ebx, cr3 + mov cr3, eax + + mov [ecx], edx + + mov cr3, ebx + + pop ebx + pop ebp + ret + +# C declaration: +# void switch_to_task(thread_control_block *next_thread); +# +# WARNING: Caller is expected to disable IRQs before calling, and enable IRQs again after function returns + +switch_to_task: + cli + + # Save previous task's state + + # Notes: + # For cdecl; EAX, ECX, and EDX are already saved by the caller and don't need to be saved again + # EIP is already saved on the stack by the caller's "CALL" instruction + # The task isn't able to change CR3 so it doesn't need to be saved + # Segment registers are constants (while running kernel code) so they don't need to be saved + + push ebx + push esi + push edi + push ebp + + mov edi,[current_task_TCB] # edi = address of the previous task's "thread control block" + mov [edi+TCB.ESP],esp # Save ESP for previous task's kernel stack in the thread's TCB + + # Load next task's state + + mov esi,[esp+(4+1)*4] # esi = address of the next task's "thread control block" (parameter passed on stack) + mov [current_task_TCB],esi # Current task's TCB is the next task TCB + + mov esp,[esi+TCB.ESP] # Load ESP for next task's kernel stack from the thread's TCB + mov eax,[esi+TCB.CR3] # eax = address of page directory for next task + mov ebx,[esi+TCB.ESP0] # ebx = address for the top of the next task's kernel stack +# mov [TSS.ESP0],ebx # Adjust the ESP0 field in the TSS (used by CPU for for CPL=3 -> CPL=0 privilege level changes) +# mov ecx,cr3 # ecx = previous task's virtual address space + +# FIXME: This branch gets a from the assembler, something about "relaxed branches". +# this branch would probably not be used anyway but should be checked on later anyway. +# cmp eax,ecx # Does the virtual address space need to being changed? + +# je .doneVAS # no, virtual address space is the same, so don't reload it and cause TLB flushes + mov cr3,eax # yes, load the next task's virtual address space +#.doneVAS: + + pop ebp + pop edi + pop esi + pop ebx + + sti + ret # Load next task's EIP from its kernel stack diff --git a/kernel/sched/scheduler.c b/kernel/sched/scheduler.c index e2e4aa0..8019e5a 100644 --- a/kernel/sched/scheduler.c +++ b/kernel/sched/scheduler.c @@ -6,6 +6,11 @@ #include <errno.h> #include <fs/vfs.h> +// FIXME: Use the process_t struct instead or keep this contained in it. +TCB *current_task_TCB; + +void switch_to_task(TCB *next_thread); + #define STACK_LOCATION ((void *)0x90000000) #define STACK_SIZE 0x80000 #define HEAP_SIZE 0x400000 @@ -39,7 +44,10 @@ void set_signal_handler(int sig, void (*handler)(int)) { current_task->signal_handlers[sig] = handler; } -process_t *create_process(process_t *p) { +void insert_eip_on_stack(u32 cr3, u32 address, u32 value); + +process_t *create_process(process_t *p, u32 esp, u32 eip) { + kprintf("CREATE_PROCESS\n"); process_t *r; r = kcalloc(1, sizeof(process_t)); r->dead = 0; @@ -61,8 +69,31 @@ process_t *create_process(process_t *p) { r->parent = p; r->child = NULL; r->halt_list = NULL; + r->interrupt_handler = NULL; + + r->tcb = kcalloc(1, sizeof(struct TCB)); + kprintf("r->tcb: %x\n", r->tcb); + kprintf("r->cr3: %x\n", r->cr3); + kprintf("p: %x\n", p); + r->tcb->CR3 = r->cr3->physical_address; + + // Temporarily switch to the page directory to be able to place the + // "entry_instruction_pointer" onto the stack. + + if (esp) { + esp -= 4; + insert_eip_on_stack(r->cr3->physical_address, esp, eip); + esp -= 4; + insert_eip_on_stack(r->cr3->physical_address, esp, 0x1337); + esp -= 4; + insert_eip_on_stack(r->cr3->physical_address, esp, 0x1488); + esp -= 4; + esp -= 4; + insert_eip_on_stack(r->cr3->physical_address, esp, 0xF00DBABE); + r->tcb->ESP = esp; + } - mmu_allocate_region((void *)(0x80000000 - 0x1000), 0x1000, MMU_FLAG_RW, + mmu_allocate_region((void *)(0x80000000 - 0x8000), 0x8000, MMU_FLAG_RW, r->cr3); r->signal_handler_stack = 0x80000000; @@ -109,7 +140,11 @@ int get_free_fd(process_t *p, int allocate) { } void tasking_init(void) { - current_task = ready_queue = create_process(NULL); + current_task = ready_queue = create_process(NULL, 0, 0); + current_task_TCB = current_task->tcb; + current_task->tcb->CR3 = current_task->cr3->physical_address; + // // Switch to itself to update the internal values + // switch_task(0); } int i = 0; @@ -164,7 +199,7 @@ void exit(int status) { } current_task->dead = 1; // This function will enable interrupts - switch_task(); + switch_task(1); } u32 setup_stack(u32 stack_pointer, int argc, char **argv) { @@ -231,7 +266,7 @@ int exec(const char *filename, char **argv) { ASSERT_NOT_REACHED; return 0; } - +/* int fork(void) { process_t *parent_task = (process_t *)current_task; @@ -255,12 +290,36 @@ int fork(void) { new_task->eip = eip; asm("\ - mov %%esp, %0;\ - mov %%ebp, %1;" + mov %%esp, %0;\ + mov %%ebp, %1;" : "=r"(new_task->esp), "=r"(new_task->ebp)); + asm("\ + mov %%esp, %0;" + : "=r"(new_task->tcb->ESP)); asm("sti"); return new_task->pid; } +*/ + +process_t *internal_fork(process_t *parent); +int fork(void) { + process_t *new_task; + new_task = internal_fork(current_task); + if (NULL == new_task) { + return 0; + } + + process_t *tmp_task = (process_t *)ready_queue; + for (; tmp_task->next;) + tmp_task = tmp_task->next; + + tmp_task->next = new_task; + + new_task->child_rc = -1; + new_task->parent = current_task; + current_task->child = new_task; + return new_task->pid; +} int is_halted(process_t *process) { for (int i = 0; i < 2; i++) @@ -292,7 +351,7 @@ process_t *next_task(process_t *c) { return c; } -int task_save_state(void) { +int task_save_state() { asm("mov %%esp, %0" : "=r"(current_task->esp)); asm("mov %%ebp, %0" : "=r"(current_task->ebp)); @@ -329,44 +388,19 @@ int kill(pid_t pid, int sig) { } void jump_signal_handler(void *func, u32 esp); -void switch_task() { - if (!current_task) - return; - if (0 == task_save_state()) { +void none_save_switch() { +} + +void switch_task(int save) { + if (!current_task) { return; } current_task = next_task((process_t *)current_task); - active_directory = current_task->cr3; - if (current_task->incoming_signal) { - u8 sig = current_task->incoming_signal; - current_task->incoming_signal = 0; - asm("mov %0, %%cr3" ::"r"(current_task->cr3->physical_address)); - - void *handler = current_task->signal_handlers[sig]; - if (9 == sig) { - klog("Task recieved SIGKILL", LOG_NOTE); - exit(0); - } - if (!handler) { - klog("Task recieved unhandeled signal. Killing process.", LOG_WARN); - exit(1); - } - jump_signal_handler(handler, current_task->signal_handler_stack); - } else { - asm(" \ - mov %0, %%esp; \ - mov %1, %%ebp; \ - mov %2, %%ecx; \ - mov %3, %%cr3; \ - mov $0x1, %%eax; \ - jmp *%%ecx" ::"r"(current_task->esp), - "r"(current_task->ebp), "r"(current_task->eip), - "r"(current_task->cr3->physical_address)); - } + switch_to_task(current_task->tcb); } MemoryMap **get_free_map(void) { @@ -378,8 +412,8 @@ MemoryMap **get_free_map(void) { } void *get_free_virtual_memory(size_t length) { - void *n = - (void *)((uintptr_t)(get_current_task()->data_segment_end) + length); + void *n = (void *)((uintptr_t)(get_current_task()->data_segment_end) + + length + 0x1000); void *rc = get_current_task()->data_segment_end; get_current_task()->data_segment_end = align_page(n); diff --git a/kernel/sched/scheduler.h b/kernel/sched/scheduler.h index 17e5d56..01276dc 100644 --- a/kernel/sched/scheduler.h +++ b/kernel/sched/scheduler.h @@ -14,7 +14,7 @@ int fork(void); int exec(const char *filename, char **argv); -void switch_task(); +void switch_task(int save); void tasking_init(void); void exit(int status); @@ -34,14 +34,23 @@ typedef struct { typedef struct Process process_t; +typedef struct TCB { + uint32_t ESP; + uint32_t CR3; + uint32_t ESP0; +} __attribute__((packed)) TCB; + struct Process { u32 pid; char program_name[100]; char current_working_directory[MAX_PATH]; u32 eip, esp, ebp; + u32 saved_eip, saved_esp, saved_ebp; + u32 useresp; u8 incoming_signal; u32 signal_handler_stack; void *signal_handlers[20]; + void *interrupt_handler; PageDirectory *cr3; struct IpcMailbox ipc_mailbox; vfs_fd_t *file_descriptors[100]; @@ -53,6 +62,9 @@ struct Process { void *data_segment_end; process_t *next; process_t *parent; + + TCB *tcb; + // TODO: Create a linkedlist of childs so that the parent process // can do stuff such as reap zombies and get status. process_t *child; @@ -66,4 +78,5 @@ bool get_task_from_pid(u32 pid, process_t **out); process_t *get_current_task(void); int get_free_fd(process_t *p, int allocate); void free_process(void); +void *get_free_virtual_memory(size_t length); #endif diff --git a/kernel/syscalls/msleep.c b/kernel/syscalls/msleep.c index a752d94..47cc785 100644 --- a/kernel/syscalls/msleep.c +++ b/kernel/syscalls/msleep.c @@ -5,5 +5,5 @@ void syscall_msleep(u32 ms) { get_current_task()->sleep_until = pit_num_ms() + ms; - switch_task(); + switch_task(1); } diff --git a/meta/debug.sh b/meta/debug.sh index d1eeedb..2cb3d90 100755 --- a/meta/debug.sh +++ b/meta/debug.sh @@ -2,5 +2,6 @@ scriptdir="$(dirname "$0")" cd "$scriptdir" cd .. -qemu-system-i386 -no-reboot -no-shutdown -serial file:./logs/serial.log -hda ./meta/ext2.img -m 1G -cdrom ./kernel/myos.iso -s -S & +#qemu-system-i386 -no-reboot -no-shutdown -serial file:./logs/serial.log -hda ./meta/ext2.img -m 1G -cdrom ./kernel/myos.iso -s -S & +qemu-system-i386 -netdev user,id=n0,hostfwd=tcp:127.0.0.1:6001-:6000 -device rtl8139,netdev=n0 -object filter-dump,id=id,netdev=n0,file=./logs/netout -no-reboot -no-shutdown -chardev stdio,id=char0,logfile=./logs/serial.log,signal=off -serial chardev:char0 -drive id=disk,file=./meta/ext2.img,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -m 512M -cdrom ./kernel/myos.iso -s -S & gdb -x .gdbinit diff --git a/meta/userland.sh b/meta/userland.sh index 94ab441..de6cbd5 100755 --- a/meta/userland.sh +++ b/meta/userland.sh @@ -15,8 +15,10 @@ make -C ./userland/windowserver make -C ./userland/test make -C ./userland/minibox make -C ./userland/libppm +make -C ./userland/rtl8139 mkdir sysroot +sudo cp ./userland/rtl8139/rtl8139 ./sysroot/rtl8139 sudo cp ./userland/libppm/ppm ./sysroot/ppm sudo cp ./userland/sh/sh ./sysroot/sh sudo cp ./userland/terminal/term ./sysroot/term diff --git a/userland/libc/include/syscall.h b/userland/libc/include/syscall.h index b50c061..72f781d 100644 --- a/userland/libc/include/syscall.h +++ b/userland/libc/include/syscall.h @@ -45,6 +45,13 @@ #define SYS_IPC_READ 36 #define SYS_IPC_WRITE 37 #define SYS_IPC_WRITE_TO_PROCESS 38 +#define SYS_OUTW 39 +#define SYS_INL 40 +#define SYS_OUTL 41 +#define SYS_MAP_FRAMES 42 +#define SYS_VIRTUAL_TO_PHYSICAL 43 +#define SYS_INSTALL_IRQ 44 +#define SYS_TMP_KERNEL_HANDLE_PACKET 45 int syscall(uint32_t eax, uint32_t ebx, uint32_t ecx, uint32_t edx, uint32_t esi, uint32_t edi); diff --git a/userland/libppm/ppm.c b/userland/libppm/ppm.c index 030c68d..9013e27 100644 --- a/userland/libppm/ppm.c +++ b/userland/libppm/ppm.c @@ -64,36 +64,47 @@ int load_ppm6_file(FILE *fp, const struct PPM_IMAGE *img, uint32_t buf_width, printf("end malloc\n"); printf("fread"); - int rc = fread(rgb, 3, n_pixels, fp); + const int rc = fread(rgb, 3, n_pixels, fp); if (0 == rc) return 0; printf("end fread"); uint32_t *p = rgb; + u32 buf_size = buf_height * buf_width; if (1 == modifier) { - for (; rc--; p = ((uint8_t *)p) + 3) { - uint32_t v = *p; - buffer[cy * buf_width + cx] = - ((v & 0xFF) << 16) | ((v & 0xFF00)) | ((v & 0xFF0000) >> 16); + for (int i = 0; i < rc && i < buf_size; i++, p = ((uint8_t *)p) + 3) { + if (cx > buf_width) { + i--; + } else { + uint32_t v = *p; + buffer[cy * buf_width + cx] = + ((v & 0xFF) << 16) | ((v & 0xFF00)) | ((v & 0xFF0000) >> 16); + } cx++; if (cx == img->width) { cx = 0; cy++; + i--; continue; } } } else { - for (; rc--; p = ((uint8_t *)p) + 3) { + for (int i = 0; i < rc && i < buf_size; i++, p = ((uint8_t *)p) + 3) { ((uint8_t *)p)[0] *= modifier; ((uint8_t *)p)[1] *= modifier; ((uint8_t *)p)[2] *= modifier; - uint32_t v = *p; - buffer[cy * buf_width + cx] = - ((v & 0xFF) << 16) | ((v & 0xFF00)) | ((v & 0xFF0000) >> 16); + if (cx > buf_width) { + i--; + } else { + uint32_t v = *p; + buffer[cy * buf_width + cx] = + ((v & 0xFF) << 16) | ((v & 0xFF00)) | ((v & 0xFF0000) >> 16); + } cx++; if (cx == img->width) { cx = 0; cy++; + i--; continue; } } |