blob: 2f119a94194d8073301b3a9501e69ba2f091f7c8 [file] [log] [blame]
bellard7d132992003-03-06 23:23:54 +00001/*
2 * i386 emulator main execution loop
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard66321a12005-04-06 20:47:48 +00004 * Copyright (c) 2003-2005 Fabrice Bellard
bellard7d132992003-03-06 23:23:54 +00005 *
bellard3ef693a2003-03-23 20:17:16 +00006 * 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.
bellard7d132992003-03-06 23:23:54 +000010 *
bellard3ef693a2003-03-23 20:17:16 +000011 * 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.
bellard7d132992003-03-06 23:23:54 +000015 *
bellard3ef693a2003-03-23 20:17:16 +000016 * You should have received a copy of the GNU Lesser General Public
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
bellard7d132992003-03-06 23:23:54 +000018 */
bellarde4533c72003-06-15 19:51:39 +000019#include "config.h"
bellard93ac68b2003-09-30 20:57:29 +000020#include "exec.h"
bellard956034d2003-04-29 20:40:53 +000021#include "disas.h"
bellard7cb69ca2008-05-10 10:55:51 +000022#include "tcg.h"
aliguori7ba1e612008-11-05 16:04:33 +000023#include "kvm.h"
bellard7d132992003-03-06 23:23:54 +000024
bellardfbf9eeb2004-04-25 21:21:33 +000025#if !defined(CONFIG_SOFTMMU)
26#undef EAX
27#undef ECX
28#undef EDX
29#undef EBX
30#undef ESP
31#undef EBP
32#undef ESI
33#undef EDI
34#undef EIP
35#include <signal.h>
blueswir184778502008-10-26 20:33:16 +000036#ifdef __linux__
bellardfbf9eeb2004-04-25 21:21:33 +000037#include <sys/ucontext.h>
38#endif
blueswir184778502008-10-26 20:33:16 +000039#endif
bellardfbf9eeb2004-04-25 21:21:33 +000040
Juan Quinteladfe5fff2009-07-27 16:12:40 +020041#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
blueswir1572a9d42008-05-17 07:38:10 +000042// Work around ugly bugs in glibc that mangle global register contents
43#undef env
44#define env cpu_single_env
45#endif
46
bellard36bdbe52003-11-19 22:12:02 +000047int tb_invalidated_flag;
48
Juan Quintelaf0667e62009-07-27 16:13:05 +020049//#define CONFIG_DEBUG_EXEC
bellard9de5e442003-03-23 16:49:39 +000050//#define DEBUG_SIGNAL
bellard7d132992003-03-06 23:23:54 +000051
aliguori6a4955a2009-04-24 18:03:20 +000052int qemu_cpu_has_work(CPUState *env)
53{
54 return cpu_has_work(env);
55}
56
bellarde4533c72003-06-15 19:51:39 +000057void cpu_loop_exit(void)
58{
59 longjmp(env->jmp_env, 1);
60}
thsbfed01f2007-06-03 17:44:37 +000061
bellardfbf9eeb2004-04-25 21:21:33 +000062/* exit the current TB from a signal handler. The host registers are
63 restored in a state compatible with the CPU emulator
64 */
ths5fafdf22007-09-16 21:08:06 +000065void cpu_resume_from_signal(CPUState *env1, void *puc)
bellardfbf9eeb2004-04-25 21:21:33 +000066{
67#if !defined(CONFIG_SOFTMMU)
blueswir184778502008-10-26 20:33:16 +000068#ifdef __linux__
bellardfbf9eeb2004-04-25 21:21:33 +000069 struct ucontext *uc = puc;
blueswir184778502008-10-26 20:33:16 +000070#elif defined(__OpenBSD__)
71 struct sigcontext *uc = puc;
72#endif
bellardfbf9eeb2004-04-25 21:21:33 +000073#endif
74
75 env = env1;
76
77 /* XXX: restore cpu registers saved in host registers */
78
79#if !defined(CONFIG_SOFTMMU)
80 if (puc) {
81 /* XXX: use siglongjmp ? */
blueswir184778502008-10-26 20:33:16 +000082#ifdef __linux__
bellardfbf9eeb2004-04-25 21:21:33 +000083 sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
blueswir184778502008-10-26 20:33:16 +000084#elif defined(__OpenBSD__)
85 sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
86#endif
bellardfbf9eeb2004-04-25 21:21:33 +000087 }
88#endif
pbrook9a3ea652008-12-19 12:49:13 +000089 env->exception_index = -1;
bellardfbf9eeb2004-04-25 21:21:33 +000090 longjmp(env->jmp_env, 1);
91}
92
pbrook2e70f6e2008-06-29 01:03:05 +000093/* Execute the code without caching the generated code. An interpreter
94 could be used if available. */
95static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
96{
97 unsigned long next_tb;
98 TranslationBlock *tb;
99
100 /* Should never happen.
101 We only end up here when an existing TB is too long. */
102 if (max_cycles > CF_COUNT_MASK)
103 max_cycles = CF_COUNT_MASK;
104
105 tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
106 max_cycles);
107 env->current_tb = tb;
108 /* execute the generated code */
109 next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
110
111 if ((next_tb & 3) == 2) {
112 /* Restore PC. This may happen if async event occurs before
113 the TB starts executing. */
aliguori622ed362008-11-18 19:36:03 +0000114 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000115 }
116 tb_phys_invalidate(tb, -1);
117 tb_free(tb);
118}
119
bellard8a40a182005-11-20 10:35:40 +0000120static TranslationBlock *tb_find_slow(target_ulong pc,
121 target_ulong cs_base,
j_mayerc0686882007-09-20 22:47:42 +0000122 uint64_t flags)
bellard8a40a182005-11-20 10:35:40 +0000123{
124 TranslationBlock *tb, **ptb1;
bellard8a40a182005-11-20 10:35:40 +0000125 unsigned int h;
126 target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
ths3b46e622007-09-17 08:09:54 +0000127
bellard8a40a182005-11-20 10:35:40 +0000128 tb_invalidated_flag = 0;
ths3b46e622007-09-17 08:09:54 +0000129
bellard8a40a182005-11-20 10:35:40 +0000130 /* find translated block using physical mappings */
131 phys_pc = get_phys_addr_code(env, pc);
132 phys_page1 = phys_pc & TARGET_PAGE_MASK;
133 phys_page2 = -1;
134 h = tb_phys_hash_func(phys_pc);
135 ptb1 = &tb_phys_hash[h];
136 for(;;) {
137 tb = *ptb1;
138 if (!tb)
139 goto not_found;
ths5fafdf22007-09-16 21:08:06 +0000140 if (tb->pc == pc &&
bellard8a40a182005-11-20 10:35:40 +0000141 tb->page_addr[0] == phys_page1 &&
ths5fafdf22007-09-16 21:08:06 +0000142 tb->cs_base == cs_base &&
bellard8a40a182005-11-20 10:35:40 +0000143 tb->flags == flags) {
144 /* check next page if needed */
145 if (tb->page_addr[1] != -1) {
ths5fafdf22007-09-16 21:08:06 +0000146 virt_page2 = (pc & TARGET_PAGE_MASK) +
bellard8a40a182005-11-20 10:35:40 +0000147 TARGET_PAGE_SIZE;
148 phys_page2 = get_phys_addr_code(env, virt_page2);
149 if (tb->page_addr[1] == phys_page2)
150 goto found;
151 } else {
152 goto found;
153 }
154 }
155 ptb1 = &tb->phys_hash_next;
156 }
157 not_found:
pbrook2e70f6e2008-06-29 01:03:05 +0000158 /* if no translated code available, then translate it now */
159 tb = tb_gen_code(env, pc, cs_base, flags, 0);
ths3b46e622007-09-17 08:09:54 +0000160
bellard8a40a182005-11-20 10:35:40 +0000161 found:
bellard8a40a182005-11-20 10:35:40 +0000162 /* we add the TB in the virtual pc hash table */
163 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
bellard8a40a182005-11-20 10:35:40 +0000164 return tb;
165}
166
167static inline TranslationBlock *tb_find_fast(void)
168{
169 TranslationBlock *tb;
170 target_ulong cs_base, pc;
aliguori6b917542008-11-18 19:46:41 +0000171 int flags;
bellard8a40a182005-11-20 10:35:40 +0000172
173 /* we record a subset of the CPU state. It will
174 always be the same before a given translated block
175 is executed. */
aliguori6b917542008-11-18 19:46:41 +0000176 cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
bellardbce61842008-02-01 22:18:51 +0000177 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
ths551bd272008-07-03 17:57:36 +0000178 if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
179 tb->flags != flags)) {
bellard8a40a182005-11-20 10:35:40 +0000180 tb = tb_find_slow(pc, cs_base, flags);
181 }
182 return tb;
183}
184
aliguoridde23672008-11-18 20:50:36 +0000185static CPUDebugExcpHandler *debug_excp_handler;
186
187CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
188{
189 CPUDebugExcpHandler *old_handler = debug_excp_handler;
190
191 debug_excp_handler = handler;
192 return old_handler;
193}
194
aliguori6e140f22008-11-18 20:37:55 +0000195static void cpu_handle_debug_exception(CPUState *env)
196{
197 CPUWatchpoint *wp;
198
199 if (!env->watchpoint_hit)
Blue Swirl72cf2d42009-09-12 07:36:22 +0000200 QTAILQ_FOREACH(wp, &env->watchpoints, entry)
aliguori6e140f22008-11-18 20:37:55 +0000201 wp->flags &= ~BP_WATCHPOINT_HIT;
aliguoridde23672008-11-18 20:50:36 +0000202
203 if (debug_excp_handler)
204 debug_excp_handler(env);
aliguori6e140f22008-11-18 20:37:55 +0000205}
206
bellard7d132992003-03-06 23:23:54 +0000207/* main execution loop */
208
bellarde4533c72003-06-15 19:51:39 +0000209int cpu_exec(CPUState *env1)
bellard7d132992003-03-06 23:23:54 +0000210{
pbrook1057eaa2007-02-04 13:37:44 +0000211#define DECLARE_HOST_REGS 1
212#include "hostregs_helper.h"
bellard8a40a182005-11-20 10:35:40 +0000213 int ret, interrupt_request;
bellard8a40a182005-11-20 10:35:40 +0000214 TranslationBlock *tb;
bellardc27004e2005-01-03 23:35:10 +0000215 uint8_t *tc_ptr;
pbrookd5975362008-06-07 20:50:51 +0000216 unsigned long next_tb;
bellard8c6939c2003-06-09 15:28:00 +0000217
thsbfed01f2007-06-03 17:44:37 +0000218 if (cpu_halted(env1) == EXCP_HALTED)
219 return EXCP_HALTED;
bellard5a1e3cf2005-11-23 21:02:53 +0000220
ths5fafdf22007-09-16 21:08:06 +0000221 cpu_single_env = env1;
bellard6a00d602005-11-21 23:25:50 +0000222
bellard7d132992003-03-06 23:23:54 +0000223 /* first we save global registers */
pbrook1057eaa2007-02-04 13:37:44 +0000224#define SAVE_HOST_REGS 1
225#include "hostregs_helper.h"
bellardc27004e2005-01-03 23:35:10 +0000226 env = env1;
bellarde4533c72003-06-15 19:51:39 +0000227
thsecb644f2007-06-03 18:45:53 +0000228#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000229 /* put eflags in CPU temporary format */
bellardfc2b4c42003-03-29 16:52:44 +0000230 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
231 DF = 1 - (2 * ((env->eflags >> 10) & 1));
bellard9de5e442003-03-23 16:49:39 +0000232 CC_OP = CC_OP_EFLAGS;
bellardfc2b4c42003-03-29 16:52:44 +0000233 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellard93ac68b2003-09-30 20:57:29 +0000234#elif defined(TARGET_SPARC)
pbrooke6e59062006-10-22 00:18:54 +0000235#elif defined(TARGET_M68K)
236 env->cc_op = CC_OP_FLAGS;
237 env->cc_dest = env->sr & 0xf;
238 env->cc_x = (env->sr >> 4) & 1;
thsecb644f2007-06-03 18:45:53 +0000239#elif defined(TARGET_ALPHA)
240#elif defined(TARGET_ARM)
241#elif defined(TARGET_PPC)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200242#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000243#elif defined(TARGET_MIPS)
bellardfdf9b3e2006-04-27 21:07:38 +0000244#elif defined(TARGET_SH4)
thsf1ccf902007-10-08 13:16:14 +0000245#elif defined(TARGET_CRIS)
Alexander Graf10ec5112009-12-05 12:44:21 +0100246#elif defined(TARGET_S390X)
bellardfdf9b3e2006-04-27 21:07:38 +0000247 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000248#else
249#error unsupported target CPU
250#endif
bellard3fb2ded2003-06-24 13:22:59 +0000251 env->exception_index = -1;
bellard9d27abd2003-05-10 13:13:54 +0000252
bellard7d132992003-03-06 23:23:54 +0000253 /* prepare setjmp context for exception handling */
bellard3fb2ded2003-06-24 13:22:59 +0000254 for(;;) {
255 if (setjmp(env->jmp_env) == 0) {
Juan Quinteladfe5fff2009-07-27 16:12:40 +0200256#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
blueswir19ddff3d2009-04-04 07:41:20 +0000257#undef env
258 env = cpu_single_env;
259#define env cpu_single_env
260#endif
bellardee8b7022004-02-03 23:35:10 +0000261 env->current_tb = NULL;
bellard3fb2ded2003-06-24 13:22:59 +0000262 /* if an exception is pending, we execute it here */
263 if (env->exception_index >= 0) {
264 if (env->exception_index >= EXCP_INTERRUPT) {
265 /* exit request from the cpu execution loop */
266 ret = env->exception_index;
aliguori6e140f22008-11-18 20:37:55 +0000267 if (ret == EXCP_DEBUG)
268 cpu_handle_debug_exception(env);
bellard3fb2ded2003-06-24 13:22:59 +0000269 break;
aurel3272d239e2009-01-14 19:40:27 +0000270 } else {
271#if defined(CONFIG_USER_ONLY)
bellard3fb2ded2003-06-24 13:22:59 +0000272 /* if user mode only, we simulate a fake exception
ths9f083492006-12-07 18:28:42 +0000273 which will be handled outside the cpu execution
bellard3fb2ded2003-06-24 13:22:59 +0000274 loop */
bellard83479e72003-06-25 16:12:37 +0000275#if defined(TARGET_I386)
ths5fafdf22007-09-16 21:08:06 +0000276 do_interrupt_user(env->exception_index,
277 env->exception_is_int,
278 env->error_code,
bellard3fb2ded2003-06-24 13:22:59 +0000279 env->exception_next_eip);
bellardeba01622008-05-12 12:04:40 +0000280 /* successfully delivered */
281 env->old_exception = -1;
bellard83479e72003-06-25 16:12:37 +0000282#endif
bellard3fb2ded2003-06-24 13:22:59 +0000283 ret = env->exception_index;
284 break;
aurel3272d239e2009-01-14 19:40:27 +0000285#else
bellard83479e72003-06-25 16:12:37 +0000286#if defined(TARGET_I386)
bellard3fb2ded2003-06-24 13:22:59 +0000287 /* simulate a real cpu exception. On i386, it can
288 trigger new exceptions, but we do not handle
289 double or triple faults yet. */
ths5fafdf22007-09-16 21:08:06 +0000290 do_interrupt(env->exception_index,
291 env->exception_is_int,
292 env->error_code,
bellardd05e66d2003-08-20 21:34:35 +0000293 env->exception_next_eip, 0);
ths678dde12007-03-31 20:28:52 +0000294 /* successfully delivered */
295 env->old_exception = -1;
bellardce097762004-01-04 23:53:18 +0000296#elif defined(TARGET_PPC)
297 do_interrupt(env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200298#elif defined(TARGET_MICROBLAZE)
299 do_interrupt(env);
bellard6af0bf92005-07-02 14:58:51 +0000300#elif defined(TARGET_MIPS)
301 do_interrupt(env);
bellarde95c8d52004-09-30 22:22:08 +0000302#elif defined(TARGET_SPARC)
blueswir1f2bc7e72008-05-27 17:35:30 +0000303 do_interrupt(env);
bellardb5ff1b32005-11-26 10:38:39 +0000304#elif defined(TARGET_ARM)
305 do_interrupt(env);
bellardfdf9b3e2006-04-27 21:07:38 +0000306#elif defined(TARGET_SH4)
307 do_interrupt(env);
j_mayereddf68a2007-04-05 07:22:49 +0000308#elif defined(TARGET_ALPHA)
309 do_interrupt(env);
thsf1ccf902007-10-08 13:16:14 +0000310#elif defined(TARGET_CRIS)
311 do_interrupt(env);
pbrook06338792007-05-23 19:58:11 +0000312#elif defined(TARGET_M68K)
313 do_interrupt(0);
bellard83479e72003-06-25 16:12:37 +0000314#endif
aurel3272d239e2009-01-14 19:40:27 +0000315#endif
bellard3fb2ded2003-06-24 13:22:59 +0000316 }
317 env->exception_index = -1;
ths5fafdf22007-09-16 21:08:06 +0000318 }
bellard9df217a2005-02-10 22:05:51 +0000319
aliguori7ba1e612008-11-05 16:04:33 +0000320 if (kvm_enabled()) {
aliguoribecfc392008-11-10 15:55:14 +0000321 kvm_cpu_exec(env);
322 longjmp(env->jmp_env, 1);
aliguori7ba1e612008-11-05 16:04:33 +0000323 }
324
blueswir1b5fc09a2008-05-04 06:38:18 +0000325 next_tb = 0; /* force lookup of first TB */
bellard3fb2ded2003-06-24 13:22:59 +0000326 for(;;) {
bellard68a79312003-06-30 13:12:32 +0000327 interrupt_request = env->interrupt_request;
malce1638bd2008-11-06 18:54:46 +0000328 if (unlikely(interrupt_request)) {
329 if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
330 /* Mask out external interrupts for this step. */
331 interrupt_request &= ~(CPU_INTERRUPT_HARD |
332 CPU_INTERRUPT_FIQ |
333 CPU_INTERRUPT_SMI |
334 CPU_INTERRUPT_NMI);
335 }
pbrook6658ffb2007-03-16 23:58:11 +0000336 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
337 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
338 env->exception_index = EXCP_DEBUG;
339 cpu_loop_exit();
340 }
balroga90b7312007-05-01 01:28:01 +0000341#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200342 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
343 defined(TARGET_MICROBLAZE)
balroga90b7312007-05-01 01:28:01 +0000344 if (interrupt_request & CPU_INTERRUPT_HALT) {
345 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
346 env->halted = 1;
347 env->exception_index = EXCP_HLT;
348 cpu_loop_exit();
349 }
350#endif
bellard68a79312003-06-30 13:12:32 +0000351#if defined(TARGET_I386)
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300352 if (interrupt_request & CPU_INTERRUPT_INIT) {
353 svm_check_intercept(SVM_EXIT_INIT);
354 do_cpu_init(env);
355 env->exception_index = EXCP_HALTED;
356 cpu_loop_exit();
357 } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
358 do_cpu_sipi(env);
359 } else if (env->hflags2 & HF2_GIF_MASK) {
bellarddb620f42008-06-04 17:02:19 +0000360 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
361 !(env->hflags & HF_SMM_MASK)) {
362 svm_check_intercept(SVM_EXIT_SMI);
363 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
364 do_smm_enter();
365 next_tb = 0;
366 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
367 !(env->hflags2 & HF2_NMI_MASK)) {
368 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
369 env->hflags2 |= HF2_NMI_MASK;
370 do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
371 next_tb = 0;
Huang Ying79c4f6b2009-06-23 10:05:14 +0800372 } else if (interrupt_request & CPU_INTERRUPT_MCE) {
373 env->interrupt_request &= ~CPU_INTERRUPT_MCE;
374 do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
375 next_tb = 0;
bellarddb620f42008-06-04 17:02:19 +0000376 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
377 (((env->hflags2 & HF2_VINTR_MASK) &&
378 (env->hflags2 & HF2_HIF_MASK)) ||
379 (!(env->hflags2 & HF2_VINTR_MASK) &&
380 (env->eflags & IF_MASK &&
381 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
382 int intno;
383 svm_check_intercept(SVM_EXIT_INTR);
384 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
385 intno = cpu_get_pic_interrupt(env);
aliguori93fcfe32009-01-15 22:34:14 +0000386 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
Juan Quinteladfe5fff2009-07-27 16:12:40 +0200387#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
blueswir19ddff3d2009-04-04 07:41:20 +0000388#undef env
389 env = cpu_single_env;
390#define env cpu_single_env
391#endif
bellarddb620f42008-06-04 17:02:19 +0000392 do_interrupt(intno, 0, 0, 0, 1);
393 /* ensure that no TB jump will be modified as
394 the program flow was changed */
395 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000396#if !defined(CONFIG_USER_ONLY)
bellarddb620f42008-06-04 17:02:19 +0000397 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
398 (env->eflags & IF_MASK) &&
399 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
400 int intno;
401 /* FIXME: this should respect TPR */
402 svm_check_intercept(SVM_EXIT_VINTR);
bellarddb620f42008-06-04 17:02:19 +0000403 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
aliguori93fcfe32009-01-15 22:34:14 +0000404 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
bellarddb620f42008-06-04 17:02:19 +0000405 do_interrupt(intno, 0, 0, 0, 1);
aurel32d40c54d2008-12-13 12:33:02 +0000406 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
bellarddb620f42008-06-04 17:02:19 +0000407 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000408#endif
bellarddb620f42008-06-04 17:02:19 +0000409 }
bellard68a79312003-06-30 13:12:32 +0000410 }
bellardce097762004-01-04 23:53:18 +0000411#elif defined(TARGET_PPC)
bellard9fddaa02004-05-21 12:59:32 +0000412#if 0
413 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
Blue Swirld84bda42009-11-07 10:36:04 +0000414 cpu_reset(env);
bellard9fddaa02004-05-21 12:59:32 +0000415 }
416#endif
j_mayer47103572007-03-30 09:38:04 +0000417 if (interrupt_request & CPU_INTERRUPT_HARD) {
j_mayere9df0142007-04-09 22:45:36 +0000418 ppc_hw_interrupt(env);
419 if (env->pending_interrupts == 0)
420 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
blueswir1b5fc09a2008-05-04 06:38:18 +0000421 next_tb = 0;
bellardce097762004-01-04 23:53:18 +0000422 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200423#elif defined(TARGET_MICROBLAZE)
424 if ((interrupt_request & CPU_INTERRUPT_HARD)
425 && (env->sregs[SR_MSR] & MSR_IE)
426 && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
427 && !(env->iflags & (D_FLAG | IMM_FLAG))) {
428 env->exception_index = EXCP_IRQ;
429 do_interrupt(env);
430 next_tb = 0;
431 }
bellard6af0bf92005-07-02 14:58:51 +0000432#elif defined(TARGET_MIPS)
433 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
ths24c7b0e2007-03-30 16:44:54 +0000434 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
bellard6af0bf92005-07-02 14:58:51 +0000435 (env->CP0_Status & (1 << CP0St_IE)) &&
ths24c7b0e2007-03-30 16:44:54 +0000436 !(env->CP0_Status & (1 << CP0St_EXL)) &&
437 !(env->CP0_Status & (1 << CP0St_ERL)) &&
bellard6af0bf92005-07-02 14:58:51 +0000438 !(env->hflags & MIPS_HFLAG_DM)) {
439 /* Raise it */
440 env->exception_index = EXCP_EXT_INTERRUPT;
441 env->error_code = 0;
442 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000443 next_tb = 0;
bellard6af0bf92005-07-02 14:58:51 +0000444 }
bellarde95c8d52004-09-30 22:22:08 +0000445#elif defined(TARGET_SPARC)
Igor V. Kovalenkod532b262010-01-07 23:28:31 +0300446 if (interrupt_request & CPU_INTERRUPT_HARD) {
447 if (cpu_interrupts_enabled(env) &&
448 env->interrupt_index > 0) {
449 int pil = env->interrupt_index & 0xf;
450 int type = env->interrupt_index & 0xf0;
bellard66321a12005-04-06 20:47:48 +0000451
Igor V. Kovalenkod532b262010-01-07 23:28:31 +0300452 if (((type == TT_EXTINT) &&
453 cpu_pil_allowed(env, pil)) ||
454 type != TT_EXTINT) {
455 env->exception_index = env->interrupt_index;
456 do_interrupt(env);
457 next_tb = 0;
458 }
459 }
bellarde95c8d52004-09-30 22:22:08 +0000460 } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
461 //do_interrupt(0, 0, 0, 0, 0);
462 env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
balroga90b7312007-05-01 01:28:01 +0000463 }
bellardb5ff1b32005-11-26 10:38:39 +0000464#elif defined(TARGET_ARM)
465 if (interrupt_request & CPU_INTERRUPT_FIQ
466 && !(env->uncached_cpsr & CPSR_F)) {
467 env->exception_index = EXCP_FIQ;
468 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000469 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000470 }
pbrook9ee6e8b2007-11-11 00:04:49 +0000471 /* ARMv7-M interrupt return works by loading a magic value
472 into the PC. On real hardware the load causes the
473 return to occur. The qemu implementation performs the
474 jump normally, then does the exception return when the
475 CPU tries to execute code at the magic address.
476 This will cause the magic PC value to be pushed to
477 the stack if an interrupt occured at the wrong time.
478 We avoid this by disabling interrupts when
479 pc contains a magic address. */
bellardb5ff1b32005-11-26 10:38:39 +0000480 if (interrupt_request & CPU_INTERRUPT_HARD
pbrook9ee6e8b2007-11-11 00:04:49 +0000481 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
482 || !(env->uncached_cpsr & CPSR_I))) {
bellardb5ff1b32005-11-26 10:38:39 +0000483 env->exception_index = EXCP_IRQ;
484 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000485 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000486 }
bellardfdf9b3e2006-04-27 21:07:38 +0000487#elif defined(TARGET_SH4)
thse96e2042007-12-02 06:18:24 +0000488 if (interrupt_request & CPU_INTERRUPT_HARD) {
489 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000490 next_tb = 0;
thse96e2042007-12-02 06:18:24 +0000491 }
j_mayereddf68a2007-04-05 07:22:49 +0000492#elif defined(TARGET_ALPHA)
493 if (interrupt_request & CPU_INTERRUPT_HARD) {
494 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000495 next_tb = 0;
j_mayereddf68a2007-04-05 07:22:49 +0000496 }
thsf1ccf902007-10-08 13:16:14 +0000497#elif defined(TARGET_CRIS)
edgar_igl1b1a38b2008-06-09 23:18:06 +0000498 if (interrupt_request & CPU_INTERRUPT_HARD
499 && (env->pregs[PR_CCS] & I_FLAG)) {
500 env->exception_index = EXCP_IRQ;
501 do_interrupt(env);
502 next_tb = 0;
503 }
504 if (interrupt_request & CPU_INTERRUPT_NMI
505 && (env->pregs[PR_CCS] & M_FLAG)) {
506 env->exception_index = EXCP_NMI;
thsf1ccf902007-10-08 13:16:14 +0000507 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000508 next_tb = 0;
thsf1ccf902007-10-08 13:16:14 +0000509 }
pbrook06338792007-05-23 19:58:11 +0000510#elif defined(TARGET_M68K)
511 if (interrupt_request & CPU_INTERRUPT_HARD
512 && ((env->sr & SR_I) >> SR_I_SHIFT)
513 < env->pending_level) {
514 /* Real hardware gets the interrupt vector via an
515 IACK cycle at this point. Current emulated
516 hardware doesn't rely on this, so we
517 provide/save the vector when the interrupt is
518 first signalled. */
519 env->exception_index = env->pending_vector;
520 do_interrupt(1);
blueswir1b5fc09a2008-05-04 06:38:18 +0000521 next_tb = 0;
pbrook06338792007-05-23 19:58:11 +0000522 }
bellard68a79312003-06-30 13:12:32 +0000523#endif
bellard9d050952006-05-22 22:03:52 +0000524 /* Don't use the cached interupt_request value,
525 do_interrupt may have updated the EXITTB flag. */
bellardb5ff1b32005-11-26 10:38:39 +0000526 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
bellardbf3e8bf2004-02-16 21:58:54 +0000527 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
528 /* ensure that no TB jump will be modified as
529 the program flow was changed */
blueswir1b5fc09a2008-05-04 06:38:18 +0000530 next_tb = 0;
bellardbf3e8bf2004-02-16 21:58:54 +0000531 }
aurel32be214e62009-03-06 21:48:00 +0000532 }
533 if (unlikely(env->exit_request)) {
534 env->exit_request = 0;
535 env->exception_index = EXCP_INTERRUPT;
536 cpu_loop_exit();
bellard3fb2ded2003-06-24 13:22:59 +0000537 }
Juan Quintelaf0667e62009-07-27 16:13:05 +0200538#ifdef CONFIG_DEBUG_EXEC
aliguori8fec2b82009-01-15 22:36:53 +0000539 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
bellard3fb2ded2003-06-24 13:22:59 +0000540 /* restore flags in standard format */
thsecb644f2007-06-03 18:45:53 +0000541#if defined(TARGET_I386)
pbrooka7812ae2008-11-17 14:43:54 +0000542 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
aliguori93fcfe32009-01-15 22:34:14 +0000543 log_cpu_state(env, X86_DUMP_CCOP);
bellard3fb2ded2003-06-24 13:22:59 +0000544 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellarde4533c72003-06-15 19:51:39 +0000545#elif defined(TARGET_ARM)
aliguori93fcfe32009-01-15 22:34:14 +0000546 log_cpu_state(env, 0);
bellard93ac68b2003-09-30 20:57:29 +0000547#elif defined(TARGET_SPARC)
aliguori93fcfe32009-01-15 22:34:14 +0000548 log_cpu_state(env, 0);
bellard67867302003-11-23 17:05:30 +0000549#elif defined(TARGET_PPC)
aliguori93fcfe32009-01-15 22:34:14 +0000550 log_cpu_state(env, 0);
pbrooke6e59062006-10-22 00:18:54 +0000551#elif defined(TARGET_M68K)
552 cpu_m68k_flush_flags(env, env->cc_op);
553 env->cc_op = CC_OP_FLAGS;
554 env->sr = (env->sr & 0xffe0)
555 | env->cc_dest | (env->cc_x << 4);
aliguori93fcfe32009-01-15 22:34:14 +0000556 log_cpu_state(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200557#elif defined(TARGET_MICROBLAZE)
558 log_cpu_state(env, 0);
bellard6af0bf92005-07-02 14:58:51 +0000559#elif defined(TARGET_MIPS)
aliguori93fcfe32009-01-15 22:34:14 +0000560 log_cpu_state(env, 0);
bellardfdf9b3e2006-04-27 21:07:38 +0000561#elif defined(TARGET_SH4)
aliguori93fcfe32009-01-15 22:34:14 +0000562 log_cpu_state(env, 0);
j_mayereddf68a2007-04-05 07:22:49 +0000563#elif defined(TARGET_ALPHA)
aliguori93fcfe32009-01-15 22:34:14 +0000564 log_cpu_state(env, 0);
thsf1ccf902007-10-08 13:16:14 +0000565#elif defined(TARGET_CRIS)
aliguori93fcfe32009-01-15 22:34:14 +0000566 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000567#else
ths5fafdf22007-09-16 21:08:06 +0000568#error unsupported target CPU
bellarde4533c72003-06-15 19:51:39 +0000569#endif
bellard3fb2ded2003-06-24 13:22:59 +0000570 }
bellard7d132992003-03-06 23:23:54 +0000571#endif
pbrookd5975362008-06-07 20:50:51 +0000572 spin_lock(&tb_lock);
bellard8a40a182005-11-20 10:35:40 +0000573 tb = tb_find_fast();
pbrookd5975362008-06-07 20:50:51 +0000574 /* Note: we do it here to avoid a gcc bug on Mac OS X when
575 doing it in tb_find_slow */
576 if (tb_invalidated_flag) {
577 /* as some TB could have been invalidated because
578 of memory exceptions while generating the code, we
579 must recompute the hash index here */
580 next_tb = 0;
pbrook2e70f6e2008-06-29 01:03:05 +0000581 tb_invalidated_flag = 0;
pbrookd5975362008-06-07 20:50:51 +0000582 }
Juan Quintelaf0667e62009-07-27 16:13:05 +0200583#ifdef CONFIG_DEBUG_EXEC
aliguori93fcfe32009-01-15 22:34:14 +0000584 qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
585 (long)tb->tc_ptr, tb->pc,
586 lookup_symbol(tb->pc));
bellard9d27abd2003-05-10 13:13:54 +0000587#endif
bellard8a40a182005-11-20 10:35:40 +0000588 /* see if we can patch the calling TB. When the TB
589 spans two pages, we cannot safely do a direct
590 jump. */
Paolo Bonzini040f2fb2010-01-15 08:56:36 +0100591 if (next_tb != 0 && tb->page_addr[1] == -1) {
blueswir1b5fc09a2008-05-04 06:38:18 +0000592 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
bellard3fb2ded2003-06-24 13:22:59 +0000593 }
pbrookd5975362008-06-07 20:50:51 +0000594 spin_unlock(&tb_lock);
bellard83479e72003-06-25 16:12:37 +0000595 env->current_tb = tb;
malc55e8b852008-11-04 14:18:13 +0000596
597 /* cpu_interrupt might be called while translating the
598 TB, but before it is linked into a potentially
599 infinite loop and becomes env->current_tb. Avoid
600 starting execution if there is a pending interrupt. */
aurel32be214e62009-03-06 21:48:00 +0000601 if (unlikely (env->exit_request))
malc55e8b852008-11-04 14:18:13 +0000602 env->current_tb = NULL;
603
pbrook2e70f6e2008-06-29 01:03:05 +0000604 while (env->current_tb) {
605 tc_ptr = tb->tc_ptr;
bellard3fb2ded2003-06-24 13:22:59 +0000606 /* execute the generated code */
Juan Quinteladfe5fff2009-07-27 16:12:40 +0200607#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
blueswir1572a9d42008-05-17 07:38:10 +0000608#undef env
pbrook2e70f6e2008-06-29 01:03:05 +0000609 env = cpu_single_env;
blueswir1572a9d42008-05-17 07:38:10 +0000610#define env cpu_single_env
611#endif
pbrook2e70f6e2008-06-29 01:03:05 +0000612 next_tb = tcg_qemu_tb_exec(tc_ptr);
613 env->current_tb = NULL;
614 if ((next_tb & 3) == 2) {
thsbf20dc02008-06-30 17:22:19 +0000615 /* Instruction counter expired. */
pbrook2e70f6e2008-06-29 01:03:05 +0000616 int insns_left;
617 tb = (TranslationBlock *)(long)(next_tb & ~3);
618 /* Restore PC. */
aliguori622ed362008-11-18 19:36:03 +0000619 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000620 insns_left = env->icount_decr.u32;
621 if (env->icount_extra && insns_left >= 0) {
622 /* Refill decrementer and continue execution. */
623 env->icount_extra += insns_left;
624 if (env->icount_extra > 0xffff) {
625 insns_left = 0xffff;
626 } else {
627 insns_left = env->icount_extra;
628 }
629 env->icount_extra -= insns_left;
630 env->icount_decr.u16.low = insns_left;
631 } else {
632 if (insns_left > 0) {
633 /* Execute remaining instructions. */
634 cpu_exec_nocache(insns_left, tb);
635 }
636 env->exception_index = EXCP_INTERRUPT;
637 next_tb = 0;
638 cpu_loop_exit();
639 }
640 }
641 }
bellard4cbf74b2003-08-10 21:48:43 +0000642 /* reset soft MMU for next block (it can currently
643 only be set by a memory fault) */
ths50a518e2007-06-03 18:52:15 +0000644 } /* for(;;) */
bellard7d132992003-03-06 23:23:54 +0000645 }
bellard3fb2ded2003-06-24 13:22:59 +0000646 } /* for(;;) */
647
bellard7d132992003-03-06 23:23:54 +0000648
bellarde4533c72003-06-15 19:51:39 +0000649#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000650 /* restore flags in standard format */
pbrooka7812ae2008-11-17 14:43:54 +0000651 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
bellarde4533c72003-06-15 19:51:39 +0000652#elif defined(TARGET_ARM)
bellardb7bcbe92005-02-22 19:27:29 +0000653 /* XXX: Save/restore host fpu exception state?. */
bellard93ac68b2003-09-30 20:57:29 +0000654#elif defined(TARGET_SPARC)
bellard67867302003-11-23 17:05:30 +0000655#elif defined(TARGET_PPC)
pbrooke6e59062006-10-22 00:18:54 +0000656#elif defined(TARGET_M68K)
657 cpu_m68k_flush_flags(env, env->cc_op);
658 env->cc_op = CC_OP_FLAGS;
659 env->sr = (env->sr & 0xffe0)
660 | env->cc_dest | (env->cc_x << 4);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200661#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000662#elif defined(TARGET_MIPS)
bellardfdf9b3e2006-04-27 21:07:38 +0000663#elif defined(TARGET_SH4)
j_mayereddf68a2007-04-05 07:22:49 +0000664#elif defined(TARGET_ALPHA)
thsf1ccf902007-10-08 13:16:14 +0000665#elif defined(TARGET_CRIS)
Alexander Graf10ec5112009-12-05 12:44:21 +0100666#elif defined(TARGET_S390X)
bellardfdf9b3e2006-04-27 21:07:38 +0000667 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000668#else
669#error unsupported target CPU
670#endif
pbrook1057eaa2007-02-04 13:37:44 +0000671
672 /* restore global registers */
pbrook1057eaa2007-02-04 13:37:44 +0000673#include "hostregs_helper.h"
674
bellard6a00d602005-11-21 23:25:50 +0000675 /* fail safe : never use cpu_single_env outside cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000676 cpu_single_env = NULL;
bellard7d132992003-03-06 23:23:54 +0000677 return ret;
678}
bellard6dbad632003-03-16 18:05:05 +0000679
bellardfbf9eeb2004-04-25 21:21:33 +0000680/* must only be called from the generated code as an exception can be
681 generated */
682void tb_invalidate_page_range(target_ulong start, target_ulong end)
683{
bellarddc5d0b32004-06-22 18:43:30 +0000684 /* XXX: cannot enable it yet because it yields to MMU exception
685 where NIP != read address on PowerPC */
686#if 0
bellardfbf9eeb2004-04-25 21:21:33 +0000687 target_ulong phys_addr;
688 phys_addr = get_phys_addr_code(env, start);
689 tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
bellarddc5d0b32004-06-22 18:43:30 +0000690#endif
bellardfbf9eeb2004-04-25 21:21:33 +0000691}
692
bellard1a18c712003-10-30 01:07:51 +0000693#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
bellarde4533c72003-06-15 19:51:39 +0000694
bellard6dbad632003-03-16 18:05:05 +0000695void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
696{
697 CPUX86State *saved_env;
698
699 saved_env = env;
700 env = s;
bellarda412ac52003-07-26 18:01:40 +0000701 if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
bellarda513fe12003-05-27 23:29:48 +0000702 selector &= 0xffff;
ths5fafdf22007-09-16 21:08:06 +0000703 cpu_x86_load_seg_cache(env, seg_reg, selector,
bellardc27004e2005-01-03 23:35:10 +0000704 (selector << 4), 0xffff, 0);
bellarda513fe12003-05-27 23:29:48 +0000705 } else {
bellard5d975592008-05-12 22:05:33 +0000706 helper_load_seg(seg_reg, selector);
bellarda513fe12003-05-27 23:29:48 +0000707 }
bellard6dbad632003-03-16 18:05:05 +0000708 env = saved_env;
709}
bellard9de5e442003-03-23 16:49:39 +0000710
bellard6f12a2a2007-11-11 22:16:56 +0000711void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
bellardd0a1ffc2003-05-29 20:04:28 +0000712{
713 CPUX86State *saved_env;
714
715 saved_env = env;
716 env = s;
ths3b46e622007-09-17 08:09:54 +0000717
bellard6f12a2a2007-11-11 22:16:56 +0000718 helper_fsave(ptr, data32);
bellardd0a1ffc2003-05-29 20:04:28 +0000719
720 env = saved_env;
721}
722
bellard6f12a2a2007-11-11 22:16:56 +0000723void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
bellardd0a1ffc2003-05-29 20:04:28 +0000724{
725 CPUX86State *saved_env;
726
727 saved_env = env;
728 env = s;
ths3b46e622007-09-17 08:09:54 +0000729
bellard6f12a2a2007-11-11 22:16:56 +0000730 helper_frstor(ptr, data32);
bellardd0a1ffc2003-05-29 20:04:28 +0000731
732 env = saved_env;
733}
734
bellarde4533c72003-06-15 19:51:39 +0000735#endif /* TARGET_I386 */
736
bellard67b915a2004-03-31 23:37:16 +0000737#if !defined(CONFIG_SOFTMMU)
738
bellard3fb2ded2003-06-24 13:22:59 +0000739#if defined(TARGET_I386)
Nathan Froyd0b5c1ce2009-08-10 13:37:36 -0700740#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
741#else
742#define EXCEPTION_ACTION cpu_loop_exit()
743#endif
bellard3fb2ded2003-06-24 13:22:59 +0000744
bellardb56dad12003-05-08 15:38:04 +0000745/* 'pc' is the host PC at which the exception was raised. 'address' is
bellardfd6ce8f2003-05-14 19:00:11 +0000746 the effective address of the memory exception. 'is_write' is 1 if a
747 write caused the exception and otherwise 0'. 'old_set' is the
748 signal set which should be restored */
bellard2b413142003-05-14 23:01:10 +0000749static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
ths5fafdf22007-09-16 21:08:06 +0000750 int is_write, sigset_t *old_set,
bellardbf3e8bf2004-02-16 21:58:54 +0000751 void *puc)
bellard9de5e442003-03-23 16:49:39 +0000752{
bellarda513fe12003-05-27 23:29:48 +0000753 TranslationBlock *tb;
754 int ret;
bellard68a79312003-06-30 13:12:32 +0000755
bellard83479e72003-06-25 16:12:37 +0000756 if (cpu_single_env)
757 env = cpu_single_env; /* XXX: find a correct solution for multithread */
bellardfd6ce8f2003-05-14 19:00:11 +0000758#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000759 qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellardbf3e8bf2004-02-16 21:58:54 +0000760 pc, address, is_write, *(unsigned long *)old_set);
bellard9de5e442003-03-23 16:49:39 +0000761#endif
bellard25eb4482003-05-14 21:50:54 +0000762 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000763 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellardfd6ce8f2003-05-14 19:00:11 +0000764 return 1;
765 }
bellardfbf9eeb2004-04-25 21:21:33 +0000766
bellard3fb2ded2003-06-24 13:22:59 +0000767 /* see if it is an MMU fault */
Nathan Froyd0b5c1ce2009-08-10 13:37:36 -0700768 ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard3fb2ded2003-06-24 13:22:59 +0000769 if (ret < 0)
770 return 0; /* not an MMU fault */
771 if (ret == 0)
772 return 1; /* the MMU fault was handled without causing real CPU fault */
773 /* now we have a real cpu fault */
bellarda513fe12003-05-27 23:29:48 +0000774 tb = tb_find_pc(pc);
775 if (tb) {
bellard9de5e442003-03-23 16:49:39 +0000776 /* the PC is inside the translated code. It means that we have
777 a virtual CPU fault */
bellardbf3e8bf2004-02-16 21:58:54 +0000778 cpu_restore_state(tb, env, pc, puc);
bellard3fb2ded2003-06-24 13:22:59 +0000779 }
bellard3fb2ded2003-06-24 13:22:59 +0000780
bellard68016c62005-02-07 23:12:27 +0000781 /* we restore the process signal mask as the sigreturn should
782 do it (XXX: use sigsetjmp) */
783 sigprocmask(SIG_SETMASK, old_set, NULL);
Nathan Froyd0b5c1ce2009-08-10 13:37:36 -0700784 EXCEPTION_ACTION;
785
aurel32968c74d2008-04-11 04:55:17 +0000786 /* never comes here */
787 return 1;
bellard3fb2ded2003-06-24 13:22:59 +0000788}
bellard9de5e442003-03-23 16:49:39 +0000789
bellard2b413142003-05-14 23:01:10 +0000790#if defined(__i386__)
791
bellardd8ecc0b2007-02-05 21:41:46 +0000792#if defined(__APPLE__)
793# include <sys/ucontext.h>
794
795# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
796# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
797# define ERROR_sig(context) ((context)->uc_mcontext->es.err)
blueswir1d39bb242009-04-10 07:29:34 +0000798# define MASK_sig(context) ((context)->uc_sigmask)
Juergen Lock78cfb072009-10-17 00:34:26 +0200799#elif defined (__NetBSD__)
800# include <ucontext.h>
801
802# define EIP_sig(context) ((context)->uc_mcontext.__gregs[_REG_EIP])
803# define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
804# define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
805# define MASK_sig(context) ((context)->uc_sigmask)
806#elif defined (__FreeBSD__) || defined(__DragonFly__)
807# include <ucontext.h>
808
809# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
810# define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
811# define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
812# define MASK_sig(context) ((context)->uc_sigmask)
blueswir1d39bb242009-04-10 07:29:34 +0000813#elif defined(__OpenBSD__)
814# define EIP_sig(context) ((context)->sc_eip)
815# define TRAP_sig(context) ((context)->sc_trapno)
816# define ERROR_sig(context) ((context)->sc_err)
817# define MASK_sig(context) ((context)->sc_mask)
bellardd8ecc0b2007-02-05 21:41:46 +0000818#else
819# define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
820# define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
821# define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
blueswir1d39bb242009-04-10 07:29:34 +0000822# define MASK_sig(context) ((context)->uc_sigmask)
bellardd8ecc0b2007-02-05 21:41:46 +0000823#endif
824
ths5fafdf22007-09-16 21:08:06 +0000825int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +0000826 void *puc)
bellard9de5e442003-03-23 16:49:39 +0000827{
ths5a7b5422007-01-31 12:16:51 +0000828 siginfo_t *info = pinfo;
Juergen Lock78cfb072009-10-17 00:34:26 +0200829#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
830 ucontext_t *uc = puc;
831#elif defined(__OpenBSD__)
blueswir1d39bb242009-04-10 07:29:34 +0000832 struct sigcontext *uc = puc;
833#else
bellard9de5e442003-03-23 16:49:39 +0000834 struct ucontext *uc = puc;
blueswir1d39bb242009-04-10 07:29:34 +0000835#endif
bellard9de5e442003-03-23 16:49:39 +0000836 unsigned long pc;
bellardbf3e8bf2004-02-16 21:58:54 +0000837 int trapno;
bellard97eb5b12004-02-25 23:19:55 +0000838
bellardd691f662003-03-24 21:58:34 +0000839#ifndef REG_EIP
840/* for glibc 2.1 */
bellardfd6ce8f2003-05-14 19:00:11 +0000841#define REG_EIP EIP
842#define REG_ERR ERR
843#define REG_TRAPNO TRAPNO
bellardd691f662003-03-24 21:58:34 +0000844#endif
bellardd8ecc0b2007-02-05 21:41:46 +0000845 pc = EIP_sig(uc);
846 trapno = TRAP_sig(uc);
bellardec6338b2007-11-08 14:25:03 +0000847 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
848 trapno == 0xe ?
849 (ERROR_sig(uc) >> 1) & 1 : 0,
blueswir1d39bb242009-04-10 07:29:34 +0000850 &MASK_sig(uc), puc);
bellard2b413142003-05-14 23:01:10 +0000851}
852
bellardbc51c5c2004-03-17 23:46:04 +0000853#elif defined(__x86_64__)
854
blueswir1b3efe5c2008-12-05 17:55:45 +0000855#ifdef __NetBSD__
blueswir1d397abb2009-04-10 13:00:29 +0000856#define PC_sig(context) _UC_MACHINE_PC(context)
857#define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
858#define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
859#define MASK_sig(context) ((context)->uc_sigmask)
860#elif defined(__OpenBSD__)
861#define PC_sig(context) ((context)->sc_rip)
862#define TRAP_sig(context) ((context)->sc_trapno)
863#define ERROR_sig(context) ((context)->sc_err)
864#define MASK_sig(context) ((context)->sc_mask)
Juergen Lock78cfb072009-10-17 00:34:26 +0200865#elif defined (__FreeBSD__) || defined(__DragonFly__)
866#include <ucontext.h>
867
868#define PC_sig(context) (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
869#define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
870#define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
871#define MASK_sig(context) ((context)->uc_sigmask)
blueswir1b3efe5c2008-12-05 17:55:45 +0000872#else
blueswir1d397abb2009-04-10 13:00:29 +0000873#define PC_sig(context) ((context)->uc_mcontext.gregs[REG_RIP])
874#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
875#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
876#define MASK_sig(context) ((context)->uc_sigmask)
blueswir1b3efe5c2008-12-05 17:55:45 +0000877#endif
878
ths5a7b5422007-01-31 12:16:51 +0000879int cpu_signal_handler(int host_signum, void *pinfo,
bellardbc51c5c2004-03-17 23:46:04 +0000880 void *puc)
881{
ths5a7b5422007-01-31 12:16:51 +0000882 siginfo_t *info = pinfo;
bellardbc51c5c2004-03-17 23:46:04 +0000883 unsigned long pc;
Juergen Lock78cfb072009-10-17 00:34:26 +0200884#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
blueswir1b3efe5c2008-12-05 17:55:45 +0000885 ucontext_t *uc = puc;
blueswir1d397abb2009-04-10 13:00:29 +0000886#elif defined(__OpenBSD__)
887 struct sigcontext *uc = puc;
blueswir1b3efe5c2008-12-05 17:55:45 +0000888#else
889 struct ucontext *uc = puc;
890#endif
bellardbc51c5c2004-03-17 23:46:04 +0000891
blueswir1d397abb2009-04-10 13:00:29 +0000892 pc = PC_sig(uc);
ths5fafdf22007-09-16 21:08:06 +0000893 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
blueswir1d397abb2009-04-10 13:00:29 +0000894 TRAP_sig(uc) == 0xe ?
895 (ERROR_sig(uc) >> 1) & 1 : 0,
896 &MASK_sig(uc), puc);
bellardbc51c5c2004-03-17 23:46:04 +0000897}
898
malce58ffeb2009-01-14 18:39:49 +0000899#elif defined(_ARCH_PPC)
bellard2b413142003-05-14 23:01:10 +0000900
bellard83fb7ad2004-07-05 21:25:26 +0000901/***********************************************************************
902 * signal context platform-specific definitions
903 * From Wine
904 */
905#ifdef linux
906/* All Registers access - only for local access */
907# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
908/* Gpr Registers access */
909# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
910# define IAR_sig(context) REG_sig(nip, context) /* Program counter */
911# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
912# define CTR_sig(context) REG_sig(ctr, context) /* Count register */
913# define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
914# define LR_sig(context) REG_sig(link, context) /* Link register */
915# define CR_sig(context) REG_sig(ccr, context) /* Condition register */
916/* Float Registers access */
917# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
918# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
919/* Exception Registers access */
920# define DAR_sig(context) REG_sig(dar, context)
921# define DSISR_sig(context) REG_sig(dsisr, context)
922# define TRAP_sig(context) REG_sig(trap, context)
923#endif /* linux */
924
925#ifdef __APPLE__
926# include <sys/ucontext.h>
927typedef struct ucontext SIGCONTEXT;
928/* All Registers access - only for local access */
929# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
930# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
931# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
932# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
933/* Gpr Registers access */
934# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
935# define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
936# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
937# define CTR_sig(context) REG_sig(ctr, context)
938# define XER_sig(context) REG_sig(xer, context) /* Link register */
939# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
940# define CR_sig(context) REG_sig(cr, context) /* Condition register */
941/* Float Registers access */
942# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
943# define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
944/* Exception Registers access */
945# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
946# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
947# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
948#endif /* __APPLE__ */
949
ths5fafdf22007-09-16 21:08:06 +0000950int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +0000951 void *puc)
bellard2b413142003-05-14 23:01:10 +0000952{
ths5a7b5422007-01-31 12:16:51 +0000953 siginfo_t *info = pinfo;
bellard25eb4482003-05-14 21:50:54 +0000954 struct ucontext *uc = puc;
bellard25eb4482003-05-14 21:50:54 +0000955 unsigned long pc;
bellard25eb4482003-05-14 21:50:54 +0000956 int is_write;
957
bellard83fb7ad2004-07-05 21:25:26 +0000958 pc = IAR_sig(uc);
bellard25eb4482003-05-14 21:50:54 +0000959 is_write = 0;
960#if 0
961 /* ppc 4xx case */
bellard83fb7ad2004-07-05 21:25:26 +0000962 if (DSISR_sig(uc) & 0x00800000)
bellard25eb4482003-05-14 21:50:54 +0000963 is_write = 1;
bellard9de5e442003-03-23 16:49:39 +0000964#else
bellard83fb7ad2004-07-05 21:25:26 +0000965 if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
bellard25eb4482003-05-14 21:50:54 +0000966 is_write = 1;
967#endif
ths5fafdf22007-09-16 21:08:06 +0000968 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +0000969 is_write, &uc->uc_sigmask, puc);
bellard9de5e442003-03-23 16:49:39 +0000970}
bellard2b413142003-05-14 23:01:10 +0000971
bellard2f87c602003-06-02 20:38:09 +0000972#elif defined(__alpha__)
973
ths5fafdf22007-09-16 21:08:06 +0000974int cpu_signal_handler(int host_signum, void *pinfo,
bellard2f87c602003-06-02 20:38:09 +0000975 void *puc)
976{
ths5a7b5422007-01-31 12:16:51 +0000977 siginfo_t *info = pinfo;
bellard2f87c602003-06-02 20:38:09 +0000978 struct ucontext *uc = puc;
979 uint32_t *pc = uc->uc_mcontext.sc_pc;
980 uint32_t insn = *pc;
981 int is_write = 0;
982
bellard8c6939c2003-06-09 15:28:00 +0000983 /* XXX: need kernel patch to get write flag faster */
bellard2f87c602003-06-02 20:38:09 +0000984 switch (insn >> 26) {
985 case 0x0d: // stw
986 case 0x0e: // stb
987 case 0x0f: // stq_u
988 case 0x24: // stf
989 case 0x25: // stg
990 case 0x26: // sts
991 case 0x27: // stt
992 case 0x2c: // stl
993 case 0x2d: // stq
994 case 0x2e: // stl_c
995 case 0x2f: // stq_c
996 is_write = 1;
997 }
998
ths5fafdf22007-09-16 21:08:06 +0000999 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001000 is_write, &uc->uc_sigmask, puc);
bellard2f87c602003-06-02 20:38:09 +00001001}
bellard8c6939c2003-06-09 15:28:00 +00001002#elif defined(__sparc__)
1003
ths5fafdf22007-09-16 21:08:06 +00001004int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001005 void *puc)
bellard8c6939c2003-06-09 15:28:00 +00001006{
ths5a7b5422007-01-31 12:16:51 +00001007 siginfo_t *info = pinfo;
bellard8c6939c2003-06-09 15:28:00 +00001008 int is_write;
1009 uint32_t insn;
Juan Quinteladfe5fff2009-07-27 16:12:40 +02001010#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
blueswir1c9e1e2b2008-05-18 06:40:16 +00001011 uint32_t *regs = (uint32_t *)(info + 1);
1012 void *sigmask = (regs + 20);
bellard8c6939c2003-06-09 15:28:00 +00001013 /* XXX: is there a standard glibc define ? */
blueswir1c9e1e2b2008-05-18 06:40:16 +00001014 unsigned long pc = regs[1];
1015#else
blueswir184778502008-10-26 20:33:16 +00001016#ifdef __linux__
blueswir1c9e1e2b2008-05-18 06:40:16 +00001017 struct sigcontext *sc = puc;
1018 unsigned long pc = sc->sigc_regs.tpc;
1019 void *sigmask = (void *)sc->sigc_mask;
blueswir184778502008-10-26 20:33:16 +00001020#elif defined(__OpenBSD__)
1021 struct sigcontext *uc = puc;
1022 unsigned long pc = uc->sc_pc;
1023 void *sigmask = (void *)(long)uc->sc_mask;
1024#endif
blueswir1c9e1e2b2008-05-18 06:40:16 +00001025#endif
1026
bellard8c6939c2003-06-09 15:28:00 +00001027 /* XXX: need kernel patch to get write flag faster */
1028 is_write = 0;
1029 insn = *(uint32_t *)pc;
1030 if ((insn >> 30) == 3) {
1031 switch((insn >> 19) & 0x3f) {
1032 case 0x05: // stb
Blue Swirld877fa52009-04-25 19:07:16 +00001033 case 0x15: // stba
bellard8c6939c2003-06-09 15:28:00 +00001034 case 0x06: // sth
Blue Swirld877fa52009-04-25 19:07:16 +00001035 case 0x16: // stha
bellard8c6939c2003-06-09 15:28:00 +00001036 case 0x04: // st
Blue Swirld877fa52009-04-25 19:07:16 +00001037 case 0x14: // sta
bellard8c6939c2003-06-09 15:28:00 +00001038 case 0x07: // std
Blue Swirld877fa52009-04-25 19:07:16 +00001039 case 0x17: // stda
1040 case 0x0e: // stx
1041 case 0x1e: // stxa
bellard8c6939c2003-06-09 15:28:00 +00001042 case 0x24: // stf
Blue Swirld877fa52009-04-25 19:07:16 +00001043 case 0x34: // stfa
bellard8c6939c2003-06-09 15:28:00 +00001044 case 0x27: // stdf
Blue Swirld877fa52009-04-25 19:07:16 +00001045 case 0x37: // stdfa
1046 case 0x26: // stqf
1047 case 0x36: // stqfa
bellard8c6939c2003-06-09 15:28:00 +00001048 case 0x25: // stfsr
Blue Swirld877fa52009-04-25 19:07:16 +00001049 case 0x3c: // casa
1050 case 0x3e: // casxa
bellard8c6939c2003-06-09 15:28:00 +00001051 is_write = 1;
1052 break;
1053 }
1054 }
ths5fafdf22007-09-16 21:08:06 +00001055 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001056 is_write, sigmask, NULL);
bellard8c6939c2003-06-09 15:28:00 +00001057}
1058
1059#elif defined(__arm__)
1060
ths5fafdf22007-09-16 21:08:06 +00001061int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001062 void *puc)
bellard8c6939c2003-06-09 15:28:00 +00001063{
ths5a7b5422007-01-31 12:16:51 +00001064 siginfo_t *info = pinfo;
bellard8c6939c2003-06-09 15:28:00 +00001065 struct ucontext *uc = puc;
1066 unsigned long pc;
1067 int is_write;
ths3b46e622007-09-17 08:09:54 +00001068
blueswir148bbf112008-07-08 18:35:02 +00001069#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
balrog5c49b362008-06-02 01:01:18 +00001070 pc = uc->uc_mcontext.gregs[R15];
1071#else
balrog4eee57f2008-05-06 14:47:19 +00001072 pc = uc->uc_mcontext.arm_pc;
balrog5c49b362008-06-02 01:01:18 +00001073#endif
bellard8c6939c2003-06-09 15:28:00 +00001074 /* XXX: compute is_write */
1075 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001076 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellard8c6939c2003-06-09 15:28:00 +00001077 is_write,
pbrookf3a96762006-07-29 19:09:31 +00001078 &uc->uc_sigmask, puc);
bellard8c6939c2003-06-09 15:28:00 +00001079}
1080
bellard38e584a2003-08-10 22:14:22 +00001081#elif defined(__mc68000)
1082
ths5fafdf22007-09-16 21:08:06 +00001083int cpu_signal_handler(int host_signum, void *pinfo,
bellard38e584a2003-08-10 22:14:22 +00001084 void *puc)
1085{
ths5a7b5422007-01-31 12:16:51 +00001086 siginfo_t *info = pinfo;
bellard38e584a2003-08-10 22:14:22 +00001087 struct ucontext *uc = puc;
1088 unsigned long pc;
1089 int is_write;
ths3b46e622007-09-17 08:09:54 +00001090
bellard38e584a2003-08-10 22:14:22 +00001091 pc = uc->uc_mcontext.gregs[16];
1092 /* XXX: compute is_write */
1093 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001094 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellard38e584a2003-08-10 22:14:22 +00001095 is_write,
bellardbf3e8bf2004-02-16 21:58:54 +00001096 &uc->uc_sigmask, puc);
bellard38e584a2003-08-10 22:14:22 +00001097}
1098
bellardb8076a72005-04-07 22:20:31 +00001099#elif defined(__ia64)
1100
1101#ifndef __ISR_VALID
1102 /* This ought to be in <bits/siginfo.h>... */
1103# define __ISR_VALID 1
bellardb8076a72005-04-07 22:20:31 +00001104#endif
1105
ths5a7b5422007-01-31 12:16:51 +00001106int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
bellardb8076a72005-04-07 22:20:31 +00001107{
ths5a7b5422007-01-31 12:16:51 +00001108 siginfo_t *info = pinfo;
bellardb8076a72005-04-07 22:20:31 +00001109 struct ucontext *uc = puc;
1110 unsigned long ip;
1111 int is_write = 0;
1112
1113 ip = uc->uc_mcontext.sc_ip;
1114 switch (host_signum) {
1115 case SIGILL:
1116 case SIGFPE:
1117 case SIGSEGV:
1118 case SIGBUS:
1119 case SIGTRAP:
bellardfd4a43e2006-04-24 20:32:17 +00001120 if (info->si_code && (info->si_segvflags & __ISR_VALID))
bellardb8076a72005-04-07 22:20:31 +00001121 /* ISR.W (write-access) is bit 33: */
1122 is_write = (info->si_isr >> 33) & 1;
1123 break;
1124
1125 default:
1126 break;
1127 }
1128 return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1129 is_write,
1130 &uc->uc_sigmask, puc);
1131}
1132
bellard90cb9492005-07-24 15:11:38 +00001133#elif defined(__s390__)
1134
ths5fafdf22007-09-16 21:08:06 +00001135int cpu_signal_handler(int host_signum, void *pinfo,
bellard90cb9492005-07-24 15:11:38 +00001136 void *puc)
1137{
ths5a7b5422007-01-31 12:16:51 +00001138 siginfo_t *info = pinfo;
bellard90cb9492005-07-24 15:11:38 +00001139 struct ucontext *uc = puc;
1140 unsigned long pc;
1141 int is_write;
ths3b46e622007-09-17 08:09:54 +00001142
bellard90cb9492005-07-24 15:11:38 +00001143 pc = uc->uc_mcontext.psw.addr;
1144 /* XXX: compute is_write */
1145 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001146 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
thsc4b89d12007-05-05 19:23:11 +00001147 is_write, &uc->uc_sigmask, puc);
1148}
1149
1150#elif defined(__mips__)
1151
ths5fafdf22007-09-16 21:08:06 +00001152int cpu_signal_handler(int host_signum, void *pinfo,
thsc4b89d12007-05-05 19:23:11 +00001153 void *puc)
1154{
ths9617efe2007-05-08 21:05:55 +00001155 siginfo_t *info = pinfo;
thsc4b89d12007-05-05 19:23:11 +00001156 struct ucontext *uc = puc;
1157 greg_t pc = uc->uc_mcontext.pc;
1158 int is_write;
ths3b46e622007-09-17 08:09:54 +00001159
thsc4b89d12007-05-05 19:23:11 +00001160 /* XXX: compute is_write */
1161 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001162 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
thsc4b89d12007-05-05 19:23:11 +00001163 is_write, &uc->uc_sigmask, puc);
bellard90cb9492005-07-24 15:11:38 +00001164}
1165
aurel32f54b3f92008-04-12 20:14:54 +00001166#elif defined(__hppa__)
1167
1168int cpu_signal_handler(int host_signum, void *pinfo,
1169 void *puc)
1170{
1171 struct siginfo *info = pinfo;
1172 struct ucontext *uc = puc;
1173 unsigned long pc;
1174 int is_write;
1175
1176 pc = uc->uc_mcontext.sc_iaoq[0];
1177 /* FIXME: compute is_write */
1178 is_write = 0;
1179 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1180 is_write,
1181 &uc->uc_sigmask, puc);
1182}
1183
bellard2b413142003-05-14 23:01:10 +00001184#else
1185
bellard3fb2ded2003-06-24 13:22:59 +00001186#error host CPU specific signal handler needed
bellard2b413142003-05-14 23:01:10 +00001187
1188#endif
bellard67b915a2004-03-31 23:37:16 +00001189
1190#endif /* !defined(CONFIG_SOFTMMU) */