From nobody Sun May 5 11:27:35 2024 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 1508185684515995.9367618858616; Mon, 16 Oct 2017 13:28:04 -0700 (PDT) Received: from localhost ([::1]:35082 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e4BzJ-0004xZ-Ly for importer@patchew.org; Mon, 16 Oct 2017 16:27:49 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46584) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e4Bvn-0002Ag-21 for qemu-devel@nongnu.org; Mon, 16 Oct 2017 16:24:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1e4Bvj-0004YH-J2 for qemu-devel@nongnu.org; Mon, 16 Oct 2017 16:24:11 -0400 Received: from mx1.redhat.com ([209.132.183.28]:10275) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1e4Bvj-0004Xm-AZ; Mon, 16 Oct 2017 16:24:07 -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 5C0E1624DE; Mon, 16 Oct 2017 20:24:06 +0000 (UTC) Received: from t460s.redhat.com (ovpn-116-93.ams2.redhat.com [10.36.116.93]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7804D6062D; Mon, 16 Oct 2017 20:24:01 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 5C0E1624DE Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=david@redhat.com From: David Hildenbrand To: qemu-devel@nongnu.org Date: Mon, 16 Oct 2017 22:23:57 +0200 Message-Id: <20171016202358.3633-2-david@redhat.com> In-Reply-To: <20171016202358.3633-1-david@redhat.com> References: <20171016202358.3633-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.39]); Mon, 16 Oct 2017 20:24:06 +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 v1 1/2] accel/tcg: allow to invalidate a write TLB entry immediately 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: Peter Maydell , Thomas Huth , David Hildenbrand , cohuck@redhat.com, Alexander Graf , qemu-s390x@nongnu.org, Richard Henderson 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" Background: s390x implements Low-Address Protection (LAP). If LAP is enabled, writing to effective addresses (before any transaltion) 0-511 and 4096-4607 triggers a protection exception. So we have subpage protection on the first two pages of every address space (where the lowcore - the CPU private data resides). By immediately invalidating the write entry but allowing the caller to continue, we force every write access onto these first two pages into the slow path. we will get a tlb fault with the specific accessed addresses and can then evaluate if protection applies or not. We have to make sure to ignore the invalid bit if tlb_fill() succeeds. Signed-off-by: David Hildenbrand --- accel/tcg/cputlb.c | 5 ++++- accel/tcg/softmmu_template.h | 4 ++-- include/exec/cpu-all.h | 3 +++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 5b1ef1442c..a23919c3a8 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -694,6 +694,9 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulon= g vaddr, } else { tn.addr_write =3D address; } + if (prot & PAGE_WRITE_INV) { + tn.addr_write |=3D TLB_INVALID_MASK; + } } =20 /* Pairs with flag setting in tlb_reset_dirty_range */ @@ -978,7 +981,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, targe= t_ulong addr, if (!VICTIM_TLB_HIT(addr_write, addr)) { tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, reta= ddr); } - tlb_addr =3D tlbe->addr_write; + tlb_addr =3D tlbe->addr_write & ~TLB_INVALID_MASK; } =20 /* Check notdirty */ diff --git a/accel/tcg/softmmu_template.h b/accel/tcg/softmmu_template.h index d7563292a5..3fc5144316 100644 --- a/accel/tcg/softmmu_template.h +++ b/accel/tcg/softmmu_template.h @@ -285,7 +285,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong = addr, DATA_TYPE val, if (!VICTIM_TLB_HIT(addr_write, addr)) { tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, reta= ddr); } - tlb_addr =3D env->tlb_table[mmu_idx][index].addr_write; + tlb_addr =3D env->tlb_table[mmu_idx][index].addr_write & ~TLB_INVA= LID_MASK; } =20 /* Handle an IO access. */ @@ -361,7 +361,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong = addr, DATA_TYPE val, if (!VICTIM_TLB_HIT(addr_write, addr)) { tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, reta= ddr); } - tlb_addr =3D env->tlb_table[mmu_idx][index].addr_write; + tlb_addr =3D env->tlb_table[mmu_idx][index].addr_write & ~TLB_INVA= LID_MASK; } =20 /* Handle an IO access. */ diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 778031c3d7..0b141683f0 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -245,6 +245,9 @@ extern intptr_t qemu_host_page_mask; /* original state of the write flag (used when tracking self-modifying code */ #define PAGE_WRITE_ORG 0x0010 +/* Invalidate the TLB entry immediately, helpful for s390x + * Low-Address-Protection. Used with PAGE_WRITE in tlb_set_page_with_attrs= () */ +#define PAGE_WRITE_INV 0x0040 #if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY) /* FIXME: Code that sets/uses this is broken and needs to go away. */ #define PAGE_RESERVED 0x0020 --=20 2.13.5 From nobody Sun May 5 11:27:35 2024 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 1508185782708958.4089705722375; Mon, 16 Oct 2017 13:29:42 -0700 (PDT) Received: from localhost ([::1]:35086 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e4C0t-00065O-VS for importer@patchew.org; Mon, 16 Oct 2017 16:29:27 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46593) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e4Bvn-0002B3-Fb for qemu-devel@nongnu.org; Mon, 16 Oct 2017 16:24:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1e4Bvm-0004ZX-1z for qemu-devel@nongnu.org; Mon, 16 Oct 2017 16:24:11 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54688) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1e4Bvl-0004Z3-Or; Mon, 16 Oct 2017 16:24:09 -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 C95B35D5EB; Mon, 16 Oct 2017 20:24:08 +0000 (UTC) Received: from t460s.redhat.com (ovpn-116-93.ams2.redhat.com [10.36.116.93]) by smtp.corp.redhat.com (Postfix) with ESMTP id AE6B517F48; Mon, 16 Oct 2017 20:24:06 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com C95B35D5EB Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=david@redhat.com From: David Hildenbrand To: qemu-devel@nongnu.org Date: Mon, 16 Oct 2017 22:23:58 +0200 Message-Id: <20171016202358.3633-3-david@redhat.com> In-Reply-To: <20171016202358.3633-1-david@redhat.com> References: <20171016202358.3633-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.39]); Mon, 16 Oct 2017 20:24:08 +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 v1 2/2] 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: Peter Maydell , Thomas Huth , David Hildenbrand , cohuck@redhat.com, Alexander Graf , qemu-s390x@nongnu.org, Richard Henderson 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. Reviewed-by: Richard Henderson Signed-off-by: David Hildenbrand --- target/s390x/excp_helper.c | 3 +- target/s390x/mem_helper.c | 8 ---- target/s390x/mmu_helper.c | 94 +++++++++++++++++++++++++++++-------------= ---- 3 files changed, 60 insertions(+), 45 deletions(-) diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c index cff308a18d..e04b670663 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..9806685bee 100644 --- a/target/s390x/mmu_helper.c +++ b/target/s390x/mmu_helper.c @@ -106,6 +106,35 @@ 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 <=3D 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: + g_assert_not_reached(); + } +} + /** * Translate real address to absolute (=3D physical) * address by taking care of the prefix mapping. @@ -323,6 +352,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 +439,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 +523,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