85 Commits

Author SHA1 Message Date
b7c004528a Implement tracking of available physical pages 2025-12-23 22:13:09 +01:00
5012c8dc37 Initialize system PTE pools and implement reservation routines 2025-12-23 20:16:08 +01:00
1e3917882c Initialize system page tables and configure kernel mappings 2025-12-23 18:03:02 +01:00
b3b874d3ce Include mm/colors.cc in kernel build configuration 2025-12-23 14:29:26 +01:00
288b2f8b24 Introduce page coloring support to memory manager 2025-12-23 14:27:12 +01:00
c7cc536685 Add storage for PFN database size 2025-12-23 14:13:33 +01:00
b8e81e2223 Initialize memory manager during kernel startup 2025-12-23 14:05:07 +01:00
0fd2b8b729 Update modified page list enum terminology 2025-12-23 13:55:42 +01:00
560cd43b34 Update memory manager type definitions and constants 2025-12-23 12:04:43 +01:00
f0a06db7d2 Bring up i686 page table initialization 2025-12-22 23:48:04 +01:00
7575526f07 Fix physical page count overflow by using 64-bit type 2025-12-22 23:32:54 +01:00
643fd0d1e8 Fix PTE free list sentinel handling 2025-12-22 15:00:14 +01:00
6aa148784b Select correct self-map base for PAE and non-PAE paging 2025-12-22 10:14:11 +01:00
e237a944cc Extend PTE helpers with raw read and write support 2025-12-22 08:21:43 +01:00
755a167f2c Respect architecture-specific PTE layouts and write PTEs via PML-aware helpers 2025-12-22 00:07:48 +01:00
24dccf4bed Make PPE mapping architecture-specific 2025-12-19 20:25:43 +01:00
7b93c39348 Add early spin lock initialization 2025-12-19 19:12:50 +01:00
570301bb35 Clarify page table entry offset semantics 2025-12-18 22:38:59 +01:00
b183d52806 Fix paging abstraction for PDE/PTE virtual address calculation 2025-12-18 22:26:31 +01:00
687c58d923 Implement initial virtual memory layout setup 2025-12-17 22:28:08 +01:00
049c9c6bbd Update SelfMapAddress 2025-12-17 20:35:28 +01:00
f1a76bc01a Call page table initialization 2025-12-16 22:34:41 +01:00
cb4d113e31 Add virtual address validation and system PTE helpers 2025-12-16 22:31:15 +01:00
728241f998 Move memory layout initialization to architecture-specific code 2025-12-16 20:36:16 +01:00
00d428d8de Architecture-specific system PTE limits 2025-12-16 20:05:51 +01:00
020b7c7676 Extend memory layout 2025-12-16 18:37:28 +01:00
2265a4a522 Remove unsupported PML4/PML5 PTE interfaces 2025-12-16 14:13:55 +01:00
dc23f91110 Split PTE implementation per architecture 2025-12-16 14:08:32 +01:00
7f0ca6a948 Compute PTE count per page from entry size 2025-12-15 13:56:39 +01:00
36c273ea13 Implement early page table mapping routines 2025-12-15 13:24:02 +01:00
5cf3dfa844 Add bootstrap physical page allocator 2025-12-15 12:38:08 +01:00
070c508e42 Introduce kernel virtual memory layout 2025-12-14 15:35:24 +01:00
5224dc315f Compute PFN database size during MM initialization 2025-12-13 22:50:27 +01:00
b7bbf9ffa8 Tidy up memory type verification helpers 2025-12-13 21:04:55 +01:00
eae48320f3 Harden PFN initialization and expose page count 2025-12-13 21:01:13 +01:00
17b5649362 Make memory type verification helpers accessible to PFN 2025-12-13 20:50:32 +01:00
783a9eea3a Extract PFN management into separate module 2025-12-13 20:42:48 +01:00
237f6a2974 Refactor memory manager initialization into MM::Manager 2025-12-13 20:21:08 +01:00
ee9514fd5c Fix GetP5eAddress return type 2025-12-13 19:58:49 +01:00
63c27a149a Add missing virtual GetPteDistance to pagemap interface 2025-12-06 00:29:51 +01:00
7694df7744 Add architecture-specific GetPteDistance 2025-12-06 00:19:24 +01:00
c710ec4688 Refactor XPA detection API 2025-12-04 23:07:59 +01:00
8054bb915a Fix incorrect pointer types 2025-11-30 20:06:51 +01:00
86aa22e5f8 Fix incorrect pointer types 2025-11-30 20:03:12 +01:00
4a7494ad3f Split paging interface into arch-specific code 2025-11-30 19:19:32 +01:00
d4287198b0 Implement virtual address resolvers for all page map levels and add XPA status accessor 2025-11-30 18:23:51 +01:00
4265ae92d0 Add MM::PageMap::GetXpaStatus() for querying PML level 2025-11-29 23:45:00 +01:00
931586eebd Refactor PageMap to enable architecture-specific VA translation 2025-11-29 23:37:08 +01:00
c099882866 Add PFN_COUNT typedef 2025-11-29 23:14:30 +01:00
0097cb88d7 Correct LA57 paging base addresses, add self-map constants and extend PTE structures 2025-11-29 23:11:54 +01:00
20b0bfdfad Add kernel parameters section and fix minor formatting issues 2025-11-17 23:19:16 +01:00
35523a230a Prevent duplicate object generation by linking xtoskrnl with libxtos 2025-11-17 23:15:22 +01:00
7b11a8feb1 Add page list and PTE pool type enums 2025-11-06 06:55:31 +01:00
0cf178a648 Fix class name 2025-11-04 23:10:02 +01:00
66f27e4b9a Add GetPageFrameNumber() to PTE interfaces 2025-11-04 23:03:47 +01:00
10b8ab347a Make MM::Paging::GetExtendedPhysicalAddressingStatus public 2025-11-04 22:51:34 +01:00
071c840ca8 Replace writable flag with AttributesMask in PTE setup 2025-11-04 17:34:49 +01:00
dda8f88830 Add PTE attribute definitions 2025-11-04 17:26:47 +01:00
cb2da54956 Unify PTE pointer types across MM subsystem 2025-11-03 22:13:32 +01:00
fd13091476 Unify MMPML2_PTE field naming convention 2025-11-03 22:02:59 +01:00
c28c3f8344 Add input qualifiers to page map interface definitions 2025-11-03 20:04:21 +01:00
dfb0284427 Add input qualifiers to paging interface definitions 2025-11-03 16:00:46 +01:00
1150b9ecdb Add PTE management routines 2025-10-30 22:03:25 +01:00
f6dac12057 Add missing EmptyPteList field to MMPAGEMAP_INFO 2025-10-30 20:19:35 +01:00
ffa480d69a Implement unified PTE accessors and management helpers 2025-10-30 20:14:02 +01:00
0120ba167f Introduce RAII helpers for runlevel transitions 2025-10-29 23:07:27 +01:00
4e9dc15501 Define VIRTUAL macro 2025-10-29 22:32:07 +01:00
164ff0c135 Expand spinlock queue levels 2025-10-28 08:35:34 +01:00
f538d035e2 Introduce global spinlock initialization and RAII guard classes 2025-10-27 20:48:44 +01:00
72b92f853e Use PTE base from PageMapInfo 2025-10-23 08:54:57 +02:00
00b04f5405 Refactor IDT gate setup to use explicit DPL and type fields 2025-10-18 18:29:49 +02:00
52afd31e77 Implement Stage2 loading in VBR code 2025-10-17 20:44:57 +02:00
7f06abf236 New message for unsupported CPUs 2025-10-17 09:18:49 +02:00
4f4df52d3d Include architecture-specific code in VBR 2025-10-17 09:12:54 +02:00
764fec4d75 Implement low-level CPU initialization support for i686 and AMD64 boot sectors 2025-10-17 09:05:24 +02:00
ca8a539c0e Change message labels naming convention 2025-10-17 08:58:41 +02:00
c206b443ed Move XTLDR image base definition to arch-specific config 2025-10-16 12:22:30 +02:00
b19b27a621 Build relocatable image to allow proper UEFI loading 2025-10-16 12:10:00 +02:00
56b81f5d73 Set fixed image base 2025-10-15 23:06:12 +02:00
1e99a3f4a9 Set fixed alignment and base address to allow execution under BIOS 2025-10-15 21:03:03 +02:00
0a71bc3995 Print fallback message in non-EFI environment 2025-10-15 20:55:16 +02:00
13a9d4c522 Introduce legacy VGA text mode support 2025-10-15 20:49:17 +02:00
9bf867af95 Propagate compile definitions to bootsector sources 2025-10-11 23:18:14 +02:00
a7be533521 Improve reliability and correctness of the PowerShell configure script (#21)
Co-authored-by: Pedro Valadés <perikiyoxd@gmail.com>
Co-committed-by: Pedro Valadés <perikiyoxd@gmail.com>
2025-10-10 20:18:05 +02:00
fdbe157c18 Fix CHS sector-by-sector read loop 2025-10-10 19:05:23 +02:00
65 changed files with 5144 additions and 643 deletions

View File

@@ -1,6 +1,8 @@
# XT Boot Sector
PROJECT(BOOTSECT)
add_definitions("-DARCH_ESP_SOURCE=\\\"${ARCH}/cpu.S\\\"")
# Compile boot sectors
compile_bootsector(mbrboot ${BOOTSECT_SOURCE_DIR}/mbrboot.S 0x7C00 Start)
compile_bootsector(espboot ${BOOTSECT_SOURCE_DIR}/espboot.S 0x7C00 Start)

144
boot/bootsect/amd64/cpu.S Normal file
View File

@@ -0,0 +1,144 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: boot/bootsect/amd64/cpu.S
* DESCRIPTION: Low-level support for CPU initialization
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
BuildPageMap:
/* Generate page map for first 1GB of memory */
pushaw
pushw %es
cld
movw $(0x1000 / 16), %ax
movw %ax, %es
xorw %di, %di
movl $(0x2000 | 0x07), %eax
stosl
xorl %eax, %eax
movw $1021, %cx
rep stosl
movw $(0x2000 / 16), %ax
movw %ax, %es
xorw %di, %di
movl $(0x3000 | 0x07), %eax
stosl
xorl %eax, %eax
movw $1021, %cx
rep stosl
movw $(0x3000 / 16), %ax
movw %ax, %es
xorw %di, %di
movw $512, %cx
movl $0x00000083, %eax
.BuildPageMapLoop:
/* Identity map 512 pages of 2MB */
movl %eax, %es:(%di)
addl $2097152, %eax
addw $0x08, %di
loop .BuildPageMapLoop
popw %es
popaw
ret
InitializeCpu:
/* Check if CPU supports CPUID, long mode and PAE */
pushal
pushfl
popl %eax
movl %eax, %ebx
xorl $0x00200000, %eax
pushl %eax
popfl
pushfl
popl %eax
cmpl %ebx, %eax
je CpuUnsupported
movl $0x01, %eax
cpuid
testl $0x40, %edx
jz CpuUnsupported
movl $0x80000000, %eax
cpuid
cmpl $0x80000000, %eax
jbe CpuUnsupported
movl $0x80000001, %eax
cpuid
testl $0x20000000, %edx
jz CpuUnsupported
popal
call LoadGdt
ret
LoadGdt:
/* Load Global Descriptor Table */
lgdt .GdtPointer
ret
RunStage2:
/* Switch to long mode and pass control to Stage 2 */
call BuildPageMap
call ParseExecutableHeader
xorl %edx, %edx
pushl %edx
pushl %eax
cli
xorw %ax, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
movl %cr4, %eax
orl $0x00A0, %eax
movl %eax, %cr4
movl $0x00001000, %eax
movl %eax, %cr3
movl $0xC0000080, %ecx
rdmsr
orl $0x00000100, %eax
wrmsr
movl %cr0, %eax
orl $0x80000001, %eax
movl %eax, %cr0
ljmp $0x10, $.Stage2LongMode
.code64
.Stage2LongMode:
/* Set segments and stack, then jump to Stage 2 */
movw $0x18, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
xorw %ax, %ax
movw %ax, %fs
movw %ax, %gs
popq %rax
xorq %rbx, %rbx
xorq %rcx, %rcx
xorq %rdx, %rdx
xorq %rsi, %rsi
xorq %rdi, %rdi
xorq %rbp, %rbp
jmp *%rax
.code16
.GdtDescriptor:
/* Global Descriptor Table */
.quad 0x0000000000000000
.quad 0x0000000000000000
.quad 0x00AF9A000000FFFF
.quad 0x00CF92000000FFFF
.quad 0x00009E000000FFFF
.quad 0x000092000000FFFF
.quad 0x00CF9B000000FFFF
.GdtPointer:
/* Pointer to Global Descriptor Table */
.word .GdtPointer - .GdtDescriptor - 1
.long .GdtDescriptor
.Stage2FileName:
/* Name of Stage 2 executable file */
.ascii "BOOTX64 EFI"

View File

@@ -121,15 +121,15 @@ VerifyBiosParameterBlock:
ja FsError
ReadExtraCode:
/* Read second VBR sector with extra boot code */
/* Read second VBR sector with extra boot code (3 sectors starting from sector 2) */
movl HiddenSectors - Start(%bp), %eax
addl $0x02, %eax
movw $0x01, %cx
movw $0x03, %cx
xorw %bx, %bx
movw %bx, %es
movw $0x7E00, %bx
call ReadSectors
jmp StartSectors
jmp StartExtraCode
ReadSectors:
/* Check for extended BIOS functions and use it only if available */
@@ -139,18 +139,22 @@ ReadSectors:
movw $0x55AA, %bx
movb DriveNumber - Start(%bp), %dl
int $0x13
jc ReadCHS
jc .ReadCHS
cmpw $0xAA55, %bx
jne ReadCHS
jne .ReadCHS
testb $0x01, %cl
jz ReadCHS
jz .ReadCHS
/* Verify drive size and determine whether to use CHS or LBA */
cmpl %edi, %eax
jnb ReadLBA
jnb .ReadLBA
ReadCHS:
.ReadCHS:
/* Read sectors using CHS */
popal
.CHSLoop:
/* Read sector by sector using CHS */
pushw %cx
pushal
xorl %edx, %edx
@@ -176,11 +180,11 @@ ReadCHS:
movw %es, %dx
addw $0x20, %dx
movw %dx, %es
loop ReadCHS
loop .CHSLoop
popw %es
ret
ReadLBA:
.ReadLBA:
/* Prepare DAP packet and read sectors using LBA */
popal
pushw %cx
@@ -209,19 +213,19 @@ ReadLBA:
movw %dx, %es
popw %bx
subw %si, %cx
jnz ReadLBA
jnz .ReadLBA
popw %es
ret
DiskError:
/* Display disk error message and reboot */
movw $msgDiskError, %si
movw $.MsgDiskError, %si
call Print
jmp Reboot
FsError:
/* Display FS error message and reboot */
movw $msgFsError, %si
movw $.MsgFsError, %si
call Print
jmp Reboot
@@ -229,48 +233,297 @@ Print:
/* Simple routine to print messages */
lodsb
orb %al, %al
jz DonePrint
jz .DonePrint
movb $0x0E, %ah
movw $0x07, %bx
int $0x10
jmp Print
DonePrint:
.DonePrint:
retw
Reboot:
/* Display a message, wait for a key press and reboot */
movw $msgAnyKey, %si
movw $.MsgAnyKey, %si
call Print
xorw %ax, %ax
int $0x16
int $0x19
msgAnyKey:
.ascii "Press any key to restart\r\n"
.MsgAnyKey:
.ascii "Press any key to restart...\r\n\0"
msgDiskError:
.ascii "Disk error\r\n"
.MsgDiskError:
.ascii "Disk error!\r\n\0"
msgFsError:
.ascii "File system error\r\n"
.MsgFsError:
.ascii "File system error!\r\n\0"
/* Fill the rest of the VBR with zeros and add VBR signature at the end */
.fill (510 - (. - Start)), 1, 0
.word 0xAA55
StartSectors:
/* Print message */
movw $msgUnavailable, %si
StartExtraCode:
/* Load XTLDR file from disk */
call LoadStage2
/* Enable A20 gate */
call EnableA20
/* Call architecture specific initialization code */
call InitializeCpu
/* Jump to Stage2 */
call RunStage2
Clear8042:
/* Clear 8042 PS/2 buffer */
nop
nop
nop
nop
inb $0x64, %al
cmpb $0xff, %al
je .Clear8042_Done
testb $0x02, %al
jnz Clear8042
.Clear8042_Done:
ret
EnableA20:
/* Enable A20 gate */
pushaw
call Clear8042
movb $0xD1, %al
outb %al, $0x64
call Clear8042
movb $0xDF, %al
outb %al, $0x60
call Clear8042
movb $0xFF, %al
outb %al, $0x64
call Clear8042
popaw
ret
FindFatEntry:
/* Find a file or directory in the FAT table */
pushw %bx
pushw %cx
pushw %dx
pushw %si
pushw %di
.FindFatCluster:
/* Find FAT32 cluster holding the entry */
cmp $0x0FFFFFF8, %eax
jae .FindEntryFail
pushl %eax
movw $0x0200, %bx
movw %bx, %es
call ReadCluster
popl %eax
movb SectorsPerCluster - Start(%bp), %cl
shlw $0x04, %cx
xorw %di, %di
.FindEntryLoop:
/* Find the entry */
movb %es:(%di), %al
cmpb $0x00, %al
je .FindEntryFail
cmpb $0xE5, %al
je .FindSkipEntry
movb %es:0x0B(%di), %ah
cmpb $0x0F, %ah
je .FindSkipEntry
pushw %di
pushw %si
pushw %cx
movw $0x0B, %cx
repe cmpsb
popw %cx
popw %si
popw %di
jnz .FindSkipEntry
movw %es:0x1A(%di), %ax
movw %es:0x14(%di), %dx
shll $0x10, %edx
orl %edx, %eax
clc
jmp .FindEntryDone
.FindSkipEntry:
/* Skip to the next entry */
addw $0x20, %di
decw %cx
jnz .FindEntryLoop
call GetFatEntry
jmp .FindFatCluster
.FindEntryFail:
/* Error, file/directory not found */
stc
.FindEntryDone:
/* Clean up the stack */
popw %di
popw %si
popw %dx
popw %cx
popw %bx
ret
GetFatEntry:
/* Get FAT32 sector and offset from FAT table */
shll $0x02, %eax
movl %eax, %ecx
xorl %edx, %edx
movzwl BytesPerSector - Start(%bp), %ebx
pushl %ebx
divl %ebx
movzwl ReservedSectors - Start(%bp), %ebx
addl %ebx, %eax
movl HiddenSectors - Start(%bp), %ebx
addl %ebx, %eax
popl %ebx
decl %ebx
andl %ebx, %ecx
movzwl ExtendedFlags - Start(%bp), %ebx
andw $0x0F, %bx
jz LoadFatSector
cmpb FatCopies - Start(%bp), %bl
jae FsError
pushl %eax
movl BigSectorsPerFat - Start(%bp), %eax
mull %ebx
popl %edx
addl %edx, %eax
LoadFatSector:
/* Load FAT32 sector from disk */
pushl %ecx
movw $0x9000, %bx
movw %bx, %es
cmpl %esi, %eax
je .LoadFatSectorDone
movl %eax, %esi
xorw %bx, %bx
movw $0x01, %cx
call ReadSectors
.LoadFatSectorDone:
/* Clean up the stack */
popl %ecx
movl %es:(%ecx), %eax
andl $0x0FFFFFFF, %eax
ret
LoadStage2:
/* Load Stage2 executable, first find file in the path */
movl $0xFFFFFFFF, %esi
pushl %esi
movl 0x7C2C, %eax
movw $.EfiDirName, %si
call FindFatEntry
jc Stage2NotLoaded
movw $.BootDirName, %si
call FindFatEntry
jc Stage2NotLoaded
movw $.Stage2FileName, %si
call FindFatEntry
jc Stage2NotLoaded
popl %esi
/* Load XTLDR file from disk */
cmpl $0x02, %eax
jb FileNotFound
cmpl $0x0FFFFFF8, %eax
jae FileNotFound
movw $(0xF800 / 16), %bx
movw %bx, %es
.LoadStage2Loop:
/* Load file data from disk */
pushl %eax
xorw %bx, %bx
pushw %es
call ReadCluster
popw %es
xorw %bx, %bx
movb SectorsPerCluster - Start(%bp), %bl
shlw $0x05, %bx
movw %es, %ax
addw %bx, %ax
movw %ax, %es
popl %eax
pushw %es
call GetFatEntry
popw %es
cmpl $0x0FFFFFF8, %eax
jb .LoadStage2Loop
ret
ParseExecutableHeader:
/* Parse Stage2 PE/COFF executable header */
pushw %es
movw $(0xF800 / 16), %ax
movw %ax, %es
movl %es:60, %eax
addl $(4 + 20), %eax
movl %es:16(%eax), %eax
addl $0xF800, %eax
popw %es
ret
ReadCluster:
/* Read FAT32 cluster from disk */
decl %eax
decl %eax
xorl %edx, %edx
movzbl SectorsPerCluster - Start(%bp), %ebx
mull %ebx
pushl %eax
xorl %edx, %edx
movzbl FatCopies - Start(%bp), %eax
mull BigSectorsPerFat - Start(%bp)
movzwl ReservedSectors - Start(%bp), %ebx
addl %ebx, %eax
addl HiddenSectors - Start(%bp), %eax
popl %ebx
addl %ebx, %eax
xorw %bx, %bx
movzbw SectorsPerCluster - Start(%bp), %cx
call ReadSectors
ret
/* Include architecture specific code */
.include ARCH_ESP_SOURCE
CpuUnsupported:
/* Display CPU unsupported message and reboot */
popal
movw $.MsgCpuUnsupported, %si
call Print
jmp Reboot
/* Wait for key press and reboot */
xorw %ax, %ax
int $0x16
int $0x19
FileNotFound:
/* Display XTLDR not found message and reboot */
movw $.MsgXtLdrNotFound, %si
call Print
jmp Reboot
msgUnavailable:
.ascii "XTLDR requires EFI-based system!\r\nPress any key to restart\r\n"
Stage2NotLoaded:
/* Clean up the stack and display XTLDR not found message and reboot */
popl %esi
jmp FileNotFound
/* Fill the rest of the extra VBR with zeros */
.fill (1024 - (. - Start)), 1, 0
.BootDirName:
/* Boot directory name */
.ascii "BOOT "
.EfiDirName:
/* EFI directory name */
.ascii "EFI "
.MsgCpuUnsupported:
.ascii "CPU not supported!\r\n\0"
.MsgXtLdrNotFound:
.ascii "XTLDR Stage2 not found!\r\n\0"
/* Fill the rest of the extra VBR with zeros and add signature */
.fill (2043 - (. - Start)), 1, 0
.ascii "XTLDR"

124
boot/bootsect/i686/cpu.S Normal file
View File

@@ -0,0 +1,124 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: boot/bootsect/i686/cpu.S
* DESCRIPTION: Low-level support for CPU initialization
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
BuildPageMap:
/* Generate page map for first 16MB of memory */
pushaw
pushw %es
cld
movw $(0x1000 >> 0x04), %ax
movw %ax, %es
xorw %di, %di
movl $(0x2000 | 0x03), %eax
stosl
movl $(0x3000 | 0x03), %eax
stosl
movl $(0x4000 | 0x03), %eax
stosl
movl $(0x5000 | 0x03), %eax
stosl
xorl %eax, %eax
movw $(1024 - 4), %cx
rep stosl
movl $0x00000003, %eax
movl $4, %edx
movw $(0x2000 >> 0x04), %bx
.BuildPageMapLoop:
/* Identity map 1024 pages of 4KB */
movw %bx, %es
xorw %di, %di
pushl %edx
movw $1024, %cx
.FillPageMapTable:
/* Fill the page table */
movl %eax, %es:(%di)
addl $4096, %eax
addw $0x04, %di
loop .FillPageMapTable
popl %edx
addw $(0x1000 >> 0x04), %bx
decl %edx
jnz .BuildPageMapLoop
popw %es
popaw
ret
InitializeCpu:
/* Check if CPU supports CPUID */
pushal
pushfl
popl %eax
movl %eax, %ebx
xorl $0x00200000, %eax
pushl %eax
popfl
pushfl
popl %eax
cmpl %ebx, %eax
je CpuUnsupported
popal
call LoadGdt
ret
LoadGdt:
/* Load Global Descriptor Table */
lgdt .GdtPointer
ret
RunStage2:
/* Switch to protected mode and pass control to Stage 2 */
call BuildPageMap
call ParseExecutableHeader
pushl %eax
cli
movl %cr0, %eax
orl $0x01, %eax
movl %eax, %cr0
ljmp $0x08, $.Stage2ProtectedMode
.code32
.Stage2ProtectedMode:
/* Set segments and stack, then jump to Stage 2 */
movw $0x10, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
xorw %ax, %ax
movw %ax, %fs
movw %ax, %gs
popl %eax
xorl %ebx, %ebx
xorl %ecx, %ecx
xorl %edx, %edx
xorl %esi, %esi
xorl %edi, %edi
xorl %ebp, %ebp
movl $0x1000, %ebx
movl %ebx, %cr3
movl %cr0, %ebx
orl $0x80000000, %ebx
movl %ebx, %cr0
jmp *%eax
.code16
.GdtDescriptor:
/* Global Descriptor Table */
.quad 0x0000000000000000
.quad 0x00CF9A000000FFFF
.quad 0x00CF92000000FFFF
.quad 0x00009E000000FFFF
.quad 0x000092000000FFFF
.GdtPointer:
/* Pointer to Global Descriptor Table */
.word .GdtPointer - .GdtDescriptor - 1
.long .GdtDescriptor
.Stage2FileName:
/* Name of Stage 2 executable file */
.ascii "BOOTIA32EFI"

View File

@@ -4,6 +4,7 @@
* FILE: boot/bootsect/amd64/mbrboot.S
* DESCRIPTION: XT Boot Loader MBR boot code
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
* Aiken Harris <aiken@codingworkshop.eu.org>
*/
.text
@@ -41,7 +42,7 @@ RealStart:
movw %ax, %ss
/* Print welcome message */
leaw msgXtosBoot, %si
leaw .MsgXtosBoot, %si
call Print
/* Get BIOS boot drive and partition table offset */
@@ -90,19 +91,19 @@ PartitionFound:
InvalidSignature:
/* Invalid signature error */
leaw msgInvalidSignature, %si
leaw .MsgInvalidSignature, %si
call Print
jmp HaltSystem
PartitionNotFound:
/* Active partition not found error */
leaw msgPartitionNotFound, %si
leaw .MsgPartitionNotFound, %si
call Print
jmp HaltSystem
VbrReadFail:
/* VBR read failed error */
leaw msgVbrReadFail, %si
leaw .MsgVbrReadFail, %si
call Print
jmp HaltSystem
@@ -136,16 +137,16 @@ DonePrint:
/* Storage for the LBA start */
.long 0
msgInvalidSignature:
.MsgInvalidSignature:
.asciz "Invalid partition signature!"
msgPartitionNotFound:
.MsgPartitionNotFound:
.asciz "Bootable partition not found!"
msgVbrReadFail:
.MsgVbrReadFail:
.asciz "VBR read failed!"
msgXtosBoot:
.MsgXtosBoot:
.asciz "Starting XTOS boot loader...\r\n"
/* Fill the rest of the MBR with zeros and add MBR signature at the end */

View File

@@ -16,6 +16,7 @@ list(APPEND LIBXTLDR_SOURCE
# Specify list of source code files
list(APPEND XTLDR_SOURCE
${XTLDR_SOURCE_DIR}/arch/${ARCH}/memory.cc
${XTLDR_SOURCE_DIR}/biosutil.cc
${XTLDR_SOURCE_DIR}/bootutil.cc
${XTLDR_SOURCE_DIR}/config.cc
${XTLDR_SOURCE_DIR}/console.cc
@@ -38,6 +39,9 @@ add_executable(xtldr ${XTLDR_SOURCE})
# Add linker libraries
target_link_libraries(xtldr libxtos)
# Add linker options
target_link_options(xtldr PRIVATE /ALIGN:512)
# Set proper binary name and install target
if(ARCH STREQUAL "i686")
set(BINARY_NAME "bootia32")
@@ -49,5 +53,6 @@ set_install_target(xtldr efi/boot)
# Set loader entrypoint and subsystem
set_entrypoint(xtldr "BlStartXtLoader")
set_imagebase(xtldr ${BASEADDRESS_XTLDR})
set_linker_map(xtldr TRUE)
set_subsystem(xtldr efi_application)

190
boot/xtldr/biosutil.cc Normal file
View File

@@ -0,0 +1,190 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtldr/biosutil.cc
* DESCRIPTION: Legacy BIOS support
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtldr.hh>
/**
* Clears the entire screen and moves the cursor to the top-left corner.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
BiosUtils::ClearScreen()
{
VOLATILE PUSHORT VgaBuffer = (PUSHORT)0xB8000;
USHORT Blank;
UINT Index;
/* Set blank character */
Blank = (0x0F << 8) | L' ';
/* Fill the entire screen with blank characters */
for(Index = 0; Index < VgaWidth * VgaHeight; Index++)
{
VgaBuffer[Index] = Blank;
}
/* Reset cursor position to the top-left corner */
CursorX = 0;
CursorY = 0;
/* Update the hardware cursor position */
UpdateCursor();
}
/**
* Formats the input string and prints it out to the screen.
*
* @param Format
* The formatted string that is to be written to the output.
*
* @param ...
* Depending on the format string, this routine might expect a sequence of additional arguments.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
BiosUtils::Print(IN PCWSTR Format,
IN ...)
{
RTL_PRINT_CONTEXT PrintContext;
VA_LIST Arguments;
/* Initialise the print contexts */
PrintContext.WriteWideCharacter = PutChar;
/* Initialise the va_list */
VA_START(Arguments, Format);
/* Format and print the string to the stdout */
RTL::WideString::FormatWideString(&PrintContext, (PWCHAR)Format, Arguments);
/* Clean up the va_list */
VA_END(Arguments);
}
/**
* Writes a single wide character to the screen using legacy BIOS VGA text mode.
*
* @param Character
* The wide character to be printed.
*
* @return This routine returns a status code.
*
* @since XT 1.0
*/
XTCDECL
XTSTATUS
BiosUtils::PutChar(IN WCHAR Character)
{
VOLATILE PUSHORT VgaBuffer = (PUSHORT)0xB8000;
USHORT VgaCharacter;
/* Handle special characters */
if(Character == L'\n')
{
/* Move to the next line */
CursorX = 0;
CursorY++;
}
else if(Character == L'\r')
{
/* Move to the beginning of the current line */
CursorX = 0;
}
else
{
/* Print character and move cursor to the right */
VgaCharacter = (0x0F << 8) | (Character & 0xFF);
VgaBuffer[CursorY * VgaWidth + CursorX] = VgaCharacter;
CursorX++;
}
/* Handle moving to the next line if cursor is at the end of the line */
if(CursorX >= VgaWidth)
{
CursorX = 0;
CursorY++;
}
/* Handle scrolling if cursor is at the end of the screen */
if(CursorY >= VgaHeight)
{
ScrollScreen();
CursorY = VgaHeight - 1;
}
/* Update the hardware cursor position */
UpdateCursor();
/* Return success */
return STATUS_EFI_SUCCESS;
}
/**
* Scrolls the entire screen content up by one line and clears the last line.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
BiosUtils::ScrollScreen()
{
VOLATILE PUSHORT VgaBuffer = (PUSHORT)0xB8000;
USHORT Blank;
UINT Index;
/* Set blank character */
Blank = (0x0F << 8) | L' ';
/* Move every line up by one */
for(Index = 0; Index < (VgaHeight - 1) * VgaWidth; Index++)
{
VgaBuffer[Index] = VgaBuffer[Index + VgaWidth];
}
/* Clear the last line */
for(Index = (VgaHeight - 1) * VgaWidth; Index < VgaHeight * VgaWidth; Index++)
{
VgaBuffer[Index] = Blank;
}
}
/**
* Updates the hardware cursor position on the screen.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
BiosUtils::UpdateCursor()
{
USHORT Position;
/* Calculate cursor position */
Position = CursorY * VgaWidth + CursorX;
/* Send command to set the high byte of the cursor position */
HL::IoPort::WritePort8(0x3D4, 0x0E);
HL::IoPort::WritePort8(0x3D5, (UCHAR)((Position >> 8) & 0xFF));
/* Send command to set the low byte of the cursor position */
HL::IoPort::WritePort8(0x3D4, 0x0F);
HL::IoPort::WritePort8(0x3D5, (UCHAR)(Position & 0xFF));
}

