xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Boris Ostrovsky <boris.ostrovsky@amd.com>
To: Jan Beulich <JBeulich@suse.com>
Cc: Ian.Campbell@citrix.com, Christoph_Egger@gmx.de, xen-devel@lists.xen.org
Subject: Re: [PATCH] x86/ucode: Improve error handling and container file processing on AMD
Date: Fri, 7 Dec 2012 08:46:28 -0500	[thread overview]
Message-ID: <50C1F334.20802@amd.com> (raw)
In-Reply-To: <50C1E41402000078000AEED6@nat28.tlf.novell.com>

Inline.

On 12/07/2012 06:41 AM, Jan Beulich wrote:
>>>> On 06.12.12 at 19:28, Boris Ostrovsky <boris.ostrovsky@amd.com> wrote:
>> Do not report error when a patch is not appplicable to current processor,
>> simply skip it and move on to next patch in container file.
>>
>> Process container file to the end instead of stopping at the first
>> applicable patch.
>>
>> Log the fact that a patch has been applied at KERN_WARNING level, add
>> CPU number to debug messages.
>>
>> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@amd.com>
>> ---
>>   xen/arch/x86/microcode_amd.c |   69 +++++++++++++++++++++++-------------------
>>   1 file changed, 38 insertions(+), 31 deletions(-)
>>
>> diff --git a/xen/arch/x86/microcode_amd.c b/xen/arch/x86/microcode_amd.c
>> index 7a54001..bb5968e 100644
>> --- a/xen/arch/x86/microcode_amd.c
>> +++ b/xen/arch/x86/microcode_amd.c
>> @@ -88,13 +88,13 @@ static int collect_cpu_info(int cpu, struct cpu_signature
>> *csig)
>>
>>       rdmsrl(MSR_AMD_PATCHLEVEL, csig->rev);
>>
>> -    printk(KERN_DEBUG "microcode: collect_cpu_info: patch_id=%#x\n",
>> -           csig->rev);
>> +    printk(KERN_DEBUG "microcode: CPU%d collect_cpu_info: patch_id=%#x\n",
>> +           cpu, csig->rev);
>>
>>       return 0;
>>   }
>>
>> -static int microcode_fits(const struct microcode_amd *mc_amd, int cpu)
>> +static bool_t 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;
>> @@ -125,11 +125,16 @@ static int microcode_fits(const struct microcode_amd *mc_amd, int cpu)
>>           printk(KERN_DEBUG "microcode: CPU%d patch does not match "
>>                  "(patch is %x, cpu base id is %x) \n",
>>                  cpu, mc_header->processor_rev_id, equiv_cpu_id);
>> -        return -EINVAL;
>> +        return 0;
>>       }
>>
>>       if ( mc_header->patch_id <= uci->cpu_sig.rev )
>> +    {
>> +        printk(KERN_DEBUG "microcode: CPU%d patching is not needed: "
>> +               "patch provides level 0x%x, cpu is at 0x%x \n",
>
> Did you not notice that all the other messages now use %#x?
>
> Also, I'm not really convinced we need this added verbosity. I
> personally tend to run all my systems with "loglvl=all", and the
> amount of output produced by the code in this file made me
> change that for just the one AMD machine I have that is new
> enough to support microcode loading.
>
> Minimally I'd expect nothing to be printed here if the two
> versions match.

Yes, I may have gone a bit overboard with chattiness.

This is actually made worse by the fact that we are going through patch 
loading twice during boot --- once through start_secondary() (or via 
microcode_presmp_init() on CPU0) and second time when the driver is 
initialized.

Do we really need what microcode_init() does?

>
>> +               cpu, mc_header->patch_id, uci->cpu_sig.rev);
>>           return 0;
>> +    }
>>
>>       printk(KERN_DEBUG "microcode: CPU%d found a matching microcode "
>>              "update with version %#x (current=%#x)\n",
>> @@ -173,7 +178,7 @@ static int apply_microcode(int cpu)
>>           return -EIO;
>>       }
>>
>> -    printk(KERN_INFO "microcode: CPU%d updated from revision %#x to %#x\n",
>> +    printk(KERN_WARNING "microcode: CPU%d updated from revision %#x to %#x\n",
>>              cpu, uci->cpu_sig.rev, hdr->patch_id);
>>
>>       uci->cpu_sig.rev = rev;
>> @@ -181,7 +186,7 @@ static int apply_microcode(int cpu)
>>       return 0;
>>   }
>>
>> -static int get_next_ucode_from_buffer_amd(
>> +static int get_ucode_from_buffer_amd(
>>       struct microcode_amd *mc_amd,
>>       const void *buf,
>>       size_t bufsize,
>> @@ -194,8 +199,12 @@ static int get_next_ucode_from_buffer_amd(
>>       off = *offset;
>>
>>       /* No more data */
>> -    if ( off >= bufsize )
>> -        return 1;
>> +    if ( off >= bufsize )
>> +    {
>> +        printk(KERN_ERR "microcode: error! "
>> +               "ucode buffer overrun\n");
>
> All on one line please (and the "error!" probably is superfluous).
>
> Also, is printing this really correct when off == bufsize? Or can
> this not happen at all?

Prior to this patch off >= bufsize was not an error but actually loop 
termination condition for the caller ("==" was the most likely case). 
Now the loop is broken out explicitly so when off >= bufsize (including 
"==") we have an error. Having said this, it is pretty much impossible 
to get it with current code.

>
>> +        return -EINVAL;
>> +    }
>>
>>       mpbuf = (const struct mpbhdr *)&bufp[off];
>>       if ( mpbuf->type != UCODE_UCODE_TYPE )
>> @@ -205,8 +214,8 @@ static int get_next_ucode_from_buffer_amd(
>>           return -EINVAL;
>>       }
>>
>> -    printk(KERN_DEBUG "microcode: size %zu, block size %u, offset %zu\n",
>> -           bufsize, mpbuf->len, off);
>> +    printk(KERN_DEBUG "microcode: CPU%d size %zu, block size %u, offset %zu\n",
>> +           raw_smp_processor_id(), bufsize, mpbuf->len, off);
>>
>>       if ( (off + mpbuf->len) > bufsize )
>>       {
>> @@ -278,8 +287,8 @@ static int cpu_request_microcode(int cpu, const void *buf, size_t bufsize)
>>   {
>>       struct microcode_amd *mc_amd, *mc_old;
>>       size_t offset = bufsize;
>> +    size_t last_offset, applied_offset = 0;
>>       int error = 0;
>> -    int ret;
>>       struct ucode_cpu_info *uci = &per_cpu(ucode_cpu_info, cpu);
>>
>>       /* We should bind the task to the CPU */
>> @@ -321,33 +330,32 @@ static int cpu_request_microcode(int cpu, const void
>> *buf, size_t bufsize)
>>        */
>>       mc_amd->mpb = NULL;
>>       mc_amd->mpb_size = 0;
>> -    while ( (ret = get_next_ucode_from_buffer_amd(mc_amd, buf, bufsize,
>> -                                                  &offset)) == 0 )
>> +    last_offset = offset;
>> +    while ( (error = get_ucode_from_buffer_amd(mc_amd, buf, bufsize,
>> +                                               &offset)) == 0 )
>>       {
>> -        error = microcode_fits(mc_amd, cpu);
>> -        if (error <= 0)
>> -            continue;
>> +        if ( microcode_fits(mc_amd, cpu) )
>> +            if ( apply_microcode(cpu) == 0 )
>
> Fold the two if()-s into one, please.
>
> But then again you lose the return value of apply_microcode()
> here, which is wrong.

Right, I need to deal with it. Unfortunately apply_microcode() may get 
an error after a previous patch has been successfully loaded (for the 
very unlikely cases when container has multiple matches). I will 
probably still make the driver return an error in this case too.


Thanks.
-boris


>
>> +                applied_offset = last_offset;
>>
>> -        error = apply_microcode(cpu);
>> -        if (error == 0)
>> -        {
>> -            error = 1;
>> +        last_offset = offset;
>> +
>> +        if ( offset >= bufsize )
>>               break;
>> -        }
>>       }
>>
>> -    if ( ret < 0 )
>> -        error = ret;
>> -
>>       /* On success keep the microcode patch for
>>        * re-apply on resume.
>>        */
>> -    if ( error == 1 )
>> +    if ( applied_offset != 0 )
>>       {
>> -        xfree(mc_old);
>> -        error = 0;
>> +        error = get_ucode_from_buffer_amd(mc_amd, buf, bufsize,
>> +                                          &applied_offset);
>> +        if (error == 0)
>> +            xfree(mc_old);
>>       }
>> -    else
>> +
>> +    if ( applied_offset == 0 || error != 0 )
>>       {
>>           xfree(mc_amd);
>>           uci->mc.mc_amd = mc_old;
>> @@ -364,10 +372,9 @@ static int microcode_resume_match(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;
>> -    int res = microcode_fits(src, cpu);
>>
>> -    if ( res <= 0 )
>> -        return res;
>> +    if ( microcode_fits(src, cpu) == 0 )
>
> microcode_fits() now returning bool_t clearly asks for using ! instead
> of == 0 here.
>
> Jan
>
>> +        return 0;
>>
>>       if ( src != mc_amd )
>>       {
>> --
>> 1.7.10.4
>
>
>

  reply	other threads:[~2012-12-07 13:46 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-06 18:28 [PATCH] x86/ucode: Improve error handling and container file processing on AMD Boris Ostrovsky
2012-12-07 10:21 ` Ian Campbell
2012-12-07 11:41 ` Jan Beulich
2012-12-07 13:46   ` Boris Ostrovsky [this message]
2012-12-07 15:08     ` Jan Beulich
2012-12-07 15:25       ` Boris Ostrovsky
2012-12-07 15:42         ` 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=50C1F334.20802@amd.com \
    --to=boris.ostrovsky@amd.com \
    --cc=Christoph_Egger@gmx.de \
    --cc=Ian.Campbell@citrix.com \
    --cc=JBeulich@suse.com \
    --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).