[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v2] xen/keyhandler: Rework keyhandler infrastructure



struct keyhandler does not contain much information, and requires a lot
of boilerplate to use.  It is far more convenient to have
register_keyhandler() take each piece of information a parameter,
especially when introducing temporary debugging keyhandlers.

This in turn allows struct keyhandler itself to become private to
keyhandler.c and for the key_table to become more efficient.

key_table doesn't need to contain 256 entries; all keys are ASCII which
limits them to 7 bits of index, rather than 8.  It can also become a
straight array, rather than an array of pointers.  The overall effect of
this is the key_table grows in size by 50%, but there are no longer
24-byte keyhandler structures all over the data section.

All of the key_table entries in keyhandler.c can be initialised at
compile time rather than runtime.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Keir Fraser <keir@xxxxxxx>

---

v2:
 * Keep {,irq_}keyhandler_t's as function typedefs
 * Adjustment of initialiser macros
 * Trim more trailing whitespace
 * Implement register_irq_keyhandler()
 * Tweak wording of some descriptions

Note: I have avoided CC'ing all maintainers as this is largely a mechanical
change across the whole codebase.  Most non-mechanical changes are in common
code, but there is a trivial externing change
xen/drivers/passthrough/vtd/extern.h as previously the struct keyhandler was
in a different translation unit to the function it referenced.
---
 xen/arch/x86/acpi/cpu_idle.c             |    8 +-
 xen/arch/x86/hvm/irq.c                   |    8 +-
 xen/arch/x86/hvm/svm/vmcb.c              |    8 +-
 xen/arch/x86/hvm/vmx/vmcs.c              |    8 +-
 xen/arch/x86/io_apic.c                   |    7 +-
 xen/arch/x86/irq.c                       |    8 +-
 xen/arch/x86/mm/p2m-ept.c                |    8 +-
 xen/arch/x86/mm/shadow/common.c          |   14 +-
 xen/arch/x86/msi.c                       |    8 +-
 xen/arch/x86/nmi.c                       |   15 +--
 xen/arch/x86/numa.c                      |    8 +-
 xen/arch/x86/time.c                      |    8 +-
 xen/common/event_channel.c               |    8 +-
 xen/common/grant_table.c                 |    9 +-
 xen/common/kexec.c                       |    7 +-
 xen/common/keyhandler.c                  |  207 ++++++++++++------------------
 xen/common/page_alloc.c                  |   16 +--
 xen/common/timer.c                       |    8 +-
 xen/drivers/char/console.c               |   16 +--
 xen/drivers/passthrough/amd/iommu_intr.c |    9 +-
 xen/drivers/passthrough/iommu.c          |    8 +-
 xen/drivers/passthrough/pci.c            |    8 +-
 xen/drivers/passthrough/vtd/extern.h     |    2 +-
 xen/drivers/passthrough/vtd/iommu.c      |    2 +-
 xen/drivers/passthrough/vtd/utils.c      |    8 +-
 xen/include/xen/keyhandler.h             |   71 +++++-----
 26 files changed, 145 insertions(+), 342 deletions(-)

diff --git a/xen/arch/x86/acpi/cpu_idle.c b/xen/arch/x86/acpi/cpu_idle.c
index 15fe2e9..d1f99a7 100644
--- a/xen/arch/x86/acpi/cpu_idle.c
+++ b/xen/arch/x86/acpi/cpu_idle.c
@@ -334,15 +334,9 @@ static void dump_cx(unsigned char key)
             print_acpi_power(cpu, processor_powers[cpu]);
 }
 
-static struct keyhandler dump_cx_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = dump_cx,
-    .desc = "dump ACPI Cx structures"
-};
-
 static int __init cpu_idle_key_init(void)
 {
-    register_keyhandler('c', &dump_cx_keyhandler);
+    register_keyhandler('c', dump_cx, "dump ACPI Cx structures", 1);
     return 0;
 }
 __initcall(cpu_idle_key_init);
diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c
index 50fcf73..990a2ca 100644
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -527,15 +527,9 @@ static void dump_irq_info(unsigned char key)
     rcu_read_unlock(&domlist_read_lock);
 }
 
-static struct keyhandler dump_irq_info_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = dump_irq_info,
-    .desc = "dump HVM irq info"
-};
-
 static int __init dump_irq_info_key_init(void)
 {
-    register_keyhandler('I', &dump_irq_info_keyhandler);
+    register_keyhandler('I', dump_irq_info, "dump HVM irq info", 1);
     return 0;
 }
 __initcall(dump_irq_info_key_init);
diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c
index b5d7165..9ea014f 100644
--- a/xen/arch/x86/hvm/svm/vmcb.c
+++ b/xen/arch/x86/hvm/svm/vmcb.c
@@ -303,15 +303,9 @@ static void vmcb_dump(unsigned char ch)
     printk("**************************************\n");
 }
 
