blob: 9d11c9b4f1bcf6196036658a593d9a7c3d25cd35 [file] [log] [blame]
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001/*
2 * i386 emulator main execution loop
3 *
4 * Copyright (c) 2003-2005 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080018 */
19#include "config.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080020#include "exec.h"
David 'Digit' Turnercc33b2d2013-12-15 00:09:42 +010021#include "disas/disas.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080022#include "tcg.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010023#include "sysemu/kvm.h"
David 'Digit' Turnere1e03df2013-12-15 00:42:21 +010024#include "exec/hax.h"
25#include "qemu/atomic.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080026
27#if !defined(CONFIG_SOFTMMU)
28#undef EAX
29#undef ECX
30#undef EDX
31#undef EBX
32#undef ESP
33#undef EBP
34#undef ESI
35#undef EDI
36#undef EIP
37#include <signal.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070038#ifdef __linux__
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080039#include <sys/ucontext.h>
40#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070041#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080042
David 'Digit' Turner2c538c82010-05-10 16:48:20 -070043#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080044// Work around ugly bugs in glibc that mangle global register contents
45#undef env
46#define env cpu_single_env
47#endif
48
49int tb_invalidated_flag;
50
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070051//#define CONFIG_DEBUG_EXEC
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080052//#define DEBUG_SIGNAL
53
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010054int qemu_cpu_has_work(CPUOldState *env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070055{
56 return cpu_has_work(env);
57}
58
David 'Digit' Turner85c62202014-02-16 20:53:40 +010059void cpu_loop_exit(CPUArchState* env1)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080060{
David 'Digit' Turner85c62202014-02-16 20:53:40 +010061 env1->current_tb = NULL;
62 longjmp(env1->jmp_env, 1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080063}
64
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080065/* exit the current TB from a signal handler. The host registers are
66 restored in a state compatible with the CPU emulator
67 */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +010068void cpu_resume_from_signal(CPUArchState *env1, void *puc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080069{
70#if !defined(CONFIG_SOFTMMU)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070071#ifdef __linux__
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080072 struct ucontext *uc = puc;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070073#elif defined(__OpenBSD__)
74 struct sigcontext *uc = puc;
75#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080076#endif
77
78 env = env1;
79
80 /* XXX: restore cpu registers saved in host registers */
81
82#if !defined(CONFIG_SOFTMMU)
83 if (puc) {
84 /* XXX: use siglongjmp ? */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070085#ifdef __linux__
David Turner24cd25a2010-09-10 14:22:27 +020086#ifdef __ia64
87 sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
88#else
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080089 sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
David Turner24cd25a2010-09-10 14:22:27 +020090#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070091#elif defined(__OpenBSD__)
92 sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
93#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080094 }
95#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070096 env->exception_index = -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080097 longjmp(env->jmp_env, 1);
98}
99
100/* Execute the code without caching the generated code. An interpreter
101 could be used if available. */
102static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
103{
104 unsigned long next_tb;
105 TranslationBlock *tb;
106
107 /* Should never happen.
108 We only end up here when an existing TB is too long. */
109 if (max_cycles > CF_COUNT_MASK)
110 max_cycles = CF_COUNT_MASK;
111
112 tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
113 max_cycles);
114 env->current_tb = tb;
115 /* execute the generated code */
116 next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
David Turner24cd25a2010-09-10 14:22:27 +0200117 env->current_tb = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800118
119 if ((next_tb & 3) == 2) {
120 /* Restore PC. This may happen if async event occurs before
121 the TB starts executing. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700122 cpu_pc_from_tb(env, tb);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800123 }
124 tb_phys_invalidate(tb, -1);
125 tb_free(tb);
126}
127
128static TranslationBlock *tb_find_slow(target_ulong pc,
129 target_ulong cs_base,
130 uint64_t flags)
131{
132 TranslationBlock *tb, **ptb1;
133 unsigned int h;
134 target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
135
136 tb_invalidated_flag = 0;
137
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800138 /* find translated block using physical mappings */
David 'Digit' Turner13487772014-02-17 21:16:46 +0100139 phys_pc = get_page_addr_code(env, pc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800140 phys_page1 = phys_pc & TARGET_PAGE_MASK;
141 phys_page2 = -1;
142 h = tb_phys_hash_func(phys_pc);
David 'Digit' Turner13487772014-02-17 21:16:46 +0100143 ptb1 = &tcg_ctx.tb_ctx.tb_phys_hash[h];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800144 for(;;) {
145 tb = *ptb1;
146 if (!tb)
147 goto not_found;
148 if (tb->pc == pc &&
149 tb->page_addr[0] == phys_page1 &&
150 tb->cs_base == cs_base &&
151 tb->flags == flags) {
152 /* check next page if needed */
153 if (tb->page_addr[1] != -1) {
154 virt_page2 = (pc & TARGET_PAGE_MASK) +
155 TARGET_PAGE_SIZE;
David 'Digit' Turner13487772014-02-17 21:16:46 +0100156 phys_page2 = get_page_addr_code(env, virt_page2);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800157 if (tb->page_addr[1] == phys_page2)
158 goto found;
159 } else {
160 goto found;
161 }
162 }
163 ptb1 = &tb->phys_hash_next;
164 }
165 not_found:
166 /* if no translated code available, then translate it now */
167 tb = tb_gen_code(env, pc, cs_base, flags, 0);
168
169 found:
David 'Digit' Turner52858642011-06-03 13:41:05 +0200170 /* Move the last found TB to the head of the list */
171 if (likely(*ptb1)) {
172 *ptb1 = tb->phys_hash_next;
David 'Digit' Turner13487772014-02-17 21:16:46 +0100173 tb->phys_hash_next = tcg_ctx.tb_ctx.tb_phys_hash[h];
174 tcg_ctx.tb_ctx.tb_phys_hash[h] = tb;
David 'Digit' Turner52858642011-06-03 13:41:05 +0200175 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800176 /* we add the TB in the virtual pc hash table */
177 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
178 return tb;
179}
180
181static inline TranslationBlock *tb_find_fast(void)
182{
183 TranslationBlock *tb;
184 target_ulong cs_base, pc;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700185 int flags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800186
187 /* we record a subset of the CPU state. It will
188 always be the same before a given translated block
189 is executed. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700190 cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800191 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
192 if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
193 tb->flags != flags)) {
194 tb = tb_find_slow(pc, cs_base, flags);
195 }
196 return tb;
197}
198
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700199static CPUDebugExcpHandler *debug_excp_handler;
200
David 'Digit' Turner13487772014-02-17 21:16:46 +0100201void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700202{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700203 debug_excp_handler = handler;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700204}
205
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100206static void cpu_handle_debug_exception(CPUOldState *env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700207{
208 CPUWatchpoint *wp;
209
David 'Digit' Turner42760382011-05-11 01:48:19 +0200210 if (!env->watchpoint_hit) {
211 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700212 wp->flags &= ~BP_WATCHPOINT_HIT;
David 'Digit' Turner42760382011-05-11 01:48:19 +0200213 }
214 }
215 if (debug_excp_handler) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700216 debug_excp_handler(env);
David 'Digit' Turner42760382011-05-11 01:48:19 +0200217 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700218}
219
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800220/* main execution loop */
221
David Turner24cd25a2010-09-10 14:22:27 +0200222volatile sig_atomic_t exit_request;
223
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800224/*
225 * Qemu emulation can happen because of MMIO or emulation mode,
226 * i.e. non-PG mode. For MMIO cases, the pending interrupt should not
227 * be emulated in qemu because MMIO is emulated for only one
228 * instruction now and then back to the HAX kernel module.
229 */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100230int need_handle_intr_request(CPUOldState *env)
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800231{
232#ifdef CONFIG_HAX
233 if (!hax_enabled() || hax_vcpu_emulation_mode(env))
234 return env->interrupt_request;
235 return 0;
236#else
237 return env->interrupt_request;
238#endif
239}
240
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100241int cpu_exec(CPUOldState *env1)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800242{
David Turner24cd25a2010-09-10 14:22:27 +0200243 volatile host_reg_t saved_env_reg;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800244 int ret, interrupt_request;
245 TranslationBlock *tb;
246 uint8_t *tc_ptr;
247 unsigned long next_tb;
248
David 'Digit' Turner52858642011-06-03 13:41:05 +0200249 if (env1->halted) {
250 if (!cpu_has_work(env1)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800251 return EXCP_HALTED;
David 'Digit' Turner52858642011-06-03 13:41:05 +0200252 }
253
254 env1->halted = 0;
255 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800256
257 cpu_single_env = env1;
258
David Turner24cd25a2010-09-10 14:22:27 +0200259 /* the access to env below is actually saving the global register's
260 value, so that files not including target-xyz/exec.h are free to
261 use it. */
262 QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
263 saved_env_reg = (host_reg_t) env;
264 barrier();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800265 env = env1;
266
David Turner24cd25a2010-09-10 14:22:27 +0200267 if (unlikely(exit_request)) {
268 env->exit_request = 1;
269 }
270
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800271#if defined(TARGET_I386)
David Turner24cd25a2010-09-10 14:22:27 +0200272 if (!kvm_enabled()) {
273 /* put eflags in CPU temporary format */
274 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
275 DF = 1 - (2 * ((env->eflags >> 10) & 1));
276 CC_OP = CC_OP_EFLAGS;
277 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
278 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800279#elif defined(TARGET_SPARC)
280#elif defined(TARGET_M68K)
281 env->cc_op = CC_OP_FLAGS;
282 env->cc_dest = env->sr & 0xf;
283 env->cc_x = (env->sr >> 4) & 1;
284#elif defined(TARGET_ALPHA)
285#elif defined(TARGET_ARM)
David 'Digit' Turner42760382011-05-11 01:48:19 +0200286#elif defined(TARGET_UNICORE32)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800287#elif defined(TARGET_PPC)
David 'Digit' Turner42760382011-05-11 01:48:19 +0200288#elif defined(TARGET_LM32)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700289#elif defined(TARGET_MICROBLAZE)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800290#elif defined(TARGET_MIPS)
291#elif defined(TARGET_SH4)
292#elif defined(TARGET_CRIS)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700293#elif defined(TARGET_S390X)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800294 /* XXXXX */
295#else
296#error unsupported target CPU
297#endif
298 env->exception_index = -1;
299
300 /* prepare setjmp context for exception handling */
301 for(;;) {
302 if (setjmp(env->jmp_env) == 0) {
David 'Digit' Turner2c538c82010-05-10 16:48:20 -0700303#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700304#undef env
305 env = cpu_single_env;
306#define env cpu_single_env
307#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800308 /* if an exception is pending, we execute it here */
309 if (env->exception_index >= 0) {
310 if (env->exception_index >= EXCP_INTERRUPT) {
311 /* exit request from the cpu execution loop */
312 ret = env->exception_index;
David 'Digit' Turner42760382011-05-11 01:48:19 +0200313 if (ret == EXCP_DEBUG) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700314 cpu_handle_debug_exception(env);
David 'Digit' Turner42760382011-05-11 01:48:19 +0200315 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800316 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700317 } else {
318#if defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800319 /* if user mode only, we simulate a fake exception
320 which will be handled outside the cpu execution
321 loop */
322#if defined(TARGET_I386)
323 do_interrupt_user(env->exception_index,
324 env->exception_is_int,
325 env->error_code,
326 env->exception_next_eip);
327 /* successfully delivered */
328 env->old_exception = -1;
329#endif
330 ret = env->exception_index;
331 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700332#else
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800333#if defined(TARGET_I386)
334 /* simulate a real cpu exception. On i386, it can
335 trigger new exceptions, but we do not handle
336 double or triple faults yet. */
337 do_interrupt(env->exception_index,
338 env->exception_is_int,
339 env->error_code,
340 env->exception_next_eip, 0);
341 /* successfully delivered */
342 env->old_exception = -1;
343#elif defined(TARGET_PPC)
344 do_interrupt(env);
David 'Digit' Turner42760382011-05-11 01:48:19 +0200345#elif defined(TARGET_LM32)
346 do_interrupt(env);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700347#elif defined(TARGET_MICROBLAZE)
348 do_interrupt(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800349#elif defined(TARGET_MIPS)
350 do_interrupt(env);
351#elif defined(TARGET_SPARC)
352 do_interrupt(env);
353#elif defined(TARGET_ARM)
354 do_interrupt(env);
David 'Digit' Turner42760382011-05-11 01:48:19 +0200355#elif defined(TARGET_UNICORE32)
356 do_interrupt(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800357#elif defined(TARGET_SH4)
358 do_interrupt(env);
359#elif defined(TARGET_ALPHA)
360 do_interrupt(env);
361#elif defined(TARGET_CRIS)
362 do_interrupt(env);
363#elif defined(TARGET_M68K)
364 do_interrupt(0);
David 'Digit' Turner42760382011-05-11 01:48:19 +0200365#elif defined(TARGET_S390X)
366 do_interrupt(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800367#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700368 env->exception_index = -1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700369#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800370 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800371 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800372
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800373#ifdef CONFIG_HAX
374 if (hax_enabled() && !hax_vcpu_exec(env))
375 longjmp(env->jmp_env, 1);
376#endif
377
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700378 if (kvm_enabled()) {
379 kvm_cpu_exec(env);
380 longjmp(env->jmp_env, 1);
381 }
382
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800383 next_tb = 0; /* force lookup of first TB */
384 for(;;) {
385 interrupt_request = env->interrupt_request;
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800386 if (unlikely(need_handle_intr_request(env))) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700387 if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
388 /* Mask out external interrupts for this step. */
David 'Digit' Turner52858642011-06-03 13:41:05 +0200389 interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700390 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800391 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
392 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
393 env->exception_index = EXCP_DEBUG;
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100394 cpu_loop_exit(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800395 }
396#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700397 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
David 'Digit' Turner42760382011-05-11 01:48:19 +0200398 defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800399 if (interrupt_request & CPU_INTERRUPT_HALT) {
400 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
401 env->halted = 1;
402 env->exception_index = EXCP_HLT;
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100403 cpu_loop_exit(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800404 }
405#endif
406#if defined(TARGET_I386)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700407 if (interrupt_request & CPU_INTERRUPT_INIT) {
408 svm_check_intercept(SVM_EXIT_INIT);
409 do_cpu_init(env);
410 env->exception_index = EXCP_HALTED;
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100411 cpu_loop_exit(env);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700412 } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
413 do_cpu_sipi(env);
414 } else if (env->hflags2 & HF2_GIF_MASK) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800415 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
416 !(env->hflags & HF_SMM_MASK)) {
417 svm_check_intercept(SVM_EXIT_SMI);
418 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
419 do_smm_enter();
420 next_tb = 0;
421 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
422 !(env->hflags2 & HF2_NMI_MASK)) {
423 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
424 env->hflags2 |= HF2_NMI_MASK;
425 do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
426 next_tb = 0;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700427 } else if (interrupt_request & CPU_INTERRUPT_MCE) {
428 env->interrupt_request &= ~CPU_INTERRUPT_MCE;
429 do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
430 next_tb = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800431 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200432 (((env->hflags2 & HF2_VINTR_MASK) &&
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800433 (env->hflags2 & HF2_HIF_MASK)) ||
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200434 (!(env->hflags2 & HF2_VINTR_MASK) &&
435 (env->eflags & IF_MASK &&
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800436 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
437 int intno;
438 svm_check_intercept(SVM_EXIT_INTR);
439 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
440 intno = cpu_get_pic_interrupt(env);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700441 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
David 'Digit' Turner2c538c82010-05-10 16:48:20 -0700442#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700443#undef env
444 env = cpu_single_env;
445#define env cpu_single_env
446#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800447 do_interrupt(intno, 0, 0, 0, 1);
448 /* ensure that no TB jump will be modified as
449 the program flow was changed */
450 next_tb = 0;
451#if !defined(CONFIG_USER_ONLY)
452 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200453 (env->eflags & IF_MASK) &&
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800454 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
455 int intno;
456 /* FIXME: this should respect TPR */
457 svm_check_intercept(SVM_EXIT_VINTR);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800458 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700459 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800460 do_interrupt(intno, 0, 0, 0, 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700461 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800462 next_tb = 0;
463#endif
464 }
465 }
466#elif defined(TARGET_PPC)
467#if 0
468 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700469 cpu_reset(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800470 }
471#endif
472 if (interrupt_request & CPU_INTERRUPT_HARD) {
473 ppc_hw_interrupt(env);
474 if (env->pending_interrupts == 0)
475 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
476 next_tb = 0;
477 }
David 'Digit' Turner42760382011-05-11 01:48:19 +0200478#elif defined(TARGET_LM32)
479 if ((interrupt_request & CPU_INTERRUPT_HARD)
480 && (env->ie & IE_IE)) {
481 env->exception_index = EXCP_IRQ;
482 do_interrupt(env);
483 next_tb = 0;
484 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700485#elif defined(TARGET_MICROBLAZE)
486 if ((interrupt_request & CPU_INTERRUPT_HARD)
487 && (env->sregs[SR_MSR] & MSR_IE)
488 && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
489 && !(env->iflags & (D_FLAG | IMM_FLAG))) {
490 env->exception_index = EXCP_IRQ;
491 do_interrupt(env);
492 next_tb = 0;
493 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800494#elif defined(TARGET_MIPS)
495 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
David 'Digit' Turner42760382011-05-11 01:48:19 +0200496 cpu_mips_hw_interrupts_pending(env)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800497 /* Raise it */
498 env->exception_index = EXCP_EXT_INTERRUPT;
499 env->error_code = 0;
500 do_interrupt(env);
501 next_tb = 0;
502 }
503#elif defined(TARGET_SPARC)
David Turner24cd25a2010-09-10 14:22:27 +0200504 if (interrupt_request & CPU_INTERRUPT_HARD) {
505 if (cpu_interrupts_enabled(env) &&
506 env->interrupt_index > 0) {
507 int pil = env->interrupt_index & 0xf;
508 int type = env->interrupt_index & 0xf0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800509
David Turner24cd25a2010-09-10 14:22:27 +0200510 if (((type == TT_EXTINT) &&
511 cpu_pil_allowed(env, pil)) ||
512 type != TT_EXTINT) {
513 env->exception_index = env->interrupt_index;
514 do_interrupt(env);
515 next_tb = 0;
516 }
517 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800518 }
519#elif defined(TARGET_ARM)
520 if (interrupt_request & CPU_INTERRUPT_FIQ
521 && !(env->uncached_cpsr & CPSR_F)) {
522 env->exception_index = EXCP_FIQ;
523 do_interrupt(env);
524 next_tb = 0;
525 }
526 /* ARMv7-M interrupt return works by loading a magic value
527 into the PC. On real hardware the load causes the
528 return to occur. The qemu implementation performs the
529 jump normally, then does the exception return when the
530 CPU tries to execute code at the magic address.
531 This will cause the magic PC value to be pushed to
David 'Digit' Turner52858642011-06-03 13:41:05 +0200532 the stack if an interrupt occurred at the wrong time.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800533 We avoid this by disabling interrupts when
534 pc contains a magic address. */
535 if (interrupt_request & CPU_INTERRUPT_HARD
536 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
537 || !(env->uncached_cpsr & CPSR_I))) {
538 env->exception_index = EXCP_IRQ;
539 do_interrupt(env);
540 next_tb = 0;
541 }
David 'Digit' Turner42760382011-05-11 01:48:19 +0200542#elif defined(TARGET_UNICORE32)
543 if (interrupt_request & CPU_INTERRUPT_HARD
544 && !(env->uncached_asr & ASR_I)) {
545 do_interrupt(env);
546 next_tb = 0;
547 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800548#elif defined(TARGET_SH4)
549 if (interrupt_request & CPU_INTERRUPT_HARD) {
550 do_interrupt(env);
551 next_tb = 0;
552 }
553#elif defined(TARGET_ALPHA)
554 if (interrupt_request & CPU_INTERRUPT_HARD) {
555 do_interrupt(env);
556 next_tb = 0;
557 }
558#elif defined(TARGET_CRIS)
559 if (interrupt_request & CPU_INTERRUPT_HARD
David Turner24cd25a2010-09-10 14:22:27 +0200560 && (env->pregs[PR_CCS] & I_FLAG)
561 && !env->locked_irq) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800562 env->exception_index = EXCP_IRQ;
563 do_interrupt(env);
564 next_tb = 0;
565 }
566 if (interrupt_request & CPU_INTERRUPT_NMI
567 && (env->pregs[PR_CCS] & M_FLAG)) {
568 env->exception_index = EXCP_NMI;
569 do_interrupt(env);
570 next_tb = 0;
571 }
572#elif defined(TARGET_M68K)
573 if (interrupt_request & CPU_INTERRUPT_HARD
574 && ((env->sr & SR_I) >> SR_I_SHIFT)
575 < env->pending_level) {
576 /* Real hardware gets the interrupt vector via an
577 IACK cycle at this point. Current emulated
578 hardware doesn't rely on this, so we
579 provide/save the vector when the interrupt is
580 first signalled. */
581 env->exception_index = env->pending_vector;
582 do_interrupt(1);
583 next_tb = 0;
584 }
David 'Digit' Turner42760382011-05-11 01:48:19 +0200585#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
586 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
587 (env->psw.mask & PSW_MASK_EXT)) {
588 do_interrupt(env);
589 next_tb = 0;
590 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800591#endif
David 'Digit' Turner52858642011-06-03 13:41:05 +0200592 /* Don't use the cached interrupt_request value,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800593 do_interrupt may have updated the EXITTB flag. */
594 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
595 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
596 /* ensure that no TB jump will be modified as
597 the program flow was changed */
598 next_tb = 0;
599 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700600 }
601 if (unlikely(env->exit_request)) {
602 env->exit_request = 0;
603 env->exception_index = EXCP_INTERRUPT;
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100604 cpu_loop_exit(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800605 }
David Turner24cd25a2010-09-10 14:22:27 +0200606#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700607 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800608 /* restore flags in standard format */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800609#if defined(TARGET_I386)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700610 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
611 log_cpu_state(env, X86_DUMP_CCOP);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800612 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800613#elif defined(TARGET_M68K)
614 cpu_m68k_flush_flags(env, env->cc_op);
615 env->cc_op = CC_OP_FLAGS;
616 env->sr = (env->sr & 0xffe0)
617 | env->cc_dest | (env->cc_x << 4);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700618 log_cpu_state(env, 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800619#else
David Turner24cd25a2010-09-10 14:22:27 +0200620 log_cpu_state(env, 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800621#endif
622 }
David Turner24cd25a2010-09-10 14:22:27 +0200623#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
David 'Digit' Turner13487772014-02-17 21:16:46 +0100624 spin_lock(&tcg_ctx.tb_ctx.tb_lock);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800625 tb = tb_find_fast();
626 /* Note: we do it here to avoid a gcc bug on Mac OS X when
627 doing it in tb_find_slow */
628 if (tb_invalidated_flag) {
629 /* as some TB could have been invalidated because
630 of memory exceptions while generating the code, we
631 must recompute the hash index here */
632 next_tb = 0;
633 tb_invalidated_flag = 0;
634 }
David Turner24cd25a2010-09-10 14:22:27 +0200635#ifdef CONFIG_DEBUG_EXEC
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700636 qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
637 (long)tb->tc_ptr, tb->pc,
638 lookup_symbol(tb->pc));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800639#endif
640 /* see if we can patch the calling TB. When the TB
641 spans two pages, we cannot safely do a direct
642 jump. */
David Turner24cd25a2010-09-10 14:22:27 +0200643 if (next_tb != 0 && tb->page_addr[1] == -1) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800644 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
645 }
David 'Digit' Turner13487772014-02-17 21:16:46 +0100646 spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700647
648 /* cpu_interrupt might be called while translating the
649 TB, but before it is linked into a potentially
650 infinite loop and becomes env->current_tb. Avoid
651 starting execution if there is a pending interrupt. */
David Turner24cd25a2010-09-10 14:22:27 +0200652 env->current_tb = tb;
653 barrier();
654 if (likely(!env->exit_request)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800655 tc_ptr = tb->tc_ptr;
656 /* execute the generated code */
David 'Digit' Turner2c538c82010-05-10 16:48:20 -0700657#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800658#undef env
659 env = cpu_single_env;
660#define env cpu_single_env
661#endif
662 next_tb = tcg_qemu_tb_exec(tc_ptr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800663 if ((next_tb & 3) == 2) {
664 /* Instruction counter expired. */
665 int insns_left;
666 tb = (TranslationBlock *)(long)(next_tb & ~3);
667 /* Restore PC. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700668 cpu_pc_from_tb(env, tb);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800669 insns_left = env->icount_decr.u32;
670 if (env->icount_extra && insns_left >= 0) {
671 /* Refill decrementer and continue execution. */
672 env->icount_extra += insns_left;
673 if (env->icount_extra > 0xffff) {
674 insns_left = 0xffff;
675 } else {
676 insns_left = env->icount_extra;
677 }
678 env->icount_extra -= insns_left;
679 env->icount_decr.u16.low = insns_left;
680 } else {
681 if (insns_left > 0) {
682 /* Execute remaining instructions. */
683 cpu_exec_nocache(insns_left, tb);
684 }
685 env->exception_index = EXCP_INTERRUPT;
686 next_tb = 0;
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100687 cpu_loop_exit(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800688 }
689 }
690 }
David Turner24cd25a2010-09-10 14:22:27 +0200691 env->current_tb = NULL;
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800692#ifdef CONFIG_HAX
693 if (hax_enabled() && hax_stop_emulation(env))
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100694 cpu_loop_exit(env);
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800695#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800696 /* reset soft MMU for next block (it can currently
697 only be set by a memory fault) */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800698 } /* for(;;) */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800699 }
700 } /* for(;;) */
701
702
703#if defined(TARGET_I386)
704 /* restore flags in standard format */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700705 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800706#elif defined(TARGET_ARM)
707 /* XXX: Save/restore host fpu exception state?. */
David 'Digit' Turner42760382011-05-11 01:48:19 +0200708#elif defined(TARGET_UNICORE32)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800709#elif defined(TARGET_SPARC)
710#elif defined(TARGET_PPC)
David 'Digit' Turner42760382011-05-11 01:48:19 +0200711#elif defined(TARGET_LM32)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800712#elif defined(TARGET_M68K)
713 cpu_m68k_flush_flags(env, env->cc_op);
714 env->cc_op = CC_OP_FLAGS;
715 env->sr = (env->sr & 0xffe0)
716 | env->cc_dest | (env->cc_x << 4);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700717#elif defined(TARGET_MICROBLAZE)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800718#elif defined(TARGET_MIPS)
719#elif defined(TARGET_SH4)
720#elif defined(TARGET_ALPHA)
721#elif defined(TARGET_CRIS)
David Turner24cd25a2010-09-10 14:22:27 +0200722#elif defined(TARGET_S390X)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800723 /* XXXXX */
724#else
725#error unsupported target CPU
726#endif
727
728 /* restore global registers */
David Turner24cd25a2010-09-10 14:22:27 +0200729 barrier();
730 env = (void *) saved_env_reg;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800731
732 /* fail safe : never use cpu_single_env outside cpu_exec() */
733 cpu_single_env = NULL;
734 return ret;
735}
736
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800737#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
738
739void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
740{
741 CPUX86State *saved_env;
742
743 saved_env = env;
744 env = s;
745 if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
746 selector &= 0xffff;
747 cpu_x86_load_seg_cache(env, seg_reg, selector,
748 (selector << 4), 0xffff, 0);
749 } else {
750 helper_load_seg(seg_reg, selector);
751 }
752 env = saved_env;
753}
754
755void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
756{
757 CPUX86State *saved_env;
758
759 saved_env = env;
760 env = s;
761
762 helper_fsave(ptr, data32);
763
764 env = saved_env;
765}
766
767void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
768{
769 CPUX86State *saved_env;
770
771 saved_env = env;
772 env = s;
773
774 helper_frstor(ptr, data32);
775
776 env = saved_env;
777}
778
779#endif /* TARGET_I386 */
780
781#if !defined(CONFIG_SOFTMMU)
782
783#if defined(TARGET_I386)
David Turner24cd25a2010-09-10 14:22:27 +0200784#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
785#else
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100786#define EXCEPTION_ACTION cpu_loop_exit(env)
David Turner24cd25a2010-09-10 14:22:27 +0200787#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800788
789/* 'pc' is the host PC at which the exception was raised. 'address' is
790 the effective address of the memory exception. 'is_write' is 1 if a
791 write caused the exception and otherwise 0'. 'old_set' is the
792 signal set which should be restored */
793static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
794 int is_write, sigset_t *old_set,
795 void *puc)
796{
797 TranslationBlock *tb;
798 int ret;
799
800 if (cpu_single_env)
801 env = cpu_single_env; /* XXX: find a correct solution for multithread */
802#if defined(DEBUG_SIGNAL)
803 qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
804 pc, address, is_write, *(unsigned long *)old_set);
805#endif
806 /* XXX: locking issue */
807 if (is_write && page_unprotect(h2g(address), pc, puc)) {
808 return 1;
809 }
810
811 /* see if it is an MMU fault */
David Turner24cd25a2010-09-10 14:22:27 +0200812 ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800813 if (ret < 0)
814 return 0; /* not an MMU fault */
815 if (ret == 0)
816 return 1; /* the MMU fault was handled without causing real CPU fault */
817 /* now we have a real cpu fault */
818 tb = tb_find_pc(pc);
819 if (tb) {
820 /* the PC is inside the translated code. It means that we have
821 a virtual CPU fault */
David 'Digit' Turner3e0677d2014-03-07 15:01:06 +0100822 cpu_restore_state(env, pc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800823 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800824
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800825 /* we restore the process signal mask as the sigreturn should
826 do it (XXX: use sigsetjmp) */
827 sigprocmask(SIG_SETMASK, old_set, NULL);
David Turner24cd25a2010-09-10 14:22:27 +0200828 EXCEPTION_ACTION;
829
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800830 /* never comes here */
831 return 1;
832}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800833
834#if defined(__i386__)
835
836#if defined(__APPLE__)
837# include <sys/ucontext.h>
838
839# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
840# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
841# define ERROR_sig(context) ((context)->uc_mcontext->es.err)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700842# define MASK_sig(context) ((context)->uc_sigmask)
David Turner24cd25a2010-09-10 14:22:27 +0200843#elif defined (__NetBSD__)
844# include <ucontext.h>
845
846# define EIP_sig(context) ((context)->uc_mcontext.__gregs[_REG_EIP])
847# define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
848# define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
849# define MASK_sig(context) ((context)->uc_sigmask)
850#elif defined (__FreeBSD__) || defined(__DragonFly__)
851# include <ucontext.h>
852
853# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
854# define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
855# define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
856# define MASK_sig(context) ((context)->uc_sigmask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700857#elif defined(__OpenBSD__)
858# define EIP_sig(context) ((context)->sc_eip)
859# define TRAP_sig(context) ((context)->sc_trapno)
860# define ERROR_sig(context) ((context)->sc_err)
861# define MASK_sig(context) ((context)->sc_mask)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800862#else
863# define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
864# define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
865# define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700866# define MASK_sig(context) ((context)->uc_sigmask)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800867#endif
868
869int cpu_signal_handler(int host_signum, void *pinfo,
870 void *puc)
871{
872 siginfo_t *info = pinfo;
David Turner24cd25a2010-09-10 14:22:27 +0200873#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
874 ucontext_t *uc = puc;
875#elif defined(__OpenBSD__)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700876 struct sigcontext *uc = puc;
877#else
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800878 struct ucontext *uc = puc;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700879#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800880 unsigned long pc;
881 int trapno;
882
883#ifndef REG_EIP
884/* for glibc 2.1 */
885#define REG_EIP EIP
886#define REG_ERR ERR
887#define REG_TRAPNO TRAPNO
888#endif
889 pc = EIP_sig(uc);
890 trapno = TRAP_sig(uc);
891 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
892 trapno == 0xe ?
893 (ERROR_sig(uc) >> 1) & 1 : 0,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700894 &MASK_sig(uc), puc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800895}
896
897#elif defined(__x86_64__)
898
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700899#ifdef __NetBSD__
900#define PC_sig(context) _UC_MACHINE_PC(context)
901#define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
902#define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
903#define MASK_sig(context) ((context)->uc_sigmask)
904#elif defined(__OpenBSD__)
905#define PC_sig(context) ((context)->sc_rip)
906#define TRAP_sig(context) ((context)->sc_trapno)
907#define ERROR_sig(context) ((context)->sc_err)
908#define MASK_sig(context) ((context)->sc_mask)
David Turner24cd25a2010-09-10 14:22:27 +0200909#elif defined (__FreeBSD__) || defined(__DragonFly__)
910#include <ucontext.h>
911
912#define PC_sig(context) (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
913#define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
914#define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
915#define MASK_sig(context) ((context)->uc_sigmask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700916#else
917#define PC_sig(context) ((context)->uc_mcontext.gregs[REG_RIP])
918#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
919#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
920#define MASK_sig(context) ((context)->uc_sigmask)
921#endif
922
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800923int cpu_signal_handler(int host_signum, void *pinfo,
924 void *puc)
925{
926 siginfo_t *info = pinfo;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800927 unsigned long pc;
David Turner24cd25a2010-09-10 14:22:27 +0200928#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700929 ucontext_t *uc = puc;
930#elif defined(__OpenBSD__)
931 struct sigcontext *uc = puc;
932#else
933 struct ucontext *uc = puc;
934#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800935
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700936 pc = PC_sig(uc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800937 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700938 TRAP_sig(uc) == 0xe ?
939 (ERROR_sig(uc) >> 1) & 1 : 0,
940 &MASK_sig(uc), puc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800941}
942
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700943#elif defined(_ARCH_PPC)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800944
945/***********************************************************************
946 * signal context platform-specific definitions
947 * From Wine
948 */
949#ifdef linux
950/* All Registers access - only for local access */
951# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
952/* Gpr Registers access */
953# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
954# define IAR_sig(context) REG_sig(nip, context) /* Program counter */
955# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
956# define CTR_sig(context) REG_sig(ctr, context) /* Count register */
957# define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
958# define LR_sig(context) REG_sig(link, context) /* Link register */
959# define CR_sig(context) REG_sig(ccr, context) /* Condition register */
960/* Float Registers access */
961# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
962# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
963/* Exception Registers access */
964# define DAR_sig(context) REG_sig(dar, context)
965# define DSISR_sig(context) REG_sig(dsisr, context)
966# define TRAP_sig(context) REG_sig(trap, context)
967#endif /* linux */
968
David Turner24cd25a2010-09-10 14:22:27 +0200969#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
970#include <ucontext.h>
971# define IAR_sig(context) ((context)->uc_mcontext.mc_srr0)
972# define MSR_sig(context) ((context)->uc_mcontext.mc_srr1)
973# define CTR_sig(context) ((context)->uc_mcontext.mc_ctr)
974# define XER_sig(context) ((context)->uc_mcontext.mc_xer)
975# define LR_sig(context) ((context)->uc_mcontext.mc_lr)
976# define CR_sig(context) ((context)->uc_mcontext.mc_cr)
977/* Exception Registers access */
978# define DAR_sig(context) ((context)->uc_mcontext.mc_dar)
979# define DSISR_sig(context) ((context)->uc_mcontext.mc_dsisr)
980# define TRAP_sig(context) ((context)->uc_mcontext.mc_exc)
981#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
982
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800983#ifdef __APPLE__
984# include <sys/ucontext.h>
985typedef struct ucontext SIGCONTEXT;
986/* All Registers access - only for local access */
987# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
988# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
989# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
990# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
991/* Gpr Registers access */
992# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
993# define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
994# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
995# define CTR_sig(context) REG_sig(ctr, context)
996# define XER_sig(context) REG_sig(xer, context) /* Link register */
997# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
998# define CR_sig(context) REG_sig(cr, context) /* Condition register */
999/* Float Registers access */
1000# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
1001# define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
1002/* Exception Registers access */
1003# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
1004# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
1005# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1006#endif /* __APPLE__ */
1007
1008int cpu_signal_handler(int host_signum, void *pinfo,
1009 void *puc)
1010{
1011 siginfo_t *info = pinfo;
David Turner24cd25a2010-09-10 14:22:27 +02001012#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1013 ucontext_t *uc = puc;
1014#else
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001015 struct ucontext *uc = puc;
David Turner24cd25a2010-09-10 14:22:27 +02001016#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001017 unsigned long pc;
1018 int is_write;
1019
1020 pc = IAR_sig(uc);
1021 is_write = 0;
1022#if 0
1023 /* ppc 4xx case */
1024 if (DSISR_sig(uc) & 0x00800000)
1025 is_write = 1;
1026#else
1027 if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1028 is_write = 1;
1029#endif
1030 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1031 is_write, &uc->uc_sigmask, puc);
1032}
1033
1034#elif defined(__alpha__)
1035
1036int cpu_signal_handler(int host_signum, void *pinfo,
1037 void *puc)
1038{
1039 siginfo_t *info = pinfo;
1040 struct ucontext *uc = puc;
1041 uint32_t *pc = uc->uc_mcontext.sc_pc;
1042 uint32_t insn = *pc;
1043 int is_write = 0;
1044
1045 /* XXX: need kernel patch to get write flag faster */
1046 switch (insn >> 26) {
1047 case 0x0d: // stw
1048 case 0x0e: // stb
1049 case 0x0f: // stq_u
1050 case 0x24: // stf
1051 case 0x25: // stg
1052 case 0x26: // sts
1053 case 0x27: // stt
1054 case 0x2c: // stl
1055 case 0x2d: // stq
1056 case 0x2e: // stl_c
1057 case 0x2f: // stq_c
1058 is_write = 1;
1059 }
1060
1061 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1062 is_write, &uc->uc_sigmask, puc);
1063}
1064#elif defined(__sparc__)
1065
1066int cpu_signal_handler(int host_signum, void *pinfo,
1067 void *puc)
1068{
1069 siginfo_t *info = pinfo;
1070 int is_write;
1071 uint32_t insn;
David 'Digit' Turner2c538c82010-05-10 16:48:20 -07001072#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001073 uint32_t *regs = (uint32_t *)(info + 1);
1074 void *sigmask = (regs + 20);
1075 /* XXX: is there a standard glibc define ? */
1076 unsigned long pc = regs[1];
1077#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001078#ifdef __linux__
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001079 struct sigcontext *sc = puc;
1080 unsigned long pc = sc->sigc_regs.tpc;
1081 void *sigmask = (void *)sc->sigc_mask;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001082#elif defined(__OpenBSD__)
1083 struct sigcontext *uc = puc;
1084 unsigned long pc = uc->sc_pc;
1085 void *sigmask = (void *)(long)uc->sc_mask;
1086#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001087#endif
1088
1089 /* XXX: need kernel patch to get write flag faster */
1090 is_write = 0;
1091 insn = *(uint32_t *)pc;
1092 if ((insn >> 30) == 3) {
1093 switch((insn >> 19) & 0x3f) {
1094 case 0x05: // stb
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001095 case 0x15: // stba
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001096 case 0x06: // sth
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001097 case 0x16: // stha
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001098 case 0x04: // st
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001099 case 0x14: // sta
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001100 case 0x07: // std
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001101 case 0x17: // stda
1102 case 0x0e: // stx
1103 case 0x1e: // stxa
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001104 case 0x24: // stf
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001105 case 0x34: // stfa
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001106 case 0x27: // stdf
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001107 case 0x37: // stdfa
1108 case 0x26: // stqf
1109 case 0x36: // stqfa
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001110 case 0x25: // stfsr
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001111 case 0x3c: // casa
1112 case 0x3e: // casxa
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001113 is_write = 1;
1114 break;
1115 }
1116 }
1117 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1118 is_write, sigmask, NULL);
1119}
1120
1121#elif defined(__arm__)
1122
1123int cpu_signal_handler(int host_signum, void *pinfo,
1124 void *puc)
1125{
1126 siginfo_t *info = pinfo;
1127 struct ucontext *uc = puc;
1128 unsigned long pc;
1129 int is_write;
1130
1131#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1132 pc = uc->uc_mcontext.gregs[R15];
1133#else
1134 pc = uc->uc_mcontext.arm_pc;
1135#endif
1136 /* XXX: compute is_write */
1137 is_write = 0;
1138 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1139 is_write,
1140 &uc->uc_sigmask, puc);
1141}
1142
1143#elif defined(__mc68000)
1144
1145int cpu_signal_handler(int host_signum, void *pinfo,
1146 void *puc)
1147{
1148 siginfo_t *info = pinfo;
1149 struct ucontext *uc = puc;
1150 unsigned long pc;
1151 int is_write;
1152
1153 pc = uc->uc_mcontext.gregs[16];
1154 /* XXX: compute is_write */
1155 is_write = 0;
1156 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1157 is_write,
1158 &uc->uc_sigmask, puc);
1159}
1160
1161#elif defined(__ia64)
1162
1163#ifndef __ISR_VALID
1164 /* This ought to be in <bits/siginfo.h>... */
1165# define __ISR_VALID 1
1166#endif
1167
1168int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1169{
1170 siginfo_t *info = pinfo;
1171 struct ucontext *uc = puc;
1172 unsigned long ip;
1173 int is_write = 0;
1174
1175 ip = uc->uc_mcontext.sc_ip;
1176 switch (host_signum) {
1177 case SIGILL:
1178 case SIGFPE:
1179 case SIGSEGV:
1180 case SIGBUS:
1181 case SIGTRAP:
1182 if (info->si_code && (info->si_segvflags & __ISR_VALID))
1183 /* ISR.W (write-access) is bit 33: */
1184 is_write = (info->si_isr >> 33) & 1;
1185 break;
1186
1187 default:
1188 break;
1189 }
1190 return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1191 is_write,
David Turner24cd25a2010-09-10 14:22:27 +02001192 (sigset_t *)&uc->uc_sigmask, puc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001193}
1194
1195#elif defined(__s390__)
1196
1197int cpu_signal_handler(int host_signum, void *pinfo,
1198 void *puc)
1199{
1200 siginfo_t *info = pinfo;
1201 struct ucontext *uc = puc;
1202 unsigned long pc;
David Turner24cd25a2010-09-10 14:22:27 +02001203 uint16_t *pinsn;
1204 int is_write = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001205
1206 pc = uc->uc_mcontext.psw.addr;
David Turner24cd25a2010-09-10 14:22:27 +02001207
1208 /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
1209 of the normal 2 arguments. The 3rd argument contains the "int_code"
1210 from the hardware which does in fact contain the is_write value.
1211 The rt signal handler, as far as I can tell, does not give this value
1212 at all. Not that we could get to it from here even if it were. */
1213 /* ??? This is not even close to complete, since it ignores all
1214 of the read-modify-write instructions. */
1215 pinsn = (uint16_t *)pc;
1216 switch (pinsn[0] >> 8) {
1217 case 0x50: /* ST */
1218 case 0x42: /* STC */
1219 case 0x40: /* STH */
1220 is_write = 1;
1221 break;
1222 case 0xc4: /* RIL format insns */
1223 switch (pinsn[0] & 0xf) {
1224 case 0xf: /* STRL */
1225 case 0xb: /* STGRL */
1226 case 0x7: /* STHRL */
1227 is_write = 1;
1228 }
1229 break;
1230 case 0xe3: /* RXY format insns */
1231 switch (pinsn[2] & 0xff) {
1232 case 0x50: /* STY */
1233 case 0x24: /* STG */
1234 case 0x72: /* STCY */
1235 case 0x70: /* STHY */
1236 case 0x8e: /* STPQ */
1237 case 0x3f: /* STRVH */
1238 case 0x3e: /* STRV */
1239 case 0x2f: /* STRVG */
1240 is_write = 1;
1241 }
1242 break;
1243 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001244 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1245 is_write, &uc->uc_sigmask, puc);
1246}
1247
1248#elif defined(__mips__)
1249
1250int cpu_signal_handler(int host_signum, void *pinfo,
1251 void *puc)
1252{
1253 siginfo_t *info = pinfo;
1254 struct ucontext *uc = puc;
1255 greg_t pc = uc->uc_mcontext.pc;
1256 int is_write;
1257
1258 /* XXX: compute is_write */
1259 is_write = 0;
1260 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1261 is_write, &uc->uc_sigmask, puc);
1262}
1263
1264#elif defined(__hppa__)
1265
1266int cpu_signal_handler(int host_signum, void *pinfo,
1267 void *puc)
1268{
1269 struct siginfo *info = pinfo;
1270 struct ucontext *uc = puc;
David Turner24cd25a2010-09-10 14:22:27 +02001271 unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
1272 uint32_t insn = *(uint32_t *)pc;
1273 int is_write = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001274
David Turner24cd25a2010-09-10 14:22:27 +02001275 /* XXX: need kernel patch to get write flag faster. */
1276 switch (insn >> 26) {
1277 case 0x1a: /* STW */
1278 case 0x19: /* STH */
1279 case 0x18: /* STB */
1280 case 0x1b: /* STWM */
1281 is_write = 1;
1282 break;
1283
1284 case 0x09: /* CSTWX, FSTWX, FSTWS */
1285 case 0x0b: /* CSTDX, FSTDX, FSTDS */
1286 /* Distinguish from coprocessor load ... */
1287 is_write = (insn >> 9) & 1;
1288 break;
1289
1290 case 0x03:
1291 switch ((insn >> 6) & 15) {
1292 case 0xa: /* STWS */
1293 case 0x9: /* STHS */
1294 case 0x8: /* STBS */
1295 case 0xe: /* STWAS */
1296 case 0xc: /* STBYS */
1297 is_write = 1;
1298 }
1299 break;
1300 }
1301
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02001302 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
David Turner24cd25a2010-09-10 14:22:27 +02001303 is_write, &uc->uc_sigmask, puc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001304}
1305
1306#else
1307
1308#error host CPU specific signal handler needed
1309
1310#endif
1311
1312#endif /* !defined(CONFIG_SOFTMMU) */