summaryrefslogtreecommitdiffstats
path: root/sys/ddb
diff options
context:
space:
mode:
Diffstat (limited to 'sys/ddb')
-rw-r--r--sys/ddb/db_expr.c4
-rw-r--r--sys/ddb/db_sym.c169
-rw-r--r--sys/ddb/db_variables.c6
-rw-r--r--sys/ddb/db_variables.h5
-rw-r--r--sys/ddb/ddb.h2
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 *);
OpenPOWER on IntegriCloud