From: Aravind Gopalakrishnan <aravind.gopalakrishnan@amd.com>
To: Jan Beulich <JBeulich@suse.com>,
xen-devel@lists.xen.org, boris.ostrovsky@oracle.com,
keir@xen.org
Subject: Re: [PATCH V3] x86, amd_ucode: Support multiple container files appended together
Date: Fri, 27 Jun 2014 12:07:35 -0500 [thread overview]
Message-ID: <53ADA4D7.3090801@amd.com> (raw)
In-Reply-To: <53AD689D020000780001DE4E@mail.emea.novell.com>
On 6/27/2014 5:50 AM, Jan Beulich wrote:
>>>> On 25.06.14 at 21:34, <aravind.gopalakrishnan@amd.com> wrote:
>> This patch adds support for parsing through multiple AMD container
>> binaries concatenated together. It is a feature already present in Linux.
>> Link to linux patch:
>> http://lkml.kernel.org/r/1370463236-2115-3-git-send-email-jacob.shin@amd.com
>>
>> Other changes introduced:
>> - Define HDR_SIZE's explicitly for code clarity.
>>
>> Changes in V3
>> - Change approach that used AMD_MAX_CONT_APPEND to handle edge case
>> - No need of a 'found' variable
>> - return 0 for success and not AMD_UCODE_APPLY_SUCCESS as someone
>> could just as easily break things by redefining it as bool
>> - No need of 'header' in container_fast_forward
>> - Handle more corner cases in container_fast_forward
>> - Fix code style issues
> Can you please get used to put this revision log after the first ---
> marker? It doesn't belong in ti actual commit message.
Okay.
>> @@ -272,14 +293,13 @@ static int get_ucode_from_buffer_amd(
>>
>> static int install_equiv_cpu_table(
>> struct microcode_amd *mc_amd,
>> - const uint32_t *buf,
>> + const void *data,
>> size_t *offset)
>> {
>> + uint32_t *buf = (uint32_t *) (data + *offset);
> I know I complained about this or a similar pointless cast for the
> previous version.
Yes, I thought I'll handle it as a separate cleanup patch as it was not
directly
related to the subject of the patch. But it's a small change, so I'll do
this and include
it in the commit message as well..
>> +static int container_fast_forward(const void *data, size_t size_left, size_t *offset)
>> +{
>> + size_t size;
>> +
>> + while ( size_left )
>> + {
>> + if ( size_left < SECTION_HDR_SIZE )
>> + return -EINVAL;
>> +
>> + if ( *(const uint32_t *)(data + *offset) == UCODE_MAGIC &&
>> + *(const uint32_t *)(data + *offset + 4) ==
>> + UCODE_EQUIV_CPU_TABLE_TYPE )
>> + break;
>> +
>> + size = *(uint32_t *)(data + *offset + 4) + SECTION_HDR_SIZE;
> Now these three casts+derefs surely warrant a "const uint32_t *"
> variable, making the resulting code quite a bit easier to read.
Okay. Will just use the bits in V2 with a const qualifier
>> + if ( size_left < size )
>> + return -EINVAL;
>> +
>> + size_left -= size;
>> + *offset += size;
> Endless loop if size ends up being zero? (If you do such verifications
> at all, you should perhaps be as strict as possible,
Sorry about that (Again). Will fix.
> i.e. if size is
> required to be a multiple of 4 [which I think it is], you should also
> check that.)
I don't think that's a rule per-se.
#define F16H_MPB_MAX_SIZE 3458
Which is indivisible by 4.
>> @@ -334,7 +384,40 @@ static int cpu_request_microcode(int cpu, const void
>> *buf, size_t bufsize)
>> goto out;
>> }
>>
>> - error = install_equiv_cpu_table(mc_amd, buf, &offset);
>> + /*
>> + * Multiple container file support:
>> + * 1. check if this container file has equiv_cpu_id match
>> + * 2. If not, fast-fwd to next container file
>> + */
>> + while ( offset < bufsize )
>> + {
>> + error = install_equiv_cpu_table(mc_amd, buf, &offset);
>> +
>> + if ( !error &&
>> + find_equiv_cpu_id(mc_amd->equiv_cpu_table, current_cpu_id,
>> + &equiv_cpu_id) )
>> + break;
>> +
>> + /*
>> + * Could happen as we advance 'offset' early
>> + * in install_equiv_cpu_table
>> + */
>> + if ( offset > bufsize )
>> + {
>> + printk(KERN_ERR "microcode: Microcode buffer overrun\n");
>> + return -EINVAL;
>> + }
>> +
>> + error = container_fast_forward(buf, bufsize - offset, &offset);
>> + if ( error )
>> + {
>> + 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);
>> + goto out;
>> + }
> So the immediately preceding error path used just "return" - why
> are they different (and I'm not asking about the printk())?
Ok, Shall use one or the other.. (Probably the goto as I see that's the
favored one in this function)
>> @@ -379,12 +462,35 @@ static int cpu_request_microcode(int cpu, const void *buf, size_t bufsize)
>> save_error = get_ucode_from_buffer_amd(
>> mc_amd, buf, bufsize, &applied_offset);
>>
>> - if ( save_error )
>> + /*
>> + * If there happens to be multiple container files and if patch
>> + * update succeeded on an earlier container itself, a stale error
> Do you perhaps mean bogus instead of stale?
Yes. Wrong word. Will fix.
>> + * val is returned from get_ucode_from_buffer_amd. Since we already
>> + * succeeded in patch application, force error = 0
>> + */
>> + if ( offset < bufsize )
>> + error = 0;
>> + else if ( save_error )
>> error = save_error;
> And still my question stands: Since you don't look at further containers
> if you found a match and successfully applied the updated, why is this
> change needed (or is the comment saying the wrong thing)?
Maybe the comment needs to be more verbose(?)
Yes, we found a match and yes, we applied the patch successfully.
But, while ( (error = get_ucode_from_buffer_amd(mc_amd, buf,
bufsize,&offset)) == 0 )
is going to, at some point hit if ( mpbuf->type != UCODE_UCODE_TYPE )
and return -EINVAL
which is assigned to the variable 'error'
(Assuming ofc that there is a second container there which we don't need
to parse because
we have already succeeded in patch application)
This is what I wanted to convey from
"astale bogus error val is returned from get_ucode_from_buffer_amd."
But, we need to return 0 on success; which is why this change is needed
here..
>
>> }
>>
>> if ( save_error )
>> {
>> + /*
>> + * By the time 'microcode_init' runs, we have already updated the
>> + * patch level on all (currently) running cpus.
>> + * But, get_ucode_from_buffer_amd will return -EINVAL as
>> + * if ( mpbuf->type != UCODE_UCODE_TYPE ) fails in this case:
>> + * Multiple containers are present && update succeeded with the
>> + * first container file itself.
>> + *
>> + * Only this time, there is no 'applied_offset' as well.
>> + * So, 'save_error' = 1. But error = -EINVAL.
>> + * Hence, this check is necessary to return 0 for success.
>> + */
>> + if ( (error != save_error) && (offset < bufsize) )
>> + error = 0;
> Same for this change/comment.
>
Hmm.. I'm having trouble trying to re-word this comment then..
Given the situation where - we have already applied the patch update after
'microcode_presmp_init' and 'microcode_resume_cpu';
|
v
Now 'microcode_init' runs and calls into 'cpu_request_microcode';
|
v
We use 1st while loop to find_equiv_cpu_id() and match it with the container
|
v
For this particular case, we assume it's a match on the 1st container;
so break
|
v
Enter while ( (error = get_ucode_from_buffer_amd(mc_amd, buf,
bufsize,&offset)) == 0 )
|
v
At some point, it will find the correct patch; but this time there is no
need to update
|
v
The behavior is now similar to what I have described above. i.e
while ( (error = get_ucode_from_buffer_amd(mc_amd, buf,
bufsize,&offset)) == 0 )
is going to, at some point hit if ( mpbuf->type != UCODE_UCODE_TYPE )
and return -EINVAL
which is assigned to the variable 'error'
|
v
But, now (as stated in the comment..)
* Only this time, there is no 'applied_offset' as well.
+ * So, 'save_error' = 1. But error = -EINVAL.
|
v
And since we need to return 0 for success, this change is needed here.
Thanks,
-Aravind
next prev parent reply other threads:[~2014-06-27 17:07 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-25 19:34 [PATCH V3] x86, amd_ucode: Support multiple container files appended together Aravind Gopalakrishnan
2014-06-26 13:14 ` Boris Ostrovsky
2014-06-26 15:03 ` Aravind Gopalakrishnan
2014-06-27 10:50 ` Jan Beulich
2014-06-27 17:07 ` Aravind Gopalakrishnan [this message]
2014-06-30 9:32 ` Jan Beulich
2014-06-30 16:51 ` Aravind Gopalakrishnan
-- strict thread matches above, loose matches on Subject: below --
2014-06-26 16:01 Boris Ostrovsky
2014-06-26 16:37 ` Aravind Gopalakrishnan
2014-06-26 20:00 ` Boris Ostrovsky
2014-06-26 21:55 ` Aravind Gopalakrishnan
2014-06-27 2:04 ` Boris Ostrovsky
2014-06-27 8:15 ` Jan Beulich
2014-06-27 12:47 ` Boris Ostrovsky
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=53ADA4D7.3090801@amd.com \
--to=aravind.gopalakrishnan@amd.com \
--cc=JBeulich@suse.com \
--cc=boris.ostrovsky@oracle.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.