ia64/xen-unstable

view xen/common/keyhandler.c @ 15717:c229802cedbb

[32on64] Copy the right grant table status code back to the guest.

Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
author Ian Campbell <ian.campbell@xensource.com>
date Mon Aug 06 13:19:44 2007 +0100 (2007-08-06)
parents 3c28bc13a3f8
children 1c85fe14169f
line source
1 /******************************************************************************
2 * keyhandler.c
3 */
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 <asm/debugger.h>
17 #include <asm/div64.h>
19 #define KEY_MAX 256
20 #define STR_MAX 64
22 static struct {
23 union {
24 keyhandler_t *handler;
25 irq_keyhandler_t *irq_handler;
26 } u;
27 unsigned int flags;
28 char desc[STR_MAX];
29 } key_table[KEY_MAX];
31 #define KEYHANDLER_IRQ_CALLBACK 0x1
33 static unsigned char keypress_key;
35 static void keypress_softirq(void)
36 {
37 keyhandler_t *h;
38 unsigned char key = keypress_key;
39 console_start_log_everything();
40 if ( (h = key_table[key].u.handler) != NULL )
41 (*h)(key);
42 console_end_log_everything();
43 }
45 void handle_keypress(unsigned char key, struct cpu_user_regs *regs)
46 {
47 irq_keyhandler_t *h;
49 if ( !in_irq() || (key_table[key].flags & KEYHANDLER_IRQ_CALLBACK) )
50 {
51 console_start_log_everything();
52 if ( (h = key_table[key].u.irq_handler) != NULL )
53 (*h)(key, regs);
54 console_end_log_everything();
55 }
56 else
57 {
58 keypress_key = key;
59 raise_softirq(KEYPRESS_SOFTIRQ);
60 }
61 }
63 void register_keyhandler(
64 unsigned char key, keyhandler_t *handler, char *desc)
65 {
66 ASSERT(key_table[key].u.handler == NULL);
67 key_table[key].u.handler = handler;
68 key_table[key].flags = 0;
69 safe_strcpy(key_table[key].desc, desc);
70 }
72 void register_irq_keyhandler(
73 unsigned char key, irq_keyhandler_t *handler, char *desc)
74 {
75 ASSERT(key_table[key].u.irq_handler == NULL);
76 key_table[key].u.irq_handler = handler;
77 key_table[key].flags = KEYHANDLER_IRQ_CALLBACK;
78 safe_strcpy(key_table[key].desc, desc);
79 }
81 static void show_handlers(unsigned char key)
82 {
83 int i;
84 printk("'%c' pressed -> showing installed handlers\n", key);
85 for ( i = 0; i < KEY_MAX; i++ )
86 if ( key_table[i].u.handler != NULL )
87 printk(" key '%c' (ascii '%02x') => %s\n",
88 (i<33 || i>126)?(' '):(i),i,
89 key_table[i].desc);
90 }
92 static void __dump_execstate(void *unused)
93 {
94 dump_execution_state();
95 printk("*** Dumping CPU%d guest state: ***\n", smp_processor_id());
96 if ( is_idle_vcpu(current) )
97 printk("No guest context (CPU is idle).\n");
98 else
99 show_execution_state(guest_cpu_user_regs());
100 }
102 static void dump_registers(unsigned char key, struct cpu_user_regs *regs)
103 {
104 unsigned int cpu;
106 printk("'%c' pressed -> dumping registers\n", key);
108 /* Get local execution state out immediately, in case we get stuck. */
109 printk("\n*** Dumping CPU%d host state: ***\n", smp_processor_id());
110 __dump_execstate(NULL);
112 for_each_online_cpu ( cpu )
113 {
114 if ( cpu == smp_processor_id() )
115 continue;
116 printk("\n*** Dumping CPU%d host state: ***\n", cpu);
117 on_selected_cpus(cpumask_of_cpu(cpu), __dump_execstate, NULL, 1, 1);
118 }
120 printk("\n");
121 }
123 static void halt_machine(unsigned char key, struct cpu_user_regs *regs)
124 {
125 printk("'%c' pressed -> rebooting machine\n", key);
126 machine_restart(NULL);
127 }
129 static void cpuset_print(char *set, int size, cpumask_t mask)
130 {
131 *set++ = '{';
132 set += cpulist_scnprintf(set, size-2, mask);
133 *set++ = '}';
134 *set++ = '\0';
135 }
137 static void periodic_timer_print(char *str, int size, uint64_t period)
138 {
139 if ( period == 0 )
140 {
141 strlcpy(str, "No periodic timer", size);
142 return;
143 }
145 snprintf(str, size,
146 "%u Hz periodic timer (period %u ms)",
147 1000000000/(int)period, (int)period/1000000);
148 }
150 static void dump_domains(unsigned char key)
151 {
152 struct domain *d;
153 struct vcpu *v;
154 s_time_t now = NOW();
155 char tmpstr[100];
157 printk("'%c' pressed -> dumping domain info (now=0x%X:%08X)\n", key,
158 (u32)(now>>32), (u32)now);
160 rcu_read_lock(&domlist_read_lock);
162 for_each_domain ( d )
163 {
164 printk("General information for domain %u:\n", d->domain_id);
165 cpuset_print(tmpstr, sizeof(tmpstr), d->domain_dirty_cpumask);
166 printk(" refcnt=%d nr_pages=%d xenheap_pages=%d "
167 "dirty_cpus=%s\n",
168 atomic_read(&d->refcnt),
169 d->tot_pages, d->xenheap_pages, tmpstr);
170 printk(" handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-"
171 "%02x%02x-%02x%02x%02x%02x%02x%02x vm_assist=%08lx\n",
172 d->handle[ 0], d->handle[ 1], d->handle[ 2], d->handle[ 3],
173 d->handle[ 4], d->handle[ 5], d->handle[ 6], d->handle[ 7],
174 d->handle[ 8], d->handle[ 9], d->handle[10], d->handle[11],
175 d->handle[12], d->handle[13], d->handle[14], d->handle[15],
176 d->vm_assist);
178 arch_dump_domain_info(d);
180 rangeset_domain_printk(d);
182 dump_pageframe_info(d);
184 printk("VCPU information and callbacks for domain %u:\n",
185 d->domain_id);
186 for_each_vcpu ( d, v ) {
187 printk(" VCPU%d: CPU%d [has=%c] flags=%lx "
188 "upcall_pend = %02x, upcall_mask = %02x ",
189 v->vcpu_id, v->processor,
190 v->is_running ? 'T':'F',
191 v->pause_flags,
192 vcpu_info(v, evtchn_upcall_pending),
193 vcpu_info(v, evtchn_upcall_mask));
194 cpuset_print(tmpstr, sizeof(tmpstr), v->vcpu_dirty_cpumask);
195 printk("dirty_cpus=%s ", tmpstr);
196 cpuset_print(tmpstr, sizeof(tmpstr), v->cpu_affinity);
197 printk("cpu_affinity=%s\n", tmpstr);
198 arch_dump_vcpu_info(v);
199 periodic_timer_print(tmpstr, sizeof(tmpstr), v->periodic_period);
200 printk(" %s\n", tmpstr);
201 printk(" Notifying guest (virq %d, port %d, stat %d/%d/%d)\n",
202 VIRQ_DEBUG, v->virq_to_evtchn[VIRQ_DEBUG],
203 test_bit(v->virq_to_evtchn[VIRQ_DEBUG],
204 shared_info_addr(d, evtchn_pending)),
205 test_bit(v->virq_to_evtchn[VIRQ_DEBUG],
206 shared_info_addr(d, evtchn_mask)),
207 test_bit(v->virq_to_evtchn[VIRQ_DEBUG] /
208 BITS_PER_GUEST_LONG(d),
209 vcpu_info_addr(v, evtchn_pending_sel)));
210 send_guest_vcpu_virq(v, VIRQ_DEBUG);
211 }
212 }
214 rcu_read_unlock(&domlist_read_lock);
215 }
217 static cpumask_t read_clocks_cpumask = CPU_MASK_NONE;
218 static s_time_t read_clocks_time[NR_CPUS];
220 static void read_clocks_slave(void *unused)
221 {
222 unsigned int cpu = smp_processor_id();
223 while ( !cpu_isset(cpu, read_clocks_cpumask) )
224 cpu_relax();
225 read_clocks_time[cpu] = NOW();
226 cpu_clear(cpu, read_clocks_cpumask);
227 }
229 static void read_clocks(unsigned char key)
230 {
231 unsigned int cpu = smp_processor_id(), min_cpu, max_cpu;
232 u64 min, max, dif, difus;
233 static DEFINE_SPINLOCK(lock);
235 spin_lock(&lock);
237 smp_call_function(read_clocks_slave, NULL, 0, 0);
239 local_irq_disable();
240 read_clocks_cpumask = cpu_online_map;
241 read_clocks_time[cpu] = NOW();
242 cpu_clear(cpu, read_clocks_cpumask);
243 local_irq_enable();
245 while ( !cpus_empty(read_clocks_cpumask) )
246 cpu_relax();
248 min_cpu = max_cpu = cpu;
249 for_each_online_cpu ( cpu )
250 {
251 if ( read_clocks_time[cpu] < read_clocks_time[min_cpu] )
252 min_cpu = cpu;
253 if ( read_clocks_time[cpu] > read_clocks_time[max_cpu] )
254 max_cpu = cpu;
255 }
257 min = read_clocks_time[min_cpu];
258 max = read_clocks_time[max_cpu];
260 spin_unlock(&lock);
262 dif = difus = max - min;
263 do_div(difus, 1000);
264 printk("Min = %"PRIu64" ; Max = %"PRIu64" ; Diff = %"PRIu64
265 " (%"PRIu64" microseconds)\n",
266 min, max, dif, difus);
267 }
269 extern void dump_runq(unsigned char key);
271 #ifdef PERF_COUNTERS
272 extern void perfc_printall(unsigned char key);
273 extern void perfc_reset(unsigned char key);
274 #endif
276 static void do_debug_key(unsigned char key, struct cpu_user_regs *regs)
277 {
278 (void)debugger_trap_fatal(0xf001, regs);
279 nop(); /* Prevent the compiler doing tail call
280 optimisation, as that confuses xendbg a
281 bit. */
282 }
284 void __init initialize_keytable(void)
285 {
286 open_softirq(KEYPRESS_SOFTIRQ, keypress_softirq);
288 register_irq_keyhandler(
289 'd', dump_registers, "dump registers");
290 register_keyhandler(
291 'h', show_handlers, "show this message");
292 register_keyhandler(
293 'q', dump_domains, "dump domain (and guest debug) info");
294 register_keyhandler(
295 'r', dump_runq, "dump run queues");
296 register_irq_keyhandler(
297 'R', halt_machine, "reboot machine");
299 register_keyhandler(
300 't', read_clocks, "display multi-cpu clock info");
302 #ifdef PERF_COUNTERS
303 register_keyhandler(
304 'p', perfc_printall, "print performance counters");
305 register_keyhandler(
306 'P', perfc_reset, "reset performance counters");
307 #endif
309 register_irq_keyhandler('%', do_debug_key, "Trap to xendbg");
310 }
312 /*
313 * Local variables:
314 * mode: C
315 * c-set-style: "BSD"
316 * c-basic-offset: 4
317 * tab-width: 4
318 * indent-tabs-mode: nil
319 * End:
320 */