xref: /linux/drivers/gpu/drm/xe/xe_page_reclaim.h (revision fbf5df34a4dbcd09d433dd4f0916bf9b2ddb16de)
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(&gt_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