diff options
Diffstat (limited to 'sys/ddb')
-rw-r--r-- | sys/ddb/db_expr.c | 4 | ||||
-rw-r--r-- | sys/ddb/db_sym.c | 169 | ||||
-rw-r--r-- | sys/ddb/db_variables.c | 6 | ||||
-rw-r--r-- | sys/ddb/db_variables.h | 5 | ||||
-rw-r--r-- | sys/ddb/ddb.h | 2 |
5 files changed, 185 insertions, 1 deletions
diff --git a/sys/ddb/db_expr.c b/sys/ddb/db_expr.c index eaab874..424384c 100644 --- a/sys/ddb/db_expr.c +++ b/sys/ddb/db_expr.c @@ -51,7 +51,9 @@ db_term(db_expr_t *valuep) t = db_read_token(); if (t == tIDENT) { - if (!db_value_of_name(db_tok_string, valuep)) { + if (!db_value_of_name(db_tok_string, valuep) && + !db_value_of_name_pcpu(db_tok_string, valuep) && + !db_value_of_name_vnet(db_tok_string, valuep)) { db_error("Symbol not found\n"); /*NOTREACHED*/ } diff --git a/sys/ddb/db_sym.c b/sys/ddb/db_sym.c index 9d043b3..1a95c11 100644 --- a/sys/ddb/db_sym.c +++ b/sys/ddb/db_sym.c @@ -32,10 +32,15 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <sys/smp.h> #include <sys/systm.h> +#include <sys/vimage.h> + +#include <net/vnet.h> #include <ddb/ddb.h> #include <ddb/db_sym.h> +#include <ddb/db_variables.h> #include <opt_ddb.h> @@ -56,6 +61,117 @@ static char *db_qualify(c_db_sym_t sym, char *symtabname); static boolean_t db_symbol_is_ambiguous(c_db_sym_t sym); static boolean_t db_line_at_pc(c_db_sym_t, char **, int *, db_expr_t); +static int db_cpu = -1; + +#ifdef VIMAGE +extern uintptr_t *__start_set_vnet; +extern uintptr_t *__stop_set_vnet; + +#define VNET_START (uintptr_t)&__start_set_vnet +#define VNET_STOP (uintptr_t)&__stop_set_vnet + +static void *db_vnet = NULL; +#endif + +/* + * Validate the CPU number used to interpret per-CPU variables so we can + * avoid later confusion if an invalid CPU is requested. + */ +int +db_var_db_cpu(struct db_variable *vp, db_expr_t *valuep, int op) +{ + + switch (op) { + case DB_VAR_GET: + *valuep = db_cpu; + return (1); + + case DB_VAR_SET: + if (*(int *)valuep < -1 && *(int *)valuep > mp_maxid) { + db_printf("Invalid value: %d", *(int*)valuep); + return (0); + } + db_cpu = *(int *)valuep; + return (1); + + default: + db_printf("db_var_db_cpu: unknown operation\n"); + return (0); + } +} + +/* + * Read-only variable reporting the current CPU, which is what we use when + * db_cpu is set to -1. + */ +int +db_var_curcpu(struct db_variable *vp, db_expr_t *valuep, int op) +{ + + switch (op) { + case DB_VAR_GET: + *valuep = curcpu; + return (1); + + case DB_VAR_SET: + db_printf("Read-only variable.\n"); + return (0); + + default: + db_printf("db_var_curcpu: unknown operation\n"); + return (0); + } +} + +#ifdef VIMAGE +/* + * Validate the virtual network pointer used to interpret per-vnet global + * variable expansion. Right now we don't do much here, really we should + * walk the global vnet list to check it's an OK pointer. + */ +int +db_var_db_vnet(struct db_variable *vp, db_expr_t *valuep, int op) +{ + + switch (op) { + case DB_VAR_GET: + *valuep = (db_expr_t)db_vnet; + return (1); + + case DB_VAR_SET: + db_vnet = *(void **)valuep; + return (1); + + default: + db_printf("db_var_db_vnet: unknown operation\n"); + return (0); + } +} + +/* + * Read-only variable reporting the current vnet, which is what we use when + * db_vnet is set to NULL. + */ +int +db_var_curvnet(struct db_variable *vp, db_expr_t *valuep, int op) +{ + + switch (op) { + case DB_VAR_GET: + *valuep = (db_expr_t)curvnet; + return (1); + + case DB_VAR_SET: + db_printf("Read-only variable.\n"); + return (0); + + default: + db_printf("db_var_curcpu: unknown operation\n"); + return (0); + } +} +#endif + /* * Add symbol table, with given name, to list of symbol tables. */ @@ -125,6 +241,59 @@ db_value_of_name(name, valuep) return (TRUE); } +boolean_t +db_value_of_name_pcpu(name, valuep) + const char *name; + db_expr_t *valuep; +{ + static char tmp[256]; + db_expr_t value; + c_db_sym_t sym; + int cpu; + + if (db_cpu != -1) + cpu = db_cpu; + else + cpu = curcpu; + snprintf(tmp, sizeof(tmp), "pcpu_entry_%s", name); + sym = db_lookup(tmp); + if (sym == C_DB_SYM_NULL) + return (FALSE); + db_symbol_values(sym, &name, &value); + if (value < DPCPU_START || value >= DPCPU_STOP) + return (FALSE); + *valuep = (db_expr_t)((uintptr_t)value + dpcpu_off[cpu]); + return (TRUE); +} + +boolean_t +db_value_of_name_vnet(name, valuep) + const char *name; + db_expr_t *valuep; +{ +#ifdef VIMAGE + static char tmp[256]; + db_expr_t value; + c_db_sym_t sym; + struct vnet *vnet; + + if (db_vnet != NULL) + vnet = db_vnet; + else + vnet = curvnet; + snprintf(tmp, sizeof(tmp), "vnet_entry_%s", name); + sym = db_lookup(tmp); + if (sym == C_DB_SYM_NULL) + return (FALSE); + db_symbol_values(sym, &name, &value); + if (value < VNET_START || value >= VNET_STOP) + return (FALSE); + *valuep = (db_expr_t)((uintptr_t)value + vnet->vnet_data_base); + return (TRUE); +#else + return (FALSE); +#endif +} /* * Lookup a symbol. diff --git a/sys/ddb/db_variables.c b/sys/ddb/db_variables.c index 706ebe6..69c11ae 100644 --- a/sys/ddb/db_variables.c +++ b/sys/ddb/db_variables.c @@ -46,6 +46,12 @@ static struct db_variable db_vars[] = { { "maxwidth", &db_max_width, FCN_NULL }, { "tabstops", &db_tab_stop_width, FCN_NULL }, { "lines", &db_lines_per_page, FCN_NULL }, + { "curcpu", NULL, db_var_curcpu }, + { "db_cpu", NULL, db_var_db_cpu }, +#ifdef VIMAGE + { "curvnet", NULL, db_var_curvnet }, + { "db_vnet", NULL, db_var_db_vnet }, +#endif }; static struct db_variable *db_evars = db_vars + sizeof(db_vars)/sizeof(db_vars[0]); diff --git a/sys/ddb/db_variables.h b/sys/ddb/db_variables.h index 1ff0e44..42a3bf9 100644 --- a/sys/ddb/db_variables.h +++ b/sys/ddb/db_variables.h @@ -52,6 +52,11 @@ struct db_variable { extern struct db_variable db_regs[]; /* machine registers */ extern struct db_variable *db_eregs; +extern db_varfcn_t db_var_curcpu; /* DPCPU default CPU */ +extern db_varfcn_t db_var_curvnet; /* Default vnet */ +extern db_varfcn_t db_var_db_cpu; /* DPCPU active CPU */ +extern db_varfcn_t db_var_db_vnet; /* Active vnet */ + int db_read_variable(struct db_variable *, db_expr_t *); int db_write_variable(struct db_variable *, db_expr_t); diff --git a/sys/ddb/ddb.h b/sys/ddb/ddb.h index 1afdfa3..e6d8a95 100644 --- a/sys/ddb/ddb.h +++ b/sys/ddb/ddb.h @@ -213,6 +213,8 @@ boolean_t db_stop_at_pc(boolean_t *is_breakpoint); void db_trace_self(void); int db_trace_thread(struct thread *, int); int db_value_of_name(const char *name, db_expr_t *valuep); +int db_value_of_name_pcpu(const char *name, db_expr_t *valuep); +int db_value_of_name_vnet(const char *name, db_expr_t *valuep); int db_write_bytes(vm_offset_t addr, size_t size, char *data); void db_command_register(struct command_table *, struct command *); void db_command_unregister(struct command_table *, struct command *); |