diff options
| -rw-r--r-- | include/linux/kexec.h | 29 | ||||
| -rw-r--r-- | kernel/kexec_file.c | 30 | ||||
| -rw-r--r-- | kernel/kexec_internal.h | 16 |
3 files changed, 50 insertions, 25 deletions
diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 406c33dcae13..5e320ddaaa82 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h | |||
| @@ -148,7 +148,34 @@ struct kexec_file_ops { | |||
| 148 | kexec_verify_sig_t *verify_sig; | 148 | kexec_verify_sig_t *verify_sig; |
| 149 | #endif | 149 | #endif |
| 150 | }; | 150 | }; |
| 151 | #endif | 151 | |
| 152 | /** | ||
| 153 | * struct kexec_buf - parameters for finding a place for a buffer in memory | ||
| 154 | * @image: kexec image in which memory to search. | ||
| 155 | * @buffer: Contents which will be copied to the allocated memory. | ||
| 156 | * @bufsz: Size of @buffer. | ||
| 157 | * @mem: On return will have address of the buffer in memory. | ||
| 158 | * @memsz: Size for the buffer in memory. | ||
| 159 | * @buf_align: Minimum alignment needed. | ||
| 160 | * @buf_min: The buffer can't be placed below this address. | ||
| 161 | * @buf_max: The buffer can't be placed above this address. | ||
| 162 | * @top_down: Allocate from top of memory. | ||
| 163 | */ | ||
| 164 | struct kexec_buf { | ||
| 165 | struct kimage *image; | ||
| 166 | char *buffer; | ||
| 167 | unsigned long bufsz; | ||
| 168 | unsigned long mem; | ||
| 169 | unsigned long memsz; | ||
| 170 | unsigned long buf_align; | ||
| 171 | unsigned long buf_min; | ||
| 172 | unsigned long buf_max; | ||
| 173 | bool top_down; | ||
| 174 | }; | ||
| 175 | |||
| 176 | int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf, | ||
| 177 | int (*func)(u64, u64, void *)); | ||
| 178 | #endif /* CONFIG_KEXEC_FILE */ | ||
| 152 | 179 | ||
| 153 | struct kimage { | 180 | struct kimage { |
| 154 | kimage_entry_t head; | 181 | kimage_entry_t head; |
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 037c321c5618..f865674bff51 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c | |||
| @@ -428,6 +428,27 @@ static int locate_mem_hole_callback(u64 start, u64 end, void *arg) | |||
| 428 | return locate_mem_hole_bottom_up(start, end, kbuf); | 428 | return locate_mem_hole_bottom_up(start, end, kbuf); |
| 429 | } | 429 | } |
| 430 | 430 | ||
| 431 | /** | ||
| 432 | * arch_kexec_walk_mem - call func(data) on free memory regions | ||
| 433 | * @kbuf: Context info for the search. Also passed to @func. | ||
| 434 | * @func: Function to call for each memory region. | ||
| 435 | * | ||
| 436 | * Return: The memory walk will stop when func returns a non-zero value | ||
| 437 | * and that value will be returned. If all free regions are visited without | ||
| 438 | * func returning non-zero, then zero will be returned. | ||
| 439 | */ | ||
| 440 | int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf, | ||
| 441 | int (*func)(u64, u64, void *)) | ||
| 442 | { | ||
| 443 | if (kbuf->image->type == KEXEC_TYPE_CRASH) | ||
| 444 | return walk_iomem_res_desc(crashk_res.desc, | ||
| 445 | IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY, | ||
| 446 | crashk_res.start, crashk_res.end, | ||
| 447 | kbuf, func); | ||
| 448 | else | ||
| 449 | return walk_system_ram_res(0, ULONG_MAX, kbuf, func); | ||
| 450 | } | ||
| 451 | |||
| 431 | /* | 452 | /* |
| 432 | * Helper function for placing a buffer in a kexec segment. This assumes | 453 | * Helper function for placing a buffer in a kexec segment. This assumes |
| 433 | * that kexec_mutex is held. | 454 | * that kexec_mutex is held. |
| @@ -474,14 +495,7 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz, | |||
| 474 | kbuf->top_down = top_down; | 495 | kbuf->top_down = top_down; |
| 475 | 496 | ||
| 476 | /* Walk the RAM ranges and allocate a suitable range for the buffer */ | 497 | /* Walk the RAM ranges and allocate a suitable range for the buffer */ |
| 477 | if (image->type == KEXEC_TYPE_CRASH) | 498 | ret = arch_kexec_walk_mem(kbuf, locate_mem_hole_callback); |
| 478 | ret = walk_iomem_res_desc(crashk_res.desc, | ||
| 479 | IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY, | ||
| 480 | crashk_res.start, crashk_res.end, kbuf, | ||
| 481 | locate_mem_hole_callback); | ||
| 482 | else | ||
| 483 | ret = walk_system_ram_res(0, -1, kbuf, | ||
| 484 | locate_mem_hole_callback); | ||
| 485 | if (ret != 1) { | 499 | if (ret != 1) { |
| 486 | /* A suitable memory range could not be found for buffer */ | 500 | /* A suitable memory range could not be found for buffer */ |
| 487 | return -EADDRNOTAVAIL; | 501 | return -EADDRNOTAVAIL; |
diff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h index 0a52315d9c62..4cef7e4706b0 100644 --- a/kernel/kexec_internal.h +++ b/kernel/kexec_internal.h | |||
| @@ -20,22 +20,6 @@ struct kexec_sha_region { | |||
| 20 | unsigned long len; | 20 | unsigned long len; |
| 21 | }; | 21 | }; |
| 22 | 22 | ||
| 23 | /* | ||
| 24 | * Keeps track of buffer parameters as provided by caller for requesting | ||
| 25 | * memory placement of buffer. | ||
| 26 | */ | ||
| 27 | struct kexec_buf { | ||
| 28 | struct kimage *image; | ||
| 29 | char *buffer; | ||
| 30 | unsigned long bufsz; | ||
| 31 | unsigned long mem; | ||
| 32 | unsigned long memsz; | ||
| 33 | unsigned long buf_align; | ||
| 34 | unsigned long buf_min; | ||
| 35 | unsigned long buf_max; | ||
| 36 | bool top_down; /* allocate from top of memory hole */ | ||
| 37 | }; | ||
| 38 | |||
| 39 | void kimage_file_post_load_cleanup(struct kimage *image); | 23 | void kimage_file_post_load_cleanup(struct kimage *image); |
| 40 | #else /* CONFIG_KEXEC_FILE */ | 24 | #else /* CONFIG_KEXEC_FILE */ |
| 41 | static inline void kimage_file_post_load_cleanup(struct kimage *image) { } | 25 | static inline void kimage_file_post_load_cleanup(struct kimage *image) { } |
