[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH V4] x86, amd_ucode: Support multiple container files appended together



On 7/1/2014 3:23 AM, Jan Beulich wrote:
On 30.06.14 at 18:52, <aravind.gopalakrishnan@xxxxxxx> wrote:
@@ -272,14 +293,12 @@ 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)
  {
-    const struct mpbhdr *mpbuf = (const struct mpbhdr *)&buf[1];
+    const struct mpbhdr *mpbuf = (const struct mpbhdr *)(data + *offset + 4);
There's still a pointless cast here.

Fixed.

@@ -303,7 +322,35 @@ static int install_equiv_cpu_table(
      memcpy(mc_amd->equiv_cpu_table, mpbuf->data, mpbuf->len);
      mc_amd->equiv_cpu_table_size = mpbuf->len;
- *offset = mpbuf->len + 12; /* add header length */
+    return 0;
+}
+
+static int container_fast_forward(const void *data, size_t size_left, size_t 
*offset)
+{
+    size_t size;
+    const uint32_t *header;
+
+    while ( size_left )
+    {
+        if ( size_left < SECTION_HDR_SIZE )
+            return -EINVAL;
+
+        header = (const uint32_t *) (data + *offset);
And you again introduce another one here.

Fixed.

+    }
+
+    if ( !size_left )
+        return -EINVAL;
And btw, this check is kind of redundant with the size_left <
SECTION_HDR_SIZE one inside the loop: If you make the loop
header "for ( ; ; )", you won't need this extra if().

Fixed.

@@ -379,12 +464,48 @@ 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 )
+        /*
+         * 1. Given a situation where multiple containers exist and correct
+         *    patch lives on 1st container
+         * 2. We match equivalent ids using find_equiv_cpu_id() from the
+         *    earlier while() (On this case, matches on first container
+         *    file and we break)
+         * 3. Proceed to while ( (error = get_ucode_from_buffer_amd(mc_amd,
+         *                                  buf, bufsize,&offset)) == 0 )
+         * 4. Find correct patch using microcode_fits() and apply the patch
+         *    (Assume: apply_microcode() is successful)
+         * 5. The while() loop from (3) continues to parse the binary as
+         *    there is a subsequent container file, but...
+         * 6. returns -EINVAL as the condition
+         *    if ( mpbuf->type != UCODE_UCODE_TYPE ) evaluates to false.
+         * 7. A correct patch can only be on one container and not on any
+         *    subsequent ones. (Refer docs for more info) Therefore, we
+         *    don't have to parse a subsequent container. So, we can abort
+         *    the process here and discard this error value as we succeeded
+         *    already in patch update.
+         * 8. Since we need to return 0 for success, force error = 0.
+         */
Much better. One thing I'd like to avoid though is special casing the 1st
container in the description. Just refer to "some container other than
the last one" instead.

Okay.

+        if ( offset < bufsize )
+            error = 0;
+        else if ( save_error )
              error = save_error;
And with the comment having become precise, it is now more obvious
what's odd here: Flushing the error to zero should imo be done
conditionally upon the next thing following being a UCODE_MAGIC
rather than the much more generic "offset < bufsize".

Hmm. Yep.
I have been experimenting with this-
if ( offset + SECTION_HDR_SIZE <= bufsize &&
                   *(const uint32_t *)(buf + offset) == UCODE_MAGIC ) {
            printk("DEBUG: hit another container. breaking..\n");
            break;
        }

within the

while ( (error = get_ucode_from_buffer_amd(mc_amd, buf, bufsize,&offset)) == 0 )

loop and it seems to work fine. i.e, We can actually eliminate the need to workaround the corner cases as we pre-check (if that's the right word) for the occurrence of a subsequent container before the if ( mpbuf->type != UCODE_UCODE_TYPE ) check fails and returns -EINVAL.
This ensures that 'error' variable retains a success value (0)

I have tested this bit with both the edge cases and they work fine.
As a consequence, I'll re-word the comments.

Thanks,
-Aravind.

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.