1*08dbd0f8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
25df87c15SRichard Kuo /*
35df87c15SRichard Kuo * Hexagon Virtual Machine TLB functions
45df87c15SRichard Kuo *
5e1858b2aSRichard Kuo * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
65df87c15SRichard Kuo */
75df87c15SRichard Kuo
85df87c15SRichard Kuo /*
95df87c15SRichard Kuo * The Hexagon Virtual Machine conceals the real workings of
105df87c15SRichard Kuo * the TLB, but there are one or two functions that need to
115df87c15SRichard Kuo * be instantiated for it, differently from a native build.
125df87c15SRichard Kuo */
135df87c15SRichard Kuo #include <linux/mm.h>
1400f3ca2cSJohannes Weiner #include <linux/sched.h>
155df87c15SRichard Kuo #include <asm/page.h>
165df87c15SRichard Kuo #include <asm/hexagon_vm.h>
175df87c15SRichard Kuo
185df87c15SRichard Kuo /*
195df87c15SRichard Kuo * Initial VM implementation has only one map active at a time, with
205df87c15SRichard Kuo * TLB purgings on changes. So either we're nuking the current map,
215df87c15SRichard Kuo * or it's a no-op. This operation is messy on true SMPs where other
225df87c15SRichard Kuo * processors must be induced to flush the copies in their local TLBs,
235df87c15SRichard Kuo * but Hexagon thread-based virtual processors share the same MMU.
245df87c15SRichard Kuo */
flush_tlb_range(struct vm_area_struct * vma,unsigned long start,unsigned long end)255df87c15SRichard Kuo void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
265df87c15SRichard Kuo unsigned long end)
275df87c15SRichard Kuo {
285df87c15SRichard Kuo struct mm_struct *mm = vma->vm_mm;
295df87c15SRichard Kuo
305df87c15SRichard Kuo if (mm->context.ptbase == current->active_mm->context.ptbase)
315df87c15SRichard Kuo __vmclrmap((void *)start, end - start);
325df87c15SRichard Kuo }
335df87c15SRichard Kuo
345df87c15SRichard Kuo /*
355df87c15SRichard Kuo * Flush a page from the kernel virtual map - used by highmem
365df87c15SRichard Kuo */
flush_tlb_one(unsigned long vaddr)375df87c15SRichard Kuo void flush_tlb_one(unsigned long vaddr)
385df87c15SRichard Kuo {
395df87c15SRichard Kuo __vmclrmap((void *)vaddr, PAGE_SIZE);
405df87c15SRichard Kuo }
415df87c15SRichard Kuo
425df87c15SRichard Kuo /*
435df87c15SRichard Kuo * Flush all TLBs across all CPUs, virtual or real.
445df87c15SRichard Kuo * A single Hexagon core has 6 thread contexts but
455df87c15SRichard Kuo * only one TLB.
465df87c15SRichard Kuo */
tlb_flush_all(void)475df87c15SRichard Kuo void tlb_flush_all(void)
485df87c15SRichard Kuo {
495df87c15SRichard Kuo /* should probably use that fixaddr end or whateve label */
505df87c15SRichard Kuo __vmclrmap(0, 0xffff0000);
515df87c15SRichard Kuo }
525df87c15SRichard Kuo
535df87c15SRichard Kuo /*
545df87c15SRichard Kuo * Flush TLB entries associated with a given mm_struct mapping.
555df87c15SRichard Kuo */
flush_tlb_mm(struct mm_struct * mm)565df87c15SRichard Kuo void flush_tlb_mm(struct mm_struct *mm)
575df87c15SRichard Kuo {
585df87c15SRichard Kuo /* Current Virtual Machine has only one map active at a time */
595df87c15SRichard Kuo if (current->active_mm->context.ptbase == mm->context.ptbase)
605df87c15SRichard Kuo tlb_flush_all();
615df87c15SRichard Kuo }
625df87c15SRichard Kuo
635df87c15SRichard Kuo /*
645df87c15SRichard Kuo * Flush TLB state associated with a page of a vma.
655df87c15SRichard Kuo */
flush_tlb_page(struct vm_area_struct * vma,unsigned long vaddr)665df87c15SRichard Kuo void flush_tlb_page(struct vm_area_struct *vma, unsigned long vaddr)
675df87c15SRichard Kuo {
685df87c15SRichard Kuo struct mm_struct *mm = vma->vm_mm;
695df87c15SRichard Kuo
705df87c15SRichard Kuo if (mm->context.ptbase == current->active_mm->context.ptbase)
715df87c15SRichard Kuo __vmclrmap((void *)vaddr, PAGE_SIZE);
725df87c15SRichard Kuo }
735df87c15SRichard Kuo
745df87c15SRichard Kuo /*
755df87c15SRichard Kuo * Flush TLB entries associated with a kernel address range.
765df87c15SRichard Kuo * Like flush range, but without the check on the vma->vm_mm.
775df87c15SRichard Kuo */
flush_tlb_kernel_range(unsigned long start,unsigned long end)785df87c15SRichard Kuo void flush_tlb_kernel_range(unsigned long start, unsigned long end)
795df87c15SRichard Kuo {
805df87c15SRichard Kuo __vmclrmap((void *)start, end - start);
815df87c15SRichard Kuo }
82