~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to xen/common/keyhandler.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include <xeno/keyhandler.h> 
2
 
#include <xeno/reboot.h>
3
 
 
4
 
#define KEY_MAX 256
5
 
#define STR_MAX  64
6
 
 
7
 
typedef struct _key_te { 
8
 
    key_handler *handler; 
9
 
    char         desc[STR_MAX]; 
10
 
} key_te_t; 
11
 
 
12
 
static key_te_t key_table[KEY_MAX]; 
13
 
    
14
 
void add_key_handler(u_char key, key_handler *handler, char *desc) 
15
 
{
16
 
    int i; 
17
 
    char *str; 
18
 
 
19
 
    if(key_table[key].handler != NULL) 
20
 
        printk("Warning: overwriting handler for key 0x%x\n", key); 
21
 
 
22
 
    key_table[key].handler = handler; 
23
 
 
24
 
    str = key_table[key].desc; 
25
 
    for(i = 0; i < STR_MAX; i++) {
26
 
        if(*desc) 
27
 
            *str++ = *desc++; 
28
 
        else break; 
29
 
    }
30
 
    if (i == STR_MAX) 
31
 
        key_table[key].desc[STR_MAX-1] = '\0'; 
32
 
 
33
 
    return; 
34
 
}
35
 
 
36
 
key_handler *get_key_handler(u_char key)
37
 
{
38
 
    return key_table[key].handler; 
39
 
}
40
 
 
41
 
 
42
 
static void show_handlers(u_char key, void *dev_id, struct pt_regs *regs) 
43
 
{
44
 
    int i; 
45
 
 
46
 
    printk("'%c' pressed -> showing installed handlers\n", key); 
47
 
    for(i=0; i < KEY_MAX; i++) 
48
 
        if(key_table[i].handler) 
49
 
            printk(" key '%c' (ascii '%02x') => %s\n", 
50
 
                        (i<33 || i>126)?(' '):(i),i,
51
 
                        key_table[i].desc);
52
 
    return; 
53
 
}
54
 
 
55
 
 
56
 
static void dump_registers(u_char key, void *dev_id, struct pt_regs *regs) 
57
 
{
58
 
    extern void show_registers(struct pt_regs *regs); 
59
 
 
60
 
    printk("'%c' pressed -> dumping registers\n", key); 
61
 
    show_registers(regs); 
62
 
    return; 
63
 
}
64
 
 
65
 
static void halt_machine(u_char key, void *dev_id, struct pt_regs *regs) 
66
 
{
67
 
    printk("'%c' pressed -> rebooting machine\n", key); 
68
 
    machine_restart(NULL); 
69
 
    return; 
70
 
}
71
 
 
72
 
static void kill_dom0(u_char key, void *dev_id, struct pt_regs *regs) 
73
 
{
74
 
    printk("'%c' pressed -> gracefully rebooting machine\n", key); 
75
 
    kill_other_domain(0, 0);
76
 
    return;
77
 
}
78
 
 
79
 
 
80
 
/* XXX SMH: this is keir's fault */
81
 
static char *task_states[] = 
82
 
83
 
    "Runnable", 
84
 
    "Interruptible Sleep", 
85
 
    "Uninterruptible Sleep", 
86
 
    NULL, "Stopped", 
87
 
    NULL, NULL, NULL, "Dying", 
88
 
}; 
89
 
 
90
 
void do_task_queues(u_char key, void *dev_id, struct pt_regs *regs) 
91
 
