So far I have managed this for user-state processes by retrieving a
pointer to the process descriptor of the process in question and then
treating the ps_usp member as copy of the current stack pointer. From
there, according to the documented stack frame format for the PowerPC
processor, the current program counter is *((u_int *)ps_usp + 1).
That seems to work for user-state processes, but not for system-state
processes. In particular, it fails badly for spf_rx.
I have also found that if a process examines its own process
descriptor then ps_usp is never the same as r1, the actual stack
pointer, but this might be because r1 is only saved to ps_usp when the
process is switched out of the CPU (I don't know).
My questions are these:
1a. Is prdesc->ps_usp really the saved value of the stack pointer of
all user-state processes that are currently switched out of the CPU?
If not, what is?
1b. If I am examining the process descriptor from a system alarm
routine, is the process effectively switched out of the CPU - i.e.
assuming the answer to 1a is 'yes', is it still 'yes' in this case?
1c. Will the program counter obtained in the above way be correct for
a user-state process that is currently in sleeping in a device driver,
i.e. in system-state?
2. Is there an equivalent way to get the stack pointer of a system-
state process?
3. How can I distinguish between a user-state process and a system-
state process? There seems to be nothing in the process descriptor to
tell them apart.
4. Is there an easier way of getting the saved program counter than
the above?
This is with a Microware compiler?
Yes, I'm using Microware OS-9 for PowerPC version 4.2.
I solved the problem by using an interrupt service routine instead of
a system state alarm. I attach my ISR to the clock ticker IRQ vector
at a higher priority than the clock ticker, and then return from it
EOS_NOTME so that the clock ticker (tkdec) is called immediately after
my ISR.
#define VECTOR T_DEC
#define PRIORITY 8
err = _os_irq(VECTOR, PRIORITY, myIsr, data);
Thus myIsr() is called on every clock tick. On entry to myIsr(), the
special register SRR0 contains the program counter to which the ISR
will return - i.e. the program counter of the next instruction at the
point of the interruption, and SRR1 contains the machine status
register (MSR). Bit MSR_PR is clear if the processor is in system
state and set if in user state. (Yes, it really is that way round.)
The functions _get_srr0() and _get_srr1() are useful here.
The essential header files to look at are regs.h, regsppc.h, and
getset.h.
That's basically it.