debuggers.hg

annotate xen/common/keyhandler.c @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents dca1b7cf2e2c
children
rev   line source
kaf24@3008 1 /******************************************************************************
kaf24@3008 2 * keyhandler.c
kaf24@3008 3 */
kaf24@1098 4
cl349@3921 5 #include <asm/regs.h>
kaf24@1248 6 #include <xen/keyhandler.h>
kaf24@10989 7 #include <xen/shutdown.h>
kaf24@1248 8 #include <xen/event.h>
kaf24@1248 9 #include <xen/console.h>
kaf24@1248 10 #include <xen/serial.h>
mwilli2@1284 11 #include <xen/sched.h>
keir@21242 12 #include <xen/tasklet.h>
cl349@5285 13 #include <xen/domain.h>
kaf24@8486 14 #include <xen/rangeset.h>
ack@13294 15 #include <xen/compat.h>
keir@20048 16 #include <xen/ctype.h>
sos22@3801 17 #include <asm/debugger.h>
kaf24@9261 18 #include <asm/div64.h>
iap10@274 19
keir@20048 20 static struct keyhandler *key_table[256];
kaf24@2842 21 static unsigned char keypress_key;
keir@21350 22 static bool_t alt_key_handling;
kaf24@2842 23
keir@20982 24 char keyhandler_scratch[1024];
keir@20975 25
keir@17481 26 static void keypress_action(unsigned long unused)
kaf24@2842 27 {
keir@20975 28 handle_keypress(keypress_key, NULL);
kaf24@2842 29 }
kaf24@2842 30
keir@17481 31 static DECLARE_TASKLET(keypress_tasklet, keypress_action, 0);
keir@17481 32
kaf24@4721 33 void handle_keypress(unsigned char key, struct cpu_user_regs *regs)
kaf24@2842 34 {
keir@20048 35 struct keyhandler *h;
cl349@2988 36
keir@20048 37 if ( (h = key_table[key]) == NULL )
keir@20048 38 return;
keir@20048 39
keir@20048 40 if ( !in_irq() || h->irq_callback )
kaf24@3008 41 {
keir@17896 42 console_start_log_everything();
keir@20975 43 h->irq_callback ? (*h->u.irq_fn)(key, regs) : (*h->u.fn)(key);
keir@17896 44 console_end_log_everything();
kaf24@3008 45 }
cl349@2988 46 else
kaf24@3008 47 {
kaf24@3008 48 keypress_key = key;
keir@17481 49 tasklet_schedule(&keypress_tasklet);
kaf24@3008 50 }
kaf24@2842 51 }
kaf24@2842 52
keir@20048 53 void register_keyhandler(unsigned char key, struct keyhandler *handler)
kaf24@1584 54 {
keir@20048 55 ASSERT(key_table[key] == NULL);
keir@20048 56 key_table[key] = handler;
cl349@2988 57 }
cl349@2988 58
kaf24@2842 59 static void show_handlers(unsigned char key)
iap10@274 60 {
shand@11173 61 int i;
kaf24@1584 62 printk("'%c' pressed -> showing installed handlers\n", key);
keir@20048 63 for ( i = 0; i < ARRAY_SIZE(key_table); i++ )
keir@20048 64 if ( key_table[i] != NULL )
kaf24@1464 65 printk(" key '%c' (ascii '%02x') => %s\n",
keir@20048 66 isprint(i) ? i : ' ', i, key_table[i]->desc);
iap10@274 67 }
iap10@274 68
keir@20048 69 static struct keyhandler show_handlers_keyhandler = {
keir@20048 70 .u.fn = show_handlers,
keir@20048 71 .desc = "show this message"
keir@20048 72 };
keir@20048 73
keir@21355 74 static cpumask_t dump_execstate_mask;
keir@21355 75
keir@21355 76 void dump_execstate(struct cpu_user_regs *regs)
kfraser@10485 77 {
keir@21355 78 unsigned int cpu = smp_processor_id();
keir@21355 79
keir@21355 80 if ( !guest_mode(regs) )
keir@21355 81 {
keir@21355 82 printk("*** Dumping CPU%u host state: ***\n", cpu);
keir@21355 83 show_execution_state(regs);
keir@21355 84 }
keir@21355 85
keir@21355 86 if ( !is_idle_vcpu(current) )
keir@21355 87 {
keir@21355 88 printk("*** Dumping CPU%u guest state (d%d:v%d): ***\n",
keir@21355 89 smp_processor_id(), current->domain->domain_id,
keir@21355 90 current->vcpu_id);
kfraser@13408 91 show_execution_state(guest_cpu_user_regs());
keir@21355 92 printk("\n");
keir@21355 93 }
keir@21355 94
keir@21355 95 cpu_clear(cpu, dump_execstate_mask);
keir@21355 96 if ( !alt_key_handling )
keir@21355 97 return;
keir@21355 98
keir@21355 99 cpu = cycle_cpu(cpu, dump_execstate_mask);
keir@21355 100 if ( cpu < NR_CPUS )
keir@21355 101 {
keir@21355 102 smp_send_state_dump(cpu);
keir@21355 103 return;
keir@21355 104 }
keir@21355 105
keir@21355 106 console_end_sync();
keir@21355 107 watchdog_enable();
kfraser@10485 108 }
kfraser@10485 109
kaf24@4721 110 static void dump_registers(unsigned char key, struct cpu_user_regs *regs)
iap10@274 111 {
kfraser@10485 112 unsigned int cpu;
kfraser@10485 113
keir@17896 114 /* We want to get everything out that we possibly can. */
keir@20678 115 watchdog_disable();
keir@17896 116 console_start_sync();
keir@17896 117
keir@21355 118 printk("'%c' pressed -> dumping registers\n\n", key);
keir@21355 119
keir@21355 120 dump_execstate_mask = cpu_online_map;
kfraser@10485 121
kfraser@10485 122 /* Get local execution state out immediately, in case we get stuck. */
keir@21355 123 dump_execstate(regs);
kfraser@10485 124
keir@21355 125 /* Alt. handling: remaining CPUs are dumped asynchronously one-by-one. */
keir@21355 126 if ( alt_key_handling )
keir@21355 127 return;
keir@21355 128
keir@21355 129 /* Normal handling: synchronously dump the remaining CPUs' states. */
keir@21355 130 for_each_cpu_mask ( cpu, dump_execstate_mask )
kfraser@10485 131 {
keir@21355 132 smp_send_state_dump(cpu);
keir@21355 133 while ( cpu_isset(cpu, dump_execstate_mask) )
keir@21355 134 cpu_relax();
kfraser@10485 135 }
kfraser@13408 136
keir@17896 137 console_end_sync();
keir@20678 138 watchdog_enable();
iap10@274 139 }
iap10@274 140
keir@20048 141 static struct keyhandler dump_registers_keyhandler = {
keir@20048 142 .irq_callback = 1,
keir@20048 143 .diagnostic = 1,
keir@20048 144 .u.irq_fn = dump_registers,
keir@20048 145 .desc = "dump registers"
keir@20048 146 };
keir@20048 147
keir@21350 148 static DECLARE_TASKLET(dump_dom0_tasklet, NULL, 0);
keir@21350 149
keir@21350 150 static void dump_dom0_action(unsigned long arg)
keir@21350 151 {
keir@21350 152 struct vcpu *v = (void *)arg;
keir@21350 153
keir@21350 154 for ( ; ; )
keir@21350 155 {
keir@21350 156 vcpu_show_execution_state(v);
keir@21350 157 if ( (v = v->next_in_list) == NULL )
keir@21350 158 break;
keir@21350 159 if ( softirq_pending(smp_processor_id()) )
keir@21350 160 {
keir@21350 161 dump_dom0_tasklet.data = (unsigned long)v;
keir@21350 162 tasklet_schedule_on_cpu(&dump_dom0_tasklet, v->processor);
keir@21350 163 break;
keir@21350 164 }
keir@21350 165 }
keir@21350 166 }
keir@21350 167
keir@17880 168 static void dump_dom0_registers(unsigned char key)
keir@17880 169 {
keir@17880 170 struct vcpu *v;
keir@17880 171
keir@17880 172 if ( dom0 == NULL )
keir@17880 173 return;
keir@17880 174
keir@17880 175 printk("'%c' pressed -> dumping Dom0's registers\n", key);
keir@17880 176
keir@17880 177 for_each_vcpu ( dom0, v )
keir@21350 178 {
keir@21350 179 if ( alt_key_handling && softirq_pending(smp_processor_id()) )
keir@21350 180 {
keir@21350 181 tasklet_kill(&dump_dom0_tasklet);
keir@21350 182 tasklet_init(&dump_dom0_tasklet, dump_dom0_action,
keir@21350 183 (unsigned long)v);
keir@21350 184 tasklet_schedule_on_cpu(&dump_dom0_tasklet, v->processor);
keir@21350 185 return;
keir@21350 186 }
keir@17880 187 vcpu_show_execution_state(v);
keir@21350 188 }
keir@17880 189 }
keir@17880 190
keir@20048 191 static struct keyhandler dump_dom0_registers_keyhandler = {
keir@20048 192 .diagnostic = 1,
keir@20048 193 .u.fn = dump_dom0_registers,
keir@20048 194 .desc = "dump Dom0 registers"
keir@20048 195 };
keir@20048 196
keir@20048 197 static void reboot_machine(unsigned char key, struct cpu_user_regs *regs)
iap10@274 198 {
shand@11173 199 printk("'%c' pressed -> rebooting machine\n", key);
keir@18251 200 machine_restart(0);
iap10@274 201 }
iap10@274 202
keir@20048 203 static struct keyhandler reboot_machine_keyhandler = {
keir@20048 204 .irq_callback = 1,
keir@20048 205 .u.irq_fn = reboot_machine,
keir@20048 206 .desc = "reboot machine"
keir@20048 207 };
keir@20048 208
kaf24@8550 209 static void cpuset_print(char *set, int size, cpumask_t mask)
kaf24@8550 210 {
kaf24@8550 211 *set++ = '{';
kaf24@8550 212 set += cpulist_scnprintf(set, size-2, mask);
kaf24@8550 213 *set++ = '}';
kaf24@8550 214 *set++ = '\0';
kaf24@8550 215 }
kaf24@8550 216
kfraser@14363 217 static void periodic_timer_print(char *str, int size, uint64_t period)
kfraser@14363 218 {
kfraser@14363 219 if ( period == 0 )
kfraser@14363 220 {
kfraser@14363 221 strlcpy(str, "No periodic timer", size);
kfraser@14363 222 return;
kfraser@14363 223 }
kfraser@14363 224
kfraser@14363 225 snprintf(str, size,
kfraser@14363 226 "%u Hz periodic timer (period %u ms)",
kfraser@14363 227 1000000000/(int)period, (int)period/1000000);
kfraser@14363 228 }
kfraser@14363 229
kaf24@8550 230 static void dump_domains(unsigned char key)
iap10@274 231 {
kaf24@1584 232 struct domain *d;
kaf24@7416 233 struct vcpu *v;
kaf24@1580 234 s_time_t now = NOW();
keir@20975 235 #define tmpstr keyhandler_scratch
iap10@274 236
kaf24@8550 237 printk("'%c' pressed -> dumping domain info (now=0x%X:%08X)\n", key,
shand@11173 238 (u32)(now>>32), (u32)now);
kaf24@817 239
kfraser@14074 240 rcu_read_lock(&domlist_read_lock);
kaf24@817 241
kaf24@1580 242 for_each_domain ( d )
kaf24@1161 243 {
keir@21575 244 unsigned int i;
kaf24@8499 245 printk("General information for domain %u:\n", d->domain_id);
kfraser@14363 246 cpuset_print(tmpstr, sizeof(tmpstr), d->domain_dirty_cpumask);
keir@18759 247 printk(" refcnt=%d dying=%d nr_pages=%d xenheap_pages=%d "
keir@19055 248 "dirty_cpus=%s max_pages=%u\n",
keir@18759 249 atomic_read(&d->refcnt), d->is_dying,
keir@19055 250 d->tot_pages, d->xenheap_pages, tmpstr, d->max_pages);
kaf24@8499 251 printk(" handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-"
kaf24@10304 252 "%02x%02x-%02x%02x%02x%02x%02x%02x vm_assist=%08lx\n",
kaf24@7416 253 d->handle[ 0], d->handle[ 1], d->handle[ 2], d->handle[ 3],
kaf24@7416 254 d->handle[ 4], d->handle[ 5], d->handle[ 6], d->handle[ 7],
kaf24@7416 255 d->handle[ 8], d->handle[ 9], d->handle[10], d->handle[11],
kaf24@10304 256 d->handle[12], d->handle[13], d->handle[14], d->handle[15],
kaf24@10304 257 d->vm_assist);
keir@21855 258 for ( i = 0 ; i < NR_DOMAIN_WATCHDOG_TIMERS; i++ )
keir@21575 259 if ( test_bit(i, &d->watchdog_inuse_map) )
keir@21575 260 printk(" watchdog %d expires in %d seconds\n",
keir@21575 261 i, (u32)((d->watchdog_timer[i].expires - NOW()) >> 30));
kaf24@8993 262
kaf24@8993 263 arch_dump_domain_info(d);
kaf24@1678 264
kaf24@8486 265 rangeset_domain_printk(d);
kaf24@8486 266
kaf24@3515 267 dump_pageframe_info(d);
kaf24@1678 268
kaf24@8499 269 printk("VCPU information and callbacks for domain %u:\n",
kaf24@8499 270 d->domain_id);
keir@21855 271 for_each_vcpu ( d, v )
keir@21855 272 {
keir@18566 273 printk(" VCPU%d: CPU%d [has=%c] flags=%lx poll=%d "
kaf24@8550 274 "upcall_pend = %02x, upcall_mask = %02x ",
kaf24@8499 275 v->vcpu_id, v->processor,
kfraser@14692 276 v->is_running ? 'T':'F',
keir@18566 277 v->pause_flags, v->poll_evtchn,
keir@20430 278 vcpu_info(v, evtchn_upcall_pending),
keir@20430 279 vcpu_info(v, evtchn_upcall_mask));
kfraser@14363 280 cpuset_print(tmpstr, sizeof(tmpstr), v->vcpu_dirty_cpumask);
kfraser@14363 281 printk("dirty_cpus=%s ", tmpstr);
kfraser@14363 282 cpuset_print(tmpstr, sizeof(tmpstr), v->cpu_affinity);
kfraser@14363 283 printk("cpu_affinity=%s\n", tmpstr);
Tim@11889 284 arch_dump_vcpu_info(v);
kfraser@14363 285 periodic_timer_print(tmpstr, sizeof(tmpstr), v->periodic_period);
kfraser@14363 286 printk(" %s\n", tmpstr);
keir@21855 287 }
keir@21855 288 }
keir@21855 289
keir@21855 290 for_each_domain ( d )
keir@21855 291 {
keir@21855 292 for_each_vcpu ( d, v )
keir@21855 293 {
keir@21855 294 printk("Notifying guest %d:%d (virq %d, port %d, stat %d/%d/%d)\n",
keir@21855 295 d->domain_id, v->vcpu_id,
kaf24@5327 296 VIRQ_DEBUG, v->virq_to_evtchn[VIRQ_DEBUG],
kaf24@5327 297 test_bit(v->virq_to_evtchn[VIRQ_DEBUG],
keir@17232 298 &shared_info(d, evtchn_pending)),
kaf24@5327 299 test_bit(v->virq_to_evtchn[VIRQ_DEBUG],
keir@17232 300 &shared_info(d, evtchn_mask)),
kfraser@14363 301 test_bit(v->virq_to_evtchn[VIRQ_DEBUG] /
keir@19304 302 BITS_PER_EVTCHN_WORD(d),
keir@17232 303 &vcpu_info(v, evtchn_pending_sel)));
kaf24@9582 304 send_guest_vcpu_virq(v, VIRQ_DEBUG);
cl349@2957 305 }
kaf24@1161 306 }
iap10@274 307
kfraser@14074 308 rcu_read_unlock(&domlist_read_lock);
keir@20975 309 #undef tmpstr
iap10@274 310 }
iap10@274 311
keir@20048 312 static struct keyhandler dump_domains_keyhandler = {
keir@20048 313 .diagnostic = 1,
keir@20048 314 .u.fn = dump_domains,
keir@20048 315 .desc = "dump domain (and guest debug) info"
keir@20048 316 };
keir@20048 317
kaf24@9261 318 static cpumask_t read_clocks_cpumask = CPU_MASK_NONE;
keir@21810 319 static DEFINE_PER_CPU(s_time_t, read_clocks_time);
keir@21810 320 static DEFINE_PER_CPU(u64, read_cycles_time);
kaf24@9261 321
kaf24@9261 322 static void read_clocks_slave(void *unused)
kaf24@9261 323 {
kaf24@9261 324 unsigned int cpu = smp_processor_id();
keir@18138 325 local_irq_disable();
kaf24@9261 326 while ( !cpu_isset(cpu, read_clocks_cpumask) )
kaf24@9261 327 cpu_relax();
keir@21810 328 per_cpu(read_clocks_time, cpu) = NOW();
keir@21810 329 per_cpu(read_cycles_time, cpu) = get_cycles();
kaf24@9261 330 cpu_clear(cpu, read_clocks_cpumask);
keir@18138 331 local_irq_enable();
kaf24@9261 332 }
kaf24@9261 333
kaf24@9261 334 static void read_clocks(unsigned char key)
kaf24@9261 335 {
keir@18189 336 unsigned int cpu = smp_processor_id(), min_stime_cpu, max_stime_cpu;
keir@18189 337 unsigned int min_cycles_cpu, max_cycles_cpu;
keir@18189 338 u64 min_stime, max_stime, dif_stime;
keir@18189 339 u64 min_cycles, max_cycles, dif_cycles;
keir@18189 340 static u64 sumdif_stime = 0, maxdif_stime = 0;
keir@18189 341 static u64 sumdif_cycles = 0, maxdif_cycles = 0;
keir@18189 342 static u32 count = 0;
kaf24@9261 343 static DEFINE_SPINLOCK(lock);
kaf24@9261 344
kaf24@9261 345 spin_lock(&lock);
kaf24@9261 346
keir@19690 347 smp_call_function(read_clocks_slave, NULL, 0);
kaf24@9261 348
kaf24@9261 349 local_irq_disable();
kaf24@9261 350 read_clocks_cpumask = cpu_online_map;
keir@21810 351 per_cpu(read_clocks_time, cpu) = NOW();
keir@21810 352 per_cpu(read_cycles_time, cpu) = get_cycles();
kaf24@9261 353 cpu_clear(cpu, read_clocks_cpumask);
kaf24@9261 354 local_irq_enable();
kaf24@9261 355
kaf24@9261 356 while ( !cpus_empty(read_clocks_cpumask) )
kaf24@9261 357 cpu_relax();
kaf24@9261 358
keir@18189 359 min_stime_cpu = max_stime_cpu = min_cycles_cpu = max_cycles_cpu = cpu;
kaf24@9261 360 for_each_online_cpu ( cpu )
kaf24@9261 361 {
keir@21810 362 if ( per_cpu(read_clocks_time, cpu) <
keir@21810 363 per_cpu(read_clocks_time, min_stime_cpu) )
keir@18189 364 min_stime_cpu = cpu;
keir@21810 365 if ( per_cpu(read_clocks_time, cpu) >
keir@21810 366 per_cpu(read_clocks_time, max_stime_cpu) )
keir@18189 367 max_stime_cpu = cpu;
keir@21810 368 if ( per_cpu(read_cycles_time, cpu) <
keir@21810 369 per_cpu(read_cycles_time, min_cycles_cpu) )
keir@18189 370 min_cycles_cpu = cpu;
keir@21810 371 if ( per_cpu(read_cycles_time, cpu) >
keir@21810 372 per_cpu(read_cycles_time, max_cycles_cpu) )
keir@18189 373 max_cycles_cpu = cpu;
kaf24@9261 374 }
kaf24@9261 375
keir@21810 376 min_stime = per_cpu(read_clocks_time, min_stime_cpu);
keir@21810 377 max_stime = per_cpu(read_clocks_time, max_stime_cpu);
keir@21810 378 min_cycles = per_cpu(read_cycles_time, min_cycles_cpu);
keir@21810 379 max_cycles = per_cpu(read_cycles_time, max_cycles_cpu);
kaf24@9261 380
kaf24@9261 381 spin_unlock(&lock);
kaf24@9261 382
keir@18189 383 dif_stime = max_stime - min_stime;
keir@18189 384 if ( dif_stime > maxdif_stime )
keir@18189 385 maxdif_stime = dif_stime;
keir@18189 386 sumdif_stime += dif_stime;
keir@18189 387 dif_cycles = max_cycles - min_cycles;
keir@18189 388 if ( dif_cycles > maxdif_cycles )
keir@18189 389 maxdif_cycles = dif_cycles;
keir@18189 390 sumdif_cycles += dif_cycles;
keir@18189 391 count++;
keir@18189 392 printk("Synced stime skew: max=%"PRIu64"ns avg=%"PRIu64"ns "
keir@18189 393 "samples=%"PRIu32" current=%"PRIu64"ns\n",
keir@18189 394 maxdif_stime, sumdif_stime/count, count, dif_stime);
keir@18189 395 printk("Synced cycles skew: max=%"PRIu64" avg=%"PRIu64" "
keir@18189 396 "samples=%"PRIu32" current=%"PRIu64"\n",
keir@18189 397 maxdif_cycles, sumdif_cycles/count, count, dif_cycles);
kaf24@9261 398 }
kaf24@9261 399
keir@20048 400 static struct keyhandler read_clocks_keyhandler = {
keir@20048 401 .diagnostic = 1,
keir@20048 402 .u.fn = read_clocks,
keir@20048 403 .desc = "display multi-cpu clock info"
keir@20048 404 };
keir@20048 405
kaf24@2842 406 extern void dump_runq(unsigned char key);
keir@20048 407 static struct keyhandler dump_runq_keyhandler = {
keir@20048 408 .diagnostic = 1,
keir@20048 409 .u.fn = dump_runq,
keir@20048 410 .desc = "dump run queues"
keir@20048 411 };
iap10@2479 412
kaf24@1482 413 #ifdef PERF_COUNTERS
kaf24@2842 414 extern void perfc_printall(unsigned char key);
keir@20048 415 static struct keyhandler perfc_printall_keyhandler = {
keir@20048 416 .diagnostic = 1,
keir@20048 417 .u.fn = perfc_printall,
keir@20048 418 .desc = "print performance counters"
keir@20048 419 };
kaf24@2842 420 extern void perfc_reset(unsigned char key);
keir@20048 421 static struct keyhandler perfc_reset_keyhandler = {
keir@20048 422 .u.fn = perfc_reset,
keir@20048 423 .desc = "reset performance counters"
keir@20048 424 };
kaf24@1312 425 #endif
rn@340 426
keir@20350 427 #ifdef LOCK_PROFILE
keir@20350 428 extern void spinlock_profile_printall(unsigned char key);
keir@20350 429 static struct keyhandler spinlock_printall_keyhandler = {
keir@20350 430 .diagnostic = 1,
keir@20350 431 .u.fn = spinlock_profile_printall,
keir@20350 432 .desc = "print lock profile info"
keir@20350 433 };
keir@20350 434 extern void spinlock_profile_reset(unsigned char key);
keir@20350 435 static struct keyhandler spinlock_reset_keyhandler = {
keir@20350 436 .u.fn = spinlock_profile_reset,
keir@20350 437 .desc = "reset lock profile info"
keir@20350 438 };
keir@20350 439 #endif
keir@20350 440
keir@20048 441 static void run_all_nonirq_keyhandlers(unsigned long unused)
keir@20048 442 {
keir@20048 443 /* Fire all the non-IRQ-context diagnostic keyhandlers */
keir@20048 444 struct keyhandler *h;
keir@20048 445 int k;
keir@20048 446
keir@22677 447 console_start_log_everything();
keir@22677 448
keir@20048 449 for ( k = 0; k < ARRAY_SIZE(key_table); k++ )
keir@20048 450 {
keir@22584 451 process_pending_softirqs();
keir@20048 452 h = key_table[k];
keir@20048 453 if ( (h == NULL) || !h->diagnostic || h->irq_callback )
keir@20048 454 continue;
keir@20048 455 printk("[%c: %s]\n", k, h->desc);
keir@20048 456 (*h->u.fn)(k);
keir@20048 457 }
keir@22677 458
keir@22677 459 console_end_log_everything();
keir@20048 460 }
keir@20048 461
keir@20048 462 static DECLARE_TASKLET(run_all_keyhandlers_tasklet,
keir@20048 463 run_all_nonirq_keyhandlers, 0);
keir@20048 464
keir@20048 465 static void run_all_keyhandlers(unsigned char key, struct cpu_user_regs *regs)
keir@20048 466 {
keir@20048 467 struct keyhandler *h;
keir@20048 468 int k;
keir@20048 469
keir@22584 470 watchdog_disable();
keir@22584 471
keir@20048 472 printk("'%c' pressed -> firing all diagnostic keyhandlers\n", key);
keir@20048 473
keir@20048 474 /* Fire all the IRQ-context diangostic keyhandlers now */
keir@20048 475 for ( k = 0; k < ARRAY_SIZE(key_table); k++ )
keir@20048 476 {
keir@20048 477 h = key_table[k];
keir@20048 478 if ( (h == NULL) || !h->diagnostic || !h->irq_callback )
keir@20048 479 continue;
keir@20048 480 printk("[%c: %s]\n", k, h->desc);
keir@20048 481 (*h->u.irq_fn)(k, regs);
keir@20048 482 }
keir@22584 483
keir@22584 484 watchdog_enable();
keir@20048 485
keir@20048 486 /* Trigger the others from a tasklet in non-IRQ context */
keir@20048 487 tasklet_schedule(&run_all_keyhandlers_tasklet);
keir@20048 488 }
keir@20048 489
keir@20048 490 static struct keyhandler run_all_keyhandlers_keyhandler = {
keir@20048 491 .irq_callback = 1,
keir@20048 492 .u.irq_fn = run_all_keyhandlers,
keir@20048 493 .desc = "print all diagnostics"
keir@20048 494 };
keir@20048 495
kaf24@9261 496 static void do_debug_key(unsigned char key, struct cpu_user_regs *regs)
sos22@1989 497 {
keir@16634 498 printk("'%c' pressed -> trapping into debugger\n", key);
sos22@3814 499 (void)debugger_trap_fatal(0xf001, regs);
iap10@3871 500 nop(); /* Prevent the compiler doing tail call
sos22@3801 501 optimisation, as that confuses xendbg a
sos22@3801 502 bit. */
sos22@1989 503 }
sos22@1989 504
keir@20048 505 static struct keyhandler do_debug_key_keyhandler = {
keir@20048 506 .irq_callback = 1,
keir@20048 507 .u.irq_fn = do_debug_key,
keir@20048 508 .desc = "trap to xendbg"
keir@20048 509 };
keir@20048 510
keir@21350 511 static void do_toggle_alt_key(unsigned char key, struct cpu_user_regs *regs)
keir@21350 512 {
keir@21350 513 alt_key_handling = !alt_key_handling;
keir@21350 514 printk("'%c' pressed -> using %s key handling\n", key,
keir@21350 515 alt_key_handling ? "alternative" : "normal");
keir@21350 516 }
keir@21350 517
keir@21350 518 static struct keyhandler toggle_alt_keyhandler = {
keir@21350 519 .irq_callback = 1,
keir@21350 520 .u.irq_fn = do_toggle_alt_key,
keir@21350 521 .desc = "toggle alternative key handling"
keir@21350 522 };
keir@21350 523
keir@15081 524 void __init initialize_keytable(void)
iap10@274 525 {
keir@21350 526 if ( num_present_cpus() > 16 )
keir@21350 527 {
keir@21350 528 alt_key_handling = 1;
keir@21350 529 printk(XENLOG_INFO "Defaulting to alternative key handling; "
keir@21350 530 "send 'A' to switch to normal mode.\n");
keir@21350 531 }
keir@21350 532 register_keyhandler('A', &toggle_alt_keyhandler);
keir@20048 533 register_keyhandler('d', &dump_registers_keyhandler);
keir@20048 534 register_keyhandler('h', &show_handlers_keyhandler);
keir@20048 535 register_keyhandler('q', &dump_domains_keyhandler);
keir@20048 536 register_keyhandler('r', &dump_runq_keyhandler);
keir@20048 537 register_keyhandler('R', &reboot_machine_keyhandler);
keir@20048 538 register_keyhandler('t', &read_clocks_keyhandler);
keir@20048 539 register_keyhandler('0', &dump_dom0_registers_keyhandler);
keir@20048 540 register_keyhandler('%', &do_debug_key_keyhandler);
keir@20048 541 register_keyhandler('*', &run_all_keyhandlers_keyhandler);
kaf24@9261 542
kaf24@1482 543 #ifdef PERF_COUNTERS
keir@20048 544 register_keyhandler('p', &perfc_printall_keyhandler);
keir@20048 545 register_keyhandler('P', &perfc_reset_keyhandler);
kaf24@1312 546 #endif
keir@20350 547
keir@20350 548 #ifdef LOCK_PROFILE
keir@20350 549 register_keyhandler('l', &spinlock_printall_keyhandler);
keir@20350 550 register_keyhandler('L', &spinlock_reset_keyhandler);
keir@20350 551 #endif
keir@20350 552
iap10@274 553 }
kaf24@3952 554
kaf24@3952 555 /*
kaf24@3952 556 * Local variables:
kaf24@3952 557 * mode: C
kaf24@3952 558 * c-set-style: "BSD"
kaf24@3952 559 * c-basic-offset: 4
kaf24@3952 560 * tab-width: 4
kaf24@3952 561 * indent-tabs-mode: nil
kaf24@4026 562 * End:
kaf24@3952 563 */