-static struct keyhandler vmcb_dump_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = vmcb_dump,
-    .desc = "dump AMD-V VMCBs"
-};
-
 void __init setup_vmcb_dump(void)
 {
-    register_keyhandler('v', &vmcb_dump_keyhandler);
+    register_keyhandler('v', vmcb_dump, "dump AMD-V VMCBs", 1);
 }
 
 /*
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index 08f2078..15b136b 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -1858,15 +1858,9 @@ static void vmcs_dump(unsigned char ch)
     printk("**************************************\n");
 }
 
-static struct keyhandler vmcs_dump_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = vmcs_dump,
-    .desc = "dump Intel's VMCS"
-};
-
 void __init setup_vmcs_dump(void)
 {
-    register_keyhandler('v', &vmcs_dump_keyhandler);
+    register_keyhandler('v', vmcs_dump, "dump VT-x VMCSs", 1);
 }
 
 
diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c
index b8e37b5..1e710d6 100644
--- a/xen/arch/x86/io_apic.c
+++ b/xen/arch/x86/io_apic.c
@@ -1251,11 +1251,6 @@ static void _print_IO_APIC_keyhandler(unsigned char key)
 {
     __print_IO_APIC(0);
 }
-static struct keyhandler print_IO_APIC_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = _print_IO_APIC_keyhandler,
-    .desc = "print ioapic info"
-};
 
 static void __init enable_IO_APIC(void)
 {
@@ -2054,7 +2049,7 @@ void __init setup_IO_APIC(void)
     print_IO_APIC();
     ioapic_pm_state_alloc();
 
-    register_keyhandler('z', &print_IO_APIC_keyhandler);
+    register_keyhandler('z', _print_IO_APIC_keyhandler, "dump IOAPIC info", 1);
 }
 
 void ioapic_suspend(void)
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index bf2e822..f1397d6 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -2316,15 +2316,9 @@ static void dump_irqs(unsigned char key)
     dump_ioapic_irq_info();
 }
 
-static struct keyhandler dump_irqs_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = dump_irqs,
-    .desc = "dump interrupt bindings"
-};
-
 static int __init setup_dump_irqs(void)
 {
-    register_keyhandler('i', &dump_irqs_keyhandler);
+    register_keyhandler('i', dump_irqs, "dump interrupt bindings", 1);
     return 0;
 }
 __initcall(setup_dump_irqs);
diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
index dde242e..e4d3d6b 100644
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -1257,15 +1257,9 @@ static void ept_dump_p2m_table(unsigned char key)
     }
 }
 
-static struct keyhandler ept_p2m_table = {
-    .diagnostic = 0,
-    .u.fn = ept_dump_p2m_table,
-    .desc = "dump ept p2m table"
-};
-
 void setup_ept_dump(void)
 {
-    register_keyhandler('D', &ept_p2m_table);
+    register_keyhandler('D', ept_dump_p2m_table, "dump VT-x EPT tables", 0);
 }
 
 /*
diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
index 0264b91..3759232 100644
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -97,14 +97,9 @@ static void shadow_audit_key(unsigned char key)
            __func__, shadow_audit_enable);
 }
 
-static struct keyhandler shadow_audit_keyhandler = {
-    .u.fn = shadow_audit_key,
-    .desc = "toggle shadow audits"
-};
-
 static int __init shadow_audit_key_init(void)
 {
-    register_keyhandler('O', &shadow_audit_keyhandler);
+    register_keyhandler('O', shadow_audit_key, "toggle shadow audits", 0);
     return 0;
 }
 __initcall(shadow_audit_key_init);
@@ -1409,15 +1404,10 @@ static void shadow_blow_all_tables(unsigned char c)
     rcu_read_unlock(&domlist_read_lock);
 }
 
-static struct keyhandler shadow_blow_all_tables_keyhandler = {
-    .u.fn = shadow_blow_all_tables,
-    .desc = "reset shadow pagetables"
-};
-
 /* Register this function in the Xen console keypress table */
 static __init int shadow_blow_tables_keyhandler_init(void)
 {
-    register_keyhandler('S', &shadow_blow_all_tables_keyhandler);
+    register_keyhandler('S', shadow_blow_all_tables, "reset shadow 
pagetables", 1);
     return 0;
 }
 __initcall(shadow_blow_tables_keyhandler_init);
diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c
index 3dbb84d..5a481f6 100644
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -1590,15 +1590,9 @@ static void dump_msi(unsigned char key)
     }
 }
 
-static struct keyhandler dump_msi_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = dump_msi,
-    .desc = "dump MSI state"
-};
-
 static int __init msi_setup_keyhandler(void)
 {
-    register_keyhandler('M', &dump_msi_keyhandler);
+    register_keyhandler('M', dump_msi, "dump MSI state", 1);
     return 0;
 }
 __initcall(msi_setup_keyhandler);
diff --git a/xen/arch/x86/nmi.c b/xen/arch/x86/nmi.c
index 2ab97a0..7520454 100644
--- a/xen/arch/x86/nmi.c
+++ b/xen/arch/x86/nmi.c
@@ -554,11 +554,6 @@ static void do_nmi_trigger(unsigned char key)
     self_nmi();
 }
 
-static struct keyhandler nmi_trigger_keyhandler = {
-    .u.fn = do_nmi_trigger,
-    .desc = "trigger an NMI"
-};
-
 static void do_nmi_stats(unsigned char key)
 {
     int i;
@@ -582,16 +577,10 @@ static void do_nmi_stats(unsigned char key)
         printk("dom0 vcpu0: NMI neither pending nor masked\n");
 }
 
