Last active
April 26, 2024 03:08
-
-
Save 3llena/f23a48775bbe5425b4825eefcebf1197 to your computer and use it in GitHub Desktop.
complete IA-32e paging for vtop
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 | |
// | |
namespace os | |
{ | |
union virtual_address_t | |
{ | |
struct | |
{ | |
std::uint64_t m_offset : 12; | |
std::uint64_t m_pml1_idx : 9; | |
std::uint64_t m_pml2_idx : 9; | |
std::uint64_t m_pml3_idx : 9; | |
std::uint64_t m_pml4_idx : 9; | |
std::uint64_t m_unused : 16; | |
}; | |
std::uint64_t m_value; | |
}; | |
// | |
// Table 4-12. Use of CR3 with IA-32e Paging and CR4.PCIDE = 0 | |
// | |
union directory_table_base_t | |
{ | |
struct | |
{ | |
std::uint64_t m_ignored0 : 3; // 2:0 Ignored | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_ignored1 : 7; // 11:5 Ignored | |
std::uint64_t m_physical_address : 36; // 47:12 Physical address of the 4-KByte aligned PML4 table used for linear-address translation | |
std::uint64_t m_reserved0 : 16; // 63:48 Reserved (must be 0) | |
}; | |
std::uint64_t m_value; | |
}; | |
// | |
// Table 4-19. Format of an IA-32e Page-Table Entry that Maps a 4-KByte Page | |
// | |
union pml1e_t | |
{ | |
struct | |
{ | |
std::uint64_t m_present : 1; // 0 Present; must be 1 to map a 4-KByte page | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_accessed : 1; // 5 Accessed; indicates whether software has accessed the 4-KByte page referenced by this entry (see Section 4.8) | |
std::uint64_t m_dirty : 1; // 6 Dirty; indicates whether software has written to the 4-KByte page referenced by this entry (see Section 4.8) | |
std::uint64_t m_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) | |
std::uint64_t m_global : 1; // 8 Global; if CR4.PGE = 1, determines whether the translation is global (see Section 4.10); ignored otherwise | |
std::uint64_t m_ignored0 : 3; // 11:9 Ignored | |
std::uint64_t m_physical_address : 38; // 49:12 Physical address of the 4-KByte page referenced by this entry | |
std::uint64_t m_reserved0 : 2; // 51:50 Reserved (must be 0) | |
std::uint64_t m_ignored1 : 7; // 58:52 Ignored | |
std::uint64_t m_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 | |
std::uint64_t m_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) | |
}; | |
std::uint64_t m_value; | |
}; | |
// | |
// Table 4-18. Format of an IA-32e Page-Directory Entry that References a Page Table | |
// | |
union pml2e_t | |
{ | |
struct | |
{ | |
std::uint64_t m_present : 1; // 0 Present; must be 1 to reference a page table | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_accessed : 1; // 5 Accessed; indicates whether this entry has been used for linear-address translation (see Section 4.8) | |
std::uint64_t m_ignored0 : 1; // 6 Ignored | |
std::uint64_t m_pagesize : 1; // 7 Page size; must be 0 (otherwise, this entry maps a 2-MByte page; see Table 4-17) | |
std::uint64_t m_ignored1 : 4; // 11:8 Ignored | |
std::uint64_t m_physical_address : 38; // 49:12 Physical address of 4-KByte aligned page table referenced by this entry | |
std::uint64_t m_reserved0 : 2; // 51:50 Reserved (must be 0) | |
std::uint64_t m_ignored2 : 11; // 62:52 Ignored | |
std::uint64_t m_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) | |
}; | |
std::uint64_t m_value; | |
}; | |
// | |
// Table 4-17. Format of an IA-32e Page-Directory Entry that Maps a 2-MByte Page | |
// | |
union pml2e_large_t | |
{ | |
struct | |
{ | |
std::uint64_t m_present : 1; // 0 Present; must be 1 to map a 2-MByte page | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_accessed : 1; // 5 Accessed; indicates whether software has accessed the 2-MByte page referenced by this entry (see Section 4.8) | |
std::uint64_t m_dirty : 1; // 6 Dirty; indicates whether software has written to the 2-MByte page referenced by this entry (see Section 4.8) | |
std::uint64_t m_page_size : 1; // 7 Page size; must be 1 (otherwise, this entry references a page table; see Table 4-18) | |
std::uint64_t m_global : 1; // 8 Global; if CR4.PGE = 1, determines whether the translation is global (see Section 4.10); ignored otherwise | |
std::uint64_t m_ignored0 : 3; // 11:9 Ignored | |
std::uint64_t m_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) | |
std::uint64_t m_reserved0 : 8; // 20:13 Reserved (must be 0) | |
std::uint64_t m_physical_address : 29; // 49:21 Physical address of the 2-MByte page referenced by this entry | |
std::uint64_t m_reserved1 : 2; // 51:50 Reserved (must be 0) | |
std::uint64_t m_ignored1 : 7; // 58:52 Ignored | |
std::uint64_t m_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 | |
std::uint64_t m_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) | |
}; | |
std::uint64_t m_value; | |
}; | |
// | |
// Table 4-16. Format of an IA-32e Page-Directory-Pointer-Table Entry (PDPTE) that References a Page Directory | |
// | |
union pml3e_t | |
{ | |
struct | |
{ | |
std::uint64_t m_present : 1; // 0 Present; must be 1 to reference a page directory | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_accessed : 1; // 5 Accessed; indicates whether this entry has been used for linear-address translation (see Section 4.8) | |
std::uint64_t m_ignored0 : 1; // 6 Ignored | |
std::uint64_t m_page_size : 1; // 7 Page size; must be 0 (otherwise, this entry maps a 1-GByte page; see Table 4-15) | |
std::uint64_t m_ignored1 : 4; // 11:8 Ignored | |
std::uint64_t m_physical_address : 40; // 49:12 Physical address of 4-KByte aligned page directory referenced by this entry | |
std::uint64_t m_reserved0 : 1; // 51:50 Reserved (must be 0) | |
std::uint64_t m_ignored2 : 10; // 62:52 Ignored | |
std::uint64_t m_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) | |
}; | |
std::uint64_t m_value; | |
}; | |
// | |
// 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 | |
{ | |
std::uint64_t m_present : 1; // 0 Present; must be 1 to map a 1-GByte page | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_accessed : 1; // 5 Accessed; indicates whether software has accessed the 1-GByte page referenced by this entry (see Section 4.8) | |
std::uint64_t m_dirty : 1; // 6 Dirty; indicates whether software has written to the 1-GByte page referenced by this entry (see Section 4.8) | |
std::uint64_t m_page_size : 1; // 7 Page size; must be 1 (otherwise, this entry references a page directory; see Table 4-16) | |
std::uint64_t m_global : 1; // 8 Global; if CR4.PGE = 1, determines whether the translation is global (see Section 4.10); ignored otherwise | |
std::uint64_t m_ignored0 : 3; // 11:9 Ignored | |
std::uint64_t m_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) | |
std::uint64_t m_reserved0 : 17; // 29:13 Reserved (must be 0) | |
std::uint64_t m_physical_address : 21; // 50:30 Physical address of the 1-GByte page referenced by this entry | |
std::uint64_t m_reserved1 : 1; // 51 Reserved (must be 0) | |
std::uint64_t m_ignored1 : 7; // 58:52 Ignored | |
std::uint64_t m_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 | |
std::uint64_t m_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) | |
}; | |
std::uint64_t m_value; | |
}; | |
// | |
// Table 4-14. Format of an IA-32e PML4 Entry (PML4E) that References a Page-Directory-Pointer Table | |
// | |
union pml4e_t | |
{ | |
struct | |
{ | |
std::uint64_t m_present : 1; // 0 Present; must be 1 to reference a page-directory-pointer table | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_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) | |
std::uint64_t m_accessed : 1; // 5 Accessed; indicates whether this entry has been used for linear-address translation (see Section 4.8) | |
std::uint64_t m_ignored0 : 1; // 6 Ignored | |
std::uint64_t m_reserved0 : 1; // 7 Reserved (must be 0) | |
std::uint64_t m_ignored1 : 4; // 11:8 Ignored | |
std::uint64_t m_physical_address : 39; // 50:12 Physical address of 4-KByte aligned page-directory-pointer table referenced by this entry | |
std::uint64_t m_reserved1 : 1; // 51 Reserved (must be 0) | |
std::uint64_t m_ignored2 : 11; // 62:52 Ignored | |
std::uint64_t m_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) | |
}; | |
std::uint64_t m_value; | |
}; | |
} | |
#define _page_1gb_shift 30 | |
#define _page_2mb_shift 21 | |
#define _page_4kb_shift 12 | |
#define _page_1gb_offset( addr ) ( addr & ( ~( ( ( std::uint64_t )~( ( std::uint64_t )0 ) ) << _page_1gb_shift ) ) ) // addr & 111111111111111111111111111111 | |
#define _page_2mb_offset( addr ) ( addr & ( ~( ( ( std::uint64_t )~( ( std::uint64_t )0 ) ) << _page_2mb_shift ) ) ) // addr & 111111111111111111111 | |
#define _page_4kb_offset( addr ) ( addr & ( ~( ( ( std::uint64_t )~( ( std::uint64_t )0 ) ) << _page_4kb_shift ) ) ) // addr & 111111111111 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment