xref: /plan9/sys/src/9/omap/arch.c (revision fac6300f1f1b25611e114fc0bdda9cf428c13da4)
17bb09086SDavid du Colombier #include "u.h"
27bb09086SDavid du Colombier #include "../port/lib.h"
37bb09086SDavid du Colombier #include "mem.h"
47bb09086SDavid du Colombier #include "dat.h"
57bb09086SDavid du Colombier #include "fns.h"
67bb09086SDavid du Colombier #include "../port/error.h"
77bb09086SDavid du Colombier 
87bb09086SDavid du Colombier #include <tos.h>
97bb09086SDavid du Colombier #include "ureg.h"
107bb09086SDavid du Colombier 
117bb09086SDavid du Colombier #include "arm.h"
127bb09086SDavid du Colombier 
137bb09086SDavid du Colombier /*
147bb09086SDavid du Colombier  * A lot of this stuff doesn't belong here
157bb09086SDavid du Colombier  * but this is a convenient dumping ground for
167bb09086SDavid du Colombier  * later sorting into the appropriate buckets.
177bb09086SDavid du Colombier  */
187bb09086SDavid du Colombier 
197bb09086SDavid du Colombier /* Give enough context in the ureg to produce a kernel stack for
207bb09086SDavid du Colombier  * a sleeping process
217bb09086SDavid du Colombier  */
227bb09086SDavid du Colombier void
setkernur(Ureg * ureg,Proc * p)237bb09086SDavid du Colombier setkernur(Ureg* ureg, Proc* p)
247bb09086SDavid du Colombier {
257bb09086SDavid du Colombier 	ureg->pc = p->sched.pc;
267bb09086SDavid du Colombier 	ureg->sp = p->sched.sp+4;
277bb09086SDavid du Colombier 	ureg->r14 = PTR2UINT(sched);
287bb09086SDavid du Colombier }
297bb09086SDavid du Colombier 
307bb09086SDavid du Colombier /*
31*fac6300fSDavid du Colombier  * called in syscallfmt.c, sysfile.c, sysproc.c
327bb09086SDavid du Colombier  */
337bb09086SDavid du Colombier void
validalign(uintptr addr,unsigned align)34*fac6300fSDavid du Colombier validalign(uintptr addr, unsigned align)
357bb09086SDavid du Colombier {
36*fac6300fSDavid du Colombier 	/*
37*fac6300fSDavid du Colombier 	 * Plan 9 is a 32-bit O/S, and the hardware it runs on
38*fac6300fSDavid du Colombier 	 * does not usually have instructions which move 64-bit
39*fac6300fSDavid du Colombier 	 * quantities directly, synthesizing the operations
40*fac6300fSDavid du Colombier 	 * with 32-bit move instructions. Therefore, the compiler
41*fac6300fSDavid du Colombier 	 * (and hardware) usually only enforce 32-bit alignment,
42*fac6300fSDavid du Colombier 	 * if at all.
43*fac6300fSDavid du Colombier 	 *
44*fac6300fSDavid du Colombier 	 * Take this out if the architecture warrants it.
45*fac6300fSDavid du Colombier 	 */
46*fac6300fSDavid du Colombier 	if(align == sizeof(vlong))
47*fac6300fSDavid du Colombier 		align = sizeof(long);
48*fac6300fSDavid du Colombier 
49*fac6300fSDavid du Colombier 	/*
50*fac6300fSDavid du Colombier 	 * Check align is a power of 2, then addr alignment.
51*fac6300fSDavid du Colombier 	 */
52*fac6300fSDavid du Colombier 	if((align != 0 && !(align & (align-1))) && !(addr & (align-1)))
53*fac6300fSDavid du Colombier 		return;
547bb09086SDavid du Colombier 	postnote(up, 1, "sys: odd address", NDebug);
557bb09086SDavid du Colombier 	error(Ebadarg);
56*fac6300fSDavid du Colombier 	/*NOTREACHED*/
577bb09086SDavid du Colombier }
587bb09086SDavid du Colombier 
597bb09086SDavid du Colombier /* go to user space */
607bb09086SDavid du Colombier void
kexit(Ureg *)617bb09086SDavid du Colombier kexit(Ureg*)
627bb09086SDavid du Colombier {
637bb09086SDavid du Colombier 	uvlong t;
647bb09086SDavid du Colombier 	Tos *tos;
657bb09086SDavid du Colombier 
667bb09086SDavid du Colombier 	/* precise time accounting, kernel exit */
677bb09086SDavid du Colombier 	tos = (Tos*)(USTKTOP-sizeof(Tos));
687bb09086SDavid du Colombier 	cycles(&t);
697bb09086SDavid du Colombier 	tos->kcycles += t - up->kentry;
707bb09086SDavid du Colombier 	tos->pcycles = up->pcycles;
717bb09086SDavid du Colombier 	tos->cyclefreq = m->cpuhz;
727bb09086SDavid du Colombier 	tos->pid = up->pid;
737bb09086SDavid du Colombier 
747bb09086SDavid du Colombier 	/* make visible immediately to user proc */
757bb09086SDavid du Colombier 	cachedwbinvse(tos, sizeof *tos);
767bb09086SDavid du Colombier }
777bb09086SDavid du Colombier 
787bb09086SDavid du Colombier /*
797bb09086SDavid du Colombier  *  return the userpc the last exception happened at
807bb09086SDavid du Colombier  */
817bb09086SDavid du Colombier uintptr
userpc(void)827bb09086SDavid du Colombier userpc(void)
837bb09086SDavid du Colombier {
847bb09086SDavid du Colombier 	Ureg *ureg = up->dbgreg;
857bb09086SDavid du Colombier 	return ureg->pc;
867bb09086SDavid du Colombier }
877bb09086SDavid du Colombier 
887bb09086SDavid du Colombier /* This routine must save the values of registers the user is not permitted
897bb09086SDavid du Colombier  * to write from devproc and then restore the saved values before returning.
907bb09086SDavid du Colombier  */
917bb09086SDavid du Colombier void
setregisters(Ureg * ureg,char * pureg,char * uva,int n)927bb09086SDavid du Colombier setregisters(Ureg* ureg, char* pureg, char* uva, int n)
937bb09086SDavid du Colombier {
947bb09086SDavid du Colombier 	USED(ureg, pureg, uva, n);
957bb09086SDavid du Colombier }
967bb09086SDavid du Colombier 
977bb09086SDavid du Colombier /*
987bb09086SDavid du Colombier  *  this is the body for all kproc's
997bb09086SDavid du Colombier  */
1007bb09086SDavid du Colombier static void
linkproc(void)1017bb09086SDavid du Colombier linkproc(void)
1027bb09086SDavid du Colombier {
1037bb09086SDavid du Colombier 	spllo();
1047bb09086SDavid du Colombier 	up->kpfun(up->kparg);
1057bb09086SDavid du Colombier 	pexit("kproc exiting", 0);
1067bb09086SDavid du Colombier }
1077bb09086SDavid du Colombier 
1087bb09086SDavid du Colombier /*
1097bb09086SDavid du Colombier  *  setup stack and initial PC for a new kernel proc.  This is architecture
1107bb09086SDavid du Colombier  *  dependent because of the starting stack location
1117bb09086SDavid du Colombier  */
1127bb09086SDavid du Colombier void
kprocchild(Proc * p,void (* func)(void *),void * arg)1137bb09086SDavid du Colombier kprocchild(Proc *p, void (*func)(void*), void *arg)
1147bb09086SDavid du Colombier {
1157bb09086SDavid du Colombier 	p->sched.pc = PTR2UINT(linkproc);
1167bb09086SDavid du Colombier 	p->sched.sp = PTR2UINT(p->kstack+KSTACK);
1177bb09086SDavid du Colombier 
1187bb09086SDavid du Colombier 	p->kpfun = func;
1197bb09086SDavid du Colombier 	p->kparg = arg;
1207bb09086SDavid du Colombier }
1217bb09086SDavid du Colombier 
1227bb09086SDavid du Colombier /*
1237bb09086SDavid du Colombier  *  pc output by dumpaproc
1247bb09086SDavid du Colombier  */
1257bb09086SDavid du Colombier uintptr
dbgpc(Proc * p)1267bb09086SDavid du Colombier dbgpc(Proc* p)
1277bb09086SDavid du Colombier {
1287bb09086SDavid du Colombier 	Ureg *ureg;
1297bb09086SDavid du Colombier 
1307bb09086SDavid du Colombier 	ureg = p->dbgreg;
1317bb09086SDavid du Colombier 	if(ureg == 0)
1327bb09086SDavid du Colombier 		return 0;
1337bb09086SDavid du Colombier 
1347bb09086SDavid du Colombier 	return ureg->pc;
1357bb09086SDavid du Colombier }
1367bb09086SDavid du Colombier 
1377bb09086SDavid du Colombier /*
1387bb09086SDavid du Colombier  *  set mach dependent process state for a new process
1397bb09086SDavid du Colombier  */
1407bb09086SDavid du Colombier void
procsetup(Proc * p)1417bb09086SDavid du Colombier procsetup(Proc* p)
1427bb09086SDavid du Colombier {
1437bb09086SDavid du Colombier 	fpusysprocsetup(p);
1447bb09086SDavid du Colombier }
1457bb09086SDavid du Colombier 
1467bb09086SDavid du Colombier /*
1477bb09086SDavid du Colombier  *  Save the mach dependent part of the process state.
1487bb09086SDavid du Colombier  */
1497bb09086SDavid du Colombier void
procsave(Proc * p)1507bb09086SDavid du Colombier procsave(Proc* p)
1517bb09086SDavid du Colombier {
1527bb09086SDavid du Colombier 	uvlong t;
1537bb09086SDavid du Colombier 
1547bb09086SDavid du Colombier 	cycles(&t);
1557bb09086SDavid du Colombier 	p->pcycles += t;
1567bb09086SDavid du Colombier 
1577bb09086SDavid du Colombier // TODO: save and restore VFPv3 FP state once 5[cal] know the new registers.
1587bb09086SDavid du Colombier 	fpuprocsave(p);
1597bb09086SDavid du Colombier }
1607bb09086SDavid du Colombier 
1617bb09086SDavid du Colombier void
procrestore(Proc * p)1627bb09086SDavid du Colombier procrestore(Proc* p)
1637bb09086SDavid du Colombier {
1647bb09086SDavid du Colombier 	uvlong t;
1657bb09086SDavid du Colombier 
1667bb09086SDavid du Colombier 	if(p->kp)
1677bb09086SDavid du Colombier 		return;
1687bb09086SDavid du Colombier 	cycles(&t);
1697bb09086SDavid du Colombier 	p->pcycles -= t;
1707bb09086SDavid du Colombier 
1717bb09086SDavid du Colombier 	fpuprocrestore(p);
1727bb09086SDavid du Colombier }
1737bb09086SDavid du Colombier 
1747bb09086SDavid du Colombier int
userureg(Ureg * ureg)1757bb09086SDavid du Colombier userureg(Ureg* ureg)
1767bb09086SDavid du Colombier {
1777bb09086SDavid du Colombier 	return (ureg->psr & PsrMask) == PsrMusr;
1787bb09086SDavid du Colombier }
1797bb09086SDavid du Colombier 
1807bb09086SDavid du Colombier /*
1817bb09086SDavid du Colombier  * atomic ops
1827bb09086SDavid du Colombier  * make sure that we don't drag in the C library versions
1837bb09086SDavid du Colombier  */
1847bb09086SDavid du Colombier 
1857bb09086SDavid du Colombier long
_xdec(long * p)1867bb09086SDavid du Colombier _xdec(long *p)
1877bb09086SDavid du Colombier {
1887bb09086SDavid du Colombier 	int s, v;
1897bb09086SDavid du Colombier 
1907bb09086SDavid du Colombier 	s = splhi();
1917bb09086SDavid du Colombier 	v = --*p;
1927bb09086SDavid du Colombier 	splx(s);
1937bb09086SDavid du Colombier 	return v;
1947bb09086SDavid du Colombier }
1957bb09086SDavid du Colombier 
1967bb09086SDavid du Colombier void
_xinc(long * p)1977bb09086SDavid du Colombier _xinc(long *p)
1987bb09086SDavid du Colombier {
1997bb09086SDavid du Colombier 	int s;
2007bb09086SDavid du Colombier 
2017bb09086SDavid du Colombier 	s = splhi();
2027bb09086SDavid du Colombier 	++*p;
2037bb09086SDavid du Colombier 	splx(s);
2047bb09086SDavid du Colombier }
2057bb09086SDavid du Colombier 
2067bb09086SDavid du Colombier int
ainc(int * p)2077bb09086SDavid du Colombier ainc(int *p)
2087bb09086SDavid du Colombier {
2097bb09086SDavid du Colombier 	int s, v;
2107bb09086SDavid du Colombier 
2117bb09086SDavid du Colombier 	s = splhi();
2127bb09086SDavid du Colombier 	v = ++*p;
2137bb09086SDavid du Colombier 	splx(s);
2147bb09086SDavid du Colombier 	return v;
2157bb09086SDavid du Colombier }
2167bb09086SDavid du Colombier 
2177bb09086SDavid du Colombier int
adec(int * p)2187bb09086SDavid du Colombier adec(int *p)
2197bb09086SDavid du Colombier {
2207bb09086SDavid du Colombier 	int s, v;
2217bb09086SDavid du Colombier 
2227bb09086SDavid du Colombier 	s = splhi();
2237bb09086SDavid du Colombier 	v = --*p;
2247bb09086SDavid du Colombier 	splx(s);
2257bb09086SDavid du Colombier 	return v;
2267bb09086SDavid du Colombier }
2277bb09086SDavid du Colombier 
2287bb09086SDavid du Colombier int
cas32(void * addr,u32int old,u32int new)2297bb09086SDavid du Colombier cas32(void* addr, u32int old, u32int new)
2307bb09086SDavid du Colombier {
2317bb09086SDavid du Colombier 	int r, s;
2327bb09086SDavid du Colombier 
2337bb09086SDavid du Colombier 	s = splhi();
2347bb09086SDavid du Colombier 	if(r = (*(u32int*)addr == old))
2357bb09086SDavid du Colombier 		*(u32int*)addr = new;
2367bb09086SDavid du Colombier 	splx(s);
2377bb09086SDavid du Colombier 	if (r)
2387bb09086SDavid du Colombier 		coherence();
2397bb09086SDavid du Colombier 	return r;
2407bb09086SDavid du Colombier }
241