Page 1 of 1

IOP Exception handler ?

Posted: Thu Sep 09, 2004 1:14 pm
by pixel
Okay, I have dig a bit thru the IOP. I found out that the exception handler located at 0x80000080 will actually search for an exception vector at 0x440. So, I wrote my own exception handler, and put its address there. Everything goes fine, I can even manage to callback a C function, mainly during interrupts. I call back the old manager at the end of my function. I also noticed that the normal manager search for what I would call "user land exception handler vector" at 0x5F0. So, I also tried to put a function there. In both cases, everything runs fine during normal mode (that is, interrupts goes there, and runs fine), but whenever I launch a syscall, or a defective load (like lw $a0, 1($0)), the IOP completely stalls. I can't know if my function are called, nor what I should exactly do there. The most obvious thing I did was:

Code: Select all

#define EPC ((u32 *)(0x404)) // that's where the kernel's handler stores EPC.
#define USER_HANDLER ((u32 *)(0x5F0)) // that's where the kernel's handler reads the custom handler.

int my_handler(void * arg) {
    EPC[0] = 0;  // remove the defective instruction
    return 0; // the kernel's exception handler should go back to epc afterward.
}

void install_and_stuff(void) {
    int intrStat;
    CpuDisableIntr(&intrStat);
    USER_HANDLER[0] = my_handler;
    CpuEnableIntr(&intrStat);
    printf("Before?\n");
    __asm__("lw $a0, 1($0)\n"); // let's crash
    printf("After?"\n");
}
But this doesn't work...

I am now out of ideas. Does somebody have some spare for me ? :P

Re: IOP Exception handler ?

Posted: Thu Sep 09, 2004 2:20 pm
by Guest
Just a few days ago I went through this same exercise on the EE side.
I ran into these issues:

1. I had to end up installing the exception vectors as KSEG0 addresses.
Exception vectors wanted everything to be KSEG0 (I also had TLB
exceptions if I didn't)
2. I had to modify the actual contents of memory using KSEG1 addresses
in order to avoid TLB issues there (mostly because ps2link was not running in
kernel mode).
3. Things still hosed unless I flushed both I and D caches before and after
modifying the vector contents and the "patches" I made the instructions
within the exception code. In other words, I was "poking" modified
instructions into memory. This probably was corrupting and confusing
the caches as to what was I and what was D.
4. I had to continuously called ee_kmode_enter() or whatever before
every syscall I made for debug printfs() and anything else in order
to avoid TLB errors.

I am away from my code right now, but I can forward it to you later on
so you can see if what I did on the EE side can apply to the IOP. It was
much trial and error. Most of the problems I had were TLB and bad
address exceptions.

BTW, everything was working in the end.

Gorim

Posted: Thu Sep 09, 2004 4:42 pm
by redcoat
Ironically, I have been pondering the issue of IOP exception handling and reporting over the last couple of days. My first couple of simple EE-side apps caused exceptions, but ps2link has that very handy exception handler builtin to give a register dump (on the PS2's screen)--my thanks to pukko & adresd for that one ;)

As a newbie, coding an IOP handler is still way over my head, but I wanted to let you guys know that I'm interested in seeing this idea/code developed further. Especially, in the area of IOP exception reporting, if possible via ps2link. If I can help idiot-proof your work (being a newbie I figure I'm nearly equivalent to an idiot :P)

On the related topic of diagnostic information, has there been any work done of parsing an ELF file (when ps2link loads it in the EE's memory) for STABS(ECOFF) debug information that GCC can generate. I was considering this at the same time as the IOP exception handling and realized it would be incredibly helpful if ps2link could, at least, spit-out the source code line number (from the debug info.) when an exception occurs. I appreciate this is a non-trivial problem, but I'm curious to know if this idea has been considered.

Re: IOP Exception handler ?

Posted: Thu Sep 09, 2004 5:05 pm
by redcoat
pixel wrote:I can't know if my function are called, nor what I should exactly do there.

I am now out of ideas. Does somebody have some spare for me ? :P
Here is an idea for you to find out if your exception handler function has been called or not.

Have your handler generate a specific byte code sequence in the IOP's memory and then put a copy of the IOP's registers after this byte code sequence.

Then on the EE-side, when the IOP stalls or you decide it has stalled, have a app. that searches the IOP memory (start at 0xBC000000 in the EE's memory ;) ) for your byte code sequence. If you find it you know:
a) your handler was called
b) what was in the IOP's register

OK, that's it...just an idea ;)

Re: IOP Exception handler ?

Posted: Thu Sep 09, 2004 6:32 pm
by Guest
pixel wrote:

Code: Select all

int my_handler(void * arg) {
    EPC[0] = 0;  // remove the defective instruction
    return 0; // the kernel's exception handler should go back to epc afterward.
}
I think this may be the problem. EPC is the address of the instruction
that caused the exception. It is supposed to be incremented to the next
instruction before return from exception (and while taking proper case
in the cases of branches and branch delay slots, so its sometimes more
complex than a simple increment). After the handler executes, it uses
this address for the "return". (jr $EPC, there is no "eret" on R3000a).

So you should not be setting it equal to zero. In fact, the main routine
at 0x80 probably takes care of the incrementing for you before jumping
to the individual handler for that cause event. So your handler might need
only jr back to that specific address, or jr back into the main exception
routine, which will itself jr back to your program.

Or just look for me on #ps2dev tonight ;)

Gorim

Posted: Thu Sep 09, 2004 9:46 pm
by pixel
redcoat: actually, the EE stalls too... Hum.... But maybe it's because it stalls during the RPC...

gorim: I actually could give you the full disassembly code located at 80. There's not much things actually, and I've seen nowhere the incrementation before jumping back. The whole handler at 80 is actually "interrupt oritented". Or maybe I am only missing some flags in the cop0. Or... would I have to reenable the interrupts afterward ?

On a side note though, Herben told me he has some working piece of code for me, he has to dig it up though :p

Exception handling on the EE and IOP

Posted: Thu Sep 09, 2004 10:21 pm
by tjd
On the IOP, I found it easiest to install a new handler using excepman. If you don't have the library stub, I can post it. The call is:
RegisterDefaultExceptionHandler(your-trap-handler);

It's better to do this than install you own handler since the basic IOP has to keep running and I'd rather be able to debug the trap handler by carefully injecting exceptions, than by throwing everything at it at once.


Also, on the R3000, you use an "rfe" instruction. Its very important, especially if you are the first handler" to restore as much of the machine state as possible before returning. And yes, EPC does have to get fiddled around to account for delay slots, conditional branches etc.

As for the EE, it is pretty straighforward-- no fiddling with KSEG0/1 etc. is needed. Just use the standard calls for defining handlers.

I have have code (EE & IOP) which prints out the registers and a stack trace if anyone is interested. After that, I moved on and have gdb running on both the EE and IOP. Life is much nicer now that I've [re-]entered the 1980's... Symbolic debugging: stack traces, breakpoints, printing out complicated C++ structures from the debugger-- who wouldda thought?

tjd

ps. All this trap handling at the basic levels is much more suited to assembly language than C. You have to muck with a bunch of COP0 registers. Just remember the damn delay slots...

Posted: Thu Sep 09, 2004 10:48 pm
by pixel
Ah ha! I didn't know of that IOP module :P

Okay, let's have a look. Thanks ;)

--edit-- okay, "same thing". Even when running a simple syscall :p

So, now I'd like to see some "working code" :D

Actually my first pieces of code were doing the same things as the EXCEPMAN module. That's only my user handlers which are completely wrong, but without much examples or documentation, it's quite difficult to know what is, and what is not to be done :p

Re: Exception handling on the EE and IOP

Posted: Fri Sep 10, 2004 3:39 am
by redcoat
tjd wrote:I have have code (EE & IOP) which prints out the registers and a stack trace if anyone is interested. After that, I moved on and have gdb running on both the EE and IOP. Life is much nicer now that I've [re-]entered the 1980's... Symbolic debugging: stack traces, breakpoints, printing out complicated C++ structures from the debugger-- who wouldda thought?
Yes, I am interested :)


I haven't delved into using gdb on the EE and IOP--I wasn't aware that it could be used on the IOP(?). Guess I need to "bite the bullet" here and get that setup. ;)