add cycv kernel

This commit is contained in:
aiju 2020-01-08 02:35:01 +00:00
parent 826c76f90d
commit 17ebe55031
18 changed files with 3323 additions and 1 deletions

55
sys/src/9/cycv/cycv Normal file
View file

@ -0,0 +1,55 @@
dev
root
cons
swap
# arch
uart
mnt
srv
shr
proc
env
pipe
dup
ether netif
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
ssl
tls
# cap
# kprof
sd
# draw screen
# mouse
# usb
segment
link
ethermedium
loopbackmedium
netdevmedium
# usbehci usbehcizynq
misc
uartcycv
# sdmmc emmc
sdram
ip
tcp
udp
rudp
ipifc
icmp
icmp6
gre
ipmux
esp
port
int cpuserver = 0;
bootdir
/$objtype/bin/paqfs
/$objtype/bin/auth/factotum
boot
bootfs.paq

202
sys/src/9/cycv/dat.h Normal file
View file

@ -0,0 +1,202 @@
typedef struct Conf Conf;
typedef struct Confmem Confmem;
typedef struct FPsave FPsave;
typedef struct PFPU PFPU;
typedef struct L1 L1;
typedef struct Label Label;
typedef struct Lock Lock;
typedef struct KMap KMap;
typedef struct MMMU MMMU;
typedef struct Mach Mach;
typedef struct Page Page;
typedef struct Proc Proc;
typedef struct PMMU PMMU;
typedef struct Ureg Ureg;
typedef struct ISAConf ISAConf;
typedef uvlong Tval;
#pragma incomplete Ureg
#define MAXSYSARG 5 /* for mount(fd, mpt, flag, arg, srv) */
#define AOUT_MAGIC (E_MAGIC)
struct Lock
{
ulong key;
u32int sr;
uintptr pc;
Proc* p;
Mach* m;
int isilock;
};
struct Label
{
uintptr sp;
uintptr pc;
};
struct FPsave
{
ulong exc, scr;
uchar regs[256];
};
struct PFPU
{
int fpstate;
FPsave fpsave[1];
};
enum
{
FPinit,
FPactive,
FPinactive,
FPillegal = 0x100
};
struct Confmem
{
uintptr base;
usize npage;
uintptr kbase;
uintptr klimit;
};
struct Conf
{
ulong nmach; /* processors */
ulong nproc; /* processes */
Confmem mem[2]; /* 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 */
int monitor;
};
/*
* MMU stuff in proc
*/
#define NCOLOR 1
struct PMMU
{
L1 *l1;
Page *mmuused, *mmufree;
int nkmap;
Page *kmaptable;
};
#include "../port/portdat.h"
struct L1
{
Ref;
uintptr pa;
ulong *va;
L1 *next;
};
struct MMMU
{
L1 l1;
L1 *l1free;
int nfree;
uchar asid;
};
struct Mach
{
/* known to assembly */
int machno; /* physical id of processor */
uintptr splpc; /* pc of last caller to splhi */
Proc* proc; /* current process */
ulong excregs[3];
ulong cycleshi;
/* end of known to assembly */
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 */
ulong delayloop;
/* stats */
int tlbfault;
int tlbpurge;
int pfault;
int cs;
int syscall;
int load;
int intr;
int lastintr;
int ilockdepth;
Perf perf; /* performance counters */
int cpumhz;
uvlong cpuhz; /* speed of cpu */
uvlong cyclefreq; /* Frequency of user readable cycle counter */
MMMU;
int stack[1];
};
#define NISAOPT 8
struct ISAConf
{
char *type;
ulong port;
int irq;
int nopt;
char *opt[NISAOPT];
};
#define BUSUNKNOWN -1
struct
{
char machs[MAXMACH]; /* active CPUs */
int exiting; /* shutdown */
}active;
extern register Mach* m; /* R10 */
extern register Proc* up; /* R9 */
extern int normalprint;
void nope(void);
#define NOPE nope();
/*
* hardware info about a device
*/
typedef struct {
ulong port;
int size;
} Devport;
struct DevConf
{
ulong intnum; /* interrupt number */
char *type; /* card type, malloced */
int nports; /* Number of ports */
Devport *ports; /* The ports themselves */
};
#define mpcore ((ulong*)MPCORE_BASE)

389
sys/src/9/cycv/devarch.c Normal file
View file

@ -0,0 +1,389 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "../port/error.h"
enum {
Qdir = 0,
Qtemp,
Qpl,
Qfbctl,
Qbase,
Qmax = 16,
};
static Dirtab archdir[Qmax] = {
".", { Qdir, 0, QTDIR }, 0, 0555,
"temp", { Qtemp, 0}, 0, 0440,
"pl", { Qpl, 0 }, 0, 0660,
"fbctl", { Qfbctl, 0 }, 0, 0660,
};
static int narchdir = Qbase;
static int temp = -128;
static ulong *devc;
static int dmadone;
enum { PLBUFSIZ = 8192 };
static uchar *plbuf;
static Rendez plinitr, pldoner, pldmar;
static QLock plrlock, plwlock;
static Ref plwopen;
static Physseg *axi;
enum {
DEVCTRL = 0,
DEVISTS = 0xc/4,
DEVMASK,
DEVSTS,
DMASRC = 0x18/4,
DMADST,
DMASRCL,
DMADSTL,
XADCCFG = 0x100/4,
XADCSTS,
XADCMASK,
XADCMSTS,
XADCCMD,
XADCREAD,
XADCMCTL,
FPGA0_CLK_CTRL = 0x170/4,
};
enum {
PROG = 1<<30,
DONE = 1<<2,
INITPE = 1<<1,
INIT = 1<<4,
DMADONE = 1<<13,
};
static void
scram(void)
{
splhi();
slcr[0x100/4] |= 1<<4;
slcr[0x104/4] |= 1<<4;
slcr[0x108/4] |= 1<<4;
slcr[DEVCTRL] &= ~PROG;
slcr[0x244/4] = 1<<4|1<<5;
}
static void
xadcirq(Ureg *, void *)
{
int v;
static int al, notfirst;
while((devc[XADCMSTS] & 1<<8) == 0){
v = ((u16int)devc[XADCREAD]) >> 4;
if(v == 0){
if(notfirst)
print("temperature sensor reads 0, shouldn't happen\n");
break;
}
notfirst = 1;
temp = v * 5040 / 4096 - 2732;
if(temp >= 800){
if(al == 0)
print("temperature exceeds 80 deg C\n");
al = 1;
}
if(temp <= 750)
al = 0;
if(temp >= 900){
print("chip temperature exceeds 90 deg C, shutting down");
scram();
}
}
devc[XADCSTS] = -1;
}
static void
xadctimer(void)
{
devc[XADCCMD] = 1<<26 | 0<<16;
}
static void
xadcinit(void)
{
int i;
int x;
devc = vmap(DEVC_BASE, 0x11C);
devc[XADCMCTL] |= 1<<4;
devc[XADCMCTL] &= ~(1<<4);
devc[XADCCMD] = 0x08030000;
for(i = 0; i < 15; i++)
devc[XADCCMD] = 0;
while((devc[XADCMSTS] & 1<<10) == 0)
;
while((devc[XADCMSTS] & 1<<8) == 0){
x = devc[XADCREAD];
USED(x);
}
devc[XADCCFG] = 0x80001114;
devc[XADCMASK] = ~(1<<8);
devc[XADCSTS] = -1;
intrenable(XADCIRQ, xadcirq, nil, LEVEL, "xadc");
addclock0link(xadctimer, XADCINTERVAL);
}
static int
isplinit(void *)
{
return devc[DEVSTS] & INIT;
}
static int
ispldone(void *)
{
return devc[DEVISTS] & DONE;
}
static int
isdmadone(void *)
{
return dmadone;
}
static void
plirq(Ureg *, void *)
{
ulong fl;
fl = devc[DEVISTS];
if((fl & INITPE) != 0)
wakeup(&plinitr);
if((fl & DONE) != 0){
slcr[0x900/4] = 0xf;
slcr[0x240/4] = 0;
devc[DEVMASK] |= DONE;
axi->attr &= ~SG_FAULT;
wakeup(&pldoner);
}
if((fl & DMADONE) != 0){
dmadone++;
wakeup(&pldmar);
}
devc[DEVISTS] = fl;
}
static void
plinit(void)
{
Physseg seg;
memset(&seg, 0, sizeof seg);
seg.attr = SG_PHYSICAL | SG_DEVICE | SG_NOEXEC | SG_FAULT;
seg.name = "axi";
seg.pa = 0x40000000;
seg.size = 0x8000000;
axi = addphysseg(&seg);
devc[DEVCTRL] &= ~(PROG|1<<25);
devc[DEVCTRL] |= 3<<26|PROG;
devc[DEVISTS] = -1;
devc[DEVMASK] = ~(DONE|INITPE|DMADONE);
intrenable(DEVCIRQ, plirq, nil, LEVEL, "pl");
slcr[FPGA0_CLK_CTRL] = 1<<20 | 10<<8;
}
static void
plconf(void)
{
axi->attr |= SG_FAULT;
procflushpseg(axi);
flushmmu();
slcr[0x240/4] = 0xf;
slcr[0x900/4] = 0xa;
devc[DEVISTS] = DONE|INITPE|DMADONE;
devc[DEVCTRL] |= PROG;
devc[DEVCTRL] &= ~PROG;
devc[DEVMASK] &= ~DONE;
devc[DEVCTRL] |= PROG;
while(waserror())
;
sleep(&plinitr, isplinit, nil);
poperror();
}
static long
plwrite(uintptr pa, long n)
{
dmadone = 0;
coherence();
devc[DMASRC] = pa;
devc[DMADST] = -1;
devc[DMASRCL] = n>>2;
devc[DMADSTL] = 0;
while(waserror())
;
sleep(&pldmar, isdmadone, nil);
poperror();
return n;
}
static long
plcopy(uchar *d, long n)
{
long ret;
ulong nn;
uintptr pa;
if((n & 3) != 0 || n <= 0)
error(Eshort);
eqlock(&plwlock);
if(waserror()){
qunlock(&plwlock);
nexterror();
}
ret = n;
pa = PADDR(plbuf);
while(n > 0){
if(n > PLBUFSIZ)
nn = PLBUFSIZ;
else
nn = n;
memmove(plbuf, d, nn);
cleandse(plbuf, plbuf + nn);
clean2pa(pa, pa + nn);
n -= plwrite(pa, nn);
}
qunlock(&plwlock);
poperror();
return ret;
}
void
archinit(void)
{
slcr[2] = 0xDF0D;
xadcinit();
plinit();
}
static long
archread(Chan *c, void *a, long n, vlong offset)
{
char buf[64];
switch((ulong)c->qid.path){
case Qdir:
return devdirread(c, a, n, archdir, narchdir, devgen);
case Qtemp:
snprint(buf, sizeof(buf), "%d.%d\n", temp/10, temp%10);
return readstr(offset, a, n, buf);
case Qpl:
eqlock(&plrlock);
if(waserror()){
qunlock(&plrlock);
nexterror();
}
sleep(&pldoner, ispldone, nil);
qunlock(&plrlock);
poperror();
return 0;
case Qfbctl:
return fbctlread(c, a, n, offset);
default:
error(Egreg);
return -1;
}
}
static long
archwrite(Chan *c, void *a, long n, vlong offset)
{
switch((ulong)c->qid.path){
case Qpl:
return plcopy(a, n);
case Qfbctl:
return fbctlwrite(c, a, n, offset);
default:
error(Egreg);
return -1;
}
}
Walkqid*
archwalk(Chan* c, Chan *nc, char** name, int nname)
{
return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
}
static int
archstat(Chan* c, uchar* dp, int n)
{
return devstat(c, dp, n, archdir, narchdir, devgen);
}
static Chan*
archopen(Chan* c, int omode)
{
devopen(c, omode, archdir, narchdir, devgen);
if((ulong)c->qid.path == Qpl && (c->mode == OWRITE || c->mode == ORDWR)){
if(incref(&plwopen) != 1){
c->flag &= ~COPEN;
decref(&plwopen);
error(Einuse);
}
plbuf = smalloc(PLBUFSIZ);
plconf();
}
return c;
}
static void
archclose(Chan* c)
{
if((c->flag & COPEN) != 0)
if((ulong)c->qid.path == Qpl && (c->mode == OWRITE || c->mode == ORDWR)){
free(plbuf);
plbuf = nil;
decref(&plwopen);
}
}
static Chan*
archattach(char* spec)
{
return devattach('P', spec);
}
Dev archdevtab = {
'P',
"arch",
devreset,
devinit,
devshutdown,
archattach,
archwalk,
archstat,
archopen,
devcreate,
archclose,
archread,
devbread,
archwrite,
devbwrite,
devremove,
devwstat,
};

