晶羽科技-解读点评影视小说作品

微信
手机版

xch汇编,cx汇编

2023-11-30 03:57 作者:岑岑 围观:

Xv6必须设置x86硬件在遇到int指令时做一些合理的事情,这将导致处理器生成一个陷阱。x86允许256种不同的中断。中断0-31是为软件异常定义的,比如除法错误或试图访问无效的内存地址。Xv6将32个硬件中断映射到范围32-63,并将中断64用作系统调用中断。

Xv6在遇到int指令时必须设置x86硬件执行一些合理的操作,这会导致处理器产生陷阱。X86允许256种不同的中断。中断0-31是为软件异常而定义的,例如除法错误或试图访问无效的存储器地址。Xv6将32个硬件中断映射到范围32-63,并将中断64用作系统调用中断。

从main调用的Tvinit (3367)在表idt中设置了256个条目。中断I由vectorstvinit中地址的代码处理

Tvinit处理T_SYSCALL,用户系统调用陷阱,特别是:它通过传递值1作为第二个参数来指定gate是“trap”类型。陷阱门不清除IF标志,允许系统调用处理程序期间的其他中断。

Tvinit处理T_SYSCALL,用户系统调用trap。特别是,它通过将值1作为第二个参数来指定门的类型为“trap”。陷阱门不清除IF标志,允许系统调用处理程序期间的其他中断。

内核还将系统调用门权限设置为DPL用户,这允许用户程序使用显式int指令生成陷阱。xv6不允许进程用int引发其他中断(比如设备中断);如果他们尝试,他们将会遇到一个一般的保护异常,这将进入向量13。

内核还将系统调用门特权设置为DPL用户,这允许用户程序使用显式int指令生成陷阱。Xv6不允许进程以int的形式触发其他中断(比如设备中断);如果他们尝试,他们将会遇到一个一般的保护异常,这将进入向量13。

当将保护级别从用户模式更改为内核模式时,内核不应该使用用户进程的堆栈,因为它可能无效。用户进程可能是恶意的或包含错误,导致用户%esp包含不属于该进程用户内存的地址。Xv6对x86硬件进行编程,通过设置任务段描述符在陷阱上执行堆栈切换,硬件通过任务段描述符加载堆栈段选择器和%esp的新值。函数switchuvm (1860)将用户进程的内核堆栈顶部的地址存储到任务段描述符中。

switchuvm

将保护级别从用户模式更改为内核模式时,内核不应使用用户进程的堆栈,因为它可能无效。用户进程可能是恶意的或包含错误,导致用户%esp包含不属于用户进程内存的地址。Xv6通过设置任务段描述符对x86硬件进行编程,使其在陷阱上执行堆栈切换,硬件通过该描述符加载堆栈段选择器和% esp的新值。函数switchuvm(1860)将用户进程的内核栈顶地址存储在任务段描述符中。

当陷阱发生时,处理器硬件执行以下操作。如果处理器在用户模式下执行,它从任务段描述符加载%esp和%ss,将旧的用户%ss和%esp推送到新的堆栈上。如果处理器在内核模式下执行,上述情况都不会发生。然后,处理器推入%eflags、%cs和%eip寄存器。对于某些陷阱(例如页面错误),处理器还会推出一个错误字。然后,处理器从相关的IDT条目加载%eip和%cs。

当陷阱发生时,处理器硬件执行以下操作。如果处理器在用户模式下执行,它将从任务段描述符加载%esp和%ss,并将旧用户%ss和%esp压入新堆栈。如果处理器在内核模式下执行,这种情况不会发生。然后,处理器将推入%eflags、%cs和%eip寄存器。对于某些陷阱(例如页面错误),处理器还会推送错误字。然后,处理器从相关的IDT条目中加载%eip和%cs。

xv6使用Perl脚本(3250)来生成IDT条目指向的入口点。如果处理器没有发送错误代码,每个条目发送一个错误代码,发送中断号,然后跳转到alltraps。

Xv6使用Perl脚本(3250)生成IDT条目指向的入口点。如果处理器不这样做,每个条目将推送一个错误代码,推送中断号,然后跳转到alltrap。

