handle page faults
This commit is contained in:
parent
cf1d99fb79
commit
113145e430
2
Makefile
2
Makefile
|
@ -19,7 +19,7 @@ ISO := Hazel.iso
|
||||||
|
|
||||||
CFLAGS := -ffreestanding -Wall -Wextra -Werror -I $(INCLUDEDIR) -I lib
|
CFLAGS := -ffreestanding -Wall -Wextra -Werror -I $(INCLUDEDIR) -I lib
|
||||||
LDFLAGS := -ffreestanding -nostdlib -lgcc -T kernel/kernel.ld
|
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)
|
$(BUILDDIR)/$(KIMG): $(KOBJ) $(LOBJ)
|
||||||
$(CC) $^ -o $@ $(LDFLAGS)
|
$(CC) $^ -o $@ $(LDFLAGS)
|
||||||
|
|
118
include/kernel/acpi.h
Normal file
118
include/kernel/acpi.h
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
#ifndef HAZEL_ACPI_H_
|
||||||
|
#define HAZEL_ACPI_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#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
|
40
kernel/acpi.c
Normal file
40
kernel/acpi.c
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#include <kernel/acpi.h>
|
||||||
|
#include <kernel/kernel.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
#include <kernel/elf.h>
|
#include <kernel/elf.h>
|
||||||
#include <kernel/task.h>
|
#include <kernel/task.h>
|
||||||
#include <kernel/ps2.h>
|
#include <kernel/ps2.h>
|
||||||
|
#include <kernel/acpi.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
kernel_ctx_t ctx = {0};
|
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);
|
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",
|
LOG("\nEIP: 0x%08X\nCS: 0x%08X\nEFLAGS: 0x%08X\n",
|
||||||
r.eip, r.cs, r.eflags);
|
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) {
|
void sleep(int delay) {
|
||||||
|
@ -100,12 +117,25 @@ void kernel(multiboot_info_t *info) {
|
||||||
if (serial_port_init(COM1)) ctx.log_method = LOG_COM1;
|
if (serial_port_init(COM1)) ctx.log_method = LOG_COM1;
|
||||||
LOG("Kernel log being sent to COM1\n");
|
LOG("Kernel log being sent to COM1\n");
|
||||||
|
|
||||||
|
idt_init();
|
||||||
|
|
||||||
ctx.multi_mmap = (multi_mmap_t *)(info->memmapaddress + KERNEL_VMA);
|
ctx.multi_mmap = (multi_mmap_t *)(info->memmapaddress + KERNEL_VMA);
|
||||||
ctx.multi_mmap_size = info->memmaplength;
|
ctx.multi_mmap_size = info->memmaplength;
|
||||||
if (!mmap_init()) goto halt;
|
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);
|
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);
|
pic_remap(PIC_1_START, PIC_2_START);
|
||||||
ps2_init();
|
ps2_init();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user