From 77ad2ef52c9f9f88a96a7a473223ab61c20f2032 Mon Sep 17 00:00:00 2001 From: Adrien Bourmault Date: Sun, 24 Mar 2019 20:25:11 +0100 Subject: [PATCH] Big enhancement, memory detection ! --- Makefile | 2 +- ProjectTree | 11 +-- build/kernel.ld | 2 + kaleid/include/kernel/base.h | 1 + kaleid/include/kernel/mm.h | 47 +++++++++-- kaleid/include/kernel/multiboot.h | 13 ++- kaleid/kernel/init/init.c | 12 ++- kaleid/kernel/mm/heap.c | 4 +- kaleid/kernel/mm/map.c | 132 ++++++++++++++++++++++++++++-- 9 files changed, 186 insertions(+), 38 deletions(-) diff --git a/Makefile b/Makefile index a5bfb2f..9ffbd33 100644 --- a/Makefile +++ b/Makefile @@ -171,7 +171,7 @@ $(KOBJDIR)/kernel/malloc.o: $(KERNELDIR)/kernel/mm/malloc.c $(KERNELDIR)/include .PHONY: test test: all - @qemu-system-x86_64 -m 5G -hda build/bin/disk.img -d cpu_reset,guest_errors,pcall,int -enable-kvm 2> qemu.log & + @qemu-system-x86_64 -m 5G -mem-prealloc -hda build/bin/disk.img -d cpu_reset,guest_errors,pcall,int -enable-kvm 2> qemu.log & @ndisasm $(BINDIR)/kaleid -o 0x00100000 -b 64 > loader_disasm64.asm @ndisasm $(BINDIR)/kaleid -o 0x00100000 -b 32 > loader_disasm32.asm .PHONY: test32 diff --git a/ProjectTree b/ProjectTree index 74b8d52..03a52e6 100644 --- a/ProjectTree +++ b/ProjectTree @@ -56,15 +56,6 @@ │   │   │   └── loader.o │   │   └── kaleid │   │   ├── kernel -│   │   │   ├── init -│   │   │   │   ├── init.o -│   │   │   │   └── table.o -│   │   │   ├── io -│   │   │   │   ├── cursor.o -│   │   │   │   ├── term.o -│   │   │   │   └── vga.o -│   │   │   ├── ke -│   │   │   │   └── panic.o │   │   │   ├── cpuid.o │   │   │   ├── cursor.o │   │   │   ├── heap.o @@ -167,4 +158,4 @@ ├── qemu.log └── Readme.md -30 directories, 112 files +27 directories, 106 files diff --git a/build/kernel.ld b/build/kernel.ld index ea46357..50a5d81 100644 --- a/build/kernel.ld +++ b/build/kernel.ld @@ -61,6 +61,8 @@ SECTIONS { *(.rodata) /* all rodata sections from all files */ } + kernelEnd = .; + /DISCARD/ : { *(.comment) diff --git a/kaleid/include/kernel/base.h b/kaleid/include/kernel/base.h index e6efe12..9719931 100644 --- a/kaleid/include/kernel/base.h +++ b/kaleid/include/kernel/base.h @@ -108,6 +108,7 @@ struct BootInfo_t void *modulesAddr; //mods_addr char *grubName; //boot_loader_name void *kernelAddr; + void *kernelEndAddr; } btldr; // Informations about drives diff --git a/kaleid/include/kernel/mm.h b/kaleid/include/kernel/mm.h index 49072e0..928dfd8 100644 --- a/kaleid/include/kernel/mm.h +++ b/kaleid/include/kernel/mm.h @@ -22,19 +22,54 @@ // along with OS/K. If not, see . // //----------------------------------------------------------------------------// -#include #include -#define MINIMUM_RAM_SIZE 16 //Mio, the minimum RAM size. +#define MINIMUM_RAM_SIZE 16 // Mio, the minimum RAM size. -// -// Returns a pointer to the first entry of the memory map -// -void *GetMemoryMap(void); +#define AVAILABLE_ZONE 1 // Fully usable RAM zone +#define RESERVED_ZONE 2 // Used by the firmware +#define ACPI_ZONE 3 // Used by ACPI but can be freed +#define NVS_ZONE 4 // Dunno +#define BADRAM_ZONE 5 // Invalid zone because material problem... +#define MAX_ENTRIES 2048 // Max number of memory map entries + +// -------------------------------------------------------------------------- // + +typedef struct MemoryMap_t MemoryMap_t; +typedef struct MapEntry_t MapEntry_t; + +// -------------------------------------------------------------------------- // +// The entry structure of the map +struct MapEntry_t { + void *addr; + size_t length; // in bytes + uint type; // reserved or not +} __attribute__((packed)); + +// the map structure +struct MemoryMap_t { + size_t length; + size_t freeRamSize; + size_t nonfreeRamSize; + MapEntry_t entry[MAX_ENTRIES]; +} __attribute__((packed)); + + + +// -------------------------------------------------------------------------- // // // Initializes the memory map structure // error_t InitMemoryMap(void); +// +// Returns the size of the first available memory zone from the start address pointer +// +size_t GetAvailZoneSize(void *start); + +// +// Returns the first available memory zone from the start address pointer +void *GetFirstAvailZone(void *start); + // -------------------------------------------------------------------------- // diff --git a/kaleid/include/kernel/multiboot.h b/kaleid/include/kernel/multiboot.h index d1f8516..896f23d 100644 --- a/kaleid/include/kernel/multiboot.h +++ b/kaleid/include/kernel/multiboot.h @@ -232,15 +232,12 @@ struct multiboot_color struct multiboot_mmap_entry { uint size; - ullong addr; - ullong len; -#define MULTIBOOT_MEMORY_AVAILABLE 1 -#define MULTIBOOT_MEMORY_RESERVED 2 -#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 -#define MULTIBOOT_MEMORY_NVS 4 -#define MULTIBOOT_MEMORY_BADRAM 5 + uint addr_low; + uint addr_high; + uint len_low; + uint len_high; uint type; -} __attribute__((packed)); +} __attribute__((packed)) __attribute__((aligned (4))); typedef struct multiboot_mmap_entry multiboot_memory_map_t; struct multiboot_mod_list diff --git a/kaleid/kernel/init/init.c b/kaleid/kernel/init/init.c index 94c8034..23bb762 100644 --- a/kaleid/kernel/init/init.c +++ b/kaleid/kernel/init/init.c @@ -22,8 +22,9 @@ // along with OS/K. If not, see . // //----------------------------------------------------------------------------// -#include +#include #include +#include #include // @@ -32,7 +33,8 @@ // void InitBootInfo(multiboot_info_t *mbi) { - extern void MB_header(void); + extern ullong MB_header; + extern ullong kernelEnd; // We need the multiboot structure KalAlwaysAssert(mbi); @@ -43,6 +45,7 @@ void InitBootInfo(multiboot_info_t *mbi) if (GetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_BOOT_LOADER_NAME) { GetBootInfo(btldr).grubName = (char*)(ullong)(mbi->boot_loader_name); GetBootInfo(btldr).kernelAddr = (void*)&MB_header; + GetBootInfo(btldr).kernelEndAddr = (void*)&kernelEnd; GetBootInfo(btldr).valid = 1; } if (GetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_MODS) { @@ -135,6 +138,11 @@ noreturn void StartKern(multiboot_info_t *mbInfo, int mbMagic) mapBad ); + KernLog("[Init] TEST First zone from %p : %p\n", (void*)0xB8010, GetFirstAvailZone((void*)0xB8010)); + KernLog("[Init] TEST Size of zone : %u Kio\n\n", GetAvailZoneSize(GetFirstAvailZone((void*)0xB8010)) / KB); + + + // We're out KernLog("\n[Init] Evil never dies !\n"); CrashSystem(); //yay diff --git a/kaleid/kernel/mm/heap.c b/kaleid/kernel/mm/heap.c index 06dbf9c..74048c2 100644 --- a/kaleid/kernel/mm/heap.c +++ b/kaleid/kernel/mm/heap.c @@ -23,6 +23,7 @@ //----------------------------------------------------------------------------// #include +#include // Least address out of the heap static void *_heap_end; @@ -33,9 +34,6 @@ static size_t _heap_max; // Lock NOT used internally, but used by KalAllocMemory() & co. static Lock_t _heap_lock = INITLOCK(KLOCK_SPINLOCK); -// Debugging stub -size_t GetAvailZoneSize(void *x) { (void)x; return 8 * MB; } - // // Initializes heap managment // diff --git a/kaleid/kernel/mm/map.c b/kaleid/kernel/mm/map.c index d84f662..7c27017 100644 --- a/kaleid/kernel/mm/map.c +++ b/kaleid/kernel/mm/map.c @@ -1,7 +1,7 @@ //----------------------------------------------------------------------------// // GNU GPL OS/K // // // -// Desc: // +// Desc: Mapping and checking memory related functions // // // // // // Copyright © 2018-2019 The OS/K Team // @@ -24,23 +24,139 @@ #include #include +#include +MemoryMap_t memoryMap = { 0 }; + + + +// +// Initilization of the memory map, and computation of the available ram size +// error_t InitMemoryMap(void) { + multiboot_memory_map_t *currentEntry; + multiboot_memory_map_t *mapEnd; + uint i = 0; + + // sanity checks if (!GetBootInfo(memory).memValid && GetBootInfo(memory).mapValid) return ENXIO; - DebugLog("[InitMemoryMap] Memory map address : %p, length : %d\n", - GetBootInfo(memory).mapAddr, GetBootInfo(memory).mapLength); if ((GetBootInfo(memory).upMemory / (MB/KB)) <= MINIMUM_RAM_SIZE) return ENOMEM; - DebugLog("[InitMemoryMap] Low memory : %d Kio, Up memory : %d Mio\n", - GetBootInfo(memory).lowMemory, GetBootInfo(memory).upMemory / (MB/KB)); + +// Ok then we can work ------------------------------------------------------ // + + // the memory map provided by GRUB via the BIOS + currentEntry = (multiboot_memory_map_t*)GetBootInfo(memory).mapAddr; + // End address of the map + mapEnd = (multiboot_memory_map_t*) + ((ullong)currentEntry + (ullong)GetBootInfo(memory).mapLength); + + // fill the map + while (currentEntry < mapEnd) { + // memory zone address + memoryMap.entry[i].addr = (void*)( (ullong)currentEntry->addr_low + + (((ullong)currentEntry->addr_high) << 32 )); + // memory zone size in bytes + memoryMap.entry[i].length = (ullong)currentEntry->len_low + + (((ullong)currentEntry->len_high) << 32); + // memory availability + memoryMap.entry[i].type = (uint)currentEntry->type; + // Adding the size to the size (yup) + memoryMap.length++; + // moving up ! + currentEntry = (multiboot_memory_map_t*) ((ullong)currentEntry + + currentEntry->size + sizeof(currentEntry->size)); + i++; + } + + DebugLog("[InitMemoryMap] %d entries detected in the memory map\n", + memoryMap.length); + + // compute the free ram size + for (i = 0; i < memoryMap.length; i++) { + if (memoryMap.entry[i].type == AVAILABLE_ZONE) { + memoryMap.freeRamSize += memoryMap.entry[i].length; + } else { + memoryMap.nonfreeRamSize += memoryMap.entry[i].length; + } + } + + // Trully strange if it happens... + if (memoryMap.freeRamSize < MINIMUM_RAM_SIZE) + return ENOMEM; + + KernLog("[InitMemoryMap] Available Ram Size : %u Mio, Used Ram Size : %u Kio\n", + memoryMap.freeRamSize / MB, memoryMap.nonfreeRamSize / KB); + KernLog("[InitMemoryMap] Physical Ram Size : %d Mio\n\n", + (memoryMap.freeRamSize + memoryMap.nonfreeRamSize) / MB); return EOK; } -void *GetMemoryMap(void) -{ - return (void*)0; +size_t GetAvailZoneSize(void *start) { + uint i; + + // Because the kernel is the kernel + if (start < GetBootInfo(btldr).kernelEndAddr) + return 0; + + // Search the zone where the start address is + for (i = 0; i < memoryMap.length; i++) { + // if the address is in an available zone, we can return the length + if ( + memoryMap.entry[i].type == AVAILABLE_ZONE && + (ullong)start >= (ullong)memoryMap.entry[i].addr && + (ullong)start < ((ullong)memoryMap.entry[i].addr + + (ullong)memoryMap.entry[i].length) + ) { + return (size_t)((ullong)memoryMap.entry[i].length - (ullong)start); + } + } + + // If there is no zone, we return a 0 size + return 0; +} + +void *GetFirstAvailZone(void *start) { + uint i; + void *current = 0; + + // Because the kernel is the kernel + if ((ullong)start < (ullong)GetBootInfo(btldr).kernelEndAddr) { + return GetFirstAvailZone(GetBootInfo(btldr).kernelEndAddr); + } + + // Search the zone where the start address is + for (i = 0; i < memoryMap.length; i++) { + // if the address is in an available zone, we can return the start address + if ( + memoryMap.entry[i].type == AVAILABLE_ZONE && + (ullong)start >= (ullong)memoryMap.entry[i].addr && + (ullong)start < ((ullong)memoryMap.entry[i].addr + + (ullong)memoryMap.entry[i].length) + ) { + current = start; + break; + } + } + + if (current) + return current; + + // Search the first zone from start + for (i = 0; i < memoryMap.length; i++) { + // Return the first zone that is after start + if ( + memoryMap.entry[i].type == AVAILABLE_ZONE && + (ullong)start <= (ullong)memoryMap.entry[i].addr + ) { + current = memoryMap.entry[i].addr; + break; + } + } + + return current; }