From patchwork Sun Jun 3 14:29:53 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Blue Swirl X-Patchwork-Id: 162536 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id E8E1CB6FFC for ; Mon, 4 Jun 2012 00:30:34 +1000 (EST) Received: from localhost ([::1]:57940 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SbBpA-00058M-QI for incoming@patchwork.ozlabs.org; Sun, 03 Jun 2012 10:30:32 -0400 Received: from eggs.gnu.org ([208.118.235.92]:35784) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SbBox-00057u-0A for qemu-devel@nongnu.org; Sun, 03 Jun 2012 10:30:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SbBot-0002mw-Ic for qemu-devel@nongnu.org; Sun, 03 Jun 2012 10:30:18 -0400 Received: from mail-yx0-f173.google.com ([209.85.213.173]:44523) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SbBot-0002me-92 for qemu-devel@nongnu.org; Sun, 03 Jun 2012 10:30:15 -0400 Received: by yenm4 with SMTP id m4so2905269yen.4 for ; Sun, 03 Jun 2012 07:30:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to:content-type; bh=uP3AHCNzXtVbTeDSzftDry9lUrUpcUM3TJb9CMjfPac=; b=EuiS8GzXiuBfvf3zjMprgkFfcm904nGdTI0p1AVpGEoMQr5YtQ9PQt3I7AzJfjbezD i3nKrZ0h3s30N23FqiNN33o+nEXjUPSTdvERxkoC2zYhYbBLyd5cyWV7NeLo1gty5XML uTdrnUopX+hTteWqC5lSZ1QuKZWYH4fQuPoeI6OP3Rq3Wtohx/Ztnxq2Kz6aWexwbzMv uxI58OhXQ5UvjKzfrKNl7HlIU3d10Cn/e7sjN7NYfoAysB+9UMgLdLRmxtYaccLALa+u y6Jd6Ilc2pFoJpnk+dISx6oF2xFMn9S1Wcd5PoNDKLz0TUHRkOltVwHK4HuXwDoE1xnT WFiA== Received: by 10.43.69.12 with SMTP id ya12mr2269816icb.50.1338733813313; Sun, 03 Jun 2012 07:30:13 -0700 (PDT) MIME-Version: 1.0 Received: by 10.64.38.68 with HTTP; Sun, 3 Jun 2012 07:29:53 -0700 (PDT) From: Blue Swirl Date: Sun, 3 Jun 2012 14:29:53 +0000 Message-ID: To: qemu-devel X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.213.173 Subject: [Qemu-devel] [PATCH 03/25] x86: split off exception handlers X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Move exception handlers from op_helper.c to excp_helper.c. Signed-off-by: Blue Swirl --- Makefile.target | 3 ++ target-i386/cpu.h | 10 ++-- target-i386/excp_helper.c | 132 +++++++++++++++++++++++++++++++++++++++++++++ target-i386/op_helper.c | 113 -------------------------------------- 4 files changed, 142 insertions(+), 116 deletions(-) create mode 100644 target-i386/excp_helper.c 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, @@ -1529,101 +1521,6 @@ void do_interrupt_x86_hardirq(CPUX86State *env1, int intno, int is_hw) env = saved_env; } -/* This should come from sysemu.h - if we could include it here... */ -void qemu_system_reset_request(void); - -/* - * Check nested exceptions and change to double or triple fault if - * needed. It should only be called, if this is not an interrupt. - * Returns the new exception number. - */ -static int check_exception(CPUX86State *env, int intno, int *error_code) -{ - int first_contributory = env->old_exception == 0 || - (env->old_exception >= 10 && - env->old_exception <= 13); - int second_contributory = intno == 0 || - (intno >= 10 && intno <= 13); - - qemu_log_mask(CPU_LOG_INT, "check_exception old: 0x%x new 0x%x\n", - env->old_exception, intno); - -#if !defined(CONFIG_USER_ONLY) - if (env->old_exception == EXCP08_DBLE) { - if (env->hflags & HF_SVMI_MASK) { - cpu_vmexit(env, SVM_EXIT_SHUTDOWN, 0); /* does not return */ - } - - qemu_log_mask(CPU_LOG_RESET, "Triple fault\n"); - - qemu_system_reset_request(); - return EXCP_HLT; - } -#endif - - if ((first_contributory && second_contributory) - || (env->old_exception == EXCP0E_PAGE && - (second_contributory || (intno == EXCP0E_PAGE)))) { - intno = EXCP08_DBLE; - *error_code = 0; - } - - if (second_contributory || (intno == EXCP0E_PAGE) || - (intno == EXCP08_DBLE)) { - env->old_exception = intno; - } - - return intno; -} - -/* - * Signal an interruption. It is executed in the main CPU loop. - * is_int is TRUE if coming from the int instruction. next_eip is the - * EIP value AFTER the interrupt instruction. It is only relevant if - * is_int is TRUE. - */ -static void QEMU_NORETURN raise_interrupt2(CPUX86State *env, int intno, - int is_int, int error_code, - int next_eip_addend) -{ - if (!is_int) { - cpu_svm_check_intercept_param(env, SVM_EXIT_EXCP_BASE + intno, - error_code); - intno = check_exception(env, intno, &error_code); - } else { - cpu_svm_check_intercept_param(env, SVM_EXIT_SWINT, 0); - } - - env->exception_index = intno; - env->error_code = error_code; - env->exception_is_int = is_int; - env->exception_next_eip = env->eip + next_eip_addend; - cpu_loop_exit(env); -} - -/* shortcuts to generate exceptions */ - -static void QEMU_NORETURN raise_interrupt(CPUX86State *nenv, - int intno, int is_int, - int error_code, - int next_eip_addend) -{ - env = nenv; - raise_interrupt2(env, intno, is_int, error_code, next_eip_addend); -} - -void raise_exception_err(CPUX86State *nenv, int exception_index, - int error_code) -{ - env = nenv; - raise_interrupt2(env, exception_index, 0, error_code, 0); -} - -void raise_exception(CPUX86State *nenv, int exception_index) -{ - env = nenv; - raise_interrupt2(env, exception_index, 0, 0, 0); -} /* SMM support */ #if defined(CONFIG_USER_ONLY) @@ -5220,16 +5117,6 @@ void helper_reset_rf(void) env->eflags &= ~RF_MASK; } -void helper_raise_interrupt(CPUX86State *env, int intno, int next_eip_addend) -{ - raise_interrupt(env, intno, 1, 0, next_eip_addend); -} - -void helper_raise_exception(CPUX86State *env, int exception_index) -{ - raise_exception(env, exception_index); -} - void helper_cli(void) { env->eflags &= ~IF_MASK; diff --git a/Makefile.target b/Makefile.target index 1582904..eefaedf 100644 --- a/Makefile.target +++ b/Makefile.target @@ -90,6 +90,9 @@ libobj-y += helper.o ifneq ($(TARGET_BASE_ARCH), ppc) libobj-y += cpu.o endif +ifeq ($(TARGET_BASE_ARCH), i386) +libobj-y += excp_helper.o +endif libobj-$(TARGET_SPARC64) += vis_helper.o libobj-$(CONFIG_NEED_MMU) += mmu.o libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o diff --git a/target-i386/cpu.h b/target-i386/cpu.h index f6c2de3..c103597 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1063,12 +1063,16 @@ void cpu_x86_inject_mce(Monitor *mon, CPUX86State *cenv, int bank, uint64_t status, uint64_t mcg_status, uint64_t addr, uint64_t misc, int flags); -/* op_helper.c */ -void do_interrupt(CPUX86State *env); -void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw); +/* excp_helper.c */ void QEMU_NORETURN raise_exception(CPUX86State *env, int exception_index); void QEMU_NORETURN raise_exception_err(CPUX86State *env, int exception_index, int error_code); +void QEMU_NORETURN raise_interrupt(CPUX86State *nenv, int intno, int is_int, + int error_code, int next_eip_addend); + +/* op_helper.c */ +void do_interrupt(CPUX86State *env); +void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw); void do_smm_enter(CPUX86State *env1); diff --git a/target-i386/excp_helper.c b/target-i386/excp_helper.c new file mode 100644 index 0000000..72bd46d --- /dev/null +++ b/target-i386/excp_helper.c @@ -0,0 +1,132 @@ +/* + * x86 exception helpers + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "cpu.h" +#include "qemu-log.h" +#include "helper.h" + +#if 0 +#define raise_exception_err(env, a, b) \ + do { \ + qemu_log("raise_exception line=%d\n", __LINE__); \ + (raise_exception_err)(env, a, b); \ + } while (0) +#endif + +void helper_raise_interrupt(CPUX86State *env, int intno, int next_eip_addend) +{ + raise_interrupt(env, intno, 1, 0, next_eip_addend); +} + +void helper_raise_exception(CPUX86State *env, int exception_index) +{ + raise_exception(env, exception_index); +} + + +/* This should come from sysemu.h - if we could include it here... */ +void qemu_system_reset_request(void); + +/* + * Check nested exceptions and change to double or triple fault if + * needed. It should only be called, if this is not an interrupt. + * Returns the new exception number. + */ +static int check_exception(CPUX86State *env, int intno, int *error_code) +{ + int first_contributory = env->old_exception == 0 || + (env->old_exception >= 10 && + env->old_exception <= 13); + int second_contributory = intno == 0 || + (intno >= 10 && intno <= 13); + + qemu_log_mask(CPU_LOG_INT, "check_exception old: 0x%x new 0x%x\n", + env->old_exception, intno); + +#if !defined(CONFIG_USER_ONLY) + if (env->old_exception == EXCP08_DBLE) { + if (env->hflags & HF_SVMI_MASK) { + cpu_vmexit(env, SVM_EXIT_SHUTDOWN, 0); /* does not return */ + } + + qemu_log_mask(CPU_LOG_RESET, "Triple fault\n"); + + qemu_system_reset_request(); + return EXCP_HLT; + } +#endif + + if ((first_contributory && second_contributory) + || (env->old_exception == EXCP0E_PAGE && + (second_contributory || (intno == EXCP0E_PAGE)))) { + intno = EXCP08_DBLE; + *error_code = 0; + } + + if (second_contributory || (intno == EXCP0E_PAGE) || + (intno == EXCP08_DBLE)) { + env->old_exception = intno; + } + + return intno; +} + +/* + * Signal an interruption. It is executed in the main CPU loop. + * is_int is TRUE if coming from the int instruction. next_eip is the + * EIP value AFTER the interrupt instruction. It is only relevant if + * is_int is TRUE. + */ +static void QEMU_NORETURN raise_interrupt2(CPUX86State *env, int intno, + int is_int, int error_code, + int next_eip_addend) +{ + if (!is_int) { + cpu_svm_check_intercept_param(env, SVM_EXIT_EXCP_BASE + intno, + error_code); + intno = check_exception(env, intno, &error_code); + } else { + cpu_svm_check_intercept_param(env, SVM_EXIT_SWINT, 0); + } + + env->exception_index = intno; + env->error_code = error_code; + env->exception_is_int = is_int; + env->exception_next_eip = env->eip + next_eip_addend; + cpu_loop_exit(env); +} + +/* shortcuts to generate exceptions */ + +void QEMU_NORETURN raise_interrupt(CPUX86State *env, int intno, int is_int, + int error_code, int next_eip_addend) +{ + raise_interrupt2(env, intno, is_int, error_code, next_eip_addend); +} + +void raise_exception_err(CPUX86State *env, int exception_index, + int error_code) +{ + raise_interrupt2(env, exception_index, 0, error_code, 0); +} + +void raise_exception(CPUX86State *env, int exception_index) +{ + raise_interrupt2(env, exception_index, 0, 0, 0); +} diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c index b6819dd..8466e9d 100644 --- a/target-i386/op_helper.c +++ b/target-i386/op_helper.c @@ -138,14 +138,6 @@ static inline void cpu_load_efer(CPUX86State *env, uint64_t val) } } -#if 0 -#define raise_exception_err(env, a, b) \ - do { \ - qemu_log("raise_exception line=%d\n", __LINE__); \ - (raise_exception_err)(env, a, b); \ - } while (0) -#endif - static const uint8_t parity_table[256] = { CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,