diff options
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/include/asm/page_64.h | 1 | ||||
-rw-r--r-- | arch/sparc/include/asm/smp_64.h | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/setup_64.c | 26 | ||||
-rw-r--r-- | arch/sparc/kernel/smp_64.c | 14 | ||||
-rw-r--r-- | arch/sparc/mm/fault_64.c | 1 | ||||
-rw-r--r-- | arch/sparc/mm/init_64.c | 22 | ||||
-rw-r--r-- | arch/sparc/mm/tlb.c | 35 | ||||
-rw-r--r-- | arch/sparc/mm/tsb.c | 18 |
8 files changed, 90 insertions, 29 deletions
diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h index 8c2a8c937540..c1263fc390db 100644 --- a/arch/sparc/include/asm/page_64.h +++ b/arch/sparc/include/asm/page_64.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #define HPAGE_MASK (~(HPAGE_SIZE - 1UL)) | 25 | #define HPAGE_MASK (~(HPAGE_SIZE - 1UL)) |
26 | #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) | 26 | #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) |
27 | #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA | 27 | #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA |
28 | #define REAL_HPAGE_PER_HPAGE (_AC(1,UL) << (HPAGE_SHIFT - REAL_HPAGE_SHIFT)) | ||
28 | #endif | 29 | #endif |
29 | 30 | ||
30 | #ifndef __ASSEMBLY__ | 31 | #ifndef __ASSEMBLY__ |
diff --git a/arch/sparc/include/asm/smp_64.h b/arch/sparc/include/asm/smp_64.h index 26d9e7726867..ce2233f7e662 100644 --- a/arch/sparc/include/asm/smp_64.h +++ b/arch/sparc/include/asm/smp_64.h | |||
@@ -43,6 +43,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask); | |||
43 | int hard_smp_processor_id(void); | 43 | int hard_smp_processor_id(void); |
44 | #define raw_smp_processor_id() (current_thread_info()->cpu) | 44 | #define raw_smp_processor_id() (current_thread_info()->cpu) |
45 | 45 | ||
46 | void smp_fill_in_cpu_possible_map(void); | ||
46 | void smp_fill_in_sib_core_maps(void); | 47 | void smp_fill_in_sib_core_maps(void); |
47 | void cpu_play_dead(void); | 48 | void cpu_play_dead(void); |
48 | 49 | ||
@@ -72,6 +73,7 @@ void __cpu_die(unsigned int cpu); | |||
72 | #define smp_fill_in_sib_core_maps() do { } while (0) | 73 | #define smp_fill_in_sib_core_maps() do { } while (0) |
73 | #define smp_fetch_global_regs() do { } while (0) | 74 | #define smp_fetch_global_regs() do { } while (0) |
74 | #define smp_fetch_global_pmu() do { } while (0) | 75 | #define smp_fetch_global_pmu() do { } while (0) |
76 | #define smp_fill_in_cpu_possible_map() do { } while (0) | ||
75 | 77 | ||
76 | #endif /* !(CONFIG_SMP) */ | 78 | #endif /* !(CONFIG_SMP) */ |
77 | 79 | ||
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 599f1207eed2..6b7331d198e9 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/initrd.h> | 31 | #include <linux/initrd.h> |
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/start_kernel.h> | 33 | #include <linux/start_kernel.h> |
34 | #include <linux/bootmem.h> | ||
34 | 35 | ||
35 | #include <asm/io.h> | 36 | #include <asm/io.h> |
36 | #include <asm/processor.h> | 37 | #include <asm/processor.h> |
@@ -50,6 +51,8 @@ | |||
50 | #include <asm/elf.h> | 51 | #include <asm/elf.h> |
51 | #include <asm/mdesc.h> | 52 | #include <asm/mdesc.h> |
52 | #include <asm/cacheflush.h> | 53 | #include <asm/cacheflush.h> |
54 | #include <asm/dma.h> | ||
55 | #include <asm/irq.h> | ||
53 | 56 | ||
54 | #ifdef CONFIG_IP_PNP | 57 | #ifdef CONFIG_IP_PNP |
55 | #include <net/ipconfig.h> | 58 | #include <net/ipconfig.h> |
@@ -590,6 +593,22 @@ static void __init init_sparc64_elf_hwcap(void) | |||
590 | pause_patch(); | 593 | pause_patch(); |
591 | } | 594 | } |
592 | 595 | ||
596 | void __init alloc_irqstack_bootmem(void) | ||
597 | { | ||
598 | unsigned int i, node; | ||
599 | |||
600 | for_each_possible_cpu(i) { | ||
601 | node = cpu_to_node(i); | ||
602 | |||
603 | softirq_stack[i] = __alloc_bootmem_node(NODE_DATA(node), | ||
604 | THREAD_SIZE, | ||
605 | THREAD_SIZE, 0); | ||
606 | hardirq_stack[i] = __alloc_bootmem_node(NODE_DATA(node), | ||
607 | THREAD_SIZE, | ||
608 | THREAD_SIZE, 0); | ||
609 | } | ||
610 | } | ||
611 | |||
593 | void __init setup_arch(char **cmdline_p) | 612 | void __init setup_arch(char **cmdline_p) |
594 | { | 613 | { |
595 | /* Initialize PROM console and command line. */ | 614 | /* Initialize PROM console and command line. */ |
@@ -650,6 +669,13 @@ void __init setup_arch(char **cmdline_p) | |||
650 | 669 | ||
651 | paging_init(); | 670 | paging_init(); |
652 | init_sparc64_elf_hwcap(); | 671 | init_sparc64_elf_hwcap(); |
672 | smp_fill_in_cpu_possible_map(); | ||
673 | /* | ||
674 | * Once the OF device tree and MDESC have been setup and nr_cpus has | ||
675 | * been parsed, we know the list of possible cpus. Therefore we can | ||
676 | * allocate the IRQ stacks. | ||
677 | */ | ||
678 | alloc_irqstack_bootmem(); | ||
653 | } | 679 | } |
654 | 680 | ||
655 | extern int stop_a_enabled; | 681 | extern int stop_a_enabled; |
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 8a6151a628ce..d3035ba6cd31 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c | |||
@@ -1227,6 +1227,20 @@ void __init smp_setup_processor_id(void) | |||
1227 | xcall_deliver_impl = hypervisor_xcall_deliver; | 1227 | xcall_deliver_impl = hypervisor_xcall_deliver; |
1228 | } | 1228 | } |
1229 | 1229 | ||
1230 | void __init smp_fill_in_cpu_possible_map(void) | ||
1231 | { | ||
1232 | int possible_cpus = num_possible_cpus(); | ||
1233 | int i; | ||
1234 | |||
1235 | if (possible_cpus > nr_cpu_ids) | ||
1236 | possible_cpus = nr_cpu_ids; | ||
1237 | |||
1238 | for (i = 0; i < possible_cpus; i++) | ||
1239 | set_cpu_possible(i, true); | ||
1240 | for (; i < NR_CPUS; i++) | ||
1241 | set_cpu_possible(i, false); | ||
1242 | } | ||
1243 | |||
1230 | void smp_fill_in_sib_core_maps(void) | 1244 | void smp_fill_in_sib_core_maps(void) |
1231 | { | 1245 | { |
1232 | unsigned int i; | 1246 | unsigned int i; |
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index e16fdd28a931..3f291d8c57f7 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c | |||
@@ -484,6 +484,7 @@ good_area: | |||
484 | tsb_grow(mm, MM_TSB_BASE, mm_rss); | 484 | tsb_grow(mm, MM_TSB_BASE, mm_rss); |
485 | #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) | 485 | #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) |
486 | mm_rss = mm->context.hugetlb_pte_count + mm->context.thp_pte_count; | 486 | mm_rss = mm->context.hugetlb_pte_count + mm->context.thp_pte_count; |
487 | mm_rss *= REAL_HPAGE_PER_HPAGE; | ||
487 | if (unlikely(mm_rss > | 488 | if (unlikely(mm_rss > |
488 | mm->context.tsb_block[MM_TSB_HUGE].tsb_rss_limit)) { | 489 | mm->context.tsb_block[MM_TSB_HUGE].tsb_rss_limit)) { |
489 | if (mm->context.tsb_block[MM_TSB_HUGE].tsb) | 490 | if (mm->context.tsb_block[MM_TSB_HUGE].tsb) |
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 65457c9f1365..7ac6b62fb7c1 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c | |||
@@ -1160,7 +1160,7 @@ int __node_distance(int from, int to) | |||
1160 | return numa_latency[from][to]; | 1160 | return numa_latency[from][to]; |
1161 | } | 1161 | } |
1162 | 1162 | ||
1163 | static int find_best_numa_node_for_mlgroup(struct mdesc_mlgroup *grp) | 1163 | static int __init find_best_numa_node_for_mlgroup(struct mdesc_mlgroup *grp) |
1164 | { | 1164 | { |
1165 | int i; | 1165 | int i; |
1166 | 1166 | ||
@@ -1173,8 +1173,8 @@ static int find_best_numa_node_for_mlgroup(struct mdesc_mlgroup *grp) | |||
1173 | return i; | 1173 | return i; |
1174 | } | 1174 | } |
1175 | 1175 | ||
1176 | static void find_numa_latencies_for_group(struct mdesc_handle *md, u64 grp, | 1176 | static void __init find_numa_latencies_for_group(struct mdesc_handle *md, |
1177 | int index) | 1177 | u64 grp, int index) |
1178 | { | 1178 | { |
1179 | u64 arc; | 1179 | u64 arc; |
1180 | 1180 | ||
@@ -2081,7 +2081,6 @@ void __init paging_init(void) | |||
2081 | { | 2081 | { |
2082 | unsigned long end_pfn, shift, phys_base; | 2082 | unsigned long end_pfn, shift, phys_base; |
2083 | unsigned long real_end, i; | 2083 | unsigned long real_end, i; |
2084 | int node; | ||
2085 | 2084 | ||
2086 | setup_page_offset(); | 2085 | setup_page_offset(); |
2087 | 2086 | ||
@@ -2250,21 +2249,6 @@ void __init paging_init(void) | |||
2250 | /* Setup bootmem... */ | 2249 | /* Setup bootmem... */ |
2251 | last_valid_pfn = end_pfn = bootmem_init(phys_base); | 2250 | last_valid_pfn = end_pfn = bootmem_init(phys_base); |
2252 | 2251 | ||
2253 | /* Once the OF device tree and MDESC have been setup, we know | ||
2254 | * the list of possible cpus. Therefore we can allocate the | ||
2255 | * IRQ stacks. | ||
2256 | */ | ||
2257 | for_each_possible_cpu(i) { | ||
2258 | node = cpu_to_node(i); | ||
2259 | |||
2260 | softirq_stack[i] = __alloc_bootmem_node(NODE_DATA(node), | ||
2261 | THREAD_SIZE, | ||
2262 | THREAD_SIZE, 0); | ||
2263 | hardirq_stack[i] = __alloc_bootmem_node(NODE_DATA(node), | ||
2264 | THREAD_SIZE, | ||
2265 | THREAD_SIZE, 0); | ||
2266 | } | ||
2267 | |||
2268 | kernel_physical_mapping_init(); | 2252 | kernel_physical_mapping_init(); |
2269 | 2253 | ||
2270 | { | 2254 | { |
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index 3659d37b4d81..c56a195c9071 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c | |||
@@ -174,10 +174,25 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, | |||
174 | return; | 174 | return; |
175 | 175 | ||
176 | if ((pmd_val(pmd) ^ pmd_val(orig)) & _PAGE_PMD_HUGE) { | 176 | if ((pmd_val(pmd) ^ pmd_val(orig)) & _PAGE_PMD_HUGE) { |
177 | if (pmd_val(pmd) & _PAGE_PMD_HUGE) | 177 | /* |
178 | mm->context.thp_pte_count++; | 178 | * Note that this routine only sets pmds for THP pages. |
179 | else | 179 | * Hugetlb pages are handled elsewhere. We need to check |
180 | mm->context.thp_pte_count--; | 180 | * for huge zero page. Huge zero pages are like hugetlb |
181 | * pages in that there is no RSS, but there is the need | ||
182 | * for TSB entries. So, huge zero page counts go into | ||
183 | * hugetlb_pte_count. | ||
184 | */ | ||
185 | if (pmd_val(pmd) & _PAGE_PMD_HUGE) { | ||
186 | if (is_huge_zero_page(pmd_page(pmd))) | ||
187 | mm->context.hugetlb_pte_count++; | ||
188 | else | ||
189 | mm->context.thp_pte_count++; | ||
190 | } else { | ||
191 | if (is_huge_zero_page(pmd_page(orig))) | ||
192 | mm->context.hugetlb_pte_count--; | ||
193 | else | ||
194 | mm->context.thp_pte_count--; | ||
195 | } | ||
181 | 196 | ||
182 | /* Do not try to allocate the TSB hash table if we | 197 | /* Do not try to allocate the TSB hash table if we |
183 | * don't have one already. We have various locks held | 198 | * don't have one already. We have various locks held |
@@ -204,6 +219,9 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, | |||
204 | } | 219 | } |
205 | } | 220 | } |
206 | 221 | ||
222 | /* | ||
223 | * This routine is only called when splitting a THP | ||
224 | */ | ||
207 | void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, | 225 | void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, |
208 | pmd_t *pmdp) | 226 | pmd_t *pmdp) |
209 | { | 227 | { |
@@ -213,6 +231,15 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, | |||
213 | 231 | ||
214 | set_pmd_at(vma->vm_mm, address, pmdp, entry); | 232 | set_pmd_at(vma->vm_mm, address, pmdp, entry); |
215 | flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); | 233 | flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); |
234 | |||
235 | /* | ||
236 | * set_pmd_at() will not be called in a way to decrement | ||
237 | * thp_pte_count when splitting a THP, so do it now. | ||
238 | * Sanity check pmd before doing the actual decrement. | ||
239 | */ | ||
240 | if ((pmd_val(entry) & _PAGE_PMD_HUGE) && | ||
241 | !is_huge_zero_page(pmd_page(entry))) | ||
242 | (vma->vm_mm)->context.thp_pte_count--; | ||
216 | } | 243 | } |
217 | 244 | ||
218 | void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp, | 245 | void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp, |
diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c index 6725ed45580e..f2b77112e9d8 100644 --- a/arch/sparc/mm/tsb.c +++ b/arch/sparc/mm/tsb.c | |||
@@ -469,8 +469,10 @@ retry_tsb_alloc: | |||
469 | 469 | ||
470 | int init_new_context(struct task_struct *tsk, struct mm_struct *mm) | 470 | int init_new_context(struct task_struct *tsk, struct mm_struct *mm) |
471 | { | 471 | { |
472 | unsigned long mm_rss = get_mm_rss(mm); | ||
472 | #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) | 473 | #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) |
473 | unsigned long total_huge_pte_count; | 474 | unsigned long saved_hugetlb_pte_count; |
475 | unsigned long saved_thp_pte_count; | ||
474 | #endif | 476 | #endif |
475 | unsigned int i; | 477 | unsigned int i; |
476 | 478 | ||
@@ -483,10 +485,12 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) | |||
483 | * will re-increment the counters as the parent PTEs are | 485 | * will re-increment the counters as the parent PTEs are |
484 | * copied into the child address space. | 486 | * copied into the child address space. |
485 | */ | 487 | */ |
486 | total_huge_pte_count = mm->context.hugetlb_pte_count + | 488 | saved_hugetlb_pte_count = mm->context.hugetlb_pte_count; |
487 | mm->context.thp_pte_count; | 489 | saved_thp_pte_count = mm->context.thp_pte_count; |
488 | mm->context.hugetlb_pte_count = 0; | 490 | mm->context.hugetlb_pte_count = 0; |
489 | mm->context.thp_pte_count = 0; | 491 | mm->context.thp_pte_count = 0; |
492 | |||
493 | mm_rss -= saved_thp_pte_count * (HPAGE_SIZE / PAGE_SIZE); | ||
490 | #endif | 494 | #endif |
491 | 495 | ||
492 | /* copy_mm() copies over the parent's mm_struct before calling | 496 | /* copy_mm() copies over the parent's mm_struct before calling |
@@ -499,11 +503,13 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) | |||
499 | /* If this is fork, inherit the parent's TSB size. We would | 503 | /* If this is fork, inherit the parent's TSB size. We would |
500 | * grow it to that size on the first page fault anyways. | 504 | * grow it to that size on the first page fault anyways. |
501 | */ | 505 | */ |
502 | tsb_grow(mm, MM_TSB_BASE, get_mm_rss(mm)); | 506 | tsb_grow(mm, MM_TSB_BASE, mm_rss); |
503 | 507 | ||
504 | #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) | 508 | #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) |
505 | if (unlikely(total_huge_pte_count)) | 509 | if (unlikely(saved_hugetlb_pte_count + saved_thp_pte_count)) |
506 | tsb_grow(mm, MM_TSB_HUGE, total_huge_pte_count); | 510 | tsb_grow(mm, MM_TSB_HUGE, |
511 | (saved_hugetlb_pte_count + saved_thp_pte_count) * | ||
512 | REAL_HPAGE_PER_HPAGE); | ||
507 | #endif | 513 | #endif |
508 | 514 | ||
509 | if (unlikely(!mm->context.tsb_block[MM_TSB_BASE].tsb)) | 515 | if (unlikely(!mm->context.tsb_block[MM_TSB_BASE].tsb)) |