• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * QEMU System Emulator
3  *
4  * Copyright (c) 2003-2008 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "config-host.h"
25 
26 #include "cpu.h"
27 #include "monitor/monitor.h"
28 #include "sysemu/sysemu.h"
29 #include "cpu.h"
30 #include "exec/exec-all.h"
31 #include "exec/gdbstub.h"
32 #include "sysemu/dma.h"
33 #include "sysemu/kvm.h"
34 #include "exec/exec-all.h"
35 #include "exec/hax.h"
36 
37 #include "sysemu/cpus.h"
38 
39 static CPUState *cur_cpu;
40 static CPUState *next_cpu;
41 
42 /***********************************************************/
hw_error(const char * fmt,...)43 void hw_error(const char *fmt, ...)
44 {
45     va_list ap;
46     CPUState *cpu;
47 
48     va_start(ap, fmt);
49     fprintf(stderr, "qemu: hardware error: ");
50     vfprintf(stderr, fmt, ap);
51     fprintf(stderr, "\n");
52     CPU_FOREACH(cpu) {
53         fprintf(stderr, "CPU #%d:\n", cpu->cpu_index);
54 #ifdef TARGET_I386
55         cpu_dump_state(cpu->env_ptr, stderr, fprintf, X86_DUMP_FPU);
56 #else
57         cpu_dump_state(cpu->env_ptr, stderr, fprintf, 0);
58 #endif
59     }
60     va_end(ap);
61     abort();
62 }
63 
do_vm_stop(int reason)64 static void do_vm_stop(int reason)
65 {
66     if (vm_running) {
67         cpu_disable_ticks();
68         vm_running = 0;
69         pause_all_vcpus();
70         vm_state_notify(0, reason);
71     }
72 }
73 
cpu_can_run(CPUArchState * env)74 static int cpu_can_run(CPUArchState *env)
75 {
76     CPUState *cpu = ENV_GET_CPU(env);
77     if (cpu->stop)
78         return 0;
79     if (cpu->stopped)
80         return 0;
81     return 1;
82 }
83 
tcg_has_work(void)84 int tcg_has_work(void)
85 {
86     CPUState *cpu;
87 
88     CPU_FOREACH(cpu) {
89         if (cpu->stop)
90             return 1;
91         if (cpu->stopped)
92             return 0;
93         if (!cpu->halted)
94             return 1;
95         if (cpu_has_work(cpu))
96             return 1;
97         return 0;
98     }
99     return 0;
100 }
101 
qemu_init_vcpu(CPUState * cpu)102 void qemu_init_vcpu(CPUState *cpu)
103 {
104     if (kvm_enabled())
105         kvm_init_vcpu(cpu);
106 #ifdef CONFIG_HAX
107     if (hax_enabled())
108         hax_init_vcpu(cpu);
109 #endif
110     return;
111 }
112 
qemu_cpu_is_self(CPUState * cpu)113 bool qemu_cpu_is_self(CPUState *cpu)
114 {
115     return true;
116 }
117 
resume_all_vcpus(void)118 void resume_all_vcpus(void)
119 {
120 }
121 
pause_all_vcpus(void)122 void pause_all_vcpus(void)
123 {
124 }
125 
qemu_cpu_kick(CPUState * cpu)126 void qemu_cpu_kick(CPUState *cpu)
127 {
128     return;
129 }
130 
131 // In main-loop.c
132 #ifdef _WIN32
133 extern HANDLE qemu_event_handle;
134 #endif
135 
qemu_notify_event(void)136 void qemu_notify_event(void)
137 {
138     CPUState *cpu = current_cpu;
139 
140     if (cpu) {
141         cpu_exit(cpu);
142     /*
143      * This is mainly for the Windows host, where the timer may be in
144      * a different thread with vcpu. Thus the timer function needs to
145      * notify the vcpu thread of more than simply cpu_exit.  If env is
146      * not NULL, it means that the vcpu is in execute state, we need
147      * only to set the flags.  If the guest is in execute state, the
148      * HAX kernel module will exit to qemu.  If env is NULL, vcpu is
149      * in main_loop_wait, and we need a event to notify it.
150      */
151 #ifdef CONFIG_HAX
152         if (hax_enabled())
153             hax_raise_event(cpu);
154      } else {
155 #ifdef _WIN32
156          if(hax_enabled())
157              SetEvent(qemu_event_handle);
158 #endif
159      }
160 #else
161      }
162 #endif
163 }
164 
qemu_mutex_lock_iothread(void)165 void qemu_mutex_lock_iothread(void)
166 {
167 }
168 
qemu_mutex_unlock_iothread(void)169 void qemu_mutex_unlock_iothread(void)
170 {
171 }
172 
vm_stop(int reason)173 void vm_stop(int reason)
174 {
175     do_vm_stop(reason);
176 }
177 
qemu_cpu_exec(CPUOldState * env)178 static int qemu_cpu_exec(CPUOldState *env)
179 {
180     int ret;
181 
182 #ifdef CONFIG_PROFILER
183     int64_t ti = profile_getclock();
184 #endif
185 #ifndef CONFIG_ANDROID
186     if (use_icount) {
187         int64_t count;
188         int decr;
189         qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
190         env->icount_decr.u16.low = 0;
191         env->icount_extra = 0;
192         count = qemu_next_icount_deadline();
193         count = (count + (1 << icount_time_shift) - 1)
194                 >> icount_time_shift;
195         qemu_icount += count;
196         decr = (count > 0xffff) ? 0xffff : count;
197         count -= decr;
198         env->icount_decr.u16.low = decr;
199         env->icount_extra = count;
200     }
201 #endif
202     ret = cpu_exec(env);
203 #ifdef CONFIG_PROFILER
204     qemu_time += profile_getclock() - ti;
205 #endif
206 #ifndef CONFIG_ANDROID
207     if (use_icount) {
208         /* Fold pending instructions back into the
209            instruction counter, and clear the interrupt flag.  */
210         qemu_icount -= (env->icount_decr.u16.low
211                         + env->icount_extra);
212         env->icount_decr.u32 = 0;
213         env->icount_extra = 0;
214     }
215 #endif
216     return ret;
217 }
218 
tcg_cpu_exec(void)219 void tcg_cpu_exec(void)
220 {
221     int ret = 0;
222 
223     if (next_cpu == NULL)
224         next_cpu = QTAILQ_FIRST(&cpus);
225     for (; next_cpu != NULL; next_cpu = QTAILQ_NEXT(next_cpu, node)) {\
226         cur_cpu = next_cpu;
227         CPUOldState *env = cur_cpu->env_ptr;
228 
229         if (!vm_running)
230             break;
231         if (qemu_timer_alarm_pending()) {
232             break;
233         }
234         if (cpu_can_run(env))
235             ret = qemu_cpu_exec(env);
236         if (ret == EXCP_DEBUG) {
237             gdb_set_stop_cpu(cur_cpu);
238             debug_requested = 1;
239             break;
240         }
241     }
242 }
243 
244 /***********************************************************/
245 /* guest cycle counter */
246 
247 typedef struct TimersState {
248     int64_t cpu_ticks_prev;
249     int64_t cpu_ticks_offset;
250     int64_t cpu_clock_offset;
251     int32_t cpu_ticks_enabled;
252     int64_t dummy;
253 } TimersState;
254 
timer_save(QEMUFile * f,void * opaque)255 static void timer_save(QEMUFile *f, void *opaque)
256 {
257     TimersState *s = opaque;
258 
259     if (s->cpu_ticks_enabled) {
260         hw_error("cannot save state if virtual timers are running");
261     }
262     qemu_put_be64(f, s->cpu_ticks_prev);
263     qemu_put_be64(f, s->cpu_ticks_offset);
264     qemu_put_be64(f, s->cpu_clock_offset);
265  }
266 
timer_load(QEMUFile * f,void * opaque,int version_id)267 static int timer_load(QEMUFile *f, void *opaque, int version_id)
268 {
269     TimersState *s = opaque;
270 
271     if (version_id != 1 && version_id != 2)
272         return -EINVAL;
273     if (s->cpu_ticks_enabled) {
274         return -EINVAL;
275     }
276     s->cpu_ticks_prev   = qemu_get_sbe64(f);
277     s->cpu_ticks_offset = qemu_get_sbe64(f);
278     if (version_id == 2) {
279         s->cpu_clock_offset = qemu_get_sbe64(f);
280     }
281     return 0;
282 }
283 
284 
285 TimersState timers_state;
286 
qemu_timer_register_savevm(void)287 void qemu_timer_register_savevm(void) {
288     register_savevm(NULL,
289                     "timer",
290                     0,
291                     2,
292                     timer_save,
293                     timer_load,
294                     &timers_state);
295 }
296 
297 /* Return the virtual CPU time, based on the instruction counter.  */
cpu_get_icount(void)298 int64_t cpu_get_icount(void)
299 {
300     int64_t icount;
301     CPUOldState *env = cpu_single_env;;
302 
303     icount = qemu_icount;
304     if (env) {
305         if (!can_do_io(env)) {
306             fprintf(stderr, "Bad clock read\n");
307         }
308         icount -= (env->icount_decr.u16.low + env->icount_extra);
309     }
310     return qemu_icount_bias + (icount << icount_time_shift);
311 }
312 
313 /* return the host CPU cycle counter and handle stop/restart */
cpu_get_ticks(void)314 int64_t cpu_get_ticks(void)
315 {
316     if (use_icount) {
317         return cpu_get_icount();
318     }
319     if (!timers_state.cpu_ticks_enabled) {
320         return timers_state.cpu_ticks_offset;
321     } else {
322         int64_t ticks;
323         ticks = cpu_get_real_ticks();
324         if (timers_state.cpu_ticks_prev > ticks) {
325             /* Note: non increasing ticks may happen if the host uses
326                software suspend */
327             timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
328         }
329         timers_state.cpu_ticks_prev = ticks;
330         return ticks + timers_state.cpu_ticks_offset;
331     }
332 }
333 
334 /* return the host CPU monotonic timer and handle stop/restart */
cpu_get_clock(void)335 int64_t cpu_get_clock(void)
336 {
337     int64_t ti;
338     if (!timers_state.cpu_ticks_enabled) {
339         return timers_state.cpu_clock_offset;
340     } else {
341         ti = get_clock();
342         return ti + timers_state.cpu_clock_offset;
343     }
344 }
345 
346 /* enable cpu_get_ticks() */
cpu_enable_ticks(void)347 void cpu_enable_ticks(void)
348 {
349     if (!timers_state.cpu_ticks_enabled) {
350         timers_state.cpu_ticks_offset -= cpu_get_real_ticks();
351         timers_state.cpu_clock_offset -= get_clock();
352         timers_state.cpu_ticks_enabled = 1;
353     }
354 }
355 
356 /* disable cpu_get_ticks() : the clock is stopped. You must not call
357    cpu_get_ticks() after that.  */
cpu_disable_ticks(void)358 void cpu_disable_ticks(void)
359 {
360     if (timers_state.cpu_ticks_enabled) {
361         timers_state.cpu_ticks_offset = cpu_get_ticks();
362         timers_state.cpu_clock_offset = cpu_get_clock();
363         timers_state.cpu_ticks_enabled = 0;
364     }
365 }
366 
qemu_clock_warp(QEMUClockType clock)367 void qemu_clock_warp(QEMUClockType clock) {
368 }
369