Fixed small errors in PIC signalling, added code for allocation and MMIO mapping

This commit is contained in:
Conál Paxton 2026-02-15 05:55:36 -05:00
parent 4ca9447efa
commit d4e1c29f07
19 changed files with 1324 additions and 734 deletions

BIN
bin/os

Binary file not shown.

4
bochs.bxrc Normal file
View File

@ -0,0 +1,4 @@
vga: extension=vgahw
ata0-master: type=disk, path="image.hdd", mode=flat
boot: disk
memory: guest=1024, host=1024

View File

@ -1,3 +0,0 @@
vga: extension=vgahw
display_library: x, options="gui_debug"

26
flake.lock generated
View File

@ -1,26 +0,0 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1770057536,
"narHash": "sha256-Y/Dqu+7StqRVlzQEbow5l2Ws02P9IrHO3eVnpVWbLTE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "79faf5ae0424fe8cd1d07064a513667e6b6ae65a",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

BIN
image.hdd

Binary file not shown.

0
image.hdd.lock Normal file
View File

Binary file not shown.

View File

@ -1,6 +1,7 @@
obj/src/main.c.o: src/main.c src/../include/limine.h src/acpi.h \ obj/src/main.c.o: src/main.c src/../include/limine.h src/acpi.h \
src/common.h src/print.h src/common.h src/alloc.h src/print.h
src/../include/limine.h: src/../include/limine.h:
src/acpi.h: src/acpi.h:
src/common.h: src/common.h:
src/alloc.h:
src/print.h: src/print.h:

Binary file not shown.

196
src/alloc.c Normal file
View File

