Usermode now loads at 0x800000, Virtual 8086 loads consistent DS&ES for data access

This commit is contained in:
Lucia Ceionia 2023-02-17 01:41:30 -06:00
parent 5fe565b6f7
commit d0a5eb4c6f
12 changed files with 86 additions and 52 deletions

View File

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

View File

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

View File

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

View File

@ -3,7 +3,8 @@ ENTRY(entry)
SECTIONS {
. = 0x100000;
_USERMODE = 0x400000;
_USERMODE = 0x800000;
_USERMODE_END = 0x1000000;
.text : {
*(.text);

View File

@ -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();
}

View File

@ -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, &regs);

View File

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

View File

@ -1,5 +1,5 @@
[BITS 32]
[ORG 0x400000]
[ORG 0x800000]
xchg bx,bx
mov edi, 0xB8000
mov ecx, 80*25

View File

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

View File

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

View File

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

Binary file not shown.