From: Aravind Gopalakrishnan <aravind.gopalakrishnan@amd.com>
To: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: Thomas.Lendacky@amd.com, keir@xen.org,
Suravee.Suthikulpanit@amd.com, jbeulich@suse.com,
xen-devel@lists.xen.org
Subject: Re: [PATCH] x86, amd_ucode: Verify max allowed patch size before apply
Date: Fri, 25 Apr 2014 14:48:06 -0500 [thread overview]
Message-ID: <535ABBF6.1060303@amd.com> (raw)
In-Reply-To: <5359738A.6050607@citrix.com>
On 4/24/2014 3:26 PM, Andrew Cooper wrote:
> On 24/04/14 20:54, Aravind Gopalakrishnan wrote:
>>
>> -static bool_t microcode_fits(const struct microcode_amd *mc_amd, int cpu)
>> +static bool_t verify_patch_size(uint32_t patch_size)
>> +{
>> + uint8_t family;
>> + uint32_t max_size;
>> +
>> +#define F1XH_MPB_MAX_SIZE 2048
>> +#define F14H_MPB_MAX_SIZE 1824
>> +#define F15H_MPB_MAX_SIZE 4096
>> +#define F16H_MPB_MAX_SIZE 3458
>> +
>> + family = boot_cpu_data.x86;
>> + switch (family)
> You can drop the family variable and just switch on boot_cpu_data.x86
Noted.
>> +static int microcode_fits(const struct microcode_amd *mc_amd, int cpu)
>> {
>> struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu);
>> const struct microcode_header_amd *mc_header = mc_amd->mpb;
>> @@ -118,19 +151,25 @@ static bool_t microcode_fits(const struct microcode_amd *mc_amd, int cpu)
>> }
>>
>> if ( !equiv_cpu_id )
>> - return 0;
>> + return -EINVAL;
>>
>> if ( (mc_header->processor_rev_id) != equiv_cpu_id )
>> - return 0;
>> + return -EINVAL;
>> +
>> + if ( !verify_patch_size(mc_amd->mpb_size) )
>> + {
>> + printk(KERN_ERR "microcode: patch size mismatch\n");
>> + return -EINVAL;
> XENLOG_ERR "microcode patch size too large"
> return -E2BIG;
>
> And is this really worth being an error as opposed to a warning, or
> frankly even just debug? It is presumably one of N possible blobs in the
> hypercall.
Right. Modified it to use XENLOG_DEBUG instead.
>>
>> static int apply_microcode(int cpu)
>> @@ -319,7 +358,8 @@ static int cpu_request_microcode(int cpu, const void *buf, size_t bufsize)
>> while ( (error = get_ucode_from_buffer_amd(mc_amd, buf, bufsize,
>> &offset)) == 0 )
>> {
>> - if ( microcode_fits(mc_amd, cpu) )
>> + error = microcode_fits(mc_amd, cpu);
>> + if ( !error )
>> {
>> error = apply_microcode(cpu);
>> if ( error )
>> @@ -329,6 +369,11 @@ static int cpu_request_microcode(int cpu, const void *buf, size_t bufsize)
>>
>> last_offset = offset;
>>
>> + if ( error == -EEXIST ) {
>> + printk(KERN_DEBUG "microcode: patch is already at required level or greater.\n");
>> + break;
> You can't break from the loop here. What if a subsequent blob in the
> buffer contains a newer piece of microcode?
>
Right. Didn't think about that. Sorry..
But I ran into larger issues here:
Since we don't break on the first match and continue to parse the entire
fw image till the very end;
*and* since I modified the error handling around 'microcode_fits' thus:
if ( (mc_header->processor_rev_id) != equiv_cpu_id )
-return 0;
+return -EINVAL;
+
The last returned error val is '-22' which is bubbled up to microcode.c.
'microcode_presmp_init' as a result
flushes out ucode_blob or NULL-ifies ucode_mod_map.
Which means 'microcode_init' returns early as it can't validate
ucode_mod.mod_end or ucode_blob.size
Now, this breaks original functionality (sorry for catching this late),
*but*
doesn't cause any problem to updating(,applying) ucode patches to cpus
as we apply the patches during
'microcode_resume_cpu' anyway. (which is why I thought at first all is
fine)
Could someone please help me understand why there are two initcalls -
'microcode_presmp_init' && 'microcode_init'
that perform the same tasks?
It results in these functions - 'collect_cpu_info',
'cpu_request_microcode' to run a second time through 'microcode_init'
when we have already accomplished the job of updating cpu with microcode
patches
through 'microcode_presmp_init' and 'microcode_resume_cpu'
If there is particular reason for 'microcode_init''s existence, then
I'll modify the patch so that the error handling around 'microcode_fits'
is not altered. But if not, then I simply have to just remove the
'break' statement.
Thanks,
-Aravind.
next prev parent reply other threads:[~2014-04-25 19:48 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-24 19:54 [PATCH] x86, amd_ucode: Verify max allowed patch size before apply Aravind Gopalakrishnan
2014-04-24 20:26 ` Andrew Cooper
2014-04-25 19:48 ` Aravind Gopalakrishnan [this message]
2014-04-25 20:30 ` Andrew Cooper
2014-04-28 8:49 ` Jan Beulich
2014-04-28 15:48 ` Aravind Gopalakrishnan
2014-04-25 7:00 ` Jan Beulich
2014-04-25 19:48 ` Aravind Gopalakrishnan
2014-04-28 7:21 ` Jan Beulich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=535ABBF6.1060303@amd.com \
--to=aravind.gopalakrishnan@amd.com \
--cc=Suravee.Suthikulpanit@amd.com \
--cc=Thomas.Lendacky@amd.com \
--cc=andrew.cooper3@citrix.com \
--cc=jbeulich@suse.com \
--cc=keir@xen.org \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).