9
include/allocator.h
Normal file
9
include/allocator.h
Normal 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
8
include/context.h
Normal 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));
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
27
include/resource.h
Normal 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);
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
34
src/allocator.c
Normal 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;
|
||||||
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
40
src/elf.c
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
77
src/kernel.c
77
src/kernel.c
@@ -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");
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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++)
|
||||||
|
|||||||
@@ -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
13
src/resource.c
Normal 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;
|
||||||
|
}
|
||||||
@@ -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
32
src/x86/context.c
Normal 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));
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)"
|
||||||
:
|
:
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user