blob: c4fbb62680039246575634407a618daf0778e8a9 [file] [log] [blame]
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +02001/*
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
David 'Digit' Turner9b3a4b02014-01-23 00:52:54 +010026#include "cpu.h"
27#include "exec/exec-all.h"
David 'Digit' Turner6af67652013-12-14 23:49:32 +010028#include "monitor/monitor.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010029#include "sysemu/sysemu.h"
David 'Digit' Turner0e051542014-01-23 02:41:42 +010030#include "exec/exec-all.h"
David 'Digit' Turner852088c2013-12-14 23:04:12 +010031#include "exec/gdbstub.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010032#include "sysemu/dma.h"
33#include "sysemu/kvm.h"
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +010034#include "exec/exec-all.h"
David 'Digit' Turnere1e03df2013-12-15 00:42:21 +010035#include "exec/hax.h"
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020036
David 'Digit' Turner11822842013-12-17 09:16:47 +010037#include "sysemu/cpus.h"
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020038
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010039static CPUOldState *cur_cpu;
40static CPUOldState *next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020041
42/***********************************************************/
43void hw_error(const char *fmt, ...)
44{
45 va_list ap;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010046 CPUOldState *env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020047
48 va_start(ap, fmt);
49 fprintf(stderr, "qemu: hardware error: ");
50 vfprintf(stderr, fmt, ap);
51 fprintf(stderr, "\n");
52 for(env = first_cpu; env != NULL; env = env->next_cpu) {
53 fprintf(stderr, "CPU #%d:\n", env->cpu_index);
54#ifdef TARGET_I386
55 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU);
56#else
57 cpu_dump_state(env, stderr, fprintf, 0);
58#endif
59 }
60 va_end(ap);
61 abort();
62}
63
64static 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
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010074static int cpu_can_run(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020075{
76 if (env->stop)
77 return 0;
78 if (env->stopped)
79 return 0;
80 return 1;
81}
82
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010083static int cpu_has_work(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020084{
85 if (env->stop)
86 return 1;
87 if (env->stopped)
88 return 0;
89 if (!env->halted)
90 return 1;
91 if (qemu_cpu_has_work(env))
92 return 1;
93 return 0;
94}
95
96int tcg_has_work(void)
97{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010098 CPUOldState *env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020099
100 for (env = first_cpu; env != NULL; env = env->next_cpu)
101 if (cpu_has_work(env))
102 return 1;
103 return 0;
104}
105
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200106void qemu_init_vcpu(void *_env)
107{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100108 CPUOldState *env = _env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200109
110 if (kvm_enabled())
111 kvm_init_vcpu(env);
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800112#ifdef CONFIG_HAX
113 if (hax_enabled())
114 hax_init_vcpu(env);
115#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200116 return;
117}
118
119int qemu_cpu_self(void *env)
120{
121 return 1;
122}
123
124void resume_all_vcpus(void)
125{
126}
127
128void pause_all_vcpus(void)
129{
130}
131
132void qemu_cpu_kick(void *env)
133{
134 return;
135}
136
David 'Digit' Turnerf9077a82014-02-10 23:10:47 +0100137// In main-loop.c
138#ifdef _WIN32
139extern HANDLE qemu_event_handle;
140#endif
141
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200142void qemu_notify_event(void)
143{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100144 CPUOldState *env = cpu_single_env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200145
146 if (env) {
147 cpu_exit(env);
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800148 /*
149 * This is mainly for the Windows host, where the timer may be in
150 * a different thread with vcpu. Thus the timer function needs to
151 * notify the vcpu thread of more than simply cpu_exit. If env is
152 * not NULL, it means that the vcpu is in execute state, we need
153 * only to set the flags. If the guest is in execute state, the
154 * HAX kernel module will exit to qemu. If env is NULL, vcpu is
155 * in main_loop_wait, and we need a event to notify it.
156 */
157#ifdef CONFIG_HAX
158 if (hax_enabled())
159 hax_raise_event(env);
160 } else {
161#ifdef _WIN32
162 if(hax_enabled())
163 SetEvent(qemu_event_handle);
164#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200165 }
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800166#else
167 }
168#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200169}
170
171void qemu_mutex_lock_iothread(void)
172{
173}
174
175void qemu_mutex_unlock_iothread(void)
176{
177}
178
179void vm_stop(int reason)
180{
181 do_vm_stop(reason);
182}
183
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100184static int qemu_cpu_exec(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200185{
186 int ret;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200187
188#ifdef CONFIG_PROFILER
David 'Digit' Turnerf9077a82014-02-10 23:10:47 +0100189 int64_t ti = profile_getclock();
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200190#endif
191 if (use_icount) {
192 int64_t count;
193 int decr;
194 qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
195 env->icount_decr.u16.low = 0;
196 env->icount_extra = 0;
197 count = qemu_next_icount_deadline();
198 count = (count + (1 << icount_time_shift) - 1)
199 >> icount_time_shift;
200 qemu_icount += count;
201 decr = (count > 0xffff) ? 0xffff : count;
202 count -= decr;
203 env->icount_decr.u16.low = decr;
204 env->icount_extra = count;
205 }
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200206
207 ret = cpu_exec(env);
208#ifdef CONFIG_PROFILER
209 qemu_time += profile_getclock() - ti;
210#endif
211 if (use_icount) {
212 /* Fold pending instructions back into the
213 instruction counter, and clear the interrupt flag. */
214 qemu_icount -= (env->icount_decr.u16.low
215 + env->icount_extra);
216 env->icount_decr.u32 = 0;
217 env->icount_extra = 0;
218 }
219 return ret;
220}
221
222void tcg_cpu_exec(void)
223{
224 int ret = 0;
225
226 if (next_cpu == NULL)
227 next_cpu = first_cpu;
228 for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100229 CPUOldState *env = cur_cpu = next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200230
231 if (!vm_running)
232 break;
233 if (qemu_timer_alarm_pending()) {
234 break;
235 }
236 if (cpu_can_run(env))
237 ret = qemu_cpu_exec(env);
238 if (ret == EXCP_DEBUG) {
239 gdb_set_stop_cpu(env);
240 debug_requested = 1;
241 break;
242 }
243 }
244}
245
David 'Digit' Turnerf0183552014-02-16 14:20:45 +0100246/***********************************************************/
247/* guest cycle counter */
248
249typedef struct TimersState {
250 int64_t cpu_ticks_prev;
251 int64_t cpu_ticks_offset;
252 int64_t cpu_clock_offset;
253 int32_t cpu_ticks_enabled;
254 int64_t dummy;
255} TimersState;
256
257static void timer_save(QEMUFile *f, void *opaque)
258{
259 TimersState *s = opaque;
260
261 if (s->cpu_ticks_enabled) {
262 hw_error("cannot save state if virtual timers are running");
263 }
264 qemu_put_be64(f, s->cpu_ticks_prev);
265 qemu_put_be64(f, s->cpu_ticks_offset);
266 qemu_put_be64(f, s->cpu_clock_offset);
267 }
268
269static int timer_load(QEMUFile *f, void *opaque, int version_id)
270{
271 TimersState *s = opaque;
272
273 if (version_id != 1 && version_id != 2)
274 return -EINVAL;
275 if (s->cpu_ticks_enabled) {
276 return -EINVAL;
277 }
278 s->cpu_ticks_prev = qemu_get_sbe64(f);
279 s->cpu_ticks_offset = qemu_get_sbe64(f);
280 if (version_id == 2) {
281 s->cpu_clock_offset = qemu_get_sbe64(f);
282 }
283 return 0;
284}
285
286
287TimersState timers_state;
288
289void qemu_timer_register_savevm(void) {
290 register_savevm("timer", 0, 2, timer_save, timer_load, &timers_state);
291}
292
David 'Digit' Turner9b3a4b02014-01-23 00:52:54 +0100293/* Return the virtual CPU time, based on the instruction counter. */
294int64_t cpu_get_icount(void)
295{
296 int64_t icount;
297 CPUOldState *env = cpu_single_env;;
298
299 icount = qemu_icount;
300 if (env) {
301 if (!can_do_io(env)) {
302 fprintf(stderr, "Bad clock read\n");
303 }
304 icount -= (env->icount_decr.u16.low + env->icount_extra);
305 }
306 return qemu_icount_bias + (icount << icount_time_shift);
307}
David 'Digit' Turnerf0183552014-02-16 14:20:45 +0100308
309/* return the host CPU cycle counter and handle stop/restart */
310int64_t cpu_get_ticks(void)
311{
312 if (use_icount) {
313 return cpu_get_icount();
314 }
315 if (!timers_state.cpu_ticks_enabled) {
316 return timers_state.cpu_ticks_offset;
317 } else {
318 int64_t ticks;
319 ticks = cpu_get_real_ticks();
320 if (timers_state.cpu_ticks_prev > ticks) {
321 /* Note: non increasing ticks may happen if the host uses
322 software suspend */
323 timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
324 }
325 timers_state.cpu_ticks_prev = ticks;
326 return ticks + timers_state.cpu_ticks_offset;
327 }
328}
329
330/* return the host CPU monotonic timer and handle stop/restart */
331int64_t cpu_get_clock(void)
332{
333 int64_t ti;
334 if (!timers_state.cpu_ticks_enabled) {
335 return timers_state.cpu_clock_offset;
336 } else {
337 ti = get_clock();
338 return ti + timers_state.cpu_clock_offset;
339 }
340}
341
342/* enable cpu_get_ticks() */
343void cpu_enable_ticks(void)
344{
345 if (!timers_state.cpu_ticks_enabled) {
346 timers_state.cpu_ticks_offset -= cpu_get_real_ticks();
347 timers_state.cpu_clock_offset -= get_clock();
348 timers_state.cpu_ticks_enabled = 1;
349 }
350}
351
352/* disable cpu_get_ticks() : the clock is stopped. You must not call
353 cpu_get_ticks() after that. */
354void cpu_disable_ticks(void)
355{
356 if (timers_state.cpu_ticks_enabled) {
357 timers_state.cpu_ticks_offset = cpu_get_ticks();
358 timers_state.cpu_clock_offset = cpu_get_clock();
359 timers_state.cpu_ticks_enabled = 0;
360 }
361}