{
92
 
    unsigned long       flags; 
93
 
    struct task_struct *p; 
94
 
    shared_info_t      *s; 
95
 
    net_vif_t          *v;
96
 
 
97
 
    printk("'%c' pressed -> dumping task queues\n", key); 
98
 
 
99
 
    read_lock_irqsave(&tasklist_lock, flags); 
100
 
 
101
 
    p = &idle0_task;
102
 
    do {
103
 
        printk("Xen: DOM %d, CPU %d [has=%c], state = %s, "
104
 
               "hyp_events = %08x\n", 
105
 
               p->domain, p->processor, p->has_cpu ? 'T':'F', 
106
 
               task_states[p->state], p->hyp_events); 
107
 
        s = p->shared_info; 
108
 
        if( !is_idle_task(p) )
109
 
        {
110
 
            printk("Guest: events = %08lx, events_mask = %08lx\n", 
111
 
                   s->events, s->events_mask); 
112
 
          
113
 
            if ( (v = find_vif_by_id((p->domain)<<VIF_DOMAIN_SHIFT)) != NULL )
114
 
            {
115
 
                printk("rx_prod=%d ,rx_cons=%d, tx_prod=%d, tx_cons=%d\n",
116
 
                       v->rx_prod, v->rx_cons, v->tx_prod, v->tx_cons );
117
 
                printk("rx_req_cons=%d, rx_resp_prod=%d, "
118
 
                       "tx_req_cons=%d, tx_resp_prod=%d\n", 
119
 
                       v->rx_req_cons, v->rx_resp_prod, 
120
 
                       v->tx_req_cons, v->tx_resp_prod);
121
 
                put_vif(v);
122
 
            }
123
 
            printk("Notifying guest...\n"); 
124
 
            set_bit(_EVENT_DEBUG, &s->events); 
125
 
        }
126
 
    } while ( (p = p->next_task) != &idle0_task );
127
 
 
128
 
    read_unlock_irqrestore(&tasklist_lock, flags); 
129
 
}
130
 
 
131
 
extern void perfc_printall (u_char key, void *dev_id, struct pt_regs *regs);
132
 
extern void perfc_reset (u_char key, void *dev_id, struct pt_regs *regs);
133
 
extern void dump_runq(u_char key, void *dev_id, struct pt_regs *regs);
134
 
extern void print_sched_histo(u_char key, void *dev_id, struct pt_regs *regs);
135
 
extern void reset_sched_histo(u_char key, void *dev_id, struct pt_regs *regs);
136
 
 
137
 
 
138
 
void initialize_keytable() 
139
 
{
140
 
    int i; 
141
 
 
142
 
    /* first initialize key handler table */
143
 
    for(i = 0; i < KEY_MAX; i++) 
144
 
        key_table[i].handler = (key_handler *)NULL; 
145
 
        
146
 
    /* setup own handlers */
147
 
    add_key_handler('d', dump_registers, "dump registers"); 
148
 
    add_key_handler('h', show_handlers, "show this message");
149
 
    add_key_handler('l', print_sched_histo, "print sched latency histogram");
150
 
    add_key_handler('L', reset_sched_histo, "reset sched latency histogram");
151
 
    add_key_handler('p', perfc_printall, "print performance counters"); 
152
 
    add_key_handler('P', perfc_reset,    "reset performance counters"); 
153
 
    add_key_handler('q', do_task_queues, "dump task queues + guest state");
154
 
    add_key_handler('r', dump_runq,      "dump run queues");
155
 
    add_key_handler('B', kill_dom0,      "reboot machine gracefully"); 
156
 
    add_key_handler('R', halt_machine,   "reboot machine ungracefully"); 
157
 
    return; 
158
 
}
 
1
/******************************************************************************
 
2
 * keyhandler.c
 
3
 */
 
4
 
 
5
#include <asm/regs.h>
 
6
#include <xen/keyhandler.h> 
 
7
#include <xen/shutdown.h>
 
8
#include <xen/event.h>
 
9
#include <xen/console.h>
 
10
#include <xen/serial.h>
 
11
#include <xen/sched.h>
 
12
#include <xen/softirq.h>
 
13
#include <xen/domain.h>
 
14
#include <xen/rangeset.h>
 
15
#include <xen/compat.h>
 
16
#include <xen/ctype.h>
 
17
#include <asm/debugger.h>
 
18
#include <asm/div64.h>
 
19
 
 
20
static struct keyhandler *key_table[256];
 
21
static unsigned char keypress_key;
 
22
 
 
23
char keyhandler_scratch[1024];
 
24
 
 
25
static void keypress_action(unsigned long unused)
 