@ -0,0 +1,196 @@
#include "alloc.h"
#include "common.h"
#include "print.h"
#include "../include/limine.h"
__attribute__((used, section(".limine_requests")))
static volatile struct limine_memmap_request mem_req = {
.id = LIMINE_MEMMAP_REQUEST_ID,
.revision = 0,
};
extern u32 fg, bg;
static void print_memmap_entry(struct limine_memmap_entry* entry) {
u32 savefg = fg;
u32 savebg = bg;
static const char* type_strs[] = {
"Usable",
"Reserved",
"ACPI Reclaimable",
"ACPI NVS",
"BAD!!!",
"Bootloader Reclaimable",
"Executable and Modules",
"Framebuffer",
"ACPI Tables",
};
static u32 type_colors[] = {
0x00AF00,
0xAF1F00,
0x7f7f00,
0x7f7f00,
0xFF0000,
0x007f7f,
0x408000,
0x0000FF,
0x00FF00
};
bg = type_colors[entry->type];
fg = ~bg;
u64 addr = entry->base;
u64 end = addr + entry->length;
print("[");
print(type_strs[entry->type]);
print("]");
print64(addr);
print(" - ");
print64(end);
print("\n");
fg = savefg;
bg = savebg;
}
static size_t total_pages;
static u8* alloc_start;
static u8* alloc_end;
static u8* alloc_next;
static u64* alloc_bitmap;
void alloc_init() {
print("Initializing Page Allocator\n");
if(!mem_req.response) {
print("Failed to get memory map :(\n)");
hang();
}
u64 largest_base = 0;
size_t largest_size = 0;
for(size_t i = 0; i < mem_req.response->entry_count; i++) {
struct limine_memmap_entry* entry = mem_req.response->entries[i];
print_memmap_entry(entry);
if(entry->type == LIMINE_MEMMAP_USABLE) {
if(entry->length > largest_size) {
largest_base = entry->base;
largest_size = entry->length;
print("\t\\LARGEST USABLE: ");
print64(entry->length >> 20);
print("MiB\n");
}
}
}
if(!largest_size) {
print("Couldn't find a free page!!!\n");
hang();
}
total_pages = largest_size / PAGE_SIZE;
size_t usage_bitmap_size = (total_pages + 7) / 8;
total_pages -= (usage_bitmap_size + PAGE_SIZE-1) / PAGE_SIZE;
alloc_bitmap = (u64*)(phys_to_virt(largest_base));
alloc_start = (u8*)(phys_to_virt(largest_base + usage_bitmap_size));
alloc_next = alloc_start;
alloc_end = (u8*)(phys_to_virt(largest_base + largest_size));
}
static size_t page(void* addr) {
return ((u8*)addr - alloc_start) / PAGE_SIZE;
}
static void* addr(size_t page) {
return alloc_start + page*PAGE_SIZE;
}
static void usepage(size_t page) {
size_t idx = page / 64;
size_t bit = page & 63;
alloc_bitmap[idx] |= (1 << bit);
}
static void usepagerange(size_t page, size_t len) {
for(size_t i = 0; i < len; len++) {
usepage(i + page);
}
}
static void unusepage(size_t page) {
size_t idx = page / 64;
size_t bit = page & 63;
alloc_bitmap[idx] &= ~(1 << bit);
}
static void unusepagerange(size_t page, size_t len) {
for(size_t i = 0; i < len; len++) {
unusepage(i+page);
}
}
static u8 getpageusage(size_t page) {
return (alloc_bitmap[page / 8] >> (page & 7)) & 1;
}
void dealloc(void* addr, size_t size) {
// adjust to page size
size_t pages = (size+PAGE_SIZE-1) / PAGE_SIZE;
unusepagerange(page(addr), pages);
}
void* alloc(size_t size) {
size_t pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
size_t page = 0;
if(pages == 0 || pages >= total_pages) {
return NULL;
}
size_t consecutive = 0;
for(size_t i = 0; i < pages; i++) {
u64 word = alloc_bitmap[i];
if(word == 0) {
if(!consecutive)
page = i * 64;
consecutive += 64;
if(consecutive >= pages) {
usepagerange(page, pages);
return addr(page);
}
continue;
}
if(word == ~0ULL) {
consecutive = 0;
page = -1;
}
for(size_t bit = 0; bit < 64; bit++) {
if((word & (1ULL << bit)) == 0) {
if(!consecutive)
page = i * 64 + bit;
if(++consecutive >= pages) {
usepagerange(page, pages);
return addr(pages);
}
} else {
consecutive = 0;
page = -1;
}
}
}
return NULL;
}

16
src/alloc.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include "common.h"
static const size_t PAGE_SIZE = (1 << 12);
void alloc_init();
void* alloc(size_t size);
void dealloc(void* arg, size_t size);
static inline u64 virt_to_phys(void* virt) {
return (u64)virt - hhdm_offset;
}
static inline void* phys_to_virt(u64 phys) {
return (void*)(phys + hhdm_offset);
}

View File

