1 /* SPDX-License-Identifier: MIT */ 2 /* 3 * Copyright © 2025 Intel Corporation 4 */ 5 6 #ifndef _XE_PAGE_RECLAIM_H_ 7 #define _XE_PAGE_RECLAIM_H_ 8 9 #include <linux/kref.h> 10 #include <linux/mm.h> 11 #include <linux/slab.h> 12 #include <linux/types.h> 13 #include <linux/workqueue.h> 14 #include <linux/bits.h> 15 16 #define XE_PAGE_RECLAIM_MAX_ENTRIES 512 17 #define XE_PAGE_RECLAIM_LIST_MAX_SIZE SZ_4K 18 19 struct xe_tlb_inval; 20 struct xe_tlb_inval_fence; 21 struct xe_tile; 22 struct xe_gt; 23 struct xe_guc; 24 struct xe_vma; 25 26 struct xe_guc_page_reclaim_entry { 27 u64 qw; 28 /* valid reclaim entry bit */ 29 #define XE_PAGE_RECLAIM_VALID BIT_ULL(0) 30 /* 31 * offset order of page size to be reclaimed 32 * page_size = 1 << (XE_PTE_SHIFT + reclamation_size) 33 */ 34 #define XE_PAGE_RECLAIM_SIZE GENMASK_ULL(6, 1) 35 #define XE_PAGE_RECLAIM_RSVD_0 GENMASK_ULL(11, 7) 36 /* lower 20 bits of the physical address */ 37 #define XE_PAGE_RECLAIM_ADDR_LO GENMASK_ULL(31, 12) 38 /* upper 20 bits of the physical address */ 39 #define XE_PAGE_RECLAIM_ADDR_HI GENMASK_ULL(51, 32) 40 #define XE_PAGE_RECLAIM_RSVD_1 GENMASK_ULL(63, 52) 41 } __packed; 42 43 struct xe_page_reclaim_list { 44 /** @entries: array of page reclaim entries, page allocated */ 45 struct xe_guc_page_reclaim_entry *entries; 46 /** @num_entries: number of entries */ 47 int num_entries; 48 #define XE_PAGE_RECLAIM_INVALID_LIST -1 49 }; 50 51 /** 52 * xe_page_reclaim_list_is_new() - Check if PRL is new allocation 53 * @prl: Pointer to page reclaim list 54 * 55 * PRL indicates it hasn't been allocated through both values being NULL 56 */ 57 static inline bool xe_page_reclaim_list_is_new(struct xe_page_reclaim_list *prl) 58 { 59 return !prl->entries && prl->num_entries == 0; 60 } 61 62 /** 63 * xe_page_reclaim_list_valid() - Check if the page reclaim list is valid 64 * @prl: Pointer to page reclaim list 65 * 66 * PRL uses the XE_PAGE_RECLAIM_INVALID_LIST to indicate that a PRL 67 * is unusable. 68 */ 69 static inline bool xe_page_reclaim_list_valid(struct xe_page_reclaim_list *prl) 70 { 71 return !xe_page_reclaim_list_is_new(prl) && 72 prl->num_entries != XE_PAGE_RECLAIM_INVALID_LIST; 73 } 74 75 bool xe_page_reclaim_skip(struct xe_tile *tile, struct xe_vma *vma); 76 struct drm_suballoc *xe_page_reclaim_create_prl_bo(struct xe_tlb_inval *tlb_inval, 77 struct xe_page_reclaim_list *prl, 78 struct xe_tlb_inval_fence *fence); 79 void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list *prl); 80 81 /** 82 * xe_page_reclaim_list_abort() - Invalidate a PRL and log an abort reason 83 * @gt: GT owning the page reclaim request 84 * @prl: Page reclaim list to invalidate 85 * @fmt: format string for the log message with args 86 * 87 * Abort page reclaim process by invalidating PRL and doing any relevant logging. 88 */ 89 #define xe_page_reclaim_list_abort(gt, prl, fmt, ...) \ 90 do { \ 91 struct xe_gt *__gt = (gt); \ 92 struct xe_page_reclaim_list *__prl = (prl); \ 93 \ 94 xe_page_reclaim_list_invalidate(__prl); \ 95 xe_gt_stats_incr(__gt, XE_GT_STATS_ID_PRL_ABORTED_COUNT, 1); \ 96 vm_dbg(>_to_xe(__gt)->drm, "PRL aborted: " fmt, ##__VA_ARGS__); \ 97 } while (0) 98 99 void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl); 100 int xe_page_reclaim_list_alloc_entries(struct xe_page_reclaim_list *prl); 101 /** 102 * xe_page_reclaim_entries_get() - Increment the reference count of page reclaim entries. 103 * @entries: Pointer to the array of page reclaim entries. 104 * 105 * This function increments the reference count of the backing page. 106 */ 107 static inline void xe_page_reclaim_entries_get(struct xe_guc_page_reclaim_entry *entries) 108 { 109 if (entries) 110 get_page(virt_to_page(entries)); 111 } 112 113 /** 114 * xe_page_reclaim_entries_put() - Decrement the reference count of page reclaim entries. 115 * @entries: Pointer to the array of page reclaim entries. 116 * 117 * This function decrements the reference count of the backing page 118 * and frees it if the count reaches zero. 119 */ 120 static inline void xe_page_reclaim_entries_put(struct xe_guc_page_reclaim_entry *entries) 121 { 122 if (entries) 123 put_page(virt_to_page(entries)); 124 } 125 126 int xe_guc_page_reclaim_done_handler(struct xe_guc *guc, u32 *msg, u32 len); 127 128 #endif /* _XE_PAGE_RECLAIM_H_ */ 129