feat: pmm
This commit is contained in:
@@ -15,6 +15,7 @@ add_executable(kernel
|
||||
src/modules/gdt.c
|
||||
src/modules/idt.c
|
||||
src/modules/interrupts.c
|
||||
src/modules/pmm.c
|
||||
src/modules/memory.c
|
||||
src/modules/serial.c
|
||||
src/modules/console.c
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
#include "types.h"
|
||||
|
||||
#define MAX(a, b) ({ \
|
||||
auto _a = (a); \
|
||||
auto _b = (b); \
|
||||
_a > _b ? _a : _b; \
|
||||
})
|
||||
|
||||
static inline int abs(int n) {
|
||||
return (n < 0) ? -n : n;
|
||||
}
|
||||
|
||||
static inline i64 i64abs(i64 n) {
|
||||
return (n < 0) ? -n : n;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
#define PANIC_H
|
||||
#include "types.h"
|
||||
|
||||
__attribute__((noreturn)) void panic(Registers *regs);
|
||||
__attribute__((noreturn)) void panic_exception(Registers *regs);
|
||||
__attribute__((noreturn)) void panic(const char* msg);
|
||||
|
||||
extern const char* exception_messages[];
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef PMM_H
|
||||
#define PMM_H
|
||||
|
||||
#include "types.h"
|
||||
#include "../common/bootinfo.h"
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
#define BLOCKS_PER_BYTE 8
|
||||
|
||||
#define BITMAP_BYTE_INDEX(addr) ((addr / PAGE_SIZE) / BLOCKS_PER_BYTE)
|
||||
#define BITMAP_BIT_OFFSET(addr) ((addr / PAGE_SIZE) % BLOCKS_PER_BYTE)
|
||||
#define BITMAP_TEST(bitmap, addr) (bitmap[BITMAP_BYTE_INDEX(addr)] & (1 << BITMAP_BIT_OFFSET(addr)))
|
||||
#define BITMAP_SET(bitmap, addr) (bitmap[BITMAP_BYTE_INDEX(addr)] |= (1 << BITMAP_BIT_OFFSET(addr)))
|
||||
#define BITMAP_UNSET(bitmap, addr) (bitmap[BITMAP_BYTE_INDEX(addr)] &= ~(1 << BITMAP_BIT_OFFSET(addr)))
|
||||
|
||||
void pmm_init(BI_MemoryMap mmap);
|
||||
u8* get_bitmap();
|
||||
|
||||
#endif
|
||||
@@ -20,4 +20,32 @@ typedef struct {
|
||||
u64 rip, cs, rflags, rsp, ss; // Pushed by CPU
|
||||
} Registers;
|
||||
|
||||
typedef struct {
|
||||
u32 type;
|
||||
u32 pad;
|
||||
u64 physical_start;
|
||||
u64 virtual_start;
|
||||
u64 number_of_pages;
|
||||
u64 attribute;
|
||||
} __attribute__((packed)) efi_memory_descriptor_k;
|
||||
|
||||
typedef enum {
|
||||
EfiReservedMemoryType,
|
||||
EfiLoaderCode,
|
||||
EfiLoaderData,
|
||||
EfiBootServicesCode,
|
||||
EfiBootServicesData,
|
||||
EfiRuntimeServicesCode,
|
||||
EfiRuntimeServicesData,
|
||||
EfiConventionalMemory,
|
||||
EfiUnusableMemory,
|
||||
EfiACPIReclaimMemory,
|
||||
EfiACPIMemoryNVS,
|
||||
EfiMemoryMappedIO,
|
||||
EfiMemoryMappedIOPortSpace,
|
||||
EfiPalCode,
|
||||
EfiPersistentMemory,
|
||||
EfiMaxMemoryType
|
||||
} EFI_MEMORY_TYPE;
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,7 @@ ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x100000;
|
||||
_kernel_start = .;
|
||||
|
||||
.text : {
|
||||
*(.text.entry)
|
||||
@@ -26,6 +27,9 @@ SECTIONS
|
||||
*(.stack)
|
||||
}
|
||||
|
||||
. = ALIGN(4096);
|
||||
_kernel_end = .;
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.note*)
|
||||
*(.comment*)
|
||||
|
||||
+14
-4
@@ -1,20 +1,25 @@
|
||||
#include "../../common/bootinfo.h"
|
||||
#include "console.h"
|
||||
#include "types.h"
|
||||
|
||||
#include "shitgui.h"
|
||||
#include "serial.h"
|
||||
#include "console.h"
|
||||
#include "panic.h" // IWYU pragma: keep
|
||||
#include "../data/logo.h"
|
||||
|
||||
#include "gdt.h"
|
||||
#include "idt.h"
|
||||
#include "pmm.h"
|
||||
|
||||
#include "../data/logo.h"
|
||||
|
||||
|
||||
int rectest(int a) {
|
||||
volatile int b = a + 1;
|
||||
return rectest(b * 2);
|
||||
}
|
||||
|
||||
extern u64 _kernel_end;
|
||||
|
||||
void kmain(Bootinfo* info) {
|
||||
u32 *fb = (u32*)info->framebuffer.base;
|
||||
if (!fb) return;
|
||||
@@ -42,8 +47,13 @@ void kmain(Bootinfo* info) {
|
||||
kprintf("Welcome to ^ptermOS^0!!!\n");
|
||||
SG_Point text_normal_point = {0, 120}; // not nice to hardcode nums like that but we have what we have
|
||||
console_set_cursor_pos(&text_normal_point);
|
||||
|
||||
pmm_init(info->mem);
|
||||
|
||||
kprintf("MemoryMap located at ^g%x^0; \nMemory map size is ^g%x^0\n", (u64)info->mem.map, (u64)info->mem.map_size);
|
||||
kprintf("MemoryMap located at ^g%x^0 (^r%X^0); \
|
||||
\nMemory map size is ^g%x^0\
|
||||
\nKernel ends at ^g%x^0\
|
||||
\nBITMAP located at ^g%x^0", (u64)info->mem.map, (u64)info->mem.map,(u64)info->mem.map_size, &_kernel_end, get_bitmap());
|
||||
|
||||
// kfetch();
|
||||
|
||||
@@ -52,7 +62,7 @@ void kmain(Bootinfo* info) {
|
||||
|
||||
// rectest(0);
|
||||
|
||||
// __asm__("ud2"); // panic :(
|
||||
// __asm__("ud2"); // panic :(
|
||||
|
||||
while (1) { __asm__("hlt"); }
|
||||
}
|
||||
@@ -7,8 +7,13 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
#define COLOR_RED 0xFF5555
|
||||
#define COLOR_VERYRED 0xFF0000
|
||||
#define COLOR_GREEN 0x08bf39
|
||||
#define COLOR_VERYGREEN 0x00FF00
|
||||
#define COLOR_TURQUOISE 0x5effaf
|
||||
#define COLOR_BLUE 0x5555FF
|
||||
#define COLOR_VERYBLUE 0x0000FF
|
||||
#define COLOR_LIGHTBLUE 0x3890e8
|
||||
#define COLOR_YELLOW 0xFFFF55
|
||||
#define COLOR_CYAN 0x55FFFF
|
||||
#define COLOR_MAGENTA 0xFF55FF
|
||||
@@ -98,24 +103,29 @@ static void print_dec(const i64 n) {
|
||||
}
|
||||
}
|
||||
|
||||
static void print_hex(u64 u) {
|
||||
static void print_hex(u64 u, u8 padding) {
|
||||
console_putc('0');
|
||||
console_putc('x');
|
||||
|
||||
if (u == 0) {
|
||||
console_putc('0');
|
||||
for (i32 i = 1; i < padding; i++) console_putc('0');
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[16];
|
||||
char buffer[16] = {0};
|
||||
i32 i = 0;
|
||||
|
||||
while (u > 0) {
|
||||
do {
|
||||
i32 digit = u % 16;
|
||||
if (digit < 10) { buffer[i] = digit + '0'; }
|
||||
else { buffer[i] = digit - 10 + 'A'; }
|
||||
if (digit < 10) buffer[i++] = digit + '0';
|
||||
else buffer[i++] = digit - 10 + 'A';
|
||||
u /= 16;
|
||||
i++;
|
||||
} while (u > 0);
|
||||
|
||||
while(i < padding) {
|
||||
console_putc('0');
|
||||
padding--;
|
||||
}
|
||||
|
||||
while (--i >= 0) {
|
||||
@@ -123,6 +133,7 @@ static void print_hex(u64 u) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void kprintf(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
@@ -149,9 +160,14 @@ void kprintf(const char *fmt, ...) {
|
||||
}
|
||||
case 'x': {
|
||||
u64 num = va_arg(args, u64);
|
||||
print_hex(num);
|
||||
print_hex(num, 0);
|
||||
break;
|
||||
}
|
||||
case 'X' : {
|
||||
u64 num = va_arg(args, u64);
|
||||
print_hex(num, 16);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
console_putc(fmt[i]);
|
||||
break;
|
||||
@@ -161,8 +177,13 @@ void kprintf(const char *fmt, ...) {
|
||||
i++;
|
||||
switch (fmt[i]) {
|
||||
case 'r': console_set_color(COLOR_RED); break;
|
||||
case 'R': console_set_color(COLOR_VERYRED); break;
|
||||
case 'g': console_set_color(COLOR_GREEN); break;
|
||||
case 'G': console_set_color(COLOR_VERYGREEN); break;
|
||||
case 't': console_set_color(COLOR_TURQUOISE); break;
|
||||
case 'b': console_set_color(COLOR_BLUE); break;
|
||||
case 'B': console_set_color(COLOR_VERYBLUE); break;
|
||||
case 'l': console_set_color(COLOR_LIGHTBLUE); break;
|
||||
case 'y': console_set_color(COLOR_YELLOW); break;
|
||||
case 'c': console_set_color(COLOR_CYAN); break;
|
||||
case 'm': console_set_color(COLOR_MAGENTA); break;
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
#include "types.h"
|
||||
|
||||
void isr_handler_c(Registers *regs) {
|
||||
panic(regs);
|
||||
panic_exception(regs);
|
||||
}
|
||||
+47
-25
@@ -5,7 +5,6 @@
|
||||
#include "shitgui.h"
|
||||
|
||||
const char* fun_messages[] = {
|
||||
"Ooops! All red!",
|
||||
"Execution finished abnormally with code: 0x_x",
|
||||
"It's definitely your fault.",
|
||||
"No more Roblox!",
|
||||
@@ -28,12 +27,12 @@ const char* fun_messages[] = {
|
||||
"Code have been eaten by Aliens",
|
||||
"That's all, folks!",
|
||||
"Raiden, answer me, Raiden, respond! Raiden?! RAIDEEEEEEEEEN!",
|
||||
"Fatal error has been occurred. Your device will be terminated in 30 seconds.",
|
||||
"Fatal error has been occurred.\n\t\t\t\t Your device will be terminated in 30 seconds.",
|
||||
"I'll be back",
|
||||
"Hastla la vista, baby",
|
||||
"Ti chego mne tut nagovoril...",
|
||||
"Your access has been denied because of your region. Please, use Chultem VPN and try again later.",
|
||||
"Fatal error has been occurred. Your device will be transformed into Niva in a few seconds.",
|
||||
"Your access has been denied because of your region.\n\t\t\t\tPlease, use Chultem VPN and try again later.",
|
||||
"Fatal error has been occurred. \n\t\t\t\tYour device will be transformed into Niva in a few seconds.",
|
||||
"Have you tried turning it off and on again?",
|
||||
"Put it in rice maybe?",
|
||||
"Just hit the monitor, it usually helps",
|
||||
@@ -82,8 +81,14 @@ const char* exception_messages[] = {
|
||||
"Reserved"
|
||||
};
|
||||
|
||||
__attribute__((noreturn)) void panic(Registers *regs) {
|
||||
console_clear(0xFF0000);
|
||||
__attribute__((noreturn)) void die() {
|
||||
while (1) {
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
}
|
||||
|
||||
void draw_panic_bg() {
|
||||
console_clear(0x101010);
|
||||
console_set_color(0xFFFFFF);
|
||||
|
||||
SG_Point p = console_get_dimensions();
|
||||
@@ -97,32 +102,49 @@ __attribute__((noreturn)) void panic(Registers *regs) {
|
||||
u8 rand_num = shitrand() % msg_count;
|
||||
|
||||
kprintf("\n\n");
|
||||
kprintf("\t\t\t\tKERNEL PANIC :( \n");
|
||||
kprintf("\t\t\t\t^tKERNEL PANIC^w :( \n");
|
||||
kprintf("\t\t--------------------------------\n");
|
||||
kprintf("\t\t\t\t%s\n", fun_messages[rand_num]);
|
||||
kprintf("\t\t\t\t^r%s^w\n", fun_messages[rand_num]);
|
||||
kprintf("\t\t--------------------------------\n");
|
||||
kprintf("\t\tCPU EXCEPTION: %s (%d)\n", exception_messages[regs->int_no], regs->int_no);
|
||||
if (regs->err_code) kprintf("\t\tError Code: %x\n", regs->err_code);
|
||||
kprintf("\t\tInstruction Pointer (RIP): %x\n", regs->rip);
|
||||
kprintf("\t\tCode Segment (CS): %x\n", regs->cs);
|
||||
kprintf("\t\tFlags (RFLAGS): %x\n", regs->rflags);
|
||||
kprintf("\t\tStack Pointer (RSP): %x\n", regs->rsp);
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void panic_exception(Registers *regs) {
|
||||
draw_panic_bg();
|
||||
|
||||
kprintf("\t\t^yCPU EXCEPTION^w: ^m%s^w (%d)\n", exception_messages[regs->int_no], regs->int_no);
|
||||
if (regs->err_code) kprintf("\t\t^yError Code^w: %X\n", regs->err_code);
|
||||
kprintf("\t\t^yInstruction Pointer^w (^yRIP^w): %X\n", regs->rip);
|
||||
kprintf("\t\t^yCode Segment^w (^yCS^w): %X\n", regs->cs);
|
||||
kprintf("\t\t^yFlags^w (^yRFLAGS^w): %X\n", regs->rflags);
|
||||
kprintf("\t\t^yStack Pointer^w (^yRSP^w): %X\n", regs->rsp);
|
||||
if (regs->int_no == 14) {
|
||||
u64 cr2;
|
||||
__asm__ volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||
kprintf("\t\tFaulting Address (CR2): %x\n", cr2);
|
||||
kprintf("\t\t^yFaulting Address^w (^yCR2^w): %X\n", cr2);
|
||||
}
|
||||
kprintf("\t\t--------------------------------\n");
|
||||
kprintf("\t\t\t\tREGSISTERS\n");
|
||||
kprintf("\t\t\t\t^yREGSISTERS^w\n");
|
||||
kprintf("\t\t--------------------------------\n");
|
||||
kprintf("\t\tRAX=%x, RBX=%x, RCX=%x, RDX=%x\n", regs->rax, regs->rbx, regs->rcx, regs->rdx);
|
||||
kprintf("\t\tRSI=%x, RDI=%x, RBP=%x, R8=%x\n", regs->rsi, regs->rdi, regs->rbp, regs->r8);
|
||||
kprintf("\t\tR9=%x, R10=%x, R11=%x, R12=%x\n", regs->r9, regs->r10, regs->r11, regs->r12);
|
||||
kprintf("\t\tR13=%x, R14=%x, R15=%x\n", regs->r13, regs->r14, regs->r15);
|
||||
kprintf("\t\t^yRAX^w=%X, ^yRBX^w=%X\n", regs->rax, regs->rbx);
|
||||
kprintf("\t\t^yRCX^w=%X, ^yRDX^w=%X\n", regs->rcx, regs->rdx);
|
||||
kprintf("\t\t^yRSI^w=%X, ^yRDI^w=%X\n", regs->rsi, regs->rdi);
|
||||
kprintf("\t\t^yRBP^w=%X, ^yR8^w =%X\n", regs->rbp, regs->r8);
|
||||
kprintf("\t\t^yR9^w =%X, ^yR10^w=%X \n", regs->r9, regs->r10);
|
||||
kprintf("\t\t^yR11^w=%X, ^yR12^w=%X\n", regs->r11, regs->r12);
|
||||
kprintf("\t\t^yR13^w=%X, ^yR14^w=%X\n", regs->r13, regs->r14);
|
||||
kprintf("\t\t^yR15^w=%X\n",regs->r15);
|
||||
kprintf("\t\t--------------------------------\n");
|
||||
kprintf("\t\t\t\tSystem halted.\n");
|
||||
kprintf("\t\t\t\t^tSystem halted.^w\n");
|
||||
|
||||
die();
|
||||
}
|
||||
|
||||
while (1) {
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
}
|
||||
__attribute__((noreturn)) void panic(const char* msg) {
|
||||
draw_panic_bg();
|
||||
|
||||
kprintf("\t\t^yReason^w: %s\n", msg);
|
||||
kprintf("\t\t--------------------------------\n");
|
||||
kprintf("\t\t\t\t^tSystem halted.^w\n");
|
||||
|
||||
die();
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
#include "pmm.h"
|
||||
#include "bootinfo.h"
|
||||
#include "panic.h"
|
||||
#include "types.h"
|
||||
#include "memory.h" // IWYU pragma: keep // clangd is stupid af
|
||||
#include "math.h"
|
||||
|
||||
#define SAFE_SPACE_START_ADDR 0x100000
|
||||
|
||||
extern u64 _kernel_start;
|
||||
extern u64 _kernel_end;
|
||||
|
||||
u8* bitmap = nullptr;
|
||||
u64 bitmap_size_g = 0;
|
||||
|
||||
void pmm_init(BI_MemoryMap mmap) {
|
||||
u64 descriptors_count = mmap.map_size / mmap.descriptor_size;
|
||||
u64 max_physical_address = 0;
|
||||
|
||||
for (u64 i = 0; i < descriptors_count; i++) {
|
||||
efi_memory_descriptor_k* descriptor = (efi_memory_descriptor_k*)((u8*)mmap.map + (i * mmap.descriptor_size));
|
||||
u64 nominee = descriptor->physical_start + descriptor->number_of_pages * PAGE_SIZE;
|
||||
max_physical_address = MAX(nominee, max_physical_address);
|
||||
}
|
||||
|
||||
u64 pages_count = max_physical_address / PAGE_SIZE;
|
||||
u64 bitmap_size = (pages_count + 7) / 8;
|
||||
efi_memory_descriptor_k* desc_to_save = nullptr;
|
||||
|
||||
for (u64 i = 0; i < descriptors_count; i++) {
|
||||
efi_memory_descriptor_k* descriptor = (efi_memory_descriptor_k*)((u8*)mmap.map + (i * mmap.descriptor_size));
|
||||
// scary
|
||||
if ((descriptor->type == EfiConventionalMemory) && \
|
||||
((descriptor->number_of_pages * PAGE_SIZE) >= bitmap_size) && \
|
||||
(descriptor->physical_start >= SAFE_SPACE_START_ADDR)) {
|
||||
desc_to_save = descriptor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (desc_to_save == nullptr) {
|
||||
panic("Not enough RAM for bitmap!");
|
||||
}
|
||||
|
||||
bitmap = (u8*)desc_to_save->physical_start;
|
||||
bitmap_size_g = bitmap_size;
|
||||
|
||||
memset(bitmap, 0xFF, bitmap_size);
|
||||
|
||||
for (u64 i = 0; i < descriptors_count; i++) {
|
||||
efi_memory_descriptor_k* descriptor = (efi_memory_descriptor_k*)((u8*)mmap.map + (i * mmap.descriptor_size));// this shit will haunt my dreams
|
||||
if (descriptor->type != EfiConventionalMemory) continue;
|
||||
u64 start_addr = descriptor->physical_start;
|
||||
u64 end_addr = start_addr + (descriptor->number_of_pages * PAGE_SIZE);
|
||||
for (u64 j = start_addr; j < end_addr; j += PAGE_SIZE) BITMAP_UNSET(bitmap, j);
|
||||
}
|
||||
|
||||
u64 k_start = (u64)&_kernel_start;
|
||||
u64 k_end = (u64)&_kernel_end;
|
||||
|
||||
u64 bitmap_start = (u64)bitmap;
|
||||
u64 bitmap_end = bitmap_start + bitmap_size_g;
|
||||
|
||||
for (u64 i = 0; i < SAFE_SPACE_START_ADDR; i += PAGE_SIZE) BITMAP_SET(bitmap, i); // mem, that addr < 1MB is NOT safe to use on x86
|
||||
for (u64 i = k_start; i < k_end; i += PAGE_SIZE) BITMAP_SET(bitmap, i);
|
||||
for (u64 i = bitmap_start; i < bitmap_end; i += PAGE_SIZE) BITMAP_SET(bitmap, i);
|
||||
}
|
||||
|
||||
void* pmm_alloc_page() {
|
||||
for (u64 i = 0; i < bitmap_size_g; i++) {
|
||||
if (bitmap[i] == 0xFF) continue;
|
||||
for (u64 j = 0; j < 8; j++) {
|
||||
u64 addr = (i * 8 + j) * PAGE_SIZE;
|
||||
if ((bitmap[i] & (1 << j)) == 0) {
|
||||
BITMAP_SET(bitmap, addr);
|
||||
return (void*)addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void pmm_free_page(void* addr) {
|
||||
BITMAP_UNSET(bitmap, (u64)addr);
|
||||
}
|
||||
|
||||
u8* get_bitmap() {
|
||||
return bitmap;
|
||||
}
|
||||
Reference in New Issue
Block a user