Fixed small errors in PIC signalling, added code for allocation and MMIO mapping
This commit is contained in:
parent
4ca9447efa
commit
d4e1c29f07
4
bochs.bxrc
Normal file
4
bochs.bxrc
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
vga: extension=vgahw
|
||||||
|
ata0-master: type=disk, path="image.hdd", mode=flat
|
||||||
|
boot: disk
|
||||||
|
memory: guest=1024, host=1024
|
||||||
26
flake.lock
generated
26
flake.lock
generated
@ -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
|
|
||||||
}
|
|
||||||
0
image.hdd.lock
Normal file
0
image.hdd.lock
Normal file
BIN
obj/src/int.c.o
BIN
obj/src/int.c.o
Binary file not shown.
@ -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:
|
||||||
|
|||||||
BIN
obj/src/main.c.o
BIN
obj/src/main.c.o
Binary file not shown.
34
src/acpi.c
34
src/acpi.c
@ -1,17 +1,17 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
|
|
||||||
#include "../include/limine.h"
|
#include "../include/limine.h"
|
||||||
|
|
||||||
// credit to dreamportdev's OSDev-Notes and the OSDev Wiki for table layouts
|
// credit to dreamportdev's OSDev-Notes and the OSDev Wiki for table layouts
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "acpi.h"
|
#include "acpi.h"
|
||||||
#define RSDT_SIGNATURE "RSDT"
|
#define RSDT_SIGNATURE "RSDT"
|
||||||
#define XSDT_SIGNATURE "XSDT"
|
#define XSDT_SIGNATURE "XSDT"
|
||||||
|
|
||||||
|
|
||||||
static struct acpi_rsdt* rsdt;
|
static struct acpi_rsdt* rsdt;
|
||||||
|
|
||||||
struct acpi_rsdp_header* rsdp;
|
struct acpi_rsdp_header* rsdp;
|
||||||
|
|
||||||
|
|||||||
88
src/acpi.h
88
src/acpi.h
@ -1,44 +1,44 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
#define RSDP_SIGNATURE "RSDT PTR "
|
#define RSDP_SIGNATURE "RSDT PTR "
|
||||||
|
|
||||||
|
|
||||||
pstruct acpi_rsdp_header {
|
pstruct acpi_rsdp_header {
|
||||||
u8 signature[8];
|
u8 signature[8];
|
||||||
u8 checksum;
|
u8 checksum;
|
||||||
u8 OEMID[6];
|
u8 OEMID[6];
|
||||||
u8 revision;
|
u8 revision;
|
||||||
/*
|
/*
|
||||||
union {
|
union {
|
||||||
struct acpi_rsdt* rsdt :32;
|
struct acpi_rsdt* rsdt :32;
|
||||||
struct acpi_xsdt* xsdt :32;
|
struct acpi_xsdt* xsdt :32;
|
||||||
} ptr;
|
} ptr;
|
||||||
*/
|
*/
|
||||||
u32 ptr32;
|
u32 ptr32;
|
||||||
// v2
|
// v2
|
||||||
u32 len;
|
u32 len;
|
||||||
u64 ptr64;
|
u64 ptr64;
|
||||||
u8 extended_checksum;
|
u8 extended_checksum;
|
||||||
u8 resv[3];
|
u8 resv[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct acpi_rsdt {
|
struct acpi_rsdt {
|
||||||
u8 signature[4];
|
u8 signature[4];
|
||||||
u32 len;
|
u32 len;
|
||||||
u8 revision;
|
u8 revision;
|
||||||
u8 checksum;
|
u8 checksum;
|
||||||
u8 OEMID[6];
|
u8 OEMID[6];
|
||||||
u8 OEM_table_id[8];
|
u8 OEM_table_id[8];
|
||||||
u32 OEM_revision;
|
u32 OEM_revision;
|
||||||
u32 creator_id;
|
u32 creator_id;
|
||||||
u32 creator_revision;
|
u32 creator_revision;
|
||||||
union {
|
union {
|
||||||
u32 addrs32[];
|
u32 addrs32[];
|
||||||
u64 addrs64[];
|
u64 addrs64[];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct acpi_rsdp_header* rsdp;
|
extern struct acpi_rsdp_header* rsdp;
|
||||||
|
|||||||
196
src/alloc.c
Normal file
196
src/alloc.c
Normal 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
16
src/alloc.h
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
204
src/apic.c
204
src/apic.c
@ -1,73 +1,131 @@
|
|||||||
#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
|
|
||||||
// as we only care about initializing it to disable it
|
// stub of a PIC layout, we don't need the whole thing
|
||||||
enum {
|
// as we only care about initializing it to disable it
|
||||||
PIC_COMM_MASTER = 0x20,
|
enum {
|
||||||
PIC_COMM_SLAVE = 0x21,
|
PIC_COMM_MASTER = 0x20,
|
||||||
PIC_DATA_MASTER = 0xA0,
|
PIC_COMM_SLAVE = 0xA0,
|
||||||
PIC_DATA_SLAVE = 0xA1,
|
PIC_DATA_MASTER = 0x21,
|
||||||
};
|
PIC_DATA_SLAVE = 0xA1,
|
||||||
|
};
|
||||||
static void pic_disable() {
|
|
||||||
outb(PIC_DATA_MASTER, ~0);
|
#define IOAPIC_REG_REDIR(n) (0x10 + 2(n))
|
||||||
outb(PIC_DATA_SLAVE, ~0);
|
|
||||||
}
|
enum {
|
||||||
|
IOAPIC_REG_SELECT = 0x00,
|
||||||
static inline u64 rdmsr(u32 msr) {
|
IOAPIC_REG_WINDOW = 0x10,
|
||||||
u32 hi, lo;
|
};
|
||||||
asm volatile (
|
|
||||||
"rdmsr"
|
// I/O APIC redirection entry bits
|
||||||
: "=a"(lo), "=d"(hi)
|
#define IOAPIC_DST_PHYS (0 << 11)
|
||||||
: "c"(msr)
|
#define IOAPIC_DST_LOGICAL (1 << 11)
|
||||||
);
|
#define IOAPIC_MASKED (1 << 16)
|
||||||
|
#define IOAPIC_LVL_TRIGG (1 << 15)
|
||||||
return (((u64)hi) << 32) | (u64)lo;
|
#define IOAPIC_EDGE_TRIGG (0 << 15)
|
||||||
}
|
#define IOAPIC_ACTIVE_LOW (1 << 13)
|
||||||
|
#define IOAPIC_ACTIVE_HIGH (0 << 13)
|
||||||
static inline void wrmsr(u32 msr, u64 val) {
|
|
||||||
u32 eax = (u32) val;
|
static void pic_init() {
|
||||||
u32 edx = (u32) (val >> 32);
|
// Start initialization sequence
|
||||||
asm volatile (
|
outb(PIC_COMM_MASTER, 0x11); // ICW1: Initialize in cascading mode
|
||||||
"wrmsr"
|
outb(PIC_DATA_MASTER, 0x20); // ICW2: Master PIC vector offset
|
||||||
:
|
outb(PIC_DATA_MASTER, 0x04); // ICW3: Slave PIC at IRQ2
|
||||||
: "c"(msr), "a" (eax), "d" (edx)
|
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
|
||||||
static u64 apic_base;
|
outb(PIC_DATA_SLAVE, 0x01); // ICW4: 8086/88 mode
|
||||||
|
|
||||||
u64 apic_get_local_base() {
|
// Mask all interrupts
|
||||||
const u8 APIC_BASE_MSR = 0x1B;
|
outb(PIC_DATA_MASTER, 0xFF);
|
||||||
|
outb(PIC_DATA_SLAVE, 0xFF);
|
||||||
u64 msr = rdmsr(APIC_BASE_MSR);
|
}
|
||||||
|
|
||||||
return (apic_base = (msr & 0xfffff000));
|
static void pic_disable() {
|
||||||
}
|
pic_init();
|
||||||
|
outb(PIC_DATA_MASTER, ~0);
|
||||||
static u64 apic_set_local_base(u64 base) {
|
outb(PIC_DATA_SLAVE, ~0);
|
||||||
const u8 APIC_BASE_MSR = 0x1B;
|
}
|
||||||
|
|
||||||
wrmsr(APIC_BASE_MSR, base & 0xfffff000);
|
static inline u64 rdmsr(u32 msr) {
|
||||||
|
u32 hi, lo;
|
||||||
return base & 0xfffff000;
|
asm volatile (
|
||||||
}
|
"rdmsr"
|
||||||
|
: "=a"(lo), "=d"(hi)
|
||||||
static u32* apic_reg(u32 reg) {
|
: "c"(msr)
|
||||||
return (u32*) (apic_base + reg);
|
);
|
||||||
}
|
|
||||||
|
return (((u64)hi) << 32) | (u64)lo;
|
||||||
void apic_enable() {
|
}
|
||||||
pic_disable();
|
|
||||||
print("\nPIC Disabled\n");
|
static inline void wrmsr(u32 msr, u64 val) {
|
||||||
apic_set_local_base(apic_get_local_base());
|
u32 eax = (u32) val;
|
||||||
volatile u32* reg = apic_reg(0xF0);
|
u32 edx = (u32) (val >> 32);
|
||||||
print("Local Base Set\nReg 0xF0 at 0x");
|
asm volatile (
|
||||||
print64((u64) reg);
|
"wrmsr"
|
||||||
// set enable flag
|
:
|
||||||
*reg = (*reg | 0x100);
|
: "c"(msr), "a" (eax), "d" (edx)
|
||||||
print("\nReg written\n");
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u64 apic_base;
|
||||||
|
|
||||||
|
u64 apic_get_local_base() {
|
||||||
|
const u8 APIC_BASE_MSR = 0x1B;
|
||||||
|
|
||||||
|
u64 msr = rdmsr(APIC_BASE_MSR);
|
||||||
|
|
||||||
|
return (apic_base = (msr & 0xfffff000));
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 apic_set_local_base(u64 base) {
|
||||||
|
const u8 APIC_BASE_MSR = 0x1B;
|
||||||
|
|
||||||
|
wrmsr(APIC_BASE_MSR, base & 0xfffff000);
|
||||||
|
|
||||||
|
return base & 0xfffff000;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32* apic_reg(u32 reg) {
|
||||||
|
return (u32*) (apic_base + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void apic_enable() {
|
||||||
|
pic_disable();
|
||||||
|
print("\nPIC Disabled\n");
|
||||||
|
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);
|
||||||
|
print("Reg 0xF0 at 0x");
|
||||||
|
print64((u64) reg);
|
||||||
|
// set enable flag
|
||||||
|
*reg = (*reg | 0x100);
|
||||||
|
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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
84
src/common.h
84
src/common.h
@ -1,42 +1,42 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define pstruct struct __attribute__((packed))
|
#define pstruct struct __attribute__((packed))
|
||||||
|
|
||||||
typedef uint8_t u8;
|
typedef uint8_t u8;
|
||||||
typedef uint16_t u16;
|
typedef uint16_t u16;
|
||||||
typedef uint32_t u32;
|
typedef uint32_t u32;
|
||||||
typedef uint64_t u64;
|
typedef uint64_t u64;
|
||||||
typedef int8_t i8;
|
typedef int8_t i8;
|
||||||
typedef int16_t i16;
|
typedef int16_t i16;
|
||||||
typedef int32_t i32;
|
typedef int32_t i32;
|
||||||
typedef int64_t i64;
|
typedef int64_t i64;
|
||||||
|
|
||||||
static inline void INT(int n) {
|
static inline void INT(int n) {
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"int %0"
|
"int %0"
|
||||||
:
|
:
|
||||||
: "i"(n)
|
: "i"(n)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void outb(u16 port, u8 value) {
|
static inline void outb(u16 port, u8 value) {
|
||||||
asm volatile ("outb %0, %1" : : "a"(value), "Nd"(port));
|
asm volatile ("outb %0, %1" : : "a"(value), "Nd"(port));
|
||||||
}
|
}
|
||||||
static inline void outw(u16 port, u16 value) {
|
static inline void outw(u16 port, u16 value) {
|
||||||
asm volatile ("outw %0, %1" : : "a"(value), "Nd"(port));
|
asm volatile ("outw %0, %1" : : "a"(value), "Nd"(port));
|
||||||
}
|
}
|
||||||
static inline void outd(u16 port, u32 value) {
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
564
src/int.c
564
src/int.c
@ -1,282 +1,282 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
// for debugging
|
// for debugging
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
// for trap debugging
|
// for trap debugging
|
||||||
u64 dbg_var = 0;
|
u64 dbg_var = 0;
|
||||||
|
|
||||||
pstruct int_desc {
|
pstruct int_desc {
|
||||||
u16 addr_low;
|
u16 addr_low;
|
||||||
u16 selector;
|
u16 selector;
|
||||||
u8 ist;
|
u8 ist;
|
||||||
u8 flags;
|
u8 flags;
|
||||||
u16 addr_mid;
|
u16 addr_mid;
|
||||||
u32 addr_high;
|
u32 addr_high;
|
||||||
u32 resv;
|
u32 resv;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum INT_DESC_FLAGS {
|
enum INT_DESC_FLAGS {
|
||||||
ID_GATE_INT = 0b00001110,
|
ID_GATE_INT = 0b00001110,
|
||||||
ID_GATE_TRAP = 0b00001111,
|
ID_GATE_TRAP = 0b00001111,
|
||||||
ID_DPL = 0b00100000,
|
ID_DPL = 0b00100000,
|
||||||
ID_PRESENT = 0b10000000,
|
ID_PRESENT = 0b10000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define CODE64_SELECTOR 0x28
|
#define CODE64_SELECTOR 0x28
|
||||||
|
|
||||||
struct int_desc idt[256];
|
struct int_desc idt[256];
|
||||||
|
|
||||||
void set_idt(u8 vect, void* handler, u8 dpl) {
|
void set_idt(u8 vect, void* handler, u8 dpl) {
|
||||||
struct int_desc* ent = &idt[vect];
|
struct int_desc* ent = &idt[vect];
|
||||||
u64 addr = (u64) handler;
|
u64 addr = (u64) handler;
|
||||||
ent->addr_low = addr & 0xFFFF;
|
ent->addr_low = addr & 0xFFFF;
|
||||||
ent->addr_mid = (addr >> 16) & 0xFFFF;
|
ent->addr_mid = (addr >> 16) & 0xFFFF;
|
||||||
ent->addr_high = addr >> 32;
|
ent->addr_high = addr >> 32;
|
||||||
|
|
||||||
ent->selector = CODE64_SELECTOR;
|
ent->selector = CODE64_SELECTOR;
|
||||||
ent->flags = ID_GATE_INT | dpl*ID_DPL | ID_PRESENT;
|
ent->flags = ID_GATE_INT | dpl*ID_DPL | ID_PRESENT;
|
||||||
ent->ist = 0;
|
ent->ist = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pstruct idtr {
|
pstruct idtr {
|
||||||
u16 limit;
|
u16 limit;
|
||||||
u64 base;
|
u64 base;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IDTR_LIMIT (sizeof(struct int_desc)*256 - 1)
|
#define IDTR_LIMIT (sizeof(struct int_desc)*256 - 1)
|
||||||
|
|
||||||
void load_idt(void* addr) {
|
void load_idt(void* addr) {
|
||||||
struct idtr ir = (struct idtr) {
|
struct idtr ir = (struct idtr) {
|
||||||
.limit = IDTR_LIMIT,
|
.limit = IDTR_LIMIT,
|
||||||
.base = (u64) addr,
|
.base = (u64) addr,
|
||||||
};
|
};
|
||||||
|
|
||||||
asm volatile("lidt %0" :: "m"(ir));
|
asm volatile("lidt %0" :: "m"(ir));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void draw(u8 vect);
|
extern void draw(u8 vect);
|
||||||
|
|
||||||
struct cpu_ctx {
|
struct cpu_ctx {
|
||||||
u64 r15, r14, r13, r12, r11, r10, r9, r8, rdi, rsi, rdx, rcx, rbx, rax;
|
u64 r15, r14, r13, r12, r11, r10, r9, r8, rdi, rsi, rdx, rcx, rbx, rax;
|
||||||
|
|
||||||
u64 vect;
|
u64 vect;
|
||||||
u64 err;
|
u64 err;
|
||||||
|
|
||||||
u64 iret_rip;
|
u64 iret_rip;
|
||||||
u64 iret_cs;
|
u64 iret_cs;
|
||||||
u64 iret_flags;
|
u64 iret_flags;
|
||||||
u64 iret_rsp;
|
u64 iret_rsp;
|
||||||
u64 iret_ss;
|
u64 iret_ss;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cpu_ctx* interrupt_dispatch(struct cpu_ctx* ctx) {
|
struct cpu_ctx* interrupt_dispatch(struct cpu_ctx* ctx) {
|
||||||
print("\n[IRQ ");
|
print("\n[IRQ ");
|
||||||
print8(ctx->vect);
|
print8(ctx->vect);
|
||||||
print("] with message: ");
|
print("] with message: ");
|
||||||
print64(dbg_var);
|
print64(dbg_var);
|
||||||
print("\n");
|
print("\n");
|
||||||
while(1);
|
while(1);
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((naked))
|
__attribute__((naked))
|
||||||
void int_stub(void) {
|
void int_stub(void) {
|
||||||
__asm__ volatile (
|
__asm__ volatile (
|
||||||
"push %%rax\n"
|
"push %%rax\n"
|
||||||
"push %%rbx\n"
|
"push %%rbx\n"
|
||||||
"push %%rcx\n"
|
"push %%rcx\n"
|
||||||
"push %%rdx\n"
|
"push %%rdx\n"
|
||||||
"push %%rsi\n"
|
"push %%rsi\n"
|
||||||
"push %%rdi\n"
|
"push %%rdi\n"
|
||||||
"push %%r8\n"
|
"push %%r8\n"
|
||||||
"push %%r9\n"
|
"push %%r9\n"
|
||||||
"push %%r10\n"
|
"push %%r10\n"
|
||||||
"push %%r11\n"
|
"push %%r11\n"
|
||||||
"push %%r12\n"
|
"push %%r12\n"
|
||||||
"push %%r13\n"
|
"push %%r13\n"
|
||||||
"push %%r14\n"
|
"push %%r14\n"
|
||||||
"push %%r15\n"
|
"push %%r15\n"
|
||||||
"mov %%rsp, %%rdi\n"
|
"mov %%rsp, %%rdi\n"
|
||||||
"call interrupt_dispatch\n"
|
"call interrupt_dispatch\n"
|
||||||
"mov %%rax, %%rsp\n"
|
"mov %%rax, %%rsp\n"
|
||||||
"pop %%r15\n"
|
"pop %%r15\n"
|
||||||
"pop %%r14\n"
|
"pop %%r14\n"
|
||||||
"pop %%r13\n"
|
"pop %%r13\n"
|
||||||
"pop %%r12\n"
|
"pop %%r12\n"
|
||||||
"pop %%r11\n"
|
"pop %%r11\n"
|
||||||
"pop %%r10\n"
|
"pop %%r10\n"
|
||||||
"pop %%r9\n"
|
"pop %%r9\n"
|
||||||
"pop %%r8\n"
|
"pop %%r8\n"
|
||||||
"pop %%rdi\n"
|
"pop %%rdi\n"
|
||||||
"pop %%rsi\n"
|
"pop %%rsi\n"
|
||||||
"pop %%rdx\n"
|
"pop %%rdx\n"
|
||||||
"pop %%rcx\n"
|
"pop %%rcx\n"
|
||||||
"pop %%rbx\n"
|
"pop %%rbx\n"
|
||||||
"pop %%rax\n"
|
"pop %%rax\n"
|
||||||
"add $16, %%rsp\n"
|
"add $16, %%rsp\n"
|
||||||
"iretq\n"
|
"iretq\n"
|
||||||
:
|
:
|
||||||
:
|
:
|
||||||
: "memory"
|
: "memory"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Macro to generate interrupt stubs without error codes (push dummy 0)
|
// Macro to generate interrupt stubs without error codes (push dummy 0)
|
||||||
#define ISR_NO_ERR(num) \
|
#define ISR_NO_ERR(num) \
|
||||||
__attribute__((naked)) void isr##num(void) { \
|
__attribute__((naked)) void isr##num(void) { \
|
||||||
asm volatile( \
|
asm volatile( \
|
||||||
"push $0\n" \
|
"push $0\n" \
|
||||||
"push %0\n" \
|
"push %0\n" \
|
||||||
"jmp int_stub\n" \
|
"jmp int_stub\n" \
|
||||||
: : "i"(num)); \
|
: : "i"(num)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
// Macro to generate interrupt stubs with error codes
|
// Macro to generate interrupt stubs with error codes
|
||||||
#define ISR_ERR(num) \
|
#define ISR_ERR(num) \
|
||||||
__attribute__((naked)) void isr##num(void) { \
|
__attribute__((naked)) void isr##num(void) { \
|
||||||
asm volatile( \
|
asm volatile( \
|
||||||
"push %0\n" \
|
"push %0\n" \
|
||||||
"jmp int_stub\n" \
|
"jmp int_stub\n" \
|
||||||
: : "i"(num)); \
|
: : "i"(num)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
// CPU exceptions (0-31)
|
// CPU exceptions (0-31)
|
||||||
ISR_NO_ERR(0) // Divide by zero
|
ISR_NO_ERR(0) // Divide by zero
|
||||||
ISR_NO_ERR(1) // Debug
|
ISR_NO_ERR(1) // Debug
|
||||||
ISR_NO_ERR(2) // NMI
|
ISR_NO_ERR(2) // NMI
|
||||||
ISR_NO_ERR(3) // Breakpoint
|
ISR_NO_ERR(3) // Breakpoint
|
||||||
ISR_NO_ERR(4) // Overflow
|
ISR_NO_ERR(4) // Overflow
|
||||||
ISR_NO_ERR(5) // Bound range exceeded
|
ISR_NO_ERR(5) // Bound range exceeded
|
||||||
ISR_NO_ERR(6) // Invalid opcode
|
ISR_NO_ERR(6) // Invalid opcode
|
||||||
ISR_NO_ERR(7) // Device not available
|
ISR_NO_ERR(7) // Device not available
|
||||||
ISR_ERR(8) // Double fault (pushes error code)
|
ISR_ERR(8) // Double fault (pushes error code)
|
||||||
ISR_NO_ERR(9) // Coprocessor segment overrun
|
ISR_NO_ERR(9) // Coprocessor segment overrun
|
||||||
ISR_ERR(10) // Invalid TSS (pushes error code)
|
ISR_ERR(10) // Invalid TSS (pushes error code)
|
||||||
ISR_ERR(11) // Segment not present (pushes error code)
|
ISR_ERR(11) // Segment not present (pushes error code)
|
||||||
ISR_ERR(12) // Stack-segment fault (pushes error code)
|
ISR_ERR(12) // Stack-segment fault (pushes error code)
|
||||||
ISR_ERR(13) // General protection fault (pushes error code)
|
ISR_ERR(13) // General protection fault (pushes error code)
|
||||||
ISR_ERR(14) // Page fault (pushes error code)
|
ISR_ERR(14) // Page fault (pushes error code)
|
||||||
ISR_NO_ERR(15) // Reserved
|
ISR_NO_ERR(15) // Reserved
|
||||||
ISR_NO_ERR(16) // x87 FPU error
|
ISR_NO_ERR(16) // x87 FPU error
|
||||||
ISR_ERR(17) // Alignment check (pushes error code)
|
ISR_ERR(17) // Alignment check (pushes error code)
|
||||||
ISR_NO_ERR(18) // Machine check
|
ISR_NO_ERR(18) // Machine check
|
||||||
ISR_NO_ERR(19) // SIMD floating-point exception
|
ISR_NO_ERR(19) // SIMD floating-point exception
|
||||||
ISR_NO_ERR(20) // Virtualization exception
|
ISR_NO_ERR(20) // Virtualization exception
|
||||||
ISR_ERR(21) // Control protection exception (pushes error code)
|
ISR_ERR(21) // Control protection exception (pushes error code)
|
||||||
ISR_NO_ERR(22) // Reserved
|
ISR_NO_ERR(22) // Reserved
|
||||||
ISR_NO_ERR(23) // Reserved
|
ISR_NO_ERR(23) // Reserved
|
||||||
ISR_NO_ERR(24) // Reserved
|
ISR_NO_ERR(24) // Reserved
|
||||||
ISR_NO_ERR(25) // Reserved
|
ISR_NO_ERR(25) // Reserved
|
||||||
ISR_NO_ERR(26) // Reserved
|
ISR_NO_ERR(26) // Reserved
|
||||||
ISR_NO_ERR(27) // Reserved
|
ISR_NO_ERR(27) // Reserved
|
||||||
ISR_NO_ERR(28) // Reserved
|
ISR_NO_ERR(28) // Reserved
|
||||||
ISR_NO_ERR(29) // Reserved
|
ISR_NO_ERR(29) // Reserved
|
||||||
ISR_ERR(30) // Security exception (pushes error code)
|
ISR_ERR(30) // Security exception (pushes error code)
|
||||||
ISR_NO_ERR(31) // Reserved
|
ISR_NO_ERR(31) // Reserved
|
||||||
|
|
||||||
// IRQs and user-defined interrupts (32-255)
|
// IRQs and user-defined interrupts (32-255)
|
||||||
ISR_NO_ERR(32) ISR_NO_ERR(33) ISR_NO_ERR(34) ISR_NO_ERR(35)
|
ISR_NO_ERR(32) ISR_NO_ERR(33) ISR_NO_ERR(34) ISR_NO_ERR(35)
|
||||||
ISR_NO_ERR(36) ISR_NO_ERR(37) ISR_NO_ERR(38) ISR_NO_ERR(39)
|
ISR_NO_ERR(36) ISR_NO_ERR(37) ISR_NO_ERR(38) ISR_NO_ERR(39)
|
||||||
ISR_NO_ERR(40) ISR_NO_ERR(41) ISR_NO_ERR(42) ISR_NO_ERR(43)
|
ISR_NO_ERR(40) ISR_NO_ERR(41) ISR_NO_ERR(42) ISR_NO_ERR(43)
|
||||||
ISR_NO_ERR(44) ISR_NO_ERR(45) ISR_NO_ERR(46) ISR_NO_ERR(47)
|
ISR_NO_ERR(44) ISR_NO_ERR(45) ISR_NO_ERR(46) ISR_NO_ERR(47)
|
||||||
ISR_NO_ERR(48) ISR_NO_ERR(49) ISR_NO_ERR(50) ISR_NO_ERR(51)
|
ISR_NO_ERR(48) ISR_NO_ERR(49) ISR_NO_ERR(50) ISR_NO_ERR(51)
|
||||||
ISR_NO_ERR(52) ISR_NO_ERR(53) ISR_NO_ERR(54) ISR_NO_ERR(55)
|
ISR_NO_ERR(52) ISR_NO_ERR(53) ISR_NO_ERR(54) ISR_NO_ERR(55)
|
||||||
ISR_NO_ERR(56) ISR_NO_ERR(57) ISR_NO_ERR(58) ISR_NO_ERR(59)
|
ISR_NO_ERR(56) ISR_NO_ERR(57) ISR_NO_ERR(58) ISR_NO_ERR(59)
|
||||||
ISR_NO_ERR(60) ISR_NO_ERR(61) ISR_NO_ERR(62) ISR_NO_ERR(63)
|
ISR_NO_ERR(60) ISR_NO_ERR(61) ISR_NO_ERR(62) ISR_NO_ERR(63)
|
||||||
ISR_NO_ERR(64) ISR_NO_ERR(65) ISR_NO_ERR(66) ISR_NO_ERR(67)
|
ISR_NO_ERR(64) ISR_NO_ERR(65) ISR_NO_ERR(66) ISR_NO_ERR(67)
|
||||||
ISR_NO_ERR(68) ISR_NO_ERR(69) ISR_NO_ERR(70) ISR_NO_ERR(71)
|
ISR_NO_ERR(68) ISR_NO_ERR(69) ISR_NO_ERR(70) ISR_NO_ERR(71)
|
||||||
ISR_NO_ERR(72) ISR_NO_ERR(73) ISR_NO_ERR(74) ISR_NO_ERR(75)
|
ISR_NO_ERR(72) ISR_NO_ERR(73) ISR_NO_ERR(74) ISR_NO_ERR(75)
|
||||||
ISR_NO_ERR(76) ISR_NO_ERR(77) ISR_NO_ERR(78) ISR_NO_ERR(79)
|
ISR_NO_ERR(76) ISR_NO_ERR(77) ISR_NO_ERR(78) ISR_NO_ERR(79)
|
||||||
ISR_NO_ERR(80) ISR_NO_ERR(81) ISR_NO_ERR(82) ISR_NO_ERR(83)
|
ISR_NO_ERR(80) ISR_NO_ERR(81) ISR_NO_ERR(82) ISR_NO_ERR(83)
|
||||||
ISR_NO_ERR(84) ISR_NO_ERR(85) ISR_NO_ERR(86) ISR_NO_ERR(87)
|
ISR_NO_ERR(84) ISR_NO_ERR(85) ISR_NO_ERR(86) ISR_NO_ERR(87)
|
||||||
ISR_NO_ERR(88) ISR_NO_ERR(89) ISR_NO_ERR(90) ISR_NO_ERR(91)
|
ISR_NO_ERR(88) ISR_NO_ERR(89) ISR_NO_ERR(90) ISR_NO_ERR(91)
|
||||||
ISR_NO_ERR(92) ISR_NO_ERR(93) ISR_NO_ERR(94) ISR_NO_ERR(95)
|
ISR_NO_ERR(92) ISR_NO_ERR(93) ISR_NO_ERR(94) ISR_NO_ERR(95)
|
||||||
ISR_NO_ERR(96) ISR_NO_ERR(97) ISR_NO_ERR(98) ISR_NO_ERR(99)
|
ISR_NO_ERR(96) ISR_NO_ERR(97) ISR_NO_ERR(98) ISR_NO_ERR(99)
|
||||||
ISR_NO_ERR(100) ISR_NO_ERR(101) ISR_NO_ERR(102) ISR_NO_ERR(103)
|
ISR_NO_ERR(100) ISR_NO_ERR(101) ISR_NO_ERR(102) ISR_NO_ERR(103)
|
||||||
ISR_NO_ERR(104) ISR_NO_ERR(105) ISR_NO_ERR(106) ISR_NO_ERR(107)
|
ISR_NO_ERR(104) ISR_NO_ERR(105) ISR_NO_ERR(106) ISR_NO_ERR(107)
|
||||||
ISR_NO_ERR(108) ISR_NO_ERR(109) ISR_NO_ERR(110) ISR_NO_ERR(111)
|
ISR_NO_ERR(108) ISR_NO_ERR(109) ISR_NO_ERR(110) ISR_NO_ERR(111)
|
||||||
ISR_NO_ERR(112) ISR_NO_ERR(113) ISR_NO_ERR(114) ISR_NO_ERR(115)
|
ISR_NO_ERR(112) ISR_NO_ERR(113) ISR_NO_ERR(114) ISR_NO_ERR(115)
|
||||||
ISR_NO_ERR(116) ISR_NO_ERR(117) ISR_NO_ERR(118) ISR_NO_ERR(119)
|
ISR_NO_ERR(116) ISR_NO_ERR(117) ISR_NO_ERR(118) ISR_NO_ERR(119)
|
||||||
ISR_NO_ERR(120) ISR_NO_ERR(121) ISR_NO_ERR(122) ISR_NO_ERR(123)
|
ISR_NO_ERR(120) ISR_NO_ERR(121) ISR_NO_ERR(122) ISR_NO_ERR(123)
|
||||||
ISR_NO_ERR(124) ISR_NO_ERR(125) ISR_NO_ERR(126) ISR_NO_ERR(127)
|
ISR_NO_ERR(124) ISR_NO_ERR(125) ISR_NO_ERR(126) ISR_NO_ERR(127)
|
||||||
ISR_NO_ERR(128) ISR_NO_ERR(129) ISR_NO_ERR(130) ISR_NO_ERR(131)
|
ISR_NO_ERR(128) ISR_NO_ERR(129) ISR_NO_ERR(130) ISR_NO_ERR(131)
|
||||||
ISR_NO_ERR(132) ISR_NO_ERR(133) ISR_NO_ERR(134) ISR_NO_ERR(135)
|
ISR_NO_ERR(132) ISR_NO_ERR(133) ISR_NO_ERR(134) ISR_NO_ERR(135)
|
||||||
ISR_NO_ERR(136) ISR_NO_ERR(137) ISR_NO_ERR(138) ISR_NO_ERR(139)
|
ISR_NO_ERR(136) ISR_NO_ERR(137) ISR_NO_ERR(138) ISR_NO_ERR(139)
|
||||||
ISR_NO_ERR(140) ISR_NO_ERR(141) ISR_NO_ERR(142) ISR_NO_ERR(143)
|
ISR_NO_ERR(140) ISR_NO_ERR(141) ISR_NO_ERR(142) ISR_NO_ERR(143)
|
||||||
ISR_NO_ERR(144) ISR_NO_ERR(145) ISR_NO_ERR(146) ISR_NO_ERR(147)
|
ISR_NO_ERR(144) ISR_NO_ERR(145) ISR_NO_ERR(146) ISR_NO_ERR(147)
|
||||||
ISR_NO_ERR(148) ISR_NO_ERR(149) ISR_NO_ERR(150) ISR_NO_ERR(151)
|
ISR_NO_ERR(148) ISR_NO_ERR(149) ISR_NO_ERR(150) ISR_NO_ERR(151)
|
||||||
ISR_NO_ERR(152) ISR_NO_ERR(153) ISR_NO_ERR(154) ISR_NO_ERR(155)
|
ISR_NO_ERR(152) ISR_NO_ERR(153) ISR_NO_ERR(154) ISR_NO_ERR(155)
|
||||||
ISR_NO_ERR(156) ISR_NO_ERR(157) ISR_NO_ERR(158) ISR_NO_ERR(159)
|
ISR_NO_ERR(156) ISR_NO_ERR(157) ISR_NO_ERR(158) ISR_NO_ERR(159)
|
||||||
ISR_NO_ERR(160) ISR_NO_ERR(161) ISR_NO_ERR(162) ISR_NO_ERR(163)
|
ISR_NO_ERR(160) ISR_NO_ERR(161) ISR_NO_ERR(162) ISR_NO_ERR(163)
|
||||||
ISR_NO_ERR(164) ISR_NO_ERR(165) ISR_NO_ERR(166) ISR_NO_ERR(167)
|
ISR_NO_ERR(164) ISR_NO_ERR(165) ISR_NO_ERR(166) ISR_NO_ERR(167)
|
||||||
ISR_NO_ERR(168) ISR_NO_ERR(169) ISR_NO_ERR(170) ISR_NO_ERR(171)
|
ISR_NO_ERR(168) ISR_NO_ERR(169) ISR_NO_ERR(170) ISR_NO_ERR(171)
|
||||||
ISR_NO_ERR(172) ISR_NO_ERR(173) ISR_NO_ERR(174) ISR_NO_ERR(175)
|
ISR_NO_ERR(172) ISR_NO_ERR(173) ISR_NO_ERR(174) ISR_NO_ERR(175)
|
||||||
ISR_NO_ERR(176) ISR_NO_ERR(177) ISR_NO_ERR(178) ISR_NO_ERR(179)
|
ISR_NO_ERR(176) ISR_NO_ERR(177) ISR_NO_ERR(178) ISR_NO_ERR(179)
|
||||||
ISR_NO_ERR(180) ISR_NO_ERR(181) ISR_NO_ERR(182) ISR_NO_ERR(183)
|
ISR_NO_ERR(180) ISR_NO_ERR(181) ISR_NO_ERR(182) ISR_NO_ERR(183)
|
||||||
ISR_NO_ERR(184) ISR_NO_ERR(185) ISR_NO_ERR(186) ISR_NO_ERR(187)
|
ISR_NO_ERR(184) ISR_NO_ERR(185) ISR_NO_ERR(186) ISR_NO_ERR(187)
|
||||||
ISR_NO_ERR(188) ISR_NO_ERR(189) ISR_NO_ERR(190) ISR_NO_ERR(191)
|
ISR_NO_ERR(188) ISR_NO_ERR(189) ISR_NO_ERR(190) ISR_NO_ERR(191)
|
||||||
ISR_NO_ERR(192) ISR_NO_ERR(193) ISR_NO_ERR(194) ISR_NO_ERR(195)
|
ISR_NO_ERR(192) ISR_NO_ERR(193) ISR_NO_ERR(194) ISR_NO_ERR(195)
|
||||||
ISR_NO_ERR(196) ISR_NO_ERR(197) ISR_NO_ERR(198) ISR_NO_ERR(199)
|
ISR_NO_ERR(196) ISR_NO_ERR(197) ISR_NO_ERR(198) ISR_NO_ERR(199)
|
||||||
ISR_NO_ERR(200) ISR_NO_ERR(201) ISR_NO_ERR(202) ISR_NO_ERR(203)
|
ISR_NO_ERR(200) ISR_NO_ERR(201) ISR_NO_ERR(202) ISR_NO_ERR(203)
|
||||||
ISR_NO_ERR(204) ISR_NO_ERR(205) ISR_NO_ERR(206) ISR_NO_ERR(207)
|
ISR_NO_ERR(204) ISR_NO_ERR(205) ISR_NO_ERR(206) ISR_NO_ERR(207)
|
||||||
ISR_NO_ERR(208) ISR_NO_ERR(209) ISR_NO_ERR(210) ISR_NO_ERR(211)
|
ISR_NO_ERR(208) ISR_NO_ERR(209) ISR_NO_ERR(210) ISR_NO_ERR(211)
|
||||||
ISR_NO_ERR(212) ISR_NO_ERR(213) ISR_NO_ERR(214) ISR_NO_ERR(215)
|
ISR_NO_ERR(212) ISR_NO_ERR(213) ISR_NO_ERR(214) ISR_NO_ERR(215)
|
||||||
ISR_NO_ERR(216) ISR_NO_ERR(217) ISR_NO_ERR(218) ISR_NO_ERR(219)
|
ISR_NO_ERR(216) ISR_NO_ERR(217) ISR_NO_ERR(218) ISR_NO_ERR(219)
|
||||||
ISR_NO_ERR(220) ISR_NO_ERR(221) ISR_NO_ERR(222) ISR_NO_ERR(223)
|
ISR_NO_ERR(220) ISR_NO_ERR(221) ISR_NO_ERR(222) ISR_NO_ERR(223)
|
||||||
ISR_NO_ERR(224) ISR_NO_ERR(225) ISR_NO_ERR(226) ISR_NO_ERR(227)
|
ISR_NO_ERR(224) ISR_NO_ERR(225) ISR_NO_ERR(226) ISR_NO_ERR(227)
|
||||||
ISR_NO_ERR(228) ISR_NO_ERR(229) ISR_NO_ERR(230) ISR_NO_ERR(231)
|
ISR_NO_ERR(228) ISR_NO_ERR(229) ISR_NO_ERR(230) ISR_NO_ERR(231)
|
||||||
ISR_NO_ERR(232) ISR_NO_ERR(233) ISR_NO_ERR(234) ISR_NO_ERR(235)
|
ISR_NO_ERR(232) ISR_NO_ERR(233) ISR_NO_ERR(234) ISR_NO_ERR(235)
|
||||||
ISR_NO_ERR(236) ISR_NO_ERR(237) ISR_NO_ERR(238) ISR_NO_ERR(239)
|
ISR_NO_ERR(236) ISR_NO_ERR(237) ISR_NO_ERR(238) ISR_NO_ERR(239)
|
||||||
ISR_NO_ERR(240) ISR_NO_ERR(241) ISR_NO_ERR(242) ISR_NO_ERR(243)
|
ISR_NO_ERR(240) ISR_NO_ERR(241) ISR_NO_ERR(242) ISR_NO_ERR(243)
|
||||||
ISR_NO_ERR(244) ISR_NO_ERR(245) ISR_NO_ERR(246) ISR_NO_ERR(247)
|
ISR_NO_ERR(244) ISR_NO_ERR(245) ISR_NO_ERR(246) ISR_NO_ERR(247)
|
||||||
ISR_NO_ERR(248) ISR_NO_ERR(249) ISR_NO_ERR(250) ISR_NO_ERR(251)
|
ISR_NO_ERR(248) ISR_NO_ERR(249) ISR_NO_ERR(250) ISR_NO_ERR(251)
|
||||||
ISR_NO_ERR(252) ISR_NO_ERR(253) ISR_NO_ERR(254) ISR_NO_ERR(255)
|
ISR_NO_ERR(252) ISR_NO_ERR(253) ISR_NO_ERR(254) ISR_NO_ERR(255)
|
||||||
|
|
||||||
// Array of all ISR handlers for easy initialization
|
// Array of all ISR handlers for easy initialization
|
||||||
void* isr_table[256] = {
|
void* isr_table[256] = {
|
||||||
isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7,
|
isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7,
|
||||||
isr8, isr9, isr10, isr11, isr12, isr13, isr14, isr15,
|
isr8, isr9, isr10, isr11, isr12, isr13, isr14, isr15,
|
||||||
isr16, isr17, isr18, isr19, isr20, isr21, isr22, isr23,
|
isr16, isr17, isr18, isr19, isr20, isr21, isr22, isr23,
|
||||||
isr24, isr25, isr26, isr27, isr28, isr29, isr30, isr31,
|
isr24, isr25, isr26, isr27, isr28, isr29, isr30, isr31,
|
||||||
isr32, isr33, isr34, isr35, isr36, isr37, isr38, isr39,
|
isr32, isr33, isr34, isr35, isr36, isr37, isr38, isr39,
|
||||||
isr40, isr41, isr42, isr43, isr44, isr45, isr46, isr47,
|
isr40, isr41, isr42, isr43, isr44, isr45, isr46, isr47,
|
||||||
isr48, isr49, isr50, isr51, isr52, isr53, isr54, isr55,
|
isr48, isr49, isr50, isr51, isr52, isr53, isr54, isr55,
|
||||||
isr56, isr57, isr58, isr59, isr60, isr61, isr62, isr63,
|
isr56, isr57, isr58, isr59, isr60, isr61, isr62, isr63,
|
||||||
isr64, isr65, isr66, isr67, isr68, isr69, isr70, isr71,
|
isr64, isr65, isr66, isr67, isr68, isr69, isr70, isr71,
|
||||||
isr72, isr73, isr74, isr75, isr76, isr77, isr78, isr79,
|
isr72, isr73, isr74, isr75, isr76, isr77, isr78, isr79,
|
||||||
isr80, isr81, isr82, isr83, isr84, isr85, isr86, isr87,
|
isr80, isr81, isr82, isr83, isr84, isr85, isr86, isr87,
|
||||||
isr88, isr89, isr90, isr91, isr92, isr93, isr94, isr95,
|
isr88, isr89, isr90, isr91, isr92, isr93, isr94, isr95,
|
||||||
isr96, isr97, isr98, isr99, isr100, isr101, isr102, isr103,
|
isr96, isr97, isr98, isr99, isr100, isr101, isr102, isr103,
|
||||||
isr104, isr105, isr106, isr107, isr108, isr109, isr110, isr111,
|
isr104, isr105, isr106, isr107, isr108, isr109, isr110, isr111,
|
||||||
isr112, isr113, isr114, isr115, isr116, isr117, isr118, isr119,
|
isr112, isr113, isr114, isr115, isr116, isr117, isr118, isr119,
|
||||||
isr120, isr121, isr122, isr123, isr124, isr125, isr126, isr127,
|
isr120, isr121, isr122, isr123, isr124, isr125, isr126, isr127,
|
||||||
isr128, isr129, isr130, isr131, isr132, isr133, isr134, isr135,
|
isr128, isr129, isr130, isr131, isr132, isr133, isr134, isr135,
|
||||||
isr136, isr137, isr138, isr139, isr140, isr141, isr142, isr143,
|
isr136, isr137, isr138, isr139, isr140, isr141, isr142, isr143,
|
||||||
isr144, isr145, isr146, isr147, isr148, isr149, isr150, isr151,
|
isr144, isr145, isr146, isr147, isr148, isr149, isr150, isr151,
|
||||||
isr152, isr153, isr154, isr155, isr156, isr157, isr158, isr159,
|
isr152, isr153, isr154, isr155, isr156, isr157, isr158, isr159,
|
||||||
isr160, isr161, isr162, isr163, isr164, isr165, isr166, isr167,
|
isr160, isr161, isr162, isr163, isr164, isr165, isr166, isr167,
|
||||||
isr168, isr169, isr170, isr171, isr172, isr173, isr174, isr175,
|
isr168, isr169, isr170, isr171, isr172, isr173, isr174, isr175,
|
||||||
isr176, isr177, isr178, isr179, isr180, isr181, isr182, isr183,
|
isr176, isr177, isr178, isr179, isr180, isr181, isr182, isr183,
|
||||||
isr184, isr185, isr186, isr187, isr188, isr189, isr190, isr191,
|
isr184, isr185, isr186, isr187, isr188, isr189, isr190, isr191,
|
||||||
isr192, isr193, isr194, isr195, isr196, isr197, isr198, isr199,
|
isr192, isr193, isr194, isr195, isr196, isr197, isr198, isr199,
|
||||||
isr200, isr201, isr202, isr203, isr204, isr205, isr206, isr207,
|
isr200, isr201, isr202, isr203, isr204, isr205, isr206, isr207,
|
||||||
isr208, isr209, isr210, isr211, isr212, isr213, isr214, isr215,
|
isr208, isr209, isr210, isr211, isr212, isr213, isr214, isr215,
|
||||||
isr216, isr217, isr218, isr219, isr220, isr221, isr222, isr223,
|
isr216, isr217, isr218, isr219, isr220, isr221, isr222, isr223,
|
||||||
isr224, isr225, isr226, isr227, isr228, isr229, isr230, isr231,
|
isr224, isr225, isr226, isr227, isr228, isr229, isr230, isr231,
|
||||||
isr232, isr233, isr234, isr235, isr236, isr237, isr238, isr239,
|
isr232, isr233, isr234, isr235, isr236, isr237, isr238, isr239,
|
||||||
isr240, isr241, isr242, isr243, isr244, isr245, isr246, isr247,
|
isr240, isr241, isr242, isr243, isr244, isr245, isr246, isr247,
|
||||||
isr248, isr249, isr250, isr251, isr252, isr253, isr254, isr255,
|
isr248, isr249, isr250, isr251, isr252, isr253, isr254, isr255,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize all IDT entries
|
// Initialize all IDT entries
|
||||||
void init_idt(void) {
|
void init_idt(void) {
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
set_idt(i, isr_table[i], 0);
|
set_idt(i, isr_table[i], 0);
|
||||||
}
|
}
|
||||||
load_idt(idt);
|
load_idt(idt);
|
||||||
}
|
}
|
||||||
|
|||||||
442
src/main.c
442
src/main.c
@ -1,246 +1,196 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "../include/limine.h"
|
#include "../include/limine.h"
|
||||||
|
|
||||||
#include "acpi.h"
|
#include "acpi.h"
|
||||||
#include "common.h"
|
#include "alloc.h"
|
||||||
#include "print.h"
|
#include "common.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
|
||||||
__attribute__((used, section(".limine_requests")))
|
|
||||||
static volatile u64 limine_base_revision[] = LIMINE_BASE_REVISION(4);
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
static volatile u64 limine_base_revision[] = LIMINE_BASE_REVISION(4);
|
||||||
__attribute__((used, section(".limine_requests")))
|
|
||||||
static volatile struct limine_framebuffer_request fb_req = {
|
__attribute__((used, section(".limine_requests")))
|
||||||
.id = LIMINE_FRAMEBUFFER_REQUEST_ID,
|
static volatile struct limine_framebuffer_request fb_req = {
|
||||||
.revision = 0
|
.id = LIMINE_FRAMEBUFFER_REQUEST_ID,
|
||||||
};
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
__attribute__((used, section(".limine_requests")))
|
|
||||||
static volatile struct limine_memmap_request mem_req = {
|
__attribute__((used, section(".limine_requests")))
|
||||||
.id = LIMINE_MEMMAP_REQUEST_ID,
|
static volatile struct limine_hhdm_request hhdm_req = {
|
||||||
.revision = 0,
|
.id = LIMINE_HHDM_REQUEST_ID,
|
||||||
};
|
.revision = 0
|
||||||
|
};
|
||||||
__attribute__((used, section(".limine_requests")))
|
|
||||||
static volatile struct limine_hhdm_request hhdm_req = {
|
__attribute__((used, section(".limine_requests")))
|
||||||
.id = LIMINE_HHDM_REQUEST_ID,
|
static volatile struct limine_rsdp_request rsdp_req = {
|
||||||
.revision = 0
|
.id = LIMINE_RSDP_REQUEST_ID,
|
||||||
};
|
.revision = 0
|
||||||
|
};
|
||||||
__attribute__((used, section(".limine_requests")))
|
|
||||||
static volatile struct limine_rsdp_request rsdp_req = {
|
u64 hhdm_offset;
|
||||||
.id = LIMINE_RSDP_REQUEST_ID,
|
|
||||||
.revision = 0
|
__attribute__((used, section(".limine_requests_start")))
|
||||||
};
|
static volatile u64 limine_requests_start_marker[] = LIMINE_REQUESTS_START_MARKER;
|
||||||
|
|
||||||
u64 hhdm_offset;
|
__attribute__((used, section(".limine_requests_end")))
|
||||||
|
static volatile u64 limine_requests_end_marker[] = LIMINE_REQUESTS_END_MARKER;
|
||||||
__attribute__((used, section(".limine_requests_start")))
|
|
||||||
static volatile u64 limine_requests_start_marker[] = LIMINE_REQUESTS_START_MARKER;
|
void* memcpy(void* restrict dst, const void* src, size_t n) {
|
||||||
|
u8* restrict pdst = (u8* restrict)dst;
|
||||||
__attribute__((used, section(".limine_requests_end")))
|
const u8* restrict psrc = (const u8* restrict)src;
|
||||||
static volatile u64 limine_requests_end_marker[] = LIMINE_REQUESTS_END_MARKER;
|
|
||||||
|
for(size_t i = 0; i < n; i++) {
|
||||||
void* memcpy(void* restrict dst, const void* src, size_t n) {
|
pdst[i] = psrc[i];
|
||||||
u8* restrict pdst = (u8* restrict)dst;
|
}
|
||||||
const u8* restrict psrc = (const u8* restrict)src;
|
|
||||||
|
return dst;
|
||||||
for(size_t i = 0; i < n; i++) {
|
}
|
||||||
pdst[i] = psrc[i];
|
|
||||||
}
|
void* memset(void* s, int c, size_t n) {
|
||||||
|
u8* p = (u8*) s;
|
||||||
return dst;
|
|
||||||
}
|
for(size_t i = 0; i < n; i++) {
|
||||||
|
p[i] = (u8)c;
|
||||||
void* memset(void* s, int c, size_t n) {
|
}
|
||||||
u8* p = (u8*) s;
|
|
||||||
|
return s;
|
||||||
for(size_t i = 0; i < n; i++) {
|
}
|
||||||
p[i] = (u8)c;
|
|
||||||
}
|
void* memmove(void* dst, const void* src, size_t n) {
|
||||||
|
u8* restrict pdst = (u8* restrict)dst;
|
||||||
return s;
|
const u8* restrict psrc = (const u8* restrict)src;
|
||||||
}
|
|
||||||
|
if(src > dst) {
|
||||||
void* memmove(void* dst, const void* src, size_t n) {
|
for(size_t i = 0; i < n; i++) {
|
||||||
u8* restrict pdst = (u8* restrict)dst;
|
pdst[i] = psrc[i];
|
||||||
const u8* restrict psrc = (const u8* restrict)src;
|
}
|
||||||
|
} else if(src < dst) {
|
||||||
if(src > dst) {
|
for(size_t i = n; i > 0; i--) {
|
||||||
for(size_t i = 0; i < n; i++) {
|
pdst[i-1] = psrc[i-1];
|
||||||
pdst[i] = psrc[i];
|
}
|
||||||
}
|
}
|
||||||
} else if(src < dst) {
|
|
||||||
for(size_t i = n; i > 0; i--) {
|
return dst;
|
||||||
pdst[i-1] = psrc[i-1];
|
}
|
||||||
}
|
|
||||||
}
|
int memcmp(const void* s1, const void* s2, size_t n) {
|
||||||
|
const u8* p1 = (const u8* )s1;
|
||||||
return dst;
|
const u8* p2 = (const u8* )s2;
|
||||||
}
|
|
||||||
|
for(size_t i = 0; i < n; i++) {
|
||||||
int memcmp(const void* s1, const void* s2, size_t n) {
|
if(p1[i] != p2[i]) {
|
||||||
const u8* p1 = (const u8* )s1;
|
return p1[i] < p2[i] ? -1 : 1;
|
||||||
const u8* p2 = (const u8* )s2;
|
}
|
||||||
|
}
|
||||||
for(size_t i = 0; i < n; i++) {
|
|
||||||
if(p1[i] != p2[i]) {
|
return 0;
|
||||||
return p1[i] < p2[i] ? -1 : 1;
|
}
|
||||||
}
|
|
||||||
}
|
void hang() {
|
||||||
|
for(;;) {
|
||||||
return 0;
|
asm ("hlt");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
static void hang() {
|
|
||||||
for(;;) {
|
|
||||||
asm ("hlt");
|
struct limine_framebuffer* fb;
|
||||||
}
|
|
||||||
}
|
void draw(u8 vect) {
|
||||||
|
for(size_t y = 0; y < fb->height; y++) {
|
||||||
|
for(size_t x = 0; x < fb->width; x++) {
|
||||||
struct limine_framebuffer* fb;
|
volatile u32* fb_ptr = fb->address;
|
||||||
|
fb_ptr[y * fb->width + x] = (
|
||||||
void draw(u8 vect) {
|
(x + y) * 0x00010000 |
|
||||||
for(size_t y = 0; y < fb->height; y++) {
|
(x ^ y) * 0x00000100 |
|
||||||
for(size_t x = 0; x < fb->width; x++) {
|
(x - y) * 0x00000001
|
||||||
volatile u32* fb_ptr = fb->address;
|
)*vect;
|
||||||
fb_ptr[y * fb->width + x] = (
|
}
|
||||||
(x + y) * 0x00010000 |
|
}
|
||||||
(x ^ y) * 0x00000100 |
|
}
|
||||||
(x - y) * 0x00000001
|
|
||||||
)*vect;
|
extern void init_idt(void);
|
||||||
}
|
|
||||||
}
|
extern u32 fg;
|
||||||
}
|
extern u32 bg;
|
||||||
|
|
||||||
extern void init_idt(void);
|
|
||||||
|
|
||||||
extern u32 fg;
|
u32 apic_get_local_base();
|
||||||
extern u32 bg;
|
void apic_enable();
|
||||||
void print_memmap_entry(struct limine_memmap_entry* entry) {
|
void setup_identity_mapping();
|
||||||
u32 savefg = fg;
|
|
||||||
u32 savebg = bg;
|
void kmain() {
|
||||||
static const char* type_strs[] = {
|
if(LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) {
|
||||||
"Usable",
|
hang();
|
||||||
"Reserved",
|
}
|
||||||
"ACPI Reclaimable",
|
|
||||||
"ACPI NVS",
|
if(fb_req.response == NULL || fb_req.response->framebuffer_count < 1) {
|
||||||
"BAD!!!",
|
hang();
|
||||||
"Bootloader Reclaimable",
|
}
|
||||||
"Executable and Modules",
|
|
||||||
"Framebuffer",
|
fb = fb_req.response->framebuffers[0];
|
||||||
"ACPI Tables",
|
|
||||||
};
|
print_init(fb);
|
||||||
|
init_idt();
|
||||||
static u32 type_colors[] = {
|
|
||||||
0x00AF00,
|
|
||||||
0xAF1F00,
|
|
||||||
0x7f7f00,
|
if(!hhdm_req.response) {
|
||||||
0x7f7f00,
|
print("Failed to get higher half direct mapping\n.");
|
||||||
0xFF0000,
|
hang();
|
||||||
0x007f7f,
|
}
|
||||||
0x408000,
|
|
||||||
0x0000FF,
|
hhdm_offset = hhdm_req.response->offset;
|
||||||
0x00FF00
|
|
||||||
};
|
if(!rsdp_req.response) {
|
||||||
|
print ("Failed to find rsdp\n.");
|
||||||
bg = type_colors[entry->type];
|
hang();
|
||||||
fg = ~bg;
|
}
|
||||||
|
|
||||||
u64 addr = entry->base;
|
alloc_init();
|
||||||
u64 end = addr + entry->length;
|
|
||||||
print("[");
|
rsdp = (struct acpi_rsdp_header*)(rsdp_req.response->address);
|
||||||
print(type_strs[entry->type]);
|
|
||||||
print("]");
|
|
||||||
print64(addr);
|
print("Found RSDP @ 0x");
|
||||||
print(" - ");
|
print64((u64)rsdp);
|
||||||
print64(end);
|
put('\n');
|
||||||
print("\n");
|
|
||||||
fg = savefg;
|
print("With signature: ");
|
||||||
bg = savebg;
|
printn((char*)rsdp->signature, sizeof(rsdp->signature));
|
||||||
}
|
|
||||||
|
print(" v");
|
||||||
|
print8(rsdp->revision);
|
||||||
|
print("\nRSDT at 0x");
|
||||||
u32 apic_get_local_base();
|
struct acpi_rsdt* rsdt =
|
||||||
void apic_enable();
|
(struct acpi_rsdt*)(
|
||||||
|
(rsdp->revision? rsdp->ptr64:rsdp->ptr32) + hhdm_offset
|
||||||
void kmain() {
|
);
|
||||||
if(LIMINE_BASE_REVISION_SUPPORTED(limine_base_revision) == false) {
|
print64((u64)rsdt);
|
||||||
hang();
|
print("\nSDT Signature: ");
|
||||||
}
|
|
||||||
|
|
||||||
if(fb_req.response == NULL || fb_req.response->framebuffer_count < 1) {
|
printn((const char*) rsdt->signature, sizeof(rsdt->signature));
|
||||||
hang();
|
print("\nAPIC Local Base: ");
|
||||||
}
|
|
||||||
|
/* I should check cpuid to ensure its supported but it will
|
||||||
fb = fb_req.response->framebuffers[0];
|
* be for my machines ;^) */
|
||||||
|
/* APIC stuff */
|
||||||
print_init(fb);
|
u32 r = 0xDEADBEEF;
|
||||||
init_idt();
|
r = apic_get_local_base();
|
||||||
|
print32(r);
|
||||||
if(!mem_req.response) {
|
|
||||||
print("Failed to get memory map :(\n)");
|
apic_enable();
|
||||||
hang();
|
|
||||||
}
|
print("\nAPIC Enabled");
|
||||||
|
|
||||||
if(!hhdm_req.response) {
|
hang();
|
||||||
print("Failed to get higher half direct mapping\n.");
|
|
||||||
hang();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
hhdm_offset = hhdm_req.response->offset;
|
|
||||||
|
|
||||||
if(!rsdp_req.response) {
|
|
||||||
print ("Failed to find rsdp\n.");
|
|
||||||
hang();
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
print64((u64)rsdp);
|
|
||||||
put('\n');
|
|
||||||
|
|
||||||
print("With signature: ");
|
|
||||||
printn((char*)rsdp->signature, sizeof(rsdp->signature));
|
|
||||||
|
|
||||||
print(" v");
|
|
||||||
print8(rsdp->revision);
|
|
||||||
print("\nRSDT at 0x");
|
|
||||||
struct acpi_rsdt* rsdt =
|
|
||||||
(struct acpi_rsdt*)(
|
|
||||||
(rsdp->revision? rsdp->ptr64:rsdp->ptr32) + hhdm_offset
|
|
||||||
);
|
|
||||||
print64((u64)rsdt);
|
|
||||||
print("\nSDT Signature: ");
|
|
||||||
|
|
||||||
|
|
||||||
printn((const char*) rsdt->signature, sizeof(rsdt->signature));
|
|
||||||
print("\nAPIC Local Base: ");
|
|
||||||
|
|
||||||
/* I should check cpuid to ensure its supported but it will
|
|
||||||
* be for my machines ;^) */
|
|
||||||
/* APIC stuff */
|
|
||||||
u32 r = 0xDEADBEEF;
|
|
||||||
r = apic_get_local_base();
|
|
||||||
print32(r);
|
|
||||||
|
|
||||||
apic_enable();
|
|
||||||
|
|
||||||
print("\nAPIC Enabled");
|
|
||||||
|
|
||||||
hang();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
388
src/map.c
Normal file
388
src/map.c
Normal 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");
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user