Implemented Paging! Moved Kernel to 0x100000, Moved TSS above 1M, Moved V86 to 0x8000, Moved Usermode test to 0x400000, Moved lots of things!

This commit is contained in:
Lucia Ceionia 2023-01-31 21:26:43 -06:00
parent 43e902e83c
commit afaf5e1a03
14 changed files with 274 additions and 161 deletions

View File

@ -1,5 +1,5 @@
objects = entry.o kernel.o task.o handler.o interrupt.o v86.o print.o tss.o dosfs/dosfs.o objects = entry.o kernel.o task.o handler.o interrupt.o v86.o print.o tss.o dosfs/dosfs.o gdt.o usermode.o paging.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 -Wno-int-conversion -nostdlib -c
%.o: %.nasm %.o: %.nasm
nasm -f elf32 -o $@ $< nasm -f elf32 -o $@ $<
@ -9,7 +9,7 @@ CFLAGS = -target "i686-elf" -m32 -mgeneral-regs-only -ffreestanding -march=penti
all: $(objects) all: $(objects)
nasm boot.nasm -o boot.bin nasm boot.nasm -o boot.bin
gcc -Tlink.ld -m32 -ffreestanding -nostartfiles -nostdlib -o kernel.bin\ gcc -Tlink.ld -Wl,-M -m32 -ffreestanding -nostartfiles -nostdlib -o kernel.bin\
$(objects) $(objects)
dd bs=256 count=1 conv=notrunc if=boot.bin of=virtdisk.bin dd bs=256 count=1 conv=notrunc if=boot.bin of=virtdisk.bin
dd bs=512 seek=1 conv=notrunc if=kernel.bin of=virtdisk.bin dd bs=512 seek=1 conv=notrunc if=kernel.bin of=virtdisk.bin

View File

@ -7,7 +7,7 @@ mov es, ax
mov ah, 0x42 mov ah, 0x42
mov si, addr_packet mov si, addr_packet
int 0x13 int 0x13
jnc 0x8000 jnc entry
push 0xb800 push 0xb800
pop es pop es
xor di, di xor di, di
@ -21,6 +21,41 @@ loop err_print
hlt_loop: hlt_loop:
hlt hlt
jmp hlt_loop jmp hlt_loop
entry:
cli ; no interrupts
xor ax,ax
mov ds, ax
lgdt [gdt_desc] ; load gdt register
mov eax, cr0 ; set pmode bit
or al, 1
mov cr0, eax
jmp 08h:Pmode
[BITS 32]
Pmode:
mov ax, 0x10
mov ds, ax
mov es, ax
mov esi, 0x8000
mov edi, 0x100000
mov ecx, 0x10000
rep movsb
jmp 08h:0x100000
gdt_desc:
dw gdt_end - gdt
dd gdt
gdt:
gdt_null: dq 0
gdt_code: dw 0xFFFF, 0 ; bits 0-15 limit (4GB), bits 0-15 base address
db 0 ; bits 16-23 base address
db 10011010b ; access byte
db 11001111b ; bits 16-19 limit (4GB), 4 bits flags
db 0 ; bits 24-31 base address
gdt_data: dw 0xFFFF, 0 ; bits 0-15 limit (4GB), bits 0-15 base address
db 0 ; bits 16-23 base address
db 10010010b ; access byte
db 11001111b ; bits 16-19 limit (4GB), 4 bits flags
db 0 ; bits 24-31 base address
gdt_end:
string: db 'DISK ERROR' string: db 'DISK ERROR'

View File