78
sys/src/9/cycv/fns.h Normal file
View file

@ -0,0 +1,78 @@
#include "../port/portfns.h"
int tas(void *);
int cmpswap(long *, long, long);
void evenaddr(uintptr);
void* kaddr(uintptr);
uintptr paddr(void *);
uintptr cankaddr(uintptr);
void procsave(Proc *);
void procrestore(Proc *);
void idlehands(void);
void sendevent(void);
void coherence(void);
void procfork(Proc *);
void procsetup(Proc *);
KMap* kmap(Page *);
void kunmap(KMap *);
#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
#define getpgcolor(a) 0
#define kmapinval()
#define KADDR(a) kaddr(a)
#define PADDR(a) paddr((void*)(a))
#define userureg(ur) (((ur)->psr & PsrMask) == PsrMusr)
#define VA(k) ((void*)(k))
#define PTR2UINT(p) ((uintptr)(p))
void uartinit(void);
void mmuinit(void);
uintptr ttbget(void);
void ttbput(uintptr);
void cycles(uvlong *);
void kexit(Ureg *);
ulong getifsr(void);
ulong getdfsr(void);
uintptr getifar(void);
uintptr getdfar(void);
void links(void);
void timerinit(void);
void synccycles(void);
void setpmcr(ulong);
void setpmcnten(ulong);
void* tmpmap(uintptr);
void tmpunmap(void*);
void flushpg(void *);
void setasid(ulong);
void flushtlb(void);
void touser(void *);
void noted(Ureg *, ulong);
void l1switch(L1 *, int);
void intrenable(int, void (*)(Ureg *, void *), void *, int, char *);
void intrinit(void);
void intr(Ureg *);
int uartconsole(void);
long fbctlread(Chan*,void*,long,vlong);
long fbctlwrite(Chan*,void*,long,vlong);
void fpoff(void);
void fpsave(FPsave *);
void fprestore(FPsave *);
void fpinit(void);
void fpclear(void);
char* getconf(char *);
void invalise(void *, void *);
void cleandse(void *, void *);
void invaldse(void *, void *);
void clinvdse(void *, void *);
void invaldln(void *);
void cleandln(void *);
void clinvdln(void *);
void dmaflush(int, void*, ulong);
void* ucalloc(ulong);
void clean2pa(uintptr, uintptr);
void inval2pa(uintptr, uintptr);
void archinit(void);
uintptr palookur(void *);
void screeninit(void);
int isaconfig(char*, int, ISAConf*);
void cputhex(u32int);

7
sys/src/9/cycv/init9.s Normal file
View file

@ -0,0 +1,7 @@
TEXT _main(SB), $-4
MOVW $setR12(SB), R12
MOVW 4(R13), R0
ADD $4, R13, R1
SUB $4, R13
MOVW R1, 8(R13)
MOVW $startboot(SB), R15

121
sys/src/9/cycv/intr.c Normal file
View file

@ -0,0 +1,121 @@
#include "u.h"
#include <ureg.h>
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
enum {
NINTR = 212,
NPRIVATE = 32
};
static struct irq {
void (*f)(Ureg *, void *);
void *arg;
char *name;
} irqs[NINTR];
enum {
ICCICR = 0x100/4,
ICCPMR,
ICCBPR,
ICCIAR,
ICCEOIR,
ICDDCR = 0x1000/4,
ICDISR = 0x1080/4,
ICDISER = 0x1100/4,
ICDICER = 0x1180/4,
ICDICPR = 0x1280/4,
ICDABR = 0x1300/4,
ICDIPRI = 0x1400/4,
ICDIPTR = 0x1800/4,
ICDICFR = 0x1C00/4,
};
void
intrinit(void)
{
int i;
mpcore[ICDDCR] = 3;
mpcore[ICCICR] = 7;
mpcore[ICCBPR] = 3;
mpcore[ICCPMR] = 255;
if(m->machno != 0)
return;
/* disable all irqs and clear any pending interrupts */
for(i = 0; i < NINTR/32; i++){
mpcore[ICDISR + i] = -1;
mpcore[ICDICER + i] = -1;
mpcore[ICDICPR + i] = -1;
mpcore[ICDABR + i] = 0;
}
}
void
intrenable(int irq, void (*f)(Ureg *, void *), void *arg, int type, char *name)
{
ulong *e, s;
struct irq *i;
if(f == nil)
panic("intrenable: f == nil");
if(irq < 0 || irq >= NINTR)
panic("intrenable: invalid irq %d", irq);
if(type != LEVEL && type != EDGE)
panic("intrenable: invalid type %d", type);
if(irqs[irq].f != nil && irqs[irq].f != f)
panic("intrenable: handler already assigned");
if(irq >= NPRIVATE){
e = &mpcore[ICDIPTR + (irq >> 2)];
s = irq << 3 & 24;
*e = *e & ~(3 << s) | 1 << s;
e = &mpcore[ICDICFR + (irq >> 4)];
s = irq << 1 & 30 | 1;
*e = *e & ~(1 << s) | type << s;
}
((uchar*)&mpcore[ICDIPRI])[irq] = 0;
i = &irqs[irq];
i->f = f;
i->arg = arg;
i->name = name;
mpcore[ICDISER + (irq >> 5)] = 1 << (irq & 31);
mpcore[ICDABR + (irq >> 5)] |= 1 << (irq & 31);
}
void
intr(Ureg *ureg)
{
ulong v;
int irq;
struct irq *i;
v = mpcore[ICCIAR];
irq = v & 0x3ff;
if(irq == 0x3ff)
return;
m->intr++;
m->lastintr = irq;
i = &irqs[irq];
if(i->f == nil)
print("irq without handler %d\n", irq);
else
i->f(ureg, i->arg);
mpcore[ICCEOIR] = v;
if(up != nil){
if(irq == TIMERIRQ){
if(up->delaysched){
splhi();
sched();
}
}else
preempted();
}
}

13
sys/src/9/cycv/io.h Normal file
View file

@ -0,0 +1,13 @@
#define UART_BASE 0xFFC02000
#define MPCORE_BASE 0xFFFEC000
#define L2_BASE 0xFFFEF000
#define CLOCKMGR_BASE 0xFFD04000
#define HPS_CLK 25
#define TIMERIRQ 29
#define UART0IRQ 194
#define LEVEL 0
#define EDGE 1

502
sys/src/9/cycv/l.s Normal file
View file

