blob: 089e0fe12ff46b1095a3a414e7f529af1e9f84a3 [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"
David 'Digit' Turner6af67652013-12-14 23:49:32 +010027#include "monitor/monitor.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010028#include "sysemu/sysemu.h"
David 'Digit' Turner0e051542014-01-23 02:41:42 +010029#include "exec/exec-all.h"
David 'Digit' Turner852088c2013-12-14 23:04:12 +010030#include "exec/gdbstub.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010031#include "sysemu/dma.h"
32#include "sysemu/kvm.h"
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +010033#include "exec/exec-all.h"
David 'Digit' Turnere1e03df2013-12-15 00:42:21 +010034#include "exec/hax.h"
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020035
David 'Digit' Turner11822842013-12-17 09:16:47 +010036#include "sysemu/cpus.h"
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020037
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010038static CPUOldState *cur_cpu;
39static CPUOldState *next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020040
41/***********************************************************/
42void hw_error(const char *fmt, ...)
43{
44 va_list ap;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010045 CPUOldState *env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020046
47 va_start(ap, fmt);
48 fprintf(stderr, "qemu: hardware error: ");
49 vfprintf(stderr, fmt, ap);
50 fprintf(stderr, "\n");
51 for(env = first_cpu; env != NULL; env = env->next_cpu) {
52 fprintf(stderr, "CPU #%d:\n", env->cpu_index);
53#ifdef TARGET_I386
54 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU);
55#else
56 cpu_dump_state(env, stderr, fprintf, 0);
57#endif
58 }
59 va_end(ap);
60 abort();
61}
62
63static void do_vm_stop(int reason)
64{
65 if (vm_running) {
66 cpu_disable_ticks();
67 vm_running = 0;
68 pause_all_vcpus();
69 vm_state_notify(0, reason);
70 }
71}
72
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010073static int cpu_can_run(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020074{
75 if (env->stop)
76 return 0;
77 if (env->stopped)
78 return 0;
79 return 1;
80}
81
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010082static int cpu_has_work(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020083{
84 if (env->stop)
85 return 1;
86 if (env->stopped)
87 return 0;
88 if (!env->halted)
89 return 1;
90 if (qemu_cpu_has_work(env))
91 return 1;
92 return 0;
93}
94
95int tcg_has_work(void)
96{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010097 CPUOldState *env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020098
99 for (env = first_cpu; env != NULL; env = env->next_cpu)
100 if (cpu_has_work(env))
101 return 1;
102 return 0;
103}
104
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200105void qemu_init_vcpu(void *_env)
106{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100107 CPUOldState *env = _env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200108
109 if (kvm_enabled())
110 kvm_init_vcpu(env);
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800111#ifdef CONFIG_HAX
112 if (hax_enabled())
113 hax_init_vcpu(env);
114#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200115 return;
116}
117
118int qemu_cpu_self(void *env)
119{
120 return 1;
121}
122
123void resume_all_vcpus(void)
124{
125}
126
127void pause_all_vcpus(void)
128{
129}
130
131void qemu_cpu_kick(void *env)
132{
133 return;
134}
135
David 'Digit' Turnerf9077a82014-02-10 23:10:47 +0100136// In main-loop.c
137#ifdef _WIN32
138extern HANDLE qemu_event_handle;
139#endif
140
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200141void qemu_notify_event(void)
142{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100143 CPUOldState *env = cpu_single_env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200144
145 if (env) {
146 cpu_exit(env);
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800147 /*
148 * This is mainly for the Windows host, where the timer may be in
149 * a different thread with vcpu. Thus the timer function needs to
150 * notify the vcpu thread of more than simply cpu_exit. If env is
151 * not NULL, it means that the vcpu is in execute state, we need
152 * only to set the flags. If the guest is in execute state, the
153 * HAX kernel module will exit to qemu. If env is NULL, vcpu is
154 * in main_loop_wait, and we need a event to notify it.
155 */
156#ifdef CONFIG_HAX
157 if (hax_enabled())
158 hax_raise_event(env);
159 } else {
160#ifdef _WIN32
161 if(hax_enabled())
162 SetEvent(qemu_event_handle);
163#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200164 }
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800165#else
166 }
167#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200168}
169
170void qemu_mutex_lock_iothread(void)
171{
172}
173
174void qemu_mutex_unlock_iothread(void)
175{
176}
177
178void vm_stop(int reason)
179{
180 do_vm_stop(reason);
181}
182
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100183static int qemu_cpu_exec(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200184{
185 int ret;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200186
187#ifdef CONFIG_PROFILER
David 'Digit' Turnerf9077a82014-02-10 23:10:47 +0100188 int64_t ti = profile_getclock();
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200189#endif
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100190#ifndef CONFIG_ANDROID
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200191 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' Turnerdcda9492014-02-16 15:13:55 +0100206#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200207 ret = cpu_exec(env);
208#ifdef CONFIG_PROFILER
209 qemu_time += profile_getclock() - ti;
210#endif
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100211#ifndef CONFIG_ANDROID
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200212 if (use_icount) {
213 /* Fold pending instructions back into the
214 instruction counter, and clear the interrupt flag. */
215 qemu_icount -= (env->icount_decr.u16.low
216 + env->icount_extra);
217 env->icount_decr.u32 = 0;
218 env->icount_extra = 0;
219 }
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100220#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200221 return ret;
222}
223
224void tcg_cpu_exec(void)
225{
226 int ret = 0;
227
228 if (next_cpu == NULL)
229 next_cpu = first_cpu;
230 for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100231 CPUOldState *env = cur_cpu = next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200232
233 if (!vm_running)
234 break;
235 if (qemu_timer_alarm_pending()) {
236 break;
237 }
238 if (cpu_can_run(env))
239 ret = qemu_cpu_exec(env);
240 if (ret == EXCP_DEBUG) {
241 gdb_set_stop_cpu(env);
242 debug_requested = 1;
243 break;
244 }
245 }
246}
247
David 'Digit' Turnerf0183552014-02-16 14:20:45 +0100248/***********************************************************/
249/* guest cycle counter */
250
251typedef struct TimersState {
252 int64_t cpu_ticks_prev;
253 int64_t cpu_ticks_offset;
254 int64_t cpu_clock_offset;
255 int32_t cpu_ticks_enabled;
256 int64_t dummy;
257} TimersState;
258
259static void timer_save(QEMUFile *f, void *opaque)
260{
261 TimersState *s = opaque;
262
263 if (s->cpu_ticks_enabled) {
264 hw_error("cannot save state if virtual timers are running");
265 }
266 qemu_put_be64(f, s->cpu_ticks_prev);
267 qemu_put_be64(f, s->cpu_ticks_offset);
268 qemu_put_be64(f, s->cpu_clock_offset);
269 }
270
271static int timer_load(QEMUFile *f, void *opaque, int version_id)
272{
273 TimersState *s = opaque;
274
275 if (version_id != 1 && version_id != 2)
276 return -EINVAL;
277 if (s->cpu_ticks_enabled) {
278 return -EINVAL;
279 }
280 s->cpu_ticks_prev = qemu_get_sbe64(f);
281 s->cpu_ticks_offset = qemu_get_sbe64(f);
282 if (version_id == 2) {
283 s->cpu_clock_offset = qemu_get_sbe64(f);
284 }
285 return 0;
286}
287
288
289TimersState timers_state;
290
291void qemu_timer_register_savevm(void) {
David 'Digit' Turner5cb5c0b2014-02-17 16:04:03 +0100292 register_savevm(NULL,
293 "timer",
294 0,
295 2,
296 timer_save,
297 timer_load,
298 &timers_state);
David 'Digit' Turnerf0183552014-02-16 14:20:45 +0100299}
300
David 'Digit' Turner9b3a4b02014-01-23 00:52:54 +0100301/* Return the virtual CPU time, based on the instruction counter. */
302int64_t cpu_get_icount(void)
303{
304 int64_t icount;
305 CPUOldState *env = cpu_single_env;;
306
307 icount = qemu_icount;
308 if (env) {
309 if (!can_do_io(env)) {
310 fprintf(stderr, "Bad clock read\n");
311 }
312 icount -= (env->icount_decr.u16.low + env->icount_extra);
313 }
314 return qemu_icount_bias + (icount << icount_time_shift);
315}
David 'Digit' Turnerf0183552014-02-16 14:20:45 +0100316
317/* return the host CPU cycle counter and handle stop/restart */
318int64_t cpu_get_ticks(void)
319{
320 if (use_icount) {
321 return cpu_get_icount();
322 }
323 if (!timers_state.cpu_ticks_enabled) {
324 return timers_state.cpu_ticks_offset;
325 } else {
326 int64_t ticks;
327 ticks = cpu_get_real_ticks();
328 if (timers_state.cpu_ticks_prev > ticks) {
329 /* Note: non increasing ticks may happen if the host uses
330 software suspend */
331 timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
332 }
333 timers_state.cpu_ticks_prev = ticks;
334 return ticks + timers_state.cpu_ticks_offset;
335 }
336}
337
338/* return the host CPU monotonic timer and handle stop/restart */
339int64_t cpu_get_clock(void)
340{
341 int64_t ti;
342 if (!timers_state.cpu_ticks_enabled) {
343 return timers_state.cpu_clock_offset;
344 } else {
345 ti = get_clock();
346 return ti + timers_state.cpu_clock_offset;
347 }
348}
349
350/* enable cpu_get_ticks() */
351void cpu_enable_ticks(void)
352{
353 if (!timers_state.cpu_ticks_enabled) {
354 timers_state.cpu_ticks_offset -= cpu_get_real_ticks();
355 timers_state.cpu_clock_offset -= get_clock();
356 timers_state.cpu_ticks_enabled = 1;
357 }
358}
359
360/* disable cpu_get_ticks() : the clock is stopped. You must not call
361 cpu_get_ticks() after that. */
362void cpu_disable_ticks(void)
363{
364 if (timers_state.cpu_ticks_enabled) {
365 timers_state.cpu_ticks_offset = cpu_get_ticks();
366 timers_state.cpu_clock_offset = cpu_get_clock();
367 timers_state.cpu_ticks_enabled = 0;
368 }
369}
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100370
371void qemu_clock_warp(QEMUClockType clock) {
372}