【MIPS CPU 体系结构概述2】连载11:

好了,说了一通系统调用,无非是想让大家明白内核中寄存器的保存恢复过程,以及 为了少做些无用功所做的努力.下面看为什么要save_static_function:为了避免 s0寄存器的破坏.

如果我们使用

sys_rt_sigsuspend()
{
save_static;

}

会有什么问题呢,请看,

Nasty degree - 3 days of tracking.

The symptom was pthread cannot be created. In the end the caller will get a BUS error.
What exactly happened has to do with how registers are saved. Below attached is the beginning part of sys_sigsuspend() function. It is easy to see that s0 is saved into stack frame AFTER its modified. Next time when process returns to userland, the s0 reg will be wrong!

So the bug is either

1) that we need to save s0 register in SAVE_SOME and not save it in save_static; or that
2) we fix compiler so that it does not use s0 register in that case (it
does the same thing for sys_rt_sigsuspend)
I am sure Ralf will have something to say about it. :-) In any case, I attached a patch for 1) fix.

sys_sigsuspend(struct pt_regs regs)
{
8008e280: 27bdffc0 addiu $sp,$sp,-64
8008e284: afb00030 sw $s0,48($sp)
sigset_t *uset, saveset, newset;

save_static(&regs);

8008e288: 27b00040

8008e28c: afbf003c
8008e290: afb20038
8008e294: afb10034
8008e298: afa40040
8008e29c: afa50044
8008e2a0: afa60048
8008e2a4: afa7004c
8008e2a8: ae100058
8008e2ac: ae11005c

#ifdef CONFIG_SMP
# define GET_SAVED_SP

addiu $s0,$sp,64 /* save_static时
s0已经破坏*/
sw $ra,60($sp)
sw $s2,56($sp)
sw $s1,52($sp)
sw $a0,64($sp)
sw $a1,68($sp)
sw $a2,72($sp)
sw $a3,76($sp)
sw $s0,88($s0)
sw $s1,92($s0)

\
mfc0 k0, CP0_CONTEXT; \

lui k1, %hi(kernelsp); \

srl k0, k0, 23; \

sll k0, k0, 2; \

addu k1, k0; \
lw k1, %lo(kernelsp)(k1);

#else
# define GET_SAVED_SP \
/*实际上就是k1 = kernelsp, kernelsp保存当前进程的内核栈指针 */
lui k1, %hi(kernelsp); \
lw k1, %lo(kernelsp)(k1);
#endif

--电子创新网--
粤ICP备12070055号