@ -1,14 +1,9 @@
[BITS 16]
global entry global entry
entry: entry:
cli ; no interrupts
xor ax,ax
mov ds, ax
lgdt [gdt_desc] ; load gdt register lgdt [gdt_desc] ; load gdt register
mov eax, cr0 ; set pmode bit jmp Pmodecode
or al, 1
mov cr0, eax extern gdt_desc
jmp 08h:Pmodecode
[BITS 32] [BITS 32]
Pmodecode: Pmodecode:
@ -30,110 +25,3 @@ hlt
jmp hlt_loop jmp hlt_loop
extern start extern start
; currently unused first 8MB identity paging
; taken from Linux 0.01
setup_paging:
mov ecx, 1024*3 ; 3K?
xor eax, eax
mov edi, 0x1000
rep stosd ; zero first 3K for some reason
mov edi, 0x4000
mov eax, 0x800007 ; 8MB + 7
std ; fill backwards
.fill:
stosd
sub eax, 0x1000
jge .fill
cld ; fix direction
mov dword [0x0000], 0x2000 + 7
mov dword [0x0004], 0x3000 + 7
mov eax, 0x1000
mov cr3, eax ; page dir start 0x1000
mov eax, cr0
or eax, 0x80000000
mov cr0, eax ; set paging bit
ret ; flushes pre-fetch queue
user_test:
mov dword [0xb8000], 0x0f000f00 | 'U' | 's' << 16
mov dword [0xb8004], 0x0f000f00 | 'e' | 'r' << 16
mov dword [0xb8008], 0x0f000f00 | 'm' | 'o' << 16
mov dword [0xb800C], 0x0f000f00 | 'd' | 'e' << 16
mov word [0xb8010], 0x0f00 | '!'
mov edi, 0xA0000
xor eax, eax
.loop:
mov ecx, 320
rep stosb
inc al
cmp eax, 200
jl .loop
mov eax, 0xA0000
int 0x30 ; Exit
xor ebx, ebx
div bl ; Unhandled DIV0 exception
global jmp_usermode_test
jmp_usermode_test:
pop eax ; return address
mov ecx, esp ; return stack
call save_current_task
mov esp, 0x500000 ; usermode stack
mov eax, 0x20 | 3
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
push 0x20 | 3
push eax
pushfd
push 0x18 | 3
push user_test
iret
extern save_current_task
global flushTSS
flushTSS:
mov ax, 0x28
ltr ax
ret
extern tss_data
global ivt
ivt: dd 0x00000000
gdt_desc:
dw gdt_end - gdt
dd gdt
gdt:
gdt_null: dq 0
gdt_code: dw 0xFFFF, 0 ; bits 0-15 limit (4GB), bits 0-15 base address
db 0 ; bits 16-23 base address
db 10011010b ; access byte
db 11001111b ; bits 16-19 limit (4GB), 4 bits flags
db 0 ; bits 24-31 base address
gdt_data: dw 0xFFFF, 0 ; bits 0-15 limit (4GB), bits 0-15 base address
db 0 ; bits 16-23 base address
db 10010010b ; access byte
db 11001111b ; bits 16-19 limit (4GB), 4 bits flags
db 0 ; bits 24-31 base address
gdt_r3code: dw 0xFFFF, 0 ; bits 0-15 limit (4GB), bits 0-15 base address
db 0 ; bits 16-23 base address
db 0xFA ; access byte
db 11001111b ; bits 16-19 limit (4GB), 4 bits flags
db 0 ; bits 24-31 base address
gdt_r3data: dw 0xFFFF, 0 ; bits 0-15 limit (4GB), bits 0-15 base address
db 0 ; bits 16-23 base address
db 0xF2 ; access byte
db 11001111b ; bits 16-19 limit (4GB), 4 bits flags
db 0 ; bits 24-31 base address
gdt_tss: dw 0x2080, 0x0000;26*4, tss_data ; bits 0-15 limit (4GB), bits 0-15 base address
db 0x2 ; bits 16-23 base address
db 0x89 ; access byte
db 00000000b ; bits 16-19 limit (4GB), 4 bits flags
db 0 ; bits 24-31 base address
gdt_end:

35
gdt.nasm Normal file
View File

@ -0,0 +1,35 @@
global ivt
ivt: dd 0x00000000
global gdt_desc
gdt_desc:
dw gdt_end - gdt
dd gdt
gdt:
gdt_null: dq 0
gdt_code: dw 0xFFFF, 0 ; bits 0-15 limit (4GB), bits 0-15 base address
db 0 ; bits 16-23 base address
db 10011010b ; access byte
db 11001111b ; bits 16-19 limit (4GB), 4 bits flags
db 0 ; bits 24-31 base address
gdt_data: dw 0xFFFF, 0 ; bits 0-15 limit (4GB), bits 0-15 base address
db 0 ; bits 16-23 base address
db 10010010b ; access byte
db 11001111b ; bits 16-19 limit (4GB), 4 bits flags
db 0 ; bits 24-31 base address
gdt_r3code: dw 0xFFFF, 0 ; bits 0-15 limit (4GB), bits 0-15 base address
db 0 ; bits 16-23 base address
db 0xFA ; access byte
db 11001111b ; bits 16-19 limit (4GB), 4 bits flags
db 0 ; bits 24-31 base address
gdt_r3data: dw 0xFFFF, 0 ; bits 0-15 limit (4GB), bits 0-15 base address
db 0 ; bits 16-23 base address
db 0xF2 ; access byte
db 11001111b ; bits 16-19 limit (4GB), 4 bits flags
db 0 ; bits 24-31 base address
gdt_tss: dw 0x2080, 0x0000;26*4, tss_data ; bits 0-15 limit (4GB), bits 0-15 base address
db 0x20 ; bits 16-23 base address
db 0x89 ; access byte
db 00000000b ; bits 16-19 limit (4GB), 4 bits flags
db 0 ; bits 24-31 base address
gdt_end:

