annotate src/arm.c @ 0:53676d1f5817 default tip

firsh commit
author tobaru
date Sun, 04 Feb 2018 17:54:49 +0900
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
1 // BSP support routine
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
2 #include "types.h"
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
3 #include "defs.h"
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
4 #include "param.h"
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
5 #include "memlayout.h"
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
6 #include "proc.h"
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
7 #include "arm.h"
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
8 #include "mmu.h"
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
9
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
10 void cli (void)
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
11 {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
12 uint val;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
13
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
14 // ok, enable paging using read/modify/write
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
15 asm("MRS %[v], cpsr": [v]"=r" (val)::);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
16 val |= DIS_INT;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
17 asm("MSR cpsr_cxsf, %[v]": :[v]"r" (val):);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
18 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
19
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
20 void sti (void)
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
21 {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
22 uint val;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
23
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
24 // ok, enable paging using read/modify/write
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
25 asm("MRS %[v], cpsr": [v]"=r" (val)::);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
26 val &= ~DIS_INT;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
27 asm("MSR cpsr_cxsf, %[v]": :[v]"r" (val):);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
28 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
29
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
30 // return the cpsr used for user program
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
31 uint spsr_usr ()
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
32 {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
33 uint val;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
34
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
35 // ok, enable paging using read/modify/write
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
36 asm("MRS %[v], cpsr": [v]"=r" (val)::);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
37 val &= ~MODE_MASK;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
38 val |= USR_MODE;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
39
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
40 return val;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
41 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
42
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
43 // return whether interrupt is currently enabled
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
44 int int_enabled ()
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
45 {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
46 uint val;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
47
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
48 // ok, enable paging using read/modify/write
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
49 asm("MRS %[v], cpsr": [v]"=r" (val)::);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
50
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
51 return !(val & DIS_INT);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
52 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
53
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
54 // Pushcli/popcli are like cli/sti except that they are matched:
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
55 // it takes two popcli to undo two pushcli. Also, if interrupts
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
56 // are off, then pushcli, popcli leaves them off.
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
57
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
58 void pushcli (void)
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
59 {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
60 int enabled;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
61
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
62 enabled = int_enabled();
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
63
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
64 cli();
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
65
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
66 if (cpu->ncli++ == 0) {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
67 cpu->intena = enabled;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
68 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
69 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
70
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
71 void popcli (void)
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
72 {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
73 if (int_enabled()) {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
74 panic("popcli - interruptible");
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
75 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
76
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
77 if (--cpu->ncli < 0) {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
78 cprintf("cpu (%d)->ncli: %d\n", cpu, cpu->ncli);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
79 panic("popcli -- ncli < 0");
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
80 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
81
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
82 if ((cpu->ncli == 0) && cpu->intena) {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
83 sti();
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
84 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
85 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
86
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
87 // Record the current call stack in pcs[] by following the call chain.
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
88 // In ARM ABI, the function prologue is as:
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
89 // push {fp, lr}
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
90 // add fp, sp, #4
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
91 // so, fp points to lr, the return address
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
92 void getcallerpcs (void * v, uint pcs[])
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
93 {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
94 uint *fp;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
95 int i;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
96
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
97 fp = (uint*) v;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
98
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
99 for (i = 0; i < N_CALLSTK; i++) {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
100 if ((fp == 0) || (fp < (uint*) KERNBASE) || (fp == (uint*) 0xffffffff)) {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
101 break;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
102 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
103
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
104 fp = fp - 1; // points fp to the saved fp
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
105 pcs[i] = fp[1]; // saved lr
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
106 fp = (uint*) fp[0]; // saved fp
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
107 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
108
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
109 for (; i < N_CALLSTK; i++) {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
110 pcs[i] = 0;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
111 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
112 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
113
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
114 void show_callstk (char *s)
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
115 {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
116 int i;
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
117 uint pcs[N_CALLSTK];
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
118
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
119 cprintf("%s\n", s);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
120
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
121 getcallerpcs(get_fp(), pcs);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
122
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
123 for (i = N_CALLSTK - 1; i >= 0; i--) {
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
124 cprintf("%d: 0x%x\n", i + 1, pcs[i]);
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
125 }
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
126
53676d1f5817 firsh commit
tobaru
parents:
diff changeset
127 }