xref: /kernel/linux/linux-6.6/arch/hexagon/mm/vm_tlb.c (revision 62306a36)
162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Hexagon Virtual Machine TLB functions
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci/*
962306a36Sopenharmony_ci * The Hexagon Virtual Machine conceals the real workings of
1062306a36Sopenharmony_ci * the TLB, but there are one or two functions that need to
1162306a36Sopenharmony_ci * be instantiated for it, differently from a native build.
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci#include <linux/mm.h>
1462306a36Sopenharmony_ci#include <linux/sched.h>
1562306a36Sopenharmony_ci#include <asm/page.h>
1662306a36Sopenharmony_ci#include <asm/hexagon_vm.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/*
1962306a36Sopenharmony_ci * Initial VM implementation has only one map active at a time, with
2062306a36Sopenharmony_ci * TLB purgings on changes.  So either we're nuking the current map,
2162306a36Sopenharmony_ci * or it's a no-op.  This operation is messy on true SMPs where other
2262306a36Sopenharmony_ci * processors must be induced to flush the copies in their local TLBs,
2362306a36Sopenharmony_ci * but Hexagon thread-based virtual processors share the same MMU.
2462306a36Sopenharmony_ci */
2562306a36Sopenharmony_civoid flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
2662306a36Sopenharmony_ci			unsigned long end)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	struct mm_struct *mm = vma->vm_mm;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	if (mm->context.ptbase == current->active_mm->context.ptbase)
3162306a36Sopenharmony_ci		__vmclrmap((void *)start, end - start);
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/*
3562306a36Sopenharmony_ci * Flush a page from the kernel virtual map - used by highmem
3662306a36Sopenharmony_ci */
3762306a36Sopenharmony_civoid flush_tlb_one(unsigned long vaddr)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	__vmclrmap((void *)vaddr, PAGE_SIZE);
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/*
4362306a36Sopenharmony_ci * Flush all TLBs across all CPUs, virtual or real.
4462306a36Sopenharmony_ci * A single Hexagon core has 6 thread contexts but
4562306a36Sopenharmony_ci * only one TLB.
4662306a36Sopenharmony_ci */
4762306a36Sopenharmony_civoid tlb_flush_all(void)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	/*  should probably use that fixaddr end or whateve label  */
5062306a36Sopenharmony_ci	__vmclrmap(0, 0xffff0000);
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/*
5462306a36Sopenharmony_ci * Flush TLB entries associated with a given mm_struct mapping.
5562306a36Sopenharmony_ci */
5662306a36Sopenharmony_civoid flush_tlb_mm(struct mm_struct *mm)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	/* Current Virtual Machine has only one map active at a time */
5962306a36Sopenharmony_ci	if (current->active_mm->context.ptbase == mm->context.ptbase)
6062306a36Sopenharmony_ci		tlb_flush_all();
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci/*
6462306a36Sopenharmony_ci * Flush TLB state associated with a page of a vma.
6562306a36Sopenharmony_ci */
6662306a36Sopenharmony_civoid flush_tlb_page(struct vm_area_struct *vma, unsigned long vaddr)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	struct mm_struct *mm = vma->vm_mm;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	if (mm->context.ptbase  == current->active_mm->context.ptbase)
7162306a36Sopenharmony_ci		__vmclrmap((void *)vaddr, PAGE_SIZE);
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci/*
7562306a36Sopenharmony_ci * Flush TLB entries associated with a kernel address range.
7662306a36Sopenharmony_ci * Like flush range, but without the check on the vma->vm_mm.
7762306a36Sopenharmony_ci */
7862306a36Sopenharmony_civoid flush_tlb_kernel_range(unsigned long start, unsigned long end)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci		__vmclrmap((void *)start, end - start);
8162306a36Sopenharmony_ci}
82