Merge pull request #5 from ngiddings/pre-alpha

Pre alpha
This commit is contained in:
Nathan Giddings
2021-04-17 03:46:34 -05:00
committed by GitHub
32 changed files with 699 additions and 355 deletions

9
include/allocator.h Normal file
View File

@@ -0,0 +1,9 @@
#pragma once
#include <stddef.h>
void initialize_allocator(void *bottom, void *top);
void *allocate_from_bottom(size_t size);
void *allocate_from_top(size_t size);

8
include/context.h Normal file
View File

@@ -0,0 +1,8 @@
#pragma once
#include "pageallocator.h"
#include "process.h"
void *initialize_context(void *task_entry, struct page_stack_t *page_stack);
void load_context(struct process_state_t *context) __attribute__((noreturn));

View File

@@ -1,10 +1,9 @@
#pragma once #pragma once
#include "pageallocator.h"
#include "types/physaddr.h" #include "types/physaddr.h"
#include <stdint.h> #include <stdint.h>
const uint32_t elf_magic_number = 0x464c457f;
enum elf_endianness_t enum elf_endianness_t
{ {
ELF_LITTLE_ENDIAN = 1, ELF_LITTLE_ENDIAN = 1,
@@ -107,11 +106,13 @@ struct elf_section_header_t
}; };
#if defined __i386__ #if defined __i386__
static const elf_isa_t HOST_ISA = ELF_ISA_x86; static const enum elf_isa_t HOST_ISA = ELF_ISA_x86;
#elif defined __x86_64__ #elif defined __x86_64__
static const elf_isa_t HOST_ISA = ELF_ISA_x86_64; static const enum elf_isa_t HOST_ISA = ELF_ISA_x86_64;
#elif defined __arm__ #elif defined __arm__
static const elf_isa_t HOST_ISA = ELF_ISA_ARM; static const enum elf_isa_t HOST_ISA = ELF_ISA_ARM;
#elif defined __aarch64__ #elif defined __aarch64__
static const elf_isa_t HOST_ISA = ELF_ISA_AARCH64; static const enum elf_isa_t HOST_ISA = ELF_ISA_AARCH64;
#endif #endif
int load_program(struct elf_file_header_t *elf, struct page_stack_t *page_stack);

View File

@@ -1,18 +1,31 @@
#pragma once #pragma once
#include "pageallocator.h"
#include "priorityqueue.h" #include "priorityqueue.h"
#include "resource.h"
#include "module.h" #include "module.h"
#include "process.h"
#include <stddef.h> #include <stddef.h>
enum syscall_id_t
{
SYSCALL_YIELD = 1
};
struct kernel_t struct kernel_t
{ {
struct page_stack_t *page_stack;
struct priority_queue_t *priority_queue; struct priority_queue_t *priority_queue;
struct process_t *active_process;
struct resource_table_t *resource_table;
}; };
extern struct kernel_t kernel; extern struct kernel_t kernel_state;
int do_syscall(struct kernel_t *kernel, size_t id, size_t arg1, size_t arg2, size_t arg3); size_t do_syscall(struct kernel_t *kernel, enum syscall_id_t id, size_t arg1, size_t arg2, size_t arg3);
int load_module(struct kernel_t *kernel, struct module_t *module); int load_module(struct kernel_t *kernel, struct module_t *module);
struct process_state_t *next_process(struct kernel_t *kernel, struct process_state_t *prev_state) __attribute__((noreturn));
void panic(const char *message) __attribute__ ((noreturn)); void panic(const char *message) __attribute__ ((noreturn));

View File

@@ -3,6 +3,15 @@
#include "pageallocator.h" #include "pageallocator.h"
#include "types/physaddr.h" #include "types/physaddr.h"
enum page_flag_t
{
PAGE_RW = 1,
PAGE_EXECUTABLE = 1 << 1,
PAGE_USERMODE = 1 << 2
};
extern const size_t page_size;
/** /**
* @brief Create a new top-level page table and map the kernel in it. * @brief Create a new top-level page table and map the kernel in it.
* *
@@ -19,6 +28,15 @@ physaddr_t create_address_space(struct page_stack_t *page_stack);
*/ */
void load_address_space(physaddr_t table); void load_address_space(physaddr_t table);
/**
* @brief Returns the physical address of the top-level page table currently in
* use.
*
* @param table
* @return physaddr_t
*/
physaddr_t current_address_space();
/** /**
* @brief Maps a single page with the specified flags. * @brief Maps a single page with the specified flags.
* *

View File

@@ -72,4 +72,4 @@ size_t free_page_count(struct page_stack_t *stack);
* @param stack * @param stack
* @param map * @param map
*/ */
int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map, size_t page_size); int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map);

View File

@@ -43,7 +43,7 @@ struct process_t *extract_min(struct priority_queue_t *queue);
* @param process * @param process
* @return int * @return int
*/ */
int insert(struct priority_queue_t *queue, struct process_t *process); int queue_insert(struct priority_queue_t *queue, struct process_t *process);
/** /**
* @brief * @brief
@@ -52,4 +52,4 @@ int insert(struct priority_queue_t *queue, struct process_t *process);
* @param process * @param process
* @return int * @return int
*/ */
int remove(struct priority_queue_t *queue, struct process_t *process); int queue_remove(struct priority_queue_t *queue, struct process_t *process);

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "types/physaddr.h"
#include <stddef.h> #include <stddef.h>
struct process_state_t; struct process_state_t;
@@ -7,6 +8,6 @@ struct process_state_t;
struct process_t struct process_t
{ {
size_t priority; size_t priority;
struct process_state_t *state; struct process_state_t *state;
physaddr_t page_table;
}; };

27
include/resource.h Normal file
View File

