aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuzuki K. Poulose <suzuki.poulose@arm.com>2015-10-19 09:24:46 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2015-10-21 10:35:56 -0400
commit3086d391f992984def0aa6aa4a36f54853c58536 (patch)
treed83a9c5f47cce6fb234e1a46b09e0e381b74c6f9
parent3c739b57108436211c7f798ba3de0bb0cd8ef469 (diff)
arm64: Consolidate CPU Sanity check to CPU Feature infrastructure
This patch consolidates the CPU Sanity check to the new infrastructure. Cc: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com> Tested-by: Dave Martin <Dave.Martin@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r--arch/arm64/include/asm/cpu.h3
-rw-r--r--arch/arm64/kernel/cpufeature.c164
-rw-r--r--arch/arm64/kernel/cpuinfo.c113
3 files changed, 134 insertions, 146 deletions
diff --git a/arch/arm64/include/asm/cpu.h b/arch/arm64/include/asm/cpu.h
index 704c17ba3ab0..b5e9cee4b5f8 100644
--- a/arch/arm64/include/asm/cpu.h
+++ b/arch/arm64/include/asm/cpu.h
@@ -64,6 +64,7 @@ void cpuinfo_store_cpu(void);
64void __init cpuinfo_store_boot_cpu(void); 64void __init cpuinfo_store_boot_cpu(void);
65 65
66void __init init_cpu_features(struct cpuinfo_arm64 *info); 66void __init init_cpu_features(struct cpuinfo_arm64 *info);
67void update_cpu_features(struct cpuinfo_arm64 *info); 67void update_cpu_features(int cpu, struct cpuinfo_arm64 *info,
68 struct cpuinfo_arm64 *boot);
68 69
69#endif /* __ASM_CPU_H */ 70#endif /* __ASM_CPU_H */
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 8d7abaa3a7f9..aae181760e1f 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -438,12 +438,9 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
438 update_mixed_endian_el0_support(info); 438 update_mixed_endian_el0_support(info);
439} 439}
440 440
441static void update_cpu_ftr_reg(u32 sys_reg, u64 new) 441static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
442{ 442{
443 struct arm64_ftr_bits *ftrp; 443 struct arm64_ftr_bits *ftrp;
444 struct arm64_ftr_reg *reg = get_arm64_ftr_reg(sys_reg);
445
446 BUG_ON(!reg);
447 444
448 for (ftrp = reg->ftr_bits; ftrp->width; ftrp++) { 445 for (ftrp = reg->ftr_bits; ftrp->width; ftrp++) {
449 s64 ftr_cur = arm64_ftr_value(ftrp, reg->sys_val); 446 s64 ftr_cur = arm64_ftr_value(ftrp, reg->sys_val);
@@ -458,36 +455,137 @@ static void update_cpu_ftr_reg(u32 sys_reg, u64 new)
458 455
459} 456}
460 457
461/* Update CPU feature register from non-boot CPU */ 458static int check_update_ftr_reg(u32 sys_id, int cpu, u64 val, u64 boot)
462void update_cpu_features(struct cpuinfo_arm64 *info)
463{ 459{
464 update_cpu_ftr_reg(SYS_CTR_EL0, info->reg_ctr); 460 struct arm64_ftr_reg *regp = get_arm64_ftr_reg(sys_id);
465 update_cpu_ftr_reg(SYS_DCZID_EL0, info->reg_dczid); 461
466 update_cpu_ftr_reg(SYS_CNTFRQ_EL0, info->reg_cntfrq); 462 BUG_ON(!regp);
467 update_cpu_ftr_reg(SYS_ID_AA64DFR0_EL1, info->reg_id_aa64dfr0); 463 update_cpu_ftr_reg(regp, val);
468 update_cpu_ftr_reg(SYS_ID_AA64DFR1_EL1, info->reg_id_aa64dfr1); 464 if ((boot & regp->strict_mask) == (val & regp->strict_mask))
469 update_cpu_ftr_reg(SYS_ID_AA64ISAR0_EL1, info->reg_id_aa64isar0); 465 return 0;
470 update_cpu_ftr_reg(SYS_ID_AA64ISAR1_EL1, info->reg_id_aa64isar1); 466 pr_warn("SANITY CHECK: Unexpected variation in %s. Boot CPU: %#016llx, CPU%d: %#016llx\n",
471 update_cpu_ftr_reg(SYS_ID_AA64MMFR0_EL1, info->reg_id_aa64mmfr0); 467 regp->name, boot, cpu, val);
472 update_cpu_ftr_reg(SYS_ID_AA64MMFR1_EL1, info->reg_id_aa64mmfr1); 468 return 1;
473 update_cpu_ftr_reg(SYS_ID_AA64PFR0_EL1, info->reg_id_aa64pfr0); 469}
474 update_cpu_ftr_reg(SYS_ID_AA64PFR1_EL1, info->reg_id_aa64pfr1); 470
475 update_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0); 471/*
476 update_cpu_ftr_reg(SYS_ID_ISAR0_EL1, info->reg_id_isar0); 472 * Update system wide CPU feature registers with the values from a
477 update_cpu_ftr_reg(SYS_ID_ISAR1_EL1, info->reg_id_isar1); 473 * non-boot CPU. Also performs SANITY checks to make sure that there
478 update_cpu_ftr_reg(SYS_ID_ISAR2_EL1, info->reg_id_isar2); 474 * aren't any insane variations from that of the boot CPU.
479 update_cpu_ftr_reg(SYS_ID_ISAR3_EL1, info->reg_id_isar3); 475 */
480 update_cpu_ftr_reg(SYS_ID_ISAR4_EL1, info->reg_id_isar4); 476void update_cpu_features(int cpu,
481 update_cpu_ftr_reg(SYS_ID_ISAR5_EL1, info->reg_id_isar5); 477 struct cpuinfo_arm64 *info,
482 update_cpu_ftr_reg(SYS_ID_MMFR0_EL1, info->reg_id_mmfr0); 478 struct cpuinfo_arm64 *boot)
483 update_cpu_ftr_reg(SYS_ID_MMFR1_EL1, info->reg_id_mmfr1); 479{
484 update_cpu_ftr_reg(SYS_ID_MMFR2_EL1, info->reg_id_mmfr2); 480 int taint = 0;
485 update_cpu_ftr_reg(SYS_ID_MMFR3_EL1, info->reg_id_mmfr3); 481
486 update_cpu_ftr_reg(SYS_ID_PFR0_EL1, info->reg_id_pfr0); 482 /*
487 update_cpu_ftr_reg(SYS_ID_PFR1_EL1, info->reg_id_pfr1); 483 * The kernel can handle differing I-cache policies, but otherwise
488 update_cpu_ftr_reg(SYS_MVFR0_EL1, info->reg_mvfr0); 484 * caches should look identical. Userspace JITs will make use of
489 update_cpu_ftr_reg(SYS_MVFR1_EL1, info->reg_mvfr1); 485 * *minLine.
490 update_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2); 486 */
487 taint |= check_update_ftr_reg(SYS_CTR_EL0, cpu,
488 info->reg_ctr, boot->reg_ctr);
489
490 /*
491 * Userspace may perform DC ZVA instructions. Mismatched block sizes
492 * could result in too much or too little memory being zeroed if a
493 * process is preempted and migrated between CPUs.
494 */
495 taint |= check_update_ftr_reg(SYS_DCZID_EL0, cpu,
496 info->reg_dczid, boot->reg_dczid);
497
498 /* If different, timekeeping will be broken (especially with KVM) */
499 taint |= check_update_ftr_reg(SYS_CNTFRQ_EL0, cpu,
500 info->reg_cntfrq, boot->reg_cntfrq);
501
502 /*
503 * The kernel uses self-hosted debug features and expects CPUs to
504 * support identical debug features. We presently need CTX_CMPs, WRPs,
505 * and BRPs to be identical.
506 * ID_AA64DFR1 is currently RES0.
507 */
508 taint |= check_update_ftr_reg(SYS_ID_AA64DFR0_EL1, cpu,
509 info->reg_id_aa64dfr0, boot->reg_id_aa64dfr0);
510 taint |= check_update_ftr_reg(SYS_ID_AA64DFR1_EL1, cpu,
511 info->reg_id_aa64dfr1, boot->reg_id_aa64dfr1);
512 /*
513 * Even in big.LITTLE, processors should be identical instruction-set
514 * wise.
515 */
516 taint |= check_update_ftr_reg(SYS_ID_AA64ISAR0_EL1, cpu,
517 info->reg_id_aa64isar0, boot->reg_id_aa64isar0);
518 taint |= check_update_ftr_reg(SYS_ID_AA64ISAR1_EL1, cpu,
519 info->reg_id_aa64isar1, boot->reg_id_aa64isar1);
520
521 /*
522 * Differing PARange support is fine as long as all peripherals and
523 * memory are mapped within the minimum PARange of all CPUs.
524 * Linux should not care about secure memory.
525 */
526 taint |= check_update_ftr_reg(SYS_ID_AA64MMFR0_EL1, cpu,
527 info->reg_id_aa64mmfr0, boot->reg_id_aa64mmfr0);
528 taint |= check_update_ftr_reg(SYS_ID_AA64MMFR1_EL1, cpu,
529 info->reg_id_aa64mmfr1, boot->reg_id_aa64mmfr1);
530
531 /*
532 * EL3 is not our concern.
533 * ID_AA64PFR1 is currently RES0.
534 */
535 taint |= check_update_ftr_reg(SYS_ID_AA64PFR0_EL1, cpu,
536 info->reg_id_aa64pfr0, boot->reg_id_aa64pfr0);
537 taint |= check_update_ftr_reg(SYS_ID_AA64PFR1_EL1, cpu,
538 info->reg_id_aa64pfr1, boot->reg_id_aa64pfr1);
539
540 /*
541 * If we have AArch32, we care about 32-bit features for compat. These
542 * registers should be RES0 otherwise.
543 */
544 taint |= check_update_ftr_reg(SYS_ID_DFR0_EL1, cpu,
545 info->reg_id_dfr0, boot->reg_id_dfr0);
546 taint |= check_update_ftr_reg(SYS_ID_ISAR0_EL1, cpu,
547 info->reg_id_isar0, boot->reg_id_isar0);
548 taint |= check_update_ftr_reg(SYS_ID_ISAR1_EL1, cpu,
549 info->reg_id_isar1, boot->reg_id_isar1);
550 taint |= check_update_ftr_reg(SYS_ID_ISAR2_EL1, cpu,
551 info->reg_id_isar2, boot->reg_id_isar2);
552 taint |= check_update_ftr_reg(SYS_ID_ISAR3_EL1, cpu,
553 info->reg_id_isar3, boot->reg_id_isar3);
554 taint |= check_update_ftr_reg(SYS_ID_ISAR4_EL1, cpu,
555 info->reg_id_isar4, boot->reg_id_isar4);
556 taint |= check_update_ftr_reg(SYS_ID_ISAR5_EL1, cpu,
557 info->reg_id_isar5, boot->reg_id_isar5);
558
559 /*
560 * Regardless of the value of the AuxReg field, the AIFSR, ADFSR, and
561 * ACTLR formats could differ across CPUs and therefore would have to
562 * be trapped for virtualization anyway.
563 */
564 taint |= check_update_ftr_reg(SYS_ID_MMFR0_EL1, cpu,
565 info->reg_id_mmfr0, boot->reg_id_mmfr0);
566 taint |= check_update_ftr_reg(SYS_ID_MMFR1_EL1, cpu,
567 info->reg_id_mmfr1, boot->reg_id_mmfr1);
568 taint |= check_update_ftr_reg(SYS_ID_MMFR2_EL1, cpu,
569 info->reg_id_mmfr2, boot->reg_id_mmfr2);
570 taint |= check_update_ftr_reg(SYS_ID_MMFR3_EL1, cpu,
571 info->reg_id_mmfr3, boot->reg_id_mmfr3);
572 taint |= check_update_ftr_reg(SYS_ID_PFR0_EL1, cpu,
573 info->reg_id_pfr0, boot->reg_id_pfr0);
574 taint |= check_update_ftr_reg(SYS_ID_PFR1_EL1, cpu,
575 info->reg_id_pfr1, boot->reg_id_pfr1);
576 taint |= check_update_ftr_reg(SYS_MVFR0_EL1, cpu,
577 info->reg_mvfr0, boot->reg_mvfr0);
578 taint |= check_update_ftr_reg(SYS_MVFR1_EL1, cpu,
579 info->reg_mvfr1, boot->reg_mvfr1);
580 taint |= check_update_ftr_reg(SYS_MVFR2_EL1, cpu,
581 info->reg_mvfr2, boot->reg_mvfr2);
582
583 /*
584 * Mismatched CPU features are a recipe for disaster. Don't even
585 * pretend to support them.
586 */
587 WARN_TAINT_ONCE(taint, TAINT_CPU_OUT_OF_SPEC,
588 "Unsupported CPU feature variation.\n");
491 589
492 update_mixed_endian_el0_support(info); 590 update_mixed_endian_el0_support(info);
493} 591}
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 857aaf05a143..f25869ea2646 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -192,116 +192,6 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
192 pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu); 192 pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
193} 193}
194 194
195static int check_reg_mask(char *name, u64 mask, u64 boot, u64 cur, int cpu)
196{
197 if ((boot & mask) == (cur & mask))
198 return 0;
199
200 pr_warn("SANITY CHECK: Unexpected variation in %s. Boot CPU: %#016lx, CPU%d: %#016lx\n",
201 name, (unsigned long)boot, cpu, (unsigned long)cur);
202
203 return 1;
204}
205
206#define CHECK_MASK(field, mask, boot, cur, cpu) \
207 check_reg_mask(#field, mask, (boot)->reg_ ## field, (cur)->reg_ ## field, cpu)
208
209#define CHECK(field, boot, cur, cpu) \
210 CHECK_MASK(field, ~0ULL, boot, cur, cpu)
211
212/*
213 * Verify that CPUs don't have unexpected differences that will cause problems.
214 */
215static void cpuinfo_sanity_check(struct cpuinfo_arm64 *cur)
216{
217 unsigned int cpu = smp_processor_id();
218 struct cpuinfo_arm64 *boot = &boot_cpu_data;
219 unsigned int diff = 0;
220
221 /*
222 * The kernel can handle differing I-cache policies, but otherwise
223 * caches should look identical. Userspace JITs will make use of
224 * *minLine.
225 */
226 diff |= CHECK_MASK(ctr, 0xffff3fff, boot, cur, cpu);
227
228 /*
229 * Userspace may perform DC ZVA instructions. Mismatched block sizes
230 * could result in too much or too little memory being zeroed if a
231 * process is preempted and migrated between CPUs.
232 */
233 diff |= CHECK(dczid, boot, cur, cpu);
234
235 /* If different, timekeeping will be broken (especially with KVM) */
236 diff |= CHECK(cntfrq, boot, cur, cpu);
237
238 /*
239 * The kernel uses self-hosted debug features and expects CPUs to
240 * support identical debug features. We presently need CTX_CMPs, WRPs,
241 * and BRPs to be identical.
242 * ID_AA64DFR1 is currently RES0.
243 */
244 diff |= CHECK(id_aa64dfr0, boot, cur, cpu);
245 diff |= CHECK(id_aa64dfr1, boot, cur, cpu);
246
247 /*
248 * Even in big.LITTLE, processors should be identical instruction-set
249 * wise.
250 */
251 diff |= CHECK(id_aa64isar0, boot, cur, cpu);
252 diff |= CHECK(id_aa64isar1, boot, cur, cpu);
253
254 /*
255 * Differing PARange support is fine as long as all peripherals and
256 * memory are mapped within the minimum PARange of all CPUs.
257 * Linux should not care about secure memory.
258 * ID_AA64MMFR1 is currently RES0.
259 */
260 diff |= CHECK_MASK(id_aa64mmfr0, 0xffffffffffff0ff0, boot, cur, cpu);
261 diff |= CHECK(id_aa64mmfr1, boot, cur, cpu);
262
263 /*
264 * EL3 is not our concern.
265 * ID_AA64PFR1 is currently RES0.
266 */
267 diff |= CHECK_MASK(id_aa64pfr0, 0xffffffffffff0fff, boot, cur, cpu);
268 diff |= CHECK(id_aa64pfr1, boot, cur, cpu);
269
270 /*
271 * If we have AArch32, we care about 32-bit features for compat. These
272 * registers should be RES0 otherwise.
273 */
274 diff |= CHECK(id_dfr0, boot, cur, cpu);
275 diff |= CHECK(id_isar0, boot, cur, cpu);
276 diff |= CHECK(id_isar1, boot, cur, cpu);
277 diff |= CHECK(id_isar2, boot, cur, cpu);
278 diff |= CHECK(id_isar3, boot, cur, cpu);
279 diff |= CHECK(id_isar4, boot, cur, cpu);
280 diff |= CHECK(id_isar5, boot, cur, cpu);
281 /*
282 * Regardless of the value of the AuxReg field, the AIFSR, ADFSR, and
283 * ACTLR formats could differ across CPUs and therefore would have to
284 * be trapped for virtualization anyway.
285 */
286 diff |= CHECK_MASK(id_mmfr0, 0xff0fffff, boot, cur, cpu);
287 diff |= CHECK(id_mmfr1, boot, cur, cpu);
288 diff |= CHECK(id_mmfr2, boot, cur, cpu);
289 diff |= CHECK(id_mmfr3, boot, cur, cpu);
290 diff |= CHECK(id_pfr0, boot, cur, cpu);
291 diff |= CHECK(id_pfr1, boot, cur, cpu);
292
293 diff |= CHECK(mvfr0, boot, cur, cpu);
294 diff |= CHECK(mvfr1, boot, cur, cpu);
295 diff |= CHECK(mvfr2, boot, cur, cpu);
296
297 /*
298 * Mismatched CPU features are a recipe for disaster. Don't even
299 * pretend to support them.
300 */
301 WARN_TAINT_ONCE(diff, TAINT_CPU_OUT_OF_SPEC,
302 "Unsupported CPU feature variation.\n");
303}
304
305static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info) 195static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
306{ 196{
307 info->reg_cntfrq = arch_timer_get_cntfrq(); 197 info->reg_cntfrq = arch_timer_get_cntfrq();
@@ -346,8 +236,7 @@ void cpuinfo_store_cpu(void)
346{ 236{
347 struct cpuinfo_arm64 *info = this_cpu_ptr(&cpu_data); 237 struct cpuinfo_arm64 *info = this_cpu_ptr(&cpu_data);
348 __cpuinfo_store_cpu(info); 238 __cpuinfo_store_cpu(info);
349 cpuinfo_sanity_check(info); 239 update_cpu_features(smp_processor_id(), info, &boot_cpu_data);
350 update_cpu_features(info);
351} 240}
352 241
353void __init cpuinfo_store_boot_cpu(void) 242void __init cpuinfo_store_boot_cpu(void)