增加内存管理模块

This commit is contained in:
pointer-to-bios 2023-12-13 02:24:25 +08:00
parent 8c4c9a27d1
commit 56d4ab3121
21 changed files with 1069 additions and 40 deletions

View File

@ -44,6 +44,6 @@ libk:
@echo -e "\e[33m-------------------------\e[0m"
clear:
@make -C kernel clear --no-print-directory
@make -C libk clear --no-print-directory
@make -C kernel clear --no-print-directory ${DEFINES}
@make -C libk clear --no-print-directory ${DEFINES}
@-rm metaverse.elf metaverse.map

View File

@ -0,0 +1,7 @@
#ifndef X86_64_KERNEL_H
#define X86_64_KERNEL_H 1
#include <types.h>
#endif

View File

@ -0,0 +1,110 @@
#ifndef X86_64_MEMM_H
#define X86_64_MEMM_H 1
#include <types.h>
#include <libk/bits.h>
/* 页大小以MEMM_PAGE_SIZE为单位 */
#define MEMM_PAGE_SIZE 4096
typedef enum __memm_page_size
{
MEMM_PAGE_SIZE_4K = 1, // 1个4KB页大小
MEMM_PAGE_SIZE_2M = 512, // 512个4KB页大小
MEMM_PAGE_SIZE_1G = 262144, // 262144个4KB页大小
} memm_page_size;
extern u64 PML4[512];
#define MEMM_PAGE_TABLE_FLAGS_AREA ((u64)0xfff)
/* 页对齐掩码 */
#define MEMM_4K_ALIGN_MASK ((u64)0xfff)
#define MEMM_2M_ALIGN_MASK ((u64)0x1fffff)
#define MEMM_1G_ALIGN_MASK ((u64)0x3fffffff)
/* 页表项属性FLAGS */
#define MEMM_ENTRY_FLAG_PRESENT ((u64)1)
#define MEMM_ENTRY_FLAG_WRITE ((u64)1 << 1)
#define MEMM_ENTRY_FLAG_USER ((u64)1 << 2)
#define MEMM_ENTRY_FLAG_PWT ((u64)1 << 3)
#define MEMM_ENTRY_FLAG_PCD ((u64)1 << 4)
#define MEMM_ENTRY_FLAG_ACCECED ((u64)1 << 5)
#define MEMM_ENTRY_FLAG_DIRTY ((u64)1 << 6)
#define MEMM_ENTRY_FLAG_PS ((u64)1 << 7)
#define MEMM_ENTRY_FLAG_GLOBAL ((u64)1 << 8)
#define MEMM_ENTRY_FLAG_PAT ((u64)1 << 12)
#define MEMM_PTE_ENTRY_FLAG_PAT ((u64)1 << 7)
#define MEMM_ENTRY_FLAG_XD ((u64)1 << 63)
#define memm_entry_flag_get(entry, flag) \
((entry & flag) ? true : false)
/* 页表(大型页)项地址域掩码 */
#define MEMM_ENTRY_ADDRESS_MASK ((u64)0x000ffffffffff000)
#define MEMM_BP_ENTRY_ADDRESS_MASK ((u64)0x000fffffffffe000)
#define memm_entry_get_address(entry) \
((entry) & (memm_entry_flag_get(entry, MEMM_ENTRY_FLAG_PS) \
? MEMM_BP_ENTRY_ADDRESS_MASK \
: MEMM_ENTRY_ADDRESS_MASK))
/* 线性地址表项索引或页内偏移掩码 */
#define MEMM_LA_PML4EI_MASK ((u64)0x0000ff8000000000)
#define MEMM_LA_PDPTEI_MASK ((u64)0x0000007fc0000000)
#define MEMM_LA_PDEI_MASK ((u64)0x000000003fe00000)
#define MEMM_LA_PEI_MASK ((u64)0x00000000001ff000)
#define MEMM_LA_1GB_PAGE_OFFSET_MASK ((u64)0x000000003fffffff)
#define MEMM_LA_2MB_PAGE_OFFSET_MASK ((u64)0x00000000001fffff)
#define MEMM_LA_4KB_PAGE_OFFSET_MASK ((u64)0x0000000000000fff)
/* 线性地址表项索引偏移位数 */
#define MEMM_LA_PML4EI_OFFSET (39)
#define MEMM_LA_PDPTEI_OFFSET (30)
#define MEMM_LA_PDEI_OFFSET (21)
#define MEMM_LA_PEI_OFFSET (12)
/* 获取线性地址中某个表项索引以及获取页内偏移 */
#define MEMM_LA_PML4EI
#define MEMM_LA_PDPTEI
#define MEMM_LA_PDEI
#define MEMM_LA_PEI
#define memm_la_get_entry_index(addr, entry) \
(((addr) & (entry##_MASK)) >> (entry##_OFFSET))
#define MEMM_LA_1GB_PAGE_OFFSET
#define MEMM_LA_2MB_PAGE_OFFSET
#define MEMM_LA_4KB_PAGE_OFFSET
#define memm_la_get_offset(addr, page_type) \
((addr) & (page_type##_MASK))
/*
canonical型地址
target与physical至少都是以MEMM_PAGE_SIZE对齐的
MEMM_PAGE_SIZE对齐的canonical型地址都会返回false
1GB的一半且地址1GB对齐1GB页
2MB的一半且地址2MB对齐2MB页
4KB页
*/
bool memm_map_pageframes_to(
u64 target, u64 physical,
usize size,
bool user, bool write);
extern void reload_pml4();
#define is_user_address(addr) \
(((addr) > 0xffff7fffffffffff) ? true : false)
#define is_cannonical(addr) \
(((addr) < 0x0000800000000000 || (addr) > 0xffff7fffffffffff) ? true : false)
#define memm_get_page_align(addr) \
(is_aligned(addr, MEMM_PAGE_SIZE_1G) \
? MEMM_PAGE_SIZE_1G \
: (is_aligned(addr, MEMM_PAGE_SIZE_2M) \
? MEMM_PAGE_SIZE_2M \
: MEMM_PAGE_SIZE_4K))
#endif

View File

@ -2,7 +2,14 @@
#define KERNEL_H 1
#include <types.h>
#include <asm/sysctl.h>
#ifdef __x86_64__
#include <kernel/arch/x86_64/kernel.h>
#define ISA_STRING "x86_64"
#endif
#define KERNEL_TODO() \
while (true) \

150
src/include/kernel/memm.h Normal file
View File

@ -0,0 +1,150 @@
#ifndef MEMM_H
#define MEMM_H 1
#ifdef __x86_64__
#include <kernel/arch/x86_64/memm.h>
#endif
#include <libk/lst.h>
/**
* @brief
*
* TODO
*/
/* 最大支持1TB内存 */
#define MEMM_MAX_SUPPORTED_MEMORY (1024 * (1024 * (1024 * (usize)1024)))
/* 最大支持的分页数量 */
// 这里的页均以最小的页大小计算
#define MEMM_MAX_SUPPORTED_PAGES (MEMM_MAX_SUPPORTED_MEMORY / MEMM_PAGE_SIZE)
/* 只分配不映射空间 */
#define MEMM_ALLOC_ONLY_MEMORY (128 * 1024 * 1024)
/*
MEMM_PAGE_SIZE对齐的
*/
typedef struct __allocator_t
{
bool initialized;
// 在本分配器中调用allocate返回nullptr后为true
// 调用free后为false
bool full;
// 进程id当pid=0时代表内核
usize pid;
// 分配器类型
usize type;
usize size;
// 分配器实例的allocate函数
// 无法分配空间返回nullptr
// 在size参数为0时保证不可以分配空间但是如果空间已满依然返回nullptr
// 当参数align=0时表示不需要对齐
void *(*allocate)(void *allocator, usize size, usize align);
// 分配器实例的free函数
// 若不是allocate得到的地址则什么都不做
void (*free)(void *allocator, void *mem);
// 分配器实例
// 对应`type`类型使用
// 在kernel/memm/allocator/中是所有的内存分配器
u64 allocator_instance[0];
} allocator_t;
typedef struct __allocator_iterator_t
{
allocator_t *allocator;
struct __allocator_iterator_t *left, *right;
// 这个节点的内存空间处于的那个分配器
allocator_t *owned_allocator;
} allocator_iterator_t;
/*
allocator记录中allocator完成
page_map中置位map_with_allocator中复位map_with_destructed_allocator中复位
available_pages_table中的页使
*/
typedef struct __mem_manager_t
{
usize memory_size;
usize page_amount;
// 这里记录的数量为最小的页的数量
usize mapped_page_amount;
// 在进入内核主程序之前,有些不在内核中的虚拟内存空间已经被
// 页表映射,这部分内存不可以再映射到物理页框
usize alloc_only_memory;
#ifdef __x86_64__
// 在这里三种页的数量分别记录
usize mapped_4k_page;
usize mapped_2m_page;
usize mapped_1g_page;
#endif
// 页地图
// 每个bit都表示这个页是否被映射
u8 *page_map;
// 分配器页地图
// 每个bit表示这个页是否被内存分配器控制
// (不代表每个页都包含完整的分配器)
u8 *map_with_allocator;
// 分配器释放页地图
// 每个bit表示这个页是否曾经被内存分配器控制且现在被释放
// 需要取消映射
u8 *map_with_destructed_allocator;
// 空闲页线段搜索表
lst_iterator_t *available_pages_table;
// 分配器树
// 为方便查找,以二叉树的形式存储
// index=0为无效项
allocator_iterator_t *allocators;
} mem_manager_t;
mem_manager_t *memm_new(usize mem_size);
/*
`start``length`
`pid`0使
*/
allocator_t *memm_allocator_new(void *start, usize length, usize type, usize pid);
/*
*/
void memm_allocator_destruct(allocator_t *allocator);
/*
使
pid=0
线
allocator对象在进程与内核之间传递时一律使用内核空间的映射地址
*/
void *memm_allocate(usize size, usize pid, allocator_t **allocator);
/*
*/
void memm_free(allocator_t *allocator, void *mem);
/*
*/
usize find_fitable_pages(usize page_count);
#endif

View File

@ -0,0 +1,31 @@
#ifndef RAW_H
#define RAW_H 1
#include <types.h>
#define MEMM_RAW_ALLOCATOR 1
typedef struct __raw_allocator_cell
{
usize capacity; // 是content的长度
usize length; // 是实际使用的长度
u8 content[0];
} raw_allocator_cell;
// 原始分配器
// 包括至少一个cell分配时像cell的分裂一样将空白的一段分成两段
// 释放时只把length归零并不将cell合并
// length=0的cell称为空cell
// 在分配时遇到第一个空cell时将紧随其后的空cell都合并掉
typedef struct __raw_allocator_t
{
usize size, reserved;
raw_allocator_cell cells[0];
} raw_allocator_t;
void raw_allocator_new(raw_allocator_t *allocator, usize size);
void *raw_allocator_allocate(raw_allocator_t *allocator, usize size, usize align);
void raw_allocator_free(raw_allocator_t *allocator, void *mem);
#endif

View File

@ -2,6 +2,7 @@
#define TTY_H
#include <types.h>
#include <kernel/memm.h>
typedef enum __tty_type
{
@ -58,21 +59,23 @@ typedef struct __tty
tty_typeinfo typeinfo;
tty_mode mode;
tty_text_state text;
allocator_t *allocator;
} tty;
// tty控制器
typedef struct __tty_controller
typedef struct __tty_controller_t
{
#define TTY_MAX_NUM 128
tty *ttys[TTY_MAX_NUM];
bool map[TTY_MAX_NUM];
} tty_controller;
} tty_controller_t;
/**
* @brief tty控制器
*
*/
void tty_controller_init();
tty_controller_t *tty_controller_new();
/**
* @brief tty
@ -82,7 +85,7 @@ void tty_controller_init();
* @return tty* tty对象的地址tty数量超过TTY_MAX_NUM返回nullptr
* __tty是否是nullptr
*/
tty *tty_new(tty *__tty, tty_type type, tty_mode mode);
tty *tty_new(tty_type type, tty_mode mode);
/**
* @brief tty id获取一个tty

28
src/include/libk/bits.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef BITS_H
#define BITS_H 1
#include <types.h>
#define bit_set(byte, n) (byte) |= (1 << (n));
#define bit_reset(byte, n) (byte) &= ~(1 << (n));
#define bit_get(byte, n) (((byte) & (1 << (n))) >> (n))
#define bitmap_set(map, n) bit_set(((u8 *)(map))[(n) / 8], (n) % 8);
#define bitmap_reset(map, n) bit_reset(((u8 *)(map))[(n) / 8], (n) % 8);
#define bitmap_get(map, n) bit_get(map[(n) / 8], (n) % 8)
// 向后对齐
#define align_to(addr, align) \
if ((usize)(addr) % (align) != 0) \
{ \
usize __align_to_tmp_addr = (usize)(addr); \
__align_to_tmp_addr /= (align); \
__align_to_tmp_addr++; \
__align_to_tmp_addr *= (align); \
addr = __align_to_tmp_addr; \
}
#define is_aligned(addr, align) \
(addr % align == 0)
#endif

44
src/include/libk/lst.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef LST_H
#define LST_H 1
/*
Line Search Table
线
*/
#include <types.h>
typedef struct __lst_line_t
{
usize left, right;
} lst_line_t;
typedef struct __lst_iterator_t
{
lst_line_t line;
// 这个指针是kernel/memm.h中的allocator_t *
// 代表当前lst_line_index_t对象在allocate时使用的allocator
// 用的话会造成递归include
void *allocator;
struct __lst_iterator_t *next;
} lst_iterator_t;
lst_iterator_t *lst_new(usize start, usize end);
lst_iterator_t *lst_next(lst_iterator_t *iterator);
/*
`lst`线[left,right)
force=true时忽略不存在于`lst`线
force=false时若有不存在于`lst`线线falsetrue
*/
bool lst_remove(lst_iterator_t *lst, usize left, usize right, bool force);
/*
`lst`线[left,right)
force=true时忽略已经存在于`lst`线
force=false时若有存在于`lst`线线falsetrue
*/
bool lst_add(lst_iterator_t *lst, usize left, usize right, bool force);
#endif

7
src/include/libk/math.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef MATH_H
#define MATH_H 1
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif

View File

@ -9,7 +9,7 @@ ifdef release
CCFLAGS := ${CCFLAGS} -O2
endif
C_SRCS = main.c tty.c klog.c font.c
C_SRCS = main.c tty.c klog.c font.c memm.c memm_${ARCH}.c raw.c
C_OBJS = ${C_SRCS:.c=.o}
################################
@ -33,7 +33,7 @@ endif
ASMFLAGS := ${ASMFLAGS}
ASMFLAGS32 = -f elf32
S_OBJS = entry32.32.o entry.o
S_OBJS = entry32.32.o entry.o memm_${ARCH}_s.o
################################
@ -44,7 +44,7 @@ STRIP_SECS = -R .comment -R .note.GNU-stack
OBJCOPY_FLAGS = ${STRIP_SECS}
# 子目录
VPATH = mm/ tty/ klog/
VPATH = memm/ memm/allocator tty/ klog/ arch/${ARCH}
%.o: %.c
@echo -e "\e[1m\e[33m${CC}\e[0m \e[32m$<\e[0m \e[34m-->\e[0m \e[1m\e[32m$@\e[0m"
@ -56,16 +56,17 @@ VPATH = mm/ tty/ klog/
%.32.o: arch/${ARCH}/%.s
@echo -e "\e[1m\e[33m${ASM}\e[0m \e[32m$<\e[0m \e[34m-->\e[0m \e[1m\e[32m$@\e[0m"
@${ASM} ${ASMFLAGS32} -o $@ $< 2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red"
@objcopy -I elf32-i386 -O elf64-x86-64 $@ $@ 2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red" "objcopy=lyellow"
@${ASM} ${ASMFLAGS32} -o $@ $< 2>&1 | "${SOURCE}/colorize" "warning:=pink" "error:=red"
@objcopy -I elf32-i386 -O elf64-x86-64 $@ $@ 2>&1 | "${SOURCE}/colorize" "warning:=pink" "error:=red" "objcopy=lyellow"
%.o: arch/${ARCH}/%.s
@echo -e "\e[1m\e[33m${ASM}\e[0m \e[32m$<\e[0m \e[34m-->\e[0m \e[1m\e[32m$@\e[0m"
@${ASM} ${ASMFLAGS} -o $@ $< 2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red"
@${ASM} ${ASMFLAGS} -o $@ $< 2>&1 | "${SOURCE}/colorize" "warning:=pink" "error:=red"
kernel.o: ${OBJS}
@echo -e "\e[1m\e[33mld\e[0m \e[1m\e[32mkernel.o\e[0m \e[34m<--\e[0m \e[32m${OBJS}\e[0m"
@ld -r ${OBJS} -o kernel.o -Map=kernel.map -unresolved-symbols=ignore-all 2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red" "ld=lyellow"
@ld -r ${OBJS} -o kernel.o -Map=kernel.map -unresolved-symbols=ignore-all 2>&1 \
| "${SOURCE}/colorize" "warning:=pink" "error:=red" "ld=lyellow"
@objcopy ${OBJCOPY_FLAGS} kernel.o kernel.o
.PHONY: all clear

View File

@ -75,7 +75,7 @@ init32:
jmp 0x8:init64
section .cpumeta align=4096
global PML4
; 分页
; 链接器会把这些数据替换掉所以要在代码中重新设置
PML4:

View File

@ -0,0 +1,134 @@
#include <kernel/arch/x86_64/memm.h>
#include <kernel/memm.h>
#include <libk/string.h>
#include <libk/math.h>
#define map_pagemap(addr) \
map_pageframe_to((u64)addr, (u64)addr, false, true, MEMM_PAGE_SIZE_4K);
// 这里的physical必须保证根据ps对齐
static void map_pageframe_to(u64 target, u64 physical,
bool user, bool write, memm_page_size ps)
{
if (!is_cannonical(target))
return;
usize pml4ei = memm_la_get_entry_index(target, MEMM_LA_PML4EI);
usize pml4e = PML4[pml4ei];
u64 *PDPT;
if (memm_entry_flag_get(pml4e, MEMM_ENTRY_FLAG_PRESENT) == true)
PDPT = (u64 *)memm_entry_get_address(pml4e);
else
{
PDPT = (u64 *)(find_fitable_pages(1) * MEMM_PAGE_SIZE);
map_pagemap(PDPT);
memset(PDPT, 0, MEMM_PAGE_SIZE);
PML4[pml4ei] =
MEMM_ENTRY_FLAG_PRESENT |
MEMM_ENTRY_FLAG_WRITE |
(u64)PDPT;
}
usize pdptei = memm_la_get_entry_index(target, MEMM_LA_PDPTEI);
if (ps == MEMM_PAGE_SIZE_1G)
{
PDPT[pdptei] =
MEMM_ENTRY_FLAG_PRESENT |
(write ? MEMM_ENTRY_FLAG_WRITE : 0) |
(is_user_address(target) ? MEMM_ENTRY_FLAG_USER : 0) |
MEMM_ENTRY_FLAG_PS |
(is_user_address(target) ? 0 : MEMM_ENTRY_FLAG_GLOBAL) |
physical;
return;
}
usize pdpte = PDPT[pdptei];
u64 *PDT;
if (memm_entry_flag_get(pdpte, MEMM_ENTRY_FLAG_PRESENT) == true)
PDT = (u64 *)memm_entry_get_address(pdpte);
else
{
PDT = (u64 *)(find_fitable_pages(1) * MEMM_PAGE_SIZE);
map_pagemap(PDT);
memset(PDT, 0, MEMM_PAGE_SIZE);
PDPT[pdptei] =
MEMM_ENTRY_FLAG_PRESENT |
MEMM_ENTRY_FLAG_WRITE |
(u64)PDT;
}
usize pdei = memm_la_get_entry_index(target, MEMM_LA_PDEI);
if (ps == MEMM_PAGE_SIZE_2M)
{
PDT[pdei] =
MEMM_ENTRY_FLAG_PRESENT |
(write ? MEMM_ENTRY_FLAG_WRITE : 0) |
(is_user_address(target) ? MEMM_ENTRY_FLAG_USER : 0) |
MEMM_ENTRY_FLAG_PS |
(is_user_address(target) ? 0 : MEMM_ENTRY_FLAG_GLOBAL) |
physical;
return;
}
usize pde = PDT[pdei];
u64 *PT;
if (memm_entry_flag_get(pde, MEMM_ENTRY_FLAG_PRESENT) == true)
PT = (u64 *)memm_entry_get_address(pde);
else
{
PT = (u64 *)(find_fitable_pages(1) * MEMM_PAGE_SIZE);
map_pagemap(PT);
memset(PT, 0, MEMM_PAGE_SIZE);
PDT[pdei] =
MEMM_ENTRY_FLAG_PRESENT |
MEMM_ENTRY_FLAG_WRITE |
(u64)PT;
}
usize pei = memm_la_get_entry_index(target, MEMM_LA_PEI);
PT[pei] =
MEMM_ENTRY_FLAG_PRESENT |
(write ? MEMM_ENTRY_FLAG_WRITE : 0) |
(is_user_address(target) ? MEMM_ENTRY_FLAG_USER : 0) |
MEMM_ENTRY_FLAG_PS |
(is_user_address(target) ? 0 : MEMM_ENTRY_FLAG_GLOBAL) |
physical;
return;
}
bool memm_map_pageframes_to(
u64 target, u64 physical,
usize size,
bool user, bool write)
{
if (!is_cannonical(target) || !is_cannonical(physical))
return false;
if (!is_aligned(target, MEMM_PAGE_SIZE) || !is_aligned(physical, MEMM_PAGE_SIZE))
return false;
while (size != 0)
{
memm_page_size align = memm_get_page_align(physical);
if (align == MEMM_PAGE_SIZE_1G)
{
if (size < (usize)align * MEMM_PAGE_SIZE / 2)
align = MEMM_2M_ALIGN_MASK;
}
if (align == MEMM_PAGE_SIZE_2M)
{
if (size < (usize)align * MEMM_PAGE_SIZE / 2)
align = MEMM_4K_ALIGN_MASK;
}
map_pageframe_to(target, physical, user, write, align);
usize step = min(size, (usize)align * MEMM_PAGE_SIZE);
size -= step;
target += step;
physical += step;
}
reload_pml4();
return true;
}

View File

@ -0,0 +1,11 @@
section .text
global reload_pml4
reload_pml4:
push rax
mov rax, cr3
mov cr3, rax
pop rax
ret

View File

@ -16,7 +16,7 @@ void kmain(void *mb2_bootinfo)
// 获取内存信息
void **tags;
usize tags_amount;
if ((tags_amount = bootinfo_get_tag(bootinfo, BOOTINFO_BASIC_MEMORY_INFO_TYPE, &tags)) == 0)
if ((tags_amount = bootinfo_get_tag(&bootinfo, BOOTINFO_BASIC_MEMORY_INFO_TYPE, &tags)) == 0)
{
KERNEL_TODO();
}
@ -26,15 +26,17 @@ void kmain(void *mb2_bootinfo)
// 初始化内存管理模块
mem_manager_t *memm = memm_new(mem_size);
tty_controller_init();
// 初始化tty模块
tty_controller_t *tty_controler = tty_controller_new();
framebuffer fb;
get_frame_buffer_with_bootinfo(&fb, &bootinfo);
tty tty0;
tty_new(&tty0, tty_type_raw_framebuffer, tty_mode_text);
tty *tty0 = tty_new(tty_type_raw_framebuffer, tty_mode_text);
tty_set_framebuffer(&tty0, &fb);
tty_text_print(&tty0, "Hello Metaverse!\n", gen_color(0xbb, 0xbb, 0xbb), gen_color(0, 0, 0));
tty_text_print(&tty0, "Hello Metaverse!\n", gen_color(0xee, 0xee, 0xee), gen_color(0, 0, 0));
// 初始化内核日志模块
while (true)
{
@ -54,11 +56,9 @@ void get_frame_buffer_with_bootinfo(framebuffer *fb, bootinfo_t *bootinfo)
fb->width = fbinfo->framebuffer_width;
fb->height = fbinfo->framebuffer_height;
fb->pixsize = fbinfo->framebuffer_bpp / 8;
// TODO 对应内存空间还没有分页
KERNEL_TODO();
for (usize i = 0; i < 10000; i++)
{
((u8 *)fb->pointer)[i] = 0xff;
}
KERNEL_TODO();
memm_map_pageframes_to(
(u64)fb->pointer, (u64)fb->pointer,
fb->width * fb->height * fb->pixsize,
false, true);
// TODO fb->type需要确定
}

View File

@ -0,0 +1,69 @@
#include <kernel/memm/allocator/raw.h>
#include <kernel/kernel.h>
#include <libk/bits.h>
void raw_allocator_new(raw_allocator_t *allocator, usize size)
{
allocator->size = size - sizeof(allocator->size);
allocator->cells[0].capacity = size - sizeof(raw_allocator_t);
allocator->cells[0].length = 0;
}
void *raw_allocator_allocate(raw_allocator_t *allocator, usize size, usize align)
{
// 搜索
raw_allocator_cell *cell = allocator->cells;
while ((void *)cell < (void *)allocator + allocator->size &&
cell->length != 0 && cell->capacity >= size)
{
cell = (void *)cell + sizeof(raw_allocator_cell) + cell->capacity;
}
if ((void *)cell >= (void *)allocator + allocator->size)
return nullptr;
// 合并
raw_allocator_cell *next_cell = (void *)cell + sizeof(raw_allocator_cell) + cell->capacity;
while ((void *)next_cell < (void *)allocator + allocator->size &&
next_cell->length == 0)
{
cell->capacity += sizeof(raw_allocator_cell) + next_cell->capacity;
next_cell = (void *)next_cell + sizeof(raw_allocator_cell) + next_cell->capacity;
}
// 分割
usize allsize = sizeof(raw_allocator_cell) + size;
align_to(allsize, 16);
next_cell = (void *)cell + allsize;
if (allsize + sizeof(raw_allocator_cell) < sizeof(raw_allocator_cell) + cell->capacity)
{
usize nextsize = sizeof(raw_allocator_cell) + cell->capacity - allsize;
next_cell->capacity = nextsize - sizeof(raw_allocator_cell);
next_cell->length = 0;
}
else
{
allsize += 16;
}
// 分配
cell->capacity = allsize - sizeof(raw_allocator_cell);
cell->length = size;
return &cell->content;
}
void raw_allocator_free(raw_allocator_t *allocator, void *mem)
{
raw_allocator_cell *cell = allocator->cells;
while ((void *)cell < (void *)allocator + allocator->size)
{
if (mem == cell->content)
{
cell->length = 0;
break;
}
cell = (void *)cell + sizeof(raw_allocator_cell) + cell->capacity;
}
}

240
src/kernel/memm/memm.c Normal file
View File

@ -0,0 +1,240 @@
#include <kernel/kernel.h>
#include <kernel/memm.h>
#include <kernel/memm/allocator/raw.h>
#include <libk/string.h>
#include <libk/bits.h>
mem_manager_t memory_manager;
mem_manager_t *memm_new(usize mem_size)
{
memset(&memory_manager, 0, sizeof(memory_manager));
memory_manager.memory_size = mem_size;
memory_manager.page_amount = mem_size / MEMM_PAGE_SIZE;
usize kernel_initial_size = (usize)&kend;
align_to(kernel_initial_size, MEMM_PAGE_SIZE);
memory_manager.alloc_only_memory = MEMM_ALLOC_ONLY_MEMORY;
// 配置分配器树
allocator_t *allocator0 = memm_allocator_new(
(void *)kernel_initial_size,
memory_manager.alloc_only_memory - kernel_initial_size,
MEMM_RAW_ALLOCATOR, 0);
allocator_iterator_t *alcatr_ind = allocator0->allocate(
&allocator0->allocator_instance, sizeof(allocator_iterator_t), 0);
alcatr_ind->allocator = allocator0;
alcatr_ind->left = nullptr;
alcatr_ind->right = nullptr;
memory_manager.allocators = alcatr_ind;
// 配置页映射地图
usize pmc_size = memory_manager.page_amount;
align_to(pmc_size, 8);
pmc_size /= 8;
memory_manager.page_map = allocator0->allocate(&allocator0->allocator_instance, pmc_size, 0);
memset(memory_manager.page_map, 0, pmc_size);
memset(memory_manager.page_map, 0xff, MEMM_ALLOC_ONLY_MEMORY / MEMM_PAGE_SIZE / 8);
for (usize i = (MEMM_ALLOC_ONLY_MEMORY / MEMM_PAGE_SIZE / 8) * (u8)8;
i < MEMM_ALLOC_ONLY_MEMORY / MEMM_PAGE_SIZE % 8; i++)
{
bitmap_set(memory_manager.page_map, i);
}
// 配置分配器页地图
memory_manager.map_with_allocator =
allocator0->allocate(&allocator0->allocator_instance, pmc_size, 0);
memset(memory_manager.map_with_allocator, 0, pmc_size);
for (usize i = kernel_initial_size / MEMM_PAGE_SIZE;
i < MEMM_ALLOC_ONLY_MEMORY / MEMM_PAGE_SIZE;
i += MEMM_PAGE_SIZE)
{
bitmap_set(memory_manager.map_with_allocator, i);
}
// 分配器释放页地图
memory_manager.map_with_destructed_allocator =
allocator0->allocate(&allocator0->allocator_instance, pmc_size, 0);
memset(memory_manager.map_with_destructed_allocator, 0, pmc_size);
// 配置空闲页线段搜索表
memory_manager.available_pages_table = lst_new(0, memory_manager.page_amount);
lst_remove(memory_manager.available_pages_table, 0, MEMM_ALLOC_ONLY_MEMORY / MEMM_PAGE_SIZE, false);
return &memory_manager;
}
allocator_t *memm_allocator_new(void *start, usize length, usize type, usize pid)
{
allocator_t *allocator = start;
allocator->initialized = true;
allocator->full = false;
allocator->pid = 0;
allocator->size = length;
allocator->type = type;
switch (type)
{
case MEMM_RAW_ALLOCATOR:
raw_allocator_new((void *)allocator->allocator_instance, length - sizeof(allocator_t));
allocator->allocate = &raw_allocator_allocate;
allocator->free = &raw_allocator_free;
break;
default:
allocator->initialized = false;
break;
}
}
void memm_allocator_destruct(allocator_t *allocator)
{
allocator->initialized = false;
// TODO 从分配器树中删除这个分配器
KERNEL_TODO();
}
void *memm_find_and_allocate(allocator_iterator_t *allocator_ind, usize size, usize pid, allocator_t **writeback)
{
void *ptr;
allocator_t *allocator = allocator_ind->allocator;
if (allocator->pid == pid && allocator->full == false)
{ // 尝试用本节点分配
if ((ptr = allocator->allocate(&allocator->allocator_instance, size, 0)) != nullptr)
{
*writeback = allocator;
return ptr;
}
else
{
if ((ptr = allocator->allocate(&allocator->allocator_instance, 0, 0)) == nullptr)
allocator->full = true;
}
}
if (allocator_ind->left != nullptr)
{ // 尝试用左子树分配
ptr = memm_find_and_allocate(allocator_ind->left, size, pid, writeback);
if (ptr != nullptr)
return ptr;
}
if (allocator_ind->right != nullptr)
{ // 尝试用右子树分配
ptr = memm_find_and_allocate(allocator_ind->right, size, pid, writeback);
if (ptr != nullptr)
return ptr;
}
// 都不行就只能返回nullptr
return nullptr;
}
static void insert_allocator(allocator_iterator_t *iter, allocator_iterator_t *inserter)
{
if (inserter->allocator < iter->allocator)
{
if (iter->left == nullptr)
{
iter->left = inserter;
return;
}
else
{
insert_allocator(iter->left, inserter);
}
}
else if (inserter->allocator > iter->allocator)
{
if (iter->right == nullptr)
{
iter->right = inserter;
return;
}
else
{
insert_allocator(iter->right, inserter);
}
}
}
void *memm_allocate(usize size, usize pid, allocator_t **allocator)
{
usize orgsize = size;
// 从分配器树中分配内存
void *ptr = memm_find_and_allocate(memory_manager.allocators, size, pid, allocator);
if (ptr != nullptr)
goto after_allocation;
// 分配器树中没有可分配的内存
size += sizeof(allocator_t) + MEMM_PAGE_SIZE;
align_to(size, MEMM_PAGE_SIZE);
size /= MEMM_PAGE_SIZE;
usize allocator_start = find_fitable_pages(size);
for (usize i = allocator_start; i < allocator_start + size; i++)
{
bitmap_set(memory_manager.map_with_allocator, i);
}
if (allocator_start == 0)
return nullptr; // 内存中已经没有可分配的页了
memm_map_pageframes_to(allocator_start * MEMM_PAGE_SIZE, allocator_start * MEMM_PAGE_SIZE,
size * MEMM_PAGE_SIZE,
false, // 用户空间标志
true // 写权限
);
// 在新映射的页中创建一个分配器
// TODO 在用户态可能需要实现一个效率更高的分配器
allocator_t *new_allocator =
memm_allocator_new((void *)(allocator_start * MEMM_PAGE_SIZE), size * MEMM_PAGE_SIZE,
MEMM_RAW_ALLOCATOR, pid);
*allocator = new_allocator;
allocator_t *all;
allocator_iterator_t *allind = memm_allocate(sizeof(allocator_iterator_t), 0, &all);
allind->owned_allocator = all;
allind->allocator = new_allocator;
allind->left = nullptr;
allind->right = nullptr;
insert_allocator(memory_manager.allocators, allind);
ptr = new_allocator->allocate(&new_allocator->allocator_instance, orgsize, 0);
after_allocation:
if (pid != 0)
{ // TODO 进程管理中应该有一个用户地址-内核地址映射表
// 在进程分配时将页映射到用户空间中,并将这个映射关系记录进这个表中
// 需要返回的是用户空间的地址
}
return ptr;
}
void memm_free(allocator_t *allocator, void *mem)
{
if (is_user_address((u64)mem))
{ // TODO 对于用户空间的地址需要先转换到内核地址后释放
}
allocator->free(allocator->allocator_instance, mem);
if (allocator->full)
allocator->full = false;
}
usize find_fitable_pages(usize page_count)
{
usize res = 0;
lst_iterator_t *iter = memory_manager.available_pages_table;
do
{
if (iter->line.right - iter->line.left > page_count)
{
res = iter->line.left;
lst_remove(iter, res, res + page_count, false);
for (usize i = res; i < res + page_count; i++)
{
bitmap_set(memory_manager.page_map, i);
}
break;
}
} while ((iter = lst_next(iter)) != nullptr);
memory_manager.mapped_page_amount += page_count;
return res;
}

View File

@ -1,24 +1,26 @@
#include <kernel/kernel.h>
#include <kernel/tty.h>
#include <kernel/kernel.h>
#include <libk/string.h>
tty_controller tty_ctrler;
tty_controller_t tty_ctrler;
void tty_controller_init()
tty_controller_t *tty_controller_new()
{
memset(tty_ctrler.ttys, 0, sizeof(tty_ctrler.ttys));
memset(tty_ctrler.map, 0, sizeof(tty_ctrler.map));
return &tty_ctrler;
}
tty *tty_new(tty *__tty, tty_type type, tty_mode mode)
tty *tty_new(tty_type type, tty_mode mode)
{
if (__tty == nullptr)
{ // TODO 实现内存管理功能后实现
KERNEL_TODO();
}
allocator_t *allocator;
tty *__tty = memm_allocate(sizeof(tty), 0, &allocator);
memset(__tty, 0, sizeof(tty));
__tty->type = type;
__tty->mode = mode;
__tty->allocator = allocator;
tty *res = nullptr;
for (usize i = 0; i < TTY_MAX_NUM; ++i)
{

View File

@ -7,12 +7,14 @@ endif
# C语言环境变量
CC = gcc
CCFLAGS = -m64 -mcmodel=large -I ../include -fno-stack-protector -fno-exceptions -fno-builtin -nostdinc -nostdlib
CCFLAGS = -m64 -mcmodel=large -I ../include \
-fno-stack-protector -fno-exceptions \
-fno-builtin -nostdinc -nostdlib
ifdef release
CCFLAGS := ${CCFLAGS} -O2
endif
C_OBJS = bootinfo.o
C_OBJS = bootinfo.o lst.o
################################
@ -57,11 +59,12 @@ VPATH = multiboot2/ string/
%.o: arch/${ARCH}/%.s
@echo -e "\e[1m\e[33m${ASM}\e[0m \e[32m$<\e[0m \e[34m-->\e[0m \e[1m\e[32m$@\e[0m"
@${ASM} ${ASMFLAGS} -o $@ $< 2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red"
@${ASM} ${ASMFLAGS} -o $@ $< 2>&1 | "${SOURCE}/colorize" "warning:=pink" "error:=red"
libk.o: ${OBJS}
@echo -e "\e[1m\e[33mld\e[0m \e[1m\e[32mlibk.o\e[0m \e[34m<--\e[0m \e[32m${OBJS}\e[0m"
@ld -r ${OBJS} -o libk.o -Map=libk.map 2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red" "ld=lyellow"
@ld -r ${OBJS} -o libk.o -Map=libk.map -unresolved-symbols=ignore-all 2>&1 \
| "${SOURCE}/colorize" "warning:=pink" "error:=red" "ld=lyellow"
@objcopy ${OBJCOPY_FLAGS} libk.o libk.o
.PHONY: all postproc postproc_x86_64

183
src/libk/lst.c Normal file
View File

@ -0,0 +1,183 @@
#include <libk/lst.h>
#include <kernel/kernel.h>
#include <kernel/memm.h>
#include <libk/math.h>
lst_iterator_t *lst_new(usize start, usize end)
{
allocator_t *allocator;
lst_iterator_t *lst = memm_allocate(sizeof(lst_iterator_t), 0, &allocator);
lst->line.left = start;
lst->line.right = end;
lst->allocator = allocator;
lst->next = nullptr;
return lst;
}
lst_iterator_t *lst_next(lst_iterator_t *iterator)
{
return iterator->next;
}
static lst_line_t get_overlap(lst_line_t *l1, lst_line_t *l2)
{
lst_line_t l;
if (l1->right < l2->left || l2->right < l1->left)
{
l.left = l.right = 0;
return l;
}
if (l1->left < l2->left)
{
if (l1->right < l2->right)
{
l.left = l2->left;
l.right = l1->right;
return l;
}
else
{
l.left = l2->left;
l.right = l2->right;
return l;
}
}
else
{
if (l1->right < l2->right)
{
l.left = l1->left;
l.right = l1->right;
return l;
}
else
{
l.left = l1->left;
l.right = l2->right;
return l;
}
}
}
/*
线
*/
static void substract_line(lst_line_t *line, lst_line_t *substractor)
{
if (line->left == substractor->left && line->right > substractor->right)
{
line->left = substractor->right;
}
else if (line->right == substractor->right && line->left < substractor->left)
{
line->right = substractor->left;
}
}
#define line_is_equal(a, b) ((a).left == (b).left && (a).right == (b).right)
#define line_is_zero(l) ((l).left == (l).right)
bool lst_remove(lst_iterator_t *lst, usize left, usize right, bool force)
{
while (lst != nullptr)
{
if (left > lst->line.left && right < lst->line.right)
{
lst_iterator_t *new_node = lst_new(right, lst->line.right);
lst->line.right = left;
new_node->next = lst->next;
lst->next = new_node;
return true;
}
else
{
lst_line_t line = {
.left = left,
.right = right,
};
lst_line_t ol = get_overlap(&line, &lst->line);
substract_line(&line, &ol);
if (!line_is_zero(line) && !force)
return false;
substract_line(&lst->line, &ol);
return true;
}
lst = lst_next(lst);
}
return force;
}
bool lst_add(lst_iterator_t *lst, usize left, usize right, bool force)
{
lst_iterator_t *last = nullptr;
while (lst != nullptr)
{
if (left < lst->line.left)
{
lst_line_t line = {
.left = left,
.right = right,
};
lst_line_t ol = get_overlap(&line, &lst->line);
if (!force && !line_is_zero(ol))
return false;
if (right >= lst->line.right)
lst->line.left = left;
else
{
allocator_t *alloctr;
lst_iterator_t *new_node = memm_allocate(sizeof(lst_iterator_t), 0, &alloctr);
new_node->allocator = alloctr;
new_node->line = line;
new_node->next = lst;
if (last != nullptr)
last->next = new_node;
return true;
}
}
else if (left <= lst->line.right)
{
if (!force && left < lst->line.right)
return false;
if (right <= lst->line.right)
{
return true;
}
else if (right < lst->next->line.left)
{
lst->line.right = right;
return true;
}
else
{
if (!force && right >= lst->next->line.left)
return false;
lst_iterator_t *tmpnode = lst->next;
lst_iterator_t tmplast = *lst;
while (tmpnode != nullptr)
{
if (right < tmpnode->line.left)
{
lst->line.right = tmplast.line.right;
lst->next = tmpnode;
return true;
}
tmplast = *tmpnode;
lst_iterator_t *t = lst_next(tmpnode);
memm_free(tmpnode->allocator, tmpnode);
tmpnode = t;
}
lst->line.right = max(tmplast.line.right, right);
lst->next = nullptr;
return true;
}
}
last = lst;
lst = lst_next(lst);
}
}

View File

@ -26,7 +26,6 @@ SECTIONS {
. = 16M;
.text :
{
kmain = .;
*(.text)
}
.data :