From patchwork Thu Jun 2 06:51:42 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 98554 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 13212B6FAD for ; Fri, 3 Jun 2011 21:46:59 +1000 (EST) Received: from localhost ([::1]:50993 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QSSq7-0006Ql-G4 for incoming@patchwork.ozlabs.org; Fri, 03 Jun 2011 07:46:55 -0400 Received: from eggs.gnu.org ([140.186.70.92]:49028) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QSSmI-0006NV-4Y for qemu-devel@nongnu.org; Fri, 03 Jun 2011 07:43:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QSSmB-0001E7-UG for qemu-devel@nongnu.org; Fri, 03 Jun 2011 07:42:57 -0400 Received: from cantor.suse.de ([195.135.220.2]:36430 helo=mx1.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QSSmA-0001Cq-Lc for qemu-devel@nongnu.org; Fri, 03 Jun 2011 07:42:50 -0400 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.suse.de (Postfix) with ESMTP id C91B9945D8; Fri, 3 Jun 2011 13:42:48 +0200 (CEST) From: Alexander Graf To: "qemu-devel@nongnu.org Developers" Date: Thu, 2 Jun 2011 08:51:42 +0200 Message-Id: <1306997503-29304-13-git-send-email-agraf@suse.de> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: <1306997503-29304-1-git-send-email-agraf@suse.de> References: <1306997503-29304-1-git-send-email-agraf@suse.de> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4-2.6 X-Received-From: 195.135.220.2 Cc: Aurelien Jarno Subject: [Qemu-devel] [PATCH 12/13] s390x: fix cksm instruction 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 cksm instruction was implemented incorrectly, rendering UDP and TCP checksum calculation wrong, making an emulated s390x Linux guest break in most networking operations. This patch fixes odd end checksum calculation, takes the input register as input for the checksum and optimizes the overflow pieces by a bit. Signed-off-by: Alexander Graf --- target-s390x/op_helper.c | 28 ++++++++-------------------- 1 files changed, 8 insertions(+), 20 deletions(-) diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c index 49760a4..db03a79 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/op_helper.c @@ -1731,25 +1731,15 @@ void HELPER(sqdbr)(uint32_t f1, uint32_t f2) env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status); } -static inline uint64_t cksm_overflow(uint64_t cksm) -{ - if (cksm > 0xffffffffULL) { - cksm &= 0xffffffffULL; - cksm++; - } - return cksm; -} - /* checksum */ void HELPER(cksm)(uint32_t r1, uint32_t r2) { uint64_t src = get_address_31fix(r2); uint64_t src_len = env->regs[(r2 + 1) & 15]; - uint64_t cksm = 0; + uint64_t cksm = (uint32_t)env->regs[r1]; while (src_len >= 4) { cksm += ldl(src); - cksm = cksm_overflow(cksm); /* move to next word */ src_len -= 4; @@ -1760,26 +1750,24 @@ void HELPER(cksm)(uint32_t r1, uint32_t r2) case 0: break; case 1: - cksm += ldub(src); - cksm = cksm_overflow(cksm); + cksm += ldub(src) << 24; break; case 2: - cksm += lduw(src); - cksm = cksm_overflow(cksm); + cksm += lduw(src) << 16; break; case 3: - /* XXX check if this really is correct */ - cksm += lduw(src) << 8; - cksm += ldub(src + 2); - cksm = cksm_overflow(cksm); + cksm += lduw(src) << 16; + cksm += ldub(src + 2) << 8; break; } /* indicate we've processed everything */ + env->regs[r2] = src + src_len; env->regs[(r2 + 1) & 15] = 0; /* store result */ - env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | (uint32_t)cksm; + env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | + ((uint32_t)cksm + (cksm >> 32)); } static inline uint32_t cc_calc_ltgt_32(CPUState *env, int32_t src,