diff options
-rw-r--r-- | arch/powerpc/mm/hash_utils_64.c | 44 | ||||
-rw-r--r-- | arch/powerpc/mm/hugetlbpage.c | 16 | ||||
-rw-r--r-- | include/asm-powerpc/mmu-hash64.h | 2 |
3 files changed, 61 insertions, 1 deletions
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 8d3b58ebd38e..ae4c717243a5 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -68,6 +68,7 @@ | |||
68 | 68 | ||
69 | #define KB (1024) | 69 | #define KB (1024) |
70 | #define MB (1024*KB) | 70 | #define MB (1024*KB) |
71 | #define GB (1024L*MB) | ||
71 | 72 | ||
72 | /* | 73 | /* |
73 | * Note: pte --> Linux PTE | 74 | * Note: pte --> Linux PTE |
@@ -329,6 +330,44 @@ static int __init htab_dt_scan_page_sizes(unsigned long node, | |||
329 | return 0; | 330 | return 0; |
330 | } | 331 | } |
331 | 332 | ||
333 | /* Scan for 16G memory blocks that have been set aside for huge pages | ||
334 | * and reserve those blocks for 16G huge pages. | ||
335 | */ | ||
336 | static int __init htab_dt_scan_hugepage_blocks(unsigned long node, | ||
337 | const char *uname, int depth, | ||
338 | void *data) { | ||
339 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | ||
340 | unsigned long *addr_prop; | ||
341 | u32 *page_count_prop; | ||
342 | unsigned int expected_pages; | ||
343 | long unsigned int phys_addr; | ||
344 | long unsigned int block_size; | ||
345 | |||
346 | /* We are scanning "memory" nodes only */ | ||
347 | if (type == NULL || strcmp(type, "memory") != 0) | ||
348 | return 0; | ||
349 | |||
350 | /* This property is the log base 2 of the number of virtual pages that | ||
351 | * will represent this memory block. */ | ||
352 | page_count_prop = of_get_flat_dt_prop(node, "ibm,expected#pages", NULL); | ||
353 | if (page_count_prop == NULL) | ||
354 | return 0; | ||
355 | expected_pages = (1 << page_count_prop[0]); | ||
356 | addr_prop = of_get_flat_dt_prop(node, "reg", NULL); | ||
357 | if (addr_prop == NULL) | ||
358 | return 0; | ||
359 | phys_addr = addr_prop[0]; | ||
360 | block_size = addr_prop[1]; | ||
361 | if (block_size != (16 * GB)) | ||
362 | return 0; | ||
363 | printk(KERN_INFO "Huge page(16GB) memory: " | ||
364 | "addr = 0x%lX size = 0x%lX pages = %d\n", | ||
365 | phys_addr, block_size, expected_pages); | ||
366 | lmb_reserve(phys_addr, block_size * expected_pages); | ||
367 | add_gpage(phys_addr, block_size, expected_pages); | ||
368 | return 0; | ||
369 | } | ||
370 | |||
332 | static void __init htab_init_page_sizes(void) | 371 | static void __init htab_init_page_sizes(void) |
333 | { | 372 | { |
334 | int rc; | 373 | int rc; |
@@ -418,7 +457,10 @@ static void __init htab_init_page_sizes(void) | |||
418 | ); | 457 | ); |
419 | 458 | ||
420 | #ifdef CONFIG_HUGETLB_PAGE | 459 | #ifdef CONFIG_HUGETLB_PAGE |
421 | /* Init large page size. Currently, we pick 16M or 1M depending | 460 | /* Reserve 16G huge page memory sections for huge pages */ |
461 | of_scan_flat_dt(htab_dt_scan_hugepage_blocks, NULL); | ||
462 | |||
463 | /* Init large page size. Currently, we pick 16M or 1M depending | ||
422 | * on what is available | 464 | * on what is available |
423 | */ | 465 | */ |
424 | if (mmu_psize_defs[MMU_PAGE_16M].shift) | 466 | if (mmu_psize_defs[MMU_PAGE_16M].shift) |
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 5df82186fc93..e2a650a9e533 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
@@ -110,6 +110,22 @@ pmd_t *hpmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr) | |||
110 | } | 110 | } |
111 | #endif | 111 | #endif |
112 | 112 | ||
113 | /* Build list of addresses of gigantic pages. This function is used in early | ||
114 | * boot before the buddy or bootmem allocator is setup. | ||
115 | */ | ||
116 | void add_gpage(unsigned long addr, unsigned long page_size, | ||
117 | unsigned long number_of_pages) | ||
118 | { | ||
119 | if (!addr) | ||
120 | return; | ||
121 | while (number_of_pages > 0) { | ||
122 | gpage_freearray[nr_gpages] = addr; | ||
123 | nr_gpages++; | ||
124 | number_of_pages--; | ||
125 | addr += page_size; | ||
126 | } | ||
127 | } | ||
128 | |||
113 | /* Moves the gigantic page addresses from the temporary list to the | 129 | /* Moves the gigantic page addresses from the temporary list to the |
114 | * huge_boot_pages list. */ | 130 | * huge_boot_pages list. */ |
115 | int alloc_bootmem_huge_page(struct hstate *h) | 131 | int alloc_bootmem_huge_page(struct hstate *h) |
diff --git a/include/asm-powerpc/mmu-hash64.h b/include/asm-powerpc/mmu-hash64.h index d1dc16afb118..b61181aa7746 100644 --- a/include/asm-powerpc/mmu-hash64.h +++ b/include/asm-powerpc/mmu-hash64.h | |||
@@ -281,6 +281,8 @@ extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | |||
281 | unsigned long pstart, unsigned long mode, | 281 | unsigned long pstart, unsigned long mode, |
282 | int psize, int ssize); | 282 | int psize, int ssize); |
283 | extern void set_huge_psize(int psize); | 283 | extern void set_huge_psize(int psize); |
284 | extern void add_gpage(unsigned long addr, unsigned long page_size, | ||
285 | unsigned long number_of_pages); | ||
284 | extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr); | 286 | extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr); |
285 | 287 | ||
286 | extern void htab_initialize(void); | 288 | extern void htab_initialize(void); |