blob: e1de56b397784f1b1add3f31e7455743d7dc15ed [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"
Jan Kiszka1d93f0f2010-06-25 16:56:49 +020024#include "qemu-barrier.h"
bellard7d132992003-03-06 23:23:54 +000025
Juan Quinteladfe5fff2009-07-27 16:12:40 +020026#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
blueswir1572a9d42008-05-17 07:38:10 +000027// Work around ugly bugs in glibc that mangle global register contents
28#undef env
29#define env cpu_single_env
30#endif
31
bellard36bdbe52003-11-19 22:12:02 +000032int tb_invalidated_flag;
33
Juan Quintelaf0667e62009-07-27 16:13:05 +020034//#define CONFIG_DEBUG_EXEC
bellard7d132992003-03-06 23:23:54 +000035
aliguori6a4955a2009-04-24 18:03:20 +000036int qemu_cpu_has_work(CPUState *env)
37{
38 return cpu_has_work(env);
39}
40
bellarde4533c72003-06-15 19:51:39 +000041void cpu_loop_exit(void)
42{
Paolo Bonzini1c3569f2010-01-15 09:42:07 +010043 env->current_tb = NULL;
bellarde4533c72003-06-15 19:51:39 +000044 longjmp(env->jmp_env, 1);
45}
thsbfed01f2007-06-03 17:44:37 +000046
bellardfbf9eeb2004-04-25 21:21:33 +000047/* exit the current TB from a signal handler. The host registers are
48 restored in a state compatible with the CPU emulator
49 */
Blue Swirl9eff14f2011-05-21 08:42:35 +000050#if defined(CONFIG_SOFTMMU)
ths5fafdf22007-09-16 21:08:06 +000051void cpu_resume_from_signal(CPUState *env1, void *puc)
bellardfbf9eeb2004-04-25 21:21:33 +000052{
Blue Swirl9eff14f2011-05-21 08:42:35 +000053 env = env1;
54
55 /* XXX: restore cpu registers saved in host registers */
56
57 env->exception_index = -1;
58 longjmp(env->jmp_env, 1);
59}
Blue Swirl9eff14f2011-05-21 08:42:35 +000060#endif
bellardfbf9eeb2004-04-25 21:21:33 +000061
pbrook2e70f6e2008-06-29 01:03:05 +000062/* Execute the code without caching the generated code. An interpreter
63 could be used if available. */
64static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
65{
66 unsigned long next_tb;
67 TranslationBlock *tb;
68
69 /* Should never happen.
70 We only end up here when an existing TB is too long. */
71 if (max_cycles > CF_COUNT_MASK)
72 max_cycles = CF_COUNT_MASK;
73
74 tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
75 max_cycles);
76 env->current_tb = tb;
77 /* execute the generated code */
78 next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
Paolo Bonzini1c3569f2010-01-15 09:42:07 +010079 env->current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +000080
81 if ((next_tb & 3) == 2) {
82 /* Restore PC. This may happen if async event occurs before
83 the TB starts executing. */
aliguori622ed362008-11-18 19:36:03 +000084 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +000085 }
86 tb_phys_invalidate(tb, -1);
87 tb_free(tb);
88}
89
bellard8a40a182005-11-20 10:35:40 +000090static TranslationBlock *tb_find_slow(target_ulong pc,
91 target_ulong cs_base,
j_mayerc0686882007-09-20 22:47:42 +000092 uint64_t flags)
bellard8a40a182005-11-20 10:35:40 +000093{
94 TranslationBlock *tb, **ptb1;
bellard8a40a182005-11-20 10:35:40 +000095 unsigned int h;
Paul Brook41c1b1c2010-03-12 16:54:58 +000096 tb_page_addr_t phys_pc, phys_page1, phys_page2;
97 target_ulong virt_page2;
ths3b46e622007-09-17 08:09:54 +000098
bellard8a40a182005-11-20 10:35:40 +000099 tb_invalidated_flag = 0;
ths3b46e622007-09-17 08:09:54 +0000100
bellard8a40a182005-11-20 10:35:40 +0000101 /* find translated block using physical mappings */
Paul Brook41c1b1c2010-03-12 16:54:58 +0000102 phys_pc = get_page_addr_code(env, pc);
bellard8a40a182005-11-20 10:35:40 +0000103 phys_page1 = phys_pc & TARGET_PAGE_MASK;
104 phys_page2 = -1;
105 h = tb_phys_hash_func(phys_pc);
106 ptb1 = &tb_phys_hash[h];
107 for(;;) {
108 tb = *ptb1;
109 if (!tb)
110 goto not_found;
ths5fafdf22007-09-16 21:08:06 +0000111 if (tb->pc == pc &&
bellard8a40a182005-11-20 10:35:40 +0000112 tb->page_addr[0] == phys_page1 &&
ths5fafdf22007-09-16 21:08:06 +0000113 tb->cs_base == cs_base &&
bellard8a40a182005-11-20 10:35:40 +0000114 tb->flags == flags) {
115 /* check next page if needed */
116 if (tb->page_addr[1] != -1) {
ths5fafdf22007-09-16 21:08:06 +0000117 virt_page2 = (pc & TARGET_PAGE_MASK) +
bellard8a40a182005-11-20 10:35:40 +0000118 TARGET_PAGE_SIZE;
Paul Brook41c1b1c2010-03-12 16:54:58 +0000119 phys_page2 = get_page_addr_code(env, virt_page2);
bellard8a40a182005-11-20 10:35:40 +0000120 if (tb->page_addr[1] == phys_page2)
121 goto found;
122 } else {
123 goto found;
124 }
125 }
126 ptb1 = &tb->phys_hash_next;
127 }
128 not_found:
pbrook2e70f6e2008-06-29 01:03:05 +0000129 /* if no translated code available, then translate it now */
130 tb = tb_gen_code(env, pc, cs_base, flags, 0);
ths3b46e622007-09-17 08:09:54 +0000131
bellard8a40a182005-11-20 10:35:40 +0000132 found:
Kirill Batuzov2c90fe22010-12-02 16:12:46 +0300133 /* Move the last found TB to the head of the list */
134 if (likely(*ptb1)) {
135 *ptb1 = tb->phys_hash_next;
136 tb->phys_hash_next = tb_phys_hash[h];
137 tb_phys_hash[h] = tb;
138 }
bellard8a40a182005-11-20 10:35:40 +0000139 /* we add the TB in the virtual pc hash table */
140 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
bellard8a40a182005-11-20 10:35:40 +0000141 return tb;
142}
143
144static inline TranslationBlock *tb_find_fast(void)
145{
146 TranslationBlock *tb;
147 target_ulong cs_base, pc;
aliguori6b917542008-11-18 19:46:41 +0000148 int flags;
bellard8a40a182005-11-20 10:35:40 +0000149
150 /* we record a subset of the CPU state. It will
151 always be the same before a given translated block
152 is executed. */
aliguori6b917542008-11-18 19:46:41 +0000153 cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
bellardbce61842008-02-01 22:18:51 +0000154 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
ths551bd272008-07-03 17:57:36 +0000155 if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
156 tb->flags != flags)) {
bellard8a40a182005-11-20 10:35:40 +0000157 tb = tb_find_slow(pc, cs_base, flags);
158 }
159 return tb;
160}
161
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100162static CPUDebugExcpHandler *debug_excp_handler;
163
164CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
165{
166 CPUDebugExcpHandler *old_handler = debug_excp_handler;
167
168 debug_excp_handler = handler;
169 return old_handler;
170}
171
172static void cpu_handle_debug_exception(CPUState *env)
173{
174 CPUWatchpoint *wp;
175
176 if (!env->watchpoint_hit) {
177 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
178 wp->flags &= ~BP_WATCHPOINT_HIT;
179 }
180 }
181 if (debug_excp_handler) {
182 debug_excp_handler(env);
183 }
184}
185
bellard7d132992003-03-06 23:23:54 +0000186/* main execution loop */
187
Marcelo Tosatti1a28cac2010-05-04 09:45:20 -0300188volatile sig_atomic_t exit_request;
189
bellarde4533c72003-06-15 19:51:39 +0000190int cpu_exec(CPUState *env1)
bellard7d132992003-03-06 23:23:54 +0000191{
Paolo Bonzini1d9000e2010-02-23 19:21:00 +0100192 volatile host_reg_t saved_env_reg;
bellard8a40a182005-11-20 10:35:40 +0000193 int ret, interrupt_request;
bellard8a40a182005-11-20 10:35:40 +0000194 TranslationBlock *tb;
bellardc27004e2005-01-03 23:35:10 +0000195 uint8_t *tc_ptr;
pbrookd5975362008-06-07 20:50:51 +0000196 unsigned long next_tb;
bellard8c6939c2003-06-09 15:28:00 +0000197
Paolo Bonzinieda48c32011-03-12 17:43:56 +0100198 if (env1->halted) {
199 if (!cpu_has_work(env1)) {
200 return EXCP_HALTED;
201 }
202
203 env1->halted = 0;
204 }
bellard5a1e3cf2005-11-23 21:02:53 +0000205
ths5fafdf22007-09-16 21:08:06 +0000206 cpu_single_env = env1;
bellard6a00d602005-11-21 23:25:50 +0000207
Paolo Bonzini24ebf5f2010-02-18 21:25:23 +0100208 /* the access to env below is actually saving the global register's
209 value, so that files not including target-xyz/exec.h are free to
210 use it. */
211 QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
212 saved_env_reg = (host_reg_t) env;
Jan Kiszka1d93f0f2010-06-25 16:56:49 +0200213 barrier();
bellardc27004e2005-01-03 23:35:10 +0000214 env = env1;
bellarde4533c72003-06-15 19:51:39 +0000215
Jan Kiszkac629a4b2010-06-25 16:56:52 +0200216 if (unlikely(exit_request)) {
Marcelo Tosatti1a28cac2010-05-04 09:45:20 -0300217 env->exit_request = 1;
Marcelo Tosatti1a28cac2010-05-04 09:45:20 -0300218 }
219
thsecb644f2007-06-03 18:45:53 +0000220#if defined(TARGET_I386)
Jan Kiszka6792a572011-02-07 12:19:18 +0100221 /* put eflags in CPU temporary format */
222 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
223 DF = 1 - (2 * ((env->eflags >> 10) & 1));
224 CC_OP = CC_OP_EFLAGS;
225 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellard93ac68b2003-09-30 20:57:29 +0000226#elif defined(TARGET_SPARC)
pbrooke6e59062006-10-22 00:18:54 +0000227#elif defined(TARGET_M68K)
228 env->cc_op = CC_OP_FLAGS;
229 env->cc_dest = env->sr & 0xf;
230 env->cc_x = (env->sr >> 4) & 1;
thsecb644f2007-06-03 18:45:53 +0000231#elif defined(TARGET_ALPHA)
232#elif defined(TARGET_ARM)
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800233#elif defined(TARGET_UNICORE32)
thsecb644f2007-06-03 18:45:53 +0000234#elif defined(TARGET_PPC)
Michael Walle81ea0e12011-02-17 23:45:02 +0100235#elif defined(TARGET_LM32)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200236#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000237#elif defined(TARGET_MIPS)
bellardfdf9b3e2006-04-27 21:07:38 +0000238#elif defined(TARGET_SH4)
thsf1ccf902007-10-08 13:16:14 +0000239#elif defined(TARGET_CRIS)
Alexander Graf10ec5112009-12-05 12:44:21 +0100240#elif defined(TARGET_S390X)
bellardfdf9b3e2006-04-27 21:07:38 +0000241 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000242#else
243#error unsupported target CPU
244#endif
bellard3fb2ded2003-06-24 13:22:59 +0000245 env->exception_index = -1;
bellard9d27abd2003-05-10 13:13:54 +0000246
bellard7d132992003-03-06 23:23:54 +0000247 /* prepare setjmp context for exception handling */
bellard3fb2ded2003-06-24 13:22:59 +0000248 for(;;) {
249 if (setjmp(env->jmp_env) == 0) {
Juan Quinteladfe5fff2009-07-27 16:12:40 +0200250#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
blueswir19ddff3d2009-04-04 07:41:20 +0000251#undef env
Jan Kiszka6792a572011-02-07 12:19:18 +0100252 env = cpu_single_env;
blueswir19ddff3d2009-04-04 07:41:20 +0000253#define env cpu_single_env
254#endif
bellard3fb2ded2003-06-24 13:22:59 +0000255 /* if an exception is pending, we execute it here */
256 if (env->exception_index >= 0) {
257 if (env->exception_index >= EXCP_INTERRUPT) {
258 /* exit request from the cpu execution loop */
259 ret = env->exception_index;
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100260 if (ret == EXCP_DEBUG) {
261 cpu_handle_debug_exception(env);
262 }
bellard3fb2ded2003-06-24 13:22:59 +0000263 break;
aurel3272d239e2009-01-14 19:40:27 +0000264 } else {
265#if defined(CONFIG_USER_ONLY)
bellard3fb2ded2003-06-24 13:22:59 +0000266 /* if user mode only, we simulate a fake exception
ths9f083492006-12-07 18:28:42 +0000267 which will be handled outside the cpu execution
bellard3fb2ded2003-06-24 13:22:59 +0000268 loop */
bellard83479e72003-06-25 16:12:37 +0000269#if defined(TARGET_I386)
ths5fafdf22007-09-16 21:08:06 +0000270 do_interrupt_user(env->exception_index,
271 env->exception_is_int,
272 env->error_code,
bellard3fb2ded2003-06-24 13:22:59 +0000273 env->exception_next_eip);
bellardeba01622008-05-12 12:04:40 +0000274 /* successfully delivered */
275 env->old_exception = -1;
bellard83479e72003-06-25 16:12:37 +0000276#endif
bellard3fb2ded2003-06-24 13:22:59 +0000277 ret = env->exception_index;
278 break;
aurel3272d239e2009-01-14 19:40:27 +0000279#else
bellard83479e72003-06-25 16:12:37 +0000280#if defined(TARGET_I386)
bellard3fb2ded2003-06-24 13:22:59 +0000281 /* simulate a real cpu exception. On i386, it can
282 trigger new exceptions, but we do not handle
283 double or triple faults yet. */
ths5fafdf22007-09-16 21:08:06 +0000284 do_interrupt(env->exception_index,
285 env->exception_is_int,
286 env->error_code,
bellardd05e66d2003-08-20 21:34:35 +0000287 env->exception_next_eip, 0);
ths678dde12007-03-31 20:28:52 +0000288 /* successfully delivered */
289 env->old_exception = -1;
bellardce097762004-01-04 23:53:18 +0000290#elif defined(TARGET_PPC)
291 do_interrupt(env);
Michael Walle81ea0e12011-02-17 23:45:02 +0100292#elif defined(TARGET_LM32)
293 do_interrupt(env);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200294#elif defined(TARGET_MICROBLAZE)
295 do_interrupt(env);
bellard6af0bf92005-07-02 14:58:51 +0000296#elif defined(TARGET_MIPS)
297 do_interrupt(env);
bellarde95c8d52004-09-30 22:22:08 +0000298#elif defined(TARGET_SPARC)
blueswir1f2bc7e72008-05-27 17:35:30 +0000299 do_interrupt(env);
bellardb5ff1b32005-11-26 10:38:39 +0000300#elif defined(TARGET_ARM)
301 do_interrupt(env);
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800302#elif defined(TARGET_UNICORE32)
303 do_interrupt(env);
bellardfdf9b3e2006-04-27 21:07:38 +0000304#elif defined(TARGET_SH4)
305 do_interrupt(env);
j_mayereddf68a2007-04-05 07:22:49 +0000306#elif defined(TARGET_ALPHA)
307 do_interrupt(env);
thsf1ccf902007-10-08 13:16:14 +0000308#elif defined(TARGET_CRIS)
309 do_interrupt(env);
pbrook06338792007-05-23 19:58:11 +0000310#elif defined(TARGET_M68K)
311 do_interrupt(0);
Alexander Graf3110e292011-04-15 17:32:48 +0200312#elif defined(TARGET_S390X)
313 do_interrupt(env);
bellard83479e72003-06-25 16:12:37 +0000314#endif
Paolo Bonzini301d2902010-01-15 09:41:01 +0100315 env->exception_index = -1;
aurel3272d239e2009-01-14 19:40:27 +0000316#endif
bellard3fb2ded2003-06-24 13:22:59 +0000317 }
ths5fafdf22007-09-16 21:08:06 +0000318 }
bellard9df217a2005-02-10 22:05:51 +0000319
blueswir1b5fc09a2008-05-04 06:38:18 +0000320 next_tb = 0; /* force lookup of first TB */
bellard3fb2ded2003-06-24 13:22:59 +0000321 for(;;) {
bellard68a79312003-06-30 13:12:32 +0000322 interrupt_request = env->interrupt_request;
malce1638bd2008-11-06 18:54:46 +0000323 if (unlikely(interrupt_request)) {
324 if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
325 /* Mask out external interrupts for this step. */
Richard Henderson3125f762011-05-04 13:34:25 -0700326 interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
malce1638bd2008-11-06 18:54:46 +0000327 }
pbrook6658ffb2007-03-16 23:58:11 +0000328 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
329 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
330 env->exception_index = EXCP_DEBUG;
331 cpu_loop_exit();
332 }
balroga90b7312007-05-01 01:28:01 +0000333#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200334 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800335 defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
balroga90b7312007-05-01 01:28:01 +0000336 if (interrupt_request & CPU_INTERRUPT_HALT) {
337 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
338 env->halted = 1;
339 env->exception_index = EXCP_HLT;
340 cpu_loop_exit();
341 }
342#endif
bellard68a79312003-06-30 13:12:32 +0000343#if defined(TARGET_I386)
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300344 if (interrupt_request & CPU_INTERRUPT_INIT) {
345 svm_check_intercept(SVM_EXIT_INIT);
346 do_cpu_init(env);
347 env->exception_index = EXCP_HALTED;
348 cpu_loop_exit();
349 } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
350 do_cpu_sipi(env);
351 } else if (env->hflags2 & HF2_GIF_MASK) {
bellarddb620f42008-06-04 17:02:19 +0000352 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
353 !(env->hflags & HF_SMM_MASK)) {
354 svm_check_intercept(SVM_EXIT_SMI);
355 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
356 do_smm_enter();
357 next_tb = 0;
358 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
359 !(env->hflags2 & HF2_NMI_MASK)) {
360 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
361 env->hflags2 |= HF2_NMI_MASK;
362 do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
363 next_tb = 0;
Huang Ying79c4f6b2009-06-23 10:05:14 +0800364 } else if (interrupt_request & CPU_INTERRUPT_MCE) {
365 env->interrupt_request &= ~CPU_INTERRUPT_MCE;
366 do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
367 next_tb = 0;
bellarddb620f42008-06-04 17:02:19 +0000368 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
369 (((env->hflags2 & HF2_VINTR_MASK) &&
370 (env->hflags2 & HF2_HIF_MASK)) ||
371 (!(env->hflags2 & HF2_VINTR_MASK) &&
372 (env->eflags & IF_MASK &&
373 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
374 int intno;
375 svm_check_intercept(SVM_EXIT_INTR);
376 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
377 intno = cpu_get_pic_interrupt(env);
aliguori93fcfe32009-01-15 22:34:14 +0000378 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
Juan Quinteladfe5fff2009-07-27 16:12:40 +0200379#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
blueswir19ddff3d2009-04-04 07:41:20 +0000380#undef env
381 env = cpu_single_env;
382#define env cpu_single_env
383#endif
bellarddb620f42008-06-04 17:02:19 +0000384 do_interrupt(intno, 0, 0, 0, 1);
385 /* ensure that no TB jump will be modified as
386 the program flow was changed */
387 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000388#if !defined(CONFIG_USER_ONLY)
bellarddb620f42008-06-04 17:02:19 +0000389 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
390 (env->eflags & IF_MASK) &&
391 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
392 int intno;
393 /* FIXME: this should respect TPR */
394 svm_check_intercept(SVM_EXIT_VINTR);
bellarddb620f42008-06-04 17:02:19 +0000395 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
aliguori93fcfe32009-01-15 22:34:14 +0000396 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
bellarddb620f42008-06-04 17:02:19 +0000397 do_interrupt(intno, 0, 0, 0, 1);
aurel32d40c54d2008-12-13 12:33:02 +0000398 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
bellarddb620f42008-06-04 17:02:19 +0000399 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000400#endif
bellarddb620f42008-06-04 17:02:19 +0000401 }
bellard68a79312003-06-30 13:12:32 +0000402 }
bellardce097762004-01-04 23:53:18 +0000403#elif defined(TARGET_PPC)
bellard9fddaa02004-05-21 12:59:32 +0000404#if 0
405 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
Blue Swirld84bda42009-11-07 10:36:04 +0000406 cpu_reset(env);
bellard9fddaa02004-05-21 12:59:32 +0000407 }
408#endif
j_mayer47103572007-03-30 09:38:04 +0000409 if (interrupt_request & CPU_INTERRUPT_HARD) {
j_mayere9df0142007-04-09 22:45:36 +0000410 ppc_hw_interrupt(env);
411 if (env->pending_interrupts == 0)
412 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
blueswir1b5fc09a2008-05-04 06:38:18 +0000413 next_tb = 0;
bellardce097762004-01-04 23:53:18 +0000414 }
Michael Walle81ea0e12011-02-17 23:45:02 +0100415#elif defined(TARGET_LM32)
416 if ((interrupt_request & CPU_INTERRUPT_HARD)
417 && (env->ie & IE_IE)) {
418 env->exception_index = EXCP_IRQ;
419 do_interrupt(env);
420 next_tb = 0;
421 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200422#elif defined(TARGET_MICROBLAZE)
423 if ((interrupt_request & CPU_INTERRUPT_HARD)
424 && (env->sregs[SR_MSR] & MSR_IE)
425 && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
426 && !(env->iflags & (D_FLAG | IMM_FLAG))) {
427 env->exception_index = EXCP_IRQ;
428 do_interrupt(env);
429 next_tb = 0;
430 }
bellard6af0bf92005-07-02 14:58:51 +0000431#elif defined(TARGET_MIPS)
432 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
Aurelien Jarno4cdc1cd2010-12-25 22:56:32 +0100433 cpu_mips_hw_interrupts_pending(env)) {
bellard6af0bf92005-07-02 14:58:51 +0000434 /* Raise it */
435 env->exception_index = EXCP_EXT_INTERRUPT;
436 env->error_code = 0;
437 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000438 next_tb = 0;
bellard6af0bf92005-07-02 14:58:51 +0000439 }
bellarde95c8d52004-09-30 22:22:08 +0000440#elif defined(TARGET_SPARC)
Igor V. Kovalenkod532b262010-01-07 23:28:31 +0300441 if (interrupt_request & CPU_INTERRUPT_HARD) {
442 if (cpu_interrupts_enabled(env) &&
443 env->interrupt_index > 0) {
444 int pil = env->interrupt_index & 0xf;
445 int type = env->interrupt_index & 0xf0;
bellard66321a12005-04-06 20:47:48 +0000446
Igor V. Kovalenkod532b262010-01-07 23:28:31 +0300447 if (((type == TT_EXTINT) &&
448 cpu_pil_allowed(env, pil)) ||
449 type != TT_EXTINT) {
450 env->exception_index = env->interrupt_index;
451 do_interrupt(env);
452 next_tb = 0;
453 }
454 }
balroga90b7312007-05-01 01:28:01 +0000455 }
bellardb5ff1b32005-11-26 10:38:39 +0000456#elif defined(TARGET_ARM)
457 if (interrupt_request & CPU_INTERRUPT_FIQ
458 && !(env->uncached_cpsr & CPSR_F)) {
459 env->exception_index = EXCP_FIQ;
460 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000461 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000462 }
pbrook9ee6e8b2007-11-11 00:04:49 +0000463 /* ARMv7-M interrupt return works by loading a magic value
464 into the PC. On real hardware the load causes the
465 return to occur. The qemu implementation performs the
466 jump normally, then does the exception return when the
467 CPU tries to execute code at the magic address.
468 This will cause the magic PC value to be pushed to
Stefan Weila1c72732011-04-28 17:20:38 +0200469 the stack if an interrupt occurred at the wrong time.
pbrook9ee6e8b2007-11-11 00:04:49 +0000470 We avoid this by disabling interrupts when
471 pc contains a magic address. */
bellardb5ff1b32005-11-26 10:38:39 +0000472 if (interrupt_request & CPU_INTERRUPT_HARD
pbrook9ee6e8b2007-11-11 00:04:49 +0000473 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
474 || !(env->uncached_cpsr & CPSR_I))) {
bellardb5ff1b32005-11-26 10:38:39 +0000475 env->exception_index = EXCP_IRQ;
476 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000477 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000478 }
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800479#elif defined(TARGET_UNICORE32)
480 if (interrupt_request & CPU_INTERRUPT_HARD
481 && !(env->uncached_asr & ASR_I)) {
482 do_interrupt(env);
483 next_tb = 0;
484 }
bellardfdf9b3e2006-04-27 21:07:38 +0000485#elif defined(TARGET_SH4)
thse96e2042007-12-02 06:18:24 +0000486 if (interrupt_request & CPU_INTERRUPT_HARD) {
487 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000488 next_tb = 0;
thse96e2042007-12-02 06:18:24 +0000489 }
j_mayereddf68a2007-04-05 07:22:49 +0000490#elif defined(TARGET_ALPHA)
Richard Henderson6a80e082011-04-18 15:09:09 -0700491 {
492 int idx = -1;
493 /* ??? This hard-codes the OSF/1 interrupt levels. */
494 switch (env->pal_mode ? 7 : env->ps & PS_INT_MASK) {
495 case 0 ... 3:
496 if (interrupt_request & CPU_INTERRUPT_HARD) {
497 idx = EXCP_DEV_INTERRUPT;
498 }
499 /* FALLTHRU */
500 case 4:
501 if (interrupt_request & CPU_INTERRUPT_TIMER) {
502 idx = EXCP_CLK_INTERRUPT;
503 }
504 /* FALLTHRU */
505 case 5:
506 if (interrupt_request & CPU_INTERRUPT_SMP) {
507 idx = EXCP_SMP_INTERRUPT;
508 }
509 /* FALLTHRU */
510 case 6:
511 if (interrupt_request & CPU_INTERRUPT_MCHK) {
512 idx = EXCP_MCHK;
513 }
514 }
515 if (idx >= 0) {
516 env->exception_index = idx;
517 env->error_code = 0;
518 do_interrupt(env);
519 next_tb = 0;
520 }
j_mayereddf68a2007-04-05 07:22:49 +0000521 }
thsf1ccf902007-10-08 13:16:14 +0000522#elif defined(TARGET_CRIS)
edgar_igl1b1a38b2008-06-09 23:18:06 +0000523 if (interrupt_request & CPU_INTERRUPT_HARD
Edgar E. Iglesiasfb9fb692010-02-15 11:17:33 +0100524 && (env->pregs[PR_CCS] & I_FLAG)
525 && !env->locked_irq) {
edgar_igl1b1a38b2008-06-09 23:18:06 +0000526 env->exception_index = EXCP_IRQ;
527 do_interrupt(env);
528 next_tb = 0;
529 }
530 if (interrupt_request & CPU_INTERRUPT_NMI
531 && (env->pregs[PR_CCS] & M_FLAG)) {
532 env->exception_index = EXCP_NMI;
thsf1ccf902007-10-08 13:16:14 +0000533 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000534 next_tb = 0;
thsf1ccf902007-10-08 13:16:14 +0000535 }
pbrook06338792007-05-23 19:58:11 +0000536#elif defined(TARGET_M68K)
537 if (interrupt_request & CPU_INTERRUPT_HARD
538 && ((env->sr & SR_I) >> SR_I_SHIFT)
539 < env->pending_level) {
540 /* Real hardware gets the interrupt vector via an
541 IACK cycle at this point. Current emulated
542 hardware doesn't rely on this, so we
543 provide/save the vector when the interrupt is
544 first signalled. */
545 env->exception_index = env->pending_vector;
546 do_interrupt(1);
blueswir1b5fc09a2008-05-04 06:38:18 +0000547 next_tb = 0;
pbrook06338792007-05-23 19:58:11 +0000548 }
Alexander Graf3110e292011-04-15 17:32:48 +0200549#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
550 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
551 (env->psw.mask & PSW_MASK_EXT)) {
552 do_interrupt(env);
553 next_tb = 0;
554 }
bellard68a79312003-06-30 13:12:32 +0000555#endif
Stefan Weilff2712b2011-04-28 17:20:35 +0200556 /* Don't use the cached interrupt_request value,
bellard9d050952006-05-22 22:03:52 +0000557 do_interrupt may have updated the EXITTB flag. */
bellardb5ff1b32005-11-26 10:38:39 +0000558 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
bellardbf3e8bf2004-02-16 21:58:54 +0000559 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
560 /* ensure that no TB jump will be modified as
561 the program flow was changed */
blueswir1b5fc09a2008-05-04 06:38:18 +0000562 next_tb = 0;
bellardbf3e8bf2004-02-16 21:58:54 +0000563 }
aurel32be214e62009-03-06 21:48:00 +0000564 }
565 if (unlikely(env->exit_request)) {
566 env->exit_request = 0;
567 env->exception_index = EXCP_INTERRUPT;
568 cpu_loop_exit();
bellard3fb2ded2003-06-24 13:22:59 +0000569 }
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700570#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
aliguori8fec2b82009-01-15 22:36:53 +0000571 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
bellard3fb2ded2003-06-24 13:22:59 +0000572 /* restore flags in standard format */
thsecb644f2007-06-03 18:45:53 +0000573#if defined(TARGET_I386)
pbrooka7812ae2008-11-17 14:43:54 +0000574 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
aliguori93fcfe32009-01-15 22:34:14 +0000575 log_cpu_state(env, X86_DUMP_CCOP);
bellard3fb2ded2003-06-24 13:22:59 +0000576 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
pbrooke6e59062006-10-22 00:18:54 +0000577#elif defined(TARGET_M68K)
578 cpu_m68k_flush_flags(env, env->cc_op);
579 env->cc_op = CC_OP_FLAGS;
580 env->sr = (env->sr & 0xffe0)
581 | env->cc_dest | (env->cc_x << 4);
aliguori93fcfe32009-01-15 22:34:14 +0000582 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000583#else
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700584 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000585#endif
bellard3fb2ded2003-06-24 13:22:59 +0000586 }
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700587#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
pbrookd5975362008-06-07 20:50:51 +0000588 spin_lock(&tb_lock);
bellard8a40a182005-11-20 10:35:40 +0000589 tb = tb_find_fast();
pbrookd5975362008-06-07 20:50:51 +0000590 /* Note: we do it here to avoid a gcc bug on Mac OS X when
591 doing it in tb_find_slow */
592 if (tb_invalidated_flag) {
593 /* as some TB could have been invalidated because
594 of memory exceptions while generating the code, we
595 must recompute the hash index here */
596 next_tb = 0;
pbrook2e70f6e2008-06-29 01:03:05 +0000597 tb_invalidated_flag = 0;
pbrookd5975362008-06-07 20:50:51 +0000598 }
Juan Quintelaf0667e62009-07-27 16:13:05 +0200599#ifdef CONFIG_DEBUG_EXEC
aliguori93fcfe32009-01-15 22:34:14 +0000600 qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
601 (long)tb->tc_ptr, tb->pc,
602 lookup_symbol(tb->pc));
bellard9d27abd2003-05-10 13:13:54 +0000603#endif
bellard8a40a182005-11-20 10:35:40 +0000604 /* see if we can patch the calling TB. When the TB
605 spans two pages, we cannot safely do a direct
606 jump. */
Paolo Bonzini040f2fb2010-01-15 08:56:36 +0100607 if (next_tb != 0 && tb->page_addr[1] == -1) {
blueswir1b5fc09a2008-05-04 06:38:18 +0000608 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
bellard3fb2ded2003-06-24 13:22:59 +0000609 }
pbrookd5975362008-06-07 20:50:51 +0000610 spin_unlock(&tb_lock);
malc55e8b852008-11-04 14:18:13 +0000611
612 /* cpu_interrupt might be called while translating the
613 TB, but before it is linked into a potentially
614 infinite loop and becomes env->current_tb. Avoid
615 starting execution if there is a pending interrupt. */
Jan Kiszkab0052d12010-06-25 16:56:50 +0200616 env->current_tb = tb;
617 barrier();
618 if (likely(!env->exit_request)) {
pbrook2e70f6e2008-06-29 01:03:05 +0000619 tc_ptr = tb->tc_ptr;
bellard3fb2ded2003-06-24 13:22:59 +0000620 /* execute the generated code */
Juan Quinteladfe5fff2009-07-27 16:12:40 +0200621#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
blueswir1572a9d42008-05-17 07:38:10 +0000622#undef env
pbrook2e70f6e2008-06-29 01:03:05 +0000623 env = cpu_single_env;
blueswir1572a9d42008-05-17 07:38:10 +0000624#define env cpu_single_env
625#endif
pbrook2e70f6e2008-06-29 01:03:05 +0000626 next_tb = tcg_qemu_tb_exec(tc_ptr);
pbrook2e70f6e2008-06-29 01:03:05 +0000627 if ((next_tb & 3) == 2) {
thsbf20dc02008-06-30 17:22:19 +0000628 /* Instruction counter expired. */
pbrook2e70f6e2008-06-29 01:03:05 +0000629 int insns_left;
630 tb = (TranslationBlock *)(long)(next_tb & ~3);
631 /* Restore PC. */
aliguori622ed362008-11-18 19:36:03 +0000632 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000633 insns_left = env->icount_decr.u32;
634 if (env->icount_extra && insns_left >= 0) {
635 /* Refill decrementer and continue execution. */
636 env->icount_extra += insns_left;
637 if (env->icount_extra > 0xffff) {
638 insns_left = 0xffff;
639 } else {
640 insns_left = env->icount_extra;
641 }
642 env->icount_extra -= insns_left;
643 env->icount_decr.u16.low = insns_left;
644 } else {
645 if (insns_left > 0) {
646 /* Execute remaining instructions. */
647 cpu_exec_nocache(insns_left, tb);
648 }
649 env->exception_index = EXCP_INTERRUPT;
650 next_tb = 0;
651 cpu_loop_exit();
652 }
653 }
654 }
Jan Kiszkab0052d12010-06-25 16:56:50 +0200655 env->current_tb = NULL;
bellard4cbf74b2003-08-10 21:48:43 +0000656 /* reset soft MMU for next block (it can currently
657 only be set by a memory fault) */
ths50a518e2007-06-03 18:52:15 +0000658 } /* for(;;) */
bellard7d132992003-03-06 23:23:54 +0000659 }
bellard3fb2ded2003-06-24 13:22:59 +0000660 } /* for(;;) */
661
bellard7d132992003-03-06 23:23:54 +0000662
bellarde4533c72003-06-15 19:51:39 +0000663#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000664 /* restore flags in standard format */
pbrooka7812ae2008-11-17 14:43:54 +0000665 env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
bellarde4533c72003-06-15 19:51:39 +0000666#elif defined(TARGET_ARM)
bellardb7bcbe92005-02-22 19:27:29 +0000667 /* XXX: Save/restore host fpu exception state?. */
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800668#elif defined(TARGET_UNICORE32)
bellard93ac68b2003-09-30 20:57:29 +0000669#elif defined(TARGET_SPARC)
bellard67867302003-11-23 17:05:30 +0000670#elif defined(TARGET_PPC)
Michael Walle81ea0e12011-02-17 23:45:02 +0100671#elif defined(TARGET_LM32)
pbrooke6e59062006-10-22 00:18:54 +0000672#elif defined(TARGET_M68K)
673 cpu_m68k_flush_flags(env, env->cc_op);
674 env->cc_op = CC_OP_FLAGS;
675 env->sr = (env->sr & 0xffe0)
676 | env->cc_dest | (env->cc_x << 4);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200677#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000678#elif defined(TARGET_MIPS)
bellardfdf9b3e2006-04-27 21:07:38 +0000679#elif defined(TARGET_SH4)
j_mayereddf68a2007-04-05 07:22:49 +0000680#elif defined(TARGET_ALPHA)
thsf1ccf902007-10-08 13:16:14 +0000681#elif defined(TARGET_CRIS)
Alexander Graf10ec5112009-12-05 12:44:21 +0100682#elif defined(TARGET_S390X)
bellardfdf9b3e2006-04-27 21:07:38 +0000683 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000684#else
685#error unsupported target CPU
686#endif
pbrook1057eaa2007-02-04 13:37:44 +0000687
688 /* restore global registers */
Jan Kiszka1d93f0f2010-06-25 16:56:49 +0200689 barrier();
Paolo Bonzini24ebf5f2010-02-18 21:25:23 +0100690 env = (void *) saved_env_reg;
pbrook1057eaa2007-02-04 13:37:44 +0000691
bellard6a00d602005-11-21 23:25:50 +0000692 /* fail safe : never use cpu_single_env outside cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000693 cpu_single_env = NULL;
bellard7d132992003-03-06 23:23:54 +0000694 return ret;
695}