blob: 9c675cc72e738e786e4e8ac594008330e57fd026 [file] [log] [blame]
Dmitry V. Levin90aa9f42014-02-05 13:48:26 +00001#include "defs.h"
2#include <linux/kexec.h>
3
4static const struct xlat kexec_arch_values[] = {
5 XLAT(KEXEC_ARCH_DEFAULT),
6 XLAT(KEXEC_ARCH_386),
7 XLAT(KEXEC_ARCH_X86_64),
8 XLAT(KEXEC_ARCH_PPC),
9 XLAT(KEXEC_ARCH_PPC64),
10 XLAT(KEXEC_ARCH_IA_64),
11 XLAT(KEXEC_ARCH_ARM),
12 XLAT(KEXEC_ARCH_S390),
13 XLAT(KEXEC_ARCH_SH),
14 XLAT(KEXEC_ARCH_MIPS_LE),
15 XLAT(KEXEC_ARCH_MIPS),
16 XLAT_END
17};
18
19static const struct xlat kexec_flags[] = {
20 XLAT(KEXEC_ON_CRASH),
21 XLAT(KEXEC_PRESERVE_CONTEXT),
22 XLAT_END
23};
24
25static void
26print_kexec_segments(struct tcb *tcp, unsigned long addr, unsigned long len)
27{
28#if SUPPORTED_PERSONALITIES > 1
29 union {
30 struct { u_int32_t buf, bufsz, mem, memsz; } seg32;
31 struct { u_int64_t buf, bufsz, mem, memsz; } seg64;
32 } seg;
33# define sizeof_seg \
34 (current_wordsize == 4 ? sizeof(seg.seg32) : sizeof(seg.seg64))
35# define seg_buf \
36 (current_wordsize == 4 ? (uint64_t) seg.seg32.buf : seg.seg64.buf)
37# define seg_bufsz \
38 (current_wordsize == 4 ? (uint64_t) seg.seg32.bufsz : seg.seg64.bufsz)
39# define seg_mem \
40 (current_wordsize == 4 ? (uint64_t) seg.seg32.mem : seg.seg64.mem)
41# define seg_memsz \
42 (current_wordsize == 4 ? (uint64_t) seg.seg32.memsz : seg.seg64.memsz)
43#else
44 struct kexec_segment seg;
45# define sizeof_seg sizeof(seg)
46# define seg_buf seg.seg_buf
47# define seg_bufsz seg.seg_bufsz
48# define seg_mem seg.seg_mem
49# define seg_memsz seg.seg_memsz
50#endif
51 unsigned int i, failed;
52
53 if (!len) {
54 tprints("[]");
55 return;
56 }
57
58 if (len > KEXEC_SEGMENT_MAX) {
59 tprintf("%#lx", addr);
60 return;
61 }
62
63 failed = 0;
64 tprints("[");
65 for (i = 0; i < len; ++i) {
66 if (i)
67 tprints(", ");
68 if (umoven(tcp, addr + i * sizeof_seg, sizeof_seg,
69 (char *) &seg) < 0) {
70 tprints("?");
71 failed = 1;
72 break;
73 }
74 tprintf("{%#lx, %lu, %#lx, %lu}",
75 (long) seg_buf, (unsigned long) seg_bufsz,
76 (long) seg_mem, (unsigned long) seg_memsz);
77 }
78 tprints("]");
79 if (failed)
80 tprintf(" %#lx", addr);
81}
82
83int
84sys_kexec_load(struct tcb *tcp)
85{
86 unsigned long n;
87
88 if (exiting(tcp))
89 return 0;
90
91 /* entry, nr_segments */
92 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
93
94 /* segments */
95 print_kexec_segments(tcp, tcp->u_arg[2], tcp->u_arg[1]);
96 tprints(", ");
97
98 /* flags */
99 n = tcp->u_arg[3];
100 printxval(kexec_arch_values, n & KEXEC_ARCH_MASK, "KEXEC_ARCH_???");
101 n &= ~KEXEC_ARCH_MASK;
102 if (n) {
103 tprints("|");
104 printflags(kexec_flags, n, "KEXEC_???");
105 }
106
107 return 0;
108}