xref: /openbmc/linux/arch/hexagon/mm/vm_tlb.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
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