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