Move to git
This commit is contained in:
41
src/boot0.asm
Normal file
41
src/boot0.asm
Normal file
@@ -0,0 +1,41 @@
|
||||
cpu 386
|
||||
|
||||
bits 16
|
||||
org 0x7C00
|
||||
|
||||
start:
|
||||
jmp 0:cseg
|
||||
cseg:
|
||||
cld
|
||||
|
||||
mov ax, 0xB800
|
||||
mov fs, ax
|
||||
|
||||
mov ax, 0x3000
|
||||
mov es, ax
|
||||
|
||||
mov ax, 0x0200 | ((BOOT1_SIZE + 511) / 512)
|
||||
mov cx, 0x0002
|
||||
mov dh, 0
|
||||
mov bx, 0
|
||||
int 0x13
|
||||
|
||||
setc al
|
||||
add al, '0'
|
||||
mov [fs:0], al
|
||||
|
||||
xor ax, ax
|
||||
mov es, ax
|
||||
|
||||
mov ax, 0x3000
|
||||
mov ds, ax
|
||||
|
||||
mov ax, 0x4000 ;Apparently Bochs' BIOS bugs out if below 0x7C00 linear
|
||||
mov ss, ax
|
||||
xor sp, sp
|
||||
|
||||
jmp 0x3000:0
|
||||
|
||||
db "Yo waddup"
|
||||
|
||||
times 446 - ($ - $$) db 0
|
||||
864
src/boot1.asm
Normal file
864
src/boot1.asm
Normal file
@@ -0,0 +1,864 @@
|
||||
cpu 386
|
||||
|
||||
bits 16
|
||||
org 0
|
||||
|
||||
%define BIT_READWRITE (1 << 1)
|
||||
%define BIT_EXECUTABLE (1 << 3)
|
||||
%define BIT_ISCODEORDATA (1 << 4)
|
||||
%define BIT_PRESENT (1 << 7)
|
||||
|
||||
%define PBIT_PRESENT 1
|
||||
%define PBIT_WRITABLE 2
|
||||
%define PBIT_USERLEVEL 4
|
||||
%define PBIT_WRITETHROUGH 8
|
||||
%define PBIT_CACHEDISABLE 16
|
||||
%define PBIT_ACCESSED 32
|
||||
|
||||
MALLOC_MEM equ 0x520
|
||||
|
||||
BOOT1_SEGMENT equ 0x3000
|
||||
BOOT1_ADDR equ (BOOT1_SEGMENT * 0x10)
|
||||
|
||||
start:
|
||||
mov [ld_lba.drive + 1], dl
|
||||
|
||||
mov ah, 8
|
||||
mov di, 0
|
||||
int 0x13
|
||||
mov dl, dh
|
||||
mov dh, 0
|
||||
inc dx
|
||||
mov [lba2chs.numheads + 1], dx
|
||||
and cl, 0x3F
|
||||
mov ch, 0
|
||||
mov [lba2chs.spt + 1], cx
|
||||
|
||||
mov eax, [es:0x7C00 + 0x1BE + 8]
|
||||
mov [get_inode.abs1], eax
|
||||
mov [read_inode.abs1], eax
|
||||
|
||||
mov ecx, 40 * 25
|
||||
mov edi, 0
|
||||
.lup:
|
||||
mov [fs:edi + ecx * 4 - 4], dword 0x0F000F00
|
||||
dec ecx
|
||||
jnz .lup
|
||||
|
||||
mov si, MSG_START
|
||||
mov ax, MSG_START.end - MSG_START
|
||||
call print16
|
||||
|
||||
mov edi, MALLOC_MEM ;Bump allocator pointer
|
||||
|
||||
add edi, 4096
|
||||
mov [TSS.esp0], edi ;End of stack ~ beginning of memory map!!
|
||||
|
||||
a20:
|
||||
cli
|
||||
call .waito
|
||||
mov al, 0xAD
|
||||
out 0x64, al
|
||||
call .waito
|
||||
mov al, 0xD0
|
||||
out 0x64, al
|
||||
.waiti:
|
||||
in al, 0x64
|
||||
test al, 1
|
||||
jz .waiti
|
||||
in al, 0x60
|
||||
push ax
|
||||
call .waito
|
||||
mov al, 0xD1
|
||||
out 0x64, al
|
||||
call .waito
|
||||
pop ax
|
||||
or al, 2
|
||||
out 0x60, al
|
||||
call .waito
|
||||
mov al, 0xAE
|
||||
out 0x64, al
|
||||
call .waito
|
||||
sti
|
||||
jmp ramdetect
|
||||
.waito:
|
||||
in al, 0x64
|
||||
test al, 2
|
||||
jnz .waito
|
||||
ret
|
||||
|
||||
ramdetect: ;Currently only detects RAM below 16MB, which will be enough for a while.
|
||||
clc
|
||||
int 0x12
|
||||
jc .fail
|
||||
mov [es:di + 0], dword 0
|
||||
mov [es:di + 4], dword 0
|
||||
movzx ecx, ax
|
||||
shr cx, 2
|
||||
mov [es:di + 8], ecx
|
||||
mov [es:di + 12], byte 0
|
||||
add di, 13
|
||||
mov al, 0
|
||||
add cx, 7
|
||||
shr cx, 3
|
||||
rep stosb
|
||||
|
||||
xor cx, cx
|
||||
xor dx, dx
|
||||
mov ax, 0xE801
|
||||
int 0x15
|
||||
jc .fail
|
||||
cmp ah, 0x86
|
||||
je .fail
|
||||
cmp ah, 0x80
|
||||
je .fail
|
||||
jcxz .useax
|
||||
mov ax, cx
|
||||
mov bx, dx
|
||||
.useax:
|
||||
mov [es:di + 0], dword 0x100000
|
||||
mov [es:di + 4], dword 0
|
||||
movzx ecx, ax
|
||||
shr ecx, 2
|
||||
mov [es:di + 8], ecx
|
||||
mov [es:di + 12], byte 0
|
||||
add di, 13
|
||||
mov al, 0
|
||||
shr ecx, 3
|
||||
rep stosb
|
||||
jmp .foundMMap
|
||||
|
||||
.fail:
|
||||
mov si, MSG_FAIL
|
||||
mov ax, MSG_FAIL.end - MSG_FAIL
|
||||
call print16
|
||||
|
||||
jmp $
|
||||
.foundMMap:
|
||||
mov si, MSG_DETECTED_MEMORY_MAP
|
||||
mov ax, MSG_DETECTED_MEMORY_MAP.end - MSG_DETECTED_MEMORY_MAP
|
||||
call print16
|
||||
|
||||
pg:
|
||||
; Create page directory
|
||||
add edi, 4095
|
||||
and edi, ~4095
|
||||
mov cr3, edi ;In advance
|
||||
lea eax, [edi + 4096]
|
||||
or eax, PBIT_PRESENT | PBIT_WRITABLE
|
||||
mov [es:edi], eax
|
||||
add edi, 4
|
||||
mov eax, 0
|
||||
mov ecx, 1023
|
||||
rep stosd
|
||||
|
||||
mov ecx, 192
|
||||
mov edx, PBIT_PRESENT | PBIT_WRITABLE
|
||||
.lup:
|
||||
mov [es:edi], edx
|
||||
add edi, 4
|
||||
add edx, 4096
|
||||
dec ecx
|
||||
jnz .lup
|
||||
|
||||
mov ecx, 1024 - 192
|
||||
mov eax, 0
|
||||
rep stosd
|
||||
|
||||
mov eax, cr3 ;Back to the page directory
|
||||
mov [es:eax + 4092], edi
|
||||
or dword [es:eax + 4092], PBIT_PRESENT | PBIT_WRITABLE
|
||||
mov [es:edi + 4092], edi
|
||||
or dword [es:edi + 4092], PBIT_PRESENT | PBIT_WRITABLE
|
||||
add edi, 4096
|
||||
|
||||
mov esi, MSG_STEP3s
|
||||
mov eax, MSG_STEP3s.end - MSG_STEP3s
|
||||
call print16
|
||||
|
||||
loadkernel:
|
||||
mov eax, 2 ;root
|
||||
call get_inode
|
||||
mov bx, di
|
||||
call read_inode
|
||||
mov eax, edi
|
||||
mov esi, KERNEL_FILE
|
||||
mov ecx, KERNEL_FILE.end - KERNEL_FILE
|
||||
call find_in_dirnode
|
||||
test eax, eax
|
||||
jnz .found
|
||||
|
||||
mov si, MSG_STEP5f
|
||||
mov ax, MSG_STEP5f.end - MSG_STEP5f
|
||||
call print16
|
||||
jmp $
|
||||
.found:
|
||||
call get_inode
|
||||
mov bx, di
|
||||
call read_inode
|
||||
; Now edi is kernel location, ebx is after kernel.
|
||||
call fix_module_addresses
|
||||
mov [inPE.KERNEL_START], edi
|
||||
mov edi, ebx ;Allocate modules after kernel
|
||||
;~ mov [inPE.MODULES_START], edi
|
||||
|
||||
loadmods:
|
||||
mov eax, 2
|
||||
call get_inode
|
||||
mov esi, [endSector + 32] ;filesize
|
||||
push es
|
||||
push ds
|
||||
pop es
|
||||
mov bx, endSector + 0x200 ;Will break if root directory is larger than 1KB.
|
||||
call read_inode
|
||||
pop es
|
||||
mov eax, endSector + 0x200
|
||||
.lup: ;Loop over files, the names of which end with ".mod"
|
||||
movzx ecx, word [eax + 10] ;Length of name
|
||||
lea edx, [eax + 12] ;Get name string
|
||||
cmp ecx, 4 ;Test if shorter than 4 characters
|
||||
jb .cont
|
||||
.testext:
|
||||
cmp [eax + ecx + 12 - 4], dword ".mod"
|
||||
jne .cont
|
||||
.testkrnl:
|
||||
cmp [eax + 12], dword "krnl"
|
||||
je .cont
|
||||
.ismod:
|
||||
inc dword [inPE.MOD_COUNT]
|
||||
push eax
|
||||
mov eax, [eax] ;inode
|
||||
call get_inode
|
||||
call page_align_es_edi
|
||||
push esi
|
||||
mov esi, cr3
|
||||
mov cx, 1024
|
||||
push ds
|
||||
push word 0
|
||||
pop ds
|
||||
rep movsd ;Copy page directory to one local to process
|
||||
pop ds
|
||||
pop esi
|
||||
mov bx, di
|
||||
call read_inode ;edi = start, ebx = end
|
||||
mov di, bx
|
||||
pop eax
|
||||
.cont:
|
||||
movzx ecx, byte [eax + 9]
|
||||
shl cx, 4
|
||||
add eax, ecx
|
||||
sub esi, ecx
|
||||
jnz .lup
|
||||
.end:
|
||||
mov di, es
|
||||
shl edi, 4
|
||||
add edi, 4095
|
||||
and edi, ~4095
|
||||
mov [inPE.IMPORTANT_MEM_END], edi
|
||||
xor ax, ax
|
||||
mov es, ax
|
||||
|
||||
add ebx, edi
|
||||
fixmmap: ; Make all module memories "used"
|
||||
lea ecx, [es:ebx + 4095]
|
||||
shr ecx, 12
|
||||
mov ebx, ecx
|
||||
and ebx, 7
|
||||
shr ecx, 3
|
||||
mov edi, [TSS.esp0]
|
||||
add edi, 13
|
||||
push edi
|
||||
mov al, -1
|
||||
rep stosb
|
||||
mov ecx, ebx
|
||||
mov al, 1
|
||||
shl al, cl
|
||||
dec al
|
||||
mov [es:edi], al
|
||||
pop edi
|
||||
or [es:edi + (BOOT1_ADDR / 4096 / 8)], byte 3 ; TODO: Let boot1 get overwritten after load
|
||||
|
||||
modex:
|
||||
mov ax, 0x13
|
||||
int 0x10
|
||||
|
||||
mov dx, 0x3C4
|
||||
mov al, 4
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
mov al, 6
|
||||
out dx, al
|
||||
|
||||
mov dx, 0x3D4
|
||||
mov al, 0x14
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
xor al, al
|
||||
out dx, al
|
||||
|
||||
dec dx
|
||||
mov al, 0x17
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
mov al, 0xE3
|
||||
out dx, al
|
||||
|
||||
dec dx
|
||||
mov al, 0x11
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
mov al, 0x2C
|
||||
out dx, al
|
||||
|
||||
dec dx
|
||||
mov al, 0x06
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
mov al, 0x0D
|
||||
out dx, al
|
||||
|
||||
dec dx
|
||||
mov al, 0x07
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
mov al, 0x3E
|
||||
out dx, al
|
||||
|
||||
dec dx
|
||||
mov al, 0x10
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
mov al, 0xEA
|
||||
out dx, al
|
||||
|
||||
dec dx
|
||||
mov al, 0x11
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
mov al, 0xAC
|
||||
out dx, al
|
||||
|
||||
dec dx
|
||||
mov al, 0x12
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
mov al, 0xDF
|
||||
out dx, al
|
||||
|
||||
dec dx
|
||||
mov al, 0x15
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
mov al, 0xE7
|
||||
out dx, al
|
||||
|
||||
dec dx
|
||||
mov al, 0x16
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
mov al, 0x06
|
||||
out dx, al
|
||||
|
||||
; ESP should be zero here.
|
||||
push strict dword BOOT1_ADDR + inPE
|
||||
mov esp, BOOT1_ADDR + 0x10000 + 0xFFFC
|
||||
jmp enterPM
|
||||
|
||||
enterPM:
|
||||
cli
|
||||
or [GDT.R0CSLIMFLAGS], byte 64 ;Make 32-bit
|
||||
lgdt [GDT]
|
||||
mov eax, cr0
|
||||
or eax, 1 | (1 << 31)
|
||||
mov cr0, eax
|
||||
jmp 8:dword BOOT1_ADDR + .inPM
|
||||
.inPM:
|
||||
bits 32
|
||||
mov eax, 0x23
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov al, 0x10
|
||||
mov ss, ax
|
||||
ret
|
||||
|
||||
enterRM:
|
||||
and [GDT.R0CSLIMFLAGS], byte ~64 ;Make 16-bit
|
||||
lgdt [GDT]
|
||||
jmp 8:.in16
|
||||
.in16:
|
||||
bits 16
|
||||
mov eax, cr0
|
||||
and eax, ~(1 | (1 << 31))
|
||||
mov cr0, eax
|
||||
jmp 0:.inRM
|
||||
.inRM:
|
||||
mov ax, 0
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
sti
|
||||
ret
|
||||
|
||||
; Makes es:edi a normalized far pointer
|
||||
normalize_es_edi:
|
||||
push eax
|
||||
push edi
|
||||
mov ax, es
|
||||
shr di, 4
|
||||
add ax, di
|
||||
mov es, ax
|
||||
pop edi
|
||||
and edi, 15
|
||||
pop eax
|
||||
ret
|
||||
|
||||
page_align_es_edi:
|
||||
push eax
|
||||
xor eax, eax
|
||||
mov ax, es
|
||||
shl eax, 4
|
||||
add eax, edi
|
||||
add eax, 4095
|
||||
and eax, ~4095
|
||||
shr eax, 4
|
||||
mov es, ax
|
||||
pop eax
|
||||
xor edi, edi
|
||||
ret
|
||||
|
||||
print16:
|
||||
push di
|
||||
push cx
|
||||
push ax
|
||||
.ind:
|
||||
mov di, 0
|
||||
mov cx, ax
|
||||
.lup:
|
||||
mov al, [ds:si]
|
||||
mov [fs:di], al
|
||||
inc si
|
||||
inc di
|
||||
inc di
|
||||
dec cx
|
||||
jnz .lup
|
||||
mov [.ind + 1], di ;SMC
|
||||
pop ax
|
||||
pop cx
|
||||
pop di
|
||||
ret
|
||||
|
||||
ld_lba:
|
||||
pushad
|
||||
call lba2chs
|
||||
mov ch, al
|
||||
mov dh, dl
|
||||
.drive:
|
||||
mov dl, 0
|
||||
mov ah, 2
|
||||
mov al, 1
|
||||
int 0x13
|
||||
popad
|
||||
ret
|
||||
|
||||
; In: AX = lba
|
||||
; Out: CX = sector, AX = cylinder, DX = head
|
||||
lba2chs:
|
||||
push bx
|
||||
.spt:
|
||||
mov bx, 0xF157
|
||||
xor dx, dx
|
||||
div bx
|
||||
mov cx, dx
|
||||
inc cx
|
||||
.numheads:
|
||||
mov bx, 0x9001
|
||||
xor dx, dx
|
||||
div bx
|
||||
pop bx
|
||||
ret
|
||||
|
||||
; In: EAX = inode
|
||||
; Out: *BOOT1_SEGMENT:endSector = inode struct
|
||||
get_inode:
|
||||
push eax
|
||||
push ebx
|
||||
.abs1 equ ($ + 2)
|
||||
add eax, strict dword 0xABCDEF42
|
||||
push es
|
||||
push ds
|
||||
pop es
|
||||
mov bx, endSector
|
||||
call ld_lba
|
||||
pop es
|
||||
pop ebx
|
||||
pop eax
|
||||
ret
|
||||
|
||||
; In: *BOOT1_SEGMENT:endSector = inode struct
|
||||
; Out: *ES:BX = data
|
||||
read_inode:
|
||||
push edx
|
||||
push ecx
|
||||
push eax
|
||||
push esi
|
||||
push edi
|
||||
push ebx
|
||||
|
||||
mov dl, [endSector + 8] ;extent count
|
||||
mov ecx, endSector + 104 ;extent starts
|
||||
|
||||
.lup:
|
||||
mov eax, [ecx] ;start
|
||||
mov esi, [ecx + 48] ;size of extent
|
||||
.abs1 equ ($ + 2)
|
||||
add eax, strict dword 0x12345678
|
||||
|
||||
.lup2:
|
||||
call ld_lba
|
||||
add bx, 512
|
||||
inc eax
|
||||
dec esi
|
||||
jnz .lup2
|
||||
|
||||
add ecx, 8
|
||||
dec dl
|
||||
jnz .lup
|
||||
|
||||
mov edi, [esp] ;dest address
|
||||
lea esi, [edi + 176]
|
||||
test dword [endSector + 28], 1 << 19
|
||||
jz .doesntHaveInline
|
||||
add esi, 512 - 176
|
||||
.doesntHaveInline:
|
||||
mov ecx, [endSector + 32] ;filesize
|
||||
push ds
|
||||
push es
|
||||
pop ds
|
||||
rep movsb
|
||||
pop ds
|
||||
|
||||
add esp, 4 ;ignore old ebx, because read_inode should return the addr after
|
||||
pop edi
|
||||
pop esi
|
||||
pop eax
|
||||
pop ecx
|
||||
pop edx
|
||||
ret
|
||||
|
||||
; In: *ES:EAX = directory content buffer, *ESI = name to test, ECX = name length
|
||||
; Out: EAX = inode or 0 if not found
|
||||
find_in_dirnode:
|
||||
push ebx
|
||||
push edx
|
||||
push edi
|
||||
|
||||
mov edi, [endSector + 32] ;filesize
|
||||
.lup:
|
||||
movzx edx, word [es:eax + 10] ;record name length
|
||||
cmp dx, cx
|
||||
.lup2:
|
||||
dec dx
|
||||
mov bl, [es:eax + 12 + edx]
|
||||
cmp bl, [esi + edx]
|
||||
jne .next
|
||||
test dx, dx
|
||||
jnz .lup2
|
||||
jmp .found
|
||||
.next:
|
||||
movzx edx, byte [es:eax + 9] ;record length
|
||||
shl dx, 4
|
||||
add eax, edx
|
||||
sub edi, edx
|
||||
jnz .lup
|
||||
|
||||
mov eax, 0
|
||||
jmp .end
|
||||
.found:
|
||||
mov eax, [es:eax]
|
||||
.end:
|
||||
pop edi
|
||||
pop edx
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
fix_module_addresses:
|
||||
push esi
|
||||
push ecx
|
||||
push eax
|
||||
push ebx
|
||||
|
||||
movzx ecx, word [es:edi + 4] ;amount of syms
|
||||
lea esi, [es:edi + 12 + ecx * 4]
|
||||
lea esi, [es:esi + ecx * 2]
|
||||
movzx ecx, word [es:edi + 6] ;amount of relocs
|
||||
mov eax, esi ;ptr to relocs
|
||||
lea esi, [esi + ecx * 4] ;ptr to data
|
||||
add esi, 15
|
||||
and esi, ~15
|
||||
mov [es:edi], esi ;Replace the MOD\0 magic header with the base address
|
||||
test ecx, ecx ;If none, end
|
||||
jz .end
|
||||
.lup:
|
||||
; Apply relocation
|
||||
mov ebx, [es:eax]
|
||||
add ebx, esi
|
||||
add [es:ebx], esi
|
||||
|
||||
add eax, 4
|
||||
dec ecx
|
||||
jnz .lup
|
||||
.end:
|
||||
|
||||
pop ebx
|
||||
pop eax
|
||||
pop ecx
|
||||
pop esi
|
||||
ret
|
||||
|
||||
bits 32
|
||||
|
||||
inPE:
|
||||
mov [BOOT1_ADDR + TSS.ss0], dword 0x10
|
||||
mov esp, [BOOT1_ADDR + TSS.esp0]
|
||||
|
||||
mov eax, 40
|
||||
ltr ax
|
||||
|
||||
mov ax, [BOOT1_ADDR + print16.ind + 1]
|
||||
mov [BOOT1_ADDR + print32.LAST], ax
|
||||
|
||||
mov esi, BOOT1_ADDR + MSG_STEP2s
|
||||
mov eax, MSG_STEP2s.end - MSG_STEP2s
|
||||
call print32
|
||||
|
||||
.KERNEL_START equ ($ + 1)
|
||||
mov edi, strict dword 0
|
||||
lea ebx, [edi + 14]
|
||||
; Sym 0: ppm_Bitmap
|
||||
mov eax, [ebx]
|
||||
add eax, [edi] ;Base address that used to be magic header
|
||||
push dword [BOOT1_ADDR + TSS.esp0] ;As said before, end of stack ~ beginning of mmap!
|
||||
pop dword [eax]
|
||||
add ebx, 6
|
||||
; Sym 1: vpm_init
|
||||
mov eax, [ebx]
|
||||
add eax, [edi]
|
||||
.IMPORTANT_MEM_END equ ($ + 1)
|
||||
push strict dword 0
|
||||
call eax
|
||||
add esp, 4
|
||||
add ebx, 6
|
||||
; Sym 2: vpm_map
|
||||
mov eax, [ebx]
|
||||
add eax, [edi]
|
||||
mov [BOOT1_ADDR + .VPM_MAP_ENTRY], eax
|
||||
add ebx, 6
|
||||
; Sym 3: canal_init
|
||||
mov eax, [ebx]
|
||||
add eax, [edi]
|
||||
call eax
|
||||
add ebx, 6
|
||||
; Sym 4: pci_init
|
||||
mov eax, [ebx]
|
||||
add eax, [edi]
|
||||
call eax
|
||||
add ebx, 6
|
||||
; Sym 5: scheduler_init
|
||||
mov eax, [ebx]
|
||||
add eax, [edi]
|
||||
call eax
|
||||
add ebx, 6
|
||||
; Sym 6: scheduler_spawn
|
||||
mov eax, [ebx]
|
||||
add eax, [edi]
|
||||
mov [BOOT1_ADDR + .SCHEDULER_SPAWN_ENTRY], eax
|
||||
add ebx, 6
|
||||
; Sym 7: scheduler_start
|
||||
mov eax, [ebx]
|
||||
add eax, [edi]
|
||||
mov [BOOT1_ADDR + .SCHEDULER_START_ENTRY], eax
|
||||
|
||||
.MOD_COUNT equ ($ + 1)
|
||||
mov ebp, strict dword 0
|
||||
.modspawnlup:
|
||||
; Find next module
|
||||
movzx ecx, word [edi + 4]
|
||||
lea eax, [edi + ecx * 4]
|
||||
lea eax, [eax + ecx * 2]
|
||||
movzx ecx, word [edi + 6]
|
||||
lea eax, [eax + ecx * 4]
|
||||
add eax, 15
|
||||
and eax, ~15
|
||||
mov ecx, [edi + 8]
|
||||
lea eax, [eax + ecx]
|
||||
add eax, 4096 + 4095
|
||||
and eax, ~4095
|
||||
mov edi, eax
|
||||
mov ebx, 0x40000000
|
||||
call rebase_module32
|
||||
sub edx, edi
|
||||
|
||||
push strict dword edx
|
||||
push strict dword edi
|
||||
push strict dword 0x40000000
|
||||
push strict dword 1 ;user
|
||||
lea eax, [edi - 4096] ; cr3
|
||||
push eax
|
||||
.VPM_MAP_ENTRY equ ($ + 1)
|
||||
mov eax, strict dword 0
|
||||
call eax
|
||||
add esp, 20
|
||||
|
||||
push strict dword 0
|
||||
.SCHEDULER_SPAWN_ENTRY equ ($ + 1)
|
||||
mov eax, strict dword 0
|
||||
call eax
|
||||
add esp, 4
|
||||
lea ebx, [edi - 4096]
|
||||
mov [eax + 46], ebx ;cr3
|
||||
mov ebx, [edi + 14] ;get sym 0 (modentry)
|
||||
add ebx, [edi] ;add data offset
|
||||
mov [eax + 34], ebx ;eip
|
||||
|
||||
dec ebp
|
||||
jnz .modspawnlup
|
||||
|
||||
.SCHEDULER_START_ENTRY equ ($ + 1)
|
||||
mov eax, strict dword 0
|
||||
jmp eax
|
||||
|
||||
print32:
|
||||
push ebx
|
||||
push eax
|
||||
push ecx
|
||||
movzx ebx, word [BOOT1_ADDR + .LAST]
|
||||
mov ecx, eax
|
||||
.lup:
|
||||
mov al, [esi]
|
||||
mov [0xB8000 + ebx], al
|
||||
inc esi
|
||||
inc ebx
|
||||
inc ebx
|
||||
dec ecx
|
||||
jnz .lup
|
||||
mov [BOOT1_ADDR + .LAST], bx
|
||||
pop ecx
|
||||
pop eax
|
||||
pop ebx
|
||||
ret
|
||||
.LAST: dw 0
|
||||
|
||||
; In: EDI = module pointer, EBX = rebase address
|
||||
; Out: EDX = physical module end
|
||||
rebase_module32:
|
||||
push ecx
|
||||
push eax
|
||||
push ebx
|
||||
push ebp
|
||||
movzx ecx, word [edi + 4]
|
||||
lea eax, [edi + 12 + ecx * 2]
|
||||
lea eax, [eax + ecx * 4] ; eax = relocations pointer
|
||||
movzx ecx, word [edi + 6] ;ecx = amount of relocations
|
||||
lea edx, [eax + ecx * 4] ; edx = data pointer
|
||||
add edx, 15
|
||||
and edx, ~15
|
||||
mov [edi], edx ;Store offset of data buffer in
|
||||
sub [edi], edi ;file in place of magic header
|
||||
add [edi], ebx ;
|
||||
mov ebx, [edi]
|
||||
test ecx, ecx
|
||||
jz .end
|
||||
.lup:
|
||||
mov ebp, [eax]
|
||||
add [edx + ebp], ebx
|
||||
add eax, 4
|
||||
dec ecx
|
||||
jnz .lup
|
||||
.end:
|
||||
add edx, [edi + 8]
|
||||
pop ebp
|
||||
pop ebx
|
||||
pop eax
|
||||
pop ecx
|
||||
ret
|
||||
|
||||
MSG_FAIL: db "Failed to detect memory map. "
|
||||
.end:
|
||||
|
||||
MSG_START: db "Starting eklernel. "
|
||||
.end:
|
||||
|
||||
MSG_DETECTED_MEMORY_MAP: db "Found memory map. "
|
||||
.end:
|
||||
|
||||
MSG_STEP2s: db "Entered protected mode. "
|
||||
.end:
|
||||
|
||||
MSG_STEP3s: db "Generated paging structures. "
|
||||
.end:
|
||||
|
||||
MSG_STEP4f: db "Boot filesystem must have block size of 1024. "
|
||||
.end:
|
||||
|
||||
KERNEL_FILE: db "krnl.mod"
|
||||
.end:
|
||||
|
||||
MSG_STEP5f: db "Kernel not found; aborting boot. "
|
||||
.end:
|
||||
|
||||
GDT:
|
||||
dw (GDT.END - GDT) - 1 ;GDT descriptor in the null entry
|
||||
dd BOOT1_ADDR + GDT
|
||||
dw 0
|
||||
|
||||
dw 0xFFFF, 0x0000
|
||||
db 0x00, BIT_READWRITE | BIT_EXECUTABLE | BIT_ISCODEORDATA | BIT_PRESENT | (0 << 5)
|
||||
.R0CSLIMFLAGS:
|
||||
db (128 | 64) | 0xF
|
||||
db 0
|
||||
|
||||
dw 0xFFFF, 0x0000
|
||||
db 0x00, BIT_READWRITE | BIT_ISCODEORDATA | BIT_PRESENT | (0 << 5)
|
||||
db (128 | 64) | 0xF
|
||||
db 0
|
||||
|
||||
dw 0xFFFF, 0x0000
|
||||
db 0x00, BIT_READWRITE | BIT_EXECUTABLE | BIT_ISCODEORDATA | BIT_PRESENT | (3 << 5)
|
||||
db (128 | 64) | 0xF
|
||||
db 0
|
||||
|
||||
dw 0xFFFF, 0x0000
|
||||
db 0x00, BIT_READWRITE | BIT_ISCODEORDATA | BIT_PRESENT | (3 << 5)
|
||||
db (128 | 64) | 0xF
|
||||
db 0
|
||||
|
||||
dw (TSS.END - TSS) - 1
|
||||
dw TSS
|
||||
db BOOT1_ADDR / 0x10000, 1 | 8 | 128
|
||||
db 0, 0
|
||||
.END:
|
||||
TSS:
|
||||
dd 0
|
||||
.esp0: dd 0
|
||||
.ss0: dd 0
|
||||
times 23 dd 0
|
||||
.END:
|
||||
|
||||
end:
|
||||
times (end - start + 511) / 512 * 512 - ($ - $$) db 0
|
||||
endSector:
|
||||
181
src/kernel/arch/x86/canal.c
Normal file
181
src/kernel/arch/x86/canal.c
Normal file
@@ -0,0 +1,181 @@
|
||||
#include"canal.h"
|
||||
|
||||
#include"vpm.h"
|
||||
#include"mem.h"
|
||||
#include"scheduler.h"
|
||||
#include"ppm.h"
|
||||
|
||||
static inline void pr(int c) {
|
||||
asm volatile("outb %%al, $0xE9" :: "a"(c) :);
|
||||
}
|
||||
|
||||
static inline void pri(size_t num) {
|
||||
char buf[16] = {};
|
||||
int i = 16;
|
||||
|
||||
do {
|
||||
buf[--i] = num % 10;
|
||||
num /= 10;
|
||||
} while(num);
|
||||
|
||||
for(; i < 16; i++) {
|
||||
pr(buf[i] + '0');
|
||||
}
|
||||
}
|
||||
|
||||
static inline void prcs(const char *str) {
|
||||
while(*str) {
|
||||
pr(*str);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
static Canal *canals = 0;
|
||||
static Link *links = 0;
|
||||
|
||||
void canal_init() {
|
||||
uint32_t cr3;
|
||||
asm volatile("movl %%cr3, %0" : "=r"(cr3) :);
|
||||
|
||||
canals = vpm_map(cr3, VPM_KERNEL, -1, -1, 4096);
|
||||
kmemw1(canals, 0, 4096);
|
||||
|
||||
links = vpm_map(cr3, VPM_KERNEL, -1, -1, 4096);
|
||||
kmemw1(links, 0xFF, 4096);
|
||||
}
|
||||
|
||||
uint32_t canal_create(uint64_t name, uint16_t hostProcessId) {
|
||||
Process *hostProcess = scheduler_find(hostProcessId);
|
||||
|
||||
for(int i = 0; i < 4096 / sizeof(Canal); i++) {
|
||||
if(canals[i].name == name) return -2;
|
||||
|
||||
if(canals[i].name == 0) {
|
||||
canals[i].name = name;
|
||||
canals[i].hostProcess = hostProcess;
|
||||
canals[i].links = NULL;
|
||||
|
||||
canals[i].ownedNext = hostProcess->ownedCanal;
|
||||
hostProcess->ownedCanal = &canals[i];
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t link_create(uint64_t canalName, uint16_t guestProcessId, uint32_t areaSize) {
|
||||
int canalId = -1;
|
||||
for(int i = 0; i < 4096 / sizeof(Canal); i++) {
|
||||
if(canals[i].name == canalName) {
|
||||
canalId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Process *guest = scheduler_find(guestProcessId);
|
||||
|
||||
if(canalId == -1) return -1;
|
||||
if(canals[canalId].hostProcess == guest) return -1;
|
||||
|
||||
uint32_t hostCR3 = canals[canalId].hostProcess->ctx.cr3;
|
||||
uint32_t hostAreaVirtAddr = vpm_find_free(hostCR3, VPM_USER, areaSize);
|
||||
|
||||
uint32_t guestCR3 = guest->ctx.cr3;
|
||||
uint32_t guestAreaVirtAddr = vpm_find_free(guestCR3, VPM_USER, areaSize);
|
||||
|
||||
/* TODO: Fail if areas not found. */
|
||||
|
||||
for(int i = 0; i < 4096 / sizeof(Link); i++) {
|
||||
if(links[i].canalId == -1) {
|
||||
links[i].canalId = canalId;
|
||||
links[i].guestProcess = guest;
|
||||
links[i].hostVirtAddr = hostAreaVirtAddr;
|
||||
links[i].guestVirtAddr = guestAreaVirtAddr;
|
||||
links[i].flags = 0;
|
||||
|
||||
uint32_t pages = (areaSize + 4095) / 4096;
|
||||
|
||||
uint32_t phys = ppm_alloc(pages);
|
||||
vpm_map(hostCR3, VPM_USER, hostAreaVirtAddr, phys, areaSize);
|
||||
vpm_map(guestCR3, VPM_USER, guestAreaVirtAddr, phys, areaSize);
|
||||
|
||||
canals[canalId].hostProcess->eventsRequest++;
|
||||
|
||||
links[i].nextInCanal = canals[canalId].links;
|
||||
canals[canalId].links = &links[i];
|
||||
|
||||
links[i].nextGuestLink = guest->guestLinks;
|
||||
guest->guestLinks = &links[i];
|
||||
|
||||
return guestAreaVirtAddr;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t canal_accept(uint16_t hostProcessId, uint32_t canalId) {
|
||||
for(int i = 0; i < 4096 / sizeof(Link); i++) {
|
||||
if(links[i].canalId != -1 && canals[links[i].canalId].hostProcess->id == hostProcessId && (canalId == (uint32_t)-1 || links[i].canalId == canalId) && !(links[i].flags & LINK_FLAG_ACCEPTED)) {
|
||||
links[i].flags = links[i].flags | LINK_FLAG_ACCEPTED;
|
||||
prcs("RETURNING ");
|
||||
pri(links[i].hostVirtAddr);
|
||||
pr('\n');
|
||||
return links[i].hostVirtAddr;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void link_send_signal_from(uint16_t processId, uint32_t processAreaAddr, uint32_t meta) {
|
||||
for(int i = 0; i < 4096 / sizeof(Link); i++) {
|
||||
if(links[i].guestProcess->id == processId && links[i].guestVirtAddr == processAreaAddr) {
|
||||
if(!(links[i].flags & LINK_FLAG_G2H)) {
|
||||
canals[links[i].canalId].hostProcess->eventsSignal++;
|
||||
links[i].flags |= LINK_FLAG_G2H;
|
||||
}
|
||||
|
||||
links[i].metaG2H = meta;
|
||||
|
||||
return;
|
||||
} else if(canals[links[i].canalId].hostProcess->id == processId && links[i].hostVirtAddr == processAreaAddr) {
|
||||
if(!(links[i].flags & LINK_FLAG_H2G)) {
|
||||
links[i].guestProcess->eventsSignal++;
|
||||
links[i].flags |= LINK_FLAG_H2G;
|
||||
}
|
||||
|
||||
links[i].metaH2G = meta;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t is_signal_awaiting_to_concerning_link(uint16_t processId, uint32_t area, uint32_t *metaOut, uint32_t *canalId) {
|
||||
for(int i = 0; i < 4096 / sizeof(Link); i++) {
|
||||
if((links[i].guestProcess->id == processId && (area == -1 || links[i].guestVirtAddr == area) && (links[i].flags & LINK_FLAG_H2G))
|
||||
|| (canals[links[i].canalId].hostProcess->id == processId && (area == -1 || area == links[i].hostVirtAddr) && (links[i].flags & LINK_FLAG_G2H))) {
|
||||
|
||||
*canalId = links[i].canalId;
|
||||
|
||||
return signal_accept(scheduler_find(processId), &links[i], metaOut);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t signal_accept(Process *p, Link *l, uint32_t *meta) {
|
||||
p->eventsSignal--;
|
||||
|
||||
if(l->guestProcess == p) {
|
||||
l->flags &= ~LINK_FLAG_H2G;
|
||||
*meta = l->metaH2G;
|
||||
return l->guestVirtAddr;
|
||||
} else {
|
||||
l->flags &= ~LINK_FLAG_G2H;
|
||||
*meta = l->metaG2H;
|
||||
return l->hostVirtAddr;
|
||||
}
|
||||
}
|
||||
42
src/kernel/arch/x86/canal.h
Normal file
42
src/kernel/arch/x86/canal.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef _CANAL_H
|
||||
#define _CANAL_H
|
||||
|
||||
#include<stdint.h>
|
||||
|
||||
#define LINK_FLAG_ACCEPTED 1
|
||||
|
||||
#define LINK_FLAG_G2H 2
|
||||
#define LINK_FLAG_H2G 4
|
||||
|
||||
struct Process;
|
||||
struct Link;
|
||||
|
||||
typedef struct Canal {
|
||||
uint64_t name;
|
||||
struct Process *hostProcess;
|
||||
struct Canal *ownedNext;
|
||||
struct Link *links;
|
||||
} __attribute__((packed)) Canal;
|
||||
|
||||
typedef struct Link {
|
||||
uint32_t canalId;
|
||||
uint32_t hostVirtAddr;
|
||||
struct Process *guestProcess;
|
||||
uint32_t guestVirtAddr;
|
||||
uint32_t metaG2H;
|
||||
uint32_t metaH2G;
|
||||
uint8_t flags;
|
||||
struct Link *nextInCanal;
|
||||
struct Link *nextGuestLink;
|
||||
} __attribute__((packed)) Link;
|
||||
|
||||
uint32_t canal_create(uint64_t name, uint16_t hostProcessId);
|
||||
uint32_t link_create(uint64_t canal, uint16_t guestProcessId, uint32_t areaSize);
|
||||
uint32_t canal_accept(uint16_t hostProcessId, uint32_t canalId);
|
||||
void link_send_signal_from(uint16_t processId, uint32_t processAreaAddr, uint32_t meta);
|
||||
uint32_t link_get_oldest_signal_to(uint16_t processId);
|
||||
uint32_t is_signal_awaiting_to_concerning_link(uint16_t processId, uint32_t area, uint32_t *metaOut, uint32_t *canalId);
|
||||
|
||||
uint32_t signal_accept(struct Process *p, Link *l, uint32_t *meta);
|
||||
|
||||
#endif
|
||||
20
src/kernel/arch/x86/consts.h
Normal file
20
src/kernel/arch/x86/consts.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef _X86_CONSTS_H
|
||||
#define _X86_CONSTS_H
|
||||
|
||||
#define EFLAGS_IOPL_0 (0 << 12)
|
||||
#define EFLAGS_IOPL_1 (1 << 12)
|
||||
#define EFLAGS_IOPL_2 (2 << 12)
|
||||
#define EFLAGS_IOPL_3 (3 << 12)
|
||||
#define EFLAGS_IF (1 << 9)
|
||||
#define EFLAGS_RESET 2
|
||||
|
||||
#define RPL_0 0
|
||||
#define RPL_1 1
|
||||
#define RPL_2 2
|
||||
#define RPL_3 3
|
||||
|
||||
#define PAGE_BIT_PRESENT 1
|
||||
#define PAGE_BIT_WRITABLE 2
|
||||
#define PAGE_BIT_USER 4
|
||||
|
||||
#endif
|
||||
827
src/kernel/arch/x86/interrupt.asm
Normal file
827
src/kernel/arch/x86/interrupt.asm
Normal file
@@ -0,0 +1,827 @@
|
||||
cpu 386
|
||||
bits 32
|
||||
|
||||
TIMER_FREQUENCY equ 250;Hz
|
||||
|
||||
; TODO: perform IO waits
|
||||
|
||||
section .text
|
||||
|
||||
extern scheduler_switch
|
||||
extern scheduler_CurrentProcess
|
||||
pit_handler:
|
||||
extern scheduler_Tick
|
||||
inc dword [scheduler_Tick]
|
||||
push eax
|
||||
mov al, 0x20
|
||||
out 0x20, al
|
||||
pop eax
|
||||
|
||||
ctx_switch:
|
||||
push eax
|
||||
|
||||
mov eax, [scheduler_CurrentProcess]
|
||||
test eax, eax
|
||||
jnz .a
|
||||
add esp, 16
|
||||
jmp .b
|
||||
.a:
|
||||
pop dword [eax + 2] ;eax
|
||||
pop dword [eax + 34] ;eip
|
||||
pop dword [eax + 42] ;cs
|
||||
pop dword [eax + 38] ;eflags
|
||||
mov [eax + 6], ebx
|
||||
mov [eax + 10], ecx
|
||||
mov [eax + 14], edx
|
||||
mov [eax + 18], esi
|
||||
mov [eax + 22], edi
|
||||
mov [eax + 26], ebp
|
||||
cmp dword [eax + 42], 8 ;CS 8 implies ring 0
|
||||
jne .isR3
|
||||
mov [eax + 30], esp
|
||||
jmp .b
|
||||
.isR3:
|
||||
pop dword [eax + 30] ;esp
|
||||
add esp, 4 ;ss
|
||||
.b:
|
||||
call scheduler_switch
|
||||
jmp jump_to_process
|
||||
|
||||
global jump_to_process
|
||||
jump_to_process:
|
||||
mov eax, [scheduler_CurrentProcess]
|
||||
test eax, eax
|
||||
jnz .c
|
||||
; No next process, goto hlt loop.
|
||||
push dword 0x202
|
||||
push dword 8
|
||||
push haltLoop
|
||||
iretd
|
||||
.c:
|
||||
mov ebx, [eax + 46]
|
||||
mov cr3, ebx
|
||||
mov ebx, [eax + 6]
|
||||
mov ecx, [eax + 10]
|
||||
mov edx, [eax + 14]
|
||||
mov esi, [eax + 18]
|
||||
mov edi, [eax + 22]
|
||||
mov ebp, [eax + 26]
|
||||
cmp dword [eax + 42], 8
|
||||
je .isR0
|
||||
push dword 32 | 3
|
||||
push dword [eax + 30]
|
||||
jmp .b
|
||||
.isR0:
|
||||
mov esp, [eax + 30]
|
||||
.b:
|
||||
push dword [eax + 38] ;eflags
|
||||
push dword [eax + 42] ;cs
|
||||
push dword [eax + 34] ;eip
|
||||
mov eax, [eax + 2]
|
||||
iretd
|
||||
|
||||
set_bit:
|
||||
push edx
|
||||
push ebx
|
||||
push ecx
|
||||
push eax
|
||||
|
||||
shl ebx, 1
|
||||
|
||||
mov dx, 0x3C4
|
||||
mov al, 2
|
||||
out dx, al
|
||||
|
||||
mov ecx, ebx
|
||||
and ecx, 3
|
||||
mov eax, 1
|
||||
shl eax, cl
|
||||
|
||||
mov dx, 0x3C5
|
||||
out dx, al
|
||||
|
||||
mov ecx, ebx
|
||||
sar ecx, 2
|
||||
|
||||
pop eax
|
||||
|
||||
mov [0xA0000 + ecx], byte al
|
||||
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop edx
|
||||
|
||||
ret
|
||||
|
||||
write_dword:
|
||||
push eax
|
||||
push ecx
|
||||
|
||||
mov ecx, 32
|
||||
|
||||
.lup:
|
||||
|
||||
rol eax, 1
|
||||
|
||||
push eax
|
||||
and eax, 1
|
||||
shl eax, 4
|
||||
add eax, 20
|
||||
call set_bit
|
||||
pop eax
|
||||
.nz:
|
||||
inc ebx
|
||||
|
||||
dec ecx
|
||||
jnz .lup
|
||||
|
||||
pop ecx
|
||||
pop eax
|
||||
|
||||
ret
|
||||
|
||||
clear_screen:
|
||||
push eax
|
||||
push ecx
|
||||
push edx
|
||||
push edi
|
||||
|
||||
mov dx, 0x3C4
|
||||
mov al, 2
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
mov al, 15
|
||||
out dx, al
|
||||
|
||||
mov edi, 0xA0000
|
||||
mov ecx, 4800
|
||||
mov eax, 0
|
||||
rep stosd
|
||||
|
||||
pop edi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop eax
|
||||
|
||||
ret
|
||||
|
||||
pgf_handler:
|
||||
call clear_screen
|
||||
|
||||
pop eax ;error code
|
||||
mov ebx, 0
|
||||
call write_dword
|
||||
|
||||
inc ebx
|
||||
|
||||
mov eax, cr2 ;accessed address
|
||||
call write_dword
|
||||
|
||||
inc ebx
|
||||
|
||||
pop eax ;instruction cause of exception
|
||||
call write_dword
|
||||
|
||||
add ebx, 100
|
||||
|
||||
mov eax, [eax] ;instruction data
|
||||
call write_dword
|
||||
.LOUP:
|
||||
hlt
|
||||
jmp .LOUP
|
||||
|
||||
dbf_handler:
|
||||
add esp, 4
|
||||
mov [0xA0000], dword "D_F_"
|
||||
.LOUP:
|
||||
hlt
|
||||
jmp .LOUP
|
||||
|
||||
gpf_handler:
|
||||
pop eax
|
||||
movzx ebx, al
|
||||
and bl, 0xF
|
||||
mov bl, [.tbl + ebx]
|
||||
mov [0xB800E], bl
|
||||
movzx ebx, al
|
||||
shr bl, 4
|
||||
mov bl, [.tbl + ebx]
|
||||
mov [0xB800C], bl
|
||||
shr eax, 8
|
||||
movzx ebx, al
|
||||
and bl, 0xF
|
||||
mov bl, [.tbl + ebx]
|
||||
mov [0xB800A], bl
|
||||
movzx ebx, al
|
||||
shr bl, 4
|
||||
mov bl, [.tbl + ebx]
|
||||
mov [0xB8008], bl
|
||||
shr eax, 8
|
||||
movzx ebx, al
|
||||
and bl, 0xF
|
||||
mov bl, [.tbl + ebx]
|
||||
mov [0xB8006], bl
|
||||
movzx ebx, al
|
||||
shr bl, 4
|
||||
mov bl, [.tbl + ebx]
|
||||
mov [0xB8004], bl
|
||||
shr eax, 8
|
||||
movzx ebx, al
|
||||
and bl, 0xF
|
||||
mov bl, [.tbl + ebx]
|
||||
mov [0xB8002], bl
|
||||
movzx ebx, al
|
||||
shr bl, 4
|
||||
mov bl, [.tbl + ebx]
|
||||
mov [0xB8000], bl
|
||||
shr eax, 8
|
||||
.LOUP:
|
||||
hlt
|
||||
jmp .LOUP
|
||||
.tbl: db "0123456789ABCDEF"
|
||||
|
||||
spur_handler:
|
||||
iret
|
||||
|
||||
syscall_int_entry:
|
||||
cmp eax, (.tblend - .tbl) / 4
|
||||
jae .invalid
|
||||
jmp [.tbl + eax * 4]
|
||||
.invalid:
|
||||
mov eax, 0
|
||||
iret
|
||||
.tbl:
|
||||
dd .sys_vpm_map, .sys_canal_create, .sys_link_create, .sys_canal_accept, .sys_signal_send, .sys_signal_wait, .sys_pci_claim, .sys_pci_read, .sys_vpm_unmap, .sys_vpm_get_phys, .sys_sleep, .sys_pci_write_1, .sys_pci_write_2, .sys_pci_write_4, .sys_irq_claim, .sys_wait_for_irq, .sys_create_thread, .sys_spawn, .sys_abuse_map, .sys_release, .sys_abuse_state, .sys_exit, .sys_event_wait
|
||||
.tblend:
|
||||
.sys_vpm_map:
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
push 1 ;USER mapping
|
||||
mov eax, cr3
|
||||
push eax
|
||||
extern vpm_map
|
||||
call vpm_map
|
||||
add esp, 16
|
||||
pop edx
|
||||
pop ecx
|
||||
iret
|
||||
.sys_canal_create:
|
||||
push ecx
|
||||
push edx
|
||||
mov eax, [scheduler_CurrentProcess]
|
||||
movzx eax, word [eax] ;process ID
|
||||
push eax
|
||||
push esi
|
||||
push edi
|
||||
extern canal_create
|
||||
call canal_create
|
||||
add esp, 12
|
||||
pop edx
|
||||
pop ecx
|
||||
iret
|
||||
.sys_link_create:
|
||||
push ecx
|
||||
push edx
|
||||
mov eax, [scheduler_CurrentProcess]
|
||||
movzx eax, word [eax]
|
||||
push eax
|
||||
push esi
|
||||
push edi
|
||||
extern link_create
|
||||
call link_create
|
||||
add esp, 12
|
||||
pop edx
|
||||
pop ecx
|
||||
iret
|
||||
.sys_canal_accept:
|
||||
push ecx
|
||||
push edx
|
||||
push edi
|
||||
mov eax, [scheduler_CurrentProcess]
|
||||
movzx eax, word [eax] ;id
|
||||
push eax
|
||||
extern canal_accept
|
||||
call canal_accept
|
||||
add esp, 8
|
||||
pop edx
|
||||
pop ecx
|
||||
iret
|
||||
.sys_signal_send:
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
mov eax, [scheduler_CurrentProcess]
|
||||
movzx eax, word [eax] ;id
|
||||
push eax
|
||||
extern link_send_signal_from
|
||||
call link_send_signal_from
|
||||
pop eax
|
||||
add esp, 8
|
||||
pop edx
|
||||
pop ecx
|
||||
iret
|
||||
.sys_signal_wait:
|
||||
push eax
|
||||
mov eax, [scheduler_CurrentProcess]
|
||||
mov [eax + 50], byte 1
|
||||
mov [eax + 51], edi
|
||||
pop eax
|
||||
jmp ctx_switch
|
||||
.sys_pci_claim:
|
||||
push ecx
|
||||
push edx
|
||||
push edi
|
||||
extern pci_claim
|
||||
call pci_claim
|
||||
pop edx
|
||||
pop edx
|
||||
pop ecx
|
||||
iret
|
||||
.sys_pci_read:
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
extern pci_read
|
||||
call pci_read
|
||||
add esp, 8
|
||||
pop edx
|
||||
pop ecx
|
||||
iret
|
||||
.sys_vpm_unmap:
|
||||
push eax
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
mov eax, cr3
|
||||
push eax
|
||||
extern vpm_unmap
|
||||
call vpm_unmap
|
||||
add esp, 12
|
||||
pop edx
|
||||
pop ecx
|
||||
pop eax
|
||||
iret
|
||||
.sys_vpm_get_phys:
|
||||
push ecx
|
||||
push edx
|
||||
push edi
|
||||
mov eax, cr3
|
||||
push eax
|
||||
extern vpm_get_phys
|
||||
call vpm_get_phys
|
||||
add esp, 8
|
||||
pop edx
|
||||
pop ecx
|
||||
iret
|
||||
.sys_sleep:
|
||||
push edx
|
||||
push ebx
|
||||
push eax
|
||||
xor edx, edx
|
||||
mov eax, edi
|
||||
mov ebx, 1000 / TIMER_FREQUENCY
|
||||
div ebx
|
||||
add eax, [scheduler_Tick]
|
||||
mov ebx, [scheduler_CurrentProcess]
|
||||
mov byte [ebx + 50], 2
|
||||
mov [ebx + 51], eax
|
||||
pop eax
|
||||
pop ebx
|
||||
pop edx
|
||||
jmp ctx_switch
|
||||
.sys_pci_write_1:
|
||||
push eax
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
extern pci_write_1
|
||||
call pci_write_1
|
||||
add esp, 8
|
||||
pop edx
|
||||
pop ecx
|
||||
pop eax
|
||||
iret
|
||||
.sys_pci_write_2:
|
||||
push eax
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
extern pci_write_2
|
||||
call pci_write_2
|
||||
add esp, 8
|
||||
pop edx
|
||||
pop ecx
|
||||
pop eax
|
||||
iret
|
||||
.sys_pci_write_4:
|
||||
push eax
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push edi
|
||||
extern pci_write_4
|
||||
call pci_write_4
|
||||
add esp, 8
|
||||
pop edx
|
||||
pop ecx
|
||||
pop eax
|
||||
iret
|
||||
.sys_irq_claim:
|
||||
push ecx
|
||||
push edx
|
||||
call irq_claim
|
||||
pop edx
|
||||
pop ecx
|
||||
iret
|
||||
.sys_wait_for_irq:
|
||||
push ecx
|
||||
mov ecx, edi
|
||||
; TODO: check privilege
|
||||
call toggle_irq_mask
|
||||
mov ecx, [scheduler_CurrentProcess]
|
||||
mov [ecx + 50], byte 3 ; Wait type IRQ
|
||||
pop ecx
|
||||
jmp ctx_switch
|
||||
.sys_create_thread:
|
||||
push eax
|
||||
push ecx
|
||||
push edx
|
||||
extern scheduler_spawn
|
||||
call scheduler_spawn
|
||||
mov ecx, cr3
|
||||
mov [eax + 46], ecx ;cr3
|
||||
mov [eax + 34], edi ;eip
|
||||
pop edx
|
||||
pop ecx
|
||||
pop eax
|
||||
mov eax, 1
|
||||
iret
|
||||
.sys_spawn:
|
||||
push ecx
|
||||
push edx
|
||||
call scheduler_spawn
|
||||
test eax, eax
|
||||
jnz .sys_spawn_spawned
|
||||
pop edx
|
||||
pop ecx
|
||||
iret
|
||||
.sys_spawn_spawned:
|
||||
push eax
|
||||
mov eax, [scheduler_CurrentProcess]
|
||||
movzx eax, word [eax] ;proc ID
|
||||
push eax
|
||||
extern scheduler_enslave
|
||||
call scheduler_enslave
|
||||
add esp, 8
|
||||
pop edx
|
||||
pop ecx
|
||||
iret
|
||||
.sys_abuse_map:
|
||||
push ecx
|
||||
push edx
|
||||
push edi
|
||||
call scheduler_find
|
||||
add esp, 4
|
||||
pop edx
|
||||
pop ecx
|
||||
|
||||
test eax, eax
|
||||
jz .notfound
|
||||
|
||||
push ecx
|
||||
push edx
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push esi
|
||||
push dword [eax + 46] ;cr3
|
||||
mov eax, cr3
|
||||
push eax
|
||||
extern vpm_double_map
|
||||
call vpm_double_map
|
||||
add esp, 24
|
||||
pop edx
|
||||
pop ecx
|
||||
|
||||
iret
|
||||
.notfound:
|
||||
mov eax, -1
|
||||
iret
|
||||
.sys_release:
|
||||
push ecx
|
||||
push edx
|
||||
push edi
|
||||
extern scheduler_unslave
|
||||
call scheduler_unslave
|
||||
pop edi
|
||||
pop edx
|
||||
pop ecx
|
||||
iret
|
||||
.sys_abuse_state:
|
||||
push ecx
|
||||
push edx
|
||||
push edi
|
||||
call scheduler_find
|
||||
add esp, 4
|
||||
pop edx
|
||||
pop ecx
|
||||
|
||||
test eax, eax
|
||||
jz .notfound2
|
||||
|
||||
push ecx
|
||||
push edx
|
||||
push edx
|
||||
push esi
|
||||
push eax
|
||||
extern process_abuse_state
|
||||
call process_abuse_state
|
||||
add esp, 12
|
||||
pop edx
|
||||
pop ecx
|
||||
|
||||
iret
|
||||
.notfound2:
|
||||
mov eax, -1
|
||||
iret
|
||||
.sys_exit:
|
||||
iret
|
||||
.sys_event_wait:
|
||||
push eax
|
||||
push ecx
|
||||
push edx
|
||||
push edi
|
||||
push dword [scheduler_CurrentProcess]
|
||||
extern process_search_event
|
||||
call process_search_event
|
||||
add esp, 8
|
||||
pop edx
|
||||
pop ecx
|
||||
pop eax
|
||||
iret
|
||||
|
||||
|
||||
global scheduler_start:
|
||||
scheduler_start:
|
||||
.pic_init:
|
||||
mov al, 0x10 | 0x01
|
||||
out 0x20, al
|
||||
out 0xA0, al
|
||||
|
||||
mov al, 32
|
||||
out 0x21, al
|
||||
mov al, 40
|
||||
out 0xA1, al
|
||||
|
||||
mov al, 4
|
||||
out 0x21, al
|
||||
mov al, 2
|
||||
out 0xA1, al
|
||||
|
||||
mov al, 0x01
|
||||
out 0x21, al
|
||||
out 0xA1, al
|
||||
|
||||
.pic_mask:
|
||||
mov al, ~1 ;PIT
|
||||
out 0x21, al
|
||||
mov al, ~0
|
||||
out 0xA1, al
|
||||
|
||||
.idt:
|
||||
; Page fault handler
|
||||
mov eax, pgf_handler
|
||||
and eax, 0x0000FFFF
|
||||
or eax, 0x00080000
|
||||
mov [idt + 14 * 8], eax
|
||||
|
||||
mov eax, pgf_handler
|
||||
and eax, 0xFFFF0000
|
||||
or eax, (14 << 8) | (1 << 15)
|
||||
mov [idt + 14 * 8 + 4], eax
|
||||
|
||||
; Double fault handler
|
||||
mov eax, dbf_handler
|
||||
and eax, 0x0000FFFF
|
||||
or eax, 0x00080000
|
||||
mov [idt + 8 * 8], eax
|
||||
|
||||
mov eax, dbf_handler
|
||||
and eax, 0xFFFF0000
|
||||
or eax, (14 << 8) | (1 << 15)
|
||||
mov [idt + 8 * 8 + 4], eax
|
||||
|
||||
; General protection fault handler
|
||||
mov eax, gpf_handler
|
||||
and eax, 0x0000FFFF
|
||||
or eax, 0x00080000
|
||||
mov [idt + 13 * 8], eax
|
||||
|
||||
mov eax, gpf_handler
|
||||
and eax, 0xFFFF0000
|
||||
or eax, (14 << 8) | (1 << 15)
|
||||
mov [idt + 13 * 8 + 4], eax
|
||||
|
||||
; Timer scheduler handler
|
||||
mov eax, pit_handler
|
||||
and eax, 0x0000FFFF
|
||||
or eax, 0x00080000
|
||||
mov [idt + 32 * 8], eax
|
||||
|
||||
mov eax, pit_handler
|
||||
and eax, 0xFFFF0000
|
||||
or eax, (14 << 8) | (1 << 15)
|
||||
mov [idt + 32 * 8 + 4], eax
|
||||
|
||||
; Spurious interrupt handler
|
||||
mov eax, spur_handler
|
||||
and eax, 0x0000FFFF
|
||||
or eax, 0x00080000
|
||||
mov [idt + 39 * 8], eax
|
||||
|
||||
mov eax, spur_handler
|
||||
and eax, 0xFFFF0000
|
||||
or eax, (14 << 8) | (1 << 15)
|
||||
mov [idt + 39 * 8 + 4], eax
|
||||
|
||||
; Software interrupt syscall entry point
|
||||
mov eax, syscall_int_entry
|
||||
and eax, 0x0000FFFF
|
||||
or eax, 0x00080000
|
||||
mov [idt + 0xEC * 8], eax
|
||||
|
||||
mov eax, syscall_int_entry
|
||||
and eax, 0xFFFF0000
|
||||
or eax, (14 << 8) | (1 << 15) | (3 << 13)
|
||||
mov [idt + 0xEC * 8 + 4], eax
|
||||
|
||||
push idt
|
||||
push (idt.end - idt - 1) << 16
|
||||
lidt [esp + 2]
|
||||
add esp, 8
|
||||
|
||||
.pit:
|
||||
mov al, (2 << 1) | (2 << 4)
|
||||
out 0x43, al
|
||||
|
||||
mov al, (1193182 / TIMER_FREQUENCY) % 256
|
||||
out 0x40, al
|
||||
mov al, (1193182 / TIMER_FREQUENCY) / 256
|
||||
out 0x40, al
|
||||
|
||||
sti
|
||||
|
||||
haltLoop:
|
||||
hlt
|
||||
jmp haltLoop
|
||||
|
||||
; ecx = id
|
||||
toggle_irq_mask:
|
||||
push ecx
|
||||
push ebx
|
||||
push edx
|
||||
push eax
|
||||
mov dx, 0x21
|
||||
cmp cl, 8
|
||||
jl .lower
|
||||
sub cl, 8
|
||||
mov dx, 0xA1
|
||||
.lower:
|
||||
mov bl, 1
|
||||
shl bl, cl
|
||||
in al, dx
|
||||
xor al, bl
|
||||
out dx, al
|
||||
pop eax
|
||||
pop edx
|
||||
pop ebx
|
||||
pop ecx
|
||||
ret
|
||||
|
||||
irq_claim:
|
||||
test edi, edi
|
||||
jnz .notTimer
|
||||
xor eax, eax
|
||||
ret
|
||||
.notTimer:
|
||||
mov eax, [scheduler_CurrentProcess]
|
||||
mov bx, [eax] ;id
|
||||
lea eax, [edi * 8]
|
||||
lea eax, [eax * 2 + edi] ;17x
|
||||
lea eax, [eax + irqhandlers - 17]
|
||||
mov [eax + 2], esi ;mov edi, handler
|
||||
mov [eax + 7], bx ;mov esi, process id
|
||||
mov ecx, edi
|
||||
mov [eax + 12], cl
|
||||
|
||||
push eax
|
||||
and eax, 0x0000FFFF
|
||||
or eax, 0x00080000
|
||||
mov [idt + edi * 8 + 256], eax
|
||||
|
||||
pop eax
|
||||
and eax, 0xFFFF0000
|
||||
or eax, (14 << 8) | (1 << 15)
|
||||
mov [idt + edi * 8 + 256 + 4], eax
|
||||
|
||||
mov eax, 1
|
||||
ret
|
||||
|
||||
irqhandlers:
|
||||
pushad
|
||||
mov edi, strict dword 0
|
||||
mov esi, strict dword 0
|
||||
mov cl, strict byte 0
|
||||
jmp strict word irqhandler
|
||||
pushad
|
||||
mov edi, strict dword 0
|
||||
mov esi, strict dword 0
|
||||
mov cl, strict byte 0
|
||||
jmp strict word irqhandler
|
||||
pushad
|
||||
mov edi, strict dword 0
|
||||
mov esi, strict dword 0
|
||||
mov cl, strict byte 0
|
||||
jmp strict word irqhandler
|
||||
pushad
|
||||
mov edi, strict dword 0
|
||||
mov esi, strict dword 0
|
||||
mov cl, strict byte 0
|
||||
jmp strict word irqhandler
|
||||
pushad
|
||||
mov edi, strict dword 0
|
||||
mov esi, strict dword 0
|
||||
mov cl, strict byte 0
|
||||
jmp strict word irqhandler
|
||||
pushad
|
||||
mov edi, strict dword 0
|
||||
mov esi, strict dword 0
|
||||
mov cl, strict byte 0
|
||||
jmp strict word irqhandler
|
||||
pushad
|
||||
mov edi, strict dword 0
|
||||
mov esi, strict dword 0
|
||||
mov cl, strict byte 0
|
||||
jmp strict word irqhandler
|
||||
pushad
|
||||
mov edi, strict dword 0
|
||||
mov esi, strict dword 0
|
||||
mov cl, strict byte 0
|
||||
jmp strict word irqhandler
|
||||
pushad
|
||||
mov edi, strict dword 0
|
||||
mov esi, strict dword 0
|
||||
mov cl, strict byte 0
|
||||
jmp strict word irqhandler
|
||||
pushad
|
||||
mov edi, strict dword 0
|
||||
mov esi, strict dword 0
|
||||
mov cl, strict byte 0
|
||||
jmp strict word irqhandler
|
||||
pushad
|
||||
mov edi, strict dword 0
|
||||
mov esi, strict dword 0
|
||||
mov cl, strict byte 0
|
||||
jmp strict word irqhandler
|
||||
pushad
|
||||
mov edi, strict dword 0
|
||||
mov esi, strict dword 0
|
||||
mov cl, strict byte 0
|
||||
jmp strict word irqhandler
|
||||
pushad
|
||||
mov edi, strict dword 0
|
||||
mov esi, strict dword 0
|
||||
mov cl, strict byte 0
|
||||
jmp strict word irqhandler
|
||||
pushad
|
||||
mov edi, strict dword 0
|
||||
mov esi, strict dword 0
|
||||
mov cl, strict byte 0
|
||||
jmp strict word irqhandler
|
||||
pushad
|
||||
mov edi, strict dword 0
|
||||
mov esi, strict dword 0
|
||||
mov cl, strict byte 0
|
||||
irqhandler:
|
||||
call toggle_irq_mask
|
||||
mov al, 0x20
|
||||
out 0x20, al
|
||||
push esi
|
||||
extern scheduler_find
|
||||
call scheduler_find
|
||||
add esp, 4
|
||||
mov [eax + 55], edi
|
||||
popad
|
||||
iret
|
||||
|
||||
idt:
|
||||
times 256 dq 0
|
||||
.end:
|
||||
67
src/kernel/arch/x86/log.asm
Normal file
67
src/kernel/arch/x86/log.asm
Normal file
@@ -0,0 +1,67 @@
|
||||
section .data
|
||||
|
||||
section .text
|
||||
|
||||
global klogc
|
||||
klogc:
|
||||
mov eax, [esp + 4]
|
||||
out 0xE9, al
|
||||
ret
|
||||
|
||||
global klogs
|
||||
klogs:
|
||||
mov ecx, [esp + 4]
|
||||
.lup:
|
||||
mov al, [ecx]
|
||||
test al, al
|
||||
jz .end
|
||||
out 0xE9, al
|
||||
inc ecx
|
||||
jmp .lup
|
||||
.end:
|
||||
ret
|
||||
|
||||
;~ global klogp
|
||||
;~ klogp:
|
||||
;~ push eax
|
||||
;~ mov edx, [esp + 12]
|
||||
;~ mov eax, edx
|
||||
;~ shr eax, 28
|
||||
;~ call .logh
|
||||
;~ mov eax, edx
|
||||
;~ shr eax, 24
|
||||
;~ and al, 0x0F
|
||||
;~ call .logh
|
||||
;~ mov eax, edx
|
||||
;~ shr eax, 20
|
||||
;~ and al, 0x0F
|
||||
;~ call .logh
|
||||
;~ mov eax, edx
|
||||
;~ shr eax, 16
|
||||
;~ and al, 0x0F
|
||||
;~ call .logh
|
||||
;~ mov eax, edx
|
||||
;~ shr eax, 12
|
||||
;~ and al, 0x0F
|
||||
;~ call .logh
|
||||
;~ mov eax, edx
|
||||
;~ shr eax, 8
|
||||
;~ and al, 0x0F
|
||||
;~ call .logh
|
||||
;~ mov eax, edx
|
||||
;~ shr eax, 4
|
||||
;~ and al, 0x0F
|
||||
;~ call .logh
|
||||
;~ mov eax, edx
|
||||
;~ and al, 0x0F
|
||||
;~ call .logh
|
||||
;~ pop eax
|
||||
;~ ret
|
||||
;~ .logh:
|
||||
;~ add al, '0'
|
||||
;~ cmp al, '0' + 9
|
||||
;~ jle .p
|
||||
;~ add al, 7
|
||||
;~ .p:
|
||||
;~ out 0xE9, al
|
||||
;~ ret
|
||||
15
src/kernel/arch/x86/mem.c
Normal file
15
src/kernel/arch/x86/mem.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include"mem.h"
|
||||
|
||||
void kmemw1(void *_ptr, uint8_t val, size_t amount) {
|
||||
uint8_t *ptr = _ptr;
|
||||
for(size_t i = 0; i < amount; i++) {
|
||||
*(ptr++) = val;
|
||||
}
|
||||
}
|
||||
|
||||
void kmemw4(void *_ptr, uint32_t val, size_t amount) {
|
||||
uint32_t *ptr = _ptr;
|
||||
for(size_t i = 0; i < amount; i++) {
|
||||
*(ptr++) = val;
|
||||
}
|
||||
}
|
||||
10
src/kernel/arch/x86/mem.h
Normal file
10
src/kernel/arch/x86/mem.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef _MEM_H
|
||||
#define _MEM_H
|
||||
|
||||
#include<stdint.h>
|
||||
#include<stddef.h>
|
||||
|
||||
void kmemw1(void *ptr, uint8_t val, size_t amount);
|
||||
void kmemw4(void *ptr, uint32_t val, size_t amount);
|
||||
|
||||
#endif
|
||||
60
src/kernel/arch/x86/pci.c
Normal file
60
src/kernel/arch/x86/pci.c
Normal file
@@ -0,0 +1,60 @@
|
||||
#include"pci.h"
|
||||
|
||||
#include<stddef.h>
|
||||
#include"vpm.h"
|
||||
|
||||
size_t claimedCount = 0;
|
||||
uint32_t *claimed;
|
||||
|
||||
void pci_init() {
|
||||
uint32_t cr3;
|
||||
asm volatile("movl %%cr3, %0" : "=r" (cr3) :);
|
||||
|
||||
claimed = vpm_map(cr3, VPM_KERNEL, -1, -1, 4096);
|
||||
}
|
||||
|
||||
uint32_t pci_claim(uint32_t cscp) {
|
||||
for(int b = 0; b < 256; b++) {
|
||||
for(int d = 0; d < 32; d++) {
|
||||
for(int f = 0; f < 8; f++) {
|
||||
uint32_t id = (b << 16) | (d << 11) | (f << 8);
|
||||
if((pci_read(id, 8) & 0xFFFFFF00) == cscp) {
|
||||
for(size_t i = 0; i < claimedCount; i++) {
|
||||
if(claimed[i] == id) {
|
||||
goto cont;
|
||||
}
|
||||
}
|
||||
|
||||
claimed[claimedCount++] = id;
|
||||
return id;
|
||||
}
|
||||
cont:;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t pci_read(uint32_t id, uint8_t offset) {
|
||||
asm volatile("outl %%eax, %%dx" : : "a"(0x80000000 | id | offset), "d"(0xCF8));
|
||||
|
||||
uint32_t ret;
|
||||
asm volatile("inl %%dx, %%eax" : "=a"(ret) : "d"(0xCFC));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void pci_write_1(uint32_t id, uint8_t offset, uint8_t val) {
|
||||
asm volatile("outl %%eax, %%dx" : : "a"(0x80000000 | id | offset), "d"(0xCF8));
|
||||
asm volatile("outb %%al, %%dx" : : "a"(val), "d"(0xCFC + (offset & 3)));
|
||||
}
|
||||
|
||||
void pci_write_2(uint32_t id, uint8_t offset, uint16_t val) {
|
||||
asm volatile("outl %%eax, %%dx" : : "a"(0x80000000 | id | offset), "d"(0xCF8));
|
||||
asm volatile("outw %%ax, %%dx" : : "a"(val), "d"(0xCFC + (offset & 2)));
|
||||
}
|
||||
|
||||
void pci_write_4(uint32_t id, uint8_t offset, uint32_t val) {
|
||||
asm volatile("outl %%eax, %%dx" : : "a"(0x80000000 | id | offset), "d"(0xCF8));
|
||||
asm volatile("outl %%eax, %%dx" : : "a"(val), "d"(0xCFC));
|
||||
}
|
||||
13
src/kernel/arch/x86/pci.h
Normal file
13
src/kernel/arch/x86/pci.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef _PCI_H
|
||||
#define _PCI_H
|
||||
|
||||
#include<stdint.h>
|
||||
|
||||
void pci_init();
|
||||
uint32_t pci_claim(uint32_t);
|
||||
uint32_t pci_read(uint32_t, uint8_t);
|
||||
void pci_write_1(uint32_t, uint8_t, uint8_t);
|
||||
void pci_write_2(uint32_t, uint8_t, uint16_t);
|
||||
void pci_write_4(uint32_t, uint8_t, uint32_t);
|
||||
|
||||
#endif
|
||||
64
src/kernel/arch/x86/ppm.c
Normal file
64
src/kernel/arch/x86/ppm.c
Normal file
@@ -0,0 +1,64 @@
|
||||
#include"ppm.h"
|
||||
|
||||
#include<stdint.h>
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint64_t start;
|
||||
uint32_t length;
|
||||
uint8_t flags;
|
||||
uint8_t data[];
|
||||
} PPMBitmap;
|
||||
|
||||
PPMBitmap *ppm_Bitmap;
|
||||
|
||||
static int availability_test(PPMBitmap *bm, size_t pg, size_t len) {
|
||||
if(pg > bm->length - len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while(len--) {
|
||||
if(bm->data[pg / 8] & (1 << (pg % 8))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pg++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mark(PPMBitmap *bm, size_t pg, size_t len) {
|
||||
if(pg > bm->length - len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while(len--) {
|
||||
bm->data[pg / 8] |= 1 << (pg % 8);
|
||||
|
||||
pg++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t ppm_alloc(size_t len) {
|
||||
PPMBitmap *bm = ppm_Bitmap;
|
||||
|
||||
for(int bmid = 0; bmid < 2; bmid++) {
|
||||
if(bm->length < len) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for(size_t pg = 0; pg <= bm->length - len; pg++) {
|
||||
if(availability_test(bm, pg, len)) {
|
||||
if(mark(bm, pg, len)) {
|
||||
return bm->start + pg * 4096;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bm = (PPMBitmap*) ((uintptr_t) bm + sizeof(*bm) + (bm->length + 7) / 8);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
9
src/kernel/arch/x86/ppm.h
Normal file
9
src/kernel/arch/x86/ppm.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef _PPM_H
|
||||
#define _PPM_H
|
||||
|
||||
#include<stddef.h>
|
||||
#include<stdint.h>
|
||||
|
||||
uint64_t ppm_alloc(size_t len);
|
||||
|
||||
#endif
|
||||
46
src/kernel/arch/x86/process.h
Normal file
46
src/kernel/arch/x86/process.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef _PROCESS_H
|
||||
#define _PROCESS_H
|
||||
|
||||
#include<stdint.h>
|
||||
|
||||
struct Canal;
|
||||
struct Link;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t eax; //0
|
||||
uint32_t ebx; //4
|
||||
uint32_t ecx; //8
|
||||
uint32_t edx; //12
|
||||
uint32_t esi; //16
|
||||
uint32_t edi; //20
|
||||
uint32_t ebp; //24
|
||||
uint32_t esp; //28
|
||||
uint32_t eip; //32
|
||||
uint32_t eflags; //36
|
||||
uint32_t cs; //40
|
||||
uint32_t cr3; //44
|
||||
} Context;
|
||||
|
||||
#define WAIT_TYPE_NONE 0
|
||||
#define WAIT_TYPE_SIGNAL 1
|
||||
#define WAIT_TYPE_TIME 2
|
||||
#define WAIT_TYPE_IRQ 3
|
||||
#define WAIT_TYPE_MINOR 4
|
||||
|
||||
typedef struct __attribute__((packed)) Process {
|
||||
uint16_t id;
|
||||
Context ctx;
|
||||
uint8_t waitType;
|
||||
uint32_t waitValue;
|
||||
uint32_t irqWaiting;
|
||||
uint8_t minipriority;
|
||||
struct Process *next;
|
||||
uint16_t ownerId;
|
||||
uint8_t eventsRequest;
|
||||
uint8_t eventsSignal;
|
||||
uint8_t eventsClosed;
|
||||
struct Canal *ownedCanal;
|
||||
struct Link *guestLinks;
|
||||
} Process;
|
||||
|
||||
#endif
|
||||
301
src/kernel/arch/x86/scheduler.c
Normal file
301
src/kernel/arch/x86/scheduler.c
Normal file
@@ -0,0 +1,301 @@
|
||||
#include"scheduler.h"
|
||||
|
||||
#include"vpm.h"
|
||||
#include"mem.h"
|
||||
|
||||
#include<kernel/arch/x86/consts.h>
|
||||
|
||||
#include"canal.h"
|
||||
|
||||
#define PROCESS_ZONE_SIZE 4096
|
||||
#define HANDLE_ZONE_SIZE 4096
|
||||
|
||||
Process *scheduler_ProcessZone = 0;
|
||||
Process *scheduler_ProcessQueues[TOTAL_PRIORITIES];
|
||||
|
||||
static int scheduler_CurrentPriority;
|
||||
volatile Process *scheduler_CurrentProcess = 0;
|
||||
|
||||
uint32_t scheduler_Tick;
|
||||
|
||||
void klogs(const char *str);
|
||||
void klogc(int c);
|
||||
|
||||
static void klogp(void *p) {
|
||||
static char hex[16]="0123456789ABCDEF";
|
||||
|
||||
uintptr_t i = (uintptr_t) p;
|
||||
klogc(hex[(i >> 28) & 0xF]);
|
||||
klogc(hex[(i >> 24) & 0xF]);
|
||||
klogc(hex[(i >> 20) & 0xF]);
|
||||
klogc(hex[(i >> 16) & 0xF]);
|
||||
klogc(hex[(i >> 12) & 0xF]);
|
||||
klogc(hex[(i >> 8) & 0xF]);
|
||||
klogc(hex[(i >> 4) & 0xF]);
|
||||
klogc(hex[(i >> 0) & 0xF]);
|
||||
}
|
||||
|
||||
void scheduler_init() {
|
||||
uint32_t cr3;
|
||||
asm volatile("movl %%cr3, %0" : "=r" (cr3) :);
|
||||
|
||||
scheduler_ProcessZone = vpm_map(cr3, VPM_KERNEL, -1, -1, PROCESS_ZONE_SIZE);
|
||||
kmemw1(scheduler_ProcessZone, 0, PROCESS_ZONE_SIZE);
|
||||
}
|
||||
|
||||
static int consider_switch(Process *p) {
|
||||
if(p->waitType == WAIT_TYPE_SIGNAL) {
|
||||
uint32_t meta = 0;
|
||||
uint32_t canalId = -1;
|
||||
uint32_t which = is_signal_awaiting_to_concerning_link(p->id, p->waitValue, &meta, &canalId);
|
||||
if(which != 0xFFFFFFFF) {
|
||||
p->waitType = WAIT_TYPE_NONE;
|
||||
p->ctx.eax = which;
|
||||
p->ctx.edx = meta;
|
||||
p->ctx.ebx = canalId;
|
||||
} else return 0;
|
||||
} else if(p->waitType == WAIT_TYPE_TIME) {
|
||||
if(p->waitValue <= scheduler_Tick) {
|
||||
p->waitType = WAIT_TYPE_NONE;
|
||||
} else return 0;
|
||||
} else if(p->waitType == WAIT_TYPE_IRQ) {
|
||||
if(p->irqWaiting) {
|
||||
p->waitType = WAIT_TYPE_NONE;
|
||||
p->ctx.eip = p->irqWaiting;
|
||||
p->irqWaiting = 0;
|
||||
} else return 0;
|
||||
} else if(p->waitType == WAIT_TYPE_MINOR) {
|
||||
//asm("xchg %bx, %bx");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*static char hex[16]="0123456789ABCDEF";
|
||||
klogc('0' + p->id);
|
||||
klogc(' ');
|
||||
klogc(hex[p->priority / PRIORITY_UNIT]);
|
||||
klogc('\n');*/
|
||||
|
||||
scheduler_CurrentPriority = p->minipriority / PRIORITY_UNIT;
|
||||
scheduler_CurrentProcess = p;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void scheduler_switch() {
|
||||
if(scheduler_CurrentProcess == 0) {
|
||||
for(int p = 0; p < TOTAL_PRIORITIES; p++) {
|
||||
Process *q = scheduler_ProcessQueues[p];
|
||||
while(q) {
|
||||
if(consider_switch(q)) {
|
||||
return;
|
||||
}
|
||||
q = q->next;
|
||||
}
|
||||
}
|
||||
|
||||
scheduler_CurrentProcess = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for(int p = 0; p < scheduler_CurrentPriority; p++) {
|
||||
Process *q = scheduler_ProcessQueues[p];
|
||||
|
||||
while(q) {
|
||||
if(consider_switch(q)) {
|
||||
return;
|
||||
}
|
||||
q = q->next;
|
||||
}
|
||||
}
|
||||
|
||||
Process *p = scheduler_CurrentProcess;
|
||||
do {
|
||||
p = p->next;
|
||||
|
||||
if(!p) {
|
||||
p = scheduler_ProcessQueues[scheduler_CurrentPriority];
|
||||
}
|
||||
|
||||
if(consider_switch(p)) {
|
||||
return;
|
||||
}
|
||||
} while(p != scheduler_CurrentProcess);
|
||||
|
||||
for(int p = scheduler_CurrentPriority + 1; p < TOTAL_PRIORITIES; p++) {
|
||||
Process *q = scheduler_ProcessQueues[p];
|
||||
|
||||
while(q) {
|
||||
if(consider_switch(q)) {
|
||||
return;
|
||||
}
|
||||
q = q->next;
|
||||
}
|
||||
}
|
||||
|
||||
scheduler_CurrentProcess = 0;
|
||||
}
|
||||
|
||||
Process *scheduler_find(uint16_t id) {
|
||||
for(int p = 0; p < TOTAL_PRIORITIES; p++) {
|
||||
Process *q = scheduler_ProcessQueues[p];
|
||||
|
||||
while(q) {
|
||||
if(q->id == id) {
|
||||
return q;
|
||||
}
|
||||
q = q->next;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint16_t next_free_id() {
|
||||
for(uint32_t id = 1; id < 65536; id++) {
|
||||
if(!scheduler_find(id)) {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Process *scheduler_spawn(int minipriority) {
|
||||
int found = 0;
|
||||
Process *p = scheduler_ProcessZone;
|
||||
|
||||
for(size_t i = 0; i < PROCESS_ZONE_SIZE / sizeof(Process); i++) {
|
||||
if(p->id == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
kmemw1(p, 0, sizeof(*p));
|
||||
p->id = next_free_id();
|
||||
p->ctx.eflags = EFLAGS_RESET | EFLAGS_IF | EFLAGS_IOPL_3;
|
||||
p->ctx.cs = 24 | RPL_3;
|
||||
p->waitType = WAIT_TYPE_NONE;
|
||||
p->irqWaiting = 0;
|
||||
p->minipriority = minipriority;
|
||||
p->next = scheduler_ProcessQueues[minipriority / PRIORITY_UNIT];
|
||||
p->eventsRequest = 0;
|
||||
p->eventsSignal = 0;
|
||||
p->eventsClosed = 0;
|
||||
p->ownedCanal = NULL;
|
||||
p->guestLinks = NULL;
|
||||
|
||||
scheduler_ProcessQueues[minipriority / PRIORITY_UNIT] = p;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
size_t scheduler_enslave(uint16_t ownerId, Process *child) {
|
||||
child->waitType = WAIT_TYPE_MINOR;
|
||||
child->ownerId = ownerId;
|
||||
|
||||
// Should not be how it works.
|
||||
child->ctx.cr3 = vpm_create_space();
|
||||
|
||||
return child->id;
|
||||
}
|
||||
|
||||
int scheduler_unslave(size_t handle) {
|
||||
struct Process *proc = scheduler_find(handle);
|
||||
if(proc && proc->waitType == WAIT_TYPE_MINOR) {
|
||||
proc->waitType = WAIT_TYPE_NONE;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define SYS_STATE_X86_EIP 0
|
||||
int process_abuse_state(struct Process *proc, size_t type, uintmax_t val) {
|
||||
switch(type) {
|
||||
case SYS_STATE_X86_EIP:
|
||||
proc->ctx.eip = val;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define KEV_TYPE_NONE 0
|
||||
#define KEV_TYPE_LINK_REQUEST 1
|
||||
#define KEV_TYPE_LINK_SIGNAL 2
|
||||
#define KEV_TYPE_LINK_CLOSE 3
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t type;
|
||||
uint32_t canalId;
|
||||
void *area;
|
||||
uint32_t meta;
|
||||
} KEvent;
|
||||
|
||||
int process_search_event(Process *proc, KEvent *kev) {
|
||||
if(proc->eventsRequest) {
|
||||
kev->type = KEV_TYPE_LINK_REQUEST;
|
||||
|
||||
Canal *c = proc->ownedCanal;
|
||||
while(c) {
|
||||
Link *l = c->links;
|
||||
|
||||
while(l) {
|
||||
if(!(l->flags & LINK_FLAG_ACCEPTED)) {
|
||||
kev->canalId = l->canalId;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
l = l->nextInCanal;
|
||||
}
|
||||
|
||||
c = c->ownedNext;
|
||||
}
|
||||
}
|
||||
|
||||
if(proc->eventsSignal) {
|
||||
kev->type = KEV_TYPE_LINK_SIGNAL;
|
||||
|
||||
Link *l = proc->guestLinks;
|
||||
while(l) {
|
||||
if(l->flags & LINK_FLAG_H2G) {
|
||||
kev->area = signal_accept(proc, l, &kev->meta);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
l = l->nextGuestLink;
|
||||
}
|
||||
}
|
||||
|
||||
if(proc->eventsSignal) {
|
||||
kev->type = KEV_TYPE_LINK_SIGNAL;
|
||||
|
||||
Canal *c = proc->ownedCanal;
|
||||
while(c) {
|
||||
Link *l = c->links;
|
||||
while(l) {
|
||||
if(l->flags & LINK_FLAG_G2H) {
|
||||
kev->area = signal_accept(proc, l, &kev->meta);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
l = l->nextInCanal;
|
||||
}
|
||||
|
||||
c = c->ownedNext;
|
||||
}
|
||||
}
|
||||
|
||||
kev->type = KEV_TYPE_NONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
22
src/kernel/arch/x86/scheduler.h
Normal file
22
src/kernel/arch/x86/scheduler.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef _SCHEDULER_H
|
||||
#define _SCHEDULER_H
|
||||
|
||||
#include"process.h"
|
||||
#include<stddef.h>
|
||||
|
||||
void scheduler_init();
|
||||
void scheduler_switch();
|
||||
Process *scheduler_spawn();
|
||||
size_t scheduler_create_handle(uint16_t ownerId, Process *child);
|
||||
|
||||
Process *scheduler_find(uint16_t procId);
|
||||
|
||||
#define MAX_MINIPRIORITY 255
|
||||
#define TOTAL_PRIORITIES 16
|
||||
#define PRIORITY_UNIT ((MAX_MINIPRIORITY + 1) / TOTAL_PRIORITIES)
|
||||
|
||||
//extern size_t scheduler_ProcessCount;
|
||||
extern Process *scheduler_ProcessZone;
|
||||
extern Process *scheduler_ProcessQueues[TOTAL_PRIORITIES];
|
||||
|
||||
#endif
|
||||
268
src/kernel/arch/x86/vpm.c
Normal file
268
src/kernel/arch/x86/vpm.c
Normal file
@@ -0,0 +1,268 @@
|
||||
#include"vpm.h"
|
||||
|
||||
#include"ppm.h"
|
||||
#include"mem.h"
|
||||
|
||||
extern void *_kernel_end;
|
||||
|
||||
void set_temporary_mapping(uint32_t addr) {
|
||||
if((addr & 0xFFF) != 0) asm volatile("xchgw %bx, %bx");
|
||||
|
||||
*(volatile uint32_t*) 0xFFFFFFF8 = addr | 3;
|
||||
asm volatile("invlpg 0xFFFFE000" : : : "memory");
|
||||
}
|
||||
|
||||
static uint32_t nextAllocs[2] = {[VPM_KERNEL] = 0, [VPM_USER] = 1 * 1024 * 1024 * 1024};
|
||||
|
||||
void vpm_init(uint32_t kernelEnd) {
|
||||
nextAllocs[VPM_KERNEL] = (kernelEnd + 4095) & ~4095;
|
||||
}
|
||||
|
||||
/* TODO: Make better. */
|
||||
uint32_t vpm_find_free(uint32_t addrspace, AllocationOwner owner, size_t lenBytes) {
|
||||
size_t len = (lenBytes + 4095) / 4096;
|
||||
|
||||
uint32_t ret = nextAllocs[owner];
|
||||
for(size_t i = 0; i < len;) {
|
||||
uint32_t pdeid = (ret + i * 4096) >> 22;
|
||||
uint32_t pteid = ((ret + i * 4096) >> 12) & 1023;
|
||||
|
||||
set_temporary_mapping(addrspace);
|
||||
|
||||
volatile uint32_t *pde = &((volatile uint32_t*) 0xFFFFE000)[pdeid];
|
||||
if((*pde & 1) == 0) {
|
||||
i += 4096;
|
||||
} else {
|
||||
set_temporary_mapping(*pde & ~0xFFF);
|
||||
|
||||
if((((volatile uint32_t*) 0xFFFFE000)[pteid] & 1) == 0) {
|
||||
i++;
|
||||
} else {
|
||||
ret += (i + 1) * 4096;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If phys is -1, map to uncontiguous physical pages anywhere, else map contiguous span of physical memory. */
|
||||
/* If phys is -2, automatically find contiguous span of physical memory */
|
||||
/* If virt is -1, find free space, else overwrite. */
|
||||
void *vpm_map(uint32_t addrspace, AllocationOwner owner, uint32_t virt, uint32_t phys, size_t len) {
|
||||
uint32_t thisspace;
|
||||
asm volatile("movl %%cr3, %0" : "=r" (thisspace) :);
|
||||
|
||||
//if(len == 32768)asm("xchg %%bx, %%bx":::);
|
||||
|
||||
if(virt == -1) {
|
||||
virt = vpm_find_free(addrspace, owner, len);
|
||||
}
|
||||
|
||||
len = (len + 4095) / 4096;
|
||||
|
||||
if(phys == -2) {
|
||||
phys = ppm_alloc(len);
|
||||
|
||||
if(!phys) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < len; i++) {
|
||||
set_temporary_mapping(addrspace);
|
||||
|
||||
uint32_t pdeid = (virt + i * 4096) >> 22;
|
||||
uint32_t pteid = ((virt + i * 4096) >> 12) & 1023;
|
||||
|
||||
volatile uint32_t *pde = &((volatile uint32_t*) 0xFFFFE000)[pdeid];
|
||||
|
||||
if((*pde & 1) == 0) {
|
||||
uint64_t physpag = ppm_alloc(1);
|
||||
|
||||
if(physpag) {
|
||||
*pde = physpag | 3 | (owner == VPM_USER ? 4 : 0);
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
set_temporary_mapping(*pde & ~0xFFF);
|
||||
|
||||
volatile uint32_t *pte = &((volatile uint32_t*) 0xFFFFE000)[pteid];
|
||||
if(phys == -1) {
|
||||
*pte = ppm_alloc(1);
|
||||
if(!*pte) goto error;
|
||||
} else {
|
||||
*pte = phys + i * 4096;
|
||||
}
|
||||
*pte |= 3 | (owner == VPM_USER ? 4 : 0);
|
||||
|
||||
if(thisspace == addrspace) {
|
||||
//~ asm volatile("xchg %bx, %bx");
|
||||
asm volatile("invlpg %0" : : "m"(*(char*) (virt + i * 4096)) : "memory");
|
||||
}
|
||||
}
|
||||
|
||||
return (void*) virt;
|
||||
|
||||
error:
|
||||
// TODO: Deallocate physical pages.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vpm_double_map(uint32_t cr3a, uint32_t cr3b, uint32_t *va, uint32_t *vb, uintptr_t phys, size_t len) {
|
||||
uint32_t thisspace;
|
||||
asm volatile("movl %%cr3, %0" : "=r" (thisspace) :);
|
||||
|
||||
if(*va == -1) {
|
||||
*va = vpm_find_free(cr3a, VPM_USER, len);
|
||||
}
|
||||
if(*vb == -1) {
|
||||
*vb = vpm_find_free(cr3b, VPM_USER, len);
|
||||
}
|
||||
|
||||
len = (len + 4095) / 4096;
|
||||
|
||||
if(phys == -2) {
|
||||
phys = ppm_alloc(len);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < len; i++) {
|
||||
uint32_t backend;
|
||||
|
||||
if(phys == -1) {
|
||||
backend = ppm_alloc(1);
|
||||
if(!backend) goto error;
|
||||
} else {
|
||||
backend = phys + i * 4096;
|
||||
}
|
||||
|
||||
{
|
||||
set_temporary_mapping(cr3a);
|
||||
|
||||
uint32_t pdeid = (*va + i * 4096) >> 22;
|
||||
uint32_t pteid = ((*va + i * 4096) >> 12) & 1023;
|
||||
|
||||
volatile uint32_t *pde = &((volatile uint32_t*) 0xFFFFE000)[pdeid];
|
||||
|
||||
if((*pde & 1) == 0) {
|
||||
uintptr_t physpag = ppm_alloc(1);
|
||||
|
||||
if(physpag) {
|
||||
*pde = physpag | 3 | 4;
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
set_temporary_mapping(*pde & ~0xFFF);
|
||||
|
||||
volatile uint32_t *pte = &((volatile uint32_t*) 0xFFFFE000)[pteid];
|
||||
|
||||
*pte = backend | 3 | 4;
|
||||
|
||||
if(thisspace == cr3a) {
|
||||
asm volatile("invlpg %0" : : "m"(*(char*) (*va + i * 4096)) : "memory");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
set_temporary_mapping(cr3b);
|
||||
|
||||
uint32_t pdeid = (*vb + i * 4096) >> 22;
|
||||
uint32_t pteid = ((*vb + i * 4096) >> 12) & 1023;
|
||||
|
||||
volatile uint32_t *pde = &((volatile uint32_t*) 0xFFFFE000)[pdeid];
|
||||
|
||||
if((*pde & 1) == 0) {
|
||||
uintptr_t physpag = ppm_alloc(1);
|
||||
|
||||
if(physpag) {
|
||||
*pde = physpag | 3 | 4;
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
set_temporary_mapping(*pde & ~0xFFF);
|
||||
|
||||
volatile uint32_t *pte = &((volatile uint32_t*) 0xFFFFE000)[pteid];
|
||||
|
||||
*pte = backend | 3 | 4;
|
||||
|
||||
if(thisspace == cr3b) {
|
||||
asm volatile("invlpg %0" : : "m"(*(char*) (*vb + i * 4096)) : "memory");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t vpm_create_space() {
|
||||
uint32_t curPD;
|
||||
asm volatile("movl %%cr3, %0" : "=r"(curPD) :);
|
||||
set_temporary_mapping(curPD);
|
||||
|
||||
uint32_t pde0000 = *(volatile uint32_t*) 0xFFFFE000;
|
||||
uint32_t pde1023 = *(volatile uint32_t*) 0xFFFFEFFC;
|
||||
|
||||
uint32_t newPD = ppm_alloc(1);
|
||||
|
||||
set_temporary_mapping(newPD);
|
||||
|
||||
*(volatile uint32_t*) 0xFFFFE000 = pde0000;
|
||||
kmemw4((void*) 0xFFFFE004, 0, 1022);
|
||||
*(volatile uint32_t*) 0xFFFFEFFC = pde1023;
|
||||
|
||||
return newPD;
|
||||
}
|
||||
|
||||
void vpm_set_space(uint32_t cr3) {
|
||||
asm volatile("movl %0, %%cr3" : : "r"(cr3));
|
||||
}
|
||||
|
||||
uint32_t vpm_get_phys(uint32_t cr3, uint32_t v) {
|
||||
uint32_t offset = v & 4095;
|
||||
|
||||
uint32_t pdeid = v >> 22;
|
||||
uint32_t pteid = (v >> 12) & 1023;
|
||||
|
||||
set_temporary_mapping(cr3);
|
||||
set_temporary_mapping(((uint32_t*) 0xFFFFE000)[pdeid] & ~0xFFF);
|
||||
|
||||
return (((uint32_t*) 0xFFFFE000)[pteid] & ~0xFFF) + offset;
|
||||
}
|
||||
|
||||
void vpm_unmap(uint32_t cr3, uint32_t virt, size_t len) {
|
||||
uint32_t thisspace;
|
||||
asm volatile("movl %%cr3, %0" : "=r"(thisspace) :);
|
||||
|
||||
len = (len + 4095) / 4096;
|
||||
|
||||
for(size_t i = 0; i < len; i++) {
|
||||
set_temporary_mapping(cr3);
|
||||
|
||||
uint32_t pdeid = (virt + i * 4096) >> 22;
|
||||
uint32_t pteid = ((virt + i * 4096) >> 12) & 1023;
|
||||
|
||||
volatile uint32_t *pde = &((volatile uint32_t*) 0xFFFFE000)[pdeid];
|
||||
|
||||
if((*pde & 1) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
set_temporary_mapping(*pde & ~0xFFF);
|
||||
|
||||
((volatile uint32_t*) 0xFFFFE000)[pteid] = 0;
|
||||
|
||||
if(thisspace == cr3) {
|
||||
asm volatile("invlpg %0" : : "m"(*(char*) (virt + i * 4096)) : "memory");
|
||||
}
|
||||
}
|
||||
}
|
||||
24
src/kernel/arch/x86/vpm.h
Normal file
24
src/kernel/arch/x86/vpm.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef _VPM_H
|
||||
#define _VPM_H
|
||||
|
||||
#include<stdint.h>
|
||||
#include<stddef.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t from, to;
|
||||
} SharedRange;
|
||||
|
||||
typedef enum {
|
||||
VPM_KERNEL, VPM_USER
|
||||
} AllocationOwner;
|
||||
|
||||
void set_temporary_mapping(uint32_t addr);
|
||||
|
||||
uint32_t vpm_find_free(uint32_t addrspace, AllocationOwner owner, size_t len);
|
||||
void *vpm_map(uint32_t cr3, AllocationOwner owner, uint32_t virt, uint32_t phys, size_t len);
|
||||
uint32_t vpm_create_space();
|
||||
void vpm_set_space(uint32_t cr3);
|
||||
uint32_t vpm_get_phys(uint32_t cr3, uint32_t);
|
||||
void vpm_unmap(uint32_t cr3, uint32_t virt, size_t len);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user