diff options
Diffstat (limited to 'arch/arm64/kernel')
| -rw-r--r-- | arch/arm64/kernel/cacheinfo.c | 6 | ||||
| -rw-r--r-- | arch/arm64/kernel/cpu_errata.c | 12 | ||||
| -rw-r--r-- | arch/arm64/kernel/cpufeature.c | 5 | ||||
| -rw-r--r-- | arch/arm64/kernel/entry.S | 2 | ||||
| -rw-r--r-- | arch/arm64/kernel/fpsimd.c | 21 | ||||
| -rw-r--r-- | arch/arm64/kernel/head.S | 2 | ||||
| -rw-r--r-- | arch/arm64/kernel/machine_kexec_file.c | 2 | ||||
| -rw-r--r-- | arch/arm64/kernel/pi/kaslr_early.c | 8 | ||||
| -rw-r--r-- | arch/arm64/kernel/ptrace.c | 8 | ||||
| -rw-r--r-- | arch/arm64/kernel/signal.c | 14 | ||||
| -rw-r--r-- | arch/arm64/kernel/sleep.S | 3 | ||||
| -rw-r--r-- | arch/arm64/kernel/topology.c | 34 | 
12 files changed, 83 insertions, 34 deletions
diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c index 587543c6c51c..97c42be71338 100644 --- a/arch/arm64/kernel/cacheinfo.c +++ b/arch/arm64/kernel/cacheinfo.c @@ -45,7 +45,8 @@ static void ci_leaf_init(struct cacheinfo *this_leaf,  int init_cache_level(unsigned int cpu)  { -	unsigned int ctype, level, leaves, fw_level; +	unsigned int ctype, level, leaves; +	int fw_level;  	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);  	for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) { @@ -63,6 +64,9 @@ int init_cache_level(unsigned int cpu)  	else  		fw_level = acpi_find_last_cache_level(cpu); +	if (fw_level < 0) +		return fw_level; +  	if (level < fw_level) {  		/*  		 * some external caches not specified in CLIDR_EL1 diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 7e6289e709fc..53b973b6059f 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -208,6 +208,8 @@ static const struct arm64_cpu_capabilities arm64_repeat_tlbi_list[] = {  #ifdef CONFIG_ARM64_ERRATUM_1286807  	{  		ERRATA_MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 0), +	}, +	{  		/* Kryo4xx Gold (rcpe to rfpe) => (r0p0 to r3p0) */  		ERRATA_MIDR_RANGE(MIDR_QCOM_KRYO_4XX_GOLD, 0xc, 0xe, 0xf, 0xe),  	}, @@ -654,6 +656,16 @@ const struct arm64_cpu_capabilities arm64_errata[] = {  		ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A510, 0, 0, 2)  	},  #endif +#ifdef CONFIG_ARM64_ERRATUM_2457168 +	{ +		.desc = "ARM erratum 2457168", +		.capability = ARM64_WORKAROUND_2457168, +		.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE, + +		/* Cortex-A510 r0p0-r1p1 */ +		CAP_MIDR_RANGE(MIDR_CORTEX_A510, 0, 0, 1, 1) +	}, +#endif  #ifdef CONFIG_ARM64_ERRATUM_2038923  	{  		.desc = "ARM erratum 2038923", diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 907401e4fffb..af4de817d712 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -1870,7 +1870,10 @@ static void cpu_amu_enable(struct arm64_cpu_capabilities const *cap)  		pr_info("detected CPU%d: Activity Monitors Unit (AMU)\n",  			smp_processor_id());  		cpumask_set_cpu(smp_processor_id(), &amu_cpus); -		update_freq_counters_refs(); + +		/* 0 reference values signal broken/disabled counters */ +		if (!this_cpu_has_cap(ARM64_WORKAROUND_2457168)) +			update_freq_counters_refs();  	}  } diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 254fe31c03a0..2d73b3e793b2 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -502,7 +502,7 @@ tsk	.req	x28		// current thread_info  SYM_CODE_START(vectors)  	kernel_ventry	1, t, 64, sync		// Synchronous EL1t  	kernel_ventry	1, t, 64, irq		// IRQ EL1t -	kernel_ventry	1, t, 64, fiq		// FIQ EL1h +	kernel_ventry	1, t, 64, fiq		// FIQ EL1t  	kernel_ventry	1, t, 64, error		// Error EL1t  	kernel_ventry	1, h, 64, sync		// Synchronous EL1h diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index dd63ffc3a2fa..23834d96d1e7 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -715,10 +715,12 @@ size_t sve_state_size(struct task_struct const *task)   * do_sve_acc() case, there is no ABI requirement to hide stale data   * written previously be task.   */ -void sve_alloc(struct task_struct *task) +void sve_alloc(struct task_struct *task, bool flush)  {  	if (task->thread.sve_state) { -		memset(task->thread.sve_state, 0, sve_state_size(task)); +		if (flush) +			memset(task->thread.sve_state, 0, +			       sve_state_size(task));  		return;  	} @@ -1388,7 +1390,7 @@ void do_sve_acc(unsigned long esr, struct pt_regs *regs)  		return;  	} -	sve_alloc(current); +	sve_alloc(current, true);  	if (!current->thread.sve_state) {  		force_sig(SIGKILL);  		return; @@ -1439,7 +1441,7 @@ void do_sme_acc(unsigned long esr, struct pt_regs *regs)  		return;  	} -	sve_alloc(current); +	sve_alloc(current, false);  	sme_alloc(current);  	if (!current->thread.sve_state || !current->thread.za_state) {  		force_sig(SIGKILL); @@ -1460,17 +1462,6 @@ void do_sme_acc(unsigned long esr, struct pt_regs *regs)  		fpsimd_bind_task_to_cpu();  	} -	/* -	 * If SVE was not already active initialise the SVE registers, -	 * any non-shared state between the streaming and regular SVE -	 * registers is architecturally guaranteed to be zeroed when -	 * we enter streaming mode.  We do not need to initialize ZA -	 * since ZA must be disabled at this point and enabling ZA is -	 * architecturally defined to zero ZA. -	 */ -	if (system_supports_sve() && !test_thread_flag(TIF_SVE)) -		sve_init_regs(); -  	put_cpu_fpsimd_context();  } diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index cefe6a73ee54..814b6587ccb7 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -371,7 +371,9 @@ SYM_FUNC_END(create_idmap)  SYM_FUNC_START_LOCAL(create_kernel_mapping)  	adrp	x0, init_pg_dir  	mov_q	x5, KIMAGE_VADDR		// compile time __va(_text) +#ifdef CONFIG_RELOCATABLE  	add	x5, x5, x23			// add KASLR displacement +#endif  	adrp	x6, _end			// runtime __pa(_end)  	adrp	x3, _text			// runtime __pa(_text)  	sub	x6, x6, x3			// _end - _text diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c index 889951291cc0..a11a6e14ba89 100644 --- a/arch/arm64/kernel/machine_kexec_file.c +++ b/arch/arm64/kernel/machine_kexec_file.c @@ -47,7 +47,7 @@ static int prepare_elf_headers(void **addr, unsigned long *sz)  	u64 i;  	phys_addr_t start, end; -	nr_ranges = 1; /* for exclusion of crashkernel region */ +	nr_ranges = 2; /* for exclusion of crashkernel region */  	for_each_mem_range(i, &start, &end)  		nr_ranges++; diff --git a/arch/arm64/kernel/pi/kaslr_early.c b/arch/arm64/kernel/pi/kaslr_early.c index 6c3855e69395..17bff6e399e4 100644 --- a/arch/arm64/kernel/pi/kaslr_early.c +++ b/arch/arm64/kernel/pi/kaslr_early.c @@ -94,11 +94,9 @@ asmlinkage u64 kaslr_early_init(void *fdt)  	seed = get_kaslr_seed(fdt);  	if (!seed) { -#ifdef CONFIG_ARCH_RANDOM -		 if (!__early_cpu_has_rndr() || -		     !__arm64_rndr((unsigned long *)&seed)) -#endif -		return 0; +		if (!__early_cpu_has_rndr() || +		    !__arm64_rndr((unsigned long *)&seed)) +			return 0;  	}  	/* diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 21da83187a60..041d2ae5c30a 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -882,7 +882,7 @@ static int sve_set_common(struct task_struct *target,  		 * state and ensure there's storage.  		 */  		if (target->thread.svcr != old_svcr) -			sve_alloc(target); +			sve_alloc(target, true);  	}  	/* Registers: FPSIMD-only case */ @@ -912,7 +912,7 @@ static int sve_set_common(struct task_struct *target,  		goto out;  	} -	sve_alloc(target); +	sve_alloc(target, true);  	if (!target->thread.sve_state) {  		ret = -ENOMEM;  		clear_tsk_thread_flag(target, TIF_SVE); @@ -1082,9 +1082,8 @@ static int za_set(struct task_struct *target,  	/* Ensure there is some SVE storage for streaming mode */  	if (!target->thread.sve_state) { -		sve_alloc(target); +		sve_alloc(target, false);  		if (!target->thread.sve_state) { -			clear_thread_flag(TIF_SME);  			ret = -ENOMEM;  			goto out;  		} @@ -1094,7 +1093,6 @@ static int za_set(struct task_struct *target,  	sme_alloc(target);  	if (!target->thread.za_state) {  		ret = -ENOMEM; -		clear_tsk_thread_flag(target, TIF_SME);  		goto out;  	} diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 3e6d0352d7d3..9ad911f1647c 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -91,7 +91,7 @@ static size_t sigframe_size(struct rt_sigframe_user_layout const *user)   * not taken into account.  This limit is not a guarantee and is   * NOT ABI.   */ -#define SIGFRAME_MAXSZ SZ_64K +#define SIGFRAME_MAXSZ SZ_256K  static int __sigframe_alloc(struct rt_sigframe_user_layout *user,  			    unsigned long *offset, size_t size, bool extend) @@ -310,7 +310,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)  	fpsimd_flush_task_state(current);  	/* From now, fpsimd_thread_switch() won't touch thread.sve_state */ -	sve_alloc(current); +	sve_alloc(current, true);  	if (!current->thread.sve_state) {  		clear_thread_flag(TIF_SVE);  		return -ENOMEM; @@ -926,6 +926,16 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,  	/* Signal handlers are invoked with ZA and streaming mode disabled */  	if (system_supports_sme()) { +		/* +		 * If we were in streaming mode the saved register +		 * state was SVE but we will exit SM and use the +		 * FPSIMD register state - flush the saved FPSIMD +		 * register state in case it gets loaded. +		 */ +		if (current->thread.svcr & SVCR_SM_MASK) +			memset(¤t->thread.uw.fpsimd_state, 0, +			       sizeof(current->thread.uw.fpsimd_state)); +  		current->thread.svcr &= ~(SVCR_ZA_MASK |  					  SVCR_SM_MASK);  		sme_smstop(); diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S index 617f78ad43a1..97c9de57725d 100644 --- a/arch/arm64/kernel/sleep.S +++ b/arch/arm64/kernel/sleep.S @@ -101,6 +101,9 @@ SYM_FUNC_END(__cpu_suspend_enter)  SYM_CODE_START(cpu_resume)  	bl	init_kernel_el  	bl	finalise_el2 +#if VA_BITS > 48 +	ldr_l	x0, vabits_actual +#endif  	bl	__cpu_setup  	/* enable the MMU early - so we can access sleep_save_stash by va */  	adrp	x1, swapper_pg_dir diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 869ffc4d4484..44ebf5b2fc4b 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -237,7 +237,7 @@ static void amu_fie_setup(const struct cpumask *cpus)  	for_each_cpu(cpu, cpus) {  		if (!freq_counters_valid(cpu) ||  		    freq_inv_set_max_ratio(cpu, -					   cpufreq_get_hw_max_freq(cpu) * 1000, +					   cpufreq_get_hw_max_freq(cpu) * 1000ULL,  					   arch_timer_get_rate()))  			return;  	} @@ -296,12 +296,25 @@ core_initcall(init_amu_fie);  static void cpu_read_corecnt(void *val)  { +	/* +	 * A value of 0 can be returned if the current CPU does not support AMUs +	 * or if the counter is disabled for this CPU. A return value of 0 at +	 * counter read is properly handled as an error case by the users of the +	 * counter. +	 */  	*(u64 *)val = read_corecnt();  }  static void cpu_read_constcnt(void *val)  { -	*(u64 *)val = read_constcnt(); +	/* +	 * Return 0 if the current CPU is affected by erratum 2457168. A value +	 * of 0 is also returned if the current CPU does not support AMUs or if +	 * the counter is disabled. A return value of 0 at counter read is +	 * properly handled as an error case by the users of the counter. +	 */ +	*(u64 *)val = this_cpu_has_cap(ARM64_WORKAROUND_2457168) ? +		      0UL : read_constcnt();  }  static inline @@ -328,7 +341,22 @@ int counters_read_on_cpu(int cpu, smp_call_func_t func, u64 *val)   */  bool cpc_ffh_supported(void)  { -	return freq_counters_valid(get_cpu_with_amu_feat()); +	int cpu = get_cpu_with_amu_feat(); + +	/* +	 * FFH is considered supported if there is at least one present CPU that +	 * supports AMUs. Using FFH to read core and reference counters for CPUs +	 * that do not support AMUs, have counters disabled or that are affected +	 * by errata, will result in a return value of 0. +	 * +	 * This is done to allow any enabled and valid counters to be read +	 * through FFH, knowing that potentially returning 0 as counter value is +	 * properly handled by the users of these counters. +	 */ +	if ((cpu >= nr_cpu_ids) || !cpumask_test_cpu(cpu, cpu_present_mask)) +		return false; + +	return true;  }  int cpc_read_ffh(int cpu, struct cpc_reg *reg, u64 *val)  | 
