mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 02:46:47 +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/gate.h"
|
||||||
#include "exception/trap.h"
|
#include "exception/trap.h"
|
||||||
#include "mm/mm.h"
|
#include "mm/mm.h"
|
||||||
|
#include "common/kprint.h"
|
||||||
|
|
||||||
int *FR_address = (int *)0xffff800000a00000; //帧缓存区的地址
|
int *FR_address = (int *)0xffff800000a00000; //帧缓存区的地址
|
||||||
//char fxsave_region[512] __attribute__((aligned(16)));
|
//char fxsave_region[512] __attribute__((aligned(16)));
|
||||||
@ -61,6 +62,23 @@ void test_printk()
|
|||||||
printk("\nTest base 16 : %d --> %#X\n", 255, 255);
|
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()
|
void init()
|
||||||
{
|
{
|
||||||
// 初始化printk
|
// 初始化printk
|
||||||
@ -76,7 +94,6 @@ void init()
|
|||||||
// 初始化中断描述符表
|
// 初始化中断描述符表
|
||||||
init_sys_vector();
|
init_sys_vector();
|
||||||
|
|
||||||
|
|
||||||
//asm volatile(" fxsave %0 " ::"m"(fxsave_region));
|
//asm volatile(" fxsave %0 " ::"m"(fxsave_region));
|
||||||
// 初始化内存管理单元
|
// 初始化内存管理单元
|
||||||
printk("[ DragonOS ] Initializing memory manage unit...\n");
|
printk("[ DragonOS ] Initializing memory manage unit...\n");
|
||||||
@ -87,7 +104,8 @@ void Start_Kernel(void)
|
|||||||
{
|
{
|
||||||
|
|
||||||
init();
|
init();
|
||||||
show_welcome();
|
//show_welcome();
|
||||||
|
test_mm();
|
||||||
|
|
||||||
//test_printk();
|
//test_printk();
|
||||||
|
|
||||||
|
@ -67,7 +67,6 @@ void mm_init()
|
|||||||
memory_management_struct.bits_size = max_addr >> PAGE_2M_SHIFT; // 物理地址空间的最大页面数
|
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变量组成
|
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空间全部置位。稍后再将可用物理内存页复位。
|
// 初始化bitmap, 先将整个bmp空间全部置位。稍后再将可用物理内存页复位。
|
||||||
memset(memory_management_struct.bmp, 0xff, memory_management_struct.bmp_len);
|
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)
|
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", 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(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(*(phys_2_virt(cr3)) & (~0xff)) & (~0xff));
|
||||||
|
|
||||||
// 消除一致性页表映射,将页目录(PML4E)的前10项清空
|
// 消除一致性页表映射,将页目录(PML4E)的前10项清空
|
||||||
for(int i=0;i<10;++i)
|
for (int i = 0; i < 10; ++i)
|
||||||
*(phys_2_virt(cr3)+i) = 0UL;
|
*(phys_2_virt(cr3) + i) = 0UL;
|
||||||
|
|
||||||
flush_tlb();
|
flush_tlb();
|
||||||
|
|
||||||
printk("[ INFO ] Memory management unit initialized.\n");
|
printk("[ INFO ] Memory management unit initialized.\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -235,4 +233,81 @@ unsigned long page_init(struct Page *page, ul flags)
|
|||||||
page->attr |= flags;
|
page->attr |= flags;
|
||||||
}
|
}
|
||||||
return 0;
|
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 virt_2_phys(addr) ((unsigned long)(addr)-KERNEL_BASE_ADDR)
|
||||||
#define phys_2_virt(addr) ((unsigned long *)((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)
|
#define PAGE_PGT_MAPPED (1 << 0)
|
||||||
@ -52,6 +60,23 @@
|
|||||||
// slab内存分配器的页
|
// slab内存分配器的页
|
||||||
#define PAGE_SLAB (1 << 9)
|
#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 地址范围描述符
|
// Address Range Descriptor Structure 地址范围描述符
|
||||||
struct ARDS
|
struct ARDS
|
||||||
{
|
{
|
||||||
@ -168,16 +193,11 @@ unsigned long *get_CR3()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 刷新TLB的宏定义
|
* @brief 从已初始化的页结构中搜索符合申请条件的、连续num个struct page
|
||||||
* 由于任何写入cr3的操作都会刷新TLB,因此这个宏定义可以刷新TLB
|
*
|
||||||
|
* @param zone_select 选择内存区域, 可选项:dma, mapped in pgt, unmapped in pgt
|
||||||
|
* @param num 需要申请的内存页的数量 num<=64
|
||||||
|
* @param flags 将页面属性设置成flag
|
||||||
|
* @return struct Page*
|
||||||
*/
|
*/
|
||||||
#define flush_tlb() \
|
struct Page* alloc_pages(unsigned int zone_select, int num, ul flags);
|
||||||
do \
|
|
||||||
{ \
|
|
||||||
ul tmp; \
|
|
||||||
__asm__ __volatile__( \
|
|
||||||
"movq %%cr3, %0\n\t" \
|
|
||||||
"movq %0, %%cr3\n\t" \
|
|
||||||
: "=r"(tmp)::"memory"); \
|
|
||||||
\
|
|
||||||
} while (0);
|
|
Loading…
x
Reference in New Issue
Block a user