summaryrefslogtreecommitdiffstats
path: root/kernel/kexec.c
diff options
context:
space:
mode:
authorMinfei Huang <mnfhuang@gmail.com>2016-05-23 19:24:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-23 20:04:14 -0400
commit0eea08678ebe9f7d8ef98fed974a5bf1a0dd2dd2 (patch)
tree24894ffc23a22f6f40a1f418811c17f73a15df10 /kernel/kexec.c
parent917a35605f09c0d16aeb2e92c7fbff562e19a116 (diff)
kexec: do a cleanup for function kexec_load
There are a lof of work to be done in function kexec_load, not only for allocating structs and loading initram, but also for some misc. To make it more clear, wrap a new function do_kexec_load which is used to allocate structs and load initram. And the pre-work will be done in kexec_load. Signed-off-by: Minfei Huang <mnfhuang@gmail.com> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Xunlei Pang <xlpang@redhat.com> Cc: Baoquan He <bhe@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/kexec.c')
-rw-r--r--kernel/kexec.c125
1 files changed, 69 insertions, 56 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 4b49aa71304f..b73dc211fcfd 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -103,6 +103,74 @@ out_free_image:
103 return ret; 103 return ret;
104} 104}
105 105
106static int do_kexec_load(unsigned long entry, unsigned long nr_segments,
107 struct kexec_segment __user *segments, unsigned long flags)
108{
109 struct kimage **dest_image, *image;
110 unsigned long i;
111 int ret;
112
113 if (flags & KEXEC_ON_CRASH) {
114 dest_image = &kexec_crash_image;
115 if (kexec_crash_image)
116 arch_kexec_unprotect_crashkres();
117 } else {
118 dest_image = &kexec_image;
119 }
120
121 if (nr_segments == 0) {
122 /* Uninstall image */
123 kimage_free(xchg(dest_image, NULL));
124 return 0;
125 }
126 if (flags & KEXEC_ON_CRASH) {
127 /*
128 * Loading another kernel to switch to if this one
129 * crashes. Free any current crash dump kernel before
130 * we corrupt it.
131 */
132 kimage_free(xchg(&kexec_crash_image, NULL));
133 }
134
135 ret = kimage_alloc_init(&image, entry, nr_segments, segments, flags);
136 if (ret)
137 return ret;
138
139 if (flags & KEXEC_ON_CRASH)
140 crash_map_reserved_pages();
141
142 if (flags & KEXEC_PRESERVE_CONTEXT)
143 image->preserve_context = 1;
144
145 ret = machine_kexec_prepare(image);
146 if (ret)
147 goto out;
148
149 for (i = 0; i < nr_segments; i++) {
150 ret = kimage_load_segment(image, &image->segment[i]);
151 if (ret)
152 goto out;
153 }
154
155 kimage_terminate(image);
156
157 /* Install the new kernel and uninstall the old */
158 image = xchg(dest_image, image);
159
160out:
161 if ((flags & KEXEC_ON_CRASH) && kexec_crash_image)
162 arch_kexec_protect_crashkres();
163
164 /*
165 * Once the reserved memory is mapped, we should unmap this memory
166 * before returning
167 */
168 if (flags & KEXEC_ON_CRASH)
169 crash_unmap_reserved_pages();
170 kimage_free(image);
171 return ret;
172}
173
106/* 174/*
107 * Exec Kernel system call: for obvious reasons only root may call it. 175 * Exec Kernel system call: for obvious reasons only root may call it.
108 * 176 *
@@ -127,7 +195,6 @@ out_free_image:
127SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, 195SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
128 struct kexec_segment __user *, segments, unsigned long, flags) 196 struct kexec_segment __user *, segments, unsigned long, flags)
129{ 197{
130 struct kimage **dest_image, *image;
131 int result; 198 int result;
132 199
133 /* We only trust the superuser with rebooting the system. */ 200 /* We only trust the superuser with rebooting the system. */
@@ -152,9 +219,6 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
152 if (nr_segments > KEXEC_SEGMENT_MAX) 219 if (nr_segments > KEXEC_SEGMENT_MAX)
153 return -EINVAL; 220 return -EINVAL;
154 221
155 image = NULL;
156 result = 0;
157
158 /* Because we write directly to the reserved memory 222 /* Because we write directly to the reserved memory
159 * region when loading crash kernels we need a mutex here to 223 * region when loading crash kernels we need a mutex here to
160 * prevent multiple crash kernels from attempting to load 224 * prevent multiple crash kernels from attempting to load
@@ -166,63 +230,12 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
166 if (!mutex_trylock(&kexec_mutex)) 230 if (!mutex_trylock(&kexec_mutex))
167 return -EBUSY; 231 return -EBUSY;
168 232
169 dest_image = &kexec_image; 233 result = do_kexec_load(entry, nr_segments, segments, flags);
170 if (flags & KEXEC_ON_CRASH) {
171 dest_image = &kexec_crash_image;
172 if (kexec_crash_image)
173 arch_kexec_unprotect_crashkres();
174 }
175
176 if (nr_segments > 0) {
177 unsigned long i;
178
179 if (flags & KEXEC_ON_CRASH) {
180 /*
181 * Loading another kernel to switch to if this one
182 * crashes. Free any current crash dump kernel before
183 * we corrupt it.
184 */
185
186 kimage_free(xchg(&kexec_crash_image, NULL));
187 result = kimage_alloc_init(&image, entry, nr_segments,
188 segments, flags);
189 crash_map_reserved_pages();
190 } else {
191 /* Loading another kernel to reboot into. */
192
193 result = kimage_alloc_init(&image, entry, nr_segments,
194 segments, flags);
195 }
196 if (result)
197 goto unmap_page;
198
199 if (flags & KEXEC_PRESERVE_CONTEXT)
200 image->preserve_context = 1;
201 result = machine_kexec_prepare(image);
202 if (result)
203 goto unmap_page;
204
205 for (i = 0; i < nr_segments; i++) {
206 result = kimage_load_segment(image, &image->segment[i]);
207 if (result)
208 goto unmap_page;
209 }
210 kimage_terminate(image);
211unmap_page:
212 if (flags & KEXEC_ON_CRASH)
213 crash_unmap_reserved_pages();
214 if (result)
215 goto out;
216 }
217 /* Install the new kernel, and Uninstall the old */
218 image = xchg(dest_image, image);
219 234
220out:
221 if ((flags & KEXEC_ON_CRASH) && kexec_crash_image) 235 if ((flags & KEXEC_ON_CRASH) && kexec_crash_image)
222 arch_kexec_protect_crashkres(); 236 arch_kexec_protect_crashkres();
223 237
224 mutex_unlock(&kexec_mutex); 238 mutex_unlock(&kexec_mutex);
225 kimage_free(image);
226 239
227 return result; 240 return result;
228} 241}