forked from xt-sys/exectos
Compare commits
85 Commits
powershell
...
memmgr
| Author | SHA1 | Date | |
|---|---|---|---|
|
b7c004528a
|
|||
|
5012c8dc37
|
|||
|
1e3917882c
|
|||
|
b3b874d3ce
|
|||
|
288b2f8b24
|
|||
|
c7cc536685
|
|||
|
b8e81e2223
|
|||
|
0fd2b8b729
|
|||
|
560cd43b34
|
|||
|
f0a06db7d2
|
|||
|
7575526f07
|
|||
|
643fd0d1e8
|
|||
|
6aa148784b
|
|||
|
e237a944cc
|
|||
|
755a167f2c
|
|||
|
24dccf4bed
|
|||
|
7b93c39348
|
|||
|
570301bb35
|
|||
|
b183d52806
|
|||
|
687c58d923
|
|||
|
049c9c6bbd
|
|||
|
f1a76bc01a
|
|||
|
cb4d113e31
|
|||
|
728241f998
|
|||
|
00d428d8de
|
|||
|
020b7c7676
|
|||
|
2265a4a522
|
|||
|
dc23f91110
|
|||
|
7f0ca6a948
|
|||
|
36c273ea13
|
|||
|
5cf3dfa844
|
|||
|
070c508e42
|
|||
|
5224dc315f
|
|||
|
b7bbf9ffa8
|
|||
|
eae48320f3
|
|||
|
17b5649362
|
|||
|
783a9eea3a
|
|||
|
237f6a2974
|
|||
|
ee9514fd5c
|
|||
|
63c27a149a
|
|||
|
7694df7744
|
|||
|
c710ec4688
|
|||
|
8054bb915a
|
|||
|
86aa22e5f8
|
|||
|
4a7494ad3f
|
|||
|
d4287198b0
|
|||
|
4265ae92d0
|
|||
|
931586eebd
|
|||
|
c099882866
|
|||
|
0097cb88d7
|
|||
|
20b0bfdfad
|
|||
|
35523a230a
|
|||
|
7b11a8feb1
|
|||
|
0cf178a648
|
|||
|
66f27e4b9a
|
|||
|
10b8ab347a
|
|||
|
071c840ca8
|
|||
|
dda8f88830
|
|||
|
cb2da54956
|
|||
|
fd13091476
|
|||
|
c28c3f8344
|
|||
|
dfb0284427
|
|||
|
1150b9ecdb
|
|||
|
f6dac12057
|
|||
|
ffa480d69a
|
|||
|
0120ba167f
|
|||
|
4e9dc15501
|
|||
|
164ff0c135
|
|||
|
f538d035e2
|
|||
|
72b92f853e
|
|||
|
00b04f5405
|
|||
|
52afd31e77
|
|||
|
7f06abf236
|
|||
|
4f4df52d3d
|
|||
|
764fec4d75
|
|||
|
ca8a539c0e
|
|||
|
c206b443ed
|
|||
|
b19b27a621
|
|||
|
56b81f5d73
|
|||
|
1e99a3f4a9
|
|||
|
0a71bc3995
|
|||
|
13a9d4c522
|
|||
|
9bf867af95
|
|||
|
a7be533521
|
|||
|
fdbe157c18
|
@@ -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
144
boot/bootsect/amd64/cpu.S
Normal 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"
|
||||
@@ -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
124
boot/bootsect/i686/cpu.S
Normal 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"
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
190
boot/xtldr/biosutil.cc
Normal 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));
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
# Set base addresses for all modules
|
||||
set(BASEADDRESS_XTLDR 0x000000000000F800)
|
||||
set(BASEADDRESS_XTOSKRNL 0x0000000140000000)
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
# Set base addresses for all modules
|
||||
set(BASEADDRESS_XTLDR 0x0000F800)
|
||||
set(BASEADDRESS_XTOSKRNL 0x00400000)
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -272,11 +272,18 @@ typedef struct _KIDTENTRY
|
||||
{
|
||||
USHORT OffsetLow;
|
||||
USHORT Selector;
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
UCHAR Reserved;
|
||||
UCHAR Type:4;
|
||||
UCHAR Flag:1;
|
||||
UCHAR Dpl:2;
|
||||
UCHAR Present:1;
|
||||
};
|
||||
USHORT Access;
|
||||
};
|
||||
USHORT ExtendedOffset;
|
||||
} KIDTENTRY, *PKIDTENTRY;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 bootloader’s 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:
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -67,7 +67,8 @@ namespace AR
|
||||
IN PVOID Handler,
|
||||
IN USHORT Selector,
|
||||
IN USHORT Ist,
|
||||
IN USHORT Access);
|
||||
IN USHORT Dpl,
|
||||
IN USHORT Type);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
74
xtoskrnl/includes/mm/amd64/paging.hh
Normal file
74
xtoskrnl/includes/mm/amd64/paging.hh
Normal 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 */
|
||||
65
xtoskrnl/includes/mm/amd64/pte.hh
Normal file
65
xtoskrnl/includes/mm/amd64/pte.hh
Normal 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 */
|
||||
35
xtoskrnl/includes/mm/colors.hh
Normal file
35
xtoskrnl/includes/mm/colors.hh
Normal 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 */
|
||||
@@ -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 */
|
||||
|
||||
70
xtoskrnl/includes/mm/i686/paging.hh
Normal file
70
xtoskrnl/includes/mm/i686/paging.hh
Normal 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 */
|
||||
59
xtoskrnl/includes/mm/i686/pte.hh
Normal file
59
xtoskrnl/includes/mm/i686/pte.hh
Normal 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 */
|
||||
@@ -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 */
|
||||
34
xtoskrnl/includes/mm/mmgr.hh
Normal file
34
xtoskrnl/includes/mm/mmgr.hh
Normal 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 */
|
||||
@@ -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 */
|
||||
42
xtoskrnl/includes/mm/pfn.hh
Normal file
42
xtoskrnl/includes/mm/pfn.hh
Normal 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 */
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
77
xtoskrnl/mm/amd64/mmgr.cc
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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
296
xtoskrnl/mm/amd64/pte.cc
Normal 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
95
xtoskrnl/mm/colors.cc
Normal 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;
|
||||
}
|
||||
@@ -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};
|
||||
|
||||
@@ -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++)
|
||||
|
||||
@@ -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
84
xtoskrnl/mm/i686/mmgr.cc
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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
139
xtoskrnl/mm/i686/pte.cc
Normal 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;
|
||||
}
|
||||
@@ -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
110
xtoskrnl/mm/mmgr.cc
Normal 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));
|
||||
}
|
||||
@@ -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
206
xtoskrnl/mm/pfn.cc
Normal 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
395
xtoskrnl/mm/pte.cc
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user