This commit is contained in:
Niklas Gollenstede
2025-10-31 22:37:36 +01:00
commit 174fe17e89
197 changed files with 79558 additions and 0 deletions

20
kernel/memory/config.h Normal file
View File

@@ -0,0 +1,20 @@
#pragma once
#include "../types.h"
// External symbols introduced by the linker with kernel start and end address
extern "C" void* ___KERNEL_START___;
extern "C" void* ___KERNEL_END___;
/*! \brief Lowest memory address we will make use of
* It seems wise to ignore everything below the first 1 MB
* since it is used by BIOS and memory mapped devices,
* and not every BIOS gives us a correct memory map.
*/
const uintptr_t KERNEL_SPACE = 0x100000;
/*! \brief Border between Kernel and User space
* Memory below this border (starting by MINIMUM) is for kernel (which is
* identity mapped), memory above for user space.
* Let's choose 64 MB since this should be enough for the kernel.
*/
const uintptr_t USER_SPACE = 0x4000000;

55
kernel/memory/page.h Normal file
View File

@@ -0,0 +1,55 @@
#pragma once
#include "../types.h"
namespace Page {
/*! \brief Page Bits
* We use the least significant 12 Bits
*/
const uintptr_t BITS = 12;
/*! \brief Page size
* We go with 2^12 = 4K
*/
const uintptr_t SIZE = 1 << BITS;
/*! \brief Mask for Page
*/
const uintptr_t MASK = SIZE - 1;
/*! \brief Round to next (upper) page aligned address
* \param address memory address
* \return nearest ceiling page aligned address
*/
template <typename T>
T ceil(T address) {
return (address + MASK) & (~MASK);
}
/*! \brief Round to last (lower) page aligned address
* \param address memory address
* \return nearest floor page aligned address
*/
template <typename T>
T floor(T ptr) {
return ptr & (~MASK);
}
/*! \brief Get offset in page
* \param address memory address
* \return offset
*/
template <typename T>
T offset(T ptr) {
return ptr & MASK;
}
/*! \brief Check if address is page aligned
* \param address memory address
* \return true if page aligned address
*/
template <typename T>
bool aligned(T ptr) {
return offset(ptr) == 0;
}
} // namespace Page

View File

@@ -0,0 +1,49 @@
#include "memory/pagefault.h"
#include "arch/core.h"
#include "arch/core_interrupt.h"
#include "arch/idt.h"
#include "debug/output.h"
#include "memory/config.h"
namespace PageFault {
union ErrorCode {
uint32_t value;
struct {
uint32_t present : 1; ///< was the page present?
uint32_t write : 1; ///< was the access a write?
uint32_t usermode : 1; ///< was it in user mode?
uint32_t reserved : 1; ///< reserved bit violation
uint32_t instruction : 1; ///< was it caused by instruction fetch?
uint32_t : 0;
} __attribute__((packed));
explicit ErrorCode(uint32_t value) : value(value) {}
};
assert_size(ErrorCode, 4);
[[gnu::interrupt]] static void pagefault_handler(InterruptContext *context,
uint64_t err) {
PageFault::ErrorCode error(err);
// Get the faulting address
uintptr_t virt;
asm volatile("mov %%cr2, %0" : "=r"(virt));
DBG << "Page fault at " << hex << virt << dec << endl;
// show page fault message
DBG << "PAGEFAULT: " << hex << virt << ":" << dec << error.present
<< error.write << error.usermode << error.reserved << error.instruction
<< " @ " << hex << context->ip << endl;
Core::die();
}
void init() {
IDT::set(Core::Interrupt::Vector::PAGE_FAULT,
IDT::InterruptDescriptor::ReturningWithError(pagefault_handler));
}
} // namespace PageFault

12
kernel/memory/pagefault.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
#include "../debug/assert.h"
#include "../interrupt/handlers.h"
#include "../types.h"
/*! \brief Page Fault Handler
*/
namespace PageFault {
/*! \brief Install page fault handler
*/
void init();
} // namespace PageFault