Skip to content

Instantly share code, notes, and snippets.

@hLunaaa
Last active April 25, 2025 21:23
Show Gist options
  • Save hLunaaa/f23a48775bbe5425b4825eefcebf1197 to your computer and use it in GitHub Desktop.
Save hLunaaa/f23a48775bbe5425b4825eefcebf1197 to your computer and use it in GitHub Desktop.
complete IA-32e paging for vtop
#pragma once
//
// https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.pdf
//
#define __pfn_to_page(pfn) (pfn << PAGE_SHIFT)
#define __page_to_pfn(pfn) (pfn >> PAGE_SHIFT)
union virt_addr_t
{
struct
{
u64 offset : 12;
u64 pml1_idx : 9;
u64 pml2_idx : 9;
u64 pml3_idx : 9;
u64 pml4_idx : 9;
u64 user : 16; // if (pml4_idx > 255) user = 0xffff;
};
u64 val;
};
//
// Table 4-12. Use of CR3 with IA-32e Paging and CR4.PCIDE = 0
//
union cr3_t
{
struct
{
u64 ignored0 : 3; // 2:0 Ignored
u64 page_write_through : 1; // 3 Page-level write-through; indirectly determines the memory type used to access the PML4 table during linearaddress translation (see Section 4.9.2)
u64 page_cache_disable : 1; // 4 Page-level cache disable; indirectly determines the memory type used to access the PML4 table during linear-address translation(see Section 4.9.2)
u64 ignored1 : 7; // 11:5 Ignored
u64 physical_address : 36; // 47:12 Physical address of the 4-KByte aligned PML4 table used for linear-address translation
u64 reserved0 : 16; // 63:48 Reserved (must be 0)
};
u64 val;
};
//
// Table 4-19. Format of an IA-32e Page-Table Entry that Maps a 4-KByte Page
//
union pml1e_t
{
struct
{
u64 present : 1; // 0 Present; must be 1 to map a 4-KByte page
u64 read_write : 1; // 1 Read/write; if 0, writes may not be allowed to the 4-KByte page referenced by this entry (see Section 4.6)
u64 user_supervisor : 1; // 2 User/supervisor; if 0, user-mode accesses are not allowed to the 4-KByte page referenced by this entry (see Section 4.6)
u64 page_write_through : 1; // 3 Page-level write-through; indirectly determines the memory type used to access the 4-KByte page referenced by this entry(see Section 4.9.2)
u64 page_cache_disable : 1; // 4 Page-level cache disable; indirectly determines the memory type used to access the 4-KByte page referenced by this entry(see Section 4.9.2)
u64 accessed : 1; // 5 Accessed; indicates whether software has accessed the 4-KByte page referenced by this entry (see Section 4.8)
u64 dirty : 1; // 6 Dirty; indicates whether software has written to the 4-KByte page referenced by this entry (see Section 4.8)
u64 page_attribute_table : 1; // 7 Indirectly determines the memory type used to access the 4-KByte page referenced by this entry (see Section 4.9.2)
u64 global : 1; // 8 Global; if CR4.PGE = 1, determines whether the translation is global (see Section 4.10); ignored otherwise
u64 ignored0 : 3; // 11:9 Ignored
u64 physical_address : 36; // 49:12 Physical address of the 4-KByte page referenced by this entry
u64 reserved0 : 4; // 51:50 Reserved (must be 0)
u64 ignored1 : 7; // 58:52 Ignored
u64 protection_key : 4; // 62:59 Protection key; if CR4.PKE = 1, determines the protection key of the page (see Section 4.6.2); ignored otherwise
u64 execute_disable : 1; // 63 If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 4-KByte page controlled by this entry; see Section 4.6); otherwise, reserved(must be 0)
};
u64 val;
};
//
// Table 4-18. Format of an IA-32e Page-Directory Entry that References a Page Table
//
union pml2e_t
{
struct
{
u64 present : 1; // 0 Present; must be 1 to reference a page table
u64 read_write : 1; // 1 Read/write; if 0, writes may not be allowed to the 2-MByte region controlled by this entry (see Section 4.6)
u64 user_supervisor : 1; // 2 User/supervisor; if 0, user-mode accesses are not allowed to the 2-MByte region controlled by this entry (see Section 4.6)
u64 page_write_through : 1; // 3 Page-level write-through; indirectly determines the memory type used to access the page table referenced by this entry(see Section 4.9.2)
u64 page_cache_disable : 1; // 4 Page-level cache disable; indirectly determines the memory type used to access the page table referenced by this entry(see Section 4.9.2)
u64 accessed : 1; // 5 Accessed; indicates whether this entry has been used for linear-address translation (see Section 4.8)
u64 ignored0 : 1; // 6 Ignored
u64 page_size : 1; // 7 Page size; must be 0 (otherwise, this entry maps a 2-MByte page; see Table 4-17)
u64 ignored1 : 4; // 11:8 Ignored
u64 physical_address : 36; // 49:12 Physical address of 4-KByte aligned page table referenced by this entry
u64 reserved0 : 4; // 51:50 Reserved (must be 0)
u64 ignored2 : 11; // 62:52 Ignored
u64 execute_disable : 1; // 63 If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 2-MByte region controlled by this entry; see Section 4.6); otherwise, reserved(must be 0)
};
u64 val;
};
//
// Table 4-17. Format of an IA-32e Page-Directory Entry that Maps a 2-MByte Page
//
union pml2e_large_t
{
struct
{
u64 present : 1; // 0 Present; must be 1 to map a 2-MByte page
u64 read_write : 1; // 1 Read/write; if 0, writes may not be allowed to the 2-MByte page referenced by this entry (see Section 4.6)
u64 user_supervisor : 1; // 2 User/supervisor; if 0, user-mode accesses are not allowed to the 2-MByte page referenced by this entry (see Section 4.6)
u64 page_write_through : 1; // 3 Page-level write-through; indirectly determines the memory type used to access the 2-MByte page referenced by this entry(see Section 4.9.2)
u64 page_cache_disable : 1; // 4 Page-level cache disable; indirectly determines the memory type used to access the 2-MByte page referenced by this entry(see Section 4.9.2)
u64 accessed : 1; // 5 Accessed; indicates whether software has accessed the 2-MByte page referenced by this entry (see Section 4.8)
u64 dirty : 1; // 6 Dirty; indicates whether software has written to the 2-MByte page referenced by this entry (see Section 4.8)
u64 page_size : 1; // 7 Page size; must be 1 (otherwise, this entry references a page table; see Table 4-18)
u64 global : 1; // 8 Global; if CR4.PGE = 1, determines whether the translation is global (see Section 4.10); ignored otherwise
u64 ignored0 : 3; // 11:9 Ignored
u64 page_attribute_table : 1; // 12 Indirectly determines the memory type used to access the 2-MByte page referenced by this entry (see Section 4.9.2)
u64 reserved0 : 8; // 20:13 Reserved (must be 0)
u64 physical_address : 29; // 49:21 Physical address of the 2-MByte page referenced by this entry
u64 reserved1 : 2; // 51:50 Reserved (must be 0)
u64 ignored1 : 7; // 58:52 Ignored
u64 protection_key : 4; // 62:59 Protection key; if CR4.PKE = 1, determines the protection key of the page (see Section 4.6.2); ignored otherwise
u64 execute_disable : 1; // 63 If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 2-MByte page controlled by this entry; see Section 4.6); otherwise, reserved(must be 0)
};
u64 val;
};
//
// Table 4-16. Format of an IA-32e Page-Directory-Pointer-Table Entry (PDPTE) that References a Page Directory
//
union pml3e_t
{
struct
{
u64 present : 1; // 0 Present; must be 1 to reference a page directory
u64 read_write : 1; // 1 Read/write; if 0, writes may not be allowed to the 1-GByte region controlled by this entry (see Section 4.6)
u64 user_supervisor : 1; // 2 User/supervisor; if 0, user-mode accesses are not allowed to the 1-GByte region controlled by this entry (see Section 4.6)
u64 page_write_through : 1; // 3 Page-level write-through; indirectly determines the memory type used to access the page directory referenced by this entry(see Section 4.9.2)
u64 page_cache_disable : 1; // 4 Page-level cache disable; indirectly determines the memory type used to access the page directory referenced by this entry(see Section 4.9.2)
u64 accessed : 1; // 5 Accessed; indicates whether this entry has been used for linear-address translation (see Section 4.8)
u64 ignored0 : 1; // 6 Ignored
u64 page_size : 1; // 7 Page size; must be 0 (otherwise, this entry maps a 1-GByte page; see Table 4-15)
u64 ignored1 : 4; // 11:8 Ignored
u64 physical_address : 36; // 49:12 Physical address of 4-KByte aligned page directory referenced by this entry
u64 reserved0 : 4; // 51:50 Reserved (must be 0)
u64 ignored2 : 11; // 62:52 Ignored
u64 execute_disable : 1; // 63 If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 1-GByte region controlled by this entry; see Section 4.6); otherwise, reserved(must be 0)
};
u64 val;
};
//
// Table 4-15. Format of an IA-32e Page-Directory-Pointer-Table Entry (PDPTE) that Maps a 1-GByte Page
//
union pml3e_large_t
{
struct
{
u64 present : 1; // 0 Present; must be 1 to map a 1-GByte page
u64 read_write : 1; // 1 Read/write; if 0, writes may not be allowed to the 1-GByte page referenced by this entry (see Section 4.6)
u64 user_supervisor : 1; // 2 User/supervisor; if 0, user-mode accesses are not allowed to the 1-GByte page referenced by this entry (see Section 4.6)
u64 page_write_through : 1; // 3 Page-level write-through; indirectly determines the memory type used to access the 1-GByte page referenced by this entry(see Section 4.9.2)
u64 page_cache_disable : 1; // 4 Page-level cache disable; indirectly determines the memory type used to access the 1-GByte page referenced by this entry(see Section 4.9.2)
u64 accessed : 1; // 5 Accessed; indicates whether software has accessed the 1-GByte page referenced by this entry (see Section 4.8)
u64 dirty : 1; // 6 Dirty; indicates whether software has written to the 1-GByte page referenced by this entry (see Section 4.8)
u64 page_size : 1; // 7 Page size; must be 1 (otherwise, this entry references a page directory; see Table 4-16)
u64 global : 1; // 8 Global; if CR4.PGE = 1, determines whether the translation is global (see Section 4.10); ignored otherwise
u64 ignored0 : 3; // 11:9 Ignored
u64 page_attribute_table : 1; // 12 Indirectly determines the memory type used to access the 1-GByte page referenced by this entry (see Section 4.9.2)
u64 reserved0 : 17; // 29:13 Reserved (must be 0)
u64 physical_address : 21; // 50:30 Physical address of the 1-GByte page referenced by this entry
u64 reserved1 : 1; // 51 Reserved (must be 0)
u64 ignored1 : 7; // 58:52 Ignored
u64 protection_key : 4; // 62:59 Protection key; if CR4.PKE = 1, determines the protection key of the page (see Section 4.6.2); ignored otherwise
u64 execute_disable : 1; // 63 If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 1-GByte page controlled by this entry; see Section 4.6); otherwise, reserved(must be 0)
};
u64 val;
};
//
// Table 4-14. Format of an IA-32e PML4 Entry (PML4E) that References a Page-Directory-Pointer Table
//
union pml4e_t
{
struct
{
u64 present : 1; // 0 Present; must be 1 to reference a page-directory-pointer table
u64 read_write : 1; // 1 Read/write; if 0, writes may not be allowed to the 512-GByte region controlled by this entry (see Section 4.6)
u64 user_supervisor : 1; // 2 User/supervisor; if 0, user-mode accesses are not allowed to the 512-GByte region controlled by this entry (see Section 4.6)
u64 page_write_through : 1; // 3 Page-level write-through; indirectly determines the memory type used to access the page-directory-pointer table referenced by this entry(see Section 4.9.2)
u64 page_cache_disable : 1; // 4 Page-level cache disable; indirectly determines the memory type used to access the page-directory-pointer table referenced by this entry(see Section 4.9.2)
u64 accessed : 1; // 5 Accessed; indicates whether this entry has been used for linear-address translation (see Section 4.8)
u64 ignored0 : 1; // 6 Ignored
u64 page_size : 1; // 7 Reserved (must be 0)
u64 ignored1 : 4; // 11:8 Ignored
u64 physical_address : 36; // 50:12 Physical address of 4-KByte aligned page-directory-pointer table referenced by this entry
u64 reserved1 : 4; // 51 Reserved (must be 0)
u64 ignored2 : 11; // 62:52 Ignored
u64 execute_disable : 1; // 63 If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 512-GByte region controlled by this entry; see Section 4.6); otherwise, reserved(must be 0)
};
u64 val;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment