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