26
{
 
27
    handle_keypress(keypress_key, NULL);
 
28
}
 
29
 
 
30
static DECLARE_TASKLET(keypress_tasklet, keypress_action, 0);
 
31
 
 
32
void handle_keypress(unsigned char key, struct cpu_user_regs *regs)
 
33
{
 
34
    struct keyhandler *h;
 
35
 
 
36
    if ( (h = key_table[key]) == NULL )
 
37
        return;
 
38
 
 
39
    if ( !in_irq() || h->irq_callback )
 
40
    {
 
41
        console_start_log_everything();
 
42
        h->irq_callback ? (*h->u.irq_fn)(key, regs) : (*h->u.fn)(key);
 
43
        console_end_log_everything();
 
44
    }
 
45
    else
 
46
    {
 
47
        keypress_key = key;
 
48
        tasklet_schedule(&keypress_tasklet);
 
49
    }
 
50
}
 
51
 
 
52
void register_keyhandler(unsigned char key, struct keyhandler *handler)
 
53
{
 
54
    ASSERT(key_table[key] == NULL);
 
55
    key_table[key] = handler;
 
56
}
 
57
 
 
58
static void show_handlers(unsigned char key)
 
59
{
 
60
    int i;
 
61
    printk("'%c' pressed -> showing installed handlers\n", key);
 
62
    for ( i = 0; i < ARRAY_SIZE(key_table); i++ ) 
 
63
        if ( key_table[i] != NULL ) 
 
64
            printk(" key '%c' (ascii '%02x') => %s\n", 
 
65
                   isprint(i) ? i : ' ', i, key_table[i]->desc);
 
66
}
 
67
 
 
68
static struct keyhandler show_handlers_keyhandler = {
 
69
    .u.fn = show_handlers,
 
70
    .desc = "show this message"
 
71
};
 
72
 
 
73
static void __dump_execstate(void *unused)
 
74
{
 
75
    dump_execution_state();
 
76
    printk("*** Dumping CPU%d guest state: ***\n", smp_processor_id());
 
77
    if ( is_idle_vcpu(current) )
 
78
        printk("No guest context (CPU is idle).\n");
 
79
    else
 
80
        show_execution_state(guest_cpu_user_regs());
 
81
}
 
82
 
 
83
static void dump_registers(unsigned char key, struct cpu_user_regs *regs)
 
84
{
 
85
    unsigned int cpu;
 
86
 
 
87
    /* We want to get everything out that we possibly can. */
 
88
    watchdog_disable();
 
89
    console_start_sync();
 
90
 
 
91
    printk("'%c' pressed -> dumping registers\n", key);
 
92
 
 
93
    /* Get local execution state out immediately, in case we get stuck. */
 
94
    printk("\n*** Dumping CPU%d host state: ***\n", smp_processor_id());
 
95
    __dump_execstate(NULL);
 
96
 
 
97
    for_each_online_cpu ( cpu )
 
98
    {
 
99
        if ( cpu == smp_processor_id() )
 
100
            continue;
 
101
        printk("\n*** Dumping CPU%d host state: ***\n", cpu);
 
102
        on_selected_cpus(cpumask_of(cpu), __dump_execstate, NULL, 1);
 
103
    }
 
104
 
 
105
    printk("\n");
 
106
 
 
107
    console_end_sync();
 
108
    watchdog_enable();
 
109
}
 
110
 
 
111
static struct keyhandler dump_registers_keyhandler = {
 
112
    .irq_callback = 1,
 
113
    .diagnostic = 1,
 
114
    .u.irq_fn = dump_registers,
 
115
    .desc = "dump registers"
 
116
};
 
117
 
 
118
static void dump_dom0_registers(unsigned char key)
 
119
{
 
120
    struct vcpu *v;
 
121
 
 
122
    if ( dom0 == NULL )
 
123
        return;
 
124
 
 
125
    printk("'%c' pressed -> dumping Dom0's registers\n", key);
 
126
 
 
127
    for_each_vcpu ( dom0, v )
 
128
        vcpu_show_execution_state(v);
 
129
}
 
