Received: by 2002:a25:1506:0:0:0:0:0 with SMTP id 6csp6214987ybv; Tue, 18 Feb 2020 12:10:32 -0800 (PST) X-Google-Smtp-Source: APXvYqwt+Ro4Tsu0qjlIdURxaoV1ICrJRCx/UgvB6PTP4+u9Md0IVtl2aonqYxSFSEg4+0Yc93tR X-Received: by 2002:a05:6830:22ca:: with SMTP id q10mr18297808otc.280.1582056631940; Tue, 18 Feb 2020 12:10:31 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1582056631; cv=none; d=google.com; s=arc-20160816; b=wWWe+U2zhZYtXS1wWs4FewpGSxkKBLnR/7TFy1djhdVHRw0x06ga192/w1xEa5UttX jNsDMc+KRQTqFmuG+q6YFOZrXyW1SkP5FhB6x+Ak3BlDO44/MIBg1dqMOpi2AWf6hxgr RAcM8ynSR2UDpLG0XTpCUo1hgplNAGK6dbdBwgdUU0Cr+iWMcuydi86v74o0cLKdGak3 AnAmbsg8GTrhJYF/vkAEDxNn6s6iZ4cA1cWc6nv0p7iGhGewhInlNVHoq7n0CjggAtY7 S+httcPJ3FSIICDKDTOiVd8z5loKrfd7qLtX2Sibr0/4afQ8ukzUIK4Sjlm72T4jblOL PXfA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=9cxH6omnedL6gvVk6IpvDWkv4ulZXaXokdxFIcbBpOE=; b=tKzrEHcXsy75Kh6ZCVvzO5WDBSmir/eYLTx0bRmV8m9ov6g7k9udCOrxMRxs9Ud5Ti Iu6z/iU4MHRrk6DHi+YuREa98rOK1v2BX1CAzacxx45QmaowpByGSLOeVSiPuwXTC43p Jn//IkbLOYWe6mmAHAAPEwHXRl0EfUlKLJl2/Nhhu4H2S4fPm4iFoQz6aHWb5CRl4rr8 Ry88XSRkC6iun21yuDx4mZgHqN7wZzo+YUmNWQ7yaHftZLCw/K7y+y/KVdkeYvW635qj INM5dUoXBDt4ODBuUsdSGDwUK3pAOqta/UeZT2rd+eczdpSbtXt7OQJ2KE/A44Jv9rz2 +H0w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=OlE93QL8; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id k128si8544054oih.274.2020.02.18.12.10.19; Tue, 18 Feb 2020 12:10:31 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=OlE93QL8; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726964AbgBRT5D (ORCPT + 99 others); Tue, 18 Feb 2020 14:57:03 -0500 Received: from mail.kernel.org ([198.145.29.99]:34198 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727761AbgBRT5B (ORCPT ); Tue, 18 Feb 2020 14:57:01 -0500 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 6A7C124670; Tue, 18 Feb 2020 19:56:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1582055819; bh=mi1fa9tjV0BUcFYBmkbrq5si7+ROUjp6B9kLMqc2Fkg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OlE93QL8HCTLTCrVxk+YobygV38gC/i0Rylq80NmgBaKSed3RCNRZ6bwp66cFejXi 8bWLauJToTnDrwjDPFkiREk2aC5zyXHJQ6P1AfdXU8mcDU8+l9KfC0s9tZ9Zrul2F0 +AyoK9sjpCyMYPn1/SzF2sNcB8jPDtle5m2pqyvE= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Will Deacon , Mark Rutland , Ard Biesheuvel , Catalin Marinas , Marc Zyngier , Suzuki K Poulose , Sasha Levin Subject: [PATCH 4.19 08/38] arm64: nofpsmid: Handle TIF_FOREIGN_FPSTATE flag cleanly Date: Tue, 18 Feb 2020 20:54:54 +0100 Message-Id: <20200218190419.519633378@linuxfoundation.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200218190418.536430858@linuxfoundation.org> References: <20200218190418.536430858@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Suzuki K Poulose commit 52f73c383b2418f2d31b798e765ae7d596c35021 upstream We detect the absence of FP/SIMD after an incapable CPU is brought up, and by then we have kernel threads running already with TIF_FOREIGN_FPSTATE set which could be set for early userspace applications (e.g, modprobe triggered from initramfs) and init. This could cause the applications to loop forever in do_nofity_resume() as we never clear the TIF flag, once we now know that we don't support FP. Fix this by making sure that we clear the TIF_FOREIGN_FPSTATE flag for tasks which may have them set, as we would have done in the normal case, but avoiding touching the hardware state (since we don't support any). Also to make sure we handle the cases seemlessly we categorise the helper functions to two : 1) Helpers for common core code, which calls into take appropriate actions without knowing the current FPSIMD state of the CPU/task. e.g fpsimd_restore_current_state(), fpsimd_flush_task_state(), fpsimd_save_and_flush_cpu_state(). We bail out early for these functions, taking any appropriate actions (e.g, clearing the TIF flag) where necessary to hide the handling from core code. 2) Helpers used when the presence of FP/SIMD is apparent. i.e, save/restore the FP/SIMD register state, modify the CPU/task FP/SIMD state. e.g, fpsimd_save(), task_fpsimd_load() - save/restore task FP/SIMD registers fpsimd_bind_task_to_cpu() \ - Update the "state" metadata for CPU/task. fpsimd_bind_state_to_cpu() / fpsimd_update_current_state() - Update the fp/simd state for the current task from memory. These must not be called in the absence of FP/SIMD. Put in a WARNING to make sure they are not invoked in the absence of FP/SIMD. KVM also uses the TIF_FOREIGN_FPSTATE flag to manage the FP/SIMD state on the CPU. However, without FP/SIMD support we trap all accesses and inject undefined instruction. Thus we should never "load" guest state. Add a sanity check to make sure this is valid. Cc: stable@vger.kernel.org # v4.19 Cc: Will Deacon Cc: Mark Rutland Reviewed-by: Ard Biesheuvel Reviewed-by: Catalin Marinas Acked-by: Marc Zyngier Signed-off-by: Suzuki K Poulose Signed-off-by: Will Deacon Signed-off-by: Sasha Levin --- arch/arm64/kernel/fpsimd.c | 20 ++++++++++++++++++-- arch/arm64/kvm/hyp/switch.c | 10 +++++++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 58c53bc969289..14fdbaa6ee3ab 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -218,6 +218,7 @@ static void sve_free(struct task_struct *task) static void task_fpsimd_load(void) { WARN_ON(!in_softirq() && !irqs_disabled()); + WARN_ON(!system_supports_fpsimd()); if (system_supports_sve() && test_thread_flag(TIF_SVE)) sve_load_state(sve_pffr(¤t->thread), @@ -238,6 +239,7 @@ void fpsimd_save(void) struct user_fpsimd_state *st = __this_cpu_read(fpsimd_last_state.st); /* set by fpsimd_bind_task_to_cpu() or fpsimd_bind_state_to_cpu() */ + WARN_ON(!system_supports_fpsimd()); WARN_ON(!in_softirq() && !irqs_disabled()); if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) { @@ -977,6 +979,7 @@ void fpsimd_bind_task_to_cpu(void) struct fpsimd_last_state_struct *last = this_cpu_ptr(&fpsimd_last_state); + WARN_ON(!system_supports_fpsimd()); last->st = ¤t->thread.uw.fpsimd_state; current->thread.fpsimd_cpu = smp_processor_id(); @@ -996,6 +999,7 @@ void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st) struct fpsimd_last_state_struct *last = this_cpu_ptr(&fpsimd_last_state); + WARN_ON(!system_supports_fpsimd()); WARN_ON(!in_softirq() && !irqs_disabled()); last->st = st; @@ -1008,8 +1012,19 @@ void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st) */ void fpsimd_restore_current_state(void) { - if (!system_supports_fpsimd()) + /* + * For the tasks that were created before we detected the absence of + * FP/SIMD, the TIF_FOREIGN_FPSTATE could be set via fpsimd_thread_switch(), + * e.g, init. This could be then inherited by the children processes. + * If we later detect that the system doesn't support FP/SIMD, + * we must clear the flag for all the tasks to indicate that the + * FPSTATE is clean (as we can't have one) to avoid looping for ever in + * do_notify_resume(). + */ + if (!system_supports_fpsimd()) { + clear_thread_flag(TIF_FOREIGN_FPSTATE); return; + } local_bh_disable(); @@ -1028,7 +1043,7 @@ void fpsimd_restore_current_state(void) */ void fpsimd_update_current_state(struct user_fpsimd_state const *state) { - if (!system_supports_fpsimd()) + if (WARN_ON(!system_supports_fpsimd())) return; local_bh_disable(); @@ -1055,6 +1070,7 @@ void fpsimd_flush_task_state(struct task_struct *t) void fpsimd_flush_cpu_state(void) { + WARN_ON(!system_supports_fpsimd()); __this_cpu_write(fpsimd_last_state.st, NULL); set_thread_flag(TIF_FOREIGN_FPSTATE); } diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index 6290a4e81d57a..f3978931aaf40 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -37,7 +37,15 @@ /* Check whether the FP regs were dirtied while in the host-side run loop: */ static bool __hyp_text update_fp_enabled(struct kvm_vcpu *vcpu) { - if (vcpu->arch.host_thread_info->flags & _TIF_FOREIGN_FPSTATE) + /* + * When the system doesn't support FP/SIMD, we cannot rely on + * the _TIF_FOREIGN_FPSTATE flag. However, we always inject an + * abort on the very first access to FP and thus we should never + * see KVM_ARM64_FP_ENABLED. For added safety, make sure we always + * trap the accesses. + */ + if (!system_supports_fpsimd() || + vcpu->arch.host_thread_info->flags & _TIF_FOREIGN_FPSTATE) vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED | KVM_ARM64_FP_HOST); -- 2.20.1