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.

Reply via email to