blob: f96c2dd1dcb59b3df55e7e88fbe88736226843f5 [file] [log] [blame]
Dmitry V. Levin90aa9f42014-02-05 13:48:26 +00001#include "defs.h"
2#include <linux/kexec.h>
3
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +00004#include "xlat/kexec_arch_values.h"
Dmitry V. Levin90aa9f42014-02-05 13:48:26 +00005
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +00006#include "xlat/kexec_flags.h"
Dmitry V. Levin90aa9f42014-02-05 13:48:26 +00007
8static void
9print_kexec_segments(struct tcb *tcp, unsigned long addr, unsigned long len)
10{
11#if SUPPORTED_PERSONALITIES > 1
12 union {
13 struct { u_int32_t buf, bufsz, mem, memsz; } seg32;
14 struct { u_int64_t buf, bufsz, mem, memsz; } seg64;
15 } seg;
16# define sizeof_seg \
17 (current_wordsize == 4 ? sizeof(seg.seg32) : sizeof(seg.seg64))
18# define seg_buf \
19 (current_wordsize == 4 ? (uint64_t) seg.seg32.buf : seg.seg64.buf)
20# define seg_bufsz \
21 (current_wordsize == 4 ? (uint64_t) seg.seg32.bufsz : seg.seg64.bufsz)
22# define seg_mem \
23 (current_wordsize == 4 ? (uint64_t) seg.seg32.mem : seg.seg64.mem)
24# define seg_memsz \
25 (current_wordsize == 4 ? (uint64_t) seg.seg32.memsz : seg.seg64.memsz)
26#else
27 struct kexec_segment seg;
28# define sizeof_seg sizeof(seg)
Dmitry V. Levin900ec1b2014-02-06 21:13:36 +000029# define seg_buf seg.buf
30# define seg_bufsz seg.bufsz
31# define seg_mem seg.mem
32# define seg_memsz seg.memsz
Dmitry V. Levin90aa9f42014-02-05 13:48:26 +000033#endif
34 unsigned int i, failed;
35
36 if (!len) {
37 tprints("[]");
38 return;
39 }
40
41 if (len > KEXEC_SEGMENT_MAX) {
42 tprintf("%#lx", addr);
43 return;
44 }
45
46 failed = 0;
47 tprints("[");
48 for (i = 0; i < len; ++i) {
49 if (i)
50 tprints(", ");
51 if (umoven(tcp, addr + i * sizeof_seg, sizeof_seg,
52 (char *) &seg) < 0) {
53 tprints("?");
54 failed = 1;
55 break;
56 }
57 tprintf("{%#lx, %lu, %#lx, %lu}",
58 (long) seg_buf, (unsigned long) seg_bufsz,
59 (long) seg_mem, (unsigned long) seg_memsz);
60 }
61 tprints("]");
62 if (failed)
63 tprintf(" %#lx", addr);
64}
65
66int
67sys_kexec_load(struct tcb *tcp)
68{
69 unsigned long n;
70
71 if (exiting(tcp))
72 return 0;
73
74 /* entry, nr_segments */
75 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
76
77 /* segments */
78 print_kexec_segments(tcp, tcp->u_arg[2], tcp->u_arg[1]);
79 tprints(", ");
80
81 /* flags */
82 n = tcp->u_arg[3];
83 printxval(kexec_arch_values, n & KEXEC_ARCH_MASK, "KEXEC_ARCH_???");
84 n &= ~KEXEC_ARCH_MASK;
85 if (n) {
86 tprints("|");
87 printflags(kexec_flags, n, "KEXEC_???");
88 }
89
90 return 0;
91}