Massive backlog of changes

This commit is contained in:
2022-06-15 15:59:31 -05:00
parent c962a83ff0
commit a52f06f81e
49 changed files with 1855 additions and 1083 deletions

View File

@@ -1,5 +1,4 @@
#include "mmgr.h"
#include "allocator.h"
#include "x86/apic.h"
#include "x86/msr.h"
#include "stdio.h"
@@ -7,9 +6,9 @@
extern int _kernel_end;
struct apic_registers_t volatile *apic_registers;
struct apic_registers_t volatile apic_registers __attribute__ ((aligned (4096)));
void apic_enable(struct page_stact_t *page_stack)
void apic_enable()
{
// Remap and mask 8259 PIC
asm volatile(
@@ -32,18 +31,19 @@ void apic_enable(struct page_stact_t *page_stack)
"outb %%al, $0x21;"
::: "al"
);
printf("APIC register size: %04x\n", sizeof(struct apic_register_t));
struct msr_apic_base_t msr;
read_msr(MSR_APIC_BASE, (uint64_t*)&msr);
apic_registers = (struct apic_registers_t*)allocate_from_bottom(page_size);
map_page(page_stack, apic_registers, msr.apic_base << 12, PAGE_RW);
map_page(&apic_registers, msr.apic_base << 12, PAGE_RW);
printf("MSR_APIC_BASE: %016x\n", *((uint32_t*)&msr));
apic_registers->spurious_iv.value = apic_registers->spurious_iv.value | 0x1FF;
apic_registers->destination_format.value = 0xFFFFFFFF;
apic_registers.spurious_iv.value = apic_registers.spurious_iv.value | 0x1FF;
apic_registers.destination_format.value = 0xFFFFFFFF;
printf("Finished enabling APIC.\n");
}
void apic_eoi()
{
apic_registers->eoi.value = 0;
apic_registers.eoi.value = 0;
}
void apic_send_ipi(
@@ -65,7 +65,7 @@ void apic_send_ipi(
.destination = destination
};
uint32_t *value_addr = (uint32_t*) &value;
uint32_t *icr_addr = (uint32_t*)&apic_registers->interrput_command;
uint32_t *icr_addr = (uint32_t*)&apic_registers.interrput_command;
icr_addr[4] = value_addr[4];
icr_addr[0] = value_addr[0];
}

View File