130
 
 
131
static struct keyhandler dump_dom0_registers_keyhandler = {
 
132
    .diagnostic = 1,
 
133
    .u.fn = dump_dom0_registers,
 
134
    .desc = "dump Dom0 registers"
 
135
};
 
136
 
 
137
static void reboot_machine(unsigned char key, struct cpu_user_regs *regs)
 
138
{
 
139
    printk("'%c' pressed -> rebooting machine\n", key);
 
140
    machine_restart(0);
 
141
}
 
142
 
 
143
static struct keyhandler reboot_machine_keyhandler = {
 
144
    .irq_callback = 1,
 
145
    .u.irq_fn = reboot_machine,
 
146
    .desc = "reboot machine"
 
147
};
 
148
 
 
149
static void cpuset_print(char *set, int size, cpumask_t mask)
 
150
{
 
151
    *set++ = '{';
 
152
    set += cpulist_scnprintf(set, size-2, mask);
 
153
    *set++ = '}';
 
154
    *set++ = '\0';
 
155
}
 
156
 
 
157
static void periodic_timer_print(char *str, int size, uint64_t period)
 
158
{
 
159
    if ( period == 0 )
 
160
    {
 
161
        strlcpy(str, "No periodic timer", size);
 
162
        return;
 
163
    }
 
164
 
 
165
    snprintf(str, size,
 
166
             "%u Hz periodic timer (period %u ms)",
 
167
             1000000000/(int)period, (int)period/1000000);
 
168
}
 
169
 
 
170
static void dump_domains(unsigned char key)
 
171
{
 
172
    struct domain *d;
 
173
    struct vcpu   *v;
 
174
    s_time_t       now = NOW();
 
175
#define tmpstr keyhandler_scratch
 
176
 
 
177
    printk("'%c' pressed -> dumping domain info (now=0x%X:%08X)\n", key,
 
178
           (u32)(now>>32), (u32)now);
 
179
 
 
180
    rcu_read_lock(&domlist_read_lock);
 
181
 
 
182
    for_each_domain ( d )
 
183
    {
 
184
        printk("General information for domain %u:\n", d->domain_id);
 
185
        cpuset_print(tmpstr, sizeof(tmpstr), d->domain_dirty_cpumask);
 
186
        printk("    refcnt=%d dying=%d nr_pages=%d xenheap_pages=%d "
 
187
               "dirty_cpus=%s max_pages=%u\n",
 
188
               atomic_read(&d->refcnt), d->is_dying,
 
189
               d->tot_pages, d->xenheap_pages, tmpstr, d->max_pages);
 
190
        printk("    handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-"
 
191
               "%02x%02x-%02x%02x%02x%02x%02x%02x vm_assist=%08lx\n",
 
192
               d->handle[ 0], d->handle[ 1], d->handle[ 2], d->handle[ 3],
 
193
               d->handle[ 4], d->handle[ 5], d->handle[ 6], d->handle[ 7],
 
194
               d->handle[ 8], d->handle[ 9], d->handle[10], d->handle[11],
 
195
               d->handle[12], d->handle[13], d->handle[14], d->handle[15],
 
196
               d->vm_assist);
 
197
 
 
198
        arch_dump_domain_info(d);
 
199
 
 
200
        rangeset_domain_printk(d);
 
201
 
 
202
        dump_pageframe_info(d);
 
203
               
 
204
        printk("VCPU information and callbacks for domain %u:\n",
 
205
               d->domain_id);
 
206
        for_each_vcpu ( d, v ) {
 
207
            printk("    VCPU%d: CPU%d [has=%c] flags=%lx poll=%d "
 
208
                   "upcall_pend = %02x, upcall_mask = %02x ",
 
209
                   v->vcpu_id, v->processor,
 
210
                   v->is_running ? 'T':'F',
 
211
                   v->pause_flags, v->poll_evtchn,
 
212
                   vcpu_info(v, evtchn_upcall_pending),
 
213
                   vcpu_info(v, evtchn_upcall_mask));
 
214
            cpuset_print(tmpstr, sizeof(tmpstr), v->vcpu_dirty_cpumask);
 
215
            printk("dirty_cpus=%s ", tmpstr);
 
216
            cpuset_print(tmpstr, sizeof(tmpstr), v->cpu_affinity);
 
217
            printk("cpu_affinity=%s\n", tmpstr);
 
218
            arch_dump_vcpu_info(v);
 
219
            periodic_timer_print(tmpstr, sizeof(tmpstr), v->periodic_period);
 
220
            printk("    %s\n", tmpstr);
 
221
            printk("    Notifying guest (virq %d, port %d, stat %d/%d/%d)\n",
 
222
                   VIRQ_DEBUG, v->virq_to_evtchn[VIRQ_DEBUG],
 
223
                   test_bit(v->virq_to_evtchn[VIRQ_DEBUG], 
 
224
                            &shared_info(d, evtchn_pending)),
 
225
                   test_bit(v->virq_to_evtchn[VIRQ_DEBUG], 
 
226
                            &shared_info(d, evtchn_mask)),
 
227
                   test_bit(v->virq_to_evtchn[VIRQ_DEBUG] /
 
228
                            BITS_PER_EVTCHN_WORD(d),
 
229
                            &vcpu_info(v, evtchn_pending_sel)));
 
230
            send_guest_vcpu_virq(v, VIRQ_DEBUG);
 
231
        }
 
232
    }
 
233
 
 
234
    rcu_read_unlock(&domlist_read_lock);
 
235
#undef tmpstr
 
236
}
 
