From nobody Mon Feb 9 09:29:33 2026 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1568272825; cv=none; d=zoho.com; s=zohoarc; b=Zubayy3dRev9gzVt9pBSzARlR8bzpa4ZtXy/Dymxh1yQxxmqgsBg5UxvkCzE8XRWgjo7ypjcIROCEcAqpxlY6dSz/vOD9LyuRze/AooZuaLBJ/8FCy01akZmown9M1YA4nzU8e4K1hjOMBhWgGSZfPsgt6x7qxxWhE4zbh/koWs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1568272825; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=Lc0QUNlL4+VSrAnqrA5ybrRRn/dIawsD9yT22M6IPFY=; b=CJrt89qKKe3D2SPtmy1oUYh0N90Ob8HRS247oTbLBLyXqr8cZ4ejOYdIznqrSd9XIVaaTo9nGoVMRqAOrM5H9w+KlMPtvXNHWOhY0osye32D8lfbYoukUJ+CXJSD90yH7H+hkl9hcINnRQQzcBI+Kpe+JsRfGXSpHrNYZdeJMeY= ARC-Authentication-Results: i=1; mx.zoho.com; spf=none (zoho.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 15682728258067.9803523614504; Thu, 12 Sep 2019 00:20:25 -0700 (PDT) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8JNz-0001mJ-7o; Thu, 12 Sep 2019 07:19:23 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8JNy-0001lX-6c for xen-devel@lists.xenproject.org; Thu, 12 Sep 2019 07:19:22 +0000 Received: from mga01.intel.com (unknown [192.55.52.88]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 989afc8c-d52d-11e9-83e3-12813bfff9fa; Thu, 12 Sep 2019 07:19:02 +0000 (UTC) Received: from orsmga006.jf.intel.com ([10.7.209.51]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 12 Sep 2019 00:19:01 -0700 Received: from gao-cwp.sh.intel.com ([10.239.159.26]) by orsmga006.jf.intel.com with ESMTP; 12 Sep 2019 00:18:59 -0700 X-Inumbo-ID: 989afc8c-d52d-11e9-83e3-12813bfff9fa X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,492,1559545200"; d="scan'208";a="189906315" From: Chao Gao To: xen-devel@lists.xenproject.org Date: Thu, 12 Sep 2019 15:22:24 +0800 Message-Id: <1568272949-1086-12-git-send-email-chao.gao@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1568272949-1086-1-git-send-email-chao.gao@intel.com> References: <1568272949-1086-1-git-send-email-chao.gao@intel.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH v10 11/16] microcode: reduce memory allocation and copy when creating a 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?Roger=20Pau=20Monn=C3=A9?= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" To create a microcode patch from a vendor-specific update, allocate_microcode_patch() copied everything from the update. It is not efficient. Essentially, we just need to go through ucodes in the blob, find the one with the newest revision and install it into the microcode_patch. In the process, buffers like mc_amd, equiv_cpu_table (on AMD side), and mc (on Intel side) can be reused. microcode_patch now is allocated after it is sure that there is a matching ucode. Signed-off-by: Chao Gao Reviewed-by: Roger Pau Monn=C3=A9 Reviewed-by: Jan Beulich --- Changes in v10: - avoid unnecessary type casting * introduce compare_header on AMD side * specify the type of the first parameter of get_next_ucode_from_buffer() on Intel side Changes in v9: - new --- xen/arch/x86/microcode_amd.c | 112 +++++++++++++++++--------------------= ---- xen/arch/x86/microcode_intel.c | 67 +++++++++--------------- 2 files changed, 69 insertions(+), 110 deletions(-) diff --git a/xen/arch/x86/microcode_amd.c b/xen/arch/x86/microcode_amd.c index 1d1bea4..f05db72 100644 --- a/xen/arch/x86/microcode_amd.c +++ b/xen/arch/x86/microcode_amd.c @@ -194,36 +194,6 @@ static bool match_cpu(const struct microcode_patch *pa= tch) return patch && (microcode_fits(patch->mc_amd) =3D=3D NEW_UCODE); } =20 -static struct microcode_patch *alloc_microcode_patch( - const struct microcode_amd *mc_amd) -{ - struct microcode_patch *microcode_patch =3D xmalloc(struct microcode_p= atch); - struct microcode_amd *cache =3D xmalloc(struct microcode_amd); - void *mpb =3D xmalloc_bytes(mc_amd->mpb_size); - struct equiv_cpu_entry *equiv_cpu_table =3D - 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); - return ERR_PTR(-ENOMEM); - } - - memcpy(mpb, mc_amd->mpb, mc_amd->mpb_size); - cache->mpb =3D mpb; - cache->mpb_size =3D mc_amd->mpb_size; - memcpy(equiv_cpu_table, mc_amd->equiv_cpu_table, - mc_amd->equiv_cpu_table_size); - cache->equiv_cpu_table =3D equiv_cpu_table; - cache->equiv_cpu_table_size =3D mc_amd->equiv_cpu_table_size; - microcode_patch->mc_amd =3D cache; - - return microcode_patch; -} - static void free_patch(void *mc) { struct microcode_amd *mc_amd =3D mc; @@ -236,6 +206,17 @@ static void free_patch(void *mc) } } =20 +static enum microcode_match_result compare_header( + const struct microcode_header_amd *new_header, + const struct microcode_header_amd *old_header) +{ + if ( new_header->processor_rev_id =3D=3D old_header->processor_rev_id ) + return (new_header->patch_id > old_header->patch_id) ? NEW_UCODE + : OLD_UCODE; + + return MIS_UCODE; +} + static enum microcode_match_result compare_patch( const struct microcode_patch *new, const struct microcode_patch *old) { @@ -246,11 +227,7 @@ static enum microcode_match_result compare_patch( ASSERT(microcode_fits(new->mc_amd) !=3D MIS_UCODE); ASSERT(microcode_fits(new->mc_amd) !=3D MIS_UCODE); =20 - if ( new_header->processor_rev_id =3D=3D old_header->processor_rev_id ) - return (new_header->patch_id > old_header->patch_id) ? - NEW_UCODE : OLD_UCODE; - - return MIS_UCODE; + return compare_header(new_header, old_header); } =20 static int apply_microcode(const struct microcode_patch *patch) @@ -328,18 +305,10 @@ static int get_ucode_from_buffer_amd( return -EINVAL; } =20 - if ( mc_amd->mpb_size < mpbuf->len ) - { - if ( mc_amd->mpb ) - { - xfree(mc_amd->mpb); - mc_amd->mpb_size =3D 0; - } - mc_amd->mpb =3D xmalloc_bytes(mpbuf->len); - if ( mc_amd->mpb =3D=3D NULL ) - return -ENOMEM; - mc_amd->mpb_size =3D mpbuf->len; - } + mc_amd->mpb =3D xmalloc_bytes(mpbuf->len); + if ( !mc_amd->mpb ) + return -ENOMEM; + mc_amd->mpb_size =3D mpbuf->len; memcpy(mc_amd->mpb, mpbuf->data, mpbuf->len); =20 pr_debug("microcode: CPU%d size %zu, block size %u offset %zu equivID = %#x rev %#x\n", @@ -459,8 +428,9 @@ static struct microcode_patch *cpu_request_microcode(co= nst void *buf, size_t bufsize) { struct microcode_amd *mc_amd; + struct microcode_header_amd *saved =3D NULL; struct microcode_patch *patch =3D NULL; - size_t offset =3D 0; + size_t offset =3D 0, saved_size =3D 0; int error =3D 0; unsigned int current_cpu_id; unsigned int equiv_cpu_id; @@ -550,29 +520,22 @@ static struct microcode_patch *cpu_request_microcode(= const void *buf, while ( (error =3D get_ucode_from_buffer_amd(mc_amd, buf, bufsize, &offset)) =3D=3D 0 ) { - struct microcode_patch *new_patch =3D alloc_microcode_patch(mc_amd= ); - - if ( IS_ERR(new_patch) ) - { - error =3D PTR_ERR(new_patch); - break; - } - /* - * If the new patch covers current CPU, compare patches and store = the + * If the new ucode covers current CPU, compare ucodes and store t= he * one with higher revision. */ - if ( (microcode_fits(new_patch->mc_amd) !=3D MIS_UCODE) && - (!patch || (compare_patch(new_patch, patch) =3D=3D NEW_UCODE)= ) ) + if ( (microcode_fits(mc_amd) !=3D MIS_UCODE) && + (!saved || (compare_header(mc_amd->mpb, saved) =3D=3D NEW_UCO= DE)) ) { - struct microcode_patch *tmp =3D patch; - - patch =3D new_patch; - new_patch =3D tmp; + xfree(saved); + saved =3D mc_amd->mpb; + saved_size =3D mc_amd->mpb_size; + } + else + { + xfree(mc_amd->mpb); + mc_amd->mpb =3D NULL; } - - if ( new_patch ) - microcode_free_patch(new_patch); =20 if ( offset >=3D bufsize ) break; @@ -601,7 +564,22 @@ static struct microcode_patch *cpu_request_microcode(c= onst void *buf, *(const uint32_t *)(buf + offset) =3D=3D UCODE_MAGIC ) break; } - free_patch(mc_amd); + + if ( saved ) + { + mc_amd->mpb =3D saved; + mc_amd->mpb_size =3D saved_size; + patch =3D xmalloc(struct microcode_patch); + if ( patch ) + patch->mc_amd =3D mc_amd; + else + { + free_patch(mc_amd); + error =3D -ENOMEM; + } + } + else + free_patch(mc_amd); =20 out: if ( error && !patch ) diff --git a/xen/arch/x86/microcode_intel.c b/xen/arch/x86/microcode_intel.c index c3083d7..4e811b7 100644 --- a/xen/arch/x86/microcode_intel.c +++ b/xen/arch/x86/microcode_intel.c @@ -286,25 +286,6 @@ static enum microcode_match_result compare_patch( : OLD_UCODE; } =20 -static struct microcode_patch *alloc_microcode_patch( - const struct microcode_header_intel *mc_header) -{ - unsigned long total_size =3D get_totalsize(mc_header); - void *new_mc =3D xmalloc_bytes(total_size); - struct microcode_patch *new_patch =3D xmalloc(struct microcode_patch); - - if ( !new_patch || !new_mc ) - { - xfree(new_patch); - xfree(new_mc); - return ERR_PTR(-ENOMEM); - } - memcpy(new_mc, mc_header, total_size); - new_patch->mc_intel =3D new_mc; - - return new_patch; -} - static int apply_microcode(const struct microcode_patch *patch) { unsigned long flags; @@ -353,8 +334,9 @@ static int apply_microcode(const struct microcode_patch= *patch) return 0; } =20 -static long get_next_ucode_from_buffer(void **mc, const u8 *buf, - unsigned long size, long offset) +static long get_next_ucode_from_buffer(struct microcode_intel **mc, + const u8 *buf, unsigned long size, + long offset) { struct microcode_header_intel *mc_header; unsigned long total_size; @@ -386,47 +368,46 @@ static struct microcode_patch *cpu_request_microcode(= const void *buf, { long offset =3D 0; int error =3D 0; - void *mc; + struct microcode_intel *mc, *saved =3D NULL; struct microcode_patch *patch =3D NULL; =20 while ( (offset =3D get_next_ucode_from_buffer(&mc, buf, size, offset)= ) > 0 ) { - struct microcode_patch *new_patch; - error =3D microcode_sanity_check(mc); if ( error ) - break; - - new_patch =3D alloc_microcode_patch(mc); - if ( IS_ERR(new_patch) ) { - error =3D PTR_ERR(new_patch); + xfree(mc); break; } =20 /* - * If the new patch covers current CPU, compare patches and store = the + * If the new update covers current CPU, compare updates and store= the * one with higher revision. */ - if ( (microcode_update_match(&new_patch->mc_intel->hdr) !=3D MIS_U= CODE) && - (!patch || (compare_patch(new_patch, patch) =3D=3D NEW_UCODE)= ) ) + if ( (microcode_update_match(&mc->hdr) !=3D MIS_UCODE) && + (!saved || (mc->hdr.rev > saved->hdr.rev)) ) { - struct microcode_patch *tmp =3D patch; - - patch =3D new_patch; - new_patch =3D tmp; + xfree(saved); + saved =3D mc; } - - if ( new_patch ) - microcode_free_patch(new_patch); - - xfree(mc); + else + xfree(mc); } - if ( offset > 0 ) - xfree(mc); if ( offset < 0 ) error =3D offset; =20 + if ( saved ) + { + patch =3D xmalloc(struct microcode_patch); + if ( patch ) + patch->mc_intel =3D saved; + else + { + xfree(saved); + error =3D -ENOMEM; + } + } + if ( error && !patch ) patch =3D ERR_PTR(error); =20 --=20 1.8.3.1 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xenproject.org https://lists.xenproject.org/mailman/listinfo/xen-devel