shithub: riscv

Download patch

ref: e4ce6aadac9e1de8d5ea625e9680d24cabce0e1a
parent: 08c1622b0d8de92c2650d7b0338d9abf20985827
author: cinap_lenrek <[email protected]>
date: Sun Dec 20 17:34:41 EST 2020

kernel: handle tos and per process pcycle counters in port/

we might as well handle the per process cycle
counter in the portable part instead of duplicating the code
in every arch and have inconsistent implementations.

we now have a portable kenter() and kexit() function,
that is ment to be used in trap/syscall from user,
which updates the counters.

some kernels missed initializing Mach.cyclefreq.

--- a/sys/src/9/bcm/arch.c
+++ b/sys/src/9/bcm/arch.c
@@ -39,25 +39,6 @@
 	}
 }
 
-/* go to user space */
-void
-kexit(Ureg*)
-{
-	uvlong t;
-	Tos *tos;
-
-	/* precise time accounting, kernel exit */
-	tos = (Tos*)(USTKTOP-sizeof(Tos));
-	cycles(&t);
-	tos->kcycles += t - up->kentry;
-	tos->pcycles = t + up->pcycles;
-	tos->cyclefreq = m->cpuhz;
-	tos->pid = up->pid;
-
-	/* make visible immediately to user proc */
-	cachedwbinvse(tos, sizeof *tos);
-}
-
 /*
  *  return the userpc the last exception happened at
  */
@@ -80,28 +61,14 @@
 }
 
 /*
- *  this is the body for all kproc's
- */
-static void
-linkproc(void)
-{
-	spllo();
-	up->kpfun(up->kparg);
-	pexit("kproc exiting", 0);
-}
-
-/*
  *  setup stack and initial PC for a new kernel proc.  This is architecture
  *  dependent because of the starting stack location
  */
 void
-kprocchild(Proc *p, void (*func)(void*), void *arg)
+kprocchild(Proc *p, void (*entry)(void))
 {
-	p->sched.pc = (uintptr)linkproc;
+	p->sched.pc = (uintptr)entry;
 	p->sched.sp = (uintptr)p->kstack+KSTACK;
-
-	p->kpfun = func;
-	p->kparg = arg;
 }
 
 /*
@@ -126,17 +93,11 @@
 procsetup(Proc* p)
 {
 	fpusysprocsetup(p);
-
-	cycles(&p->kentry);
-	p->pcycles = -p->kentry;
 }
 
 void
 procfork(Proc* p)
 {
-	p->kentry = up->kentry;
-	p->pcycles = -p->kentry;
-
 	fpuprocfork(p);
 }
 
@@ -146,12 +107,6 @@
 void
 procsave(Proc* p)
 {
-	uvlong t;
-
-	cycles(&t);
-	p->pcycles += t;
-	p->kentry -= t;
-
 // TODO: save and restore VFPv3 FP state once 5[cal] know the new registers.
 	fpuprocsave(p);
 
@@ -173,14 +128,6 @@
 void
 procrestore(Proc* p)
 {
-	uvlong t;
-
-	if(p->kp)
-		return;
-	cycles(&t);
-	p->pcycles -= t;
-	p->kentry += t;
-
 	fpuprocrestore(p);
 }
 
--- a/sys/src/9/bcm/fns.h
+++ b/sys/src/9/bcm/fns.h
@@ -129,8 +129,6 @@
 extern void* sysexecregs(uintptr, ulong, int);
 extern void sysprocsetup(Proc*);
 
-extern void kexit(Ureg*);
-
 #define	getpgcolor(a)	0
 #define	kmapinval()
 #define countpagerefs(a, b)
--- a/sys/src/9/bcm/trap.c
+++ b/sys/src/9/bcm/trap.c
@@ -150,12 +150,7 @@
 			rem, up, ureg, ureg->pc);
 	}
 
-	user = (ureg->psr & PsrMask) == PsrMusr;
-	if(user){
-		up->dbgreg = ureg;
-		cycles(&up->kentry);
-	}
-
+	user = kenter(ureg);
 	/*
 	 * All interrupts/exceptions should be resumed at ureg->pc-4,
 	 * except for Data Abort which resumes at ureg->pc-8.
--- a/sys/src/9/bcm64/fns.h
+++ b/sys/src/9/bcm64/fns.h
@@ -8,7 +8,8 @@
 extern int cmpswap(long*, long, long);
 extern void coherence(void);
 extern void idlehands(void);
-extern uvlong cycles(void);
+extern uvlong vcycles(void);
+#define cycles(ip) *(ip) = vcycles()
 extern int splfhi(void);
 extern void splflo(void);
 extern void touser(uintptr sp);
--- a/sys/src/9/bcm64/l.s
+++ b/sys/src/9/bcm64/l.s
@@ -297,7 +297,7 @@
 	WFE
 	RETURN
 
-TEXT cycles(SB), 1, $-4
+TEXT vcycles(SB), 1, $-4
 TEXT lcycles(SB), 1, $-4
 	MRS	PMCCNTR_EL0, R0
 	RETURN
--- a/sys/src/9/bcm64/trap.c
+++ b/sys/src/9/bcm64/trap.c
@@ -81,20 +81,6 @@
 	splx(0x3<<6);	// unmask serr and debug
 }
 
-void
-kexit(Ureg*)
-{
-	Tos *tos;
-	uvlong t;
-
-	t = cycles();
-
-	tos = (Tos*)(USTKTOP-sizeof(Tos));
-	tos->kcycles += t - up->kentry;
-	tos->pcycles = t + up->pcycles;
-	tos->pid = up->pid;
-}
-
 static char *traps[64] = {
 	[0x00]	"sys: trap: unknown",
 	[0x01]	"sys: trap: WFI or WFE instruction execution",
@@ -112,7 +98,8 @@
 trap(Ureg *ureg)
 {
 	u32int type, intr;
-	
+	int user;
+
 	intr = ureg->type >> 32;
 	if(intr == 2){
 		fiq(ureg);
@@ -119,10 +106,7 @@
 		return;
 	}
 	splflo();
-	if(userureg(ureg)){
-		up->dbgreg = ureg;
-		up->kentry = cycles();
-	}
+	user = kenter(ureg);
 	type = (u32int)ureg->type >> 26;
 	switch(type){
 	case 0x20:	// instruction abort from lower level
@@ -187,7 +171,7 @@
 		break;
 	}
 	splhi();
-	if(userureg(ureg)){
+	if(user){
 		if(up->procctl || up->nnote)
 			notify(ureg);
 		kexit(ureg);
@@ -203,12 +187,12 @@
 	int i, s;
 	char *e;
 
-	up->kentry = cycles();
+	if(!kenter(ureg))
+		panic("syscall from  kernel");
 	
 	m->syscall++;
 	up->insyscall = 1;
 	up->pc = ureg->pc;
-	up->dbgreg = ureg;
 	
 	sp = ureg->sp;
 	up->scallnr = scallnr = ureg->r0;
@@ -542,9 +526,6 @@
 	splx(s);
 
 	p->tpidr = up->tpidr;
-
-	p->kentry = up->kentry;
-	p->pcycles = -p->kentry;
 }
 
 void
@@ -555,16 +536,11 @@
 
 	p->tpidr = 0;
 	syswr(TPIDR_EL0, p->tpidr);
-
-	p->kentry = cycles();
-	p->pcycles = -p->kentry;
 }
 
 void
 procsave(Proc *p)
 {
-	uvlong t;
-
 	if(p->fpstate == FPactive){
 		if(p->state == Moribund)
 			fpclear();
@@ -577,44 +553,21 @@
 		p->tpidr = sysrd(TPIDR_EL0);
 
 	putasid(p);	// release asid
-
-	t = cycles();
-	p->kentry -= t;
-	p->pcycles += t;
 }
 
 void
 procrestore(Proc *p)
 {
-	uvlong t;
-
-	if(p->kp)
-		return;
-	
-	syswr(TPIDR_EL0, p->tpidr);
-
-	t = cycles();
-	p->kentry += t;
-	p->pcycles -= t;
+	if(p->kp == 0)
+		syswr(TPIDR_EL0, p->tpidr);
 }
 
-static void
-linkproc(void)
-{
-	spllo();
-	up->kpfun(up->kparg);
-	pexit("kproc dying", 0);
-}
-
 void
-kprocchild(Proc* p, void (*func)(void*), void* arg)
+kprocchild(Proc *p, void (*entry)(void))
 {
-	p->sched.pc = (uintptr) linkproc;
+	p->sched.pc = (uintptr) entry;
 	p->sched.sp = (uintptr) p->kstack + KSTACK - 16;
 	*(void**)p->sched.sp = kprocchild;	/* fake */
