lab3学习

struct Env {
     struct Trapframe env_tf;       // Saved registers 
     LIST_ENTRY(Env) env_link;      // Free LIST_ENTRY 
     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;
};

env_pgdir : 这个变量保存了该进程页目录的内核虚拟地址

env_cr3 : 这个变量保存了该进程页目录的物理地址。

env_sched_link : 这个变量用来构造调度队列。

env_pri : 这个变量保存了该进程的优先级。

u_int mkenvid(struct Env *e) 生成一个新的进程id

asid_alloc():根据int asid_bitmap[2]的64位生成一个asid

本实验里的寄存器状态保存的地方是TIMESTACK区域

关于汇编中的 beq k1 1f中的1f,在R3000中的原文如下

The assembler allows the use of numbers (decimal between 1-99) asa label. These are treated as ‘‘temporary’’, and are “re-usable”. In abranch instruction ‘‘1f’’ (forward) refers to the next ‘‘1:’’ label in thecode, and ‘‘1b’’ (back) refers to the last-met ‘‘1:’’ label.

即跳转到下一个1标签

运算宏 作用
ENVX 有效的envid
GET_ENV_ASID (((envid)>> 11)<<6)
定义宏 含义
#define STATUS_CU0 0x10000000 CP0_STATUS的CU0位,表示允许在用户模式下使用 CP0 寄存器
函数 作用
u_int mkenvid(struct Env *e) 生成一个新的进程id
asid_alloc() 根据int asid_bitmap[2]的64位生成一个asid
void env_free(struct Env *e) 解除所有内存页映射,释放asid,插入空闲进程块列表
void env_destroy(struct Env *e) free一个env,并且bcopy((void *)KERNEL_SP - sizeof(struct Trapframe),(void *)TIMESTACK - sizeof(struct Trapframe),sizeof(struct Trapframe));最后sched_yield();
env_pop_tf(&(curenv->env_tf), GET_ENV_ASID(curenv->env_id));
汇编函数
将curenv的env_tf之前保存的进程上下文恢复到当前进程的上下文,并将TLB重填中的ASID换成当前进程的
sched_yield 从调度进程队列里选队首进程调度,注意当进程被创建时插入的是list[0],并没有把curenv置为被创建的进程。同时不能在这个函数里把切换的进程e设置为curenv,否则在调度时无法保存被切换进程curenv的上下文
mips宏或函数 作用
CLI 读取CP0status寄存器,开启CU0(允许用户状态使用CP0寄存器),同时将IEc置0,关中断
SAVE_ALL 调用了get_sp宏,即当CP0_CAUSE第12位不为1且无异常时,将当前进程上下文保存到TIMESTACK的trapframe大小的空间中,反之保存到KERNAL_SP中
env_pop_tf .set mips1下面的指令是R2000/R3000指令,即MIPS I指令集
将切换运行的进程trapframe中保存的上下文恢复到当前上下文,并跳到trapframe的pc开始运行

IDT R30xx Family Software Reference Manual》阅读笔记

CP0寄存器 作用 CP0编号
SR (状态寄存器)CPU模式标志 12
Cause 描述最近识别的异常 13
EPC 来自trap的返回地址 14
BadVaddr 包含导致trap的最后一个无效程序地址。它是由各种地址错误设置的,即使没有MMU 8

SR

image-20220303213254529

