Make shmif memory access slightly more sane. Create a header which

is shared by the interface and the bus analyzer.
This commit is contained in:
pooka 2010-08-12 17:33:55 +00:00
parent 7049a3dc1c
commit 36e63e6874
3 changed files with 81 additions and 48 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: dumpbus.c,v 1.2 2010/08/12 17:00:41 pooka Exp $ */
/* $NetBSD: dumpbus.c,v 1.3 2010/08/12 17:33:55 pooka Exp $ */
/*
* Little utility to convert shmif bus traffic to a pcap file
@ -9,6 +9,7 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <assert.h>
#include <err.h>
#include <fcntl.h>
#include <pcap.h>
@ -17,13 +18,7 @@
#include <string.h>
#include <unistd.h>
/* XXX: sync with driver */
struct bushdr {
uint32_t lock;
uint32_t gen;
uint32_t last;
uint32_t version;
};
#include "shmifvar.h"
static void
usage(void)
@ -40,8 +35,9 @@ main(int argc, char *argv[])
void *busmem;
const char *pcapfile = NULL;
uint8_t *curbus, *buslast;
struct bushdr *bhdr;
struct shmif_mem *bmem;
int fd, pfd, i, ch;
uint32_t pktlen;
while ((ch = getopt(argc, argv, "p:")) != -1) {
switch (ch) {
@ -70,13 +66,13 @@ main(int argc, char *argv[])
if (busmem == MAP_FAILED)
err(1, "mmap");
bhdr = busmem;
if (bhdr->version != 1)
errx(1, "cannot handle bus version %d", bhdr->version);
bmem = busmem;
if (bmem->shm_version != 1)
errx(1, "cannot handle bus version %d", bmem->shm_version);
printf("bus version %d, lock: %d, generation: %d, lastoff: 0x%x\n",
bhdr->version, bhdr->lock, bhdr->gen, bhdr->last);
bmem->shm_version, bmem->shm_lock, bmem->shm_gen, bmem->shm_last);
if (bhdr->gen != 0) {
if (bmem->shm_gen != 0) {
printf("this dumper can manage only generation 0, sorry\n");
exit(0);
}
@ -99,13 +95,12 @@ main(int argc, char *argv[])
err(1, "phdr write");
}
curbus = busmem;
buslast = curbus + bhdr->last;
curbus += sizeof(*bhdr);
curbus = bmem->shm_data;
buslast = bmem->shm_data + bmem->shm_last;
assert(sizeof(pktlen) == PKTLEN_SIZE);
i = 0;
while (curbus <= buslast) {
uint32_t pktlen;
struct pcap_pkthdr packhdr;
pktlen = *(uint32_t *)curbus;
@ -116,7 +111,7 @@ main(int argc, char *argv[])
continue;
printf("packet %d, offset 0x%x, length 0x%x\n",
i++, curbus - (uint8_t *)(bhdr + 1), pktlen);
i++, curbus - (uint8_t *)(bmem + 1), pktlen);
if (!pcapfile || pktlen == 0) {
curbus += pktlen;

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_shmem.c,v 1.15 2010/08/11 12:10:39 pooka Exp $ */
/* $NetBSD: if_shmem.c,v 1.16 2010/08/12 17:33:55 pooka Exp $ */
/*
* Copyright (c) 2009 Antti Kantee. All Rights Reserved.
@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_shmem.c,v 1.15 2010/08/11 12:10:39 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_shmem.c,v 1.16 2010/08/12 17:33:55 pooka Exp $");
#include <sys/param.h>
#include <sys/atomic.h>
@ -66,27 +66,20 @@ static int shmif_ioctl(struct ifnet *, u_long, void *);
static void shmif_start(struct ifnet *);
static void shmif_stop(struct ifnet *, int);
#include "shmifvar.h"
struct shmif_sc {
struct ethercom sc_ec;
uint8_t sc_myaddr[6];
uint8_t *sc_busmem;
struct shmif_mem *sc_busmem;
int sc_memfd;
int sc_kq;
uint32_t sc_nextpacket;
uint32_t sc_prevgen;
};
#define IFMEM_LOCK (0x00)
#define IFMEM_GENERATION (0x04)
#define IFMEM_LASTPACKET (0x08)
#define IFMEM_WAKEUP (0x0c)
#define IFMEM_BUSVERSION IFMEM_WAKEUP
#define IFMEM_DATA (0x10)
#define BUSCTRL_ATOFF(sc, off) ((uint32_t *)(sc->sc_busmem+(off)))
#define BUSMEM_SIZE (1024*1024) /* need write throttling? */
#define PKTLEN_SIZE 4
/* just in case ... */
static const uint32_t busversion = 1;
@ -107,7 +100,7 @@ static void
lockbus(struct shmif_sc *sc)
{
while (atomic_cas_32((uint32_t *)sc->sc_busmem,
while (atomic_cas_32(&sc->sc_busmem->shm_lock,
LOCK_UNLOCKED, LOCK_LOCKED) == LOCK_LOCKED)
continue;
membar_enter();
@ -119,7 +112,7 @@ unlockbus(struct shmif_sc *sc)
unsigned int old;
membar_exit();
old = atomic_swap_32((uint32_t *)sc->sc_busmem, LOCK_UNLOCKED);
old = atomic_swap_32(&sc->sc_busmem->shm_lock, LOCK_UNLOCKED);
KASSERT(old == LOCK_LOCKED);
}
@ -130,7 +123,7 @@ busread(struct shmif_sc *sc, void *dest, uint32_t off, size_t len)
KASSERT(len < (BUSMEM_SIZE - IFMEM_DATA) && off <= BUSMEM_SIZE);
chunk = MIN(len, BUSMEM_SIZE - off);
memcpy(dest, sc->sc_busmem + off, chunk);
memcpy(dest, (uint8_t *)sc->sc_busmem + off, chunk);
len -= chunk;
if (len == 0)
@ -138,10 +131,10 @@ busread(struct shmif_sc *sc, void *dest, uint32_t off, size_t len)
/* else, wraps around */
off = IFMEM_DATA;
sc->sc_prevgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION);
sc->sc_prevgen = sc->sc_busmem->shm_gen;
/* finish reading */
memcpy((uint8_t *)dest + chunk, sc->sc_busmem + off, len);
memcpy((uint8_t *)dest + chunk, (uint8_t *)sc->sc_busmem + off, len);
return off + len;
}
@ -154,7 +147,7 @@ buswrite(struct shmif_sc *sc, uint32_t off, void *data, size_t len)
&& off >= IFMEM_DATA);
chunk = MIN(len, BUSMEM_SIZE - off);
memcpy(sc->sc_busmem + off, data, chunk);
memcpy((uint8_t *)sc->sc_busmem + off, data, chunk);
len -= chunk;
if (len == 0)
@ -165,11 +158,11 @@ buswrite(struct shmif_sc *sc, uint32_t off, void *data, size_t len)
/* else, wraps around */
off = IFMEM_DATA;
(*BUSCTRL_ATOFF(sc, IFMEM_GENERATION))++;
sc->sc_prevgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION);
sc->sc_prevgen = sc->sc_busmem->shm_gen;
sc->sc_busmem->shm_gen++;
/* finish writing */
memcpy(sc->sc_busmem + off, (uint8_t *)data + chunk, len);
memcpy((uint8_t *)sc->sc_busmem + off, (uint8_t *)data + chunk, len);
return off + len;
}
@ -224,10 +217,10 @@ rump_shmif_create(const char *path, int *ifnum)
goto fail;
lockbus(sc);
if (*BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET) == 0)
*BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET) = IFMEM_DATA;
sc->sc_nextpacket = *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET);
sc->sc_prevgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION);
if (sc->sc_busmem->shm_last == 0)
sc->sc_busmem->shm_last = IFMEM_DATA;
sc->sc_nextpacket = sc->sc_busmem->shm_last;
sc->sc_prevgen = sc->sc_busmem->shm_gen;
unlockbus(sc);
sc->sc_kq = rumpuser_writewatchfile_setup(-1, sc->sc_memfd, 0, &error);
@ -306,7 +299,7 @@ shmif_start(struct ifnet *ifp)
}
lockbus(sc);
lastoff = *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET);
lastoff = sc->sc_busmem->shm_last;
npktlenoff = nextpktoff(sc, lastoff);
dataoff = advance(npktlenoff, PKTLEN_SIZE);
@ -317,7 +310,7 @@ shmif_start(struct ifnet *ifp)
m->m_len);
}
buswrite(sc, npktlenoff, &pktsize, PKTLEN_SIZE);
*BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET) = npktlenoff;
sc->sc_busmem->shm_last = npktlenoff;
unlockbus(sc);
m_freem(m0);
@ -359,8 +352,8 @@ shmif_rcv(void *arg)
KASSERT(m->m_flags & M_EXT);
lockbus(sc);
lastpkt = *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET);
busgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION);
lastpkt = sc->sc_busmem->shm_last;
busgen = sc->sc_busmem->shm_gen;
lastnext = nextpktoff(sc, lastpkt);
if ((lastnext > sc->sc_nextpacket && busgen > sc->sc_prevgen)
|| (busgen > sc->sc_prevgen+1)) {

View File

@ -0,0 +1,45 @@
/* $NetBSD: shmifvar.h,v 1.1 2010/08/12 17:33:55 pooka Exp $ */
/*-
* Copyright (c) 2009 Antti Kantee. All Rights Reserved.
*
* Development of this software was supported by The Nokia Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _RUMP_NET_SHMIFVAR_H_
#define _RUMP_NET_SHMIFVAR_H_
struct shmif_mem {
uint32_t shm_lock;
uint32_t shm_gen;
uint32_t shm_last;
uint32_t shm_version;
uint8_t shm_data[0];
};
#define IFMEM_DATA (offsetof(struct shmif_mem, shm_data))
#define IFMEM_WAKEUP (offsetof(struct shmif_mem, shm_version))
#define PKTLEN_SIZE (sizeof(uint32_t))
#endif