-
-	p->kpfun = func;
-	p->kparg = arg;
 }
 
 void
--- a/sys/src/9/cycv/fns.h
+++ b/sys/src/9/cycv/fns.h
@@ -30,7 +30,6 @@
 uintptr ttbget(void);
 void ttbput(uintptr);
 void cycles(uvlong *);
-void kexit(Ureg *);
 ulong getifsr(void);
 ulong getdfsr(void);
 uintptr getifar(void);
--- a/sys/src/9/cycv/main.c
+++ b/sys/src/9/cycv/main.c
@@ -43,9 +43,6 @@
 {
 	ulong s;
 
-	p->kentry = up->kentry;
-	p->pcycles = -p->kentry;
-	
 	s = splhi();
 	switch(up->fpstate & ~FPillegal){
 	case FPactive:
@@ -63,22 +60,6 @@
 {
 	p->fpstate = FPinit;
 	fpoff();
-	
-	cycles(&p->kentry);
-	p->pcycles = -p->kentry;
-}
-
-void
-kexit(Ureg *)
-{
-	Tos *tos;
-	uvlong t;
-
-	tos = (Tos*)(USTKTOP-sizeof(Tos));
-	cycles(&t);
-	tos->kcycles += t - up->kentry;
-	tos->pcycles = t + up->pcycles;
-	tos->pid = up->pid;
 }
 
 static void
--- a/sys/src/9/cycv/timer.c
+++ b/sys/src/9/cycv/timer.c
@@ -96,6 +96,7 @@
 	hz = HPS_CLK * 1000000 * (numer + 1) / ((denum + 1) * 2 * (mpuclk + 1));
 	m->cpumhz = (hz + 500000) / 1000000;
 	m->cpuhz = hz;
+	m->cyclefreq = hz;
 	timerhz = m->cpuhz / 4;
 
 	mpcore[GTIMERCTL] = TIMERDIV - 1 << 8 | 3;
--- a/sys/src/9/cycv/trap.c
+++ b/sys/src/9/cycv/trap.c
@@ -150,13 +150,7 @@
 	int user;
 	ulong opc, cp;
 
-	user = userureg(ureg);
-	if(user){
-		if(up == nil)
-			panic("user trap: up=nil");
-		up->dbgreg = ureg;
-		cycles(&up->kentry);
-	}
+	user = kenter(ureg);
 	switch(ureg->type){
 	case PsrMund:
 		ureg->pc -= 4;
@@ -213,15 +207,12 @@
 	ulong scallnr;
 	vlong startns, stopns;
 	
-	if(!userureg(ureg))
+	if(!kenter(ureg))
 		panic("syscall: pc=%#.8lux", ureg->pc);
 	
-	cycles(&up->kentry);
-	
 	m->syscall++;
 	up->insyscall = 1;
 	up->pc = ureg->pc;
-	up->dbgreg = ureg;
 	
 	sp = ureg->sp;
 	up->scallnr = scallnr = ureg->r0;
@@ -511,8 +502,6 @@
 void
 procsave(Proc *p)
 {
-	uvlong t;
-
 	if(p->fpstate == FPactive){
 		if(p->state == Moribund)
 			fpclear();
@@ -520,9 +509,6 @@
 			fpsave(p->fpsave);
 		p->fpstate = FPinactive;
 	}
-	cycles(&t);
-	p->kentry -= t;
-	p->pcycles += t;
 
 	l1switch(&m->l1, 0);
 }
@@ -530,32 +516,13 @@
 void
 procrestore(Proc *p)
 {
-	uvlong t;
-
-	if(p->kp)
-		return;
-
-	cycles(&t);
-	p->kentry += t;
-	p->pcycles -= t;
 }
 
-static void
-linkproc(void)
-{
-	spllo();
-	up->kpfun(up->kparg);
-	pexit("kproc dying", 0);
-}
-
 void
-kprocchild(Proc* p, void (*func)(void*), void* arg)
+kprocchild(Proc *p, void (*entry)(void))
 {
-	p->sched.pc = (uintptr) linkproc;
+	p->sched.pc = (uintptr) entry;
 	p->sched.sp = (uintptr) p->kstack + KSTACK;
-
-	p->kpfun = func;
-	p->kparg = arg;
 }
 
 void
--- a/sys/src/9/kw/arch.c
+++ b/sys/src/9/kw/arch.c
@@ -39,25 +39,6 @@
 	}
 }
 
-/* go to user space */
-void
-kexit(Ureg*)
-{
-	uvlong t;
-	Tos *tos;
-
-	/* precise time accounting, kernel exit */
-	tos = (Tos*)(USTKTOP-sizeof(Tos));
-	t = fastticks(nil);
-	tos->kcycles += t - up->kentry;
-	tos->pcycles = t + up->pcycles;
-	tos->cyclefreq = Frequency;
-	tos->pid = up->pid;
-
-	/* make visible immediately to user proc */
-	cachedwbinvse(tos, sizeof *tos);
-}
-
 /*
  *  return the userpc the last exception happened at
  */
@@ -80,28 +61,14 @@
 }
 
 /*
- *  this is the body for all kproc's
- */
-static void
-linkproc(void)
-{
-	spllo();
-	up->kpfun(up->kparg);
-	pexit("kproc exiting", 0);
-}
-
-/*
  *  setup stack and initial PC for a new kernel proc.  This is architecture
  *  dependent because of the starting stack location
  */
 void
