From patchwork Wed Jun 3 21:09:56 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aurelien Jarno X-Patchwork-Id: 480227 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id EA6AD1401DE for ; Thu, 4 Jun 2015 07:16:42 +1000 (AEST) Received: from localhost ([::1]:38249 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z0G1g-00051N-PL for incoming@patchwork.ozlabs.org; Wed, 03 Jun 2015 17:16:40 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60540) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z0FvM-0001QS-Fr for qemu-devel@nongnu.org; Wed, 03 Jun 2015 17:10:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z0FvI-0007td-L1 for qemu-devel@nongnu.org; Wed, 03 Jun 2015 17:10:08 -0400 Received: from hall.aurel32.net ([2001:bc8:30d7:101::1]:40107) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z0FvI-0007sX-FY for qemu-devel@nongnu.org; Wed, 03 Jun 2015 17:10:04 -0400 Received: from weber.rr44.fr ([2001:470:d4ed:0:7e05:7ff:fe0d:f152]) by hall.aurel32.net with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84) (envelope-from ) id 1Z0FvG-0003Wq-HZ; Wed, 03 Jun 2015 23:10:02 +0200 Received: from aurel32 by weber.rr44.fr with local (Exim 4.85) (envelope-from ) id 1Z0FvF-0000QW-Cc; Wed, 03 Jun 2015 23:10:01 +0200 From: Aurelien Jarno To: qemu-devel@nongnu.org Date: Wed, 3 Jun 2015 23:09:56 +0200 Message-Id: <1433365796-1118-17-git-send-email-aurelien@aurel32.net> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1433365796-1118-1-git-send-email-aurelien@aurel32.net> References: <1433365796-1118-1-git-send-email-aurelien@aurel32.net> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:bc8:30d7:101::1 Cc: Alexander Graf , Aurelien Jarno , Richard Henderson Subject: [Qemu-devel] [PATCH v2 16/16] target-s390x: fix MVC instruction when areas overlap 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 The MVC instruction and the memmove C funtion do not have the same semantic when memory areas overlap: MVC: When the operands overlap, the result is obtained as if the operands were processed one byte at a time and each result byte were stored immediately after fetching the necessary operand byte. memmove: Copying takes place as though the bytes in src are first copied into a temporary array that does not overlap src or dest, and the bytes are then copied from the temporary array to dest. The behaviour is therefore the same when the destination is at a lower address than the source, but not in the other case. This is actually a trick for propagating a value to an area. While the current code detects that and call memset in that case, it only does for 1-byte value. This trick can and is used for propagating two or more bytes to an area. In the softmmu case, the call to mvc_fast_memmove is correct as the above tests verify that source and destination are each within a page, and both in a different page. The part doing the move 8 bytes by 8 bytes is wrong and we need to check that if the source and destination overlap, they do with a distance of minimum 8 bytes before copying 8 bytes at a time. In the user code, we should check check that the destination is at a lower address than source or than the end of the source is at a lower address than the destination before calling memmove. In the opposite case we fallback to the same code as the softmmu one. Note that l represents (length - 1). Cc: Alexander Graf Cc: Richard Henderson Signed-off-by: Aurelien Jarno Reviewed-by: Richard Henderson --- target-s390x/mem_helper.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c index 04500ab..b4e5d44 100644 --- a/target-s390x/mem_helper.c +++ b/target-s390x/mem_helper.c @@ -213,21 +213,22 @@ void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src) if (dest == (src + 1)) { memset(g2h(dest), cpu_ldub_data(env, src), l + 1); return; - } else { + /* mvc and memmove do not behave the same when areas overlap! */ + } else if ((dest < src) || (src + l < dest)) { memmove(g2h(dest), g2h(src), l + 1); return; } #endif /* handle the parts that fit into 8-byte loads/stores */ - if (dest != (src + 1)) { + if ((dest + 8 <= src) || (src + 8 <= dest)) { for (i = 0; i < l_64; i++) { cpu_stq_data(env, dest + x, cpu_ldq_data(env, src + x)); x += 8; } } - /* slow version crossing pages with byte accesses */ + /* slow version with byte accesses which always work */ for (i = x; i <= l; i++) { cpu_stb_data(env, dest + i, cpu_ldub_data(env, src + i)); }