12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
247d99948SChristophe Leroy /*
347d99948SChristophe Leroy * PowerPC64 SLB support.
447d99948SChristophe Leroy *
547d99948SChristophe Leroy * Copyright (C) 2004 David Gibson <dwg@au.ibm.com>, IBM
647d99948SChristophe Leroy * Based on earlier code written by:
747d99948SChristophe Leroy * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com
847d99948SChristophe Leroy * Copyright (c) 2001 Dave Engebretsen
947d99948SChristophe Leroy * Copyright (C) 2002 Anton Blanchard <anton@au.ibm.com>, IBM
1047d99948SChristophe Leroy */
1147d99948SChristophe Leroy
123a96570fSNicholas Piggin #include <asm/interrupt.h>
1347d99948SChristophe Leroy #include <asm/mmu.h>
1447d99948SChristophe Leroy #include <asm/mmu_context.h>
1547d99948SChristophe Leroy #include <asm/paca.h>
16*1aa00066SMichael Ellerman #include <asm/lppaca.h>
1747d99948SChristophe Leroy #include <asm/ppc-opcode.h>
1847d99948SChristophe Leroy #include <asm/cputable.h>
1947d99948SChristophe Leroy #include <asm/cacheflush.h>
2047d99948SChristophe Leroy #include <asm/smp.h>
2147d99948SChristophe Leroy #include <linux/compiler.h>
2247d99948SChristophe Leroy #include <linux/context_tracking.h>
2347d99948SChristophe Leroy #include <linux/mm_types.h>
2465fddcfcSMike Rapoport #include <linux/pgtable.h>
2547d99948SChristophe Leroy
2647d99948SChristophe Leroy #include <asm/udbg.h>
2747d99948SChristophe Leroy #include <asm/code-patching.h>
2847d99948SChristophe Leroy
2982a1b8edSNicholas Piggin #include "internal.h"
3082a1b8edSNicholas Piggin
3182a1b8edSNicholas Piggin
3247d99948SChristophe Leroy static long slb_allocate_user(struct mm_struct *mm, unsigned long ea);
3347d99948SChristophe Leroy
3482a1b8edSNicholas Piggin bool stress_slb_enabled __initdata;
3582a1b8edSNicholas Piggin
parse_stress_slb(char * p)3682a1b8edSNicholas Piggin static int __init parse_stress_slb(char *p)
3782a1b8edSNicholas Piggin {
3882a1b8edSNicholas Piggin stress_slb_enabled = true;
3982a1b8edSNicholas Piggin return 0;
4082a1b8edSNicholas Piggin }
4182a1b8edSNicholas Piggin early_param("stress_slb", parse_stress_slb);
4282a1b8edSNicholas Piggin
4382a1b8edSNicholas Piggin __ro_after_init DEFINE_STATIC_KEY_FALSE(stress_slb_key);
4482a1b8edSNicholas Piggin
assert_slb_presence(bool present,unsigned long ea)4547d99948SChristophe Leroy static void assert_slb_presence(bool present, unsigned long ea)
4647d99948SChristophe Leroy {
4747d99948SChristophe Leroy #ifdef CONFIG_DEBUG_VM
4847d99948SChristophe Leroy unsigned long tmp;
4947d99948SChristophe Leroy
5047d99948SChristophe Leroy WARN_ON_ONCE(mfmsr() & MSR_EE);
5147d99948SChristophe Leroy
5247d99948SChristophe Leroy if (!cpu_has_feature(CPU_FTR_ARCH_206))
5347d99948SChristophe Leroy return;
5447d99948SChristophe Leroy
5547d99948SChristophe Leroy /*
5647d99948SChristophe Leroy * slbfee. requires bit 24 (PPC bit 39) be clear in RB. Hardware
5747d99948SChristophe Leroy * ignores all other bits from 0-27, so just clear them all.
5847d99948SChristophe Leroy */
5982a1b8edSNicholas Piggin ea &= ~((1UL << SID_SHIFT) - 1);
6047d99948SChristophe Leroy asm volatile(__PPC_SLBFEE_DOT(%0, %1) : "=r"(tmp) : "r"(ea) : "cr0");
6147d99948SChristophe Leroy
6247d99948SChristophe Leroy WARN_ON(present == (tmp == 0));
6347d99948SChristophe Leroy #endif
6447d99948SChristophe Leroy }
6547d99948SChristophe Leroy
slb_shadow_update(unsigned long ea,int ssize,unsigned long flags,enum slb_index index)6647d99948SChristophe Leroy static inline void slb_shadow_update(unsigned long ea, int ssize,
6747d99948SChristophe Leroy unsigned long flags,
6847d99948SChristophe Leroy enum slb_index index)
6947d99948SChristophe Leroy {
7047d99948SChristophe Leroy struct slb_shadow *p = get_slb_shadow();
7147d99948SChristophe Leroy
7247d99948SChristophe Leroy /*
7347d99948SChristophe Leroy * Clear the ESID first so the entry is not valid while we are
7447d99948SChristophe Leroy * updating it. No write barriers are needed here, provided
7547d99948SChristophe Leroy * we only update the current CPU's SLB shadow buffer.
7647d99948SChristophe Leroy */
7747d99948SChristophe Leroy WRITE_ONCE(p->save_area[index].esid, 0);
7847d99948SChristophe Leroy WRITE_ONCE(p->save_area[index].vsid, cpu_to_be64(mk_vsid_data(ea, ssize, flags)));
7947d99948SChristophe Leroy WRITE_ONCE(p->save_area[index].esid, cpu_to_be64(mk_esid_data(ea, ssize, index)));
8047d99948SChristophe Leroy }
8147d99948SChristophe Leroy
slb_shadow_clear(enum slb_index index)8247d99948SChristophe Leroy static inline void slb_shadow_clear(enum slb_index index)
8347d99948SChristophe Leroy {
8447d99948SChristophe Leroy WRITE_ONCE(get_slb_shadow()->save_area[index].esid, cpu_to_be64(index));
8547d99948SChristophe Leroy }
8647d99948SChristophe Leroy
create_shadowed_slbe(unsigned long ea,int ssize,unsigned long flags,enum slb_index index)8747d99948SChristophe Leroy static inline void create_shadowed_slbe(unsigned long ea, int ssize,
8847d99948SChristophe Leroy unsigned long flags,
8947d99948SChristophe Leroy enum slb_index index)
9047d99948SChristophe Leroy {
9147d99948SChristophe Leroy /*
9247d99948SChristophe Leroy * Updating the shadow buffer before writing the SLB ensures
9347d99948SChristophe Leroy * we don't get a stale entry here if we get preempted by PHYP
9447d99948SChristophe Leroy * between these two statements.
9547d99948SChristophe Leroy */
9647d99948SChristophe Leroy slb_shadow_update(ea, ssize, flags, index);
9747d99948SChristophe Leroy
9847d99948SChristophe Leroy assert_slb_presence(false, ea);
9947d99948SChristophe Leroy asm volatile("slbmte %0,%1" :
10047d99948SChristophe Leroy : "r" (mk_vsid_data(ea, ssize, flags)),
10147d99948SChristophe Leroy "r" (mk_esid_data(ea, ssize, index))
10247d99948SChristophe Leroy : "memory" );
10347d99948SChristophe Leroy }
10447d99948SChristophe Leroy
10547d99948SChristophe Leroy /*
10647d99948SChristophe Leroy * Insert bolted entries into SLB (which may not be empty, so don't clear
10747d99948SChristophe Leroy * slb_cache_ptr).
10847d99948SChristophe Leroy */
__slb_restore_bolted_realmode(void)10947d99948SChristophe Leroy void __slb_restore_bolted_realmode(void)
11047d99948SChristophe Leroy {
11147d99948SChristophe Leroy struct slb_shadow *p = get_slb_shadow();
11247d99948SChristophe Leroy enum slb_index index;
11347d99948SChristophe Leroy
11447d99948SChristophe Leroy /* No isync needed because realmode. */
11547d99948SChristophe Leroy for (index = 0; index < SLB_NUM_BOLTED; index++) {
11647d99948SChristophe Leroy asm volatile("slbmte %0,%1" :
11747d99948SChristophe Leroy : "r" (be64_to_cpu(p->save_area[index].vsid)),
11847d99948SChristophe Leroy "r" (be64_to_cpu(p->save_area[index].esid)));
11947d99948SChristophe Leroy }
12047d99948SChristophe Leroy
12147d99948SChristophe Leroy assert_slb_presence(true, local_paca->kstack);
12247d99948SChristophe Leroy }
12347d99948SChristophe Leroy
12447d99948SChristophe Leroy /*
12547d99948SChristophe Leroy * Insert the bolted entries into an empty SLB.
12647d99948SChristophe Leroy */
slb_restore_bolted_realmode(void)12747d99948SChristophe Leroy void slb_restore_bolted_realmode(void)
12847d99948SChristophe Leroy {
12947d99948SChristophe Leroy __slb_restore_bolted_realmode();
13047d99948SChristophe Leroy get_paca()->slb_cache_ptr = 0;
13147d99948SChristophe Leroy
13247d99948SChristophe Leroy get_paca()->slb_kern_bitmap = (1U << SLB_NUM_BOLTED) - 1;
13347d99948SChristophe Leroy get_paca()->slb_used_bitmap = get_paca()->slb_kern_bitmap;
13447d99948SChristophe Leroy }
13547d99948SChristophe Leroy
13647d99948SChristophe Leroy /*
13747d99948SChristophe Leroy * This flushes all SLB entries including 0, so it must be realmode.
13847d99948SChristophe Leroy */
slb_flush_all_realmode(void)13947d99948SChristophe Leroy void slb_flush_all_realmode(void)
14047d99948SChristophe Leroy {
14147d99948SChristophe Leroy asm volatile("slbmte %0,%0; slbia" : : "r" (0));
14247d99948SChristophe Leroy }
14347d99948SChristophe Leroy
__slb_flush_and_restore_bolted(bool preserve_kernel_lookaside)14482a1b8edSNicholas Piggin static __always_inline void __slb_flush_and_restore_bolted(bool preserve_kernel_lookaside)
14582a1b8edSNicholas Piggin {
14682a1b8edSNicholas Piggin struct slb_shadow *p = get_slb_shadow();
14782a1b8edSNicholas Piggin unsigned long ksp_esid_data, ksp_vsid_data;
14882a1b8edSNicholas Piggin u32 ih;
14982a1b8edSNicholas Piggin
15082a1b8edSNicholas Piggin /*
15182a1b8edSNicholas Piggin * SLBIA IH=1 on ISA v2.05 and newer processors may preserve lookaside
15282a1b8edSNicholas Piggin * information created with Class=0 entries, which we use for kernel
15382a1b8edSNicholas Piggin * SLB entries (the SLB entries themselves are still invalidated).
15482a1b8edSNicholas Piggin *
15582a1b8edSNicholas Piggin * Older processors will ignore this optimisation. Over-invalidation
15682a1b8edSNicholas Piggin * is fine because we never rely on lookaside information existing.
15782a1b8edSNicholas Piggin */
15882a1b8edSNicholas Piggin if (preserve_kernel_lookaside)
15982a1b8edSNicholas Piggin ih = 1;
16082a1b8edSNicholas Piggin else
16182a1b8edSNicholas Piggin ih = 0;
16282a1b8edSNicholas Piggin
16382a1b8edSNicholas Piggin ksp_esid_data = be64_to_cpu(p->save_area[KSTACK_INDEX].esid);
16482a1b8edSNicholas Piggin ksp_vsid_data = be64_to_cpu(p->save_area[KSTACK_INDEX].vsid);
16582a1b8edSNicholas Piggin
16682a1b8edSNicholas Piggin asm volatile(PPC_SLBIA(%0)" \n"
16782a1b8edSNicholas Piggin "slbmte %1, %2 \n"
16882a1b8edSNicholas Piggin :: "i" (ih),
16982a1b8edSNicholas Piggin "r" (ksp_vsid_data),
17082a1b8edSNicholas Piggin "r" (ksp_esid_data)
17182a1b8edSNicholas Piggin : "memory");
17282a1b8edSNicholas Piggin }
17382a1b8edSNicholas Piggin
17447d99948SChristophe Leroy /*
17547d99948SChristophe Leroy * This flushes non-bolted entries, it can be run in virtual mode. Must
17647d99948SChristophe Leroy * be called with interrupts disabled.
17747d99948SChristophe Leroy */
slb_flush_and_restore_bolted(void)17847d99948SChristophe Leroy void slb_flush_and_restore_bolted(void)
17947d99948SChristophe Leroy {
18047d99948SChristophe Leroy BUILD_BUG_ON(SLB_NUM_BOLTED != 2);
18147d99948SChristophe Leroy
18247d99948SChristophe Leroy WARN_ON(!irqs_disabled());
18347d99948SChristophe Leroy
18447d99948SChristophe Leroy /*
18547d99948SChristophe Leroy * We can't take a PMU exception in the following code, so hard
18647d99948SChristophe Leroy * disable interrupts.
18747d99948SChristophe Leroy */
18847d99948SChristophe Leroy hard_irq_disable();
18947d99948SChristophe Leroy
19082a1b8edSNicholas Piggin isync();
19182a1b8edSNicholas Piggin __slb_flush_and_restore_bolted(false);
19282a1b8edSNicholas Piggin isync();
19382a1b8edSNicholas Piggin
19447d99948SChristophe Leroy assert_slb_presence(true, get_paca()->kstack);
19547d99948SChristophe Leroy
19647d99948SChristophe Leroy get_paca()->slb_cache_ptr = 0;
19747d99948SChristophe Leroy
19847d99948SChristophe Leroy get_paca()->slb_kern_bitmap = (1U << SLB_NUM_BOLTED) - 1;
19947d99948SChristophe Leroy get_paca()->slb_used_bitmap = get_paca()->slb_kern_bitmap;
20047d99948SChristophe Leroy }
20147d99948SChristophe Leroy
slb_save_contents(struct slb_entry * slb_ptr)20247d99948SChristophe Leroy void slb_save_contents(struct slb_entry *slb_ptr)
20347d99948SChristophe Leroy {
20447d99948SChristophe Leroy int i;
20547d99948SChristophe Leroy unsigned long e, v;
20647d99948SChristophe Leroy
20747d99948SChristophe Leroy /* Save slb_cache_ptr value. */
20847d99948SChristophe Leroy get_paca()->slb_save_cache_ptr = get_paca()->slb_cache_ptr;
20947d99948SChristophe Leroy
21047d99948SChristophe Leroy if (!slb_ptr)
21147d99948SChristophe Leroy return;
21247d99948SChristophe Leroy
21347d99948SChristophe Leroy for (i = 0; i < mmu_slb_size; i++) {
21447d99948SChristophe Leroy asm volatile("slbmfee %0,%1" : "=r" (e) : "r" (i));
21547d99948SChristophe Leroy asm volatile("slbmfev %0,%1" : "=r" (v) : "r" (i));
21647d99948SChristophe Leroy slb_ptr->esid = e;
21747d99948SChristophe Leroy slb_ptr->vsid = v;
21847d99948SChristophe Leroy slb_ptr++;
21947d99948SChristophe Leroy }
22047d99948SChristophe Leroy }
22147d99948SChristophe Leroy
slb_dump_contents(struct slb_entry * slb_ptr)22247d99948SChristophe Leroy void slb_dump_contents(struct slb_entry *slb_ptr)
22347d99948SChristophe Leroy {
22447d99948SChristophe Leroy int i, n;
22547d99948SChristophe Leroy unsigned long e, v;
22647d99948SChristophe Leroy unsigned long llp;
22747d99948SChristophe Leroy
22847d99948SChristophe Leroy if (!slb_ptr)
22947d99948SChristophe Leroy return;
23047d99948SChristophe Leroy
23147d99948SChristophe Leroy pr_err("SLB contents of cpu 0x%x\n", smp_processor_id());
23247d99948SChristophe Leroy
23347d99948SChristophe Leroy for (i = 0; i < mmu_slb_size; i++) {
23447d99948SChristophe Leroy e = slb_ptr->esid;
23547d99948SChristophe Leroy v = slb_ptr->vsid;
23647d99948SChristophe Leroy slb_ptr++;
23747d99948SChristophe Leroy
23847d99948SChristophe Leroy if (!e && !v)
23947d99948SChristophe Leroy continue;
24047d99948SChristophe Leroy
241865ae6f2SNicholas Piggin pr_err("%02d %016lx %016lx %s\n", i, e, v,
242865ae6f2SNicholas Piggin (e & SLB_ESID_V) ? "VALID" : "NOT VALID");
24347d99948SChristophe Leroy
244865ae6f2SNicholas Piggin if (!(e & SLB_ESID_V))
24547d99948SChristophe Leroy continue;
246865ae6f2SNicholas Piggin
24747d99948SChristophe Leroy llp = v & SLB_VSID_LLP;
24847d99948SChristophe Leroy if (v & SLB_VSID_B_1T) {
24947d99948SChristophe Leroy pr_err(" 1T ESID=%9lx VSID=%13lx LLP:%3lx\n",
25047d99948SChristophe Leroy GET_ESID_1T(e),
25147d99948SChristophe Leroy (v & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T, llp);
25247d99948SChristophe Leroy } else {
25347d99948SChristophe Leroy pr_err(" 256M ESID=%9lx VSID=%13lx LLP:%3lx\n",
25447d99948SChristophe Leroy GET_ESID(e),
25547d99948SChristophe Leroy (v & ~SLB_VSID_B) >> SLB_VSID_SHIFT, llp);
25647d99948SChristophe Leroy }
25747d99948SChristophe Leroy }
258865ae6f2SNicholas Piggin
259865ae6f2SNicholas Piggin if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) {
260865ae6f2SNicholas Piggin /* RR is not so useful as it's often not used for allocation */
261865ae6f2SNicholas Piggin pr_err("SLB RR allocator index %d\n", get_paca()->stab_rr);
26247d99948SChristophe Leroy
26347d99948SChristophe Leroy /* Dump slb cache entires as well. */
26447d99948SChristophe Leroy pr_err("SLB cache ptr value = %d\n", get_paca()->slb_save_cache_ptr);
26547d99948SChristophe Leroy pr_err("Valid SLB cache entries:\n");
26647d99948SChristophe Leroy n = min_t(int, get_paca()->slb_save_cache_ptr, SLB_CACHE_ENTRIES);
26747d99948SChristophe Leroy for (i = 0; i < n; i++)
26847d99948SChristophe Leroy pr_err("%02d EA[0-35]=%9x\n", i, get_paca()->slb_cache[i]);
26947d99948SChristophe Leroy pr_err("Rest of SLB cache entries:\n");
27047d99948SChristophe Leroy for (i = n; i < SLB_CACHE_ENTRIES; i++)
27147d99948SChristophe Leroy pr_err("%02d EA[0-35]=%9x\n", i, get_paca()->slb_cache[i]);
27247d99948SChristophe Leroy }
273865ae6f2SNicholas Piggin }
27447d99948SChristophe Leroy
slb_vmalloc_update(void)27547d99948SChristophe Leroy void slb_vmalloc_update(void)
27647d99948SChristophe Leroy {
27747d99948SChristophe Leroy /*
27847d99948SChristophe Leroy * vmalloc is not bolted, so just have to flush non-bolted.
27947d99948SChristophe Leroy */
28047d99948SChristophe Leroy slb_flush_and_restore_bolted();
28147d99948SChristophe Leroy }
28247d99948SChristophe Leroy
preload_hit(struct thread_info * ti,unsigned long esid)28347d99948SChristophe Leroy static bool preload_hit(struct thread_info *ti, unsigned long esid)
28447d99948SChristophe Leroy {
28547d99948SChristophe Leroy unsigned char i;
28647d99948SChristophe Leroy
28747d99948SChristophe Leroy for (i = 0; i < ti->slb_preload_nr; i++) {
28847d99948SChristophe Leroy unsigned char idx;
28947d99948SChristophe Leroy
29047d99948SChristophe Leroy idx = (ti->slb_preload_tail + i) % SLB_PRELOAD_NR;
29147d99948SChristophe Leroy if (esid == ti->slb_preload_esid[idx])
29247d99948SChristophe Leroy return true;
29347d99948SChristophe Leroy }
29447d99948SChristophe Leroy return false;
29547d99948SChristophe Leroy }
29647d99948SChristophe Leroy
preload_add(struct thread_info * ti,unsigned long ea)29747d99948SChristophe Leroy static bool preload_add(struct thread_info *ti, unsigned long ea)
29847d99948SChristophe Leroy {
29947d99948SChristophe Leroy unsigned char idx;
30047d99948SChristophe Leroy unsigned long esid;
30147d99948SChristophe Leroy
30247d99948SChristophe Leroy if (mmu_has_feature(MMU_FTR_1T_SEGMENT)) {
30347d99948SChristophe Leroy /* EAs are stored >> 28 so 256MB segments don't need clearing */
30447d99948SChristophe Leroy if (ea & ESID_MASK_1T)
30547d99948SChristophe Leroy ea &= ESID_MASK_1T;
30647d99948SChristophe Leroy }
30747d99948SChristophe Leroy
30847d99948SChristophe Leroy esid = ea >> SID_SHIFT;
30947d99948SChristophe Leroy
31047d99948SChristophe Leroy if (preload_hit(ti, esid))
31147d99948SChristophe Leroy return false;
31247d99948SChristophe Leroy
31347d99948SChristophe Leroy idx = (ti->slb_preload_tail + ti->slb_preload_nr) % SLB_PRELOAD_NR;
31447d99948SChristophe Leroy ti->slb_preload_esid[idx] = esid;
31547d99948SChristophe Leroy if (ti->slb_preload_nr == SLB_PRELOAD_NR)
31647d99948SChristophe Leroy ti->slb_preload_tail = (ti->slb_preload_tail + 1) % SLB_PRELOAD_NR;
31747d99948SChristophe Leroy else
31847d99948SChristophe Leroy ti->slb_preload_nr++;
31947d99948SChristophe Leroy
32047d99948SChristophe Leroy return true;
32147d99948SChristophe Leroy }
32247d99948SChristophe Leroy
preload_age(struct thread_info * ti)32347d99948SChristophe Leroy static void preload_age(struct thread_info *ti)
32447d99948SChristophe Leroy {
32547d99948SChristophe Leroy if (!ti->slb_preload_nr)
32647d99948SChristophe Leroy return;
32747d99948SChristophe Leroy ti->slb_preload_nr--;
32847d99948SChristophe Leroy ti->slb_preload_tail = (ti->slb_preload_tail + 1) % SLB_PRELOAD_NR;
32947d99948SChristophe Leroy }
33047d99948SChristophe Leroy
slb_setup_new_exec(void)33147d99948SChristophe Leroy void slb_setup_new_exec(void)
33247d99948SChristophe Leroy {
33347d99948SChristophe Leroy struct thread_info *ti = current_thread_info();
33447d99948SChristophe Leroy struct mm_struct *mm = current->mm;
33547d99948SChristophe Leroy unsigned long exec = 0x10000000;
33647d99948SChristophe Leroy
33747d99948SChristophe Leroy WARN_ON(irqs_disabled());
33847d99948SChristophe Leroy
33947d99948SChristophe Leroy /*
34047d99948SChristophe Leroy * preload cache can only be used to determine whether a SLB
34147d99948SChristophe Leroy * entry exists if it does not start to overflow.
34247d99948SChristophe Leroy */
34347d99948SChristophe Leroy if (ti->slb_preload_nr + 2 > SLB_PRELOAD_NR)
34447d99948SChristophe Leroy return;
34547d99948SChristophe Leroy
34647d99948SChristophe Leroy hard_irq_disable();
34747d99948SChristophe Leroy
34847d99948SChristophe Leroy /*
34947d99948SChristophe Leroy * We have no good place to clear the slb preload cache on exec,
35047d99948SChristophe Leroy * flush_thread is about the earliest arch hook but that happens
3511fd02f66SJulia Lawall * after we switch to the mm and have already preloaded the SLBEs.
35247d99948SChristophe Leroy *
35347d99948SChristophe Leroy * For the most part that's probably okay to use entries from the
35447d99948SChristophe Leroy * previous exec, they will age out if unused. It may turn out to
35547d99948SChristophe Leroy * be an advantage to clear the cache before switching to it,
35647d99948SChristophe Leroy * however.
35747d99948SChristophe Leroy */
35847d99948SChristophe Leroy
35947d99948SChristophe Leroy /*
36047d99948SChristophe Leroy * preload some userspace segments into the SLB.
36147d99948SChristophe Leroy * Almost all 32 and 64bit PowerPC executables are linked at
36247d99948SChristophe Leroy * 0x10000000 so it makes sense to preload this segment.
36347d99948SChristophe Leroy */
36447d99948SChristophe Leroy if (!is_kernel_addr(exec)) {
36547d99948SChristophe Leroy if (preload_add(ti, exec))
36647d99948SChristophe Leroy slb_allocate_user(mm, exec);
36747d99948SChristophe Leroy }
36847d99948SChristophe Leroy
36947d99948SChristophe Leroy /* Libraries and mmaps. */
37047d99948SChristophe Leroy if (!is_kernel_addr(mm->mmap_base)) {
37147d99948SChristophe Leroy if (preload_add(ti, mm->mmap_base))
37247d99948SChristophe Leroy slb_allocate_user(mm, mm->mmap_base);
37347d99948SChristophe Leroy }
37447d99948SChristophe Leroy
37547d99948SChristophe Leroy /* see switch_slb */
37647d99948SChristophe Leroy asm volatile("isync" : : : "memory");
37747d99948SChristophe Leroy
37847d99948SChristophe Leroy local_irq_enable();
37947d99948SChristophe Leroy }
38047d99948SChristophe Leroy
preload_new_slb_context(unsigned long start,unsigned long sp)38147d99948SChristophe Leroy void preload_new_slb_context(unsigned long start, unsigned long sp)
38247d99948SChristophe Leroy {
38347d99948SChristophe Leroy struct thread_info *ti = current_thread_info();
38447d99948SChristophe Leroy struct mm_struct *mm = current->mm;
38547d99948SChristophe Leroy unsigned long heap = mm->start_brk;
38647d99948SChristophe Leroy
38747d99948SChristophe Leroy WARN_ON(irqs_disabled());
38847d99948SChristophe Leroy
38947d99948SChristophe Leroy /* see above */
39047d99948SChristophe Leroy if (ti->slb_preload_nr + 3 > SLB_PRELOAD_NR)
39147d99948SChristophe Leroy return;
39247d99948SChristophe Leroy
39347d99948SChristophe Leroy hard_irq_disable();
39447d99948SChristophe Leroy
39547d99948SChristophe Leroy /* Userspace entry address. */
39647d99948SChristophe Leroy if (!is_kernel_addr(start)) {
39747d99948SChristophe Leroy if (preload_add(ti, start))
39847d99948SChristophe Leroy slb_allocate_user(mm, start);
39947d99948SChristophe Leroy }
40047d99948SChristophe Leroy
40147d99948SChristophe Leroy /* Top of stack, grows down. */
40247d99948SChristophe Leroy if (!is_kernel_addr(sp)) {
40347d99948SChristophe Leroy if (preload_add(ti, sp))
40447d99948SChristophe Leroy slb_allocate_user(mm, sp);
40547d99948SChristophe Leroy }
40647d99948SChristophe Leroy
40747d99948SChristophe Leroy /* Bottom of heap, grows up. */
40847d99948SChristophe Leroy if (heap && !is_kernel_addr(heap)) {
40947d99948SChristophe Leroy if (preload_add(ti, heap))
41047d99948SChristophe Leroy slb_allocate_user(mm, heap);
41147d99948SChristophe Leroy }
41247d99948SChristophe Leroy
41347d99948SChristophe Leroy /* see switch_slb */
41447d99948SChristophe Leroy asm volatile("isync" : : : "memory");
41547d99948SChristophe Leroy
41647d99948SChristophe Leroy local_irq_enable();
41747d99948SChristophe Leroy }
41847d99948SChristophe Leroy
slb_cache_slbie_kernel(unsigned int index)41982a1b8edSNicholas Piggin static void slb_cache_slbie_kernel(unsigned int index)
42082a1b8edSNicholas Piggin {
42182a1b8edSNicholas Piggin unsigned long slbie_data = get_paca()->slb_cache[index];
42282a1b8edSNicholas Piggin unsigned long ksp = get_paca()->kstack;
42382a1b8edSNicholas Piggin
42482a1b8edSNicholas Piggin slbie_data <<= SID_SHIFT;
42582a1b8edSNicholas Piggin slbie_data |= 0xc000000000000000ULL;
42682a1b8edSNicholas Piggin if ((ksp & slb_esid_mask(mmu_kernel_ssize)) == slbie_data)
42782a1b8edSNicholas Piggin return;
42882a1b8edSNicholas Piggin slbie_data |= mmu_kernel_ssize << SLBIE_SSIZE_SHIFT;
42982a1b8edSNicholas Piggin
43082a1b8edSNicholas Piggin asm volatile("slbie %0" : : "r" (slbie_data));
43182a1b8edSNicholas Piggin }
43282a1b8edSNicholas Piggin
slb_cache_slbie_user(unsigned int index)43382a1b8edSNicholas Piggin static void slb_cache_slbie_user(unsigned int index)
43482a1b8edSNicholas Piggin {
43582a1b8edSNicholas Piggin unsigned long slbie_data = get_paca()->slb_cache[index];
43682a1b8edSNicholas Piggin
43782a1b8edSNicholas Piggin slbie_data <<= SID_SHIFT;
43882a1b8edSNicholas Piggin slbie_data |= user_segment_size(slbie_data) << SLBIE_SSIZE_SHIFT;
43982a1b8edSNicholas Piggin slbie_data |= SLBIE_C; /* user slbs have C=1 */
44082a1b8edSNicholas Piggin
44182a1b8edSNicholas Piggin asm volatile("slbie %0" : : "r" (slbie_data));
44282a1b8edSNicholas Piggin }
44347d99948SChristophe Leroy
44447d99948SChristophe Leroy /* Flush all user entries from the segment table of the current processor. */
switch_slb(struct task_struct * tsk,struct mm_struct * mm)44547d99948SChristophe Leroy void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
44647d99948SChristophe Leroy {
44747d99948SChristophe Leroy struct thread_info *ti = task_thread_info(tsk);
44847d99948SChristophe Leroy unsigned char i;
44947d99948SChristophe Leroy
45047d99948SChristophe Leroy /*
45147d99948SChristophe Leroy * We need interrupts hard-disabled here, not just soft-disabled,
45247d99948SChristophe Leroy * so that a PMU interrupt can't occur, which might try to access
45347d99948SChristophe Leroy * user memory (to get a stack trace) and possible cause an SLB miss
45447d99948SChristophe Leroy * which would update the slb_cache/slb_cache_ptr fields in the PACA.
45547d99948SChristophe Leroy */
45647d99948SChristophe Leroy hard_irq_disable();
45782a1b8edSNicholas Piggin isync();
45882a1b8edSNicholas Piggin if (stress_slb()) {
45982a1b8edSNicholas Piggin __slb_flush_and_restore_bolted(false);
46082a1b8edSNicholas Piggin isync();
46182a1b8edSNicholas Piggin get_paca()->slb_cache_ptr = 0;
46282a1b8edSNicholas Piggin get_paca()->slb_kern_bitmap = (1U << SLB_NUM_BOLTED) - 1;
46382a1b8edSNicholas Piggin
46482a1b8edSNicholas Piggin } else if (cpu_has_feature(CPU_FTR_ARCH_300)) {
46547d99948SChristophe Leroy /*
46647d99948SChristophe Leroy * SLBIA IH=3 invalidates all Class=1 SLBEs and their
46747d99948SChristophe Leroy * associated lookaside structures, which matches what
46847d99948SChristophe Leroy * switch_slb wants. So ARCH_300 does not use the slb
46947d99948SChristophe Leroy * cache.
47047d99948SChristophe Leroy */
47147d99948SChristophe Leroy asm volatile(PPC_SLBIA(3));
47282a1b8edSNicholas Piggin
47347d99948SChristophe Leroy } else {
47447d99948SChristophe Leroy unsigned long offset = get_paca()->slb_cache_ptr;
47547d99948SChristophe Leroy
47647d99948SChristophe Leroy if (!mmu_has_feature(MMU_FTR_NO_SLBIE_B) &&
47747d99948SChristophe Leroy offset <= SLB_CACHE_ENTRIES) {
47847d99948SChristophe Leroy /*
47947d99948SChristophe Leroy * Could assert_slb_presence(true) here, but
48047d99948SChristophe Leroy * hypervisor or machine check could have come
48147d99948SChristophe Leroy * in and removed the entry at this point.
48247d99948SChristophe Leroy */
48347d99948SChristophe Leroy
48482a1b8edSNicholas Piggin for (i = 0; i < offset; i++)
48582a1b8edSNicholas Piggin slb_cache_slbie_user(i);
48647d99948SChristophe Leroy
48747d99948SChristophe Leroy /* Workaround POWER5 < DD2.1 issue */
48847d99948SChristophe Leroy if (!cpu_has_feature(CPU_FTR_ARCH_207S) && offset == 1)
48982a1b8edSNicholas Piggin slb_cache_slbie_user(0);
49047d99948SChristophe Leroy
49147d99948SChristophe Leroy } else {
49282a1b8edSNicholas Piggin /* Flush but retain kernel lookaside information */
49382a1b8edSNicholas Piggin __slb_flush_and_restore_bolted(true);
49482a1b8edSNicholas Piggin isync();
49547d99948SChristophe Leroy
49647d99948SChristophe Leroy get_paca()->slb_kern_bitmap = (1U << SLB_NUM_BOLTED) - 1;
49747d99948SChristophe Leroy }
49847d99948SChristophe Leroy
49947d99948SChristophe Leroy get_paca()->slb_cache_ptr = 0;
50047d99948SChristophe Leroy }
50147d99948SChristophe Leroy get_paca()->slb_used_bitmap = get_paca()->slb_kern_bitmap;
50247d99948SChristophe Leroy
50347d99948SChristophe Leroy copy_mm_to_paca(mm);
50447d99948SChristophe Leroy
50547d99948SChristophe Leroy /*
50647d99948SChristophe Leroy * We gradually age out SLBs after a number of context switches to
50747d99948SChristophe Leroy * reduce reload overhead of unused entries (like we do with FP/VEC
50847d99948SChristophe Leroy * reload). Each time we wrap 256 switches, take an entry out of the
50947d99948SChristophe Leroy * SLB preload cache.
51047d99948SChristophe Leroy */
51147d99948SChristophe Leroy tsk->thread.load_slb++;
51247d99948SChristophe Leroy if (!tsk->thread.load_slb) {
51347d99948SChristophe Leroy unsigned long pc = KSTK_EIP(tsk);
51447d99948SChristophe Leroy
51547d99948SChristophe Leroy preload_age(ti);
51647d99948SChristophe Leroy preload_add(ti, pc);
51747d99948SChristophe Leroy }
51847d99948SChristophe Leroy
51947d99948SChristophe Leroy for (i = 0; i < ti->slb_preload_nr; i++) {
52047d99948SChristophe Leroy unsigned char idx;
52147d99948SChristophe Leroy unsigned long ea;
52247d99948SChristophe Leroy
52347d99948SChristophe Leroy idx = (ti->slb_preload_tail + i) % SLB_PRELOAD_NR;
52447d99948SChristophe Leroy ea = (unsigned long)ti->slb_preload_esid[idx] << SID_SHIFT;
52547d99948SChristophe Leroy
52647d99948SChristophe Leroy slb_allocate_user(mm, ea);
52747d99948SChristophe Leroy }
52847d99948SChristophe Leroy
52947d99948SChristophe Leroy /*
53047d99948SChristophe Leroy * Synchronize slbmte preloads with possible subsequent user memory
53147d99948SChristophe Leroy * address accesses by the kernel (user mode won't happen until
53247d99948SChristophe Leroy * rfid, which is safe).
53347d99948SChristophe Leroy */
53482a1b8edSNicholas Piggin isync();
53547d99948SChristophe Leroy }
53647d99948SChristophe Leroy
slb_set_size(u16 size)53747d99948SChristophe Leroy void slb_set_size(u16 size)
53847d99948SChristophe Leroy {
53947d99948SChristophe Leroy mmu_slb_size = size;
54047d99948SChristophe Leroy }
54147d99948SChristophe Leroy
slb_initialize(void)54247d99948SChristophe Leroy void slb_initialize(void)
54347d99948SChristophe Leroy {
54447d99948SChristophe Leroy unsigned long linear_llp, vmalloc_llp, io_llp;
54547d99948SChristophe Leroy unsigned long lflags;
54647d99948SChristophe Leroy static int slb_encoding_inited;
54747d99948SChristophe Leroy #ifdef CONFIG_SPARSEMEM_VMEMMAP
54847d99948SChristophe Leroy unsigned long vmemmap_llp;
54947d99948SChristophe Leroy #endif
55047d99948SChristophe Leroy
55147d99948SChristophe Leroy /* Prepare our SLB miss handler based on our page size */
55247d99948SChristophe Leroy linear_llp = mmu_psize_defs[mmu_linear_psize].sllp;
55347d99948SChristophe Leroy io_llp = mmu_psize_defs[mmu_io_psize].sllp;
55447d99948SChristophe Leroy vmalloc_llp = mmu_psize_defs[mmu_vmalloc_psize].sllp;
55547d99948SChristophe Leroy get_paca()->vmalloc_sllp = SLB_VSID_KERNEL | vmalloc_llp;
55647d99948SChristophe Leroy #ifdef CONFIG_SPARSEMEM_VMEMMAP
55747d99948SChristophe Leroy vmemmap_llp = mmu_psize_defs[mmu_vmemmap_psize].sllp;
55847d99948SChristophe Leroy #endif
55947d99948SChristophe Leroy if (!slb_encoding_inited) {
56047d99948SChristophe Leroy slb_encoding_inited = 1;
56147d99948SChristophe Leroy pr_devel("SLB: linear LLP = %04lx\n", linear_llp);
56247d99948SChristophe Leroy pr_devel("SLB: io LLP = %04lx\n", io_llp);
56347d99948SChristophe Leroy #ifdef CONFIG_SPARSEMEM_VMEMMAP
56447d99948SChristophe Leroy pr_devel("SLB: vmemmap LLP = %04lx\n", vmemmap_llp);
56547d99948SChristophe Leroy #endif
56647d99948SChristophe Leroy }
56747d99948SChristophe Leroy
56847d99948SChristophe Leroy get_paca()->stab_rr = SLB_NUM_BOLTED - 1;
56947d99948SChristophe Leroy get_paca()->slb_kern_bitmap = (1U << SLB_NUM_BOLTED) - 1;
57047d99948SChristophe Leroy get_paca()->slb_used_bitmap = get_paca()->slb_kern_bitmap;
57147d99948SChristophe Leroy
57247d99948SChristophe Leroy lflags = SLB_VSID_KERNEL | linear_llp;
57347d99948SChristophe Leroy
57447d99948SChristophe Leroy /* Invalidate the entire SLB (even entry 0) & all the ERATS */
57547d99948SChristophe Leroy asm volatile("isync":::"memory");
57647d99948SChristophe Leroy asm volatile("slbmte %0,%0"::"r" (0) : "memory");
57747d99948SChristophe Leroy asm volatile("isync; slbia; isync":::"memory");
57847d99948SChristophe Leroy create_shadowed_slbe(PAGE_OFFSET, mmu_kernel_ssize, lflags, LINEAR_INDEX);
57947d99948SChristophe Leroy
58047d99948SChristophe Leroy /*
58147d99948SChristophe Leroy * For the boot cpu, we're running on the stack in init_thread_union,
58247d99948SChristophe Leroy * which is in the first segment of the linear mapping, and also
58347d99948SChristophe Leroy * get_paca()->kstack hasn't been initialized yet.
58447d99948SChristophe Leroy * For secondary cpus, we need to bolt the kernel stack entry now.
58547d99948SChristophe Leroy */
58647d99948SChristophe Leroy slb_shadow_clear(KSTACK_INDEX);
58747d99948SChristophe Leroy if (raw_smp_processor_id() != boot_cpuid &&
58847d99948SChristophe Leroy (get_paca()->kstack & slb_esid_mask(mmu_kernel_ssize)) > PAGE_OFFSET)
58947d99948SChristophe Leroy create_shadowed_slbe(get_paca()->kstack,
59047d99948SChristophe Leroy mmu_kernel_ssize, lflags, KSTACK_INDEX);
59147d99948SChristophe Leroy
59247d99948SChristophe Leroy asm volatile("isync":::"memory");
59347d99948SChristophe Leroy }
59447d99948SChristophe Leroy
slb_cache_update(unsigned long esid_data)59547d99948SChristophe Leroy static void slb_cache_update(unsigned long esid_data)
59647d99948SChristophe Leroy {
59747d99948SChristophe Leroy int slb_cache_index;
59847d99948SChristophe Leroy
59947d99948SChristophe Leroy if (cpu_has_feature(CPU_FTR_ARCH_300))
60047d99948SChristophe Leroy return; /* ISAv3.0B and later does not use slb_cache */
60147d99948SChristophe Leroy
60282a1b8edSNicholas Piggin if (stress_slb())
60382a1b8edSNicholas Piggin return;
60482a1b8edSNicholas Piggin
60547d99948SChristophe Leroy /*
60647d99948SChristophe Leroy * Now update slb cache entries
60747d99948SChristophe Leroy */
60847d99948SChristophe Leroy slb_cache_index = local_paca->slb_cache_ptr;
60947d99948SChristophe Leroy if (slb_cache_index < SLB_CACHE_ENTRIES) {
61047d99948SChristophe Leroy /*
61147d99948SChristophe Leroy * We have space in slb cache for optimized switch_slb().
61247d99948SChristophe Leroy * Top 36 bits from esid_data as per ISA
61347d99948SChristophe Leroy */
61482a1b8edSNicholas Piggin local_paca->slb_cache[slb_cache_index++] = esid_data >> SID_SHIFT;
61547d99948SChristophe Leroy local_paca->slb_cache_ptr++;
61647d99948SChristophe Leroy } else {
61747d99948SChristophe Leroy /*
61847d99948SChristophe Leroy * Our cache is full and the current cache content strictly
6191fd02f66SJulia Lawall * doesn't indicate the active SLB contents. Bump the ptr
62047d99948SChristophe Leroy * so that switch_slb() will ignore the cache.
62147d99948SChristophe Leroy */
62247d99948SChristophe Leroy local_paca->slb_cache_ptr = SLB_CACHE_ENTRIES + 1;
62347d99948SChristophe Leroy }
62447d99948SChristophe Leroy }
62547d99948SChristophe Leroy
alloc_slb_index(bool kernel)62647d99948SChristophe Leroy static enum slb_index alloc_slb_index(bool kernel)
62747d99948SChristophe Leroy {
62847d99948SChristophe Leroy enum slb_index index;
62947d99948SChristophe Leroy
63047d99948SChristophe Leroy /*
63147d99948SChristophe Leroy * The allocation bitmaps can become out of synch with the SLB
63247d99948SChristophe Leroy * when the _switch code does slbie when bolting a new stack
63347d99948SChristophe Leroy * segment and it must not be anywhere else in the SLB. This leaves
63447d99948SChristophe Leroy * a kernel allocated entry that is unused in the SLB. With very
63547d99948SChristophe Leroy * large systems or small segment sizes, the bitmaps could slowly
63647d99948SChristophe Leroy * fill with these entries. They will eventually be cleared out
63747d99948SChristophe Leroy * by the round robin allocator in that case, so it's probably not
63847d99948SChristophe Leroy * worth accounting for.
63947d99948SChristophe Leroy */
64047d99948SChristophe Leroy
64147d99948SChristophe Leroy /*
64247d99948SChristophe Leroy * SLBs beyond 32 entries are allocated with stab_rr only
64347d99948SChristophe Leroy * POWER7/8/9 have 32 SLB entries, this could be expanded if a
64447d99948SChristophe Leroy * future CPU has more.
64547d99948SChristophe Leroy */
64647d99948SChristophe Leroy if (local_paca->slb_used_bitmap != U32_MAX) {
64747d99948SChristophe Leroy index = ffz(local_paca->slb_used_bitmap);
64847d99948SChristophe Leroy local_paca->slb_used_bitmap |= 1U << index;
64947d99948SChristophe Leroy if (kernel)
65047d99948SChristophe Leroy local_paca->slb_kern_bitmap |= 1U << index;
65147d99948SChristophe Leroy } else {
65247d99948SChristophe Leroy /* round-robin replacement of slb starting at SLB_NUM_BOLTED. */
65347d99948SChristophe Leroy index = local_paca->stab_rr;
65447d99948SChristophe Leroy if (index < (mmu_slb_size - 1))
65547d99948SChristophe Leroy index++;
65647d99948SChristophe Leroy else
65747d99948SChristophe Leroy index = SLB_NUM_BOLTED;
65847d99948SChristophe Leroy local_paca->stab_rr = index;
65947d99948SChristophe Leroy if (index < 32) {
66047d99948SChristophe Leroy if (kernel)
66147d99948SChristophe Leroy local_paca->slb_kern_bitmap |= 1U << index;
66247d99948SChristophe Leroy else
66347d99948SChristophe Leroy local_paca->slb_kern_bitmap &= ~(1U << index);
66447d99948SChristophe Leroy }
66547d99948SChristophe Leroy }
66647d99948SChristophe Leroy BUG_ON(index < SLB_NUM_BOLTED);
66747d99948SChristophe Leroy
66847d99948SChristophe Leroy return index;
66947d99948SChristophe Leroy }
67047d99948SChristophe Leroy
slb_insert_entry(unsigned long ea,unsigned long context,unsigned long flags,int ssize,bool kernel)67147d99948SChristophe Leroy static long slb_insert_entry(unsigned long ea, unsigned long context,
67247d99948SChristophe Leroy unsigned long flags, int ssize, bool kernel)
67347d99948SChristophe Leroy {
67447d99948SChristophe Leroy unsigned long vsid;
67547d99948SChristophe Leroy unsigned long vsid_data, esid_data;
67647d99948SChristophe Leroy enum slb_index index;
67747d99948SChristophe Leroy
67847d99948SChristophe Leroy vsid = get_vsid(context, ea, ssize);
67947d99948SChristophe Leroy if (!vsid)
68047d99948SChristophe Leroy return -EFAULT;
68147d99948SChristophe Leroy
68247d99948SChristophe Leroy /*
68347d99948SChristophe Leroy * There must not be a kernel SLB fault in alloc_slb_index or before
68447d99948SChristophe Leroy * slbmte here or the allocation bitmaps could get out of whack with
68547d99948SChristophe Leroy * the SLB.
68647d99948SChristophe Leroy *
68747d99948SChristophe Leroy * User SLB faults or preloads take this path which might get inlined
68847d99948SChristophe Leroy * into the caller, so add compiler barriers here to ensure unsafe
68947d99948SChristophe Leroy * memory accesses do not come between.
69047d99948SChristophe Leroy */
69147d99948SChristophe Leroy barrier();
69247d99948SChristophe Leroy
69347d99948SChristophe Leroy index = alloc_slb_index(kernel);
69447d99948SChristophe Leroy
69547d99948SChristophe Leroy vsid_data = __mk_vsid_data(vsid, ssize, flags);
69647d99948SChristophe Leroy esid_data = mk_esid_data(ea, ssize, index);
69747d99948SChristophe Leroy
69847d99948SChristophe Leroy /*
69947d99948SChristophe Leroy * No need for an isync before or after this slbmte. The exception
70047d99948SChristophe Leroy * we enter with and the rfid we exit with are context synchronizing.
70147d99948SChristophe Leroy * User preloads should add isync afterwards in case the kernel
70247d99948SChristophe Leroy * accesses user memory before it returns to userspace with rfid.
70347d99948SChristophe Leroy */
70447d99948SChristophe Leroy assert_slb_presence(false, ea);
70582a1b8edSNicholas Piggin if (stress_slb()) {
70682a1b8edSNicholas Piggin int slb_cache_index = local_paca->slb_cache_ptr;
70782a1b8edSNicholas Piggin
70882a1b8edSNicholas Piggin /*
70982a1b8edSNicholas Piggin * stress_slb() does not use slb cache, repurpose as a
71082a1b8edSNicholas Piggin * cache of inserted (non-bolted) kernel SLB entries. All
71182a1b8edSNicholas Piggin * non-bolted kernel entries are flushed on any user fault,
71282a1b8edSNicholas Piggin * or if there are already 3 non-boled kernel entries.
71382a1b8edSNicholas Piggin */
71482a1b8edSNicholas Piggin BUILD_BUG_ON(SLB_CACHE_ENTRIES < 3);
71582a1b8edSNicholas Piggin if (!kernel || slb_cache_index == 3) {
71682a1b8edSNicholas Piggin int i;
71782a1b8edSNicholas Piggin
71882a1b8edSNicholas Piggin for (i = 0; i < slb_cache_index; i++)
71982a1b8edSNicholas Piggin slb_cache_slbie_kernel(i);
72082a1b8edSNicholas Piggin slb_cache_index = 0;
72182a1b8edSNicholas Piggin }
72282a1b8edSNicholas Piggin
72382a1b8edSNicholas Piggin if (kernel)
72482a1b8edSNicholas Piggin local_paca->slb_cache[slb_cache_index++] = esid_data >> SID_SHIFT;
72582a1b8edSNicholas Piggin local_paca->slb_cache_ptr = slb_cache_index;
72682a1b8edSNicholas Piggin }
72747d99948SChristophe Leroy asm volatile("slbmte %0, %1" : : "r" (vsid_data), "r" (esid_data));
72847d99948SChristophe Leroy
72947d99948SChristophe Leroy barrier();
73047d99948SChristophe Leroy
73147d99948SChristophe Leroy if (!kernel)
73247d99948SChristophe Leroy slb_cache_update(esid_data);
73347d99948SChristophe Leroy
73447d99948SChristophe Leroy return 0;
73547d99948SChristophe Leroy }
73647d99948SChristophe Leroy
slb_allocate_kernel(unsigned long ea,unsigned long id)73747d99948SChristophe Leroy static long slb_allocate_kernel(unsigned long ea, unsigned long id)
73847d99948SChristophe Leroy {
73947d99948SChristophe Leroy unsigned long context;
74047d99948SChristophe Leroy unsigned long flags;
74147d99948SChristophe Leroy int ssize;
74247d99948SChristophe Leroy
74347d99948SChristophe Leroy if (id == LINEAR_MAP_REGION_ID) {
74447d99948SChristophe Leroy
745b32d5d7eSAneesh Kumar K.V /* We only support upto H_MAX_PHYSMEM_BITS */
746b32d5d7eSAneesh Kumar K.V if ((ea & EA_MASK) > (1UL << H_MAX_PHYSMEM_BITS))
74747d99948SChristophe Leroy return -EFAULT;
74847d99948SChristophe Leroy
74947d99948SChristophe Leroy flags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_linear_psize].sllp;
75047d99948SChristophe Leroy
75147d99948SChristophe Leroy #ifdef CONFIG_SPARSEMEM_VMEMMAP
75247d99948SChristophe Leroy } else if (id == VMEMMAP_REGION_ID) {
75347d99948SChristophe Leroy
75447d99948SChristophe Leroy if (ea >= H_VMEMMAP_END)
75547d99948SChristophe Leroy return -EFAULT;
75647d99948SChristophe Leroy
75747d99948SChristophe Leroy flags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_vmemmap_psize].sllp;
75847d99948SChristophe Leroy #endif
75947d99948SChristophe Leroy } else if (id == VMALLOC_REGION_ID) {
76047d99948SChristophe Leroy
76147d99948SChristophe Leroy if (ea >= H_VMALLOC_END)
76247d99948SChristophe Leroy return -EFAULT;
76347d99948SChristophe Leroy
76447d99948SChristophe Leroy flags = local_paca->vmalloc_sllp;
76547d99948SChristophe Leroy
76647d99948SChristophe Leroy } else if (id == IO_REGION_ID) {
76747d99948SChristophe Leroy
76847d99948SChristophe Leroy if (ea >= H_KERN_IO_END)
76947d99948SChristophe Leroy return -EFAULT;
77047d99948SChristophe Leroy
77147d99948SChristophe Leroy flags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_io_psize].sllp;
77247d99948SChristophe Leroy
77347d99948SChristophe Leroy } else {
77447d99948SChristophe Leroy return -EFAULT;
77547d99948SChristophe Leroy }
77647d99948SChristophe Leroy
77747d99948SChristophe Leroy ssize = MMU_SEGSIZE_1T;
77847d99948SChristophe Leroy if (!mmu_has_feature(MMU_FTR_1T_SEGMENT))
77947d99948SChristophe Leroy ssize = MMU_SEGSIZE_256M;
78047d99948SChristophe Leroy
78147d99948SChristophe Leroy context = get_kernel_context(ea);
78247d99948SChristophe Leroy
78347d99948SChristophe Leroy return slb_insert_entry(ea, context, flags, ssize, true);
78447d99948SChristophe Leroy }
78547d99948SChristophe Leroy
slb_allocate_user(struct mm_struct * mm,unsigned long ea)78647d99948SChristophe Leroy static long slb_allocate_user(struct mm_struct *mm, unsigned long ea)
78747d99948SChristophe Leroy {
78847d99948SChristophe Leroy unsigned long context;
78947d99948SChristophe Leroy unsigned long flags;
79047d99948SChristophe Leroy int bpsize;
79147d99948SChristophe Leroy int ssize;
79247d99948SChristophe Leroy
79347d99948SChristophe Leroy /*
79447d99948SChristophe Leroy * consider this as bad access if we take a SLB miss
79547d99948SChristophe Leroy * on an address above addr limit.
79647d99948SChristophe Leroy */
79747d99948SChristophe Leroy if (ea >= mm_ctx_slb_addr_limit(&mm->context))
79847d99948SChristophe Leroy return -EFAULT;
79947d99948SChristophe Leroy
80047d99948SChristophe Leroy context = get_user_context(&mm->context, ea);
80147d99948SChristophe Leroy if (!context)
80247d99948SChristophe Leroy return -EFAULT;
80347d99948SChristophe Leroy
80447d99948SChristophe Leroy if (unlikely(ea >= H_PGTABLE_RANGE)) {
80547d99948SChristophe Leroy WARN_ON(1);
80647d99948SChristophe Leroy return -EFAULT;
80747d99948SChristophe Leroy }
80847d99948SChristophe Leroy
80947d99948SChristophe Leroy ssize = user_segment_size(ea);
81047d99948SChristophe Leroy
81147d99948SChristophe Leroy bpsize = get_slice_psize(mm, ea);
81247d99948SChristophe Leroy flags = SLB_VSID_USER | mmu_psize_defs[bpsize].sllp;
81347d99948SChristophe Leroy
81447d99948SChristophe Leroy return slb_insert_entry(ea, context, flags, ssize, false);
81547d99948SChristophe Leroy }
81647d99948SChristophe Leroy
DEFINE_INTERRUPT_HANDLER_RAW(do_slb_fault)8173a96570fSNicholas Piggin DEFINE_INTERRUPT_HANDLER_RAW(do_slb_fault)
81847d99948SChristophe Leroy {
819a01a3f2dSNicholas Piggin unsigned long ea = regs->dar;
82047d99948SChristophe Leroy unsigned long id = get_region_id(ea);
82147d99948SChristophe Leroy
82247d99948SChristophe Leroy /* IRQs are not reconciled here, so can't check irqs_disabled */
82347d99948SChristophe Leroy VM_WARN_ON(mfmsr() & MSR_EE);
82447d99948SChristophe Leroy
825806c0e6eSChristophe Leroy if (regs_is_unrecoverable(regs))
82647d99948SChristophe Leroy return -EINVAL;
82747d99948SChristophe Leroy
82847d99948SChristophe Leroy /*
829e44370abSNicholas Piggin * SLB kernel faults must be very careful not to touch anything that is
830e44370abSNicholas Piggin * not bolted. E.g., PACA and global variables are okay, mm->context
831e44370abSNicholas Piggin * stuff is not. SLB user faults may access all of memory (and induce
832e44370abSNicholas Piggin * one recursive SLB kernel fault), so the kernel fault must not
833e44370abSNicholas Piggin * trample on the user fault state at those points.
834e44370abSNicholas Piggin */
835e44370abSNicholas Piggin
836e44370abSNicholas Piggin /*
8373a96570fSNicholas Piggin * This is a raw interrupt handler, for performance, so that
838e44370abSNicholas Piggin * fast_interrupt_return can be used. The handler must not touch local
839e44370abSNicholas Piggin * irq state, or schedule. We could test for usermode and upgrade to a
840e44370abSNicholas Piggin * normal process context (synchronous) interrupt for those, which
841e44370abSNicholas Piggin * would make them first-class kernel code and able to be traced and
842e44370abSNicholas Piggin * instrumented, although performance would suffer a bit, it would
843e44370abSNicholas Piggin * probably be a good tradeoff.
84447d99948SChristophe Leroy */
84547d99948SChristophe Leroy if (id >= LINEAR_MAP_REGION_ID) {
84647d99948SChristophe Leroy long err;
84747d99948SChristophe Leroy #ifdef CONFIG_DEBUG_VM
84847d99948SChristophe Leroy /* Catch recursive kernel SLB faults. */
84947d99948SChristophe Leroy BUG_ON(local_paca->in_kernel_slb_handler);
85047d99948SChristophe Leroy local_paca->in_kernel_slb_handler = 1;
85147d99948SChristophe Leroy #endif
85247d99948SChristophe Leroy err = slb_allocate_kernel(ea, id);
85347d99948SChristophe Leroy #ifdef CONFIG_DEBUG_VM
85447d99948SChristophe Leroy local_paca->in_kernel_slb_handler = 0;
85547d99948SChristophe Leroy #endif
85647d99948SChristophe Leroy return err;
85747d99948SChristophe Leroy } else {
85847d99948SChristophe Leroy struct mm_struct *mm = current->mm;
85947d99948SChristophe Leroy long err;
86047d99948SChristophe Leroy
86147d99948SChristophe Leroy if (unlikely(!mm))
86247d99948SChristophe Leroy return -EFAULT;
86347d99948SChristophe Leroy
86447d99948SChristophe Leroy err = slb_allocate_user(mm, ea);
86547d99948SChristophe Leroy if (!err)
86647d99948SChristophe Leroy preload_add(current_thread_info(), ea);
86747d99948SChristophe Leroy
86847d99948SChristophe Leroy return err;
86947d99948SChristophe Leroy }
87047d99948SChristophe Leroy }
871