727 lines
18 KiB
C
727 lines
18 KiB
C
#include "multiboot.h"
|
|
#include "string.h"
|
|
#include "pvec.h"
|
|
#include "memory.h"
|
|
#include "console.h"
|
|
|
|
extern struct task_t *current_task;
|
|
|
|
extern void ivld_tlb(unsigned int virt);
|
|
|
|
void mem_reserve(char *blk, int pages);
|
|
|
|
#ifdef MEM_DEBUG
|
|
|
|
char *mem_alloc_pid(int pid);
|
|
|
|
struct mem_frame_t {
|
|
unsigned int page;
|
|
int pid;
|
|
} __attribute__((packed));
|
|
|
|
struct mem_frame_t *pageframes;
|
|
|
|
#else
|
|
|
|
#define mem_alloc_pid(x) mem_alloc()
|
|
|
|
unsigned char *mem_bitmap = (unsigned char *)0;
|
|
unsigned int mem_bitmap_size;
|
|
#endif
|
|
|
|
unsigned char *start_free_mem;
|
|
unsigned char *end_free_mem;
|
|
|
|
unsigned int *page_directory;
|
|
|
|
unsigned char *kernel_ds_at;
|
|
unsigned char *pci_mem_at;
|
|
|
|
unsigned int framebuffer_start;
|
|
unsigned int framebuffer_len;
|
|
|
|
int free_page_count;
|
|
|
|
extern unsigned char *videoram;
|
|
extern unsigned char vidmode;
|
|
|
|
unsigned int pages_above_kernel;
|
|
|
|
#define PAGE_SIZE 4096
|
|
#define PAGE_MASK (~(0xffffffff << 12))
|
|
|
|
char *mem_free_last_called_by;
|
|
|
|
static __inline__ unsigned long round_up_to_page(unsigned long addr) {
|
|
if ((addr & PAGE_MASK) != 0) {
|
|
addr &= ~(PAGE_MASK);
|
|
addr += PAGE_SIZE;
|
|
}
|
|
return addr;
|
|
}
|
|
|
|
extern unsigned char *endkernel;
|
|
|
|
void init_mem(multiboot_info_t *mbd) {
|
|
int available = 0;
|
|
int total = 0;
|
|
unsigned int mem_end;
|
|
int i;
|
|
|
|
mem_free_last_called_by = "Init MEM";
|
|
|
|
pages_above_kernel = 0;
|
|
|
|
multiboot_memory_map_t *mmap = (multiboot_memory_map_t *)mbd->mmap_addr;
|
|
while (mmap < (multiboot_memory_map_t *)(mbd->mmap_addr + mbd->mmap_length)) {
|
|
if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE) {
|
|
if (mmap->addr == 0x00100000) {
|
|
pages_above_kernel = mmap->len / PAGE_SIZE;
|
|
end_free_mem = (unsigned char *)((unsigned int)mmap->addr + (unsigned int)mmap->len);
|
|
}
|
|
available += mmap->len;
|
|
}
|
|
total += mmap->len;
|
|
|
|
mmap = (multiboot_memory_map_t *)((unsigned int)mmap + mmap->size + sizeof(unsigned int));
|
|
}
|
|
|
|
mem_end = (unsigned int)&endkernel;
|
|
|
|
multiboot_module_t *mod;
|
|
|
|
if (mbd->mods_count > 0) {
|
|
mod = (multiboot_module_t *)mbd->mods_addr;
|
|
mem_end = mod->mod_end;
|
|
}
|
|
|
|
mem_end = round_up_to_page(mem_end);
|
|
|
|
pages_above_kernel -= (mem_end / PAGE_SIZE);
|
|
|
|
#ifdef MEM_DEBUG
|
|
pageframes = (struct mem_frame_t *)mem_end;
|
|
int pages_in_frames = round_up_to_page((pages_above_kernel * PAGE_SIZE) / sizeof(struct mem_frame_t)) / PAGE_SIZE;
|
|
|
|
free_page_count = (pages_above_kernel - pages_in_frames);
|
|
|
|
start_free_mem = (unsigned char *)round_up_to_page(mem_end + (pages_in_frames * PAGE_SIZE));
|
|
|
|
for (i = 0; i < free_page_count; i++) {
|
|
pageframes[i].page = start_free_mem + i * PAGE_SIZE;
|
|
pageframes[i].pid = -1;
|
|
}
|
|
|
|
#else
|
|
mem_bitmap = (unsigned char *)mem_end;
|
|
|
|
mem_bitmap_size = pages_above_kernel / 8;
|
|
|
|
start_free_mem = (unsigned char *)round_up_to_page(mem_end + mem_bitmap_size);
|
|
|
|
free_page_count = ((unsigned int)end_free_mem - (unsigned int)start_free_mem) / PAGE_SIZE;
|
|
|
|
for (i = 0; i < mem_bitmap_size; i++) {
|
|
mem_bitmap[i] = 0;
|
|
}
|
|
|
|
#endif
|
|
mem_reserve((char *)0x00f00000, 256); // ISA HOLE
|
|
|
|
kernel_ds_at = (unsigned char *)0;
|
|
pci_mem_at = (unsigned char *)0x20000000;
|
|
}
|
|
|
|
extern unsigned char initialized;
|
|
|
|
void mem_clear_page_dir(unsigned int *user_page_directory) {
|
|
int i;
|
|
unsigned int *fake_dir = (unsigned int *)0x29002000;
|
|
mem_map_page((unsigned int)user_page_directory, (unsigned int)fake_dir, 3);
|
|
|
|
for (i = 0x100; i < 0x340; i++) {
|
|
if ((fake_dir[i] & 0x1) != 0) {
|
|
mem_free((char *)(fake_dir[i] & 0xFFFFF000), "mem_clear_page_dir 2 ");
|
|
fake_dir[i] = 0 | 6;
|
|
}
|
|
}
|
|
}
|
|
|
|
void mem_free_page_dir(unsigned int *user_page_directory) {
|
|
mem_clear_page_dir(user_page_directory);
|
|
mem_free((char *)user_page_directory, "mem_free_page_dir");
|
|
}
|
|
|
|
int mem_cpy_pages(struct task_t *old_task, struct task_t *new_task) {
|
|
unsigned int virt;
|
|
int i;
|
|
unsigned int *fake_tab = (unsigned int *)0x29003000;
|
|
|
|
if (old_task->user_pages != (void *)0) {
|
|
|
|
new_task->user_pages = (unsigned int *)malloc(sizeof(unsigned int) * old_task->user_pages_cnt);
|
|
new_task->user_pages_virt = (unsigned int *)malloc(sizeof(unsigned int) * old_task->user_pages_cnt);
|
|
if (!new_task->user_pages || !new_task->user_pages_virt) {
|
|
return 0;
|
|
}
|
|
|
|
new_task->user_pages_at = old_task->user_pages_at;
|
|
new_task->user_pages_cnt = old_task->user_pages_cnt;
|
|
|
|
for (i = 0; i < old_task->user_pages_cnt; i++) {
|
|
virt = i * 0x1000 + 0x40000000;
|
|
new_task->user_pages[i] = (unsigned int)mem_alloc_pid(new_task->pid);
|
|
new_task->user_pages_virt[i] = old_task->user_pages_virt[i];
|
|
mem_map_page(new_task->user_pages[i], (unsigned int)fake_tab, 7);
|
|
memcpy((char *)fake_tab, (char *)old_task->user_pages_virt[i], 0x1000);
|
|
mem_map_page_in(new_task->user_pages[i], new_task->user_pages_virt[i], new_task->cr3, 7);
|
|
}
|
|
} else {
|
|
new_task->user_pages_at = 0x40000000;
|
|
new_task->user_pages_cnt = 0;
|
|
}
|
|
|
|
// copy user stack
|
|
|
|
for (i = 0; i < USER_STACK_SIZE / 0x1000; i++) {
|
|
virt = 0xf0200000 + i * 0x1000;
|
|
new_task->user_stack_pages[i] = (unsigned int)mem_alloc_pid(new_task->pid);
|
|
mem_map_page(new_task->user_stack_pages[i], (unsigned int)fake_tab, 7);
|
|
if (old_task->user_stack_pages[i] != 0) {
|
|
memcpy((char *)fake_tab, (char *)virt, 0x1000);
|
|
} else {
|
|
memset((char *)fake_tab, 0, 0x1000);
|
|
}
|
|
mem_map_page_in(new_task->user_stack_pages[i], virt, new_task->cr3, 7);
|
|
}
|
|
|
|
// copy environment
|
|
virt = 0xf0000000;
|
|
for (i = 0; i < 64; i++) {
|
|
virt = 0xf0000000 + (i * 0x1000);
|
|
new_task->user_env_pages[i] = (unsigned int)mem_alloc_pid(new_task->pid);
|
|
mem_map_page(new_task->user_env_pages[i], (unsigned int)fake_tab, 7);
|
|
|
|
if (old_task->user_env_pages[i] != 0) {
|
|
memcpy((char *)fake_tab, (char *)virt, 0x1000);
|
|
} else {
|
|
memset((char *)fake_tab, 0, 0x1000);
|
|
}
|
|
mem_map_page_in(new_task->user_env_pages[i], virt, new_task->cr3, 7);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void mem_clear_user_pages(struct task_t *this_task) {
|
|
int i;
|
|
|
|
for (i = 0; i < this_task->user_pages_cnt; i++) {
|
|
unsigned int virt = this_task->user_pages_virt[i];
|
|
unsigned int table_entry = (virt >> 12) & 0x03ff;
|
|
unsigned int dir_entry = (virt >> 22);
|
|
unsigned int *pt_map = (unsigned int *)0xffc00000 + (0x400 * dir_entry);
|
|
mem_free((char *)(pt_map[table_entry] & 0xfffff000), "mem_clear_user_pages");
|
|
pt_map[table_entry] = 0 | 6;
|
|
}
|
|
|
|
for (i = 0; i < this_task->user_pages_cnt; i++) {
|
|
unsigned int *pd_map = (unsigned int *)0xfffff000;
|
|
unsigned int virt = i * 0x1000 + 0x40000000;
|
|
unsigned int dir_entry = (virt >> 22);
|
|
if (pd_map[dir_entry] & 0x1) {
|
|
mem_free((char *)(pd_map[dir_entry] & 0xFFFFF000), "mem_clear_user_pages 2");
|
|
pd_map[dir_entry] = 0 | 6;
|
|
}
|
|
}
|
|
|
|
// ivld_cr3();
|
|
}
|
|
|
|
#ifdef MEM_DEBUG
|
|
|
|
void mem_reserve(char *blk, int pages) {
|
|
unsigned int i = ((unsigned int)blk - (unsigned int)start_free_mem) / PAGE_SIZE;
|
|
int j;
|
|
|
|
for (j = i; j < i + pages; j++) {
|
|
pageframes[i].pid = 0;
|
|
}
|
|
}
|
|
char *mem_alloc_pid(int pid) {
|
|
int i;
|
|
for (i = 0; i < free_page_count; i++) {
|
|
if (pageframes[i].pid == -1) {
|
|
pageframes[i].pid = pid;
|
|
return (char *)pageframes[i].page;
|
|
}
|
|
}
|
|
|
|
return (void *)0;
|
|
}
|
|
|
|
char *mem_alloc(void) {
|
|
int i;
|
|
for (i = 0; i < free_page_count; i++) {
|
|
if (pageframes[i].pid == -1) {
|
|
pageframes[i].pid = current_task->pid;
|
|
return (char *)pageframes[i].page;
|
|
}
|
|
}
|
|
|
|
return (void *)0;
|
|
}
|
|
|
|
void mem_free(char *blk, char *caller) {
|
|
struct mem_frame_t *page = &pageframes[((unsigned int)blk - (unsigned int)start_free_mem) / PAGE_SIZE];
|
|
|
|
if (page->page == (unsigned int)blk) {
|
|
if (page->pid != current_task->pid && strcmp(caller, "sched_free_task") != 0) {
|
|
kprintf("Page owned by %d, freed by %d %s\n", page->pid, current_task->pid, caller);
|
|
}
|
|
page->pid = -1;
|
|
} else {
|
|
kprintf("ERROR IN MEM MANAGER\n");
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
void mem_reserve(char *blk, int pages) {
|
|
unsigned int i = ((unsigned int)blk - (unsigned int)start_free_mem) / PAGE_SIZE;
|
|
unsigned long mask, offset, index;
|
|
unsigned int j;
|
|
for (j = i; j < i + pages; j++) {
|
|
mask = 1;
|
|
index = j / 8;
|
|
offset = j % 8;
|
|
|
|
mem_bitmap[index] |= (mask << offset);
|
|
}
|
|
}
|
|
|
|
char *mem_alloc(void) { return mem_alloc_pages(1); }
|
|
// allocates a single physical page
|
|
char *mem_alloc_pages(int count) {
|
|
unsigned long mask, offset, index, i, j;
|
|
int consecutive = 0;
|
|
|
|
unsigned long start;
|
|
|
|
for (i = 0; i < free_page_count; i++) {
|
|
mask = 1;
|
|
index = i / 8;
|
|
offset = i % 8;
|
|
|
|
if (!(mem_bitmap[index] & (mask << offset))) {
|
|
mem_bitmap[index] |= (mask << offset);
|
|
if (consecutive == 0) {
|
|
start = (unsigned long)start_free_mem + (i * PAGE_SIZE);
|
|
}
|
|
consecutive++;
|
|
|
|
if (consecutive == count) {
|
|
return (char *)start;
|
|
}
|
|
} else {
|
|
for (j = 0; j < consecutive; j++) {
|
|
mem_free((char *)(start + (j * PAGE_SIZE)), "mem_alloc");
|
|
}
|
|
consecutive = 0;
|
|
}
|
|
}
|
|
|
|
return (char *)0;
|
|
}
|
|
|
|
// frees a single physical page
|
|
void mem_free(char *blk, char *caller) {
|
|
unsigned long mask, offset, index;
|
|
mem_free_last_called_by = caller;
|
|
|
|
unsigned long addr = (unsigned long)blk;
|
|
|
|
if ((unsigned int)blk & 0x00000FFF) {
|
|
kprintf("Bad Free 0x%p %s\n", addr, caller);
|
|
return;
|
|
}
|
|
|
|
addr -= (unsigned long)start_free_mem;
|
|
|
|
if (addr < 0 || addr > (unsigned long)end_free_mem) {
|
|
kprintf("Bad Free 0x%p %s\n", addr, caller);
|
|
return;
|
|
}
|
|
|
|
index = (addr / PAGE_SIZE) / 8;
|
|
offset = (addr / PAGE_SIZE) % 8;
|
|
|
|
if (!(mem_bitmap[index] & (1 << offset))) {
|
|
kprintf("Double Free 0x%p %s\n", blk, caller);
|
|
return;
|
|
}
|
|
|
|
mask = ~(1 << offset);
|
|
mem_bitmap[index] &= mask;
|
|
}
|
|
|
|
#endif
|
|
|
|
extern void console_pagemap();
|
|
|
|
void init_paging(void) {
|
|
unsigned int i;
|
|
unsigned int *page_table;
|
|
|
|
page_directory = (unsigned int *)mem_alloc();
|
|
|
|
// map page directory into itself
|
|
page_directory[1023] = (unsigned int)page_directory | 3;
|
|
for (i = 0; i < 1023; i++) {
|
|
page_directory[i] = (unsigned int)0 | 2;
|
|
}
|
|
|
|
// identity map lower 4 MB
|
|
page_table = (unsigned int *)mem_alloc();
|
|
memset((char *)page_table, 0, 4096);
|
|
|
|
page_directory[0] = (unsigned int)page_table | 3;
|
|
|
|
unsigned int address = 0;
|
|
|
|
while (address <= (unsigned int)start_free_mem) {
|
|
if (!(page_directory[address / 4096 / 1024] & 0x1)) {
|
|
page_directory[address / 4096 / 1024] = (unsigned int)mem_alloc() | 3;
|
|
}
|
|
|
|
page_table = (unsigned int *)(page_directory[address / 4096 / 1024] & 0xfffff000);
|
|
|
|
page_table[address / 4096 % 1024] = address | 3;
|
|
|
|
address += PAGE_SIZE;
|
|
}
|
|
|
|
for (i = 0x80; i < 0xA4; i++) {
|
|
unsigned char *pt = (unsigned char *)mem_alloc();
|
|
|
|
memset(pt, 0, 0x1000);
|
|
|
|
page_directory[i] = (unsigned int)pt | 3;
|
|
}
|
|
|
|
for (i = 0x340; i < 0x380; i++) {
|
|
unsigned char *pt = (unsigned char *)mem_alloc();
|
|
|
|
memset(pt, 0, 0x1000);
|
|
|
|
page_directory[i] = (unsigned int)pt | 3;
|
|
}
|
|
|
|
// enable paging
|
|
asm volatile("mov %0, %%cr3" ::"b"(page_directory));
|
|
unsigned int cr0;
|
|
asm volatile("mov %%cr0, %0" : "=b"(cr0));
|
|
cr0 |= 0x80000000;
|
|
asm volatile("mov %0, %%cr0" ::"b"(cr0));
|
|
}
|
|
|
|
unsigned int *mem_new_pagedirectory(struct task_t *new_task) {
|
|
unsigned int *new_page_directory;
|
|
// unsigned int *new_page_table;
|
|
|
|
unsigned int *old_page_dir = (unsigned int *)0xfffff000;
|
|
// unsigned int *old_page_table = (unsigned int *)0xffc00000;
|
|
|
|
unsigned int *fake_dir = (unsigned int *)0x29000000;
|
|
// unsigned int *fake_tab = (unsigned int *)0x29001000;
|
|
|
|
unsigned int i;
|
|
|
|
new_page_directory = (unsigned int *)mem_alloc_pid(new_task->pid);
|
|
mem_map_page((unsigned int)new_page_directory, (unsigned int)fake_dir, 3);
|
|
|
|
// map page directory into itself
|
|
fake_dir[1023] = (unsigned int)new_page_directory | 3;
|
|
for (i = 0; i < 1023; i++) {
|
|
fake_dir[i] = 0 | 6;
|
|
}
|
|
|
|
unsigned int table_end = (unsigned int)start_free_mem / 4096 / 1024 + 1;
|
|
|
|
for (i = 0; i < table_end; i++)
|
|
fake_dir[i] = old_page_dir[i];
|
|
|
|
for (i = 0x80; i < 0xA4; i++) {
|
|
fake_dir[i] = old_page_dir[i];
|
|
}
|
|
|
|
for (i = 0x340; i < 0x380; i++) {
|
|
fake_dir[i] = old_page_dir[i];
|
|
}
|
|
|
|
// map kernel stack areas
|
|
for (i = 0xC4; i < 0xC8; i++) {
|
|
fake_dir[i] = old_page_dir[i];
|
|
}
|
|
// map framebuffers
|
|
if (vidmode == 1) {
|
|
|
|
for (i = 0x380; i < 0x380 + (framebuffer_len / 0x400000) + 1; i++) {
|
|
fake_dir[i] = old_page_dir[i];
|
|
}
|
|
}
|
|
|
|
return new_page_directory;
|
|
}
|
|
|
|
unsigned char *mem_map_page_in(unsigned int phys, unsigned int virt, unsigned int cr3, int flags) {
|
|
unsigned int *fake_dir = (unsigned int *)0x29004000;
|
|
unsigned int *fake_tab = (unsigned int *)0x29001000;
|
|
unsigned int dir_entry = (virt >> 22);
|
|
unsigned int table_entry = (virt >> 12) & 0x03ff;
|
|
int i;
|
|
|
|
mem_map_page((unsigned int)cr3, (unsigned int)fake_dir, flags);
|
|
|
|
if ((fake_dir[dir_entry] & 1) == 0) {
|
|
fake_dir[dir_entry] = (unsigned int)mem_alloc() | flags;
|
|
mem_map_page((unsigned int)fake_dir[dir_entry] & 0xfffff000, (unsigned int)fake_tab, flags);
|
|
for (i = 0; i < 1023; i++) {
|
|
fake_tab[i] = 0x2;
|
|
}
|
|
fake_tab[1023] = (unsigned int)fake_tab;
|
|
} else {
|
|
mem_map_page((unsigned int)fake_dir[dir_entry] & 0xfffff000, (unsigned int)fake_tab, flags);
|
|
}
|
|
|
|
fake_tab[table_entry] = phys | flags;
|
|
return (unsigned char *)virt;
|
|
}
|
|
|
|
unsigned int mem_virt_2_phys(unsigned int virt) {
|
|
unsigned int dir_entry = (virt >> 22);
|
|
unsigned int table_entry = (virt >> 12) & 0x03ff;
|
|
unsigned int *pt_map = (unsigned int *)0xffc00000 + (0x400 * dir_entry);
|
|
|
|
return ((pt_map[table_entry] & ~0xFFF) + (virt & 0xFFF));
|
|
}
|
|
|
|
unsigned char *mem_map_page(unsigned int phys, unsigned int virt, int flags) {
|
|
unsigned int dir_entry = (virt >> 22);
|
|
unsigned int table_entry = (virt >> 12) & 0x03ff;
|
|
int i;
|
|
unsigned int *pd_map = (unsigned int *)0xfffff000;
|
|
unsigned int *pt_map = (unsigned int *)0xffc00000 + (0x400 * dir_entry);
|
|
|
|
if ((pd_map[dir_entry] & 1) == 0) {
|
|
// table doesnt exist, create it.
|
|
pd_map[dir_entry] = (unsigned int)mem_alloc() | flags;
|
|
ivld_tlb(virt);
|
|
for (i = 0; i < 1023; i++) {
|
|
pt_map[i] = 0x02;
|
|
}
|
|
pt_map[1023] = (unsigned int)pt_map;
|
|
}
|
|
pt_map[table_entry] = phys | flags;
|
|
ivld_tlb(virt);
|
|
|
|
return (unsigned char *)virt;
|
|
}
|
|
|
|
unsigned char *mem_map_framebuffer(unsigned int phys, unsigned int fb_length) {
|
|
unsigned int virt = 0xe0000000;
|
|
|
|
unsigned int start = phys & 0xFFFFF000;
|
|
|
|
framebuffer_start = start;
|
|
framebuffer_len = round_up_to_page(fb_length);
|
|
|
|
for (unsigned int i = start; i < start + framebuffer_len; i += 0x1000) {
|
|
|
|
mem_map_page(i, virt, 3);
|
|
|
|
virt += 0x1000;
|
|
}
|
|
|
|
return (unsigned char *)0xe0000000;
|
|
}
|
|
|
|
char *mem_alloc_user_page(unsigned int virt) {
|
|
current_task->user_pages_cnt++;
|
|
|
|
if (current_task->user_pages == (void *)0) {
|
|
current_task->user_pages = (unsigned int *)malloc(current_task->user_pages_cnt * sizeof(unsigned int));
|
|
current_task->user_pages_virt = (unsigned int *)malloc(current_task->user_pages_cnt * sizeof(unsigned int));
|
|
} else {
|
|
current_task->user_pages = (unsigned int *)realloc(current_task->user_pages, current_task->user_pages_cnt * sizeof(unsigned int));
|
|
current_task->user_pages_virt = (unsigned int *)realloc(current_task->user_pages_virt, current_task->user_pages_cnt * sizeof(unsigned int));
|
|
}
|
|
|
|
current_task->user_pages[current_task->user_pages_cnt - 1] = (unsigned int)mem_alloc();
|
|
current_task->user_pages_virt[current_task->user_pages_cnt - 1] = virt;
|
|
return (char *)current_task->user_pages[current_task->user_pages_cnt - 1];
|
|
}
|
|
|
|
int mem_map_user_page(unsigned int virt) {
|
|
unsigned int dir_entry = (virt >> 22);
|
|
unsigned int table_entry = (virt >> 12) & 0x03ff;
|
|
unsigned int *pd_map = (unsigned int *)0xfffff000;
|
|
unsigned int *pt_map = (unsigned int *)0xffc00000 + (0x400 * dir_entry);
|
|
int i;
|
|
|
|
if (virt > round_up_to_page(current_task->user_pages_at)) {
|
|
return 0;
|
|
}
|
|
|
|
if ((pd_map[dir_entry] & 1) == 0) {
|
|
// table doesnt exist, create it. should this be in user pages?!?
|
|
|
|
pd_map[dir_entry] = (unsigned int)mem_alloc() | 7;
|
|
ivld_tlb(virt);
|
|
|
|
for (i = 0; i < 1023; i++) {
|
|
pt_map[i] = 0x2;
|
|
}
|
|
}
|
|
|
|
pt_map[table_entry] = (unsigned int)mem_alloc_user_page(virt) | 7;
|
|
|
|
ivld_tlb(virt);
|
|
|
|
memset((unsigned char *)(virt & 0xFFFFF000), 0, 0x1000);
|
|
|
|
// kprintf("Allocated %p %s %d\n", virt, current_task->name, current_task->pid);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int mem_map_krnl_page(unsigned int virt) {
|
|
if (virt > (unsigned int)kernel_ds_at) {
|
|
return 0;
|
|
}
|
|
mem_map_page((unsigned int)mem_alloc(), virt, 3);
|
|
return 1;
|
|
}
|
|
|
|
#define KERNEL_DS_START 0xd0000000
|
|
|
|
unsigned int mem_pci_sbrk(unsigned int amount) {
|
|
unsigned int mem = (unsigned int)pci_mem_at;
|
|
if (pci_mem_at < (unsigned char *)0x29000000) {
|
|
|
|
pci_mem_at += round_up_to_page(amount);
|
|
|
|
return mem;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
unsigned int mem_usr_sbrk(int amount) {
|
|
unsigned int previous_ds;
|
|
|
|
previous_ds = current_task->user_pages_at;
|
|
|
|
if (amount <= 0) {
|
|
return previous_ds;
|
|
}
|
|
|
|
current_task->user_pages_at += round_up_to_page(amount);
|
|
|
|
return previous_ds;
|
|
}
|
|
|
|
void *sbrk(int amount) {
|
|
unsigned char *previous_ds;
|
|
|
|
if (kernel_ds_at == 0) {
|
|
kernel_ds_at = (unsigned char *)KERNEL_DS_START;
|
|
}
|
|
|
|
if (amount <= 0) {
|
|
if (initialized) {
|
|
kprintf("trying to free kernel memory\n");
|
|
}
|
|
return kernel_ds_at;
|
|
}
|
|
|
|
if (kernel_ds_at + amount >= (unsigned char *)0xe0000000) {
|
|
kprintf("Out of kernel memory :(\n");
|
|
return 0;
|
|
}
|
|
|
|
previous_ds = kernel_ds_at;
|
|
|
|
kernel_ds_at += amount;
|
|
|
|
return previous_ds;
|
|
}
|
|
|
|
int brk(void *end_data_segment) {
|
|
unsigned char *req_brk = end_data_segment;
|
|
|
|
if (req_brk > (unsigned char *)0xd0000000 && req_brk <= (unsigned char *)0xe0000000) {
|
|
kernel_ds_at = req_brk;
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
char *db_malloc_caller;
|
|
char *db_malloc_prev_caller = (void *)0;
|
|
|
|
void *dbmalloc(int size, char *caller) {
|
|
db_malloc_prev_caller = db_malloc_caller;
|
|
db_malloc_caller = caller;
|
|
return malloc(size);
|
|
}
|
|
|
|
void *dbrealloc(void *ptr, int size, char *caller) {
|
|
db_malloc_prev_caller = db_malloc_caller;
|
|
db_malloc_caller = caller;
|
|
return realloc(ptr, size);
|
|
}
|
|
|
|
void dbfree(void *ptr, char *caller) {
|
|
db_malloc_prev_caller = db_malloc_caller;
|
|
db_malloc_caller = caller;
|
|
free(ptr);
|
|
}
|
|
|
|
#ifdef MEM_DEBUG
|
|
|
|
unsigned int mem_get_info(struct mem_info *info) {
|
|
info->total = free_page_count * PAGE_SIZE;
|
|
info->used = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < free_page_count; i++) {
|
|
if (pageframes[i].pid != -1) {
|
|
info->used += PAGE_SIZE;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
#else
|
|
|
|
unsigned int mem_get_info(struct mem_info *info) {
|
|
info->total = free_page_count * PAGE_SIZE;
|
|
info->used = 0;
|
|
|
|
unsigned long mask, offset, index, i;
|
|
|
|
for (i = 0; i < free_page_count; i++) {
|
|
mask = 1;
|
|
index = i / 8;
|
|
offset = i % 8;
|
|
|
|
if (mem_bitmap[index] & (mask << offset)) {
|
|
info->used += PAGE_SIZE;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
#endif
|