added omap4 kernel prototype

This commit is contained in:
aiju 2011-09-02 12:23:34 +02:00
parent df91e24667
commit d886c9d248
17 changed files with 2079 additions and 0 deletions

161
sys/src/9/omap4/arch.c Normal file
View file

@ -0,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);
}

246
sys/src/9/omap4/arm.h Normal file
View file

@ -0,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)

31
sys/src/9/omap4/arm.s Normal file
View file

@ -0,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;

117
sys/src/9/omap4/clock.c Normal file
View file

@ -0,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);
}

144
sys/src/9/omap4/dat.h Normal file
View file

@ -0,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

34
sys/src/9/omap4/fns.h Normal file
View file

@ -0,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*));

25
sys/src/9/omap4/init9.s Normal file
View file

@ -0,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

0
sys/src/9/omap4/io.h Normal file
View file

298
sys/src/9/omap4/l.s Normal file
View file

@ -0,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

194
sys/src/9/omap4/main.c Normal file
View file

@ -0,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");
}

65
sys/src/9/omap4/mem.h Normal file
View file

@ -0,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)

101
sys/src/9/omap4/mkfile Normal file
View file

@ -0,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

237
sys/src/9/omap4/mmu.c Normal file
View file

@ -0,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;
}

78
sys/src/9/omap4/panda Normal file
View file

@ -0,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

138
sys/src/9/omap4/random.c Normal file
View file

@ -0,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;
}

192
sys/src/9/omap4/trap.c Normal file
View file

@ -0,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;
}

18
sys/src/9/omap4/uart.c Normal file
View file

@ -0,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;
}
}