1 /*
2  * Copyright (C) 2018-2022 Intel Corporation.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef SCHEDULE_H
8 #define SCHEDULE_H
9 #include <asm/lib/spinlock.h>
10 #include <lib/list.h>
11 #include <timer.h>
12 
13 #define	NEED_RESCHEDULE		(1U)
14 
15 #define DEL_MODE_INIT		(1U)
16 #define DEL_MODE_IPI		(2U)
17 
18 #define IDLE_MODE_PAUSE		(1U)
19 #define IDLE_MODE_HLT		(2U)
20 
21 #define THREAD_DATA_SIZE	(256U)
22 
23 enum thread_object_state {
24 	THREAD_STS_RUNNING = 1,
25 	THREAD_STS_RUNNABLE,
26 	THREAD_STS_BLOCKED
27 };
28 
29 /* Tools can configure a VM to use PRIO_LOW or PRIO_HIGH */
30 enum thread_priority {
31 	PRIO_IDLE = 0,
32 	PRIO_LOW,
33 	PRIO_HIGH,
34 	PRIO_MAX
35 };
36 
37 /*
38  * For now, we just have several parameters for all the schedulers. So we
39  * put them together here for simplicity. TODO When this structure grows big
40  * enough, we need to replace it with a union of parameters of different
41  * schedulers.
42  */
43 struct sched_params {
44 	uint32_t prio;		/* The priority of a thread */
45 
46 	/* per thread parameters for bvt scheduler */
47 	uint8_t bvt_weight;	/* the weight of a thread */
48 	int32_t bvt_warp_value; /* the warp reduce effective VT to boost priority */
49 	uint32_t bvt_warp_limit;	/* max time in one warp */
50 	uint32_t bvt_unwarp_period;	/* min unwarp time after a warp */
51 };
52 
53 struct thread_object;
54 typedef void (*thread_entry_t)(struct thread_object *obj);
55 typedef void (*switch_t)(struct thread_object *obj);
56 struct thread_object {
57 	char name[16];
58 	uint16_t pcpu_id;
59 	struct sched_control *sched_ctl;
60 	thread_entry_t thread_entry;
61 	volatile enum thread_object_state status;
62 	bool be_blocking;
63 
64 	uint64_t host_sp;
65 	switch_t switch_out;
66 	switch_t switch_in;
67 
68 	uint8_t data[THREAD_DATA_SIZE];
69 };
70 
71 struct sched_control {
72 	uint16_t pcpu_id;
73 	uint64_t flags;
74 	struct thread_object *curr_obj;
75 	spinlock_t scheduler_lock;	/* to protect sched_control and thread_object */
76 	struct acrn_scheduler *scheduler;
77 	void *priv;
78 };
79 
80 #define SCHEDULER_MAX_NUMBER 4U
81 struct acrn_scheduler {
82 	char name[16];
83 
84 	/* init scheduler */
85 	int32_t	(*init)(struct sched_control *ctl);
86 	/* init private data of scheduler */
87 	void	(*init_data)(struct thread_object *obj, struct sched_params *params);
88 	/* pick the next thread object */
89 	struct thread_object* (*pick_next)(struct sched_control *ctl);
90 	/* put thread object into sleep */
91 	void	(*sleep)(struct thread_object *obj);
92 	/* wake up thread object from sleep status */
93 	void	(*wake)(struct thread_object *obj);
94 	/* yield current thread object */
95 	void	(*yield)(struct sched_control *ctl);
96 	/* prioritize the thread object */
97 	void	(*prioritize)(struct thread_object *obj);
98 	/* deinit private data of scheduler */
99 	void	(*deinit_data)(struct thread_object *obj);
100 	/* deinit scheduler */
101 	void	(*deinit)(struct sched_control *ctl);
102 	/* suspend scheduler */
103 	void	(*suspend)(struct sched_control *ctl);
104 	/* resume scheduler */
105 	void	(*resume)(struct sched_control *ctl);
106 };
107 extern struct acrn_scheduler sched_noop;
108 extern struct acrn_scheduler sched_iorr;
109 
110 struct sched_noop_control {
111 	struct thread_object *noop_thread_obj;
112 };
113 
114 struct sched_iorr_control {
115 	struct list_head runqueue;
116 	struct hv_timer tick_timer;
117 };
118 
119 extern struct acrn_scheduler sched_bvt;
120 struct sched_bvt_control {
121 	struct list_head runqueue;
122 	struct hv_timer tick_timer;
123 	/* The minimum AVT of any runnable threads */
124 	int64_t svt;
125 };
126 
127 extern struct acrn_scheduler sched_prio;
128 struct sched_prio_control {
129 	struct list_head prio_queue;
130 };
131 
132 bool is_idle_thread(const struct thread_object *obj);
133 uint16_t sched_get_pcpuid(const struct thread_object *obj);
134 struct thread_object *sched_get_current(uint16_t pcpu_id);
135 
136 void init_sched(uint16_t pcpu_id);
137 void deinit_sched(uint16_t pcpu_id);
138 void suspend_sched(void);
139 void resume_sched(void);
140 void obtain_schedule_lock(uint16_t pcpu_id, uint64_t *rflag);
141 void release_schedule_lock(uint16_t pcpu_id, uint64_t rflag);
142 
143 void init_thread_data(struct thread_object *obj, struct sched_params *params);
144 void deinit_thread_data(struct thread_object *obj);
145 
146 void make_reschedule_request(uint16_t pcpu_id);
147 bool need_reschedule(uint16_t pcpu_id);
148 
149 void run_thread(struct thread_object *obj);
150 void sleep_thread(struct thread_object *obj);
151 void sleep_thread_sync(struct thread_object *obj);
152 void wake_thread(struct thread_object *obj);
153 void yield_current(void);
154 void schedule(void);
155 
156 void arch_switch_to(void *prev_sp, void *next_sp);
157 void run_idle_thread(void);
158 #endif /* SCHEDULE_H */
159 
160