| /* |
| * Hexagon Virtual Machine TLB functions |
| * |
| * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 and |
| * only version 2 as published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| * 02110-1301, USA. |
| */ |
| |
| /* |
| * The Hexagon Virtual Machine conceals the real workings of |
| * the TLB, but there are one or two functions that need to |
| * be instantiated for it, differently from a native build. |
| */ |
| #include <linux/mm.h> |
| #include <asm/page.h> |
| #include <asm/hexagon_vm.h> |
| |
| /* |
| * Initial VM implementation has only one map active at a time, with |
| * TLB purgings on changes. So either we're nuking the current map, |
| * or it's a no-op. This operation is messy on true SMPs where other |
| * processors must be induced to flush the copies in their local TLBs, |
| * but Hexagon thread-based virtual processors share the same MMU. |
| */ |
| void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, |
| unsigned long end) |
| { |
| struct mm_struct *mm = vma->vm_mm; |
| |
| if (mm->context.ptbase == current->active_mm->context.ptbase) |
| __vmclrmap((void *)start, end - start); |
| } |
| |
| /* |
| * Flush a page from the kernel virtual map - used by highmem |
| */ |
| void flush_tlb_one(unsigned long vaddr) |
| { |
| __vmclrmap((void *)vaddr, PAGE_SIZE); |
| } |
| |
| /* |
| * Flush all TLBs across all CPUs, virtual or real. |
| * A single Hexagon core has 6 thread contexts but |
| * only one TLB. |
| */ |
| void tlb_flush_all(void) |
| { |
| /* should probably use that fixaddr end or whateve label */ |
| __vmclrmap(0, 0xffff0000); |
| } |
| |
| /* |
| * Flush TLB entries associated with a given mm_struct mapping. |
| */ |
| void flush_tlb_mm(struct mm_struct *mm) |
| { |
| /* Current Virtual Machine has only one map active at a time */ |
| if (current->active_mm->context.ptbase == mm->context.ptbase) |
| tlb_flush_all(); |
| } |
| |
| /* |
| * Flush TLB state associated with a page of a vma. |
| */ |
| void flush_tlb_page(struct vm_area_struct *vma, unsigned long vaddr) |
| { |
| struct mm_struct *mm = vma->vm_mm; |
| |
| if (mm->context.ptbase == current->active_mm->context.ptbase) |
| __vmclrmap((void *)vaddr, PAGE_SIZE); |
| } |
| |
| /* |
| * Flush TLB entries associated with a kernel address range. |
| * Like flush range, but without the check on the vma->vm_mm. |
| */ |
| void flush_tlb_kernel_range(unsigned long start, unsigned long end) |
| { |
| __vmclrmap((void *)start, end - start); |
| } |