@@ -0,0 +1,27 @@
#pragma once
#include "process.h"
#include <stddef.h>
enum resource_type_t
{
RESOURCE_UNAVAILABLE = 0,
RESOURCE_PROCESS
};
struct resource_t
{
size_t type;
union
{
struct process_t process;
};
};
struct resource_table_t
{
struct resource_t *array;
size_t capacity;
};
int find_resource_slot(struct resource_table_t *table);

View File

@@ -2,6 +2,8 @@
#include <stdarg.h> #include <stdarg.h>
int initialize_screen();
int putchar(int c); int putchar(int c);
int puts(const char *str); int puts(const char *str);

View File

@@ -1,5 +1,5 @@
noinst_PROGRAMS = quark-kernel noinst_PROGRAMS = quark-kernel
quark_kernel_SOURCES = kernel.c memorymap.c pageallocator.c priorityqueue.c stdio.c string.c quark_kernel_SOURCES = kernel.c memorymap.c pageallocator.c priorityqueue.c stdio.c string.c elf.c resource.c allocator.c
quark_kernel_LDADD = -lgcc quark_kernel_LDADD = -lgcc
quark_kernel_CFLAGS = -I$(top_srcdir)/include -ffreestanding -mgeneral-regs-only -O0 -Wall -ggdb quark_kernel_CFLAGS = -I$(top_srcdir)/include -ffreestanding -mgeneral-regs-only -O0 -Wall -ggdb
quark_kernel_LDFLAGS = -nostdlib quark_kernel_LDFLAGS = -nostdlib
@@ -12,6 +12,7 @@ quark_kernel_SOURCES += x86/mmgr.c \
x86/apic.c \ x86/apic.c \
x86/isr.c \ x86/isr.c \
x86/msr.c \ x86/msr.c \
x86/context.c \
x86/quark_x86.c \ x86/quark_x86.c \
x86/entry.S x86/entry.S
quark_kernel_LDFLAGS += -T x86/linker.ld quark_kernel_LDFLAGS += -T x86/linker.ld

34
src/allocator.c Normal file
View File

@@ -0,0 +1,34 @@
#include "allocator.h"
struct linear_allocator_t
{
void *bottom;
void *top;
} allocator;
void initialize_allocator(void *bottom, void *top)
{
allocator.bottom = bottom;
allocator.top = top;
}
void *allocate_from_bottom(size_t size)
{
if((size_t)allocator.bottom + size <= (size_t)allocator.top)
{
void *ptr = allocator.bottom;
allocator.bottom += size;
return ptr;
}
return (void*)NULL;
}
void *allocate_from_top(size_t size)
{
if((size_t)allocator.top - size >= (size_t)allocator.bottom)
{
allocator.top -= size;
return allocator.top;
}
return (void*)NULL;
}

View File

@@ -1,102 +0,0 @@
#include "allocator.hpp"
#define AVAIL 0
#define UNAVAIL -1
inline size_t ilog2(size_t n)
{
size_t m = n;
size_t count = 0;
bool isPowerOfTwo = true;
while(m)
{
if((m & 1) == 1 && m > 1)
{
isPowerOfTwo = false;
}
count++;
m >>= 1;
}
return count - (isPowerOfTwo ? 1 : 0);
}
kernelns::Allocator::Allocator()
{
}
kernelns::Allocator::Allocator(void* base, size_t heapSize, size_t blockSize)
{
this->base = (char*) base;
this->heapSize = heapSize;
this->blockSize = blockSize;
this->treeHeight = ilog2(heapSize / blockSize);
size_t headerSize = (heapSize / blockSize) << 1;
for(size_t i = 1; i < (heapSize / blockSize) * 2; i++)
this->base[i] = UNAVAIL;
for(size_t i = 0; i < heapSize / blockSize; i++)
{
if(blockSize * i >= headerSize)
{
size_t index = i + (1 << treeHeight);
this->base[index] = AVAIL;
for(; index > 1 && this->base[index ^ 1] == 0; index >>= 1)
{
this->base[index] = UNAVAIL;
this->base[index ^ 1] = UNAVAIL;
this->base[index >> 1] = AVAIL;
}
}
else
{
this->base[i + (1 << treeHeight)] = 1;
}
}
}
void* kernelns::Allocator::allocate(size_t size)
{
size += blockSize - 1;
size -= size % blockSize;
size_t height = ilog2(size / blockSize);
size_t index = findFreeBlock(height);
if(index)
{
base[index] = height + 1;
return (void*) ((size_t) base + (blockSize << height) * (index - (1 << (treeHeight - height))));
}
return NULL;
}
void kernelns::Allocator::free(void* location)
{
size_t offset = (size_t) location - (size_t) base;
size_t index = (offset / blockSize) + (1 << treeHeight);
for(; index > 0 && base[index] == UNAVAIL; index >>= 1);
base[index] = AVAIL;
for(; index > 1 && base[index ^ 1] == AVAIL; index >>= 1)
{
base[index] = UNAVAIL;
base[index ^ 1] = UNAVAIL;
base[index >> 1] = AVAIL;
}
}
size_t kernelns::Allocator::findFreeBlock(size_t height)
{
if(height > treeHeight)
return 0;
for(size_t index = 1 << (treeHeight - height); index < 1 << (treeHeight - height + 1); index++)
{
if(base[index] == AVAIL)
return index;
}
size_t index = findFreeBlock(height + 1);
if(index)
{
base[index] = UNAVAIL;
base[index << 1] = AVAIL;
base[(index << 1) ^ 1] = AVAIL;
}
return index << 1;
}

View File

@@ -1,42 +0,0 @@
#ifndef ALLOCATOR_H
#define ALLOCATOR_H
#include <stddef.h>
namespace kernelns
{
class Allocator
{
public:
Allocator();
/**
* @param base A pointer to the start of the heap.
* @param heapSize The size of the heap, in bytes. Must be a power of two.
* @param blockSize The smallest unit of allocation, in bytes. Must be a power of two less than or equal to heapSize.
*/
Allocator(void* base, size_t heapSize, size_t blockSize);
void* allocate(size_t size);
void free(void* location);
private:
size_t findFreeBlock(size_t height);
char* base;
size_t heapSize;
size_t blockSize;
size_t treeHeight;
};
}
#endif