@ -0,0 +1,502 @@
#include "mem.h"
#include "io.h"
#define PUTC(c) MOVW $(c), R0; MOVW R0, (R8)
TEXT _start(SB), $-4
MOVW $(KTZERO-KZERO), R13
MOVW $(UART_BASE), R8
/* disable L2 cache */
MOVW $0, R0
MOVW $(L2_BASE+0x100), R1
MOVW R0, (R1)
PUTC('P')
/* disable MMU and L1 caches */
MOVW $0x20c5047a, R1
MOVW $_start0-KZERO(SB), R2
MCR 15, 0, R1, C(1), C(0), 0
MOVW R2, R15
TEXT _start0(SB), $-4
DSB
ISB
PUTC('l')
/* clean up to KTZERO */
MOVW $0, R0
MOVW R0, R1
MOVW $(KTZERO-KZERO), R2
_clrstart:
MOVW.P R0, 4(R1)
CMP.S R1, R2
BGE _clrstart
/* clean BSS */
MOVW $edata-KZERO(SB), R1
MOVW $end-KZERO(SB), R2
_clrbss:
MOVW.P R0, 4(R1)
CMP.S R1, R2
BGE _clrbss
PUTC('a')
/* KZERO to PERIPH is mapped to 0 */
MOVW $SECSZ, R0
MOVW $(MACHL1(0)-KZERO), R4
MOVW $KZERO, R1
ADD R1>>(SECSH-2), R4, R1
MOVW $(L1SEC|L1CACHED|L1KERRW), R2
MOVW $(PERIPH-KZERO), R3
_start1:
MOVW.P R2, 4(R1)
ADD R0, R2
CMP.S R2, R3
BGE _start1
/* memory above PERIPH is mapped to itself */
MOVW $(PERIPH|L1SEC|L1DEVICE|L1NOEXEC|L1KERRW), R2
_start2:
MOVW.P R2, 4(R1)
ADD.S R0, R2
BCC _start2
PUTC('n')
MOVW $(MACH(0)-KZERO), R(Rmach)
_start3:
/* enable MMU permission checking */
MOVW $0x55555555, R0
MCR 15, 0, R0, C(3), C(0), 0
/* select page table and enable MMU */
MOVW $0, R0
MCR 15, 0, R0, C(8), C(7), 0
DSB
ORR $TTBATTR, R4, R1
MCR 15, 0, R1, C(2), C(0), 0
MOVW $0x20c5047b, R1
MOVW $_virt(SB), R2
PUTC(' ')
MCR 15, 0, R1, C(1), C(0), 0
MOVW R2, R15
TEXT _virt(SB), $-4
DSB
ISB
ADD $KZERO, R(Rmach)
MOVW R(Rmach), R13
ADD $MACHSIZE, R13
MOVW R(Rmach), R0
ADD $12, R0
BL loadsp(SB)
MOVW $vectors(SB), R1
MCR 15, 0, R1, C(12), C(0)
/* enable maths coprocessors in CPACR but disable them in FPEXC */
MRC 15, 0, R0, C(1), C(0), 2
ORR $(15<<20), R0
MCR 15, 0, R0, C(1), C(0), 2
VMRS(0xe, FPEXC, 0)
BIC $(3<<30), R0
VMSR(0xe, 0, FPEXC)
/* enable L1 cache */
MOVW $0, R0
MCR 15, 0, R0, C(7), C(5), 0
MCR 15, 0, R0, C(7), C(5), 6
BL l1dclear(SB)
MRC 15, 0, R0, C(1), C(0), 1
ORR $(1|2|1<<6), R0
MCR 15, 0, R0, C(1), C(0), 1
MRC 15, 0, R0, C(1), C(0), 0
ORR $(3<<11|1<<2), R0
MCR 15, 0, R0, C(1), C(0), 0
DSB
ISB
MOVW $UART_BASE, R8
PUTC('9')
/* kernel Mach* in TPIDRPRW */
MCR 15, 0, R(Rmach), C(13), C(0), 4
MOVW $setR12(SB), R12
MOVW $0, R(Rup)
BL main(SB)
B idlehands(SB)
BL _div(SB) /* hack to load _div */
TEXT touser(SB), $-4
CPS(CPSID)
SUB $12, R13
MOVW R0, (R13)
MOVW $0, R1
MOVW R1, 4(R13)
MOVW $(UTZERO+0x20), R1
MOVW R1, 8(R13)
MOVW CPSR, R1
BIC $(PsrMask|PsrDirq|PsrDfiq), R1
ORR $PsrMusr, R1
MOVW R1, SPSR
MOVW $(KTZERO-(15*4)), R0
MOVM.IA (R0), [R0-R12]
MOVM.IA.S (R13), [R13-R14]
ADD $8, R13
MOVM.IA.W.S (R13), [R15]
TEXT forkret(SB), $-4
MOVW (16*4)(R13), R0
MOVW R0, SPSR
MOVM.IA.W (R13), [R0-R12]
MOVM.IA.S (R13), [R13-R14]
ADD $16, R13
DSB
ISB
MOVM.IA.W.S (R13), [R15]
TEXT loadsp(SB), $0
CPS(CPSMODE | PsrMabt)
MOVW R0, R13
CPS(CPSMODE | PsrMund)
MOVW R0, R13
CPS(CPSMODE | PsrMirq)
MOVW R0, R13
CPS(CPSMODE | PsrMfiq)
MOVW R0, R13
CPS(CPSMODE | PsrMsvc)
RET
TEXT cputhex(SB), $0
MOVW R0, R7
MOVW $UART_BASE, R8
TEXT puthex(SB), $0
_p0:
MOVW 0x14(R8), R6
AND.S $(1<<5), R6
BEQ _p0
#define DIG MOVW R7>>28, R6; AND $15, R6; ADD $'0', R6; CMP $'9', R6; ADD.GT $7, R6; MOVW R6, (R8); MOVW R7<<4, R7
DIG; DIG; DIG; DIG
DIG; DIG; DIG; DIG
MOVW $13, R6
MOVW R6, (R8)
MOVW $10, R6
MOVW R6, (R8)
RET
TEXT spllo(SB), $-4
MOVW CPSR, R0
CPS(CPSIE)
RET
TEXT splhi(SB), $-4
MOVW R14, 4(R(Rmach))
MOVW CPSR, R0
CPS(CPSID)
RET
TEXT splx(SB), $-4
MOVW R14, 4(R(Rmach))
MOVW R0, R1
MOVW CPSR, R0
MOVW R1, CPSR
RET
TEXT spldone(SB), $-4
RET
TEXT islo(SB), $0
MOVW CPSR, R0
AND $(PsrDirq), R0
EOR $(PsrDirq), R0
RET
TEXT setlabel(SB), $-4
MOVW R13, 0(R0)
MOVW R14, 4(R0)
MOVW $0, R0
RET
TEXT gotolabel(SB), $-4
MOVW 0(R0), R13
MOVW 4(R0), R14
MOVW $1, R0
RET
TEXT cas(SB), $0
TEXT cmpswap(SB), $0
MOVW ov+4(FP), R1
MOVW nv+8(FP), R2
spincas:
LDREX (R0), R3
CMP.S R3, R1
BNE fail
STREX R2, (R0), R4
CMP.S $0, R4
BNE spincas
MOVW $1, R0
DMB
RET
fail:
CLREX
MOVW $0, R0
RET
TEXT tas(SB), $0
TEXT _tas(SB), $0
MOVW $0xDEADDEAD, R2
_tas1:
LDREX (R0), R1
STREX R2, (R0), R3
CMP.S $0, R3
BNE _tas1
MOVW R1, R0
DMB
RET
TEXT coherence(SB), $0
DSB
RET
TEXT idlehands(SB), $0
DSB
WFE
RET
TEXT sendevent(SB), $0
SEV
RET
TEXT ttbget(SB), $0
MRC 15, 0, R0, C(2), C(0), 0
BIC $0x7f, R0
RET
TEXT ttbput(SB), $0
ORR $TTBATTR, R0
MCR 15, 0, R0, C(2), C(0), 0
RET
TEXT flushpg(SB), $0
MCR 15, 0, R0, C(8), C(7), 3
DSB
RET
TEXT flushtlb(SB), $0
MCR 15, 0, R0, C(8), C(3), 0
DSB
RET
TEXT setasid(SB), $0
DSB /* errata */
MCR 15, 0, R0, C(13), C(0), 1
RET
TEXT getifar(SB), $0
MRC 15, 0, R0, C(6), C(0), 2
RET
TEXT getdfar(SB), $0
MRC 15, 0, R0, C(6), C(0), 0
RET
TEXT getifsr(SB), $0
MRC 15, 0, R0, C(5), C(0), 1
RET
TEXT getdfsr(SB), $0
MRC 15, 0, R0, C(5), C(0), 0
RET
TEXT setpmcr(SB), $0
MCR 15, 0, R0, C(9), C(12), 0
RET
TEXT setpmcnten(SB), $0
MCR 15, 0, R0, C(9), C(12), 1
RET
TEXT perfticks(SB), $0
MRC 15, 0, R0, C(9), C(13), 0
RET
TEXT cycles(SB), $0
MRC 15, 0, R1, C(9), C(13), 0
MOVW R1, (R0)
MOVW 24(R(Rmach)), R1
MRC 15, 0, R2, C(9), C(12), 3
AND.S $(1<<31), R2
BEQ _cycles0
MCR 15, 0, R2, C(9), C(12), 3
ADD $1, R1
MOVW R1, 24(R(Rmach))
_cycles0:
MOVW R1, 4(R0)
RET
TEXT fpinit(SB), $0
MOVW $(1<<30), R0
VMSR(0xe, 0, FPEXC)
MOVW $0, R0
VMSR(0xe, 0, FPSCR)
RET
TEXT fprestore(SB), $0
MOVM.IA.W (R0), [R1-R2]
VMSR(0xe, 1, FPEXC)
VMSR(0xe, 2, FPSCR)
WORD $0xecb00b20
WORD $0xecf00b20
RET
TEXT fpsave(SB), $0
VMRS(0xe, FPEXC, 1)
VMRS(0xe, FPSCR, 2)
MOVM.IA.W [R1-R2], (R0)
WORD $0xeca00b20
WORD $0xece00b20
/* wet floor */
TEXT fpoff(SB), $0
TEXT fpclear(SB), $0
MOVW $0, R1
VMSR(0xe, 1, FPEXC)
RET
#define Rnoway R1
#define Rwayinc R2
#define Rmaxway R3
#define Rsetinc R4
#define Rmaxset R5
TEXT l1dclear(SB), $0
MOVW $0, R0
MCR 15, 2, R0, C(0), C(0), 0
MRC 15, 1, R9, C(0), C(0), 0
AND $7, R9, R8
ADD $4, R8
MOVW $1, Rsetinc
MOVW Rsetinc<<R8, Rsetinc
MOVW R9>>13, Rmaxset
AND $0x7fff, Rmaxset
MOVW Rmaxset<<R8, Rmaxset
MOVW R9>>3, R0
AND $0x3ff, R0
MOVW $(1<<31), Rwayinc
MOVW $(1<<31), Rnoway
MOVW R0, Rmaxway
ADD $1, R0
_l1dclear0:
MOVW.S R0>>1, R0
BEQ _l1dclear1
MOVW Rwayinc>>1, Rwayinc
MOVW Rnoway->1, Rnoway
MOVW Rmaxway@>1, Rmaxway
B _l1dclear0
_l1dclear1:
MOVW Rwayinc<<1, Rwayinc
MVN Rnoway<<1, Rnoway
BIC Rnoway, Rmaxway
MOVW $0, R0
_l1dclear2:
MCR 15, 0, R0, C(7), C(14), 2
ADD Rwayinc, R0
CMP.S Rmaxway, R0
BLT _l1dclear2
AND Rnoway, R0
ADD Rsetinc, R0
CMP.S Rmaxset, R0
BLT _l1dclear2
RET
TEXT invalise(SB), $0
MOVW 4(FP), R1
ADD $(LINSIZ - 1), R1
BIC $(LINSIZ - 1), R0
BIC $(LINSIZ - 1), R1
_invalise0:
MCR 15, 0, R0, C(7), C(5), 1
ADD $LINSIZ, R0
CMP.S R1, R0
BLT _invalise0
RET
TEXT cleandse(SB), $0
DSB
MOVW 4(FP), R1
ADD $(LINSIZ - 1), R1
BIC $(LINSIZ - 1), R0
BIC $(LINSIZ - 1), R1
_cleandse0:
MCR 15, 0, R0, C(7), C(10), 1
ADD $LINSIZ, R0
CMP.S R1, R0
BLT _cleandse0
DSB
RET
TEXT invaldse(SB), $0
MOVW 4(FP), R1
ADD $(LINSIZ - 1), R1
BIC $(LINSIZ - 1), R0
BIC $(LINSIZ - 1), R1
_invaldse0:
MCR 15, 0, R0, C(7), C(6), 1
ADD $LINSIZ, R0
CMP.S R1, R0
BLT _invaldse0
DSB
RET
TEXT clinvdse(SB), $0
DSB
MOVW 4(FP), R1
ADD $(LINSIZ - 1), R1
BIC $(LINSIZ - 1), R0
BIC $(LINSIZ - 1), R1
_clinvdse0:
MCR 15, 0, R0, C(7), C(14), 1
ADD $LINSIZ, R0
CMP.S R1, R0
BLT _clinvdse0
DSB
RET
TEXT cleandln(SB), $0
DSB
MCR 15, 0, R0, C(7), C(10), 1
DSB
RET
TEXT invaldln(SB), $0
MCR 15, 0, R0, C(7), C(6), 1
DSB
RET
TEXT clinvdln(SB), $0
DSB
MCR 15, 0, R0, C(7), C(14), 1
DSB
RET
TEXT palookur(SB), $0
MCR 15, 0, R0, C(7), C(8), 2
DSB
MRC 15, 0, R0, C(7), C(4), 0
RET

