diff --git a/lab4/kernel/common/lock.c b/lab4/kernel/common/lock.c index 93a770a..f2dc95f 100644 --- a/lab4/kernel/common/lock.c +++ b/lab4/kernel/common/lock.c @@ -91,6 +91,8 @@ void unlock(struct lock *lock) * Unlock the ticket lock here * Your code should be no more than 5 lines */ + // 因为仍在临界区,所以可以直接 ++ + lock->owner++; } /** @@ -101,7 +103,7 @@ void unlock(struct lock *lock) */ int is_locked(struct lock *lock) { - return -1; + return lock->owner != lock->next; } /** @@ -110,6 +112,7 @@ int is_locked(struct lock *lock) */ void kernel_lock_init(void) { + lock_init(&big_kernel_lock); } /** @@ -118,6 +121,7 @@ void kernel_lock_init(void) */ void lock_kernel(void) { + lock(&big_kernel_lock); } /** @@ -126,4 +130,5 @@ void lock_kernel(void) */ void unlock_kernel(void) { + unlock(&big_kernel_lock); } diff --git a/lab4/kernel/common/smp.c b/lab4/kernel/common/smp.c index 17bd153..969ee32 100644 --- a/lab4/kernel/common/smp.c +++ b/lab4/kernel/common/smp.c @@ -34,11 +34,13 @@ void enable_smp_cores(void *addr) * _start of `start.S`. Then, what's the flag? * You only need to write one line of code. */ + secondary_boot_flag[i] = 1; /* Lab4 * The BSP waits for the currently initializing AP finishing * before activating the next one */ + while (cpu_status[i] != cpu_run); } /* This information is printed when all CPUs finish their initialization */ diff --git a/lab4/kernel/exception/exception.c b/lab4/kernel/exception/exception.c index 499f16b..2cdfb34 100644 --- a/lab4/kernel/exception/exception.c +++ b/lab4/kernel/exception/exception.c @@ -54,6 +54,9 @@ void handle_entry_c(int type, u64 esr, u64 address) * Lab4 * Acquire the big kernel lock, if the exception is not from kernel */ + if (type >= SYNC_EL0_64) { + lock_kernel(); + } /* ec: exception class */ u32 esr_ec = GET_ESR_EL1_EC(esr); diff --git a/lab4/kernel/exception/exception_table.S b/lab4/kernel/exception/exception_table.S index c41a725..d9dbb61 100644 --- a/lab4/kernel/exception/exception_table.S +++ b/lab4/kernel/exception/exception_table.S @@ -91,6 +91,9 @@ * unlock the big kernel lock before returning to the user mode */ .macro exception_return + + bl unlock_kernel + exception_exit .endm diff --git a/lab4/kernel/exception/irq.c b/lab4/kernel/exception/irq.c index 47b39d6..9a71412 100644 --- a/lab4/kernel/exception/irq.c +++ b/lab4/kernel/exception/irq.c @@ -40,6 +40,9 @@ void handle_irq(int type) * The irq is not from the kernel * The thread being interrupted is an idle thread. */ + if (type >= SYNC_EL0_64 || current_thread->thread_ctx->type == TYPE_IDLE) { + lock_kernel(); + } plat_handle_irq(); diff --git a/lab4/kernel/main.c b/lab4/kernel/main.c index d2fbcd6..f0e1bf8 100644 --- a/lab4/kernel/main.c +++ b/lab4/kernel/main.c @@ -66,6 +66,7 @@ void main(void *addr) */ kernel_lock_init(); kinfo("[ChCore] lock init finished\n"); + lock_kernel(); /* Init scheduler with specified policy. */ sched_init(&rr); @@ -112,6 +113,7 @@ void secondary_start(void) * Inform the BSP at last to start cpu one by one * Hints: use cpu_status */ + cpu_status[smp_get_cpu_id()] = cpu_run; #ifndef TEST run_test(false); @@ -121,6 +123,7 @@ void secondary_start(void) * Lab4 * Acquire the big kernel lock */ + lock_kernel(); /* Where the AP first returns to the user mode */ sched(); diff --git a/note.org b/note.org index e235e26..4d94523 100644 --- a/note.org +++ b/note.org @@ -181,3 +181,17 @@ process_create_root、thread_create_main 直接写在注释里面了。 正常情况下还需要调用 commit_page_to_pmo 记录具体的分配物理页,要不然无法回收。但是注释说为了简便起见就不做了。 顺便吐槽一下开了 Debug 日志就没办法通过样例了,因为 brk 样例触发缺页中断会输出一个 Debug,正好在"0,[Debug]...1,2,..."。 + +** Lab 4 + +*** 练习1 + +基本流程其实类似。但是对于其他 cpu 并不是单纯死循环,而是等待 bss 段清空、切换权限等级、等待多核准备完成最后进入 c 入口。 + +*** 练习3 + +boot 阶段的栈是独立的。函数也没调用几个,我猜测可能是 el1_mmu_activate 函数的问题? + +*** 练习6 + +原因是 unlock_kernel 后才进行从栈恢复,而且函数退出时内核栈还是空的,所以 unlock 的时候无所谓。