diff options
Diffstat (limited to 'arch/powerpc/mm')
-rw-r--r-- | arch/powerpc/mm/hash_utils_64.c | 38 | ||||
-rw-r--r-- | arch/powerpc/mm/init_32.c | 3 | ||||
-rw-r--r-- | arch/powerpc/mm/init_64.c | 20 | ||||
-rw-r--r-- | arch/powerpc/mm/mem.c | 4 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable_64.c | 7 | ||||
-rw-r--r-- | arch/powerpc/mm/stab.c | 21 |
6 files changed, 72 insertions, 21 deletions
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 22e474876133..706e8a63ced9 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -84,10 +84,11 @@ | |||
84 | extern unsigned long dart_tablebase; | 84 | extern unsigned long dart_tablebase; |
85 | #endif /* CONFIG_U3_DART */ | 85 | #endif /* CONFIG_U3_DART */ |
86 | 86 | ||
87 | static unsigned long _SDR1; | ||
88 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; | ||
89 | |||
87 | hpte_t *htab_address; | 90 | hpte_t *htab_address; |
88 | unsigned long htab_hash_mask; | 91 | unsigned long htab_hash_mask; |
89 | unsigned long _SDR1; | ||
90 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; | ||
91 | int mmu_linear_psize = MMU_PAGE_4K; | 92 | int mmu_linear_psize = MMU_PAGE_4K; |
92 | int mmu_virtual_psize = MMU_PAGE_4K; | 93 | int mmu_virtual_psize = MMU_PAGE_4K; |
93 | #ifdef CONFIG_HUGETLB_PAGE | 94 | #ifdef CONFIG_HUGETLB_PAGE |
@@ -165,7 +166,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | |||
165 | * normal insert callback here. | 166 | * normal insert callback here. |
166 | */ | 167 | */ |
167 | #ifdef CONFIG_PPC_ISERIES | 168 | #ifdef CONFIG_PPC_ISERIES |
168 | if (systemcfg->platform == PLATFORM_ISERIES_LPAR) | 169 | if (_machine == PLATFORM_ISERIES_LPAR) |
169 | ret = iSeries_hpte_insert(hpteg, va, | 170 | ret = iSeries_hpte_insert(hpteg, va, |
170 | virt_to_abs(paddr), | 171 | virt_to_abs(paddr), |
171 | tmp_mode, | 172 | tmp_mode, |
@@ -174,7 +175,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | |||
174 | else | 175 | else |
175 | #endif | 176 | #endif |
176 | #ifdef CONFIG_PPC_PSERIES | 177 | #ifdef CONFIG_PPC_PSERIES |
177 | if (systemcfg->platform & PLATFORM_LPAR) | 178 | if (_machine & PLATFORM_LPAR) |
178 | ret = pSeries_lpar_hpte_insert(hpteg, va, | 179 | ret = pSeries_lpar_hpte_insert(hpteg, va, |
179 | virt_to_abs(paddr), | 180 | virt_to_abs(paddr), |
180 | tmp_mode, | 181 | tmp_mode, |
@@ -293,7 +294,7 @@ static void __init htab_init_page_sizes(void) | |||
293 | * Not in the device-tree, let's fallback on known size | 294 | * Not in the device-tree, let's fallback on known size |
294 | * list for 16M capable GP & GR | 295 | * list for 16M capable GP & GR |
295 | */ | 296 | */ |
296 | if ((systemcfg->platform != PLATFORM_ISERIES_LPAR) && | 297 | if ((_machine != PLATFORM_ISERIES_LPAR) && |
297 | cpu_has_feature(CPU_FTR_16M_PAGE)) | 298 | cpu_has_feature(CPU_FTR_16M_PAGE)) |
298 | memcpy(mmu_psize_defs, mmu_psize_defaults_gp, | 299 | memcpy(mmu_psize_defs, mmu_psize_defaults_gp, |
299 | sizeof(mmu_psize_defaults_gp)); | 300 | sizeof(mmu_psize_defaults_gp)); |
@@ -364,7 +365,7 @@ static int __init htab_dt_scan_pftsize(unsigned long node, | |||
364 | 365 | ||
365 | static unsigned long __init htab_get_table_size(void) | 366 | static unsigned long __init htab_get_table_size(void) |
366 | { | 367 | { |
367 | unsigned long rnd_mem_size, pteg_count; | 368 | unsigned long mem_size, rnd_mem_size, pteg_count; |
368 | 369 | ||
369 | /* If hash size isn't already provided by the platform, we try to | 370 | /* If hash size isn't already provided by the platform, we try to |
370 | * retreive it from the device-tree. If it's not there neither, we | 371 | * retreive it from the device-tree. If it's not there neither, we |
@@ -376,8 +377,9 @@ static unsigned long __init htab_get_table_size(void) | |||
376 | return 1UL << ppc64_pft_size; | 377 | return 1UL << ppc64_pft_size; |
377 | 378 | ||
378 | /* round mem_size up to next power of 2 */ | 379 | /* round mem_size up to next power of 2 */ |
379 | rnd_mem_size = 1UL << __ilog2(systemcfg->physicalMemorySize); | 380 | mem_size = lmb_phys_mem_size(); |
380 | if (rnd_mem_size < systemcfg->physicalMemorySize) | 381 | rnd_mem_size = 1UL << __ilog2(mem_size); |
382 | if (rnd_mem_size < mem_size) | ||
381 | rnd_mem_size <<= 1; | 383 | rnd_mem_size <<= 1; |
382 | 384 | ||
383 | /* # pages / 2 */ | 385 | /* # pages / 2 */ |
@@ -386,6 +388,15 @@ static unsigned long __init htab_get_table_size(void) | |||
386 | return pteg_count << 7; | 388 | return pteg_count << 7; |
387 | } | 389 | } |
388 | 390 | ||
391 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
392 | void create_section_mapping(unsigned long start, unsigned long end) | ||
393 | { | ||
394 | BUG_ON(htab_bolt_mapping(start, end, start, | ||
395 | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX, | ||
396 | mmu_linear_psize)); | ||
397 | } | ||
398 | #endif /* CONFIG_MEMORY_HOTPLUG */ | ||
399 | |||
389 | void __init htab_initialize(void) | 400 | void __init htab_initialize(void) |
390 | { | 401 | { |
391 | unsigned long table, htab_size_bytes; | 402 | unsigned long table, htab_size_bytes; |
@@ -410,7 +421,7 @@ void __init htab_initialize(void) | |||
410 | 421 | ||
411 | htab_hash_mask = pteg_count - 1; | 422 | htab_hash_mask = pteg_count - 1; |
412 | 423 | ||
413 | if (systemcfg->platform & PLATFORM_LPAR) { | 424 | if (platform_is_lpar()) { |
414 | /* Using a hypervisor which owns the htab */ | 425 | /* Using a hypervisor which owns the htab */ |
415 | htab_address = NULL; | 426 | htab_address = NULL; |
416 | _SDR1 = 0; | 427 | _SDR1 = 0; |
@@ -431,6 +442,9 @@ void __init htab_initialize(void) | |||
431 | 442 | ||
432 | /* Initialize the HPT with no entries */ | 443 | /* Initialize the HPT with no entries */ |
433 | memset((void *)table, 0, htab_size_bytes); | 444 | memset((void *)table, 0, htab_size_bytes); |
445 | |||
446 | /* Set SDR1 */ | ||
447 | mtspr(SPRN_SDR1, _SDR1); | ||
434 | } | 448 | } |
435 | 449 | ||
436 | mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX; | 450 | mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX; |
@@ -500,6 +514,12 @@ void __init htab_initialize(void) | |||
500 | #undef KB | 514 | #undef KB |
501 | #undef MB | 515 | #undef MB |
502 | 516 | ||
517 | void __init htab_initialize_secondary(void) | ||
518 | { | ||
519 | if (!platform_is_lpar()) | ||
520 | mtspr(SPRN_SDR1, _SDR1); | ||
521 | } | ||
522 | |||
503 | /* | 523 | /* |
504 | * Called by asm hashtable.S for doing lazy icache flush | 524 | * Called by asm hashtable.S for doing lazy icache flush |
505 | */ | 525 | */ |
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 4612a79dfb6e..7d4b8b5f0606 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c | |||
@@ -84,9 +84,6 @@ void MMU_init(void); | |||
84 | /* XXX should be in current.h -- paulus */ | 84 | /* XXX should be in current.h -- paulus */ |
85 | extern struct task_struct *current_set[NR_CPUS]; | 85 | extern struct task_struct *current_set[NR_CPUS]; |
86 | 86 | ||
87 | char *klimit = _end; | ||
88 | struct device_node *memory_node; | ||
89 | |||
90 | extern int init_bootmem_done; | 87 | extern int init_bootmem_done; |
91 | 88 | ||
92 | /* | 89 | /* |
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index ce974c83d88a..1134f70f231d 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
@@ -20,6 +20,8 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #undef DEBUG | ||
24 | |||
23 | #include <linux/config.h> | 25 | #include <linux/config.h> |
24 | #include <linux/signal.h> | 26 | #include <linux/signal.h> |
25 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
@@ -64,6 +66,12 @@ | |||
64 | #include <asm/vdso.h> | 66 | #include <asm/vdso.h> |
65 | #include <asm/imalloc.h> | 67 | #include <asm/imalloc.h> |
66 | 68 | ||
69 | #ifdef DEBUG | ||
70 | #define DBG(fmt...) printk(fmt) | ||
71 | #else | ||
72 | #define DBG(fmt...) | ||
73 | #endif | ||
74 | |||
67 | #if PGTABLE_RANGE > USER_VSID_RANGE | 75 | #if PGTABLE_RANGE > USER_VSID_RANGE |
68 | #warning Limited user VSID range means pagetable space is wasted | 76 | #warning Limited user VSID range means pagetable space is wasted |
69 | #endif | 77 | #endif |
@@ -72,8 +80,6 @@ | |||
72 | #warning TASK_SIZE is smaller than it needs to be. | 80 | #warning TASK_SIZE is smaller than it needs to be. |
73 | #endif | 81 | #endif |
74 | 82 | ||
75 | unsigned long klimit = (unsigned long)_end; | ||
76 | |||
77 | /* max amount of RAM to use */ | 83 | /* max amount of RAM to use */ |
78 | unsigned long __max_memory; | 84 | unsigned long __max_memory; |
79 | 85 | ||
@@ -188,14 +194,14 @@ static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags) | |||
188 | } | 194 | } |
189 | 195 | ||
190 | #ifdef CONFIG_PPC_64K_PAGES | 196 | #ifdef CONFIG_PPC_64K_PAGES |
191 | static const int pgtable_cache_size[2] = { | 197 | static const unsigned int pgtable_cache_size[3] = { |
192 | PTE_TABLE_SIZE, PGD_TABLE_SIZE | 198 | PTE_TABLE_SIZE, PMD_TABLE_SIZE, PGD_TABLE_SIZE |
193 | }; | 199 | }; |
194 | static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { | 200 | static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { |
195 | "pte_pmd_cache", "pgd_cache", | 201 | "pte_pmd_cache", "pmd_cache", "pgd_cache", |
196 | }; | 202 | }; |
197 | #else | 203 | #else |
198 | static const int pgtable_cache_size[2] = { | 204 | static const unsigned int pgtable_cache_size[2] = { |
199 | PTE_TABLE_SIZE, PMD_TABLE_SIZE | 205 | PTE_TABLE_SIZE, PMD_TABLE_SIZE |
200 | }; | 206 | }; |
201 | static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { | 207 | static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { |
@@ -213,6 +219,8 @@ void pgtable_cache_init(void) | |||
213 | int size = pgtable_cache_size[i]; | 219 | int size = pgtable_cache_size[i]; |
214 | const char *name = pgtable_cache_name[i]; | 220 | const char *name = pgtable_cache_name[i]; |
215 | 221 | ||
222 | DBG("Allocating page table cache %s (#%d) " | ||
223 | "for size: %08x...\n", name, i, size); | ||
216 | pgtable_cache[i] = kmem_cache_create(name, | 224 | pgtable_cache[i] = kmem_cache_create(name, |
217 | size, size, | 225 | size, size, |
218 | SLAB_HWCACHE_ALIGN | | 226 | SLAB_HWCACHE_ALIGN | |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 6f55efd9be95..1dd3cc69a490 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -110,6 +110,7 @@ EXPORT_SYMBOL(phys_mem_access_prot); | |||
110 | void online_page(struct page *page) | 110 | void online_page(struct page *page) |
111 | { | 111 | { |
112 | ClearPageReserved(page); | 112 | ClearPageReserved(page); |
113 | set_page_count(page, 0); | ||
113 | free_cold_page(page); | 114 | free_cold_page(page); |
114 | totalram_pages++; | 115 | totalram_pages++; |
115 | num_physpages++; | 116 | num_physpages++; |
@@ -127,6 +128,9 @@ int __devinit add_memory(u64 start, u64 size) | |||
127 | unsigned long start_pfn = start >> PAGE_SHIFT; | 128 | unsigned long start_pfn = start >> PAGE_SHIFT; |
128 | unsigned long nr_pages = size >> PAGE_SHIFT; | 129 | unsigned long nr_pages = size >> PAGE_SHIFT; |
129 | 130 | ||
131 | start += KERNELBASE; | ||
132 | create_section_mapping(start, start + size); | ||
133 | |||
130 | /* this should work for most non-highmem platforms */ | 134 | /* this should work for most non-highmem platforms */ |
131 | zone = pgdata->node_zones; | 135 | zone = pgdata->node_zones; |
132 | 136 | ||
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 900842451bd3..c7f7bb6f30b3 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
@@ -122,8 +122,11 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) | |||
122 | * | 122 | * |
123 | */ | 123 | */ |
124 | if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, | 124 | if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, |
125 | mmu_virtual_psize)) | 125 | mmu_virtual_psize)) { |
126 | panic("Can't map bolted IO mapping"); | 126 | printk(KERN_ERR "Failed to do bolted mapping IO " |
127 | "memory at %016lx !\n", pa); | ||
128 | return -ENOMEM; | ||
129 | } | ||
127 | } | 130 | } |
128 | return 0; | 131 | return 0; |
129 | } | 132 | } |
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index fa325dbf98fc..cfbb4e1f966b 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <asm/cputable.h> | 20 | #include <asm/cputable.h> |
21 | #include <asm/lmb.h> | 21 | #include <asm/lmb.h> |
22 | #include <asm/abs_addr.h> | 22 | #include <asm/abs_addr.h> |
23 | #include <asm/firmware.h> | ||
23 | 24 | ||
24 | struct stab_entry { | 25 | struct stab_entry { |
25 | unsigned long esid_data; | 26 | unsigned long esid_data; |
@@ -256,7 +257,7 @@ void stabs_alloc(void) | |||
256 | 257 | ||
257 | paca[cpu].stab_addr = newstab; | 258 | paca[cpu].stab_addr = newstab; |
258 | paca[cpu].stab_real = virt_to_abs(newstab); | 259 | paca[cpu].stab_real = virt_to_abs(newstab); |
259 | printk(KERN_DEBUG "Segment table for CPU %d at 0x%lx " | 260 | printk(KERN_INFO "Segment table for CPU %d at 0x%lx " |
260 | "virtual, 0x%lx absolute\n", | 261 | "virtual, 0x%lx absolute\n", |
261 | cpu, paca[cpu].stab_addr, paca[cpu].stab_real); | 262 | cpu, paca[cpu].stab_addr, paca[cpu].stab_real); |
262 | } | 263 | } |
@@ -270,10 +271,28 @@ void stabs_alloc(void) | |||
270 | void stab_initialize(unsigned long stab) | 271 | void stab_initialize(unsigned long stab) |
271 | { | 272 | { |
272 | unsigned long vsid = get_kernel_vsid(KERNELBASE); | 273 | unsigned long vsid = get_kernel_vsid(KERNELBASE); |
274 | unsigned long stabreal; | ||
273 | 275 | ||
274 | asm volatile("isync; slbia; isync":::"memory"); | 276 | asm volatile("isync; slbia; isync":::"memory"); |
275 | make_ste(stab, GET_ESID(KERNELBASE), vsid); | 277 | make_ste(stab, GET_ESID(KERNELBASE), vsid); |
276 | 278 | ||
277 | /* Order update */ | 279 | /* Order update */ |
278 | asm volatile("sync":::"memory"); | 280 | asm volatile("sync":::"memory"); |
281 | |||
282 | /* Set ASR */ | ||
283 | stabreal = get_paca()->stab_real | 0x1ul; | ||
284 | |||
285 | #ifdef CONFIG_PPC_ISERIES | ||
286 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | ||
287 | HvCall1(HvCallBaseSetASR, stabreal); | ||
288 | return; | ||
289 | } | ||
290 | #endif /* CONFIG_PPC_ISERIES */ | ||
291 | #ifdef CONFIG_PPC_PSERIES | ||
292 | if (platform_is_lpar()) { | ||
293 | plpar_hcall_norets(H_SET_ASR, stabreal); | ||
294 | return; | ||
295 | } | ||
296 | #endif | ||
297 | mtspr(SPRN_ASR, stabreal); | ||
279 | } | 298 | } |