237
 
 
238
static struct keyhandler dump_domains_keyhandler = {
 
239
    .diagnostic = 1,
 
240
    .u.fn = dump_domains,
 
241
    .desc = "dump domain (and guest debug) info"
 
242
};
 
243
 
 
244
static cpumask_t read_clocks_cpumask = CPU_MASK_NONE;
 
245
static s_time_t read_clocks_time[NR_CPUS];
 
246
static u64 read_cycles_time[NR_CPUS];
 
247
 
 
248
static void read_clocks_slave(void *unused)
 
249
{
 
250
    unsigned int cpu = smp_processor_id();
 
251
    local_irq_disable();
 
252
    while ( !cpu_isset(cpu, read_clocks_cpumask) )
 
253
        cpu_relax();
 
254
    read_clocks_time[cpu] = NOW();
 
255
    read_cycles_time[cpu] = get_cycles();
 
256
    cpu_clear(cpu, read_clocks_cpumask);
 
257
    local_irq_enable();
 
258
}
 
259
 
 
260
static void read_clocks(unsigned char key)
 
261
{
 
262
    unsigned int cpu = smp_processor_id(), min_stime_cpu, max_stime_cpu;
 
263
    unsigned int min_cycles_cpu, max_cycles_cpu;
 
264
    u64 min_stime, max_stime, dif_stime;
 
265
    u64 min_cycles, max_cycles, dif_cycles;
 
266
    static u64 sumdif_stime = 0, maxdif_stime = 0;
 
267
    static u64 sumdif_cycles = 0, maxdif_cycles = 0;
 
268
    static u32 count = 0;
 
269
    static DEFINE_SPINLOCK(lock);
 
270
 
 
271
    spin_lock(&lock);
 
272
 
 
273
    smp_call_function(read_clocks_slave, NULL, 0);
 
274
 
 
275
    local_irq_disable();
 
276
    read_clocks_cpumask = cpu_online_map;
 
277
    read_clocks_time[cpu] = NOW();
 
278
    read_cycles_time[cpu] = get_cycles();
 
279
    cpu_clear(cpu, read_clocks_cpumask);
 
280
    local_irq_enable();
 
281
 
 
282
    while ( !cpus_empty(read_clocks_cpumask) )
 
283
        cpu_relax();
 
284
 
 
285
    min_stime_cpu = max_stime_cpu = min_cycles_cpu = max_cycles_cpu = cpu;
 
286
    for_each_online_cpu ( cpu )
 
287
    {
 
288
        if ( read_clocks_time[cpu] < read_clocks_time[min_stime_cpu] )
 
289
            min_stime_cpu = cpu;
 
290
        if ( read_clocks_time[cpu] > read_clocks_time[max_stime_cpu] )
 
291
            max_stime_cpu = cpu;
 
292
        if ( read_cycles_time[cpu] < read_cycles_time[min_cycles_cpu] )
 
293
            min_cycles_cpu = cpu;
 
294
        if ( read_cycles_time[cpu] > read_cycles_time[max_cycles_cpu] )
 
295
            max_cycles_cpu = cpu;
 
296
    }
 
297
 
 
298
    min_stime = read_clocks_time[min_stime_cpu];
 
299
    max_stime = read_clocks_time[max_stime_cpu];
 
300
    min_cycles = read_cycles_time[min_cycles_cpu];
 
301
    max_cycles = read_cycles_time[max_cycles_cpu];
 
302
 
 
303
    spin_unlock(&lock);
 
304
 
 
305
    dif_stime = max_stime - min_stime;
 
306
    if ( dif_stime > maxdif_stime )
 
307
        maxdif_stime = dif_stime;
 
308
    sumdif_stime += dif_stime;
 
309
    dif_cycles = max_cycles - min_cycles;
 
310
    if ( dif_cycles > maxdif_cycles )
 
311
        maxdif_cycles = dif_cycles;
 
312
    sumdif_cycles += dif_cycles;
 
313
    count++;
 
314
    printk("Synced stime skew: max=%"PRIu64"ns avg=%"PRIu64"ns "
 
315
           "samples=%"PRIu32" current=%"PRIu64"ns\n",
 
316
           maxdif_stime, sumdif_stime/count, count, dif_stime);
 
317
    printk("Synced cycles skew: max=%"PRIu64" avg=%"PRIu64" "
 
318
           "samples=%"PRIu32" current=%"PRIu64"\n",
 
319
           maxdif_cycles, sumdif_cycles/count, count, dif_cycles);
 
320
}
 