Alltraps (3304)继续保存处理器寄存器:它推送%ds、%es、%fs、%gs和通用寄存器(3305-3310)。这一努力的结果是内核堆栈现在包含了一个struct trapframe (0602 ),它包含了陷阱发生时的处理器寄存器(见图3-2)。处理器推送%ss、%esp、%eflags、%cs和%eip。处理器或陷阱向量推送一个错误号,alltraps推送其余的错误号。当内核返回到当前进程时,陷阱帧包含恢复用户模式处理器寄存器所需的所有信息,以便处理器可以完全像陷阱开始时一样继续运行。回想一下第2章,用户手工构建了一个陷框来实现这个目标(见图1-4)。

alltraps

陷框

Alltraps(3304)继续保存处理器寄存器:它将推送%ds、%es、%fs、%gs和通用寄存器(3305-3310)。由于这一努力,内核堆栈现在包含了一个struct trapframe(0602),它包含了捕获时的处理器寄存器(见图3-2)。处理器按下了%ss、%esp、%eflags、%cs和%eip。处理器或陷阱向量推送一个错误号,而alltrap推送其余的错误号。当内核返回到当前进程时,陷阱帧包含恢复用户模式处理器寄存器所需的所有信息,以便处理器可以继续运行,就像陷阱启动时一样。回想一下第2章,userinit手工构建了一个陷阱框架来实现这个目标(见图1-4)。

在第一次系统调用的情况下,保存的%eip是紧接在int指令之后的指令的地址。%cs是用户代码段选择器。%eflags是执行int指令时%eflags寄存器的内容。作为保存通用寄存器的一部分,alltraps还保存%eax,它包含系统调用号,供内核以后检查。

在第一次系统调用的情况下,保存的%eip是紧接在int指令之后的指令的地址。%cs是用户代码段选择器。执行int指令时,%eflags是%eflags寄存器的内容。作为保存通用寄存器的一部分,alltraps还保存%eax,它包含内核稍后将检查的系统调用号。

既然用户模式处理器寄存器已经保存,alltraps可以完成设置处理器来运行内核C代码了。处理器在进入处理程序之前设置了选择器%cs和% ssalltraps集合%ds和%es (3313-3315)。

既然用户模式处理器寄存器已经保存,alltraps可以完成设置处理器来运行内核C代码了。处理器在进入处理程序之前设置了选择器%cs和%ss。Alltraps集合%ds和%es(3313-3315)。

一旦段被正确设置,alltraps可以调用C陷阱处理程序trap。它将指向它刚刚构建的陷阱框架的%esp作为trap的参数推送到堆栈上(3318)。然后它调用trap (3319)。trap返回后,alltraps通过添加堆栈指针(3320)将参数弹出堆栈,然后开始执行标签trapret处的代码。当第一个用户进程运行它并退出到用户空间时,我们在第2章中跟踪了这段代码。这里发生了相同的序列:通过陷阱帧弹出恢复用户模式寄存器,然后iret跳回用户空间。

一旦段设置正确,alltrap就可以调用C trap来处理陷阱。它将指向它刚刚构建的陷阱框架的%esp作为trap的参数推送到堆栈上(3318)。然后调用trap(3319)。陷阱返回后,alltrap通过将参数添加到堆栈指针(3320)来弹出堆栈,然后开始执行标签trapret处的代码。在第2章中,我们跟踪了第一个用户进程运行代码以退出用户空时的代码。这里发生了同样的事情:用户模式寄存器被trap帧的弹出恢复,然后IRET跳转回user 空。

到目前为止的讨论已经谈到了在用户模式下发生的陷阱,但是陷阱也可能在内核执行时发生。在这种情况下,硬件不切换堆栈或保存堆栈指针或堆栈段选择器;否则,将出现与用户模式陷阱中相同的步骤,并执行相同的xv6陷阱处理代码。当iret稍后恢复内核模式%cs时,处理器继续在内核模式下执行。

到目前为止,我们一直在讨论发生在用户模式下的陷阱,但陷阱也可能发生在内核执行时。在这种情况下,硬件不切换堆栈或保存堆栈指针或堆栈段选择器;否则,将出现与用户模式陷阱中相同的步骤,并执行相同的Xv6陷阱处理代码。当iret稍后恢复内核模式%cs时,处理器将继续在内核模式下执行。

相关文章