From patchwork Wed May 8 14:43:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "kirill.shutemov@linux.intel.com" X-Patchwork-Id: 10935979 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CEB4D1515 for ; Wed, 8 May 2019 14:49:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BF6DD28485 for ; Wed, 8 May 2019 14:49:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B3CED28928; Wed, 8 May 2019 14:49:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4E08428485 for ; Wed, 8 May 2019 14:49:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727509AbfEHOtK (ORCPT ); Wed, 8 May 2019 10:49:10 -0400 Received: from mga11.intel.com ([192.55.52.93]:7358 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728389AbfEHOos (ORCPT ); Wed, 8 May 2019 10:44:48 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 08 May 2019 07:44:48 -0700 X-ExtLoop1: 1 Received: from black.fi.intel.com ([10.237.72.28]) by fmsmga004.fm.intel.com with ESMTP; 08 May 2019 07:44:44 -0700 Received: by black.fi.intel.com (Postfix, from userid 1000) id 9190FC01; Wed, 8 May 2019 17:44:30 +0300 (EEST) From: "Kirill A. Shutemov" To: Andrew Morton , x86@kernel.org, Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , Borislav Petkov , Peter Zijlstra , Andy Lutomirski , David Howells Cc: Kees Cook , Dave Hansen , Kai Huang , Jacob Pan , Alison Schofield , linux-mm@kvack.org, kvm@vger.kernel.org, keyrings@vger.kernel.org, linux-kernel@vger.kernel.org, "Kirill A . Shutemov" Subject: [PATCH, RFC 38/62] keys/mktme: Support CPU hotplug for MKTME key service Date: Wed, 8 May 2019 17:43:58 +0300 Message-Id: <20190508144422.13171-39-kirill.shutemov@linux.intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190508144422.13171-1-kirill.shutemov@linux.intel.com> References: <20190508144422.13171-1-kirill.shutemov@linux.intel.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Alison Schofield The MKTME encryption hardware resides on each physical package. The encryption hardware includes 'Key Tables' that must be programmed identically across all physical packages in the platform. Although every CPU in a package can program its key table, the kernel uses one lead CPU per package for programming. CPU Hotplug Teardown -------------------- MKTME manages CPU hotplug teardown to make sure the ability to program all packages is preserved when MKTME keys are present. When MKTME keys are not currently programmed, simply allow the teardown, and set "mktme_allow_keys" to false. This will force a re-evaluation of the platform topology before the next key creation. If this CPU teardown mattered, MKTME key service will report an error and fail to create the key. (User can online that CPU and try again) When MKTME keys are currently programmed, allow teardowns of non 'lead CPU's' and of CPUs where another, core sibling CPU, can take over as lead. Do not allow teardown of any lead CPU that would render a hardware key table unreachable! CPU Hotplug Startup ------------------- CPUs coming online are of interest to the key service, but since the service never needs to block a CPU startup event, nor does it need to prepare for an onlining CPU, a callback is not implemented. MKTME will catch the availability of the new CPU, if it is needed, at the next key creation time. If keys are not allowed, that new CPU will be part of the topology evaluation to determine if keys should now be allowed. Signed-off-by: Alison Schofield Signed-off-by: Kirill A. Shutemov --- security/keys/mktme_keys.c | 51 +++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/security/keys/mktme_keys.c b/security/keys/mktme_keys.c index 734e1d28eb24..3dfc0647f1e5 100644 --- a/security/keys/mktme_keys.c +++ b/security/keys/mktme_keys.c @@ -102,9 +102,9 @@ void mktme_percpu_ref_release(struct percpu_ref *ref) return; } percpu_ref_exit(ref); - spin_lock_irqsave(&mktme_map_lock, flags); + spin_lock_irqsave(&mktme_lock, flags); mktme_release_keyid(keyid); - spin_unlock_irqrestore(&mktme_map_lock, flags); + spin_unlock_irqrestore(&mktme_lock, flags); } enum mktme_opt_id { @@ -506,9 +506,46 @@ static int mktme_alloc_pconfig_targets(void) return 0; } +static int mktme_cpu_teardown(unsigned int cpu) +{ + int new_leadcpu, ret = 0; + unsigned long flags; + + /* Do not allow key programming during cpu hotplug event */ + spin_lock_irqsave(&mktme_lock, flags); + + /* + * When no keys are in use, allow the teardown, and set + * mktme_allow_keys to FALSE. That forces an evaluation + * of the topology before the next key creation. + */ + if (!mktme_map->mapped_keyids) { + mktme_allow_keys = false; + goto out; + } + /* Teardown CPU is not a lead CPU. Allow teardown. */ + if (!cpumask_test_cpu(cpu, mktme_leadcpus)) + goto out; + + /* Teardown CPU is a lead CPU. Look for a new lead CPU. */ + new_leadcpu = cpumask_any_but(topology_core_cpumask(cpu), cpu); + + if (new_leadcpu < nr_cpumask_bits) { + /* New lead CPU found. Update the programming mask */ + __cpumask_clear_cpu(cpu, mktme_leadcpus); + __cpumask_set_cpu(new_leadcpu, mktme_leadcpus); + } else { + /* New lead CPU not found. Do not allow CPU teardown */ + ret = -1; + } +out: + spin_unlock_irqrestore(&mktme_lock, flags); + return ret; +} + static int __init init_mktme(void) { - int ret; + int ret, cpuhp; /* Verify keys are present */ if (mktme_nr_keyids < 1) @@ -553,10 +590,18 @@ static int __init init_mktme(void) if (!mktme_key_store) goto free_bitmap; + cpuhp = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, + "keys/mktme_keys:online", + NULL, mktme_cpu_teardown); + if (cpuhp < 0) + goto free_store; + ret = register_key_type(&key_type_mktme); if (!ret) return ret; /* SUCCESS */ + cpuhp_remove_state_nocalls(cpuhp); +free_store: kfree(mktme_key_store); free_bitmap: bitmap_free(mktme_bitmap_user_type);