debuggers.hg

view xen/common/kexec.c @ 22906:700ac6445812

Now add KDB to the non-kdb tree
author Mukesh Rathor
date Thu Feb 03 15:42:41 2011 -0800 (2011-02-03)
parents cb756381087c
children
line source
1 /******************************************************************************
2 * kexec.c - Achitecture independent kexec code for Xen
3 *
4 * Xen port written by:
5 * - Simon 'Horms' Horman <horms@verge.net.au>
6 * - Magnus Damm <magnus@valinux.co.jp>
7 */
9 #include <xen/init.h>
10 #include <xen/lib.h>
11 #include <xen/acpi.h>
12 #include <xen/ctype.h>
13 #include <xen/errno.h>
14 #include <xen/guest_access.h>
15 #include <xen/sched.h>
16 #include <xen/types.h>
17 #include <xen/kexec.h>
18 #include <xen/keyhandler.h>
19 #include <public/kexec.h>
20 #include <xen/cpumask.h>
21 #include <asm/atomic.h>
22 #include <xen/spinlock.h>
23 #include <xen/version.h>
24 #include <xen/console.h>
25 #include <xen/kexec.h>
26 #include <public/elfnote.h>
27 #include <xsm/xsm.h>
28 #ifdef CONFIG_COMPAT
29 #include <compat/kexec.h>
30 #endif
32 static DEFINE_PER_CPU_READ_MOSTLY(void *, crash_notes);
34 static Elf_Note *xen_crash_note;
36 static cpumask_t crash_saved_cpus;
38 static xen_kexec_image_t kexec_image[KEXEC_IMAGE_NR];
40 #define KEXEC_FLAG_DEFAULT_POS (KEXEC_IMAGE_NR + 0)
41 #define KEXEC_FLAG_CRASH_POS (KEXEC_IMAGE_NR + 1)
42 #define KEXEC_FLAG_IN_PROGRESS (KEXEC_IMAGE_NR + 2)
44 static unsigned long kexec_flags = 0; /* the lowest bits are for KEXEC_IMAGE... */
46 static spinlock_t kexec_lock = SPIN_LOCK_UNLOCKED;
48 static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
49 static size_t vmcoreinfo_size = 0;
51 xen_kexec_reserve_t kexec_crash_area;
52 static struct {
53 u64 start, end;
54 unsigned long size;
55 } ranges[16] __initdata;
57 /*
58 * Parse command lines in the format
59 *
60 * crashkernel=<ramsize-range>:<size>[,...][@<offset>]
61 *
62 * with <ramsize-range> being of form
63 *
64 * <start>-[<end>]
65 *
66 * as well as the legacy ones in the format
67 *
68 * crashkernel=<size>[@<offset>]
69 */
70 static void __init parse_crashkernel(const char *str)
71 {
72 const char *cur;
74 if ( strchr(str, ':' ) )
75 {
76 unsigned int idx = 0;
78 do {
79 if ( idx >= ARRAY_SIZE(ranges) )
80 {
81 printk(XENLOG_WARNING "crashkernel: too many ranges\n");
82 cur = NULL;
83 str = strchr(str, '@');
84 break;
85 }
87 ranges[idx].start = parse_size_and_unit(cur = str + !!idx, &str);
88 if ( cur == str )
89 break;
91 if ( *str != '-' )
92 {
93 printk(XENLOG_WARNING "crashkernel: '-' expected\n");
94 break;
95 }
97 if ( *++str != ':' )
98 {
99 ranges[idx].end = parse_size_and_unit(cur = str, &str);
100 if ( cur == str )
101 break;
102 if ( ranges[idx].end <= ranges[idx].start )
103 {
104 printk(XENLOG_WARNING "crashkernel: end <= start\n");
105 break;
106 }
107 }
108 else
109 ranges[idx].end = -1;
111 if ( *str != ':' )
112 {
113 printk(XENLOG_WARNING "crashkernel: ':' expected\n");
114 break;
115 }
117 ranges[idx].size = parse_size_and_unit(cur = str + 1, &str);
118 if ( cur == str )
119 break;
121 ++idx;
122 } while ( *str == ',' );
123 if ( idx < ARRAY_SIZE(ranges) )
124 ranges[idx].size = 0;
125 }
126 else
127 kexec_crash_area.size = parse_size_and_unit(cur = str, &str);
128 if ( cur != str && *str == '@' )
129 kexec_crash_area.start = parse_size_and_unit(cur = str + 1, &str);
130 if ( cur == str )
131 printk(XENLOG_WARNING "crashkernel: memory value expected\n");
132 }
133 custom_param("crashkernel", parse_crashkernel);
135 void __init set_kexec_crash_area_size(u64 system_ram)
136 {
137 unsigned int idx;
139 for ( idx = 0; idx < ARRAY_SIZE(ranges) && !kexec_crash_area.size; ++idx )
140 {
141 if ( !ranges[idx].size )
142 break;
144 if ( ranges[idx].size >= system_ram )
145 {
146 printk(XENLOG_WARNING "crashkernel: invalid size\n");
147 continue;
148 }
150 if ( ranges[idx].start <= system_ram && ranges[idx].end > system_ram )
151 kexec_crash_area.size = ranges[idx].size;
152 }
153 }
155 static void one_cpu_only(void)
156 {
157 /* Only allow the first cpu to continue - force other cpus to spin */
158 if ( test_and_set_bit(KEXEC_FLAG_IN_PROGRESS, &kexec_flags) )
159 for ( ; ; ) ;
160 }
162 /* Save the registers in the per-cpu crash note buffer. */
163 void kexec_crash_save_cpu(void)
164 {
165 int cpu = smp_processor_id();
166 Elf_Note *note = per_cpu(crash_notes, cpu);
167 ELF_Prstatus *prstatus;
168 crash_xen_core_t *xencore;
170 if ( cpu_test_and_set(cpu, crash_saved_cpus) )
171 return;
173 prstatus = (ELF_Prstatus *)ELFNOTE_DESC(note);
175 note = ELFNOTE_NEXT(note);
176 xencore = (crash_xen_core_t *)ELFNOTE_DESC(note);
178 elf_core_save_regs(&prstatus->pr_reg, xencore);
179 }
181 /* Set up the single Xen-specific-info crash note. */
182 crash_xen_info_t *kexec_crash_save_info(void)
183 {
184 int cpu = smp_processor_id();
185 crash_xen_info_t info;
186 crash_xen_info_t *out = (crash_xen_info_t *)ELFNOTE_DESC(xen_crash_note);
188 BUG_ON(!cpu_test_and_set(cpu, crash_saved_cpus));
190 memset(&info, 0, sizeof(info));
191 info.xen_major_version = xen_major_version();
192 info.xen_minor_version = xen_minor_version();
193 info.xen_extra_version = __pa(xen_extra_version());
194 info.xen_changeset = __pa(xen_changeset());
195 info.xen_compiler = __pa(xen_compiler());
196 info.xen_compile_date = __pa(xen_compile_date());
197 info.xen_compile_time = __pa(xen_compile_time());
198 info.tainted = tainted;
200 /* Copy from guaranteed-aligned local copy to possibly-unaligned dest. */
201 memcpy(out, &info, sizeof(info));
203 return out;
204 }
206 static void kexec_common_shutdown(void)
207 {
208 watchdog_disable();
209 console_start_sync();
210 spin_debug_disable();
211 one_cpu_only();
212 acpi_dmar_reinstate();
213 }
215 void kexec_crash(void)
216 {
217 int pos;
219 pos = (test_bit(KEXEC_FLAG_CRASH_POS, &kexec_flags) != 0);
220 if ( !test_bit(KEXEC_IMAGE_CRASH_BASE + pos, &kexec_flags) )
221 return;
223 kexec_common_shutdown();
224 kexec_crash_save_cpu();
225 machine_crash_shutdown();
226 machine_kexec(&kexec_image[KEXEC_IMAGE_CRASH_BASE + pos]);
228 BUG();
229 }
231 static long kexec_reboot(void *_image)
232 {
233 xen_kexec_image_t *image = _image;
235 kexec_common_shutdown();
236 machine_reboot_kexec(image);
238 BUG();
239 return 0;
240 }
242 static void do_crashdump_trigger(unsigned char key)
243 {
244 printk("'%c' pressed -> triggering crashdump\n", key);
245 kexec_crash();
246 printk(" * no crash kernel loaded!\n");
247 }
249 static struct keyhandler crashdump_trigger_keyhandler = {
250 .u.fn = do_crashdump_trigger,
251 .desc = "trigger a crashdump"
252 };
254 static __init int register_crashdump_trigger(void)
255 {
256 register_keyhandler('C', &crashdump_trigger_keyhandler);
257 return 0;
258 }
259 __initcall(register_crashdump_trigger);
261 static void setup_note(Elf_Note *n, const char *name, int type, int descsz)
262 {
263 int l = strlen(name) + 1;
264 strlcpy(ELFNOTE_NAME(n), name, l);
265 n->namesz = l;
266 n->descsz = descsz;
267 n->type = type;
268 }
270 static int sizeof_note(const char *name, int descsz)
271 {
272 return (sizeof(Elf_Note) +
273 ELFNOTE_ALIGN(strlen(name)+1) +
274 ELFNOTE_ALIGN(descsz));
275 }
277 static int kexec_get_reserve(xen_kexec_range_t *range)
278 {
279 if ( kexec_crash_area.size > 0 && kexec_crash_area.start > 0) {
280 range->start = kexec_crash_area.start;
281 range->size = kexec_crash_area.size;
282 }
283 else
284 range->start = range->size = 0;
285 return 0;
286 }
288 static int kexec_get_cpu(xen_kexec_range_t *range)
289 {
290 int nr = range->nr;
291 int nr_bytes = 0;
293 if ( nr < 0 || nr >= NR_CPUS || !cpu_online(nr) )
294 return -EINVAL;
296 nr_bytes += sizeof_note("CORE", sizeof(ELF_Prstatus));
297 nr_bytes += sizeof_note("Xen", sizeof(crash_xen_core_t));
299 /* The Xen info note is included in CPU0's range. */
300 if ( nr == 0 )
301 nr_bytes += sizeof_note("Xen", sizeof(crash_xen_info_t));
303 if ( per_cpu(crash_notes, nr) == NULL )
304 {
305 Elf_Note *note;
307 note = per_cpu(crash_notes, nr) = xmalloc_bytes(nr_bytes);
309 if ( note == NULL )
310 return -ENOMEM;
312 /* Setup CORE note. */
313 setup_note(note, "CORE", NT_PRSTATUS, sizeof(ELF_Prstatus));
315 /* Setup Xen CORE note. */
316 note = ELFNOTE_NEXT(note);
317 setup_note(note, "Xen", XEN_ELFNOTE_CRASH_REGS, sizeof(crash_xen_core_t));
319 if (nr == 0)
320 {
321 /* Setup system wide Xen info note. */
322 xen_crash_note = note = ELFNOTE_NEXT(note);
323 setup_note(note, "Xen", XEN_ELFNOTE_CRASH_INFO, sizeof(crash_xen_info_t));
324 }
325 }
327 range->start = __pa((unsigned long)per_cpu(crash_notes, nr));
328 range->size = nr_bytes;
329 return 0;
330 }
332 static int kexec_get_vmcoreinfo(xen_kexec_range_t *range)
333 {
334 range->start = __pa((unsigned long)vmcoreinfo_data);
335 range->size = VMCOREINFO_BYTES;
336 return 0;
337 }
339 static int kexec_get_range_internal(xen_kexec_range_t *range)
340 {
341 int ret = -EINVAL;
343 switch ( range->range )
344 {
345 case KEXEC_RANGE_MA_CRASH:
346 ret = kexec_get_reserve(range);
347 break;
348 case KEXEC_RANGE_MA_CPU:
349 ret = kexec_get_cpu(range);
350 break;
351 case KEXEC_RANGE_MA_VMCOREINFO:
352 ret = kexec_get_vmcoreinfo(range);
353 break;
354 default:
355 ret = machine_kexec_get(range);
356 break;
357 }
359 return ret;
360 }
362 static int kexec_get_range(XEN_GUEST_HANDLE(void) uarg)
363 {
364 xen_kexec_range_t range;
365 int ret = -EINVAL;
367 if ( unlikely(copy_from_guest(&range, uarg, 1)) )
368 return -EFAULT;
370 ret = kexec_get_range_internal(&range);
372 if ( ret == 0 && unlikely(copy_to_guest(uarg, &range, 1)) )
373 return -EFAULT;
375 return ret;
376 }
378 static int kexec_get_range_compat(XEN_GUEST_HANDLE(void) uarg)
379 {
380 #ifdef CONFIG_COMPAT
381 xen_kexec_range_t range;
382 compat_kexec_range_t compat_range;
383 int ret = -EINVAL;
385 if ( unlikely(copy_from_guest(&compat_range, uarg, 1)) )
386 return -EFAULT;
388 XLAT_kexec_range(&range, &compat_range);
390 ret = kexec_get_range_internal(&range);
392 if ( ret == 0 ) {
393 XLAT_kexec_range(&compat_range, &range);
394 if ( unlikely(copy_to_guest(uarg, &compat_range, 1)) )
395 return -EFAULT;
396 }
398 return ret;
399 #else /* CONFIG_COMPAT */
400 return 0;
401 #endif /* CONFIG_COMPAT */
402 }
404 static int kexec_load_get_bits(int type, int *base, int *bit)
405 {
406 switch ( type )
407 {
408 case KEXEC_TYPE_DEFAULT:
409 *base = KEXEC_IMAGE_DEFAULT_BASE;
410 *bit = KEXEC_FLAG_DEFAULT_POS;
411 break;
412 case KEXEC_TYPE_CRASH:
413 *base = KEXEC_IMAGE_CRASH_BASE;
414 *bit = KEXEC_FLAG_CRASH_POS;
415 break;
416 default:
417 return -1;
418 }
419 return 0;
420 }
422 void vmcoreinfo_append_str(const char *fmt, ...)
423 {
424 va_list args;
425 char buf[0x50];
426 int r;
427 size_t note_size = sizeof(Elf_Note) + ELFNOTE_ALIGN(strlen(VMCOREINFO_NOTE_NAME) + 1);
429 if (vmcoreinfo_size + note_size + sizeof(buf) > VMCOREINFO_BYTES)
430 return;
432 va_start(args, fmt);
433 r = vsnprintf(buf, sizeof(buf), fmt, args);
434 va_end(args);
436 memcpy(&vmcoreinfo_data[note_size + vmcoreinfo_size], buf, r);
438 vmcoreinfo_size += r;
439 }
441 static void crash_save_vmcoreinfo(void)
442 {
443 size_t data_size;
445 if (vmcoreinfo_size > 0) /* already saved */
446 return;
448 data_size = VMCOREINFO_BYTES - (sizeof(Elf_Note) + ELFNOTE_ALIGN(strlen(VMCOREINFO_NOTE_NAME) + 1));
449 setup_note((Elf_Note *)vmcoreinfo_data, VMCOREINFO_NOTE_NAME, 0, data_size);
451 VMCOREINFO_PAGESIZE(PAGE_SIZE);
453 VMCOREINFO_SYMBOL(domain_list);
454 #ifndef frame_table
455 VMCOREINFO_SYMBOL(frame_table);
456 #else
457 {
458 static const void *const _frame_table = frame_table;
459 VMCOREINFO_SYMBOL_ALIAS(frame_table, _frame_table);
460 }
461 #endif
462 VMCOREINFO_SYMBOL(max_page);
464 VMCOREINFO_STRUCT_SIZE(page_info);
465 VMCOREINFO_STRUCT_SIZE(domain);
467 VMCOREINFO_OFFSET(page_info, count_info);
468 #ifdef __ia64__
469 VMCOREINFO_OFFSET_SUB(page_info, u.inuse, _domain);
470 #else
471 VMCOREINFO_OFFSET_SUB(page_info, v.inuse, _domain);
472 #endif
473 VMCOREINFO_OFFSET(domain, domain_id);
474 VMCOREINFO_OFFSET(domain, next_in_list);
476 #ifdef ARCH_CRASH_SAVE_VMCOREINFO
477 arch_crash_save_vmcoreinfo();
478 #endif
479 }
481 static int kexec_load_unload_internal(unsigned long op, xen_kexec_load_t *load)
482 {
483 xen_kexec_image_t *image;
484 int base, bit, pos;
485 int ret = 0;
487 if ( kexec_load_get_bits(load->type, &base, &bit) )
488 return -EINVAL;
490 pos = (test_bit(bit, &kexec_flags) != 0);
492 /* Load the user data into an unused image */
493 if ( op == KEXEC_CMD_kexec_load )
494 {
495 image = &kexec_image[base + !pos];
497 BUG_ON(test_bit((base + !pos), &kexec_flags)); /* must be free */
499 memcpy(image, &load->image, sizeof(*image));
501 if ( !(ret = machine_kexec_load(load->type, base + !pos, image)) )
502 {
503 /* Set image present bit */
504 set_bit((base + !pos), &kexec_flags);
506 /* Make new image the active one */
507 change_bit(bit, &kexec_flags);
508 }
510 crash_save_vmcoreinfo();
511 }
513 /* Unload the old image if present and load successful */
514 if ( ret == 0 && !test_bit(KEXEC_FLAG_IN_PROGRESS, &kexec_flags) )
515 {
516 if ( test_and_clear_bit((base + pos), &kexec_flags) )
517 {
518 image = &kexec_image[base + pos];
519 machine_kexec_unload(load->type, base + pos, image);
520 }
521 }
523 return ret;
524 }
526 static int kexec_load_unload(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
527 {
528 xen_kexec_load_t load;
530 if ( unlikely(copy_from_guest(&load, uarg, 1)) )
531 return -EFAULT;
533 return kexec_load_unload_internal(op, &load);
534 }
536 static int kexec_load_unload_compat(unsigned long op,
537 XEN_GUEST_HANDLE(void) uarg)
538 {
539 #ifdef CONFIG_COMPAT
540 compat_kexec_load_t compat_load;
541 xen_kexec_load_t load;
543 if ( unlikely(copy_from_guest(&compat_load, uarg, 1)) )
544 return -EFAULT;
546 /* This is a bit dodgy, load.image is inside load,
547 * but XLAT_kexec_load (which is automatically generated)
548 * doesn't translate load.image (correctly)
549 * Just copy load->type, the only other member, manually instead.
550 *
551 * XLAT_kexec_load(&load, &compat_load);
552 */
553 load.type = compat_load.type;
554 XLAT_kexec_image(&load.image, &compat_load.image);
556 return kexec_load_unload_internal(op, &load);
557 #else /* CONFIG_COMPAT */
558 return 0;
559 #endif /* CONFIG_COMPAT */
560 }
562 static int kexec_exec(XEN_GUEST_HANDLE(void) uarg)
563 {
564 xen_kexec_exec_t exec;
565 xen_kexec_image_t *image;
566 int base, bit, pos, ret = -EINVAL;
568 if ( unlikely(copy_from_guest(&exec, uarg, 1)) )
569 return -EFAULT;
571 if ( kexec_load_get_bits(exec.type, &base, &bit) )
572 return -EINVAL;
574 pos = (test_bit(bit, &kexec_flags) != 0);
576 /* Only allow kexec/kdump into loaded images */
577 if ( !test_bit(base + pos, &kexec_flags) )
578 return -ENOENT;
580 switch (exec.type)
581 {
582 case KEXEC_TYPE_DEFAULT:
583 image = &kexec_image[base + pos];
584 ret = continue_hypercall_on_cpu(0, kexec_reboot, image);
585 break;
586 case KEXEC_TYPE_CRASH:
587 kexec_crash(); /* Does not return */
588 break;
589 }
591 return -EINVAL; /* never reached */
592 }
594 int do_kexec_op_internal(unsigned long op, XEN_GUEST_HANDLE(void) uarg,
595 int compat)
596 {
597 unsigned long flags;
598 int ret = -EINVAL;
600 if ( !IS_PRIV(current->domain) )
601 return -EPERM;
603 ret = xsm_kexec();
604 if ( ret )
605 return ret;
607 switch ( op )
608 {
609 case KEXEC_CMD_kexec_get_range:
610 if (compat)
611 ret = kexec_get_range_compat(uarg);
612 else
613 ret = kexec_get_range(uarg);
614 break;
615 case KEXEC_CMD_kexec_load:
616 case KEXEC_CMD_kexec_unload:
617 spin_lock_irqsave(&kexec_lock, flags);
618 if (!test_bit(KEXEC_FLAG_IN_PROGRESS, &kexec_flags))
619 {
620 if (compat)
621 ret = kexec_load_unload_compat(op, uarg);
622 else
623 ret = kexec_load_unload(op, uarg);
624 }
625 spin_unlock_irqrestore(&kexec_lock, flags);
626 break;
627 case KEXEC_CMD_kexec:
628 ret = kexec_exec(uarg);
629 break;
630 }
632 return ret;
633 }
635 long do_kexec_op(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
636 {
637 return do_kexec_op_internal(op, uarg, 0);
638 }
640 #ifdef CONFIG_COMPAT
641 int compat_kexec_op(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
642 {
643 return do_kexec_op_internal(op, uarg, 1);
644 }
645 #endif
647 /*
648 * Local variables:
649 * mode: C
650 * c-set-style: "BSD"
651 * c-basic-offset: 4
652 * tab-width: 4
653 * indent-tabs-mode: nil
654 * End:
655 */