-static struct keyhandler nmi_stats_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = do_nmi_stats,
-    .desc = "NMI statistics"
-};
-
 static __init int register_nmi_trigger(void)
 {
-    register_keyhandler('N', &nmi_trigger_keyhandler);
-    register_keyhandler('n', &nmi_stats_keyhandler);
+    register_keyhandler('N', do_nmi_trigger, "trigger an NMI", 0);
+    register_keyhandler('n', do_nmi_stats, "NMI statistics", 1);
     return 0;
 }
 __initcall(register_nmi_trigger);
diff --git a/xen/arch/x86/numa.c b/xen/arch/x86/numa.c
index 3041b24..0e82dd4 100644
--- a/xen/arch/x86/numa.c
+++ b/xen/arch/x86/numa.c
@@ -501,15 +501,9 @@ static void dump_numa(unsigned char key)
     rcu_read_unlock(&domlist_read_lock);
 }
 
-static struct keyhandler dump_numa_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = dump_numa,
-    .desc = "dump numa info"
-};
-
 static __init int register_numa_trigger(void)
 {
-    register_keyhandler('u', &dump_numa_keyhandler);
+    register_keyhandler('u', dump_numa, "dump NUMA info", 1);
     return 0;
 }
 __initcall(register_numa_trigger);
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index bbb7e6c..b334f2f 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -2047,15 +2047,9 @@ static void dump_softtsc(unsigned char key)
             printk("No domains have emulated TSC\n");
 }
 
-static struct keyhandler dump_softtsc_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = dump_softtsc,
-    .desc = "dump softtsc stats"
-};
-
 static int __init setup_dump_softtsc(void)
 {
-    register_keyhandler('s', &dump_softtsc_keyhandler);
+    register_keyhandler('s', dump_softtsc, "dump softtsc stats", 1);
     return 0;
 }
 __initcall(setup_dump_softtsc);
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index bd334f9..5a529a6 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -1431,15 +1431,9 @@ static void dump_evtchn_info(unsigned char key)
     rcu_read_unlock(&domlist_read_lock);
 }
 
-static struct keyhandler dump_evtchn_info_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = dump_evtchn_info,
-    .desc = "dump evtchn info"
-};
-
 static int __init dump_evtchn_info_key_init(void)
 {
-    register_keyhandler('e', &dump_evtchn_info_keyhandler);
+    register_keyhandler('e', dump_evtchn_info, "dump evtchn info", 1);
     return 0;
 }
 __initcall(dump_evtchn_info_key_init);
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 23185e7..c92abda 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -3492,12 +3492,6 @@ static void gnttab_usage_print_all(unsigned char key)
     printk("%s ] done\n", __FUNCTION__);
 }
 
-static struct keyhandler gnttab_usage_print_all_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = gnttab_usage_print_all,
-    .desc = "print grant table usage"
-};
-
 static int __init gnttab_usage_init(void)
 {
     if ( max_nr_grant_frames )
@@ -3518,7 +3512,8 @@ static int __init gnttab_usage_init(void)
     if ( !max_maptrack_frames )
         max_maptrack_frames = DEFAULT_MAX_MAPTRACK_FRAMES;
 
-    register_keyhandler('g', &gnttab_usage_print_all_keyhandler);
+    register_keyhandler('g', gnttab_usage_print_all,
+                        "print grant table usage", 1);
     return 0;
 }
 __initcall(gnttab_usage_init);
diff --git a/xen/common/kexec.c b/xen/common/kexec.c
index 7dd2700..2fc2957 100644
--- a/xen/common/kexec.c
+++ b/xen/common/kexec.c
@@ -374,11 +374,6 @@ static void do_crashdump_trigger(unsigned char key)
     printk(" * no crash kernel loaded!\n");
 }
 
