From nobody Thu Apr 2 23:57:09 2026 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id ED7041E32CF; Mon, 16 Feb 2026 14:26:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771251978; cv=none; b=UyUE/5XVj60d+Wccp/kjGYdSSr/ieHmotw1H4oQtvDq/5QEEIm6ue5DcgGhgnymwaqBBHk9wdZKFDRttOxO69NqKXyciuBvWduJ5CbBfGGu7Qc/S5jI84JfIv5FUEW9wsiMQMCNN6r8zrnnzIJtH+OogX4Hq/nchwOTSINXQXZM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771251978; c=relaxed/simple; bh=rLmnyxyErHYiXtdh+CV6iMzJzbzCJSo0gnxl2xhAGRA=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=krtCZ+06owxagtKfJqttFcTewe+dNAw/tokQdwvHKKoIC+ie7f+19pcBXGcE2i3nNkkDw2h77GeIiLSE/xSnVuqCvekefqBHYcfyPWh4DUzXT5Xm/5NTAxnmSHxzLINk27PVUbejMoZLAySTa/OocWnafRQzBHo227N29ffTFZE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [223.64.68.227]) by gateway (Coremail) with SMTP id _____8Dx88D_KJNpetISAA--.82S3; Mon, 16 Feb 2026 22:26:07 +0800 (CST) Received: from kernelserver (unknown [223.64.68.227]) by front1 (Coremail) with SMTP id qMiowJCxdcD3KJNpUiFHAA--.20742S2; Mon, 16 Feb 2026 22:26:03 +0800 (CST) From: Huacai Chen To: Greg Kroah-Hartman , Sasha Levin , Huacai Chen Cc: Xuerui Wang , stable@vger.kernel.org, linux-kernel@vger.kernel.org, loongarch@lists.linux.dev, Tiezhu Yang , Huacai Chen Subject: [PATCH V2 for 6.6 & 6.12] LoongArch: Rework KASAN initialization for PTW-enabled systems Date: Mon, 16 Feb 2026 22:25:50 +0800 Message-ID: <20260216142550.1479337-1-chenhuacai@loongson.cn> X-Mailer: git-send-email 2.52.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: qMiowJCxdcD3KJNpUiFHAA--.20742S2 X-CM-SenderInfo: hfkh0x5xdftxo6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj93XoW3Wry5Kw1fAF4kAr1kGr13KFX_yoW7ur43pr WkKa48Kr4vvr4qqwsxGw1UZry8Jws3Ca97tFZxta9Ykay7CF1Fqr1kGF97ZF1UWrW8JF1Y 9w1SvFWDGr45JacCm3ZEXasCq-sJn29KB7ZKAUJUUUUr529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUvEb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Jr0_JF4l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Jr0_Gr1l84ACjcxK6I8E87Iv67AKxVW8JVWxJwA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_ Gr0_Gr1UM2kKe7AKxVWUXVWUAwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07AIYI kI8VC2zVCFFI0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWUXVWU AwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI4 8JMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMxCIbckI1I0E14v26r1Y 6r17MI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7 AF67AKxVWUtVW8ZwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE 2Ix0cI8IcVCY1x0267AKxVWUJVW8JwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcV C2z280aVAFwI0_Jr0_Gr1lIxAIcVC2z280aVCY1x0267AKxVWUJVW8JbIYCTnIWIevJa73 UjIFyTuYvjxU2MKZDUUUU Content-Type: text/plain; charset="utf-8" From: Tiezhu Yang commit 5ec5ac4ca27e4daa234540ac32f9fc5219377d53 upstream. kasan_init_generic() indicates that kasan is fully initialized, so it should be put at end of kasan_init(). Otherwise bringing up the primary CPU failed when CONFIG_KASAN is set on PTW-enabled systems, here are the call chains: kernel_entry() start_kernel() setup_arch() kasan_init() kasan_init_generic() The reason is PTW-enabled systems have speculative accesses which means memory accesses to the shadow memory after kasan_init() may be executed by hardware before. However, accessing shadow memory is safe only after kasan fully initialized because kasan_init() uses a temporary PGD table until we have populated all levels of shadow page tables and writen the PGD register. Moving kasan_init_generic() later can defer the occasion of kasan_enabled(), so as to avoid speculative accesses on shadow pages. After moving kasan_init_generic() to the end, kasan_init() can no longer call kasan_mem_to_shadow() for shadow address conversion because it will always return kasan_early_shadow_page. On the other hand, we should keep the current logic of kasan_mem_to_shadow() for both the early and final stage because there may be instrumentation before kasan_init(). To solve this, we factor out a new mem_to_shadow() function from current kasan_mem_to_shadow() for the shadow address conversion in kasan_init(). [ Huacai: To backport from upstream to 6.6 & 6.12, kasan_enabled() is replaced with kasan_arch_is_ready() and kasan_init_generic() is replaced with "kasan_early_stage =3D false". ] Cc: stable@vger.kernel.org Signed-off-by: Tiezhu Yang Signed-off-by: Huacai Chen --- arch/loongarch/mm/kasan_init.c | 77 ++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/arch/loongarch/mm/kasan_init.c b/arch/loongarch/mm/kasan_init.c index d2681272d8f0..9337380a70eb 100644 --- a/arch/loongarch/mm/kasan_init.c +++ b/arch/loongarch/mm/kasan_init.c @@ -42,39 +42,43 @@ static pgd_t kasan_pg_dir[PTRS_PER_PGD] __initdata __al= igned(PAGE_SIZE); =20 bool kasan_early_stage =3D true; =20 -void *kasan_mem_to_shadow(const void *addr) +static void *mem_to_shadow(const void *addr) { - if (!kasan_arch_is_ready()) { + unsigned long offset =3D 0; + unsigned long maddr =3D (unsigned long)addr; + unsigned long xrange =3D (maddr >> XRANGE_SHIFT) & 0xffff; + + if (maddr >=3D FIXADDR_START) return (void *)(kasan_early_shadow_page); - } else { - unsigned long maddr =3D (unsigned long)addr; - unsigned long xrange =3D (maddr >> XRANGE_SHIFT) & 0xffff; - unsigned long offset =3D 0; - - if (maddr >=3D FIXADDR_START) - return (void *)(kasan_early_shadow_page); - - maddr &=3D XRANGE_SHADOW_MASK; - switch (xrange) { - case XKPRANGE_CC_SEG: - offset =3D XKPRANGE_CC_SHADOW_OFFSET; - break; - case XKPRANGE_UC_SEG: - offset =3D XKPRANGE_UC_SHADOW_OFFSET; - break; - case XKPRANGE_WC_SEG: - offset =3D XKPRANGE_WC_SHADOW_OFFSET; - break; - case XKVRANGE_VC_SEG: - offset =3D XKVRANGE_VC_SHADOW_OFFSET; - break; - default: - WARN_ON(1); - return NULL; - } =20 - return (void *)((maddr >> KASAN_SHADOW_SCALE_SHIFT) + offset); + maddr &=3D XRANGE_SHADOW_MASK; + switch (xrange) { + case XKPRANGE_CC_SEG: + offset =3D XKPRANGE_CC_SHADOW_OFFSET; + break; + case XKPRANGE_UC_SEG: + offset =3D XKPRANGE_UC_SHADOW_OFFSET; + break; + case XKPRANGE_WC_SEG: + offset =3D XKPRANGE_WC_SHADOW_OFFSET; + break; + case XKVRANGE_VC_SEG: + offset =3D XKVRANGE_VC_SHADOW_OFFSET; + break; + default: + WARN_ON(1); + return NULL; } + + return (void *)((maddr >> KASAN_SHADOW_SCALE_SHIFT) + offset); +} + +void *kasan_mem_to_shadow(const void *addr) +{ + if (kasan_arch_is_ready()) + return mem_to_shadow(addr); + else + return (void *)(kasan_early_shadow_page); } =20 const void *kasan_shadow_to_mem(const void *shadow_addr) @@ -295,10 +299,8 @@ void __init kasan_init(void) /* Maps everything to a single page of zeroes */ kasan_pgd_populate(KASAN_SHADOW_START, KASAN_SHADOW_END, NUMA_NO_NODE, tr= ue); =20 - kasan_populate_early_shadow(kasan_mem_to_shadow((void *)VMALLOC_START), - kasan_mem_to_shadow((void *)KFENCE_AREA_END)); - - kasan_early_stage =3D false; + kasan_populate_early_shadow(mem_to_shadow((void *)VMALLOC_START), + mem_to_shadow((void *)KFENCE_AREA_END)); =20 /* Populate the linear mapping */ for_each_mem_range(i, &pa_start, &pa_end) { @@ -308,13 +310,13 @@ void __init kasan_init(void) if (start >=3D end) break; =20 - kasan_map_populate((unsigned long)kasan_mem_to_shadow(start), - (unsigned long)kasan_mem_to_shadow(end), NUMA_NO_NODE); + kasan_map_populate((unsigned long)mem_to_shadow(start), + (unsigned long)mem_to_shadow(end), NUMA_NO_NODE); } =20 /* Populate modules mapping */ - kasan_map_populate((unsigned long)kasan_mem_to_shadow((void *)MODULES_VAD= DR), - (unsigned long)kasan_mem_to_shadow((void *)MODULES_END), NUMA_NO_NODE); + kasan_map_populate((unsigned long)mem_to_shadow((void *)MODULES_VADDR), + (unsigned long)mem_to_shadow((void *)MODULES_END), NUMA_NO_NODE); /* * KAsan may reuse the contents of kasan_early_shadow_pte directly, so we * should make sure that it maps the zero page read-only. @@ -329,5 +331,6 @@ void __init kasan_init(void) =20 /* At this point kasan is fully initialized. Enable error messages */ init_task.kasan_depth =3D 0; + kasan_early_stage =3D false; pr_info("KernelAddressSanitizer initialized.\n"); } --=20 2.52.0