/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * arm mpcore generic interrupt controller (gic) v1 * traps, exceptions, interrupts, system calls. * * there are two pieces: the interrupt distributor and the cpu interface. * * memset or memmove on any of the distributor registers generates an * exception like this one: * panic: external abort 0x28 pc 0xc048bf68 addr 0x50041800 * * we use l1 and l2 cache ops to force vectors to be visible everywhere. * * apparently irqs 0—15 (SGIs) are always enabled. */#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/error.h" #include "ureg.h"#include "arm.h" #define ISSGI(irq) ((uint)(irq) < Nsgi) enum { Debug = 0, Nvec = 8, /* # of vectors at start of lexception.s */ Bi2long = BI2BY * sizeof(long), Nirqs = 1024, Nsgi = 16, /* software-generated (inter-processor) intrs */ Nppi = 32, /* sgis + other private peripheral intrs */}; typedef struct Intrcpuregs Intrcpuregs;typedef struct Intrdistregs Intrdistregs; /* * almost this entire register set is buggered. * the distributor is supposed to be per-system, not per-cpu, * yet some registers are banked per-cpu, as marked. */struct Intrdistregs { /* distributor */ ulong ctl; ulong ctlrtype; ulong distid; uchar _pad0[0x80 - 0xc]; /* botch: *[0] are banked per-cpu from here */ /* bit maps */ ulong grp[32]; /* in group 1 (non-secure) */ ulong setena[32]; /* forward to cpu interfaces */ ulong clrena[32]; ulong setpend[32]; ulong clrpend[32]; ulong setact[32]; /* active? */ ulong clract[32]; /* botch: *[0] are banked per-cpu until here */ uchar pri[1020]; /* botch: pri[0] — pri[7] are banked per-cpu */ ulong _rsrvd1; /* botch: targ[0] through targ[7] are banked per-cpu and RO */ uchar targ[1020]; /* byte bit maps: cpu targets indexed by intr */ ulong _rsrvd2; /* botch: cfg[1] is banked per-cpu */ ulong cfg[64]; /* bit pairs: edge? 1-N? */ ulong _pad1[64]; ulong nsac[64]; /* bit pairs (v2 only) */ /* software-generated intrs (a.k.a. sgi) */ ulong swgen; /* intr targets */ uchar _pad2[0xf10 - 0xf04]; uchar clrsgipend[16]; /* bit map (v2 only) */ uchar setsgipend[16]; /* bit map (v2 only) */}; enum { /* ctl bits */ Forw2cpuif = 1, /* ctlrtype bits */ Cpunoshft = 5, Cpunomask = MASK(3), Intrlines = MASK(5), /* cfg bits */ Level = 0<<1, Edge = 1<<1, /* edge-, not level-sensitive */ Toall = 0<<0, To1 = 1<<0, /* vs. to all */ /* swgen bits */ Totargets = 0, Tonotme = 1<<24, Tome = 2<<24,}; /* each cpu sees its own registers at the same base address (soc.intr) */struct Intrcpuregs { ulong ctl; ulong primask; ulong binpt; /* group pri vs subpri split */ ulong ack; ulong end; ulong runpri; ulong hipripend; /* aliased regs (secure, for group 1) */ ulong alibinpt; ulong aliack; /* (v2 only) */ ulong aliend; /* (v2 only) */ ulong alihipripend; /* (v2 only) */ uchar _pad0[0xd0 - 0x2c]; ulong actpri[4]; /* (v2 only) */ ulong nsactpri[4]; /* (v2 only) */ uchar _pad0[0xfc - 0xf0]; ulong ifid; /* ro */ uchar _pad0[0x1000 - 0x100]; ulong deact; /* wo (v2 only) */}; enum { /* ctl bits */ Enable = 1, Eoinodeact = 1<<9, /* (v2 only) */ /* (ali) ack/end/hipriend/deact bits */ Intrmask = MASK(10), Cpuidshift = 10, Cpuidmask = MASK(3), /* ifid bits */ Archversshift = 16, Archversmask = MASK(4),}; typedef struct Vctl Vctl;typedef struct Vctl { Vctl* next; /* handlers on this vector */ char *name; /* of driver, xallocated */ void (*f)(Ureg*, void*); /* handler to call */ void* a; /* argument to call it with */} Vctl; static Lock vctllock;static Vctl* vctl[Nirqs]; /* * Layout at virtual address 0. */typedef struct Vpage0 { void (*vectors[Nvec])(void); u32int vtable[Nvec];} Vpage0; enum{ Ntimevec = 20 /* number of time buckets for each intr */};ulong intrtimes[Nirqs][Ntimevec]; uvlong ninterrupt;uvlong ninterruptticks;int irqtooearly = 1; static ulong shadena[32]; /* copy of enable bits, saved by intcmaskall */static Lock distlock, nintrlock; extern int notify(Ureg*); static void dumpstackwithureg(Ureg *ureg); voidprintrs(int base, ulong word){ int bit; for (bit = 0; word; bit++, word >>= 1) if (word & 1) iprint(" %d", base + bit);} voiddumpintrs(char *what, ulong *bits){ int i, first, some; ulong word; Intrdistregs *idp = (Intrdistregs *)soc.intrdist; first = 1; some = 0; USED(idp); for (i = 0; i < nelem(idp->setpend); i++) { word = bits[i]; if (word) { if (first) { first = 0; iprint("%s", what); } some = 1; printrs(i * Bi2long, word); } } if (!some) iprint("%s none", what); iprint("\n");} voiddumpintrpend(void){ Intrdistregs *idp = (Intrdistregs *)soc.intrdist; iprint("\ncpu%d gic regs:\n", m->machno); dumpintrs("group 1", idp->grp); dumpintrs("enabled", idp->setena); dumpintrs("pending", idp->setpend); dumpintrs("active ", idp->setact);} /* * keep histogram of interrupt service times */voidintrtime(Mach*, int vno){ ulong diff; ulong x; x = perfticks(); diff = x - m->perf.intrts; m->perf.intrts = x; m->perf.inintr += diff; if(up == nil && m->perf.inidle > diff) m->perf.inidle -= diff; if (m->cpumhz == 0) return; /* don't divide by zero */ diff /= m->cpumhz*100; /* quantum = 100µsec */ if(diff >= Ntimevec) diff = Ntimevec-1; if ((uint)vno >= Nirqs) vno = Nirqs-1; intrtimes[vno][diff]++;} static ulongintack(Intrcpuregs *icp){ return icp->ack & Intrmask;} static voidintdismiss(Intrcpuregs *icp, ulong ack){ icp->end = ack; coherence();} static intirqinuse(uint irq){ Intrdistregs *idp = (Intrdistregs *)soc.intrdist; return idp->setena[irq / Bi2long] & (1 << (irq % Bi2long));} voidintcunmask(uint irq){ Intrdistregs *idp = (Intrdistregs *)soc.intrdist; ilock(&distlock); idp->setena[irq / Bi2long] = 1 << (irq % Bi2long); iunlock(&distlock);} voidintcmask(uint irq){ Intrdistregs *idp = (Intrdistregs *)soc.intrdist; ilock(&distlock); idp->clrena[irq / Bi2long] = 1 << (irq % Bi2long); iunlock(&distlock);} static voidintcmaskall(Intrdistregs *idp) /* mask all intrs for all cpus */{ int i; for (i = 0; i < nelem(idp->setena); i++) shadena[i] = idp->setena[i]; for (i = 0; i < nelem(idp->clrena); i++) idp->clrena[i] = ~0; coherence();} static voidintcunmaskall(Intrdistregs *idp) /* unused */{ int i; for (i = 0; i < nelem(idp->setena); i++) idp->setena[i] = shadena[i]; coherence();} static ulongpermintrs(Intrdistregs *idp, int base, int r){ ulong perms; idp->clrena[r] = ~0; /* disable all */ coherence(); perms = idp->clrena[r]; if (perms) { iprint("perm intrs:"); printrs(base, perms); iprint("\n"); } return perms;} static voidintrcfg(Intrdistregs *idp){ int i, cpumask; ulong pat; /* set up all interrupts as level-sensitive, to one cpu (0) */ pat = 0; for (i = 0; i < Bi2long; i += 2) pat |= (Level | To1) << i; if (m->machno == 0) { /* system-wide & cpu0 cfg */ for (i = 0; i < nelem(idp->grp); i++) idp->grp[i] = 0; /* secure */ for (i = 0; i < nelem(idp->pri); i++) idp->pri[i] = 0; /* highest priority */ /* set up all interrupts as level-sensitive, to one cpu (0) */ for (i = 0; i < nelem(idp->cfg); i++) idp->cfg[i] = pat; /* first Nppi are read-only for SGIs and PPIs */ cpumask = 1<<0; /* just cpu 0 */ navailcpus = getncpus(); for (i = Nppi; i < sizeof idp->targ; i++) idp->targ[i] = cpumask; coherence(); intcmaskall(idp); for (i = 0; i < nelem(idp->clrena); i++) { // permintrs(idp, i * Bi2long, i); idp->clrpend[i] = idp->clract[i] = idp->clrena[i] = ~0; } } else { /* per-cpu config */ idp->grp[0] = 0; /* secure */ for (i = 0; i < 8; i++) idp->pri[i] = 0; /* highest priority */ /* idp->targ[0 through Nppi-1] are supposed to be read-only */ for (i = 0; i < Nppi; i++) idp->targ[i] = 1<<m->machno; idp->cfg[1] = pat; coherence(); // permintrs(idp, i * Bi2long, i); idp->clrpend[0] = idp->clract[0] = idp->clrena[0] = ~0; /* on cpu1, irq Extpmuirq (118) is always pending here */ } coherence();} voidintrto(int cpu, int irq){ Intrdistregs *idp = (Intrdistregs *)soc.intrdist; /* first Nppi are read-only for SGIs and the like */ ilock(&distlock); idp->targ[irq] = 1 << cpu; iunlock(&distlock);} voidintrsto(int cpu) /* unused */{ int i; Intrdistregs *idp = (Intrdistregs *)soc.intrdist; /* first Nppi are read-only for SGIs and the like */ for (i = Nppi; i < sizeof idp->targ; i++) intrto(cpu, i); USED(idp);} voidintrcpu(int cpu){ Intrdistregs *idp = (Intrdistregs *)soc.intrdist; ilock(&distlock); idp->swgen = Totargets | 1 << (cpu + 16) | m->machno; iunlock(&distlock);} /* * set up for exceptions */voidtrapinit(void){ int s; Intrdistregs *idp = (Intrdistregs *)soc.intrdist; Intrcpuregs *icp = (Intrcpuregs *)soc.intr; Vpage0 *vpage0; enum { Vecsize = sizeof vpage0->vectors + sizeof vpage0->vtable, }; /* * set up the exception vectors, high and low. * * we can't use cache ops on HVECTORS address, since they * work on virtual addresses, and only those that have a * physical address == PADDR(virtual). */ if (m->machno == 0) { vpage0 = (Vpage0*)HVECTORS; memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors)); memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable)); vpage0 = (Vpage0*)KADDR(0); memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors)); memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable)); allcache->wbse(vpage0, Vecsize); cacheiinv(); } /* * set up the stack pointers for the exception modes for this cpu. * they point to small `save areas' in Mach, not actual stacks. */ s = splhi(); /* make these modes ignore intrs too */ setr13(PsrMfiq, m->sfiq); setr13(PsrMirq, m->sirq); setr13(PsrMmon, m->smon); setr13(PsrMabt, m->sabt); setr13(PsrMund, m->sund); setr13(PsrMsys, m->ssys); splx(s); assert((idp->distid & MASK(12)) == 0x43b); /* made by arm */ assert((icp->ifid & MASK(12)) == 0x43b); /* made by arm */ ilock(&distlock); idp->ctl = 0; icp->ctl = 0; coherence(); intrcfg(idp); /* some per-cpu cfg here */ icp->ctl = Enable; icp->primask = (uchar)~0; /* let all priorities through */ coherence(); idp->ctl = Forw2cpuif; iunlock(&distlock);} voidintrsoff(void){ ilock(&distlock); intcmaskall((Intrdistregs *)soc.intrdist); iunlock(&distlock);} voidintrcpushutdown(void){ Intrcpuregs *icp = (Intrcpuregs *)soc.intr; icp->ctl = 0; icp->primask = 0; /* let no priorities through */Lines 1–500 of 1094. Load more
/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * arm mpcore generic interrupt controller (gic) v1 * traps, exceptions, interrupts, system calls. * * there are two pieces: the interrupt distributor and the cpu interface. * * memset or memmove on any of the distributor registers generates an * exception like this one: * panic: external abort 0x28 pc 0xc048bf68 addr 0x50041800 * * we use l1 and l2 cache ops to force vectors to be visible everywhere. * * apparently irqs 0—15 (SGIs) are always enabled. */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "ureg.h" #include "arm.h" #define ISSGI(irq) ((uint)(irq) < Nsgi) enum { Debug = 0, Nvec = 8, /* # of vectors at start of lexception.s */ Bi2long = BI2BY * sizeof(long), Nirqs = 1024, Nsgi = 16, /* software-generated (inter-processor) intrs */ Nppi = 32, /* sgis + other private peripheral intrs */ }; typedef struct Intrcpuregs Intrcpuregs; typedef struct Intrdistregs Intrdistregs; /* * almost this entire register set is buggered. * the distributor is supposed to be per-system, not per-cpu, * yet some registers are banked per-cpu, as marked. */ struct Intrdistregs { /* distributor */ ulong ctl; ulong ctlrtype; ulong distid; uchar _pad0[0x80 - 0xc]; /* botch: *[0] are banked per-cpu from here */ /* bit maps */ ulong grp[32]; /* in group 1 (non-secure) */ ulong setena[32]; /* forward to cpu interfaces */ ulong clrena[32]; ulong setpend[32]; ulong clrpend[32]; ulong setact[32]; /* active? */ ulong clract[32]; /* botch: *[0] are banked per-cpu until here */ uchar pri[1020]; /* botch: pri[0] — pri[7] are banked per-cpu */ ulong _rsrvd1; /* botch: targ[0] through targ[7] are banked per-cpu and RO */ uchar targ[1020]; /* byte bit maps: cpu targets indexed by intr */ ulong _rsrvd2; /* botch: cfg[1] is banked per-cpu */ ulong cfg[64]; /* bit pairs: edge? 1-N? */ ulong _pad1[64]; ulong nsac[64]; /* bit pairs (v2 only) */ /* software-generated intrs (a.k.a. sgi) */ ulong swgen; /* intr targets */ uchar _pad2[0xf10 - 0xf04]; uchar clrsgipend[16]; /* bit map (v2 only) */ uchar setsgipend[16]; /* bit map (v2 only) */ }; enum { /* ctl bits */ Forw2cpuif = 1, /* ctlrtype bits */ Cpunoshft = 5, Cpunomask = MASK(3), Intrlines = MASK(5), /* cfg bits */ Level = 0<<1, Edge = 1<<1, /* edge-, not level-sensitive */ Toall = 0<<0, To1 = 1<<0, /* vs. to all */ /* swgen bits */ Totargets = 0, Tonotme = 1<<24, Tome = 2<<24, }; /* each cpu sees its own registers at the same base address (soc.intr) */ struct Intrcpuregs { ulong ctl; ulong primask; ulong binpt; /* group pri vs subpri split */ ulong ack; ulong end; ulong runpri; ulong hipripend; /* aliased regs (secure, for group 1) */ ulong alibinpt; ulong aliack; /* (v2 only) */ ulong aliend; /* (v2 only) */ ulong alihipripend; /* (v2 only) */ uchar _pad0[0xd0 - 0x2c]; ulong actpri[4]; /* (v2 only) */ ulong nsactpri[4]; /* (v2 only) */ uchar _pad0[0xfc - 0xf0]; ulong ifid; /* ro */ uchar _pad0[0x1000 - 0x100]; ulong deact; /* wo (v2 only) */ }; enum { /* ctl bits */ Enable = 1, Eoinodeact = 1<<9, /* (v2 only) */ /* (ali) ack/end/hipriend/deact bits */ Intrmask = MASK(10), Cpuidshift = 10, Cpuidmask = MASK(3), /* ifid bits */ Archversshift = 16, Archversmask = MASK(4), }; typedef struct Vctl Vctl; typedef struct Vctl { Vctl* next; /* handlers on this vector */ char *name; /* of driver, xallocated */ void (*f)(Ureg*, void*); /* handler to call */ void* a; /* argument to call it with */ } Vctl; static Lock vctllock; static Vctl* vctl[Nirqs]; /* * Layout at virtual address 0. */ typedef struct Vpage0 { void (*vectors[Nvec])(void); u32int vtable[Nvec]; } Vpage0; enum { Ntimevec = 20 /* number of time buckets for each intr */ }; ulong intrtimes[Nirqs][Ntimevec]; uvlong ninterrupt; uvlong ninterruptticks; int irqtooearly = 1; static ulong shadena[32]; /* copy of enable bits, saved by intcmaskall */ static Lock distlock, nintrlock; extern int notify(Ureg*); static void dumpstackwithureg(Ureg *ureg); void printrs(int base, ulong word) { int bit; for (bit = 0; word; bit++, word >>= 1) if (word & 1) iprint(" %d", base + bit); } void dumpintrs(char *what, ulong *bits) { int i, first, some; ulong word; Intrdistregs *idp = (Intrdistregs *)soc.intrdist; first = 1; some = 0; USED(idp); for (i = 0; i < nelem(idp->setpend); i++) { word = bits[i]; if (word) { if (first) { first = 0; iprint("%s", what); } some = 1; printrs(i * Bi2long, word); } } if (!some) iprint("%s none", what); iprint("\n"); } void dumpintrpend(void) { Intrdistregs *idp = (Intrdistregs *)soc.intrdist; iprint("\ncpu%d gic regs:\n", m->machno); dumpintrs("group 1", idp->grp); dumpintrs("enabled", idp->setena); dumpintrs("pending", idp->setpend); dumpintrs("active ", idp->setact); } /* * keep histogram of interrupt service times */ void intrtime(Mach*, int vno) { ulong diff; ulong x; x = perfticks(); diff = x - m->perf.intrts; m->perf.intrts = x; m->perf.inintr += diff; if(up == nil && m->perf.inidle > diff) m->perf.inidle -= diff; if (m->cpumhz == 0) return; /* don't divide by zero */ diff /= m->cpumhz*100; /* quantum = 100µsec */ if(diff >= Ntimevec) diff = Ntimevec-1; if ((uint)vno >= Nirqs) vno = Nirqs-1; intrtimes[vno][diff]++; } static ulong intack(Intrcpuregs *icp) { return icp->ack & Intrmask; } static void intdismiss(Intrcpuregs *icp, ulong ack) { icp->end = ack; coherence(); } static int irqinuse(uint irq) { Intrdistregs *idp = (Intrdistregs *)soc.intrdist; return idp->setena[irq / Bi2long] & (1 << (irq % Bi2long)); } void intcunmask(uint irq) { Intrdistregs *idp = (Intrdistregs *)soc.intrdist; ilock(&distlock); idp->setena[irq / Bi2long] = 1 << (irq % Bi2long); iunlock(&distlock); } void intcmask(uint irq) { Intrdistregs *idp = (Intrdistregs *)soc.intrdist; ilock(&distlock); idp->clrena[irq / Bi2long] = 1 << (irq % Bi2long); iunlock(&distlock); } static void intcmaskall(Intrdistregs *idp) /* mask all intrs for all cpus */ { int i; for (i = 0; i < nelem(idp->setena); i++) shadena[i] = idp->setena[i]; for (i = 0; i < nelem(idp->clrena); i++) idp->clrena[i] = ~0; coherence(); } static void intcunmaskall(Intrdistregs *idp) /* unused */ { int i; for (i = 0; i < nelem(idp->setena); i++) idp->setena[i] = shadena[i]; coherence(); } static ulong permintrs(Intrdistregs *idp, int base, int r) { ulong perms; idp->clrena[r] = ~0; /* disable all */ coherence(); perms = idp->clrena[r]; if (perms) { iprint("perm intrs:"); printrs(base, perms); iprint("\n"); } return perms; } static void intrcfg(Intrdistregs *idp) { int i, cpumask; ulong pat; /* set up all interrupts as level-sensitive, to one cpu (0) */ pat = 0; for (i = 0; i < Bi2long; i += 2) pat |= (Level | To1) << i; if (m->machno == 0) { /* system-wide & cpu0 cfg */ for (i = 0; i < nelem(idp->grp); i++) idp->grp[i] = 0; /* secure */ for (i = 0; i < nelem(idp->pri); i++) idp->pri[i] = 0; /* highest priority */ /* set up all interrupts as level-sensitive, to one cpu (0) */ for (i = 0; i < nelem(idp->cfg); i++) idp->cfg[i] = pat; /* first Nppi are read-only for SGIs and PPIs */ cpumask = 1<<0; /* just cpu 0 */ navailcpus = getncpus(); for (i = Nppi; i < sizeof idp->targ; i++) idp->targ[i] = cpumask; coherence(); intcmaskall(idp); for (i = 0; i < nelem(idp->clrena); i++) { // permintrs(idp, i * Bi2long, i); idp->clrpend[i] = idp->clract[i] = idp->clrena[i] = ~0; } } else { /* per-cpu config */ idp->grp[0] = 0; /* secure */ for (i = 0; i < 8; i++) idp->pri[i] = 0; /* highest priority */ /* idp->targ[0 through Nppi-1] are supposed to be read-only */ for (i = 0; i < Nppi; i++) idp->targ[i] = 1<<m->machno; idp->cfg[1] = pat; coherence(); // permintrs(idp, i * Bi2long, i); idp->clrpend[0] = idp->clract[0] = idp->clrena[0] = ~0; /* on cpu1, irq Extpmuirq (118) is always pending here */ } coherence(); } void intrto(int cpu, int irq) { Intrdistregs *idp = (Intrdistregs *)soc.intrdist; /* first Nppi are read-only for SGIs and the like */ ilock(&distlock); idp->targ[irq] = 1 << cpu; iunlock(&distlock); } void intrsto(int cpu) /* unused */ { int i; Intrdistregs *idp = (Intrdistregs *)soc.intrdist; /* first Nppi are read-only for SGIs and the like */ for (i = Nppi; i < sizeof idp->targ; i++) intrto(cpu, i); USED(idp); } void intrcpu(int cpu) { Intrdistregs *idp = (Intrdistregs *)soc.intrdist; ilock(&distlock); idp->swgen = Totargets | 1 << (cpu + 16) | m->machno; iunlock(&distlock); } /* * set up for exceptions */ void trapinit(void) { int s; Intrdistregs *idp = (Intrdistregs *)soc.intrdist; Intrcpuregs *icp = (Intrcpuregs *)soc.intr; Vpage0 *vpage0; enum { Vecsize = sizeof vpage0->vectors + sizeof vpage0->vtable, }; /* * set up the exception vectors, high and low. * * we can't use cache ops on HVECTORS address, since they * work on virtual addresses, and only those that have a * physical address == PADDR(virtual). */ if (m->machno == 0) { vpage0 = (Vpage0*)HVECTORS; memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors)); memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable)); vpage0 = (Vpage0*)KADDR(0); memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors)); memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable)); allcache->wbse(vpage0, Vecsize); cacheiinv(); } /* * set up the stack pointers for the exception modes for this cpu. * they point to small `save areas' in Mach, not actual stacks. */ s = splhi(); /* make these modes ignore intrs too */ setr13(PsrMfiq, m->sfiq); setr13(PsrMirq, m->sirq); setr13(PsrMmon, m->smon); setr13(PsrMabt, m->sabt); setr13(PsrMund, m->sund); setr13(PsrMsys, m->ssys); splx(s); assert((idp->distid & MASK(12)) == 0x43b); /* made by arm */ assert((icp->ifid & MASK(12)) == 0x43b); /* made by arm */ ilock(&distlock); idp->ctl = 0; icp->ctl = 0; coherence(); intrcfg(idp); /* some per-cpu cfg here */ icp->ctl = Enable; icp->primask = (uchar)~0; /* let all priorities through */ coherence(); idp->ctl = Forw2cpuif; iunlock(&distlock); } void intrsoff(void) { ilock(&distlock); intcmaskall((Intrdistregs *)soc.intrdist); iunlock(&distlock); } void intrcpushutdown(void) { Intrcpuregs *icp = (Intrcpuregs *)soc.intr; icp->ctl = 0; icp->primask = 0; /* let no priorities through */