18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef _ASM_X86_TLBFLUSH_H 38c2ecf20Sopenharmony_ci#define _ASM_X86_TLBFLUSH_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <linux/mm.h> 68c2ecf20Sopenharmony_ci#include <linux/sched.h> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <asm/processor.h> 98c2ecf20Sopenharmony_ci#include <asm/cpufeature.h> 108c2ecf20Sopenharmony_ci#include <asm/special_insns.h> 118c2ecf20Sopenharmony_ci#include <asm/smp.h> 128c2ecf20Sopenharmony_ci#include <asm/invpcid.h> 138c2ecf20Sopenharmony_ci#include <asm/pti.h> 148c2ecf20Sopenharmony_ci#include <asm/processor-flags.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_civoid __flush_tlb_all(void); 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define TLB_FLUSH_ALL -1UL 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_civoid cr4_update_irqsoff(unsigned long set, unsigned long clear); 218c2ecf20Sopenharmony_ciunsigned long cr4_read_shadow(void); 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* Set in this cpu's CR4. */ 248c2ecf20Sopenharmony_cistatic inline void cr4_set_bits_irqsoff(unsigned long mask) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci cr4_update_irqsoff(mask, 0); 278c2ecf20Sopenharmony_ci} 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/* Clear in this cpu's CR4. */ 308c2ecf20Sopenharmony_cistatic inline void cr4_clear_bits_irqsoff(unsigned long mask) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci cr4_update_irqsoff(0, mask); 338c2ecf20Sopenharmony_ci} 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/* Set in this cpu's CR4. */ 368c2ecf20Sopenharmony_cistatic inline void cr4_set_bits(unsigned long mask) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci unsigned long flags; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci local_irq_save(flags); 418c2ecf20Sopenharmony_ci cr4_set_bits_irqsoff(mask); 428c2ecf20Sopenharmony_ci local_irq_restore(flags); 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* Clear in this cpu's CR4. */ 468c2ecf20Sopenharmony_cistatic inline void cr4_clear_bits(unsigned long mask) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci unsigned long flags; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci local_irq_save(flags); 518c2ecf20Sopenharmony_ci cr4_clear_bits_irqsoff(mask); 528c2ecf20Sopenharmony_ci local_irq_restore(flags); 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#ifndef MODULE 568c2ecf20Sopenharmony_ci/* 578c2ecf20Sopenharmony_ci * 6 because 6 should be plenty and struct tlb_state will fit in two cache 588c2ecf20Sopenharmony_ci * lines. 598c2ecf20Sopenharmony_ci */ 608c2ecf20Sopenharmony_ci#define TLB_NR_DYN_ASIDS 6 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistruct tlb_context { 638c2ecf20Sopenharmony_ci u64 ctx_id; 648c2ecf20Sopenharmony_ci u64 tlb_gen; 658c2ecf20Sopenharmony_ci}; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistruct tlb_state { 688c2ecf20Sopenharmony_ci /* 698c2ecf20Sopenharmony_ci * cpu_tlbstate.loaded_mm should match CR3 whenever interrupts 708c2ecf20Sopenharmony_ci * are on. This means that it may not match current->active_mm, 718c2ecf20Sopenharmony_ci * which will contain the previous user mm when we're in lazy TLB 728c2ecf20Sopenharmony_ci * mode even if we've already switched back to swapper_pg_dir. 738c2ecf20Sopenharmony_ci * 748c2ecf20Sopenharmony_ci * During switch_mm_irqs_off(), loaded_mm will be set to 758c2ecf20Sopenharmony_ci * LOADED_MM_SWITCHING during the brief interrupts-off window 768c2ecf20Sopenharmony_ci * when CR3 and loaded_mm would otherwise be inconsistent. This 778c2ecf20Sopenharmony_ci * is for nmi_uaccess_okay()'s benefit. 788c2ecf20Sopenharmony_ci */ 798c2ecf20Sopenharmony_ci struct mm_struct *loaded_mm; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci#define LOADED_MM_SWITCHING ((struct mm_struct *)1UL) 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci /* Last user mm for optimizing IBPB */ 848c2ecf20Sopenharmony_ci union { 858c2ecf20Sopenharmony_ci struct mm_struct *last_user_mm; 868c2ecf20Sopenharmony_ci unsigned long last_user_mm_ibpb; 878c2ecf20Sopenharmony_ci }; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci u16 loaded_mm_asid; 908c2ecf20Sopenharmony_ci u16 next_asid; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci /* 938c2ecf20Sopenharmony_ci * We can be in one of several states: 948c2ecf20Sopenharmony_ci * 958c2ecf20Sopenharmony_ci * - Actively using an mm. Our CPU's bit will be set in 968c2ecf20Sopenharmony_ci * mm_cpumask(loaded_mm) and is_lazy == false; 978c2ecf20Sopenharmony_ci * 988c2ecf20Sopenharmony_ci * - Not using a real mm. loaded_mm == &init_mm. Our CPU's bit 998c2ecf20Sopenharmony_ci * will not be set in mm_cpumask(&init_mm) and is_lazy == false. 1008c2ecf20Sopenharmony_ci * 1018c2ecf20Sopenharmony_ci * - Lazily using a real mm. loaded_mm != &init_mm, our bit 1028c2ecf20Sopenharmony_ci * is set in mm_cpumask(loaded_mm), but is_lazy == true. 1038c2ecf20Sopenharmony_ci * We're heuristically guessing that the CR3 load we 1048c2ecf20Sopenharmony_ci * skipped more than makes up for the overhead added by 1058c2ecf20Sopenharmony_ci * lazy mode. 1068c2ecf20Sopenharmony_ci */ 1078c2ecf20Sopenharmony_ci bool is_lazy; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci /* 1108c2ecf20Sopenharmony_ci * If set we changed the page tables in such a way that we 1118c2ecf20Sopenharmony_ci * needed an invalidation of all contexts (aka. PCIDs / ASIDs). 1128c2ecf20Sopenharmony_ci * This tells us to go invalidate all the non-loaded ctxs[] 1138c2ecf20Sopenharmony_ci * on the next context switch. 1148c2ecf20Sopenharmony_ci * 1158c2ecf20Sopenharmony_ci * The current ctx was kept up-to-date as it ran and does not 1168c2ecf20Sopenharmony_ci * need to be invalidated. 1178c2ecf20Sopenharmony_ci */ 1188c2ecf20Sopenharmony_ci bool invalidate_other; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci /* 1218c2ecf20Sopenharmony_ci * Mask that contains TLB_NR_DYN_ASIDS+1 bits to indicate 1228c2ecf20Sopenharmony_ci * the corresponding user PCID needs a flush next time we 1238c2ecf20Sopenharmony_ci * switch to it; see SWITCH_TO_USER_CR3. 1248c2ecf20Sopenharmony_ci */ 1258c2ecf20Sopenharmony_ci unsigned short user_pcid_flush_mask; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* 1288c2ecf20Sopenharmony_ci * Access to this CR4 shadow and to H/W CR4 is protected by 1298c2ecf20Sopenharmony_ci * disabling interrupts when modifying either one. 1308c2ecf20Sopenharmony_ci */ 1318c2ecf20Sopenharmony_ci unsigned long cr4; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci /* 1348c2ecf20Sopenharmony_ci * This is a list of all contexts that might exist in the TLB. 1358c2ecf20Sopenharmony_ci * There is one per ASID that we use, and the ASID (what the 1368c2ecf20Sopenharmony_ci * CPU calls PCID) is the index into ctxts. 1378c2ecf20Sopenharmony_ci * 1388c2ecf20Sopenharmony_ci * For each context, ctx_id indicates which mm the TLB's user 1398c2ecf20Sopenharmony_ci * entries came from. As an invariant, the TLB will never 1408c2ecf20Sopenharmony_ci * contain entries that are out-of-date as when that mm reached 1418c2ecf20Sopenharmony_ci * the tlb_gen in the list. 1428c2ecf20Sopenharmony_ci * 1438c2ecf20Sopenharmony_ci * To be clear, this means that it's legal for the TLB code to 1448c2ecf20Sopenharmony_ci * flush the TLB without updating tlb_gen. This can happen 1458c2ecf20Sopenharmony_ci * (for now, at least) due to paravirt remote flushes. 1468c2ecf20Sopenharmony_ci * 1478c2ecf20Sopenharmony_ci * NB: context 0 is a bit special, since it's also used by 1488c2ecf20Sopenharmony_ci * various bits of init code. This is fine -- code that 1498c2ecf20Sopenharmony_ci * isn't aware of PCID will end up harmlessly flushing 1508c2ecf20Sopenharmony_ci * context 0. 1518c2ecf20Sopenharmony_ci */ 1528c2ecf20Sopenharmony_ci struct tlb_context ctxs[TLB_NR_DYN_ASIDS]; 1538c2ecf20Sopenharmony_ci}; 1548c2ecf20Sopenharmony_ciDECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cibool nmi_uaccess_okay(void); 1578c2ecf20Sopenharmony_ci#define nmi_uaccess_okay nmi_uaccess_okay 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci/* Initialize cr4 shadow for this CPU. */ 1608c2ecf20Sopenharmony_cistatic inline void cr4_init_shadow(void) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci this_cpu_write(cpu_tlbstate.cr4, __read_cr4()); 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ciextern unsigned long mmu_cr4_features; 1668c2ecf20Sopenharmony_ciextern u32 *trampoline_cr4_features; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ciextern void initialize_tlbstate_and_flush(void); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci/* 1718c2ecf20Sopenharmony_ci * TLB flushing: 1728c2ecf20Sopenharmony_ci * 1738c2ecf20Sopenharmony_ci * - flush_tlb_all() flushes all processes TLBs 1748c2ecf20Sopenharmony_ci * - flush_tlb_mm(mm) flushes the specified mm context TLB's 1758c2ecf20Sopenharmony_ci * - flush_tlb_page(vma, vmaddr) flushes one page 1768c2ecf20Sopenharmony_ci * - flush_tlb_range(vma, start, end) flushes a range of pages 1778c2ecf20Sopenharmony_ci * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages 1788c2ecf20Sopenharmony_ci * - flush_tlb_others(cpumask, info) flushes TLBs on other cpus 1798c2ecf20Sopenharmony_ci * 1808c2ecf20Sopenharmony_ci * ..but the i386 has somewhat limited tlb flushing capabilities, 1818c2ecf20Sopenharmony_ci * and page-granular flushes are available only on i486 and up. 1828c2ecf20Sopenharmony_ci */ 1838c2ecf20Sopenharmony_cistruct flush_tlb_info { 1848c2ecf20Sopenharmony_ci /* 1858c2ecf20Sopenharmony_ci * We support several kinds of flushes. 1868c2ecf20Sopenharmony_ci * 1878c2ecf20Sopenharmony_ci * - Fully flush a single mm. .mm will be set, .end will be 1888c2ecf20Sopenharmony_ci * TLB_FLUSH_ALL, and .new_tlb_gen will be the tlb_gen to 1898c2ecf20Sopenharmony_ci * which the IPI sender is trying to catch us up. 1908c2ecf20Sopenharmony_ci * 1918c2ecf20Sopenharmony_ci * - Partially flush a single mm. .mm will be set, .start and 1928c2ecf20Sopenharmony_ci * .end will indicate the range, and .new_tlb_gen will be set 1938c2ecf20Sopenharmony_ci * such that the changes between generation .new_tlb_gen-1 and 1948c2ecf20Sopenharmony_ci * .new_tlb_gen are entirely contained in the indicated range. 1958c2ecf20Sopenharmony_ci * 1968c2ecf20Sopenharmony_ci * - Fully flush all mms whose tlb_gens have been updated. .mm 1978c2ecf20Sopenharmony_ci * will be NULL, .end will be TLB_FLUSH_ALL, and .new_tlb_gen 1988c2ecf20Sopenharmony_ci * will be zero. 1998c2ecf20Sopenharmony_ci */ 2008c2ecf20Sopenharmony_ci struct mm_struct *mm; 2018c2ecf20Sopenharmony_ci unsigned long start; 2028c2ecf20Sopenharmony_ci unsigned long end; 2038c2ecf20Sopenharmony_ci u64 new_tlb_gen; 2048c2ecf20Sopenharmony_ci unsigned int stride_shift; 2058c2ecf20Sopenharmony_ci bool freed_tables; 2068c2ecf20Sopenharmony_ci}; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_civoid flush_tlb_local(void); 2098c2ecf20Sopenharmony_civoid flush_tlb_one_user(unsigned long addr); 2108c2ecf20Sopenharmony_civoid flush_tlb_one_kernel(unsigned long addr); 2118c2ecf20Sopenharmony_civoid flush_tlb_others(const struct cpumask *cpumask, 2128c2ecf20Sopenharmony_ci const struct flush_tlb_info *info); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci#ifdef CONFIG_PARAVIRT 2158c2ecf20Sopenharmony_ci#include <asm/paravirt.h> 2168c2ecf20Sopenharmony_ci#endif 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci#define flush_tlb_mm(mm) \ 2198c2ecf20Sopenharmony_ci flush_tlb_mm_range(mm, 0UL, TLB_FLUSH_ALL, 0UL, true) 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci#define flush_tlb_range(vma, start, end) \ 2228c2ecf20Sopenharmony_ci flush_tlb_mm_range((vma)->vm_mm, start, end, \ 2238c2ecf20Sopenharmony_ci ((vma)->vm_flags & VM_HUGETLB) \ 2248c2ecf20Sopenharmony_ci ? huge_page_shift(hstate_vma(vma)) \ 2258c2ecf20Sopenharmony_ci : PAGE_SHIFT, false) 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ciextern void flush_tlb_all(void); 2288c2ecf20Sopenharmony_ciextern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, 2298c2ecf20Sopenharmony_ci unsigned long end, unsigned int stride_shift, 2308c2ecf20Sopenharmony_ci bool freed_tables); 2318c2ecf20Sopenharmony_ciextern void flush_tlb_kernel_range(unsigned long start, unsigned long end); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_cistatic inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long a) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci flush_tlb_mm_range(vma->vm_mm, a, a + PAGE_SIZE, PAGE_SHIFT, false); 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic inline u64 inc_mm_tlb_gen(struct mm_struct *mm) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci /* 2418c2ecf20Sopenharmony_ci * Bump the generation count. This also serves as a full barrier 2428c2ecf20Sopenharmony_ci * that synchronizes with switch_mm(): callers are required to order 2438c2ecf20Sopenharmony_ci * their read of mm_cpumask after their writes to the paging 2448c2ecf20Sopenharmony_ci * structures. 2458c2ecf20Sopenharmony_ci */ 2468c2ecf20Sopenharmony_ci return atomic64_inc_return(&mm->context.tlb_gen); 2478c2ecf20Sopenharmony_ci} 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic inline void arch_tlbbatch_add_mm(struct arch_tlbflush_unmap_batch *batch, 2508c2ecf20Sopenharmony_ci struct mm_struct *mm) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci inc_mm_tlb_gen(mm); 2538c2ecf20Sopenharmony_ci cpumask_or(&batch->cpumask, &batch->cpumask, mm_cpumask(mm)); 2548c2ecf20Sopenharmony_ci} 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ciextern void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci#endif /* !MODULE */ 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci#endif /* _ASM_X86_TLBFLUSH_H */ 261