From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54342) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z5CfN-0005o7-A2 for qemu-devel@nongnu.org; Wed, 17 Jun 2015 08:42:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z5CfI-0006TW-5S for qemu-devel@nongnu.org; Wed, 17 Jun 2015 08:42:05 -0400 Received: from mail.ispras.ru ([83.149.199.45]:36449) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z5CfH-0006RP-P1 for qemu-devel@nongnu.org; Wed, 17 Jun 2015 08:42:00 -0400 From: Pavel Dovgalyuk Date: Wed, 17 Jun 2015 15:41:59 +0300 Message-ID: <20150617124158.3316.54954.stgit@PASHA-ISP> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH v2 0/3] Fix exceptions handling for MIPS and i386 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, rth7680@gmail.com, leon.alrae@imgtec.com, aurelien@aurel32.net, pavel.dovgaluk@ispras.ru This set of patches fixes exception handling for MIPS and i386 targets. These targets contain instructions that break correct execution in icount/TCG modes (MIPS) and in regular TCG mode (i386). Incorrect execution for i386 is causes by exceptions raised by MMU functions. MMU helper functions are called from generated code and other helper functions. In both cases they try to get function's return address for restoring virtual CPU state. When MMU helper is called from some other helper function (like helper_maskmov_xmm) through cpu_st* function, the return address will point to that helper. That is why CPU state cannot be restored in the case of MMU fault. This bug can occur when maskmov instruction is located in the middle of the translation block. Execution sequence for this example: TB start: PC1: instr1 instr2 PC2: maskmov PC1: instr1 instr2 maskmov At the start of TB execution guest PC points to instr1. When page fault occurs QEMU tries to restore guest PC (which should be equal to PC2). It reads host PC from the call stack and checks whether it points to TB or not. Bug in ldst helpers implementation provides incorrect host PC, which is not located within the TB. That's why QEMU cannot recover guest PC and it remains the same (PC1). After page fault processing QEMU restarts TB and executes instr1 and instr2 for the second time, because guest PC was not recovered. Bugs in MIPS helper functions do not break the execution in regular TCG mode, because PC value is updated before calling the functions that can raise an exception. But icount value cannot be updated this way. Therefore exceptions make execution in icount mode non-determinisic. In icount mode every translation block looks as follows: if icount < n then exit icount -= n instr1 instr2 ... instrn exit When one of these instructions initiates an exception, icount should be restored and adjusted number of instructions should be subtracted from icount instead of initial n. tlb_fill function passes retaddr to raise_exception, which allows restoring current instructions in TB and correct icount calculation. When exception triggered with other function (e.g. by embedding call to exception raising helper into TB), then PC is not passed as retaddr and correct icount is not recovered. In such cases icount will be decreased by the value equal to the size of TB. This behavior leads to incorrect values of virtual clock and non-deterministic execution of the code. These patches passes pointer to the translation block code to the exception handler. It allows correct restoring of PC and icount values. v2 changes: * Added softmmu functions to pass TB return value into memory operations handlers * Fixed memory operations handling for MIPS * Disabled updates of the PC that are overridden with cpu_restore_state * Fixed memory operations and exceptions invoked by i386 helpers --- Pavel Dovgalyuk (3): softmmu: add helper function to pass through retaddr target-mips: exceptions handling in icount mode target-i386: fix memory operations in helpers include/exec/cpu_ldst_template.h | 42 ++ include/exec/exec-all.h | 27 + softmmu_template.h | 18 + target-i386/cc_helper.c | 2 target-i386/cpu.h | 5 target-i386/excp_helper.c | 23 + target-i386/fpu_helper.c | 146 ++++---- target-i386/helper.c | 4 target-i386/int_helper.c | 32 +- target-i386/mem_helper.c | 39 +- target-i386/misc_helper.c | 12 - target-i386/ops_sse.h | 2 target-i386/seg_helper.c | 712 +++++++++++++++++++------------------- target-i386/svm_helper.c | 4 target-i386/translate.c | 25 - target-mips/cpu.h | 28 + target-mips/helper.h | 1 target-mips/msa_helper.c | 5 target-mips/op_helper.c | 183 +++++----- target-mips/translate.c | 46 +- 20 files changed, 726 insertions(+), 630 deletions(-) -- Pavel Dovgalyuk