xref: /linux-6.15/include/linux/damon.h (revision 3b23a44f)
12224d848SSeongJae Park /* SPDX-License-Identifier: GPL-2.0 */
22224d848SSeongJae Park /*
32224d848SSeongJae Park  * DAMON api
42224d848SSeongJae Park  *
56ad59a38SSeongJae Park  * Author: SeongJae Park <[email protected]>
62224d848SSeongJae Park  */
72224d848SSeongJae Park 
82224d848SSeongJae Park #ifndef _DAMON_H_
92224d848SSeongJae Park #define _DAMON_H_
102224d848SSeongJae Park 
1198def236SSeongJae Park #include <linux/memcontrol.h>
122224d848SSeongJae Park #include <linux/mutex.h>
132224d848SSeongJae Park #include <linux/time64.h>
142224d848SSeongJae Park #include <linux/types.h>
159b2a38d6SXin Hao #include <linux/random.h>
162224d848SSeongJae Park 
17b9a6ac4eSSeongJae Park /* Minimal region size.  Every damon_region is aligned by this. */
18b9a6ac4eSSeongJae Park #define DAMON_MIN_REGION	PAGE_SIZE
1938683e00SSeongJae Park /* Max priority score for DAMON-based operation schemes */
2038683e00SSeongJae Park #define DAMOS_MAX_SCORE		(99)
21b9a6ac4eSSeongJae Park 
229b2a38d6SXin Hao /* Get a random number in [l, r) */
damon_rand(unsigned long l,unsigned long r)23234d6873SXin Hao static inline unsigned long damon_rand(unsigned long l, unsigned long r)
24234d6873SXin Hao {
258032bf12SJason A. Donenfeld 	return l + get_random_u32_below(r - l);
26234d6873SXin Hao }
279b2a38d6SXin Hao 
28f23b8eeeSSeongJae Park /**
29f23b8eeeSSeongJae Park  * struct damon_addr_range - Represents an address region of [@start, @end).
30f23b8eeeSSeongJae Park  * @start:	Start address of the region (inclusive).
31f23b8eeeSSeongJae Park  * @end:	End address of the region (exclusive).
32f23b8eeeSSeongJae Park  */
33f23b8eeeSSeongJae Park struct damon_addr_range {
34f23b8eeeSSeongJae Park 	unsigned long start;
35f23b8eeeSSeongJae Park 	unsigned long end;
36f23b8eeeSSeongJae Park };
37f23b8eeeSSeongJae Park 
38f23b8eeeSSeongJae Park /**
390431c426SUsama Arif  * struct damon_size_range - Represents size for filter to operate on [@min, @max].
400431c426SUsama Arif  * @min:	Min size (inclusive).
410431c426SUsama Arif  * @max:	Max size (inclusive).
420431c426SUsama Arif  */
430431c426SUsama Arif struct damon_size_range {
440431c426SUsama Arif 	unsigned long min;
450431c426SUsama Arif 	unsigned long max;
460431c426SUsama Arif };
470431c426SUsama Arif 
480431c426SUsama Arif /**
49f23b8eeeSSeongJae Park  * struct damon_region - Represents a monitoring target region.
50f23b8eeeSSeongJae Park  * @ar:			The address range of the region.
51f23b8eeeSSeongJae Park  * @sampling_addr:	Address of the sample for the next access check.
52f23b8eeeSSeongJae Park  * @nr_accesses:	Access frequency of this region.
53ace30fb2SSeongJae Park  * @nr_accesses_bp:	@nr_accesses in basis point (0.01%) that updated for
54ace30fb2SSeongJae Park  *			each sampling interval.
55f23b8eeeSSeongJae Park  * @list:		List head for siblings.
56fda504faSSeongJae Park  * @age:		Age of this region.
57fda504faSSeongJae Park  *
58d896073fSSeongJae Park  * @nr_accesses is reset to zero for every &damon_attrs->aggr_interval and be
59d896073fSSeongJae Park  * increased for every &damon_attrs->sample_interval if an access to the region
6078fbfb15SSeongJae Park  * during the last sampling interval is found.  The update of this field should
6178fbfb15SSeongJae Park  * not be done with direct access but with the helper function,
6278fbfb15SSeongJae Park  * damon_update_region_access_rate().
63d896073fSSeongJae Park  *
6480333828SSeongJae Park  * @nr_accesses_bp is another representation of @nr_accesses in basis point
65ace30fb2SSeongJae Park  * (1 in 10,000) that updated for every &damon_attrs->sample_interval in a
66ace30fb2SSeongJae Park  * manner similar to moving sum.  By the algorithm, this value becomes
67ace30fb2SSeongJae Park  * @nr_accesses * 10000 for every &struct damon_attrs->aggr_interval.  This can
68ace30fb2SSeongJae Park  * be used when the aggregation interval is too huge and therefore cannot wait
69ace30fb2SSeongJae Park  * for it before getting the access monitoring results.
7080333828SSeongJae Park  *
71fda504faSSeongJae Park  * @age is initially zero, increased for each aggregation interval, and reset
72fda504faSSeongJae Park  * to zero again if the access frequency is significantly changed.  If two
73fda504faSSeongJae Park  * regions are merged into a new region, both @nr_accesses and @age of the new
74fda504faSSeongJae Park  * region are set as region size-weighted average of those of the two regions.
75f23b8eeeSSeongJae Park  */
76f23b8eeeSSeongJae Park struct damon_region {
77f23b8eeeSSeongJae Park 	struct damon_addr_range ar;
78f23b8eeeSSeongJae Park 	unsigned long sampling_addr;
79f23b8eeeSSeongJae Park 	unsigned int nr_accesses;
8080333828SSeongJae Park 	unsigned int nr_accesses_bp;
81f23b8eeeSSeongJae Park 	struct list_head list;
82fda504faSSeongJae Park 
83fda504faSSeongJae Park 	unsigned int age;
84fda504faSSeongJae Park /* private: Internal value for age calculation. */
85fda504faSSeongJae Park 	unsigned int last_nr_accesses;
86f23b8eeeSSeongJae Park };
87f23b8eeeSSeongJae Park 
88f23b8eeeSSeongJae Park /**
89f23b8eeeSSeongJae Park  * struct damon_target - Represents a monitoring target.
901971bd63SSeongJae Park  * @pid:		The PID of the virtual address space to monitor.
91b9a6ac4eSSeongJae Park  * @nr_regions:		Number of monitoring target regions of this target.
92f23b8eeeSSeongJae Park  * @regions_list:	Head of the monitoring target regions of this target.
93f23b8eeeSSeongJae Park  * @list:		List head for siblings.
94f23b8eeeSSeongJae Park  *
95f23b8eeeSSeongJae Park  * Each monitoring context could have multiple targets.  For example, a context
96f23b8eeeSSeongJae Park  * for virtual memory address spaces could have multiple target processes.  The
97f7d911c3SSeongJae Park  * @pid should be set for appropriate &struct damon_operations including the
98f7d911c3SSeongJae Park  * virtual address spaces monitoring operations.
99f23b8eeeSSeongJae Park  */
100f23b8eeeSSeongJae Park struct damon_target {
1011971bd63SSeongJae Park 	struct pid *pid;
102b9a6ac4eSSeongJae Park 	unsigned int nr_regions;
103f23b8eeeSSeongJae Park 	struct list_head regions_list;
104f23b8eeeSSeongJae Park 	struct list_head list;
105f23b8eeeSSeongJae Park };
106f23b8eeeSSeongJae Park 
1071f366e42SSeongJae Park /**
1081f366e42SSeongJae Park  * enum damos_action - Represents an action of a Data Access Monitoring-based
1091f366e42SSeongJae Park  * Operation Scheme.
1101f366e42SSeongJae Park  *
1111f366e42SSeongJae Park  * @DAMOS_WILLNEED:	Call ``madvise()`` for the region with MADV_WILLNEED.
1121f366e42SSeongJae Park  * @DAMOS_COLD:		Call ``madvise()`` for the region with MADV_COLD.
1131f366e42SSeongJae Park  * @DAMOS_PAGEOUT:	Call ``madvise()`` for the region with MADV_PAGEOUT.
1141f366e42SSeongJae Park  * @DAMOS_HUGEPAGE:	Call ``madvise()`` for the region with MADV_HUGEPAGE.
1151f366e42SSeongJae Park  * @DAMOS_NOHUGEPAGE:	Call ``madvise()`` for the region with MADV_NOHUGEPAGE.
1168cdcc532SSeongJae Park  * @DAMOS_LRU_PRIO:	Prioritize the region on its LRU lists.
11799cdc2cdSSeongJae Park  * @DAMOS_LRU_DEPRIO:	Deprioritize the region on its LRU lists.
118b696722dSHyeongtak Ji  * @DAMOS_MIGRATE_HOT:  Migrate the regions prioritizing warmer regions.
119b51820ebSHonggyu Kim  * @DAMOS_MIGRATE_COLD:	Migrate the regions prioritizing colder regions.
1202f0b548cSSeongJae Park  * @DAMOS_STAT:		Do nothing but count the stat.
1215257f36eSSeongJae Park  * @NR_DAMOS_ACTIONS:	Total number of DAMOS actions
122fb6f026bSSeongJae Park  *
123fb6f026bSSeongJae Park  * The support of each action is up to running &struct damon_operations.
124fb6f026bSSeongJae Park  * &enum DAMON_OPS_VADDR and &enum DAMON_OPS_FVADDR supports all actions except
125fb6f026bSSeongJae Park  * &enum DAMOS_LRU_PRIO and &enum DAMOS_LRU_DEPRIO.  &enum DAMON_OPS_PADDR
126fb6f026bSSeongJae Park  * supports only &enum DAMOS_PAGEOUT, &enum DAMOS_LRU_PRIO, &enum
127fb6f026bSSeongJae Park  * DAMOS_LRU_DEPRIO, and &DAMOS_STAT.
1281f366e42SSeongJae Park  */
1291f366e42SSeongJae Park enum damos_action {
1301f366e42SSeongJae Park 	DAMOS_WILLNEED,
1311f366e42SSeongJae Park 	DAMOS_COLD,
1321f366e42SSeongJae Park 	DAMOS_PAGEOUT,
1331f366e42SSeongJae Park 	DAMOS_HUGEPAGE,
1341f366e42SSeongJae Park 	DAMOS_NOHUGEPAGE,
1358cdcc532SSeongJae Park 	DAMOS_LRU_PRIO,
13699cdc2cdSSeongJae Park 	DAMOS_LRU_DEPRIO,
137b696722dSHyeongtak Ji 	DAMOS_MIGRATE_HOT,
138b51820ebSHonggyu Kim 	DAMOS_MIGRATE_COLD,
1392f0b548cSSeongJae Park 	DAMOS_STAT,		/* Do nothing but only record the stat */
1405257f36eSSeongJae Park 	NR_DAMOS_ACTIONS,
1411f366e42SSeongJae Park };
1421f366e42SSeongJae Park 
1431f366e42SSeongJae Park /**
144bcce9bc1SSeongJae Park  * enum damos_quota_goal_metric - Represents the metric to be used as the goal
145bcce9bc1SSeongJae Park  *
146bcce9bc1SSeongJae Park  * @DAMOS_QUOTA_USER_INPUT:	User-input value.
1472dbb60f7SSeongJae Park  * @DAMOS_QUOTA_SOME_MEM_PSI_US:	System level some memory PSI in us.
148bcce9bc1SSeongJae Park  * @NR_DAMOS_QUOTA_GOAL_METRICS:	Number of DAMOS quota goal metrics.
149bcce9bc1SSeongJae Park  *
150bcce9bc1SSeongJae Park  * Metrics equal to larger than @NR_DAMOS_QUOTA_GOAL_METRICS are unsupported.
151bcce9bc1SSeongJae Park  */
152bcce9bc1SSeongJae Park enum damos_quota_goal_metric {
153bcce9bc1SSeongJae Park 	DAMOS_QUOTA_USER_INPUT,
1542dbb60f7SSeongJae Park 	DAMOS_QUOTA_SOME_MEM_PSI_US,
155bcce9bc1SSeongJae Park 	NR_DAMOS_QUOTA_GOAL_METRICS,
156bcce9bc1SSeongJae Park };
157bcce9bc1SSeongJae Park 
158bcce9bc1SSeongJae Park /**
159106e26fcSSeongJae Park  * struct damos_quota_goal - DAMOS scheme quota auto-tuning goal.
160bcce9bc1SSeongJae Park  * @metric:		Metric to be used for representing the goal.
161bcce9bc1SSeongJae Park  * @target_value:	Target value of @metric to achieve with the tuning.
162bcce9bc1SSeongJae Park  * @current_value:	Current value of @metric.
1632dbb60f7SSeongJae Park  * @last_psi_total:	Last measured total PSI
16491f21216SSeongJae Park  * @list:		List head for siblings.
165106e26fcSSeongJae Park  *
16606ba5b30SSeongJae Park  * Data structure for getting the current score of the quota tuning goal.  The
16706ba5b30SSeongJae Park  * score is calculated by how close @current_value and @target_value are.  Then
16806ba5b30SSeongJae Park  * the score is entered to DAMON's internal feedback loop mechanism to get the
16906ba5b30SSeongJae Park  * auto-tuned quota.
170bcce9bc1SSeongJae Park  *
171bcce9bc1SSeongJae Park  * If @metric is DAMOS_QUOTA_USER_INPUT, @current_value should be manually
172bcce9bc1SSeongJae Park  * entered by the user, probably inside the kdamond callbacks.  Otherwise,
173bcce9bc1SSeongJae Park  * DAMON sets @current_value with self-measured value of @metric.
174106e26fcSSeongJae Park  */
175106e26fcSSeongJae Park struct damos_quota_goal {
176bcce9bc1SSeongJae Park 	enum damos_quota_goal_metric metric;
17706ba5b30SSeongJae Park 	unsigned long target_value;
17806ba5b30SSeongJae Park 	unsigned long current_value;
1792dbb60f7SSeongJae Park 	/* metric-dependent fields */
1802dbb60f7SSeongJae Park 	union {
1812dbb60f7SSeongJae Park 		u64 last_psi_total;
1822dbb60f7SSeongJae Park 	};
18391f21216SSeongJae Park 	struct list_head list;
184106e26fcSSeongJae Park };
185106e26fcSSeongJae Park 
186106e26fcSSeongJae Park /**
1872b8a248dSSeongJae Park  * struct damos_quota - Controls the aggressiveness of the given scheme.
1884d791a0aSSeongJae Park  * @reset_interval:	Charge reset interval in milliseconds.
1891cd24303SSeongJae Park  * @ms:			Maximum milliseconds that the scheme can use.
1902b8a248dSSeongJae Park  * @sz:			Maximum bytes of memory that the action can be applied.
19191f21216SSeongJae Park  * @goals:		Head of quota tuning goals (&damos_quota_goal) list.
1924d791a0aSSeongJae Park  * @esz:		Effective size quota in bytes.
1932b8a248dSSeongJae Park  *
19438683e00SSeongJae Park  * @weight_sz:		Weight of the region's size for prioritization.
19538683e00SSeongJae Park  * @weight_nr_accesses:	Weight of the region's nr_accesses for prioritization.
19638683e00SSeongJae Park  * @weight_age:		Weight of the region's age for prioritization.
19738683e00SSeongJae Park  *
1982b8a248dSSeongJae Park  * To avoid consuming too much CPU time or IO resources for applying the
1991cd24303SSeongJae Park  * &struct damos->action to large memory, DAMON allows users to set time and/or
2001cd24303SSeongJae Park  * size quotas.  The quotas can be set by writing non-zero values to &ms and
2011cd24303SSeongJae Park  * &sz, respectively.  If the time quota is set, DAMON tries to use only up to
2021cd24303SSeongJae Park  * &ms milliseconds within &reset_interval for applying the action.  If the
2031cd24303SSeongJae Park  * size quota is set, DAMON tries to apply the action only up to &sz bytes
2041cd24303SSeongJae Park  * within &reset_interval.
2051cd24303SSeongJae Park  *
206d783cc59SSeongJae Park  * To convince the different types of quotas and goals, DAMON internally
207d783cc59SSeongJae Park  * converts those into one single size quota called "effective quota".  DAMON
208d783cc59SSeongJae Park  * internally uses it as the only one real quota.  The conversion is made as
209d783cc59SSeongJae Park  * follows.
21038683e00SSeongJae Park  *
211d783cc59SSeongJae Park  * The time quota is transformed to a size quota using estimated throughput of
212d783cc59SSeongJae Park  * the scheme's action.  DAMON then compares it against &sz and uses smaller
213d783cc59SSeongJae Park  * one as the effective quota.
214d783cc59SSeongJae Park  *
215d783cc59SSeongJae Park  * If @goals is not empty, DAMON calculates yet another size quota based on the
21689d347a5SSeongJae Park  * goals using its internal feedback loop algorithm, for every @reset_interval.
21789d347a5SSeongJae Park  * Then, if the new size quota is smaller than the effective quota, it uses the
21889d347a5SSeongJae Park  * new size quota as the effective quota.
21991f21216SSeongJae Park  *
22078f2f603SSeongJae Park  * The resulting effective size quota in bytes is set to @esz.
2214d791a0aSSeongJae Park  *
2224d791a0aSSeongJae Park  * For selecting regions within the quota, DAMON prioritizes current scheme's
2234d791a0aSSeongJae Park  * target memory regions using the &struct damon_operations->get_scheme_score.
2244d791a0aSSeongJae Park  * You could customize the prioritization logic by setting &weight_sz,
2254d791a0aSSeongJae Park  * &weight_nr_accesses, and &weight_age, because monitoring operations are
2264d791a0aSSeongJae Park  * encouraged to respect those.
2272b8a248dSSeongJae Park  */
2282b8a248dSSeongJae Park struct damos_quota {
2294d791a0aSSeongJae Park 	unsigned long reset_interval;
2301cd24303SSeongJae Park 	unsigned long ms;
2312b8a248dSSeongJae Park 	unsigned long sz;
23291f21216SSeongJae Park 	struct list_head goals;
2334d791a0aSSeongJae Park 	unsigned long esz;
2342b8a248dSSeongJae Park 
23538683e00SSeongJae Park 	unsigned int weight_sz;
23638683e00SSeongJae Park 	unsigned int weight_nr_accesses;
23738683e00SSeongJae Park 	unsigned int weight_age;
23838683e00SSeongJae Park 
2391cd24303SSeongJae Park /* private: */
2401cd24303SSeongJae Park 	/* For throughput estimation */
2411cd24303SSeongJae Park 	unsigned long total_charged_sz;
2421cd24303SSeongJae Park 	unsigned long total_charged_ns;
2431cd24303SSeongJae Park 
2441cd24303SSeongJae Park 	/* For charging the quota */
2452b8a248dSSeongJae Park 	unsigned long charged_sz;
2462b8a248dSSeongJae Park 	unsigned long charged_from;
24750585192SSeongJae Park 	struct damon_target *charge_target_from;
24850585192SSeongJae Park 	unsigned long charge_addr_from;
24938683e00SSeongJae Park 
25038683e00SSeongJae Park 	/* For prioritization */
25138683e00SSeongJae Park 	unsigned int min_score;
2529294a037SSeongJae Park 
2539294a037SSeongJae Park 	/* For feedback loop */
2549294a037SSeongJae Park 	unsigned long esz_bp;
2552b8a248dSSeongJae Park };
2562b8a248dSSeongJae Park 
2572b8a248dSSeongJae Park /**
258ee801b7dSSeongJae Park  * enum damos_wmark_metric - Represents the watermark metric.
259ee801b7dSSeongJae Park  *
260ee801b7dSSeongJae Park  * @DAMOS_WMARK_NONE:		Ignore the watermarks of the given scheme.
261ee801b7dSSeongJae Park  * @DAMOS_WMARK_FREE_MEM_RATE:	Free memory rate of the system in [0,1000].
2625257f36eSSeongJae Park  * @NR_DAMOS_WMARK_METRICS:	Total number of DAMOS watermark metrics
263ee801b7dSSeongJae Park  */
264ee801b7dSSeongJae Park enum damos_wmark_metric {
265ee801b7dSSeongJae Park 	DAMOS_WMARK_NONE,
266ee801b7dSSeongJae Park 	DAMOS_WMARK_FREE_MEM_RATE,
2675257f36eSSeongJae Park 	NR_DAMOS_WMARK_METRICS,
268ee801b7dSSeongJae Park };
269ee801b7dSSeongJae Park 
270ee801b7dSSeongJae Park /**
271ee801b7dSSeongJae Park  * struct damos_watermarks - Controls when a given scheme should be activated.
272ee801b7dSSeongJae Park  * @metric:	Metric for the watermarks.
273ee801b7dSSeongJae Park  * @interval:	Watermarks check time interval in microseconds.
274ee801b7dSSeongJae Park  * @high:	High watermark.
275ee801b7dSSeongJae Park  * @mid:	Middle watermark.
276ee801b7dSSeongJae Park  * @low:	Low watermark.
277ee801b7dSSeongJae Park  *
278ee801b7dSSeongJae Park  * If &metric is &DAMOS_WMARK_NONE, the scheme is always active.  Being active
279ee801b7dSSeongJae Park  * means DAMON does monitoring and applying the action of the scheme to
280ee801b7dSSeongJae Park  * appropriate memory regions.  Else, DAMON checks &metric of the system for at
281ee801b7dSSeongJae Park  * least every &interval microseconds and works as below.
282ee801b7dSSeongJae Park  *
283ee801b7dSSeongJae Park  * If &metric is higher than &high, the scheme is inactivated.  If &metric is
284ee801b7dSSeongJae Park  * between &mid and &low, the scheme is activated.  If &metric is lower than
285ee801b7dSSeongJae Park  * &low, the scheme is inactivated.
286ee801b7dSSeongJae Park  */
287ee801b7dSSeongJae Park struct damos_watermarks {
288ee801b7dSSeongJae Park 	enum damos_wmark_metric metric;
289ee801b7dSSeongJae Park 	unsigned long interval;
290ee801b7dSSeongJae Park 	unsigned long high;
291ee801b7dSSeongJae Park 	unsigned long mid;
292ee801b7dSSeongJae Park 	unsigned long low;
293ee801b7dSSeongJae Park 
294ee801b7dSSeongJae Park /* private: */
295ee801b7dSSeongJae Park 	bool activated;
296ee801b7dSSeongJae Park };
297ee801b7dSSeongJae Park 
298ee801b7dSSeongJae Park /**
2990e92c2eeSSeongJae Park  * struct damos_stat - Statistics on a given scheme.
3000e92c2eeSSeongJae Park  * @nr_tried:	Total number of regions that the scheme is tried to be applied.
3010e92c2eeSSeongJae Park  * @sz_tried:	Total size of regions that the scheme is tried to be applied.
3020e92c2eeSSeongJae Park  * @nr_applied:	Total number of regions that the scheme is applied.
3030e92c2eeSSeongJae Park  * @sz_applied:	Total size of regions that the scheme is applied.
30460fa9355SSeongJae Park  * @sz_ops_filter_passed:
30560fa9355SSeongJae Park  *		Total bytes that passed ops layer-handled DAMOS filters.
3066268eac3SSeongJae Park  * @qt_exceeds: Total number of times the quota of the scheme has exceeded.
307626ffabeSSeongJae Park  *
308626ffabeSSeongJae Park  * "Tried an action to a region" in this context means the DAMOS core logic
309626ffabeSSeongJae Park  * determined the region as eligible to apply the action.  The access pattern
310626ffabeSSeongJae Park  * (&struct damos_access_pattern), quotas (&struct damos_quota), watermarks
311626ffabeSSeongJae Park  * (&struct damos_watermarks) and filters (&struct damos_filter) that handled
312626ffabeSSeongJae Park  * on core logic can affect this.  The core logic asks the operation set
313626ffabeSSeongJae Park  * (&struct damon_operations) to apply the action to the region.
314626ffabeSSeongJae Park  *
315626ffabeSSeongJae Park  * "Applied an action to a region" in this context means the operation set
316626ffabeSSeongJae Park  * (&struct damon_operations) successfully applied the action to the region, at
317626ffabeSSeongJae Park  * least to a part of the region.  The filters (&struct damos_filter) that
318626ffabeSSeongJae Park  * handled on operation set layer and type of the action and pages of the
319626ffabeSSeongJae Park  * region can affect this.  For example, if a filter is set to exclude
320626ffabeSSeongJae Park  * anonymous pages and the region has only anonymous pages, the region will be
321626ffabeSSeongJae Park  * failed at applying the action.  If the action is &DAMOS_PAGEOUT and all
322626ffabeSSeongJae Park  * pages of the region are already paged out, the region will be failed at
323626ffabeSSeongJae Park  * applying the action.
3240e92c2eeSSeongJae Park  */
3250e92c2eeSSeongJae Park struct damos_stat {
3260e92c2eeSSeongJae Park 	unsigned long nr_tried;
3270e92c2eeSSeongJae Park 	unsigned long sz_tried;
3280e92c2eeSSeongJae Park 	unsigned long nr_applied;
3290e92c2eeSSeongJae Park 	unsigned long sz_applied;
33060fa9355SSeongJae Park 	unsigned long sz_ops_filter_passed;
3316268eac3SSeongJae Park 	unsigned long qt_exceeds;
3320e92c2eeSSeongJae Park };
3330e92c2eeSSeongJae Park 
3340e92c2eeSSeongJae Park /**
33598def236SSeongJae Park  * enum damos_filter_type - Type of memory for &struct damos_filter
33698def236SSeongJae Park  * @DAMOS_FILTER_TYPE_ANON:	Anonymous pages.
337*3b23a44fSNhat Pham  * @DAMOS_FILTER_TYPE_ACTIVE:	Active pages.
33898def236SSeongJae Park  * @DAMOS_FILTER_TYPE_MEMCG:	Specific memcg's pages.
3392d8b2465SSeongJae Park  * @DAMOS_FILTER_TYPE_YOUNG:	Recently accessed pages.
3400431c426SUsama Arif  * @DAMOS_FILTER_TYPE_HUGEPAGE_SIZE:	Page is part of a hugepage.
341f809b9f3SSeongJae Park  * @DAMOS_FILTER_TYPE_UNMAPPED:	Unmapped pages.
342ab9bda00SSeongJae Park  * @DAMOS_FILTER_TYPE_ADDR:	Address range.
34317e7c724SSeongJae Park  * @DAMOS_FILTER_TYPE_TARGET:	Data Access Monitoring target.
34498def236SSeongJae Park  * @NR_DAMOS_FILTER_TYPES:	Number of filter types.
34555901e89SSeongJae Park  *
346ab9bda00SSeongJae Park  * The anon pages type and memcg type filters are handled by underlying
347ab9bda00SSeongJae Park  * &struct damon_operations as a part of scheme action trying, and therefore
348ab9bda00SSeongJae Park  * accounted as 'tried'.  In contrast, other types are handled by core layer
349ab9bda00SSeongJae Park  * before trying of the action and therefore not accounted as 'tried'.
350ab9bda00SSeongJae Park  *
351ab9bda00SSeongJae Park  * The support of the filters that handled by &struct damon_operations depend
352ab9bda00SSeongJae Park  * on the running &struct damon_operations.
353ab9bda00SSeongJae Park  * &enum DAMON_OPS_PADDR supports both anon pages type and memcg type filters,
354ab9bda00SSeongJae Park  * while &enum DAMON_OPS_VADDR and &enum DAMON_OPS_FVADDR don't support any of
355ab9bda00SSeongJae Park  * the two types.
35698def236SSeongJae Park  */
35798def236SSeongJae Park enum damos_filter_type {
35898def236SSeongJae Park 	DAMOS_FILTER_TYPE_ANON,
359*3b23a44fSNhat Pham 	DAMOS_FILTER_TYPE_ACTIVE,
36098def236SSeongJae Park 	DAMOS_FILTER_TYPE_MEMCG,
3612d8b2465SSeongJae Park 	DAMOS_FILTER_TYPE_YOUNG,
3620431c426SUsama Arif 	DAMOS_FILTER_TYPE_HUGEPAGE_SIZE,
363f809b9f3SSeongJae Park 	DAMOS_FILTER_TYPE_UNMAPPED,
364ab9bda00SSeongJae Park 	DAMOS_FILTER_TYPE_ADDR,
36517e7c724SSeongJae Park 	DAMOS_FILTER_TYPE_TARGET,
36698def236SSeongJae Park 	NR_DAMOS_FILTER_TYPES,
36798def236SSeongJae Park };
36898def236SSeongJae Park 
36998def236SSeongJae Park /**
37098def236SSeongJae Park  * struct damos_filter - DAMOS action target memory filter.
371e20f52e8SSeongJae Park  * @type:	Type of the target memory.
372fe6d7fddSSeongJae Park  * @matching:	Whether this is for @type-matching memory.
373fe6d7fddSSeongJae Park  * @allow:	Whether to include or exclude the @matching memory.
37498def236SSeongJae Park  * @memcg_id:	Memcg id of the question if @type is DAMOS_FILTER_MEMCG.
375ab9bda00SSeongJae Park  * @addr_range:	Address range if @type is DAMOS_FILTER_TYPE_ADDR.
37617e7c724SSeongJae Park  * @target_idx:	Index of the &struct damon_target of
37717e7c724SSeongJae Park  *		&damon_ctx->adaptive_targets if @type is
37817e7c724SSeongJae Park  *		DAMOS_FILTER_TYPE_TARGET.
3790431c426SUsama Arif  * @sz_range:	Size range if @type is DAMOS_FILTER_TYPE_HUGEPAGE_SIZE.
38098def236SSeongJae Park  * @list:	List head for siblings.
38198def236SSeongJae Park  *
38298def236SSeongJae Park  * Before applying the &damos->action to a memory region, DAMOS checks if each
383e20f52e8SSeongJae Park  * byte of the region matches to this given condition and avoid applying the
384e20f52e8SSeongJae Park  * action if so.  Support of each filter type depends on the running &struct
385e20f52e8SSeongJae Park  * damon_operations and the type.  Refer to &enum damos_filter_type for more
386e20f52e8SSeongJae Park  * details.
38798def236SSeongJae Park  */
38898def236SSeongJae Park struct damos_filter {
38998def236SSeongJae Park 	enum damos_filter_type type;
39098def236SSeongJae Park 	bool matching;
391fe6d7fddSSeongJae Park 	bool allow;
39298def236SSeongJae Park 	union {
39398def236SSeongJae Park 		unsigned short memcg_id;
394ab9bda00SSeongJae Park 		struct damon_addr_range addr_range;
39517e7c724SSeongJae Park 		int target_idx;
3960431c426SUsama Arif 		struct damon_size_range sz_range;
39798def236SSeongJae Park 	};
39898def236SSeongJae Park 	struct list_head list;
39998def236SSeongJae Park };
40098def236SSeongJae Park 
401bf0eaba0SSeongJae Park struct damon_ctx;
402bf0eaba0SSeongJae Park struct damos;
403bf0eaba0SSeongJae Park 
404bf0eaba0SSeongJae Park /**
405bf0eaba0SSeongJae Park  * struct damos_walk_control - Control damos_walk().
406bf0eaba0SSeongJae Park  *
407bf0eaba0SSeongJae Park  * @walk_fn:	Function to be called back for each region.
408bf0eaba0SSeongJae Park  * @data:	Data that will be passed to walk functions.
409bf0eaba0SSeongJae Park  *
410bf0eaba0SSeongJae Park  * Control damos_walk(), which requests specific kdamond to invoke the given
411bf0eaba0SSeongJae Park  * function to each region that eligible to apply actions of the kdamond's
412bf0eaba0SSeongJae Park  * schemes.  Refer to damos_walk() for more details.
413bf0eaba0SSeongJae Park  */
414bf0eaba0SSeongJae Park struct damos_walk_control {
415bf0eaba0SSeongJae Park 	void (*walk_fn)(void *data, struct damon_ctx *ctx,
416bf0eaba0SSeongJae Park 			struct damon_target *t, struct damon_region *r,
417cfc33a7dSSeongJae Park 			struct damos *s, unsigned long sz_filter_passed);
418bf0eaba0SSeongJae Park 	void *data;
419bf0eaba0SSeongJae Park /* private: internal use only */
420bf0eaba0SSeongJae Park 	/* informs if the kdamond finished handling of the walk request */
421bf0eaba0SSeongJae Park 	struct completion completion;
422bf0eaba0SSeongJae Park 	/* informs if the walk is canceled. */
423bf0eaba0SSeongJae Park 	bool canceled;
424bf0eaba0SSeongJae Park };
425bf0eaba0SSeongJae Park 
42698def236SSeongJae Park /**
427f5a79d7cSYajun Deng  * struct damos_access_pattern - Target access pattern of the given scheme.
4281f366e42SSeongJae Park  * @min_sz_region:	Minimum size of target regions.
4291f366e42SSeongJae Park  * @max_sz_region:	Maximum size of target regions.
4301f366e42SSeongJae Park  * @min_nr_accesses:	Minimum ``->nr_accesses`` of target regions.
4311f366e42SSeongJae Park  * @max_nr_accesses:	Maximum ``->nr_accesses`` of target regions.
4321f366e42SSeongJae Park  * @min_age_region:	Minimum age of target regions.
4331f366e42SSeongJae Park  * @max_age_region:	Maximum age of target regions.
434f5a79d7cSYajun Deng  */
435f5a79d7cSYajun Deng struct damos_access_pattern {
436f5a79d7cSYajun Deng 	unsigned long min_sz_region;
437f5a79d7cSYajun Deng 	unsigned long max_sz_region;
438f5a79d7cSYajun Deng 	unsigned int min_nr_accesses;
439f5a79d7cSYajun Deng 	unsigned int max_nr_accesses;
440f5a79d7cSYajun Deng 	unsigned int min_age_region;
441f5a79d7cSYajun Deng 	unsigned int max_age_region;
442f5a79d7cSYajun Deng };
443f5a79d7cSYajun Deng 
444f5a79d7cSYajun Deng /**
445f5a79d7cSYajun Deng  * struct damos - Represents a Data Access Monitoring-based Operation Scheme.
446f5a79d7cSYajun Deng  * @pattern:		Access pattern of target regions.
4471f366e42SSeongJae Park  * @action:		&damo_action to be applied to the target regions.
44842f994b7SSeongJae Park  * @apply_interval_us:	The time between applying the @action.
4492b8a248dSSeongJae Park  * @quota:		Control the aggressiveness of this scheme.
450ee801b7dSSeongJae Park  * @wmarks:		Watermarks for automated (in)activation of this scheme.
451e36287c6SHyeongtak Ji  * @target_nid:		Destination node if @action is "migrate_{hot,cold}".
45298def236SSeongJae Park  * @filters:		Additional set of &struct damos_filter for &action.
453ab82e579SSeongJae Park  * @ops_filters:	ops layer handling &struct damos_filter objects list.
45494ba17adSSeongJae Park  * @last_applied:	Last @action applied ops-managing entity.
4550e92c2eeSSeongJae Park  * @stat:		Statistics of this scheme.
4561f366e42SSeongJae Park  * @list:		List head for siblings.
4571f366e42SSeongJae Park  *
45842f994b7SSeongJae Park  * For each @apply_interval_us, DAMON finds regions which fit in the
459f5a79d7cSYajun Deng  * &pattern and applies &action to those. To avoid consuming too much
460f5a79d7cSYajun Deng  * CPU time or IO resources for the &action, &quota is used.
4612b8a248dSSeongJae Park  *
46242f994b7SSeongJae Park  * If @apply_interval_us is zero, &damon_attrs->aggr_interval is used instead.
46342f994b7SSeongJae Park  *
464ee801b7dSSeongJae Park  * To do the work only when needed, schemes can be activated for specific
465ee801b7dSSeongJae Park  * system situations using &wmarks.  If all schemes that registered to the
466ee801b7dSSeongJae Park  * monitoring context are inactive, DAMON stops monitoring either, and just
467ee801b7dSSeongJae Park  * repeatedly checks the watermarks.
468ee801b7dSSeongJae Park  *
469e36287c6SHyeongtak Ji  * @target_nid is used to set the migration target node for migrate_hot or
470e36287c6SHyeongtak Ji  * migrate_cold actions, which means it's only meaningful when @action is either
471e36287c6SHyeongtak Ji  * "migrate_hot" or "migrate_cold".
472e36287c6SHyeongtak Ji  *
47398def236SSeongJae Park  * Before applying the &action to a memory region, &struct damon_operations
47498def236SSeongJae Park  * implementation could check pages of the region and skip &action to respect
47598def236SSeongJae Park  * &filters
47698def236SSeongJae Park  *
47794ba17adSSeongJae Park  * The minimum entity that @action can be applied depends on the underlying
47894ba17adSSeongJae Park  * &struct damon_operations.  Since it may not be aligned with the core layer
47994ba17adSSeongJae Park  * abstract, namely &struct damon_region, &struct damon_operations could apply
48094ba17adSSeongJae Park  * @action to same entity multiple times.  Large folios that underlying on
48194ba17adSSeongJae Park  * multiple &struct damon region objects could be such examples.  The &struct
48294ba17adSSeongJae Park  * damon_operations can use @last_applied to avoid that.  DAMOS core logic
48394ba17adSSeongJae Park  * unsets @last_applied when each regions walking for applying the scheme is
48494ba17adSSeongJae Park  * finished.
48594ba17adSSeongJae Park  *
4862b8a248dSSeongJae Park  * After applying the &action to each region, &stat_count and &stat_sz is
4872b8a248dSSeongJae Park  * updated to reflect the number of regions and total size of regions that the
4882b8a248dSSeongJae Park  * &action is applied.
4891f366e42SSeongJae Park  */
4901f366e42SSeongJae Park struct damos {
491f5a79d7cSYajun Deng 	struct damos_access_pattern pattern;
4921f366e42SSeongJae Park 	enum damos_action action;
49342f994b7SSeongJae Park 	unsigned long apply_interval_us;
49442f994b7SSeongJae Park /* private: internal use only */
49542f994b7SSeongJae Park 	/*
49642f994b7SSeongJae Park 	 * number of sample intervals that should be passed before applying
49742f994b7SSeongJae Park 	 * @action
49842f994b7SSeongJae Park 	 */
49942f994b7SSeongJae Park 	unsigned long next_apply_sis;
500bf0eaba0SSeongJae Park 	/* informs if ongoing DAMOS walk for this scheme is finished */
501bf0eaba0SSeongJae Park 	bool walk_completed;
50239a326e6SSeongJae Park 	/*
50339a326e6SSeongJae Park 	 * If the current region in the filtering stage is allowed by core
50439a326e6SSeongJae Park 	 * layer-handled filters.  If true, operations layer allows it, too.
50539a326e6SSeongJae Park 	 */
50639a326e6SSeongJae Park 	bool core_filters_allowed;
507dd038b72SSeongJae Park 	/* whether to reject core/ops filters umatched regions */
508dd038b72SSeongJae Park 	bool core_filters_default_reject;
509dd038b72SSeongJae Park 	bool ops_filters_default_reject;
51042f994b7SSeongJae Park /* public: */
5112b8a248dSSeongJae Park 	struct damos_quota quota;
512ee801b7dSSeongJae Park 	struct damos_watermarks wmarks;
513e36287c6SHyeongtak Ji 	union {
514e36287c6SHyeongtak Ji 		int target_nid;
515e36287c6SHyeongtak Ji 	};
51698def236SSeongJae Park 	struct list_head filters;
517ab82e579SSeongJae Park 	struct list_head ops_filters;
51894ba17adSSeongJae Park 	void *last_applied;
5190e92c2eeSSeongJae Park 	struct damos_stat stat;
5201f366e42SSeongJae Park 	struct list_head list;
5211f366e42SSeongJae Park };
5221f366e42SSeongJae Park 
5239f7b053aSSeongJae Park /**
5249f7b053aSSeongJae Park  * enum damon_ops_id - Identifier for each monitoring operations implementation
5259f7b053aSSeongJae Park  *
5269f7b053aSSeongJae Park  * @DAMON_OPS_VADDR:	Monitoring operations for virtual address spaces
527de6d0154SSeongJae Park  * @DAMON_OPS_FVADDR:	Monitoring operations for only fixed ranges of virtual
528de6d0154SSeongJae Park  *			address spaces
5299f7b053aSSeongJae Park  * @DAMON_OPS_PADDR:	Monitoring operations for the physical address space
530d4a157f5SGautam Menghani  * @NR_DAMON_OPS:	Number of monitoring operations implementations
5319f7b053aSSeongJae Park  */
5329f7b053aSSeongJae Park enum damon_ops_id {
5339f7b053aSSeongJae Park 	DAMON_OPS_VADDR,
534de6d0154SSeongJae Park 	DAMON_OPS_FVADDR,
5359f7b053aSSeongJae Park 	DAMON_OPS_PADDR,
5369f7b053aSSeongJae Park 	NR_DAMON_OPS,
5379f7b053aSSeongJae Park };
5389f7b053aSSeongJae Park 
5392224d848SSeongJae Park /**
540f7d911c3SSeongJae Park  * struct damon_operations - Monitoring operations for given use cases.
5412224d848SSeongJae Park  *
5429f7b053aSSeongJae Park  * @id:				Identifier of this operations set.
543f7d911c3SSeongJae Park  * @init:			Initialize operations-related data structures.
544f7d911c3SSeongJae Park  * @update:			Update operations-related data structures.
5452224d848SSeongJae Park  * @prepare_access_checks:	Prepare next access check of target regions.
5462224d848SSeongJae Park  * @check_accesses:		Check the accesses to target regions.
54738683e00SSeongJae Park  * @get_scheme_score:		Get the score of a region for a scheme.
5481f366e42SSeongJae Park  * @apply_scheme:		Apply a DAMON-based operation scheme.
5492224d848SSeongJae Park  * @target_valid:		Determine if the target is valid.
5502224d848SSeongJae Park  * @cleanup:			Clean up the context.
5512224d848SSeongJae Park  *
5522224d848SSeongJae Park  * DAMON can be extended for various address spaces and usages.  For this,
553f7d911c3SSeongJae Park  * users should register the low level operations for their target address
554f7d911c3SSeongJae Park  * space and usecase via the &damon_ctx.ops.  Then, the monitoring thread
5552224d848SSeongJae Park  * (&damon_ctx.kdamond) calls @init and @prepare_access_checks before starting
5566b3f013bSSeongJae Park  * the monitoring, @update after each &damon_attrs.ops_update_interval, and
5572224d848SSeongJae Park  * @check_accesses, @target_valid and @prepare_access_checks after each
558105f830fSSeongJae Park  * &damon_attrs.sample_interval.
5592224d848SSeongJae Park  *
5609f7b053aSSeongJae Park  * Each &struct damon_operations instance having valid @id can be registered
5619f7b053aSSeongJae Park  * via damon_register_ops() and selected by damon_select_ops() later.
562f7d911c3SSeongJae Park  * @init should initialize operations-related data structures.  For example,
5632224d848SSeongJae Park  * this could be used to construct proper monitoring target regions and link
564f23b8eeeSSeongJae Park  * those to @damon_ctx.adaptive_targets.
565f7d911c3SSeongJae Park  * @update should update the operations-related data structures.  For example,
5662224d848SSeongJae Park  * this could be used to update monitoring target regions for current status.
5672224d848SSeongJae Park  * @prepare_access_checks should manipulate the monitoring regions to be
5682224d848SSeongJae Park  * prepared for the next access check.
5692224d848SSeongJae Park  * @check_accesses should check the accesses to each region that made after the
5702224d848SSeongJae Park  * last preparation and update the number of observed accesses of each region.
571b9a6ac4eSSeongJae Park  * It should also return max number of observed accesses that made as a result
572b9a6ac4eSSeongJae Park  * of its update.  The value will be used for regions adjustment threshold.
57338683e00SSeongJae Park  * @get_scheme_score should return the priority score of a region for a scheme
57438683e00SSeongJae Park  * as an integer in [0, &DAMOS_MAX_SCORE].
5751f366e42SSeongJae Park  * @apply_scheme is called from @kdamond when a region for user provided
5761f366e42SSeongJae Park  * DAMON-based operation scheme is found.  It should apply the scheme's action
5770e92c2eeSSeongJae Park  * to the region and return bytes of the region that the action is successfully
578b5bbe9c0SSeongJae Park  * applied.  It should also report how many bytes of the region has passed
579b5bbe9c0SSeongJae Park  * filters (&struct damos_filter) that handled by itself.
5802224d848SSeongJae Park  * @target_valid should check whether the target is still valid for the
5812224d848SSeongJae Park  * monitoring.
5822224d848SSeongJae Park  * @cleanup is called from @kdamond just before its termination.
5832224d848SSeongJae Park  */
584f7d911c3SSeongJae Park struct damon_operations {
5859f7b053aSSeongJae Park 	enum damon_ops_id id;
5862224d848SSeongJae Park 	void (*init)(struct damon_ctx *context);
5872224d848SSeongJae Park 	void (*update)(struct damon_ctx *context);
5882224d848SSeongJae Park 	void (*prepare_access_checks)(struct damon_ctx *context);
589b9a6ac4eSSeongJae Park 	unsigned int (*check_accesses)(struct damon_ctx *context);
59038683e00SSeongJae Park 	int (*get_scheme_score)(struct damon_ctx *context,
59138683e00SSeongJae Park 			struct damon_target *t, struct damon_region *r,
59238683e00SSeongJae Park 			struct damos *scheme);
5930e92c2eeSSeongJae Park 	unsigned long (*apply_scheme)(struct damon_ctx *context,
5940e92c2eeSSeongJae Park 			struct damon_target *t, struct damon_region *r,
595b5bbe9c0SSeongJae Park 			struct damos *scheme, unsigned long *sz_filter_passed);
59616bc1b0fSKaixu Xia 	bool (*target_valid)(struct damon_target *t);
5972224d848SSeongJae Park 	void (*cleanup)(struct damon_ctx *context);
5982224d848SSeongJae Park };
5992224d848SSeongJae Park 
600d2f272b3SSeongJae Park /**
601d2f272b3SSeongJae Park  * struct damon_callback - Monitoring events notification callbacks.
6022224d848SSeongJae Park  *
6036e74d2bfSSeongJae Park  * @after_wmarks_check:	Called after each schemes' watermarks check.
6042224d848SSeongJae Park  * @after_aggregation:	Called after each aggregation.
6052224d848SSeongJae Park  * @before_terminate:	Called before terminating the monitoring.
6062224d848SSeongJae Park  *
60707da2185SSeongJae Park  * The monitoring thread (&damon_ctx.kdamond) calls @before_terminate just
60807da2185SSeongJae Park  * before finishing the monitoring.
6092224d848SSeongJae Park  *
6106e74d2bfSSeongJae Park  * The monitoring thread calls @after_wmarks_check after each DAMON-based
6116e74d2bfSSeongJae Park  * operation schemes' watermarks check.  If users need to make changes to the
6126e74d2bfSSeongJae Park  * attributes of the monitoring context while it's deactivated due to the
6136e74d2bfSSeongJae Park  * watermarks, this is the good place to do.
6146e74d2bfSSeongJae Park  *
615cedee98fSSeongJae Park  * The monitoring thread calls @after_aggregation for each of the aggregation
616cedee98fSSeongJae Park  * intervals.  Therefore, users can safely access the monitoring results
617cedee98fSSeongJae Park  * without additional protection.  For the reason, users are recommended to use
618cedee98fSSeongJae Park  * these callback for the accesses to the results.
6192224d848SSeongJae Park  *
6202224d848SSeongJae Park  * If any callback returns non-zero, monitoring stops.
6212224d848SSeongJae Park  */
6222224d848SSeongJae Park struct damon_callback {
6236e74d2bfSSeongJae Park 	int (*after_wmarks_check)(struct damon_ctx *context);
6242224d848SSeongJae Park 	int (*after_aggregation)(struct damon_ctx *context);
625658f9ae7SChangbin Du 	void (*before_terminate)(struct damon_ctx *context);
6262224d848SSeongJae Park };
6272224d848SSeongJae Park 
62842b7491aSSeongJae Park /*
62942b7491aSSeongJae Park  * struct damon_call_control - Control damon_call().
63042b7491aSSeongJae Park  *
63142b7491aSSeongJae Park  * @fn:			Function to be called back.
63242b7491aSSeongJae Park  * @data:		Data that will be passed to @fn.
63342b7491aSSeongJae Park  * @return_code:	Return code from @fn invocation.
63442b7491aSSeongJae Park  *
63542b7491aSSeongJae Park  * Control damon_call(), which requests specific kdamond to invoke a given
63642b7491aSSeongJae Park  * function.  Refer to damon_call() for more details.
63742b7491aSSeongJae Park  */
63842b7491aSSeongJae Park struct damon_call_control {
63942b7491aSSeongJae Park 	int (*fn)(void *data);
64042b7491aSSeongJae Park 	void *data;
64142b7491aSSeongJae Park 	int return_code;
64242b7491aSSeongJae Park /* private: internal use only */
64342b7491aSSeongJae Park 	/* informs if the kdamond finished handling of the request */
64442b7491aSSeongJae Park 	struct completion completion;
64542b7491aSSeongJae Park 	/* informs if the kdamond canceled @fn infocation */
64642b7491aSSeongJae Park 	bool canceled;
64742b7491aSSeongJae Park };
64842b7491aSSeongJae Park 
6492224d848SSeongJae Park /**
6501eb3471bSSeongJae Park  * struct damon_intervals_goal - Monitoring intervals auto-tuning goal.
6511eb3471bSSeongJae Park  *
6521eb3471bSSeongJae Park  * @access_bp:		Access events observation ratio to achieve in bp.
6531eb3471bSSeongJae Park  * @aggrs:		Number of aggregations to acheive @access_bp within.
6541eb3471bSSeongJae Park  * @min_sample_us:	Minimum resulting sampling interval in microseconds.
6551eb3471bSSeongJae Park  * @max_sample_us:	Maximum resulting sampling interval in microseconds.
6561eb3471bSSeongJae Park  *
6571eb3471bSSeongJae Park  * DAMON automatically tunes &damon_attrs->sample_interval and
6581eb3471bSSeongJae Park  * &damon_attrs->aggr_interval aiming the ratio in bp (1/10,000) of
6591eb3471bSSeongJae Park  * DAMON-observed access events to theoretical maximum amount within @aggrs
6601eb3471bSSeongJae Park  * aggregations be same to @access_bp.  The logic increases
6611eb3471bSSeongJae Park  * &damon_attrs->aggr_interval and &damon_attrs->sampling_interval in same
6621eb3471bSSeongJae Park  * ratio if the current access events observation ratio is lower than the
6631eb3471bSSeongJae Park  * target for each @aggrs aggregations, and vice versa.
6641eb3471bSSeongJae Park  *
6651eb3471bSSeongJae Park  * If @aggrs is zero, the tuning is disabled and hence this struct is ignored.
6661eb3471bSSeongJae Park  */
6671eb3471bSSeongJae Park struct damon_intervals_goal {
6681eb3471bSSeongJae Park 	unsigned long access_bp;
6691eb3471bSSeongJae Park 	unsigned long aggrs;
6701eb3471bSSeongJae Park 	unsigned long min_sample_us;
6711eb3471bSSeongJae Park 	unsigned long max_sample_us;
6721eb3471bSSeongJae Park };
6731eb3471bSSeongJae Park 
6741eb3471bSSeongJae Park /**
675cbeaa77bSSeongJae Park  * struct damon_attrs - Monitoring attributes for accuracy/overhead control.
6762224d848SSeongJae Park  *
6772224d848SSeongJae Park  * @sample_interval:		The time between access samplings.
6782224d848SSeongJae Park  * @aggr_interval:		The time between monitor results aggregations.
679f7d911c3SSeongJae Park  * @ops_update_interval:	The time between monitoring operations updates.
6801eb3471bSSeongJae Park  * @intervals_goal:		Intervals auto-tuning goal.
681cbeaa77bSSeongJae Park  * @min_nr_regions:		The minimum number of adaptive monitoring
682cbeaa77bSSeongJae Park  *				regions.
683cbeaa77bSSeongJae Park  * @max_nr_regions:		The maximum number of adaptive monitoring
684cbeaa77bSSeongJae Park  *				regions.
6852224d848SSeongJae Park  *
6862224d848SSeongJae Park  * For each @sample_interval, DAMON checks whether each region is accessed or
687d896073fSSeongJae Park  * not during the last @sample_interval.  If such access is found, DAMON
688d896073fSSeongJae Park  * aggregates the information by increasing &damon_region->nr_accesses for
689d896073fSSeongJae Park  * @aggr_interval time.  For each @aggr_interval, the count is reset.  DAMON
690d896073fSSeongJae Park  * also checks whether the target memory regions need update (e.g., by
691d896073fSSeongJae Park  * ``mmap()`` calls from the application, in case of virtual memory monitoring)
692d896073fSSeongJae Park  * and applies the changes for each @ops_update_interval.  All time intervals
693d896073fSSeongJae Park  * are in micro-seconds.  Please refer to &struct damon_operations and &struct
694d896073fSSeongJae Park  * damon_callback for more detail.
695cbeaa77bSSeongJae Park  */
696cbeaa77bSSeongJae Park struct damon_attrs {
697cbeaa77bSSeongJae Park 	unsigned long sample_interval;
698cbeaa77bSSeongJae Park 	unsigned long aggr_interval;
699cbeaa77bSSeongJae Park 	unsigned long ops_update_interval;
7001eb3471bSSeongJae Park 	struct damon_intervals_goal intervals_goal;
701cbeaa77bSSeongJae Park 	unsigned long min_nr_regions;
702cbeaa77bSSeongJae Park 	unsigned long max_nr_regions;
703f04b0fedSSeongJae Park /* private: internal use only */
704f04b0fedSSeongJae Park 	/*
705f04b0fedSSeongJae Park 	 * @aggr_interval to @sample_interval ratio.
706f04b0fedSSeongJae Park 	 * Core-external components call damon_set_attrs() with &damon_attrs
707f04b0fedSSeongJae Park 	 * that this field is unset.  In the case, damon_set_attrs() sets this
708f04b0fedSSeongJae Park 	 * field of resulting &damon_attrs.  Core-internal components such as
709f04b0fedSSeongJae Park 	 * kdamond_tune_intervals() calls damon_set_attrs() with &damon_attrs
710f04b0fedSSeongJae Park 	 * that this field is set.  In the case, damon_set_attrs() just keep
711f04b0fedSSeongJae Park 	 * it.
712f04b0fedSSeongJae Park 	 */
713f04b0fedSSeongJae Park 	unsigned long aggr_samples;
714cbeaa77bSSeongJae Park };
715cbeaa77bSSeongJae Park 
716cbeaa77bSSeongJae Park /**
717cbeaa77bSSeongJae Park  * struct damon_ctx - Represents a context for each monitoring.  This is the
718cbeaa77bSSeongJae Park  * main interface that allows users to set the attributes and get the results
719cbeaa77bSSeongJae Park  * of the monitoring.
7202224d848SSeongJae Park  *
721cbeaa77bSSeongJae Park  * @attrs:		Monitoring attributes for accuracy/overhead control.
7222224d848SSeongJae Park  * @kdamond:		Kernel thread who does the monitoring.
7232224d848SSeongJae Park  * @kdamond_lock:	Mutex for the synchronizations with @kdamond.
7242224d848SSeongJae Park  *
7252224d848SSeongJae Park  * For each monitoring context, one kernel thread for the monitoring is
7262224d848SSeongJae Park  * created.  The pointer to the thread is stored in @kdamond.
7272224d848SSeongJae Park  *
7282224d848SSeongJae Park  * Once started, the monitoring thread runs until explicitly required to be
7292224d848SSeongJae Park  * terminated or every monitoring target is invalid.  The validity of the
730f7d911c3SSeongJae Park  * targets is checked via the &damon_operations.target_valid of @ops.  The
731bcc728ebSChengming Zhou  * termination can also be explicitly requested by calling damon_stop().
732bcc728ebSChengming Zhou  * The thread sets @kdamond to NULL when it terminates. Therefore, users can
733bcc728ebSChengming Zhou  * know whether the monitoring is ongoing or terminated by reading @kdamond.
734bcc728ebSChengming Zhou  * Reads and writes to @kdamond from outside of the monitoring thread must
735bcc728ebSChengming Zhou  * be protected by @kdamond_lock.
7362224d848SSeongJae Park  *
737bcc728ebSChengming Zhou  * Note that the monitoring thread protects only @kdamond via @kdamond_lock.
738bcc728ebSChengming Zhou  * Accesses to other fields must be protected by themselves.
7392224d848SSeongJae Park  *
740f7d911c3SSeongJae Park  * @ops:	Set of monitoring operations for given use cases.
7412224d848SSeongJae Park  * @callback:	Set of callbacks for monitoring events notifications.
7422224d848SSeongJae Park  *
743b9a6ac4eSSeongJae Park  * @adaptive_targets:	Head of monitoring targets (&damon_target) list.
7441f366e42SSeongJae Park  * @schemes:		Head of schemes (&damos) list.
7452224d848SSeongJae Park  */
7462224d848SSeongJae Park struct damon_ctx {
747cbeaa77bSSeongJae Park 	struct damon_attrs attrs;
7482224d848SSeongJae Park 
7492224d848SSeongJae Park /* private: internal use only */
7504472edf6SSeongJae Park 	/* number of sample intervals that passed since this context started */
7514472edf6SSeongJae Park 	unsigned long passed_sample_intervals;
7524472edf6SSeongJae Park 	/*
7534472edf6SSeongJae Park 	 * number of sample intervals that should be passed before next
7544472edf6SSeongJae Park 	 * aggregation
7554472edf6SSeongJae Park 	 */
7564472edf6SSeongJae Park 	unsigned long next_aggregation_sis;
7574472edf6SSeongJae Park 	/*
7584472edf6SSeongJae Park 	 * number of sample intervals that should be passed before next ops
7594472edf6SSeongJae Park 	 * update
7604472edf6SSeongJae Park 	 */
7614472edf6SSeongJae Park 	unsigned long next_ops_update_sis;
762f04b0fedSSeongJae Park 	/*
763f04b0fedSSeongJae Park 	 * number of sample intervals that should be passed before next
764f04b0fedSSeongJae Park 	 * intervals tuning
765f04b0fedSSeongJae Park 	 */
766f04b0fedSSeongJae Park 	unsigned long next_intervals_tune_sis;
7676376a824SSeongJae Park 	/* for waiting until the execution of the kdamond_fn is started */
7686376a824SSeongJae Park 	struct completion kdamond_started;
769b7315fbbSSeongJae Park 	/* for scheme quotas prioritization */
770b7315fbbSSeongJae Park 	unsigned long *regions_score_histogram;
7712224d848SSeongJae Park 
77242b7491aSSeongJae Park 	struct damon_call_control *call_control;
77342b7491aSSeongJae Park 	struct mutex call_control_lock;
77442b7491aSSeongJae Park 
775bf0eaba0SSeongJae Park 	struct damos_walk_control *walk_control;
776bf0eaba0SSeongJae Park 	struct mutex walk_control_lock;
777bf0eaba0SSeongJae Park 
7782224d848SSeongJae Park /* public: */
7792224d848SSeongJae Park 	struct task_struct *kdamond;
7802224d848SSeongJae Park 	struct mutex kdamond_lock;
7812224d848SSeongJae Park 
782f7d911c3SSeongJae Park 	struct damon_operations ops;
7832224d848SSeongJae Park 	struct damon_callback callback;
7842224d848SSeongJae Park 
785b9a6ac4eSSeongJae Park 	struct list_head adaptive_targets;
7861f366e42SSeongJae Park 	struct list_head schemes;
7872224d848SSeongJae Park };
7882224d848SSeongJae Park 
damon_next_region(struct damon_region * r)78988f86dcfSSeongJae Park static inline struct damon_region *damon_next_region(struct damon_region *r)
79088f86dcfSSeongJae Park {
79188f86dcfSSeongJae Park 	return container_of(r->list.next, struct damon_region, list);
79288f86dcfSSeongJae Park }
793f23b8eeeSSeongJae Park 
damon_prev_region(struct damon_region * r)79488f86dcfSSeongJae Park static inline struct damon_region *damon_prev_region(struct damon_region *r)
79588f86dcfSSeongJae Park {
79688f86dcfSSeongJae Park 	return container_of(r->list.prev, struct damon_region, list);
79788f86dcfSSeongJae Park }
798f23b8eeeSSeongJae Park 
damon_last_region(struct damon_target * t)79988f86dcfSSeongJae Park static inline struct damon_region *damon_last_region(struct damon_target *t)
80088f86dcfSSeongJae Park {
80188f86dcfSSeongJae Park 	return list_last_entry(&t->regions_list, struct damon_region, list);
80288f86dcfSSeongJae Park }
80350585192SSeongJae Park 
damon_first_region(struct damon_target * t)80436001cbaSKaixu Xia static inline struct damon_region *damon_first_region(struct damon_target *t)
80536001cbaSKaixu Xia {
80636001cbaSKaixu Xia 	return list_first_entry(&t->regions_list, struct damon_region, list);
80736001cbaSKaixu Xia }
80836001cbaSKaixu Xia 
damon_sz_region(struct damon_region * r)809652e0446SXin Hao static inline unsigned long damon_sz_region(struct damon_region *r)
810652e0446SXin Hao {
811652e0446SXin Hao 	return r->ar.end - r->ar.start;
812652e0446SXin Hao }
813652e0446SXin Hao 
814652e0446SXin Hao 
815f23b8eeeSSeongJae Park #define damon_for_each_region(r, t) \
816f23b8eeeSSeongJae Park 	list_for_each_entry(r, &t->regions_list, list)
817f23b8eeeSSeongJae Park 
81836001cbaSKaixu Xia #define damon_for_each_region_from(r, t) \
81936001cbaSKaixu Xia 	list_for_each_entry_from(r, &t->regions_list, list)
82036001cbaSKaixu Xia 
821f23b8eeeSSeongJae Park #define damon_for_each_region_safe(r, next, t) \
822f23b8eeeSSeongJae Park 	list_for_each_entry_safe(r, next, &t->regions_list, list)
823f23b8eeeSSeongJae Park 
824f23b8eeeSSeongJae Park #define damon_for_each_target(t, ctx) \
825b9a6ac4eSSeongJae Park 	list_for_each_entry(t, &(ctx)->adaptive_targets, list)
826f23b8eeeSSeongJae Park 
827f23b8eeeSSeongJae Park #define damon_for_each_target_safe(t, next, ctx)	\
828b9a6ac4eSSeongJae Park 	list_for_each_entry_safe(t, next, &(ctx)->adaptive_targets, list)
829f23b8eeeSSeongJae Park 
8301f366e42SSeongJae Park #define damon_for_each_scheme(s, ctx) \
8311f366e42SSeongJae Park 	list_for_each_entry(s, &(ctx)->schemes, list)
8321f366e42SSeongJae Park 
8331f366e42SSeongJae Park #define damon_for_each_scheme_safe(s, next, ctx) \
8341f366e42SSeongJae Park 	list_for_each_entry_safe(s, next, &(ctx)->schemes, list)
8351f366e42SSeongJae Park 
83691f21216SSeongJae Park #define damos_for_each_quota_goal(goal, quota) \
83791f21216SSeongJae Park 	list_for_each_entry(goal, &quota->goals, list)
83891f21216SSeongJae Park 
83991f21216SSeongJae Park #define damos_for_each_quota_goal_safe(goal, next, quota) \
84091f21216SSeongJae Park 	list_for_each_entry_safe(goal, next, &(quota)->goals, list)
84191f21216SSeongJae Park 
84298def236SSeongJae Park #define damos_for_each_filter(f, scheme) \
84398def236SSeongJae Park 	list_for_each_entry(f, &(scheme)->filters, list)
84498def236SSeongJae Park 
84598def236SSeongJae Park #define damos_for_each_filter_safe(f, next, scheme) \
84698def236SSeongJae Park 	list_for_each_entry_safe(f, next, &(scheme)->filters, list)
84798def236SSeongJae Park 
848ab82e579SSeongJae Park #define damos_for_each_ops_filter(f, scheme) \
849ab82e579SSeongJae Park 	list_for_each_entry(f, &(scheme)->ops_filters, list)
850ab82e579SSeongJae Park 
851ab82e579SSeongJae Park #define damos_for_each_ops_filter_safe(f, next, scheme) \
852ab82e579SSeongJae Park 	list_for_each_entry_safe(f, next, &(scheme)->ops_filters, list)
853ab82e579SSeongJae Park 
8542224d848SSeongJae Park #ifdef CONFIG_DAMON
8552224d848SSeongJae Park 
856f23b8eeeSSeongJae Park struct damon_region *damon_new_region(unsigned long start, unsigned long end);
8572cd4b8e1SGuoqing Jiang 
8582cd4b8e1SGuoqing Jiang /*
8592cd4b8e1SGuoqing Jiang  * Add a region between two other regions
8602cd4b8e1SGuoqing Jiang  */
damon_insert_region(struct damon_region * r,struct damon_region * prev,struct damon_region * next,struct damon_target * t)8612cd4b8e1SGuoqing Jiang static inline void damon_insert_region(struct damon_region *r,
862b9a6ac4eSSeongJae Park 		struct damon_region *prev, struct damon_region *next,
8632cd4b8e1SGuoqing Jiang 		struct damon_target *t)
8642cd4b8e1SGuoqing Jiang {
8652cd4b8e1SGuoqing Jiang 	__list_add(&r->list, &prev->list, &next->list);
8662cd4b8e1SGuoqing Jiang 	t->nr_regions++;
8672cd4b8e1SGuoqing Jiang }
8682cd4b8e1SGuoqing Jiang 
869f23b8eeeSSeongJae Park void damon_add_region(struct damon_region *r, struct damon_target *t);
870b9a6ac4eSSeongJae Park void damon_destroy_region(struct damon_region *r, struct damon_target *t);
871d0723bc0SSeongJae Park int damon_set_regions(struct damon_target *t, struct damon_addr_range *ranges,
872d0723bc0SSeongJae Park 		unsigned int nr_ranges);
873ace30fb2SSeongJae Park void damon_update_region_access_rate(struct damon_region *r, bool accessed,
874ace30fb2SSeongJae Park 		struct damon_attrs *attrs);
875f23b8eeeSSeongJae Park 
87698def236SSeongJae Park struct damos_filter *damos_new_filter(enum damos_filter_type type,
877e2fbfedaSSeongJae Park 		bool matching, bool allow);
87898def236SSeongJae Park void damos_add_filter(struct damos *s, struct damos_filter *f);
879f7f0d88bSSeongJae Park bool damos_filter_for_ops(enum damos_filter_type type);
88098def236SSeongJae Park void damos_destroy_filter(struct damos_filter *f);
88198def236SSeongJae Park 
88291f21216SSeongJae Park struct damos_quota_goal *damos_new_quota_goal(
883bcce9bc1SSeongJae Park 		enum damos_quota_goal_metric metric,
884bcce9bc1SSeongJae Park 		unsigned long target_value);
88591f21216SSeongJae Park void damos_add_quota_goal(struct damos_quota *q, struct damos_quota_goal *g);
88691f21216SSeongJae Park void damos_destroy_quota_goal(struct damos_quota_goal *goal);
88791f21216SSeongJae Park 
888f5a79d7cSYajun Deng struct damos *damon_new_scheme(struct damos_access_pattern *pattern,
88942f994b7SSeongJae Park 			enum damos_action action,
89042f994b7SSeongJae Park 			unsigned long apply_interval_us,
89142f994b7SSeongJae Park 			struct damos_quota *quota,
892e36287c6SHyeongtak Ji 			struct damos_watermarks *wmarks,
893e36287c6SHyeongtak Ji 			int target_nid);
8941f366e42SSeongJae Park void damon_add_scheme(struct damon_ctx *ctx, struct damos *s);
8951f366e42SSeongJae Park void damon_destroy_scheme(struct damos *s);
8963ad1dce6SSeongJae Park int damos_commit_quota_goals(struct damos_quota *dst, struct damos_quota *src);
8971f366e42SSeongJae Park 
8981971bd63SSeongJae Park struct damon_target *damon_new_target(void);
899f23b8eeeSSeongJae Park void damon_add_target(struct damon_ctx *ctx, struct damon_target *t);
900b5ca3e83SXin Hao bool damon_targets_empty(struct damon_ctx *ctx);
901f23b8eeeSSeongJae Park void damon_free_target(struct damon_target *t);
902f23b8eeeSSeongJae Park void damon_destroy_target(struct damon_target *t);
903b9a6ac4eSSeongJae Park unsigned int damon_nr_regions(struct damon_target *t);
904f23b8eeeSSeongJae Park 
9052224d848SSeongJae Park struct damon_ctx *damon_new_ctx(void);
9062224d848SSeongJae Park void damon_destroy_ctx(struct damon_ctx *ctx);
907bead3b00SSeongJae Park int damon_set_attrs(struct damon_ctx *ctx, struct damon_attrs *attrs);
908cc713520SKaixu Xia void damon_set_schemes(struct damon_ctx *ctx,
9091f366e42SSeongJae Park 			struct damos **schemes, ssize_t nr_schemes);
9109cb3d0b9SSeongJae Park int damon_commit_ctx(struct damon_ctx *old_ctx, struct damon_ctx *new_ctx);
9114bc05954SSeongJae Park int damon_nr_running_ctxs(void);
912152e5617SSeongJae Park bool damon_is_registered_ops(enum damon_ops_id id);
9139f7b053aSSeongJae Park int damon_register_ops(struct damon_operations *ops);
9149f7b053aSSeongJae Park int damon_select_ops(struct damon_ctx *ctx, enum damon_ops_id id);
9152224d848SSeongJae Park 
damon_target_has_pid(const struct damon_ctx * ctx)916c9e124e0SSeongJae Park static inline bool damon_target_has_pid(const struct damon_ctx *ctx)
917c9e124e0SSeongJae Park {
918c9e124e0SSeongJae Park 	return ctx->ops.id == DAMON_OPS_VADDR || ctx->ops.id == DAMON_OPS_FVADDR;
919c9e124e0SSeongJae Park }
920c9e124e0SSeongJae Park 
damon_max_nr_accesses(const struct damon_attrs * attrs)92135f5d941SSeongJae Park static inline unsigned int damon_max_nr_accesses(const struct damon_attrs *attrs)
92235f5d941SSeongJae Park {
92335f5d941SSeongJae Park 	/* {aggr,sample}_interval are unsigned long, hence could overflow */
92435f5d941SSeongJae Park 	return min(attrs->aggr_interval / attrs->sample_interval,
92535f5d941SSeongJae Park 			(unsigned long)UINT_MAX);
92635f5d941SSeongJae Park }
92735f5d941SSeongJae Park 
928c9e124e0SSeongJae Park 
9298b9b0d33SSeongJae Park int damon_start(struct damon_ctx **ctxs, int nr_ctxs, bool exclusive);
9302224d848SSeongJae Park int damon_stop(struct damon_ctx **ctxs, int nr_ctxs);
9312224d848SSeongJae Park 
93242b7491aSSeongJae Park int damon_call(struct damon_ctx *ctx, struct damon_call_control *control);
933bf0eaba0SSeongJae Park int damos_walk(struct damon_ctx *ctx, struct damos_walk_control *control);
93442b7491aSSeongJae Park 
935233f0b31SKaixu Xia int damon_set_region_biggest_system_ram_default(struct damon_target *t,
936233f0b31SKaixu Xia 				unsigned long *start, unsigned long *end);
9370d83b2d8SXin Hao 
9382224d848SSeongJae Park #endif	/* CONFIG_DAMON */
9392224d848SSeongJae Park 
9402224d848SSeongJae Park #endif	/* _DAMON_H */
941