xref: /linux/drivers/iommu/generic_pt/pt_defs.h (revision ce5cfb0fa20dc6454da039612e34325b7b4a8243)
17c5b184dSJason Gunthorpe /* SPDX-License-Identifier: GPL-2.0-only */
27c5b184dSJason Gunthorpe /*
37c5b184dSJason Gunthorpe  * Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES
47c5b184dSJason Gunthorpe  *
57c5b184dSJason Gunthorpe  * This header is included before the format. It contains definitions
67c5b184dSJason Gunthorpe  * that are required to compile the format. The header order is:
77c5b184dSJason Gunthorpe  *  pt_defs.h
87c5b184dSJason Gunthorpe  *  fmt_XX.h
97c5b184dSJason Gunthorpe  *  pt_common.h
107c5b184dSJason Gunthorpe  */
117c5b184dSJason Gunthorpe #ifndef __GENERIC_PT_DEFS_H
127c5b184dSJason Gunthorpe #define __GENERIC_PT_DEFS_H
137c5b184dSJason Gunthorpe 
147c5b184dSJason Gunthorpe #include <linux/generic_pt/common.h>
157c5b184dSJason Gunthorpe 
167c5b184dSJason Gunthorpe #include <linux/types.h>
177c5b184dSJason Gunthorpe #include <linux/atomic.h>
187c5b184dSJason Gunthorpe #include <linux/bits.h>
197c5b184dSJason Gunthorpe #include <linux/limits.h>
207c5b184dSJason Gunthorpe #include <linux/bug.h>
217c5b184dSJason Gunthorpe #include <linux/kconfig.h>
227c5b184dSJason Gunthorpe #include "pt_log2.h"
237c5b184dSJason Gunthorpe 
247c5b184dSJason Gunthorpe /* Header self-compile default defines */
257c5b184dSJason Gunthorpe #ifndef pt_write_attrs
267c5b184dSJason Gunthorpe typedef u64 pt_vaddr_t;
277c5b184dSJason Gunthorpe typedef u64 pt_oaddr_t;
287c5b184dSJason Gunthorpe #endif
297c5b184dSJason Gunthorpe 
307c5b184dSJason Gunthorpe struct pt_table_p;
317c5b184dSJason Gunthorpe 
327c5b184dSJason Gunthorpe enum {
337c5b184dSJason Gunthorpe 	PT_VADDR_MAX = sizeof(pt_vaddr_t) == 8 ? U64_MAX : U32_MAX,
347c5b184dSJason Gunthorpe 	PT_VADDR_MAX_LG2 = sizeof(pt_vaddr_t) == 8 ? 64 : 32,
357c5b184dSJason Gunthorpe 	PT_OADDR_MAX = sizeof(pt_oaddr_t) == 8 ? U64_MAX : U32_MAX,
367c5b184dSJason Gunthorpe 	PT_OADDR_MAX_LG2 = sizeof(pt_oaddr_t) == 8 ? 64 : 32,
377c5b184dSJason Gunthorpe };
387c5b184dSJason Gunthorpe 
397c5b184dSJason Gunthorpe /*
407c5b184dSJason Gunthorpe  * The format instantiation can have features wired off or on to optimize the
417c5b184dSJason Gunthorpe  * code gen. Supported features are just a reflection of what the current set of
427c5b184dSJason Gunthorpe  * kernel users want to use.
437c5b184dSJason Gunthorpe  */
447c5b184dSJason Gunthorpe #ifndef PT_SUPPORTED_FEATURES
457c5b184dSJason Gunthorpe #define PT_SUPPORTED_FEATURES 0
467c5b184dSJason Gunthorpe #endif
477c5b184dSJason Gunthorpe 
487c5b184dSJason Gunthorpe /*
497c5b184dSJason Gunthorpe  * When in debug mode we compile all formats with all features. This allows the
507c5b184dSJason Gunthorpe  * kunit to test the full matrix. SIGN_EXTEND can't co-exist with DYNAMIC_TOP or
51*aefd967dSJason Gunthorpe  * FULL_VA. DMA_INCOHERENT requires a SW bit that not all formats have
527c5b184dSJason Gunthorpe  */
537c5b184dSJason Gunthorpe #if IS_ENABLED(CONFIG_DEBUG_GENERIC_PT)
547c5b184dSJason Gunthorpe enum {
557c5b184dSJason Gunthorpe 	PT_ORIG_SUPPORTED_FEATURES = PT_SUPPORTED_FEATURES,
567c5b184dSJason Gunthorpe 	PT_DEBUG_SUPPORTED_FEATURES =
577c5b184dSJason Gunthorpe 		UINT_MAX &
58*aefd967dSJason Gunthorpe 		~((PT_ORIG_SUPPORTED_FEATURES & BIT(PT_FEAT_DMA_INCOHERENT) ?
59*aefd967dSJason Gunthorpe 			   0 :
60*aefd967dSJason Gunthorpe 			   BIT(PT_FEAT_DMA_INCOHERENT))) &
617c5b184dSJason Gunthorpe 		~((PT_ORIG_SUPPORTED_FEATURES & BIT(PT_FEAT_SIGN_EXTEND)) ?
627c5b184dSJason Gunthorpe 			  BIT(PT_FEAT_DYNAMIC_TOP) | BIT(PT_FEAT_FULL_VA) :
637c5b184dSJason Gunthorpe 			  BIT(PT_FEAT_SIGN_EXTEND)),
647c5b184dSJason Gunthorpe };
657c5b184dSJason Gunthorpe #undef PT_SUPPORTED_FEATURES
667c5b184dSJason Gunthorpe #define PT_SUPPORTED_FEATURES PT_DEBUG_SUPPORTED_FEATURES
677c5b184dSJason Gunthorpe #endif
687c5b184dSJason Gunthorpe 
697c5b184dSJason Gunthorpe #ifndef PT_FORCE_ENABLED_FEATURES
707c5b184dSJason Gunthorpe #define PT_FORCE_ENABLED_FEATURES 0
717c5b184dSJason Gunthorpe #endif
727c5b184dSJason Gunthorpe 
737c5b184dSJason Gunthorpe /**
747c5b184dSJason Gunthorpe  * DOC: Generic Page Table Language
757c5b184dSJason Gunthorpe  *
767c5b184dSJason Gunthorpe  * Language used in Generic Page Table
777c5b184dSJason Gunthorpe  *  VA
787c5b184dSJason Gunthorpe  *     The input address to the page table, often the virtual address.
797c5b184dSJason Gunthorpe  *  OA
807c5b184dSJason Gunthorpe  *     The output address from the page table, often the physical address.
817c5b184dSJason Gunthorpe  *  leaf
827c5b184dSJason Gunthorpe  *     An entry that results in an output address.
837c5b184dSJason Gunthorpe  *  start/end
847c5b184dSJason Gunthorpe  *     An half-open range, e.g. [0,0) refers to no VA.
857c5b184dSJason Gunthorpe  *  start/last
867c5b184dSJason Gunthorpe  *     An inclusive closed range, e.g. [0,0] refers to the VA 0
877c5b184dSJason Gunthorpe  *  common
887c5b184dSJason Gunthorpe  *     The generic page table container struct pt_common
897c5b184dSJason Gunthorpe  *  level
907c5b184dSJason Gunthorpe  *     Level 0 is always a table of only leaves with no futher table pointers.
917c5b184dSJason Gunthorpe  *     Increasing levels increase the size of the table items. The least
927c5b184dSJason Gunthorpe  *     significant VA bits used to index page tables are used to index the Level
937c5b184dSJason Gunthorpe  *     0 table. The various labels for table levels used by HW descriptions are
947c5b184dSJason Gunthorpe  *     not used.
957c5b184dSJason Gunthorpe  *  top_level
967c5b184dSJason Gunthorpe  *     The inclusive highest level of the table. A two-level table
977c5b184dSJason Gunthorpe  *     has a top level of 1.
987c5b184dSJason Gunthorpe  *  table
997c5b184dSJason Gunthorpe  *     A linear array of translation items for that level.
1007c5b184dSJason Gunthorpe  *  index
1017c5b184dSJason Gunthorpe  *     The position in a table of an element: item = table[index]
1027c5b184dSJason Gunthorpe  *  item
1037c5b184dSJason Gunthorpe  *     A single index in a table
1047c5b184dSJason Gunthorpe  *  entry
1057c5b184dSJason Gunthorpe  *     A single logical element in a table. If contiguous pages are not
1067c5b184dSJason Gunthorpe  *     supported then item and entry are the same thing, otherwise entry refers
1077c5b184dSJason Gunthorpe  *     to all the items that comprise a single contiguous translation.
1087c5b184dSJason Gunthorpe  *  item/entry_size
1097c5b184dSJason Gunthorpe  *     The number of bytes of VA the table index translates for.
1107c5b184dSJason Gunthorpe  *     If the item is a table entry then the next table covers
1117c5b184dSJason Gunthorpe  *     this size. If the entry translates to an output address then the
1127c5b184dSJason Gunthorpe  *     full OA is: OA | (VA % entry_size)
1137c5b184dSJason Gunthorpe  *  contig_count
1147c5b184dSJason Gunthorpe  *     The number of consecutive items fused into a single entry.
1157c5b184dSJason Gunthorpe  *     item_size * contig_count is the size of that entry's translation.
1167c5b184dSJason Gunthorpe  *  lg2
1177c5b184dSJason Gunthorpe  *     Indicates the value is encoded as log2, i.e. 1<<x is the actual value.
1187c5b184dSJason Gunthorpe  *     Normally the compiler is fine to optimize divide and mod with log2 values
1197c5b184dSJason Gunthorpe  *     automatically when inlining, however if the values are not constant
1207c5b184dSJason Gunthorpe  *     expressions it can't. So we do it by hand; we want to avoid 64-bit
1217c5b184dSJason Gunthorpe  *     divmod.
1227c5b184dSJason Gunthorpe  */
1237c5b184dSJason Gunthorpe 
1247c5b184dSJason Gunthorpe /* Returned by pt_load_entry() and for_each_pt_level_entry() */
1257c5b184dSJason Gunthorpe enum pt_entry_type {
1267c5b184dSJason Gunthorpe 	PT_ENTRY_EMPTY,
1277c5b184dSJason Gunthorpe 	/* Entry is valid and points to a lower table level */
1287c5b184dSJason Gunthorpe 	PT_ENTRY_TABLE,
1297c5b184dSJason Gunthorpe 	/* Entry is valid and returns an output address */
1307c5b184dSJason Gunthorpe 	PT_ENTRY_OA,
1317c5b184dSJason Gunthorpe };
1327c5b184dSJason Gunthorpe 
1337c5b184dSJason Gunthorpe struct pt_range {
1347c5b184dSJason Gunthorpe 	struct pt_common *common;
1357c5b184dSJason Gunthorpe 	struct pt_table_p *top_table;
1367c5b184dSJason Gunthorpe 	pt_vaddr_t va;
1377c5b184dSJason Gunthorpe 	pt_vaddr_t last_va;
1387c5b184dSJason Gunthorpe 	u8 top_level;
1397c5b184dSJason Gunthorpe 	u8 max_vasz_lg2;
1407c5b184dSJason Gunthorpe };
1417c5b184dSJason Gunthorpe 
1427c5b184dSJason Gunthorpe /*
1437c5b184dSJason Gunthorpe  * Similar to xa_state, this records information about an in-progress parse at a
1447c5b184dSJason Gunthorpe  * single level.
1457c5b184dSJason Gunthorpe  */
1467c5b184dSJason Gunthorpe struct pt_state {
1477c5b184dSJason Gunthorpe 	struct pt_range *range;
1487c5b184dSJason Gunthorpe 	struct pt_table_p *table;
1497c5b184dSJason Gunthorpe 	struct pt_table_p *table_lower;
1507c5b184dSJason Gunthorpe 	u64 entry;
1517c5b184dSJason Gunthorpe 	enum pt_entry_type type;
1527c5b184dSJason Gunthorpe 	unsigned short index;
1537c5b184dSJason Gunthorpe 	unsigned short end_index;
1547c5b184dSJason Gunthorpe 	u8 level;
1557c5b184dSJason Gunthorpe };
1567c5b184dSJason Gunthorpe 
1577c5b184dSJason Gunthorpe #define pt_cur_table(pts, type) ((type *)((pts)->table))
1587c5b184dSJason Gunthorpe 
1597c5b184dSJason Gunthorpe /*
1607c5b184dSJason Gunthorpe  * Try to install a new table pointer. The locking methodology requires this to
1617c5b184dSJason Gunthorpe  * be atomic (multiple threads can race to install a pointer). The losing
1627c5b184dSJason Gunthorpe  * threads will fail the atomic and return false. They should free any memory
1637c5b184dSJason Gunthorpe  * and reparse the table level again.
1647c5b184dSJason Gunthorpe  */
1657c5b184dSJason Gunthorpe #if !IS_ENABLED(CONFIG_GENERIC_ATOMIC64)
pt_table_install64(struct pt_state * pts,u64 table_entry)1667c5b184dSJason Gunthorpe static inline bool pt_table_install64(struct pt_state *pts, u64 table_entry)
1677c5b184dSJason Gunthorpe {
1687c5b184dSJason Gunthorpe 	u64 *entryp = pt_cur_table(pts, u64) + pts->index;
1697c5b184dSJason Gunthorpe 	u64 old_entry = pts->entry;
1707c5b184dSJason Gunthorpe 	bool ret;
1717c5b184dSJason Gunthorpe 
1727c5b184dSJason Gunthorpe 	/*
1737c5b184dSJason Gunthorpe 	 * Ensure the zero'd table content itself is visible before its PTE can
1747c5b184dSJason Gunthorpe 	 * be. release is a NOP on !SMP, but the HW is still doing an acquire.
1757c5b184dSJason Gunthorpe 	 */
1767c5b184dSJason Gunthorpe 	if (!IS_ENABLED(CONFIG_SMP))
1777c5b184dSJason Gunthorpe 		dma_wmb();
1787c5b184dSJason Gunthorpe 	ret = try_cmpxchg64_release(entryp, &old_entry, table_entry);
1797c5b184dSJason Gunthorpe 	if (ret)
1807c5b184dSJason Gunthorpe 		pts->entry = table_entry;
1817c5b184dSJason Gunthorpe 	return ret;
1827c5b184dSJason Gunthorpe }
1837c5b184dSJason Gunthorpe #endif
1847c5b184dSJason Gunthorpe 
pt_table_install32(struct pt_state * pts,u32 table_entry)1857c5b184dSJason Gunthorpe static inline bool pt_table_install32(struct pt_state *pts, u32 table_entry)
1867c5b184dSJason Gunthorpe {
1877c5b184dSJason Gunthorpe 	u32 *entryp = pt_cur_table(pts, u32) + pts->index;
1887c5b184dSJason Gunthorpe 	u32 old_entry = pts->entry;
1897c5b184dSJason Gunthorpe 	bool ret;
1907c5b184dSJason Gunthorpe 
1917c5b184dSJason Gunthorpe 	/*
1927c5b184dSJason Gunthorpe 	 * Ensure the zero'd table content itself is visible before its PTE can
1937c5b184dSJason Gunthorpe 	 * be. release is a NOP on !SMP, but the HW is still doing an acquire.
1947c5b184dSJason Gunthorpe 	 */
1957c5b184dSJason Gunthorpe 	if (!IS_ENABLED(CONFIG_SMP))
1967c5b184dSJason Gunthorpe 		dma_wmb();
1977c5b184dSJason Gunthorpe 	ret = try_cmpxchg_release(entryp, &old_entry, table_entry);
1987c5b184dSJason Gunthorpe 	if (ret)
1997c5b184dSJason Gunthorpe 		pts->entry = table_entry;
2007c5b184dSJason Gunthorpe 	return ret;
2017c5b184dSJason Gunthorpe }
2027c5b184dSJason Gunthorpe 
2037c5b184dSJason Gunthorpe #define PT_SUPPORTED_FEATURE(feature_nr) (PT_SUPPORTED_FEATURES & BIT(feature_nr))
2047c5b184dSJason Gunthorpe 
pt_feature(const struct pt_common * common,unsigned int feature_nr)2057c5b184dSJason Gunthorpe static inline bool pt_feature(const struct pt_common *common,
2067c5b184dSJason Gunthorpe 			      unsigned int feature_nr)
2077c5b184dSJason Gunthorpe {
2087c5b184dSJason Gunthorpe 	if (PT_FORCE_ENABLED_FEATURES & BIT(feature_nr))
2097c5b184dSJason Gunthorpe 		return true;
2107c5b184dSJason Gunthorpe 	if (!PT_SUPPORTED_FEATURE(feature_nr))
2117c5b184dSJason Gunthorpe 		return false;
2127c5b184dSJason Gunthorpe 	return common->features & BIT(feature_nr);
2137c5b184dSJason Gunthorpe }
2147c5b184dSJason Gunthorpe 
pts_feature(const struct pt_state * pts,unsigned int feature_nr)2157c5b184dSJason Gunthorpe static inline bool pts_feature(const struct pt_state *pts,
2167c5b184dSJason Gunthorpe 			       unsigned int feature_nr)
2177c5b184dSJason Gunthorpe {
2187c5b184dSJason Gunthorpe 	return pt_feature(pts->range->common, feature_nr);
2197c5b184dSJason Gunthorpe }
2207c5b184dSJason Gunthorpe 
2217c5b184dSJason Gunthorpe /*
2227c5b184dSJason Gunthorpe  * PT_WARN_ON is used for invariants that the kunit should be checking can't
2237c5b184dSJason Gunthorpe  * happen.
2247c5b184dSJason Gunthorpe  */
2257c5b184dSJason Gunthorpe #if IS_ENABLED(CONFIG_DEBUG_GENERIC_PT)
2267c5b184dSJason Gunthorpe #define PT_WARN_ON WARN_ON
2277c5b184dSJason Gunthorpe #else
PT_WARN_ON(bool condition)2287c5b184dSJason Gunthorpe static inline bool PT_WARN_ON(bool condition)
2297c5b184dSJason Gunthorpe {
2307c5b184dSJason Gunthorpe 	return false;
2317c5b184dSJason Gunthorpe }
2327c5b184dSJason Gunthorpe #endif
2337c5b184dSJason Gunthorpe 
2347c5b184dSJason Gunthorpe /* These all work on the VA type */
2357c5b184dSJason Gunthorpe #define log2_to_int(a_lg2) log2_to_int_t(pt_vaddr_t, a_lg2)
2367c5b184dSJason Gunthorpe #define log2_to_max_int(a_lg2) log2_to_max_int_t(pt_vaddr_t, a_lg2)
2377c5b184dSJason Gunthorpe #define log2_div(a, b_lg2) log2_div_t(pt_vaddr_t, a, b_lg2)
2387c5b184dSJason Gunthorpe #define log2_div_eq(a, b, c_lg2) log2_div_eq_t(pt_vaddr_t, a, b, c_lg2)
2397c5b184dSJason Gunthorpe #define log2_mod(a, b_lg2) log2_mod_t(pt_vaddr_t, a, b_lg2)
2407c5b184dSJason Gunthorpe #define log2_mod_eq_max(a, b_lg2) log2_mod_eq_max_t(pt_vaddr_t, a, b_lg2)
2417c5b184dSJason Gunthorpe #define log2_set_mod(a, val, b_lg2) log2_set_mod_t(pt_vaddr_t, a, val, b_lg2)
2427c5b184dSJason Gunthorpe #define log2_set_mod_max(a, b_lg2) log2_set_mod_max_t(pt_vaddr_t, a, b_lg2)
2437c5b184dSJason Gunthorpe #define log2_mul(a, b_lg2) log2_mul_t(pt_vaddr_t, a, b_lg2)
2447c5b184dSJason Gunthorpe #define vaffs(a) ffs_t(pt_vaddr_t, a)
2457c5b184dSJason Gunthorpe #define vafls(a) fls_t(pt_vaddr_t, a)
2467c5b184dSJason Gunthorpe #define vaffz(a) ffz_t(pt_vaddr_t, a)
2477c5b184dSJason Gunthorpe 
2487c5b184dSJason Gunthorpe /*
2497c5b184dSJason Gunthorpe  * The full VA (fva) versions permit the lg2 value to be == PT_VADDR_MAX_LG2 and
2507c5b184dSJason Gunthorpe  * generate a useful defined result. The non-fva versions will malfunction at
2517c5b184dSJason Gunthorpe  * this extreme.
2527c5b184dSJason Gunthorpe  */
fvalog2_div(pt_vaddr_t a,unsigned int b_lg2)2537c5b184dSJason Gunthorpe static inline pt_vaddr_t fvalog2_div(pt_vaddr_t a, unsigned int b_lg2)
2547c5b184dSJason Gunthorpe {
2557c5b184dSJason Gunthorpe 	if (PT_SUPPORTED_FEATURE(PT_FEAT_FULL_VA) && b_lg2 == PT_VADDR_MAX_LG2)
2567c5b184dSJason Gunthorpe 		return 0;
2577c5b184dSJason Gunthorpe 	return log2_div_t(pt_vaddr_t, a, b_lg2);
2587c5b184dSJason Gunthorpe }
2597c5b184dSJason Gunthorpe 
fvalog2_mod(pt_vaddr_t a,unsigned int b_lg2)2607c5b184dSJason Gunthorpe static inline pt_vaddr_t fvalog2_mod(pt_vaddr_t a, unsigned int b_lg2)
2617c5b184dSJason Gunthorpe {
2627c5b184dSJason Gunthorpe 	if (PT_SUPPORTED_FEATURE(PT_FEAT_FULL_VA) && b_lg2 == PT_VADDR_MAX_LG2)
2637c5b184dSJason Gunthorpe 		return a;
2647c5b184dSJason Gunthorpe 	return log2_mod_t(pt_vaddr_t, a, b_lg2);
2657c5b184dSJason Gunthorpe }
2667c5b184dSJason Gunthorpe 
fvalog2_div_eq(pt_vaddr_t a,pt_vaddr_t b,unsigned int c_lg2)2677c5b184dSJason Gunthorpe static inline bool fvalog2_div_eq(pt_vaddr_t a, pt_vaddr_t b,
2687c5b184dSJason Gunthorpe 				  unsigned int c_lg2)
2697c5b184dSJason Gunthorpe {
2707c5b184dSJason Gunthorpe 	if (PT_SUPPORTED_FEATURE(PT_FEAT_FULL_VA) && c_lg2 == PT_VADDR_MAX_LG2)
2717c5b184dSJason Gunthorpe 		return true;
2727c5b184dSJason Gunthorpe 	return log2_div_eq_t(pt_vaddr_t, a, b, c_lg2);
2737c5b184dSJason Gunthorpe }
2747c5b184dSJason Gunthorpe 
fvalog2_set_mod(pt_vaddr_t a,pt_vaddr_t val,unsigned int b_lg2)2757c5b184dSJason Gunthorpe static inline pt_vaddr_t fvalog2_set_mod(pt_vaddr_t a, pt_vaddr_t val,
2767c5b184dSJason Gunthorpe 					 unsigned int b_lg2)
2777c5b184dSJason Gunthorpe {
2787c5b184dSJason Gunthorpe 	if (PT_SUPPORTED_FEATURE(PT_FEAT_FULL_VA) && b_lg2 == PT_VADDR_MAX_LG2)
2797c5b184dSJason Gunthorpe 		return val;
2807c5b184dSJason Gunthorpe 	return log2_set_mod_t(pt_vaddr_t, a, val, b_lg2);
2817c5b184dSJason Gunthorpe }
2827c5b184dSJason Gunthorpe 
fvalog2_set_mod_max(pt_vaddr_t a,unsigned int b_lg2)2837c5b184dSJason Gunthorpe static inline pt_vaddr_t fvalog2_set_mod_max(pt_vaddr_t a, unsigned int b_lg2)
2847c5b184dSJason Gunthorpe {
2857c5b184dSJason Gunthorpe 	if (PT_SUPPORTED_FEATURE(PT_FEAT_FULL_VA) && b_lg2 == PT_VADDR_MAX_LG2)
2867c5b184dSJason Gunthorpe 		return PT_VADDR_MAX;
2877c5b184dSJason Gunthorpe 	return log2_set_mod_max_t(pt_vaddr_t, a, b_lg2);
2887c5b184dSJason Gunthorpe }
2897c5b184dSJason Gunthorpe 
2907c5b184dSJason Gunthorpe /* These all work on the OA type */
2917c5b184dSJason Gunthorpe #define oalog2_to_int(a_lg2) log2_to_int_t(pt_oaddr_t, a_lg2)
2927c5b184dSJason Gunthorpe #define oalog2_to_max_int(a_lg2) log2_to_max_int_t(pt_oaddr_t, a_lg2)
2937c5b184dSJason Gunthorpe #define oalog2_div(a, b_lg2) log2_div_t(pt_oaddr_t, a, b_lg2)
2947c5b184dSJason Gunthorpe #define oalog2_div_eq(a, b, c_lg2) log2_div_eq_t(pt_oaddr_t, a, b, c_lg2)
2957c5b184dSJason Gunthorpe #define oalog2_mod(a, b_lg2) log2_mod_t(pt_oaddr_t, a, b_lg2)
2967c5b184dSJason Gunthorpe #define oalog2_mod_eq_max(a, b_lg2) log2_mod_eq_max_t(pt_oaddr_t, a, b_lg2)
2977c5b184dSJason Gunthorpe #define oalog2_set_mod(a, val, b_lg2) log2_set_mod_t(pt_oaddr_t, a, val, b_lg2)
2987c5b184dSJason Gunthorpe #define oalog2_set_mod_max(a, b_lg2) log2_set_mod_max_t(pt_oaddr_t, a, b_lg2)
2997c5b184dSJason Gunthorpe #define oalog2_mul(a, b_lg2) log2_mul_t(pt_oaddr_t, a, b_lg2)
3007c5b184dSJason Gunthorpe #define oaffs(a) ffs_t(pt_oaddr_t, a)
3017c5b184dSJason Gunthorpe #define oafls(a) fls_t(pt_oaddr_t, a)
3027c5b184dSJason Gunthorpe #define oaffz(a) ffz_t(pt_oaddr_t, a)
3037c5b184dSJason Gunthorpe 
_pt_top_set(struct pt_table_p * table_mem,unsigned int top_level)3047c5b184dSJason Gunthorpe static inline uintptr_t _pt_top_set(struct pt_table_p *table_mem,
3057c5b184dSJason Gunthorpe 				    unsigned int top_level)
3067c5b184dSJason Gunthorpe {
3077c5b184dSJason Gunthorpe 	return top_level | (uintptr_t)table_mem;
3087c5b184dSJason Gunthorpe }
3097c5b184dSJason Gunthorpe 
pt_top_set(struct pt_common * common,struct pt_table_p * table_mem,unsigned int top_level)3107c5b184dSJason Gunthorpe static inline void pt_top_set(struct pt_common *common,
3117c5b184dSJason Gunthorpe 			      struct pt_table_p *table_mem,
3127c5b184dSJason Gunthorpe 			      unsigned int top_level)
3137c5b184dSJason Gunthorpe {
3147c5b184dSJason Gunthorpe 	WRITE_ONCE(common->top_of_table, _pt_top_set(table_mem, top_level));
3157c5b184dSJason Gunthorpe }
3167c5b184dSJason Gunthorpe 
pt_top_set_level(struct pt_common * common,unsigned int top_level)3177c5b184dSJason Gunthorpe static inline void pt_top_set_level(struct pt_common *common,
3187c5b184dSJason Gunthorpe 				    unsigned int top_level)
3197c5b184dSJason Gunthorpe {
3207c5b184dSJason Gunthorpe 	pt_top_set(common, NULL, top_level);
3217c5b184dSJason Gunthorpe }
3227c5b184dSJason Gunthorpe 
pt_top_get_level(const struct pt_common * common)3237c5b184dSJason Gunthorpe static inline unsigned int pt_top_get_level(const struct pt_common *common)
3247c5b184dSJason Gunthorpe {
3257c5b184dSJason Gunthorpe 	return READ_ONCE(common->top_of_table) % (1 << PT_TOP_LEVEL_BITS);
3267c5b184dSJason Gunthorpe }
3277c5b184dSJason Gunthorpe 
3287c5b184dSJason Gunthorpe static inline bool pt_check_install_leaf_args(struct pt_state *pts,
3297c5b184dSJason Gunthorpe 					      pt_oaddr_t oa,
3307c5b184dSJason Gunthorpe 					      unsigned int oasz_lg2);
3317c5b184dSJason Gunthorpe 
3327c5b184dSJason Gunthorpe #endif
333