summaryrefslogtreecommitdiff
path: root/sys/src/9/kw
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2018-02-11 18:08:03 +0100
committercinap_lenrek <cinap_lenrek@felloff.net>2018-02-11 18:08:03 +0100
commitd6e0e9c402e215dc5659ad525e3e652501f76810 (patch)
treed3157154f97516235da7c473e962b3410be46359 /sys/src/9/kw
parentdebb786fea3d6ea8018c3d83cdedfdbff0703441 (diff)
kernel: move devether and wifi to port/
the only architecture dependence of devether was enabling interrupts, which is now done at the end of the driver's reset() function now. the wifi stack and dummy ethersink also go to port/. do the IRQ2->IRQ9 hack for pc kernels in intrenabale(), so not every caller of intrenable() has to be aware of it.
Diffstat (limited to 'sys/src/9/kw')
-rw-r--r--sys/src/9/kw/archkw.c13
-rw-r--r--sys/src/9/kw/devether.c502
-rw-r--r--sys/src/9/kw/ether1116.c26
-rw-r--r--sys/src/9/kw/etherif.h55
-rw-r--r--sys/src/9/kw/ethermii.c2
-rw-r--r--sys/src/9/kw/mem.h5
-rw-r--r--sys/src/9/kw/mkfile2
-rw-r--r--sys/src/9/kw/mmu.c2
8 files changed, 21 insertions, 586 deletions
diff --git a/sys/src/9/kw/archkw.c b/sys/src/9/kw/archkw.c
index d6fd700fa..bcffd5e4c 100644
--- a/sys/src/9/kw/archkw.c
+++ b/sys/src/9/kw/archkw.c
@@ -11,7 +11,7 @@
#include "io.h"
#include "../port/netif.h"
-#include "etherif.h"
+#include "../port/etherif.h"
#include "../port/flashif.h"
#include "arm.h"
@@ -395,17 +395,6 @@ archkwlink(void)
{
}
-int
-archether(unsigned ctlno, Ether *ether)
-{
- if(ctlno >= 2)
- return -1;
- ether->type = "88e1116";
- ether->port = ctlno;
-// ether->mbps = 1000;
- return 1;
-}
-
/* LED/USB gpios */
enum {
/*
diff --git a/sys/src/9/kw/devether.c b/sys/src/9/kw/devether.c
deleted file mode 100644
index b70d85310..000000000
--- a/sys/src/9/kw/devether.c
+++ /dev/null
@@ -1,502 +0,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/error.h"
-
-#include "../port/netif.h"
-#include "etherif.h"
-
-extern int archether(unsigned ctlno, Ether *ether);
-
-static Ether *etherxx[MaxEther];
-
-Chan*
-etherattach(char* spec)
-{
- int ctlrno;
- char *p;
- Chan *chan;
-
- ctlrno = 0;
- if(spec && *spec){
- ctlrno = strtoul(spec, &p, 0);
- if((ctlrno == 0 && p == spec) || *p != 0)
- error(Ebadarg);
- if(ctlrno < 0 || ctlrno >= MaxEther)
- error(Ebadarg);
- }
- if(etherxx[ctlrno] == 0)
- error(Enodev);
-
- chan = devattach('l', spec);
- if(waserror()){
- chanfree(chan);
- nexterror();
- }
- chan->dev = ctlrno;
- if(etherxx[ctlrno]->attach)
- etherxx[ctlrno]->attach(etherxx[ctlrno]);
- poperror();
- return chan;
-}
-
-static Walkqid*
-etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
-{
- return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
-}
-
-static int
-etherstat(Chan* chan, uchar* dp, int n)
-{
- return netifstat(etherxx[chan->dev], chan, dp, n);
-}
-
-static Chan*
-etheropen(Chan* chan, int omode)
-{
- return netifopen(etherxx[chan->dev], chan, omode);
-}
-
-static Chan*
-ethercreate(Chan*, char*, int, ulong)
-{
- error(Eperm);
- return 0;
-}
-
-static void
-etherclose(Chan* chan)
-{
- netifclose(etherxx[chan->dev], chan);
-}
-
-static long
-etherread(Chan* chan, void* buf, long n, vlong off)
-{
- Ether *ether;
- ulong offset = off;
-
- ether = etherxx[chan->dev];
- if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
- /*
- * With some controllers it is necessary to reach
- * into the chip to extract statistics.
- */
- if(NETTYPE(chan->qid.path) == Nifstatqid)
- return ether->ifstat(ether, buf, n, offset);
- else if(NETTYPE(chan->qid.path) == Nstatqid)
- ether->ifstat(ether, buf, 0, offset);
- }
-
- return netifread(ether, chan, buf, n, offset);
-}
-
-static Block*
-etherbread(Chan* chan, long n, ulong offset)
-{
- return netifbread(etherxx[chan->dev], chan, n, offset);
-}
-
-static int
-etherwstat(Chan* chan, uchar* dp, int n)
-{
- return netifwstat(etherxx[chan->dev], chan, dp, n);
-}
-
-static void
-etherrtrace(Netfile* f, Etherpkt* pkt, int len)
-{
- int i, n;
- Block *bp;
-
- if(qwindow(f->in) <= 0)
- return;
- if(len > 58)
- n = 58;
- else
- n = len;
- bp = iallocb(64);
- if(bp == nil)
- return;
- memmove(bp->wp, pkt->d, n);
- i = TK2MS(MACHP(0)->ticks);
- bp->wp[58] = len>>8;
- bp->wp[59] = len;
- bp->wp[60] = i>>24;
- bp->wp[61] = i>>16;
- bp->wp[62] = i>>8;
- bp->wp[63] = i;
- bp->wp += 64;
- qpass(f->in, bp);
-}
-
-Block*
-etheriq(Ether* ether, Block* bp, int fromwire)
-{
- Etherpkt *pkt;
- ushort type;
- int len, multi, tome, fromme;
- Netfile **ep, *f, **fp, *fx;
- Block *xbp;
-
- ether->inpackets++;
-
- pkt = (Etherpkt*)bp->rp;
- len = BLEN(bp);
- type = (pkt->type[0]<<8)|pkt->type[1];
- fx = 0;
- ep = &ether->f[Ntypes];
-
- multi = pkt->d[0] & 1;
- /* check for valid multicast addresses */
- if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){
- if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
- if(fromwire){
- freeb(bp);
- bp = 0;
- }
- return bp;
- }
- }
-
- /* is it for me? */
- tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
- fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
-
- /*
- * Multiplex the packet to all the connections which want it.
- * If the packet is not to be used subsequently (fromwire != 0),
- * attempt to simply pass it into one of the connections, thereby
- * saving a copy of the data (usual case hopefully).
- */
- for(fp = ether->f; fp < ep; fp++){
- if(f = *fp)
- if(f->type == type || f->type < 0)
- if(tome || multi || f->prom){
- /* Don't want to hear loopback or bridged packets */
- if(f->bridge && (tome || !fromwire && !fromme))
- continue;
- if(!f->headersonly){
- if(fromwire && fx == 0)
- fx = f;
- else if(xbp = iallocb(len)){
- memmove(xbp->wp, pkt, len);
- xbp->wp += len;
- if(qpass(f->in, xbp) < 0)
- ether->soverflows++;
- }
- else
- ether->soverflows++;
- }
- else
- etherrtrace(f, pkt, len);
- }
- }
-
- if(fx){
- if(qpass(fx->in, bp) < 0)
- ether->soverflows++;
- return 0;
- }
- if(fromwire){
- freeb(bp);
- return 0;
- }
-
- return bp;
-}
-
-static int
-etheroq(Ether* ether, Block* bp)
-{
- int len, loopback;
- Etherpkt *pkt;
-
- ether->outpackets++;
-
- /*
- * Check if the packet has to be placed back onto the input queue,
- * i.e. if it's a loopback or broadcast packet or the interface is
- * in promiscuous mode.
- * If it's a loopback packet indicate to etheriq that the data isn't
- * needed and return, etheriq will pass-on or free the block.
- * To enable bridging to work, only packets that were originated
- * by this interface are fed back.
- */
- pkt = (Etherpkt*)bp->rp;
- len = BLEN(bp);
- loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
- if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom)
- if(etheriq(ether, bp, loopback) == 0)
- return len;
-
- qbwrite(ether->oq, bp);
- if(ether->transmit != nil)
- ether->transmit(ether);
- return len;
-}
-
-static long
-etherwrite(Chan* chan, void* buf, long n, vlong)
-{
- Ether *ether;
- Block *bp;
- int nn, onoff;
- Cmdbuf *cb;
-
- ether = etherxx[chan->dev];
- if(NETTYPE(chan->qid.path) != Ndataqid) {
- nn = netifwrite(ether, chan, buf, n);
- if(nn >= 0)
- return nn;
- cb = parsecmd(buf, n);
- if(strcmp(cb->f[0], "nonblocking") == 0){
- if(cb->nf <= 1)
- onoff = 1;
- else
- onoff = atoi(cb->f[1]);
- qnoblock(ether->oq, onoff);
- free(cb);
- return n;
- }
- free(cb);
- if(ether->ctl!=nil)
- return ether->ctl(ether,buf,n);
-
- error(Ebadctl);
- }
-
- if(n > ether->maxmtu)
- error(Etoobig);
- if(n < ether->minmtu)
- error(Etoosmall);
-
- bp = allocb(n);
- if(waserror()){
- freeb(bp);
- nexterror();
- }
- memmove(bp->rp, buf, n);
- if(!ether->f[NETID(chan->qid.path)]->bridge)
- memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
- poperror();
- bp->wp += n;
-
- return etheroq(ether, bp);
-}
-
-static long
-etherbwrite(Chan* chan, Block* bp, ulong)
-{
- Ether *ether;
- long n;
-
- n = BLEN(bp);
- if(NETTYPE(chan->qid.path) != Ndataqid){
- if(waserror()) {
- freeb(bp);
- nexterror();
- }
- n = etherwrite(chan, bp->rp, n, 0);
- poperror();
- freeb(bp);
- return n;
- }
- ether = etherxx[chan->dev];
-
- if(n > ether->maxmtu){
- freeb(bp);
- error(Etoobig);
- }
- if(n < ether->minmtu){
- freeb(bp);
- error(Etoosmall);
- }
-
- return etheroq(ether, bp);
-}
-
-static struct {
- char* type;
- int (*reset)(Ether*);
-} cards[MaxEther+1];
-
-void
-addethercard(char* t, int (*r)(Ether*))
-{
- static int ncard;
-
- if(ncard == MaxEther)
- panic("too many ether cards");
- cards[ncard].type = t;
- cards[ncard].reset = r;
- ncard++;
-}
-
-static void
-etherreset(void)
-{
- Ether *ether;
- int i, n, ctlrno;
- char name[KNAMELEN], buf[128];
-
- for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
- if(ether == 0)
- ether = malloc(sizeof(Ether));
- memset(ether, 0, sizeof(Ether));
- ether->ctlrno = ctlrno;
- ether->mbps = 10;
- ether->minmtu = ETHERMINTU;
- ether->maxmtu = ETHERMAXTU;
-
- if(archether(ctlrno, ether) <= 0)
- continue;
-
- for(n = 0; cards[n].type; n++){
- if(cistrcmp(cards[n].type, ether->type))
- continue;
- for(i = 0; i < ether->nopt; i++){
- if(cistrncmp(ether->opt[i], "ea=", 3) == 0){
- if(parseether(ether->ea, &ether->opt[i][3]) == -1)
- memset(ether->ea, 0, Eaddrlen);
- }else if(cistrcmp(ether->opt[i], "fullduplex") == 0 ||
- cistrcmp(ether->opt[i], "10BASE-TFD") == 0)
- ether->fullduplex = 1;
- else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
- ether->mbps = 100;
- }
- if(cards[n].reset(ether))
- break;
- snprint(name, sizeof(name), "ether%d", ctlrno);
-
- if(ether->interrupt != nil)
- intrenable(Irqlo, ether->irq, ether->interrupt,
- ether, name);
-
- i = snprint(buf, sizeof buf,
- "#l%d: %s: %dMbps port %#lux irq %d",
- ctlrno, ether->type, ether->mbps, ether->port,
- ether->irq);
- if(ether->mem)
- i += snprint(buf+i, sizeof buf - i,
- " addr %#lux", PADDR(ether->mem));
- if(ether->size)
- i += snprint(buf+i, sizeof buf - i,
- " size %#luX", ether->size);
- i += snprint(buf+i, sizeof buf - i,
- ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
- ether->ea[0], ether->ea[1], ether->ea[2],
- ether->ea[3], ether->ea[4], ether->ea[5]);
- snprint(buf+i, sizeof buf - i, "\n");
- print("%s", buf);
-
- if(ether->mbps >= 1000)
- netifinit(ether, name, Ntypes, 4*1024*1024);
- else if(ether->mbps >= 100)
- netifinit(ether, name, Ntypes, 1024*1024);
- else
- netifinit(ether, name, Ntypes, 65*1024);
- if(ether->oq == 0)
- ether->oq = qopen(ether->limit, Qmsg, 0, 0);
- if(ether->oq == 0)
- panic("etherreset %s", name);
- ether->alen = Eaddrlen;
- memmove(ether->addr, ether->ea, Eaddrlen);
- memset(ether->bcast, 0xFF, Eaddrlen);
-
- etherxx[ctlrno] = ether;
- ether = 0;
- break;
- }
- }
- if(ether)
- free(ether);
-}
-
-static void
-ethershutdown(void)
-{
- Ether *ether;
- int i;
-
- for(i = 0; i < MaxEther; i++){
- ether = etherxx[i];
- if(ether == nil)
- continue;
- if(ether->shutdown == nil) {
- print("#l%d: no shutdown function\n", i);
- continue;
- }
- (*ether->shutdown)(ether);
- }
-}
-
-#define POLY 0xedb88320
-
-/* really slow 32 bit crc for ethers */
-ulong
-ethercrc(uchar *p, int len)
-{
- int i, j;
- ulong crc, b;
-
- crc = 0xffffffff;
- for(i = 0; i < len; i++){
- b = *p++;
- for(j = 0; j < 8; j++){
- crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
- b >>= 1;
- }
- }
- return crc;
-}
-
-void
-dumpoq(Queue *oq)
-{
- if (oq == nil)
- print("no outq! ");
- else if (qisclosed(oq))
- print("outq closed ");
- else if (qfull(oq))
- print("outq full ");
- else
- print("outq %d ", qlen(oq));
-}
-
-void
-dumpnetif(Netif *netif)
-{
- print("netif %s ", netif->name);
- print("limit %d mbps %d link %d ",
- netif->limit, netif->mbps, netif->link);
- print("inpkts %lld outpkts %lld errs %d\n",
- netif->inpackets, netif->outpackets,
- netif->crcs + netif->oerrs + netif->frames + netif->overflows +
- netif->buffs + netif->soverflows);
-}
-
-Dev etherdevtab = {
- 'l',
- "ether",
-
- etherreset,
- devinit,
- ethershutdown,
- etherattach,
- etherwalk,
- etherstat,
- etheropen,
- ethercreate,
- etherclose,
- etherread,
- etherbread,
- etherwrite,
- etherbwrite,
- devremove,
- etherwstat,
-};
diff --git a/sys/src/9/kw/ether1116.c b/sys/src/9/kw/ether1116.c
index 9e54ef173..9987593f0 100644
--- a/sys/src/9/kw/ether1116.c
+++ b/sys/src/9/kw/ether1116.c
@@ -16,8 +16,8 @@
#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"
+#include "../port/etherif.h"
-#include "etherif.h"
#include "ethermii.h"
#include "../ip/ip.h"
@@ -144,6 +144,9 @@ struct Ctlr {
Mii *mii;
int port;
+ int linkchg; /* link status changed? */
+ uvlong starttime; /* last activity time */
+
/* stats */
ulong intrs;
ulong newintrs;
@@ -579,14 +582,16 @@ dump(uchar *bp, long max)
static void
etheractive(Ether *ether)
{
- ether->starttime = TK2MS(MACHP(0)->ticks)/1000;
+ Ctlr *ctlr = ether->ctlr;
+ ctlr->starttime = TK2MS(MACHP(0)->ticks)/1000;
}
static void
ethercheck(Ether *ether)
{
- if (ether->starttime != 0 &&
- TK2MS(MACHP(0)->ticks)/1000 - ether->starttime > Etherstuck) {
+ Ctlr *ctlr = ether->ctlr;
+ if (ctlr->starttime != 0 &&
+ TK2MS(MACHP(0)->ticks)/1000 - ctlr->starttime > Etherstuck) {
etheractive(ether);
if (ether->ctlrno == 0) /* only complain about main ether */
iprint("#l%d: ethernet stuck\n", ether->ctlrno);
@@ -833,7 +838,7 @@ interrupt(Ureg*, void *arg)
*/
if(irqe & IEphystschg) {
ether->link = (reg->ps0 & PS0linkup) != 0;
- ether->linkchg = 1;
+ ctlr->linkchg = 1;
}
if(irqe & IEtxerrq(Qno))
ether->oerrs++;
@@ -858,10 +863,10 @@ interrupt(Ureg*, void *arg)
irq &= ~(Irxerr | Irxerrq(Qno));
}
- if(ether->linkchg && (reg->ps1 & PS1an_done)) {
+ if(ctlr->linkchg && (reg->ps1 & PS1an_done)) {
handled++;
ether->link = (reg->ps0 & PS0linkup) != 0;
- ether->linkchg = 0;
+ ctlr->linkchg = 0;
}
ctlr->newintrs++;
@@ -1652,7 +1657,6 @@ ifstat(Ether *ether, void *a, long n, ulong off)
p = seprint(p, e, "transmitted broadcast frames: %lud\n", ctlr->txbcastpkt);
p = seprint(p, e, "transmitted multicast frames: %lud\n", ctlr->txmcastpkt);
p = seprint(p, e, "transmit frames dropped by collision: %lud\n", ctlr->txcollpktdrop);
- p = seprint(p, e, "misaligned buffers: %lud\n", ether->pktsmisaligned);
p = seprint(p, e, "bad mac control frames: %lud\n", ctlr->badmacctlpkts);
p = seprint(p, e, "transmitted flow control messages: %lud\n", ctlr->txflctl);
@@ -1689,7 +1693,7 @@ reset(Ether *ether)
ether->irq = IRQ0gbe1sum;
break;
default:
- panic("ether1116: bad ether ctlr #%d", ether->ctlrno);
+ return -1;
}
ctlr->reg = (Gbereg*)soc.ether[ether->ctlrno];
@@ -1728,7 +1732,6 @@ iprint("ether1116: reset: zero ether->ea\n");
ether->attach = attach;
ether->transmit = transmit;
- ether->interrupt = interrupt;
ether->ifstat = ifstat;
ether->shutdown = shutdown;
ether->ctl = ctl;
@@ -1736,6 +1739,9 @@ iprint("ether1116: reset: zero ether->ea\n");
ether->arg = ether;
ether->promiscuous = promiscuous;
ether->multicast = multicast;
+
+ intrenable(Irqlo, ether->irq, interrupt, ether, ether->name);
+
return 0;
}
diff --git a/sys/src/9/kw/etherif.h b/sys/src/9/kw/etherif.h
deleted file mode 100644
index 35d131fe3..000000000
--- a/sys/src/9/kw/etherif.h
+++ /dev/null
@@ -1,55 +0,0 @@
-enum
-{
- MaxEther = 2,
- Ntypes = 8,
-};
-
-typedef struct Ether Ether;
-struct Ether {
- RWlock; /* TO DO */
- ISAConf; /* hardware info */
- int ctlrno;
- int minmtu;
- int maxmtu;
- uchar ea[Eaddrlen];
- void *address;
- int tbusy;
-
- void (*attach)(Ether*); /* filled in by reset routine */
- void (*closed)(Ether*);
- void (*detach)(Ether*);
- void (*transmit)(Ether*);
- void (*interrupt)(Ureg*, void*);
- long (*ifstat)(Ether*, void*, long, ulong);
- long (*ctl)(Ether*, void*, long); /* custom ctl messages */
- void (*power)(Ether*, int); /* power on/off */
- void (*shutdown)(Ether*); /* shutdown hardware before reboot */
- void *ctlr;
- int pcmslot; /* PCMCIA */
- int fullduplex; /* non-zero if full duplex */
- int linkchg; /* link status changed? */
- uvlong starttime; /* last activity time */
-
- Queue* oq;
-
- /* statistics */
- ulong interrupts;
- ulong dmarxintr;
- ulong dmatxintr;
- ulong promisc;
- ulong pktsdropped;
- ulong pktsmisaligned;
- ulong resets; /* after initialisation */
- ulong bcasts; /* broadcast pkts rcv'd */
- ulong mcasts; /* multicast pkts rcv'd */
-
- Netif;
-};
-
-extern Block* etheriq(Ether*, Block*, int);
-extern void addethercard(char*, int(*)(Ether*));
-extern ulong ethercrc(uchar*, int);
-extern int parseether(uchar*, char*);
-
-#define NEXT(x, l) (((x)+1)%(l))
-#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
diff --git a/sys/src/9/kw/ethermii.c b/sys/src/9/kw/ethermii.c
index 90b219b3f..16d766ef4 100644
--- a/sys/src/9/kw/ethermii.c
+++ b/sys/src/9/kw/ethermii.c
@@ -6,8 +6,8 @@
#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"
+#include "../port/etherif.h"
-#include "etherif.h"
#include "ethermii.h"
int
diff --git a/sys/src/9/kw/mem.h b/sys/src/9/kw/mem.h
index 3cc93a381..775933bc3 100644
--- a/sys/src/9/kw/mem.h
+++ b/sys/src/9/kw/mem.h
@@ -5,9 +5,6 @@
#define MiB 1048576u /* Mebi 0x0000000000100000 */
#define GiB 1073741824u /* Gibi 000000000040000000 */
-#define HOWMANY(x, y) (((x)+((y)-1))/(y))
-#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y)) /* ceiling */
-#define ROUNDDN(x, y) (((x)/(y))*(y)) /* floor */
#define MIN(a, b) ((a) < (b)? (a): (b))
#define MAX(a, b) ((a) > (b)? (a): (b))
@@ -36,7 +33,7 @@
*/
#define BY2PG (4*KiB) /* bytes per page */
#define PGSHIFT 12 /* log(BY2PG) */
-#define PGROUND(s) ROUNDUP(s, BY2PG)
+#define PGROUND(s) ROUND(s, BY2PG)
#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
#define MAXMACH 1 /* max # cpus system can run */
diff --git a/sys/src/9/kw/mkfile b/sys/src/9/kw/mkfile
index 8134b3bb2..2f5af40d2 100644
--- a/sys/src/9/kw/mkfile
+++ b/sys/src/9/kw/mkfile
@@ -124,7 +124,7 @@ arch.$O clock.$O fpiarm.$O main.$O mmu.$O screen.$O sdscsi.$O syscall.$O \
trap.$O: /$objtype/include/ureg.h
archkw.$O devether.$O ether1116.$O ethermii.$O: \
- etherif.h ethermii.h ../port/netif.h
+ ethermii.h ../port/etherif.h ../port/netif.h
archkw.$O devflash.$O flashkw.$O: ../port/flashif.h
fpi.$O fpiarm.$O fpimem.$O: fpi.h
l.$O lexception.$O lproc.$O mmu.$O: arm.s arm.h mem.h
diff --git a/sys/src/9/kw/mmu.c b/sys/src/9/kw/mmu.c
index cd633d992..72db1fb65 100644
--- a/sys/src/9/kw/mmu.c
+++ b/sys/src/9/kw/mmu.c
@@ -465,7 +465,7 @@ vmap(uintptr pa, usize size)
o = pa & (BY2PG-1);
pa -= o;
size += o;
- size = ROUNDUP(size, BY2PG);
+ size = PGROUND(size);
va = kseg0|pa;
pae = mmukmap(va, pa, size);