100
sys/src/9/cycv/ltrap.s Normal file
View file

@ -0,0 +1,100 @@
#include "mem.h"
#include "io.h"
TEXT vectors(SB), $-4
MOVW $_start-KZERO(SB), R15
MOVW $_vexc(SB), R15
MOVW $_vsvc(SB), R15
MOVW $_viabt(SB), R15
MOVW $_vexc(SB), R15
MOVW $vectors(SB), R15
MOVW $_vexc(SB), R15
MOVW $_vexc(SB), R15
TEXT _viabt(SB), $-4
CPS(CPSID)
CLREX
DSB
MOVW R14, 8(R13)
MOVW SPSR, R14
MOVW R14, 4(R13)
MOVW CPSR, R14
AND $0x1e, R14
B _exc
TEXT _vexc(SB), $-4
CPS(CPSID)
CLREX
DSB
MOVW R14, 8(R13)
MOVW SPSR, R14
MOVW R14, 4(R13)
MOVW CPSR, R14
AND $0x1f, R14
_exc:
MOVW R14, 0(R13)
CPS(CPSMODE | PsrMsvc)
SUB $(18*4), R13
MOVM.IA [R0-R14], (R13)
/* get Mach* from TPIDRPRW */
MRC 15, 0, R(Rmach), C(13), C(0), 4
MOVW 8(R(Rmach)), R(Rup)
MOVW $setR12(SB), R12
ADD $12, R(Rmach), R0
MOVM.IA (R0), [R1-R3]
ADD $(15*4), R13, R0
MOVM.IA [R1-R3], (R0)
AND.S $0xf, R2
ADD.NE $(18*4), R13, R0
MOVW.NE R0, (13*4)(R13)
ADD.EQ $(13*4), R13, R0
MOVM.IA.S.EQ [R13-R14], (R0)
MOVW R13, R0
SUB $8, R13
BL trap(SB)
ADD $8, R13
MOVW (16*4)(R13), R0
MOVW R0, SPSR
AND.S $0xf, R0
BEQ _uret
MOVW R(Rmach), (Rmach*4)(R13)
MOVM.IA (R13), [R0-R14]
DSB
MOVM.DB.S (R13), [R15]
TEXT _vsvc(SB), $-4
CLREX
DSB
MOVW.W R14, -4(R13)
MOVW SPSR, R14
MOVW.W R14, -4(R13)
MOVW $PsrMsvc, R14
MOVW.W R14, -4(R13)
MOVM.DB.S [R0-R14], (R13)
SUB $(15*4), R13
/* get Mach* from TPIDRPRW */
MRC 15, 0, R(Rmach), C(13), C(0), 4
MOVW 8(R(Rmach)), R(Rup)
MOVW $setR12(SB), R12
MOVW R13, R0
SUB $8, R13
BL syscall(SB)
ADD $8, R13
MOVW (16*4)(R13), R0
MOVW R0, SPSR
_uret:
MOVM.IA.S (R13), [R0-R14]
ADD $(17*4), R13
DSB
ISB
MOVM.IA.S.W (R13), [R15]

316
sys/src/9/cycv/main.c Normal file
View file

@ -0,0 +1,316 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "init.h"
#include "pool.h"
#include "io.h"
#include "../port/error.h"
#include "tos.h"
Conf conf;
int normalprint, delaylink;
enum { MAXCONF = 64 };
char *confname[MAXCONF], *confval[MAXCONF];
int nconf;
void
exit(int)
{
cpushutdown();
for(;;) idlehands();
}
void
reboot(void *, void *, ulong)
{
}
void
evenaddr(uintptr va)
{
if((va & 3) != 0){
dumpstack();
postnote(up, 1, "sys: odd address", NDebug);
error(Ebadarg);
}
}
void
procfork(Proc *p)
{
ulong s;
p->kentry = up->kentry;
p->pcycles = -p->kentry;
s = splhi();
switch(up->fpstate & ~FPillegal){
case FPactive:
fpsave(up->fpsave);
up->fpstate = FPinactive;
case FPinactive:
memmove(p->fpsave, up->fpsave, sizeof(FPsave));
p->fpstate = FPinactive;
}
splx(s);
}
void
procsetup(Proc *p)
{
p->fpstate = FPinit;
fpoff();
cycles(&p->kentry);
p->pcycles = -p->kentry;
}
void
kexit(Ureg *)
{
Tos *tos;
uvlong t;
tos = (Tos*)(USTKTOP-sizeof(Tos));
cycles(&t);
tos->kcycles += t - up->kentry;
tos->pcycles = t + up->pcycles;
tos->pid = up->pid;
}
static void
options(void)
{
long i, n;
char *cp, *line[MAXCONF], *p, *q;
cp = (char *) CONFADDR;
p = cp;
for(q = cp; *q; q++){
if(*q == '\r')
continue;
if(*q == '\t')
*q = ' ';
*p++ = *q;
}
*p = 0;
n = getfields(cp, line, MAXCONF, 1, "\n");
for(i = 0; i < n; i++){
if(*line[i] == '#')
continue;
cp = strchr(line[i], '=');
if(cp == nil)
continue;
*cp++ = '\0';
confname[nconf] = line[i];
confval[nconf] = cp;
nconf++;
}
}
void
confinit(void)
{
ulong kmem;
int i;
conf.nmach = 1;
conf.nproc = 2000;
conf.ialloc = 16*1024*1024;
conf.nimage = 200;
conf.mem[0].base = PGROUND((ulong)end - KZERO);
conf.mem[0].npage = (1024*1024*1024 - conf.mem[0].base) >> PGSHIFT;
ramdiskinit();
conf.npage = 0;
for(i = 0; i < nelem(conf.mem); i++)
conf.npage += conf.mem[i].npage;
kmem = 200*1024*1024;
conf.upages = conf.npage - kmem/BY2PG;
kmem -= conf.upages*sizeof(Page)
+ conf.nproc*sizeof(Proc)
+ conf.nimage*sizeof(Image);
mainmem->maxsize = kmem;
imagmem->maxsize = kmem - (kmem/10);
}
static void
init0(void)
{
char buf[ERRMAX], **sp;
int i;
up->nerrlab = 0;
spllo();
up->slash = namec("#/", Atodir, 0, 0);
pathclose(up->slash->path);
up->slash->path = newpath("/");
up->dot = cclone(up->slash);
chandevinit();
if(!waserror()){
ksetenv("cputype", "arm", 0);
if(cpuserver)
ksetenv("service", "cpu", 0);
else
ksetenv("service", "terminal", 0);
ksetenv("console", "0", 0);
snprint(buf, sizeof(buf), "zynq %s", conffile);
ksetenv("terminal", buf, 0);
for(i = 0; i < nconf; i++){
if(*confname[i] != '*')
ksetenv(confname[i], confval[i], 0);
ksetenv(confname[i], confval[i], 1);
}
poperror();
}
kproc("alarm", alarmkproc, 0);
sp = (char**)(USTKTOP - sizeof(Tos) - 8 - sizeof(sp[0])*4);
sp[3] = sp[2] = nil;
strcpy(sp[1] = (char*)&sp[4], "boot");
sp[0] = nil;
touser(sp);
}
void
userinit(void)
{
Proc *p;
Segment *s;
void *v;
Page *pg;
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);
segpage(s, pg);
v = tmpmap(pg->pa);
memset(v, 0, BY2PG);
tmpunmap(v);
s = newseg(SG_TEXT, UTZERO, 1);
s->flushme++;
p->seg[TSEG] = s;
pg = newpage(0, 0, UTZERO);
pg->txtflush = ~0;
segpage(s, pg);
v = tmpmap(pg->pa);
memset(v, 0, BY2PG);
memmove(v, initcode, sizeof(initcode));
tmpunmap(v);
ready(p);
}
void
sanity(void)
{
static int dat = 0xdeadbeef;
extern ulong vectors[];
assert(dat == 0xdeadbeef);
assert(((uintptr)vectors & 31) == 0);
assert(sizeof(Mach) + KSTACK <= MACHSIZE);
assert((KZERO & SECSZ - 1) == 0);
}
char *
getconf(char *n)
{
int i;
for(i = 0; i < nconf; i++)
if(cistrcmp(confname[i], n) == 0)
return confval[i];
return nil;
}
int
isaconfig(char *, int, ISAConf*)
{
return 0;
}
void
cpuidprint(void)
{
print("cpu%d: %dMHz ARM Cortex-A9\n", m->machno, m->cpumhz);
}
void
main(void)
{
active.machs[m->machno] = 1;
if(m->machno != 0){
uartputs("\n", 1);
mmuinit();
intrinit();
timerinit();
cpuidprint();
synccycles();
timersinit();
schedinit();
return;
}
uartinit();
mmuinit();
intrinit();
options();
confinit();
timerinit();
uartputs(" from Bell Labs\n", 16);
xinit();
printinit();
quotefmtinstall();
cpuidprint();
sanity();
todinit();
timersinit();
procinit0();
initseg();
if(delaylink)
bootlinks();
else
links();
chandevreset();
pageinit();
userinit();
schedinit();
}
void
setupwatchpts(Proc *, Watchpt *, int n)
{
if(n > 0)
error("no watchpoints");
}

