CR3 points to the physical address page directory.
The first entry of the page directory points to the physical address of a page table.
The page table entries point to the physical addresses of the first 1024 4K pages.
Everything is 4K-aligned, but it reboots.
Here's the code that implements it, it seems completely OK but it reboots the machine, and I know that code like this will take me 1 or 2 weeks to fix on my own.
Code: Select all
;;;;INIT: 32-bit Paging initialization
;;;;INIT: 32-bit Paging initialization
;;;;INIT: 32-bit Paging initialization
;;;;INIT: 32-bit Paging initialization
;;;;INIT: 32-bit Paging initialization
;;;;INIT: 32-bit Paging initialization
;;;;INIT: 32-bit Paging initialization
;;;;INIT: 32-bit Paging initialization
cli
;Generate an empty page directory
;in a place we have proven to be empty
;and, if we have more than 16MB, put as much
;as we can of the paging structures there:
;;
mov widedi,kernel_page_window ;Make this function dynamically get
;a free page, but for that we need to
;detect memory by different methods
;before loading the kernel and record
;the memory used by the kernel with a
;memory management function set that
;tell us if a given page is in a reserved
;area or not. That's not the function
;of paging itself but of basic memory detection,
;and reserved areas defined by the PC (BIOS,
;video, DMA, PCI, the first Megabyte, memory holes...).
;It must record the area in an element with
;value 0 (NULL) in the CR3 array, and an
;index variable to indicate the currently active
;CR3. Element 0 should always be the root CR3.
call OPCODE__CPU_generate_4KB_empty_page_directory ;Take into account reserved regions from some subsystem and add complexity to it gradually
;Generate an entry in the page directory
;to a page table for the first 2 or 4 Megabytes:
;;
mov wideax,kernel_page_window+(4096*1)
or dword[widedi],_FLAG_x86_32_pageDirectoryEntry_Bit0_Present_TRUE
or dword[widedi],wideax
;Generate the addresses for the first 4MB
;in the first page table:
;;
mov widedi,kernel_page_window+(4096*1) ;Address of page table
mov widecx,1024 ;1024 entries
xor wideax,wideax ;Current address
or wideax,_FLAG_x86_32_pageDirectoryEntry_Bit0_Present_TRUE|_FLAG_x86_32_pageDirectoryEntry_Bit1_ReadWrite|_FLAG_x86_32_pageDirectoryEntry_Bit2_SupervisorLevel
align wideword_sz
.pgtbl0:
stosd
add wideax,4096
loop .pgtbl0
;Enable default 32-bit paging:
;;
mov wideax,kernel_page_window
call OPCODE__CPU_Enable_Default_Paging
hlt
sti
;;;;END: 32-bit Paging initialization
;;;;END: 32-bit Paging initialization
;;;;END: 32-bit Paging initialization
;;;;END: 32-bit Paging initialization
;;;;END: 32-bit Paging initialization
;;;;END: 32-bit Paging initialization
;;;;END: 32-bit Paging initialization
;;;;END: 32-bit Paging initialization
Code: Select all
align 4096
kernel_page_window:
times 4096 db 0 ;Could be used as the kernel page directory
times 4096 db 0 ;Could be used as 1 entry of the kernel page directory (a page table)
times 4096 db 0 ;Could be used as 1 entry of the kernel page directory (a page table)
times 4096 db 0 ;Could be used as 1 entry of the kernel page directory (a page table)
times 4096 db 0 ;Could be used as 1 entry of the kernel page directory (a page table)
Code: Select all
;Inputs:
; WIDEDI -- 4KB-aligned memory address
; to place the generated page directory.
;
;
;;
OPCODE__CPU_generate_4KB_empty_page_directory:
push wideax
push widecx
pushfwide
mov cr3,widedi
mov wideax,_FLAG_x86_32_pageDirectoryEntry_Bit0_Present_FALSE|_FLAG_x86_32_pageDirectoryEntry_Bit1_ReadWrite|_FLAG_x86_32_pageDirectoryEntry_Bit2_SupervisorLevel
mov widecx,1024
rep stosd
popfwide
pop widecx
pop wideax
retwide
Code: Select all
;Parameters:
;
; WIDEAX -- Page directory root
;
;
;
;;
;;;
;;;;
align wideword_sz
OPCODE__CPU_Enable_Default_Paging:
push wideax
pushfwide
;Load the page directory into CR3
;and store the kernel page directory
;in element 0 of the system's CR3 values array:
;;
mov cr3,wideax
mov [CR3_array],wideax
;Enable paging bit 31 in CR0.
;Bit 31 for paging makes thing as if
;paging was the best, most difficult
;thing from the x86 CPU, the last thing left
;that was done:
;;
mov eax,cr0
or eax,10000000_00000000_00000000_00000000b
mov cr0,eax
popfwide
pop wideax
retwide
Code: Select all
; -
_FLAG_x86_32_pageDirectoryEntry_Bit0_Present_TRUE equ 00000001b
_FLAG_x86_32_pageDirectoryEntry_Bit0_Present_FALSE equ 00000000b
; -
; -
_FLAG_x86_32_pageDirectoryEntry_Bit1_ReadWrite equ 00000010b
_FLAG_x86_32_pageDirectoryEntry_Bit1_ReadOnly equ 00000000b
; -
; -
_FLAG_x86_32_pageDirectoryEntry_Bit2_SupervisorLevel equ 00000000b
_FLAG_x86_32_pageDirectoryEntry_Bit2_UserLevel equ 00000100b
; -
; -
_FLAG_x86_32_pageDirectoryEntry_Bit3_WriteBack equ 00000000b
_FLAG_x86_32_pageDirectoryEntry_Bit3_WriteThrough equ 00001000b
; -
; -
_FLAG_x86_32_pageDirectoryEntry_Bit4_DisableCache equ 00010000b
_FLAG_x86_32_pageDirectoryEntry_Bit4_EnableCache equ 00010000b
; -
; -
CPU_x86_32_Paging_Bit0_Present_TRUE equ 00000001b
CPU_x86_32_Paging_Bit0_Present_FALSE equ 00000000b
; -
; -
CPU_x86_32_Paging_Bit1_ReadWrite equ 00000010b
CPU_x86_32_Paging_Bit1_ReadOnly equ 00000000b
; -
; -
CPU_x86_32_Paging_Bit2_SupervisorLevel equ 00000000b
CPU_x86_32_Paging_Bit2_UserLevel equ 00000100b
; -
; -
CPU_x86_32_Paging_Bit3_WriteBack equ 00000000b
CPU_x86_32_Paging_Bit3_WriteThrough equ 00001000b
; -
; -
CPU_x86_32_Paging_Bit4_DisableCache equ 00010000b
CPU_x86_32_Paging_Bit4_EnableCache equ 00000000b
; -
; -
CPU_x86_32_Paging_Bit5_Accessed_FALSE equ 00000000b
CPU_x86_32_Paging_Bit5_Accessed_TRUE equ 00100000b
; -
; -
CPU_x86_32_PageTable_Bit6_Dirty_FALSE equ 00000000b
CPU_x86_32_PageTable_Bit6_Dirty_TRUE equ 01000000b
; -
;-
CPU_x86_32_PageTable_Bit7_PageAttributeTable_FALSE equ 00000000b
CPU_x86_32_PageTable_Bit7_PageAttributeTable_TRUE equ 10000000b
;-
;-
CPU_x86_32_PageTable_Bit8_GlobalPage_FALSE equ 0_00000000b
CPU_x86_32_PageTable_Bit8_GlobalPage_TRUE equ 1_00000000b
;-
; -
CPU_x86_32_PageDir_Bit12_PageAttributeTable_FALSE equ 00000000_00000000b
CPU_x86_32_PageDir_Bit12_PageAttributeTable_TRUE equ 00010000_00000000b
; -
; ---
CPU_x86_32_Paging_Bit9_11_AVL_0 equ 00000000_00000000b
CPU_x86_32_Paging_Bit9_11_AVL_1 equ 00000010_00000000b
CPU_x86_32_Paging_Bit9_11_AVL_2 equ 00000100_00000000b
CPU_x86_32_Paging_Bit9_11_AVL_3 equ 00000110_00000000b
CPU_x86_32_Paging_Bit9_11_AVL_4 equ 00001000_00000000b
CPU_x86_32_Paging_Bit9_11_AVL_5 equ 00001010_00000000b
CPU_x86_32_Paging_Bit9_11_AVL_6 equ 00001100_00000000b
CPU_x86_32_Paging_Bit9_11_AVL_7 equ 00001110_00000000b
; ---
Code: Select all
;A certain number of CR3 registers mapped
;physically in the main kernel image should
;allow us to switch/swap address spaces enough.
;
;This needs to be aligned to 4096 since it's
;the most important thing to map globally in
;any paging directory, but the main kernel
;image should also be mapped, so it should be
;minimal/small, for what concerns the kernel:
;;
align 4096
CR3_array times 128 dd 0
CR3_index ww 0