diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2012-10-25 10:23:31 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2012-12-13 11:00:39 -0500 |
commit | abe77f90dc9c65a7c9a4d61c2cbb8db4d5566e4f (patch) | |
tree | 69fd0cfe31a9041e8e1a881829c011892075ea2c /arch | |
parent | 7aa1c8f47e7e792d11f898cbdddaf6fa21ff08cc (diff) |
MIPS: Octeon: Add kexec and kdump support
[ralf@linux-mips.org: Original patch by Maxim Uvarov <muvarov@gmail.com>
with plenty of further shining, polishing, debugging and testing by me.]
Signed-off-by: Maxim Uvarov <muvarov@gmail.com>
Cc: linux-mips@linux-mips.org
Cc: kexec@lists.infradead.org
Cc: horms@verge.net.au
Patchwork: https://patchwork.linux-mips.org/patch/1026/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/Makefile | 4 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/executive/cvmx-bootmem.c | 5 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/setup.c | 312 | ||||
-rw-r--r-- | arch/mips/include/asm/octeon/cvmx-bootmem.h | 2 | ||||
-rw-r--r-- | arch/mips/kernel/crash_dump.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/relocate_kernel.S | 19 |
6 files changed, 335 insertions, 9 deletions
diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 654b1ad39f05..033395ec82f1 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile | |||
@@ -192,6 +192,10 @@ endif | |||
192 | # | 192 | # |
193 | include $(srctree)/arch/mips/Kbuild.platforms | 193 | include $(srctree)/arch/mips/Kbuild.platforms |
194 | 194 | ||
195 | ifdef CONFIG_PHYSICAL_START | ||
196 | load-y = $(CONFIG_PHYSICAL_START) | ||
197 | endif | ||
198 | |||
195 | cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic | 199 | cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic |
196 | drivers-$(CONFIG_PCI) += arch/mips/pci/ | 200 | drivers-$(CONFIG_PCI) += arch/mips/pci/ |
197 | 201 | ||
diff --git a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c index fdf5f19bfdb0..6d5ddbc112cc 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c +++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c | |||
@@ -688,3 +688,8 @@ int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr, | |||
688 | cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock)); | 688 | cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock)); |
689 | return addr_allocated; | 689 | return addr_allocated; |
690 | } | 690 | } |
691 | |||
692 | struct cvmx_bootmem_desc *cvmx_bootmem_get_desc(void) | ||
693 | { | ||
694 | return cvmx_bootmem_desc; | ||
695 | } | ||
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 67aa3b942f06..7c2b7aab77ba 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/serial_8250.h> | 25 | #include <linux/serial_8250.h> |
26 | #include <linux/of_fdt.h> | 26 | #include <linux/of_fdt.h> |
27 | #include <linux/libfdt.h> | 27 | #include <linux/libfdt.h> |
28 | #include <linux/kexec.h> | ||
28 | 29 | ||
29 | #include <asm/processor.h> | 30 | #include <asm/processor.h> |
30 | #include <asm/reboot.h> | 31 | #include <asm/reboot.h> |
@@ -58,11 +59,208 @@ struct octeon_boot_descriptor *octeon_boot_desc_ptr; | |||
58 | struct cvmx_bootinfo *octeon_bootinfo; | 59 | struct cvmx_bootinfo *octeon_bootinfo; |
59 | EXPORT_SYMBOL(octeon_bootinfo); | 60 | EXPORT_SYMBOL(octeon_bootinfo); |
60 | 61 | ||
62 | static unsigned long long RESERVE_LOW_MEM = 0ull; | ||
63 | #ifdef CONFIG_KEXEC | ||
64 | #ifdef CONFIG_SMP | ||
65 | /* | ||
66 | * Wait for relocation code is prepared and send | ||
67 | * secondary CPUs to spin until kernel is relocated. | ||
68 | */ | ||
69 | static void octeon_kexec_smp_down(void *ignored) | ||
70 | { | ||
71 | int cpu = smp_processor_id(); | ||
72 | |||
73 | local_irq_disable(); | ||
74 | set_cpu_online(cpu, false); | ||
75 | while (!atomic_read(&kexec_ready_to_reboot)) | ||
76 | cpu_relax(); | ||
77 | |||
78 | asm volatile ( | ||
79 | " sync \n" | ||
80 | " synci ($0) \n"); | ||
81 | |||
82 | relocated_kexec_smp_wait(NULL); | ||
83 | } | ||
84 | #endif | ||
85 | |||
86 | #define OCTEON_DDR0_BASE (0x0ULL) | ||
87 | #define OCTEON_DDR0_SIZE (0x010000000ULL) | ||
88 | #define OCTEON_DDR1_BASE (0x410000000ULL) | ||
89 | #define OCTEON_DDR1_SIZE (0x010000000ULL) | ||
90 | #define OCTEON_DDR2_BASE (0x020000000ULL) | ||
91 | #define OCTEON_DDR2_SIZE (0x3e0000000ULL) | ||
92 | #define OCTEON_MAX_PHY_MEM_SIZE (16*1024*1024*1024ULL) | ||
93 | |||
94 | static struct kimage *kimage_ptr; | ||
95 | |||
96 | static void kexec_bootmem_init(uint64_t mem_size, uint32_t low_reserved_bytes) | ||
97 | { | ||
98 | int64_t addr; | ||
99 | struct cvmx_bootmem_desc *bootmem_desc; | ||
100 | |||
101 | bootmem_desc = cvmx_bootmem_get_desc(); | ||
102 | |||
103 | if (mem_size > OCTEON_MAX_PHY_MEM_SIZE) { | ||
104 | mem_size = OCTEON_MAX_PHY_MEM_SIZE; | ||
105 | pr_err("Error: requested memory too large," | ||
106 | "truncating to maximum size\n"); | ||
107 | } | ||
108 | |||
109 | bootmem_desc->major_version = CVMX_BOOTMEM_DESC_MAJ_VER; | ||
110 | bootmem_desc->minor_version = CVMX_BOOTMEM_DESC_MIN_VER; | ||
111 | |||
112 | addr = (OCTEON_DDR0_BASE + RESERVE_LOW_MEM + low_reserved_bytes); | ||
113 | bootmem_desc->head_addr = 0; | ||
114 | |||
115 | if (mem_size <= OCTEON_DDR0_SIZE) { | ||
116 | __cvmx_bootmem_phy_free(addr, | ||
117 | mem_size - RESERVE_LOW_MEM - | ||
118 | low_reserved_bytes, 0); | ||
119 | return; | ||
120 | } | ||
121 | |||
122 | __cvmx_bootmem_phy_free(addr, | ||
123 | OCTEON_DDR0_SIZE - RESERVE_LOW_MEM - | ||
124 | low_reserved_bytes, 0); | ||
125 | |||
126 | mem_size -= OCTEON_DDR0_SIZE; | ||
127 | |||
128 | if (mem_size > OCTEON_DDR1_SIZE) { | ||
129 | __cvmx_bootmem_phy_free(OCTEON_DDR1_BASE, OCTEON_DDR1_SIZE, 0); | ||
130 | __cvmx_bootmem_phy_free(OCTEON_DDR2_BASE, | ||
131 | mem_size - OCTEON_DDR1_SIZE, 0); | ||
132 | } else | ||
133 | __cvmx_bootmem_phy_free(OCTEON_DDR1_BASE, mem_size, 0); | ||
134 | } | ||
135 | |||
136 | static int octeon_kexec_prepare(struct kimage *image) | ||
137 | { | ||
138 | int i; | ||
139 | char *bootloader = "kexec"; | ||
140 | |||
141 | octeon_boot_desc_ptr->argc = 0; | ||
142 | for (i = 0; i < image->nr_segments; i++) { | ||
143 | if (!strncmp(bootloader, (char *)image->segment[i].buf, | ||
144 | strlen(bootloader))) { | ||
145 | /* | ||
146 | * convert command line string to array | ||
147 | * of parameters (as bootloader does). | ||
148 | */ | ||
149 | int argc = 0, offt; | ||
150 | char *str = (char *)image->segment[i].buf; | ||
151 | char *ptr = strchr(str, ' '); | ||
152 | while (ptr && (OCTEON_ARGV_MAX_ARGS > argc)) { | ||
153 | *ptr = '\0'; | ||
154 | if (ptr[1] != ' ') { | ||
155 | offt = (int)(ptr - str + 1); | ||
156 | octeon_boot_desc_ptr->argv[argc] = | ||
157 | image->segment[i].mem + offt; | ||
158 | argc++; | ||
159 | } | ||
160 | ptr = strchr(ptr + 1, ' '); | ||
161 | } | ||
162 | octeon_boot_desc_ptr->argc = argc; | ||
163 | break; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | /* | ||
168 | * Information about segments will be needed during pre-boot memory | ||
169 | * initialization. | ||
170 | */ | ||
171 | kimage_ptr = image; | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static void octeon_generic_shutdown(void) | ||
176 | { | ||
177 | int cpu, i; | ||
178 | struct cvmx_bootmem_desc *bootmem_desc; | ||
179 | void *named_block_array_ptr; | ||
180 | |||
181 | bootmem_desc = cvmx_bootmem_get_desc(); | ||
182 | named_block_array_ptr = | ||
183 | cvmx_phys_to_ptr(bootmem_desc->named_block_array_addr); | ||
184 | |||
185 | #ifdef CONFIG_SMP | ||
186 | /* disable watchdogs */ | ||
187 | for_each_online_cpu(cpu) | ||
188 | cvmx_write_csr(CVMX_CIU_WDOGX(cpu_logical_map(cpu)), 0); | ||
189 | #else | ||
190 | cvmx_write_csr(CVMX_CIU_WDOGX(cvmx_get_core_num()), 0); | ||
191 | #endif | ||
192 | if (kimage_ptr != kexec_crash_image) { | ||
193 | memset(named_block_array_ptr, | ||
194 | 0x0, | ||
195 | CVMX_BOOTMEM_NUM_NAMED_BLOCKS * | ||
196 | sizeof(struct cvmx_bootmem_named_block_desc)); | ||
197 | /* | ||
198 | * Mark all memory (except low 0x100000 bytes) as free. | ||
199 | * It is the same thing that bootloader does. | ||
200 | */ | ||
201 | kexec_bootmem_init(octeon_bootinfo->dram_size*1024ULL*1024ULL, | ||
202 | 0x100000); | ||
203 | /* | ||
204 | * Allocate all segments to avoid their corruption during boot. | ||
205 | */ | ||
206 | for (i = 0; i < kimage_ptr->nr_segments; i++) | ||
207 | cvmx_bootmem_alloc_address( | ||
208 | kimage_ptr->segment[i].memsz + 2*PAGE_SIZE, | ||
209 | kimage_ptr->segment[i].mem - PAGE_SIZE, | ||
210 | PAGE_SIZE); | ||
211 | } else { | ||
212 | /* | ||
213 | * Do not mark all memory as free. Free only named sections | ||
214 | * leaving the rest of memory unchanged. | ||
215 | */ | ||
216 | struct cvmx_bootmem_named_block_desc *ptr = | ||
217 | (struct cvmx_bootmem_named_block_desc *) | ||
218 | named_block_array_ptr; | ||
219 | |||
220 | for (i = 0; i < bootmem_desc->named_block_num_blocks; i++) | ||
221 | if (ptr[i].size) | ||
222 | cvmx_bootmem_free_named(ptr[i].name); | ||
223 | } | ||
224 | kexec_args[2] = 1UL; /* running on octeon_main_processor */ | ||
225 | kexec_args[3] = (unsigned long)octeon_boot_desc_ptr; | ||
226 | #ifdef CONFIG_SMP | ||
227 | secondary_kexec_args[2] = 0UL; /* running on secondary cpu */ | ||
228 | secondary_kexec_args[3] = (unsigned long)octeon_boot_desc_ptr; | ||
229 | #endif | ||
230 | } | ||
231 | |||
232 | static void octeon_shutdown(void) | ||
233 | { | ||
234 | octeon_generic_shutdown(); | ||
235 | #ifdef CONFIG_SMP | ||
236 | smp_call_function(octeon_kexec_smp_down, NULL, 0); | ||
237 | smp_wmb(); | ||
238 | while (num_online_cpus() > 1) { | ||
239 | cpu_relax(); | ||
240 | mdelay(1); | ||
241 | } | ||
242 | #endif | ||
243 | } | ||
244 | |||
245 | static void octeon_crash_shutdown(struct pt_regs *regs) | ||
246 | { | ||
247 | octeon_generic_shutdown(); | ||
248 | default_machine_crash_shutdown(regs); | ||
249 | } | ||
250 | |||
251 | #endif /* CONFIG_KEXEC */ | ||
252 | |||
61 | #ifdef CONFIG_CAVIUM_RESERVE32 | 253 | #ifdef CONFIG_CAVIUM_RESERVE32 |
62 | uint64_t octeon_reserve32_memory; | 254 | uint64_t octeon_reserve32_memory; |
63 | EXPORT_SYMBOL(octeon_reserve32_memory); | 255 | EXPORT_SYMBOL(octeon_reserve32_memory); |
64 | #endif | 256 | #endif |
65 | 257 | ||
258 | #ifdef CONFIG_KEXEC | ||
259 | /* crashkernel cmdline parameter is parsed _after_ memory setup | ||
260 | * we also parse it here (workaround for EHB5200) */ | ||
261 | static uint64_t crashk_size, crashk_base; | ||
262 | #endif | ||
263 | |||
66 | static int octeon_uart; | 264 | static int octeon_uart; |
67 | 265 | ||
68 | extern asmlinkage void handle_int(void); | 266 | extern asmlinkage void handle_int(void); |
@@ -417,6 +615,8 @@ void octeon_user_io_init(void) | |||
417 | void __init prom_init(void) | 615 | void __init prom_init(void) |
418 | { | 616 | { |
419 | struct cvmx_sysinfo *sysinfo; | 617 | struct cvmx_sysinfo *sysinfo; |
618 | const char *arg; | ||
619 | char *p; | ||
420 | int i; | 620 | int i; |
421 | int argc; | 621 | int argc; |
422 | #ifdef CONFIG_CAVIUM_RESERVE32 | 622 | #ifdef CONFIG_CAVIUM_RESERVE32 |
@@ -568,6 +768,15 @@ void __init prom_init(void) | |||
568 | if (octeon_is_simulation()) | 768 | if (octeon_is_simulation()) |
569 | MAX_MEMORY = 64ull << 20; | 769 | MAX_MEMORY = 64ull << 20; |
570 | 770 | ||
771 | arg = strstr(arcs_cmdline, "mem="); | ||
772 | if (arg) { | ||
773 | MAX_MEMORY = memparse(arg + 4, &p); | ||
774 | if (MAX_MEMORY == 0) | ||
775 | MAX_MEMORY = 32ull << 30; | ||
776 | if (*p == '@') | ||
777 | RESERVE_LOW_MEM = memparse(p + 1, &p); | ||
778 | } | ||
779 | |||
571 | arcs_cmdline[0] = 0; | 780 | arcs_cmdline[0] = 0; |
572 | argc = octeon_boot_desc_ptr->argc; | 781 | argc = octeon_boot_desc_ptr->argc; |
573 | for (i = 0; i < argc; i++) { | 782 | for (i = 0; i < argc; i++) { |
@@ -575,16 +784,30 @@ void __init prom_init(void) | |||
575 | cvmx_phys_to_ptr(octeon_boot_desc_ptr->argv[i]); | 784 | cvmx_phys_to_ptr(octeon_boot_desc_ptr->argv[i]); |
576 | if ((strncmp(arg, "MEM=", 4) == 0) || | 785 | if ((strncmp(arg, "MEM=", 4) == 0) || |
577 | (strncmp(arg, "mem=", 4) == 0)) { | 786 | (strncmp(arg, "mem=", 4) == 0)) { |
578 | sscanf(arg + 4, "%llu", &MAX_MEMORY); | 787 | MAX_MEMORY = memparse(arg + 4, &p); |
579 | MAX_MEMORY <<= 20; | ||
580 | if (MAX_MEMORY == 0) | 788 | if (MAX_MEMORY == 0) |
581 | MAX_MEMORY = 32ull << 30; | 789 | MAX_MEMORY = 32ull << 30; |
790 | if (*p == '@') | ||
791 | RESERVE_LOW_MEM = memparse(p + 1, &p); | ||
582 | } else if (strcmp(arg, "ecc_verbose") == 0) { | 792 | } else if (strcmp(arg, "ecc_verbose") == 0) { |
583 | #ifdef CONFIG_CAVIUM_REPORT_SINGLE_BIT_ECC | 793 | #ifdef CONFIG_CAVIUM_REPORT_SINGLE_BIT_ECC |
584 | __cvmx_interrupt_ecc_report_single_bit_errors = 1; | 794 | __cvmx_interrupt_ecc_report_single_bit_errors = 1; |
585 | pr_notice("Reporting of single bit ECC errors is " | 795 | pr_notice("Reporting of single bit ECC errors is " |
586 | "turned on\n"); | 796 | "turned on\n"); |
587 | #endif | 797 | #endif |
798 | #ifdef CONFIG_KEXEC | ||
799 | } else if (strncmp(arg, "crashkernel=", 12) == 0) { | ||
800 | crashk_size = memparse(arg+12, &p); | ||
801 | if (*p == '@') | ||
802 | crashk_base = memparse(p+1, &p); | ||
803 | strcat(arcs_cmdline, " "); | ||
804 | strcat(arcs_cmdline, arg); | ||
805 | /* | ||
806 | * To do: switch parsing to new style, something like: | ||
807 | * parse_crashkernel(arg, sysinfo->system_dram_size, | ||
808 | * &crashk_size, &crashk_base); | ||
809 | */ | ||
810 | #endif | ||
588 | } else if (strlen(arcs_cmdline) + strlen(arg) + 1 < | 811 | } else if (strlen(arcs_cmdline) + strlen(arg) + 1 < |
589 | sizeof(arcs_cmdline) - 1) { | 812 | sizeof(arcs_cmdline) - 1) { |
590 | strcat(arcs_cmdline, " "); | 813 | strcat(arcs_cmdline, " "); |
@@ -619,11 +842,18 @@ void __init prom_init(void) | |||
619 | _machine_restart = octeon_restart; | 842 | _machine_restart = octeon_restart; |
620 | _machine_halt = octeon_halt; | 843 | _machine_halt = octeon_halt; |
621 | 844 | ||
845 | #ifdef CONFIG_KEXEC | ||
846 | _machine_kexec_shutdown = octeon_shutdown; | ||
847 | _machine_crash_shutdown = octeon_crash_shutdown; | ||
848 | _machine_kexec_prepare = octeon_kexec_prepare; | ||
849 | #endif | ||
850 | |||
622 | octeon_user_io_init(); | 851 | octeon_user_io_init(); |
623 | register_smp_ops(&octeon_smp_ops); | 852 | register_smp_ops(&octeon_smp_ops); |
624 | } | 853 | } |
625 | 854 | ||
626 | /* Exclude a single page from the regions obtained in plat_mem_setup. */ | 855 | /* Exclude a single page from the regions obtained in plat_mem_setup. */ |
856 | #ifndef CONFIG_CRASH_DUMP | ||
627 | static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size) | 857 | static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size) |
628 | { | 858 | { |
629 | if (addr > *mem && addr < *mem + *size) { | 859 | if (addr > *mem && addr < *mem + *size) { |
@@ -638,14 +868,21 @@ static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size) | |||
638 | *size -= PAGE_SIZE; | 868 | *size -= PAGE_SIZE; |
639 | } | 869 | } |
640 | } | 870 | } |
871 | #endif /* CONFIG_CRASH_DUMP */ | ||
641 | 872 | ||
642 | void __init plat_mem_setup(void) | 873 | void __init plat_mem_setup(void) |
643 | { | 874 | { |
644 | uint64_t mem_alloc_size; | 875 | uint64_t mem_alloc_size; |
645 | uint64_t total; | 876 | uint64_t total; |
877 | uint64_t crashk_end; | ||
878 | #ifndef CONFIG_CRASH_DUMP | ||
646 | int64_t memory; | 879 | int64_t memory; |
880 | uint64_t kernel_start; | ||
881 | uint64_t kernel_size; | ||
882 | #endif | ||
647 | 883 | ||
648 | total = 0; | 884 | total = 0; |
885 | crashk_end = 0; | ||
649 | 886 | ||
650 | /* | 887 | /* |
651 | * The Mips memory init uses the first memory location for | 888 | * The Mips memory init uses the first memory location for |
@@ -658,6 +895,17 @@ void __init plat_mem_setup(void) | |||
658 | if (mem_alloc_size > MAX_MEMORY) | 895 | if (mem_alloc_size > MAX_MEMORY) |
659 | mem_alloc_size = MAX_MEMORY; | 896 | mem_alloc_size = MAX_MEMORY; |
660 | 897 | ||
898 | /* Crashkernel ignores bootmem list. It relies on mem=X@Y option */ | ||
899 | #ifdef CONFIG_CRASH_DUMP | ||
900 | add_memory_region(RESERVE_LOW_MEM, MAX_MEMORY, BOOT_MEM_RAM); | ||
901 | total += MAX_MEMORY; | ||
902 | #else | ||
903 | #ifdef CONFIG_KEXEC | ||
904 | if (crashk_size > 0) { | ||
905 | add_memory_region(crashk_base, crashk_size, BOOT_MEM_RAM); | ||
906 | crashk_end = crashk_base + crashk_size; | ||
907 | } | ||
908 | #endif | ||
661 | /* | 909 | /* |
662 | * When allocating memory, we want incrementing addresses from | 910 | * When allocating memory, we want incrementing addresses from |
663 | * bootmem_alloc so the code in add_memory_region can merge | 911 | * bootmem_alloc so the code in add_memory_region can merge |
@@ -672,6 +920,9 @@ void __init plat_mem_setup(void) | |||
672 | CVMX_BOOTMEM_FLAG_NO_LOCKING); | 920 | CVMX_BOOTMEM_FLAG_NO_LOCKING); |
673 | if (memory >= 0) { | 921 | if (memory >= 0) { |
674 | u64 size = mem_alloc_size; | 922 | u64 size = mem_alloc_size; |
923 | #ifdef CONFIG_KEXEC | ||
924 | uint64_t end; | ||
925 | #endif | ||
675 | 926 | ||
676 | /* | 927 | /* |
677 | * exclude a page at the beginning and end of | 928 | * exclude a page at the beginning and end of |
@@ -684,20 +935,67 @@ void __init plat_mem_setup(void) | |||
684 | memory_exclude_page(CVMX_PCIE_BAR1_PHYS_BASE + | 935 | memory_exclude_page(CVMX_PCIE_BAR1_PHYS_BASE + |
685 | CVMX_PCIE_BAR1_PHYS_SIZE, | 936 | CVMX_PCIE_BAR1_PHYS_SIZE, |
686 | &memory, &size); | 937 | &memory, &size); |
938 | #ifdef CONFIG_KEXEC | ||
939 | end = memory + mem_alloc_size; | ||
687 | 940 | ||
688 | /* | 941 | /* |
689 | * This function automatically merges address | 942 | * This function automatically merges address regions |
690 | * regions next to each other if they are | 943 | * next to each other if they are received in |
691 | * received in incrementing order. | 944 | * incrementing order |
692 | */ | 945 | */ |
693 | if (size) | 946 | if (memory < crashk_base && end > crashk_end) { |
694 | add_memory_region(memory, size, BOOT_MEM_RAM); | 947 | /* region is fully in */ |
948 | add_memory_region(memory, | ||
949 | crashk_base - memory, | ||
950 | BOOT_MEM_RAM); | ||
951 | total += crashk_base - memory; | ||
952 | add_memory_region(crashk_end, | ||
953 | end - crashk_end, | ||
954 | BOOT_MEM_RAM); | ||
955 | total += end - crashk_end; | ||
956 | continue; | ||
957 | } | ||
958 | |||
959 | if (memory >= crashk_base && end <= crashk_end) | ||
960 | /* | ||
961 | * Entire memory region is within the new | ||
962 | * kernel's memory, ignore it. | ||
963 | */ | ||
964 | continue; | ||
965 | |||
966 | if (memory > crashk_base && memory < crashk_end && | ||
967 | end > crashk_end) { | ||
968 | /* | ||
969 | * Overlap with the beginning of the region, | ||
970 | * reserve the beginning. | ||
971 | */ | ||
972 | mem_alloc_size -= crashk_end - memory; | ||
973 | memory = crashk_end; | ||
974 | } else if (memory < crashk_base && end > crashk_base && | ||
975 | end < crashk_end) | ||
976 | /* | ||
977 | * Overlap with the beginning of the region, | ||
978 | * chop of end. | ||
979 | */ | ||
980 | mem_alloc_size -= end - crashk_base; | ||
981 | #endif | ||
982 | add_memory_region(memory, mem_alloc_size, BOOT_MEM_RAM); | ||
695 | total += mem_alloc_size; | 983 | total += mem_alloc_size; |
984 | /* Recovering mem_alloc_size */ | ||
985 | mem_alloc_size = 4 << 20; | ||
696 | } else { | 986 | } else { |
697 | break; | 987 | break; |
698 | } | 988 | } |
699 | } | 989 | } |
700 | cvmx_bootmem_unlock(); | 990 | cvmx_bootmem_unlock(); |
991 | /* Add the memory region for the kernel. */ | ||
992 | kernel_start = (unsigned long) _text; | ||
993 | kernel_size = ALIGN(_end - _text, 0x100000); | ||
994 | |||
995 | /* Adjust for physical offset. */ | ||
996 | kernel_start &= ~0xffffffff80000000ULL; | ||
997 | add_memory_region(kernel_start, kernel_size, BOOT_MEM_RAM); | ||
998 | #endif /* CONFIG_CRASH_DUMP */ | ||
701 | 999 | ||
702 | #ifdef CONFIG_CAVIUM_RESERVE32 | 1000 | #ifdef CONFIG_CAVIUM_RESERVE32 |
703 | /* | 1001 | /* |
diff --git a/arch/mips/include/asm/octeon/cvmx-bootmem.h b/arch/mips/include/asm/octeon/cvmx-bootmem.h index 877845b84b14..42db2be663f1 100644 --- a/arch/mips/include/asm/octeon/cvmx-bootmem.h +++ b/arch/mips/include/asm/octeon/cvmx-bootmem.h | |||
@@ -370,4 +370,6 @@ void cvmx_bootmem_lock(void); | |||
370 | */ | 370 | */ |
371 | void cvmx_bootmem_unlock(void); | 371 | void cvmx_bootmem_unlock(void); |
372 | 372 | ||
373 | extern struct cvmx_bootmem_desc *cvmx_bootmem_get_desc(void); | ||
374 | |||
373 | #endif /* __CVMX_BOOTMEM_H__ */ | 375 | #endif /* __CVMX_BOOTMEM_H__ */ |
diff --git a/arch/mips/kernel/crash_dump.c b/arch/mips/kernel/crash_dump.c index d9ec3898f9fa..35bed0d2342c 100644 --- a/arch/mips/kernel/crash_dump.c +++ b/arch/mips/kernel/crash_dump.c | |||
@@ -3,8 +3,6 @@ | |||
3 | #include <linux/crash_dump.h> | 3 | #include <linux/crash_dump.h> |
4 | #include <asm/uaccess.h> | 4 | #include <asm/uaccess.h> |
5 | 5 | ||
6 | unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX; | ||
7 | |||
8 | static int __init parse_savemaxmem(char *p) | 6 | static int __init parse_savemaxmem(char *p) |
9 | { | 7 | { |
10 | if (p) | 8 | if (p) |
diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S index 0b108587f065..e4142c5f7c2b 100644 --- a/arch/mips/kernel/relocate_kernel.S +++ b/arch/mips/kernel/relocate_kernel.S | |||
@@ -78,7 +78,19 @@ done: | |||
78 | LONG_S zero,(t0) | 78 | LONG_S zero,(t0) |
79 | #endif | 79 | #endif |
80 | 80 | ||
81 | #ifdef CONFIG_CPU_CAVIUM_OCTEON | ||
82 | /* We need to flush I-cache before jumping to new kernel. | ||
83 | * Unfortunatelly, this code is cpu-specific. | ||
84 | */ | ||
85 | .set push | ||
86 | .set noreorder | ||
87 | syncw | ||
88 | syncw | ||
89 | synci 0($0) | ||
90 | .set pop | ||
91 | #else | ||
81 | sync | 92 | sync |
93 | #endif | ||
82 | /* jump to kexec_start_address */ | 94 | /* jump to kexec_start_address */ |
83 | j s1 | 95 | j s1 |
84 | END(relocate_new_kernel) | 96 | END(relocate_new_kernel) |
@@ -110,7 +122,14 @@ LEAF(kexec_smp_wait) | |||
110 | 1: LONG_L s0, (t0) | 122 | 1: LONG_L s0, (t0) |
111 | bne s0, zero,1b | 123 | bne s0, zero,1b |
112 | 124 | ||
125 | #ifdef CONFIG_CPU_CAVIUM_OCTEON | ||
126 | .set push | ||
127 | .set noreorder | ||
128 | synci 0($0) | ||
129 | .set pop | ||
130 | #else | ||
113 | sync | 131 | sync |
132 | #endif | ||
114 | j s1 | 133 | j s1 |
115 | END(kexec_smp_wait) | 134 | END(kexec_smp_wait) |
116 | #endif | 135 | #endif |