diff options
Diffstat (limited to 'arch/sparc/mm')
-rw-r--r-- | arch/sparc/mm/gup.c | 9 | ||||
-rw-r--r-- | arch/sparc/mm/init_64.c | 102 | ||||
-rw-r--r-- | arch/sparc/mm/tlb.c | 9 |
3 files changed, 10 insertions, 110 deletions
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c index 01ee23dd724d..c4d3da68b800 100644 --- a/arch/sparc/mm/gup.c +++ b/arch/sparc/mm/gup.c | |||
@@ -71,13 +71,12 @@ static int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr, | |||
71 | int *nr) | 71 | int *nr) |
72 | { | 72 | { |
73 | struct page *head, *page, *tail; | 73 | struct page *head, *page, *tail; |
74 | u32 mask; | ||
75 | int refs; | 74 | int refs; |
76 | 75 | ||
77 | mask = PMD_HUGE_PRESENT; | 76 | if (!pmd_large(pmd)) |
78 | if (write) | 77 | return 0; |
79 | mask |= PMD_HUGE_WRITE; | 78 | |
80 | if ((pmd_val(pmd) & mask) != mask) | 79 | if (write && !pmd_write(pmd)) |
81 | return 0; | 80 | return 0; |
82 | 81 | ||
83 | refs = 0; | 82 | refs = 0; |
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 828784419e25..bd6430ded69f 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c | |||
@@ -2602,121 +2602,21 @@ void pgtable_free(void *table, bool is_page) | |||
2602 | } | 2602 | } |
2603 | 2603 | ||
2604 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 2604 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
2605 | static pmd_t pmd_set_protbits(pmd_t pmd, pgprot_t pgprot, bool for_modify) | ||
2606 | { | ||
2607 | if (pgprot_val(pgprot) & _PAGE_VALID) | ||
2608 | pmd_val(pmd) |= PMD_HUGE_PRESENT; | ||
2609 | if (tlb_type == hypervisor) { | ||
2610 | if (pgprot_val(pgprot) & _PAGE_WRITE_4V) | ||
2611 | pmd_val(pmd) |= PMD_HUGE_WRITE; | ||
2612 | if (pgprot_val(pgprot) & _PAGE_EXEC_4V) | ||
2613 | pmd_val(pmd) |= PMD_HUGE_EXEC; | ||
2614 | |||
2615 | if (!for_modify) { | ||
2616 | if (pgprot_val(pgprot) & _PAGE_ACCESSED_4V) | ||
2617 | pmd_val(pmd) |= PMD_HUGE_ACCESSED; | ||
2618 | if (pgprot_val(pgprot) & _PAGE_MODIFIED_4V) | ||
2619 | pmd_val(pmd) |= PMD_HUGE_DIRTY; | ||
2620 | } | ||
2621 | } else { | ||
2622 | if (pgprot_val(pgprot) & _PAGE_WRITE_4U) | ||
2623 | pmd_val(pmd) |= PMD_HUGE_WRITE; | ||
2624 | if (pgprot_val(pgprot) & _PAGE_EXEC_4U) | ||
2625 | pmd_val(pmd) |= PMD_HUGE_EXEC; | ||
2626 | |||
2627 | if (!for_modify) { | ||
2628 | if (pgprot_val(pgprot) & _PAGE_ACCESSED_4U) | ||
2629 | pmd_val(pmd) |= PMD_HUGE_ACCESSED; | ||
2630 | if (pgprot_val(pgprot) & _PAGE_MODIFIED_4U) | ||
2631 | pmd_val(pmd) |= PMD_HUGE_DIRTY; | ||
2632 | } | ||
2633 | } | ||
2634 | |||
2635 | return pmd; | ||
2636 | } | ||
2637 | |||
2638 | pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot) | ||
2639 | { | ||
2640 | pmd_t pmd; | ||
2641 | |||
2642 | pmd_val(pmd) = (page_nr << ((PAGE_SHIFT - PMD_PADDR_SHIFT))); | ||
2643 | pmd_val(pmd) |= PMD_ISHUGE; | ||
2644 | pmd = pmd_set_protbits(pmd, pgprot, false); | ||
2645 | return pmd; | ||
2646 | } | ||
2647 | |||
2648 | pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) | ||
2649 | { | ||
2650 | pmd_val(pmd) &= ~(PMD_HUGE_PRESENT | | ||
2651 | PMD_HUGE_WRITE | | ||
2652 | PMD_HUGE_EXEC); | ||
2653 | pmd = pmd_set_protbits(pmd, newprot, true); | ||
2654 | return pmd; | ||
2655 | } | ||
2656 | |||
2657 | pgprot_t pmd_pgprot(pmd_t entry) | ||
2658 | { | ||
2659 | unsigned long pte = 0; | ||
2660 | |||
2661 | if (pmd_val(entry) & PMD_HUGE_PRESENT) | ||
2662 | pte |= _PAGE_VALID; | ||
2663 | |||
2664 | if (tlb_type == hypervisor) { | ||
2665 | if (pmd_val(entry) & PMD_HUGE_PRESENT) | ||
2666 | pte |= _PAGE_PRESENT_4V; | ||
2667 | if (pmd_val(entry) & PMD_HUGE_EXEC) | ||
2668 | pte |= _PAGE_EXEC_4V; | ||
2669 | if (pmd_val(entry) & PMD_HUGE_WRITE) | ||
2670 | pte |= _PAGE_W_4V; | ||
2671 | if (pmd_val(entry) & PMD_HUGE_ACCESSED) | ||
2672 | pte |= _PAGE_ACCESSED_4V; | ||
2673 | if (pmd_val(entry) & PMD_HUGE_DIRTY) | ||
2674 | pte |= _PAGE_MODIFIED_4V; | ||
2675 | pte |= _PAGE_CP_4V|_PAGE_CV_4V; | ||
2676 | } else { | ||
2677 | if (pmd_val(entry) & PMD_HUGE_PRESENT) | ||
2678 | pte |= _PAGE_PRESENT_4U; | ||
2679 | if (pmd_val(entry) & PMD_HUGE_EXEC) | ||
2680 | pte |= _PAGE_EXEC_4U; | ||
2681 | if (pmd_val(entry) & PMD_HUGE_WRITE) | ||
2682 | pte |= _PAGE_W_4U; | ||
2683 | if (pmd_val(entry) & PMD_HUGE_ACCESSED) | ||
2684 | pte |= _PAGE_ACCESSED_4U; | ||
2685 | if (pmd_val(entry) & PMD_HUGE_DIRTY) | ||
2686 | pte |= _PAGE_MODIFIED_4U; | ||
2687 | pte |= _PAGE_CP_4U|_PAGE_CV_4U; | ||
2688 | } | ||
2689 | |||
2690 | return __pgprot(pte); | ||
2691 | } | ||
2692 | |||
2693 | void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr, | 2605 | void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr, |
2694 | pmd_t *pmd) | 2606 | pmd_t *pmd) |
2695 | { | 2607 | { |
2696 | unsigned long pte, flags; | 2608 | unsigned long pte, flags; |
2697 | struct mm_struct *mm; | 2609 | struct mm_struct *mm; |
2698 | pmd_t entry = *pmd; | 2610 | pmd_t entry = *pmd; |
2699 | pgprot_t prot; | ||
2700 | 2611 | ||
2701 | if (!pmd_large(entry) || !pmd_young(entry)) | 2612 | if (!pmd_large(entry) || !pmd_young(entry)) |
2702 | return; | 2613 | return; |
2703 | 2614 | ||
2704 | pte = (pmd_val(entry) & ~PMD_HUGE_PROTBITS); | 2615 | pte = pmd_val(entry); |
2705 | pte <<= PMD_PADDR_SHIFT; | ||
2706 | pte |= _PAGE_VALID; | ||
2707 | 2616 | ||
2708 | /* We are fabricating 8MB pages using 4MB real hw pages. */ | 2617 | /* We are fabricating 8MB pages using 4MB real hw pages. */ |
2709 | pte |= (addr & (1UL << REAL_HPAGE_SHIFT)); | 2618 | pte |= (addr & (1UL << REAL_HPAGE_SHIFT)); |
2710 | 2619 | ||
2711 | prot = pmd_pgprot(entry); | ||
2712 | |||
2713 | if (tlb_type == hypervisor) | ||
2714 | pgprot_val(prot) |= _PAGE_SZHUGE_4V; | ||
2715 | else | ||
2716 | pgprot_val(prot) |= _PAGE_SZHUGE_4U; | ||
2717 | |||
2718 | pte |= pgprot_val(prot); | ||
2719 | |||
2720 | mm = vma->vm_mm; | 2620 | mm = vma->vm_mm; |
2721 | 2621 | ||
2722 | spin_lock_irqsave(&mm->context.lock, flags); | 2622 | spin_lock_irqsave(&mm->context.lock, flags); |
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index 97d1e56e9863..f1bd83019e71 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c | |||
@@ -161,8 +161,8 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, | |||
161 | if (mm == &init_mm) | 161 | if (mm == &init_mm) |
162 | return; | 162 | return; |
163 | 163 | ||
164 | if ((pmd_val(pmd) ^ pmd_val(orig)) & PMD_ISHUGE) { | 164 | if ((pmd_val(pmd) ^ pmd_val(orig)) & _PAGE_PMD_HUGE) { |
165 | if (pmd_val(pmd) & PMD_ISHUGE) | 165 | if (pmd_val(pmd) & _PAGE_PMD_HUGE) |
166 | mm->context.huge_pte_count++; | 166 | mm->context.huge_pte_count++; |
167 | else | 167 | else |
168 | mm->context.huge_pte_count--; | 168 | mm->context.huge_pte_count--; |
@@ -178,10 +178,11 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, | |||
178 | } | 178 | } |
179 | 179 | ||
180 | if (!pmd_none(orig)) { | 180 | if (!pmd_none(orig)) { |
181 | bool exec = ((pmd_val(orig) & PMD_HUGE_EXEC) != 0); | 181 | pte_t orig_pte = __pte(pmd_val(orig)); |
182 | bool exec = pte_exec(orig_pte); | ||
182 | 183 | ||
183 | addr &= HPAGE_MASK; | 184 | addr &= HPAGE_MASK; |
184 | if (pmd_val(orig) & PMD_ISHUGE) { | 185 | if (pmd_trans_huge(orig)) { |
185 | tlb_batch_add_one(mm, addr, exec); | 186 | tlb_batch_add_one(mm, addr, exec); |
186 | tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec); | 187 | tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec); |
187 | } else { | 188 | } else { |