-static struct keyhandler crashdump_trigger_keyhandler = {
-    .u.fn = do_crashdump_trigger,
-    .desc = "trigger a crashdump"
-};
-
 static void setup_note(Elf_Note *n, const char *name, int type, int descsz)
 {
     int l = strlen(name) + 1;
@@ -571,7 +566,7 @@ static int __init kexec_init(void)
     if ( ! crash_notes )
         return -ENOMEM;
 
-    register_keyhandler('C', &crashdump_trigger_keyhandler);
+    register_keyhandler('C', do_crashdump_trigger, "trigger a crashdump", 0);
 
     cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
     register_cpu_notifier(&cpu_nfb);
diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c
index 5d21e48..3361682 100644
--- a/xen/common/keyhandler.c
+++ b/xen/common/keyhandler.c
@@ -3,7 +3,7 @@
  */
 
 #include <asm/regs.h>
-#include <xen/keyhandler.h> 
+#include <xen/keyhandler.h>
 #include <xen/shutdown.h>
 #include <xen/event.h>
 #include <xen/console.h>
@@ -21,12 +21,58 @@
 #include <asm/debugger.h>
 #include <asm/div64.h>
 
-static struct keyhandler *key_table[256];
 static unsigned char keypress_key;
 static bool_t alt_key_handling;
 
+static keyhandler_fn_t show_handlers, dump_hwdom_registers,
+    dump_domains, read_clocks;
+static irq_keyhandler_fn_t do_toggle_alt_key, dump_registers,
+    reboot_machine, run_all_keyhandlers, do_debug_key;
+
 char keyhandler_scratch[1024];
 
+static struct keyhandler {
+    union {
+        keyhandler_fn_t *fn;
+        irq_keyhandler_fn_t *irq_fn;
+    };
+
+    const char *desc;    /* Description for help message.                 */
+    bool_t irq_callback, /* Call in irq context? if not, tasklet context. */
+        diagnostic;      /* Include in 'dump all' handler.                */
+} key_table[128] __read_mostly =
+{
+#define KEYHANDLER(k, f, desc, diag)            \
+    [k] = { .fn = (f), (desc), 0, (diag) }
+
+#define IRQ_KEYHANDLER(k, f, desc, diag)        \
+    [k] = { .irq_fn = (f), (desc), 1, (diag) }
+
+    IRQ_KEYHANDLER('A', do_toggle_alt_key, "toggle alternative key handling", 
0),
+    IRQ_KEYHANDLER('d', dump_registers, "dump registers", 1),
+        KEYHANDLER('h', show_handlers, "show this message", 0),
+        KEYHANDLER('q', dump_domains, "dump domain (and guest debug) info", 1),
+        KEYHANDLER('r', dump_runq, "dump run queues", 1),
+    IRQ_KEYHANDLER('R', reboot_machine, "reboot machine", 0),
+        KEYHANDLER('t', read_clocks, "display multi-cpu clock info", 1),
+        KEYHANDLER('0', dump_hwdom_registers, "dump Dom0 registers", 1),
+    IRQ_KEYHANDLER('%', do_debug_key, "trap to xendbg", 0),
+    IRQ_KEYHANDLER('*', run_all_keyhandlers, "print all diagnostics", 0),
+
+#ifdef PERF_COUNTERS
+    KEYHANDLER('p', perfc_printall, "print performance counters", 1),
+    KEYHANDLER('P', perfc_reset, "reset performance counters", 0),
+#endif
+
+#ifdef LOCK_PROFILE
+    KEYHANDLER('l', spinlock_profile_printall, "print lock profile info", 1),
+    KEYHANDLER('L', spinlock_profile_reset, "reset lock profile info", 0),
+#endif
+
+#undef IRQ_KEYHANDLER
+#undef KEYHANDLER
+};
+
 static void keypress_action(unsigned long unused)
 {
     handle_keypress(keypress_key, NULL);
@@ -38,13 +84,13 @@ void handle_keypress(unsigned char key, struct 
cpu_user_regs *regs)
 {
     struct keyhandler *h;
 
-    if ( (h = key_table[key]) == NULL )
+    if ( key >= ARRAY_SIZE(key_table) || !(h = &key_table[key])->fn )
         return;
 
     if ( !in_irq() || h->irq_callback )
     {
         console_start_log_everything();
-        h->irq_callback ? (*h->u.irq_fn)(key, regs) : (*h->u.fn)(key);
+        h->irq_callback ? h->irq_fn(key, regs) : h->fn(key);
         console_end_log_everything();
     }
     else
@@ -54,27 +100,34 @@ void handle_keypress(unsigned char key, struct 
cpu_user_regs *regs)
     }
 }
 
-void register_keyhandler(unsigned char key, struct keyhandler *handler)
+void register_keyhandler(unsigned char key, keyhandler_fn_t fn,
+                         const char *desc, bool_t diagnostic)
+{
+    BUG_ON(key >= ARRAY_SIZE(key_table)); /* Key in range? */
+    ASSERT(!key_table[key].fn);           /* Clobbering something else? */
+
+    key_table[key] = (struct keyhandler){ .fn = fn, desc, 0, diagnostic };
+}
+
+void register_irq_keyhandler(unsigned char key, irq_keyhandler_fn_t fn,
+                             const char *desc, bool_t diagnostic)
 {
-    ASSERT(key_table[key] == NULL);
-    key_table[key] = handler;
+    BUG_ON(key >= ARRAY_SIZE(key_table)); /* Key in range? */
+    ASSERT(!key_table[key].irq_fn);       /* Clobbering something else? */
+
+    key_table[key] = (struct keyhandler){ .irq_fn = fn, desc, 1, diagnostic };
 }
 
 static void show_handlers(unsigned char key)
 {
-    int i;
+    unsigned int i;
     printk("'%c' pressed -> showing installed handlers\n", key);
-    for ( i = 0; i < ARRAY_SIZE(key_table); i++ ) 
-        if ( key_table[i] != NULL ) 
-            printk(" key '%c' (ascii '%02x') => %s\n", 
-                   isprint(i) ? i : ' ', i, key_table[i]->desc);
+    for ( i = 0; i < ARRAY_SIZE(key_table); i++ )
+        if ( key_table[i].fn )
+            printk(" key '%c' (ascii '%02x') => %s\n",
+                   isprint(i) ? i : ' ', i, key_table[i].desc);
 }
 
-static struct keyhandler show_handlers_keyhandler = {
-    .u.fn = show_handlers,
-    .desc = "show this message"
-};
-
 static cpumask_t dump_execstate_mask;
 
 void dump_execstate(struct cpu_user_regs *regs)
@@ -141,13 +194,6 @@ static void dump_registers(unsigned char key, struct 
cpu_user_regs *regs)
     watchdog_enable();
 }
 
