Fix a problem seen when a new process was returning to userland

through fork_trampoline.

This was caused because we were clearing the SR_INT_IE and setting
SR_EXL bits of the status register at the same time. This meant
that if an interrupt happened while this MTC0 was making its way
through the pipeline the exception processing would see the
status register with SR_EXL bit set. This in turn would mean that
the COP_0_EXC_PC would not be updated so the return from exception
would be to an incorrect address.

It is easy to verify this fix by a program that forks in a loop
and the child just exits:

	while (1) {
	pid_t pid = vfork();
	if (pid == 0)
	       _exit(0);
	if (pid != -1)
	       waitpid(pid, NULL, 0);
	}

Also remove two instances where we set SR_EXL bit gratuitously in exception.S.

Approved by: imp (mentor)
This commit is contained in:
Neel Natu 2010-01-26 02:26:04 +00:00
parent fe1ee31bc8
commit 49396cced3
3 changed files with 6 additions and 12 deletions

View File

@ -106,7 +106,11 @@
#elif defined(CPU_SB1)
#define COP0_SYNC ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop
#else
#define COP0_SYNC /* nothing */
/*
* Pick a reasonable default based on the "typical" spacing described in the
* "CP0 Hazards" chapter of MIPS Architecture Book Vol III.
*/
#define COP0_SYNC ssnop; ssnop; ssnop; ssnop; ssnop
#endif
#define COP0_HAZARD_FPUENABLE nop; nop; nop; nop;

View File

@ -519,9 +519,6 @@ NNON_LEAF(MipsUserGenException, STAND_FRAME_SIZE, ra)
and t0, t0, ~(MIPS_SR_INT_IE)
mtc0 t0, COP_0_STATUS_REG
ITLBNOPFIX
or t0, t0, SR_EXL
mtc0 t0, COP_0_STATUS_REG # set exeption level
ITLBNOPFIX
/*
* The use of k1 for storing the PCB pointer must be done only
@ -751,9 +748,6 @@ NNON_LEAF(MipsUserIntr, STAND_FRAME_SIZE, ra)
and t0, t0, ~(MIPS_SR_INT_IE)
mtc0 t0, COP_0_STATUS_REG
ITLBNOPFIX
or t0, t0, SR_EXL
mtc0 t0, COP_0_STATUS_REG # set exeption level
ITLBNOPFIX
GET_CPU_PCPU(k1)
lw k1, PC_CURPCB(k1)

View File

@ -171,13 +171,9 @@ LEAF(fork_trampoline)
1:
mfc0 v0, COP_0_STATUS_REG # set exeption level bit.
or v0, SR_EXL
and v0, ~(SR_INT_ENAB)
mtc0 v0, COP_0_STATUS_REG # set exeption level bit.
nop
nop
nop
nop
COP0_SYNC
.set noat
move k1, a1
RESTORE_U_PCB_REG(t0, MULLO, k1)