Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Update of scheduling infrastructure and newest version of EDF scheduler
[palacios.git] / palacios / src / palacios / vmm_scheduler.c
1 /* \r
2  * This file is part of the Palacios Virtual Machine Monitor developed\r
3  * by the V3VEE Project with funding from the United States National \r
4  * Science Foundation and the Department of Energy.  \r
5  *\r
6  * The V3VEE Project is a joint project between Northwestern University\r
7  * and the University of New Mexico.  You can find out more at \r
8  * http://www.v3vee.org\r
9  *\r
10  * Copyright (c) 2013, Oscar Mondragon <omondrag@cs.unm.edu> \r
11  * Copyright (c) 2013, Patrick G. Bridges <bridges@cs.unm.edu>\r
12  * Copyright (c) 2013, The V3VEE Project <http://www.v3vee.org> \r
13  * All rights reserved.\r
14  *\r
15  * Author: Oscar Mondragon <omondrag@cs.unm.edu>\r
16  *         Patrick G. Bridges <bridges@cs.unm.edu>\r
17  *\r
18  * This is free software.  You are permitted to use,\r
19  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".\r
20  */\r
21 \r
22 #include <palacios/vmm.h>\r
23 #include <palacios/vm_guest.h>\r
24 #include <palacios/vmm_scheduler.h>\r
25 #include <palacios/vmm_hashtable.h>\r
26 \r
27 #ifndef V3_CONFIG_DEBUG_SCHEDULER\r
28 #undef PrintDebug\r
29 #define PrintDebug(fmt, args...)\r
30 #endif\r
31 \r
32 static char default_strategy[] = "host";\r
33 static struct hashtable * master_scheduler_table = NULL;\r
34 static int create_host_scheduler();\r
35 \r
36 static struct vm_scheduler_impl *scheduler = NULL;\r
37 \r
38 static uint_t scheduler_hash_fn(addr_t key) {\r
39     char * name = (char *)key;\r
40     return v3_hash_buffer((uint8_t *)name, strlen(name));\r
41 }\r
42 \r
43 static int scheduler_eq_fn(addr_t key1, addr_t key2) {\r
44     char * name1 = (char *)key1;\r
45     char * name2 = (char *)key2;\r
46 \r
47     return (strcmp(name1, name2) == 0);\r
48 }\r
49 \r
50 int V3_init_scheduling() {\r
51    \r
52      PrintDebug(VM_NONE, VCORE_NONE,"Initializing scheduler");\r
53 \r
54     master_scheduler_table = v3_create_htable(0, scheduler_hash_fn, scheduler_eq_fn);\r
55     return create_host_scheduler();\r
56 }\r
57 \r
58 \r
59 int v3_register_scheduler(struct vm_scheduler_impl *s) {\r
60 \r
61     PrintDebug(VM_NONE, VCORE_NONE,"Registering Scheduler (%s)\n", s->name);\r
62 \r
63     if (v3_htable_search(master_scheduler_table, (addr_t)(s->name))) {\r
64         PrintError(VM_NONE, VCORE_NONE, "Multiple instances of scheduler (%s)\n", s->name);\r
65         return -1;\r
66     }\r
67   \r
68     if (v3_htable_insert(master_scheduler_table,\r
69                          (addr_t)(s->name),\r
70                          (addr_t)(s)) == 0) {\r
71         PrintError(VM_NONE, VCORE_NONE, "Could not register scheduler (%s)\n", s->name);\r
72         return -1;\r
73     }\r
74 \r
75     return 0;\r
76 }\r
77 \r
78 struct vm_scheduler_impl *v3_scheduler_lookup(char *name)\r
79 {\r
80     return (struct vm_scheduler_impl *)v3_htable_search(master_scheduler_table, (addr_t)(name));\r
81 }\r
82 \r
83 int V3_enable_scheduler() {\r
84     /* XXX Lookup the specified scheduler to use for palacios and use it */\r
85     \r
86     scheduler = v3_scheduler_lookup(default_strategy);\r
87     PrintDebug(VM_NONE, VCORE_NONE,"Sched. Scheduler %s found",scheduler->name);\r
88     \r
89     if (!scheduler) {\r
90         PrintError(VM_NONE, VCORE_NONE,"Specified Palacios scheduler \"%s\" not found.\n", default_strategy);\r
91         return -1;\r
92     }\r
93     if (scheduler->init) {\r
94         return scheduler->init();\r
95     } else {\r
96         return 0;\r
97     }\r
98 }\r
99 \r
100 int v3_scheduler_register_vm(struct v3_vm_info *vm) {\r
101     if (scheduler->vm_init) {\r
102         return scheduler->vm_init(vm);\r
103     } else {\r
104         return 0;\r
105     }\r
106 }\r
107 int v3_scheduler_register_core(struct guest_info *core) {\r
108     if (scheduler->core_init) {\r
109         return scheduler->core_init(core);\r
110     } else {\r
111         return 0;\r
112     }\r
113 }\r
114 int v3_scheduler_admit_vm(struct v3_vm_info *vm) {\r
115     if (scheduler->admit) {\r
116         return scheduler->admit(vm);\r
117     } else {\r
118         return 0;\r
119     }\r
120 }\r
121 int v3_scheduler_notify_remap(struct v3_vm_info *vm) {\r
122     if (scheduler->remap) {\r
123         return scheduler->remap(vm);\r
124     } else {\r
125         return 0;\r
126     }\r
127 }\r
128 int v3_scheduler_notify_dvfs(struct v3_vm_info *vm) {\r
129     if (scheduler->dvfs) {\r
130         return scheduler->dvfs(vm);\r
131     } else {\r
132         return 0;\r
133     }\r
134 }\r
135 void v3_schedule(struct guest_info *core) {\r
136     if (scheduler->schedule) {\r
137         scheduler->schedule(core);\r
138     }\r
139     return;\r
140 }\r
141 void v3_yield(struct guest_info *core, int usec) {\r
142     if (scheduler->yield) {\r
143         scheduler->yield(core, usec);\r
144     } \r
145     return;\r
146 }\r
147 \r
148 int host_sched_vm_init(struct v3_vm_info *vm)\r
149 {\r
150 \r
151     PrintDebug(vm, VCORE_NONE,"Sched. host_sched_init\n"); \r
152 \r
153     char * schedule_hz_str = v3_cfg_val(vm->cfg_data->cfg, "schedule_hz");\r
154     uint32_t sched_hz = 100;    \r
155 \r
156 \r
157     if (schedule_hz_str) {\r
158         sched_hz = atoi(schedule_hz_str);\r
159     }\r
160 \r
161     PrintDebug(vm, VCORE_NONE,"CPU_KHZ = %d, schedule_freq=%p\n", V3_CPU_KHZ(), \r
162                (void *)(addr_t)sched_hz);\r
163 \r
164     uint64_t yield_cycle_period = (V3_CPU_KHZ() * 1000) / sched_hz;\r
165     vm->sched_priv_data = (void *)yield_cycle_period; \r
166 \r
167     return 0;\r
168 }\r
169 \r
170 int host_sched_core_init(struct guest_info *core)\r
171 {\r
172     PrintDebug(core->vm_info, core,"Sched. host_sched_core_init\n"); \r
173 \r
174     uint64_t t = v3_get_host_time(&core->time_state); \r
175     core->sched_priv_data = (void *)t;\r
176 \r
177     return 0;\r
178 }\r
179 \r
180 void host_sched_schedule(struct guest_info *core)\r
181 {\r
182     uint64_t cur_cycle;\r
183     cur_cycle = v3_get_host_time(&core->time_state);\r
184 \r
185     if (cur_cycle > ( (uint64_t)core->sched_priv_data + (uint64_t)core->vm_info->sched_priv_data)) {\r
186         \r
187         V3_Yield();\r
188       \r
189         uint64_t yield_start_cycle = (uint64_t) core->sched_priv_data;\r
190         yield_start_cycle +=  (uint64_t)core->vm_info->sched_priv_data;\r
191         core->sched_priv_data = (void *)yield_start_cycle;\r
192       \r
193     }\r
194 }\r
195 \r
196 /* \r
197  * unconditional cpu yield \r
198  * if the yielding thread is a guest context, the guest quantum is reset on resumption \r
199  * Non guest context threads should call this function with a NULL argument\r
200  *\r
201  * usec <0  => the non-timed yield is used\r
202  * usec >=0 => the timed yield is used, which also usually implies interruptible\r
203  */\r
204 void host_sched_yield(struct guest_info * core, int usec) {\r
205     uint64_t yield_start_cycle;\r
206     if (usec < 0) {\r
207         V3_Yield();\r
208     } else {\r
209         V3_Sleep(usec);\r
210     }\r
211     yield_start_cycle = (uint64_t) core->sched_priv_data\r
212                         + (uint64_t)core->vm_info->sched_priv_data;\r
213     core->sched_priv_data = (void *)yield_start_cycle;\r
214 }\r
215 \r
216 \r
217 int host_sched_admit(struct v3_vm_info *vm){\r
218     return 0;\r
219 }\r
220 \r
221 static struct vm_scheduler_impl host_sched_impl = {\r
222     .name = "host",\r
223     .init = NULL,\r
224     .deinit = NULL,\r
225     .vm_init = host_sched_vm_init,\r
226     .vm_deinit = NULL,\r
227     .core_init = host_sched_core_init,\r
228     .core_deinit = NULL,\r
229     .schedule = host_sched_schedule,\r
230     .yield = host_sched_yield,\r
231     .admit = host_sched_admit,\r
232     .remap = NULL,\r
233     .dvfs=NULL\r
234 };\r
235 \r
236 static int create_host_scheduler()\r
237 {\r
238         v3_register_scheduler(&host_sched_impl);\r
239         return 0;\r
240 }\r