diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-11-04 14:18:29 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-11-04 14:18:29 -0500 |
commit | 8a97577a5967c1234ccc3bc1b45e4b1a58b39ea8 (patch) | |
tree | 5da3ad09d120c3d1a2b3e1aee80822adbd3bc221 /arch | |
parent | 1efa82ecb621a819b552cf541fc5169c44816a6d (diff) | |
parent | 10ccaf178b2b961d8bca252d647ed7ed8aae2a20 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mpe/linux
Pull powerpc fixes from Michael Ellerman:
"Some more powerpc fixes if you please"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mpe/linux:
powerpc: use device_online/offline() instead of cpu_up/down()
powerpc/powernv: Properly fix LPC debugfs endianness
powerpc: do_notify_resume can be called with bad thread_info flags argument
powerpc/fadump: Fix endianess issues in firmware assisted dump handling
powerpc: Fix section mismatch warning
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/include/asm/fadump.h | 52 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/fadump.c | 114 | ||||
-rw-r--r-- | arch/powerpc/mm/init_32.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/opal-lpc.c | 59 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/dlpar.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/lpar.c | 14 |
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 */ |
81 | struct fadump_section { | 81 | struct 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. */ |
92 | struct fadump_section_header { | 92 | struct 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. */ |
176 | struct fadump_reg_save_area_header { | 176 | struct 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. */ |
183 | struct fadump_reg_entry { | 183 | struct 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) | |||
659 | 3: | 659 | 3: |
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) | |||
828 | static inline unsigned long fadump_relocate(unsigned long paddr) | 828 | static 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); |
1223 | out: | 1223 | out: |
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 | */ |
106 | void MMU_setup(void) | 106 | void __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(); |