blob: cf103f227b012ceedcfd6322e78ea1ae9a9db9ec [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{
Blue Swirlcea5f9a2011-05-15 16:03:25 +000035 env->current_tb = NULL;
36 longjmp(env->jmp_env, 1);
bellarde4533c72003-06-15 19:51:39 +000037}
thsbfed01f2007-06-03 17:44:37 +000038
bellardfbf9eeb2004-04-25 21:21:33 +000039/* exit the current TB from a signal handler. The host registers are
40 restored in a state compatible with the CPU emulator
41 */
Blue Swirl9eff14f2011-05-21 08:42:35 +000042#if defined(CONFIG_SOFTMMU)
Andreas Färber9349b4f2012-03-14 01:38:32 +010043void cpu_resume_from_signal(CPUArchState *env, void *puc)
bellardfbf9eeb2004-04-25 21:21:33 +000044{
Blue Swirl9eff14f2011-05-21 08:42:35 +000045 /* XXX: restore cpu registers saved in host registers */
46
47 env->exception_index = -1;
48 longjmp(env->jmp_env, 1);
49}
Blue Swirl9eff14f2011-05-21 08:42:35 +000050#endif
bellardfbf9eeb2004-04-25 21:21:33 +000051
pbrook2e70f6e2008-06-29 01:03:05 +000052/* Execute the code without caching the generated code. An interpreter
53 could be used if available. */
Andreas Färber9349b4f2012-03-14 01:38:32 +010054static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
Blue Swirlcea5f9a2011-05-15 16:03:25 +000055 TranslationBlock *orig_tb)
pbrook2e70f6e2008-06-29 01:03:05 +000056{
Stefan Weil69784ea2012-03-16 23:50:54 +010057 tcg_target_ulong next_tb;
pbrook2e70f6e2008-06-29 01:03:05 +000058 TranslationBlock *tb;
59
60 /* Should never happen.
61 We only end up here when an existing TB is too long. */
62 if (max_cycles > CF_COUNT_MASK)
63 max_cycles = CF_COUNT_MASK;
64
65 tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
66 max_cycles);
67 env->current_tb = tb;
68 /* execute the generated code */
Blue Swirlcea5f9a2011-05-15 16:03:25 +000069 next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
Paolo Bonzini1c3569f2010-01-15 09:42:07 +010070 env->current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +000071
72 if ((next_tb & 3) == 2) {
73 /* Restore PC. This may happen if async event occurs before
74 the TB starts executing. */
aliguori622ed362008-11-18 19:36:03 +000075 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +000076 }
77 tb_phys_invalidate(tb, -1);
78 tb_free(tb);
79}
80
Andreas Färber9349b4f2012-03-14 01:38:32 +010081static TranslationBlock *tb_find_slow(CPUArchState *env,
Blue Swirlcea5f9a2011-05-15 16:03:25 +000082 target_ulong pc,
bellard8a40a182005-11-20 10:35:40 +000083 target_ulong cs_base,
j_mayerc0686882007-09-20 22:47:42 +000084 uint64_t flags)
bellard8a40a182005-11-20 10:35:40 +000085{
86 TranslationBlock *tb, **ptb1;
bellard8a40a182005-11-20 10:35:40 +000087 unsigned int h;
Blue Swirl337fc752011-09-04 11:06:22 +000088 tb_page_addr_t phys_pc, phys_page1;
Paul Brook41c1b1c2010-03-12 16:54:58 +000089 target_ulong virt_page2;
ths3b46e622007-09-17 08:09:54 +000090
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +070091 tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
ths3b46e622007-09-17 08:09:54 +000092
bellard8a40a182005-11-20 10:35:40 +000093 /* find translated block using physical mappings */
Paul Brook41c1b1c2010-03-12 16:54:58 +000094 phys_pc = get_page_addr_code(env, pc);
bellard8a40a182005-11-20 10:35:40 +000095 phys_page1 = phys_pc & TARGET_PAGE_MASK;
bellard8a40a182005-11-20 10:35:40 +000096 h = tb_phys_hash_func(phys_pc);
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +070097 ptb1 = &tcg_ctx.tb_ctx.tb_phys_hash[h];
bellard8a40a182005-11-20 10:35:40 +000098 for(;;) {
99 tb = *ptb1;
100 if (!tb)
101 goto not_found;
ths5fafdf22007-09-16 21:08:06 +0000102 if (tb->pc == pc &&
bellard8a40a182005-11-20 10:35:40 +0000103 tb->page_addr[0] == phys_page1 &&
ths5fafdf22007-09-16 21:08:06 +0000104 tb->cs_base == cs_base &&
bellard8a40a182005-11-20 10:35:40 +0000105 tb->flags == flags) {
106 /* check next page if needed */
107 if (tb->page_addr[1] != -1) {
Blue Swirl337fc752011-09-04 11:06:22 +0000108 tb_page_addr_t phys_page2;
109
ths5fafdf22007-09-16 21:08:06 +0000110 virt_page2 = (pc & TARGET_PAGE_MASK) +
bellard8a40a182005-11-20 10:35:40 +0000111 TARGET_PAGE_SIZE;
Paul Brook41c1b1c2010-03-12 16:54:58 +0000112 phys_page2 = get_page_addr_code(env, virt_page2);
bellard8a40a182005-11-20 10:35:40 +0000113 if (tb->page_addr[1] == phys_page2)
114 goto found;
115 } else {
116 goto found;
117 }
118 }
119 ptb1 = &tb->phys_hash_next;
120 }
121 not_found:
pbrook2e70f6e2008-06-29 01:03:05 +0000122 /* if no translated code available, then translate it now */
123 tb = tb_gen_code(env, pc, cs_base, flags, 0);
ths3b46e622007-09-17 08:09:54 +0000124
bellard8a40a182005-11-20 10:35:40 +0000125 found:
Kirill Batuzov2c90fe22010-12-02 16:12:46 +0300126 /* Move the last found TB to the head of the list */
127 if (likely(*ptb1)) {
128 *ptb1 = tb->phys_hash_next;
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700129 tb->phys_hash_next = tcg_ctx.tb_ctx.tb_phys_hash[h];
130 tcg_ctx.tb_ctx.tb_phys_hash[h] = tb;
Kirill Batuzov2c90fe22010-12-02 16:12:46 +0300131 }
bellard8a40a182005-11-20 10:35:40 +0000132 /* we add the TB in the virtual pc hash table */
133 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
bellard8a40a182005-11-20 10:35:40 +0000134 return tb;
135}
136
Andreas Färber9349b4f2012-03-14 01:38:32 +0100137static inline TranslationBlock *tb_find_fast(CPUArchState *env)
bellard8a40a182005-11-20 10:35:40 +0000138{
139 TranslationBlock *tb;
140 target_ulong cs_base, pc;
aliguori6b917542008-11-18 19:46:41 +0000141 int flags;
bellard8a40a182005-11-20 10:35:40 +0000142
143 /* we record a subset of the CPU state. It will
144 always be the same before a given translated block
145 is executed. */
aliguori6b917542008-11-18 19:46:41 +0000146 cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
bellardbce61842008-02-01 22:18:51 +0000147 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
ths551bd272008-07-03 17:57:36 +0000148 if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
149 tb->flags != flags)) {
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000150 tb = tb_find_slow(env, pc, cs_base, flags);
bellard8a40a182005-11-20 10:35:40 +0000151 }
152 return tb;
153}
154
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100155static CPUDebugExcpHandler *debug_excp_handler;
156
Igor Mammedov84e3b602012-06-21 18:29:38 +0200157void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100158{
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100159 debug_excp_handler = handler;
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100160}
161
Andreas Färber9349b4f2012-03-14 01:38:32 +0100162static void cpu_handle_debug_exception(CPUArchState *env)
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100163{
164 CPUWatchpoint *wp;
165
166 if (!env->watchpoint_hit) {
167 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
168 wp->flags &= ~BP_WATCHPOINT_HIT;
169 }
170 }
171 if (debug_excp_handler) {
172 debug_excp_handler(env);
173 }
174}
175
bellard7d132992003-03-06 23:23:54 +0000176/* main execution loop */
177
Marcelo Tosatti1a28cac2010-05-04 09:45:20 -0300178volatile sig_atomic_t exit_request;
179
Andreas Färber9349b4f2012-03-14 01:38:32 +0100180int cpu_exec(CPUArchState *env)
bellard7d132992003-03-06 23:23:54 +0000181{
Andreas Färberc356a1b2012-05-04 19:39:23 +0200182 CPUState *cpu = ENV_GET_CPU(env);
bellard8a40a182005-11-20 10:35:40 +0000183 int ret, interrupt_request;
bellard8a40a182005-11-20 10:35:40 +0000184 TranslationBlock *tb;
bellardc27004e2005-01-03 23:35:10 +0000185 uint8_t *tc_ptr;
Stefan Weil69784ea2012-03-16 23:50:54 +0100186 tcg_target_ulong next_tb;
bellard8c6939c2003-06-09 15:28:00 +0000187
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000188 if (env->halted) {
Andreas Färber3993c6b2012-05-03 06:43:49 +0200189 if (!cpu_has_work(cpu)) {
Paolo Bonzinieda48c32011-03-12 17:43:56 +0100190 return EXCP_HALTED;
191 }
192
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000193 env->halted = 0;
Paolo Bonzinieda48c32011-03-12 17:43:56 +0100194 }
bellard5a1e3cf2005-11-23 21:02:53 +0000195
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000196 cpu_single_env = env;
bellarde4533c72003-06-15 19:51:39 +0000197
Jan Kiszkac629a4b2010-06-25 16:56:52 +0200198 if (unlikely(exit_request)) {
Andreas Färberfcd7d002012-12-17 08:02:44 +0100199 cpu->exit_request = 1;
Marcelo Tosatti1a28cac2010-05-04 09:45:20 -0300200 }
201
thsecb644f2007-06-03 18:45:53 +0000202#if defined(TARGET_I386)
Jan Kiszka6792a572011-02-07 12:19:18 +0100203 /* put eflags in CPU temporary format */
204 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
205 DF = 1 - (2 * ((env->eflags >> 10) & 1));
206 CC_OP = CC_OP_EFLAGS;
207 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellard93ac68b2003-09-30 20:57:29 +0000208#elif defined(TARGET_SPARC)
pbrooke6e59062006-10-22 00:18:54 +0000209#elif defined(TARGET_M68K)
210 env->cc_op = CC_OP_FLAGS;
211 env->cc_dest = env->sr & 0xf;
212 env->cc_x = (env->sr >> 4) & 1;
thsecb644f2007-06-03 18:45:53 +0000213#elif defined(TARGET_ALPHA)
214#elif defined(TARGET_ARM)
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800215#elif defined(TARGET_UNICORE32)
thsecb644f2007-06-03 18:45:53 +0000216#elif defined(TARGET_PPC)
Elie Richa4e85f822011-07-22 05:58:39 +0000217 env->reserve_addr = -1;
Michael Walle81ea0e12011-02-17 23:45:02 +0100218#elif defined(TARGET_LM32)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200219#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000220#elif defined(TARGET_MIPS)
Jia Liue67db062012-07-20 15:50:39 +0800221#elif defined(TARGET_OPENRISC)
bellardfdf9b3e2006-04-27 21:07:38 +0000222#elif defined(TARGET_SH4)
thsf1ccf902007-10-08 13:16:14 +0000223#elif defined(TARGET_CRIS)
Alexander Graf10ec5112009-12-05 12:44:21 +0100224#elif defined(TARGET_S390X)
Max Filippov23288262011-09-06 03:55:25 +0400225#elif defined(TARGET_XTENSA)
bellardfdf9b3e2006-04-27 21:07:38 +0000226 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000227#else
228#error unsupported target CPU
229#endif
bellard3fb2ded2003-06-24 13:22:59 +0000230 env->exception_index = -1;
bellard9d27abd2003-05-10 13:13:54 +0000231
bellard7d132992003-03-06 23:23:54 +0000232 /* prepare setjmp context for exception handling */
bellard3fb2ded2003-06-24 13:22:59 +0000233 for(;;) {
234 if (setjmp(env->jmp_env) == 0) {
235 /* if an exception is pending, we execute it here */
236 if (env->exception_index >= 0) {
237 if (env->exception_index >= EXCP_INTERRUPT) {
238 /* exit request from the cpu execution loop */
239 ret = env->exception_index;
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100240 if (ret == EXCP_DEBUG) {
241 cpu_handle_debug_exception(env);
242 }
bellard3fb2ded2003-06-24 13:22:59 +0000243 break;
aurel3272d239e2009-01-14 19:40:27 +0000244 } else {
245#if defined(CONFIG_USER_ONLY)
bellard3fb2ded2003-06-24 13:22:59 +0000246 /* if user mode only, we simulate a fake exception
ths9f083492006-12-07 18:28:42 +0000247 which will be handled outside the cpu execution
bellard3fb2ded2003-06-24 13:22:59 +0000248 loop */
bellard83479e72003-06-25 16:12:37 +0000249#if defined(TARGET_I386)
Blue Swirle694d4e2011-05-16 19:38:48 +0000250 do_interrupt(env);
bellard83479e72003-06-25 16:12:37 +0000251#endif
bellard3fb2ded2003-06-24 13:22:59 +0000252 ret = env->exception_index;
253 break;
aurel3272d239e2009-01-14 19:40:27 +0000254#else
Blue Swirle694d4e2011-05-16 19:38:48 +0000255 do_interrupt(env);
Paolo Bonzini301d2902010-01-15 09:41:01 +0100256 env->exception_index = -1;
aurel3272d239e2009-01-14 19:40:27 +0000257#endif
bellard3fb2ded2003-06-24 13:22:59 +0000258 }
ths5fafdf22007-09-16 21:08:06 +0000259 }
bellard9df217a2005-02-10 22:05:51 +0000260
blueswir1b5fc09a2008-05-04 06:38:18 +0000261 next_tb = 0; /* force lookup of first TB */
bellard3fb2ded2003-06-24 13:22:59 +0000262 for(;;) {
bellard68a79312003-06-30 13:12:32 +0000263 interrupt_request = env->interrupt_request;
malce1638bd2008-11-06 18:54:46 +0000264 if (unlikely(interrupt_request)) {
265 if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
266 /* Mask out external interrupts for this step. */
Richard Henderson3125f762011-05-04 13:34:25 -0700267 interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
malce1638bd2008-11-06 18:54:46 +0000268 }
pbrook6658ffb2007-03-16 23:58:11 +0000269 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
270 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
271 env->exception_index = EXCP_DEBUG;
Blue Swirl1162c042011-05-14 12:52:35 +0000272 cpu_loop_exit(env);
pbrook6658ffb2007-03-16 23:58:11 +0000273 }
balroga90b7312007-05-01 01:28:01 +0000274#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200275 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800276 defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
balroga90b7312007-05-01 01:28:01 +0000277 if (interrupt_request & CPU_INTERRUPT_HALT) {
278 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
279 env->halted = 1;
280 env->exception_index = EXCP_HLT;
Blue Swirl1162c042011-05-14 12:52:35 +0000281 cpu_loop_exit(env);
balroga90b7312007-05-01 01:28:01 +0000282 }
283#endif
bellard68a79312003-06-30 13:12:32 +0000284#if defined(TARGET_I386)
Jan Kiszka5d62c432012-07-09 16:42:32 +0200285#if !defined(CONFIG_USER_ONLY)
286 if (interrupt_request & CPU_INTERRUPT_POLL) {
287 env->interrupt_request &= ~CPU_INTERRUPT_POLL;
288 apic_poll_irq(env->apic_state);
289 }
290#endif
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300291 if (interrupt_request & CPU_INTERRUPT_INIT) {
Blue Swirl77b2bc22012-04-28 19:35:10 +0000292 cpu_svm_check_intercept_param(env, SVM_EXIT_INIT,
293 0);
Andreas Färber232fc232012-05-05 01:14:41 +0200294 do_cpu_init(x86_env_get_cpu(env));
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300295 env->exception_index = EXCP_HALTED;
Blue Swirl1162c042011-05-14 12:52:35 +0000296 cpu_loop_exit(env);
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300297 } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
Andreas Färber232fc232012-05-05 01:14:41 +0200298 do_cpu_sipi(x86_env_get_cpu(env));
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300299 } else if (env->hflags2 & HF2_GIF_MASK) {
bellarddb620f42008-06-04 17:02:19 +0000300 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
301 !(env->hflags & HF_SMM_MASK)) {
Blue Swirl77b2bc22012-04-28 19:35:10 +0000302 cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,
303 0);
bellarddb620f42008-06-04 17:02:19 +0000304 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
Blue Swirle694d4e2011-05-16 19:38:48 +0000305 do_smm_enter(env);
bellarddb620f42008-06-04 17:02:19 +0000306 next_tb = 0;
307 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
308 !(env->hflags2 & HF2_NMI_MASK)) {
309 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
310 env->hflags2 |= HF2_NMI_MASK;
Blue Swirle694d4e2011-05-16 19:38:48 +0000311 do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
bellarddb620f42008-06-04 17:02:19 +0000312 next_tb = 0;
陳韋任e965fc32012-02-06 14:02:55 +0800313 } else if (interrupt_request & CPU_INTERRUPT_MCE) {
Huang Ying79c4f6b2009-06-23 10:05:14 +0800314 env->interrupt_request &= ~CPU_INTERRUPT_MCE;
Blue Swirle694d4e2011-05-16 19:38:48 +0000315 do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
Huang Ying79c4f6b2009-06-23 10:05:14 +0800316 next_tb = 0;
bellarddb620f42008-06-04 17:02:19 +0000317 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
318 (((env->hflags2 & HF2_VINTR_MASK) &&
319 (env->hflags2 & HF2_HIF_MASK)) ||
320 (!(env->hflags2 & HF2_VINTR_MASK) &&
321 (env->eflags & IF_MASK &&
322 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
323 int intno;
Blue Swirl77b2bc22012-04-28 19:35:10 +0000324 cpu_svm_check_intercept_param(env, SVM_EXIT_INTR,
325 0);
bellarddb620f42008-06-04 17:02:19 +0000326 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
327 intno = cpu_get_pic_interrupt(env);
malc4f213872012-08-27 18:33:12 +0400328 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
329 do_interrupt_x86_hardirq(env, intno, 1);
330 /* ensure that no TB jump will be modified as
331 the program flow was changed */
332 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000333#if !defined(CONFIG_USER_ONLY)
bellarddb620f42008-06-04 17:02:19 +0000334 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
335 (env->eflags & IF_MASK) &&
336 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
337 int intno;
338 /* FIXME: this should respect TPR */
Blue Swirl77b2bc22012-04-28 19:35:10 +0000339 cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR,
340 0);
bellarddb620f42008-06-04 17:02:19 +0000341 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
aliguori93fcfe32009-01-15 22:34:14 +0000342 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
Blue Swirle694d4e2011-05-16 19:38:48 +0000343 do_interrupt_x86_hardirq(env, intno, 1);
aurel32d40c54d2008-12-13 12:33:02 +0000344 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
bellarddb620f42008-06-04 17:02:19 +0000345 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000346#endif
bellarddb620f42008-06-04 17:02:19 +0000347 }
bellard68a79312003-06-30 13:12:32 +0000348 }
bellardce097762004-01-04 23:53:18 +0000349#elif defined(TARGET_PPC)
bellard9fddaa02004-05-21 12:59:32 +0000350 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
Andreas Färberc356a1b2012-05-04 19:39:23 +0200351 cpu_reset(cpu);
bellard9fddaa02004-05-21 12:59:32 +0000352 }
j_mayer47103572007-03-30 09:38:04 +0000353 if (interrupt_request & CPU_INTERRUPT_HARD) {
j_mayere9df0142007-04-09 22:45:36 +0000354 ppc_hw_interrupt(env);
355 if (env->pending_interrupts == 0)
356 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
blueswir1b5fc09a2008-05-04 06:38:18 +0000357 next_tb = 0;
bellardce097762004-01-04 23:53:18 +0000358 }
Michael Walle81ea0e12011-02-17 23:45:02 +0100359#elif defined(TARGET_LM32)
360 if ((interrupt_request & CPU_INTERRUPT_HARD)
361 && (env->ie & IE_IE)) {
362 env->exception_index = EXCP_IRQ;
363 do_interrupt(env);
364 next_tb = 0;
365 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200366#elif defined(TARGET_MICROBLAZE)
367 if ((interrupt_request & CPU_INTERRUPT_HARD)
368 && (env->sregs[SR_MSR] & MSR_IE)
369 && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
370 && !(env->iflags & (D_FLAG | IMM_FLAG))) {
371 env->exception_index = EXCP_IRQ;
372 do_interrupt(env);
373 next_tb = 0;
374 }
bellard6af0bf92005-07-02 14:58:51 +0000375#elif defined(TARGET_MIPS)
376 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
Aurelien Jarno4cdc1cd2010-12-25 22:56:32 +0100377 cpu_mips_hw_interrupts_pending(env)) {
bellard6af0bf92005-07-02 14:58:51 +0000378 /* Raise it */
379 env->exception_index = EXCP_EXT_INTERRUPT;
380 env->error_code = 0;
381 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000382 next_tb = 0;
bellard6af0bf92005-07-02 14:58:51 +0000383 }
Jia Liub6a71ef2012-07-20 15:50:41 +0800384#elif defined(TARGET_OPENRISC)
385 {
386 int idx = -1;
387 if ((interrupt_request & CPU_INTERRUPT_HARD)
388 && (env->sr & SR_IEE)) {
389 idx = EXCP_INT;
390 }
391 if ((interrupt_request & CPU_INTERRUPT_TIMER)
392 && (env->sr & SR_TEE)) {
393 idx = EXCP_TICK;
394 }
395 if (idx >= 0) {
396 env->exception_index = idx;
397 do_interrupt(env);
398 next_tb = 0;
399 }
400 }
bellarde95c8d52004-09-30 22:22:08 +0000401#elif defined(TARGET_SPARC)
Igor V. Kovalenkod532b262010-01-07 23:28:31 +0300402 if (interrupt_request & CPU_INTERRUPT_HARD) {
403 if (cpu_interrupts_enabled(env) &&
404 env->interrupt_index > 0) {
405 int pil = env->interrupt_index & 0xf;
406 int type = env->interrupt_index & 0xf0;
bellard66321a12005-04-06 20:47:48 +0000407
Igor V. Kovalenkod532b262010-01-07 23:28:31 +0300408 if (((type == TT_EXTINT) &&
409 cpu_pil_allowed(env, pil)) ||
410 type != TT_EXTINT) {
411 env->exception_index = env->interrupt_index;
412 do_interrupt(env);
413 next_tb = 0;
414 }
415 }
陳韋任e965fc32012-02-06 14:02:55 +0800416 }
bellardb5ff1b32005-11-26 10:38:39 +0000417#elif defined(TARGET_ARM)
418 if (interrupt_request & CPU_INTERRUPT_FIQ
419 && !(env->uncached_cpsr & CPSR_F)) {
420 env->exception_index = EXCP_FIQ;
421 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000422 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000423 }
pbrook9ee6e8b2007-11-11 00:04:49 +0000424 /* ARMv7-M interrupt return works by loading a magic value
425 into the PC. On real hardware the load causes the
426 return to occur. The qemu implementation performs the
427 jump normally, then does the exception return when the
428 CPU tries to execute code at the magic address.
429 This will cause the magic PC value to be pushed to
Stefan Weila1c72732011-04-28 17:20:38 +0200430 the stack if an interrupt occurred at the wrong time.
pbrook9ee6e8b2007-11-11 00:04:49 +0000431 We avoid this by disabling interrupts when
432 pc contains a magic address. */
bellardb5ff1b32005-11-26 10:38:39 +0000433 if (interrupt_request & CPU_INTERRUPT_HARD
pbrook9ee6e8b2007-11-11 00:04:49 +0000434 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
435 || !(env->uncached_cpsr & CPSR_I))) {
bellardb5ff1b32005-11-26 10:38:39 +0000436 env->exception_index = EXCP_IRQ;
437 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000438 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000439 }
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800440#elif defined(TARGET_UNICORE32)
441 if (interrupt_request & CPU_INTERRUPT_HARD
442 && !(env->uncached_asr & ASR_I)) {
Guan Xuetaod48813d2012-08-10 14:42:23 +0800443 env->exception_index = UC32_EXCP_INTR;
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800444 do_interrupt(env);
445 next_tb = 0;
446 }
bellardfdf9b3e2006-04-27 21:07:38 +0000447#elif defined(TARGET_SH4)
thse96e2042007-12-02 06:18:24 +0000448 if (interrupt_request & CPU_INTERRUPT_HARD) {
449 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000450 next_tb = 0;
thse96e2042007-12-02 06:18:24 +0000451 }
j_mayereddf68a2007-04-05 07:22:49 +0000452#elif defined(TARGET_ALPHA)
Richard Henderson6a80e082011-04-18 15:09:09 -0700453 {
454 int idx = -1;
455 /* ??? This hard-codes the OSF/1 interrupt levels. */
陳韋任e965fc32012-02-06 14:02:55 +0800456 switch (env->pal_mode ? 7 : env->ps & PS_INT_MASK) {
Richard Henderson6a80e082011-04-18 15:09:09 -0700457 case 0 ... 3:
458 if (interrupt_request & CPU_INTERRUPT_HARD) {
459 idx = EXCP_DEV_INTERRUPT;
460 }
461 /* FALLTHRU */
462 case 4:
463 if (interrupt_request & CPU_INTERRUPT_TIMER) {
464 idx = EXCP_CLK_INTERRUPT;
465 }
466 /* FALLTHRU */
467 case 5:
468 if (interrupt_request & CPU_INTERRUPT_SMP) {
469 idx = EXCP_SMP_INTERRUPT;
470 }
471 /* FALLTHRU */
472 case 6:
473 if (interrupt_request & CPU_INTERRUPT_MCHK) {
474 idx = EXCP_MCHK;
475 }
476 }
477 if (idx >= 0) {
478 env->exception_index = idx;
479 env->error_code = 0;
480 do_interrupt(env);
481 next_tb = 0;
482 }
j_mayereddf68a2007-04-05 07:22:49 +0000483 }
thsf1ccf902007-10-08 13:16:14 +0000484#elif defined(TARGET_CRIS)
edgar_igl1b1a38b2008-06-09 23:18:06 +0000485 if (interrupt_request & CPU_INTERRUPT_HARD
Edgar E. Iglesiasfb9fb692010-02-15 11:17:33 +0100486 && (env->pregs[PR_CCS] & I_FLAG)
487 && !env->locked_irq) {
edgar_igl1b1a38b2008-06-09 23:18:06 +0000488 env->exception_index = EXCP_IRQ;
489 do_interrupt(env);
490 next_tb = 0;
491 }
Lars Persson82193142012-06-14 16:23:55 +0200492 if (interrupt_request & CPU_INTERRUPT_NMI) {
493 unsigned int m_flag_archval;
494 if (env->pregs[PR_VR] < 32) {
495 m_flag_archval = M_FLAG_V10;
496 } else {
497 m_flag_archval = M_FLAG_V32;
498 }
499 if ((env->pregs[PR_CCS] & m_flag_archval)) {
500 env->exception_index = EXCP_NMI;
501 do_interrupt(env);
502 next_tb = 0;
503 }
thsf1ccf902007-10-08 13:16:14 +0000504 }
pbrook06338792007-05-23 19:58:11 +0000505#elif defined(TARGET_M68K)
506 if (interrupt_request & CPU_INTERRUPT_HARD
507 && ((env->sr & SR_I) >> SR_I_SHIFT)
508 < env->pending_level) {
509 /* Real hardware gets the interrupt vector via an
510 IACK cycle at this point. Current emulated
511 hardware doesn't rely on this, so we
512 provide/save the vector when the interrupt is
513 first signalled. */
514 env->exception_index = env->pending_vector;
Blue Swirl3c688822011-05-21 07:55:24 +0000515 do_interrupt_m68k_hardirq(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000516 next_tb = 0;
pbrook06338792007-05-23 19:58:11 +0000517 }
Alexander Graf3110e292011-04-15 17:32:48 +0200518#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
519 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
520 (env->psw.mask & PSW_MASK_EXT)) {
521 do_interrupt(env);
522 next_tb = 0;
523 }
Max Filippov40643d72011-09-06 03:55:41 +0400524#elif defined(TARGET_XTENSA)
525 if (interrupt_request & CPU_INTERRUPT_HARD) {
526 env->exception_index = EXC_IRQ;
527 do_interrupt(env);
528 next_tb = 0;
529 }
bellard68a79312003-06-30 13:12:32 +0000530#endif
Stefan Weilff2712b2011-04-28 17:20:35 +0200531 /* Don't use the cached interrupt_request value,
bellard9d050952006-05-22 22:03:52 +0000532 do_interrupt may have updated the EXITTB flag. */
bellardb5ff1b32005-11-26 10:38:39 +0000533 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
bellardbf3e8bf2004-02-16 21:58:54 +0000534 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
535 /* ensure that no TB jump will be modified as
536 the program flow was changed */
blueswir1b5fc09a2008-05-04 06:38:18 +0000537 next_tb = 0;
bellardbf3e8bf2004-02-16 21:58:54 +0000538 }
aurel32be214e62009-03-06 21:48:00 +0000539 }
Andreas Färberfcd7d002012-12-17 08:02:44 +0100540 if (unlikely(cpu->exit_request)) {
541 cpu->exit_request = 0;
aurel32be214e62009-03-06 21:48:00 +0000542 env->exception_index = EXCP_INTERRUPT;
Blue Swirl1162c042011-05-14 12:52:35 +0000543 cpu_loop_exit(env);
bellard3fb2ded2003-06-24 13:22:59 +0000544 }
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700545#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
aliguori8fec2b82009-01-15 22:36:53 +0000546 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
bellard3fb2ded2003-06-24 13:22:59 +0000547 /* restore flags in standard format */
thsecb644f2007-06-03 18:45:53 +0000548#if defined(TARGET_I386)
Blue Swirle694d4e2011-05-16 19:38:48 +0000549 env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
550 | (DF & DF_MASK);
Peter Maydell6fd2a022012-10-05 15:04:43 +0100551 log_cpu_state(env, CPU_DUMP_CCOP);
bellard3fb2ded2003-06-24 13:22:59 +0000552 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
pbrooke6e59062006-10-22 00:18:54 +0000553#elif defined(TARGET_M68K)
554 cpu_m68k_flush_flags(env, env->cc_op);
555 env->cc_op = CC_OP_FLAGS;
556 env->sr = (env->sr & 0xffe0)
557 | env->cc_dest | (env->cc_x << 4);
aliguori93fcfe32009-01-15 22:34:14 +0000558 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000559#else
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700560 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000561#endif
bellard3fb2ded2003-06-24 13:22:59 +0000562 }
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700563#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700564 spin_lock(&tcg_ctx.tb_ctx.tb_lock);
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000565 tb = tb_find_fast(env);
pbrookd5975362008-06-07 20:50:51 +0000566 /* Note: we do it here to avoid a gcc bug on Mac OS X when
567 doing it in tb_find_slow */
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700568 if (tcg_ctx.tb_ctx.tb_invalidated_flag) {
pbrookd5975362008-06-07 20:50:51 +0000569 /* as some TB could have been invalidated because
570 of memory exceptions while generating the code, we
571 must recompute the hash index here */
572 next_tb = 0;
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700573 tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
pbrookd5975362008-06-07 20:50:51 +0000574 }
Juan Quintelaf0667e62009-07-27 16:13:05 +0200575#ifdef CONFIG_DEBUG_EXEC
Stefan Weil3ba19252012-04-12 15:44:24 +0200576 qemu_log_mask(CPU_LOG_EXEC, "Trace %p [" TARGET_FMT_lx "] %s\n",
577 tb->tc_ptr, tb->pc,
aliguori93fcfe32009-01-15 22:34:14 +0000578 lookup_symbol(tb->pc));
bellard9d27abd2003-05-10 13:13:54 +0000579#endif
bellard8a40a182005-11-20 10:35:40 +0000580 /* see if we can patch the calling TB. When the TB
581 spans two pages, we cannot safely do a direct
582 jump. */
Paolo Bonzini040f2fb2010-01-15 08:56:36 +0100583 if (next_tb != 0 && tb->page_addr[1] == -1) {
blueswir1b5fc09a2008-05-04 06:38:18 +0000584 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
bellard3fb2ded2003-06-24 13:22:59 +0000585 }
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700586 spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
malc55e8b852008-11-04 14:18:13 +0000587
588 /* cpu_interrupt might be called while translating the
589 TB, but before it is linked into a potentially
590 infinite loop and becomes env->current_tb. Avoid
591 starting execution if there is a pending interrupt. */
Jan Kiszkab0052d12010-06-25 16:56:50 +0200592 env->current_tb = tb;
593 barrier();
Andreas Färberfcd7d002012-12-17 08:02:44 +0100594 if (likely(!cpu->exit_request)) {
pbrook2e70f6e2008-06-29 01:03:05 +0000595 tc_ptr = tb->tc_ptr;
陳韋任e965fc32012-02-06 14:02:55 +0800596 /* execute the generated code */
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000597 next_tb = tcg_qemu_tb_exec(env, tc_ptr);
pbrook2e70f6e2008-06-29 01:03:05 +0000598 if ((next_tb & 3) == 2) {
thsbf20dc02008-06-30 17:22:19 +0000599 /* Instruction counter expired. */
pbrook2e70f6e2008-06-29 01:03:05 +0000600 int insns_left;
Stefan Weil69784ea2012-03-16 23:50:54 +0100601 tb = (TranslationBlock *)(next_tb & ~3);
pbrook2e70f6e2008-06-29 01:03:05 +0000602 /* Restore PC. */
aliguori622ed362008-11-18 19:36:03 +0000603 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000604 insns_left = env->icount_decr.u32;
605 if (env->icount_extra && insns_left >= 0) {
606 /* Refill decrementer and continue execution. */
607 env->icount_extra += insns_left;
608 if (env->icount_extra > 0xffff) {
609 insns_left = 0xffff;
610 } else {
611 insns_left = env->icount_extra;
612 }
613 env->icount_extra -= insns_left;
614 env->icount_decr.u16.low = insns_left;
615 } else {
616 if (insns_left > 0) {
617 /* Execute remaining instructions. */
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000618 cpu_exec_nocache(env, insns_left, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000619 }
620 env->exception_index = EXCP_INTERRUPT;
621 next_tb = 0;
Blue Swirl1162c042011-05-14 12:52:35 +0000622 cpu_loop_exit(env);
pbrook2e70f6e2008-06-29 01:03:05 +0000623 }
624 }
625 }
Jan Kiszkab0052d12010-06-25 16:56:50 +0200626 env->current_tb = NULL;
bellard4cbf74b2003-08-10 21:48:43 +0000627 /* reset soft MMU for next block (it can currently
628 only be set by a memory fault) */
ths50a518e2007-06-03 18:52:15 +0000629 } /* for(;;) */
Jan Kiszka0d101932011-07-02 09:50:51 +0200630 } else {
631 /* Reload env after longjmp - the compiler may have smashed all
632 * local variables as longjmp is marked 'noreturn'. */
633 env = cpu_single_env;
bellard7d132992003-03-06 23:23:54 +0000634 }
bellard3fb2ded2003-06-24 13:22:59 +0000635 } /* for(;;) */
636
bellard7d132992003-03-06 23:23:54 +0000637
bellarde4533c72003-06-15 19:51:39 +0000638#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000639 /* restore flags in standard format */
Blue Swirle694d4e2011-05-16 19:38:48 +0000640 env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
641 | (DF & DF_MASK);
bellarde4533c72003-06-15 19:51:39 +0000642#elif defined(TARGET_ARM)
bellardb7bcbe92005-02-22 19:27:29 +0000643 /* XXX: Save/restore host fpu exception state?. */
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800644#elif defined(TARGET_UNICORE32)
bellard93ac68b2003-09-30 20:57:29 +0000645#elif defined(TARGET_SPARC)
bellard67867302003-11-23 17:05:30 +0000646#elif defined(TARGET_PPC)
Michael Walle81ea0e12011-02-17 23:45:02 +0100647#elif defined(TARGET_LM32)
pbrooke6e59062006-10-22 00:18:54 +0000648#elif defined(TARGET_M68K)
649 cpu_m68k_flush_flags(env, env->cc_op);
650 env->cc_op = CC_OP_FLAGS;
651 env->sr = (env->sr & 0xffe0)
652 | env->cc_dest | (env->cc_x << 4);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200653#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000654#elif defined(TARGET_MIPS)
Jia Liue67db062012-07-20 15:50:39 +0800655#elif defined(TARGET_OPENRISC)
bellardfdf9b3e2006-04-27 21:07:38 +0000656#elif defined(TARGET_SH4)
j_mayereddf68a2007-04-05 07:22:49 +0000657#elif defined(TARGET_ALPHA)
thsf1ccf902007-10-08 13:16:14 +0000658#elif defined(TARGET_CRIS)
Alexander Graf10ec5112009-12-05 12:44:21 +0100659#elif defined(TARGET_S390X)
Max Filippov23288262011-09-06 03:55:25 +0400660#elif defined(TARGET_XTENSA)
bellardfdf9b3e2006-04-27 21:07:38 +0000661 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000662#else
663#error unsupported target CPU
664#endif
pbrook1057eaa2007-02-04 13:37:44 +0000665
bellard6a00d602005-11-21 23:25:50 +0000666 /* fail safe : never use cpu_single_env outside cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000667 cpu_single_env = NULL;
bellard7d132992003-03-06 23:23:54 +0000668 return ret;
669}