xref: /plan9/sys/src/9/teg2/arch.c (revision fac6300f1f1b25611e114fc0bdda9cf428c13da4)
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