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