diff --git a/src/arch/x86_64/acpi.c b/src/arch/x86_64/acpi.c index 330b3f4c..55f2f57d 100644 --- a/src/arch/x86_64/acpi.c +++ b/src/arch/x86_64/acpi.c @@ -16,13 +16,12 @@ static volatile struct limine_rsdp_request rsdpreq = { .revision = 0 }; -static bool checksumok(sdt_t* table){ +bool acpi_checksumok(sdt_t* table){ uint8_t sum; uint8_t* ptr = (uint8_t*)table; for(size_t i = 0; i < table->length; ++i) sum += *ptr++; - return sum == 0; } @@ -35,12 +34,11 @@ void* acpi_gettable(char* sig, size_t n){ for(size_t i = 0; i < sdtentrycount; ++i){ sdt_t* table = usersdt ? (*(uint32_t*)ptr & 0xFFFFFFFF) : *(uint64_t*)ptr; - table = (uint8_t*)table + (size_t)limine_hhdm_offset; if(!strncmp(sig, table->signature, 4)){ if(n-- == 0) - return (uint8_t*)table + (size_t) limine_hhdm_offset; + return table; } @@ -76,7 +74,7 @@ void acpi_init(){ printf("Root System Description Table address: %p with %lu tables\n", sdt, sdtentrycount); - if(!checksumok(sdt)) + if(!acpi_checksumok(sdt)) _panic("Invalid RSDT checksum!", 0); } diff --git a/src/arch/x86_64/apic.c b/src/arch/x86_64/apic.c new file mode 100644 index 00000000..b583a02f --- /dev/null +++ b/src/arch/x86_64/apic.c @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include +#include + + +#define TYPE_LAPIC 0 +#define TYPE_IOAPIC 1 +#define TYPE_OVERRIDE 2 +#define TYPE_IOAPICNMI 3 +#define TYPE_LAPICNMI 4 +#define TYPE_ADDROVERRIDE 5 +#define TYPE_X2APIC 9 + +typedef struct{ + uint8_t type; + uint8_t length; +} __attribute__((packed)) entry_head; + +typedef struct{ + entry_head header; + uint8_t acpi_id; + uint8_t apicid; + uint32_t flags; +} __attribute__((packed)) lapic_entry; + +typedef struct{ + entry_head header; + uint8_t id; + uint8_t reserved; + uint32_t address; + uint32_t gsibase; +} __attribute__((packed)) ioapic_entry; + +typedef struct{ + entry_head header; + uint8_t bus; + uint8_t irq; + uint32_t gsi; + uint16_t flags; + +} __attribute__((packed)) override_entry; + +typedef struct{ + entry_head header; + uint8_t source; + uint8_t reserved; + uint16_t flags; + uint32_t gsi; +} __attribute__((packed)) ioapicnmi_entry; + +typedef struct{ + entry_head header; + uint8_t acpi_id; + uint16_t flags; + uint8_t lint; +} __attribute__((packed)) lapicnmi_entry; + +typedef struct{ + entry_head header; + uint16_t reserved; + uint64_t addr; +} __attribute__((packed)) overrideaddr_entry; + +typedef struct{ + entry_head header; + uint16_t reserved; + uint32_t x2apicid; + uint32_t flags; + uint32_t acpi_id; +} __attribute__((packed)) x2apic_entry; + +typedef struct{ + int id; + int gsi; + volatile void* address; + size_t mre; +} ioapic_descriptor; + +static size_t lapic_count = 0; +static size_t ioapic_count = 0; +static size_t override_count = 0; +static size_t ionmi_count = 0; +static size_t localnmi_count = 0; +static size_t x2apic_count = 0; + +void* lapicaddr; +ioapic_descriptor* ioapics; + +void* tablestart; +void* tableend; + +static inline entry_head* next(entry_head* entry){ + return (void*)entry + entry->length; +} + +static void* findstructure(size_t type, size_t n){ + + entry_head* entry = tablestart; + + + while(entry < tableend){ + if(entry->type == type){ + if(n-- == 0) + return entry; + } + + entry = next(entry); + } + + return NULL; + +} + +static inline void ioapic_writereg(ioapic_descriptor* ioapic, uint32_t offset, uint32_t data){ + volatile uint32_t* reg = ioapic->address; + *reg = offset; // select + *(reg + 4) = data; // data +} + +static inline uint32_t ioapic_readreg(ioapic_descriptor* ioapic, uint32_t offset){ + volatile uint32_t* reg = ioapic->address; + *reg = offset; // select + return *(reg + 4); // data + + +} + +static void ioapic_writeiored(ioapic_descriptor* ioapic, uint8_t irq, uint8_t vector, uint8_t delivery, uint8_t destmode, uint8_t polarity, uint8_t irr, uint8_t mode, uint8_t mask, uint8_t dest){ + uint32_t val = vector; + val |= (delivery & 0b111) << 8; + val |= (destmode & 1) << 11; + val |= (polarity & 1) << 13; + val |= (irr & 1) << 14; + val |= (mode & 1) << 15; + val |= (mask & 1) << 16; + + ioapic_writereg(ioapic, 0x10 + irq * 2, val & 0xFFFFFFFF); + ioapic_writereg(ioapic, 0x10 + irq * 2 + 1, dest << 24); + +} + +void apic_init(){ + + // first get some cool info about the apic in the system + + madt_t* apic = acpi_gettable("APIC", 0); + + if(!apic) + _panic("No MADT found", 0); + + printf("MADT at %p\n", apic); + + lapicaddr = apic->apicaddr; + + // get the count of relevant entries + + size_t len = apic->header.length - sizeof(madt_t); + void* start = (void*)apic + sizeof(madt_t); + void* end = start + len; + entry_head* entry = start; + tablestart = start; + tableend = end; + while(entry < end){ + switch(entry->type){ + case TYPE_LAPIC: + ++lapic_count; + break; + case TYPE_IOAPIC: + ++ioapic_count; + break; + case TYPE_OVERRIDE: + ++override_count; + break; + case TYPE_IOAPICNMI: + ++ionmi_count; + break; + case TYPE_LAPICNMI: + ++localnmi_count; + break; + case TYPE_ADDROVERRIDE: + lapicaddr = ((overrideaddr_entry*)entry)->addr; + break; + case TYPE_X2APIC: + ++x2apic_count; + break; + + } + entry = next(entry); + } + + printf("MADT info:\nLocal APIC count: %lu\nIO APIC count: %lu\noverride count: %lu\nIO NMI count: %lu\nLocal NMI count: %lu\nX2APIC count: %lu\nLocal apic address: %p\n", lapic_count, ioapic_count, override_count, ionmi_count, localnmi_count, x2apic_count, lapicaddr); + + // map the local apic into memory (sea bios doesn't pass this to the limine map for some reason? I know my laptop UEFI firmware passes it) + + void* tmp = vmm_alloc(1, 0); + if(!tmp) _panic("Out of memory", 0); + vmm_map(lapicaddr, tmp, 1, ARCH_MMU_MAP_READ | ARCH_MMU_MAP_WRITE); + lapicaddr = tmp; + + // now set up the IO apic + + ioapics = alloc(sizeof(ioapic_descriptor)*ioapic_count); + + for(size_t i = 0; i < ioapic_count; ++i){ + + ioapic_entry* entry = findstructure(TYPE_IOAPIC, i); + void* tmp = vmm_alloc(1, 0); + if(!tmp) _panic("Out of memory", 0); + vmm_map(entry->address, tmp, 1, ARCH_MMU_MAP_READ | ARCH_MMU_MAP_WRITE); + + ioapics[i].address = tmp; + ioapics[i].gsi = entry->gsibase; + ioapics[i].id = entry->id; + ioapics[i].mre = (ioapic_readreg(&ioapics[i], 1) >> 16) & 0xFF; + + for(size_t j = 0; j <= ioapics[i].mre; ++j) + ioapic_writeiored(&ioapics[i], j, 0, 0, 0, 0, 0, 0, 1, 0); + } + + + +} diff --git a/src/arch/x86_64/include/arch/acpi.h b/src/arch/x86_64/include/arch/acpi.h index 0cd24ace..92152343 100644 --- a/src/arch/x86_64/include/arch/acpi.h +++ b/src/arch/x86_64/include/arch/acpi.h @@ -3,6 +3,7 @@ #include #include +#include typedef struct { char signature[8]; @@ -38,7 +39,14 @@ typedef struct { uint32_t pointers[]; } __attribute__((packed)) rsdt_t; +typedef struct { + sdt_t header; + uint32_t apicaddr; + uint32_t flags; +} __attribute__((packed)) madt_t; + void* acpi_gettable(char* sig, size_t n); void acpi_init(); +bool acpi_checksumok(sdt_t* table); #endif diff --git a/src/arch/x86_64/include/arch/apic.h b/src/arch/x86_64/include/arch/apic.h new file mode 100644 index 00000000..3ef03abb --- /dev/null +++ b/src/arch/x86_64/include/arch/apic.h @@ -0,0 +1,8 @@ +#ifndef _APIC_H_INCLUDE +#define _APIC_H_INCLUDE + + + +void apic_init(); + +#endif diff --git a/src/arch/x86_64/main.c b/src/arch/x86_64/main.c index b357fcfc..317d6752 100644 --- a/src/arch/x86_64/main.c +++ b/src/arch/x86_64/main.c @@ -9,6 +9,9 @@ #include #include #include +#include +#include +#include static volatile struct limine_terminal_request liminettyr = { .id = LIMINE_TERMINAL_REQUEST, @@ -38,10 +41,6 @@ void kmain(){ pmm_init(); - //set from 0xA0000 to 0x100000 as used - //as sometimes the bootloader doesn't pass this region as being used - - pmm_setused((void*)0xA0000, 0x60); arch_mmu_init(); @@ -59,6 +58,8 @@ void kmain(){ initrd_parse(); acpi_init(); + + apic_init(); _panic("End of kmain()", 0); diff --git a/src/include/string/strncmp.c b/src/include/string/strncmp.c index cb7c7636..9d31e9fa 100644 --- a/src/include/string/strncmp.c +++ b/src/include/string/strncmp.c @@ -4,7 +4,7 @@ int strncmp(const char *a, const char *b, size_t c){ int diff = 0; - while(c--) + while(c-- && diff == 0) diff += *a++ - *b++; diff --git a/src/sys/mm/pmm.c b/src/sys/mm/pmm.c index 8e12bd7b..d2265dd6 100644 --- a/src/sys/mm/pmm.c +++ b/src/sys/mm/pmm.c @@ -7,8 +7,8 @@ #define PAGE_SIZE 4096 -#define STATE_USED 1 -#define STATE_FREE 0 +#define STATE_USED 0 +#define STATE_FREE 1 void* limine_hhdm_offset; @@ -219,7 +219,7 @@ void pmm_init(){ memset(bitmap, 0, bitmapsize); - // mark needed entries as used now + // mark needed entries as free now printf("Ranges: \n"); @@ -236,9 +236,9 @@ void pmm_init(){ if(i % 2) printf("\n\033[0m"); - if(current->type == LIMINE_MEMMAP_USABLE) continue; + if(!current->type == LIMINE_MEMMAP_USABLE) continue; - pmm_setused((void*)current->base, current->length / PAGE_SIZE + 1); + pmm_free((void*)current->base, current->length / PAGE_SIZE + 1); }