View File

@ -9,6 +9,22 @@ mov dword [0xb8008], 0x0f000f00 | 'R' | '!' << 16
hlt hlt
jmp .hlt jmp .hlt
global pageFaultHandler
pageFaultHandler:
mov ax, 0x10
mov ds, ax
pop eax ; error code
mov ebx, 0x0f000f00 | '0' | '!' << 16
and eax, 0x7 ; U/S,R/W,P
add ebx, eax
mov dword [0xb8000], 0x0f000f00 | 'P' | 'G' << 16
mov dword [0xb8004], 0x0f000f00 | 'F' | 'L' << 16
mov dword [0xb8008], 0x0f000f00 | 'T' | ':' << 16
mov dword [0xb800C], ebx
.hlt:
hlt
jmp .hlt
extern gpf_handler_v86 extern gpf_handler_v86
global gpfHandler global gpfHandler
gpfHandler: gpfHandler:

View File

@ -237,6 +237,7 @@ void gpf_handler_v86(struct interrupt_frame *frame, unsigned long error_code) {
extern void timerHandler(); extern void timerHandler();
extern void keyboardHandler(); extern void keyboardHandler();
extern void gpfHandler(); extern void gpfHandler();
extern void pageFaultHandler();
extern void unhandled_handler(); extern void unhandled_handler();
extern void picInit(); extern void picInit();
void set_system_gate(uint8_t gate, void (*handler)()) { void set_system_gate(uint8_t gate, void (*handler)()) {
@ -272,6 +273,7 @@ void setup_interrupts() {
set_system_gate(0x21, keyboardHandler); set_system_gate(0x21, keyboardHandler);
//set_trap_gate(13, gpf_handler_v86); //set_trap_gate(13, gpf_handler_v86);
set_trap_gate(13, gpfHandler); set_trap_gate(13, gpfHandler);
set_trap_gate(14, pageFaultHandler);
asm volatile("lidt %0": : "m"(IDTR)); asm volatile("lidt %0": : "m"(IDTR));
picInit(); picInit();

View File

@ -3,8 +3,8 @@
#include "dosfs/dosfs.h" #include "dosfs/dosfs.h"
#include "print.h" #include "print.h"
#include "interrupt.h" #include "interrupt.h"
#include "tss.h" #include "tss.h"
#include "paging.h"
typedef unsigned short word; typedef unsigned short word;
@ -72,29 +72,49 @@ extern char *jmp_usermode_test();
__attribute((__no_caller_saved_registers__)) __attribute((__no_caller_saved_registers__))
extern void kbd_wait(); extern void kbd_wait();
extern char _edata, _v86code, _ev86code, _bstart, _bend, _loadusercode, _usercode, _eusercode;
void setup_binary() {
// Put V86 code in proper place based on linker
char *s = &_edata;
char *d = &_v86code;
while (d < &_ev86code)
*d++ = *s++;
// Put Usermode code in proper place based on linker
s = &_loadusercode;
d = &_usercode;
while (d < &_eusercode)
*d++ = *s++;
// Clear BSS area
for (d = &_bstart; d < &_bend; d++)
*d = 0;
}
/* /*
Real Mode Accessible (First MB) Real Mode Accessible (First MB)
00000 - 00400 IVT (1kB) 00000 - 00400 IVT (1kB)
00400 - 01000 Unused (3kB) 00400 - 01000 Unused (3kB)
01000 - 04000 Paging (12kB) 01000 - 04000 Free (12kB)
04000 - 07C00 Free (15kB) 04000 - 07C00 Free (15kB)
07C00 - 08000 Boot (512B) 07C00 - 08000 Boot (512B)
08000 - 20000 Kernel Code (96kB) 08000 - 20000 V86 Code (96kB)
20000 - 20080 TSS (128B) 20000 - 30000 Disk Buffer (64kB)
20080 - 22080 TSS IOMAP (8kB)
22080 - 22400 Unused (896B)
22400 - 23000 Free (3kB)
23000 - 30000 Disk Buffer (52kB)
30000 - 80000 Free (320kB) 30000 - 80000 Free (320kB)
80000 - 90000 Real Mode Stack (64kB) 80000 - 90000 Real Mode Stack (64kB)
90000 - A0000 Free (64kB) 90000 - A0000 Free (64kB)
A0000 - FFFFF BIOS Area (384kB) A0000 - C0000 VGA (128kB)
C0000 - FFFFF BIOS Area (256kB)
Protected Only (1MB+) Protected Only (1MB+)
100000 - 300000 Free (2mB) 100000 - 200000 Kernel Code (1mB)
200000 - 200080 TSS (128B)
200080 - 202080 TSS IOMAP (8kB)
202080 - 300000 Free (~1mB)
300000 - 310000 Task Stack (64kB) 300000 - 310000 Task Stack (64kB)
310000 - 320000 Interrupt Stack (64kB) 310000 - 320000 Interrupt Stack (64kB)
320000 - 400000 Kernel Stack (896kB) 320000 - 400000 Kernel Stack (896kB)
400000 - 500000 Usermode Stack (1mB) 400000 - 700000 Usermode Code (3mB)
700000 - 800000 Usermode Stack (1mB)
*/ */
void TestV86() { void TestV86() {
@ -218,14 +238,16 @@ void start() {
if (!sse) return; if (!sse) return;
enable_sse(); enable_sse();
setup_binary();
// edit // edit
setup_interrupts(); setup_interrupts();
setup_tss(); setup_tss();
print_flags(); init_paging();
//print_flags();
print_cr0(); print_cr0();
print_cr3(); //print_cr3();
print_cr4(); //print_cr4();
//asm ("xchgw %bx, %bx");
TestV86(); // has int 3 wait in v86 TestV86(); // has int 3 wait in v86
TestGfx(); TestGfx();

28
link.ld
View File

@ -2,18 +2,34 @@ OUTPUT_FORMAT(binary)
ENTRY(entry) ENTRY(entry)
SECTIONS { SECTIONS {
. = 0x8000; . = 0x100000;
.text : ALIGN(0x1000) { .text : ALIGN(0x1000) {
*(.text) *(.text);
} }
.data : ALIGN(0x1000) { .data : ALIGN(0x1000) {
*(.data) *(.data);
*(.rodata) *(.rodata);
*(.rodata*);
_edata = .;
} }
.bss : ALIGN(0x1000) { .realmode 0x8000 :
*(.bss) AT ( ADDR(.data) + SIZEOF(.data) )
{ _v86code = .; *(.v86); _ev86code = .; }
. = ADDR(.data) + SIZEOF(.data) + SIZEOF(.realmode);
.thing : { _loadusercode = .; }
.usermode 0x400000 :
AT ( ADDR(.data) + SIZEOF(.data) + SIZEOF(.realmode) )
{ _usercode = .; *(.user); _eusercode = .; }
. = ADDR(.data) + SIZEOF(.data) + SIZEOF(.realmode) + SIZEOF(.usermode);
.bss : ALIGN(0x1000)
{
_bstart = .; *(.bss); _bend = .;
} }
} }

50
paging.c Normal file
View File

@ -0,0 +1,50 @@
#include "paging.h"
uint32_t page_directory[1024] __attribute__((aligned(4096)));
uint32_t first_page_table[1024] __attribute__((aligned(4096))); // 0x00000000 - 0x00400000
uint32_t second_page_table[1024] __attribute__((aligned(4096))); // 0x00400000 - 0x00800000
void enable_paging() {
asm(
"mov %%eax, %%cr3\n"
"mov %%cr0, %%eax\n"
"or $0x80000001, %%eax\n"
"mov %%eax, %%cr0\n"
::"a"(page_directory));
}
void init_paging() {
for (int i = 0; i < 1024; i++)
// Supervisor, R/W, Not Present
page_directory[i] = 2;
// First Page Table
// First MB: Real Mode
{
int i;
// Up to 0xC0000
// TODO make some areas here Read Only
for (i = 0;i < 16*0xC; i++)
// User, R/W, Present
first_page_table[i] = (i * 0x1000) |4|2|1;
// Remainder of first MB BIOS Area (writable?)
for (;i < 256; i++)
// User, R/W, Present
first_page_table[i] = (i * 0x1000) |4|2|1;
}
// Next 3MB: Kernel
for (int i = 256; i < 1024; i++)
// Supervisor, R/W, Present
first_page_table[i] = (i * 0x1000) |2|1;
// Usermode Page Table
for (int i = 0; i < 1024; i++)
// User, R/W, Present
second_page_table[i] = (i * 0x1000 + 0x400000) |4|2|1;
// User, R/W, Present
page_directory[0] = ((uintptr_t)first_page_table)|4|2|1;
page_directory[1] = ((uintptr_t)second_page_table)|4|2|1;
enable_paging();
}

3
paging.h Normal file
View File

@ -0,0 +1,3 @@
#include <stdint.h>
void init_paging();

View File

@ -1,3 +1,9 @@
global flushTSS
flushTSS:
mov ax, 0x28
ltr ax
ret
task_ptr: equ (0x310000-4) task_ptr: equ (0x310000-4)
; return address in EAX ; return address in EAX
@ -56,3 +62,42 @@ mov eax, [edx+12+16] ; ds
mov ds, ax mov ds, ax
mov eax, ecx ; restore return value mov eax, ecx ; restore return value
iret iret
; extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip);
global enter_v86
enter_v86:
pop eax ; return address
mov ecx, esp ; return stack
call save_current_task
mov ebp, esp ; save stack pointer
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+8] ; cs
push dword [ebp+12] ; eip
iret
; return address in eax, return stack in ebp
;extern save_current_task
extern user_test
global jmp_usermode_test
jmp_usermode_test:
pop eax ; return address
mov ecx, esp ; return stack
call save_current_task
mov esp, 0x800000 ; usermode stack
mov eax, 0x20 | 3
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
push 0x20 | 3
push eax
pushfd
push 0x18 | 3
push user_test
iret

2
tss.c
View File

@ -33,7 +33,7 @@ struct __attribute__((__packed__)) tss_entry_struct {
}; };
struct tss_entry_struct *tss_data; struct tss_entry_struct *tss_data;
void write_tss() { void write_tss() {
tss_data = (struct tss_entry_struct *)0x20000; tss_data = (struct tss_entry_struct *)0x200000;
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;

20
usermode.nasm Normal file
View File

@ -0,0 +1,20 @@
[SECTION .user]
global user_test
user_test:
mov dword [0xb8000], 0x0f000f00 | 'U' | 's' << 16
mov dword [0xb8004], 0x0f000f00 | 'e' | 'r' << 16
mov dword [0xb8008], 0x0f000f00 | 'm' | 'o' << 16
mov dword [0xb800C], 0x0f000f00 | 'd' | 'e' << 16
mov word [0xb8010], 0x0f00 | '!'
mov edi, 0xA0000
xor eax, eax
.loop:
mov ecx, 320
rep stosb
inc al
cmp eax, 200
jl .loop
mov eax, 0xA0000
int 0x30 ; Exit
xor ebx, ebx
div bl ; Unhandled DIV0 exception

View File

@ -1,4 +1,5 @@
[BITS 16] [BITS 16]
[SECTION .v86]
real_hexprint: real_hexprint:
xor cx, cx xor cx, cx
mov bl, al mov bl, al
@ -77,23 +78,3 @@ db 0x10, 0x00 ; size, reserved
dw 0x1 ; blocks dw 0x1 ; blocks
dd 0x23000000 ; transfer buffer 0x23000 dd 0x23000000 ; transfer buffer 0x23000
dq 0x1 ; start block dq 0x1 ; start block
[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 ; return address
mov ecx, esp ; return stack
call save_current_task
mov ebp, esp ; save stack pointer
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+8] ; cs
push dword [ebp+12] ; eip
iret
; return address in eax, return stack in ebp
extern save_current_task