-static struct keyhandler dump_registers_keyhandler = {
-    .irq_callback = 1,
-    .diagnostic = 1,
-    .u.irq_fn = dump_registers,
-    .desc = "dump registers"
-};
-
 static DECLARE_TASKLET(dump_hwdom_tasklet, NULL, 0);
 
 static void dump_hwdom_action(unsigned long arg)
@@ -191,24 +237,12 @@ static void dump_hwdom_registers(unsigned char key)
     }
 }
 
-static struct keyhandler dump_hwdom_registers_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = dump_hwdom_registers,
-    .desc = "dump Dom0 registers"
-};
-
 static void reboot_machine(unsigned char key, struct cpu_user_regs *regs)
 {
     printk("'%c' pressed -> rebooting machine\n", key);
     machine_restart(0);
 }
 
-static struct keyhandler reboot_machine_keyhandler = {
-    .irq_callback = 1,
-    .u.irq_fn = reboot_machine,
-    .desc = "reboot machine"
-};
-
 static void cpuset_print(char *set, int size, const cpumask_t *mask)
 {
     *set++ = '{';
@@ -262,8 +296,8 @@ static void dump_domains(unsigned char key)
                atomic_read(&d->refcnt), d->is_dying,
                atomic_read(&d->pause_count));
         printk("    nr_pages=%d xenheap_pages=%d shared_pages=%u 
paged_pages=%u "
-               "dirty_cpus=%s max_pages=%u\n", d->tot_pages, d->xenheap_pages, 
-                atomic_read(&d->shr_pages), atomic_read(&d->paged_pages), 
+               "dirty_cpus=%s max_pages=%u\n", d->tot_pages, d->xenheap_pages,
+                atomic_read(&d->shr_pages), atomic_read(&d->paged_pages),
                 tmpstr, d->max_pages);
         printk("    handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-"
                "%02x%02x-%02x%02x%02x%02x%02x%02x vm_assist=%08lx\n",
@@ -282,7 +316,7 @@ static void dump_domains(unsigned char key)
         rangeset_domain_printk(d);
 
         dump_pageframe_info(d);
-               
+
         nodeset_print(tmpstr, sizeof(tmpstr), &d->node_affinity);
         printk("NODE affinity for domain %d: %s\n", d->domain_id, tmpstr);
 
@@ -333,12 +367,6 @@ static void dump_domains(unsigned char key)
 #undef tmpstr
 }
 
-static struct keyhandler dump_domains_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = dump_domains,
-    .desc = "dump domain (and guest debug) info"
-};
-
 static cpumask_t read_clocks_cpumask;
 static DEFINE_PER_CPU(s_time_t, read_clocks_time);
 static DEFINE_PER_CPU(u64, read_cycles_time);
@@ -420,42 +448,6 @@ static void read_clocks(unsigned char key)
            maxdif_cycles, sumdif_cycles/count, count, dif_cycles);
 }
 
