From patchwork Thu Feb 15 20:52:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Caleb Connolly X-Patchwork-Id: 773027 Delivered-To: patch@linaro.org Received: by 2002:adf:9dc2:0:b0:33b:4db1:f5b3 with SMTP id q2csp1036768wre; Thu, 15 Feb 2024 12:59:20 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCX+EfojSyn4Ijg7IWKU/T6S4a9FfCtik/YtgtcrDoCuSQVIR3wl2MwR69fxtKZvk7reYBGX9ZbiAt9NnrAGuL3a X-Google-Smtp-Source: AGHT+IHadRVDQe4zyjmXvZOB/biN8tHeO+wC0iM/j6gEPvEq94zQoQai+bNAIDj/OYOO/eXR8Adp X-Received: by 2002:a17:906:f4e:b0:a3d:9a28:52e6 with SMTP id h14-20020a1709060f4e00b00a3d9a2852e6mr1748185ejj.50.1708030760012; Thu, 15 Feb 2024 12:59:20 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1708030759; cv=none; d=google.com; s=arc-20160816; b=pGJrflBhy8Q/tEEHWy7WcxpYEWrKY9UznU5Qrp7lOrSsr4jqOPIxV6hJxDEAL9XRUT 0LNgCREUdYSL8FI2/Z++Zj/Md5v9RKy+diEuRJ2UEtkvoP81TmqzD7lt+ymhKcUt15Gb XInB89UE1+gbKMB5YpnbbKGN7U35KzVhT+um2E6hDMM+Cm1z9V4JcfSpMFOHd3xgo1J/ fFmzr2+HThjnucB9GP/ZDlS6SVyDwmjP3uAGHu/PyOci/peO2IyUpYdF3dVVXw74H0hl nGLOLAu5LAjQIrTaUNDqIWKP0xtemPgQ0nqTet5sxtksNQsm9gFU43eFBWm+AfUmeCZP wvqg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:cc:to:in-reply-to:references :message-id:content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=3nGsG1La79C+vZkTTuFd/Hd+jEjcf96rfARUkQOE49E=; fh=I5vtxyBeTFwKz5EoRV8VBMUrmyvnAKL8/bdOSua+kuk=; b=CTTSH+pAOdOr2UY21Cj0ZgjQA4+pJO5DgvFBvOVIIVhWnWIJ1PFibcQmEhPL8fBAfc jyn043U2lTMVG1ytMJqQp0+Gt2Ed2j3xLqh22f1v3pcqKx+vBvXDxYBaK+nv+niY4WX3 2ZwKsdEMbTc+Cc+m5046HSucl2TnrTTQNK3uGARqYoHmNrKwXQ+1G+trbzOk8T+UxSey 7pB0rQRK2EXmH/hr54vAr3w0KYL6iZfuUciE1tNJ/l9g+eXWDUjXsvZvIQBOl8bRyOpM ReGs6hMLwxS3VX97dzo8hE+33M+eY0vXk81JuvnXh63W8dieLEhsXWSjBJ6gYd7/d0F/ lTcg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=AZMXdUjH; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id h8-20020a170906260800b00a3c02c21607si983170ejc.357.2024.02.15.12.59.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 12:59:19 -0800 (PST) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=AZMXdUjH; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 2422887F7A; Thu, 15 Feb 2024 21:53:54 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="AZMXdUjH"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 82A8A87E32; Thu, 15 Feb 2024 21:53:42 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, T_SCC_BODY_TEXT_LINE,T_SPF_TEMPERROR autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 8FBE987E77 for ; Thu, 15 Feb 2024 21:52:48 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=caleb.connolly@linaro.org Received: by mail-wr1-x434.google.com with SMTP id ffacd0b85a97d-33d066f8239so528436f8f.1 for ; Thu, 15 Feb 2024 12:52:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1708030367; x=1708635167; darn=lists.denx.de; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=3nGsG1La79C+vZkTTuFd/Hd+jEjcf96rfARUkQOE49E=; b=AZMXdUjHp99vOafoWUFVls7s9mEb+q4uvvn0FFeAIMr1q5s7WxrrpluXuOESgZIJO2 A5hQ5DjqvRLgYY1XSCyC0DK8kLIV32m7uKXpqLQyyRouga9YnqdFM9UmOZ4fYAMlAGla tr1sCVI8A14vS2hHGkQDMPWdvGheW1X+kYAJb0nIRECaLLyIHf75HOctOHJrBKzdmpHh j8//vCprPdFNO9/rW68WxcDqn3DH6qjDDtCH+x58f6yND6pCKQwT96AKzBu2K/m2Ho/3 7vCJUBwGrGRsL5MJc+Q2biA7u5jbHaYNg7wMiBG0+lZfZnbCEi0Jf+bxySZwyn6dkjZo Ieyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708030367; x=1708635167; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3nGsG1La79C+vZkTTuFd/Hd+jEjcf96rfARUkQOE49E=; b=qxUeRpI0auvFQVx+1Ed+QFSSRZGZ6DS2S284S5MaWkL8gZXgmoKkapVKe4zp8QXNUr V4PN+nvYWlyBumCly77Y19xHqaT9rdnmSBGRhgv3yMBX5IYt18UrE1dUy7izkQDKkBPZ sYEmexc1IAEn3pALhDBAi2ituDwpIerVGATdNTzC9vg41iOcBvMS7SNNj7Blqo3gsaZx vi0W5b6JUFTcPQ2g3P0YyKUs2ngqpD1ZSpywVdPw/ZgWilEjTbOxefDZh0dDmJ6DmJTu 6Gk+QxvVIJ+8i8cEeNw7vZWsW1ngF2WzdC4NE0dBfRUIgzo1boWANDH1B1AN4tiOduD6 4Lvg== X-Forwarded-Encrypted: i=1; AJvYcCV0q0InV1JUQgyQvg3sIRjyBxot8AJJYnZSAMM5jm3bSewI8h5QYMRWnBnGg7Y2shdONhrWe0JXYczYHGorImeqnlyXSA== X-Gm-Message-State: AOJu0Yxnn98kAawmfPJkPNf/MJp5p/+tr1E82yid+cgG0Tr7sfU9TGBL 0osDFSCm5Aan2qEf8jSR0QU446oCjJUeIbnEw/Q5E6k7hagZ82UXjxP/ppD0wt+zjTE0W1ENlHV N X-Received: by 2002:adf:e8d0:0:b0:33d:1062:4d70 with SMTP id k16-20020adfe8d0000000b0033d10624d70mr1439332wrn.14.1708030367642; Thu, 15 Feb 2024 12:52:47 -0800 (PST) Received: from lion.localdomain (host-92-17-96-232.as13285.net. [92.17.96.232]) by smtp.gmail.com with ESMTPSA id e4-20020adfe384000000b0033cfa00e497sm194025wrm.64.2024.02.15.12.52.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 12:52:47 -0800 (PST) From: Caleb Connolly Date: Thu, 15 Feb 2024 20:52:41 +0000 Subject: [PATCH v4 23/39] mach-snapdragon: carve out no-map regions MIME-Version: 1.0 Message-Id: <20240215-b4-qcom-common-target-v4-23-ed06355c634a@linaro.org> References: <20240215-b4-qcom-common-target-v4-0-ed06355c634a@linaro.org> In-Reply-To: <20240215-b4-qcom-common-target-v4-0-ed06355c634a@linaro.org> To: Neil Armstrong , Sumit Garg , Ramon Fried , Dzmitry Sankouski , Caleb Connolly , Peng Fan , Jaehoon Chung , Rayagonda Kokatanur , Lukasz Majewski , Sean Anderson , Jorge Ramirez-Ortiz , Stephan Gerhold Cc: Marek Vasut , u-boot@lists.denx.de X-Mailer: b4 0.13-dev-4bd13 X-Developer-Signature: v=1; a=openpgp-sha256; l=7421; i=caleb.connolly@linaro.org; h=from:subject:message-id; bh=B71Tj+IEa6aadfutZmKU9MlHEMT2tEtxIJHJj5NYLX8=; b=owGbwMvMwCFYaeA6f6eBkTjjabUkhtRzlW0tPX2pfFsfJJ9VfKooZDhn6SvdIz+jGzc2nfzKU Ntpfsqko5SFQZCDQVZMkUX8xDLLprWX7TW2L7gAM4eVCWQIAxenAEykKY/hf93LpxrnWN+bfUi+ /Ujw/36ZNZfX7/ZeM+FSyhxvvS0eAkEMv9mPH1Lg6Ko4Mrese7b4Ooav/P1c01fYSu01WL4gU7r 70R8A X-Developer-Key: i=caleb.connolly@linaro.org; a=openpgp; fpr=83B24DA7FE145076BC38BB250CD904EB673A7C47 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean On Qualcomm platforms, the TZ may already have certain memory regions under protection by the time U-Boot starts. There is a rare case on some platforms where the prefetcher might speculatively access one of these regions resulting in a board crash (TZ traps and then resets the board). We shouldn't be accessing these regions from within U-Boot anyway, so let's mark them all with PTE_TYPE_FAULT to prevent any speculative access and correctly trap in EL1 rather than EL3. This is quite costly with caches off (takes ~2 seconds on SDM845 vs 35ms with caches on). So to minimise the impact this is only enabled on QCS404 for now (where the issue is known to occur). In the future, we should try to find a more efficient way to handle this, perhaps by turning on the MMU in stages. Signed-off-by: Caleb Connolly Reviewed-by: Sumit Garg --- arch/arm/mach-snapdragon/board.c | 162 +++++++++++++++++++++++++++++++++------ 1 file changed, 140 insertions(+), 22 deletions(-) diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c index 5a859aabd5c4..f12f5791a136 100644 --- a/arch/arm/mach-snapdragon/board.c +++ b/arch/arm/mach-snapdragon/board.c @@ -25,6 +25,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -296,7 +297,7 @@ int board_late_init(void) static void build_mem_map(void) { - int i; + int i, j; /* * Ensure the peripheral block is sized to correctly cover the address range @@ -312,28 +313,23 @@ static void build_mem_map(void) PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN; - debug("Configured memory map:\n"); - debug(" 0x%016llx - 0x%016llx: Peripheral block\n", - mem_map[0].phys, mem_map[0].phys + mem_map[0].size); - - /* - * Now add memory map entries for each DRAM bank, ensuring we don't - * overwrite the list terminator - */ - for (i = 0; i < ARRAY_SIZE(rbx_mem_map) - 2 && gd->bd->bi_dram[i].size; i++) { - if (i == ARRAY_SIZE(rbx_mem_map) - 1) { - log_warning("Too many DRAM banks!\n"); - break; - } - mem_map[i + 1].phys = gd->bd->bi_dram[i].start; - mem_map[i + 1].virt = mem_map[i + 1].phys; - mem_map[i + 1].size = gd->bd->bi_dram[i].size; - mem_map[i + 1].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | - PTE_BLOCK_INNER_SHARE; - - debug(" 0x%016llx - 0x%016llx: DDR bank %d\n", - mem_map[i + 1].phys, mem_map[i + 1].phys + mem_map[i + 1].size, i); + for (i = 1, j = 0; i < ARRAY_SIZE(rbx_mem_map) - 1 && gd->bd->bi_dram[j].size; i++, j++) { + mem_map[i].phys = gd->bd->bi_dram[j].start; + mem_map[i].virt = mem_map[i].phys; + mem_map[i].size = gd->bd->bi_dram[j].size; + mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | \ + PTE_BLOCK_INNER_SHARE; } + + mem_map[i].phys = UINT64_MAX; + mem_map[i].size = 0; + +#ifdef DEBUG + debug("Configured memory map:\n"); + for (i = 0; mem_map[i].size; i++) + debug(" 0x%016llx - 0x%016llx: entry %d\n", + mem_map[i].phys, mem_map[i].phys + mem_map[i].size, i); +#endif } u64 get_page_table_size(void) @@ -341,10 +337,132 @@ u64 get_page_table_size(void) return SZ_64K; } +static int fdt_cmp_res(const void *v1, const void *v2) +{ + const struct fdt_resource *res1 = v1, *res2 = v2; + + return res1->start - res2->start; +} + +#define N_RESERVED_REGIONS 32 + +/* Mark all no-map regions as PTE_TYPE_FAULT to prevent speculative access. + * On some platforms this is enough to trigger a security violation and trap + * to EL3. + */ +static void carve_out_reserved_memory(void) +{ + static struct fdt_resource res[N_RESERVED_REGIONS] = { 0 }; + int parent, rmem, count, i = 0; + phys_addr_t start; + size_t size; + + /* Some reserved nodes must be carved out, as the cache-prefetcher may otherwise + * attempt to access them, causing a security exception. + */ + parent = fdt_path_offset(gd->fdt_blob, "/reserved-memory"); + if (parent <= 0) { + log_err("No reserved memory regions found\n"); + return; + } + + /* Collect the reserved memory regions */ + fdt_for_each_subnode(rmem, gd->fdt_blob, parent) { + const fdt32_t *ptr; + int len; + if (!fdt_getprop(gd->fdt_blob, rmem, "no-map", NULL)) + continue; + + if (i == N_RESERVED_REGIONS) { + log_err("Too many reserved regions!\n"); + break; + } + + /* Read the address and size out from the reg property. Doing this "properly" with + * fdt_get_resource() takes ~70ms on SDM845, but open-coding the happy path here + * takes <1ms... Oh the woes of no dcache. + */ + ptr = fdt_getprop(gd->fdt_blob, rmem, "reg", &len); + if (ptr) { + /* Qualcomm devices use #address/size-cells = <2> but all reserved regions are within + * the 32-bit address space. So we can cheat here for speed. + */ + res[i].start = fdt32_to_cpu(ptr[1]); + res[i].end = res[i].start + fdt32_to_cpu(ptr[3]); + i++; + } + } + + /* Sort the reserved memory regions by address */ + count = i; + qsort(res, count, sizeof(struct fdt_resource), fdt_cmp_res); + + /* Now set the right attributes for them. Often a lot of the regions are tightly packed together + * so we can optimise the number of calls to mmu_change_region_attr() by combining adjacent + * regions. + */ + start = ALIGN_DOWN(res[0].start, SZ_2M); + size = ALIGN(res[0].end - start, SZ_2M); + for (i = 1; i <= count; i++) { + /* We ideally want to 2M align everything for more efficient pagetables, but we must avoid + * overwriting reserved memory regions which shouldn't be mapped as FAULT (like those with + * compatible properties). + * If within 2M of the previous region, bump the size to include this region. Otherwise + * start a new region. + */ + if (i == count || start + size < res[i].start - SZ_2M) { + debug(" 0x%016llx - 0x%016llx: reserved\n", + start, start + size); + mmu_change_region_attr(start, size, PTE_TYPE_FAULT); + /* If this is the final region then quit here before we index + * out of bounds... + */ + if (i == count) + break; + start = ALIGN_DOWN(res[i].start, SZ_2M); + size = ALIGN(res[i].end - start, SZ_2M); + } else { + /* Bump size if this region is immediately after the previous one */ + size = ALIGN(res[i].end - start, SZ_2M); + } + } +} + +/* This function open-codes setup_all_pgtables() so that we can + * insert additional mappings *before* turning on the MMU. + */ void enable_caches(void) { + u64 tlb_addr = gd->arch.tlb_addr; + u64 tlb_size = gd->arch.tlb_size; + u64 pt_size; + ulong carveout_start; + + gd->arch.tlb_fillptr = tlb_addr; + build_mem_map(); icache_enable(); + + /* Create normal system page tables */ + setup_pgtables(); + + pt_size = (uintptr_t)gd->arch.tlb_fillptr - + (uintptr_t)gd->arch.tlb_addr; + debug("Primary pagetable size: %lluKiB\n", pt_size / 1024); + + /* Create emergency page tables */ + gd->arch.tlb_size -= pt_size; + gd->arch.tlb_addr = gd->arch.tlb_fillptr; + setup_pgtables(); + gd->arch.tlb_emerg = gd->arch.tlb_addr; + gd->arch.tlb_addr = tlb_addr; + gd->arch.tlb_size = tlb_size; + + carveout_start = get_timer(0); + /* Takes ~20-50ms on SDM845 */ + carve_out_reserved_memory(); + debug("carveout time: %lums\n", get_timer(carveout_start)); + dcache_enable(); }