diff options
| author | Paul Mundt <lethal@linux-sh.org> | 2010-05-13 04:48:05 -0400 |
|---|---|---|
| committer | Paul Mundt <lethal@linux-sh.org> | 2010-05-13 04:48:05 -0400 |
| commit | ef4ed97d6bd91aa41907181e80a7feaf2721719a (patch) | |
| tree | adc44e858c150c41ebf1dd7c6ee2f6bcbac75502 /arch | |
| parent | c5eb5b372e7ea18a5eeb6b5192a6369967cb1afe (diff) | |
| parent | 21823259a70b7a2a21eea1d48c25a6f38896dd11 (diff) | |
Merge branch 'sh/lmb'
Conflicts:
arch/sh/kernel/setup.c
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/sh/include/asm/io_generic.h | 1 | ||||
| -rw-r--r-- | arch/sh/include/asm/kexec.h | 8 | ||||
| -rw-r--r-- | arch/sh/include/asm/machvec.h | 2 | ||||
| -rw-r--r-- | arch/sh/include/asm/mmzone.h | 3 | ||||
| -rw-r--r-- | arch/sh/include/asm/page.h | 2 | ||||
| -rw-r--r-- | arch/sh/include/asm/setup.h | 1 | ||||
| -rw-r--r-- | arch/sh/kernel/machine_kexec.c | 59 | ||||
| -rw-r--r-- | arch/sh/kernel/machvec.c | 1 | ||||
| -rw-r--r-- | arch/sh/kernel/setup.c | 228 | ||||
| -rw-r--r-- | arch/sh/mm/init.c | 173 | ||||
| -rw-r--r-- | arch/sh/mm/pmb.c | 2 |
11 files changed, 271 insertions, 209 deletions
diff --git a/arch/sh/include/asm/io_generic.h b/arch/sh/include/asm/io_generic.h index 1e5d375f55dc..491df93cbf8e 100644 --- a/arch/sh/include/asm/io_generic.h +++ b/arch/sh/include/asm/io_generic.h | |||
| @@ -38,5 +38,6 @@ void IO_CONCAT(__IO_PREFIX,iounmap)(void *addr); | |||
| 38 | 38 | ||
| 39 | void __iomem *IO_CONCAT(__IO_PREFIX,ioport_map)(unsigned long addr, unsigned int size); | 39 | void __iomem *IO_CONCAT(__IO_PREFIX,ioport_map)(unsigned long addr, unsigned int size); |
| 40 | void IO_CONCAT(__IO_PREFIX,ioport_unmap)(void __iomem *addr); | 40 | void IO_CONCAT(__IO_PREFIX,ioport_unmap)(void __iomem *addr); |
| 41 | void IO_CONCAT(__IO_PREFIX,mem_init)(void); | ||
| 41 | 42 | ||
| 42 | #undef __IO_PREFIX | 43 | #undef __IO_PREFIX |
diff --git a/arch/sh/include/asm/kexec.h b/arch/sh/include/asm/kexec.h index 765a5e1660fc..ad6ef8a275ee 100644 --- a/arch/sh/include/asm/kexec.h +++ b/arch/sh/include/asm/kexec.h | |||
| @@ -26,6 +26,10 @@ | |||
| 26 | /* The native architecture */ | 26 | /* The native architecture */ |
| 27 | #define KEXEC_ARCH KEXEC_ARCH_SH | 27 | #define KEXEC_ARCH KEXEC_ARCH_SH |
| 28 | 28 | ||
| 29 | #ifdef CONFIG_KEXEC | ||
| 30 | /* arch/sh/kernel/machine_kexec.c */ | ||
| 31 | void reserve_crashkernel(void); | ||
| 32 | |||
| 29 | static inline void crash_setup_regs(struct pt_regs *newregs, | 33 | static inline void crash_setup_regs(struct pt_regs *newregs, |
| 30 | struct pt_regs *oldregs) | 34 | struct pt_regs *oldregs) |
| 31 | { | 35 | { |
| @@ -59,4 +63,8 @@ static inline void crash_setup_regs(struct pt_regs *newregs, | |||
| 59 | newregs->pc = (unsigned long)current_text_addr(); | 63 | newregs->pc = (unsigned long)current_text_addr(); |
| 60 | } | 64 | } |
| 61 | } | 65 | } |
| 66 | #else | ||
| 67 | static inline void reserve_crashkernel(void) { } | ||
| 68 | #endif /* CONFIG_KEXEC */ | ||
| 69 | |||
| 62 | #endif /* __ASM_SH_KEXEC_H */ | 70 | #endif /* __ASM_SH_KEXEC_H */ |
diff --git a/arch/sh/include/asm/machvec.h b/arch/sh/include/asm/machvec.h index 9c30955630ff..bc0218cb72e1 100644 --- a/arch/sh/include/asm/machvec.h +++ b/arch/sh/include/asm/machvec.h | |||
| @@ -49,6 +49,8 @@ struct sh_machine_vector { | |||
| 49 | 49 | ||
| 50 | int (*mv_clk_init)(void); | 50 | int (*mv_clk_init)(void); |
| 51 | int (*mv_mode_pins)(void); | 51 | int (*mv_mode_pins)(void); |
| 52 | |||
| 53 | void (*mv_mem_init)(void); | ||
| 52 | }; | 54 | }; |
| 53 | 55 | ||
| 54 | extern struct sh_machine_vector sh_mv; | 56 | extern struct sh_machine_vector sh_mv; |
diff --git a/arch/sh/include/asm/mmzone.h b/arch/sh/include/asm/mmzone.h index 7f5363b29ba0..8887baff5eff 100644 --- a/arch/sh/include/asm/mmzone.h +++ b/arch/sh/include/asm/mmzone.h | |||
| @@ -42,9 +42,10 @@ setup_bootmem_node(int nid, unsigned long start, unsigned long end) | |||
| 42 | void __init plat_mem_setup(void); | 42 | void __init plat_mem_setup(void); |
| 43 | 43 | ||
| 44 | /* arch/sh/kernel/setup.c */ | 44 | /* arch/sh/kernel/setup.c */ |
| 45 | void __init setup_bootmem_allocator(unsigned long start_pfn); | ||
| 46 | void __init __add_active_range(unsigned int nid, unsigned long start_pfn, | 45 | void __init __add_active_range(unsigned int nid, unsigned long start_pfn, |
| 47 | unsigned long end_pfn); | 46 | unsigned long end_pfn); |
| 47 | /* arch/sh/mm/init.c */ | ||
| 48 | void __init allocate_pgdat(unsigned int nid); | ||
| 48 | 49 | ||
| 49 | #endif /* __KERNEL__ */ | 50 | #endif /* __KERNEL__ */ |
| 50 | #endif /* __ASM_SH_MMZONE_H */ | 51 | #endif /* __ASM_SH_MMZONE_H */ |
diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index 0152c040f6c3..fb703d120d09 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h | |||
| @@ -49,7 +49,7 @@ | |||
| 49 | 49 | ||
| 50 | extern unsigned long shm_align_mask; | 50 | extern unsigned long shm_align_mask; |
| 51 | extern unsigned long max_low_pfn, min_low_pfn; | 51 | extern unsigned long max_low_pfn, min_low_pfn; |
| 52 | extern unsigned long memory_start, memory_end; | 52 | extern unsigned long memory_start, memory_end, memory_limit; |
| 53 | 53 | ||
| 54 | static inline unsigned long | 54 | static inline unsigned long |
| 55 | pages_do_alias(unsigned long addr1, unsigned long addr2) | 55 | pages_do_alias(unsigned long addr1, unsigned long addr2) |
diff --git a/arch/sh/include/asm/setup.h b/arch/sh/include/asm/setup.h index 4758325bb24a..01fa17a3d759 100644 --- a/arch/sh/include/asm/setup.h +++ b/arch/sh/include/asm/setup.h | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #define COMMAND_LINE ((char *) (PARAM+0x100)) | 19 | #define COMMAND_LINE ((char *) (PARAM+0x100)) |
| 20 | 20 | ||
| 21 | void sh_mv_setup(void); | 21 | void sh_mv_setup(void); |
| 22 | void check_for_initrd(void); | ||
| 22 | 23 | ||
| 23 | #endif /* __KERNEL__ */ | 24 | #endif /* __KERNEL__ */ |
| 24 | 25 | ||
diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index 0e90c7f9564f..5a559e666eb3 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | * This source code is licensed under the GNU General Public License, | 8 | * This source code is licensed under the GNU General Public License, |
| 9 | * Version 2. See the file COPYING for more details. | 9 | * Version 2. See the file COPYING for more details. |
| 10 | */ | 10 | */ |
| 11 | |||
| 12 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
| 13 | #include <linux/kexec.h> | 12 | #include <linux/kexec.h> |
| 14 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
| @@ -16,6 +15,7 @@ | |||
| 16 | #include <linux/numa.h> | 15 | #include <linux/numa.h> |
| 17 | #include <linux/ftrace.h> | 16 | #include <linux/ftrace.h> |
| 18 | #include <linux/suspend.h> | 17 | #include <linux/suspend.h> |
| 18 | #include <linux/lmb.h> | ||
| 19 | #include <asm/pgtable.h> | 19 | #include <asm/pgtable.h> |
| 20 | #include <asm/pgalloc.h> | 20 | #include <asm/pgalloc.h> |
| 21 | #include <asm/mmu_context.h> | 21 | #include <asm/mmu_context.h> |
| @@ -151,3 +151,60 @@ void arch_crash_save_vmcoreinfo(void) | |||
| 151 | VMCOREINFO_CONFIG(X2TLB); | 151 | VMCOREINFO_CONFIG(X2TLB); |
| 152 | #endif | 152 | #endif |
| 153 | } | 153 | } |
| 154 | |||
| 155 | void __init reserve_crashkernel(void) | ||
| 156 | { | ||
| 157 | unsigned long long crash_size, crash_base; | ||
| 158 | int ret; | ||
| 159 | |||
| 160 | /* this is necessary because of lmb_phys_mem_size() */ | ||
| 161 | lmb_analyze(); | ||
| 162 | |||
| 163 | ret = parse_crashkernel(boot_command_line, lmb_phys_mem_size(), | ||
| 164 | &crash_size, &crash_base); | ||
| 165 | if (ret == 0 && crash_size > 0) { | ||
| 166 | crashk_res.start = crash_base; | ||
| 167 | crashk_res.end = crash_base + crash_size - 1; | ||
| 168 | } | ||
| 169 | |||
| 170 | if (crashk_res.end == crashk_res.start) | ||
| 171 | goto disable; | ||
| 172 | |||
| 173 | crash_size = PAGE_ALIGN(crashk_res.end - crashk_res.start + 1); | ||
| 174 | if (!crashk_res.start) { | ||
| 175 | unsigned long max = lmb_end_of_DRAM() - memory_limit; | ||
| 176 | crashk_res.start = __lmb_alloc_base(crash_size, PAGE_SIZE, max); | ||
| 177 | if (!crashk_res.start) { | ||
| 178 | pr_err("crashkernel allocation failed\n"); | ||
| 179 | goto disable; | ||
| 180 | } | ||
| 181 | } else { | ||
| 182 | ret = lmb_reserve(crashk_res.start, crash_size); | ||
| 183 | if (unlikely(ret < 0)) { | ||
| 184 | pr_err("crashkernel reservation failed - " | ||
| 185 | "memory is in use\n"); | ||
| 186 | goto disable; | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | crashk_res.end = crashk_res.start + crash_size - 1; | ||
| 191 | |||
| 192 | /* | ||
| 193 | * Crash kernel trumps memory limit | ||
| 194 | */ | ||
| 195 | if ((lmb_end_of_DRAM() - memory_limit) <= crashk_res.end) { | ||
| 196 | memory_limit = 0; | ||
| 197 | pr_info("Disabled memory limit for crashkernel\n"); | ||
| 198 | } | ||
| 199 | |||
| 200 | pr_info("Reserving %ldMB of memory at 0x%08lx " | ||
| 201 | "for crashkernel (System RAM: %ldMB)\n", | ||
| 202 | (unsigned long)(crash_size >> 20), | ||
| 203 | (unsigned long)(crashk_res.start), | ||
| 204 | (unsigned long)(lmb_phys_mem_size() >> 20)); | ||
| 205 | |||
| 206 | return; | ||
| 207 | |||
| 208 | disable: | ||
| 209 | crashk_res.start = crashk_res.end = 0; | ||
| 210 | } | ||
diff --git a/arch/sh/kernel/machvec.c b/arch/sh/kernel/machvec.c index 1652340ba3f2..85cfaf916fdc 100644 --- a/arch/sh/kernel/machvec.c +++ b/arch/sh/kernel/machvec.c | |||
| @@ -131,6 +131,7 @@ void __init sh_mv_setup(void) | |||
| 131 | mv_set(ioport_unmap); | 131 | mv_set(ioport_unmap); |
| 132 | mv_set(irq_demux); | 132 | mv_set(irq_demux); |
| 133 | mv_set(mode_pins); | 133 | mv_set(mode_pins); |
| 134 | mv_set(mem_init); | ||
| 134 | 135 | ||
| 135 | if (!sh_mv.mv_nr_irqs) | 136 | if (!sh_mv.mv_nr_irqs) |
| 136 | sh_mv.mv_nr_irqs = NR_IRQS; | 137 | sh_mv.mv_nr_irqs = NR_IRQS; |
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 4f1585f41f2b..272734681d29 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | * This file handles the architecture-dependent parts of initialization | 4 | * This file handles the architecture-dependent parts of initialization |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 1999 Niibe Yutaka | 6 | * Copyright (C) 1999 Niibe Yutaka |
| 7 | * Copyright (C) 2002 - 2007 Paul Mundt | 7 | * Copyright (C) 2002 - 2010 Paul Mundt |
| 8 | */ | 8 | */ |
| 9 | #include <linux/screen_info.h> | 9 | #include <linux/screen_info.h> |
| 10 | #include <linux/ioport.h> | 10 | #include <linux/ioport.h> |
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <asm/clock.h> | 41 | #include <asm/clock.h> |
| 42 | #include <asm/smp.h> | 42 | #include <asm/smp.h> |
| 43 | #include <asm/mmu_context.h> | 43 | #include <asm/mmu_context.h> |
| 44 | #include <asm/mmzone.h> | ||
| 44 | 45 | ||
| 45 | /* | 46 | /* |
| 46 | * Initialize loops_per_jiffy as 10000000 (1000MIPS). | 47 | * Initialize loops_per_jiffy as 10000000 (1000MIPS). |
| @@ -94,6 +95,7 @@ unsigned long memory_start; | |||
| 94 | EXPORT_SYMBOL(memory_start); | 95 | EXPORT_SYMBOL(memory_start); |
| 95 | unsigned long memory_end = 0; | 96 | unsigned long memory_end = 0; |
| 96 | EXPORT_SYMBOL(memory_end); | 97 | EXPORT_SYMBOL(memory_end); |
| 98 | unsigned long memory_limit = 0; | ||
| 97 | 99 | ||
| 98 | static struct resource mem_resources[MAX_NUMNODES]; | 100 | static struct resource mem_resources[MAX_NUMNODES]; |
| 99 | 101 | ||
| @@ -101,94 +103,18 @@ int l1i_cache_shape, l1d_cache_shape, l2_cache_shape; | |||
| 101 | 103 | ||
| 102 | static int __init early_parse_mem(char *p) | 104 | static int __init early_parse_mem(char *p) |
| 103 | { | 105 | { |
| 104 | unsigned long size; | 106 | if (!p) |
| 107 | return 1; | ||
| 105 | 108 | ||
| 106 | memory_start = (unsigned long)__va(__MEMORY_START); | 109 | memory_limit = PAGE_ALIGN(memparse(p, &p)); |
| 107 | size = memparse(p, &p); | ||
| 108 | 110 | ||
| 109 | if (size > __MEMORY_SIZE) { | 111 | pr_notice("Memory limited to %ldMB\n", memory_limit >> 20); |
| 110 | printk(KERN_ERR | ||
| 111 | "Using mem= to increase the size of kernel memory " | ||
| 112 | "is not allowed.\n" | ||
| 113 | " Recompile the kernel with the correct value for " | ||
| 114 | "CONFIG_MEMORY_SIZE.\n"); | ||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | |||
| 118 | memory_end = memory_start + size; | ||
| 119 | 112 | ||
| 120 | return 0; | 113 | return 0; |
| 121 | } | 114 | } |
| 122 | early_param("mem", early_parse_mem); | 115 | early_param("mem", early_parse_mem); |
| 123 | 116 | ||
| 124 | /* | 117 | void __init check_for_initrd(void) |
| 125 | * Register fully available low RAM pages with the bootmem allocator. | ||
| 126 | */ | ||
| 127 | static void __init register_bootmem_low_pages(void) | ||
| 128 | { | ||
| 129 | unsigned long curr_pfn, last_pfn, pages; | ||
| 130 | |||
| 131 | /* | ||
| 132 | * We are rounding up the start address of usable memory: | ||
| 133 | */ | ||
| 134 | curr_pfn = PFN_UP(__MEMORY_START); | ||
| 135 | |||
| 136 | /* | ||
| 137 | * ... and at the end of the usable range downwards: | ||
| 138 | */ | ||
| 139 | last_pfn = PFN_DOWN(__pa(memory_end)); | ||
| 140 | |||
| 141 | if (last_pfn > max_low_pfn) | ||
| 142 | last_pfn = max_low_pfn; | ||
| 143 | |||
| 144 | pages = last_pfn - curr_pfn; | ||
| 145 | free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages)); | ||
| 146 | } | ||
| 147 | |||
| 148 | #ifdef CONFIG_KEXEC | ||
| 149 | static void __init reserve_crashkernel(void) | ||
| 150 | { | ||
| 151 | unsigned long long free_mem; | ||
| 152 | unsigned long long crash_size, crash_base; | ||
| 153 | void *vp; | ||
| 154 | int ret; | ||
| 155 | |||
| 156 | free_mem = ((unsigned long long)max_low_pfn - min_low_pfn) << PAGE_SHIFT; | ||
| 157 | |||
| 158 | ret = parse_crashkernel(boot_command_line, free_mem, | ||
| 159 | &crash_size, &crash_base); | ||
| 160 | if (ret == 0 && crash_size) { | ||
| 161 | if (crash_base <= 0) { | ||
| 162 | vp = alloc_bootmem_nopanic(crash_size); | ||
| 163 | if (!vp) { | ||
| 164 | printk(KERN_INFO "crashkernel allocation " | ||
| 165 | "failed\n"); | ||
| 166 | return; | ||
| 167 | } | ||
| 168 | crash_base = __pa(vp); | ||
| 169 | } else if (reserve_bootmem(crash_base, crash_size, | ||
| 170 | BOOTMEM_EXCLUSIVE) < 0) { | ||
| 171 | printk(KERN_INFO "crashkernel reservation failed - " | ||
| 172 | "memory is in use\n"); | ||
| 173 | return; | ||
| 174 | } | ||
| 175 | |||
| 176 | printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " | ||
| 177 | "for crashkernel (System RAM: %ldMB)\n", | ||
| 178 | (unsigned long)(crash_size >> 20), | ||
| 179 | (unsigned long)(crash_base >> 20), | ||
| 180 | (unsigned long)(free_mem >> 20)); | ||
| 181 | crashk_res.start = crash_base; | ||
| 182 | crashk_res.end = crash_base + crash_size - 1; | ||
| 183 | insert_resource(&iomem_resource, &crashk_res); | ||
| 184 | } | ||
| 185 | } | ||
| 186 | #else | ||
| 187 | static inline void __init reserve_crashkernel(void) | ||
| 188 | {} | ||
| 189 | #endif | ||
| 190 | |||
| 191 | static void __init check_for_initrd(void) | ||
| 192 | { | 118 | { |
| 193 | #ifdef CONFIG_BLK_DEV_INITRD | 119 | #ifdef CONFIG_BLK_DEV_INITRD |
| 194 | unsigned long start, end; | 120 | unsigned long start, end; |
| @@ -235,7 +161,7 @@ static void __init check_for_initrd(void) | |||
| 235 | initrd_start = (unsigned long)__va(__pa(start)); | 161 | initrd_start = (unsigned long)__va(__pa(start)); |
| 236 | initrd_end = initrd_start + INITRD_SIZE; | 162 | initrd_end = initrd_start + INITRD_SIZE; |
| 237 | 163 | ||
| 238 | reserve_bootmem(__pa(initrd_start), INITRD_SIZE, BOOTMEM_DEFAULT); | 164 | lmb_reserve(__pa(initrd_start), INITRD_SIZE); |
| 239 | 165 | ||
| 240 | return; | 166 | return; |
| 241 | 167 | ||
| @@ -265,13 +191,18 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn, | |||
| 265 | unsigned long end_pfn) | 191 | unsigned long end_pfn) |
| 266 | { | 192 | { |
| 267 | struct resource *res = &mem_resources[nid]; | 193 | struct resource *res = &mem_resources[nid]; |
| 194 | unsigned long start, end; | ||
| 268 | 195 | ||
| 269 | WARN_ON(res->name); /* max one active range per node for now */ | 196 | WARN_ON(res->name); /* max one active range per node for now */ |
| 270 | 197 | ||
| 198 | start = start_pfn << PAGE_SHIFT; | ||
| 199 | end = end_pfn << PAGE_SHIFT; | ||
| 200 | |||
| 271 | res->name = "System RAM"; | 201 | res->name = "System RAM"; |
| 272 | res->start = start_pfn << PAGE_SHIFT; | 202 | res->start = start; |
| 273 | res->end = (end_pfn << PAGE_SHIFT) - 1; | 203 | res->end = end - 1; |
| 274 | res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; | 204 | res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; |
| 205 | |||
| 275 | if (request_resource(&iomem_resource, res)) { | 206 | if (request_resource(&iomem_resource, res)) { |
| 276 | pr_err("unable to request memory_resource 0x%lx 0x%lx\n", | 207 | pr_err("unable to request memory_resource 0x%lx 0x%lx\n", |
| 277 | start_pfn, end_pfn); | 208 | start_pfn, end_pfn); |
| @@ -287,100 +218,18 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn, | |||
| 287 | request_resource(res, &data_resource); | 218 | request_resource(res, &data_resource); |
| 288 | request_resource(res, &bss_resource); | 219 | request_resource(res, &bss_resource); |
| 289 | 220 | ||
| 290 | add_active_range(nid, start_pfn, end_pfn); | ||
| 291 | } | ||
| 292 | |||
| 293 | void __init setup_bootmem_allocator(unsigned long free_pfn) | ||
| 294 | { | ||
| 295 | unsigned long bootmap_size; | ||
| 296 | unsigned long bootmap_pages, bootmem_paddr; | ||
| 297 | u64 total_pages = (lmb_end_of_DRAM() - __MEMORY_START) >> PAGE_SHIFT; | ||
| 298 | int i; | ||
| 299 | |||
| 300 | bootmap_pages = bootmem_bootmap_pages(total_pages); | ||
| 301 | |||
| 302 | bootmem_paddr = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE); | ||
| 303 | |||
| 304 | /* | ||
| 305 | * Find a proper area for the bootmem bitmap. After this | ||
| 306 | * bootstrap step all allocations (until the page allocator | ||
| 307 | * is intact) must be done via bootmem_alloc(). | ||
| 308 | */ | ||
| 309 | bootmap_size = init_bootmem_node(NODE_DATA(0), | ||
| 310 | bootmem_paddr >> PAGE_SHIFT, | ||
| 311 | min_low_pfn, max_low_pfn); | ||
| 312 | |||
| 313 | /* Add active regions with valid PFNs. */ | ||
| 314 | for (i = 0; i < lmb.memory.cnt; i++) { | ||
| 315 | unsigned long start_pfn, end_pfn; | ||
| 316 | start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT; | ||
| 317 | end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i); | ||
| 318 | __add_active_range(0, start_pfn, end_pfn); | ||
| 319 | } | ||
| 320 | |||
| 321 | /* | ||
| 322 | * Add all physical memory to the bootmem map and mark each | ||
| 323 | * area as present. | ||
| 324 | */ | ||
| 325 | register_bootmem_low_pages(); | ||
| 326 | |||
| 327 | /* Reserve the sections we're already using. */ | ||
| 328 | for (i = 0; i < lmb.reserved.cnt; i++) | ||
| 329 | reserve_bootmem(lmb.reserved.region[i].base, | ||
| 330 | lmb_size_bytes(&lmb.reserved, i), | ||
| 331 | BOOTMEM_DEFAULT); | ||
| 332 | |||
| 333 | node_set_online(0); | ||
| 334 | |||
| 335 | sparse_memory_present_with_active_regions(0); | ||
| 336 | |||
| 337 | check_for_initrd(); | ||
| 338 | |||
| 339 | reserve_crashkernel(); | ||
| 340 | } | ||
| 341 | |||
| 342 | #ifndef CONFIG_NEED_MULTIPLE_NODES | ||
| 343 | static void __init setup_memory(void) | ||
| 344 | { | ||
| 345 | unsigned long start_pfn; | ||
| 346 | u64 base = min_low_pfn << PAGE_SHIFT; | ||
| 347 | u64 size = (max_low_pfn << PAGE_SHIFT) - base; | ||
| 348 | |||
| 349 | /* | 221 | /* |
| 350 | * Partially used pages are not usable - thus | 222 | * Also make sure that there is a PMB mapping that covers this |
| 351 | * we are rounding upwards: | 223 | * range before we attempt to activate it, to avoid reset by MMU. |
| 224 | * We can hit this path with NUMA or memory hot-add. | ||
| 352 | */ | 225 | */ |
| 353 | start_pfn = PFN_UP(__pa(_end)); | 226 | pmb_bolt_mapping((unsigned long)__va(start), start, end - start, |
| 227 | PAGE_KERNEL); | ||
| 354 | 228 | ||
| 355 | lmb_add(base, size); | 229 | add_active_range(nid, start_pfn, end_pfn); |
| 356 | |||
| 357 | /* | ||
| 358 | * Reserve the kernel text and | ||
| 359 | * Reserve the bootmem bitmap. We do this in two steps (first step | ||
| 360 | * was init_bootmem()), because this catches the (definitely buggy) | ||
| 361 | * case of us accidentally initializing the bootmem allocator with | ||
| 362 | * an invalid RAM area. | ||
| 363 | */ | ||
| 364 | lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET, | ||
| 365 | (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) - | ||
| 366 | (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET)); | ||
| 367 | |||
| 368 | /* | ||
| 369 | * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET. | ||
| 370 | */ | ||
| 371 | if (CONFIG_ZERO_PAGE_OFFSET != 0) | ||
| 372 | lmb_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET); | ||
| 373 | |||
| 374 | lmb_analyze(); | ||
| 375 | lmb_dump_all(); | ||
| 376 | |||
| 377 | setup_bootmem_allocator(start_pfn); | ||
| 378 | } | 230 | } |
| 379 | #else | ||
| 380 | extern void __init setup_memory(void); | ||
| 381 | #endif | ||
| 382 | 231 | ||
| 383 | void __init __attribute__ ((weak)) plat_early_device_setup(void) | 232 | void __init __weak plat_early_device_setup(void) |
| 384 | { | 233 | { |
| 385 | } | 234 | } |
| 386 | 235 | ||
| @@ -421,10 +270,6 @@ void __init setup_arch(char **cmdline_p) | |||
| 421 | bss_resource.start = virt_to_phys(__bss_start); | 270 | bss_resource.start = virt_to_phys(__bss_start); |
| 422 | bss_resource.end = virt_to_phys(_ebss)-1; | 271 | bss_resource.end = virt_to_phys(_ebss)-1; |
| 423 | 272 | ||
| 424 | memory_start = (unsigned long)__va(__MEMORY_START); | ||
| 425 | if (!memory_end) | ||
| 426 | memory_end = memory_start + __MEMORY_SIZE; | ||
| 427 | |||
| 428 | #ifdef CONFIG_CMDLINE_OVERWRITE | 273 | #ifdef CONFIG_CMDLINE_OVERWRITE |
| 429 | strlcpy(command_line, CONFIG_CMDLINE, sizeof(command_line)); | 274 | strlcpy(command_line, CONFIG_CMDLINE, sizeof(command_line)); |
| 430 | #else | 275 | #else |
| @@ -441,39 +286,18 @@ void __init setup_arch(char **cmdline_p) | |||
| 441 | 286 | ||
| 442 | parse_early_param(); | 287 | parse_early_param(); |
| 443 | 288 | ||
| 444 | uncached_init(); | ||
| 445 | |||
| 446 | plat_early_device_setup(); | 289 | plat_early_device_setup(); |
| 447 | 290 | ||
| 448 | /* Let earlyprintk output early console messages */ | ||
| 449 | early_platform_driver_probe("earlyprintk", 1, 1); | ||
| 450 | |||
| 451 | sh_mv_setup(); | 291 | sh_mv_setup(); |
| 452 | 292 | ||
| 453 | /* | 293 | /* Let earlyprintk output early console messages */ |
| 454 | * Find the highest page frame number we have available | 294 | early_platform_driver_probe("earlyprintk", 1, 1); |
| 455 | */ | ||
| 456 | max_pfn = PFN_DOWN(__pa(memory_end)); | ||
| 457 | |||
| 458 | /* | ||
| 459 | * Determine low and high memory ranges: | ||
| 460 | */ | ||
| 461 | max_low_pfn = max_pfn; | ||
| 462 | min_low_pfn = __MEMORY_START >> PAGE_SHIFT; | ||
| 463 | |||
| 464 | nodes_clear(node_online_map); | ||
| 465 | 295 | ||
| 466 | pmb_init(); | 296 | paging_init(); |
| 467 | lmb_init(); | ||
| 468 | setup_memory(); | ||
| 469 | sparse_init(); | ||
| 470 | 297 | ||
| 471 | #ifdef CONFIG_DUMMY_CONSOLE | 298 | #ifdef CONFIG_DUMMY_CONSOLE |
| 472 | conswitchp = &dummy_con; | 299 | conswitchp = &dummy_con; |
| 473 | #endif | 300 | #endif |
| 474 | paging_init(); | ||
| 475 | |||
| 476 | ioremap_fixed_init(); | ||
| 477 | 301 | ||
| 478 | /* Perform the machine specific initialisation */ | 302 | /* Perform the machine specific initialisation */ |
| 479 | if (likely(sh_mv.mv_setup)) | 303 | if (likely(sh_mv.mv_setup)) |
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index c505de61a5ca..7f3cb5254abb 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * linux/arch/sh/mm/init.c | 2 | * linux/arch/sh/mm/init.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 1999 Niibe Yutaka | 4 | * Copyright (C) 1999 Niibe Yutaka |
| 5 | * Copyright (C) 2002 - 2007 Paul Mundt | 5 | * Copyright (C) 2002 - 2010 Paul Mundt |
| 6 | * | 6 | * |
| 7 | * Based on linux/arch/i386/mm/init.c: | 7 | * Based on linux/arch/i386/mm/init.c: |
| 8 | * Copyright (C) 1995 Linus Torvalds | 8 | * Copyright (C) 1995 Linus Torvalds |
| @@ -16,17 +16,31 @@ | |||
| 16 | #include <linux/pagemap.h> | 16 | #include <linux/pagemap.h> |
| 17 | #include <linux/percpu.h> | 17 | #include <linux/percpu.h> |
| 18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
| 19 | #include <linux/lmb.h> | ||
| 20 | #include <linux/kexec.h> | ||
| 19 | #include <linux/dma-mapping.h> | 21 | #include <linux/dma-mapping.h> |
| 20 | #include <asm/mmu_context.h> | 22 | #include <asm/mmu_context.h> |
| 23 | #include <asm/mmzone.h> | ||
| 21 | #include <asm/tlb.h> | 24 | #include <asm/tlb.h> |
| 22 | #include <asm/cacheflush.h> | 25 | #include <asm/cacheflush.h> |
| 23 | #include <asm/sections.h> | 26 | #include <asm/sections.h> |
| 27 | #include <asm/setup.h> | ||
| 24 | #include <asm/cache.h> | 28 | #include <asm/cache.h> |
| 25 | #include <asm/sizes.h> | 29 | #include <asm/sizes.h> |
| 26 | 30 | ||
| 27 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 31 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
| 28 | pgd_t swapper_pg_dir[PTRS_PER_PGD]; | 32 | pgd_t swapper_pg_dir[PTRS_PER_PGD]; |
| 29 | 33 | ||
| 34 | void __init generic_mem_init(void) | ||
| 35 | { | ||
| 36 | lmb_add(__MEMORY_START, __MEMORY_SIZE); | ||
| 37 | } | ||
| 38 | |||
| 39 | void __init __weak plat_mem_setup(void) | ||
| 40 | { | ||
| 41 | /* Nothing to see here, move along. */ | ||
| 42 | } | ||
| 43 | |||
| 30 | #ifdef CONFIG_MMU | 44 | #ifdef CONFIG_MMU |
| 31 | static pte_t *__get_pte_phys(unsigned long addr) | 45 | static pte_t *__get_pte_phys(unsigned long addr) |
| 32 | { | 46 | { |
| @@ -152,15 +166,166 @@ void __init page_table_range_init(unsigned long start, unsigned long end, | |||
| 152 | } | 166 | } |
| 153 | #endif /* CONFIG_MMU */ | 167 | #endif /* CONFIG_MMU */ |
| 154 | 168 | ||
| 155 | /* | 169 | void __init allocate_pgdat(unsigned int nid) |
| 156 | * paging_init() sets up the page tables | 170 | { |
| 157 | */ | 171 | unsigned long start_pfn, end_pfn; |
| 172 | #ifdef CONFIG_NEED_MULTIPLE_NODES | ||
| 173 | unsigned long phys; | ||
| 174 | #endif | ||
| 175 | |||
| 176 | get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); | ||
| 177 | |||
| 178 | #ifdef CONFIG_NEED_MULTIPLE_NODES | ||
| 179 | phys = __lmb_alloc_base(sizeof(struct pglist_data), | ||
| 180 | SMP_CACHE_BYTES, end_pfn << PAGE_SHIFT); | ||
| 181 | /* Retry with all of system memory */ | ||
| 182 | if (!phys) | ||
| 183 | phys = __lmb_alloc_base(sizeof(struct pglist_data), | ||
| 184 | SMP_CACHE_BYTES, lmb_end_of_DRAM()); | ||
| 185 | if (!phys) | ||
| 186 | panic("Can't allocate pgdat for node %d\n", nid); | ||
| 187 | |||
| 188 | NODE_DATA(nid) = __va(phys); | ||
| 189 | memset(NODE_DATA(nid), 0, sizeof(struct pglist_data)); | ||
| 190 | |||
| 191 | NODE_DATA(nid)->bdata = &bootmem_node_data[nid]; | ||
| 192 | #endif | ||
| 193 | |||
| 194 | NODE_DATA(nid)->node_start_pfn = start_pfn; | ||
| 195 | NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn; | ||
| 196 | } | ||
| 197 | |||
| 198 | static void __init bootmem_init_one_node(unsigned int nid) | ||
| 199 | { | ||
| 200 | unsigned long total_pages, paddr; | ||
| 201 | unsigned long end_pfn; | ||
| 202 | struct pglist_data *p; | ||
| 203 | int i; | ||
| 204 | |||
| 205 | p = NODE_DATA(nid); | ||
| 206 | |||
| 207 | /* Nothing to do.. */ | ||
| 208 | if (!p->node_spanned_pages) | ||
| 209 | return; | ||
| 210 | |||
| 211 | end_pfn = p->node_start_pfn + p->node_spanned_pages; | ||
| 212 | |||
| 213 | total_pages = bootmem_bootmap_pages(p->node_spanned_pages); | ||
| 214 | |||
| 215 | paddr = lmb_alloc(total_pages << PAGE_SHIFT, PAGE_SIZE); | ||
| 216 | if (!paddr) | ||
| 217 | panic("Can't allocate bootmap for nid[%d]\n", nid); | ||
| 218 | |||
| 219 | init_bootmem_node(p, paddr >> PAGE_SHIFT, p->node_start_pfn, end_pfn); | ||
| 220 | |||
| 221 | free_bootmem_with_active_regions(nid, end_pfn); | ||
| 222 | |||
| 223 | /* | ||
| 224 | * XXX Handle initial reservations for the system memory node | ||
| 225 | * only for the moment, we'll refactor this later for handling | ||
| 226 | * reservations in other nodes. | ||
| 227 | */ | ||
| 228 | if (nid == 0) { | ||
| 229 | /* Reserve the sections we're already using. */ | ||
| 230 | for (i = 0; i < lmb.reserved.cnt; i++) | ||
| 231 | reserve_bootmem(lmb.reserved.region[i].base, | ||
| 232 | lmb_size_bytes(&lmb.reserved, i), | ||
| 233 | BOOTMEM_DEFAULT); | ||
| 234 | } | ||
| 235 | |||
| 236 | sparse_memory_present_with_active_regions(nid); | ||
| 237 | } | ||
| 238 | |||
| 239 | static void __init do_init_bootmem(void) | ||
| 240 | { | ||
| 241 | int i; | ||
| 242 | |||
| 243 | /* Add active regions with valid PFNs. */ | ||
| 244 | for (i = 0; i < lmb.memory.cnt; i++) { | ||
| 245 | unsigned long start_pfn, end_pfn; | ||
| 246 | start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT; | ||
| 247 | end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i); | ||
| 248 | __add_active_range(0, start_pfn, end_pfn); | ||
| 249 | } | ||
| 250 | |||
| 251 | /* All of system RAM sits in node 0 for the non-NUMA case */ | ||
| 252 | allocate_pgdat(0); | ||
| 253 | node_set_online(0); | ||
| 254 | |||
| 255 | plat_mem_setup(); | ||
| 256 | |||
| 257 | for_each_online_node(i) | ||
| 258 | bootmem_init_one_node(i); | ||
| 259 | |||
| 260 | sparse_init(); | ||
| 261 | } | ||
| 262 | |||
| 263 | static void __init early_reserve_mem(void) | ||
| 264 | { | ||
| 265 | unsigned long start_pfn; | ||
| 266 | |||
| 267 | /* | ||
| 268 | * Partially used pages are not usable - thus | ||
| 269 | * we are rounding upwards: | ||
| 270 | */ | ||
| 271 | start_pfn = PFN_UP(__pa(_end)); | ||
| 272 | |||
| 273 | /* | ||
| 274 | * Reserve the kernel text and Reserve the bootmem bitmap. We do | ||
| 275 | * this in two steps (first step was init_bootmem()), because | ||
| 276 | * this catches the (definitely buggy) case of us accidentally | ||
| 277 | * initializing the bootmem allocator with an invalid RAM area. | ||
| 278 | */ | ||
| 279 | lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET, | ||
| 280 | (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) - | ||
| 281 | (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET)); | ||
| 282 | |||
| 283 | /* | ||
| 284 | * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET. | ||
| 285 | */ | ||
| 286 | if (CONFIG_ZERO_PAGE_OFFSET != 0) | ||
| 287 | lmb_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET); | ||
| 288 | |||
| 289 | /* | ||
| 290 | * Handle additional early reservations | ||
| 291 | */ | ||
| 292 | check_for_initrd(); | ||
| 293 | reserve_crashkernel(); | ||
| 294 | } | ||
| 295 | |||
| 158 | void __init paging_init(void) | 296 | void __init paging_init(void) |
| 159 | { | 297 | { |
| 160 | unsigned long max_zone_pfns[MAX_NR_ZONES]; | 298 | unsigned long max_zone_pfns[MAX_NR_ZONES]; |
| 161 | unsigned long vaddr, end; | 299 | unsigned long vaddr, end; |
| 162 | int nid; | 300 | int nid; |
| 163 | 301 | ||
| 302 | lmb_init(); | ||
| 303 | |||
| 304 | sh_mv.mv_mem_init(); | ||
| 305 | |||
| 306 | early_reserve_mem(); | ||
| 307 | |||
| 308 | lmb_enforce_memory_limit(memory_limit); | ||
| 309 | lmb_analyze(); | ||
| 310 | |||
| 311 | lmb_dump_all(); | ||
| 312 | |||
| 313 | /* | ||
| 314 | * Determine low and high memory ranges: | ||
| 315 | */ | ||
| 316 | max_low_pfn = max_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT; | ||
| 317 | min_low_pfn = __MEMORY_START >> PAGE_SHIFT; | ||
| 318 | |||
| 319 | nodes_clear(node_online_map); | ||
| 320 | |||
| 321 | memory_start = (unsigned long)__va(__MEMORY_START); | ||
| 322 | memory_end = memory_start + (memory_limit ?: lmb_phys_mem_size()); | ||
| 323 | |||
| 324 | uncached_init(); | ||
| 325 | pmb_init(); | ||
| 326 | do_init_bootmem(); | ||
| 327 | ioremap_fixed_init(); | ||
| 328 | |||
| 164 | /* We don't need to map the kernel through the TLB, as | 329 | /* We don't need to map the kernel through the TLB, as |
| 165 | * it is permanatly mapped using P1. So clear the | 330 | * it is permanatly mapped using P1. So clear the |
| 166 | * entire pgd. */ | 331 | * entire pgd. */ |
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c index e9f5384f3f1c..18623ba751b3 100644 --- a/arch/sh/mm/pmb.c +++ b/arch/sh/mm/pmb.c | |||
| @@ -341,6 +341,8 @@ int pmb_bolt_mapping(unsigned long vaddr, phys_addr_t phys, | |||
| 341 | unsigned long flags, pmb_flags; | 341 | unsigned long flags, pmb_flags; |
| 342 | int i, mapped; | 342 | int i, mapped; |
| 343 | 343 | ||
| 344 | if (size < SZ_16M) | ||
| 345 | return -EINVAL; | ||
| 344 | if (!pmb_addr_valid(vaddr, size)) | 346 | if (!pmb_addr_valid(vaddr, size)) |
| 345 | return -EFAULT; | 347 | return -EFAULT; |
| 346 | if (pmb_mapping_exists(vaddr, phys, size)) | 348 | if (pmb_mapping_exists(vaddr, phys, size)) |
