blob: 9fcfe9e0dbeff241761db23b6ca1151134221188 [file] [log] [blame]
bellard7d132992003-03-06 23:23:54 +00001/*
陳韋任e965fc32012-02-06 14:02:55 +08002 * 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"
Blue Swirlcea5f9a2011-05-15 16:03:25 +000020#include "cpu.h"
Paolo Bonzini76cad712012-10-24 11:12:21 +020021#include "disas/disas.h"
bellard7cb69ca2008-05-10 10:55:51 +000022#include "tcg.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010023#include "qemu/atomic.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010024#include "sysemu/qtest.h"
bellard7d132992003-03-06 23:23:54 +000025
Juan Quintelaf0667e62009-07-27 16:13:05 +020026//#define CONFIG_DEBUG_EXEC
bellard7d132992003-03-06 23:23:54 +000027
Andreas Färber3993c6b2012-05-03 06:43:49 +020028bool qemu_cpu_has_work(CPUState *cpu)
aliguori6a4955a2009-04-24 18:03:20 +000029{
Andreas Färber3993c6b2012-05-03 06:43:49 +020030 return cpu_has_work(cpu);
aliguori6a4955a2009-04-24 18:03:20 +000031}
32
Andreas Färber9349b4f2012-03-14 01:38:32 +010033void cpu_loop_exit(CPUArchState *env)
bellarde4533c72003-06-15 19:51:39 +000034{
Andreas Färberd77953b2013-01-16 19:29:31 +010035 CPUState *cpu = ENV_GET_CPU(env);
36
37 cpu->current_tb = NULL;
Blue Swirlcea5f9a2011-05-15 16:03:25 +000038 longjmp(env->jmp_env, 1);
bellarde4533c72003-06-15 19:51:39 +000039}
thsbfed01f2007-06-03 17:44:37 +000040
bellardfbf9eeb2004-04-25 21:21:33 +000041/* exit the current TB from a signal handler. The host registers are
42 restored in a state compatible with the CPU emulator
43 */
Blue Swirl9eff14f2011-05-21 08:42:35 +000044#if defined(CONFIG_SOFTMMU)
Andreas Färber9349b4f2012-03-14 01:38:32 +010045void cpu_resume_from_signal(CPUArchState *env, void *puc)
bellardfbf9eeb2004-04-25 21:21:33 +000046{
Blue Swirl9eff14f2011-05-21 08:42:35 +000047 /* XXX: restore cpu registers saved in host registers */
48
49 env->exception_index = -1;
50 longjmp(env->jmp_env, 1);
51}
Blue Swirl9eff14f2011-05-21 08:42:35 +000052#endif
bellardfbf9eeb2004-04-25 21:21:33 +000053
pbrook2e70f6e2008-06-29 01:03:05 +000054/* Execute the code without caching the generated code. An interpreter
55 could be used if available. */
Andreas Färber9349b4f2012-03-14 01:38:32 +010056static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
Blue Swirlcea5f9a2011-05-15 16:03:25 +000057 TranslationBlock *orig_tb)
pbrook2e70f6e2008-06-29 01:03:05 +000058{
Andreas Färberd77953b2013-01-16 19:29:31 +010059 CPUState *cpu = ENV_GET_CPU(env);
Stefan Weil69784ea2012-03-16 23:50:54 +010060 tcg_target_ulong next_tb;
pbrook2e70f6e2008-06-29 01:03:05 +000061 TranslationBlock *tb;
62
63 /* Should never happen.
64 We only end up here when an existing TB is too long. */
65 if (max_cycles > CF_COUNT_MASK)
66 max_cycles = CF_COUNT_MASK;
67
68 tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
69 max_cycles);
Andreas Färberd77953b2013-01-16 19:29:31 +010070 cpu->current_tb = tb;
pbrook2e70f6e2008-06-29 01:03:05 +000071 /* execute the generated code */
Blue Swirlcea5f9a2011-05-15 16:03:25 +000072 next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
Andreas Färberd77953b2013-01-16 19:29:31 +010073 cpu->current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +000074
75 if ((next_tb & 3) == 2) {
76 /* Restore PC. This may happen if async event occurs before
77 the TB starts executing. */
aliguori622ed362008-11-18 19:36:03 +000078 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +000079 }
80 tb_phys_invalidate(tb, -1);
81 tb_free(tb);
82}
83
Andreas Färber9349b4f2012-03-14 01:38:32 +010084static TranslationBlock *tb_find_slow(CPUArchState *env,
Blue Swirlcea5f9a2011-05-15 16:03:25 +000085 target_ulong pc,
bellard8a40a182005-11-20 10:35:40 +000086 target_ulong cs_base,
j_mayerc0686882007-09-20 22:47:42 +000087 uint64_t flags)
bellard8a40a182005-11-20 10:35:40 +000088{
89 TranslationBlock *tb, **ptb1;
bellard8a40a182005-11-20 10:35:40 +000090 unsigned int h;
Blue Swirl337fc752011-09-04 11:06:22 +000091 tb_page_addr_t phys_pc, phys_page1;
Paul Brook41c1b1c2010-03-12 16:54:58 +000092 target_ulong virt_page2;
ths3b46e622007-09-17 08:09:54 +000093
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +070094 tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
ths3b46e622007-09-17 08:09:54 +000095
bellard8a40a182005-11-20 10:35:40 +000096 /* find translated block using physical mappings */
Paul Brook41c1b1c2010-03-12 16:54:58 +000097 phys_pc = get_page_addr_code(env, pc);
bellard8a40a182005-11-20 10:35:40 +000098 phys_page1 = phys_pc & TARGET_PAGE_MASK;
bellard8a40a182005-11-20 10:35:40 +000099 h = tb_phys_hash_func(phys_pc);
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700100 ptb1 = &tcg_ctx.tb_ctx.tb_phys_hash[h];
bellard8a40a182005-11-20 10:35:40 +0000101 for(;;) {
102 tb = *ptb1;
103 if (!tb)
104 goto not_found;
ths5fafdf22007-09-16 21:08:06 +0000105 if (tb->pc == pc &&
bellard8a40a182005-11-20 10:35:40 +0000106 tb->page_addr[0] == phys_page1 &&
ths5fafdf22007-09-16 21:08:06 +0000107 tb->cs_base == cs_base &&
bellard8a40a182005-11-20 10:35:40 +0000108 tb->flags == flags) {
109 /* check next page if needed */
110 if (tb->page_addr[1] != -1) {
Blue Swirl337fc752011-09-04 11:06:22 +0000111 tb_page_addr_t phys_page2;
112
ths5fafdf22007-09-16 21:08:06 +0000113 virt_page2 = (pc & TARGET_PAGE_MASK) +
bellard8a40a182005-11-20 10:35:40 +0000114 TARGET_PAGE_SIZE;
Paul Brook41c1b1c2010-03-12 16:54:58 +0000115 phys_page2 = get_page_addr_code(env, virt_page2);
bellard8a40a182005-11-20 10:35:40 +0000116 if (tb->page_addr[1] == phys_page2)
117 goto found;
118 } else {
119 goto found;
120 }
121 }
122 ptb1 = &tb->phys_hash_next;
123 }
124 not_found:
pbrook2e70f6e2008-06-29 01:03:05 +0000125 /* if no translated code available, then translate it now */
126 tb = tb_gen_code(env, pc, cs_base, flags, 0);
ths3b46e622007-09-17 08:09:54 +0000127
bellard8a40a182005-11-20 10:35:40 +0000128 found:
Kirill Batuzov2c90fe22010-12-02 16:12:46 +0300129 /* Move the last found TB to the head of the list */
130 if (likely(*ptb1)) {
131 *ptb1 = tb->phys_hash_next;
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700132 tb->phys_hash_next = tcg_ctx.tb_ctx.tb_phys_hash[h];
133 tcg_ctx.tb_ctx.tb_phys_hash[h] = tb;
Kirill Batuzov2c90fe22010-12-02 16:12:46 +0300134 }
bellard8a40a182005-11-20 10:35:40 +0000135 /* we add the TB in the virtual pc hash table */
136 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
bellard8a40a182005-11-20 10:35:40 +0000137 return tb;
138}
139
Andreas Färber9349b4f2012-03-14 01:38:32 +0100140static inline TranslationBlock *tb_find_fast(CPUArchState *env)
bellard8a40a182005-11-20 10:35:40 +0000141{
142 TranslationBlock *tb;
143 target_ulong cs_base, pc;
aliguori6b917542008-11-18 19:46:41 +0000144 int flags;
bellard8a40a182005-11-20 10:35:40 +0000145
146 /* we record a subset of the CPU state. It will
147 always be the same before a given translated block
148 is executed. */
aliguori6b917542008-11-18 19:46:41 +0000149 cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
bellardbce61842008-02-01 22:18:51 +0000150 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
ths551bd272008-07-03 17:57:36 +0000151 if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
152 tb->flags != flags)) {
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000153 tb = tb_find_slow(env, pc, cs_base, flags);
bellard8a40a182005-11-20 10:35:40 +0000154 }
155 return tb;
156}
157
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100158static CPUDebugExcpHandler *debug_excp_handler;
159
Igor Mammedov84e3b602012-06-21 18:29:38 +0200160void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100161{
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100162 debug_excp_handler = handler;
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100163}
164
Andreas Färber9349b4f2012-03-14 01:38:32 +0100165static void cpu_handle_debug_exception(CPUArchState *env)
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100166{
167 CPUWatchpoint *wp;
168
169 if (!env->watchpoint_hit) {
170 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
171 wp->flags &= ~BP_WATCHPOINT_HIT;
172 }
173 }
174 if (debug_excp_handler) {
175 debug_excp_handler(env);
176 }
177}
178
bellard7d132992003-03-06 23:23:54 +0000179/* main execution loop */
180
Marcelo Tosatti1a28cac2010-05-04 09:45:20 -0300181volatile sig_atomic_t exit_request;
182
Andreas Färber9349b4f2012-03-14 01:38:32 +0100183int cpu_exec(CPUArchState *env)
bellard7d132992003-03-06 23:23:54 +0000184{
Andreas Färberc356a1b2012-05-04 19:39:23 +0200185 CPUState *cpu = ENV_GET_CPU(env);
bellard8a40a182005-11-20 10:35:40 +0000186 int ret, interrupt_request;
bellard8a40a182005-11-20 10:35:40 +0000187 TranslationBlock *tb;
bellardc27004e2005-01-03 23:35:10 +0000188 uint8_t *tc_ptr;
Stefan Weil69784ea2012-03-16 23:50:54 +0100189 tcg_target_ulong next_tb;
bellard8c6939c2003-06-09 15:28:00 +0000190
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000191 if (env->halted) {
Andreas Färber3993c6b2012-05-03 06:43:49 +0200192 if (!cpu_has_work(cpu)) {
Paolo Bonzinieda48c32011-03-12 17:43:56 +0100193 return EXCP_HALTED;
194 }
195
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000196 env->halted = 0;
Paolo Bonzinieda48c32011-03-12 17:43:56 +0100197 }
bellard5a1e3cf2005-11-23 21:02:53 +0000198
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000199 cpu_single_env = env;
bellarde4533c72003-06-15 19:51:39 +0000200
Jan Kiszkac629a4b2010-06-25 16:56:52 +0200201 if (unlikely(exit_request)) {
Andreas Färberfcd7d002012-12-17 08:02:44 +0100202 cpu->exit_request = 1;
Marcelo Tosatti1a28cac2010-05-04 09:45:20 -0300203 }
204
thsecb644f2007-06-03 18:45:53 +0000205#if defined(TARGET_I386)
Jan Kiszka6792a572011-02-07 12:19:18 +0100206 /* put eflags in CPU temporary format */
207 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
208 DF = 1 - (2 * ((env->eflags >> 10) & 1));
209 CC_OP = CC_OP_EFLAGS;
210 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellard93ac68b2003-09-30 20:57:29 +0000211#elif defined(TARGET_SPARC)
pbrooke6e59062006-10-22 00:18:54 +0000212#elif defined(TARGET_M68K)
213 env->cc_op = CC_OP_FLAGS;
214 env->cc_dest = env->sr & 0xf;
215 env->cc_x = (env->sr >> 4) & 1;
thsecb644f2007-06-03 18:45:53 +0000216#elif defined(TARGET_ALPHA)
217#elif defined(TARGET_ARM)
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800218#elif defined(TARGET_UNICORE32)
thsecb644f2007-06-03 18:45:53 +0000219#elif defined(TARGET_PPC)
Elie Richa4e85f822011-07-22 05:58:39 +0000220 env->reserve_addr = -1;
Michael Walle81ea0e12011-02-17 23:45:02 +0100221#elif defined(TARGET_LM32)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200222#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000223#elif defined(TARGET_MIPS)
Jia Liue67db062012-07-20 15:50:39 +0800224#elif defined(TARGET_OPENRISC)
bellardfdf9b3e2006-04-27 21:07:38 +0000225#elif defined(TARGET_SH4)
thsf1ccf902007-10-08 13:16:14 +0000226#elif defined(TARGET_CRIS)
Alexander Graf10ec5112009-12-05 12:44:21 +0100227#elif defined(TARGET_S390X)
Max Filippov23288262011-09-06 03:55:25 +0400228#elif defined(TARGET_XTENSA)
bellardfdf9b3e2006-04-27 21:07:38 +0000229 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000230#else
231#error unsupported target CPU
232#endif
bellard3fb2ded2003-06-24 13:22:59 +0000233 env->exception_index = -1;
bellard9d27abd2003-05-10 13:13:54 +0000234
bellard7d132992003-03-06 23:23:54 +0000235 /* prepare setjmp context for exception handling */
bellard3fb2ded2003-06-24 13:22:59 +0000236 for(;;) {
237 if (setjmp(env->jmp_env) == 0) {
238 /* if an exception is pending, we execute it here */
239 if (env->exception_index >= 0) {
240 if (env->exception_index >= EXCP_INTERRUPT) {
241 /* exit request from the cpu execution loop */
242 ret = env->exception_index;
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100243 if (ret == EXCP_DEBUG) {
244 cpu_handle_debug_exception(env);
245 }
bellard3fb2ded2003-06-24 13:22:59 +0000246 break;
aurel3272d239e2009-01-14 19:40:27 +0000247 } else {
248#if defined(CONFIG_USER_ONLY)
bellard3fb2ded2003-06-24 13:22:59 +0000249 /* if user mode only, we simulate a fake exception
ths9f083492006-12-07 18:28:42 +0000250 which will be handled outside the cpu execution
bellard3fb2ded2003-06-24 13:22:59 +0000251 loop */
bellard83479e72003-06-25 16:12:37 +0000252#if defined(TARGET_I386)
Blue Swirle694d4e2011-05-16 19:38:48 +0000253 do_interrupt(env);
bellard83479e72003-06-25 16:12:37 +0000254#endif
bellard3fb2ded2003-06-24 13:22:59 +0000255 ret = env->exception_index;
256 break;
aurel3272d239e2009-01-14 19:40:27 +0000257#else
Blue Swirle694d4e2011-05-16 19:38:48 +0000258 do_interrupt(env);
Paolo Bonzini301d2902010-01-15 09:41:01 +0100259 env->exception_index = -1;
aurel3272d239e2009-01-14 19:40:27 +0000260#endif
bellard3fb2ded2003-06-24 13:22:59 +0000261 }
ths5fafdf22007-09-16 21:08:06 +0000262 }
bellard9df217a2005-02-10 22:05:51 +0000263
blueswir1b5fc09a2008-05-04 06:38:18 +0000264 next_tb = 0; /* force lookup of first TB */
bellard3fb2ded2003-06-24 13:22:59 +0000265 for(;;) {
bellard68a79312003-06-30 13:12:32 +0000266 interrupt_request = env->interrupt_request;
malce1638bd2008-11-06 18:54:46 +0000267 if (unlikely(interrupt_request)) {
268 if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
269 /* Mask out external interrupts for this step. */
Richard Henderson3125f762011-05-04 13:34:25 -0700270 interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
malce1638bd2008-11-06 18:54:46 +0000271 }
pbrook6658ffb2007-03-16 23:58:11 +0000272 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
273 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
274 env->exception_index = EXCP_DEBUG;
Blue Swirl1162c042011-05-14 12:52:35 +0000275 cpu_loop_exit(env);
pbrook6658ffb2007-03-16 23:58:11 +0000276 }
balroga90b7312007-05-01 01:28:01 +0000277#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200278 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800279 defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
balroga90b7312007-05-01 01:28:01 +0000280 if (interrupt_request & CPU_INTERRUPT_HALT) {
281 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
282 env->halted = 1;
283 env->exception_index = EXCP_HLT;
Blue Swirl1162c042011-05-14 12:52:35 +0000284 cpu_loop_exit(env);
balroga90b7312007-05-01 01:28:01 +0000285 }
286#endif
bellard68a79312003-06-30 13:12:32 +0000287#if defined(TARGET_I386)
Jan Kiszka5d62c432012-07-09 16:42:32 +0200288#if !defined(CONFIG_USER_ONLY)
289 if (interrupt_request & CPU_INTERRUPT_POLL) {
290 env->interrupt_request &= ~CPU_INTERRUPT_POLL;
291 apic_poll_irq(env->apic_state);
292 }
293#endif
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300294 if (interrupt_request & CPU_INTERRUPT_INIT) {
Blue Swirl77b2bc22012-04-28 19:35:10 +0000295 cpu_svm_check_intercept_param(env, SVM_EXIT_INIT,
296 0);
Andreas Färber232fc232012-05-05 01:14:41 +0200297 do_cpu_init(x86_env_get_cpu(env));
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300298 env->exception_index = EXCP_HALTED;
Blue Swirl1162c042011-05-14 12:52:35 +0000299 cpu_loop_exit(env);
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300300 } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
Andreas Färber232fc232012-05-05 01:14:41 +0200301 do_cpu_sipi(x86_env_get_cpu(env));
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300302 } else if (env->hflags2 & HF2_GIF_MASK) {
bellarddb620f42008-06-04 17:02:19 +0000303 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
304 !(env->hflags & HF_SMM_MASK)) {
Blue Swirl77b2bc22012-04-28 19:35:10 +0000305 cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,
306 0);
bellarddb620f42008-06-04 17:02:19 +0000307 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
Blue Swirle694d4e2011-05-16 19:38:48 +0000308 do_smm_enter(env);
bellarddb620f42008-06-04 17:02:19 +0000309 next_tb = 0;
310 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
311 !(env->hflags2 & HF2_NMI_MASK)) {
312 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
313 env->hflags2 |= HF2_NMI_MASK;
Blue Swirle694d4e2011-05-16 19:38:48 +0000314 do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
bellarddb620f42008-06-04 17:02:19 +0000315 next_tb = 0;
陳韋任e965fc32012-02-06 14:02:55 +0800316 } else if (interrupt_request & CPU_INTERRUPT_MCE) {
Huang Ying79c4f6b2009-06-23 10:05:14 +0800317 env->interrupt_request &= ~CPU_INTERRUPT_MCE;
Blue Swirle694d4e2011-05-16 19:38:48 +0000318 do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
Huang Ying79c4f6b2009-06-23 10:05:14 +0800319 next_tb = 0;
bellarddb620f42008-06-04 17:02:19 +0000320 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
321 (((env->hflags2 & HF2_VINTR_MASK) &&
322 (env->hflags2 & HF2_HIF_MASK)) ||
323 (!(env->hflags2 & HF2_VINTR_MASK) &&
324 (env->eflags & IF_MASK &&
325 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
326 int intno;
Blue Swirl77b2bc22012-04-28 19:35:10 +0000327 cpu_svm_check_intercept_param(env, SVM_EXIT_INTR,
328 0);
bellarddb620f42008-06-04 17:02:19 +0000329 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
330 intno = cpu_get_pic_interrupt(env);
malc4f213872012-08-27 18:33:12 +0400331 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
332 do_interrupt_x86_hardirq(env, intno, 1);
333 /* ensure that no TB jump will be modified as
334 the program flow was changed */
335 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000336#if !defined(CONFIG_USER_ONLY)
bellarddb620f42008-06-04 17:02:19 +0000337 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
338 (env->eflags & IF_MASK) &&
339 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
340 int intno;
341 /* FIXME: this should respect TPR */
Blue Swirl77b2bc22012-04-28 19:35:10 +0000342 cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR,
343 0);
bellarddb620f42008-06-04 17:02:19 +0000344 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
aliguori93fcfe32009-01-15 22:34:14 +0000345 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
Blue Swirle694d4e2011-05-16 19:38:48 +0000346 do_interrupt_x86_hardirq(env, intno, 1);
aurel32d40c54d2008-12-13 12:33:02 +0000347 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
bellarddb620f42008-06-04 17:02:19 +0000348 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000349#endif
bellarddb620f42008-06-04 17:02:19 +0000350 }
bellard68a79312003-06-30 13:12:32 +0000351 }
bellardce097762004-01-04 23:53:18 +0000352#elif defined(TARGET_PPC)
bellard9fddaa02004-05-21 12:59:32 +0000353 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
Andreas Färberc356a1b2012-05-04 19:39:23 +0200354 cpu_reset(cpu);
bellard9fddaa02004-05-21 12:59:32 +0000355 }
j_mayer47103572007-03-30 09:38:04 +0000356 if (interrupt_request & CPU_INTERRUPT_HARD) {
j_mayere9df0142007-04-09 22:45:36 +0000357 ppc_hw_interrupt(env);
358 if (env->pending_interrupts == 0)
359 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
blueswir1b5fc09a2008-05-04 06:38:18 +0000360 next_tb = 0;
bellardce097762004-01-04 23:53:18 +0000361 }
Michael Walle81ea0e12011-02-17 23:45:02 +0100362#elif defined(TARGET_LM32)
363 if ((interrupt_request & CPU_INTERRUPT_HARD)
364 && (env->ie & IE_IE)) {
365 env->exception_index = EXCP_IRQ;
366 do_interrupt(env);
367 next_tb = 0;
368 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200369#elif defined(TARGET_MICROBLAZE)
370 if ((interrupt_request & CPU_INTERRUPT_HARD)
371 && (env->sregs[SR_MSR] & MSR_IE)
372 && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
373 && !(env->iflags & (D_FLAG | IMM_FLAG))) {
374 env->exception_index = EXCP_IRQ;
375 do_interrupt(env);
376 next_tb = 0;
377 }
bellard6af0bf92005-07-02 14:58:51 +0000378#elif defined(TARGET_MIPS)
379 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
Aurelien Jarno4cdc1cd2010-12-25 22:56:32 +0100380 cpu_mips_hw_interrupts_pending(env)) {
bellard6af0bf92005-07-02 14:58:51 +0000381 /* Raise it */
382 env->exception_index = EXCP_EXT_INTERRUPT;
383 env->error_code = 0;
384 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000385 next_tb = 0;
bellard6af0bf92005-07-02 14:58:51 +0000386 }
Jia Liub6a71ef2012-07-20 15:50:41 +0800387#elif defined(TARGET_OPENRISC)
388 {
389 int idx = -1;
390 if ((interrupt_request & CPU_INTERRUPT_HARD)
391 && (env->sr & SR_IEE)) {
392 idx = EXCP_INT;
393 }
394 if ((interrupt_request & CPU_INTERRUPT_TIMER)
395 && (env->sr & SR_TEE)) {
396 idx = EXCP_TICK;
397 }
398 if (idx >= 0) {
399 env->exception_index = idx;
400 do_interrupt(env);
401 next_tb = 0;
402 }
403 }
bellarde95c8d52004-09-30 22:22:08 +0000404#elif defined(TARGET_SPARC)
Igor V. Kovalenkod532b262010-01-07 23:28:31 +0300405 if (interrupt_request & CPU_INTERRUPT_HARD) {
406 if (cpu_interrupts_enabled(env) &&
407 env->interrupt_index > 0) {
408 int pil = env->interrupt_index & 0xf;
409 int type = env->interrupt_index & 0xf0;
bellard66321a12005-04-06 20:47:48 +0000410
Igor V. Kovalenkod532b262010-01-07 23:28:31 +0300411 if (((type == TT_EXTINT) &&
412 cpu_pil_allowed(env, pil)) ||
413 type != TT_EXTINT) {
414 env->exception_index = env->interrupt_index;
415 do_interrupt(env);
416 next_tb = 0;
417 }
418 }
陳韋任e965fc32012-02-06 14:02:55 +0800419 }
bellardb5ff1b32005-11-26 10:38:39 +0000420#elif defined(TARGET_ARM)
421 if (interrupt_request & CPU_INTERRUPT_FIQ
422 && !(env->uncached_cpsr & CPSR_F)) {
423 env->exception_index = EXCP_FIQ;
424 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000425 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000426 }
pbrook9ee6e8b2007-11-11 00:04:49 +0000427 /* ARMv7-M interrupt return works by loading a magic value
428 into the PC. On real hardware the load causes the
429 return to occur. The qemu implementation performs the
430 jump normally, then does the exception return when the
431 CPU tries to execute code at the magic address.
432 This will cause the magic PC value to be pushed to
Stefan Weila1c72732011-04-28 17:20:38 +0200433 the stack if an interrupt occurred at the wrong time.
pbrook9ee6e8b2007-11-11 00:04:49 +0000434 We avoid this by disabling interrupts when
435 pc contains a magic address. */
bellardb5ff1b32005-11-26 10:38:39 +0000436 if (interrupt_request & CPU_INTERRUPT_HARD
pbrook9ee6e8b2007-11-11 00:04:49 +0000437 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
438 || !(env->uncached_cpsr & CPSR_I))) {
bellardb5ff1b32005-11-26 10:38:39 +0000439 env->exception_index = EXCP_IRQ;
440 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000441 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000442 }
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800443#elif defined(TARGET_UNICORE32)
444 if (interrupt_request & CPU_INTERRUPT_HARD
445 && !(env->uncached_asr & ASR_I)) {
Guan Xuetaod48813d2012-08-10 14:42:23 +0800446 env->exception_index = UC32_EXCP_INTR;
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800447 do_interrupt(env);
448 next_tb = 0;
449 }
bellardfdf9b3e2006-04-27 21:07:38 +0000450#elif defined(TARGET_SH4)
thse96e2042007-12-02 06:18:24 +0000451 if (interrupt_request & CPU_INTERRUPT_HARD) {
452 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000453 next_tb = 0;
thse96e2042007-12-02 06:18:24 +0000454 }
j_mayereddf68a2007-04-05 07:22:49 +0000455#elif defined(TARGET_ALPHA)
Richard Henderson6a80e082011-04-18 15:09:09 -0700456 {
457 int idx = -1;
458 /* ??? This hard-codes the OSF/1 interrupt levels. */
陳韋任e965fc32012-02-06 14:02:55 +0800459 switch (env->pal_mode ? 7 : env->ps & PS_INT_MASK) {
Richard Henderson6a80e082011-04-18 15:09:09 -0700460 case 0 ... 3:
461 if (interrupt_request & CPU_INTERRUPT_HARD) {
462 idx = EXCP_DEV_INTERRUPT;
463 }
464 /* FALLTHRU */
465 case 4:
466 if (interrupt_request & CPU_INTERRUPT_TIMER) {
467 idx = EXCP_CLK_INTERRUPT;
468 }
469 /* FALLTHRU */
470 case 5:
471 if (interrupt_request & CPU_INTERRUPT_SMP) {
472 idx = EXCP_SMP_INTERRUPT;
473 }
474 /* FALLTHRU */
475 case 6:
476 if (interrupt_request & CPU_INTERRUPT_MCHK) {
477 idx = EXCP_MCHK;
478 }
479 }
480 if (idx >= 0) {
481 env->exception_index = idx;
482 env->error_code = 0;
483 do_interrupt(env);
484 next_tb = 0;
485 }
j_mayereddf68a2007-04-05 07:22:49 +0000486 }
thsf1ccf902007-10-08 13:16:14 +0000487#elif defined(TARGET_CRIS)
edgar_igl1b1a38b2008-06-09 23:18:06 +0000488 if (interrupt_request & CPU_INTERRUPT_HARD
Edgar E. Iglesiasfb9fb692010-02-15 11:17:33 +0100489 && (env->pregs[PR_CCS] & I_FLAG)
490 && !env->locked_irq) {
edgar_igl1b1a38b2008-06-09 23:18:06 +0000491 env->exception_index = EXCP_IRQ;
492 do_interrupt(env);
493 next_tb = 0;
494 }
Lars Persson82193142012-06-14 16:23:55 +0200495 if (interrupt_request & CPU_INTERRUPT_NMI) {
496 unsigned int m_flag_archval;
497 if (env->pregs[PR_VR] < 32) {
498 m_flag_archval = M_FLAG_V10;
499 } else {
500 m_flag_archval = M_FLAG_V32;
501 }
502 if ((env->pregs[PR_CCS] & m_flag_archval)) {
503 env->exception_index = EXCP_NMI;
504 do_interrupt(env);
505 next_tb = 0;
506 }
thsf1ccf902007-10-08 13:16:14 +0000507 }
pbrook06338792007-05-23 19:58:11 +0000508#elif defined(TARGET_M68K)
509 if (interrupt_request & CPU_INTERRUPT_HARD
510 && ((env->sr & SR_I) >> SR_I_SHIFT)
511 < env->pending_level) {
512 /* Real hardware gets the interrupt vector via an
513 IACK cycle at this point. Current emulated
514 hardware doesn't rely on this, so we
515 provide/save the vector when the interrupt is
516 first signalled. */
517 env->exception_index = env->pending_vector;
Blue Swirl3c688822011-05-21 07:55:24 +0000518 do_interrupt_m68k_hardirq(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000519 next_tb = 0;
pbrook06338792007-05-23 19:58:11 +0000520 }
Alexander Graf3110e292011-04-15 17:32:48 +0200521#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
522 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
523 (env->psw.mask & PSW_MASK_EXT)) {
524 do_interrupt(env);
525 next_tb = 0;
526 }
Max Filippov40643d72011-09-06 03:55:41 +0400527#elif defined(TARGET_XTENSA)
528 if (interrupt_request & CPU_INTERRUPT_HARD) {
529 env->exception_index = EXC_IRQ;
530 do_interrupt(env);
531 next_tb = 0;
532 }
bellard68a79312003-06-30 13:12:32 +0000533#endif
Stefan Weilff2712b2011-04-28 17:20:35 +0200534 /* Don't use the cached interrupt_request value,
bellard9d050952006-05-22 22:03:52 +0000535 do_interrupt may have updated the EXITTB flag. */
bellardb5ff1b32005-11-26 10:38:39 +0000536 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
bellardbf3e8bf2004-02-16 21:58:54 +0000537 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
538 /* ensure that no TB jump will be modified as
539 the program flow was changed */
blueswir1b5fc09a2008-05-04 06:38:18 +0000540 next_tb = 0;
bellardbf3e8bf2004-02-16 21:58:54 +0000541 }
aurel32be214e62009-03-06 21:48:00 +0000542 }
Andreas Färberfcd7d002012-12-17 08:02:44 +0100543 if (unlikely(cpu->exit_request)) {
544 cpu->exit_request = 0;
aurel32be214e62009-03-06 21:48:00 +0000545 env->exception_index = EXCP_INTERRUPT;
Blue Swirl1162c042011-05-14 12:52:35 +0000546 cpu_loop_exit(env);
bellard3fb2ded2003-06-24 13:22:59 +0000547 }
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700548#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
aliguori8fec2b82009-01-15 22:36:53 +0000549 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
bellard3fb2ded2003-06-24 13:22:59 +0000550 /* restore flags in standard format */
thsecb644f2007-06-03 18:45:53 +0000551#if defined(TARGET_I386)
Blue Swirle694d4e2011-05-16 19:38:48 +0000552 env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
553 | (DF & DF_MASK);
Peter Maydell6fd2a022012-10-05 15:04:43 +0100554 log_cpu_state(env, CPU_DUMP_CCOP);
bellard3fb2ded2003-06-24 13:22:59 +0000555 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
pbrooke6e59062006-10-22 00:18:54 +0000556#elif defined(TARGET_M68K)
557 cpu_m68k_flush_flags(env, env->cc_op);
558 env->cc_op = CC_OP_FLAGS;
559 env->sr = (env->sr & 0xffe0)
560 | env->cc_dest | (env->cc_x << 4);
aliguori93fcfe32009-01-15 22:34:14 +0000561 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000562#else
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700563 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000564#endif
bellard3fb2ded2003-06-24 13:22:59 +0000565 }
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700566#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700567 spin_lock(&tcg_ctx.tb_ctx.tb_lock);
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000568 tb = tb_find_fast(env);
pbrookd5975362008-06-07 20:50:51 +0000569 /* Note: we do it here to avoid a gcc bug on Mac OS X when
570 doing it in tb_find_slow */
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700571 if (tcg_ctx.tb_ctx.tb_invalidated_flag) {
pbrookd5975362008-06-07 20:50:51 +0000572 /* as some TB could have been invalidated because
573 of memory exceptions while generating the code, we
574 must recompute the hash index here */
575 next_tb = 0;
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700576 tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
pbrookd5975362008-06-07 20:50:51 +0000577 }
Juan Quintelaf0667e62009-07-27 16:13:05 +0200578#ifdef CONFIG_DEBUG_EXEC
Stefan Weil3ba19252012-04-12 15:44:24 +0200579 qemu_log_mask(CPU_LOG_EXEC, "Trace %p [" TARGET_FMT_lx "] %s\n",
580 tb->tc_ptr, tb->pc,
aliguori93fcfe32009-01-15 22:34:14 +0000581 lookup_symbol(tb->pc));
bellard9d27abd2003-05-10 13:13:54 +0000582#endif
bellard8a40a182005-11-20 10:35:40 +0000583 /* see if we can patch the calling TB. When the TB
584 spans two pages, we cannot safely do a direct
585 jump. */
Paolo Bonzini040f2fb2010-01-15 08:56:36 +0100586 if (next_tb != 0 && tb->page_addr[1] == -1) {
blueswir1b5fc09a2008-05-04 06:38:18 +0000587 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
bellard3fb2ded2003-06-24 13:22:59 +0000588 }
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700589 spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
malc55e8b852008-11-04 14:18:13 +0000590
591 /* cpu_interrupt might be called while translating the
592 TB, but before it is linked into a potentially
593 infinite loop and becomes env->current_tb. Avoid
594 starting execution if there is a pending interrupt. */
Andreas Färberd77953b2013-01-16 19:29:31 +0100595 cpu->current_tb = tb;
Jan Kiszkab0052d12010-06-25 16:56:50 +0200596 barrier();
Andreas Färberfcd7d002012-12-17 08:02:44 +0100597 if (likely(!cpu->exit_request)) {
pbrook2e70f6e2008-06-29 01:03:05 +0000598 tc_ptr = tb->tc_ptr;
陳韋任e965fc32012-02-06 14:02:55 +0800599 /* execute the generated code */
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000600 next_tb = tcg_qemu_tb_exec(env, tc_ptr);
pbrook2e70f6e2008-06-29 01:03:05 +0000601 if ((next_tb & 3) == 2) {
thsbf20dc02008-06-30 17:22:19 +0000602 /* Instruction counter expired. */
pbrook2e70f6e2008-06-29 01:03:05 +0000603 int insns_left;
Stefan Weil69784ea2012-03-16 23:50:54 +0100604 tb = (TranslationBlock *)(next_tb & ~3);
pbrook2e70f6e2008-06-29 01:03:05 +0000605 /* Restore PC. */
aliguori622ed362008-11-18 19:36:03 +0000606 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000607 insns_left = env->icount_decr.u32;
608 if (env->icount_extra && insns_left >= 0) {
609 /* Refill decrementer and continue execution. */
610 env->icount_extra += insns_left;
611 if (env->icount_extra > 0xffff) {
612 insns_left = 0xffff;
613 } else {
614 insns_left = env->icount_extra;
615 }
616 env->icount_extra -= insns_left;
617 env->icount_decr.u16.low = insns_left;
618 } else {
619 if (insns_left > 0) {
620 /* Execute remaining instructions. */
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000621 cpu_exec_nocache(env, insns_left, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000622 }
623 env->exception_index = EXCP_INTERRUPT;
624 next_tb = 0;
Blue Swirl1162c042011-05-14 12:52:35 +0000625 cpu_loop_exit(env);
pbrook2e70f6e2008-06-29 01:03:05 +0000626 }
627 }
628 }
Andreas Färberd77953b2013-01-16 19:29:31 +0100629 cpu->current_tb = NULL;
bellard4cbf74b2003-08-10 21:48:43 +0000630 /* reset soft MMU for next block (it can currently
631 only be set by a memory fault) */
ths50a518e2007-06-03 18:52:15 +0000632 } /* for(;;) */
Jan Kiszka0d101932011-07-02 09:50:51 +0200633 } else {
634 /* Reload env after longjmp - the compiler may have smashed all
635 * local variables as longjmp is marked 'noreturn'. */
636 env = cpu_single_env;
bellard7d132992003-03-06 23:23:54 +0000637 }
bellard3fb2ded2003-06-24 13:22:59 +0000638 } /* for(;;) */
639
bellard7d132992003-03-06 23:23:54 +0000640
bellarde4533c72003-06-15 19:51:39 +0000641#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000642 /* restore flags in standard format */
Blue Swirle694d4e2011-05-16 19:38:48 +0000643 env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
644 | (DF & DF_MASK);
bellarde4533c72003-06-15 19:51:39 +0000645#elif defined(TARGET_ARM)
bellardb7bcbe92005-02-22 19:27:29 +0000646 /* XXX: Save/restore host fpu exception state?. */
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800647#elif defined(TARGET_UNICORE32)
bellard93ac68b2003-09-30 20:57:29 +0000648#elif defined(TARGET_SPARC)
bellard67867302003-11-23 17:05:30 +0000649#elif defined(TARGET_PPC)
Michael Walle81ea0e12011-02-17 23:45:02 +0100650#elif defined(TARGET_LM32)
pbrooke6e59062006-10-22 00:18:54 +0000651#elif defined(TARGET_M68K)
652 cpu_m68k_flush_flags(env, env->cc_op);
653 env->cc_op = CC_OP_FLAGS;
654 env->sr = (env->sr & 0xffe0)
655 | env->cc_dest | (env->cc_x << 4);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200656#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000657#elif defined(TARGET_MIPS)
Jia Liue67db062012-07-20 15:50:39 +0800658#elif defined(TARGET_OPENRISC)
bellardfdf9b3e2006-04-27 21:07:38 +0000659#elif defined(TARGET_SH4)
j_mayereddf68a2007-04-05 07:22:49 +0000660#elif defined(TARGET_ALPHA)
thsf1ccf902007-10-08 13:16:14 +0000661#elif defined(TARGET_CRIS)
Alexander Graf10ec5112009-12-05 12:44:21 +0100662#elif defined(TARGET_S390X)
Max Filippov23288262011-09-06 03:55:25 +0400663#elif defined(TARGET_XTENSA)
bellardfdf9b3e2006-04-27 21:07:38 +0000664 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000665#else
666#error unsupported target CPU
667#endif
pbrook1057eaa2007-02-04 13:37:44 +0000668
bellard6a00d602005-11-21 23:25:50 +0000669 /* fail safe : never use cpu_single_env outside cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000670 cpu_single_env = NULL;
bellard7d132992003-03-06 23:23:54 +0000671 return ret;
672}