@@ -4,18 +4,17 @@
|
|||||||
AC_PREREQ([2.69])
|
AC_PREREQ([2.69])
|
||||||
AC_INIT([quark-kernel], [pre-alpha])
|
AC_INIT([quark-kernel], [pre-alpha])
|
||||||
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
|
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
|
||||||
AC_CONFIG_SRCDIR([src/allocator.cpp])
|
AC_CONFIG_SRCDIR([src/kernel.c])
|
||||||
AC_CONFIG_HEADERS([src/config.h])
|
AC_CONFIG_HEADERS([src/config.h])
|
||||||
|
|
||||||
# Checks for programs.
|
# Checks for programs.
|
||||||
AC_PROG_CXX
|
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
AM_PROG_AS
|
AM_PROG_AS
|
||||||
AM_PROG_AR
|
AM_PROG_AR
|
||||||
AC_PROG_RANLIB
|
AC_PROG_RANLIB
|
||||||
|
|
||||||
# Checks for header files.
|
# Checks for header files.
|
||||||
AC_CHECK_HEADERS([stddef.h stdint.h])
|
AC_CHECK_HEADERS([stddef.h stdint.h stdarg.h])
|
||||||
|
|
||||||
# Checks for typedefs, structures, and compiler characteristics.
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
AC_CHECK_HEADER_STDBOOL
|
AC_CHECK_HEADER_STDBOOL
|
||||||
|
|||||||
117
include/elf.h
Normal file
117
include/elf.h
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types/physaddr.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
const uint32_t elf_magic_number = 0x464c457f;
|
||||||
|
|
||||||
|
enum elf_endianness_t
|
||||||
|
{
|
||||||
|
ELF_LITTLE_ENDIAN = 1,
|
||||||
|
ELF_BIG_ENDIAN = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum elf_isa_t
|
||||||
|
{
|
||||||
|
ELF_ISA_NA = 0x00,
|
||||||
|
ELF_ISA_x86 = 0x03,
|
||||||
|
ELF_ISA_MIPS = 0x08,
|
||||||
|
ELF_ISA_PPC = 0x14,
|
||||||
|
ELF_ISA_PPC64 = 0x15,
|
||||||
|
ELF_ISA_ARM = 0x28,
|
||||||
|
ELF_ISA_x86_64 = 0x3E,
|
||||||
|
ELF_ISA_AARCH64 = 0xB7
|
||||||
|
};
|
||||||
|
|
||||||
|
enum elf_segment_type_t
|
||||||
|
{
|
||||||
|
ELF_UNUSED = 0,
|
||||||
|
ELF_LOAD = 1,
|
||||||
|
ELF_DYNAMIC = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
struct elf_file_header_t
|
||||||
|
{
|
||||||
|
uint32_t magic;
|
||||||
|
char size;
|
||||||
|
char endianness;
|
||||||
|
char version;
|
||||||
|
char abi;
|
||||||
|
char abi_version;
|
||||||
|
char reserved[7];
|
||||||
|
uint16_t type;
|
||||||
|
uint16_t machine;
|
||||||
|
uint32_t _version;
|
||||||
|
void *entry;
|
||||||
|
#if defined __i386__ || defined __arm__
|
||||||
|
uint32_t phoffset;
|
||||||
|
uint32_t shoffset;
|
||||||
|
#elif defined __x86_64__ || defined __aarch64__
|
||||||
|
uint64_t phoffset;
|
||||||
|
uint64_t shoffset;
|
||||||
|
#endif
|
||||||
|
uint32_t flags;
|
||||||
|
uint16_t header_size;
|
||||||
|
uint16_t phsize;
|
||||||
|
uint16_t phcount;
|
||||||
|
uint16_t shsize;
|
||||||
|
uint16_t shcount;
|
||||||
|
uint16_t shstrndx;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct elf_program_header_t
|
||||||
|
{
|
||||||
|
uint32_t type;
|
||||||
|
#if defined __i386__ || defined __arm__
|
||||||
|
uint32_t offset;
|
||||||
|
void *vaddr;
|
||||||
|
physaddr_t paddr;
|
||||||
|
uint32_t filesize;
|
||||||
|
uint32_t memsize;
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t align;
|
||||||
|
#elif defined __x86_64__ || defined __aarch64__
|
||||||
|
uint32_t flags;
|
||||||
|
uint64_t offset;
|
||||||
|
void *vaddr;
|
||||||
|
physaddr_t paddr;
|
||||||
|
uint64_t filesize;
|
||||||
|
uint64_t memsize;
|
||||||
|
uint64_t align;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
struct elf_section_header_t
|
||||||
|
{
|
||||||
|
uint32_t name;
|
||||||
|
uint32_t type;
|
||||||
|
#if defined __i386__ || defined __arm__
|
||||||
|
uint32_t flags;
|
||||||
|
void *addr;
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t link;
|
||||||
|
uint32_t info;
|
||||||
|
uint32_t align;
|
||||||
|
uint32_t entry_size;
|
||||||
|
#elif defined __x86_64__ || defined __aarch64__
|
||||||
|
uint64_t flags;
|
||||||
|
void *addr;
|
||||||
|
uint64_t offset;
|
||||||
|
uint64_t size;
|
||||||
|
uint32_t link;
|
||||||
|
uint32_t info;
|
||||||
|
uint64_t align;
|
||||||
|
uint64_t entry_size;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined __i386__
|
||||||
|
static const elf_isa_t HOST_ISA = ELF_ISA_x86;
|
||||||
|
#elif defined __x86_64__
|
||||||
|
static const elf_isa_t HOST_ISA = ELF_ISA_x86_64;
|
||||||
|
#elif defined __arm__
|
||||||
|
static const elf_isa_t HOST_ISA = ELF_ISA_ARM;
|
||||||
|
#elif defined __aarch64__
|
||||||
|
static const elf_isa_t HOST_ISA = ELF_ISA_AARCH64;
|
||||||
|
#endif
|
||||||
18
include/kernel.h
Normal file
18
include/kernel.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "priorityqueue.h"
|
||||||
|
#include "module.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct kernel_t
|
||||||
|
{
|
||||||
|
struct priority_queue_t *priority_queue;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct kernel_t kernel;
|
||||||
|
|
||||||
|
int do_syscall(struct kernel_t *kernel, size_t id, size_t arg1, size_t arg2, size_t arg3);
|
||||||
|
|
||||||
|
int load_module(struct kernel_t *kernel, struct module_t *module);
|
||||||
|
|
||||||
|
void panic(const char *message) __attribute__ ((noreturn));
|
||||||
27
include/memorymap.h
Normal file
27
include/memorymap.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types/physaddr.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
enum memory_type_t
|
||||||
|
{
|
||||||
|
M_AVAILABLE = 1,
|
||||||
|
M_UNAVAILABLE = 2,
|
||||||
|
M_DEFECTIVE = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
struct memory_region_t
|
||||||
|
{
|
||||||
|
physaddr_t location;
|
||||||
|
size_t size;
|
||||||
|
unsigned int type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct memory_map_t
|
||||||
|
{
|
||||||
|
struct memory_region_t *array;
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
};
|
||||||
|
|
||||||
|
void insert_region(struct memory_map_t *map, physaddr_t location, size_t size, enum memory_type_t type);
|
||||||
39
include/mmgr.h
Normal file
39
include/mmgr.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pageallocator.h"
|
||||||
|
#include "types/physaddr.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new top-level page table and map the kernel in it.
|
||||||
|
*
|
||||||
|
* This function does not load the page table; it only initializes it.
|
||||||
|
*
|
||||||
|
* @return physaddr_t
|
||||||
|
*/
|
||||||
|
physaddr_t create_address_space(struct page_stack_t *page_stack);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Load an existing top-level page table
|
||||||
|
*
|
||||||
|
* @param table
|
||||||
|
*/
|
||||||
|
void load_address_space(physaddr_t table);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maps a single page with the specified flags.
|
||||||
|
*
|
||||||
|
* @param page
|
||||||
|
* @param frame
|
||||||
|
* @param flags
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int map_page(struct page_stack_t *page_stack, void *page, physaddr_t frame, int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unmaps a single page, returning the physical address of the frame it
|
||||||
|
* pointed to.
|
||||||
|
*
|
||||||
|
* @param page
|
||||||
|
* @return physaddr_t
|
||||||
|
*/
|
||||||
|
physaddr_t unmap_page(void *page);
|
||||||
10
include/module.h
Normal file
10
include/module.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types/physaddr.h"
|
||||||
|
|
||||||
|
struct module_t
|
||||||
|
{
|
||||||
|
physaddr_t start;
|
||||||
|
physaddr_t end;
|
||||||
|
char str[64 - 2 * sizeof(physaddr_t)];
|
||||||
|
};
|
||||||
75
include/pageallocator.h
Normal file
75
include/pageallocator.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "memorymap.h"
|
||||||
|
#include "types/physaddr.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Describes a stack containing the physical addresses of available page
|
||||||
|
* frames.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct page_stack_t
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief The total number of physical pages managed by the system.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
size_t total_pages;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Points to the topmost physical address on the stack.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
physaddr_t *stack_pointer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Points to the bottom of the stack.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
physaddr_t *base_pointer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Points to the limit of the stack. The stack cannot grow beyond
|
||||||
|
* this point.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
physaddr_t *limit_pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pop the topmost address from the stack and returns that value.
|
||||||
|
*
|
||||||
|
* If the stack is empty, this function will instead return a status code. This
|
||||||
|
* can be identified by testing the least signifigant bits of the return value.
|
||||||
|
*
|
||||||
|
* @param stack
|
||||||
|
* @return physaddr_t
|
||||||
|
*/
|
||||||
|
physaddr_t reserve_page(struct page_stack_t *stack);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pushes `location` onto the stack.
|
||||||
|
*
|
||||||
|
* If there is no room on the stack, the stack will be unaffected.
|
||||||
|
*
|
||||||
|
* @param stack
|
||||||
|
* @param location
|
||||||
|
*/
|
||||||
|
int free_page(struct page_stack_t *stack, physaddr_t location);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Computes the number of available pages.
|
||||||
|
*
|
||||||
|
* @param stack
|
||||||
|
* @return size_t
|
||||||
|
*/
|
||||||
|
size_t free_page_count(struct page_stack_t *stack);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Push all available pages in `map` onto the stack
|
||||||
|
*
|
||||||
|
* @param stack
|
||||||
|
* @param map
|
||||||
|
*/
|
||||||
|
int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map, size_t page_size);
|
||||||
55
include/priorityqueue.h
Normal file
55
include/priorityqueue.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "process.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct priority_queue_t
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief A pointer to the heap described by this structure.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct process_t **heap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The current number of elements stored in the heap.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum number of elements that the heap can currently hold.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
size_t capacity;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* @param queue
|
||||||
|
* @return struct process_t*
|
||||||
|
*/
|
||||||
|
struct process_t *extract_min(struct priority_queue_t *queue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* @param queue
|
||||||
|
* @param process
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int insert(struct priority_queue_t *queue, struct process_t *process);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* @param queue
|
||||||
|
* @param process
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int remove(struct priority_queue_t *queue, struct process_t *process);
|
||||||
12
include/process.h
Normal file
12
include/process.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct process_state_t;
|
||||||
|
|
||||||
|
struct process_t
|
||||||
|
{
|
||||||
|
size_t priority;
|
||||||
|
|
||||||
|
struct process_state_t *state;
|
||||||
|
};
|
||||||
11
include/stdio.h
Normal file
11
include/stdio.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
int putchar(int c);
|
||||||
|
|
||||||
|
int puts(const char *str);
|
||||||
|
|
||||||
|
int printf(const char *format, ...);
|
||||||
|
|
||||||
|
int sprintf(char *str, const char *format, ...);
|
||||||
15
include/string.h
Normal file
15
include/string.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void *memcpy(void *destination, const void *source, size_t num);
|
||||||
|
|
||||||
|
void *memmove(void *destination, const void *source, size_t num);
|
||||||
|
|
||||||
|
int memcmp(const void *ptr1, const void *ptr2, size_t num);
|
||||||
|
|
||||||
|
void *memset(void *ptr, int value, size_t num);
|
||||||
|
|
||||||
|
int strlen(const char *str);
|
||||||
|
|
||||||
|
char *strcpy(char *destination, const char *source);
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
#ifndef PHYSADDR_H
|
#pragma once
|
||||||
#define PHYSADDR_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#if defined __i386__ || __arm__
|
#if defined __i386__ || __arm__
|
||||||
typedef uint32_t physaddr_t;
|
typedef uint32_t physaddr_t;
|
||||||
@@ -10,6 +8,4 @@ typedef uint32_t physaddr_t;
|
|||||||
typedef uint64_t physaddr_t;
|
typedef uint64_t physaddr_t;
|
||||||
#else
|
#else
|
||||||
typedef uint64_t physaddr_t;
|
typedef uint64_t physaddr_t;
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
9
include/types/status.h
Normal file
9
include/types/status.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum status_t
|
||||||
|
{
|
||||||
|
S_OK = 0,
|
||||||
|
S_BAD_SYSCALL,
|
||||||
|
S_OUT_OF_MEMORY,
|
||||||
|
S_OUT_OF_BOUNDS
|
||||||
|
};
|
||||||
@@ -1,15 +1,18 @@
|
|||||||
noinst_PROGRAMS = quark-kernel
|
noinst_PROGRAMS = quark-kernel
|
||||||
quark_kernel_SOURCES = module.cpp util.cpp memorymap.cpp memoryregion.cpp pageallocator.cpp allocator.cpp scheduler.cpp
|
quark_kernel_SOURCES = kernel.c memorymap.c pageallocator.c priorityqueue.c stdio.c string.c
|
||||||
quark_kernel_LDADD = -lgcc
|
quark_kernel_LDADD = -lgcc
|
||||||
quark_kernel_CPPFLAGS = -ffreestanding -mgeneral-regs-only -O0 -Wall -fno-exceptions -fno-rtti -ggdb
|
quark_kernel_CFLAGS = -I$(top_srcdir)/include -ffreestanding -mgeneral-regs-only -O0 -Wall -ggdb
|
||||||
quark_kernel_LDFLAGS = -nostdlib
|
quark_kernel_LDFLAGS = -nostdlib
|
||||||
|
|
||||||
if x86
|
if x86
|
||||||
quark_kernel_SOURCES += x86/mmap.cpp \
|
quark_kernel_SOURCES += x86/mmgr.c \
|
||||||
x86/tty.cpp \
|
x86/putc.c \
|
||||||
x86/interrupts.cpp \
|
x86/multiboot2.c \
|
||||||
x86/multiboot2.cpp \
|
x86/interrupts.c \
|
||||||
x86/initialize.cpp \
|
x86/apic.c \
|
||||||
|
x86/isr.c \
|
||||||
|
x86/msr.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
|
||||||
quark_kernel_DEPENDENCIES = x86/linker.ld
|
quark_kernel_DEPENDENCIES = x86/linker.ld
|
||||||
|
|||||||
44
src/elf.cpp
44
src/elf.cpp
@@ -1,44 +0,0 @@
|
|||||||
#include "elf.hpp"
|
|
||||||
#include "util.hpp"
|
|
||||||
|
|
||||||
kernelns::ELF::ELF()
|
|
||||||
{
|
|
||||||
this->m_fileLocation = (void*) NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
kernelns::ELF::ELF(void* location)
|
|
||||||
{
|
|
||||||
this->m_fileLocation = location;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* kernelns::ELF::entry()
|
|
||||||
{
|
|
||||||
Header* fileHeader = (Header*) m_fileLocation;
|
|
||||||
return fileHeader->entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
int kernelns::ELF::validate()
|
|
||||||
{
|
|
||||||
Header* fileHeader = (Header*) m_fileLocation;
|
|
||||||
if(fileHeader->magic != 0x464c457f)
|
|
||||||
return -1;
|
|
||||||
else if((ISA) fileHeader->machine != HOST_ISA)
|
|
||||||
return -1;
|
|
||||||
else if((Endianness) fileHeader->endianness != Little)
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int kernelns::ELF::load()
|
|
||||||
{
|
|
||||||
Header* fileHeader = (Header*) m_fileLocation;
|
|
||||||
ProgramHeader* programHeader = (ProgramHeader*) ((size_t) m_fileLocation + fileHeader->phoffset);
|
|
||||||
int count = (int) fileHeader->phcount;
|
|
||||||
for(int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
if((SegmentType) programHeader->type != Load)
|
|
||||||
continue;
|
|
||||||
memcpy(programHeader->vaddr, m_fileLocation + programHeader->offset, programHeader->filesize);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
142
src/elf.hpp
142
src/elf.hpp
@@ -1,142 +0,0 @@
|
|||||||
#ifndef ELF_H
|
|
||||||
#define ELF_H
|
|
||||||
|
|
||||||
#include "systypes.hpp"
|
|
||||||
|
|
||||||
namespace kernelns
|
|
||||||
{
|
|
||||||
|
|
||||||
class ELF
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum Endianness
|
|
||||||
{
|
|
||||||
Little = 1,
|
|
||||||
Big = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ISA
|
|
||||||
{
|
|
||||||
NA = 0x00,
|
|
||||||
x86 = 0x03,
|
|
||||||
MIPS = 0x08,
|
|
||||||
PPC = 0x14,
|
|
||||||
PPC64 = 0x15,
|
|
||||||
ARM = 0x28,
|
|
||||||
x86_64 = 0x3E,
|
|
||||||
aarch64 = 0xB7
|
|
||||||
};
|
|
||||||
|
|
||||||
enum SegmentType
|
|
||||||
{
|
|
||||||
Unused = 0,
|
|
||||||
Load = 1,
|
|
||||||
Dynamic = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Header
|
|
||||||
{
|
|
||||||
uint32_t magic;
|
|
||||||
char size;
|
|
||||||
char endianness;
|
|
||||||
char version;
|
|
||||||
char abi;
|
|
||||||
char abiVersion;
|
|
||||||
char reserved[7];
|
|
||||||
uint16_t type;
|
|
||||||
uint16_t machine;
|
|
||||||
uint32_t _version;
|
|
||||||
void* entry;
|
|
||||||
#if defined __i386__ || defined __arm__
|
|
||||||
uint32_t phoffset;
|
|
||||||
uint32_t shoffset;
|
|
||||||
#elif defined __x86_64__ || defined __aarch64__
|
|
||||||
uint64_t phoffset;
|
|
||||||
uint64_t shoffset;
|
|
||||||
#endif
|
|
||||||
uint32_t flags;
|
|
||||||
uint16_t headerSize;
|
|
||||||
uint16_t phsize;
|
|
||||||
uint16_t phcount;
|
|
||||||
uint16_t shsize;
|
|
||||||
uint16_t shcount;
|
|
||||||
uint16_t shstrndx;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ProgramHeader
|
|
||||||
{
|
|
||||||
uint32_t type;
|
|
||||||
#if defined __i386__ || defined __arm__
|
|
||||||
uint32_t offset;
|
|
||||||
void* vaddr;
|
|
||||||
physaddr_t paddr;
|
|
||||||
uint32_t filesize;
|
|
||||||
uint32_t memsize;
|
|
||||||
uint32_t flags;
|
|
||||||
uint32_t align;
|
|
||||||
#elif defined __x86_64__ || defined __aarch64__
|
|
||||||
uint32_t flags;
|
|
||||||
uint64_t offset;
|
|
||||||
void* vaddr;
|
|
||||||
physaddr_t paddr;
|
|
||||||
uint64_t filesize;
|
|
||||||
uint64_t memsize;
|
|
||||||
uint64_t align;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SectionHeader
|
|
||||||
{
|
|
||||||
uint32_t name;
|
|
||||||
uint32_t type;
|
|
||||||
#if defined __i386__ || defined __arm__
|
|
||||||
uint32_t flags;
|
|
||||||
void* addr;
|
|
||||||
uint32_t offset;
|
|
||||||
uint32_t size;
|
|
||||||
uint32_t link;
|
|
||||||
uint32_t info;
|
|
||||||
uint32_t align;
|
|
||||||
uint32_t entrysize;
|
|
||||||
#elif defined __x86_64__ || defined __aarch64__
|
|
||||||
uint64_t flags;
|
|
||||||
void* addr;
|
|
||||||
uint64_t offset;
|
|
||||||
uint64_t size;
|
|
||||||
uint32_t link;
|
|
||||||
uint32_t info;
|
|
||||||
uint64_t align;
|
|
||||||
uint64_t entrysize;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined __i386__
|
|
||||||
static const ISA HOST_ISA = x86;
|
|
||||||
#elif defined __x86_64__
|
|
||||||
static const ISA HOST_ISA = x86_64;
|
|
||||||
#elif defined __arm__
|
|
||||||
static const ISA HOST_ISA = ARM;
|
|
||||||
#elif defined __aarch64__
|
|
||||||
static const ISA HOST_ISA = aarch64;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ELF();
|
|
||||||
|
|
||||||
ELF(void* location);
|
|
||||||
|
|
||||||
void* entry();
|
|
||||||
|
|
||||||
int validate();
|
|
||||||
|
|
||||||
int load();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void* m_fileLocation;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
98
src/heap.hpp
98
src/heap.hpp
@@ -1,98 +0,0 @@
|
|||||||
#ifndef SCHEDULER_H
|
|
||||||
#define SCHEDULER_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include "process.hpp"
|
|
||||||
|
|
||||||
namespace kernelns
|
|
||||||
{
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class Heap
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
Heap()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Heap(T** array, size_t maxSize)
|
|
||||||
{
|
|
||||||
m_array = array;
|
|
||||||
m_size = 0;
|
|
||||||
m_limit = maxSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* extractMin()
|
|
||||||
{
|
|
||||||
if(m_size == 0)
|
|
||||||
return nullptr;
|
|
||||||
m_size--;
|
|
||||||
T* p = m_array[0];
|
|
||||||
m_array[0] = m_array[m_size];
|
|
||||||
heapify(0);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status insert(T* n)
|
|
||||||
{
|
|
||||||
if(m_size == m_limit)
|
|
||||||
return Status::NoMemory;
|
|
||||||
size_t i = m_size;
|
|
||||||
m_size++;
|
|
||||||
while(i > 0 && *m_array[(i - 1) / 2] > *n)
|
|
||||||
{
|
|
||||||
m_array[i] = m_array[(i - 1) / 2];
|
|
||||||
i = (i - 1) / 2;
|
|
||||||
}
|
|
||||||
m_array[i] = n;
|
|
||||||
return Status::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove(T* n)
|
|
||||||
{
|
|
||||||
for(size_t i = 0; i < m_size; i++)
|
|
||||||
{
|
|
||||||
if(m_array[i] == n)
|
|
||||||
{
|
|
||||||
m_size--;
|
|
||||||
m_array[i] = m_array[m_size];
|
|
||||||
heapify(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void heapify(size_t index)
|
|
||||||
{
|
|
||||||
if(i * 2 + 1 >= m_size)
|
|
||||||
return;
|
|
||||||
if (*m_array[i * 2 + 1] <= *m_array[i] && *m_array[i * 2 + 1] <= *m_array[i * 2 + 2])
|
|
||||||
{
|
|
||||||
T buffer = m_array[i];
|
|
||||||
m_array[i] = m_array[i * 2 + 1];
|
|
||||||
m_array[i * 2 + 1] = buffer;
|
|
||||||
heapify(i * 2 + 1);
|
|
||||||
}
|
|
||||||
else if (*m_array[i * 2 + 2] <= *m_array[i] && *m_array[i * 2 + 2] <= *m_array[i * 2 + 1])
|
|
||||||
{
|
|
||||||
T buffer = m_array[i];
|
|
||||||
m_array[i] = m_array[i * 2 + 2];
|
|
||||||
m_array[i * 2 + 2] = buffer;
|
|
||||||
heapify(i * 2 + 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
T** m_array;
|
|
||||||
|
|
||||||
size_t m_size, m_limit;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#ifndef INTERRUPTS_H
|
|
||||||
#define INTERRUPTS_H
|
|
||||||
|
|
||||||
namespace kernelns
|
|
||||||
{
|
|
||||||
class Interrupts
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
static const unsigned int MAX_SYSCALL_ID = 31;
|
|
||||||
|
|
||||||
Interrupts();
|
|
||||||
|
|
||||||
void enable();
|
|
||||||
|
|
||||||
void disable();
|
|
||||||
|
|
||||||
void addSyscall(unsigned int id, void* function);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void* syscalls[MAX_SYSCALL_ID + 1];
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
11
src/kernel.c
Normal file
11
src/kernel.c
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include "kernel.h"
|
||||||
|
|
||||||
|
int do_syscall(struct kernel_t *kernel, size_t id, size_t arg1, size_t arg2, size_t arg3)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int load_module(struct kernel_t *kernel, struct module_t *module)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#include "kernel.hpp"
|
|
||||||
|
|
||||||
int Kernel::allocateRegion(void* page, size_t length, int flags)
|
|
||||||
{
|
|
||||||
char* ptr = (char*) page;
|
|
||||||
for(int i = (int) length; i > 0; i -= mmgr.getPageSize())
|
|
||||||
{
|
|
||||||
physaddr_t frame = pageAllocator.allocate(mmgr.getPageSize());
|
|
||||||
if(frame != 0)
|
|
||||||
mmgr.mapPage(page, reserveFrame(), flags);
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
ptr += mmgr.getPageSize();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Kernel::freeRegion(void* page, size_t length)
|
|
||||||
{
|
|
||||||
char* ptr = (char*) page;
|
|
||||||
for(int i = (int) length; i > 0; i -= mmgr.getPageSize())
|
|
||||||
{
|
|
||||||
pageAllocator.free(mmgr.unmapPage((void*) ptr), mmgr.getPageSize());
|
|
||||||
ptr += mmgr.getPageSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int Kernel::mapRegion(void* page, physaddr_t frame, size_t length, int flags)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
156
src/kernel.hpp
156
src/kernel.hpp
@@ -1,156 +0,0 @@
|
|||||||
#ifndef KERNEL_H
|
|
||||||
#define KERNEL_H
|
|
||||||
|
|
||||||
#include "pageallocator.hpp"
|
|
||||||
#include "memorymanager.hpp"
|
|
||||||
#include "memorymap.hpp"
|
|
||||||
#include "sharedblock.hpp"
|
|
||||||
#include "process.hpp"
|
|
||||||
#include "systypes.hpp"
|
|
||||||
|
|
||||||
using namespace kernelns;
|
|
||||||
|
|
||||||
class Kernel
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
void* malloc(size_t size);
|
|
||||||
|
|
||||||
void free(void* ptr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Maps a region of pages starting at virtual address 'page' with
|
|
||||||
* length 'length'. Allocates each mapped frame and any necessary page
|
|
||||||
* tables. This method does not perform any checks before overwriting page
|
|
||||||
* tables; it is the responsibility of the caller to ensure that the
|
|
||||||
* operation is safe to perform.
|
|
||||||
*
|
|
||||||
* @param page The virtual address of the first page to map
|
|
||||||
* @param length The size in bytes of the region to map
|
|
||||||
* @param flags The flags to apply to each page
|
|
||||||
*
|
|
||||||
* @returns zero upon success, nonzero on failure
|
|
||||||
*/
|
|
||||||
int allocateRegion(void* page, size_t length, int flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Unmaps and frees a region of mapped pages starting at virtual
|
|
||||||
* address 'page' with length 'length'. Does not free any page tables
|
|
||||||
* that are made redundant by this operation. It is the responsibility
|
|
||||||
* of the caller to ensure that all pages in the specified region are
|
|
||||||
* mapped and should be returned to the page allocator.
|
|
||||||
*
|
|
||||||
* @param page The virtual address of the first page to free
|
|
||||||
* @param length The size in bytes of the region to free
|
|
||||||
*/
|
|
||||||
void freeRegion(void* page, size_t length);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Maps a contiguous region of pages to a contiguous region of
|
|
||||||
* frames. Allocates new page tables as needed. All pages will share
|
|
||||||
* the same flags.
|
|
||||||
*
|
|
||||||
* @param page The virtual address of the first page to map
|
|
||||||
* @param frame The physical address of the first frame to map to
|
|
||||||
* @param length The size in bytes of the region to map
|
|
||||||
* @param flags The flags to apply to each page
|
|
||||||
*
|
|
||||||
* @returns zero upon success, nonzero on failure
|
|
||||||
*/
|
|
||||||
int mapRegion(void* page, physaddr_t frame, size_t length, int flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Unmaps a region of pages; does not return them to the page
|
|
||||||
* allocator.
|
|
||||||
*
|
|
||||||
* @param page The virtual address of the first page to unmap
|
|
||||||
* @param length The size in bytes of the region to unmap
|
|
||||||
*/
|
|
||||||
void unmapRegion(void* page, size_t length);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a Shared Block object
|
|
||||||
*
|
|
||||||
* @param length
|
|
||||||
* @param flags
|
|
||||||
* @returns The ID of the
|
|
||||||
*/
|
|
||||||
unsigned int createSharedBlock(size_t length, int flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the shared memory block referred to by 'id'
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
* @returns a reference
|
|
||||||
*/
|
|
||||||
const SharedBlock& getSharedBlock(unsigned int id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a new process
|
|
||||||
*
|
|
||||||
* @param imageBlockID
|
|
||||||
* @return Process&
|
|
||||||
*/
|
|
||||||
Process& createProcess(unsigned int imageBlockID);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the process object corresponsing to 'pid'
|
|
||||||
*
|
|
||||||
* @param pid id of the process to fetch
|
|
||||||
* @returns a reference to the requested process
|
|
||||||
*/
|
|
||||||
Process& getProcess(unsigned int pid);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the current active process object.
|
|
||||||
*
|
|
||||||
* @returns a reference to the active process
|
|
||||||
*/
|
|
||||||
Process& getActiveProcess();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Puts the current active process back on the run queue, and sets
|
|
||||||
* the active process to the next one selected by the scheduler.
|
|
||||||
*
|
|
||||||
* @returns a reference to the new active process
|
|
||||||
*/
|
|
||||||
Process& yieldActiveProcess();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Puts the current active process to sleep, and sets the active
|
|
||||||
* process to the next one selected by the scheduler.
|
|
||||||
*
|
|
||||||
* @returns a reference to the new active process
|
|
||||||
*/
|
|
||||||
Process& sleepActiveProcess();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Terminates the current active process, freeing all its resources,
|
|
||||||
* and activates the next process selected by the scheduler.
|
|
||||||
*
|
|
||||||
* @return Process&
|
|
||||||
*/
|
|
||||||
Process& terminateActiveProcess();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Terminates the process with id 'pid', freeing all its resources.
|
|
||||||
* If it holds any shared blocks which are not held by any other process,
|
|
||||||
* those blocks will be freed.
|
|
||||||
*
|
|
||||||
* @param pid id of the process to terminate
|
|
||||||
*/
|
|
||||||
void terminateProcess(unsigned int pid);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
PageAllocator& pageAllocator;
|
|
||||||
|
|
||||||
MemoryManager& mmgr;
|
|
||||||
|
|
||||||
MemoryMap& memoryMap;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
extern Kernel kernel;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#ifndef MEMORYMANAGER_H
|
|
||||||
#define MEMORYMANAGER_H
|
|
||||||
|
|
||||||
#include "systypes.hpp"
|
|
||||||
|
|
||||||
class MemoryManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the size of a single page on the present platform.
|
|
||||||
*
|
|
||||||
* @return the size in bytes of a single page
|
|
||||||
*/
|
|
||||||
virtual unsigned int getPageSize() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates space for a new top-level page table, and initializes it to
|
|
||||||
* point only to the kernel's page tables.
|
|
||||||
*
|
|
||||||
* @returns the physical address of the new top-level page table
|
|
||||||
*/
|
|
||||||
virtual physaddr_t createAddressSpace() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the given top-level page table(s).
|
|
||||||
*
|
|
||||||
* @param table the top-level page table to load
|
|
||||||
*/
|
|
||||||
virtual void loadAddressSpace(physaddr_t table) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps a single page to a single frame. Allocates a new page table if one
|
|
||||||
* does not exist for that frame.
|
|
||||||
*
|
|
||||||
* @param page the virtual address of the page to map
|
|
||||||
* @param frame the physical address of the frame to map to
|
|
||||||
* @param flags flags to apply to the entry
|
|
||||||
*
|
|
||||||
* @returns zero upon success, nonzero on failure
|
|
||||||
*/
|
|
||||||
virtual int mapPage(void* page, physaddr_t frame, int flags) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes the page table entry for the specified page. Does not deallocate
|
|
||||||
* redundant page tables or modify higher level tables; these are cleaned up
|
|
||||||
* after the owning process ends.
|
|
||||||
*
|
|
||||||
* @param page the virtual address of the page to unmap
|
|
||||||
*/
|
|
||||||
virtual physaddr_t unmapPage(void* page) = 0;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
136
src/memorymap.c
Normal file
136
src/memorymap.c
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
#include "memorymap.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
int compare_regions(struct memory_region_t *lhs, struct memory_region_t *rhs)
|
||||||
|
{
|
||||||
|
if(lhs->location == rhs->location)
|
||||||
|
{
|
||||||
|
return lhs->size > rhs->size ? 1
|
||||||
|
: (lhs->size == rhs->size ? 0
|
||||||
|
: -1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return lhs->location > rhs->location ? 1 : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool region_overlaps(struct memory_region_t *lhs, struct memory_region_t *rhs)
|
||||||
|
{
|
||||||
|
if(rhs->location < lhs->location)
|
||||||
|
{
|
||||||
|
return rhs->location + rhs->size > lhs->location;
|
||||||
|
}
|
||||||
|
return rhs->location < lhs->location + lhs->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool region_contains(struct memory_region_t *lhs, struct memory_region_t *rhs)
|
||||||
|
{
|
||||||
|
return (rhs->location >= lhs->location) &&
|
||||||
|
(rhs->location + rhs->size <= lhs->location + lhs->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert_map_entry(struct memory_map_t *map, physaddr_t location, size_t size, unsigned int type)
|
||||||
|
{
|
||||||
|
struct memory_region_t new_region = {.location = location, .size = size, .type = type};
|
||||||
|
unsigned int i = 0;
|
||||||
|
while(i < map->size)
|
||||||
|
{
|
||||||
|
if(compare_regions(&new_region, &map->array[i]) < 0)
|
||||||
|
{
|
||||||
|
struct memory_region_t buffer = new_region;
|
||||||
|
new_region = map->array[i];
|
||||||
|
map->array[i] = buffer;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
map->array[i] = new_region;
|
||||||
|
map->size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_map_entry(struct memory_map_t *map, int index)
|
||||||
|
{
|
||||||
|
if(index >= 0 && index < map->size)
|
||||||
|
{
|
||||||
|
for(int i = index; i < map->size - 1; i++)
|
||||||
|
{
|
||||||
|
map->array[i] = map->array[i + 1];
|
||||||
|
}
|
||||||
|
map->size--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int trim_map(struct memory_map_t *map, int index)
|
||||||
|
{
|
||||||
|
if(index + 1 >= map->size)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
struct memory_region_t left = map->array[index];
|
||||||
|
struct memory_region_t right = map->array[index + 1];
|
||||||
|
if(region_overlaps(&left, &right))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
remove_map_entry(map, index + 1);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
else if(left.type < right.type)
|
||||||
|
{
|
||||||
|
if(region_contains(&right, &left))
|
||||||
|
{
|
||||||
|
remove_map_entry(map, index);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
else if(left.location + left.size <= right.location + right.size)
|
||||||
|
{
|
||||||
|
left.size = (right.location > left.location) ? right.location - left.location : 0;
|
||||||
|
return index + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct memory_region_t new_right = {
|
||||||
|
.location = right.location + right.size,
|
||||||
|
.size = (left.location + left.size) - (right.location + right.size),
|
||||||
|
.type = left.type};
|
||||||
|
left.size = (right.location > left.location) ? right.location - left.location : 0;
|
||||||
|
if(left.size == 0)
|
||||||
|
remove_map_entry(map, index);
|
||||||
|
insert_map_entry(map, new_right.location, new_right.size, new_right.type);
|
||||||
|
return index + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(region_contains(&left, &right))
|
||||||
|
{
|
||||||
|
remove_map_entry(map, index + 1);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
right.size = (right.location + right.size) - (left.location + left.size);
|
||||||
|
right.location = left.location + left.size;
|
||||||
|
return index + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if((left.location + left.size == right.location) && left.type == right.type)
|
||||||
|
{
|
||||||
|
left.size = right.location + right.size - left.location;
|
||||||
|
remove_map_entry(map, index + 1);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
return index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert_region(struct memory_map_t *map, physaddr_t location, size_t size, unsigned int type)
|
||||||
|
{
|
||||||
|
insert_map_entry(map, location, size, type);
|
||||||
|
int i = 0;
|
||||||
|
while(i >= 0)
|
||||||
|
{
|
||||||
|
i = trim_map(map, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
#include "memorymap.hpp"
|
|
||||||
|
|
||||||
using namespace kernelns;
|
|
||||||
|
|
||||||
MemoryMap::MemoryMap()
|
|
||||||
{
|
|
||||||
this->m_entries = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryMap::MemoryMap(MemoryMap& copy)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < copy.m_entries; i++)
|
|
||||||
m_map[i] = copy[i];
|
|
||||||
this->m_entries = copy.m_entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MemoryRegion& MemoryMap::operator[](size_t index) const
|
|
||||||
{
|
|
||||||
return m_map[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t MemoryMap::size() const
|
|
||||||
{
|
|
||||||
return m_entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t MemoryMap::totalMemory() const
|
|
||||||
{
|
|
||||||
size_t sum = 0;
|
|
||||||
for(int i = 0; i < m_entries; i++)
|
|
||||||
{
|
|
||||||
sum += m_map[i].getSize();
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t MemoryMap::totalMemory(unsigned int type) const
|
|
||||||
{
|
|
||||||
size_t sum = 0;
|
|
||||||
for(int i = 0; i < m_entries; i++)
|
|
||||||
{
|
|
||||||
if(m_map[i].getType() == type)
|
|
||||||
sum += m_map[i].getSize();
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryMap::overlaps(const MemoryRegion& region) const
|
|
||||||
{
|
|
||||||
for(int i = 0; i < m_entries; i++)
|
|
||||||
{
|
|
||||||
if(m_map[i].overlaps(region))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryMap::contains(const MemoryRegion& region) const
|
|
||||||
{
|
|
||||||
for(int i = 0; i < m_entries; i++)
|
|
||||||
{
|
|
||||||
if(m_map[i].contains(region) && m_map[i].getType() == region.getType())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryMap::insertEntry(const MemoryRegion& region)
|
|
||||||
{
|
|
||||||
simpleInsert(region);
|
|
||||||
unsigned int i = 0;
|
|
||||||
while(i != invalidIndex)
|
|
||||||
i = trim(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryMap::insertEntry(physaddr_t location, size_t size, unsigned int type)
|
|
||||||
{
|
|
||||||
insertEntry(MemoryRegion(location, size, type));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryMap::remove(unsigned int index)
|
|
||||||
{
|
|
||||||
for(unsigned int i = index; i < (m_entries - 1); i++)
|
|
||||||
{
|
|
||||||
m_map[i] = m_map[i+1];
|
|
||||||
}
|
|
||||||
m_entries--;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryMap::simpleInsert(const MemoryRegion& region)
|
|
||||||
{
|
|
||||||
MemoryRegion newRegion(region);
|
|
||||||
unsigned int i = 0;
|
|
||||||
while(i < m_entries)
|
|
||||||
{
|
|
||||||
if(newRegion < m_map[i])
|
|
||||||
{
|
|
||||||
MemoryRegion buffer = newRegion;
|
|
||||||
newRegion = m_map[i];
|
|
||||||
m_map[i] = buffer;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
m_map[i] = newRegion;
|
|
||||||
m_entries++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryMap::simpleInsert(physaddr_t location, size_t size, unsigned int type)
|
|
||||||
{
|
|
||||||
simpleInsert(MemoryRegion(location, size, type));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int MemoryMap::trim(unsigned int index)
|
|
||||||
{
|
|
||||||
if(index + 1 >= m_entries)
|
|
||||||
return invalidIndex;
|
|
||||||
MemoryRegion& left = m_map[index];
|
|
||||||
MemoryRegion& right = m_map[index+1];
|
|
||||||
if(left.overlaps(right))
|
|
||||||
{
|
|
||||||
if(left.getType() == right.getType())
|
|
||||||
{
|
|
||||||
left = MemoryRegion(left.getLocation(),
|
|
||||||
(right.getEnd() > left.getEnd() ? right.getEnd() : left.getEnd()) - left.getLocation(),
|
|
||||||
left.getType());
|
|
||||||
remove(index + 1);
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
else if(left.getType() < right.getType())
|
|
||||||
{
|
|
||||||
if(right.contains(left))
|
|
||||||
{
|
|
||||||
remove(index);
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
else if(left.getEnd() <= right.getEnd())
|
|
||||||
{
|
|
||||||
left.truncateRight(right.getLocation());
|
|
||||||
return index + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MemoryRegion newRight(right.getEnd(), left.getEnd() - right.getEnd(), left.getType());
|
|
||||||
left.truncateRight(right.getLocation());
|
|
||||||
if(left.getSize() == 0)
|
|
||||||
remove(index);
|
|
||||||
simpleInsert(newRight);
|
|
||||||
return index + 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(left.contains(right))
|
|
||||||
{
|
|
||||||
remove(index + 1);
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
right.truncateLeft(left.getEnd());
|
|
||||||
return index + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(left.bordersLeft(right) && left.getType() == right.getType())
|
|
||||||
{
|
|
||||||
left = MemoryRegion(left.getLocation(), right.getEnd() - left.getLocation(), left.getType());
|
|
||||||
remove(index + 1);
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
return index + 1;
|
|
||||||
}
|
|
||||||
@@ -1,152 +0,0 @@
|
|||||||
#ifndef MEMORYMAP_H
|
|
||||||
#define MEMORYMAP_H
|
|
||||||
|
|
||||||
#include "systypes.hpp"
|
|
||||||
#include "memoryregion.hpp"
|
|
||||||
|
|
||||||
namespace kernelns
|
|
||||||
{
|
|
||||||
|
|
||||||
class MemoryMap
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
MemoryMap();
|
|
||||||
|
|
||||||
MemoryMap(MemoryMap& copy);
|
|
||||||
|
|
||||||
const MemoryRegion& operator[](size_t index) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The number of memory regions described by this object
|
|
||||||
*/
|
|
||||||
size_t size() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the total amount of memory described by this memory map.
|
|
||||||
* Since no two regions may overlap, this is equivalent to the sum of the
|
|
||||||
* size of each memory region stored in this object.
|
|
||||||
*
|
|
||||||
* @return The total amount of memory described by this memory map.
|
|
||||||
*/
|
|
||||||
size_t totalMemory() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the total amount of memory of a specified type described by
|
|
||||||
* this memory map. Since no two regions overlap, this is equivalent to the
|
|
||||||
* sum of the size of each memory region stored in this object whose type
|
|
||||||
* is equal to `type`.
|
|
||||||
*
|
|
||||||
* @param type The type of memory region to count
|
|
||||||
* @return The total amount of memory of the specified type
|
|
||||||
*/
|
|
||||||
size_t totalMemory(unsigned int type) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if `region` overlaps any memory region contained in this
|
|
||||||
* memory map.
|
|
||||||
*
|
|
||||||
* @param region
|
|
||||||
* @return true if, for any region `k` in this map, `k.overlaps(region)`.
|
|
||||||
* @return false if there is no region in this map where `k.overlaps(region)`.
|
|
||||||
*/
|
|
||||||
bool overlaps(const MemoryRegion& region) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if `region` is contained an any memory region in this map
|
|
||||||
* with the same type as `region`.
|
|
||||||
*
|
|
||||||
* @param region
|
|
||||||
* @return true if, for any region `k` in this map, `k.contains(region)
|
|
||||||
* && k.getType() == region.getType()`.
|
|
||||||
* @return false if the condition above is not true
|
|
||||||
*/
|
|
||||||
bool contains(const MemoryRegion& region) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Adds `region` into the memory map. Adjusts the map as necessary
|
|
||||||
* so that no regions overlap. Regions of higher type take precedence over
|
|
||||||
* regions with lower types; therefore, the lower typed regions are trimmed
|
|
||||||
* or deleted where they overlap with higher typed regions. Adjacent or
|
|
||||||
* overlapping regions with identical types are merged.
|
|
||||||
*
|
|
||||||
* @param region The memory region to insert
|
|
||||||
*/
|
|
||||||
void insertEntry(const MemoryRegion& region);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Overload of `insertEntry()`. @see insertRegion(const MemoryRegion&).
|
|
||||||
*
|
|
||||||
* @param location
|
|
||||||
* @param size
|
|
||||||
* @param type
|
|
||||||
*/
|
|
||||||
void insertEntry(physaddr_t location, size_t size, unsigned int type);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Removes the element at `index` in `m_map`. All objects located
|
|
||||||
* after that index are moved accordingly.
|
|
||||||
*
|
|
||||||
* @param index Locatation of the object to delete
|
|
||||||
*/
|
|
||||||
void remove(unsigned int index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Inserts a copy of `region` into `m_map`. The new element is
|
|
||||||
* inserted such that `m_map` is sorted in ascending order. Overlapping
|
|
||||||
* elements are not trimmed.
|
|
||||||
*
|
|
||||||
* @param region The memory region to insert
|
|
||||||
*/
|
|
||||||
void simpleInsert(const MemoryRegion& region);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Overload of `simpleInsert(const MemoryRegion& region)`.
|
|
||||||
*
|
|
||||||
* @param location
|
|
||||||
* @param size
|
|
||||||
* @param type
|
|
||||||
*/
|
|
||||||
void simpleInsert(physaddr_t location, size_t size, unsigned int type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief If `m_map[index].overlaps(m_map[index+1])`, the two elements are
|
|
||||||
* modified so that they no longer overlap. The following rules apply:
|
|
||||||
*
|
|
||||||
* 1. This memory map will describe the same set of locations before and
|
|
||||||
* after performing this operation.
|
|
||||||
*
|
|
||||||
* 2. Adjacent regions of the same type are merged into a single region.
|
|
||||||
*
|
|
||||||
* 3. Where two regions of differing types overlap, the higher type takes
|
|
||||||
* precedence. The region of the lower type is truncated, split, or deleted
|
|
||||||
* so as to not overlap the region of the higher type.
|
|
||||||
*
|
|
||||||
* 4. This operation is local: only `m_map[index]` and `m_map[index+1]` are
|
|
||||||
* modified (although if a region must be split, a new region will be
|
|
||||||
* inserted at the location `index+2`).
|
|
||||||
*
|
|
||||||
* This function has no effect if `index+1 >= m_entries`, or if
|
|
||||||
* `m_map[index]` does not overlap the `m_map[index+1]`.
|
|
||||||
*
|
|
||||||
* @param index The location of the region to trim.
|
|
||||||
*
|
|
||||||
* @return The index of the rightmost region affected.
|
|
||||||
*/
|
|
||||||
unsigned int trim(unsigned int index);
|
|
||||||
|
|
||||||
static const unsigned int maxEntries = 16;
|
|
||||||
|
|
||||||
static const unsigned int invalidIndex = 0xFFFF;
|
|
||||||
|
|
||||||
MemoryRegion m_map[maxEntries];
|
|
||||||
|
|
||||||
size_t m_entries;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
#include "memoryregion.hpp"
|
|
||||||
|
|
||||||
MemoryRegion::MemoryRegion()
|
|
||||||
{
|
|
||||||
m_location = 0;
|
|
||||||
m_size = 0;
|
|
||||||
m_type = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryRegion::MemoryRegion(const MemoryRegion& copy)
|
|
||||||
{
|
|
||||||
m_location = copy.m_location;
|
|
||||||
m_size = copy.m_size;
|
|
||||||
m_type = copy.m_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryRegion::MemoryRegion(physaddr_t location, size_t size, unsigned int type)
|
|
||||||
{
|
|
||||||
m_location = location;
|
|
||||||
m_size = size;
|
|
||||||
m_type = (size_t) type;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MemoryRegion& MemoryRegion::operator=(const MemoryRegion& rhs)
|
|
||||||
{
|
|
||||||
m_location = rhs.m_location;
|
|
||||||
m_size = rhs.m_size;
|
|
||||||
m_type = rhs.m_type;
|
|
||||||
return rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryRegion::operator==(const MemoryRegion& rhs) const
|
|
||||||
{
|
|
||||||
return (m_location == rhs.m_location) && (m_size == rhs.m_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryRegion::operator!=(const MemoryRegion& rhs) const
|
|
||||||
{
|
|
||||||
return (m_location != rhs.m_location) || (m_size != rhs.m_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryRegion::operator<(const MemoryRegion& rhs) const
|
|
||||||
{
|
|
||||||
return (m_location < rhs.m_location) || ((m_location == rhs.m_location) && (m_size < rhs.m_size));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryRegion::operator>(const MemoryRegion& rhs) const
|
|
||||||
{
|
|
||||||
return (m_location > rhs.m_location) || ((m_location == rhs.m_location) && (m_size > rhs.m_size));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryRegion::operator<=(const MemoryRegion& rhs) const
|
|
||||||
{
|
|
||||||
return (m_location < rhs.m_location) || ((m_location == rhs.m_location) && (m_size <= rhs.m_size));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryRegion::operator>=(const MemoryRegion& rhs) const
|
|
||||||
{
|
|
||||||
return (m_location > rhs.m_location) || ((m_location == rhs.m_location) && (m_size >= rhs.m_size));
|
|
||||||
}
|
|
||||||
|
|
||||||
physaddr_t MemoryRegion::getLocation() const
|
|
||||||
{
|
|
||||||
return m_location;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t MemoryRegion::getSize() const
|
|
||||||
{
|
|
||||||
return m_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int MemoryRegion::getType() const
|
|
||||||
{
|
|
||||||
return m_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
physaddr_t MemoryRegion::getEnd() const
|
|
||||||
{
|
|
||||||
return m_location + m_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryRegion::contains(const MemoryRegion& r) const
|
|
||||||
{
|
|
||||||
return contains(r.m_location, r.m_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryRegion::contains(physaddr_t location, size_t size) const
|
|
||||||
{
|
|
||||||
return (location >= m_location) &&
|
|
||||||
(location + size <= m_location + m_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryRegion::overlaps(const MemoryRegion& r) const
|
|
||||||
{
|
|
||||||
if(r.m_location < m_location)
|
|
||||||
return r.m_location + r.m_size > m_location;
|
|
||||||
else
|
|
||||||
return r.m_location < getEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryRegion::bordersLeft(const MemoryRegion& right) const
|
|
||||||
{
|
|
||||||
return getEnd() == right.m_location;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryRegion::bordersRight(const MemoryRegion& left) const
|
|
||||||
{
|
|
||||||
return m_location == left.m_location + left.m_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryRegion::borders(const MemoryRegion& r) const
|
|
||||||
{
|
|
||||||
return bordersLeft(r) || bordersRight(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryRegion::truncateLeft(physaddr_t left)
|
|
||||||
{
|
|
||||||
m_size = getEnd() - left;
|
|
||||||
m_location = left;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryRegion::truncateRight(physaddr_t right)
|
|
||||||
{
|
|
||||||
if(right > m_location)
|
|
||||||
m_size = right - m_location;
|
|
||||||
else
|
|
||||||
m_size = 0;
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
#ifndef MEMORYBLOCK_H
|
|
||||||
#define MEMORYBLOCK_H
|
|
||||||
|
|
||||||
#include "systypes.hpp"
|
|
||||||
|
|
||||||
class MemoryRegion
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
MemoryRegion();
|
|
||||||
|
|
||||||
MemoryRegion(const MemoryRegion& copy);
|
|
||||||
|
|
||||||
MemoryRegion(physaddr_t location, size_t size, unsigned int type);
|
|
||||||
|
|
||||||
const MemoryRegion& operator=(const MemoryRegion& rhs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Tests whether this object describes the same region of memory
|
|
||||||
* as rhs, irrespective of type.
|
|
||||||
*
|
|
||||||
* @param rhs The object to compare to
|
|
||||||
* @return true if and only if the location and size of the two regions are equal
|
|
||||||
* @return false if the two regions have differing locations or differing sizes
|
|
||||||
*/
|
|
||||||
bool operator==(const MemoryRegion& rhs) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Tests whether this object describes a different region of memory
|
|
||||||
* than rhs, irrespective of type.
|
|
||||||
*
|
|
||||||
* @param rhs The object to compare to
|
|
||||||
* @return true if the two regions have differing locations or differing sizes
|
|
||||||
* @return false if and only if the location and size of the two regions are equal
|
|
||||||
*/
|
|
||||||
bool operator!=(const MemoryRegion& rhs) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief
|
|
||||||
*
|
|
||||||
* @param rhs
|
|
||||||
* @return true
|
|
||||||
* @return false
|
|
||||||
*/
|
|
||||||
bool operator<(const MemoryRegion& rhs) const;
|
|
||||||
|
|
||||||
bool operator>(const MemoryRegion& rhs) const;
|
|
||||||
|
|
||||||
bool operator<=(const MemoryRegion& rhs) const;
|
|
||||||
|
|
||||||
bool operator>=(const MemoryRegion& rhs) const;
|
|
||||||
|
|
||||||
physaddr_t getLocation() const;
|
|
||||||
|
|
||||||
size_t getSize() const;
|
|
||||||
|
|
||||||
unsigned int getType() const;
|
|
||||||
|
|
||||||
physaddr_t getEnd() const;
|
|
||||||
|
|
||||||
bool contains(const MemoryRegion& r) const;
|
|
||||||
|
|
||||||
bool contains(physaddr_t location, size_t size) const;
|
|
||||||
|
|
||||||
bool overlaps(const MemoryRegion& r) const;
|
|
||||||
|
|
||||||
bool bordersLeft(const MemoryRegion& right) const;
|
|
||||||
|
|
||||||
bool bordersRight(const MemoryRegion& left) const;
|
|
||||||
|
|
||||||
bool borders(const MemoryRegion& r) const;
|
|
||||||
|
|
||||||
void truncateLeft(physaddr_t left);
|
|
||||||
|
|
||||||
void truncateRight(physaddr_t right);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
physaddr_t m_location;
|
|
||||||
|
|
||||||
size_t m_size;
|
|
||||||
|
|
||||||
unsigned int m_type;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#ifndef MEMORYTYPE_H
|
|
||||||
#define MEMORYTYPE_H
|
|
||||||
|
|
||||||
enum class MemoryType
|
|
||||||
{
|
|
||||||
Available = 1,
|
|
||||||
Unavailable = 2,
|
|
||||||
Defective = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#include "message.hpp"
|
|
||||||
|
|
||||||
Message::Message()
|
|
||||||
{
|
|
||||||
m_sender = 0;
|
|
||||||
m_type = 0;
|
|
||||||
m_args[0] = 0;
|
|
||||||
m_args[1] = 0;
|
|
||||||
m_args[2] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Message::Message(const Message& copy)
|
|
||||||
{
|
|
||||||
m_sender = copy.m_sender;
|
|
||||||
m_type = copy.m_type;
|
|
||||||
m_args[0] = copy.m_args[0];
|
|
||||||
m_args[1] = copy.m_args[1];
|
|
||||||
m_args[2] = copy.m_args[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
Message::Message(unsigned int sender, unsigned int type,
|
|
||||||
unsigned long arg1, unsigned long arg2, unsigned long arg3)
|
|
||||||
{
|
|
||||||
m_sender = sender;
|
|
||||||
m_type = type;
|
|
||||||
m_args[0] = arg1;
|
|
||||||
m_args[1] = arg2;
|
|
||||||
m_args[2] = arg3;
|
|
||||||
}
|
|
||||||
|
|
||||||
Message& Message::operator=(const Message& rhs)
|
|
||||||
{
|
|
||||||
m_sender = rhs.m_sender;
|
|
||||||
m_type = rhs.m_type;
|
|
||||||
m_args[0] = rhs.m_args[0];
|
|
||||||
m_args[1] = rhs.m_args[1];
|
|
||||||
m_args[2] = rhs.m_args[2];
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
#ifndef MESSAGE_H
|
|
||||||
#define MESSAGE_H
|
|
||||||
|
|
||||||
struct Message
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Default constructor. Initializes all members to 0.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
Message();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Copy constructor.
|
|
||||||
*
|
|
||||||
* @param copy
|
|
||||||
*/
|
|
||||||
Message(const Message& copy);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Message object.
|
|
||||||
*
|
|
||||||
* @param sender
|
|
||||||
* @param type
|
|
||||||
* @param arg1
|
|
||||||
* @param arg2
|
|
||||||
* @param arg3
|
|
||||||
*/
|
|
||||||
Message(unsigned int sender, unsigned int type,
|
|
||||||
unsigned long arg1, unsigned long arg2, unsigned long arg3);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Copy the contents of `rhs` to this object.
|
|
||||||
*
|
|
||||||
* @param rhs
|
|
||||||
* @return Message&
|
|
||||||
*/
|
|
||||||
Message& operator=(const Message& rhs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PID of the process that generated this message.
|
|
||||||
*/
|
|
||||||
unsigned int m_sender;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Context-specific parameter which indicates to the receiver how
|
|
||||||
* the arguments are to be interpreted.
|
|
||||||
*/
|
|
||||||
unsigned int m_type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Arguments of this message. The meaning of these values depend on
|
|
||||||
* context, as well as the values of `m_sender` and `m_type`.
|
|
||||||
*/
|
|
||||||
unsigned long m_args[3];
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
31
src/mmap.hpp
31
src/mmap.hpp
@@ -1,31 +0,0 @@
|
|||||||
#ifndef MMAP_H
|
|
||||||
#define MMAP_H
|
|
||||||
|
|
||||||
#include "pageallocator.hpp"
|
|
||||||
|
|
||||||
#define MMAP_RW 0x01
|
|
||||||
#define MMAP_EXEC 0x02
|
|
||||||
#define MMAP_SHARED 0x04
|
|
||||||
|
|
||||||
namespace kernelns
|
|
||||||
{
|
|
||||||
|
|
||||||
int mmap(void* start, size_t length, int flags);
|
|
||||||
|
|
||||||
int mmap(void* start, physaddr_t p_start, size_t length, int flags);
|
|
||||||
|
|
||||||
int mapPage(void* start, physaddr_t p_start, int flags);
|
|
||||||
|
|
||||||
int munmap(void* start, size_t length);
|
|
||||||
|
|
||||||
bool isMapped(void* addr);
|
|
||||||
|
|
||||||
physaddr_t getPhysicalAddress(void* addr);
|
|
||||||
|
|
||||||
int createAddressSpace(void* table);
|
|
||||||
|
|
||||||
int loadAddressSpace(physaddr_t table);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
#include "module.hpp"
|
|
||||||
#include "util.hpp"
|
|
||||||
|
|
||||||
using namespace kernelns;
|
|
||||||
|
|
||||||
Module::Module()
|
|
||||||
{
|
|
||||||
m_start = 0;
|
|
||||||
m_end = 0;
|
|
||||||
m_command = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Module::Module(physaddr_t start, physaddr_t end, const char* command)
|
|
||||||
{
|
|
||||||
m_start = start;
|
|
||||||
m_end = end;
|
|
||||||
m_command = new char[strlen(command) + 1];
|
|
||||||
strcpy(m_command, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
Module::~Module()
|
|
||||||
{
|
|
||||||
delete[] m_command;
|
|
||||||
}
|
|
||||||
|
|
||||||
physaddr_t Module::getStart() const
|
|
||||||
{
|
|
||||||
return m_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
physaddr_t Module::getEnd() const
|
|
||||||
{
|
|
||||||
return m_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* Module::getCommand() const
|
|
||||||
{
|
|
||||||
return m_command;
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
#ifndef ELF_H
|
|
||||||
#define ELF_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "systypes.hpp"
|
|
||||||
|
|
||||||
namespace kernelns
|
|
||||||
{
|
|
||||||
|
|
||||||
class Module
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
Module();
|
|
||||||
|
|
||||||
Module(physaddr_t start, physaddr_t end, const char* command);
|
|
||||||
|
|
||||||
~Module();
|
|
||||||
|
|
||||||
physaddr_t getStart() const;
|
|
||||||
|
|
||||||
physaddr_t getEnd() const;
|
|
||||||
|
|
||||||
const char* getCommand() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
physaddr_t m_start;
|
|
||||||
|
|
||||||
physaddr_t m_end;
|
|
||||||
|
|
||||||
char* m_command;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
52
src/pageallocator.c
Normal file
52
src/pageallocator.c
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#include "pageallocator.h"
|
||||||
|
#include "types/status.h"
|
||||||
|
|
||||||
|
physaddr_t reserve_page(struct page_stack_t *stack)
|
||||||
|
{
|
||||||
|
if(stack->stack_pointer < stack->base_pointer)
|
||||||
|
{
|
||||||
|
physaddr_t frame = *stack->stack_pointer;
|
||||||
|
*stack->stack_pointer = (physaddr_t) 0;
|
||||||
|
stack->stack_pointer++;
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
return S_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
int free_page(struct page_stack_t *stack, physaddr_t location)
|
||||||
|
{
|
||||||
|
if(stack->stack_pointer > stack->limit_pointer)
|
||||||
|
{
|
||||||
|
stack->stack_pointer--;
|
||||||
|
*stack->stack_pointer = location;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
return S_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t free_page_count(struct page_stack_t *stack)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
stack->total_pages = 0;
|
||||||
|
for(int i = 0; i < map->size; i++)
|
||||||
|
{
|
||||||
|
if(map->array[i].type != M_AVAILABLE)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
size_t location = (map->array[i].location + page_size - 1) & ~(page_size - 1);
|
||||||
|
while(location + page_size <= map->array[i].location + map->array[i].size)
|
||||||
|
{
|
||||||
|
if(free_page(stack, location) != S_OK)
|
||||||
|
{
|
||||||
|
return S_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
stack->total_pages++;
|
||||||
|
location += page_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
#ifndef __MEMORYALLOCATOR_H_
|
|
||||||
#define __MEMORYALLOCATOR_H_
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "systypes.hpp"
|
|
||||||
|
|
||||||
namespace kernelns
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for a physical memory allocator.
|
|
||||||
*/
|
|
||||||
class PageAllocator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocate a single page, returning its physical address. Upon failure,
|
|
||||||
* returns an error code such that the least signifigant byte is nonzero.
|
|
||||||
*/
|
|
||||||
virtual physaddr_t next() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees a single page that has previously been allocated.
|
|
||||||
*/
|
|
||||||
virtual void free(physaddr_t location) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns the total number of free blocks of memory.
|
|
||||||
*/
|
|
||||||
virtual size_t freeBlocks() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns the total number of blocks managed by this memory
|
|
||||||
* allocator.
|
|
||||||
*/
|
|
||||||
virtual size_t getMemorySize() const = 0;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
#include "pageallocatorstack.hpp"
|
|
||||||
#include "memorytype.hpp"
|
|
||||||
|
|
||||||
using namespace kernelns;
|
|
||||||
|
|
||||||
PageAllocatorStack::PageAllocatorStack(physaddr_t *stackBase, physaddr_t *stackTop, size_t frameSize, const MemoryMap& memoryMap)
|
|
||||||
{
|
|
||||||
m_base = stackBase;
|
|
||||||
m_top = stackTop;
|
|
||||||
m_stack = m_base;
|
|
||||||
for(int i = 0; i < memoryMap.size(); i++)
|
|
||||||
{
|
|
||||||
if((MemoryType) memoryMap[i].getType() == MemoryType::Available)
|
|
||||||
{
|
|
||||||
for(int j = 0; j < memoryMap[i].getSize() / frameSize; j++)
|
|
||||||
{
|
|
||||||
free(memoryMap[i].getLocation() + j * frameSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
physaddr_t PageAllocatorStack::next()
|
|
||||||
{
|
|
||||||
if(m_stack < m_base)
|
|
||||||
{
|
|
||||||
physaddr_t frame = *m_stack;
|
|
||||||
*m_stack = (physaddr_t) 0;
|
|
||||||
m_stack++;
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
return (physaddr_t) -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PageAllocatorStack::free(physaddr_t location)
|
|
||||||
{
|
|
||||||
if(m_stack > m_top)
|
|
||||||
{
|
|
||||||
m_stack--;
|
|
||||||
*m_stack = location;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t PageAllocatorStack::freeBlocks() const
|
|
||||||
{
|
|
||||||
return m_base - m_stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t PageAllocatorStack::getMemorySize() const
|
|
||||||
{
|
|
||||||
return m_totalSize;
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#ifndef PAGEALLOCATORSTACK_H
|
|
||||||
#define PAGEALLOCATORSTACK_H
|
|
||||||
|
|
||||||
#include "pageallocator.hpp"
|
|
||||||
#include "memorymap.hpp"
|
|
||||||
|
|
||||||
namespace kernelns
|
|
||||||
{
|
|
||||||
|
|
||||||
class PageAllocatorStack : public PageAllocator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
PageAllocatorStack(physaddr_t *stackBase, physaddr_t *stackTop, size_t frameSize, const MemoryMap& memoryMap);
|
|
||||||
|
|
||||||
virtual physaddr_t next();
|
|
||||||
|
|
||||||
virtual void free(physaddr_t location);
|
|
||||||
|
|
||||||
virtual size_t freeBlocks() const;
|
|
||||||
|
|
||||||
virtual size_t getMemorySize() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
size_t m_totalSize;
|
|
||||||
|
|
||||||
physaddr_t *m_stack, *m_base, *m_top;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
67
src/priorityqueue.c
Normal file
67
src/priorityqueue.c
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#include "priorityqueue.h"
|
||||||
|
#include "types/status.h"
|
||||||
|
|
||||||
|
void heapify(struct priority_queue_t *queue, size_t i)
|
||||||
|
{
|
||||||
|
if(i * 2 + 1 >= queue->size)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(queue->heap[i * 2 + 1]->priority <= queue->heap[i]->priority
|
||||||
|
&& queue->heap[i * 2 + 1]->priority <= queue->heap[i * 2 + 2]->priority)
|
||||||
|
{
|
||||||
|
struct process_t *buffer = queue->heap[i];
|
||||||
|
queue->heap[i] = queue->heap[i * 2 + 1];
|
||||||
|
queue->heap[i * 2 + 1] = buffer;
|
||||||
|
heapify(queue, i * 2 + 1);
|
||||||
|
}
|
||||||
|
else if(queue->heap[i * 2 + 2]->priority <= queue->heap[i]->priority
|
||||||
|
&& queue->heap[i * 2 + 2]->priority <= queue->heap[i * 2 + 1]->priority)
|
||||||
|
{
|
||||||
|
struct process_t *buffer = queue->heap[i];
|
||||||
|
queue->heap[i] = queue->heap[i * 2 + 2];
|
||||||
|
queue->heap[i * 2 + 2] = buffer;
|
||||||
|
heapify(queue, i * 2 + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct process_t *extract_min(struct priority_queue_t *queue)
|
||||||
|
{
|
||||||
|
if(queue->size == 0)
|
||||||
|
return NULL;
|
||||||
|
queue->size--;
|
||||||
|
struct process_t *p = queue->heap[0];
|
||||||
|
queue->heap[0] = queue->heap[queue->size];
|
||||||
|
heapify(queue, 0);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int insert(struct priority_queue_t *queue, struct process_t *process)
|
||||||
|
{
|
||||||
|
if(queue->size == queue->capacity)
|
||||||
|
return S_OUT_OF_MEMORY;
|
||||||
|
size_t i = queue->size;
|
||||||
|
queue->size++;
|
||||||
|
while(i > 0 && queue->heap[(i - 1) / 2]->priority > process->priority)
|
||||||
|
{
|
||||||
|
queue->heap[i] = queue->heap[(i - 1) / 2];
|
||||||
|
i = (i - 1) / 2;
|
||||||
|
}
|
||||||
|
queue->heap[i] = process;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int remove(struct priority_queue_t *queue, struct process_t *process)
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < queue->size; i++)
|
||||||
|
{
|
||||||
|
if(queue->heap[i] == process)
|
||||||
|
{
|
||||||
|
queue->size--;
|
||||||
|
queue->heap[i] = queue->heap[queue->size];
|
||||||
|
heapify(queue, i);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return S_OUT_OF_BOUNDS;
|
||||||
|
}
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
#ifndef PROCESS_H
|
|
||||||
#define PROCESS_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include "message.hpp"
|
|
||||||
|
|
||||||
namespace kernelns
|
|
||||||
{
|
|
||||||
|
|
||||||
class Process
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
size_t priority;
|
|
||||||
|
|
||||||
void* stack;
|
|
||||||
|
|
||||||
Process();
|
|
||||||
|
|
||||||
unsigned int getID() const;
|
|
||||||
|
|
||||||
bool map(void* location, size_t size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief If the specified region is mapped and does not overlap a shared
|
|
||||||
* or private block, or the kernel, removes that region from the process's
|
|
||||||
* internal memory map. If the specified region overlaps an unmapped region,
|
|
||||||
* a shared or private block, or the kernel, the object goes unmodified.
|
|
||||||
* This method does not affect the page tables in any way, only the process's
|
|
||||||
* internal bookkeeping.
|
|
||||||
*
|
|
||||||
* @param location
|
|
||||||
* @param size
|
|
||||||
* @return true if the memory map was sucessfully updated
|
|
||||||
* @return false if the memory map was not modified
|
|
||||||
*/
|
|
||||||
bool unmap(void* location, size_t size);
|
|
||||||
|
|
||||||
bool hasSharedBlock(unsigned int blockID) const;
|
|
||||||
|
|
||||||
bool hasPhysicalBlock(unsigned int blockID) const;
|
|
||||||
|
|
||||||
void pushMessage(Message* message);
|
|
||||||
|
|
||||||
Message* popMessage();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#ifndef SHAREDBLOCK_H
|
|
||||||
#define SHAREDBLOCK_H
|
|
||||||
|
|
||||||
#include "memoryregion.hpp"
|
|
||||||
|
|
||||||
class SharedBlock : public MemoryRegion
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
unsigned int getFlags() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
unsigned int m_flags;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
100
src/stdio.c
Normal file
100
src/stdio.c
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
#include "stdio.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
enum format_flags_t
|
||||||
|
{
|
||||||
|
FORMAT_PADDING = '0',
|
||||||
|
FORMAT_WIDTH = '*',
|
||||||
|
|
||||||
|
FORMAT_SIGNED_DECIMAL = 'i',
|
||||||
|
FORMAT_UNSIGNED_DECIMAL = 'u',
|
||||||
|
FORMAT_UNSIGNED_OCTAL = 'o',
|
||||||
|
FORMAT_UNSIGNED_HEX = 'x',
|
||||||
|
FORMAT_STRING = 's',
|
||||||
|
FORMAT_COUNT = 'n',
|
||||||
|
FORMAT_PERCENT = '%'
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
char *itoa(unsigned int n, unsigned int base, unsigned int width)
|
||||||
|
{
|
||||||
|
if (base < 2 || base > 16)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
static const char *digits = "0123456789abcdef";
|
||||||
|
static char buffer[65];
|
||||||
|
char *s = &buffer[64];
|
||||||
|
unsigned int count = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*--s = digits[n % base];
|
||||||
|
n /= base;
|
||||||
|
count++;
|
||||||
|
} while (count < width || n != 0);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int printf(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list valist;
|
||||||
|
va_start(valist, format);
|
||||||
|
while (*format)
|
||||||
|
{
|
||||||
|
if (*format == '%')
|
||||||
|
{
|
||||||
|
size_t width = 0;
|
||||||
|
bool padding = false;
|
||||||
|
switch (*++format)
|
||||||
|
{
|
||||||
|
case FORMAT_PADDING:
|
||||||
|
padding = true;
|
||||||
|
format++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while (*format >= '0' && *format <= '9')
|
||||||
|
{
|
||||||
|
width = (width * 10) + *format - '0';
|
||||||
|
format++;
|
||||||
|
}
|
||||||
|
switch (*format)
|
||||||
|
{
|
||||||
|
case FORMAT_SIGNED_DECIMAL:;
|
||||||
|
int n = va_arg(valist, int);
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
putchar('-');
|
||||||
|
n *= -1;
|
||||||
|
}
|
||||||
|
puts(itoa((unsigned int)n, 10, width));
|
||||||
|
break;
|
||||||
|
case FORMAT_UNSIGNED_DECIMAL:
|
||||||
|
puts(itoa(va_arg(valist, unsigned int), 10, width));
|
||||||
|
break;
|
||||||
|
case FORMAT_UNSIGNED_OCTAL:
|
||||||
|
puts(itoa(va_arg(valist, unsigned int), 8, width));
|
||||||
|
case FORMAT_UNSIGNED_HEX:
|
||||||
|
puts(itoa(va_arg(valist, unsigned int), 16, width));
|
||||||
|
break;
|
||||||
|
case FORMAT_STRING:
|
||||||
|
puts(va_arg(valist, const char *));
|
||||||
|
break;
|
||||||
|
case FORMAT_PERCENT:
|
||||||
|
putchar('%');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
putchar(*format);
|
||||||
|
}
|
||||||
|
format++;
|
||||||
|
}
|
||||||
|
va_end(valist);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sprintf(char *str, const char *format, ...)
|
||||||
|
{
|
||||||
|
}
|
||||||
110
src/string.c
Normal file
110
src/string.c
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#include "string.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void *memcpy(void *destination, const void *source, size_t num)
|
||||||
|
{
|
||||||
|
if (num > 0)
|
||||||
|
{
|
||||||
|
const uint8_t *src = (const uint8_t *)source;
|
||||||
|
uint8_t *dest = (uint8_t *)destination;
|
||||||
|
for (size_t i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
dest[i] = src[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memmove(void *destination, const void *source, size_t num)
|
||||||
|
{
|
||||||
|
if (num > 0)
|
||||||
|
{
|
||||||
|
if (((size_t)destination) < ((size_t)source) || ((size_t)destination) >= (((size_t)source)) + num)
|
||||||
|
{
|
||||||
|
return memcpy(destination, source, num);
|
||||||
|
}
|
||||||
|
else if (destination != source)
|
||||||
|
{
|
||||||
|
size_t i = num - 1;
|
||||||
|
const uint8_t *src = (const uint8_t *)source;
|
||||||
|
uint8_t *dest = (uint8_t *)destination;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
dest[i] = src[i];
|
||||||
|
i--;
|
||||||
|
} while (i != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
int memcmp(const void *ptr1, const void *ptr2, size_t num)
|
||||||
|
{
|
||||||
|
const uint8_t *a = (const uint8_t *)ptr1;
|
||||||
|
const uint8_t *b = (const uint8_t *)ptr2;
|
||||||
|
for (size_t i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
if (a[i] < b[i])
|
||||||
|
return -1;
|
||||||
|
else if (a[i] > b[i])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memset(void *ptr, int value, size_t num)
|
||||||
|
{
|
||||||
|
uint8_t *dest = (uint8_t *)ptr;
|
||||||
|
uint8_t v = (uint8_t)value;
|
||||||
|
for (size_t i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
dest[i] = v;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int strlen(const char *str)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strcpy(char *destination, const char *source)
|
||||||
|
{
|
||||||
|
int sourceLen = strlen(source);
|
||||||
|
if ((destination <= source) || (destination > (source + sourceLen)))
|
||||||
|
{
|
||||||
|
char *d = destination;
|
||||||
|
const char *s = source;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
*d = *s;
|
||||||
|
if (*s == '\0')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
d++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *d = destination + sourceLen;
|
||||||
|
const char *s = source + sourceLen;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*d = *s;
|
||||||
|
d--;
|
||||||
|
s--;
|
||||||
|
} while (d > destination);
|
||||||
|
}
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
#include "syscalls.hpp"
|
|
||||||
#include "kernel.hpp"
|
|
||||||
#include "memorytype.hpp"
|
|
||||||
|
|
||||||
int mmap(void* location, size_t length, int flags)
|
|
||||||
{
|
|
||||||
if(kernel.getActiveProcess().map(location, length))
|
|
||||||
{
|
|
||||||
if(kernel.allocateRegion(location, length, flags))
|
|
||||||
return 0;
|
|
||||||
else if(kernel.getActiveProcess().unmap(location, length))
|
|
||||||
return 1;
|
|
||||||
kernel.terminateActiveProcess();
|
|
||||||
}
|
|
||||||
return kernel.allocateRegion(location, length, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
int munmap(void* location, size_t length)
|
|
||||||
{
|
|
||||||
if(kernel.getActiveProcess().unmap(location, length))
|
|
||||||
{
|
|
||||||
kernel.freeRegion(location, length);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int createSharedBlock(void* location, size_t length, int flags)
|
|
||||||
{
|
|
||||||
unsigned int blockID = kernel.createSharedBlock(length, flags);
|
|
||||||
if(blockID > 0)
|
|
||||||
{
|
|
||||||
const SharedBlock& block = kernel.getSharedBlock(blockID);
|
|
||||||
kernel.mapRegion(location, block.getLocation(), length, flags);
|
|
||||||
// TODO: add block to current process
|
|
||||||
// TODO: perform safety checks
|
|
||||||
}
|
|
||||||
return blockID;
|
|
||||||
}
|
|
||||||
|
|
||||||
int aquireSharedBlock(void* location, unsigned int id)
|
|
||||||
{
|
|
||||||
const SharedBlock& block = kernel.getSharedBlock(id);
|
|
||||||
kernel.mapRegion(location, block.getLocation(), block.getSize(), block.getFlags());
|
|
||||||
// TODO: (somehow) handle invalid ids -- possibly hard while using references
|
|
||||||
// TODO: add block to current process
|
|
||||||
// TODO: perform safety checks
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int releaseSharedBlock(int id)
|
|
||||||
{
|
|
||||||
// (0) Check that process actually posesses block
|
|
||||||
// (1) Get virtual address of block
|
|
||||||
// (2) Unmap block
|
|
||||||
// (3) Delete block if no one posesses it anymore
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int querySharedBlock(void* info, int id)
|
|
||||||
{
|
|
||||||
// TODO: define struct for block info
|
|
||||||
}
|
|
||||||
|
|
||||||
int aquirePhysicalBlock(void* location, physaddr_t physicalAddress, size_t length)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int releasePhysicalBlock(int id)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sendMessage(unsigned int recipient, const Message* message)
|
|
||||||
{
|
|
||||||
Message* copy = new Message(*message);
|
|
||||||
copy->m_sender = kernel.getActiveProcess().getID();
|
|
||||||
kernel.getProcess(recipient).pushMessage(copy);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int receiveMessage(Message* buffer)
|
|
||||||
{
|
|
||||||
if(buffer == nullptr)
|
|
||||||
return 1;
|
|
||||||
Message* message = kernel.getActiveProcess().popMessage();
|
|
||||||
if(message == nullptr)
|
|
||||||
return 1;
|
|
||||||
*buffer = *message;
|
|
||||||
delete message;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#ifndef SYSCALLS_H
|
|
||||||
#define SYSCALLS_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "systypes.hpp"
|
|
||||||
#include "message.hpp"
|
|
||||||
|
|
||||||
int mmap(void* location, size_t length, int flags);
|
|
||||||
|
|
||||||
int munmap(void* location, size_t length);
|
|
||||||
|
|
||||||
unsigned int createSharedBlock(void* location, size_t length, int flags);
|
|
||||||
|
|
||||||
int aquireSharedBlock(void* location, unsigned int id);
|
|
||||||
|
|
||||||
int releaseSharedBlock(int id);
|
|
||||||
|
|
||||||
int querySharedBlock(void* info, int id);
|
|
||||||
|
|
||||||
int aquirePhysicalBlock(void* location, physaddr_t physicalAddress, size_t length);
|
|
||||||
|
|
||||||
int releasePhysicalBlock(int id);
|
|
||||||
|
|
||||||
int sendMessage(unsigned int recipient, const Message* message);
|
|
||||||
|
|
||||||
int receiveMessage(Message* buffer);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#ifndef SYSTYPES_H
|
|
||||||
#define SYSTYPES_H
|
|
||||||
|
|
||||||
#include "types/physaddr.h"
|
|
||||||
#include "types/status.h"
|
|
||||||
#include "types/handle.h"
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#ifndef HANDLE_H
|
|
||||||
#define HANDLE_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef uint64_t handle_t;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#ifndef STATUS_H
|
|
||||||
#define STATUS_H
|
|
||||||
|
|
||||||
enum class Status
|
|
||||||
{
|
|
||||||
OK = 0,
|
|
||||||
BadArgument,
|
|
||||||
NoMemory
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
165
src/util.cpp
165
src/util.cpp
@@ -1,165 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "util.hpp"
|
|
||||||
#include "kernel.hpp"
|
|
||||||
|
|
||||||
void* memcpy(void* destination, const void* source, size_t num)
|
|
||||||
{
|
|
||||||
if(num > 0)
|
|
||||||
{
|
|
||||||
const uint8_t* src = (const uint8_t*) source;
|
|
||||||
uint8_t* dest = (uint8_t*) destination;
|
|
||||||
for(size_t i = 0; i < num; i++)
|
|
||||||
{
|
|
||||||
dest[i] = src[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* memmove(void* destination, const void* source, size_t num)
|
|
||||||
{
|
|
||||||
if(num > 0)
|
|
||||||
{
|
|
||||||
if(((size_t) destination) < ((size_t) source) || ((size_t) destination) >= (((size_t) source)) + num)
|
|
||||||
{
|
|
||||||
return memcpy(destination, source, num);
|
|
||||||
}
|
|
||||||
else if(destination != source)
|
|
||||||
{
|
|
||||||
size_t i = num - 1;
|
|
||||||
const uint8_t* src = (const uint8_t*) source;
|
|
||||||
uint8_t* dest = (uint8_t*) destination;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
dest[i] = src[i];
|
|
||||||
i--;
|
|
||||||
} while(i != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
int memcmp(const void* ptr1, const void* ptr2, size_t num)
|
|
||||||
{
|
|
||||||
const uint8_t* a = (const uint8_t*) ptr1;
|
|
||||||
const uint8_t* b = (const uint8_t*) ptr2;
|
|
||||||
for(size_t i = 0; i < num; i++)
|
|
||||||
{
|
|
||||||
if(a[i] < b[i])
|
|
||||||
return -1;
|
|
||||||
else if(a[i] > b[i])
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* memset(void* ptr, int value, size_t num)
|
|
||||||
{
|
|
||||||
uint8_t* dest = (uint8_t*) ptr;
|
|
||||||
uint8_t v = (uint8_t) value;
|
|
||||||
for(size_t i = 0; i < num; i++)
|
|
||||||
{
|
|
||||||
dest[i] = v;
|
|
||||||
}
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int strlen(const char* str)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
while(str[i] != '\0')
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* strcpy(char* destination, const char* source)
|
|
||||||
{
|
|
||||||
int sourceLen = strlen(source);
|
|
||||||
if((destination <= source) || (destination > (source + sourceLen)))
|
|
||||||
{
|
|
||||||
char* d = destination;
|
|
||||||
const char* s = source;
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
*d = *s;
|
|
||||||
if(*s == '\0')
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s++;
|
|
||||||
d++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char* d = destination + sourceLen;
|
|
||||||
const char* s = source + sourceLen;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
*d = *s;
|
|
||||||
d--;
|
|
||||||
s--;
|
|
||||||
} while(d > destination);
|
|
||||||
}
|
|
||||||
return destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* malloc(size_t size)
|
|
||||||
{
|
|
||||||
return kernel.malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* calloc(size_t count, size_t size)
|
|
||||||
{
|
|
||||||
void* ptr = malloc(count * size);
|
|
||||||
if(ptr != nullptr)
|
|
||||||
memset(malloc(count * size), 0, count * size);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* realloc(void* ptr, size_t size)
|
|
||||||
{
|
|
||||||
void* n = kernel.malloc(size);
|
|
||||||
if(n != nullptr)
|
|
||||||
{
|
|
||||||
memmove(n, ptr, size);
|
|
||||||
free(ptr);
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
void free(void* p)
|
|
||||||
{
|
|
||||||
kernel.free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __cxa_pure_virtual()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void* operator new(size_t size)
|
|
||||||
{
|
|
||||||
return malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* operator new[](size_t size)
|
|
||||||
{
|
|
||||||
return malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator delete(void* p)
|
|
||||||
{
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator delete[](void* p)
|
|
||||||
{
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
56
src/util.hpp
56
src/util.hpp
@@ -1,56 +0,0 @@
|
|||||||
#ifndef UTIL_H
|
|
||||||
#define UTIL_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
extern "C" void* memcpy(void* destination, const void* source, size_t num);
|
|
||||||
|
|
||||||
extern "C" void* memmove(void* destination, const void* source, size_t num);
|
|
||||||
|
|
||||||
extern "C" int memcmp(const void* ptr1, const void* ptr2, size_t num);
|
|
||||||
|
|
||||||
extern "C" void* memset(void* ptr, int value, size_t num);
|
|
||||||
|
|
||||||
extern "C" int strlen(const char* str);
|
|
||||||
|
|
||||||
extern "C" char* strcpy(char* destination, const char* source);
|
|
||||||
|
|
||||||
extern "C" void* malloc(size_t size);
|
|
||||||
|
|
||||||
extern "C" void* calloc(size_t count, size_t size);
|
|
||||||
|
|
||||||
extern "C" void* realloc(void* ptr, size_t size);
|
|
||||||
|
|
||||||
extern "C" void free(void* p);
|
|
||||||
|
|
||||||
extern "C" void __cxa_pure_virtual();
|
|
||||||
|
|
||||||
void* operator new(size_t size);
|
|
||||||
|
|
||||||
void* operator new[](size_t size);
|
|
||||||
|
|
||||||
void operator delete(void* p);
|
|
||||||
|
|
||||||
void operator delete[](void* p);
|
|
||||||
|
|
||||||
inline void* operator new(size_t, void *p)
|
|
||||||
{
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void* operator new[](size_t, void *p)
|
|
||||||
{
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void operator delete(void *, void *)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void operator delete[](void *, void *)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
35
src/x86/apic.c
Normal file
35
src/x86/apic.c
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#include "apic.h"
|
||||||
|
|
||||||
|
void apic_enable()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void apic_eoi()
|
||||||
|
{
|
||||||
|
apic_registers->eoi.value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void apic_send_ipi(
|
||||||
|
uint32_t vector,
|
||||||
|
enum apic_delivery_mode_t delivery_mode,
|
||||||
|
enum apic_destination_mode_t destination_mode,
|
||||||
|
enum apic_level_t level,
|
||||||
|
enum apic_trigger_mode_t trigger_mode,
|
||||||
|
enum apic_destination_shorthand_t shorthand,
|
||||||
|
uint32_t destination)
|
||||||
|
{
|
||||||
|
struct apic_icr_t value = {
|
||||||
|
.vector = vector,
|
||||||
|
.delivery_mode = delivery_mode,
|
||||||
|
.destination_mode = destination_mode,
|
||||||
|
.level = level,
|
||||||
|
.trigger_mode = trigger_mode,
|
||||||
|
.destination_shorthand = shorthand,
|
||||||
|
.destination = destination
|
||||||
|
};
|
||||||
|
uint32_t *value_addr = (uint32_t*) &value;
|
||||||
|
uint32_t *icr_addr = (uint32_t*)&apic_registers->interrput_command;
|
||||||
|
icr_addr[4] = value_addr[4];
|
||||||
|
icr_addr[0] = value_addr[0];
|
||||||
|
}
|
||||||
156
src/x86/apic.h
Normal file
156
src/x86/apic.h
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum apic_delivery_mode_t
|
||||||
|
{
|
||||||
|
APIC_DELIVERY_MODE_FIXED = 0b000,
|
||||||
|
APIC_DELIVERY_MODE_LOWEST_PRIORITY = 0b001,
|
||||||
|
APIC_DELIVERY_MODE_SMI = 0b010,
|
||||||
|
APIC_DELIVERY_MODE_NMI = 0b100,
|
||||||
|
APIC_DELIVERY_MODE_INIT = 0b101,
|
||||||
|
APIC_DELIVERY_MODE_SIPI = 0b110,
|
||||||
|
APIV_DELIVERY_MODE_EXTINIT = 0b111
|
||||||
|
};
|
||||||
|
|
||||||
|
enum apic_destination_mode_t
|
||||||
|
{
|
||||||
|
APIC_DESTINATION_MODE_PHYSICAL = 0,
|
||||||
|
APIC_DESTINATION_MODE_LOGICAL = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum apic_level_t
|
||||||
|
{
|
||||||
|
APIC_LEVEL_DEASSERT = 0,
|
||||||
|
APIC_LEVEL_ASSERT = 1
|
||||||
|
};
|
||||||
|
enum apic_trigger_mode_t
|
||||||
|
{
|
||||||
|
APIC_TRIGGER_MODE_EDGE = 0,
|
||||||
|
APIC_TRIGGER_MODE_LEVEL = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum apic_destination_shorthand_t
|
||||||
|
{
|
||||||
|
APIC_DEST_SHORTHAND_NONE = 0,
|
||||||
|
APIC_DEST_SHORTHAND_SELF = 1,
|
||||||
|
APIC_DEST_SHORTHAND_ALL = 2,
|
||||||
|
APIC_DEST_SHORTHAND_OTHERS = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum apic_divide_mode_t
|
||||||
|
{
|
||||||
|
APIC_DIVIDE_1 = 0b1011,
|
||||||
|
APIC_DIVIDE_2 = 0b0000,
|
||||||
|
APIC_DIVIDE_4 = 0b0001,
|
||||||
|
APIC_DIVIDE_8 = 0b0010,
|
||||||
|
APIC_DIVIDE_16 = 0b0011,
|
||||||
|
APIC_DIVIDE_32 = 0b1000,
|
||||||
|
APIC_DIVIDE_64 = 0b1001,
|
||||||
|
APIC_DIVIDE_128 = 0b1011
|
||||||
|
};
|
||||||
|
|
||||||
|
enum apic_timer_mode_t
|
||||||
|
{
|
||||||
|
APIC_TIMER_ONESHOT = 0,
|
||||||
|
APIC_TIMER_PERIODIC = 1,
|
||||||
|
APIC_TIMER_TSCDEADLINE = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
struct apic_register_t
|
||||||
|
{
|
||||||
|
uint32_t value;
|
||||||
|
uint32_t padding[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct apic_lapic_version_t
|
||||||
|
{
|
||||||
|
uint32_t version : 8;
|
||||||
|
uint32_t reserved_1 : 8;
|
||||||
|
uint32_t max_lvt_entry : 8;
|
||||||
|
uint32_t suppress_eoi_broadcast : 1;
|
||||||
|
uint32_t reserved_2 : 7;
|
||||||
|
uint32_t padding[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct apic_lvt_t
|
||||||
|
{
|
||||||
|
uint32_t vector: 8;
|
||||||
|
uint32_t delivery_mode : 3;
|
||||||
|
uint32_t reserved_1 : 1;
|
||||||
|
uint32_t delivery_status : 1;
|
||||||
|
uint32_t pin_polarity : 1;
|
||||||
|
uint32_t remote_irr : 1;
|
||||||
|
uint32_t trigger_mode : 1;
|
||||||
|
uint32_t mask : 1;
|
||||||
|
uint32_t timer_mode : 2;
|
||||||
|
uint32_t reserved_2 : 13;
|
||||||
|
uint32_t padding[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct apic_icr_t
|
||||||
|
{
|
||||||
|
uint32_t vector : 8;
|
||||||
|
uint32_t delivery_mode : 3;
|
||||||
|
uint32_t destination_mode : 1;
|
||||||
|
uint32_t delivery_status : 1;
|
||||||
|
uint32_t reserved_1 : 1;
|
||||||
|
uint32_t level : 1;
|
||||||
|
uint32_t trigger_mode : 1;
|
||||||
|
uint32_t reserved_2 : 2;
|
||||||
|
uint32_t destination_shorthand : 2;
|
||||||
|
uint32_t reserved_3 : 12;
|
||||||
|
uint32_t padding_1[3];
|
||||||
|
uint32_t reserved : 24;
|
||||||
|
uint32_t destination : 8;
|
||||||
|
uint32_t padding_2[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct apic_registers_t
|
||||||
|
{
|
||||||
|
struct apic_register_t reserved_1[2];
|
||||||
|
struct apic_register_t lapic_id;
|
||||||
|
struct apic_lapic_version_t lapic_version;
|
||||||
|
struct apic_register_t reserved_2[4];
|
||||||
|
struct apic_register_t task_priority;
|
||||||
|
struct apic_register_t arbitration_priority;
|
||||||
|
struct apic_register_t processor_priority;
|
||||||
|
struct apic_register_t eoi;
|
||||||
|
struct apic_register_t remote_read;
|
||||||
|
struct apic_register_t logical_destination;
|
||||||
|
struct apic_register_t destination_format;
|
||||||
|
struct apic_register_t spurious_iv;
|
||||||
|
struct apic_register_t in_service[8];
|
||||||
|
struct apic_register_t trigger_mode[8];
|
||||||
|
struct apic_register_t interrupt_request[8];
|
||||||
|
struct apic_register_t error_status;
|
||||||
|
struct apic_register_t reserved_3[6];
|
||||||
|
struct apic_lvt_t lvt_cmci;
|
||||||
|
struct apic_icr_t interrput_command;
|
||||||
|
struct apic_lvt_t lvt_timer;
|
||||||
|
struct apic_lvt_t lvt_thermal_sensor;
|
||||||
|
struct apic_lvt_t lvt_performance_counters;
|
||||||
|
struct apic_lvt_t lvt_lint0;
|
||||||
|
struct apic_lvt_t lvt_lint1;
|
||||||
|
struct apic_lvt_t lvt_error;
|
||||||
|
struct apic_register_t initial_count;
|
||||||
|
struct apic_register_t current_count;
|
||||||
|
struct apic_register_t reserved_4[4];
|
||||||
|
struct apic_register_t divide_config;
|
||||||
|
struct apic_register_t reserved_5;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct apic_registers_t volatile *apic_registers;
|
||||||
|
|
||||||
|
void apic_enable();
|
||||||
|
|
||||||
|
void apic_eoi();
|
||||||
|
|
||||||
|
void apic_send_ipi(
|
||||||
|
uint32_t vector,
|
||||||
|
enum apic_delivery_mode_t delivery_mode,
|
||||||
|
enum apic_destination_mode_t destination_mode,
|
||||||
|
enum apic_level_t level,
|
||||||
|
enum apic_trigger_mode_t trigger_mode,
|
||||||
|
enum apic_destination_shorthand_t shorthand,
|
||||||
|
uint32_t destination);
|
||||||
@@ -124,7 +124,7 @@ _tempPgDir:
|
|||||||
_tempIdentityMap:
|
_tempIdentityMap:
|
||||||
.skip 4096
|
.skip 4096
|
||||||
_tempPgTable:
|
_tempPgTable:
|
||||||
.skip 8192
|
.skip 4096
|
||||||
|
|
||||||
_bootCmdLine:
|
_bootCmdLine:
|
||||||
.skip 64
|
.skip 64
|
||||||
@@ -143,6 +143,9 @@ memory_map:
|
|||||||
.global _start
|
.global _start
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
_start:
|
_start:
|
||||||
|
|
||||||
|
cli
|
||||||
|
|
||||||
# This platform reqires a Multiboot2 bootloader.
|
# This platform reqires a Multiboot2 bootloader.
|
||||||
cmp $0x36d76289, %eax
|
cmp $0x36d76289, %eax
|
||||||
jne .err
|
jne .err
|
||||||
@@ -212,12 +215,6 @@ _start:
|
|||||||
push %ebx
|
push %ebx
|
||||||
call initialize
|
call initialize
|
||||||
|
|
||||||
# mov $_bootCmdLine, %eax
|
|
||||||
# push %eax
|
|
||||||
|
|
||||||
# Call main function
|
|
||||||
# call main
|
|
||||||
|
|
||||||
.err:
|
.err:
|
||||||
cli
|
cli
|
||||||
2: hlt
|
2: hlt
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
#include "multiboot2.hpp"
|
|
||||||
#include "tty.hpp"
|
|
||||||
#include "../mmap.hpp"
|
|
||||||
#include "../util.hpp"
|
|
||||||
#include "../memorytype.hpp"
|
|
||||||
|
|
||||||
using namespace kernelns;
|
|
||||||
|
|
||||||
extern int _kernelEnd;
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
int initialize(void* multibootInfo)
|
|
||||||
{
|
|
||||||
size_t heapSize = 0xFFC00000 - (size_t) &_kernelEnd;
|
|
||||||
int log = 0;
|
|
||||||
for(; heapSize > 1; log++)
|
|
||||||
heapSize >>= 1;
|
|
||||||
heapSize <<= log;
|
|
||||||
//new(&State::allocator) Allocator((void*) (0xFFC00000 - heapSize), heapSize, 64);
|
|
||||||
Multiboot2Info bootInfo(multibootInfo);
|
|
||||||
if(!bootInfo.isValid())
|
|
||||||
return 1;
|
|
||||||
bootInfo.getMemoryMap().insertEntry(0, 4 * 1024 * 1024, (unsigned int) MemoryType::Unavailable);
|
|
||||||
//new(&State::config) SystemInfo(bootInfo.getMemoryMap(), bootInfo.getCommandLine());
|
|
||||||
TTY tty((char*) 0xFF8B8000);
|
|
||||||
tty << "Type\t\tLocation\t\tSize\n";
|
|
||||||
for(size_t i = 0; i < bootInfo.getMemoryMap().size() && bootInfo.getMemoryMap()[i].getSize() > 0; i++)
|
|
||||||
{
|
|
||||||
tty << (int) bootInfo.getMemoryMap()[i].getType() << "\t\t\t";
|
|
||||||
tty << (void*) bootInfo.getMemoryMap()[i].getLocation() << "\t\t";
|
|
||||||
tty << (int) bootInfo.getMemoryMap()[i].getSize() << "\n";
|
|
||||||
}
|
|
||||||
// TODO: Initialize page allocator
|
|
||||||
// TODO: Initialize process queue, add entry for each module
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
29
src/x86/interrupts.c
Normal file
29
src/x86/interrupts.c
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include "interrupts.h"
|
||||||
|
|
||||||
|
struct idt_info_t
|
||||||
|
{
|
||||||
|
uint16_t size;
|
||||||
|
void *location;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
void lidt(struct interrupt_descriptor_t *idt)
|
||||||
|
{
|
||||||
|
struct idt_info_t idt_info;
|
||||||
|
idt_info.size = sizeof(struct interrupt_descriptor_t) * 256 - 1;
|
||||||
|
idt_info.location = (void *)idt;
|
||||||
|
asm("lidt (%0)"
|
||||||
|
:
|
||||||
|
: "r"(&idt_info));
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void *isr, enum isr_type_t type, uint32_t privilage)
|
||||||
|
{
|
||||||
|
descriptor->offset_1 = (uint32_t) isr & 0xFFFF;
|
||||||
|
descriptor->offset_2 = (uint32_t) isr >> 16;
|
||||||
|
descriptor->selector = 8;
|
||||||
|
descriptor->zero = 0;
|
||||||
|
descriptor->type = type;
|
||||||
|
descriptor->storage = 0;
|
||||||
|
descriptor->dpl = privilage;
|
||||||
|
descriptor->present = 1;
|
||||||
|
}
|
||||||
@@ -1,169 +0,0 @@
|
|||||||
#include "../interrupts.hpp"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
class InterruptDescriptor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum Type
|
|
||||||
{
|
|
||||||
TASK32 = 5,
|
|
||||||
TRAP32 = 15,
|
|
||||||
INT32 = 14,
|
|
||||||
TRAP16 = 7,
|
|
||||||
INT16 = 6
|
|
||||||
};
|
|
||||||
|
|
||||||
InterruptDescriptor()
|
|
||||||
{
|
|
||||||
this->m_offset1 = 0;
|
|
||||||
this->m_selector = 0;
|
|
||||||
this->m_zero = 0;
|
|
||||||
this->m_type = 0;
|
|
||||||
this->m_storage = 0;
|
|
||||||
this->m_dpl = 0;
|
|
||||||
this->m_present = 0;
|
|
||||||
this->m_offset2 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
InterruptDescriptor(void* handler, Type type, unsigned int dpl)
|
|
||||||
{
|
|
||||||
uint32_t offset = (uint32_t) handler;
|
|
||||||
this->m_offset1 = (uint16_t) offset;
|
|
||||||
this->m_selector = 8;
|
|
||||||
this->m_zero = 0;
|
|
||||||
this->m_type = (uint16_t) type;
|
|
||||||
this->m_storage = 0;
|
|
||||||
this->m_dpl = dpl;
|
|
||||||
this->m_present = 1;
|
|
||||||
this->m_offset2 = offset >> 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool present()
|
|
||||||
{
|
|
||||||
return m_present == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void present(bool present)
|
|
||||||
{
|
|
||||||
m_present = present ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type type()
|
|
||||||
{
|
|
||||||
return (Type) m_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void type(Type type)
|
|
||||||
{
|
|
||||||
m_type = (unsigned int) type;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int dpl()
|
|
||||||
{
|
|
||||||
return m_dpl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dpl(unsigned int dpl)
|
|
||||||
{
|
|
||||||
m_dpl = dpl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* operator=(void* rhs)
|
|
||||||
{
|
|
||||||
uint32_t offset = (uint32_t) rhs;
|
|
||||||
m_offset1 = (uint16_t) offset;
|
|
||||||
m_offset2 = (offset >> 16);
|
|
||||||
return rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
uint16_t m_offset1;
|
|
||||||
uint16_t m_selector;
|
|
||||||
uint16_t m_zero : 8;
|
|
||||||
uint16_t m_type : 4;
|
|
||||||
uint16_t m_storage : 1;
|
|
||||||
uint16_t m_dpl : 2;
|
|
||||||
uint16_t m_present : 1;
|
|
||||||
uint16_t m_offset2;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IDTInfo
|
|
||||||
{
|
|
||||||
uint16_t size;
|
|
||||||
void* location;
|
|
||||||
};
|
|
||||||
|
|
||||||
InterruptDescriptor idt[256];
|
|
||||||
|
|
||||||
void lidt()
|
|
||||||
{
|
|
||||||
IDTInfo idtInfo;
|
|
||||||
idtInfo.size = sizeof(idt) - 1;
|
|
||||||
idtInfo.location = (void*) &idt;
|
|
||||||
asm("lidt (%0)"
|
|
||||||
:
|
|
||||||
: "r" (&idtInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((interrupt))
|
|
||||||
void divisionByZero(void* frame)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((interrupt))
|
|
||||||
void gpFaultHandler(void* frame, unsigned int error)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((interrupt))
|
|
||||||
void pageFaultHandler(void* frame, unsigned int error)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((interrupt))
|
|
||||||
void doubleFaultHandler(void* frame, unsigned int error)
|
|
||||||
{
|
|
||||||
asm("hlt");
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((interrupt))
|
|
||||||
void syscallHandler(void* frame)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
kernelns::Interrupts::Interrupts()
|
|
||||||
{
|
|
||||||
for(unsigned int i = 0; i <= MAX_SYSCALL_ID; i++)
|
|
||||||
syscalls[i] = (void*) NULL;
|
|
||||||
idt[0] = InterruptDescriptor((void*) &divisionByZero, InterruptDescriptor::INT32, 0);
|
|
||||||
idt[8] = InterruptDescriptor((void*) &doubleFaultHandler, InterruptDescriptor::INT32, 0);
|
|
||||||
idt[0x80] = InterruptDescriptor((void*) &syscallHandler, InterruptDescriptor::INT32, 0);
|
|
||||||
// Load interrupt handlers
|
|
||||||
// Configure PIC
|
|
||||||
lidt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void kernelns::Interrupts::enable()
|
|
||||||
{
|
|
||||||
asm("sti");
|
|
||||||
}
|
|
||||||
|
|
||||||
void kernelns::Interrupts::disable()
|
|
||||||
{
|
|
||||||
asm("cli");
|
|
||||||
}
|
|
||||||
|
|
||||||
void kernelns::Interrupts::addSyscall(unsigned int id, void* function)
|
|
||||||
{
|
|
||||||
if(id <= MAX_SYSCALL_ID)
|
|
||||||
syscalls[id] = function;
|
|
||||||
}
|
|
||||||
54
src/x86/interrupts.h
Normal file
54
src/x86/interrupts.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum interrupt_code_t
|
||||||
|
{
|
||||||
|
EXCEPTION_DIV_BY_0 = 0,
|
||||||
|
EXCEPTION_DEBUG = 1,
|
||||||
|
EXCEPTION_NMI = 2,
|
||||||
|
EXCEPTION_BREAKPOINT = 3,
|
||||||
|
EXCEPTION_OVERFLOW = 4,
|
||||||
|
EXCEPTION_OUT_OF_BOUNDS = 5,
|
||||||
|
EXCEPTION_INVALID_OPCODE = 6,
|
||||||
|
EXCEPTION_DEVICE_NOT_AVAILABLE = 7,
|
||||||
|
EXCEPTION_DOUBLE_FAULT = 8,
|
||||||
|
EXCEPTION_INVALID_TSS = 10,
|
||||||
|
EXCEPTION_SEGMENT_NOT_PRESENT = 11,
|
||||||
|
EXCEPTION_STACK_SEGMENT_FAULT = 12,
|
||||||
|
EXCEPTION_GPF = 13,
|
||||||
|
EXCEPTION_PAGE_FAULT = 14,
|
||||||
|
EXCEPTION_x87_FLOATING_POINT = 16,
|
||||||
|
EXCEPTION_ALIGNMENT_CHECK = 17,
|
||||||
|
EXCEPTION_MACHINE_CHECK = 18,
|
||||||
|
EXCEPTION_SIMD_FLOATING_POINT = 19,
|
||||||
|
EXCEPTION_VIRTUALIZATION = 20,
|
||||||
|
EXCEPTION_SECURITY = 30,
|
||||||
|
ISR_AP_START = 127,
|
||||||
|
ISR_SYSCALL = 128
|
||||||
|
};
|
||||||
|
|
||||||
|
enum isr_type_t
|
||||||
|
{
|
||||||
|
INTERRPUT_TASK32 = 5,
|
||||||
|
INTERRPUT_TRAP32 = 15,
|
||||||
|
INTERRPUT_INT32 = 14,
|
||||||
|
INTERRPUT_TRAP16 = 7,
|
||||||
|
INTERRPUT_INT16 = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
void lidt(struct interrupt_descriptor_t *idt);
|
||||||
|
|
||||||
|
void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void *isr, enum isr_type_t type, uint32_t privilage);
|
||||||
41
src/x86/isr.c
Normal file
41
src/x86/isr.c
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include "isr.h"
|
||||||
|
#include "stdio.h"
|
||||||
|
|
||||||
|
__attribute__ ((interrupt))
|
||||||
|
void isr_division_by_zero(void* frame)
|
||||||
|
{
|
||||||
|
printf("Exception: Division by zero\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((interrupt))
|
||||||
|
void isr_gp_fault(void* frame, unsigned int 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");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((naked))
|
||||||
|
void isr_ap_start(void* frame)
|
||||||
|
{
|
||||||
|
asm(".code16");
|
||||||
|
//...
|
||||||
|
asm(".code32");
|
||||||
|
// do something useful
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((interrupt))
|
||||||
|
void isr_syscall(void* frame)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
19
src/x86/isr.h
Normal file
19
src/x86/isr.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
__attribute__ ((interrupt))
|
||||||
|
void isr_division_by_zero(void* frame);
|
||||||
|
|
||||||
|
__attribute__ ((interrupt))
|
||||||
|
void isr_gp_fault(void* frame, unsigned int error);
|
||||||
|
|
||||||
|
__attribute__ ((interrupt))
|
||||||
|
void isr_page_fault(void* frame, unsigned int error);
|
||||||
|
|
||||||
|
__attribute__ ((interrupt))
|
||||||
|
void isr_double_fault(void* frame, unsigned int error);
|
||||||
|
|
||||||
|
__attribute__ ((naked))
|
||||||
|
void isr_ap_start(void* frame);
|
||||||
|
|
||||||
|
__attribute__ ((interrupt))
|
||||||
|
void isr_syscall(void* frame);
|
||||||
@@ -38,5 +38,5 @@ SECTIONS
|
|||||||
_heapLocation = 0xFFB00000;
|
_heapLocation = 0xFFB00000;
|
||||||
_heapSize = 0x100000;
|
_heapSize = 0x100000;
|
||||||
_kernelStart = VIRTUAL_BASE;
|
_kernelStart = VIRTUAL_BASE;
|
||||||
_kernelEnd = VIRTUAL_BASE + (4096 * IMAGE_SIZE);
|
_kernel_end = VIRTUAL_BASE + (4096 * IMAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
#include "memorymanagerx86.hpp"
|
|
||||||
|
|
||||||
unsigned int MemoryManagerx86::getPageSize() const
|
|
||||||
{
|
|
||||||
return pageSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
physaddr_t MemoryManagerx86::createAddressSpace()
|
|
||||||
{
|
|
||||||
if(((size_t) table & 0xFFF) != 0)
|
|
||||||
return -1;
|
|
||||||
PageTableEntry* newDirectory = (PageTableEntry*) table;
|
|
||||||
newDirectory[1022] = m_pageDirectory[1022];
|
|
||||||
newDirectory[1023] = m_pageDirectory[1023];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryManagerx86::loadAddressSpace(physaddr_t table)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int MemoryManagerx86::mapPage(void *page, physaddr_t frame, int flags)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
physaddr_t MemoryManagerx86::unmapPage(void *page)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#ifndef MEMORYMANAGERX86_H
|
|
||||||
#define MEMORYMANAGERX86_H
|
|
||||||
|
|
||||||
#include "../memorymanager.hpp"
|
|
||||||
#include "pagetableentry.hpp"
|
|
||||||
|
|
||||||
class MemoryManagerx86 : public MemoryManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual unsigned int getPageSize() const;
|
|
||||||
|
|
||||||
virtual physaddr_t createAddressSpace();
|
|
||||||
|
|
||||||
virtual void loadAddressSpace(physaddr_t table);
|
|
||||||
|
|
||||||
virtual int mapPage(void* page, physaddr_t frame, int flags);
|
|
||||||
|
|
||||||
virtual physaddr_t unmapPage(void* page);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
static const unsigned int pageSize = 4096;
|
|
||||||
|
|
||||||
PageTableEntry *m_pageTables, *m_pageDirectory;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
292
src/x86/mmap.cpp
292
src/x86/mmap.cpp
@@ -1,292 +0,0 @@
|
|||||||
#include "../mmap.hpp"
|
|
||||||
#include "../kernelstate.hpp"
|
|
||||||
|
|
||||||
class PageTableEntry {
|
|
||||||
public:
|
|
||||||
|
|
||||||
PageTableEntry()
|
|
||||||
{
|
|
||||||
this->present = 0;
|
|
||||||
this->rw = 0;
|
|
||||||
this->usermode = 0;
|
|
||||||
this->writeThrough = 0;
|
|
||||||
this->cacheDisable = 0;
|
|
||||||
this->accessed = 0;
|
|
||||||
this->dirty = 0;
|
|
||||||
this->pat = 0;
|
|
||||||
this->global = 0;
|
|
||||||
this->shared = 0;
|
|
||||||
this->ignored = 0;
|
|
||||||
this->physicalAddress = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getAccessed() const
|
|
||||||
{
|
|
||||||
return accessed == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getCacheDisable() const
|
|
||||||
{
|
|
||||||
return cacheDisable == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCacheDisable(bool cacheDisable)
|
|
||||||
{
|
|
||||||
this->cacheDisable = cacheDisable ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getDirty() const
|
|
||||||
{
|
|
||||||
return dirty == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getGlobal() const
|
|
||||||
{
|
|
||||||
return global == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setGlobal(bool global)
|
|
||||||
{
|
|
||||||
this->global = global ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getPat() const
|
|
||||||
{
|
|
||||||
return pat == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPat(bool pat)
|
|
||||||
{
|
|
||||||
this->pat = pat ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
physaddr_t getPhysicalAddress() const
|
|
||||||
{
|
|
||||||
physaddr_t physicalAddress = this->physicalAddress;
|
|
||||||
return physicalAddress << 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
physaddr_t setPhysicalAddress(physaddr_t physicalAddress)
|
|
||||||
{
|
|
||||||
this->physicalAddress = physicalAddress >> 12;
|
|
||||||
return this->physicalAddress << 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getPresent() const
|
|
||||||
{
|
|
||||||
return present == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPresent(bool present)
|
|
||||||
{
|
|
||||||
this->present = present ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getRw() const
|
|
||||||
{
|
|
||||||
return rw == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setRw(bool rw)
|
|
||||||
{
|
|
||||||
this->rw = rw ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getShared() const
|
|
||||||
{
|
|
||||||
return shared == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setShared(bool shared)
|
|
||||||
{
|
|
||||||
this->shared = shared ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getUsermode() const
|
|
||||||
{
|
|
||||||
return usermode == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setUsermode(bool usermode)
|
|
||||||
{
|
|
||||||
this->usermode = usermode ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getWriteThrough() const
|
|
||||||
{
|
|
||||||
return writeThrough == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setWriteThrough(bool writeThrough)
|
|
||||||
{
|
|
||||||
this->writeThrough = writeThrough ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
physaddr_t operator=(physaddr_t rhs)
|
|
||||||
{
|
|
||||||
return setPhysicalAddress(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
PageTableEntry operator=(PageTableEntry rhs)
|
|
||||||
{
|
|
||||||
uint32_t* iThis = (uint32_t*) this;
|
|
||||||
uint32_t* iThat = (uint32_t*) &rhs;
|
|
||||||
*iThis = *iThat;
|
|
||||||
return rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t present : 1;
|
|
||||||
uint32_t rw : 1;
|
|
||||||
uint32_t usermode : 1;
|
|
||||||
uint32_t writeThrough : 1;
|
|
||||||
uint32_t cacheDisable : 1;
|
|
||||||
uint32_t accessed : 1;
|
|
||||||
uint32_t dirty : 1;
|
|
||||||
uint32_t pat : 1;
|
|
||||||
uint32_t global : 1;
|
|
||||||
uint32_t shared : 1;
|
|
||||||
uint32_t ignored : 2;
|
|
||||||
uint32_t physicalAddress : 20;
|
|
||||||
};
|
|
||||||
|
|
||||||
int kernelns::mmap(void* start, size_t length, int flags)
|
|
||||||
{
|
|
||||||
if((size_t) start % 4096 != 0)
|
|
||||||
return -1;
|
|
||||||
PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000;
|
|
||||||
PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000;
|
|
||||||
size_t tableIndex = (size_t) start / 4096;
|
|
||||||
for(int i = (int) length; i > 0; i -= 4096)
|
|
||||||
{
|
|
||||||
size_t directoryIndex = tableIndex / 1024;
|
|
||||||
if(!pageDirectory[directoryIndex].getPresent())
|
|
||||||
{
|
|
||||||
physaddr_t newPT = State::pageAllocator.allocate(4096);
|
|
||||||
if(newPT == 0)
|
|
||||||
return -1;
|
|
||||||
pageDirectory[directoryIndex] = newPT;
|
|
||||||
pageDirectory[directoryIndex].setPresent(true);
|
|
||||||
pageDirectory[directoryIndex].setUsermode(false);
|
|
||||||
pageDirectory[directoryIndex].setRw(true);
|
|
||||||
}
|
|
||||||
if(!pageTables[tableIndex].getPresent())
|
|
||||||
{
|
|
||||||
physaddr_t page = State::pageAllocator.allocate(4096);
|
|
||||||
pageTables[tableIndex] = page;
|
|
||||||
pageTables[tableIndex].setPresent(true);
|
|
||||||
pageTables[tableIndex].setUsermode(false);
|
|
||||||
if(flags & MMAP_RW)
|
|
||||||
pageTables[tableIndex].setRw(true);
|
|
||||||
}
|
|
||||||
tableIndex++;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int kernelns::mmap(void* start, physaddr_t p_start, size_t length, int flags)
|
|
||||||
{
|
|
||||||
if((size_t) start % 4096 != 0 || p_start % 4096 != 0)
|
|
||||||
return -1;
|
|
||||||
physaddr_t page = p_start;
|
|
||||||
for(int i = (int) length; i > 0; i -= 4096)
|
|
||||||
{
|
|
||||||
if(mapPage(start, page, flags) != 0)
|
|
||||||
return -1;
|
|
||||||
page += 4096;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int kernelns::mapPage(void* start, physaddr_t p_start, int flags)
|
|
||||||
{
|
|
||||||
if((size_t) start % 4096 != 0 || p_start % 4096 != 0)
|
|
||||||
return -1;
|
|
||||||
PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000;
|
|
||||||
PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000;
|
|
||||||
size_t tableIndex = (size_t) start / 4096;
|
|
||||||
physaddr_t page = p_start;
|
|
||||||
size_t directoryIndex = tableIndex / 1024;
|
|
||||||
if(!pageDirectory[directoryIndex].getPresent())
|
|
||||||
{
|
|
||||||
physaddr_t newPT = State::pageAllocator.allocate(4096);
|
|
||||||
if(newPT == 0)
|
|
||||||
return -1;
|
|
||||||
pageDirectory[directoryIndex] = newPT;
|
|
||||||
pageDirectory[directoryIndex].setPresent(true);
|
|
||||||
pageDirectory[directoryIndex].setUsermode(false);
|
|
||||||
pageDirectory[directoryIndex].setRw(true);
|
|
||||||
}
|
|
||||||
if(!pageTables[tableIndex].getPresent())
|
|
||||||
{
|
|
||||||
pageTables[tableIndex] = page;
|
|
||||||
pageTables[tableIndex].setPresent(true);
|
|
||||||
pageTables[tableIndex].setUsermode(false);
|
|
||||||
if(flags & MMAP_RW)
|
|
||||||
pageTables[tableIndex].setRw(true);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int kernelns::munmap(void* start, size_t length)
|
|
||||||
{
|
|
||||||
if((size_t) start % 4096 != 0)
|
|
||||||
return -1;
|
|
||||||
PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000;
|
|
||||||
PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000;
|
|
||||||
size_t tableIndex = (size_t) start / 4096;
|
|
||||||
for(int i = (int) length; i > 0; i -= 4096)
|
|
||||||
{
|
|
||||||
size_t directoryIndex = tableIndex / 1024;
|
|
||||||
if(pageDirectory[directoryIndex].getPresent())
|
|
||||||
{
|
|
||||||
pageTables[tableIndex] = 0;
|
|
||||||
pageTables[tableIndex].setPresent(false);
|
|
||||||
pageTables[tableIndex].setUsermode(false);
|
|
||||||
pageTables[tableIndex].setRw(false);
|
|
||||||
}
|
|
||||||
tableIndex++;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool kernelns::isMapped(void* addr)
|
|
||||||
{
|
|
||||||
PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000;
|
|
||||||
size_t tableIndex = (size_t) addr / 4096;
|
|
||||||
size_t directoryIndex = tableIndex / 1024;
|
|
||||||
if(pageDirectory[directoryIndex].getPresent())
|
|
||||||
{
|
|
||||||
PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000;
|
|
||||||
return pageTables[tableIndex].getPresent();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
physaddr_t kernelns::getPhysicalAddress(void* addr)
|
|
||||||
{
|
|
||||||
PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000;
|
|
||||||
size_t tableIndex = (size_t) addr / 4096;
|
|
||||||
return pageTables[tableIndex].getPhysicalAddress() + ((size_t) addr & 0xFFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
int kernelns::createAddressSpace(void* table)
|
|
||||||
{
|
|
||||||
if(((size_t) table & 0xFFF) != 0)
|
|
||||||
return -1;
|
|
||||||
PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000;
|
|
||||||
PageTableEntry* newDirectory = (PageTableEntry*) table;
|
|
||||||
newDirectory[1022] = pageDirectory[1022];
|
|
||||||
newDirectory[1023] = pageDirectory[1023];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int kernelns::loadAddressSpace(physaddr_t table)
|
|
||||||
{
|
|
||||||
if((table & 0xFFF) != 0)
|
|
||||||
return -1;
|
|
||||||
asm("mov %0, %%cr3"
|
|
||||||
:
|
|
||||||
: "r" (table));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
123
src/x86/mmgr.c
Normal file
123
src/x86/mmgr.c
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
#include "mmgr.h"
|
||||||
|
#include "pageallocator.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "types/status.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
const size_t page_size = 4096;
|
||||||
|
|
||||||
|
const size_t page_bits = 12;
|
||||||
|
|
||||||
|
struct page_table_entry_t
|
||||||
|
{
|
||||||
|
uint32_t present : 1;
|
||||||
|
|
||||||
|
uint32_t rw : 1;
|
||||||
|
|
||||||
|
uint32_t usermode : 1;
|
||||||
|
|
||||||
|
uint32_t writeThrough : 1;
|
||||||
|
|
||||||
|
uint32_t cacheDisable : 1;
|
||||||
|
|
||||||
|
uint32_t accessed : 1;
|
||||||
|
|
||||||
|
uint32_t dirty : 1;
|
||||||
|
|
||||||
|
uint32_t pat : 1;
|
||||||
|
|
||||||
|
uint32_t global : 1;
|
||||||
|
|
||||||
|
uint32_t shared : 1;
|
||||||
|
|
||||||
|
uint32_t ignored : 2;
|
||||||
|
|
||||||
|
uint32_t physicalAddress : 20;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct page_table_entry_t *page_tables = (struct page_table_entry_t *)0xFFC00000;
|
||||||
|
|
||||||
|
struct page_table_entry_t *page_directory = (struct page_table_entry_t *)0xFFFFF000;
|
||||||
|
|
||||||
|
physaddr_t create_address_space(struct page_stack_t *page_stack)
|
||||||
|
{
|
||||||
|
physaddr_t table = reserve_page(page_stack);
|
||||||
|
if (table == S_OUT_OF_MEMORY)
|
||||||
|
{
|
||||||
|
return S_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
struct page_table_entry_t buffer = page_directory[0];
|
||||||
|
page_directory[0].physicalAddress = table >> page_bits;
|
||||||
|
asm volatile("invlpg 0xFFC00000" ::
|
||||||
|
: "memory");
|
||||||
|
memset((void *)page_tables, 0, 1022 * 4);
|
||||||
|
page_tables[1022] = page_directory[1022];
|
||||||
|
page_tables[1023] = page_directory[1023];
|
||||||
|
page_directory[0] = buffer;
|
||||||
|
asm volatile("invlpg 0xFFC00000" ::
|
||||||
|
: "memory");
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_address_space(physaddr_t table)
|
||||||
|
{
|
||||||
|
asm volatile("mov %0, %%cr3"
|
||||||
|
:
|
||||||
|
: "r"(table)
|
||||||
|
: "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
int map_page(struct page_stack_t *page_stack, void *page, physaddr_t frame, int flags)
|
||||||
|
{
|
||||||
|
if ((size_t)page % page_size != 0 || frame % page_size != 0)
|
||||||
|
{
|
||||||
|
return S_OUT_OF_BOUNDS;
|
||||||
|
}
|
||||||
|
size_t table_index = (size_t)page / page_size;
|
||||||
|
size_t directory_index = table_index / (page_size / sizeof(struct page_table_entry_t));
|
||||||
|
if (!page_directory[directory_index].present)
|
||||||
|
{
|
||||||
|
physaddr_t new_table = reserve_page(page_stack);
|
||||||
|
if (new_table == S_OUT_OF_MEMORY)
|
||||||
|
{
|
||||||
|
return S_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
page_directory[directory_index].physicalAddress = new_table >> page_bits;
|
||||||
|
page_directory[directory_index].present = 1;
|
||||||
|
page_directory[directory_index].usermode = 0;
|
||||||
|
page_directory[directory_index].rw = 1;
|
||||||
|
}
|
||||||
|
page_tables[table_index].physicalAddress = frame >> 12;
|
||||||
|
page_tables[table_index].present = 1;
|
||||||
|
page_tables[table_index].usermode = 1;
|
||||||
|
page_tables[table_index].rw = 1;
|
||||||
|
asm volatile("invlpg (%0)"
|
||||||
|
:
|
||||||
|
: "r"(page)
|
||||||
|
: "memory");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
physaddr_t unmap_page(void *page)
|
||||||
|
{
|
||||||
|
if ((size_t)page % page_size != 0)
|
||||||
|
{
|
||||||
|
return S_OUT_OF_BOUNDS;
|
||||||
|
}
|
||||||
|
size_t table_index = (size_t)page / page_size;
|
||||||
|
size_t directory_index = table_index / (page_size / sizeof(struct page_table_entry_t));
|
||||||
|
if (!page_directory[directory_index].present || !page_tables[table_index].present)
|
||||||
|
{
|
||||||
|
return S_OUT_OF_BOUNDS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
physaddr_t frame = page_tables[table_index].physicalAddress << page_bits;
|
||||||
|
memset(&page_tables[table_index], 0, sizeof(struct page_table_entry_t));
|
||||||
|
asm volatile("invlpg (%0)"
|
||||||
|
:
|
||||||
|
: "r"(page)
|
||||||
|
: "memory");
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/x86/msr.c
Normal file
17
src/x86/msr.c
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#include "msr.h"
|
||||||
|
|
||||||
|
void read_msr(enum msr_id_t msr_addr, uint64_t *value)
|
||||||
|
{
|
||||||
|
uint64_t v;
|
||||||
|
asm volatile("rdmsr"
|
||||||
|
: "=edx:eax" (v)
|
||||||
|
: "ecx" (msr_addr));
|
||||||
|
*value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_msr(enum msr_id_t msr_addr, uint64_t *value)
|
||||||
|
{
|
||||||
|
uint64_t v = *value;
|
||||||
|
asm volatile("wrmsr"
|
||||||
|
:: "ecx"(msr_addr), "A"(v));
|
||||||
|
}
|
||||||
22
src/x86/msr.h
Normal file
22
src/x86/msr.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum msr_id_t
|
||||||
|
{
|
||||||
|
MSR_APIC_BASE = 0x1B
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msr_apic_base_t
|
||||||
|
{
|
||||||
|
uint64_t reserved_1 : 8;
|
||||||
|
uint64_t bsp : 1;
|
||||||
|
uint64_t reserved_2 : 1;
|
||||||
|
uint64_t x2apic_enable : 1;
|
||||||
|
uint64_t apic_global_enable : 1;
|
||||||
|
uint64_t apic_base : 52;
|
||||||
|
};
|
||||||
|
|
||||||
|
void read_msr(enum msr_id_t msr_addr, uint64_t *value);
|
||||||
|
|
||||||
|
void write_msr(enum msr_id_t msr_addr, uint64_t *value);
|
||||||
55
src/x86/multiboot2.c
Normal file
55
src/x86/multiboot2.c
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#include "multiboot2.h"
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
void *read_multiboot_table(struct boot_info_t *boot_info, void *table)
|
||||||
|
{
|
||||||
|
uint32_t *int_table = (uint32_t *)table;
|
||||||
|
switch (*int_table)
|
||||||
|
{
|
||||||
|
case MB_END_TAG:
|
||||||
|
return NULL;
|
||||||
|
case MB_MEMORY_MAP: ;
|
||||||
|
unsigned int tag_size = ((struct multiboot2_memory_map_t*) table)->size - 16;
|
||||||
|
unsigned int entry_size = ((struct multiboot2_memory_map_t*) table)->entry_size;
|
||||||
|
struct multiboot2_map_entry_t *entry = &((struct multiboot2_memory_map_t*) table)->entries;
|
||||||
|
while(tag_size)
|
||||||
|
{
|
||||||
|
unsigned int entry_type =
|
||||||
|
entry->type == MB_AVAILABLE ? M_AVAILABLE
|
||||||
|
: (entry->type == MB_DEFECTIVE ? M_DEFECTIVE
|
||||||
|
: M_UNAVAILABLE);
|
||||||
|
insert_region(&boot_info->map, entry->base, entry->length, entry_type);
|
||||||
|
entry = (struct multiboot2_map_entry_t*) ((void*) entry + entry_size);
|
||||||
|
tag_size -= entry_size;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MB_MODULE:
|
||||||
|
if(boot_info->module_count < 8)
|
||||||
|
{
|
||||||
|
boot_info->modules[boot_info->module_count].start = ((struct multiboot2_module_t*) table)->start;
|
||||||
|
boot_info->modules[boot_info->module_count].end = ((struct multiboot2_module_t*) table)->end;
|
||||||
|
strcpy(boot_info->modules[boot_info->module_count].str, ((struct multiboot2_module_t*) table)->str);
|
||||||
|
insert_region(&boot_info->map,
|
||||||
|
((struct multiboot2_module_t*) table)->start,
|
||||||
|
((struct multiboot2_module_t*) table)->end - ((struct multiboot2_module_t*) table)->start,
|
||||||
|
M_UNAVAILABLE);
|
||||||
|
boot_info->module_count++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("WARNING: Too many modules, must skip one.\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MB_BOOT_COMMAND:
|
||||||
|
strcpy(boot_info->parameters, &((struct multiboot2_string_t*) table)->str);
|
||||||
|
break;
|
||||||
|
case MB_BOOTLOADER:
|
||||||
|
strcpy(boot_info->bootloader, &((struct multiboot2_string_t*) table)->str);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size_t size = (int_table[1] + 7) - ((int_table[1] + 7) % 8);
|
||||||
|
return table + size;
|
||||||
|
}
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
#include "multiboot2.hpp"
|
|
||||||
#include "../memorytype.hpp"
|
|
||||||
|
|
||||||
using namespace kernelns;
|
|
||||||
|
|
||||||
Multiboot2Info::Multiboot2Info(void* tableLocation)
|
|
||||||
{
|
|
||||||
m_commandLine = NULL;
|
|
||||||
m_bootloader = NULL;
|
|
||||||
m_moduleCount = 0;
|
|
||||||
uint32_t* ptr = (uint32_t*) tableLocation;
|
|
||||||
ptr += 2;
|
|
||||||
while(*ptr != 0)
|
|
||||||
{
|
|
||||||
if(*ptr == (uint32_t) Tag::BootCommand)
|
|
||||||
{
|
|
||||||
m_commandLine = &reinterpret_cast<TagString*>(ptr)->str;
|
|
||||||
}
|
|
||||||
else if(*ptr == (uint32_t) Tag::Bootloader)
|
|
||||||
{
|
|
||||||
m_bootloader = &reinterpret_cast<TagString*>(ptr)->str;
|
|
||||||
}
|
|
||||||
else if(*ptr == (uint32_t) Tag::MemoryMap)
|
|
||||||
{
|
|
||||||
unsigned int tagSize = reinterpret_cast<TagMemoryMap*>(ptr)->size - 16;
|
|
||||||
unsigned int entrySize = reinterpret_cast<TagMemoryMap*>(ptr)->entrySize;
|
|
||||||
MemoryMapEntry* entry = &reinterpret_cast<TagMemoryMap*>(ptr)->entries;
|
|
||||||
while(tagSize > 0)
|
|
||||||
{
|
|
||||||
unsigned int regionType =
|
|
||||||
(entry->type == (unsigned int) Multiboot2MemoryType::Available) ? (unsigned int) MemoryType::Available
|
|
||||||
: ((entry->type == (unsigned int) Multiboot2MemoryType::Defective) ? (unsigned int) MemoryType::Defective
|
|
||||||
: (unsigned int) MemoryType::Unavailable);
|
|
||||||
m_memmap.insertEntry(entry->base, entry->length, entry->type);
|
|
||||||
entry = (MemoryMapEntry*) (reinterpret_cast<char*>(entry) + entrySize);
|
|
||||||
tagSize -= entrySize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(*ptr == (uint32_t) Tag::Module)
|
|
||||||
{
|
|
||||||
TagModule* moduleTag = reinterpret_cast<TagModule*>(ptr);
|
|
||||||
m_modules[m_moduleCount] = Module(moduleTag->start, moduleTag->end, &moduleTag->str);
|
|
||||||
m_memmap.insertEntry(moduleTag->start, moduleTag->end - moduleTag->start, (unsigned int) MemoryType::Unavailable);
|
|
||||||
}
|
|
||||||
unsigned int size = (ptr[1] + 7) - ((ptr[1] + 7) % 8);
|
|
||||||
ptr += size / sizeof(uint32_t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Multiboot2Info::~Multiboot2Info()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Multiboot2Info::isValid() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryMap& Multiboot2Info::getMemoryMap()
|
|
||||||
{
|
|
||||||
return m_memmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Module* Multiboot2Info::getModules() const
|
|
||||||
{
|
|
||||||
return m_modules;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Multiboot2Info::getModuleCount() const
|
|
||||||
{
|
|
||||||
return m_moduleCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* Multiboot2Info::getCommandLine() const
|
|
||||||
{
|
|
||||||
return m_commandLine;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* Multiboot2Info::getBootloaderName() const
|
|
||||||
{
|
|
||||||
return m_bootloader;
|
|
||||||
}
|
|
||||||
84
src/x86/multiboot2.h
Normal file
84
src/x86/multiboot2.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "memorymap.h"
|
||||||
|
#include "module.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define module_limit 8
|
||||||
|
|
||||||
|
enum multiboot2_tag_types
|
||||||
|
{
|
||||||
|
MB_END_TAG = 0,
|
||||||
|
MB_BOOT_COMMAND = 1,
|
||||||
|
MB_BOOTLOADER = 2,
|
||||||
|
MB_MODULE = 3,
|
||||||
|
MB_MEMORY_INFO = 4,
|
||||||
|
MB_BIOS_BOOT_DEVICE = 5,
|
||||||
|
MB_MEMORY_MAP = 6,
|
||||||
|
MB_VBE = 7,
|
||||||
|
MB_FRAMEBUFFER = 8,
|
||||||
|
MB_ELF_SYMBOLS = 9,
|
||||||
|
MB_APM = 10,
|
||||||
|
MB_EFI32_SYSTEM_TABLE = 11,
|
||||||
|
MB_EFI64_SYSTEM_TABLE = 12,
|
||||||
|
MB_SMBIOS = 13,
|
||||||
|
MB_ACPI10_RSDP = 14,
|
||||||
|
MB_ACPT20_RSDP = 15,
|
||||||
|
MB_NETOWRK = 16,
|
||||||
|
MB_EFI_MEMORY_MAP = 17,
|
||||||
|
MB_EFI_BOOT_SERVICES = 18,
|
||||||
|
MB_EFI32_IMAGE = 19,
|
||||||
|
MB_EFI64_IMAGE = 20,
|
||||||
|
MB_LOAD_ADDRESS = 21
|
||||||
|
};
|
||||||
|
|
||||||
|
enum multiboot2_memory_types
|
||||||
|
{
|
||||||
|
MB_AVAILABLE = 1,
|
||||||
|
MB_ACPI = 3,
|
||||||
|
MB_DEFECTIVE = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot2_string_t
|
||||||
|
{
|
||||||
|
uint32_t type;
|
||||||
|
uint32_t size;
|
||||||
|
char str;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot2_module_t
|
||||||
|
{
|
||||||
|
uint32_t type;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t start;
|
||||||
|
uint32_t end;
|
||||||
|
char str;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot2_map_entry_t
|
||||||
|
{
|
||||||
|
uint64_t base;
|
||||||
|
uint64_t length;
|
||||||
|
uint32_t type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct multiboot2_memory_map_t
|
||||||
|
{
|
||||||
|
uint32_t type;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t entry_size;
|
||||||
|
uint32_t entry_version;
|
||||||
|
struct multiboot2_map_entry_t entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct boot_info_t
|
||||||
|
{
|
||||||
|
char *bootloader;
|
||||||
|
char *parameters;
|
||||||
|
size_t module_count;
|
||||||
|
struct memory_map_t map;
|
||||||
|
struct module_t modules[module_limit];
|
||||||
|
};
|
||||||
|
|
||||||
|
void *read_multiboot_table(struct boot_info_t *boot_info, void *table);
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
#ifndef MULTIBOOT2_H
|
|
||||||
#define MULTIBOOT2_H
|
|
||||||
|
|
||||||
#include "../memorymap.hpp"
|
|
||||||
#include "../module.hpp"
|
|
||||||
|
|
||||||
namespace kernelns
|
|
||||||
{
|
|
||||||
|
|
||||||
class Multiboot2Info
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum class Tag
|
|
||||||
{
|
|
||||||
BootCommand = 1,
|
|
||||||
Bootloader = 2,
|
|
||||||
Module = 3,
|
|
||||||
MemoryInfo = 4,
|
|
||||||
BIOSBootDevice = 5,
|
|
||||||
MemoryMap = 6,
|
|
||||||
VBE = 7,
|
|
||||||
Framebuffer = 8,
|
|
||||||
ELFSymbols = 9,
|
|
||||||
APM = 10,
|
|
||||||
EFI32SystemTable = 11,
|
|
||||||
EFI64SystemTable = 12,
|
|
||||||
SMBIOS = 13,
|
|
||||||
ACPI10RSDP = 14,
|
|
||||||
ACPT20RSDP = 15,
|
|
||||||
Network = 16,
|
|
||||||
EFIMemoryMap = 17,
|
|
||||||
EFIBootServices = 18,
|
|
||||||
EFI32Image = 19,
|
|
||||||
EFI64Image = 20,
|
|
||||||
LoadAddress = 21
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class Multiboot2MemoryType
|
|
||||||
{
|
|
||||||
Available = 1,
|
|
||||||
ACPI = 3,
|
|
||||||
Defective = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TagString
|
|
||||||
{
|
|
||||||
uint32_t type;
|
|
||||||
uint32_t size;
|
|
||||||
char str;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TagModule
|
|
||||||
{
|
|
||||||
uint32_t type;
|
|
||||||
uint32_t size;
|
|
||||||
uint32_t start;
|
|
||||||
uint32_t end;
|
|
||||||
char str;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MemoryMapEntry
|
|
||||||
{
|
|
||||||
uint64_t base;
|
|
||||||
uint64_t length;
|
|
||||||
uint32_t type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TagMemoryMap
|
|
||||||
{
|
|
||||||
uint32_t type;
|
|
||||||
uint32_t size;
|
|
||||||
uint32_t entrySize;
|
|
||||||
uint32_t entryVersion;
|
|
||||||
MemoryMapEntry entries;
|
|
||||||
};
|
|
||||||
|
|
||||||
Multiboot2Info(void* tableLocation);
|
|
||||||
|
|
||||||
~Multiboot2Info();
|
|
||||||
|
|
||||||
bool isValid() const;
|
|
||||||
|
|
||||||
MemoryMap& getMemoryMap();
|
|
||||||
|
|
||||||
const Module* getModules() const;
|
|
||||||
|
|
||||||
unsigned int getModuleCount() const;
|
|
||||||
|
|
||||||
const char* getCommandLine() const;
|
|
||||||
|
|
||||||
const char* getBootloaderName() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
Module m_modules[16];
|
|
||||||
|
|
||||||
unsigned int m_moduleCount;
|
|
||||||
|
|
||||||
MemoryMap m_memmap;
|
|
||||||
|
|
||||||
char* m_commandLine;
|
|
||||||
|
|
||||||
char* m_bootloader;
|
|
||||||
|
|
||||||
void* m_tableLocation;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
#include "pagetableentry.hpp"
|
|
||||||
|
|
||||||
PageTableEntry::PageTableEntry()
|
|
||||||
{
|
|
||||||
this->present = 0;
|
|
||||||
this->rw = 0;
|
|
||||||
this->usermode = 0;
|
|
||||||
this->writeThrough = 0;
|
|
||||||
this->cacheDisable = 0;
|
|
||||||
this->accessed = 0;
|
|
||||||
this->dirty = 0;
|
|
||||||
this->pat = 0;
|
|
||||||
this->global = 0;
|
|
||||||
this->shared = 0;
|
|
||||||
this->ignored = 0;
|
|
||||||
this->physicalAddress = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PageTableEntry::getAccessed() const
|
|
||||||
{
|
|
||||||
return accessed == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PageTableEntry::getCacheDisable() const
|
|
||||||
{
|
|
||||||
return cacheDisable == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PageTableEntry::setCacheDisable(bool cacheDisable)
|
|
||||||
{
|
|
||||||
this->cacheDisable = cacheDisable ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PageTableEntry::getDirty() const
|
|
||||||
{
|
|
||||||
return dirty == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PageTableEntry::getGlobal() const
|
|
||||||
{
|
|
||||||
return global == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PageTableEntry::setGlobal(bool global)
|
|
||||||
{
|
|
||||||
this->global = global ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PageTableEntry::getPat() const
|
|
||||||
{
|
|
||||||
return pat == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PageTableEntry::setPat(bool pat)
|
|
||||||
{
|
|
||||||
this->pat = pat ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
physaddr_t PageTableEntry::getPhysicalAddress() const
|
|
||||||
{
|
|
||||||
physaddr_t physicalAddress = this->physicalAddress;
|
|
||||||
return physicalAddress << 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
physaddr_t PageTableEntry::setPhysicalAddress(physaddr_t physicalAddress)
|
|
||||||
{
|
|
||||||
this->physicalAddress = physicalAddress >> 12;
|
|
||||||
return this->physicalAddress << 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PageTableEntry::getPresent() const
|
|
||||||
{
|
|
||||||
return present == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PageTableEntry::setPresent(bool present)
|
|
||||||
{
|
|
||||||
this->present = present ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PageTableEntry::getRw() const
|
|
||||||
{
|
|
||||||
return rw == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PageTableEntry::setRw(bool rw)
|
|
||||||
{
|
|
||||||
this->rw = rw ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PageTableEntry::getShared() const
|
|
||||||
{
|
|
||||||
return shared == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PageTableEntry::setShared(bool shared)
|
|
||||||
{
|
|
||||||
this->shared = shared ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PageTableEntry::getUsermode() const
|
|
||||||
{
|
|
||||||
return usermode == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PageTableEntry::setUsermode(bool usermode)
|
|
||||||
{
|
|
||||||
this->usermode = usermode ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PageTableEntry::getWriteThrough() const
|
|
||||||
{
|
|
||||||
return writeThrough == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PageTableEntry::setWriteThrough(bool writeThrough)
|
|
||||||
{
|
|
||||||
this->writeThrough = writeThrough ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
physaddr_t PageTableEntry::operator=(physaddr_t rhs)
|
|
||||||
{
|
|
||||||
return setPhysicalAddress(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
PageTableEntry PageTableEntry::operator=(PageTableEntry rhs)
|
|
||||||
{
|
|
||||||
uint32_t *iThis = (uint32_t *)this;
|
|
||||||
uint32_t *iThat = (uint32_t *)&rhs;
|
|
||||||
*iThis = *iThat;
|
|
||||||
return rhs;
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
#ifndef PAGETABLEENTRY_H
|
|
||||||
#define PAGETABLEENTRY_H
|
|
||||||
|
|
||||||
#include "../systypes.hpp"
|
|
||||||
|
|
||||||
class PageTableEntry {
|
|
||||||
public:
|
|
||||||
|
|
||||||
PageTableEntry();
|
|
||||||
|
|
||||||
bool getAccessed() const;
|
|
||||||
|
|
||||||
bool getCacheDisable() const;
|
|
||||||
|
|
||||||
void setCacheDisable(bool cacheDisable);
|
|
||||||
|
|
||||||
bool getDirty() const;
|
|
||||||
|
|
||||||
bool getGlobal() const;
|
|
||||||
|
|
||||||
void setGlobal(bool global);
|
|
||||||
|
|
||||||
bool getPat() const;
|
|
||||||
|
|
||||||
void setPat(bool pat);
|
|
||||||
|
|
||||||
physaddr_t getPhysicalAddress() const;
|
|
||||||
|
|
||||||
physaddr_t setPhysicalAddress(physaddr_t physicalAddress);
|
|
||||||
|
|
||||||
bool getPresent() const;
|
|
||||||
|
|
||||||
void setPresent(bool present);
|
|
||||||
|
|
||||||
bool getRw() const;
|
|
||||||
|
|
||||||
void setRw(bool rw);
|
|
||||||
|
|
||||||
bool getShared() const;
|
|
||||||
|
|
||||||
void setShared(bool shared);
|
|
||||||
|
|
||||||
bool getUsermode() const;
|
|
||||||
|
|
||||||
void setUsermode(bool usermode);
|
|
||||||
|
|
||||||
bool getWriteThrough() const;
|
|
||||||
|
|
||||||
void setWriteThrough(bool writeThrough);
|
|
||||||
|
|
||||||
physaddr_t operator=(physaddr_t rhs);
|
|
||||||
|
|
||||||
PageTableEntry operator=(PageTableEntry rhs);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
uint32_t present : 1;
|
|
||||||
|
|
||||||
uint32_t rw : 1;
|
|
||||||
|
|
||||||
uint32_t usermode : 1;
|
|
||||||
|
|
||||||
uint32_t writeThrough : 1;
|
|
||||||
|
|
||||||
uint32_t cacheDisable : 1;
|
|
||||||
|
|
||||||
uint32_t accessed : 1;
|
|
||||||
|
|
||||||
uint32_t dirty : 1;
|
|
||||||
|
|
||||||
uint32_t pat : 1;
|
|
||||||
|
|
||||||
uint32_t global : 1;
|
|
||||||
|
|
||||||
uint32_t shared : 1;
|
|
||||||
|
|
||||||
uint32_t ignored : 2;
|
|
||||||
|
|
||||||
uint32_t physicalAddress : 20;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
68
src/x86/putc.c
Normal file
68
src/x86/putc.c
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#include "stdio.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
enum vga_color_t {
|
||||||
|
VGA_COLOR_BLACK = 0,
|
||||||
|
VGA_COLOR_BLUE = 1,
|
||||||
|
VGA_COLOR_GREEN = 2,
|
||||||
|
VGA_COLOR_CYAN = 3,
|
||||||
|
VGA_COLOR_RED = 4,
|
||||||
|
VGA_COLOR_MAGENTA = 5,
|
||||||
|
VGA_COLOR_BROWN = 6,
|
||||||
|
VGA_COLOR_LIGHT_GREY = 7,
|
||||||
|
VGA_COLOR_DARK_GREY = 8,
|
||||||
|
VGA_COLOR_LIGHT_BLUE = 9,
|
||||||
|
VGA_COLOR_LIGHT_GREEN = 10,
|
||||||
|
VGA_COLOR_LIGHT_CYAN = 11,
|
||||||
|
VGA_COLOR_LIGHT_RED = 12,
|
||||||
|
VGA_COLOR_LIGHT_MAGENTA = 13,
|
||||||
|
VGA_COLOR_LIGHT_BROWN = 14,
|
||||||
|
VGA_COLOR_WHITE = 15,
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__ ((packed))
|
||||||
|
struct cell_t
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
char fg : 4;
|
||||||
|
char bg : 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cell_t *screen = (struct cell_t*)0xFF8B8000;
|
||||||
|
size_t cursor = 0;
|
||||||
|
|
||||||
|
const size_t tab_width = 4;
|
||||||
|
const size_t line_width = 80;
|
||||||
|
|
||||||
|
int putchar(int c)
|
||||||
|
{
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case '\n':
|
||||||
|
cursor += line_width;
|
||||||
|
cursor -= cursor % line_width;
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
cursor += tab_width;
|
||||||
|
cursor -= cursor % tab_width;
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
cursor -= line_width - 1;
|
||||||
|
cursor += line_width - (cursor % line_width);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
screen[cursor].c = (char) c;
|
||||||
|
cursor++;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int puts(const char *str)
|
||||||
|
{
|
||||||
|
while(*str)
|
||||||
|
{
|
||||||
|
putchar(*str);
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
102
src/x86/quark_x86.c
Normal file
102
src/x86/quark_x86.c
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
#include "kernel.h"
|
||||||
|
#include "pageallocator.h"
|
||||||
|
#include "multiboot2.h"
|
||||||
|
#include "memorymap.h"
|
||||||
|
#include "apic.h"
|
||||||
|
#include "interrupts.h"
|
||||||
|
#include "msr.h"
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "module.h"
|
||||||
|
#include "isr.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
extern int _kernel_end;
|
||||||
|
|
||||||
|
struct apic_registers_t volatile *apic_registers;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
static struct interrupt_descriptor_t idt[256];
|
||||||
|
static struct page_stack_t page_stack;
|
||||||
|
static struct kernel_t kernel;
|
||||||
|
struct memory_region_t map_array[16];
|
||||||
|
char bootloader_name[64];
|
||||||
|
char kernel_parameters[64];
|
||||||
|
struct boot_info_t boot_info = {
|
||||||
|
.bootloader = bootloader_name,
|
||||||
|
.parameters = kernel_parameters,
|
||||||
|
.module_count = 0,
|
||||||
|
.map = {
|
||||||
|
.array = map_array,
|
||||||
|
.size = 0,
|
||||||
|
.capacity = 16}};
|
||||||
|
multiboot_info += 8;
|
||||||
|
while (multiboot_info != NULL)
|
||||||
|
{
|
||||||
|
multiboot_info = read_multiboot_table(&boot_info, multiboot_info);
|
||||||
|
}
|
||||||
|
insert_region(&boot_info.map, 0, 1 << 22, M_UNAVAILABLE);
|
||||||
|
printf("Type\t\tLocation\t\tSize\n");
|
||||||
|
for (size_t i = 0; i < boot_info.map.size && boot_info.map.array[i].size > 0; i++)
|
||||||
|
{
|
||||||
|
printf("%i\t\t\t%08x\t\t%u\n", boot_info.map.array[i].type, boot_info.map.array[i].location, boot_info.map.array[i].size);
|
||||||
|
}
|
||||||
|
page_stack.base_pointer = (physaddr_t*)0xFFC00000;
|
||||||
|
page_stack.stack_pointer = (physaddr_t*)0xFFC00000;
|
||||||
|
page_stack.limit_pointer = (physaddr_t*)0xFF900000;
|
||||||
|
initialize_page_stack(&page_stack, &boot_info.map, 4096);
|
||||||
|
for(int i = 0; i < boot_info.module_count; i++)
|
||||||
|
{
|
||||||
|
load_module(&kernel, &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 volatile(
|
||||||
|
"mov $0xFF, %%al;"
|
||||||
|
"outb %%al, $0xA1;"
|
||||||
|
"outb %%al, $0x21;"
|
||||||
|
::: "al"
|
||||||
|
);
|
||||||
|
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
|
||||||
|
}
|
||||||
125
src/x86/tty.cpp
125
src/x86/tty.cpp
@@ -1,125 +0,0 @@
|
|||||||
#include <stdbool.h>
|
|
||||||
#include "tty.hpp"
|
|
||||||
|
|
||||||
kernelns::TTY::TTY(char* vga)
|
|
||||||
{
|
|
||||||
this->vga = vga;
|
|
||||||
this->cursor = 0;
|
|
||||||
this->width = 0;
|
|
||||||
this->base = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
kernelns::TTY& kernelns::TTY::operator<<(kernelns::TTY::Format fmt)
|
|
||||||
{
|
|
||||||
switch(fmt)
|
|
||||||
{
|
|
||||||
case Binary:
|
|
||||||
base = 2;
|
|
||||||
break;
|
|
||||||
case Decimal:
|
|
||||||
base = 10;
|
|
||||||
break;
|
|
||||||
case Hex:
|
|
||||||
base = 16;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kernelns::TTY& kernelns::TTY::operator<<(const char* str)
|
|
||||||
{
|
|
||||||
return printString(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
kernelns::TTY& kernelns::TTY::operator<<(unsigned int n)
|
|
||||||
{
|
|
||||||
return printNumber(n, base, width);
|
|
||||||
}
|
|
||||||
|
|
||||||
kernelns::TTY& kernelns::TTY::operator<<(int n)
|
|
||||||
{
|
|
||||||
return printNumber((unsigned int) n, base, width);
|
|
||||||
}
|
|
||||||
|
|
||||||
kernelns::TTY& kernelns::TTY::operator<<(void* n)
|
|
||||||
{
|
|
||||||
return printNumber((unsigned int) n, 16, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
kernelns::TTY& kernelns::TTY::operator<<(char c)
|
|
||||||
{
|
|
||||||
return putChar(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void kernelns::TTY::setWidth(size_t width)
|
|
||||||
{
|
|
||||||
this->width = width;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t kernelns::TTY::getWidth()
|
|
||||||
{
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
void kernelns::TTY::clear()
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 80*25; i++)
|
|
||||||
{
|
|
||||||
vga[i * 2] = ' ';
|
|
||||||
}
|
|
||||||
cursor = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
kernelns::TTY& kernelns::TTY::printNumber(unsigned int n, size_t base,
|
|
||||||
size_t width)
|
|
||||||
{
|
|
||||||
const char* digits = "0123456789ABCDEF";
|
|
||||||
char str[33];
|
|
||||||
size_t i = 1;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
str[i] = digits[n % base];
|
|
||||||
n /= base;
|
|
||||||
i++;
|
|
||||||
} while(n > 0);
|
|
||||||
while(i <= width)
|
|
||||||
{
|
|
||||||
str[i] = '0';
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
str[0] = '\0';
|
|
||||||
for(char* s = str + (i - 1); *s; s--)
|
|
||||||
{
|
|
||||||
putChar(*s);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
kernelns::TTY& kernelns::TTY::printString(const char* str)
|
|
||||||
{
|
|
||||||
while(*str)
|
|
||||||
{
|
|
||||||
putChar(*str);
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
kernelns::TTY& kernelns::TTY::putChar(char c)
|
|
||||||
{
|
|
||||||
switch(c)
|
|
||||||
{
|
|
||||||
case '\n':
|
|
||||||
cursor = (cursor + 80) - (cursor % 80);
|
|
||||||
break;
|
|
||||||
case '\t':
|
|
||||||
cursor = (cursor + 4) - (cursor % 4);
|
|
||||||
break;
|
|
||||||
case '\r':
|
|
||||||
cursor -= cursor % 160;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vga[cursor * 2] = c;
|
|
||||||
cursor++;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
#ifndef TTY_H_
|
|
||||||
#define TTY_H_
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
namespace kernelns
|
|
||||||
{
|
|
||||||
|
|
||||||
class TTY
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum Format
|
|
||||||
{
|
|
||||||
Binary,
|
|
||||||
Decimal,
|
|
||||||
Hex
|
|
||||||
};
|
|
||||||
|
|
||||||
TTY(char* vga);
|
|
||||||
|
|
||||||
TTY& operator<<(Format fmt);
|
|
||||||
|
|
||||||
TTY& operator<<(const char* str);
|
|
||||||
|
|
||||||
TTY& operator<<(unsigned int n);
|
|
||||||
|
|
||||||
TTY& operator<<(int n);
|
|
||||||
|
|
||||||
TTY& operator<<(void* n);
|
|
||||||
|
|
||||||
TTY& operator<<(char c);
|
|
||||||
|
|
||||||
void setWidth(size_t width);
|
|
||||||
|
|
||||||
size_t getWidth();
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
TTY& printNumber(unsigned int n, size_t base, size_t width);
|
|
||||||
|
|
||||||
TTY& printString(const char* str);
|
|
||||||
|
|
||||||
TTY& putChar(char c);
|
|
||||||
|
|
||||||
char* vga;
|
|
||||||
|
|
||||||
int cursor;
|
|
||||||
|
|
||||||
size_t width;
|
|
||||||
|
|
||||||
size_t base;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Reference in New Issue
Block a user