From 113145e4302455164fa426712f4e0242e010ee0a Mon Sep 17 00:00:00 2001 From: rami Date: Thu, 1 Aug 2024 12:33:24 -0400 Subject: [PATCH] handle page faults --- Makefile | 2 +- include/kernel/acpi.h | 118 ++++++++++++++++++++++++++++++++++++++++++ kernel/acpi.c | 40 ++++++++++++++ kernel/kernel.c | 34 +++++++++++- 4 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 include/kernel/acpi.h create mode 100644 kernel/acpi.c diff --git a/Makefile b/Makefile index c2eb474..3244ab2 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ ISO := Hazel.iso CFLAGS := -ffreestanding -Wall -Wextra -Werror -I $(INCLUDEDIR) -I lib LDFLAGS := -ffreestanding -nostdlib -lgcc -T kernel/kernel.ld -QEMUFLAGS := -cdrom $(BUILDDIR)/$(ISO) -s -m 512M -serial stdio +QEMUFLAGS := -d int -cdrom $(BUILDDIR)/$(ISO) -s -m 512M -serial stdio $(BUILDDIR)/$(KIMG): $(KOBJ) $(LOBJ) $(CC) $^ -o $@ $(LDFLAGS) diff --git a/include/kernel/acpi.h b/include/kernel/acpi.h new file mode 100644 index 0000000..4b8e4b9 --- /dev/null +++ b/include/kernel/acpi.h @@ -0,0 +1,118 @@ +#ifndef HAZEL_ACPI_H_ +#define HAZEL_ACPI_H_ + +#include + +#define BIOS_START 0x000E0000 +#define BIOS_END 0x000FFFFF +#define RSDP_SIG "RSD PTR " +#define RSDP_SIG_LEN 8 +#define RSDP_SIZE 20 + +struct RSDP { + char Signature[RSDP_SIG_LEN]; + uint8_t Checksum; + char OEMID[6]; + uint8_t Revision; + uint32_t RsdtAddress; +} __attribute__ ((packed)); +typedef struct RSDP rsdp_t; + +typedef struct { + char Signature[4]; + uint32_t Length; + uint8_t Revision; + uint8_t Checksum; + char OEMID[6]; + char OEMTableID[8]; + uint32_t OEMRevision; + uint32_t CreatorID; + uint32_t CreatorRevision; +} sdt_hdr_t; + +typedef struct { + sdt_hdr_t hdr; + uint32_t other_tables[]; +} rsdt_t; + +struct GenericAddressStructure +{ + uint8_t AddressSpace; + uint8_t BitWidth; + uint8_t BitOffset; + uint8_t AccessSize; + uint64_t Address; +}; + +struct fadt { + sdt_hdr_t hdr; + uint32_t FirmwareCtrl; + uint32_t Dsdt; + + // field used in ACPI 1.0; no longer in use, for compatibility only + uint8_t Reserved; + + uint8_t PreferredPowerManagementProfile; + uint16_t SCI_Interrupt; + uint32_t SMI_CommandPort; + uint8_t AcpiEnable; + uint8_t AcpiDisable; + uint8_t S4BIOS_REQ; + uint8_t PSTATE_Control; + uint32_t PM1aEventBlock; + uint32_t PM1bEventBlock; + uint32_t PM1aControlBlock; + uint32_t PM1bControlBlock; + uint32_t PM2ControlBlock; + uint32_t PMTimerBlock; + uint32_t GPE0Block; + uint32_t GPE1Block; + uint8_t PM1EventLength; + uint8_t PM1ControlLength; + uint8_t PM2ControlLength; + uint8_t PMTimerLength; + uint8_t GPE0Length; + uint8_t GPE1Length; + uint8_t GPE1Base; + uint8_t CStateControl; + uint16_t WorstC2Latency; + uint16_t WorstC3Latency; + uint16_t FlushSize; + uint16_t FlushStride; + uint8_t DutyOffset; + uint8_t DutyWidth; + uint8_t DayAlarm; + uint8_t MonthAlarm; + uint8_t Century; + + // reserved in ACPI 1.0; used since ACPI 2.0+ + uint16_t BootArchitectureFlags; + + uint8_t Reserved2; + uint32_t Flags; + + // 12 byte structure; see below for details + struct GenericAddressStructure ResetReg; + + uint8_t ResetValue; + uint8_t Reserved3[3]; + + // 64bit pointers - Available on ACPI 2.0+ + uint64_t X_FirmwareControl; + uint64_t X_Dsdt; + + struct GenericAddressStructure X_PM1aEventBlock; + struct GenericAddressStructure X_PM1bEventBlock; + struct GenericAddressStructure X_PM1aControlBlock; + struct GenericAddressStructure X_PM1bControlBlock; + struct GenericAddressStructure X_PM2ControlBlock; + struct GenericAddressStructure X_PMTimerBlock; + struct GenericAddressStructure X_GPE0Block; + struct GenericAddressStructure X_GPE1Block; +}; + +rsdp_t *acpi_find_rsdp(); +uint32_t acpi_checksum(void *s, int size); +void *acpi_find_sdt(rsdt_t *rsdt, const char sig[6]); + +#endif diff --git a/kernel/acpi.c b/kernel/acpi.c new file mode 100644 index 0000000..9810305 --- /dev/null +++ b/kernel/acpi.c @@ -0,0 +1,40 @@ +#include +#include + +rsdp_t *acpi_find_rsdp() { + char *ptr = (char *)(KERNEL_VMA + BIOS_START); + const char sig[RSDP_SIG_LEN] = RSDP_SIG; + + for (; (uint32_t)ptr - KERNEL_VMA <= BIOS_END; ptr += 16) { + int i = 0; + for (; i < RSDP_SIG_LEN; i++) + if (ptr[i] != sig[i]) break; + + if (i == RSDP_SIG_LEN) return (rsdp_t *)ptr; + } + + return 0; +} + +uint32_t acpi_checksum(void *s, int size) { + uint32_t sum = 0; + for (int i = 0; i < size; i++) { + sum += ((uint8_t *)s)[i]; + } + + return sum; +} + +void *acpi_find_sdt(rsdt_t *rsdt, const char sig[6]) { + int entries = (rsdt->hdr.Length - sizeof(sdt_hdr_t)) / 4; + for (int i = 0; i < entries; i++) { + const char *ptr = (const char *)rsdt->other_tables[i]; + int j = 0; + for (; j < RSDP_SIG_LEN; j++) + if (ptr[j] != sig[j]) break; + + if (j == RSDP_SIG_LEN) return (void *)ptr; + } + + return 0; +} diff --git a/kernel/kernel.c b/kernel/kernel.c index f06d8c7..6fe83b8 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -8,6 +8,7 @@ #include #include #include +#include #include kernel_ctx_t ctx = {0}; @@ -69,7 +70,23 @@ void exception_handler(int_stack_frame_t r) { r.int_no, r.err_code, r.eax, r.ecx, r.edx, r.ebx, r.esi, r.edi, r.ebp, r.esp+24); LOG("\nEIP: 0x%08X\nCS: 0x%08X\nEFLAGS: 0x%08X\n", r.eip, r.cs, r.eflags); - for (;;) {} + + // Page fault + if (r.int_no == 0xe) { + uint32_t cr2 = 0; + asm volatile ("mov %%cr2, %0" : "=r" (cr2)); + + if ((boot_page_dir[PAGE_DIR_INDEX(cr2)] & 0xFFFFF000) == 0) { + LOG("Creating new page table\n"); + uint32_t *page_tab = mmap_find_first_free_block(); + if (!page_tab) for (;;) {} + page_tab[PAGE_TAB_INDEX(cr2)] = (cr2 & 0xFFFFF000) | 7; + boot_page_dir[PAGE_DIR_INDEX(cr2)] = ((uint32_t)page_tab - KERNEL_VMA) | 7; + } else { + uint32_t *page_tab = (uint32_t *)(KERNEL_VMA + (boot_page_dir[PAGE_DIR_INDEX(cr2)] & 0xFFFFF000)); + page_tab[PAGE_TAB_INDEX(cr2)] = (cr2 & 0xFFFFF000) | 7; + } + } } void sleep(int delay) { @@ -100,12 +117,25 @@ void kernel(multiboot_info_t *info) { if (serial_port_init(COM1)) ctx.log_method = LOG_COM1; LOG("Kernel log being sent to COM1\n"); + idt_init(); + ctx.multi_mmap = (multi_mmap_t *)(info->memmapaddress + KERNEL_VMA); ctx.multi_mmap_size = info->memmaplength; if (!mmap_init()) goto halt; LOG("%d bytes of RAM detected\nCreated a %d byte large physical memory map at 0x%08X\n", ctx.mmap_size*BLOCK_SIZE*8, ctx.mmap_size, (uint32_t)ctx.mmap); - idt_init(); + rsdp_t *rsdp = acpi_find_rsdp(); + if (!rsdp) goto halt; + if ((acpi_checksum(rsdp, sizeof(rsdp_t)) & 0xFF) != 0) goto halt; + LOG("RSDP found\n"); + + rsdt_t *rsdt = (rsdt_t *)(rsdp->RsdtAddress); + if (!rsdt) goto halt; + LOG("%08X\n", acpi_checksum(rsdt, rsdt->hdr.Length)); + if (acpi_checksum(rsdt, sizeof(rsdt_t)) != 0) goto halt; + LOG("RSDT is valid\n"); + +// for (;;) {} pic_remap(PIC_1_START, PIC_2_START); ps2_init();