40
src/elf.c Normal file
View File

@@ -0,0 +1,40 @@
#include "elf.h"
#include "pageallocator.h"
#include "mmgr.h"
#include "string.h"
#include "types/status.h"
const uint32_t elf_magic_number = 0x464c457f;
int load_program(struct elf_file_header_t *elf, struct page_stack_t *page_stack)
{
struct elf_program_header_t *program_header = (struct elf_program_header_t*)((void*)elf + elf->phoffset);
unsigned int count = elf->phcount;
while(count > 0)
{
if(program_header->type == ELF_LOAD)
{
void *d = program_header->vaddr, *s = (void*)elf + program_header->offset;
for(size_t n = 0; n < program_header->memsize; n += page_size)
{
physaddr_t page = reserve_page(page_stack);
if(page == S_OUT_OF_MEMORY)
{
return S_OUT_OF_MEMORY;
}
int status = map_page(page_stack, d, page, PAGE_RW | PAGE_USERMODE | PAGE_EXECUTABLE);
switch(status)
{
case S_OUT_OF_MEMORY:
return status;
case S_OUT_OF_BOUNDS:
return status;
case S_OK:
memcpy(d, s, page_size);
}
}
}
count--;
program_header = (struct elf_program_header_t*)((void*)program_header + elf->phsize);
}
}

View File

@@ -1,11 +1,84 @@
#include "kernel.h" #include "kernel.h"
#include "mmgr.h"
#include "stdio.h"
#include "elf.h"
#include "context.h"
#include "types/status.h"
int do_syscall(struct kernel_t *kernel, size_t id, size_t arg1, size_t arg2, size_t arg3) size_t do_syscall(struct kernel_t *kernel, enum syscall_id_t id, size_t arg1, size_t arg2, size_t arg3)
{ {
} }
int load_module(struct kernel_t *kernel, struct module_t *module) int load_module(struct kernel_t *kernel, struct module_t *module)
{ {
physaddr_t module_address_space = create_address_space(kernel->page_stack);
load_address_space(module_address_space);
void *const load_base = (void*)0x80000000;
size_t load_offset = 0;
for(physaddr_t p = module->start & ~(page_size - 1); p < module->end; p += page_size)
{
int status = map_page(kernel->page_stack, load_base + load_offset, p, PAGE_RW);
switch(status)
{
case S_OUT_OF_MEMORY:
panic("ran out of memory while mapping module");
case S_OUT_OF_BOUNDS:
panic("got out-of-bounds error while mapping module");
}
load_offset += page_size;
}
int status = load_program(load_base, kernel->page_stack);
switch(status)
{
case S_OUT_OF_MEMORY:
panic("ran out of memory while reading ELF file");
case S_OUT_OF_BOUNDS:
panic("got out-of-bounds error while reading ELF file");
}
void *module_entry = ((struct elf_file_header_t*)load_base)->entry;
void *module_context = initialize_context(module_entry, kernel->page_stack);
printf("loaded module with entry point %08x\n", (unsigned int)module_entry);
load_offset = 0;
for(physaddr_t p = module->start & ~(page_size - 1); p < module->end; p += page_size)
{
int status = unmap_page(load_base + load_offset);
switch(status)
{
case S_OUT_OF_MEMORY:
panic("ran out of memory while unmapping module");
case S_OUT_OF_BOUNDS:
panic("got out-of-bounds error while unmapping module");
}
load_offset += page_size;
}
int index = find_resource_slot(kernel);
if(index < 0)
{
panic("no space left in resource table for module");
}
kernel->resource_table->array[index].type = RESOURCE_PROCESS;
kernel->resource_table->array[index].process.priority = 1;
kernel->resource_table->array[index].process.state = module_context;
kernel->resource_table->array[index].process.page_table = current_address_space();
queue_insert(kernel->priority_queue, &kernel->resource_table->array[index].process);
return S_OK;
}
struct process_state_t *next_process(struct kernel_t *kernel, struct process_state_t *prev_state)
{
if(prev_state != NULL)
{
kernel->active_process->state = prev_state;
queue_insert(kernel->priority_queue, kernel->active_process);
}
kernel->active_process = extract_min(kernel->priority_queue);
load_context(kernel->active_process->state);
}
void panic(const char *message)
{
printf("panic: %s", message);
asm("cli");
while(1) asm("hlt");
} }

View File