-kprocchild(Proc *p, void (*func)(void*), void *arg)
+kprocchild(Proc *p, void (*entry)(void))
 {
-	p->sched.pc = (uintptr)linkproc;
+	p->sched.pc = (uintptr)entry;
 	p->sched.sp = (uintptr)p->kstack+KSTACK;
-
-	p->kpfun = func;
-	p->kparg = arg;
 }
 
 /*
@@ -126,16 +93,11 @@
 procsetup(Proc* p)
 {
 	fpusysprocsetup(p);
-
-	cycles(&p->kentry);
-	p->pcycles = -p->kentry;
 }
 
 void
-procfork(Proc* p)
+procfork(Proc*)
 {
-	p->kentry = up->kentry;
-	p->pcycles = -p->kentry;
 }
 
 /*
@@ -144,12 +106,6 @@
 void
 procsave(Proc* p)
 {
-	uvlong t;
-
-	cycles(&t);
-	p->pcycles += t;
-	p->kentry -= t;
-
 	fpuprocsave(p);
 }
 
@@ -156,15 +112,6 @@
 void
 procrestore(Proc* p)
 {
-	uvlong t;
-
-	if(p->kp)
-		return;
-
-	cycles(&t);
-	p->pcycles -= t;
-	p->kentry += t;
-
 	fpuprocrestore(p);
 }
 
--- a/sys/src/9/kw/archkw.c
+++ b/sys/src/9/kw/archkw.c
@@ -381,6 +381,7 @@
 archconfinit(void)
 {
 	m->cpuhz = Frequency;
+	m->cyclefreq = m->cpuhz;
 	m->delayloop = m->cpuhz/2000; 	 /* initial estimate */
 	fixaddrmap();
 	if (Debug)
--- a/sys/src/9/kw/fns.h
+++ b/sys/src/9/kw/fns.h
@@ -140,8 +140,6 @@
 void*	vmap(uintptr, usize);
 void	vunmap(void*, usize);
 
-extern void kexit(Ureg*);
-
 #define	getpgcolor(a)	0
 #define	kmapinval()
 
--- a/sys/src/9/kw/syscall.c
+++ b/sys/src/9/kw/syscall.c
@@ -187,16 +187,13 @@
 	int i, scallnr;
 	vlong startns, stopns;
 
-	if(!userureg(ureg))
+	if(!kenter(ureg))
 		panic("syscall: from kernel: pc %#lux r14 %#lux psr %#lux",
 			ureg->pc, ureg->r14, ureg->psr);
 
-	cycles(&up->kentry);
-
 	m->syscall++;
 	up->insyscall = 1;
 	up->pc = ureg->pc;
-	up->dbgreg = ureg;
 
 	scallnr = ureg->r0;
 	up->scallnr = scallnr;
--- a/sys/src/9/kw/trap.c
+++ b/sys/src/9/kw/trap.c
@@ -376,12 +376,7 @@
 			rem, up, ureg, ureg->pc);
 	}
 
-	user = (ureg->psr & PsrMask) == PsrMusr;
-	if(user){
-		up->dbgreg = ureg;
-		cycles(&up->kentry);
-	}
-
+	user = kenter(ureg);
 	if(ureg->type == PsrMabt+1)
 		ureg->pc -= 8;
 	else
--- a/sys/src/9/mtx/trap.c
+++ b/sys/src/9/mtx/trap.c
@@ -215,11 +215,8 @@
 	int ecode, user;
 	char buf[ERRMAX], *s;
 
+	user = kenter(ureg);
 	ecode = (ureg->cause >> 8) & 0xff;
-	user = (ureg->srr1 & MSR_PR) != 0;
-	if(user)
-		up->dbgreg = ureg;
-
 	if((ureg->status & MSR_RI) == 0)
 		print("double fault?: ecode = %d\n", ecode);
 
@@ -503,22 +500,11 @@
 		print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
 }
 
-static void
-linkproc(void)
-{
-	spllo();
-	(*up->kpfun)(up->kparg);
-	pexit("", 0);
-}
-
 void
-kprocchild(Proc *p, void (*func)(void*), void *arg)
+kprocchild(Proc *p, void (*entry)(void))
 {
-	p->sched.pc = (ulong)linkproc;
+	p->sched.pc = (ulong)entry;
 	p->sched.sp = (ulong)p->kstack+KSTACK;
-
-	p->kpfun = func;
-	p->kparg = arg;
 }
 
 /*
@@ -625,7 +611,6 @@
 	m->syscall++;
 	up->insyscall = 1;
 	up->pc = ureg->pc;
-	up->dbgreg = ureg;
 
 	scallnr = ureg->r3;
 	up->scallnr = ureg->r3;
--- a/sys/src/9/omap/arch.c
+++ b/sys/src/9/omap/arch.c
@@ -39,25 +39,6 @@
 	}
 }
 
-/* go to user space */
-void
-kexit(Ureg*)
-{
-	uvlong t;
-	Tos *tos;
-
-	/* precise time accounting, kernel exit */
-	tos = (Tos*)(USTKTOP-sizeof(Tos));
-	cycles(&t);
-	tos->kcycles += t - up->kentry;
-	tos->pcycles = t + up->pcycles;
-	tos->cyclefreq = m->cpuhz;
-	tos->pid = up->pid;
-
-	/* make visible immediately to user proc */
-	cachedwbinvse(tos, sizeof *tos);
-}
-
 /*
  *  return the userpc the last exception happened at
  */
@@ -80,28 +61,14 @@
 }
 
 /*
- *  this is the body for all kproc's
- */
-static void
-linkproc(void)
-{
-	spllo();
-	up->kpfun(up->kparg);
-	pexit("kproc exiting", 0);
-}
-
-/*
  *  setup stack and initial PC for a new kernel proc.  This is architecture
  *  dependent because of the starting stack location
  */
 void