127
sys/src/9/cycv/mem.h Normal file
View file

@ -0,0 +1,127 @@
/*
* Memory and machine-specific definitions. Used in C and assembler.
*/
#define MIN(a, b) ((a) < (b)? (a): (b))
#define MAX(a, b) ((a) > (b)? (a): (b))
/*
* Sizes
*/
#define BI2BY 8 /* bits per byte */
#define BI2WD 32 /* bits per word */
#define BY2WD 4 /* bytes per word */
#define BY2V 8 /* bytes per double word */
#define BY2PG 4096 /* bytes per page */
#define WD2PG (BY2PG/BY2WD) /* words per page */
#define PGSHIFT 12 /* log(BY2PG) */
#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1))
#define PGROUND(s) ROUND(s, BY2PG)
#define LINSIZ 32
#define BLOCKALIGN LINSIZ
#define FPalign 16
#define MAXMACH 2
#define KSTACK 4096
#define HZ (1000)
#define MS2HZ (1000/HZ)
#define TK2SEC(t) ((t)/HZ)
#define KZERO 0xF0000000
#define KTZERO (KZERO+0x100000)
#define TMAPSZ SECSZ
#define TMAP (KZERO - TMAPSZ)
#define KMAPSZ SECSZ
#define KMAP (TMAP - KMAPSZ)
#define NKMAP (KMAPSZ / BY2PG - 1)
#define MACHSIZE 8192
#define MACH(n) (KZERO+(n)*MACHSIZE)
#define MACHP(n) ((Mach *)MACH(n))
#define MACHL1(n) (ROUND(MACH(MAXMACH), L1SZ) + (n)*L1SZ)
#define TMAPL2(n) (MACHL1(MAXMACH) + (n) * L2SZ)
#define TMAPL2SZ (MAXMACH * L2SZ)
#define CONFSIZE 65536
#define CONFADDR (KTZERO-CONFSIZE)
#define PERIPH 0xFF000000
#define UZERO 0
#define UTZERO BY2PG
#define UTROUND(t) ROUNDUP(t, BY2PG)
#define USTKTOP 0xE0000000
#define USTKSIZE (16*1024*1024)
#define PTEMAPMEM (1024*1024)
#define PTEPERTAB (PTEMAPMEM/BY2PG)
#define SEGMAPSIZE 1984
#define SSEGMAPSIZE 16
#define PTEVALID L2VALID
#define PTERONLY L2RONLY
#define PTEWRITE L2WRITE
#define PTENOEXEC L2NOEXEC
#define PTECACHED L2CACHED
#define PTEUNCACHED L2DEVICE
#define PPN(x) ((x)&~(BY2PG-1))
#define PsrDirq (1<<7)
#define PsrDfiq (1<<6)
#define PsrMask 0x1f
#define PsrMusr 0x10
#define PsrMfiq 0x11
#define PsrMirq 0x12
#define PsrMsvc 0x13
#define PsrMabt 0x17
#define PsrMiabt 0x16 /* not an actual mode; for ureg->type */
#define PsrMund 0x1b
#define DMB WORD $0xf57ff05f
#define DSB WORD $0xf57ff04f
#define ISB WORD $0xf57ff06f
#define WFE WORD $0xe320f002
#define SEV WORD $0xe320f004
#define CPS(m) WORD $(0xf1000000|(m))
#define CPSMODE (1<<17)
#define CPSIE (3<<6|2<<18)
#define CPSID (3<<6|3<<18)
#define Rmach 10
#define Rup 9
#define VMSR(c, r1, r2) WORD $(0x0ee00a10|(c)<<28|(r2)<<16|(r1)<<12)
#define VMRS(c, r1, r2) WORD $(0x0ef00a10|(c)<<28|(r2)<<12|(r1)<<16)
#define FPSID 0x0
#define FPSCR 0x1
#define MVFR1 0x6
#define MVFR0 0x7
#define FPEXC 0x8
#define L1PT 1
#define L1SEC (2|1<<10)
#define L1DEVICE 0
#define L1CACHED (1<<16|1<<14|1<<12|1<<2)
#define L1NOEXEC (1<<4)
#define L1KERRW 0
#define L1SZ (4096*4)
#define L2SZ (256*4)
#define SECSZ 1048576
#define SECSH 20
#define NL2 256
#define L1X(va) (((ulong)(va)) >> 20)
#define L1RX(va) (((ulong)(va)) >> 20 & ~3)
#define L2X(va) (((ulong)(va)) >> 12 & 0xff)
#define L2RX(va) (((ulong)(va)) >> 12 & 0x3ff)
#define L2VALID (2|1<<4)
#define L2CACHED (1<<10|1<<8|1<<6|1<<2)
#define L2DEVICE 0
#define L2NOEXEC (1<<0)
#define L2KERRW L2KERNEL
#define L2KERNEL 0
#define L2USER (1<<5)
#define L2RONLY (1<<9)
#define L2WRITE 0
#define L2LOCAL (1<<11)
#define TTBATTR (1<<6|1<<3|1<<1)

89
sys/src/9/cycv/mkfile Normal file
View file

@ -0,0 +1,89 @@
CONF=cycv
CONFLIST=cycv
#must match mem.h
KTZERO=0xf0100020
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\
sysfile.$O\
sysproc.$O\
taslock.$O\
tod.$O\
xalloc.$O\
random.$O\
rdb.$O\
syscallfmt.$O\
OBJ=\
ltrap.$O\
l.$O\
main.$O\
mmu.$O\
trap.$O\
intr.$O\
timer.$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\
$p$CONF.u:D: $p$CONF
aux/aout2uimage $p$CONF
$p$CONF:D: $CONF.c $OBJ $LIB mkfile
$CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
$LD -o $target -T$KTZERO -l $OBJ $CONF.$O $LIB
<../boot/bootmkfile
<../port/portmkfile
<|../port/mkbootrules $CONF
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 /arm/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
install:V: $p$CONF $p$CONF.u
cp $p$CONF $p$CONF.u /$objtype/
for(i in $EXTRACOPIES)
import $i / /n/$i && cp $p$CONF $p$CONF.u /n/$i/$objtype/

376
sys/src/9/cycv/mmu.c Normal file
View file

