2019-03-06 20:05:18 +01:00
|
|
|
;=----------------------------------------------------------------------------=;
|
|
|
|
; GNU GPL OS/K ;
|
|
|
|
; ;
|
|
|
|
; Desc: Memory management from protected mode ;
|
|
|
|
; (x86_64 architecture only) ;
|
|
|
|
; ;
|
|
|
|
; ;
|
|
|
|
; Copyright © 2018-2019 The OS/K Team ;
|
|
|
|
; ;
|
|
|
|
; This file is part of OS/K. ;
|
|
|
|
; ;
|
|
|
|
; OS/K is free software: you can redistribute it and/or modify ;
|
|
|
|
; it under the terms of the GNU General Public License as published by ;
|
|
|
|
; the Free Software Foundation, either version 3 of the License, or ;
|
|
|
|
; (at your option) any later version. ;
|
|
|
|
; ;
|
|
|
|
; OS/K is distributed in the hope that it will be useful, ;
|
|
|
|
; but WITHOUT ANY WARRANTY; without even the implied warranty of ;
|
|
|
|
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;
|
|
|
|
; GNU General Public License for more details. ;
|
|
|
|
; ;
|
|
|
|
; You should have received a copy of the GNU General Public License ;
|
|
|
|
; along with OS/K. If not, see <https://www.gnu.org/licenses/>. ;
|
|
|
|
;=----------------------------------------------------------------------------=;
|
|
|
|
|
2019-03-28 22:53:16 +01:00
|
|
|
%define MAX_MEMORY 4 ; GiB
|
2019-03-27 17:29:39 +01:00
|
|
|
|
2019-03-06 20:05:18 +01:00
|
|
|
[BITS 32]
|
2019-03-12 22:11:00 +01:00
|
|
|
[section .text]
|
2019-03-06 20:05:18 +01:00
|
|
|
; ---------------------------------------------------------------------------- ;
|
|
|
|
; Constructor for the page tables in protected mode ;
|
|
|
|
; ---------------------------------------------------------------------------- ;
|
|
|
|
Setup_paging:
|
|
|
|
;; Map the first PML4 entry to PDP table
|
|
|
|
mov eax, PDP_table
|
2019-03-08 08:43:44 +01:00
|
|
|
or eax, 1 << 1 | 1 << 0 ; present + writable
|
2019-03-06 20:05:18 +01:00
|
|
|
mov [PML4_table], eax
|
|
|
|
|
2019-03-28 10:34:18 +01:00
|
|
|
;; Map the PDP entries to PD tables
|
|
|
|
mov ebx, PD_table ; start address
|
|
|
|
mov ecx, 0x0 ; counter variable
|
2019-03-27 17:29:39 +01:00
|
|
|
.map_pdp_table:
|
2019-03-28 10:34:18 +01:00
|
|
|
mov eax, ebx
|
2019-03-08 08:43:44 +01:00
|
|
|
or eax, 1 << 1 | 1 << 0 ; present + writable
|
2019-03-28 10:34:18 +01:00
|
|
|
mov [PDP_table + 8 * ecx], eax
|
2019-03-27 17:29:39 +01:00
|
|
|
inc ecx
|
2019-03-28 10:34:18 +01:00
|
|
|
add ebx, 4096
|
|
|
|
cmp ecx, MAX_MEMORY ; PDP table is mapped if MAX_MEMORY
|
|
|
|
jne .map_pdp_table ; else map the next entry
|
2019-03-06 20:05:18 +01:00
|
|
|
|
|
|
|
;; Map each PD entry to a 'huge' 2MiB page
|
2019-03-28 10:34:18 +01:00
|
|
|
|
2019-03-08 08:43:44 +01:00
|
|
|
mov ecx, 0x0 ; counter variable
|
2019-03-27 17:29:39 +01:00
|
|
|
.map_pd_table:
|
2019-03-06 20:05:18 +01:00
|
|
|
;; map ecx-th PD entry to a huge page that starts at address 2MiB*ecx
|
|
|
|
mov eax, 0x200000
|
2019-03-08 08:43:44 +01:00
|
|
|
mul ecx ; start address of ecx-th page
|
|
|
|
or eax, 1 << 7 | 1 << 1 | 1 << 0 ; present + writable + huge
|
2019-03-06 20:05:18 +01:00
|
|
|
mov [PD_table + ecx * 8], eax
|
|
|
|
inc ecx
|
2019-03-27 17:29:39 +01:00
|
|
|
cmp ecx, 512 * MAX_MEMORY ; PD table is mapped if 512
|
|
|
|
jne .map_pd_table ; else map the next entry
|
2019-03-06 20:05:18 +01:00
|
|
|
|
2019-03-06 20:05:18 +01:00
|
|
|
; ---------------------------------------------------------------------------- ;
|
|
|
|
; Enable long mode and paging ;
|
|
|
|
; ---------------------------------------------------------------------------- ;
|
|
|
|
Go64:
|
2019-03-06 20:05:18 +01:00
|
|
|
pusha
|
|
|
|
|
2019-03-06 20:05:18 +01:00
|
|
|
;; Registering paging
|
|
|
|
mov eax, PML4_table
|
2019-03-08 08:43:44 +01:00
|
|
|
mov cr3, eax ; Load PML4 to cr3
|
2019-03-06 20:05:18 +01:00
|
|
|
|
|
|
|
mov eax, cr4
|
|
|
|
or eax, 1 << 5
|
2019-03-08 08:43:44 +01:00
|
|
|
mov cr4, eax ; Enable PAE
|
2019-03-06 20:05:18 +01:00
|
|
|
|
|
|
|
;; Activate long mode
|
2019-03-08 08:43:44 +01:00
|
|
|
mov ecx, 0xC0000080 ; Address of MSR
|
|
|
|
rdmsr ; Read MSR
|
|
|
|
or eax, 1 << 8 ; LME = 1. (Long Mode Enable)
|
|
|
|
wrmsr ; Write MSR
|
2019-03-06 20:05:18 +01:00
|
|
|
|
|
|
|
;; Enable paging
|
|
|
|
mov eax, cr0
|
2019-03-08 08:43:44 +01:00
|
|
|
or eax, 1 << 31 ; Make MSR bit 31 (PG = Paging) to 1 :
|
|
|
|
; |1|000000000000000000000000000000
|
|
|
|
; |
|
|
|
|
; `------ Paging bit
|
2019-03-06 20:05:18 +01:00
|
|
|
mov cr0, eax
|
2019-03-06 20:05:18 +01:00
|
|
|
jmp .end
|
|
|
|
nop
|
|
|
|
nop
|
|
|
|
.end:
|
2019-03-06 20:05:18 +01:00
|
|
|
|
2019-03-06 20:05:18 +01:00
|
|
|
popa
|
2019-03-06 20:05:18 +01:00
|
|
|
ret
|
2019-03-06 20:05:18 +01:00
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------- ;
|
|
|
|
; Checks if Grub has enabled A20 line ;
|
|
|
|
; ---------------------------------------------------------------------------- ;
|
|
|
|
CheckA20:
|
|
|
|
pushad
|
2019-03-08 08:43:44 +01:00
|
|
|
mov edi, 0x112345 ; Odd megabyte address.
|
|
|
|
mov esi, 0x012345 ; Even megabyte address.
|
|
|
|
mov [esi],esi ; Making sure that both addresses contain diffrent values.
|
|
|
|
mov [edi],edi ; (if A20 line is cleared the two pointers would point to the address 0x012345 that would contain 0x112345 (edi))
|
|
|
|
cmpsd ; Compare addresses to see if the're equivalent.
|
2019-03-06 20:05:18 +01:00
|
|
|
popad
|
2019-03-08 08:43:44 +01:00
|
|
|
jne .A20_on ; If not equivalent , A20 line is set.
|
2019-03-06 20:05:18 +01:00
|
|
|
jmp .A20_err
|
|
|
|
.A20_on:
|
|
|
|
ret
|
|
|
|
.A20_err:
|
2019-03-08 08:43:44 +01:00
|
|
|
mov ax, "04" ; ERROR 04 : A20 line failed
|
2019-03-06 20:05:18 +01:00
|
|
|
jmp Error
|
2019-03-25 23:10:06 +01:00
|
|
|
|
|
|
|
[BITS 64]
|
|
|
|
; ---------------------------------------------------------------------------- ;
|
|
|
|
; Initilizes the stack ;
|
|
|
|
; ---------------------------------------------------------------------------- ;
|
|
|
|
InitStack:
|
|
|
|
xor rax, rax ; "Fill pattern"
|
|
|
|
push rcx
|
|
|
|
push rdi
|
|
|
|
|
|
|
|
;; Begin address to fill and length
|
2019-05-11 20:55:46 +02:00
|
|
|
mov qword [realKernelEnd], kernelEnd
|
2019-05-13 02:00:02 +02:00
|
|
|
mov qword [newKernelEnd], KERNEL_STACK
|
|
|
|
mov qword [kernelEnd], qword 0xbad0bad
|
|
|
|
mov rdi, kernelEnd + 16
|
|
|
|
mov rcx, KERNEL_STACK - kernelEnd - 16 * 2
|
|
|
|
; The Stack can begin at kernelEnd + 16 in order to not overwrite the
|
|
|
|
; kernel by pushing
|
|
|
|
; We must stop before the return address in the current stack so -16 in rcx
|
2019-03-25 23:10:06 +01:00
|
|
|
|
|
|
|
;; If bit 0 is on, fill one byte
|
|
|
|
sar rcx, 1 ; Shift bit 0 into CY
|
|
|
|
jnc $ + 3
|
|
|
|
stosb
|
2019-03-27 17:29:39 +01:00
|
|
|
|
2019-03-25 23:10:06 +01:00
|
|
|
;; We are word aligned and if bit 1 was on fill another word
|
|
|
|
sar rcx, 1 ; Shift bit 1 into CY
|
|
|
|
jnc $ + 4
|
|
|
|
stosw
|
2019-03-27 17:29:39 +01:00
|
|
|
|
2019-03-25 23:10:06 +01:00
|
|
|
;; We are dword aligned and if bit 2 was on fill another dword
|
|
|
|
sar rcx, 1 ; Shift bit 2 into CY
|
|
|
|
jnc $ + 3
|
|
|
|
stosd
|
|
|
|
;; RCX now equals the number of qwords to fill
|
|
|
|
repnz stosq ; Finish by writing RCX qwords.
|
|
|
|
|
|
|
|
pop rdi
|
|
|
|
pop rcx
|
|
|
|
ret
|