From patchwork Wed Jun 20 13:06:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 139326 Delivered-To: patches@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp769282lji; Wed, 20 Jun 2018 06:06:35 -0700 (PDT) X-Google-Smtp-Source: ADUXVKK19zN69WwQlD+MNrToLqjRxHr0ITbUkoTOkDO2hAoA2DP9Baddl0iBtTBuuaUIiF0o+0De X-Received: by 2002:a17:902:89:: with SMTP id a9-v6mr23214832pla.326.1529499991877; Wed, 20 Jun 2018 06:06:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529499986; cv=none; d=google.com; s=arc-20160816; b=LkmVpUCGvAL9OGwZRzUj0ZAsWU/ncXitzQ9TI7GXdfXJ7LjWR5ZOKaKsSe+1urphaN YlWl5o/zY0j2uNw83WX0R/pIn+CixAmt5t/rwhpvUf1ZgGjILkMIrB+L5QYhlp840rFb QZREe5whaUQS0SrqBU8/udklgiAFzf65Z6GfEGnCdUp+Zs78gBsi9aje7TSzdSuzG0fN gvb9QhrNz9ibSI0Em2MdSElQ7VwzgqBKudYzJYPlBfqRG2P0/rFaGoh593O1eeS8gd0G /bXOzVuRK4LIVFdEve/gEiBi2fhiILEorNV2U+ahi/3fQMXbwAnnwq083Hnee6+HckW/ gz7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=ws2eHmbcddDFykZSrslDEX6wlfHRJQ/kUai1F4PfpDY=; b=Tzic2DyFjsHpA5/xYOmxRaeFEnAqVO13pUKeD5J8MDalRdS/rBuVXpXcfoiedDp+wF n8XCpNG4gaNBdN1OpXXEPCNJW4sZXvog/n5rvNmcy/QwqwnCCody2H+z5Jtji8ynpOZS 5Tcc5o04Yn2KCy4nxL+IPT0wE893h0nSdvtlFRXc6IzU8eblQx8IzxfxY3PGhtoABVdw HNcd/boL4e8a9z4gZa+1dtrOIfnXmpxvXEd2BHTzofRAYQIIH86M1+IYTneJHDsRq0+Y p1aZiF8xZZzEjjh0xp1YuuR4pUPX7qugYZzJRVQHtK7m7TsA2BfaqnbCIVa92OZ6pw3A QFqQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id l76-v6si587112pga.120.2018.06.20.06.06.25 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 20 Jun 2018 06:06:26 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fVcoX-0001Vz-W7; Wed, 20 Jun 2018 14:06:21 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, Paolo Bonzini , Richard Henderson Subject: [PATCH 2/3] target/arm: Set page (region) size in get_phys_addr_pmsav7() Date: Wed, 20 Jun 2018 14:06:18 +0100 Message-Id: <20180620130619.11362-3-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180620130619.11362-1-peter.maydell@linaro.org> References: <20180620130619.11362-1-peter.maydell@linaro.org> We want to handle small MPU region sizes for ARMv7M. To do this, make get_phys_addr_pmsav7() set the page size to the region size if it is less that TARGET_PAGE_SIZE, rather than working only in TARGET_PAGE_SIZE chunks. Since the core TCG code con't handle execution from small MPU regions, we strip the exec permission from them so that any execution attempts will cause an MPU exception, rather than allowing it to end up with a cpu_abort() in get_page_addr_code(). (The previous code's intention was to make any small page be treated as having no permissions, but unfortunately errors in the implementation meant that it didn't behave that way. It's possible that some binaries using small regions were accidentally working with our old behaviour and won't now.) Signed-off-by: Peter Maydell --- target/arm/helper.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) -- 2.17.1 diff --git a/target/arm/helper.c b/target/arm/helper.c index 1248d84e6fa..a7edeb66633 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -9596,6 +9596,7 @@ static inline bool m_is_system_region(CPUARMState *env, uint32_t address) static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, hwaddr *phys_ptr, int *prot, + target_ulong *page_size, ARMMMUFaultInfo *fi) { ARMCPU *cpu = arm_env_get_cpu(env); @@ -9603,6 +9604,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, bool is_user = regime_is_user(env, mmu_idx); *phys_ptr = address; + *page_size = TARGET_PAGE_SIZE; *prot = 0; if (regime_translation_disabled(env, mmu_idx) || @@ -9675,16 +9677,12 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, rsize++; } } - if (rsize < TARGET_PAGE_BITS) { - qemu_log_mask(LOG_UNIMP, - "DRSR[%d]: No support for MPU (sub)region size of" - " %" PRIu32 " bytes. Minimum is %d.\n", - n, (1 << rsize), TARGET_PAGE_SIZE); - continue; - } if (srdis) { continue; } + if (rsize < TARGET_PAGE_BITS) { + *page_size = 1 << rsize; + } break; } @@ -9765,6 +9763,17 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, fi->type = ARMFault_Permission; fi->level = 1; + /* + * Core QEMU code can't handle execution from small pages yet, so + * don't try it. This way we'll get an MPU exception, rather than + * eventually causing QEMU to exit in get_page_addr_code(). + */ + if (*page_size < TARGET_PAGE_SIZE && (*prot & PAGE_EXEC)) { + qemu_log_mask(LOG_UNIMP, + "MPU: No support for execution from regions " + "smaller than 1K\n"); + *prot &= ~PAGE_EXEC; + } return !(*prot & (1 << access_type)); } @@ -10334,7 +10343,7 @@ static bool get_phys_addr(CPUARMState *env, target_ulong address, } else if (arm_feature(env, ARM_FEATURE_V7)) { /* PMSAv7 */ ret = get_phys_addr_pmsav7(env, address, access_type, mmu_idx, - phys_ptr, prot, fi); + phys_ptr, prot, page_size, fi); } else { /* Pre-v7 MPU */ ret = get_phys_addr_pmsav5(env, address, access_type, mmu_idx, @@ -10396,9 +10405,15 @@ bool arm_tlb_fill(CPUState *cs, vaddr address, core_to_arm_mmu_idx(env, mmu_idx), &phys_addr, &attrs, &prot, &page_size, fi, NULL); if (!ret) { - /* Map a single [sub]page. */ - phys_addr &= TARGET_PAGE_MASK; - address &= TARGET_PAGE_MASK; + /* + * Map a single [sub]page. Regions smaller than our declared + * target page size are handled specially, so for those we + * pass in the exact addresses. + */ + if (page_size >= TARGET_PAGE_SIZE) { + phys_addr &= TARGET_PAGE_MASK; + address &= TARGET_PAGE_MASK; + } tlb_set_page_with_attrs(cs, address, phys_addr, attrs, prot, mmu_idx, page_size); return 0;