17
17
#include <linux/memblock.h>
18
18
#include <linux/of_fdt.h>
19
19
#include <linux/random.h>
20
+ #include <linux/slab.h>
20
21
#include <linux/string.h>
21
22
#include <linux/types.h>
22
23
#include <linux/vmalloc.h>
23
24
#include <asm/byteorder.h>
24
25
25
26
/* relevant device tree properties */
27
+ #define FDT_PROP_KEXEC_ELFHDR "linux,elfcorehdr"
28
+ #define FDT_PROP_MEM_RANGE "linux,usable-memory-range"
26
29
#define FDT_PROP_INITRD_START "linux,initrd-start"
27
30
#define FDT_PROP_INITRD_END "linux,initrd-end"
28
31
#define FDT_PROP_BOOTARGS "bootargs"
@@ -40,6 +43,10 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
40
43
vfree (image -> arch .dtb );
41
44
image -> arch .dtb = NULL ;
42
45
46
+ vfree (image -> arch .elf_headers );
47
+ image -> arch .elf_headers = NULL ;
48
+ image -> arch .elf_headers_sz = 0 ;
49
+
43
50
return kexec_image_post_load_cleanup_default (image );
44
51
}
45
52
@@ -55,6 +62,31 @@ static int setup_dtb(struct kimage *image,
55
62
56
63
off = ret ;
57
64
65
+ ret = fdt_delprop (dtb , off , FDT_PROP_KEXEC_ELFHDR );
66
+ if (ret && ret != - FDT_ERR_NOTFOUND )
67
+ goto out ;
68
+ ret = fdt_delprop (dtb , off , FDT_PROP_MEM_RANGE );
69
+ if (ret && ret != - FDT_ERR_NOTFOUND )
70
+ goto out ;
71
+
72
+ if (image -> type == KEXEC_TYPE_CRASH ) {
73
+ /* add linux,elfcorehdr */
74
+ ret = fdt_appendprop_addrrange (dtb , 0 , off ,
75
+ FDT_PROP_KEXEC_ELFHDR ,
76
+ image -> arch .elf_headers_mem ,
77
+ image -> arch .elf_headers_sz );
78
+ if (ret )
79
+ return (ret == - FDT_ERR_NOSPACE ? - ENOMEM : - EINVAL );
80
+
81
+ /* add linux,usable-memory-range */
82
+ ret = fdt_appendprop_addrrange (dtb , 0 , off ,
83
+ FDT_PROP_MEM_RANGE ,
84
+ crashk_res .start ,
85
+ crashk_res .end - crashk_res .start + 1 );
86
+ if (ret )
87
+ return (ret == - FDT_ERR_NOSPACE ? - ENOMEM : - EINVAL );
88
+ }
89
+
58
90
/* add bootargs */
59
91
if (cmdline ) {
60
92
ret = fdt_setprop_string (dtb , off , FDT_PROP_BOOTARGS , cmdline );
@@ -125,8 +157,8 @@ static int setup_dtb(struct kimage *image,
125
157
}
126
158
127
159
/*
128
- * More space needed so that we can add initrd, bootargs, kaslr-seed, and
129
- * rng-seed.
160
+ * More space needed so that we can add initrd, bootargs, kaslr-seed,
161
+ * rng-seed, userable-memory-range and elfcorehdr .
130
162
*/
131
163
#define DTB_EXTRA_SPACE 0x1000
132
164
@@ -174,21 +206,87 @@ static int create_dtb(struct kimage *image,
174
206
}
175
207
}
176
208
209
+ static int prepare_elf_headers (void * * addr , unsigned long * sz )
210
+ {
211
+ struct crash_mem * cmem ;
212
+ unsigned int nr_ranges ;
213
+ int ret ;
214
+ u64 i ;
215
+ phys_addr_t start , end ;
216
+
217
+ nr_ranges = 1 ; /* for exclusion of crashkernel region */
218
+ for_each_mem_range (i , & memblock .memory , NULL , NUMA_NO_NODE ,
219
+ MEMBLOCK_NONE , & start , & end , NULL )
220
+ nr_ranges ++ ;
221
+
222
+ cmem = kmalloc (sizeof (struct crash_mem ) +
223
+ sizeof (struct crash_mem_range ) * nr_ranges , GFP_KERNEL );
224
+ if (!cmem )
225
+ return - ENOMEM ;
226
+
227
+ cmem -> max_nr_ranges = nr_ranges ;
228
+ cmem -> nr_ranges = 0 ;
229
+ for_each_mem_range (i , & memblock .memory , NULL , NUMA_NO_NODE ,
230
+ MEMBLOCK_NONE , & start , & end , NULL ) {
231
+ cmem -> ranges [cmem -> nr_ranges ].start = start ;
232
+ cmem -> ranges [cmem -> nr_ranges ].end = end - 1 ;
233
+ cmem -> nr_ranges ++ ;
234
+ }
235
+
236
+ /* Exclude crashkernel region */
237
+ ret = crash_exclude_mem_range (cmem , crashk_res .start , crashk_res .end );
238
+
239
+ if (!ret )
240
+ ret = crash_prepare_elf64_headers (cmem , true, addr , sz );
241
+
242
+ kfree (cmem );
243
+ return ret ;
244
+ }
245
+
177
246
int load_other_segments (struct kimage * image ,
178
247
unsigned long kernel_load_addr ,
179
248
unsigned long kernel_size ,
180
249
char * initrd , unsigned long initrd_len ,
181
250
char * cmdline )
182
251
{
183
252
struct kexec_buf kbuf ;
184
- void * dtb = NULL ;
185
- unsigned long initrd_load_addr = 0 , dtb_len ;
253
+ void * headers , * dtb = NULL ;
254
+ unsigned long headers_sz , initrd_load_addr = 0 , dtb_len ;
186
255
int ret = 0 ;
187
256
188
257
kbuf .image = image ;
189
258
/* not allocate anything below the kernel */
190
259
kbuf .buf_min = kernel_load_addr + kernel_size ;
191
260
261
+ /* load elf core header */
262
+ if (image -> type == KEXEC_TYPE_CRASH ) {
263
+ ret = prepare_elf_headers (& headers , & headers_sz );
264
+ if (ret ) {
265
+ pr_err ("Preparing elf core header failed\n" );
266
+ goto out_err ;
267
+ }
268
+
269
+ kbuf .buffer = headers ;
270
+ kbuf .bufsz = headers_sz ;
271
+ kbuf .mem = KEXEC_BUF_MEM_UNKNOWN ;
272
+ kbuf .memsz = headers_sz ;
273
+ kbuf .buf_align = SZ_64K ; /* largest supported page size */
274
+ kbuf .buf_max = ULONG_MAX ;
275
+ kbuf .top_down = true;
276
+
277
+ ret = kexec_add_buffer (& kbuf );
278
+ if (ret ) {
279
+ vfree (headers );
280
+ goto out_err ;
281
+ }
282
+ image -> arch .elf_headers = headers ;
283
+ image -> arch .elf_headers_mem = kbuf .mem ;
284
+ image -> arch .elf_headers_sz = headers_sz ;
285
+
286
+ pr_debug ("Loaded elf core header at 0x%lx bufsz=0x%lx memsz=0x%lx\n" ,
287
+ image -> arch .elf_headers_mem , headers_sz , headers_sz );
288
+ }
289
+
192
290
/* load initrd */
193
291
if (initrd ) {
194
292
kbuf .buffer = initrd ;
0 commit comments