From patchwork Mon May 27 08:31:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Gao X-Patchwork-Id: 10962273 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 1F3E191E for ; Mon, 27 May 2019 08:29:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1035428AAC for ; Mon, 27 May 2019 08:29:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0426528AB3; Mon, 27 May 2019 08:29:03 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 841D728AAC for ; Mon, 27 May 2019 08:29:02 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyd-00049j-9O; Mon, 27 May 2019 08:27:27 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyc-00049c-6h for xen-devel@lists.xenproject.org; Mon, 27 May 2019 08:27:26 +0000 X-Inumbo-ID: 41731805-8059-11e9-8980-bc764e045a96 Received: from mga12.intel.com (unknown [192.55.52.136]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 41731805-8059-11e9-8980-bc764e045a96; Mon, 27 May 2019 08:27:25 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 May 2019 01:27:24 -0700 X-ExtLoop1: 1 Received: from gao-cwp.sh.intel.com ([10.239.159.26]) by orsmga005.jf.intel.com with ESMTP; 27 May 2019 01:27:23 -0700 From: Chao Gao To: xen-devel@lists.xenproject.org Date: Mon, 27 May 2019 16:31:22 +0800 Message-Id: <1558945891-3015-2-git-send-email-chao.gao@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1558945891-3015-1-git-send-email-chao.gao@intel.com> References: <1558945891-3015-1-git-send-email-chao.gao@intel.com> Subject: [Xen-devel] [PATCH v7 01/10] misc/xen-ucode: Upload a microcode blob to the hypervisor X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Sergey Dyasli , Ashok Raj , Wei Liu , Konrad Rzeszutek Wilk , Ian Jackson , Chao Gao MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP This patch provides a tool for late microcode update. Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Chao Gao Acked-by: Andrew Cooper --- Changes in v7: - introduce xc_microcode_update() rather than xc_platform_op() - avoid creating bounce buffer twice - rename xenmicrocode to xen-ucode, following naming tradition of other tools there. --- tools/libxc/include/xenctrl.h | 1 + tools/libxc/xc_misc.c | 23 +++++++++++++ tools/misc/Makefile | 4 +++ tools/misc/xen-ucode.c | 78 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+) create mode 100644 tools/misc/xen-ucode.c diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index 538007a..6d80ae5 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -1244,6 +1244,7 @@ typedef uint32_t xc_node_to_node_dist_t; int xc_physinfo(xc_interface *xch, xc_physinfo_t *info); int xc_cputopoinfo(xc_interface *xch, unsigned *max_cpus, xc_cputopo_t *cputopo); +int xc_microcode_update(xc_interface *xch, const void *buf, size_t len); int xc_numainfo(xc_interface *xch, unsigned *max_nodes, xc_meminfo_t *meminfo, uint32_t *distance); int xc_pcitopoinfo(xc_interface *xch, unsigned num_devs, diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c index 5e6714a..85538e0 100644 --- a/tools/libxc/xc_misc.c +++ b/tools/libxc/xc_misc.c @@ -226,6 +226,29 @@ int xc_physinfo(xc_interface *xch, return 0; } +int xc_microcode_update(xc_interface *xch, const void *buf, size_t len) +{ + int ret; + DECLARE_PLATFORM_OP; + DECLARE_HYPERCALL_BUFFER(struct xenpf_microcode_update, uc); + + uc = xc_hypercall_buffer_alloc(xch, uc, len); + if (uc == NULL) + return -1; + + memcpy(uc, buf, len); + + platform_op.cmd = XENPF_microcode_update; + platform_op.u.microcode.length = len; + set_xen_guest_handle(platform_op.u.microcode.data, uc); + + ret = do_platform_op(xch, &platform_op); + + xc_hypercall_buffer_free(xch, uc); + + return ret; +} + int xc_cputopoinfo(xc_interface *xch, unsigned *max_cpus, xc_cputopo_t *cputopo) { diff --git a/tools/misc/Makefile b/tools/misc/Makefile index d4320dc..63947bf 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -22,6 +22,7 @@ INSTALL_SBIN-$(CONFIG_X86) += xen-hvmcrash INSTALL_SBIN-$(CONFIG_X86) += xen-hvmctx INSTALL_SBIN-$(CONFIG_X86) += xen-lowmemd INSTALL_SBIN-$(CONFIG_X86) += xen-mfndump +INSTALL_SBIN-$(CONFIG_X86) += xen-ucode INSTALL_SBIN += xencov INSTALL_SBIN += xenlockprof INSTALL_SBIN += xenperf @@ -113,4 +114,7 @@ xen-lowmemd: xen-lowmemd.o xencov: xencov.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS) +xen-ucode: xen-ucode.o + $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS) + -include $(DEPS_INCLUDE) diff --git a/tools/misc/xen-ucode.c b/tools/misc/xen-ucode.c new file mode 100644 index 0000000..da668ca --- /dev/null +++ b/tools/misc/xen-ucode.c @@ -0,0 +1,78 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void show_help(void) +{ + fprintf(stderr, + "xenmicrocode: Xen microcode updating tool\n" + "Usage: xenmicrocode \n"); +} + +int main(int argc, char *argv[]) +{ + int fd, len, ret; + char *filename, *buf; + struct stat st; + xc_interface *xch; + + if (argc < 2) + { + show_help(); + return 0; + } + + filename = argv[1]; + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Could not open %s. (err: %s)\n", + filename, strerror(errno)); + return errno; + } + + if (stat(filename, &st) != 0) { + fprintf(stderr, "Could not get the size of %s. (err: %s)\n", + filename, strerror(errno)); + return errno; + } + + len = st.st_size; + buf = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0); + if (buf == MAP_FAILED) { + fprintf(stderr, "mmap failed. (error: %s)\n", strerror(errno)); + return errno; + } + + xch = xc_interface_open(0,0,0); + if (xch == NULL) + { + fprintf(stderr, "Error opening xc interface. (err: %s)\n", + strerror(errno)); + return errno; + } + + ret = xc_microcode_update(xch, buf, len); + if (ret) + fprintf(stderr, "Failed to update microcode. (err: %s)\n", + strerror(errno)); + + xc_interface_close(xch); + + if (munmap(buf, len)) { + printf("Could not unmap: %d(%s)\n", errno, strerror(errno)); + return errno; + } + close(fd); + + return 0; +} From patchwork Mon May 27 08:31:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Chao Gao X-Patchwork-Id: 10962289 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 ED34F91E for ; Mon, 27 May 2019 08:29:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DE2F228AAC for ; Mon, 27 May 2019 08:29:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D25C528AB0; Mon, 27 May 2019 08:29:37 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 4F73A28AAC for ; Mon, 27 May 2019 08:29:37 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyg-0004A3-IP; Mon, 27 May 2019 08:27:30 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAye-00049q-Kf for xen-devel@lists.xenproject.org; Mon, 27 May 2019 08:27:28 +0000 X-Inumbo-ID: 42f5e26a-8059-11e9-8980-bc764e045a96 Received: from mga12.intel.com (unknown [192.55.52.136]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 42f5e26a-8059-11e9-8980-bc764e045a96; Mon, 27 May 2019 08:27:27 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 May 2019 01:27:27 -0700 X-ExtLoop1: 1 Received: from gao-cwp.sh.intel.com ([10.239.159.26]) by orsmga005.jf.intel.com with ESMTP; 27 May 2019 01:27:25 -0700 From: Chao Gao To: xen-devel@lists.xenproject.org Date: Mon, 27 May 2019 16:31:23 +0800 Message-Id: <1558945891-3015-3-git-send-email-chao.gao@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1558945891-3015-1-git-send-email-chao.gao@intel.com> References: <1558945891-3015-1-git-send-email-chao.gao@intel.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH v7 02/10] microcode/intel: extend microcode_update_match() X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Sergey Dyasli , Ashok Raj , Wei Liu , Andrew Cooper , Jan Beulich , Chao Gao , =?utf-8?q?R?= =?utf-8?q?oger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP to a more generic function. Then, this function can compare two given microcodes' signature/revision as well. Comparing two microcodes is used to update the global microcode cache (introduced by the later patches in this series) when a new microcode is given. Note that enum microcode_match_result will be used in common code (aka microcode.c), it has been placed in the common header. Signed-off-by: Chao Gao Reviewed-by: Roger Pau MonnĂ© --- Changes in v6: - eliminate unnecessary type casting in microcode_update_match - check if a patch has an extend header Changes in v5: - constify the extended_signature - use named enum type for the return value of microcode_update_match --- xen/arch/x86/microcode_intel.c | 48 +++++++++++++++++++---------------------- xen/include/asm-x86/microcode.h | 6 ++++++ 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/xen/arch/x86/microcode_intel.c b/xen/arch/x86/microcode_intel.c index 22fdeca..ecec83b 100644 --- a/xen/arch/x86/microcode_intel.c +++ b/xen/arch/x86/microcode_intel.c @@ -134,14 +134,28 @@ static int collect_cpu_info(unsigned int cpu_num, struct cpu_signature *csig) return 0; } -static inline int microcode_update_match( - unsigned int cpu_num, const struct microcode_header_intel *mc_header, - int sig, int pf) +static enum microcode_match_result microcode_update_match( + const struct microcode_header_intel *mc_header, unsigned int sig, + unsigned int pf, unsigned int rev) { - struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu_num); + const struct extended_sigtable *ext_header; + const struct extended_signature *ext_sig; + unsigned long data_size = get_datasize(mc_header); + unsigned int i; + + if ( sigmatch(sig, mc_header->sig, pf, mc_header->pf) ) + return (mc_header->rev > rev) ? NEW_UCODE : OLD_UCODE; - return (sigmatch(sig, uci->cpu_sig.sig, pf, uci->cpu_sig.pf) && - (mc_header->rev > uci->cpu_sig.rev)); + if ( get_totalsize(mc_header) == (data_size + MC_HEADER_SIZE) ) + return MIS_UCODE; + + ext_header = (const void *)(mc_header + 1) + data_size; + ext_sig = (const void *)(ext_header + 1); + for ( i = 0; i < ext_header->count; i++ ) + if ( sigmatch(sig, ext_sig[i].sig, pf, ext_sig[i].pf) ) + return (mc_header->rev > rev) ? NEW_UCODE : OLD_UCODE; + + return MIS_UCODE; } static int microcode_sanity_check(void *mc) @@ -243,31 +257,13 @@ static int get_matching_microcode(const void *mc, unsigned int cpu) { struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu); const struct microcode_header_intel *mc_header = mc; - const struct extended_sigtable *ext_header; unsigned long total_size = get_totalsize(mc_header); - int ext_sigcount, i; - struct extended_signature *ext_sig; void *new_mc; - if ( microcode_update_match(cpu, mc_header, - mc_header->sig, mc_header->pf) ) - goto find; - - if ( total_size <= (get_datasize(mc_header) + MC_HEADER_SIZE) ) + if ( microcode_update_match(mc, uci->cpu_sig.sig, uci->cpu_sig.pf, + uci->cpu_sig.rev) != NEW_UCODE ) return 0; - ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE; - ext_sigcount = ext_header->count; - ext_sig = (void *)ext_header + EXT_HEADER_SIZE; - for ( i = 0; i < ext_sigcount; i++ ) - { - if ( microcode_update_match(cpu, mc_header, - ext_sig->sig, ext_sig->pf) ) - goto find; - ext_sig++; - } - return 0; - find: pr_debug("microcode: CPU%d found a matching microcode update with" " version %#x (current=%#x)\n", cpu, mc_header->rev, uci->cpu_sig.rev); diff --git a/xen/include/asm-x86/microcode.h b/xen/include/asm-x86/microcode.h index 23ea954..73ebe9a 100644 --- a/xen/include/asm-x86/microcode.h +++ b/xen/include/asm-x86/microcode.h @@ -3,6 +3,12 @@ #include +enum microcode_match_result { + OLD_UCODE, /* signature matched, but revision id isn't newer */ + NEW_UCODE, /* signature matched, but revision id is newer */ + MIS_UCODE, /* signature mismatched */ +}; + struct cpu_signature; struct ucode_cpu_info; From patchwork Mon May 27 08:31:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Gao X-Patchwork-Id: 10962275 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 F1B4F91E for ; Mon, 27 May 2019 08:29:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E1DF728AAC for ; Mon, 27 May 2019 08:29:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D598D28AB3; Mon, 27 May 2019 08:29:05 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id EF49728AAC for ; Mon, 27 May 2019 08:29:04 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyj-0004B2-Sr; Mon, 27 May 2019 08:27:33 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyi-0004Ai-BZ for xen-devel@lists.xenproject.org; Mon, 27 May 2019 08:27:32 +0000 X-Inumbo-ID: 448cdb66-8059-11e9-8980-bc764e045a96 Received: from mga12.intel.com (unknown [192.55.52.136]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 448cdb66-8059-11e9-8980-bc764e045a96; Mon, 27 May 2019 08:27:30 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 May 2019 01:27:29 -0700 X-ExtLoop1: 1 Received: from gao-cwp.sh.intel.com ([10.239.159.26]) by orsmga005.jf.intel.com with ESMTP; 27 May 2019 01:27:28 -0700 From: Chao Gao To: xen-devel@lists.xenproject.org Date: Mon, 27 May 2019 16:31:24 +0800 Message-Id: <1558945891-3015-4-git-send-email-chao.gao@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1558945891-3015-1-git-send-email-chao.gao@intel.com> References: <1558945891-3015-1-git-send-email-chao.gao@intel.com> Subject: [Xen-devel] [PATCH v7 03/10] microcode: introduce a global cache of ucode patch X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Sergey Dyasli , Ashok Raj , Wei Liu , Andrew Cooper , Jan Beulich , Chao Gao , =?utf-8?q?R?= =?utf-8?q?oger_Pau_Monn=C3=A9?= MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP to replace the current per-cpu cache 'uci->mc'. With the assumption that all CPUs in the system have the same signature (family, model, stepping and 'pf'), one microcode update matches with one cpu should match with others. And Having multiple microcode revisions on different cpus would cause system unstable and is what should be avoided. Hence, caching only one microcode update is good enough for all cases. Introduce a global variable, microcode_cache, to store the newest matching microcode update. Whenever we get a new valid microcode update, its revision id is compared against that of the microcode update to determine whether the "microcode_cache" needs to be replaced. And now this global cache is loaded to cpu in apply_microcode(). All operations on the cache is expected to be done with the 'microcode_mutex' hold. Note that I deliberately avoid touching 'uci->mc' as I am going to remove it completely in the next patch. Signed-off-by: Chao Gao --- Changes in v7: - reworked to cache only one microcode patch rather than a list of microcode patches. Changes in v6: - constify local variables and function parameters if possible - comment that the global cache is protected by 'microcode_mutex'. and add assertions to catch violations in microcode_{save/find}_patch() Changes in v5: - reword the commit description - find_patch() and save_patch() are abstracted into common functions with some hooks for AMD and Intel --- xen/arch/x86/microcode.c | 36 ++++++++++++++++ xen/arch/x86/microcode_amd.c | 91 +++++++++++++++++++++++++++++++++++++---- xen/arch/x86/microcode_intel.c | 77 +++++++++++++++++++++++++++------- xen/include/asm-x86/microcode.h | 15 +++++++ 4 files changed, 197 insertions(+), 22 deletions(-) diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c index 4163f50..cff86a9 100644 --- a/xen/arch/x86/microcode.c +++ b/xen/arch/x86/microcode.c @@ -61,6 +61,9 @@ static struct ucode_mod_blob __initdata ucode_blob; */ static bool_t __initdata ucode_scan; +/* Protected by microcode_mutex */ +static struct microcode_patch *microcode_cache; + void __init microcode_set_module(unsigned int idx) { ucode_mod_idx = idx; @@ -262,6 +265,39 @@ int microcode_resume_cpu(unsigned int cpu) return err; } +const struct microcode_patch *microcode_get_cache(void) +{ + ASSERT(spin_is_locked(µcode_mutex)); + + return microcode_cache; +} + +/* Return true if cache gets updated. Otherwise, return false */ +bool microcode_update_cache(struct microcode_patch *patch) +{ + + ASSERT(spin_is_locked(µcode_mutex)); + + if ( !microcode_ops->match_cpu(patch) ) + return false; + + if ( !microcode_cache ) + microcode_cache = patch; + else if ( microcode_ops->compare_patch(patch, microcode_cache) == + NEW_UCODE ) + { + microcode_ops->free_patch(microcode_cache); + microcode_cache = patch; + } + else + { + microcode_ops->free_patch(patch); + return false; + } + + return true; +} + static int microcode_update_cpu(const void *buf, size_t size) { int err; diff --git a/xen/arch/x86/microcode_amd.c b/xen/arch/x86/microcode_amd.c index 7a854c0..1f05899 100644 --- a/xen/arch/x86/microcode_amd.c +++ b/xen/arch/x86/microcode_amd.c @@ -190,24 +190,85 @@ static bool_t microcode_fits(const struct microcode_amd *mc_amd, return 1; } +static bool match_cpu(const struct microcode_patch *patch) +{ + if ( !patch ) + return false; + return microcode_fits(patch->mc_amd, smp_processor_id()); +} + +static struct microcode_patch *alloc_microcode_patch( + const struct microcode_amd *mc_amd) +{ + struct microcode_patch *microcode_patch = xmalloc(struct microcode_patch); + struct microcode_amd *cache = xmalloc(struct microcode_amd); + void *mpb = xmalloc_bytes(mc_amd->mpb_size); + struct equiv_cpu_entry *equiv_cpu_table = + xmalloc_bytes(mc_amd->equiv_cpu_table_size); + + if ( !microcode_patch || !cache || !mpb || !equiv_cpu_table ) + { + xfree(microcode_patch); + xfree(cache); + xfree(mpb); + xfree(equiv_cpu_table); + printk(XENLOG_ERR "microcode: Can not allocate memory\n"); + return ERR_PTR(-ENOMEM); + } + + cache->equiv_cpu_table = equiv_cpu_table; + cache->mpb = mpb; + memcpy(cache->equiv_cpu_table, mc_amd->equiv_cpu_table, + mc_amd->equiv_cpu_table_size); + memcpy(cache->mpb, mc_amd->mpb, mc_amd->mpb_size); + cache->equiv_cpu_table_size = mc_amd->equiv_cpu_table_size; + cache->mpb_size = mc_amd->mpb_size; + microcode_patch->mc_amd = cache; + + return microcode_patch; +} + +static void free_patch(struct microcode_patch *microcode_patch) +{ + struct microcode_amd *mc_amd = microcode_patch->mc_amd; + + xfree(mc_amd->equiv_cpu_table); + xfree(mc_amd->mpb); + xfree(mc_amd); + xfree(microcode_patch); +} + +static enum microcode_match_result compare_patch( + const struct microcode_patch *new, const struct microcode_patch *old) +{ + const struct microcode_amd *new_mc = new->mc_amd; + const struct microcode_header_amd *new_header = new_mc->mpb; + const struct microcode_amd *old_mc = old->mc_amd; + const struct microcode_header_amd *old_header = old_mc->mpb; + + if ( new_header->processor_rev_id == old_header->processor_rev_id ) + return (new_header->patch_id > old_header->patch_id) ? + NEW_UCODE : OLD_UCODE; + + return MIS_UCODE; +} + static int apply_microcode(unsigned int cpu) { unsigned long flags; struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu); uint32_t rev; - struct microcode_amd *mc_amd = uci->mc.mc_amd; - struct microcode_header_amd *hdr; int hw_err; + const struct microcode_header_amd *hdr; + const struct microcode_patch *patch = microcode_get_cache(); /* We should bind the task to the CPU */ BUG_ON(raw_smp_processor_id() != cpu); - if ( mc_amd == NULL ) + if ( !match_cpu(patch) ) return -EINVAL; - hdr = mc_amd->mpb; - if ( hdr == NULL ) - return -EINVAL; + hdr = patch->mc_amd->mpb; spin_lock_irqsave(µcode_update_lock, flags); @@ -497,7 +558,20 @@ static int cpu_request_microcode(unsigned int cpu, const void *buf, while ( (error = get_ucode_from_buffer_amd(mc_amd, buf, bufsize, &offset)) == 0 ) { - if ( microcode_fits(mc_amd, cpu) ) + struct microcode_patch *new_patch = alloc_microcode_patch(mc_amd); + + if ( IS_ERR(new_patch) ) + { + error = PTR_ERR(new_patch); + break; + } + + if ( match_cpu(new_patch) ) + microcode_update_cache(new_patch); + else + free_patch(new_patch); + + if ( match_cpu(microcode_get_cache()) ) { error = apply_microcode(cpu); if ( error ) @@ -639,6 +713,9 @@ static const struct microcode_ops microcode_amd_ops = { .collect_cpu_info = collect_cpu_info, .apply_microcode = apply_microcode, .start_update = start_update, + .free_patch = free_patch, + .compare_patch = compare_patch, + .match_cpu = match_cpu, }; int __init microcode_init_amd(void) diff --git a/xen/arch/x86/microcode_intel.c b/xen/arch/x86/microcode_intel.c index ecec83b..d3405a0 100644 --- a/xen/arch/x86/microcode_intel.c +++ b/xen/arch/x86/microcode_intel.c @@ -248,6 +248,32 @@ static int microcode_sanity_check(void *mc) return 0; } +static bool match_cpu(const struct microcode_patch *patch) +{ + const struct ucode_cpu_info *uci = &this_cpu(ucode_cpu_info); + + if ( !patch ) + return false; + + return microcode_update_match(&patch->mc_intel->hdr, uci->cpu_sig.sig, + uci->cpu_sig.pf, uci->cpu_sig.rev) == NEW_UCODE; +} + +static void free_patch(struct microcode_patch *patch) +{ + xfree(patch->mc_intel); + xfree(patch); +} + +static enum microcode_match_result compare_patch( + const struct microcode_patch *new, const struct microcode_patch *old) +{ + const struct microcode_header_intel *old_header = &old->mc_intel->hdr; + + return microcode_update_match(&new->mc_intel->hdr, old_header->sig, + old_header->pf, old_header->rev); +} + /* * return 0 - no update found * return 1 - found update @@ -258,10 +284,26 @@ static int get_matching_microcode(const void *mc, unsigned int cpu) struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu); const struct microcode_header_intel *mc_header = mc; unsigned long total_size = get_totalsize(mc_header); - void *new_mc; + void *new_mc = xmalloc_bytes(total_size); + struct microcode_patch *new_patch = xmalloc(struct microcode_patch); + + if ( !new_patch || !new_mc ) + { + xfree(new_patch); + xfree(new_mc); + printk(XENLOG_ERR "microcode: Can not allocate memory\n"); + return -ENOMEM; + } + memcpy(new_mc, mc, total_size); + new_patch->mc_intel = new_mc; - if ( microcode_update_match(mc, uci->cpu_sig.sig, uci->cpu_sig.pf, - uci->cpu_sig.rev) != NEW_UCODE ) + if ( !match_cpu(new_patch) ) + { + free_patch(new_patch); + return 0; + } + + if ( !microcode_update_cache(new_patch) ) return 0; pr_debug("microcode: CPU%d found a matching microcode update with" @@ -277,6 +319,7 @@ static int get_matching_microcode(const void *mc, unsigned int cpu) memcpy(new_mc, mc, total_size); xfree(uci->mc.mc_intel); uci->mc.mc_intel = new_mc; + return 1; } @@ -287,18 +330,22 @@ static int apply_microcode(unsigned int cpu) unsigned int val[2]; unsigned int cpu_num = raw_smp_processor_id(); struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu_num); + const struct microcode_intel *mc_intel; + const struct microcode_patch *patch = microcode_get_cache(); /* We should bind the task to the CPU */ BUG_ON(cpu_num != cpu); - if ( uci->mc.mc_intel == NULL ) + if ( !match_cpu(patch) ) return -EINVAL; + mc_intel = patch->mc_intel; + /* serialize access to the physical write to MSR 0x79 */ spin_lock_irqsave(µcode_update_lock, flags); /* write microcode via MSR 0x79 */ - wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)uci->mc.mc_intel->bits); + wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc_intel->bits); wrmsrl(MSR_IA32_UCODE_REV, 0x0ULL); /* As documented in the SDM: Do a CPUID 1 here */ @@ -309,19 +356,19 @@ static int apply_microcode(unsigned int cpu) val[1] = (uint32_t)(msr_content >> 32); spin_unlock_irqrestore(µcode_update_lock, flags); - if ( val[1] != uci->mc.mc_intel->hdr.rev ) + if ( val[1] != mc_intel->hdr.rev ) { printk(KERN_ERR "microcode: CPU%d update from revision " "%#x to %#x failed. Resulting revision is %#x.\n", cpu_num, - uci->cpu_sig.rev, uci->mc.mc_intel->hdr.rev, val[1]); + uci->cpu_sig.rev, mc_intel->hdr.rev, val[1]); return -EIO; } printk(KERN_INFO "microcode: CPU%d updated from revision " "%#x to %#x, date = %04x-%02x-%02x \n", cpu_num, uci->cpu_sig.rev, val[1], - uci->mc.mc_intel->hdr.year, - uci->mc.mc_intel->hdr.month, - uci->mc.mc_intel->hdr.day); + mc_intel->hdr.year, + mc_intel->hdr.month, + mc_intel->hdr.day); uci->cpu_sig.rev = val[1]; return 0; @@ -361,7 +408,6 @@ static int cpu_request_microcode(unsigned int cpu, const void *buf, long offset = 0; int error = 0; void *mc; - unsigned int matching_count = 0; /* We should bind the task to the CPU */ BUG_ON(cpu != raw_smp_processor_id()); @@ -379,10 +425,8 @@ static int cpu_request_microcode(unsigned int cpu, const void *buf, * lets keep searching till the latest version */ if ( error == 1 ) - { - matching_count++; error = 0; - } + xfree(mc); } if ( offset > 0 ) @@ -390,7 +434,7 @@ static int cpu_request_microcode(unsigned int cpu, const void *buf, if ( offset < 0 ) error = offset; - if ( !error && matching_count ) + if ( !error && match_cpu(microcode_get_cache()) ) error = apply_microcode(cpu); return error; @@ -406,6 +450,9 @@ static const struct microcode_ops microcode_intel_ops = { .cpu_request_microcode = cpu_request_microcode, .collect_cpu_info = collect_cpu_info, .apply_microcode = apply_microcode, + .free_patch = free_patch, + .compare_patch = compare_patch, + .match_cpu = match_cpu, }; int __init microcode_init_intel(void) diff --git a/xen/include/asm-x86/microcode.h b/xen/include/asm-x86/microcode.h index 73ebe9a..6541c58 100644 --- a/xen/include/asm-x86/microcode.h +++ b/xen/include/asm-x86/microcode.h @@ -12,6 +12,13 @@ enum microcode_match_result { struct cpu_signature; struct ucode_cpu_info; +struct microcode_patch { + union { + struct microcode_intel *mc_intel; + struct microcode_amd *mc_amd; + }; +}; + struct microcode_ops { int (*microcode_resume_match)(unsigned int cpu, const void *mc); int (*cpu_request_microcode)(unsigned int cpu, const void *buf, @@ -19,6 +26,11 @@ struct microcode_ops { int (*collect_cpu_info)(unsigned int cpu, struct cpu_signature *csig); int (*apply_microcode)(unsigned int cpu); int (*start_update)(void); + void (*free_patch)(struct microcode_patch *patch); + bool (*match_cpu)(const struct microcode_patch *patch); + enum microcode_match_result (*compare_patch)( + const struct microcode_patch *new, + const struct microcode_patch *old); }; struct cpu_signature { @@ -39,4 +51,7 @@ struct ucode_cpu_info { DECLARE_PER_CPU(struct ucode_cpu_info, ucode_cpu_info); extern const struct microcode_ops *microcode_ops; +const struct microcode_patch *microcode_get_cache(void); +bool microcode_update_cache(struct microcode_patch *patch); + #endif /* ASM_X86__MICROCODE_H */ From patchwork Mon May 27 08:31:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Gao X-Patchwork-Id: 10962283 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 55BCC91E for ; Mon, 27 May 2019 08:29:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4462A28AAC for ; Mon, 27 May 2019 08:29:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3838C28AB3; Mon, 27 May 2019 08:29:29 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 34C3628AAC for ; Mon, 27 May 2019 08:29:28 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAym-0004CC-By; Mon, 27 May 2019 08:27:36 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyk-0004Be-QO for xen-devel@lists.xenproject.org; Mon, 27 May 2019 08:27:34 +0000 X-Inumbo-ID: 4626625c-8059-11e9-8980-bc764e045a96 Received: from mga12.intel.com (unknown [192.55.52.136]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 4626625c-8059-11e9-8980-bc764e045a96; Mon, 27 May 2019 08:27:32 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 May 2019 01:27:32 -0700 X-ExtLoop1: 1 Received: from gao-cwp.sh.intel.com ([10.239.159.26]) by orsmga005.jf.intel.com with ESMTP; 27 May 2019 01:27:30 -0700 From: Chao Gao To: xen-devel@lists.xenproject.org Date: Mon, 27 May 2019 16:31:25 +0800 Message-Id: <1558945891-3015-5-git-send-email-chao.gao@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1558945891-3015-1-git-send-email-chao.gao@intel.com> References: <1558945891-3015-1-git-send-email-chao.gao@intel.com> Subject: [Xen-devel] [PATCH v7 04/10] microcode: remove struct ucode_cpu_info X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Sergey Dyasli , Ashok Raj , Wei Liu , Andrew Cooper , Jan Beulich , Chao Gao , =?utf-8?q?R?= =?utf-8?q?oger_Pau_Monn=C3=A9?= MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP We can remove the per-cpu cache field in struct ucode_cpu_info since it has been replaced by a global cache. It would leads to only one field remaining in ucode_cpu_info. Then, this struct is removed and the remaining field (cpu signature) is stored in per-cpu area. Also remove 'microcode_resume_match' from microcode_ops because the check is done in find_patch(). The cpu status notifier is also removed. It was used to free the "mc" field to avoid memory leak. Signed-off-by: Chao Gao --- Changes in v6: - remove the whole struct ucode_cpu_info instead of the per-cpu cache in it. --- xen/arch/x86/apic.c | 2 +- xen/arch/x86/microcode.c | 91 +++--------------------------------- xen/arch/x86/microcode_amd.c | 100 +++++----------------------------------- xen/arch/x86/microcode_intel.c | 33 ++++--------- xen/arch/x86/spec_ctrl.c | 2 +- xen/include/asm-x86/microcode.h | 13 +----- 6 files changed, 30 insertions(+), 211 deletions(-) diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c index fafc0bd..d216455 100644 --- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -1188,7 +1188,7 @@ static void __init check_deadline_errata(void) else rev = (unsigned long)m->driver_data; - if ( this_cpu(ucode_cpu_info).cpu_sig.rev >= rev ) + if ( this_cpu(cpu_sig).rev >= rev ) return; setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE); diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c index cff86a9..0c01dfa 100644 --- a/xen/arch/x86/microcode.c +++ b/xen/arch/x86/microcode.c @@ -187,7 +187,7 @@ const struct microcode_ops *microcode_ops; static DEFINE_SPINLOCK(microcode_mutex); -DEFINE_PER_CPU(struct ucode_cpu_info, ucode_cpu_info); +DEFINE_PER_CPU(struct cpu_signature, cpu_sig); struct microcode_info { unsigned int cpu; @@ -196,70 +196,19 @@ struct microcode_info { char buffer[1]; }; -static void __microcode_fini_cpu(unsigned int cpu) -{ - struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu); - - xfree(uci->mc.mc_valid); - memset(uci, 0, sizeof(*uci)); -} - -static void microcode_fini_cpu(unsigned int cpu) -{ - spin_lock(µcode_mutex); - __microcode_fini_cpu(cpu); - spin_unlock(µcode_mutex); -} - int microcode_resume_cpu(unsigned int cpu) { int err; - struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu); - struct cpu_signature nsig; - unsigned int cpu2; + struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); if ( !microcode_ops ) return 0; spin_lock(µcode_mutex); - err = microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig); - if ( err ) - { - __microcode_fini_cpu(cpu); - spin_unlock(µcode_mutex); - return err; - } - - if ( uci->mc.mc_valid ) - { - err = microcode_ops->microcode_resume_match(cpu, uci->mc.mc_valid); - if ( err >= 0 ) - { - if ( err ) - err = microcode_ops->apply_microcode(cpu); - spin_unlock(µcode_mutex); - return err; - } - } - - nsig = uci->cpu_sig; - __microcode_fini_cpu(cpu); - uci->cpu_sig = nsig; - - err = -EIO; - for_each_online_cpu ( cpu2 ) - { - uci = &per_cpu(ucode_cpu_info, cpu2); - if ( uci->mc.mc_valid && - microcode_ops->microcode_resume_match(cpu, uci->mc.mc_valid) > 0 ) - { - err = microcode_ops->apply_microcode(cpu); - break; - } - } - - __microcode_fini_cpu(cpu); + err = microcode_ops->collect_cpu_info(cpu, sig); + if ( likely(!err) ) + err = microcode_ops->apply_microcode(cpu); spin_unlock(µcode_mutex); return err; @@ -302,16 +251,13 @@ static int microcode_update_cpu(const void *buf, size_t size) { int err; unsigned int cpu = smp_processor_id(); - struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu); + struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); spin_lock(µcode_mutex); - err = microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig); + err = microcode_ops->collect_cpu_info(cpu, sig); if ( likely(!err) ) err = microcode_ops->cpu_request_microcode(cpu, buf, size); - else - __microcode_fini_cpu(cpu); - spin_unlock(µcode_mutex); return err; @@ -398,25 +344,6 @@ static int __init microcode_init(void) } __initcall(microcode_init); -static int microcode_percpu_callback( - struct notifier_block *nfb, unsigned long action, void *hcpu) -{ - unsigned int cpu = (unsigned long)hcpu; - - switch ( action ) - { - case CPU_DEAD: - microcode_fini_cpu(cpu); - break; - } - - return NOTIFY_DONE; -} - -static struct notifier_block microcode_percpu_nfb = { - .notifier_call = microcode_percpu_callback, -}; - int __init early_microcode_update_cpu(bool start_update) { int rc = 0; @@ -460,12 +387,8 @@ int __init early_microcode_init(void) return rc; if ( microcode_ops ) - { if ( ucode_mod.mod_end || ucode_blob.size ) rc = early_microcode_update_cpu(true); - register_cpu_notifier(µcode_percpu_nfb); - } - return rc; } diff --git a/xen/arch/x86/microcode_amd.c b/xen/arch/x86/microcode_amd.c index 1f05899..93af2c9 100644 --- a/xen/arch/x86/microcode_amd.c +++ b/xen/arch/x86/microcode_amd.c @@ -155,7 +155,7 @@ static bool_t find_equiv_cpu_id(const struct equiv_cpu_entry *equiv_cpu_table, static bool_t microcode_fits(const struct microcode_amd *mc_amd, unsigned int cpu) { - struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu); + const struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); const struct microcode_header_amd *mc_header = mc_amd->mpb; const struct equiv_cpu_entry *equiv_cpu_table = mc_amd->equiv_cpu_table; unsigned int current_cpu_id; @@ -178,14 +178,14 @@ static bool_t microcode_fits(const struct microcode_amd *mc_amd, return 0; } - if ( mc_header->patch_id <= uci->cpu_sig.rev ) + if ( mc_header->patch_id <= sig->rev ) { pr_debug("microcode: patch is already at required level or greater.\n"); return 0; } pr_debug("microcode: CPU%d found a matching microcode update with version %#x (current=%#x)\n", - cpu, mc_header->patch_id, uci->cpu_sig.rev); + cpu, mc_header->patch_id, sig->rev); return 1; } @@ -256,9 +256,9 @@ static enum microcode_match_result compare_patch( static int apply_microcode(unsigned int cpu) { unsigned long flags; - struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu); uint32_t rev; int hw_err; + struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); const struct microcode_header_amd *hdr; const struct microcode_patch *patch = microcode_get_cache(); @@ -294,9 +294,9 @@ static int apply_microcode(unsigned int cpu) } printk(KERN_WARNING "microcode: CPU%d updated from revision %#x to %#x\n", - cpu, uci->cpu_sig.rev, hdr->patch_id); + cpu, sig->rev, hdr->patch_id); - uci->cpu_sig.rev = rev; + sig->rev = rev; return 0; } @@ -442,14 +442,14 @@ static bool_t check_final_patch_levels(unsigned int cpu) * any of the 'final_levels', then we should not update the microcode * patch on the cpu as system will hang otherwise. */ - struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu); + const struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); unsigned int i; if ( boot_cpu_data.x86 != 0x10 ) return 0; for ( i = 0; i < ARRAY_SIZE(final_levels); i++ ) - if ( uci->cpu_sig.rev == final_levels[i] ) + if ( sig->rev == final_levels[i] ) return 1; return 0; @@ -458,13 +458,12 @@ static bool_t check_final_patch_levels(unsigned int cpu) static int cpu_request_microcode(unsigned int cpu, const void *buf, size_t bufsize) { - struct microcode_amd *mc_amd, *mc_old; + struct microcode_amd *mc_amd; size_t offset = 0; - size_t last_offset, applied_offset = 0; - int error = 0, save_error = 1; - struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu); + int error = 0; unsigned int current_cpu_id; unsigned int equiv_cpu_id; + const struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); /* We should bind the task to the CPU */ BUG_ON(cpu != raw_smp_processor_id()); @@ -533,7 +532,7 @@ static int cpu_request_microcode(unsigned int cpu, const void *buf, { printk(KERN_ERR "microcode: CPU%d incorrect or corrupt container file\n" "microcode: Failed to update patch level. " - "Current lvl:%#x\n", cpu, uci->cpu_sig.rev); + "Current lvl:%#x\n", cpu, sig->rev); break; } } @@ -544,17 +543,12 @@ static int cpu_request_microcode(unsigned int cpu, const void *buf, goto out; } - mc_old = uci->mc.mc_amd; - /* implicitely validates uci->mc.mc_valid */ - uci->mc.mc_amd = mc_amd; - /* * It's possible the data file has multiple matching ucode, * lets keep searching till the latest version */ mc_amd->mpb = NULL; mc_amd->mpb_size = 0; - last_offset = offset; while ( (error = get_ucode_from_buffer_amd(mc_amd, buf, bufsize, &offset)) == 0 ) { @@ -576,11 +570,8 @@ static int cpu_request_microcode(unsigned int cpu, const void *buf, error = apply_microcode(cpu); if ( error ) break; - applied_offset = last_offset; } - last_offset = offset; - if ( offset >= bufsize ) break; @@ -609,26 +600,6 @@ static int cpu_request_microcode(unsigned int cpu, const void *buf, break; } - /* On success keep the microcode patch for - * re-apply on resume. - */ - if ( applied_offset ) - { - save_error = get_ucode_from_buffer_amd( - mc_amd, buf, bufsize, &applied_offset); - - if ( save_error ) - error = save_error; - } - - if ( save_error ) - { - xfree(mc_amd); - uci->mc.mc_amd = mc_old; - } - else - xfree(mc_old); - out: #if CONFIG_HVM svm_host_osvw_init(); @@ -643,52 +614,6 @@ static int cpu_request_microcode(unsigned int cpu, const void *buf, return error; } -static int microcode_resume_match(unsigned int cpu, const void *mc) -{ - struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu); - struct microcode_amd *mc_amd = uci->mc.mc_amd; - const struct microcode_amd *src = mc; - - if ( !microcode_fits(src, cpu) ) - return 0; - - if ( src != mc_amd ) - { - if ( mc_amd ) - { - xfree(mc_amd->equiv_cpu_table); - xfree(mc_amd->mpb); - xfree(mc_amd); - } - - mc_amd = xmalloc(struct microcode_amd); - uci->mc.mc_amd = mc_amd; - if ( !mc_amd ) - return -ENOMEM; - mc_amd->equiv_cpu_table = xmalloc_bytes(src->equiv_cpu_table_size); - if ( !mc_amd->equiv_cpu_table ) - goto err1; - mc_amd->mpb = xmalloc_bytes(src->mpb_size); - if ( !mc_amd->mpb ) - goto err2; - - mc_amd->equiv_cpu_table_size = src->equiv_cpu_table_size; - mc_amd->mpb_size = src->mpb_size; - memcpy(mc_amd->mpb, src->mpb, src->mpb_size); - memcpy(mc_amd->equiv_cpu_table, src->equiv_cpu_table, - src->equiv_cpu_table_size); - } - - return 1; - -err2: - xfree(mc_amd->equiv_cpu_table); -err1: - xfree(mc_amd); - uci->mc.mc_amd = NULL; - return -ENOMEM; -} - static int start_update(void) { #if CONFIG_HVM @@ -708,7 +633,6 @@ static int start_update(void) } static const struct microcode_ops microcode_amd_ops = { - .microcode_resume_match = microcode_resume_match, .cpu_request_microcode = cpu_request_microcode, .collect_cpu_info = collect_cpu_info, .apply_microcode = apply_microcode, diff --git a/xen/arch/x86/microcode_intel.c b/xen/arch/x86/microcode_intel.c index d3405a0..bf6497f 100644 --- a/xen/arch/x86/microcode_intel.c +++ b/xen/arch/x86/microcode_intel.c @@ -250,13 +250,13 @@ static int microcode_sanity_check(void *mc) static bool match_cpu(const struct microcode_patch *patch) { - const struct ucode_cpu_info *uci = &this_cpu(ucode_cpu_info); + const struct cpu_signature *sig = &this_cpu(cpu_sig); if ( !patch ) return false; - return microcode_update_match(&patch->mc_intel->hdr, uci->cpu_sig.sig, - uci->cpu_sig.pf, uci->cpu_sig.rev) == NEW_UCODE; + return microcode_update_match(&patch->mc_intel->hdr, + sig->sig, sig->pf, sig->rev) == NEW_UCODE; } static void free_patch(struct microcode_patch *patch) @@ -281,7 +281,6 @@ static enum microcode_match_result compare_patch( */ static int get_matching_microcode(const void *mc, unsigned int cpu) { - struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu); const struct microcode_header_intel *mc_header = mc; unsigned long total_size = get_totalsize(mc_header); void *new_mc = xmalloc_bytes(total_size); @@ -308,17 +307,7 @@ static int get_matching_microcode(const void *mc, unsigned int cpu) pr_debug("microcode: CPU%d found a matching microcode update with" " version %#x (current=%#x)\n", - cpu, mc_header->rev, uci->cpu_sig.rev); - new_mc = xmalloc_bytes(total_size); - if ( new_mc == NULL ) - { - printk(KERN_ERR "microcode: error! Can not allocate memory\n"); - return -ENOMEM; - } - - memcpy(new_mc, mc, total_size); - xfree(uci->mc.mc_intel); - uci->mc.mc_intel = new_mc; + cpu, mc_header->rev, this_cpu(cpu_sig).rev); return 1; } @@ -329,7 +318,7 @@ static int apply_microcode(unsigned int cpu) uint64_t msr_content; unsigned int val[2]; unsigned int cpu_num = raw_smp_processor_id(); - struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu_num); + struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); const struct microcode_intel *mc_intel; const struct microcode_patch *patch = microcode_get_cache(); @@ -360,16 +349,16 @@ static int apply_microcode(unsigned int cpu) { printk(KERN_ERR "microcode: CPU%d update from revision " "%#x to %#x failed. Resulting revision is %#x.\n", cpu_num, - uci->cpu_sig.rev, mc_intel->hdr.rev, val[1]); + sig->rev, mc_intel->hdr.rev, val[1]); return -EIO; } printk(KERN_INFO "microcode: CPU%d updated from revision " "%#x to %#x, date = %04x-%02x-%02x \n", - cpu_num, uci->cpu_sig.rev, val[1], + cpu_num, sig->rev, val[1], mc_intel->hdr.year, mc_intel->hdr.month, mc_intel->hdr.day); - uci->cpu_sig.rev = val[1]; + sig->rev = val[1]; return 0; } @@ -440,13 +429,7 @@ static int cpu_request_microcode(unsigned int cpu, const void *buf, return error; } -static int microcode_resume_match(unsigned int cpu, const void *mc) -{ - return get_matching_microcode(mc, cpu); -} - static const struct microcode_ops microcode_intel_ops = { - .microcode_resume_match = microcode_resume_match, .cpu_request_microcode = cpu_request_microcode, .collect_cpu_info = collect_cpu_info, .apply_microcode = apply_microcode, diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c index 5d98cac..43128c3 100644 --- a/xen/arch/x86/spec_ctrl.c +++ b/xen/arch/x86/spec_ctrl.c @@ -436,7 +436,7 @@ static bool __init check_smt_enabled(void) /* Calculate whether Retpoline is known-safe on this CPU. */ static bool __init retpoline_safe(uint64_t caps) { - unsigned int ucode_rev = this_cpu(ucode_cpu_info).cpu_sig.rev; + unsigned int ucode_rev = this_cpu(cpu_sig).rev; if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD ) return true; diff --git a/xen/include/asm-x86/microcode.h b/xen/include/asm-x86/microcode.h index 6541c58..f2ac509 100644 --- a/xen/include/asm-x86/microcode.h +++ b/xen/include/asm-x86/microcode.h @@ -10,7 +10,6 @@ enum microcode_match_result { }; struct cpu_signature; -struct ucode_cpu_info; struct microcode_patch { union { @@ -20,7 +19,6 @@ struct microcode_patch { }; struct microcode_ops { - int (*microcode_resume_match)(unsigned int cpu, const void *mc); int (*cpu_request_microcode)(unsigned int cpu, const void *buf, size_t size); int (*collect_cpu_info)(unsigned int cpu, struct cpu_signature *csig); @@ -39,16 +37,7 @@ struct cpu_signature { unsigned int rev; }; -struct ucode_cpu_info { - struct cpu_signature cpu_sig; - union { - struct microcode_intel *mc_intel; - struct microcode_amd *mc_amd; - void *mc_valid; - } mc; -}; - -DECLARE_PER_CPU(struct ucode_cpu_info, ucode_cpu_info); +DECLARE_PER_CPU(struct cpu_signature, cpu_sig); extern const struct microcode_ops *microcode_ops; const struct microcode_patch *microcode_get_cache(void); From patchwork Mon May 27 08:31:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Gao X-Patchwork-Id: 10962279 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 EFEA61390 for ; Mon, 27 May 2019 08:29:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DFE2128AAC for ; Mon, 27 May 2019 08:29:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D3B1E28AB3; Mon, 27 May 2019 08:29:08 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 114D628AAC for ; Mon, 27 May 2019 08:29:08 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyo-0004Db-Om; Mon, 27 May 2019 08:27:38 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyn-0004Cr-4l for xen-devel@lists.xenproject.org; Mon, 27 May 2019 08:27:37 +0000 X-Inumbo-ID: 479fdf4e-8059-11e9-8980-bc764e045a96 Received: from mga12.intel.com (unknown [192.55.52.136]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 479fdf4e-8059-11e9-8980-bc764e045a96; Mon, 27 May 2019 08:27:35 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 May 2019 01:27:35 -0700 X-ExtLoop1: 1 Received: from gao-cwp.sh.intel.com ([10.239.159.26]) by orsmga005.jf.intel.com with ESMTP; 27 May 2019 01:27:33 -0700 From: Chao Gao To: xen-devel@lists.xenproject.org Date: Mon, 27 May 2019 16:31:26 +0800 Message-Id: <1558945891-3015-6-git-send-email-chao.gao@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1558945891-3015-1-git-send-email-chao.gao@intel.com> References: <1558945891-3015-1-git-send-email-chao.gao@intel.com> Subject: [Xen-devel] [PATCH v7 05/10] microcode: remove pointless 'cpu' parameter X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Sergey Dyasli , Ashok Raj , Wei Liu , Andrew Cooper , Jan Beulich , Chao Gao , =?utf-8?q?R?= =?utf-8?q?oger_Pau_Monn=C3=A9?= MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Some callbacks in microcode_ops or related functions take a cpu id parameter. But at current call sites, the cpu id parameter is always equal to current cpu id. Some of them even use an assertion to guarantee this. Remove this redundent 'cpu' parameter. Signed-off-by: Chao Gao --- xen/arch/x86/acpi/power.c | 2 +- xen/arch/x86/microcode.c | 12 ++++++------ xen/arch/x86/microcode_amd.c | 35 +++++++++++++---------------------- xen/arch/x86/microcode_intel.c | 25 +++++++++---------------- xen/arch/x86/smpboot.c | 2 +- xen/include/asm-x86/microcode.h | 7 +++---- xen/include/asm-x86/processor.h | 2 +- 7 files changed, 34 insertions(+), 51 deletions(-) diff --git a/xen/arch/x86/acpi/power.c b/xen/arch/x86/acpi/power.c index aecc754..4f21903 100644 --- a/xen/arch/x86/acpi/power.c +++ b/xen/arch/x86/acpi/power.c @@ -253,7 +253,7 @@ static int enter_state(u32 state) console_end_sync(); - microcode_resume_cpu(0); + microcode_resume_cpu(); if ( !recheck_cpu_features(0) ) panic("Missing previously available feature(s)\n"); diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c index 0c01dfa..16a6d50 100644 --- a/xen/arch/x86/microcode.c +++ b/xen/arch/x86/microcode.c @@ -196,19 +196,19 @@ struct microcode_info { char buffer[1]; }; -int microcode_resume_cpu(unsigned int cpu) +int microcode_resume_cpu(void) { int err; - struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); + struct cpu_signature *sig = &this_cpu(cpu_sig); if ( !microcode_ops ) return 0; spin_lock(µcode_mutex); - err = microcode_ops->collect_cpu_info(cpu, sig); + err = microcode_ops->collect_cpu_info(sig); if ( likely(!err) ) - err = microcode_ops->apply_microcode(cpu); + err = microcode_ops->apply_microcode(); spin_unlock(µcode_mutex); return err; @@ -255,9 +255,9 @@ static int microcode_update_cpu(const void *buf, size_t size) spin_lock(µcode_mutex); - err = microcode_ops->collect_cpu_info(cpu, sig); + err = microcode_ops->collect_cpu_info(sig); if ( likely(!err) ) - err = microcode_ops->cpu_request_microcode(cpu, buf, size); + err = microcode_ops->cpu_request_microcode(buf, size); spin_unlock(µcode_mutex); return err; diff --git a/xen/arch/x86/microcode_amd.c b/xen/arch/x86/microcode_amd.c index 93af2c9..0144df1 100644 --- a/xen/arch/x86/microcode_amd.c +++ b/xen/arch/x86/microcode_amd.c @@ -78,8 +78,9 @@ struct mpbhdr { static DEFINE_SPINLOCK(microcode_update_lock); /* See comment in start_update() for cases when this routine fails */ -static int collect_cpu_info(unsigned int cpu, struct cpu_signature *csig) +static int collect_cpu_info(struct cpu_signature *csig) { + unsigned int cpu = smp_processor_id(); struct cpuinfo_x86 *c = &cpu_data[cpu]; memset(csig, 0, sizeof(*csig)); @@ -152,18 +153,15 @@ static bool_t find_equiv_cpu_id(const struct equiv_cpu_entry *equiv_cpu_table, return 0; } -static bool_t microcode_fits(const struct microcode_amd *mc_amd, - unsigned int cpu) +static bool microcode_fits(const struct microcode_amd *mc_amd) { + unsigned int cpu = smp_processor_id(); const struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); const struct microcode_header_amd *mc_header = mc_amd->mpb; const struct equiv_cpu_entry *equiv_cpu_table = mc_amd->equiv_cpu_table; unsigned int current_cpu_id; unsigned int equiv_cpu_id; - /* We should bind the task to the CPU */ - BUG_ON(cpu != raw_smp_processor_id()); - current_cpu_id = cpuid_eax(0x00000001); if ( !find_equiv_cpu_id(equiv_cpu_table, current_cpu_id, &equiv_cpu_id) ) @@ -192,9 +190,7 @@ static bool_t microcode_fits(const struct microcode_amd *mc_amd, static bool match_cpu(const struct microcode_patch *patch) { - if ( !patch ) - return false; - return microcode_fits(patch->mc_amd, smp_processor_id()); + return patch ? microcode_fits(patch->mc_amd) : false; } static struct microcode_patch *alloc_microcode_patch( @@ -253,18 +249,16 @@ static enum microcode_match_result compare_patch( return MIS_UCODE; } -static int apply_microcode(unsigned int cpu) +static int apply_microcode(void) { unsigned long flags; uint32_t rev; int hw_err; + unsigned int cpu = smp_processor_id(); struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); const struct microcode_header_amd *hdr; const struct microcode_patch *patch = microcode_get_cache(); - /* We should bind the task to the CPU */ - BUG_ON(raw_smp_processor_id() != cpu); - if ( !match_cpu(patch) ) return -EINVAL; @@ -435,14 +429,14 @@ static const unsigned int final_levels[] = { 0x010000af }; -static bool_t check_final_patch_levels(unsigned int cpu) +static bool check_final_patch_levels(void) { /* * Check the current patch levels on the cpu. If they are equal to * any of the 'final_levels', then we should not update the microcode * patch on the cpu as system will hang otherwise. */ - const struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); + const struct cpu_signature *sig = &this_cpu(cpu_sig); unsigned int i; if ( boot_cpu_data.x86 != 0x10 ) @@ -455,19 +449,16 @@ static bool_t check_final_patch_levels(unsigned int cpu) return 0; } -static int cpu_request_microcode(unsigned int cpu, const void *buf, - size_t bufsize) +static int cpu_request_microcode(const void *buf, size_t bufsize) { struct microcode_amd *mc_amd; size_t offset = 0; int error = 0; unsigned int current_cpu_id; unsigned int equiv_cpu_id; + unsigned int cpu = smp_processor_id(); const struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); - /* We should bind the task to the CPU */ - BUG_ON(cpu != raw_smp_processor_id()); - current_cpu_id = cpuid_eax(0x00000001); if ( *(const uint32_t *)buf != UCODE_MAGIC ) @@ -477,7 +468,7 @@ static int cpu_request_microcode(unsigned int cpu, const void *buf, goto out; } - if ( check_final_patch_levels(cpu) ) + if ( check_final_patch_levels() ) { printk(XENLOG_INFO "microcode: Cannot update microcode patch on the cpu as we hit a final level\n"); @@ -567,7 +558,7 @@ static int cpu_request_microcode(unsigned int cpu, const void *buf, if ( match_cpu(microcode_get_cache()) ) { - error = apply_microcode(cpu); + error = apply_microcode(); if ( error ) break; } diff --git a/xen/arch/x86/microcode_intel.c b/xen/arch/x86/microcode_intel.c index bf6497f..b66844d 100644 --- a/xen/arch/x86/microcode_intel.c +++ b/xen/arch/x86/microcode_intel.c @@ -96,13 +96,12 @@ struct extended_sigtable { /* serialize access to the physical write to MSR 0x79 */ static DEFINE_SPINLOCK(microcode_update_lock); -static int collect_cpu_info(unsigned int cpu_num, struct cpu_signature *csig) +static int collect_cpu_info(struct cpu_signature *csig) { + unsigned int cpu_num = smp_processor_id(); struct cpuinfo_x86 *c = &cpu_data[cpu_num]; uint64_t msr_content; - BUG_ON(cpu_num != smp_processor_id()); - memset(csig, 0, sizeof(*csig)); if ( (c->x86_vendor != X86_VENDOR_INTEL) || (c->x86 < 6) ) @@ -279,12 +278,13 @@ static enum microcode_match_result compare_patch( * return 1 - found update * return < 0 - error */ -static int get_matching_microcode(const void *mc, unsigned int cpu) +static int get_matching_microcode(const void *mc) { const struct microcode_header_intel *mc_header = mc; unsigned long total_size = get_totalsize(mc_header); void *new_mc = xmalloc_bytes(total_size); struct microcode_patch *new_patch = xmalloc(struct microcode_patch); + unsigned int __maybe_unused cpu = smp_processor_id(); if ( !new_patch || !new_mc ) { @@ -312,19 +312,16 @@ static int get_matching_microcode(const void *mc, unsigned int cpu) return 1; } -static int apply_microcode(unsigned int cpu) +static int apply_microcode(void) { unsigned long flags; uint64_t msr_content; unsigned int val[2]; unsigned int cpu_num = raw_smp_processor_id(); - struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); + struct cpu_signature *sig = &this_cpu(cpu_sig); const struct microcode_intel *mc_intel; const struct microcode_patch *patch = microcode_get_cache(); - /* We should bind the task to the CPU */ - BUG_ON(cpu_num != cpu); - if ( !match_cpu(patch) ) return -EINVAL; @@ -391,22 +388,18 @@ static long get_next_ucode_from_buffer(void **mc, const u8 *buf, return offset + total_size; } -static int cpu_request_microcode(unsigned int cpu, const void *buf, - size_t size) +static int cpu_request_microcode(const void *buf, size_t size) { long offset = 0; int error = 0; void *mc; - /* We should bind the task to the CPU */ - BUG_ON(cpu != raw_smp_processor_id()); - while ( (offset = get_next_ucode_from_buffer(&mc, buf, size, offset)) > 0 ) { error = microcode_sanity_check(mc); if ( error ) break; - error = get_matching_microcode(mc, cpu); + error = get_matching_microcode(mc); if ( error < 0 ) break; /* @@ -424,7 +417,7 @@ static int cpu_request_microcode(unsigned int cpu, const void *buf, error = offset; if ( !error && match_cpu(microcode_get_cache()) ) - error = apply_microcode(cpu); + error = apply_microcode(); return error; } diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 274865a..de19b67 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -366,7 +366,7 @@ void start_secondary(void *unused) if ( system_state <= SYS_STATE_smp_boot ) early_microcode_update_cpu(false); else - microcode_resume_cpu(cpu); + microcode_resume_cpu(); /* * If MSR_SPEC_CTRL is available, apply Xen's default setting and discard diff --git a/xen/include/asm-x86/microcode.h b/xen/include/asm-x86/microcode.h index f2ac509..e6842d4 100644 --- a/xen/include/asm-x86/microcode.h +++ b/xen/include/asm-x86/microcode.h @@ -19,10 +19,9 @@ struct microcode_patch { }; struct microcode_ops { - int (*cpu_request_microcode)(unsigned int cpu, const void *buf, - size_t size); - int (*collect_cpu_info)(unsigned int cpu, struct cpu_signature *csig); - int (*apply_microcode)(unsigned int cpu); + int (*cpu_request_microcode)(const void *buf, size_t size); + int (*collect_cpu_info)(struct cpu_signature *csig); + int (*apply_microcode)(void); int (*start_update)(void); void (*free_patch)(struct microcode_patch *patch); bool (*match_cpu)(const struct microcode_patch *patch); diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index cef3ffb..8b7e484 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -573,7 +573,7 @@ int guest_wrmsr_xen(struct vcpu *v, uint32_t idx, uint64_t val); void microcode_set_module(unsigned int); int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void), unsigned long len); -int microcode_resume_cpu(unsigned int cpu); +int microcode_resume_cpu(void); int early_microcode_update_cpu(bool start_update); int early_microcode_init(void); int microcode_init_intel(void); From patchwork Mon May 27 08:31:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Gao X-Patchwork-Id: 10962287 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 C9C7E16C1 for ; Mon, 27 May 2019 08:29:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B91B528AB0 for ; Mon, 27 May 2019 08:29:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AA4A628AB7; Mon, 27 May 2019 08:29:37 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 8CC7A28AB0 for ; Mon, 27 May 2019 08:29:36 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyr-0004FH-Ad; Mon, 27 May 2019 08:27:41 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyp-0004El-Vl for xen-devel@lists.xenproject.org; Mon, 27 May 2019 08:27:40 +0000 X-Inumbo-ID: 493a4e8e-8059-11e9-8980-bc764e045a96 Received: from mga12.intel.com (unknown [192.55.52.136]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 493a4e8e-8059-11e9-8980-bc764e045a96; Mon, 27 May 2019 08:27:38 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 May 2019 01:27:37 -0700 X-ExtLoop1: 1 Received: from gao-cwp.sh.intel.com ([10.239.159.26]) by orsmga005.jf.intel.com with ESMTP; 27 May 2019 01:27:35 -0700 From: Chao Gao To: xen-devel@lists.xenproject.org Date: Mon, 27 May 2019 16:31:27 +0800 Message-Id: <1558945891-3015-7-git-send-email-chao.gao@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1558945891-3015-1-git-send-email-chao.gao@intel.com> References: <1558945891-3015-1-git-send-email-chao.gao@intel.com> Subject: [Xen-devel] [PATCH v7 06/10] microcode: split out apply_microcode() from cpu_request_microcode() X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Sergey Dyasli , Ashok Raj , Wei Liu , Andrew Cooper , Jan Beulich , Chao Gao , =?utf-8?q?R?= =?utf-8?q?oger_Pau_Monn=C3=A9?= MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP During late microcode update, apply_microcode() is invoked in cpu_request_microcode(). To make late microcode update more reliable, we want to put the apply_microcode() into stop_machine context. So we split out it from cpu_request_microcode(). As a consequence, apply_microcode() should be invoked explicitly in the common code. Previously, apply_microcode() gets the microcode patch to be applied from the microcode cache. Now, the patch is passed as a function argument and a patch is cached for cpu-hotplug and cpu resuming, only after it has been loaded to a cpu without any error. As a consequence, the 'match_cpu' check in microcode_update_cache is removed, which otherwise would fail. Assuming that all CPUs have the same signature, one patch matching with current CPU should match with others. Then parsing microcode only needs to be done once; cpu_request_microcode() is also moved out of microcode_update_cpu(). On AMD side, svm_host_osvw_init() is supposed to be called after microcode update. As apply_micrcode() won't be called by cpu_request_microcode() now, svm_host_osvw_init() is moved to the end of apply_microcode(). Signed-off-by: Chao Gao --- Changes in v7: - to handle load failure, unvalidated patches won't be cached. They are passed as function arguments. So if update failed, we needn't any cleanup to microcode cache. - microcode_info which passes microcode blob to be parsed to each CPU is replaced by microcode_patch. Changes in v6: - during early microcode update, BSP and APs call different functions. Thus AP can bypass parsing microcode blob. --- xen/arch/x86/acpi/power.c | 2 +- xen/arch/x86/microcode.c | 209 ++++++++++++++++++++++++++-------------- xen/arch/x86/microcode_amd.c | 41 ++++---- xen/arch/x86/microcode_intel.c | 69 ++++++------- xen/arch/x86/smpboot.c | 5 +- xen/include/asm-x86/microcode.h | 8 +- xen/include/asm-x86/processor.h | 3 +- 7 files changed, 193 insertions(+), 144 deletions(-) diff --git a/xen/arch/x86/acpi/power.c b/xen/arch/x86/acpi/power.c index 4f21903..9583172 100644 --- a/xen/arch/x86/acpi/power.c +++ b/xen/arch/x86/acpi/power.c @@ -253,7 +253,7 @@ static int enter_state(u32 state) console_end_sync(); - microcode_resume_cpu(); + early_microcode_update_cpu(); if ( !recheck_cpu_features(0) ) panic("Missing previously available feature(s)\n"); diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c index 16a6d50..23cf550 100644 --- a/xen/arch/x86/microcode.c +++ b/xen/arch/x86/microcode.c @@ -189,36 +189,62 @@ static DEFINE_SPINLOCK(microcode_mutex); DEFINE_PER_CPU(struct cpu_signature, cpu_sig); -struct microcode_info { - unsigned int cpu; - uint32_t buffer_size; - int error; - char buffer[1]; -}; +/* + * Return the patch with the highest revision id among all matching + * patches in the blob. Return NULL if no suitable patch. + */ +static struct microcode_patch *microcode_parse_blob(const char *buf, + uint32_t len) +{ + if ( likely(!microcode_ops->collect_cpu_info(&this_cpu(cpu_sig))) ) + return microcode_ops->cpu_request_microcode(buf, len); -int microcode_resume_cpu(void) + return NULL; +} + +/* + * Load a microcode update to current CPU. + * + * If no patch is provided, the cached patch will be loaded. Microcode update + * during APs bringup and CPU resuming falls into this case. + */ +static int microcode_update_cpu(struct microcode_patch *patch) { - int err; - struct cpu_signature *sig = &this_cpu(cpu_sig); + int ret = microcode_ops->collect_cpu_info(&this_cpu(cpu_sig)); - if ( !microcode_ops ) - return 0; + if ( unlikely(ret) ) + return ret; spin_lock(µcode_mutex); - err = microcode_ops->collect_cpu_info(sig); - if ( likely(!err) ) - err = microcode_ops->apply_microcode(); - spin_unlock(µcode_mutex); + if ( patch ) + { + /* + * If a patch is specified, it should has newer revision than + * that of the patch cached. + */ + if ( microcode_cache && + microcode_ops->compare_patch(patch, microcode_cache) != NEW_UCODE ) + { + spin_unlock(µcode_mutex); + return -EINVAL; + } - return err; -} + ret = microcode_ops->apply_microcode(patch); + } + else if ( microcode_cache ) + { + ret = microcode_ops->apply_microcode(microcode_cache); + if ( ret == -EIO ) + printk("Update failed. Reboot needed\n"); + } + else + /* No patch to update */ + ret = -EINVAL; -const struct microcode_patch *microcode_get_cache(void) -{ - ASSERT(spin_is_locked(µcode_mutex)); + spin_unlock(µcode_mutex); - return microcode_cache; + return ret; } /* Return true if cache gets updated. Otherwise, return false */ @@ -227,9 +253,6 @@ bool microcode_update_cache(struct microcode_patch *patch) ASSERT(spin_is_locked(µcode_mutex)); - if ( !microcode_ops->match_cpu(patch) ) - return false; - if ( !microcode_cache ) microcode_cache = patch; else if ( microcode_ops->compare_patch(patch, microcode_cache) == @@ -247,46 +270,32 @@ bool microcode_update_cache(struct microcode_patch *patch) return true; } -static int microcode_update_cpu(const void *buf, size_t size) +static long do_microcode_update(void *patch) { - int err; - unsigned int cpu = smp_processor_id(); - struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); - - spin_lock(µcode_mutex); + int error, cpu; - err = microcode_ops->collect_cpu_info(sig); - if ( likely(!err) ) - err = microcode_ops->cpu_request_microcode(buf, size); - spin_unlock(µcode_mutex); - - return err; -} - -static long do_microcode_update(void *_info) -{ - struct microcode_info *info = _info; - int error; + error = microcode_update_cpu(patch); + if ( error ) + { + microcode_ops->free_patch(microcode_cache); + return error; + } - BUG_ON(info->cpu != smp_processor_id()); - error = microcode_update_cpu(info->buffer, info->buffer_size); - if ( error ) - info->error = error; + cpu = cpumask_next(smp_processor_id(), &cpu_online_map); + if ( cpu < nr_cpu_ids ) + return continue_hypercall_on_cpu(cpu, do_microcode_update, patch); - info->cpu = cpumask_next(info->cpu, &cpu_online_map); - if ( info->cpu < nr_cpu_ids ) - return continue_hypercall_on_cpu(info->cpu, do_microcode_update, info); + microcode_update_cache(patch); - error = info->error; - xfree(info); return error; } int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void) buf, unsigned long len) { int ret; - struct microcode_info *info; + void *buffer; + struct microcode_patch *patch; if ( len != (uint32_t)len ) return -E2BIG; @@ -294,32 +303,49 @@ int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void) buf, unsigned long len) if ( microcode_ops == NULL ) return -EINVAL; - info = xmalloc_bytes(sizeof(*info) + len); - if ( info == NULL ) - return -ENOMEM; - - ret = copy_from_guest(info->buffer, buf, len); - if ( ret != 0 ) + buffer = xmalloc_bytes(len); + if ( !buffer ) { - xfree(info); - return ret; + ret = -ENOMEM; + goto free; } - info->buffer_size = len; - info->error = 0; - info->cpu = cpumask_first(&cpu_online_map); + if ( copy_from_guest(buffer, buf, len) ) + { + ret = -EFAULT; + goto free; + } if ( microcode_ops->start_update ) { ret = microcode_ops->start_update(); if ( ret != 0 ) - { - xfree(info); - return ret; - } + goto free; } - return continue_hypercall_on_cpu(info->cpu, do_microcode_update, info); + patch = microcode_parse_blob(buffer, len); + if ( IS_ERR(patch) ) + { + printk(XENLOG_ERR "Parsing microcode blob error %ld\n", PTR_ERR(patch)); + ret = PTR_ERR(patch); + goto free; + } + + if ( !microcode_ops->match_cpu(patch) ) + { + printk(XENLOG_ERR "No matching or newer ucode found. Update aborted!\n"); + if ( patch ) + microcode_ops->free_patch(patch); + ret = -EINVAL; + goto free; + } + + ret = continue_hypercall_on_cpu(cpumask_first(&cpu_online_map), + do_microcode_update, patch); + + free: + xfree(buffer); + return ret; } static int __init microcode_init(void) @@ -344,7 +370,16 @@ static int __init microcode_init(void) } __initcall(microcode_init); -int __init early_microcode_update_cpu(bool start_update) +int early_microcode_update_cpu(void) +{ + return microcode_ops ? microcode_update_cpu(NULL) : 0; +} + +/* + * BSP needs to parse the ucode blob and then apply an update. + * APs just apply an update by calling early_microcode_update_cpu(). + */ +static int __init early_microcode_parse_and_update_cpu(void) { int rc = 0; void *data = NULL; @@ -362,13 +397,41 @@ int __init early_microcode_update_cpu(bool start_update) } if ( data ) { - if ( start_update && microcode_ops->start_update ) + struct microcode_patch *patch; + + if ( microcode_ops->start_update ) rc = microcode_ops->start_update(); if ( rc ) return rc; - return microcode_update_cpu(data, len); + patch = microcode_parse_blob(data, len); + if ( IS_ERR(patch) ) + { + printk(XENLOG_ERR "Parsing microcode blob error %ld\n", + PTR_ERR(patch)); + return PTR_ERR(patch); + } + + if ( !microcode_ops->match_cpu(patch) ) + { + printk(XENLOG_ERR "No matching or newer ucode found. Update aborted!\n"); + if ( patch ) + microcode_ops->free_patch(patch); + return -EINVAL; + } + + rc = microcode_update_cpu(patch); + if ( !rc ) + { + spin_lock(µcode_mutex); + microcode_update_cache(patch); + spin_unlock(µcode_mutex); + } + else + microcode_ops->free_patch(patch); + + return rc; } else return -ENOMEM; @@ -387,8 +450,10 @@ int __init early_microcode_init(void) return rc; if ( microcode_ops ) + { if ( ucode_mod.mod_end || ucode_blob.size ) - rc = early_microcode_update_cpu(true); + rc = early_microcode_parse_and_update_cpu(); + } return rc; } diff --git a/xen/arch/x86/microcode_amd.c b/xen/arch/x86/microcode_amd.c index 0144df1..c819028 100644 --- a/xen/arch/x86/microcode_amd.c +++ b/xen/arch/x86/microcode_amd.c @@ -249,7 +249,7 @@ static enum microcode_match_result compare_patch( return MIS_UCODE; } -static int apply_microcode(void) +static int apply_microcode(const struct microcode_patch *patch) { unsigned long flags; uint32_t rev; @@ -257,7 +257,6 @@ static int apply_microcode(void) unsigned int cpu = smp_processor_id(); struct cpu_signature *sig = &per_cpu(cpu_sig, cpu); const struct microcode_header_amd *hdr; - const struct microcode_patch *patch = microcode_get_cache(); if ( !match_cpu(patch) ) return -EINVAL; @@ -292,6 +291,10 @@ static int apply_microcode(void) sig->rev = rev; +#ifdef CONFIG_HVM + svm_host_osvw_init(); +#endif + return 0; } @@ -449,9 +452,11 @@ static bool check_final_patch_levels(void) return 0; } -static int cpu_request_microcode(const void *buf, size_t bufsize) +static struct microcode_patch *cpu_request_microcode(const void *buf, + size_t bufsize) { struct microcode_amd *mc_amd; + struct microcode_patch *patch = NULL; size_t offset = 0; int error = 0; unsigned int current_cpu_id; @@ -551,17 +556,16 @@ static int cpu_request_microcode(const void *buf, size_t bufsize) break; } - if ( match_cpu(new_patch) ) - microcode_update_cache(new_patch); - else - free_patch(new_patch); - - if ( match_cpu(microcode_get_cache()) ) + /* Compare patches and store the one with higher revision */ + if ( !patch && match_cpu(new_patch) ) + patch = new_patch; + else if ( patch && (compare_patch(new_patch, patch) == NEW_UCODE) ) { - error = apply_microcode(); - if ( error ) - break; + free_patch(patch); + patch = new_patch; } + else + free_patch(new_patch); if ( offset >= bufsize ) break; @@ -592,17 +596,10 @@ static int cpu_request_microcode(const void *buf, size_t bufsize) } out: -#if CONFIG_HVM - svm_host_osvw_init(); -#endif + if ( error && !patch ) + patch = ERR_PTR(error); - /* - * In some cases we may return an error even if processor's microcode has - * been updated. For example, the first patch in a container file is loaded - * successfully but subsequent container file processing encounters a - * failure. - */ - return error; + return patch; } static int start_update(void) diff --git a/xen/arch/x86/microcode_intel.c b/xen/arch/x86/microcode_intel.c index b66844d..650495d 100644 --- a/xen/arch/x86/microcode_intel.c +++ b/xen/arch/x86/microcode_intel.c @@ -273,46 +273,27 @@ static enum microcode_match_result compare_patch( old_header->pf, old_header->rev); } -/* - * return 0 - no update found - * return 1 - found update - * return < 0 - error - */ -static int get_matching_microcode(const void *mc) +static struct microcode_patch *allow_microcode_patch( + const struct microcode_header_intel *mc_header) { - const struct microcode_header_intel *mc_header = mc; unsigned long total_size = get_totalsize(mc_header); void *new_mc = xmalloc_bytes(total_size); struct microcode_patch *new_patch = xmalloc(struct microcode_patch); - unsigned int __maybe_unused cpu = smp_processor_id(); if ( !new_patch || !new_mc ) { xfree(new_patch); xfree(new_mc); printk(XENLOG_ERR "microcode: Can not allocate memory\n"); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } - memcpy(new_mc, mc, total_size); + memcpy(new_mc, mc_header, total_size); new_patch->mc_intel = new_mc; - if ( !match_cpu(new_patch) ) - { - free_patch(new_patch); - return 0; - } - - if ( !microcode_update_cache(new_patch) ) - return 0; - - pr_debug("microcode: CPU%d found a matching microcode update with" - " version %#x (current=%#x)\n", - cpu, mc_header->rev, this_cpu(cpu_sig).rev); - - return 1; + return new_patch; } -static int apply_microcode(void) +static int apply_microcode(const struct microcode_patch *patch) { unsigned long flags; uint64_t msr_content; @@ -320,7 +301,6 @@ static int apply_microcode(void) unsigned int cpu_num = raw_smp_processor_id(); struct cpu_signature *sig = &this_cpu(cpu_sig); const struct microcode_intel *mc_intel; - const struct microcode_patch *patch = microcode_get_cache(); if ( !match_cpu(patch) ) return -EINVAL; @@ -388,26 +368,39 @@ static long get_next_ucode_from_buffer(void **mc, const u8 *buf, return offset + total_size; } -static int cpu_request_microcode(const void *buf, size_t size) +static struct microcode_patch *cpu_request_microcode(const void *buf, + size_t size) { long offset = 0; int error = 0; void *mc; + struct microcode_patch *patch = NULL; while ( (offset = get_next_ucode_from_buffer(&mc, buf, size, offset)) > 0 ) { + struct microcode_patch *new_patch; + error = microcode_sanity_check(mc); if ( error ) break; - error = get_matching_microcode(mc); - if ( error < 0 ) + + new_patch = allow_microcode_patch(mc); + if ( IS_ERR(new_patch) ) + { + error = PTR_ERR(new_patch); break; - /* - * It's possible the data file has multiple matching ucode, - * lets keep searching till the latest version - */ - if ( error == 1 ) - error = 0; + } + + /* Compare patches and store the one with higher revision */ + if ( !patch && match_cpu(new_patch) ) + patch = new_patch; + else if ( patch && (compare_patch(new_patch, patch) == NEW_UCODE) ) + { + free_patch(patch); + patch = new_patch; + } + else + free_patch(new_patch); xfree(mc); } @@ -416,10 +409,10 @@ static int cpu_request_microcode(const void *buf, size_t size) if ( offset < 0 ) error = offset; - if ( !error && match_cpu(microcode_get_cache()) ) - error = apply_microcode(); + if ( error && !patch ) + patch = ERR_PTR(error); - return error; + return patch; } static const struct microcode_ops microcode_intel_ops = { diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index de19b67..cd5f9cc 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -363,10 +363,7 @@ void start_secondary(void *unused) initialize_cpu_data(cpu); - if ( system_state <= SYS_STATE_smp_boot ) - early_microcode_update_cpu(false); - else - microcode_resume_cpu(); + early_microcode_update_cpu(); /* * If MSR_SPEC_CTRL is available, apply Xen's default setting and discard diff --git a/xen/include/asm-x86/microcode.h b/xen/include/asm-x86/microcode.h index e6842d4..3fa3acd 100644 --- a/xen/include/asm-x86/microcode.h +++ b/xen/include/asm-x86/microcode.h @@ -19,9 +19,10 @@ struct microcode_patch { }; struct microcode_ops { - int (*cpu_request_microcode)(const void *buf, size_t size); + struct microcode_patch *(*cpu_request_microcode)(const void *buf, + size_t size); int (*collect_cpu_info)(struct cpu_signature *csig); - int (*apply_microcode)(void); + int (*apply_microcode)(const struct microcode_patch *patch); int (*start_update)(void); void (*free_patch)(struct microcode_patch *patch); bool (*match_cpu)(const struct microcode_patch *patch); @@ -39,7 +40,4 @@ struct cpu_signature { DECLARE_PER_CPU(struct cpu_signature, cpu_sig); extern const struct microcode_ops *microcode_ops; -const struct microcode_patch *microcode_get_cache(void); -bool microcode_update_cache(struct microcode_patch *patch); - #endif /* ASM_X86__MICROCODE_H */ diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index 8b7e484..d8668e6 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -573,8 +573,7 @@ int guest_wrmsr_xen(struct vcpu *v, uint32_t idx, uint64_t val); void microcode_set_module(unsigned int); int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void), unsigned long len); -int microcode_resume_cpu(void); -int early_microcode_update_cpu(bool start_update); +int early_microcode_update_cpu(void); int early_microcode_init(void); int microcode_init_intel(void); int microcode_init_amd(void); From patchwork Mon May 27 08:31:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Gao X-Patchwork-Id: 10962277 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 BA97091E for ; Mon, 27 May 2019 08:29:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ACDE328AAC for ; Mon, 27 May 2019 08:29:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A12B228AB3; Mon, 27 May 2019 08:29:07 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 53C5D28AAC for ; Mon, 27 May 2019 08:29:07 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAys-0004GI-LP; Mon, 27 May 2019 08:27:42 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyr-0004FG-F9 for xen-devel@lists.xenproject.org; Mon, 27 May 2019 08:27:41 +0000 X-Inumbo-ID: 4a960c5d-8059-11e9-8980-bc764e045a96 Received: from mga12.intel.com (unknown [192.55.52.136]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 4a960c5d-8059-11e9-8980-bc764e045a96; Mon, 27 May 2019 08:27:40 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 May 2019 01:27:40 -0700 X-ExtLoop1: 1 Received: from gao-cwp.sh.intel.com ([10.239.159.26]) by orsmga005.jf.intel.com with ESMTP; 27 May 2019 01:27:38 -0700 From: Chao Gao To: xen-devel@lists.xenproject.org Date: Mon, 27 May 2019 16:31:28 +0800 Message-Id: <1558945891-3015-8-git-send-email-chao.gao@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1558945891-3015-1-git-send-email-chao.gao@intel.com> References: <1558945891-3015-1-git-send-email-chao.gao@intel.com> Subject: [Xen-devel] [PATCH v7 07/10] microcode/intel: Writeback and invalidate caches before updating microcode X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Sergey Dyasli , Ashok Raj , Wei Liu , Andrew Cooper , Jan Beulich , Chao Gao , =?utf-8?q?R?= =?utf-8?q?oger_Pau_Monn=C3=A9?= MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Updating microcode is less error prone when caches have been flushed and depending on what exactly the microcode is updating. For example, some of the issues around certain Broadwell parts can be addressed by doing a full cache flush. With parallel microcode update, the cost of this patch is hardly noticable. Although only BDX with an old microcode needs this fix, we would like to avoid future issues in case they come by later due to other reasons. [linux commit: 91df9fdf51492aec9fed6b4cbd33160886740f47] Signed-off-by: Chao Gao Cc: Ashok Raj --- Changes in v7: - explain why we do 'wbinvd' unconditionally rather than only for BDX in commit message Changes in v6: - new --- xen/arch/x86/microcode_intel.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xen/arch/x86/microcode_intel.c b/xen/arch/x86/microcode_intel.c index 650495d..bfb48ce 100644 --- a/xen/arch/x86/microcode_intel.c +++ b/xen/arch/x86/microcode_intel.c @@ -310,6 +310,12 @@ static int apply_microcode(const struct microcode_patch *patch) /* serialize access to the physical write to MSR 0x79 */ spin_lock_irqsave(µcode_update_lock, flags); + /* + * Writeback and invalidate caches before updating microcode to avoid + * internal issues depending on what the microcode is updating. + */ + wbinvd(); + /* write microcode via MSR 0x79 */ wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc_intel->bits); wrmsrl(MSR_IA32_UCODE_REV, 0x0ULL); From patchwork Mon May 27 08:31:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Gao X-Patchwork-Id: 10962291 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 6CEEC91E for ; Mon, 27 May 2019 08:29:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5E50D28AAC for ; Mon, 27 May 2019 08:29:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5251328AB3; Mon, 27 May 2019 08:29:43 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 91F2428AAC for ; Mon, 27 May 2019 08:29:42 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyw-0004IW-0A; Mon, 27 May 2019 08:27:46 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyu-0004Hg-Oo for xen-devel@lists.xenproject.org; Mon, 27 May 2019 08:27:44 +0000 X-Inumbo-ID: 4c7b69c6-8059-11e9-8980-bc764e045a96 Received: from mga12.intel.com (unknown [192.55.52.136]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 4c7b69c6-8059-11e9-8980-bc764e045a96; Mon, 27 May 2019 08:27:43 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 May 2019 01:27:43 -0700 X-ExtLoop1: 1 Received: from gao-cwp.sh.intel.com ([10.239.159.26]) by orsmga005.jf.intel.com with ESMTP; 27 May 2019 01:27:40 -0700 From: Chao Gao To: xen-devel@lists.xenproject.org Date: Mon, 27 May 2019 16:31:29 +0800 Message-Id: <1558945891-3015-9-git-send-email-chao.gao@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1558945891-3015-1-git-send-email-chao.gao@intel.com> References: <1558945891-3015-1-git-send-email-chao.gao@intel.com> Subject: [Xen-devel] [PATCH v7 08/10] x86/microcode: Synchronize late microcode loading X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Sergey Dyasli , Kevin Tian , Borislav Petkov , Ashok Raj , Wei Liu , Jun Nakajima , Andrew Cooper , Jan Beulich , Thomas Gleixner , Chao Gao , =?utf-8?q?Roger_Pau_Monn=C3=A9?= MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP This patch ports microcode improvement patches from linux kernel. Before you read any further: the early loading method is still the preferred one and you should always do that. The following patch is improving the late loading mechanism for long running jobs and cloud use cases. Gather all cores and serialize the microcode update on them by doing it one-by-one to make the late update process as reliable as possible and avoid potential issues caused by the microcode update. Signed-off-by: Chao Gao Tested-by: Chao Gao [linux commit: a5321aec6412b20b5ad15db2d6b916c05349dbff] [linux commit: bb8c13d61a629276a162c1d2b1a20a815cbcfbb7] Cc: Kevin Tian Cc: Jun Nakajima Cc: Ashok Raj Cc: Borislav Petkov Cc: Thomas Gleixner Cc: Andrew Cooper Cc: Jan Beulich --- Changes in v7: - Check whether 'timeout' is 0 rather than "<=0" since it is unsigned int. - reword the comment above microcode_update_cpu() to clearly state that one thread per core should do the update. Changes in v6: - Use one timeout period for rendezvous stage and another for update stage. - scale time to wait by the number of remaining cpus to respond. It helps to find something wrong earlier and thus we can reboot the system earlier. --- xen/arch/x86/microcode.c | 171 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 155 insertions(+), 16 deletions(-) diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c index 23cf550..f4a417e 100644 --- a/xen/arch/x86/microcode.c +++ b/xen/arch/x86/microcode.c @@ -22,6 +22,7 @@ */ #include +#include #include #include #include @@ -30,15 +31,34 @@ #include #include #include +#include #include #include #include +#include +#include #include #include #include #include +/* + * Before performing a late microcode update on any thread, we + * rendezvous all cpus in stop_machine context. The timeout for + * waiting for cpu rendezvous is 30ms. It is the timeout used by + * live patching + */ +#define MICROCODE_CALLIN_TIMEOUT_US 30000 + +/* + * Timeout for each thread to complete update is set to 1s. It is a + * conservative choice considering all possible interference (for + * instance, sometimes wbinvd takes relative long time). And a perfect + * timeout doesn't help a lot except an early shutdown. + */ +#define MICROCODE_UPDATE_TIMEOUT_US 1000000 + static module_t __initdata ucode_mod; static signed int __initdata ucode_mod_idx; static bool_t __initdata ucode_mod_forced; @@ -190,6 +210,12 @@ static DEFINE_SPINLOCK(microcode_mutex); DEFINE_PER_CPU(struct cpu_signature, cpu_sig); /* + * Count the CPUs that have entered, exited the rendezvous and succeeded in + * microcode update during late microcode update respectively. + */ +static atomic_t cpu_in, cpu_out, cpu_updated; + +/* * Return the patch with the highest revision id among all matching * patches in the blob. Return NULL if no suitable patch. */ @@ -270,31 +296,90 @@ bool microcode_update_cache(struct microcode_patch *patch) return true; } -static long do_microcode_update(void *patch) +/* Wait for CPUs to rendezvous with a timeout (us) */ +static int wait_for_cpus(atomic_t *cnt, unsigned int expect, + unsigned int timeout) { - int error, cpu; - - error = microcode_update_cpu(patch); - if ( error ) + while ( atomic_read(cnt) < expect ) { - microcode_ops->free_patch(microcode_cache); - return error; + if ( !timeout ) + { + printk("CPU%d: Timeout when waiting for CPUs calling in\n", + smp_processor_id()); + return -EBUSY; + } + udelay(1); + timeout--; } + return 0; +} - cpu = cpumask_next(smp_processor_id(), &cpu_online_map); - if ( cpu < nr_cpu_ids ) - return continue_hypercall_on_cpu(cpu, do_microcode_update, patch); +static int do_microcode_update(void *patch) +{ + unsigned int cpu = smp_processor_id(); + unsigned int cpu_nr = num_online_cpus(); + unsigned int finished; + int ret; + static bool error; - microcode_update_cache(patch); + atomic_inc(&cpu_in); + ret = wait_for_cpus(&cpu_in, cpu_nr, MICROCODE_CALLIN_TIMEOUT_US); + if ( ret ) + return ret; - return error; + ret = microcode_ops->collect_cpu_info(&this_cpu(cpu_sig)); + /* + * Load microcode update on only one logical processor per core. + * Here, among logical processors of a core, the one with the + * lowest thread id is chosen to perform the loading. + */ + if ( !ret && (cpu == cpumask_first(per_cpu(cpu_sibling_mask, cpu))) ) + { + ret = microcode_ops->apply_microcode(patch); + if ( !ret ) + atomic_inc(&cpu_updated); + } + /* + * Increase the wait timeout to a safe value here since we're serializing + * the microcode update and that could take a while on a large number of + * CPUs. And that is fine as the *actual* timeout will be determined by + * the last CPU finished updating and thus cut short + */ + atomic_inc(&cpu_out); + finished = atomic_read(&cpu_out); + while ( !error && finished != cpu_nr ) + { + /* + * During each timeout interval, at least a CPU is expected to + * finish its update. Otherwise, something goes wrong. + */ + if ( wait_for_cpus(&cpu_out, finished + 1, + MICROCODE_UPDATE_TIMEOUT_US) && !error ) + { + error = true; + panic("Timeout when finishing updating microcode (finished %d/%d)", + finished, cpu_nr); + } + + finished = atomic_read(&cpu_out); + } + + /* + * Refresh CPU signature (revision) on threads which didn't call + * apply_microcode(). + */ + if ( cpu != cpumask_first(per_cpu(cpu_sibling_mask, cpu)) ) + ret = microcode_ops->collect_cpu_info(&this_cpu(cpu_sig)); + + return ret; } int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void) buf, unsigned long len) { int ret; void *buffer; + unsigned int cpu, nr_cores; struct microcode_patch *patch; if ( len != (uint32_t)len ) @@ -316,11 +401,18 @@ int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void) buf, unsigned long len) goto free; } + /* cpu_online_map must not change during update */ + if ( !get_cpu_maps() ) + { + ret = -EBUSY; + goto free; + } + if ( microcode_ops->start_update ) { ret = microcode_ops->start_update(); if ( ret != 0 ) - goto free; + goto put; } patch = microcode_parse_blob(buffer, len); @@ -337,12 +429,59 @@ int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void) buf, unsigned long len) if ( patch ) microcode_ops->free_patch(patch); ret = -EINVAL; - goto free; + goto put; } - ret = continue_hypercall_on_cpu(cpumask_first(&cpu_online_map), - do_microcode_update, patch); + atomic_set(&cpu_in, 0); + atomic_set(&cpu_out, 0); + atomic_set(&cpu_updated, 0); + + /* Calculate the number of online CPU core */ + nr_cores = 0; + for_each_online_cpu(cpu) + if ( cpu == cpumask_first(per_cpu(cpu_sibling_mask, cpu)) ) + nr_cores++; + + printk(XENLOG_INFO "%d cores are to update their microcode\n", nr_cores); + + /* + * We intend to disable interrupt for long time, which may lead to + * watchdog timeout. + */ + watchdog_disable(); + /* + * Late loading dance. Why the heavy-handed stop_machine effort? + * + * - HT siblings must be idle and not execute other code while the other + * sibling is loading microcode in order to avoid any negative + * interactions cause by the loading. + * + * - In addition, microcode update on the cores must be serialized until + * this requirement can be relaxed in the future. Right now, this is + * conservative and good. + */ + ret = stop_machine_run(do_microcode_update, patch, NR_CPUS); + watchdog_enable(); + + if ( atomic_read(&cpu_updated) == nr_cores ) + { + spin_lock(µcode_mutex); + microcode_update_cache(patch); + spin_unlock(µcode_mutex); + } + else if ( atomic_read(&cpu_updated) == 0 ) + microcode_ops->free_patch(patch); + else + { + printk("Updating microcode succeeded on part of CPUs and failed on\n" + "others due to an unknown reason. A system with different\n" + "microcode revisions is considered unstable. Please reboot and\n" + "do not load the microcode that triggers this warning\n"); + microcode_ops->free_patch(patch); + } + put: + put_cpu_maps(); free: xfree(buffer); return ret; From patchwork Mon May 27 08:31:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Gao X-Patchwork-Id: 10962281 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 81DE41390 for ; Mon, 27 May 2019 08:29:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 70BBD28AAC for ; Mon, 27 May 2019 08:29:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5F89228AB3; Mon, 27 May 2019 08:29:15 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D7A1B28AAC for ; Mon, 27 May 2019 08:29:14 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyy-0004LQ-Ky; Mon, 27 May 2019 08:27:48 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyx-0004K7-Da for xen-devel@lists.xenproject.org; Mon, 27 May 2019 08:27:47 +0000 X-Inumbo-ID: 4deb591e-8059-11e9-8980-bc764e045a96 Received: from mga12.intel.com (unknown [192.55.52.136]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 4deb591e-8059-11e9-8980-bc764e045a96; Mon, 27 May 2019 08:27:46 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 May 2019 01:27:45 -0700 X-ExtLoop1: 1 Received: from gao-cwp.sh.intel.com ([10.239.159.26]) by orsmga005.jf.intel.com with ESMTP; 27 May 2019 01:27:44 -0700 From: Chao Gao To: xen-devel@lists.xenproject.org Date: Mon, 27 May 2019 16:31:30 +0800 Message-Id: <1558945891-3015-10-git-send-email-chao.gao@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1558945891-3015-1-git-send-email-chao.gao@intel.com> References: <1558945891-3015-1-git-send-email-chao.gao@intel.com> Subject: [Xen-devel] [PATCH v7 09/10] microcode: remove microcode_update_lock X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Sergey Dyasli , Ashok Raj , Wei Liu , Andrew Cooper , Jan Beulich , Chao Gao , =?utf-8?q?R?= =?utf-8?q?oger_Pau_Monn=C3=A9?= MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP microcode_update_lock is to prevent logic threads of a same core from updating microcode at the same time. But due to using a global lock, it also prevented parallel microcode updating on different cores. Remove this lock in order to update microcode in parallel. It is safe because we have already ensured serialization of sibling threads at the caller side. 1.For late microcode update, do_microcode_update() ensures that only one sibiling thread of a core can update microcode. 2.For microcode update during system startup or CPU-hotplug, microcode_mutex() guarantees update serialization of logical threads. 3.get/put_cpu_bitmaps() prevents the concurrency of CPU-hotplug and late microcode update. Note that printk in apply_microcode() and svm_host_osvm_init() (for AMD only) are still processed sequentially. Signed-off-by: Chao Gao Reviewed-by: Jan Beulich --- Changes in v7: - reworked. Remove complex lock logics introduced in v5 and v6. The microcode patch to be applied is passed as an argument without any global variable. Thus no lock is added to serialize potential readers/writers. Callers of apply_microcode() will guarantee the correctness: the patch poninted by the arguments won't be changed by others. Changes in v6: - introduce early_ucode_update_lock to serialize early ucode update. Changes in v5: - newly add --- xen/arch/x86/microcode_amd.c | 8 +------- xen/arch/x86/microcode_intel.c | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/xen/arch/x86/microcode_amd.c b/xen/arch/x86/microcode_amd.c index c819028..b64a58d 100644 --- a/xen/arch/x86/microcode_amd.c +++ b/xen/arch/x86/microcode_amd.c @@ -74,9 +74,6 @@ struct mpbhdr { uint8_t data[]; }; -/* serialize access to the physical write */ -static DEFINE_SPINLOCK(microcode_update_lock); - /* See comment in start_update() for cases when this routine fails */ static int collect_cpu_info(struct cpu_signature *csig) { @@ -251,7 +248,6 @@ static enum microcode_match_result compare_patch( static int apply_microcode(const struct microcode_patch *patch) { - unsigned long flags; uint32_t rev; int hw_err; unsigned int cpu = smp_processor_id(); @@ -263,15 +259,13 @@ static int apply_microcode(const struct microcode_patch *patch) hdr = patch->mc_amd->mpb; - spin_lock_irqsave(µcode_update_lock, flags); + BUG_ON(local_irq_is_enabled()); hw_err = wrmsr_safe(MSR_AMD_PATCHLOADER, (unsigned long)hdr); /* get patch id after patching */ rdmsrl(MSR_AMD_PATCHLEVEL, rev); - spin_unlock_irqrestore(µcode_update_lock, flags); - /* * Some processors leave the ucode blob mapping as UC after the update. * Flush the mapping to regain normal cacheability. diff --git a/xen/arch/x86/microcode_intel.c b/xen/arch/x86/microcode_intel.c index bfb48ce..94a1561 100644 --- a/xen/arch/x86/microcode_intel.c +++ b/xen/arch/x86/microcode_intel.c @@ -93,9 +93,6 @@ struct extended_sigtable { #define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE) -/* serialize access to the physical write to MSR 0x79 */ -static DEFINE_SPINLOCK(microcode_update_lock); - static int collect_cpu_info(struct cpu_signature *csig) { unsigned int cpu_num = smp_processor_id(); @@ -295,7 +292,6 @@ static struct microcode_patch *allow_microcode_patch( static int apply_microcode(const struct microcode_patch *patch) { - unsigned long flags; uint64_t msr_content; unsigned int val[2]; unsigned int cpu_num = raw_smp_processor_id(); @@ -307,8 +303,7 @@ static int apply_microcode(const struct microcode_patch *patch) mc_intel = patch->mc_intel; - /* serialize access to the physical write to MSR 0x79 */ - spin_lock_irqsave(µcode_update_lock, flags); + BUG_ON(local_irq_is_enabled()); /* * Writeback and invalidate caches before updating microcode to avoid @@ -327,7 +322,6 @@ static int apply_microcode(const struct microcode_patch *patch) rdmsrl(MSR_IA32_UCODE_REV, msr_content); val[1] = (uint32_t)(msr_content >> 32); - spin_unlock_irqrestore(µcode_update_lock, flags); if ( val[1] != mc_intel->hdr.rev ) { printk(KERN_ERR "microcode: CPU%d update from revision " From patchwork Mon May 27 08:31:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Gao X-Patchwork-Id: 10962293 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 224951390 for ; Mon, 27 May 2019 08:29:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1253528AAC for ; Mon, 27 May 2019 08:29:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 069F528AB3; Mon, 27 May 2019 08:29:48 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id B20D828AAC for ; Mon, 27 May 2019 08:29:47 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAz1-0004NX-1W; Mon, 27 May 2019 08:27:51 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hVAyz-0004ML-MY for xen-devel@lists.xenproject.org; Mon, 27 May 2019 08:27:49 +0000 X-Inumbo-ID: 4f661d75-8059-11e9-8980-bc764e045a96 Received: from mga12.intel.com (unknown [192.55.52.136]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 4f661d75-8059-11e9-8980-bc764e045a96; Mon, 27 May 2019 08:27:48 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 May 2019 01:27:48 -0700 X-ExtLoop1: 1 Received: from gao-cwp.sh.intel.com ([10.239.159.26]) by orsmga005.jf.intel.com with ESMTP; 27 May 2019 01:27:46 -0700 From: Chao Gao To: xen-devel@lists.xenproject.org Date: Mon, 27 May 2019 16:31:31 +0800 Message-Id: <1558945891-3015-11-git-send-email-chao.gao@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1558945891-3015-1-git-send-email-chao.gao@intel.com> References: <1558945891-3015-1-git-send-email-chao.gao@intel.com> Subject: [Xen-devel] [PATCH v7 10/10] x86/microcode: always collect_cpu_info() during boot X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Sergey Dyasli , Ashok Raj , Wei Liu , Andrew Cooper , Jan Beulich , Chao Gao , =?utf-8?q?R?= =?utf-8?q?oger_Pau_Monn=C3=A9?= MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Sergey Dyasli Currently cpu_sig struct is not updated during boot when either: 1. ucode_scan is set to false (e.g. no "ucode=scan" in cmdline) 2. initrd does not contain a microcode blob These will result in cpu_sig.rev being 0 which affects APIC's check_deadline_errata() and retpoline_safe() functions. Fix this by getting ucode revision early during boot and SMP bring up. While at it. Signed-off-by: Sergey Dyasli Signed-off-by: Chao Gao --- changes in v7: - rebase on patch 1~9 --- xen/arch/x86/microcode.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c index f4a417e..8aeb152 100644 --- a/xen/arch/x86/microcode.c +++ b/xen/arch/x86/microcode.c @@ -590,6 +590,10 @@ int __init early_microcode_init(void) if ( microcode_ops ) { + rc = microcode_ops->collect_cpu_info(&this_cpu(cpu_sig)); + if ( rc ) + return rc; + if ( ucode_mod.mod_end || ucode_blob.size ) rc = early_microcode_parse_and_update_cpu(); }