-kprocchild(Proc *p, void (*func)(void*), void *arg)
+kprocchild(Proc *p, void (*entry)(void))
 {
-	p->sched.pc = (uintptr)linkproc;
+	p->sched.pc = (uintptr)entry;
 	p->sched.sp = (uintptr)p->kstack+KSTACK;
-
-	p->kpfun = func;
-	p->kparg = arg;
 }
 
 /*
@@ -126,17 +93,11 @@
 procsetup(Proc* p)
 {
 	fpusysprocsetup(p);
-
-	cycles(&p->kentry);
-	p->pcycles = -p->kentry;
 }
 
 void
 procfork(Proc* p)
 {
-	p->kentry = up->kentry;
-	p->pcycles = -p->kentry;
-
 	fpuprocfork(p);
 }
 
@@ -146,12 +107,6 @@
 void
 procsave(Proc* p)
 {
-	uvlong t;
-
-	cycles(&t);
-	p->pcycles += t;
-	p->kentry -= t;
-
 // TODO: save and restore VFPv3 FP state once 5[cal] know the new registers.
 	fpuprocsave(p);
 }
@@ -159,14 +114,6 @@
 void
 procrestore(Proc* p)
 {
-	uvlong t;
-
-	if(p->kp)
-		return;
-	cycles(&t);
-	p->pcycles -= t;
-	p->kentry += t;
-
 	fpuprocrestore(p);
 }
 
--- a/sys/src/9/omap/fns.h
+++ b/sys/src/9/omap/fns.h
@@ -157,8 +157,6 @@
 void*	vmap(uintptr, usize);
 void	vunmap(void*, usize);
 
-extern void kexit(Ureg*);
-
 #define	getpgcolor(a)	0
 #define	kmapinval()
 
--- a/sys/src/9/omap/syscall.c
+++ b/sys/src/9/omap/syscall.c
@@ -186,16 +186,13 @@
 	long ret;
 	int i, scallnr;
 
-	if(!userureg(ureg))
+	if(!kenter(ureg))
 		panic("syscall: from kernel: pc %#lux r14 %#lux psr %#lux",
 			ureg->pc, ureg->r14, ureg->psr);
 
-	cycles(&up->kentry);
-
 	m->syscall++;
 	up->insyscall = 1;
 	up->pc = ureg->pc;
-	up->dbgreg = ureg;
 
 	if(up->procctl == Proc_tracesyscall){
 		up->procctl = Proc_stopme;
--- a/sys/src/9/omap/trap.c
+++ b/sys/src/9/omap/trap.c
@@ -465,12 +465,7 @@
 			rem, up, ureg, ureg->pc);
 	}
 
-	user = (ureg->psr & PsrMask) == PsrMusr;
-	if(user){
-		up->dbgreg = ureg;
-		cycles(&up->kentry);
-	}
-
+	user = kenter(ureg);
 	/*
 	 * All interrupts/exceptions should be resumed at ureg->pc-4,
 	 * except for Data Abort which resumes at ureg->pc-8.
--- a/sys/src/9/pc/main.c
+++ b/sys/src/9/pc/main.c
@@ -251,9 +251,6 @@
 		m->dr7 = 0;
 		putdr7(0);
 	}
-
-	cycles(&p->kentry);
-	p->pcycles = -p->kentry;
 }
 
 void
@@ -261,9 +258,6 @@
 {
 	int s;
 
-	p->kentry = up->kentry;
-	p->pcycles = -p->kentry;
-
 	/* inherit user descriptors */
 	memmove(p->gdt, up->gdt, sizeof(p->gdt));
 
@@ -292,8 +286,6 @@
 void
 procrestore(Proc *p)
 {
-	uvlong t;
-	
 	if(p->dr[7] != 0){
 		m->dr7 = p->dr[7];
 		putdr(p->dr);
@@ -301,13 +293,6 @@
 	
 	if(p->vmx != nil)
 		vmxprocrestore(p);
-
-	if(p->kp)
-		return;
-
-	cycles(&t);
-	p->kentry += t;
-	p->pcycles -= t;
 }
 
 /*
@@ -316,12 +301,6 @@
 void
 procsave(Proc *p)
 {
-	uvlong t;
-	
-	cycles(&t);
-	p->kentry -= t;
-	p->pcycles += t;
-
 	/* we could just always putdr7(0) but accessing DR7 might be slow in a VM */
 	if(m->dr7 != 0){
 		m->dr7 = 0;
--- a/sys/src/9/pc/trap.c
+++ b/sys/src/9/pc/trap.c
@@ -128,21 +128,6 @@
 	return 0;
 }
 
-/* go to user space */
-void
-kexit(Ureg*)
-{
-	uvlong t;
-	Tos *tos;
-
-	/* precise time accounting, kernel exit */
-	tos = (Tos*)(USTKTOP-sizeof(Tos));
-	cycles(&t);
-	tos->kcycles += t - up->kentry;
-	tos->pcycles = t + up->pcycles;
-	tos->pid = up->pid;
-}
-
 /*
  *  All traps come here.  It is slower to have all traps call trap()
  *  rather than directly vectoring the handler.  However, this avoids a
@@ -155,12 +140,7 @@
 {
 	int vno, user;
 
-	user = userureg(ureg);
-	if(user){
-		up->dbgreg = ureg;
-		cycles(&up->kentry);
-	}
-
+	user = kenter(ureg);
 	vno = ureg->trap;
 	if(!irqhandled(ureg, vno) && (!user || !usertrap(vno))){
 		if(!user){
@@ -490,15 +470,12 @@
 	ulong scallnr;
 	vlong startns, stopns;
 
-	if(!userureg(ureg))
+	if(!kenter(ureg))
 		panic("syscall: cs 0x%4.4luX", ureg->cs);
 
-	cycles(&up->kentry);
-
 	m->syscall++;
 	up->insyscall = 1;
 	up->pc = ureg->pc;
-	up->dbgreg = ureg;
 
 	sp = ureg->usp;
 	scallnr = ureg->ax;
@@ -789,16 +766,8 @@
 	ureg->ss |= 3;
 }
 
-static void
-linkproc(void)
-{
-	spllo();
-	up->kpfun(up->kparg);
-	pexit("kproc dying", 0);
-}
-
 void
-kprocchild(Proc* p, void (*func)(void*), void* arg)
+kprocchild(Proc *p, void (*entry)(void))
 {
 	/*
 	 * gotolabel() needs a word on the stack in
@@ -805,11 +774,8 @@
 	 * which to place the return PC used to jump
 	 * to linkproc().
 	 */
-	p->sched.pc = (ulong)linkproc;
+	p->sched.pc = (ulong)entry;
 	p->sched.sp = (ulong)p->kstack+KSTACK-BY2WD;
-
-	p->kpfun = func;
-	p->kparg = arg;
 }
 
 void
--- a/sys/src/9/pc64/main.c
+++ b/sys/src/9/pc64/main.c
@@ -304,17 +304,11 @@
 		m->dr7 = 0;
 		putdr7(0);
 	}
-
-	cycles(&p->kentry);
-	p->pcycles = -p->kentry;
 }
 
 void
 procfork(Proc *p)
 {
-	p->kentry = up->kentry;
-	p->pcycles = -p->kentry;
-
 	fpuprocfork(p);
 }
 
