Time to create content of io.h with references to control registers, irq nums etc:

 1#define IOBASE			0x20000000		/* base of io regs */
 2#define INTREGS			(IOBASE+0x00B200)
 3#define POWERREGS		(IOBASE+0x100000)
 4#define PL011REGS		(IOBASE+0x201000)
 5
 6#define UART_PL01x_FR_TXFF	0x20
 7
 8typedef struct Intregs Intregs;
 9
10/* interrupt control registers */
11struct Intregs {
12	u32int  ARMpending;
13	u32int  GPUpending[2];
14	u32int  FIQctl;
15	u32int  GPUenable[2];
16	u32int  ARMenable;
17	u32int  GPUdisable[2];
18	u32int  ARMdisable;
19};
20
21enum {
22	IRQtimer0	= 0,
23	IRQtimer1	= 1,
24	IRQtimer2	= 2,
25	IRQtimer3	= 3,
26	IRQclock	= IRQtimer3,
27	IRQdma0		= 16,
28#define IRQDMA(chan)	(IRQdma0+(chan))
29	IRQaux		= 29,
30	IRQmmc		= 62,
31	IRQbasic	= 64,
32	IRQtimerArm	= IRQbasic + 0,
33	DmaD2M		= 0,		/* device to memory */
34	DmaM2D		= 1,		/* memory to device */
35	DmaM2M		= 2,		/* memory to memory */
36	DmaChanEmmc	= 4,		/* can only use 2-5, 11-12 */
37	DmaDevEmmc	= 11
38};

Then in Mach struct we need to add stacks – they will be used as short memory blocks for stack:

1struct Mach {
2        ...
3	/* stacks for exceptions */
4	ulong   fiqstack[4];
5	ulong   irqstack[4];
6	ulong   abtstack[4];
7	ulong   undstack[4];
8	int	stack[1];
9};

Also Mach.stack reference at the end of Mach will be very useful for us because it is indication of low limit of kernel stack. If kernel stack address moves below this we detect that it is “kernel panic” situation – that will be performed in interrupts coding.

Then, because we will work with assembler codes and can easily get unpredictable cases, let’s create dump.c with functions that will help us with dumping all registers, stack, memory fragments, etc:

  1#include "u.h"
  2#include "../port/lib.h"
  3#include "mem.h"
  4#include "dat.h"
  5#include "ureg.h"
  6#include "armv6.h"
  7
  8void
  9dumplongs(char *msg, ulong *v, int n)
 10{
 11	int i, l;
 12
 13	l = 0;
 14	iprint("%s at %.8p: ", msg, v);
 15	for(i=0; i<n; i++){
 16		if(l >= 4){
 17			iprint("\n    %.8p: ", v);
 18			l = 0;
 19		}
 20		if(isvalid_va(v)){
 21			iprint(" %.8lux", *v++);
 22			l++;
 23		}else{
 24			iprint(" invalid");
 25			break;
 26		}
 27	}
 28	iprint("\n");
 29}
 30
 31static void
 32_dumpstack(Ureg *ureg)
 33{
 34	ulong *v, *l;
 35	ulong inst;
 36	ulong *estack;
 37	int i;
 38
 39	l = (ulong*)(ureg+1);
 40	if(!isvalid_wa(l)){
 41		iprint("invalid ureg/stack: %.8p\n", l);
 42		return;
 43	}
 44	print("ktrace /kernel/path %.8ux %.8ux %.8ux\n"	
 45		,ureg->pc, ureg->sp, ureg->r14);
 46	if(up != nil && l >= (ulong*)up->kstack 
 47		&& l <= (ulong*)(up->kstack+KSTACK-4))
 48		estack = (ulong*)(up->kstack+KSTACK);
 49	else if(l >= (ulong*)m->stack && l <= (ulong*)((ulong)m+BY2PG-4))
 50		estack = (ulong*)((ulong)m+BY2PG-4);
 51	else{
 52		iprint("unknown stack\n");
 53		return;
 54	}
 55	i = 0;
 56	for(; l<estack; l++) {
 57		if(!isvalid_wa(l)) {
 58			iprint("invalid(%8.8p)", l);
 59			break;
 60		}
 61		v = (ulong*)*l;
 62		if(isvalid_wa(v)) {
 63			inst = v[-1];
 64			if((inst & 0x0ff0f000) == 0x0280f000 &&
 65				 (*(v-2) & 0x0ffff000) == 0x028fe000    ||
 66				(inst & 0x0f000000) == 0x0b000000) {
 67				iprint("%8.8p=%8.8lux ", l, v);
 68				i++;
 69			}
 70		}
 71		if(i == 4){
 72			iprint("\n");
 73			i = 0;
 74		}
 75	}
 76	if(i)
 77		print("\n");
 78}
 79
 80/*
 81 * Fill in enough of Ureg to get a stack trace, and call a function.
 82 * Used by debugging interface rdb.
 83 */
 84void
 85callwithureg(void (*fn)(Ureg*))
 86{
 87	Ureg ureg;
 88	ureg.pc = getcallerpc(&fn);
 89	ureg.sp = (ulong)&fn;
 90	ureg.r14 = 0;
 91	fn(&ureg);
 92}
 93
 94void
 95dumpstack(void)
 96{
 97	callwithureg(_dumpstack);
 98}
 99
100void
101dumparound(uint addr)
102{
103	uint addr0 = (addr/16)*16;
104	int a_row, a_col;
105	uchar ch, *cha;
106	uint c;
107	/* +-32 bytes to print */
108	print("%8.8uX:\n", addr0 +(-2)*16);
109	for (a_col = 0; a_col<16; ++a_col) {
110		print(" %.2uX", a_col);
111	}
112	print("\n");
113
114	for (a_row = -2; a_row < 3; ++a_row) {
115		for (a_col = 0; a_col<16; ++a_col) {
116			cha = (uchar *)(addr0 +a_row*16+a_col);
117			ch = *cha;
118			c = ch;
119			if (cha == (uchar *)addr)
120				print(">%2.2uX", c);
121			else print(" %2.2uX", c);
122		}
123		print("\n");
124	}
125	print("\n");
126}
127
128void
129dumpregs(Ureg* ureg)
130{
131	print("TRAP: %s", trapname(ureg->type));
132	if((ureg->psr & PsrMask) != PsrMsvc)
133		print(" in %s", trapname(ureg->psr));
134	print("\n");
135	print("PSR %8.8uX type %2.2uX PC %8.8uX LINK %8.8uX\n",
136		ureg->psr, ureg->type, ureg->pc, ureg->link);
137	print("R14 %8.8uX R13 %8.8uX R12 %8.8uX R11 %8.8uX R10 %8.8uX\n",
138		ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
139	print("R9  %8.8uX R8  %8.8uX R7  %8.8uX R6  %8.8uX R5  %8.8uX\n",
140		ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
141	print("R4  %8.8uX R3  %8.8uX R2  %8.8uX R1  %8.8uX R0  %8.8uX\n",
142		ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
143	print("Stack is at: %8.8luX\n", ureg);
144	print("PC %8.8lux LINK %8.8lux\n", (ulong)ureg->pc, (ulong)ureg->link);
145
146	if(up)
147		print("Process stack:  %8.8lux-%8.8lux\n",
148			up->kstack, up->kstack+KSTACK-4);
149	else
150		print("System stack: %8.8lux-%8.8lux\n",
151			(ulong)(m+1), (ulong)m+BY2PG-4);
152	dumplongs("stack", (ulong *)(ureg + 1), 16);
153	_dumpstack(ureg);
154	dumparound(ureg->pc);
155}

So, nothing complicated, just print() mostly

FILES: