206 lines
5.7 KiB
Diff
206 lines
5.7 KiB
Diff
From 363087cd156f870dfd07fef04077696daa77acaa Mon Sep 17 00:00:00 2001
|
|
From: Song Shuai <songshuaishuai@tinylab.org>
|
|
Date: Tue, 22 Apr 2025 18:22:59 +0200
|
|
Subject: [PATCH] RISC-V: Separate elf_riscv_find_pbase out
|
|
|
|
The is the preparative patch for RISC-V kexec Image file support.
|
|
|
|
Separate the elf_riscv_find_pbase() function out to
|
|
allow kernel_load syscall load Image binary file.
|
|
|
|
Signed-off-by: Song Shuai <songshuaishuai@tinylab.org>
|
|
Signed-off-by: Simon Horman <horms@kernel.org>
|
|
---
|
|
kexec/arch/riscv/kexec-elf-riscv.c | 72 +-----------------------------
|
|
kexec/arch/riscv/kexec-riscv.c | 55 +++++++++++++++++++++++
|
|
kexec/arch/riscv/kexec-riscv.h | 13 ++++++
|
|
3 files changed, 69 insertions(+), 71 deletions(-)
|
|
|
|
diff --git a/kexec/arch/riscv/kexec-elf-riscv.c b/kexec/arch/riscv/kexec-elf-riscv.c
|
|
index 2b9f66d7..434873cf 100644
|
|
--- a/kexec/arch/riscv/kexec-elf-riscv.c
|
|
+++ b/kexec/arch/riscv/kexec-elf-riscv.c
|
|
@@ -12,76 +12,6 @@
|
|
#include "kexec-syscall.h" /* For KEXEC_ON_CRASH */
|
|
#include "kexec-riscv.h"
|
|
|
|
-
|
|
-/*********\
|
|
-* HELPERS *
|
|
-\*********/
|
|
-
|
|
-/*
|
|
- * Go through the available physical memory regions and
|
|
- * find one that can hold an image of the specified size.
|
|
- * Note: This is called after get_memory_ranges so
|
|
- * info->memory_range[] should be populated. Also note that
|
|
- * memory ranges are sorted, so we'll return the first region
|
|
- * that's big enough for holding the image.
|
|
- */
|
|
-static int elf_riscv_find_pbase(struct kexec_info *info, off_t *addr,
|
|
- off_t size)
|
|
-{
|
|
- int i = 0;
|
|
- off_t start = 0;
|
|
- off_t end = 0;
|
|
- int ret = 0;
|
|
-
|
|
- /*
|
|
- * If this image is for a crash kernel, use the region
|
|
- * the primary kernel has already reserved for us.
|
|
- */
|
|
- if (info->kexec_flags & KEXEC_ON_CRASH) {
|
|
- ret = get_crash_kernel_load_range((uint64_t *) &start,
|
|
- (uint64_t *) &end);
|
|
- if (!ret) {
|
|
- /*
|
|
- * Kernel should be aligned to the nearest
|
|
- * hugepage (2MB for RV64, 4MB for RV32).
|
|
- */
|
|
-#if __riscv_xlen == 64
|
|
- start = _ALIGN_UP(start, 0x200000);
|
|
-#else
|
|
- start = _ALIGN_UP(start, 0x400000);
|
|
-#endif
|
|
- if (end > start && ((end - start) >= size)) {
|
|
- *addr = start;
|
|
- return 0;
|
|
- }
|
|
-
|
|
- return -EFBIG;
|
|
- } else
|
|
- return ENOCRASHKERNEL;
|
|
- }
|
|
-
|
|
- for (i = 0; i < info->memory_ranges; i++) {
|
|
- if (info->memory_range[i].type != RANGE_RAM)
|
|
- continue;
|
|
-
|
|
- start = info->memory_range[i].start;
|
|
- end = info->memory_range[i].end;
|
|
-
|
|
-#if __riscv_xlen == 64
|
|
- start = _ALIGN_UP(start, 0x200000);
|
|
-#else
|
|
- start = _ALIGN_UP(start, 0x400000);
|
|
-#endif
|
|
-
|
|
- if (end > start && ((end - start) >= size)) {
|
|
- *addr = start;
|
|
- return 0;
|
|
- }
|
|
- }
|
|
-
|
|
- return -EFBIG;
|
|
-}
|
|
-
|
|
/**************\
|
|
* ENTRY POINTS *
|
|
\**************/
|
|
@@ -182,7 +112,7 @@ int elf_riscv_load(int argc, char **argv, const char *buf, off_t len,
|
|
kernel_size / 1024, old_base_addr, old_start_addr);
|
|
|
|
/* Get a continuous physical region that can hold the kernel */
|
|
- ret = elf_riscv_find_pbase(info, &new_base_addr, kernel_size);
|
|
+ ret = riscv_find_pbase(info, &new_base_addr, kernel_size, KERNEL_ALIGN);
|
|
if (ret < 0) {
|
|
fprintf(stderr, "Could not find a memory region for the "
|
|
"provided ELF image\n");
|
|
diff --git a/kexec/arch/riscv/kexec-riscv.c b/kexec/arch/riscv/kexec-riscv.c
|
|
index bbc25c5c..63165930 100644
|
|
--- a/kexec/arch/riscv/kexec-riscv.c
|
|
+++ b/kexec/arch/riscv/kexec-riscv.c
|
|
@@ -50,6 +50,61 @@ static struct fdt_image provided_fdt = {0};
|
|
* COMMON HELPERS *
|
|
\****************/
|
|
|
|
+/*
|
|
+ * Go through the available physical memory regions and
|
|
+ * find one that can hold an image of the specified size
|
|
+ * and start address should be aligned up with `align`.
|
|
+ * Note: This is called after get_memory_ranges so
|
|
+ * info->memory_range[] should be populated. Also note that
|
|
+ * memory ranges are sorted, so we'll return the first region
|
|
+ * that's big enough for holding the image.
|
|
+ */
|
|
+int riscv_find_pbase(struct kexec_info *info, off_t *addr,
|
|
+ off_t size, off_t align)
|
|
+{
|
|
+ int i = 0;
|
|
+ off_t start = 0;
|
|
+ off_t end = 0;
|
|
+ int ret = 0;
|
|
+
|
|
+ /*
|
|
+ * If this image is for a crash kernel, use the region
|
|
+ * the primary kernel has already reserved for us.
|
|
+ */
|
|
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
|
|
+ ret = get_crash_kernel_load_range((uint64_t *) &start,
|
|
+ (uint64_t *) &end);
|
|
+ if (!ret) {
|
|
+ start = _ALIGN_UP(start, align);
|
|
+
|
|
+ if (end > start && ((end - start) >= size)) {
|
|
+ *addr = start;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return -EFBIG;
|
|
+ } else
|
|
+ return ENOCRASHKERNEL;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < info->memory_ranges; i++) {
|
|
+ if (info->memory_range[i].type != RANGE_RAM)
|
|
+ continue;
|
|
+
|
|
+ start = info->memory_range[i].start;
|
|
+ end = info->memory_range[i].end;
|
|
+
|
|
+ start = _ALIGN_UP(start, align);
|
|
+
|
|
+ if (end > start && ((end - start) >= size)) {
|
|
+ *addr = start;
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return -EFBIG;
|
|
+}
|
|
+
|
|
int load_extra_segments(struct kexec_info *info, uint64_t kernel_base,
|
|
uint64_t kernel_size, uint64_t max_addr)
|
|
{
|
|
diff --git a/kexec/arch/riscv/kexec-riscv.h b/kexec/arch/riscv/kexec-riscv.h
|
|
index f136c7ea..61809929 100644
|
|
--- a/kexec/arch/riscv/kexec-riscv.h
|
|
+++ b/kexec/arch/riscv/kexec-riscv.h
|
|
@@ -4,6 +4,17 @@
|
|
* Nick Kossifidis <mick@ics.forth.gr>
|
|
*/
|
|
|
|
+/*
|
|
+ * Kernel should be aligned to the nearest
|
|
+ * hugepage (2MB for RV64, 4MB for RV32).
|
|
+ */
|
|
+
|
|
+#if __riscv_xlen == 64
|
|
+#define KERNEL_ALIGN 0x200000
|
|
+#else
|
|
+#define KERNEL_ALIGN 0x400000
|
|
+#endif
|
|
+
|
|
struct fdt_image {
|
|
char *buf;
|
|
off_t size;
|
|
@@ -26,6 +37,8 @@ int load_elfcorehdr(struct kexec_info *info);
|
|
int prepare_kexec_file_options(struct kexec_info *info);
|
|
int load_extra_segments(struct kexec_info *info, uint64_t kernel_base,
|
|
uint64_t kernel_size, uint64_t max_addr);
|
|
+int riscv_find_pbase(struct kexec_info *info, off_t *addr,
|
|
+ off_t size, off_t align);
|
|
|
|
int elf_riscv_probe(const char *buf, off_t len);
|
|
void elf_riscv_usage(void);
|