blob: ae2fcd0827ad4f9d5375f139820c3762ed62fac2 [file] [log] [blame]
bellard7d132992003-03-06 23:23:54 +00001/*
2 * i386 emulator main execution loop
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard66321a12005-04-06 20:47:48 +00004 * Copyright (c) 2003-2005 Fabrice Bellard
bellard7d132992003-03-06 23:23:54 +00005 *
bellard3ef693a2003-03-23 20:17:16 +00006 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
bellard7d132992003-03-06 23:23:54 +000010 *
bellard3ef693a2003-03-23 20:17:16 +000011 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
bellard7d132992003-03-06 23:23:54 +000015 *
bellard3ef693a2003-03-23 20:17:16 +000016 * You should have received a copy of the GNU Lesser General Public
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
bellard7d132992003-03-06 23:23:54 +000018 */
bellarde4533c72003-06-15 19:51:39 +000019#include "config.h"
bellard93ac68b2003-09-30 20:57:29 +000020#include "exec.h"
bellard956034d2003-04-29 20:40:53 +000021#include "disas.h"
bellard7cb69ca2008-05-10 10:55:51 +000022#include "tcg.h"
aliguori7ba1e612008-11-05 16:04:33 +000023#include "kvm.h"
bellard7d132992003-03-06 23:23:54 +000024
bellardfbf9eeb2004-04-25 21:21:33 +000025#if !defined(CONFIG_SOFTMMU)
26#undef EAX
27#undef ECX
28#undef EDX
29#undef EBX
30#undef ESP
31#undef EBP
32#undef ESI
33#undef EDI
34#undef EIP
35#include <signal.h>
blueswir184778502008-10-26 20:33:16 +000036#ifdef __linux__
bellardfbf9eeb2004-04-25 21:21:33 +000037#include <sys/ucontext.h>
38#endif
blueswir184778502008-10-26 20:33:16 +000039#endif
bellardfbf9eeb2004-04-25 21:21:33 +000040
Juan Quinteladfe5fff2009-07-27 16:12:40 +020041#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
blueswir1572a9d42008-05-17 07:38:10 +000042// Work around ugly bugs in glibc that mangle global register contents
43#undef env
44#define env cpu_single_env
45#endif
46
bellard36bdbe52003-11-19 22:12:02 +000047int tb_invalidated_flag;
48
bellarddc990652003-03-19 00:00:28 +000049//#define DEBUG_EXEC
bellard9de5e442003-03-23 16:49:39 +000050//#define DEBUG_SIGNAL
bellard7d132992003-03-06 23:23:54 +000051
aliguori6a4955a2009-04-24 18:03:20 +000052int qemu_cpu_has_work(CPUState *env)
53{
54 return cpu_has_work(env);
55}
56
bellarde4533c72003-06-15 19:51:39 +000057void cpu_loop_exit(void)
58{
thsbfed01f2007-06-03 17:44:37 +000059 /* NOTE: the register at this point must be saved by hand because
60 longjmp restore them */
61 regs_to_env();
bellarde4533c72003-06-15 19:51:39 +000062 longjmp(env->jmp_env, 1);
63}
thsbfed01f2007-06-03 17:44:37 +000064
bellardfbf9eeb2004-04-25 21:21:33 +000065/* exit the current TB from a signal handler. The host registers are
66 restored in a state compatible with the CPU emulator
67 */
ths5fafdf22007-09-16 21:08:06 +000068void cpu_resume_from_signal(CPUState *env1, void *puc)
bellardfbf9eeb2004-04-25 21:21:33 +000069{
70#if !defined(CONFIG_SOFTMMU)
blueswir184778502008-10-26 20:33:16 +000071#ifdef __linux__
bellardfbf9eeb2004-04-25 21:21:33 +000072 struct ucontext *uc = puc;
blueswir184778502008-10-26 20:33:16 +000073#elif defined(__OpenBSD__)
74 struct sigcontext *uc = puc;
75#endif
bellardfbf9eeb2004-04-25 21:21:33 +000076#endif
77
78 env = env1;
79
80 /* XXX: restore cpu registers saved in host registers */
81
82#if !defined(CONFIG_SOFTMMU)
83 if (puc) {
84 /* XXX: use siglongjmp ? */
blueswir184778502008-10-26 20:33:16 +000085#ifdef __linux__
bellardfbf9eeb2004-04-25 21:21:33 +000086 sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
blueswir184778502008-10-26 20:33:16 +000087#elif defined(__OpenBSD__)
88 sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
89#endif
bellardfbf9eeb2004-04-25 21:21:33 +000090 }
91#endif
pbrook9a3ea652008-12-19 12:49:13 +000092 env->exception_index = -1;
bellardfbf9eeb2004-04-25 21:21:33 +000093 longjmp(env->jmp_env, 1);
94}
95
pbrook2e70f6e2008-06-29 01:03:05 +000096/* Execute the code without caching the generated code. An interpreter
97 could be used if available. */
98static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
99{
100 unsigned long next_tb;
101 TranslationBlock *tb;
102
103 /* Should never happen.
104 We only end up here when an existing TB is too long. */
105 if (max_cycles > CF_COUNT_MASK)
106 max_cycles = CF_COUNT_MASK;
107
108 tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
109 max_cycles);
110 env->current_tb = tb;
111 /* execute the generated code */
112 next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
113
114 if ((next_tb & 3) == 2) {
115 /* Restore PC. This may happen if async event occurs before
116 the TB starts executing. */
aliguori622ed362008-11-18 19:36:03 +0000117 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000118 }
119 tb_phys_invalidate(tb, -1);
120 tb_free(tb);
121}
122
bellard8a40a182005-11-20 10:35:40 +0000123static TranslationBlock *tb_find_slow(target_ulong pc,
124 target_ulong cs_base,
j_mayerc0686882007-09-20 22:47:42 +0000125 uint64_t flags)
bellard8a40a182005-11-20 10:35:40 +0000126{
127 TranslationBlock *tb, **ptb1;
bellard8a40a182005-11-20 10:35:40 +0000128 unsigned int h;
129 target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
ths3b46e622007-09-17 08:09:54 +0000130
bellard8a40a182005-11-20 10:35:40 +0000131 tb_invalidated_flag = 0;
ths3b46e622007-09-17 08:09:54 +0000132
bellard8a40a182005-11-20 10:35:40 +0000133 regs_to_env(); /* XXX: do it just before cpu_gen_code() */
ths3b46e622007-09-17 08:09:54 +0000134
bellard8a40a182005-11-20 10:35:40 +0000135 /* find translated block using physical mappings */
136 phys_pc = get_phys_addr_code(env, pc);
137 phys_page1 = phys_pc & TARGET_PAGE_MASK;
138 phys_page2 = -1;
139 h = tb_phys_hash_func(phys_pc);
140 ptb1 = &tb_phys_hash[h];
141 for(;;) {
142 tb = *ptb1;
143 if (!tb)
144 goto not_found;
ths5fafdf22007-09-16 21:08:06 +0000145 if (tb->pc == pc &&
bellard8a40a182005-11-20 10:35:40 +0000146 tb->page_addr[0] == phys_page1 &&
ths5fafdf22007-09-16 21:08:06 +0000147 tb->cs_base == cs_base &&
bellard8a40a182005-11-20 10:35:40 +0000148 tb->flags == flags) {
149 /* check next page if needed */
150 if (tb->page_addr[1] != -1) {
ths5fafdf22007-09-16 21:08:06 +0000151 virt_page2 = (pc & TARGET_PAGE_MASK) +
bellard8a40a182005-11-20 10:35:40 +0000152 TARGET_PAGE_SIZE;
153 phys_page2 = get_phys_addr_code(env, virt_page2);
154 if (tb->page_addr[1] == phys_page2)
155 goto found;
156 } else {
157 goto found;
158 }
159 }
160 ptb1 = &tb->phys_hash_next;
161 }
162 not_found:
pbrook2e70f6e2008-06-29 01:03:05 +0000163 /* if no translated code available, then translate it now */
164 tb = tb_gen_code(env, pc, cs_base, flags, 0);
ths3b46e622007-09-17 08:09:54 +0000165
bellard8a40a182005-11-20 10:35:40 +0000166 found:
bellard8a40a182005-11-20 10:35:40 +0000167 /* we add the TB in the virtual pc hash table */
168 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
bellard8a40a182005-11-20 10:35:40 +0000169 return tb;
170}
171
172static inline TranslationBlock *tb_find_fast(void)
173{
174 TranslationBlock *tb;
175 target_ulong cs_base, pc;
aliguori6b917542008-11-18 19:46:41 +0000176 int flags;
bellard8a40a182005-11-20 10:35:40 +0000177
178 /* we record a subset of the CPU state. It will
179 always be the same before a given translated block
180 is executed. */
aliguori6b917542008-11-18 19:46:41 +0000181 cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
bellardbce61842008-02-01 22:18:51 +0000182 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
ths551bd272008-07-03 17:57:36 +0000183 if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
184 tb->flags != flags)) {
bellard8a40a182005-11-20 10:35:40 +0000185 tb = tb_find_slow(pc, cs_base, flags);
186 }
187 return tb;
188}
189
aliguoridde23672008-11-18 20:50:36 +0000190static CPUDebugExcpHandler *debug_excp_handler;
191
192CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
193{
194 CPUDebugExcpHandler *old_handler = debug_excp_handler;
195
196 debug_excp_handler = handler;
197 return old_handler;
198}
199
aliguori6e140f22008-11-18 20:37:55 +0000200static void cpu_handle_debug_exception(CPUState *env)
201{
202 CPUWatchpoint *wp;
203
204 if (!env->watchpoint_hit)
aliguoric0ce9982008-11-25 22:13:57 +0000205 TAILQ_FOREACH(wp, &env->watchpoints, entry)
aliguori6e140f22008-11-18 20:37:55 +0000206 wp->flags &= ~BP_WATCHPOINT_HIT;
aliguoridde23672008-11-18 20:50:36 +0000207
208 if (debug_excp_handler)
209 debug_excp_handler(env);
aliguori6e140f22008-11-18 20:37:55 +0000210}
211
bellard7d132992003-03-06 23:23:54 +0000212/* main execution loop */
213
bellarde4533c72003-06-15 19:51:39 +0000214int cpu_exec(CPUState *env1)
bellard7d132992003-03-06 23:23:54 +0000215{
pbrook1057eaa2007-02-04 13:37:44 +0000216#define DECLARE_HOST_REGS 1
217#include "hostregs_helper.h"
bellard8a40a182005-11-20 10:35:40 +0000218 int ret, interrupt_request;
bellard8a40a182005-11-20 10:35:40 +0000219 TranslationBlock *tb;
bellardc27004e2005-01-03 23:35:10 +0000220 uint8_t *tc_ptr;
pbrookd5975362008-06-07 20:50:51 +0000221 unsigned long next_tb;
bellard8c6939c2003-06-09 15:28:00 +0000222
thsbfed01f2007-06-03 17:44:37 +0000223 if (cpu_halted(env1) == EXCP_HALTED)
224 return EXCP_HALTED;
bellard5a1e3cf2005-11-23 21:02:53 +0000225
ths5fafdf22007-09-16 21:08:06 +0000226 cpu_single_env = env1;
bellard6a00d602005-11-21 23:25:50 +0000227
bellard7d132992003-03-06 23:23:54 +0000228 /* first we save global registers */
pbrook1057eaa2007-02-04 13:37:44 +0000229#define SAVE_HOST_REGS 1
230#include "hostregs_helper.h"
bellardc27004e2005-01-03 23:35:10 +0000231 env = env1;
bellarde4533c72003-06-15 19:51:39 +0000232
bellard0d1a29f2004-10-12 22:01:28 +0000233 env_to_regs();
thsecb644f2007-06-03 18:45:53 +0000234#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000235 /* put eflags in CPU temporary format */
bellardfc2b4c42003-03-29 16:52:44 +0000236 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
237 DF = 1 - (2 * ((env->eflags >> 10) & 1));
bellard9de5e442003-03-23 16:49:39 +0000238 CC_OP = CC_OP_EFLAGS;
bellardfc2b4c42003-03-29 16:52:44 +0000239 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellard93ac68b2003-09-30 20:57:29 +0000240#elif defined(TARGET_SPARC)
pbrooke6e59062006-10-22 00:18:54 +0000241#elif defined(TARGET_M68K)
242 env->cc_op = CC_OP_FLAGS;
243 env->cc_dest = env->sr & 0xf;
244 env->cc_x = (env->sr >> 4) & 1;
thsecb644f2007-06-03 18:45:53 +0000245#elif defined(TARGET_ALPHA)
246#elif defined(TARGET_ARM)
247#elif defined(TARGET_PPC)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200248#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000249#elif defined(TARGET_MIPS)
bellardfdf9b3e2006-04-27 21:07:38 +0000250#elif defined(TARGET_SH4)
thsf1ccf902007-10-08 13:16:14 +0000251#elif defined(TARGET_CRIS)
bellardfdf9b3e2006-04-27 21:07:38 +0000252 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000253#else
254#error unsupported target CPU
255#endif
bellard3fb2ded2003-06-24 13:22:59 +0000256 env->exception_index = -1;
bellard9d27abd2003-05-10 13:13:54 +0000257
bellard7d132992003-03-06 23:23:54 +0000258 /* prepare setjmp context for exception handling */
bellard3fb2ded2003-06-24 13:22:59 +0000259 for(;;) {
260 if (setjmp(env->jmp_env) == 0) {
Juan Quinteladfe5fff2009-07-27 16:12:40 +0200261#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
blueswir19ddff3d2009-04-04 07:41:20 +0000262#undef env
263 env = cpu_single_env;
264#define env cpu_single_env
265#endif
bellardee8b7022004-02-03 23:35:10 +0000266 env->current_tb = NULL;
bellard3fb2ded2003-06-24 13:22:59 +0000267 /* if an exception is pending, we execute it here */
268 if (env->exception_index >= 0) {
269 if (env->exception_index >= EXCP_INTERRUPT) {
270 /* exit request from the cpu execution loop */
271 ret = env->exception_index;
aliguori6e140f22008-11-18 20:37:55 +0000272 if (ret == EXCP_DEBUG)
273 cpu_handle_debug_exception(env);
bellard3fb2ded2003-06-24 13:22:59 +0000274 break;
aurel3272d239e2009-01-14 19:40:27 +0000275 } else {
276#if defined(CONFIG_USER_ONLY)
bellard3fb2ded2003-06-24 13:22:59 +0000277 /* if user mode only, we simulate a fake exception
ths9f083492006-12-07 18:28:42 +0000278 which will be handled outside the cpu execution
bellard3fb2ded2003-06-24 13:22:59 +0000279 loop */
bellard83479e72003-06-25 16:12:37 +0000280#if defined(TARGET_I386)
ths5fafdf22007-09-16 21:08:06 +0000281 do_interrupt_user(env->exception_index,
282 env->exception_is_int,
283 env->error_code,
bellard3fb2ded2003-06-24 13:22:59 +0000284 env->exception_next_eip);
bellardeba01622008-05-12 12:04:40 +0000285 /* successfully delivered */
286 env->old_exception = -1;
bellard83479e72003-06-25 16:12:37 +0000287#endif
bellard3fb2ded2003-06-24 13:22:59 +0000288 ret = env->exception_index;
289 break;
aurel3272d239e2009-01-14 19:40:27 +0000290#else
bellard83479e72003-06-25 16:12:37 +0000291#if defined(TARGET_I386)
bellard3fb2ded2003-06-24 13:22:59 +0000292 /* simulate a real cpu exception. On i386, it can
293 trigger new exceptions, but we do not handle
294 double or triple faults yet. */
ths5fafdf22007-09-16 21:08:06 +0000295 do_interrupt(env->exception_index,
296 env->exception_is_int,
297 env->error_code,
bellardd05e66d2003-08-20 21:34:35 +0000298 env->exception_next_eip, 0);
ths678dde12007-03-31 20:28:52 +0000299 /* successfully delivered */
300 env->old_exception = -1;
bellardce097762004-01-04 23:53:18 +0000301#elif defined(TARGET_PPC)
302 do_interrupt(env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200303#elif defined(TARGET_MICROBLAZE)
304 do_interrupt(env);
bellard6af0bf92005-07-02 14:58:51 +0000305#elif defined(TARGET_MIPS)
306 do_interrupt(env);
bellarde95c8d52004-09-30 22:22:08 +0000307#elif defined(TARGET_SPARC)
blueswir1f2bc7e72008-05-27 17:35:30 +0000308 do_interrupt(env);
bellardb5ff1b32005-11-26 10:38:39 +0000309#elif defined(TARGET_ARM)
310 do_interrupt(env);
bellardfdf9b3e2006-04-27 21:07:38 +0000311#elif defined(TARGET_SH4)
312 do_interrupt(env);
j_mayereddf68a2007-04-05 07:22:49 +0000313#elif defined(TARGET_ALPHA)
314 do_interrupt(env);
thsf1ccf902007-10-08 13:16:14 +0000315#elif defined(TARGET_CRIS)
316 do_interrupt(env);
pbrook06338792007-05-23 19:58:11 +0000317#elif defined(TARGET_M68K)
318 do_interrupt(0);
bellard83479e72003-06-25 16:12:37 +0000319#endif
aurel3272d239e2009-01-14 19:40:27 +0000320#endif
bellard3fb2ded2003-06-24 13:22:59 +0000321 }
322 env->exception_index = -1;
ths5fafdf22007-09-16 21:08:06 +0000323 }
blueswir1640f42e2009-04-19 10:18:01 +0000324#ifdef CONFIG_KQEMU
aurel32be214e62009-03-06 21:48:00 +0000325 if (kqemu_is_ok(env) && env->interrupt_request == 0 && env->exit_request == 0) {
bellard9df217a2005-02-10 22:05:51 +0000326 int ret;
pbrooka7812ae2008-11-17 14:43:54 +0000327 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
bellard9df217a2005-02-10 22:05:51 +0000328 ret = kqemu_cpu_exec(env);
329 /* put eflags in CPU temporary format */
330 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
331 DF = 1 - (2 * ((env->eflags >> 10) & 1));
332 CC_OP = CC_OP_EFLAGS;
333 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
334 if (ret == 1) {
335 /* exception */
336 longjmp(env->jmp_env, 1);
337 } else if (ret == 2) {
338 /* softmmu execution needed */
339 } else {
aurel32be214e62009-03-06 21:48:00 +0000340 if (env->interrupt_request != 0 || env->exit_request != 0) {
bellard9df217a2005-02-10 22:05:51 +0000341 /* hardware interrupt will be executed just after */
342 } else {
343 /* otherwise, we restart */
344 longjmp(env->jmp_env, 1);
345 }
346 }
bellard9de5e442003-03-23 16:49:39 +0000347 }
bellard9df217a2005-02-10 22:05:51 +0000348#endif
349
aliguori7ba1e612008-11-05 16:04:33 +0000350 if (kvm_enabled()) {
aliguoribecfc392008-11-10 15:55:14 +0000351 kvm_cpu_exec(env);
352 longjmp(env->jmp_env, 1);
aliguori7ba1e612008-11-05 16:04:33 +0000353 }
354
blueswir1b5fc09a2008-05-04 06:38:18 +0000355 next_tb = 0; /* force lookup of first TB */
bellard3fb2ded2003-06-24 13:22:59 +0000356 for(;;) {
bellard68a79312003-06-30 13:12:32 +0000357 interrupt_request = env->interrupt_request;
malce1638bd2008-11-06 18:54:46 +0000358 if (unlikely(interrupt_request)) {
359 if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
360 /* Mask out external interrupts for this step. */
361 interrupt_request &= ~(CPU_INTERRUPT_HARD |
362 CPU_INTERRUPT_FIQ |
363 CPU_INTERRUPT_SMI |
364 CPU_INTERRUPT_NMI);
365 }
pbrook6658ffb2007-03-16 23:58:11 +0000366 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
367 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
368 env->exception_index = EXCP_DEBUG;
369 cpu_loop_exit();
370 }
balroga90b7312007-05-01 01:28:01 +0000371#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200372 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
373 defined(TARGET_MICROBLAZE)
balroga90b7312007-05-01 01:28:01 +0000374 if (interrupt_request & CPU_INTERRUPT_HALT) {
375 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
376 env->halted = 1;
377 env->exception_index = EXCP_HLT;
378 cpu_loop_exit();
379 }
380#endif
bellard68a79312003-06-30 13:12:32 +0000381#if defined(TARGET_I386)
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300382 if (interrupt_request & CPU_INTERRUPT_INIT) {
383 svm_check_intercept(SVM_EXIT_INIT);
384 do_cpu_init(env);
385 env->exception_index = EXCP_HALTED;
386 cpu_loop_exit();
387 } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
388 do_cpu_sipi(env);
389 } else if (env->hflags2 & HF2_GIF_MASK) {
bellarddb620f42008-06-04 17:02:19 +0000390 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
391 !(env->hflags & HF_SMM_MASK)) {
392 svm_check_intercept(SVM_EXIT_SMI);
393 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
394 do_smm_enter();
395 next_tb = 0;
396 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
397 !(env->hflags2 & HF2_NMI_MASK)) {
398 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
399 env->hflags2 |= HF2_NMI_MASK;
400 do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
401 next_tb = 0;
Huang Ying79c4f6b2009-06-23 10:05:14 +0800402 } else if (interrupt_request & CPU_INTERRUPT_MCE) {
403 env->interrupt_request &= ~CPU_INTERRUPT_MCE;
404 do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
405 next_tb = 0;
bellarddb620f42008-06-04 17:02:19 +0000406 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
407 (((env->hflags2 & HF2_VINTR_MASK) &&
408 (env->hflags2 & HF2_HIF_MASK)) ||
409 (!(env->hflags2 & HF2_VINTR_MASK) &&
410 (env->eflags & IF_MASK &&
411 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
412 int intno;
413 svm_check_intercept(SVM_EXIT_INTR);
414 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
415 intno = cpu_get_pic_interrupt(env);
aliguori93fcfe32009-01-15 22:34:14 +0000416 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
Juan Quinteladfe5fff2009-07-27 16:12:40 +0200417#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
blueswir19ddff3d2009-04-04 07:41:20 +0000418#undef env
419 env = cpu_single_env;
420#define env cpu_single_env
421#endif
bellarddb620f42008-06-04 17:02:19 +0000422 do_interrupt(intno, 0, 0, 0, 1);
423 /* ensure that no TB jump will be modified as
424 the program flow was changed */
425 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000426#if !defined(CONFIG_USER_ONLY)
bellarddb620f42008-06-04 17:02:19 +0000427 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
428 (env->eflags & IF_MASK) &&
429 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
430 int intno;
431 /* FIXME: this should respect TPR */
432 svm_check_intercept(SVM_EXIT_VINTR);
bellarddb620f42008-06-04 17:02:19 +0000433 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
aliguori93fcfe32009-01-15 22:34:14 +0000434 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
bellarddb620f42008-06-04 17:02:19 +0000435 do_interrupt(intno, 0, 0, 0, 1);
aurel32d40c54d2008-12-13 12:33:02 +0000436 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
bellarddb620f42008-06-04 17:02:19 +0000437 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000438#endif
bellarddb620f42008-06-04 17:02:19 +0000439 }
bellard68a79312003-06-30 13:12:32 +0000440 }
bellardce097762004-01-04 23:53:18 +0000441#elif defined(TARGET_PPC)
bellard9fddaa02004-05-21 12:59:32 +0000442#if 0
443 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
444 cpu_ppc_reset(env);
445 }
446#endif
j_mayer47103572007-03-30 09:38:04 +0000447 if (interrupt_request & CPU_INTERRUPT_HARD) {
j_mayere9df0142007-04-09 22:45:36 +0000448 ppc_hw_interrupt(env);
449 if (env->pending_interrupts == 0)
450 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
blueswir1b5fc09a2008-05-04 06:38:18 +0000451 next_tb = 0;
bellardce097762004-01-04 23:53:18 +0000452 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200453#elif defined(TARGET_MICROBLAZE)
454 if ((interrupt_request & CPU_INTERRUPT_HARD)
455 && (env->sregs[SR_MSR] & MSR_IE)
456 && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
457 && !(env->iflags & (D_FLAG | IMM_FLAG))) {
458 env->exception_index = EXCP_IRQ;
459 do_interrupt(env);
460 next_tb = 0;
461 }
bellard6af0bf92005-07-02 14:58:51 +0000462#elif defined(TARGET_MIPS)
463 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
ths24c7b0e2007-03-30 16:44:54 +0000464 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
bellard6af0bf92005-07-02 14:58:51 +0000465 (env->CP0_Status & (1 << CP0St_IE)) &&
ths24c7b0e2007-03-30 16:44:54 +0000466 !(env->CP0_Status & (1 << CP0St_EXL)) &&
467 !(env->CP0_Status & (1 << CP0St_ERL)) &&
bellard6af0bf92005-07-02 14:58:51 +0000468 !(env->hflags & MIPS_HFLAG_DM)) {
469 /* Raise it */
470 env->exception_index = EXCP_EXT_INTERRUPT;
471 env->error_code = 0;
472 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000473 next_tb = 0;
bellard6af0bf92005-07-02 14:58:51 +0000474 }
bellarde95c8d52004-09-30 22:22:08 +0000475#elif defined(TARGET_SPARC)
bellard66321a12005-04-06 20:47:48 +0000476 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
Igor Kovalenko52109772009-07-12 12:35:31 +0400477 cpu_interrupts_enabled(env)) {
bellard66321a12005-04-06 20:47:48 +0000478 int pil = env->interrupt_index & 15;
479 int type = env->interrupt_index & 0xf0;
480
481 if (((type == TT_EXTINT) &&
482 (pil == 15 || pil > env->psrpil)) ||
483 type != TT_EXTINT) {
484 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
blueswir1f2bc7e72008-05-27 17:35:30 +0000485 env->exception_index = env->interrupt_index;
486 do_interrupt(env);
bellard66321a12005-04-06 20:47:48 +0000487 env->interrupt_index = 0;
Igor Kovalenko52109772009-07-12 12:35:31 +0400488#if !defined(CONFIG_USER_ONLY)
blueswir1327ac2e2007-08-04 10:50:30 +0000489 cpu_check_irqs(env);
490#endif
blueswir1b5fc09a2008-05-04 06:38:18 +0000491 next_tb = 0;
bellard66321a12005-04-06 20:47:48 +0000492 }
bellarde95c8d52004-09-30 22:22:08 +0000493 } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
494 //do_interrupt(0, 0, 0, 0, 0);
495 env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
balroga90b7312007-05-01 01:28:01 +0000496 }
bellardb5ff1b32005-11-26 10:38:39 +0000497#elif defined(TARGET_ARM)
498 if (interrupt_request & CPU_INTERRUPT_FIQ
499 && !(env->uncached_cpsr & CPSR_F)) {
500 env->exception_index = EXCP_FIQ;
501 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000502 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000503 }
pbrook9ee6e8b2007-11-11 00:04:49 +0000504 /* ARMv7-M interrupt return works by loading a magic value
505 into the PC. On real hardware the load causes the
506 return to occur. The qemu implementation performs the
507 jump normally, then does the exception return when the
508 CPU tries to execute code at the magic address.
509 This will cause the magic PC value to be pushed to
510 the stack if an interrupt occured at the wrong time.
511 We avoid this by disabling interrupts when
512 pc contains a magic address. */
bellardb5ff1b32005-11-26 10:38:39 +0000513 if (interrupt_request & CPU_INTERRUPT_HARD
pbrook9ee6e8b2007-11-11 00:04:49 +0000514 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
515 || !(env->uncached_cpsr & CPSR_I))) {
bellardb5ff1b32005-11-26 10:38:39 +0000516 env->exception_index = EXCP_IRQ;
517 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000518 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000519 }
bellardfdf9b3e2006-04-27 21:07:38 +0000520#elif defined(TARGET_SH4)
thse96e2042007-12-02 06:18:24 +0000521 if (interrupt_request & CPU_INTERRUPT_HARD) {
522 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000523 next_tb = 0;
thse96e2042007-12-02 06:18:24 +0000524 }
j_mayereddf68a2007-04-05 07:22:49 +0000525#elif defined(TARGET_ALPHA)
526 if (interrupt_request & CPU_INTERRUPT_HARD) {
527 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000528 next_tb = 0;
j_mayereddf68a2007-04-05 07:22:49 +0000529 }
thsf1ccf902007-10-08 13:16:14 +0000530#elif defined(TARGET_CRIS)
edgar_igl1b1a38b2008-06-09 23:18:06 +0000531 if (interrupt_request & CPU_INTERRUPT_HARD
532 && (env->pregs[PR_CCS] & I_FLAG)) {
533 env->exception_index = EXCP_IRQ;
534 do_interrupt(env);
535 next_tb = 0;
536 }
537 if (interrupt_request & CPU_INTERRUPT_NMI
538 && (env->pregs[PR_CCS] & M_FLAG)) {
539 env->exception_index = EXCP_NMI;
thsf1ccf902007-10-08 13:16:14 +0000540 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000541 next_tb = 0;
thsf1ccf902007-10-08 13:16:14 +0000542 }
pbrook06338792007-05-23 19:58:11 +0000543#elif defined(TARGET_M68K)
544 if (interrupt_request & CPU_INTERRUPT_HARD
545 && ((env->sr & SR_I) >> SR_I_SHIFT)
546 < env->pending_level) {
547 /* Real hardware gets the interrupt vector via an
548 IACK cycle at this point. Current emulated
549 hardware doesn't rely on this, so we
550 provide/save the vector when the interrupt is
551 first signalled. */
552 env->exception_index = env->pending_vector;
553 do_interrupt(1);
blueswir1b5fc09a2008-05-04 06:38:18 +0000554 next_tb = 0;
pbrook06338792007-05-23 19:58:11 +0000555 }
bellard68a79312003-06-30 13:12:32 +0000556#endif
bellard9d050952006-05-22 22:03:52 +0000557 /* Don't use the cached interupt_request value,
558 do_interrupt may have updated the EXITTB flag. */
bellardb5ff1b32005-11-26 10:38:39 +0000559 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
bellardbf3e8bf2004-02-16 21:58:54 +0000560 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
561 /* ensure that no TB jump will be modified as
562 the program flow was changed */
blueswir1b5fc09a2008-05-04 06:38:18 +0000563 next_tb = 0;
bellardbf3e8bf2004-02-16 21:58:54 +0000564 }
aurel32be214e62009-03-06 21:48:00 +0000565 }
566 if (unlikely(env->exit_request)) {
567 env->exit_request = 0;
568 env->exception_index = EXCP_INTERRUPT;
569 cpu_loop_exit();
bellard3fb2ded2003-06-24 13:22:59 +0000570 }
571#ifdef DEBUG_EXEC
aliguori8fec2b82009-01-15 22:36:53 +0000572 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
bellard3fb2ded2003-06-24 13:22:59 +0000573 /* restore flags in standard format */
thsecb644f2007-06-03 18:45:53 +0000574 regs_to_env();
575#if defined(TARGET_I386)
pbrooka7812ae2008-11-17 14:43:54 +0000576 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
aliguori93fcfe32009-01-15 22:34:14 +0000577 log_cpu_state(env, X86_DUMP_CCOP);
bellard3fb2ded2003-06-24 13:22:59 +0000578 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellarde4533c72003-06-15 19:51:39 +0000579#elif defined(TARGET_ARM)
aliguori93fcfe32009-01-15 22:34:14 +0000580 log_cpu_state(env, 0);
bellard93ac68b2003-09-30 20:57:29 +0000581#elif defined(TARGET_SPARC)
aliguori93fcfe32009-01-15 22:34:14 +0000582 log_cpu_state(env, 0);
bellard67867302003-11-23 17:05:30 +0000583#elif defined(TARGET_PPC)
aliguori93fcfe32009-01-15 22:34:14 +0000584 log_cpu_state(env, 0);
pbrooke6e59062006-10-22 00:18:54 +0000585#elif defined(TARGET_M68K)
586 cpu_m68k_flush_flags(env, env->cc_op);
587 env->cc_op = CC_OP_FLAGS;
588 env->sr = (env->sr & 0xffe0)
589 | env->cc_dest | (env->cc_x << 4);
aliguori93fcfe32009-01-15 22:34:14 +0000590 log_cpu_state(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200591#elif defined(TARGET_MICROBLAZE)
592 log_cpu_state(env, 0);
bellard6af0bf92005-07-02 14:58:51 +0000593#elif defined(TARGET_MIPS)
aliguori93fcfe32009-01-15 22:34:14 +0000594 log_cpu_state(env, 0);
bellardfdf9b3e2006-04-27 21:07:38 +0000595#elif defined(TARGET_SH4)
aliguori93fcfe32009-01-15 22:34:14 +0000596 log_cpu_state(env, 0);
j_mayereddf68a2007-04-05 07:22:49 +0000597#elif defined(TARGET_ALPHA)
aliguori93fcfe32009-01-15 22:34:14 +0000598 log_cpu_state(env, 0);
thsf1ccf902007-10-08 13:16:14 +0000599#elif defined(TARGET_CRIS)
aliguori93fcfe32009-01-15 22:34:14 +0000600 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000601#else
ths5fafdf22007-09-16 21:08:06 +0000602#error unsupported target CPU
bellarde4533c72003-06-15 19:51:39 +0000603#endif
bellard3fb2ded2003-06-24 13:22:59 +0000604 }
bellard7d132992003-03-06 23:23:54 +0000605#endif
pbrookd5975362008-06-07 20:50:51 +0000606 spin_lock(&tb_lock);
bellard8a40a182005-11-20 10:35:40 +0000607 tb = tb_find_fast();
pbrookd5975362008-06-07 20:50:51 +0000608 /* Note: we do it here to avoid a gcc bug on Mac OS X when
609 doing it in tb_find_slow */
610 if (tb_invalidated_flag) {
611 /* as some TB could have been invalidated because
612 of memory exceptions while generating the code, we
613 must recompute the hash index here */
614 next_tb = 0;
pbrook2e70f6e2008-06-29 01:03:05 +0000615 tb_invalidated_flag = 0;
pbrookd5975362008-06-07 20:50:51 +0000616 }
bellard9d27abd2003-05-10 13:13:54 +0000617#ifdef DEBUG_EXEC
aliguori93fcfe32009-01-15 22:34:14 +0000618 qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
619 (long)tb->tc_ptr, tb->pc,
620 lookup_symbol(tb->pc));
bellard9d27abd2003-05-10 13:13:54 +0000621#endif
bellard8a40a182005-11-20 10:35:40 +0000622 /* see if we can patch the calling TB. When the TB
623 spans two pages, we cannot safely do a direct
624 jump. */
bellardc27004e2005-01-03 23:35:10 +0000625 {
blueswir1b5fc09a2008-05-04 06:38:18 +0000626 if (next_tb != 0 &&
blueswir1640f42e2009-04-19 10:18:01 +0000627#ifdef CONFIG_KQEMU
bellardf32fc642006-02-08 22:43:39 +0000628 (env->kqemu_enabled != 2) &&
629#endif
bellardec6338b2007-11-08 14:25:03 +0000630 tb->page_addr[1] == -1) {
blueswir1b5fc09a2008-05-04 06:38:18 +0000631 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
bellard3fb2ded2003-06-24 13:22:59 +0000632 }
bellardc27004e2005-01-03 23:35:10 +0000633 }
pbrookd5975362008-06-07 20:50:51 +0000634 spin_unlock(&tb_lock);
bellard83479e72003-06-25 16:12:37 +0000635 env->current_tb = tb;
malc55e8b852008-11-04 14:18:13 +0000636
637 /* cpu_interrupt might be called while translating the
638 TB, but before it is linked into a potentially
639 infinite loop and becomes env->current_tb. Avoid
640 starting execution if there is a pending interrupt. */
aurel32be214e62009-03-06 21:48:00 +0000641 if (unlikely (env->exit_request))
malc55e8b852008-11-04 14:18:13 +0000642 env->current_tb = NULL;
643
pbrook2e70f6e2008-06-29 01:03:05 +0000644 while (env->current_tb) {
645 tc_ptr = tb->tc_ptr;
bellard3fb2ded2003-06-24 13:22:59 +0000646 /* execute the generated code */
Juan Quinteladfe5fff2009-07-27 16:12:40 +0200647#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
blueswir1572a9d42008-05-17 07:38:10 +0000648#undef env
pbrook2e70f6e2008-06-29 01:03:05 +0000649 env = cpu_single_env;
blueswir1572a9d42008-05-17 07:38:10 +0000650#define env cpu_single_env
651#endif
pbrook2e70f6e2008-06-29 01:03:05 +0000652 next_tb = tcg_qemu_tb_exec(tc_ptr);
653 env->current_tb = NULL;
654 if ((next_tb & 3) == 2) {
thsbf20dc02008-06-30 17:22:19 +0000655 /* Instruction counter expired. */
pbrook2e70f6e2008-06-29 01:03:05 +0000656 int insns_left;
657 tb = (TranslationBlock *)(long)(next_tb & ~3);
658 /* Restore PC. */
aliguori622ed362008-11-18 19:36:03 +0000659 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000660 insns_left = env->icount_decr.u32;
661 if (env->icount_extra && insns_left >= 0) {
662 /* Refill decrementer and continue execution. */
663 env->icount_extra += insns_left;
664 if (env->icount_extra > 0xffff) {
665 insns_left = 0xffff;
666 } else {
667 insns_left = env->icount_extra;
668 }
669 env->icount_extra -= insns_left;
670 env->icount_decr.u16.low = insns_left;
671 } else {
672 if (insns_left > 0) {
673 /* Execute remaining instructions. */
674 cpu_exec_nocache(insns_left, tb);
675 }
676 env->exception_index = EXCP_INTERRUPT;
677 next_tb = 0;
678 cpu_loop_exit();
679 }
680 }
681 }
bellard4cbf74b2003-08-10 21:48:43 +0000682 /* reset soft MMU for next block (it can currently
683 only be set by a memory fault) */
blueswir1640f42e2009-04-19 10:18:01 +0000684#if defined(CONFIG_KQEMU)
bellardf32fc642006-02-08 22:43:39 +0000685#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
686 if (kqemu_is_ok(env) &&
687 (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
688 cpu_loop_exit();
689 }
690#endif
ths50a518e2007-06-03 18:52:15 +0000691 } /* for(;;) */
bellard3fb2ded2003-06-24 13:22:59 +0000692 } else {
bellard0d1a29f2004-10-12 22:01:28 +0000693 env_to_regs();
bellard7d132992003-03-06 23:23:54 +0000694 }
bellard3fb2ded2003-06-24 13:22:59 +0000695 } /* for(;;) */
696
bellard7d132992003-03-06 23:23:54 +0000697
bellarde4533c72003-06-15 19:51:39 +0000698#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000699 /* restore flags in standard format */
pbrooka7812ae2008-11-17 14:43:54 +0000700 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
bellarde4533c72003-06-15 19:51:39 +0000701#elif defined(TARGET_ARM)
bellardb7bcbe92005-02-22 19:27:29 +0000702 /* XXX: Save/restore host fpu exception state?. */
bellard93ac68b2003-09-30 20:57:29 +0000703#elif defined(TARGET_SPARC)
bellard67867302003-11-23 17:05:30 +0000704#elif defined(TARGET_PPC)
pbrooke6e59062006-10-22 00:18:54 +0000705#elif defined(TARGET_M68K)
706 cpu_m68k_flush_flags(env, env->cc_op);
707 env->cc_op = CC_OP_FLAGS;
708 env->sr = (env->sr & 0xffe0)
709 | env->cc_dest | (env->cc_x << 4);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200710#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000711#elif defined(TARGET_MIPS)
bellardfdf9b3e2006-04-27 21:07:38 +0000712#elif defined(TARGET_SH4)
j_mayereddf68a2007-04-05 07:22:49 +0000713#elif defined(TARGET_ALPHA)
thsf1ccf902007-10-08 13:16:14 +0000714#elif defined(TARGET_CRIS)
bellardfdf9b3e2006-04-27 21:07:38 +0000715 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000716#else
717#error unsupported target CPU
718#endif
pbrook1057eaa2007-02-04 13:37:44 +0000719
720 /* restore global registers */
pbrook1057eaa2007-02-04 13:37:44 +0000721#include "hostregs_helper.h"
722
bellard6a00d602005-11-21 23:25:50 +0000723 /* fail safe : never use cpu_single_env outside cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000724 cpu_single_env = NULL;
bellard7d132992003-03-06 23:23:54 +0000725 return ret;
726}
bellard6dbad632003-03-16 18:05:05 +0000727
bellardfbf9eeb2004-04-25 21:21:33 +0000728/* must only be called from the generated code as an exception can be
729 generated */
730void tb_invalidate_page_range(target_ulong start, target_ulong end)
731{
bellarddc5d0b32004-06-22 18:43:30 +0000732 /* XXX: cannot enable it yet because it yields to MMU exception
733 where NIP != read address on PowerPC */
734#if 0
bellardfbf9eeb2004-04-25 21:21:33 +0000735 target_ulong phys_addr;
736 phys_addr = get_phys_addr_code(env, start);
737 tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
bellarddc5d0b32004-06-22 18:43:30 +0000738#endif
bellardfbf9eeb2004-04-25 21:21:33 +0000739}
740
bellard1a18c712003-10-30 01:07:51 +0000741#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
bellarde4533c72003-06-15 19:51:39 +0000742
bellard6dbad632003-03-16 18:05:05 +0000743void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
744{
745 CPUX86State *saved_env;
746
747 saved_env = env;
748 env = s;
bellarda412ac52003-07-26 18:01:40 +0000749 if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
bellarda513fe12003-05-27 23:29:48 +0000750 selector &= 0xffff;
ths5fafdf22007-09-16 21:08:06 +0000751 cpu_x86_load_seg_cache(env, seg_reg, selector,
bellardc27004e2005-01-03 23:35:10 +0000752 (selector << 4), 0xffff, 0);
bellarda513fe12003-05-27 23:29:48 +0000753 } else {
bellard5d975592008-05-12 22:05:33 +0000754 helper_load_seg(seg_reg, selector);
bellarda513fe12003-05-27 23:29:48 +0000755 }
bellard6dbad632003-03-16 18:05:05 +0000756 env = saved_env;
757}
bellard9de5e442003-03-23 16:49:39 +0000758
bellard6f12a2a2007-11-11 22:16:56 +0000759void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
bellardd0a1ffc2003-05-29 20:04:28 +0000760{
761 CPUX86State *saved_env;
762
763 saved_env = env;
764 env = s;
ths3b46e622007-09-17 08:09:54 +0000765
bellard6f12a2a2007-11-11 22:16:56 +0000766 helper_fsave(ptr, data32);
bellardd0a1ffc2003-05-29 20:04:28 +0000767
768 env = saved_env;
769}
770
bellard6f12a2a2007-11-11 22:16:56 +0000771void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
bellardd0a1ffc2003-05-29 20:04:28 +0000772{
773 CPUX86State *saved_env;
774
775 saved_env = env;
776 env = s;
ths3b46e622007-09-17 08:09:54 +0000777
bellard6f12a2a2007-11-11 22:16:56 +0000778 helper_frstor(ptr, data32);
bellardd0a1ffc2003-05-29 20:04:28 +0000779
780 env = saved_env;
781}
782
bellarde4533c72003-06-15 19:51:39 +0000783#endif /* TARGET_I386 */
784
bellard67b915a2004-03-31 23:37:16 +0000785#if !defined(CONFIG_SOFTMMU)
786
bellard3fb2ded2003-06-24 13:22:59 +0000787#if defined(TARGET_I386)
788
bellardb56dad12003-05-08 15:38:04 +0000789/* 'pc' is the host PC at which the exception was raised. 'address' is
bellardfd6ce8f2003-05-14 19:00:11 +0000790 the effective address of the memory exception. 'is_write' is 1 if a
791 write caused the exception and otherwise 0'. 'old_set' is the
792 signal set which should be restored */
bellard2b413142003-05-14 23:01:10 +0000793static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
ths5fafdf22007-09-16 21:08:06 +0000794 int is_write, sigset_t *old_set,
bellardbf3e8bf2004-02-16 21:58:54 +0000795 void *puc)
bellard9de5e442003-03-23 16:49:39 +0000796{
bellarda513fe12003-05-27 23:29:48 +0000797 TranslationBlock *tb;
798 int ret;
bellard68a79312003-06-30 13:12:32 +0000799
bellard83479e72003-06-25 16:12:37 +0000800 if (cpu_single_env)
801 env = cpu_single_env; /* XXX: find a correct solution for multithread */
bellardfd6ce8f2003-05-14 19:00:11 +0000802#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000803 qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellardbf3e8bf2004-02-16 21:58:54 +0000804 pc, address, is_write, *(unsigned long *)old_set);
bellard9de5e442003-03-23 16:49:39 +0000805#endif
bellard25eb4482003-05-14 21:50:54 +0000806 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000807 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellardfd6ce8f2003-05-14 19:00:11 +0000808 return 1;
809 }
bellardfbf9eeb2004-04-25 21:21:33 +0000810
bellard3fb2ded2003-06-24 13:22:59 +0000811 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000812 ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard3fb2ded2003-06-24 13:22:59 +0000813 if (ret < 0)
814 return 0; /* not an MMU fault */
815 if (ret == 0)
816 return 1; /* the MMU fault was handled without causing real CPU fault */
817 /* now we have a real cpu fault */
bellarda513fe12003-05-27 23:29:48 +0000818 tb = tb_find_pc(pc);
819 if (tb) {
bellard9de5e442003-03-23 16:49:39 +0000820 /* the PC is inside the translated code. It means that we have
821 a virtual CPU fault */
bellardbf3e8bf2004-02-16 21:58:54 +0000822 cpu_restore_state(tb, env, pc, puc);
bellard3fb2ded2003-06-24 13:22:59 +0000823 }
bellard4cbf74b2003-08-10 21:48:43 +0000824 if (ret == 1) {
bellard3fb2ded2003-06-24 13:22:59 +0000825#if 0
ths5fafdf22007-09-16 21:08:06 +0000826 printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
bellard4cbf74b2003-08-10 21:48:43 +0000827 env->eip, env->cr[2], env->error_code);
bellard3fb2ded2003-06-24 13:22:59 +0000828#endif
bellard4cbf74b2003-08-10 21:48:43 +0000829 /* we restore the process signal mask as the sigreturn should
830 do it (XXX: use sigsetjmp) */
831 sigprocmask(SIG_SETMASK, old_set, NULL);
bellard54ca9092005-12-04 18:46:06 +0000832 raise_exception_err(env->exception_index, env->error_code);
bellard4cbf74b2003-08-10 21:48:43 +0000833 } else {
834 /* activate soft MMU for this block */
bellard3f337312003-08-20 23:02:09 +0000835 env->hflags |= HF_SOFTMMU_MASK;
bellardfbf9eeb2004-04-25 21:21:33 +0000836 cpu_resume_from_signal(env, puc);
bellard4cbf74b2003-08-10 21:48:43 +0000837 }
bellard3fb2ded2003-06-24 13:22:59 +0000838 /* never comes here */
839 return 1;
840}
841
bellarde4533c72003-06-15 19:51:39 +0000842#elif defined(TARGET_ARM)
bellard3fb2ded2003-06-24 13:22:59 +0000843static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bellardbf3e8bf2004-02-16 21:58:54 +0000844 int is_write, sigset_t *old_set,
845 void *puc)
bellard3fb2ded2003-06-24 13:22:59 +0000846{
bellard68016c62005-02-07 23:12:27 +0000847 TranslationBlock *tb;
848 int ret;
849
850 if (cpu_single_env)
851 env = cpu_single_env; /* XXX: find a correct solution for multithread */
852#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000853 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard68016c62005-02-07 23:12:27 +0000854 pc, address, is_write, *(unsigned long *)old_set);
855#endif
bellard9f0777e2005-02-02 20:42:01 +0000856 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000857 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellard9f0777e2005-02-02 20:42:01 +0000858 return 1;
859 }
bellard68016c62005-02-07 23:12:27 +0000860 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000861 ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard68016c62005-02-07 23:12:27 +0000862 if (ret < 0)
863 return 0; /* not an MMU fault */
864 if (ret == 0)
865 return 1; /* the MMU fault was handled without causing real CPU fault */
866 /* now we have a real cpu fault */
867 tb = tb_find_pc(pc);
868 if (tb) {
869 /* the PC is inside the translated code. It means that we have
870 a virtual CPU fault */
871 cpu_restore_state(tb, env, pc, puc);
872 }
873 /* we restore the process signal mask as the sigreturn should
874 do it (XXX: use sigsetjmp) */
875 sigprocmask(SIG_SETMASK, old_set, NULL);
876 cpu_loop_exit();
aurel32968c74d2008-04-11 04:55:17 +0000877 /* never comes here */
878 return 1;
bellard3fb2ded2003-06-24 13:22:59 +0000879}
bellard93ac68b2003-09-30 20:57:29 +0000880#elif defined(TARGET_SPARC)
881static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bellardbf3e8bf2004-02-16 21:58:54 +0000882 int is_write, sigset_t *old_set,
883 void *puc)
bellard93ac68b2003-09-30 20:57:29 +0000884{
bellard68016c62005-02-07 23:12:27 +0000885 TranslationBlock *tb;
886 int ret;
887
888 if (cpu_single_env)
889 env = cpu_single_env; /* XXX: find a correct solution for multithread */
890#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000891 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard68016c62005-02-07 23:12:27 +0000892 pc, address, is_write, *(unsigned long *)old_set);
893#endif
bellardb453b702004-01-04 15:45:21 +0000894 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000895 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellardb453b702004-01-04 15:45:21 +0000896 return 1;
897 }
bellard68016c62005-02-07 23:12:27 +0000898 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000899 ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard68016c62005-02-07 23:12:27 +0000900 if (ret < 0)
901 return 0; /* not an MMU fault */
902 if (ret == 0)
903 return 1; /* the MMU fault was handled without causing real CPU fault */
904 /* now we have a real cpu fault */
905 tb = tb_find_pc(pc);
906 if (tb) {
907 /* the PC is inside the translated code. It means that we have
908 a virtual CPU fault */
909 cpu_restore_state(tb, env, pc, puc);
910 }
911 /* we restore the process signal mask as the sigreturn should
912 do it (XXX: use sigsetjmp) */
913 sigprocmask(SIG_SETMASK, old_set, NULL);
914 cpu_loop_exit();
aurel32968c74d2008-04-11 04:55:17 +0000915 /* never comes here */
916 return 1;
bellard93ac68b2003-09-30 20:57:29 +0000917}
bellard67867302003-11-23 17:05:30 +0000918#elif defined (TARGET_PPC)
919static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bellardbf3e8bf2004-02-16 21:58:54 +0000920 int is_write, sigset_t *old_set,
921 void *puc)
bellard67867302003-11-23 17:05:30 +0000922{
923 TranslationBlock *tb;
bellardce097762004-01-04 23:53:18 +0000924 int ret;
ths3b46e622007-09-17 08:09:54 +0000925
bellard67867302003-11-23 17:05:30 +0000926 if (cpu_single_env)
927 env = cpu_single_env; /* XXX: find a correct solution for multithread */
bellard67867302003-11-23 17:05:30 +0000928#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000929 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard67867302003-11-23 17:05:30 +0000930 pc, address, is_write, *(unsigned long *)old_set);
931#endif
932 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000933 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellard67867302003-11-23 17:05:30 +0000934 return 1;
935 }
936
bellardce097762004-01-04 23:53:18 +0000937 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000938 ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellardce097762004-01-04 23:53:18 +0000939 if (ret < 0)
940 return 0; /* not an MMU fault */
941 if (ret == 0)
942 return 1; /* the MMU fault was handled without causing real CPU fault */
943
bellard67867302003-11-23 17:05:30 +0000944 /* now we have a real cpu fault */
945 tb = tb_find_pc(pc);
946 if (tb) {
947 /* the PC is inside the translated code. It means that we have
948 a virtual CPU fault */
bellardbf3e8bf2004-02-16 21:58:54 +0000949 cpu_restore_state(tb, env, pc, puc);
bellard67867302003-11-23 17:05:30 +0000950 }
bellardce097762004-01-04 23:53:18 +0000951 if (ret == 1) {
bellard67867302003-11-23 17:05:30 +0000952#if 0
ths5fafdf22007-09-16 21:08:06 +0000953 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
bellardce097762004-01-04 23:53:18 +0000954 env->nip, env->error_code, tb);
bellard67867302003-11-23 17:05:30 +0000955#endif
956 /* we restore the process signal mask as the sigreturn should
957 do it (XXX: use sigsetjmp) */
bellardbf3e8bf2004-02-16 21:58:54 +0000958 sigprocmask(SIG_SETMASK, old_set, NULL);
aurel32e06fcd72008-12-11 22:42:14 +0000959 cpu_loop_exit();
bellardce097762004-01-04 23:53:18 +0000960 } else {
961 /* activate soft MMU for this block */
bellardfbf9eeb2004-04-25 21:21:33 +0000962 cpu_resume_from_signal(env, puc);
bellardce097762004-01-04 23:53:18 +0000963 }
bellard67867302003-11-23 17:05:30 +0000964 /* never comes here */
965 return 1;
966}
bellard6af0bf92005-07-02 14:58:51 +0000967
pbrooke6e59062006-10-22 00:18:54 +0000968#elif defined(TARGET_M68K)
969static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
970 int is_write, sigset_t *old_set,
971 void *puc)
972{
973 TranslationBlock *tb;
974 int ret;
975
976 if (cpu_single_env)
977 env = cpu_single_env; /* XXX: find a correct solution for multithread */
978#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000979 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
pbrooke6e59062006-10-22 00:18:54 +0000980 pc, address, is_write, *(unsigned long *)old_set);
981#endif
982 /* XXX: locking issue */
983 if (is_write && page_unprotect(address, pc, puc)) {
984 return 1;
985 }
986 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000987 ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
pbrooke6e59062006-10-22 00:18:54 +0000988 if (ret < 0)
989 return 0; /* not an MMU fault */
990 if (ret == 0)
991 return 1; /* the MMU fault was handled without causing real CPU fault */
992 /* now we have a real cpu fault */
993 tb = tb_find_pc(pc);
994 if (tb) {
995 /* the PC is inside the translated code. It means that we have
996 a virtual CPU fault */
997 cpu_restore_state(tb, env, pc, puc);
998 }
999 /* we restore the process signal mask as the sigreturn should
1000 do it (XXX: use sigsetjmp) */
1001 sigprocmask(SIG_SETMASK, old_set, NULL);
1002 cpu_loop_exit();
1003 /* never comes here */
1004 return 1;
1005}
1006
bellard6af0bf92005-07-02 14:58:51 +00001007#elif defined (TARGET_MIPS)
1008static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1009 int is_write, sigset_t *old_set,
1010 void *puc)
1011{
1012 TranslationBlock *tb;
1013 int ret;
ths3b46e622007-09-17 08:09:54 +00001014
bellard6af0bf92005-07-02 14:58:51 +00001015 if (cpu_single_env)
1016 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1017#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001018 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard6af0bf92005-07-02 14:58:51 +00001019 pc, address, is_write, *(unsigned long *)old_set);
1020#endif
1021 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +00001022 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellard6af0bf92005-07-02 14:58:51 +00001023 return 1;
1024 }
1025
1026 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001027 ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard6af0bf92005-07-02 14:58:51 +00001028 if (ret < 0)
1029 return 0; /* not an MMU fault */
1030 if (ret == 0)
1031 return 1; /* the MMU fault was handled without causing real CPU fault */
1032
1033 /* now we have a real cpu fault */
1034 tb = tb_find_pc(pc);
1035 if (tb) {
1036 /* the PC is inside the translated code. It means that we have
1037 a virtual CPU fault */
1038 cpu_restore_state(tb, env, pc, puc);
1039 }
1040 if (ret == 1) {
1041#if 0
ths5fafdf22007-09-16 21:08:06 +00001042 printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
ths1eb52072007-05-12 16:57:42 +00001043 env->PC, env->error_code, tb);
bellard6af0bf92005-07-02 14:58:51 +00001044#endif
1045 /* we restore the process signal mask as the sigreturn should
1046 do it (XXX: use sigsetjmp) */
1047 sigprocmask(SIG_SETMASK, old_set, NULL);
thsf9480ff2008-12-20 19:42:14 +00001048 cpu_loop_exit();
bellard6af0bf92005-07-02 14:58:51 +00001049 } else {
1050 /* activate soft MMU for this block */
1051 cpu_resume_from_signal(env, puc);
1052 }
1053 /* never comes here */
1054 return 1;
1055}
1056
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02001057#elif defined (TARGET_MICROBLAZE)
1058static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1059 int is_write, sigset_t *old_set,
1060 void *puc)
1061{
1062 TranslationBlock *tb;
1063 int ret;
1064
1065 if (cpu_single_env)
1066 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1067#if defined(DEBUG_SIGNAL)
1068 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1069 pc, address, is_write, *(unsigned long *)old_set);
1070#endif
1071 /* XXX: locking issue */
1072 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1073 return 1;
1074 }
1075
1076 /* see if it is an MMU fault */
1077 ret = cpu_mb_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1078 if (ret < 0)
1079 return 0; /* not an MMU fault */
1080 if (ret == 0)
1081 return 1; /* the MMU fault was handled without causing real CPU fault */
1082
1083 /* now we have a real cpu fault */
1084 tb = tb_find_pc(pc);
1085 if (tb) {
1086 /* the PC is inside the translated code. It means that we have
1087 a virtual CPU fault */
1088 cpu_restore_state(tb, env, pc, puc);
1089 }
1090 if (ret == 1) {
1091#if 0
1092 printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1093 env->PC, env->error_code, tb);
1094#endif
1095 /* we restore the process signal mask as the sigreturn should
1096 do it (XXX: use sigsetjmp) */
1097 sigprocmask(SIG_SETMASK, old_set, NULL);
1098 cpu_loop_exit();
1099 } else {
1100 /* activate soft MMU for this block */
1101 cpu_resume_from_signal(env, puc);
1102 }
1103 /* never comes here */
1104 return 1;
1105}
1106
bellardfdf9b3e2006-04-27 21:07:38 +00001107#elif defined (TARGET_SH4)
1108static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1109 int is_write, sigset_t *old_set,
1110 void *puc)
1111{
1112 TranslationBlock *tb;
1113 int ret;
ths3b46e622007-09-17 08:09:54 +00001114
bellardfdf9b3e2006-04-27 21:07:38 +00001115 if (cpu_single_env)
1116 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1117#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001118 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellardfdf9b3e2006-04-27 21:07:38 +00001119 pc, address, is_write, *(unsigned long *)old_set);
1120#endif
1121 /* XXX: locking issue */
1122 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1123 return 1;
1124 }
1125
1126 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001127 ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellardfdf9b3e2006-04-27 21:07:38 +00001128 if (ret < 0)
1129 return 0; /* not an MMU fault */
1130 if (ret == 0)
1131 return 1; /* the MMU fault was handled without causing real CPU fault */
1132
1133 /* now we have a real cpu fault */
1134 tb = tb_find_pc(pc);
1135 if (tb) {
1136 /* the PC is inside the translated code. It means that we have
1137 a virtual CPU fault */
1138 cpu_restore_state(tb, env, pc, puc);
1139 }
bellardfdf9b3e2006-04-27 21:07:38 +00001140#if 0
ths5fafdf22007-09-16 21:08:06 +00001141 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
bellardfdf9b3e2006-04-27 21:07:38 +00001142 env->nip, env->error_code, tb);
1143#endif
1144 /* we restore the process signal mask as the sigreturn should
1145 do it (XXX: use sigsetjmp) */
pbrook355fb232006-06-17 19:58:25 +00001146 sigprocmask(SIG_SETMASK, old_set, NULL);
1147 cpu_loop_exit();
bellardfdf9b3e2006-04-27 21:07:38 +00001148 /* never comes here */
1149 return 1;
1150}
j_mayereddf68a2007-04-05 07:22:49 +00001151
1152#elif defined (TARGET_ALPHA)
1153static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1154 int is_write, sigset_t *old_set,
1155 void *puc)
1156{
1157 TranslationBlock *tb;
1158 int ret;
ths3b46e622007-09-17 08:09:54 +00001159
j_mayereddf68a2007-04-05 07:22:49 +00001160 if (cpu_single_env)
1161 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1162#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001163 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
j_mayereddf68a2007-04-05 07:22:49 +00001164 pc, address, is_write, *(unsigned long *)old_set);
1165#endif
1166 /* XXX: locking issue */
1167 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1168 return 1;
1169 }
1170
1171 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001172 ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
j_mayereddf68a2007-04-05 07:22:49 +00001173 if (ret < 0)
1174 return 0; /* not an MMU fault */
1175 if (ret == 0)
1176 return 1; /* the MMU fault was handled without causing real CPU fault */
1177
1178 /* now we have a real cpu fault */
1179 tb = tb_find_pc(pc);
1180 if (tb) {
1181 /* the PC is inside the translated code. It means that we have
1182 a virtual CPU fault */
1183 cpu_restore_state(tb, env, pc, puc);
1184 }
1185#if 0
ths5fafdf22007-09-16 21:08:06 +00001186 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
j_mayereddf68a2007-04-05 07:22:49 +00001187 env->nip, env->error_code, tb);
1188#endif
1189 /* we restore the process signal mask as the sigreturn should
1190 do it (XXX: use sigsetjmp) */
1191 sigprocmask(SIG_SETMASK, old_set, NULL);
1192 cpu_loop_exit();
1193 /* never comes here */
1194 return 1;
1195}
thsf1ccf902007-10-08 13:16:14 +00001196#elif defined (TARGET_CRIS)
1197static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1198 int is_write, sigset_t *old_set,
1199 void *puc)
1200{
1201 TranslationBlock *tb;
1202 int ret;
1203
1204 if (cpu_single_env)
1205 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1206#if defined(DEBUG_SIGNAL)
1207 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1208 pc, address, is_write, *(unsigned long *)old_set);
1209#endif
1210 /* XXX: locking issue */
1211 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1212 return 1;
1213 }
1214
1215 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001216 ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
thsf1ccf902007-10-08 13:16:14 +00001217 if (ret < 0)
1218 return 0; /* not an MMU fault */
1219 if (ret == 0)
1220 return 1; /* the MMU fault was handled without causing real CPU fault */
1221
1222 /* now we have a real cpu fault */
1223 tb = tb_find_pc(pc);
1224 if (tb) {
1225 /* the PC is inside the translated code. It means that we have
1226 a virtual CPU fault */
1227 cpu_restore_state(tb, env, pc, puc);
1228 }
thsf1ccf902007-10-08 13:16:14 +00001229 /* we restore the process signal mask as the sigreturn should
1230 do it (XXX: use sigsetjmp) */
1231 sigprocmask(SIG_SETMASK, old_set, NULL);
1232 cpu_loop_exit();
1233 /* never comes here */
1234 return 1;
1235}
1236
bellarde4533c72003-06-15 19:51:39 +00001237#else
1238#error unsupported target CPU
1239#endif
bellard9de5e442003-03-23 16:49:39 +00001240
bellard2b413142003-05-14 23:01:10 +00001241#if defined(__i386__)
1242
bellardd8ecc0b2007-02-05 21:41:46 +00001243#if defined(__APPLE__)
1244# include <sys/ucontext.h>
1245
1246# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1247# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
1248# define ERROR_sig(context) ((context)->uc_mcontext->es.err)
blueswir1d39bb242009-04-10 07:29:34 +00001249# define MASK_sig(context) ((context)->uc_sigmask)
1250#elif defined(__OpenBSD__)
1251# define EIP_sig(context) ((context)->sc_eip)
1252# define TRAP_sig(context) ((context)->sc_trapno)
1253# define ERROR_sig(context) ((context)->sc_err)
1254# define MASK_sig(context) ((context)->sc_mask)
bellardd8ecc0b2007-02-05 21:41:46 +00001255#else
1256# define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
1257# define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
1258# define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
blueswir1d39bb242009-04-10 07:29:34 +00001259# define MASK_sig(context) ((context)->uc_sigmask)
bellardd8ecc0b2007-02-05 21:41:46 +00001260#endif
1261
ths5fafdf22007-09-16 21:08:06 +00001262int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001263 void *puc)
bellard9de5e442003-03-23 16:49:39 +00001264{
ths5a7b5422007-01-31 12:16:51 +00001265 siginfo_t *info = pinfo;
blueswir1d39bb242009-04-10 07:29:34 +00001266#if defined(__OpenBSD__)
1267 struct sigcontext *uc = puc;
1268#else
bellard9de5e442003-03-23 16:49:39 +00001269 struct ucontext *uc = puc;
blueswir1d39bb242009-04-10 07:29:34 +00001270#endif
bellard9de5e442003-03-23 16:49:39 +00001271 unsigned long pc;
bellardbf3e8bf2004-02-16 21:58:54 +00001272 int trapno;
bellard97eb5b12004-02-25 23:19:55 +00001273
bellardd691f662003-03-24 21:58:34 +00001274#ifndef REG_EIP
1275/* for glibc 2.1 */
bellardfd6ce8f2003-05-14 19:00:11 +00001276#define REG_EIP EIP
1277#define REG_ERR ERR
1278#define REG_TRAPNO TRAPNO
bellardd691f662003-03-24 21:58:34 +00001279#endif
bellardd8ecc0b2007-02-05 21:41:46 +00001280 pc = EIP_sig(uc);
1281 trapno = TRAP_sig(uc);
bellardec6338b2007-11-08 14:25:03 +00001282 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1283 trapno == 0xe ?
1284 (ERROR_sig(uc) >> 1) & 1 : 0,
blueswir1d39bb242009-04-10 07:29:34 +00001285 &MASK_sig(uc), puc);
bellard2b413142003-05-14 23:01:10 +00001286}
1287
bellardbc51c5c2004-03-17 23:46:04 +00001288#elif defined(__x86_64__)
1289
blueswir1b3efe5c2008-12-05 17:55:45 +00001290#ifdef __NetBSD__
blueswir1d397abb2009-04-10 13:00:29 +00001291#define PC_sig(context) _UC_MACHINE_PC(context)
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)
1295#elif defined(__OpenBSD__)
1296#define PC_sig(context) ((context)->sc_rip)
1297#define TRAP_sig(context) ((context)->sc_trapno)
1298#define ERROR_sig(context) ((context)->sc_err)
1299#define MASK_sig(context) ((context)->sc_mask)
blueswir1b3efe5c2008-12-05 17:55:45 +00001300#else
blueswir1d397abb2009-04-10 13:00:29 +00001301#define PC_sig(context) ((context)->uc_mcontext.gregs[REG_RIP])
1302#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
1303#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
1304#define MASK_sig(context) ((context)->uc_sigmask)
blueswir1b3efe5c2008-12-05 17:55:45 +00001305#endif
1306
ths5a7b5422007-01-31 12:16:51 +00001307int cpu_signal_handler(int host_signum, void *pinfo,
bellardbc51c5c2004-03-17 23:46:04 +00001308 void *puc)
1309{
ths5a7b5422007-01-31 12:16:51 +00001310 siginfo_t *info = pinfo;
bellardbc51c5c2004-03-17 23:46:04 +00001311 unsigned long pc;
blueswir1b3efe5c2008-12-05 17:55:45 +00001312#ifdef __NetBSD__
1313 ucontext_t *uc = puc;
blueswir1d397abb2009-04-10 13:00:29 +00001314#elif defined(__OpenBSD__)
1315 struct sigcontext *uc = puc;
blueswir1b3efe5c2008-12-05 17:55:45 +00001316#else
1317 struct ucontext *uc = puc;
1318#endif
bellardbc51c5c2004-03-17 23:46:04 +00001319
blueswir1d397abb2009-04-10 13:00:29 +00001320 pc = PC_sig(uc);
ths5fafdf22007-09-16 21:08:06 +00001321 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
blueswir1d397abb2009-04-10 13:00:29 +00001322 TRAP_sig(uc) == 0xe ?
1323 (ERROR_sig(uc) >> 1) & 1 : 0,
1324 &MASK_sig(uc), puc);
bellardbc51c5c2004-03-17 23:46:04 +00001325}
1326
malce58ffeb2009-01-14 18:39:49 +00001327#elif defined(_ARCH_PPC)
bellard2b413142003-05-14 23:01:10 +00001328
bellard83fb7ad2004-07-05 21:25:26 +00001329/***********************************************************************
1330 * signal context platform-specific definitions
1331 * From Wine
1332 */
1333#ifdef linux
1334/* All Registers access - only for local access */
1335# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
1336/* Gpr Registers access */
1337# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
1338# define IAR_sig(context) REG_sig(nip, context) /* Program counter */
1339# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
1340# define CTR_sig(context) REG_sig(ctr, context) /* Count register */
1341# define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
1342# define LR_sig(context) REG_sig(link, context) /* Link register */
1343# define CR_sig(context) REG_sig(ccr, context) /* Condition register */
1344/* Float Registers access */
1345# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1346# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1347/* Exception Registers access */
1348# define DAR_sig(context) REG_sig(dar, context)
1349# define DSISR_sig(context) REG_sig(dsisr, context)
1350# define TRAP_sig(context) REG_sig(trap, context)
1351#endif /* linux */
1352
1353#ifdef __APPLE__
1354# include <sys/ucontext.h>
1355typedef struct ucontext SIGCONTEXT;
1356/* All Registers access - only for local access */
1357# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
1358# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
1359# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
1360# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
1361/* Gpr Registers access */
1362# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
1363# define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
1364# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
1365# define CTR_sig(context) REG_sig(ctr, context)
1366# define XER_sig(context) REG_sig(xer, context) /* Link register */
1367# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
1368# define CR_sig(context) REG_sig(cr, context) /* Condition register */
1369/* Float Registers access */
1370# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
1371# define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
1372/* Exception Registers access */
1373# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
1374# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
1375# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1376#endif /* __APPLE__ */
1377
ths5fafdf22007-09-16 21:08:06 +00001378int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001379 void *puc)
bellard2b413142003-05-14 23:01:10 +00001380{
ths5a7b5422007-01-31 12:16:51 +00001381 siginfo_t *info = pinfo;
bellard25eb4482003-05-14 21:50:54 +00001382 struct ucontext *uc = puc;
bellard25eb4482003-05-14 21:50:54 +00001383 unsigned long pc;
bellard25eb4482003-05-14 21:50:54 +00001384 int is_write;
1385
bellard83fb7ad2004-07-05 21:25:26 +00001386 pc = IAR_sig(uc);
bellard25eb4482003-05-14 21:50:54 +00001387 is_write = 0;
1388#if 0
1389 /* ppc 4xx case */
bellard83fb7ad2004-07-05 21:25:26 +00001390 if (DSISR_sig(uc) & 0x00800000)
bellard25eb4482003-05-14 21:50:54 +00001391 is_write = 1;
bellard9de5e442003-03-23 16:49:39 +00001392#else
bellard83fb7ad2004-07-05 21:25:26 +00001393 if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
bellard25eb4482003-05-14 21:50:54 +00001394 is_write = 1;
1395#endif
ths5fafdf22007-09-16 21:08:06 +00001396 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001397 is_write, &uc->uc_sigmask, puc);
bellard9de5e442003-03-23 16:49:39 +00001398}
bellard2b413142003-05-14 23:01:10 +00001399
bellard2f87c602003-06-02 20:38:09 +00001400#elif defined(__alpha__)
1401
ths5fafdf22007-09-16 21:08:06 +00001402int cpu_signal_handler(int host_signum, void *pinfo,
bellard2f87c602003-06-02 20:38:09 +00001403 void *puc)
1404{
ths5a7b5422007-01-31 12:16:51 +00001405 siginfo_t *info = pinfo;
bellard2f87c602003-06-02 20:38:09 +00001406 struct ucontext *uc = puc;
1407 uint32_t *pc = uc->uc_mcontext.sc_pc;
1408 uint32_t insn = *pc;
1409 int is_write = 0;
1410
bellard8c6939c2003-06-09 15:28:00 +00001411 /* XXX: need kernel patch to get write flag faster */
bellard2f87c602003-06-02 20:38:09 +00001412 switch (insn >> 26) {
1413 case 0x0d: // stw
1414 case 0x0e: // stb
1415 case 0x0f: // stq_u
1416 case 0x24: // stf
1417 case 0x25: // stg
1418 case 0x26: // sts
1419 case 0x27: // stt
1420 case 0x2c: // stl
1421 case 0x2d: // stq
1422 case 0x2e: // stl_c
1423 case 0x2f: // stq_c
1424 is_write = 1;
1425 }
1426
ths5fafdf22007-09-16 21:08:06 +00001427 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001428 is_write, &uc->uc_sigmask, puc);
bellard2f87c602003-06-02 20:38:09 +00001429}
bellard8c6939c2003-06-09 15:28:00 +00001430#elif defined(__sparc__)
1431
ths5fafdf22007-09-16 21:08:06 +00001432int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001433 void *puc)
bellard8c6939c2003-06-09 15:28:00 +00001434{
ths5a7b5422007-01-31 12:16:51 +00001435 siginfo_t *info = pinfo;
bellard8c6939c2003-06-09 15:28:00 +00001436 int is_write;
1437 uint32_t insn;
Juan Quinteladfe5fff2009-07-27 16:12:40 +02001438#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
blueswir1c9e1e2b2008-05-18 06:40:16 +00001439 uint32_t *regs = (uint32_t *)(info + 1);
1440 void *sigmask = (regs + 20);
bellard8c6939c2003-06-09 15:28:00 +00001441 /* XXX: is there a standard glibc define ? */
blueswir1c9e1e2b2008-05-18 06:40:16 +00001442 unsigned long pc = regs[1];
1443#else
blueswir184778502008-10-26 20:33:16 +00001444#ifdef __linux__
blueswir1c9e1e2b2008-05-18 06:40:16 +00001445 struct sigcontext *sc = puc;
1446 unsigned long pc = sc->sigc_regs.tpc;
1447 void *sigmask = (void *)sc->sigc_mask;
blueswir184778502008-10-26 20:33:16 +00001448#elif defined(__OpenBSD__)
1449 struct sigcontext *uc = puc;
1450 unsigned long pc = uc->sc_pc;
1451 void *sigmask = (void *)(long)uc->sc_mask;
1452#endif
blueswir1c9e1e2b2008-05-18 06:40:16 +00001453#endif
1454
bellard8c6939c2003-06-09 15:28:00 +00001455 /* XXX: need kernel patch to get write flag faster */
1456 is_write = 0;
1457 insn = *(uint32_t *)pc;
1458 if ((insn >> 30) == 3) {
1459 switch((insn >> 19) & 0x3f) {
1460 case 0x05: // stb
Blue Swirld877fa52009-04-25 19:07:16 +00001461 case 0x15: // stba
bellard8c6939c2003-06-09 15:28:00 +00001462 case 0x06: // sth
Blue Swirld877fa52009-04-25 19:07:16 +00001463 case 0x16: // stha
bellard8c6939c2003-06-09 15:28:00 +00001464 case 0x04: // st
Blue Swirld877fa52009-04-25 19:07:16 +00001465 case 0x14: // sta
bellard8c6939c2003-06-09 15:28:00 +00001466 case 0x07: // std
Blue Swirld877fa52009-04-25 19:07:16 +00001467 case 0x17: // stda
1468 case 0x0e: // stx
1469 case 0x1e: // stxa
bellard8c6939c2003-06-09 15:28:00 +00001470 case 0x24: // stf
Blue Swirld877fa52009-04-25 19:07:16 +00001471 case 0x34: // stfa
bellard8c6939c2003-06-09 15:28:00 +00001472 case 0x27: // stdf
Blue Swirld877fa52009-04-25 19:07:16 +00001473 case 0x37: // stdfa
1474 case 0x26: // stqf
1475 case 0x36: // stqfa
bellard8c6939c2003-06-09 15:28:00 +00001476 case 0x25: // stfsr
Blue Swirld877fa52009-04-25 19:07:16 +00001477 case 0x3c: // casa
1478 case 0x3e: // casxa
bellard8c6939c2003-06-09 15:28:00 +00001479 is_write = 1;
1480 break;
1481 }
1482 }
ths5fafdf22007-09-16 21:08:06 +00001483 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001484 is_write, sigmask, NULL);
bellard8c6939c2003-06-09 15:28:00 +00001485}
1486
1487#elif defined(__arm__)
1488
ths5fafdf22007-09-16 21:08:06 +00001489int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001490 void *puc)
bellard8c6939c2003-06-09 15:28:00 +00001491{
ths5a7b5422007-01-31 12:16:51 +00001492 siginfo_t *info = pinfo;
bellard8c6939c2003-06-09 15:28:00 +00001493 struct ucontext *uc = puc;
1494 unsigned long pc;
1495 int is_write;
ths3b46e622007-09-17 08:09:54 +00001496
blueswir148bbf112008-07-08 18:35:02 +00001497#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
balrog5c49b362008-06-02 01:01:18 +00001498 pc = uc->uc_mcontext.gregs[R15];
1499#else
balrog4eee57f2008-05-06 14:47:19 +00001500 pc = uc->uc_mcontext.arm_pc;
balrog5c49b362008-06-02 01:01:18 +00001501#endif
bellard8c6939c2003-06-09 15:28:00 +00001502 /* XXX: compute is_write */
1503 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001504 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellard8c6939c2003-06-09 15:28:00 +00001505 is_write,
pbrookf3a96762006-07-29 19:09:31 +00001506 &uc->uc_sigmask, puc);
bellard8c6939c2003-06-09 15:28:00 +00001507}
1508
bellard38e584a2003-08-10 22:14:22 +00001509#elif defined(__mc68000)
1510
ths5fafdf22007-09-16 21:08:06 +00001511int cpu_signal_handler(int host_signum, void *pinfo,
bellard38e584a2003-08-10 22:14:22 +00001512 void *puc)
1513{
ths5a7b5422007-01-31 12:16:51 +00001514 siginfo_t *info = pinfo;
bellard38e584a2003-08-10 22:14:22 +00001515 struct ucontext *uc = puc;
1516 unsigned long pc;
1517 int is_write;
ths3b46e622007-09-17 08:09:54 +00001518
bellard38e584a2003-08-10 22:14:22 +00001519 pc = uc->uc_mcontext.gregs[16];
1520 /* XXX: compute is_write */
1521 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001522 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellard38e584a2003-08-10 22:14:22 +00001523 is_write,
bellardbf3e8bf2004-02-16 21:58:54 +00001524 &uc->uc_sigmask, puc);
bellard38e584a2003-08-10 22:14:22 +00001525}
1526
bellardb8076a72005-04-07 22:20:31 +00001527#elif defined(__ia64)
1528
1529#ifndef __ISR_VALID
1530 /* This ought to be in <bits/siginfo.h>... */
1531# define __ISR_VALID 1
bellardb8076a72005-04-07 22:20:31 +00001532#endif
1533
ths5a7b5422007-01-31 12:16:51 +00001534int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
bellardb8076a72005-04-07 22:20:31 +00001535{
ths5a7b5422007-01-31 12:16:51 +00001536 siginfo_t *info = pinfo;
bellardb8076a72005-04-07 22:20:31 +00001537 struct ucontext *uc = puc;
1538 unsigned long ip;
1539 int is_write = 0;
1540
1541 ip = uc->uc_mcontext.sc_ip;
1542 switch (host_signum) {
1543 case SIGILL:
1544 case SIGFPE:
1545 case SIGSEGV:
1546 case SIGBUS:
1547 case SIGTRAP:
bellardfd4a43e2006-04-24 20:32:17 +00001548 if (info->si_code && (info->si_segvflags & __ISR_VALID))
bellardb8076a72005-04-07 22:20:31 +00001549 /* ISR.W (write-access) is bit 33: */
1550 is_write = (info->si_isr >> 33) & 1;
1551 break;
1552
1553 default:
1554 break;
1555 }
1556 return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1557 is_write,
1558 &uc->uc_sigmask, puc);
1559}
1560
bellard90cb9492005-07-24 15:11:38 +00001561#elif defined(__s390__)
1562
ths5fafdf22007-09-16 21:08:06 +00001563int cpu_signal_handler(int host_signum, void *pinfo,
bellard90cb9492005-07-24 15:11:38 +00001564 void *puc)
1565{
ths5a7b5422007-01-31 12:16:51 +00001566 siginfo_t *info = pinfo;
bellard90cb9492005-07-24 15:11:38 +00001567 struct ucontext *uc = puc;
1568 unsigned long pc;
1569 int is_write;
ths3b46e622007-09-17 08:09:54 +00001570
bellard90cb9492005-07-24 15:11:38 +00001571 pc = uc->uc_mcontext.psw.addr;
1572 /* XXX: compute is_write */
1573 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001574 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
thsc4b89d12007-05-05 19:23:11 +00001575 is_write, &uc->uc_sigmask, puc);
1576}
1577
1578#elif defined(__mips__)
1579
ths5fafdf22007-09-16 21:08:06 +00001580int cpu_signal_handler(int host_signum, void *pinfo,
thsc4b89d12007-05-05 19:23:11 +00001581 void *puc)
1582{
ths9617efe2007-05-08 21:05:55 +00001583 siginfo_t *info = pinfo;
thsc4b89d12007-05-05 19:23:11 +00001584 struct ucontext *uc = puc;
1585 greg_t pc = uc->uc_mcontext.pc;
1586 int is_write;
ths3b46e622007-09-17 08:09:54 +00001587
thsc4b89d12007-05-05 19:23:11 +00001588 /* XXX: compute is_write */
1589 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001590 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
thsc4b89d12007-05-05 19:23:11 +00001591 is_write, &uc->uc_sigmask, puc);
bellard90cb9492005-07-24 15:11:38 +00001592}
1593
aurel32f54b3f92008-04-12 20:14:54 +00001594#elif defined(__hppa__)
1595
1596int cpu_signal_handler(int host_signum, void *pinfo,
1597 void *puc)
1598{
1599 struct siginfo *info = pinfo;
1600 struct ucontext *uc = puc;
1601 unsigned long pc;
1602 int is_write;
1603
1604 pc = uc->uc_mcontext.sc_iaoq[0];
1605 /* FIXME: compute is_write */
1606 is_write = 0;
1607 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1608 is_write,
1609 &uc->uc_sigmask, puc);
1610}
1611
bellard2b413142003-05-14 23:01:10 +00001612#else
1613
bellard3fb2ded2003-06-24 13:22:59 +00001614#error host CPU specific signal handler needed
bellard2b413142003-05-14 23:01:10 +00001615
1616#endif
bellard67b915a2004-03-31 23:37:16 +00001617
1618#endif /* !defined(CONFIG_SOFTMMU) */