diff --git a/drivers/iommu/generic_pt/pt_fmt_defaults.h b/drivers/iommu/generic_pt/pt_fmt_defaults.h new file mode 100644 index 00000000000000..19e8f820c1dccf --- /dev/null +++ b/drivers/iommu/generic_pt/pt_fmt_defaults.h @@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/*
- Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES
- Default definitions for formats that don't define these functions.
- */
+#ifndef __GENERIC_PT_PT_FMT_DEFAULTS_H +#define __GENERIC_PT_PT_FMT_DEFAULTS_H
+#include "pt_defs.h" +#include <linux/log2.h>
+/* Header self-compile default defines */ +#ifndef pt_load_entry_raw +#include "fmt/amdv1.h" +#endif
+/*
- The format must provide PT_GRANULE_LG2SZ, PT_TABLEMEM_LG2SZ, and
- PT_ITEM_WORD_SIZE. They must be the same at every level excluding the top.
- */
+#ifndef pt_table_item_lg2sz +static inline unsigned int pt_table_item_lg2sz(const struct pt_state *pts) +{
- return PT_GRANULE_LG2SZ +
(PT_TABLEMEM_LG2SZ - ilog2(PT_ITEM_WORD_SIZE)) * pts->level;
+} +#endif
+#ifndef pt_pgsz_lg2_to_level +static inline unsigned int pt_pgsz_lg2_to_level(struct pt_common *common,
unsigned int pgsize_lg2)
+{
- return (pgsize_lg2 - PT_GRANULE_LG2SZ) /
(PT_TABLEMEM_LG2SZ - ilog2(PT_ITEM_WORD_SIZE));
- return 0;
this return is dead code.
+} +#endif
[snip]
+/**
- pt_compute_best_pgsize() - Determine the best page size for leaf entries
- @pgsz_bitmap: Permitted page sizes
- @va: Starting virtual address for the leaf entry
- @last_va: Last virtual address for the leaf entry, sets the max page size
- @oa: Starting output address for the leaf entry
- Compute the largest page size for va, last_va, and oa together and return it
- in lg2. The largest page size depends on the format's supported page sizes at
- this level, and the relative alignment of the VA and OA addresses. 0 means
- the OA cannot be stored with the provided pgsz_bitmap.
- */
+static inline unsigned int pt_compute_best_pgsize(pt_vaddr_t pgsz_bitmap,
pt_vaddr_t va,
pt_vaddr_t last_va,
pt_oaddr_t oa)
+{
- unsigned int best_pgsz_lg2;
- unsigned int pgsz_lg2;
- pt_vaddr_t len = last_va - va + 1;
- pt_vaddr_t mask;
- if (PT_WARN_ON(va >= last_va))
return 0;
- /*
* Given a VA/OA pair the best page size is the largest page side
largest page side or largest page size
* where:
*
* 1) VA and OA start at the page. Bitwise this is the count of least
* significant 0 bits.
* This also implies that last_va/oa has the same prefix as va/oa.
*/
- mask = va | oa;
- /*
* 2) The page size is not larger than the last_va (length). Since page
* sizes are always power of two this can't be larger than the
* largest power of two factor of the length.
*/
- mask |= log2_to_int(log2_fls(len) - 1);
- best_pgsz_lg2 = log2_ffs(mask);
- /* Choose the higest bit <= best_pgsz_lg2 */
higest -> highest
- if (best_pgsz_lg2 < PT_VADDR_MAX_LG2 - 1)
pgsz_bitmap = log2_mod(pgsz_bitmap, best_pgsz_lg2 + 1);
- pgsz_lg2 = log2_fls(pgsz_bitmap);
- if (!pgsz_lg2)
return 0;
- pgsz_lg2--;
- PT_WARN_ON(log2_mod(va, pgsz_lg2) != 0);
- PT_WARN_ON(oalog2_mod(oa, pgsz_lg2) != 0);
- PT_WARN_ON(va + log2_to_int(pgsz_lg2) - 1 > last_va);
- PT_WARN_ON(!log2_div_eq(va, va + log2_to_int(pgsz_lg2) - 1, pgsz_lg2));
- PT_WARN_ON(
!oalog2_div_eq(oa, oa + log2_to_int(pgsz_lg2) - 1, pgsz_lg2));
- return pgsz_lg2;
+}
Thanks, Alok