321
 
 
322
static struct keyhandler read_clocks_keyhandler = {
 
323
    .diagnostic = 1,
 
324
    .u.fn = read_clocks,
 
325
    .desc = "display multi-cpu clock info"
 
326
};
 
327
 
 
328
extern void dump_runq(unsigned char key);
 
329
static struct keyhandler dump_runq_keyhandler = {
 
330
    .diagnostic = 1,
 
331
    .u.fn = dump_runq,
 
332
    .desc = "dump run queues"
 
333
};
 
334
 
 
335
#ifdef PERF_COUNTERS
 
336
extern void perfc_printall(unsigned char key);
 
337
static struct keyhandler perfc_printall_keyhandler = {
 
338
    .diagnostic = 1,
 
339
    .u.fn = perfc_printall,
 
340
    .desc = "print performance counters"
 
341
};
 
342
extern void perfc_reset(unsigned char key);
 
343
static struct keyhandler perfc_reset_keyhandler = {
 
344
    .u.fn = perfc_reset,
 
345
    .desc = "reset performance counters"
 
346
};
 
347
#endif
 
348
 
 
349
#ifdef LOCK_PROFILE
 
350
extern void spinlock_profile_printall(unsigned char key);
 
351
static struct keyhandler spinlock_printall_keyhandler = {
 
352
    .diagnostic = 1,
 
353
    .u.fn = spinlock_profile_printall,
 
354
    .desc = "print lock profile info"
 
355
};
 
356
extern void spinlock_profile_reset(unsigned char key);
 
357
static struct keyhandler spinlock_reset_keyhandler = {
 
358
    .u.fn = spinlock_profile_reset,
 
359
    .desc = "reset lock profile info"
 
360
};
 
361
#endif
 
362
 
 
363
static void run_all_nonirq_keyhandlers(unsigned long unused)
 