-static struct keyhandler read_clocks_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = read_clocks,
-    .desc = "display multi-cpu clock info"
-};
-
-static struct keyhandler dump_runq_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = dump_runq,
-    .desc = "dump run queues"
-};
-
-#ifdef PERF_COUNTERS
-static struct keyhandler perfc_printall_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = perfc_printall,
-    .desc = "print performance counters"
-};
-static struct keyhandler perfc_reset_keyhandler = {
-    .u.fn = perfc_reset,
-    .desc = "reset performance counters"
-};
-#endif
-
-#ifdef LOCK_PROFILE
-static struct keyhandler spinlock_printall_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = spinlock_profile_printall,
-    .desc = "print lock profile info"
-};
-static struct keyhandler spinlock_reset_keyhandler = {
-    .u.fn = spinlock_profile_reset,
-    .desc = "reset lock profile info"
-};
-#endif
-
 static void run_all_nonirq_keyhandlers(unsigned long unused)
 {
     /* Fire all the non-IRQ-context diagnostic keyhandlers */
@@ -467,11 +459,11 @@ static void run_all_nonirq_keyhandlers(unsigned long 
unused)
     for ( k = 0; k < ARRAY_SIZE(key_table); k++ )
     {
         process_pending_softirqs();
-        h = key_table[k];
-        if ( (h == NULL) || !h->diagnostic || h->irq_callback )
+        h = &key_table[k];
+        if ( !h->fn || !h->diagnostic || h->irq_callback )
             continue;
         printk("[%c: %s]\n", k, h->desc);
-        (*h->u.fn)(k);
+        h->fn(k);
     }
 
     console_end_log_everything();
@@ -483,7 +475,7 @@ static DECLARE_TASKLET(run_all_keyhandlers_tasklet,
 static void run_all_keyhandlers(unsigned char key, struct cpu_user_regs *regs)
 {
     struct keyhandler *h;
-    int k;
+    unsigned int k;
 
     watchdog_disable();
 
@@ -492,11 +484,11 @@ static void run_all_keyhandlers(unsigned char key, struct 
cpu_user_regs *regs)
     /* Fire all the IRQ-context diangostic keyhandlers now */
     for ( k = 0; k < ARRAY_SIZE(key_table); k++ )
     {
-        h = key_table[k];
-        if ( (h == NULL) || !h->diagnostic || !h->irq_callback )
+        h = &key_table[k];
+        if ( !h->irq_fn || !h->diagnostic || !h->irq_callback )
             continue;
         printk("[%c: %s]\n", k, h->desc);
-        (*h->u.irq_fn)(k, regs);
+        h->irq_fn(k, regs);
     }
 
     watchdog_enable();
@@ -505,12 +497,6 @@ static void run_all_keyhandlers(unsigned char key, struct 
cpu_user_regs *regs)
     tasklet_schedule(&run_all_keyhandlers_tasklet);
 }
 
-static struct keyhandler run_all_keyhandlers_keyhandler = {
-    .irq_callback = 1,
-    .u.irq_fn = run_all_keyhandlers,
-    .desc = "print all diagnostics"
-};
-
 static void do_debug_key(unsigned char key, struct cpu_user_regs *regs)
 {
     printk("'%c' pressed -> trapping into debugger\n", key);
@@ -520,12 +506,6 @@ static void do_debug_key(unsigned char key, struct 
cpu_user_regs *regs)
                              bit. */
 }
 
-static struct keyhandler do_debug_key_keyhandler = {
-    .irq_callback = 1,
-    .u.irq_fn = do_debug_key,
-    .desc = "trap to xendbg"
-};
-
 static void do_toggle_alt_key(unsigned char key, struct cpu_user_regs *regs)
 {
     alt_key_handling = !alt_key_handling;
@@ -533,12 +513,6 @@ static void do_toggle_alt_key(unsigned char key, struct 
cpu_user_regs *regs)
            alt_key_handling ? "alternative" : "normal");
 }
 
-static struct keyhandler toggle_alt_keyhandler = {
-    .irq_callback = 1,
-    .u.irq_fn = do_toggle_alt_key,
-    .desc = "toggle alternative key handling"
-};
-
 void __init initialize_keytable(void)
 {
     if ( num_present_cpus() > 16 )
@@ -547,27 +521,6 @@ void __init initialize_keytable(void)
         printk(XENLOG_INFO "Defaulting to alternative key handling; "
                "send 'A' to switch to normal mode.\n");
     }
-    register_keyhandler('A', &toggle_alt_keyhandler);
-    register_keyhandler('d', &dump_registers_keyhandler);
-    register_keyhandler('h', &show_handlers_keyhandler);
-    register_keyhandler('q', &dump_domains_keyhandler);
-    register_keyhandler('r', &dump_runq_keyhandler);
-    register_keyhandler('R', &reboot_machine_keyhandler);
-    register_keyhandler('t', &read_clocks_keyhandler);
-    register_keyhandler('0', &dump_hwdom_registers_keyhandler);
-    register_keyhandler('%', &do_debug_key_keyhandler);
-    register_keyhandler('*', &run_all_keyhandlers_keyhandler);
-
-#ifdef PERF_COUNTERS
-    register_keyhandler('p', &perfc_printall_keyhandler);
-    register_keyhandler('P', &perfc_reset_keyhandler);
-#endif
-
-#ifdef LOCK_PROFILE
-    register_keyhandler('l', &spinlock_printall_keyhandler);
-    register_keyhandler('L', &spinlock_reset_keyhandler);
-#endif
-
 }
 
 /*
diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 74fc1de..2b8810c 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -1849,15 +1849,9 @@ static void pagealloc_info(unsigned char key)
     printk("    Dom heap: %lukB free\n", total << (PAGE_SHIFT-10));
 }
 
-static struct keyhandler pagealloc_info_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = pagealloc_info,
-    .desc = "memory info"
-};
-
 static __init int pagealloc_keyhandler_init(void)
 {
-    register_keyhandler('m', &pagealloc_info_keyhandler);
+    register_keyhandler('m', pagealloc_info, "memory info", 1);
     return 0;
 }
 __initcall(pagealloc_keyhandler_init);
@@ -1901,15 +1895,9 @@ static void dump_heap(unsigned char key)
     }
 }
 
-static struct keyhandler dump_heap_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = dump_heap,
-    .desc = "dump heap info"
-};
-
 static __init int register_heap_trigger(void)
 {
-    register_keyhandler('H', &dump_heap_keyhandler);
+    register_keyhandler('H', dump_heap, "dump heap info", 1);
     return 0;
 }
 __initcall(register_heap_trigger);
diff --git a/xen/common/timer.c b/xen/common/timer.c
index f36aebc..29a60a9 100644
--- a/xen/common/timer.c
+++ b/xen/common/timer.c
@@ -540,12 +540,6 @@ static void dump_timerq(unsigned char key)
     }
 }
 
-static struct keyhandler dump_timerq_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = dump_timerq,
-    .desc = "dump timer queues"
-};
-
 static void migrate_timers_from_cpu(unsigned int old_cpu)
 {
     unsigned int new_cpu = cpumask_any(&cpu_online_map);
@@ -639,7 +633,7 @@ void __init timer_init(void)
     cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
     register_cpu_notifier(&cpu_nfb);
 
-    register_keyhandler('a', &dump_timerq_keyhandler);
+    register_keyhandler('a', dump_timerq, "dump timer queues", 1);
 }
 
 /*
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index fce4cc8..4362400 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -322,11 +322,6 @@ static void dump_console_ring_key(unsigned char key)
     free_xenheap_pages(buf, order);
 }
 
-static struct keyhandler dump_console_ring_keyhandler = {
-    .u.fn = dump_console_ring_key,
-    .desc = "synchronously dump console ring buffer (dmesg)"
-};
-
 /* CTRL-<switch_char> switches input direction between Xen and DOM0. */
 #define switch_code (opt_conswitch[0]-'a'+1)
 static int __read_mostly xen_rx = 1; /* FALSE => input passed to domain 0. */
