lkml.org 
[lkml]   [2013]   [May]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: [PATCH V3 4/4] microcode/x86/amd: early microcode patch loading support for AMD
On Fri, May 31, 2013 at 06:30:39PM -0300, Henrique de Moraes Holschuh wrote:
> On Fri, 31 May 2013, Andreas Herrmann wrote:
> > On Fri, May 31, 2013 at 01:26:49AM -0300, Henrique de Moraes Holschuh wrote:
> > > On Thu, 30 May 2013, Jacob Shin wrote:
> > > > mkdir initrd
> > > > cd initrd
> > > > -mkdir kernel
> > > > -mkdir kernel/x86
> > > > -mkdir kernel/x86/microcode
> > > > -cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin
> > > > -find .|cpio -oc >../ucode.cpio
> > > > +mkdir -p kernel/x86/microcode
> > > > +cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin (or AuthenticAMD.bin)
> > >
> > > Can I just
> > > 'cat /lib/firmware/amd-ucode/*bin >kernel/x86/microcode/AuthenticAMD.bin'
> > > to get a valid microcode container for all amd processors?
> > >
> > > The answer for Intel is "yes". I sure hope it is the same for AMD...
> >
> > No, this doesn't work for AMD.
> >
> > The container file includes a header section with information how to
> > map CPU F/M/S to microcode revisions provided with a container
> > file. Concatenating several container files will not create an
> > all-embracing header section.
> >
> > More details were available on the amd64.org web pages. But it seems
> > that the web site is not available anymore ...
>
> Well, this is a problem for userspace. Maybe the easier solution would be
> to make kernel/x86/microcode/AuthenticAMD a folder, and look for files there
> with names we can derivate from the ones used by the firmware interface (or
> even the same names)?
>
> The early-initramfs API easily allows this to be implemented...

Yeah, but since that will break symmetry with Intel's GenuineIntel.bin
file path, so I decided to add some more logic to early loading code
to be able to parse through multiple containers files concatanated
together.

Any thoughts on this Boris?

Patch below:

---8<---

From 40ba7f578e2abb83897f218e6577396a3852ad00 Mon Sep 17 00:00:00 2001
From: Jacob Shin <jacob.shin@amd.com>
Date: Fri, 31 May 2013 13:57:02 -0500
Subject: [PATCH 1/1] x86/microcode/amd: allow multiple family's bin files
appended together

Add support for parsing through multiple family's microcode patch
container binary files appended together when early loading. This is
already supported on Intel.

Reported-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Jacob Shin <jacob.shin@amd.com>
---
arch/x86/kernel/microcode_amd_early.c | 63 +++++++++++++++++++++++++++------
1 file changed, 53 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c
index 9618805..2426dab 100644
--- a/arch/x86/kernel/microcode_amd_early.c
+++ b/arch/x86/kernel/microcode_amd_early.c
@@ -16,6 +16,7 @@

static bool ucode_loaded;
static u32 ucode_new_rev;
+static int family_offset;

/*
* Microcode patch container file is prepended to the initrd in cpio format.
@@ -27,6 +28,7 @@ static struct cpio_data __cpuinit find_ucode_in_initrd(void)
{
long offset = 0;
struct cpio_data cd;
+ int *fam_offset = &family_offset;

#ifdef CONFIG_X86_32
/*
@@ -39,12 +41,18 @@ static struct cpio_data __cpuinit find_ucode_in_initrd(void)
cd = find_cpio_data((char *)__pa_nodebug(ucode_path),
(void *)p->hdr.ramdisk_image, p->hdr.ramdisk_size,
&offset);
+ fam_offset = (int *)__pa_nodebug(&family_offset);
} else
#endif
cd = find_cpio_data(ucode_path,
(void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET),
boot_params.hdr.ramdisk_size, &offset);

+ if (*fam_offset) {
+ cd.data = (u8 *)cd.data + *fam_offset;
+ cd.size -= *fam_offset;
+ }
+
if (*(u32 *)cd.data != UCODE_MAGIC) {
cd.data = NULL;
cd.size = 0;
@@ -68,15 +76,18 @@ static void __cpuinit apply_ucode_in_initrd(void)
struct equiv_cpu_entry *eq;
u32 *header;
u8 *data;
- u16 eq_id;
+ u16 eq_id = 0;
int offset, left;
- u32 rev, dummy;
+ u32 rev, eax;
u32 *new_rev;
+ int *fam_off;

#ifdef CONFIG_X86_32
new_rev = (u32 *)__pa_nodebug(&ucode_new_rev);
+ fam_off = (int *)__pa_nodebug(&family_offset);
#else
new_rev = &ucode_new_rev;
+ fam_off = &family_offset;
#endif
cd = find_ucode_in_initrd();
if (!cd.data)
@@ -92,18 +103,44 @@ static void __cpuinit apply_ucode_in_initrd(void)
header[2] == 0) /* size */
return;

- eq = (struct equiv_cpu_entry *)(data + CONTAINER_HDR_SZ);
- offset = header[2] + CONTAINER_HDR_SZ;
- data += offset;
- left -= offset;
+ eax = cpuid_eax(0x00000001);
+
+ while (left > 0) {
+ eq = (struct equiv_cpu_entry *)(data + CONTAINER_HDR_SZ);
+
+ offset = header[2] + CONTAINER_HDR_SZ;
+ data += offset;
+ left -= offset;
+
+ eq_id = find_equiv_id(eq, eax);
+ if (eq_id)
+ break;
+
+ /*
+ * support multiple container files appended together. if this
+ * one does not have a matching equivalent cpu entry, we fast
+ * forward to the next container file.
+ */
+ while (left > 0) {
+ header = (u32 *)data;
+ if (header[0] == UCODE_MAGIC &&
+ header[1] == UCODE_EQUIV_CPU_TABLE_TYPE)
+ break;
+
+ offset = header[1] + SECTION_HDR_SIZE;
+ data += offset;
+ left -= offset;
+ }
+
+ *fam_off = data - (u8 *)cd.data;
+ }

- eq_id = find_equiv_id(eq, cpuid_eax(0x00000001));
if (!eq_id)
return;

/* find ucode and update if needed */

- rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+ rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);

while (left > 0) {
struct microcode_amd *mc;
@@ -116,8 +153,11 @@ static void __cpuinit apply_ucode_in_initrd(void)
mc = (struct microcode_amd *)(data + SECTION_HDR_SIZE);
if (eq_id == mc->hdr.processor_rev_id && rev < mc->hdr.patch_id)
if (__apply_microcode_amd(mc) == 0) {
- if (!(*new_rev))
- *new_rev = mc->hdr.patch_id;
+#ifdef CONFIG_X86_32
+ u8 *mpb = (u8 *)__pa_nodebug(&amd_bsp_mpb);
+ memcpy(mpb, mc, header[1]);
+#endif
+ *new_rev = mc->hdr.patch_id;
break;
}

@@ -182,6 +222,9 @@ void __cpuinit load_ucode_amd_ap(void)

if (cpu && !ucode_loaded) {
struct cpio_data cd = find_ucode_in_initrd();
+ if (!cd.data)
+ return;
+
if (load_microcode_amd(0, cd.data, cd.size) != UCODE_OK)
return;
ucode_loaded = true;
--
1.7.9.5



\
 
 \ /
  Last update: 2013-06-01 03:41    [W:0.079 / U:1.840 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site