'Better' task management, needs more testing

This commit is contained in:
Lucia Ceionia 2022-09-19 16:06:01 -05:00
parent c80a420da0
commit 606fc37e37
10 changed files with 133 additions and 86 deletions

View File

@ -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 CFLAGS = -target "i686-elf" -m32 -mgeneral-regs-only -ffreestanding -march=pentium-m -fno-stack-protector -nostdlib -c
%.o: %.nasm %.o: %.nasm

View File

@ -1,6 +1,5 @@
# configuration file generated by Bochs # configuration file generated by Bochs
display_library: x, options="gui_debug" 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 plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, iodebug=true, pcidev=false, usb_uhci=false
config_interface: textconfig config_interface: textconfig
display_library: x 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 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 print_timestamps: enabled=0
debugger_log: - debugger_log: -
magic_break: enabled=0 magic_break: enabled=1
port_e9_hack: enabled=0 port_e9_hack: enabled=0
private_colormap: enabled=0 private_colormap: enabled=0
clock: sync=none, time0=local, rtc_sync=0 clock: sync=none, time0=local, rtc_sync=0

View File

@ -76,17 +76,9 @@ global jmp_usermode_test
jmp_usermode_test: jmp_usermode_test:
pop eax ; return address pop eax ; return address
mov ebp, esp ; return stack mov ebp, esp ; return stack
push ss call save_current_task
push ebp mov esp, 0x500000 ; usermode stack
pushfd mov eax, 0x20 | 3
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
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
@ -99,6 +91,8 @@ push 0x18 | 3
push user_test push user_test
iret iret
extern save_current_task
global flushTSS global flushTSS
flushTSS: flushTSS:
mov ax, 0x28 mov ax, 0x28

View File

@ -35,12 +35,9 @@ movzx eax, word [eax]
cmp eax, 0x30CD ; int 0x30 cmp eax, 0x30CD ; int 0x30
jne gpf_unhandled jne gpf_unhandled
pop eax ; return value pop eax ; return value
mov esp, dword [0x20004] ; return info jmp return_prev_task
pop gs
pop fs extern return_prev_task
pop es
pop ds
iret ; return to original caller
scancodesToAscii: db 0, 0 ; 0x00 - 0x01 scancodesToAscii: db 0, 0 ; 0x00 - 0x01
db "1234567890" ; 0x02 - 0x0B db "1234567890" ; 0x02 - 0x0B

View File

