arch/xtensa/mm/tlb.c

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

File Facts

System
Linux kernel
Corpus path
arch/xtensa/mm/tlb.c
Extension
.c
Size
7178 bytes
Lines
296
Domain
Architecture Layer
Bucket
arch/xtensa
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

while(start < end) {
				invalidate_itlb_mapping(start);
				invalidate_dtlb_mapping(start);
				start += PAGE_SIZE;
			}
		else
			while(start < end) {
				invalidate_dtlb_mapping(start);
				start += PAGE_SIZE;
			}

		set_rasid_register(oldpid);
	} else {
		local_flush_tlb_mm(mm);
	}
	local_irq_restore(flags);
}

void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
{
	int cpu = smp_processor_id();
	struct mm_struct* mm = vma->vm_mm;
	unsigned long flags;
	int oldpid;

	if (mm->context.asid[cpu] == NO_CONTEXT)
		return;

	local_irq_save(flags);

	oldpid = get_rasid_register();
	set_rasid_register(ASID_INSERT(mm->context.asid[cpu]));

	if (vma->vm_flags & VM_EXEC)
		invalidate_itlb_mapping(page);
	invalidate_dtlb_mapping(page);

	set_rasid_register(oldpid);

	local_irq_restore(flags);
}

void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
	if (end > start && start >= TASK_SIZE && end <= PAGE_OFFSET &&
	    end - start < _TLB_ENTRIES << PAGE_SHIFT) {
		start &= PAGE_MASK;
		while (start < end) {
			invalidate_itlb_mapping(start);
			invalidate_dtlb_mapping(start);
			start += PAGE_SIZE;
		}
	} else {
		local_flush_tlb_all();
	}
}

void update_mmu_tlb_range(struct vm_area_struct *vma,
			unsigned long address, pte_t *ptep, unsigned int nr)
{
	local_flush_tlb_range(vma, address, address + PAGE_SIZE * nr);
}

#ifdef CONFIG_DEBUG_TLB_SANITY

static unsigned get_pte_for_vaddr(unsigned vaddr)
{
	struct task_struct *task = get_current();
	struct mm_struct *mm = task->mm;
	pgd_t *pgd;
	p4d_t *p4d;
	pud_t *pud;
	pmd_t *pmd;
	pte_t *pte;
	unsigned int pteval;

	if (!mm)
		mm = task->active_mm;
	pgd = pgd_offset(mm, vaddr);
	if (pgd_none_or_clear_bad(pgd))
		return 0;
	p4d = p4d_offset(pgd, vaddr);
	if (p4d_none_or_clear_bad(p4d))
		return 0;
	pud = pud_offset(p4d, vaddr);
	if (pud_none_or_clear_bad(pud))
		return 0;
	pmd = pmd_offset(pud, vaddr);
	if (pmd_none_or_clear_bad(pmd))
		return 0;

Annotation

Implementation Notes