View File

@@ -10,6 +10,18 @@
#include <xtldr.hh>
/* Legacy BIOS cursor X position */
USHORT BiosUtils::CursorX = 0;
/* Legacy BIOS cursor Y position */
USHORT BiosUtils::CursorY = 0;
/* Legacy BIOS screen height */
CONST USHORT BiosUtils::VgaHeight = 25;
/* Legacy BIOS screen width */
CONST USHORT BiosUtils::VgaWidth = 80;
/* XT Boot Loader menu list */
PLIST_ENTRY Configuration::BootMenuList = NULLPTR;

View File

@@ -15,6 +15,25 @@
#include <libxtos.hh>
class BiosUtils
{
private:
STATIC USHORT CursorX;
STATIC USHORT CursorY;
STATIC CONST USHORT VgaHeight;
STATIC CONST USHORT VgaWidth;
public:
STATIC XTCDECL VOID ClearScreen();
STATIC XTCDECL VOID Print(IN PCWSTR Format,
IN ...);
STATIC XTCDECL XTSTATUS PutChar(IN WCHAR Character);
private:
STATIC XTCDECL VOID ScrollScreen();
STATIC XTCDECL VOID UpdateCursor();
};
class BootUtils
{
public:

View File

@@ -59,9 +59,22 @@ EFI_STATUS
Xtos::EnablePaging(IN PXTBL_PAGE_MAPPING PageMap)
{
EFI_STATUS Status;
ULONG_PTR SelfMapAddress;
/* Initialize self map address */
if(PageMap->PageMapLevel == 3)
{
/* For PML3 (PAE) use PTE base address */
SelfMapAddress = MM_PTE_BASE;
}
else
{
/* For PML2 (PAE disabled) use legacy PDE base address */
SelfMapAddress = MM_PDE_LEGACY_BASE;
}
/* Build page map */
Status = XtLdrProtocol->Memory.BuildPageMap(PageMap, MM_PTE_BASE);
Status = XtLdrProtocol->Memory.BuildPageMap(PageMap, SelfMapAddress);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to build page map */

View File

@@ -236,6 +236,15 @@ BlStartXtLoader(IN EFI_HANDLE ImageHandle,
PWCHAR Modules;
EFI_STATUS Status;
/* Check if system is EFI-based and provided parameters are valid */
if(ImageHandle == NULLPTR || SystemTable == NULLPTR)
{
/* Invalid parameters, print error message using BIOS calls and hang */
BiosUtils::ClearScreen();
BiosUtils::Print(L"XTLDR requires EFI-based system!");
for(;;);
}
/* Initialize XTLDR and */
XtLoader::InitializeBootLoader(ImageHandle, SystemTable);

View File

@@ -4,48 +4,41 @@
# DESCRIPTION: Project configuration script for preparing the build environment
# DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
# Check XTchain
if (-not $env:XTCVER) {
Write-Host "XTChain not detected or corrupted!"
Write-Error "XTChain not detected or corrupted!"
exit 1
}
# Set target architecture
if ($env:TARGET) {
$ARCH = $env:TARGET
} else {
$ARCH = "amd64"
}
# Set target architecture defaulting to amd64
$ARCH = if ($env:TARGET) { $env:TARGET } else { "amd64" }
# Set target build type
if (-not $env:BUILD_TYPE) {
$env:BUILD_TYPE = "DEBUG"
}
# Set target build type defaulting to Debug
$env:BUILD_TYPE = if ($env:BUILD_TYPE -in @("Debug", "Release")) { $env:BUILD_TYPE } else { "Debug" }
# Set variables
$EXECTOS_SOURCE_DIR = (Get-Location).Path
$EXECTOS_BINARY_DIR = "build-$($ARCH)-$($env:BUILD_TYPE.ToLower())"
$EXECTOS_SOURCE_DIR = $PSScriptRoot
$EXECTOS_BINARY_DIR = Join-Path $EXECTOS_SOURCE_DIR "build-$ARCH-$($env:BUILD_TYPE.ToLower())"
# Create directories if needed
if ($EXECTOS_SOURCE_DIR -eq (Get-Location).Path) {
Write-Host "Creating directories in $EXECTOS_BINARY_DIR"
# Create build directory
if (-not (Test-Path $EXECTOS_BINARY_DIR)) {
Write-Host "Creating build directory: $EXECTOS_BINARY_DIR"
New-Item -ItemType Directory -Path $EXECTOS_BINARY_DIR -Force | Out-Null
Set-Location -Path $EXECTOS_BINARY_DIR
}
Set-Location $EXECTOS_BINARY_DIR
# Delete old cache
Remove-Item -Path "CMakeCache.txt" -ErrorAction SilentlyContinue
Remove-Item -Path "host-tools/CMakeCache.txt" -ErrorAction SilentlyContinue
Remove-Item "CMakeCache.txt", "host-tools/CMakeCache.txt" -ErrorAction SilentlyContinue
# Configure project using CMake
& cmake -G Ninja -DARCH:STRING=$($ARCH) -DBUILD_TYPE:STRING=$($env:BUILD_TYPE) $EXECTOS_SOURCE_DIR
& cmake -G Ninja "-DARCH:STRING=$ARCH" "-DBUILD_TYPE:STRING=$($env:BUILD_TYPE)" $EXECTOS_SOURCE_DIR
# Check if configuration succeeded
if ($LASTEXITCODE -ne 0) {
Write-Host "Configure script failed."
Write-Error "Configure script failed."
exit 1
} else {
"$($ARCH)" | Out-File -Encoding ASCII -NoNewline build.arch
Write-Host "Configure script completed. Enter '$EXECTOS_BINARY_DIR' directory and execute 'xbuild' to build ExectOS."
}
$ARCH | Out-File -Encoding ASCII -NoNewline "build.arch"
Write-Host "Configure completed. Run 'xbuild' to build ExectOS."

View File

@@ -1,2 +1,3 @@
# Set base addresses for all modules
set(BASEADDRESS_XTLDR 0x000000000000F800)
set(BASEADDRESS_XTOSKRNL 0x0000000140000000)

View File

@@ -1,2 +1,3 @@
# Set base addresses for all modules
set(BASEADDRESS_XTLDR 0x0000F800)
set(BASEADDRESS_XTOSKRNL 0x00400000)

View File

@@ -64,11 +64,17 @@ function(compile_bootsector NAME SOURCE BASEADDR ENTRYPOINT)
set(BINARY_NAME "${NAME}.bin")
set(OBJECT_NAME "${NAME}.obj")
get_directory_property(DEFS COMPILE_DEFINITIONS)
foreach(def ${DEFS})
list(APPEND ASM_DEFS "-D${def}")
endforeach()
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}
COMMAND ${CMAKE_ASM_COMPILER}
/nologo
--target=i386-none-elf
${ASM_DEFS}
-I${CMAKE_CURRENT_SOURCE_DIR}
/Fo${CMAKE_CURRENT_BINARY_DIR}/${OBJECT_NAME}
-c -- ${SOURCE}

View File

@@ -272,11 +272,18 @@ typedef struct _KIDTENTRY
{
USHORT OffsetLow;
USHORT Selector;
USHORT IstIndex:3;
USHORT Reserved0:5;
USHORT Type:5;
USHORT Dpl:2;
USHORT Present:1;
union
{
struct
{
USHORT IstIndex:3;
USHORT Reserved0:5;
USHORT Type:5;
USHORT Dpl:2;
USHORT Present:1;
};
USHORT Access;
};
USHORT OffsetMiddle;
ULONG OffsetHigh;
ULONG Reserved1;

View File

@@ -25,11 +25,11 @@
#define MM_PXE_BASE 0xFFFFF6FB7DBED000ULL
/* Page directory and page base addresses for 5-level paging */
#define MM_PTE_LA57_BASE 0xFFFF000000000000ULL
#define MM_PDE_LA57_BASE 0xFFFF010000000000ULL
#define MM_PPE_LA57_BASE 0xFFFF010800000000ULL
#define MM_PXE_LA57_BASE 0xFFFF010840000000ULL
#define MM_P5E_LA57_BASE 0xFFFF010840200000ULL
#define MM_PTE_LA57_BASE 0xFFED000000000000ULL
#define MM_PDE_LA57_BASE 0xFFEDF68000000000ULL
#define MM_PPE_LA57_BASE 0xFFEDF6FB40000000ULL
#define MM_PXE_LA57_BASE 0xFFEDF6FB7DA00000ULL
#define MM_P5E_LA57_BASE 0xFFEDF6FB7DBED000ULL
/* PTE shift values */
#define MM_PTE_SHIFT 3
@@ -39,15 +39,55 @@
#define MM_PXI_SHIFT 39
#define MM_P5I_SHIFT 48
/* Number of PTEs per page */
#define MM_PTE_PER_PAGE 512
#define MM_PDE_PER_PAGE 512
#define MM_PPE_PER_PAGE 512
#define MM_PXE_PER_PAGE 512
/* PTE state flags */
#define MM_PTE_VALID 0x0000000000000001ULL
#define MM_PTE_ACCESSED 0x0000000000000020ULL
#define MM_PTE_DIRTY 0x0000000000000040ULL
/* PTE scope flags */
#define MM_PTE_LARGE_PAGE 0x0000000000000080ULL
#define MM_PTE_GLOBAL 0x0000000000000100ULL
/* PTE access flags */
#define MM_PTE_NOACCESS 0x0000000000000000ULL
#define MM_PTE_READONLY 0x0000000000000000ULL
#define MM_PTE_EXECUTE 0x0000000000000000ULL
#define MM_PTE_EXECUTE_READ 0x0000000000000000ULL
#define MM_PTE_READWRITE 0x8000000000000002ULL
#define MM_PTE_WRITECOPY 0x8000000000000200ULL
#define MM_PTE_EXECUTE_READWRITE 0x0000000000000002ULL
#define MM_PTE_EXECUTE_WRITECOPY 0x0000000000000200ULL
/* PTE protection flags */
#define MM_PTE_NOEXECUTE 0x8000000000000000ULL
#define MM_PTE_PROTECT 0x8000000000000612ULL
/* PTE cache flags */
#define MM_PTE_CACHE_ENABLE 0x0000000000000000ULL
#define MM_PTE_CACHE_DISABLE 0x0000000000000010ULL
#define MM_PTE_CACHE_WRITECOMBINED 0x0000000000000010ULL
#define MM_PTE_CACHE_WRITETHROUGH 0x0000000000000008ULL
/* PTE software flags */
#define MM_PTE_COPY_ON_WRITE 0x0000000000000200ULL
#define MM_PTE_PROTOTYPE 0x0000000000000400ULL
#define MM_PTE_TRANSITION 0x0000000000000800ULL
/* PTE frame bits */
#define MM_PTE_FRAME_BITS 57
/* PTE protection bits */
#define MM_PTE_PROTECTION_BITS 5
/* Base address of the system page table */
#define MM_SYSTEM_PTE_BASE KSEG0_BASE
/* Minimum number of physical pages needed by the system */
#define MM_MINIMUM_PHYSICAL_PAGES 2048
/* Number of system PTEs */
#define MM_DEFAULT_NUMBER_SYSTEM_PTES 22000
/* Default number of secondary colors */
#define MM_DEFAULT_SECONDARY_COLORS 64
@@ -63,6 +103,9 @@
/* Maximum physical address used by HAL allocations */
#define MM_MAXIMUM_PHYSICAL_ADDRESS 0x00000000FFFFFFFFULL
/* Highest system address */
#define MM_HIGHEST_SYSTEM_ADDRESS 0xFFFFFFFFFFFFFFFFULL
/* Trampoline code address */
#define MM_TRAMPOLINE_ADDRESS 0x80000
@@ -99,6 +142,7 @@ typedef struct _HARDWARE_PTE
typedef struct _MMPAGEMAP_INFO
{
BOOLEAN Xpa;
ULONGLONG EmptyPteList;
ULONGLONG PteBase;
ULONGLONG PdeBase;
ULONGLONG PpeBase;
@@ -252,6 +296,7 @@ typedef struct _MMPFN
USHORT ReferenceCount;
} e2;
} u3;
ULONG UsedPageTableEntries;
union
{
MMPTE OriginalPte;
@@ -262,12 +307,11 @@ typedef struct _MMPFN
ULONG_PTR EntireFrame;
struct
{
ULONG_PTR PteFrame:58;
ULONG_PTR PteFrame:57;
ULONG_PTR InPageError:1;
ULONG_PTR VerifierAllocation:1;
ULONG_PTR AweAllocation:1;
ULONG_PTR LockCharged:1;
ULONG_PTR KernelStack:1;
ULONG_PTR Priority:3;
ULONG_PTR MustBeCached:1;
};
} u4;

View File

@@ -58,12 +58,6 @@
#define KIDT_ACCESS_RING0 0x00
#define KIDT_ACCESS_RING3 0x60
/* IDT gate types */
#define KIDT_TASK 0x05
#define KIDT_CALL 0x0C
#define KIDT_INTERRUPT 0x0E
#define KIDT_TRAP 0x0F
/* TSS Offsets */
#define KTSS_ESP0 0x04
#define KTSS_CR3 0x1C
@@ -284,7 +278,18 @@ typedef struct _KIDTENTRY
{
USHORT Offset;
USHORT Selector;
USHORT Access;
union
{
struct
{
UCHAR Reserved;
UCHAR Type:4;
UCHAR Flag:1;
UCHAR Dpl:2;
UCHAR Present:1;
};
USHORT Access;
};
USHORT ExtendedOffset;
} KIDTENTRY, *PKIDTENTRY;

View File

@@ -35,9 +35,57 @@
#define MM_PTE_LEGACY_SHIFT 2
#define MM_PDI_LEGACY_SHIFT 22
/* PTE state flags */
#define MM_PTE_VALID 0x00000001
#define MM_PTE_ACCESSED 0x00000020
#define MM_PTE_DIRTY 0x00000040
/* PTE scope flags */
#define MM_PTE_LARGE_PAGE 0x00000080
#define MM_PTE_GLOBAL 0x00000100
/* PTE access flags */
#define MM_PTE_NOACCESS 0x00000000
#define MM_PTE_READONLY 0x00000000
#define MM_PTE_EXECUTE 0x00000000
#define MM_PTE_EXECUTE_READ 0x00000000
#define MM_PTE_READWRITE 0x00000002
#define MM_PTE_WRITECOPY 0x00000200
#define MM_PTE_EXECUTE_READWRITE 0x00000002
#define MM_PTE_EXECUTE_WRITECOPY 0x00000200
/* PTE protection flags */
#define MM_PTE_NOEXECUTE 0x00000000
#define MM_PTE_PROTECT 0x00000612
/* PTE cache flags */
#define MM_PTE_CACHE_ENABLE 0x00000000
#define MM_PTE_CACHE_DISABLE 0x00000010
#define MM_PTE_CACHE_WRITECOMBINED 0x00000010
#define MM_PTE_CACHE_WRITETHROUGH 0x00000008
/* PTE software flags */
#define MM_PTE_COPY_ON_WRITE 0x00000200
#define MM_PTE_PROTOTYPE 0x00000400
#define MM_PTE_TRANSITION 0x00000800
/* PTE frame bits */
#define MM_PTE_FRAME_BITS 25
/* PTE protection bits */
#define MM_PTE_PROTECTION_BITS 5
/* Base address of the system page table */
#define MM_SYSTEM_PTE_BASE NULLPTR
/* Minimum number of physical pages needed by the system */
#define MM_MINIMUM_PHYSICAL_PAGES 1100
/* Number of system PTEs */
#define MM_MINIMUM_NUMBER_SYSTEM_PTES 7000
#define MM_DEFAULT_NUMBER_SYSTEM_PTES 11000
#define MM_MAXIMUM_NUMBER_SYSTEM_PTES 22000
/* Default number of secondary colors */
#define MM_DEFAULT_SECONDARY_COLORS 64
@@ -53,6 +101,9 @@
/* Maximum physical address used by HAL allocations */
#define MM_MAXIMUM_PHYSICAL_ADDRESS 0xFFFFFFFF
/* Highest system address */
#define MM_HIGHEST_SYSTEM_ADDRESS 0xFFFFFFFF
/* Trampoline code address */
#define MM_TRAMPOLINE_ADDRESS 0x80000
@@ -106,7 +157,6 @@ typedef struct _HARDWARE_MODERN_PTE
/* Generic Page Table entry union to abstract PML2 and PML3 formats */
typedef union _HARDWARE_PTE
{
ULONGLONG Long;
HARDWARE_LEGACY_PTE Pml2;
HARDWARE_MODERN_PTE Pml3;
} HARDWARE_PTE, *PHARDWARE_PTE;
@@ -115,6 +165,7 @@ typedef union _HARDWARE_PTE
typedef struct _MMPAGEMAP_INFO
{
BOOLEAN Xpa;
ULONG EmptyPteList;
ULONG PteBase;
ULONG PdeBase;
ULONG PdiShift;
@@ -201,12 +252,12 @@ typedef struct _MMPML2_PTE_TRANSITION
typedef union _MMPML2_PTE
{
ULONG Long;
HARDWARE_PTE Flush;
MMPML2_PTE_HARDWARE Hard;
MMPML2_PTE_PROTOTYPE Proto;
MMPML2_PTE_SOFTWARE Soft;
MMPML2_PTE_TRANSITION Trans;
MMPML2_PTE_SUBSECTION Subsect;
HARDWARE_LEGACY_PTE Flush;
MMPML2_PTE_HARDWARE Hardware;
MMPML2_PTE_PROTOTYPE Prototype;
MMPML2_PTE_SOFTWARE Software;
MMPML2_PTE_TRANSITION Transition;
MMPML2_PTE_SUBSECTION Subsection;
MMPML2_PTE_LIST List;
} MMPML2_PTE, *PMMPML2_PTE;
@@ -296,7 +347,7 @@ typedef struct _MMPML3_PTE_TRANSITION
typedef union _MMPML3_PTE
{
ULONGLONG Long;
HARDWARE_PTE Flush;
HARDWARE_MODERN_PTE Flush;
MMPML3_PTE_HARDWARE Hardware;
MMPML3_PTE_PROTOTYPE Prototype;
MMPML3_PTE_SOFTWARE Software;
@@ -308,7 +359,6 @@ typedef union _MMPML3_PTE
/* Generic Page Table Entry union to abstract PML2 and PML3 formats */
typedef union _MMPTE
{
ULONGLONG Long;
MMPML2_PTE Pml2;
MMPML3_PTE Pml3;
} MMPTE, *PMMPTE;
@@ -339,6 +389,7 @@ typedef struct _MMPFN
USHORT ReferenceCount;
} e2;
} u3;
ULONG UsedPageTableEntries;
union
{
MMPTE OriginalPte;
@@ -349,12 +400,11 @@ typedef struct _MMPFN
ULONG_PTR EntireFrame;
struct
{
ULONG_PTR PteFrame:26;
ULONG_PTR PteFrame:25;
ULONG_PTR InPageError:1;
ULONG_PTR VerifierAllocation:1;
ULONG_PTR AweAllocation:1;
ULONG_PTR LockCharged:1;
ULONG_PTR KernelStack:1;
ULONG_PTR Priority:3;
ULONG_PTR MustBeCached:1;
};
} u4;

View File

@@ -150,21 +150,23 @@ typedef enum _KTHREAD_STATE
typedef enum _KSPIN_LOCK_QUEUE_LEVEL
{
DispatcherLock,
UnusedSpareLock,
ExpansionLock,
PfnLock,
SystemSpaceLock,
VacbLock,
MasterLock,
NonPagedPoolLock,
NonPagedAllocPoolLock,
IoCancelLock,
WorkQueueLock,
IoVpbLock,
IoDatabaseLock,
IoCompletionLock,
FsStructLock,
FileSystemLock,
AfdWorkQueueLock,
BcbLock,
MmNonPagedPoolLock,
NonPagedPoolLock,
ReservedSystemLock,
TimerTableLock,
MaximumLock
} KSPIN_LOCK_QUEUE_LEVEL, *PKSPIN_LOCK_QUEUE_LEVEL;

View File

@@ -4,6 +4,7 @@
* FILE: sdk/xtdk/mmtypes.h
* DESCRIPTION: Memory management data structures
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
* Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTDK_MMTYPES_H
@@ -13,6 +14,48 @@
#include ARCH_HEADER(xtstruct.h)
/* Number of hyper space pages */
#define MM_HYPERSPACE_PAGE_COUNT 255
/* Number of paging colors */
#define MM_PAGING_COLORS 64
/* PTE frame mask definition */
#define MM_PFN_PTE_FRAME (((ULONG_PTR)1 << MM_PTE_FRAME_BITS) - 1)
/* Number of reserved zeroed PTEs */
#define MM_RESERVED_ZERO_PTES 32
/* Memory manager page lists */
typedef enum _MMPAGELISTS
{
ZeroedPageList = 0,
FreePageList = 1,
StandbyPageList = 2,
ModifiedPageList = 3,
ModifiedReadOnlyPageList = 4,
BadPageList = 5,
ActiveAndValid = 6,
TransitionPage = 7
} MMPAGELISTS, *PMMPAGELISTS;
/* Page cache attributes */
typedef enum _MMPFN_CACHE_ATTRIBUTE
{
PfnNonCached,
PfnCached,
PfnWriteCombined,
PfnNotMapped
} MMPFN_CACHE_ATTRIBUTE, *PMMPFN_CACHE_ATTRIBUTE;
/* Page table pool types */
typedef enum _MMSYSTEM_PTE_POOL_TYPE
{
SystemPteSpace,
NonPagedPoolExpansion,
MaximumPtePoolTypes
} MMSYSTEM_PTE_POOL_TYPE, *PMMSYSTEM_PTE_POOL_TYPE;
/* Page map routines structure definition */
typedef CONST STRUCT _CMMPAGEMAP_ROUTINES
{
@@ -30,6 +73,22 @@ typedef struct _MMCOLOR_TABLES
ULONG_PTR Count;
} MMCOLOR_TABLES, *PMMCOLOR_TABLES;
/* Memory layout structure definition */
typedef struct _MMMEMORY_LAYOUT
{
PMMPFN PfnDatabaseAddress;
PVOID SelfMapAddress;
PVOID HyperSpaceStart;
PVOID HyperSpaceEnd;
PVOID NonPagedPoolStart;
PVOID NonPagedPoolEnd;
PVOID PagedPoolStart;
PVOID PagedPoolEnd;
PVOID SystemSpaceStart;
PVOID SystemSpaceEnd;
PVOID UserSpaceEnd;
} MMMEMORY_LAYOUT, *PMMMEMORY_LAYOUT;
/* Page Frame Entry structure definition */
typedef struct _MMPFNENTRY
{
@@ -45,4 +104,13 @@ typedef struct _MMPFNENTRY
USHORT ParityError:1;
} MMPFNENTRY, *PMMPFNENTRY;
/* Page Frame List structure definition */
typedef struct _MMPFNLIST
{
PFN_NUMBER Total;
MMPAGELISTS ListName;
PFN_NUMBER Flink;
PFN_NUMBER Blink;
} MMPFNLIST, *PMMPFNLIST;
#endif /* __XTDK_MMTYPES_H */

View File

@@ -29,6 +29,9 @@ typedef UCHAR KRUNLEVEL, *PKRUNLEVEL;
/* Spin locks synchronization mechanism */
typedef ULONG_PTR KSPIN_LOCK, *PKSPIN_LOCK;
/* Page Frame Number count */
typedef ULONG PFN_COUNT;
/* Page Frame Number */
typedef ULONG_PTR PFN_NUMBER, *PPFN_NUMBER;

View File

@@ -12,8 +12,9 @@
#ifdef __cplusplus
/* C++ definitions */
#define XTCLINK extern "C"
#define NULLPTR nullptr
#define VIRTUAL virtual
#define XTCLINK extern "C"
/* C++ boolean type */
typedef bool BOOLEAN, *PBOOLEAN;
@@ -24,8 +25,9 @@
typedef wchar_t wchar;
#else
/* C definitions */
#define XTCLINK
#define NULLPTR ((void *)0)
#define VIRTUAL
#define XTCLINK
/* C boolean type */
typedef enum _BOOLEAN

View File

@@ -48,6 +48,9 @@ typedef enum _KTHREAD_STATE KTHREAD_STATE, *PKTHREAD_STATE;
typedef enum _KTIMER_TYPE KTIMER_TYPE, *PKTIMER_TYPE;
typedef enum _KUBSAN_DATA_TYPE KUBSAN_DATA_TYPE, *PKUBSAN_DATA_TYPE;
typedef enum _LOADER_MEMORY_TYPE LOADER_MEMORY_TYPE, *PLOADER_MEMORY_TYPE;
typedef enum _MMPAGELISTS MMPAGELISTS, *PMMPAGELISTS;
typedef enum _MMPFN_CACHE_ATTRIBUTE MMPFN_CACHE_ATTRIBUTE, *PMMPFN_CACHE_ATTRIBUTE;
typedef enum _MMSYSTEM_PTE_POOL_TYPE MMSYSTEM_PTE_POOL_TYPE, *PMMSYSTEM_PTE_POOL_TYPE;
typedef enum _MODE MODE, *PMODE;
typedef enum _RTL_VARIABLE_TYPE RTL_VARIABLE_TYPE, *PRTL_VARIABLE_TYPE;
typedef enum _SYSTEM_FIRMWARE_TYPE SYSTEM_FIRMWARE_TYPE, *PSYSTEM_FIRMWARE_TYPE;
@@ -274,7 +277,9 @@ typedef struct _LOADER_INFORMATION_BLOCK LOADER_INFORMATION_BLOCK, *PLOADER_INFO
typedef struct _LOADER_MEMORY_DESCRIPTOR LOADER_MEMORY_DESCRIPTOR, *PLOADER_MEMORY_DESCRIPTOR;
typedef struct _M128 M128, *PM128;
typedef struct _MMCOLOR_TABLES MMCOLOR_TABLES, *PMMCOLOR_TABLES;
typedef struct _MMMEMORY_LAYOUT MMMEMORY_LAYOUT, *PMMMEMORY_LAYOUT;
typedef struct _MMPFNENTRY MMPFNENTRY, *PMMPFNENTRY;
typedef struct _MMPFNLIST MMPFNLIST, *PMMPFNLIST;
typedef struct _PCAT_FIRMWARE_INFORMATION PCAT_FIRMWARE_INFORMATION, *PPCAT_FIRMWARE_INFORMATION;
typedef struct _PCI_BRIDGE_CONTROL_REGISTER PCI_BRIDGE_CONTROL_REGISTER, *PPCI_BRIDGE_CONTROL_REGISTER;
typedef struct _PCI_COMMON_CONFIG PCI_COMMON_CONFIG, *PPCI_COMMON_CONFIG;

View File

@@ -51,14 +51,18 @@ list(APPEND XTOSKRNL_SOURCE
${XTOSKRNL_SOURCE_DIR}/ke/spinlock.cc
${XTOSKRNL_SOURCE_DIR}/ke/sysres.cc
${XTOSKRNL_SOURCE_DIR}/ke/timer.cc
${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/init.cc
${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/mmgr.cc
${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pagemap.cc
${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/paging.cc
${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/pte.cc
${XTOSKRNL_SOURCE_DIR}/mm/colors.cc
${XTOSKRNL_SOURCE_DIR}/mm/data.cc
${XTOSKRNL_SOURCE_DIR}/mm/hlpool.cc
${XTOSKRNL_SOURCE_DIR}/mm/init.cc
${XTOSKRNL_SOURCE_DIR}/mm/kpool.cc
${XTOSKRNL_SOURCE_DIR}/mm/mmgr.cc
${XTOSKRNL_SOURCE_DIR}/mm/paging.cc
${XTOSKRNL_SOURCE_DIR}/mm/pfn.cc
${XTOSKRNL_SOURCE_DIR}/mm/pte.cc
${XTOSKRNL_SOURCE_DIR}/po/idle.cc
${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/dispatch.cc
${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/exsup.cc
@@ -82,11 +86,12 @@ add_library(libxtos ${XTOSKRNL_SOURCE})
# Link kernel executable
add_executable(xtoskrnl
${XTOSKRNL_SOURCE}
${CMAKE_CURRENT_BINARY_DIR}/xtoskrnl.def)
# Add linker libraries
target_link_libraries(xtoskrnl)
target_link_libraries(xtoskrnl
PRIVATE
libxtos)
# Set proper binary name and install target
set_target_properties(xtoskrnl PROPERTIES SUFFIX .exe)

View File

@@ -4,6 +4,18 @@ within the XTOS kernel space. It is responsible for various core services, such
management, and process scheduling. The kernel contains the scheduler (sometimes referred to as the Dispatcher), the
cache, object, and memory managers, the security manager, and other executive components described below.
## Kernel Parameters
Kernel parameters are XTOS boot-time options used to ensure proper initialization and handling of hardware peripherals.
These parameters can be configured either temporarily by editing the boot entry in the bootloaders selection menu, or
permanently by modifying the XTLDR configuration file.
The following is a consolidated list of available kernel parameters:
* **NOXPA**: Disables PAE or LA57 support, depending on the CPU architecture. This parameter is handled by the
bootloader, which configures paging and selects the appropriate Page Map Level (PML) before transferring control to
the kernel.
## Source Code
The source code of the kernel is organized into subsystem-specific directories. Each directory name also defines the
corresponding C++ namespace in which the subsystem's classes and routines reside. These subsystems include:
@@ -68,8 +80,8 @@ routine:
For all C++ code inside the kernel the naming model has evolved. Consider the **KE::KThread::InitializeThread()**
routine:
* **KE** - The namespace replaces the prefix and indicates the subsystem. Namespaces are written in uppercase and no
longer use the trailing p for private routines, because classes use C++ visibility to control access.
longer use the trailing p for private routines, because classes use C++ visibility to control access.
* **KThread** - Within each namespace, related functionality is grouped into classes, which encapsulate variables and
methods.
methods.
* **InitializeThread** - Method names follow the `<Operation><Object>` pattern.

View File

@@ -249,34 +249,34 @@ AR::ProcSup::InitializeIdt(IN PKPROCESSOR_BLOCK ProcessorBlock)
for(Vector = 0; Vector < IDT_ENTRIES; Vector++)
{
/* Set the IDT to handle unexpected interrupts */
SetIdtGate(ProcessorBlock->IdtBase, Vector, (PVOID)ArTrap0xFF, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, Vector, (PVOID)ArTrap0xFF, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
}
/* Setup IDT handlers for known interrupts and traps */
SetIdtGate(ProcessorBlock->IdtBase, 0x00, (PVOID)ArTrap0x00, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x01, (PVOID)ArTrap0x01, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x02, (PVOID)ArTrap0x02, KGDT_R0_CODE, KIDT_IST_PANIC, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x03, (PVOID)ArTrap0x03, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3);
SetIdtGate(ProcessorBlock->IdtBase, 0x04, (PVOID)ArTrap0x04, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3);
SetIdtGate(ProcessorBlock->IdtBase, 0x05, (PVOID)ArTrap0x05, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x06, (PVOID)ArTrap0x06, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x07, (PVOID)ArTrap0x07, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x08, (PVOID)ArTrap0x08, KGDT_R0_CODE, KIDT_IST_PANIC, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x09, (PVOID)ArTrap0x09, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x0A, (PVOID)ArTrap0x0A, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x0B, (PVOID)ArTrap0x0B, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x0C, (PVOID)ArTrap0x0C, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x0D, (PVOID)ArTrap0x0D, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x0E, (PVOID)ArTrap0x0E, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x10, (PVOID)ArTrap0x10, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x11, (PVOID)ArTrap0x11, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x12, (PVOID)ArTrap0x12, KGDT_R0_CODE, KIDT_IST_MCA, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x13, (PVOID)ArTrap0x13, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x1F, (PVOID)ArTrap0x1F, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x2C, (PVOID)ArTrap0x2C, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3);
SetIdtGate(ProcessorBlock->IdtBase, 0x2D, (PVOID)ArTrap0x2D, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3);
SetIdtGate(ProcessorBlock->IdtBase, 0x2F, (PVOID)ArTrap0x2F, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0xE1, (PVOID)ArTrap0xE1, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x00, (PVOID)ArTrap0x00, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x01, (PVOID)ArTrap0x01, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x02, (PVOID)ArTrap0x02, KGDT_R0_CODE, KIDT_IST_PANIC, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x03, (PVOID)ArTrap0x03, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x04, (PVOID)ArTrap0x04, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x05, (PVOID)ArTrap0x05, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x06, (PVOID)ArTrap0x06, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x07, (PVOID)ArTrap0x07, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x08, (PVOID)ArTrap0x08, KGDT_R0_CODE, KIDT_IST_PANIC, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x09, (PVOID)ArTrap0x09, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0A, (PVOID)ArTrap0x0A, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0B, (PVOID)ArTrap0x0B, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0C, (PVOID)ArTrap0x0C, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0D, (PVOID)ArTrap0x0D, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0E, (PVOID)ArTrap0x0E, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x10, (PVOID)ArTrap0x10, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x11, (PVOID)ArTrap0x11, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x12, (PVOID)ArTrap0x12, KGDT_R0_CODE, KIDT_IST_MCA, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x13, (PVOID)ArTrap0x13, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x1F, (PVOID)ArTrap0x1F, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x2C, (PVOID)ArTrap0x2C, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x2D, (PVOID)ArTrap0x2D, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x2F, (PVOID)ArTrap0x2F, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0xE1, (PVOID)ArTrap0xE1, KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
}
/**
@@ -636,6 +636,9 @@ AR::ProcSup::SetGdtEntryBase(IN PKGDTENTRY Gdt,
* @param Access
* Supplies the gate access rights.
*
* @param Type
* Supplies the gate type.
*
* @return This routine does not return any value.
*
* @since XT 1.0
@@ -647,15 +650,22 @@ AR::ProcSup::SetIdtGate(IN PKIDTENTRY Idt,
IN PVOID Handler,
IN USHORT Selector,
IN USHORT Ist,
IN USHORT Access)
IN USHORT Dpl,
IN USHORT Type)
{
/* Setup the gate */
/* Set the handler's address */
Idt[Vector].OffsetLow = ((ULONG_PTR)Handler & 0xFFFF);
Idt[Vector].OffsetMiddle = (((ULONG_PTR)Handler >> 16) & 0xFFFF);
Idt[Vector].OffsetHigh = (ULONG_PTR)Handler >> 32;
Idt[Vector].Dpl = Access;
/* Set the code segment selector */
Idt[Vector].Selector = Selector;
/* Initialize the gate's attributes and flags */
Idt[Vector].Access = 0;
Idt[Vector].Dpl = Dpl;
Idt[Vector].IstIndex = Ist;
Idt[Vector].Present = 1;
Idt[Vector].Selector = Selector;
Idt[Vector].Type = 0xE;
Idt[Vector].Reserved1 = 0;
Idt[Vector].Type = Type;
}

View File

@@ -242,34 +242,34 @@ AR::ProcSup::InitializeIdt(IN PKPROCESSOR_BLOCK ProcessorBlock)
for(Vector = 0; Vector < IDT_ENTRIES; Vector++)
{
/* Set the IDT to handle unexpected interrupts */
SetIdtGate(ProcessorBlock->IdtBase, Vector, (PVOID)ArTrap0xFF, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, Vector, (PVOID)ArTrap0xFF, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE);
}
/* Setup IDT handlers for known interrupts and traps */
SetIdtGate(ProcessorBlock->IdtBase, 0x00, (PVOID)ArTrap0x00, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x01, (PVOID)ArTrap0x01, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x02, (PVOID)ArTrap0x02, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x03, (PVOID)ArTrap0x03, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING3);
SetIdtGate(ProcessorBlock->IdtBase, 0x04, (PVOID)ArTrap0x04, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING3);
SetIdtGate(ProcessorBlock->IdtBase, 0x05, (PVOID)ArTrap0x05, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x06, (PVOID)ArTrap0x06, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x07, (PVOID)ArTrap0x07, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x08, (PVOID)ArTrap0x08, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x09, (PVOID)ArTrap0x09, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x0A, (PVOID)ArTrap0x0A, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x0B, (PVOID)ArTrap0x0B, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x0C, (PVOID)ArTrap0x0C, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x0D, (PVOID)ArTrap0x0D, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x0E, (PVOID)ArTrap0x0E, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x10, (PVOID)ArTrap0x10, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x11, (PVOID)ArTrap0x11, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x12, (PVOID)ArTrap0x12, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x13, (PVOID)ArTrap0x13, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING0);
SetIdtGate(ProcessorBlock->IdtBase, 0x2A, (PVOID)ArTrap0x2A, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING3);
SetIdtGate(ProcessorBlock->IdtBase, 0x2B, (PVOID)ArTrap0x2B, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING3);
SetIdtGate(ProcessorBlock->IdtBase, 0x2C, (PVOID)ArTrap0x2C, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING3);
SetIdtGate(ProcessorBlock->IdtBase, 0x2D, (PVOID)ArTrap0x2D, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING3);
SetIdtGate(ProcessorBlock->IdtBase, 0x2E, (PVOID)ArTrap0x2E, KGDT_R0_CODE, 0, KIDT_INTERRUPT | KIDT_ACCESS_RING3);
SetIdtGate(ProcessorBlock->IdtBase, 0x00, (PVOID)ArTrap0x00, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x01, (PVOID)ArTrap0x01, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x02, (PVOID)ArTrap0x02, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x03, (PVOID)ArTrap0x03, KGDT_R0_CODE, 0, KIDT_ACCESS_RING3, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x04, (PVOID)ArTrap0x04, KGDT_R0_CODE, 0, KIDT_ACCESS_RING3, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x05, (PVOID)ArTrap0x05, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x06, (PVOID)ArTrap0x06, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x07, (PVOID)ArTrap0x07, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x08, (PVOID)ArTrap0x08, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x09, (PVOID)ArTrap0x09, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0A, (PVOID)ArTrap0x0A, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0B, (PVOID)ArTrap0x0B, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0C, (PVOID)ArTrap0x0C, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0D, (PVOID)ArTrap0x0D, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0E, (PVOID)ArTrap0x0E, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x10, (PVOID)ArTrap0x10, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x11, (PVOID)ArTrap0x11, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x12, (PVOID)ArTrap0x12, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x13, (PVOID)ArTrap0x13, KGDT_R0_CODE, 0, KIDT_ACCESS_RING0, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x2A, (PVOID)ArTrap0x2A, KGDT_R0_CODE, 0, KIDT_ACCESS_RING3, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x2B, (PVOID)ArTrap0x2B, KGDT_R0_CODE, 0, KIDT_ACCESS_RING3, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x2C, (PVOID)ArTrap0x2C, KGDT_R0_CODE, 0, KIDT_ACCESS_RING3, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x2D, (PVOID)ArTrap0x2D, KGDT_R0_CODE, 0, KIDT_ACCESS_RING3, I686_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x2E, (PVOID)ArTrap0x2E, KGDT_R0_CODE, 0, KIDT_ACCESS_RING3, I686_TRAP_GATE);
}
/**
@@ -656,6 +656,9 @@ AR::ProcSup::SetGdtEntryBase(IN PKGDTENTRY Gdt,
* @param Access
* Supplies the gate access rights.
*
* @param Type
* Supplies the gate type.
*
* @return This routine does not return any value.
*
* @since XT 1.0
@@ -667,13 +670,21 @@ AR::ProcSup::SetIdtGate(IN PKIDTENTRY Idt,
IN PVOID Handler,
IN USHORT Selector,
IN USHORT Ist,
IN USHORT Access)
IN USHORT Dpl,
IN USHORT Type)
{
/* Setup the gate */
/* Set the handler's address */
Idt[Vector].Offset = (USHORT)((ULONG)Handler & 0xFFFF);
Idt[Vector].ExtendedOffset = (USHORT)((ULONG)Handler >> 16);
Idt[Vector].Access = 0x8000 | (Access << 8);
/* Set the code segment selector */
Idt[Vector].Selector = Selector;
/* Initialize the gate's attributes and flags */
Idt[Vector].Access = 0;
Idt[Vector].Dpl = Dpl;
Idt[Vector].Present = 1;
Idt[Vector].Type = Type;
}
/**

View File

@@ -67,7 +67,8 @@ namespace AR
IN PVOID Handler,
IN USHORT Selector,
IN USHORT Ist,
IN USHORT Access);
IN USHORT Dpl,
IN USHORT Type);
};
}

View File

@@ -72,7 +72,8 @@ namespace AR
IN PVOID Handler,
IN USHORT Selector,
IN USHORT Ist,
IN USHORT Access);
IN USHORT Dpl,
IN USHORT Type);
STATIC XTAPI VOID SetNonMaskableInterruptTssEntry(IN PKPROCESSOR_BLOCK ProcessorBlock,
IN PVOID KernelFaultStack);

View File

@@ -22,6 +22,48 @@ namespace KE
STATIC XTFASTCALL VOID LowerRunLevel(IN KRUNLEVEL RunLevel);
STATIC XTFASTCALL KRUNLEVEL RaiseRunLevel(IN KRUNLEVEL RunLevel);
};
class LowerRunLevel
{
private:
KRUNLEVEL PreviousRunLevel;
public:
LowerRunLevel(KRUNLEVEL RunLevel)
{
PreviousRunLevel = KE::RunLevel::GetCurrentRunLevel();
KE::RunLevel::LowerRunLevel(RunLevel);
}
~LowerRunLevel()
{
KE::RunLevel::RaiseRunLevel(PreviousRunLevel);
}
LowerRunLevel(const LowerRunLevel&) = delete;
LowerRunLevel& operator=(const LowerRunLevel&) = delete;
};
class RaiseRunLevel
{
private:
KRUNLEVEL PreviousRunLevel;
public:
RaiseRunLevel(KRUNLEVEL RunLevel)
{
PreviousRunLevel = KE::RunLevel::GetCurrentRunLevel();
KE::RunLevel::RaiseRunLevel(RunLevel);
}
~RaiseRunLevel()
{
KE::RunLevel::LowerRunLevel(PreviousRunLevel);
}
RaiseRunLevel(const RaiseRunLevel&) = delete;
RaiseRunLevel& operator=(const RaiseRunLevel&) = delete;
};
}
#endif /* __XTOSKRNL_KE_RUNLEVEL_HH */

View File

@@ -17,12 +17,73 @@ namespace KE
{
class SpinLock
{
private:
STATIC KSPIN_LOCK DispatcherLockQueue;
STATIC KSPIN_LOCK ExpansionLockQueue;
STATIC KSPIN_LOCK FileSystemLockQueue;
STATIC KSPIN_LOCK IoCancelLockQueue;
STATIC KSPIN_LOCK IoCompletionLockQueue;
STATIC KSPIN_LOCK IoDatabaseLockQueue;
STATIC KSPIN_LOCK IoVpbLockQueue;
STATIC KSPIN_LOCK MasterLockQueue;
STATIC KSPIN_LOCK NonPagedAllocLockQueue;
STATIC KSPIN_LOCK NonPagedPoolLockQueue;
STATIC KSPIN_LOCK PfnLockQueue;
STATIC KSPIN_LOCK SystemSpaceLockQueue;
STATIC KSPIN_LOCK TimerTableLockQueue;
STATIC KSPIN_LOCK VacbLockQueue;
STATIC KSPIN_LOCK WorkLockQueue;
public:
STATIC XTFASTCALL VOID AcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_LEVEL LockLevel);
STATIC XTFASTCALL VOID AcquireSpinLock(IN OUT PKSPIN_LOCK SpinLock);
STATIC XTAPI VOID InitializeAllLocks();
STATIC XTAPI VOID InitializeLockQueues();
STATIC XTAPI VOID InitializeSpinLock(IN PKSPIN_LOCK SpinLock);
STATIC XTFASTCALL VOID ReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_LEVEL LockLevel);
STATIC XTFASTCALL VOID ReleaseSpinLock(IN OUT PKSPIN_LOCK SpinLock);
STATIC XTFASTCALL BOOLEAN TestSpinLock(IN PKSPIN_LOCK SpinLock);
};
class QueuedSpinLockGuard
{
private:
KSPIN_LOCK_QUEUE_LEVEL QueuedLockLevel;
public:
QueuedSpinLockGuard(IN OUT KSPIN_LOCK_QUEUE_LEVEL LockLevel)
{
QueuedLockLevel = LockLevel;
KE::SpinLock::AcquireQueuedSpinLock(QueuedLockLevel);
}
~QueuedSpinLockGuard()
{
KE::SpinLock::ReleaseQueuedSpinLock(QueuedLockLevel);
}
QueuedSpinLockGuard(const QueuedSpinLockGuard&) = delete;
QueuedSpinLockGuard& operator=(const QueuedSpinLockGuard&) = delete;
};
class SpinLockGuard
{
private:
PKSPIN_LOCK SpinLock;
public:
SpinLockGuard(IN OUT PKSPIN_LOCK SpinLock)
{
KE::SpinLock::AcquireSpinLock(SpinLock);
}
~SpinLockGuard()
{
KE::SpinLock::ReleaseSpinLock(SpinLock);
}
SpinLockGuard(const SpinLockGuard&) = delete;
SpinLockGuard& operator=(const SpinLockGuard&) = delete;
};
}

View File

@@ -12,10 +12,13 @@
#include <xtos.hh>
#include XTOS_ARCH_HEADER(mm, pagemap.hh)
#include XTOS_ARCH_HEADER(mm, paging.hh)
#include XTOS_ARCH_HEADER(mm, pte.hh)
#include <mm/colors.hh>
#include <mm/hlpool.hh>
#include <mm/init.hh>
#include <mm/kpool.hh>
#include <mm/paging.hh>
#include <mm/mmgr.hh>
#include <mm/pfn.hh>
#endif /* __XTOSKRNL_MM_HH */

View File

@@ -1,13 +1,13 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/mm/pagemap.hh
* FILE: xtoskrnl/includes/mm/amd64/pagemap.hh
* DESCRIPTION: Low-level support for page map manipulation
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_MM_PAGEMAP_HH
#define __XTOSKRNL_MM_PAGEMAP_HH
#ifndef __XTOSKRNL_MM_AMD64_PAGEMAP_HH
#define __XTOSKRNL_MM_AMD64_PAGEMAP_HH
#include <xtos.hh>
@@ -21,33 +21,71 @@ namespace MM
MMPAGEMAP_INFO PageMapInfo;
public:
XTAPI VOID ClearPte(PHARDWARE_PTE PtePointer);
XTAPI PMMP5E GetP5eAddress(PVOID Address);
XTAPI PMMPDE GetPdeAddress(PVOID Address);
XTAPI PMMPPE GetPpeAddress(PVOID Address);
XTAPI PMMPTE GetPteAddress(PVOID Address);
XTAPI PMMPXE GetPxeAddress(PVOID Address);
virtual XTAPI VOID InitializePageMapInfo(VOID) = 0;
XTAPI BOOLEAN PteValid(PHARDWARE_PTE PtePointer);
XTAPI VOID SetPte(PHARDWARE_PTE PtePointer,
PFN_NUMBER PageFrameNumber,
BOOLEAN Writable);
XTAPI VOID SetPteCaching(PHARDWARE_PTE PtePointer,
BOOLEAN CacheDisable,
BOOLEAN WriteThrough);
XTAPI PMMPTE AdvancePte(IN PMMPTE Pte,
IN LONG Count);
XTAPI VOID ClearPte(IN PMMPTE PtePointer);
XTAPI ULONGLONG GetEmptyPteList(VOID);
XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte);
XTAPI PMMPTE GetNextPte(IN PMMPTE Pte);
XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte);
XTAPI PMMP5E GetP5eAddress(IN PVOID Address);
XTAPI ULONG GetP5eOffset(IN PVOID Address);
XTAPI PVOID GetP5eVirtualAddress(IN PMMP5E P5ePointer);
XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte);
XTAPI PMMPDE GetPdeAddress(IN PVOID Address);
XTAPI ULONG GetPdeOffset(IN PVOID Address);
VIRTUAL XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer) = 0;
XTAPI PMMPPE GetPpeAddress(IN PVOID Address);
XTAPI ULONG GetPpeOffset(IN PVOID Address);
VIRTUAL XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer) = 0;
XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer);
XTAPI PMMPTE GetPteAddress(IN PVOID Address);
XTAPI LONG GetPteDistance(PMMPTE EndPte,
PMMPTE StartPte);
XTAPI ULONG GetPteOffset(IN PVOID Address);
XTAPI ULONG GetPteSize(VOID);
VIRTUAL XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer) = 0;
XTAPI PMMPXE GetPxeAddress(IN PVOID Address);
XTAPI ULONG GetPxeOffset(IN PVOID Address);
VIRTUAL XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer) = 0;
XTAPI BOOLEAN GetXpaStatus();
VIRTUAL XTAPI VOID InitializePageMapInfo(VOID) = 0;
XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer);
XTAPI VOID SetNextEntry(IN PMMPTE Pte,
IN ULONG_PTR Value);
XTAPI VOID SetOneEntry(IN PMMPTE Pte,
IN BOOLEAN Value);
XTAPI VOID SetPte(IN PMMPTE PtePointer,
IN PFN_NUMBER PageFrameNumber,
IN ULONG_PTR AttributesMask);
XTAPI VOID SetPte(IN PMMPTE PtePointer,
IN ULONG_PTR Attributes);
XTAPI VOID SetPteCaching(IN PMMPTE PtePointer,
IN BOOLEAN CacheDisable,
IN BOOLEAN WriteThrough);
XTAPI VOID WritePte(IN PMMPTE Pte,
IN MMPTE Value);
} PAGEMAP, *PPAGEMAP;
class PageMapBasic final : public PageMap
{
public:
XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer);
XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer);
XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer);
XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer);
XTAPI VOID InitializePageMapInfo(VOID);
};
class PageMapXpa final : public PageMap
{
public:
XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer);
XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer);
XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer);
XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer);
XTAPI VOID InitializePageMapInfo(VOID);
};
}
#endif /* __XTOSKRNL_MM_PAGEMAP_HH */
#endif /* __XTOSKRNL_MM_AMD64_PAGEMAP_HH */

