Skip to content

Instantly share code, notes, and snippets.

@3llena
Last active April 26, 2024 03:08
Show Gist options
  • Save 3llena/f23a48775bbe5425b4825eefcebf1197 to your computer and use it in GitHub Desktop.
Save 3llena/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
//
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