@ -87,6 +87,8 @@ extern void real_test();
__attribute((__no_caller_saved_registers__)) __attribute((__no_caller_saved_registers__))
extern void kbd_wait(); extern void kbd_wait();
extern void jmp_usermode_test(); extern void jmp_usermode_test();
__attribute((__no_caller_saved_registers__))
extern void return_prev_task();
#define VALID_FLAGS 0xDFF #define VALID_FLAGS 0xDFF
__attribute__ ((interrupt)) __attribute__ ((interrupt))
void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code) { 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; stack32 = (uint32_t*)stack;
char *vga = (char*)0xb8000 + (160 * 10); char *vga = (char*)0xb8000 + (160 * 10);
vga[0] = 'I'; vga[2] = 'P'; int_printWord(frame->eip, (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] = '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[0] = 'F'; vga[2] = 'L'; int_printDword(frame->eflags, (uint16_t*)&vga[4]); vga += 14;
vga = (char*)0xb8000 + (160 * 11); //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] = '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[0] = 'S'; vga[2] = 'S'; int_printWord(frame->ss, (uint16_t*)&vga[4]); vga += 14;
vga = (char*)0xb8000 + (160 * 12); //vga = (char*)0xb8000 + (160 * 12);
vga[0] = 'E'; vga[2] = 'S'; int_printWord(frame->es, (uint16_t*)&vga[4]); vga += 14; //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] = '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] = '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] = 'G'; vga[2] = 'S'; int_printWord(frame->gs, (uint16_t*)&vga[4]); vga += 14;
//vga[2]++; //vga[2]++;
//printDword(frame, &vga[20]); //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 += (sizeof(uint8_t)*2)*2;
//} //}
vga = (char*)0xb8000 + (160*3); vga = (char*)0xb8000 + (160*3);
uint32_t *tss_esp0 = (uint32_t*)0x20004;
for(;;) { for(;;) {
switch (ip[0]) { switch (ip[0]) {
case 0x66: // O32 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'; vga[0] = 'I'; vga[2]++; if (vga[2] < '0') vga[2] = '0';
switch (ip[1]) { switch (ip[1]) {
case 0x30: case 0x30:
asm ("mov %%eax, %%esp\nret"::"a"(*tss_esp0)); return_prev_task();
for(;;); for(;;);
case 0x3: case 0x3:
kbd_wait(); kbd_wait();
@ -219,18 +220,18 @@ void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code) {
} }
} }
done:; done:;
vga = (char*)0xb8000 + (160 * 13); //vga = (char*)0xb8000 + (160 * 13);
vga[0] = 'I'; vga[2] = 'P'; int_printWord(frame->eip, (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] = '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[0] = 'F'; vga[2] = 'L'; int_printDword(frame->eflags, (uint16_t*)&vga[4]); vga += 14;
vga = (char*)0xb8000 + (160 * 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] = '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[0] = 'S'; vga[2] = 'S'; int_printWord(frame->ss, (uint16_t*)&vga[4]); vga += 14;
vga = (char*)0xb8000 + (160 * 15); //vga = (char*)0xb8000 + (160 * 15);
vga[0] = 'E'; vga[2] = 'S'; int_printWord(frame->es, (uint16_t*)&vga[4]); vga += 14; //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] = '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] = '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] = 'G'; vga[2] = 'S'; int_printWord(frame->gs, (uint16_t*)&vga[4]); vga += 14;
} }
extern void timerHandler(); extern void timerHandler();

View File

@ -3,7 +3,7 @@
#include "print.h" #include "print.h"
#include "interrupt.h" #include "interrupt.h"
#include "tss.c" #include "tss.h"
typedef unsigned short word; typedef unsigned short word;
@ -54,23 +54,33 @@ void print_cr4() {
__attribute((__no_caller_saved_registers__)) __attribute((__no_caller_saved_registers__))
extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip); 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__)) __attribute((__no_caller_saved_registers__))
extern char *jmp_usermode_test(); extern char *jmp_usermode_test();
/* /*
Real Mode Accessible (First MB) Real Mode Accessible (First MB)
00000 - 02000 IVT 00000 - 00400 IVT (1kB)
01000 - 04000 Paging 00400 - 01000 Unused (3kB)
04000 - 07C00 Free 01000 - 04000 Paging (12kB)
07C00 - 08000 Boot 04000 - 07C00 Free (15kB)
08000 - 20000 Kernel Code 07C00 - 08000 Boot (512B)
20000 - 22080 TSS 08000 - 20000 Kernel Code (96kB)
80000 - 90000 Real Mode Stack 20000 - 20080 TSS (128B)
90000 - A0000 Free 20080 - 22080 TSS IOMAP (8kB)
A0000 - FFFFF BIOS Area 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+) 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() { void start() {
@ -107,9 +117,12 @@ void start() {
print_cr0(); print_cr0();
print_cr3(); print_cr3();
print_cr4(); 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)); enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry));
char *vga = jmp_usermode_test(); char *vga = jmp_usermode_test();
//asm ("xchgw %bx, %bx");
for (int i = 0; i < 320; i++) { for (int i = 0; i < 320; i++) {
vga[i] = i; vga[i] = i;

46
task.nasm Normal file
View File

@ -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

9
tss.c
View File

@ -1,5 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include "tss.h"
struct __attribute__((__packed__)) tss_entry_struct { struct __attribute__((__packed__)) tss_entry_struct {
uint32_t prev_tss; uint32_t prev_tss;
uint32_t esp0; uint32_t esp0;
@ -35,8 +37,13 @@ void write_tss() {
for (int i = 0; i < 0x2080; i++) for (int i = 0; i < 0x2080; i++)
((uint8_t*)tss_data)[i] = 0; ((uint8_t*)tss_data)[i] = 0;
tss_data->ss0 = 0x10; tss_data->ss0 = 0x10;
tss_data->esp0 = 0x400000; tss_data->esp0 = 0x320000;
tss_data->iomap_base = 0x80; 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(); extern void flushTSS();

2
tss.h Normal file
View File

@ -0,0 +1,2 @@
#pragma once
void setup_tss();

View File

@ -26,8 +26,8 @@ call real_hexprint
mov ax, dx mov ax, dx
call real_hexprint call real_hexprint
ret ret
extern v86Code global v86Test
v86Code: v86Test:
mov ax, 0xb814 mov ax, 0xb814
mov es, ax mov es, ax
mov di, 20 mov di, 20
@ -41,43 +41,31 @@ mov ax, cs
call real_printword call real_printword
.loop: .loop:
inc byte [0] 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
int 3 int 3
;jmp .loop
mov ax, 0x13
int 0x10
int 0x30 ; exit int 0x30 ; exit
jmp $ jmp $
extern real_test global v86GfxMode
real_test: v86GfxMode:
nop mov ax, 0x13
nop int 0x10
nop int 0x30
jmp $ jmp $
[BITS 32] [BITS 32]
; extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip); ; extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip);
global enter_v86 global enter_v86
enter_v86: enter_v86:
pop eax
mov ebp, esp ; save stack pointer mov ebp, esp ; save stack pointer
mov dword [0x20004], ebp ; tss ESP0 call save_current_task
push dword [ebp+4] ; ss push dword [ebp+0] ; ss
push dword [ebp+8] ; esp push dword [ebp+4] ; esp
pushfd ; eflags pushfd ; eflags
or dword [esp], (1 << 17) ; set VM flags or dword [esp], (1 << 17) ; set VM flags
;or dword [esp], (3 << 12) ; IOPL 3 ;or dword [esp], (3 << 12) ; IOPL 3
push dword [ebp+12] ; cs push dword [ebp+8] ; cs
push dword [ebp+16] ; eip push dword [ebp+12] ; eip
iret iret
; return address in eax, return stack in ebp
extern save_current_task