@@ -66,36 +66,36 @@ int trim_map(struct memory_map_t *map, int index)
{ {
return -1; return -1;
} }
struct memory_region_t left = map->array[index]; struct memory_region_t *left = &map->array[index];
struct memory_region_t right = map->array[index + 1]; struct memory_region_t *right = &map->array[index + 1];
if(region_overlaps(&left, &right)) if(region_overlaps(left, right))
{ {
if(left.type == right.type) if(left->type == right->type)
{ {
left.size = (right.location + right.size > left.location + left.size ? right.location + right.size : left.location + left.size) - left.location; left->size = (right->location + right->size > left->location + left->size ? right->location + right->size : left->location + left->size) - left->location;
remove_map_entry(map, index + 1); remove_map_entry(map, index + 1);
return index; return index;
} }
else if(left.type < right.type) else if(left->type < right->type)
{ {
if(region_contains(&right, &left)) if(region_contains(right, left))
{ {
remove_map_entry(map, index); remove_map_entry(map, index);
return index; return index;
} }
else if(left.location + left.size <= right.location + right.size) else if(left->location + left->size <= right->location + right->size)
{ {
left.size = (right.location > left.location) ? right.location - left.location : 0; left->size = (right->location > left->location) ? right->location - left->location : 0;
return index + 1; return index + 1;
} }
else else
{ {
struct memory_region_t new_right = { struct memory_region_t new_right = {
.location = right.location + right.size, .location = right->location + right->size,
.size = (left.location + left.size) - (right.location + right.size), .size = (left->location + left->size) - (right->location + right->size),
.type = left.type}; .type = left->type};
left.size = (right.location > left.location) ? right.location - left.location : 0; left->size = (right->location > left->location) ? right->location - left->location : 0;
if(left.size == 0) if(left->size == 0)
remove_map_entry(map, index); remove_map_entry(map, index);
insert_map_entry(map, new_right.location, new_right.size, new_right.type); insert_map_entry(map, new_right.location, new_right.size, new_right.type);
return index + 2; return index + 2;
@@ -103,22 +103,22 @@ int trim_map(struct memory_map_t *map, int index)
} }
else else
{ {
if(region_contains(&left, &right)) if(region_contains(left, right))
{ {
remove_map_entry(map, index + 1); remove_map_entry(map, index + 1);
return index; return index;
} }
else else
{ {
right.size = (right.location + right.size) - (left.location + left.size); right->size = (right->location + right->size) - (left->location + left->size);
right.location = left.location + left.size; right->location = left->location + left->size;
return index + 1; return index + 1;
} }
} }
} }
else if((left.location + left.size == right.location) && left.type == right.type) else if((left->location + left->size == right->location) && left->type == right->type)
{ {
left.size = right.location + right.size - left.location; left->size = right->location + right->size - left->location;
remove_map_entry(map, index + 1); remove_map_entry(map, index + 1);
return index; return index;
} }

View File

@@ -1,4 +1,6 @@
#include "pageallocator.h" #include "pageallocator.h"
#include "mmgr.h"
#include "allocator.h"
#include "types/status.h" #include "types/status.h"
physaddr_t reserve_page(struct page_stack_t *stack) physaddr_t reserve_page(struct page_stack_t *stack)
@@ -15,12 +17,25 @@ physaddr_t reserve_page(struct page_stack_t *stack)
int free_page(struct page_stack_t *stack, physaddr_t location) int free_page(struct page_stack_t *stack, physaddr_t location)
{ {
void *new_limit;
if(stack->stack_pointer > stack->limit_pointer) if(stack->stack_pointer > stack->limit_pointer)
{ {
stack->stack_pointer--; stack->stack_pointer--;
*stack->stack_pointer = location; *stack->stack_pointer = location;
return S_OK; return S_OK;
} }
else if((new_limit = allocate_from_top(page_size)) != NULL)
{
switch(map_page(stack, new_limit, location, PAGE_RW))
{
case S_OUT_OF_MEMORY:
return S_OUT_OF_MEMORY;
case S_OUT_OF_BOUNDS:
return S_OUT_OF_BOUNDS;
case S_OK:
stack->limit_pointer = new_limit;
}
}
return S_OUT_OF_MEMORY; return S_OUT_OF_MEMORY;
} }
@@ -29,7 +44,7 @@ size_t free_page_count(struct page_stack_t *stack)
return stack->base_pointer - stack->stack_pointer; return stack->base_pointer - stack->stack_pointer;
} }
int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map, size_t page_size) int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map)
{ {
stack->total_pages = 0; stack->total_pages = 0;
for(int i = 0; i < map->size; i++) for(int i = 0; i < map->size; i++)

View File

@@ -36,7 +36,7 @@ struct process_t *extract_min(struct priority_queue_t *queue)
return p; return p;
} }
int insert(struct priority_queue_t *queue, struct process_t *process) int queue_insert(struct priority_queue_t *queue, struct process_t *process)
{ {
if(queue->size == queue->capacity) if(queue->size == queue->capacity)
return S_OUT_OF_MEMORY; return S_OUT_OF_MEMORY;
@@ -51,7 +51,7 @@ int insert(struct priority_queue_t *queue, struct process_t *process)
return S_OK; return S_OK;
} }
int remove(struct priority_queue_t *queue, struct process_t *process) int queue_remove(struct priority_queue_t *queue, struct process_t *process)
{ {
for(size_t i = 0; i < queue->size; i++) for(size_t i = 0; i < queue->size; i++)
{ {

13
src/resource.c Normal file
View File

@@ -0,0 +1,13 @@
#include "resource.h"
int find_resource_slot(struct resource_table_t *table)
{
for(int i = 0; i < table->capacity; i++)
{
if(table->array[i].type == RESOURCE_UNAVAILABLE)
{
return i;
}
}
return -1;
}

View File

@@ -1,8 +1,43 @@
#include "mmgr.h"
#include "allocator.h"
#include "apic.h" #include "apic.h"
#include "msr.h"
#include "stdio.h"
#include <stddef.h>
void apic_enable() extern int _kernel_end;
struct apic_registers_t volatile *apic_registers;
void apic_enable(struct page_stact_t *page_stack)
{ {
// Remap and mask 8259 PIC
asm volatile(
"mov $0x11, %%al;"
"outb %%al, $0x20;"
"outb %%al, $0xA0;"
"mov $0x20, %%al;"
"outb %%al, $0x21;"
"mov $0x28, %%al;"
"outb %%al, $0xA1;"
"mov $4, %%al;"
"outb %%al, $0x21;"
"mov $2, %%al;"
"outb %%al, $0xA1;"
"mov $0x01, %%al;"
"outb %%al, $0x21;"
"outb %%al, $0xA1;"
"mov $0xFF, %%al;"
"outb %%al, $0xA1;"
"outb %%al, $0x21;"
::: "al"
);
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);
printf("MSR_APIC_BASE: %016x\n", *((uint32_t*)&msr));
apic_registers->spurious_iv.value = apic_registers->spurious_iv.value | 0x100;
} }
void apic_eoi() void apic_eoi()

32
src/x86/context.c Normal file
View File

@@ -0,0 +1,32 @@
#include "context.h"
#include "pageallocator.h"
#include "mmgr.h"
void *initialize_context(void *task_entry, struct page_stack_t *page_stack)
{
physaddr_t stack0 = reserve_page(page_stack);
map_page(page_stack, (void*)0xFF7FF000, stack0, PAGE_RW);
map_page(page_stack, (void*)0xFF7FD000, stack0, PAGE_RW | PAGE_USERMODE);
unmap_page((void*)0xFF7FE000);
unmap_page((void*)0xFF7FC000);
uint32_t flags;
uint32_t *stack = (uint32_t*)((void*)stack0 - 20);
asm("pushf; "
"mov (%%esp), %0; "
"popf; "
: "=r"(flags));
stack[0] = (uint32_t)task_entry;
stack[1] = 27;
stack[2] = flags;
stack[3] = 0xFF7FE000;
stack[4] = 35;
return (void*)stack;
}
void load_context(struct process_state_t *context)
{
asm("mov %0, %%esp; "
"popal; "
"iret; "
:: "r"(context));
}

View File

@@ -30,7 +30,7 @@
.set tagEntryType, 3 .set tagEntryType, 3
.set tagEntrySize, 12 .set tagEntrySize, 12
.set tagEntryAddress, _start - (0xFF900000 - 0x100000) .set tagEntryAddress, _start - (0xFF800000 - 0x100000)
.set tagModuleAlignType, 6 .set tagModuleAlignType, 6
.set tagModuleAlignSize, 8 .set tagModuleAlignSize, 8
@@ -94,23 +94,6 @@ _multibootInfoTagEnd:
_multibootHeaderEnd: _multibootHeaderEnd:
.section .rodata
gdt:
.long 0, 0
.short 0xFFFF
.short 0x0000
.short 0x9A00
.short 0x00CF
.short 0xFFFF
.short 0x0000
.short 0x9200
.short 0x00CF
gdt_info:
.short 23
.long gdt
.section .bss .section .bss
.align 16 .align 16
@@ -126,19 +109,6 @@ _tempIdentityMap:
_tempPgTable: _tempPgTable:
.skip 4096 .skip 4096
_bootCmdLine:
.skip 64
.align 64
.global system_info
system_info:
.skip 16
.align 64
.global memory_map
memory_map:
.skip 16 * 16
.section .text .section .text
.global _start .global _start
.type _start, @function .type _start, @function
@@ -169,8 +139,17 @@ _start:
sub $BASE_DIFF, %eax sub $BASE_DIFF, %eax
push %eax push %eax
# Push ending physical address to map
mov (%ebx), %eax
add %ebx, %eax
push %eax
# Push starting physical address to map
mov $PHYSICAL_BASE, %eax
push %eax
# Load physical address of startPaging() # Load physical address of startPaging()
mov $startPaging, %eax mov $start_paging, %eax
sub $BASE_DIFF, %eax sub $BASE_DIFF, %eax
# Initialize paging # Initialize paging
@@ -180,8 +159,6 @@ _start:
lea 1f, %eax lea 1f, %eax
jmp *%eax jmp *%eax
1: 1:
# Delete PDE corresponding to identity map. We shouldn't need it anymore.
movl $0, (_tempIdentityMap)
# Flush TLB # Flush TLB
mov %cr3, %eax mov %cr3, %eax
@@ -190,22 +167,9 @@ _start:
# Initialize stack in virtual memory # Initialize stack in virtual memory
mov $stackTop, %esp mov $stackTop, %esp
# Load GPT
lgdt gdt_info
# Load segment registers
jmp $8, $.ldcs
.ldcs:
mov $16, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %gs
mov %ax, %fs
mov %ax, %ss
# Change EBX to point to the virtual address of the multiboot info # Change EBX to point to the virtual address of the multiboot info
# If the new pointer is out-of-bounds, error # If the new pointer is out-of-bounds, error
add $0xFF800000, %ebx add $0xFF700000, %ebx
cmp $0xFF800000, %ebx cmp $0xFF800000, %ebx
jl .err jl .err
cmp $0xFFC00000, %ebx cmp $0xFFC00000, %ebx

View File

@@ -1,14 +1,85 @@
#include "interrupts.h" #include "interrupts.h"
#include "isr.h"
#include "string.h"
#include <stddef.h>
struct idt_info_t #define idt_size 256
#define gdt_size 6
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 gran : 1;
unsigned int base_high : 8;
} __attribute__ ((packed));
struct tss_t
{
};
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;
};
struct descriptor_table_info_t
{ {
uint16_t size; uint16_t size;
void *location; void *location;
} __attribute__ ((packed)); } __attribute__ ((packed));
void lidt(struct interrupt_descriptor_t *idt) struct tss_t tss;
void load_gdt(struct gdt_entry_t *gdt)
{ {
struct idt_info_t idt_info; struct descriptor_table_info_t gdt_info;
gdt_info.size = sizeof(struct gdt_entry_t) * 6 - 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.size = sizeof(struct interrupt_descriptor_t) * 256 - 1;
idt_info.location = (void *)idt; idt_info.location = (void *)idt;
asm("lidt (%0)" asm("lidt (%0)"
@@ -27,3 +98,104 @@ void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void
descriptor->dpl = privilage; descriptor->dpl = privilage;
descriptor->present = 1; 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->gran = 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->gran = 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->gran = 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->gran = 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->gran = 0;
}
}
void initialize_gdt()
{
static struct gdt_entry_t gdt[gdt_size];
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_t), SEGMENT_TSS);
load_gdt(gdt);
}
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);
}
create_interrupt_descriptor(&idt[EXCEPTION_DIV_BY_0], (void*)isr_division_by_zero, INTERRPUT_INT32, 0);
create_interrupt_descriptor(&idt[EXCEPTION_GPF], (void*)isr_gp_fault, INTERRPUT_INT32, 0);
create_interrupt_descriptor(&idt[EXCEPTION_PAGE_FAULT], (void*)isr_page_fault, INTERRPUT_INT32, 0);
create_interrupt_descriptor(&idt[EXCEPTION_DOUBLE_FAULT], (void*)isr_double_fault, INTERRPUT_INT32, 0);
create_interrupt_descriptor(&idt[ISR_APIC_TIMER], (void*)isr_timer, INTERRPUT_INT32, 0);
create_interrupt_descriptor(&idt[ISR_AP_START], (void*)isr_ap_start, INTERRPUT_INT32, 0);
create_interrupt_descriptor(&idt[ISR_SYSCALL], (void*)isr_syscall, INTERRPUT_INT32, 0);
load_idt(idt);
}