标记位 作用
CU3 CU2 位(31:30)分别控制“协同处理器”3和2的可用性。在R30xx系列中,如果软件希望使用BrCond(3:2)输入引脚进行轮询,或加快异常解码的速度,则可以启用这些功能。
CU1 “协同处理器1可用”:1使用FPA,0禁用。当值为0时,所有FPA指令都会导致异常,即使是对内核。即使有可用的FPA,关闭FPA也是有用的;如果打算使用BrCond(1)pin作为轮询输入,它也可以在不包含FPA的设备中启用。
CU0 “协同处理器0可用”:设置1为能够在用户模式下使用一些名义上的特权指令(这很少这样做)。编码为“协处理器0”类型的CPU控制指令在内核模式下始终可用,无论此位的设置如何。
RE “在用户模式下反转环境”。MIPS处理器可以在重置时配置“环境性”(字节排序约定,在各种CPU的用户手册和本手册后面讨论)。RE位允许使用一个字节排序约定运行的二进制文件在约定相反的系统中运行,假设操作系统软件提供了必要的支持。当RE处于活动状态时,用户特权软件运行就像CPU配置了相反的环境一样。然而,实现跨宇宙运行也需要大量的软件工作,而且在嵌入式系统中应该不是必要的。
BEV “引导异常向量”:当BEV==1时,CPU使用ROM(kseg1)空间异常入口点(在后面的章节中描述)。在正在运行的系统中,BEV通常被设置为零;这将重新定位异常向量。对RAM地址,加速访问并允许使用“用户提供的”异常服务例程。
TS “TLB关闭”:在实现完整的R3000AMMU的设备中,如果一个程序地址同时匹配两个TLB条目,则TS将被设置。在某些实现中,在这种状态下的长时间操作可能会导致内部争用和损坏芯片。TLB关机是终端,只能通过硬件重置来清除。在不包括TLB的基本家族成员中,此位通过重置来设置;软件可以依赖此功能来确定是否存在TLB支持硬件。
PE 如果发生了缓存奇偶校验错误,请进行设置。这种情况不会产生异常,而这实际上只对诊断有用。MIPS体系结构具有缓存诊断功能,因为CPU的早期版本使用了外部缓存,这提供了一种验证特定系统的时间安排的方法。对于这些实现,缓存奇偶校验错误位是一个必要的设计调试工具。对于具有片上缓存的cpu,很少需要这一特性;只有R3071和R3081对片上缓存实现奇偶校验。
CM 显示使用隔离的Dcache执行的最后一次加载操作的结果(见缓存管理章节所述)。如果缓存确实包含寻址内存位置的数据(即:即使缓存没有被隔离,负载也会在缓存中命中),则设置CM
PZ 设置时,缓存奇偶校验位被写为零,不检查。这在需要外部缓存ram的旧R3000A系统中很有用,但与R30xx家族没有什么关系。
SwC,IsC “交换缓存“”和“”隔离(数据)缓存“”。用于缓存管理和诊断的缓存模式位;它们的使用将在后面的缓存管理章节中有详细介绍。简单地说:
IsC设置1:使所有加载和存储只访问数据缓存,而不访问内存;在这种模式下,部分字存储会使缓存条目无效。注意,当设置此位时,即使在总线上也看不到未缓存的数据访问;此外,此位不会通过重置进行初始化。引导软件必须确保在依赖外部数据引用之前正确地初始化这个位。
SwCset1:反转I-缓存和D-缓存的角色,以便软件可以访问并使I-缓存条目无效。
IM “中断掩码”:一个8位字段,定义在激活时哪个中断源可以导致异常。其中6个中断源是外部引脚(一个可以被FPA使用,尽管它生活在同一芯片上,但在逻辑上是外部的);另外两个是原因寄存器中的软件可写的中断位。CPU不提供中断优先级:硬件处理所有中断位都相同。这将在处理异常的章节中进行更详细的描述。
KUc,IEc 两个基本的CPU保护位。
当使用内核权限运行时,KUc设置为1,用户模式设置为0。在内核模式下,软件可以获取整个程序地址空间,并使用特权(“协同处理器0”)指令。用户模式限制软件的程序地址在0x0000 0000 和0x7FFFFFFF之间,并且可以拒绝运行特权指令的权限;尝试违反规则会导致异常。
IEc被设置为0,以防止CPU采取任何中断,并通过1来启用。
KUp, IEp “KU previous, IE previous”
在异常下,硬件取KUc和IEc的值并保存在这里;同时将KUc、IEc的值更改为[1,0](内核模式,禁用中断)。指令rfe可用于将KUp、IEp复制回KUc、IEc。
KUo, IEo ‘‘KU old, IE old’’
在一个异常下,KUp,IEp位被保存在这里。实际上,6个KU/IE位被作为一个3深、2位宽的堆栈操作,它在一个异常上推送并被rfe弹出。这提供了从异常处理例程中早期发生的异常中干净恢复的机会,因此第一个异常尚未保存SR。可以做到这一点的情况是有限的,而且它可能只在允许用户TLB重新填充代码变得更短方面真正有用,如内存管理一章所述。

