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 | } |
