Re: Register reads in kernel space ...

Petr Vandrovec Ing. VTEI (VANDROVE@vc.cvut.cz)
Thu, 15 Jul 1999 11:58:11 MET-1


> What's the best way to capture a register snapshot within the kernel
> context? For example, how do I capture pt_regs in any function,
> assuming I'm not taking an exception ... I'm executing normally.
> (My question is specific to x86 code). I realize show_registers()
> is available for dumping the register state, but to get the current
> register state, it looks like you have to pull each register from
> the context of get_current(). Is that what we're left with?

I'm using this... It generates pt_regs struct on stack (and prints
them+stacktrace). If you need them in some structure, you have to
fill it manually - there is no library function AFAIK (patch is for
2.3.11-pre3):

diff -urdN linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- linux/arch/i386/kernel/traps.c Mon Jul 12 11:31:00 1999
+++ linux/arch/i386/kernel/traps.c Mon Jul 12 11:35:20 1999
@@ -191,6 +191,42 @@
printk("\n");
}

+void printstate(void) {
+ asm volatile (
+ "pushl %%ss\n\t"
+ "pushl %%esp\n\t"
+ "pushfl\n\t"
+ "pushl %%cs\n\t"
+ "call 1f\n"
+ "1:\n\t"
+ "pushl %%eax\n\t"
+ "pushl %%ds\n\t"
+ "pushl %%es\n\t"
+ "pushl %%eax\n\t"
+ "pushl %%ebp\n\t"
+ "pushl %%edi\n\t"
+ "pushl %%esi\n\t"
+ "pushl %%edx\n\t"
+ "pushl %%ecx\n\t"
+ "pushl %%ebx\n\t"
+ "movl %%esp,%%eax\n\t"
+ "pushl %%eax\n\t"
+ "call show_registers\n\t"
+ "addl $4,%%esp\n\t"
+ "popl %%ebx\n\t"
+ "popl %%ecx\n\t"
+ "popl %%edx\n\t"
+ "popl %%esi\n\t"
+ "popl %%edi\n\t"
+ "popl %%ebp\n\t"
+ "popl %%eax\n\t"
+ "popl %%es\n\t"
+ "popl %%ds\n\t"
+ "popl %%eax\n\t"
+ "addl $20,%%esp\n\t"
+ : : : "memory" );
+}
+
spinlock_t die_lock;

void die(const char * str, struct pt_regs * regs, long err)

> And while we're on the topic, what about register snapshots for each
> CPU?
You are out of luck. You have to add an IPI operation `store my registers
somewhere'. Or, you can (with new TSSes) change IPI interrupt to task
gate and prepare dummy TSS, which can do (1) endless loop or (2) execute
old IPI proc and iret. Then send IPI... In both cases, old TSS will be filled
with registers at time of IPI. Or you can change timer interrupt or anything
else, but IPI comes to my mind as it is delivered to all (or specific) cpus.
> Thanks for any advice. I'm looking for a consistent method to do
> this (so we can create proper kernel backtraces for our post-crash
> analysis utilities.)
If it is `complete crash' postcrash, I think that TSS with endless loop
is best. You kill two problems with this: (1) other CPUs will stop doing
damage in memory and (2) you'll get their registers... (and (3) you can
revive them after that by simple overwritting endless loop with iret).
Best regards,
Petr Vandrovec
vandrove@vc.cvut.cz

P.S.: It is i386 specific, of course. You have to code it for every
architecture you support (as each architecture has different registers
and different IPI mechanism).

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/