diff options
| -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(); |
