diff options
Diffstat (limited to 'arch/powerpc/mm')
-rw-r--r-- | arch/powerpc/mm/hash_low_64.S | 6 | ||||
-rw-r--r-- | arch/powerpc/mm/hash_utils_64.c | 4 | ||||
-rw-r--r-- | arch/powerpc/mm/numa.c | 4 | ||||
-rw-r--r-- | arch/powerpc/mm/slb.c | 69 | ||||
-rw-r--r-- | arch/powerpc/mm/slice.c | 2 |
5 files changed, 42 insertions, 43 deletions
diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S index 4762ff7c14d..35eabfb5072 100644 --- a/arch/powerpc/mm/hash_low_64.S +++ b/arch/powerpc/mm/hash_low_64.S @@ -472,10 +472,12 @@ _GLOBAL(htab_call_hpte_insert1) /* Now try secondary slot */ /* real page number in r5, PTE RPN value + index */ - rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + andis. r0,r31,_PAGE_4K_PFN@h + srdi r5,r31,PTE_RPN_SHIFT + bne- 3f sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT add r5,r5,r25 - sldi r5,r5,HW_PAGE_SHIFT +3: sldi r5,r5,HW_PAGE_SHIFT /* Calculate secondary group hash */ andc r0,r27,r28 diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index bc7b0cedae5..a47151e806c 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -759,7 +759,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) mmu_psize_defs[mmu_vmalloc_psize].sllp) { get_paca()->vmalloc_sllp = mmu_psize_defs[mmu_vmalloc_psize].sllp; - slb_flush_and_rebolt(); + slb_vmalloc_update(); } #endif /* CONFIG_PPC_64K_PAGES */ @@ -795,7 +795,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, #ifdef CONFIG_PPC_MM_SLICES /* We only prefault standard pages for now */ - if (unlikely(get_slice_psize(mm, ea) != mm->context.user_psize)); + if (unlikely(get_slice_psize(mm, ea) != mm->context.user_psize)) return; #endif diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index de45aa82d97..c12adc3ddff 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -307,9 +307,9 @@ static void __init parse_drconf_memory(struct device_node *memory) const unsigned int *lm, *dm, *aa; unsigned int ls, ld, la; unsigned int n, aam, aalen; - unsigned long lmb_size, size; + unsigned long lmb_size, size, start; int nid, default_nid = 0; - unsigned int start, ai, flags; + unsigned int ai, flags; lm = of_get_property(memory, "ibm,lmb-size", &ls); dm = of_get_property(memory, "ibm,dynamic-memory", &ld); diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index 304375a7357..a73d2d70097 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c @@ -53,7 +53,8 @@ static inline unsigned long mk_vsid_data(unsigned long ea, unsigned long flags) return (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | flags; } -static inline void slb_shadow_update(unsigned long esid, unsigned long vsid, +static inline void slb_shadow_update(unsigned long ea, + unsigned long flags, unsigned long entry) { /* @@ -61,28 +62,16 @@ static inline void slb_shadow_update(unsigned long esid, unsigned long vsid, * updating it. */ get_slb_shadow()->save_area[entry].esid = 0; - barrier(); - get_slb_shadow()->save_area[entry].vsid = vsid; - barrier(); - get_slb_shadow()->save_area[entry].esid = esid; - + smp_wmb(); + get_slb_shadow()->save_area[entry].vsid = mk_vsid_data(ea, flags); + smp_wmb(); + get_slb_shadow()->save_area[entry].esid = mk_esid_data(ea, entry); + smp_wmb(); } -static inline void create_shadowed_slbe(unsigned long ea, unsigned long flags, - unsigned long entry) +static inline void slb_shadow_clear(unsigned long entry) { - /* - * Updating the shadow buffer before writing the SLB ensures - * we don't get a stale entry here if we get preempted by PHYP - * between these two statements. - */ - slb_shadow_update(mk_esid_data(ea, entry), mk_vsid_data(ea, flags), - entry); - - asm volatile("slbmte %0,%1" : - : "r" (mk_vsid_data(ea, flags)), - "r" (mk_esid_data(ea, entry)) - : "memory" ); + get_slb_shadow()->save_area[entry].esid = 0; } void slb_flush_and_rebolt(void) @@ -100,12 +89,13 @@ void slb_flush_and_rebolt(void) vflags = SLB_VSID_KERNEL | vmalloc_llp; ksp_esid_data = mk_esid_data(get_paca()->kstack, 2); - if ((ksp_esid_data & ESID_MASK) == PAGE_OFFSET) + if ((ksp_esid_data & ESID_MASK) == PAGE_OFFSET) { ksp_esid_data &= ~SLB_ESID_V; - - /* Only third entry (stack) may change here so only resave that */ - slb_shadow_update(ksp_esid_data, - mk_vsid_data(ksp_esid_data, lflags), 2); + slb_shadow_clear(2); + } else { + /* Update stack entry; others don't change */ + slb_shadow_update(get_paca()->kstack, lflags, 2); + } /* We need to do this all in asm, so we're sure we don't touch * the stack between the slbia and rebolting it. */ @@ -123,6 +113,15 @@ void slb_flush_and_rebolt(void) : "memory"); } +void slb_vmalloc_update(void) +{ + unsigned long vflags; + + vflags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_vmalloc_psize].sllp; + slb_shadow_update(VMALLOC_START, vflags, 1); + slb_flush_and_rebolt(); +} + /* Flush all user entries from the segment table of the current processor. */ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) { @@ -227,16 +226,12 @@ void slb_initialize(void) vflags = SLB_VSID_KERNEL | vmalloc_llp; /* Invalidate the entire SLB (even slot 0) & all the ERATS */ - asm volatile("isync":::"memory"); - asm volatile("slbmte %0,%0"::"r" (0) : "memory"); - asm volatile("isync; slbia; isync":::"memory"); - create_shadowed_slbe(PAGE_OFFSET, lflags, 0); - - create_shadowed_slbe(VMALLOC_START, vflags, 1); - - /* We don't bolt the stack for the time being - we're in boot, - * so the stack is in the bolted segment. By the time it goes - * elsewhere, we'll call _switch() which will bolt in the new - * one. */ - asm volatile("isync":::"memory"); + slb_shadow_update(PAGE_OFFSET, lflags, 0); + asm volatile("isync; slbia; sync; slbmte %0,%1; isync" :: + "r" (get_slb_shadow()->save_area[0].vsid), + "r" (get_slb_shadow()->save_area[0].esid) : "memory"); + + slb_shadow_update(VMALLOC_START, vflags, 1); + + slb_flush_and_rebolt(); } diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c index f833dba2a02..d5fd3909d13 100644 --- a/arch/powerpc/mm/slice.c +++ b/arch/powerpc/mm/slice.c @@ -405,6 +405,8 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, if (len > mm->task_size) return -ENOMEM; + if (len & ((1ul << pshift) - 1)) + return -EINVAL; if (fixed && (addr & ((1ul << pshift) - 1))) return -EINVAL; if (fixed && addr > (mm->task_size - len)) |