aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/fadump.h52
-rw-r--r--arch/powerpc/kernel/entry_64.S6
-rw-r--r--arch/powerpc/kernel/fadump.c114
-rw-r--r--arch/powerpc/mm/init_32.c2
-rw-r--r--arch/powerpc/platforms/powernv/opal-lpc.c59
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c4
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c14
7 files changed, 163 insertions, 88 deletions
diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h
index a6774560afe3..493e72f64b35 100644
--- a/arch/powerpc/include/asm/fadump.h
+++ b/arch/powerpc/include/asm/fadump.h
@@ -70,39 +70,39 @@
70#define CPU_UNKNOWN (~((u32)0)) 70#define CPU_UNKNOWN (~((u32)0))
71 71
72/* Utility macros */ 72/* Utility macros */
73#define SKIP_TO_NEXT_CPU(reg_entry) \ 73#define SKIP_TO_NEXT_CPU(reg_entry) \
74({ \ 74({ \
75 while (reg_entry->reg_id != REG_ID("CPUEND")) \ 75 while (be64_to_cpu(reg_entry->reg_id) != REG_ID("CPUEND")) \
76 reg_entry++; \ 76 reg_entry++; \
77 reg_entry++; \ 77 reg_entry++; \
78}) 78})
79 79
80/* Kernel Dump section info */ 80/* Kernel Dump section info */
81struct fadump_section { 81struct fadump_section {
82 u32 request_flag; 82 __be32 request_flag;
83 u16 source_data_type; 83 __be16 source_data_type;
84 u16 error_flags; 84 __be16 error_flags;
85 u64 source_address; 85 __be64 source_address;
86 u64 source_len; 86 __be64 source_len;
87 u64 bytes_dumped; 87 __be64 bytes_dumped;
88 u64 destination_address; 88 __be64 destination_address;
89}; 89};
90 90
91/* ibm,configure-kernel-dump header. */ 91/* ibm,configure-kernel-dump header. */
92struct fadump_section_header { 92struct fadump_section_header {
93 u32 dump_format_version; 93 __be32 dump_format_version;
94 u16 dump_num_sections; 94 __be16 dump_num_sections;
95 u16 dump_status_flag; 95 __be16 dump_status_flag;
96 u32 offset_first_dump_section; 96 __be32 offset_first_dump_section;
97 97
98 /* Fields for disk dump option. */ 98 /* Fields for disk dump option. */
99 u32 dd_block_size; 99 __be32 dd_block_size;
100 u64 dd_block_offset; 100 __be64 dd_block_offset;
101 u64 dd_num_blocks; 101 __be64 dd_num_blocks;
102 u32 dd_offset_disk_path; 102 __be32 dd_offset_disk_path;
103 103
104 /* Maximum time allowed to prevent an automatic dump-reboot. */ 104 /* Maximum time allowed to prevent an automatic dump-reboot. */
105 u32 max_time_auto; 105 __be32 max_time_auto;
106}; 106};
107 107
108/* 108/*
@@ -174,15 +174,15 @@ static inline u64 str_to_u64(const char *str)
174 174
175/* Register save area header. */ 175/* Register save area header. */
176struct fadump_reg_save_area_header { 176struct fadump_reg_save_area_header {
177 u64 magic_number; 177 __be64 magic_number;
178 u32 version; 178 __be32 version;
179 u32 num_cpu_offset; 179 __be32 num_cpu_offset;
180}; 180};
181 181
182/* Register entry. */ 182/* Register entry. */
183struct fadump_reg_entry { 183struct fadump_reg_entry {
184 u64 reg_id; 184 __be64 reg_id;
185 u64 reg_value; 185 __be64 reg_value;
186}; 186};
187 187
188/* fadump crash info structure */ 188/* fadump crash info structure */
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 5bbd1bc8c3b0..0905c8da90f1 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -659,7 +659,13 @@ _GLOBAL(ret_from_except_lite)
6593: 6593:
660#endif 660#endif
661 bl save_nvgprs 661 bl save_nvgprs
662 /*
663 * Use a non volatile GPR to save and restore our thread_info flags
664 * across the call to restore_interrupts.
665 */
666 mr r30,r4
662 bl restore_interrupts 667 bl restore_interrupts
668 mr r4,r30
663 addi r3,r1,STACK_FRAME_OVERHEAD 669 addi r3,r1,STACK_FRAME_OVERHEAD
664 bl do_notify_resume 670 bl do_notify_resume
665 b ret_from_except 671 b ret_from_except
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 742694c1d852..26d091a1a54c 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -58,7 +58,7 @@ int __init early_init_dt_scan_fw_dump(unsigned long node,
58 const __be32 *sections; 58 const __be32 *sections;
59 int i, num_sections; 59 int i, num_sections;
60 int size; 60 int size;
61 const int *token; 61 const __be32 *token;
62 62
63 if (depth != 1 || strcmp(uname, "rtas") != 0) 63 if (depth != 1 || strcmp(uname, "rtas") != 0)
64 return 0; 64 return 0;
@@ -72,7 +72,7 @@ int __init early_init_dt_scan_fw_dump(unsigned long node,
72 return 1; 72 return 1;
73 73
74 fw_dump.fadump_supported = 1; 74 fw_dump.fadump_supported = 1;
75 fw_dump.ibm_configure_kernel_dump = *token; 75 fw_dump.ibm_configure_kernel_dump = be32_to_cpu(*token);
76 76
77 /* 77 /*
78 * The 'ibm,kernel-dump' rtas node is present only if there is 78 * The 'ibm,kernel-dump' rtas node is present only if there is
@@ -147,11 +147,11 @@ static unsigned long init_fadump_mem_struct(struct fadump_mem_struct *fdm,
147 memset(fdm, 0, sizeof(struct fadump_mem_struct)); 147 memset(fdm, 0, sizeof(struct fadump_mem_struct));
148 addr = addr & PAGE_MASK; 148 addr = addr & PAGE_MASK;
149 149
150 fdm->header.dump_format_version = 0x00000001; 150 fdm->header.dump_format_version = cpu_to_be32(0x00000001);
151 fdm->header.dump_num_sections = 3; 151 fdm->header.dump_num_sections = cpu_to_be16(3);
152 fdm->header.dump_status_flag = 0; 152 fdm->header.dump_status_flag = 0;
153 fdm->header.offset_first_dump_section = 153 fdm->header.offset_first_dump_section =
154 (u32)offsetof(struct fadump_mem_struct, cpu_state_data); 154 cpu_to_be32((u32)offsetof(struct fadump_mem_struct, cpu_state_data));
155 155
156 /* 156 /*
157 * Fields for disk dump option. 157 * Fields for disk dump option.
@@ -167,27 +167,27 @@ static unsigned long init_fadump_mem_struct(struct fadump_mem_struct *fdm,
167 167
168 /* Kernel dump sections */ 168 /* Kernel dump sections */
169 /* cpu state data section. */ 169 /* cpu state data section. */
170 fdm->cpu_state_data.request_flag = FADUMP_REQUEST_FLAG; 170 fdm->cpu_state_data.request_flag = cpu_to_be32(FADUMP_REQUEST_FLAG);
171 fdm->cpu_state_data.source_data_type = FADUMP_CPU_STATE_DATA; 171 fdm->cpu_state_data.source_data_type = cpu_to_be16(FADUMP_CPU_STATE_DATA);
172 fdm->cpu_state_data.source_address = 0; 172 fdm->cpu_state_data.source_address = 0;
173 fdm->cpu_state_data.source_len = fw_dump.cpu_state_data_size; 173 fdm->cpu_state_data.source_len = cpu_to_be64(fw_dump.cpu_state_data_size);
174 fdm->cpu_state_data.destination_address = addr; 174 fdm->cpu_state_data.destination_address = cpu_to_be64(addr);
175 addr += fw_dump.cpu_state_data_size; 175 addr += fw_dump.cpu_state_data_size;
176 176
177 /* hpte region section */ 177 /* hpte region section */
178 fdm->hpte_region.request_flag = FADUMP_REQUEST_FLAG; 178 fdm->hpte_region.request_flag = cpu_to_be32(FADUMP_REQUEST_FLAG);
179 fdm->hpte_region.source_data_type = FADUMP_HPTE_REGION; 179 fdm->hpte_region.source_data_type = cpu_to_be16(FADUMP_HPTE_REGION);
180 fdm->hpte_region.source_address = 0; 180 fdm->hpte_region.source_address = 0;
181 fdm->hpte_region.source_len = fw_dump.hpte_region_size; 181 fdm->hpte_region.source_len = cpu_to_be64(fw_dump.hpte_region_size);
182 fdm->hpte_region.destination_address = addr; 182 fdm->hpte_region.destination_address = cpu_to_be64(addr);
183 addr += fw_dump.hpte_region_size; 183 addr += fw_dump.hpte_region_size;
184 184
185 /* RMA region section */ 185 /* RMA region section */
186 fdm->rmr_region.request_flag = FADUMP_REQUEST_FLAG; 186 fdm->rmr_region.request_flag = cpu_to_be32(FADUMP_REQUEST_FLAG);
187 fdm->rmr_region.source_data_type = FADUMP_REAL_MODE_REGION; 187 fdm->rmr_region.source_data_type = cpu_to_be16(FADUMP_REAL_MODE_REGION);
188 fdm->rmr_region.source_address = RMA_START; 188 fdm->rmr_region.source_address = cpu_to_be64(RMA_START);
189 fdm->rmr_region.source_len = fw_dump.boot_memory_size; 189 fdm->rmr_region.source_len = cpu_to_be64(fw_dump.boot_memory_size);
190 fdm->rmr_region.destination_address = addr; 190 fdm->rmr_region.destination_address = cpu_to_be64(addr);
191 addr += fw_dump.boot_memory_size; 191 addr += fw_dump.boot_memory_size;
192 192
193 return addr; 193 return addr;
@@ -272,7 +272,7 @@ int __init fadump_reserve_mem(void)
272 * first kernel. 272 * first kernel.
273 */ 273 */
274 if (fdm_active) 274 if (fdm_active)
275 fw_dump.boot_memory_size = fdm_active->rmr_region.source_len; 275 fw_dump.boot_memory_size = be64_to_cpu(fdm_active->rmr_region.source_len);
276 else 276 else
277 fw_dump.boot_memory_size = fadump_calculate_reserve_size(); 277 fw_dump.boot_memory_size = fadump_calculate_reserve_size();
278 278
@@ -314,8 +314,8 @@ int __init fadump_reserve_mem(void)
314 (unsigned long)(base >> 20)); 314 (unsigned long)(base >> 20));
315 315
316 fw_dump.fadumphdr_addr = 316 fw_dump.fadumphdr_addr =
317 fdm_active->rmr_region.destination_address + 317 be64_to_cpu(fdm_active->rmr_region.destination_address) +
318 fdm_active->rmr_region.source_len; 318 be64_to_cpu(fdm_active->rmr_region.source_len);
319 pr_debug("fadumphdr_addr = %p\n", 319 pr_debug("fadumphdr_addr = %p\n",
320 (void *) fw_dump.fadumphdr_addr); 320 (void *) fw_dump.fadumphdr_addr);
321 } else { 321 } else {
@@ -472,9 +472,9 @@ fadump_read_registers(struct fadump_reg_entry *reg_entry, struct pt_regs *regs)
472{ 472{
473 memset(regs, 0, sizeof(struct pt_regs)); 473 memset(regs, 0, sizeof(struct pt_regs));
474 474
475 while (reg_entry->reg_id != REG_ID("CPUEND")) { 475 while (be64_to_cpu(reg_entry->reg_id) != REG_ID("CPUEND")) {
476 fadump_set_regval(regs, reg_entry->reg_id, 476 fadump_set_regval(regs, be64_to_cpu(reg_entry->reg_id),
477 reg_entry->reg_value); 477 be64_to_cpu(reg_entry->reg_value));
478 reg_entry++; 478 reg_entry++;
479 } 479 }
480 reg_entry++; 480 reg_entry++;
@@ -603,20 +603,20 @@ static int __init fadump_build_cpu_notes(const struct fadump_mem_struct *fdm)
603 if (!fdm->cpu_state_data.bytes_dumped) 603 if (!fdm->cpu_state_data.bytes_dumped)
604 return -EINVAL; 604 return -EINVAL;
605 605
606 addr = fdm->cpu_state_data.destination_address; 606 addr = be64_to_cpu(fdm->cpu_state_data.destination_address);
607 vaddr = __va(addr); 607 vaddr = __va(addr);
608 608
609 reg_header = vaddr; 609 reg_header = vaddr;
610 if (reg_header->magic_number != REGSAVE_AREA_MAGIC) { 610 if (be64_to_cpu(reg_header->magic_number) != REGSAVE_AREA_MAGIC) {
611 printk(KERN_ERR "Unable to read register save area.\n"); 611 printk(KERN_ERR "Unable to read register save area.\n");
612 return -ENOENT; 612 return -ENOENT;
613 } 613 }
614 pr_debug("--------CPU State Data------------\n"); 614 pr_debug("--------CPU State Data------------\n");
615 pr_debug("Magic Number: %llx\n", reg_header->magic_number); 615 pr_debug("Magic Number: %llx\n", be64_to_cpu(reg_header->magic_number));
616 pr_debug("NumCpuOffset: %x\n", reg_header->num_cpu_offset); 616 pr_debug("NumCpuOffset: %x\n", be32_to_cpu(reg_header->num_cpu_offset));
617 617
618 vaddr += reg_header->num_cpu_offset; 618 vaddr += be32_to_cpu(reg_header->num_cpu_offset);
619 num_cpus = *((u32 *)(vaddr)); 619 num_cpus = be32_to_cpu(*((__be32 *)(vaddr)));
620 pr_debug("NumCpus : %u\n", num_cpus); 620 pr_debug("NumCpus : %u\n", num_cpus);
621 vaddr += sizeof(u32); 621 vaddr += sizeof(u32);
622 reg_entry = (struct fadump_reg_entry *)vaddr; 622 reg_entry = (struct fadump_reg_entry *)vaddr;
@@ -639,13 +639,13 @@ static int __init fadump_build_cpu_notes(const struct fadump_mem_struct *fdm)
639 fdh = __va(fw_dump.fadumphdr_addr); 639 fdh = __va(fw_dump.fadumphdr_addr);
640 640
641 for (i = 0; i < num_cpus; i++) { 641 for (i = 0; i < num_cpus; i++) {
642 if (reg_entry->reg_id != REG_ID("CPUSTRT")) { 642 if (be64_to_cpu(reg_entry->reg_id) != REG_ID("CPUSTRT")) {
643 printk(KERN_ERR "Unable to read CPU state data\n"); 643 printk(KERN_ERR "Unable to read CPU state data\n");
644 rc = -ENOENT; 644 rc = -ENOENT;
645 goto error_out; 645 goto error_out;
646 } 646 }
647 /* Lower 4 bytes of reg_value contains logical cpu id */ 647 /* Lower 4 bytes of reg_value contains logical cpu id */
648 cpu = reg_entry->reg_value & FADUMP_CPU_ID_MASK; 648 cpu = be64_to_cpu(reg_entry->reg_value) & FADUMP_CPU_ID_MASK;
649 if (fdh && !cpumask_test_cpu(cpu, &fdh->cpu_online_mask)) { 649 if (fdh && !cpumask_test_cpu(cpu, &fdh->cpu_online_mask)) {
650 SKIP_TO_NEXT_CPU(reg_entry); 650 SKIP_TO_NEXT_CPU(reg_entry);
651 continue; 651 continue;
@@ -692,7 +692,7 @@ static int __init process_fadump(const struct fadump_mem_struct *fdm_active)
692 return -EINVAL; 692 return -EINVAL;
693 693
694 /* Check if the dump data is valid. */ 694 /* Check if the dump data is valid. */
695 if ((fdm_active->header.dump_status_flag == FADUMP_ERROR_FLAG) || 695 if ((be16_to_cpu(fdm_active->header.dump_status_flag) == FADUMP_ERROR_FLAG) ||
696 (fdm_active->cpu_state_data.error_flags != 0) || 696 (fdm_active->cpu_state_data.error_flags != 0) ||
697 (fdm_active->rmr_region.error_flags != 0)) { 697 (fdm_active->rmr_region.error_flags != 0)) {
698 printk(KERN_ERR "Dump taken by platform is not valid\n"); 698 printk(KERN_ERR "Dump taken by platform is not valid\n");
@@ -828,7 +828,7 @@ static void fadump_setup_crash_memory_ranges(void)
828static inline unsigned long fadump_relocate(unsigned long paddr) 828static inline unsigned long fadump_relocate(unsigned long paddr)
829{ 829{
830 if (paddr > RMA_START && paddr < fw_dump.boot_memory_size) 830 if (paddr > RMA_START && paddr < fw_dump.boot_memory_size)
831 return fdm.rmr_region.destination_address + paddr; 831 return be64_to_cpu(fdm.rmr_region.destination_address) + paddr;
832 else 832 else
833 return paddr; 833 return paddr;
834} 834}
@@ -902,7 +902,7 @@ static int fadump_create_elfcore_headers(char *bufp)
902 * to the specified destination_address. Hence set 902 * to the specified destination_address. Hence set
903 * the correct offset. 903 * the correct offset.
904 */ 904 */
905 phdr->p_offset = fdm.rmr_region.destination_address; 905 phdr->p_offset = be64_to_cpu(fdm.rmr_region.destination_address);
906 } 906 }
907 907
908 phdr->p_paddr = mbase; 908 phdr->p_paddr = mbase;
@@ -951,7 +951,7 @@ static void register_fadump(void)
951 951
952 fadump_setup_crash_memory_ranges(); 952 fadump_setup_crash_memory_ranges();
953 953
954 addr = fdm.rmr_region.destination_address + fdm.rmr_region.source_len; 954 addr = be64_to_cpu(fdm.rmr_region.destination_address) + be64_to_cpu(fdm.rmr_region.source_len);
955 /* Initialize fadump crash info header. */ 955 /* Initialize fadump crash info header. */
956 addr = init_fadump_header(addr); 956 addr = init_fadump_header(addr);
957 vaddr = __va(addr); 957 vaddr = __va(addr);
@@ -1023,7 +1023,7 @@ void fadump_cleanup(void)
1023 /* Invalidate the registration only if dump is active. */ 1023 /* Invalidate the registration only if dump is active. */
1024 if (fw_dump.dump_active) { 1024 if (fw_dump.dump_active) {
1025 init_fadump_mem_struct(&fdm, 1025 init_fadump_mem_struct(&fdm,
1026 fdm_active->cpu_state_data.destination_address); 1026 be64_to_cpu(fdm_active->cpu_state_data.destination_address));
1027 fadump_invalidate_dump(&fdm); 1027 fadump_invalidate_dump(&fdm);
1028 } 1028 }
1029} 1029}
@@ -1063,7 +1063,7 @@ static void fadump_invalidate_release_mem(void)
1063 return; 1063 return;
1064 } 1064 }
1065 1065
1066 destination_address = fdm_active->cpu_state_data.destination_address; 1066 destination_address = be64_to_cpu(fdm_active->cpu_state_data.destination_address);
1067 fadump_cleanup(); 1067 fadump_cleanup();
1068 mutex_unlock(&fadump_mutex); 1068 mutex_unlock(&fadump_mutex);
1069 1069
@@ -1183,31 +1183,31 @@ static int fadump_region_show(struct seq_file *m, void *private)
1183 seq_printf(m, 1183 seq_printf(m,
1184 "CPU : [%#016llx-%#016llx] %#llx bytes, " 1184 "CPU : [%#016llx-%#016llx] %#llx bytes, "
1185 "Dumped: %#llx\n", 1185 "Dumped: %#llx\n",
1186 fdm_ptr->cpu_state_data.destination_address, 1186 be64_to_cpu(fdm_ptr->cpu_state_data.destination_address),
1187 fdm_ptr->cpu_state_data.destination_address + 1187 be64_to_cpu(fdm_ptr->cpu_state_data.destination_address) +
1188 fdm_ptr->cpu_state_data.source_len - 1, 1188 be64_to_cpu(fdm_ptr->cpu_state_data.source_len) - 1,
1189 fdm_ptr->cpu_state_data.source_len, 1189 be64_to_cpu(fdm_ptr->cpu_state_data.source_len),
1190 fdm_ptr->cpu_state_data.bytes_dumped); 1190 be64_to_cpu(fdm_ptr->cpu_state_data.bytes_dumped));
1191 seq_printf(m, 1191 seq_printf(m,
1192 "HPTE: [%#016llx-%#016llx] %#llx bytes, " 1192 "HPTE: [%#016llx-%#016llx] %#llx bytes, "
1193 "Dumped: %#llx\n", 1193 "Dumped: %#llx\n",
1194 fdm_ptr->hpte_region.destination_address, 1194 be64_to_cpu(fdm_ptr->hpte_region.destination_address),
1195 fdm_ptr->hpte_region.destination_address + 1195 be64_to_cpu(fdm_ptr->hpte_region.destination_address) +
1196 fdm_ptr->hpte_region.source_len - 1, 1196 be64_to_cpu(fdm_ptr->hpte_region.source_len) - 1,
1197 fdm_ptr->hpte_region.source_len, 1197 be64_to_cpu(fdm_ptr->hpte_region.source_len),
1198 fdm_ptr->hpte_region.bytes_dumped); 1198 be64_to_cpu(fdm_ptr->hpte_region.bytes_dumped));
1199 seq_printf(m, 1199 seq_printf(m,
1200 "DUMP: [%#016llx-%#016llx] %#llx bytes, " 1200 "DUMP: [%#016llx-%#016llx] %#llx bytes, "
1201 "Dumped: %#llx\n", 1201 "Dumped: %#llx\n",
1202 fdm_ptr->rmr_region.destination_address, 1202 be64_to_cpu(fdm_ptr->rmr_region.destination_address),
1203 fdm_ptr->rmr_region.destination_address + 1203 be64_to_cpu(fdm_ptr->rmr_region.destination_address) +
1204 fdm_ptr->rmr_region.source_len - 1, 1204 be64_to_cpu(fdm_ptr->rmr_region.source_len) - 1,
1205 fdm_ptr->rmr_region.source_len, 1205 be64_to_cpu(fdm_ptr->rmr_region.source_len),
1206 fdm_ptr->rmr_region.bytes_dumped); 1206 be64_to_cpu(fdm_ptr->rmr_region.bytes_dumped));
1207 1207
1208 if (!fdm_active || 1208 if (!fdm_active ||
1209 (fw_dump.reserve_dump_area_start == 1209 (fw_dump.reserve_dump_area_start ==
1210 fdm_ptr->cpu_state_data.destination_address)) 1210 be64_to_cpu(fdm_ptr->cpu_state_data.destination_address)))
1211 goto out; 1211 goto out;
1212 1212
1213 /* Dump is active. Show reserved memory region. */ 1213 /* Dump is active. Show reserved memory region. */
@@ -1215,10 +1215,10 @@ static int fadump_region_show(struct seq_file *m, void *private)
1215 " : [%#016llx-%#016llx] %#llx bytes, " 1215 " : [%#016llx-%#016llx] %#llx bytes, "
1216 "Dumped: %#llx\n", 1216 "Dumped: %#llx\n",
1217 (unsigned long long)fw_dump.reserve_dump_area_start, 1217 (unsigned long long)fw_dump.reserve_dump_area_start,
1218 fdm_ptr->cpu_state_data.destination_address - 1, 1218 be64_to_cpu(fdm_ptr->cpu_state_data.destination_address) - 1,
1219 fdm_ptr->cpu_state_data.destination_address - 1219 be64_to_cpu(fdm_ptr->cpu_state_data.destination_address) -
1220 fw_dump.reserve_dump_area_start, 1220 fw_dump.reserve_dump_area_start,
1221 fdm_ptr->cpu_state_data.destination_address - 1221 be64_to_cpu(fdm_ptr->cpu_state_data.destination_address) -
1222 fw_dump.reserve_dump_area_start); 1222 fw_dump.reserve_dump_area_start);
1223out: 1223out:
1224 if (fdm_active) 1224 if (fdm_active)
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index cad68ff8eca5..415a51b028b9 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -103,7 +103,7 @@ unsigned long __max_low_memory = MAX_LOW_MEM;
103/* 103/*
104 * Check for command-line options that affect what MMU_init will do. 104 * Check for command-line options that affect what MMU_init will do.
105 */ 105 */
106void MMU_setup(void) 106void __init MMU_setup(void)
107{ 107{
108 /* Check for nobats option (used in mapin_ram). */ 108 /* Check for nobats option (used in mapin_ram). */
109 if (strstr(boot_command_line, "nobats")) { 109 if (strstr(boot_command_line, "nobats")) {
diff --git a/arch/powerpc/platforms/powernv/opal-lpc.c b/arch/powerpc/platforms/powernv/opal-lpc.c
index ad4b31df779a..e4169d68cb32 100644
--- a/arch/powerpc/platforms/powernv/opal-lpc.c
+++ b/arch/powerpc/platforms/powernv/opal-lpc.c
@@ -216,14 +216,54 @@ static ssize_t lpc_debug_read(struct file *filp, char __user *ubuf,
216 &data, len); 216 &data, len);
217 if (rc) 217 if (rc)
218 return -ENXIO; 218 return -ENXIO;
219
220 /*
221 * Now there is some trickery with the data returned by OPAL
222 * as it's the desired data right justified in a 32-bit BE
223 * word.
224 *
225 * This is a very bad interface and I'm to blame for it :-(
226 *
227 * So we can't just apply a 32-bit swap to what comes from OPAL,
228 * because user space expects the *bytes* to be in their proper
229 * respective positions (ie, LPC position).
230 *
231 * So what we really want to do here is to shift data right
232 * appropriately on a LE kernel.
233 *
234 * IE. If the LPC transaction has bytes B0, B1, B2 and B3 in that
235 * order, we have in memory written to by OPAL at the "data"
236 * pointer:
237 *
238 * Bytes: OPAL "data" LE "data"
239 * 32-bit: B0 B1 B2 B3 B0B1B2B3 B3B2B1B0
240 * 16-bit: B0 B1 0000B0B1 B1B00000
241 * 8-bit: B0 000000B0 B0000000
242 *
243 * So a BE kernel will have the leftmost of the above in the MSB
244 * and rightmost in the LSB and can just then "cast" the u32 "data"
245 * down to the appropriate quantity and write it.
246 *
247 * However, an LE kernel can't. It doesn't need to swap because a
248 * load from data followed by a store to user are going to preserve
249 * the byte ordering which is the wire byte order which is what the
250 * user wants, but in order to "crop" to the right size, we need to
251 * shift right first.
252 */
219 switch(len) { 253 switch(len) {
220 case 4: 254 case 4:
221 rc = __put_user((u32)data, (u32 __user *)ubuf); 255 rc = __put_user((u32)data, (u32 __user *)ubuf);
222 break; 256 break;
223 case 2: 257 case 2:
258#ifdef __LITTLE_ENDIAN__
259 data >>= 16;
260#endif
224 rc = __put_user((u16)data, (u16 __user *)ubuf); 261 rc = __put_user((u16)data, (u16 __user *)ubuf);
225 break; 262 break;
226 default: 263 default:
264#ifdef __LITTLE_ENDIAN__
265 data >>= 24;
266#endif
227 rc = __put_user((u8)data, (u8 __user *)ubuf); 267 rc = __put_user((u8)data, (u8 __user *)ubuf);
228 break; 268 break;
229 } 269 }
@@ -263,12 +303,31 @@ static ssize_t lpc_debug_write(struct file *filp, const char __user *ubuf,
263 else if (todo > 1 && (pos & 1) == 0) 303 else if (todo > 1 && (pos & 1) == 0)
264 len = 2; 304 len = 2;
265 } 305 }
306
307 /*
308 * Similarly to the read case, we have some trickery here but
309 * it's different to handle. We need to pass the value to OPAL in
310 * a register whose layout depends on the access size. We want
311 * to reproduce the memory layout of the user, however we aren't
312 * doing a load from user and a store to another memory location
313 * which would achieve that. Here we pass the value to OPAL via
314 * a register which is expected to contain the "BE" interpretation
315 * of the byte sequence. IE: for a 32-bit access, byte 0 should be
316 * in the MSB. So here we *do* need to byteswap on LE.
317 *
318 * User bytes: LE "data" OPAL "data"
319 * 32-bit: B0 B1 B2 B3 B3B2B1B0 B0B1B2B3
320 * 16-bit: B0 B1 0000B1B0 0000B0B1
321 * 8-bit: B0 000000B0 000000B0
322 */
266 switch(len) { 323 switch(len) {
267 case 4: 324 case 4:
268 rc = __get_user(data, (u32 __user *)ubuf); 325 rc = __get_user(data, (u32 __user *)ubuf);
326 data = cpu_to_be32(data);
269 break; 327 break;
270 case 2: 328 case 2:
271 rc = __get_user(data, (u16 __user *)ubuf); 329 rc = __get_user(data, (u16 __user *)ubuf);
330 data = cpu_to_be16(data);
272 break; 331 break;
273 default: 332 default:
274 rc = __get_user(data, (u8 __user *)ubuf); 333 rc = __get_user(data, (u8 __user *)ubuf);
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index 6ad83bd11fe2..c22bb1b4beb8 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -382,7 +382,7 @@ static int dlpar_online_cpu(struct device_node *dn)
382 BUG_ON(get_cpu_current_state(cpu) 382 BUG_ON(get_cpu_current_state(cpu)
383 != CPU_STATE_OFFLINE); 383 != CPU_STATE_OFFLINE);
384 cpu_maps_update_done(); 384 cpu_maps_update_done();
385 rc = cpu_up(cpu); 385 rc = device_online(get_cpu_device(cpu));
386 if (rc) 386 if (rc)
387 goto out; 387 goto out;
388 cpu_maps_update_begin(); 388 cpu_maps_update_begin();
@@ -467,7 +467,7 @@ static int dlpar_offline_cpu(struct device_node *dn)
467 if (get_cpu_current_state(cpu) == CPU_STATE_ONLINE) { 467 if (get_cpu_current_state(cpu) == CPU_STATE_ONLINE) {
468 set_preferred_offline_state(cpu, CPU_STATE_OFFLINE); 468 set_preferred_offline_state(cpu, CPU_STATE_OFFLINE);
469 cpu_maps_update_done(); 469 cpu_maps_update_done();
470 rc = cpu_down(cpu); 470 rc = device_offline(get_cpu_device(cpu));
471 if (rc) 471 if (rc)
472 goto out; 472 goto out;
473 cpu_maps_update_begin(); 473 cpu_maps_update_begin();
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 8c509d5397c6..f6880d2a40fb 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -43,6 +43,7 @@
43#include <asm/trace.h> 43#include <asm/trace.h>
44#include <asm/firmware.h> 44#include <asm/firmware.h>
45#include <asm/plpar_wrappers.h> 45#include <asm/plpar_wrappers.h>
46#include <asm/fadump.h>
46 47
47#include "pseries.h" 48#include "pseries.h"
48 49
@@ -247,8 +248,17 @@ static void pSeries_lpar_hptab_clear(void)
247 } 248 }
248 249
249#ifdef __LITTLE_ENDIAN__ 250#ifdef __LITTLE_ENDIAN__
250 /* Reset exceptions to big endian */ 251 /*
251 if (firmware_has_feature(FW_FEATURE_SET_MODE)) { 252 * Reset exceptions to big endian.
253 *
254 * FIXME this is a hack for kexec, we need to reset the exception
255 * endian before starting the new kernel and this is a convenient place
256 * to do it.
257 *
258 * This is also called on boot when a fadump happens. In that case we
259 * must not change the exception endian mode.
260 */
261 if (firmware_has_feature(FW_FEATURE_SET_MODE) && !is_fadump_active()) {
252 long rc; 262 long rc;
253 263
254 rc = pseries_big_endian_exceptions(); 264 rc = pseries_big_endian_exceptions();