Added code to setup IRQ's through ioapic but somethings still not working
This commit is contained in:
parent
d4e1c29f07
commit
07e8015800
@ -1,3 +1,4 @@
|
|||||||
obj/src/int.c.o: src/int.c src/print.h src/common.h
|
obj/src/int.c.o: src/int.c src/apic.h src/common.h src/print.h
|
||||||
src/print.h:
|
src/apic.h:
|
||||||
src/common.h:
|
src/common.h:
|
||||||
|
src/print.h:
|
||||||
|
|||||||
BIN
obj/src/int.c.o
BIN
obj/src/int.c.o
Binary file not shown.
@ -1,7 +1,9 @@
|
|||||||
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/alloc.h src/print.h
|
src/common.h src/apic.h src/alloc.h src/map.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/apic.h:
|
||||||
src/alloc.h:
|
src/alloc.h:
|
||||||
|
src/map.h:
|
||||||
src/print.h:
|
src/print.h:
|
||||||
|
|||||||
BIN
obj/src/main.c.o
BIN
obj/src/main.c.o
Binary file not shown.
11
src/alloc.c
11
src/alloc.c
@ -151,12 +151,18 @@ void* alloc(size_t size) {
|
|||||||
size_t page = 0;
|
size_t page = 0;
|
||||||
|
|
||||||
if(pages == 0 || pages >= total_pages) {
|
if(pages == 0 || pages >= total_pages) {
|
||||||
|
print("Too many or too few pages: ");
|
||||||
|
print8(pages);
|
||||||
|
print("\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print("Attempting to find ");
|
||||||
|
print64(pages);
|
||||||
|
print(" consecutive pages\n");
|
||||||
size_t consecutive = 0;
|
size_t consecutive = 0;
|
||||||
|
|
||||||
for(size_t i = 0; i < pages; i++) {
|
for(size_t i = 0; i < total_pages/64; i++) {
|
||||||
u64 word = alloc_bitmap[i];
|
u64 word = alloc_bitmap[i];
|
||||||
if(word == 0) {
|
if(word == 0) {
|
||||||
if(!consecutive)
|
if(!consecutive)
|
||||||
@ -181,7 +187,7 @@ void* alloc(size_t size) {
|
|||||||
|
|
||||||
if(++consecutive >= pages) {
|
if(++consecutive >= pages) {
|
||||||
usepagerange(page, pages);
|
usepagerange(page, pages);
|
||||||
return addr(pages);
|
return addr(page);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
consecutive = 0;
|
consecutive = 0;
|
||||||
@ -190,7 +196,6 @@ void* alloc(size_t size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
109
src/apic.c
109
src/apic.c
@ -11,7 +11,7 @@ enum {
|
|||||||
PIC_DATA_SLAVE = 0xA1,
|
PIC_DATA_SLAVE = 0xA1,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IOAPIC_REG_REDIR(n) (0x10 + 2(n))
|
#define IOAPIC_REG_REDIR(n) (0x10 + 2*(n))
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
IOAPIC_REG_SELECT = 0x00,
|
IOAPIC_REG_SELECT = 0x00,
|
||||||
@ -27,6 +27,7 @@ enum {
|
|||||||
#define IOAPIC_ACTIVE_LOW (1 << 13)
|
#define IOAPIC_ACTIVE_LOW (1 << 13)
|
||||||
#define IOAPIC_ACTIVE_HIGH (0 << 13)
|
#define IOAPIC_ACTIVE_HIGH (0 << 13)
|
||||||
|
|
||||||
|
|
||||||
static void pic_init() {
|
static void pic_init() {
|
||||||
// Start initialization sequence
|
// Start initialization sequence
|
||||||
outb(PIC_COMM_MASTER, 0x11); // ICW1: Initialize in cascading mode
|
outb(PIC_COMM_MASTER, 0x11); // ICW1: Initialize in cascading mode
|
||||||
@ -85,18 +86,29 @@ u64 apic_get_local_base() {
|
|||||||
static u64 apic_set_local_base(u64 base) {
|
static u64 apic_set_local_base(u64 base) {
|
||||||
const u8 APIC_BASE_MSR = 0x1B;
|
const u8 APIC_BASE_MSR = 0x1B;
|
||||||
|
|
||||||
wrmsr(APIC_BASE_MSR, base & 0xfffff000);
|
u64 msr = rdmsr(APIC_BASE_MSR);
|
||||||
|
msr &= 0xFFF; // keep flags
|
||||||
|
msr |= (base & 0xFFFFF000);
|
||||||
|
msr |= (1 << 11); // to ensure APIC is enabled
|
||||||
|
|
||||||
|
wrmsr(APIC_BASE_MSR, msr);
|
||||||
|
|
||||||
return base & 0xfffff000;
|
return base & 0xfffff000;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32* apic_reg(u32 reg) {
|
u32* apic_reg(u32 reg) {
|
||||||
return (u32*) (apic_base + reg);
|
return (u32*) (hhdm_offset + apic_base + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_eoi() {
|
||||||
|
volatile u32* reg= apic_reg(0xB0);
|
||||||
|
*reg = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void apic_enable() {
|
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)) {
|
if(!map_mmio((u64)apic_base, 1<<12)) {
|
||||||
@ -104,15 +116,35 @@ void apic_enable() {
|
|||||||
hang();
|
hang();
|
||||||
}
|
}
|
||||||
|
|
||||||
volatile u32* reg = apic_reg(0xF0);
|
volatile u32* spurious = apic_reg(0xF0);
|
||||||
print("Reg 0xF0 at 0x");
|
print("Reg 0xF0 at 0x");
|
||||||
print64((u64) reg);
|
print64((u64) spurious);
|
||||||
|
print("\nSpurious: ");
|
||||||
|
print32(*spurious);
|
||||||
// set enable flag
|
// set enable flag
|
||||||
*reg = (*reg | 0x100);
|
*spurious |= 0x100;
|
||||||
print("\nReg written\n");
|
print(" after flag: ");
|
||||||
|
print32(*spurious);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
// TPR = 0 (accept all interrupts)
|
||||||
|
volatile u32* tpr = apic_reg(0x80);
|
||||||
|
*tpr = 0;
|
||||||
|
|
||||||
|
// Mask all LVT antries except LINT0 (0x21)
|
||||||
|
|
||||||
|
volatile u32* timer = apic_reg(0x320);
|
||||||
|
*timer = (1 << 16);
|
||||||
|
volatile u32* LINT0 = apic_reg(0x350);
|
||||||
|
*LINT0 = (7 << 8);
|
||||||
|
// *LINT0 = (1 << 16);
|
||||||
|
volatile u32* LINT1 = apic_reg(0x360);
|
||||||
|
*LINT1 = (1 << 16);
|
||||||
|
volatile u32* Error = apic_reg(0x370);
|
||||||
|
*Error = (1 << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32* ioapic_base;
|
static volatile u32* ioapic_base;
|
||||||
|
|
||||||
void ioapic_write(u8 reg, u32 value) {
|
void ioapic_write(u8 reg, u32 value) {
|
||||||
ioapic_base[IOAPIC_REG_SELECT / 4] = reg;
|
ioapic_base[IOAPIC_REG_SELECT / 4] = reg;
|
||||||
@ -124,8 +156,63 @@ u32 ioapic_read(u8 reg) {
|
|||||||
return ioapic_base[IOAPIC_REG_WINDOW / 4];
|
return ioapic_base[IOAPIC_REG_WINDOW / 4];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ioapic_init() {
|
void ioapic_init() {
|
||||||
|
// simply assume it is at the default address
|
||||||
|
ioapic_base = map_mmio(0xFEC00000, 4096);
|
||||||
|
print("IOAPIC BASE: ");
|
||||||
|
print64((u64)ioapic_base);
|
||||||
|
print("\nIOAPIC Version:");
|
||||||
|
ioapic_base[0] = 0x01;
|
||||||
|
print32(ioapic_base[4]);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
// mask all IRQs
|
||||||
|
for(size_t i = 0; i < 24; i++) {
|
||||||
|
u8 vect = 0x20 + i;
|
||||||
|
u32 low = vect | IOAPIC_MASKED | IOAPIC_DST_PHYS | IOAPIC_EDGE_TRIGG | IOAPIC_ACTIVE_HIGH;
|
||||||
|
u32 high = 0;
|
||||||
|
|
||||||
|
ioapic_write(0x10 + i*2, low);
|
||||||
|
ioapic_write(0x10 + i*2 + 1, high);
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup keyboard by selecting IRQ1
|
||||||
|
u8 irq = 1;
|
||||||
|
u8 vect = 0x21;
|
||||||
|
u8 cpu = 0;
|
||||||
|
|
||||||
|
u32 low = ioapic_read(IOAPIC_REG_REDIR(irq));
|
||||||
|
u32 high = ioapic_read(IOAPIC_REG_REDIR(irq)+1);
|
||||||
|
|
||||||
|
|
||||||
|
print("Current redirection for IRQ");
|
||||||
|
print8(irq);
|
||||||
|
print(": ");
|
||||||
|
print32(low);
|
||||||
|
print(" ");
|
||||||
|
print32(high);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
// Configure keyboard - UNMASKED (no IOAPIC_MASKED bit!)
|
||||||
|
low = vect | IOAPIC_DST_PHYS | IOAPIC_EDGE_TRIGG | IOAPIC_ACTIVE_HIGH;
|
||||||
|
high = (cpu << 24);
|
||||||
|
|
||||||
|
ioapic_write(IOAPIC_REG_REDIR(irq), low);
|
||||||
|
ioapic_write(IOAPIC_REG_REDIR(irq)+1, high);
|
||||||
|
|
||||||
|
low = ioapic_read(IOAPIC_REG_REDIR(irq));
|
||||||
|
high = ioapic_read(IOAPIC_REG_REDIR(irq)+1);
|
||||||
|
// Verify it worked
|
||||||
|
print("Current redirection for IRQ");
|
||||||
|
print8(irq);
|
||||||
|
print(": ");
|
||||||
|
print32(low);
|
||||||
|
print(" ");
|
||||||
|
print32(high);
|
||||||
|
print("\n");
|
||||||
|
if (low & IOAPIC_MASKED) {
|
||||||
|
print(" [STILL MASKED (BAD)]\n");
|
||||||
|
} else {
|
||||||
|
print(" [UNMASKED (GOOD)]\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/apic.h
Normal file
11
src/apic.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
u32 apic_get_local_base();
|
||||||
|
void apic_enable();
|
||||||
|
void send_eoi();
|
||||||
|
void ioapic_write(u8 reg, u32 value);
|
||||||
|
u32 ioapic_read(u8 reg);
|
||||||
|
void ioapic_init();
|
||||||
|
u32* apic_reg(u32 reg);
|
||||||
17
src/common.h
17
src/common.h
@ -33,6 +33,23 @@ static inline void outd(u16 port, u32 value) {
|
|||||||
asm volatile ("outl %0, %1" : : "a"(value), "Nd"(port));
|
asm volatile ("outl %0, %1" : : "a"(value), "Nd"(port));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline u8 inb(u16 port) {
|
||||||
|
u8 value;
|
||||||
|
asm volatile ("inb %w1, %b0" : "=a"(value) : "Nd"(port) : "memory");
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
static inline u16 inw(u16 port) {
|
||||||
|
u16 value;
|
||||||
|
asm volatile ("inw %w1, %b0" : "=a"(value) : "Nd"(port) : "memory");
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
static inline u32 ind(u16 port) {
|
||||||
|
u32 value;
|
||||||
|
asm volatile ("ind %w1, %b0" : "=a"(value) : "Nd"(port) : "memory");
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void* memcpy(void* 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);
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "apic.h"
|
||||||
// for debugging
|
// for debugging
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
|
|
||||||
@ -80,7 +81,8 @@ struct cpu_ctx* interrupt_dispatch(struct cpu_ctx* ctx) {
|
|||||||
print("] with message: ");
|
print("] with message: ");
|
||||||
print64(dbg_var);
|
print64(dbg_var);
|
||||||
print("\n");
|
print("\n");
|
||||||
while(1);
|
|
||||||
|
send_eoi();
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
87
src/main.c
87
src/main.c
@ -5,8 +5,10 @@
|
|||||||
#include "../include/limine.h"
|
#include "../include/limine.h"
|
||||||
|
|
||||||
#include "acpi.h"
|
#include "acpi.h"
|
||||||
|
#include "apic.h"
|
||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "map.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
|
|
||||||
// credit owed to https://wiki.osdev.org/Limine_Bare_Bones for the limine setup code
|
// credit owed to https://wiki.osdev.org/Limine_Bare_Bones for the limine setup code
|
||||||
@ -106,9 +108,7 @@ void draw(u8 vect) {
|
|||||||
for(size_t x = 0; x < fb->width; x++) {
|
for(size_t x = 0; x < fb->width; x++) {
|
||||||
volatile u32* fb_ptr = fb->address;
|
volatile u32* fb_ptr = fb->address;
|
||||||
fb_ptr[y * fb->width + x] = (
|
fb_ptr[y * fb->width + x] = (
|
||||||
(x + y) * 0x00010000 |
|
((x ^ y) & 0xff) * 0x0F0003
|
||||||
(x ^ y) * 0x00000100 |
|
|
||||||
(x - y) * 0x00000001
|
|
||||||
)*vect;
|
)*vect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,11 +119,23 @@ extern void init_idt(void);
|
|||||||
extern u32 fg;
|
extern u32 fg;
|
||||||
extern u32 bg;
|
extern u32 bg;
|
||||||
|
|
||||||
|
void enable_ps2_keyboard_interrupts(void) {
|
||||||
|
// Read PS/2 configuration byte
|
||||||
|
outb(0x64, 0x20);
|
||||||
|
while (!(inb(0x64) & 0x01)); // Wait for data
|
||||||
|
u8 config = inb(0x60);
|
||||||
|
|
||||||
|
// Enable keyboard interrupt (bit 0) and clock (clear bit 4)
|
||||||
|
config |= 0x01; // Enable first port interrupt
|
||||||
|
config &= ~0x10; // Enable first port clock
|
||||||
|
|
||||||
u32 apic_get_local_base();
|
// Write config back
|
||||||
void apic_enable();
|
outb(0x64, 0x60);
|
||||||
void setup_identity_mapping();
|
outb(0x60, config);
|
||||||
|
|
||||||
|
// Enable keyboard port
|
||||||
|
outb(0x64, 0xAE);
|
||||||
|
}
|
||||||
|
|
||||||
void kmain() {
|
void kmain() {
|
||||||
if(LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) {
|
if(LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) {
|
||||||
@ -136,10 +148,11 @@ void kmain() {
|
|||||||
|
|
||||||
fb = fb_req.response->framebuffers[0];
|
fb = fb_req.response->framebuffers[0];
|
||||||
|
|
||||||
|
draw(1);
|
||||||
print_init(fb);
|
print_init(fb);
|
||||||
init_idt();
|
init_idt();
|
||||||
|
bg = 0xFFFFFF;
|
||||||
|
fg = 0x000000;
|
||||||
|
|
||||||
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.");
|
||||||
@ -155,6 +168,7 @@ void kmain() {
|
|||||||
|
|
||||||
alloc_init();
|
alloc_init();
|
||||||
|
|
||||||
|
|
||||||
rsdp = (struct acpi_rsdp_header*)(rsdp_req.response->address);
|
rsdp = (struct acpi_rsdp_header*)(rsdp_req.response->address);
|
||||||
|
|
||||||
|
|
||||||
@ -182,13 +196,60 @@ void kmain() {
|
|||||||
/* I should check cpuid to ensure its supported but it will
|
/* I should check cpuid to ensure its supported but it will
|
||||||
* be for my machines ;^) */
|
* be for my machines ;^) */
|
||||||
/* APIC stuff */
|
/* APIC stuff */
|
||||||
u32 r = 0xDEADBEEF;
|
|
||||||
r = apic_get_local_base();
|
|
||||||
print32(r);
|
|
||||||
|
|
||||||
apic_enable();
|
apic_enable();
|
||||||
|
print("APIC Enabled\n");
|
||||||
|
ioapic_init();
|
||||||
|
|
||||||
print("\nAPIC Enabled");
|
if(!test_if_mapped((u64) apic_reg(0))) {
|
||||||
|
print("Mapping APIC registers failed :(\n");
|
||||||
|
hang();
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 id = *apic_reg(0x20);
|
||||||
|
print("LAPIC ID: ");
|
||||||
|
print32(id);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("Enabling keyboard\n");
|
||||||
|
enable_ps2_keyboard_interrupts();
|
||||||
|
|
||||||
|
outb(0x64, 0x20); // Read config
|
||||||
|
while (!(inb(0x64) & 0x01));
|
||||||
|
u8 config = inb(0x60);
|
||||||
|
|
||||||
|
asm volatile("sti");
|
||||||
|
print("Press a key NOW...\n");
|
||||||
|
|
||||||
|
volatile u32* tpr = apic_reg(0x80);
|
||||||
|
print("TPR: 0x");
|
||||||
|
print32(*tpr);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print("PS/2 config: 0x");
|
||||||
|
print8(config);
|
||||||
|
if (!(config & 0x01)) {
|
||||||
|
print("\nProblem: Bit 0 is 0 (interrupt disabled)\n");
|
||||||
|
} else {
|
||||||
|
print("\nOK: Bit 0 is 1 (interrupt enabled)\n");
|
||||||
|
}
|
||||||
|
print("Press keys (polling test)...\n");
|
||||||
|
while (1) {
|
||||||
|
if (inb(0x64) & 0x01) { // Data available
|
||||||
|
u8 code = inb(0x60);
|
||||||
|
print("Scan code: 0x");
|
||||||
|
print8(code);
|
||||||
|
print("\n");
|
||||||
|
volatile u32* irr = apic_reg(0x210);
|
||||||
|
print32(*irr);
|
||||||
|
irr = apic_reg(0x200); // IRR bits 31:0
|
||||||
|
u32* isr = apic_reg(0x100); // ISR bits 31:0
|
||||||
|
|
||||||
|
print("IRR: "); print32(*irr);
|
||||||
|
print(" ISR: "); print32(*isr);
|
||||||
|
print("\n");
|
||||||
|
if (code == 0x01) break; // ESC
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hang();
|
hang();
|
||||||
|
|
||||||
|
|||||||
91
src/map.c
91
src/map.c
@ -39,6 +39,9 @@ static u64 get_cr3() {
|
|||||||
|
|
||||||
static u64 alloc_page_table() {
|
static u64 alloc_page_table() {
|
||||||
void* a = alloc((1<<12) / PAGE_SIZE);
|
void* a = alloc((1<<12) / PAGE_SIZE);
|
||||||
|
if(!a) {
|
||||||
|
print("Failed to allocate page table\n");
|
||||||
|
}
|
||||||
return a? virt_to_phys(a) : 0;
|
return a? virt_to_phys(a) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +50,7 @@ static struct page_entry* get_or_create_table(struct page_entry *table, u64 inde
|
|||||||
if (!table[index].present) {
|
if (!table[index].present) {
|
||||||
u64 new_table_phys = alloc_page_table();
|
u64 new_table_phys = alloc_page_table();
|
||||||
if (new_table_phys == 0) {
|
if (new_table_phys == 0) {
|
||||||
|
print("failed to alloc\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,8 +75,8 @@ void* map_mmio(u64 physical_addr, u64 size) {
|
|||||||
print("\n Size: 0x");
|
print("\n Size: 0x");
|
||||||
print64(size);
|
print64(size);
|
||||||
print(" (");
|
print(" (");
|
||||||
print64(size);
|
print64(size >> 20);
|
||||||
print(" bytes)\n");
|
print(" MiB)\n");
|
||||||
|
|
||||||
// Align physical address down to page boundary
|
// Align physical address down to page boundary
|
||||||
u64 phys_base = physical_addr & ~(PAGE_SIZE-1);
|
u64 phys_base = physical_addr & ~(PAGE_SIZE-1);
|
||||||
@ -154,6 +158,89 @@ void* map_mmio(u64 physical_addr, u64 size) {
|
|||||||
return (void*)(virt_base + offset_in_page);
|
return (void*)(virt_base + offset_in_page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test correct mapping
|
||||||
|
int test_if_mapped(u64 virt_addr) {
|
||||||
|
// Try to read - if we get page fault, it's not mapped
|
||||||
|
// For now, just check the page tables manually
|
||||||
|
|
||||||
|
u64 pml4_idx = (virt_addr >> 39) & 0x1FF;
|
||||||
|
u64 pdpt_idx = (virt_addr >> 30) & 0x1FF;
|
||||||
|
u64 pd_idx = (virt_addr >> 21) & 0x1FF;
|
||||||
|
u64 pt_idx = (virt_addr >> 12) & 0x1FF;
|
||||||
|
|
||||||
|
// Get CR3
|
||||||
|
u64 cr3;
|
||||||
|
asm volatile("mov %%cr3, %0" : "=r"(cr3));
|
||||||
|
u64 pml4_phys = cr3 & ~0xFFF;
|
||||||
|
|
||||||
|
struct page_entry {
|
||||||
|
u64 present : 1;
|
||||||
|
u64 writable : 1;
|
||||||
|
u64 user : 1;
|
||||||
|
u64 write_through : 1;
|
||||||
|
u64 cache_disabled : 1;
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Access PML4
|
||||||
|
struct page_entry *pml4 = (struct page_entry*)(pml4_phys + hhdm_offset);
|
||||||
|
|
||||||
|
if (!pml4[pml4_idx].present) {
|
||||||
|
print(" PML4[");
|
||||||
|
print64(pml4_idx);
|
||||||
|
print("] NOT PRESENT\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Access PDPT
|
||||||
|
struct page_entry *pdpt = (struct page_entry*)(((u64)pml4[pml4_idx].frame << 12) + hhdm_offset);
|
||||||
|
|
||||||
|
if (!pdpt[pdpt_idx].present) {
|
||||||
|
print(" PDPT[");
|
||||||
|
print64(pdpt_idx);
|
||||||
|
print("] NOT PRESENT\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Access PD
|
||||||
|
struct page_entry *pd = (struct page_entry*)(((u64)pdpt[pdpt_idx].frame << 12) + hhdm_offset);
|
||||||
|
|
||||||
|
if (!pd[pd_idx].present) {
|
||||||
|
print(" PD[");
|
||||||
|
print64(pd_idx);
|
||||||
|
print("] NOT PRESENT\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Access PT
|
||||||
|
struct page_entry *pt = (struct page_entry*)(((u64)pd[pd_idx].frame << 12) + hhdm_offset);
|
||||||
|
|
||||||
|
if (!pt[pt_idx].present) {
|
||||||
|
print(" PT[");
|
||||||
|
print64(pt_idx);
|
||||||
|
print("] NOT PRESENT\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
print(" All levels present\n");
|
||||||
|
print(" Physical page: 0x");
|
||||||
|
print64((u64)pt[pt_idx].frame << 12);
|
||||||
|
print("\n");
|
||||||
|
print(" Cache disabled: ");
|
||||||
|
print8(pt[pt_idx].cache_disabled);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Unmap MMIO region
|
// Unmap MMIO region
|
||||||
void unmap_mmio(void *virtual_addr, u64 size) {
|
void unmap_mmio(void *virtual_addr, u64 size) {
|
||||||
u64 virt_base = (u64)virtual_addr & ~0xFFF;
|
u64 virt_base = (u64)virtual_addr & ~0xFFF;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user