Skip to content

Commit d6b93f6

Browse files
committed
Update
1 parent c3f2976 commit d6b93f6

File tree

8 files changed

+43
-7
lines changed

8 files changed

+43
-7
lines changed

devlog/devlog20200306.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,11 @@
4444

4545
# SimpleKernel 开发日志 20200312
4646

47-
思考了一下发现,为啥我不直接用 pmm_alloc 进行分配?有物理地址对齐需求的也就只有这里了,用 pmm 刚好啊
47+
思考了一下发现,为啥我不直接用 pmm_alloc 进行分配?有物理地址对齐需求的也就只有这里了,用 pmm 刚好啊。
48+
49+
我真傻,真的。我要对齐的是线性地址,关物理内存什么事?我是个沙雕吧
50+
51+
好的,那么新的解决方案是这样:
52+
53+
- 添加一个专门分配栈空间的函数,负责申请物理内存+映射,保证返回的地址可以用 slab 管理
54+
- 为了避免线性空间冲突的问题,需要在每次映射页之前判断一下有没有冲突,旧有的 alloc_page 函数与新的函数都需要

iso/boot/kernel.bin

276 Bytes
Binary file not shown.

simplekernel.iso

2 KB
Binary file not shown.

src/arch/x86_64/mm/vmm.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ void unmap(pgd_t * pgd_now, ptr_t va) {
7878
return;
7979
}
8080

81-
uint32_t get_mapping(pgd_t * pgd_now, ptr_t va, ptr_t pa) {
81+
uint32_t get_mapping(pgd_t * pgd_now, ptr_t va, ptr_t * pa) {
8282
uint32_t pgd_idx = VMM_PGD_INDEX(va);
8383
uint32_t pte_idx = VMM_PTE_INDEX(va);
8484

@@ -89,8 +89,10 @@ uint32_t get_mapping(pgd_t * pgd_now, ptr_t va, ptr_t pa) {
8989
// 转换到内核线性地址
9090
pte = (pte_t *)VMM_PA_LA( (ptr_t)pte);
9191
// 如果地址有效而且指针不为 NULL
92-
if( ( (void *)pte[pte_idx] != NULL) && ( (void *)pa != NULL) ) {
93-
pa = pte[pte_idx] & VMM_PAGE_MASK;
92+
if( (void *)pte[pte_idx] != NULL) {
93+
if( (void *)pa != NULL) {
94+
pa = pte[pte_idx] & VMM_PAGE_MASK;
95+
}
9496
return 1;
9597
}
9698
return 0;

src/arch/x86_64/task/task.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ ListEntry * wait_list = NULL;
3232
static inline ptr_t alloc_stack(void);
3333
static inline ptr_t alloc_stack(void) {
3434

35+
return 0;
3536
}
3637

3738
// 返回一个空的任务控制块

src/include/mem/vmm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ void unmap(pgd_t * pgd_now, ptr_t va);
9898

9999
// 如果虚拟地址 va 映射到物理地址则返回 1
100100
// 同时如果 pa 不是空指针则把物理地址写入 pa 参数
101-
uint32_t get_mapping(pgd_t * pgd_now, ptr_t va, ptr_t pa);
101+
uint32_t get_mapping(pgd_t * pgd_now, ptr_t va, ptr_t * pa);
102102

103103
// 更换当前页目录
104104
void switch_pgd(ptr_t pd);

src/kernel.bin

276 Bytes
Binary file not shown.

src/kernel/mem/slab.c

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,13 +260,39 @@ ptr_t alloc_page(ptr_t va, size_t page) {
260260
for(ptr_t va_start = va, pa_start = pa ;
261261
pa_start < pa + VMM_PAGE_SIZE * page ;
262262
pa_start += VMM_PAGE_SIZE, va_start += VMM_PAGE_SIZE) {
263-
map(pgd_kernel, va_start, pa_start, VMM_PAGE_PRESENT | VMM_PAGE_RW);
263+
// 如果当前线性地址没有映射
264+
if(get_mapping(pgd_kernel, va_start, (ptr_t *)NULL) == 0) {
265+
map(pgd_kernel, va_start, pa_start, VMM_PAGE_PRESENT | VMM_PAGE_RW);
266+
}
267+
else {
268+
// 如果有部分映射了,则全部 unmap
269+
ptr_t addr = (ptr_t)NULL;
270+
for(addr = va ; addr < va_start ; addr += VMM_PAGE_SIZE) {
271+
unmap(pgd_kernel, addr);
272+
}
273+
// 并重新计算 va 的值
274+
// 运行到这里时 addr 尚未被检测,所以下面的代码从 addr 开始
275+
// 计算方法:addr~addr+page*VMM_PAGE_SIZE 的 get_mapping 结果全部为 0
276+
ptr_t tmp = addr;
277+
while(addr < tmp + page * VMM_PAGE_SIZE) {
278+
// 如果遇到映射过的
279+
if(get_mapping(pgd_kernel, addr, (ptr_t *)NULL) != 0) {
280+
// 更新 addr 地址
281+
addr += VMM_PAGE_SIZE;
282+
tmp = addr;
283+
}
284+
addr += VMM_PAGE_SIZE;
285+
}
286+
// 这时 addr 就是符合要求的地址
287+
// 全部映射即可
288+
map(pgd_kernel, addr, pa_start, VMM_PAGE_PRESENT | VMM_PAGE_RW);
289+
return addr;
290+
}
264291
}
265292
bzero( (void *)va, VMM_PAGE_SIZE * page);
266293
return va;
267294
}
268295

269-
// align 参数为按照 align 地址对齐
270296
ptr_t alloc(size_t byte) {
271297
// 所有申请的内存长度(限制最小大小)加上管理头的长度
272298
size_t len = (byte > SLAB_MIN) ? byte : SLAB_MIN;

0 commit comments

Comments
 (0)