I'm curious if we don't want to expose the topology in the same way linux does in /proc so libraries like libnuma can compile and just work. I see the usefulness of this for variables in general, but I'm not sure num_cores should be here (or maybe it's also here in addition to /proc).
On Tue, Nov 24, 2015 at 2:02 PM, Barret Rhoden <[email protected]> wrote: > With #vars, you can specify certain global variables, such as num_cores, to > be exposed to userspace. If you want, you can: > > $ bind -a \#vars /dev > $ cat /dev/num_cores > > For debugging, you can add entries to vars_dir[] to temporarily track > certain variables. In the future, we could try adding support for > dynamically adding entries. > > Signed-off-by: Barret Rhoden <[email protected]> > --- > kern/drivers/dev/Kbuild | 1 + > kern/drivers/dev/Kconfig | 7 ++ > kern/drivers/dev/vars.c | 183 > +++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 191 insertions(+) > create mode 100644 kern/drivers/dev/vars.c > > diff --git a/kern/drivers/dev/Kbuild b/kern/drivers/dev/Kbuild > index 57fd9368fb60..ee5e7a74fe21 100644 > --- a/kern/drivers/dev/Kbuild > +++ b/kern/drivers/dev/Kbuild > @@ -12,5 +12,6 @@ obj-y += proc.o > obj-$(CONFIG_REGRESS) += regress.o > obj-y += root.o > obj-y += srv.o > +obj-$(CONFIG_VARS) += vars.o > > obj-$(CONFIG_NIX) += nix.o > diff --git a/kern/drivers/dev/Kconfig b/kern/drivers/dev/Kconfig > index eb737b8b11cb..85aac58f1a3f 100644 > --- a/kern/drivers/dev/Kconfig > +++ b/kern/drivers/dev/Kconfig > @@ -4,3 +4,10 @@ config REGRESS > help > The regression test device allows you to push commands to > monitor() > for testing. Defaults to 'y' for now. > + > +config VARS > + bool "#vars kernel variable exporter" > + default y > + help > + The #vars device exports read access to select kernel > variables. The > + list of variables is statically declared in vars.c > diff --git a/kern/drivers/dev/vars.c b/kern/drivers/dev/vars.c > new file mode 100644 > index 000000000000..573e3ac1c1d9 > --- /dev/null > +++ b/kern/drivers/dev/vars.c > @@ -0,0 +1,183 @@ > +/* Copyright (c) 2015 Google Inc > + * Barret Rhoden <[email protected]> > + * See LICENSE for details. > + * > + * #vars device, exports read access to select kernel global variables. > These > + * variables are statically determined (i.e. set in the code below). > + * > + * To add a variable, add a VARS_ENTRY to vars_dir. If the variable is a > number > + * and you want it in hex, "or" VARS_HEX into the type. e.g: > + * > + * VARS_ENTRY(foobar, type_int | VARS_HEX), > + * > + * If we add write support to vars, those will also be flags for 'type.' > + * > + * Another thing we can consider doing is implementing create() to add > variables > + * on the fly. We can easily get the address (symbol table), but not the > type, > + * unless we get debugging info. We could consider a CTL command to allow > the > + * user to change the type, though that might overload write() if we also > allow > + * setting variables. */ > + > +#include <ns.h> > +#include <kmalloc.h> > +#include <kref.h> > +#include <atomic.h> > +#include <string.h> > +#include <stdio.h> > +#include <assert.h> > +#include <error.h> > +#include <sys/queue.h> > +#include <fdtap.h> > +#include <syscall.h> > + > +struct dev vars_devtab; > + > +static char *devname(void) > +{ > + return vars_devtab.name; > +} > + > +enum { > + type_s8 = 1, > + type_s16, > + type_s32, > + type_s64, > + type_u8, > + type_u16, > + type_u32, > + type_u64, > + > + type_bool, > + type_char, > + type_short, > + type_int, > + type_long, > + type_ushort, > + type_uint, > + type_ulong, > + type_ntstr, /* null-terminated string */ > + > + VARS_HEX = (1 << 31), > +}; > + > +/* The qid.path is the addr of the variable. The qid.vers is the type. > Or-in > + * any VARS_* flags you want to the type. "." has no type or addr. */ > +#define VARS_ENTRY(name, type) {#name, > \ > + {(uint64_t)&(name), (type), QTFILE}, > \ > + sizeof((name)), > \ > + 0444} > + > +static struct dirtab vars_dir[] = { > + {".", {0, 0, QTDIR}, 0, DMDIR | 0555}, > + VARS_ENTRY(num_cores, type_int), > +}; > + > +static struct chan *vars_attach(char *spec) > +{ > + struct chan *c; > + > + c = devattach(devname(), spec); > + mkqid(&c->qid, 0, 0, QTDIR); > + return c; > +} > + > +static struct walkqid *vars_walk(struct chan *c, struct chan *nc, char > **name, > + int nname) > +{ > + return devwalk(c, nc, name, nname, vars_dir, ARRAY_SIZE(vars_dir), > devgen); > +} > + > +static int vars_stat(struct chan *c, uint8_t *db, int n) > +{ > + return devstat(c, db, n, vars_dir, ARRAY_SIZE(vars_dir), devgen); > +} > + > +static struct chan *vars_open(struct chan *c, int omode) > +{ > + return devopen(c, omode, vars_dir, ARRAY_SIZE(vars_dir), devgen); > +} > + > +static void vars_close(struct chan *c) > +{ > +} > + > +static long vars_read(struct chan *c, void *ubuf, long n, int64_t offset) > +{ > + char tmp[128]; /* big enough for any number and most strings */ > + size_t size = sizeof(tmp); > + char *fmt_str_s32 = c->qid.vers & VARS_HEX ? "0x%x" : "%d"; > + char *fmt_str_s64 = c->qid.vers & VARS_HEX ? "0x%lx" : "%ld"; > + char *fmt_str_u32 = c->qid.vers & VARS_HEX ? "0x%x" : "%u"; > + char *fmt_str_u64 = c->qid.vers & VARS_HEX ? "0x%lx" : "%lu"; > + int type = c->qid.vers & ~VARS_HEX; > + > + switch (type) { > + case 0: > + return devdirread(c, ubuf, n, vars_dir, ARRAY_SIZE(vars_dir), > devgen); > + case type_bool: > + case type_u8: > + size = snprintf(tmp, size, fmt_str_u32, > *(uint8_t*)c->qid.path); > + break; > + case type_u16: > + size = snprintf(tmp, size, fmt_str_u32, > *(uint16_t*)c->qid.path); > + break; > + case type_uint: > + case type_u32: > + size = snprintf(tmp, size, fmt_str_u32, > *(uint32_t*)c->qid.path); > + break; > + case type_ulong: > + case type_u64: > + size = snprintf(tmp, size, fmt_str_u64, > *(uint64_t*)c->qid.path); > + break; > + case type_s8: > + size = snprintf(tmp, size, fmt_str_s32, > *(int8_t*)c->qid.path); > + break; > + case type_s16: > + size = snprintf(tmp, size, fmt_str_s32, > *(int16_t*)c->qid.path); > + break; > + case type_int: > + case type_s32: > + size = snprintf(tmp, size, fmt_str_s32, > *(int32_t*)c->qid.path); > + break; > + case type_long: > + case type_s64: > + size = snprintf(tmp, size, fmt_str_s64, > *(int64_t*)c->qid.path); > + break; > + case type_char: > + size = snprintf(tmp, size, "%c", *(char*)c->qid.path); > + break; > + case type_ntstr: > + size = snprintf(tmp, size, "%s", *(char**)c->qid.path); > + break; > + default: > + panic("Unknown #%s type %d", devname(), type); > + } > + return readmem(offset, ubuf, n, tmp, size + 1); > +} > + > +static long vars_write(struct chan *c, void *ubuf, long n, int64_t offset) > +{ > + error(EFAIL, "Can't write to a #%s file", devname()); > +} > + > +struct dev vars_devtab __devtab = { > + .name = "vars", > + .reset = devreset, > + .init = devinit, > + .shutdown = devshutdown, > + .attach = vars_attach, > + .walk = vars_walk, > + .stat = vars_stat, > + .open = vars_open, > + .create = devcreate, > + .close = vars_close, > + .read = vars_read, > + .bread = devbread, > + .write = vars_write, > + .bwrite = devbwrite, > + .remove = devremove, > + .wstat = devwstat, > + .power = devpower, > + .chaninfo = devchaninfo, > + .tapfd = 0, > +}; > -- > 2.6.0.rc2.230.g3dd15c0 > > -- > You received this message because you are subscribed to the Google Groups > "Akaros" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > For more options, visit https://groups.google.com/d/optout. -- ~Kevin -- You received this message because you are subscribed to the Google Groups "Akaros" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. For more options, visit https://groups.google.com/d/optout.
