blob: 8734337d6744fa78b69d17c82d5b6bd55d9ac95f [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
17 * License along with this library; if not, write to the Free Software
aurel32fad6cb12009-01-04 22:05:52 +000018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
bellard7d132992003-03-06 23:23:54 +000019 */
bellarde4533c72003-06-15 19:51:39 +000020#include "config.h"
bellard93ac68b2003-09-30 20:57:29 +000021#include "exec.h"
bellard956034d2003-04-29 20:40:53 +000022#include "disas.h"
bellard7cb69ca2008-05-10 10:55:51 +000023#include "tcg.h"
aliguori7ba1e612008-11-05 16:04:33 +000024#include "kvm.h"
bellard7d132992003-03-06 23:23:54 +000025
bellardfbf9eeb2004-04-25 21:21:33 +000026#if !defined(CONFIG_SOFTMMU)
27#undef EAX
28#undef ECX
29#undef EDX
30#undef EBX
31#undef ESP
32#undef EBP
33#undef ESI
34#undef EDI
35#undef EIP
36#include <signal.h>
blueswir184778502008-10-26 20:33:16 +000037#ifdef __linux__
bellardfbf9eeb2004-04-25 21:21:33 +000038#include <sys/ucontext.h>
39#endif
blueswir184778502008-10-26 20:33:16 +000040#endif
bellardfbf9eeb2004-04-25 21:21:33 +000041
blueswir1572a9d42008-05-17 07:38:10 +000042#if defined(__sparc__) && !defined(HOST_SOLARIS)
43// Work around ugly bugs in glibc that mangle global register contents
44#undef env
45#define env cpu_single_env
46#endif
47
bellard36bdbe52003-11-19 22:12:02 +000048int tb_invalidated_flag;
49
bellarddc990652003-03-19 00:00:28 +000050//#define DEBUG_EXEC
bellard9de5e442003-03-23 16:49:39 +000051//#define DEBUG_SIGNAL
bellard7d132992003-03-06 23:23:54 +000052
aliguori6a4955a2009-04-24 18:03:20 +000053int qemu_cpu_has_work(CPUState *env)
54{
55 return cpu_has_work(env);
56}
57
bellarde4533c72003-06-15 19:51:39 +000058void cpu_loop_exit(void)
59{
thsbfed01f2007-06-03 17:44:37 +000060 /* NOTE: the register at this point must be saved by hand because
61 longjmp restore them */
62 regs_to_env();
bellarde4533c72003-06-15 19:51:39 +000063 longjmp(env->jmp_env, 1);
64}
thsbfed01f2007-06-03 17:44:37 +000065
bellardfbf9eeb2004-04-25 21:21:33 +000066/* exit the current TB from a signal handler. The host registers are
67 restored in a state compatible with the CPU emulator
68 */
ths5fafdf22007-09-16 21:08:06 +000069void cpu_resume_from_signal(CPUState *env1, void *puc)
bellardfbf9eeb2004-04-25 21:21:33 +000070{
71#if !defined(CONFIG_SOFTMMU)
blueswir184778502008-10-26 20:33:16 +000072#ifdef __linux__
bellardfbf9eeb2004-04-25 21:21:33 +000073 struct ucontext *uc = puc;
blueswir184778502008-10-26 20:33:16 +000074#elif defined(__OpenBSD__)
75 struct sigcontext *uc = puc;
76#endif
bellardfbf9eeb2004-04-25 21:21:33 +000077#endif
78
79 env = env1;
80
81 /* XXX: restore cpu registers saved in host registers */
82
83#if !defined(CONFIG_SOFTMMU)
84 if (puc) {
85 /* XXX: use siglongjmp ? */
blueswir184778502008-10-26 20:33:16 +000086#ifdef __linux__
bellardfbf9eeb2004-04-25 21:21:33 +000087 sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
blueswir184778502008-10-26 20:33:16 +000088#elif defined(__OpenBSD__)
89 sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
90#endif
bellardfbf9eeb2004-04-25 21:21:33 +000091 }
92#endif
pbrook9a3ea652008-12-19 12:49:13 +000093 env->exception_index = -1;
bellardfbf9eeb2004-04-25 21:21:33 +000094 longjmp(env->jmp_env, 1);
95}
96
pbrook2e70f6e2008-06-29 01:03:05 +000097/* Execute the code without caching the generated code. An interpreter
98 could be used if available. */
99static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
100{
101 unsigned long next_tb;
102 TranslationBlock *tb;
103
104 /* Should never happen.
105 We only end up here when an existing TB is too long. */
106 if (max_cycles > CF_COUNT_MASK)
107 max_cycles = CF_COUNT_MASK;
108
109 tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
110 max_cycles);
111 env->current_tb = tb;
112 /* execute the generated code */
113 next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
114
115 if ((next_tb & 3) == 2) {
116 /* Restore PC. This may happen if async event occurs before
117 the TB starts executing. */
aliguori622ed362008-11-18 19:36:03 +0000118 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000119 }
120 tb_phys_invalidate(tb, -1);
121 tb_free(tb);
122}
123
bellard8a40a182005-11-20 10:35:40 +0000124static TranslationBlock *tb_find_slow(target_ulong pc,
125 target_ulong cs_base,
j_mayerc0686882007-09-20 22:47:42 +0000126 uint64_t flags)
bellard8a40a182005-11-20 10:35:40 +0000127{
128 TranslationBlock *tb, **ptb1;
bellard8a40a182005-11-20 10:35:40 +0000129 unsigned int h;
130 target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
ths3b46e622007-09-17 08:09:54 +0000131
bellard8a40a182005-11-20 10:35:40 +0000132 tb_invalidated_flag = 0;
ths3b46e622007-09-17 08:09:54 +0000133
bellard8a40a182005-11-20 10:35:40 +0000134 regs_to_env(); /* XXX: do it just before cpu_gen_code() */
ths3b46e622007-09-17 08:09:54 +0000135
bellard8a40a182005-11-20 10:35:40 +0000136 /* find translated block using physical mappings */
137 phys_pc = get_phys_addr_code(env, pc);
138 phys_page1 = phys_pc & TARGET_PAGE_MASK;
139 phys_page2 = -1;
140 h = tb_phys_hash_func(phys_pc);
141 ptb1 = &tb_phys_hash[h];
142 for(;;) {
143 tb = *ptb1;
144 if (!tb)
145 goto not_found;
ths5fafdf22007-09-16 21:08:06 +0000146 if (tb->pc == pc &&
bellard8a40a182005-11-20 10:35:40 +0000147 tb->page_addr[0] == phys_page1 &&
ths5fafdf22007-09-16 21:08:06 +0000148 tb->cs_base == cs_base &&
bellard8a40a182005-11-20 10:35:40 +0000149 tb->flags == flags) {
150 /* check next page if needed */
151 if (tb->page_addr[1] != -1) {
ths5fafdf22007-09-16 21:08:06 +0000152 virt_page2 = (pc & TARGET_PAGE_MASK) +
bellard8a40a182005-11-20 10:35:40 +0000153 TARGET_PAGE_SIZE;
154 phys_page2 = get_phys_addr_code(env, virt_page2);
155 if (tb->page_addr[1] == phys_page2)
156 goto found;
157 } else {
158 goto found;
159 }
160 }
161 ptb1 = &tb->phys_hash_next;
162 }
163 not_found:
pbrook2e70f6e2008-06-29 01:03:05 +0000164 /* if no translated code available, then translate it now */
165 tb = tb_gen_code(env, pc, cs_base, flags, 0);
ths3b46e622007-09-17 08:09:54 +0000166
bellard8a40a182005-11-20 10:35:40 +0000167 found:
bellard8a40a182005-11-20 10:35:40 +0000168 /* we add the TB in the virtual pc hash table */
169 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
bellard8a40a182005-11-20 10:35:40 +0000170 return tb;
171}
172
173static inline TranslationBlock *tb_find_fast(void)
174{
175 TranslationBlock *tb;
176 target_ulong cs_base, pc;
aliguori6b917542008-11-18 19:46:41 +0000177 int flags;
bellard8a40a182005-11-20 10:35:40 +0000178
179 /* we record a subset of the CPU state. It will
180 always be the same before a given translated block
181 is executed. */
aliguori6b917542008-11-18 19:46:41 +0000182 cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
bellardbce61842008-02-01 22:18:51 +0000183 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
ths551bd272008-07-03 17:57:36 +0000184 if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
185 tb->flags != flags)) {
bellard8a40a182005-11-20 10:35:40 +0000186 tb = tb_find_slow(pc, cs_base, flags);
187 }
188 return tb;
189}
190
aliguoridde23672008-11-18 20:50:36 +0000191static CPUDebugExcpHandler *debug_excp_handler;
192
193CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
194{
195 CPUDebugExcpHandler *old_handler = debug_excp_handler;
196
197 debug_excp_handler = handler;
198 return old_handler;
199}
200
aliguori6e140f22008-11-18 20:37:55 +0000201static void cpu_handle_debug_exception(CPUState *env)
202{
203 CPUWatchpoint *wp;
204
205 if (!env->watchpoint_hit)
aliguoric0ce9982008-11-25 22:13:57 +0000206 TAILQ_FOREACH(wp, &env->watchpoints, entry)
aliguori6e140f22008-11-18 20:37:55 +0000207 wp->flags &= ~BP_WATCHPOINT_HIT;
aliguoridde23672008-11-18 20:50:36 +0000208
209 if (debug_excp_handler)
210 debug_excp_handler(env);
aliguori6e140f22008-11-18 20:37:55 +0000211}
212
bellard7d132992003-03-06 23:23:54 +0000213/* main execution loop */
214
bellarde4533c72003-06-15 19:51:39 +0000215int cpu_exec(CPUState *env1)
bellard7d132992003-03-06 23:23:54 +0000216{
pbrook1057eaa2007-02-04 13:37:44 +0000217#define DECLARE_HOST_REGS 1
218#include "hostregs_helper.h"
bellard8a40a182005-11-20 10:35:40 +0000219 int ret, interrupt_request;
bellard8a40a182005-11-20 10:35:40 +0000220 TranslationBlock *tb;
bellardc27004e2005-01-03 23:35:10 +0000221 uint8_t *tc_ptr;
pbrookd5975362008-06-07 20:50:51 +0000222 unsigned long next_tb;
bellard8c6939c2003-06-09 15:28:00 +0000223
thsbfed01f2007-06-03 17:44:37 +0000224 if (cpu_halted(env1) == EXCP_HALTED)
225 return EXCP_HALTED;
bellard5a1e3cf2005-11-23 21:02:53 +0000226
ths5fafdf22007-09-16 21:08:06 +0000227 cpu_single_env = env1;
bellard6a00d602005-11-21 23:25:50 +0000228
bellard7d132992003-03-06 23:23:54 +0000229 /* first we save global registers */
pbrook1057eaa2007-02-04 13:37:44 +0000230#define SAVE_HOST_REGS 1
231#include "hostregs_helper.h"
bellardc27004e2005-01-03 23:35:10 +0000232 env = env1;
bellarde4533c72003-06-15 19:51:39 +0000233
bellard0d1a29f2004-10-12 22:01:28 +0000234 env_to_regs();
thsecb644f2007-06-03 18:45:53 +0000235#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000236 /* put eflags in CPU temporary format */
bellardfc2b4c42003-03-29 16:52:44 +0000237 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
238 DF = 1 - (2 * ((env->eflags >> 10) & 1));
bellard9de5e442003-03-23 16:49:39 +0000239 CC_OP = CC_OP_EFLAGS;
bellardfc2b4c42003-03-29 16:52:44 +0000240 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellard93ac68b2003-09-30 20:57:29 +0000241#elif defined(TARGET_SPARC)
pbrooke6e59062006-10-22 00:18:54 +0000242#elif defined(TARGET_M68K)
243 env->cc_op = CC_OP_FLAGS;
244 env->cc_dest = env->sr & 0xf;
245 env->cc_x = (env->sr >> 4) & 1;
thsecb644f2007-06-03 18:45:53 +0000246#elif defined(TARGET_ALPHA)
247#elif defined(TARGET_ARM)
248#elif defined(TARGET_PPC)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200249#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000250#elif defined(TARGET_MIPS)
bellardfdf9b3e2006-04-27 21:07:38 +0000251#elif defined(TARGET_SH4)
thsf1ccf902007-10-08 13:16:14 +0000252#elif defined(TARGET_CRIS)
bellardfdf9b3e2006-04-27 21:07:38 +0000253 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000254#else
255#error unsupported target CPU
256#endif
bellard3fb2ded2003-06-24 13:22:59 +0000257 env->exception_index = -1;
bellard9d27abd2003-05-10 13:13:54 +0000258
bellard7d132992003-03-06 23:23:54 +0000259 /* prepare setjmp context for exception handling */
bellard3fb2ded2003-06-24 13:22:59 +0000260 for(;;) {
261 if (setjmp(env->jmp_env) == 0) {
blueswir19ddff3d2009-04-04 07:41:20 +0000262#if defined(__sparc__) && !defined(HOST_SOLARIS)
263#undef env
264 env = cpu_single_env;
265#define env cpu_single_env
266#endif
bellardee8b7022004-02-03 23:35:10 +0000267 env->current_tb = NULL;
bellard3fb2ded2003-06-24 13:22:59 +0000268 /* if an exception is pending, we execute it here */
269 if (env->exception_index >= 0) {
270 if (env->exception_index >= EXCP_INTERRUPT) {
271 /* exit request from the cpu execution loop */
272 ret = env->exception_index;
aliguori6e140f22008-11-18 20:37:55 +0000273 if (ret == EXCP_DEBUG)
274 cpu_handle_debug_exception(env);
bellard3fb2ded2003-06-24 13:22:59 +0000275 break;
aurel3272d239e2009-01-14 19:40:27 +0000276 } else {
277#if defined(CONFIG_USER_ONLY)
bellard3fb2ded2003-06-24 13:22:59 +0000278 /* if user mode only, we simulate a fake exception
ths9f083492006-12-07 18:28:42 +0000279 which will be handled outside the cpu execution
bellard3fb2ded2003-06-24 13:22:59 +0000280 loop */
bellard83479e72003-06-25 16:12:37 +0000281#if defined(TARGET_I386)
ths5fafdf22007-09-16 21:08:06 +0000282 do_interrupt_user(env->exception_index,
283 env->exception_is_int,
284 env->error_code,
bellard3fb2ded2003-06-24 13:22:59 +0000285 env->exception_next_eip);
bellardeba01622008-05-12 12:04:40 +0000286 /* successfully delivered */
287 env->old_exception = -1;
bellard83479e72003-06-25 16:12:37 +0000288#endif
bellard3fb2ded2003-06-24 13:22:59 +0000289 ret = env->exception_index;
290 break;
aurel3272d239e2009-01-14 19:40:27 +0000291#else
bellard83479e72003-06-25 16:12:37 +0000292#if defined(TARGET_I386)
bellard3fb2ded2003-06-24 13:22:59 +0000293 /* simulate a real cpu exception. On i386, it can
294 trigger new exceptions, but we do not handle
295 double or triple faults yet. */
ths5fafdf22007-09-16 21:08:06 +0000296 do_interrupt(env->exception_index,
297 env->exception_is_int,
298 env->error_code,
bellardd05e66d2003-08-20 21:34:35 +0000299 env->exception_next_eip, 0);
ths678dde12007-03-31 20:28:52 +0000300 /* successfully delivered */
301 env->old_exception = -1;
bellardce097762004-01-04 23:53:18 +0000302#elif defined(TARGET_PPC)
303 do_interrupt(env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200304#elif defined(TARGET_MICROBLAZE)
305 do_interrupt(env);
bellard6af0bf92005-07-02 14:58:51 +0000306#elif defined(TARGET_MIPS)
307 do_interrupt(env);
bellarde95c8d52004-09-30 22:22:08 +0000308#elif defined(TARGET_SPARC)
blueswir1f2bc7e72008-05-27 17:35:30 +0000309 do_interrupt(env);
bellardb5ff1b32005-11-26 10:38:39 +0000310#elif defined(TARGET_ARM)
311 do_interrupt(env);
bellardfdf9b3e2006-04-27 21:07:38 +0000312#elif defined(TARGET_SH4)
313 do_interrupt(env);
j_mayereddf68a2007-04-05 07:22:49 +0000314#elif defined(TARGET_ALPHA)
315 do_interrupt(env);
thsf1ccf902007-10-08 13:16:14 +0000316#elif defined(TARGET_CRIS)
317 do_interrupt(env);
pbrook06338792007-05-23 19:58:11 +0000318#elif defined(TARGET_M68K)
319 do_interrupt(0);
bellard83479e72003-06-25 16:12:37 +0000320#endif
aurel3272d239e2009-01-14 19:40:27 +0000321#endif
bellard3fb2ded2003-06-24 13:22:59 +0000322 }
323 env->exception_index = -1;
ths5fafdf22007-09-16 21:08:06 +0000324 }
blueswir1640f42e2009-04-19 10:18:01 +0000325#ifdef CONFIG_KQEMU
aurel32be214e62009-03-06 21:48:00 +0000326 if (kqemu_is_ok(env) && env->interrupt_request == 0 && env->exit_request == 0) {
bellard9df217a2005-02-10 22:05:51 +0000327 int ret;
pbrooka7812ae2008-11-17 14:43:54 +0000328 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
bellard9df217a2005-02-10 22:05:51 +0000329 ret = kqemu_cpu_exec(env);
330 /* put eflags in CPU temporary format */
331 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
332 DF = 1 - (2 * ((env->eflags >> 10) & 1));
333 CC_OP = CC_OP_EFLAGS;
334 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
335 if (ret == 1) {
336 /* exception */
337 longjmp(env->jmp_env, 1);
338 } else if (ret == 2) {
339 /* softmmu execution needed */
340 } else {
aurel32be214e62009-03-06 21:48:00 +0000341 if (env->interrupt_request != 0 || env->exit_request != 0) {
bellard9df217a2005-02-10 22:05:51 +0000342 /* hardware interrupt will be executed just after */
343 } else {
344 /* otherwise, we restart */
345 longjmp(env->jmp_env, 1);
346 }
347 }
bellard9de5e442003-03-23 16:49:39 +0000348 }
bellard9df217a2005-02-10 22:05:51 +0000349#endif
350
aliguori7ba1e612008-11-05 16:04:33 +0000351 if (kvm_enabled()) {
aliguoribecfc392008-11-10 15:55:14 +0000352 kvm_cpu_exec(env);
353 longjmp(env->jmp_env, 1);
aliguori7ba1e612008-11-05 16:04:33 +0000354 }
355
blueswir1b5fc09a2008-05-04 06:38:18 +0000356 next_tb = 0; /* force lookup of first TB */
bellard3fb2ded2003-06-24 13:22:59 +0000357 for(;;) {
bellard68a79312003-06-30 13:12:32 +0000358 interrupt_request = env->interrupt_request;
malce1638bd2008-11-06 18:54:46 +0000359 if (unlikely(interrupt_request)) {
360 if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
361 /* Mask out external interrupts for this step. */
362 interrupt_request &= ~(CPU_INTERRUPT_HARD |
363 CPU_INTERRUPT_FIQ |
364 CPU_INTERRUPT_SMI |
365 CPU_INTERRUPT_NMI);
366 }
pbrook6658ffb2007-03-16 23:58:11 +0000367 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
368 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
369 env->exception_index = EXCP_DEBUG;
370 cpu_loop_exit();
371 }
balroga90b7312007-05-01 01:28:01 +0000372#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200373 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
374 defined(TARGET_MICROBLAZE)
balroga90b7312007-05-01 01:28:01 +0000375 if (interrupt_request & CPU_INTERRUPT_HALT) {
376 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
377 env->halted = 1;
378 env->exception_index = EXCP_HLT;
379 cpu_loop_exit();
380 }
381#endif
bellard68a79312003-06-30 13:12:32 +0000382#if defined(TARGET_I386)
bellarddb620f42008-06-04 17:02:19 +0000383 if (env->hflags2 & HF2_GIF_MASK) {
384 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
385 !(env->hflags & HF_SMM_MASK)) {
386 svm_check_intercept(SVM_EXIT_SMI);
387 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
388 do_smm_enter();
389 next_tb = 0;
390 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
391 !(env->hflags2 & HF2_NMI_MASK)) {
392 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
393 env->hflags2 |= HF2_NMI_MASK;
394 do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
395 next_tb = 0;
396 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
397 (((env->hflags2 & HF2_VINTR_MASK) &&
398 (env->hflags2 & HF2_HIF_MASK)) ||
399 (!(env->hflags2 & HF2_VINTR_MASK) &&
400 (env->eflags & IF_MASK &&
401 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
402 int intno;
403 svm_check_intercept(SVM_EXIT_INTR);
404 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
405 intno = cpu_get_pic_interrupt(env);
aliguori93fcfe32009-01-15 22:34:14 +0000406 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
blueswir19ddff3d2009-04-04 07:41:20 +0000407#if defined(__sparc__) && !defined(HOST_SOLARIS)
408#undef env
409 env = cpu_single_env;
410#define env cpu_single_env
411#endif
bellarddb620f42008-06-04 17:02:19 +0000412 do_interrupt(intno, 0, 0, 0, 1);
413 /* ensure that no TB jump will be modified as
414 the program flow was changed */
415 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000416#if !defined(CONFIG_USER_ONLY)
bellarddb620f42008-06-04 17:02:19 +0000417 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
418 (env->eflags & IF_MASK) &&
419 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
420 int intno;
421 /* FIXME: this should respect TPR */
422 svm_check_intercept(SVM_EXIT_VINTR);
bellarddb620f42008-06-04 17:02:19 +0000423 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
aliguori93fcfe32009-01-15 22:34:14 +0000424 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
bellarddb620f42008-06-04 17:02:19 +0000425 do_interrupt(intno, 0, 0, 0, 1);
aurel32d40c54d2008-12-13 12:33:02 +0000426 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
bellarddb620f42008-06-04 17:02:19 +0000427 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000428#endif
bellarddb620f42008-06-04 17:02:19 +0000429 }
bellard68a79312003-06-30 13:12:32 +0000430 }
bellardce097762004-01-04 23:53:18 +0000431#elif defined(TARGET_PPC)
bellard9fddaa02004-05-21 12:59:32 +0000432#if 0
433 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
434 cpu_ppc_reset(env);
435 }
436#endif
j_mayer47103572007-03-30 09:38:04 +0000437 if (interrupt_request & CPU_INTERRUPT_HARD) {
j_mayere9df0142007-04-09 22:45:36 +0000438 ppc_hw_interrupt(env);
439 if (env->pending_interrupts == 0)
440 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
blueswir1b5fc09a2008-05-04 06:38:18 +0000441 next_tb = 0;
bellardce097762004-01-04 23:53:18 +0000442 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200443#elif defined(TARGET_MICROBLAZE)
444 if ((interrupt_request & CPU_INTERRUPT_HARD)
445 && (env->sregs[SR_MSR] & MSR_IE)
446 && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
447 && !(env->iflags & (D_FLAG | IMM_FLAG))) {
448 env->exception_index = EXCP_IRQ;
449 do_interrupt(env);
450 next_tb = 0;
451 }
bellard6af0bf92005-07-02 14:58:51 +0000452#elif defined(TARGET_MIPS)
453 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
ths24c7b0e2007-03-30 16:44:54 +0000454 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
bellard6af0bf92005-07-02 14:58:51 +0000455 (env->CP0_Status & (1 << CP0St_IE)) &&
ths24c7b0e2007-03-30 16:44:54 +0000456 !(env->CP0_Status & (1 << CP0St_EXL)) &&
457 !(env->CP0_Status & (1 << CP0St_ERL)) &&
bellard6af0bf92005-07-02 14:58:51 +0000458 !(env->hflags & MIPS_HFLAG_DM)) {
459 /* Raise it */
460 env->exception_index = EXCP_EXT_INTERRUPT;
461 env->error_code = 0;
462 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000463 next_tb = 0;
bellard6af0bf92005-07-02 14:58:51 +0000464 }
bellarde95c8d52004-09-30 22:22:08 +0000465#elif defined(TARGET_SPARC)
bellard66321a12005-04-06 20:47:48 +0000466 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
467 (env->psret != 0)) {
468 int pil = env->interrupt_index & 15;
469 int type = env->interrupt_index & 0xf0;
470
471 if (((type == TT_EXTINT) &&
472 (pil == 15 || pil > env->psrpil)) ||
473 type != TT_EXTINT) {
474 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
blueswir1f2bc7e72008-05-27 17:35:30 +0000475 env->exception_index = env->interrupt_index;
476 do_interrupt(env);
bellard66321a12005-04-06 20:47:48 +0000477 env->interrupt_index = 0;
blueswir1327ac2e2007-08-04 10:50:30 +0000478#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
479 cpu_check_irqs(env);
480#endif
blueswir1b5fc09a2008-05-04 06:38:18 +0000481 next_tb = 0;
bellard66321a12005-04-06 20:47:48 +0000482 }
bellarde95c8d52004-09-30 22:22:08 +0000483 } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
484 //do_interrupt(0, 0, 0, 0, 0);
485 env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
balroga90b7312007-05-01 01:28:01 +0000486 }
bellardb5ff1b32005-11-26 10:38:39 +0000487#elif defined(TARGET_ARM)
488 if (interrupt_request & CPU_INTERRUPT_FIQ
489 && !(env->uncached_cpsr & CPSR_F)) {
490 env->exception_index = EXCP_FIQ;
491 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000492 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000493 }
pbrook9ee6e8b2007-11-11 00:04:49 +0000494 /* ARMv7-M interrupt return works by loading a magic value
495 into the PC. On real hardware the load causes the
496 return to occur. The qemu implementation performs the
497 jump normally, then does the exception return when the
498 CPU tries to execute code at the magic address.
499 This will cause the magic PC value to be pushed to
500 the stack if an interrupt occured at the wrong time.
501 We avoid this by disabling interrupts when
502 pc contains a magic address. */
bellardb5ff1b32005-11-26 10:38:39 +0000503 if (interrupt_request & CPU_INTERRUPT_HARD
pbrook9ee6e8b2007-11-11 00:04:49 +0000504 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
505 || !(env->uncached_cpsr & CPSR_I))) {
bellardb5ff1b32005-11-26 10:38:39 +0000506 env->exception_index = EXCP_IRQ;
507 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000508 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000509 }
bellardfdf9b3e2006-04-27 21:07:38 +0000510#elif defined(TARGET_SH4)
thse96e2042007-12-02 06:18:24 +0000511 if (interrupt_request & CPU_INTERRUPT_HARD) {
512 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000513 next_tb = 0;
thse96e2042007-12-02 06:18:24 +0000514 }
j_mayereddf68a2007-04-05 07:22:49 +0000515#elif defined(TARGET_ALPHA)
516 if (interrupt_request & CPU_INTERRUPT_HARD) {
517 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000518 next_tb = 0;
j_mayereddf68a2007-04-05 07:22:49 +0000519 }
thsf1ccf902007-10-08 13:16:14 +0000520#elif defined(TARGET_CRIS)
edgar_igl1b1a38b2008-06-09 23:18:06 +0000521 if (interrupt_request & CPU_INTERRUPT_HARD
522 && (env->pregs[PR_CCS] & I_FLAG)) {
523 env->exception_index = EXCP_IRQ;
524 do_interrupt(env);
525 next_tb = 0;
526 }
527 if (interrupt_request & CPU_INTERRUPT_NMI
528 && (env->pregs[PR_CCS] & M_FLAG)) {
529 env->exception_index = EXCP_NMI;
thsf1ccf902007-10-08 13:16:14 +0000530 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000531 next_tb = 0;
thsf1ccf902007-10-08 13:16:14 +0000532 }
pbrook06338792007-05-23 19:58:11 +0000533#elif defined(TARGET_M68K)
534 if (interrupt_request & CPU_INTERRUPT_HARD
535 && ((env->sr & SR_I) >> SR_I_SHIFT)
536 < env->pending_level) {
537 /* Real hardware gets the interrupt vector via an
538 IACK cycle at this point. Current emulated
539 hardware doesn't rely on this, so we
540 provide/save the vector when the interrupt is
541 first signalled. */
542 env->exception_index = env->pending_vector;
543 do_interrupt(1);
blueswir1b5fc09a2008-05-04 06:38:18 +0000544 next_tb = 0;
pbrook06338792007-05-23 19:58:11 +0000545 }
bellard68a79312003-06-30 13:12:32 +0000546#endif
bellard9d050952006-05-22 22:03:52 +0000547 /* Don't use the cached interupt_request value,
548 do_interrupt may have updated the EXITTB flag. */
bellardb5ff1b32005-11-26 10:38:39 +0000549 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
bellardbf3e8bf2004-02-16 21:58:54 +0000550 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
551 /* ensure that no TB jump will be modified as
552 the program flow was changed */
blueswir1b5fc09a2008-05-04 06:38:18 +0000553 next_tb = 0;
bellardbf3e8bf2004-02-16 21:58:54 +0000554 }
aurel32be214e62009-03-06 21:48:00 +0000555 }
556 if (unlikely(env->exit_request)) {
557 env->exit_request = 0;
558 env->exception_index = EXCP_INTERRUPT;
559 cpu_loop_exit();
bellard3fb2ded2003-06-24 13:22:59 +0000560 }
561#ifdef DEBUG_EXEC
aliguori8fec2b82009-01-15 22:36:53 +0000562 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
bellard3fb2ded2003-06-24 13:22:59 +0000563 /* restore flags in standard format */
thsecb644f2007-06-03 18:45:53 +0000564 regs_to_env();
565#if defined(TARGET_I386)
pbrooka7812ae2008-11-17 14:43:54 +0000566 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
aliguori93fcfe32009-01-15 22:34:14 +0000567 log_cpu_state(env, X86_DUMP_CCOP);
bellard3fb2ded2003-06-24 13:22:59 +0000568 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellarde4533c72003-06-15 19:51:39 +0000569#elif defined(TARGET_ARM)
aliguori93fcfe32009-01-15 22:34:14 +0000570 log_cpu_state(env, 0);
bellard93ac68b2003-09-30 20:57:29 +0000571#elif defined(TARGET_SPARC)
aliguori93fcfe32009-01-15 22:34:14 +0000572 log_cpu_state(env, 0);
bellard67867302003-11-23 17:05:30 +0000573#elif defined(TARGET_PPC)
aliguori93fcfe32009-01-15 22:34:14 +0000574 log_cpu_state(env, 0);
pbrooke6e59062006-10-22 00:18:54 +0000575#elif defined(TARGET_M68K)
576 cpu_m68k_flush_flags(env, env->cc_op);
577 env->cc_op = CC_OP_FLAGS;
578 env->sr = (env->sr & 0xffe0)
579 | env->cc_dest | (env->cc_x << 4);
aliguori93fcfe32009-01-15 22:34:14 +0000580 log_cpu_state(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200581#elif defined(TARGET_MICROBLAZE)
582 log_cpu_state(env, 0);
bellard6af0bf92005-07-02 14:58:51 +0000583#elif defined(TARGET_MIPS)
aliguori93fcfe32009-01-15 22:34:14 +0000584 log_cpu_state(env, 0);
bellardfdf9b3e2006-04-27 21:07:38 +0000585#elif defined(TARGET_SH4)
aliguori93fcfe32009-01-15 22:34:14 +0000586 log_cpu_state(env, 0);
j_mayereddf68a2007-04-05 07:22:49 +0000587#elif defined(TARGET_ALPHA)
aliguori93fcfe32009-01-15 22:34:14 +0000588 log_cpu_state(env, 0);
thsf1ccf902007-10-08 13:16:14 +0000589#elif defined(TARGET_CRIS)
aliguori93fcfe32009-01-15 22:34:14 +0000590 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000591#else
ths5fafdf22007-09-16 21:08:06 +0000592#error unsupported target CPU
bellarde4533c72003-06-15 19:51:39 +0000593#endif
bellard3fb2ded2003-06-24 13:22:59 +0000594 }
bellard7d132992003-03-06 23:23:54 +0000595#endif
pbrookd5975362008-06-07 20:50:51 +0000596 spin_lock(&tb_lock);
bellard8a40a182005-11-20 10:35:40 +0000597 tb = tb_find_fast();
pbrookd5975362008-06-07 20:50:51 +0000598 /* Note: we do it here to avoid a gcc bug on Mac OS X when
599 doing it in tb_find_slow */
600 if (tb_invalidated_flag) {
601 /* as some TB could have been invalidated because
602 of memory exceptions while generating the code, we
603 must recompute the hash index here */
604 next_tb = 0;
pbrook2e70f6e2008-06-29 01:03:05 +0000605 tb_invalidated_flag = 0;
pbrookd5975362008-06-07 20:50:51 +0000606 }
bellard9d27abd2003-05-10 13:13:54 +0000607#ifdef DEBUG_EXEC
aliguori93fcfe32009-01-15 22:34:14 +0000608 qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
609 (long)tb->tc_ptr, tb->pc,
610 lookup_symbol(tb->pc));
bellard9d27abd2003-05-10 13:13:54 +0000611#endif
bellard8a40a182005-11-20 10:35:40 +0000612 /* see if we can patch the calling TB. When the TB
613 spans two pages, we cannot safely do a direct
614 jump. */
bellardc27004e2005-01-03 23:35:10 +0000615 {
blueswir1b5fc09a2008-05-04 06:38:18 +0000616 if (next_tb != 0 &&
blueswir1640f42e2009-04-19 10:18:01 +0000617#ifdef CONFIG_KQEMU
bellardf32fc642006-02-08 22:43:39 +0000618 (env->kqemu_enabled != 2) &&
619#endif
bellardec6338b2007-11-08 14:25:03 +0000620 tb->page_addr[1] == -1) {
blueswir1b5fc09a2008-05-04 06:38:18 +0000621 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
bellard3fb2ded2003-06-24 13:22:59 +0000622 }
bellardc27004e2005-01-03 23:35:10 +0000623 }
pbrookd5975362008-06-07 20:50:51 +0000624 spin_unlock(&tb_lock);
bellard83479e72003-06-25 16:12:37 +0000625 env->current_tb = tb;
malc55e8b852008-11-04 14:18:13 +0000626
627 /* cpu_interrupt might be called while translating the
628 TB, but before it is linked into a potentially
629 infinite loop and becomes env->current_tb. Avoid
630 starting execution if there is a pending interrupt. */
aurel32be214e62009-03-06 21:48:00 +0000631 if (unlikely (env->exit_request))
malc55e8b852008-11-04 14:18:13 +0000632 env->current_tb = NULL;
633
pbrook2e70f6e2008-06-29 01:03:05 +0000634 while (env->current_tb) {
635 tc_ptr = tb->tc_ptr;
bellard3fb2ded2003-06-24 13:22:59 +0000636 /* execute the generated code */
blueswir1572a9d42008-05-17 07:38:10 +0000637#if defined(__sparc__) && !defined(HOST_SOLARIS)
638#undef env
pbrook2e70f6e2008-06-29 01:03:05 +0000639 env = cpu_single_env;
blueswir1572a9d42008-05-17 07:38:10 +0000640#define env cpu_single_env
641#endif
pbrook2e70f6e2008-06-29 01:03:05 +0000642 next_tb = tcg_qemu_tb_exec(tc_ptr);
643 env->current_tb = NULL;
644 if ((next_tb & 3) == 2) {
thsbf20dc02008-06-30 17:22:19 +0000645 /* Instruction counter expired. */
pbrook2e70f6e2008-06-29 01:03:05 +0000646 int insns_left;
647 tb = (TranslationBlock *)(long)(next_tb & ~3);
648 /* Restore PC. */
aliguori622ed362008-11-18 19:36:03 +0000649 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000650 insns_left = env->icount_decr.u32;
651 if (env->icount_extra && insns_left >= 0) {
652 /* Refill decrementer and continue execution. */
653 env->icount_extra += insns_left;
654 if (env->icount_extra > 0xffff) {
655 insns_left = 0xffff;
656 } else {
657 insns_left = env->icount_extra;
658 }
659 env->icount_extra -= insns_left;
660 env->icount_decr.u16.low = insns_left;
661 } else {
662 if (insns_left > 0) {
663 /* Execute remaining instructions. */
664 cpu_exec_nocache(insns_left, tb);
665 }
666 env->exception_index = EXCP_INTERRUPT;
667 next_tb = 0;
668 cpu_loop_exit();
669 }
670 }
671 }
bellard4cbf74b2003-08-10 21:48:43 +0000672 /* reset soft MMU for next block (it can currently
673 only be set by a memory fault) */
blueswir1640f42e2009-04-19 10:18:01 +0000674#if defined(CONFIG_KQEMU)
bellardf32fc642006-02-08 22:43:39 +0000675#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
676 if (kqemu_is_ok(env) &&
677 (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
678 cpu_loop_exit();
679 }
680#endif
ths50a518e2007-06-03 18:52:15 +0000681 } /* for(;;) */
bellard3fb2ded2003-06-24 13:22:59 +0000682 } else {
bellard0d1a29f2004-10-12 22:01:28 +0000683 env_to_regs();
bellard7d132992003-03-06 23:23:54 +0000684 }
bellard3fb2ded2003-06-24 13:22:59 +0000685 } /* for(;;) */
686
bellard7d132992003-03-06 23:23:54 +0000687
bellarde4533c72003-06-15 19:51:39 +0000688#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000689 /* restore flags in standard format */
pbrooka7812ae2008-11-17 14:43:54 +0000690 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
bellarde4533c72003-06-15 19:51:39 +0000691#elif defined(TARGET_ARM)
bellardb7bcbe92005-02-22 19:27:29 +0000692 /* XXX: Save/restore host fpu exception state?. */
bellard93ac68b2003-09-30 20:57:29 +0000693#elif defined(TARGET_SPARC)
bellard67867302003-11-23 17:05:30 +0000694#elif defined(TARGET_PPC)
pbrooke6e59062006-10-22 00:18:54 +0000695#elif defined(TARGET_M68K)
696 cpu_m68k_flush_flags(env, env->cc_op);
697 env->cc_op = CC_OP_FLAGS;
698 env->sr = (env->sr & 0xffe0)
699 | env->cc_dest | (env->cc_x << 4);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200700#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000701#elif defined(TARGET_MIPS)
bellardfdf9b3e2006-04-27 21:07:38 +0000702#elif defined(TARGET_SH4)
j_mayereddf68a2007-04-05 07:22:49 +0000703#elif defined(TARGET_ALPHA)
thsf1ccf902007-10-08 13:16:14 +0000704#elif defined(TARGET_CRIS)
bellardfdf9b3e2006-04-27 21:07:38 +0000705 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000706#else
707#error unsupported target CPU
708#endif
pbrook1057eaa2007-02-04 13:37:44 +0000709
710 /* restore global registers */
pbrook1057eaa2007-02-04 13:37:44 +0000711#include "hostregs_helper.h"
712
bellard6a00d602005-11-21 23:25:50 +0000713 /* fail safe : never use cpu_single_env outside cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000714 cpu_single_env = NULL;
bellard7d132992003-03-06 23:23:54 +0000715 return ret;
716}
bellard6dbad632003-03-16 18:05:05 +0000717
bellardfbf9eeb2004-04-25 21:21:33 +0000718/* must only be called from the generated code as an exception can be
719 generated */
720void tb_invalidate_page_range(target_ulong start, target_ulong end)
721{
bellarddc5d0b32004-06-22 18:43:30 +0000722 /* XXX: cannot enable it yet because it yields to MMU exception
723 where NIP != read address on PowerPC */
724#if 0
bellardfbf9eeb2004-04-25 21:21:33 +0000725 target_ulong phys_addr;
726 phys_addr = get_phys_addr_code(env, start);
727 tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
bellarddc5d0b32004-06-22 18:43:30 +0000728#endif
bellardfbf9eeb2004-04-25 21:21:33 +0000729}
730
bellard1a18c712003-10-30 01:07:51 +0000731#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
bellarde4533c72003-06-15 19:51:39 +0000732
bellard6dbad632003-03-16 18:05:05 +0000733void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
734{
735 CPUX86State *saved_env;
736
737 saved_env = env;
738 env = s;
bellarda412ac52003-07-26 18:01:40 +0000739 if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
bellarda513fe12003-05-27 23:29:48 +0000740 selector &= 0xffff;
ths5fafdf22007-09-16 21:08:06 +0000741 cpu_x86_load_seg_cache(env, seg_reg, selector,
bellardc27004e2005-01-03 23:35:10 +0000742 (selector << 4), 0xffff, 0);
bellarda513fe12003-05-27 23:29:48 +0000743 } else {
bellard5d975592008-05-12 22:05:33 +0000744 helper_load_seg(seg_reg, selector);
bellarda513fe12003-05-27 23:29:48 +0000745 }
bellard6dbad632003-03-16 18:05:05 +0000746 env = saved_env;
747}
bellard9de5e442003-03-23 16:49:39 +0000748
bellard6f12a2a2007-11-11 22:16:56 +0000749void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
bellardd0a1ffc2003-05-29 20:04:28 +0000750{
751 CPUX86State *saved_env;
752
753 saved_env = env;
754 env = s;
ths3b46e622007-09-17 08:09:54 +0000755
bellard6f12a2a2007-11-11 22:16:56 +0000756 helper_fsave(ptr, data32);
bellardd0a1ffc2003-05-29 20:04:28 +0000757
758 env = saved_env;
759}
760
bellard6f12a2a2007-11-11 22:16:56 +0000761void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
bellardd0a1ffc2003-05-29 20:04:28 +0000762{
763 CPUX86State *saved_env;
764
765 saved_env = env;
766 env = s;
ths3b46e622007-09-17 08:09:54 +0000767
bellard6f12a2a2007-11-11 22:16:56 +0000768 helper_frstor(ptr, data32);
bellardd0a1ffc2003-05-29 20:04:28 +0000769
770 env = saved_env;
771}
772
bellarde4533c72003-06-15 19:51:39 +0000773#endif /* TARGET_I386 */
774
bellard67b915a2004-03-31 23:37:16 +0000775#if !defined(CONFIG_SOFTMMU)
776
bellard3fb2ded2003-06-24 13:22:59 +0000777#if defined(TARGET_I386)
778
bellardb56dad12003-05-08 15:38:04 +0000779/* 'pc' is the host PC at which the exception was raised. 'address' is
bellardfd6ce8f2003-05-14 19:00:11 +0000780 the effective address of the memory exception. 'is_write' is 1 if a
781 write caused the exception and otherwise 0'. 'old_set' is the
782 signal set which should be restored */
bellard2b413142003-05-14 23:01:10 +0000783static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
ths5fafdf22007-09-16 21:08:06 +0000784 int is_write, sigset_t *old_set,
bellardbf3e8bf2004-02-16 21:58:54 +0000785 void *puc)
bellard9de5e442003-03-23 16:49:39 +0000786{
bellarda513fe12003-05-27 23:29:48 +0000787 TranslationBlock *tb;
788 int ret;
bellard68a79312003-06-30 13:12:32 +0000789
bellard83479e72003-06-25 16:12:37 +0000790 if (cpu_single_env)
791 env = cpu_single_env; /* XXX: find a correct solution for multithread */
bellardfd6ce8f2003-05-14 19:00:11 +0000792#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000793 qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellardbf3e8bf2004-02-16 21:58:54 +0000794 pc, address, is_write, *(unsigned long *)old_set);
bellard9de5e442003-03-23 16:49:39 +0000795#endif
bellard25eb4482003-05-14 21:50:54 +0000796 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000797 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellardfd6ce8f2003-05-14 19:00:11 +0000798 return 1;
799 }
bellardfbf9eeb2004-04-25 21:21:33 +0000800
bellard3fb2ded2003-06-24 13:22:59 +0000801 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000802 ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard3fb2ded2003-06-24 13:22:59 +0000803 if (ret < 0)
804 return 0; /* not an MMU fault */
805 if (ret == 0)
806 return 1; /* the MMU fault was handled without causing real CPU fault */
807 /* now we have a real cpu fault */
bellarda513fe12003-05-27 23:29:48 +0000808 tb = tb_find_pc(pc);
809 if (tb) {
bellard9de5e442003-03-23 16:49:39 +0000810 /* the PC is inside the translated code. It means that we have
811 a virtual CPU fault */
bellardbf3e8bf2004-02-16 21:58:54 +0000812 cpu_restore_state(tb, env, pc, puc);
bellard3fb2ded2003-06-24 13:22:59 +0000813 }
bellard4cbf74b2003-08-10 21:48:43 +0000814 if (ret == 1) {
bellard3fb2ded2003-06-24 13:22:59 +0000815#if 0
ths5fafdf22007-09-16 21:08:06 +0000816 printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
bellard4cbf74b2003-08-10 21:48:43 +0000817 env->eip, env->cr[2], env->error_code);
bellard3fb2ded2003-06-24 13:22:59 +0000818#endif
bellard4cbf74b2003-08-10 21:48:43 +0000819 /* we restore the process signal mask as the sigreturn should
820 do it (XXX: use sigsetjmp) */
821 sigprocmask(SIG_SETMASK, old_set, NULL);
bellard54ca9092005-12-04 18:46:06 +0000822 raise_exception_err(env->exception_index, env->error_code);
bellard4cbf74b2003-08-10 21:48:43 +0000823 } else {
824 /* activate soft MMU for this block */
bellard3f337312003-08-20 23:02:09 +0000825 env->hflags |= HF_SOFTMMU_MASK;
bellardfbf9eeb2004-04-25 21:21:33 +0000826 cpu_resume_from_signal(env, puc);
bellard4cbf74b2003-08-10 21:48:43 +0000827 }
bellard3fb2ded2003-06-24 13:22:59 +0000828 /* never comes here */
829 return 1;
830}
831
bellarde4533c72003-06-15 19:51:39 +0000832#elif defined(TARGET_ARM)
bellard3fb2ded2003-06-24 13:22:59 +0000833static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bellardbf3e8bf2004-02-16 21:58:54 +0000834 int is_write, sigset_t *old_set,
835 void *puc)
bellard3fb2ded2003-06-24 13:22:59 +0000836{
bellard68016c62005-02-07 23:12:27 +0000837 TranslationBlock *tb;
838 int ret;
839
840 if (cpu_single_env)
841 env = cpu_single_env; /* XXX: find a correct solution for multithread */
842#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000843 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard68016c62005-02-07 23:12:27 +0000844 pc, address, is_write, *(unsigned long *)old_set);
845#endif
bellard9f0777e2005-02-02 20:42:01 +0000846 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000847 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellard9f0777e2005-02-02 20:42:01 +0000848 return 1;
849 }
bellard68016c62005-02-07 23:12:27 +0000850 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000851 ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard68016c62005-02-07 23:12:27 +0000852 if (ret < 0)
853 return 0; /* not an MMU fault */
854 if (ret == 0)
855 return 1; /* the MMU fault was handled without causing real CPU fault */
856 /* now we have a real cpu fault */
857 tb = tb_find_pc(pc);
858 if (tb) {
859 /* the PC is inside the translated code. It means that we have
860 a virtual CPU fault */
861 cpu_restore_state(tb, env, pc, puc);
862 }
863 /* we restore the process signal mask as the sigreturn should
864 do it (XXX: use sigsetjmp) */
865 sigprocmask(SIG_SETMASK, old_set, NULL);
866 cpu_loop_exit();
aurel32968c74d2008-04-11 04:55:17 +0000867 /* never comes here */
868 return 1;
bellard3fb2ded2003-06-24 13:22:59 +0000869}
bellard93ac68b2003-09-30 20:57:29 +0000870#elif defined(TARGET_SPARC)
871static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bellardbf3e8bf2004-02-16 21:58:54 +0000872 int is_write, sigset_t *old_set,
873 void *puc)
bellard93ac68b2003-09-30 20:57:29 +0000874{
bellard68016c62005-02-07 23:12:27 +0000875 TranslationBlock *tb;
876 int ret;
877
878 if (cpu_single_env)
879 env = cpu_single_env; /* XXX: find a correct solution for multithread */
880#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000881 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard68016c62005-02-07 23:12:27 +0000882 pc, address, is_write, *(unsigned long *)old_set);
883#endif
bellardb453b702004-01-04 15:45:21 +0000884 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000885 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellardb453b702004-01-04 15:45:21 +0000886 return 1;
887 }
bellard68016c62005-02-07 23:12:27 +0000888 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000889 ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard68016c62005-02-07 23:12:27 +0000890 if (ret < 0)
891 return 0; /* not an MMU fault */
892 if (ret == 0)
893 return 1; /* the MMU fault was handled without causing real CPU fault */
894 /* now we have a real cpu fault */
895 tb = tb_find_pc(pc);
896 if (tb) {
897 /* the PC is inside the translated code. It means that we have
898 a virtual CPU fault */
899 cpu_restore_state(tb, env, pc, puc);
900 }
901 /* we restore the process signal mask as the sigreturn should
902 do it (XXX: use sigsetjmp) */
903 sigprocmask(SIG_SETMASK, old_set, NULL);
904 cpu_loop_exit();
aurel32968c74d2008-04-11 04:55:17 +0000905 /* never comes here */
906 return 1;
bellard93ac68b2003-09-30 20:57:29 +0000907}
bellard67867302003-11-23 17:05:30 +0000908#elif defined (TARGET_PPC)
909static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bellardbf3e8bf2004-02-16 21:58:54 +0000910 int is_write, sigset_t *old_set,
911 void *puc)
bellard67867302003-11-23 17:05:30 +0000912{
913 TranslationBlock *tb;
bellardce097762004-01-04 23:53:18 +0000914 int ret;
ths3b46e622007-09-17 08:09:54 +0000915
bellard67867302003-11-23 17:05:30 +0000916 if (cpu_single_env)
917 env = cpu_single_env; /* XXX: find a correct solution for multithread */
bellard67867302003-11-23 17:05:30 +0000918#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000919 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard67867302003-11-23 17:05:30 +0000920 pc, address, is_write, *(unsigned long *)old_set);
921#endif
922 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000923 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellard67867302003-11-23 17:05:30 +0000924 return 1;
925 }
926
bellardce097762004-01-04 23:53:18 +0000927 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000928 ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellardce097762004-01-04 23:53:18 +0000929 if (ret < 0)
930 return 0; /* not an MMU fault */
931 if (ret == 0)
932 return 1; /* the MMU fault was handled without causing real CPU fault */
933
bellard67867302003-11-23 17:05:30 +0000934 /* now we have a real cpu fault */
935 tb = tb_find_pc(pc);
936 if (tb) {
937 /* the PC is inside the translated code. It means that we have
938 a virtual CPU fault */
bellardbf3e8bf2004-02-16 21:58:54 +0000939 cpu_restore_state(tb, env, pc, puc);
bellard67867302003-11-23 17:05:30 +0000940 }
bellardce097762004-01-04 23:53:18 +0000941 if (ret == 1) {
bellard67867302003-11-23 17:05:30 +0000942#if 0
ths5fafdf22007-09-16 21:08:06 +0000943 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
bellardce097762004-01-04 23:53:18 +0000944 env->nip, env->error_code, tb);
bellard67867302003-11-23 17:05:30 +0000945#endif
946 /* we restore the process signal mask as the sigreturn should
947 do it (XXX: use sigsetjmp) */
bellardbf3e8bf2004-02-16 21:58:54 +0000948 sigprocmask(SIG_SETMASK, old_set, NULL);
aurel32e06fcd72008-12-11 22:42:14 +0000949 cpu_loop_exit();
bellardce097762004-01-04 23:53:18 +0000950 } else {
951 /* activate soft MMU for this block */
bellardfbf9eeb2004-04-25 21:21:33 +0000952 cpu_resume_from_signal(env, puc);
bellardce097762004-01-04 23:53:18 +0000953 }
bellard67867302003-11-23 17:05:30 +0000954 /* never comes here */
955 return 1;
956}
bellard6af0bf92005-07-02 14:58:51 +0000957
pbrooke6e59062006-10-22 00:18:54 +0000958#elif defined(TARGET_M68K)
959static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
960 int is_write, sigset_t *old_set,
961 void *puc)
962{
963 TranslationBlock *tb;
964 int ret;
965
966 if (cpu_single_env)
967 env = cpu_single_env; /* XXX: find a correct solution for multithread */
968#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000969 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
pbrooke6e59062006-10-22 00:18:54 +0000970 pc, address, is_write, *(unsigned long *)old_set);
971#endif
972 /* XXX: locking issue */
973 if (is_write && page_unprotect(address, pc, puc)) {
974 return 1;
975 }
976 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000977 ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
pbrooke6e59062006-10-22 00:18:54 +0000978 if (ret < 0)
979 return 0; /* not an MMU fault */
980 if (ret == 0)
981 return 1; /* the MMU fault was handled without causing real CPU fault */
982 /* now we have a real cpu fault */
983 tb = tb_find_pc(pc);
984 if (tb) {
985 /* the PC is inside the translated code. It means that we have
986 a virtual CPU fault */
987 cpu_restore_state(tb, env, pc, puc);
988 }
989 /* we restore the process signal mask as the sigreturn should
990 do it (XXX: use sigsetjmp) */
991 sigprocmask(SIG_SETMASK, old_set, NULL);
992 cpu_loop_exit();
993 /* never comes here */
994 return 1;
995}
996
bellard6af0bf92005-07-02 14:58:51 +0000997#elif defined (TARGET_MIPS)
998static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
999 int is_write, sigset_t *old_set,
1000 void *puc)
1001{
1002 TranslationBlock *tb;
1003 int ret;
ths3b46e622007-09-17 08:09:54 +00001004
bellard6af0bf92005-07-02 14:58:51 +00001005 if (cpu_single_env)
1006 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1007#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001008 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard6af0bf92005-07-02 14:58:51 +00001009 pc, address, is_write, *(unsigned long *)old_set);
1010#endif
1011 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +00001012 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellard6af0bf92005-07-02 14:58:51 +00001013 return 1;
1014 }
1015
1016 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001017 ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard6af0bf92005-07-02 14:58:51 +00001018 if (ret < 0)
1019 return 0; /* not an MMU fault */
1020 if (ret == 0)
1021 return 1; /* the MMU fault was handled without causing real CPU fault */
1022
1023 /* now we have a real cpu fault */
1024 tb = tb_find_pc(pc);
1025 if (tb) {
1026 /* the PC is inside the translated code. It means that we have
1027 a virtual CPU fault */
1028 cpu_restore_state(tb, env, pc, puc);
1029 }
1030 if (ret == 1) {
1031#if 0
ths5fafdf22007-09-16 21:08:06 +00001032 printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
ths1eb52072007-05-12 16:57:42 +00001033 env->PC, env->error_code, tb);
bellard6af0bf92005-07-02 14:58:51 +00001034#endif
1035 /* we restore the process signal mask as the sigreturn should
1036 do it (XXX: use sigsetjmp) */
1037 sigprocmask(SIG_SETMASK, old_set, NULL);
thsf9480ff2008-12-20 19:42:14 +00001038 cpu_loop_exit();
bellard6af0bf92005-07-02 14:58:51 +00001039 } else {
1040 /* activate soft MMU for this block */
1041 cpu_resume_from_signal(env, puc);
1042 }
1043 /* never comes here */
1044 return 1;
1045}
1046
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02001047#elif defined (TARGET_MICROBLAZE)
1048static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1049 int is_write, sigset_t *old_set,
1050 void *puc)
1051{
1052 TranslationBlock *tb;
1053 int ret;
1054
1055 if (cpu_single_env)
1056 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1057#if defined(DEBUG_SIGNAL)
1058 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1059 pc, address, is_write, *(unsigned long *)old_set);
1060#endif
1061 /* XXX: locking issue */
1062 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1063 return 1;
1064 }
1065
1066 /* see if it is an MMU fault */
1067 ret = cpu_mb_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1068 if (ret < 0)
1069 return 0; /* not an MMU fault */
1070 if (ret == 0)
1071 return 1; /* the MMU fault was handled without causing real CPU fault */
1072
1073 /* now we have a real cpu fault */
1074 tb = tb_find_pc(pc);
1075 if (tb) {
1076 /* the PC is inside the translated code. It means that we have
1077 a virtual CPU fault */
1078 cpu_restore_state(tb, env, pc, puc);
1079 }
1080 if (ret == 1) {
1081#if 0
1082 printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1083 env->PC, env->error_code, tb);
1084#endif
1085 /* we restore the process signal mask as the sigreturn should
1086 do it (XXX: use sigsetjmp) */
1087 sigprocmask(SIG_SETMASK, old_set, NULL);
1088 cpu_loop_exit();
1089 } else {
1090 /* activate soft MMU for this block */
1091 cpu_resume_from_signal(env, puc);
1092 }
1093 /* never comes here */
1094 return 1;
1095}
1096
bellardfdf9b3e2006-04-27 21:07:38 +00001097#elif defined (TARGET_SH4)
1098static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1099 int is_write, sigset_t *old_set,
1100 void *puc)
1101{
1102 TranslationBlock *tb;
1103 int ret;
ths3b46e622007-09-17 08:09:54 +00001104
bellardfdf9b3e2006-04-27 21:07:38 +00001105 if (cpu_single_env)
1106 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1107#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001108 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellardfdf9b3e2006-04-27 21:07:38 +00001109 pc, address, is_write, *(unsigned long *)old_set);
1110#endif
1111 /* XXX: locking issue */
1112 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1113 return 1;
1114 }
1115
1116 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001117 ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellardfdf9b3e2006-04-27 21:07:38 +00001118 if (ret < 0)
1119 return 0; /* not an MMU fault */
1120 if (ret == 0)
1121 return 1; /* the MMU fault was handled without causing real CPU fault */
1122
1123 /* now we have a real cpu fault */
1124 tb = tb_find_pc(pc);
1125 if (tb) {
1126 /* the PC is inside the translated code. It means that we have
1127 a virtual CPU fault */
1128 cpu_restore_state(tb, env, pc, puc);
1129 }
bellardfdf9b3e2006-04-27 21:07:38 +00001130#if 0
ths5fafdf22007-09-16 21:08:06 +00001131 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
bellardfdf9b3e2006-04-27 21:07:38 +00001132 env->nip, env->error_code, tb);
1133#endif
1134 /* we restore the process signal mask as the sigreturn should
1135 do it (XXX: use sigsetjmp) */
pbrook355fb232006-06-17 19:58:25 +00001136 sigprocmask(SIG_SETMASK, old_set, NULL);
1137 cpu_loop_exit();
bellardfdf9b3e2006-04-27 21:07:38 +00001138 /* never comes here */
1139 return 1;
1140}
j_mayereddf68a2007-04-05 07:22:49 +00001141
1142#elif defined (TARGET_ALPHA)
1143static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1144 int is_write, sigset_t *old_set,
1145 void *puc)
1146{
1147 TranslationBlock *tb;
1148 int ret;
ths3b46e622007-09-17 08:09:54 +00001149
j_mayereddf68a2007-04-05 07:22:49 +00001150 if (cpu_single_env)
1151 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1152#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001153 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
j_mayereddf68a2007-04-05 07:22:49 +00001154 pc, address, is_write, *(unsigned long *)old_set);
1155#endif
1156 /* XXX: locking issue */
1157 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1158 return 1;
1159 }
1160
1161 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001162 ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
j_mayereddf68a2007-04-05 07:22:49 +00001163 if (ret < 0)
1164 return 0; /* not an MMU fault */
1165 if (ret == 0)
1166 return 1; /* the MMU fault was handled without causing real CPU fault */
1167
1168 /* now we have a real cpu fault */
1169 tb = tb_find_pc(pc);
1170 if (tb) {
1171 /* the PC is inside the translated code. It means that we have
1172 a virtual CPU fault */
1173 cpu_restore_state(tb, env, pc, puc);
1174 }
1175#if 0
ths5fafdf22007-09-16 21:08:06 +00001176 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
j_mayereddf68a2007-04-05 07:22:49 +00001177 env->nip, env->error_code, tb);
1178#endif
1179 /* we restore the process signal mask as the sigreturn should
1180 do it (XXX: use sigsetjmp) */
1181 sigprocmask(SIG_SETMASK, old_set, NULL);
1182 cpu_loop_exit();
1183 /* never comes here */
1184 return 1;
1185}
thsf1ccf902007-10-08 13:16:14 +00001186#elif defined (TARGET_CRIS)
1187static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1188 int is_write, sigset_t *old_set,
1189 void *puc)
1190{
1191 TranslationBlock *tb;
1192 int ret;
1193
1194 if (cpu_single_env)
1195 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1196#if defined(DEBUG_SIGNAL)
1197 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1198 pc, address, is_write, *(unsigned long *)old_set);
1199#endif
1200 /* XXX: locking issue */
1201 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1202 return 1;
1203 }
1204
1205 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001206 ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
thsf1ccf902007-10-08 13:16:14 +00001207 if (ret < 0)
1208 return 0; /* not an MMU fault */
1209 if (ret == 0)
1210 return 1; /* the MMU fault was handled without causing real CPU fault */
1211
1212 /* now we have a real cpu fault */
1213 tb = tb_find_pc(pc);
1214 if (tb) {
1215 /* the PC is inside the translated code. It means that we have
1216 a virtual CPU fault */
1217 cpu_restore_state(tb, env, pc, puc);
1218 }
thsf1ccf902007-10-08 13:16:14 +00001219 /* we restore the process signal mask as the sigreturn should
1220 do it (XXX: use sigsetjmp) */
1221 sigprocmask(SIG_SETMASK, old_set, NULL);
1222 cpu_loop_exit();
1223 /* never comes here */
1224 return 1;
1225}
1226
bellarde4533c72003-06-15 19:51:39 +00001227#else
1228#error unsupported target CPU
1229#endif
bellard9de5e442003-03-23 16:49:39 +00001230
bellard2b413142003-05-14 23:01:10 +00001231#if defined(__i386__)
1232
bellardd8ecc0b2007-02-05 21:41:46 +00001233#if defined(__APPLE__)
1234# include <sys/ucontext.h>
1235
1236# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1237# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
1238# define ERROR_sig(context) ((context)->uc_mcontext->es.err)
blueswir1d39bb242009-04-10 07:29:34 +00001239# define MASK_sig(context) ((context)->uc_sigmask)
1240#elif defined(__OpenBSD__)
1241# define EIP_sig(context) ((context)->sc_eip)
1242# define TRAP_sig(context) ((context)->sc_trapno)
1243# define ERROR_sig(context) ((context)->sc_err)
1244# define MASK_sig(context) ((context)->sc_mask)
bellardd8ecc0b2007-02-05 21:41:46 +00001245#else
1246# define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
1247# define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
1248# define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
blueswir1d39bb242009-04-10 07:29:34 +00001249# define MASK_sig(context) ((context)->uc_sigmask)
bellardd8ecc0b2007-02-05 21:41:46 +00001250#endif
1251
ths5fafdf22007-09-16 21:08:06 +00001252int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001253 void *puc)
bellard9de5e442003-03-23 16:49:39 +00001254{
ths5a7b5422007-01-31 12:16:51 +00001255 siginfo_t *info = pinfo;
blueswir1d39bb242009-04-10 07:29:34 +00001256#if defined(__OpenBSD__)
1257 struct sigcontext *uc = puc;
1258#else
bellard9de5e442003-03-23 16:49:39 +00001259 struct ucontext *uc = puc;
blueswir1d39bb242009-04-10 07:29:34 +00001260#endif
bellard9de5e442003-03-23 16:49:39 +00001261 unsigned long pc;
bellardbf3e8bf2004-02-16 21:58:54 +00001262 int trapno;
bellard97eb5b12004-02-25 23:19:55 +00001263
bellardd691f662003-03-24 21:58:34 +00001264#ifndef REG_EIP
1265/* for glibc 2.1 */
bellardfd6ce8f2003-05-14 19:00:11 +00001266#define REG_EIP EIP
1267#define REG_ERR ERR
1268#define REG_TRAPNO TRAPNO
bellardd691f662003-03-24 21:58:34 +00001269#endif
bellardd8ecc0b2007-02-05 21:41:46 +00001270 pc = EIP_sig(uc);
1271 trapno = TRAP_sig(uc);
bellardec6338b2007-11-08 14:25:03 +00001272 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1273 trapno == 0xe ?
1274 (ERROR_sig(uc) >> 1) & 1 : 0,
blueswir1d39bb242009-04-10 07:29:34 +00001275 &MASK_sig(uc), puc);
bellard2b413142003-05-14 23:01:10 +00001276}
1277
bellardbc51c5c2004-03-17 23:46:04 +00001278#elif defined(__x86_64__)
1279
blueswir1b3efe5c2008-12-05 17:55:45 +00001280#ifdef __NetBSD__
blueswir1d397abb2009-04-10 13:00:29 +00001281#define PC_sig(context) _UC_MACHINE_PC(context)
1282#define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
1283#define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
1284#define MASK_sig(context) ((context)->uc_sigmask)
1285#elif defined(__OpenBSD__)
1286#define PC_sig(context) ((context)->sc_rip)
1287#define TRAP_sig(context) ((context)->sc_trapno)
1288#define ERROR_sig(context) ((context)->sc_err)
1289#define MASK_sig(context) ((context)->sc_mask)
blueswir1b3efe5c2008-12-05 17:55:45 +00001290#else
blueswir1d397abb2009-04-10 13:00:29 +00001291#define PC_sig(context) ((context)->uc_mcontext.gregs[REG_RIP])
1292#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
1293#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
1294#define MASK_sig(context) ((context)->uc_sigmask)
blueswir1b3efe5c2008-12-05 17:55:45 +00001295#endif
1296
ths5a7b5422007-01-31 12:16:51 +00001297int cpu_signal_handler(int host_signum, void *pinfo,
bellardbc51c5c2004-03-17 23:46:04 +00001298 void *puc)
1299{
ths5a7b5422007-01-31 12:16:51 +00001300 siginfo_t *info = pinfo;
bellardbc51c5c2004-03-17 23:46:04 +00001301 unsigned long pc;
blueswir1b3efe5c2008-12-05 17:55:45 +00001302#ifdef __NetBSD__
1303 ucontext_t *uc = puc;
blueswir1d397abb2009-04-10 13:00:29 +00001304#elif defined(__OpenBSD__)
1305 struct sigcontext *uc = puc;
blueswir1b3efe5c2008-12-05 17:55:45 +00001306#else
1307 struct ucontext *uc = puc;
1308#endif
bellardbc51c5c2004-03-17 23:46:04 +00001309
blueswir1d397abb2009-04-10 13:00:29 +00001310 pc = PC_sig(uc);
ths5fafdf22007-09-16 21:08:06 +00001311 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
blueswir1d397abb2009-04-10 13:00:29 +00001312 TRAP_sig(uc) == 0xe ?
1313 (ERROR_sig(uc) >> 1) & 1 : 0,
1314 &MASK_sig(uc), puc);
bellardbc51c5c2004-03-17 23:46:04 +00001315}
1316
malce58ffeb2009-01-14 18:39:49 +00001317#elif defined(_ARCH_PPC)
bellard2b413142003-05-14 23:01:10 +00001318
bellard83fb7ad2004-07-05 21:25:26 +00001319/***********************************************************************
1320 * signal context platform-specific definitions
1321 * From Wine
1322 */
1323#ifdef linux
1324/* All Registers access - only for local access */
1325# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
1326/* Gpr Registers access */
1327# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
1328# define IAR_sig(context) REG_sig(nip, context) /* Program counter */
1329# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
1330# define CTR_sig(context) REG_sig(ctr, context) /* Count register */
1331# define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
1332# define LR_sig(context) REG_sig(link, context) /* Link register */
1333# define CR_sig(context) REG_sig(ccr, context) /* Condition register */
1334/* Float Registers access */
1335# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1336# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1337/* Exception Registers access */
1338# define DAR_sig(context) REG_sig(dar, context)
1339# define DSISR_sig(context) REG_sig(dsisr, context)
1340# define TRAP_sig(context) REG_sig(trap, context)
1341#endif /* linux */
1342
1343#ifdef __APPLE__
1344# include <sys/ucontext.h>
1345typedef struct ucontext SIGCONTEXT;
1346/* All Registers access - only for local access */
1347# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
1348# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
1349# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
1350# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
1351/* Gpr Registers access */
1352# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
1353# define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
1354# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
1355# define CTR_sig(context) REG_sig(ctr, context)
1356# define XER_sig(context) REG_sig(xer, context) /* Link register */
1357# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
1358# define CR_sig(context) REG_sig(cr, context) /* Condition register */
1359/* Float Registers access */
1360# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
1361# define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
1362/* Exception Registers access */
1363# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
1364# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
1365# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1366#endif /* __APPLE__ */
1367
ths5fafdf22007-09-16 21:08:06 +00001368int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001369 void *puc)
bellard2b413142003-05-14 23:01:10 +00001370{
ths5a7b5422007-01-31 12:16:51 +00001371 siginfo_t *info = pinfo;
bellard25eb4482003-05-14 21:50:54 +00001372 struct ucontext *uc = puc;
bellard25eb4482003-05-14 21:50:54 +00001373 unsigned long pc;
bellard25eb4482003-05-14 21:50:54 +00001374 int is_write;
1375
bellard83fb7ad2004-07-05 21:25:26 +00001376 pc = IAR_sig(uc);
bellard25eb4482003-05-14 21:50:54 +00001377 is_write = 0;
1378#if 0
1379 /* ppc 4xx case */
bellard83fb7ad2004-07-05 21:25:26 +00001380 if (DSISR_sig(uc) & 0x00800000)
bellard25eb4482003-05-14 21:50:54 +00001381 is_write = 1;
bellard9de5e442003-03-23 16:49:39 +00001382#else
bellard83fb7ad2004-07-05 21:25:26 +00001383 if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
bellard25eb4482003-05-14 21:50:54 +00001384 is_write = 1;
1385#endif
ths5fafdf22007-09-16 21:08:06 +00001386 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001387 is_write, &uc->uc_sigmask, puc);
bellard9de5e442003-03-23 16:49:39 +00001388}
bellard2b413142003-05-14 23:01:10 +00001389
bellard2f87c602003-06-02 20:38:09 +00001390#elif defined(__alpha__)
1391
ths5fafdf22007-09-16 21:08:06 +00001392int cpu_signal_handler(int host_signum, void *pinfo,
bellard2f87c602003-06-02 20:38:09 +00001393 void *puc)
1394{
ths5a7b5422007-01-31 12:16:51 +00001395 siginfo_t *info = pinfo;
bellard2f87c602003-06-02 20:38:09 +00001396 struct ucontext *uc = puc;
1397 uint32_t *pc = uc->uc_mcontext.sc_pc;
1398 uint32_t insn = *pc;
1399 int is_write = 0;
1400
bellard8c6939c2003-06-09 15:28:00 +00001401 /* XXX: need kernel patch to get write flag faster */
bellard2f87c602003-06-02 20:38:09 +00001402 switch (insn >> 26) {
1403 case 0x0d: // stw
1404 case 0x0e: // stb
1405 case 0x0f: // stq_u
1406 case 0x24: // stf
1407 case 0x25: // stg
1408 case 0x26: // sts
1409 case 0x27: // stt
1410 case 0x2c: // stl
1411 case 0x2d: // stq
1412 case 0x2e: // stl_c
1413 case 0x2f: // stq_c
1414 is_write = 1;
1415 }
1416
ths5fafdf22007-09-16 21:08:06 +00001417 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001418 is_write, &uc->uc_sigmask, puc);
bellard2f87c602003-06-02 20:38:09 +00001419}
bellard8c6939c2003-06-09 15:28:00 +00001420#elif defined(__sparc__)
1421
ths5fafdf22007-09-16 21:08:06 +00001422int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001423 void *puc)
bellard8c6939c2003-06-09 15:28:00 +00001424{
ths5a7b5422007-01-31 12:16:51 +00001425 siginfo_t *info = pinfo;
bellard8c6939c2003-06-09 15:28:00 +00001426 int is_write;
1427 uint32_t insn;
blueswir16b4c11c2008-05-19 17:20:01 +00001428#if !defined(__arch64__) || defined(HOST_SOLARIS)
blueswir1c9e1e2b2008-05-18 06:40:16 +00001429 uint32_t *regs = (uint32_t *)(info + 1);
1430 void *sigmask = (regs + 20);
bellard8c6939c2003-06-09 15:28:00 +00001431 /* XXX: is there a standard glibc define ? */
blueswir1c9e1e2b2008-05-18 06:40:16 +00001432 unsigned long pc = regs[1];
1433#else
blueswir184778502008-10-26 20:33:16 +00001434#ifdef __linux__
blueswir1c9e1e2b2008-05-18 06:40:16 +00001435 struct sigcontext *sc = puc;
1436 unsigned long pc = sc->sigc_regs.tpc;
1437 void *sigmask = (void *)sc->sigc_mask;
blueswir184778502008-10-26 20:33:16 +00001438#elif defined(__OpenBSD__)
1439 struct sigcontext *uc = puc;
1440 unsigned long pc = uc->sc_pc;
1441 void *sigmask = (void *)(long)uc->sc_mask;
1442#endif
blueswir1c9e1e2b2008-05-18 06:40:16 +00001443#endif
1444
bellard8c6939c2003-06-09 15:28:00 +00001445 /* XXX: need kernel patch to get write flag faster */
1446 is_write = 0;
1447 insn = *(uint32_t *)pc;
1448 if ((insn >> 30) == 3) {
1449 switch((insn >> 19) & 0x3f) {
1450 case 0x05: // stb
Blue Swirld877fa52009-04-25 19:07:16 +00001451 case 0x15: // stba
bellard8c6939c2003-06-09 15:28:00 +00001452 case 0x06: // sth
Blue Swirld877fa52009-04-25 19:07:16 +00001453 case 0x16: // stha
bellard8c6939c2003-06-09 15:28:00 +00001454 case 0x04: // st
Blue Swirld877fa52009-04-25 19:07:16 +00001455 case 0x14: // sta
bellard8c6939c2003-06-09 15:28:00 +00001456 case 0x07: // std
Blue Swirld877fa52009-04-25 19:07:16 +00001457 case 0x17: // stda
1458 case 0x0e: // stx
1459 case 0x1e: // stxa
bellard8c6939c2003-06-09 15:28:00 +00001460 case 0x24: // stf
Blue Swirld877fa52009-04-25 19:07:16 +00001461 case 0x34: // stfa
bellard8c6939c2003-06-09 15:28:00 +00001462 case 0x27: // stdf
Blue Swirld877fa52009-04-25 19:07:16 +00001463 case 0x37: // stdfa
1464 case 0x26: // stqf
1465 case 0x36: // stqfa
bellard8c6939c2003-06-09 15:28:00 +00001466 case 0x25: // stfsr
Blue Swirld877fa52009-04-25 19:07:16 +00001467 case 0x3c: // casa
1468 case 0x3e: // casxa
bellard8c6939c2003-06-09 15:28:00 +00001469 is_write = 1;
1470 break;
1471 }
1472 }
ths5fafdf22007-09-16 21:08:06 +00001473 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001474 is_write, sigmask, NULL);
bellard8c6939c2003-06-09 15:28:00 +00001475}
1476
1477#elif defined(__arm__)
1478
ths5fafdf22007-09-16 21:08:06 +00001479int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001480 void *puc)
bellard8c6939c2003-06-09 15:28:00 +00001481{
ths5a7b5422007-01-31 12:16:51 +00001482 siginfo_t *info = pinfo;
bellard8c6939c2003-06-09 15:28:00 +00001483 struct ucontext *uc = puc;
1484 unsigned long pc;
1485 int is_write;
ths3b46e622007-09-17 08:09:54 +00001486
blueswir148bbf112008-07-08 18:35:02 +00001487#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
balrog5c49b362008-06-02 01:01:18 +00001488 pc = uc->uc_mcontext.gregs[R15];
1489#else
balrog4eee57f2008-05-06 14:47:19 +00001490 pc = uc->uc_mcontext.arm_pc;
balrog5c49b362008-06-02 01:01:18 +00001491#endif
bellard8c6939c2003-06-09 15:28:00 +00001492 /* XXX: compute is_write */
1493 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001494 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellard8c6939c2003-06-09 15:28:00 +00001495 is_write,
pbrookf3a96762006-07-29 19:09:31 +00001496 &uc->uc_sigmask, puc);
bellard8c6939c2003-06-09 15:28:00 +00001497}
1498
bellard38e584a2003-08-10 22:14:22 +00001499#elif defined(__mc68000)
1500
ths5fafdf22007-09-16 21:08:06 +00001501int cpu_signal_handler(int host_signum, void *pinfo,
bellard38e584a2003-08-10 22:14:22 +00001502 void *puc)
1503{
ths5a7b5422007-01-31 12:16:51 +00001504 siginfo_t *info = pinfo;
bellard38e584a2003-08-10 22:14:22 +00001505 struct ucontext *uc = puc;
1506 unsigned long pc;
1507 int is_write;
ths3b46e622007-09-17 08:09:54 +00001508
bellard38e584a2003-08-10 22:14:22 +00001509 pc = uc->uc_mcontext.gregs[16];
1510 /* XXX: compute is_write */
1511 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001512 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellard38e584a2003-08-10 22:14:22 +00001513 is_write,
bellardbf3e8bf2004-02-16 21:58:54 +00001514 &uc->uc_sigmask, puc);
bellard38e584a2003-08-10 22:14:22 +00001515}
1516
bellardb8076a72005-04-07 22:20:31 +00001517#elif defined(__ia64)
1518
1519#ifndef __ISR_VALID
1520 /* This ought to be in <bits/siginfo.h>... */
1521# define __ISR_VALID 1
bellardb8076a72005-04-07 22:20:31 +00001522#endif
1523
ths5a7b5422007-01-31 12:16:51 +00001524int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
bellardb8076a72005-04-07 22:20:31 +00001525{
ths5a7b5422007-01-31 12:16:51 +00001526 siginfo_t *info = pinfo;
bellardb8076a72005-04-07 22:20:31 +00001527 struct ucontext *uc = puc;
1528 unsigned long ip;
1529 int is_write = 0;
1530
1531 ip = uc->uc_mcontext.sc_ip;
1532 switch (host_signum) {
1533 case SIGILL:
1534 case SIGFPE:
1535 case SIGSEGV:
1536 case SIGBUS:
1537 case SIGTRAP:
bellardfd4a43e2006-04-24 20:32:17 +00001538 if (info->si_code && (info->si_segvflags & __ISR_VALID))
bellardb8076a72005-04-07 22:20:31 +00001539 /* ISR.W (write-access) is bit 33: */
1540 is_write = (info->si_isr >> 33) & 1;
1541 break;
1542
1543 default:
1544 break;
1545 }
1546 return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1547 is_write,
1548 &uc->uc_sigmask, puc);
1549}
1550
bellard90cb9492005-07-24 15:11:38 +00001551#elif defined(__s390__)
1552
ths5fafdf22007-09-16 21:08:06 +00001553int cpu_signal_handler(int host_signum, void *pinfo,
bellard90cb9492005-07-24 15:11:38 +00001554 void *puc)
1555{
ths5a7b5422007-01-31 12:16:51 +00001556 siginfo_t *info = pinfo;
bellard90cb9492005-07-24 15:11:38 +00001557 struct ucontext *uc = puc;
1558 unsigned long pc;
1559 int is_write;
ths3b46e622007-09-17 08:09:54 +00001560
bellard90cb9492005-07-24 15:11:38 +00001561 pc = uc->uc_mcontext.psw.addr;
1562 /* XXX: compute is_write */
1563 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001564 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
thsc4b89d12007-05-05 19:23:11 +00001565 is_write, &uc->uc_sigmask, puc);
1566}
1567
1568#elif defined(__mips__)
1569
ths5fafdf22007-09-16 21:08:06 +00001570int cpu_signal_handler(int host_signum, void *pinfo,
thsc4b89d12007-05-05 19:23:11 +00001571 void *puc)
1572{
ths9617efe2007-05-08 21:05:55 +00001573 siginfo_t *info = pinfo;
thsc4b89d12007-05-05 19:23:11 +00001574 struct ucontext *uc = puc;
1575 greg_t pc = uc->uc_mcontext.pc;
1576 int is_write;
ths3b46e622007-09-17 08:09:54 +00001577
thsc4b89d12007-05-05 19:23:11 +00001578 /* XXX: compute is_write */
1579 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001580 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
thsc4b89d12007-05-05 19:23:11 +00001581 is_write, &uc->uc_sigmask, puc);
bellard90cb9492005-07-24 15:11:38 +00001582}
1583
aurel32f54b3f92008-04-12 20:14:54 +00001584#elif defined(__hppa__)
1585
1586int cpu_signal_handler(int host_signum, void *pinfo,
1587 void *puc)
1588{
1589 struct siginfo *info = pinfo;
1590 struct ucontext *uc = puc;
1591 unsigned long pc;
1592 int is_write;
1593
1594 pc = uc->uc_mcontext.sc_iaoq[0];
1595 /* FIXME: compute is_write */
1596 is_write = 0;
1597 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1598 is_write,
1599 &uc->uc_sigmask, puc);
1600}
1601
bellard2b413142003-05-14 23:01:10 +00001602#else
1603
bellard3fb2ded2003-06-24 13:22:59 +00001604#error host CPU specific signal handler needed
bellard2b413142003-05-14 23:01:10 +00001605
1606#endif
bellard67b915a2004-03-31 23:37:16 +00001607
1608#endif /* !defined(CONFIG_SOFTMMU) */