View File

@@ -0,0 +1,74 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/mm/amd64/paging.hh
* DESCRIPTION: Low level page management support for AMD64
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_MM_AMD64_PAGING_HH
#define __XTOSKRNL_MM_AMD64_PAGING_HH
#include <xtos.hh>
/* Memory Manager */
namespace MM
{
class Paging
{
private:
STATIC PPAGEMAP PmlRoutines;
public:
STATIC XTAPI PMMPTE AdvancePte(IN PMMPTE Pte,
IN LONG Count);
STATIC XTAPI VOID ClearPte(IN PMMPTE PtePointer);
STATIC XTAPI VOID FlushTlb(VOID);
STATIC XTAPI ULONG_PTR GetEmptyPteList(VOID);
STATIC XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte);
STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte);
STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte);
STATIC XTAPI PMMP5E GetP5eAddress(IN PVOID Address);
STATIC XTAPI PVOID GetP5eVirtualAddress(IN PMMP5E P5ePointer);
STATIC XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte);
STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address);
STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer);
STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address);
STATIC XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer);
STATIC XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer);
STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address);
STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte,
PMMPTE StartPte);
STATIC XTAPI ULONG GetPteSize(VOID);
STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer);
STATIC XTAPI PMMPXE GetPxeAddress(IN PVOID Address);
STATIC XTAPI PVOID GetPxeVirtualAddress(IN PMMPXE PxePointer);
STATIC XTAPI BOOLEAN GetXpaStatus(VOID);
STATIC XTAPI VOID InitializePageMapSupport(VOID);
STATIC XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer);
STATIC XTAPI VOID SetNextEntry(IN PMMPTE Pte,
IN ULONG_PTR Value);
STATIC XTAPI VOID SetOneEntry(IN PMMPTE Pte,
IN BOOLEAN Value);
STATIC XTAPI VOID SetPte(IN PMMPTE PtePointer,
IN PFN_NUMBER PageFrameNumber,
IN ULONG_PTR AttributesMask);
STATIC XTAPI VOID SetPte(IN PMMPTE PtePointer,
IN ULONG_PTR Attributes);
STATIC XTAPI VOID SetPteCaching(IN PMMPTE PtePointer,
IN BOOLEAN CacheDisable,
IN BOOLEAN WriteThrough);
STATIC XTAPI VOID WritePte(IN PMMPTE Pte,
IN MMPTE Value);
STATIC XTFASTCALL VOID ZeroPages(IN PVOID Address,
IN ULONG Size);
private:
STATIC XTAPI BOOLEAN GetExtendedPhysicalAddressingStatus(VOID);
STATIC XTAPI PPAGEMAP GetPageMapBasicRoutines(VOID);
STATIC XTAPI PPAGEMAP GetPageMapXpaRoutines(VOID);
};
}
#endif /* __XTOSKRNL_MM_AMD64_PAGING_HH */