Cause Register

image-20220303215119767

Cause寄存器中的字段”显示了原因寄存器中的字段,通过查阅这些字段来确定所发生的异常的类型,并将用于决定要调用哪个异常例程。

标记位 作用
BD “分支延迟”:如果设置,此位表示EPC不指向实际的“异常”指令,而是指向它之前的分支指令。当异常重启点是位于分支后面的“延迟槽”中的指令时,EPC必须指向分支指令;重新执行该分支是无害的,但是如果CPU从异常返回到分支延迟指令本身,该分支将不会被接受,异常将破坏中断的程序。软件可能对这一位敏感的唯一时间是,如果它必须分析“违规”指令(如果BD==1,那么该指令是在EPC+4)。如果需要模拟该指令(例如,没有硬件FPA的设备中的浮点指令;或放置在分支延迟槽中的断点),则会发生这种情况。
CE “协处理器错误“”:如果因为“协处理器”格式指令对应的“协处理器”在SR中的CUx位没有启用而发生异常,则此字段具有该指令的协处理器号
IP “中断待定”:显示当前断言的中断(但可能被“屏蔽”,无法实际发出异常信号)。这些位遵循六个硬件级别的CPU输入。位9和位8是可读/可写的,并包含最后一次写入它们的值。然而,当被适当的IM位和SR中的全局中断启用标志IEc启用时,激活的8位中的任何一个都会导致中断。IP与其他原因寄存器字段有细微的不同;它并不指示异常发生时发生了什么,而是显示现在发生了什么。
ExcCode 一种5位代码,它指示发生了什么类型的异常
ExcCode Value Mnemonic (助记符) Description
0 Int Interrupt
1 Mod ‘TLB modifification’’
(“TLB修改”)
2 TLBL TLB load
3 TLBS TLB store
4 AdEL 地址错误(在加载或存储时)。在用户模式下尝试访问kuseg外部,或者试图在一个不对齐的地址上读取一个单词或半单词
5 AdES 地址错误(在读取或存储时)。在用户模式下尝试访问kuseg外部,或者试图在一个不对齐的地址上读取一个单词或半单词
6 IBE 总线错误(指令获取)。外部硬件发出了某种错误的信号。适当的异常处理是依赖于系统的。R30xx系列CPU不能在存储时发生总线错误。R30xx系列CPU在存储时不能接受总线错误。写入缓冲器会使这种异常 "不精确"。
7 DBE 总线错误(数据加载)。外部硬件发出了某种错误的信号。适当的异常处理是依赖于系统的。R30xx系列CPU不能在存储时发生总线错误。R30xx系列CPU在存储时不能接受总线错误。写入缓冲器会使这种异常 "不精确"。
8 Syscall 由系统切换指令无条件生成的
9 Bp Breakpoint - a break instruction.
中断指令
10 RI reserved instruction
保留指令
11 CpU Co-Processor unusable
协处理器无法使用
12 Ov 算术溢出''。请注意,"无符号 "版本的指令(例如addu)从来不会引起这种异常。

EPC Register

这是一个32位的寄存器,包含这个异常的返回点的32位地址。的32位地址。导致(或遭受)异常的指令在EPC,除非BD在Cause中被设置,在这种情况下EPC指向前一条(分支)指令。

BadVaddr Register

一个32位的寄存器,包含了导致异常的地址;在任何与MMU相关的异常中,当用户程序试图访问kuseg以外的地址时,或者当一个地址被错误地对齐了所引用的数据量时,都会被设置。在任何其他异常情况下,这个寄存器都是未定义的。特别要注意的是 它在总线错误后不会被设置。

posted @ 2022-06-15 21:39  繁华丶人间  阅读(99)  评论(0编辑  收藏  举报