linux-mips-fnet
[Top] [All Lists]

Q: R3000, how to manipulate CP0_EPC?

To: linux-mips@fnet.fr
Subject: Q: R3000, how to manipulate CP0_EPC?
From: harald.koerfgen@netcologne.de
Date: Tue, 27 Jan 1998 18:32:09 +0100 (MET)
Organization: none
Reply-to: harald.koerfgen@netcologne.de
Sender: harry@franz.netcologne.de
Hello MIPS hackers,

as I've mailed before the DECstation kernel crashes because the return from the
very first syscall instruction does not work properly. After two weeks of
playing my favourite adventure game "Leisure Suit Harry looking for bugs (in
several wrong places)" I think I have found the cause (but not the cure).

This is the begin of the RESTORE_ALL macro, which is used in ret_from_sys_call:
#define RESTORE_ALL                                      \
                mfc0    t0, CP0_STATUS;                  \
                nop;                                     \
                ori     t0, 0x01;                        \
                xori    t0, 0x01;                        \
                mtc0    t0, CP0_STATUS;                  \
                lw      v0, PT_STATUS(sp);               \
                lw      v1, PT_LO(sp);                   \
                mtc0    v0, CP0_STATUS;                  \
                mtlo    v1;                              \
                lw      v0, PT_HI(sp);                   \
                lw      v1, PT_EPC(sp);                  \
                mthi    v0;                              \
                mtc0    v1, CP0_EPC;                     \
..

PT_EPC is manipulated in do_sys to point behind the syscall instruction and a
PRINT(...) shows that v1 contains the correct value. Nevertheless CP0_EPC
remains to be unchanged.

After finding that, I used the following test code:
#define RESTORE_ALL_TEST                                \
                lui     v0,0xffff;                      \
                mtc0    v0,CP0_EPC;                     \
                nop;                                    \
                mfc0    a1,CP0_EPC;                     \
                nop;                                    \
                PRINT("CP0_EPC   : %08x\n");            \

which "compiles" into:
800375d0 <return_test> lui $v0,0xffff
800375d4 <return_test+4> mtc0 $v0,$14
800375dc <return_test+c> mfc0 $a1,$14
800375e4 <return_test+14> lui $a0,0x800c
800375e8 <return_test+18> jal 80054478 <printk>
800375ec <return_test+1c> addiu $a0,$a0,5680  

and the result is:
CP0_EPC   : 80036aa4

which is the address of the syscall instruction itself. But the result should be
0xFFFF0000, shouldn't it?.

Has anybody an explanation for this, or am I just completely blind?

---
regards,
Harald

<Prev in Thread] Current Thread [Next in Thread>