From nobody Wed Oct 1 22:35:18 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