add cycv kernel
This commit is contained in:
parent
826c76f90d
commit
17ebe55031
18 changed files with 3323 additions and 1 deletions
55
sys/src/9/cycv/cycv
Normal file
55
sys/src/9/cycv/cycv
Normal 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
202
sys/src/9/cycv/dat.h
Normal 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
389
sys/src/9/cycv/devarch.c
Normal 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
78
sys/src/9/cycv/fns.h
Normal 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
7
sys/src/9/cycv/init9.s
Normal 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
121
sys/src/9/cycv/intr.c
Normal 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
13
sys/src/9/cycv/io.h
Normal 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
502
sys/src/9/cycv/l.s
Normal 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
100
sys/src/9/cycv/ltrap.s
Normal 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
316
sys/src/9/cycv/main.c
Normal 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
127
sys/src/9/cycv/mem.h
Normal 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
89
sys/src/9/cycv/mkfile
Normal 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
376
sys/src/9/cycv/mmu.c
Normal 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
112
sys/src/9/cycv/timer.c
Normal 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
591
sys/src/9/cycv/trap.c
Normal 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
243
sys/src/9/cycv/uartcycv.c
Normal 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,
|
||||||
|
};
|
|
@ -1,5 +1,6 @@
|
||||||
ARCH=\
|
ARCH=\
|
||||||
bcm\
|
bcm\
|
||||||
|
cycv\
|
||||||
kw\
|
kw\
|
||||||
mtx\
|
mtx\
|
||||||
omap\
|
omap\
|
||||||
|
|
|
@ -35,7 +35,7 @@ clean:V:
|
||||||
mk $i.clean
|
mk $i.clean
|
||||||
|
|
||||||
%.clean:V:
|
%.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
|
nuke:V: clean
|
||||||
rm -f ../boot/libboot.a$O *.elf *.rr *.acid
|
rm -f ../boot/libboot.a$O *.elf *.rr *.acid
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue