{"id":19149221,"url":"https://github.com/hoshimin/arch","last_synced_at":"2025-05-07T04:41:45.744Z","repository":{"id":112688502,"uuid":"585706427","full_name":"HoShiMin/Arch","owner":"HoShiMin","description":"A bunch of architectural headers for i386 and AMD64","archived":false,"fork":false,"pushed_at":"2023-10-07T17:24:17.000Z","size":104,"stargazers_count":37,"open_issues_count":0,"forks_count":9,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-05-07T04:41:37.175Z","etag":null,"topics":["amd-v","arch","eflags","gdt","global-descriptor-table","idt","intel","interrupts","layout","msr","pte","registers","ring0","segmentation","svm","vmx","vt-x","x86"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HoShiMin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-01-05T21:28:54.000Z","updated_at":"2025-05-06T12:39:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"770274d6-c177-4c8a-84bf-8746b9ef6505","html_url":"https://github.com/HoShiMin/Arch","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoShiMin%2FArch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoShiMin%2FArch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoShiMin%2FArch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HoShiMin%2FArch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HoShiMin","download_url":"https://codeload.github.com/HoShiMin/Arch/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252816519,"owners_count":21808702,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amd-v","arch","eflags","gdt","global-descriptor-table","idt","intel","interrupts","layout","msr","pte","registers","ring0","segmentation","svm","vmx","vt-x","x86"],"created_at":"2024-11-09T08:07:15.022Z","updated_at":"2025-05-07T04:41:45.721Z","avatar_url":"https://github.com/HoShiMin.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🧩 Arch\nIt's a bit-perfect (and maybe the most complete in some cases) bunch of architectural headers for i386/AMD64 platform written in C++17.\n\n### 📜 Supported structures and layouts:\n* **Memory paging** for all possible regimes and page sizes:\n  - Regimes:\n    - Legacy Non-PAE with and without CR4.PSE (4Kb and 4Mb pages).\n    - Legacy PAE (4Kb and 2Mb pages).\n    - Long-mode 4-Level (4Kb, 2Mb and 1Gb pages).\n    - Long-mode 5-Level (4Kb, 2Mb and 1Gb pages).  \n  - With definitions for all possible page tables and entries:\n    - PML5 table with PML5E entries introduced with Intel 10th Gen (Ice Lake) and AMD Epyc 7xxx \"Genoa\" (Zen4).\n    - PML4 table with PML4E entries.\n    - PDP table with PDPE entries (also known as PDPT table and PDPTE entries in Intel terms) including PageSize forms.\n    - PD table with PDE entries including PageSize forms.\n    - PT table with PTE entries.\n* **Segmentation**:\n  - GDT - Global Descriptor Table.\n  - IDT - Interrupt Descriptor Table.\n  - LDT - Local Descriptor Table.\n  - TSS - Task State Segment.\n  - Segment selector (format of CS, DS, GS, FS, ES, SS and TR registers).\n  - Descriptor table register (IDTR, GDTR and LDTR registers).\n  - Descriptors (system- and user-segments and gates for all possible interpretations).\n* **System registers**:\n  - EFlags.\n  - Control registers: CR0, CR, CR3, CR4, CR8.\n  - Debug registers: DR0..DR7.\n* **Interrupt vectors**.\n* **CPUID** with some leaves specific for Intel and AMD.\n* **MSRs** (Model Specific Registers) for Intel and AMD:\n  - All possible MSR addresses for Intel and AMD.\n  - Layouts for some of them (including Memory Type Range Registers (MTRRs) for Intel).\n* Architectural **intrinsics** for MSVC and CLang.\n* **Virtualization**:\n  - Intel VT-x (also known as Intel VMX):\n    - VMCS - Virtual Machine Control Structure.\n    - Exit reasons.\n    - EPT tables.\n    - MSR permission map.\n    - VMENTRY configuration.\n    - VMEXIT qualification.\n  - AMD-V (also known as AMD SVM):\n    - VMCB - Virtual Machine Control Block.\n    - Exit reasons.\n    - NPT - Nested Page Tables (also known as AMD-RVI) which are the same as normal page tables.\n    - MSR permission map.\n    - Event injection layout.\n  - A bit of Hyper-V:\n    - Hypercall layout.\n    - Hypercall result values.\n    - Hypercall codes.\n    - Hypervisor status.\n    - Synthetic MSRs.\n\n\n### 🏗️ Requirements:\n  * MSVC or Clang (GCC has not tested).\n  * C++17 or above.\n  * Both usermode and kernelmode are supported.\n\n### ✍️ How to?\nJust add the folder `Arch/include` to additional headers path and you're ready to go!  \nLet's start with CPUID example:\n```cpp\n#include \u003cArch/x86/Cpuid.h\u003e\n\nint main()\n{\n    const auto basicInfo = Cpuid::Cpuid::query\u003cCpuid::Generic::MaximumFunctionNumberAndVendorId\u003e();\n    if (basicInfo-\u003eisIntel())\n    {\n        const auto features = Cpuid::Cpuid::query\u003cCpuid::Intel::FeatureInformation\u003e();\n        printf(\"SSE 4.2 is supported: %u\\n\", features-\u003eSSE42);\n    }\n    else if (basicInfo-\u003eisAmd())\n    {\n        const auto features = Cpuid::Cpuid::query\u003cCpuid::Amd::FeatureInformation\u003e();\n        printf(\"SSE 4.2 is supported: %u\\n\", features-\u003eSSE42);\n    }\n    else\n    {\n        /* Unknown CPU */\n    }\n}\n```\n\nAll right, let's go to kernel and try MSRs and control registers:\n```cpp\n#include \u003cArch/x86/Registers.h\u003e\n\nvoid test()\n{\n    const auto efer = Msr::Msr::read\u003cMsr::Intel::Ia32Efer\u003e();\n\n    if (efer-\u003eLME \u0026\u0026 efer-\u003eLMA) // Is long-mode enabled and active?\n    {\n        const auto cr3 = Regs::Native::Cr3::query();\n        const auto cr4 = Regs::Native::Cr4::query();\n        if (cr4-\u003elayout.LA57)\n        {\n            // 5-Level paging:\n            const auto pml5pfn = cr3-\u003epaging5Level.PML5;\n            ...\n        }\n        else\n        {\n            // 4-Level paging:\n            const auto pml4pfn = cr3-\u003epaging4Level.PML4;\n            ...\n        }\n    }\n}\n```\n\n \nWell done! Let's try page traversal through a page table.  \nSuppose we're in long 4-Level paging mode and the page is presented - checks for presense of a page were omitted for the simplicity:\n```cpp\n#include \u003cntifs.h\u003e\n#include \u003cArch/x86/Pte.h\u003e\n\ntemplate \u003ctypename Type\u003e\ntypename Type::Layout* phys2virt(const Type phys)\n{\n    return MmGetVirtualForPhysical(PHYSICAL_ADDRESS{ .QuadPart = static_cast\u003clong long\u003e(phys); });\n}\n\nunsigned long long getPhysicalAddress(void* virtualAddress)\n{\n    constexpr auto k_mode = Pte::Mode::longMode4Level;\n\n    using LinearAddress = Pte::LinearAddress\u003ck_mode\u003e;\n    using Tables = Pte::Tables\u003ck_mode\u003e;\n\n    const LinearAddress addr{ .raw = reinterpret_cast\u003csize_t\u003e(virtualAddress) };\n    const auto cr3Pfn = Regs::Native::Cr3::query()-\u003epaging4Level.PML4;\n\n    const auto* const pml4e = phys2virt(Tables::pml4e(cr3Pfn, addr));\n    const auto* const pdpe = phys2virt(pml4e-\u003epdpe(addr));\n    switch (pdpe-\u003epageSize())\n    {\n    case Pte::PageSize::nonPse:\n    {\n        const auto* const pde = phys2virt(pdpe-\u003enonPse.pde(addr));\n        switch (pde-\u003epageSize())\n        {\n        case Pte::PageSize::nonPse:\n        {\n            // 4Kb:\n            const auto* const pte = phys2virt(pde-\u003enonPse.pte(addr));\n            const auto phys = pte-\u003ephysicalAddress(addr);\n            return phys.physicalAddress;\n        }\n        case Pte::PageSize::pse:\n        {\n            // 2Mb:\n            const auto phys = pde-\u003epse.physicalAddress(addr);\n            return phys.physicalAddress;\n        }\n        }\n        break;\n    }\n    case Pte::PageSize::pse:\n    {\n        // 1Gb:\n        const auto phys = pdpe-\u003epse.physicalAddress(addr);\n        return phys.physicalAddress;\n    }\n    }\n\n    return 0; // Invalid translation\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoshimin%2Farch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhoshimin%2Farch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoshimin%2Farch/lists"}