View File

@@ -24,6 +24,7 @@ enum interrupt_code_t
EXCEPTION_SIMD_FLOATING_POINT = 19, EXCEPTION_SIMD_FLOATING_POINT = 19,
EXCEPTION_VIRTUALIZATION = 20, EXCEPTION_VIRTUALIZATION = 20,
EXCEPTION_SECURITY = 30, EXCEPTION_SECURITY = 30,
ISR_APIC_TIMER = 64,
ISR_AP_START = 127, ISR_AP_START = 127,
ISR_SYSCALL = 128 ISR_SYSCALL = 128
}; };
@@ -37,18 +38,6 @@ enum isr_type_t
INTERRPUT_INT16 = 6 INTERRPUT_INT16 = 6
}; };
struct interrupt_descriptor_t void initialize_gdt();
{
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;
};
void lidt(struct interrupt_descriptor_t *idt); void initialize_idt();
void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void *isr, enum isr_type_t type, uint32_t privilage);

View File

@@ -1,31 +1,58 @@
#include "kernel.h"
#include "isr.h" #include "isr.h"
#include "stdio.h" #include "stdio.h"
#include "apic.h"
void isr_generic(void* frame)
{
printf("Generic interrupt.\n");
}
__attribute__ ((interrupt))
void isr_division_by_zero(void* frame) void isr_division_by_zero(void* frame)
{ {
printf("Exception: Division by zero\n"); printf("Exception: Division by zero\n");
} }
__attribute__ ((interrupt))
void isr_gp_fault(void* frame, unsigned int error) void isr_gp_fault(void* frame, unsigned int error)
{ {
asm("cli");
} printf("Exception: GP fault, code %08x\n", error);
__attribute__ ((interrupt))
void isr_page_fault(void* frame, unsigned int error)
{
}
__attribute__ ((interrupt))
void isr_double_fault(void* frame, unsigned int error)
{
asm("hlt"); asm("hlt");
} }
__attribute__ ((naked)) void isr_page_fault(void* frame, unsigned int error)
{
size_t addr;
asm("mov %%cr2, %0"
: "=r"(addr));
printf("Exception: Page fault, code %08x, linear address %08x\n", error, addr);
asm("hlt");
}
void isr_double_fault(void* frame, unsigned int error)
{
asm("cli");
printf("Exception: Double fault (!!), code %08x\n", error);
asm("hlt");
}
void isr_timer(void* frame)
{
printf("Timer tick.\n");
apic_eoi();
}
void isr_preempt(void* frame)
{
asm("pushal;"
"mov %esp, %ebp");
struct process_state_t *process_state;
asm("mov %%ebp, %0"
: "=r"(process_state));
next_process(&kernel_state, process_state);
}
void isr_ap_start(void* frame) void isr_ap_start(void* frame)
{ {
asm(".code16"); asm(".code16");
@@ -34,7 +61,6 @@ void isr_ap_start(void* frame)
// do something useful // do something useful
} }
__attribute__ ((interrupt))
void isr_syscall(void* frame) void isr_syscall(void* frame)
{ {

View File

@@ -1,5 +1,8 @@
#pragma once #pragma once
__attribute__ ((interrupt))
void isr_generic(void* frame);
__attribute__ ((interrupt)) __attribute__ ((interrupt))
void isr_division_by_zero(void* frame); void isr_division_by_zero(void* frame);
@@ -12,6 +15,12 @@ void isr_page_fault(void* frame, unsigned int error);
__attribute__ ((interrupt)) __attribute__ ((interrupt))
void isr_double_fault(void* frame, unsigned int error); void isr_double_fault(void* frame, unsigned int error);
__attribute__ ((interrupt))
void isr_timer(void* frame);
__attribute__ ((naked))
void isr_preempt(void* frame);
__attribute__ ((naked)) __attribute__ ((naked))
void isr_ap_start(void* frame); void isr_ap_start(void* frame);

View File

@@ -2,7 +2,7 @@ ENTRY(_start)
SECTIONS SECTIONS
{ {
. = 0xFF900000; . = 0xFF800000;
VIRTUAL_BASE = .; VIRTUAL_BASE = .;
PHYSICAL_BASE = 0x100000; PHYSICAL_BASE = 0x100000;
BASE_DIFF = VIRTUAL_BASE - PHYSICAL_BASE; BASE_DIFF = VIRTUAL_BASE - PHYSICAL_BASE;
@@ -34,9 +34,8 @@ SECTIONS
BSS_END = ADDR(.bss) + SIZEOF(.bss) - (VIRTUAL_BASE - PHYSICAL_BASE); BSS_END = ADDR(.bss) + SIZEOF(.bss) - (VIRTUAL_BASE - PHYSICAL_BASE);
IMAGE_SIZE = ((BSS_END - LOAD_START) + (4096 - ((BSS_END - LOAD_START) % 4096))) / 4096; IMAGE_SIZE = ((BSS_END - LOAD_START) + (4096 - ((BSS_END - LOAD_START) % 4096))) / 4096;
_pageMapLocation = 0xFF800000; _kernel_pstart = PHYSICAL_BASE;
_heapLocation = 0xFFB00000; _kernel_pend = PHYSICAL_BASE + (4096 * IMAGE_SIZE);
_heapSize = 0x100000; _kernel_start = VIRTUAL_BASE;
_kernelStart = VIRTUAL_BASE;
_kernel_end = VIRTUAL_BASE + (4096 * IMAGE_SIZE); _kernel_end = VIRTUAL_BASE + (4096 * IMAGE_SIZE);
} }

View File

@@ -11,34 +11,51 @@ const size_t page_bits = 12;
struct page_table_entry_t struct page_table_entry_t
{ {
uint32_t present : 1; uint32_t present : 1;
uint32_t rw : 1; uint32_t rw : 1;
uint32_t usermode : 1; uint32_t usermode : 1;
uint32_t write_through : 1;
uint32_t writeThrough : 1; uint32_t cache_disable : 1;
uint32_t cacheDisable : 1;
uint32_t accessed : 1; uint32_t accessed : 1;
uint32_t dirty : 1; uint32_t dirty : 1;
uint32_t pat : 1; uint32_t pat : 1;
uint32_t global : 1; uint32_t global : 1;
uint32_t shared : 1; uint32_t shared : 1;
uint32_t ignored : 2; uint32_t ignored : 2;
uint32_t physical_address : 20;
uint32_t physicalAddress : 20;
}; };
struct page_table_entry_t *page_tables = (struct page_table_entry_t *)0xFFC00000; 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 *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;
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 create_address_space(struct page_stack_t *page_stack)
{ {
physaddr_t table = reserve_page(page_stack); physaddr_t table = reserve_page(page_stack);
@@ -47,12 +64,14 @@ physaddr_t create_address_space(struct page_stack_t *page_stack)
return S_OUT_OF_MEMORY; return S_OUT_OF_MEMORY;
} }
struct page_table_entry_t buffer = page_directory[0]; struct page_table_entry_t buffer = page_directory[0];
page_directory[0].physicalAddress = table >> page_bits; page_directory[0].physical_address = table >> page_bits;
asm volatile("invlpg 0xFFC00000" :: asm volatile("invlpg 0xFFC00000" ::
: "memory"); : "memory");
memset((void *)page_tables, 0, 1022 * 4); memset((void *)page_tables, 0, 1022 * 4);
page_tables[1022] = page_directory[1022]; page_tables[1022] = page_directory[1022];
page_tables[1023] = page_directory[1023]; page_tables[1023].physical_address = table >> page_bits;
page_tables[1023].present = 1;
page_tables[1023].rw = 1;
page_directory[0] = buffer; page_directory[0] = buffer;
asm volatile("invlpg 0xFFC00000" :: asm volatile("invlpg 0xFFC00000" ::
: "memory"); : "memory");
@@ -67,6 +86,11 @@ void load_address_space(physaddr_t table)
: "memory"); : "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) 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) if ((size_t)page % page_size != 0 || frame % page_size != 0)
@@ -82,15 +106,15 @@ int map_page(struct page_stack_t *page_stack, void *page, physaddr_t frame, int
{ {
return S_OUT_OF_MEMORY; return S_OUT_OF_MEMORY;
} }
page_directory[directory_index].physicalAddress = new_table >> page_bits; page_directory[directory_index].physical_address = new_table >> page_bits;
page_directory[directory_index].present = 1; page_directory[directory_index].present = 1;
page_directory[directory_index].usermode = 0; page_directory[directory_index].usermode = (directory_index < 1022) ? 1 : 0;
page_directory[directory_index].rw = 1; page_directory[directory_index].rw = 1;
} }
page_tables[table_index].physicalAddress = frame >> 12; page_tables[table_index].physical_address = frame >> 12;
page_tables[table_index].present = 1; page_tables[table_index].present = 1;
page_tables[table_index].usermode = 1; page_tables[table_index].usermode = (flags & PAGE_USERMODE) ? 1 : 0;
page_tables[table_index].rw = 1; page_tables[table_index].rw = (flags & PAGE_RW) ? 1 : 0;
asm volatile("invlpg (%0)" asm volatile("invlpg (%0)"
: :
: "r"(page) : "r"(page)
@@ -112,7 +136,7 @@ physaddr_t unmap_page(void *page)
} }
else else
{ {
physaddr_t frame = page_tables[table_index].physicalAddress << page_bits; physaddr_t frame = page_tables[table_index].physical_address << page_bits;
memset(&page_tables[table_index], 0, sizeof(struct page_table_entry_t)); memset(&page_tables[table_index], 0, sizeof(struct page_table_entry_t));
asm volatile("invlpg (%0)" asm volatile("invlpg (%0)"
: :

View File

@@ -36,10 +36,6 @@ void *read_multiboot_table(struct boot_info_t *boot_info, void *table)
M_UNAVAILABLE); M_UNAVAILABLE);
boot_info->module_count++; boot_info->module_count++;
} }
else
{
printf("WARNING: Too many modules, must skip one.\n");
}
break; break;
case MB_BOOT_COMMAND: case MB_BOOT_COMMAND:
strcpy(boot_info->parameters, &((struct multiboot2_string_t*) table)->str); strcpy(boot_info->parameters, &((struct multiboot2_string_t*) table)->str);

