Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4fdb4a98 authored by Catalin Marinas's avatar Catalin Marinas Committed by Joonwoo Park
Browse files

arm64: Implement cache_line_size() based on CTR_EL0.CWG



The hardware provides the maximum cache line size in the system via the
CTR_EL0.CWG bits. This patch implements the cache_line_size() function
to read such information, together with a sanity check if the statically
defined L1_CACHE_BYTES is smaller than the hardware value.

Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Acked-by: default avatarWill Deacon <will.deacon@arm.com>
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git


Git-commit: a41dc0e841523efe1df7fa5ad48b5e9027a921df
[joonwoop@codeaurora.org: fixed trivial merge conflict.]
Signed-off-by: default avatarJoonwoo Park <joonwoop@codeaurora.org>
parent 3106c79c
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -404,6 +404,9 @@ config ARCH_WANT_HUGE_PMD_SHARE
config HAVE_ARCH_TRANSPARENT_HUGEPAGE
	def_bool y

config ARCH_HAS_CACHE_LINE_SIZE
	def_bool y

config ARMV7_COMPAT
	bool "Kernel support for ARMv7 applications"
	depends on COMPAT
+12 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@
#ifndef __ASM_CACHE_H
#define __ASM_CACHE_H

#include <asm/cachetype.h>

#define L1_CACHE_SHIFT		6
#define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)

@@ -27,6 +29,15 @@
 * the CPU.
 */
#define ARCH_DMA_MINALIGN	L1_CACHE_BYTES
#define ARCH_SLAB_MINALIGN	8

#ifndef __ASSEMBLY__

static inline int cache_line_size(void)
{
	u32 cwg = cache_type_cwg();
	return cwg ? 4 << cwg : L1_CACHE_BYTES;
}

#endif	/* __ASSEMBLY__ */

#endif
+11 −0
Original line number Diff line number Diff line
@@ -20,12 +20,16 @@

#define CTR_L1IP_SHIFT		14
#define CTR_L1IP_MASK		3
#define CTR_CWG_SHIFT		24
#define CTR_CWG_MASK		15

#define ICACHE_POLICY_RESERVED	0
#define ICACHE_POLICY_AIVIVT	1
#define ICACHE_POLICY_VIPT	2
#define ICACHE_POLICY_PIPT	3

#ifndef __ASSEMBLY__

static inline u32 icache_policy(void)
{
	return (read_cpuid_cachetype() >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK;
@@ -45,4 +49,11 @@ static inline int icache_is_aivivt(void)
	return icache_policy() == ICACHE_POLICY_AIVIVT;
}

static inline u32 cache_type_cwg(void)
{
	return (read_cpuid_cachetype() >> CTR_CWG_SHIFT) & CTR_CWG_MASK;
}

#endif	/* __ASSEMBLY__ */

#endif	/* __ASM_CACHETYPE_H */
+15 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <linux/utsname.h>
#include <linux/initrd.h>
#include <linux/console.h>
#include <linux/cache.h>
#include <linux/bootmem.h>
#include <linux/seq_file.h>
#include <linux/screen_info.h>
@@ -210,6 +211,8 @@ static void __init setup_processor(void)
{
	struct cpu_info *cpu_info;
	u64 features, block;
	u32 cwg;
	int cls;

	cpu_info = lookup_processor_type(read_cpuid_id());
	if (!cpu_info) {
@@ -226,6 +229,18 @@ static void __init setup_processor(void)
	sprintf(init_utsname()->machine, ELF_PLATFORM);
	elf_hwcap = 0;

	/*
	 * Check for sane CTR_EL0.CWG value.
	 */
	cwg = cache_type_cwg();
	cls = cache_line_size();
	if (!cwg)
		pr_warn("No Cache Writeback Granule information, assuming cache line size %d\n",
			cls);
	if (L1_CACHE_BYTES < cls)
		pr_warn("L1_CACHE_BYTES smaller than the Cache Writeback Granule (%d < %d)\n",
			L1_CACHE_BYTES, cls);

	/*
	 * ID_AA64ISAR0_EL1 contains 4-bit wide signed feature blocks.
	 * The blocks we test below represent incremental functionality