diff options
-rw-r--r-- | arch/powerpc/include/asm/fadump.h | 57 | ||||
-rw-r--r-- | arch/powerpc/kernel/fadump.c | 355 | ||||
-rw-r--r-- | arch/powerpc/kernel/iommu.c | 8 | ||||
-rw-r--r-- | arch/powerpc/mm/hash_utils_64.c | 11 |
4 files changed, 427 insertions, 4 deletions
diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h index 7be25d30d985..bbaf278bdccc 100644 --- a/arch/powerpc/include/asm/fadump.h +++ b/arch/powerpc/include/asm/fadump.h | |||
@@ -48,6 +48,58 @@ | |||
48 | #define FADUMP_HPTE_REGION 0x0002 | 48 | #define FADUMP_HPTE_REGION 0x0002 |
49 | #define FADUMP_REAL_MODE_REGION 0x0011 | 49 | #define FADUMP_REAL_MODE_REGION 0x0011 |
50 | 50 | ||
51 | /* Dump request flag */ | ||
52 | #define FADUMP_REQUEST_FLAG 0x00000001 | ||
53 | |||
54 | /* FAD commands */ | ||
55 | #define FADUMP_REGISTER 1 | ||
56 | #define FADUMP_UNREGISTER 2 | ||
57 | #define FADUMP_INVALIDATE 3 | ||
58 | |||
59 | /* Kernel Dump section info */ | ||
60 | struct fadump_section { | ||
61 | u32 request_flag; | ||
62 | u16 source_data_type; | ||
63 | u16 error_flags; | ||
64 | u64 source_address; | ||
65 | u64 source_len; | ||
66 | u64 bytes_dumped; | ||
67 | u64 destination_address; | ||
68 | }; | ||
69 | |||
70 | /* ibm,configure-kernel-dump header. */ | ||
71 | struct fadump_section_header { | ||
72 | u32 dump_format_version; | ||
73 | u16 dump_num_sections; | ||
74 | u16 dump_status_flag; | ||
75 | u32 offset_first_dump_section; | ||
76 | |||
77 | /* Fields for disk dump option. */ | ||
78 | u32 dd_block_size; | ||
79 | u64 dd_block_offset; | ||
80 | u64 dd_num_blocks; | ||
81 | u32 dd_offset_disk_path; | ||
82 | |||
83 | /* Maximum time allowed to prevent an automatic dump-reboot. */ | ||
84 | u32 max_time_auto; | ||
85 | }; | ||
86 | |||
87 | /* | ||
88 | * Firmware Assisted dump memory structure. This structure is required for | ||
89 | * registering future kernel dump with power firmware through rtas call. | ||
90 | * | ||
91 | * No disk dump option. Hence disk dump path string section is not included. | ||
92 | */ | ||
93 | struct fadump_mem_struct { | ||
94 | struct fadump_section_header header; | ||
95 | |||
96 | /* Kernel dump sections */ | ||
97 | struct fadump_section cpu_state_data; | ||
98 | struct fadump_section hpte_region; | ||
99 | struct fadump_section rmr_region; | ||
100 | }; | ||
101 | |||
102 | /* Firmware-assisted dump configuration details. */ | ||
51 | struct fw_dump { | 103 | struct fw_dump { |
52 | unsigned long cpu_state_data_size; | 104 | unsigned long cpu_state_data_size; |
53 | unsigned long hpte_region_size; | 105 | unsigned long hpte_region_size; |
@@ -62,10 +114,15 @@ struct fw_dump { | |||
62 | unsigned long fadump_enabled:1; | 114 | unsigned long fadump_enabled:1; |
63 | unsigned long fadump_supported:1; | 115 | unsigned long fadump_supported:1; |
64 | unsigned long dump_active:1; | 116 | unsigned long dump_active:1; |
117 | unsigned long dump_registered:1; | ||
65 | }; | 118 | }; |
66 | 119 | ||
67 | extern int early_init_dt_scan_fw_dump(unsigned long node, | 120 | extern int early_init_dt_scan_fw_dump(unsigned long node, |
68 | const char *uname, int depth, void *data); | 121 | const char *uname, int depth, void *data); |
69 | extern int fadump_reserve_mem(void); | 122 | extern int fadump_reserve_mem(void); |
123 | extern int setup_fadump(void); | ||
124 | extern int is_fadump_active(void); | ||
125 | #else /* CONFIG_FA_DUMP */ | ||
126 | static inline int is_fadump_active(void) { return 0; } | ||
70 | #endif | 127 | #endif |
71 | #endif | 128 | #endif |
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index deb276a9ce71..eb8f782afade 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c | |||
@@ -29,6 +29,9 @@ | |||
29 | 29 | ||
30 | #include <linux/string.h> | 30 | #include <linux/string.h> |
31 | #include <linux/memblock.h> | 31 | #include <linux/memblock.h> |
32 | #include <linux/delay.h> | ||
33 | #include <linux/debugfs.h> | ||
34 | #include <linux/seq_file.h> | ||
32 | 35 | ||
33 | #include <asm/page.h> | 36 | #include <asm/page.h> |
34 | #include <asm/prom.h> | 37 | #include <asm/prom.h> |
@@ -36,6 +39,10 @@ | |||
36 | #include <asm/fadump.h> | 39 | #include <asm/fadump.h> |
37 | 40 | ||
38 | static struct fw_dump fw_dump; | 41 | static struct fw_dump fw_dump; |
42 | static struct fadump_mem_struct fdm; | ||
43 | static const struct fadump_mem_struct *fdm_active; | ||
44 | |||
45 | static DEFINE_MUTEX(fadump_mutex); | ||
39 | 46 | ||
40 | /* Scan the Firmware Assisted dump configuration details. */ | 47 | /* Scan the Firmware Assisted dump configuration details. */ |
41 | int __init early_init_dt_scan_fw_dump(unsigned long node, | 48 | int __init early_init_dt_scan_fw_dump(unsigned long node, |
@@ -64,7 +71,8 @@ int __init early_init_dt_scan_fw_dump(unsigned long node, | |||
64 | * The 'ibm,kernel-dump' rtas node is present only if there is | 71 | * The 'ibm,kernel-dump' rtas node is present only if there is |
65 | * dump data waiting for us. | 72 | * dump data waiting for us. |
66 | */ | 73 | */ |
67 | if (of_get_flat_dt_prop(node, "ibm,kernel-dump", NULL)) | 74 | fdm_active = of_get_flat_dt_prop(node, "ibm,kernel-dump", NULL); |
75 | if (fdm_active) | ||
68 | fw_dump.dump_active = 1; | 76 | fw_dump.dump_active = 1; |
69 | 77 | ||
70 | /* Get the sizes required to store dump data for the firmware provided | 78 | /* Get the sizes required to store dump data for the firmware provided |
@@ -98,6 +106,85 @@ int __init early_init_dt_scan_fw_dump(unsigned long node, | |||
98 | return 1; | 106 | return 1; |
99 | } | 107 | } |
100 | 108 | ||
109 | int is_fadump_active(void) | ||
110 | { | ||
111 | return fw_dump.dump_active; | ||
112 | } | ||
113 | |||
114 | /* Print firmware assisted dump configurations for debugging purpose. */ | ||
115 | static void fadump_show_config(void) | ||
116 | { | ||
117 | pr_debug("Support for firmware-assisted dump (fadump): %s\n", | ||
118 | (fw_dump.fadump_supported ? "present" : "no support")); | ||
119 | |||
120 | if (!fw_dump.fadump_supported) | ||
121 | return; | ||
122 | |||
123 | pr_debug("Fadump enabled : %s\n", | ||
124 | (fw_dump.fadump_enabled ? "yes" : "no")); | ||
125 | pr_debug("Dump Active : %s\n", | ||
126 | (fw_dump.dump_active ? "yes" : "no")); | ||
127 | pr_debug("Dump section sizes:\n"); | ||
128 | pr_debug(" CPU state data size: %lx\n", fw_dump.cpu_state_data_size); | ||
129 | pr_debug(" HPTE region size : %lx\n", fw_dump.hpte_region_size); | ||
130 | pr_debug("Boot memory size : %lx\n", fw_dump.boot_memory_size); | ||
131 | } | ||
132 | |||
133 | static unsigned long init_fadump_mem_struct(struct fadump_mem_struct *fdm, | ||
134 | unsigned long addr) | ||
135 | { | ||
136 | if (!fdm) | ||
137 | return 0; | ||
138 | |||
139 | memset(fdm, 0, sizeof(struct fadump_mem_struct)); | ||
140 | addr = addr & PAGE_MASK; | ||
141 | |||
142 | fdm->header.dump_format_version = 0x00000001; | ||
143 | fdm->header.dump_num_sections = 3; | ||
144 | fdm->header.dump_status_flag = 0; | ||
145 | fdm->header.offset_first_dump_section = | ||
146 | (u32)offsetof(struct fadump_mem_struct, cpu_state_data); | ||
147 | |||
148 | /* | ||
149 | * Fields for disk dump option. | ||
150 | * We are not using disk dump option, hence set these fields to 0. | ||
151 | */ | ||
152 | fdm->header.dd_block_size = 0; | ||
153 | fdm->header.dd_block_offset = 0; | ||
154 | fdm->header.dd_num_blocks = 0; | ||
155 | fdm->header.dd_offset_disk_path = 0; | ||
156 | |||
157 | /* set 0 to disable an automatic dump-reboot. */ | ||
158 | fdm->header.max_time_auto = 0; | ||
159 | |||
160 | /* Kernel dump sections */ | ||
161 | /* cpu state data section. */ | ||
162 | fdm->cpu_state_data.request_flag = FADUMP_REQUEST_FLAG; | ||
163 | fdm->cpu_state_data.source_data_type = FADUMP_CPU_STATE_DATA; | ||
164 | fdm->cpu_state_data.source_address = 0; | ||
165 | fdm->cpu_state_data.source_len = fw_dump.cpu_state_data_size; | ||
166 | fdm->cpu_state_data.destination_address = addr; | ||
167 | addr += fw_dump.cpu_state_data_size; | ||
168 | |||
169 | /* hpte region section */ | ||
170 | fdm->hpte_region.request_flag = FADUMP_REQUEST_FLAG; | ||
171 | fdm->hpte_region.source_data_type = FADUMP_HPTE_REGION; | ||
172 | fdm->hpte_region.source_address = 0; | ||
173 | fdm->hpte_region.source_len = fw_dump.hpte_region_size; | ||
174 | fdm->hpte_region.destination_address = addr; | ||
175 | addr += fw_dump.hpte_region_size; | ||
176 | |||
177 | /* RMA region section */ | ||
178 | fdm->rmr_region.request_flag = FADUMP_REQUEST_FLAG; | ||
179 | fdm->rmr_region.source_data_type = FADUMP_REAL_MODE_REGION; | ||
180 | fdm->rmr_region.source_address = RMA_START; | ||
181 | fdm->rmr_region.source_len = fw_dump.boot_memory_size; | ||
182 | fdm->rmr_region.destination_address = addr; | ||
183 | addr += fw_dump.boot_memory_size; | ||
184 | |||
185 | return addr; | ||
186 | } | ||
187 | |||
101 | /** | 188 | /** |
102 | * fadump_calculate_reserve_size(): reserve variable boot area 5% of System RAM | 189 | * fadump_calculate_reserve_size(): reserve variable boot area 5% of System RAM |
103 | * | 190 | * |
@@ -166,8 +253,15 @@ int __init fadump_reserve_mem(void) | |||
166 | fw_dump.fadump_enabled = 0; | 253 | fw_dump.fadump_enabled = 0; |
167 | return 0; | 254 | return 0; |
168 | } | 255 | } |
169 | /* Initialize boot memory size */ | 256 | /* |
170 | fw_dump.boot_memory_size = fadump_calculate_reserve_size(); | 257 | * Initialize boot memory size |
258 | * If dump is active then we have already calculated the size during | ||
259 | * first kernel. | ||
260 | */ | ||
261 | if (fdm_active) | ||
262 | fw_dump.boot_memory_size = fdm_active->rmr_region.source_len; | ||
263 | else | ||
264 | fw_dump.boot_memory_size = fadump_calculate_reserve_size(); | ||
171 | 265 | ||
172 | /* | 266 | /* |
173 | * Calculate the memory boundary. | 267 | * Calculate the memory boundary. |
@@ -244,3 +338,258 @@ static int __init early_fadump_reserve_mem(char *p) | |||
244 | return 0; | 338 | return 0; |
245 | } | 339 | } |
246 | early_param("fadump_reserve_mem", early_fadump_reserve_mem); | 340 | early_param("fadump_reserve_mem", early_fadump_reserve_mem); |
341 | |||
342 | static void register_fw_dump(struct fadump_mem_struct *fdm) | ||
343 | { | ||
344 | int rc; | ||
345 | unsigned int wait_time; | ||
346 | |||
347 | pr_debug("Registering for firmware-assisted kernel dump...\n"); | ||
348 | |||
349 | /* TODO: Add upper time limit for the delay */ | ||
350 | do { | ||
351 | rc = rtas_call(fw_dump.ibm_configure_kernel_dump, 3, 1, NULL, | ||
352 | FADUMP_REGISTER, fdm, | ||
353 | sizeof(struct fadump_mem_struct)); | ||
354 | |||
355 | wait_time = rtas_busy_delay_time(rc); | ||
356 | if (wait_time) | ||
357 | mdelay(wait_time); | ||
358 | |||
359 | } while (wait_time); | ||
360 | |||
361 | switch (rc) { | ||
362 | case -1: | ||
363 | printk(KERN_ERR "Failed to register firmware-assisted kernel" | ||
364 | " dump. Hardware Error(%d).\n", rc); | ||
365 | break; | ||
366 | case -3: | ||
367 | printk(KERN_ERR "Failed to register firmware-assisted kernel" | ||
368 | " dump. Parameter Error(%d).\n", rc); | ||
369 | break; | ||
370 | case -9: | ||
371 | printk(KERN_ERR "firmware-assisted kernel dump is already " | ||
372 | " registered."); | ||
373 | fw_dump.dump_registered = 1; | ||
374 | break; | ||
375 | case 0: | ||
376 | printk(KERN_INFO "firmware-assisted kernel dump registration" | ||
377 | " is successful\n"); | ||
378 | fw_dump.dump_registered = 1; | ||
379 | break; | ||
380 | } | ||
381 | } | ||
382 | |||
383 | static void register_fadump(void) | ||
384 | { | ||
385 | /* | ||
386 | * If no memory is reserved then we can not register for firmware- | ||
387 | * assisted dump. | ||
388 | */ | ||
389 | if (!fw_dump.reserve_dump_area_size) | ||
390 | return; | ||
391 | |||
392 | /* register the future kernel dump with firmware. */ | ||
393 | register_fw_dump(&fdm); | ||
394 | } | ||
395 | |||
396 | static int fadump_unregister_dump(struct fadump_mem_struct *fdm) | ||
397 | { | ||
398 | int rc = 0; | ||
399 | unsigned int wait_time; | ||
400 | |||
401 | pr_debug("Un-register firmware-assisted dump\n"); | ||
402 | |||
403 | /* TODO: Add upper time limit for the delay */ | ||
404 | do { | ||
405 | rc = rtas_call(fw_dump.ibm_configure_kernel_dump, 3, 1, NULL, | ||
406 | FADUMP_UNREGISTER, fdm, | ||
407 | sizeof(struct fadump_mem_struct)); | ||
408 | |||
409 | wait_time = rtas_busy_delay_time(rc); | ||
410 | if (wait_time) | ||
411 | mdelay(wait_time); | ||
412 | } while (wait_time); | ||
413 | |||
414 | if (rc) { | ||
415 | printk(KERN_ERR "Failed to un-register firmware-assisted dump." | ||
416 | " unexpected error(%d).\n", rc); | ||
417 | return rc; | ||
418 | } | ||
419 | fw_dump.dump_registered = 0; | ||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static ssize_t fadump_enabled_show(struct kobject *kobj, | ||
424 | struct kobj_attribute *attr, | ||
425 | char *buf) | ||
426 | { | ||
427 | return sprintf(buf, "%d\n", fw_dump.fadump_enabled); | ||
428 | } | ||
429 | |||
430 | static ssize_t fadump_register_show(struct kobject *kobj, | ||
431 | struct kobj_attribute *attr, | ||
432 | char *buf) | ||
433 | { | ||
434 | return sprintf(buf, "%d\n", fw_dump.dump_registered); | ||
435 | } | ||
436 | |||
437 | static ssize_t fadump_register_store(struct kobject *kobj, | ||
438 | struct kobj_attribute *attr, | ||
439 | const char *buf, size_t count) | ||
440 | { | ||
441 | int ret = 0; | ||
442 | |||
443 | if (!fw_dump.fadump_enabled || fdm_active) | ||
444 | return -EPERM; | ||
445 | |||
446 | mutex_lock(&fadump_mutex); | ||
447 | |||
448 | switch (buf[0]) { | ||
449 | case '0': | ||
450 | if (fw_dump.dump_registered == 0) { | ||
451 | ret = -EINVAL; | ||
452 | goto unlock_out; | ||
453 | } | ||
454 | /* Un-register Firmware-assisted dump */ | ||
455 | fadump_unregister_dump(&fdm); | ||
456 | break; | ||
457 | case '1': | ||
458 | if (fw_dump.dump_registered == 1) { | ||
459 | ret = -EINVAL; | ||
460 | goto unlock_out; | ||
461 | } | ||
462 | /* Register Firmware-assisted dump */ | ||
463 | register_fadump(); | ||
464 | break; | ||
465 | default: | ||
466 | ret = -EINVAL; | ||
467 | break; | ||
468 | } | ||
469 | |||
470 | unlock_out: | ||
471 | mutex_unlock(&fadump_mutex); | ||
472 | return ret < 0 ? ret : count; | ||
473 | } | ||
474 | |||
475 | static int fadump_region_show(struct seq_file *m, void *private) | ||
476 | { | ||
477 | const struct fadump_mem_struct *fdm_ptr; | ||
478 | |||
479 | if (!fw_dump.fadump_enabled) | ||
480 | return 0; | ||
481 | |||
482 | if (fdm_active) | ||
483 | fdm_ptr = fdm_active; | ||
484 | else | ||
485 | fdm_ptr = &fdm; | ||
486 | |||
487 | seq_printf(m, | ||
488 | "CPU : [%#016llx-%#016llx] %#llx bytes, " | ||
489 | "Dumped: %#llx\n", | ||
490 | fdm_ptr->cpu_state_data.destination_address, | ||
491 | fdm_ptr->cpu_state_data.destination_address + | ||
492 | fdm_ptr->cpu_state_data.source_len - 1, | ||
493 | fdm_ptr->cpu_state_data.source_len, | ||
494 | fdm_ptr->cpu_state_data.bytes_dumped); | ||
495 | seq_printf(m, | ||
496 | "HPTE: [%#016llx-%#016llx] %#llx bytes, " | ||
497 | "Dumped: %#llx\n", | ||
498 | fdm_ptr->hpte_region.destination_address, | ||
499 | fdm_ptr->hpte_region.destination_address + | ||
500 | fdm_ptr->hpte_region.source_len - 1, | ||
501 | fdm_ptr->hpte_region.source_len, | ||
502 | fdm_ptr->hpte_region.bytes_dumped); | ||
503 | seq_printf(m, | ||
504 | "DUMP: [%#016llx-%#016llx] %#llx bytes, " | ||
505 | "Dumped: %#llx\n", | ||
506 | fdm_ptr->rmr_region.destination_address, | ||
507 | fdm_ptr->rmr_region.destination_address + | ||
508 | fdm_ptr->rmr_region.source_len - 1, | ||
509 | fdm_ptr->rmr_region.source_len, | ||
510 | fdm_ptr->rmr_region.bytes_dumped); | ||
511 | |||
512 | if (!fdm_active || | ||
513 | (fw_dump.reserve_dump_area_start == | ||
514 | fdm_ptr->cpu_state_data.destination_address)) | ||
515 | return 0; | ||
516 | |||
517 | /* Dump is active. Show reserved memory region. */ | ||
518 | seq_printf(m, | ||
519 | " : [%#016llx-%#016llx] %#llx bytes, " | ||
520 | "Dumped: %#llx\n", | ||
521 | (unsigned long long)fw_dump.reserve_dump_area_start, | ||
522 | fdm_ptr->cpu_state_data.destination_address - 1, | ||
523 | fdm_ptr->cpu_state_data.destination_address - | ||
524 | fw_dump.reserve_dump_area_start, | ||
525 | fdm_ptr->cpu_state_data.destination_address - | ||
526 | fw_dump.reserve_dump_area_start); | ||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | static struct kobj_attribute fadump_attr = __ATTR(fadump_enabled, | ||
531 | 0444, fadump_enabled_show, | ||
532 | NULL); | ||
533 | static struct kobj_attribute fadump_register_attr = __ATTR(fadump_registered, | ||
534 | 0644, fadump_register_show, | ||
535 | fadump_register_store); | ||
536 | |||
537 | static int fadump_region_open(struct inode *inode, struct file *file) | ||
538 | { | ||
539 | return single_open(file, fadump_region_show, inode->i_private); | ||
540 | } | ||
541 | |||
542 | static const struct file_operations fadump_region_fops = { | ||
543 | .open = fadump_region_open, | ||
544 | .read = seq_read, | ||
545 | .llseek = seq_lseek, | ||
546 | .release = single_release, | ||
547 | }; | ||
548 | |||
549 | static void fadump_init_files(void) | ||
550 | { | ||
551 | struct dentry *debugfs_file; | ||
552 | int rc = 0; | ||
553 | |||
554 | rc = sysfs_create_file(kernel_kobj, &fadump_attr.attr); | ||
555 | if (rc) | ||
556 | printk(KERN_ERR "fadump: unable to create sysfs file" | ||
557 | " fadump_enabled (%d)\n", rc); | ||
558 | |||
559 | rc = sysfs_create_file(kernel_kobj, &fadump_register_attr.attr); | ||
560 | if (rc) | ||
561 | printk(KERN_ERR "fadump: unable to create sysfs file" | ||
562 | " fadump_registered (%d)\n", rc); | ||
563 | |||
564 | debugfs_file = debugfs_create_file("fadump_region", 0444, | ||
565 | powerpc_debugfs_root, NULL, | ||
566 | &fadump_region_fops); | ||
567 | if (!debugfs_file) | ||
568 | printk(KERN_ERR "fadump: unable to create debugfs file" | ||
569 | " fadump_region\n"); | ||
570 | return; | ||
571 | } | ||
572 | |||
573 | /* | ||
574 | * Prepare for firmware-assisted dump. | ||
575 | */ | ||
576 | int __init setup_fadump(void) | ||
577 | { | ||
578 | if (!fw_dump.fadump_enabled) | ||
579 | return 0; | ||
580 | |||
581 | if (!fw_dump.fadump_supported) { | ||
582 | printk(KERN_ERR "Firmware-assisted dump is not supported on" | ||
583 | " this hardware\n"); | ||
584 | return 0; | ||
585 | } | ||
586 | |||
587 | fadump_show_config(); | ||
588 | /* Initialize the kernel dump memory structure for FAD registration. */ | ||
589 | if (fw_dump.reserve_dump_area_size) | ||
590 | init_fadump_mem_struct(&fdm, fw_dump.reserve_dump_area_start); | ||
591 | fadump_init_files(); | ||
592 | |||
593 | return 1; | ||
594 | } | ||
595 | subsys_initcall(setup_fadump); | ||
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 0cfcf98aafca..359f078571c7 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <asm/pci-bridge.h> | 39 | #include <asm/pci-bridge.h> |
40 | #include <asm/machdep.h> | 40 | #include <asm/machdep.h> |
41 | #include <asm/kdump.h> | 41 | #include <asm/kdump.h> |
42 | #include <asm/fadump.h> | ||
42 | 43 | ||
43 | #define DBG(...) | 44 | #define DBG(...) |
44 | 45 | ||
@@ -445,7 +446,12 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, | |||
445 | 446 | ||
446 | static void iommu_table_clear(struct iommu_table *tbl) | 447 | static void iommu_table_clear(struct iommu_table *tbl) |
447 | { | 448 | { |
448 | if (!is_kdump_kernel()) { | 449 | /* |
450 | * In case of firmware assisted dump system goes through clean | ||
451 | * reboot process at the time of system crash. Hence it's safe to | ||
452 | * clear the TCE entries if firmware assisted dump is active. | ||
453 | */ | ||
454 | if (!is_kdump_kernel() || is_fadump_active()) { | ||
449 | /* Clear the table in case firmware left allocations in it */ | 455 | /* Clear the table in case firmware left allocations in it */ |
450 | ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size); | 456 | ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size); |
451 | return; | 457 | return; |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 2d282186cb45..b534bbac3f82 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include <asm/spu.h> | 55 | #include <asm/spu.h> |
56 | #include <asm/udbg.h> | 56 | #include <asm/udbg.h> |
57 | #include <asm/code-patching.h> | 57 | #include <asm/code-patching.h> |
58 | #include <asm/fadump.h> | ||
58 | 59 | ||
59 | #ifdef DEBUG | 60 | #ifdef DEBUG |
60 | #define DBG(fmt...) udbg_printf(fmt) | 61 | #define DBG(fmt...) udbg_printf(fmt) |
@@ -625,6 +626,16 @@ static void __init htab_initialize(void) | |||
625 | /* Using a hypervisor which owns the htab */ | 626 | /* Using a hypervisor which owns the htab */ |
626 | htab_address = NULL; | 627 | htab_address = NULL; |
627 | _SDR1 = 0; | 628 | _SDR1 = 0; |
629 | #ifdef CONFIG_FA_DUMP | ||
630 | /* | ||
631 | * If firmware assisted dump is active firmware preserves | ||
632 | * the contents of htab along with entire partition memory. | ||
633 | * Clear the htab if firmware assisted dump is active so | ||
634 | * that we dont end up using old mappings. | ||
635 | */ | ||
636 | if (is_fadump_active() && ppc_md.hpte_clear_all) | ||
637 | ppc_md.hpte_clear_all(); | ||
638 | #endif | ||
628 | } else { | 639 | } else { |
629 | /* Find storage for the HPT. Must be contiguous in | 640 | /* Find storage for the HPT. Must be contiguous in |
630 | * the absolute address space. On cell we want it to be | 641 | * the absolute address space. On cell we want it to be |