From nobody Sun Feb 8 21:47:47 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.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 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1506531947311751.7301789310354; Wed, 27 Sep 2017 10:05:47 -0700 (PDT) Received: from localhost ([::1]:55642 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dxFmM-0001hd-LL for importer@patchew.org; Wed, 27 Sep 2017 13:05:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60091) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dxFhX-0006dX-2V for qemu-devel@nongnu.org; Wed, 27 Sep 2017 13:00:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dxFhS-000663-P2 for qemu-devel@nongnu.org; Wed, 27 Sep 2017 13:00:47 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53376) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dxFhS-00065O-GV for qemu-devel@nongnu.org; Wed, 27 Sep 2017 13:00:42 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7E14B16349C; Wed, 27 Sep 2017 17:00:41 +0000 (UTC) Received: from t460s.redhat.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id 005A2E8184; Wed, 27 Sep 2017 17:00:38 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 7E14B16349C Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=david@redhat.com From: David Hildenbrand To: qemu-devel@nongnu.org Date: Wed, 27 Sep 2017 19:00:26 +0200 Message-Id: <20170927170027.8539-3-david@redhat.com> In-Reply-To: <20170927170027.8539-1-david@redhat.com> References: <20170927170027.8539-1-david@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Wed, 27 Sep 2017 17:00:41 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH RFC 2/3] s390x/tcg: low-address protection support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: thuth@redhat.com, David Hildenbrand , cohuck@redhat.com, Richard Henderson , Alexander Graf , Christian Borntraeger Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This is a neat way to implement low address protection, whereby only the first 512 bytes of the first two pages (each 4096 bytes) of every address space are protected. Store a tec of 0 for the access exception, this is what is defined by Enhanced Suppression on Protection in case of a low address protection (Bit 61 set to 0, rest undefined). We have to make sure to to pass the access address, not the masked page address into mmu_translate*(). Drop the check from testblock. So we can properly test this via kvm-unit-tests. This will check every access going through one of the MMUs. Signed-off-by: David Hildenbrand Reviewed-by: Richard Henderson --- target/s390x/excp_helper.c | 3 +- target/s390x/mem_helper.c | 8 ---- target/s390x/mmu_helper.c | 96 +++++++++++++++++++++++++++++-------------= ---- 3 files changed, 62 insertions(+), 45 deletions(-) diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c index 3e4349d00b..aa0cbf67ac 100644 --- a/target/s390x/excp_helper.c +++ b/target/s390x/excp_helper.c @@ -95,7 +95,6 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_va= ddr, DPRINTF("%s: address 0x%" VADDR_PRIx " rw %d mmu_idx %d\n", __func__, orig_vaddr, rw, mmu_idx); =20 - orig_vaddr &=3D TARGET_PAGE_MASK; vaddr =3D orig_vaddr; =20 if (mmu_idx < MMU_REAL_IDX) { @@ -127,7 +126,7 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_= vaddr, qemu_log_mask(CPU_LOG_MMU, "%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x= )\n", __func__, (uint64_t)vaddr, (uint64_t)raddr, prot); =20 - tlb_set_page(cs, orig_vaddr, raddr, prot, + tlb_set_page(cs, orig_vaddr & TARGET_PAGE_MASK, raddr, prot, mmu_idx, TARGET_PAGE_SIZE); =20 return 0; diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index bbbe1c62b3..69a16867d4 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1687,18 +1687,10 @@ void HELPER(stctl)(CPUS390XState *env, uint32_t r1,= uint64_t a2, uint32_t r3) uint32_t HELPER(testblock)(CPUS390XState *env, uint64_t real_addr) { uintptr_t ra =3D GETPC(); - CPUState *cs =3D CPU(s390_env_get_cpu(env)); int i; =20 real_addr =3D wrap_address(env, real_addr) & TARGET_PAGE_MASK; =20 - /* Check low-address protection */ - if ((env->cregs[0] & CR0_LOWPROT) && real_addr < 0x2000) { - cpu_restore_state(cs, ra); - program_interrupt(env, PGM_PROTECTION, 4); - return 1; - } - for (i =3D 0; i < TARGET_PAGE_SIZE; i +=3D 8) { cpu_stq_real_ra(env, real_addr + i, 0, ra); } diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c index 9daa0fd8e2..44a15449d2 100644 --- a/target/s390x/mmu_helper.c +++ b/target/s390x/mmu_helper.c @@ -106,6 +106,37 @@ static void trigger_page_fault(CPUS390XState *env, tar= get_ulong vaddr, trigger_access_exception(env, type, ilen, tec); } =20 +/* check whether the address would be proteted by Low-Address Protection */ +static bool is_low_address(uint64_t addr) +{ + return addr < 512 || (addr >=3D 4096 && addr < 4607); +} + +/* check whether Low-Address Protection is enabled for mmu_translate() */ +static bool lowprot_enabled(const CPUS390XState *env, uint64_t asc) +{ + if (!(env->cregs[0] & CR0_LOWPROT)) { + return false; + } + if (!(env->psw.mask & PSW_MASK_DAT)) { + return true; + } + + /* Check the private-space control bit */ + switch (asc) { + case PSW_ASC_PRIMARY: + return !(env->cregs[1] & _ASCE_PRIVATE_SPACE); + case PSW_ASC_SECONDARY: + return !(env->cregs[7] & _ASCE_PRIVATE_SPACE); + case PSW_ASC_HOME: + return !(env->cregs[13] & _ASCE_PRIVATE_SPACE); + default: + /* We don't support access register mode */ + error_report("unsupported addressing mode"); + exit(1); + } +} + /** * Translate real address to absolute (=3D physical) * address by taking care of the prefix mapping. @@ -323,6 +354,24 @@ int mmu_translate(CPUS390XState *env, target_ulong vad= dr, int rw, uint64_t asc, } =20 *flags =3D PAGE_READ | PAGE_WRITE | PAGE_EXEC; + if (is_low_address(vaddr & TARGET_PAGE_MASK) && lowprot_enabled(env, a= sc)) { + /* + * If any part of this page is currently protected, make sure the + * TLB entry will not be reused. + * + * As the protected range is always the first 512 bytes of the + * two first pages, we are able to catch all writes to these areas + * just by looking at the start address (triggering the tlb miss). + */ + *flags |=3D PAGE_WRITE_INV; + if (is_low_address(vaddr) && rw =3D=3D MMU_DATA_STORE) { + if (exc) { + trigger_access_exception(env, PGM_PROTECTION, ILEN_AUTO, 0= ); + } + return -EACCES; + } + } + vaddr &=3D TARGET_PAGE_MASK; =20 if (!(env->psw.mask & PSW_MASK_DAT)) { @@ -392,50 +441,17 @@ int mmu_translate(CPUS390XState *env, target_ulong va= ddr, int rw, uint64_t asc, } =20 /** - * lowprot_enabled: Check whether low-address protection is enabled - */ -static bool lowprot_enabled(const CPUS390XState *env) -{ - if (!(env->cregs[0] & CR0_LOWPROT)) { - return false; - } - if (!(env->psw.mask & PSW_MASK_DAT)) { - return true; - } - - /* Check the private-space control bit */ - switch (env->psw.mask & PSW_MASK_ASC) { - case PSW_ASC_PRIMARY: - return !(env->cregs[1] & _ASCE_PRIVATE_SPACE); - case PSW_ASC_SECONDARY: - return !(env->cregs[7] & _ASCE_PRIVATE_SPACE); - case PSW_ASC_HOME: - return !(env->cregs[13] & _ASCE_PRIVATE_SPACE); - default: - /* We don't support access register mode */ - error_report("unsupported addressing mode"); - exit(1); - } -} - -/** * translate_pages: Translate a set of consecutive logical page addresses * to absolute addresses */ static int translate_pages(S390CPU *cpu, vaddr addr, int nr_pages, target_ulong *pages, bool is_write) { - bool lowprot =3D is_write && lowprot_enabled(&cpu->env); uint64_t asc =3D cpu->env.psw.mask & PSW_MASK_ASC; CPUS390XState *env =3D &cpu->env; int ret, i, pflags; =20 for (i =3D 0; i < nr_pages; i++) { - /* Low-address protection? */ - if (lowprot && (addr < 512 || (addr >=3D 4096 && addr < 4096 + 512= ))) { - trigger_access_exception(env, PGM_PROTECTION, ILEN_AUTO, 0); - return -EACCES; - } ret =3D mmu_translate(env, addr, is_write, asc, &pages[i], &pflags= , true); if (ret) { return ret; @@ -509,9 +525,19 @@ int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, ui= nt8_t ar, void *hostbuf, int mmu_translate_real(CPUS390XState *env, target_ulong raddr, int rw, target_ulong *addr, int *flags) { - /* TODO: low address protection once we flush the tlb on cr changes */ + const bool lowprot_enabled =3D env->cregs[0] & CR0_LOWPROT; + *flags =3D PAGE_READ | PAGE_WRITE; - *addr =3D mmu_real2abs(env, raddr); + if (is_low_address(raddr & TARGET_PAGE_MASK) && lowprot_enabled) { + /* see comment in mmu_translate() how this works */ + *flags |=3D PAGE_WRITE_INV; + if (is_low_address(raddr) && rw =3D=3D MMU_DATA_STORE) { + trigger_access_exception(env, PGM_PROTECTION, ILEN_AUTO, 0); + return -EACCES; + } + } + + *addr =3D mmu_real2abs(env, raddr & TARGET_PAGE_MASK); =20 /* TODO: storage key handling */ return 0; --=20 2.13.5