arch/powerpc/mm/book3s64/slb.c

Source file repositories/reference/linux-study-clean/arch/powerpc/mm/book3s64/slb.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/mm/book3s64/slb.c
Extension
.c
Size
21074 bytes
Lines
796
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (v & SLB_VSID_B_1T) {
			pr_err("     1T ESID=%9lx VSID=%13lx LLP:%3lx\n",
			       GET_ESID_1T(e),
			       (v & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T, llp);
		} else {
			pr_err("   256M ESID=%9lx VSID=%13lx LLP:%3lx\n",
			       GET_ESID(e),
			       (v & ~SLB_VSID_B) >> SLB_VSID_SHIFT, llp);
		}
	}

	if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) {
		/* RR is not so useful as it's often not used for allocation */
		pr_err("SLB RR allocator index %d\n", get_paca()->stab_rr);

		/* Dump slb cache entires as well. */
		pr_err("SLB cache ptr value = %d\n", get_paca()->slb_save_cache_ptr);
		pr_err("Valid SLB cache entries:\n");
		n = min_t(int, get_paca()->slb_save_cache_ptr, SLB_CACHE_ENTRIES);
		for (i = 0; i < n; i++)
			pr_err("%02d EA[0-35]=%9x\n", i, get_paca()->slb_cache[i]);
		pr_err("Rest of SLB cache entries:\n");
		for (i = n; i < SLB_CACHE_ENTRIES; i++)
			pr_err("%02d EA[0-35]=%9x\n", i, get_paca()->slb_cache[i]);
	}
}

void slb_vmalloc_update(void)
{
	/*
	 * vmalloc is not bolted, so just have to flush non-bolted.
	 */
	slb_flush_and_restore_bolted();
}

static bool preload_hit(struct thread_info *ti, unsigned long esid)
{
	unsigned char i;

	for (i = 0; i < ti->slb_preload_nr; i++) {
		unsigned char idx;

		idx = (ti->slb_preload_tail + i) % SLB_PRELOAD_NR;
		if (esid == ti->slb_preload_esid[idx])
			return true;
	}
	return false;
}

static void preload_add(struct thread_info *ti, unsigned long ea)
{
	unsigned char idx;
	unsigned long esid;

	if (slb_preload_disabled())
		return;

	if (mmu_has_feature(MMU_FTR_1T_SEGMENT)) {
		/* EAs are stored >> 28 so 256MB segments don't need clearing */
		if (ea & ESID_MASK_1T)
			ea &= ESID_MASK_1T;
	}

	esid = ea >> SID_SHIFT;

	if (preload_hit(ti, esid))
		return;

	idx = (ti->slb_preload_tail + ti->slb_preload_nr) % SLB_PRELOAD_NR;
	ti->slb_preload_esid[idx] = esid;
	if (ti->slb_preload_nr == SLB_PRELOAD_NR)
		ti->slb_preload_tail = (ti->slb_preload_tail + 1) % SLB_PRELOAD_NR;
	else
		ti->slb_preload_nr++;
}

static void preload_age(struct thread_info *ti)
{
	if (!ti->slb_preload_nr)
		return;
	ti->slb_preload_nr--;
	ti->slb_preload_tail = (ti->slb_preload_tail + 1) % SLB_PRELOAD_NR;
}

static void slb_cache_slbie_kernel(unsigned int index)
{
	unsigned long slbie_data = get_paca()->slb_cache[index];
	unsigned long ksp = get_paca()->kstack;

	slbie_data <<= SID_SHIFT;

Annotation

Implementation Notes