summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/mm')
-rw-r--r--arch/powerpc/mm/hash_low_64.S6
-rw-r--r--arch/powerpc/mm/hash_utils_64.c4
-rw-r--r--arch/powerpc/mm/numa.c4
-rw-r--r--arch/powerpc/mm/slb.c69
-rw-r--r--arch/powerpc/mm/slice.c2
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 4762ff7c14df..35eabfb50723 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 bc7b0cedae5e..a47151e806ca 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 de45aa82d97b..c12adc3ddffd 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 304375a73574..a73d2d700973 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 f833dba2a028..d5fd3909d13a 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))