@ -0,0 +1,376 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
void
mmuinit(void)
{
m->l1.pa = ttbget();
m->l1.va = KADDR(m->l1.pa);
memset((uchar*)TMAPL2(m->machno), 0, TMAPL2SZ);
m->l1.va[L1X(TMAP)] = PADDR(TMAPL2(m->machno)) | L1PT;
incref(&m->l1);
}
void
l1switch(L1 *p, int flush)
{
assert(!islo());
ttbput(p->pa);
if(flush){
if(++m->asid == 0)
flushtlb();
setasid(m->asid);
}
}
static L1 *
l1alloc(void)
{
L1 *p;
int s;
s = splhi();
p = m->l1free;
if(p != nil){
m->l1free = p->next;
p->next = nil;
m->nfree--;
splx(s);
return p;
}
splx(s);
p = smalloc(sizeof(L1));
for(;;){
p->va = mallocalign(L1SZ, L1SZ, 0, 0);
if(p->va != nil)
break;
if(!waserror()){
resrcwait("no memory for L1 table");
poperror();
}
}
p->pa = PADDR(p->va);
memmove(p->va, m->l1.va, L1SZ);
return p;
}
static void
l1free(L1 *l1)
{
if(islo())
panic("l1free: islo");
if(m->nfree >= 40){
free(l1->va);
free(l1);
}else{
l1->next = m->l1free;
m->l1free = l1;
m->nfree++;
}
}
static void
upallocl1(void)
{
L1 *p;
int s;
if(up->l1 != nil)
return;
p = l1alloc();
s = splhi();
if(up->l1 != nil)
panic("upalloc1: up->l1 != nil");
up->l1 = p;
l1switch(p, 1);
splx(s);
}
static void
l2free(Proc *proc)
{
ulong *t;
Page *p, **l;
if(proc->l1 == nil || proc->mmuused == nil)
return;
l = &proc->mmuused;
for(p = *l; p != nil; p = p->next){
t = proc->l1->va + p->daddr;
*t++ = 0;
*t++ = 0;
*t++ = 0;
*t = 0;
l = &p->next;
}
proc->l1->va[L1X(TMAP)] = 0;
*l = proc->mmufree;
proc->mmufree = proc->mmuused;
proc->mmuused = 0;
}
void
mmuswitch(Proc *p)
{
if(p->newtlb){
p->newtlb = 0;
l2free(p);
}
if(p->l1 != nil)
l1switch(p->l1, 1);
else
l1switch(&m->l1, 1);
}
void
putmmu(uintptr va, uintptr pa, Page *pg)
{
Page *p;
ulong *e;
ulong *l2;
ulong old;
uintptr l2p;
int s;
if(up->l1 == nil)
upallocl1();
e = &up->l1->va[L1RX(va)];
if((*e & 3) == 0){
p = up->mmufree;
if(p != nil)
up->mmufree = p->next;
else
p = newpage(0, 0, 0);
p->daddr = L1RX(va);
p->next = up->mmuused;
up->mmuused = p;
s = splhi();
l2p = p->pa;
l2 = tmpmap(l2p);
memset(l2, 0, BY2PG);
coherence();
e[0] = p->pa | L1PT;
e[1] = e[0] + L2SZ;
e[2] = e[1] + L2SZ;
e[3] = e[2] + L2SZ;
coherence();
}else{
s = splhi();
l2p = *e & ~(BY2PG - 1);
l2 = tmpmap(l2p);
}
e = &l2[L2RX(va)];
old = *e;
*e = pa | L2VALID | L2USER | L2LOCAL;
tmpunmap(l2);
splx(s);
if((old & L2VALID) != 0)
flushpg((void *) va);
if(pg->txtflush & (1<<m->machno)){
cleandse((void *) va, (void *) (va + BY2PG));
invalise((void *) va, (void *) (va + BY2PG));
pg->txtflush &= ~(1<<m->machno);
}
}
void
checkmmu(uintptr, uintptr)
{
}
void
flushmmu(void)
{
int s;
s = splhi();
up->newtlb = 1;
mmuswitch(up);
splx(s);
}
void
mmurelease(Proc *proc)
{
Page *p, *n;
if(islo())
panic("mmurelease: islo");
l1switch(&m->l1, 0);
if(proc->kmaptable != nil){
if(proc->l1 == nil)
panic("mmurelease: no l1");
if(decref(proc->kmaptable) != 0)
panic("mmurelease: kmap ref %ld", proc->kmaptable->ref);
if(proc->nkmap)
panic("mmurelease: nkmap %d", proc->nkmap);
if(PPN(proc->l1->va[L1X(KMAP)]) != proc->kmaptable->pa)
panic("mmurelease: bad kmap l2 %#.8lux kmap %#.8lux", proc->l1->va[L1X(KMAP)], proc->kmaptable->pa);
proc->l1->va[L1X(KMAP)] = 0;
pagechainhead(proc->kmaptable);
proc->kmaptable = nil;
}
if(proc->l1 != nil){
l2free(proc);
l1free(proc->l1);
proc->l1 = nil;
}
for(p = proc->mmufree; p != nil; p = n){
n = p->next;
if(decref(p) != 0)
panic("mmurelease: p->ref %ld", p->ref);
pagechainhead(p);
}
if(proc->mmufree != nil)
pagechaindone();
proc->mmufree = nil;
}
uintptr
paddr(void *v)
{
if((uintptr)v >= PERIPH)
return (uintptr)v;
if((uintptr)v >= KZERO)
return (uintptr)v-KZERO;
panic("paddr: va=%#p pc=%#p", v, getcallerpc(&v));
return 0;
}
void *
kaddr(uintptr u)
{
if(u >= (uintptr)PERIPH)
return (void *)u;
if(u < (uintptr)-KZERO)
return (void *)(u + KZERO);
panic("kaddr: pa=%#p pc=%#p", u, getcallerpc(&u));
return nil;
}
uintptr
cankaddr(uintptr u)
{
if(u >= (uintptr)PERIPH)
return -u;
if(u < (uintptr)-KZERO)
return PERIPH-KZERO - u;
return 0;
}
KMap *
kmap(Page *page)
{
ulong *e, *v;
int i, s;
if(cankaddr(page->pa))
return (KMap*)KADDR(page->pa);
if(up == nil)
panic("kmap: up=0 pc=%#.8lux", getcallerpc(&page));
if(up->l1 == nil)
upallocl1();
if(up->nkmap < 0)
panic("kmap %lud %s: nkmap=%d", up->pid, up->text, up->nkmap);
up->nkmap++;
e = &up->l1->va[L1X(KMAP)];
if((*e & 3) == 0){
if(up->kmaptable != nil)
panic("kmaptable != nil");
up->kmaptable = newpage(0, 0, 0);
s = splhi();
v = tmpmap(up->kmaptable->pa);
memset(v, 0, BY2PG);
v[0] = page->pa | L2KERRW | L2VALID | L2CACHED | L2LOCAL;
v[NKMAP] = up->kmaptable->pa | L2KERRW | L2VALID | L2CACHED | L2LOCAL;
tmpunmap(v);
splx(s);
*e = up->kmaptable->pa | L1PT;
coherence();
return (KMap *) KMAP;
}
if(up->kmaptable == nil)
panic("kmaptable == nil");
e = (ulong *) (KMAP + NKMAP * BY2PG);
for(i = 0; i < NKMAP; i++)
if((e[i] & 3) == 0){
e[i] = page->pa | L2KERRW | L2VALID | L2CACHED | L2LOCAL;
coherence();
return (KMap *) (KMAP + i * BY2PG);
}
panic("out of kmap");
return nil;
}
void
kunmap(KMap *arg)
{
uintptr va;
ulong *e;
va = (uintptr) arg;
if(va >= KZERO)
return;
if(up->l1 == nil || (up->l1->va[L1X(KMAP)] & 3) == 0)
panic("kunmap: no kmaps");
if(va < KMAP || va >= KMAP + NKMAP * BY2PG)
panic("kunmap: bad address %#.8lux pc=%#p", va, getcallerpc(&arg));
e = (ulong *) (KMAP + NKMAP * BY2PG) + L2X(va);
if((*e & 3) == 0)
panic("kunmap: not mapped %#.8lux pc=%#p", va, getcallerpc(&arg));
up->nkmap--;
if(up->nkmap < 0)
panic("kunmap %lud %s: nkmap=%d", up->pid, up->text, up->nkmap);
*e = 0;
coherence();
flushpg((void *) va);
}
void *
tmpmap(ulong pa)
{
ulong *u, *ub, *ue;
if(islo())
panic("tmpmap: islow %#p", getcallerpc(&pa));
if(cankaddr(pa))
return KADDR(pa);
ub = (ulong *) TMAPL2(m->machno);
ue = ub + NL2;
for(u = ub; u < ue; u++)
if((*u & 3) == 0){
*u = pa | L2VALID | L2CACHED | L2KERRW;
assert(m->l1.va[L1X(TMAP)] != 0);
if(up != nil && up->l1 != nil)
up->l1->va[L1X(TMAP)] = m->l1.va[L1X(TMAP)];
coherence();
return (void *) ((u - ub) * BY2PG + TMAP);
}
panic("tmpmap: full (pa=%#.8lux)", pa);
return nil;
}
void
tmpunmap(void *v)
{
ulong *u;
if(v >= (void*) KZERO)
return;
if(v < (void*)TMAP || v >= (void*)(TMAP + TMAPSZ))
panic("tmpunmap: invalid address (va=%#.8lux)", (uintptr) v);
u = (ulong *) TMAPL2(m->machno) + L2X(v);
if((*u & 3) == 0)
panic("tmpunmap: double unmap (va=%#.8lux)", (uintptr) v);
*u = 0;
coherence();
flushpg(v);
}

112
sys/src/9/cycv/timer.c Normal file
View file

@ -0,0 +1,112 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#define clockmgr ((u32int*)(CLOCKMGR_BASE))
uvlong timerhz;
enum {
TIMERDIV = 1,
LTIMERDIV = 1,
GTIMERVALL = 0x200/4,
GTIMERVALH,
GTIMERCTL,
LTIMERVAL = 0x604/4,
LTIMERCTL,
LTIMERISR,
};
void
microdelay(int n)
{
ulong now;
now = µs();
while(µs() - now < n);
}
void
delay(int n)
{
while(--n >= 0)
microdelay(1000);
}
uvlong
fastticks(uvlong *hz)
{
ulong lo, hi;
if(hz != nil)
*hz = timerhz;
do{
hi = mpcore[GTIMERVALH];
lo = mpcore[GTIMERVALL];
}while(hi != mpcore[GTIMERVALH]);
return lo | (uvlong)hi << 32;
}
ulong
µs(void)
{
return fastticks2us(fastticks(nil));
}
void
timerset(Tval v)
{
vlong w;
w = v - fastticks(nil);
if(w < 1)
w = 1;
if(w > 0xffffffffLL)
w = 0xffffffff;
mpcore[LTIMERCTL] &= ~1;
mpcore[LTIMERVAL] = w;
mpcore[LTIMERCTL] |= 1;
}
void
timerirq(Ureg *u, void *)
{
if((mpcore[LTIMERISR] & 1) != 0){
mpcore[LTIMERISR] |= 1;
timerintr(u, 0);
}
}
void
timerinit(void)
{
u32int vco;
u64int hz;
int denum, numer, mpuclk;
vco = clockmgr[0x40 / 4];
denum = vco >> 16 & 0x3f;
numer = vco >> 3 & 0x1fff;
mpuclk = clockmgr[0x48 / 4] & 0x1ff;
hz = HPS_CLK * 1000000 * (numer + 1) / ((denum + 1) * 2 * (mpuclk + 1));
m->cpumhz = (hz + 500000) / 1000000;
m->cpuhz = hz;
timerhz = m->cpuhz / 4;
mpcore[GTIMERCTL] = TIMERDIV - 1 << 8 | 3;
mpcore[LTIMERCTL] = LTIMERDIV - 1 << 8 | 4;
intrenable(TIMERIRQ, timerirq, nil, EDGE, "clock");
}
/*
* synchronize all cpu's cycle counter registers
*/
void
synccycles(void)
{
}

591
sys/src/9/cycv/trap.c Normal file
View file

