From fb8dd43dd33fbdccfb4de731e846959910c4e5ff Mon Sep 17 00:00:00 2001 From: Ruslan Isaev Date: Fri, 29 Aug 2025 18:35:22 +0300 Subject: [PATCH] start implementing APIC utils --- Makefile | 5 ++- include/apic.h | 13 ++++++++ include/pic.h | 2 ++ include/utils.h | 6 ++++ src/kernel/apic.c | 79 +++++++++++++++++++++++++++++++++++++++++++++ src/kernel/isr.c | 20 ++++++++++-- src/kernel/kernel.c | 35 +++++++++++++------- src/kernel/pic.c | 7 ++++ src/utils/utils.c | 24 ++++++++++++++ 9 files changed, 176 insertions(+), 15 deletions(-) create mode 100644 include/apic.h create mode 100644 src/kernel/apic.c diff --git a/Makefile b/Makefile index 613ac6a..e277088 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ OBJS = bin/boot.o bin/kernel.o bin/idt.o bin/isr.o bin/screen.o \ bin/keyboard.o bin/paging.o bin/page_alloc.o bin/page_tables.o \ bin/fat.o bin/task.o bin/switch.o bin/sys_exit.o bin/gdt.o bin/isr-asm.o \ bin/kheap.o bin/liballoc.o bin/exec_from_file.o bin/syscalls.o bin/atapi.o \ - bin/lib9660.o bin/vfs.o + bin/lib9660.o bin/vfs.o bin/apic.o # Define the compiler and assembler #CC = i686-elf-gcc -D__is_katauos @@ -163,6 +163,9 @@ bin/lib9660.o: src/fs/lib9660.c bin/vfs.o: src/fs/vfs.c $(CC) $(CFLAGS) -c $< -o $@ +bin/apic.o: src/kernel/apic.c + $(CC) $(CFLAGS) -c $< -o $@ + clean: rm -rf bin/ rm -f $(OUTPUT) diff --git a/include/apic.h b/include/apic.h new file mode 100644 index 0000000..338e597 --- /dev/null +++ b/include/apic.h @@ -0,0 +1,13 @@ +#include "../include/utils.h" + +#include +#include + +extern bool lapic_enabled; + +bool check_apic(); +void enable_apic(); + +void lapic_write(uint32_t reg_offset, uint32_t value); +uint32_t lapic_read(uint32_t reg_offset); +void lapic_eoi(); \ No newline at end of file diff --git a/include/pic.h b/include/pic.h index ad4c094..aa8e32c 100644 --- a/include/pic.h +++ b/include/pic.h @@ -4,6 +4,8 @@ #include "../include/utils.h" void pic_remap(int offset1, int offset2); +void pic_disable(void); void pic_end_int(uint8_t irq); +void pic_apply_masks(); #endif diff --git a/include/utils.h b/include/utils.h index 5f3be7d..78a8fe9 100644 --- a/include/utils.h +++ b/include/utils.h @@ -11,6 +11,12 @@ void get_fancy_datetime(); void get_datetime(uint16_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second); uint32_t fat32_datetime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second); +//got these from osdev.org +void cpuid(int code, uint32_t *a, uint32_t *d); +bool cpuHasMSR(); +void cpuGetMSR(uint32_t msr, uint32_t *lo, uint32_t *hi); +void cpuSetMSR(uint32_t msr, uint32_t lo, uint32_t hi); + #define inb inportb #define outb outportb diff --git a/src/kernel/apic.c b/src/kernel/apic.c new file mode 100644 index 0000000..05514ae --- /dev/null +++ b/src/kernel/apic.c @@ -0,0 +1,79 @@ +#include "../include/apic.h" +#include "../include/paging.h" + +#define IA32_APIC_BASE_MSR 0x1B +#define IA32_APIC_BASE_MSR_BSP 0x100 // Processor is a BSP +#define IA32_APIC_BASE_MSR_ENABLE 0x800 + +#define LAPIC_ID_REG 0x020 // ID Register +#define LAPIC_EOI_REG 0x0B0 // End-of-Interrupt Register +#define LAPIC_SPURIOUS_REG 0x0F0 // Spurious Interrupt Vector Register + +#define PAGE_PRESENT (1 << 0) +#define PAGE_WRITE (1 << 1) +#define PAGE_WRITE_THROUGH (1 << 3) +#define PAGE_CACHE_DISABLE (1 << 4) + +const unsigned int APIC_PAGE_FLAGS = PAGE_PRESENT | PAGE_WRITE | PAGE_WRITE_THROUGH | PAGE_CACHE_DISABLE; + +bool lapic_enabled = false; +volatile uint32_t* lapic_ptr = NULL; + +bool check_apic() +{ + uint32_t eax, edx; + cpuid(1, &eax, &edx); + + return edx & (1 << 9); +} + +void cpu_set_apic_base(uintptr_t apic) { + uint32_t edx = 0; + uint32_t eax = (apic & 0xfffff0000) | IA32_APIC_BASE_MSR_ENABLE; + + #ifdef __PHYSICAL_MEMORY_EXTENSION__ + edx = (apic >> 32) & 0x0f; + #endif + + cpuSetMSR(IA32_APIC_BASE_MSR, eax, edx); + } + +uintptr_t cpu_get_apic_base() { + uint32_t eax, edx; + cpuGetMSR(IA32_APIC_BASE_MSR, &eax, &edx); + + #ifdef __PHYSICAL_MEMORY_EXTENSION__ + return (eax & 0xfffff000) | ((edx & 0x0f) << 32); + #else + return (eax & 0xfffff000); + #endif + } + + void enable_apic() { + /* Section 11.4.1 of 3rd volume of Intel SDM recommends mapping the base address page as strong uncacheable for correct APIC operation. */ + + /* Hardware enable the Local APIC if it wasn't enabled */ + cpu_set_apic_base(cpu_get_apic_base()); + + printf("APIC base: 0x%X\n", cpu_get_apic_base()); + map_page((void*)cpu_get_apic_base(), (void*)cpu_get_apic_base(), APIC_PAGE_FLAGS); + + lapic_ptr = (uint32_t*)cpu_get_apic_base(); + + /* Set the Spurious Interrupt Vector Register bit 8 to start receiving interrupts */ + lapic_write(0xF0, lapic_read(0xF0) | 0x100); +} + +void lapic_write(uint32_t offset, uint32_t value) { + uint32_t volatile *ptr = (uint32_t volatile *)(lapic_ptr + offset); + *ptr = value; + } + +uint32_t lapic_read(uint32_t offset) { + uint32_t volatile *ptr = (uint32_t volatile *)(lapic_ptr + offset); + return *ptr; +} + +void lapic_eoi() { + lapic_write(LAPIC_EOI_REG, 0); +} \ No newline at end of file diff --git a/src/kernel/isr.c b/src/kernel/isr.c index 2da5d8a..21f057c 100644 --- a/src/kernel/isr.c +++ b/src/kernel/isr.c @@ -5,6 +5,7 @@ #include "../include/pit.h" #include "../include/keyboard.h" #include "../include/task.h" +#include "../include/apic.h" #include @@ -103,8 +104,14 @@ void handle_page_fault(uint32_t error_code, uint32_t faulting_address) __attribute__((interrupt)) void isr_timer(struct interrupt_frame *frame) { - pit_init(100); - pic_end_int(0x0); + if(lapic_enabled) + { + lapic_eoi(); + } + else + { + pic_end_int(0x0); + } //scheduler_lock(); schedule(); @@ -115,7 +122,14 @@ __attribute__((interrupt)) void isr_custom(struct interrupt_frame *frame) { //terminal_writestring("YOOOOO!!!!!! I LOVE KATYA!!!!"); handle_keyboard(); - pic_end_int(0x1); + if(lapic_enabled) + { + lapic_eoi(); + } + else + { + pic_end_int(0x1); + } } void isr0() diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 720463b..4b70b1e 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -14,18 +14,11 @@ #include "../include/kheap.h" #include "../include/exec_from_file.h" #include "../include/atapi.h" -#include "../include/lib9660.h" #include "../include/vfs.h" +#include "../include/apic.h" #include -void apply_pic_masks() -{ - //0x21 is master pic, 0xa1 is slave pic - outb(0x21,0xfc);//0b11111100 (bit 0 is PIT, bit 1 is keyboard and so on) - outb(0xa1,0xff); -} - void kmain(unsigned int magic, unsigned int info) { struct multiboot_info mbi; @@ -52,10 +45,30 @@ void kmain(unsigned int magic, unsigned int info) printf("done\n"); isr_install(); - pic_remap(0x20, 0x28); - pit_init(100); - apply_pic_masks(); + if(cpuHasMSR()) + { + printf("CPU has MSR\n"); + } + + if(check_apic() && cpuHasMSR()) + { + printf("APIC is present\n"); + lapic_enabled = true; + } + + if(!lapic_enabled) + { + pic_remap(0x20, 0x28); + pit_init(100); + + pic_apply_masks(); + } + else + { + pic_disable(); + enable_apic(); + } printf("done fucking with pages and memory map!\n"); char *test_str; diff --git a/src/kernel/pic.c b/src/kernel/pic.c index 25434f8..709d7f9 100644 --- a/src/kernel/pic.c +++ b/src/kernel/pic.c @@ -75,3 +75,10 @@ void pic_end_int(uint8_t irq) { if (irq >= 8) outb(PIC2_COMMAND, 0x20); outb(PIC1_COMMAND, 0x20); } + +void pic_apply_masks() +{ + //0x21 is master pic, 0xa1 is slave pic + outb(0x21,0xfc);//0b11111100 (bit 0 is PIT, bit 1 is keyboard and so on) + outb(0xa1,0xff); +} diff --git a/src/utils/utils.c b/src/utils/utils.c index 87b7805..972ef51 100644 --- a/src/utils/utils.c +++ b/src/utils/utils.c @@ -57,3 +57,27 @@ uint32_t fat32_datetime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, return fat_datetime; } + +inline void cpuid(int code, uint32_t *a, uint32_t *d) +{ + asm volatile("cpuid":"=a"(*a),"=d"(*d):"a"(code):"ecx","ebx"); +} + +const uint32_t CPUID_FLAG_MSR = 1 << 5; + +bool cpuHasMSR() +{ + static uint32_t a, d; // eax, edx + cpuid(1, &a, &d); + return d & CPUID_FLAG_MSR; +} + +void cpuGetMSR(uint32_t msr, uint32_t *lo, uint32_t *hi) +{ + asm volatile("rdmsr" : "=a"(*lo), "=d"(*hi) : "c"(msr)); +} + +void cpuSetMSR(uint32_t msr, uint32_t lo, uint32_t hi) +{ + asm volatile("wrmsr" : : "a"(lo), "d"(hi), "c"(msr)); +} \ No newline at end of file