diff --git a/kernel/common/kprint.h b/kernel/common/kprint.h new file mode 100644 index 00000000..51cf8814 --- /dev/null +++ b/kernel/common/kprint.h @@ -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); + diff --git a/kernel/main.c b/kernel/main.c index d9dcaabf..fca52735 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -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(); diff --git a/kernel/mm/mm.c b/kernel/mm/mm.c index 839c3a90..d7aaa859 100644 --- a/kernel/mm/mm.c +++ b/kernel/mm/mm.c @@ -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