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