15f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen/*
25f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * AVR32 TLB operations
35f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen *
45f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * Copyright (C) 2004-2006 Atmel Corporation
55f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen *
65f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * This program is free software; you can redistribute it and/or modify
75f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * it under the terms of the GNU General Public License version 2 as
85f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen * published by the Free Software Foundation.
95f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen */
105f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <linux/mm.h>
115f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
125f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <asm/mmu_context.h>
135f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
14b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen/* TODO: Get the correct number from the CONFIG1 system register */
15b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen#define NR_TLB_ENTRIES 32
165f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
17b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoenstatic void show_dtlb_entry(unsigned int index)
185f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
19b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	u32 tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save;
20361f6ed1d00f666a1a7c33f3e9aaccb713f9b9e4Haavard Skinnemoen	unsigned long flags;
215f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
225f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	local_irq_save(flags);
235f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	mmucr_save = sysreg_read(MMUCR);
245f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	tlbehi_save = sysreg_read(TLBEHI);
25b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	mmucr = SYSREG_BFINS(DRP, index, mmucr_save);
265f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	sysreg_write(MMUCR, mmucr);
275f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
28b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	__builtin_tlbr();
295f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	cpu_sync_pipeline();
305f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
315f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	tlbehi = sysreg_read(TLBEHI);
325f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	tlbelo = sysreg_read(TLBELO);
335f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
345f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	printk("%2u: %c %c %02x   %05x %05x %o  %o  %c %c %c %c\n",
355f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	       index,
36b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	       SYSREG_BFEXT(TLBEHI_V, tlbehi) ? '1' : '0',
37b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	       SYSREG_BFEXT(G, tlbelo) ? '1' : '0',
38b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	       SYSREG_BFEXT(ASID, tlbehi),
39b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	       SYSREG_BFEXT(VPN, tlbehi) >> 2,
40b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	       SYSREG_BFEXT(PFN, tlbelo) >> 2,
41b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	       SYSREG_BFEXT(AP, tlbelo),
42b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	       SYSREG_BFEXT(SZ, tlbelo),
43b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	       SYSREG_BFEXT(TLBELO_C, tlbelo) ? 'C' : ' ',
44b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	       SYSREG_BFEXT(B, tlbelo) ? 'B' : ' ',
45b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	       SYSREG_BFEXT(W, tlbelo) ? 'W' : ' ',
46b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	       SYSREG_BFEXT(TLBELO_D, tlbelo) ? 'D' : ' ');
475f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
485f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	sysreg_write(MMUCR, mmucr_save);
495f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	sysreg_write(TLBEHI, tlbehi_save);
505f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	cpu_sync_pipeline();
515f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	local_irq_restore(flags);
525f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
535f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
545f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenvoid dump_dtlb(void)
555f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
565f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	unsigned int i;
575f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
585f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	printk("ID  V G ASID VPN   PFN   AP SZ C B W D\n");
59b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	for (i = 0; i < NR_TLB_ENTRIES; i++)
605f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		show_dtlb_entry(i);
615f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
625f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
63b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoenstatic void update_dtlb(unsigned long address, pte_t pte)
645f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
65b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	u32 tlbehi;
66b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	u32 mmucr;
675f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
68b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	/*
69b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	 * We're not changing the ASID here, so no need to flush the
70b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	 * pipeline.
71b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	 */
72b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	tlbehi = sysreg_read(TLBEHI);
73b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi));
74b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	tlbehi |= address & MMU_VPN_MASK;
75b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	tlbehi |= SYSREG_BIT(TLBEHI_V);
76b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	sysreg_write(TLBEHI, tlbehi);
775f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
785f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	/* Does this mapping already exist? */
79b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	__builtin_tlbs();
80b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	mmucr = sysreg_read(MMUCR);
815f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
825f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	if (mmucr & SYSREG_BIT(MMUCR_N)) {
835f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		/* Not found -- pick a not-recently-accessed entry */
84b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		unsigned int rp;
85b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		u32 tlbar = sysreg_read(TLBARLO);
865f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
875f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		rp = 32 - fls(tlbar);
885f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		if (rp == 32) {
895f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			rp = 0;
905f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			sysreg_write(TLBARLO, -1L);
915f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		}
925f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
93b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		mmucr = SYSREG_BFINS(DRP, rp, mmucr);
945f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		sysreg_write(MMUCR, mmucr);
955f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	}
965f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
975f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	sysreg_write(TLBELO, pte_val(pte) & _PAGE_FLAGS_HARDWARE_MASK);
985f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
995f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	/* Let's go */
100b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	__builtin_tlbw();
1015f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
1025f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1035f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenvoid update_mmu_cache(struct vm_area_struct *vma,
1044b3073e1c53a256275f1079c0fbfbe85883d9275Russell King		      unsigned long address, pte_t *ptep)
1055f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
1065f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	unsigned long flags;
1075f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1085f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	/* ptrace may call this routine */
1095f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	if (vma && current->active_mm != vma->vm_mm)
1105f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		return;
1115f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1125f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	local_irq_save(flags);
1134b3073e1c53a256275f1079c0fbfbe85883d9275Russell King	update_dtlb(address, *ptep);
1145f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	local_irq_restore(flags);
1155f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
1165f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
117b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoenstatic void __flush_tlb_page(unsigned long asid, unsigned long page)
1185f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
119b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	u32 mmucr, tlbehi;
1205f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
121b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	/*
122b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	 * Caller is responsible for masking out non-PFN bits in page
123b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	 * and changing the current ASID if necessary. This means that
124b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	 * we don't need to flush the pipeline after writing TLBEHI.
125b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	 */
126b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	tlbehi = page | asid;
127b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	sysreg_write(TLBEHI, tlbehi);
128b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen
129b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	__builtin_tlbs();
1305f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	mmucr = sysreg_read(MMUCR);
1315f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1325f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	if (!(mmucr & SYSREG_BIT(MMUCR_N))) {
133b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		unsigned int entry;
134b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		u32 tlbarlo;
1355f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1365f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		/* Clear the "valid" bit */
1375f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		sysreg_write(TLBEHI, tlbehi);
1385f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1395f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		/* mark the entry as "not accessed" */
140b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		entry = SYSREG_BFEXT(DRP, mmucr);
1415f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		tlbarlo = sysreg_read(TLBARLO);
142b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		tlbarlo |= (0x80000000UL >> entry);
1435f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		sysreg_write(TLBARLO, tlbarlo);
1445f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1455f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		/* update the entry with valid bit clear */
146b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		__builtin_tlbw();
1475f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	}
1485f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
1495f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1505f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenvoid flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
1515f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
1525f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	if (vma->vm_mm && vma->vm_mm->context != NO_CONTEXT) {
1535f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		unsigned long flags, asid;
1545f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		unsigned long saved_asid = MMU_NO_ASID;
1555f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1565f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		asid = vma->vm_mm->context & MMU_CONTEXT_ASID_MASK;
1575f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		page &= PAGE_MASK;
1585f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1595f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		local_irq_save(flags);
1605f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		if (vma->vm_mm != current->mm) {
1615f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			saved_asid = get_asid();
1625f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			set_asid(asid);
1635f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		}
1645f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1655f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		__flush_tlb_page(asid, page);
1665f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1675f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		if (saved_asid != MMU_NO_ASID)
1685f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			set_asid(saved_asid);
1695f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		local_irq_restore(flags);
1705f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	}
1715f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
1725f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1735f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenvoid flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
1745f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		     unsigned long end)
1755f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
1765f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	struct mm_struct *mm = vma->vm_mm;
1775f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1785f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	if (mm->context != NO_CONTEXT) {
1795f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		unsigned long flags;
1805f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		int size;
1815f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1825f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		local_irq_save(flags);
1835f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
184b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen
1855f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		if (size > (MMU_DTLB_ENTRIES / 4)) { /* Too many entries to flush */
1865f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			mm->context = NO_CONTEXT;
1875f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			if (mm == current->mm)
1885f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen				activate_context(mm);
1895f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		} else {
190b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen			unsigned long asid;
191b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen			unsigned long saved_asid;
192b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen
193b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen			asid = mm->context & MMU_CONTEXT_ASID_MASK;
194b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen			saved_asid = MMU_NO_ASID;
1955f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
1965f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			start &= PAGE_MASK;
1975f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			end += (PAGE_SIZE - 1);
1985f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			end &= PAGE_MASK;
199b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen
2005f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			if (mm != current->mm) {
2015f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen				saved_asid = get_asid();
2025f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen				set_asid(asid);
2035f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			}
2045f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
2055f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			while (start < end) {
2065f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen				__flush_tlb_page(asid, start);
2075f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen				start += PAGE_SIZE;
2085f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			}
2095f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			if (saved_asid != MMU_NO_ASID)
2105f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen				set_asid(saved_asid);
2115f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		}
2125f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		local_irq_restore(flags);
2135f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	}
2145f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
2155f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
2165f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen/*
217b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen * This function depends on the pages to be flushed having the G
218b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen * (global) bit set in their pte. This is true for all
219b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen * PAGE_KERNEL(_RO) pages.
2205f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen */
2215f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenvoid flush_tlb_kernel_range(unsigned long start, unsigned long end)
2225f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
2235f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	unsigned long flags;
2245f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	int size;
2255f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
2265f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
2275f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	if (size > (MMU_DTLB_ENTRIES / 4)) { /* Too many entries to flush */
2285f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		flush_tlb_all();
2295f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	} else {
230b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		unsigned long asid;
231b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen
232b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		local_irq_save(flags);
233b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		asid = get_asid();
2345f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
2355f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		start &= PAGE_MASK;
2365f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		end += (PAGE_SIZE - 1);
2375f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		end &= PAGE_MASK;
238b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen
2395f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		while (start < end) {
2405f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			__flush_tlb_page(asid, start);
2415f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			start += PAGE_SIZE;
2425f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		}
243b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		local_irq_restore(flags);
2445f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	}
2455f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
2465f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
2475f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenvoid flush_tlb_mm(struct mm_struct *mm)
2485f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
2495f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	/* Invalidate all TLB entries of this process by getting a new ASID */
2505f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	if (mm->context != NO_CONTEXT) {
2515f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		unsigned long flags;
2525f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
2535f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		local_irq_save(flags);
2545f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		mm->context = NO_CONTEXT;
2555f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		if (mm == current->mm)
2565f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen			activate_context(mm);
2575f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		local_irq_restore(flags);
2585f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	}
2595f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
2605f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
2615f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenvoid flush_tlb_all(void)
2625f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
2635f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	unsigned long flags;
2645f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
2655f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	local_irq_save(flags);
2665f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	sysreg_write(MMUCR, sysreg_read(MMUCR) | SYSREG_BIT(MMUCR_I));
2675f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	local_irq_restore(flags);
2685f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
2695f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
2705f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#ifdef CONFIG_PROC_FS
2715f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
2725f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <linux/seq_file.h>
2735f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <linux/proc_fs.h>
2745f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#include <linux/init.h>
2755f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
2765f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenstatic void *tlb_start(struct seq_file *tlb, loff_t *pos)
2775f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
2785f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	static unsigned long tlb_index;
2795f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
280b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	if (*pos >= NR_TLB_ENTRIES)
2815f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		return NULL;
2825f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
2835f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	tlb_index = 0;
2845f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	return &tlb_index;
2855f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
2865f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
2875f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenstatic void *tlb_next(struct seq_file *tlb, void *v, loff_t *pos)
2885f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
2895f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	unsigned long *index = v;
2905f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
291b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	if (*index >= NR_TLB_ENTRIES - 1)
2925f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		return NULL;
2935f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
2945f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	++*pos;
2955f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	++*index;
2965f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	return index;
2975f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
2985f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
2995f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenstatic void tlb_stop(struct seq_file *tlb, void *v)
3005f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
3015f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
3025f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
3035f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
3045f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenstatic int tlb_show(struct seq_file *tlb, void *v)
3055f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
306361f6ed1d00f666a1a7c33f3e9aaccb713f9b9e4Haavard Skinnemoen	unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save;
307361f6ed1d00f666a1a7c33f3e9aaccb713f9b9e4Haavard Skinnemoen	unsigned long flags;
3085f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	unsigned long *index = v;
3095f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
3105f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	if (*index == 0)
3115f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen		seq_puts(tlb, "ID  V G ASID VPN   PFN   AP SZ C B W D\n");
3125f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
313b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	BUG_ON(*index >= NR_TLB_ENTRIES);
3145f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
3155f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	local_irq_save(flags);
3165f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	mmucr_save = sysreg_read(MMUCR);
3175f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	tlbehi_save = sysreg_read(TLBEHI);
318b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	mmucr = SYSREG_BFINS(DRP, *index, mmucr_save);
3195f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	sysreg_write(MMUCR, mmucr);
3205f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
321b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	/* TLBR might change the ASID */
322b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen	__builtin_tlbr();
3235f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	cpu_sync_pipeline();
3245f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
3255f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	tlbehi = sysreg_read(TLBEHI);
3265f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	tlbelo = sysreg_read(TLBELO);
3275f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
3285f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	sysreg_write(MMUCR, mmucr_save);
3295f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	sysreg_write(TLBEHI, tlbehi_save);
3305f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	cpu_sync_pipeline();
3315f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	local_irq_restore(flags);
3325f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
3335f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	seq_printf(tlb, "%2lu: %c %c %02x   %05x %05x %o  %o  %c %c %c %c\n",
334b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		   *index,
335b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		   SYSREG_BFEXT(TLBEHI_V, tlbehi) ? '1' : '0',
336b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		   SYSREG_BFEXT(G, tlbelo) ? '1' : '0',
337b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		   SYSREG_BFEXT(ASID, tlbehi),
338b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		   SYSREG_BFEXT(VPN, tlbehi) >> 2,
339b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		   SYSREG_BFEXT(PFN, tlbelo) >> 2,
340b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		   SYSREG_BFEXT(AP, tlbelo),
341b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		   SYSREG_BFEXT(SZ, tlbelo),
342b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		   SYSREG_BFEXT(TLBELO_C, tlbelo) ? '1' : '0',
343b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		   SYSREG_BFEXT(B, tlbelo) ? '1' : '0',
344b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		   SYSREG_BFEXT(W, tlbelo) ? '1' : '0',
345b13d618b44fefea7529bd467e55423d353a599fcHaavard Skinnemoen		   SYSREG_BFEXT(TLBELO_D, tlbelo) ? '1' : '0');
3465f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
3475f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	return 0;
3485f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
3495f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
350f6135d12db4bed3b992052020f1c50d749cd8dc6Jan Engelhardtstatic const struct seq_operations tlb_ops = {
3515f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	.start		= tlb_start,
3525f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	.next		= tlb_next,
3535f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	.stop		= tlb_stop,
3545f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	.show		= tlb_show,
3555f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen};
3565f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
3575f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenstatic int tlb_open(struct inode *inode, struct file *file)
3585f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
3595f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	return seq_open(file, &tlb_ops);
3605f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
3615f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
3625dfe4c964a0dd7bb3a1d64a4166835a153146207Arjan van de Venstatic const struct file_operations proc_tlb_operations = {
3635f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	.open		= tlb_open,
3645f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	.read		= seq_read,
3655f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	.llseek		= seq_lseek,
3665f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	.release	= seq_release,
3675f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen};
3685f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen
3695f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenstatic int __init proctlb_init(void)
3705f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen{
3710d9f10f4eb65797cf2d238836f7439045a37722eDenis V. Lunev	proc_create("tlb", 0, NULL, &proc_tlb_operations);
3725f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen	return 0;
3735f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen}
3745f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoenlate_initcall(proctlb_init);
3755f97f7f9400de47ae837170bb274e90ad3934386Haavard Skinnemoen#endif /* CONFIG_PROC_FS */
376