@@ -1,14 +1,18 @@
#include "context.h"
#include "pageallocator.h"
#include "platform/context.h"
#include "mmgr.h"
#include "string.h"
#include "x86/processstate.h"
void *initialize_context(void *task_entry, struct page_stack_t *page_stack)
void *initialize_context(void *task_entry)
{
map_page(page_stack, (void*)NULL, reserve_page(page_stack), PAGE_RW);
map_page(page_stack, (void*)0xFF7FF000, reserve_page(page_stack), PAGE_RW | PAGE_USERMODE);
unmap_page((void*)0xFF7FE000);
/*
* TODO: this implementation is a goddamn mess.
* Stack pointer is hardcoded, and the stack isn't resizable.
* PCB pointer is just a constant.
*/
map_page(NULL, reserve_page(), PAGE_RW);
map_page((void*)0xFF3FF000, reserve_page(), PAGE_RW | PAGE_USERMODE);
unmap_page((void*)0xFF3FE000);
uint32_t flags;
asm("pushf; "
"mov (%%esp), %0; "
@@ -20,7 +24,12 @@ void *initialize_context(void *task_entry, struct page_stack_t *page_stack)
state->eip = (uint32_t)task_entry;
state->flags = (flags & ~0xFD) | 0x200;
state->ss = 0x23;
state->esp = 0xFF800000;
state->ebp = 0xFF800000;
state->esp = 0xFF400000;
state->ebp = 0xFF400000;
return (void*)state;
}
void destroy_context(void *ctx)
{
// Nothing to do...
}

View File

@@ -30,7 +30,7 @@
.set tagEntryType, 3
.set tagEntrySize, 12
.set tagEntryAddress, _start - (0xFF800000 - 0x100000)
.set tagEntryAddress, _entry_paddr
.set tagModuleAlignType, 6
.set tagModuleAlignSize, 8
@@ -150,6 +150,10 @@ _start:
mov $PHYSICAL_BASE, %eax
push %eax
# Push kernel's starting linear address
mov $VIRTUAL_BASE, %eax
push %eax
# Load physical address of startPaging()
mov $start_paging, %eax
sub $BASE_DIFF, %eax
@@ -171,15 +175,15 @@ _start:
# Change EBX to point to the virtual address of the multiboot info
# If the new pointer is out-of-bounds, error
add $0xFF700000, %ebx
cmp $0xFF800000, %ebx
add $BASE_DIFF, %ebx
cmp $VIRTUAL_BASE, %ebx
jl .err
cmp $0xFFC00000, %ebx
jge .err
# Call initialize(void* multibootInfo)
# Call x86_startup(void* multibootInfo)
push %ebx
call initialize
call x86_startup
.err:
cli

259
src/x86/idt.c Normal file
View File

@@ -0,0 +1,259 @@
#include "x86/idt.h"
#include "x86/isr.h"
#include "string.h"
#include "system.h"
#include <stddef.h>
#define idt_size 256
#define gdt_size 7
extern int default_page_dir;
enum segment_type_t
{
SEGMENT_KERNEL_CODE,
SEGMENT_KERNEL_DATA,
SEGMENT_USER_CODE,
SEGMENT_USER_DATA,
SEGMENT_TSS
};
struct gdt_entry_t
{
unsigned int limit_low : 16;
unsigned int base_low : 24;
unsigned int accessed : 1;
unsigned int read_write : 1;
unsigned int conforming_expand_down : 1;
unsigned int code : 1;
unsigned int code_data_segment : 1;
unsigned int dpl : 2;
unsigned int present : 1;
unsigned int limit_high : 4;
unsigned int available : 1;
unsigned int long_mode : 1;
unsigned int big : 1;
unsigned int granularity : 1;
unsigned int base_high : 8;
} __attribute__ ((packed));
struct tss_entry_t
{
uint32_t prev_tss;
uint32_t esp0;
uint32_t ss0;
uint32_t esp1;
uint32_t ss1;
uint32_t esp2;
uint32_t ss2;
uint32_t cr3;
uint32_t eip;
uint32_t eflags;
uint32_t eax;
uint32_t ecx;
uint32_t edx;
uint32_t ebx;
uint32_t esp;
uint32_t ebp;
uint32_t esi;
uint32_t edi;
uint32_t es;
uint32_t cs;
uint32_t ss;
uint32_t ds;
uint32_t fs;
uint32_t gs;
uint32_t ldt;
uint16_t trap;
uint16_t iomap_base;
};
struct interrupt_descriptor_t
{
uint16_t offset_1;
uint16_t selector;
uint16_t zero : 8;
uint16_t type : 4;
uint16_t storage : 1;
uint16_t dpl : 2;
uint16_t present : 1;
uint16_t offset_2;
} __attribute__ ((packed));
struct descriptor_table_info_t
{
uint16_t size;
void *location;
} __attribute__ ((packed));
void load_gdt(struct gdt_entry_t *gdt)
{
struct descriptor_table_info_t gdt_info;
gdt_info.size = sizeof(struct gdt_entry_t) * 7 - 1;
gdt_info.location = (void *)gdt;
asm("lgdt (%0);"
"jmp $8, $.ldcs;"
".ldcs:;"
"mov $16, %%ax;"
"mov %%ax, %%ds;"
"mov %%ax, %%es;"
"mov %%ax, %%gs;"
"mov %%ax, %%fs;"
"mov %%ax, %%ss;"
:
: "r"(&gdt_info));
}
void load_idt(struct interrupt_descriptor_t *idt)
{
struct descriptor_table_info_t idt_info;
idt_info.size = sizeof(struct interrupt_descriptor_t) * 256 - 1;
idt_info.location = (void *)idt;
asm("lidt (%0)"
:
: "r"(&idt_info));
}
void load_tr(uint16_t gdt_offset)
{
gdt_offset |= 3;
asm("mov %0, %%ax; "
"ltr %%ax; "
:
: "r"(gdt_offset));
}
void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void *isr, enum isr_type_t type, uint32_t privilage, uint32_t selector)
{
if(type != INTERRPUT_TASK32)
{
descriptor->offset_1 = (uint32_t) isr & 0xFFFF;
descriptor->offset_2 = (uint32_t) isr >> 16;
}
descriptor->selector = selector;
descriptor->zero = 0;
descriptor->type = type;
descriptor->storage = 0;
descriptor->dpl = privilage;
descriptor->present = 1;
}
void create_segment_descriptor(struct gdt_entry_t *descriptor, size_t base, size_t limit, enum segment_type_t type)
{
descriptor->limit_low = limit;
descriptor->limit_high = (limit & (0xf << 16)) >> 16;
descriptor->base_low = base;
descriptor->base_high = (base & (0xff << 24)) >> 24;
descriptor->present = 1;
switch(type)
{
case SEGMENT_KERNEL_CODE:
descriptor->accessed = 0;
descriptor->read_write = 1;
descriptor->conforming_expand_down = 0;
descriptor->code = 1;
descriptor->code_data_segment = 1;
descriptor->dpl = 0;
descriptor->available = 0;
descriptor->long_mode = 0;
descriptor->big = 1;
descriptor->granularity = 1;
break;
case SEGMENT_KERNEL_DATA:
descriptor->accessed = 0;
descriptor->read_write = 1;
descriptor->conforming_expand_down = 0;
descriptor->code = 0;
descriptor->code_data_segment = 1;
descriptor->dpl = 0;
descriptor->available = 0;
descriptor->long_mode = 0;
descriptor->big = 1;
descriptor->granularity = 1;
break;
case SEGMENT_USER_CODE:
descriptor->accessed = 0;
descriptor->read_write = 1;
descriptor->conforming_expand_down = 0;
descriptor->code = 1;
descriptor->code_data_segment = 1;
descriptor->dpl = 3;
descriptor->available = 0;
descriptor->long_mode = 0;
descriptor->big = 1;
descriptor->granularity = 1;
break;
case SEGMENT_USER_DATA:
descriptor->accessed = 0;
descriptor->read_write = 1;
descriptor->conforming_expand_down = 0;
descriptor->code = 0;
descriptor->code_data_segment = 1;
descriptor->dpl = 3;
descriptor->available = 0;
descriptor->long_mode = 0;
descriptor->big = 1;
descriptor->granularity = 1;
break;
case SEGMENT_TSS:
descriptor->accessed = 1;
descriptor->read_write = 0;
descriptor->conforming_expand_down = 0;
descriptor->code = 1;
descriptor->code_data_segment = 0;
descriptor->dpl = 3;
descriptor->available = 0;
descriptor->long_mode = 0;
descriptor->big = 0;
descriptor->granularity = 0;
}
}
void initialize_gdt()
{
static struct gdt_entry_t gdt[gdt_size];
static struct tss_entry_t tss;
static struct tss_entry_t double_fault_tss;
memset(gdt, 0, sizeof(struct gdt_entry_t) * gdt_size);
create_segment_descriptor(&gdt[1], 0, 0xFFFFF, SEGMENT_KERNEL_CODE);
create_segment_descriptor(&gdt[2], 0, 0xFFFFF, SEGMENT_KERNEL_DATA);
create_segment_descriptor(&gdt[3], 0, 0xFFFFF, SEGMENT_USER_CODE);
create_segment_descriptor(&gdt[4], 0, 0xFFFFF, SEGMENT_USER_DATA);
create_segment_descriptor(&gdt[5], (size_t)&tss, sizeof(struct tss_entry_t) - 1, SEGMENT_TSS);
create_segment_descriptor(&gdt[6], (size_t)&double_fault_tss, sizeof(struct tss_entry_t) - 1, SEGMENT_TSS);
memset(&tss, 0, sizeof(tss));
memset(&double_fault_tss, 0, sizeof(tss));
tss.esp0 = (uint32_t)&stack_top;
tss.ss0 = 0x10;
double_fault_tss.esp0 = (uint32_t)&stack_top;
double_fault_tss.ss0 = 0x10;
double_fault_tss.esp = (uint32_t)&stack_top;
double_fault_tss.cs = 0x08;
double_fault_tss.ds = 0x10;
double_fault_tss.ss = 0x10;
double_fault_tss.fs = 0x10;
double_fault_tss.gs = 0x10;
double_fault_tss.cr3 = (uint32_t)&default_page_dir - (uint32_t)&_kernel_start + (uint32_t)&_kernel_pstart;
double_fault_tss.eip = (uint32_t)isr_double_fault;
load_gdt(gdt);
load_tr(5 * sizeof(struct gdt_entry_t));
}
void initialize_idt()
{
static struct interrupt_descriptor_t idt[idt_size];
memset(idt, 0, sizeof(struct interrupt_descriptor_t) * idt_size);
for(int i = 0; i < idt_size; i++)
{
create_interrupt_descriptor(&idt[i], (void*)isr_generic, INTERRPUT_INT32, 0, 8);
}
create_interrupt_descriptor(&idt[EXCEPTION_DIV_BY_0], (void*)isr_division_by_zero, INTERRPUT_INT32, 0, 8);
create_interrupt_descriptor(&idt[EXCEPTION_SEGMENT_NOT_PRESENT], (void*)isr_segment_not_present, INTERRPUT_TRAP32, 0, 8);
create_interrupt_descriptor(&idt[EXCEPTION_GPF], (void*)isr_gp_fault, INTERRPUT_TRAP32, 0, 8);
create_interrupt_descriptor(&idt[EXCEPTION_PAGE_FAULT], (void*)isr_page_fault, INTERRPUT_TRAP32, 0, 8);
create_interrupt_descriptor(&idt[EXCEPTION_DOUBLE_FAULT], /*(void*)isr_double_fault*/NULL, INTERRPUT_TASK32, 0, 8 * 6);
create_interrupt_descriptor(&idt[ISR_PREEMPT], (void*)isr_preempt, INTERRPUT_INT32, 3, 8);
create_interrupt_descriptor(&idt[ISR_APIC_TIMER], (void*)isr_timer, INTERRPUT_INT32, 0, 8);
create_interrupt_descriptor(&idt[ISR_SYSCALL], (void*)isr_syscall, INTERRPUT_INT32, 3, 8);
load_idt(idt);
}

