blob: 2b74aeecf7351d867824296e196886008004d8cc [file] [log] [blame]
bellard7d132992003-03-06 23:23:54 +00001/*
2 * i386 emulator main execution loop
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard66321a12005-04-06 20:47:48 +00004 * Copyright (c) 2003-2005 Fabrice Bellard
bellard7d132992003-03-06 23:23:54 +00005 *
bellard3ef693a2003-03-23 20:17:16 +00006 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
bellard7d132992003-03-06 23:23:54 +000010 *
bellard3ef693a2003-03-23 20:17:16 +000011 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
bellard7d132992003-03-06 23:23:54 +000015 *
bellard3ef693a2003-03-23 20:17:16 +000016 * You should have received a copy of the GNU Lesser General Public
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
bellard7d132992003-03-06 23:23:54 +000018 */
bellarde4533c72003-06-15 19:51:39 +000019#include "config.h"
bellard93ac68b2003-09-30 20:57:29 +000020#include "exec.h"
bellard956034d2003-04-29 20:40:53 +000021#include "disas.h"
bellard7cb69ca2008-05-10 10:55:51 +000022#include "tcg.h"
aliguori7ba1e612008-11-05 16:04:33 +000023#include "kvm.h"
bellard7d132992003-03-06 23:23:54 +000024
bellardfbf9eeb2004-04-25 21:21:33 +000025#if !defined(CONFIG_SOFTMMU)
26#undef EAX
27#undef ECX
28#undef EDX
29#undef EBX
30#undef ESP
31#undef EBP
32#undef ESI
33#undef EDI
34#undef EIP
35#include <signal.h>
blueswir184778502008-10-26 20:33:16 +000036#ifdef __linux__
bellardfbf9eeb2004-04-25 21:21:33 +000037#include <sys/ucontext.h>
38#endif
blueswir184778502008-10-26 20:33:16 +000039#endif
bellardfbf9eeb2004-04-25 21:21:33 +000040
Juan Quinteladfe5fff2009-07-27 16:12:40 +020041#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
blueswir1572a9d42008-05-17 07:38:10 +000042// Work around ugly bugs in glibc that mangle global register contents
43#undef env
44#define env cpu_single_env
45#endif
46
bellard36bdbe52003-11-19 22:12:02 +000047int tb_invalidated_flag;
48
Juan Quintelaf0667e62009-07-27 16:13:05 +020049//#define CONFIG_DEBUG_EXEC
bellard9de5e442003-03-23 16:49:39 +000050//#define DEBUG_SIGNAL
bellard7d132992003-03-06 23:23:54 +000051
aliguori6a4955a2009-04-24 18:03:20 +000052int qemu_cpu_has_work(CPUState *env)
53{
54 return cpu_has_work(env);
55}
56
bellarde4533c72003-06-15 19:51:39 +000057void cpu_loop_exit(void)
58{
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;
blueswir1b5fc09a2008-05-04 06:38:18 +0000488 next_tb = 0;
bellard66321a12005-04-06 20:47:48 +0000489 }
bellarde95c8d52004-09-30 22:22:08 +0000490 } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
491 //do_interrupt(0, 0, 0, 0, 0);
492 env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
balroga90b7312007-05-01 01:28:01 +0000493 }
bellardb5ff1b32005-11-26 10:38:39 +0000494#elif defined(TARGET_ARM)
495 if (interrupt_request & CPU_INTERRUPT_FIQ
496 && !(env->uncached_cpsr & CPSR_F)) {
497 env->exception_index = EXCP_FIQ;
498 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000499 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000500 }
pbrook9ee6e8b2007-11-11 00:04:49 +0000501 /* ARMv7-M interrupt return works by loading a magic value
502 into the PC. On real hardware the load causes the
503 return to occur. The qemu implementation performs the
504 jump normally, then does the exception return when the
505 CPU tries to execute code at the magic address.
506 This will cause the magic PC value to be pushed to
507 the stack if an interrupt occured at the wrong time.
508 We avoid this by disabling interrupts when
509 pc contains a magic address. */
bellardb5ff1b32005-11-26 10:38:39 +0000510 if (interrupt_request & CPU_INTERRUPT_HARD
pbrook9ee6e8b2007-11-11 00:04:49 +0000511 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
512 || !(env->uncached_cpsr & CPSR_I))) {
bellardb5ff1b32005-11-26 10:38:39 +0000513 env->exception_index = EXCP_IRQ;
514 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000515 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000516 }
bellardfdf9b3e2006-04-27 21:07:38 +0000517#elif defined(TARGET_SH4)
thse96e2042007-12-02 06:18:24 +0000518 if (interrupt_request & CPU_INTERRUPT_HARD) {
519 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000520 next_tb = 0;
thse96e2042007-12-02 06:18:24 +0000521 }
j_mayereddf68a2007-04-05 07:22:49 +0000522#elif defined(TARGET_ALPHA)
523 if (interrupt_request & CPU_INTERRUPT_HARD) {
524 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000525 next_tb = 0;
j_mayereddf68a2007-04-05 07:22:49 +0000526 }
thsf1ccf902007-10-08 13:16:14 +0000527#elif defined(TARGET_CRIS)
edgar_igl1b1a38b2008-06-09 23:18:06 +0000528 if (interrupt_request & CPU_INTERRUPT_HARD
529 && (env->pregs[PR_CCS] & I_FLAG)) {
530 env->exception_index = EXCP_IRQ;
531 do_interrupt(env);
532 next_tb = 0;
533 }
534 if (interrupt_request & CPU_INTERRUPT_NMI
535 && (env->pregs[PR_CCS] & M_FLAG)) {
536 env->exception_index = EXCP_NMI;
thsf1ccf902007-10-08 13:16:14 +0000537 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000538 next_tb = 0;
thsf1ccf902007-10-08 13:16:14 +0000539 }
pbrook06338792007-05-23 19:58:11 +0000540#elif defined(TARGET_M68K)
541 if (interrupt_request & CPU_INTERRUPT_HARD
542 && ((env->sr & SR_I) >> SR_I_SHIFT)
543 < env->pending_level) {
544 /* Real hardware gets the interrupt vector via an
545 IACK cycle at this point. Current emulated
546 hardware doesn't rely on this, so we
547 provide/save the vector when the interrupt is
548 first signalled. */
549 env->exception_index = env->pending_vector;
550 do_interrupt(1);
blueswir1b5fc09a2008-05-04 06:38:18 +0000551 next_tb = 0;
pbrook06338792007-05-23 19:58:11 +0000552 }
bellard68a79312003-06-30 13:12:32 +0000553#endif
bellard9d050952006-05-22 22:03:52 +0000554 /* Don't use the cached interupt_request value,
555 do_interrupt may have updated the EXITTB flag. */
bellardb5ff1b32005-11-26 10:38:39 +0000556 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
bellardbf3e8bf2004-02-16 21:58:54 +0000557 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
558 /* ensure that no TB jump will be modified as
559 the program flow was changed */
blueswir1b5fc09a2008-05-04 06:38:18 +0000560 next_tb = 0;
bellardbf3e8bf2004-02-16 21:58:54 +0000561 }
aurel32be214e62009-03-06 21:48:00 +0000562 }
563 if (unlikely(env->exit_request)) {
564 env->exit_request = 0;
565 env->exception_index = EXCP_INTERRUPT;
566 cpu_loop_exit();
bellard3fb2ded2003-06-24 13:22:59 +0000567 }
Juan Quintelaf0667e62009-07-27 16:13:05 +0200568#ifdef CONFIG_DEBUG_EXEC
aliguori8fec2b82009-01-15 22:36:53 +0000569 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
bellard3fb2ded2003-06-24 13:22:59 +0000570 /* restore flags in standard format */
thsecb644f2007-06-03 18:45:53 +0000571 regs_to_env();
572#if defined(TARGET_I386)
pbrooka7812ae2008-11-17 14:43:54 +0000573 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
aliguori93fcfe32009-01-15 22:34:14 +0000574 log_cpu_state(env, X86_DUMP_CCOP);
bellard3fb2ded2003-06-24 13:22:59 +0000575 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellarde4533c72003-06-15 19:51:39 +0000576#elif defined(TARGET_ARM)
aliguori93fcfe32009-01-15 22:34:14 +0000577 log_cpu_state(env, 0);
bellard93ac68b2003-09-30 20:57:29 +0000578#elif defined(TARGET_SPARC)
aliguori93fcfe32009-01-15 22:34:14 +0000579 log_cpu_state(env, 0);
bellard67867302003-11-23 17:05:30 +0000580#elif defined(TARGET_PPC)
aliguori93fcfe32009-01-15 22:34:14 +0000581 log_cpu_state(env, 0);
pbrooke6e59062006-10-22 00:18:54 +0000582#elif defined(TARGET_M68K)
583 cpu_m68k_flush_flags(env, env->cc_op);
584 env->cc_op = CC_OP_FLAGS;
585 env->sr = (env->sr & 0xffe0)
586 | env->cc_dest | (env->cc_x << 4);
aliguori93fcfe32009-01-15 22:34:14 +0000587 log_cpu_state(env, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200588#elif defined(TARGET_MICROBLAZE)
589 log_cpu_state(env, 0);
bellard6af0bf92005-07-02 14:58:51 +0000590#elif defined(TARGET_MIPS)
aliguori93fcfe32009-01-15 22:34:14 +0000591 log_cpu_state(env, 0);
bellardfdf9b3e2006-04-27 21:07:38 +0000592#elif defined(TARGET_SH4)
aliguori93fcfe32009-01-15 22:34:14 +0000593 log_cpu_state(env, 0);
j_mayereddf68a2007-04-05 07:22:49 +0000594#elif defined(TARGET_ALPHA)
aliguori93fcfe32009-01-15 22:34:14 +0000595 log_cpu_state(env, 0);
thsf1ccf902007-10-08 13:16:14 +0000596#elif defined(TARGET_CRIS)
aliguori93fcfe32009-01-15 22:34:14 +0000597 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000598#else
ths5fafdf22007-09-16 21:08:06 +0000599#error unsupported target CPU
bellarde4533c72003-06-15 19:51:39 +0000600#endif
bellard3fb2ded2003-06-24 13:22:59 +0000601 }
bellard7d132992003-03-06 23:23:54 +0000602#endif
pbrookd5975362008-06-07 20:50:51 +0000603 spin_lock(&tb_lock);
bellard8a40a182005-11-20 10:35:40 +0000604 tb = tb_find_fast();
pbrookd5975362008-06-07 20:50:51 +0000605 /* Note: we do it here to avoid a gcc bug on Mac OS X when
606 doing it in tb_find_slow */
607 if (tb_invalidated_flag) {
608 /* as some TB could have been invalidated because
609 of memory exceptions while generating the code, we
610 must recompute the hash index here */
611 next_tb = 0;
pbrook2e70f6e2008-06-29 01:03:05 +0000612 tb_invalidated_flag = 0;
pbrookd5975362008-06-07 20:50:51 +0000613 }
Juan Quintelaf0667e62009-07-27 16:13:05 +0200614#ifdef CONFIG_DEBUG_EXEC
aliguori93fcfe32009-01-15 22:34:14 +0000615 qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
616 (long)tb->tc_ptr, tb->pc,
617 lookup_symbol(tb->pc));
bellard9d27abd2003-05-10 13:13:54 +0000618#endif
bellard8a40a182005-11-20 10:35:40 +0000619 /* see if we can patch the calling TB. When the TB
620 spans two pages, we cannot safely do a direct
621 jump. */
bellardc27004e2005-01-03 23:35:10 +0000622 {
blueswir1b5fc09a2008-05-04 06:38:18 +0000623 if (next_tb != 0 &&
blueswir1640f42e2009-04-19 10:18:01 +0000624#ifdef CONFIG_KQEMU
bellardf32fc642006-02-08 22:43:39 +0000625 (env->kqemu_enabled != 2) &&
626#endif
bellardec6338b2007-11-08 14:25:03 +0000627 tb->page_addr[1] == -1) {
blueswir1b5fc09a2008-05-04 06:38:18 +0000628 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
bellard3fb2ded2003-06-24 13:22:59 +0000629 }
bellardc27004e2005-01-03 23:35:10 +0000630 }
pbrookd5975362008-06-07 20:50:51 +0000631 spin_unlock(&tb_lock);
bellard83479e72003-06-25 16:12:37 +0000632 env->current_tb = tb;
malc55e8b852008-11-04 14:18:13 +0000633
634 /* cpu_interrupt might be called while translating the
635 TB, but before it is linked into a potentially
636 infinite loop and becomes env->current_tb. Avoid
637 starting execution if there is a pending interrupt. */
aurel32be214e62009-03-06 21:48:00 +0000638 if (unlikely (env->exit_request))
malc55e8b852008-11-04 14:18:13 +0000639 env->current_tb = NULL;
640
pbrook2e70f6e2008-06-29 01:03:05 +0000641 while (env->current_tb) {
642 tc_ptr = tb->tc_ptr;
bellard3fb2ded2003-06-24 13:22:59 +0000643 /* execute the generated code */
Juan Quinteladfe5fff2009-07-27 16:12:40 +0200644#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
blueswir1572a9d42008-05-17 07:38:10 +0000645#undef env
pbrook2e70f6e2008-06-29 01:03:05 +0000646 env = cpu_single_env;
blueswir1572a9d42008-05-17 07:38:10 +0000647#define env cpu_single_env
648#endif
pbrook2e70f6e2008-06-29 01:03:05 +0000649 next_tb = tcg_qemu_tb_exec(tc_ptr);
650 env->current_tb = NULL;
651 if ((next_tb & 3) == 2) {
thsbf20dc02008-06-30 17:22:19 +0000652 /* Instruction counter expired. */
pbrook2e70f6e2008-06-29 01:03:05 +0000653 int insns_left;
654 tb = (TranslationBlock *)(long)(next_tb & ~3);
655 /* Restore PC. */
aliguori622ed362008-11-18 19:36:03 +0000656 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000657 insns_left = env->icount_decr.u32;
658 if (env->icount_extra && insns_left >= 0) {
659 /* Refill decrementer and continue execution. */
660 env->icount_extra += insns_left;
661 if (env->icount_extra > 0xffff) {
662 insns_left = 0xffff;
663 } else {
664 insns_left = env->icount_extra;
665 }
666 env->icount_extra -= insns_left;
667 env->icount_decr.u16.low = insns_left;
668 } else {
669 if (insns_left > 0) {
670 /* Execute remaining instructions. */
671 cpu_exec_nocache(insns_left, tb);
672 }
673 env->exception_index = EXCP_INTERRUPT;
674 next_tb = 0;
675 cpu_loop_exit();
676 }
677 }
678 }
bellard4cbf74b2003-08-10 21:48:43 +0000679 /* reset soft MMU for next block (it can currently
680 only be set by a memory fault) */
blueswir1640f42e2009-04-19 10:18:01 +0000681#if defined(CONFIG_KQEMU)
bellardf32fc642006-02-08 22:43:39 +0000682#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
683 if (kqemu_is_ok(env) &&
684 (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
685 cpu_loop_exit();
686 }
687#endif
ths50a518e2007-06-03 18:52:15 +0000688 } /* for(;;) */
bellard3fb2ded2003-06-24 13:22:59 +0000689 } else {
bellard0d1a29f2004-10-12 22:01:28 +0000690 env_to_regs();
bellard7d132992003-03-06 23:23:54 +0000691 }
bellard3fb2ded2003-06-24 13:22:59 +0000692 } /* for(;;) */
693
bellard7d132992003-03-06 23:23:54 +0000694
bellarde4533c72003-06-15 19:51:39 +0000695#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000696 /* restore flags in standard format */
pbrooka7812ae2008-11-17 14:43:54 +0000697 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
bellarde4533c72003-06-15 19:51:39 +0000698#elif defined(TARGET_ARM)
bellardb7bcbe92005-02-22 19:27:29 +0000699 /* XXX: Save/restore host fpu exception state?. */
bellard93ac68b2003-09-30 20:57:29 +0000700#elif defined(TARGET_SPARC)
bellard67867302003-11-23 17:05:30 +0000701#elif defined(TARGET_PPC)
pbrooke6e59062006-10-22 00:18:54 +0000702#elif defined(TARGET_M68K)
703 cpu_m68k_flush_flags(env, env->cc_op);
704 env->cc_op = CC_OP_FLAGS;
705 env->sr = (env->sr & 0xffe0)
706 | env->cc_dest | (env->cc_x << 4);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200707#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000708#elif defined(TARGET_MIPS)
bellardfdf9b3e2006-04-27 21:07:38 +0000709#elif defined(TARGET_SH4)
j_mayereddf68a2007-04-05 07:22:49 +0000710#elif defined(TARGET_ALPHA)
thsf1ccf902007-10-08 13:16:14 +0000711#elif defined(TARGET_CRIS)
bellardfdf9b3e2006-04-27 21:07:38 +0000712 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000713#else
714#error unsupported target CPU
715#endif
pbrook1057eaa2007-02-04 13:37:44 +0000716
717 /* restore global registers */
pbrook1057eaa2007-02-04 13:37:44 +0000718#include "hostregs_helper.h"
719
bellard6a00d602005-11-21 23:25:50 +0000720 /* fail safe : never use cpu_single_env outside cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000721 cpu_single_env = NULL;
bellard7d132992003-03-06 23:23:54 +0000722 return ret;
723}
bellard6dbad632003-03-16 18:05:05 +0000724
bellardfbf9eeb2004-04-25 21:21:33 +0000725/* must only be called from the generated code as an exception can be
726 generated */
727void tb_invalidate_page_range(target_ulong start, target_ulong end)
728{
bellarddc5d0b32004-06-22 18:43:30 +0000729 /* XXX: cannot enable it yet because it yields to MMU exception
730 where NIP != read address on PowerPC */
731#if 0
bellardfbf9eeb2004-04-25 21:21:33 +0000732 target_ulong phys_addr;
733 phys_addr = get_phys_addr_code(env, start);
734 tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
bellarddc5d0b32004-06-22 18:43:30 +0000735#endif
bellardfbf9eeb2004-04-25 21:21:33 +0000736}
737
bellard1a18c712003-10-30 01:07:51 +0000738#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
bellarde4533c72003-06-15 19:51:39 +0000739
bellard6dbad632003-03-16 18:05:05 +0000740void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
741{
742 CPUX86State *saved_env;
743
744 saved_env = env;
745 env = s;
bellarda412ac52003-07-26 18:01:40 +0000746 if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
bellarda513fe12003-05-27 23:29:48 +0000747 selector &= 0xffff;
ths5fafdf22007-09-16 21:08:06 +0000748 cpu_x86_load_seg_cache(env, seg_reg, selector,
bellardc27004e2005-01-03 23:35:10 +0000749 (selector << 4), 0xffff, 0);
bellarda513fe12003-05-27 23:29:48 +0000750 } else {
bellard5d975592008-05-12 22:05:33 +0000751 helper_load_seg(seg_reg, selector);
bellarda513fe12003-05-27 23:29:48 +0000752 }
bellard6dbad632003-03-16 18:05:05 +0000753 env = saved_env;
754}
bellard9de5e442003-03-23 16:49:39 +0000755
bellard6f12a2a2007-11-11 22:16:56 +0000756void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
bellardd0a1ffc2003-05-29 20:04:28 +0000757{
758 CPUX86State *saved_env;
759
760 saved_env = env;
761 env = s;
ths3b46e622007-09-17 08:09:54 +0000762
bellard6f12a2a2007-11-11 22:16:56 +0000763 helper_fsave(ptr, data32);
bellardd0a1ffc2003-05-29 20:04:28 +0000764
765 env = saved_env;
766}
767
bellard6f12a2a2007-11-11 22:16:56 +0000768void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
bellardd0a1ffc2003-05-29 20:04:28 +0000769{
770 CPUX86State *saved_env;
771
772 saved_env = env;
773 env = s;
ths3b46e622007-09-17 08:09:54 +0000774
bellard6f12a2a2007-11-11 22:16:56 +0000775 helper_frstor(ptr, data32);
bellardd0a1ffc2003-05-29 20:04:28 +0000776
777 env = saved_env;
778}
779
bellarde4533c72003-06-15 19:51:39 +0000780#endif /* TARGET_I386 */
781
bellard67b915a2004-03-31 23:37:16 +0000782#if !defined(CONFIG_SOFTMMU)
783
bellard3fb2ded2003-06-24 13:22:59 +0000784#if defined(TARGET_I386)
785
bellardb56dad12003-05-08 15:38:04 +0000786/* 'pc' is the host PC at which the exception was raised. 'address' is
bellardfd6ce8f2003-05-14 19:00:11 +0000787 the effective address of the memory exception. 'is_write' is 1 if a
788 write caused the exception and otherwise 0'. 'old_set' is the
789 signal set which should be restored */
bellard2b413142003-05-14 23:01:10 +0000790static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
ths5fafdf22007-09-16 21:08:06 +0000791 int is_write, sigset_t *old_set,
bellardbf3e8bf2004-02-16 21:58:54 +0000792 void *puc)
bellard9de5e442003-03-23 16:49:39 +0000793{
bellarda513fe12003-05-27 23:29:48 +0000794 TranslationBlock *tb;
795 int ret;
bellard68a79312003-06-30 13:12:32 +0000796
bellard83479e72003-06-25 16:12:37 +0000797 if (cpu_single_env)
798 env = cpu_single_env; /* XXX: find a correct solution for multithread */
bellardfd6ce8f2003-05-14 19:00:11 +0000799#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000800 qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellardbf3e8bf2004-02-16 21:58:54 +0000801 pc, address, is_write, *(unsigned long *)old_set);
bellard9de5e442003-03-23 16:49:39 +0000802#endif
bellard25eb4482003-05-14 21:50:54 +0000803 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000804 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellardfd6ce8f2003-05-14 19:00:11 +0000805 return 1;
806 }
bellardfbf9eeb2004-04-25 21:21:33 +0000807
bellard3fb2ded2003-06-24 13:22:59 +0000808 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000809 ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard3fb2ded2003-06-24 13:22:59 +0000810 if (ret < 0)
811 return 0; /* not an MMU fault */
812 if (ret == 0)
813 return 1; /* the MMU fault was handled without causing real CPU fault */
814 /* now we have a real cpu fault */
bellarda513fe12003-05-27 23:29:48 +0000815 tb = tb_find_pc(pc);
816 if (tb) {
bellard9de5e442003-03-23 16:49:39 +0000817 /* the PC is inside the translated code. It means that we have
818 a virtual CPU fault */
bellardbf3e8bf2004-02-16 21:58:54 +0000819 cpu_restore_state(tb, env, pc, puc);
bellard3fb2ded2003-06-24 13:22:59 +0000820 }
bellard4cbf74b2003-08-10 21:48:43 +0000821 if (ret == 1) {
bellard3fb2ded2003-06-24 13:22:59 +0000822#if 0
ths5fafdf22007-09-16 21:08:06 +0000823 printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
bellard4cbf74b2003-08-10 21:48:43 +0000824 env->eip, env->cr[2], env->error_code);
bellard3fb2ded2003-06-24 13:22:59 +0000825#endif
bellard4cbf74b2003-08-10 21:48:43 +0000826 /* we restore the process signal mask as the sigreturn should
827 do it (XXX: use sigsetjmp) */
828 sigprocmask(SIG_SETMASK, old_set, NULL);
bellard54ca9092005-12-04 18:46:06 +0000829 raise_exception_err(env->exception_index, env->error_code);
bellard4cbf74b2003-08-10 21:48:43 +0000830 } else {
831 /* activate soft MMU for this block */
bellard3f337312003-08-20 23:02:09 +0000832 env->hflags |= HF_SOFTMMU_MASK;
bellardfbf9eeb2004-04-25 21:21:33 +0000833 cpu_resume_from_signal(env, puc);
bellard4cbf74b2003-08-10 21:48:43 +0000834 }
bellard3fb2ded2003-06-24 13:22:59 +0000835 /* never comes here */
836 return 1;
837}
838
bellarde4533c72003-06-15 19:51:39 +0000839#elif defined(TARGET_ARM)
bellard3fb2ded2003-06-24 13:22:59 +0000840static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bellardbf3e8bf2004-02-16 21:58:54 +0000841 int is_write, sigset_t *old_set,
842 void *puc)
bellard3fb2ded2003-06-24 13:22:59 +0000843{
bellard68016c62005-02-07 23:12:27 +0000844 TranslationBlock *tb;
845 int ret;
846
847 if (cpu_single_env)
848 env = cpu_single_env; /* XXX: find a correct solution for multithread */
849#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000850 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard68016c62005-02-07 23:12:27 +0000851 pc, address, is_write, *(unsigned long *)old_set);
852#endif
bellard9f0777e2005-02-02 20:42:01 +0000853 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000854 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellard9f0777e2005-02-02 20:42:01 +0000855 return 1;
856 }
bellard68016c62005-02-07 23:12:27 +0000857 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000858 ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard68016c62005-02-07 23:12:27 +0000859 if (ret < 0)
860 return 0; /* not an MMU fault */
861 if (ret == 0)
862 return 1; /* the MMU fault was handled without causing real CPU fault */
863 /* now we have a real cpu fault */
864 tb = tb_find_pc(pc);
865 if (tb) {
866 /* the PC is inside the translated code. It means that we have
867 a virtual CPU fault */
868 cpu_restore_state(tb, env, pc, puc);
869 }
870 /* we restore the process signal mask as the sigreturn should
871 do it (XXX: use sigsetjmp) */
872 sigprocmask(SIG_SETMASK, old_set, NULL);
873 cpu_loop_exit();
aurel32968c74d2008-04-11 04:55:17 +0000874 /* never comes here */
875 return 1;
bellard3fb2ded2003-06-24 13:22:59 +0000876}
bellard93ac68b2003-09-30 20:57:29 +0000877#elif defined(TARGET_SPARC)
878static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bellardbf3e8bf2004-02-16 21:58:54 +0000879 int is_write, sigset_t *old_set,
880 void *puc)
bellard93ac68b2003-09-30 20:57:29 +0000881{
bellard68016c62005-02-07 23:12:27 +0000882 TranslationBlock *tb;
883 int ret;
884
885 if (cpu_single_env)
886 env = cpu_single_env; /* XXX: find a correct solution for multithread */
887#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000888 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard68016c62005-02-07 23:12:27 +0000889 pc, address, is_write, *(unsigned long *)old_set);
890#endif
bellardb453b702004-01-04 15:45:21 +0000891 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000892 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellardb453b702004-01-04 15:45:21 +0000893 return 1;
894 }
bellard68016c62005-02-07 23:12:27 +0000895 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000896 ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard68016c62005-02-07 23:12:27 +0000897 if (ret < 0)
898 return 0; /* not an MMU fault */
899 if (ret == 0)
900 return 1; /* the MMU fault was handled without causing real CPU fault */
901 /* now we have a real cpu fault */
902 tb = tb_find_pc(pc);
903 if (tb) {
904 /* the PC is inside the translated code. It means that we have
905 a virtual CPU fault */
906 cpu_restore_state(tb, env, pc, puc);
907 }
908 /* we restore the process signal mask as the sigreturn should
909 do it (XXX: use sigsetjmp) */
910 sigprocmask(SIG_SETMASK, old_set, NULL);
911 cpu_loop_exit();
aurel32968c74d2008-04-11 04:55:17 +0000912 /* never comes here */
913 return 1;
bellard93ac68b2003-09-30 20:57:29 +0000914}
bellard67867302003-11-23 17:05:30 +0000915#elif defined (TARGET_PPC)
916static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
bellardbf3e8bf2004-02-16 21:58:54 +0000917 int is_write, sigset_t *old_set,
918 void *puc)
bellard67867302003-11-23 17:05:30 +0000919{
920 TranslationBlock *tb;
bellardce097762004-01-04 23:53:18 +0000921 int ret;
ths3b46e622007-09-17 08:09:54 +0000922
bellard67867302003-11-23 17:05:30 +0000923 if (cpu_single_env)
924 env = cpu_single_env; /* XXX: find a correct solution for multithread */
bellard67867302003-11-23 17:05:30 +0000925#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000926 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard67867302003-11-23 17:05:30 +0000927 pc, address, is_write, *(unsigned long *)old_set);
928#endif
929 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +0000930 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellard67867302003-11-23 17:05:30 +0000931 return 1;
932 }
933
bellardce097762004-01-04 23:53:18 +0000934 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000935 ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellardce097762004-01-04 23:53:18 +0000936 if (ret < 0)
937 return 0; /* not an MMU fault */
938 if (ret == 0)
939 return 1; /* the MMU fault was handled without causing real CPU fault */
940
bellard67867302003-11-23 17:05:30 +0000941 /* now we have a real cpu fault */
942 tb = tb_find_pc(pc);
943 if (tb) {
944 /* the PC is inside the translated code. It means that we have
945 a virtual CPU fault */
bellardbf3e8bf2004-02-16 21:58:54 +0000946 cpu_restore_state(tb, env, pc, puc);
bellard67867302003-11-23 17:05:30 +0000947 }
bellardce097762004-01-04 23:53:18 +0000948 if (ret == 1) {
bellard67867302003-11-23 17:05:30 +0000949#if 0
ths5fafdf22007-09-16 21:08:06 +0000950 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
bellardce097762004-01-04 23:53:18 +0000951 env->nip, env->error_code, tb);
bellard67867302003-11-23 17:05:30 +0000952#endif
953 /* we restore the process signal mask as the sigreturn should
954 do it (XXX: use sigsetjmp) */
bellardbf3e8bf2004-02-16 21:58:54 +0000955 sigprocmask(SIG_SETMASK, old_set, NULL);
aurel32e06fcd72008-12-11 22:42:14 +0000956 cpu_loop_exit();
bellardce097762004-01-04 23:53:18 +0000957 } else {
958 /* activate soft MMU for this block */
bellardfbf9eeb2004-04-25 21:21:33 +0000959 cpu_resume_from_signal(env, puc);
bellardce097762004-01-04 23:53:18 +0000960 }
bellard67867302003-11-23 17:05:30 +0000961 /* never comes here */
962 return 1;
963}
bellard6af0bf92005-07-02 14:58:51 +0000964
pbrooke6e59062006-10-22 00:18:54 +0000965#elif defined(TARGET_M68K)
966static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
967 int is_write, sigset_t *old_set,
968 void *puc)
969{
970 TranslationBlock *tb;
971 int ret;
972
973 if (cpu_single_env)
974 env = cpu_single_env; /* XXX: find a correct solution for multithread */
975#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +0000976 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
pbrooke6e59062006-10-22 00:18:54 +0000977 pc, address, is_write, *(unsigned long *)old_set);
978#endif
979 /* XXX: locking issue */
980 if (is_write && page_unprotect(address, pc, puc)) {
981 return 1;
982 }
983 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +0000984 ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
pbrooke6e59062006-10-22 00:18:54 +0000985 if (ret < 0)
986 return 0; /* not an MMU fault */
987 if (ret == 0)
988 return 1; /* the MMU fault was handled without causing real CPU fault */
989 /* now we have a real cpu fault */
990 tb = tb_find_pc(pc);
991 if (tb) {
992 /* the PC is inside the translated code. It means that we have
993 a virtual CPU fault */
994 cpu_restore_state(tb, env, pc, puc);
995 }
996 /* we restore the process signal mask as the sigreturn should
997 do it (XXX: use sigsetjmp) */
998 sigprocmask(SIG_SETMASK, old_set, NULL);
999 cpu_loop_exit();
1000 /* never comes here */
1001 return 1;
1002}
1003
bellard6af0bf92005-07-02 14:58:51 +00001004#elif defined (TARGET_MIPS)
1005static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1006 int is_write, sigset_t *old_set,
1007 void *puc)
1008{
1009 TranslationBlock *tb;
1010 int ret;
ths3b46e622007-09-17 08:09:54 +00001011
bellard6af0bf92005-07-02 14:58:51 +00001012 if (cpu_single_env)
1013 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1014#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001015 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellard6af0bf92005-07-02 14:58:51 +00001016 pc, address, is_write, *(unsigned long *)old_set);
1017#endif
1018 /* XXX: locking issue */
pbrook53a59602006-03-25 19:31:22 +00001019 if (is_write && page_unprotect(h2g(address), pc, puc)) {
bellard6af0bf92005-07-02 14:58:51 +00001020 return 1;
1021 }
1022
1023 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001024 ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellard6af0bf92005-07-02 14:58:51 +00001025 if (ret < 0)
1026 return 0; /* not an MMU fault */
1027 if (ret == 0)
1028 return 1; /* the MMU fault was handled without causing real CPU fault */
1029
1030 /* now we have a real cpu fault */
1031 tb = tb_find_pc(pc);
1032 if (tb) {
1033 /* the PC is inside the translated code. It means that we have
1034 a virtual CPU fault */
1035 cpu_restore_state(tb, env, pc, puc);
1036 }
1037 if (ret == 1) {
1038#if 0
ths5fafdf22007-09-16 21:08:06 +00001039 printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
ths1eb52072007-05-12 16:57:42 +00001040 env->PC, env->error_code, tb);
bellard6af0bf92005-07-02 14:58:51 +00001041#endif
1042 /* we restore the process signal mask as the sigreturn should
1043 do it (XXX: use sigsetjmp) */
1044 sigprocmask(SIG_SETMASK, old_set, NULL);
thsf9480ff2008-12-20 19:42:14 +00001045 cpu_loop_exit();
bellard6af0bf92005-07-02 14:58:51 +00001046 } else {
1047 /* activate soft MMU for this block */
1048 cpu_resume_from_signal(env, puc);
1049 }
1050 /* never comes here */
1051 return 1;
1052}
1053
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02001054#elif defined (TARGET_MICROBLAZE)
1055static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1056 int is_write, sigset_t *old_set,
1057 void *puc)
1058{
1059 TranslationBlock *tb;
1060 int ret;
1061
1062 if (cpu_single_env)
1063 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1064#if defined(DEBUG_SIGNAL)
1065 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1066 pc, address, is_write, *(unsigned long *)old_set);
1067#endif
1068 /* XXX: locking issue */
1069 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1070 return 1;
1071 }
1072
1073 /* see if it is an MMU fault */
1074 ret = cpu_mb_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1075 if (ret < 0)
1076 return 0; /* not an MMU fault */
1077 if (ret == 0)
1078 return 1; /* the MMU fault was handled without causing real CPU fault */
1079
1080 /* now we have a real cpu fault */
1081 tb = tb_find_pc(pc);
1082 if (tb) {
1083 /* the PC is inside the translated code. It means that we have
1084 a virtual CPU fault */
1085 cpu_restore_state(tb, env, pc, puc);
1086 }
1087 if (ret == 1) {
1088#if 0
1089 printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1090 env->PC, env->error_code, tb);
1091#endif
1092 /* we restore the process signal mask as the sigreturn should
1093 do it (XXX: use sigsetjmp) */
1094 sigprocmask(SIG_SETMASK, old_set, NULL);
1095 cpu_loop_exit();
1096 } else {
1097 /* activate soft MMU for this block */
1098 cpu_resume_from_signal(env, puc);
1099 }
1100 /* never comes here */
1101 return 1;
1102}
1103
bellardfdf9b3e2006-04-27 21:07:38 +00001104#elif defined (TARGET_SH4)
1105static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1106 int is_write, sigset_t *old_set,
1107 void *puc)
1108{
1109 TranslationBlock *tb;
1110 int ret;
ths3b46e622007-09-17 08:09:54 +00001111
bellardfdf9b3e2006-04-27 21:07:38 +00001112 if (cpu_single_env)
1113 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1114#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001115 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
bellardfdf9b3e2006-04-27 21:07:38 +00001116 pc, address, is_write, *(unsigned long *)old_set);
1117#endif
1118 /* XXX: locking issue */
1119 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1120 return 1;
1121 }
1122
1123 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001124 ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
bellardfdf9b3e2006-04-27 21:07:38 +00001125 if (ret < 0)
1126 return 0; /* not an MMU fault */
1127 if (ret == 0)
1128 return 1; /* the MMU fault was handled without causing real CPU fault */
1129
1130 /* now we have a real cpu fault */
1131 tb = tb_find_pc(pc);
1132 if (tb) {
1133 /* the PC is inside the translated code. It means that we have
1134 a virtual CPU fault */
1135 cpu_restore_state(tb, env, pc, puc);
1136 }
bellardfdf9b3e2006-04-27 21:07:38 +00001137#if 0
ths5fafdf22007-09-16 21:08:06 +00001138 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
bellardfdf9b3e2006-04-27 21:07:38 +00001139 env->nip, env->error_code, tb);
1140#endif
1141 /* we restore the process signal mask as the sigreturn should
1142 do it (XXX: use sigsetjmp) */
pbrook355fb232006-06-17 19:58:25 +00001143 sigprocmask(SIG_SETMASK, old_set, NULL);
1144 cpu_loop_exit();
bellardfdf9b3e2006-04-27 21:07:38 +00001145 /* never comes here */
1146 return 1;
1147}
j_mayereddf68a2007-04-05 07:22:49 +00001148
1149#elif defined (TARGET_ALPHA)
1150static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1151 int is_write, sigset_t *old_set,
1152 void *puc)
1153{
1154 TranslationBlock *tb;
1155 int ret;
ths3b46e622007-09-17 08:09:54 +00001156
j_mayereddf68a2007-04-05 07:22:49 +00001157 if (cpu_single_env)
1158 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1159#if defined(DEBUG_SIGNAL)
ths5fafdf22007-09-16 21:08:06 +00001160 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
j_mayereddf68a2007-04-05 07:22:49 +00001161 pc, address, is_write, *(unsigned long *)old_set);
1162#endif
1163 /* XXX: locking issue */
1164 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1165 return 1;
1166 }
1167
1168 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001169 ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
j_mayereddf68a2007-04-05 07:22:49 +00001170 if (ret < 0)
1171 return 0; /* not an MMU fault */
1172 if (ret == 0)
1173 return 1; /* the MMU fault was handled without causing real CPU fault */
1174
1175 /* now we have a real cpu fault */
1176 tb = tb_find_pc(pc);
1177 if (tb) {
1178 /* the PC is inside the translated code. It means that we have
1179 a virtual CPU fault */
1180 cpu_restore_state(tb, env, pc, puc);
1181 }
1182#if 0
ths5fafdf22007-09-16 21:08:06 +00001183 printf("PF exception: NIP=0x%08x error=0x%x %p\n",
j_mayereddf68a2007-04-05 07:22:49 +00001184 env->nip, env->error_code, tb);
1185#endif
1186 /* we restore the process signal mask as the sigreturn should
1187 do it (XXX: use sigsetjmp) */
1188 sigprocmask(SIG_SETMASK, old_set, NULL);
1189 cpu_loop_exit();
1190 /* never comes here */
1191 return 1;
1192}
thsf1ccf902007-10-08 13:16:14 +00001193#elif defined (TARGET_CRIS)
1194static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1195 int is_write, sigset_t *old_set,
1196 void *puc)
1197{
1198 TranslationBlock *tb;
1199 int ret;
1200
1201 if (cpu_single_env)
1202 env = cpu_single_env; /* XXX: find a correct solution for multithread */
1203#if defined(DEBUG_SIGNAL)
1204 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1205 pc, address, is_write, *(unsigned long *)old_set);
1206#endif
1207 /* XXX: locking issue */
1208 if (is_write && page_unprotect(h2g(address), pc, puc)) {
1209 return 1;
1210 }
1211
1212 /* see if it is an MMU fault */
j_mayer6ebbf392007-10-14 07:07:08 +00001213 ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
thsf1ccf902007-10-08 13:16:14 +00001214 if (ret < 0)
1215 return 0; /* not an MMU fault */
1216 if (ret == 0)
1217 return 1; /* the MMU fault was handled without causing real CPU fault */
1218
1219 /* now we have a real cpu fault */
1220 tb = tb_find_pc(pc);
1221 if (tb) {
1222 /* the PC is inside the translated code. It means that we have
1223 a virtual CPU fault */
1224 cpu_restore_state(tb, env, pc, puc);
1225 }
thsf1ccf902007-10-08 13:16:14 +00001226 /* we restore the process signal mask as the sigreturn should
1227 do it (XXX: use sigsetjmp) */
1228 sigprocmask(SIG_SETMASK, old_set, NULL);
1229 cpu_loop_exit();
1230 /* never comes here */
1231 return 1;
1232}
1233
bellarde4533c72003-06-15 19:51:39 +00001234#else
1235#error unsupported target CPU
1236#endif
bellard9de5e442003-03-23 16:49:39 +00001237
bellard2b413142003-05-14 23:01:10 +00001238#if defined(__i386__)
1239
bellardd8ecc0b2007-02-05 21:41:46 +00001240#if defined(__APPLE__)
1241# include <sys/ucontext.h>
1242
1243# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1244# define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
1245# define ERROR_sig(context) ((context)->uc_mcontext->es.err)
blueswir1d39bb242009-04-10 07:29:34 +00001246# define MASK_sig(context) ((context)->uc_sigmask)
1247#elif defined(__OpenBSD__)
1248# define EIP_sig(context) ((context)->sc_eip)
1249# define TRAP_sig(context) ((context)->sc_trapno)
1250# define ERROR_sig(context) ((context)->sc_err)
1251# define MASK_sig(context) ((context)->sc_mask)
bellardd8ecc0b2007-02-05 21:41:46 +00001252#else
1253# define EIP_sig(context) ((context)->uc_mcontext.gregs[REG_EIP])
1254# define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
1255# define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
blueswir1d39bb242009-04-10 07:29:34 +00001256# define MASK_sig(context) ((context)->uc_sigmask)
bellardd8ecc0b2007-02-05 21:41:46 +00001257#endif
1258
ths5fafdf22007-09-16 21:08:06 +00001259int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001260 void *puc)
bellard9de5e442003-03-23 16:49:39 +00001261{
ths5a7b5422007-01-31 12:16:51 +00001262 siginfo_t *info = pinfo;
blueswir1d39bb242009-04-10 07:29:34 +00001263#if defined(__OpenBSD__)
1264 struct sigcontext *uc = puc;
1265#else
bellard9de5e442003-03-23 16:49:39 +00001266 struct ucontext *uc = puc;
blueswir1d39bb242009-04-10 07:29:34 +00001267#endif
bellard9de5e442003-03-23 16:49:39 +00001268 unsigned long pc;
bellardbf3e8bf2004-02-16 21:58:54 +00001269 int trapno;
bellard97eb5b12004-02-25 23:19:55 +00001270
bellardd691f662003-03-24 21:58:34 +00001271#ifndef REG_EIP
1272/* for glibc 2.1 */
bellardfd6ce8f2003-05-14 19:00:11 +00001273#define REG_EIP EIP
1274#define REG_ERR ERR
1275#define REG_TRAPNO TRAPNO
bellardd691f662003-03-24 21:58:34 +00001276#endif
bellardd8ecc0b2007-02-05 21:41:46 +00001277 pc = EIP_sig(uc);
1278 trapno = TRAP_sig(uc);
bellardec6338b2007-11-08 14:25:03 +00001279 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1280 trapno == 0xe ?
1281 (ERROR_sig(uc) >> 1) & 1 : 0,
blueswir1d39bb242009-04-10 07:29:34 +00001282 &MASK_sig(uc), puc);
bellard2b413142003-05-14 23:01:10 +00001283}
1284
bellardbc51c5c2004-03-17 23:46:04 +00001285#elif defined(__x86_64__)
1286
blueswir1b3efe5c2008-12-05 17:55:45 +00001287#ifdef __NetBSD__
blueswir1d397abb2009-04-10 13:00:29 +00001288#define PC_sig(context) _UC_MACHINE_PC(context)
1289#define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
1290#define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
1291#define MASK_sig(context) ((context)->uc_sigmask)
1292#elif defined(__OpenBSD__)
1293#define PC_sig(context) ((context)->sc_rip)
1294#define TRAP_sig(context) ((context)->sc_trapno)
1295#define ERROR_sig(context) ((context)->sc_err)
1296#define MASK_sig(context) ((context)->sc_mask)
blueswir1b3efe5c2008-12-05 17:55:45 +00001297#else
blueswir1d397abb2009-04-10 13:00:29 +00001298#define PC_sig(context) ((context)->uc_mcontext.gregs[REG_RIP])
1299#define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
1300#define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
1301#define MASK_sig(context) ((context)->uc_sigmask)
blueswir1b3efe5c2008-12-05 17:55:45 +00001302#endif
1303
ths5a7b5422007-01-31 12:16:51 +00001304int cpu_signal_handler(int host_signum, void *pinfo,
bellardbc51c5c2004-03-17 23:46:04 +00001305 void *puc)
1306{
ths5a7b5422007-01-31 12:16:51 +00001307 siginfo_t *info = pinfo;
bellardbc51c5c2004-03-17 23:46:04 +00001308 unsigned long pc;
blueswir1b3efe5c2008-12-05 17:55:45 +00001309#ifdef __NetBSD__
1310 ucontext_t *uc = puc;
blueswir1d397abb2009-04-10 13:00:29 +00001311#elif defined(__OpenBSD__)
1312 struct sigcontext *uc = puc;
blueswir1b3efe5c2008-12-05 17:55:45 +00001313#else
1314 struct ucontext *uc = puc;
1315#endif
bellardbc51c5c2004-03-17 23:46:04 +00001316
blueswir1d397abb2009-04-10 13:00:29 +00001317 pc = PC_sig(uc);
ths5fafdf22007-09-16 21:08:06 +00001318 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
blueswir1d397abb2009-04-10 13:00:29 +00001319 TRAP_sig(uc) == 0xe ?
1320 (ERROR_sig(uc) >> 1) & 1 : 0,
1321 &MASK_sig(uc), puc);
bellardbc51c5c2004-03-17 23:46:04 +00001322}
1323
malce58ffeb2009-01-14 18:39:49 +00001324#elif defined(_ARCH_PPC)
bellard2b413142003-05-14 23:01:10 +00001325
bellard83fb7ad2004-07-05 21:25:26 +00001326/***********************************************************************
1327 * signal context platform-specific definitions
1328 * From Wine
1329 */
1330#ifdef linux
1331/* All Registers access - only for local access */
1332# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
1333/* Gpr Registers access */
1334# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
1335# define IAR_sig(context) REG_sig(nip, context) /* Program counter */
1336# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
1337# define CTR_sig(context) REG_sig(ctr, context) /* Count register */
1338# define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
1339# define LR_sig(context) REG_sig(link, context) /* Link register */
1340# define CR_sig(context) REG_sig(ccr, context) /* Condition register */
1341/* Float Registers access */
1342# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1343# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1344/* Exception Registers access */
1345# define DAR_sig(context) REG_sig(dar, context)
1346# define DSISR_sig(context) REG_sig(dsisr, context)
1347# define TRAP_sig(context) REG_sig(trap, context)
1348#endif /* linux */
1349
1350#ifdef __APPLE__
1351# include <sys/ucontext.h>
1352typedef struct ucontext SIGCONTEXT;
1353/* All Registers access - only for local access */
1354# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
1355# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
1356# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
1357# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
1358/* Gpr Registers access */
1359# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
1360# define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
1361# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
1362# define CTR_sig(context) REG_sig(ctr, context)
1363# define XER_sig(context) REG_sig(xer, context) /* Link register */
1364# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
1365# define CR_sig(context) REG_sig(cr, context) /* Condition register */
1366/* Float Registers access */
1367# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
1368# define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
1369/* Exception Registers access */
1370# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
1371# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
1372# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1373#endif /* __APPLE__ */
1374
ths5fafdf22007-09-16 21:08:06 +00001375int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001376 void *puc)
bellard2b413142003-05-14 23:01:10 +00001377{
ths5a7b5422007-01-31 12:16:51 +00001378 siginfo_t *info = pinfo;
bellard25eb4482003-05-14 21:50:54 +00001379 struct ucontext *uc = puc;
bellard25eb4482003-05-14 21:50:54 +00001380 unsigned long pc;
bellard25eb4482003-05-14 21:50:54 +00001381 int is_write;
1382
bellard83fb7ad2004-07-05 21:25:26 +00001383 pc = IAR_sig(uc);
bellard25eb4482003-05-14 21:50:54 +00001384 is_write = 0;
1385#if 0
1386 /* ppc 4xx case */
bellard83fb7ad2004-07-05 21:25:26 +00001387 if (DSISR_sig(uc) & 0x00800000)
bellard25eb4482003-05-14 21:50:54 +00001388 is_write = 1;
bellard9de5e442003-03-23 16:49:39 +00001389#else
bellard83fb7ad2004-07-05 21:25:26 +00001390 if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
bellard25eb4482003-05-14 21:50:54 +00001391 is_write = 1;
1392#endif
ths5fafdf22007-09-16 21:08:06 +00001393 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001394 is_write, &uc->uc_sigmask, puc);
bellard9de5e442003-03-23 16:49:39 +00001395}
bellard2b413142003-05-14 23:01:10 +00001396
bellard2f87c602003-06-02 20:38:09 +00001397#elif defined(__alpha__)
1398
ths5fafdf22007-09-16 21:08:06 +00001399int cpu_signal_handler(int host_signum, void *pinfo,
bellard2f87c602003-06-02 20:38:09 +00001400 void *puc)
1401{
ths5a7b5422007-01-31 12:16:51 +00001402 siginfo_t *info = pinfo;
bellard2f87c602003-06-02 20:38:09 +00001403 struct ucontext *uc = puc;
1404 uint32_t *pc = uc->uc_mcontext.sc_pc;
1405 uint32_t insn = *pc;
1406 int is_write = 0;
1407
bellard8c6939c2003-06-09 15:28:00 +00001408 /* XXX: need kernel patch to get write flag faster */
bellard2f87c602003-06-02 20:38:09 +00001409 switch (insn >> 26) {
1410 case 0x0d: // stw
1411 case 0x0e: // stb
1412 case 0x0f: // stq_u
1413 case 0x24: // stf
1414 case 0x25: // stg
1415 case 0x26: // sts
1416 case 0x27: // stt
1417 case 0x2c: // stl
1418 case 0x2d: // stq
1419 case 0x2e: // stl_c
1420 case 0x2f: // stq_c
1421 is_write = 1;
1422 }
1423
ths5fafdf22007-09-16 21:08:06 +00001424 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001425 is_write, &uc->uc_sigmask, puc);
bellard2f87c602003-06-02 20:38:09 +00001426}
bellard8c6939c2003-06-09 15:28:00 +00001427#elif defined(__sparc__)
1428
ths5fafdf22007-09-16 21:08:06 +00001429int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001430 void *puc)
bellard8c6939c2003-06-09 15:28:00 +00001431{
ths5a7b5422007-01-31 12:16:51 +00001432 siginfo_t *info = pinfo;
bellard8c6939c2003-06-09 15:28:00 +00001433 int is_write;
1434 uint32_t insn;
Juan Quinteladfe5fff2009-07-27 16:12:40 +02001435#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
blueswir1c9e1e2b2008-05-18 06:40:16 +00001436 uint32_t *regs = (uint32_t *)(info + 1);
1437 void *sigmask = (regs + 20);
bellard8c6939c2003-06-09 15:28:00 +00001438 /* XXX: is there a standard glibc define ? */
blueswir1c9e1e2b2008-05-18 06:40:16 +00001439 unsigned long pc = regs[1];
1440#else
blueswir184778502008-10-26 20:33:16 +00001441#ifdef __linux__
blueswir1c9e1e2b2008-05-18 06:40:16 +00001442 struct sigcontext *sc = puc;
1443 unsigned long pc = sc->sigc_regs.tpc;
1444 void *sigmask = (void *)sc->sigc_mask;
blueswir184778502008-10-26 20:33:16 +00001445#elif defined(__OpenBSD__)
1446 struct sigcontext *uc = puc;
1447 unsigned long pc = uc->sc_pc;
1448 void *sigmask = (void *)(long)uc->sc_mask;
1449#endif
blueswir1c9e1e2b2008-05-18 06:40:16 +00001450#endif
1451
bellard8c6939c2003-06-09 15:28:00 +00001452 /* XXX: need kernel patch to get write flag faster */
1453 is_write = 0;
1454 insn = *(uint32_t *)pc;
1455 if ((insn >> 30) == 3) {
1456 switch((insn >> 19) & 0x3f) {
1457 case 0x05: // stb
Blue Swirld877fa52009-04-25 19:07:16 +00001458 case 0x15: // stba
bellard8c6939c2003-06-09 15:28:00 +00001459 case 0x06: // sth
Blue Swirld877fa52009-04-25 19:07:16 +00001460 case 0x16: // stha
bellard8c6939c2003-06-09 15:28:00 +00001461 case 0x04: // st
Blue Swirld877fa52009-04-25 19:07:16 +00001462 case 0x14: // sta
bellard8c6939c2003-06-09 15:28:00 +00001463 case 0x07: // std
Blue Swirld877fa52009-04-25 19:07:16 +00001464 case 0x17: // stda
1465 case 0x0e: // stx
1466 case 0x1e: // stxa
bellard8c6939c2003-06-09 15:28:00 +00001467 case 0x24: // stf
Blue Swirld877fa52009-04-25 19:07:16 +00001468 case 0x34: // stfa
bellard8c6939c2003-06-09 15:28:00 +00001469 case 0x27: // stdf
Blue Swirld877fa52009-04-25 19:07:16 +00001470 case 0x37: // stdfa
1471 case 0x26: // stqf
1472 case 0x36: // stqfa
bellard8c6939c2003-06-09 15:28:00 +00001473 case 0x25: // stfsr
Blue Swirld877fa52009-04-25 19:07:16 +00001474 case 0x3c: // casa
1475 case 0x3e: // casxa
bellard8c6939c2003-06-09 15:28:00 +00001476 is_write = 1;
1477 break;
1478 }
1479 }
ths5fafdf22007-09-16 21:08:06 +00001480 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellardbf3e8bf2004-02-16 21:58:54 +00001481 is_write, sigmask, NULL);
bellard8c6939c2003-06-09 15:28:00 +00001482}
1483
1484#elif defined(__arm__)
1485
ths5fafdf22007-09-16 21:08:06 +00001486int cpu_signal_handler(int host_signum, void *pinfo,
bellarde4533c72003-06-15 19:51:39 +00001487 void *puc)
bellard8c6939c2003-06-09 15:28:00 +00001488{
ths5a7b5422007-01-31 12:16:51 +00001489 siginfo_t *info = pinfo;
bellard8c6939c2003-06-09 15:28:00 +00001490 struct ucontext *uc = puc;
1491 unsigned long pc;
1492 int is_write;
ths3b46e622007-09-17 08:09:54 +00001493
blueswir148bbf112008-07-08 18:35:02 +00001494#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
balrog5c49b362008-06-02 01:01:18 +00001495 pc = uc->uc_mcontext.gregs[R15];
1496#else
balrog4eee57f2008-05-06 14:47:19 +00001497 pc = uc->uc_mcontext.arm_pc;
balrog5c49b362008-06-02 01:01:18 +00001498#endif
bellard8c6939c2003-06-09 15:28:00 +00001499 /* XXX: compute is_write */
1500 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001501 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellard8c6939c2003-06-09 15:28:00 +00001502 is_write,
pbrookf3a96762006-07-29 19:09:31 +00001503 &uc->uc_sigmask, puc);
bellard8c6939c2003-06-09 15:28:00 +00001504}
1505
bellard38e584a2003-08-10 22:14:22 +00001506#elif defined(__mc68000)
1507
ths5fafdf22007-09-16 21:08:06 +00001508int cpu_signal_handler(int host_signum, void *pinfo,
bellard38e584a2003-08-10 22:14:22 +00001509 void *puc)
1510{
ths5a7b5422007-01-31 12:16:51 +00001511 siginfo_t *info = pinfo;
bellard38e584a2003-08-10 22:14:22 +00001512 struct ucontext *uc = puc;
1513 unsigned long pc;
1514 int is_write;
ths3b46e622007-09-17 08:09:54 +00001515
bellard38e584a2003-08-10 22:14:22 +00001516 pc = uc->uc_mcontext.gregs[16];
1517 /* XXX: compute is_write */
1518 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001519 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
bellard38e584a2003-08-10 22:14:22 +00001520 is_write,
bellardbf3e8bf2004-02-16 21:58:54 +00001521 &uc->uc_sigmask, puc);
bellard38e584a2003-08-10 22:14:22 +00001522}
1523
bellardb8076a72005-04-07 22:20:31 +00001524#elif defined(__ia64)
1525
1526#ifndef __ISR_VALID
1527 /* This ought to be in <bits/siginfo.h>... */
1528# define __ISR_VALID 1
bellardb8076a72005-04-07 22:20:31 +00001529#endif
1530
ths5a7b5422007-01-31 12:16:51 +00001531int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
bellardb8076a72005-04-07 22:20:31 +00001532{
ths5a7b5422007-01-31 12:16:51 +00001533 siginfo_t *info = pinfo;
bellardb8076a72005-04-07 22:20:31 +00001534 struct ucontext *uc = puc;
1535 unsigned long ip;
1536 int is_write = 0;
1537
1538 ip = uc->uc_mcontext.sc_ip;
1539 switch (host_signum) {
1540 case SIGILL:
1541 case SIGFPE:
1542 case SIGSEGV:
1543 case SIGBUS:
1544 case SIGTRAP:
bellardfd4a43e2006-04-24 20:32:17 +00001545 if (info->si_code && (info->si_segvflags & __ISR_VALID))
bellardb8076a72005-04-07 22:20:31 +00001546 /* ISR.W (write-access) is bit 33: */
1547 is_write = (info->si_isr >> 33) & 1;
1548 break;
1549
1550 default:
1551 break;
1552 }
1553 return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1554 is_write,
1555 &uc->uc_sigmask, puc);
1556}
1557
bellard90cb9492005-07-24 15:11:38 +00001558#elif defined(__s390__)
1559
ths5fafdf22007-09-16 21:08:06 +00001560int cpu_signal_handler(int host_signum, void *pinfo,
bellard90cb9492005-07-24 15:11:38 +00001561 void *puc)
1562{
ths5a7b5422007-01-31 12:16:51 +00001563 siginfo_t *info = pinfo;
bellard90cb9492005-07-24 15:11:38 +00001564 struct ucontext *uc = puc;
1565 unsigned long pc;
1566 int is_write;
ths3b46e622007-09-17 08:09:54 +00001567
bellard90cb9492005-07-24 15:11:38 +00001568 pc = uc->uc_mcontext.psw.addr;
1569 /* XXX: compute is_write */
1570 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001571 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
thsc4b89d12007-05-05 19:23:11 +00001572 is_write, &uc->uc_sigmask, puc);
1573}
1574
1575#elif defined(__mips__)
1576
ths5fafdf22007-09-16 21:08:06 +00001577int cpu_signal_handler(int host_signum, void *pinfo,
thsc4b89d12007-05-05 19:23:11 +00001578 void *puc)
1579{
ths9617efe2007-05-08 21:05:55 +00001580 siginfo_t *info = pinfo;
thsc4b89d12007-05-05 19:23:11 +00001581 struct ucontext *uc = puc;
1582 greg_t pc = uc->uc_mcontext.pc;
1583 int is_write;
ths3b46e622007-09-17 08:09:54 +00001584
thsc4b89d12007-05-05 19:23:11 +00001585 /* XXX: compute is_write */
1586 is_write = 0;
ths5fafdf22007-09-16 21:08:06 +00001587 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
thsc4b89d12007-05-05 19:23:11 +00001588 is_write, &uc->uc_sigmask, puc);
bellard90cb9492005-07-24 15:11:38 +00001589}
1590
aurel32f54b3f92008-04-12 20:14:54 +00001591#elif defined(__hppa__)
1592
1593int cpu_signal_handler(int host_signum, void *pinfo,
1594 void *puc)
1595{
1596 struct siginfo *info = pinfo;
1597 struct ucontext *uc = puc;
1598 unsigned long pc;
1599 int is_write;
1600
1601 pc = uc->uc_mcontext.sc_iaoq[0];
1602 /* FIXME: compute is_write */
1603 is_write = 0;
1604 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1605 is_write,
1606 &uc->uc_sigmask, puc);
1607}
1608
bellard2b413142003-05-14 23:01:10 +00001609#else
1610
bellard3fb2ded2003-06-24 13:22:59 +00001611#error host CPU specific signal handler needed
bellard2b413142003-05-14 23:01:10 +00001612
1613#endif
bellard67b915a2004-03-31 23:37:16 +00001614
1615#endif /* !defined(CONFIG_SOFTMMU) */