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;
+ }
+}