aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/keyhandler.c
blob: 8bb4fecab0a00e48ee17aaad8417771075a841c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <xeno/keyhandler.h> 
#include <xeno/reboot.h>

extern void perfc_printall (u_char key, void *dev_id, struct pt_regs *regs);

#define KEY_MAX 256
#define STR_MAX  64

typedef struct _key_te { 
    key_handler *handler; 
    char         desc[STR_MAX]; 
} key_te_t; 

static key_te_t key_table[KEY_MAX]; 
    
void add_key_handler(u_char key, key_handler *handler, char *desc) 
{
    int i; 
    char *str; 

    if(key_table[key].handler != NULL) 
	printk("Warning: overwriting handler for key 0x%x\n", key); 

    key_table[key].handler = handler; 

    str = key_table[key].desc; 
    for(i = 0; i < STR_MAX; i++) {
	if(*desc) 
	    *str++ = *desc++; 
	else break; 
    }
    if (i == STR_MAX) 
	key_table[key].desc[STR_MAX-1] = '\0'; 

    return; 
}

key_handler *get_key_handler(u_char key)
{
    return key_table[key].handler; 
}


void show_handlers(u_char key, void *dev_id, struct pt_regs *regs) 
{
    int i; 

    printk("'%c' pressed -> showing installed handlers\n", key); 
    for(i=0; i < KEY_MAX; i++) 
	if(key_table[i].handler) 
	    printk(" key '%c' (ascii '%02x') => %s\n", 
			(i<33 || i>126)?(' '):(i),i,
			key_table[i].desc);
    return; 
}


void dump_registers(u_char key, void *dev_id, struct pt_regs *regs) 
{
    extern void show_registers(struct pt_regs *regs); 

    printk("'%c' pressed -> dumping registers\n", key); 
    show_registers(regs); 
    return; 
}

void halt_machine(u_char key, void *dev_id, struct pt_regs *regs) 
{
    printk("'%c' pressed -> rebooting machine\n", key); 
    machine_restart(NULL); 
    return; 
}



/* XXX SMH: this is keir's fault */
static char *task_states[] = 
{ 
    "Runnable", 
    "Interruptible Sleep", 
    "Uninterruptible Sleep", 
    NULL, "Stopped", 
    NULL, NULL, NULL, "Dying", 
}; 

void do_task_queues(u_char key, void *dev_id, struct pt_regs *regs) 
{
    u_long flags; 
    struct task_struct *p; 
    shared_info_t *s; 

    printk("'%c' pressed -> dumping task queues\n", key); 
    read_lock_irqsave(&tasklist_lock, flags); 
    p = &idle0_task;
    do {
        printk("Xen: DOM %d, CPU %d [has=%c], state = %s, "
	       "hyp_events = %08x\n", 
	       p->domain, p->processor, p->has_cpu ? 'T':'F', 
	       task_states[p->state], p->hyp_events); 
	s = p->shared_info; 
	if(!is_idle_task(p)) {
	    printk("Guest: events = %08lx, event_enable = %08lx\n", 
		   s->events, s->events_enable); 
	    printk("Notifying guest...\n"); 
	    set_bit(_EVENT_DEBUG, &s->events); 
	}
    } while ( (p = p->next_task) != &idle0_task );

    read_unlock_irqrestore(&tasklist_lock, flags); 
}


void initialize_keytable() 
{
    int i; 

    /* first initialize key handler table */
    for(i = 0; i < KEY_MAX; i++) 
	key_table[i].handler = (key_handler *)NULL; 
	
    /* setup own handlers */
    add_key_handler('d', dump_registers, "dump registers"); 
    add_key_handler('h', show_handlers, "show this message");
    add_key_handler('p', perfc_printall, "print performance counters"); 
    add_key_handler('q', do_task_queues, "dump task queues + guest state");
    add_key_handler('R', halt_machine, "reboot machine ungracefully"); 
    
    return; 
}