18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef _ASM_X86_INVPCID 38c2ecf20Sopenharmony_ci#define _ASM_X86_INVPCID 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_cistatic inline void __invpcid(unsigned long pcid, unsigned long addr, 68c2ecf20Sopenharmony_ci unsigned long type) 78c2ecf20Sopenharmony_ci{ 88c2ecf20Sopenharmony_ci struct { u64 d[2]; } desc = { { pcid, addr } }; 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci /* 118c2ecf20Sopenharmony_ci * The memory clobber is because the whole point is to invalidate 128c2ecf20Sopenharmony_ci * stale TLB entries and, especially if we're flushing global 138c2ecf20Sopenharmony_ci * mappings, we don't want the compiler to reorder any subsequent 148c2ecf20Sopenharmony_ci * memory accesses before the TLB flush. 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci asm volatile("invpcid %[desc], %[type]" 178c2ecf20Sopenharmony_ci :: [desc] "m" (desc), [type] "r" (type) : "memory"); 188c2ecf20Sopenharmony_ci} 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define INVPCID_TYPE_INDIV_ADDR 0 218c2ecf20Sopenharmony_ci#define INVPCID_TYPE_SINGLE_CTXT 1 228c2ecf20Sopenharmony_ci#define INVPCID_TYPE_ALL_INCL_GLOBAL 2 238c2ecf20Sopenharmony_ci#define INVPCID_TYPE_ALL_NON_GLOBAL 3 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/* Flush all mappings for a given pcid and addr, not including globals. */ 268c2ecf20Sopenharmony_cistatic inline void invpcid_flush_one(unsigned long pcid, 278c2ecf20Sopenharmony_ci unsigned long addr) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci __invpcid(pcid, addr, INVPCID_TYPE_INDIV_ADDR); 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* Flush all mappings for a given PCID, not including globals. */ 338c2ecf20Sopenharmony_cistatic inline void invpcid_flush_single_context(unsigned long pcid) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci __invpcid(pcid, 0, INVPCID_TYPE_SINGLE_CTXT); 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* Flush all mappings, including globals, for all PCIDs. */ 398c2ecf20Sopenharmony_cistatic inline void invpcid_flush_all(void) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci __invpcid(0, 0, INVPCID_TYPE_ALL_INCL_GLOBAL); 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/* Flush all mappings for all PCIDs except globals. */ 458c2ecf20Sopenharmony_cistatic inline void invpcid_flush_all_nonglobals(void) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci __invpcid(0, 0, INVPCID_TYPE_ALL_NON_GLOBAL); 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#endif /* _ASM_X86_INVPCID */ 51