physical mem manager
This commit is contained in:
parent
3e127f4686
commit
269f7f6845
2
Makefile
2
Makefile
|
@ -20,7 +20,7 @@ ISO := Hazel.iso
|
||||||
CFLAGS := -ffreestanding -Wall -Wextra -Werror -I $(INCLUDEDIR) -I lib
|
CFLAGS := -ffreestanding -Wall -Wextra -Werror -I $(INCLUDEDIR) -I lib
|
||||||
LDFLAGS := -ffreestanding -nostdlib -lgcc -T kernel/kernel.ld
|
LDFLAGS := -ffreestanding -nostdlib -lgcc -T kernel/kernel.ld
|
||||||
QEMUFLAGS := -cdrom $(BUILDDIR)/$(ISO) \
|
QEMUFLAGS := -cdrom $(BUILDDIR)/$(ISO) \
|
||||||
-d int \
|
-m 512M \
|
||||||
-serial stdio
|
-serial stdio
|
||||||
|
|
||||||
$(BUILDDIR)/$(KIMG): $(KOBJ) $(LOBJ)
|
$(BUILDDIR)/$(KIMG): $(KOBJ) $(LOBJ)
|
||||||
|
|
|
@ -8,8 +8,10 @@
|
||||||
#define CHECK_FLAG(x, n) (x & (1<<n))
|
#define CHECK_FLAG(x, n) (x & (1<<n))
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
multiboot_memory_map_t *mem_map;
|
multi_mmap_t *multi_mmap;
|
||||||
uint32_t mem_map_len;
|
uint32_t multi_mmap_size;
|
||||||
|
uint32_t *mmap;
|
||||||
|
uint32_t mmap_size;
|
||||||
log_method_t log_method;
|
log_method_t log_method;
|
||||||
uint64_t ticks;
|
uint64_t ticks;
|
||||||
} kernel_ctx_t;
|
} kernel_ctx_t;
|
||||||
|
|
26
include/kernel/mem.h
Normal file
26
include/kernel/mem.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef HAZEL_MEM_H_
|
||||||
|
#define HAZEL_MEM_H_
|
||||||
|
|
||||||
|
#include <kernel/kernel.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define KERNEL_START 0x1000000 // 1 MiB
|
||||||
|
#define KERNEL_SIZE 0xC800 // 50 KiB
|
||||||
|
#define BLOCK_SIZE 4096
|
||||||
|
#define BITS 32
|
||||||
|
|
||||||
|
uint8_t mmap_init(void);
|
||||||
|
void mmap_set_block(int block);
|
||||||
|
void mmap_free_block(int block);
|
||||||
|
void *mmap_find_first_free_block(void);
|
||||||
|
void *mmap_block_to_physical(int block);
|
||||||
|
|
||||||
|
void memset(void *s, int c, uint32_t len);
|
||||||
|
void memcpy(void *dest, void *src, int n);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *data;
|
||||||
|
void *next;
|
||||||
|
} linked_mem_t;
|
||||||
|
|
||||||
|
#endif
|
|
@ -40,7 +40,7 @@ struct multiboot_mmap_entry
|
||||||
#define MULTIBOOT_MEMORY_BADRAM 5
|
#define MULTIBOOT_MEMORY_BADRAM 5
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
|
typedef struct multiboot_mmap_entry multi_mmap_t;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,7 +43,6 @@ _start:
|
||||||
mov esp, stack_bottom
|
mov esp, stack_bottom
|
||||||
mov ebp, esp
|
mov ebp, esp
|
||||||
push ebx
|
push ebx
|
||||||
and esp, 0xfffffff0
|
|
||||||
extern kernel
|
extern kernel
|
||||||
call kernel
|
call kernel
|
||||||
cli
|
cli
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <kernel/kernel.h>
|
#include <kernel/kernel.h>
|
||||||
#include <kernel/multiboot.h>
|
#include <kernel/multiboot.h>
|
||||||
|
#include <kernel/mem.h>
|
||||||
#include <kernel/serial.h>
|
#include <kernel/serial.h>
|
||||||
#include <kernel/idt.h>
|
#include <kernel/idt.h>
|
||||||
#include <kernel/pic.h>
|
#include <kernel/pic.h>
|
||||||
|
@ -28,13 +29,15 @@ void sleep(int delay) {
|
||||||
void kernel(multiboot_info_t *info) {
|
void kernel(multiboot_info_t *info) {
|
||||||
if (!CHECK_FLAG(info->flags, 6)) goto halt; // Memory map
|
if (!CHECK_FLAG(info->flags, 6)) goto halt; // Memory map
|
||||||
if (!CHECK_FLAG(info->flags, 12)) goto halt; // VBE data
|
if (!CHECK_FLAG(info->flags, 12)) goto halt; // VBE data
|
||||||
ctx.mem_map = (multiboot_memory_map_t *)info->memmapaddress;
|
ctx.multi_mmap = (multi_mmap_t *)info->memmapaddress;
|
||||||
ctx.mem_map_len = info->memmaplength;
|
ctx.multi_mmap_size = info->memmaplength;
|
||||||
|
|
||||||
if (serial_port_init(COM1)) ctx.log_method = LOG_COM1;
|
if (serial_port_init(COM1)) ctx.log_method = LOG_COM1;
|
||||||
|
|
||||||
LOG("Kernel log being sent to COM1\n");
|
LOG("Kernel log being sent to COM1\n");
|
||||||
|
|
||||||
|
if (!mmap_init()) goto halt;
|
||||||
|
LOG("%d bytes of RAM detected\nCreated a %d byte large physical memory map at 0x%08X\n", ctx.mmap_size*BLOCK_SIZE*8, ctx.mmap_size, ctx.mmap);
|
||||||
|
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
idt_encode_entry(idt, i, isr_stub_table[i], GDT_SEGMENT_SELECTOR(1, 0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT);
|
idt_encode_entry(idt, i, isr_stub_table[i], GDT_SEGMENT_SELECTOR(1, 0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT);
|
||||||
}
|
}
|
||||||
|
|
127
kernel/mem.c
Normal file
127
kernel/mem.c
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
#include <kernel/mem.h>
|
||||||
|
|
||||||
|
extern kernel_ctx_t ctx;
|
||||||
|
|
||||||
|
// TODO: Fix this, it wastes memory when switching regions because the previous offset isnt being subtracted
|
||||||
|
// Should work fine for now?
|
||||||
|
void *mmap_block_to_physical(int block) {
|
||||||
|
uint32_t offset = block * BLOCK_SIZE;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < ctx.multi_mmap_size; i++) {
|
||||||
|
struct multiboot_mmap_entry entry = ctx.multi_mmap[i];
|
||||||
|
if (entry.type != MULTIBOOT_MEMORY_AVAILABLE) continue;
|
||||||
|
|
||||||
|
uint32_t len = (uint32_t)(entry.len_low | entry.len_high);
|
||||||
|
uint32_t addr = (uint32_t)(entry.addr_low | entry.addr_high);
|
||||||
|
if (len > offset)
|
||||||
|
return (void *)(addr + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void memset(void *s, int c, uint32_t len) {
|
||||||
|
unsigned char *dst = s;
|
||||||
|
while (len > 0) {
|
||||||
|
*dst = (unsigned char) c;
|
||||||
|
dst++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void memcpy(void *dest, void *src, int n) {
|
||||||
|
for (int i=0; i<n; i++)
|
||||||
|
((char *)dest)[i] = ((char *)src)[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t mmap_init(void) {
|
||||||
|
// Calculate the number of bytes available to us
|
||||||
|
uint64_t available_bytes = 0;
|
||||||
|
for (uint32_t i = 0; i < ctx.multi_mmap_size; i++) {
|
||||||
|
struct multiboot_mmap_entry entry = ctx.multi_mmap[i];
|
||||||
|
if (entry.type != MULTIBOOT_MEMORY_AVAILABLE) continue;
|
||||||
|
|
||||||
|
uint32_t len = (uint32_t)(entry.len_low | entry.len_high);
|
||||||
|
available_bytes += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.mmap_size = available_bytes / BLOCK_SIZE / 8;
|
||||||
|
|
||||||
|
// Loop again to find the first region with enough space to hold the memory map
|
||||||
|
int index = -1;
|
||||||
|
for (uint32_t i = 0; i < ctx.multi_mmap_size; i++) {
|
||||||
|
struct multiboot_mmap_entry entry = ctx.multi_mmap[i];
|
||||||
|
if (entry.type != MULTIBOOT_MEMORY_AVAILABLE) continue;
|
||||||
|
|
||||||
|
uint32_t len = (uint32_t)(entry.len_low | entry.len_high);
|
||||||
|
if (len > ctx.mmap_size) {
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == -1) return 0; // Failed
|
||||||
|
|
||||||
|
// Create map
|
||||||
|
struct multiboot_mmap_entry entry = ctx.multi_mmap[index];
|
||||||
|
uint32_t addr = (uint32_t)(entry.addr_low | entry.addr_high);
|
||||||
|
ctx.mmap = (uint32_t *)addr;
|
||||||
|
// Zero the map
|
||||||
|
memset(ctx.mmap, 0, ctx.mmap_size);
|
||||||
|
// Reserve the blocks that hold the memory map + 1
|
||||||
|
uint32_t blocks_to_set = ctx.mmap_size / BLOCK_SIZE + 1;
|
||||||
|
for (uint32_t i = 0; i < blocks_to_set; i++)
|
||||||
|
mmap_set_block(i);
|
||||||
|
// Reserve the kernel space
|
||||||
|
int bits = ctx.mmap_size * 8;
|
||||||
|
for (int i = 0; i < bits; i++) {
|
||||||
|
uint32_t phys = (uint32_t)mmap_block_to_physical(i);
|
||||||
|
if (phys > KERNEL_START && phys < KERNEL_START + KERNEL_SIZE)
|
||||||
|
mmap_set_block(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmap_set_block(int block) {
|
||||||
|
int index = block / BITS;
|
||||||
|
int bit = block;
|
||||||
|
if (block >= BITS)
|
||||||
|
bit -= BITS;
|
||||||
|
|
||||||
|
uint32_t mask = 1 << bit;
|
||||||
|
if (!(ctx.mmap[index] & mask))
|
||||||
|
ctx.mmap[index] |= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmap_free_block(int block) {
|
||||||
|
int index = block / BITS;
|
||||||
|
int bit = block;
|
||||||
|
if (block >= BITS)
|
||||||
|
bit -= BITS;
|
||||||
|
|
||||||
|
uint32_t mask = 1 << bit;
|
||||||
|
if (ctx.mmap[index] & mask)
|
||||||
|
ctx.mmap[index] ^= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *mmap_find_first_free_block(void) {
|
||||||
|
int bits = ctx.mmap_size * 8;
|
||||||
|
for (int i = 0; i < bits; i++) {
|
||||||
|
int index = i / BITS;
|
||||||
|
int bit = i;
|
||||||
|
if (i >= BITS)
|
||||||
|
bit -= BITS;
|
||||||
|
|
||||||
|
uint32_t mask = 1 << bit;
|
||||||
|
|
||||||
|
uint32_t dword = ctx.mmap[index];
|
||||||
|
if (!(dword & mask)) {
|
||||||
|
mmap_set_block(i);
|
||||||
|
return mmap_block_to_physical(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user