Usermode now loads at 0x800000, Virtual 8086 loads consistent DS&ES for data access
This commit is contained in:
parent
5fe565b6f7
commit
d0a5eb4c6f
@ -16,7 +16,7 @@ mov es, ax
|
||||
mov ss, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ebp, 0x400000
|
||||
mov ebp, 0x800000
|
||||
mov esp, ebp
|
||||
mov eax, 0x1f001f00
|
||||
mov ecx, (80*25)/2
|
||||
|
@ -83,6 +83,7 @@ je .int30
|
||||
cmp eax, 0x21CD ; int 0x21
|
||||
je .int21
|
||||
jmp gpf_unhandled
|
||||
|
||||
.int21:
|
||||
pop eax ; command
|
||||
cmp al, 0x00 ; get key
|
||||
@ -94,7 +95,13 @@ jne .s86
|
||||
call get_scancode
|
||||
jmp .return_to_offender
|
||||
.s86: cmp al, 0x86 ; v86 interrupt call
|
||||
je .v86int
|
||||
cmp ax, 0x86D8 ; get v86 data pointer
|
||||
jne .return_to_offender
|
||||
mov eax, 0x30000 ; V86 Data
|
||||
jmp .return_to_offender
|
||||
|
||||
.v86int:
|
||||
add esp, 4
|
||||
add dword [esp+0], 2
|
||||
; add a new task
|
||||
@ -120,6 +127,7 @@ push eax ; cs
|
||||
push 0xFF00 ; sp
|
||||
push 0x8000 ; ss
|
||||
jmp _enter_v86_internal_no_task ; NOT a function call
|
||||
|
||||
.int30:
|
||||
pop eax ; return value
|
||||
jmp return_prev_task
|
||||
|
10
kernel.c
10
kernel.c
@ -171,10 +171,11 @@ Real Mode Accessible (First MB)
|
||||
01000 - 04000 Free (12kB)
|
||||
04000 - 07C00 V86 Code (15kB)
|
||||
07C00 - 08000 Boot & V86 Code (512B)
|
||||
08000 - 20000 V86 Code (96kB)
|
||||
08000 - 20000 Free (96kB)
|
||||
20000 - 30000 Disk Buffer (64kB)
|
||||
30000 - 80000 Free (320kB)
|
||||
80000 - 90000 Real Mode Stack (64kB)
|
||||
30000 - 40000 V86 Data (64kB)
|
||||
40000 - 80000 Free (256kB)
|
||||
80000 - 90000 V86 Stack (64kB)
|
||||
90000 - A0000 Free (64kB)
|
||||
A0000 - C0000 VGA (128kB)
|
||||
C0000 - FFFFF BIOS Area (256kB)
|
||||
@ -434,6 +435,8 @@ void SystemRun(uint8_t sysPartition) {
|
||||
RestoreVGA();
|
||||
DrawScreen((uint16_t*)0xb8000);
|
||||
|
||||
InitDisk();
|
||||
|
||||
// Check for FAT partition
|
||||
{
|
||||
// TODO Check partitions beyond 0
|
||||
@ -528,7 +531,6 @@ void start() {
|
||||
setup_tss();
|
||||
init_paging();
|
||||
backup_ivtbios();
|
||||
InitDisk();
|
||||
|
||||
// DL contained disk number, DH contained active partition
|
||||
uint8_t SystemPartition = boot_dx >> 8;
|
||||
|
3
link.ld
3
link.ld
@ -3,7 +3,8 @@ ENTRY(entry)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x100000;
|
||||
_USERMODE = 0x400000;
|
||||
_USERMODE = 0x800000;
|
||||
_USERMODE_END = 0x1000000;
|
||||
|
||||
.text : {
|
||||
*(.text);
|
||||
|
63
paging.c
63
paging.c
@ -1,8 +1,7 @@
|
||||
#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
|
||||
uint32_t page_tables[4][1024] __attribute__((aligned(4096)));
|
||||
|
||||
void enable_paging() {
|
||||
asm(
|
||||
@ -13,38 +12,52 @@ void enable_paging() {
|
||||
::"a"(page_directory));
|
||||
}
|
||||
|
||||
// TODO Add a function which can dynamically add and remove pages,
|
||||
// that keeps track internally of what's already used?
|
||||
|
||||
// NOTE This function cannot cross 4MB (1024 page) boundaries
|
||||
void map_pages(uintptr_t page, uintptr_t num_pages, uintptr_t phy_address, char access_flags) {
|
||||
uintptr_t access = access_flags & 0x7;
|
||||
|
||||
// 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;
|
||||
|
||||
// Address must be 4K aligned
|
||||
if (phy_address & 0x3ff) return;
|
||||
|
||||
for (int i = 0; i < num_pages; i++)
|
||||
page_tables[page_dir_entry][page_index + i] = phy_address + (i * 0x1000) | access_flags;
|
||||
}
|
||||
|
||||
// User, R/W, Present
|
||||
#define USERACCESS (4|2|1)
|
||||
// Supervisor, R/W, Present
|
||||
#define SUPERACCESS (2|1)
|
||||
|
||||
void init_paging() {
|
||||
for (int i = 0; i < 1024; i++)
|
||||
// Supervisor, R/W, Not Present
|
||||
page_directory[i] = 2;
|
||||
|
||||
// First Page Table
|
||||
// 1024 Pages = 1MB
|
||||
// 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;
|
||||
}
|
||||
// TODO Make some of this not accessible to usermode?
|
||||
map_pages(0x00000000 >> 12, 256, 0x00000000, USERACCESS);
|
||||
// Next 3MB: Kernel
|
||||
for (int i = 256; i < 1024; i++)
|
||||
// Supervisor, R/W, Present
|
||||
first_page_table[i] = (i * 0x1000) |2|1;
|
||||
map_pages(0x00100000 >> 12, 768, 0x00100000, SUPERACCESS);
|
||||
// Next 4MB: Kernel
|
||||
map_pages(0x00400000 >> 12, 1024, 0x00400000, SUPERACCESS);
|
||||
|
||||
// Usermode Page Table
|
||||
for (int i = 0; i < 1024; i++)
|
||||
// User, R/W, Present
|
||||
second_page_table[i] = (i * 0x1000 + 0x400000) |4|2|1;
|
||||
// Next 8MB: Usermode
|
||||
map_pages(0x00800000 >> 12, 1024, 0x00800000, USERACCESS);
|
||||
map_pages(0x00C00000 >> 12, 1024, 0x00C00000, USERACCESS);
|
||||
|
||||
// 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;
|
||||
// We aren't using page directory permissions
|
||||
for (int i = 0; i < 4; i++)
|
||||
page_directory[i] = ((uintptr_t)&page_tables[i]) | USERACCESS;
|
||||
|
||||
enable_paging();
|
||||
}
|
||||
|
6
progs.c
6
progs.c
@ -1,9 +1,7 @@
|
||||
#include "progs.h"
|
||||
#include "file.h"
|
||||
|
||||
// 400000 - 700000 Usermode Code (3mB)
|
||||
// 700000 - 800000 Usermode Stack (1mB)
|
||||
extern char _USERMODE;
|
||||
extern char _USERMODE, _USERMODE_END;
|
||||
extern uint32_t create_user_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
|
||||
void ProgramLoadTest(char *path, dirent *de) {
|
||||
uint16_t *vga_text = (uint16_t *)0xb8000;
|
||||
@ -46,7 +44,7 @@ void ProgramLoadTest(char *path, dirent *de) {
|
||||
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(0x800000, (uintptr_t)&_USERMODE, 0);
|
||||
uint32_t res = create_user_child((uintptr_t)&_USERMODE_END, (uintptr_t)&_USERMODE, 0);
|
||||
union V86Regs_t regs;
|
||||
regs.w.ax = 3; // text mode
|
||||
V8086Int(0x10, ®s);
|
||||
|
30
task.nasm
30
task.nasm
@ -152,17 +152,12 @@ mov ecx, esp ; return stack
|
||||
call save_current_task
|
||||
_enter_v86_internal_no_task:
|
||||
mov ebp, esp ; save stack pointer
|
||||
mov eax, dword [ebp+16] ; regs
|
||||
test eax, eax
|
||||
jz .no_regs
|
||||
; load regs: edi, esi, ebx, edx, ecx, eax
|
||||
mov edi, dword [eax+0]
|
||||
mov esi, dword [eax+4]
|
||||
mov ebx, dword [eax+8]
|
||||
mov edx, dword [eax+12]
|
||||
mov ecx, dword [eax+16]
|
||||
mov eax, dword [eax+20]
|
||||
.no_regs:
|
||||
; push v86 stuff for iret
|
||||
mov eax, 0x3000
|
||||
push eax ; gs
|
||||
push eax ; fs
|
||||
push eax ; ds
|
||||
push eax ; es
|
||||
push dword [ebp+0] ; ss
|
||||
push dword [ebp+4] ; esp
|
||||
pushfd ; eflags
|
||||
@ -170,6 +165,19 @@ 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
|
||||
; check if we have regs
|
||||
mov eax, dword [ebp+16] ; regs
|
||||
test eax, eax
|
||||
jz .no_regs
|
||||
; load regs: ebp, edi, esi, ebx, edx, ecx, eax
|
||||
mov ebp, dword [eax+0]
|
||||
mov edi, dword [eax+4]
|
||||
mov esi, dword [eax+8]
|
||||
mov ebx, dword [eax+12]
|
||||
mov edx, dword [eax+16]
|
||||
mov ecx, dword [eax+20]
|
||||
mov eax, dword [eax+24]
|
||||
.no_regs:
|
||||
iret
|
||||
|
||||
; return address in eax, return stack in ebp
|
||||
|
@ -1,5 +1,5 @@
|
||||
[BITS 32]
|
||||
[ORG 0x400000]
|
||||
[ORG 0x800000]
|
||||
xchg bx,bx
|
||||
mov edi, 0xB8000
|
||||
mov ecx, 80*25
|
||||
|
4
tests.c
4
tests.c
@ -16,7 +16,7 @@ void TestV86() {
|
||||
uint16_t *vga_text = (uint16_t *)0xb8000 + (80*2);
|
||||
vga_text += printStr("Done.", vga_text);
|
||||
}
|
||||
extern char _USERMODE;
|
||||
extern char _USERMODE, _USERMODE_END;
|
||||
extern char _binary_usermode_bin_start, _binary_usermode_bin_end;
|
||||
void ReloadUser() {
|
||||
// Put Usermode code in proper place based on linker
|
||||
@ -27,7 +27,7 @@ void ReloadUser() {
|
||||
}
|
||||
char TestUser() {
|
||||
ReloadUser();
|
||||
char *vga = (char *)(uintptr_t)create_user_child(0x800000, (uintptr_t)&_USERMODE, 0);
|
||||
char *vga = (char *)(uintptr_t)create_user_child((uintptr_t)&_USERMODE_END, (uintptr_t)&_USERMODE, 0);
|
||||
if ((uintptr_t)vga != 0xA0000) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
[BITS 32]
|
||||
[ORG 0x400000]
|
||||
[ORG 0x800000]
|
||||
global user_test
|
||||
user_test:
|
||||
mov dword [0xb8000], 0x0f000f00 | 'U' | 's' << 16
|
||||
@ -43,6 +43,7 @@ push 0x00000000 ; edx
|
||||
push 0x00000000 ; ebx
|
||||
push 0x00000000 ; esi
|
||||
push 0x00000000 ; edi
|
||||
push 0x00000000 ; ebp
|
||||
push esp ; regs
|
||||
push 0x10 ; interrupt
|
||||
mov eax, 0x86 ; command = 86h, virtual 8086 call
|
||||
|
@ -14,6 +14,7 @@ extern void v86DiskReadCHS();
|
||||
|
||||
union __attribute((__packed__)) V86Regs_t {
|
||||
struct dword_regs {
|
||||
uint32_t ebp;
|
||||
uint32_t edi;
|
||||
uint32_t esi;
|
||||
uint32_t ebx;
|
||||
@ -22,6 +23,7 @@ union __attribute((__packed__)) V86Regs_t {
|
||||
uint32_t eax;
|
||||
} d;
|
||||
struct word_regs {
|
||||
uint16_t bp, _upper_bp;
|
||||
uint16_t di, _upper_di;
|
||||
uint16_t si, _upper_si;
|
||||
uint16_t bx, _upper_bx;
|
||||
@ -30,8 +32,9 @@ union __attribute((__packed__)) V86Regs_t {
|
||||
uint16_t ax, _upper_ax;
|
||||
} w;
|
||||
struct byte_regs {
|
||||
uint16_t di, _upper_di;
|
||||
uint16_t si, _upper_si;
|
||||
uint32_t ebp;
|
||||
uint32_t edi;
|
||||
uint32_t esi;
|
||||
uint8_t bl, bh;
|
||||
uint16_t _upper_bx;
|
||||
uint8_t dl, dh;
|
||||
|
BIN
virtdisk.bin.ex
BIN
virtdisk.bin.ex
Binary file not shown.
Loading…
Reference in New Issue
Block a user