@ -1,16 +1,51 @@
#include "common.h" #include "common.h"
#include "print.h" #include "print.h"
#include "map.h"
// stub of a PIC layout, we don't need the whole thing // stub of a PIC layout, we don't need the whole thing
// as we only care about initializing it to disable it // as we only care about initializing it to disable it
enum { enum {
PIC_COMM_MASTER = 0x20, PIC_COMM_MASTER = 0x20,
PIC_COMM_SLAVE = 0x21, PIC_COMM_SLAVE = 0xA0,
PIC_DATA_MASTER = 0xA0, PIC_DATA_MASTER = 0x21,
PIC_DATA_SLAVE = 0xA1, PIC_DATA_SLAVE = 0xA1,
}; };
#define IOAPIC_REG_REDIR(n) (0x10 + 2(n))
enum {
IOAPIC_REG_SELECT = 0x00,
IOAPIC_REG_WINDOW = 0x10,
};
// I/O APIC redirection entry bits
#define IOAPIC_DST_PHYS (0 << 11)
#define IOAPIC_DST_LOGICAL (1 << 11)
#define IOAPIC_MASKED (1 << 16)
#define IOAPIC_LVL_TRIGG (1 << 15)
#define IOAPIC_EDGE_TRIGG (0 << 15)
#define IOAPIC_ACTIVE_LOW (1 << 13)
#define IOAPIC_ACTIVE_HIGH (0 << 13)
static void pic_init() {
// Start initialization sequence
outb(PIC_COMM_MASTER, 0x11); // ICW1: Initialize in cascading mode
outb(PIC_DATA_MASTER, 0x20); // ICW2: Master PIC vector offset
outb(PIC_DATA_MASTER, 0x04); // ICW3: Slave PIC at IRQ2
outb(PIC_DATA_MASTER, 0x01); // ICW4: 8086/88 (MCS-80 compatible)
outb(PIC_COMM_SLAVE, 0x11); // ICW1: Initialize slave PIC
outb(PIC_DATA_SLAVE, 0x28); // ICW2: Slave PIC vector offset
outb(PIC_DATA_SLAVE, 0x02); // ICW3: It's connected to master PIC
outb(PIC_DATA_SLAVE, 0x01); // ICW4: 8086/88 mode
// Mask all interrupts
outb(PIC_DATA_MASTER, 0xFF);
outb(PIC_DATA_SLAVE, 0xFF);
}
static void pic_disable() { static void pic_disable() {
pic_init();
outb(PIC_DATA_MASTER, ~0); outb(PIC_DATA_MASTER, ~0);
outb(PIC_DATA_SLAVE, ~0); outb(PIC_DATA_SLAVE, ~0);
} }
@ -63,11 +98,34 @@ void apic_enable() {
pic_disable(); pic_disable();
print("\nPIC Disabled\n"); print("\nPIC Disabled\n");
apic_set_local_base(apic_get_local_base()); apic_set_local_base(apic_get_local_base());
if(!map_mmio((u64)apic_base, 1<<12)) {
print("Failed to map APIC registers!\n");
hang();
}
volatile u32* reg = apic_reg(0xF0); volatile u32* reg = apic_reg(0xF0);
print("Local Base Set\nReg 0xF0 at 0x"); print("Reg 0xF0 at 0x");
print64((u64) reg); print64((u64) reg);
// set enable flag // set enable flag
*reg = (*reg | 0x100); *reg = (*reg | 0x100);
print("\nReg written\n"); print("\nReg written\n");
} }
static u32* ioapic_base;
void ioapic_write(u8 reg, u32 value) {
ioapic_base[IOAPIC_REG_SELECT / 4] = reg;
ioapic_base[IOAPIC_REG_WINDOW / 4] = value;
}
u32 ioapic_read(u8 reg) {
ioapic_base[IOAPIC_REG_SELECT / 4] = reg;
return ioapic_base[IOAPIC_REG_WINDOW / 4];
}
void ioapic_init() {
}

View File

@ -34,9 +34,9 @@ static inline void outd(u16 port, u32 value) {
} }
void* memcpy(void* restrict dst, const void* src, size_t n); void* memcpy(void* dst, const void* src, size_t n);
void* memset(void* s, int c, size_t n); void* memset(void* s, int c, size_t n);
void* memmove(void* dst, const void* src, size_t n); void* memmove(void* dst, const void* src, size_t n);
int memcmp(const void* s1, const void* s2, size_t n); int memcmp(const void* s1, const void* s2, size_t n);
void hang();
extern u64 hhdm_offset; extern u64 hhdm_offset;

View File

