blob: 38ecaf3f4ad6bfd5f385187cfc26ac1b7b5512eb [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"
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' Turner4ab12252014-03-24 11:29:53 +010046 CPUState *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");
David 'Digit' Turner4ab12252014-03-24 11:29:53 +010052 CPU_FOREACH(env) {
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020053 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' Turner23ca2ae2011-06-01 16:14:53 +020083int tcg_has_work(void)
84{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010085 CPUOldState *env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020086
David 'Digit' Turner4ab12252014-03-24 11:29:53 +010087 CPU_FOREACH(env) {
88 if (env->stop)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020089 return 1;
David 'Digit' Turner4ab12252014-03-24 11:29:53 +010090 if (env->stopped)
91 return 0;
92 if (!env->halted)
93 return 1;
94 if (cpu_has_work(env))
95 return 1;
96 return 0;
97 }
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020098 return 0;
99}
100
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200101void qemu_init_vcpu(void *_env)
102{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100103 CPUOldState *env = _env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200104
105 if (kvm_enabled())
106 kvm_init_vcpu(env);
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800107#ifdef CONFIG_HAX
108 if (hax_enabled())
109 hax_init_vcpu(env);
110#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200111 return;
112}
113
114int qemu_cpu_self(void *env)
115{
116 return 1;
117}
118
119void resume_all_vcpus(void)
120{
121}
122
123void pause_all_vcpus(void)
124{
125}
126
127void qemu_cpu_kick(void *env)
128{
129 return;
130}
131
David 'Digit' Turnerf9077a82014-02-10 23:10:47 +0100132// In main-loop.c
133#ifdef _WIN32
134extern HANDLE qemu_event_handle;
135#endif
136
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200137void qemu_notify_event(void)
138{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100139 CPUOldState *env = cpu_single_env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200140
141 if (env) {
142 cpu_exit(env);
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800143 /*
144 * This is mainly for the Windows host, where the timer may be in
145 * a different thread with vcpu. Thus the timer function needs to
146 * notify the vcpu thread of more than simply cpu_exit. If env is
147 * not NULL, it means that the vcpu is in execute state, we need
148 * only to set the flags. If the guest is in execute state, the
149 * HAX kernel module will exit to qemu. If env is NULL, vcpu is
150 * in main_loop_wait, and we need a event to notify it.
151 */
152#ifdef CONFIG_HAX
153 if (hax_enabled())
154 hax_raise_event(env);
155 } else {
156#ifdef _WIN32
157 if(hax_enabled())
158 SetEvent(qemu_event_handle);
159#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200160 }
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800161#else
162 }
163#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200164}
165
166void qemu_mutex_lock_iothread(void)
167{
168}
169
170void qemu_mutex_unlock_iothread(void)
171{
172}
173
174void vm_stop(int reason)
175{
176 do_vm_stop(reason);
177}
178
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100179static int qemu_cpu_exec(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200180{
181 int ret;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200182
183#ifdef CONFIG_PROFILER
David 'Digit' Turnerf9077a82014-02-10 23:10:47 +0100184 int64_t ti = profile_getclock();
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200185#endif
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100186#ifndef CONFIG_ANDROID
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200187 if (use_icount) {
188 int64_t count;
189 int decr;
190 qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
191 env->icount_decr.u16.low = 0;
192 env->icount_extra = 0;
193 count = qemu_next_icount_deadline();
194 count = (count + (1 << icount_time_shift) - 1)
195 >> icount_time_shift;
196 qemu_icount += count;
197 decr = (count > 0xffff) ? 0xffff : count;
198 count -= decr;
199 env->icount_decr.u16.low = decr;
200 env->icount_extra = count;
201 }
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100202#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200203 ret = cpu_exec(env);
204#ifdef CONFIG_PROFILER
205 qemu_time += profile_getclock() - ti;
206#endif
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100207#ifndef CONFIG_ANDROID
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200208 if (use_icount) {
209 /* Fold pending instructions back into the
210 instruction counter, and clear the interrupt flag. */
211 qemu_icount -= (env->icount_decr.u16.low
212 + env->icount_extra);
213 env->icount_decr.u32 = 0;
214 env->icount_extra = 0;
215 }
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100216#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200217 return ret;
218}
219
220void tcg_cpu_exec(void)
221{
222 int ret = 0;
223
224 if (next_cpu == NULL)
David 'Digit' Turner4ab12252014-03-24 11:29:53 +0100225 next_cpu = QTAILQ_FIRST(&cpus);
226 for (; next_cpu != NULL; next_cpu = QTAILQ_NEXT(next_cpu, node)) {
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100227 CPUOldState *env = cur_cpu = next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200228
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(env);
238 debug_requested = 1;
239 break;
240 }
241 }
242}
243
David 'Digit' Turnerf0183552014-02-16 14:20:45 +0100244/***********************************************************/
245/* guest cycle counter */
246
247typedef 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
255static 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
267static 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
285TimersState timers_state;
286
287void qemu_timer_register_savevm(void) {
David 'Digit' Turner5cb5c0b2014-02-17 16:04:03 +0100288 register_savevm(NULL,
289 "timer",
290 0,
291 2,
292 timer_save,
293 timer_load,
294 &timers_state);
David 'Digit' Turnerf0183552014-02-16 14:20:45 +0100295}
296
David 'Digit' Turner9b3a4b02014-01-23 00:52:54 +0100297/* Return the virtual CPU time, based on the instruction counter. */
298int64_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}
David 'Digit' Turnerf0183552014-02-16 14:20:45 +0100312
313/* return the host CPU cycle counter and handle stop/restart */
314int64_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 */
335int64_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() */
347void 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. */
358void 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}
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100366
367void qemu_clock_warp(QEMUClockType clock) {
368}