View File

@@ -1,4 +1,6 @@
#include "stdio.h" #include "stdio.h"
#include "mmgr.h"
#include "allocator.h"
#include <stddef.h> #include <stddef.h>
enum vga_color_t { enum vga_color_t {
@@ -28,12 +30,18 @@ struct cell_t
char bg : 4; char bg : 4;
}; };
struct cell_t *screen = (struct cell_t*)0xFF8B8000; struct cell_t *screen = (struct cell_t*)NULL;
size_t cursor = 0; size_t cursor = 0;
const size_t tab_width = 4; const size_t tab_width = 4;
const size_t line_width = 80; const size_t line_width = 80;
int initialize_screen()
{
screen = allocate_from_bottom(page_size);
map_page(NULL, screen, 0x000B8000, PAGE_RW);
}
int putchar(int c) int putchar(int c)
{ {
switch(c) switch(c)

View File

@@ -1,49 +1,31 @@
#include "kernel.h" #include "kernel.h"
#include "pageallocator.h" #include "pageallocator.h"
#include "allocator.h"
#include "mmgr.h"
#include "multiboot2.h" #include "multiboot2.h"
#include "memorymap.h" #include "memorymap.h"
#include "apic.h" #include "apic.h"
#include "interrupts.h" #include "interrupts.h"
#include "msr.h"
#include "stdio.h" #include "stdio.h"
#include "string.h" #include "string.h"
#include "module.h" #include "module.h"
#include "isr.h" #include "config.h"
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
extern int _kernel_pstart;
extern int _kernel_pend;
extern int _kernel_start;
extern int _kernel_end; extern int _kernel_end;
struct apic_registers_t volatile *apic_registers; struct kernel_t kernel_state;
int startPaging(uint32_t *directory, uint32_t *table, uint32_t *identityTable)
{
for (int i = 0; i < 1024; i++)
{
uint32_t pte = i * 4096 + 3;
table[i] = pte;
identityTable[i] = pte;
}
directory[0] = ((uint32_t)identityTable) + 3;
directory[1022] = ((uint32_t)table) + 3;
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 0;
}
int initialize(void *multiboot_info) int initialize(void *multiboot_info)
{ {
static struct interrupt_descriptor_t idt[256]; initialize_gdt();
initialize_idt();
initialize_allocator(&_kernel_end, (void*)0xFFC00000);
static struct page_stack_t page_stack; static struct page_stack_t page_stack;
static struct kernel_t kernel;
struct memory_region_t map_array[16]; struct memory_region_t map_array[16];
char bootloader_name[64]; char bootloader_name[64];
char kernel_parameters[64]; char kernel_parameters[64];
@@ -55,12 +37,19 @@ int initialize(void *multiboot_info)
.array = map_array, .array = map_array,
.size = 0, .size = 0,
.capacity = 16}}; .capacity = 16}};
void *multiboot_end = multiboot_info + *(uint32_t*)multiboot_info;
multiboot_info += 8; multiboot_info += 8;
while (multiboot_info != NULL) while (multiboot_info != NULL)
{ {
multiboot_info = read_multiboot_table(&boot_info, multiboot_info); multiboot_info = read_multiboot_table(&boot_info, multiboot_info);
} }
insert_region(&boot_info.map, 0, 1 << 22, M_UNAVAILABLE); insert_region(&boot_info.map, (physaddr_t)&_kernel_pstart, (physaddr_t)&_kernel_pend, M_UNAVAILABLE);
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"); 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++) for (size_t i = 0; i < boot_info.map.size && boot_info.map.array[i].size > 0; i++)
{ {
@@ -68,35 +57,25 @@ int initialize(void *multiboot_info)
} }
page_stack.base_pointer = (physaddr_t*)0xFFC00000; page_stack.base_pointer = (physaddr_t*)0xFFC00000;
page_stack.stack_pointer = (physaddr_t*)0xFFC00000; page_stack.stack_pointer = (physaddr_t*)0xFFC00000;
page_stack.limit_pointer = (physaddr_t*)0xFF900000; page_stack.limit_pointer = (physaddr_t*)0xFFC00000;
initialize_page_stack(&page_stack, &boot_info.map, 4096); initialize_page_stack(&page_stack, &boot_info.map);
apic_enable(page_stack);
apic_registers->divide_config.value = APIC_DIVIDE_128;
apic_registers->lvt_timer.vector = ISR_APIC_TIMER;
apic_registers->lvt_timer.timer_mode = APIC_TIMER_PERIODIC;
apic_registers->initial_count.value = 1024*1024*1024;
apic_registers->lvt_timer.mask = 0;
kernel_state.page_stack = &page_stack;
for(int i = 0; i < boot_info.module_count; i++) for(int i = 0; i < boot_info.module_count; i++)
{ {
load_module(&kernel, &boot_info.modules[i]); load_module(&kernel_state, &boot_info.modules[i]);
} }
// TODO: setup IDT
memset(idt, 0, sizeof(struct interrupt_descriptor_t) * 256);
create_interrupt_descriptor(&idt[EXCEPTION_DIV_BY_0], (void*)isr_division_by_zero, INTERRPUT_INT32, 0);
create_interrupt_descriptor(&idt[EXCEPTION_GPF], (void*)isr_gp_fault, INTERRPUT_INT32, 0);
create_interrupt_descriptor(&idt[EXCEPTION_PAGE_FAULT], (void*)isr_page_fault, INTERRPUT_INT32, 0);
create_interrupt_descriptor(&idt[EXCEPTION_DOUBLE_FAULT], (void*)isr_double_fault, INTERRPUT_INT32, 0);
create_interrupt_descriptor(&idt[ISR_AP_START], (void*)isr_ap_start, INTERRPUT_INT32, 0);
create_interrupt_descriptor(&idt[ISR_SYSCALL], (void*)isr_syscall, INTERRPUT_INT32, 0);
lidt(idt);
// TODO: setup APIC asm("sti");
asm volatile( while(1)
"mov $0xFF, %%al;" {
"outb %%al, $0xA1;" asm("hlt");
"outb %%al, $0x21;" }
::: "al" // next_process(&kernel_state, NULL);
);
apic_enable();
struct msr_apic_base_t msr;
read_msr(MSR_APIC_BASE, (uint64_t*)&msr);
msr.apic_base = (size_t) &_kernel_end >> 12;
write_msr(MSR_APIC_BASE, (uint64_t*)&msr);
printf("MSR_APIC_BASE: %016x\n", *((uint32_t*)&msr));
apic_registers = (struct apic_registers_t*) (msr.apic_base << 12);
// TODO: enter first process
} }