blob: 88294c2c565506fff13599768f497162a85e84d0 [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' Turner9b3a4b02014-01-23 00:52:54 +0100246/* Return the virtual CPU time, based on the instruction counter. */
247int64_t cpu_get_icount(void)
248{
249 int64_t icount;
250 CPUOldState *env = cpu_single_env;;
251
252 icount = qemu_icount;
253 if (env) {
254 if (!can_do_io(env)) {
255 fprintf(stderr, "Bad clock read\n");
256 }
257 icount -= (env->icount_decr.u16.low + env->icount_extra);
258 }
259 return qemu_icount_bias + (icount << icount_time_shift);
260}