View File

@@ -1,256 +1,18 @@
#include "x86/interrupts.h"
#include "x86/isr.h"
#include "string.h"
#include "system.h"
#include <stddef.h>
#include "platform/interrupts.h"
#include "x86/apic.h"
#define idt_size 256
#define gdt_size 6
extern int default_page_dir;
enum segment_type_t
int initialize_interrupts()
{
SEGMENT_KERNEL_CODE,
SEGMENT_KERNEL_DATA,
SEGMENT_USER_CODE,
SEGMENT_USER_DATA,
SEGMENT_TSS
};
struct gdt_entry_t
{
unsigned int limit_low : 16;
unsigned int base_low : 24;
unsigned int accessed : 1;
unsigned int read_write : 1;
unsigned int conforming_expand_down : 1;
unsigned int code : 1;
unsigned int code_data_segment : 1;
unsigned int dpl : 2;
unsigned int present : 1;
unsigned int limit_high : 4;
unsigned int available : 1;
unsigned int long_mode : 1;
unsigned int big : 1;
unsigned int granularity : 1;
unsigned int base_high : 8;
} __attribute__ ((packed));
struct tss_entry_t
{
uint32_t prev_tss;
uint32_t esp0;
uint32_t ss0;
uint32_t esp1;
uint32_t ss1;
uint32_t esp2;
uint32_t ss2;
uint32_t cr3;
uint32_t eip;
uint32_t eflags;
uint32_t eax;
uint32_t ecx;
uint32_t edx;
uint32_t ebx;
uint32_t esp;
uint32_t ebp;
uint32_t esi;
uint32_t edi;
uint32_t es;
uint32_t cs;
uint32_t ss;
uint32_t ds;
uint32_t fs;
uint32_t gs;
uint32_t ldt;
uint16_t trap;
uint16_t iomap_base;
};
struct interrupt_descriptor_t
{
uint16_t offset_1;
uint16_t selector;
uint16_t zero : 8;
uint16_t type : 4;
uint16_t storage : 1;
uint16_t dpl : 2;
uint16_t present : 1;
uint16_t offset_2;
} __attribute__ ((packed));
struct descriptor_table_info_t
{
uint16_t size;
void *location;
} __attribute__ ((packed));
void load_gdt(struct gdt_entry_t *gdt)
{
struct descriptor_table_info_t gdt_info;
gdt_info.size = sizeof(struct gdt_entry_t) * 7 - 1;
gdt_info.location = (void *)gdt;
asm("lgdt (%0);"
"jmp $8, $.ldcs;"
".ldcs:;"
"mov $16, %%ax;"
"mov %%ax, %%ds;"
"mov %%ax, %%es;"
"mov %%ax, %%gs;"
"mov %%ax, %%fs;"
"mov %%ax, %%ss;"
:
: "r"(&gdt_info));
apic_enable();
return 0;
}
void load_idt(struct interrupt_descriptor_t *idt)
void irq_enable()
{
struct descriptor_table_info_t idt_info;
idt_info.size = sizeof(struct interrupt_descriptor_t) * 256 - 1;
idt_info.location = (void *)idt;
asm("lidt (%0)"
:
: "r"(&idt_info));
asm("sti");
}
void load_tr(uint16_t gdt_offset)
void irq_disable()
{
gdt_offset |= 3;
asm("mov %0, %%ax; "
"ltr %%ax; "
:
: "r"(gdt_offset));
}
void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void *isr, enum isr_type_t type, uint32_t privilage, uint32_t selector)
{
if(type != INTERRPUT_TASK32)
{
descriptor->offset_1 = (uint32_t) isr & 0xFFFF;
descriptor->offset_2 = (uint32_t) isr >> 16;
}
descriptor->selector = selector;
descriptor->zero = 0;
descriptor->type = type;
descriptor->storage = 0;
descriptor->dpl = privilage;
descriptor->present = 1;
}
void create_segment_descriptor(struct gdt_entry_t *descriptor, size_t base, size_t limit, enum segment_type_t type)
{
descriptor->limit_low = limit;
descriptor->limit_high = (limit & (0xf << 16)) >> 16;
descriptor->base_low = base;
descriptor->base_high = (base & (0xff << 24)) >> 24;
descriptor->present = 1;
switch(type)
{
case SEGMENT_KERNEL_CODE:
descriptor->accessed = 0;
descriptor->read_write = 1;
descriptor->conforming_expand_down = 0;
descriptor->code = 1;
descriptor->code_data_segment = 1;
descriptor->dpl = 0;
descriptor->available = 0;
descriptor->long_mode = 0;
descriptor->big = 1;
descriptor->granularity = 1;
break;
case SEGMENT_KERNEL_DATA:
descriptor->accessed = 0;
descriptor->read_write = 1;
descriptor->conforming_expand_down = 0;
descriptor->code = 0;
descriptor->code_data_segment = 1;
descriptor->dpl = 0;
descriptor->available = 0;
descriptor->long_mode = 0;
descriptor->big = 1;
descriptor->granularity = 1;
break;
case SEGMENT_USER_CODE:
descriptor->accessed = 0;
descriptor->read_write = 1;
descriptor->conforming_expand_down = 0;
descriptor->code = 1;
descriptor->code_data_segment = 1;
descriptor->dpl = 3;
descriptor->available = 0;
descriptor->long_mode = 0;
descriptor->big = 1;
descriptor->granularity = 1;
break;
case SEGMENT_USER_DATA:
descriptor->accessed = 0;
descriptor->read_write = 1;
descriptor->conforming_expand_down = 0;
descriptor->code = 0;
descriptor->code_data_segment = 1;
descriptor->dpl = 3;
descriptor->available = 0;
descriptor->long_mode = 0;
descriptor->big = 1;
descriptor->granularity = 1;
break;
case SEGMENT_TSS:
descriptor->accessed = 1;
descriptor->read_write = 0;
descriptor->conforming_expand_down = 0;
descriptor->code = 1;
descriptor->code_data_segment = 0;
descriptor->dpl = 3;
descriptor->available = 0;
descriptor->long_mode = 0;
descriptor->big = 0;
descriptor->granularity = 0;
}
}
void initialize_gdt()
{
static struct gdt_entry_t gdt[gdt_size];
static struct tss_entry_t tss;
static struct tss_entry_t double_fault_tss;
memset(gdt, 0, sizeof(struct gdt_entry_t) * gdt_size);
create_segment_descriptor(&gdt[1], 0, 0xFFFFF, SEGMENT_KERNEL_CODE);
create_segment_descriptor(&gdt[2], 0, 0xFFFFF, SEGMENT_KERNEL_DATA);
create_segment_descriptor(&gdt[3], 0, 0xFFFFF, SEGMENT_USER_CODE);
create_segment_descriptor(&gdt[4], 0, 0xFFFFF, SEGMENT_USER_DATA);
create_segment_descriptor(&gdt[5], (size_t)&tss, sizeof(struct tss_entry_t) - 1, SEGMENT_TSS);
create_segment_descriptor(&gdt[6], (size_t)&double_fault_tss, sizeof(struct tss_entry_t) - 1, SEGMENT_TSS);
memset(&tss, 0, sizeof(tss));
memset(&double_fault_tss, 0, sizeof(tss));
tss.esp0 = &stack_top;
tss.ss0 = 0x10;
double_fault_tss.esp0 = &stack_top;
double_fault_tss.ss0 = 0x10;
double_fault_tss.esp = &stack_top;
double_fault_tss.cs = 0x08;
double_fault_tss.ds = 0x10;
double_fault_tss.ss = 0x10;
double_fault_tss.cr3 = &default_page_dir;
double_fault_tss.eip = (void*)isr_double_fault;
load_gdt(gdt);
load_tr(5 * sizeof(struct gdt_entry_t));
}
void initialize_idt()
{
static struct interrupt_descriptor_t idt[idt_size];
memset(idt, 0, sizeof(struct interrupt_descriptor_t) * idt_size);
for(int i = 0; i < idt_size; i++)
{
create_interrupt_descriptor(&idt[i], (void*)isr_generic, INTERRPUT_INT32, 0, 8);
}
create_interrupt_descriptor(&idt[EXCEPTION_DIV_BY_0], (void*)isr_division_by_zero, INTERRPUT_INT32, 0, 8);
create_interrupt_descriptor(&idt[EXCEPTION_GPF], (void*)isr_gp_fault, INTERRPUT_TRAP32, 0, 8);
create_interrupt_descriptor(&idt[EXCEPTION_PAGE_FAULT], (void*)isr_page_fault, INTERRPUT_TRAP32, 0, 8);
create_interrupt_descriptor(&idt[EXCEPTION_DOUBLE_FAULT], (void*)isr_double_fault, INTERRPUT_TASK32, 0, 8 * 6);
create_interrupt_descriptor(&idt[ISR_PREEMPT], (void*)isr_preempt, INTERRPUT_INT32, 3, 8);
create_interrupt_descriptor(&idt[ISR_APIC_TIMER], (void*)isr_timer, INTERRPUT_INT32, 0, 8);
create_interrupt_descriptor(&idt[ISR_SYSCALL], (void*)isr_syscall, INTERRPUT_INT32, 3, 8);
load_idt(idt);
}
asm("cli");
}

