Browse Source

wip physallocù

master
Mathieu Serandour 1 year ago
parent
commit
ef01edd9da
  1. 9
      Makefile
  2. 2
      kernel/acpi/acpi.c
  3. 11
      kernel/entry.c
  4. 143
      kernel/memory/physical_allocator.c
  5. 11
      kernel/memory/physical_allocator.h
  6. 6
      kernel/regs.h
  7. 36
      kernel/regs.s

9
Makefile

@ -8,12 +8,13 @@ USED_LOOPBACK := /dev/loop6
LIMINE_INSTALL := ./limine-bootloader/limine-install-linux-x86_64
QEMU_PATH := "/mnt/d/Program Files/qemu/qemu-system-x86_64.exe"
QEMU_ARGS := -monitor stdio -bios "d:/Program Files/qemu/bios/OVMF.fd" -m 256 -vga std -no-reboot
# -bios "d:/Program Files/qemu/bios/OVMF.fd"
QEMU_PATH := qemu-system-x86_64
QEMU_ARGS := -monitor stdio -bios /usr/share/ovmf/OVMF.fd -m 1024 -vga std -no-reboot
run: all
$(QEMU_PATH) $(QEMU_ARGS) -drive format=raw,file=$(HDD_FILE)
$(QEMU_PATH) $(QEMU_ARGS) -drive format=raw,file=$(HDD_FILE),id=disk,if=none \
-device ahci,id=ahci \
-device ide-hd,drive=disk,bus=ahci.0
all: disk

2
kernel/acpi/acpi.c

