mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 22:36:48 +00:00
🆕 完成了简单的内存管理单元,能分配内存页面
This commit is contained in:
parent
8131264e3f
commit
98e62e1e19
59
kernel/common/kprint.h
Normal file
59
kernel/common/kprint.h
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @file kprint.h
|
||||
* @author longjin
|
||||
* @brief 内核日志打印程序
|
||||
* @date 2022-01-28
|
||||
*
|
||||
* @copyright Copyright (c) 2022 longjin
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "printk.h"
|
||||
|
||||
#define kinfo(...) \
|
||||
do \
|
||||
{ \
|
||||
printk("[ INFO ] "); \
|
||||
printk(__VA_ARGS__); \
|
||||
printk("\n"); \
|
||||
} while (0);
|
||||
|
||||
#define kdebug(...) \
|
||||
do \
|
||||
{ \
|
||||
printk("[ DEBUG ] "); \
|
||||
printk(__VA_ARGS__); \
|
||||
printk("\n"); \
|
||||
} while (0);
|
||||
|
||||
#define kwarn(...) \
|
||||
do \
|
||||
{ \
|
||||
printk("[ "); \
|
||||
printk_color(YELLOW, BLACK, "WARN"); \
|
||||
printk(" ] "); \
|
||||
printk(__VA_ARGS__); \
|
||||
printk("\n"); \
|
||||
} while (0);
|
||||
|
||||
#define kerror(...) \
|
||||
do \
|
||||
{ \
|
||||
printk("[ "); \
|
||||
printk_color(RED, BLACK, "ERROR"); \
|
||||
printk(" ] "); \
|
||||
printk(__VA_ARGS__); \
|
||||
printk("\n"); \
|
||||
} while (0);
|
||||
|
||||
#define kterminated(...) \
|
||||
do \
|
||||
{ \
|
||||
printk("[ "); \
|
||||
printk_color(RED, BLACK, "TERMINATED"); \
|
||||
printk(" ] "); \
|
||||
printk(__VA_ARGS__); \
|
||||
printk("\n"); \
|
||||
} while (0);
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "exception/gate.h"
|
||||
#include "exception/trap.h"
|
||||
#include "mm/mm.h"
|
||||
#include "common/kprint.h"
|
||||
|
||||
int *FR_address = (int *)0xffff800000a00000; //帧缓存区的地址
|
||||
//char fxsave_region[512] __attribute__((aligned(16)));
|
||||
@ -61,6 +62,23 @@ void test_printk()
|
||||
printk("\nTest base 16 : %d --> %#X\n", 255, 255);
|
||||
}
|
||||
|
||||
// 测试内存管理单元
|
||||
void test_mm()
|
||||
{
|
||||
kinfo("Testing memory management unit...");
|
||||
printk("bmp[0]:%#018x\tbmp[1]%#018lx\n", *memory_management_struct.bmp, *memory_management_struct.bmp + 1);
|
||||
kinfo("Try to allocate 64 memory pages.");
|
||||
struct Page *page = alloc_pages(ZONE_NORMAL, 64, PAGE_PGT_MAPPED | PAGE_ACTIVE | PAGE_KERNEL);
|
||||
for (int i = 0; i <= 65; ++i)
|
||||
{
|
||||
printk("page%d\tattr:%#018lx\tphys_addr:%#018lx\t", i, page->attr, page->addr_phys);
|
||||
++page;
|
||||
if (((i + 1) % 2) == 0)
|
||||
printk("\n");
|
||||
}
|
||||
printk("bmp[0]:%#018x\tbmp[1]%#018lx\n", *memory_management_struct.bmp, *memory_management_struct.bmp + 1);
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
// 初始化printk
|
||||
@ -76,7 +94,6 @@ void init()
|
||||
// 初始化中断描述符表
|
||||
init_sys_vector();
|
||||
|
||||
|
||||
//asm volatile(" fxsave %0 " ::"m"(fxsave_region));
|
||||
// 初始化内存管理单元
|
||||
printk("[ DragonOS ] Initializing memory manage unit...\n");
|
||||
@ -87,7 +104,8 @@ void Start_Kernel(void)
|
||||
{
|
||||
|
||||
init();
|
||||
show_welcome();
|
||||
//show_welcome();
|
||||
test_mm();
|
||||
|
||||
//test_printk();
|
||||
|
||||
|
@ -67,7 +67,6 @@ void mm_init()
|
||||
memory_management_struct.bits_size = max_addr >> PAGE_2M_SHIFT; // 物理地址空间的最大页面数
|
||||
memory_management_struct.bmp_len = ((unsigned long)((max_addr >> PAGE_2M_SHIFT) + sizeof(unsigned long) * 8 - 1) / 8) & (~(sizeof(unsigned long) - 1)); // bmp由多少个unsigned long变量组成
|
||||
|
||||
|
||||
// 初始化bitmap, 先将整个bmp空间全部置位。稍后再将可用物理内存页复位。
|
||||
memset(memory_management_struct.bmp, 0xff, memory_management_struct.bmp_len);
|
||||
|
||||
@ -179,23 +178,22 @@ void mm_init()
|
||||
|
||||
for (ul j = 0; j <= mms_max_page; ++j)
|
||||
{
|
||||
page_init(memory_management_struct.pages_struct+j, PAGE_PGT_MAPPED|PAGE_KERNEL|PAGE_KERNEL_INIT|PAGE_ACTIVE);
|
||||
page_init(memory_management_struct.pages_struct + j, PAGE_PGT_MAPPED | PAGE_KERNEL | PAGE_KERNEL_INIT | PAGE_ACTIVE);
|
||||
}
|
||||
|
||||
ul* cr3 = get_CR3();
|
||||
ul *cr3 = get_CR3();
|
||||
|
||||
printk_color(INDIGO, BLACK, "cr3:\t%#018lx\n", cr3);
|
||||
printk_color(INDIGO, BLACK, "*cr3:\t%#018lx\n", *(phys_2_virt(cr3))&(~0xff));
|
||||
printk_color(INDIGO, BLACK, "**cr3:\t%#018lx\n", *phys_2_virt(*(phys_2_virt(cr3))&(~0xff))&(~0xff));
|
||||
printk_color(INDIGO, BLACK, "*cr3:\t%#018lx\n", *(phys_2_virt(cr3)) & (~0xff));
|
||||
printk_color(INDIGO, BLACK, "**cr3:\t%#018lx\n", *phys_2_virt(*(phys_2_virt(cr3)) & (~0xff)) & (~0xff));
|
||||
|
||||
// 消除一致性页表映射,将页目录(PML4E)的前10项清空
|
||||
for(int i=0;i<10;++i)
|
||||
*(phys_2_virt(cr3)+i) = 0UL;
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
*(phys_2_virt(cr3) + i) = 0UL;
|
||||
|
||||
flush_tlb();
|
||||
|
||||
printk("[ INFO ] Memory management unit initialized.\n");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -235,4 +233,81 @@ unsigned long page_init(struct Page *page, ul flags)
|
||||
page->attr |= flags;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从已初始化的页结构中搜索符合申请条件的、连续num个struct page
|
||||
*
|
||||
* @param zone_select 选择内存区域, 可选项:dma, mapped in pgt, unmapped in pgt
|
||||
* @param num 需要申请的连续内存页的数量 num<=64
|
||||
* @param flags 将页面属性设置成flag
|
||||
* @return struct Page*
|
||||
*/
|
||||
struct Page *alloc_pages(unsigned int zone_select, int num, ul flags)
|
||||
{
|
||||
ul zone_start = 0, zone_end = 0;
|
||||
switch (zone_select)
|
||||
{
|
||||
case ZONE_DMA:
|
||||
// DMA区域
|
||||
zone_start = 0;
|
||||
zone_end = ZONE_DMA_INDEX;
|
||||
break;
|
||||
case ZONE_NORMAL:
|
||||
zone_start = ZONE_DMA_INDEX;
|
||||
zone_end = ZONE_NORMAL_INDEX;
|
||||
break;
|
||||
case ZONE_UNMAPPED_IN_PGT:
|
||||
zone_start = ZONE_NORMAL_INDEX;
|
||||
zone_end = ZONE_UNMAPED_INDEX;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("[ ");
|
||||
printk_color(YELLOW, BLACK, "WARN");
|
||||
printk(" ] In alloc_pages: param: zone_select incorrect.\n");
|
||||
// 返回空
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = zone_start; i <= zone_end; ++i)
|
||||
{
|
||||
if ((memory_management_struct.zones_struct + i)->count_pages_free < num)
|
||||
continue;
|
||||
|
||||
struct Zone *z = memory_management_struct.zones_struct + i;
|
||||
|
||||
// 区域对应的起止页号以及区域拥有的页面数
|
||||
ul page_start = (z->zone_addr_start >> PAGE_2M_SHIFT);
|
||||
ul page_end = (z->zone_addr_end >> PAGE_2M_SHIFT);
|
||||
ul page_num = (z->zone_length >> PAGE_2M_SHIFT);
|
||||
|
||||
ul tmp = 64 - page_start % 64;
|
||||
for (ul j = page_start; j <= page_end; j += ((j % 64) ? tmp : 64))
|
||||
{
|
||||
// 按照bmp中的每一个元素进行查找
|
||||
// 先将p定位到bmp的起始元素
|
||||
ul *p = memory_management_struct.bmp + (j >> 6);
|
||||
|
||||
ul shift = j % 64;
|
||||
|
||||
for (int k = shift; k < 64 - shift; ++k)
|
||||
{
|
||||
// 寻找连续num个空页
|
||||
if (!(((*p >> k) | (*(p + 1) << (64 - k))) & (num == 64 ? 0xffffffffffffffffUL : ((1 << num) - 1))))
|
||||
{
|
||||
ul start_page_num = j + k - shift; // 计算得到要开始获取的内存页的页号(书上的公式有问题,这个是改过之后的版本)
|
||||
for(int l=0;l<num;++l)
|
||||
{
|
||||
struct Page* x = memory_management_struct.pages_struct+start_page_num+l;
|
||||
|
||||
page_init(x, flags);
|
||||
}
|
||||
// 成功分配了页面,返回第一个页面的指针
|
||||
return (struct Page*)(memory_management_struct.pages_struct+start_page_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -30,6 +30,14 @@
|
||||
#define virt_2_phys(addr) ((unsigned long)(addr)-KERNEL_BASE_ADDR)
|
||||
#define phys_2_virt(addr) ((unsigned long *)((unsigned long)(addr) + KERNEL_BASE_ADDR))
|
||||
|
||||
// ===== 内存区域属性 =====
|
||||
// DMA区域
|
||||
#define ZONE_DMA (1<<0)
|
||||
// 已在页表中映射的区域
|
||||
#define ZONE_NORMAL (1<<1)
|
||||
// 未在页表中映射的区域
|
||||
#define ZONE_UNMAPPED_IN_PGT (1<<2)
|
||||
|
||||
// ===== 页面属性 =====
|
||||
// 页面在页表中已被映射
|
||||
#define PAGE_PGT_MAPPED (1 << 0)
|
||||
@ -52,6 +60,23 @@
|
||||
// slab内存分配器的页
|
||||
#define PAGE_SLAB (1 << 9)
|
||||
|
||||
|
||||
/**
|
||||
* @brief 刷新TLB的宏定义
|
||||
* 由于任何写入cr3的操作都会刷新TLB,因此这个宏定义可以刷新TLB
|
||||
*/
|
||||
#define flush_tlb() \
|
||||
do \
|
||||
{ \
|
||||
ul tmp; \
|
||||
__asm__ __volatile__( \
|
||||
"movq %%cr3, %0\n\t" \
|
||||
"movq %0, %%cr3\n\t" \
|
||||
: "=r"(tmp)::"memory"); \
|
||||
\
|
||||
} while (0);
|
||||
|
||||
|
||||
// Address Range Descriptor Structure 地址范围描述符
|
||||
struct ARDS
|
||||
{
|
||||
@ -168,16 +193,11 @@ unsigned long *get_CR3()
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 刷新TLB的宏定义
|
||||
* 由于任何写入cr3的操作都会刷新TLB,因此这个宏定义可以刷新TLB
|
||||
* @brief 从已初始化的页结构中搜索符合申请条件的、连续num个struct page
|
||||
*
|
||||
* @param zone_select 选择内存区域, 可选项:dma, mapped in pgt, unmapped in pgt
|
||||
* @param num 需要申请的内存页的数量 num<=64
|
||||
* @param flags 将页面属性设置成flag
|
||||
* @return struct Page*
|
||||
*/
|
||||
#define flush_tlb() \
|
||||
do \
|
||||
{ \
|
||||
ul tmp; \
|
||||
__asm__ __volatile__( \
|
||||
"movq %%cr3, %0\n\t" \
|
||||
"movq %0, %%cr3\n\t" \
|
||||
: "=r"(tmp)::"memory"); \
|
||||
\
|
||||
} while (0);
|
||||
struct Page* alloc_pages(unsigned int zone_select, int num, ul flags);
|
Loading…
x
Reference in New Issue
Block a user