@ -5,6 +5,7 @@
#include "../include/limine.h" #include "../include/limine.h"
#include "acpi.h" #include "acpi.h"
#include "alloc.h"
#include "common.h" #include "common.h"
#include "print.h" #include "print.h"
@ -20,12 +21,6 @@ static volatile struct limine_framebuffer_request fb_req = {
}; };
__attribute__((used, section(".limine_requests")))
static volatile struct limine_memmap_request mem_req = {
.id = LIMINE_MEMMAP_REQUEST_ID,
.revision = 0,
};
__attribute__((used, section(".limine_requests"))) __attribute__((used, section(".limine_requests")))
static volatile struct limine_hhdm_request hhdm_req = { static volatile struct limine_hhdm_request hhdm_req = {
.id = LIMINE_HHDM_REQUEST_ID, .id = LIMINE_HHDM_REQUEST_ID,
@ -97,7 +92,7 @@ int memcmp(const void* s1, const void* s2, size_t n) {
return 0; return 0;
} }
static void hang() { void hang() {
for(;;) { for(;;) {
asm ("hlt"); asm ("hlt");
} }
@ -123,53 +118,12 @@ extern void init_idt(void);
extern u32 fg; extern u32 fg;
extern u32 bg; extern u32 bg;
void print_memmap_entry(struct limine_memmap_entry* entry) {
u32 savefg = fg;
u32 savebg = bg;
static const char* type_strs[] = {
"Usable",
"Reserved",
"ACPI Reclaimable",
"ACPI NVS",
"BAD!!!",
"Bootloader Reclaimable",
"Executable and Modules",
"Framebuffer",
"ACPI Tables",
};
static u32 type_colors[] = {
0x00AF00,
0xAF1F00,
0x7f7f00,
0x7f7f00,
0xFF0000,
0x007f7f,
0x408000,
0x0000FF,
0x00FF00
};
bg = type_colors[entry->type];
fg = ~bg;
u64 addr = entry->base;
u64 end = addr + entry->length;
print("[");
print(type_strs[entry->type]);
print("]");
print64(addr);
print(" - ");
print64(end);
print("\n");
fg = savefg;
bg = savebg;
}
u32 apic_get_local_base(); u32 apic_get_local_base();
void apic_enable(); void apic_enable();
void setup_identity_mapping();
void kmain() { void kmain() {
if(LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) { if(LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) {
@ -185,10 +139,7 @@ void kmain() {
print_init(fb); print_init(fb);
init_idt(); init_idt();
if(!mem_req.response) {
print("Failed to get memory map :(\n)");
hang();
}
if(!hhdm_req.response) { if(!hhdm_req.response) {
print("Failed to get higher half direct mapping\n."); print("Failed to get higher half direct mapping\n.");
@ -202,11 +153,10 @@ void kmain() {
hang(); hang();
} }
alloc_init();
rsdp = (struct acpi_rsdp_header*)(rsdp_req.response->address); rsdp = (struct acpi_rsdp_header*)(rsdp_req.response->address);
for(size_t i = 0; i < mem_req.response->entry_count; i++) {
print_memmap_entry(mem_req.response->entries[i]);
}
print("Found RSDP @ 0x"); print("Found RSDP @ 0x");
print64((u64)rsdp); print64((u64)rsdp);

388
src/map.c Normal file
View File

@ -0,0 +1,388 @@
#include "alloc.h"
#include "common.h"
#include "print.h"
// MMIO (Memory-Mapped I/O) Mapping for ACPI and other hardware registers
//
// CRITICAL: MMIO regions are NOT regular RAM!
// - They're not in Limine's memory map as "usable"
// - They're often above the RAM limit
// - Limine does NOT map them automatically
// - You must manually map them before accessing
// Page table entry structure
struct page_entry {
u64 present : 1;
u64 writable : 1;
u64 user : 1;
u64 write_through : 1;
u64 cache_disabled : 1; // IMPORTANT for MMIO!
u64 accessed : 1;
u64 dirty : 1;
u64 huge_page : 1;
u64 global : 1;
u64 unused : 3;
u64 frame : 40;
u64 reserved : 11;
u64 no_execute : 1;
};
extern u64 hhdm_offset;
// Get current page tables
static u64 get_cr3() {
u64 cr3;
asm volatile("mov %%cr3, %0" : "=r"(cr3));
return cr3 & ~0xFFF;
}
static u64 alloc_page_table() {
void* a = alloc((1<<12) / PAGE_SIZE);
return a? virt_to_phys(a) : 0;
}
// Get or create a page table entry at any level
static struct page_entry* get_or_create_table(struct page_entry *table, u64 index) {
if (!table[index].present) {
u64 new_table_phys = alloc_page_table();
if (new_table_phys == 0) {
return NULL;
}
table[index].present = 1;
table[index].writable = 1;
table[index].user = 0;
table[index].frame = new_table_phys >> 12;
}
u64 next_table_phys = (u64)table[index].frame << 12;
return (struct page_entry*)phys_to_virt(next_table_phys);
}
// Map a MMIO page with proper cache settings
// physical_addr: Physical address of MMIO region
// size: Size in bytes (will be rounded up to 4KB pages)
// Returns: Virtual address to access the MMIO region
void* map_mmio(u64 physical_addr, u64 size) {
print("Mapping MMIO region:\n");
print(" Physical: 0x");
print64(physical_addr);
print("\n Size: 0x");
print64(size);
print(" (");
print64(size);
print(" bytes)\n");
// Align physical address down to page boundary
u64 phys_base = physical_addr & ~(PAGE_SIZE-1);
u64 offset_in_page = physical_addr & (PAGE_SIZE-1);
// Calculate number of pages needed
u64 total_size = size + offset_in_page;
u64 num_pages = (total_size + PAGE_SIZE - 1) / PAGE_SIZE;
print(" Aligned physical: 0x");
print64(phys_base);
print("\n Offset in page: 0x");
print64(offset_in_page);
print("\n Pages needed: ");
print64(num_pages);
print("\n");
// For MMIO, we typically map to the HHDM region
// Virtual address = Physical address + HHDM offset
u64 virt_base = phys_base + hhdm_offset;
print(" Target virtual: 0x");
print64(virt_base);
print("\n");
// Get current page tables
u64 pml4_phys = get_cr3();
struct page_entry *pml4 = (struct page_entry*)phys_to_virt(pml4_phys);
// Map each page
for (u64 i = 0; i < num_pages; i++) {
u64 current_phys = phys_base + (i * PAGE_SIZE);
u64 current_virt = virt_base + (i * PAGE_SIZE);
// Extract indices
u64 pml4_index = (current_virt >> 39) & 0x1FF;
u64 pdpt_index = (current_virt >> 30) & 0x1FF;
u64 pd_index = (current_virt >> 21) & 0x1FF;
u64 pt_index = (current_virt >> 12) & 0x1FF;
// Walk/create page table hierarchy
struct page_entry *pdpt = get_or_create_table(pml4, pml4_index);
if (!pdpt) {
print("ERROR: Failed to get/create PDPT\n");
return NULL;
}
struct page_entry *pd = get_or_create_table(pdpt, pdpt_index);
if (!pd) {
print("ERROR: Failed to get/create PD\n");
return NULL;
}
struct page_entry *pt = get_or_create_table(pd, pd_index);
if (!pt) {
print("ERROR: Failed to get/create PT\n");
return NULL;
}
// Map the page with MMIO-appropriate settings
pt[pt_index].present = 1;
pt[pt_index].writable = 1;
pt[pt_index].user = 0;
pt[pt_index].cache_disabled = 1; // CRITICAL: Disable caching for MMIO!
pt[pt_index].write_through = 0;
pt[pt_index].no_execute = 1; // Don't execute from MMIO
pt[pt_index].frame = current_phys >> 12;
// Flush TLB for this page
asm volatile("invlpg (%0)" :: "r"(current_virt) : "memory");
}
print(" MMIO mapped successfully!\n");
print(" Access at virtual: 0x");
print64(virt_base + offset_in_page);
print("\n\n");
// Return virtual address (with original offset)
return (void*)(virt_base + offset_in_page);
}
// Unmap MMIO region
void unmap_mmio(void *virtual_addr, u64 size) {
u64 virt_base = (u64)virtual_addr & ~0xFFF;
u64 num_pages = (size + ((u64)virtual_addr & 0xFFF) + 0xFFF) / 4096;
u64 pml4_phys = get_cr3();
struct page_entry *pml4 = (struct page_entry*)phys_to_virt(pml4_phys);
for (u64 i = 0; i < num_pages; i++) {
u64 current_virt = virt_base + (i * 4096);
u64 pml4_index = (current_virt >> 39) & 0x1FF;
u64 pdpt_index = (current_virt >> 30) & 0x1FF;
u64 pd_index = (current_virt >> 21) & 0x1FF;
u64 pt_index = (current_virt >> 12) & 0x1FF;
if (!pml4[pml4_index].present) continue;
struct page_entry *pdpt = phys_to_virt((u64)pml4[pml4_index].frame << 12);
if (!pdpt[pdpt_index].present) continue;
struct page_entry *pd = phys_to_virt((u64)pdpt[pdpt_index].frame << 12);
if (!pd[pd_index].present) continue;
struct page_entry *pt = phys_to_virt((u64)pd[pd_index].frame << 12);
if (!pt[pt_index].present) continue;
// Clear the entry
*((u64*)&pt[pt_index]) = 0;
// Flush TLB
asm volatile("invlpg (%0)" :: "r"(current_virt) : "memory");
}
}
// Check if a physical address is already mapped
int is_mapped(u64 physical_addr) {
u64 virtual_addr = physical_addr + hhdm_offset;
u64 pml4_phys = get_cr3();
struct page_entry *pml4 = phys_to_virt(pml4_phys);
u64 pml4_index = (virtual_addr >> 39) & 0x1FF;
u64 pdpt_index = (virtual_addr >> 30) & 0x1FF;
u64 pd_index = (virtual_addr >> 21) & 0x1FF;
u64 pt_index = (virtual_addr >> 12) & 0x1FF;
if (!pml4[pml4_index].present) return 0;
struct page_entry *pdpt = phys_to_virt((u64)pml4[pml4_index].frame << 12);
if (!pdpt[pdpt_index].present) return 0;
// Check for 1GB huge page
if (pdpt[pdpt_index].huge_page) return 1;
struct page_entry *pd = phys_to_virt((u64)pdpt[pdpt_index].frame << 12);
if (!pd[pd_index].present) return 0;
// Check for 2MB huge page
if (pd[pd_index].huge_page) return 1;
struct page_entry *pt = phys_to_virt((u64)pd[pd_index].frame << 12);
return pt[pt_index].present;
}
// Read from ACPI register (8-bit)
u8 acpi_read8(void *mmio_base, u64 offset) {
volatile u8 *addr = (volatile u8*)((u64)mmio_base + offset);
return *addr;
}
// Read from ACPI register (16-bit)
u16 acpi_read16(void *mmio_base, u64 offset) {
volatile u16 *addr = (volatile u16*)((u64)mmio_base + offset);
return *addr;
}
// Read from ACPI register (32-bit)
u32 acpi_read32(void *mmio_base, u64 offset) {
volatile u32 *addr = (volatile u32*)((u64)mmio_base + offset);
return *addr;
}
// Read from ACPI register (64-bit)
u64 acpi_read64(void *mmio_base, u64 offset) {
volatile u64 *addr = (volatile u64*)((u64)mmio_base + offset);
return *addr;
}
// Write to ACPI register (8-bit)
void acpi_write8(void *mmio_base, u64 offset, u8 value) {
volatile u8 *addr = (volatile u8*)((u64)mmio_base + offset);
*addr = value;
}
// Write to ACPI register (16-bit)
void acpi_write16(void *mmio_base, u64 offset, u16 value) {
volatile u16 *addr = (volatile u16*)((u64)mmio_base + offset);
*addr = value;
}
// Write to ACPI register (32-bit)
void acpi_write32(void *mmio_base, u64 offset, u32 value) {
volatile u32 *addr = (volatile u32*)((u64)mmio_base + offset);
*addr = value;
}
// Write to ACPI register (64-bit)
void acpi_write64(void *mmio_base, u64 offset, u64 value) {
volatile u64 *addr = (volatile u64*)((u64)mmio_base + offset);
*addr = value;
}
// Example: Map and access ACPI PM1a Control Block
void* map_acpi_pm1a_control(u64 physical_addr) {
print("Mapping ACPI PM1a Control Block...\n");
// PM1a Control is typically 2 bytes, but map at least one page
void *mmio = map_mmio(physical_addr, 4096);
if (mmio) {
print("PM1a Control Block mapped at virtual: 0x");
print64((u64)mmio);
print("\n");
}
return mmio;
}
// Example: Map ACPI tables (FADT, MADT, etc.)
void* map_acpi_table(u64 physical_addr, u64 size) {
print("Mapping ACPI table...\n");
print(" Physical: 0x");
print64(physical_addr);
print("\n Size: ");
print64(size);
print(" bytes\n");
void *table = map_mmio(physical_addr, size);
if (table) {
print("ACPI table mapped at virtual: 0x");
print64((u64)table);
print("\n");
}
return table;
}
void print_page_mapping(u64 virtual_addr) {
print("Page mapping for virtual 0x");
print64(virtual_addr);
print(":\n");
u64 pml4_phys = get_cr3();
struct page_entry *pml4 = phys_to_virt(pml4_phys);
u64 pml4_index = (virtual_addr >> 39) & 0x1FF;
u64 pdpt_index = (virtual_addr >> 30) & 0x1FF;
u64 pd_index = (virtual_addr >> 21) & 0x1FF;
u64 pt_index = (virtual_addr >> 12) & 0x1FF;
print(" Indices: PML4[");
print64(pml4_index);
print("] PDPT[");
print64(pdpt_index);
print("] PD[");
print64(pd_index);
print("] PT[");
print64(pt_index);
print("]\n");
if (!pml4[pml4_index].present) {
print(" PML4 entry not present!\n");
return;
}
print(" PML4 entry present, frame=0x");
print64((u64)pml4[pml4_index].frame << 12);
print("\n");
struct page_entry *pdpt = phys_to_virt((u64)pml4[pml4_index].frame << 12);
if (!pdpt[pdpt_index].present) {
print(" PDPT entry not present!\n");
return;
}
print(" PDPT entry present, frame=0x");
print64((u64)pdpt[pdpt_index].frame << 12);
print("\n");
if (pdpt[pdpt_index].huge_page) {
print(" 1GB huge page!\n");
return;
}
struct page_entry *pd = phys_to_virt((u64)pdpt[pdpt_index].frame << 12);
if (!pd[pd_index].present) {
print(" PD entry not present!\n");
return;
}
print(" PD entry present, frame=0x");
print64((u64)pd[pd_index].frame << 12);
print("\n");
if (pd[pd_index].huge_page) {
print(" 2MB huge page!\n");
return;
}
struct page_entry *pt = phys_to_virt((u64)pd[pd_index].frame << 12);
if (!pt[pt_index].present) {
print(" PT entry not present!\n");
return;
}
print(" PT entry present:\n");
print(" Physical frame: 0x");
print64((u64)pt[pt_index].frame << 12);
print("\n Writable: ");
print64(pt[pt_index].writable);
print("\n Cache disabled: ");
print64(pt[pt_index].cache_disabled);
print("\n No execute: ");
print64(pt[pt_index].no_execute);
print("\n");
}

6
src/map.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include "common.h"
void* map_mmio(u64, u64);