From patchwork Fri Nov 22 16:47:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Sergey Dyasli X-Patchwork-Id: 11258163 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2E67D109A for ; Fri, 22 Nov 2019 16:48:24 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0954B2071C for ; Fri, 22 Nov 2019 16:48:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="bcfJZkxC" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0954B2071C Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iYC5o-0006A8-1J; Fri, 22 Nov 2019 16:47:36 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iYC5m-0006A2-EV for xen-devel@lists.xen.org; Fri, 22 Nov 2019 16:47:34 +0000 X-Inumbo-ID: c738be6a-0d47-11ea-984a-bc764e2007e4 Received: from esa4.hc3370-68.iphmx.com (unknown [216.71.155.144]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id c738be6a-0d47-11ea-984a-bc764e2007e4; Fri, 22 Nov 2019 16:47:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1574441253; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=Cr9SMdbxlkifg6ZO1QsLpsMSC3dPU8anRxq3lNWvhB8=; b=bcfJZkxCivnuyJFBwvEaUc5fC1yB7JytDpqtgAOXJozW9XCVmeIa/9SH llMxqlySnpSZTr+nHqp5HNnT0UoQKZ9joeVFhjFO13e1r8neYtEiCJ2BN zxg+xT7eAfYsbWg6+RqWeozzrcnk+2/UK0pVAE0/s4fNw9albGkfrSEy5 g=; Authentication-Results: esa4.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=sergey.dyasli@citrix.com; spf=Pass smtp.mailfrom=sergey.dyasli@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa4.hc3370-68.iphmx.com: no sender authenticity information available from domain of sergey.dyasli@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa4.hc3370-68.iphmx.com; envelope-from="sergey.dyasli@citrix.com"; x-sender="sergey.dyasli@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa4.hc3370-68.iphmx.com: domain of sergey.dyasli@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa4.hc3370-68.iphmx.com; envelope-from="sergey.dyasli@citrix.com"; x-sender="sergey.dyasli@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ip4:168.245.78.127 ~all" Received-SPF: None (esa4.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa4.hc3370-68.iphmx.com; envelope-from="sergey.dyasli@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: UUzRg22KH80rd81L5oYPXlpHG+ZumqoUsEeOWt5swFKD8aS/mebgzfklkspV+nTC6pdmE4MPrH ac4FeeAgAW2J1tjC6ms/IbMQ5Sosug5o2trT/4l9sfnDPzXcnj8iR8/LcOA3E0Up4yzmfmkgqG IrSzpgKgzXwGu0q1JbYiol+mjmq2B/qaF8l6E9HupDlat4kf9fzP6iIqkvEkxlDR74KoBRAfRI 8ZM3Pz8hj01O/ZmXtHd78EtfobFeJ0uuIlKLI7cA5yEo8RSF/1BLqtuopFOgyDgl4XHzh7/juC 5zY= X-SBRS: 2.7 X-MesageID: 9266497 X-Ironport-Server: esa4.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.69,230,1571716800"; d="scan'208";a="9266497" From: Sergey Dyasli To: Date: Fri, 22 Nov 2019 16:47:23 +0000 Message-ID: <20191122164723.1302-1-sergey.dyasli@citrix.com> X-Mailer: git-send-email 2.17.1 MIME-Version: 1.0 Subject: [Xen-devel] [PATCH v2 for 4.13] x86/microcode: refuse to load the same revision ucode 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: Juergen Gross , Sergey Dyasli , Andrew Cooper , Jan Beulich , Chao Gao , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Currently if a user tries to live-load the same or older ucode revision than CPU already has, he will get a single message in Xen log like: (XEN) 128 cores are to update their microcode No actual ucode loading will happen and this situation can be quite confusing. Fix this by starting ucode update only when the provided ucode revision is higher than the currently cached one (if any). This is based on the property that if microcode_cache exists, all CPUs in the system should have at least that ucode revision. Additionally, print a user friendly message if no newer ucode can be found in the provided blob. This also requires ignoring -ENODATA in AMD-side code, otherwise the message given to the user is: (XEN) Parsing microcode blob error -61 Which actually means that a ucode blob was parsed fine, but no matching ucode was found. Signed-off-by: Sergey Dyasli Reviewed-by: Chao Gao --- v1 --> v2: - compare provided ucode with the currently cached one CC: Jan Beulich CC: Andrew Cooper CC: Roger Pau MonnĂ© CC: Chao Gao CC: Juergen Gross --- xen/arch/x86/microcode.c | 12 ++++++++++-- xen/arch/x86/microcode_amd.c | 14 ++++++++++---- xen/arch/x86/microcode_intel.c | 12 +++++++++--- xen/include/asm-x86/microcode.h | 3 ++- 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c index 65d1f41e7c..dcd2c3ff77 100644 --- a/xen/arch/x86/microcode.c +++ b/xen/arch/x86/microcode.c @@ -266,10 +266,16 @@ static const struct microcode_patch *nmi_patch = ZERO_BLOCK_PTR; */ static struct microcode_patch *parse_blob(const char *buf, size_t len) { + struct microcode_patch *ret = NULL; + if ( likely(!microcode_ops->collect_cpu_info(&this_cpu(cpu_sig))) ) - return microcode_ops->cpu_request_microcode(buf, len); + { + spin_lock(µcode_mutex); + ret = microcode_ops->cpu_request_microcode(buf, len, microcode_cache); + spin_unlock(µcode_mutex); + } - return NULL; + return ret; } void microcode_free_patch(struct microcode_patch *microcode_patch) @@ -641,6 +647,8 @@ int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void) buf, unsigned long len) if ( !patch ) { ret = -ENOENT; + printk(XENLOG_WARNING "microcode: couldn't find any newer revision in " + "the provided blob!\n"); goto put; } diff --git a/xen/arch/x86/microcode_amd.c b/xen/arch/x86/microcode_amd.c index 1e52f7f49a..cf63aff009 100644 --- a/xen/arch/x86/microcode_amd.c +++ b/xen/arch/x86/microcode_amd.c @@ -419,10 +419,11 @@ static bool_t check_final_patch_levels(unsigned int cpu) } static struct microcode_patch *cpu_request_microcode(const void *buf, - size_t bufsize) + size_t bufsize, + const struct microcode_patch *cache) { struct microcode_amd *mc_amd; - struct microcode_header_amd *saved = NULL; + struct microcode_header_amd *saved = NULL, *cached = NULL; struct microcode_patch *patch = NULL; size_t offset = 0, saved_size = 0; int error = 0; @@ -507,6 +508,9 @@ static struct microcode_patch *cpu_request_microcode(const void *buf, goto out; } + if ( cache && cache->mc_amd && cache->mc_amd->mpb ) + cached = cache->mc_amd->mpb; + /* * It's possible the data file has multiple matching ucode, * lets keep searching till the latest version @@ -516,9 +520,11 @@ static struct microcode_patch *cpu_request_microcode(const void *buf, { /* * If the new ucode covers current CPU, compare ucodes and store the - * one with higher revision. + * one with higher revision. It must also be higher than currently + * cached revision. */ if ( (microcode_fits(mc_amd) != MIS_UCODE) && + (!cached || (compare_header(mc_amd->mpb, cached) == NEW_UCODE)) && (!saved || (compare_header(mc_amd->mpb, saved) == NEW_UCODE)) ) { xfree(saved); @@ -576,7 +582,7 @@ static struct microcode_patch *cpu_request_microcode(const void *buf, free_patch(mc_amd); out: - if ( error && !patch ) + if ( error && error != -ENODATA && !patch ) patch = ERR_PTR(error); return patch; diff --git a/xen/arch/x86/microcode_intel.c b/xen/arch/x86/microcode_intel.c index 9f66057aad..a82dd0e701 100644 --- a/xen/arch/x86/microcode_intel.c +++ b/xen/arch/x86/microcode_intel.c @@ -357,13 +357,17 @@ static long get_next_ucode_from_buffer(struct microcode_intel **mc, } static struct microcode_patch *cpu_request_microcode(const void *buf, - size_t size) + size_t size, + const struct microcode_patch *cache) { long offset = 0; int error = 0; - struct microcode_intel *mc, *saved = NULL; + struct microcode_intel *mc, *saved = NULL, *cached = NULL; struct microcode_patch *patch = NULL; + if ( cache && cache->mc_intel ) + cached = cache->mc_intel; + while ( (offset = get_next_ucode_from_buffer(&mc, buf, size, offset)) > 0 ) { error = microcode_sanity_check(mc); @@ -375,9 +379,11 @@ static struct microcode_patch *cpu_request_microcode(const void *buf, /* * If the new update covers current CPU, compare updates and store the - * one with higher revision. + * one with higher revision. It must also be higher than currently + * cached revision. */ if ( (microcode_update_match(&mc->hdr) != MIS_UCODE) && + (!cached || (mc->hdr.rev > cached->hdr.rev)) && (!saved || (mc->hdr.rev > saved->hdr.rev)) ) { xfree(saved); diff --git a/xen/include/asm-x86/microcode.h b/xen/include/asm-x86/microcode.h index 7d5a1f8e8a..3dbb99cb88 100644 --- a/xen/include/asm-x86/microcode.h +++ b/xen/include/asm-x86/microcode.h @@ -21,7 +21,8 @@ struct microcode_patch { struct microcode_ops { struct microcode_patch *(*cpu_request_microcode)(const void *buf, - size_t size); + size_t size, + const struct microcode_patch *cache); int (*collect_cpu_info)(struct cpu_signature *csig); int (*apply_microcode)(const struct microcode_patch *patch); int (*start_update)(void);