162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _ASM_X86_INVPCID 362306a36Sopenharmony_ci#define _ASM_X86_INVPCID 462306a36Sopenharmony_ci 562306a36Sopenharmony_cistatic inline void __invpcid(unsigned long pcid, unsigned long addr, 662306a36Sopenharmony_ci unsigned long type) 762306a36Sopenharmony_ci{ 862306a36Sopenharmony_ci struct { u64 d[2]; } desc = { { pcid, addr } }; 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci /* 1162306a36Sopenharmony_ci * The memory clobber is because the whole point is to invalidate 1262306a36Sopenharmony_ci * stale TLB entries and, especially if we're flushing global 1362306a36Sopenharmony_ci * mappings, we don't want the compiler to reorder any subsequent 1462306a36Sopenharmony_ci * memory accesses before the TLB flush. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci asm volatile("invpcid %[desc], %[type]" 1762306a36Sopenharmony_ci :: [desc] "m" (desc), [type] "r" (type) : "memory"); 1862306a36Sopenharmony_ci} 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define INVPCID_TYPE_INDIV_ADDR 0 2162306a36Sopenharmony_ci#define INVPCID_TYPE_SINGLE_CTXT 1 2262306a36Sopenharmony_ci#define INVPCID_TYPE_ALL_INCL_GLOBAL 2 2362306a36Sopenharmony_ci#define INVPCID_TYPE_ALL_NON_GLOBAL 3 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* Flush all mappings for a given pcid and addr, not including globals. */ 2662306a36Sopenharmony_cistatic inline void invpcid_flush_one(unsigned long pcid, 2762306a36Sopenharmony_ci unsigned long addr) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci __invpcid(pcid, addr, INVPCID_TYPE_INDIV_ADDR); 3062306a36Sopenharmony_ci} 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* Flush all mappings for a given PCID, not including globals. */ 3362306a36Sopenharmony_cistatic inline void invpcid_flush_single_context(unsigned long pcid) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci __invpcid(pcid, 0, INVPCID_TYPE_SINGLE_CTXT); 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/* Flush all mappings, including globals, for all PCIDs. */ 3962306a36Sopenharmony_cistatic inline void invpcid_flush_all(void) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci __invpcid(0, 0, INVPCID_TYPE_ALL_INCL_GLOBAL); 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/* Flush all mappings for all PCIDs except globals. */ 4562306a36Sopenharmony_cistatic inline void invpcid_flush_all_nonglobals(void) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci __invpcid(0, 0, INVPCID_TYPE_ALL_NON_GLOBAL); 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#endif /* _ASM_X86_INVPCID */ 51