🆕 内核线程(在kernel_thtread函数中调用test_mm会产生问题)

This commit is contained in:
fslongjin
2022-02-10 13:45:38 +08:00
parent 39ddc21ca5
commit 67633eb04e
12 changed files with 752 additions and 83 deletions

View File

@ -159,7 +159,7 @@ void mm_init()
{
struct Zone *z = memory_management_struct.zones_struct + i;
//printk_color(ORANGE, BLACK, "zone_addr_start:%#18lx, zone_addr_end:%#18lx, zone_length:%#18lx, pages_group:%#18lx, count_pages:%#18lx\n",
// z->zone_addr_start, z->zone_addr_end, z->zone_length, z->pages_group, z->count_pages);
// z->zone_addr_start, z->zone_addr_end, z->zone_length, z->pages_group, z->count_pages);
// 1GB以上的内存空间不做映射
if (z->zone_addr_start == 0x100000000)
@ -180,7 +180,7 @@ void mm_init()
page_init(memory_management_struct.pages_struct + j, PAGE_PGT_MAPPED | PAGE_KERNEL | PAGE_KERNEL_INIT | PAGE_ACTIVE);
}
ul *cr3 = get_CR3();
global_CR3 = get_CR3();
/*
printk_color(INDIGO, BLACK, "cr3:\t%#018lx\n", cr3);
@ -188,9 +188,11 @@ void mm_init()
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;
*(phys_2_virt(global_CR3) + i) = 0UL;
*/
flush_tlb();
@ -241,7 +243,7 @@ unsigned long page_init(struct Page *page, ul flags)
/**
* @brief 从已初始化的页结构中搜索符合申请条件的、连续num个struct page
*
* @param zone_select 选择内存区域, 可选项dma, mapped in pgt, unmapped in pgt
* @param zone_select 选择内存区域, 可选项dma, mapped in pgt(normal), unmapped in pgt
* @param num 需要申请的连续内存页的数量 num<=64
* @param flags 将页面属性设置成flag
* @return struct Page*
@ -310,4 +312,36 @@ struct Page *alloc_pages(unsigned int zone_select, int num, ul flags)
}
}
}
return NULL;
}
unsigned long page_clean(struct Page *p)
{
if (!p->attr)
p->attr = 0;
else if ((p->attr & PAGE_REFERENCED) || (p->attr & PAGE_K_SHARE_TO_U))
{
// 被引用的页或内核共享给用户态的页
--p->ref_counts;
--p->zone->total_pages_link;
// 当引用为0时
if (!p->ref_counts)
{
p->attr = 0;
--p->zone->count_pages_using;
++p->zone->count_pages_free;
}
}
else
{
// 将bmp复位
*(memory_management_struct.bmp + ((p->addr_phys >> PAGE_2M_SHIFT) >> 6)) &= ~(1UL << ((p->addr_phys >> PAGE_2M_SHIFT) % 64));
p->attr = 0;
p->ref_counts = 0;
--p->zone->count_pages_using;
++p->zone->count_pages_free;
--p->zone->total_pages_link;
}
}

View File

@ -7,7 +7,7 @@
#define PTRS_PER_PGT 512
// 内核层的起始地址
#define KERNEL_BASE_ADDR 0xffff800000000000
#define KERNEL_BASE_ADDR ((unsigned long)0xffff800000000000)
#define PAGE_4K_SHIFT 12
#define PAGE_2M_SHIFT 21
@ -29,14 +29,18 @@
// 虚拟地址与物理地址转换
#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 Phy_To_Virt(addr) ((unsigned long *)((unsigned long)(addr) + KERNEL_BASE_ADDR))
#define Virt_To_2M_Page(kaddr) (memory_management_struct.pages_struct + (virt_2_phys(kaddr) >> PAGE_2M_SHIFT))
#define Phy_to_2M_Page(kaddr) (memory_management_struct.pages_struct + ((unsigned long)(kaddr) >> PAGE_2M_SHIFT))
// ===== 内存区域属性 =====
// DMA区域
#define ZONE_DMA (1<<0)
#define ZONE_DMA (1 << 0)
// 已在页表中映射的区域
#define ZONE_NORMAL (1<<1)
#define ZONE_NORMAL (1 << 1)
// 未在页表中映射的区域
#define ZONE_UNMAPPED_IN_PGT (1<<2)
#define ZONE_UNMAPPED_IN_PGT (1 << 2)
// ===== 页面属性 =====
// 页面在页表中已被映射
@ -60,23 +64,21 @@
// 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" \
#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
{
@ -155,32 +157,39 @@ extern struct memory_desc memory_management_struct;
// 导出内核程序的几个段的起止地址
extern char _text;
extern char _etext;
extern char _data;
extern char _edata;
extern char _rodata;
extern char _erodata;
extern char _bss;
extern char _ebss;
extern char _end;
// 每个区域的索引
int ZONE_DMA_INDEX = 0;
int ZONE_NORMAL_INDEX = 0; //low 1GB RAM ,was mapped in pagetable
int ZONE_UNMAPED_INDEX = 0; //above 1GB RAM,unmapped in pagetable
int ZONE_NORMAL_INDEX = 0; // low 1GB RAM ,was mapped in pagetable
int ZONE_UNMAPED_INDEX = 0; // above 1GB RAM,unmapped in pagetable
ul *global_CR3 = NULL;
// 初始化内存管理单元
void mm_init();
/**
* @brief 初始化内存页
*
*
* @param page 内存页结构体
* @param flags 标志位
* 对于新页面: 初始化struct page
* 对于当前页面属性/flags中含有引用属性或共享属性时则只增加struct page和struct zone的被引用计数。否则就只是添加页表属性并置位bmp的相应位。
* @return unsigned long
* @return unsigned long
*/
unsigned long page_init(struct Page *page, ul flags);
/**
* @brief 读取CR3寄存器的值存储了页目录的基地址
*
*
* @return unsigned* cr3的值的指针
*/
unsigned long *get_CR3()
@ -194,10 +203,27 @@ unsigned long *get_CR3()
/**
* @brief 从已初始化的页结构中搜索符合申请条件的、连续num个struct page
*
* @param zone_select 选择内存区域, 可选项dma, mapped in pgt, unmapped in pgt
*
* @param zone_select 选择内存区域, 可选项dma, mapped in pgt(normal), unmapped in pgt
* @param num 需要申请的内存页的数量 num<=64
* @param flags 将页面属性设置成flag
* @return struct Page*
* @return struct Page*
*/
struct Page* alloc_pages(unsigned int zone_select, int num, ul flags);
struct Page *alloc_pages(unsigned int zone_select, int num, ul flags);
/**
* @brief 释放内存页
*
* @param page 内存页结构体
* @return unsigned long
*/
unsigned long page_clean(struct Page *page);
/**
* @brief 内存页表结构体
*
*/
typedef struct
{
unsigned long pml4t;
} pml4t_t;