18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  i386 emulator main execution loop
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  Copyright (c) 2003-2005 Fabrice Bellard
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is free software; you can redistribute it and/or
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * modify it under the terms of the GNU Lesser General Public
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * License as published by the Free Software Foundation; either
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * version 2 of the License, or (at your option) any later version.
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is distributed in the hope that it will be useful,
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Lesser General Public License for more details.
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * You should have received a copy of the GNU Lesser General Public
17a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner * License along with this library; if not, see <http://www.gnu.org/licenses/>.
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "config.h"
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "exec.h"
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "disas.h"
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "tcg.h"
235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "kvm.h"
24a381ef07088ce479610129e37bfef42538f397daJun Nakajima#include "hax.h"
2524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#include "qemu-barrier.h"
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_SOFTMMU)
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EAX
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef ECX
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EDX
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EBX
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef ESP
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EBP
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef ESI
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EDI
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EIP
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <signal.h>
385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/ucontext.h>
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
432c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// Work around ugly bugs in glibc that mangle global register contents
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef env
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define env cpu_single_env
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint tb_invalidated_flag;
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
51a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner//#define CONFIG_DEBUG_EXEC
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//#define DEBUG_SIGNAL
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_cpu_has_work(CPUState *env)
555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return cpu_has_work(env);
575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_loop_exit(void)
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    env->current_tb = NULL;
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    longjmp(env->jmp_env, 1);
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* exit the current TB from a signal handler. The host registers are
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   restored in a state compatible with the CPU emulator
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_resume_from_signal(CPUState *env1, void *puc)
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_SOFTMMU)
715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sigcontext *uc = puc;
755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = env1;
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: restore cpu registers saved in host registers */
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_SOFTMMU)
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (puc) {
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* XXX: use siglongjmp ? */
855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__
8624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#ifdef __ia64
8724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
8824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#else
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
9024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#endif
915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    env->exception_index = -1;
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    longjmp(env->jmp_env, 1);
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Execute the code without caching the generated code. An interpreter
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   could be used if available. */
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long next_tb;
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb;
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Should never happen.
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       We only end up here when an existing TB is too long.  */
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (max_cycles > CF_COUNT_MASK)
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        max_cycles = CF_COUNT_MASK;
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     max_cycles);
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->current_tb = tb;
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* execute the generated code */
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
11724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    env->current_tb = NULL;
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((next_tb & 3) == 2) {
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Restore PC.  This may happen if async event occurs before
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           the TB starts executing.  */
1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        cpu_pc_from_tb(env, tb);
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb_phys_invalidate(tb, -1);
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb_free(tb);
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic TranslationBlock *tb_find_slow(target_ulong pc,
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      target_ulong cs_base,
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      uint64_t flags)
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb, **ptb1;
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int h;
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb_invalidated_flag = 0;
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* find translated block using physical mappings */
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    phys_pc = get_phys_addr_code(env, pc);
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    phys_page1 = phys_pc & TARGET_PAGE_MASK;
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    phys_page2 = -1;
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    h = tb_phys_hash_func(phys_pc);
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ptb1 = &tb_phys_hash[h];
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(;;) {
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tb = *ptb1;
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!tb)
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto not_found;
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (tb->pc == pc &&
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tb->page_addr[0] == phys_page1 &&
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tb->cs_base == cs_base &&
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tb->flags == flags) {
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* check next page if needed */
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (tb->page_addr[1] != -1) {
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                virt_page2 = (pc & TARGET_PAGE_MASK) +
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    TARGET_PAGE_SIZE;
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                phys_page2 = get_phys_addr_code(env, virt_page2);
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (tb->page_addr[1] == phys_page2)
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto found;
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto found;
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ptb1 = &tb->phys_hash_next;
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project not_found:
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* if no translated code available, then translate it now */
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb = tb_gen_code(env, pc, cs_base, flags, 0);
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project found:
1705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Move the last found TB to the head of the list */
1715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (likely(*ptb1)) {
1725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        *ptb1 = tb->phys_hash_next;
1735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tb->phys_hash_next = tb_phys_hash[h];
1745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tb_phys_hash[h] = tb;
1755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we add the TB in the virtual pc hash table */
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tb;
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TranslationBlock *tb_find_fast(void)
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb;
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    target_ulong cs_base, pc;
1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int flags;
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we record a subset of the CPU state. It will
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       always be the same before a given translated block
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       is executed. */
1905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 tb->flags != flags)) {
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tb = tb_find_slow(pc, cs_base, flags);
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tb;
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CPUDebugExcpHandler *debug_excp_handler;
2005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerCPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CPUDebugExcpHandler *old_handler = debug_excp_handler;
2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    debug_excp_handler = handler;
2065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return old_handler;
2075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void cpu_handle_debug_exception(CPUState *env)
2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CPUWatchpoint *wp;
2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
213427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner    if (!env->watchpoint_hit) {
214427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner        QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            wp->flags &= ~BP_WATCHPOINT_HIT;
216427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner        }
217427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner    }
218427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner    if (debug_excp_handler) {
2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        debug_excp_handler(env);
220427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner    }
2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* main execution loop */
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turnervolatile sig_atomic_t exit_request;
22624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
227a381ef07088ce479610129e37bfef42538f397daJun Nakajima/*
228a381ef07088ce479610129e37bfef42538f397daJun Nakajima * Qemu emulation can happen because of MMIO or emulation mode,
229a381ef07088ce479610129e37bfef42538f397daJun Nakajima * i.e. non-PG mode.  For MMIO cases, the pending interrupt should not
230a381ef07088ce479610129e37bfef42538f397daJun Nakajima * be emulated in qemu because MMIO is emulated for only one
231a381ef07088ce479610129e37bfef42538f397daJun Nakajima * instruction now and then back to the HAX kernel module.
232a381ef07088ce479610129e37bfef42538f397daJun Nakajima */
233a381ef07088ce479610129e37bfef42538f397daJun Nakajimaint need_handle_intr_request(CPUState *env)
234a381ef07088ce479610129e37bfef42538f397daJun Nakajima{
235a381ef07088ce479610129e37bfef42538f397daJun Nakajima#ifdef CONFIG_HAX
236a381ef07088ce479610129e37bfef42538f397daJun Nakajima    if (!hax_enabled() || hax_vcpu_emulation_mode(env))
237a381ef07088ce479610129e37bfef42538f397daJun Nakajima        return env->interrupt_request;
238a381ef07088ce479610129e37bfef42538f397daJun Nakajima    return 0;
239a381ef07088ce479610129e37bfef42538f397daJun Nakajima#else
240a381ef07088ce479610129e37bfef42538f397daJun Nakajima    return env->interrupt_request;
241a381ef07088ce479610129e37bfef42538f397daJun Nakajima#endif
242a381ef07088ce479610129e37bfef42538f397daJun Nakajima}
243a381ef07088ce479610129e37bfef42538f397daJun Nakajima
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_exec(CPUState *env1)
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    volatile host_reg_t saved_env_reg;
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret, interrupt_request;
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb;
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t *tc_ptr;
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long next_tb;
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (env1->halted) {
2535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (!cpu_has_work(env1)) {
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return EXCP_HALTED;
2555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
2565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
2575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env1->halted = 0;
2585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_single_env = env1;
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    /* the access to env below is actually saving the global register's
26324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       value, so that files not including target-xyz/exec.h are free to
26424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       use it.  */
26524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
26624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    saved_env_reg = (host_reg_t) env;
26724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    barrier();
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = env1;
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    if (unlikely(exit_request)) {
27124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        env->exit_request = 1;
27224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    }
27324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
27524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    if (!kvm_enabled()) {
27624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        /* put eflags in CPU temporary format */
27724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
27824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        DF = 1 - (2 * ((env->eflags >> 10) & 1));
27924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        CC_OP = CC_OP_EFLAGS;
28024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
28124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    }
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SPARC)
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_M68K)
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cc_op = CC_OP_FLAGS;
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cc_dest = env->sr & 0xf;
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cc_x = (env->sr >> 4) & 1;
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ALPHA)
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ARM)
289427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_UNICORE32)
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_PPC)
291427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_LM32)
2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(TARGET_MICROBLAZE)
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_MIPS)
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SH4)
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_CRIS)
296a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner#elif defined(TARGET_S390X)
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXXXX */
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#error unsupported target CPU
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->exception_index = -1;
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* prepare setjmp context for exception handling */
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(;;) {
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (setjmp(env->jmp_env) == 0) {
3062c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
3075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#undef env
3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    env = cpu_single_env;
3095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define env cpu_single_env
3105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* if an exception is pending, we execute it here */
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (env->exception_index >= 0) {
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (env->exception_index >= EXCP_INTERRUPT) {
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* exit request from the cpu execution loop */
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    ret = env->exception_index;
316427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    if (ret == EXCP_DEBUG) {
3175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        cpu_handle_debug_exception(env);
318427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    }
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                } else {
3215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(CONFIG_USER_ONLY)
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* if user mode only, we simulate a fake exception
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       which will be handled outside the cpu execution
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       loop */
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt_user(env->exception_index,
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      env->exception_is_int,
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      env->error_code,
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      env->exception_next_eip);
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* successfully delivered */
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env->old_exception = -1;
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    ret = env->exception_index;
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
3355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* simulate a real cpu exception. On i386, it can
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       trigger new exceptions, but we do not handle
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       double or triple faults yet. */
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(env->exception_index,
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                 env->exception_is_int,
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                 env->error_code,
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                 env->exception_next_eip, 0);
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* successfully delivered */
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env->old_exception = -1;
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_PPC)
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(env);
348427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_LM32)
349427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    do_interrupt(env);
3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(TARGET_MICROBLAZE)
3515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    do_interrupt(env);
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_MIPS)
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(env);
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SPARC)
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(env);
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ARM)
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(env);
358427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_UNICORE32)
359427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    do_interrupt(env);
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SH4)
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    do_interrupt(env);
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ALPHA)
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(env);
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_CRIS)
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(env);
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_M68K)
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(0);
368427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_S390X)
369427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    do_interrupt(env);
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
371a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                    env->exception_index = -1;
3725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
376a381ef07088ce479610129e37bfef42538f397daJun Nakajima#ifdef CONFIG_HAX
377a381ef07088ce479610129e37bfef42538f397daJun Nakajima            if (hax_enabled() && !hax_vcpu_exec(env))
378a381ef07088ce479610129e37bfef42538f397daJun Nakajima                longjmp(env->jmp_env, 1);
379a381ef07088ce479610129e37bfef42538f397daJun Nakajima#endif
380a381ef07088ce479610129e37bfef42538f397daJun Nakajima
3815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (kvm_enabled()) {
3825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                kvm_cpu_exec(env);
3835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                longjmp(env->jmp_env, 1);
3845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
3855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            next_tb = 0; /* force lookup of first TB */
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for(;;) {
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                interrupt_request = env->interrupt_request;
389a381ef07088ce479610129e37bfef42538f397daJun Nakajima                if (unlikely(need_handle_intr_request(env))) {
3905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
3915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        /* Mask out external interrupts for this step. */
3925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
3935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    }
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_DEBUG;
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        cpu_loop_exit();
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
4005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
401427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner    defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HALT) {
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->halted = 1;
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_HLT;
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        cpu_loop_exit();
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
410a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                    if (interrupt_request & CPU_INTERRUPT_INIT) {
411a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            svm_check_intercept(SVM_EXIT_INIT);
412a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            do_cpu_init(env);
413a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            env->exception_index = EXCP_HALTED;
414a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            cpu_loop_exit();
415a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                    } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
416a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            do_cpu_sipi(env);
417a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                    } else if (env->hflags2 & HF2_GIF_MASK) {
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            !(env->hflags & HF_SMM_MASK)) {
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            svm_check_intercept(SVM_EXIT_SMI);
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            do_smm_enter();
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            next_tb = 0;
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                   !(env->hflags2 & HF2_NMI_MASK)) {
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->hflags2 |= HF2_NMI_MASK;
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            next_tb = 0;
430a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner			} else if (interrupt_request & CPU_INTERRUPT_MCE) {
431a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            env->interrupt_request &= ~CPU_INTERRUPT_MCE;
432a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
433a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            next_tb = 0;
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
435f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner                                   (((env->hflags2 & HF2_VINTR_MASK) &&
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                     (env->hflags2 & HF2_HIF_MASK)) ||
437f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner                                    (!(env->hflags2 & HF2_VINTR_MASK) &&
438f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner                                     (env->eflags & IF_MASK &&
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            int intno;
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            svm_check_intercept(SVM_EXIT_INTR);
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            intno = cpu_get_pic_interrupt(env);
4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
4452c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
4465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#undef env
4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    env = cpu_single_env;
4485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define env cpu_single_env
4495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            do_interrupt(intno, 0, 0, 0, 1);
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* ensure that no TB jump will be modified as
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               the program flow was changed */
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            next_tb = 0;
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
456f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner                                   (env->eflags & IF_MASK) &&
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            int intno;
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* FIXME: this should respect TPR */
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            svm_check_intercept(SVM_EXIT_VINTR);
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
4625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            do_interrupt(intno, 0, 0, 0, 1);
4645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            next_tb = 0;
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_PPC)
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
472a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                        cpu_reset(env);
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD) {
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        ppc_hw_interrupt(env);
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (env->pending_interrupts == 0)
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
481427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_LM32)
482427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    if ((interrupt_request & CPU_INTERRUPT_HARD)
483427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        && (env->ie & IE_IE)) {
484427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        env->exception_index = EXCP_IRQ;
485427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        do_interrupt(env);
486427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        next_tb = 0;
487427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    }
4885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(TARGET_MICROBLAZE)
4895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    if ((interrupt_request & CPU_INTERRUPT_HARD)
4905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        && (env->sregs[SR_MSR] & MSR_IE)
4915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
4925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        && !(env->iflags & (D_FLAG | IMM_FLAG))) {
4935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        env->exception_index = EXCP_IRQ;
4945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        do_interrupt(env);
4955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        next_tb = 0;
4965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    }
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_MIPS)
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
499427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        cpu_mips_hw_interrupts_pending(env)) {
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Raise it */
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_EXT_INTERRUPT;
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->error_code = 0;
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SPARC)
50724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                    if (interrupt_request & CPU_INTERRUPT_HARD) {
50824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                        if (cpu_interrupts_enabled(env) &&
50924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                            env->interrupt_index > 0) {
51024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                            int pil = env->interrupt_index & 0xf;
51124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                            int type = env->interrupt_index & 0xf0;
51224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
51324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                            if (((type == TT_EXTINT) &&
51424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                                  cpu_pil_allowed(env, pil)) ||
51524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                                  type != TT_EXTINT) {
51624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                                env->exception_index = env->interrupt_index;
51724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                                do_interrupt(env);
51824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                                next_tb = 0;
51924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                            }
52024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                        }
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    }
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ARM)
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_FIQ
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        && !(env->uncached_cpsr & CPSR_F)) {
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_FIQ;
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* ARMv7-M interrupt return works by loading a magic value
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       into the PC.  On real hardware the load causes the
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       return to occur.  The qemu implementation performs the
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       jump normally, then does the exception return when the
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       CPU tries to execute code at the magic address.
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       This will cause the magic PC value to be pushed to
5355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                       the stack if an interrupt occurred at the wrong time.
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       We avoid this by disabling interrupts when
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       pc contains a magic address.  */
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            || !(env->uncached_cpsr & CPSR_I))) {
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_IRQ;
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
545427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_UNICORE32)
546427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    if (interrupt_request & CPU_INTERRUPT_HARD
547427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        && !(env->uncached_asr & ASR_I)) {
548427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        do_interrupt(env);
549427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        next_tb = 0;
550427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    }
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SH4)
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD) {
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ALPHA)
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD) {
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_CRIS)
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD
56324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                        && (env->pregs[PR_CCS] & I_FLAG)
56424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                        && !env->locked_irq) {
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_IRQ;
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_NMI
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        && (env->pregs[PR_CCS] & M_FLAG)) {
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_NMI;
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_M68K)
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        && ((env->sr & SR_I) >> SR_I_SHIFT)
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            < env->pending_level) {
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Real hardware gets the interrupt vector via an
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           IACK cycle at this point.  Current emulated
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           hardware doesn't rely on this, so we
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           provide/save the vector when the interrupt is
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           first signalled.  */
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = env->pending_vector;
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(1);
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
588427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
589427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
590427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        (env->psw.mask & PSW_MASK_EXT)) {
591427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        do_interrupt(env);
592427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        next_tb = 0;
593427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    }
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                   /* Don't use the cached interrupt_request value,
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      do_interrupt may have updated the EXITTB flag. */
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* ensure that no TB jump will be modified as
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           the program flow was changed */
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
6035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
6045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (unlikely(env->exit_request)) {
6055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    env->exit_request = 0;
6065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    env->exception_index = EXCP_INTERRUPT;
6075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    cpu_loop_exit();
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
60924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
6105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* restore flags in standard format */
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
6145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    log_cpu_state(env, X86_DUMP_CCOP);
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_M68K)
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    cpu_m68k_flush_flags(env, env->cc_op);
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env->cc_op = CC_OP_FLAGS;
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env->sr = (env->sr & 0xffe0)
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              | env->cc_dest | (env->cc_x << 4);
6215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    log_cpu_state(env, 0);
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
62324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                    log_cpu_state(env, 0);
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
62624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                spin_lock(&tb_lock);
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tb = tb_find_fast();
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Note: we do it here to avoid a gcc bug on Mac OS X when
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   doing it in tb_find_slow */
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (tb_invalidated_flag) {
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* as some TB could have been invalidated because
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       of memory exceptions while generating the code, we
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       must recompute the hash index here */
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    next_tb = 0;
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tb_invalidated_flag = 0;
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
63824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#ifdef CONFIG_DEBUG_EXEC
6395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
6405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             (long)tb->tc_ptr, tb->pc,
6415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             lookup_symbol(tb->pc));
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* see if we can patch the calling TB. When the TB
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   spans two pages, we cannot safely do a direct
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   jump. */
64624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                if (next_tb != 0 && tb->page_addr[1] == -1) {
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                spin_unlock(&tb_lock);
6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* cpu_interrupt might be called while translating the
6525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   TB, but before it is linked into a potentially
6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   infinite loop and becomes env->current_tb. Avoid
6545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   starting execution if there is a pending interrupt. */
65524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                env->current_tb = tb;
65624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                barrier();
65724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                if (likely(!env->exit_request)) {
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tc_ptr = tb->tc_ptr;
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* execute the generated code */
6602c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef env
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env = cpu_single_env;
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define env cpu_single_env
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    next_tb = tcg_qemu_tb_exec(tc_ptr);
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((next_tb & 3) == 2) {
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Instruction counter expired.  */
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        int insns_left;
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tb = (TranslationBlock *)(long)(next_tb & ~3);
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Restore PC.  */
6715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        cpu_pc_from_tb(env, tb);
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        insns_left = env->icount_decr.u32;
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (env->icount_extra && insns_left >= 0) {
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Refill decrementer and continue execution.  */
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->icount_extra += insns_left;
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (env->icount_extra > 0xffff) {
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                insns_left = 0xffff;
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                insns_left = env->icount_extra;
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->icount_extra -= insns_left;
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->icount_decr.u16.low = insns_left;
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insns_left > 0) {
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                /* Execute remaining instructions.  */
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                cpu_exec_nocache(insns_left, tb);
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->exception_index = EXCP_INTERRUPT;
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            next_tb = 0;
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            cpu_loop_exit();
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
69424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                env->current_tb = NULL;
695a381ef07088ce479610129e37bfef42538f397daJun Nakajima#ifdef CONFIG_HAX
696a381ef07088ce479610129e37bfef42538f397daJun Nakajima                if (hax_enabled() && hax_stop_emulation(env))
697a381ef07088ce479610129e37bfef42538f397daJun Nakajima                    cpu_loop_exit();
698a381ef07088ce479610129e37bfef42538f397daJun Nakajima#endif
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* reset soft MMU for next block (it can currently
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   only be set by a memory fault) */
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } /* for(;;) */
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } /* for(;;) */
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* restore flags in standard format */
7085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ARM)
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: Save/restore host fpu exception state?.  */
711427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_UNICORE32)
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SPARC)
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_PPC)
714427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_LM32)
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_M68K)
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_m68k_flush_flags(env, env->cc_op);
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cc_op = CC_OP_FLAGS;
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->sr = (env->sr & 0xffe0)
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              | env->cc_dest | (env->cc_x << 4);
7205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(TARGET_MICROBLAZE)
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_MIPS)
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SH4)
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ALPHA)
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_CRIS)
72524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#elif defined(TARGET_S390X)
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXXXX */
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#error unsupported target CPU
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* restore global registers */
73224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    barrier();
73324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    env = (void *) saved_env_reg;
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* fail safe : never use cpu_single_env outside cpu_exec() */
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_single_env = NULL;
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* must only be called from the generated code as an exception can be
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   generated */
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid tb_invalidate_page_range(target_ulong start, target_ulong end)
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: cannot enable it yet because it yields to MMU exception
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       where NIP != read address on PowerPC */
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    target_ulong phys_addr;
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    phys_addr = get_phys_addr_code(env, start);
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CPUX86State *saved_env;
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    saved_env = env;
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = s;
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        selector &= 0xffff;
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_x86_load_seg_cache(env, seg_reg, selector,
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               (selector << 4), 0xffff, 0);
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        helper_load_seg(seg_reg, selector);
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = saved_env;
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CPUX86State *saved_env;
7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    saved_env = env;
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = s;
7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    helper_fsave(ptr, data32);
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = saved_env;
7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CPUX86State *saved_env;
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    saved_env = env;
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = s;
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    helper_frstor(ptr, data32);
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = saved_env;
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* TARGET_I386 */
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_SOFTMMU)
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
80024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
80124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#else
80224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define EXCEPTION_ACTION cpu_loop_exit()
80324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#endif
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 'pc' is the host PC at which the exception was raised. 'address' is
8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   the effective address of the memory exception. 'is_write' is 1 if a
8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   write caused the exception and otherwise 0'. 'old_set' is the
8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   signal set which should be restored */
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline int handle_cpu_signal(unsigned long pc, unsigned long address,
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                    int is_write, sigset_t *old_set,
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                    void *puc)
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb;
8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cpu_single_env)
8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env = cpu_single_env; /* XXX: find a correct solution for multithread */
8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(DEBUG_SIGNAL)
8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                pc, address, is_write, *(unsigned long *)old_set);
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
8228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: locking issue */
8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (is_write && page_unprotect(h2g(address), pc, puc)) {
8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* see if it is an MMU fault */
82824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
8298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0)
8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0; /* not an MMU fault */
8318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret == 0)
8328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1; /* the MMU fault was handled without causing real CPU fault */
8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* now we have a real cpu fault */
8348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb = tb_find_pc(pc);
8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (tb) {
8368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* the PC is inside the translated code. It means that we have
8378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           a virtual CPU fault */
838f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner        cpu_restore_state(tb, env, pc);
8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we restore the process signal mask as the sigreturn should
8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       do it (XXX: use sigsetjmp) */
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sigprocmask(SIG_SETMASK, old_set, NULL);
84424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    EXCEPTION_ACTION;
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* never comes here */
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 1;
8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(__i386__)
8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(__APPLE__)
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# include <sys/ucontext.h>
8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
8585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define MASK_sig(context)    ((context)->uc_sigmask)
85924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#elif defined (__NetBSD__)
86024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# include <ucontext.h>
86124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
86224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
86324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
86424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
86524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define MASK_sig(context)    ((context)->uc_sigmask)
86624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#elif defined (__FreeBSD__) || defined(__DragonFly__)
86724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# include <ucontext.h>
86824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
86924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
87024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
87124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
87224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define MASK_sig(context)    ((context)->uc_sigmask)
8735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
8745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define EIP_sig(context)     ((context)->sc_eip)
8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define TRAP_sig(context)    ((context)->sc_trapno)
8765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define ERROR_sig(context)   ((context)->sc_err)
8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define MASK_sig(context)    ((context)->sc_mask)
8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
8825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define MASK_sig(context)    ((context)->uc_sigmask)
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
88924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
89024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    ucontext_t *uc = puc;
89124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#elif defined(__OpenBSD__)
8925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sigcontext *uc = puc;
8935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
8955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int trapno;
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef REG_EIP
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* for glibc 2.1 */
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define REG_EIP    EIP
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define REG_ERR    ERR
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define REG_TRAPNO TRAPNO
9048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = EIP_sig(uc);
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    trapno = TRAP_sig(uc);
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             trapno == 0xe ?
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             (ERROR_sig(uc) >> 1) & 1 : 0,
9105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             &MASK_sig(uc), puc);
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__x86_64__)
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __NetBSD__
9165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define PC_sig(context)       _UC_MACHINE_PC(context)
9175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
9185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
9195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MASK_sig(context)     ((context)->uc_sigmask)
9205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
9215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define PC_sig(context)       ((context)->sc_rip)
9225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define TRAP_sig(context)     ((context)->sc_trapno)
9235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ERROR_sig(context)    ((context)->sc_err)
9245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MASK_sig(context)     ((context)->sc_mask)
92524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#elif defined (__FreeBSD__) || defined(__DragonFly__)
92624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#include <ucontext.h>
92724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
92824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define PC_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
92924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
93024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
93124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define MASK_sig(context)     ((context)->uc_sigmask)
9325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
9335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
9345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
9355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
9365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MASK_sig(context)     ((context)->uc_sigmask)
9375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
9385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
9408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
9418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
9438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
94424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
9455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ucontext_t *uc = puc;
9465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
9475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sigcontext *uc = puc;
9485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
9495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct ucontext *uc = puc;
9505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pc = PC_sig(uc);
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
9545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             TRAP_sig(uc) == 0xe ?
9555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             (ERROR_sig(uc) >> 1) & 1 : 0,
9565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             &MASK_sig(uc), puc);
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(_ARCH_PPC)
9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/***********************************************************************
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * signal context platform-specific definitions
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * From Wine
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef linux
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* All Registers access - only for local access */
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define REG_sig(reg_name, context)		((context)->uc_mcontext.regs->reg_name)
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Gpr Registers access  */
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define GPR_sig(reg_num, context)		REG_sig(gpr[reg_num], context)
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define IAR_sig(context)			REG_sig(nip, context)	/* Program counter */
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define MSR_sig(context)			REG_sig(msr, context)   /* Machine State Register (Supervisor) */
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define CTR_sig(context)			REG_sig(ctr, context)   /* Count register */
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define XER_sig(context)			REG_sig(xer, context) /* User's integer exception register */
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define LR_sig(context)			REG_sig(link, context) /* Link register */
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define CR_sig(context)			REG_sig(ccr, context) /* Condition register */
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Float Registers access  */
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define FLOAT_sig(reg_num, context)		(((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define FPSCR_sig(context)			(*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Exception Registers access */
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define DAR_sig(context)			REG_sig(dar, context)
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define DSISR_sig(context)			REG_sig(dsisr, context)
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define TRAP_sig(context)			REG_sig(trap, context)
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* linux */
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
98524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
98624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#include <ucontext.h>
98724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define IAR_sig(context)		((context)->uc_mcontext.mc_srr0)
98824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define MSR_sig(context)		((context)->uc_mcontext.mc_srr1)
98924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define CTR_sig(context)		((context)->uc_mcontext.mc_ctr)
99024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define XER_sig(context)		((context)->uc_mcontext.mc_xer)
99124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define LR_sig(context)		((context)->uc_mcontext.mc_lr)
99224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define CR_sig(context)		((context)->uc_mcontext.mc_cr)
99324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner/* Exception Registers access */
99424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define DAR_sig(context)		((context)->uc_mcontext.mc_dar)
99524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define DSISR_sig(context)		((context)->uc_mcontext.mc_dsisr)
99624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define TRAP_sig(context)		((context)->uc_mcontext.mc_exc)
99724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
99824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef __APPLE__
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# include <sys/ucontext.h>
10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ucontext SIGCONTEXT;
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* All Registers access - only for local access */
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define REG_sig(reg_name, context)		((context)->uc_mcontext->ss.reg_name)
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define FLOATREG_sig(reg_name, context)	((context)->uc_mcontext->fs.reg_name)
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define EXCEPREG_sig(reg_name, context)	((context)->uc_mcontext->es.reg_name)
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define VECREG_sig(reg_name, context)		((context)->uc_mcontext->vs.reg_name)
10078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Gpr Registers access */
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define GPR_sig(reg_num, context)		REG_sig(r##reg_num, context)
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define IAR_sig(context)			REG_sig(srr0, context)	/* Program counter */
10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define MSR_sig(context)			REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define CTR_sig(context)			REG_sig(ctr, context)
10128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define XER_sig(context)			REG_sig(xer, context) /* Link register */
10138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define LR_sig(context)			REG_sig(lr, context)  /* User's integer exception register */
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define CR_sig(context)			REG_sig(cr, context)  /* Condition register */
10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Float Registers access */
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define FLOAT_sig(reg_num, context)		FLOATREG_sig(fpregs[reg_num], context)
10178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define FPSCR_sig(context)			((double)FLOATREG_sig(fpscr, context))
10188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Exception Registers access */
10198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define DAR_sig(context)			EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
10208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define DSISR_sig(context)			EXCEPREG_sig(dsisr, context)
10218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define TRAP_sig(context)			EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
10228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* __APPLE__ */
10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
10258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
10268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
102824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
102924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    ucontext_t *uc = puc;
103024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#else
10318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
103224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#endif
10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
10348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write;
10358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = IAR_sig(uc);
10378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_write = 0;
10388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* ppc 4xx case */
10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (DSISR_sig(uc) & 0x00800000)
10418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        is_write = 1;
10428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
10438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
10448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        is_write = 1;
10458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
10468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
10478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write, &uc->uc_sigmask, puc);
10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__alpha__)
10518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
10538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           void *puc)
10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t *pc = uc->uc_mcontext.sc_pc;
10588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t insn = *pc;
10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write = 0;
10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: need kernel patch to get write flag faster */
10628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (insn >> 26) {
10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x0d: // stw
10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x0e: // stb
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x0f: // stq_u
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x24: // stf
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x25: // stg
10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x26: // sts
10698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x27: // stt
10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x2c: // stl
10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x2d: // stq
10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x2e: // stl_c
10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x2f: // stq_c
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	is_write = 1;
10758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
10788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write, &uc->uc_sigmask, puc);
10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__sparc__)
10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
10838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write;
10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t insn;
10882c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t *regs = (uint32_t *)(info + 1);
10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void *sigmask = (regs + 20);
10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: is there a standard glibc define ? */
10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc = regs[1];
10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
10945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__
10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct sigcontext *sc = puc;
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc = sc->sigc_regs.tpc;
10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void *sigmask = (void *)sc->sigc_mask;
10985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
10995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sigcontext *uc = puc;
11005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unsigned long pc = uc->sc_pc;
11015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    void *sigmask = (void *)(long)uc->sc_mask;
11025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: need kernel patch to get write flag faster */
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_write = 0;
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    insn = *(uint32_t *)pc;
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn >> 30) == 3) {
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      switch((insn >> 19) & 0x3f) {
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x05: // stb
11115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x15: // stba
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x06: // sth
11135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x16: // stha
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x04: // st
11155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x14: // sta
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x07: // std
11175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x17: // stda
11185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x0e: // stx
11195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x1e: // stxa
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x24: // stf
11215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x34: // stfa
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x27: // stdf
11235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x37: // stdfa
11245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x26: // stqf
11255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x36: // stqfa
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x25: // stfsr
11275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x3c: // casa
11285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x3e: // casxa
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	is_write = 1;
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	break;
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write, sigmask, NULL);
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__arm__)
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write;
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = uc->uc_mcontext.gregs[R15];
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = uc->uc_mcontext.arm_pc;
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: compute is_write */
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_write = 0;
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write,
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             &uc->uc_sigmask, puc);
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__mc68000)
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write;
11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = uc->uc_mcontext.gregs[16];
11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: compute is_write */
11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_write = 0;
11728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write,
11748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             &uc->uc_sigmask, puc);
11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__ia64)
11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef __ISR_VALID
11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  /* This ought to be in <bits/siginfo.h>... */
11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define __ISR_VALID	1
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo, void *puc)
11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long ip;
11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write = 0;
11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ip = uc->uc_mcontext.sc_ip;
11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (host_signum) {
11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case SIGILL:
11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case SIGFPE:
11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case SIGSEGV:
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case SIGBUS:
11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case SIGTRAP:
11988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  if (info->si_code && (info->si_segvflags & __ISR_VALID))
11998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	      /* ISR.W (write-access) is bit 33:  */
12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	      is_write = (info->si_isr >> 33) & 1;
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  break;
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      default:
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  break;
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write,
120824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                             (sigset_t *)&uc->uc_sigmask, puc);
12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__s390__)
12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
121924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    uint16_t *pinsn;
122024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    int is_write = 0;
12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = uc->uc_mcontext.psw.addr;
122324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
122424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
122524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       of the normal 2 arguments.  The 3rd argument contains the "int_code"
122624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       from the hardware which does in fact contain the is_write value.
122724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       The rt signal handler, as far as I can tell, does not give this value
122824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       at all.  Not that we could get to it from here even if it were.  */
122924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    /* ??? This is not even close to complete, since it ignores all
123024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       of the read-modify-write instructions.  */
123124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    pinsn = (uint16_t *)pc;
123224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    switch (pinsn[0] >> 8) {
123324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x50: /* ST */
123424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x42: /* STC */
123524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x40: /* STH */
123624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        is_write = 1;
123724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
123824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0xc4: /* RIL format insns */
123924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        switch (pinsn[0] & 0xf) {
124024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0xf: /* STRL */
124124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0xb: /* STGRL */
124224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x7: /* STHRL */
124324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner            is_write = 1;
124424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        }
124524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
124624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0xe3: /* RXY format insns */
124724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        switch (pinsn[2] & 0xff) {
124824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x50: /* STY */
124924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x24: /* STG */
125024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x72: /* STCY */
125124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x70: /* STHY */
125224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x8e: /* STPQ */
125324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x3f: /* STRVH */
125424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x3e: /* STRV */
125524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x2f: /* STRVG */
125624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner            is_write = 1;
125724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        }
125824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
125924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    }
12608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
12618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write, &uc->uc_sigmask, puc);
12628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__mips__)
12658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
12678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
12688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
12708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
12718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    greg_t pc = uc->uc_mcontext.pc;
12728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write;
12738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: compute is_write */
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_write = 0;
12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write, &uc->uc_sigmask, puc);
12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__hppa__)
12818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct siginfo *info = pinfo;
12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
128724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
128824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    uint32_t insn = *(uint32_t *)pc;
128924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    int is_write = 0;
129024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
129124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    /* XXX: need kernel patch to get write flag faster.  */
129224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    switch (insn >> 26) {
129324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x1a: /* STW */
129424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x19: /* STH */
129524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x18: /* STB */
129624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x1b: /* STWM */
129724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        is_write = 1;
129824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
129924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
130024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x09: /* CSTWX, FSTWX, FSTWS */
130124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x0b: /* CSTDX, FSTDX, FSTDS */
130224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        /* Distinguish from coprocessor load ... */
130324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        is_write = (insn >> 9) & 1;
130424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
130524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
130624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x03:
130724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        switch ((insn >> 6) & 15) {
130824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0xa: /* STWS */
130924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x9: /* STHS */
131024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x8: /* STBS */
131124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0xe: /* STWAS */
131224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0xc: /* STBYS */
131324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner            is_write = 1;
131424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        }
131524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
131624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    }
13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1318f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
131924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                             is_write, &uc->uc_sigmask, puc);
13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#error host CPU specific signal handler needed
13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* !defined(CONFIG_SOFTMMU) */
1329