@@ -321,8 +315,6 @@
 void
 procrestore(Proc *p)
 {
-	uvlong t;
-	
 	if(p->dr[7] != 0){
 		m->dr7 = p->dr[7];
 		putdr(p->dr);
@@ -332,24 +324,11 @@
 		vmxprocrestore(p);
 
 	fpuprocrestore(p);
-
-	if(p->kp)
-		return;
-
-	cycles(&t);
-	p->kentry += t;
-	p->pcycles -= t;
 }
 
 void
 procsave(Proc *p)
 {
-	uvlong t;
-	
-	cycles(&t);
-	p->kentry -= t;
-	p->pcycles += t;
-
 	if(m->dr7 != 0){
 		m->dr7 = 0;
 		putdr7(0);
--- a/sys/src/9/pc64/trap.c
+++ b/sys/src/9/pc64/trap.c
@@ -131,30 +131,11 @@
 
 /* go to user space */
 void
-kexit(Ureg*)
-{
-	uvlong t;
-	Tos *tos;
-
-	/* precise time accounting, kernel exit */
-	tos = (Tos*)((uintptr)USTKTOP-sizeof(Tos));
-	cycles(&t);
-	tos->kcycles += t - up->kentry;
-	tos->pcycles = t + up->pcycles;
-	tos->pid = up->pid;
-}
-
-void
 trap(Ureg *ureg)
 {
 	int vno, user;
 
-	user = userureg(ureg);
-	if(user){
-		up->dbgreg = ureg;
-		cycles(&up->kentry);
-	}
-
+	user = kenter(ureg);
 	vno = ureg->type;
 	if(!irqhandled(ureg, vno) && (!user || !usertrap(vno))){
 		if(!user){
@@ -463,15 +444,12 @@
 	ulong scallnr;
 	vlong startns, stopns;
 
-	if(!userureg(ureg))
+	if(!kenter(ureg))
 		panic("syscall: cs 0x%4.4lluX", ureg->cs);
 
-	cycles(&up->kentry);
-
 	m->syscall++;
 	up->insyscall = 1;
 	up->pc = ureg->pc;
-	up->dbgreg = ureg;
 
 	sp = ureg->sp;
 	scallnr = ureg->bp;	/* RARG */
@@ -775,16 +753,8 @@
 	ureg->pc &= UADDRMASK;
 }
 
-static void
-linkproc(void)
-{
-	spllo();
-	up->kpfun(up->kparg);
-	pexit("kproc dying", 0);
-}
-
 void
-kprocchild(Proc* p, void (*func)(void*), void* arg)
+kprocchild(Proc *p, void (*entry)(void))
 {
 	/*
 	 * gotolabel() needs a word on the stack in
@@ -791,11 +761,8 @@
 	 * which to place the return PC used to jump
 	 * to linkproc().
 	 */
-	p->sched.pc = (uintptr)linkproc;
+	p->sched.pc = (uintptr)entry;
 	p->sched.sp = (uintptr)p->kstack+KSTACK-BY2WD;
-
-	p->kpfun = func;
-	p->kparg = arg;
 }
 
 void
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -686,7 +686,7 @@
 
 	uvlong	kentry;		/* Kernel entry time stamp (for profiling) */
 	/*
-	 * pcycles: cycles spent in this process (updated on procsave/restore)
+	 * pcycles: cycles spent in this process (updated on procswitch)
 	 * when this is the current proc and we're in the kernel
 	 * (procrestores outnumber procsaves by one)
 	 * the number of cycles spent in the proc is pcycles + cycles()
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -150,10 +150,12 @@
 int		islo(void);
 Segment*	isoverlap(uintptr, uintptr);
 Physseg*	findphysseg(char*);
+int		kenter(Ureg*);
+void		kexit(Ureg*);
 void		kickpager(void);
 void		killbig(char*);
 void		kproc(char*, void(*)(void*), void*);
-void		kprocchild(Proc*, void (*)(void*), void*);
+void		kprocchild(Proc*, void (*)(void));
 void		(*kproftimer)(uintptr);
 void		ksetenv(char*, char*, int);
 void		kstrcpy(char*, char*, int);
--- a/sys/src/9/port/portmkfile
+++ b/sys/src/9/port/portmkfile
@@ -79,7 +79,9 @@
 sdscsi.$O:	../port/sd.h /$objtype/include/ureg.h
 sdaoe.$O:	../port/sd.h /$objtype/include/ureg.h
 trap.$O:	/$objtype/include/ureg.h
+proc.$O:	/$objtype/include/ureg.h
 devproc.$O:	/$objtype/include/ureg.h
+portclock.$O:	/$objtype/include/ureg.h
 userinit.$O:	initcode.i
 trap.$O:	../port/systab.h
 devpipe.$O:	../port/netif.h
@@ -94,7 +96,7 @@
 thwack.$O:	../port/thwack.h
 unthwack.$O:	../port/thwack.h
 devsdp.$O:	../port/thwack.h
-portclock.$O sysproc.$O:	/sys/include/tos.h
+portclock.$O sysproc.$O proc.$O:	/sys/include/tos.h
 devproc.$O edf.$O proc.$O:	/sys/include/trace.h
 auth.$O devcons.$O:	/sys/include/authsrv.h
 devcap.$O:	/sys/include/libsec.h
--- a/sys/src/9/port/proc.c
+++ b/sys/src/9/port/proc.c
@@ -6,6 +6,8 @@
 #include	"../port/error.h"
 #include	"edf.h"
 #include	<trace.h>
+#include	"tos.h"
+#include	"ureg.h"
 
 int	schedgain = 30;	/* units in seconds */
 int	nrdy;
@@ -109,6 +111,58 @@
 	sched();
 }
 
+int
+kenter(Ureg *ureg)
+{
+	int user;
+
+	user = userureg(ureg);
+	if(user){
+		up->dbgreg = ureg;
+		cycles(&up->kentry);
+	}
+	return user;
+}
+
+void
+kexit(Ureg*)
+{
+	uvlong t;
+	Tos *tos;
+
+	cycles(&t);
+
+	/* precise time accounting, kernel exit */
+	tos = (Tos*)(USTKTOP-sizeof(Tos));
+	tos->kcycles += t - up->kentry;
+	tos->pcycles = t + up->pcycles;
+	tos->pid = up->pid;
+}
+
+static void
+procswitch(void)
+{
+	uvlong t;
+
+	/* statistics */
+	m->cs++;
+
+	cycles(&t);
+	up->kentry -= t;
+	up->pcycles += t;
+
+	procsave(up);
+
+	if(!setlabel(&up->sched))
+		gotolabel(&m->sched);
+
+	procrestore(up);
+
+	cycles(&t);
+	up->kentry += t;
+	up->pcycles -= t;
+}
+
 /*
  *  If changing this routine, look also at sleep().  It
  *  contains a copy of the guts of sched().
@@ -151,19 +205,10 @@
 			return;
 		}
 		up->delaysched = 0;
-
 		splhi();
-
-		/* statistics */
-		m->cs++;
-
-		procsave(up);
-		if(setlabel(&up->sched)){
-			procrestore(up);
-			spllo();
-			return;
-		}
-		gotolabel(&m->sched);
+ 		procswitch();
+		spllo();
+		return;
 	}
 	p = runproc();
 	if(p->edf == nil){
@@ -758,25 +803,9 @@
 			pt(up, SSleep, 0);
 		up->state = Wakeme;
 		up->r = r;
-
-		/* statistics */
-		m->cs++;
-
-		procsave(up);
-		if(setlabel(&up->sched)) {
-			/*
-			 *  here when the process is awakened
-			 */
-			procrestore(up);
-			spllo();
-		} else {
-			/*
-			 *  here to go to sleep (i.e. stop Running)
-			 */
-			unlock(&up->rlock);
-			unlock(r);
-			gotolabel(&m->sched);
-		}
+		unlock(&up->rlock);
+		unlock(r);
+		procswitch();
 	}
 
 	if(up->notepending) {
@@ -1376,6 +1405,14 @@
 	procflushmmu(matchother, up);
 }
 
+static void
+linkproc(void)
+{
+	spllo();
+	(*up->kpfun)(up->kparg);
+	pexit("kproc exiting", 0);
+}
+
 void
 kproc(char *name, void (*func)(void *), void *arg)
 {
@@ -1406,7 +1443,9 @@
 	p->hang = 0;
 	p->kp = 1;
 
-	kprocchild(p, func, arg);
+	p->kpfun = func;
+	p->kparg = arg;
+	kprocchild(p, linkproc);
 
 	kstrdup(&p->text, name);
 	kstrdup(&p->user, eve);
@@ -1422,6 +1461,8 @@
 	p->insyscall = 1;
 	memset(p->time, 0, sizeof(p->time));
 	p->time[TReal] = MACHP(0)->ticks;
+	cycles(&p->kentry);
+	p->pcycles = -p->kentry;
 
 	pidalloc(p);
 
--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -18,7 +18,7 @@
 }
 
 static void
-abortion(void*)
+abortion(void)
 {
 	pexit("fork aborted", 1);
 }
@@ -125,6 +125,8 @@
 	p->insyscall = 0;
 	memset(p->time, 0, sizeof(p->time));
 	p->time[TReal] = MACHP(0)->ticks;
+	p->kentry = up->kentry;
+	p->pcycles = -p->kentry;
 
 	pid = pidalloc(p);
 
@@ -133,7 +135,7 @@
 	/* Abort the child process on error */
 	if(waserror()){
 		p->kp = 1;
-		kprocchild(p, abortion, 0);
+		kprocchild(p, abortion);
 		ready(p);
 		nexterror();
 	}
@@ -577,6 +579,7 @@
 	up->notified = 0;
 	up->privatemem = 0;
 	up->noswap = 0;
+	up->pcycles = -up->kentry;
 	procsetup(up);
 	qunlock(&up->debug);
 
--- a/sys/src/9/ppc/main.c
+++ b/sys/src/9/ppc/main.c
@@ -186,28 +186,16 @@
 procsetup(Proc *p)
 {
 	p->fpstate = FPinit;
-
-	cycles(&p->kentry);
-	p->pcycles = -p->kentry;
 }
 
 void
 procfork(Proc *p)
 {
-	p->kentry = up->kentry;
-	p->pcycles = -p->kentry;
 }
 
 void
 procrestore(Proc *p)
 {
-	uvlong t;
-
-	if(p->kp)
-		return;
-	cycles(&t);
-	p->pcycles -= t;
-	p->kentry += t;
 }
 
 /*
@@ -216,11 +204,6 @@
 void
 procsave(Proc *p)
 {
-	uvlong t;
-
-	cycles(&t);
-	p->pcycles += t;
-	p->kentry -= t;
 	if(p->fpstate == FPactive){
 		if(p->state != Moribund)
 			fpsave(up->fpsave);
--- a/sys/src/9/ppc/trap.c
+++ b/sys/src/9/ppc/trap.c
@@ -141,20 +141,6 @@
 };
 
 void
-kexit(Ureg*)
-{
-	uvlong t;
-	Tos *tos;
-
-	/* precise time accounting, kernel exit */
-	tos = (Tos*)(USTKTOP-sizeof(Tos));
-	cycles(&t);
-	tos->kcycles += t - up->kentry;
-	tos->pcycles = t + up->pcycles;
-	tos->pid = up->pid;
-}
-
-void
 trap(Ureg *ureg)
 {
 	int ecode, user;
@@ -161,15 +147,10 @@
 	char buf[ERRMAX], *s;
 	extern FPsave initfp;
 
-	ecode = (ureg->cause >> 8) & 0xff;
-	user = (ureg->srr1 & MSR_PR) != 0;
-	if(user){
-		cycles(&up->kentry);
-		up->dbgreg = ureg;
-	}
+	user = kenter(ureg);
 	if((ureg->status & MSR_RI) == 0)
 		print("double fault?: ecode = %d\n", ecode);
-
+	ecode = (ureg->cause >> 8) & 0xff;
 	switch(ecode) {
 	case CEI:
 		m->intr++;
@@ -495,22 +476,11 @@
 	delay(500);
 }
 
-static void
-linkproc(void)
-{
-	spllo();
-	(*up->kpfun)(up->kparg);
-	pexit("", 0);
-}
-
 void
-kprocchild(Proc *p, void (*func)(void*), void *arg)
+kprocchild(Proc *p, void (*entry)(void))
 {
-	p->sched.pc = (ulong)linkproc;
+	p->sched.pc = (ulong)entry;
 	p->sched.sp = (ulong)p->kstack+KSTACK;
-
-	p->kpfun = func;
-	p->kparg = arg;
 }
 
 /*
@@ -618,7 +588,6 @@
 	m->syscall++;
 	up->insyscall = 1;
 	up->pc = ureg->pc;
-	up->dbgreg = ureg;
 
 	if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
 		print("fpstate check, entry syscall\n");
--- a/sys/src/9/sgi/clock.c
+++ b/sys/src/9/sgi/clock.c
@@ -80,7 +80,7 @@
 
 	m->speed = mips;
 	m->hz = m->speed*Mhz;
-
+	m->cyclefreq = Basetickfreq;
 	m->maxperiod = Basetickfreq / HZ;
 	m->minperiod = Basetickfreq / (100*HZ);
 	m->lastcount = rdcount();
--- a/sys/src/9/sgi/main.c
+++ b/sys/src/9/sgi/main.c
@@ -289,9 +289,6 @@
 {
 	p->fpstate = FPinit;
 	memmove(p->fpsave, &initfp, sizeof(FPsave));
-
-	cycles(&p->kentry);
-	p->pcycles = -p->kentry;
 }
 
 void
@@ -299,9 +296,6 @@
 {
 	int s;
 
-	p->kentry = up->kentry;
-	p->pcycles = -p->kentry;
-
 	s = splhi();
 	switch(up->fpstate & ~FPillegal){
 	case FPactive:
@@ -318,8 +312,6 @@
 void
 procsave(Proc *p)
 {
-	uvlong t;
-
 	if(p->fpstate == FPactive){
 		if(p->state != Moribund) {
 			savefpregs(p->fpsave);
@@ -326,20 +318,11 @@
 			p->fpstate = FPinactive;
 		}
 	}
-	
-	cycles(&t);
-	p->pcycles += t;
 }
 
 void
 procrestore(Proc *p)
 {
-	uvlong t;
-
-	if(p->kp)
-		return;
-	cycles(&t);
-	p->pcycles -= t;
 }
 
 void
--- a/sys/src/9/sgi/trap.c
+++ b/sys/src/9/sgi/trap.c
@@ -152,24 +152,7 @@
 	}
 }
 
-/* prepare to go to user space */
 void
-kexit(Ureg *ur)
-{
-	Tos *tos;
-
-	/* replicate fpstate to ureg status */
-	if(up->fpstate != FPactive)
-		ur->status &= ~CU1;
-
-	/* precise time accounting, kernel exit */
-	tos = (Tos*)(USTKTOP-sizeof(Tos));
-	tos->kcycles += fastticks(&tos->cyclefreq) - up->kentry;
-	tos->pcycles = up->pcycles;
-	tos->pid = up->pid;
-}
-
-void
 trap(Ureg *ur)
 {
 	int ecode, clockintr, user, cop, x, fpchk;
@@ -190,18 +173,11 @@
 		dumpstack();
 		for(;;);
 	}
-
-	ecode = (ur->cause>>2)&EXCMASK;
-	user = userureg(ur);
+	user = kenter(ur);
 	if (ur->cause & TS)
 		panic("trap: tlb shutdown");
-
+	ecode = (ur->cause>>2)&EXCMASK;
 	fpchk = 0;
-	if(user){
-		up->dbgreg = ur;
-		cycles(&up->kentry);
-	}
-
 	clockintr = 0;
 	switch(ecode){
 	case CINT:
@@ -308,6 +284,9 @@
 
 	if(user){
 		notify(ur);
+		/* replicate fpstate to ureg status */
+		if(up->fpstate != FPactive)
+			ur->status &= ~CU1;
 		kexit(ur);
 	}
 }
@@ -701,12 +680,12 @@
 	vlong startns;
 	char *e;
 
-	cycles(&up->kentry);
+	if(!kenter(ur))
+		panic("syscall from kernel");
 
 	m->syscall++;
 	up->insyscall = 1;
 	up->pc = ur->pc;
-	up->dbgreg = ur;
 	ur->cause = 16<<2;	/* for debugging: system call is undef 16 */
 
 	scallnr = ur->r1;
@@ -774,6 +753,9 @@
 	/* if we delayed sched because we held a lock, sched now */
 	if(up->delaysched)
 		sched();
+	/* replicate fpstate to ureg status */
+	if(up->fpstate != FPactive)
+		ur->status &= ~CU1;
 	kexit(ur);
 }
 
@@ -794,23 +776,11 @@
 	cur->pc += 4;
 }
 
-static
 void
-linkproc(void)
+kprocchild(Proc *p, void (*entry)(void))
 {
-	spllo();
-	up->kpfun(up->kparg);
-	pexit("kproc exiting", 0);
-}
-
-void
-kprocchild(Proc *p, void (*func)(void*), void *arg)
-{
-	p->sched.pc = (ulong)linkproc;
+	p->sched.pc = (ulong)entry;
 	p->sched.sp = (ulong)p->kstack+KSTACK;
-
-	p->kpfun = func;
-	p->kparg = arg;
 }
 
 /* set up user registers before return from exec() */
--- a/sys/src/9/teg2/arch.c
+++ b/sys/src/9/teg2/arch.c
@@ -39,25 +39,6 @@
 	}
 }
 
