arch/nios2/mm/tlb.c

Source file repositories/reference/linux-study-clean/arch/nios2/mm/tlb.c

File Facts

System
Linux kernel
Corpus path
arch/nios2/mm/tlb.c
Extension
.c
Size
7739 bytes
Lines
305
Domain
Architecture Layer
Bucket
arch/nios2
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 ((tlbacc << PAGE_SHIFT) != 0) {
			pr_debug("-- way:%02x vpn:0x%08lx phys:0x%08lx pid:0x%02lx flags:%c%c%c%c%c\n",
				way,
				(pteaddr << (PAGE_SHIFT-2)),
				(tlbacc << PAGE_SHIFT),
				((tlbmisc >> TLBMISC_PID_SHIFT) &
				TLBMISC_PID_MASK),
				(tlbacc & _PAGE_READ ? 'r' : '-'),
				(tlbacc & _PAGE_WRITE ? 'w' : '-'),
				(tlbacc & _PAGE_EXEC ? 'x' : '-'),
				(tlbacc & _PAGE_GLOBAL ? 'g' : '-'),
				(tlbacc & _PAGE_CACHED ? 'c' : '-'));
		}
	}

	WRCTL(CTL_TLBMISC, org_misc);
}

void dump_tlb(void)
{
	unsigned int i;

	for (i = 0; i < cpuinfo.tlb_num_lines; i++)
		dump_tlb_line(i);
}

void flush_tlb_pid(unsigned long mmu_pid)
{
	unsigned long addr = 0;
	unsigned int line;
	unsigned int way;
	unsigned long org_misc, pid_misc;

	/* remember pid/way until we return */
	get_misc_and_pid(&org_misc, &pid_misc);

	for (line = 0; line < cpuinfo.tlb_num_lines; line++) {
		WRCTL(CTL_PTEADDR, pteaddr_invalid(addr));

		for (way = 0; way < cpuinfo.tlb_num_ways; way++) {
			unsigned long tlbmisc;
			unsigned long pid;

			tlbmisc = TLBMISC_RD | (way << TLBMISC_WAY_SHIFT);
			WRCTL(CTL_TLBMISC, tlbmisc);
			tlbmisc = RDCTL(CTL_TLBMISC);
			pid = (tlbmisc >> TLBMISC_PID_SHIFT) & TLBMISC_PID_MASK;
			if (pid != mmu_pid)
				continue;

			tlbmisc = TLBMISC_WE | (way << TLBMISC_WAY_SHIFT) |
				  (pid << TLBMISC_PID_SHIFT);
			WRCTL(CTL_TLBMISC, tlbmisc);
			WRCTL(CTL_TLBACC, 0);
		}

		addr += PAGE_SIZE;
	}

	WRCTL(CTL_TLBMISC, org_misc);
}

/*
 * All entries common to a mm share an asid.  To effectively flush these
 * entries, we just bump the asid.
 */
void flush_tlb_mm(struct mm_struct *mm)
{
	if (current->mm == mm) {
		unsigned long mmu_pid = get_pid_from_context(&mm->context);
		flush_tlb_pid(mmu_pid);
	} else {
		memset(&mm->context, 0, sizeof(mm_context_t));
	}
}

void flush_tlb_all(void)
{
	unsigned long addr = 0;
	unsigned int line;
	unsigned int way;
	unsigned long org_misc, pid_misc;

	/* remember pid/way until we return */
	get_misc_and_pid(&org_misc, &pid_misc);

	/* Map each TLB entry to physcal address 0 with no-access and a
	   bad ptbase */
	for (line = 0; line < cpuinfo.tlb_num_lines; line++) {
		WRCTL(CTL_PTEADDR, pteaddr_invalid(addr));

Annotation

Implementation Notes