Created
June 9, 2017 15:04
-
-
Save diekmann/74fbb137517588d210ce73c8ed7cc422 to your computer and use it in GitHub Desktop.
[draft] dump outermost page table in with 4 level paging (Linux x64 default)
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
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
#include <linux/init.h> | |
#include <linux/module.h> | |
#include <linux/printk.h> | |
#ifndef __x86_64__ | |
#error "wrong arch" | |
#endif | |
struct page_table{ | |
void* entry[512]; | |
}; | |
static int __init test_module_init(void) | |
{ | |
/* https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf pp.2783 | |
* March 2017, version 062 */ | |
/*Chap 3.2.1 64-Bit Mode Execution Environment. Control registers expand to 64 bits*/ | |
u64 cr0, cr3, cr4 = 0; | |
u64 ia32_efer = 0; | |
BUILD_BUG_ON(sizeof(struct page_table) != 4096); | |
BUILD_BUG_ON(sizeof(void *) != 8); | |
BUILD_BUG_ON(PAGE_SIZE != 4096); | |
pr_warn("Hello, world\n"); | |
printk("(%s) x86_phys_bits %hu\n", boot_cpu_data.x86_vendor_id, boot_cpu_data.x86_phys_bits); | |
__asm__ __volatile__ ("mov %%cr0, %%rax \n mov %%rax,%0": "=m" (cr0) : /*InputOperands*/ : "rax"); | |
__asm__ __volatile__ ("mov %%cr3, %%rax \n mov %%rax,%0": "=m" (cr3) : /*InputOperands*/ : "rax"); | |
__asm__ __volatile__ ("mov %%cr4, %%rax \n mov %%rax,%0": "=m" (cr4) : /*InputOperands*/ : "rax"); | |
if(rdmsrl_safe(MSR_EFER, &ia32_efer)){ | |
printk("Error reading MSR\n"); | |
return 1; | |
} | |
printk("cr3: 0x%llx\n", cr3); | |
if(cr3 & 0xfe7 /*ignored*/ | |
|| (cr3 & (0xffffffffffffffffLL << boot_cpu_data.x86_phys_bits) /*reserved*/)){ | |
printk("cr3 looks shady\n"); | |
} | |
if(cr3 & X86_CR3_PWT || cr3 & X86_CR3_PCD){ | |
printk("unexpected options in cr3\n"); | |
} | |
if(cr0 & X86_CR0_PG && cr4 & X86_CR4_PAE && ia32_efer & EFER_LME && !(cr4 & X86_CR4_PCIDE)){ | |
printk("paging according to Tab 4-12 p. 2783 intel dev manual (March 2017)\n"); | |
}else{ | |
printk("unknown paging setup\n"); | |
return -EPERM; /*I'm afraid I can't do that*/ | |
} | |
if(!(cr4 & X86_CR4_PKE)){ | |
printk("No protection keys enabled (this is normal)\n"); | |
} | |
struct page_table *pml4 = phys_to_virt(cr3); | |
printk("page table in virtual memory at %p\n", pml4); | |
if(!virt_addr_valid(pml4) || !IS_ALIGNED(cr3, 4096)){ | |
printk("invalid addr!\n"); | |
return 1; /*error*/ | |
} | |
int i; | |
u64 addr, addr_max; | |
//walk the outermost page table | |
for(i = 0; i < 512; ++i){ | |
u64 e = (u64)pml4->entry[i]; | |
if(!(e & 0x1LL) /*present*/){ | |
WARN_ON(e); | |
continue; | |
} | |
printk("entry %p\n", pml4->entry[i]); | |
//TODO check calculation sanity with /proc/self/maps and /proc/vmallocinfo | |
addr = i; | |
addr <<= 39; //bits 39:47 (inclusive) | |
addr_max = 0x7fffffffffLL; //2**39-1 | |
if(addr & (1LL << 47) /*highest bit set*/){ | |
addr |= (0xffffLL << 48); | |
} | |
addr_max |= addr; | |
printk("v %p %p\n", (void*)addr, (void*)addr_max); | |
} | |
return 0; | |
} | |
module_init(test_module_init); | |
static void __exit test_module_exit(void) | |
{ | |
pr_warn("Goodbye\n"); | |
} | |
module_exit(test_module_exit); | |
MODULE_AUTHOR("Cornelius Diekmann); | |
MODULE_LICENSE("GPL"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment