- Identity map kernel space and framebuffer
- Setup recursive paging.
Code: Select all
#define MEM_PML4_INDEX(x) ((x >> (MEM_PAGE_SHIFT + 27)) & 0x1FF)
#define MEM_PDPT_INDEX(x) ((x >> (MEM_PAGE_SHIFT + 18)) & 0x1FF)
#define MEM_PAGEDIR_INDEX(x) ((x >> (MEM_PAGE_SHIFT + 9)) & 0x1FF)
#define MEM_PAGETBL_INDEX(x) ((x >> MEM_PAGE_SHIFT) & 0x1FF)
typedef union {
/* Intel SDM page 3206, Table 5-19
* (We only care about 4kb page) */
struct {
uint8_t present : 1; // Must be set if the page actually exists
uint8_t readwrite : 1; // Readonly if not set.
uint8_t user_super : 1; // Set if accessible through user mode
uint8_t pwt : 1;
uint8_t pcd : 1;
uint8_t accessed : 1; // CPU sets whenever the page table entry is accessed.
uint8_t ignored0 : 1;
uint8_t page_size : 1; // Not set if referring to a 4KB page, otherwise 2MB page.
uint8_t ignored1 : 3;
uint8_t hlat_rest : 1; // Ignored, unless HLAT paging.
uint64_t address : 28; // Physical address
uint64_t ignored2 : 23; // Thank you intel, very cool!
uint8_t exec_dis : 1;
} bits;
uint64_t data;
} page_entry;
[...]
void setup_paging(){
uint64_t kernel_start = (uint64_t)&__kernel_start;
uint64_t kernel_end = (uint64_t)&__kernel_end;
uint8_t pg_size = (kernel_end - kernel_start) / PAGE_SIZE;
printf("Mapping %08x -> %08x (kernel space), %d pages\n", kernel_start, kernel_end, pg_size);
for(uint8_t i = 0; i < pg_size; i++){
uint64_t phys = kernel_start + (i*PAGE_SIZE);
page_table[MEM_PAGETBL_INDEX(phys)].data = phys | 0b11;
}
page_directory[MEM_PAGEDIR_INDEX(kernel_start)].data = (uint64_t)&page_table | 0b11;
pdpt[MEM_PDPT_INDEX(kernel_start)].data = (uint64_t)&page_directory | 0b11;
pml4[MEM_PML4_INDEX(kernel_start)].data = (uint64_t)&pdpt | 0b11;
SetCR3(pml4);
}
With the for loop condition being i < pg_size-1, I get the expected result:
Code: Select all
(qemu) info mem
0000000000200000-0000000000212000 0000000000012000 -rw
(qemu) gva2gpa 0x200000
gpa: 0x200000
Why is this happening? If needed, I can provide more code.
Thanks in advance!!!!!!


