190aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin#include "defs.h" 290aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin#include <linux/kexec.h> 390aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin 40ed617bd66624cec6138102545d73b2e2346f1f6Dmitry V. Levin#include "xlat/kexec_arch_values.h" 50ed617bd66624cec6138102545d73b2e2346f1f6Dmitry V. Levin#include "xlat/kexec_flags.h" 690aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin 790aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levinstatic void 890aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levinprint_kexec_segments(struct tcb *tcp, unsigned long addr, unsigned long len) 990aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin{ 1090aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin#if SUPPORTED_PERSONALITIES > 1 1190aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin union { 1290aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin struct { u_int32_t buf, bufsz, mem, memsz; } seg32; 1390aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin struct { u_int64_t buf, bufsz, mem, memsz; } seg64; 1490aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin } seg; 1590aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin# define sizeof_seg \ 1690aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin (current_wordsize == 4 ? sizeof(seg.seg32) : sizeof(seg.seg64)) 1790aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin# define seg_buf \ 1890aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin (current_wordsize == 4 ? (uint64_t) seg.seg32.buf : seg.seg64.buf) 1990aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin# define seg_bufsz \ 2090aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin (current_wordsize == 4 ? (uint64_t) seg.seg32.bufsz : seg.seg64.bufsz) 2190aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin# define seg_mem \ 2290aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin (current_wordsize == 4 ? (uint64_t) seg.seg32.mem : seg.seg64.mem) 2390aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin# define seg_memsz \ 2490aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin (current_wordsize == 4 ? (uint64_t) seg.seg32.memsz : seg.seg64.memsz) 2590aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin#else 2690aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin struct kexec_segment seg; 2790aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin# define sizeof_seg sizeof(seg) 28900ec1b0428b1ba2676d00b8c7cc4b0f9a89c543Dmitry V. Levin# define seg_buf seg.buf 29900ec1b0428b1ba2676d00b8c7cc4b0f9a89c543Dmitry V. Levin# define seg_bufsz seg.bufsz 30900ec1b0428b1ba2676d00b8c7cc4b0f9a89c543Dmitry V. Levin# define seg_mem seg.mem 31900ec1b0428b1ba2676d00b8c7cc4b0f9a89c543Dmitry V. Levin# define seg_memsz seg.memsz 3290aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin#endif 3390aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin unsigned int i, failed; 3490aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin 3590aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin if (!len) { 3690aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin tprints("[]"); 3790aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin return; 3890aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin } 3990aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin 4090aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin if (len > KEXEC_SEGMENT_MAX) { 4190aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin tprintf("%#lx", addr); 4290aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin return; 4390aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin } 4490aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin 4590aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin failed = 0; 4690aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin tprints("["); 4790aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin for (i = 0; i < len; ++i) { 4890aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin if (i) 4990aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin tprints(", "); 5090aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin if (umoven(tcp, addr + i * sizeof_seg, sizeof_seg, 5190aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin (char *) &seg) < 0) { 5290aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin tprints("?"); 5390aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin failed = 1; 5490aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin break; 5590aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin } 5690aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin tprintf("{%#lx, %lu, %#lx, %lu}", 5790aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin (long) seg_buf, (unsigned long) seg_bufsz, 5890aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin (long) seg_mem, (unsigned long) seg_memsz); 5990aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin } 6090aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin tprints("]"); 6190aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin if (failed) 6290aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin tprintf(" %#lx", addr); 6390aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin} 6490aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin 6590aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levinint 6690aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levinsys_kexec_load(struct tcb *tcp) 6790aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin{ 6890aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin unsigned long n; 6990aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin 7090aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin if (exiting(tcp)) 7190aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin return 0; 7290aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin 7390aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin /* entry, nr_segments */ 7490aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); 7590aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin 7690aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin /* segments */ 7790aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin print_kexec_segments(tcp, tcp->u_arg[2], tcp->u_arg[1]); 7890aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin tprints(", "); 7990aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin 8090aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin /* flags */ 8190aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin n = tcp->u_arg[3]; 8290aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin printxval(kexec_arch_values, n & KEXEC_ARCH_MASK, "KEXEC_ARCH_???"); 8390aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin n &= ~KEXEC_ARCH_MASK; 8490aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin if (n) { 8590aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin tprints("|"); 8690aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin printflags(kexec_flags, n, "KEXEC_???"); 8790aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin } 8890aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin 8990aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin return 0; 9090aa9f4d72e26581ea0a39c02db625d7bd4e2962Dmitry V. Levin} 91