ia64/xen-unstable

annotate xen/common/keyhandler.c @ 19835:edfdeb150f27

Fix buildsystem to detect udev > version 124

udev removed the udevinfo symlink from versions higher than 123 and
xen's build-system could not detect if udev is in place and has the
required version.

Signed-off-by: Marc-A. Dahlhaus <mad@wol.de>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 25 13:02:37 2009 +0100 (2009-06-25)
parents 2f9e1348aa98
children
rev   line source
kaf24@2970 1 /******************************************************************************
kaf24@2970 2 * keyhandler.c
kaf24@2970 3 */
kaf24@1060 4
cl349@3883 5 #include <asm/regs.h>
kaf24@1210 6 #include <xen/keyhandler.h>
kaf24@10979 7 #include <xen/shutdown.h>
kaf24@1210 8 #include <xen/event.h>
kaf24@1210 9 #include <xen/console.h>
kaf24@1210 10 #include <xen/serial.h>
mwilli2@1246 11 #include <xen/sched.h>
kaf24@2804 12 #include <xen/softirq.h>
cl349@5247 13 #include <xen/domain.h>
kaf24@8456 14 #include <xen/rangeset.h>
ack@13292 15 #include <xen/compat.h>
sos22@3763 16 #include <asm/debugger.h>
kaf24@9247 17 #include <asm/div64.h>
iap10@236 18
iap10@236 19 #define KEY_MAX 256
iap10@236 20 #define STR_MAX 64
iap10@236 21
kaf24@2970 22 static struct {
kaf24@2970 23 union {
kaf24@2970 24 keyhandler_t *handler;
kaf24@2970 25 irq_keyhandler_t *irq_handler;
kaf24@2970 26 } u;
kaf24@2970 27 unsigned int flags;
shand@11156 28 char desc[STR_MAX];
shand@11156 29 } key_table[KEY_MAX];
iap10@236 30
kaf24@2970 31 #define KEYHANDLER_IRQ_CALLBACK 0x1
cl349@2950 32
kaf24@2804 33 static unsigned char keypress_key;
kaf24@2804 34
keir@17445 35 static void keypress_action(unsigned long unused)
kaf24@2804 36 {
kaf24@2970 37 keyhandler_t *h;
kaf24@2804 38 unsigned char key = keypress_key;
keir@17864 39 console_start_log_everything();
kaf24@2970 40 if ( (h = key_table[key].u.handler) != NULL )
kaf24@2804 41 (*h)(key);
keir@17864 42 console_end_log_everything();
kaf24@2804 43 }
kaf24@2804 44
keir@17445 45 static DECLARE_TASKLET(keypress_tasklet, keypress_action, 0);
keir@17445 46
kaf24@4683 47 void handle_keypress(unsigned char key, struct cpu_user_regs *regs)
kaf24@2804 48 {
kaf24@2970 49 irq_keyhandler_t *h;
cl349@2950 50
kfraser@14329 51 if ( !in_irq() || (key_table[key].flags & KEYHANDLER_IRQ_CALLBACK) )
kaf24@2970 52 {
keir@17864 53 console_start_log_everything();
kaf24@2970 54 if ( (h = key_table[key].u.irq_handler) != NULL )
kaf24@2970 55 (*h)(key, regs);
keir@17864 56 console_end_log_everything();
kaf24@2970 57 }
cl349@2950 58 else
kaf24@2970 59 {
kaf24@2970 60 keypress_key = key;
keir@17445 61 tasklet_schedule(&keypress_tasklet);
kaf24@2970 62 }
kaf24@2804 63 }
kaf24@2804 64
kaf24@2970 65 void register_keyhandler(
kaf24@2970 66 unsigned char key, keyhandler_t *handler, char *desc)
kaf24@1546 67 {
kaf24@2970 68 ASSERT(key_table[key].u.handler == NULL);
kaf24@2970 69 key_table[key].u.handler = handler;
kaf24@2970 70 key_table[key].flags = 0;
kfraser@13689 71 safe_strcpy(key_table[key].desc, desc);
iap10@236 72 }
iap10@236 73
kaf24@2970 74 void register_irq_keyhandler(
kaf24@2970 75 unsigned char key, irq_keyhandler_t *handler, char *desc)
cl349@2950 76 {
kaf24@2970 77 ASSERT(key_table[key].u.irq_handler == NULL);
kaf24@2970 78 key_table[key].u.irq_handler = handler;
kaf24@2970 79 key_table[key].flags = KEYHANDLER_IRQ_CALLBACK;
kfraser@13689 80 safe_strcpy(key_table[key].desc, desc);
cl349@2950 81 }
cl349@2950 82
kaf24@2804 83 static void show_handlers(unsigned char key)
iap10@236 84 {
shand@11156 85 int i;
kaf24@1546 86 printk("'%c' pressed -> showing installed handlers\n", key);
kaf24@1104 87 for ( i = 0; i < KEY_MAX; i++ )
kaf24@2970 88 if ( key_table[i].u.handler != NULL )
kaf24@1426 89 printk(" key '%c' (ascii '%02x') => %s\n",
kaf24@1426 90 (i<33 || i>126)?(' '):(i),i,
kaf24@1426 91 key_table[i].desc);
iap10@236 92 }
iap10@236 93
kfraser@10479 94 static void __dump_execstate(void *unused)
kfraser@10479 95 {
kfraser@10479 96 dump_execution_state();
kfraser@13423 97 printk("*** Dumping CPU%d guest state: ***\n", smp_processor_id());
kfraser@13423 98 if ( is_idle_vcpu(current) )
kfraser@13423 99 printk("No guest context (CPU is idle).\n");
kfraser@13423 100 else
kfraser@13423 101 show_execution_state(guest_cpu_user_regs());
kfraser@10479 102 }
kfraser@10479 103
kaf24@4683 104 static void dump_registers(unsigned char key, struct cpu_user_regs *regs)
iap10@236 105 {
kfraser@10479 106 unsigned int cpu;
kfraser@10479 107
keir@17864 108 /* We want to get everything out that we possibly can. */
keir@17864 109 console_start_sync();
keir@17864 110
shand@11156 111 printk("'%c' pressed -> dumping registers\n", key);
kfraser@10479 112
kfraser@10479 113 /* Get local execution state out immediately, in case we get stuck. */
kfraser@13423 114 printk("\n*** Dumping CPU%d host state: ***\n", smp_processor_id());
kfraser@13423 115 __dump_execstate(NULL);
kfraser@10479 116
kfraser@10479 117 for_each_online_cpu ( cpu )
kfraser@10479 118 {
kfraser@10479 119 if ( cpu == smp_processor_id() )
kfraser@10479 120 continue;
kfraser@13423 121 printk("\n*** Dumping CPU%d host state: ***\n", cpu);
keir@19652 122 on_selected_cpus(cpumask_of(cpu), __dump_execstate, NULL, 1);
kfraser@10479 123 }
kfraser@13423 124
kfraser@13423 125 printk("\n");
keir@17864 126
keir@17864 127 console_end_sync();
iap10@236 128 }
iap10@236 129
keir@17848 130 static void dump_dom0_registers(unsigned char key)
keir@17848 131 {
keir@17848 132 struct vcpu *v;
keir@17848 133
keir@17848 134 if ( dom0 == NULL )
keir@17848 135 return;
keir@17848 136
keir@17848 137 printk("'%c' pressed -> dumping Dom0's registers\n", key);
keir@17848 138
keir@17848 139 for_each_vcpu ( dom0, v )
keir@17848 140 vcpu_show_execution_state(v);
keir@17848 141 }
keir@17848 142
kaf24@4683 143 static void halt_machine(unsigned char key, struct cpu_user_regs *regs)
iap10@236 144 {
shand@11156 145 printk("'%c' pressed -> rebooting machine\n", key);
keir@18239 146 machine_restart(0);
iap10@236 147 }
iap10@236 148
kaf24@8520 149 static void cpuset_print(char *set, int size, cpumask_t mask)
kaf24@8520 150 {
kaf24@8520 151 *set++ = '{';
kaf24@8520 152 set += cpulist_scnprintf(set, size-2, mask);
kaf24@8520 153 *set++ = '}';
kaf24@8520 154 *set++ = '\0';
kaf24@8520 155 }
kaf24@8520 156
kfraser@14345 157 static void periodic_timer_print(char *str, int size, uint64_t period)
kfraser@14345 158 {
kfraser@14345 159 if ( period == 0 )
kfraser@14345 160 {
kfraser@14345 161 strlcpy(str, "No periodic timer", size);
kfraser@14345 162 return;
kfraser@14345 163 }
kfraser@14345 164
kfraser@14345 165 snprintf(str, size,
kfraser@14345 166 "%u Hz periodic timer (period %u ms)",
kfraser@14345 167 1000000000/(int)period, (int)period/1000000);
kfraser@14345 168 }
kfraser@14345 169
kaf24@8520 170 static void dump_domains(unsigned char key)
iap10@236 171 {
kaf24@1546 172 struct domain *d;
kaf24@7388 173 struct vcpu *v;
kaf24@1542 174 s_time_t now = NOW();
kfraser@14345 175 char tmpstr[100];
iap10@236 176
kaf24@8520 177 printk("'%c' pressed -> dumping domain info (now=0x%X:%08X)\n", key,
shand@11156 178 (u32)(now>>32), (u32)now);
kaf24@779 179
kfraser@14058 180 rcu_read_lock(&domlist_read_lock);
kaf24@779 181
kaf24@1542 182 for_each_domain ( d )
kaf24@1123 183 {
kaf24@8469 184 printk("General information for domain %u:\n", d->domain_id);
kfraser@14345 185 cpuset_print(tmpstr, sizeof(tmpstr), d->domain_dirty_cpumask);
keir@18729 186 printk(" refcnt=%d dying=%d nr_pages=%d xenheap_pages=%d "
keir@19018 187 "dirty_cpus=%s max_pages=%u\n",
keir@18729 188 atomic_read(&d->refcnt), d->is_dying,
keir@19018 189 d->tot_pages, d->xenheap_pages, tmpstr, d->max_pages);
kaf24@8469 190 printk(" handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-"
kaf24@10304 191 "%02x%02x-%02x%02x%02x%02x%02x%02x vm_assist=%08lx\n",
kaf24@7388 192 d->handle[ 0], d->handle[ 1], d->handle[ 2], d->handle[ 3],
kaf24@7388 193 d->handle[ 4], d->handle[ 5], d->handle[ 6], d->handle[ 7],
kaf24@7388 194 d->handle[ 8], d->handle[ 9], d->handle[10], d->handle[11],
kaf24@10304 195 d->handle[12], d->handle[13], d->handle[14], d->handle[15],
kaf24@10304 196 d->vm_assist);
kaf24@8990 197
kaf24@8990 198 arch_dump_domain_info(d);
kaf24@1640 199
kaf24@8456 200 rangeset_domain_printk(d);
kaf24@8456 201
kaf24@3477 202 dump_pageframe_info(d);
kaf24@1640 203
kaf24@8469 204 printk("VCPU information and callbacks for domain %u:\n",
kaf24@8469 205 d->domain_id);
kaf24@5289 206 for_each_vcpu ( d, v ) {
keir@18531 207 printk(" VCPU%d: CPU%d [has=%c] flags=%lx poll=%d "
kaf24@8520 208 "upcall_pend = %02x, upcall_mask = %02x ",
kaf24@8469 209 v->vcpu_id, v->processor,
kfraser@14657 210 v->is_running ? 'T':'F',
keir@18531 211 v->pause_flags, v->poll_evtchn,
keir@19788 212 v->vcpu_info ? vcpu_info(v, evtchn_upcall_pending) : 0,
keir@19788 213 v->vcpu_info ? vcpu_info(v, evtchn_upcall_mask) : 1);
kfraser@14345 214 cpuset_print(tmpstr, sizeof(tmpstr), v->vcpu_dirty_cpumask);
kfraser@14345 215 printk("dirty_cpus=%s ", tmpstr);
kfraser@14345 216 cpuset_print(tmpstr, sizeof(tmpstr), v->cpu_affinity);
kfraser@14345 217 printk("cpu_affinity=%s\n", tmpstr);
Tim@11924 218 arch_dump_vcpu_info(v);
kfraser@14345 219 periodic_timer_print(tmpstr, sizeof(tmpstr), v->periodic_period);
kfraser@14345 220 printk(" %s\n", tmpstr);
keir@19788 221 if ( !v->vcpu_info )
keir@19788 222 continue;
kaf24@8469 223 printk(" Notifying guest (virq %d, port %d, stat %d/%d/%d)\n",
kaf24@5289 224 VIRQ_DEBUG, v->virq_to_evtchn[VIRQ_DEBUG],
kaf24@5289 225 test_bit(v->virq_to_evtchn[VIRQ_DEBUG],
keir@17211 226 &shared_info(d, evtchn_pending)),
kaf24@5289 227 test_bit(v->virq_to_evtchn[VIRQ_DEBUG],
keir@17211 228 &shared_info(d, evtchn_mask)),
kfraser@14345 229 test_bit(v->virq_to_evtchn[VIRQ_DEBUG] /
keir@19268 230 BITS_PER_EVTCHN_WORD(d),
keir@17211 231 &vcpu_info(v, evtchn_pending_sel)));
kaf24@9597 232 send_guest_vcpu_virq(v, VIRQ_DEBUG);
cl349@2919 233 }
kaf24@1123 234 }
iap10@236 235
kfraser@14058 236 rcu_read_unlock(&domlist_read_lock);
iap10@236 237 }
iap10@236 238
kaf24@9247 239 static cpumask_t read_clocks_cpumask = CPU_MASK_NONE;
kaf24@9247 240 static s_time_t read_clocks_time[NR_CPUS];
keir@18177 241 static u64 read_cycles_time[NR_CPUS];
kaf24@9247 242
kaf24@9247 243 static void read_clocks_slave(void *unused)
kaf24@9247 244 {
kaf24@9247 245 unsigned int cpu = smp_processor_id();
keir@18120 246 local_irq_disable();
kaf24@9247 247 while ( !cpu_isset(cpu, read_clocks_cpumask) )
kaf24@9247 248 cpu_relax();
kaf24@9247 249 read_clocks_time[cpu] = NOW();
keir@18177 250 read_cycles_time[cpu] = get_cycles();
kaf24@9247 251 cpu_clear(cpu, read_clocks_cpumask);
keir@18120 252 local_irq_enable();
kaf24@9247 253 }
kaf24@9247 254
kaf24@9247 255 static void read_clocks(unsigned char key)
kaf24@9247 256 {
keir@18177 257 unsigned int cpu = smp_processor_id(), min_stime_cpu, max_stime_cpu;
keir@18177 258 unsigned int min_cycles_cpu, max_cycles_cpu;
keir@18177 259 u64 min_stime, max_stime, dif_stime;
keir@18177 260 u64 min_cycles, max_cycles, dif_cycles;
keir@18177 261 static u64 sumdif_stime = 0, maxdif_stime = 0;
keir@18177 262 static u64 sumdif_cycles = 0, maxdif_cycles = 0;
keir@18177 263 static u32 count = 0;
kaf24@9247 264 static DEFINE_SPINLOCK(lock);
kaf24@9247 265
kaf24@9247 266 spin_lock(&lock);
kaf24@9247 267
keir@19652 268 smp_call_function(read_clocks_slave, NULL, 0);
kaf24@9247 269
kaf24@9247 270 local_irq_disable();
kaf24@9247 271 read_clocks_cpumask = cpu_online_map;
kaf24@9247 272 read_clocks_time[cpu] = NOW();
keir@18177 273 read_cycles_time[cpu] = get_cycles();
kaf24@9247 274 cpu_clear(cpu, read_clocks_cpumask);
kaf24@9247 275 local_irq_enable();
kaf24@9247 276
kaf24@9247 277 while ( !cpus_empty(read_clocks_cpumask) )
kaf24@9247 278 cpu_relax();
kaf24@9247 279
keir@18177 280 min_stime_cpu = max_stime_cpu = min_cycles_cpu = max_cycles_cpu = cpu;
kaf24@9247 281 for_each_online_cpu ( cpu )
kaf24@9247 282 {
keir@18177 283 if ( read_clocks_time[cpu] < read_clocks_time[min_stime_cpu] )
keir@18177 284 min_stime_cpu = cpu;
keir@18177 285 if ( read_clocks_time[cpu] > read_clocks_time[max_stime_cpu] )
keir@18177 286 max_stime_cpu = cpu;
keir@18177 287 if ( read_cycles_time[cpu] < read_cycles_time[min_cycles_cpu] )
keir@18177 288 min_cycles_cpu = cpu;
keir@18177 289 if ( read_cycles_time[cpu] > read_cycles_time[max_cycles_cpu] )
keir@18177 290 max_cycles_cpu = cpu;
kaf24@9247 291 }
kaf24@9247 292
keir@18177 293 min_stime = read_clocks_time[min_stime_cpu];
keir@18177 294 max_stime = read_clocks_time[max_stime_cpu];
keir@18177 295 min_cycles = read_cycles_time[min_cycles_cpu];
keir@18177 296 max_cycles = read_cycles_time[max_cycles_cpu];
kaf24@9247 297
kaf24@9247 298 spin_unlock(&lock);
kaf24@9247 299
keir@18177 300 dif_stime = max_stime - min_stime;
keir@18177 301 if ( dif_stime > maxdif_stime )
keir@18177 302 maxdif_stime = dif_stime;
keir@18177 303 sumdif_stime += dif_stime;
keir@18177 304 dif_cycles = max_cycles - min_cycles;
keir@18177 305 if ( dif_cycles > maxdif_cycles )
keir@18177 306 maxdif_cycles = dif_cycles;
keir@18177 307 sumdif_cycles += dif_cycles;
keir@18177 308 count++;
keir@18177 309 printk("Synced stime skew: max=%"PRIu64"ns avg=%"PRIu64"ns "
keir@18177 310 "samples=%"PRIu32" current=%"PRIu64"ns\n",
keir@18177 311 maxdif_stime, sumdif_stime/count, count, dif_stime);
keir@18177 312 printk("Synced cycles skew: max=%"PRIu64" avg=%"PRIu64" "
keir@18177 313 "samples=%"PRIu32" current=%"PRIu64"\n",
keir@18177 314 maxdif_cycles, sumdif_cycles/count, count, dif_cycles);
kaf24@9247 315 }
kaf24@9247 316
kaf24@2804 317 extern void dump_runq(unsigned char key);
iap10@2441 318
kaf24@1444 319 #ifdef PERF_COUNTERS
kaf24@2804 320 extern void perfc_printall(unsigned char key);
kaf24@2804 321 extern void perfc_reset(unsigned char key);
kaf24@1274 322 #endif
rn@302 323
kaf24@9247 324 static void do_debug_key(unsigned char key, struct cpu_user_regs *regs)
sos22@1951 325 {
keir@16599 326 printk("'%c' pressed -> trapping into debugger\n", key);
sos22@3776 327 (void)debugger_trap_fatal(0xf001, regs);
iap10@3833 328 nop(); /* Prevent the compiler doing tail call
sos22@3763 329 optimisation, as that confuses xendbg a
sos22@3763 330 bit. */
sos22@1951 331 }
sos22@1951 332
keir@15082 333 void __init initialize_keytable(void)
iap10@236 334 {
kaf24@2970 335 register_irq_keyhandler(
shand@11156 336 'd', dump_registers, "dump registers");
kaf24@2970 337 register_keyhandler(
kaf24@2970 338 'h', show_handlers, "show this message");
kaf24@2970 339 register_keyhandler(
kaf24@8520 340 'q', dump_domains, "dump domain (and guest debug) info");
kaf24@2970 341 register_keyhandler(
kaf24@2970 342 'r', dump_runq, "dump run queues");
cl349@2980 343 register_irq_keyhandler(
shand@11156 344 'R', halt_machine, "reboot machine");
iap10@2441 345
kaf24@9247 346 register_keyhandler(
kaf24@9247 347 't', read_clocks, "display multi-cpu clock info");
kaf24@9247 348
kaf24@1444 349 #ifdef PERF_COUNTERS
kaf24@2970 350 register_keyhandler(
shand@11156 351 'p', perfc_printall, "print performance counters");
kaf24@2970 352 register_keyhandler(
shand@11156 353 'P', perfc_reset, "reset performance counters");
kaf24@1274 354 #endif
kaf24@3827 355
keir@17848 356 register_keyhandler(
keir@17848 357 '0', dump_dom0_registers, "dump Dom0 registers");
keir@17848 358
sos22@3763 359 register_irq_keyhandler('%', do_debug_key, "Trap to xendbg");
iap10@236 360 }
kaf24@3914 361
kaf24@3914 362 /*
kaf24@3914 363 * Local variables:
kaf24@3914 364 * mode: C
kaf24@3914 365 * c-set-style: "BSD"
kaf24@3914 366 * c-basic-offset: 4
kaf24@3914 367 * tab-width: 4
kaf24@3914 368 * indent-tabs-mode: nil
kaf24@3988 369 * End:
kaf24@3914 370 */