@@ -833,7 +828,8 @@ void __init console_endboot(void)
     if ( opt_conswitch[1] == 'x' )
         xen_rx = !xen_rx;
 
-    register_keyhandler('w', &dump_console_ring_keyhandler);
+    register_keyhandler('w', dump_console_ring_key,
+                        "synchronously dump console ring buffer (dmesg)", 0);
 
     /* Serial input is directed to DOM0 by default. */
     switch_serial_input();
@@ -1069,11 +1065,6 @@ static void debugtrace_key(unsigned char key)
     debugtrace_toggle();
 }
 
-static struct keyhandler debugtrace_keyhandler = {
-    .u.fn = debugtrace_key,
-    .desc = "toggle debugtrace to console/buffer"
-};
-
 static int __init debugtrace_init(void)
 {
     int order;
@@ -1095,7 +1086,8 @@ static int __init debugtrace_init(void)
 
     debugtrace_bytes = bytes;
 
-    register_keyhandler('T', &debugtrace_keyhandler);
+    register_keyhandler('T', debugtrace_key,
+                        "toggle debugtrace to console/buffer", 0);
 
     return 0;
 }
diff --git a/xen/drivers/passthrough/amd/iommu_intr.c 
b/xen/drivers/passthrough/amd/iommu_intr.c
index 62e29e9..74c2809 100644
--- a/xen/drivers/passthrough/amd/iommu_intr.c
+++ b/xen/drivers/passthrough/amd/iommu_intr.c
@@ -36,12 +36,6 @@
 
 static void dump_intremap_tables(unsigned char key);
 
-static struct keyhandler dump_intremap = {
-    .diagnostic = 0,
-    .u.fn = dump_intremap_tables,
-    .desc = "dump IOMMU intremap tables"
-};
-
 static spinlock_t* get_intremap_lock(int seg, int req_id)
 {
     return (amd_iommu_perdev_intremap ?
@@ -269,7 +263,8 @@ int __init amd_iommu_setup_ioapic_remapping(void)
         }
     }
 
-    register_keyhandler('V', &dump_intremap);
+    register_keyhandler('V', &dump_intremap_tables,
+                        "dump IOMMU intremap tables", 0);
 
     return 0;
 }
diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c
index aee9d82..3e55abf 100644
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -67,12 +67,6 @@
 PAGE_LIST_HEAD(iommu_pt_cleanup_list);
 static struct tasklet iommu_pt_cleanup_tasklet;
 
-static struct keyhandler iommu_p2m_table = {
-    .diagnostic = 0,
-    .u.fn = iommu_dump_p2m_table,
-    .desc = "dump iommu p2m table"
-};
-
 static void __init parse_iommu_param(char *s)
 {
     char *ss;
@@ -161,7 +155,7 @@ void __hwdom_init iommu_hwdom_init(struct domain *d)
     if ( !iommu_enabled )
         return;
 
-    register_keyhandler('o', &iommu_p2m_table);
+    register_keyhandler('o', &iommu_dump_p2m_table, "dump iommu p2m table", 0);
     d->need_iommu = !!iommu_dom0_strict;
     if ( need_iommu(d) && !iommu_use_hap_pt(d) )
     {
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index 27b3ca7..62b311b 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -1211,15 +1211,9 @@ static void dump_pci_devices(unsigned char ch)
     spin_unlock(&pcidevs_lock);
 }
 
-struct keyhandler dump_pci_devices_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = dump_pci_devices,
-    .desc = "dump PCI devices"
-};
-
 static int __init setup_dump_pcidevs(void)
 {
-    register_keyhandler('Q', &dump_pci_devices_keyhandler);
+    register_keyhandler('Q', dump_pci_devices, "dump PCI devices", 1);
     return 0;
 }
 __initcall(setup_dump_pcidevs);
diff --git a/xen/drivers/passthrough/vtd/extern.h 
b/xen/drivers/passthrough/vtd/extern.h
index 8acf889..e1e33ac 100644
--- a/xen/drivers/passthrough/vtd/extern.h
+++ b/xen/drivers/passthrough/vtd/extern.h
@@ -29,7 +29,7 @@
 
 void print_iommu_regs(struct acpi_drhd_unit *drhd);
 void print_vtd_entries(struct iommu *iommu, int bus, int devfn, u64 gmfn);
