diff options
Diffstat (limited to 'kernel/kexec.c')
| -rw-r--r-- | kernel/kexec.c | 77 |
1 files changed, 40 insertions, 37 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c index c8380ad203bc..6748688813d0 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
| @@ -125,8 +125,8 @@ static struct page *kimage_alloc_page(struct kimage *image, | |||
| 125 | unsigned long dest); | 125 | unsigned long dest); |
| 126 | 126 | ||
| 127 | static int do_kimage_alloc(struct kimage **rimage, unsigned long entry, | 127 | static int do_kimage_alloc(struct kimage **rimage, unsigned long entry, |
| 128 | unsigned long nr_segments, | 128 | unsigned long nr_segments, |
| 129 | struct kexec_segment __user *segments) | 129 | struct kexec_segment __user *segments) |
| 130 | { | 130 | { |
| 131 | size_t segment_bytes; | 131 | size_t segment_bytes; |
| 132 | struct kimage *image; | 132 | struct kimage *image; |
| @@ -257,13 +257,13 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, | |||
| 257 | image->control_code_page = kimage_alloc_control_pages(image, | 257 | image->control_code_page = kimage_alloc_control_pages(image, |
| 258 | get_order(KEXEC_CONTROL_PAGE_SIZE)); | 258 | get_order(KEXEC_CONTROL_PAGE_SIZE)); |
| 259 | if (!image->control_code_page) { | 259 | if (!image->control_code_page) { |
| 260 | printk(KERN_ERR "Could not allocate control_code_buffer\n"); | 260 | pr_err("Could not allocate control_code_buffer\n"); |
| 261 | goto out_free; | 261 | goto out_free; |
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | image->swap_page = kimage_alloc_control_pages(image, 0); | 264 | image->swap_page = kimage_alloc_control_pages(image, 0); |
| 265 | if (!image->swap_page) { | 265 | if (!image->swap_page) { |
| 266 | printk(KERN_ERR "Could not allocate swap buffer\n"); | 266 | pr_err("Could not allocate swap buffer\n"); |
| 267 | goto out_free; | 267 | goto out_free; |
| 268 | } | 268 | } |
| 269 | 269 | ||
| @@ -332,7 +332,7 @@ static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry, | |||
| 332 | image->control_code_page = kimage_alloc_control_pages(image, | 332 | image->control_code_page = kimage_alloc_control_pages(image, |
| 333 | get_order(KEXEC_CONTROL_PAGE_SIZE)); | 333 | get_order(KEXEC_CONTROL_PAGE_SIZE)); |
| 334 | if (!image->control_code_page) { | 334 | if (!image->control_code_page) { |
| 335 | printk(KERN_ERR "Could not allocate control_code_buffer\n"); | 335 | pr_err("Could not allocate control_code_buffer\n"); |
| 336 | goto out_free; | 336 | goto out_free; |
| 337 | } | 337 | } |
| 338 | 338 | ||
| @@ -621,8 +621,8 @@ static void kimage_terminate(struct kimage *image) | |||
| 621 | 621 | ||
| 622 | #define for_each_kimage_entry(image, ptr, entry) \ | 622 | #define for_each_kimage_entry(image, ptr, entry) \ |
| 623 | for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \ | 623 | for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \ |
| 624 | ptr = (entry & IND_INDIRECTION)? \ | 624 | ptr = (entry & IND_INDIRECTION) ? \ |
| 625 | phys_to_virt((entry & PAGE_MASK)): ptr +1) | 625 | phys_to_virt((entry & PAGE_MASK)) : ptr + 1) |
| 626 | 626 | ||
| 627 | static void kimage_free_entry(kimage_entry_t entry) | 627 | static void kimage_free_entry(kimage_entry_t entry) |
| 628 | { | 628 | { |
| @@ -650,8 +650,7 @@ static void kimage_free(struct kimage *image) | |||
| 650 | * done with it. | 650 | * done with it. |
| 651 | */ | 651 | */ |
| 652 | ind = entry; | 652 | ind = entry; |
| 653 | } | 653 | } else if (entry & IND_SOURCE) |
| 654 | else if (entry & IND_SOURCE) | ||
| 655 | kimage_free_entry(entry); | 654 | kimage_free_entry(entry); |
| 656 | } | 655 | } |
| 657 | /* Free the final indirection page */ | 656 | /* Free the final indirection page */ |
| @@ -774,8 +773,7 @@ static struct page *kimage_alloc_page(struct kimage *image, | |||
| 774 | addr = old_addr; | 773 | addr = old_addr; |
| 775 | page = old_page; | 774 | page = old_page; |
| 776 | break; | 775 | break; |
| 777 | } | 776 | } else { |
| 778 | else { | ||
| 779 | /* Place the page on the destination list I | 777 | /* Place the page on the destination list I |
| 780 | * will use it later. | 778 | * will use it later. |
| 781 | */ | 779 | */ |
| @@ -1059,7 +1057,7 @@ COMPAT_SYSCALL_DEFINE4(kexec_load, compat_ulong_t, entry, | |||
| 1059 | return -EINVAL; | 1057 | return -EINVAL; |
| 1060 | 1058 | ||
| 1061 | ksegments = compat_alloc_user_space(nr_segments * sizeof(out)); | 1059 | ksegments = compat_alloc_user_space(nr_segments * sizeof(out)); |
| 1062 | for (i=0; i < nr_segments; i++) { | 1060 | for (i = 0; i < nr_segments; i++) { |
| 1063 | result = copy_from_user(&in, &segments[i], sizeof(in)); | 1061 | result = copy_from_user(&in, &segments[i], sizeof(in)); |
| 1064 | if (result) | 1062 | if (result) |
| 1065 | return -EFAULT; | 1063 | return -EFAULT; |
| @@ -1214,14 +1212,14 @@ void crash_save_cpu(struct pt_regs *regs, int cpu) | |||
| 1214 | * squirrelled away. ELF notes happen to provide | 1212 | * squirrelled away. ELF notes happen to provide |
| 1215 | * all of that, so there is no need to invent something new. | 1213 | * all of that, so there is no need to invent something new. |
| 1216 | */ | 1214 | */ |
| 1217 | buf = (u32*)per_cpu_ptr(crash_notes, cpu); | 1215 | buf = (u32 *)per_cpu_ptr(crash_notes, cpu); |
| 1218 | if (!buf) | 1216 | if (!buf) |
| 1219 | return; | 1217 | return; |
| 1220 | memset(&prstatus, 0, sizeof(prstatus)); | 1218 | memset(&prstatus, 0, sizeof(prstatus)); |
| 1221 | prstatus.pr_pid = current->pid; | 1219 | prstatus.pr_pid = current->pid; |
| 1222 | elf_core_copy_kernel_regs(&prstatus.pr_reg, regs); | 1220 | elf_core_copy_kernel_regs(&prstatus.pr_reg, regs); |
| 1223 | buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS, | 1221 | buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS, |
| 1224 | &prstatus, sizeof(prstatus)); | 1222 | &prstatus, sizeof(prstatus)); |
| 1225 | final_note(buf); | 1223 | final_note(buf); |
| 1226 | } | 1224 | } |
| 1227 | 1225 | ||
| @@ -1230,8 +1228,7 @@ static int __init crash_notes_memory_init(void) | |||
| 1230 | /* Allocate memory for saving cpu registers. */ | 1228 | /* Allocate memory for saving cpu registers. */ |
| 1231 | crash_notes = alloc_percpu(note_buf_t); | 1229 | crash_notes = alloc_percpu(note_buf_t); |
| 1232 | if (!crash_notes) { | 1230 | if (!crash_notes) { |
| 1233 | printk("Kexec: Memory allocation for saving cpu register" | 1231 | pr_warn("Kexec: Memory allocation for saving cpu register states failed\n"); |
| 1234 | " states failed\n"); | ||
| 1235 | return -ENOMEM; | 1232 | return -ENOMEM; |
| 1236 | } | 1233 | } |
| 1237 | return 0; | 1234 | return 0; |
| @@ -1253,10 +1250,10 @@ subsys_initcall(crash_notes_memory_init); | |||
| 1253 | * | 1250 | * |
| 1254 | * The function returns 0 on success and -EINVAL on failure. | 1251 | * The function returns 0 on success and -EINVAL on failure. |
| 1255 | */ | 1252 | */ |
| 1256 | static int __init parse_crashkernel_mem(char *cmdline, | 1253 | static int __init parse_crashkernel_mem(char *cmdline, |
| 1257 | unsigned long long system_ram, | 1254 | unsigned long long system_ram, |
| 1258 | unsigned long long *crash_size, | 1255 | unsigned long long *crash_size, |
| 1259 | unsigned long long *crash_base) | 1256 | unsigned long long *crash_base) |
| 1260 | { | 1257 | { |
| 1261 | char *cur = cmdline, *tmp; | 1258 | char *cur = cmdline, *tmp; |
| 1262 | 1259 | ||
| @@ -1267,12 +1264,12 @@ static int __init parse_crashkernel_mem(char *cmdline, | |||
| 1267 | /* get the start of the range */ | 1264 | /* get the start of the range */ |
| 1268 | start = memparse(cur, &tmp); | 1265 | start = memparse(cur, &tmp); |
| 1269 | if (cur == tmp) { | 1266 | if (cur == tmp) { |
| 1270 | pr_warning("crashkernel: Memory value expected\n"); | 1267 | pr_warn("crashkernel: Memory value expected\n"); |
| 1271 | return -EINVAL; | 1268 | return -EINVAL; |
| 1272 | } | 1269 | } |
| 1273 | cur = tmp; | 1270 | cur = tmp; |
| 1274 | if (*cur != '-') { | 1271 | if (*cur != '-') { |
| 1275 | pr_warning("crashkernel: '-' expected\n"); | 1272 | pr_warn("crashkernel: '-' expected\n"); |
| 1276 | return -EINVAL; | 1273 | return -EINVAL; |
| 1277 | } | 1274 | } |
| 1278 | cur++; | 1275 | cur++; |
| @@ -1281,31 +1278,30 @@ static int __init parse_crashkernel_mem(char *cmdline, | |||
| 1281 | if (*cur != ':') { | 1278 | if (*cur != ':') { |
| 1282 | end = memparse(cur, &tmp); | 1279 | end = memparse(cur, &tmp); |
| 1283 | if (cur == tmp) { | 1280 | if (cur == tmp) { |
| 1284 | pr_warning("crashkernel: Memory " | 1281 | pr_warn("crashkernel: Memory value expected\n"); |
| 1285 | "value expected\n"); | ||
| 1286 | return -EINVAL; | 1282 | return -EINVAL; |
| 1287 | } | 1283 | } |
| 1288 | cur = tmp; | 1284 | cur = tmp; |
| 1289 | if (end <= start) { | 1285 | if (end <= start) { |
| 1290 | pr_warning("crashkernel: end <= start\n"); | 1286 | pr_warn("crashkernel: end <= start\n"); |
| 1291 | return -EINVAL; | 1287 | return -EINVAL; |
| 1292 | } | 1288 | } |
| 1293 | } | 1289 | } |
| 1294 | 1290 | ||
| 1295 | if (*cur != ':') { | 1291 | if (*cur != ':') { |
| 1296 | pr_warning("crashkernel: ':' expected\n"); | 1292 | pr_warn("crashkernel: ':' expected\n"); |
| 1297 | return -EINVAL; | 1293 | return -EINVAL; |
| 1298 | } | 1294 | } |
| 1299 | cur++; | 1295 | cur++; |
| 1300 | 1296 | ||
| 1301 | size = memparse(cur, &tmp); | 1297 | size = memparse(cur, &tmp); |
| 1302 | if (cur == tmp) { | 1298 | if (cur == tmp) { |
| 1303 | pr_warning("Memory value expected\n"); | 1299 | pr_warn("Memory value expected\n"); |
| 1304 | return -EINVAL; | 1300 | return -EINVAL; |
| 1305 | } | 1301 | } |
| 1306 | cur = tmp; | 1302 | cur = tmp; |
| 1307 | if (size >= system_ram) { | 1303 | if (size >= system_ram) { |
| 1308 | pr_warning("crashkernel: invalid size\n"); | 1304 | pr_warn("crashkernel: invalid size\n"); |
| 1309 | return -EINVAL; | 1305 | return -EINVAL; |
| 1310 | } | 1306 | } |
| 1311 | 1307 | ||
| @@ -1323,8 +1319,7 @@ static int __init parse_crashkernel_mem(char *cmdline, | |||
| 1323 | cur++; | 1319 | cur++; |
| 1324 | *crash_base = memparse(cur, &tmp); | 1320 | *crash_base = memparse(cur, &tmp); |
| 1325 | if (cur == tmp) { | 1321 | if (cur == tmp) { |
| 1326 | pr_warning("Memory value expected " | 1322 | pr_warn("Memory value expected after '@'\n"); |
| 1327 | "after '@'\n"); | ||
| 1328 | return -EINVAL; | 1323 | return -EINVAL; |
| 1329 | } | 1324 | } |
| 1330 | } | 1325 | } |
| @@ -1336,26 +1331,26 @@ static int __init parse_crashkernel_mem(char *cmdline, | |||
| 1336 | /* | 1331 | /* |
| 1337 | * That function parses "simple" (old) crashkernel command lines like | 1332 | * That function parses "simple" (old) crashkernel command lines like |
| 1338 | * | 1333 | * |
| 1339 | * crashkernel=size[@offset] | 1334 | * crashkernel=size[@offset] |
| 1340 | * | 1335 | * |
| 1341 | * It returns 0 on success and -EINVAL on failure. | 1336 | * It returns 0 on success and -EINVAL on failure. |
| 1342 | */ | 1337 | */ |
| 1343 | static int __init parse_crashkernel_simple(char *cmdline, | 1338 | static int __init parse_crashkernel_simple(char *cmdline, |
| 1344 | unsigned long long *crash_size, | 1339 | unsigned long long *crash_size, |
| 1345 | unsigned long long *crash_base) | 1340 | unsigned long long *crash_base) |
| 1346 | { | 1341 | { |
| 1347 | char *cur = cmdline; | 1342 | char *cur = cmdline; |
| 1348 | 1343 | ||
| 1349 | *crash_size = memparse(cmdline, &cur); | 1344 | *crash_size = memparse(cmdline, &cur); |
| 1350 | if (cmdline == cur) { | 1345 | if (cmdline == cur) { |
| 1351 | pr_warning("crashkernel: memory value expected\n"); | 1346 | pr_warn("crashkernel: memory value expected\n"); |
| 1352 | return -EINVAL; | 1347 | return -EINVAL; |
| 1353 | } | 1348 | } |
| 1354 | 1349 | ||
| 1355 | if (*cur == '@') | 1350 | if (*cur == '@') |
| 1356 | *crash_base = memparse(cur+1, &cur); | 1351 | *crash_base = memparse(cur+1, &cur); |
| 1357 | else if (*cur != ' ' && *cur != '\0') { | 1352 | else if (*cur != ' ' && *cur != '\0') { |
| 1358 | pr_warning("crashkernel: unrecognized char\n"); | 1353 | pr_warn("crashkernel: unrecognized char\n"); |
| 1359 | return -EINVAL; | 1354 | return -EINVAL; |
| 1360 | } | 1355 | } |
| 1361 | 1356 | ||
| @@ -1683,7 +1678,15 @@ int kernel_kexec(void) | |||
| 1683 | kexec_in_progress = true; | 1678 | kexec_in_progress = true; |
| 1684 | kernel_restart_prepare(NULL); | 1679 | kernel_restart_prepare(NULL); |
| 1685 | migrate_to_reboot_cpu(); | 1680 | migrate_to_reboot_cpu(); |
| 1686 | printk(KERN_EMERG "Starting new kernel\n"); | 1681 | |
| 1682 | /* | ||
| 1683 | * migrate_to_reboot_cpu() disables CPU hotplug assuming that | ||
| 1684 | * no further code needs to use CPU hotplug (which is true in | ||
| 1685 | * the reboot case). However, the kexec path depends on using | ||
| 1686 | * CPU hotplug again; so re-enable it here. | ||
| 1687 | */ | ||
| 1688 | cpu_hotplug_enable(); | ||
| 1689 | pr_emerg("Starting new kernel\n"); | ||
| 1687 | machine_shutdown(); | 1690 | machine_shutdown(); |
| 1688 | } | 1691 | } |
| 1689 | 1692 | ||