@ -0,0 +1,591 @@
#include "u.h"
#include <ureg.h>
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
#include "tos.h"
static void
_dumpstack(Ureg *ureg)
{
uintptr l, v, i, estack;
extern ulong etext;
int x;
char *s;
if((s = getconf("*nodumpstack")) != nil && strcmp(s, "0") != 0){
iprint("dumpstack disabled\n");
return;
}
iprint("cpu%d: dumpstack\n", m->machno);
x = 0;
x += iprint("ktrace /arm/9cycv %.8lux %.8lux %.8lux <<EOF\n", ureg->pc, ureg->sp, ureg->r14);
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)m->stack
&& (uintptr)&l <= (uintptr)m+MACHSIZE)
estack = (uintptr)m+MACHSIZE;
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");
}
static char*
faulterr[0x20] = {
[0x01] "alignement fault",
[0x02] "debug event",
[0x04] "fault on instruction cache maintenance",
[0x08] "synchronous external abort",
[0x0C] "synchronous external abort on translation table walk L1",
[0x0E] "synchronous external abort on translation table walk L2",
[0x10] "tlb conflict abort",
[0x16] "asynchronous external abort",
[0x19] "synchronous parity error on memory access",
[0x1C] "synchronous parity error on translation table walk L1",
[0x1E] "synchronous parity error on translation table walk L2",
};
static void
faultarm(Ureg *ureg, ulong fsr, uintptr addr)
{
int user, insyscall, read;
static char buf[ERRMAX];
char *err;
read = (fsr & (1<<11)) == 0;
user = userureg(ureg);
if(!user){
if(addr >= USTKTOP || up == nil)
_dumpstack(ureg);
if(addr >= USTKTOP)
panic("kernel fault: bad address pc=%#.8lux addr=%#.8lux fsr=%#.8lux", ureg->pc, addr, fsr);
if(up == nil)
panic("kernel fault: no user process pc=%#.8lux addr=%#.8lux fsr=%#.8lux", ureg->pc, addr, fsr);
}
if(up == nil)
panic("user fault: up=nil pc=%#.8lux addr=%#.8lux fsr=%#.8lux", ureg->pc, addr, fsr);
insyscall = up->insyscall;
up->insyscall = 1;
switch(fsr & 0x1F){
case 0x05: /* translation fault L1 */
case 0x07: /* translation fault L2 */
case 0x03: /* access flag fault L1 */
case 0x06: /* access flag fault L2 */
case 0x09: /* domain fault L1 */
case 0x0B: /* domain fault L2 */
case 0x0D: /* permission fault L1 */
case 0x0F: /* permission fault L2 */
if(fault(addr, ureg->pc, read) == 0)
break;
/* wet floor */
default:
err = faulterr[fsr & 0x1F];
if(err == nil)
err = "fault";
if(!user){
dumpregs(ureg);
_dumpstack(ureg);
panic("kernel %s: pc=%#.8lux addr=%#.8lux fsr=%#.8lux", err, ureg->pc, addr, fsr);
}
sprint(buf, "sys: trap: %s %s addr=%#.8lux", err, read ? "read" : "write", addr);
postnote(up, 1, buf, NDebug);
}
up->insyscall = insyscall;
}
static void
mathtrap(Ureg *, ulong)
{
int s;
if((up->fpstate & FPillegal) != 0){
postnote(up, 1, "sys: floating point in note handler", NDebug);
return;
}
switch(up->fpstate){
case FPinit:
s = splhi();
fpinit();
up->fpstate = FPactive;
splx(s);
break;
case FPinactive:
s = splhi();
fprestore(up->fpsave);
up->fpstate = FPactive;
splx(s);
break;
case FPactive:
postnote(up, 1, "sys: floating point error", NDebug);
break;
}
}
void
trap(Ureg *ureg)
{
int user;
ulong opc, cp;
user = userureg(ureg);
if(user){
if(up == nil)
panic("user trap: up=nil");
up->dbgreg = ureg;
cycles(&up->kentry);
}
switch(ureg->type){
case PsrMund:
ureg->pc -= 4;
if(user){
spllo();
if(okaddr(ureg->pc, 4, 0)){
opc = *(ulong*)ureg->pc;
if((opc & 0x0f000000) == 0x0e000000 || (opc & 0x0e000000) == 0x0c000000){
cp = opc >> 8 & 15;
if(cp == 10 || cp == 11){
mathtrap(ureg, opc);
break;
}
}
}
postnote(up, 1, "sys: trap: invalid opcode", NDebug);
break;
}
dumpregs(ureg);
panic("invalid opcode at pc=%#.8lux lr=%#.8lux", ureg->pc, ureg->r14);
break;
case PsrMiabt:
ureg->pc -= 4;
faultarm(ureg, getifsr(), getifar());
break;
case PsrMabt:
ureg->pc -= 8;
faultarm(ureg, getdfsr(), getdfar());
break;
case PsrMirq:
ureg->pc -= 4;
intr(ureg);
break;
default:
iprint("cpu%d: unknown trap type %ulx\n", m->machno, ureg->type);
}
splhi();
if(user){
if(up->procctl || up->nnote)
notify(ureg);
kexit(ureg);
}
}
#include "../port/systab.h"
void
syscall(Ureg *ureg)
{
char *e;
uintptr sp;
long ret;
int i, s;
ulong scallnr;
vlong startns, stopns;
if(!userureg(ureg))
panic("syscall: pc=%#.8lux", ureg->pc);
cycles(&up->kentry);
m->syscall++;
up->insyscall = 1;
up->pc = ureg->pc;
up->dbgreg = ureg;
sp = ureg->sp;
up->scallnr = scallnr = ureg->r0;
spllo();
up->nerrlab = 0;
ret = -1;
if(!waserror()){
if(sp < USTKTOP - BY2PG || sp > USTKTOP - sizeof(Sargs) - BY2WD){
validaddr(sp, sizeof(Sargs)+BY2WD, 0);
evenaddr(sp);
}
up->s = *((Sargs*) (sp + BY2WD));
if(up->procctl == Proc_tracesyscall){
syscallfmt(scallnr, ureg->pc, (va_list) up->s.args);
s = splhi();
up->procctl = Proc_stopme;
procctl();
splx(s);
startns = todget(nil);
}
if(scallnr >= nsyscall || systab[scallnr] == 0){
pprint("bad sys call number %lud pc %lux", scallnr, ureg->pc);
postnote(up, 1, "sys: bad sys call", NDebug);
error(Ebadarg);
}
up->psstate = sysctab[scallnr];
ret = systab[scallnr]((va_list)up->s.args);
poperror();
}else{
e = up->syserrstr;
up->syserrstr = up->errstr;
up->errstr = e;
}
if(up->nerrlab){
print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
for(i = 0; i < NERR; i++)
print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
panic("error stack");
}
ureg->r0 = ret;
if(up->procctl == Proc_tracesyscall){
stopns = todget(nil);
sysretfmt(scallnr, (va_list) up->s.args, ret, startns, stopns);
s = splhi();
up->procctl = Proc_stopme;
procctl();
splx(s);
}
up->insyscall = 0;
up->psstate = 0;
if(scallnr == NOTED)
noted(ureg, *((ulong *) up->s.args));
if(scallnr != RFORK && (up->procctl || up->nnote)){
splhi();
notify(ureg);
}
if(up->delaysched)
sched();
kexit(ureg);
splhi();
}
int
notify(Ureg *ureg)
{
int l;
ulong s, sp;
Note *n;
if(up->procctl)
procctl();
if(up->nnote == 0)
return 0;
if(up->fpstate == FPactive){
fpsave(up->fpsave);
up->fpstate = FPinactive;
}
up->fpstate |= FPillegal;
s = spllo();
qlock(&up->debug);
up->notepending = 0;
n = &up->note[0];
if(strncmp(n->msg, "sys:", 4) == 0){
l = strlen(n->msg);
if(l > ERRMAX-15) /* " pc=0x12345678\0" */
l = ERRMAX-15;
sprint(n->msg+l, " pc=0x%.8lux", ureg->pc);
}
if(n->flag!=NUser && (up->notified || up->notify==0)){
qunlock(&up->debug);
if(n->flag == NDebug)
pprint("suicide: %s\n", n->msg);
pexit(n->msg, n->flag!=NDebug);
}
if(up->notified){
qunlock(&up->debug);
splhi();
return 0;
}
if(!up->notify){
qunlock(&up->debug);
pexit(n->msg, n->flag!=NDebug);
}
sp = ureg->sp;
sp -= 256; /* debugging: preserve context causing problem */
sp -= sizeof(Ureg);
if(!okaddr((uintptr)up->notify, 1, 0)
|| !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)
|| ((uintptr) up->notify & 3) != 0
|| (sp & 3) != 0){
qunlock(&up->debug);
pprint("suicide: bad address in notify\n");
pexit("Suicide", 0);
}
memmove((Ureg*)sp, ureg, sizeof(Ureg));
*(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
up->ureg = (void*)sp;
sp -= BY2WD+ERRMAX;
memmove((char*)sp, up->note[0].msg, ERRMAX);
sp -= 3*BY2WD;
*(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;
*(ulong*)(sp+1*BY2WD) = (ulong)up->ureg;
ureg->r0 = (uintptr) up->ureg;
ureg->sp = sp;
ureg->pc = (uintptr) up->notify;
ureg->r14 = 0;
up->notified = 1;
up->nnote--;
memmove(&up->lastnote, &up->note[0], sizeof(Note));
memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
qunlock(&up->debug);
splx(s);
return 1;
}
void
noted(Ureg *ureg, ulong arg0)
{
Ureg *nureg;
ulong oureg, sp;
qlock(&up->debug);
if(arg0 != NRSTR && !up->notified){
qunlock(&up->debug);
pprint("call to noted() when not notified\n");
pexit("Suicide", 0);
}
up->notified = 0;
nureg = up->ureg;
up->fpstate &= ~FPillegal;
oureg = (ulong) nureg;
if(!okaddr(oureg - BY2WD, BY2WD + sizeof(Ureg), 0) || (oureg & 3) != 0){
qunlock(&up->debug);
pprint("bad ureg in noted or call to noted when not notified\n");
pexit("Suicide", 0);
}
nureg->psr = nureg->psr & 0xf80f0000 | ureg->psr & 0x07f0ffff;
memmove(ureg, nureg, sizeof(Ureg));
switch(arg0){
case NCONT: case NRSTR:
if(!okaddr(nureg->pc, BY2WD, 0) || !okaddr(nureg->sp, BY2WD, 0) ||
(nureg->pc & 3) != 0 || (nureg->sp & 3) != 0){
qunlock(&up->debug);
pprint("suicide: trap in noted\n");
pexit("Suicide", 0);
}
up->ureg = (Ureg *) (*(ulong *) (oureg - BY2WD));
qunlock(&up->debug);
break;
case NSAVE:
if(!okaddr(nureg->pc, BY2WD, 0) || !okaddr(nureg->sp, BY2WD, 0) ||
(nureg->pc & 3) != 0 || (nureg->sp & 3) != 0){
qunlock(&up->debug);
pprint("suicide: trap in noted\n");
pexit("Suicide", 0);
}
qunlock(&up->debug);
sp = oureg - 4 * BY2WD - ERRMAX;
splhi();
ureg->sp = sp;
ureg->r0 = (uintptr) oureg;
((ulong *) sp)[1] = oureg;
((ulong *) sp)[0] = 0;
break;
default:
up->lastnote.flag = NDebug;
case NDFLT:
qunlock(&up->debug);
if(up->lastnote.flag == NDebug)
pprint("suicide: %s\n", up->lastnote.msg);
pexit(up->lastnote.msg, up->lastnote.flag != NDebug);
}
}
void
dumpstack(void)
{
callwithureg(_dumpstack);
}
void
dumpregs(Ureg *ureg)
{
iprint("trap: %lux psr %8.8lux type %2.2lux pc %8.8lux link %8.8lux\n",
ureg->type, ureg->psr, ureg->type, ureg->pc, ureg->link);
iprint("R14 %8.8lux R13 %8.8lux R12 %8.8lux R11 %8.8lux R10 %8.8lux\n",
ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
iprint("R9 %8.8lux R8 %8.8lux R7 %8.8lux R6 %8.8lux R5 %8.8lux\n",
ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
iprint("R4 %8.8lux R3 %8.8lux R2 %8.8lux R1 %8.8lux R0 %8.8lux\n",
ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
iprint("pc %#lux link %#lux\n", ureg->pc, ureg->link);
}
void
setkernur(Ureg *ureg, Proc *p)
{
ureg->pc = p->sched.pc;
ureg->sp = p->sched.sp + 4;
ureg->r14 = (uintptr) sched;
}
void
setregisters(Ureg* ureg, char* pureg, char* uva, int n)
{
ulong v;
v = ureg->psr;
memmove(pureg, uva, n);
ureg->psr = ureg->psr & 0xf80f0000 | v & 0x07f0ffff;
}
void
callwithureg(void (*f) (Ureg *))
{
Ureg u;
u.pc = getcallerpc(&f);
u.sp = (uintptr) &f - 4;
f(&u);
}
uintptr
userpc(void)
{
Ureg *ur;
ur = up->dbgreg;
return ur->pc;
}
uintptr
dbgpc(Proc *)
{
Ureg *ur;
ur = up->dbgreg;
if(ur == nil)
return 0;
return ur->pc;
}
void
procsave(Proc *p)
{
uvlong t;
if(p->fpstate == FPactive){
if(p->state == Moribund)
fpclear();
else
fpsave(p->fpsave);
p->fpstate = FPinactive;
}
cycles(&t);
p->kentry -= t;
p->pcycles += t;
l1switch(&m->l1, 0);
}
void
procrestore(Proc *p)
{
uvlong t;
if(p->kp)
return;
cycles(&t);
p->kentry += t;
p->pcycles -= t;
}
static void
linkproc(void)
{
spllo();
up->kpfun(up->kparg);
pexit("kproc dying", 0);
}
void
kprocchild(Proc* p, void (*func)(void*), void* arg)
{
p->sched.pc = (uintptr) linkproc;
p->sched.sp = (uintptr) p->kstack + KSTACK;
p->kpfun = func;
p->kparg = arg;
}
void
forkchild(Proc *p, Ureg *ureg)
{
Ureg *cureg;
p->sched.pc = (uintptr) forkret;
p->sched.sp = (uintptr) p->kstack + KSTACK - sizeof(Ureg);
cureg = (Ureg*) p->sched.sp;
memmove(cureg, ureg, sizeof(Ureg));
cureg->r0 = 0;
p->psstate = 0;
p->insyscall = 0;
}
uintptr
execregs(uintptr entry, ulong ssize, ulong nargs)
{
ulong *sp;
Ureg *ureg;
sp = (ulong*)(USTKTOP - ssize);
*--sp = nargs;
ureg = up->dbgreg;
ureg->sp = (uintptr) sp;
ureg->pc = entry;
ureg->r14 = 0;
return USTKTOP-sizeof(Tos);
}

243
sys/src/9/cycv/uartcycv.c Normal file
View file

@ -0,0 +1,243 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
enum {
RBR = 0,
IER,
FCR,
LCR,
MCR,
LSR,
MSR,
SCR,
IIR = FCR,
};
enum {
LSR_THRE = 1<<5,
LSR_DR = 1<<0,
ENTXIRQ = 1<<1,
ENRXIRQ = 1<<0
};
typedef struct Ctlr {
Lock;
ulong *r;
int irq, iena;
} Ctlr;
Uart* uartenable(Uart *);
extern PhysUart cycvphysuart;
static Ctlr vctlr[1] = {
{
.r = (void *) UART_BASE,
.irq = UART0IRQ,
}
};
static Uart vuart[1] = {
{
.regs = &vctlr[0],
.name = "UART1",
.freq = 25000000,
.phys = &cycvphysuart,
.console = 1,
.baud = 115200,
}
};
void
uartinit(void)
{
consuart = vuart;
}
static Uart *
vuartpnp(void)
{
return vuart;
}
static void
vuartkick(Uart *uart)
{
Ctlr *ct;
int i;
if(uart->blocked)
return;
ct = uart->regs;
if((ct->r[LSR] & LSR_THRE) == 0)
return;
for(i = 0; i < 128; i++){
if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
break;
ct->r[RBR] = *uart->op++;
}
}
static void
vuartintr(Ureg *, void *arg)
{
Uart *uart;
Ctlr *c;
int ch, f;
uart = arg;
c = uart->regs;
for(;;){
f = c->r[IIR] & 15;
switch(f){
case 6: USED(c->r[LSR]); break;
case 4: case 8:
while((c->r[LSR] & LSR_DR) != 0){
ch = c->r[RBR];
uartrecv(uart, ch);
}
break;
case 2:
vuartkick(uart);
break;
default:
return;
}
}
}
static void
vuartenable(Uart *uart, int ie)
{
Ctlr *c;
c = uart->regs;
ilock(c);
while((c->r[LSR] & LSR_THRE) == 0)
;
c->r[LCR] = 0x03;
c->r[FCR] = 0x1;
c->r[IER] = 0x0;
if(ie){
if(!c->iena){
intrenable(c->irq, vuartintr, uart, LEVEL, uart->name);
c->iena = 1;
}
c->r[IER] = ENTXIRQ | ENRXIRQ;
}
iunlock(c);
}
static int
vuartgetc(Uart *uart)
{
Ctlr *c;
c = uart->regs;
while((c->r[LSR] & LSR_DR) == 0)
;
return c->r[RBR];
}
static void
vuartputc(Uart *uart, int c)
{
Ctlr *ct;
ct = uart->regs;
while((ct->r[LSR] & LSR_THRE) == 0)
;
ct->r[RBR] = c;
return;
}
int
uartconsole(void)
{
Uart *uart = vuart;
if(up == nil)
return -1;
if(uartenable(uart) != nil){
serialoq = uart->oq;
uart->opens++;
consuart = uart;
}
return 0;
}
int
vuartbits(Uart *uart, int n)
{
Ctlr *c;
c = uart->regs;
switch(n){
case 5: c->r[LCR] = c->r[LCR] & ~3 | 0; return 0;
case 6: c->r[LCR] = c->r[LCR] & ~3 | 1; return 0;
case 7: c->r[LCR] = c->r[LCR] & ~3 | 2; return 0;
case 8: c->r[LCR] = c->r[LCR] & ~3 | 3; return 0;
default:
return -1;
}
}
int
vuartbaud(Uart *, int n)
{
print("uart baud %d\n", n);
return 0;
}
int
vuartparity(Uart *uart, int p)
{
Ctlr *c;
c = uart->regs;
switch(p){
case 'n': c->r[LCR] = c->r[LCR] & ~0x38; return 0;
case 'o': c->r[LCR] = c->r[LCR] & ~0x38 | 0x08; return 0;
case 'e': c->r[LCR] = c->r[LCR] & ~0x38 | 0x18; return 0;
default:
return -1;
}
}
void
vuartnop(Uart *, int)
{
}
int
vuartnope(Uart *, int)
{
return -1;
}
PhysUart cycvphysuart = {
.pnp = vuartpnp,
.enable = vuartenable,
.kick = vuartkick,
.getc = vuartgetc,
.putc = vuartputc,
.bits = vuartbits,
.baud = vuartbaud,
.parity = vuartparity,
.stop = vuartnope,
.rts = vuartnop,
.dtr = vuartnop,
.dobreak = vuartnop,
.fifo = vuartnop,
.power = vuartnop,
.modemctl = vuartnop,
};

View file

@ -1,5 +1,6 @@
ARCH=\
bcm\
cycv\
kw\
mtx\
omap\

View file

@ -35,7 +35,7 @@ clean:V:
mk $i.clean
%.clean:V:
rm -f $stem.c [9bz]$stem [9bz]$stem.gz s[9bz]$stem boot$stem.*
rm -f $stem.c [9bz]$stem [9bz]$stem.gz [9bz]$stem.u s[9bz]$stem boot$stem.*
nuke:V: clean
rm -f ../boot/libboot.a$O *.elf *.rr *.acid