-extern struct keyhandler dump_iommu_info_keyhandler;
+void vtd_dump_iommu_info(unsigned char key);
 
 int enable_qinval(struct iommu *iommu);
 void disable_qinval(struct iommu *iommu);
diff --git a/xen/drivers/passthrough/vtd/iommu.c 
b/xen/drivers/passthrough/vtd/iommu.c
index b67b624..4746a55 100644
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -2210,7 +2210,7 @@ int __init intel_vtd_setup(void)
     if ( ret )
         goto error;
 
-    register_keyhandler('V', &dump_iommu_info_keyhandler);
+    register_keyhandler('V', vtd_dump_iommu_info, "dump iommu info", 1);
 
     return 0;
 
diff --git a/xen/drivers/passthrough/vtd/utils.c 
b/xen/drivers/passthrough/vtd/utils.c
index 44c4ef5..36ed3d6 100644
--- a/xen/drivers/passthrough/vtd/utils.c
+++ b/xen/drivers/passthrough/vtd/utils.c
@@ -177,7 +177,7 @@ void print_vtd_entries(struct iommu *iommu, int bus, int 
devfn, u64 gmfn)
     } while ( --level );
 }
 
-static void dump_iommu_info(unsigned char key)
+void vtd_dump_iommu_info(unsigned char key)
 {
     struct acpi_drhd_unit *drhd;
     struct iommu *iommu;
@@ -291,12 +291,6 @@ static void dump_iommu_info(unsigned char key)
     }
 }
 
-struct keyhandler dump_iommu_info_keyhandler = {
-    .diagnostic = 1,
-    .u.fn = dump_iommu_info,
-    .desc = "dump iommu info"
-};
-
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/xen/keyhandler.h b/xen/include/xen/keyhandler.h
index d3ab0a9..39052b5 100644
--- a/xen/include/xen/keyhandler.h
+++ b/xen/include/xen/keyhandler.h
@@ -1,53 +1,48 @@
 /******************************************************************************
  * keyhandler.h
- * 
+ *
  * We keep an array of 'handlers' for each key code between 0 and 255;
- * this is intended to allow very simple debugging routines (toggle 
+ * this is intended to allow very simple debugging routines (toggle
  * debug flag, dump registers, reboot, etc) to be hooked in in a slightly
- * nicer fashion than just editing the serial/keyboard drivers. 
+ * nicer fashion than just editing the serial/keyboard drivers.
  */
 
 #ifndef __XEN_KEYHANDLER_H__
 #define __XEN_KEYHANDLER_H__
 
-typedef void keyhandler_fn_t(
-    unsigned char key);
-typedef void irq_keyhandler_fn_t(
-    unsigned char key, struct cpu_user_regs *regs);
-
-struct keyhandler {
-    /*
-     * If TRUE then u.irq_fn is called in hardirq context with interrupts
-     * disabled. The @regs callback parameter points at the interrupted
-     * register context. 
-     * If FALSE then u.fn is called in softirq context with no locks held and
-     * interrupts enabled.
-     */
-    bool_t irq_callback;
-
-    /*
-     * If TRUE then the keyhandler will be included in the "dump everything"
-     * keyhandler, so must not have any side-effects.
-     */
-    bool_t diagnostic;
-
-    union {
-        keyhandler_fn_t *fn;
-        irq_keyhandler_fn_t *irq_fn;
-    } u;
-
-    /* The string is not copied by register_keyhandler(), so must persist. */
-    char *desc;
-};
-
-/* Initialize keytable with default handlers */
-extern void initialize_keytable(void);
+#include <xen/types.h>
 
 /*
- * Register a callback handler for key @key. The keyhandler structure is not
- * copied, so must persist.
+ * Callback type for keyhander.
+ *
+ * Called in softirq context with interrupts enabled.
  */
-extern void register_keyhandler(unsigned char key, struct keyhandler *handler);
+typedef void (keyhandler_fn_t)(unsigned char key);
+
+/*
+ * Callback type for irq_keyhandler.
+ *
+ * Called in hardirq context with interrupts disabled.
+ */
+typedef void (irq_keyhandler_fn_t)(unsigned char key,
+                                   struct cpu_user_regs *regs);
+
+/* Initialize keytable with default handlers. */
+void initialize_keytable(void);
+
+/*
+ * Regiser a callback handler for key @key for either plain or irq context.
+ * If @diagnostic is set, the handler will be included in the "dump
+ * everything" keyhandler.
+ */
+void register_keyhandler(unsigned char key,
+                         keyhandler_fn_t *fn,
+                         const char *desc,
+                         bool_t diagnostic);
+void register_irq_keyhandler(unsigned char key,
+                             irq_keyhandler_fn_t *fn,
+                             const char *desc,
+                             bool_t diagnostic);
 
 /* Inject a keypress into the key-handling subsystem. */
 extern void handle_keypress(unsigned char key, struct cpu_user_regs *regs);
-- 
1.7.10.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.