364
{
 
365
    /* Fire all the non-IRQ-context diagnostic keyhandlers */
 
366
    struct keyhandler *h;
 
367
    int k;
 
368
 
 
369
    console_start_log_everything();
 
370
    for ( k = 0; k < ARRAY_SIZE(key_table); k++ )
 
371
    {
 
372
        h = key_table[k];
 
373
        if ( (h == NULL) || !h->diagnostic || h->irq_callback )
 
374
            continue;
 
375
        printk("[%c: %s]\n", k, h->desc);
 
376
        (*h->u.fn)(k);
 
377
    }
 
378
    console_end_log_everything();
 
379
}
 
380
 
 
381
static DECLARE_TASKLET(run_all_keyhandlers_tasklet,
 
382
                       run_all_nonirq_keyhandlers, 0);
 
383
 
 
384
static void run_all_keyhandlers(unsigned char key, struct cpu_user_regs *regs)
 
385
{
 
386
    struct keyhandler *h;
 
387
    int k;
 
388
 
 
389
    printk("'%c' pressed -> firing all diagnostic keyhandlers\n", key);
 
390
 
 
391
    /* Fire all the IRQ-context diangostic keyhandlers now */
 
392
    console_start_log_everything();
 
393
    for ( k = 0; k < ARRAY_SIZE(key_table); k++ )
 
394
    {
 
395
        h = key_table[k];
 
396
        if ( (h == NULL) || !h->diagnostic || !h->irq_callback )
 
397
            continue;
 
398
        printk("[%c: %s]\n", k, h->desc);
 
399
        (*h->u.irq_fn)(k, regs);
 
400
    }
 
401
    console_end_log_everything();
 
402
 
 
403
    /* Trigger the others from a tasklet in non-IRQ context */
 
404
    tasklet_schedule(&run_all_keyhandlers_tasklet);
 
405
}
 
406
 
 
407
static struct keyhandler run_all_keyhandlers_keyhandler = {
 
408
    .irq_callback = 1,
 
409
    .u.irq_fn = run_all_keyhandlers,
 
410
    .desc = "print all diagnostics"
 
411
};
 
412
 
 
413
static void do_debug_key(unsigned char key, struct cpu_user_regs *regs)
 
414
{
 
415
    printk("'%c' pressed -> trapping into debugger\n", key);
 
416
    (void)debugger_trap_fatal(0xf001, regs);
 
417
    nop(); /* Prevent the compiler doing tail call
 
418
                             optimisation, as that confuses xendbg a
 
419
                             bit. */
 
420
}
 
421
 
 
422
static struct keyhandler do_debug_key_keyhandler = {
 
423
    .irq_callback = 1,
 
424
    .u.irq_fn = do_debug_key,
 
425
    .desc = "trap to xendbg"
 
426
};
 
427
 
 
428
void __init initialize_keytable(void)
 
429
{
 
430
    register_keyhandler('d', &dump_registers_keyhandler);
 
431
    register_keyhandler('h', &show_handlers_keyhandler);
 
432
    register_keyhandler('q', &dump_domains_keyhandler);
 
433
    register_keyhandler('r', &dump_runq_keyhandler);
 
434
    register_keyhandler('R', &reboot_machine_keyhandler);
 
435
    register_keyhandler('t', &read_clocks_keyhandler);
 
436
    register_keyhandler('0', &dump_dom0_registers_keyhandler);
 
437
    register_keyhandler('%', &do_debug_key_keyhandler);
 
438
    register_keyhandler('*', &run_all_keyhandlers_keyhandler);
 
439
 
 
440
#ifdef PERF_COUNTERS
 
441
    register_keyhandler('p', &perfc_printall_keyhandler);
 
442
    register_keyhandler('P', &perfc_reset_keyhandler);
 
443
#endif
 
444
 
 
445
#ifdef LOCK_PROFILE
 
446
    register_keyhandler('l', &spinlock_printall_keyhandler);
 
447
    register_keyhandler('L', &spinlock_reset_keyhandler);
 
448
#endif
 
449
 
 
450
}
 
451
 
 
452
/*
 
453
 * Local variables:
 
454
 * mode: C
 
455
 * c-set-style: "BSD"
 
456
 * c-basic-offset: 4
 
457
 * tab-width: 4
 
458
 * indent-tabs-mode: nil
 
459
 * End:
 
460
 */