From patchwork Sat Jun 9 16:18:59 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Blue Swirl X-Patchwork-Id: 163929 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 B9A5AB6FBE for ; Sun, 10 Jun 2012 02:19:52 +1000 (EST) Received: from localhost ([::1]:52909 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SdOOE-0002wW-Ej for incoming@patchwork.ozlabs.org; Sat, 09 Jun 2012 12:19:50 -0400 Received: from eggs.gnu.org ([208.118.235.92]:41298) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SdONz-0002mE-Db for qemu-devel@nongnu.org; Sat, 09 Jun 2012 12:19:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SdONu-0003Kv-T4 for qemu-devel@nongnu.org; Sat, 09 Jun 2012 12:19:34 -0400 Received: from mail-ee0-f45.google.com ([74.125.83.45]:61400) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SdONu-0003Kc-H0 for qemu-devel@nongnu.org; Sat, 09 Jun 2012 12:19:30 -0400 Received: by eekd41 with SMTP id d41so1793685eek.4 for ; Sat, 09 Jun 2012 09:19:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:x-mailer:in-reply-to:references :in-reply-to:references; bh=me1tLrkzC+nR5I2yoxduKfDuEnpFj3mlZ41f/ZPi6iM=; b=zBNHEk1Os8iKqxuLoaLVGRPkFlJBaveAIZrDSSlojmhx8m97NqTGQrmpbXYsz1PE0O Ep/Jn2RPcXuyvHlx8kN1o/tWGbQVnasJS+7OasXpf1kW+818TC4WYtNLJZ/F+WSTNl5I RVPR0/tinGPtmLg64N0ib9Qj2M8VenPOD1sP8g2CCVe2BYzH/jXchLGvxxZIJl1eFUXi Uf0sHPS4rNywG19FCyYil2L1NZiblpV83KR+sIlAf7f9TKZe7VhXzBD1TpYzYdF4Jl2H 5UqIQi3iBkfXC9nA4wK47C7IdORtDidaacSwhaU4wdaaEtoYfG0wacHymZlpcqz9INzf fp5w== Received: by 10.14.53.77 with SMTP id f53mr4386193eec.88.1339258768391; Sat, 09 Jun 2012 09:19:28 -0700 (PDT) Received: from localhost.localdomain (blueswirl.broker.freenet6.net. [2001:5c0:1400:b::d5a3]) by mx.google.com with ESMTPS id h53sm33625570eea.1.2012.06.09.09.19.26 (version=TLSv1/SSLv3 cipher=OTHER); Sat, 09 Jun 2012 09:19:27 -0700 (PDT) From: Blue Swirl To: qemu-devel@nongnu.org Date: Sat, 9 Jun 2012 16:18:59 +0000 Message-Id: <7eba9b89f8cd1d0a68df3b3c6f932ff075f47515.1339258553.git.blauwirbel@gmail.com> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 74.125.83.45 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 --- target-i386/Makefile.objs | 1 + target-i386/cpu.h | 10 +++- target-i386/excp_helper.c | 132 +++++++++++++++++++++++++++++++++++++++++++++ target-i386/op_helper.c | 113 -------------------------------------- 4 files changed, 140 insertions(+), 116 deletions(-) create mode 100644 target-i386/excp_helper.c diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs index f913755..c0feffe 100644 --- a/target-i386/Makefile.objs +++ b/target-i386/Makefile.objs @@ -1,4 +1,5 @@ obj-y += translate.o op_helper.o helper.o cpu.o +obj-y += excp_helper.o obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o obj-$(CONFIG_KVM) += kvm.o hyperv.o obj-$(CONFIG_LINUX_USER) += ioport-user.o diff --git a/target-i386/cpu.h b/target-i386/cpu.h index c546723..cea8ecc 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1071,12 +1071,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 773148c..8625936 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, 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) @@ -5221,16 +5118,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;