用户态和内核态(也称用户模式和内核模式): 它们是 CPU 运行的两种状态。根据 lab3 的说明,在 MOS 操作系统实验使用的仿真 R3000 CPU 中,该状态由 CP0 SR 寄存器中 KUc 位的值标志。
syscall_* 的函数是我们在用户空间中最接近的内核的也是最原子的函数,而 sys_* 的函数是内核中系统调用的具体实现部分
mysyscall中syscall后epc保存syscall的pc值,然后跳到异常处理程序执行
进程的pgdir的值是内核地址
访问TLB得到物理地址时直接用12-31位的虚拟页号,TLB缺页重填时才利用页目录号和页表号进行访存
进程的env_pgfault_handler是__asm_pgfault_handler
页写入异常流程:handle_mod---->page_fault_handler---->__asm_pgfault_handler---->__pgfault_handler(pgfault)
fork的sys_env_alloc中子进程的pc被设置为epc(syscall的下一条指令,从mysyscall返回,然后从系统调用返回,返回到fork)
NESTED(except_vec3, 0, sp) .set noat .set noreorder 1: mfc0 k1,CP0_CAUSE la k0,exception_handlers andi k1,0x7c addu k0,k1 lw k0,(k0) nop jr k0 nop END(except_vec3)
struct Env { struct Trapframe env_tf; // Saved registers LIST_ENTRY(Env) env_link; // Free list u_int env_id; // Unique environment identifier u_int env_parent_id; // env_id of this env's parent u_int env_status; // Status of the environment Pde *env_pgdir; // Kernel virtual address of page dir u_int env_cr3; LIST_ENTRY(Env) env_sched_link; u_int env_pri; // Lab 4 IPC u_int env_ipc_value; // data value sent to us u_int env_ipc_from; // envid of the sender u_int env_ipc_recving; // env is blocked receiving u_int env_ipc_dstva; // va at which to map received page u_int env_ipc_perm; // perm of page mapping received // Lab 4 fault handling u_int env_pgfault_handler; // page fault state u_int env_xstacktop; // top of exception stack
struct Trapframe { //lr:need to be modified(reference to linux pt_regs) TODO /* Saved main processor registers. */ unsigned long regs[32]; /* Saved special registers. */ unsigned long cp0_status; unsigned long hi; unsigned long lo; unsigned long cp0_badvaddr; unsigned long cp0_cause; unsigned long cp0_epc; unsigned long pc; };
汇编标志 | 作用 | 例子 |
---|---|---|
.align | 这条指令允许程序员指定一个大于下一个数据指令通常所需的对齐方式。该对齐方式被指定为2的幂 | .align 4 var: .word 0 对齐2^4=16字节边界 |
.set noat/at | 汇编器在执行宏展开时保留注册器$1,以保存中间值;如果代码尝试使用寄存器,将会发送警告或错误消息。当汇编程序使用$at时并不总是明显的,而且在某些情况下,程序员可能需要确保它不使用(例如在保存$1之前的异常处理程序中)。如果汇编程序需要在宏指令中使用$1,那么打开noat将使汇编程序生成一个错误消息,并允许程序员在不收到警告的情况下显式地使用它 | |
汇编 | 作用 |
---|---|
ret_from_exception | 使用RESTORE_SOME恢复现场,k0设置为epc的值,恢复sp寄存器,并跳到k0开始执行指令同时rfe |
RESTORE_SOME宏 | SR寄存器设置为,当前SR的中断掩码加上TF的SR的其他位,同时TF的寄存器恢复到当前现场 |
env_pop_tf | 更新ENTRY_HI,最后跳到pc执行,而不像ret_from_exception跳到epc执行 在时钟中断中,time_irq会跳到sched_yield执行,sched_yield执行env_run,env_run中调用env_pop_tf恢复现场,而不是ret_from_exception |
.macro RESTORE_SOME .set mips1 mfc0 t0,CP0_STATUS #t0是当前SR ori t0,0x3 xori t0,0x3 mtc0 t0,CP0_STATUS #关中断 lw v0,TF_STATUS(sp) #v0是TF的SR li v1, 0xff00 and t0, v1 #与8-15位中断掩码and 1 其他都为0 nor v1, $0, v1 #除8-15位全为1,8-15位为0 and v0, v1 #TF的SR 8-15位中断掩码为0 or v0, t0 #当前SR的中断掩码加上TF的SR的其他位 mtc0 v0,CP0_STATUS #TF的SR存到当前的SR寄存器 lw v1,TF_LO(sp) #TF的寄存器恢复到当前现场 但没有恢复sp,k0,k1寄存器 mtlo v1 lw v0,TF_HI(sp) lw v1,TF_EPC(sp) mthi v0 mtc0 v1,CP0_EPC lw $31,TF_REG31(sp) lw $30,TF_REG30(sp) lw $28,TF_REG28(sp) lw $25,TF_REG25(sp) lw $24,TF_REG24(sp) lw $23,TF_REG23(sp) lw $22,TF_REG22(sp) lw $21,TF_REG21(sp) lw $20,TF_REG20(sp) lw $19,TF_REG19(sp) lw $18,TF_REG18(sp) lw $17,TF_REG17(sp) lw $16,TF_REG16(sp) lw $15,TF_REG15(sp) lw $14,TF_REG14(sp) lw $13,TF_REG13(sp) lw $12,TF_REG12(sp) lw $11,TF_REG11(sp) lw $10,TF_REG10(sp) lw $9,TF_REG9(sp) lw $8,TF_REG8(sp) lw $7,TF_REG7(sp) lw $6,TF_REG6(sp) lw $5,TF_REG5(sp) lw $4,TF_REG4(sp) lw $3,TF_REG3(sp) lw $2,TF_REG2(sp) lw $1,TF_REG1(sp) .endm
FEXPORT(ret_from_exception) .set noat .set noreorder RESTORE_SOME .set at lw k0,TF_EPC(sp) lw sp,TF_REG29(sp) /* Deallocate stack */ //1: j 1b nop jr k0 rfe
LEAF(env_pop_tf) .set mips1 //1: j 1b nop move k0,a0 #a0是tf地址,a1是env的asid mtc0 a1,CP0_ENTRYHI #更新ENTRYHI的asid为当前进程的asid mfc0 t0,CP0_STATUS ori t0,0x3 xori t0,0x3 mtc0 t0,CP0_STATUS lw v1,TF_LO(k0) mtlo v1 lw v0,TF_HI(k0) lw v1,TF_EPC(k0) mthi v0 mtc0 v1,CP0_EPC lw $31,TF_REG31(k0) lw $30,TF_REG30(k0) lw $29,TF_REG29(k0) lw $28,TF_REG28(k0) lw $25,TF_REG25(k0) lw $24,TF_REG24(k0) lw $23,TF_REG23(k0) lw $22,TF_REG22(k0) lw $21,TF_REG21(k0) lw $20,TF_REG20(k0) lw $19,TF_REG19(k0) lw $18,TF_REG18(k0) lw $17,TF_REG17(k0) lw $16,TF_REG16(k0) lw $15,TF_REG15(k0) lw $14,TF_REG14(k0) lw $13,TF_REG13(k0) lw $12,TF_REG12(k0) lw $11,TF_REG11(k0) lw $10,TF_REG10(k0) lw $9,TF_REG9(k0) lw $8,TF_REG8(k0) lw $7,TF_REG7(k0) lw $6,TF_REG6(k0) lw $5,TF_REG5(k0) lw $4,TF_REG4(k0) lw $3,TF_REG3(k0) lw $2,TF_REG2(k0) lw $1,TF_REG1(k0) lw k1,TF_PC(k0) lw k0,TF_STATUS(k0) nop mtc0 k0,CP0_STATUS j k1 #跳到pc执行,而非epc rfe nop END(env_pop_tf)