From nobody Thu Apr 2 23:57:06 2026 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 66079194C96; Sun, 15 Feb 2026 14:10:16 +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=1771164620; cv=none; b=jfSnrMliI1z3leF71OU/SeDwe4dxlvhjlGlYXUzUnRy/T2yAEnMUwDUikI947Wa8FnowRSL/8QYQZym+zI7m+8NDv6tTbxDyvBfyEzgZiHXA+LeDdhCZDeI7ChhgHgXzwNPKoRLby2klM8a7/pcPjomiBJRCOHhl2GaB09PRT1M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771164620; c=relaxed/simple; bh=2yStp3xIxZCnJt/Lg5CSUzoUxFjXzXcqf0vrc6IeYec=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=q2WdZ51a5qa4M9l5iBG+L70dzWU8V1rQbXFMiZ0ReK1y6s68K8p4bsCvz45hBaHu6HmS/B4TdngxwCcLk3PlLuCW7D9re6KlfQUzf6Yz3F0RlTX4u76dkfQNJOiG5zojYDtDPL4IkQckgoq+7dUZLTbSKbNNE1XJZe03U+2ltFw= 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 _____8DxusLB05FplJ0SAA--.58272S3; Sun, 15 Feb 2026 22:10:09 +0800 (CST) Received: from kernelserver (unknown [223.64.68.227]) by front1 (Coremail) with SMTP id qMiowJCxdcC705Fpp5xGAA--.20583S2; Sun, 15 Feb 2026 22:10:07 +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 for 6.6 & 6.12] LoongArch: Rework KASAN initialization for PTW-enabled systems Date: Sun, 15 Feb 2026 22:09:53 +0800 Message-ID: <20260215140953.1224579-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: qMiowJCxdcC705Fpp5xGAA--.20583S2 X-CM-SenderInfo: hfkh0x5xdftxo6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj93XoW3Wry5Kw1fAF4kWw45KF1UCFX_yoW7Cw1xpr WkKa48Gr4vvr4qqanxGw1UAry8Jwn3Ca97tFWaqa95Kay3CFy0qr1DGFykZr17WrW7JFyY 9w1SvFWDGF45tacCm3ZEXasCq-sJn29KB7ZKAUJUUUU5529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUkjb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Jr0_JF4l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Jr0_Gr1l84ACjcxK6I8E87Iv67AKxVWUJVW8JwA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_ Gr0_Gr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6xkI12xvs2x26I8E6xACxx1l5I 8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r1Y6r17McIj6I8E87Iv67AK xVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41l42xK82IYc2Ij64 vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8G jcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0xvE2I x0cI8IcVAFwI0_Jr0_JF4lIxAIcVC0I7IYx2IY6xkF7I0E14v26r1j6r4UMIIF0xvE42xK 8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87Iv6xkF7I 0E14v26r1j6r4UYxBIdaVFxhVjvjDU0xZFpf9x07j1WlkUUUUU= Content-Type: text/plain; charset="utf-8" From: Tiezhu Yang commit 5ec5ac4ca27e4daa234540ac32f9fc5219377d53 upstream. "kasan_early_stage =3D false" 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_early_stage =3D false 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_early_stage =3D false" later can defer the occasion of kasan_arch_is_ready(), so as to avoid speculative accesses on shadow pages. After moving "kasan_early_stage =3D false" 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(). 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