-/* go to user space */
-void
-kexit(Ureg*)
-{
-	uvlong t;
-	Tos *tos;
-
-	/* precise time accounting, kernel exit */
-	tos = (Tos*)(USTKTOP-sizeof(Tos));
-	cycles(&t);
-	tos->kcycles += t - up->kentry;
-	tos->pcycles = up->pcycles;
-	tos->cyclefreq = m->cpuhz;
-	tos->pid = up->pid;
-
-	/* make visible immediately to user phase */
-	l1cache->wbse(tos, sizeof *tos);
-}
-
 /*
  *  return the userpc the last exception happened at
  */
@@ -80,28 +61,14 @@
 }
 
 /*
- *  this is the body for all kproc's
- */
-static void
-linkproc(void)
-{
-	spllo();
-	up->kpfun(up->kparg);
-	pexit("kproc exiting", 0);
-}
-
-/*
  *  setup stack and initial PC for a new kernel proc.  This is architecture
  *  dependent because of the starting stack location
  */
 void
-kprocchild(Proc *p, void (*func)(void*), void *arg)
+kprocchild(Proc *p, void (*entry)(void))
 {
-	p->sched.pc = (uintptr)linkproc;
+	p->sched.pc = (uintptr)entry;
 	p->sched.sp = (uintptr)p->kstack+KSTACK;
-
-	p->kpfun = func;
-	p->kparg = arg;
 }
 
 /*
@@ -134,11 +101,6 @@
 void
 procsave(Proc* p)
 {
-	uvlong t;
-
-	cycles(&t);
-	p->pcycles += t;
-
 	fpuprocsave(p);
 	l1cache->wbse(p, sizeof *p);		/* is this needed? */
 	l1cache->wb();				/* is this needed? */
