feat: pmm

This commit is contained in:
Karina
2025-12-26 07:18:02 +04:00
parent 9dafc29aa4
commit 412c3bacc0
13 changed files with 243 additions and 41 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ add_subdirectory(kernel)
find_program(MCOPY_EXE mcopy) find_program(MCOPY_EXE mcopy)
find_program(MKFS_EXE mkfs.fat) find_program(MKFS_EXE mkfs.fat)
find_program(QEMU_EXE qemu-system-x86_64) find_program(QEMU_EXE qemu-system-x86_64)
set(OVMF_PATH "/usr/share/qemu/ovmf-x86_64.bin" CACHE FILEPATH "Path to OVMF bios") set(OVMF_PATH "/usr/share/edk2/ovmf/OVMF_CODE.fd" CACHE FILEPATH "Path to OVMF bios")
if(MCOPY_EXE AND MKFS_EXE) if(MCOPY_EXE AND MKFS_EXE)
set(IMG_FILE "${CMAKE_BINARY_DIR}/termOS.img") set(IMG_FILE "${CMAKE_BINARY_DIR}/termOS.img")
+1 -1
View File
@@ -44,7 +44,7 @@ int main()
uint64_t kernel_size = file_info->FileSize; uint64_t kernel_size = file_info->FileSize;
uintn_t kernel_size_read = (uintn_t)kernel_size; uintn_t kernel_size_read = (uintn_t)kernel_size;
efi_physical_address_t kernel_addr = 0x100000; efi_physical_address_t kernel_addr = 0x100000;
uintn_t pages = (kernel_size + 0xFFF) / 0x1000; uintn_t pages = (kernel_size + 0xFFF) / 0x1000 + 32;
status = gBS->AllocatePages(AllocateAddress, EfiLoaderData, pages, &kernel_addr); status = gBS->AllocatePages(AllocateAddress, EfiLoaderData, pages, &kernel_addr);
if (EFI_ERROR(status)) { if (EFI_ERROR(status)) {
+1
View File
@@ -15,6 +15,7 @@ add_executable(kernel
src/modules/gdt.c src/modules/gdt.c
src/modules/idt.c src/modules/idt.c
src/modules/interrupts.c src/modules/interrupts.c
src/modules/pmm.c
src/modules/memory.c src/modules/memory.c
src/modules/serial.c src/modules/serial.c
src/modules/console.c src/modules/console.c
+7
View File
@@ -1,5 +1,11 @@
#include "types.h" #include "types.h"
#define MAX(a, b) ({ \
auto _a = (a); \
auto _b = (b); \
_a > _b ? _a : _b; \
})
static inline int abs(int n) { static inline int abs(int n) {
return (n < 0) ? -n : n; return (n < 0) ? -n : n;
} }
@@ -7,3 +13,4 @@ static inline int abs(int n) {
static inline i64 i64abs(i64 n) { static inline i64 i64abs(i64 n) {
return (n < 0) ? -n : n; return (n < 0) ? -n : n;
} }
+2 -1
View File
@@ -3,7 +3,8 @@
#define PANIC_H #define PANIC_H
#include "types.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[]; extern const char* exception_messages[];
+19
View File
@@ -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
+28
View File
@@ -20,4 +20,32 @@ typedef struct {
u64 rip, cs, rflags, rsp, ss; // Pushed by CPU u64 rip, cs, rflags, rsp, ss; // Pushed by CPU
} Registers; } 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 #endif
+4
View File
@@ -3,6 +3,7 @@ ENTRY(_start)
SECTIONS SECTIONS
{ {
. = 0x100000; . = 0x100000;
_kernel_start = .;
.text : { .text : {
*(.text.entry) *(.text.entry)
@@ -26,6 +27,9 @@ SECTIONS
*(.stack) *(.stack)
} }
. = ALIGN(4096);
_kernel_end = .;
/DISCARD/ : { /DISCARD/ : {
*(.note*) *(.note*)
*(.comment*) *(.comment*)
+13 -3
View File
@@ -1,20 +1,25 @@
#include "../../common/bootinfo.h" #include "../../common/bootinfo.h"
#include "console.h"
#include "types.h" #include "types.h"
#include "shitgui.h" #include "shitgui.h"
#include "serial.h" #include "serial.h"
#include "console.h"
#include "panic.h" // IWYU pragma: keep #include "panic.h" // IWYU pragma: keep
#include "../data/logo.h"
#include "gdt.h" #include "gdt.h"
#include "idt.h" #include "idt.h"
#include "pmm.h"
#include "../data/logo.h"
int rectest(int a) { int rectest(int a) {
volatile int b = a + 1; volatile int b = a + 1;
return rectest(b * 2); return rectest(b * 2);
} }
extern u64 _kernel_end;
void kmain(Bootinfo* info) { void kmain(Bootinfo* info) {
u32 *fb = (u32*)info->framebuffer.base; u32 *fb = (u32*)info->framebuffer.base;
if (!fb) return; if (!fb) return;
@@ -43,7 +48,12 @@ void kmain(Bootinfo* info) {
SG_Point text_normal_point = {0, 120}; // not nice to hardcode nums like that but we have what we have 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); console_set_cursor_pos(&text_normal_point);
kprintf("MemoryMap located at ^g%x^0; \nMemory map size is ^g%x^0\n", (u64)info->mem.map, (u64)info->mem.map_size); pmm_init(info->mem);
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(); // kfetch();
+28 -7
View File
@@ -7,8 +7,13 @@
#include <stdarg.h> #include <stdarg.h>
#define COLOR_RED 0xFF5555 #define COLOR_RED 0xFF5555
#define COLOR_VERYRED 0xFF0000
#define COLOR_GREEN 0x08bf39 #define COLOR_GREEN 0x08bf39
#define COLOR_VERYGREEN 0x00FF00
#define COLOR_TURQUOISE 0x5effaf
#define COLOR_BLUE 0x5555FF #define COLOR_BLUE 0x5555FF
#define COLOR_VERYBLUE 0x0000FF
#define COLOR_LIGHTBLUE 0x3890e8
#define COLOR_YELLOW 0xFFFF55 #define COLOR_YELLOW 0xFFFF55
#define COLOR_CYAN 0x55FFFF #define COLOR_CYAN 0x55FFFF
#define COLOR_MAGENTA 0xFF55FF #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('0');
console_putc('x'); console_putc('x');
if (u == 0) { if (u == 0) {
console_putc('0'); console_putc('0');
for (i32 i = 1; i < padding; i++) console_putc('0');
return; return;
} }
char buffer[16]; char buffer[16] = {0};
i32 i = 0; i32 i = 0;
while (u > 0) { do {
i32 digit = u % 16; i32 digit = u % 16;
if (digit < 10) { buffer[i] = digit + '0'; } if (digit < 10) buffer[i++] = digit + '0';
else { buffer[i] = digit - 10 + 'A'; } else buffer[i++] = digit - 10 + 'A';
u /= 16; u /= 16;
i++; } while (u > 0);
while(i < padding) {
console_putc('0');
padding--;
} }
while (--i >= 0) { while (--i >= 0) {
@@ -123,6 +133,7 @@ static void print_hex(u64 u) {
} }
} }
void kprintf(const char *fmt, ...) { void kprintf(const char *fmt, ...) {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
@@ -149,7 +160,12 @@ void kprintf(const char *fmt, ...) {
} }
case 'x': { case 'x': {
u64 num = va_arg(args, u64); 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; break;
} }
default: { default: {
@@ -161,8 +177,13 @@ void kprintf(const char *fmt, ...) {
i++; i++;
switch (fmt[i]) { switch (fmt[i]) {
case 'r': console_set_color(COLOR_RED); break; 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_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_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 'y': console_set_color(COLOR_YELLOW); break;
case 'c': console_set_color(COLOR_CYAN); break; case 'c': console_set_color(COLOR_CYAN); break;
case 'm': console_set_color(COLOR_MAGENTA); break; case 'm': console_set_color(COLOR_MAGENTA); break;
+1 -1
View File
@@ -2,5 +2,5 @@
#include "types.h" #include "types.h"
void isr_handler_c(Registers *regs) { void isr_handler_c(Registers *regs) {
panic(regs); panic_exception(regs);
} }
+45 -23
View File
@@ -5,7 +5,6 @@
#include "shitgui.h" #include "shitgui.h"
const char* fun_messages[] = { const char* fun_messages[] = {
"Ooops! All red!",
"Execution finished abnormally with code: 0x_x", "Execution finished abnormally with code: 0x_x",
"It's definitely your fault.", "It's definitely your fault.",
"No more Roblox!", "No more Roblox!",
@@ -28,12 +27,12 @@ const char* fun_messages[] = {
"Code have been eaten by Aliens", "Code have been eaten by Aliens",
"That's all, folks!", "That's all, folks!",
"Raiden, answer me, Raiden, respond! Raiden?! RAIDEEEEEEEEEN!", "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", "I'll be back",
"Hastla la vista, baby", "Hastla la vista, baby",
"Ti chego mne tut nagovoril...", "Ti chego mne tut nagovoril...",
"Your access has been denied because of your region. Please, use Chultem VPN and try again later.", "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. Your device will be transformed into Niva in a few seconds.", "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?", "Have you tried turning it off and on again?",
"Put it in rice maybe?", "Put it in rice maybe?",
"Just hit the monitor, it usually helps", "Just hit the monitor, it usually helps",
@@ -82,8 +81,14 @@ const char* exception_messages[] = {
"Reserved" "Reserved"
}; };
__attribute__((noreturn)) void panic(Registers *regs) { __attribute__((noreturn)) void die() {
console_clear(0xFF0000); while (1) {
__asm__ volatile ("cli; hlt");
}
}
void draw_panic_bg() {
console_clear(0x101010);
console_set_color(0xFFFFFF); console_set_color(0xFFFFFF);
SG_Point p = console_get_dimensions(); SG_Point p = console_get_dimensions();
@@ -97,32 +102,49 @@ __attribute__((noreturn)) void panic(Registers *regs) {
u8 rand_num = shitrand() % msg_count; u8 rand_num = shitrand() % msg_count;
kprintf("\n\n"); 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--------------------------------\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\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); __attribute__((noreturn)) void panic_exception(Registers *regs) {
kprintf("\t\tCode Segment (CS): %x\n", regs->cs); draw_panic_bg();
kprintf("\t\tFlags (RFLAGS): %x\n", regs->rflags);
kprintf("\t\tStack Pointer (RSP): %x\n", regs->rsp); 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) { if (regs->int_no == 14) {
u64 cr2; u64 cr2;
__asm__ volatile("mov %%cr2, %0" : "=r"(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--------------------------------\n");
kprintf("\t\t\t\tREGSISTERS\n"); kprintf("\t\t\t\t^yREGSISTERS^w\n");
kprintf("\t\t--------------------------------\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\t^yRAX^w=%X, ^yRBX^w=%X\n", regs->rax, regs->rbx);
kprintf("\t\tRSI=%x, RDI=%x, RBP=%x, R8=%x\n", regs->rsi, regs->rdi, regs->rbp, regs->r8); kprintf("\t\t^yRCX^w=%X, ^yRDX^w=%X\n", regs->rcx, regs->rdx);
kprintf("\t\tR9=%x, R10=%x, R11=%x, R12=%x\n", regs->r9, regs->r10, regs->r11, regs->r12); kprintf("\t\t^yRSI^w=%X, ^yRDI^w=%X\n", regs->rsi, regs->rdi);
kprintf("\t\tR13=%x, R14=%x, R15=%x\n", regs->r13, regs->r14, regs->r15); 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--------------------------------\n");
kprintf("\t\t\t\tSystem halted.\n"); kprintf("\t\t\t\t^tSystem halted.^w\n");
while (1) { die();
__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();
} }
+89
View File
@@ -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;
}