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