@@ -147,9 +109,6 @@
 void
 procfork(Proc* p)
 {
-	p->kentry = up->kentry;
-	p->pcycles = -p->kentry;
-	
 	fpuprocfork(p);
 }
 
@@ -156,12 +115,8 @@
 void
 procrestore(Proc* p)
 {
-	uvlong t;
-
 	if(p->kp)
 		return;
-	cycles(&t);
-	p->pcycles -= t;
 	wakewfi();		/* in case there's another runnable proc */
 
 	/* let it fault in at first use */
--- a/sys/src/9/teg2/archtegra.c
+++ b/sys/src/9/teg2/archtegra.c
@@ -327,6 +327,7 @@
 		if (hz >= 100*Mhz && hz <= 3600UL*Mhz)
 			m->cpuhz = hz;
 	}
+	m->cyclefreq = m->cpuhz;
 	m->delayloop = m->cpuhz/2000;		/* initial estimate */
 	errata();
 }
--- a/sys/src/9/teg2/fns.h
+++ b/sys/src/9/teg2/fns.h
@@ -191,8 +191,6 @@
 void*	vmap(uintptr, usize);
 void vunmap(void*, usize);
 
-extern void kexit(Ureg*);
-
 #define	getpgcolor(a)	0
 #define	kmapinval()
 
--- a/sys/src/9/teg2/syscall.c
+++ b/sys/src/9/teg2/syscall.c
@@ -194,16 +194,13 @@
 	int i, scallnr;
 	vlong startns, stopns;
 
-	if(!userureg(ureg))
+	if(!kenter(ureg))
 		panic("syscall: from kernel: pc %#lux r14 %#lux psr %#lux",
 			ureg->pc, ureg->r14, ureg->psr);
 
-	cycles(&up->kentry);
-
 	m->syscall++;
 	up->insyscall = 1;
 	up->pc = ureg->pc;
-	up->dbgreg = ureg;
 
 	scallnr = ureg->r0;
 	up->scallnr = scallnr;
--- a/sys/src/9/teg2/trap.c
+++ b/sys/src/9/teg2/trap.c
@@ -831,12 +831,7 @@
 	}
 
 	m->perf.intrts = perfticks();