View File

@@ -0,0 +1,65 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/mm/amd64/pte.hh
* DESCRIPTION: Page table entry (PTE) for AMD64 support
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_MM_AMD64_PTE_HH
#define __XTOSKRNL_MM_AMD64_PTE_HH
#include <xtos.hh>
/* Memory Manager */
namespace MM
{
class Pte
{
private:
STATIC MMPTE FirstSystemFreePte[MaximumPtePoolTypes];
STATIC PMMPTE SystemPteBase;
STATIC PMMPTE SystemPtesEnd[MaximumPtePoolTypes];
STATIC PMMPTE SystemPtesStart[MaximumPtePoolTypes];
STATIC ULONG TotalSystemFreePtes[MaximumPtePoolTypes];
STATIC MMPTE ValidPte;
public:
STATIC XTAPI BOOLEAN AddressValid(IN PVOID VirtualAddress);
STATIC XTAPI ULONG GetPtesPerPage(VOID);
STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID);
STATIC XTAPI VOID InitializePageTable(VOID);
STATIC XTAPI VOID InitializeSystemPteSpace(VOID);
STATIC XTAPI VOID MapP5E(PVOID StartAddress,
PVOID EndAddress,
PMMP5E TemplateP5e);
STATIC XTAPI VOID MapPDE(PVOID StartAddress,
PVOID EndAddress,
PMMPDE TemplatePde);
STATIC XTAPI VOID MapPPE(PVOID StartAddress,
PVOID EndAddress,
PMMPPE TemplatePpe);
STATIC XTAPI VOID MapPTE(PVOID StartAddress,
PVOID EndAddress,
PMMPTE TemplatePte);
STATIC XTAPI VOID MapPXE(PVOID StartAddress,
PVOID EndAddress,
PMMPXE TemplatePxe);
STATIC XTAPI PMMPTE ReserveSystemPtes(IN ULONG NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType,
IN ULONG Alignment);
private:
STATIC XTAPI BOOLEAN FindFreeCluster(IN ULONG NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType,
OUT PMMPTE *FoundCluster,
OUT PMMPTE *PreviousClusterNode);
STATIC XTAPI ULONG GetClusterSize(IN PMMPTE Pte);
STATIC XTAPI VOID InitializeSystemPtePool(IN PMMPTE StartingPte,
IN ULONG NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE PoolType);
};
}
#endif /* __XTOSKRNL_MM_AMD64_PTE_HH */

View File

@@ -0,0 +1,35 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/mm/colors.hh
* DESCRIPTION: Memory manager page coloring subsystem
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_MM_COLORS_HH
#define __XTOSKRNL_MM_COLORS_HH
#include <xtos.hh>
/* Memory Manager */
namespace MM
{
class Colors
{
private:
STATIC PMMCOLOR_TABLES FreePages[FreePageList + 1];
STATIC ULONG PagingColors;
STATIC ULONG PagingColorsMask;
public:
STATIC XTAPI VOID ComputePageColoring(VOID);
STATIC XTAPI PMMCOLOR_TABLES GetFreePages(MMPAGELISTS PageList,
ULONG Color);
STATIC XTAPI ULONG GetNextColor();
STATIC XTAPI ULONG GetPagingColors();
STATIC XTAPI ULONG GetPagingColorsMask();
};
}
#endif /* __XTOSKRNL_MM_PFN_HH */

View File

@@ -1,13 +1,13 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/mm/pagemap.hh
* FILE: xtoskrnl/includes/mm/i686/pagemap.hh
* DESCRIPTION: Low-level support for page map manipulation
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_MM_PAGEMAP_HH
#define __XTOSKRNL_MM_PAGEMAP_HH
#ifndef __XTOSKRNL_MM_I686_PAGEMAP_HH
#define __XTOSKRNL_MM_I686_PAGEMAP_HH
#include <xtos.hh>
@@ -21,45 +21,114 @@ namespace MM
MMPAGEMAP_INFO PageMapInfo;
public:
XTAPI VOID ClearPte(PHARDWARE_PTE PtePointer);
XTAPI PMMPDE GetPdeAddress(PVOID Address);
XTAPI PMMPPE GetPpeAddress(PVOID Address);
XTAPI PMMPTE GetPteAddress(PVOID Address);
virtual XTAPI VOID InitializePageMapInfo(VOID) = 0;
virtual XTAPI BOOLEAN PteValid(PHARDWARE_PTE PtePointer) = 0;
virtual XTAPI VOID SetPte(PHARDWARE_PTE PtePointer,
PFN_NUMBER PageFrameNumber,
BOOLEAN Writable) = 0;
virtual XTAPI VOID SetPteCaching(PHARDWARE_PTE PtePointer,
BOOLEAN CacheDisable,
BOOLEAN WriteThrough) = 0;
VIRTUAL XTAPI PMMPTE AdvancePte(IN PMMPTE Pte,
IN ULONG Count) = 0;
VIRTUAL XTAPI VOID ClearPte(IN PMMPTE PtePointer) = 0;
XTAPI ULONG GetEmptyPteList(VOID);
VIRTUAL XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte) = 0;
VIRTUAL XTAPI PMMPTE GetNextPte(IN PMMPTE Pte) = 0;
VIRTUAL XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte) = 0;
VIRTUAL XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte) = 0;
XTAPI PMMPDE GetPdeAddress(IN PVOID Address);
XTAPI ULONG GetPdeOffset(IN PVOID Address);
VIRTUAL XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer) = 0;
XTAPI PMMPPE GetPpeAddress(IN PVOID Address);
XTAPI ULONG GetPpeOffset(IN PVOID Address);
XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer);
VIRTUAL XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer) = 0;
XTAPI PMMPTE GetPteAddress(IN PVOID Address);
XTAPI ULONG GetPteOffset(IN PVOID Address);
VIRTUAL XTAPI LONG GetPteDistance(PMMPTE EndPte,
PMMPTE StartPte) = 0;
VIRTUAL XTAPI ULONG GetPteSize(VOID) = 0;
VIRTUAL XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer) = 0;
XTAPI BOOLEAN GetXpaStatus();
VIRTUAL XTAPI VOID InitializePageMapInfo(VOID) = 0;
VIRTUAL XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer) = 0;
VIRTUAL XTAPI VOID SetNextEntry(IN PMMPTE Pte,
IN ULONG_PTR Value) = 0;
VIRTUAL XTAPI VOID SetOneEntry(IN PMMPTE Pte,
IN BOOLEAN Value) = 0;
VIRTUAL XTAPI VOID SetPte(IN PMMPTE PtePointer,
IN PFN_NUMBER PageFrameNumber,
IN ULONG_PTR AttributesMask) = 0;
VIRTUAL XTAPI VOID SetPte(IN PMMPTE PtePointer,
IN ULONG_PTR Attributes) = 0;
VIRTUAL XTAPI VOID SetPteCaching(IN PMMPTE PtePointer,
IN BOOLEAN CacheDisable,
IN BOOLEAN WriteThrough) = 0;
VIRTUAL XTAPI VOID WritePte(IN PMMPTE Pte,
IN MMPTE Value) = 0;
} PAGEMAP, *PPAGEMAP;
class PageMapBasic final : public PageMap
{
public:
XTAPI PMMPTE AdvancePte(IN PMMPTE Pte,
IN ULONG Count);
XTAPI VOID ClearPte(IN PMMPTE PtePointer);
XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte);
XTAPI PMMPTE GetNextPte(IN PMMPTE Pte);
XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte);
XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte);
XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer);
XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer);
XTAPI LONG GetPteDistance(PMMPTE EndPte,
PMMPTE StartPte);
XTAPI ULONG GetPteSize(VOID);
XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer);
XTAPI VOID InitializePageMapInfo(VOID);
XTAPI BOOLEAN PteValid(PHARDWARE_PTE PtePointer);
XTAPI VOID SetPte(PHARDWARE_PTE PtePointer,
PFN_NUMBER PageFrameNumber,
BOOLEAN Writable);
XTAPI VOID SetPteCaching(PHARDWARE_PTE PtePointer,
BOOLEAN CacheDisable,
BOOLEAN WriteThrough);
XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer);
XTAPI VOID SetNextEntry(IN PMMPTE Pte,
IN ULONG_PTR Value);
XTAPI VOID SetOneEntry(IN PMMPTE Pte,
IN BOOLEAN Value);
XTAPI VOID SetPte(IN PMMPTE PtePointer,
IN PFN_NUMBER PageFrameNumber,
IN ULONG_PTR AttributesMask);
XTAPI VOID SetPte(IN PMMPTE PtePointer,
IN ULONG_PTR Attributes);
XTAPI VOID SetPteCaching(IN PMMPTE PtePointer,
IN BOOLEAN CacheDisable,
IN BOOLEAN WriteThrough);
XTAPI VOID WritePte(IN PMMPTE Pte,
IN MMPTE Value);
};
class PageMapXpa final : public PageMap
{
public:
XTAPI PMMPTE AdvancePte(IN PMMPTE Pte,
IN ULONG Count);
XTAPI VOID ClearPte(IN PMMPTE PtePointer);
XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte);
XTAPI PMMPTE GetNextPte(IN PMMPTE Pte);
XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte);
XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte);
XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer);
XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer);
XTAPI LONG GetPteDistance(PMMPTE EndPte,
PMMPTE StartPte);
XTAPI ULONG GetPteSize(VOID);
XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer);
XTAPI VOID InitializePageMapInfo(VOID);
XTAPI BOOLEAN PteValid(PHARDWARE_PTE PtePointer);
XTAPI VOID SetPte(PHARDWARE_PTE PtePointer,
PFN_NUMBER PageFrameNumber,
BOOLEAN Writable);
XTAPI VOID SetPteCaching(PHARDWARE_PTE PtePointer,
BOOLEAN CacheDisable,
BOOLEAN WriteThrough);
XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer);
XTAPI VOID SetNextEntry(IN PMMPTE Pte,
IN ULONG_PTR Value);
XTAPI VOID SetOneEntry(IN PMMPTE Pte,
IN BOOLEAN Value);
XTAPI VOID SetPte(IN PMMPTE PtePointer,
IN PFN_NUMBER PageFrameNumber,
IN ULONG_PTR AttributesMask);
XTAPI VOID SetPte(IN PMMPTE PtePointer,
IN ULONG_PTR Attributes);
XTAPI VOID SetPteCaching(IN PMMPTE PtePointer,
IN BOOLEAN CacheDisable,
IN BOOLEAN WriteThrough);
XTAPI VOID WritePte(IN PMMPTE Pte,
IN MMPTE Value);
};
}
#endif /* __XTOSKRNL_MM_PAGEMAP_HH */
#endif /* __XTOSKRNL_MM_I686_PAGEMAP_HH */

View File

@@ -0,0 +1,70 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/mm/i686/paging.hh
* DESCRIPTION: Low level page management support for i686
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_MM_I686_PAGING_HH
#define __XTOSKRNL_MM_I686_PAGING_HH
#include <xtos.hh>
/* Memory Manager */
namespace MM
{
class Paging
{
private:
STATIC PPAGEMAP PmlRoutines;
public:
STATIC XTAPI PMMPTE AdvancePte(IN PMMPTE Pte,
IN LONG Count);
STATIC XTAPI VOID ClearPte(IN PMMPTE PtePointer);
STATIC XTAPI VOID FlushTlb(VOID);
STATIC XTAPI ULONG_PTR GetEmptyPteList(VOID);
STATIC XTAPI ULONG_PTR GetNextEntry(IN PMMPTE Pte);
STATIC XTAPI PMMPTE GetNextPte(IN PMMPTE Pte);
STATIC XTAPI BOOLEAN GetOneEntry(IN PMMPTE Pte);
STATIC XTAPI PFN_NUMBER GetPageFrameNumber(IN PMMPTE Pte);
STATIC XTAPI PMMPDE GetPdeAddress(IN PVOID Address);
STATIC XTAPI PVOID GetPdeVirtualAddress(IN PMMPDE PdePointer);
STATIC XTAPI PMMPPE GetPpeAddress(IN PVOID Address);
STATIC XTAPI PVOID GetPpeVirtualAddress(IN PMMPPE PpePointer);
STATIC XTAPI ULONG_PTR GetPte(IN PMMPTE PtePointer);
STATIC XTAPI PMMPTE GetPteAddress(IN PVOID Address);
STATIC XTAPI LONG GetPteDistance(PMMPTE EndPte,
PMMPTE StartPte);
STATIC XTAPI ULONG GetPteSize(VOID);
STATIC XTAPI PVOID GetPteVirtualAddress(IN PMMPTE PtePointer);
STATIC XTAPI BOOLEAN GetXpaStatus(VOID);
STATIC XTAPI VOID InitializePageMapSupport(VOID);
STATIC XTAPI BOOLEAN PteValid(IN PMMPTE PtePointer);
STATIC XTAPI VOID SetNextEntry(IN PMMPTE Pte,
IN ULONG_PTR Value);
STATIC XTAPI VOID SetOneEntry(IN PMMPTE Pte,
IN BOOLEAN Value);
STATIC XTAPI VOID SetPte(IN PMMPTE PtePointer,
IN PFN_NUMBER PageFrameNumber,
IN ULONG_PTR AttributesMask);
STATIC XTAPI VOID SetPte(IN PMMPTE PtePointer,
IN ULONG_PTR Attributes);
STATIC XTAPI VOID SetPteCaching(IN PMMPTE PtePointer,
IN BOOLEAN CacheDisable,
IN BOOLEAN WriteThrough);
STATIC XTAPI VOID WritePte(IN PMMPTE Pte,
IN MMPTE Value);
STATIC XTFASTCALL VOID ZeroPages(IN PVOID Address,
IN ULONG Size);
private:
STATIC XTAPI BOOLEAN GetExtendedPhysicalAddressingStatus(VOID);
STATIC XTAPI PPAGEMAP GetPageMapBasicRoutines(VOID);
STATIC XTAPI PPAGEMAP GetPageMapXpaRoutines(VOID);
};
}
#endif /* __XTOSKRNL_MM_I686_PAGING_HH */

View File

@@ -0,0 +1,59 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/mm/i686/pte.hh
* DESCRIPTION: Page table entry (PTE) for i686 support
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_MM_I686_PTE_HH
#define __XTOSKRNL_MM_I686_PTE_HH
#include <xtos.hh>
/* Memory Manager */
namespace MM
{
class Pte
{
private:
STATIC MMPTE FirstSystemFreePte[MaximumPtePoolTypes];
STATIC PMMPTE SystemPteBase;
STATIC PMMPTE SystemPtesEnd[MaximumPtePoolTypes];
STATIC PMMPTE SystemPtesStart[MaximumPtePoolTypes];
STATIC ULONG TotalSystemFreePtes[MaximumPtePoolTypes];
STATIC MMPTE ValidPte;
public:
STATIC XTAPI BOOLEAN AddressValid(IN PVOID VirtualAddress);
STATIC XTAPI ULONG GetPtesPerPage(VOID);
STATIC XTAPI PMMPTE GetSystemPteBaseAddress(VOID);
STATIC XTAPI VOID InitializePageTable(VOID);
STATIC XTAPI VOID InitializeSystemPteSpace(VOID);
STATIC XTAPI VOID MapPDE(PVOID StartAddress,
PVOID EndAddress,
PMMPDE TemplatePde);
STATIC XTAPI VOID MapPPE(PVOID StartAddress,
PVOID EndAddress,
PMMPPE TemplatePpe);
STATIC XTAPI VOID MapPTE(PVOID StartAddress,
PVOID EndAddress,
PMMPTE TemplatePte);
STATIC XTAPI PMMPTE ReserveSystemPtes(IN ULONG NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType,
IN ULONG Alignment);
private:
STATIC XTAPI BOOLEAN FindFreeCluster(IN ULONG NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType,
OUT PMMPTE *FoundCluster,
OUT PMMPTE *PreviousClusterNode);
STATIC XTAPI ULONG GetClusterSize(IN PMMPTE Pte);
STATIC XTAPI VOID InitializeSystemPtePool(IN PMMPTE StartingPte,
IN ULONG NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE PoolType);
};
}
#endif /* __XTOSKRNL_MM_I686_PTE_HH */

View File

@@ -1,39 +0,0 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/mm/init.hh
* DESCRIPTION: Memory Manager initialization
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_MM_INIT_HH
#define __XTOSKRNL_MM_INIT_HH
#include <xtos.hh>
/* Memory Manager */
namespace MM
{
class Init
{
private:
STATIC PLOADER_MEMORY_DESCRIPTOR FreeDescriptor;
STATIC ULONG_PTR HighestPhysicalPage;
STATIC ULONG_PTR LowestPhysicalPage;
STATIC ULONG NumberOfPhysicalPages;
STATIC LOADER_MEMORY_DESCRIPTOR OldFreeDescriptor;
public:
STATIC XTAPI VOID InitializeMemoryManager(VOID);
STATIC XTAPI VOID InitializePageMapSupport(VOID);
STATIC XTAPI VOID ScanMemoryDescriptors(VOID);
private:
STATIC XTAPI VOID InitializeArchitecture(VOID);
STATIC XTAPI BOOLEAN VerifyMemoryTypeFree(LOADER_MEMORY_TYPE MemoryType);
STATIC XTAPI BOOLEAN VerifyMemoryTypeInvisible(LOADER_MEMORY_TYPE MemoryType);
};
}
#endif /* __XTOSKRNL_MM_INIT_HH */

View File

@@ -0,0 +1,34 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/mm/mmgr.hh
* DESCRIPTION: Memory manager
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_MM_MMGR_HH
#define __XTOSKRNL_MM_MMGR_HH
#include <xtos.hh>
/* Memory Manager */
namespace MM
{
class Manager
{
private:
STATIC MMMEMORY_LAYOUT MemoryLayout;
STATIC PFN_NUMBER NumberOfSystemPtes;
public:
STATIC XTAPI PMMMEMORY_LAYOUT GetMemoryLayout(VOID);
STATIC XTAPI PFN_NUMBER GetNumberOfSystemPtes();
STATIC XTAPI VOID InitializeMemoryLayout(VOID);
STATIC XTAPI VOID InitializeMemoryManager(VOID);
STATIC XTAPI BOOLEAN VerifyMemoryTypeFree(LOADER_MEMORY_TYPE MemoryType);
STATIC XTAPI BOOLEAN VerifyMemoryTypeInvisible(LOADER_MEMORY_TYPE MemoryType);
};
}
#endif /* __XTOSKRNL_MM_MMGR_HH */

View File

@@ -1,47 +0,0 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/mm/paging.hh
* DESCRIPTION: Low level page management support
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_MM_PAGING_HH
#define __XTOSKRNL_MM_PAGING_HH
#include <xtos.hh>
/* Memory Manager */
namespace MM
{
class Paging
{
private:
STATIC PPAGEMAP PmlRoutines;
public:
STATIC XTAPI VOID ClearPte(PHARDWARE_PTE PtePointer);
STATIC XTAPI VOID FlushTlb(VOID);
STATIC XTAPI PMMPDE GetPdeAddress(PVOID Address);
STATIC XTAPI PMMPPE GetPpeAddress(PVOID Address);
STATIC XTAPI PMMPTE GetPteAddress(PVOID Address);
STATIC XTAPI VOID InitializePageMapSupport(VOID);
STATIC XTAPI BOOLEAN PteValid(PHARDWARE_PTE PtePointer);
STATIC XTAPI VOID SetPte(PHARDWARE_PTE PtePointer,
PFN_NUMBER PageFrameNumber,
BOOLEAN Writable);
STATIC XTAPI VOID SetPteCaching(PHARDWARE_PTE PtePointer,
BOOLEAN CacheDisable,
BOOLEAN WriteThrough);
STATIC XTFASTCALL VOID ZeroPages(IN PVOID Address,
IN ULONG Size);
private:
STATIC XTAPI BOOLEAN GetExtendedPhysicalAddressingStatus(VOID);
STATIC XTAPI PPAGEMAP GetPageMapBasicRoutines(VOID);
STATIC XTAPI PPAGEMAP GetPageMapXpaRoutines(VOID);
};
}
#endif /* __XTOSKRNL_MM_PAGING_HH */

View File

@@ -0,0 +1,42 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/mm/pfn.hh
* DESCRIPTION: Physical Frame Number (PFN) support
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_MM_PFN_HH
#define __XTOSKRNL_MM_PFN_HH
#include <xtos.hh>
/* Memory Manager */
namespace MM
{
class Pfn
{
private:
STATIC PFN_NUMBER AvailablePages;
STATIC PLOADER_MEMORY_DESCRIPTOR FreeDescriptor;
STATIC ULONG_PTR HighestPhysicalPage;
STATIC ULONG_PTR LowestPhysicalPage;
STATIC ULONGLONG NumberOfPhysicalPages;
STATIC LOADER_MEMORY_DESCRIPTOR OriginalFreeDescriptor;
STATIC PFN_NUMBER PfnDatabaseSize;
public:
STATIC XTAPI PFN_NUMBER AllocateBootstrapPages(IN PFN_NUMBER NumberOfPages);
STATIC XTAPI VOID ComputePfnDatabaseSize(VOID);
STATIC XTAPI ULONGLONG GetNumberOfPhysicalPages(VOID);
STATIC XTAPI PFN_NUMBER GetPfnDatabaseSize(VOID);
STATIC XTAPI VOID ScanMemoryDescriptors(VOID);
private:
STATIC XTAPI VOID DecrementAvailablePages(VOID);
STATIC XTAPI VOID IncrementAvailablePages(VOID);
};
}
#endif /* __XTOSKRNL_MM_PFN_HH */

View File

@@ -86,6 +86,10 @@ KE::KernelInit::StartKernel(VOID)
/* Save processor state */
Processor::SaveProcessorState(&Prcb->ProcessorState);
/* Initialize spin locks */
SpinLock::InitializeAllLocks();
SpinLock::InitializeLockQueues();
/* Lower to APC runlevel */
RunLevel::LowerRunLevel(APC_LEVEL);
@@ -108,6 +112,9 @@ KE::KernelInit::StartKernel(VOID)
CurrentThread->WaitRunLevel = DISPATCH_LEVEL;
CurrentProcess->ActiveProcessors |= (ULONG_PTR)1 << Prcb->CpuNumber;
/* Initialize Memory Manager */
MM::Manager::InitializeMemoryManager();
/* Enter infinite loop */
DebugPrint(L"KernelInit::StartKernel() finished. Entering infinite loop.\n");
Crash::HaltSystem();

View File

@@ -12,12 +12,6 @@
/* Kernel initialization block passed by boot loader */
PKERNEL_INITIALIZATION_BLOCK KE::BootInformation::InitializationBlock = {};
/* Kernel boot resources list */
LIST_ENTRY KE::SystemResources::ResourcesListHead;
/* Kernel boot resources lock */
KSPIN_LOCK KE::SystemResources::ResourcesLock;
/* Kernel initial process */
EPROCESS KE::KProcess::InitialProcess;
@@ -26,3 +20,54 @@ ETHREAD KE::KThread::InitialThread = {};
/* Kernel UBSAN active frame flag */
BOOLEAN KE::KUbsan::ActiveFrame = FALSE;
/* Kernel dispatcher lock queue */
KSPIN_LOCK KE::SpinLock::DispatcherLockQueue;
/* Kernel expansion lock queue */
KSPIN_LOCK KE::SpinLock::ExpansionLockQueue;
/* Kernel file system structures lock queue */
KSPIN_LOCK KE::SpinLock::FileSystemLockQueue;
/* Kernel IO cancel lock queue */
KSPIN_LOCK KE::SpinLock::IoCancelLockQueue;
/* Kernel IO completion lock queue */
KSPIN_LOCK KE::SpinLock::IoCompletionLockQueue;
/* Kernel IO database lock queue */
KSPIN_LOCK KE::SpinLock::IoDatabaseLockQueue;
/* Kernel IO VPB lock queue */
KSPIN_LOCK KE::SpinLock::IoVpbLockQueue;
/* Kernel cache master lock queue */
KSPIN_LOCK KE::SpinLock::MasterLockQueue;
/* Kernel non-paged allocator lock queue */
KSPIN_LOCK KE::SpinLock::NonPagedAllocLockQueue;
/* Kernel non-paged pool lock queue */
KSPIN_LOCK KE::SpinLock::NonPagedPoolLockQueue;
/* Kernel PFN lock queue */
KSPIN_LOCK KE::SpinLock::PfnLockQueue;
/* Kernel system space lock queue */
KSPIN_LOCK KE::SpinLock::SystemSpaceLockQueue;
/* Kernel Timer table lock queue */
KSPIN_LOCK KE::SpinLock::TimerTableLockQueue;
/* Kernel VACB lock queue */
KSPIN_LOCK KE::SpinLock::VacbLockQueue;
/* Kernel work queue lock queue */
KSPIN_LOCK KE::SpinLock::WorkLockQueue;
/* Kernel boot resources list */
LIST_ENTRY KE::SystemResources::ResourcesListHead;
/* Kernel boot resources lock */
KSPIN_LOCK KE::SystemResources::ResourcesLock;

View File

@@ -86,6 +86,10 @@ KE::KernelInit::StartKernel(VOID)
/* Save processor state */
Processor::SaveProcessorState(&Prcb->ProcessorState);
/* Initialize spin locks */
SpinLock::InitializeAllLocks();
SpinLock::InitializeLockQueues();
/* Lower to APC runlevel */
RunLevel::LowerRunLevel(APC_LEVEL);
@@ -108,6 +112,9 @@ KE::KernelInit::StartKernel(VOID)
CurrentThread->WaitRunLevel = DISPATCH_LEVEL;
CurrentProcess->ActiveProcessors |= (ULONG_PTR)1 << Prcb->CpuNumber;
/* Initialize Memory Manager */
MM::Manager::InitializeMemoryManager();
/* Enter infinite loop */
DebugPrint(L"KernelInit::StartKernel() finished. Entering infinite loop.\n");
Crash::HaltSystem();

View File

