réplica de
https://github.com/Arnau478/quark.git
synced 2024-11-23 12:58:07 +01:00
Physical memory manager
This commit is contained in:
pare
20d796515b
commit
1d64e83647
S'han modificat 8 arxius amb 308 adicions i 36 eliminacions
|
@ -26,6 +26,7 @@ call_kmain:
|
||||||
; Enable interrupts
|
; Enable interrupts
|
||||||
sti
|
sti
|
||||||
; Call kernel
|
; Call kernel
|
||||||
|
push ebx ; pointer to multiboot info
|
||||||
call kmain
|
call kmain
|
||||||
; If on qemu, shutdown
|
; If on qemu, shutdown
|
||||||
push 0x2000
|
push 0x2000
|
||||||
|
|
|
@ -1,27 +1,10 @@
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
static void *g_free_memory = ALLOC_START;
|
void memset(void *s, uint8_t c, size_t n){
|
||||||
|
uint8_t *p = s;
|
||||||
void *kmalloc(size_t size){
|
while(n--) *(p++) = c;
|
||||||
void *ptr = g_free_memory;
|
|
||||||
g_free_memory += size;
|
|
||||||
return ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *kcalloc(size_t count, size_t size){
|
void memcpy(void *dest, void *src, size_t n){
|
||||||
void *ptr = g_free_memory;
|
while(n--) ((uint8_t *)dest)[n] = ((uint8_t *)src)[n];
|
||||||
size *= count;
|
|
||||||
g_free_memory += size;
|
|
||||||
for(int i = 0; i < size; i++){
|
|
||||||
((uint8_t *)ptr)[i] = 0;
|
|
||||||
}
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void memcpy(uint8_t *source, uint8_t *dest, size_t count){
|
|
||||||
for(size_t i = 0; i < count; i++){
|
|
||||||
dest[i] = source[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,5 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define ALLOC_START (void *)0x1000
|
void memset(void *ptr, uint8_t val, size_t n);
|
||||||
|
void memcpy(void *dest, void *src, size_t n);
|
||||||
void *kmalloc(size_t size);
|
|
||||||
// TODO: void kfree(void *ptr);
|
|
||||||
void *kcalloc(size_t count, size_t size);
|
|
||||||
|
|
||||||
void memcpy(uint8_t *source, uint8_t *dest, size_t count);
|
|
||||||
|
|
|
@ -5,20 +5,46 @@
|
||||||
#include "drivers/keyboard.h"
|
#include "drivers/keyboard.h"
|
||||||
#include "drivers/serial.h"
|
#include "drivers/serial.h"
|
||||||
#include "fs/vfs.h"
|
#include "fs/vfs.h"
|
||||||
|
#include "mm/pmm.h"
|
||||||
|
#include "multiboot.h"
|
||||||
|
|
||||||
void __attribute__((cdecl)) kmain(uint64_t magic, uint64_t addr){
|
extern uint8_t end; // Kernel end
|
||||||
|
|
||||||
|
void __attribute__((cdecl)) kmain(multiboot_info_t *multiboot_info){
|
||||||
// Clear screen
|
// Clear screen
|
||||||
clear_screen();
|
clear_screen();
|
||||||
|
|
||||||
// Initialize chip-specific hardware
|
// Initialize chip-specific hardware
|
||||||
hal_initialize();
|
hal_initialize();
|
||||||
|
|
||||||
|
// Initialize physical memory manager
|
||||||
|
uint32_t mem_size = 1024 + multiboot_info->mem_lower + multiboot_info->mem_upper*64;
|
||||||
|
|
||||||
|
pmm_initialize(mem_size, (int)(&end));
|
||||||
|
|
||||||
|
for(int i = 0; i < multiboot_info->mmap_length; i += sizeof(multiboot_memory_map_t)){
|
||||||
|
multiboot_memory_map_t *memory_map = (multiboot_memory_map_t *)(multiboot_info->mmap_addr + i);
|
||||||
|
printf("Start Addr: 0x%x%x | Length: 0x%x%x | Size: 0x%x | Type: %i\n", memory_map->addr_h, memory_map->addr_l, memory_map->len_h, memory_map->len_l, memory_map->size, memory_map->type);
|
||||||
|
|
||||||
|
if(memory_map->type == 1){
|
||||||
|
pmm_init_region(memory_map->addr_l, memory_map->len_l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pmm_deinit_region(0x100000, (int)(&end) - 0x100000); // Deinit the section the kernel is in
|
||||||
|
|
||||||
// Initialize drivers
|
// Initialize drivers
|
||||||
timer_initialize();
|
timer_initialize();
|
||||||
keyboard_initialize();
|
keyboard_initialize();
|
||||||
|
|
||||||
// Initialize FS
|
// Initialize FS
|
||||||
vfs_initialize();
|
vfs_initialize();
|
||||||
|
|
||||||
|
// PMM test code
|
||||||
|
uint32_t *p1 = (uint32_t *)pmm_alloc_block();
|
||||||
|
printf("Allocated p1 at: 0x%x\n", p1);
|
||||||
|
uint32_t *p2 = (uint32_t *)pmm_alloc_block();
|
||||||
|
printf("Allocated p2 at: 0x%x\n", p2);
|
||||||
|
|
||||||
for(;;);
|
for(;;);
|
||||||
}
|
}
|
||||||
|
|
153
src/kernel/mm/pmm.c
Normal file
153
src/kernel/mm/pmm.c
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "pmm.h"
|
||||||
|
#include "../lib/memory.h"
|
||||||
|
|
||||||
|
static uint32_t g_pmm_memory_size = 0;
|
||||||
|
static uint32_t g_pmm_used_blocks = 0;
|
||||||
|
static uint32_t g_pmm_max_blocks = 0;
|
||||||
|
static uint32_t *g_pmm_memory_map = 0;
|
||||||
|
|
||||||
|
static inline void pmm_map_set(int bit){
|
||||||
|
g_pmm_memory_map[bit / 32] |= (1 << (bit % 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void pmm_map_unset(int bit){
|
||||||
|
g_pmm_memory_map[bit / 32] &= ~(1 << (bit % 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool pmm_map_get(int bit){
|
||||||
|
return g_pmm_memory_map[bit / 32] & (1 << (bit % 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
int pmm_map_first_free(){
|
||||||
|
for(uint32_t i = 0; i < pmm_get_block_count() / 32; i++){
|
||||||
|
if(g_pmm_memory_map[i] != 0xffffffff){
|
||||||
|
for(int j = 0; j < 32; j++){
|
||||||
|
if(!(g_pmm_memory_map[i] & (1 << j))){
|
||||||
|
return i*4*8+j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pmm_map_first_free_s(size_t size){
|
||||||
|
if(size == 0) return -1;
|
||||||
|
if(size == 1) return pmm_map_first_free();
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < pmm_get_block_count() / 32; i++){
|
||||||
|
if(g_pmm_memory_map[i] != 0xffffffff){
|
||||||
|
for(int j = 0; j < 32; j++){
|
||||||
|
int bit = 1 << j;
|
||||||
|
if(!(g_pmm_memory_map[i] & bit)){
|
||||||
|
int start_bit = i*32;
|
||||||
|
start_bit+=bit;
|
||||||
|
|
||||||
|
uint32_t free = 0;
|
||||||
|
for(uint32_t count = 0; count <= size; count++){
|
||||||
|
if(!pmm_map_get(start_bit+count)) free++;
|
||||||
|
if(free == size) return i*4*8+j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_initialize(size_t mem_size, phys_addr bitmap){
|
||||||
|
g_pmm_memory_size = mem_size;
|
||||||
|
g_pmm_memory_map = (uint32_t *)bitmap;
|
||||||
|
g_pmm_max_blocks = (pmm_get_memory_size()*1024) / PMM_BLOCK_SIZE;
|
||||||
|
g_pmm_used_blocks = g_pmm_max_blocks;
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
memset(g_pmm_memory_map, 0xFF, pmm_get_block_count() / PMM_BLOCKS_PER_BYTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_init_region(phys_addr base, size_t size){
|
||||||
|
int align = base / PMM_BLOCK_SIZE;
|
||||||
|
int blocks = size / PMM_BLOCK_SIZE;
|
||||||
|
|
||||||
|
for(; blocks >= 0; blocks--){
|
||||||
|
pmm_map_unset(align++);
|
||||||
|
g_pmm_used_blocks--;
|
||||||
|
}
|
||||||
|
|
||||||
|
pmm_map_set(0); // First block always set
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_deinit_region(phys_addr base, size_t size){
|
||||||
|
int align = base / PMM_BLOCK_SIZE;
|
||||||
|
int blocks = size / PMM_BLOCK_SIZE;
|
||||||
|
|
||||||
|
for(; blocks >= 0; blocks--){
|
||||||
|
pmm_map_set(align++);
|
||||||
|
g_pmm_used_blocks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
pmm_map_set(0); // First block always set
|
||||||
|
}
|
||||||
|
|
||||||
|
void *pmm_alloc_block(){
|
||||||
|
if(pmm_get_free_block_count() <= 0) return 0; // Out of memory
|
||||||
|
|
||||||
|
int frame = pmm_map_first_free();
|
||||||
|
if(frame == -1) return 0; // Out of memory
|
||||||
|
|
||||||
|
pmm_map_set(frame);
|
||||||
|
|
||||||
|
phys_addr addr = frame * PMM_BLOCK_SIZE;
|
||||||
|
g_pmm_used_blocks++;
|
||||||
|
|
||||||
|
return (void *)addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_free_block(void *p){
|
||||||
|
phys_addr addr = (phys_addr)p;
|
||||||
|
int frame = addr / PMM_BLOCK_SIZE;
|
||||||
|
|
||||||
|
pmm_map_unset(frame);
|
||||||
|
|
||||||
|
g_pmm_used_blocks--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *pmm_alloc_blocks(size_t size){
|
||||||
|
if(pmm_get_free_block_count() <= size) return 0; // Out of memory
|
||||||
|
|
||||||
|
int frame = pmm_map_first_free_s(size);
|
||||||
|
if(frame == -1) return 0; // Out of memory
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < size; i++) pmm_map_set(frame+i);
|
||||||
|
|
||||||
|
phys_addr addr = frame * PMM_BLOCK_SIZE;
|
||||||
|
g_pmm_used_blocks += size;
|
||||||
|
|
||||||
|
return (void *)addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_free_blocks(void *p, size_t size){
|
||||||
|
phys_addr addr = (phys_addr)p;
|
||||||
|
int frame = addr / PMM_BLOCK_SIZE;
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < size; i++) pmm_map_unset(frame+i);
|
||||||
|
|
||||||
|
g_pmm_used_blocks -= size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t pmm_get_memory_size(){
|
||||||
|
return g_pmm_memory_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t pmm_get_block_count(){
|
||||||
|
return g_pmm_max_blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t pmm_get_used_block_count(){
|
||||||
|
return g_pmm_used_blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t pmm_get_free_block_count(){
|
||||||
|
return g_pmm_max_blocks - g_pmm_used_blocks;
|
||||||
|
}
|
24
src/kernel/mm/pmm.h
Normal file
24
src/kernel/mm/pmm.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define PMM_BLOCKS_PER_BYTE 8
|
||||||
|
#define PMM_BLOCK_SIZE 4096
|
||||||
|
#define PMM_BLOCK_ALIGN PMM_BLOCK_SIZE
|
||||||
|
|
||||||
|
typedef uint32_t phys_addr;
|
||||||
|
|
||||||
|
int pmm_map_first_free();
|
||||||
|
int pmm_map_first_free_s(size_t size);
|
||||||
|
void pmm_initialize(size_t mem_size, phys_addr bitmap);
|
||||||
|
void pmm_init_region(phys_addr base, size_t size);
|
||||||
|
void pmm_deinit_region(phys_addr base, size_t size);
|
||||||
|
void *pmm_alloc_block();
|
||||||
|
void pmm_free_block(void *p);
|
||||||
|
void *pmm_alloc_blocks(size_t size);
|
||||||
|
void pmm_free_blocks(void *p, size_t size);
|
||||||
|
size_t pmm_get_memory_size();
|
||||||
|
uint32_t pmm_get_block_count();
|
||||||
|
uint32_t pmm_get_used_block_count();
|
||||||
|
uint32_t pmm_get_free_block_count();
|
96
src/kernel/multiboot.h
Normal file
96
src/kernel/multiboot.h
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t addr_l;
|
||||||
|
uint32_t addr_h;
|
||||||
|
uint32_t len_l;
|
||||||
|
uint32_t len_h;
|
||||||
|
uint32_t type;
|
||||||
|
} __attribute__((packed)) multiboot_memory_map_t;
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
uint32_t tabsize;
|
||||||
|
uint32_t strsize;
|
||||||
|
uint32_t addr;
|
||||||
|
uint32_t reserved;
|
||||||
|
} multiboot_aout_symbol_table_t;
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
uint32_t num;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t addr;
|
||||||
|
uint32_t shndx;
|
||||||
|
} multiboot_elf_section_header_table_t;
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
/* Multiboot info version number */
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
|
/* Available memory from BIOS */
|
||||||
|
uint32_t mem_lower;
|
||||||
|
uint32_t mem_upper;
|
||||||
|
|
||||||
|
/* "root" partition */
|
||||||
|
uint32_t boot_device;
|
||||||
|
|
||||||
|
/* Kernel command line */
|
||||||
|
uint32_t cmdline;
|
||||||
|
|
||||||
|
/* Boot-Module list */
|
||||||
|
uint32_t mods_count;
|
||||||
|
uint32_t mods_addr;
|
||||||
|
|
||||||
|
union{
|
||||||
|
multiboot_aout_symbol_table_t aout_sym;
|
||||||
|
multiboot_elf_section_header_table_t elf_sec;
|
||||||
|
} u;
|
||||||
|
|
||||||
|
/* Memory Mapping buffer */
|
||||||
|
uint32_t mmap_length;
|
||||||
|
uint32_t mmap_addr;
|
||||||
|
|
||||||
|
/* Drive Info buffer */
|
||||||
|
uint32_t drives_length;
|
||||||
|
uint32_t drives_addr;
|
||||||
|
|
||||||
|
/* ROM configuration table */
|
||||||
|
uint32_t config_table;
|
||||||
|
|
||||||
|
/* Boot Loader Name */
|
||||||
|
uint32_t boot_loader_name;
|
||||||
|
|
||||||
|
/* APM table */
|
||||||
|
uint32_t apm_table;
|
||||||
|
|
||||||
|
/* Video */
|
||||||
|
uint32_t vbe_control_info;
|
||||||
|
uint32_t vbe_mode_info;
|
||||||
|
uint16_t vbe_mode;
|
||||||
|
uint16_t vbe_interface_seg;
|
||||||
|
uint16_t vbe_interface_off;
|
||||||
|
uint16_t vbe_interface_len;
|
||||||
|
|
||||||
|
uint64_t framebuffer_addr; // FIXME: This may fail, as we are not in 64 bit (long) mode
|
||||||
|
uint32_t framebuffer_pitch;
|
||||||
|
uint32_t framebuffer_width;
|
||||||
|
uint32_t framebuffer_height;
|
||||||
|
uint8_t framebuffer_bpp;
|
||||||
|
uint8_t framebuffer_type;
|
||||||
|
union{
|
||||||
|
struct{
|
||||||
|
uint32_t framebuffer_palette_addr;
|
||||||
|
uint16_t framebuffer_palette_num_colors;
|
||||||
|
};
|
||||||
|
struct{
|
||||||
|
uint8_t framebuffer_red_field_position;
|
||||||
|
uint8_t framebuffer_red_mask_size;
|
||||||
|
uint8_t framebuffer_green_field_position;
|
||||||
|
uint8_t framebuffer_green_mask_size;
|
||||||
|
uint8_t framebuffer_blue_field_position;
|
||||||
|
uint8_t framebuffer_blue_mask_size;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} __attribute__((packed)) multiboot_info_t;
|
|
@ -14,12 +14,6 @@ int shell_run(char *cmd){
|
||||||
else if(!strcmp(cmd, "version")){
|
else if(!strcmp(cmd, "version")){
|
||||||
printf("%s\n", OS_VERSION);
|
printf("%s\n", OS_VERSION);
|
||||||
}
|
}
|
||||||
else if(!strcmp(cmd, "malloc")){
|
|
||||||
printf("Allocated 10 bytes:\n%x\n", kmalloc(10));
|
|
||||||
}
|
|
||||||
else if(!strcmp(cmd, "calloc")){
|
|
||||||
printf("Allocated and zeroed 10 chars:\n%x\n", kcalloc(10, sizeof(char)));
|
|
||||||
}
|
|
||||||
else if(!strcmp(cmd, "clear")){
|
else if(!strcmp(cmd, "clear")){
|
||||||
clear_screen();
|
clear_screen();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Referencia en una nova incidència