blob: 9baa9495c2836e27eb9c857d21705dde56bc4920 [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)
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300383 if (interrupt_request & CPU_INTERRUPT_INIT) {
384 svm_check_intercept(SVM_EXIT_INIT);
385 do_cpu_init(env);
386 env->exception_index = EXCP_HALTED;
387 cpu_loop_exit();
388 } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
389 do_cpu_sipi(env);
390 } else if (env->hflags2 & HF2_GIF_MASK) {
bellarddb620f42008-06-04 17:02:19 +0000391 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
392 !(env->hflags & HF_SMM_MASK)) {
393 svm_check_intercept(SVM_EXIT_SMI);
394 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
395 do_smm_enter();
396 next_tb = 0;
397 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
398 !(env->hflags2 & HF2_NMI_MASK)) {
399 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
400 env->hflags2 |= HF2_NMI_MASK;
401 do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
402 next_tb = 0;
Huang Ying79c4f6b2009-06-23 10:05:14 +0800403 } else if (interrupt_request & CPU_INTERRUPT_MCE) {
404 env->interrupt_request &= ~CPU_INTERRUPT_MCE;
405 do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
406 next_tb = 0;
bellarddb620f42008-06-04 17:02:19 +0000407 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
408 (((env->hflags2 & HF2_VINTR_MASK) &&
409 (env->hflags2 & HF2_HIF_MASK)) ||
410 (!(env->hflags2 & HF2_VINTR_MASK) &&
411 (env->eflags & IF_MASK &&
412 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
413 int intno;
414 svm_check_intercept(SVM_EXIT_INTR);
415 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
416 intno = cpu_get_pic_interrupt(env);
aliguori93fcfe32009-01-15 22:34:14 +0000417 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
blueswir19ddff3d2009-04-04 07:41:20 +0000418#if defined(__sparc__) && !defined(HOST_SOLARIS)
419#undef env
420 env = cpu_single_env;
421#define env cpu_single_env
422#endif
bellarddb620f42008-06-04 17:02:19 +0000423 do_interrupt(intno, 0, 0, 0, 1);
424 /* ensure that no TB jump will be modified as
425 the program flow was changed */
426 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000427#if !defined(CONFIG_USER_ONLY)
bellarddb620f42008-06-04 17:02:19 +0000428 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
429 (env->eflags & IF_MASK) &&
430 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
431 int intno;
432 /* FIXME: this should respect TPR */
433 svm_check_intercept(SVM_EXIT_VINTR);
bellarddb620f42008-06-04 17:02:19 +0000434 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
aliguori93fcfe32009-01-15 22:34:14 +0000435 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
bellarddb620f42008-06-04 17:02:19 +0000436 do_interrupt(intno, 0, 0, 0, 1);
aurel32d40c54d2008-12-13 12:33:02 +0000437 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
bellarddb620f42008-06-04 17:02:19 +0000438 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000439#endif
bellarddb620f42008-06-04 17:02:19 +0000440 }
bellard68a79312003-06-30 13:12:32 +0000441 }
bellardce097762004-01-04 23:53:18 +0000442#elif defined(TARGET_PPC)
bellard9fddaa02004-05-21 12:59:32 +0000443#if 0
444 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
445 cpu_ppc_reset(env);
446 }
447#endif
j_mayer47103572007-03-30 09:38:04 +0000448 if (interrupt_request & CPU_INTERRUPT_HARD) {
j_mayere9df0142007-04-09 22:45:36 +0000449 ppc_hw_interrupt(env);
450 if (env->pending_interrupts == 0)
451 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
blueswir1b5fc09a2008-05-04 06:38:18 +0000452 next_tb = 0;
bellardce097762004-01-04 23:53:18 +0000453 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200454#elif defined(TARGET_MICROBLAZE)
455 if ((interrupt_request & CPU_INTERRUPT_HARD)
456 && (env->sregs[SR_MSR] & MSR_IE)
457 && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
458 && !(env->iflags & (D_FLAG | IMM_FLAG))) {
459 env->exception_index = EXCP_IRQ;
460 do_interrupt(env);
461 next_tb = 0;
462 }
bellard6af0bf92005-07-02 14:58:51 +0000463#elif defined(TARGET_MIPS)
464 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
ths24c7b0e2007-03-30 16:44:54 +0000465 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
bellard6af0bf92005-07-02 14:58:51 +0000466 (env->CP0_Status & (1 << CP0St_IE)) &&
ths24c7b0e2007-03-30 16:44:54 +0000467 !(env->CP0_Status & (1 << CP0St_EXL)) &&
468 !(env->CP0_Status & (1 << CP0St_ERL)) &&
bellard6af0bf92005-07-02 14:58:51 +0000469 !(env->hflags & MIPS_HFLAG_DM)) {
470 /* Raise it */
471 env->exception_index = EXCP_EXT_INTERRUPT;
472 env->error_code = 0;
473 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000474 next_tb = 0;
bellard6af0bf92005-07-02 14:58:51 +0000475 }
bellarde95c8d52004-09-30 22:22:08 +0000476#elif defined(TARGET_SPARC)
bellard66321a12005-04-06 20:47:48 +0000477 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
Igor Kovalenko52109772009-07-12 12:35:31 +0400478 cpu_interrupts_enabled(env)) {
bellard66321a12005-04-06 20:47:48 +0000479 int pil = env->interrupt_index & 15;
480 int type = env->interrupt_index & 0xf0;
481
482 if (((type == TT_EXTINT) &&
483 (pil == 15 || pil > env->psrpil)) ||
484 type != TT_EXTINT) {
485 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
blueswir1f2bc7e72008-05-27 17:35:30 +0000486 env->exception_index = env->interrupt_index;
487 do_interrupt(env);
bellard66321a12005-04-06 20:47:48 +0000488 env->interrupt_index = 0;
Igor Kovalenko52109772009-07-12 12:35:31 +0400489#if !defined(CONFIG_USER_ONLY)
blueswir1327ac2e2007-08-04 10:50:30 +0000490 cpu_check_irqs(env);
491#endif
blueswir1b5fc09a2008-05-04 06:38:18 +0000492 next_tb = 0;
bellard66321a12005-04-06 20:47:48 +0000493 }
bellarde95c8d52004-09-30 22:22:08 +0000494 } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
495 //do_interrupt(0, 0, 0, 0, 0);
496 env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
balroga90b7312007-05-01 01:28:01 +0000497 }
bellardb5ff1b32005-11-26 10:38:39 +0000498#elif defined(TARGET_ARM)
499 if (interrupt_request & CPU_INTERRUPT_FIQ
500 && !(env->uncached_cpsr & CPSR_F)) {
501 env->exception_index = EXCP_FIQ;
502 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000503 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000504 }
pbrook9ee6e8b2007-11-11 00:04:49 +0000505 /* ARMv7-M interrupt return works by loading a magic value
506 into the PC. On real hardware the load causes the
507 return to occur. The qemu implementation performs the
508 jump normally, then does the exception return when the
509 CPU tries to execute code at the magic address.
510 This will cause the magic PC value to be pushed to
511 the stack if an interrupt occured at the wrong time.
512 We avoid this by disabling interrupts when
513 pc contains a magic address. */
bellardb5ff1b32005-11-26 10:38:39 +0000514 if (interrupt_request & CPU_INTERRUPT_HARD
pbrook9ee6e8b2007-11-11 00:04:49 +0000515 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
516 || !(env->uncached_cpsr & CPSR_I))) {
bellardb5ff1b32005-11-26 10:38:39 +0000517 env->exception_index = EXCP_IRQ;
518 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000519 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000520 }
bellardfdf9b3e2006-04-27 21:07:38 +0000521#elif defined(TARGET_SH4)
thse96e2042007-12-02 06:18:24 +0000522 if (interrupt_request & CPU_INTERRUPT_HARD) {
523 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000524 next_tb = 0;
thse96e2042007-12-02 06:18:24 +0000525 }
j_mayereddf68a2007-04-05 07:22:49 +0000526#elif defined(TARGET_ALPHA)
527 if (interrupt_request & CPU_INTERRUPT_HARD) {
528 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000529 next_tb = 0;
j_mayereddf68a2007-04-05 07:22:49 +0000530 }
thsf1ccf902007-10-08 13:16:14 +0000531#elif defined(TARGET_CRIS)
edgar_igl1b1a38b2008-06-09 23:18:06 +0000532 if (interrupt_request & CPU_INTERRUPT_HARD
533 && (env->pregs[PR_CCS] & I_FLAG)) {
534 env->exception_index = EXCP_IRQ;
535 do_interrupt(env);
536 next_tb = 0;
537 }
538 if (interrupt_request & CPU_INTERRUPT_NMI
539 && (env->pregs[PR_CCS] & M_FLAG)) {
540 env->exception_index = EXCP_NMI;
thsf1ccf902007-10-08 13:16:14 +0000541 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000542 next_tb = 0;
thsf1ccf902007-10-08 13:16:14 +0000543 }
pbrook06338792007-05-23 19:58:11 +0000544#elif defined(TARGET_M68K)
545 if (interrupt_request & CPU_INTERRUPT_HARD
546 && ((env->sr & SR_I) >> SR_I_SHIFT)
547 < env->pending_level) {
548 /* Real hardware gets the interrupt vector via an
549 IACK cycle at this point. Current emulated
550 hardware doesn't rely on this, so we
551 provide/save the vector when the interrupt is
552 first signalled. */
553 env->exception_index = env->pending_vector;
554 do_interrupt(1);
blueswir1b5fc09a2008-05-04 06:38:18 +0000555 next_tb = 0;
pbrook06338792007-05-23 19:58:11 +0000556 }
bellard68a79312003-06-30 13:12:32 +0000557#endif
bellard9d050952006-05-22 22:03:52 +0000558 /* Don't use the cached interupt_request value,
559 do_interrupt may have updated the EXITTB flag. */
bellardb5ff1b32005-11-26 10:38:39 +0000560 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
bellardbf3e8bf2004-02-16 21:58:54 +0000561 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
562 /* ensure that no TB jump will be modified as
563 the program flow was changed */
blueswir1b5fc09a2008-05-04 06:38:18 +0000564 next_tb = 0;
bellardbf3e8bf2004-02-16 21:58:54 +0000565 }
aurel32be214e62009-03-06 21:48:00 +0000566 }
567 if (unlikely(env->exit_request)) {
568 env->exit_request = 0;
569 env->exception_index = EXCP_INTERRUPT;
570 cpu_loop_exit();
bellard3fb2ded2003-06-24 13:22:59 +0000571 }
572#ifdef DEBUG_EXEC
aliguori8fec2b82009-01-15 22:36:53 +0000573 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
bellard3fb2ded2003-06-24 13:22:59 +0000574 /* restore flags in standard format */
thsecb644f2007-06-03 18:45:53 +0000575 regs_to_env();
576#if defined(TARGET_I386)
pbrooka7812ae2008-11-17 14:43:54 +0000577 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
aliguori93fcfe32009-01-15 22:34:14 +0000578 log_cpu_state(env, X86_DUMP_CCOP);
bellard3fb2ded2003-06-24 13:22:59 +0000579 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellarde4533c72003-06-15 19:51:39 +0000580#elif defined(TARGET_ARM)
aliguori93fcfe32009-01-15 22:34:14 +0000581 log_cpu_state(env, 0);
bellard93ac68b2003-09-30 20:57:29 +0000582#elif defined(TARGET_SPARC)
aliguori93fcfe32009-01-15 22:34:14 +0000583 log_cpu_state(env, 0);
bellard67867302003-11-23 17:05:30 +0000584#elif defined(TARGET_PPC)
aliguori93fcfe32009-01-15 22:34:14 +0000585 log_cpu_state(env, 0);
pbrooke6e59062006-10-22 00:18:54 +0000586#elif defined(TARGET_M68K)
587 cpu_m68k_flush_flags(env, env->cc_op);
588 env->cc_op = CC_OP_FLAGS;
589 env->sr = (env->sr & 0xffe0)
590 | env->cc_dest | (env->cc_x << 4);
aliguori93fcfe32009-01-15 22:34:14 +0000591 log_cpu_state(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200592#elif defined(TARGET_MICROBLAZE)
593 log_cpu_state(env, 0);
bellard6af0bf92005-07-02 14:58:51 +0000594#elif defined(TARGET_MIPS)
aliguori93fcfe32009-01-15 22:34:14 +0000595 log_cpu_state(env, 0);
bellardfdf9b3e2006-04-27 21:07:38 +0000596#elif defined(TARGET_SH4)
aliguori93fcfe32009-01-15 22:34:14 +0000597 log_cpu_state(env, 0);
j_mayereddf68a2007-04-05 07:22:49 +0000598#elif defined(TARGET_ALPHA)
aliguori93fcfe32009-01-15 22:34:14 +0000599 log_cpu_state(env, 0);
thsf1ccf902007-10-08 13:16:14 +0000600#elif defined(TARGET_CRIS)
aliguori93fcfe32009-01-15 22:34:14 +0000601 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000602#else
ths5fafdf22007-09-16 21:08:06 +0000603#error unsupported target CPU
bellarde4533c72003-06-15 19:51:39 +0000604#endif
bellard3fb2ded2003-06-24 13:22:59 +0000605 }
bellard7d132992003-03-06 23:23:54 +0000606#endif
pbrookd5975362008-06-07 20:50:51 +0000607 spin_lock(&tb_lock);
bellard8a40a182005-11-20 10:35:40 +0000608 tb = tb_find_fast();
pbrookd5975362008-06-07 20:50:51 +0000609 /* Note: we do it here to avoid a gcc bug on Mac OS X when
610 doing it in tb_find_slow */
611 if (tb_invalidated_flag) {
612 /* as some TB could have been invalidated because
613 of memory exceptions while generating the code, we
614 must recompute the hash index here */
615 next_tb = 0;
pbrook2e70f6e2008-06-29 01:03:05 +0000616 tb_invalidated_flag = 0;
pbrookd5975362008-06-07 20:50:51 +0000617 }
bellard9d27abd2003-05-10 13:13:54 +0000618#ifdef DEBUG_EXEC
aliguori93fcfe32009-01-15 22:34:14 +0000619 qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
620 (long)tb->tc_ptr, tb->pc,
621 lookup_symbol(tb->pc));
bellard9d27abd2003-05-10 13:13:54 +0000622#endif
bellard8a40a182005-11-20 10:35:40 +0000623 /* see if we can patch the calling TB. When the TB
624 spans two pages, we cannot safely do a direct
625 jump. */
bellardc27004e2005-01-03 23:35:10 +0000626 {
blueswir1b5fc09a2008-05-04 06:38:18 +0000627 if (next_tb != 0 &&
blueswir1640f42e2009-04-19 10:18:01 +0000628#ifdef CONFIG_KQEMU
bellardf32fc642006-02-08 22:43:39 +0000629 (env->kqemu_enabled != 2) &&
630#endif
bellardec6338b2007-11-08 14:25:03 +0000631 tb->page_addr[1] == -1) {
blueswir1b5fc09a2008-05-04 06:38:18 +0000632 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
bellard3fb2ded2003-06-24 13:22:59 +0000633 }
bellardc27004e2005-01-03 23:35:10 +0000634 }
pbrookd5975362008-06-07 20:50:51 +0000635 spin_unlock(&tb_lock);
bellard83479e72003-06-25 16:12:37 +0000636 env->current_tb = tb;
malc55e8b852008-11-04 14:18:13 +0000637
638 /* cpu_interrupt might be called while translating the
639 TB, but before it is linked into a potentially
640 infinite loop and becomes env->current_tb. Avoid
641 starting execution if there is a pending interrupt. */
aurel32be214e62009-03-06 21:48:00 +0000642 if (unlikely (env->exit_request))
malc55e8b852008-11-04 14:18:13 +0000643 env->current_tb = NULL;
644
pbrook2e70f6e2008-06-29 01:03:05 +0000645 while (env->current_tb) {
646 tc_ptr = tb->tc_ptr;
bellard3fb2ded2003-06-24 13:22:59 +0000647 /* execute the generated code */
blueswir1572a9d42008-05-17 07:38:10 +0000648#if defined(__sparc__) && !defined(HOST_SOLARIS)
649#undef env
pbrook2e70f6e2008-06-29 01:03:05 +0000650 env = cpu_single_env;
blueswir1572a9d42008-05-17 07:38:10 +0000651#define env cpu_single_env
652#endif
pbrook2e70f6e2008-06-29 01:03:05 +0000653 next_tb = tcg_qemu_tb_exec(tc_ptr);
654 env->current_tb = NULL;
655 if ((next_tb & 3) == 2) {
thsbf20dc02008-06-30 17:22:19 +0000656 /* Instruction counter expired. */
pbrook2e70f6e2008-06-29 01:03:05 +0000657 int insns_left;
658 tb = (TranslationBlock *)(long)(next_tb & ~3);
659 /* Restore PC. */
aliguori622ed362008-11-18 19:36:03 +0000660 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000661 insns_left = env->icount_decr.u32;
662 if (env->icount_extra && insns_left >= 0) {
663 /* Refill decrementer and continue execution. */
664 env->icount_extra += insns_left;
665 if (env->icount_extra > 0xffff) {
666 insns_left = 0xffff;
667 } else {
668 insns_left = env->icount_extra;
669 }
670 env->icount_extra -= insns_left;
671 env->icount_decr.u16.low = insns_left;
672 } else {
673 if (insns_left > 0) {
674 /* Execute remaining instructions. */
675 cpu_exec_nocache(insns_left, tb);
676 }
677 env->exception_index = EXCP_INTERRUPT;
678 next_tb = 0;
679 cpu_loop_exit();
680 }
681 }
682 }
bellard4cbf74b2003-08-10 21:48:43 +0000683 /* reset soft MMU for next block (it can currently
684 only be set by a memory fault) */
blueswir1640f42e2009-04-19 10:18:01 +0000685#if defined(CONFIG_KQEMU)
bellardf32fc642006-02-08 22:43:39 +0000686#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
687 if (kqemu_is_ok(env) &&
688 (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
689 cpu_loop_exit();
690 }
691#endif
ths50a518e2007-06-03 18:52:15 +0000692 } /* for(;;) */
bellard3fb2ded2003-06-24 13:22:59 +0000693 } else {
bellard0d1a29f2004-10-12 22:01:28 +0000694 env_to_regs();
bellard7d132992003-03-06 23:23:54 +0000695 }
bellard3fb2ded2003-06-24 13:22:59 +0000696 } /* for(;;) */
697
bellard7d132992003-03-06 23:23:54 +0000698
bellarde4533c72003-06-15 19:51:39 +0000699#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000700 /* restore flags in standard format */
pbrooka7812ae2008-11-17 14:43:54 +0000701 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
bellarde4533c72003-06-15 19:51:39 +0000702#elif defined(TARGET_ARM)
bellardb7bcbe92005-02-22 19:27:29 +0000703 /* XXX: Save/restore host fpu exception state?. */
bellard93ac68b2003-09-30 20:57:29 +0000704#elif defined(TARGET_SPARC)
bellard67867302003-11-23 17:05:30 +0000705#elif defined(TARGET_PPC)
pbrooke6e59062006-10-22 00:18:54 +0000706#elif defined(TARGET_M68K)
707 cpu_m68k_flush_flags(env, env->cc_op);
708 env->cc_op = CC_OP_FLAGS;
709 env->sr = (env->sr & 0xffe0)
710 | env->cc_dest | (env->cc_x << 4);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200711#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000712#elif defined(TARGET_MIPS)
bellardfdf9b3e2006-04-27 21:07:38 +0000713#elif defined(TARGET_SH4)
j_mayereddf68a2007-04-05 07:22:49 +0000714#elif defined(TARGET_ALPHA)
thsf1ccf902007-10-08 13:16:14 +0000715#elif defined(TARGET_CRIS)
bellardfdf9b3e2006-04-27 21:07:38 +0000716 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000717#else
718#error unsupported target CPU
719#endif
pbrook1057eaa2007-02-04 13:37:44 +0000720
721 /* restore global registers */
pbrook1057eaa2007-02-04 13:37:44 +0000722#include "hostregs_helper.h"
723
bellard6a00d602005-11-21 23:25:50 +0000724 /* fail safe : never use cpu_single_env outside cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000725 cpu_single_env = NULL;
bellard7d132992003-03-06 23:23:54 +0000726 return ret;
727}
bellard6dbad632003-03-16 18:05:05 +0000728
bellardfbf9eeb2004-04-25 21:21:33 +0000729/* must only be called from the generated code as an exception can be
730 generated */
731void tb_invalidate_page_range(target_ulong start, target_ulong end)
732{
bellarddc5d0b32004-06-22 18:43:30 +0000733 /* XXX: cannot enable it yet because it yields to MMU exception
734 where NIP != read address on PowerPC */
735#if 0
bellardfbf9eeb2004-04-25 21:21:33 +0000736 target_ulong phys_addr;
737 phys_addr = get_phys_addr_code(env, start);
738 tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
bellarddc5d0b32004-06-22 18:43:30 +0000739#endif
bellardfbf9eeb2004-04-25 21:21:33 +0000740}
741
bellard1a18c712003-10-30 01:07:51 +0000742#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
bellarde4533c72003-06-15 19:51:39 +0000743
bellard6dbad632003-03-16 18:05:05 +0000744void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
745{
746 CPUX86State *saved_env;
747
748 saved_env = env;
749 env = s;
bellarda412ac52003-07-26 18:01:40 +0000750 if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
bellarda513fe12003-05-27 23:29:48 +0000751 selector &= 0xffff;
ths5fafdf22007-09-16 21:08:06 +0000752 cpu_x86_load_seg_cache(env, seg_reg, selector,
bellardc27004e2005-01-03 23:35:10 +0000753 (selector << 4), 0xffff, 0);
bellarda513fe12003-05-27 23:29:48 +0000754 } else {
bellard5d975592008-05-12 22:05:33 +0000755 helper_load_seg(seg_reg, selector);
bellarda513fe12003-05-27 23:29:48 +0000756 }
bellard6dbad632003-03-16 18:05:05 +0000757 env = saved_env;
758}
bellard9de5e442003-03-23 16:49:39 +0000759
bellard6f12a2a2007-11-11 22:16:56 +0000760void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
bellardd0a1ffc2003-05-29 20:04:28 +0000761{
762 CPUX86State *saved_env;
763
764 saved_env = env;
765 env = s;
ths3b46e622007-09-17 08:09:54 +0000766
bellard6f12a2a2007-11-11 22:16:56 +0000767 helper_fsave(ptr, data32);
bellardd0a1ffc2003-05-29 20:04:28 +0000768
769 env = saved_env;
770}
771
bellard6f12a2a2007-11-11 22:16:56 +0000772void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
bellardd0a1ffc2003-05-29 20:04:28 +0000773{
774 CPUX86State *saved_env;
775
776 saved_env = env;
777 env = s;
ths3b46e622007-09-17 08:09:54 +0000778
bellard6f12a2a2007-11-11 22:16:56 +0000779 helper_frstor(ptr, data32);
bellardd0a1ffc2003-05-29 20:04:28 +0000780
781 env = saved_env;
782}
783
bellarde4533c72003-06-15 19:51:39 +0000784#endif /* TARGET_I386 */
785
bellard67b915a2004-03-31 23:37:16 +0000786#if !defined(CONFIG_SOFTMMU)
787
bellard3fb2ded2003-06-24 13:22:59 +0000788#if defined(TARGET_I386)
789
bellardb56dad12003-05-08 15:38:04 +0000790/* 'pc' is the host PC at which the exception was raised. 'address' is
bellardfd6ce8f2003-05-14 19:00:11 +0000791 the effective address of the memory exception. 'is_write' is 1 if a
792 write caused the exception and otherwise 0'. 'old_set' is the
793 signal set which should be restored */
bellard2b413142003-05-14 23:01:10 +0000794static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
ths5fafdf22007-09-16 21:08:06 +0000795 int is_write, sigset_t *old_set,
bellardbf3e8bf2004-02-16 21:58:54 +0000796 void *puc)
bellard9de5e442003-03-23 16:49:39 +0000797{
bellarda513fe12003-05-27 23:29:48 +0000798 TranslationBlock *tb;
799 int ret;
bellard68a79312003-06-30 13:12:32 +0000800
bellard83479e72003-06-25 16:12:37 +0000801 if (cpu_single_env)
802 env = cpu_single_env; /* XXX: find a correct solution for multithread */
bellardfd6ce8f2003-05-14 19:00:11 +0000803#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000804 qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellardbf3e8bf2004-02-16 21:58:54 +0000805 pc, address, is_write, *(unsigned long *)old_set);
bellard9de5e442003-03-23 16:49:39 +0000806#endif
bellard25eb4482003-05-14 21:50:54 +0000807 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000808 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellardfd6ce8f2003-05-14 19:00:11 +0000809 return 1;
810 }
bellardfbf9eeb2004-04-25 21:21:33 +0000811
bellard3fb2ded2003-06-24 13:22:59 +0000812 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000813 ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard3fb2ded2003-06-24 13:22:59 +0000814 if (ret < 0)
815 return 0; /* not an MMU fault */
816 if (ret == 0)
817 return 1; /* the MMU fault was handled without causing real CPU fault */
818 /* now we have a real cpu fault */
bellarda513fe12003-05-27 23:29:48 +0000819 tb = tb_find_pc(pc);
820 if (tb) {
bellard9de5e442003-03-23 16:49:39 +0000821 /* the PC is inside the translated code. It means that we have
822 a virtual CPU fault */
bellardbf3e8bf2004-02-16 21:58:54 +0000823 cpu_restore_state(tb, env, pc, puc);
bellard3fb2ded2003-06-24 13:22:59 +0000824 }
bellard4cbf74b2003-08-10 21:48:43 +0000825 if (ret == 1) {
bellard3fb2ded2003-06-24 13:22:59 +0000826#if 0
ths5fafdf22007-09-16 21:08:06 +0000827 printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
bellard4cbf74b2003-08-10 21:48:43 +0000828 env->eip, env->cr[2], env->error_code);
bellard3fb2ded2003-06-24 13:22:59 +0000829#endif
bellard4cbf74b2003-08-10 21:48:43 +0000830 /* we restore the process signal mask as the sigreturn should
831 do it (XXX: use sigsetjmp) */
832 sigprocmask(SIG_SETMASK, old_set, NULL);
bellard54ca9092005-12-04 18:46:06 +0000833 raise_exception_err(env->exception_index, env->error_code);
bellard4cbf74b2003-08-10 21:48:43 +0000834 } else {
835 /* activate soft MMU for this block */
bellard3f337312003-08-20 23:02:09 +0000836 env->hflags |= HF_SOFTMMU_MASK;
bellardfbf9eeb2004-04-25 21:21:33 +0000837 cpu_resume_from_signal(env, puc);
bellard4cbf74b2003-08-10 21:48:43 +0000838 }
bellard3fb2ded2003-06-24 13:22:59 +0000839 /* never comes here */
840 return 1;
841}
842
bellarde4533c72003-06-15 19:51:39 +0000843#elif defined(TARGET_ARM)
bellard3fb2ded2003-06-24 13:22:59 +0000844static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bellardbf3e8bf2004-02-16 21:58:54 +0000845 int is_write, sigset_t *old_set,
846 void *puc)
bellard3fb2ded2003-06-24 13:22:59 +0000847{
bellard68016c62005-02-07 23:12:27 +0000848 TranslationBlock *tb;
849 int ret;
850
851 if (cpu_single_env)
852 env = cpu_single_env; /* XXX: find a correct solution for multithread */
853#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000854 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard68016c62005-02-07 23:12:27 +0000855 pc, address, is_write, *(unsigned long *)old_set);
856#endif
bellard9f0777e2005-02-02 20:42:01 +0000857 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000858 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellard9f0777e2005-02-02 20:42:01 +0000859 return 1;
860 }
bellard68016c62005-02-07 23:12:27 +0000861 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000862 ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard68016c62005-02-07 23:12:27 +0000863 if (ret < 0)
864 return 0; /* not an MMU fault */
865 if (ret == 0)
866 return 1; /* the MMU fault was handled without causing real CPU fault */
867 /* now we have a real cpu fault */
868 tb = tb_find_pc(pc);
869 if (tb) {
870 /* the PC is inside the translated code. It means that we have
871 a virtual CPU fault */
872 cpu_restore_state(tb, env, pc, puc);
873 }
874 /* we restore the process signal mask as the sigreturn should
875 do it (XXX: use sigsetjmp) */
876 sigprocmask(SIG_SETMASK, old_set, NULL);
877 cpu_loop_exit();
aurel32968c74d2008-04-11 04:55:17 +0000878 /* never comes here */
879 return 1;
bellard3fb2ded2003-06-24 13:22:59 +0000880}
bellard93ac68b2003-09-30 20:57:29 +0000881#elif defined(TARGET_SPARC)
882static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bellardbf3e8bf2004-02-16 21:58:54 +0000883 int is_write, sigset_t *old_set,
884 void *puc)
bellard93ac68b2003-09-30 20:57:29 +0000885{
bellard68016c62005-02-07 23:12:27 +0000886 TranslationBlock *tb;
887 int ret;
888
889 if (cpu_single_env)
890 env = cpu_single_env; /* XXX: find a correct solution for multithread */
891#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000892 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard68016c62005-02-07 23:12:27 +0000893 pc, address, is_write, *(unsigned long *)old_set);
894#endif
bellardb453b702004-01-04 15:45:21 +0000895 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000896 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellardb453b702004-01-04 15:45:21 +0000897 return 1;
898 }
bellard68016c62005-02-07 23:12:27 +0000899 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000900 ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard68016c62005-02-07 23:12:27 +0000901 if (ret < 0)
902 return 0; /* not an MMU fault */
903 if (ret == 0)
904 return 1; /* the MMU fault was handled without causing real CPU fault */
905 /* now we have a real cpu fault */
906 tb = tb_find_pc(pc);
907 if (tb) {
908 /* the PC is inside the translated code. It means that we have
909 a virtual CPU fault */
910 cpu_restore_state(tb, env, pc, puc);
911 }
912 /* we restore the process signal mask as the sigreturn should
913 do it (XXX: use sigsetjmp) */
914 sigprocmask(SIG_SETMASK, old_set, NULL);
915 cpu_loop_exit();
aurel32968c74d2008-04-11 04:55:17 +0000916 /* never comes here */
917 return 1;
bellard93ac68b2003-09-30 20:57:29 +0000918}
bellard67867302003-11-23 17:05:30 +0000919#elif defined (TARGET_PPC)
920static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bellardbf3e8bf2004-02-16 21:58:54 +0000921 int is_write, sigset_t *old_set,
922 void *puc)
bellard67867302003-11-23 17:05:30 +0000923{
924 TranslationBlock *tb;
bellardce097762004-01-04 23:53:18 +0000925 int ret;
ths3b46e622007-09-17 08:09:54 +0000926
bellard67867302003-11-23 17:05:30 +0000927 if (cpu_single_env)
928 env = cpu_single_env; /* XXX: find a correct solution for multithread */
bellard67867302003-11-23 17:05:30 +0000929#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000930 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard67867302003-11-23 17:05:30 +0000931 pc, address, is_write, *(unsigned long *)old_set);
932#endif
933 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000934 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellard67867302003-11-23 17:05:30 +0000935 return 1;
936 }
937
bellardce097762004-01-04 23:53:18 +0000938 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000939 ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellardce097762004-01-04 23:53:18 +0000940 if (ret < 0)
941 return 0; /* not an MMU fault */
942 if (ret == 0)
943 return 1; /* the MMU fault was handled without causing real CPU fault */
944
bellard67867302003-11-23 17:05:30 +0000945 /* now we have a real cpu fault */
946 tb = tb_find_pc(pc);
947 if (tb) {
948 /* the PC is inside the translated code. It means that we have
949 a virtual CPU fault */
bellardbf3e8bf2004-02-16 21:58:54 +0000950 cpu_restore_state(tb, env, pc, puc);
bellard67867302003-11-23 17:05:30 +0000951 }
bellardce097762004-01-04 23:53:18 +0000952 if (ret == 1) {
bellard67867302003-11-23 17:05:30 +0000953#if 0
ths5fafdf22007-09-16 21:08:06 +0000954 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
bellardce097762004-01-04 23:53:18 +0000955 env->nip, env->error_code, tb);
bellard67867302003-11-23 17:05:30 +0000956#endif
957 /* we restore the process signal mask as the sigreturn should
958 do it (XXX: use sigsetjmp) */
bellardbf3e8bf2004-02-16 21:58:54 +0000959 sigprocmask(SIG_SETMASK, old_set, NULL);
aurel32e06fcd72008-12-11 22:42:14 +0000960 cpu_loop_exit();
bellardce097762004-01-04 23:53:18 +0000961 } else {
962 /* activate soft MMU for this block */
bellardfbf9eeb2004-04-25 21:21:33 +0000963 cpu_resume_from_signal(env, puc);
bellardce097762004-01-04 23:53:18 +0000964 }
bellard67867302003-11-23 17:05:30 +0000965 /* never comes here */
966 return 1;
967}
bellard6af0bf92005-07-02 14:58:51 +0000968
pbrooke6e59062006-10-22 00:18:54 +0000969#elif defined(TARGET_M68K)
970static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
971 int is_write, sigset_t *old_set,
972 void *puc)
973{
974 TranslationBlock *tb;
975 int ret;
976
977 if (cpu_single_env)
978 env = cpu_single_env; /* XXX: find a correct solution for multithread */
979#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000980 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
pbrooke6e59062006-10-22 00:18:54 +0000981 pc, address, is_write, *(unsigned long *)old_set);
982#endif
983 /* XXX: locking issue */
984 if (is_write && page_unprotect(address, pc, puc)) {
985 return 1;
986 }
987 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000988 ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
pbrooke6e59062006-10-22 00:18:54 +0000989 if (ret < 0)
990 return 0; /* not an MMU fault */
991 if (ret == 0)
992 return 1; /* the MMU fault was handled without causing real CPU fault */
993 /* now we have a real cpu fault */
994 tb = tb_find_pc(pc);
995 if (tb) {
996 /* the PC is inside the translated code. It means that we have
997 a virtual CPU fault */
998 cpu_restore_state(tb, env, pc, puc);
999 }
1000 /* we restore the process signal mask as the sigreturn should
1001 do it (XXX: use sigsetjmp) */
1002 sigprocmask(SIG_SETMASK, old_set, NULL);
1003 cpu_loop_exit();
1004 /* never comes here */
1005 return 1;
1006}
1007
bellard6af0bf92005-07-02 14:58:51 +00001008#elif defined (TARGET_MIPS)
1009static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1010 int is_write, sigset_t *old_set,
1011 void *puc)
1012{
1013 TranslationBlock *tb;
1014 int ret;
ths3b46e622007-09-17 08:09:54 +00001015
bellard6af0bf92005-07-02 14:58:51 +00001016 if (cpu_single_env)
1017 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1018#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001019 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard6af0bf92005-07-02 14:58:51 +00001020 pc, address, is_write, *(unsigned long *)old_set);
1021#endif
1022 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +00001023 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellard6af0bf92005-07-02 14:58:51 +00001024 return 1;
1025 }
1026
1027 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001028 ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard6af0bf92005-07-02 14:58:51 +00001029 if (ret < 0)
1030 return 0; /* not an MMU fault */
1031 if (ret == 0)
1032 return 1; /* the MMU fault was handled without causing real CPU fault */
1033
1034 /* now we have a real cpu fault */
1035 tb = tb_find_pc(pc);
1036 if (tb) {
1037 /* the PC is inside the translated code. It means that we have
1038 a virtual CPU fault */
1039 cpu_restore_state(tb, env, pc, puc);
1040 }
1041 if (ret == 1) {
1042#if 0
ths5fafdf22007-09-16 21:08:06 +00001043 printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
ths1eb52072007-05-12 16:57:42 +00001044 env->PC, env->error_code, tb);
bellard6af0bf92005-07-02 14:58:51 +00001045#endif
1046 /* we restore the process signal mask as the sigreturn should
1047 do it (XXX: use sigsetjmp) */
1048 sigprocmask(SIG_SETMASK, old_set, NULL);
thsf9480ff2008-12-20 19:42:14 +00001049 cpu_loop_exit();
bellard6af0bf92005-07-02 14:58:51 +00001050 } else {
1051 /* activate soft MMU for this block */
1052 cpu_resume_from_signal(env, puc);
1053 }
1054 /* never comes here */
1055 return 1;
1056}
1057
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02001058#elif defined (TARGET_MICROBLAZE)
1059static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1060 int is_write, sigset_t *old_set,
1061 void *puc)
1062{
1063 TranslationBlock *tb;
1064 int ret;
1065
1066 if (cpu_single_env)
1067 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1068#if defined(DEBUG_SIGNAL)
1069 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1070 pc, address, is_write, *(unsigned long *)old_set);
1071#endif
1072 /* XXX: locking issue */
1073 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1074 return 1;
1075 }
1076
1077 /* see if it is an MMU fault */
1078 ret = cpu_mb_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1079 if (ret < 0)
1080 return 0; /* not an MMU fault */
1081 if (ret == 0)
1082 return 1; /* the MMU fault was handled without causing real CPU fault */
1083
1084 /* now we have a real cpu fault */
1085 tb = tb_find_pc(pc);
1086 if (tb) {
1087 /* the PC is inside the translated code. It means that we have
1088 a virtual CPU fault */
1089 cpu_restore_state(tb, env, pc, puc);
1090 }
1091 if (ret == 1) {
1092#if 0
1093 printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1094 env->PC, env->error_code, tb);
1095#endif
1096 /* we restore the process signal mask as the sigreturn should
1097 do it (XXX: use sigsetjmp) */
1098 sigprocmask(SIG_SETMASK, old_set, NULL);
1099 cpu_loop_exit();
1100 } else {
1101 /* activate soft MMU for this block */
1102 cpu_resume_from_signal(env, puc);
1103 }
1104 /* never comes here */
1105 return 1;
1106}
1107
bellardfdf9b3e2006-04-27 21:07:38 +00001108#elif defined (TARGET_SH4)
1109static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1110 int is_write, sigset_t *old_set,
1111 void *puc)
1112{
1113 TranslationBlock *tb;
1114 int ret;
ths3b46e622007-09-17 08:09:54 +00001115
bellardfdf9b3e2006-04-27 21:07:38 +00001116 if (cpu_single_env)
1117 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1118#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001119 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellardfdf9b3e2006-04-27 21:07:38 +00001120 pc, address, is_write, *(unsigned long *)old_set);
1121#endif
1122 /* XXX: locking issue */
1123 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1124 return 1;
1125 }
1126
1127 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001128 ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellardfdf9b3e2006-04-27 21:07:38 +00001129 if (ret < 0)
1130 return 0; /* not an MMU fault */
1131 if (ret == 0)
1132 return 1; /* the MMU fault was handled without causing real CPU fault */
1133
1134 /* now we have a real cpu fault */
1135 tb = tb_find_pc(pc);
1136 if (tb) {
1137 /* the PC is inside the translated code. It means that we have
1138 a virtual CPU fault */
1139 cpu_restore_state(tb, env, pc, puc);
1140 }
bellardfdf9b3e2006-04-27 21:07:38 +00001141#if 0
ths5fafdf22007-09-16 21:08:06 +00001142 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
bellardfdf9b3e2006-04-27 21:07:38 +00001143 env->nip, env->error_code, tb);
1144#endif
1145 /* we restore the process signal mask as the sigreturn should
1146 do it (XXX: use sigsetjmp) */
pbrook355fb232006-06-17 19:58:25 +00001147 sigprocmask(SIG_SETMASK, old_set, NULL);
1148 cpu_loop_exit();
bellardfdf9b3e2006-04-27 21:07:38 +00001149 /* never comes here */
1150 return 1;
1151}
j_mayereddf68a2007-04-05 07:22:49 +00001152
1153#elif defined (TARGET_ALPHA)
1154static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1155 int is_write, sigset_t *old_set,
1156 void *puc)
1157{
1158 TranslationBlock *tb;
1159 int ret;
ths3b46e622007-09-17 08:09:54 +00001160
j_mayereddf68a2007-04-05 07:22:49 +00001161 if (cpu_single_env)
1162 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1163#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001164 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
j_mayereddf68a2007-04-05 07:22:49 +00001165 pc, address, is_write, *(unsigned long *)old_set);
1166#endif
1167 /* XXX: locking issue */
1168 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1169 return 1;
1170 }
1171
1172 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001173 ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
j_mayereddf68a2007-04-05 07:22:49 +00001174 if (ret < 0)
1175 return 0; /* not an MMU fault */
1176 if (ret == 0)
1177 return 1; /* the MMU fault was handled without causing real CPU fault */
1178
1179 /* now we have a real cpu fault */
1180 tb = tb_find_pc(pc);
1181 if (tb) {
1182 /* the PC is inside the translated code. It means that we have
1183 a virtual CPU fault */
1184 cpu_restore_state(tb, env, pc, puc);
1185 }
1186#if 0
ths5fafdf22007-09-16 21:08:06 +00001187 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
j_mayereddf68a2007-04-05 07:22:49 +00001188 env->nip, env->error_code, tb);
1189#endif
1190 /* we restore the process signal mask as the sigreturn should
1191 do it (XXX: use sigsetjmp) */
1192 sigprocmask(SIG_SETMASK, old_set, NULL);
1193 cpu_loop_exit();
1194 /* never comes here */
1195 return 1;
1196}
thsf1ccf902007-10-08 13:16:14 +00001197#elif defined (TARGET_CRIS)
1198static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1199 int is_write, sigset_t *old_set,
1200 void *puc)
1201{
1202 TranslationBlock *tb;
1203 int ret;
1204
1205 if (cpu_single_env)
1206 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1207#if defined(DEBUG_SIGNAL)
1208 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1209 pc, address, is_write, *(unsigned long *)old_set);
1210#endif
1211 /* XXX: locking issue */
1212 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1213 return 1;
1214 }
1215
1216 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001217 ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
thsf1ccf902007-10-08 13:16:14 +00001218 if (ret < 0)
1219 return 0; /* not an MMU fault */
1220 if (ret == 0)
1221 return 1; /* the MMU fault was handled without causing real CPU fault */
1222
1223 /* now we have a real cpu fault */
1224 tb = tb_find_pc(pc);
1225 if (tb) {
1226 /* the PC is inside the translated code. It means that we have
1227 a virtual CPU fault */
1228 cpu_restore_state(tb, env, pc, puc);
1229 }
thsf1ccf902007-10-08 13:16:14 +00001230 /* we restore the process signal mask as the sigreturn should
1231 do it (XXX: use sigsetjmp) */
1232 sigprocmask(SIG_SETMASK, old_set, NULL);
1233 cpu_loop_exit();
1234 /* never comes here */
1235 return 1;
1236}
1237
bellarde4533c72003-06-15 19:51:39 +00001238#else
1239#error unsupported target CPU
1240#endif
bellard9de5e442003-03-23 16:49:39 +00001241
bellard2b413142003-05-14 23:01:10 +00001242#if defined(__i386__)
1243
bellardd8ecc0b2007-02-05 21:41:46 +00001244#if defined(__APPLE__)
1245# include <sys/ucontext.h>
1246
1247# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1248# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
1249# define ERROR_sig(context) ((context)->uc_mcontext->es.err)
blueswir1d39bb242009-04-10 07:29:34 +00001250# define MASK_sig(context) ((context)->uc_sigmask)
1251#elif defined(__OpenBSD__)
1252# define EIP_sig(context) ((context)->sc_eip)
1253# define TRAP_sig(context) ((context)->sc_trapno)
1254# define ERROR_sig(context) ((context)->sc_err)
1255# define MASK_sig(context) ((context)->sc_mask)
bellardd8ecc0b2007-02-05 21:41:46 +00001256#else
1257# define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
1258# define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
1259# define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
blueswir1d39bb242009-04-10 07:29:34 +00001260# define MASK_sig(context) ((context)->uc_sigmask)
bellardd8ecc0b2007-02-05 21:41:46 +00001261#endif
1262
ths5fafdf22007-09-16 21:08:06 +00001263int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001264 void *puc)
bellard9de5e442003-03-23 16:49:39 +00001265{
ths5a7b5422007-01-31 12:16:51 +00001266 siginfo_t *info = pinfo;
blueswir1d39bb242009-04-10 07:29:34 +00001267#if defined(__OpenBSD__)
1268 struct sigcontext *uc = puc;
1269#else
bellard9de5e442003-03-23 16:49:39 +00001270 struct ucontext *uc = puc;
blueswir1d39bb242009-04-10 07:29:34 +00001271#endif
bellard9de5e442003-03-23 16:49:39 +00001272 unsigned long pc;
bellardbf3e8bf2004-02-16 21:58:54 +00001273 int trapno;
bellard97eb5b12004-02-25 23:19:55 +00001274
bellardd691f662003-03-24 21:58:34 +00001275#ifndef REG_EIP
1276/* for glibc 2.1 */
bellardfd6ce8f2003-05-14 19:00:11 +00001277#define REG_EIP EIP
1278#define REG_ERR ERR
1279#define REG_TRAPNO TRAPNO
bellardd691f662003-03-24 21:58:34 +00001280#endif
bellardd8ecc0b2007-02-05 21:41:46 +00001281 pc = EIP_sig(uc);
1282 trapno = TRAP_sig(uc);
bellardec6338b2007-11-08 14:25:03 +00001283 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1284 trapno == 0xe ?
1285 (ERROR_sig(uc) >> 1) & 1 : 0,
blueswir1d39bb242009-04-10 07:29:34 +00001286 &MASK_sig(uc), puc);
bellard2b413142003-05-14 23:01:10 +00001287}
1288
bellardbc51c5c2004-03-17 23:46:04 +00001289#elif defined(__x86_64__)
1290
blueswir1b3efe5c2008-12-05 17:55:45 +00001291#ifdef __NetBSD__
blueswir1d397abb2009-04-10 13:00:29 +00001292#define PC_sig(context) _UC_MACHINE_PC(context)
1293#define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
1294#define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
1295#define MASK_sig(context) ((context)->uc_sigmask)
1296#elif defined(__OpenBSD__)
1297#define PC_sig(context) ((context)->sc_rip)
1298#define TRAP_sig(context) ((context)->sc_trapno)
1299#define ERROR_sig(context) ((context)->sc_err)
1300#define MASK_sig(context) ((context)->sc_mask)
blueswir1b3efe5c2008-12-05 17:55:45 +00001301#else
blueswir1d397abb2009-04-10 13:00:29 +00001302#define PC_sig(context) ((context)->uc_mcontext.gregs[REG_RIP])
1303#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
1304#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
1305#define MASK_sig(context) ((context)->uc_sigmask)
blueswir1b3efe5c2008-12-05 17:55:45 +00001306#endif
1307
ths5a7b5422007-01-31 12:16:51 +00001308int cpu_signal_handler(int host_signum, void *pinfo,
bellardbc51c5c2004-03-17 23:46:04 +00001309 void *puc)
1310{
ths5a7b5422007-01-31 12:16:51 +00001311 siginfo_t *info = pinfo;
bellardbc51c5c2004-03-17 23:46:04 +00001312 unsigned long pc;
blueswir1b3efe5c2008-12-05 17:55:45 +00001313#ifdef __NetBSD__
1314 ucontext_t *uc = puc;
blueswir1d397abb2009-04-10 13:00:29 +00001315#elif defined(__OpenBSD__)
1316 struct sigcontext *uc = puc;
blueswir1b3efe5c2008-12-05 17:55:45 +00001317#else
1318 struct ucontext *uc = puc;
1319#endif
bellardbc51c5c2004-03-17 23:46:04 +00001320
blueswir1d397abb2009-04-10 13:00:29 +00001321 pc = PC_sig(uc);
ths5fafdf22007-09-16 21:08:06 +00001322 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
blueswir1d397abb2009-04-10 13:00:29 +00001323 TRAP_sig(uc) == 0xe ?
1324 (ERROR_sig(uc) >> 1) & 1 : 0,
1325 &MASK_sig(uc), puc);
bellardbc51c5c2004-03-17 23:46:04 +00001326}
1327
malce58ffeb2009-01-14 18:39:49 +00001328#elif defined(_ARCH_PPC)
bellard2b413142003-05-14 23:01:10 +00001329
bellard83fb7ad2004-07-05 21:25:26 +00001330/***********************************************************************
1331 * signal context platform-specific definitions
1332 * From Wine
1333 */
1334#ifdef linux
1335/* All Registers access - only for local access */
1336# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
1337/* Gpr Registers access */
1338# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
1339# define IAR_sig(context) REG_sig(nip, context) /* Program counter */
1340# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
1341# define CTR_sig(context) REG_sig(ctr, context) /* Count register */
1342# define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
1343# define LR_sig(context) REG_sig(link, context) /* Link register */
1344# define CR_sig(context) REG_sig(ccr, context) /* Condition register */
1345/* Float Registers access */
1346# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1347# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1348/* Exception Registers access */
1349# define DAR_sig(context) REG_sig(dar, context)
1350# define DSISR_sig(context) REG_sig(dsisr, context)
1351# define TRAP_sig(context) REG_sig(trap, context)
1352#endif /* linux */
1353
1354#ifdef __APPLE__
1355# include <sys/ucontext.h>
1356typedef struct ucontext SIGCONTEXT;
1357/* All Registers access - only for local access */
1358# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
1359# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
1360# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
1361# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
1362/* Gpr Registers access */
1363# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
1364# define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
1365# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
1366# define CTR_sig(context) REG_sig(ctr, context)
1367# define XER_sig(context) REG_sig(xer, context) /* Link register */
1368# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
1369# define CR_sig(context) REG_sig(cr, context) /* Condition register */
1370/* Float Registers access */
1371# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
1372# define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
1373/* Exception Registers access */
1374# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
1375# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
1376# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1377#endif /* __APPLE__ */
1378
ths5fafdf22007-09-16 21:08:06 +00001379int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001380 void *puc)
bellard2b413142003-05-14 23:01:10 +00001381{
ths5a7b5422007-01-31 12:16:51 +00001382 siginfo_t *info = pinfo;
bellard25eb4482003-05-14 21:50:54 +00001383 struct ucontext *uc = puc;
bellard25eb4482003-05-14 21:50:54 +00001384 unsigned long pc;
bellard25eb4482003-05-14 21:50:54 +00001385 int is_write;
1386
bellard83fb7ad2004-07-05 21:25:26 +00001387 pc = IAR_sig(uc);
bellard25eb4482003-05-14 21:50:54 +00001388 is_write = 0;
1389#if 0
1390 /* ppc 4xx case */
bellard83fb7ad2004-07-05 21:25:26 +00001391 if (DSISR_sig(uc) & 0x00800000)
bellard25eb4482003-05-14 21:50:54 +00001392 is_write = 1;
bellard9de5e442003-03-23 16:49:39 +00001393#else
bellard83fb7ad2004-07-05 21:25:26 +00001394 if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
bellard25eb4482003-05-14 21:50:54 +00001395 is_write = 1;
1396#endif
ths5fafdf22007-09-16 21:08:06 +00001397 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001398 is_write, &uc->uc_sigmask, puc);
bellard9de5e442003-03-23 16:49:39 +00001399}
bellard2b413142003-05-14 23:01:10 +00001400
bellard2f87c602003-06-02 20:38:09 +00001401#elif defined(__alpha__)
1402
ths5fafdf22007-09-16 21:08:06 +00001403int cpu_signal_handler(int host_signum, void *pinfo,
bellard2f87c602003-06-02 20:38:09 +00001404 void *puc)
1405{
ths5a7b5422007-01-31 12:16:51 +00001406 siginfo_t *info = pinfo;
bellard2f87c602003-06-02 20:38:09 +00001407 struct ucontext *uc = puc;
1408 uint32_t *pc = uc->uc_mcontext.sc_pc;
1409 uint32_t insn = *pc;
1410 int is_write = 0;
1411
bellard8c6939c2003-06-09 15:28:00 +00001412 /* XXX: need kernel patch to get write flag faster */
bellard2f87c602003-06-02 20:38:09 +00001413 switch (insn >> 26) {
1414 case 0x0d: // stw
1415 case 0x0e: // stb
1416 case 0x0f: // stq_u
1417 case 0x24: // stf
1418 case 0x25: // stg
1419 case 0x26: // sts
1420 case 0x27: // stt
1421 case 0x2c: // stl
1422 case 0x2d: // stq
1423 case 0x2e: // stl_c
1424 case 0x2f: // stq_c
1425 is_write = 1;
1426 }
1427
ths5fafdf22007-09-16 21:08:06 +00001428 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001429 is_write, &uc->uc_sigmask, puc);
bellard2f87c602003-06-02 20:38:09 +00001430}
bellard8c6939c2003-06-09 15:28:00 +00001431#elif defined(__sparc__)
1432
ths5fafdf22007-09-16 21:08:06 +00001433int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001434 void *puc)
bellard8c6939c2003-06-09 15:28:00 +00001435{
ths5a7b5422007-01-31 12:16:51 +00001436 siginfo_t *info = pinfo;
bellard8c6939c2003-06-09 15:28:00 +00001437 int is_write;
1438 uint32_t insn;
blueswir16b4c11c2008-05-19 17:20:01 +00001439#if !defined(__arch64__) || defined(HOST_SOLARIS)
blueswir1c9e1e2b2008-05-18 06:40:16 +00001440 uint32_t *regs = (uint32_t *)(info + 1);
1441 void *sigmask = (regs + 20);
bellard8c6939c2003-06-09 15:28:00 +00001442 /* XXX: is there a standard glibc define ? */
blueswir1c9e1e2b2008-05-18 06:40:16 +00001443 unsigned long pc = regs[1];
1444#else
blueswir184778502008-10-26 20:33:16 +00001445#ifdef __linux__
blueswir1c9e1e2b2008-05-18 06:40:16 +00001446 struct sigcontext *sc = puc;
1447 unsigned long pc = sc->sigc_regs.tpc;
1448 void *sigmask = (void *)sc->sigc_mask;
blueswir184778502008-10-26 20:33:16 +00001449#elif defined(__OpenBSD__)
1450 struct sigcontext *uc = puc;
1451 unsigned long pc = uc->sc_pc;
1452 void *sigmask = (void *)(long)uc->sc_mask;
1453#endif
blueswir1c9e1e2b2008-05-18 06:40:16 +00001454#endif
1455
bellard8c6939c2003-06-09 15:28:00 +00001456 /* XXX: need kernel patch to get write flag faster */
1457 is_write = 0;
1458 insn = *(uint32_t *)pc;
1459 if ((insn >> 30) == 3) {
1460 switch((insn >> 19) & 0x3f) {
1461 case 0x05: // stb
Blue Swirld877fa52009-04-25 19:07:16 +00001462 case 0x15: // stba
bellard8c6939c2003-06-09 15:28:00 +00001463 case 0x06: // sth
Blue Swirld877fa52009-04-25 19:07:16 +00001464 case 0x16: // stha
bellard8c6939c2003-06-09 15:28:00 +00001465 case 0x04: // st
Blue Swirld877fa52009-04-25 19:07:16 +00001466 case 0x14: // sta
bellard8c6939c2003-06-09 15:28:00 +00001467 case 0x07: // std
Blue Swirld877fa52009-04-25 19:07:16 +00001468 case 0x17: // stda
1469 case 0x0e: // stx
1470 case 0x1e: // stxa
bellard8c6939c2003-06-09 15:28:00 +00001471 case 0x24: // stf
Blue Swirld877fa52009-04-25 19:07:16 +00001472 case 0x34: // stfa
bellard8c6939c2003-06-09 15:28:00 +00001473 case 0x27: // stdf
Blue Swirld877fa52009-04-25 19:07:16 +00001474 case 0x37: // stdfa
1475 case 0x26: // stqf
1476 case 0x36: // stqfa
bellard8c6939c2003-06-09 15:28:00 +00001477 case 0x25: // stfsr
Blue Swirld877fa52009-04-25 19:07:16 +00001478 case 0x3c: // casa
1479 case 0x3e: // casxa
bellard8c6939c2003-06-09 15:28:00 +00001480 is_write = 1;
1481 break;
1482 }
1483 }
ths5fafdf22007-09-16 21:08:06 +00001484 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001485 is_write, sigmask, NULL);
bellard8c6939c2003-06-09 15:28:00 +00001486}
1487
1488#elif defined(__arm__)
1489
ths5fafdf22007-09-16 21:08:06 +00001490int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001491 void *puc)
bellard8c6939c2003-06-09 15:28:00 +00001492{
ths5a7b5422007-01-31 12:16:51 +00001493 siginfo_t *info = pinfo;
bellard8c6939c2003-06-09 15:28:00 +00001494 struct ucontext *uc = puc;
1495 unsigned long pc;
1496 int is_write;
ths3b46e622007-09-17 08:09:54 +00001497
blueswir148bbf112008-07-08 18:35:02 +00001498#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
balrog5c49b362008-06-02 01:01:18 +00001499 pc = uc->uc_mcontext.gregs[R15];
1500#else
balrog4eee57f2008-05-06 14:47:19 +00001501 pc = uc->uc_mcontext.arm_pc;
balrog5c49b362008-06-02 01:01:18 +00001502#endif
bellard8c6939c2003-06-09 15:28:00 +00001503 /* XXX: compute is_write */
1504 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001505 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellard8c6939c2003-06-09 15:28:00 +00001506 is_write,
pbrookf3a96762006-07-29 19:09:31 +00001507 &uc->uc_sigmask, puc);
bellard8c6939c2003-06-09 15:28:00 +00001508}
1509
bellard38e584a2003-08-10 22:14:22 +00001510#elif defined(__mc68000)
1511
ths5fafdf22007-09-16 21:08:06 +00001512int cpu_signal_handler(int host_signum, void *pinfo,
bellard38e584a2003-08-10 22:14:22 +00001513 void *puc)
1514{
ths5a7b5422007-01-31 12:16:51 +00001515 siginfo_t *info = pinfo;
bellard38e584a2003-08-10 22:14:22 +00001516 struct ucontext *uc = puc;
1517 unsigned long pc;
1518 int is_write;
ths3b46e622007-09-17 08:09:54 +00001519
bellard38e584a2003-08-10 22:14:22 +00001520 pc = uc->uc_mcontext.gregs[16];
1521 /* XXX: compute is_write */
1522 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001523 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellard38e584a2003-08-10 22:14:22 +00001524 is_write,
bellardbf3e8bf2004-02-16 21:58:54 +00001525 &uc->uc_sigmask, puc);
bellard38e584a2003-08-10 22:14:22 +00001526}
1527
bellardb8076a72005-04-07 22:20:31 +00001528#elif defined(__ia64)
1529
1530#ifndef __ISR_VALID
1531 /* This ought to be in <bits/siginfo.h>... */
1532# define __ISR_VALID 1
bellardb8076a72005-04-07 22:20:31 +00001533#endif
1534
ths5a7b5422007-01-31 12:16:51 +00001535int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
bellardb8076a72005-04-07 22:20:31 +00001536{
ths5a7b5422007-01-31 12:16:51 +00001537 siginfo_t *info = pinfo;
bellardb8076a72005-04-07 22:20:31 +00001538 struct ucontext *uc = puc;
1539 unsigned long ip;
1540 int is_write = 0;
1541
1542 ip = uc->uc_mcontext.sc_ip;
1543 switch (host_signum) {
1544 case SIGILL:
1545 case SIGFPE:
1546 case SIGSEGV:
1547 case SIGBUS:
1548 case SIGTRAP:
bellardfd4a43e2006-04-24 20:32:17 +00001549 if (info->si_code && (info->si_segvflags & __ISR_VALID))
bellardb8076a72005-04-07 22:20:31 +00001550 /* ISR.W (write-access) is bit 33: */
1551 is_write = (info->si_isr >> 33) & 1;
1552 break;
1553
1554 default:
1555 break;
1556 }
1557 return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1558 is_write,
1559 &uc->uc_sigmask, puc);
1560}
1561
bellard90cb9492005-07-24 15:11:38 +00001562#elif defined(__s390__)
1563
ths5fafdf22007-09-16 21:08:06 +00001564int cpu_signal_handler(int host_signum, void *pinfo,
bellard90cb9492005-07-24 15:11:38 +00001565 void *puc)
1566{
ths5a7b5422007-01-31 12:16:51 +00001567 siginfo_t *info = pinfo;
bellard90cb9492005-07-24 15:11:38 +00001568 struct ucontext *uc = puc;
1569 unsigned long pc;
1570 int is_write;
ths3b46e622007-09-17 08:09:54 +00001571
bellard90cb9492005-07-24 15:11:38 +00001572 pc = uc->uc_mcontext.psw.addr;
1573 /* XXX: compute is_write */
1574 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001575 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
thsc4b89d12007-05-05 19:23:11 +00001576 is_write, &uc->uc_sigmask, puc);
1577}
1578
1579#elif defined(__mips__)
1580
ths5fafdf22007-09-16 21:08:06 +00001581int cpu_signal_handler(int host_signum, void *pinfo,
thsc4b89d12007-05-05 19:23:11 +00001582 void *puc)
1583{
ths9617efe2007-05-08 21:05:55 +00001584 siginfo_t *info = pinfo;
thsc4b89d12007-05-05 19:23:11 +00001585 struct ucontext *uc = puc;
1586 greg_t pc = uc->uc_mcontext.pc;
1587 int is_write;
ths3b46e622007-09-17 08:09:54 +00001588
thsc4b89d12007-05-05 19:23:11 +00001589 /* XXX: compute is_write */
1590 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001591 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
thsc4b89d12007-05-05 19:23:11 +00001592 is_write, &uc->uc_sigmask, puc);
bellard90cb9492005-07-24 15:11:38 +00001593}
1594
aurel32f54b3f92008-04-12 20:14:54 +00001595#elif defined(__hppa__)
1596
1597int cpu_signal_handler(int host_signum, void *pinfo,
1598 void *puc)
1599{
1600 struct siginfo *info = pinfo;
1601 struct ucontext *uc = puc;
1602 unsigned long pc;
1603 int is_write;
1604
1605 pc = uc->uc_mcontext.sc_iaoq[0];
1606 /* FIXME: compute is_write */
1607 is_write = 0;
1608 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1609 is_write,
1610 &uc->uc_sigmask, puc);
1611}
1612
bellard2b413142003-05-14 23:01:10 +00001613#else
1614
bellard3fb2ded2003-06-24 13:22:59 +00001615#error host CPU specific signal handler needed
bellard2b413142003-05-14 23:01:10 +00001616
1617#endif
bellard67b915a2004-03-31 23:37:16 +00001618
1619#endif /* !defined(CONFIG_SOFTMMU) */