13de6a9c0SDavid du Colombier #include "u.h"
23de6a9c0SDavid du Colombier #include "../port/lib.h"
33de6a9c0SDavid du Colombier #include "mem.h"
43de6a9c0SDavid du Colombier #include "dat.h"
53de6a9c0SDavid du Colombier #include "fns.h"
63de6a9c0SDavid du Colombier #include "../port/error.h"
73de6a9c0SDavid du Colombier
83de6a9c0SDavid du Colombier #include <tos.h>
93de6a9c0SDavid du Colombier #include "ureg.h"
103de6a9c0SDavid du Colombier
113de6a9c0SDavid du Colombier #include "arm.h"
123de6a9c0SDavid du Colombier
133de6a9c0SDavid du Colombier /*
143de6a9c0SDavid du Colombier * A lot of this stuff doesn't belong here
153de6a9c0SDavid du Colombier * but this is a convenient dumping ground for
163de6a9c0SDavid du Colombier * later sorting into the appropriate buckets.
173de6a9c0SDavid du Colombier */
183de6a9c0SDavid du Colombier
193de6a9c0SDavid du Colombier /* Give enough context in the ureg to produce a kernel stack for
203de6a9c0SDavid du Colombier * a sleeping process
213de6a9c0SDavid du Colombier */
223de6a9c0SDavid du Colombier void
setkernur(Ureg * ureg,Proc * p)233de6a9c0SDavid du Colombier setkernur(Ureg* ureg, Proc* p)
243de6a9c0SDavid du Colombier {
253de6a9c0SDavid du Colombier ureg->pc = p->sched.pc;
263de6a9c0SDavid du Colombier ureg->sp = p->sched.sp+4;
273de6a9c0SDavid du Colombier ureg->r14 = PTR2UINT(sched);
283de6a9c0SDavid du Colombier }
293de6a9c0SDavid du Colombier
303de6a9c0SDavid du Colombier /*
31*fac6300fSDavid du Colombier * called in syscallfmt.c, sysfile.c, sysproc.c
323de6a9c0SDavid du Colombier */
333de6a9c0SDavid du Colombier void
validalign(uintptr addr,unsigned align)34*fac6300fSDavid du Colombier validalign(uintptr addr, unsigned align)
353de6a9c0SDavid 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;
543de6a9c0SDavid du Colombier postnote(up, 1, "sys: odd address", NDebug);
553de6a9c0SDavid du Colombier error(Ebadarg);
56*fac6300fSDavid du Colombier /*NOTREACHED*/
573de6a9c0SDavid du Colombier }
583de6a9c0SDavid du Colombier
593de6a9c0SDavid du Colombier /* go to user space */
603de6a9c0SDavid du Colombier void
kexit(Ureg *)613de6a9c0SDavid du Colombier kexit(Ureg*)
623de6a9c0SDavid du Colombier {
633de6a9c0SDavid du Colombier uvlong t;
643de6a9c0SDavid du Colombier Tos *tos;
653de6a9c0SDavid du Colombier
663de6a9c0SDavid du Colombier /* precise time accounting, kernel exit */
673de6a9c0SDavid du Colombier tos = (Tos*)(USTKTOP-sizeof(Tos));
683de6a9c0SDavid du Colombier cycles(&t);
693de6a9c0SDavid du Colombier tos->kcycles += t - up->kentry;
703de6a9c0SDavid du Colombier tos->pcycles = up->pcycles;
713de6a9c0SDavid du Colombier tos->cyclefreq = m->cpuhz;
723de6a9c0SDavid du Colombier tos->pid = up->pid;
733de6a9c0SDavid du Colombier
743de6a9c0SDavid du Colombier /* make visible immediately to user phase */
753de6a9c0SDavid du Colombier l1cache->wbse(tos, sizeof *tos);
763de6a9c0SDavid du Colombier }
773de6a9c0SDavid du Colombier
783de6a9c0SDavid du Colombier /*
793de6a9c0SDavid du Colombier * return the userpc the last exception happened at
803de6a9c0SDavid du Colombier */
813de6a9c0SDavid du Colombier uintptr
userpc(void)823de6a9c0SDavid du Colombier userpc(void)
833de6a9c0SDavid du Colombier {
843de6a9c0SDavid du Colombier Ureg *ureg = up->dbgreg;
853de6a9c0SDavid du Colombier return ureg->pc;
863de6a9c0SDavid du Colombier }
873de6a9c0SDavid du Colombier
883de6a9c0SDavid du Colombier /* This routine must save the values of registers the user is not permitted
893de6a9c0SDavid du Colombier * to write from devproc and then restore the saved values before returning.
903de6a9c0SDavid du Colombier */
913de6a9c0SDavid du Colombier void
setregisters(Ureg * ureg,char * pureg,char * uva,int n)923de6a9c0SDavid du Colombier setregisters(Ureg* ureg, char* pureg, char* uva, int n)
933de6a9c0SDavid du Colombier {
943de6a9c0SDavid du Colombier USED(ureg, pureg, uva, n);
953de6a9c0SDavid du Colombier }
963de6a9c0SDavid du Colombier
973de6a9c0SDavid du Colombier /*
983de6a9c0SDavid du Colombier * this is the body for all kproc's
993de6a9c0SDavid du Colombier */
1003de6a9c0SDavid du Colombier static void
linkproc(void)1013de6a9c0SDavid du Colombier linkproc(void)
1023de6a9c0SDavid du Colombier {
1033de6a9c0SDavid du Colombier spllo();
1043de6a9c0SDavid du Colombier up->kpfun(up->kparg);
1053de6a9c0SDavid du Colombier pexit("kproc exiting", 0);
1063de6a9c0SDavid du Colombier }
1073de6a9c0SDavid du Colombier
1083de6a9c0SDavid du Colombier /*
1093de6a9c0SDavid du Colombier * setup stack and initial PC for a new kernel proc. This is architecture
1103de6a9c0SDavid du Colombier * dependent because of the starting stack location
1113de6a9c0SDavid du Colombier */
1123de6a9c0SDavid du Colombier void
kprocchild(Proc * p,void (* func)(void *),void * arg)1133de6a9c0SDavid du Colombier kprocchild(Proc *p, void (*func)(void*), void *arg)
1143de6a9c0SDavid du Colombier {
1153de6a9c0SDavid du Colombier p->sched.pc = PTR2UINT(linkproc);
1163de6a9c0SDavid du Colombier p->sched.sp = PTR2UINT(p->kstack+KSTACK);
1173de6a9c0SDavid du Colombier
1183de6a9c0SDavid du Colombier p->kpfun = func;
1193de6a9c0SDavid du Colombier p->kparg = arg;
1203de6a9c0SDavid du Colombier }
1213de6a9c0SDavid du Colombier
1223de6a9c0SDavid du Colombier /*
1233de6a9c0SDavid du Colombier * pc output by dumpaproc
1243de6a9c0SDavid du Colombier */
1253de6a9c0SDavid du Colombier uintptr
dbgpc(Proc * p)1263de6a9c0SDavid du Colombier dbgpc(Proc* p)
1273de6a9c0SDavid du Colombier {
1283de6a9c0SDavid du Colombier Ureg *ureg;
1293de6a9c0SDavid du Colombier
1303de6a9c0SDavid du Colombier ureg = p->dbgreg;
1313de6a9c0SDavid du Colombier if(ureg == 0)
1323de6a9c0SDavid du Colombier return 0;
1333de6a9c0SDavid du Colombier
1343de6a9c0SDavid du Colombier return ureg->pc;
1353de6a9c0SDavid du Colombier }
1363de6a9c0SDavid du Colombier
1373de6a9c0SDavid du Colombier /*
1383de6a9c0SDavid du Colombier * set mach dependent process state for a new process
1393de6a9c0SDavid du Colombier */
1403de6a9c0SDavid du Colombier void
procsetup(Proc * p)1413de6a9c0SDavid du Colombier procsetup(Proc* p)
1423de6a9c0SDavid du Colombier {
1433de6a9c0SDavid du Colombier fpusysprocsetup(p);
1443de6a9c0SDavid du Colombier }
1453de6a9c0SDavid du Colombier
1463de6a9c0SDavid du Colombier /*
1473de6a9c0SDavid du Colombier * Save the mach dependent part of the process state.
1483de6a9c0SDavid du Colombier */
1493de6a9c0SDavid du Colombier void
procsave(Proc * p)1503de6a9c0SDavid du Colombier procsave(Proc* p)
1513de6a9c0SDavid du Colombier {
1523de6a9c0SDavid du Colombier uvlong t;
1533de6a9c0SDavid du Colombier
1543de6a9c0SDavid du Colombier cycles(&t);
1553de6a9c0SDavid du Colombier p->pcycles += t;
1563de6a9c0SDavid du Colombier
1573de6a9c0SDavid du Colombier fpuprocsave(p);
1583de6a9c0SDavid du Colombier l1cache->wbse(p, sizeof *p); /* is this needed? */
1593de6a9c0SDavid du Colombier l1cache->wb(); /* is this needed? */
1603de6a9c0SDavid du Colombier }
1613de6a9c0SDavid du Colombier
1623de6a9c0SDavid du Colombier void
procrestore(Proc * p)1633de6a9c0SDavid du Colombier procrestore(Proc* p)
1643de6a9c0SDavid du Colombier {
1653de6a9c0SDavid du Colombier uvlong t;
1663de6a9c0SDavid du Colombier
1673de6a9c0SDavid du Colombier if(p->kp)
1683de6a9c0SDavid du Colombier return;
1693de6a9c0SDavid du Colombier cycles(&t);
1703de6a9c0SDavid du Colombier p->pcycles -= t;
1713de6a9c0SDavid du Colombier wakewfi(); /* in case there's another runnable proc */
1723de6a9c0SDavid du Colombier
1733de6a9c0SDavid du Colombier /* let it fault in at first use */
1743de6a9c0SDavid du Colombier // fpuprocrestore(p);
1753de6a9c0SDavid du Colombier l1cache->wb(); /* system is more stable with this */
1763de6a9c0SDavid du Colombier }
1773de6a9c0SDavid du Colombier
1783de6a9c0SDavid du Colombier int
userureg(Ureg * ureg)1793de6a9c0SDavid du Colombier userureg(Ureg* ureg)
1803de6a9c0SDavid du Colombier {
1813de6a9c0SDavid du Colombier return (ureg->psr & PsrMask) == PsrMusr;
1823de6a9c0SDavid du Colombier }
183