summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Mikkelsen <petermikkelsen10@gmail.com>2025-07-31 22:33:56 +0200
committerPeter Mikkelsen <petermikkelsen10@gmail.com>2025-07-31 22:33:56 +0200
commit5e12467c860372dfa10323365fb0df9db79c8f9b (patch)
tree13e81afa3accb633fdb0ab0d655244ea752814a5 /src
parent0a817a5a74c328229f8a732fc3ec22d8fd7dc20d (diff)
APIC/ACPI/keyboard stuff. I now get interrupts when a key is pressed
Diffstat (limited to 'src')
-rw-r--r--src/aplos.h47
-rw-r--r--src/boot.c15
-rw-r--r--src/interrupt.c11
-rw-r--r--src/main.c9
-rw-r--r--src/nasty.S19
-rw-r--r--src/paging.c108
-rw-r--r--src/util.c10
7 files changed, 208 insertions, 11 deletions
diff --git a/src/aplos.h b/src/aplos.h
index ad9109b..bed0d7a 100644
--- a/src/aplos.h
+++ b/src/aplos.h
@@ -3,6 +3,8 @@
#include <stdarg.h>
#include <uchar.h>
+#define PAGE_SIZE 4096
+
#define nelem(arr) (sizeof(arr)/sizeof(*(arr)))
struct framebuffer
@@ -19,14 +21,20 @@ struct memmap
uint64_t size;
};
+struct ioapic_info
+{
+ uint32_t base;
+ uint32_t interrupt_base;
+};
+
struct boot_info
{
struct framebuffer framebuffer;
-
+ struct ioapic_info ioapic;
uint64_t memmap_count;
struct memmap *memmaps;
-
uint64_t physbase;
+ uint64_t rsdp;
};
struct cpu_regs
@@ -63,8 +71,33 @@ struct cpu_regs
uint16_t gs;
};
+struct ioapic_redirection
+{
+ uint8_t vector;
+ uint8_t delivery_mode;
+ uint8_t destination_mode;
+ uint8_t delivery_status;
+ uint8_t pin_polarity;
+ uint8_t remote_irr;
+ uint8_t trigger_mode;
+ uint8_t mask;
+ uint8_t destination;
+
+ uint64_t reserved;
+};
+
+/* acpi.c */
+void setup_acpi(uint64_t, struct ioapic_info *);
+
+/* apic.c */
+void setup_apic(struct ioapic_info *);
+void apic_end_of_interrupt(void);
+struct ioapic_redirection read_redirection(uint8_t);
+void write_redirection(uint8_t, struct ioapic_redirection);
+
/* boot.c */
uint64_t cpu_count(void);
+uint8_t boot_apic_id(void);
/* descriptors */
void setup_descriptors(void);
@@ -76,6 +109,10 @@ void assert(bool);
void font_init(void);
void font_draw(char8_t *, uint32_t, uint32_t, uint32_t, uint32_t);
+/* keyboard.c */
+void setup_keyboard(void);
+bool keyboard_interrupt_handler(uint32_t);
+
/* main.c */
void main(struct boot_info *);
@@ -88,12 +125,15 @@ void set_gdt(struct table_reg *, uint64_t, uint64_t, uint64_t);
void set_idt(struct table_reg *);
uint64_t get_cr2(void);
uint64_t get_cr3(void);
-extern void (*isr_stubs[32])(void);
+extern void (*isr_stubs[33])(void);
void dump_regs(struct cpu_regs *);
+uint64_t get_msr(uint32_t);
+uint8_t in_uint8(uint8_t);
/* paging.c */
void setup_paging(struct boot_info *);
bool page_fault_handler(uint32_t);
+uint64_t map_page(uint64_t, uint64_t, bool);
/* panic.c */
[[noreturn]] void panic(void);
@@ -117,3 +157,4 @@ void write_uint32_le(uint8_t *, uint32_t);
void write_uint64_le(uint8_t *, uint64_t);
int memcmp(const void *, const void *, size_t);
void memset(void *, uint8_t, size_t);
+void memcpy(void *, void *, size_t);
diff --git a/src/boot.c b/src/boot.c
index 00cbcca..00afae2 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -41,11 +41,16 @@ REQUEST struct limine_entry_point_request entry_point_request = {
.entry = bootmain
};
-REQUEST struct limine_hhdm_request hhdm_request = {
+REQUEST struct limine_hhdm_request hhdm_request = {
.id = LIMINE_HHDM_REQUEST,
.revision = 0
};
+REQUEST struct limine_rsdp_request rsdp_request = {
+ .id = LIMINE_RSDP_REQUEST,
+ .revision = 0
+};
+
LIMINE(".limine_requests_start") LIMINE_REQUESTS_START_MARKER
LIMINE(".limine_requests_end") LIMINE_REQUESTS_END_MARKER
@@ -55,6 +60,12 @@ cpu_count(void)
return mp_request.response->cpu_count;
}
+uint8_t
+boot_apic_id(void)
+{
+ return mp_request.response->bsp_lapic_id;
+}
+
static void
bootmain(void)
{
@@ -66,6 +77,7 @@ bootmain(void)
assert(paging_request.response);
assert(mp_request.response);
assert(hhdm_request.response);
+ assert(rsdp_request.response);
assert(framebuffer_request.response->framebuffer_count >= 1);
@@ -92,6 +104,7 @@ bootmain(void)
}
info.memmaps = memmaps;
info.physbase = hhdm_request.response->offset;
+ info.rsdp = rsdp_request.response->address;
main(&info);
halt();
diff --git a/src/interrupt.c b/src/interrupt.c
index 54f9947..6406fc0 100644
--- a/src/interrupt.c
+++ b/src/interrupt.c
@@ -3,6 +3,7 @@
struct handler {
char8_t *description;
bool (*fn)(uint32_t code);
+ bool apic;
} handlers[256] = {
[0] = {
.description = u8"divide-by-zero-error"
@@ -73,7 +74,12 @@ struct handler {
},
[30] = {
.description = u8"security exception"
- }
+ },
+ [32] = {
+ .description = u8"keyboard interrupt",
+ .fn = keyboard_interrupt_handler,
+ .apic = true,
+ },
};
void
@@ -87,6 +93,9 @@ interrupt_handler(uint8_t n, uint32_t code)
print(u8"Unhandled interrupt: %u8 (%s) with error code %x32\n", n, h->description ? h->description : u8"???", code);
panic();
}
+
+ if(h->apic)
+ apic_end_of_interrupt();
}
diff --git a/src/main.c b/src/main.c
index a3b7719..eddba5e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -9,7 +9,12 @@ main(struct boot_info *info)
setup_descriptors();
setup_paging(info);
+ setup_acpi(info->rsdp, &info->ioapic);
+ setup_apic(&info->ioapic);
+ setup_keyboard();
- int *x = (int*)0xBEEF;
- *x = 4; /* This should give us a page fault, and trigger the panic function */
+ halt();
+
+// int *x = (int*)0x0001;
+// *x = 4; /* This should give us a page fault, and trigger the panic function */
}
diff --git a/src/nasty.S b/src/nasty.S
index f3d958e..997fb6c 100644
--- a/src/nasty.S
+++ b/src/nasty.S
@@ -79,7 +79,8 @@ get_cr3:
ISR(28) \
ISR(29) \
ISR(30) \
- ISR(31)
+ ISR(31) \
+ ISR(32)
.extern interrupt_handler
#define ISR(n) \
@@ -147,3 +148,19 @@ dump_regs:
mov [rdi+192], fs
mov [rdi+194], gs
ret
+
+.global get_msr
+get_msr:
+ mov ecx, edi
+ mov rax, 0 /* Not sure if this and the next line are needed. My assembly skills are lacking. */
+ mov rdx, 0
+ rdmsr
+ shl rdx, 32
+ or rax, rdx
+ ret
+
+.global in_uint8
+in_uint8:
+ mov dx, di
+ in ax, dx
+ ret
diff --git a/src/paging.c b/src/paging.c
index ecbd647..9fdf6ea 100644
--- a/src/paging.c
+++ b/src/paging.c
@@ -2,6 +2,7 @@
#define MAX_REGIONS 1024
#define INVALID_PTR UINT64_MAX
+#define PADDR_MASK 0x000FFFFFFFFFF000
struct region
{
@@ -21,6 +22,8 @@ struct region_map
static struct region_map physical;
static struct region_map virtual;
+static uint64_t physbase;
+
static void init_map(struct region_map *, bool);
static void mark_region(struct region_map *, uint64_t, uint64_t, bool);
static uint64_t lookup(struct region_map *, uint64_t);
@@ -28,11 +31,17 @@ static void delete_node(struct region_map *, uint64_t);
static uint64_t add_node(struct region_map *, uint64_t, uint64_t, bool);
static void debug_region_map(struct region_map *);
static void print_size(uint64_t);
+static uint64_t allocate_virtual(uint64_t);
+static void update_pagetables(uint64_t, uint64_t, uint64_t, bool);
+static uint64_t *table_ptr(uint64_t *, uint16_t);
+static uint64_t encode_entry(uint64_t, bool);
+static uint64_t get_physical_page(void);
void
setup_paging(struct boot_info *info)
{
print(u8"Setting up paging. All usable physical memory is mapped starting at %p\n", info->physbase);
+ physbase = info->physbase;
init_map(&physical, false);
init_map(&virtual, true);
@@ -44,9 +53,7 @@ setup_paging(struct boot_info *info)
/* TODO fill in the used regions of virtual memory, by inspection the page tables that was setup for us
* by the bootloader.
*/
-
- uint64_t cr3 = get_cr3();
- print(u8"CR3: %p\n", cr3);
+ mark_region(&virtual, 0, PAGE_SIZE, false); /* don't use the first page of virtual memory */
}
bool
@@ -60,6 +67,21 @@ page_fault_handler(uint32_t code)
return false; /* We didn't actually handle it */
}
+uint64_t
+map_page(uint64_t paddr, uint64_t pagecount, bool cacheable)
+{
+ /* Find a region of virtual memory which isn't in use yet, and which is large enough */
+ uint64_t offset = paddr % PAGE_SIZE;
+ if(offset != 0){
+ pagecount++;
+ paddr -= offset;
+ }
+
+ uint64_t vaddr = allocate_virtual(pagecount);
+ update_pagetables(paddr, vaddr, pagecount, cacheable);
+ return vaddr + offset;
+}
+
static void
init_map(struct region_map *map, bool available)
{
@@ -203,3 +225,83 @@ print_size(uint64_t size)
P(kb, "KB", 0);
P(b, "B", 1);
}
+
+static uint64_t
+allocate_virtual(uint64_t pagecount)
+{
+ uint64_t size = PAGE_SIZE * pagecount;
+
+ for(uint64_t p = virtual.used; p != INVALID_PTR; p = virtual.regions[p].next){
+ struct region *r = &virtual.regions[p];
+ if(r->available && r->size >= size){
+ uint64_t vaddr = r->start;
+ mark_region(&virtual, vaddr, size, false);
+ return vaddr;
+ }
+ }
+ panic();
+}
+
+static void
+update_pagetables(uint64_t paddr, uint64_t vaddr, uint64_t pagecount, bool cacheable)
+{
+ uint64_t cr3 = get_cr3();
+ uint64_t *pml4 = table_ptr(&cr3, 0);
+
+ for(uint64_t i = 0; i < pagecount; i++){
+ uint16_t pml4o = (vaddr >> 39) & 0x1F;
+ uint16_t pdpo = (vaddr >> 30) & 0x1F;
+ uint16_t pdeo = (vaddr >> 21) & 0x1F;
+ uint16_t pteo = (vaddr >> 12) & 0x1F;
+
+ uint64_t *pdp = table_ptr(pml4, pml4o);
+ uint64_t *pde = table_ptr(pdp, pdpo);
+ uint64_t *pte = table_ptr(pde, pdeo);
+
+ pte[pteo] = encode_entry(paddr, cacheable);
+
+ paddr += PAGE_SIZE;
+ vaddr += PAGE_SIZE;
+ }
+}
+
+static uint64_t *
+table_ptr(uint64_t *table, uint16_t index)
+{
+ uint64_t v = table[index];
+ if(v == 0){
+ v = get_physical_page();
+ memset((void*)(v + physbase), 0, PAGE_SIZE);
+ table[index] = encode_entry(v, true);
+ }else
+ v &= PADDR_MASK;
+
+ return (uint64_t *)(v + physbase);
+}
+
+static uint64_t
+encode_entry(uint64_t paddr, bool cacheable)
+{
+ uint64_t v = 0;
+ v |= (paddr & PADDR_MASK);
+ v |= 0x3; /* Present + RW */
+ if(!cacheable)
+ v |= 0x10; /* Cache disable */
+ return v;
+}
+
+static uint64_t
+get_physical_page(void)
+{
+ /* Almost identical to allocate_virtual. merge them. */
+
+ for(uint64_t p = physical.used; p != INVALID_PTR; p = physical.regions[p].next){
+ struct region *r = &physical.regions[p];
+ if(r->available && r->size >= PAGE_SIZE){
+ uint64_t paddr = r->start;
+ mark_region(&physical, paddr, PAGE_SIZE, false);
+ return paddr;
+ }
+ }
+ panic();
+}
diff --git a/src/util.c b/src/util.c
index 96cbe11..235e853 100644
--- a/src/util.c
+++ b/src/util.c
@@ -65,3 +65,13 @@ memset(void *v, uint8_t b, size_t n)
for(size_t i = 0; i < n; i++)
p[i] = b;
}
+
+void
+memcpy(void *dstp, void *srcp, size_t n)
+{
+ uint8_t *dst = dstp;
+ uint8_t *src = srcp;
+
+ for(size_t i = 0; i < n; i++)
+ dst[i] = src[i];
+}