1867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* 2867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Copyright 2010 Tilera Corporation. All Rights Reserved. 3867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * 4867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * This program is free software; you can redistribute it and/or 5867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * modify it under the terms of the GNU General Public License 6867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * as published by the Free Software Foundation, version 2. 7867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * 8867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * This program is distributed in the hope that it will be useful, but 9867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * WITHOUT ANY WARRANTY; without even the implied warranty of 10867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 11867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * NON INFRINGEMENT. See the GNU General Public License for 12867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * more details. 13867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 14867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 15867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#ifndef _ASM_TILE_TLBFLUSH_H 16867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#define _ASM_TILE_TLBFLUSH_H 17867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 18867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/mm.h> 19867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/sched.h> 20867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/smp.h> 21867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <asm/cacheflush.h> 22867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <asm/page.h> 23867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <hv/hypervisor.h> 24867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 25867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* 26867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Rather than associating each mm with its own ASID, we just use 27867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * ASIDs to allow us to lazily flush the TLB when we switch mms. 28867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * This way we only have to do an actual TLB flush on mm switch 29867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * every time we wrap ASIDs, not every single time we switch. 30867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * 31867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * FIXME: We might improve performance by keeping ASIDs around 32867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * properly, though since the hypervisor direct-maps VAs to TSB 33867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * entries, we're likely to have lost at least the executable page 34867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * mappings by the time we switch back to the original mm. 35867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 36867e359b97c970a60626d5d76bbe2a8fadbf38fbChris MetcalfDECLARE_PER_CPU(int, current_asid); 37867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 38867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* The hypervisor tells us what ASIDs are available to us. */ 39867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfextern int min_asid, max_asid; 40867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 41867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic inline unsigned long hv_page_size(const struct vm_area_struct *vma) 42867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 43867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf return (vma->vm_flags & VM_HUGETLB) ? HPAGE_SIZE : PAGE_SIZE; 44867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 45867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 46867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* Pass as vma pointer for non-executable mapping, if no vma available. */ 47867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#define FLUSH_NONEXEC ((const struct vm_area_struct *)-1UL) 48867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 49867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* Flush a single user page on this cpu. */ 50867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic inline void local_flush_tlb_page(const struct vm_area_struct *vma, 51867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf unsigned long addr, 52867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf unsigned long page_size) 53867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 54867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int rc = hv_flush_page(addr, page_size); 55867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (rc < 0) 56867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf panic("hv_flush_page(%#lx,%#lx) failed: %d", 57867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf addr, page_size, rc); 58867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (!vma || (vma != FLUSH_NONEXEC && (vma->vm_flags & VM_EXEC))) 59867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf __flush_icache(); 60867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 61867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 62867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* Flush range of user pages on this cpu. */ 63867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic inline void local_flush_tlb_pages(const struct vm_area_struct *vma, 64867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf unsigned long addr, 65867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf unsigned long page_size, 66867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf unsigned long len) 67867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 68867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int rc = hv_flush_pages(addr, page_size, len); 69867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (rc < 0) 70867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf panic("hv_flush_pages(%#lx,%#lx,%#lx) failed: %d", 71867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf addr, page_size, len, rc); 72867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (!vma || (vma != FLUSH_NONEXEC && (vma->vm_flags & VM_EXEC))) 73867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf __flush_icache(); 74867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 75867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 76867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* Flush all user pages on this cpu. */ 77867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic inline void local_flush_tlb(void) 78867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 79867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int rc = hv_flush_all(1); /* preserve global mappings */ 80867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (rc < 0) 81867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf panic("hv_flush_all(1) failed: %d", rc); 82867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf __flush_icache(); 83867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 84867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 85867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* 86867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Global pages have to be flushed a bit differently. Not a real 87867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * performance problem because this does not happen often. 88867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 89867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic inline void local_flush_tlb_all(void) 90867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{ 91867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf int i; 92867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf for (i = 0; ; ++i) { 93867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf HV_VirtAddrRange r = hv_inquire_virtual(i); 94867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf if (r.size == 0) 95867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf break; 96867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf local_flush_tlb_pages(NULL, r.start, PAGE_SIZE, r.size); 97867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf local_flush_tlb_pages(NULL, r.start, HPAGE_SIZE, r.size); 98867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf } 99867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf} 100867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 101867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* 102867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * TLB flushing: 103867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * 104867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * - flush_tlb() flushes the current mm struct TLBs 105867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * - flush_tlb_all() flushes all processes TLBs 106867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * - flush_tlb_mm(mm) flushes the specified mm context TLB's 107867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * - flush_tlb_page(vma, vmaddr) flushes one page 108867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * - flush_tlb_range(vma, start, end) flushes a range of pages 109867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages 110867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * - flush_tlb_others(cpumask, mm, va) flushes TLBs on other cpus 111867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * 112867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Here (as in vm_area_struct), "end" means the first byte after 113867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * our end address. 114867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */ 115867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 116867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfextern void flush_tlb_all(void); 117867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfextern void flush_tlb_kernel_range(unsigned long start, unsigned long end); 118867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfextern void flush_tlb_current_task(void); 119867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfextern void flush_tlb_mm(struct mm_struct *); 120867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfextern void flush_tlb_page(const struct vm_area_struct *, unsigned long); 121867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfextern void flush_tlb_page_mm(const struct vm_area_struct *, 122867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf struct mm_struct *, unsigned long); 123867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfextern void flush_tlb_range(const struct vm_area_struct *, 124867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf unsigned long start, unsigned long end); 125867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 126867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#define flush_tlb() flush_tlb_current_task() 127867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf 128867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#endif /* _ASM_TILE_TLBFLUSH_H */ 129