View File

@@ -1,17 +1,17 @@
#include "kernel.h"
#include "x86/isr.h"
#include "stdio.h"
#include "x86/apic.h"
#include "x86/processstate.h"
#include "context.h"
#include "platform/interrupts.h"
#include <stdint.h>
struct interrupt_frame_t
{
size_t eip;
size_t cs;
size_t eflags;
size_t esp;
size_t ss;
uint32_t eip;
uint32_t cs;
uint32_t eflags;
uint32_t esp;
uint32_t ss;
};
void isr_generic(struct interrupt_frame_t *frame)
@@ -24,9 +24,16 @@ void isr_division_by_zero(struct interrupt_frame_t *frame)
printf("Exception: Division by zero\n");
}
void isr_segment_not_present(struct interrupt_frame_t *frame, unsigned int error)
{
irq_disable();
printf("Exception: NP fault, code %08x\n", error);
asm("hlt");
}
void isr_gp_fault(struct interrupt_frame_t *frame, unsigned int error)
{
asm("cli");
irq_disable();
asm("mov $0x10, %%ax; "
"mov %%ax, %%ds; "
"mov %%ax, %%es; "
@@ -39,7 +46,7 @@ void isr_gp_fault(struct interrupt_frame_t *frame, unsigned int error)
void isr_page_fault(struct interrupt_frame_t *frame, unsigned int error)
{
size_t addr;
uint32_t addr;
asm("mov %%cr2, %0"
: "=r"(addr));
asm("mov $0x10, %%ax; "
@@ -54,8 +61,7 @@ void isr_page_fault(struct interrupt_frame_t *frame, unsigned int error)
void isr_double_fault(struct interrupt_frame_t *frame, unsigned int error)
{
asm("cli");
irq_disable();
printf("Exception: Double fault (!!), code %08x\n", error);
asm("hlt");
}

View File

@@ -2,7 +2,7 @@ ENTRY(_start)
SECTIONS
{
. = 0xFF800000;
. = 0xFF400000;
VIRTUAL_BASE = .;
PHYSICAL_BASE = 0x100000;
BASE_DIFF = VIRTUAL_BASE - PHYSICAL_BASE;
@@ -38,4 +38,5 @@ SECTIONS
_kernel_pend = PHYSICAL_BASE + (4096 * IMAGE_SIZE);
_kernel_start = VIRTUAL_BASE;
_kernel_end = VIRTUAL_BASE + (4096 * IMAGE_SIZE);
_entry_paddr = _start - _kernel_start + _kernel_pstart;
}

View File

@@ -1,162 +0,0 @@
#include "mmgr.h"
#include "pageallocator.h"
#include "string.h"
#include "types/status.h"
#include <stdint.h>
const size_t page_size = 4096;
const size_t page_bits = 12;
struct page_table_entry_t
{
uint32_t present : 1;
uint32_t rw : 1;
uint32_t usermode : 1;
uint32_t write_through : 1;
uint32_t cache_disable : 1;
uint32_t accessed : 1;
uint32_t dirty : 1;
uint32_t pat : 1;
uint32_t global : 1;
uint32_t shared : 1;
uint32_t type : 2;
uint32_t physical_address : 20;
};
struct page_table_entry_t *page_tables = (struct page_table_entry_t *)0xFFC00000;
struct page_table_entry_t *page_directory = (struct page_table_entry_t *)0xFFFFF000;
int start_paging(physaddr_t start, physaddr_t end, uint32_t *directory, uint32_t *table, uint32_t *identity_table)
{
physaddr_t p = start;
size_t count = 0;
while (p < end)
{
uint32_t table_entry = p + 3;
int index = p / page_size;
table[index - start / page_size] = table_entry;
identity_table[index] = table_entry;
p += page_size;
count++;
}
directory[0] = ((uint32_t)identity_table) + 3;
directory[1022] = ((uint32_t)table) + 3 + 1024;
directory[1023] = ((uint32_t)directory) + 3;
asm("mov %0, %%cr3"
:
: "r"(directory));
asm("mov %%cr0, %%eax \n"
"or $0x80010000, %%eax \n"
"mov %%eax, %%cr0"
:
:
: "eax");
return count;
}
physaddr_t create_address_space(struct page_stack_t *page_stack)
{
physaddr_t table = reserve_page(page_stack);
if (table == S_OUT_OF_MEMORY)
{
return S_OUT_OF_MEMORY;
}
struct page_table_entry_t buffer = page_directory[0];
page_directory[0].physical_address = table >> page_bits;
asm volatile("invlpg 0xFFC00000" ::
: "memory");
memset((void *)page_tables, 0, 1022 * 4);
page_tables[1022] = page_directory[1022];
page_tables[1023].physical_address = table >> page_bits;
page_tables[1023].present = 1;
page_tables[1023].rw = 1;
page_directory[0] = buffer;
asm volatile("invlpg 0xFFC00000" ::
: "memory");
return table;
}
void load_address_space(physaddr_t table)
{
asm volatile("mov %0, %%cr3"
:
: "r"(table)
: "memory");
}
physaddr_t current_address_space()
{
return page_directory[1023].physical_address << 12;
}
int map_page(struct page_stack_t *page_stack, void *page, physaddr_t frame, int flags)
{
if ((size_t)page % page_size != 0 || frame % page_size != 0)
{
return S_OUT_OF_BOUNDS;
}
size_t table_index = (size_t)page / page_size;
size_t directory_index = table_index / (page_size / sizeof(struct page_table_entry_t));
if (!page_directory[directory_index].present)
{
physaddr_t new_table = reserve_page(page_stack);
if (new_table == S_OUT_OF_MEMORY)
{
return S_OUT_OF_MEMORY;
}
page_directory[directory_index].physical_address = new_table >> page_bits;
page_directory[directory_index].present = 1;
page_directory[directory_index].usermode = (directory_index < 1022) ? 1 : 0;
page_directory[directory_index].rw = 1;
}
page_tables[table_index].physical_address = frame >> 12;
page_tables[table_index].present = 1;
page_tables[table_index].usermode = (flags & PAGE_USERMODE) ? 1 : 0;
page_tables[table_index].rw = (flags & PAGE_RW) ? 1 : 0;
page_tables[table_index].type = PAGE_ANON;
asm volatile("invlpg (%0)"
:
: "r"(page)
: "memory");
return S_OK;
}
physaddr_t unmap_page(void *page)
{
if ((size_t)page % page_size != 0)
{
return S_INVALID_ARGUMENT;
}
size_t table_index = (size_t)page / page_size;
size_t directory_index = table_index / (page_size / sizeof(struct page_table_entry_t));
if (!page_directory[directory_index].present || !page_tables[table_index].present)
{
return S_OUT_OF_BOUNDS;
}
else
{
physaddr_t frame = page_tables[table_index].physical_address << page_bits;
memset(&page_tables[table_index], 0, sizeof(struct page_table_entry_t));
asm volatile("invlpg (%0)"
:
: "r"(page)
: "memory");
return frame;
}
}
enum page_type_t page_type(void *page)
{
size_t table_index = (size_t)page / page_size;
size_t directory_index = table_index / (page_size / sizeof(struct page_table_entry_t));
if (!page_directory[directory_index].present || !page_tables[table_index].present)
{
return PAGE_NOT_PRESENT;
}
else
{
return page_tables[table_index].type;
}
}

View File

@@ -1,8 +1,74 @@
#include "x86/multiboot2.h"
#include "stdio.h"
#include "string.h"
#include <stddef.h>
#include <stdint.h>
void *read_multiboot_table(struct boot_info_t *boot_info, void *table)
enum multiboot2_tag_types
{
MB_END_TAG = 0,
MB_BOOT_COMMAND = 1,
MB_BOOTLOADER = 2,
MB_MODULE = 3,
MB_MEMORY_INFO = 4,
MB_BIOS_BOOT_DEVICE = 5,
MB_MEMORY_MAP = 6,
MB_VBE = 7,
MB_FRAMEBUFFER = 8,
MB_ELF_SYMBOLS = 9,
MB_APM = 10,
MB_EFI32_SYSTEM_TABLE = 11,
MB_EFI64_SYSTEM_TABLE = 12,
MB_SMBIOS = 13,
MB_ACPI10_RSDP = 14,
MB_ACPT20_RSDP = 15,
MB_NETOWRK = 16,
MB_EFI_MEMORY_MAP = 17,
MB_EFI_BOOT_SERVICES = 18,
MB_EFI32_IMAGE = 19,
MB_EFI64_IMAGE = 20,
MB_LOAD_ADDRESS = 21
};
enum multiboot2_memory_types
{
MB_AVAILABLE = 1,
MB_ACPI = 3,
MB_DEFECTIVE = 5
};
struct multiboot2_string_t
{
uint32_t type;
uint32_t size;
char str;
};
struct multiboot2_module_t
{
uint32_t type;
uint32_t size;
uint32_t start;
uint32_t end;
char str;
};
struct multiboot2_map_entry_t
{
uint64_t base;
uint64_t length;
uint32_t type;
};
struct multiboot2_memory_map_t
{
uint32_t type;
uint32_t size;
uint32_t entry_size;
uint32_t entry_version;
struct multiboot2_map_entry_t entries;
};
void *read_multiboot_table_entry(struct boot_info_t *boot_info, void *table)
{
uint32_t *int_table = (uint32_t *)table;
switch (*int_table)
@@ -49,3 +115,14 @@ void *read_multiboot_table(struct boot_info_t *boot_info, void *table)
size_t size = (int_table[1] + 7) - ((int_table[1] + 7) % 8);
return table + size;
}
void *read_multiboot_table(struct boot_info_t *boot_info, void *table)
{
void *multiboot_end = table + *(uint32_t*)table;
table += 8;
while (table != NULL)
{
table = read_multiboot_table_entry(boot_info, table);
}
return multiboot_end;
}

196
src/x86/paging.c Normal file
View File

@@ -0,0 +1,196 @@
#include "platform/paging.h"
#include "string.h"
#include <stddef.h>
struct page_table_entry_t
{
uint32_t present : 1;
uint32_t rw : 1;
uint32_t usermode : 1;
uint32_t write_through : 1;
uint32_t cache_disable : 1;
uint32_t accessed : 1;
uint32_t dirty : 1;
uint32_t pat : 1;
uint32_t global : 1;
uint32_t shared : 1;
uint32_t type : 2;
uint32_t physical_address : 20;
};
extern int _kernel_start;
const size_t page_size = 4096;
const size_t page_bits = 12;
const size_t page_table_levels = 2;
struct page_table_entry_t *page_tables = (struct page_table_entry_t *)0xFFC00000;
struct page_table_entry_t *page_directory = (struct page_table_entry_t *)0xFFFFF000;
struct page_table_entry_t *get_pte_pointer(void *page, int level)
{
unsigned int directory_index = (unsigned int)page >> 22;
struct page_table_entry_t *entry = NULL;
if(level == 0)
{
entry = &page_directory[directory_index];
}
else if(level == 1 && page_directory[directory_index].present)
{
unsigned int page_index = (unsigned int)page >> page_bits;
entry = &page_tables[page_index];
}
return entry;
}
int start_paging(void *linear_addr, physaddr_t start, physaddr_t end, uint32_t *directory, uint32_t *table, uint32_t *identity_table)
{
unsigned int directory_index = (unsigned int) linear_addr >> 22;
physaddr_t p = start;
size_t count = 0;
while (p < end)
{
uint32_t table_entry = p + 3;
int index = p / page_size;
table[index - start / page_size] = table_entry;
identity_table[index] = table_entry;
p += page_size;
count++;
}
directory[0] = ((uint32_t)identity_table) + 3;
directory[directory_index] = ((uint32_t)table) + 3 + 1024;
directory[1023] = ((uint32_t)directory) + 3;
asm("mov %0, %%cr3"
:
: "r"(directory));
asm("mov %%cr0, %%eax \n"
"or $0x80010000, %%eax \n"
"mov %%eax, %%cr0"
:
:
: "eax");
return count;
}
int paging_init_top_table(physaddr_t table)
{
struct page_table_entry_t buffer = page_directory[0];
page_directory[0].physical_address = table >> page_bits;
asm volatile("invlpg 0xFFC00000" ::
: "memory");
memset((void *)page_tables, 0, page_size);
int last_index = (page_size / sizeof(struct page_table_entry_t)) - 1;
int kernel_index = (size_t)&_kernel_start >> 22;
for(int i = kernel_index; i < last_index; i++)
{
page_tables[i] = page_directory[i];
}
page_tables[last_index].physical_address = table >> page_bits;
page_tables[last_index].present = 1;
page_tables[last_index].rw = 1;
page_directory[0] = buffer;
asm volatile("invlpg 0xFFC00000" ::
: "memory");
return 0;
}
physaddr_t paging_current_address_space()
{
return page_directory[1023].physical_address << page_bits;
}
void paging_load_address_space(physaddr_t table)
{
asm volatile("mov %0, %%cr3"
:
: "r"(table)
: "memory");
}
int get_pte_type(void *page, int level)
{
struct page_table_entry_t *entry = get_pte_pointer(page, level);
if(entry != NULL)
{
int flags = (entry->present ? PAGE_PRESENT | PAGE_EXECUTABLE : 0)
| (entry->rw ? PAGE_RW : 0)
| (entry->usermode ? PAGE_USERMODE : 0);
return flags;
}
else
{
return 0;
}
}
int set_pte_type(void *page, int level, int flags)
{
struct page_table_entry_t *entry = get_pte_pointer(page, level);
if(entry != NULL)
{
entry->present = PAGE_PRESENT ? 1 : 0;
entry->rw = PAGE_RW ? 1 : 0;
entry->usermode = PAGE_USERMODE ? 1 : 0;
return 0;
}
else
{
return -1;
}
}
physaddr_t get_pte_address(void *page, int level)
{
struct page_table_entry_t *entry = get_pte_pointer(page, level);
if(entry != NULL)
{
return entry->physical_address << page_bits | ((size_t)page & 0xFFF);
}
else
{
return -1;
}
}
int set_pte_address(void *page, int level, physaddr_t addr)
{
struct page_table_entry_t *entry = get_pte_pointer(page, level);
if(entry != NULL)
{
entry->physical_address = addr >> page_bits;
return 0;
}
else
{
return -1;
}
}
int set_pte(void *page, int level, int flags, physaddr_t addr)
{
if(set_pte_address(page, level, addr) == 0)
{
return set_pte_type(page, level, flags);
}
else
{
return -1;
}
}
void wipe_page_table(void *page, int level)
{
if(level == 1 && (get_pte_type(page, 0) & PAGE_PRESENT) != 0)
{
unsigned int table_index = ((unsigned int)page >> page_bits) & ~0x3FF;
for(int i = 0; i < 1024; i++)
{
page_tables[table_index + i].present = 0;
page_tables[table_index + i].physical_address = 0;
}
}
}

View File

@@ -8,14 +8,13 @@ isr_syscall:
push %ecx
push %ebx
push %eax
push $kernel_state
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
call do_syscall
add $0x14, %esp
add $0x10, %esp
mov $0x23, %cx
mov %cx, %ds
mov %cx, %es
@@ -32,7 +31,6 @@ isr_preempt:
call save_context
add $8, %esp
push $0x800
push $kernel_state
call next_process
add $8, %esp
push %eax

View File

@@ -1,7 +1,5 @@
#include "stdio.h"
#include "platform/putc.h"
#include "mmgr.h"
#include "allocator.h"
#include <stddef.h>
enum vga_color_t {
VGA_COLOR_BLACK = 0,
@@ -30,17 +28,17 @@ struct cell_t
char bg : 4;
};
struct cell_t *screen = (struct cell_t*)NULL;
size_t cursor = 0;
unsigned int cursor = 0;
const size_t tab_width = 4;
const size_t line_width = 80;
const size_t line_count = 25;
const unsigned int tab_width = 4;
const unsigned int line_width = 80;
const unsigned int line_count = 25;
struct cell_t screen[4096 / sizeof(struct cell_t)] __attribute__ ((aligned (4096)));
int initialize_screen()
{
screen = allocate_from_bottom(page_size);
map_page(NULL, screen, 0x000B8000, PAGE_RW);
return map_page(screen, 0x000B8000, PAGE_RW);
}
int putchar(int c)

View File

@@ -1,29 +1,11 @@
#include "kernel.h"
#include "pageallocator.h"
#include "allocator.h"
#include "mmgr.h"
#include "priorityqueue.h"
#include "x86/multiboot2.h"
#include "memorymap.h"
#include "x86/apic.h"
#include "x86/interrupts.h"
#include "stdio.h"
#include "string.h"
#include "module.h"
#include "x86/idt.h"
#include "system.h"
#include "syscalls.h"
#include "config.h"
#include <stdint.h>
#include <stddef.h>
struct kernel_t kernel_state;
int initialize(void *multiboot_info)
void x86_startup(void *multiboot_info)
{
initialize_gdt();
initialize_idt();
initialize_allocator(&_kernel_end, (void*)0xFFC00000);
static struct page_stack_t page_stack;
struct memory_region_t map_array[24];
char bootloader_name[64];
char kernel_parameters[64];
@@ -35,42 +17,12 @@ int initialize(void *multiboot_info)
.array = map_array,
.size = 0,
.capacity = 24}};
void *multiboot_end = multiboot_info + *(uint32_t*)multiboot_info;
multiboot_info += 8;
while (multiboot_info != NULL)
{
multiboot_info = read_multiboot_table(&boot_info, multiboot_info);
}
insert_region(&boot_info.map, (physaddr_t)&_kernel_pstart, (physaddr_t)&_kernel_pend - (physaddr_t)&_kernel_pstart, M_UNAVAILABLE);
initialize_gdt();
initialize_idt();
void *multiboot_end = read_multiboot_table(&boot_info, multiboot_info);
for(void *p = (void*)&_kernel_end; p < multiboot_end; p += page_size)
{
unmap_page(p);
}
initialize_screen();
printf("***%s***\n", PACKAGE_STRING);
/*printf("Type\t\tLocation\t\tSize\n");
for (size_t i = 0; i < boot_info.map.size && boot_info.map.array[i].size > 0; i++)
{
printf("%i\t\t\t%08x\t\t%u\n", boot_info.map.array[i].type, boot_info.map.array[i].location, boot_info.map.array[i].size);
}*/
initialize_page_stack(&page_stack, &boot_info.map, (physaddr_t*)0xFFC00000);
static struct priority_queue_t priority_queue;
construct_priority_queue(&priority_queue, &page_stack);
static struct resource_table_t resource_table;
construct_resource_table(&resource_table, &page_stack);
construct_kernel_state(&kernel_state, &page_stack, &priority_queue, &resource_table, boot_info.module_count, boot_info.modules);
memset(syscall_table, 0, sizeof(syscall_t)*32);
syscall_table[SYSCALL_TEST] = test_syscall;
syscall_table[SYSCALL_MMAP] = mmap;
syscall_table[SYSCALL_MUNMAP] = munmap;
apic_enable(page_stack);
/*apic_registers->divide_config.value = APIC_DIVIDE_1;
apic_registers->lvt_timer.timer_mode = APIC_TIMER_PERIODIC;
apic_registers->lvt_timer.vector = ISR_PREEMPT;
apic_registers->lvt_timer.mask = 0;
apic_registers->initial_count.value = 1024*1024;*/
asm("sti");
load_context(next_process(&kernel_state, NULL));
while(1) asm("hlt");
kernel_initialize(&boot_info);
}