From nobody Wed Nov 12 10:06:18 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1569596028; cv=none; d=zoho.com; s=zohoarc; b=f+Q1d/6ZUAwF/uXxPXVV7dkDEBPkFsC4vaMHk3IABrd99hDVFIuVkuXZL8Leg5ObTWM1wZD4Goa8v5MB5emk4opgyTy4QRwKSFV8l9jf519k317I823yjcNgiCKlbDS3XGFwzF56leBxwP6psDnDtZqJkXXn1UTM9e45PPlts/U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1569596028; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=8KNTx+nv78pu4/bSjEhSTZyeXaaabzVdW9B9W9A+pI0=; b=KMFSrhaS/naBgPxGVclP8RpLZ7hbsg3+w75UWuXzPkZuF2t5dIKyYNQFPEwNiAOfqC1BLDGdo6K1UmCeqCmNpWwz6IB5/H/g48Ma4agaPYEWMMvixt1WxoVGQIBifSggT5IO8Y8Zr+5Z2lchDdUUmTMqBDHtcE4m9P/1y5roXI4= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1569596028389758.6144436375456; Fri, 27 Sep 2019 07:53:48 -0700 (PDT) Received: from localhost ([::1]:51956 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iDrcw-00037a-MB for importer@patchew.org; Fri, 27 Sep 2019 10:53:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37724) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iDqRY-0001Px-03 for qemu-devel@nongnu.org; Fri, 27 Sep 2019 09:37:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iDqRW-000394-5J for qemu-devel@nongnu.org; Fri, 27 Sep 2019 09:37:55 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58604) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iDqRV-00038S-Sh; Fri, 27 Sep 2019 09:37:54 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 96E0D898101; Fri, 27 Sep 2019 09:59:00 +0000 (UTC) Received: from t460s.redhat.com (ovpn-116-169.ams2.redhat.com [10.36.116.169]) by smtp.corp.redhat.com (Postfix) with ESMTP id C4AC71001B20; Fri, 27 Sep 2019 09:58:58 +0000 (UTC) From: David Hildenbrand To: qemu-devel@nongnu.org Subject: [PATCH v3 7/7] s390x/mmu: Convert to non-recursive page table walk Date: Fri, 27 Sep 2019 11:58:31 +0200 Message-Id: <20190927095831.23543-8-david@redhat.com> In-Reply-To: <20190927095831.23543-1-david@redhat.com> References: <20190927095831.23543-1-david@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.67]); Fri, 27 Sep 2019 09:59:00 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Huth , Janosch Frank , David Hildenbrand , Cornelia Huck , Halil Pasic , Christian Borntraeger , qemu-s390x@nongnu.org, Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" A non-recursive implementation allows to make better use of the branch predictor, avoids function calls, and makes the implementation of new features only for a subset of region table levels easier. We can now directly compare our implementation to the KVM gaccess implementation in arch/s390/kvm/gaccess.c:guest_translate(). Signed-off-by: David Hildenbrand Reviewed-by: Richard Henderson --- target/s390x/mmu_helper.c | 212 ++++++++++++++++++++------------------ 1 file changed, 112 insertions(+), 100 deletions(-) diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c index a114fb1628..6b34c4c7b4 100644 --- a/target/s390x/mmu_helper.c +++ b/target/s390x/mmu_helper.c @@ -114,107 +114,16 @@ static inline bool read_table_entry(CPUS390XState *e= nv, hwaddr gaddr, return true; } =20 -/* Decode page table entry (normal 4KB page) */ -static int mmu_translate_pte(CPUS390XState *env, target_ulong vaddr, - uint64_t asc, uint64_t pt_entry, - target_ulong *raddr, int *flags, int rw, bool= exc) -{ - if (pt_entry & PAGE_ENTRY_I) { - return PGM_PAGE_TRANS; - } - if (pt_entry & PAGE_ENTRY_0) { - return PGM_TRANS_SPEC; - } - if (pt_entry & PAGE_ENTRY_P) { - *flags &=3D ~PAGE_WRITE; - } - - *raddr =3D pt_entry & TARGET_PAGE_MASK; - return 0; -} - -/* Decode segment table entry */ -static int mmu_translate_segment(CPUS390XState *env, target_ulong vaddr, - uint64_t asc, uint64_t st_entry, - target_ulong *raddr, int *flags, int rw, - bool exc) -{ - uint64_t origin, offs, pt_entry; - - if (st_entry & SEGMENT_ENTRY_P) { - *flags &=3D ~PAGE_WRITE; - } - - if ((st_entry & SEGMENT_ENTRY_FC) && (env->cregs[0] & CR0_EDAT)) { - /* Decode EDAT1 segment frame absolute address (1MB page) */ - *raddr =3D (st_entry & SEGMENT_ENTRY_SFAA) | - (vaddr & ~SEGMENT_ENTRY_SFAA); - return 0; - } - - /* Look up 4KB page entry */ - origin =3D st_entry & SEGMENT_ENTRY_ORIGIN; - offs =3D VADDR_PAGE_TX(vaddr) * 8; - if (!read_table_entry(env, origin + offs, &pt_entry)) { - return PGM_ADDRESSING; - } - return mmu_translate_pte(env, vaddr, asc, pt_entry, raddr, flags, rw, = exc); -} - -/* Decode region table entries */ -static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr, - uint64_t asc, uint64_t entry, int level, - target_ulong *raddr, int *flags, int rw, - bool exc) -{ - uint64_t origin, offs, new_entry; - const int pchks[4] =3D { - PGM_SEGMENT_TRANS, PGM_REG_THIRD_TRANS, - PGM_REG_SEC_TRANS, PGM_REG_FIRST_TRANS - }; - - origin =3D entry & REGION_ENTRY_ORIGIN; - offs =3D (vaddr >> (17 + 11 * level / 4)) & 0x3ff8; - - if (!read_table_entry(env, origin + offs, &new_entry)) { - return PGM_ADDRESSING; - } - - if (new_entry & REGION_ENTRY_I) { - return pchks[level / 4]; - } - - if ((new_entry & REGION_ENTRY_TT) !=3D level) { - return PGM_TRANS_SPEC; - } - - if (level =3D=3D ASCE_TYPE_SEGMENT) { - return mmu_translate_segment(env, vaddr, asc, new_entry, raddr, fl= ags, - rw, exc); - } - - /* Check region table offset and length */ - offs =3D (vaddr >> (28 + 11 * (level - 4) / 4)) & 3; - if (offs < ((new_entry & REGION_ENTRY_TF) >> 6) - || offs > (new_entry & REGION_ENTRY_TL)) { - return pchks[level / 4 - 1]; - } - - if ((env->cregs[0] & CR0_EDAT) && (new_entry & REGION_ENTRY_P)) { - *flags &=3D ~PAGE_WRITE; - } - - /* yet another region */ - return mmu_translate_region(env, vaddr, asc, new_entry, level - 4, - raddr, flags, rw, exc); -} - static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr, uint64_t asc, uint64_t asce, target_ulong *r= addr, int *flags, int rw, bool exc) { + const bool edat1 =3D (env->cregs[0] & CR0_EDAT) && + s390_has_feat(S390_FEAT_EDAT); const int asce_tl =3D asce & ASCE_TABLE_LENGTH; - int level; + const int asce_p =3D asce & ASCE_PRIVATE_SPACE; + hwaddr gaddr =3D asce & ASCE_ORIGIN; + uint64_t entry; =20 if (asce & ASCE_REAL_SPACE) { /* direct mapping */ @@ -222,12 +131,12 @@ static int mmu_translate_asce(CPUS390XState *env, tar= get_ulong vaddr, return 0; } =20 - level =3D asce & ASCE_TYPE_MASK; - switch (level) { + switch (asce & ASCE_TYPE_MASK) { case ASCE_TYPE_REGION1: if (VADDR_REGION1_TL(vaddr) > asce_tl) { return PGM_REG_FIRST_TRANS; } + gaddr +=3D VADDR_REGION1_TX(vaddr) * 8; break; case ASCE_TYPE_REGION2: if (VADDR_REGION1_TX(vaddr)) { @@ -236,6 +145,7 @@ static int mmu_translate_asce(CPUS390XState *env, targe= t_ulong vaddr, if (VADDR_REGION2_TL(vaddr) > asce_tl) { return PGM_REG_SEC_TRANS; } + gaddr +=3D VADDR_REGION2_TX(vaddr) * 8; break; case ASCE_TYPE_REGION3: if (VADDR_REGION1_TX(vaddr) || VADDR_REGION2_TX(vaddr)) { @@ -244,6 +154,7 @@ static int mmu_translate_asce(CPUS390XState *env, targe= t_ulong vaddr, if (VADDR_REGION3_TL(vaddr) > asce_tl) { return PGM_REG_THIRD_TRANS; } + gaddr +=3D VADDR_REGION3_TX(vaddr) * 8; break; case ASCE_TYPE_SEGMENT: if (VADDR_REGION1_TX(vaddr) || VADDR_REGION2_TX(vaddr) || @@ -253,11 +164,112 @@ static int mmu_translate_asce(CPUS390XState *env, ta= rget_ulong vaddr, if (VADDR_SEGMENT_TL(vaddr) > asce_tl) { return PGM_SEGMENT_TRANS; } + gaddr +=3D VADDR_SEGMENT_TX(vaddr) * 8; + break; + default: + g_assert_not_reached(); + } + + switch (asce & ASCE_TYPE_MASK) { + case ASCE_TYPE_REGION1: + if (!read_table_entry(env, gaddr, &entry)) { + return PGM_ADDRESSING; + } + if (entry & REGION_ENTRY_I) { + return PGM_REG_FIRST_TRANS; + } + if ((entry & REGION_ENTRY_TT) !=3D REGION_ENTRY_TT_REGION1) { + return PGM_TRANS_SPEC; + } + if (VADDR_REGION2_TL(vaddr) < (entry & REGION_ENTRY_TF) >> 6 || + VADDR_REGION2_TL(vaddr) > (entry & REGION_ENTRY_TL)) { + return PGM_REG_SEC_TRANS; + } + if (edat1 && (entry & REGION_ENTRY_P)) { + *flags &=3D ~PAGE_WRITE; + } + gaddr =3D (entry & REGION_ENTRY_ORIGIN) + VADDR_REGION2_TX(vaddr) = * 8; + /* fall through */ + case ASCE_TYPE_REGION2: + if (!read_table_entry(env, gaddr, &entry)) { + return PGM_ADDRESSING; + } + if (entry & REGION_ENTRY_I) { + return PGM_REG_SEC_TRANS; + } + if ((entry & REGION_ENTRY_TT) !=3D REGION_ENTRY_TT_REGION2) { + return PGM_TRANS_SPEC; + } + if (VADDR_REGION3_TL(vaddr) < (entry & REGION_ENTRY_TF) >> 6 || + VADDR_REGION3_TL(vaddr) > (entry & REGION_ENTRY_TL)) { + return PGM_REG_THIRD_TRANS; + } + if (edat1 && (entry & REGION_ENTRY_P)) { + *flags &=3D ~PAGE_WRITE; + } + gaddr =3D (entry & REGION_ENTRY_ORIGIN) + VADDR_REGION3_TX(vaddr) = * 8; + /* fall through */ + case ASCE_TYPE_REGION3: + if (!read_table_entry(env, gaddr, &entry)) { + return PGM_ADDRESSING; + } + if (entry & REGION_ENTRY_I) { + return PGM_REG_THIRD_TRANS; + } + if ((entry & REGION_ENTRY_TT) !=3D REGION_ENTRY_TT_REGION3) { + return PGM_TRANS_SPEC; + } + if (edat1 && (entry & REGION_ENTRY_P)) { + *flags &=3D ~PAGE_WRITE; + } + if (VADDR_SEGMENT_TL(vaddr) < (entry & REGION_ENTRY_TF) >> 6 || + VADDR_SEGMENT_TL(vaddr) > (entry & REGION_ENTRY_TL)) { + return PGM_SEGMENT_TRANS; + } + gaddr =3D (entry & REGION_ENTRY_ORIGIN) + VADDR_SEGMENT_TX(vaddr) = * 8; + /* fall through */ + case ASCE_TYPE_SEGMENT: + if (!read_table_entry(env, gaddr, &entry)) { + return PGM_ADDRESSING; + } + if (entry & SEGMENT_ENTRY_I) { + return PGM_SEGMENT_TRANS; + } + if ((entry & SEGMENT_ENTRY_TT) !=3D SEGMENT_ENTRY_TT_SEGMENT) { + return PGM_TRANS_SPEC; + } + if ((entry & SEGMENT_ENTRY_CS) && asce_p) { + return PGM_TRANS_SPEC; + } + if (entry & SEGMENT_ENTRY_P) { + *flags &=3D ~PAGE_WRITE; + } + if (edat1 && (entry & SEGMENT_ENTRY_FC)) { + *raddr =3D (entry & SEGMENT_ENTRY_SFAA) | + (vaddr & ~SEGMENT_ENTRY_SFAA); + return 0; + } + gaddr =3D (entry & SEGMENT_ENTRY_ORIGIN) + VADDR_PAGE_TX(vaddr) * = 8; break; + default: + g_assert_not_reached(); + } + + if (!read_table_entry(env, gaddr, &entry)) { + return PGM_ADDRESSING; + } + if (entry & PAGE_ENTRY_I) { + return PGM_PAGE_TRANS; + } + if (entry & PAGE_ENTRY_0) { + return PGM_TRANS_SPEC; + } + if (entry & PAGE_ENTRY_P) { + *flags &=3D ~PAGE_WRITE; } =20 - return mmu_translate_region(env, vaddr, asc, asce, level, raddr, flags= , rw, - exc); + *raddr =3D entry & TARGET_PAGE_MASK; + return 0; } =20 static void mmu_handle_skey(target_ulong addr, int rw, int *flags) --=20 2.21.0