From b83368fb1f03751f87af83f164ad9db255f2bd33 Mon Sep 17 00:00:00 2001 From: KAAAsS Date: Thu, 13 May 2021 22:51:39 +0800 Subject: [PATCH] finish exec3.1 --- lab3/CMakeLists.txt | 2 +- lab3/kernel/process/thread.c | 21 ++++++++++++++++++++- lab3/kernel/sched/context.c | 6 ++++++ lab3/kernel/sched/sched.c | 2 +- note.org | 29 +++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 3 deletions(-) diff --git a/lab3/CMakeLists.txt b/lab3/CMakeLists.txt index adc2b48..5588960 100644 --- a/lab3/CMakeLists.txt +++ b/lab3/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 3.14) set(CMAKE_VERBOSE_MAKEFILE on) -set(CMAKE_BUILD_TYPE "Release") # "Release" or "Debug" +set(CMAKE_BUILD_TYPE "Debug") # "Release" or "Debug" set(CHCORE_PLAT "raspi3") set(CHCORE_ARCH "aarch64") diff --git a/lab3/kernel/process/thread.c b/lab3/kernel/process/thread.c index a222fca..ab19e25 100644 --- a/lab3/kernel/process/thread.c +++ b/lab3/kernel/process/thread.c @@ -153,7 +153,7 @@ static u64 load_binary(struct process *process, * prepare the arguments for the two following function calls: pmo_init * and vmspace_map_range. * pmo_init allocates the demanded size of physical memory for the PMO. - * vmspace_map_range maps the pmo to a sepcific virtual memory address. + * vmspace_map_range maps the pmo to a specific virtual memory address. * You should get the size of current segment and the virtual address * to be mapped from elf headers. * HINT: we suggest you use the seg_sz and p_vaddr variables for @@ -161,6 +161,15 @@ static u64 load_binary(struct process *process, * page aligned segment size. Take care of the page alignment when allocating * and mapping physical memory. */ + // 段实际数据大小 + seg_sz = elf->p_headers[i].p_filesz; + // 段虚拟地址 + p_vaddr = elf->p_headers[i].p_vaddr; + // 段映射结果大小,其实不太需要对齐,因为之后的逻辑已经处理了 + seg_map_sz = ROUND_UP(elf->p_headers[i].p_memsz, PAGE_SIZE); + if (ROUND_DOWN(p_vaddr, PAGE_SIZE) + seg_map_sz < p_vaddr + elf->p_headers[i].p_memsz) { + seg_map_sz += PAGE_SIZE; + } pmo = obj_alloc(TYPE_PMO, sizeof(*pmo)); if (!pmo) { @@ -179,9 +188,19 @@ static u64 load_binary(struct process *process, * You should copy data from the elf into the physical memory in pmo. * The physical address of a pmo can be get from pmo->start. */ + const char *section_data; + char *alloc_section; + + // 复制段内存 + section_data = bin + elf->p_headers[i].p_offset; + alloc_section = (char *) phys_to_virt(pmo->start); + kdebug("Copy segment[%d] from addr %lx -> %lx, len = %d\n", i, section_data, alloc_section, seg_sz); + memcpy(alloc_section, section_data, seg_sz); flags = PFLAGS2VMRFLAGS(elf->p_headers[i].p_flags); + kdebug("Map segment[%d] from paddr %lx -> %lx, len = %d\n", + i, pmo->start, ROUND_DOWN(p_vaddr, PAGE_SIZE), seg_map_sz); ret = vmspace_map_range(vmspace, ROUND_DOWN(p_vaddr, PAGE_SIZE), seg_map_sz, flags, pmo); diff --git a/lab3/kernel/sched/context.c b/lab3/kernel/sched/context.c index 09d3c8e..0424864 100644 --- a/lab3/kernel/sched/context.c +++ b/lab3/kernel/sched/context.c @@ -56,6 +56,12 @@ void init_thread_ctx(struct thread *thread, u64 stack, u64 func, u32 prio, */ /* Fill the context of the thread */ + // 栈寄存器 + thread->thread_ctx->ec.reg[SP_EL0] = stack; + // PC 计数器 + thread->thread_ctx->ec.reg[ELR_EL1] = func; + // 状态字寄存器 + thread->thread_ctx->ec.reg[SPSR_EL1] = SPSR_EL1_EL0t; /* Set thread type */ thread->thread_ctx->type = type; diff --git a/lab3/kernel/sched/sched.c b/lab3/kernel/sched/sched.c index dfdc3f9..dd0a704 100644 --- a/lab3/kernel/sched/sched.c +++ b/lab3/kernel/sched/sched.c @@ -72,5 +72,5 @@ u64 switch_context(void) * Return the correct value in order to make eret_to_thread work correctly * in main.c */ - return 0; + return (u64) &target_ctx->ec; } diff --git a/note.org b/note.org index 355e9b7..35c53d2 100644 --- a/note.org +++ b/note.org @@ -121,3 +121,32 @@ boot/mmu.c:L109-110 映射了 KBASE+512M~KBASE+4G 因此只需要类似操作,补全中间的 256M 即可。 注意的是,寄存器保存的地址是 paddr_t + +** Lab 3 + +*** Capability + +好像和 MC、Linux 的 Cap 都不太一样。这里的 Cap 是一个可变的描述符,用来指代一个内核资源。 + +比起 Cap,更像是一个对象表。 + +*** 练习1 + +**** ELF 读入 + +ELF Section、Segment 两个概念。 + +- Section 是程序中的不同节,比如 .text。 +- Segment 是程序中实际分配的不同段,包括多个 Section,可以用 `readelf -l` 查看关系 + +主要操作就是计算偏移与复制。 + +其实连对齐都不用,直接就干上去也行,反正之前页表的时候已经处理了没对齐的情况。 + +**** 初始化线程上下文 + +照着文字写就行,初始化 TCB + +**** 切换上下文 + +返回上下文结构体的首地址就行