@@ -4,6 +4,7 @@
* FILE: xtoskrnl/ke/spinlock.cc
* DESCRIPTION: Spinlocks support
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
* Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
@@ -56,6 +57,78 @@ KE::SpinLock::AcquireSpinLock(IN OUT PKSPIN_LOCK SpinLock)
AR::CpuFunc::ReadWriteBarrier();
}
/**
* Initializes all kernel spinlocks.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::SpinLock::InitializeAllLocks()
{
/* Initialize all spin locks */
InitializeSpinLock(&DispatcherLockQueue);
InitializeSpinLock(&PfnLockQueue);
InitializeSpinLock(&SystemSpaceLockQueue);
}
/**
* Initializes spinlock queues for current processor.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::SpinLock::InitializeLockQueues()
{
PKPROCESSOR_CONTROL_BLOCK ControlBlock;
/* Get current processor control block */
ControlBlock = KE::Processor::GetCurrentProcessorControlBlock();
/* Initialize PCB lock queues */
ControlBlock->LockQueue[DispatcherLock].Lock = &DispatcherLockQueue;
ControlBlock->LockQueue[DispatcherLock].Next = NULLPTR;
ControlBlock->LockQueue[ExpansionLock].Lock = &ExpansionLockQueue;
ControlBlock->LockQueue[ExpansionLock].Next = NULLPTR;
ControlBlock->LockQueue[PfnLock].Lock = &PfnLockQueue;
ControlBlock->LockQueue[PfnLock].Next = NULLPTR;
ControlBlock->LockQueue[SystemSpaceLock].Lock = &SystemSpaceLockQueue;
ControlBlock->LockQueue[SystemSpaceLock].Next = NULLPTR;
ControlBlock->LockQueue[VacbLock].Lock = &VacbLockQueue;
ControlBlock->LockQueue[VacbLock].Next = NULLPTR;
ControlBlock->LockQueue[MasterLock].Lock = &MasterLockQueue;
ControlBlock->LockQueue[MasterLock].Next = NULLPTR;
ControlBlock->LockQueue[NonPagedAllocPoolLock].Lock = &NonPagedAllocLockQueue;
ControlBlock->LockQueue[NonPagedAllocPoolLock].Next = NULLPTR;
ControlBlock->LockQueue[IoCancelLock].Lock = &IoCancelLockQueue;
ControlBlock->LockQueue[IoCancelLock].Next = NULLPTR;
ControlBlock->LockQueue[WorkQueueLock].Lock = &WorkLockQueue;
ControlBlock->LockQueue[WorkQueueLock].Next = NULLPTR;
ControlBlock->LockQueue[IoVpbLock].Lock = &IoVpbLockQueue;
ControlBlock->LockQueue[IoVpbLock].Next = NULLPTR;
ControlBlock->LockQueue[IoDatabaseLock].Lock = &IoDatabaseLockQueue;
ControlBlock->LockQueue[IoDatabaseLock].Next = NULLPTR;
ControlBlock->LockQueue[IoCompletionLock].Lock = &IoCompletionLockQueue;
ControlBlock->LockQueue[IoCompletionLock].Next = NULLPTR;
ControlBlock->LockQueue[FileSystemLock].Lock = &FileSystemLockQueue;
ControlBlock->LockQueue[FileSystemLock].Next = NULLPTR;
ControlBlock->LockQueue[AfdWorkQueueLock].Lock = NULLPTR;
ControlBlock->LockQueue[AfdWorkQueueLock].Next = NULLPTR;
ControlBlock->LockQueue[BcbLock].Lock = NULLPTR;
ControlBlock->LockQueue[BcbLock].Next = NULLPTR;
ControlBlock->LockQueue[NonPagedPoolLock].Lock = &NonPagedPoolLockQueue;
ControlBlock->LockQueue[NonPagedPoolLock].Next = NULLPTR;
ControlBlock->LockQueue[ReservedSystemLock].Lock = NULLPTR;
ControlBlock->LockQueue[ReservedSystemLock].Next = NULLPTR;
ControlBlock->LockQueue[TimerTableLock].Lock = &TimerTableLockQueue;
ControlBlock->LockQueue[TimerTableLock].Next = NULLPTR;
}
/**
* Initializes a kernel spinlock object.
*
@@ -112,3 +185,29 @@ KE::SpinLock::ReleaseSpinLock(IN OUT PKSPIN_LOCK SpinLock)
/* Add an explicit memory barrier */
AR::CpuFunc::ReadWriteBarrier();
}
/**
* Tests a kernel spin lock.
*
* @param SpinLock
* Supplies a pointer to the kernel spin lock.
*
* @return This routine returns TRUE if the lock is free, FALSE otherwise.
*
* @since XT 1.0
*/
XTFASTCALL
BOOLEAN
TestSpinLock(IN PKSPIN_LOCK SpinLock)
{
/* Check if the lock is free */
if(*SpinLock)
{
/* Spinlock is busy, yield processor and return FALSE */
AR::CpuFunc::YieldProcessor();
return FALSE;
}
/* Spinlock is free, return TRUE */
return TRUE;
}

View File

@@ -1,25 +0,0 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/mm/amd64/init.cc
* DESCRIPTION: Architecture specific Memory Manager initialization routines
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
* Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Performs architecture specific initialization of the XTOS Memory Manager.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Init::InitializeArchitecture(VOID)
{
UNIMPLEMENTED;
}

77
xtoskrnl/mm/amd64/mmgr.cc Normal file
View File

@@ -0,0 +1,77 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/mm/amd64/mmgr.cc
* DESCRIPTION: Memory Manager
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Initializes the kernel's virtual memory layout.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Manager::InitializeMemoryLayout(VOID)
{
ULONG_PTR PagedPoolSize, PteCount;
PFN_NUMBER PfnDatabaseSize;
ULONG PtesPerPage;
/* Get the number of PTEs per page and calculate size of paged pool (at least 32MiB) */
PtesPerPage = MM::Pte::GetPtesPerPage();
PteCount = ((SIZE_TO_PAGES(33554432) + (PtesPerPage - 1)) / PtesPerPage);
PagedPoolSize = PteCount * PtesPerPage * MM_PAGE_SIZE;
/* Retrieve the PFN database size */
PfnDatabaseSize = MM::Pfn::GetPfnDatabaseSize();
/* Define the number of system PTEs */
NumberOfSystemPtes = MM_DEFAULT_NUMBER_SYSTEM_PTES;
/* Check if 5-level paging (LA57) is enabled */
if(MM::Paging::GetXpaStatus())
{
/* Configure memory layout for 5-level paging, using 57bit address space and providing a 128 PB address space */
MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xFFFEFA8000000000ULL;
MemoryLayout.SelfMapAddress = (PVOID)MM_P5E_LA57_BASE;
/* Define the non-paged and paged pool regions */
MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE);
MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFEFFFFFFBFFFFFULL;
MemoryLayout.PagedPoolStart = (PVOID)0xFFFEF8A000000000ULL;
MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1);
/* Define hyperspace, system PTE space, and the user space limit */
MemoryLayout.HyperSpaceStart = (PVOID)0xFFFEF70000000000ULL;
MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFEF77FFFFFFFFFULL;
MemoryLayout.SystemSpaceStart = (PVOID)0xFFFEF88000000000ULL;
MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE);
MemoryLayout.UserSpaceEnd = (PVOID)0x07FFFFFFFFFFFFFULL;
}
else
{
/* Configure memory layout for 4-level paging, using 48bit address space and providing a 128 TB address space */
MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xFFFFFA8000000000ULL;
MemoryLayout.SelfMapAddress = (PVOID)MM_PXE_BASE;
/* Define the non-paged and paged pool regions */
MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE);
MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFFFFFFFFFBFFFFFULL;
MemoryLayout.PagedPoolStart = (PVOID)0xFFFFF8A000000000ULL;
MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1);
/* Define hyperspace, system PTE space, and the user space limit */
MemoryLayout.HyperSpaceStart = (PVOID)0xFFFFF70000000000ULL;
MemoryLayout.HyperSpaceEnd = (PVOID)0xFFFFF77FFFFFFFFFULL;
MemoryLayout.SystemSpaceStart = (PVOID)0xFFFFF88000000000ULL;
MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE);
MemoryLayout.UserSpaceEnd = (PVOID)0x000007FFFFFEFFFFULL;
}
}

View File

@@ -9,6 +9,28 @@
#include <xtos.hh>
/**
* Advances a PTE pointer by a given number of entries, considering the actual PTE size.
*
* @param Pte
* The PTE pointer to advance.
*
* @param Count
* The number of PTE entries to advance by.
*
* @return The advanced PTE pointer.
*
* @since XT 1.0
*/
XTAPI
PMMPTE
MM::PageMap::AdvancePte(IN PMMPTE Pte,
IN LONG Count)
{
/* Return advanced PTE pointer */
return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPTE)));
}
/**
* Clears the contents of a page table entry (PTE).
*
@@ -21,13 +43,79 @@
*/
XTAPI
VOID
MM::PageMap::ClearPte(PHARDWARE_PTE PtePointer)
MM::PageMap::ClearPte(IN PMMPTE PtePointer)
{
PtePointer->CacheDisable = 0;
PtePointer->PageFrameNumber = 0;
PtePointer->Valid = 0;
PtePointer->Writable = 0;
PtePointer->WriteThrough = 0;
/* Clear PTE */
PtePointer->Long = 0;
}
/**
* Gets the value representing an empty PTE list.
*
* @return This routine returns the value representing an empty PTE list.
*
* @since XT 1.0
*/
XTAPI
ULONGLONG
MM::PageMap::GetEmptyPteList(VOID)
{
/* Return empty PTE list mask */
return PageMapInfo.EmptyPteList;
}
/**
* Gets the next entry in a PTE list.
*
* @param Pte
* The PTE pointer to get the next entry from.
*
* @return This routine returns the next entry in the PTE list.
*
* @since XT 1.0
*/
XTAPI
ULONG_PTR
MM::PageMap::GetNextEntry(IN PMMPTE Pte)
{
/* Return next entry in PTE list */
return Pte->List.NextEntry;
}
/**
* Advances a PTE pointer, considering the actual PTE size.
*
* @param Pte
* The PTE pointer to advance.
*
* @return The advanced PTE pointer.
*
* @since XT 1.0
*/
XTAPI
PMMPTE
MM::PageMap::GetNextPte(IN PMMPTE Pte)
{
/* Return advanced PTE pointer */
return AdvancePte(Pte, 1);
}
/**
* Checks if a PTE list contains only one entry.
*
* @param Pte
* The PTE pointer to check.
*
* @return This routine returns TRUE if the PTE list has only one entry, FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
MM::PageMap::GetOneEntry(IN PMMPTE Pte)
{
/* Return one entry status */
return Pte->List.OneEntry;
}
/**
@@ -42,7 +130,7 @@ MM::PageMap::ClearPte(PHARDWARE_PTE PtePointer)
*/
XTAPI
PMMP5E
MM::PageMap::GetP5eAddress(PVOID Address)
MM::PageMap::GetP5eAddress(IN PVOID Address)
{
ULONGLONG Offset;
@@ -51,6 +139,58 @@ MM::PageMap::GetP5eAddress(PVOID Address)
return (PMMP5E)((PageMapInfo.P5eBase + Offset) * PageMapInfo.Xpa);
}
/**
* Gets the Offset of the P5E (Page Map Level 5 Entry), that maps given address.
*
* @param Address
* Specifies the virtual address for which to retrieve the corresponding P5E.
*
* @return This routine returns the Offset of the P5E, or NULLPTR if LA57 is not enabled.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::PageMap::GetP5eOffset(IN PVOID Address)
{
/* Return P5E Offset */
return (((((ULONGLONG)Address) >> MM_P5I_SHIFT) & 0x1FF) * PageMapInfo.Xpa);
}
/**
* Gets the virtual address that is mapped by a given Page Map Level 5 Entry.
*
* @param P5ePointer
* Specifies the address of the P5E.
*
* @return This routine returns the virtual address mapped by the P5E, or NULLPTR if LA57 is not enabled.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::PageMap::GetP5eVirtualAddress(IN PMMP5E P5ePointer)
{
return (PVOID)((((LONGLONG)P5ePointer << 52) >> 7) * PageMapInfo.Xpa);
}
/**
* Gets the page frame number from a corresponding PTE.
*
* @param Pte
* The PTE pointer to get the page frame number from.
*
* @return This routine returns the page frame number.
*
* @since XT 1.0
*/
XTAPI
PFN_NUMBER
MM::PageMap::GetPageFrameNumber(IN PMMPTE Pte)
{
return Pte->Hardware.PageFrameNumber;
}
/**
* Gets the address of the PDE (Page Directory Entry), that maps given address.
*
@@ -63,7 +203,7 @@ MM::PageMap::GetP5eAddress(PVOID Address)
*/
XTAPI
PMMPDE
MM::PageMap::GetPdeAddress(PVOID Address)
MM::PageMap::GetPdeAddress(IN PVOID Address)
{
ULONGLONG Offset;
@@ -73,18 +213,36 @@ MM::PageMap::GetPdeAddress(PVOID Address)
}
/**
* Gets the address of the PPE (Page Directory Pointer Table Entry), that maps given address.
* Gets the Offset of the PDE (Page Directory Entry), that maps given address.
*
* @param Address
* Specifies the virtual address for which to retrieve the corresponding PDE.
*
* @return This routine returns the Offset of the PDE.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::PageMap::GetPdeOffset(IN PVOID Address)
{
/* Return PDE Offset */
return ((((ULONGLONG)Address) >> MM_PDI_SHIFT) & 0x1FF);
}
/**
* Gets the address of the PPE (Page Directory Pointer Table Entry), that maps given address.
*
* @param Address
* Specifies the virtual address for which to retrieve the corresponding PPE.
*
* @return This routine returns the address of the PPE.
*
* @since XT 1.0
*/
XTAPI
PMMPPE
MM::PageMap::GetPpeAddress(PVOID Address)
MM::PageMap::GetPpeAddress(IN PVOID Address)
{
ULONGLONG Offset;
@@ -93,6 +251,42 @@ MM::PageMap::GetPpeAddress(PVOID Address)
return (PMMPPE)(PageMapInfo.PpeBase + Offset);
}
/**
* Gets the Offset of the PPE (Page Directory Pointer Table Entry), that maps given address.
*
* @param Address
* Specifies the virtual address for which to retrieve the corresponding PPE.
*
* @return This routine returns the Offset of the PPE.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::PageMap::GetPpeOffset(IN PVOID Address)
{
/* Return PPE Offset */
return ((((ULONGLONG)Address) >> MM_PPI_SHIFT) & 0x1FF);
}
/**
* Gets the entire contents of a Page Table Entry (PTE) as a single value.
*
* @param PtePointer
* Pointer to the Page Table Entry (PTE) to read.
*
* @return This routine returns the contents of the PTE as a single value.
*
* @since XT 1.0
*/
XTAPI
ULONG_PTR
MM::PageMap::GetPte(IN PMMPTE PtePointer)
{
/* Return PTE value */
return PtePointer->Long;
}
/**
* Gets the address of the PTE (Page Table Entry), that maps given address.
*
@@ -105,7 +299,7 @@ MM::PageMap::GetPpeAddress(PVOID Address)
*/
XTAPI
PMMPTE
MM::PageMap::GetPteAddress(PVOID Address)
MM::PageMap::GetPteAddress(IN PVOID Address)
{
ULONGLONG Offset;
@@ -114,6 +308,61 @@ MM::PageMap::GetPteAddress(PVOID Address)
return (PMMPTE)(PageMapInfo.PteBase + Offset);
}
/**
* Calculates the distance between two PTE pointers.
*
* @param EndPte
* Pointer to the ending Page Table Entry.
*
* @param StartPte
* Pointer to the starting Page Table Entry.
*
* @return This routine returns a signed value representing the number of PTEs between EndPte and StartPte.
*
* @since XT 1.0
*/
XTAPI
LONG
MM::PageMap::GetPteDistance(PMMPTE EndPte,
PMMPTE StartPte)
{
/* Return distance between PTE pointers */
return ((ULONG_PTR)EndPte - (ULONG_PTR)StartPte) / sizeof(MMPTE);
}
/**
* Gets the Offset of the PTE (Page Table Entry), that maps given address.
*
* @param Address
* Specifies the virtual address for which to retrieve the corresponding PTE.
*
* @return This routine returns the Offset of the PTE.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::PageMap::GetPteOffset(IN PVOID Address)
{
/* Return PTE Offset */
return ((((ULONGLONG)Address) >> MM_PTI_SHIFT) & 0x1FF);
}
/**
* Gets the size of a PTE.
*
* @return This routine returns the size of a PTE.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::PageMap::GetPteSize(VOID)
{
/* Return the size of MMPTE */
return sizeof(MMPTE);
}
/**
* Gets the address of the PXE (Extended Page Entry), that maps given address.
*
@@ -126,14 +375,47 @@ MM::PageMap::GetPteAddress(PVOID Address)
*/
XTAPI
PMMPXE
MM::PageMap::GetPxeAddress(PVOID Address)
MM::PageMap::GetPxeAddress(IN PVOID Address)
{
ULONGLONG Offset;
/* Calculate offset and return PXE address */
Offset = ((((ULONGLONG)Address & (((ULONGLONG)1 << PageMapInfo.VaBits) - 1)) >> MM_PXI_SHIFT) << MM_PTE_SHIFT);
return (PMMPXE)(PageMapInfo.PxeBase + Offset);
}
/**
* Gets the Offset of the PXE (Extended Page Entry), that maps given address.
*
* @param Address
* Specifies the virtual address for which to retrieve the corresponding PXE.
*
* @return This routine returns the Offset of the PXE.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::PageMap::GetPxeOffset(IN PVOID Address)
{
/* Return PXE Offset */
return ((((ULONGLONG)Address) >> MM_PXI_SHIFT) & 0x1FF);
}
/**
* Gets the status of Extended Paging Address (XPA) mode.
*
* @return This routine returns TRUE if XPA is enabled, FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
MM::PageMap::GetXpaStatus()
{
return PageMapInfo.Xpa;
}
/**
* Checks whether the given PML2 page table entry (PTE) is valid.
*
@@ -146,22 +428,20 @@ MM::PageMap::GetPxeAddress(PVOID Address)
*/
XTAPI
BOOLEAN
MM::PageMap::PteValid(PHARDWARE_PTE PtePointer)
MM::PageMap::PteValid(IN PMMPTE PtePointer)
{
return (BOOLEAN)PtePointer->Valid;
/* Check if PTE is valid */
return (BOOLEAN)PtePointer->Hardware.Valid;
}
/**
* Sets a PML2 page table entry (PTE) with the specified physical page and access flags.
* Sets the next entry in a PTE list.
*
* @param PtePointer
* Pointer to the page table entry (PTE) to set.
* @param Pte
* The PTE pointer to modify.
*
* @param PageFrameNumber
* Physical frame number to map.
*
* @param Writable
* Indicates whether the page should be writable.
* @param Value
* The value to set as the next entry.
*
* @return This routine does not return any value.
*
@@ -169,13 +449,82 @@ MM::PageMap::PteValid(PHARDWARE_PTE PtePointer)
*/
XTAPI
VOID
MM::PageMap::SetPte(PHARDWARE_PTE PtePointer,
PFN_NUMBER PageFrameNumber,
BOOLEAN Writable)
MM::PageMap::SetNextEntry(IN PMMPTE Pte,
IN ULONG_PTR Value)
{
PtePointer->PageFrameNumber = PageFrameNumber;
PtePointer->Valid = 1;
PtePointer->Writable = Writable;
/* Set next entry in PTE list */
Pte->List.NextEntry = Value;
}
/**
* Sets the flag indicating whether a PTE list contains only one entry.
*
* @param Pte
* The PTE pointer to modify.
*
* @param Value
* The value to set. TRUE if the list has only one entry, FALSE otherwise.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::PageMap::SetOneEntry(IN PMMPTE Pte,
IN BOOLEAN Value)
{
/* Set one entry status */
Pte->List.OneEntry = Value;
}
/**
* Sets a Page Table Entry (PTE) with the specified physical page and access flags.
*
* @param PtePointer
* Pointer to the page table entry (PTE) to set.
*
* @param PageFrameNumber
* Physical frame number to map.
*
* @param AttributesMask
* Specifies the attributes mask to apply to the PTE.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::PageMap::SetPte(IN PMMPTE PtePointer,
IN PFN_NUMBER PageFrameNumber,
IN ULONG_PTR AttributesMask)
{
/* Set PTE */
PtePointer->Hardware.PageFrameNumber = PageFrameNumber;
PtePointer->Hardware.Valid = 1;
PtePointer->Long |= AttributesMask;
}
/**
* Sets a Page Table Entry (PTE) with the specified attributes.
*
* @param PtePointer
* Pointer to the page table entry (PTE) to set.
*
* @param Attributes
* Specifies the attributes to apply to the PTE.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::PageMap::SetPte(IN PMMPTE PtePointer,
IN ULONG_PTR Attributes)
{
PtePointer->Long = Attributes;
}
/**
@@ -196,12 +545,107 @@ MM::PageMap::SetPte(PHARDWARE_PTE PtePointer,
*/
XTAPI
VOID
MM::PageMap::SetPteCaching(PHARDWARE_PTE PtePointer,
BOOLEAN CacheDisable,
BOOLEAN WriteThrough)
MM::PageMap::SetPteCaching(IN PMMPTE PtePointer,
IN BOOLEAN CacheDisable,
IN BOOLEAN WriteThrough)
{
PtePointer->CacheDisable = CacheDisable;
PtePointer->WriteThrough = WriteThrough;
/* Set caching attributes */
PtePointer->Hardware.CacheDisable = CacheDisable;
PtePointer->Hardware.WriteThrough = WriteThrough;
}
/**
* Writes a Page Table Entry (PTE) with the specified value.
*
* @param Pte
* Pointer to the page table entry (PTE) to write.
*
* @param Value
* The value to write to the PTE.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::PageMap::WritePte(IN PMMPTE Pte,
IN MMPTE Value)
{
/* Write PTE value */
Pte->Long = Value.Long;
}
/**
* Gets the virtual address that is mapped by a given Page Directory Entry (PML4).
*
* @param PdePointer
* Specifies the address of the PDE.
*
* @return This routine returns the virtual address mapped by the PDE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::PageMapBasic::GetPdeVirtualAddress(IN PMMPDE PdePointer)
{
/* Return PDE virtual address */
return (PVOID)(((LONGLONG)PdePointer << 34) >> 16);
}
/**
* Gets the virtual address that is mapped by a given Page Directory Pointer Table Entry (PML4).
*
* @param PpePointer
* Specifies the address of the PPE.
*
* @return This routine returns the virtual address mapped by the PPE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::PageMapBasic::GetPpeVirtualAddress(IN PMMPPE PpePointer)
{
/* Return PPE virtual address */
return (PVOID)(((LONGLONG)PpePointer << 43) >> 16);
}
/**
* Gets the virtual address that is mapped by a given Page Table Entry (PML4).
*
* @param PtePointer
* Specifies the address of the PTE.
*
* @return This routine returns the virtual address mapped by the PTE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::PageMapBasic::GetPteVirtualAddress(IN PMMPTE PtePointer)
{
/* Return PTE virtual address */
return (PVOID)(((LONGLONG)PtePointer << 25) >> 16);
}
/**
* Gets the virtual address that is mapped by a given Extended Page Entry (PML4).
*
* @param PxePointer
* Specifies the address of the PXE.
*
* @return This routine returns the virtual address mapped by the PXE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::PageMapBasic::GetPxeVirtualAddress(IN PMMPXE PxePointer)
{
/* Return PXE virtual address */
return (PVOID)(((LONGLONG)PxePointer << 52) >> 16);
}
/**
@@ -218,6 +662,9 @@ MM::PageMapBasic::InitializePageMapInfo(VOID)
/* Set PML4 page map information */
PageMapInfo.Xpa = FALSE;
/* Set PML4 empty PTE list mask */
PageMapInfo.EmptyPteList = 0xFFFFFFFFUI64;
/* Set PML4 base addresses */
PageMapInfo.PteBase = MM_PTE_BASE;
PageMapInfo.PdeBase = MM_PDE_BASE;
@@ -229,6 +676,78 @@ MM::PageMapBasic::InitializePageMapInfo(VOID)
PageMapInfo.VaBits = 48;
}
/**
* Gets the virtual address that is mapped by a given Page Directory Entry (PML5).
*
* @param PdePointer
* Specifies the address of the PDE.
*
* @return This routine returns the virtual address mapped by the PDE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::PageMapXpa::GetPdeVirtualAddress(IN PMMPDE PdePointer)
{
/* Return PDE virtual address */
return (PVOID)(((LONGLONG)PdePointer << 25) >> 7);
}
/**
* Gets the virtual address that is mapped by a given Page Directory Pointer Table Entry (PML5).
*
* @param PpePointer
* Specifies the address of the PPE.
*
* @return This routine returns the virtual address mapped by the PPE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::PageMapXpa::GetPpeVirtualAddress(IN PMMPPE PpePointer)
{
/* Return PPE virtual address */
return (PVOID)(((LONGLONG)PpePointer << 34) >> 7);
}
/**
* Gets the virtual address that is mapped by a given Page Table Entry (PML5).
*
* @param PtePointer
* Specifies the address of the PTE.
*
* @return This routine returns the virtual address mapped by the PTE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::PageMapXpa::GetPteVirtualAddress(IN PMMPTE PtePointer)
{
/* Return PTE virtual address */
return (PVOID)(((LONGLONG)PtePointer << 16) >> 7);
}
/**
* Gets the virtual address that is mapped by a given Extended Page Entry (PML5).
*
* @param PxePointer
* Specifies the address of the PXE.
*
* @return This routine returns the virtual address mapped by the PXE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::PageMapXpa::GetPxeVirtualAddress(IN PMMPXE PxePointer)
{
/* Return PXE virtual address */
return (PVOID)(((LONGLONG)PxePointer << 43) >> 7);
}
/**
* Initializes page map information for XPA paging (PML5).
*
@@ -243,6 +762,9 @@ MM::PageMapXpa::InitializePageMapInfo(VOID)
/* Set PML5 page map information */
PageMapInfo.Xpa = TRUE;
/* Set PML5 empty PTE list mask */
PageMapInfo.EmptyPteList = 0xFFFFFFFFUI64;
/* Set PML5 base addresses */
PageMapInfo.PteBase = MM_PTE_LA57_BASE;
PageMapInfo.PdeBase = MM_PDE_LA57_BASE;

View File

