增加内存管理模块
This commit is contained in:
parent
8c4c9a27d1
commit
56d4ab3121
|
@ -44,6 +44,6 @@ libk:
|
||||||
@echo -e "\e[33m-------------------------\e[0m"
|
@echo -e "\e[33m-------------------------\e[0m"
|
||||||
|
|
||||||
clear:
|
clear:
|
||||||
@make -C kernel clear --no-print-directory
|
@make -C kernel clear --no-print-directory ${DEFINES}
|
||||||
@make -C libk clear --no-print-directory
|
@make -C libk clear --no-print-directory ${DEFINES}
|
||||||
@-rm metaverse.elf metaverse.map
|
@-rm metaverse.elf metaverse.map
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef X86_64_KERNEL_H
|
||||||
|
#define X86_64_KERNEL_H 1
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -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
|
|
@ -2,7 +2,14 @@
|
||||||
#define KERNEL_H 1
|
#define KERNEL_H 1
|
||||||
|
|
||||||
#include <types.h>
|
#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() \
|
#define KERNEL_TODO() \
|
||||||
while (true) \
|
while (true) \
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -2,6 +2,7 @@
|
||||||
#define TTY_H
|
#define TTY_H
|
||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
#include <kernel/memm.h>
|
||||||
|
|
||||||
typedef enum __tty_type
|
typedef enum __tty_type
|
||||||
{
|
{
|
||||||
|
@ -58,21 +59,23 @@ typedef struct __tty
|
||||||
tty_typeinfo typeinfo;
|
tty_typeinfo typeinfo;
|
||||||
tty_mode mode;
|
tty_mode mode;
|
||||||
tty_text_state text;
|
tty_text_state text;
|
||||||
|
|
||||||
|
allocator_t *allocator;
|
||||||
} tty;
|
} tty;
|
||||||
|
|
||||||
// tty控制器
|
// tty控制器
|
||||||
typedef struct __tty_controller
|
typedef struct __tty_controller_t
|
||||||
{
|
{
|
||||||
#define TTY_MAX_NUM 128
|
#define TTY_MAX_NUM 128
|
||||||
tty *ttys[TTY_MAX_NUM];
|
tty *ttys[TTY_MAX_NUM];
|
||||||
bool map[TTY_MAX_NUM];
|
bool map[TTY_MAX_NUM];
|
||||||
} tty_controller;
|
} tty_controller_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化tty控制器
|
* @brief 初始化tty控制器
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void tty_controller_init();
|
tty_controller_t *tty_controller_new();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 创建tty
|
* @brief 创建tty
|
||||||
|
@ -82,7 +85,7 @@ void tty_controller_init();
|
||||||
* @return tty* 返回tty对象的地址,如果tty数量超过TTY_MAX_NUM返回nullptr,
|
* @return tty* 返回tty对象的地址,如果tty数量超过TTY_MAX_NUM返回nullptr,
|
||||||
* 无论传入的__tty是否是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
|
* @brief 通过tty id获取一个tty
|
||||||
|
|
|
@ -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
|
|
@ -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`中的线段,不移除任何线段,返回false,否则返回true
|
||||||
|
*/
|
||||||
|
bool lst_remove(lst_iterator_t *lst, usize left, usize right, bool force);
|
||||||
|
|
||||||
|
/*
|
||||||
|
在`lst`中添加一个线段[left,right)
|
||||||
|
force=true时忽略已经存在于`lst`中的线段
|
||||||
|
force=false时若有存在于`lst`中的线段,只添加这些部分之外的线段,返回false,否则返回true
|
||||||
|
*/
|
||||||
|
bool lst_add(lst_iterator_t *lst, usize left, usize right, bool force);
|
||||||
|
|
||||||
|
#endif
|
|
@ -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
|
|
@ -9,7 +9,7 @@ ifdef release
|
||||||
CCFLAGS := ${CCFLAGS} -O2
|
CCFLAGS := ${CCFLAGS} -O2
|
||||||
endif
|
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}
|
C_OBJS = ${C_SRCS:.c=.o}
|
||||||
|
|
||||||
################################
|
################################
|
||||||
|
@ -33,7 +33,7 @@ endif
|
||||||
ASMFLAGS := ${ASMFLAGS}
|
ASMFLAGS := ${ASMFLAGS}
|
||||||
ASMFLAGS32 = -f elf32
|
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}
|
OBJCOPY_FLAGS = ${STRIP_SECS}
|
||||||
|
|
||||||
# 子目录
|
# 子目录
|
||||||
VPATH = mm/ tty/ klog/
|
VPATH = memm/ memm/allocator tty/ klog/ arch/${ARCH}
|
||||||
|
|
||||||
%.o: %.c
|
%.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"
|
@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
|
%.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"
|
@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"
|
@${ASM} ${ASMFLAGS32} -o $@ $< 2>&1 | "${SOURCE}/colorize" "warning:=pink" "error:=red"
|
||||||
@objcopy -I elf32-i386 -O elf64-x86-64 $@ $@ 2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red" "objcopy=lyellow"
|
@objcopy -I elf32-i386 -O elf64-x86-64 $@ $@ 2>&1 | "${SOURCE}/colorize" "warning:=pink" "error:=red" "objcopy=lyellow"
|
||||||
|
|
||||||
%.o: arch/${ARCH}/%.s
|
%.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"
|
@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}
|
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"
|
@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
|
@objcopy ${OBJCOPY_FLAGS} kernel.o kernel.o
|
||||||
|
|
||||||
.PHONY: all clear
|
.PHONY: all clear
|
||||||
|
|
|
@ -75,7 +75,7 @@ init32:
|
||||||
jmp 0x8:init64
|
jmp 0x8:init64
|
||||||
|
|
||||||
section .cpumeta align=4096
|
section .cpumeta align=4096
|
||||||
|
global PML4
|
||||||
; 分页
|
; 分页
|
||||||
; 链接器会把这些数据替换掉所以要在代码中重新设置
|
; 链接器会把这些数据替换掉所以要在代码中重新设置
|
||||||
PML4:
|
PML4:
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
section .text
|
||||||
|
global reload_pml4
|
||||||
|
reload_pml4:
|
||||||
|
push rax
|
||||||
|
|
||||||
|
mov rax, cr3
|
||||||
|
mov cr3, rax
|
||||||
|
|
||||||
|
pop rax
|
||||||
|
|
||||||
|
ret
|
|
@ -16,7 +16,7 @@ void kmain(void *mb2_bootinfo)
|
||||||
// 获取内存信息
|
// 获取内存信息
|
||||||
void **tags;
|
void **tags;
|
||||||
usize tags_amount;
|
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();
|
KERNEL_TODO();
|
||||||
}
|
}
|
||||||
|
@ -26,15 +26,17 @@ void kmain(void *mb2_bootinfo)
|
||||||
// 初始化内存管理模块
|
// 初始化内存管理模块
|
||||||
mem_manager_t *memm = memm_new(mem_size);
|
mem_manager_t *memm = memm_new(mem_size);
|
||||||
|
|
||||||
tty_controller_init();
|
// 初始化tty模块
|
||||||
|
tty_controller_t *tty_controler = tty_controller_new();
|
||||||
|
|
||||||
framebuffer fb;
|
framebuffer fb;
|
||||||
get_frame_buffer_with_bootinfo(&fb, &bootinfo);
|
get_frame_buffer_with_bootinfo(&fb, &bootinfo);
|
||||||
tty tty0;
|
tty *tty0 = tty_new(tty_type_raw_framebuffer, tty_mode_text);
|
||||||
tty_new(&tty0, tty_type_raw_framebuffer, tty_mode_text);
|
|
||||||
tty_set_framebuffer(&tty0, &fb);
|
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)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -54,11 +56,9 @@ void get_frame_buffer_with_bootinfo(framebuffer *fb, bootinfo_t *bootinfo)
|
||||||
fb->width = fbinfo->framebuffer_width;
|
fb->width = fbinfo->framebuffer_width;
|
||||||
fb->height = fbinfo->framebuffer_height;
|
fb->height = fbinfo->framebuffer_height;
|
||||||
fb->pixsize = fbinfo->framebuffer_bpp / 8;
|
fb->pixsize = fbinfo->framebuffer_bpp / 8;
|
||||||
// TODO 对应内存空间还没有分页
|
memm_map_pageframes_to(
|
||||||
KERNEL_TODO();
|
(u64)fb->pointer, (u64)fb->pointer,
|
||||||
for (usize i = 0; i < 10000; i++)
|
fb->width * fb->height * fb->pixsize,
|
||||||
{
|
false, true);
|
||||||
((u8 *)fb->pointer)[i] = 0xff;
|
// TODO fb->type需要确定
|
||||||
}
|
|
||||||
KERNEL_TODO();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -1,24 +1,26 @@
|
||||||
#include <kernel/kernel.h>
|
|
||||||
#include <kernel/tty.h>
|
#include <kernel/tty.h>
|
||||||
|
|
||||||
|
#include <kernel/kernel.h>
|
||||||
|
|
||||||
#include <libk/string.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.ttys, 0, sizeof(tty_ctrler.ttys));
|
||||||
memset(tty_ctrler.map, 0, sizeof(tty_ctrler.map));
|
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)
|
allocator_t *allocator;
|
||||||
{ // TODO 实现内存管理功能后实现
|
tty *__tty = memm_allocate(sizeof(tty), 0, &allocator);
|
||||||
KERNEL_TODO();
|
|
||||||
}
|
|
||||||
memset(__tty, 0, sizeof(tty));
|
memset(__tty, 0, sizeof(tty));
|
||||||
__tty->type = type;
|
__tty->type = type;
|
||||||
__tty->mode = mode;
|
__tty->mode = mode;
|
||||||
|
__tty->allocator = allocator;
|
||||||
tty *res = nullptr;
|
tty *res = nullptr;
|
||||||
for (usize i = 0; i < TTY_MAX_NUM; ++i)
|
for (usize i = 0; i < TTY_MAX_NUM; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,12 +7,14 @@ endif
|
||||||
# C语言环境变量
|
# C语言环境变量
|
||||||
|
|
||||||
CC = gcc
|
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
|
ifdef release
|
||||||
CCFLAGS := ${CCFLAGS} -O2
|
CCFLAGS := ${CCFLAGS} -O2
|
||||||
endif
|
endif
|
||||||
|
|
||||||
C_OBJS = bootinfo.o
|
C_OBJS = bootinfo.o lst.o
|
||||||
|
|
||||||
################################
|
################################
|
||||||
|
|
||||||
|
@ -57,11 +59,12 @@ VPATH = multiboot2/ string/
|
||||||
|
|
||||||
%.o: arch/${ARCH}/%.s
|
%.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"
|
@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}
|
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"
|
@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
|
@objcopy ${OBJCOPY_FLAGS} libk.o libk.o
|
||||||
|
|
||||||
.PHONY: all postproc postproc_x86_64
|
.PHONY: all postproc postproc_x86_64
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,7 +26,6 @@ SECTIONS {
|
||||||
. = 16M;
|
. = 16M;
|
||||||
.text :
|
.text :
|
||||||
{
|
{
|
||||||
kmain = .;
|
|
||||||
*(.text)
|
*(.text)
|
||||||
}
|
}
|
||||||
.data :
|
.data :
|
||||||
|
|
Loading…
Reference in New Issue