xref: /linux-6.15/kernel/time/timer_migration.h (revision 4477b060)
17ee98877SAnna-Maria Behnsen /* SPDX-License-Identifier: GPL-2.0-only */
27ee98877SAnna-Maria Behnsen #ifndef _KERNEL_TIME_MIGRATION_H
37ee98877SAnna-Maria Behnsen #define _KERNEL_TIME_MIGRATION_H
47ee98877SAnna-Maria Behnsen 
57ee98877SAnna-Maria Behnsen /* Per group capacity. Must be a power of 2! */
67ee98877SAnna-Maria Behnsen #define TMIGR_CHILDREN_PER_GROUP 8
77ee98877SAnna-Maria Behnsen 
87ee98877SAnna-Maria Behnsen /**
97ee98877SAnna-Maria Behnsen  * struct tmigr_event - a timer event associated to a CPU
107ee98877SAnna-Maria Behnsen  * @nextevt:	The node to enqueue an event in the parent group queue
117ee98877SAnna-Maria Behnsen  * @cpu:	The CPU to which this event belongs
127ee98877SAnna-Maria Behnsen  * @ignore:	Hint whether the event could be ignored; it is set when
137ee98877SAnna-Maria Behnsen  *		CPU or group is active;
147ee98877SAnna-Maria Behnsen  */
157ee98877SAnna-Maria Behnsen struct tmigr_event {
167ee98877SAnna-Maria Behnsen 	struct timerqueue_node	nextevt;
177ee98877SAnna-Maria Behnsen 	unsigned int		cpu;
187ee98877SAnna-Maria Behnsen 	bool			ignore;
197ee98877SAnna-Maria Behnsen };
207ee98877SAnna-Maria Behnsen 
217ee98877SAnna-Maria Behnsen /**
227ee98877SAnna-Maria Behnsen  * struct tmigr_group - timer migration hierarchy group
237ee98877SAnna-Maria Behnsen  * @lock:		Lock protecting the event information and group hierarchy
247ee98877SAnna-Maria Behnsen  *			information during setup
25facd40aaSAnna-Maria Behnsen  * @parent:		Pointer to the parent group. Pointer is updated when a
26facd40aaSAnna-Maria Behnsen  *			new hierarchy level is added because of a CPU coming
27facd40aaSAnna-Maria Behnsen  *			online the first time. Once it is set, the pointer will
28facd40aaSAnna-Maria Behnsen  *			not be removed or updated. When accessing parent pointer
29facd40aaSAnna-Maria Behnsen  *			lock less to decide whether to abort a propagation or
30facd40aaSAnna-Maria Behnsen  *			not, it is not a problem. The worst outcome is an
31facd40aaSAnna-Maria Behnsen  *			unnecessary/early CPU wake up. But do not access parent
32facd40aaSAnna-Maria Behnsen  *			pointer several times in the same 'action' (like
33facd40aaSAnna-Maria Behnsen  *			activation, deactivation, check for remote expiry,...)
34facd40aaSAnna-Maria Behnsen  *			without holding the lock as it is not ensured that value
35facd40aaSAnna-Maria Behnsen  *			will not change.
367ee98877SAnna-Maria Behnsen  * @groupevt:		Next event of the group which is only used when the
377ee98877SAnna-Maria Behnsen  *			group is !active. The group event is then queued into
387ee98877SAnna-Maria Behnsen  *			the parent timer queue.
397ee98877SAnna-Maria Behnsen  *			Ignore bit of @groupevt is set when the group is active.
407ee98877SAnna-Maria Behnsen  * @next_expiry:	Base monotonic expiry time of the next event of the
417ee98877SAnna-Maria Behnsen  *			group; It is used for the racy lockless check whether a
427ee98877SAnna-Maria Behnsen  *			remote expiry is required; it is always reliable
437ee98877SAnna-Maria Behnsen  * @events:		Timer queue for child events queued in the group
447ee98877SAnna-Maria Behnsen  * @migr_state:		State of the group (see union tmigr_state)
457ee98877SAnna-Maria Behnsen  * @level:		Hierarchy level of the group; Required during setup
467ee98877SAnna-Maria Behnsen  * @numa_node:		Required for setup only to make sure CPU and low level
477ee98877SAnna-Maria Behnsen  *			group information is NUMA local. It is set to NUMA node
487ee98877SAnna-Maria Behnsen  *			as long as the group level is per NUMA node (level <
497ee98877SAnna-Maria Behnsen  *			tmigr_crossnode_level); otherwise it is set to
507ee98877SAnna-Maria Behnsen  *			NUMA_NO_NODE
517ee98877SAnna-Maria Behnsen  * @num_children:	Counter of group children to make sure the group is only
527ee98877SAnna-Maria Behnsen  *			filled with TMIGR_CHILDREN_PER_GROUP; Required for setup
537ee98877SAnna-Maria Behnsen  *			only
54835a9a67SAnna-Maria Behnsen  * @groupmask:		mask of the group in the parent group; is set during
55835a9a67SAnna-Maria Behnsen  *			setup and will never change; can be read lockless
567ee98877SAnna-Maria Behnsen  * @list:		List head that is added to the per level
577ee98877SAnna-Maria Behnsen  *			tmigr_level_list; is required during setup when a
587ee98877SAnna-Maria Behnsen  *			new group needs to be connected to the existing
597ee98877SAnna-Maria Behnsen  *			hierarchy groups
607ee98877SAnna-Maria Behnsen  */
617ee98877SAnna-Maria Behnsen struct tmigr_group {
627ee98877SAnna-Maria Behnsen 	raw_spinlock_t		lock;
637ee98877SAnna-Maria Behnsen 	struct tmigr_group	*parent;
647ee98877SAnna-Maria Behnsen 	struct tmigr_event	groupevt;
657ee98877SAnna-Maria Behnsen 	u64			next_expiry;
667ee98877SAnna-Maria Behnsen 	struct timerqueue_head	events;
677ee98877SAnna-Maria Behnsen 	atomic_t		migr_state;
687ee98877SAnna-Maria Behnsen 	unsigned int		level;
697ee98877SAnna-Maria Behnsen 	int			numa_node;
707ee98877SAnna-Maria Behnsen 	unsigned int		num_children;
71835a9a67SAnna-Maria Behnsen 	u8			groupmask;
727ee98877SAnna-Maria Behnsen 	struct list_head	list;
737ee98877SAnna-Maria Behnsen };
747ee98877SAnna-Maria Behnsen 
757ee98877SAnna-Maria Behnsen /**
767ee98877SAnna-Maria Behnsen  * struct tmigr_cpu - timer migration per CPU group
777ee98877SAnna-Maria Behnsen  * @lock:		Lock protecting the tmigr_cpu group information
787ee98877SAnna-Maria Behnsen  * @online:		Indicates whether the CPU is online; In deactivate path
797ee98877SAnna-Maria Behnsen  *			it is required to know whether the migrator in the top
807ee98877SAnna-Maria Behnsen  *			level group is to be set offline, while a timer is
817ee98877SAnna-Maria Behnsen  *			pending. Then another online CPU needs to be notified to
827ee98877SAnna-Maria Behnsen  *			take over the migrator role. Furthermore the information
837ee98877SAnna-Maria Behnsen  *			is required in CPU hotplug path as the CPU is able to go
847ee98877SAnna-Maria Behnsen  *			idle before the timer migration hierarchy hotplug AP is
857ee98877SAnna-Maria Behnsen  *			reached. During this phase, the CPU has to handle the
867ee98877SAnna-Maria Behnsen  *			global timers on its own and must not act as a migrator.
877ee98877SAnna-Maria Behnsen  * @idle:		Indicates whether the CPU is idle in the timer migration
887ee98877SAnna-Maria Behnsen  *			hierarchy
897ee98877SAnna-Maria Behnsen  * @remote:		Is set when timers of the CPU are expired remotely
907ee98877SAnna-Maria Behnsen  * @tmgroup:		Pointer to the parent group
91835a9a67SAnna-Maria Behnsen  * @groupmask:		mask of tmigr_cpu in the parent group
927ee98877SAnna-Maria Behnsen  * @wakeup:		Stores the first timer when the timer migration
937ee98877SAnna-Maria Behnsen  *			hierarchy is completely idle and remote expiry was done;
947ee98877SAnna-Maria Behnsen  *			is returned to timer code in the idle path and is only
957ee98877SAnna-Maria Behnsen  *			used in idle path.
967ee98877SAnna-Maria Behnsen  * @cpuevt:		CPU event which could be enqueued into the parent group
977ee98877SAnna-Maria Behnsen  */
987ee98877SAnna-Maria Behnsen struct tmigr_cpu {
997ee98877SAnna-Maria Behnsen 	raw_spinlock_t		lock;
1007ee98877SAnna-Maria Behnsen 	bool			online;
1017ee98877SAnna-Maria Behnsen 	bool			idle;
1027ee98877SAnna-Maria Behnsen 	bool			remote;
1037ee98877SAnna-Maria Behnsen 	struct tmigr_group	*tmgroup;
104835a9a67SAnna-Maria Behnsen 	u8			groupmask;
1057ee98877SAnna-Maria Behnsen 	u64			wakeup;
1067ee98877SAnna-Maria Behnsen 	struct tmigr_event	cpuevt;
1077ee98877SAnna-Maria Behnsen };
1087ee98877SAnna-Maria Behnsen 
1097ee98877SAnna-Maria Behnsen /**
1107ee98877SAnna-Maria Behnsen  * union tmigr_state - state of tmigr_group
1117ee98877SAnna-Maria Behnsen  * @state:	Combined version of the state - only used for atomic
1127ee98877SAnna-Maria Behnsen  *		read/cmpxchg function
113*4477b060SRandy Dunlap  * &anon struct: Split version of the state - only use the struct members to
1147ee98877SAnna-Maria Behnsen  *		update information to stay independent of endianness
115835a9a67SAnna-Maria Behnsen  * @active:	Contains each mask bit of the active children
116835a9a67SAnna-Maria Behnsen  * @migrator:	Contains mask of the child which is migrator
1177ee98877SAnna-Maria Behnsen  * @seq:	Sequence counter needs to be increased when an update
1187ee98877SAnna-Maria Behnsen  *		to the tmigr_state is done. It prevents a race when
1197ee98877SAnna-Maria Behnsen  *		updates in the child groups are propagated in changed
1207ee98877SAnna-Maria Behnsen  *		order. Detailed information about the scenario is
1217ee98877SAnna-Maria Behnsen  *		given in the documentation at the begin of
1227ee98877SAnna-Maria Behnsen  *		timer_migration.c.
1237ee98877SAnna-Maria Behnsen  */
124*4477b060SRandy Dunlap union tmigr_state {
125*4477b060SRandy Dunlap 	u32 state;
1267ee98877SAnna-Maria Behnsen 	struct {
1277ee98877SAnna-Maria Behnsen 		u8	active;
1287ee98877SAnna-Maria Behnsen 		u8	migrator;
1297ee98877SAnna-Maria Behnsen 		u16	seq;
1307ee98877SAnna-Maria Behnsen 	} __packed;
1317ee98877SAnna-Maria Behnsen };
1327ee98877SAnna-Maria Behnsen 
1337ee98877SAnna-Maria Behnsen #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
1347ee98877SAnna-Maria Behnsen extern void tmigr_handle_remote(void);
1357ee98877SAnna-Maria Behnsen extern bool tmigr_requires_handle_remote(void);
1367ee98877SAnna-Maria Behnsen extern void tmigr_cpu_activate(void);
1377ee98877SAnna-Maria Behnsen extern u64 tmigr_cpu_deactivate(u64 nextevt);
1387ee98877SAnna-Maria Behnsen extern u64 tmigr_cpu_new_timer(u64 nextevt);
1397ee98877SAnna-Maria Behnsen extern u64 tmigr_quick_check(u64 nextevt);
1407ee98877SAnna-Maria Behnsen #else
tmigr_handle_remote(void)1417ee98877SAnna-Maria Behnsen static inline void tmigr_handle_remote(void) { }
tmigr_requires_handle_remote(void)1427ee98877SAnna-Maria Behnsen static inline bool tmigr_requires_handle_remote(void) { return false; }
tmigr_cpu_activate(void)1437ee98877SAnna-Maria Behnsen static inline void tmigr_cpu_activate(void) { }
1447ee98877SAnna-Maria Behnsen #endif
1457ee98877SAnna-Maria Behnsen 
1467ee98877SAnna-Maria Behnsen #endif
147