From patchwork Tue Jun 17 17:04:34 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Rutland X-Patchwork-Id: 32082 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pd0-f199.google.com (mail-pd0-f199.google.com [209.85.192.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 94680206A0 for ; Tue, 17 Jun 2014 17:07:10 +0000 (UTC) Received: by mail-pd0-f199.google.com with SMTP id r10sf14914246pdi.10 for ; Tue, 17 Jun 2014 10:07:09 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:subject:date:message-id :in-reply-to:references:cc:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:mime-version:sender :errors-to:x-original-sender:x-original-authentication-results :mailing-list:content-type:content-transfer-encoding; bh=DT3W3BDgZkoaGelhNeDtK3YJumgXt/LOXJzl+rNMC1A=; b=LMMmW3x4ubGcBdHntKpJ3diOQGoAg48AL2qbeQcoHES8yZM0u24nNTvOhGSSusuq67 HBhTtWt4SfAwNuxd6MV9B9D0LkEcwKW09Ch4UMqK9Bu94WKCpdP+dak7a9OW7qaonbl7 57P1mejH8aQ3R3jl8p+VaDew3dUmIzBWGiyH+bScwZ6kpl4uHbZeOSH25nhprJgtgQK4 saGfevRdhtpGA8PNIeBqd+HsC7YoPC7SwWFtklSLDiCAS3tByaaYQ/1gDt+EnfQ+xK7B rpkacI9S1oy/IcSperVpHUmDi+ic7Qy/I9wNv6MbWSnvS+dmuRy6CmvyqRPRzCR6HnGs eS8A== X-Gm-Message-State: ALoCoQmHc2lVbZGF0U7szNicLPQ33JpNmUp6zCgG6LyXzgVhx5KDmwzqeqmAqxLK9FgkLVIkl1US X-Received: by 10.66.228.162 with SMTP id sj2mr2619580pac.11.1403024829935; Tue, 17 Jun 2014 10:07:09 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.25.225 with SMTP id 88ls863473qgt.85.gmail; Tue, 17 Jun 2014 10:07:09 -0700 (PDT) X-Received: by 10.58.229.101 with SMTP id sp5mr2100136vec.42.1403024829817; Tue, 17 Jun 2014 10:07:09 -0700 (PDT) Received: from mail-ve0-f175.google.com (mail-ve0-f175.google.com [209.85.128.175]) by mx.google.com with ESMTPS id ni9si5720832veb.58.2014.06.17.10.07.09 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 17 Jun 2014 10:07:09 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.128.175 as permitted sender) client-ip=209.85.128.175; Received: by mail-ve0-f175.google.com with SMTP id jx11so5092781veb.20 for ; Tue, 17 Jun 2014 10:07:09 -0700 (PDT) X-Received: by 10.58.186.207 with SMTP id fm15mr22754368vec.4.1403024829722; Tue, 17 Jun 2014 10:07:09 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.54.6 with SMTP id vs6csp224771vcb; Tue, 17 Jun 2014 10:07:09 -0700 (PDT) X-Received: by 10.229.127.199 with SMTP id h7mr22761225qcs.21.1403024829269; Tue, 17 Jun 2014 10:07:09 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id c11si14549695qgc.99.2014.06.17.10.07.09 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Jun 2014 10:07:09 -0700 (PDT) Received-SPF: none (google.com: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org does not designate permitted sender hosts) client-ip=2001:1868:205::9; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WwwpX-0007gl-J3; Tue, 17 Jun 2014 17:05:55 +0000 Received: from cam-admin0.cambridge.arm.com ([217.140.96.50]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Wwwoy-0006Ls-0s for linux-arm-kernel@lists.infradead.org; Tue, 17 Jun 2014 17:05:21 +0000 Received: from leverpostej.cambridge.arm.com (leverpostej.cambridge.arm.com [10.1.205.151]) by cam-admin0.cambridge.arm.com (8.12.6/8.12.6) with ESMTP id s5HH4ews015319; Tue, 17 Jun 2014 18:04:57 +0100 (BST) From: Mark Rutland To: linux-arm-kernel@lists.infradead.org Subject: [PATCHv2 4/4] arm64: add runtime system sanity checks Date: Tue, 17 Jun 2014 18:04:34 +0100 Message-Id: <1403024674-25108-5-git-send-email-mark.rutland@arm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1403024674-25108-1-git-send-email-mark.rutland@arm.com> References: <1403024674-25108-1-git-send-email-mark.rutland@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140617_100520_469940_A695E665 X-CRM114-Status: GOOD ( 14.48 ) X-Spam-Score: -6.0 (------) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-6.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [217.140.96.50 listed in list.dnswl.org] -1.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -0.0 SPF_PASS SPF: sender matches SPF record Cc: Mark Rutland , lorenzo.pieralisi@arm.com, will.deacon@arm.com X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: mark.rutland@arm.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.128.175 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 Unexpected variation in certain system register values across CPUs is an indicator of potential problems with a system. The kernel expects CPUs to be mostly identical in terms of supported features, even in systems with heterogeneous CPUs, with uniform instruction set support being critical for the correct operation of userspace. To help detect issues early where hardware violates the expectations of the kernel, this patch adds simple runtime sanity checks on important ID registers in the bring up path of each CPU. Signed-off-by: Mark Rutland --- arch/arm64/include/asm/cpu.h | 19 ++++++++- arch/arm64/kernel/cpuinfo.c | 94 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 111 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/cpu.h b/arch/arm64/include/asm/cpu.h index daca48d..8e6c9aa 100644 --- a/arch/arm64/include/asm/cpu.h +++ b/arch/arm64/include/asm/cpu.h @@ -16,12 +16,29 @@ /* * Records attributes of an individual CPU. * - * This is used to cache data for /proc/cpuinfo. + * This is used to cache data for /proc/cpuinfo and run-time sanity checks. */ struct cpuinfo_arm64 { struct cpu cpu; u32 reg_ctr; + u32 reg_cntfrq; u32 reg_midr; + + u64 reg_id_aa64isar0; + u64 reg_id_aa64mmfr0; + u64 reg_id_aa64pfr0; + u32 reg_id_isar0; + u32 reg_id_isar1; + u32 reg_id_isar2; + u32 reg_id_isar3; + u32 reg_id_isar4; + u32 reg_id_isar5; + u32 reg_id_mmfr0; + u32 reg_id_mmfr1; + u32 reg_id_mmfr2; + u32 reg_id_mmfr3; + u32 reg_id_pfr0; + u32 reg_id_pfr1; }; DECLARE_PER_CPU(struct cpuinfo_arm64, cpu_data); diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c index b146148..5ef96a0 100644 --- a/arch/arm64/kernel/cpuinfo.c +++ b/arch/arm64/kernel/cpuinfo.c @@ -1,5 +1,6 @@ /* - * Record CPU attributes for later retrieval + * Record CPU attributes for later retrieval, and sanity-check that processor + * features do not vary unexpectedly. * * Copyright (C) 2014 ARM Ltd. * This program is free software; you can redistribute it and/or modify @@ -14,6 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#include #include #include #include @@ -21,6 +23,7 @@ #include #include #include +#include DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data); @@ -45,13 +48,102 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info, int cpu) pr_info("Detected %s I-cache on CPU%d", icache_policy_str[l1ip], cpu); } +static void check_reg_mask(char *name, u64 mask, u64 boot, u64 cur, int cpu) +{ + if ((boot & mask) == (cur & mask)) + return; + + pr_warn("SANITY CHECK: Unexpected variation in %s. cpu0: %#016lx, cpu%d: %#016lx\n", + name, (unsigned long)boot, cpu, (unsigned long)cur); +} + +#define CHECK_MASK(field, mask, boot, cur, cpu) \ + check_reg_mask(#field, mask, (boot)->reg_ ## field, (cur)->reg_ ## field, cpu) + +#define CHECK(field, boot, cur, cpu) \ + CHECK_MASK(field, (u64)-1, boot, cur, cpu) + +/* + * Verify that CPUs don't have unexpected differences that will cause problems. + */ +void cpuinfo_sanity_check(struct cpuinfo_arm64 *cur) +{ + struct cpuinfo_arm64 *boot = &per_cpu(cpu_data, 0); + int cpu = smp_processor_id(); + + /* + * The kernel can handle differing I-cache policies, but otherwise + * caches should look identical. Userspace JITs will make use of + * *minLine. + */ + CHECK_MASK(ctr, 0xffff3fff, boot, cur, cpu); + + /* If different, timekeeping will be broken (especially with KVM) */ + CHECK(cntfrq, boot, cur, cpu); + + /* + * Even in big.LITTLE, processors should be identical instruction-set + * wise. + */ + CHECK(id_aa64isar0, boot, cur, cpu); + + /* + * Differing PARange support is fine as long as all peripherals and + * memory are mapped within the minimum PARange of all CPUs. + * Linux should not care about secure memory. + */ + CHECK_MASK(id_aa64mmfr0, 0xffffffffffff0ff0, boot, cur, cpu); + + /* + * EL3 is not our concern, and GIC system register support only matters + * if GICv3 is in use. + */ + CHECK_MASK(id_aa64pfr0, 0xfffffffff0ff0fff, boot, cur, cpu); + + /* + * If we have AArch32, we care about 32-bit features for compat. These + * registers should be RES0 otherwise. + */ + CHECK(id_isar0, boot, cur, cpu); + CHECK(id_isar1, boot, cur, cpu); + CHECK(id_isar2, boot, cur, cpu); + CHECK(id_isar3, boot, cur, cpu); + CHECK(id_isar4, boot, cur, cpu); + CHECK(id_isar5, boot, cur, cpu); + CHECK(id_mmfr0, boot, cur, cpu); + CHECK(id_mmfr1, boot, cur, cpu); + CHECK(id_mmfr2, boot, cur, cpu); + CHECK(id_mmfr3, boot, cur, cpu); + CHECK(id_pfr0, boot, cur, cpu); + CHECK(id_pfr1, boot, cur, cpu); +} + void cpuinfo_store_cpu(void) { int cpu = smp_processor_id(); struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, cpu); + cpuinfo->reg_cntfrq = arch_timer_get_cntfrq(); cpuinfo->reg_ctr = read_cpuid_cachetype(); cpuinfo->reg_midr = read_cpuid_id(); + cpuinfo->reg_id_aa64isar0 = read_cpuid(ID_AA64ISAR0_EL1); + cpuinfo->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1); + cpuinfo->reg_id_aa64pfr0 = read_cpuid(ID_AA64PFR0_EL1); + + cpuinfo->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1); + cpuinfo->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1); + cpuinfo->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1); + cpuinfo->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1); + cpuinfo->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1); + cpuinfo->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1); + cpuinfo->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1); + cpuinfo->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1); + cpuinfo->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1); + cpuinfo->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1); + cpuinfo->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1); + cpuinfo->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1); + cpuinfo_detect_icache_policy(cpuinfo, cpu); + cpuinfo_sanity_check(cpuinfo); }