@@ -25,6 +25,78 @@ MM::Paging::GetExtendedPhysicalAddressingStatus(VOID)
return ((AR::CpuFunc::ReadControlRegister(4) & CR4_LA57) != 0) ? TRUE : FALSE;
}
/**
* Gets the address of the P5E (Page Map Level 5 Entry), that maps given address.
*
* @param Address
* Specifies the virtual address for which to retrieve the corresponding P5E.
*
* @return This routine returns the address of the P5E, or NULLPTR if LA57 is not enabled.
*
* @since XT 1.0
*/
XTAPI
PMMP5E
MM::Paging::GetP5eAddress(IN PVOID Address)
{
/* Return PDE address */
return PmlRoutines->GetP5eAddress(Address);
}
/**
* Gets the virtual address that is mapped by a given Page Map Level 5 Entry.
*
* @param P5ePointer
* Specifies the address of the P5E.
*
* @return This routine returns the virtual address mapped by the P5E, or NULLPTR if LA57 is not enabled.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::Paging::GetP5eVirtualAddress(IN PMMP5E P5ePointer)
{
/* Return PTE virtual address */
return PmlRoutines->GetP5eVirtualAddress(P5ePointer);
}
/**
* Gets the address of the PXE (Extended Page Entry), that maps given address.
*
* @param Address
* Specifies the virtual address for which to retrieve the corresponding PXE.
*
* @return This routine returns the address of the PXE.
*
* @since XT 1.0
*/
XTAPI
PMMPXE
MM::Paging::GetPxeAddress(IN PVOID Address)
{
/* Return PXE address */
return PmlRoutines->GetPxeAddress(Address);
}
/**
* Gets the virtual address that is mapped by a given Extended Page Entry.
*
* @param PxePointer
* Specifies the address of the PXE.
*
* @return This routine returns the virtual address mapped by the PXE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::Paging::GetPxeVirtualAddress(IN PMMPXE PxePointer)
{
/* Return PXE virtual address */
return PmlRoutines->GetPxeVirtualAddress(PxePointer);
}
/**
* Fills a section of memory with zeroes like RtlZeroMemory(), but in more efficient way.
*

296
xtoskrnl/mm/amd64/pte.cc Normal file
View File

@@ -0,0 +1,296 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/mm/amd64/pte.cc
* DESCRIPTION: Page Table Entry (PTE) for AMD64 support
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Checks if the virtual address is valid and mapped in the page tables.
*
* @param VirtualAddress
* The virtual address to check.
*
* @return This routine returns TRUE if the address is valid, or FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
MM::Pte::AddressValid(IN PVOID VirtualAddress)
{
/* Check XPA status */
if(MM::Paging::GetXpaStatus())
{
/* Check if the P5E is valid */
if(!MM::Paging::PteValid(MM::Paging::GetP5eAddress(VirtualAddress)))
{
/* Invalid P5E, return FALSE */
return FALSE;
}
}
/* Check if PXE, PPE, PDE and PTE are valid */
if(!MM::Paging::PteValid(MM::Paging::GetPxeAddress(VirtualAddress)) ||
!MM::Paging::PteValid(MM::Paging::GetPpeAddress(VirtualAddress)) ||
!MM::Paging::PteValid(MM::Paging::GetPdeAddress(VirtualAddress)) ||
!MM::Paging::PteValid(MM::Paging::GetPteAddress(VirtualAddress)))
{
/* Invalid PXE, PPE, PDE or PTE, return FALSE */
return FALSE;
}
/* Address is valid, return TRUE */
return TRUE;
}
/**
* Retrieves the base virtual address of the system PTEs.
*
* @return This routine returns a pointer to the first PTE in the system PTE space.
*
* @since XT 1.0
*/
XTAPI
PMMPTE
MM::Pte::GetSystemPteBaseAddress(VOID)
{
PMMMEMORY_LAYOUT MemoryLayout;
/* Retrieve the system's memory layout */
MemoryLayout = MM::Manager::GetMemoryLayout();
/* Determine the base address for system PTEs based on the paging mode */
if(MM::Paging::GetXpaStatus())
{
/* For 5-level paging, system PTEs start at the beginning of system space */
return MM::Paging::GetPteAddress((PVOID)MemoryLayout->SystemSpaceStart);
}
else
{
/* For 4-level paging, system PTEs start at the legacy KSEG0_BASE */
return MM::Paging::GetPteAddress((PVOID)KSEG0_BASE);
}
}
/**
* Performs the initial setup of the system's page table hierarchy.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Pte::InitializePageTable(VOID)
{
PMMPTE EndSpacePte, PointerPte;
PMMMEMORY_LAYOUT MemoryLayout;
PVOID MappingRange;
MMPTE TemplatePte;
BOOLEAN Xpa;
/* Retrieve current paging mode and memory layout */
Xpa = MM::Paging::GetXpaStatus();
MemoryLayout = MM::Manager::GetMemoryLayout();
/* Enable the Global Paging (PGE) feature */
AR::CpuFunc::WriteControlRegister(4, AR::CpuFunc::ReadControlRegister(4) | CR4_PGE);
/* Check XPA status */
if(Xpa)
{
/* Get the PML5 user-space range if 5-level paging is active */
PointerPte = MM::Paging::GetP5eAddress(0);
EndSpacePte = MM::Paging::GetP5eAddress(MemoryLayout->UserSpaceEnd);
}
else
{
/* Otherwise, get the PML4 user-space range for 4-level paging */
PointerPte = MM::Paging::GetPxeAddress(0);
EndSpacePte = MM::Paging::GetPxeAddress(MemoryLayout->UserSpaceEnd);
}
/* Clear all top-level entries mapping the user address space */
while(PointerPte <= EndSpacePte)
{
MM::Paging::ClearPte(PointerPte);
PointerPte = MM::Paging::GetNextPte(PointerPte);
}
/* Flush the TLB to invalidate all non-global entries */
AR::CpuFunc::FlushTlb();
/* Create a template PTE for mapping kernel pages */
MM::Paging::ClearPte(&TemplatePte);
MM::Paging::SetPte(&TemplatePte, 0, MM_PTE_READWRITE | MM_PTE_CACHE_ENABLE);
/* Check XPA status */
if(Xpa)
{
/* Map the kernel's PML5 entries if 5-level paging is active */
MM::Pte::MapP5E(MemoryLayout->HyperSpaceStart, (PVOID)MM_HIGHEST_SYSTEM_ADDRESS, &TemplatePte);
}
/* Map the kernel's PML4 entries */
MM::Pte::MapPXE(MemoryLayout->HyperSpaceStart, (PVOID)MM_HIGHEST_SYSTEM_ADDRESS, &TemplatePte);
/* Calculate the end address of the hyperspace working set mapping */
MappingRange = (PVOID)((ULONG_PTR)MemoryLayout->HyperSpaceStart + MM_HYPERSPACE_PAGE_COUNT * MM_PAGE_SIZE);
/* Map the PDPT entries for paged pool and hyperspace */
MM::Pte::MapPPE(MemoryLayout->PagedPoolStart, MemoryLayout->PagedPoolEnd, &ValidPte);
MM::Pte::MapPPE(MemoryLayout->HyperSpaceStart, MemoryLayout->HyperSpaceEnd, &ValidPte);
/* Map the PDEs for the hyperspace working set */
MM::Pte::MapPDE(MemoryLayout->HyperSpaceStart, MappingRange, &ValidPte);
/* Set the hyperspace working set's PTE with the total PTE count */
MM::Paging::SetPte(MM::Paging::GetPteAddress((PVOID)MemoryLayout->HyperSpaceStart), MM_HYPERSPACE_PAGE_COUNT, 0);
}
/**
* Maps a range of virtual addresses at the P5E (PML5) level.
*
* @param StartAddress
* The beginning of the virtual address range to map.
*
* @param EndAddress
* The end of the virtual address range to map.
*
* @param TemplateP5e
* A template P5E to use for creating new entries.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Pte::MapP5E(PVOID StartAddress,
PVOID EndAddress,
PMMP5E TemplateP5e)
{
PMMP5E EndSpace, PointerP5e;
/* Get P5E addresses */
PointerP5e = MM::Paging::GetP5eAddress(StartAddress);
EndSpace = MM::Paging::GetP5eAddress(EndAddress);
/* Iterate over all P5Es */
while(PointerP5e <= EndSpace)
{
/* Check if P5E is already mapped */
if(!MM::Paging::PteValid(PointerP5e))
{
/* Map P5E */
MM::Paging::SetPte(TemplateP5e, MM::Pfn::AllocateBootstrapPages(1), 0);
*PointerP5e = *TemplateP5e;
/* Clear the page table */
RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerP5e), MM_PAGE_SIZE);
}
/* Get next table entry */
PointerP5e = MM::Paging::GetNextPte(PointerP5e);
}
}
/**
* Maps a range of virtual addresses at the PPE (Page Directory Pointer Entry) level.
*
* @param StartAddress
* The beginning of the virtual address range to map.
*
* @param EndAddress
* The end of the virtual address range to map.
*
* @param TemplatePpe
* A template PPE to use for creating new entries.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Pte::MapPPE(PVOID StartAddress,
PVOID EndAddress,
PMMPPE TemplatePpe)
{
PMMPPE EndSpace, PointerPpe;
/* Get PPE addresses */
PointerPpe = MM::Paging::GetPpeAddress(StartAddress);
EndSpace = MM::Paging::GetPpeAddress(EndAddress);
/* Iterate over all PPEs */
while(PointerPpe <= EndSpace)
{
/* Check if PPE is already mapped */
if(!MM::Paging::PteValid(PointerPpe))
{
/* Map PPE */
MM::Paging::SetPte(TemplatePpe, MM::Pfn::AllocateBootstrapPages(1), 0);
*PointerPpe = *TemplatePpe;
/* Clear the page table */
RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPpe), MM_PAGE_SIZE);
}
/* Get next table entry */
PointerPpe = MM::Paging::GetNextPte(PointerPpe);
}
}
/**
* Maps a range of virtual addresses at the PXE (PML4) level.
*
* @param StartAddress
* The beginning of the virtual address range to map.
*
* @param EndAddress
* The end of the virtual address range to map.
*
* @param TemplatePxe
* A template PXE to use for creating new entries.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Pte::MapPXE(PVOID StartAddress,
PVOID EndAddress,
PMMPXE TemplatePxe)
{
PMMPXE EndSpace, PointerPxe;
/* Get PXE addresses */
PointerPxe = MM::Paging::GetPxeAddress(StartAddress);
EndSpace = MM::Paging::GetPxeAddress(EndAddress);
/* Iterate over all PTEs */
while(PointerPxe <= EndSpace)
{
/* Check if PTE is already mapped */
if(!MM::Paging::PteValid(PointerPxe))
{
/* Map PTE */
MM::Paging::SetPte(TemplatePxe, MM::Pfn::AllocateBootstrapPages(1), 0);
*PointerPxe = *TemplatePxe;
/* Clear the page table */
RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPxe), MM_PAGE_SIZE);
}
/* Get next table entry */
PointerPxe = MM::Paging::GetNextPte(PointerPxe);
}
}

95
xtoskrnl/mm/colors.cc Normal file
View File

@@ -0,0 +1,95 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/mm/colors.cc
* DESCRIPTION: Memory manager page coloring subsystem
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Computes & initializes the system's page coloring.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Colors::ComputePageColoring(VOID)
{
UNIMPLEMENTED;
/* Compute L2 paging colors and mask */
PagingColors = MM_PAGING_COLORS;
PagingColorsMask = PagingColors - 1;
}
/**
* Retrieves a pointer to the color table for a specific page list and color.
*
* @param PageList
* The page list type (e.g., FreePageList, ZeroedPageList).
*
* @param Color
* Supplies the specific color index.
*
* @return This routine returns a pointer to the corresponding MMCOLOR_TABLES structure.
*
* @since XT 1.0
*/
XTAPI
PMMCOLOR_TABLES
MM::Colors::GetFreePages(MMPAGELISTS PageList,
ULONG Color)
{
/* Return a pointer to the requested color table entry */
return &FreePages[PageList][Color];
}
/**
* Retrieves the next available color for page coloring.
*
* @return This routine returns the next color value, ensuring it stays within the valid color range.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::Colors::GetNextColor()
{
/* Increment the color counter and wrap it around using the mask */
return ((++PagingColors) & PagingColorsMask);
}
/**
* Retrieves the total number of page colors configured in the system.
*
* @return This routine returns the number of page colors.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::Colors::GetPagingColors()
{
/* Return the total number of page colors */
return PagingColors;
}
/**
* Retrieves the bitmask used for calculating a page's color.
*
* @return This routine returns the page color mask.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::Colors::GetPagingColorsMask()
{
/* Return the mask used for page coloring calculations */
return PagingColorsMask;
}

View File

@@ -9,6 +9,15 @@
#include <xtos.hh>
/* Array of free page lists segregated by cache color */
PMMCOLOR_TABLES MM::Colors::FreePages[FreePageList + 1];
/* Number of supported page colors */
ULONG MM::Colors::PagingColors;
/* Bitmask used to calculate the cache color index */
ULONG MM::Colors::PagingColorsMask;
/* Allocation descriptors dedicated for hardware layer */
LOADER_MEMORY_DESCRIPTOR MM::HardwarePool::HardwareAllocationDescriptors[MM_HARDWARE_ALLOCATION_DESCRIPTORS];
@@ -18,23 +27,53 @@ PVOID MM::HardwarePool::HardwareHeapStart = MM_HARDWARE_HEAP_START_ADDRESS;
/* Number of used hardware allocation descriptors */
ULONG MM::HardwarePool::UsedHardwareAllocationDescriptors = 0;
/* Biggest free memory descriptor */
PLOADER_MEMORY_DESCRIPTOR MM::Init::FreeDescriptor;
/* Highest physical page number */
ULONG_PTR MM::Init::HighestPhysicalPage;
/* Lowest physical page number */
ULONG_PTR MM::Init::LowestPhysicalPage = -1;
/* Number of physical pages */
ULONG MM::Init::NumberOfPhysicalPages;
/* Old biggest free memory descriptor */
LOADER_MEMORY_DESCRIPTOR MM::Init::OldFreeDescriptor;
/* Processor structures data (THIS IS A TEMPORARY HACK) */
UCHAR MM::KernelPool::ProcessorStructuresData[MAXIMUM_PROCESSORS][KPROCESSOR_STRUCTURES_SIZE] = {{0}};
/* Memory layout */
MMMEMORY_LAYOUT MM::Manager::MemoryLayout;
/* Number of system PTEs */
PFN_NUMBER MM::Manager::NumberOfSystemPtes;
/* Instance of the page map routines for the current PML level */
MM::PPAGEMAP MM::Paging::PmlRoutines;
/* Total number of physical pages available for allocation */
PFN_NUMBER MM::Pfn::AvailablePages;
/* Biggest free memory descriptor */
PLOADER_MEMORY_DESCRIPTOR MM::Pfn::FreeDescriptor;
/* Highest physical page number */
ULONG_PTR MM::Pfn::HighestPhysicalPage;
/* Lowest physical page number */
ULONG_PTR MM::Pfn::LowestPhysicalPage = -1;
/* Number of physical pages */
ULONGLONG MM::Pfn::NumberOfPhysicalPages;
/* Old biggest free memory descriptor */
LOADER_MEMORY_DESCRIPTOR MM::Pfn::OriginalFreeDescriptor;
/* Size of the PFN database in pages */
PFN_NUMBER MM::Pfn::PfnDatabaseSize;
/* Array of lists for available System PTEs, separated by pool type */
MMPTE MM::Pte::FirstSystemFreePte[MaximumPtePoolTypes];
/* Virtual base address of the System PTE space */
PMMPTE MM::Pte::SystemPteBase;
/* End addresses for the System PTE ranges */
PMMPTE MM::Pte::SystemPtesEnd[MaximumPtePoolTypes];
/* Start addresses for the System PTE ranges */
PMMPTE MM::Pte::SystemPtesStart[MaximumPtePoolTypes];
/* Total count of available System PTEs */
ULONG MM::Pte::TotalSystemFreePtes[MaximumPtePoolTypes];
/* Template PTE entry containing standard flags for a valid, present kernel page */
MMPTE MM::Pte::ValidPte = {MM_PTE_VALID|MM_PTE_EXECUTE_READWRITE|MM_PTE_DIRTY|MM_PTE_ACCESSED};

View File

