From 606fc37e37838f82f5300694a2e832046278728e Mon Sep 17 00:00:00 2001 From: Lucia Ceionia Date: Mon, 19 Sep 2022 16:06:01 -0500 Subject: [PATCH] 'Better' task management, needs more testing --- Makefile | 2 +- bochsrc | 3 +-- entry.nasm | 16 +++++----------- handler.nasm | 9 +++------ interrupt.c | 51 ++++++++++++++++++++++++++------------------------- kernel.c | 39 ++++++++++++++++++++++++++------------- task.nasm | 46 ++++++++++++++++++++++++++++++++++++++++++++++ tss.c | 9 ++++++++- tss.h | 2 ++ v86.nasm | 42 +++++++++++++++--------------------------- 10 files changed, 133 insertions(+), 86 deletions(-) create mode 100644 task.nasm create mode 100644 tss.h diff --git a/Makefile b/Makefile index 856f62c..47a2591 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -objects = entry.o kernel.o handler.o interrupt.o v86.o print.o +objects = entry.o kernel.o task.o handler.o interrupt.o v86.o print.o tss.o CFLAGS = -target "i686-elf" -m32 -mgeneral-regs-only -ffreestanding -march=pentium-m -fno-stack-protector -nostdlib -c %.o: %.nasm diff --git a/bochsrc b/bochsrc index 9e069bf..f496470 100644 --- a/bochsrc +++ b/bochsrc @@ -1,6 +1,5 @@ # configuration file generated by Bochs display_library: x, options="gui_debug" -#magic_break: enabled=1 plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, iodebug=true, pcidev=false, usb_uhci=false config_interface: textconfig display_library: x @@ -32,7 +31,7 @@ vga: extension=vbe, update_freq=5, realtime=1, ddc=builtin cpu: count=1:1:1, ips=4000000, quantum=16, model=core_duo_t2400_yonah, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 print_timestamps: enabled=0 debugger_log: - -magic_break: enabled=0 +magic_break: enabled=1 port_e9_hack: enabled=0 private_colormap: enabled=0 clock: sync=none, time0=local, rtc_sync=0 diff --git a/entry.nasm b/entry.nasm index 80577af..aa934de 100644 --- a/entry.nasm +++ b/entry.nasm @@ -76,17 +76,9 @@ global jmp_usermode_test jmp_usermode_test: pop eax ; return address mov ebp, esp ; return stack -push ss -push ebp -pushfd -push cs -push eax ; return address -push ds ; other segs, pop -push es ; before iret -push fs ; in exit handler -push gs -mov dword [0x20004], esp ; tss ESP0 -mov ax, 0x20 | 3 +call save_current_task +mov esp, 0x500000 ; usermode stack +mov eax, 0x20 | 3 mov ds, ax mov es, ax mov fs, ax @@ -99,6 +91,8 @@ push 0x18 | 3 push user_test iret +extern save_current_task + global flushTSS flushTSS: mov ax, 0x28 diff --git a/handler.nasm b/handler.nasm index 4675e22..83f192a 100644 --- a/handler.nasm +++ b/handler.nasm @@ -35,12 +35,9 @@ movzx eax, word [eax] cmp eax, 0x30CD ; int 0x30 jne gpf_unhandled pop eax ; return value -mov esp, dword [0x20004] ; return info -pop gs -pop fs -pop es -pop ds -iret ; return to original caller +jmp return_prev_task + +extern return_prev_task scancodesToAscii: db 0, 0 ; 0x00 - 0x01 db "1234567890" ; 0x02 - 0x0B diff --git a/interrupt.c b/interrupt.c index 394221f..81448e5 100644 --- a/interrupt.c +++ b/interrupt.c @@ -87,6 +87,8 @@ extern void real_test(); __attribute((__no_caller_saved_registers__)) extern void kbd_wait(); extern void jmp_usermode_test(); +__attribute((__no_caller_saved_registers__)) +extern void return_prev_task(); #define VALID_FLAGS 0xDFF __attribute__ ((interrupt)) void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code) { @@ -100,17 +102,17 @@ void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code) { stack32 = (uint32_t*)stack; char *vga = (char*)0xb8000 + (160 * 10); - vga[0] = 'I'; vga[2] = 'P'; int_printWord(frame->eip, (uint16_t*)&vga[4]); vga += 14; - vga[0] = 'C'; vga[2] = 'S'; int_printWord(frame->cs, (uint16_t*)&vga[4]); vga += 14; - vga[0] = 'F'; vga[2] = 'L'; int_printDword(frame->eflags, (uint16_t*)&vga[4]); vga += 14; - vga = (char*)0xb8000 + (160 * 11); - vga[0] = 'S'; vga[2] = 'P'; int_printWord(frame->esp, (uint16_t*)&vga[4]); vga += 14; - vga[0] = 'S'; vga[2] = 'S'; int_printWord(frame->ss, (uint16_t*)&vga[4]); vga += 14; - vga = (char*)0xb8000 + (160 * 12); - vga[0] = 'E'; vga[2] = 'S'; int_printWord(frame->es, (uint16_t*)&vga[4]); vga += 14; - vga[0] = 'D'; vga[2] = 'S'; int_printWord(frame->ds, (uint16_t*)&vga[4]); vga += 14; - vga[0] = 'F'; vga[2] = 'S'; int_printWord(frame->fs, (uint16_t*)&vga[4]); vga += 14; - vga[0] = 'G'; vga[2] = 'S'; int_printWord(frame->gs, (uint16_t*)&vga[4]); vga += 14; + //vga[0] = 'I'; vga[2] = 'P'; int_printWord(frame->eip, (uint16_t*)&vga[4]); vga += 14; + //vga[0] = 'C'; vga[2] = 'S'; int_printWord(frame->cs, (uint16_t*)&vga[4]); vga += 14; + //vga[0] = 'F'; vga[2] = 'L'; int_printDword(frame->eflags, (uint16_t*)&vga[4]); vga += 14; + //vga = (char*)0xb8000 + (160 * 11); + //vga[0] = 'S'; vga[2] = 'P'; int_printWord(frame->esp, (uint16_t*)&vga[4]); vga += 14; + //vga[0] = 'S'; vga[2] = 'S'; int_printWord(frame->ss, (uint16_t*)&vga[4]); vga += 14; + //vga = (char*)0xb8000 + (160 * 12); + //vga[0] = 'E'; vga[2] = 'S'; int_printWord(frame->es, (uint16_t*)&vga[4]); vga += 14; + //vga[0] = 'D'; vga[2] = 'S'; int_printWord(frame->ds, (uint16_t*)&vga[4]); vga += 14; + //vga[0] = 'F'; vga[2] = 'S'; int_printWord(frame->fs, (uint16_t*)&vga[4]); vga += 14; + //vga[0] = 'G'; vga[2] = 'S'; int_printWord(frame->gs, (uint16_t*)&vga[4]); vga += 14; //vga[2]++; //printDword(frame, &vga[20]); @@ -128,7 +130,6 @@ void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code) { // vga += (sizeof(uint8_t)*2)*2; //} vga = (char*)0xb8000 + (160*3); - uint32_t *tss_esp0 = (uint32_t*)0x20004; for(;;) { switch (ip[0]) { case 0x66: // O32 @@ -177,7 +178,7 @@ void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code) { vga[0] = 'I'; vga[2]++; if (vga[2] < '0') vga[2] = '0'; switch (ip[1]) { case 0x30: - asm ("mov %%eax, %%esp\nret"::"a"(*tss_esp0)); + return_prev_task(); for(;;); case 0x3: kbd_wait(); @@ -219,18 +220,18 @@ void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code) { } } done:; - vga = (char*)0xb8000 + (160 * 13); - vga[0] = 'I'; vga[2] = 'P'; int_printWord(frame->eip, (uint16_t*)&vga[4]); vga += 14; - vga[0] = 'C'; vga[2] = 'S'; int_printWord(frame->cs, (uint16_t*)&vga[4]); vga += 14; - vga[0] = 'F'; vga[2] = 'L'; int_printDword(frame->eflags, (uint16_t*)&vga[4]); vga += 14; - vga = (char*)0xb8000 + (160 * 14); - vga[0] = 'S'; vga[2] = 'P'; int_printWord(frame->esp, (uint16_t*)&vga[4]); vga += 14; - vga[0] = 'S'; vga[2] = 'S'; int_printWord(frame->ss, (uint16_t*)&vga[4]); vga += 14; - vga = (char*)0xb8000 + (160 * 15); - vga[0] = 'E'; vga[2] = 'S'; int_printWord(frame->es, (uint16_t*)&vga[4]); vga += 14; - vga[0] = 'D'; vga[2] = 'S'; int_printWord(frame->ds, (uint16_t*)&vga[4]); vga += 14; - vga[0] = 'F'; vga[2] = 'S'; int_printWord(frame->fs, (uint16_t*)&vga[4]); vga += 14; - vga[0] = 'G'; vga[2] = 'S'; int_printWord(frame->gs, (uint16_t*)&vga[4]); vga += 14; + //vga = (char*)0xb8000 + (160 * 13); + //vga[0] = 'I'; vga[2] = 'P'; int_printWord(frame->eip, (uint16_t*)&vga[4]); vga += 14; + //vga[0] = 'C'; vga[2] = 'S'; int_printWord(frame->cs, (uint16_t*)&vga[4]); vga += 14; + //vga[0] = 'F'; vga[2] = 'L'; int_printDword(frame->eflags, (uint16_t*)&vga[4]); vga += 14; + //vga = (char*)0xb8000 + (160 * 14); + //vga[0] = 'S'; vga[2] = 'P'; int_printWord(frame->esp, (uint16_t*)&vga[4]); vga += 14; + //vga[0] = 'S'; vga[2] = 'S'; int_printWord(frame->ss, (uint16_t*)&vga[4]); vga += 14; + //vga = (char*)0xb8000 + (160 * 15); + //vga[0] = 'E'; vga[2] = 'S'; int_printWord(frame->es, (uint16_t*)&vga[4]); vga += 14; + //vga[0] = 'D'; vga[2] = 'S'; int_printWord(frame->ds, (uint16_t*)&vga[4]); vga += 14; + //vga[0] = 'F'; vga[2] = 'S'; int_printWord(frame->fs, (uint16_t*)&vga[4]); vga += 14; + //vga[0] = 'G'; vga[2] = 'S'; int_printWord(frame->gs, (uint16_t*)&vga[4]); vga += 14; } extern void timerHandler(); diff --git a/kernel.c b/kernel.c index aa1e028..751cdf6 100644 --- a/kernel.c +++ b/kernel.c @@ -3,7 +3,7 @@ #include "print.h" #include "interrupt.h" -#include "tss.c" +#include "tss.h" typedef unsigned short word; @@ -54,23 +54,33 @@ void print_cr4() { __attribute((__no_caller_saved_registers__)) extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip); -extern void v86Code(); +extern void v86Test(); +extern void v86GfxMode(); __attribute((__no_caller_saved_registers__)) extern char *jmp_usermode_test(); /* Real Mode Accessible (First MB) - 00000 - 02000 IVT - 01000 - 04000 Paging - 04000 - 07C00 Free - 07C00 - 08000 Boot - 08000 - 20000 Kernel Code - 20000 - 22080 TSS - 80000 - 90000 Real Mode Stack - 90000 - A0000 Free - A0000 - FFFFF BIOS Area + 00000 - 00400 IVT (1kB) + 00400 - 01000 Unused (3kB) + 01000 - 04000 Paging (12kB) + 04000 - 07C00 Free (15kB) + 07C00 - 08000 Boot (512B) + 08000 - 20000 Kernel Code (96kB) + 20000 - 20080 TSS (128B) + 20080 - 22080 TSS IOMAP (8kB) + 22080 - 22400 Unused (896B) + 22400 - 23000 Free (3kB) + 23000 - 80000 Free (372kB) + 80000 - 90000 Real Mode Stack (64kB) + 90000 - A0000 Free (64kB) + A0000 - FFFFF BIOS Area (384kB) Protected Only (1MB+) -100000 - Free +100000 - 300000 Free (2mB) +300000 - 310000 Task Stack (64kB) +310000 - 320000 Interrupt Stack (64kB) +320000 - 400000 Kernel Stack (896kB) +400000 - 500000 Usermode Stack (1mB) */ void start() { @@ -107,9 +117,12 @@ void start() { print_cr0(); print_cr3(); print_cr4(); - FARPTR v86_entry = i386LinearToFp(v86Code); + FARPTR v86_entry = i386LinearToFp(v86Test); + enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry)); + v86_entry = i386LinearToFp(v86GfxMode); enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry)); char *vga = jmp_usermode_test(); + //asm ("xchgw %bx, %bx"); for (int i = 0; i < 320; i++) { vga[i] = i; diff --git a/task.nasm b/task.nasm new file mode 100644 index 0000000..c575eee --- /dev/null +++ b/task.nasm @@ -0,0 +1,46 @@ +task_ptr: equ (0x310000-4) + +global save_current_task +save_current_task: +push ebx +mov ebx, esp +mov esp, dword [task_ptr] ; load current task pointer +push ss +push ebp ; return stack +pushfd +push cs +push eax ; return address +push ds ; other segs, pop +push es ; before iret +push fs ; in exit handler +push gs +mov dword [task_ptr], esp ; save new task pointer +mov esp, ebx +pop ebx +ret + +global return_prev_task +return_prev_task: +mov edi, eax ; save for later +mov esi, dword [task_ptr] ; load current task pointer +add dword [task_ptr], 36 ; adjust to last task pointer +mov eax, [esi+0] ; gs +mov gs, ax +mov eax, [esi+4] ; fs +mov fs, ax +mov eax, [esi+8] ; es +mov es, ax +mov ebx, [esi+16] ; eip +mov ecx, [esi+20] ; cs +mov edx, [esi+24] ; eflags +; SS:ESP <- return stack +mov esp, [esi+28] ; esp +mov eax, [esi+32] ; ss +mov ss, ax +mov eax, [esi+12] ; ds +mov ds, ax +push edx ; eflags +push ecx ; cs +push ebx ; eip +mov eax, edi ; restore return value +iret diff --git a/tss.c b/tss.c index 6bf164b..3b2e5c5 100644 --- a/tss.c +++ b/tss.c @@ -1,5 +1,7 @@ #include +#include "tss.h" + struct __attribute__((__packed__)) tss_entry_struct { uint32_t prev_tss; uint32_t esp0; @@ -35,8 +37,13 @@ void write_tss() { for (int i = 0; i < 0x2080; i++) ((uint8_t*)tss_data)[i] = 0; tss_data->ss0 = 0x10; - tss_data->esp0 = 0x400000; + tss_data->esp0 = 0x320000; tss_data->iomap_base = 0x80; + + // not technically TSS but set up task pointer + uint32_t *current_task_ptr = (uint32_t*)(0x310000-4); + *current_task_ptr = 0x310000-40; // each task is 9 dwords, plus 1 for pointer + /* TODO setup null recovery task at start */ } extern void flushTSS(); diff --git a/tss.h b/tss.h new file mode 100644 index 0000000..42a05ab --- /dev/null +++ b/tss.h @@ -0,0 +1,2 @@ +#pragma once +void setup_tss(); diff --git a/v86.nasm b/v86.nasm index 1ce84fe..091d9a1 100644 --- a/v86.nasm +++ b/v86.nasm @@ -26,8 +26,8 @@ call real_hexprint mov ax, dx call real_hexprint ret -extern v86Code -v86Code: +global v86Test +v86Test: mov ax, 0xb814 mov es, ax mov di, 20 @@ -41,43 +41,31 @@ mov ax, cs call real_printword .loop: inc byte [0] -;mov ax, 0x1111 -;mov ds, ax -;mov ax, 0x2222 -;mov es, ax -;mov ax, 0x3333 -;mov fs, ax -;mov ax, 0x4444 -;mov gs, ax -;mov ax, 0x5555 -;mov ss, ax -;mov ax, 0x6666 -;mov sp, ax int 3 int 3 -;jmp .loop -mov ax, 0x13 -int 0x10 int 0x30 ; exit jmp $ -extern real_test -real_test: -nop -nop -nop +global v86GfxMode +v86GfxMode: +mov ax, 0x13 +int 0x10 +int 0x30 jmp $ [BITS 32] ; extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip); global enter_v86 enter_v86: +pop eax mov ebp, esp ; save stack pointer -mov dword [0x20004], ebp ; tss ESP0 -push dword [ebp+4] ; ss -push dword [ebp+8] ; esp +call save_current_task +push dword [ebp+0] ; ss +push dword [ebp+4] ; esp pushfd ; eflags or dword [esp], (1 << 17) ; set VM flags ;or dword [esp], (3 << 12) ; IOPL 3 -push dword [ebp+12] ; cs -push dword [ebp+16] ; eip +push dword [ebp+8] ; cs +push dword [ebp+12] ; eip iret +; return address in eax, return stack in ebp +extern save_current_task