shithub: riscv

Download patch

ref: d886c9d2485faf70b0e3ebc9256cfb08f3a7f72f
parent: df91e2466799fa50bdfde912559278579381d05b
author: aiju <[email protected]>
date: Fri Sep 2 08:23:34 EDT 2011

added omap4 kernel prototype

--- /dev/null
+++ b/sys/src/9/omap4/arch.c
@@ -1,0 +1,161 @@
+#include "u.h"
+#include "ureg.h"
+#include "../port/lib.h"
+#include "../port/error.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "arm.h"
+#include "tos.h"
+
+void (*proctrace)(Proc *, int, vlong);
+
+ulong
+userpc(void)
+{
+	return dbgpc(up);
+}
+
+ulong
+dbgpc(Proc *p)
+{
+	Ureg *ureg;
+	
+	ureg = p->dbgreg;
+	if(ureg == 0)
+		return 0;
+	return ureg->pc;
+}
+
+void
+procsave(Proc *)
+{
+}
+
+void
+procrestore(Proc *)
+{
+}
+
+void
+procfork(Proc *)
+{
+}
+
+void
+procsetup(Proc *p)
+{
+	p->fpstate = FPinit;
+}
+
+static void
+linkproc(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.sp = (ulong) p->kstack + KSTACK;
+	p->kpfun = func;
+	p->kparg = arg;
+}
+
+void
+forkchild(Proc *p, Ureg *ureg)
+{
+	Ureg *cureg;
+	
+	p->sched.sp = (ulong) p->kstack + KSTACK - (sizeof(Ureg) + 8);
+	p->sched.pc = (ulong) forkret;
+	cureg = (Ureg*) (p->sched.sp + 8);
+	memmove(cureg, ureg, sizeof(Ureg));
+	cureg->r0 = 0;
+	p->psstate = 0;
+	p->insyscall = 0;
+}
+
+long
+execregs(ulong entry, ulong ssize, ulong nargs)
+{
+	ulong *sp;
+	Ureg *ureg;
+	
+	up->fpstate = FPinit;
+	sp = (ulong *) (USTKTOP - ssize);
+	*--sp = nargs;
+	
+	ureg = up->dbgreg;
+	memset(ureg, 0, sizeof *ureg);
+	ureg->psr = PsrMusr;
+	ureg->sp = (ulong) sp;
+	ureg->pc = entry;
+	return USTKTOP - sizeof(Tos);
+}
+
+void
+evenaddr(uintptr addr)
+{
+	if(addr & 3){
+		postnote(up, 1, "sys: odd address", NDebug);
+		error(Ebadarg);
+	}
+}
+
+Segment *
+data2txt(Segment *)
+{
+	panic("data2txt");
+}
+
+void
+_dumpstack(ulong sp, ulong pc)
+{
+	int x;
+	uintptr l, v, i, estack;
+
+	x = 0;
+	x += iprint("ktrace /arm/s9panda %#.8lux %#.8lux <<EOF\n",
+		pc, sp);
+	i = 0;
+	if(up
+	&& (uintptr)&l >= (uintptr)up->kstack
+	&& (uintptr)&l <= (uintptr)up->kstack+KSTACK)
+		estack = (uintptr)up->kstack+KSTACK;
+	else if((uintptr)&l >= (uintptr)(KTZERO - BY2PG)
+	&& (uintptr)&l <= (uintptr)KTZERO)
+		estack = (uintptr)KTZERO;
+	else
+		return;
+	x += iprint("estackx %p\n", estack);
+
+	for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){
+		v = *(uintptr*)l;
+		if((KTZERO < v && v < (uintptr)etext) || estack-l < 32){
+			x += iprint("%.8p=%.8p ", l, v);
+			i++;
+		}
+		if(i == 4){
+			i = 0;
+			x += iprint("\n");
+		}
+	}
+	if(i)
+		iprint("\n");
+	iprint("EOF\n");
+}
+
+void
+printureg(Ureg *ureg)
+{
+	print("R0  %.8ulx R1  %.8ulx R2  %.8ulx R3  %.8ulx\n", ureg->r0, ureg->r1, ureg->r2, ureg->r3);
+	print("R4  %.8ulx R5  %.8ulx R6  %.8ulx R7  %.8ulx\n", ureg->r4, ureg->r5, ureg->r6, ureg->r7);
+	print("R8  %.8ulx R9  %.8ulx R10 %.8ulx R11 %.8ulx\n", ureg->r8, ureg->r9, ureg->r10, ureg->r11);
+	print("R12 %.8ulx R13 %.8ulx R14 %.8ulx R15 %.8ulx\n", ureg->r12, ureg->r13, ureg->r14, ureg->pc);
+	print("PSR %.8ulx exception %ld\n", ureg->psr, ureg->type);
+}
--- /dev/null
+++ b/sys/src/9/omap4/arm.h
@@ -1,0 +1,246 @@
+/*
+ * arm-specific definitions for cortex-a8
+ * these are used in C and assembler
+ *
+ * `cortex' refers specifically to the cortex-a8.
+ */
+
+/*
+ * Program Status Registers
+ */
+#define PsrMusr		0x00000010		/* mode */
+#define PsrMfiq		0x00000011
+#define PsrMirq		0x00000012
+#define PsrMsvc		0x00000013	/* `protected mode for OS' */
+#define PsrMmon		0x00000016	/* `secure monitor' (trustzone hyper) */
+#define PsrMabt		0x00000017
+#define PsrMund		0x0000001B
+#define PsrMsys		0x0000001F	/* `privileged user mode for OS' (trustzone) */
+#define PsrMask		0x0000001F
+
+#define PsrDfiq		0x00000040		/* disable FIQ interrupts */
+#define PsrDirq		0x00000080		/* disable IRQ interrupts */
+
+#define PsrV		0x10000000		/* overflow */
+#define PsrC		0x20000000		/* carry/borrow/extend */
+#define PsrZ		0x40000000		/* zero */
+#define PsrN		0x80000000		/* negative/less than */
+
+/*
+ * Coprocessors
+ */
+#define CpFP		10			/* float FP, VFP cfg. */
+#define CpDFP		11			/* double FP */
+#define CpSC		15			/* System Control */
+
+/*
+ * Primary (CRn) CpSC registers.
+ */
+#define	CpID		0			/* ID and cache type */
+#define	CpCONTROL	1			/* miscellaneous control */
+#define	CpTTB		2			/* Translation Table Base(s) */
+#define	CpDAC		3			/* Domain Access Control */
+#define	CpFSR		5			/* Fault Status */
+#define	CpFAR		6			/* Fault Address */
+#define	CpCACHE		7			/* cache/write buffer control */
+#define	CpTLB		8			/* TLB control */
+#define	CpCLD		9			/* L2 Cache Lockdown, op1==1 */
+#define CpTLD		10			/* TLB Lockdown, with op2 */
+#define CpVECS		12			/* vector bases, op1==0, Crm==0, op2s (cortex) */
+#define	CpPID		13			/* Process ID */
+#define CpDTLB		15			/* TLB, L1 cache stuff (cortex) */
+
+/*
+ * CpTTB op1==0, Crm==0 opcode2 values.
+ */
+#define CpTTB0		0
+#define CpTTB1		1			/* cortex */
+#define CpTTBctl	2			/* cortex */
+
+/*
+ * CpID Secondary (CRm) registers.
+ */
+#define CpIDidct	0
+
+/*
+ * CpID op1==0 opcode2 fields.
+ * the cortex has more op1 codes for cache size, etc.
+ */
+#define CpIDid		0			/* main ID */
+#define CpIDct		1			/* cache type */
+#define CpIDtlb		3			/* tlb type (cortex) */
+#define CpIDmpid	5			/* multiprocessor id (cortex) */
+
+/* CpIDid op1 values */
+#define CpIDcsize	1			/* cache size (cortex) */
+#define CpIDcssel	2			/* cache size select (cortex) */
+
+/*
+ * CpCONTROL op2 codes, op1==0, Crm==0.
+ */
+#define CpMainctl	0
+#define CpAuxctl	1
+#define CpCPaccess	2
+
+/*
+ * CpCONTROL: op1==0, CRm==0, op2==CpMainctl.
+ * main control register.
+ * cortex/armv7 has more ops and CRm values.
+ */
+#define CpCmmu		0x00000001	/* M: MMU enable */
+#define CpCalign	0x00000002	/* A: alignment fault enable */
+#define CpCdcache	0x00000004	/* C: data cache on */
+#define CpCsbo (3<<22|1<<18|1<<16|017<<3)	/* must be 1 (armv7) */
+#define CpCsbz (CpCtre|1<<26|CpCve|1<<15|7<<7)	/* must be 0 (armv7) */
+#define CpCsw		(1<<10)		/* SW: SWP(B) enable (deprecated in v7) */
+#define CpCpredict	0x00000800	/* Z: branch prediction (armv7) */
+#define CpCicache	0x00001000	/* I: instruction cache on */
+#define CpChv		0x00002000	/* V: high vectors */
+#define CpCrr		(1<<14)	/* RR: round robin vs random cache replacement */
+#define CpCha		(1<<17)		/* HA: hw access flag enable */
+#define CpCdz		(1<<19)		/* DZ: divide by zero fault enable */
+#define CpCfi		(1<<21)		/* FI: fast intrs */
+#define CpCve		(1<<24)		/* VE: intr vectors enable */
+#define CpCee		(1<<25)		/* EE: exception endianness */
+#define CpCnmfi		(1<<27)		/* NMFI: non-maskable fast intrs. */
+#define CpCtre		(1<<28)		/* TRE: TEX remap enable */
+#define CpCafe		(1<<29)		/* AFE: access flag (ttb) enable */
+
+/*
+ * CpCONTROL: op1==0, CRm==0, op2==CpAuxctl.
+ * Auxiliary control register on cortex at least.
+ */
+#define CpACcachenopipe		(1<<20)	/* don't pipeline cache maint. */
+#define CpACcp15serial		(1<<18)	/* serialise CP1[45] ops. */
+#define CpACcp15waitidle	(1<<17)	/* CP1[45] wait-on-idle */
+#define CpACcp15pipeflush	(1<<16)	/* CP1[45] flush pipeline */
+#define CpACneonissue1		(1<<12)	/* neon single issue */
+#define CpACldstissue1		(1<<11)	/* force single issue ld, st */
+#define CpACissue1		(1<<10)	/* force single issue */
+#define CpACnobsm		(1<<7)	/* no branch size mispredicts */
+#define CpACibe			(1<<6)	/* cp15 invalidate & btb enable */
+#define CpACl1neon		(1<<5)	/* cache neon (FP) data in L1 cache */
+#define CpACasa			(1<<4)	/* enable speculative accesses */
+#define CpACl1pe		(1<<3)	/* l1 cache parity enable */
+#define CpACl2en		(1<<1)	/* l2 cache enable; default 1 */
+/*
+ * CpCONTROL Secondary (CRm) registers and opcode2 fields.
+ */
+#define CpCONTROLscr	1
+
+#define CpSCRscr	0
+
+/*
+ * CpCACHE Secondary (CRm) registers and opcode2 fields.  op1==0.
+ * In ARM-speak, 'flush' means invalidate and 'clean' means writeback.
+ */
+#define CpCACHEintr	0			/* interrupt (op2==4) */
+#define CpCACHEisi	1			/* inner-sharable I cache (v7) */
+#define CpCACHEpaddr	4			/* 0: phys. addr (cortex) */
+#define CpCACHEinvi	5			/* instruction, branch table */
+#define CpCACHEinvd	6			/* data or unified */
+// #define CpCACHEinvu	7			/* unified (not on cortex) */
+#define CpCACHEva2pa	8			/* va -> pa translation (cortex) */
+#define CpCACHEwb	10			/* writeback */
+#define CpCACHEinvdse	11			/* data or unified by mva */
+#define CpCACHEwbi	14			/* writeback+invalidate */
+
+#define CpCACHEall	0			/* entire (not for invd nor wb(i) on cortex) */
+#define CpCACHEse	1			/* single entry */
+#define CpCACHEsi	2			/* set/index (set/way) */
+#define CpCACHEtest	3			/* test loop */
+#define CpCACHEwait	4			/* wait (prefetch flush on cortex) */
+#define CpCACHEdmbarr	5			/* wb only (cortex) */
+#define CpCACHEflushbtc	6			/* flush branch-target cache (cortex) */
+#define CpCACHEflushbtse 7			/* ⋯ or just one entry in it (cortex) */
+
+/*
+ * CpTLB Secondary (CRm) registers and opcode2 fields.
+ */
+#define CpTLBinvi	5			/* instruction */
+#define CpTLBinvd	6			/* data */
+#define CpTLBinvu	7			/* unified */
+
+#define CpTLBinv	0			/* invalidate all */
+#define CpTLBinvse	1			/* invalidate single entry */
+#define CpTBLasid	2			/* by ASID (cortex) */
+
+/*
+ * CpCLD Secondary (CRm) registers and opcode2 fields for op1==0. (cortex)
+ */
+#define CpCLDena	12			/* enables */
+#define CpCLDcyc	13			/* cycle counter */
+#define CpCLDuser	14			/* user enable */
+
+#define CpCLDenapmnc	0
+#define CpCLDenacyc	1
+
+/*
+ * CpCLD Secondary (CRm) registers and opcode2 fields for op1==1.
+ */
+#define CpCLDl2		0			/* l2 cache */
+
+#define CpCLDl2aux	2			/* auxiliary control */
+
+/*
+ * l2 cache aux. control
+ */
+#define CpCl2ecc	(1<<28)			/* use ecc, not parity */
+#define CpCl2noldforw	(1<<27)			/* no ld forwarding */
+#define CpCl2nowrcomb	(1<<25)			/* no write combining */
+#define CpCl2nowralldel	(1<<24)			/* no write allocate delay */
+#define CpCl2nowrallcomb (1<<23)		/* no write allocate combine */
+#define CpCl2nowralloc	(1<<22)			/* no write allocate */
+#define CpCl2eccparity	(1<<21)			/* enable ecc or parity */
+#define CpCl2inner	(1<<16)			/* inner cacheability */
+/* other bits are tag ram & data ram latencies */
+
+/*
+ * CpTLD Secondary (CRm) registers and opcode2 fields.
+ */
+#define CpTLDlock	0			/* TLB lockdown registers */
+#define CpTLDpreload	1			/* TLB preload */
+
+#define CpTLDi		0			/* TLB instr. lockdown reg. */
+#define CpTLDd		1			/* " data " " */
+
+/*
+ * CpVECS Secondary (CRm) registers and opcode2 fields.
+ */
+#define CpVECSbase	0
+
+#define CpVECSnorm	0			/* (non-)secure base addr */
+#define CpVECSmon	1			/* secure monitor base addr */
+
+/*
+ * MMU page table entries.
+ */
+#define Fault		0x00000000		/* L[12] pte: unmapped */
+
+#define Coarse		(1)			/* L1 */
+#define Section		(2)			/* L1 1MB */
+#define Fine		(3)			/* L1 */
+
+#define Large		0x00000001		/* L2 64KB */
+#define Small		0x00000002		/* L2 4KB */
+#define Tiny		0x00000003		/* L2 1KB: not in v7 */
+#define Buffered	0x00000004		/* L[12]: write-back not -thru */
+#define Cached		0x00000008		/* L[12] */
+#define ExecuteNever	(1<<4)
+
+#define Noaccess	0			/* AP, DAC */
+#define Krw		1			/* AP */
+/* armv7 deprecates AP[2] == 1 & AP[1:0] == 2 (Uro), prefers 3 (new in v7) */
+#define Uro		2			/* AP */
+#define Urw		3			/* AP */
+#define Client		1			/* DAC */
+#define Manager		3			/* DAC */
+
+#define AP(n, v)	F((v), ((n)*2)+4, 2)
+#define L1AP(ap)	(AP(3, (ap)))
+#define L2AP(ap)	(AP(0, (ap)))		/* armv7 */
+#define DAC(n, v)	F((v), (n)*2, 2)
+
+#define HVECTORS	0xffff0000
+#define PTEDRAM		(L1AP(Krw)|Section|Cached|Buffered)
+#define PTEIO		(ExecuteNever)
--- /dev/null
+++ b/sys/src/9/omap4/arm.s
@@ -1,0 +1,31 @@
+#include "arm.h"
+
+/* arm v7 arch defines these */
+#define WFI	WORD	$0xe320f003	/* wait for interrupt */
+#define DMB	WORD	$0xf57ff05f	/* data mem. barrier; last f = SY */
+#define DSB	WORD	$0xf57ff04f	/* data synch. barrier; last f = SY */
+#define ISB	WORD	$0xf57ff06f	/* instr. sync. barrier; last f = SY */
+#define NOOP	WORD	$0xe320f000
+#define CLZ(s, d) WORD	$(0xe16f0f10 | (d) << 12 | (s))	/* count leading 0s */
+#define CPSIE	WORD	$0xf1080080	/* intr enable: zeroes I bit */
+#define CPSID	WORD	$0xf10c0080	/* intr disable: sets I bit */
+
+#define EWAVE(n)\
+	MOVW	$0x48020000, R0; \
+	MOVW	$n, R1; \
+	MOVW	R1, (R0);
+
+#define WAVE(n)\
+	MOVW	$0xE0000000, R0; \
+	MOVW	$n, R1; \
+	MOVW	R1, (R0);
+
+#define	LDREX(a,r)	WORD	$(0xe<<28|0x01900f9f | (a)<<16 | (r)<<12)
+#define	STREX(a,v,r)	WORD	$(0xe<<28|0x01800f90 | (a)<<16 | (r)<<12 | (v)<<0)
+#define CLREX		WORD	$0xf57ff01f
+
+#define BARRIERS\
+	MOVW	$0, R11; \
+	MCR	CpSC, 0, R11, C(CpCACHE), C(CpCACHEinvi), CpCACHEflushbtc; \
+	DSB; \
+	ISB;
--- /dev/null
+++ b/sys/src/9/omap4/clock.c
@@ -1,0 +1,117 @@
+#include "u.h"
+#include "ureg.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+extern uchar *periph;
+ulong *global, *local;
+enum { PERIPHCLK = 506965000 } ;
+
+void
+globalclockinit(void)
+{
+	global = (ulong*) (periph + 0x200);
+	local = (ulong*) (periph + 0x600);
+	global[2] &= 0xFFFF00F0;
+	global[0] = 0;
+	global[1] = 0;
+	global[2] |= 1;
+}
+
+void
+cycles(uvlong *x)
+{
+	ulong hi, newhi, lo, *y;
+	
+	newhi = global[1];
+	do{
+		hi = newhi;
+		lo = global[0];
+	}while((newhi = global[1]) != hi);
+	y = (ulong *) x;
+	y[0] = lo;
+	y[1] = hi;
+}
+
+uvlong
+fastticks(uvlong *hz)
+{
+	uvlong ret;
+
+	if(hz != nil)
+		*hz = PERIPHCLK;
+	cycles(&ret);
+	return ret;
+}
+
+ulong
+µs(void)
+{
+	return fastticks2us(fastticks(nil));
+}
+
+
+ulong
+perfticks(void)
+{
+	return global[0];
+}
+
+void
+clocktick(Ureg* ureg)
+{
+	extern void _dumpstack(ulong, ulong);
+	static int n;
+
+//	if(++n % 128 == 0 && up && up->pid == 1)
+//		_dumpstack(ureg->sp, ureg->pc);
+	timerintr(ureg, 0);
+}
+
+void
+localclockinit(void)
+{
+	local[2] = 0xFF07;
+	intenable(29, clocktick);
+}
+
+void
+timerset(uvlong val)
+{
+	uvlong now, ticks;
+	
+	cycles(&now);
+	ticks = (val - now) * (PERIPHCLK / 256) / 1000000000;
+	if(ticks == 0)
+		ticks++;
+	local[2] &= ~1;
+	local[0] = local[1] = ticks;
+	local[2] |= 1;
+}
+
+static void
+waituntil(uvlong n)
+{
+	uvlong now, then;
+	
+	cycles(&now);
+	then = now + n;
+	while(now < then)
+		cycles(&now);
+}
+
+void
+microdelay(int n)
+{
+	waituntil(((uvlong)n) * PERIPHCLK / 1000000);
+}
+
+void
+delay(int n)
+{
+	waituntil(((uvlong)n) * PERIPHCLK / 1000);
+}
+
--- /dev/null
+++ b/sys/src/9/omap4/dat.h
@@ -1,0 +1,144 @@
+typedef struct Lock Lock;
+typedef struct Label Label;
+typedef struct Ureg Ureg;
+typedef struct Mach Mach;
+typedef struct FPsave FPsave;
+typedef struct Notsave Notsave;
+typedef struct PMMU PMMU;
+typedef struct Confmem Confmem;
+typedef struct Conf Conf;
+typedef struct Proc Proc;
+typedef uvlong Tval;
+typedef void KMap;
+#define	VA(k)		((uintptr)(k))
+#define	kmap(p)		(KMap*)((p)->pa|kseg0)
+#define	kunmap(k)
+
+#pragma incomplete Ureg
+
+struct Lock
+{
+	ulong	key;
+	u32int	sr;
+	uintptr	pc;
+	Proc*	p;
+	Mach*	m;
+	int	isilock;
+};
+
+struct Label
+{
+	ulong sp;
+	ulong pc;
+};
+
+struct FPsave
+{
+	ulong status;
+	ulong control;
+	ulong regs[8][3];
+	int fpstate;
+};
+
+enum
+{
+	FPinit,
+	FPactive,
+	FPinactive,
+};
+
+struct Notsave
+{
+	int emptiness;
+};
+
+struct PMMU
+{
+	ulong l1[USTKTOP / MiB];
+};
+
+#include "../port/portdat.h"
+
+struct Mach
+{
+	int	machno;			/* physical id of processor */
+	uintptr	splpc;			/* pc of last caller to splhi */
+
+	Proc*	proc;			/* current process */
+	Proc*	externup;
+
+	int	flushmmu;		/* flush current proc mmu state */
+
+	ulong	ticks;			/* of the clock since boot time */
+	Label	sched;			/* scheduler wakeup */
+	Lock	alarmlock;		/* access to alarm list */
+	void*	alarm;			/* alarms bound to this clock */
+	int	inclockintr;
+
+	Proc*	readied;		/* for runproc */
+	ulong	schedticks;		/* next forced context switch */
+
+	int	cputype;
+	ulong	delayloop;
+
+	/* stats */
+	int	tlbfault;
+	int	tlbpurge;
+	int	pfault;
+	int	cs;
+	int	syscall;
+	int	load;
+	int	intr;
+	uvlong	fastclock;		/* last sampled value */
+	uvlong	inidle;			/* time spent in idlehands() */
+	ulong	spuriousintr;
+	int	lastintr;
+	int	ilockdepth;
+	Perf	perf;
+	uvlong	cyclefreq;		/* Frequency of user readable cycle counter */
+
+};
+
+struct Confmem
+{
+	uintptr	base;
+	usize	npage;
+	uintptr	limit;
+	uintptr	kbase;
+	uintptr	klimit;
+};
+
+struct Conf
+{
+	ulong	nmach;		/* processors */
+	ulong	nproc;		/* processes */
+	Confmem	mem[1];		/* physical memory */
+	ulong	npage;		/* total physical pages of memory */
+	usize	upages;		/* user page pool */
+	ulong	copymode;	/* 0 is copy on write, 1 is copy on reference */
+	ulong	ialloc;		/* max interrupt time allocation in bytes */
+	ulong	pipeqsize;	/* size in bytes of pipe queues */
+	ulong	nimage;		/* number of page cache image headers */
+	ulong	nswap;		/* number of swap pages */
+	int	nswppo;		/* max # of pageouts per segment pass */
+	ulong	hz;		/* processor cycle freq */
+	ulong	mhz;
+	int	monitor;	/* flag */
+};
+
+struct
+{
+	Lock;
+	int	machs;			/* bitmap of active CPUs */
+	int	exiting;		/* shutdown */
+	int	ispanic;		/* shutdown in response to a panic */
+}active;
+
+extern Mach *m;
+#define up (((Mach*)MACHADDR)->externup)
+extern Mach* machaddr[MAXMACH];
+#define MACHP(n)	(machaddr[n])
+extern uintptr kseg0;
+
+#define AOUT_MAGIC (E_MAGIC)
+#define NCOLOR 1
--- /dev/null
+++ b/sys/src/9/omap4/fns.h
@@ -1,0 +1,34 @@
+#include "../port/portfns.h"
+
+#define	waserror()	(up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
+#define getpgcolor(x)	0
+#define kmapinval()
+#define checkmmu(a,b)
+
+extern void procsave(Proc *);
+extern void procrestore(Proc *);
+extern void idlehands(void);
+extern void coherence(void);
+extern int tas(void*);
+extern int cmpswap(long*, long, long);
+extern void evenaddr(uintptr);
+extern void procsetup(Proc*);
+extern void procfork(Proc*);
+extern uintptr cankaddr(uintptr);
+extern void* KADDR(ulong);
+extern ulong paddr(void *);
+extern void cycles(uvlong *);
+#define PADDR(x) paddr((void*)(x))
+
+void	mmuinit(void);
+void	flushtlb(void);
+void	trapinit(void);
+void*	vmap(ulong, ulong);
+void	vunmap(void*, ulong);
+void	printureg(Ureg*);
+void	fillureguser(Ureg*);
+void	touser(Ureg*);
+void	links(void);
+void	globalclockinit(void);
+void	localclockinit(void);
+void	intenable(int, void(*)(Ureg*));
--- /dev/null
+++ b/sys/src/9/omap4/init9.s
@@ -1,0 +1,25 @@
+/*
+ * This is the same as the C programme:
+ *
+ *	void
+ *	main(char* argv0)
+ *	{
+ *		startboot(argv0, &argv0);
+ *	}
+ *
+ * It is in assembler because SB needs to be
+ * set and doing this in C drags in too many
+ * other routines.
+ */
+TEXT main(SB), 1, $8
+	MOVW	$setR12(SB), R12		/* load the SB */
+	MOVW	$boot(SB), R0
+
+	ADD	$12, R13, R1			/* pointer to 0(FP) */
+
+	MOVW	R0, 4(R13)			/* pass argc, argv */
+	MOVW	R1, 8(R13)
+
+	BL	startboot(SB)
+_loop:
+	B	_loop
--- /dev/null
+++ b/sys/src/9/omap4/l.s
@@ -1,0 +1,298 @@
+#include "arm.s"
+#include "mem.h"
+
+TEXT _start(SB), 1, $-4
+	MOVW	$setR12(SB), R12
+	ADD	$(PHYSDRAM - KZERO), R12
+	
+	MOVW	$(PsrDirq | PsrDfiq | PsrMsvc), CPSR
+	
+	MOVW	$0x48020014, R1
+uartloop:
+	MOVW	(R1), R0
+	AND.S	$(1<<6), R0
+	B.EQ	uartloop
+	
+	EWAVE('\r')
+	EWAVE('\n')
+	
+	MRC	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
+	BIC	$(CpCmmu), R1
+	MCR	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
+
+	EWAVE('P')
+	
+	MOVW	$KZERO, R1
+	MOVW	$(PHYSDRAM|PTEDRAM), R2
+	MOVW	$256, R3
+	BL	_mapmbs(SB)
+	MOVW	$PHYSDRAM, R1
+	MOVW	$(PHYSDRAM|PTEDRAM), R2
+	MOVW	$256, R3
+	BL	_mapmbs(SB)
+	MOVW	$0x48000000, R1
+	MOVW	$(0x48000000| L1AP(Krw) | Section | PTEIO), R2
+	MOVW	$1, R3
+	BL	_mapmbs(SB)
+	
+	EWAVE('l')
+	
+	MOVW	$L1PT, R1
+	MCR	CpSC, 0, R1, C(CpTTB), C(0), CpTTB0
+	MCR	CpSC, 0, R1, C(CpTTB), C(0), CpTTB1
+
+	EWAVE('a')
+
+	MOVW	$Client, R1
+	MCR	CpSC, 0, R1, C(CpDAC), C(0)
+	MOVW	$0, R1
+	MCR	CpSC, 0, R1, C(CpPID), C(0x0)
+
+	EWAVE('n')
+
+	MRC	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
+	ORR	$(CpCmmu|CpChv|CpCsw), R1
+	MCR	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
+
+	EWAVE(' ')
+		
+	BL	_jumphi(SB)
+	
+	EWAVE('9')
+	
+	MOVW	$setR12(SB), R12
+	MOVW	$KTZERO, R13
+	
+	EWAVE(' ')
+	
+	BL	main(SB)
+a:
+	WFI
+	B a
+	BL	_div(SB) /* hack */
+
+/* R1: virtual start, R2: physical start, R3: number of MB */
+TEXT _mapmbs(SB), 1, $-4
+	MOVW	$L1PT, R11
+	ADD	R1>>18, R11, R1
+mapmbsl:
+	MOVW.P	R2, 4(R1)	
+	ADD	$MiB, R2
+	SUB.S	$1, R3
+	B.NE	mapmbsl
+	MOVW	R14, PC
+
+TEXT _jumphi(SB), 1, $-4
+	ADD	$(KZERO - PHYSDRAM), R14
+	MOVW	R14, PC
+
+TEXT coherence(SB), 1, $-4
+	BARRIERS
+	RET
+
+TEXT splhi(SB), 1, $-4
+	MOVW	CPSR, R0
+	CPSID
+	MOVW	$(MACHADDR + 4), R11
+	MOVW	R14, (R11)
+	RET
+
+TEXT spllo(SB), 1, $-4
+	MOVW	CPSR, R0
+	CPSIE
+	RET
+
+TEXT splx(SB), 1, $-4
+	MOVW	CPSR, R1
+	MOVW	R0, CPSR
+	MOVW	R1, R0
+	RET
+
+TEXT islo(SB), 1, $-4
+	MOVW	CPSR, R0
+	AND	$PsrDirq, R0
+	EOR	$PsrDirq, R0
+	RET
+
+TEXT tas(SB), $-4
+spintas:
+	LDREX(0,1)
+	CMP.S	$0, R1
+	B.NE	tasnope
+	MOVW	$1, R3
+	STREX(0,3,2)
+	CMP.S	$0, R2
+	B.NE	spintas
+tasnope:
+	CLREX
+	MOVW	R1, R0
+	RET
+
+TEXT cmpswap(SB), $-4
+	MOVW	4(FP), R3
+	MOVW	8(FP), R4
+casspin:
+	LDREX(0,1)
+	CMP.S	R3, R1
+	B.NE	casfail
+	STREX(0,1,2)
+	CMP.S	$0, R2
+	B.NE	casspin
+	MOVW	$1, R0
+	RET
+casfail:
+	CLREX
+	MOVW	$0, R0
+	RET
+
+TEXT ainc(SB), $-4
+TEXT _xinc(SB), $-4
+spinainc:
+	LDREX(0,1)
+	ADD	$1, R1
+	STREX(0,1,2)
+	CMP.S	$0, R2
+	B.NE	spinainc
+	MOVW	R1, R0
+	RET
+
+TEXT adec(SB), $-4
+TEXT _xdec(SB), $-4
+spinadec:
+	LDREX(0,1)
+	SUB	$1, R1
+	STREX(0,1,2)
+	CMP.S	$0, R2
+	B.NE	spinadec
+	MOVW	R1, R0
+	RET
+
+TEXT setlabel(SB), 1, $-4
+	MOVW	R13, 0(R0)
+	MOVW	R14, 4(R0)
+	MOVW	$0, R0
+	RET
+
+TEXT gotolabel(SB), 1, $-4
+	MOVW	0(R0), R13
+	MOVW	4(R0), R14
+	MOVW	$1, R0
+	RET
+
+TEXT idlehands(SB), 1, $-4
+	BARRIERS
+	WFI
+	RET
+
+TEXT flushtlb(SB), $-4
+	BARRIERS
+	MCR	CpSC, 0, R1, C(8), C(7), 0
+	RET
+
+#define TRAP(n,a)\
+	SUB	$n, R14;\
+	WORD	$0xf96d0513;\
+	WORD	$0xf10e0093;\
+	MOVW	R14, -8(R13);\
+	MOVW	$a, R14;\
+	MOVW	R14, -4(R13);\
+	B _trap(SB)
+
+TEXT _reset(SB), 1, $-4
+	TRAP(4, 0)
+TEXT _undefined(SB), 1, $-4
+	TRAP(4, 1)
+TEXT _prefabort(SB), 1, $-4
+	TRAP(4, 3)
+TEXT _dataabort(SB), 1, $-4
+	TRAP(8, 4)
+TEXT _wtftrap(SB), 1, $-4
+	TRAP(4, 5)
+TEXT _irq(SB), 1, $-4
+	TRAP(4, 6)
+TEXT _fiq(SB), 1, $-4
+	TRAP(4, 7)
+
+TEXT _trap(SB), 1, $-4
+	SUB	$64, R13
+	MOVM.IA	[R0-R12], (R13)
+	MOVW	$setR12(SB), R12
+	MOVW	64(R13), R0
+	MOVW	68(R13), R1
+	MOVW	R0, 68(R13)
+	MOVW	R1, 64(R13)
+	ADD	$72, R13, R0
+	MOVW	R0, 52(R13)
+	MOVW	R13, R0
+	SUB	$8, R13
+	BL trap(SB)
+	ADD	$8, R13
+	MOVW	64(R13), R0
+	AND	$PsrMask, R0
+	CMP	$PsrMusr, R0
+	MOVW.EQ	R13, R0
+	B.EQ	gotouser
+	MOVW	68(R13), R0
+	MOVW	R0, 60(R13)
+	MOVW	64(R13), R0
+	MOVW	R0, SPSR
+	MOVW	R13, R0
+	ADD	$72, R13
+	WORD	$0xE8D0FFFF
+
+TEXT _syscall(SB), 1, $-4
+	WORD	$0xf96d0513
+	WORD	$0xf10e0093
+	SUB	$64, R13
+	MOVM.IA.S	[R0-R14], (R13)
+	MOVW	$setR12(SB), R12
+	MOVW	64(R13), R0
+	MOVW	68(R13), R1
+	MOVW	R0, 68(R13)
+	MOVW	R1, 64(R13)
+	MOVW	R13, R0
+	SUB	$8, R13
+	BL	syscall(SB)
+
+TEXT forkret(SB), 1, $-4
+	ADD	$8, R13
+	MOVW	R13, R0
+
+TEXT touser(SB), 1, $-4
+gotouser:
+	ADD	$52, R0
+	MOVM.IA.S	(R0), [R13-R14]
+	SUB	$52, R0
+	MOVW	68(R0), R1
+	MOVW	R1, 52(R0)
+	MOVW	64(R0), R1
+	MOVW	R1, SPSR
+	WORD	$0xE8D09FFF
+
+TEXT fillureguser(SB), $-4
+	ADD	$52, R0
+	MOVM.IA.S	[R13-R14], (R0)
+	RET
+
+
+TEXT dumpstack(SB), 0, $8
+	MOVW	R14, 8(R13)
+	ADD	$12, R13, R0
+	BL	_dumpstack(SB)
+	RET
+
+TEXT getdfsr(SB), 0, $-4
+	MRC	CpSC, 0, R0, C(5), C(0), 0
+	RET
+
+TEXT getifsr(SB), 0, $-4
+	MRC	CpSC, 0, R0, C(5), C(0), 1
+	RET
+
+TEXT getdfar(SB), 0, $-4
+	MRC	CpSC, 0, R0, C(6), C(0), 0
+	RET
+
+TEXT getifar(SB), 0, $-4
+	MRC	CpSC, 0, R0, C(6), C(0), 2
+	RET
--- /dev/null
+++ b/sys/src/9/omap4/main.c
@@ -1,0 +1,194 @@
+#include "u.h"
+#include "ureg.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "init.h"
+#include "tos.h"
+#include "arm.h"
+
+ulong *uart = (ulong *) 0x48020000;
+#define wave(x) (*uart = (char) (x))
+uintptr kseg0 = KZERO;
+uchar *sp;
+
+Mach *m;
+Mach *machaddr[MAXMACH];
+Conf conf;
+
+void
+machinit(void)
+{
+	machaddr[0] = m = KADDR(FIRSTMACH);
+	memset(m, 0, sizeof(Mach));
+	active.machs = conf.nmach = 1;
+	active.exiting = 0;
+	up = nil;
+
+	conf.mem[0].base = ROUNDUP(PADDR(end), BY2PG);
+	conf.mem[0].limit = ROUNDDN(PHYSDRAM + DRAMSIZ, BY2PG);
+	conf.mem[0].npage = (conf.mem[0].limit - conf.mem[0].base) / BY2PG;
+	conf.npage = conf.mem[0].npage;
+	conf.upages = conf.npage - 64 * MiB / BY2PG;
+	conf.nproc = 100;
+	conf.pipeqsize = 32768;
+	conf.nimage = 200;
+}
+
+void
+init0(void)
+{
+	Ureg ureg;
+
+	spllo();
+	up->nerrlab = 0;
+	up->slash = namec("#/", Atodir, 0, 0);
+	pathclose(up->slash->path);
+	up->slash->path = newpath("/");
+	up->dot = cclone(up->slash);
+	chandevinit();
+	if(!waserror()){
+		ksetenv("terminal", "generic /sys/src/9/omap4/panda", 0);
+		ksetenv("cputype", "arm", 0);
+		ksetenv("service", "cpu", 0);
+		poperror();
+	}
+	kproc("alarm", alarmkproc, 0);
+	memset(&ureg, 0, sizeof ureg);
+	ureg.pc = UTZERO + 32;
+	ureg.r13 = (ulong) sp;
+	ureg.psr = PsrMusr;
+	touser(&ureg);
+}
+
+static uchar *
+pusharg(char *p)
+{
+	int n;
+	
+	n = strlen(p) + 1;
+	sp -= n;
+	memmove(sp, p, n);
+	return sp;
+}
+
+static void
+bootargs(void *base)
+{
+	int ac, i;
+	uchar *av[32], **lsp;
+	sp = (uchar*)base + BY2PG - sizeof(Tos);
+
+	ac = 0;
+	av[ac++] = pusharg("boot");
+	sp = (uchar *) ROUNDDN((ulong)sp, 4);
+	sp -= (ac + 1) * 4;
+	lsp = (uchar **) sp;
+	for(i = 0; i < ac; i++)
+		lsp[i] = av[i] + ((USTKTOP - BY2PG) - (ulong) base);
+	lsp[i] = 0;
+	sp += (USTKTOP - BY2PG) - (ulong)base;
+	sp -= BY2WD;
+}
+
+void
+userinit(void)
+{
+	Proc *p;
+	Segment *s;
+	Page *pg;
+	void *v;
+	
+	p = newproc();
+	p->pgrp = newpgrp();
+	p->egrp = smalloc(sizeof(Egrp));
+	p->egrp->ref = 1;
+	p->fgrp = dupfgrp(nil);
+	p->rgrp = newrgrp();
+	p->procmode = 0640;
+	
+	kstrdup(&eve, "");
+	kstrdup(&p->text, "*init*");
+	kstrdup(&p->user, eve);
+	
+	procsetup(p);
+	
+	p->sched.pc = (ulong)init0;
+	p->sched.sp = (ulong)p->kstack + KSTACK - sizeof(Sargs) - BY2WD;
+	
+	s = newseg(SG_STACK, USTKTOP - USTKSIZE, USTKSIZE / BY2PG);
+	p->seg[SSEG] = s;
+	pg = newpage(0, 0, USTKTOP - BY2PG);
+	v = vmap(pg->pa, BY2PG);
+	memset(v, 0, BY2PG);
+	segpage(s, pg);
+	bootargs(v);
+	vunmap(v, BY2PG);
+	
+	s = newseg(SG_TEXT, UTZERO, 1);
+	s->flushme++;
+	p->seg[TSEG] = s;
+	pg = newpage(0, 0, UTZERO);
+	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
+	segpage(s, pg);
+	v = vmap(pg->pa, BY2PG);
+	memset(v, 0, BY2PG);
+	memmove(v, initcode, sizeof initcode);
+	vunmap(v, BY2PG);
+	
+	ready(p);
+}
+
+void
+main()
+{
+	extern int chandebug;
+
+	wave('f');
+	memset(edata, 0, end - edata);
+	wave('r');
+	machinit();
+	wave('o');
+	mmuinit();
+	wave('m');
+	trapinit();
+	print(" Bell Labs\n");
+	xinit();
+	globalclockinit();
+	localclockinit();
+	timersinit();
+	procinit0();
+	pageinit();
+	swapinit();
+	initseg();
+	quotefmtinstall();
+	chandevreset();
+	links();
+	chandebug++;
+	userinit();
+	schedinit();
+}
+
+void
+exit(int)
+{
+	uartputs("resting\n", 9);
+	splhi();
+	while(1)
+		idlehands();
+}
+
+void
+reboot()
+{
+	exit(0);
+}
+
+void
+rdb()
+{
+	panic("rdb");
+}
+
--- /dev/null
+++ b/sys/src/9/omap4/mem.h
@@ -1,0 +1,65 @@
+#define KiB		1024u			/* Kibi 0x0000000000000400 */
+#define MiB		1048576u		/* Mebi 0x0000000000100000 */
+#define GiB		1073741824u		/* Gibi 000000000040000000 */
+
+#define HOWMANY(x, y)	(((x)+((y)-1))/(y))
+#define ROUNDUP(x, y)	(HOWMANY((x), (y))*(y))	/* ceiling */
+#define ROUNDDN(x, y)	(((x)/(y))*(y))		/* floor */
+#define MIN(a, b)	((a) < (b)? (a): (b))
+#define MAX(a, b)	((a) > (b)? (a): (b))
+#define	PGROUND(s)	ROUNDUP(s, BY2PG)
+#define	ROUND(s, sz)	(((s)+(sz-1))&~(sz-1))
+#define	PPN(x)		((x)&~(BY2PG-1))
+#define F(v, o, w)	(((v) & ((1<<(w))-1))<<(o))
+
+#define FMASK(o, w)	(((1<<(w))-1)<<(o))
+
+#define KZERO		0xF0000000
+#define KTZERO		0xF2000000
+#define VECTORS		0xFFFF0000
+#define MACHADDR	0xFFFF1000
+
+#define UZERO		0
+#define UTZERO		BY2PG
+#define USTKTOP		0xE0000000
+
+/* we map MMIO somewhere here */
+#define IZERO		0xE0000000
+#define NIOPAGES	ROUNDDN((KZERO - IZERO) / BY2PG, 256)
+
+#define KSTKSIZ		(16*KiB)
+#define KSTACK		KSTKSIZ
+#define TSTKSIZ		256
+#define USTKSIZE		(8*MiB)
+#define	TSTKTOP		(USTKTOP - USTKSIZE)
+#define HZ		100
+
+#define	MAXSYSARG	7
+#define MAXMACH		2
+
+#define BY2WD		4
+#define BY2V		8
+#define BY2PG		4096
+#define PGSHIFT		12
+#define	PTEMAPMEM	1048576
+#define	PTEPERTAB	(PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE	1984
+#define SSEGMAPSIZE	16
+#define BLOCKALIGN	32
+
+#define	PTEVALID	(1<<0)
+#define	PTERONLY	0
+#define	PTEWRITE	(1<<1)
+#define	PTEUNCACHED	(1<<2)
+#define PTEKERNEL	(1<<3)
+
+#define PHYSDRAM	0x80000000
+#define DRAMSIZ		(1024 * MiB)
+
+#define L1PT		PHYSDRAM
+#define L1SIZ		(16 * KiB)
+#define IOPT		(L1PT + L1SIZ)
+#define L2SIZ		(1 * KiB)
+#define PRIVL2		(IOPT + L2SIZ * (NIOPAGES / 256))
+#define PHYSVECTORS	ROUNDUP(PRIVL2 + L2SIZ, BY2PG)
+#define	FIRSTMACH	(PHYSVECTORS + BY2PG)
--- /dev/null
+++ b/sys/src/9/omap4/mkfile
@@ -1,0 +1,101 @@
+CONF=panda
+CONFLIST=panda
+
+loadaddr=0xF2000000
+
+objtype=arm
+</$objtype/mkfile
+p=9
+
+DEVS=`{rc ../port/mkdevlist $CONF}
+
+PORT=\
+	alarm.$O\
+	alloc.$O\
+	allocb.$O\
+	auth.$O\
+	cache.$O\
+	chan.$O\
+	dev.$O\
+	edf.$O\
+	fault.$O\
+	mul64fract.$O\
+	rebootcmd.$O\
+	page.$O\
+	parse.$O\
+	pgrp.$O\
+	portclock.$O\
+	print.$O\
+	proc.$O\
+	qio.$O\
+	qlock.$O\
+	segment.$O\
+	swap.$O\
+	sysfile.$O\
+	sysproc.$O\
+	taslock.$O\
+	tod.$O\
+	xalloc.$O\
+
+OBJ=\
+	l.$O\
+	main.$O\
+	mmu.$O\
+	random.$O\
+	clock.$O\
+	arch.$O\
+	uart.$O\
+	trap.$O\
+	$CONF.root.$O\
+	$CONF.rootc.$O\
+	$DEVS\
+	$PORT\
+
+LIB=\
+	/$objtype/lib/libmemlayer.a\
+	/$objtype/lib/libmemdraw.a\
+	/$objtype/lib/libdraw.a\
+	/$objtype/lib/libip.a\
+	/$objtype/lib/libsec.a\
+	/$objtype/lib/libmp.a\
+	/$objtype/lib/libc.a\
+
+9:V: $p$CONF s$p$CONF
+
+$p$CONF:DQ:	$CONF.c $OBJ $LIB mkfile
+	$CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
+	echo '# linking raw kernel'
+	$LD -o $target -H0 -P -R4096 -T$loadaddr -l $OBJ $CONF.$O $LIB
+
+s$p$CONF:DQ:	$CONF.$O $OBJ $LIB
+	echo '# linking kernel with symbols'
+#	$LD -o $target -R4096 -T$loadaddr -l -a $OBJ $CONF.$O $LIB >$target.list
+	$LD -o $target -R4096 -T$loadaddr -l $OBJ $CONF.$O $LIB
+	size $target
+
+$p$CONF.gz:D:	$p$CONF
+	gzip -9 <$p$CONF >$target
+
+$OBJ: $HFILES
+
+l.$O:	arm.s
+
+install:V: /$objtype/$p$CONF
+
+/$objtype/$p$CONF:D: $p$CONF s$p$CONF
+	cp $p$CONF s$p$CONF /$objtype
+
+<../boot/bootmkfile
+<../port/portmkfile
+<|../port/mkbootrules $CONF
+
+CFLAGS= -I. -I../port $CFLAGS	# hack to compile private sysproc.c (e.g.)
+
+init.h:D:	../port/initcode.c init9.s
+	$CC ../port/initcode.c
+	$AS init9.s
+	$LD -l -R1 -s -o init.out init9.$O initcode.$O /$objtype/lib/libc.a
+	{echo 'uchar initcode[]={'
+	 xd -1x <init.out |
+		sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
+	 echo '};'} > init.h
--- /dev/null
+++ b/sys/src/9/omap4/mmu.c
@@ -1,0 +1,237 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "arm.h"
+
+char iopages[NIOPAGES / 8];
+Lock iopagelock;
+uchar *periph;
+
+static int
+isfree(int i)
+{
+	return (iopages[i / 8] & (1 << (i % 8))) == 0;
+}
+
+static void
+freeio(int i)
+{
+	iopages[i / 8] &= ~(1 << (i % 8));
+}
+
+static int
+getiopages(int n)
+{
+	int i, j;
+
+	lock(&iopagelock);
+	for(i = 0; i <= NIOPAGES - n; i++){
+		for(j = 0; j < n; j++)
+			if(!isfree(i + j))
+				goto next;
+		for(j = 0; j < n; j++)
+			iopages[(i + j) / 8] |= (1 << ((i + j) % 8));
+		unlock(&iopagelock);
+		return i;
+	next: ;
+	}
+	panic("out of i/o pages");
+	return 0;
+}
+
+static void
+putiopages(int i, int n)
+{
+	lock(&iopagelock);
+	while(n--)
+		freeio(i++);
+	unlock(&iopagelock);
+}
+
+void *
+vmap(ulong phys, ulong length)
+{
+	ulong virt, off, *l2;
+
+	off = phys % BY2PG;
+	length = (ROUNDUP(phys + length, BY2PG) - ROUNDDN(phys, BY2PG)) / BY2PG;
+	if(length == 0)
+		return nil;
+	phys = ROUNDDN(phys, BY2PG);
+	virt = getiopages(length);
+	l2 = KADDR(IOPT);
+	l2 += virt;
+	while(length--){
+		*l2++ = phys | L2AP(Krw) | Small | PTEIO;
+		phys += BY2PG;
+	}
+	flushtlb();
+	return (void *) (IZERO + BY2PG * virt + off);
+}
+
+void
+vunmap(void *virt, ulong length)
+{
+	ulong v, *l2;
+	
+	if((ulong)virt < IZERO || (ulong)virt >= IZERO + NIOPAGES * BY2PG)
+		panic("vunmap: virt=%p", virt);
+	v = (ROUNDDN((ulong) virt, BY2PG) - IZERO) / BY2PG;
+	length = (ROUNDUP(((ulong) virt) + length, BY2PG) - ROUNDDN((ulong) virt, BY2PG)) / BY2PG;
+	if(length == 0)
+		return;
+	l2 = KADDR(IOPT);
+	l2 += v;
+	lock(&iopagelock);
+	while(length--){
+		*l2++ = 0;
+		freeio(v++);
+	}
+	unlock(&iopagelock);
+	flushtlb();
+}
+
+void
+mmuinit(void)
+{
+	ulong *l1, l2, *pl2;
+	int i, n;
+	extern ulong *uart;
+
+	l1 = KADDR(L1PT);
+	l2 = IOPT;
+	n = NIOPAGES / 256;
+	memset(KADDR(l2), 0, n * L2SIZ);
+	for(i = 0; i < n; i++){
+		l1[(IZERO / MiB) + i] = l2 | Coarse;
+		l2 += L2SIZ;
+	}
+	uart = vmap((ulong) uart, BY2PG);
+	memset(l1, 0, sizeof(ulong) * (IZERO / MiB));
+	l1[4095] = PRIVL2 | Coarse;
+	pl2 = KADDR(PRIVL2);
+	for(i = 0; i < 240; i++)
+		pl2[i] = (0x8FF00000 + i * BY2PG) | L2AP(Krw) | Small | Cached | Buffered;
+	pl2[240] = PHYSVECTORS | L2AP(Krw) | Small | Cached | Buffered;
+	pl2[241] = FIRSTMACH | L2AP(Krw) | Small | Cached | Buffered;
+	flushtlb();
+	m = (Mach *) MACHADDR;
+	periph = vmap(0x48240000, 2 * BY2PG);
+}
+
+void
+mmuswitch(Proc *p)
+{
+	ulong *l1;
+	
+	l1 = KADDR(L1PT);
+	memmove(l1, p->l1, sizeof p->l1);
+	flushtlb();
+}
+
+void
+putmmu(ulong va, ulong pa, Page *)
+{
+	ulong *l1a, *l1b, *l2;
+	int l1o, l2o;
+	
+	l1o = va / MiB;
+	l2o = (va % MiB) / BY2PG;
+	l1a = KADDR(L1PT);
+	l1b = up->l1;
+	if(l1a[l1o] == 0){
+		if((pa & PTEVALID) == 0)
+			return;
+		l2 = xspanalloc(L2SIZ, L2SIZ, 0);
+		l1a[l1o] = l1b[l1o] = PADDR(l2) | Coarse;
+	} else
+		l2 = KADDR(ROUNDDN(l1a[l1o], L2SIZ));
+	l2 += l2o;
+	if((pa & PTEVALID) == 0){
+		*l2 = 0;
+		flushtlb();
+		return;
+	}
+	*l2 = ROUNDDN(pa, BY2PG) | Small;
+	if((pa & PTEWRITE) == 0)
+		*l2 |= L2AP(Uro);
+	else
+		*l2 |= L2AP(Urw);
+	if((pa & PTEUNCACHED) == 0)
+		*l2 |= Buffered | Cached;
+	flushtlb();
+}
+
+void
+flushmmu(void)
+{
+	int s, i;
+	ulong p;
+	ulong *l1;
+
+	l1 = KADDR(L1PT);
+	s = splhi();
+	for(i = 0; i < nelem(up->l1); i++){
+		p = l1[i];
+		if(p & Small)
+			free(KADDR(ROUNDDN(p, BY2PG)));
+	}
+	memset(up->l1, 0, sizeof up->l1);
+	memset(l1, 0, sizeof up->l1);
+	flushtlb();
+	splx(s);
+}
+
+void
+mmurelease(Proc *p)
+{
+	int i;
+	ulong pg;
+
+	if(p == up){
+		flushmmu();
+		return;
+	}
+	for(i = 0; i < nelem(p->l1); i++){
+		pg = p->l1[i];
+		if(pg & Small)
+			free(KADDR(ROUNDDN(pg, BY2PG)));
+	}
+	memset(p->l1, 0, sizeof p->l1);
+}
+
+void
+countpagerefs()
+{
+	panic("countpagerefs");
+}
+
+void*
+KADDR(ulong pa)
+{
+	if(pa < (ulong)PHYSDRAM || pa > (ulong)(PHYSDRAM + VECTORS - KZERO))
+		panic("kaddr: pa=%#.8lux, pc=%p", pa, getcallerpc(&pa));
+	return (void*)(pa + KZERO - PHYSDRAM);
+}
+
+ulong
+paddr(void* v)
+{
+	ulong va;
+	
+	va = (ulong) v;
+	if(va < KZERO)
+		panic("paddr: v=%p", v);
+	return va - KZERO + PHYSDRAM;
+}
+
+ulong
+cankaddr(ulong arg)
+{
+	if(arg < PHYSDRAM || arg > (ulong)(PHYSDRAM + VECTORS - KZERO))
+		return 0;
+	return PHYSDRAM - KZERO - arg;
+}
--- /dev/null
+++ b/sys/src/9/omap4/panda
@@ -1,0 +1,78 @@
+# panda board
+dev
+	root
+	cons
+	env
+	pipe
+#	proc
+	mnt
+	srv
+	shr
+#	dup
+#	arch
+#	ssl
+#	tls
+#	bridge		log
+#	sdp		thwack unthwack
+#	cap
+#	kprof
+#	aoe
+#	sd
+#	fs
+#	flash
+
+#	ether		netif
+#	ip		arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno
+
+#	draw		screen
+#	dss
+#	mouse
+
+#	uart
+#	usb
+
+link
+#	archoma
+#	ethermedium
+#	flashigep
+#	loopbackmedium
+#	netdevmedium
+
+## avoid tickling errata 3.1.1.183
+##	usbohci
+#	usbehci		usbehciomap
+
+ip
+#	tcp
+#	udp
+#	ipifc
+#	icmp
+#	icmp6
+#	ipmux
+#	gre
+#	esp
+
+misc
+#	rdb
+#	coproc
+#	dma
+#	mouse
+#	sdaoe		sdscsi
+#	softfpu
+#	syscall
+#	uarti8250
+#	ucalloc
+#	ucallocb
+
+port
+	int cpuserver = 1;
+
+boot cpu
+	tcp
+	local
+
+bootdir
+	boot$CONF.out	boot
+	/$objtype/bin/paqfs
+	/$objtype/bin/auth/factotum
+	bootfs.paq
--- /dev/null
+++ b/sys/src/9/omap4/random.c
@@ -1,0 +1,138 @@
+#include	"u.h"
+#include	"../port/lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"../port/error.h"
+
+
+struct Rb
+{
+	QLock;
+	Rendez	producer;
+	Rendez	consumer;
+	ulong	randomcount;
+	uchar	buf[128];
+	uchar	*ep;
+	uchar	*rp;
+	uchar	*wp;
+	uchar	next;
+	uchar	wakeme;
+	ushort	bits;
+	ulong	randn;
+} rb;
+
+static int
+rbnotfull(void*)
+{
+	int i;
+
+	i = rb.rp - rb.wp;
+	return i != 1 && i != (1 - sizeof(rb.buf));
+}
+
+static int
+rbnotempty(void*)
+{
+	return rb.wp != rb.rp;
+}
+
+static void
+genrandom(void*)
+{
+	up->basepri = PriNormal;
+	up->priority = up->basepri;
+
+	for(;;){
+		for(;;)
+			if(++rb.randomcount > 100000)
+				break;
+		if(anyhigher())
+			sched();
+		if(!rbnotfull(0))
+			sleep(&rb.producer, rbnotfull, 0);
+	}
+}
+
+/*
+ *  produce random bits in a circular buffer
+ */
+static void
+randomclock(void)
+{
+	if(rb.randomcount == 0 || !rbnotfull(0))
+		return;
+
+	rb.bits = (rb.bits<<2) ^ rb.randomcount;
+	rb.randomcount = 0;
+
+	rb.next++;
+	if(rb.next != 8/2)
+		return;
+	rb.next = 0;
+
+	*rb.wp ^= rb.bits;
+	if(rb.wp+1 == rb.ep)
+		rb.wp = rb.buf;
+	else
+		rb.wp = rb.wp+1;
+
+	if(rb.wakeme)
+		wakeup(&rb.consumer);
+}
+
+void
+randominit(void)
+{
+	addclock0link(randomclock, 1000/HZ);
+	rb.ep = rb.buf + sizeof(rb.buf);
+	rb.rp = rb.wp = rb.buf;
+	kproc("genrandom", genrandom, 0);
+}
+
+/*
+ *  consume random bytes from a circular buffer
+ */
+ulong
+randomread(void *xp, ulong n)
+{
+	uchar *e, *p;
+	ulong x;
+
+	p = xp;
+
+	if(waserror()){
+		qunlock(&rb);
+		nexterror();
+	}
+
+	qlock(&rb);
+	for(e = p + n; p < e; ){
+		if(rb.wp == rb.rp){
+			rb.wakeme = 1;
+			wakeup(&rb.producer);
+			sleep(&rb.consumer, rbnotempty, 0);
+			rb.wakeme = 0;
+			continue;
+		}
+
+		/*
+		 *  beating clocks will be predictable if
+		 *  they are synchronized.  Use a cheap pseudo
+		 *  random number generator to obscure any cycles.
+		 */
+		x = rb.randn*1103515245 ^ *rb.rp;
+		*p++ = rb.randn = x;
+
+		if(rb.rp+1 == rb.ep)
+			rb.rp = rb.buf;
+		else
+			rb.rp = rb.rp+1;
+	}
+	qunlock(&rb);
+	poperror();
+
+	wakeup(&rb.producer);
+
+	return n;
+}
--- /dev/null
+++ b/sys/src/9/omap4/trap.c
@@ -1,0 +1,192 @@
+#include "u.h"
+#include "ureg.h"
+#include "../port/lib.h"
+#include "../port/error.h"
+#include "../port/systab.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "arm.h"
+
+extern uchar *periph;
+ulong *intc, *intd;
+void (*irqhandler[256])(Ureg*);
+
+static char *trapname[] = {
+	"reset", /* wtf */
+	"undefined instruction",
+	"supervisor call",
+	"prefetch abort",
+	"data abort",
+	"unknown trap",
+	"IRQ",
+	"FIQ",
+};
+
+void
+trapinit(void)
+{
+	extern void _dataabort(), _undefined(), _prefabort(), _irq(), _fiq(), _reset(), _wtftrap(), _syscall();
+	int i;
+	ulong *trapv;
+
+	trapv = (ulong *) 0xFFFF0000;
+	for(i = 0; i < 8; i++)
+		trapv[i] = 0xE59FF018;
+	trapv[8] = (ulong) _reset;
+	trapv[9] = (ulong) _undefined;
+	trapv[10] = (ulong) _syscall;
+	trapv[11] = (ulong) _prefabort;
+	trapv[12] = (ulong) _dataabort;
+	trapv[13] = (ulong) _wtftrap;
+	trapv[14] = (ulong) _irq;
+	trapv[15] = (ulong) _fiq;
+	
+	intc = (ulong *) (periph + 0x100);
+	intc[1] = 0;
+	intc[0] |= 1;
+	intd = (ulong *) (periph + 0x1000);
+	intd[0] |= 1;
+}
+
+void
+intenable(int i, void (*fn)(Ureg *))
+{
+	intd[0x40 + (i / 32)] |= 1 << (i % 32);
+	irqhandler[i] = fn;
+}
+
+void
+faultarm(Ureg *ureg)
+{
+	ulong addr, sr;
+	int user, n, read, nsys;
+	extern ulong getdfsr(void), getifsr(void), getdfar(void), getifar(void);
+	char buf[ERRMAX];
+
+	user = (ureg->psr & PsrMask) == PsrMusr;
+	read = 1;
+	if(ureg->type == 3){
+		sr = getifsr();
+		addr = getifar();
+	}else{
+		sr = getdfsr();
+		addr = getdfar();
+		if(sr & (1<<11))
+			read = 0;
+	}
+	if(!user && addr >= KZERO){
+	kernel:
+		printureg(ureg);
+		panic("kernel fault: addr=%#.8lux pc=%#.8lux sr=%#.8lux", addr, ureg->pc, sr);
+	}
+	if(up == nil){
+		printureg(ureg);
+		panic("%s fault: up=nil addr=%#.8lux pc=%#.8lux sr=%#.8lux", user ? "user" : "kernel", addr, ureg->pc, sr);
+	}
+	nsys = up->insyscall;
+	up->insyscall = 1;
+	n = fault(addr, read);
+	if(n < 0){
+		if(!user)
+			goto kernel;
+		sprint(buf, "sys: trap: fault %s addr=0x%lux", read ? "read" : "write", addr);
+		postnote(up, 1, buf, NDebug);
+	}
+	up->insyscall = nsys;
+}
+
+void
+trap(Ureg *ureg)
+{
+	int user, intn, x;
+	
+	user = (ureg->psr & PsrMask) == PsrMusr;
+	if(user){
+		fillureguser(ureg);
+		up->dbgreg = ureg;
+	}
+	switch(ureg->type){
+	case 3:
+	case 4:
+		faultarm(ureg);
+		break;
+	case 6:
+		x = intc[3];
+		intn = x & 0x3F;
+		if(irqhandler[intn] != nil)
+			irqhandler[intn](ureg);
+		intc[4] = x;
+		if(intn != 29)
+			preempted();
+		if(up && up->delaysched && (intn == 29)){
+			sched();
+			splhi();
+		}
+		break;
+	default:
+		printureg(ureg);
+		panic("%s", trapname[ureg->type]);
+	}
+	if(user)
+		up->dbgreg = nil;
+}
+
+void
+syscall(Ureg *ureg)
+{
+	int scall, ret;
+	ulong s, sp;
+	char *e;
+
+	m->syscall++;
+	up->insyscall = 1;
+	up->pc = ureg->pc;
+	up->dbgreg = ureg;
+	if(up->procctl == Proc_tracesyscall){
+		up->procctl = Proc_stopme;
+		procctl(up);
+	}
+	scall = ureg->r0;
+	up->scallnr = scall;
+//	print("%s\n", sysctab[scall]);
+	spllo();
+
+	sp = ureg->sp;
+	up->nerrlab = 0;
+	ret = -1;
+	if(!waserror()){
+		if(scall >= nsyscall){
+			postnote(up, 1, "sys: bad syscall", NDebug);
+			error(Ebadarg);
+		}
+		validaddr(sp, sizeof(Sargs) + BY2WD, 0);
+		up->s = *((Sargs*)(sp + BY2WD));
+		up->psstate = sysctab[scall];
+		ret = systab[scall](up->s.args);
+		poperror();
+	}else{
+		e = up->syserrstr;
+		up->syserrstr = up->errstr;
+		up->errstr = e;
+	}
+	if(up->nerrlab != 0)
+		panic("error stack");
+	ureg->r0 = ret;
+
+	if(up->procctl == Proc_tracesyscall){
+		up->procctl = Proc_stopme;
+		s = splhi();
+		procctl(up);
+		splx(s);
+	}
+	up->insyscall = 0;
+	up->psstate = nil;
+	splhi();
+	if(up->delaysched){
+		sched();
+		splhi();
+	}
+	up->dbgreg = nil;
+}
--- /dev/null
+++ b/sys/src/9/omap4/uart.c
@@ -1,0 +1,18 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+extern ulong *uart;
+
+void
+uartputs(char *s, int n)
+{
+	for(; n--; s++){
+		while(uart[17] & 1)
+			;
+		uart[0] = *s;
+	}
+}