@ -83,7 +83,7 @@ void read_acpi_tables(const void* rsdp_location) {
assert(madt_parsed);
//assert(hpet_parsed);
assert(fadt_parsed);
assert(pcie_parsed);
//assert(pcie_parsed);
}
static void parse_hpet(const struct HPET* table) {

11
kernel/entry.c

@ -1,6 +1,6 @@
#include <stivale2.h>
#include <stddef.h>
#include <stdint.h>
#include <stivale2.h>
#include "memory/gdt.h"
#include "video/video.h"
@ -13,6 +13,7 @@
#include "int/apic.h"
#include "int/idt.h"
#include "memory/physical_allocator.h"
#define KERNEL_STACK_SIZE 8192
@ -138,9 +139,11 @@ void _start(struct stivale2_struct *stivale2_struct) {
// Let's get the terminal structure tag from the bootloader.
struct stivale2_struct_tag_terminal *term_str_tag;
struct stivale2_struct_tag_terminal* term_str_tag;
struct stivale2_struct_tag_memmap* memmap_tag;
term_str_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_TERMINAL_ID);
memmap_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_MEMMAP_ID);
// Check if the tag was actually found.
if (term_str_tag == NULL) {
// It wasn't found, just hang...
@ -190,6 +193,8 @@ void _start(struct stivale2_struct *stivale2_struct) {
read_acpi_tables((void*)rsdp_location);
kputs("DONE\n");
init_physical_allocator(memmap_tag);
apic_setup_clock();

143
kernel/memory/physical_allocator.c

@ -1,4 +1,9 @@
#include <stdint.h>
#include <stddef.h>
#include <stivale2.h>
#include "../debug/assert.h"
#include "../klib/sprintf.h"
/**
* memory modeling:
* | MR1 | MR2 | //// | MR3 | ....
@ -33,10 +38,142 @@
*
*/
// 64 MB range = 16384 pages
#define MAX_SIZE 16384
// drop the segments that are too small
#define MIN_SIZE 10
//linked list element representing a 64 MB memory region
struct memory_range {
void* base;
size_t length;
struct memory_range* next;
};
struct MR_header {
// number of available blocks for each block size bitmap
uint32_t available[4];
// padding
uint8_t padding[1152 - 16];
uint8_t bitmap_level3[128];
uint8_t bitmap_level2[256];
uint8_t bitmap_level1[512];
uint8_t bitmap_level0[2048];
};
static_assert_equals(sizeof(struct MR_header), 4096);
// 512 x 64MB regions: up to 32 Go of RAM
struct memory_range buffer[512];
// lists of memory ranges: sorted by biggest free range
struct memory_range* mr_lists[4] = {0};
// init memory range as a free range, ready to be allocated
static void init_memory_range(struct memory_range* range, uint64_t addr, size_t length) {
// init the linked list's structure
range->base = addr;
range->length = length;
// init the MR header
struct MR_header* header = (struct MR_header *)addr;
// we use one page per region for the header
header->available[0] = (length-1);
header->available[1] = (length-1) >> 2;
header->available[2] = (length-1) >> 3;
header->available[3] = (length-1) >> 4;
// choose the right linked list to insert the element in
// then insert it at the beginning: so the insertion is O(1)
for(int i = 3; i >= 0; i--) {
if(header->available[3] == 0)
continue;
range->next = mr_lists[i];
mr_lists[i] = range;
break;
}
// zero all the bit maps
memset(((uint8_t*)header)+1152, 0, 2048);
}
void init_physical_allocator(const struct stivale2_struct_tag_memmap* memmap) {
// counter of the number of detected pages
unsigned total_pages = 0;
unsigned j = 0; // index of the current created memory range struct
for(unsigned i = 0; i < memmap->entries; i++) {
const struct stivale2_mmap_entry e = memmap->memmap[i];
// dont take kernel & modules or acpi reclaimable
// memory ranges in account
if(e.type == STIVALE2_MMAP_USABLE ||
e.type == STIVALE2_MMAP_BOOTLOADER_RECLAIMABLE ||
e.type == STIVALE2_MMAP_FRAMEBUFFER) {
// ceil the size to the number of pages
size_t size = (e.length + 4096 - 1) / 4096;
uint64_t base = e.base;
while(size > 0) {
size_t s;// the actual size of the current
if(size > MAX_SIZE)
s = MAX_SIZE;
else if(size < MIN_SIZE)
break;
else
s = size;
struct memory_range* range = &buffer[j++];
init_memory_range(range, base, s);
kprintf("%l16x: %d pages\n", range->base, range->length);
total_pages += s;
size -= s;
base += 0x1000 * s;
}
}
}
kprintf("detected %u MB of memory, %u usable\n", total_pages / 256, (total_pages - j) / 256);
}
// return a MR that fits best the requested size
// it can however not fit it if no MR does
static void getMR(size_t requested_size) {
}
/**
* @brief allocate
*
* @param size
* @return void*
* @param size in 4K pages
* @return void* the physical allocated address
*/
void* physalloc(size_t size) {
}
/**
* size is in pages
*
*/
void* physalloc(size_t size);
void physfree(void* virtual_addr, size_t size) {
(void) (virtual_addr + size);
}

11
kernel/memory/physical_allocator.h

@ -0,0 +1,11 @@
#pragma once
#include <stddef.h>
struct stivale2_struct_tag_memmap;
// init the physical allocator with the stivale2 memory map
void init_physical_allocator(const struct stivale2_struct_tag_memmap* memmap);
void* physalloc(size_t size);
void physfree(void* virtual_addr, size_t size);

6
kernel/regs.h

@ -1,6 +1,4 @@
#ifndef REGS_H
#define REGS_H
#pragma once
#include <stdint.h>
uint64_t _ds(void);
@ -9,5 +7,3 @@ uint64_t _cs(void);
uint64_t _es(void);
uint64_t _fs(void);
uint64_t _gs(void);
#endif//REGS_H

36
kernel/regs.s

@ -8,6 +8,12 @@
[global outb]
[global get_rflags]
[global set_rflags]
[global set_cr0]
[global get_cr0]
[global _cr2]
[global _cr3]
[global set_cr4]
[global get_cr4]
[global _ltr]
[global read_msr]
[global write_msr]
@ -45,6 +51,36 @@ _fs:
ret
; void get_cr0(uint64_t cr3)
get_cr0:
mov rax, cr0
ret
; uint64_t set_cr0(void)
set_cr0:
mov cr0, rdi
ret
; uint64_t get_cr2(void)
_cr2:
mov rax, cr2
ret
; void cr3(uint64_t cr3)
_cr3:
mov cr3, rax
ret
; void get_cr4(uint64_t cr3)
get_cr4:
mov rax, cr4
ret
; uint64_t set_cr4(void)
set_cr4:
mov cr4, rdi
ret
get_rflags:
pushfq
pop rax

Loading…
Cancel
Save