1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright © 2022 Intel Corporation 4 */ 5 #ifndef __XE_PT_WALK__ 6 #define __XE_PT_WALK__ 7 8 #include <linux/pagewalk.h> 9 #include <linux/types.h> 10 11 struct xe_ptw_dir; 12 13 /** 14 * struct xe_ptw - base class for driver pagetable subclassing. 15 * @dir: Pointer to an array of children if any. 16 * 17 * Drivers could subclass this, and if it's a page-directory, typically 18 * embed the xe_ptw_dir::entries array in the same allocation. 19 */ 20 struct xe_ptw { 21 struct xe_ptw_dir *dir; 22 }; 23 24 /** 25 * struct xe_ptw_dir - page directory structure 26 * @entries: Array holding page directory children. 27 * 28 * It is the responsibility of the user to ensure @entries is 29 * correctly sized. 30 */ 31 struct xe_ptw_dir { 32 struct xe_ptw *entries[0]; 33 }; 34 35 /** 36 * struct xe_pt_walk - Embeddable struct for walk parameters 37 */ 38 struct xe_pt_walk { 39 /** @ops: The walk ops used for the pagewalk */ 40 const struct xe_pt_walk_ops *ops; 41 /** 42 * @shifts: Array of page-table entry shifts used for the 43 * different levels, starting out with the leaf level 0 44 * page-shift as the first entry. It's legal for this pointer to be 45 * changed during the walk. 46 */ 47 const u64 *shifts; 48 /** @max_level: Highest populated level in @sizes */ 49 unsigned int max_level; 50 /** 51 * @shared_pt_mode: Whether to skip all entries that are private 52 * to the address range and called only for entries that are 53 * shared with other address ranges. Such entries are referred to 54 * as shared pagetables. 55 */ 56 bool shared_pt_mode; 57 }; 58 59 /** 60 * typedef xe_pt_entry_fn - gpu page-table-walk callback-function 61 * @parent: The parent page.table. 62 * @offset: The offset (number of entries) into the page table. 63 * @level: The level of @parent. 64 * @addr: The virtual address. 65 * @next: The virtual address for the next call, or end address. 66 * @child: Pointer to pointer to child page-table at this @offset. The 67 * function may modify the value pointed to if, for example, allocating a 68 * child page table. 69 * @action: The walk action to take upon return. See <linux/pagewalk.h>. 70 * @walk: The walk parameters. 71 */ 72 typedef int (*xe_pt_entry_fn)(struct xe_ptw *parent, pgoff_t offset, 73 unsigned int level, u64 addr, u64 next, 74 struct xe_ptw **child, 75 enum page_walk_action *action, 76 struct xe_pt_walk *walk); 77 78 /** 79 * struct xe_pt_walk_ops - Walk callbacks. 80 */ 81 struct xe_pt_walk_ops { 82 /** 83 * @pt_entry: Callback to be called for each page table entry prior 84 * to descending to the next level. The returned value of the action 85 * function parameter is honored. 86 */ 87 xe_pt_entry_fn pt_entry; 88 /** 89 * @pt_post_descend: Callback to be called for each page table entry 90 * after return from descending to the next level. The returned value 91 * of the action function parameter is ignored. 92 */ 93 xe_pt_entry_fn pt_post_descend; 94 }; 95 96 int xe_pt_walk_range(struct xe_ptw *parent, unsigned int level, 97 u64 addr, u64 end, struct xe_pt_walk *walk); 98 99 int xe_pt_walk_shared(struct xe_ptw *parent, unsigned int level, 100 u64 addr, u64 end, struct xe_pt_walk *walk); 101 102 /** 103 * xe_pt_covers - Whether the address range covers an entire entry in @level 104 * @addr: Start of the range. 105 * @end: End of range + 1. 106 * @level: Page table level. 107 * @walk: Page table walk info. 108 * 109 * This function is a helper to aid in determining whether a leaf page table 110 * entry can be inserted at this @level. 111 * 112 * Return: Whether the range provided covers exactly an entry at this level. 113 */ 114 static inline bool xe_pt_covers(u64 addr, u64 end, unsigned int level, 115 const struct xe_pt_walk *walk) 116 { 117 u64 pt_size = 1ull << walk->shifts[level]; 118 119 return end - addr == pt_size && IS_ALIGNED(addr, pt_size); 120 } 121 122 /** 123 * xe_pt_num_entries: Number of page-table entries of a given range at this 124 * level 125 * @addr: Start address. 126 * @end: End address. 127 * @level: Page table level. 128 * @walk: Walk info. 129 * 130 * Return: The number of page table entries at this level between @start and 131 * @end. 132 */ 133 static inline pgoff_t 134 xe_pt_num_entries(u64 addr, u64 end, unsigned int level, 135 const struct xe_pt_walk *walk) 136 { 137 u64 pt_size = 1ull << walk->shifts[level]; 138 139 return (round_up(end, pt_size) - round_down(addr, pt_size)) >> 140 walk->shifts[level]; 141 } 142 143 /** 144 * xe_pt_offset: Offset of the page-table entry for a given address. 145 * @addr: The address. 146 * @level: Page table level. 147 * @walk: Walk info. 148 * 149 * Return: The page table entry offset for the given address in a 150 * page table with size indicated by @level. 151 */ 152 static inline pgoff_t 153 xe_pt_offset(u64 addr, unsigned int level, const struct xe_pt_walk *walk) 154 { 155 if (level < walk->max_level) 156 addr &= ((1ull << walk->shifts[level + 1]) - 1); 157 158 return addr >> walk->shifts[level]; 159 } 160 161 #endif 162