pt_fmt_defaults.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES
  4. *
  5. * Default definitions for formats that don't define these functions.
  6. */
  7. #ifndef __GENERIC_PT_PT_FMT_DEFAULTS_H
  8. #define __GENERIC_PT_PT_FMT_DEFAULTS_H
  9. #include "pt_defs.h"
  10. #include <linux/log2.h>
  11. /* Header self-compile default defines */
  12. #ifndef pt_load_entry_raw
  13. #include "fmt/amdv1.h"
  14. #endif
  15. /*
  16. * The format must provide PT_GRANULE_LG2SZ, PT_TABLEMEM_LG2SZ, and
  17. * PT_ITEM_WORD_SIZE. They must be the same at every level excluding the top.
  18. */
  19. #ifndef pt_table_item_lg2sz
  20. static inline unsigned int pt_table_item_lg2sz(const struct pt_state *pts)
  21. {
  22. return PT_GRANULE_LG2SZ +
  23. (PT_TABLEMEM_LG2SZ - ilog2(PT_ITEM_WORD_SIZE)) * pts->level;
  24. }
  25. #endif
  26. #ifndef pt_pgsz_lg2_to_level
  27. static inline unsigned int pt_pgsz_lg2_to_level(struct pt_common *common,
  28. unsigned int pgsize_lg2)
  29. {
  30. return ((unsigned int)(pgsize_lg2 - PT_GRANULE_LG2SZ)) /
  31. (PT_TABLEMEM_LG2SZ - ilog2(PT_ITEM_WORD_SIZE));
  32. }
  33. #endif
  34. /*
  35. * If not supplied by the format then contiguous pages are not supported.
  36. *
  37. * If contiguous pages are supported then the format must also provide
  38. * pt_contig_count_lg2() if it supports a single contiguous size per level,
  39. * or pt_possible_sizes() if it supports multiple sizes per level.
  40. */
  41. #ifndef pt_entry_num_contig_lg2
  42. static inline unsigned int pt_entry_num_contig_lg2(const struct pt_state *pts)
  43. {
  44. return ilog2(1);
  45. }
  46. /*
  47. * Return the number of contiguous OA items forming an entry at this table level
  48. */
  49. static inline unsigned short pt_contig_count_lg2(const struct pt_state *pts)
  50. {
  51. return ilog2(1);
  52. }
  53. #endif
  54. /* If not supplied by the format then dirty tracking is not supported */
  55. #ifndef pt_entry_is_write_dirty
  56. static inline bool pt_entry_is_write_dirty(const struct pt_state *pts)
  57. {
  58. return false;
  59. }
  60. static inline void pt_entry_make_write_clean(struct pt_state *pts)
  61. {
  62. }
  63. static inline bool pt_dirty_supported(struct pt_common *common)
  64. {
  65. return false;
  66. }
  67. #else
  68. /* If not supplied then dirty tracking is always enabled */
  69. #ifndef pt_dirty_supported
  70. static inline bool pt_dirty_supported(struct pt_common *common)
  71. {
  72. return true;
  73. }
  74. #endif
  75. #endif
  76. #ifndef pt_entry_make_write_dirty
  77. static inline bool pt_entry_make_write_dirty(struct pt_state *pts)
  78. {
  79. return false;
  80. }
  81. #endif
  82. /*
  83. * Format supplies either:
  84. * pt_entry_oa - OA is at the start of a contiguous entry
  85. * or
  86. * pt_item_oa - OA is adjusted for every item in a contiguous entry
  87. *
  88. * Build the missing one
  89. *
  90. * The internal helper _pt_entry_oa_fast() allows generating
  91. * an efficient pt_entry_oa_exact(), it doesn't care which
  92. * option is selected.
  93. */
  94. #ifdef pt_entry_oa
  95. static inline pt_oaddr_t pt_item_oa(const struct pt_state *pts)
  96. {
  97. return pt_entry_oa(pts) |
  98. log2_mul(pts->index, pt_table_item_lg2sz(pts));
  99. }
  100. #define _pt_entry_oa_fast pt_entry_oa
  101. #endif
  102. #ifdef pt_item_oa
  103. static inline pt_oaddr_t pt_entry_oa(const struct pt_state *pts)
  104. {
  105. return log2_set_mod(pt_item_oa(pts), 0,
  106. pt_entry_num_contig_lg2(pts) +
  107. pt_table_item_lg2sz(pts));
  108. }
  109. #define _pt_entry_oa_fast pt_item_oa
  110. #endif
  111. /*
  112. * If not supplied by the format then use the constant
  113. * PT_MAX_OUTPUT_ADDRESS_LG2.
  114. */
  115. #ifndef pt_max_oa_lg2
  116. static inline unsigned int
  117. pt_max_oa_lg2(const struct pt_common *common)
  118. {
  119. return PT_MAX_OUTPUT_ADDRESS_LG2;
  120. }
  121. #endif
  122. #ifndef pt_has_system_page_size
  123. static inline bool pt_has_system_page_size(const struct pt_common *common)
  124. {
  125. return PT_GRANULE_LG2SZ == PAGE_SHIFT;
  126. }
  127. #endif
  128. /*
  129. * If not supplied by the format then assume only one contiguous size determined
  130. * by pt_contig_count_lg2()
  131. */
  132. #ifndef pt_possible_sizes
  133. static inline unsigned short pt_contig_count_lg2(const struct pt_state *pts);
  134. /* Return a bitmap of possible leaf page sizes at this level */
  135. static inline pt_vaddr_t pt_possible_sizes(const struct pt_state *pts)
  136. {
  137. unsigned int isz_lg2 = pt_table_item_lg2sz(pts);
  138. if (!pt_can_have_leaf(pts))
  139. return 0;
  140. return log2_to_int(isz_lg2) |
  141. log2_to_int(pt_contig_count_lg2(pts) + isz_lg2);
  142. }
  143. #endif
  144. /* If not supplied by the format then use 0. */
  145. #ifndef pt_full_va_prefix
  146. static inline pt_vaddr_t pt_full_va_prefix(const struct pt_common *common)
  147. {
  148. return 0;
  149. }
  150. #endif
  151. /* If not supplied by the format then zero fill using PT_ITEM_WORD_SIZE */
  152. #ifndef pt_clear_entries
  153. static inline void pt_clear_entries64(struct pt_state *pts,
  154. unsigned int num_contig_lg2)
  155. {
  156. u64 *tablep = pt_cur_table(pts, u64) + pts->index;
  157. u64 *end = tablep + log2_to_int(num_contig_lg2);
  158. PT_WARN_ON(log2_mod(pts->index, num_contig_lg2));
  159. for (; tablep != end; tablep++)
  160. WRITE_ONCE(*tablep, 0);
  161. }
  162. static inline void pt_clear_entries32(struct pt_state *pts,
  163. unsigned int num_contig_lg2)
  164. {
  165. u32 *tablep = pt_cur_table(pts, u32) + pts->index;
  166. u32 *end = tablep + log2_to_int(num_contig_lg2);
  167. PT_WARN_ON(log2_mod(pts->index, num_contig_lg2));
  168. for (; tablep != end; tablep++)
  169. WRITE_ONCE(*tablep, 0);
  170. }
  171. static inline void pt_clear_entries(struct pt_state *pts,
  172. unsigned int num_contig_lg2)
  173. {
  174. if (PT_ITEM_WORD_SIZE == sizeof(u32))
  175. pt_clear_entries32(pts, num_contig_lg2);
  176. else
  177. pt_clear_entries64(pts, num_contig_lg2);
  178. }
  179. #define pt_clear_entries pt_clear_entries
  180. #endif
  181. /* If not supplied then SW bits are not supported */
  182. #ifdef pt_sw_bit
  183. static inline bool pt_test_sw_bit_acquire(struct pt_state *pts,
  184. unsigned int bitnr)
  185. {
  186. /* Acquire, pairs with pt_set_sw_bit_release() */
  187. smp_mb();
  188. /* For a contiguous entry the sw bit is only stored in the first item. */
  189. return pts->entry & pt_sw_bit(bitnr);
  190. }
  191. #define pt_test_sw_bit_acquire pt_test_sw_bit_acquire
  192. static inline void pt_set_sw_bit_release(struct pt_state *pts,
  193. unsigned int bitnr)
  194. {
  195. #if !IS_ENABLED(CONFIG_GENERIC_ATOMIC64)
  196. if (PT_ITEM_WORD_SIZE == sizeof(u64)) {
  197. u64 *entryp = pt_cur_table(pts, u64) + pts->index;
  198. u64 old_entry = pts->entry;
  199. u64 new_entry;
  200. do {
  201. new_entry = old_entry | pt_sw_bit(bitnr);
  202. } while (!try_cmpxchg64_release(entryp, &old_entry, new_entry));
  203. pts->entry = new_entry;
  204. return;
  205. }
  206. #endif
  207. if (PT_ITEM_WORD_SIZE == sizeof(u32)) {
  208. u32 *entryp = pt_cur_table(pts, u32) + pts->index;
  209. u32 old_entry = pts->entry;
  210. u32 new_entry;
  211. do {
  212. new_entry = old_entry | pt_sw_bit(bitnr);
  213. } while (!try_cmpxchg_release(entryp, &old_entry, new_entry));
  214. pts->entry = new_entry;
  215. } else
  216. BUILD_BUG();
  217. }
  218. #define pt_set_sw_bit_release pt_set_sw_bit_release
  219. #else
  220. static inline unsigned int pt_max_sw_bit(struct pt_common *common)
  221. {
  222. return 0;
  223. }
  224. extern void __pt_no_sw_bit(void);
  225. static inline bool pt_test_sw_bit_acquire(struct pt_state *pts,
  226. unsigned int bitnr)
  227. {
  228. __pt_no_sw_bit();
  229. return false;
  230. }
  231. static inline void pt_set_sw_bit_release(struct pt_state *pts,
  232. unsigned int bitnr)
  233. {
  234. __pt_no_sw_bit();
  235. }
  236. #endif
  237. /*
  238. * Format can call in the pt_install_leaf_entry() to check the arguments are all
  239. * aligned correctly.
  240. */
  241. static inline bool pt_check_install_leaf_args(struct pt_state *pts,
  242. pt_oaddr_t oa,
  243. unsigned int oasz_lg2)
  244. {
  245. unsigned int isz_lg2 = pt_table_item_lg2sz(pts);
  246. if (PT_WARN_ON(oalog2_mod(oa, oasz_lg2)))
  247. return false;
  248. #ifdef pt_possible_sizes
  249. if (PT_WARN_ON(isz_lg2 > oasz_lg2 ||
  250. oasz_lg2 > isz_lg2 + pt_num_items_lg2(pts)))
  251. return false;
  252. #else
  253. if (PT_WARN_ON(oasz_lg2 != isz_lg2 &&
  254. oasz_lg2 != isz_lg2 + pt_contig_count_lg2(pts)))
  255. return false;
  256. #endif
  257. if (PT_WARN_ON(oalog2_mod(pts->index, oasz_lg2 - isz_lg2)))
  258. return false;
  259. return true;
  260. }
  261. #endif