18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Hexagon Virtual Machine TLB functions 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci/* 98c2ecf20Sopenharmony_ci * The Hexagon Virtual Machine conceals the real workings of 108c2ecf20Sopenharmony_ci * the TLB, but there are one or two functions that need to 118c2ecf20Sopenharmony_ci * be instantiated for it, differently from a native build. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci#include <linux/mm.h> 148c2ecf20Sopenharmony_ci#include <linux/sched.h> 158c2ecf20Sopenharmony_ci#include <asm/page.h> 168c2ecf20Sopenharmony_ci#include <asm/hexagon_vm.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/* 198c2ecf20Sopenharmony_ci * Initial VM implementation has only one map active at a time, with 208c2ecf20Sopenharmony_ci * TLB purgings on changes. So either we're nuking the current map, 218c2ecf20Sopenharmony_ci * or it's a no-op. This operation is messy on true SMPs where other 228c2ecf20Sopenharmony_ci * processors must be induced to flush the copies in their local TLBs, 238c2ecf20Sopenharmony_ci * but Hexagon thread-based virtual processors share the same MMU. 248c2ecf20Sopenharmony_ci */ 258c2ecf20Sopenharmony_civoid flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 268c2ecf20Sopenharmony_ci unsigned long end) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci struct mm_struct *mm = vma->vm_mm; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci if (mm->context.ptbase == current->active_mm->context.ptbase) 318c2ecf20Sopenharmony_ci __vmclrmap((void *)start, end - start); 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* 358c2ecf20Sopenharmony_ci * Flush a page from the kernel virtual map - used by highmem 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_civoid flush_tlb_one(unsigned long vaddr) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci __vmclrmap((void *)vaddr, PAGE_SIZE); 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* 438c2ecf20Sopenharmony_ci * Flush all TLBs across all CPUs, virtual or real. 448c2ecf20Sopenharmony_ci * A single Hexagon core has 6 thread contexts but 458c2ecf20Sopenharmony_ci * only one TLB. 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_civoid tlb_flush_all(void) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci /* should probably use that fixaddr end or whateve label */ 508c2ecf20Sopenharmony_ci __vmclrmap(0, 0xffff0000); 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci/* 548c2ecf20Sopenharmony_ci * Flush TLB entries associated with a given mm_struct mapping. 558c2ecf20Sopenharmony_ci */ 568c2ecf20Sopenharmony_civoid flush_tlb_mm(struct mm_struct *mm) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci /* Current Virtual Machine has only one map active at a time */ 598c2ecf20Sopenharmony_ci if (current->active_mm->context.ptbase == mm->context.ptbase) 608c2ecf20Sopenharmony_ci tlb_flush_all(); 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* 648c2ecf20Sopenharmony_ci * Flush TLB state associated with a page of a vma. 658c2ecf20Sopenharmony_ci */ 668c2ecf20Sopenharmony_civoid flush_tlb_page(struct vm_area_struct *vma, unsigned long vaddr) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci struct mm_struct *mm = vma->vm_mm; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci if (mm->context.ptbase == current->active_mm->context.ptbase) 718c2ecf20Sopenharmony_ci __vmclrmap((void *)vaddr, PAGE_SIZE); 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/* 758c2ecf20Sopenharmony_ci * Flush TLB entries associated with a kernel address range. 768c2ecf20Sopenharmony_ci * Like flush range, but without the check on the vma->vm_mm. 778c2ecf20Sopenharmony_ci */ 788c2ecf20Sopenharmony_civoid flush_tlb_kernel_range(unsigned long start, unsigned long end) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci __vmclrmap((void *)start, end - start); 818c2ecf20Sopenharmony_ci} 82