@@ -170,7 +170,7 @@ MM::HardwarePool::MapHardwareMemory(IN PHYSICAL_ADDRESS PhysicalAddress,
{
PVOID BaseAddress, ReturnAddress;
PFN_NUMBER MappedPages;
PHARDWARE_PTE PtePointer;
PMMPTE PtePointer;
/* Initialize variables */
BaseAddress = HardwareHeapStart;
@@ -189,7 +189,7 @@ MM::HardwarePool::MapHardwareMemory(IN PHYSICAL_ADDRESS PhysicalAddress,
}
/* Get PTE pointer and advance to next page */
PtePointer = (PHARDWARE_PTE)MM::Paging::GetPteAddress(ReturnAddress);
PtePointer = MM::Paging::GetPteAddress(ReturnAddress);
ReturnAddress = (PVOID)((ULONG_PTR)ReturnAddress + MM_PAGE_SIZE);
/* Check if PTE is valid */
@@ -219,10 +219,10 @@ MM::HardwarePool::MapHardwareMemory(IN PHYSICAL_ADDRESS PhysicalAddress,
while(MappedPages--)
{
/* Get PTE pointer */
PtePointer = (PHARDWARE_PTE)MM::Paging::GetPteAddress(BaseAddress);
PtePointer = MM::Paging::GetPteAddress(BaseAddress);
/* Fill the PTE */
MM::Paging::SetPte(PtePointer, (PFN_NUMBER)(PhysicalAddress.QuadPart >> MM_PAGE_SHIFT), TRUE);
MM::Paging::SetPte(PtePointer, (PFN_NUMBER)(PhysicalAddress.QuadPart >> MM_PAGE_SHIFT), MM_PTE_READWRITE);
/* Advance to the next address */
PhysicalAddress.QuadPart += MM_PAGE_SIZE;
@@ -259,18 +259,18 @@ VOID
MM::HardwarePool::MarkHardwareMemoryWriteThrough(IN PVOID VirtualAddress,
IN PFN_NUMBER PageCount)
{
PHARDWARE_PTE PtePointer;
PMMPTE PtePointer;
PFN_NUMBER Page;
/* Get PTE address from virtual address */
PtePointer = (PHARDWARE_PTE)MM::Paging::GetPteAddress(VirtualAddress);
PtePointer = MM::Paging::GetPteAddress(VirtualAddress);
/* Iterate through mapped pages */
for(Page = 0; Page < PageCount; Page++)
{
/* Mark pages as CD/WT */
MM::Paging::SetPteCaching(PtePointer, TRUE, TRUE);
PtePointer++;
MM::Paging::GetNextEntry(PtePointer);
}
}
@@ -296,13 +296,13 @@ MM::HardwarePool::RemapHardwareMemory(IN PVOID VirtualAddress,
IN PHYSICAL_ADDRESS PhysicalAddress,
IN BOOLEAN FlushTlb)
{
PHARDWARE_PTE PtePointer;
PMMPTE PtePointer;
/* Get PTE address from virtual address */
PtePointer = (PHARDWARE_PTE)MM::Paging::GetPteAddress(VirtualAddress);
PtePointer = MM::Paging::GetPteAddress(VirtualAddress);
/* Remap the PTE */
MM::Paging::SetPte(PtePointer, (PFN_NUMBER)(PhysicalAddress.QuadPart >> MM_PAGE_SHIFT), TRUE);
MM::Paging::SetPte(PtePointer, (PFN_NUMBER)(PhysicalAddress.QuadPart >> MM_PAGE_SHIFT), MM_PTE_READWRITE);
/* Check if TLB needs to be flushed */
if(FlushTlb)
@@ -334,7 +334,7 @@ MM::HardwarePool::UnmapHardwareMemory(IN PVOID VirtualAddress,
IN PFN_NUMBER PageCount,
IN BOOLEAN FlushTlb)
{
PHARDWARE_PTE PtePointer;
PMMPTE PtePointer;
PFN_NUMBER Page;
/* Check if address is valid hardware memory */
@@ -348,7 +348,7 @@ MM::HardwarePool::UnmapHardwareMemory(IN PVOID VirtualAddress,
VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress & ~(MM_PAGE_SIZE - 1));
/* Get PTE address from virtual address */
PtePointer = (PHARDWARE_PTE)MM::Paging::GetPteAddress(VirtualAddress);
PtePointer = MM::Paging::GetPteAddress(VirtualAddress);
/* Iterate through mapped pages */
for(Page = 0; Page < PageCount; Page++)

View File

@@ -1,25 +0,0 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/mm/i686/init.cc
* DESCRIPTION: Architecture specific Memory Manager initialization routines
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
* Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Performs architecture specific initialization of the XTOS Memory Manager.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Init::InitializeArchitecture(VOID)
{
UNIMPLEMENTED;
}

84
xtoskrnl/mm/i686/mmgr.cc Normal file
View File

@@ -0,0 +1,84 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/mm/i686/mmgr.cc
* DESCRIPTION: Memory Manager
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Initializes the kernel's virtual memory layout.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Manager::InitializeMemoryLayout(VOID)
{
ULONG_PTR PagedPoolSize, PteCount;
PFN_NUMBER PfnDatabaseSize, PhysicalPages;
ULONG PtesPerPage;
/* Define the number of system PTEs */
NumberOfSystemPtes = MM_DEFAULT_NUMBER_SYSTEM_PTES;
/* Retrieve the number of physical pages */
PhysicalPages = MM::Pfn::GetNumberOfPhysicalPages();
/* Verify the number of physical pages */
if(PhysicalPages < 8192)
{
/* Less than 32MiB of physical memory (8192 pages), use the minimum number of system PTEs */
NumberOfSystemPtes = MM_MINIMUM_NUMBER_SYSTEM_PTES;
}
else if(PhysicalPages > 32768)
{
/* More than 128MiB of physical memory (32768 pages), use the maximum number of system PTEs */
NumberOfSystemPtes = MM_MAXIMUM_NUMBER_SYSTEM_PTES;
}
/* Check if 3-level paging (PAE) is enabled */
if(MM::Paging::GetXpaStatus())
{
/* Configure memory layout for 3-level paging, using 36bit address space and providing a 64 GB address space */
MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xB0000000;
MemoryLayout.SelfMapAddress = (PVOID)MM_PTE_BASE;
/* Define the non-paged and paged pool regions */
MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE);
MemoryLayout.NonPagedPoolEnd = (PVOID)0xEEFFFFFF;
MemoryLayout.PagedPoolStart = (PVOID)0xE2000000;
MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1);
/* Define hyperspace, system PTE space, and the user space limit */
MemoryLayout.HyperSpaceStart = (PVOID)0xC0800000;
MemoryLayout.HyperSpaceEnd = (PVOID)0xC0BFFFFF;
MemoryLayout.SystemSpaceStart = (PVOID)0xC0C00000;
MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE);
MemoryLayout.UserSpaceEnd = (PVOID)0x7FFEFFFF;
}
else
{
/* Configure memory layout for 2-level paging, using 32bit address space and providing a 4 GB address space */
MemoryLayout.PfnDatabaseAddress = (PMMPFN)0xB0000000;
MemoryLayout.SelfMapAddress = (PVOID)MM_PTE_BASE;
/* Define the non-paged and paged pool regions */
MemoryLayout.NonPagedPoolStart = (PVOID)((ULONG_PTR)MemoryLayout.PfnDatabaseAddress + PfnDatabaseSize * MM_PAGE_SIZE);
MemoryLayout.NonPagedPoolEnd = (PVOID)0xFFBE0000;
MemoryLayout.PagedPoolStart = (PVOID)0xE1000000;
MemoryLayout.PagedPoolEnd = (PVOID)(((ULONG_PTR)MemoryLayout.PagedPoolStart + PagedPoolSize) - 1);
/* Define hyperspace, system PTE space, and the user space limit */
MemoryLayout.HyperSpaceStart = (PVOID)0xC0400000;
MemoryLayout.HyperSpaceEnd = (PVOID)0xC07FFFFF;
MemoryLayout.SystemSpaceStart = (PVOID)0xC0800000;
MemoryLayout.SystemSpaceEnd = (PVOID)((ULONG_PTR)MemoryLayout.SystemSpaceStart + (NumberOfSystemPtes + 1) * MM_PAGE_SIZE);
MemoryLayout.UserSpaceEnd = (PVOID)0x7FFEFFFF;
}
}

View File

@@ -10,20 +10,18 @@
/**
* Clears the contents of a page table entry (PTE).
* Gets the value representing an empty PTE list.
*
* @param PtePointer
* Pointer to the page table entry (PTE) to be cleared.
*
* @return This routine does not return any value.
* @return This routine returns the value representing an empty PTE list.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::PageMap::ClearPte(PHARDWARE_PTE PtePointer)
ULONG
MM::PageMap::GetEmptyPteList(VOID)
{
PtePointer->Long = 0;
/* Return empty PTE list mask */
return PageMapInfo.EmptyPteList;
}
/**
@@ -38,7 +36,7 @@ MM::PageMap::ClearPte(PHARDWARE_PTE PtePointer)
*/
XTAPI
PMMPDE
MM::PageMap::GetPdeAddress(PVOID Address)
MM::PageMap::GetPdeAddress(IN PVOID Address)
{
ULONG Offset;
@@ -47,6 +45,25 @@ MM::PageMap::GetPdeAddress(PVOID Address)
return (PMMPDE)(PageMapInfo.PdeBase + Offset);
}
/**
* Gets the Offset of the PDE (Page Directory Entry), that maps given address.
*
* @param Address
* Specifies the virtual address for which to retrieve the corresponding PDE.
*
* @return This routine returns the Offset of the PDE.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::PageMap::GetPdeOffset(IN PVOID Address)
{
/* Return PDE Offset */
return ((((ULONG_PTR)(Address)) >> PageMapInfo.PdiShift) & (PageMapInfo.Xpa ? 0x1FF : 0x3FF));
}
/**
* Gets the address of the PPE (Page Directory Pointer Table Entry), that maps given address.
*
@@ -59,12 +76,48 @@ MM::PageMap::GetPdeAddress(PVOID Address)
*/
XTAPI
PMMPPE
MM::PageMap::GetPpeAddress(PVOID Address)
MM::PageMap::GetPpeAddress(IN PVOID Address)
{
/* Return zero */
return (PMMPPE)0;
}
/**
* Gets the offset of the PPE (Page Directory Pointer Table Entry), that maps given address.
*
* @param Address
* Specifies the virtual address for which to retrieve the corresponding PPE.
*
* @return This routine returns the offset of the PPE.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::PageMap::GetPpeOffset(IN PVOID Address)
{
/* Return zero */
return 0;
}
/**
* Gets the virtual address that is mapped by a given Page Directory Pointer Table Entry.
*
* @param PpePointer
* Specifies the virtual address of the PPE.
*
* @return This routine returns the virtual address mapped by the PPE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::PageMap::GetPpeVirtualAddress(IN PMMPPE PpePointer)
{
/* Return zero */
return (PVOID)0;
}
/**
* Gets the address of the PTE (Page Table Entry), that maps given address.
*
@@ -77,13 +130,247 @@ MM::PageMap::GetPpeAddress(PVOID Address)
*/
XTAPI
PMMPTE
MM::PageMap::GetPteAddress(PVOID Address)
MM::PageMap::GetPteAddress(IN PVOID Address)
{
ULONG Offset;
/* Calculate offset and return PTE address */
Offset = ((((ULONG_PTR)(Address)) >> MM_PTI_SHIFT) << PageMapInfo.PteShift);
return (PMMPTE)(MM_PTE_BASE + Offset);
return (PMMPTE)(PageMapInfo.PteBase + Offset);
}
/**
* Gets the Offset of the PTE (Page Table Entry), that maps given address.
*
* @param Address
* Specifies the virtual address for which to retrieve the corresponding PTE.
*
* @return This routine returns the Offset of the PTE.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::PageMap::GetPteOffset(IN PVOID Address)
{
/* Return PTE Offset */
return ((((ULONG_PTR)(Address)) >> MM_PTI_SHIFT) & (PageMapInfo.Xpa ? 0x1FF : 0x3FF));
}
/**
* Gets the status of Extended Paging Address (XPA) mode.
*
* @return This routine returns TRUE if XPA is enabled, FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
MM::PageMap::GetXpaStatus()
{
return PageMapInfo.Xpa;
}
/**
* Advances a PTE pointer by a given number of entries, considering the actual PTE size for PML2.
*
* @param Pte
* The PTE pointer to advance.
*
* @param Count
* The number of PTE entries to advance by.
*
* @return This routine returns the advanced PTE pointer.
*
* @since XT 1.0
*/
XTAPI
PMMPTE
MM::PageMapBasic::AdvancePte(IN PMMPTE Pte,
IN ULONG Count)
{
/* Return advanced PTE pointer */
return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPML2_PTE)));
}
/**
* Clears the contents of a page table entry (PTE).
*
* @param PtePointer
* Pointer to the page table entry (PTE) to be cleared.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::PageMapBasic::ClearPte(IN PMMPTE PtePointer)
{
/* Clear PTE */
PtePointer->Pml2.Long = 0;
}
/**
* Gets the next entry in a PTE list.
*
* @param Pte
* The PTE pointer to get the next entry from.
*
* @return This routine returns the next entry in the PTE list.
*
* @since XT 1.0
*/
XTAPI
ULONG_PTR
MM::PageMapBasic::GetNextEntry(IN PMMPTE Pte)
{
/* Return next entry in PTE list, translating the hardware limit (0xFFFFF) to the logical sentinel (MAXULONG) */
return (Pte->Pml2.List.NextEntry == 0xFFFFF) ? MAXULONG : Pte->Pml2.List.NextEntry;
}
/**
* Advances a PTE pointer, considering the actual PTE size for PML2.
*
* @param Pte
* The PTE pointer to advance.
*
* @return The advanced PTE pointer.
*
* @since XT 1.0
*/
XTAPI
PMMPTE
MM::PageMapBasic::GetNextPte(IN PMMPTE Pte)
{
/* Return advanced PTE pointer */
return AdvancePte(Pte, 1);
}
/**
* Checks if a PTE list contains only one entry.
*
* @param Pte
* The PTE pointer to check.
*
* @return This routine returns TRUE if the PTE list has only one entry, FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
MM::PageMapBasic::GetOneEntry(IN PMMPTE Pte)
{
/* Return one entry status */
return Pte->Pml2.List.OneEntry;
}
/**
* Gets the page frame number from a corresponding PTE.
*
* @param Pte
* The PTE pointer to get the page frame number from.
*
* @return This routine returns the page frame number.
*
* @since XT 1.0
*/
XTAPI
PFN_NUMBER
MM::PageMapBasic::GetPageFrameNumber(IN PMMPTE Pte)
{
return Pte->Pml2.Hardware.PageFrameNumber;
}
/**
* Gets the virtual address that is mapped by a given Page Directory Entry.
*
* @param PdePointer
* Specifies the address of the PDE.
*
* @return This routine returns the virtual address mapped by the PDE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::PageMapBasic::GetPdeVirtualAddress(IN PMMPDE PdePointer)
{
/* Return PDE virtual address */
return ((PVOID)((ULONG)(PdePointer) << 20));
}
/**
* Gets the entire contents of a PML2 Page Table Entry (PTE) as a single value.
*
* @param PtePointer
* Pointer to the Page Table Entry (PTE) to read.
*
* @return This routine returns the contents of the PTE as a single value.
*
* @since XT 1.0
*/
XTAPI
ULONG_PTR
MM::PageMapBasic::GetPte(IN PMMPTE PtePointer)
{
/* Return PTE value */
return PtePointer->Pml2.Long;
}
/**
* Calculates the distance between two PTE pointers.
*
* @param EndPte
* Pointer to the ending Page Table Entry.
*
* @param StartPte
* Pointer to the starting Page Table Entry.
*
* @return This routine returns a signed value representing the number of PTEs between EndPte and StartPte.
*
* @since XT 1.0
*/
XTAPI
LONG
MM::PageMapBasic::GetPteDistance(PMMPTE EndPte,
PMMPTE StartPte)
{
/* Return distance between PTE pointers */
return ((ULONG_PTR)EndPte - (ULONG_PTR)StartPte) / sizeof(MMPML2_PTE);
}
/**
* Gets the size of a PTE for basic paging (PML2).
*
* @return This routine returns the size of a PTE.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::PageMapBasic::GetPteSize(VOID)
{
/* Return the size of MMPTE */
return sizeof(MMPML2_PTE);
}
/**
* Gets the virtual address that is mapped by a given Page Table Entry.
*
* @param PtePointer
* Specifies the virtual address of the PTE.
*
* @return This routine returns the virtual address mapped by the PTE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::PageMapBasic::GetPteVirtualAddress(IN PMMPTE PtePointer)
{
/* Return PTE virtual address */
return ((PVOID)((ULONG)(PtePointer) << 10));
}
/**
@@ -100,6 +387,9 @@ MM::PageMapBasic::InitializePageMapInfo(VOID)
/* Set PML2 page map information */
PageMapInfo.Xpa = FALSE;
/* Set PML2 empty PTE list mask */
PageMapInfo.EmptyPteList = (ULONG)0xFFFFF;
/* Set PML2 base addresses */
PageMapInfo.PteBase = MM_PTE_BASE;
PageMapInfo.PdeBase = MM_PDE_LEGACY_BASE;
@@ -121,9 +411,54 @@ MM::PageMapBasic::InitializePageMapInfo(VOID)
*/
XTAPI
BOOLEAN
MM::PageMapBasic::PteValid(PHARDWARE_PTE PtePointer)
MM::PageMapBasic::PteValid(IN PMMPTE PtePointer)
{
return (BOOLEAN)PtePointer->Pml2.Valid;
/* Check if PTE is valid */
return (BOOLEAN)PtePointer->Pml2.Hardware.Valid;
}
/**
* Sets the next entry in a PTE list.
*
* @param Pte
* The PTE pointer to modify.
*
* @param Value
* The value to set as the next entry.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::PageMapBasic::SetNextEntry(IN PMMPTE Pte,
IN ULONG_PTR Value)
{
/* Set next entry in PTE list, translating the logical sentinel (MAXULONG) to the 20-bit hardware limit (0xFFFFF) */
Pte->Pml2.List.NextEntry = (Value == MAXULONG) ? 0xFFFFF : Value;
}
/**
* Sets the flag indicating whether a PTE list contains only one entry.
*
* @param Pte
* The PTE pointer to modify.
*
* @param Value
* The value to set. TRUE if the list has only one entry, FALSE otherwise.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::PageMapBasic::SetOneEntry(IN PMMPTE Pte,
IN BOOLEAN Value)
{
/* Set one entry status */
Pte->Pml2.List.OneEntry = Value;
}
/**
@@ -135,8 +470,8 @@ MM::PageMapBasic::PteValid(PHARDWARE_PTE PtePointer)
* @param PageFrameNumber
* Physical frame number to map.
*
* @param Writable
* Indicates whether the page should be writable.
* @param AttributesMask
* Specifies the attributes mask to apply to the PTE.
*
* @return This routine does not return any value.
*
@@ -144,13 +479,35 @@ MM::PageMapBasic::PteValid(PHARDWARE_PTE PtePointer)
*/
XTAPI
VOID
MM::PageMapBasic::SetPte(PHARDWARE_PTE PtePointer,
PFN_NUMBER PageFrameNumber,
BOOLEAN Writable)
MM::PageMapBasic::SetPte(IN PMMPTE PtePointer,
IN PFN_NUMBER PageFrameNumber,
IN ULONG_PTR AttributesMask)
{
PtePointer->Pml2.PageFrameNumber = PageFrameNumber;
PtePointer->Pml2.Valid = 1;
PtePointer->Pml2.Writable = Writable;
/* Set PTE */
PtePointer->Pml2.Hardware.PageFrameNumber = PageFrameNumber;
PtePointer->Pml2.Hardware.Valid = 1;
PtePointer->Pml2.Long |= AttributesMask;
}
/**
* Sets a PML2 page table entry (PTE) with the specified attributes.
*
* @param PtePointer
* Pointer to the page table entry (PTE) to set.
*
* @param Attributes
* Specifies the attributes to apply to the PTE.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::PageMapBasic::SetPte(IN PMMPTE PtePointer,
IN ULONG_PTR Attributes)
{
PtePointer->Pml2.Long = Attributes;
}
/**
@@ -171,12 +528,237 @@ MM::PageMapBasic::SetPte(PHARDWARE_PTE PtePointer,
*/
XTAPI
VOID
MM::PageMapBasic::SetPteCaching(PHARDWARE_PTE PtePointer,
BOOLEAN CacheDisable,
BOOLEAN WriteThrough)
MM::PageMapBasic::SetPteCaching(IN PMMPTE PtePointer,
IN BOOLEAN CacheDisable,
IN BOOLEAN WriteThrough)
{
PtePointer->Pml2.CacheDisable = CacheDisable;
PtePointer->Pml2.WriteThrough = WriteThrough;
/* Set caching attributes */
PtePointer->Pml2.Hardware.CacheDisable = CacheDisable;
PtePointer->Pml2.Hardware.WriteThrough = WriteThrough;
}
/**
* Writes a PML2 page table entry (PTE) with the specified value.
*
* @param Pte
* Pointer to the page table entry (PTE) to write.
*
* @param Value
* The value to write to the PTE.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::PageMapBasic::WritePte(IN PMMPTE Pte,
IN MMPTE Value)
{
/* Write PTE value */
Pte->Pml2.Long = Value.Pml2.Long;
}
/**
* Advances a PTE pointer by a given number of entries, considering the actual PTE size for PML3.
*
* @param Pte
* The PTE pointer to advance.
*
* @param Count
* The number of PTE entries to advance by.
*
* @return The advanced PTE pointer.
*
* @since XT 1.0
*/
XTAPI
PMMPTE
MM::PageMapXpa::AdvancePte(IN PMMPTE Pte,
IN ULONG Count)
{
/* Return advanced PTE pointer */
return (PMMPTE)((ULONG_PTR)Pte + (Count * sizeof(MMPML3_PTE)));
}
/**
* Clears the contents of a page table entry (PTE).
*
* @param PtePointer
* Pointer to the page table entry (PTE) to be cleared.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::PageMapXpa::ClearPte(IN PMMPTE PtePointer)
{
/* Clear PTE */
PtePointer->Pml3.Long = 0;
}
/**
* Gets the next entry in a PTE list.
*
* @param Pte
* The PTE pointer to get the next entry from.
*
* @return This routine returns the next entry in the PTE list.
*
* @since XT 1.0
*/
XTAPI
ULONG_PTR
MM::PageMapXpa::GetNextEntry(IN PMMPTE Pte)
{
/* Return next entry in PTE list */
return Pte->Pml3.List.NextEntry;
}
/**
* Advances a PTE pointer, considering the actual PTE size for PML3.
*
* @param Pte
* The PTE pointer to advance.
*
* @return The advanced PTE pointer.
*
* @since XT 1.0
*/
XTAPI
PMMPTE
MM::PageMapXpa::GetNextPte(IN PMMPTE Pte)
{
/* Return advanced PTE pointer */
return AdvancePte(Pte, 1);
}
/**
* Checks if a PTE list contains only one entry.
*
* @param Pte
* The PTE pointer to check.
*
* @return This routine returns TRUE if the PTE list has only one entry, FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
MM::PageMapXpa::GetOneEntry(IN PMMPTE Pte)
{
/* Return one entry status */
return Pte->Pml3.List.OneEntry;
}
/**
* Gets the page frame number from a corresponding PTE.
*
* @param Pte
* The PTE pointer to get the page frame number from.
*
* @return This routine returns the page frame number.
*
* @since XT 1.0
*/
XTAPI
PFN_NUMBER
MM::PageMapXpa::GetPageFrameNumber(IN PMMPTE Pte)
{
return Pte->Pml3.Hardware.PageFrameNumber;
}
/**
* Gets the virtual address that is mapped by a given Page Directory Entry.
*
* @param PdePointer
* Specifies the address of the PDE.
*
* @return This routine returns the virtual address mapped by the PDE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::PageMapXpa::GetPdeVirtualAddress(IN PMMPDE PdePointer)
{
/* Return PDE virtual address */
return ((PVOID)((ULONG)(PdePointer) << 18));
}
/**
* Gets the entire contents of a PML3 Page Table Entry (PTE) as a single value.
*
* @param PtePointer
* Pointer to the Page Table Entry (PTE) to read.
*
* @return This routine returns the contents of the PTE as a single value.
*
* @since XT 1.0
*/
XTAPI
ULONG_PTR
MM::PageMapXpa::GetPte(IN PMMPTE PtePointer)
{
/* Return PTE value */
return PtePointer->Pml3.Long;
}
/**
* Calculates the distance between two PTE pointers.
*
* @param EndPte
* Pointer to the ending Page Table Entry.
*
* @param StartPte
* Pointer to the starting Page Table Entry.
*
* @return This routine returns a signed value representing the number of PTEs between EndPte and StartPte.
*
* @since XT 1.0
*/
XTAPI
LONG
MM::PageMapXpa::GetPteDistance(PMMPTE EndPte,
PMMPTE StartPte)
{
/* Return distance between PTE pointers */
return ((ULONG_PTR)EndPte - (ULONG_PTR)StartPte) / sizeof(MMPML3_PTE);
}
/**
* Gets the size of a PTE for XPA paging (PML3).
*
* @return This routine returns the size of a PTE.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::PageMapXpa::GetPteSize(VOID)
{
/* Return the size of MMPTE */
return sizeof(MMPML3_PTE);
}
/**
* Gets the virtual address that is mapped by a given Page Table Entry.
*
* @param PtePointer
* Specifies the virtual address of the PTE.
*
* @return This routine returns the virtual address mapped by the PTE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::PageMapXpa::GetPteVirtualAddress(IN PMMPTE PtePointer)
{
/* Return PTE virtual address */
return ((PVOID)((ULONG)(PtePointer) << 9));
}
/**
@@ -190,14 +772,17 @@ XTAPI
VOID
MM::PageMapXpa::InitializePageMapInfo(VOID)
{
/* Set PML2 page map information */
/* Set PML3 page map information */
PageMapInfo.Xpa = TRUE;
/* Set PML2 base addresses */
/* Set PML3 empty PTE list mask */
PageMapInfo.EmptyPteList = (ULONG)0xFFFFFFFF;
/* Set PML3 base addresses */
PageMapInfo.PteBase = MM_PTE_BASE;
PageMapInfo.PdeBase = MM_PDE_BASE;
/* Set PML2 shift values */
/* Set PML3 shift values */
PageMapInfo.PdiShift = MM_PDI_SHIFT;
PageMapInfo.PteShift = MM_PTE_SHIFT;
}
@@ -214,9 +799,53 @@ MM::PageMapXpa::InitializePageMapInfo(VOID)
*/
XTAPI
BOOLEAN
MM::PageMapXpa::PteValid(PHARDWARE_PTE PtePointer)
MM::PageMapXpa::PteValid(IN PMMPTE PtePointer)
{
return (BOOLEAN)PtePointer->Pml3.Valid;
return (BOOLEAN)PtePointer->Pml3.Hardware.Valid;
}
/**
* Sets the next entry in a PTE list.
*
* @param Pte
* The PTE pointer to modify.
*
* @param Value
* The value to set as the next entry.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::PageMapXpa::SetNextEntry(IN PMMPTE Pte,
IN ULONG_PTR Value)
{
/* Set next entry in PTE list */
Pte->Pml3.List.NextEntry = Value;
}
/**
* Sets the flag indicating whether a PTE list contains only one entry.
*
* @param Pte
* The PTE pointer to modify.
*
* @param Value
* The value to set. TRUE if the list has only one entry, FALSE otherwise.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::PageMapXpa::SetOneEntry(IN PMMPTE Pte,
IN BOOLEAN Value)
{
/* Set one entry status */
Pte->Pml3.List.OneEntry = Value;
}
/**
@@ -228,8 +857,8 @@ MM::PageMapXpa::PteValid(PHARDWARE_PTE PtePointer)
* @param PageFrameNumber
* Physical frame number to map.
*
* @param Writable
* Indicates whether the page should be writable.
* @param AttributesMask
* Specifies the attributes mask to apply to the PTE.
*
* @return This routine does not return any value.
*
@@ -237,13 +866,35 @@ MM::PageMapXpa::PteValid(PHARDWARE_PTE PtePointer)
*/
XTAPI
VOID
MM::PageMapXpa::SetPte(PHARDWARE_PTE PtePointer,
PFN_NUMBER PageFrameNumber,
BOOLEAN Writable)
MM::PageMapXpa::SetPte(IN PMMPTE PtePointer,
IN PFN_NUMBER PageFrameNumber,
IN ULONG_PTR AttributesMask)
{
PtePointer->Pml3.PageFrameNumber = PageFrameNumber;
PtePointer->Pml3.Valid = 1;
PtePointer->Pml3.Writable = Writable;
/* Set PTE */
PtePointer->Pml3.Hardware.PageFrameNumber = PageFrameNumber;
PtePointer->Pml3.Hardware.Valid = 1;
PtePointer->Pml3.Long |= AttributesMask;
}
/**
* Sets a PML3 page table entry (PTE) with the specified attributes.
*
* @param PtePointer
* Pointer to the page table entry (PTE) to set.
*
* @param Attributes
* Specifies the attributes to apply to the PTE.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::PageMapXpa::SetPte(IN PMMPTE PtePointer,
IN ULONG_PTR Attributes)
{
PtePointer->Pml3.Long = Attributes;
}
/**
@@ -264,10 +915,33 @@ MM::PageMapXpa::SetPte(PHARDWARE_PTE PtePointer,
*/
XTAPI
VOID
MM::PageMapXpa::SetPteCaching(PHARDWARE_PTE PtePointer,
BOOLEAN CacheDisable,
BOOLEAN WriteThrough)
MM::PageMapXpa::SetPteCaching(IN PMMPTE PtePointer,
IN BOOLEAN CacheDisable,
IN BOOLEAN WriteThrough)
{
PtePointer->Pml3.CacheDisable = CacheDisable;
PtePointer->Pml3.WriteThrough = WriteThrough;
/* Set caching attributes */
PtePointer->Pml3.Hardware.CacheDisable = CacheDisable;
PtePointer->Pml3.Hardware.WriteThrough = WriteThrough;
}
/**
* Writes a PML3 page table entry (PTE) with the specified value.
*
* @param Pte
* Pointer to the page table entry (PTE) to write.
*
* @param Value
* The value to write to the PTE.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::PageMapXpa::WritePte(IN PMMPTE Pte,
IN MMPTE Value)
{
/* Write PTE value */
Pte->Pml3.Long = Value.Pml3.Long;
}

139
xtoskrnl/mm/i686/pte.cc Normal file
View File

@@ -0,0 +1,139 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/mm/i686/pte.cc
* DESCRIPTION: Page Table Entry (PTE) for i686 support
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Checks if the virtual address is valid and mapped in the page tables.
*
* @param VirtualAddress
* The virtual address to check.
*
* @return This routine returns TRUE if the address is valid, or FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
MM::Pte::AddressValid(IN PVOID VirtualAddress)
{
/* Check XPA status */
if(MM::Paging::GetXpaStatus())
{
/* Check if the P5E is valid */
if(!MM::Paging::PteValid(MM::Paging::GetPpeAddress(VirtualAddress)))
{
/* Invalid PPE, return FALSE */
return FALSE;
}
}
/* Check if PDE and PTE are valid */
if(!MM::Paging::PteValid(MM::Paging::GetPdeAddress(VirtualAddress)) ||
!MM::Paging::PteValid(MM::Paging::GetPteAddress(VirtualAddress)))
{
/* Invalid PDE or PTE, return FALSE */
return FALSE;
}
/* Address is valid, return TRUE */
return TRUE;
}
/**
* Retrieves the base virtual address of the system PTEs.
*
* @return This routine returns a pointer to the first PTE in the system PTE space.
*
* @since XT 1.0
*/
XTAPI
PMMPTE
MM::Pte::GetSystemPteBaseAddress(VOID)
{
return MM::Paging::GetPteAddress(NULLPTR);
}
/**
* Performs the initial setup of the system's page table hierarchy.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Pte::InitializePageTable(VOID)
{
PMMPTE EndSpacePte, PointerPte;
PMMMEMORY_LAYOUT MemoryLayout;
CPUID_REGISTERS CpuRegisters;
MMPTE TemplatePte;
/* Retrieve current paging mode and memory layout */
MemoryLayout = MM::Manager::GetMemoryLayout();
/* Get CPU features */
CpuRegisters.Leaf = CPUID_GET_STANDARD1_FEATURES;
AR::CpuFunc::CpuId(&CpuRegisters);
/* Check if Paging Global Extensions (PGE) is supported */
if(CpuRegisters.Edx & CPUID_FEATURES_EDX_PGE)
{
/* Enable the Global Paging (PGE) feature */
AR::CpuFunc::WriteControlRegister(4, AR::CpuFunc::ReadControlRegister(4) | CR4_PGE);
}
/* Get the PD user-space range for both legacy and PAE paging */
PointerPte = (PMMPTE)MM::Paging::GetPdeAddress(0);
EndSpacePte = (PMMPTE)MM::Paging::GetPdeAddress(MemoryLayout->UserSpaceEnd);
/* Clear all top-level entries mapping the user address space */
while(PointerPte <= EndSpacePte)
{
MM::Paging::ClearPte(PointerPte);
PointerPte = MM::Paging::GetNextPte(PointerPte);
}
/* Flush the TLB to invalidate all non-global entries */
AR::CpuFunc::FlushTlb();
/* Create a template PTE for mapping kernel pages */
MM::Paging::ClearPte(&TemplatePte);
MM::Paging::SetPte(&TemplatePte, 0, MM_PTE_READWRITE | MM_PTE_CACHE_ENABLE);
/* Map the kernel's PD entries */
MM::Pte::MapPDE(MemoryLayout->SystemSpaceStart, (PVOID)MM_HIGHEST_SYSTEM_ADDRESS, &TemplatePte);
}
/*
* Maps a range of virtual addresses at the PPE (Page Directory Pointer Entry) level.
*
* @param StartAddress
* The beginning of the virtual address range to map.
*
* @param EndAddress
* The end of the virtual address range to map.
*
* @param TemplatePpe
* A template PPE to use for creating new entries.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Pte::MapPPE(PVOID StartAddress,
PVOID EndAddress,
PMMPPE TemplatePpe)
{
/* Just a stub on i686 platform */
return;
}

View File

