From nobody Wed Oct 1 22:32:41 2025 Received: from out-186.mta0.migadu.com (out-186.mta0.migadu.com [91.218.175.186]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2727D23C8AA for ; Tue, 30 Sep 2025 17:28:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.186 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759253299; cv=none; b=W7pX4o0if9Wo9TN/FYiJmBednbx14+sGmFcuyu5R5k9wuQMis44xGUzfDSN27j8y4pRpm9cmY/721pR54iNrD7F4eYWww0Sj+07KOGJngVh59FQ2rL7RclEs1uZx/MmId8JZp10Bi2MRDBCGGmMmUznFJDDPVkltjJPFjcYioa4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759253299; c=relaxed/simple; bh=tUnvFmCCxQCmLoZJDB6NRrJPLZGedTfuLJ+idkUQuS4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=kyOO6JDUZ1Ggvurek52hlzf0hoAkE7HU0+GI+ZbaE5qeSmribIl4PzCM6oTs5zFJXJLEn3i8n1t0oKikUCA9+bRfW94YeMrO1/L3gnj/9SS1zXkob+6YJSGD9jg1a7FAXYIxzZ3WDVPJpuBiU6ncLtahLlzPJra5a1B9Y0ym6L4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=P5Et0A+M; arc=none smtp.client-ip=91.218.175.186 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="P5Et0A+M" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1759253293; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+jXdDUesC5zbmyy8oZM7nt2zHLqp0Qspm6EZEQwCjGM=; b=P5Et0A+MsrYTHxup/MJD2+4oY3ArVUnaC/Ht9tAea35pIzFGKf2gJu1O2sSrsRXBdqqG72 P8V/E9XnDXQk+5u9XJgaQ/ceT57orkNTnuj+q1QzE1KjSnCa3PoAv4kgHhUM1ot1znN23N NjGFOZ20DhXnQ/vat91P6it0K6x9W+Y= From: Wen Yang To: Greg Kroah-Hartman Cc: stable@vger.kernel.org, linux-kernel@vger.kernel.org, Pierre Gondois , Conor Dooley , Palmer Dabbelt , Sudeep Holla , Wen Yang Subject: [PATCH 6.1 1/6] cacheinfo: Use RISC-V's init_cache_level() as generic OF implementation Date: Wed, 1 Oct 2025 01:27:26 +0800 Message-Id: <97c153dc50435689e06ca620ce871c8165d966d3.1759251543.git.wen.yang@linux.dev> In-Reply-To: References: 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-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Pierre Gondois [ Upstream commit c3719bd9eeb2edf84bd263d662e36ca0ba262a23 ] RISC-V's implementation of init_of_cache_level() is following the Devicetree Specification v0.3 regarding caches, cf.: - s3.7.3 'Internal (L1) Cache Properties' - s3.8 'Multi-level and Shared Cache Nodes' Allow reusing the implementation by moving it. Also make 'levels', 'leaves' and 'level' unsigned int. Signed-off-by: Pierre Gondois Reviewed-by: Conor Dooley Acked-by: Palmer Dabbelt Link: https://lore.kernel.org/r/20230104183033.755668-2-pierre.gondois@arm.= com Signed-off-by: Sudeep Holla Cc: stable@vger.kernel.org Signed-off-by: Wen Yang --- arch/riscv/kernel/cacheinfo.c | 39 +------------------------------ drivers/base/cacheinfo.c | 44 +++++++++++++++++++++++++++++++++++ include/linux/cacheinfo.h | 1 + 3 files changed, 46 insertions(+), 38 deletions(-) diff --git a/arch/riscv/kernel/cacheinfo.c b/arch/riscv/kernel/cacheinfo.c index 90deabfe63ea..440a3df5944c 100644 --- a/arch/riscv/kernel/cacheinfo.c +++ b/arch/riscv/kernel/cacheinfo.c @@ -115,44 +115,7 @@ static void fill_cacheinfo(struct cacheinfo **this_lea= f, =20 int init_cache_level(unsigned int cpu) { - struct cpu_cacheinfo *this_cpu_ci =3D get_cpu_cacheinfo(cpu); - struct device_node *np =3D of_cpu_device_node_get(cpu); - struct device_node *prev =3D NULL; - int levels =3D 0, leaves =3D 0, level; - - if (of_property_read_bool(np, "cache-size")) - ++leaves; - if (of_property_read_bool(np, "i-cache-size")) - ++leaves; - if (of_property_read_bool(np, "d-cache-size")) - ++leaves; - if (leaves > 0) - levels =3D 1; - - prev =3D np; - while ((np =3D of_find_next_cache_node(np))) { - of_node_put(prev); - prev =3D np; - if (!of_device_is_compatible(np, "cache")) - break; - if (of_property_read_u32(np, "cache-level", &level)) - break; - if (level <=3D levels) - break; - if (of_property_read_bool(np, "cache-size")) - ++leaves; - if (of_property_read_bool(np, "i-cache-size")) - ++leaves; - if (of_property_read_bool(np, "d-cache-size")) - ++leaves; - levels =3D level; - } - - of_node_put(np); - this_cpu_ci->num_levels =3D levels; - this_cpu_ci->num_leaves =3D leaves; - - return 0; + return init_of_cache_level(cpu); } =20 int populate_cache_leaves(unsigned int cpu) diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index 26e13887aba4..7663eaddd168 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -223,8 +223,52 @@ static int cache_setup_of_node(unsigned int cpu) =20 return 0; } + +int init_of_cache_level(unsigned int cpu) +{ + struct cpu_cacheinfo *this_cpu_ci =3D get_cpu_cacheinfo(cpu); + struct device_node *np =3D of_cpu_device_node_get(cpu); + struct device_node *prev =3D NULL; + unsigned int levels =3D 0, leaves =3D 0, level; + + if (of_property_read_bool(np, "cache-size")) + ++leaves; + if (of_property_read_bool(np, "i-cache-size")) + ++leaves; + if (of_property_read_bool(np, "d-cache-size")) + ++leaves; + if (leaves > 0) + levels =3D 1; + + prev =3D np; + while ((np =3D of_find_next_cache_node(np))) { + of_node_put(prev); + prev =3D np; + if (!of_device_is_compatible(np, "cache")) + break; + if (of_property_read_u32(np, "cache-level", &level)) + break; + if (level <=3D levels) + break; + if (of_property_read_bool(np, "cache-size")) + ++leaves; + if (of_property_read_bool(np, "i-cache-size")) + ++leaves; + if (of_property_read_bool(np, "d-cache-size")) + ++leaves; + levels =3D level; + } + + of_node_put(np); + this_cpu_ci->num_levels =3D levels; + this_cpu_ci->num_leaves =3D leaves; + + return 0; +} + #else static inline int cache_setup_of_node(unsigned int cpu) { return 0; } +int init_of_cache_level(unsigned int cpu) { return 0; } #endif =20 int __weak cache_setup_acpi(unsigned int cpu) diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h index 00b7a6ae8617..ff0328f3fbb0 100644 --- a/include/linux/cacheinfo.h +++ b/include/linux/cacheinfo.h @@ -80,6 +80,7 @@ struct cpu_cacheinfo { =20 struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu); int init_cache_level(unsigned int cpu); +int init_of_cache_level(unsigned int cpu); int populate_cache_leaves(unsigned int cpu); int cache_setup_acpi(unsigned int cpu); bool last_level_cache_is_valid(unsigned int cpu); --=20 2.25.1 From nobody Wed Oct 1 22:32:41 2025 Received: from out-172.mta0.migadu.com (out-172.mta0.migadu.com [91.218.175.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E063E23CEF9 for ; Tue, 30 Sep 2025 17:28:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759253300; cv=none; b=R7SPHpcEbQvAwvJqXpHuLVnOQU6ad/bATynGMXsKJcI0ao8Rs4Pnh63EC2hq4AuQAmgQIAUIF17puGyKer7YkdUiBxF5ppQ6Bq+dONa035aOaRHB894OH6hgz6Ddru7v+pS89s6R7bxPpeIkPiOlR9dc6YQDWTa05OCBQDF6o3E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759253300; c=relaxed/simple; bh=Cy3b/aZmaZLpQYUPwsbTjVFhwsOtIrwg8MTNk8I/oLU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=q2Bj3J9EWfIQfN7wWENbeSlWjm57hLotGbnJJP94C92m6Hjygb+RT0AZiVklYqIwDdYZwv1xKetsseyIQCVi6oy8xYtyRHqnEI4NQ82K8Fu5k6/uR2MHXCkZtCuey0LZwyi3AgLcz5oEEfwa/niW0+wHZRk9ibfWRUsMMRmjwsM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=Sn2TgfN+; arc=none smtp.client-ip=91.218.175.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="Sn2TgfN+" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1759253297; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=SQG43KGfuEkFCSweP9GZSaF1gWhd8Z37kD+dlH+jfn0=; b=Sn2TgfN+j63Snp99WEsY7AFOYLFd+lec23J5K1v+wcyWU9PWrGgWOgiK3LQ4RSLHrAc6Xh jLtk6bQ+ou8C6pDLL/XUYXu1OoZbv2+1N3k3HRYvkC5sSL6avamdKtdoBBEC1PAfgOmwum G3qI5m9mhDosXkd396+llNAK0nX3Tjw= From: Wen Yang To: Greg Kroah-Hartman Cc: stable@vger.kernel.org, linux-kernel@vger.kernel.org, Pierre Gondois , Palmer Dabbelt , Sudeep Holla , Wen Yang Subject: [PATCH 6.1 2/6] cacheinfo: Return error code in init_of_cache_level() Date: Wed, 1 Oct 2025 01:27:27 +0800 Message-Id: <25a40240ad8a65be2c868891ef266f62b7787c3d.1759251543.git.wen.yang@linux.dev> In-Reply-To: References: 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-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Pierre Gondois [ Upstream commit 8844c3df001bc1d8397fddea341308da63855d53 ] Make init_of_cache_level() return an error code when the cache information parsing fails to help detecting missing information. init_of_cache_level() is only called for riscv. Returning an error code instead of 0 will prevent detect_cache_attributes() to allocate memory if an incomplete DT is parsed. Signed-off-by: Pierre Gondois Acked-by: Palmer Dabbelt Link: https://lore.kernel.org/r/20230104183033.755668-3-pierre.gondois@arm.= com Signed-off-by: Sudeep Holla Cc: stable@vger.kernel.org Signed-off-by: Wen Yang --- drivers/base/cacheinfo.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index 7663eaddd168..480007210bcc 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -245,11 +245,11 @@ int init_of_cache_level(unsigned int cpu) of_node_put(prev); prev =3D np; if (!of_device_is_compatible(np, "cache")) - break; + goto err_out; if (of_property_read_u32(np, "cache-level", &level)) - break; + goto err_out; if (level <=3D levels) - break; + goto err_out; if (of_property_read_bool(np, "cache-size")) ++leaves; if (of_property_read_bool(np, "i-cache-size")) @@ -264,6 +264,10 @@ int init_of_cache_level(unsigned int cpu) this_cpu_ci->num_leaves =3D leaves; =20 return 0; + +err_out: + of_node_put(np); + return -EINVAL; } =20 #else --=20 2.25.1 From nobody Wed Oct 1 22:32:41 2025 Received: from out-184.mta0.migadu.com (out-184.mta0.migadu.com [91.218.175.184]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5635030CDB4 for ; Tue, 30 Sep 2025 17:28:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.184 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759253304; cv=none; b=H/ASY5ke3lbC/JwgTsinW9Y2PthwHqd2CvEGSTA3sP/TKviCgfwtZMLBjm8IAKVwEGXjMawq9FMpXU7zH/tsbarQKOlIgLbHvGdhDNpbeTseYBy5JFP+di99r3r9mtsSGu2UKnOfkR5uaVsCumIuROq1ELFnNkv9Wb3wR/KWo6A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759253304; c=relaxed/simple; bh=KDxXnQWIvOcKAO0hI30SHajWm44YowjQ1adjboWQSLU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=m4JUZ9XNueH0G4ZkYveTjHWOJqVJYidl7eL6tKYU8ZH2zNqU3QZQ97n4HuVH5h3oUCQ7ZX4qnXPv3CkOqjjbWMiEThUnd3E5Ii1IA6bpi9Lr6x/IOHhN0njdIVT2WuSd8/5KdN8UiImamx28btUilpbr3GEL6cRqtqVRnoB/gWs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=H08aOUdp; arc=none smtp.client-ip=91.218.175.184 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="H08aOUdp" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1759253300; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UFWKO6GpxxXfQR03xrZB6itiN9eZ29IE+Uu8QNdt3u8=; b=H08aOUdpCg0muQbe+GP9q+U9qUWIPixcaCRBdvb1w+R5qCIfR4wTeWaM3yJdWwi28UkHnD bF62Ua/mVcuM4pF6YQfpnbqJ2m6ZzOns+mc4MRkv9a06DQzdHHCuDIGdRb6MrGwVMcBTAg Pr45V4ZiVvKm40aNQkEvrerjw+KiwQo= From: Wen Yang To: Greg Kroah-Hartman Cc: stable@vger.kernel.org, linux-kernel@vger.kernel.org, Pierre Gondois , Krzysztof Kozlowski , Sudeep Holla , Wen Yang Subject: [PATCH 6.1 3/6] cacheinfo: Check 'cache-unified' property to count cache leaves Date: Wed, 1 Oct 2025 01:27:28 +0800 Message-Id: <36bc21af9dee720394ea691c26b3d40eb1da546f.1759251543.git.wen.yang@linux.dev> In-Reply-To: References: 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-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Pierre Gondois [ Upstream commit de0df442ee49cb1f6ee58f3fec5dcb5e5eb70aab ] The DeviceTree Specification v0.3 specifies that the cache node '[d-|i-|]cache-size' property is required. The 'cache-unified' property is specifies whether the cache level is separate or unified. If the cache-size property is missing, no cache leaves is accounted. This can lead to a 'BUG: KASAN: slab-out-of-bounds' [1] bug. Check 'cache-unified' property and always account for at least one cache leaf when parsing the device tree. [1] https://lore.kernel.org/all/0f19cb3f-d6cf-4032-66d2-dedc9d09a0e3@linaro= .org/ Reported-by: Krzysztof Kozlowski Signed-off-by: Pierre Gondois Tested-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230104183033.755668-4-pierre.gondois@arm.= com Signed-off-by: Sudeep Holla Cc: stable@vger.kernel.org Signed-off-by: Wen Yang --- drivers/base/cacheinfo.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index 480007210bcc..ab99b0f0d010 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -224,12 +224,9 @@ static int cache_setup_of_node(unsigned int cpu) return 0; } =20 -int init_of_cache_level(unsigned int cpu) +static int of_count_cache_leaves(struct device_node *np) { - struct cpu_cacheinfo *this_cpu_ci =3D get_cpu_cacheinfo(cpu); - struct device_node *np =3D of_cpu_device_node_get(cpu); - struct device_node *prev =3D NULL; - unsigned int levels =3D 0, leaves =3D 0, level; + unsigned int leaves =3D 0; =20 if (of_property_read_bool(np, "cache-size")) ++leaves; @@ -237,6 +234,28 @@ int init_of_cache_level(unsigned int cpu) ++leaves; if (of_property_read_bool(np, "d-cache-size")) ++leaves; + + if (!leaves) { + /* The '[i-|d-|]cache-size' property is required, but + * if absent, fallback on the 'cache-unified' property. + */ + if (of_property_read_bool(np, "cache-unified")) + return 1; + else + return 2; + } + + return leaves; +} + +int init_of_cache_level(unsigned int cpu) +{ + struct cpu_cacheinfo *this_cpu_ci =3D get_cpu_cacheinfo(cpu); + struct device_node *np =3D of_cpu_device_node_get(cpu); + struct device_node *prev =3D NULL; + unsigned int levels =3D 0, leaves, level; + + leaves =3D of_count_cache_leaves(np); if (leaves > 0) levels =3D 1; =20 @@ -250,12 +269,8 @@ int init_of_cache_level(unsigned int cpu) goto err_out; if (level <=3D levels) goto err_out; - if (of_property_read_bool(np, "cache-size")) - ++leaves; - if (of_property_read_bool(np, "i-cache-size")) - ++leaves; - if (of_property_read_bool(np, "d-cache-size")) - ++leaves; + + leaves +=3D of_count_cache_leaves(np); levels =3D level; } =20 --=20 2.25.1 From nobody Wed Oct 1 22:32:41 2025 Received: from out-180.mta0.migadu.com (out-180.mta0.migadu.com [91.218.175.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BE90D30DECC for ; Tue, 30 Sep 2025 17:28:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759253308; cv=none; b=erN3yyF28QMc2ZHTRZI4Ru/qS+BbLXql4AnjUprzudHXPGXLDVzZ8qxhuxfwgTly37HDpTr7GlDiPqjMy1D+55Sw7dXDzIb0UFXyzZz7ZeIfMUGq0w7etj7wqcUy7Qc1O4NRCpL5ZfvSNMELyn8RG+3yt8byhxSXzZNWPCB37e4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759253308; c=relaxed/simple; bh=KrTQB7PgRxp34y7cFtkblAYnQMqdb2JiLEULqBQSkCA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=TPGcZZe2zQrfDyrufTcyDRGo5eaEoSdSS1OLlfNen0ye+NAHsaBtV9IKlYgynGdYg+i7P1jpJgTX5bTZb90jToV10b0ozIB2HvHBdYuVHqCig1zMzIxJD5lcKup+++oxd6CxjwvkpEyUjPjp1A0Pt0AimQQxLY3DqMMT/F48E14= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=JRrrNp08; arc=none smtp.client-ip=91.218.175.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="JRrrNp08" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1759253304; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jC4FyXfw0oGrhWfpjrh5qQ64FL3jW6VwW4LA8vLTtCs=; b=JRrrNp08o+mbjPWZu+3u11M198BzYWTGNtehKXhR2TpdbHNgG2YhWZy5y4pA9cOXHFp9wx AXPcGTZJOSskov+QgtIGvAXD3RScn5tWkgIfa8KCQijxe2T9/HG3EBOZhtG1eoZsjLUnaH LsTnl/116wRUNVbdLzG8zOZONPhC8Xg= From: Wen Yang To: Greg Kroah-Hartman Cc: stable@vger.kernel.org, linux-kernel@vger.kernel.org, Pierre Gondois , Jeremy Linton , "Rafael J . Wysocki" , Palmer Dabbelt , Sudeep Holla , Wen Yang Subject: [PATCH 6.1 4/6] ACPI: PPTT: Remove acpi_find_cache_levels() Date: Wed, 1 Oct 2025 01:27:29 +0800 Message-Id: In-Reply-To: References: 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-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Pierre Gondois [ Upstream commit fa4d566a605bc4cf32d69f16ef8cf9696635f75a ] acpi_find_cache_levels() is used at a single place and is short enough to be merged into the calling function. The removal allows an easier renaming of the calling function in the next patch. Also reorder the local variables in the 'reversed Christmas tree' order. Signed-off-by: Pierre Gondois Reviewed-by: Jeremy Linton Acked-by: Rafael J. Wysocki Acked-by: Palmer Dabbelt Link: https://lore.kernel.org/r/20230104183033.755668-5-pierre.gondois@arm.= com Signed-off-by: Sudeep Holla Cc: stable@vger.kernel.org Signed-off-by: Wen Yang --- drivers/acpi/pptt.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index 1938e4778725..01aae0f203b0 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c @@ -286,19 +286,6 @@ static struct acpi_pptt_processor *acpi_find_processor= _node(struct acpi_table_he return NULL; } =20 -static int acpi_find_cache_levels(struct acpi_table_header *table_hdr, - u32 acpi_cpu_id) -{ - int number_of_levels =3D 0; - struct acpi_pptt_processor *cpu; - - cpu =3D acpi_find_processor_node(table_hdr, acpi_cpu_id); - if (cpu) - number_of_levels =3D acpi_count_levels(table_hdr, cpu); - - return number_of_levels; -} - static u8 acpi_cache_type(enum cache_type type) { switch (type) { @@ -621,9 +608,10 @@ static int check_acpi_cpu_flag(unsigned int cpu, int r= ev, u32 flag) */ int acpi_find_last_cache_level(unsigned int cpu) { - u32 acpi_cpu_id; + struct acpi_pptt_processor *cpu_node; struct acpi_table_header *table; int number_of_levels =3D 0; + u32 acpi_cpu_id; =20 table =3D acpi_get_pptt(); if (!table) @@ -632,7 +620,10 @@ int acpi_find_last_cache_level(unsigned int cpu) pr_debug("Cache Setup find last level CPU=3D%d\n", cpu); =20 acpi_cpu_id =3D get_acpi_id_for_cpu(cpu); - number_of_levels =3D acpi_find_cache_levels(table, acpi_cpu_id); + cpu_node =3D acpi_find_processor_node(table, acpi_cpu_id); + if (cpu_node) + number_of_levels =3D acpi_count_levels(table, cpu_node); + pr_debug("Cache Setup find last level level=3D%d\n", number_of_levels); =20 return number_of_levels; --=20 2.25.1 From nobody Wed Oct 1 22:32:41 2025 Received: from out-188.mta0.migadu.com (out-188.mta0.migadu.com [91.218.175.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AB99E30E0EF for ; Tue, 30 Sep 2025 17:28:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759253314; cv=none; b=BfRc+IsPc0YgJzJgcxbc2taVZC7YshcEpH/ZlZza6JJLrRnCkaP0/6nXda1xAONjbq9DgkyE6au3bHDk03pKztNamXaLe0Si55+jrF6NRAyc/K+gsVM0L+/mzaaG34e5sb8Ce+vtgch7EdSfl/fLAO7qQdjbRRUd5Z/YARnMoOE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759253314; c=relaxed/simple; bh=FExogLh+XIugChW6t5GgcV8gXlFa/ySJUy78WLUxAng=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nO8hCu4WQoD4krt/mhV5bNJq+ZEUWkWfK+HErwWyufFTdBKZPoUQPaZfbV0ZetS5RPGELepTJGPoDCoQro61qKmgfptFFK5m6+tATICRsB3TS15/uqgbKo1yhtobzJinD6fxqwmMLCzNAI9fsrF7VEfJzKlelrooQLLfkkfzPjQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=omOoylqZ; arc=none smtp.client-ip=91.218.175.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="omOoylqZ" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1759253308; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=BXq7578xs86pyNL3GuNYIuO+HUMfQeMoIXRUc6xVIQ8=; b=omOoylqZcTAQ7DtI/I6gsHy4vktC0b3rV5A+CAntLPX2CMnUO/KfJeE+MevxeFXa/Ef7FG TrC6H6PmXjydKALKD3yJF826KB84rGeoXLjcOuR+L+cYU0tFPimbsxPBscc9I+iB4VLRKG TjFp5FcHTHaoX19x/0avn6WfxJZfc+4= From: Wen Yang To: Greg Kroah-Hartman Cc: stable@vger.kernel.org, linux-kernel@vger.kernel.org, Pierre Gondois , Jeremy Linton , "Rafael J . Wysocki" , Palmer Dabbelt , Sudeep Holla , Wen Yang Subject: [PATCH 6.1 5/6] ACPI: PPTT: Update acpi_find_last_cache_level() to acpi_get_cache_info() Date: Wed, 1 Oct 2025 01:27:30 +0800 Message-Id: <47c6b7bfc4c7e26cdf8943b2f5179c997df06a9d.1759251543.git.wen.yang@linux.dev> In-Reply-To: References: 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-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Pierre Gondois [ Upstream commit bd500361a937c03a3da57178287ce543c8f3681b ] acpi_find_last_cache_level() allows to find the last level of cache for a given CPU. The function is only called on arm64 ACPI based platforms to check for cache information that would be missing in the CLIDR_EL1 register. To allow populating (struct cpu_cacheinfo).num_leaves by only parsing a PPTT, update acpi_find_last_cache_level() to get the 'split_levels', i.e. the number of cache levels being split in data/instruction caches. It is assumed that there will not be data/instruction caches above a unified cache. If a split level consist of one data cache and no instruction cache (or opposite), then the missing cache will still be populated by default with minimal cache information, and maximal cpumask (all non-existing caches have the same fw_token). Suggested-by: Jeremy Linton Signed-off-by: Pierre Gondois Reviewed-by: Jeremy Linton Acked-by: Rafael J. Wysocki Acked-by: Palmer Dabbelt Link: https://lore.kernel.org/r/20230104183033.755668-6-pierre.gondois@arm.= com Signed-off-by: Sudeep Holla Cc: stable@vger.kernel.org Signed-off-by: Wen Yang --- arch/arm64/kernel/cacheinfo.c | 11 +++-- drivers/acpi/pptt.c | 76 +++++++++++++++++++++++------------ include/linux/cacheinfo.h | 9 +++-- 3 files changed, 63 insertions(+), 33 deletions(-) diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c index 1510f457b615..a565e8dc9c15 100644 --- a/arch/arm64/kernel/cacheinfo.c +++ b/arch/arm64/kernel/cacheinfo.c @@ -46,7 +46,7 @@ static void ci_leaf_init(struct cacheinfo *this_leaf, int init_cache_level(unsigned int cpu) { unsigned int ctype, level, leaves; - int fw_level; + int fw_level, ret; struct cpu_cacheinfo *this_cpu_ci =3D get_cpu_cacheinfo(cpu); =20 for (level =3D 1, leaves =3D 0; level <=3D MAX_CACHE_LEVEL; level++) { @@ -59,10 +59,13 @@ int init_cache_level(unsigned int cpu) leaves +=3D (ctype =3D=3D CACHE_TYPE_SEPARATE) ? 2 : 1; } =20 - if (acpi_disabled) + if (acpi_disabled) { fw_level =3D of_find_last_cache_level(cpu); - else - fw_level =3D acpi_find_last_cache_level(cpu); + } else { + ret =3D acpi_get_cache_info(cpu, &fw_level, NULL); + if (ret < 0) + return ret; + } =20 if (fw_level < 0) return fw_level; diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index 01aae0f203b0..54676e3d82dd 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c @@ -81,6 +81,7 @@ static inline bool acpi_pptt_match_type(int table_type, i= nt type) * acpi_pptt_walk_cache() - Attempt to find the requested acpi_pptt_cache * @table_hdr: Pointer to the head of the PPTT table * @local_level: passed res reflects this cache level + * @split_levels: Number of split cache levels (data/instruction). * @res: cache resource in the PPTT we want to walk * @found: returns a pointer to the requested level if found * @level: the requested cache level @@ -100,6 +101,7 @@ static inline bool acpi_pptt_match_type(int table_type,= int type) */ static unsigned int acpi_pptt_walk_cache(struct acpi_table_header *table_h= dr, unsigned int local_level, + unsigned int *split_levels, struct acpi_subtable_header *res, struct acpi_pptt_cache **found, unsigned int level, int type) @@ -113,8 +115,17 @@ static unsigned int acpi_pptt_walk_cache(struct acpi_t= able_header *table_hdr, while (cache) { local_level++; =20 + if (!(cache->flags & ACPI_PPTT_CACHE_TYPE_VALID)) { + cache =3D fetch_pptt_cache(table_hdr, cache->next_level_of_cache); + continue; + } + + if (split_levels && + (acpi_pptt_match_type(cache->attributes, ACPI_PPTT_CACHE_TYPE_DATA) = || + acpi_pptt_match_type(cache->attributes, ACPI_PPTT_CACHE_TYPE_INSTR)= )) + *split_levels =3D local_level; + if (local_level =3D=3D level && - cache->flags & ACPI_PPTT_CACHE_TYPE_VALID && acpi_pptt_match_type(cache->attributes, type)) { if (*found !=3D NULL && cache !=3D *found) pr_warn("Found duplicate cache level/type unable to determine uniquene= ss\n"); @@ -135,8 +146,8 @@ static unsigned int acpi_pptt_walk_cache(struct acpi_ta= ble_header *table_hdr, static struct acpi_pptt_cache * acpi_find_cache_level(struct acpi_table_header *table_hdr, struct acpi_pptt_processor *cpu_node, - unsigned int *starting_level, unsigned int level, - int type) + unsigned int *starting_level, unsigned int *split_levels, + unsigned int level, int type) { struct acpi_subtable_header *res; unsigned int number_of_levels =3D *starting_level; @@ -149,7 +160,8 @@ acpi_find_cache_level(struct acpi_table_header *table_h= dr, resource++; =20 local_level =3D acpi_pptt_walk_cache(table_hdr, *starting_level, - res, &ret, level, type); + split_levels, res, &ret, + level, type); /* * we are looking for the max depth. Since its potentially * possible for a given node to have resources with differing @@ -165,29 +177,29 @@ acpi_find_cache_level(struct acpi_table_header *table= _hdr, } =20 /** - * acpi_count_levels() - Given a PPTT table, and a CPU node, count the cac= hes + * acpi_count_levels() - Given a PPTT table, and a CPU node, count the cac= he + * levels and split cache levels (data/instruction). * @table_hdr: Pointer to the head of the PPTT table * @cpu_node: processor node we wish to count caches for + * @levels: Number of levels if success. + * @split_levels: Number of split cache levels (data/instruction) if + * success. Can by NULL. * * Given a processor node containing a processing unit, walk into it and c= ount * how many levels exist solely for it, and then walk up each level until = we hit * the root node (ignore the package level because it may be possible to h= ave - * caches that exist across packages). Count the number of cache levels th= at - * exist at each level on the way up. - * - * Return: Total number of levels found. + * caches that exist across packages). Count the number of cache levels and + * split cache levels (data/instruction) that exist at each level on the w= ay + * up. */ -static int acpi_count_levels(struct acpi_table_header *table_hdr, - struct acpi_pptt_processor *cpu_node) +static void acpi_count_levels(struct acpi_table_header *table_hdr, + struct acpi_pptt_processor *cpu_node, + unsigned int *levels, unsigned int *split_levels) { - int total_levels =3D 0; - do { - acpi_find_cache_level(table_hdr, cpu_node, &total_levels, 0, 0); + acpi_find_cache_level(table_hdr, cpu_node, levels, split_levels, 0, 0); cpu_node =3D fetch_pptt_node(table_hdr, cpu_node->parent); } while (cpu_node); - - return total_levels; } =20 /** @@ -326,7 +338,7 @@ static struct acpi_pptt_cache *acpi_find_cache_node(str= uct acpi_table_header *ta =20 while (cpu_node && !found) { found =3D acpi_find_cache_level(table_hdr, cpu_node, - &total_levels, level, acpi_type); + &total_levels, NULL, level, acpi_type); *node =3D cpu_node; cpu_node =3D fetch_pptt_node(table_hdr, cpu_node->parent); } @@ -597,36 +609,48 @@ static int check_acpi_cpu_flag(unsigned int cpu, int = rev, u32 flag) } =20 /** - * acpi_find_last_cache_level() - Determines the number of cache levels fo= r a PE + * acpi_get_cache_info() - Determine the number of cache levels and + * split cache levels (data/instruction) and for a PE. * @cpu: Kernel logical CPU number + * @levels: Number of levels if success. + * @split_levels: Number of levels being split (i.e. data/instruction) + * if success. Can by NULL. * * Given a logical CPU number, returns the number of levels of cache repre= sented * in the PPTT. Errors caused by lack of a PPTT table, or otherwise, retur= n 0 * indicating we didn't find any cache levels. * - * Return: Cache levels visible to this core. + * Return: -ENOENT if no PPTT table or no PPTT processor struct found. + * 0 on success. */ -int acpi_find_last_cache_level(unsigned int cpu) +int acpi_get_cache_info(unsigned int cpu, unsigned int *levels, + unsigned int *split_levels) { struct acpi_pptt_processor *cpu_node; struct acpi_table_header *table; - int number_of_levels =3D 0; u32 acpi_cpu_id; =20 + *levels =3D 0; + if (split_levels) + *split_levels =3D 0; + table =3D acpi_get_pptt(); if (!table) return -ENOENT; =20 - pr_debug("Cache Setup find last level CPU=3D%d\n", cpu); + pr_debug("Cache Setup: find cache levels for CPU=3D%d\n", cpu); =20 acpi_cpu_id =3D get_acpi_id_for_cpu(cpu); cpu_node =3D acpi_find_processor_node(table, acpi_cpu_id); - if (cpu_node) - number_of_levels =3D acpi_count_levels(table, cpu_node); + if (!cpu_node) + return -ENOENT; =20 - pr_debug("Cache Setup find last level level=3D%d\n", number_of_levels); + acpi_count_levels(table, cpu_node, levels, split_levels); =20 - return number_of_levels; + pr_debug("Cache Setup: last_level=3D%d split_levels=3D%d\n", + *levels, split_levels ? *split_levels : -1); + + return 0; } =20 /** diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h index ff0328f3fbb0..00d8e7f9d1c6 100644 --- a/include/linux/cacheinfo.h +++ b/include/linux/cacheinfo.h @@ -88,19 +88,22 @@ bool last_level_cache_is_shared(unsigned int cpu_x, uns= igned int cpu_y); int detect_cache_attributes(unsigned int cpu); #ifndef CONFIG_ACPI_PPTT /* - * acpi_find_last_cache_level is only called on ACPI enabled + * acpi_get_cache_info() is only called on ACPI enabled * platforms using the PPTT for topology. This means that if * the platform supports other firmware configuration methods * we need to stub out the call when ACPI is disabled. * ACPI enabled platforms not using PPTT won't be making calls * to this function so we need not worry about them. */ -static inline int acpi_find_last_cache_level(unsigned int cpu) +static inline +int acpi_get_cache_info(unsigned int cpu, + unsigned int *levels, unsigned int *split_levels) { return 0; } #else -int acpi_find_last_cache_level(unsigned int cpu); +int acpi_get_cache_info(unsigned int cpu, + unsigned int *levels, unsigned int *split_levels); #endif =20 const struct attribute_group *cache_get_priv_group(struct cacheinfo *this_= leaf); --=20 2.25.1 From nobody Wed Oct 1 22:32:41 2025 Received: from out-185.mta0.migadu.com (out-185.mta0.migadu.com [91.218.175.185]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1E6BB30C617 for ; Tue, 30 Sep 2025 17:28:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.185 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759253317; cv=none; b=SfcJPsRk/cLDQC12NadcfBIjn8soK51ctyjryYdMLKc0Dim6JOZnrO78Imz4MoRdMFSvDkfTUyKv7om1rjUIveuE5FV+GaP1Tl4fo4PsakgqeuwHaPN61ToI+hiNyGAFU1sdikG3v55Ieoqw2Q3s4/oNXO+kfebGhC9+ykHepb0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759253317; c=relaxed/simple; bh=zug1RGVFNRyLB1s0nsyVQMczgGwosnie+UXUsw4+l9w=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=KgB4O4ObrMN1ZACsBP9ISEB3SvcfFEP8NHN1L/2MYDV0lqlhZdkt01XBXLpHGoHRgQEHV+DxanBplk1J+wjKLhePhb49L1rW2sy5VVM/0KLda42mD5U0Y240fGdFN09qtlYBGhXrOI3fay+y17ExMjODYZjnPDsfK0BvaN+Nlvg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=JVkBCxjO; arc=none smtp.client-ip=91.218.175.185 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="JVkBCxjO" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1759253312; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=orilhY8Ftnw0yG11yBg9R6a/IIwv6TZglZsPMJyEfjY=; b=JVkBCxjOlnf5Yq0k5BOcH0TwdfBgQyp+vf2HTSCt8cXvJS9I+e0U4JlM5aIQdV/lW+jNWV 3LFY4pvuoHXyRdbcvDv3aboDuQN8N/jwBZRGtNnbrCWqW1+oOWgAKViWGpulddcMGlgOO2 jnWlBf1b6az6iIW+F+2bSlHKVco9TT0= From: Wen Yang To: Greg Kroah-Hartman Cc: stable@vger.kernel.org, linux-kernel@vger.kernel.org, Pierre Gondois , Sudeep Holla , Palmer Dabbelt , Wen Yang Subject: [PATCH 6.1 6/6] arch_topology: Build cacheinfo from primary CPU Date: Wed, 1 Oct 2025 01:27:31 +0800 Message-Id: <296ababbf0d4a3debe1ee5b5d29a5a23201f9fd6.1759251543.git.wen.yang@linux.dev> In-Reply-To: References: 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-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Pierre Gondois [ Upstream commit 5944ce092b97caed5d86d961e963b883b5c44ee2 ] commit 3fcbf1c77d08 ("arch_topology: Fix cache attributes detection in the CPU hotplug path") adds a call to detect_cache_attributes() to populate the cacheinfo before updating the siblings mask. detect_cache_attributes() allocates memory and can take the PPTT mutex (on ACPI platforms). On PREEMPT_RT kernels, on secondary CPUs, this triggers a: 'BUG: sleeping function called from invalid context' [1] as the code is executed with preemption and interrupts disabled. The primary CPU was previously storing the cache information using the now removed (struct cpu_topology).llc_id: commit 5b8dc787ce4a ("arch_topology: Drop LLC identifier stash from the CPU topology") allocate_cache_info() tries to build the cacheinfo from the primary CPU prior secondary CPUs boot, if the DT/ACPI description contains cache information. If allocate_cache_info() fails, then fallback to the current state for the cacheinfo allocation. [1] will be triggered in such case. When unplugging a CPU, the cacheinfo memory cannot be freed. If it was, then the memory would be allocated early by the re-plugged CPU and would trigger [1]. Note that populate_cache_leaves() might be called multiple times due to populate_leaves being moved up. This is required since detect_cache_attributes() might be called with per_cpu_cacheinfo(cpu) being allocated but not populated. [1]: | BUG: sleeping function called from invalid context at kernel/locking/spi= nlock_rt.c:46 | in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 0, name: swappe= r/111 | preempt_count: 1, expected: 0 | RCU nest depth: 1, expected: 1 | 3 locks held by swapper/111/0: | #0: (&pcp->lock){+.+.}-{3:3}, at: get_page_from_freelist+0x218/0x12c8 | #1: (rcu_read_lock){....}-{1:3}, at: rt_spin_trylock+0x48/0xf0 | #2: (&zone->lock){+.+.}-{3:3}, at: rmqueue_bulk+0x64/0xa80 | irq event stamp: 0 | hardirqs last enabled at (0): 0x0 | hardirqs last disabled at (0): copy_process+0x5dc/0x1ab8 | softirqs last enabled at (0): copy_process+0x5dc/0x1ab8 | softirqs last disabled at (0): 0x0 | Preemption disabled at: | migrate_enable+0x30/0x130 | CPU: 111 PID: 0 Comm: swapper/111 Tainted: G W 6.0.0-rc4= -rt6-[...] | Call trace: | __kmalloc+0xbc/0x1e8 | detect_cache_attributes+0x2d4/0x5f0 | update_siblings_masks+0x30/0x368 | store_cpu_topology+0x78/0xb8 | secondary_start_kernel+0xd0/0x198 | __secondary_switched+0xb0/0xb4 Signed-off-by: Pierre Gondois Reviewed-by: Sudeep Holla Acked-by: Palmer Dabbelt Link: https://lore.kernel.org/r/20230104183033.755668-7-pierre.gondois@arm.= com Signed-off-by: Sudeep Holla Cc: stable@vger.kernel.org Signed-off-by: Wen Yang --- arch/riscv/kernel/cacheinfo.c | 5 --- drivers/base/arch_topology.c | 12 +++++- drivers/base/cacheinfo.c | 71 ++++++++++++++++++++++++++--------- include/linux/cacheinfo.h | 1 + 4 files changed, 65 insertions(+), 24 deletions(-) diff --git a/arch/riscv/kernel/cacheinfo.c b/arch/riscv/kernel/cacheinfo.c index 440a3df5944c..3a13113f1b29 100644 --- a/arch/riscv/kernel/cacheinfo.c +++ b/arch/riscv/kernel/cacheinfo.c @@ -113,11 +113,6 @@ static void fill_cacheinfo(struct cacheinfo **this_lea= f, } } =20 -int init_cache_level(unsigned int cpu) -{ - return init_of_cache_level(cpu); -} - int populate_cache_leaves(unsigned int cpu) { struct cpu_cacheinfo *this_cpu_ci =3D get_cpu_cacheinfo(cpu); diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index e7d6e6657ffa..b1c1dd38ab01 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -736,7 +736,7 @@ void update_siblings_masks(unsigned int cpuid) =20 ret =3D detect_cache_attributes(cpuid); if (ret && ret !=3D -ENOENT) - pr_info("Early cacheinfo failed, ret =3D %d\n", ret); + pr_info("Early cacheinfo allocation failed, ret =3D %d\n", ret); =20 /* update core and thread sibling masks */ for_each_online_cpu(cpu) { @@ -825,7 +825,7 @@ __weak int __init parse_acpi_topology(void) #if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) void __init init_cpu_topology(void) { - int ret; + int cpu, ret; =20 reset_cpu_topology(); ret =3D parse_acpi_topology(); @@ -840,6 +840,14 @@ void __init init_cpu_topology(void) reset_cpu_topology(); return; } + + for_each_possible_cpu(cpu) { + ret =3D fetch_cache_info(cpu); + if (ret) { + pr_err("Early cacheinfo failed, ret =3D %d\n", ret); + break; + } + } } =20 void store_cpu_topology(unsigned int cpuid) diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index ab99b0f0d010..cd943d06d074 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -412,10 +412,6 @@ static void free_cache_attributes(unsigned int cpu) return; =20 cache_shared_cpu_map_remove(cpu); - - kfree(per_cpu_cacheinfo(cpu)); - per_cpu_cacheinfo(cpu) =3D NULL; - cache_leaves(cpu) =3D 0; } =20 int __weak init_cache_level(unsigned int cpu) @@ -428,29 +424,71 @@ int __weak populate_cache_leaves(unsigned int cpu) return -ENOENT; } =20 +static inline +int allocate_cache_info(int cpu) +{ + per_cpu_cacheinfo(cpu) =3D kcalloc(cache_leaves(cpu), + sizeof(struct cacheinfo), GFP_ATOMIC); + if (!per_cpu_cacheinfo(cpu)) { + cache_leaves(cpu) =3D 0; + return -ENOMEM; + } + + return 0; +} + +int fetch_cache_info(unsigned int cpu) +{ + struct cpu_cacheinfo *this_cpu_ci; + unsigned int levels, split_levels; + int ret; + + if (acpi_disabled) { + ret =3D init_of_cache_level(cpu); + if (ret < 0) + return ret; + } else { + ret =3D acpi_get_cache_info(cpu, &levels, &split_levels); + if (ret < 0) + return ret; + + this_cpu_ci =3D get_cpu_cacheinfo(cpu); + this_cpu_ci->num_levels =3D levels; + /* + * This assumes that: + * - there cannot be any split caches (data/instruction) + * above a unified cache + * - data/instruction caches come by pair + */ + this_cpu_ci->num_leaves =3D levels + split_levels; + } + if (!cache_leaves(cpu)) + return -ENOENT; + + return allocate_cache_info(cpu); +} + int detect_cache_attributes(unsigned int cpu) { int ret; =20 - /* Since early detection of the cacheinfo is allowed via this - * function and this also gets called as CPU hotplug callbacks via - * cacheinfo_cpu_online, the initialisation can be skipped and only - * CPU maps can be updated as the CPU online status would be update - * if called via cacheinfo_cpu_online path. + /* Since early initialization/allocation of the cacheinfo is allowed + * via fetch_cache_info() and this also gets called as CPU hotplug + * callbacks via cacheinfo_cpu_online, the init/alloc can be skipped + * as it will happen only once (the cacheinfo memory is never freed). + * Just populate the cacheinfo. */ if (per_cpu_cacheinfo(cpu)) - goto update_cpu_map; + goto populate_leaves; =20 if (init_cache_level(cpu) || !cache_leaves(cpu)) return -ENOENT; =20 - per_cpu_cacheinfo(cpu) =3D kcalloc(cache_leaves(cpu), - sizeof(struct cacheinfo), GFP_ATOMIC); - if (per_cpu_cacheinfo(cpu) =3D=3D NULL) { - cache_leaves(cpu) =3D 0; - return -ENOMEM; - } + ret =3D allocate_cache_info(cpu); + if (ret) + return ret; =20 +populate_leaves: /* * populate_cache_leaves() may completely setup the cache leaves and * shared_cpu_map or it may leave it partially setup. @@ -459,7 +497,6 @@ int detect_cache_attributes(unsigned int cpu) if (ret) goto free_ci; =20 -update_cpu_map: /* * For systems using DT for cache hierarchy, fw_token * and shared_cpu_map will be set up here only if they are diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h index 00d8e7f9d1c6..dfef57077cd0 100644 --- a/include/linux/cacheinfo.h +++ b/include/linux/cacheinfo.h @@ -85,6 +85,7 @@ int populate_cache_leaves(unsigned int cpu); int cache_setup_acpi(unsigned int cpu); bool last_level_cache_is_valid(unsigned int cpu); bool last_level_cache_is_shared(unsigned int cpu_x, unsigned int cpu_y); +int fetch_cache_info(unsigned int cpu); int detect_cache_attributes(unsigned int cpu); #ifndef CONFIG_ACPI_PPTT /* --=20 2.25.1