Compare commits
1 Commits
main
...
dev-tasks-
Author | SHA1 | Date | |
---|---|---|---|
|
6142b085cd |
4
Makefile
4
Makefile
@ -1,8 +1,8 @@
|
||||
objects = entry.o kernel.o task.o handler.o interrupt.o v86.o print.o tss.o gdt.o\
|
||||
paging.o fault.o tests.o kbd.o helper.o disk.o file.o fs.o dosfs/dosfs.o fs_dos.o\
|
||||
progs.o hexedit.o textedit.o
|
||||
CFLAGS = -target "i686-elf" -m32 -mgeneral-regs-only -ffreestanding\
|
||||
-march=i686 -fno-stack-protector -Wno-int-conversion -nostdlib -c
|
||||
CFLAGS = -target "i386-elf" -m32 -mgeneral-regs-only -ffreestanding\
|
||||
-march=i386 -fno-stack-protector -Wno-int-conversion -nostdlib -c
|
||||
LFLAGS = -Wl,--gc-sections -Wl,--print-gc-sections -m32 -nostartfiles -nostdlib
|
||||
|
||||
ifeq ($(OUTFILE),)
|
||||
|
21
fault.nasm
21
fault.nasm
@ -70,10 +70,13 @@ jmp _fault_coda
|
||||
_gpf_old_ds: dw 0
|
||||
extern get_key
|
||||
extern get_scancode
|
||||
extern get_key_no_wait
|
||||
extern get_scancode_no_wait
|
||||
extern task_ptr
|
||||
extern _enter_v86_internal_no_task
|
||||
extern return_prev_task
|
||||
extern v86Interrupt
|
||||
extern TIMERVAL
|
||||
gpf_handler_32:
|
||||
push eax
|
||||
mov eax, dword [esp+8] ; EIP
|
||||
@ -91,9 +94,25 @@ jne .s1
|
||||
call get_key
|
||||
jmp .return_to_offender
|
||||
.s1: cmp al, 0x01 ; get scancode
|
||||
jne .s86
|
||||
jne .s2
|
||||
call get_scancode
|
||||
jmp .return_to_offender
|
||||
.s2: cmp al, 0x02 ; get key no wait
|
||||
jne .s3
|
||||
call get_key_no_wait
|
||||
jmp .return_to_offender
|
||||
.s3: cmp al, 0x03 ; get scancode no wait
|
||||
jne .s4
|
||||
call get_scancode_no_wait
|
||||
jmp .return_to_offender
|
||||
.s4: cmp al, 0x04 ; get timer
|
||||
jne .s5
|
||||
mov eax, dword [TIMERVAL]
|
||||
jmp .return_to_offender
|
||||
.s5: cmp al, 0x05 ; short wait (hlt)
|
||||
jne .s86
|
||||
hlt
|
||||
jmp .return_to_offender
|
||||
.s86: cmp al, 0x86 ; v86 interrupt call
|
||||
je .v86int
|
||||
cmp ax, 0x86D8 ; get v86 data pointer
|
||||
|
73
handler.nasm
73
handler.nasm
@ -1,71 +1,38 @@
|
||||
oldscancodesToAscii: db 0, 0 ; 0x00 - 0x01
|
||||
db "1234567890" ; 0x02 - 0x0B
|
||||
db "-=" ; 0x0C - 0x0D
|
||||
db 0, 0 ; 0x0E - 0x0F
|
||||
db "qwertyuiop[]" ; 0x10 - 0x1B
|
||||
db 0, 0 ; 0x1C - 0x1D
|
||||
db "asdfghjkl;'`" ; 0x1E - 0x29
|
||||
db 0 ; 0x2A
|
||||
db "\zxcvbnm,./" ; 0x2B - 0x35
|
||||
db 0 ; 0x36
|
||||
db '*' ; 0x37
|
||||
db 0 ; 0x38
|
||||
db ' ' ; 0x39
|
||||
db 'C'
|
||||
scancodesToAsciiEnd:
|
||||
cursorCurrent: dd 0xb8000 + (80*6*2)
|
||||
global oldkeyboardHandler
|
||||
oldkeyboardHandler:
|
||||
push eax
|
||||
push ebx
|
||||
push ds
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
xor eax, eax
|
||||
in al, 0x60
|
||||
cmp eax, 0x3A
|
||||
jg .done
|
||||
mov al, [oldscancodesToAscii+eax]
|
||||
test al, al
|
||||
jz .done
|
||||
mov ebx, [cursorCurrent]
|
||||
mov byte [ebx], al
|
||||
add dword [cursorCurrent], 2
|
||||
mov byte [KBDWAIT], 1
|
||||
.done:
|
||||
mov al, 0x20
|
||||
out 0x20, al
|
||||
pop ds
|
||||
pop ebx
|
||||
pop eax
|
||||
iret
|
||||
|
||||
KBDWAIT: db 0
|
||||
oldkbd_wait:
|
||||
mov byte [KBDWAIT], 0
|
||||
.loop:
|
||||
hlt
|
||||
movzx eax, byte [KBDWAIT]
|
||||
test eax, eax
|
||||
jz .loop
|
||||
ret
|
||||
global PROC_SWITCH
|
||||
PROC_SWITCH: dw 0
|
||||
|
||||
global TIMERVAL
|
||||
global TIMERVAL_FRAC
|
||||
TIMERVAL: dd 0
|
||||
TIMERVAL_FRAC: dd 0
|
||||
global timerHandler
|
||||
timerHandler:
|
||||
push eax
|
||||
push ds
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
;inc byte [(0xb8000 + (80*8*2))]
|
||||
inc dword [TIMERVAL]
|
||||
; Value from PITPgrm
|
||||
add dword [TIMERVAL_FRAC], 0xfffdb8d0
|
||||
adc dword [TIMERVAL], 0
|
||||
mov al, 0x20
|
||||
out 0x20, al
|
||||
; Check task switch
|
||||
movzx eax, word [PROC_SWITCH]
|
||||
test eax, eax
|
||||
jnz task_switch
|
||||
pop ds
|
||||
pop eax
|
||||
iret
|
||||
|
||||
extern save_current_task_int
|
||||
task_switch:
|
||||
mov word [PROC_SWITCH], 0
|
||||
pop ds
|
||||
pop eax
|
||||
call save_current_task_int
|
||||
iret
|
||||
|
||||
|
||||
global picInit
|
||||
picInit:
|
||||
mov al, 0x11 ; initialization sequence
|
||||
|
22
kbd.c
22
kbd.c
@ -1,6 +1,11 @@
|
||||
#include "interrupt.h"
|
||||
#include "kbd.h"
|
||||
|
||||
extern uint16_t PROC_SWITCH;
|
||||
__attribute__((__noreturn__))
|
||||
__attribute__((__no_caller_saved_registers__))
|
||||
extern void ret_current_task_int();
|
||||
|
||||
uint8_t scancodesToAscii[0x3B] =
|
||||
"\0\0" // 0x00 - 0x01
|
||||
"1234567890" // 0x02 - 0x0B
|
||||
@ -69,6 +74,8 @@ void keyboardHandler(struct interrupt_frame *frame) {
|
||||
"mov %%ax, %%ds\n"
|
||||
::"a"(old_ds)
|
||||
);
|
||||
if (key == KEY_F12) PROC_SWITCH = 1;
|
||||
if (key == KEY_F11) ret_current_task_int();
|
||||
}
|
||||
|
||||
__attribute((__no_caller_saved_registers__))
|
||||
@ -106,3 +113,18 @@ uint16_t get_scancode() {
|
||||
return k;
|
||||
}
|
||||
|
||||
__attribute((__no_caller_saved_registers__))
|
||||
uint8_t get_key_no_wait() {
|
||||
uint8_t k = _LSTKEY_ASCII;
|
||||
_LSTKEY_ASCII = 0;
|
||||
return k;
|
||||
}
|
||||
|
||||
__attribute((__no_caller_saved_registers__))
|
||||
uint16_t get_scancode_no_wait() {
|
||||
uint16_t k = _LSTKEY_SCAN | (_LSTKEY_ASCII << 8);
|
||||
_LSTKEY_SCAN = 0;
|
||||
_LSTKEY_ASCII = 0;
|
||||
return k;
|
||||
}
|
||||
|
||||
|
68
kernel.c
68
kernel.c
@ -190,9 +190,11 @@ Protected Only (1MB+)
|
||||
280000 - 300000 Disk Cache (512kB)
|
||||
300000 - 310000 Task Stack (64kB)
|
||||
310000 - 320000 Interrupt Stack (64kB)
|
||||
320000 - 400000 Kernel Stack (896kB)
|
||||
400000 - 700000 Usermode Code (3mB)
|
||||
700000 - 800000 Usermode Stack (1mB)
|
||||
320000 - 400000 Free (896kB)
|
||||
400000 - 700000 Free (3mB)
|
||||
700000 - 800000 Kernel Stack (1mB)
|
||||
800000 - F00000 Usermode Code (7mB)
|
||||
F00000 - 1000000 Usermode Stack (1mB)
|
||||
*/
|
||||
|
||||
void DrawScreen(uint16_t *vga) {
|
||||
@ -247,13 +249,8 @@ void RestoreVGA() {
|
||||
}
|
||||
|
||||
int32_t fileCount, fileOffset;
|
||||
// We store dir entries in usermode space,
|
||||
// which is nice because there's nothing after,
|
||||
// but it does mean we need to reload the dir
|
||||
// after every task called. This might be fine,
|
||||
// since the task might have modified the directory.
|
||||
extern char _USERMODE;
|
||||
dirent *const DirEntries = (dirent*)&_USERMODE;
|
||||
dirent *const DirEntries = (dirent*)0x400000;
|
||||
#define MAXDISPFILES 16
|
||||
void PrintFileList(uint16_t *vga) {
|
||||
uint16_t *vga_text = &((uint16_t *)vga)[80*6+3];
|
||||
@ -377,7 +374,20 @@ void FileSelect() {
|
||||
for (int i = 0; i < DirEntries[fileHovered].namelen; i++)
|
||||
current_path[current_path_end + i] = DirEntries[fileHovered].name[i];
|
||||
current_path[current_path_end + DirEntries[fileHovered].namelen] = 0;
|
||||
{
|
||||
// Give userspace mem (8MB)
|
||||
uintptr_t process_page0 = add_pages(4|2|1);
|
||||
uintptr_t process_page1 = add_pages(4|2|1);
|
||||
asm("xchg %bx,%bx");
|
||||
// Page blocks are 4MB
|
||||
move_pages(process_page0 >> 22, (uintptr_t)&_USERMODE >> 22);
|
||||
move_pages(process_page1 >> 22, ((uintptr_t)&_USERMODE >> 22) + 1);
|
||||
asm("xchg %bx,%bx");
|
||||
create_child(GetFreeStack(), (uintptr_t)HexEditor, 1, current_path);
|
||||
// Free userspace mem
|
||||
free_pages(process_page0 >> 22);
|
||||
free_pages(process_page1 >> 22);
|
||||
}
|
||||
current_path[current_path_end] = 0;
|
||||
RestoreVGA();
|
||||
reload = 1;
|
||||
@ -388,7 +398,18 @@ void FileSelect() {
|
||||
for (int i = 0; i < DirEntries[fileHovered].namelen; i++)
|
||||
current_path[current_path_end + i] = DirEntries[fileHovered].name[i];
|
||||
current_path[current_path_end + DirEntries[fileHovered].namelen] = 0;
|
||||
{
|
||||
// Give userspace mem (8MB)
|
||||
uintptr_t process_page0 = add_pages(4|2|1);
|
||||
uintptr_t process_page1 = add_pages(4|2|1);
|
||||
// Page blocks are 4MB
|
||||
move_pages(process_page0 >> 22, (uintptr_t)&_USERMODE >> 22);
|
||||
move_pages(process_page1 >> 22, ((uintptr_t)&_USERMODE >> 22) + 1);
|
||||
create_child(GetFreeStack(), (uintptr_t)TextViewTest, 1, current_path);
|
||||
// Free userspace mem
|
||||
free_pages(process_page0 >> 22);
|
||||
free_pages(process_page1 >> 22);
|
||||
}
|
||||
current_path[current_path_end] = 0;
|
||||
RestoreVGA();
|
||||
reload = 1;
|
||||
@ -455,6 +476,34 @@ void FileSelect() {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Move this somewhere else, maybe configurable & with timer handler
|
||||
void PITPgrm() {
|
||||
const uint32_t base_clk = 3579545;
|
||||
const uint16_t reload_v = 1194;
|
||||
// (base_clk / 3) / reload_v = ~999.31463Hz
|
||||
|
||||
// 32.32 Fixed point
|
||||
const uint64_t irq_ms = (uint64_t)reload_v * 3000LL * ((1LL << 42) / (uint64_t)base_clk / (1LL << 10));
|
||||
// irq_ms = 4294818000 (0xfffdb8d0)
|
||||
// We don't actually use this here, but in handler.nasm
|
||||
// for now, eventually this should be in C
|
||||
|
||||
asm volatile(
|
||||
"cli\n"
|
||||
"movb $0b00110100, %%al\n"
|
||||
"outb %%al, $0x43\n"
|
||||
:::"%eax"
|
||||
);
|
||||
uint32_t clobber_eax;
|
||||
asm volatile(
|
||||
"outb %%al, $0x40\n"
|
||||
"movb %%ah, %%al\n"
|
||||
"outb %%al, $0x40\n"
|
||||
"sti\n"
|
||||
:"=a"(clobber_eax):"a"(reload_v)
|
||||
);
|
||||
}
|
||||
|
||||
int MakeSystemVolume(uint8_t sysPartition);
|
||||
void MakeMBRPartitions();
|
||||
void SystemRun(uint8_t sysPartition) {
|
||||
@ -463,6 +512,7 @@ void SystemRun(uint8_t sysPartition) {
|
||||
DrawScreen((uint16_t*)0xb8000);
|
||||
|
||||
InitDisk();
|
||||
PITPgrm();
|
||||
|
||||
// Check for FAT partition
|
||||
{
|
||||
|
95
paging.c
95
paging.c
@ -1,7 +1,7 @@
|
||||
#include "paging.h"
|
||||
|
||||
uint32_t page_directory[1024] __attribute__((aligned(4096)));
|
||||
uint32_t page_tables[4][1024] __attribute__((aligned(4096)));
|
||||
uint32_t page_tables[128][1024] __attribute__((aligned(4096)));
|
||||
|
||||
void enable_paging() {
|
||||
asm(
|
||||
@ -21,7 +21,6 @@ void map_pages(uintptr_t page, uintptr_t num_pages, uintptr_t phy_address, char
|
||||
|
||||
// Each page is 4K, Each page table is 4M
|
||||
uintptr_t page_dir_entry = page >> 10;
|
||||
if (page_dir_entry >= 4) return;
|
||||
uintptr_t page_index = page & 0x3ff;
|
||||
if (page_index + num_pages > 1024) return;
|
||||
|
||||
@ -32,11 +31,93 @@ void map_pages(uintptr_t page, uintptr_t num_pages, uintptr_t phy_address, char
|
||||
page_tables[page_dir_entry][page_index + i] = phy_address + (i * 0x1000) | access_flags;
|
||||
}
|
||||
|
||||
// Marks a 4MB page directory index unused, *without* freeing physical memory
|
||||
void mark_pages_unused(uint16_t page_dir_idx) {
|
||||
if (page_dir_idx >= 1024) return;
|
||||
// Supervisor, R/W, Not Present
|
||||
page_directory[page_dir_idx] = 2;
|
||||
}
|
||||
|
||||
// Bitmap of physical memory usage
|
||||
uint8_t PhyMapArr[1024/8];
|
||||
|
||||
// Marks a 4MB page directory index unused, along with underlying physical memory
|
||||
void free_pages(uint16_t page_dir_idx) {
|
||||
// Get first entry of page table
|
||||
uint32_t *page_table = (uint32_t*)(page_directory[page_dir_idx] != 2 ? (uintptr_t)page_directory[page_dir_idx] & 0xfffff000 : 0);
|
||||
if (!page_table) return;
|
||||
|
||||
// Free physical memory
|
||||
uint32_t phy_address = page_table[0] & 0xfffff000;
|
||||
uint32_t phy_address_4mb = phy_address >> 22;
|
||||
uint32_t map_idx = phy_address_4mb >> 3;
|
||||
uint32_t bit_idx = phy_address_4mb & 7;
|
||||
// Clear bit
|
||||
PhyMapArr[map_idx] &= ~(1 << bit_idx);
|
||||
|
||||
// Mark unused
|
||||
mark_pages_unused(page_dir_idx);
|
||||
}
|
||||
|
||||
// Gets an unused 4MB page directory index. Return -1 if no free pages.
|
||||
uint16_t get_unused_pages() {
|
||||
for (int i = 0; i < 1024; i++)
|
||||
if (page_directory[i] == 2) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Gets physical address of 4MB unused area of physical memory. This will have to be mapped to virtual memory space to be used.
|
||||
uint32_t get_phy_mem() {
|
||||
for (int i = 0; i < sizeof(PhyMapArr); i++) {
|
||||
// Fully used
|
||||
if (PhyMapArr[i] == 0xff) continue;
|
||||
// At least one bit must be free
|
||||
uint8_t bits = PhyMapArr[i];
|
||||
for (int j = 0; j < 8; j++)
|
||||
if (!(bits & (1 << j))) return (i << 25) + (j << 22);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// User, R/W, Present
|
||||
#define USERACCESS (4|2|1)
|
||||
// Supervisor, R/W, Present
|
||||
#define SUPERACCESS (2|1)
|
||||
|
||||
// Returns a pointer to a newly mapped 4MB memory chunk
|
||||
uintptr_t add_pages(char access_flags) {
|
||||
// Get free physical space
|
||||
uint32_t phy_mem = get_phy_mem();
|
||||
if (phy_mem == -1) return -1;
|
||||
|
||||
// Get free virtual space
|
||||
uint16_t free_ent = get_unused_pages();
|
||||
if ((int16_t)free_ent == -1) return -1;
|
||||
uintptr_t page = free_ent << 10;
|
||||
|
||||
// Mark page directory entry present, pointing to page table
|
||||
page_directory[free_ent] = ((uintptr_t)&page_tables[free_ent]) | USERACCESS;
|
||||
|
||||
// Map pages to physical address
|
||||
map_pages(page, 1024, phy_mem, access_flags);
|
||||
|
||||
// Mark physical memory used
|
||||
uint32_t phy_address_4mb = phy_mem >> 22;
|
||||
uint32_t map_idx = phy_address_4mb >> 3;
|
||||
uint32_t bit_idx = phy_address_4mb & 7;
|
||||
// Set bit
|
||||
PhyMapArr[map_idx] |= 1 << bit_idx;
|
||||
|
||||
// Return virtual address
|
||||
return page << 12;
|
||||
}
|
||||
|
||||
// Copies 4MB groups of pages
|
||||
void move_pages(uint16_t src_page_dir_idx, uint16_t dest_page_dir_idx) {
|
||||
if (src_page_dir_idx >= 1024 || dest_page_dir_idx >= 1024) return;
|
||||
page_directory[dest_page_dir_idx] = page_directory[src_page_dir_idx];
|
||||
}
|
||||
|
||||
void init_paging() {
|
||||
for (int i = 0; i < 1024; i++)
|
||||
// Supervisor, R/W, Not Present
|
||||
@ -51,13 +132,15 @@ void init_paging() {
|
||||
// Next 4MB: Kernel
|
||||
map_pages(0x00400000 >> 12, 1024, 0x00400000, SUPERACCESS);
|
||||
|
||||
// Next 8MB: Usermode
|
||||
map_pages(0x00800000 >> 12, 1024, 0x00800000, USERACCESS);
|
||||
map_pages(0x00C00000 >> 12, 1024, 0x00C00000, USERACCESS);
|
||||
|
||||
// We aren't using page directory permissions
|
||||
for (int i = 0; i < 4; i++)
|
||||
page_directory[i] = ((uintptr_t)&page_tables[i]) | USERACCESS;
|
||||
|
||||
// Mark all physical memory free TODO Check memory size
|
||||
for (int i = 0; i < sizeof(PhyMapArr); i++)
|
||||
PhyMapArr[i] = 0;
|
||||
// Mark lowest 8MB as used
|
||||
PhyMapArr[0] = 3;
|
||||
|
||||
enable_paging();
|
||||
}
|
||||
|
3
paging.h
3
paging.h
@ -1,3 +1,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
void free_pages(uint16_t page_dir_idx);
|
||||
uintptr_t add_pages(char access_flags);
|
||||
void move_pages(uint16_t src_page_dir_idx, uint16_t dest_page_dir_idx);
|
||||
void init_paging();
|
||||
|
26
progs.c
26
progs.c
@ -1,21 +1,23 @@
|
||||
#include "progs.h"
|
||||
#include "paging.h"
|
||||
#include "file.h"
|
||||
|
||||
extern char _USERMODE, _USERMODE_END;
|
||||
static uintptr_t USERMODE_STACK = (uintptr_t)&_USERMODE_END - 0x100000;
|
||||
extern uint32_t create_user_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
|
||||
void ProgramLoadTest(char *path) {
|
||||
void programLoadTestInner(char *path) {
|
||||
uint16_t *vga_text = (uint16_t *)0xb8000;
|
||||
for (int i = 0; i < 80*25; i++)
|
||||
vga_text[i] = 0x0f00;
|
||||
uint32_t successcount;
|
||||
|
||||
uint8_t *diskReadBuf = (uint8_t *)&_USERMODE;
|
||||
{
|
||||
uint32_t err;
|
||||
dirent de;
|
||||
err = path_getinfo(path, &de);
|
||||
if (de.size > 0x300000 || err) {
|
||||
if (de.size > 0xE00000 || err) {
|
||||
vga_text += printStr("File too large or error.", vga_text);
|
||||
kbd_wait();
|
||||
return;
|
||||
}
|
||||
FILE file;
|
||||
@ -45,7 +47,8 @@ void ProgramLoadTest(char *path) {
|
||||
vga_text = nextLine(vga_text,(uint16_t*)0xb8000);
|
||||
vga_text += printStr("Press any key to run.", vga_text);
|
||||
kbd_wait();
|
||||
uint32_t res = create_user_child((uintptr_t)&_USERMODE_END, (uintptr_t)&_USERMODE, 0);
|
||||
uint32_t res = create_user_child(USERMODE_STACK, (uintptr_t)&_USERMODE, 0);
|
||||
|
||||
union V86Regs_t regs;
|
||||
regs.w.ax = 3; // text mode
|
||||
V8086Int(0x10, ®s);
|
||||
@ -57,5 +60,18 @@ void ProgramLoadTest(char *path) {
|
||||
vga_text += printStr(" (0x", vga_text);
|
||||
vga_text += printDword(res, vga_text);
|
||||
vga_text += printStr("). Press any key to exit.", vga_text);
|
||||
kbd_wait();
|
||||
}
|
||||
void ProgramLoadTest(char *path) {
|
||||
// Get free memory (8MB)
|
||||
uintptr_t process_page0 = add_pages(4|2|1);
|
||||
uintptr_t process_page1 = add_pages(4|2|1);
|
||||
// Map usermode memory
|
||||
move_pages(process_page0 >> 22, (uintptr_t)&_USERMODE >> 22);
|
||||
move_pages(process_page1 >> 22, ((uintptr_t)&_USERMODE >> 22) + 1);
|
||||
// Inner program
|
||||
programLoadTestInner(path);
|
||||
kbd_wait();
|
||||
// Free process memory
|
||||
free_pages(process_page0 >> 22);
|
||||
free_pages(process_page1 >> 22);
|
||||
}
|
||||
|
98
task.nasm
98
task.nasm
@ -5,9 +5,8 @@ ltr ax
|
||||
ret
|
||||
|
||||
global task_ptr
|
||||
task_ptr: equ (0x310000-4)
|
||||
task_ptr: equ (0x310000)
|
||||
|
||||
; TODO Is varargs too compiler dependent?
|
||||
; extern void create_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
|
||||
global create_child
|
||||
create_child:
|
||||
@ -60,6 +59,101 @@ push 0x18 | 3
|
||||
push eax
|
||||
iret
|
||||
|
||||
; save task
|
||||
; stack contains caller, eip, cs, eflags(, esp, ss)
|
||||
global save_current_task_new
|
||||
save_current_task_new:
|
||||
push ds
|
||||
push ebx
|
||||
push eax
|
||||
push 0x10
|
||||
pop ds
|
||||
; 0 eax, 4 ebx, 8 ds, 12 caller, 16 eip, 20 cs, 24 eflags(, 28 esp, 32 ss)
|
||||
; location to save task
|
||||
mov ebx, dword [0x318000]
|
||||
; code & stack
|
||||
mov eax, dword [esp+16]
|
||||
mov dword [ebx+0], eax ; eip
|
||||
mov eax, dword [esp+20]
|
||||
mov dword [ebx+4], eax ; cs
|
||||
cmp ax, 0x08
|
||||
; if we're not in code segment, save stack info
|
||||
je .curr_stack
|
||||
mov eax, dword [esp+24]
|
||||
mov dword [ebx+8], eax ; eflags
|
||||
mov eax, dword [esp+28]
|
||||
mov dword [ebx+12], eax ; esp
|
||||
mov eax, dword [esp+32]
|
||||
mov dword [ebx+16], eax ; ss
|
||||
jmp .seg_regs
|
||||
; if we're in code segment, we save current info, minus interrupt stack
|
||||
.curr_stack:
|
||||
mov eax, dword [esp+24]
|
||||
mov dword [ebx+8], eax ; eflags
|
||||
lea eax, [esp+28]
|
||||
mov dword [ebx+12], eax ; esp before interrupt
|
||||
mov eax, ss
|
||||
mov dword [ebx+16], eax
|
||||
; segment regs
|
||||
.seg_regs:
|
||||
mov eax, dword [esp+8]
|
||||
mov dword [ebx+20], eax ; ds
|
||||
mov eax, es
|
||||
mov dword [ebx+24], eax
|
||||
mov eax, fs
|
||||
mov dword [ebx+28], eax
|
||||
mov eax, gs
|
||||
mov dword [ebx+32], eax
|
||||
; general regs besides esp
|
||||
mov eax, dword [esp+0]
|
||||
mov dword [ebx+36], eax ; eax
|
||||
mov eax, dword [esp+4]
|
||||
mov dword [ebx+40], eax ; ebx
|
||||
mov dword [ebx+44], ecx
|
||||
mov dword [ebx+48], edx
|
||||
mov dword [ebx+52], esi
|
||||
mov dword [ebx+56], edi
|
||||
mov dword [ebx+60], ebp
|
||||
pop eax
|
||||
pop ebx
|
||||
pop ds
|
||||
xchg bx,bx
|
||||
ret
|
||||
|
||||
; return to current task
|
||||
global ret_current_task
|
||||
ret_current_task:
|
||||
xchg bx,bx
|
||||
push 0x10
|
||||
pop ds
|
||||
; location to get task
|
||||
mov ebx, dword [0x318000]
|
||||
mov ebp, [ebx+60]
|
||||
mov edi, [ebx+56]
|
||||
mov esi, [ebx+52]
|
||||
mov edx, [ebx+48]
|
||||
mov ecx, [ebx+44]
|
||||
mov gs, [ebx+32]
|
||||
mov fs, [ebx+28]
|
||||
mov es, [ebx+24]
|
||||
mov ds, [ebx+20]
|
||||
mov eax, [ebx+4] ; cs
|
||||
cmp ax, 0x08
|
||||
je .restore_stack
|
||||
mov eax, [ebx+36]
|
||||
mov esp, ebx
|
||||
mov ebx, [ebx+40]
|
||||
iret
|
||||
.restore_stack:
|
||||
mov esp, [ebx+12]
|
||||
mov ss, [ebx+16]
|
||||
mov eax, [ebx+36]
|
||||
push dword [ebx+8]
|
||||
push dword [ebx+4]
|
||||
push dword [ebx]
|
||||
mov ebx, [ebx+40]
|
||||
iret
|
||||
|
||||
; return address in EAX
|
||||
; return stack in ECX
|
||||
; we can modify EAX, ECX, EDX
|
||||
|
12
tests.c
12
tests.c
@ -1,4 +1,5 @@
|
||||
#include "tests.h"
|
||||
#include "paging.h"
|
||||
|
||||
extern char *user_test();
|
||||
extern uint32_t create_user_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
|
||||
@ -26,8 +27,17 @@ void ReloadUser() {
|
||||
*d++ = *s++;
|
||||
}
|
||||
char TestUser() {
|
||||
// Get free memory (8MB)
|
||||
uintptr_t process_page0 = add_pages(4|2|1);
|
||||
uintptr_t process_page1 = add_pages(4|2|1);
|
||||
// Map usermode memory
|
||||
move_pages(process_page0 >> 22, (uintptr_t)&_USERMODE >> 22);
|
||||
move_pages(process_page1 >> 22, ((uintptr_t)&_USERMODE >> 22) + 1);
|
||||
ReloadUser();
|
||||
char *vga = (char *)(uintptr_t)create_user_child((uintptr_t)&_USERMODE_END, (uintptr_t)&_USERMODE, 0);
|
||||
char *vga = (char *)(uintptr_t)create_user_child((uintptr_t)&_USERMODE_END - 0x100000, (uintptr_t)&_USERMODE, 0);
|
||||
// Free process memory
|
||||
free_pages(process_page0 >> 22);
|
||||
free_pages(process_page1 >> 22);
|
||||
if ((uintptr_t)vga != 0xA0000) {
|
||||
return 1;
|
||||
}
|
||||
|
4
tss.c
4
tss.c
@ -41,8 +41,8 @@ void write_tss() {
|
||||
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-(20*4); // each task is 12 dwords, plus 1 for pointer
|
||||
uint32_t *current_task_ptr = (uint32_t*)(0x310000);
|
||||
*current_task_ptr = 0x310000-(1*4); // each task is 12 dwords, plus 1 for pointer
|
||||
/* TODO setup null recovery task at start */
|
||||
}
|
||||
extern void flushTSS();
|
||||
|
@ -27,6 +27,8 @@ mov dword [0xb8000+800], 0x0f000f00 | 'g' | ':' << 16
|
||||
mov dword [0xb8004+800], 0x0f000f00 | ' ' | '#' << 16
|
||||
mov dword [0xb8008+800], 0x0f000f00 | 'G' | 'P' << 16
|
||||
mov dword [0xb800C+800], 0x0f000f00 | 'F' | ' ' << 16
|
||||
.busy:
|
||||
jmp .busy
|
||||
mov eax, 0 ; command = 00h, get key
|
||||
int 0x21 ; OS call
|
||||
cmp al, 'd'
|
||||
|
Loading…
Reference in New Issue
Block a user