@@ -1,150 +0,0 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/mm/init.cc
* DESCRIPTION: Memory Manager initialization routines
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include <xtos.hh>
/**
* Performs an early initialization of the XTOS Memory Manager.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Init::InitializeMemoryManager(VOID)
{
/* Scan memory descriptors provided by the boot loader */
ScanMemoryDescriptors();
/* Check if there are enough physical pages */
if(NumberOfPhysicalPages < MM_MINIMUM_PHYSICAL_PAGES)
{
/* Insufficient physical pages, kernel panic */
DebugPrint(L"Insufficient physical pages! Install additional memory\n");
KE::Crash::Panic(0);
}
/* Proceed with architecture specific initialization */
InitializeArchitecture();
}
/**
* Scans memory descriptors provided by the boot loader.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Init::ScanMemoryDescriptors(VOID)
{
PLIST_ENTRY LoaderMemoryDescriptors, MemoryMappings;
PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor;
PFN_NUMBER FreePages;
/* Initially, set number of free pages to 0 */
FreePages = 0;
/* Get a list of memory descriptors provided by the boot loader */
LoaderMemoryDescriptors = KE::BootInformation::GetMemoryDescriptors();
/* Iterate through memory mappings provided by the boot loader */
MemoryMappings = LoaderMemoryDescriptors->Flink;
while(MemoryMappings != LoaderMemoryDescriptors)
{
/* Get memory descriptor */
MemoryDescriptor = CONTAIN_RECORD(MemoryMappings, LOADER_MEMORY_DESCRIPTOR, ListEntry);
/* Check if memory type is invisible or cached */
if(VerifyMemoryTypeInvisible(MemoryDescriptor->MemoryType) ||
(MemoryDescriptor->MemoryType == LoaderHardwareCachedMemory))
{
/* Skip this mapping */
MemoryMappings = MemoryMappings->Flink;
continue;
}
/* Make sure that memory type is not bad */
if(MemoryDescriptor->MemoryType != LoaderBad)
{
/* Increment number of physical pages */
NumberOfPhysicalPages += MemoryDescriptor->PageCount;
}
/* Find lowest physical page */
if(MemoryDescriptor->BasePage < LowestPhysicalPage)
{
/* Update lowest physical page */
LowestPhysicalPage = MemoryDescriptor->BasePage;
}
/* Find highest physical page */
if(MemoryDescriptor->BasePage + MemoryDescriptor->PageCount > HighestPhysicalPage)
{
/* Update highest physical page */
HighestPhysicalPage = (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) - 1;
}
/* Check if memory type should be considered as free */
if(VerifyMemoryTypeFree(MemoryDescriptor->MemoryType))
{
/* Check if this descriptor contains more free pages */
if(MemoryDescriptor->PageCount >= FreePages)
{
/* Update free descriptor */
FreePages = MemoryDescriptor->PageCount;
FreeDescriptor = MemoryDescriptor;
}
}
/* Get next memory descriptor */
MemoryMappings = MemoryMappings->Flink;
}
/* Store original free descriptor */
RTL::Memory::CopyMemory(&OldFreeDescriptor, FreeDescriptor, sizeof(LOADER_MEMORY_DESCRIPTOR));
}
/** Checks whether the specified memory type should be considered as free.
*
* @param MemoryType
* Specifies the memory type to verify.
*
* @return This routine returns TRUE if the specified memory type should be considered as free, or FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
MM::Init::VerifyMemoryTypeFree(LOADER_MEMORY_TYPE MemoryType)
{
return ((MemoryType == LoaderFree) || (MemoryType == LoaderFirmwareTemporary) ||
(MemoryType == LoaderLoadedProgram) || (MemoryType == LoaderOsloaderStack));
}
/**
* Checks whether the specified memory type should be considered as invisible for the memory manager.
*
* @param MemoryType
* Specifies the memory type to verify.
*
* @return This routine returns TRUE if the specified memory type should be considered as invisible, or FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
MM::Init::VerifyMemoryTypeInvisible(LOADER_MEMORY_TYPE MemoryType)
{
return ((MemoryType == LoaderFirmwarePermanent) ||
(MemoryType == LoaderSpecialMemory) ||
(MemoryType == LoaderBBTMemory));
}

110
xtoskrnl/mm/mmgr.cc Normal file
View File

@@ -0,0 +1,110 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/mm/mmgr.cc
* DESCRIPTION: Memory Manager
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
* Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Retrieves a pointer to the system's virtual memory layout structure.
*
* @return This routine returns a pointer to the memory layout structure.
*
* @since XT 1.0
*/
XTAPI
PMMMEMORY_LAYOUT
MM::Manager::GetMemoryLayout(VOID)
{
/* Return a pointer to the global memory layout structure */
return &MemoryLayout;
}
XTAPI
PFN_NUMBER
MM::Manager::GetNumberOfSystemPtes()
{
return NumberOfSystemPtes;
}
/**
* Performs an early initialization of the XTOS Memory Manager.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Manager::InitializeMemoryManager(VOID)
{
/* Scan memory descriptors provided by the boot loader */
MM::Pfn::ScanMemoryDescriptors();
/* Check if there are enough physical pages */
if(MM::Pfn::GetNumberOfPhysicalPages() < MM_MINIMUM_PHYSICAL_PAGES)
{
/* Insufficient physical pages, kernel panic */
DebugPrint(L"Insufficient physical pages! Install additional memory\n");
KE::Crash::Panic(0);
}
/* Compute page colors to reduce CPU cache conflicts */
MM::Colors::ComputePageColoring();
/* Compute allocation size for the PFN database */
MM::Pfn::ComputePfnDatabaseSize();
/* Initialize memory layout */
InitializeMemoryLayout();
/* Initialize page table */
MM::Pte::InitializePageTable();
/* Initialize system PTE space */
MM::Pte::InitializeSystemPteSpace();
}
/**
* Checks whether the specified memory type should be considered as free.
*
* @param MemoryType
* Specifies the memory type to verify.
*
* @return This routine returns TRUE if the specified memory type should be considered as free, or FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
MM::Manager::VerifyMemoryTypeFree(LOADER_MEMORY_TYPE MemoryType)
{
return ((MemoryType == LoaderFirmwareTemporary) ||
(MemoryType == LoaderFree) ||
(MemoryType == LoaderLoadedProgram) ||
(MemoryType == LoaderOsloaderStack));
}
/**
* Checks whether the specified memory type should be considered as invisible for the memory manager.
*
* @param MemoryType
* Specifies the memory type to verify.
*
* @return This routine returns TRUE if the specified memory type should be considered as invisible, or FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
MM::Manager::VerifyMemoryTypeInvisible(LOADER_MEMORY_TYPE MemoryType)
{
return ((MemoryType == LoaderBBTMemory) ||
(MemoryType == LoaderFirmwarePermanent) ||
(MemoryType == LoaderSpecialMemory));
}

View File

@@ -9,6 +9,28 @@
#include <xtos.hh>
/**
* Advances a PTE pointer by a given number of entries, considering the actual PTE size.
*
* @param Pte
* The PTE pointer to advance.
*
* @param Count
* The number of PTE entries to advance by.
*
* @return The advanced PTE pointer.
*
* @since XT 1.0
*/
XTAPI
PMMPTE
MM::Paging::AdvancePte(IN PMMPTE Pte,
IN LONG Count)
{
/* Return advanced PTE pointer */
return PmlRoutines->AdvancePte(Pte, Count);
}
/**
* Clears the contents of a page table entry (PTE).
*
@@ -21,8 +43,9 @@
*/
XTAPI
VOID
MM::Paging::ClearPte(PHARDWARE_PTE PtePointer)
MM::Paging::ClearPte(IN PMMPTE PtePointer)
{
/* Clear PTE */
PmlRoutines->ClearPte(PtePointer);
}
@@ -78,6 +101,92 @@ MM::Paging::FlushTlb(VOID)
}
}
/**
* Gets the value representing an empty PTE list.
*
* @return This routine returns the value representing an empty PTE list.
*
* @since XT 1.0
*/
XTAPI
ULONG_PTR
MM::Paging::GetEmptyPteList(VOID)
{
/* Return empty PTE list mask */
return (ULONG_PTR)PmlRoutines->GetEmptyPteList();
}
/**
* Gets the next entry in a PTE list.
*
* @param Pte
* The PTE pointer to get the next entry from.
*
* @return This routine returns the next entry in the PTE list.
*
* @since XT 1.0
*/
XTAPI
ULONG_PTR
MM::Paging::GetNextEntry(IN PMMPTE Pte)
{
/* Return next entry in PTE list */
return PmlRoutines->GetNextEntry(Pte);
}
/**
* Advances a PTE pointer, considering the actual PTE size.
*
* @param Pte
* The PTE pointer to advance.
*
* @return The advanced PTE pointer.
*
* @since XT 1.0
*/
XTAPI
PMMPTE
MM::Paging::GetNextPte(IN PMMPTE Pte)
{
/* Return advanced PTE pointer */
return PmlRoutines->GetNextPte(Pte);
}
/**
* Checks if a PTE list contains only one entry.
*
* @param Pte
* The PTE pointer to check.
*
* @return This routine returns TRUE if the PTE list has only one entry, FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
MM::Paging::GetOneEntry(IN PMMPTE Pte)
{
/* Return one entry status */
return PmlRoutines->GetOneEntry(Pte);
}
/**
* Gets the page frame number from a corresponding PTE.
*
* @param Pte
* The PTE pointer to get the page frame number from.
*
* @return This routine returns the page frame number.
*
* @since XT 1.0
*/
XTAPI
PFN_NUMBER
MM::Paging::GetPageFrameNumber(IN PMMPTE Pte)
{
return PmlRoutines->GetPageFrameNumber(Pte);
}
/**
* Gets the page map routines for basic paging mode (non-XPA).
*
@@ -90,6 +199,8 @@ MM::PPAGEMAP
MM::Paging::GetPageMapBasicRoutines(VOID)
{
static MM::PageMapBasic PageMapBasicRoutines;
/* Return non-XPA page map routines */
return &PageMapBasicRoutines;
}
@@ -105,6 +216,8 @@ MM::PPAGEMAP
MM::Paging::GetPageMapXpaRoutines(VOID)
{
static MM::PageMapXpa PageMapXpaRoutines;
/* Return XPA page map routines */
return &PageMapXpaRoutines;
}
@@ -120,11 +233,30 @@ MM::Paging::GetPageMapXpaRoutines(VOID)
*/
XTAPI
PMMPDE
MM::Paging::GetPdeAddress(PVOID Address)
MM::Paging::GetPdeAddress(IN PVOID Address)
{
/* Return PDE address */
return PmlRoutines->GetPdeAddress(Address);
}
/**
* Gets the virtual address that is mapped by a given Page Directory Entry.
*
* @param PdePointer
* Specifies the address of the PDE.
*
* @return This routine returns the virtual address mapped by the PDE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::Paging::GetPdeVirtualAddress(IN PMMPDE PdePointer)
{
/* Return PTE virtual address */
return PmlRoutines->GetPdeVirtualAddress(PdePointer);
}
/**
* Gets the address of the PPE (Page Directory Pointer Table Entry), that maps given address.
*
@@ -137,11 +269,48 @@ MM::Paging::GetPdeAddress(PVOID Address)
*/
XTAPI
PMMPPE
MM::Paging::GetPpeAddress(PVOID Address)
MM::Paging::GetPpeAddress(IN PVOID Address)
{
/* Return PPE address */
return PmlRoutines->GetPpeAddress(Address);
}
/**
* Gets the virtual address that is mapped by a given Page Directory Pointer Table Entry.
*
* @param PpePointer
* Specifies the address of the PPE.
*
* @return This routine returns the virtual address mapped by the PPE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::Paging::GetPpeVirtualAddress(IN PMMPPE PpePointer)
{
/* Return PTE virtual address */
return PmlRoutines->GetPpeVirtualAddress(PpePointer);
}
/**
* Gets the entire contents of a Page Table Entry (PTE) as a single value.
*
* @param PtePointer
* Pointer to the Page Table Entry (PTE) to read.
*
* @return This routine returns the contents of the PTE as a single value.
*
* @since XT 1.0
*/
XTAPI
ULONG_PTR
MM::Paging::GetPte(IN PMMPTE PtePointer)
{
/* Return PTE value */
return PmlRoutines->GetPte(PtePointer);
}
/**
* Gets the address of the PTE (Page Table Entry), that maps given address.
*
@@ -154,11 +323,81 @@ MM::Paging::GetPpeAddress(PVOID Address)
*/
XTAPI
PMMPTE
MM::Paging::GetPteAddress(PVOID Address)
MM::Paging::GetPteAddress(IN PVOID Address)
{
/* Return PTE address */
return PmlRoutines->GetPteAddress(Address);
}
/**
* Calculates the distance between two PTE pointers.
*
* @param EndPte
* Pointer to the ending Page Table Entry.
*
* @param StartPte
* Pointer to the starting Page Table Entry.
*
* @return This routine returns a signed value representing the number of PTEs between EndPte and StartPte.
*
* @since XT 1.0
*/
XTAPI
LONG
MM::Paging::GetPteDistance(PMMPTE EndPte,
PMMPTE StartPte)
{
/* Return distance between PTE pointers */
return PmlRoutines->GetPteDistance(EndPte, StartPte);
}
/**
* Gets the size of a PTE.
*
* @return This routine returns the size of a PTE.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::Paging::GetPteSize(VOID)
{
/* Return the size of MMPTE */
return PmlRoutines->GetPteSize();
}
/**
* Gets the virtual address that is mapped by a given Page Table Entry.
*
* @param PtePointer
* Specifies the address of the PTE.
*
* @return This routine returns the virtual address mapped by the PTE.
*
* @since XT 1.0
*/
XTAPI
PVOID
MM::Paging::GetPteVirtualAddress(IN PMMPTE PtePointer)
{
/* Return PTE virtual address */
return PmlRoutines->GetPteVirtualAddress(PtePointer);
}
/**
* Gets current status of eXtended Physical Addressing (XPA).
*
* @return This routine returns TRUE if PAE or LA57 (XPA) is enabled, or FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
MM::Paging::GetXpaStatus()
{
return PmlRoutines->GetXpaStatus();
}
/**
* Detects if eXtended Physical Addressing (XPA) is enabled and initializes page map support.
*
@@ -198,22 +437,20 @@ MM::Paging::InitializePageMapSupport(VOID)
*/
XTAPI
BOOLEAN
MM::Paging::PteValid(PHARDWARE_PTE PtePointer)
MM::Paging::PteValid(IN PMMPTE PtePointer)
{
/* Check if PTE is valid */
return PmlRoutines->PteValid(PtePointer);
}
/**
* Sets a PML2 page table entry (PTE) with the specified physical page and access flags.
* Sets the next entry in a PTE list.
*
* @param PtePointer
* Pointer to the page table entry (PTE) to set.
* @param Pte
* The PTE pointer to modify.
*
* @param PageFrameNumber
* Physical frame number to map.
*
* @param Writable
* Indicates whether the page should be writable.
* @param Value
* The value to set as the next entry.
*
* @return This routine does not return any value.
*
@@ -221,11 +458,80 @@ MM::Paging::PteValid(PHARDWARE_PTE PtePointer)
*/
XTAPI
VOID
MM::Paging::SetPte(PHARDWARE_PTE PtePointer,
PFN_NUMBER PageFrameNumber,
BOOLEAN Writable)
MM::Paging::SetNextEntry(IN PMMPTE Pte,
IN ULONG_PTR Value)
{
PmlRoutines->SetPte(PtePointer, PageFrameNumber, Writable);
/* Set next entry in PTE list */
PmlRoutines->SetNextEntry(Pte, Value);
}
/**
* Sets the flag indicating whether a PTE list contains only one entry.
*
* @param Pte
* The PTE pointer to modify.
*
* @param Value
* The value to set. TRUE if the list has only one entry, FALSE otherwise.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Paging::SetOneEntry(IN PMMPTE Pte,
IN BOOLEAN Value)
{
/* Set one entry status */
PmlRoutines->SetOneEntry(Pte, Value);
}
/**
* Sets a Page Table Entry (PTE) with the specified physical page and access flags.
*
* @param PtePointer
* Pointer to the page table entry (PTE) to set.
*
* @param PageFrameNumber
* Physical frame number to map.
*
* @param AttributesMask
* Specifies the attributes mask to apply to the PTE.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Paging::SetPte(IN PMMPTE PtePointer,
IN PFN_NUMBER PageFrameNumber,
IN ULONG_PTR AttributesMask)
{
/* Set PTE */
PmlRoutines->SetPte(PtePointer, PageFrameNumber, AttributesMask);
}
/**
* Sets a Page Table Entry (PTE) with the specified attributes.
*
* @param PtePointer
* Pointer to the page table entry (PTE) to set.
*
* @param Attributes
* Specifies the attributes to apply to the PTE.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Paging::SetPte(IN PMMPTE PtePointer,
IN ULONG_PTR Attributes)
{
PmlRoutines->SetPte(PtePointer, Attributes);
}
/**
@@ -246,9 +552,32 @@ MM::Paging::SetPte(PHARDWARE_PTE PtePointer,
*/
XTAPI
VOID
MM::Paging::SetPteCaching(PHARDWARE_PTE PtePointer,
BOOLEAN CacheDisable,
BOOLEAN WriteThrough)
MM::Paging::SetPteCaching(IN PMMPTE PtePointer,
IN BOOLEAN CacheDisable,
IN BOOLEAN WriteThrough)
{
/* Set caching attributes */
PmlRoutines->SetPteCaching(PtePointer, CacheDisable, WriteThrough);
}
/**
* Writes a Page Table Entry (PTE) with the specified value.
*
* @param Pte
* Pointer to the page table entry (PTE) to write.
*
* @param Value
* The value to write to the PTE.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Paging::WritePte(IN PMMPTE Pte,
IN MMPTE Value)
{
/* Assign PTE value */
PmlRoutines->WritePte(Pte, Value);
}

206
xtoskrnl/mm/pfn.cc Normal file
View File

@@ -0,0 +1,206 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/mm/pfn.cc
* DESCRIPTION: Physical Frame Number (PFN) support
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include <xtos.hh>
/**
* Allocates a block of physical pages for early kernel initialization.
*
* @param NumberOfPages
* The number of physical pages to allocate.
*
* @return This routine returns the base page frame number (PFN) of the allocated block.
*
* @since XT 1.0
*/
XTAPI
PFN_NUMBER
MM::Pfn::AllocateBootstrapPages(IN PFN_NUMBER NumberOfPages)
{
PFN_NUMBER Pfn;
/* Check if the largest free memory block has enough pages */
if(NumberOfPages > FreeDescriptor->PageCount)
{
/* Not enough physical memory available, kernel panic */
DebugPrint(L"Insufficient physical pages! Install additional memory\n");
KE::Crash::Panic(0);
}
/* Allocate pages from the beginning of the free descriptor */
Pfn = FreeDescriptor->BasePage;
FreeDescriptor->BasePage += NumberOfPages;
FreeDescriptor->PageCount -= NumberOfPages;
/* Return the base page frame number of the allocated block */
return Pfn;
}
/**
* Calculates the total number of pages required for the PFN database and its associated color tables.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Pfn::ComputePfnDatabaseSize(VOID)
{
/* Calculate the total number of pages required for the PFN database */
PfnDatabaseSize = (HighestPhysicalPage + 1) * sizeof(MMPFN);
PfnDatabaseSize = ROUND_UP(PfnDatabaseSize, MM_PAGE_SIZE);
PfnDatabaseSize >>= MM_PAGE_SHIFT;
}
/**
* Decrements the global count of available pages.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Pfn::DecrementAvailablePages(VOID)
{
/* Decrement the global count of available pages */
AvailablePages--;
}
/**
* Retrieves the total number of physical pages managed by the system.
*
* @return Returns the total count of physical memory pages.
*
* @since XT 1.0
*/
XTAPI
ULONGLONG
MM::Pfn::GetNumberOfPhysicalPages(VOID)
{
/* Return the number of physical pages */
return NumberOfPhysicalPages;
}
/**
* Gets the size of the PFN database and its associated structures, in pages.
*
* @return This routine returns the total number of pages required for the PFN database and its associated structures.
*
* @since XT 1.0
*/
XTAPI
PFN_NUMBER
MM::Pfn::GetPfnDatabaseSize(VOID)
{
/* Return the pre-calculated size of the PFN database in pages */
return PfnDatabaseSize;
}
/**
* Increments the global count of available pages.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Pfn::IncrementAvailablePages(VOID)
{
/* Increment the global count of available pages */
AvailablePages++;
}
/**
* Scans memory descriptors provided by the boot loader.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Pfn::ScanMemoryDescriptors(VOID)
{
PLIST_ENTRY LoaderMemoryDescriptors, MemoryMappings;
PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor;
PFN_NUMBER FreePages;
/* Initially, set number of free pages to 0 */
FreePages = 0;
/* Get the list head of memory descriptors */
LoaderMemoryDescriptors = KE::BootInformation::GetMemoryDescriptors();
/* Iterate through the memory descriptors */
MemoryMappings = LoaderMemoryDescriptors->Flink;
while(MemoryMappings != LoaderMemoryDescriptors)
{
/* Get the memory descriptor */
MemoryDescriptor = CONTAIN_RECORD(MemoryMappings, LOADER_MEMORY_DESCRIPTOR, ListEntry);
/* Skip invisible or hardware cached memory regions */
if(MM::Manager::VerifyMemoryTypeInvisible(MemoryDescriptor->MemoryType) ||
(MemoryDescriptor->MemoryType == LoaderHardwareCachedMemory))
{
/* Move to the next descriptor and skip further processing */
MemoryMappings = MemoryMappings->Flink;
continue;
}
/* Count the number of physical pages, excluding bad memory */
if(MemoryDescriptor->MemoryType != LoaderBad)
{
/* Add the pages from this descriptor to the total count */
NumberOfPhysicalPages += MemoryDescriptor->PageCount;
}
/* Check if this physical page is the lowest one yet */
if(MemoryDescriptor->BasePage < LowestPhysicalPage)
{
/* Update the lowest physical page number found so far */
LowestPhysicalPage = MemoryDescriptor->BasePage;
}
/* Check if this physical page is the highest one yet */
if((MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) > HighestPhysicalPage)
{
/* Update the highest physical page number found so far */
HighestPhysicalPage = (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) - 1;
}
/* Identify the largest block of free memory */
if(MM::Manager::VerifyMemoryTypeFree(MemoryDescriptor->MemoryType))
{
/* Check if this free memory block is the largest one yet */
if(MemoryDescriptor->PageCount >= FreePages)
{
/* Update the largest free block size and save the descriptor */
FreePages = MemoryDescriptor->PageCount;
FreeDescriptor = MemoryDescriptor;
}
}
/* Get next memory descriptor */
MemoryMappings = MemoryMappings->Flink;
}
/* Ensure a free memory descriptor was found */
if(!FreeDescriptor)
{
/* No free memory available to bootstrap the system */
KE::Crash::Panic(0);
}
/* Save a copy of the original free descriptor before it gets modified */
RTL::Memory::CopyMemory(&OriginalFreeDescriptor, FreeDescriptor, sizeof(LOADER_MEMORY_DESCRIPTOR));
}

395
xtoskrnl/mm/pte.cc Normal file
View File

@@ -0,0 +1,395 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/mm/pte.cc
* DESCRIPTION: Page table entry (PTE) support
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Finds a free cluster of system PTEs that can satisfy a given size.
*
* @param NumberOfPtes
* The number of contiguous PTEs required.
*
* @param SystemPtePoolType
* Specifies the system PTE pool to search within.
*
* @param FoundCluster
* On success, receives a pointer to the first PTE of the found cluster.
*
* @param PreviousClusterNode
* On success, receives a pointer to the list node that precedes the found cluster.
*
* @return This routine returns TRUE if a suitable cluster was found, FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
MM::Pte::FindFreeCluster(IN ULONG NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType,
OUT PMMPTE *FoundCluster,
OUT PMMPTE *PreviousClusterNode)
{
PMMPTE CurrentCluster;
PMMPTE PreviousNode = &FirstSystemFreePte[SystemPtePoolType];
ULONG ClusterSize;
/* Find a free PTE cluster large enough for the request */
while(MM::Paging::GetNextEntry(PreviousNode) != MAXULONG)
{
/* Retrieve the cluster and its size */
CurrentCluster = MM::Paging::AdvancePte(SystemPteBase, MM::Paging::GetNextEntry(PreviousNode));
ClusterSize = GetClusterSize(CurrentCluster);
/* Check if this cluster is large enough */
if(NumberOfPtes <= ClusterSize)
{
/* Found a suitable cluster */
*FoundCluster = CurrentCluster;
*PreviousClusterNode = PreviousNode;
return TRUE;
}
/* This cluster is too small, check the next one */
PreviousNode = CurrentCluster;
}
/* No suitable cluster was found */
return FALSE;
}
/**
* Decodes and returns the size of a free PTE cluster.
*
* @param Pte
* Supplies a pointer to the first PTE of the free cluster to inspect.
*
* @return This routine returns the total number of contiguous PTEs in the free cluster.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::Pte::GetClusterSize(IN PMMPTE Pte)
{
/* A special flag in the first PTE indicates a free cluster of size one */
if(MM::Paging::GetOneEntry(Pte))
{
/* Flag is set, so the cluster size is 1 by definition */
return 1;
}
/* For larger clusters, the size is encoded in the second PTE of the block */
Pte = MM::Paging::GetNextPte(Pte);
return MM::Paging::GetNextEntry(Pte);
}
/**
* Calculates the number of Page Table Entries (PTEs) that fit within a single page.
*
* @return This routine returns the number of PTEs per page.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::Pte::GetPtesPerPage(VOID)
{
/* Calculate and return the number of PTEs per page */
return MM_PAGE_SIZE / MM::Paging::GetPteSize();
}
/**
* Formats a range of PTEs into a freelist-based pool for system allocations.
*
* @param StartingPte
* Supplies a pointer to the start of the PTE range to be formatted.
*
* @param NumberOfPtes
* Supplies the total number of PTEs in the contiguous range.
*
* @param PoolType
* The system PTE pool type that this range will be used for.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Pte::InitializeSystemPtePool(IN PMMPTE StartingPte,
IN ULONG NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE PoolType)
{
/* Set the system PTE base address */
SystemPteBase = GetSystemPteBaseAddress();
/* Record the boundaries of this new PTE pool */
SystemPtesStart[PoolType] = StartingPte;
SystemPtesEnd[PoolType] = MM::Paging::AdvancePte(StartingPte, NumberOfPtes - 1);
/* Zero the memory for the new PTE pool before use */
RTL::Memory::ZeroMemory(StartingPte, NumberOfPtes * MM::Paging::GetPteSize());
/* Build the free list head to point to the start of the pool */
MM::Paging::SetNextEntry(StartingPte, MAXULONG);
MM::Paging::ClearPte(&FirstSystemFreePte[PoolType]);
MM::Paging::SetNextEntry(&FirstSystemFreePte[PoolType], MM::Paging::GetPteDistance(StartingPte, SystemPteBase));
/* Use the second PTE slot to store the total size of this pool */
StartingPte = MM::Paging::GetNextPte(StartingPte);
MM::Paging::ClearPte(StartingPte);
MM::Paging::SetNextEntry(StartingPte, NumberOfPtes);
/* Record the total number of free PTEs in this pool */
TotalSystemFreePtes[PoolType] = NumberOfPtes;
}
/**
* Sets up the entire system PTE address space.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Pte::InitializeSystemPteSpace(VOID)
{
PMMPTE PointerPte;
PMMPTE FirstZeroingPte;
PMMMEMORY_LAYOUT MemoryLayout;
/* Retrieve the system's memory layout */
MemoryLayout = MM::Manager::GetMemoryLayout();
/* Map the page table hierarchy for the entire system PTE space */
MM::Pte::MapPPE(MemoryLayout->SystemSpaceStart, MemoryLayout->SystemSpaceEnd, &ValidPte);
MM::Pte::MapPDE(MemoryLayout->SystemSpaceStart, MemoryLayout->SystemSpaceEnd, &ValidPte);
/* Format the main block of system PTEs into a free list pool */
PointerPte = MM::Paging::GetPteAddress(MemoryLayout->SystemSpaceStart);
InitializeSystemPtePool(PointerPte, MM::Manager::GetNumberOfSystemPtes(), SystemPteSpace);
/* Reserve and zero a dedicated block of system PTEs */
FirstZeroingPte = ReserveSystemPtes(MM_RESERVED_ZERO_PTES + 1, SystemPteSpace, 0);
RTL::Memory::ZeroMemory(FirstZeroingPte, (MM_RESERVED_ZERO_PTES + 1) * MM::Paging::GetPteSize());
/* Use the first PTE of this block as a counter for available zeroing PTEs */
MM::Paging::SetPte(FirstZeroingPte, MM_RESERVED_ZERO_PTES, 0);
}
/**
* Maps a range of virtual addresses at the PDE (Page Directory Entry) level.
*
* @param StartAddress
* The beginning of the virtual address range to map.
*
* @param EndAddress
* The end of the virtual address range to map.
*
* @param TemplatePde
* A template PDE to use for creating new entries.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Pte::MapPDE(PVOID StartAddress,
PVOID EndAddress,
PMMPDE TemplatePde)
{
PMMPDE EndSpace, PointerPde;
/* Get PDE addresses */
PointerPde = MM::Paging::GetPdeAddress(StartAddress);
EndSpace = MM::Paging::GetPdeAddress(EndAddress);
/* Iterate over all PDEs */
while(PointerPde <= EndSpace)
{
/* Check if PDE is already mapped */
if(!MM::Paging::PteValid(PointerPde))
{
/* Map PDE */
MM::Paging::SetPte(TemplatePde, MM::Pfn::AllocateBootstrapPages(1), 0);
*PointerPde = *TemplatePde;
/* Clear the page table */
RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPde), MM_PAGE_SIZE);
}
/* Get next table entry */
PointerPde = MM::Paging::GetNextPte(PointerPde);
}
}
/**
* Maps a range of virtual addresses at the PTE (Page Table Entry) level.
*
* @param StartAddress
* The beginning of the virtual address range to map.
*
* @param EndAddress
* The end of the virtual address range to map.
*
* @param TemplatePte
* A template PTE to use for creating new entries.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::Pte::MapPTE(PVOID StartAddress,
PVOID EndAddress,
PMMPTE TemplatePte)
{
PMMPTE EndSpace, PointerPte;
/* Get PTE addresses */
PointerPte = MM::Paging::GetPteAddress(StartAddress);
EndSpace = MM::Paging::GetPteAddress(EndAddress);
/* Iterate over all PTEs */
while(PointerPte <= EndSpace)
{
/* Check if PTE is already mapped */
if(!MM::Paging::PteValid(PointerPte))
{
/* Map PTE */
MM::Paging::SetPte(TemplatePte, MM::Pfn::AllocateBootstrapPages(1), 0);
*PointerPte = *TemplatePte;
/* Clear the page table */
RtlZeroMemory(MM::Paging::GetPteVirtualAddress(PointerPte), MM_PAGE_SIZE);
}
/* Get next table entry */
PointerPte = MM::Paging::GetNextPte(PointerPte);
}
}
/**
* Reserves a contiguous block of system PTEs from a specified pool.
*
* @param NumberOfPtes
* The number of contiguous PTEs to reserve.
*
* @param SystemPtePoolType
* Specifies the system PTE pool from which to allocate.
*
* @param Alignment
* This parameter is currently unused.
*
* @return This routine returns a pointer to the beginning of the reserved block,
* or NULLPTR if not enough contiguous PTEs are available.
*
* @since XT 1.0
*/
XTAPI
PMMPTE
MM::Pte::ReserveSystemPtes(IN ULONG NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType,
IN ULONG Alignment)
{
PMMPTE PreviousPte, NextPte, ReservedPte;
ULONG ClusterSize;
/* Raise runlevel and acquire lock to protect the PTE pool */
KE::RaiseRunLevel RunLevel(DISPATCH_LEVEL);
KE::QueuedSpinLockGuard SpinLock(SystemSpaceLock);
/* Find a free PTE cluster large enough for the request */
if(!FindFreeCluster(NumberOfPtes, SystemPtePoolType, &NextPte, &PreviousPte))
{
/* Out of system PTEs for this pool, return NULLPTR */
return NULLPTR;
}
/* We have the cluster, now get its size for the allocation logic below */
ClusterSize = GetClusterSize(NextPte);
/* Unlink the found cluster from the free list for processing */
MM::Paging::SetNextEntry(PreviousPte, MM::Paging::GetNextEntry(NextPte));
/* Handle the allocation based on whether the cluster size is an exact match */
if(ClusterSize == NumberOfPtes)
{
/* Exact match, allocate the entire cluster */
ReservedPte = NextPte;
/* Handle metadata cleanup for a single-PTE cluster */
if(MM::Paging::GetOneEntry(NextPte))
{
/* Clear the PTE that held the list metadata */
MM::Paging::ClearPte(NextPte);
NextPte = MM::Paging::GetNextPte(NextPte);
}
/* Clear the PTE that held the cluster size */
MM::Paging::ClearPte(NextPte);
}
else
{
/* Cluster is larger than needed, so it will be split */
ClusterSize -= NumberOfPtes;
ReservedPte = MM::Paging::AdvancePte(NextPte, ClusterSize);
/* Update metadata for the new, smaller leftover cluster */
if(ClusterSize == 1)
{
/* The leftover fragment is a single PTE */
MM::Paging::SetOneEntry(NextPte, 1);
MM::Paging::ClearPte(ReservedPte);
}
else
{
/* The leftover fragment is larger than one PTE */
NextPte = MM::Paging::GetNextPte(NextPte);
MM::Paging::SetNextEntry(NextPte, ClusterSize);
}
/* Find the correct sorted position to re-insert the leftover fragment */
PreviousPte = &FirstSystemFreePte[SystemPtePoolType];
while(MM::Paging::GetNextEntry(PreviousPte) != MAXULONG)
{
/* Get the next free cluster to check its size */
NextPte = MM::Paging::AdvancePte(SystemPteBase, MM::Paging::GetNextEntry(PreviousPte));
/* Check if the leftover fragment should be inserted here */
if(ClusterSize <= GetClusterSize(NextPte))
{
/* Found the correct sorted position */
break;
}
/* Advance to the next entry */
PreviousPte = NextPte;
}
/* Get a pointer to the start of the leftover fragment */
NextPte = MM::Paging::AdvancePte(ReservedPte, -ClusterSize);
/* Insert the leftover fragment back into the free list at its sorted position */
MM::Paging::SetNextEntry(NextPte, MM::Paging::GetNextEntry(PreviousPte));
MM::Paging::SetNextEntry(PreviousPte, MM::Paging::GetPteDistance(NextPte, SystemPteBase));
}
/* Decrement the total number of available PTEs in this pool */
TotalSystemFreePtes[SystemPtePoolType] -= NumberOfPtes;
/* Flush the TLB to ensure address translation consistency */
AR::CpuFunc::FlushTlb();
/* Return a pointer to the start of the reserved PTE block */
return ReservedPte;
}