1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
From 5a302cd06079a285cb24a74c0f60b26866ae4e4d Mon Sep 17 00:00:00 2001
From: snoweay <snoweay@163.com>
Date: Wed, 12 Aug 2020 07:59:06 -0400
Subject: [PATCH] kexec: Quick kexec implementation for arm64
Implement quick kexec on arch/arm64.
Locate kernel segments from reserved memory of range "Quick kexec".
---
kexec/arch/arm64/iomem.h | 1 +
kexec/arch/arm64/kexec-arm64.c | 42 +++++++++++++++++++++++++-----------
kexec/arch/arm64/kexec-image-arm64.c | 11 ++++++++++
3 files changed, 41 insertions(+), 13 deletions(-)
diff --git a/kexec/arch/arm64/iomem.h b/kexec/arch/arm64/iomem.h
index 45d7953..f283f50 100644
--- a/kexec/arch/arm64/iomem.h
+++ b/kexec/arch/arm64/iomem.h
@@ -7,5 +7,6 @@
#define KERNEL_DATA "Kernel data\n"
#define CRASH_KERNEL "Crash kernel\n"
#define IOMEM_RESERVED "reserved\n"
+#define QUICK_KEXEC "Quick kexec\n"
#endif
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 219ec49..8a3bb69 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -99,6 +99,9 @@ uint64_t get_vp_offset(void)
return arm64_mem.vp_offset;
}
+/* Reserved memory for quick kexec. */
+struct memory_range quick_reserved_mem;
+
/**
* arm64_process_image_header - Process the arm64 image header.
*
@@ -627,23 +630,33 @@ on_error:
return result;
}
-unsigned long arm64_locate_kernel_segment(struct kexec_info *info)
+static unsigned long locate_hole_from_range(struct memory_range *range)
{
unsigned long hole;
+ unsigned long hole_end;
- if (info->kexec_flags & KEXEC_ON_CRASH) {
- unsigned long hole_end;
+ hole = (range->start < mem_min ? mem_min : range->start);
+ hole = _ALIGN_UP(hole, MiB(2));
+ hole_end = hole + arm64_mem.text_offset + arm64_mem.image_size;
- hole = (crash_reserved_mem[usablemem_rgns.size - 1].start < mem_min ?
- mem_min : crash_reserved_mem[usablemem_rgns.size - 1].start);
- hole = _ALIGN_UP(hole, MiB(2));
- hole_end = hole + arm64_mem.text_offset + arm64_mem.image_size;
+ if ((hole_end > mem_max) ||
+ (hole_end > range->end)) {
+ dbgprintf("%s: Kexec kernel out of range\n", __func__);
+ hole = ULONG_MAX;
+ }
- if ((hole_end > mem_max) ||
- (hole_end > crash_reserved_mem[usablemem_rgns.size - 1].end)) {
- dbgprintf("%s: Crash kernel out of range\n", __func__);
- hole = ULONG_MAX;
- }
+ return hole;
+}
+
+unsigned long arm64_locate_kernel_segment(struct kexec_info *info)
+{
+ unsigned long hole;
+
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ hole = locate_hole_from_range(
+ &crash_reserved_mem[usablemem_rgns.size - 1]);
+ } else if (info->kexec_flags & KEXEC_QUICK) {
+ hole = locate_hole_from_range(&quick_reserved_mem);
} else {
hole = locate_hole(info,
arm64_mem.text_offset + arm64_mem.image_size,
@@ -709,6 +722,8 @@ int arm64_load_other_segments(struct kexec_info *info,
hole_min = image_base + arm64_mem.image_size;
if (info->kexec_flags & KEXEC_ON_CRASH)
hole_max = crash_reserved_mem[usablemem_rgns.size - 1].end;
+ else if (info->kexec_flags & KEXEC_QUICK)
+ hole_max = quick_reserved_mem.end;
else
hole_max = ULONG_MAX;
@@ -1050,7 +1050,8 @@ static bool to_be_excluded(char *str, unsigned long long start, unsigned long lo
if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) ||
!strncmp(str, KERNEL_CODE, strlen(KERNEL_CODE)) ||
- !strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)))
+ !strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)) ||
+ !strncmp(str, QUICK_KEXEC, strlen(QUICK_KEXEC)))
return false;
else
return true;
diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c
index aa8f2e2..f22db62 100644
--- a/kexec/arch/arm64/kexec-image-arm64.c
+++ b/kexec/arch/arm64/kexec-image-arm64.c
@@ -13,6 +13,9 @@
#include "kexec-arm64.h"
#include "kexec-syscall.h"
#include "arch/options.h"
+#include "iomem.h"
+
+extern struct memory_range quick_reserved_mem;
int image_arm64_probe(const char *kernel_buf, off_t kernel_size)
{
@@ -38,6 +41,7 @@ int image_arm64_load(int argc, char **argv, const char *kernel_buf,
{
const struct arm64_image_header *header;
unsigned long kernel_segment;
+ unsigned long start, end;
int result;
if (info->file_mode) {
@@ -61,6 +65,13 @@ int image_arm64_load(int argc, char **argv, const char *kernel_buf,
return 0;
}
+ if (info->kexec_flags & KEXEC_QUICK)
+ parse_iomem_single(QUICK_KEXEC, &start, &end);
+ dbgprintf("%s: Get Quick kexec reserved mem from 0x%016lx to 0x%016lx\n",
+ __func__, start, end);
+ quick_reserved_mem.start = start;
+ quick_reserved_mem.end = end;
+
header = (const struct arm64_image_header *)(kernel_buf);
if (arm64_process_image_header(header))
--
2.9.5
|