From patchwork Thu Jun 26 15:18:46 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Rutland X-Patchwork-Id: 32570 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ob0-f200.google.com (mail-ob0-f200.google.com [209.85.214.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 3C430201EF for ; Thu, 26 Jun 2014 15:22:13 +0000 (UTC) Received: by mail-ob0-f200.google.com with SMTP id wm4sf20149071obc.7 for ; Thu, 26 Jun 2014 08:22:12 -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=XMWjMpH9V0s0FQYdeJde8c80J29xZC6CIK7s4r9Ywxw=; b=ln1PbobUOD/MrN5T2pZBGNPI6lucc4snVVuft+B/q3aBzvjuCVtwDW19VzlZ5d4Jnp auGG7mueCCKXQN3v0Ofb6QtK8zzIXT2gYEkXDpb7r+e0aAxUaZrmVW8LXnuEg4N7/+nj 2k66Om9lSHxsnU8nEFKGfc/qNr9M6rLsKxvEuKNuOVXeoB847InEEaTJzhDAvxgCx5JV o7GrqxgcFk6JfX6Y4/02JClUiJiEIAIm/cyNgdM+ol+QS9Q1B9eUG+0lEHZNIe6o1zFf Wqk2I6wSszuNyb3tn9Sg/eojfQFd3SfzmQ4vX345k9gX1hDT5yXR5hkU7ekYXtrw37GT atCQ== X-Gm-Message-State: ALoCoQkJFkAOgcRSSmAXhRtifKMIx4IzSl9njuPK9ACUcckNZz1gj7sDv2hG3fpPoELSwDNHtcYv X-Received: by 10.50.85.102 with SMTP id g6mr2377152igz.8.1403796132784; Thu, 26 Jun 2014 08:22:12 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.108.245 with SMTP id j108ls260126qgf.51.gmail; Thu, 26 Jun 2014 08:22:12 -0700 (PDT) X-Received: by 10.220.81.194 with SMTP id y2mr14048327vck.29.1403796132661; Thu, 26 Jun 2014 08:22:12 -0700 (PDT) Received: from mail-ve0-f182.google.com (mail-ve0-f182.google.com [209.85.128.182]) by mx.google.com with ESMTPS id ut8si4655238vec.4.2014.06.26.08.22.12 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 26 Jun 2014 08:22:12 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.128.182 as permitted sender) client-ip=209.85.128.182; Received: by mail-ve0-f182.google.com with SMTP id oy12so3931843veb.27 for ; Thu, 26 Jun 2014 08:22:12 -0700 (PDT) X-Received: by 10.58.220.230 with SMTP id pz6mr14136130vec.9.1403796132531; Thu, 26 Jun 2014 08:22:12 -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.37.5 with SMTP id tc5csp38153vcb; Thu, 26 Jun 2014 08:22:12 -0700 (PDT) X-Received: by 10.66.224.38 with SMTP id qz6mr22236176pac.153.1403796131624; Thu, 26 Jun 2014 08:22:11 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id vy9si10327716pbc.69.2014.06.26.08.22.11 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 26 Jun 2014 08:22:11 -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 1X0BTh-00077W-Cv; Thu, 26 Jun 2014 15:20:45 +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 1X0BTM-0005nd-Rv for linux-arm-kernel@lists.infradead.org; Thu, 26 Jun 2014 15:20:28 +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 s5QFInwt014784; Thu, 26 Jun 2014 16:20:01 +0100 (BST) From: Mark Rutland To: linux-arm-kernel@lists.infradead.org Subject: [PATCHv3 5/5] arm64: add runtime system sanity checks Date: Thu, 26 Jun 2014 16:18:46 +0100 Message-Id: <1403795926-17139-6-git-send-email-mark.rutland@arm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1403795926-17139-1-git-send-email-mark.rutland@arm.com> References: <1403795926-17139-1-git-send-email-mark.rutland@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140626_082025_295313_BDBECBEE X-CRM114-Status: GOOD ( 14.04 ) X-Spam-Score: -5.0 (-----) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-5.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] -0.0 T_RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -0.0 SPF_PASS SPF: sender matches SPF record Cc: Mark Rutland , catalin.marinas@arm.com, lorenzo.pieralisi@arm.com, will.deacon@arm.com, ard.biesheuvel@linaro.org 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.182 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. Where CPUs are fundamentally mismatched, set TAINT_CPU_OUT_OF_SPEC. Given that the kernel assumes CPUs are identical feature wise, let's not pretend that we expect such configurations to work. Supporting such configurations would require massive rework, and hopefully they will never exist. Signed-off-by: Mark Rutland --- arch/arm64/kernel/cpuinfo.c | 92 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c index 20ca6d0..fb4a70e 100644 --- a/arch/arm64/kernel/cpuinfo.c +++ b/arch/arm64/kernel/cpuinfo.c @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -54,6 +55,96 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info, pr_info("Detected %s I-cache on CPU%d", icache_policy_str[l1ip], cpu); } +static int check_reg_mask(char *name, u64 mask, u64 boot, u64 cur, int cpu) +{ + if ((boot & mask) == (cur & mask)) + return 0; + + pr_warn("SANITY CHECK: Unexpected variation in %s. Boot CPU: %#016lx, CPU%d: %#016lx\n", + name, (unsigned long)boot, cpu, (unsigned long)cur); + + return 1; +} + +#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, ~0ULL, boot, cur, cpu) + +/* + * Verify that CPUs don't have unexpected differences that will cause problems. + */ +static void cpuinfo_sanity_check(struct cpuinfo_arm64 *cur, int cpu) +{ + struct cpuinfo_arm64 *boot = &boot_cpu_data; + unsigned int diff = 0; + + /* + * The kernel can handle differing I-cache policies, but otherwise + * caches should look identical. Userspace JITs will make use of + * *minLine. + */ + diff |= CHECK_MASK(ctr, 0xffff3fff, boot, cur, cpu); + + /* + * Userspace may perform DC ZVA instructions. Mismatched block sizes + * could result in too much or too little memory being zeroed if a + * process is preempted and migrated between CPUs. + */ + diff |= CHECK(dczid, boot, cur, cpu); + + /* If different, timekeeping will be broken (especially with KVM) */ + diff |= CHECK(cntfrq, boot, cur, cpu); + + /* + * Even in big.LITTLE, processors should be identical instruction-set + * wise. + */ + diff |= CHECK(id_aa64isar0, boot, cur, cpu); + diff |= CHECK(id_aa64isar1, 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. + * ID_AA64MMFR1 is currently RES0. + */ + diff |= CHECK_MASK(id_aa64mmfr0, 0xffffffffffff0ff0, boot, cur, cpu); + diff |= CHECK(id_aa64mmfr1, boot, cur, cpu); + + /* + * EL3 is not our concern. + * ID_AA64PFR1 is currently RES0. + */ + diff |= CHECK_MASK(id_aa64pfr0, 0xffffffffffff0fff, boot, cur, cpu); + diff |= CHECK(id_aa64pfr1, boot, cur, cpu); + + /* + * If we have AArch32, we care about 32-bit features for compat. These + * registers should be RES0 otherwise. + */ + diff |= CHECK(id_isar0, boot, cur, cpu); + diff |= CHECK(id_isar1, boot, cur, cpu); + diff |= CHECK(id_isar2, boot, cur, cpu); + diff |= CHECK(id_isar3, boot, cur, cpu); + diff |= CHECK(id_isar4, boot, cur, cpu); + diff |= CHECK(id_isar5, boot, cur, cpu); + diff |= CHECK(id_mmfr0, boot, cur, cpu); + diff |= CHECK(id_mmfr1, boot, cur, cpu); + diff |= CHECK(id_mmfr2, boot, cur, cpu); + diff |= CHECK(id_mmfr3, boot, cur, cpu); + diff |= CHECK(id_pfr0, boot, cur, cpu); + diff |= CHECK(id_pfr1, boot, cur, cpu); + + /* + * Mismatched CPU features are a recipe for disaster. Don't even + * pretend to support them. + */ + WARN_TAINT_ONCE(diff, TAINT_CPU_OUT_OF_SPEC, + "Unsupported CPU feature variation."); +} + static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info, unsigned int cpu) { info->reg_cntfrq = arch_timer_get_cntfrq(); @@ -89,6 +180,7 @@ void cpuinfo_store_cpu(void) unsigned int cpu = smp_processor_id(); struct cpuinfo_arm64 *info = &per_cpu(cpu_data, cpu); __cpuinfo_store_cpu(info, cpu); + cpuinfo_sanity_check(info, cpu); } void __init cpuinfo_store_boot_cpu(void)