blob: 795ea380cd60fd88f4a22940c3c795764335048e [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
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100191#ifndef CONFIG_ANDROID
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200192 if (use_icount) {
193 int64_t count;
194 int decr;
195 qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
196 env->icount_decr.u16.low = 0;
197 env->icount_extra = 0;
198 count = qemu_next_icount_deadline();
199 count = (count + (1 << icount_time_shift) - 1)
200 >> icount_time_shift;
201 qemu_icount += count;
202 decr = (count > 0xffff) ? 0xffff : count;
203 count -= decr;
204 env->icount_decr.u16.low = decr;
205 env->icount_extra = count;
206 }
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100207#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200208 ret = cpu_exec(env);
209#ifdef CONFIG_PROFILER
210 qemu_time += profile_getclock() - ti;
211#endif
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100212#ifndef CONFIG_ANDROID
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200213 if (use_icount) {
214 /* Fold pending instructions back into the
215 instruction counter, and clear the interrupt flag. */
216 qemu_icount -= (env->icount_decr.u16.low
217 + env->icount_extra);
218 env->icount_decr.u32 = 0;
219 env->icount_extra = 0;
220 }
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100221#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200222 return ret;
223}
224
225void tcg_cpu_exec(void)
226{
227 int ret = 0;
228
229 if (next_cpu == NULL)
230 next_cpu = first_cpu;
231 for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100232 CPUOldState *env = cur_cpu = next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200233
234 if (!vm_running)
235 break;
236 if (qemu_timer_alarm_pending()) {
237 break;
238 }
239 if (cpu_can_run(env))
240 ret = qemu_cpu_exec(env);
241 if (ret == EXCP_DEBUG) {
242 gdb_set_stop_cpu(env);
243 debug_requested = 1;
244 break;
245 }
246 }
247}
248
David 'Digit' Turnerf0183552014-02-16 14:20:45 +0100249/***********************************************************/
250/* guest cycle counter */
251
252typedef struct TimersState {
253 int64_t cpu_ticks_prev;
254 int64_t cpu_ticks_offset;
255 int64_t cpu_clock_offset;
256 int32_t cpu_ticks_enabled;
257 int64_t dummy;
258} TimersState;
259
260static void timer_save(QEMUFile *f, void *opaque)
261{
262 TimersState *s = opaque;
263
264 if (s->cpu_ticks_enabled) {
265 hw_error("cannot save state if virtual timers are running");
266 }
267 qemu_put_be64(f, s->cpu_ticks_prev);
268 qemu_put_be64(f, s->cpu_ticks_offset);
269 qemu_put_be64(f, s->cpu_clock_offset);
270 }
271
272static int timer_load(QEMUFile *f, void *opaque, int version_id)
273{
274 TimersState *s = opaque;
275
276 if (version_id != 1 && version_id != 2)
277 return -EINVAL;
278 if (s->cpu_ticks_enabled) {
279 return -EINVAL;
280 }
281 s->cpu_ticks_prev = qemu_get_sbe64(f);
282 s->cpu_ticks_offset = qemu_get_sbe64(f);
283 if (version_id == 2) {
284 s->cpu_clock_offset = qemu_get_sbe64(f);
285 }
286 return 0;
287}
288
289
290TimersState timers_state;
291
292void qemu_timer_register_savevm(void) {
David 'Digit' Turner5cb5c0b2014-02-17 16:04:03 +0100293 register_savevm(NULL,
294 "timer",
295 0,
296 2,
297 timer_save,
298 timer_load,
299 &timers_state);
David 'Digit' Turnerf0183552014-02-16 14:20:45 +0100300}
301
David 'Digit' Turner9b3a4b02014-01-23 00:52:54 +0100302/* Return the virtual CPU time, based on the instruction counter. */
303int64_t cpu_get_icount(void)
304{
305 int64_t icount;
306 CPUOldState *env = cpu_single_env;;
307
308 icount = qemu_icount;
309 if (env) {
310 if (!can_do_io(env)) {
311 fprintf(stderr, "Bad clock read\n");
312 }
313 icount -= (env->icount_decr.u16.low + env->icount_extra);
314 }
315 return qemu_icount_bias + (icount << icount_time_shift);
316}
David 'Digit' Turnerf0183552014-02-16 14:20:45 +0100317
318/* return the host CPU cycle counter and handle stop/restart */
319int64_t cpu_get_ticks(void)
320{
321 if (use_icount) {
322 return cpu_get_icount();
323 }
324 if (!timers_state.cpu_ticks_enabled) {
325 return timers_state.cpu_ticks_offset;
326 } else {
327 int64_t ticks;
328 ticks = cpu_get_real_ticks();
329 if (timers_state.cpu_ticks_prev > ticks) {
330 /* Note: non increasing ticks may happen if the host uses
331 software suspend */
332 timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
333 }
334 timers_state.cpu_ticks_prev = ticks;
335 return ticks + timers_state.cpu_ticks_offset;
336 }
337}
338
339/* return the host CPU monotonic timer and handle stop/restart */
340int64_t cpu_get_clock(void)
341{
342 int64_t ti;
343 if (!timers_state.cpu_ticks_enabled) {
344 return timers_state.cpu_clock_offset;
345 } else {
346 ti = get_clock();
347 return ti + timers_state.cpu_clock_offset;
348 }
349}
350
351/* enable cpu_get_ticks() */
352void cpu_enable_ticks(void)
353{
354 if (!timers_state.cpu_ticks_enabled) {
355 timers_state.cpu_ticks_offset -= cpu_get_real_ticks();
356 timers_state.cpu_clock_offset -= get_clock();
357 timers_state.cpu_ticks_enabled = 1;
358 }
359}
360
361/* disable cpu_get_ticks() : the clock is stopped. You must not call
362 cpu_get_ticks() after that. */
363void cpu_disable_ticks(void)
364{
365 if (timers_state.cpu_ticks_enabled) {
366 timers_state.cpu_ticks_offset = cpu_get_ticks();
367 timers_state.cpu_clock_offset = cpu_get_clock();
368 timers_state.cpu_ticks_enabled = 0;
369 }
370}
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100371
372void qemu_clock_warp(QEMUClockType clock) {
373}