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 Behnsenstatic inline void tmigr_handle_remote(void) { } tmigr_requires_handle_remote(void)1427ee98877SAnna-Maria Behnsenstatic inline bool tmigr_requires_handle_remote(void) { return false; } tmigr_cpu_activate(void)1437ee98877SAnna-Maria Behnsenstatic inline void tmigr_cpu_activate(void) { } 1447ee98877SAnna-Maria Behnsen #endif 1457ee98877SAnna-Maria Behnsen 1467ee98877SAnna-Maria Behnsen #endif 147