akaros/kern/drivers/dev/regress.c
<<
>>
Prefs
   1/*
   2 * This file is part of the UCB release of Plan 9. It is subject to the license
   3 * terms in the LICENSE file found in the top-level directory of this
   4 * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
   5 * part of the UCB release of Plan 9, including this file, may be copied,
   6 * modified, propagated, or distributed except according to the terms contained
   7 * in the LICENSE file.
   8 */
   9
  10// regression device.
  11// Currently, has only one file, monitor, which is used to send
  12// commands to the monitor.
  13// TODO: read them back :-)
  14
  15#include <slab.h>
  16#include <kmalloc.h>
  17#include <kref.h>
  18#include <string.h>
  19#include <stdio.h>
  20#include <assert.h>
  21#include <error.h>
  22#include <cpio.h>
  23#include <pmap.h>
  24#include <smp.h>
  25#include <net/ip.h>
  26#include <monitor.h>
  27#include <ktest.h>
  28
  29struct dev regressdevtab;
  30
  31static char *devname(void)
  32{
  33        return regressdevtab.name;
  34}
  35
  36struct regress
  37{
  38        spinlock_t lock;
  39        struct queue *monitor;
  40};
  41struct regress regress;
  42
  43enum{
  44        Monitordirqid = 0,
  45        Monitordataqid,
  46        Monitorctlqid,
  47};
  48
  49struct dirtab regresstab[]={
  50        {".",           {Monitordirqid, 0, QTDIR},      0,      DMDIR|0550},
  51        {"mondata",     {Monitordataqid},               0,      0600},
  52        {"monctl",      {Monitorctlqid},                0,      0600},
  53};
  54
  55static char *ctlcommands = "ktest";
  56
  57static struct chan *regressattach(char *spec)
  58{
  59        uint32_t n;
  60
  61        regress.monitor = qopen(2 << 20, 0, 0, 0);
  62        if (! regress.monitor) {
  63                printk("monitor allocate failed. No monitor output\n");
  64        }
  65        return devattach(devname(), spec);
  66}
  67
  68static void regressinit(void)
  69{
  70}
  71
  72static struct walkqid *regresswalk(struct chan *c, struct chan *nc, char **name,
  73                                   unsigned int nname)
  74{
  75        return devwalk(c, nc, name, nname, regresstab, ARRAY_SIZE(regresstab),
  76                       devgen);
  77}
  78
  79static size_t regressstat(struct chan *c, uint8_t *db, size_t n)
  80{
  81        if (regress.monitor)
  82                regresstab[Monitordataqid].length = qlen(regress.monitor);
  83        else
  84                regresstab[Monitordataqid].length = 0;
  85
  86        return devstat(c, db, n, regresstab, ARRAY_SIZE(regresstab), devgen);
  87}
  88
  89static struct chan *regressopen(struct chan *c, int omode)
  90{
  91        if (c->qid.type & QTDIR) {
  92                if (openmode(omode) != O_READ)
  93                        error(EPERM, ERROR_FIXME);
  94        }
  95        c->mode = openmode(omode);
  96        c->flag |= COPEN;
  97        c->offset = 0;
  98        return c;
  99}
 100
 101static void regressclose(struct chan *unused)
 102{
 103}
 104
 105static size_t regressread(struct chan *c, void *va, size_t n, off64_t off)
 106{
 107        uint64_t w, *bp;
 108        char *a, *ea;
 109        uintptr_t offset = off;
 110        uint64_t pc;
 111        int snp_ret, ret = 0;
 112
 113        switch((int)c->qid.path){
 114        case Monitordirqid:
 115                n = devdirread(c, va, n, regresstab, ARRAY_SIZE(regresstab),
 116                               devgen);
 117                break;
 118
 119        case Monitorctlqid:
 120                n = readstr(off, va, n, ctlcommands);
 121                break;
 122
 123        case Monitordataqid:
 124                if (regress.monitor) {
 125                        printd("monitordataqid: regress.monitor %p len %p\n",
 126                               regress.monitor, qlen(kprof.monitor));
 127                        if (qlen(regress.monitor) > 0)
 128                                n = qread(regress.monitor, va, n);
 129                        else
 130                                n = 0;
 131                } else
 132                        error(EFAIL, "no monitor queue");
 133                break;
 134        default:
 135                n = 0;
 136                break;
 137        }
 138        return n;
 139}
 140
 141static size_t regresswrite(struct chan *c, void *a, size_t n, off64_t unused)
 142{
 143        ERRSTACK(1);
 144        uintptr_t pc;
 145        struct cmdbuf *cb;
 146        cb = parsecmd(a, n);
 147
 148        if (waserror()) {
 149                kfree(cb);
 150                nexterror();
 151        }
 152
 153        switch ((int)(c->qid.path)) {
 154        case Monitorctlqid:
 155                if (cb->nf < 1)
 156                        error(EFAIL, "%s no command, need %s", __func__,
 157                              ctlcommands);
 158                if (!strcmp(cb->f[0], "ktest")) {
 159                        run_registered_ktest_suites();
 160                } else {
 161                        error(EFAIL, "regresswrite: only commands are %s",
 162                              ctlcommands);
 163                }
 164                break;
 165
 166        case Monitordataqid:
 167                if (onecmd(cb->nf, cb->f, NULL) < 0)
 168                        n = -1;
 169                break;
 170        default:
 171                error(EBADFD, ERROR_FIXME);
 172        }
 173        kfree(cb);
 174        poperror();
 175        return n;
 176}
 177
 178struct dev regressdevtab __devtab = {
 179        .name = "regress",
 180
 181        .reset = devreset,
 182        .init = regressinit,
 183        .shutdown = devshutdown,
 184        .attach = regressattach,
 185        .walk = regresswalk,
 186        .stat = regressstat,
 187        .open = regressopen,
 188        .create = devcreate,
 189        .close = regressclose,
 190        .read = regressread,
 191        .bread = devbread,
 192        .write = regresswrite,
 193        .bwrite = devbwrite,
 194        .remove = devremove,
 195        .wstat = devwstat,
 196};
 197