-	user = (ureg->psr & PsrMask) == PsrMusr;
-	if(user){
-		up->dbgreg = ureg;
-		cycles(&up->kentry);
-	}
-
+	user = kenter(ureg);
 	/*
 	 * All interrupts/exceptions should be resumed at ureg->pc-4,
 	 * except for Data Abort which resumes at ureg->pc-8.
--- a/sys/src/9/xen/main.c
+++ b/sys/src/9/xen/main.c
@@ -337,9 +337,6 @@
 {
 	int s;
 
-	p->kentry = up->kentry;
-	p->pcycles = -p->kentry;
-
 	/* save floating point state */
 	s = splhi();
 	switch(up->fpstate & ~FPillegal){
@@ -358,12 +355,6 @@
 void
 procrestore(Proc *p)
 {
-	uvlong t;
-
-	if(p->kp)
-		return;
-	cycles(&t);
-	p->pcycles -= t;
 }
 
 /*
@@ -372,10 +363,6 @@
 void
 procsave(Proc *p)
 {
-	uvlong t;
-
-	cycles(&t);
-	p->pcycles += t;
 	if(p->fpstate == FPactive){
 		if(p->state == Moribund)
 			fpclear();
--- a/sys/src/9/xen/trap.c
+++ b/sys/src/9/xen/trap.c
@@ -134,22 +134,6 @@
 	return 0;
 }
 
-/* go to user space */
-void
-kexit(Ureg*)
-{
-	uvlong t;
-	Tos *tos;
-
-	/* precise time accounting, kernel exit */
-	tos = (Tos*)(USTKTOP-sizeof(Tos));
-	cycles(&t);
-	tos->kcycles += t - up->kentry;
-	tos->pcycles = up->pcycles;
-	tos->pid = up->pid;
-	INTRLOG(dprint("leave kexit, TOS %p\n", tos);)
-}
-
 /*
  *  All traps come here.  It is slower to have all traps call trap()
  *  rather than directly vectoring the handler.  However, this avoids a
@@ -162,12 +146,7 @@
 {
 	int vno, user;
 
-	user = userureg(ureg);
-	if(user){
-		up->dbgreg = ureg;
-		cycles(&up->kentry);
-	}
-
+	user = kenter(ureg);
 	vno = ureg->trap;
 	if(!irqhandled(ureg, vno) && (!user || !usertrap(vno))){
 		if(!user){
@@ -406,15 +385,12 @@
 	SYSCALLLOG(dprint("%d: syscall ...#%ld(%s)\n", 
 			up->pid, ureg->ax, sysctab[ureg->ax]);)
 	
-	if((ureg->cs & 0xFFFF) != UESEL)
+	if(!kenter(ureg))
 		panic("syscall: cs 0x%4.4luX\n", ureg->cs);
 
-	cycles(&up->kentry);
-
 	m->syscall++;
 	up->insyscall = 1;
 	up->pc = ureg->pc;
-	up->dbgreg = ureg;
 
 	if(up->procctl == Proc_tracesyscall){
 		up->procctl = Proc_stopme;
@@ -725,16 +701,8 @@
 	ureg->ss = ss;
 }
 
-static void
-linkproc(void)
-{
-	spllo();
-	up->kpfun(up->kparg);
-	pexit("kproc dying", 0);
-}
-
 void
-kprocchild(Proc* p, void (*func)(void*), void* arg)
+kprocchild(Proc *p, void (*entry)(void))
 {
 	/*
 	 * gotolabel() needs a word on the stack in
@@ -741,11 +709,8 @@
 	 * which to place the return PC used to jump
 	 * to linkproc().
 	 */
-	p->sched.pc = (ulong)linkproc;
+	p->sched.pc = (ulong)entry;
 	p->sched.sp = (ulong)p->kstack+KSTACK-BY2WD;
-
-	p->kpfun = func;
-	p->kparg = arg;
 }
 
 void
--- a/sys/src/9/zynq/fns.h
+++ b/sys/src/9/zynq/fns.h
@@ -30,7 +30,6 @@
 uintptr ttbget(void);
 void ttbput(uintptr);
 void cycles(uvlong *);
-void kexit(Ureg *);
 ulong getifsr(void);
 ulong getdfsr(void);
 uintptr getifar(void);
--- a/sys/src/9/zynq/main.c
+++ b/sys/src/9/zynq/main.c
@@ -43,9 +43,6 @@
 {
 	ulong s;
 
-	p->kentry = up->kentry;
-	p->pcycles = -p->kentry;
-	
 	s = splhi();
 	switch(up->fpstate & ~FPillegal){
 	case FPactive:
@@ -63,22 +60,6 @@
 {
 	p->fpstate = FPinit;
 	fpoff();
-	
-	cycles(&p->kentry);
-	p->pcycles = -p->kentry;
-}
-
-void
-kexit(Ureg *)
-{
-	Tos *tos;
-	uvlong t;
-
-	tos = (Tos*)(USTKTOP-sizeof(Tos));
-	cycles(&t);
-	tos->kcycles += t - up->kentry;
-	tos->pcycles = t + up->pcycles;
-	tos->pid = up->pid;
 }
 
 ulong *l2;
--- a/sys/src/9/zynq/trap.c
+++ b/sys/src/9/zynq/trap.c
@@ -150,13 +150,7 @@
 	int user;
 	ulong opc, cp;
 
-	user = userureg(ureg);
-	if(user){
-		if(up == nil)
-			panic("user trap: up=nil");
-		up->dbgreg = ureg;
-		cycles(&up->kentry);
-	}
+	user = kenter(ureg);
 	switch(ureg->type){
 	case PsrMund:
 		ureg->pc -= 4;
@@ -213,15 +207,12 @@
 	ulong scallnr;
 	vlong startns, stopns;
 	
-	if(!userureg(ureg))
+	if(!kenter(ureg))
 		panic("syscall: pc=%#.8lux", ureg->pc);
 	
-	cycles(&up->kentry);
-	
 	m->syscall++;
 	up->insyscall = 1;
 	up->pc = ureg->pc;
-	up->dbgreg = ureg;
 	
 	sp = ureg->sp;
 	up->scallnr = scallnr = ureg->r0;
@@ -511,8 +502,6 @@
 void
 procsave(Proc *p)
 {
-	uvlong t;
-
 	if(p->fpstate == FPactive){
 		if(p->state == Moribund)
 			fpclear();
@@ -520,10 +509,6 @@
 			fpsave(p->fpsave);
 		p->fpstate = FPinactive;
 	}
-	cycles(&t);
-	p->kentry -= t;
-	p->pcycles += t;
-
 	l1switch(&m->l1, 0);
 }
 
@@ -530,32 +515,13 @@
 void
 procrestore(Proc *p)
 {
-	uvlong t;
-
-	if(p->kp)
-		return;
-
-	cycles(&t);
-	p->kentry += t;
-	p->pcycles -= t;
 }
 
-static void
-linkproc(void)
-{
-	spllo();
-	up->kpfun(up->kparg);
-	pexit("kproc dying", 0);
-}
-
 void
-kprocchild(Proc* p, void (*func)(void*), void* arg)
+kprocchild(Proc *p, void (*entry)(void))
 {
-	p->sched.pc = (uintptr) linkproc;
+	p->sched.pc = (uintptr) entry;
 	p->sched.sp = (uintptr) p->kstack + KSTACK;
-
-	p->kpfun = func;
-	p->kparg = arg;
 }
 
 void