blob: 9cb5011ed19142ed094fc872dcfdfb0cea193b0e [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' Turnera889d352014-03-20 12:35:32 +010029#include "cpu.h"
30#include "dyngen-exec.h"
David 'Digit' Turner0e051542014-01-23 02:41:42 +010031#include "exec/exec-all.h"
David 'Digit' Turner852088c2013-12-14 23:04:12 +010032#include "exec/gdbstub.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010033#include "sysemu/dma.h"
34#include "sysemu/kvm.h"
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +010035#include "exec/exec-all.h"
David 'Digit' Turnere1e03df2013-12-15 00:42:21 +010036#include "exec/hax.h"
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020037
David 'Digit' Turner11822842013-12-17 09:16:47 +010038#include "sysemu/cpus.h"
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020039
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010040static CPUOldState *cur_cpu;
41static CPUOldState *next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020042
43/***********************************************************/
44void hw_error(const char *fmt, ...)
45{
46 va_list ap;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010047 CPUOldState *env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020048
49 va_start(ap, fmt);
50 fprintf(stderr, "qemu: hardware error: ");
51 vfprintf(stderr, fmt, ap);
52 fprintf(stderr, "\n");
53 for(env = first_cpu; env != NULL; env = env->next_cpu) {
54 fprintf(stderr, "CPU #%d:\n", env->cpu_index);
55#ifdef TARGET_I386
56 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU);
57#else
58 cpu_dump_state(env, stderr, fprintf, 0);
59#endif
60 }
61 va_end(ap);
62 abort();
63}
64
65static void do_vm_stop(int reason)
66{
67 if (vm_running) {
68 cpu_disable_ticks();
69 vm_running = 0;
70 pause_all_vcpus();
71 vm_state_notify(0, reason);
72 }
73}
74
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010075static int cpu_can_run(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020076{
77 if (env->stop)
78 return 0;
79 if (env->stopped)
80 return 0;
81 return 1;
82}
83
David 'Digit' Turner93949dc2014-03-18 15:00:37 +010084static int internal_cpu_has_work(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020085{
86 if (env->stop)
87 return 1;
88 if (env->stopped)
89 return 0;
90 if (!env->halted)
91 return 1;
David 'Digit' Turner93949dc2014-03-18 15:00:37 +010092 if (cpu_has_work(env))
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020093 return 1;
94 return 0;
95}
96
97int tcg_has_work(void)
98{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010099 CPUOldState *env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200100
101 for (env = first_cpu; env != NULL; env = env->next_cpu)
David 'Digit' Turner93949dc2014-03-18 15:00:37 +0100102 if (internal_cpu_has_work(env))
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200103 return 1;
104 return 0;
105}
106
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200107void qemu_init_vcpu(void *_env)
108{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100109 CPUOldState *env = _env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200110
111 if (kvm_enabled())
112 kvm_init_vcpu(env);
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800113#ifdef CONFIG_HAX
114 if (hax_enabled())
115 hax_init_vcpu(env);
116#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200117 return;
118}
119
120int qemu_cpu_self(void *env)
121{
122 return 1;
123}
124
125void resume_all_vcpus(void)
126{
127}
128
129void pause_all_vcpus(void)
130{
131}
132
133void qemu_cpu_kick(void *env)
134{
135 return;
136}
137
David 'Digit' Turnerf9077a82014-02-10 23:10:47 +0100138// In main-loop.c
139#ifdef _WIN32
140extern HANDLE qemu_event_handle;
141#endif
142
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200143void qemu_notify_event(void)
144{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100145 CPUOldState *env = cpu_single_env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200146
147 if (env) {
148 cpu_exit(env);
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800149 /*
150 * This is mainly for the Windows host, where the timer may be in
151 * a different thread with vcpu. Thus the timer function needs to
152 * notify the vcpu thread of more than simply cpu_exit. If env is
153 * not NULL, it means that the vcpu is in execute state, we need
154 * only to set the flags. If the guest is in execute state, the
155 * HAX kernel module will exit to qemu. If env is NULL, vcpu is
156 * in main_loop_wait, and we need a event to notify it.
157 */
158#ifdef CONFIG_HAX
159 if (hax_enabled())
160 hax_raise_event(env);
161 } else {
162#ifdef _WIN32
163 if(hax_enabled())
164 SetEvent(qemu_event_handle);
165#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200166 }
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800167#else
168 }
169#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200170}
171
172void qemu_mutex_lock_iothread(void)
173{
174}
175
176void qemu_mutex_unlock_iothread(void)
177{
178}
179
180void vm_stop(int reason)
181{
182 do_vm_stop(reason);
183}
184
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100185static int qemu_cpu_exec(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200186{
187 int ret;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200188
189#ifdef CONFIG_PROFILER
David 'Digit' Turnerf9077a82014-02-10 23:10:47 +0100190 int64_t ti = profile_getclock();
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200191#endif
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100192#ifndef CONFIG_ANDROID
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200193 if (use_icount) {
194 int64_t count;
195 int decr;
196 qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
197 env->icount_decr.u16.low = 0;
198 env->icount_extra = 0;
199 count = qemu_next_icount_deadline();
200 count = (count + (1 << icount_time_shift) - 1)
201 >> icount_time_shift;
202 qemu_icount += count;
203 decr = (count > 0xffff) ? 0xffff : count;
204 count -= decr;
205 env->icount_decr.u16.low = decr;
206 env->icount_extra = count;
207 }
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100208#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200209 ret = cpu_exec(env);
210#ifdef CONFIG_PROFILER
211 qemu_time += profile_getclock() - ti;
212#endif
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100213#ifndef CONFIG_ANDROID
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200214 if (use_icount) {
215 /* Fold pending instructions back into the
216 instruction counter, and clear the interrupt flag. */
217 qemu_icount -= (env->icount_decr.u16.low
218 + env->icount_extra);
219 env->icount_decr.u32 = 0;
220 env->icount_extra = 0;
221 }
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100222#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200223 return ret;
224}
225
226void tcg_cpu_exec(void)
227{
228 int ret = 0;
229
230 if (next_cpu == NULL)
231 next_cpu = first_cpu;
232 for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100233 CPUOldState *env = cur_cpu = next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200234
235 if (!vm_running)
236 break;
237 if (qemu_timer_alarm_pending()) {
238 break;
239 }
240 if (cpu_can_run(env))
241 ret = qemu_cpu_exec(env);
242 if (ret == EXCP_DEBUG) {
243 gdb_set_stop_cpu(env);
244 debug_requested = 1;
245 break;
246 }
247 }
248}
249
David 'Digit' Turnerf0183552014-02-16 14:20:45 +0100250/***********************************************************/
251/* guest cycle counter */
252
253typedef struct TimersState {
254 int64_t cpu_ticks_prev;
255 int64_t cpu_ticks_offset;
256 int64_t cpu_clock_offset;
257 int32_t cpu_ticks_enabled;
258 int64_t dummy;
259} TimersState;
260
261static void timer_save(QEMUFile *f, void *opaque)
262{
263 TimersState *s = opaque;
264
265 if (s->cpu_ticks_enabled) {
266 hw_error("cannot save state if virtual timers are running");
267 }
268 qemu_put_be64(f, s->cpu_ticks_prev);
269 qemu_put_be64(f, s->cpu_ticks_offset);
270 qemu_put_be64(f, s->cpu_clock_offset);
271 }
272
273static int timer_load(QEMUFile *f, void *opaque, int version_id)
274{
275 TimersState *s = opaque;
276
277 if (version_id != 1 && version_id != 2)
278 return -EINVAL;
279 if (s->cpu_ticks_enabled) {
280 return -EINVAL;
281 }
282 s->cpu_ticks_prev = qemu_get_sbe64(f);
283 s->cpu_ticks_offset = qemu_get_sbe64(f);
284 if (version_id == 2) {
285 s->cpu_clock_offset = qemu_get_sbe64(f);
286 }
287 return 0;
288}
289
290
291TimersState timers_state;
292
293void qemu_timer_register_savevm(void) {
David 'Digit' Turner5cb5c0b2014-02-17 16:04:03 +0100294 register_savevm(NULL,
295 "timer",
296 0,
297 2,
298 timer_save,
299 timer_load,
300 &timers_state);
David 'Digit' Turnerf0183552014-02-16 14:20:45 +0100301}
302
David 'Digit' Turner9b3a4b02014-01-23 00:52:54 +0100303/* Return the virtual CPU time, based on the instruction counter. */
304int64_t cpu_get_icount(void)
305{
306 int64_t icount;
307 CPUOldState *env = cpu_single_env;;
308
309 icount = qemu_icount;
310 if (env) {
311 if (!can_do_io(env)) {
312 fprintf(stderr, "Bad clock read\n");
313 }
314 icount -= (env->icount_decr.u16.low + env->icount_extra);
315 }
316 return qemu_icount_bias + (icount << icount_time_shift);
317}
David 'Digit' Turnerf0183552014-02-16 14:20:45 +0100318
319/* return the host CPU cycle counter and handle stop/restart */
320int64_t cpu_get_ticks(void)
321{
322 if (use_icount) {
323 return cpu_get_icount();
324 }
325 if (!timers_state.cpu_ticks_enabled) {
326 return timers_state.cpu_ticks_offset;
327 } else {
328 int64_t ticks;
329 ticks = cpu_get_real_ticks();
330 if (timers_state.cpu_ticks_prev > ticks) {
331 /* Note: non increasing ticks may happen if the host uses
332 software suspend */
333 timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
334 }
335 timers_state.cpu_ticks_prev = ticks;
336 return ticks + timers_state.cpu_ticks_offset;
337 }
338}
339
340/* return the host CPU monotonic timer and handle stop/restart */
341int64_t cpu_get_clock(void)
342{
343 int64_t ti;
344 if (!timers_state.cpu_ticks_enabled) {
345 return timers_state.cpu_clock_offset;
346 } else {
347 ti = get_clock();
348 return ti + timers_state.cpu_clock_offset;
349 }
350}
351
352/* enable cpu_get_ticks() */
353void cpu_enable_ticks(void)
354{
355 if (!timers_state.cpu_ticks_enabled) {
356 timers_state.cpu_ticks_offset -= cpu_get_real_ticks();
357 timers_state.cpu_clock_offset -= get_clock();
358 timers_state.cpu_ticks_enabled = 1;
359 }
360}
361
362/* disable cpu_get_ticks() : the clock is stopped. You must not call
363 cpu_get_ticks() after that. */
364void cpu_disable_ticks(void)
365{
366 if (timers_state.cpu_ticks_enabled) {
367 timers_state.cpu_ticks_offset = cpu_get_ticks();
368 timers_state.cpu_clock_offset = cpu_get_clock();
369 timers_state.cpu_ticks_enabled = 0;
370 }
371}
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100372
373void qemu_clock_warp(QEMUClockType clock) {
374}