xref: /plan9/sys/src/9/omap/arch.c (revision 7d7728c9ff780bb29e70ac5c0f1bb4c0d6187a9b)
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "../port/error.h"
7 
8 #include <tos.h>
9 #include "ureg.h"
10 
11 #include "arm.h"
12 
13 /*
14  * A lot of this stuff doesn't belong here
15  * but this is a convenient dumping ground for
16  * later sorting into the appropriate buckets.
17  */
18 
19 /* Give enough context in the ureg to produce a kernel stack for
20  * a sleeping process
21  */
22 void
23 setkernur(Ureg* ureg, Proc* p)
24 {
25 	ureg->pc = p->sched.pc;
26 	ureg->sp = p->sched.sp+4;
27 	ureg->r14 = PTR2UINT(sched);
28 }
29 
30 /*
31  * called in sysfile.c
32  */
33 void
34 evenaddr(uintptr addr)
35 {
36 	if(addr & 3){
37 		postnote(up, 1, "sys: odd address", NDebug);
38 		error(Ebadarg);
39 	}
40 }
41 
42 /* go to user space */
43 void
44 kexit(Ureg*)
45 {
46 	uvlong t;
47 	Tos *tos;
48 
49 	/* precise time accounting, kernel exit */
50 	tos = (Tos*)(USTKTOP-sizeof(Tos));
51 	cycles(&t);
52 	tos->kcycles += t - up->kentry;
53 	tos->pcycles = up->pcycles;
54 	tos->cyclefreq = m->cpuhz;
55 	tos->pid = up->pid;
56 
57 	/* make visible immediately to user proc */
58 	cachedwbinvse(tos, sizeof *tos);
59 }
60 
61 /*
62  *  return the userpc the last exception happened at
63  */
64 uintptr
65 userpc(void)
66 {
67 	Ureg *ureg = up->dbgreg;
68 	return ureg->pc;
69 }
70 
71 /* This routine must save the values of registers the user is not permitted
72  * to write from devproc and then restore the saved values before returning.
73  */
74 void
75 setregisters(Ureg* ureg, char* pureg, char* uva, int n)
76 {
77 	USED(ureg, pureg, uva, n);
78 }
79 
80 /*
81  *  this is the body for all kproc's
82  */
83 static void
84 linkproc(void)
85 {
86 	spllo();
87 	up->kpfun(up->kparg);
88 	pexit("kproc exiting", 0);
89 }
90 
91 /*
92  *  setup stack and initial PC for a new kernel proc.  This is architecture
93  *  dependent because of the starting stack location
94  */
95 void
96 kprocchild(Proc *p, void (*func)(void*), void *arg)
97 {
98 	p->sched.pc = PTR2UINT(linkproc);
99 	p->sched.sp = PTR2UINT(p->kstack+KSTACK);
100 
101 	p->kpfun = func;
102 	p->kparg = arg;
103 }
104 
105 /*
106  *  pc output by dumpaproc
107  */
108 uintptr
109 dbgpc(Proc* p)
110 {
111 	Ureg *ureg;
112 
113 	ureg = p->dbgreg;
114 	if(ureg == 0)
115 		return 0;
116 
117 	return ureg->pc;
118 }
119 
120 /*
121  *  set mach dependent process state for a new process
122  */
123 void
124 procsetup(Proc* p)
125 {
126 	fpusysprocsetup(p);
127 }
128 
129 /*
130  *  Save the mach dependent part of the process state.
131  */
132 void
133 procsave(Proc* p)
134 {
135 	uvlong t;
136 
137 	cycles(&t);
138 	p->pcycles += t;
139 
140 // TODO: save and restore VFPv3 FP state once 5[cal] know the new registers.
141 	fpuprocsave(p);
142 }
143 
144 void
145 procrestore(Proc* p)
146 {
147 	uvlong t;
148 
149 	if(p->kp)
150 		return;
151 	cycles(&t);
152 	p->pcycles -= t;
153 
154 	fpuprocrestore(p);
155 }
156 
157 int
158 userureg(Ureg* ureg)
159 {
160 	return (ureg->psr & PsrMask) == PsrMusr;
161 }
162 
163 /*
164  * atomic ops
165  * make sure that we don't drag in the C library versions
166  */
167 
168 long
169 _xdec(long *p)
170 {
171 	int s, v;
172 
173 	s = splhi();
174 	v = --*p;
175 	splx(s);
176 	return v;
177 }
178 
179 void
180 _xinc(long *p)
181 {
182 	int s;
183 
184 	s = splhi();
185 	++*p;
186 	splx(s);
187 }
188 
189 int
190 ainc(int *p)
191 {
192 	int s, v;
193 
194 	s = splhi();
195 	v = ++*p;
196 	splx(s);
197 	return v;
198 }
199 
200 int
201 adec(int *p)
202 {
203 	int s, v;
204 
205 	s = splhi();
206 	v = --*p;
207 	splx(s);
208 	return v;
209 }
210 
211 int
212 cas32(void* addr, u32int old, u32int new)
213 {
214 	int r, s;
215 
216 	s = splhi();
217 	if(r = (*(u32int*)addr == old))
218 		*(u32int*)addr = new;
219 	splx(s);
220 	if (r)
221 		coherence();
222 	return r;
223 }
224