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