From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1HXcWt-00079G-3l for qemu-devel@nongnu.org; Sat, 31 Mar 2007 08:17:59 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1HXcWp-00077M-UI for qemu-devel@nongnu.org; Sat, 31 Mar 2007 08:17:58 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1HXcWp-00077G-Ov for qemu-devel@nongnu.org; Sat, 31 Mar 2007 07:17:55 -0500 Received: from os.inf.tu-dresden.de ([141.76.48.99]) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1HXcU1-0003DL-3b for qemu-devel@nongnu.org; Sat, 31 Mar 2007 08:15:01 -0400 Received: from silo.inf.tu-dresden.de ([141.76.48.100]) by os.inf.tu-dresden.de with esmtps (TLSv1:AES256-SHA:256) (Exim 4.66) id 1HXcTx-0004O7-9b for qemu-devel@nongnu.org; Sat, 31 Mar 2007 14:14:57 +0200 Received: from kauer by silo.inf.tu-dresden.de with local (Exim 4.50) id 1HXcTx-0002kg-53 for qemu-devel@nongnu.org; Sat, 31 Mar 2007 14:14:57 +0200 Date: Sat, 31 Mar 2007 14:14:57 +0200 Subject: [Qemu-devel] Patch: generate double and triple faults Message-ID: <20070331121457.GG24080@silo.inf.tu-dresden.de> References: <20070327114036.GD32622@silo.inf.tu-dresden.de> <460A23BD.8080605@softax.com.pl> <20070328123931.GA24080@silo.inf.tu-dresden.de> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="7iMSBzlTiPOCCT2k" Content-Disposition: inline In-Reply-To: <20070328123931.GA24080@silo.inf.tu-dresden.de> From: Bernhard Kauer Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org --7iMSBzlTiPOCCT2k Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Wed, Mar 28, 2007 at 02:39:31PM +0200, Bernhard Kauer wrote: > On Wed, Mar 28, 2007 at 10:13:49AM +0200, Sebastian Kaliszewski wrote: > > Bernhard Kauer wrote: > > >Qemu does not generate a double fault (DBF) on x86, if a general protection > > >fault could not be delivered. Instead it hangs in a loop. > > > > > >The patch fix this bug by checking whether we are already in a GPF > > >exception. > > > > If you're at it, maybe add triple fault handling (ie exception if DBF > > handler) -- it should reset CPU. > > There are many things missing in the x86 exception handling. For example > the case PF -> PF is also not handled. The attached patch implements double andd triple fault handling and makes the last patch obsolete. It does not generate a reset on triple fault, but it aborts qemu. The same happen currently if the TSS is bogous. Greetings, Bernhard Kauer --7iMSBzlTiPOCCT2k Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="qemu_exceptions.diff" Index: cpu-exec.c =================================================================== RCS file: /sources/qemu/qemu/cpu-exec.c,v retrieving revision 1.97 diff -u -r1.97 cpu-exec.c --- cpu-exec.c 30 Mar 2007 16:44:53 -0000 1.97 +++ cpu-exec.c 31 Mar 2007 11:59:52 -0000 @@ -360,6 +360,7 @@ env->exception_is_int, env->error_code, env->exception_next_eip, 0); + env->old_exception = -1; // successful delivered #elif defined(TARGET_PPC) do_interrupt(env); #elif defined(TARGET_MIPS) Index: target-i386/helper.c =================================================================== RCS file: /sources/qemu/qemu/target-i386/helper.c,v retrieving revision 1.74 diff -u -r1.74 helper.c --- target-i386/helper.c 1 Feb 2007 22:12:19 -0000 1.74 +++ target-i386/helper.c 31 Mar 2007 11:59:58 -0000 @@ -1192,6 +1193,37 @@ } } + +/** + * Check nested exceptions and change to double or triple fault if + * needed. It should only be called, if this is not an + * interrrupt. Returns the new exception number. + */ +int check_exception(int intno, int *error_code) +{ + if (loglevel & CPU_LOG_INT) + fprintf(logfile, "%s() old: %x new %x\n",__func__, env->old_exception, intno); + + + if (env->old_exception == EXCP08_DBLE) + cpu_abort(env, "triple fault"); + + char first_contributory = env->old_exception == 0 || (env->old_exception >= 10 && env->old_exception <= 13); + char second_contributory = intno == 0 || (intno >= 10 && intno <= 13); + + 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 @@ -1201,6 +1233,9 @@ void raise_interrupt(int intno, int is_int, int error_code, int next_eip_addend) { + if (!is_int) + intno = check_exception(intno, &error_code); + env->exception_index = intno; env->error_code = error_code; env->exception_is_int = is_int; @@ -1211,6 +1246,8 @@ /* same as raise_exception_err, but do not restore global registers */ static void raise_exception_err_norestore(int exception_index, int error_code) { + exception_index = check_exception(exception_index, &error_code); + env->exception_index = exception_index; env->error_code = error_code; env->exception_is_int = 0; Index: target-i386/cpu.h =================================================================== RCS file: /sources/qemu/qemu/target-i386/cpu.h,v retrieving revision 1.41 diff -u -r1.41 cpu.h --- target-i386/cpu.h 5 Feb 2007 22:06:27 -0000 1.41 +++ target-i386/cpu.h 31 Mar 2007 11:59:56 -0000 @@ -515,6 +515,7 @@ uint32_t smbase; int interrupt_request; int user_mode_only; /* user mode only simulation */ + int old_exception; /* exception in flight */ CPU_COMMON --7iMSBzlTiPOCCT2k--