上面文章摘录了ARM关于system mode的官方解释,看着是挺合理的,但这个模式似乎并没有真的被使用。
先看MTK平台是怎么处理异常的。
由于MTK平台所有的code都是运行在SVC模式,并没有使用SWI陷入内核来进行系统调用这样一种需求,所以他所有的异常处理都会切换到SVC模式来进行处理。而一旦出现了SWI也就表示系统出错了,直接进入错误处理,即使lr被覆盖了也无所谓,程序已经不需要返回到哪里去了。在这样的系统需求中,不使用system mode是可以容易被理解的。
那我们看看那些需要使用SWI的系统是怎么设计的呢?比如Linux。我本以为在Linux上system mode应该会被使用了,但并不是这样的。
在Linux上分内核空间和用户空间,用户空间的程序只能通过系统调用才能陷入到内核空间执行一些权限敏感的动作。这样一种机制在ARM上的实现就是有SWI来实现的。内核空间的程序运行在SVC模式下,用户空间的程序运行在USR模式下。当用户空间的程序调用系统调用时通过引发一个SWI异常来陷入到SVC模式下。现在SWI异常是有用处的了,所以如果其他的异常模式还是切换到SVC模式下,如果这时发生了一个SWI异常,那lr不是有可能不能恢复了吗?所以在Linux中,所以的异常模式应该切换到system mode下了吧?在Linux下,所有的异常还是切换到SVC模式下处理的。想了好久,应该是有下面两个原因:
1)SWI在Linux中只用作系统调用的实现,也就是只有从USR模式切换到SVC模式时发生的SWI才是有效的。如果在SVC模式下发生了SWI,就表示发生了一个无法返回的错误,所以lr被覆盖就没什么大的影响了。
2)system mode是和USR模式公用所有寄存器的。如果异常处理程序切换到系统模式,使用和USR模式相同的堆栈,这在一定程度上是不安全的。
或许是基于上面的理由的,Linux的异常处理程序还是切换到SVC模式去运行的。其实可以验证一下第一点的推论,看看Linux的SWI异常中有没有对异常发生前模式的检测。
上面大部分都是一些个人理解吧,Linux的coe还没怎么看,还需要进行一些验证。
那system mode能用作哪里呢?按ARM的说法,这个模式是特意在新的版本中添加的模式,可为什么现在看,总感觉是个可有可无的东西呢?希望高手能给点指引。