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: