mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH V2 0/2] x86/microcode/amd: early loading fixes
@ 2013-06-06 19:45 Jacob Shin
  2013-06-06 19:45 ` [PATCH V2 1/2] x86/microcode/amd: make find_ucode_in_initrd() __init Jacob Shin
  2013-06-06 19:45 ` [PATCH V2 2/2] x86/microcode/amd: allow multiple families' bin files appended together Jacob Shin
  0 siblings, 2 replies; 5+ messages in thread
From: Jacob Shin @ 2013-06-06 19:45 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Ingo Molnar, Thomas Gleixner, Yinghai Lu,
	Henrique de Moraes Holschuh, Borislav Petkov, Andreas Herrmann,
	x86, linux-kernel, Jacob Shin

This patchset addreses two problems with early loading on AMD.

First, feedback from Yinghai that find_ucode_in_initrd() should be
marked __init:
  https://lkml.org/lkml/2013/6/4/695

And second, feedback from Henrique that Intel early loading supports
multiple microcode firmware concatenated together, whereas the current
AMD implementation lacks this support:
  https://lkml.org/lkml/2013/5/31/4

V2:
* test for !initrd_start before using it
* use __pa() instead of __pa_nodebug() on AP load
* fixed calculation of start offset and size of the microcode container file

Jacob Shin (2):
  x86/microcode/amd: make find_ucode_in_initrd() __init
  x86/microcode/amd: allow multiple families' bin files appended
    together

 arch/x86/kernel/microcode_amd_early.c |  176 +++++++++++++++++++++++++--------
 1 file changed, 133 insertions(+), 43 deletions(-)

-- 
1.7.9.5



^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH V2 1/2] x86/microcode/amd: make find_ucode_in_initrd() __init
  2013-06-06 19:45 [PATCH V2 0/2] x86/microcode/amd: early loading fixes Jacob Shin
@ 2013-06-06 19:45 ` Jacob Shin
  2013-06-06 20:08   ` Yinghai Lu
  2013-06-06 19:45 ` [PATCH V2 2/2] x86/microcode/amd: allow multiple families' bin files appended together Jacob Shin
  1 sibling, 1 reply; 5+ messages in thread
From: Jacob Shin @ 2013-06-06 19:45 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Ingo Molnar, Thomas Gleixner, Yinghai Lu,
	Henrique de Moraes Holschuh, Borislav Petkov, Andreas Herrmann,
	x86, linux-kernel, Jacob Shin

Change find_ucode_in_initrd() to __init and only let BSP call it
during cold boot. This is the right thing to do because only BSP will
see initrd loaded by the boot loader. APs will offset into
initrd_start to find the microcode patch binary.

Reported-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Jacob Shin <jacob.shin@amd.com>
---
 arch/x86/kernel/microcode_amd_early.c |  110 +++++++++++++++++++++++----------
 1 file changed, 79 insertions(+), 31 deletions(-)

diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c
index 9618805..52f647d 100644
--- a/arch/x86/kernel/microcode_amd_early.c
+++ b/arch/x86/kernel/microcode_amd_early.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/earlycpio.h>
+#include <linux/initrd.h>
 
 #include <asm/cpu.h>
 #include <asm/setup.h>
@@ -16,40 +17,59 @@
 
 static bool ucode_loaded;
 static u32 ucode_new_rev;
+static unsigned long ucode_offset;
+static size_t ucode_size;
 
 /*
  * Microcode patch container file is prepended to the initrd in cpio format.
  * See Documentation/x86/early-microcode.txt
  */
-static __cpuinitdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
+static __initdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
 
-static struct cpio_data __cpuinit find_ucode_in_initrd(void)
+static struct cpio_data __init find_ucode_in_initrd(void)
 {
 	long offset = 0;
+	char *path;
+	void *start;
+	size_t size;
+	unsigned long *uoffset;
+	size_t *usize;
 	struct cpio_data cd;
 
 #ifdef CONFIG_X86_32
+	struct boot_params *p;
+
 	/*
 	 * On 32-bit, early load occurs before paging is turned on so we need
 	 * to use physical addresses.
 	 */
-	if (!(read_cr0() & X86_CR0_PG)) {
-		struct boot_params *p;
-		p  = (struct boot_params *)__pa_nodebug(&boot_params);
-		cd = find_cpio_data((char *)__pa_nodebug(ucode_path),
-			(void *)p->hdr.ramdisk_image, p->hdr.ramdisk_size,
-			&offset);
-	} else
+	p       = (struct boot_params *)__pa_nodebug(&boot_params);
+	path    = (char *)__pa_nodebug(ucode_path);
+	start   = (void *)p->hdr.ramdisk_image;
+	size    = p->hdr.ramdisk_size;
+	uoffset = (unsigned long *)__pa_nodebug(&ucode_offset);
+	usize   = (size_t *)__pa_nodebug(&ucode_size);
+#else
+	path    = ucode_path;
+	start   = (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET);
+	size    = boot_params.hdr.ramdisk_size;
+	uoffset = &ucode_offset;
+	usize   = &ucode_size;
 #endif
-		cd = find_cpio_data(ucode_path,
-			(void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET),
-			boot_params.hdr.ramdisk_size, &offset);
+
+	cd = find_cpio_data(path, start, size, &offset);
+	if (!cd.data)
+		return cd;
 
 	if (*(u32 *)cd.data != UCODE_MAGIC) {
 		cd.data = NULL;
 		cd.size = 0;
+		return cd;
 	}
 
+	*uoffset = (u8 *)cd.data - (u8 *)start;
+	*usize   = cd.size;
+
 	return cd;
 }
 
@@ -62,9 +82,8 @@ static struct cpio_data __cpuinit find_ucode_in_initrd(void)
  * load_microcode_amd() to save equivalent cpu table and microcode patches in
  * kernel heap memory.
  */
-static void __cpuinit apply_ucode_in_initrd(void)
+static void __cpuinit apply_ucode_in_initrd(void *ucode, size_t size)
 {
-	struct cpio_data cd;
 	struct equiv_cpu_entry *eq;
 	u32 *header;
 	u8  *data;
@@ -78,12 +97,9 @@ static void __cpuinit apply_ucode_in_initrd(void)
 #else
 	new_rev = &ucode_new_rev;
 #endif
-	cd = find_ucode_in_initrd();
-	if (!cd.data)
-		return;
 
-	data   = cd.data;
-	left   = cd.size;
+	data   = ucode;
+	left   = size;
 	header = (u32 *)data;
 
 	/* find equiv cpu table */
@@ -129,7 +145,11 @@ static void __cpuinit apply_ucode_in_initrd(void)
 
 void __init load_ucode_amd_bsp(void)
 {
-	apply_ucode_in_initrd();
+	struct cpio_data cd = find_ucode_in_initrd();
+	if (!cd.data)
+		return;
+
+	apply_ucode_in_initrd(cd.data, cd.size);
 }
 
 #ifdef CONFIG_X86_32
@@ -145,12 +165,29 @@ u8 amd_bsp_mpb[MPB_MAX_SIZE];
 void __cpuinit load_ucode_amd_ap(void)
 {
 	struct microcode_amd *mc;
+	unsigned long *initrd;
+	unsigned long *uoffset;
+	size_t *usize;
+	void *ucode;
 
-	mc = (struct microcode_amd *)__pa_nodebug(amd_bsp_mpb);
-	if (mc->hdr.patch_id && mc->hdr.processor_rev_id)
+	mc = (struct microcode_amd *)__pa(amd_bsp_mpb);
+	if (mc->hdr.patch_id && mc->hdr.processor_rev_id) {
 		__apply_microcode_amd(mc);
-	else
-		apply_ucode_in_initrd();
+		return;
+	}
+
+	initrd  = (unsigned long *)__pa(&initrd_start);
+	uoffset = (unsigned long *)__pa(&ucode_offset);
+	usize   = (size_t *)__pa(&ucode_size);
+
+	if (!(*usize))
+		return;
+
+	if (!(*initrd))
+		return;
+
+	ucode = (void *)((unsigned long)__pa(*initrd) + *uoffset);
+	apply_ucode_in_initrd(ucode, *usize);
 }
 
 static void __init collect_cpu_sig_on_bsp(void *arg)
@@ -181,8 +218,16 @@ void __cpuinit load_ucode_amd_ap(void)
 	collect_cpu_info_amd_early(&cpu_data(cpu), ucode_cpu_info + cpu);
 
 	if (cpu && !ucode_loaded) {
-		struct cpio_data cd = find_ucode_in_initrd();
-		if (load_microcode_amd(0, cd.data, cd.size) != UCODE_OK)
+		void *ucode;
+
+		if (!ucode_size)
+			return;
+
+		if (!initrd_start)
+			return;
+
+		ucode = (void *)(initrd_start + ucode_offset);
+		if (load_microcode_amd(0, ucode, ucode_size) != UCODE_OK)
 			return;
 		ucode_loaded = true;
 	}
@@ -194,7 +239,7 @@ void __cpuinit load_ucode_amd_ap(void)
 int __init save_microcode_in_initrd_amd(void)
 {
 	enum ucode_state ret;
-	struct cpio_data cd;
+	void *ucode;
 #ifdef CONFIG_X86_32
 	unsigned int bsp = boot_cpu_data.cpu_index;
 	struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
@@ -209,11 +254,14 @@ int __init save_microcode_in_initrd_amd(void)
 	if (ucode_loaded)
 		return 0;
 
-	cd = find_ucode_in_initrd();
-	if (!cd.data)
-		return -EINVAL;
+	if (!ucode_size)
+		return 0;
+
+	if (!initrd_start)
+		return 0;
 
-	ret = load_microcode_amd(0, cd.data, cd.size);
+	ucode = (void *)(initrd_start + ucode_offset);
+	ret = load_microcode_amd(0, ucode, ucode_size);
 	if (ret != UCODE_OK)
 		return -EINVAL;
 
-- 
1.7.9.5



^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH V2 2/2] x86/microcode/amd: allow multiple families' bin files appended together
  2013-06-06 19:45 [PATCH V2 0/2] x86/microcode/amd: early loading fixes Jacob Shin
  2013-06-06 19:45 ` [PATCH V2 1/2] x86/microcode/amd: make find_ucode_in_initrd() __init Jacob Shin
@ 2013-06-06 19:45 ` Jacob Shin
  1 sibling, 0 replies; 5+ messages in thread
From: Jacob Shin @ 2013-06-06 19:45 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Ingo Molnar, Thomas Gleixner, Yinghai Lu,
	Henrique de Moraes Holschuh, Borislav Petkov, Andreas Herrmann,
	x86, linux-kernel, Jacob Shin

Add support for parsing through multiple families' 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 |   68 +++++++++++++++++++++++++++------
 1 file changed, 56 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c
index 52f647d..bf91feb 100644
--- a/arch/x86/kernel/microcode_amd_early.c
+++ b/arch/x86/kernel/microcode_amd_early.c
@@ -87,15 +87,21 @@ static void __cpuinit apply_ucode_in_initrd(void *ucode, size_t size)
 	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;
+	unsigned long *uoffset;
+	size_t *usize;
 
 #ifdef CONFIG_X86_32
 	new_rev = (u32 *)__pa_nodebug(&ucode_new_rev);
+	uoffset = (unsigned long *)__pa_nodebug(&ucode_offset);
+	usize   = (size_t *)__pa_nodebug(&ucode_size);
 #else
 	new_rev = &ucode_new_rev;
+	uoffset = &ucode_offset;
+	usize   = &ucode_size;
 #endif
 
 	data   = ucode;
@@ -108,18 +114,50 @@ static void __cpuinit apply_ucode_in_initrd(void *ucode, size_t size)
 	    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, cpuid_eax(0x00000001));
-	if (!eq_id)
+		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;
+		}
+
+		/* mark where the next microcode container file starts */
+		offset    = data - (u8 *)ucode;
+		*uoffset += offset;
+		*usize   -= offset;
+		ucode     = data;
+	}
+
+	if (!eq_id) {
+		*usize = 0;
 		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;
@@ -132,15 +170,21 @@ static void __cpuinit apply_ucode_in_initrd(void *ucode, size_t size)
 		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;
-				break;
+				rev = mc->hdr.patch_id;
+				*new_rev = rev;
 			}
 
 		offset  = header[1] + SECTION_HDR_SIZE;
 		data   += offset;
 		left   -= offset;
 	}
+
+	/* mark where this microcode container file ends */
+	offset  = *usize - (data - (u8 *)ucode);
+	*usize -= offset;
+
+	if (!(*new_rev))
+		*usize = 0;
 }
 
 void __init load_ucode_amd_bsp(void)
-- 
1.7.9.5



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH V2 1/2] x86/microcode/amd: make find_ucode_in_initrd() __init
  2013-06-06 19:45 ` [PATCH V2 1/2] x86/microcode/amd: make find_ucode_in_initrd() __init Jacob Shin
@ 2013-06-06 20:08   ` Yinghai Lu
  2013-06-06 20:11     ` H. Peter Anvin
  0 siblings, 1 reply; 5+ messages in thread
From: Yinghai Lu @ 2013-06-06 20:08 UTC (permalink / raw)
  To: Jacob Shin
  Cc: H. Peter Anvin, Ingo Molnar, Thomas Gleixner,
	Henrique de Moraes Holschuh, Borislav Petkov, Andreas Herrmann,
	the arch/x86 maintainers, Linux Kernel Mailing List

On Thu, Jun 6, 2013 at 12:45 PM, Jacob Shin <jacob.shin@amd.com> wrote:
> Change find_ucode_in_initrd() to __init and only let BSP call it
> during cold boot. This is the right thing to do because only BSP will
> see initrd loaded by the boot loader. APs will offset into
> initrd_start to find the microcode patch binary.
>
> Reported-by: Yinghai Lu <yinghai@kernel.org>
> Signed-off-by: Jacob Shin <jacob.shin@amd.com>
> ---
>  arch/x86/kernel/microcode_amd_early.c |  110 +++++++++++++++++++++++----------
>  1 file changed, 79 insertions(+), 31 deletions(-)
>
> diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c
> index 9618805..52f647d 100644
> --- a/arch/x86/kernel/microcode_amd_early.c
> +++ b/arch/x86/kernel/microcode_amd_early.c
> @@ -9,6 +9,7 @@
>   */
>
>  #include <linux/earlycpio.h>
> +#include <linux/initrd.h>
>
>  #include <asm/cpu.h>
>  #include <asm/setup.h>
> @@ -16,40 +17,59 @@
>
>  static bool ucode_loaded;
>  static u32 ucode_new_rev;
> +static unsigned long ucode_offset;
> +static size_t ucode_size;
>
>  /*
>   * Microcode patch container file is prepended to the initrd in cpio format.
>   * See Documentation/x86/early-microcode.txt
>   */
> -static __cpuinitdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
> +static __initdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
>
> -static struct cpio_data __cpuinit find_ucode_in_initrd(void)
> +static struct cpio_data __init find_ucode_in_initrd(void)
>  {
>         long offset = 0;
> +       char *path;
> +       void *start;
> +       size_t size;
> +       unsigned long *uoffset;
> +       size_t *usize;
>         struct cpio_data cd;
>
>  #ifdef CONFIG_X86_32
> +       struct boot_params *p;
> +
>         /*
>          * On 32-bit, early load occurs before paging is turned on so we need
>          * to use physical addresses.
>          */
> -       if (!(read_cr0() & X86_CR0_PG)) {
> -               struct boot_params *p;
> -               p  = (struct boot_params *)__pa_nodebug(&boot_params);
> -               cd = find_cpio_data((char *)__pa_nodebug(ucode_path),
> -                       (void *)p->hdr.ramdisk_image, p->hdr.ramdisk_size,
> -                       &offset);
> -       } else
> +       p       = (struct boot_params *)__pa_nodebug(&boot_params);
> +       path    = (char *)__pa_nodebug(ucode_path);
> +       start   = (void *)p->hdr.ramdisk_image;
> +       size    = p->hdr.ramdisk_size;
> +       uoffset = (unsigned long *)__pa_nodebug(&ucode_offset);
> +       usize   = (size_t *)__pa_nodebug(&ucode_size);
> +#else
> +       path    = ucode_path;
> +       start   = (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET);
> +       size    = boot_params.hdr.ramdisk_size;
> +       uoffset = &ucode_offset;
> +       usize   = &ucode_size;
>  #endif
> -               cd = find_cpio_data(ucode_path,
> -                       (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET),
> -                       boot_params.hdr.ramdisk_size, &offset);
> +
> +       cd = find_cpio_data(path, start, size, &offset);
> +       if (!cd.data)
> +               return cd;
>
>         if (*(u32 *)cd.data != UCODE_MAGIC) {
>                 cd.data = NULL;
>                 cd.size = 0;
> +               return cd;
>         }
>
> +       *uoffset = (u8 *)cd.data - (u8 *)start;
> +       *usize   = cd.size;
> +
>         return cd;
>  }
>
> @@ -62,9 +82,8 @@ static struct cpio_data __cpuinit find_ucode_in_initrd(void)
>   * load_microcode_amd() to save equivalent cpu table and microcode patches in
>   * kernel heap memory.
>   */
> -static void __cpuinit apply_ucode_in_initrd(void)
> +static void __cpuinit apply_ucode_in_initrd(void *ucode, size_t size)
>  {
> -       struct cpio_data cd;
>         struct equiv_cpu_entry *eq;
>         u32 *header;
>         u8  *data;
> @@ -78,12 +97,9 @@ static void __cpuinit apply_ucode_in_initrd(void)
>  #else
>         new_rev = &ucode_new_rev;
>  #endif
> -       cd = find_ucode_in_initrd();
> -       if (!cd.data)
> -               return;
>
> -       data   = cd.data;
> -       left   = cd.size;
> +       data   = ucode;
> +       left   = size;
>         header = (u32 *)data;
>
>         /* find equiv cpu table */
> @@ -129,7 +145,11 @@ static void __cpuinit apply_ucode_in_initrd(void)
>
>  void __init load_ucode_amd_bsp(void)
>  {
> -       apply_ucode_in_initrd();
> +       struct cpio_data cd = find_ucode_in_initrd();
> +       if (!cd.data)
> +               return;
> +
> +       apply_ucode_in_initrd(cd.data, cd.size);
>  }
>
>  #ifdef CONFIG_X86_32
> @@ -145,12 +165,29 @@ u8 amd_bsp_mpb[MPB_MAX_SIZE];
>  void __cpuinit load_ucode_amd_ap(void)
>  {
>         struct microcode_amd *mc;
> +       unsigned long *initrd;
> +       unsigned long *uoffset;
> +       size_t *usize;
> +       void *ucode;
>
> -       mc = (struct microcode_amd *)__pa_nodebug(amd_bsp_mpb);
> -       if (mc->hdr.patch_id && mc->hdr.processor_rev_id)
> +       mc = (struct microcode_amd *)__pa(amd_bsp_mpb);
> +       if (mc->hdr.patch_id && mc->hdr.processor_rev_id) {
>                 __apply_microcode_amd(mc);
> -       else
> -               apply_ucode_in_initrd();
> +               return;
> +       }
> +
> +       initrd  = (unsigned long *)__pa(&initrd_start);
> +       uoffset = (unsigned long *)__pa(&ucode_offset);
> +       usize   = (size_t *)__pa(&ucode_size);
> +
> +       if (!(*usize))
> +               return;
> +
> +       if (!(*initrd))
> +               return;

could be save three lines if use
       if (!(*initrd) || !(*usize))
               return;

> +
> +       ucode = (void *)((unsigned long)__pa(*initrd) + *uoffset);
> +       apply_ucode_in_initrd(ucode, *usize);
>  }
>
>  static void __init collect_cpu_sig_on_bsp(void *arg)
> @@ -181,8 +218,16 @@ void __cpuinit load_ucode_amd_ap(void)
>         collect_cpu_info_amd_early(&cpu_data(cpu), ucode_cpu_info + cpu);
>
>         if (cpu && !ucode_loaded) {
> -               struct cpio_data cd = find_ucode_in_initrd();
> -               if (load_microcode_amd(0, cd.data, cd.size) != UCODE_OK)
> +               void *ucode;
> +
> +               if (!ucode_size)
> +                       return;
> +
> +               if (!initrd_start)
> +                       return;

same

> +
> +               ucode = (void *)(initrd_start + ucode_offset);
> +               if (load_microcode_amd(0, ucode, ucode_size) != UCODE_OK)
>                         return;
>                 ucode_loaded = true;
>         }
> @@ -194,7 +239,7 @@ void __cpuinit load_ucode_amd_ap(void)
>  int __init save_microcode_in_initrd_amd(void)
>  {
>         enum ucode_state ret;
> -       struct cpio_data cd;
> +       void *ucode;
>  #ifdef CONFIG_X86_32
>         unsigned int bsp = boot_cpu_data.cpu_index;
>         struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
> @@ -209,11 +254,14 @@ int __init save_microcode_in_initrd_amd(void)
>         if (ucode_loaded)
>                 return 0;
>
> -       cd = find_ucode_in_initrd();
> -       if (!cd.data)
> -               return -EINVAL;
> +       if (!ucode_size)
> +               return 0;
> +
> +       if (!initrd_start)
> +               return 0;

same

>
> -       ret = load_microcode_amd(0, cd.data, cd.size);
> +       ucode = (void *)(initrd_start + ucode_offset);
> +       ret = load_microcode_amd(0, ucode, ucode_size);
>         if (ret != UCODE_OK)
>                 return -EINVAL;
>
> --
> 1.7.9.5
>
>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH V2 1/2] x86/microcode/amd: make find_ucode_in_initrd() __init
  2013-06-06 20:08   ` Yinghai Lu
@ 2013-06-06 20:11     ` H. Peter Anvin
  0 siblings, 0 replies; 5+ messages in thread
From: H. Peter Anvin @ 2013-06-06 20:11 UTC (permalink / raw)
  To: Yinghai Lu, Jacob Shin
  Cc: Ingo Molnar, Thomas Gleixner, Henrique de Moraes Holschuh,
	Borislav Petkov, Andreas Herrmann, the arch/x86 maintainers,
	Linux Kernel Mailing List

The parentheses are redundant too.

Yinghai Lu <yinghai@kernel.org> wrote:

>On Thu, Jun 6, 2013 at 12:45 PM, Jacob Shin <jacob.shin@amd.com> wrote:
>> Change find_ucode_in_initrd() to __init and only let BSP call it
>> during cold boot. This is the right thing to do because only BSP will
>> see initrd loaded by the boot loader. APs will offset into
>> initrd_start to find the microcode patch binary.
>>
>> Reported-by: Yinghai Lu <yinghai@kernel.org>
>> Signed-off-by: Jacob Shin <jacob.shin@amd.com>
>> ---
>>  arch/x86/kernel/microcode_amd_early.c |  110
>+++++++++++++++++++++++----------
>>  1 file changed, 79 insertions(+), 31 deletions(-)
>>
>> diff --git a/arch/x86/kernel/microcode_amd_early.c
>b/arch/x86/kernel/microcode_amd_early.c
>> index 9618805..52f647d 100644
>> --- a/arch/x86/kernel/microcode_amd_early.c
>> +++ b/arch/x86/kernel/microcode_amd_early.c
>> @@ -9,6 +9,7 @@
>>   */
>>
>>  #include <linux/earlycpio.h>
>> +#include <linux/initrd.h>
>>
>>  #include <asm/cpu.h>
>>  #include <asm/setup.h>
>> @@ -16,40 +17,59 @@
>>
>>  static bool ucode_loaded;
>>  static u32 ucode_new_rev;
>> +static unsigned long ucode_offset;
>> +static size_t ucode_size;
>>
>>  /*
>>   * Microcode patch container file is prepended to the initrd in cpio
>format.
>>   * See Documentation/x86/early-microcode.txt
>>   */
>> -static __cpuinitdata char ucode_path[] =
>"kernel/x86/microcode/AuthenticAMD.bin";
>> +static __initdata char ucode_path[] =
>"kernel/x86/microcode/AuthenticAMD.bin";
>>
>> -static struct cpio_data __cpuinit find_ucode_in_initrd(void)
>> +static struct cpio_data __init find_ucode_in_initrd(void)
>>  {
>>         long offset = 0;
>> +       char *path;
>> +       void *start;
>> +       size_t size;
>> +       unsigned long *uoffset;
>> +       size_t *usize;
>>         struct cpio_data cd;
>>
>>  #ifdef CONFIG_X86_32
>> +       struct boot_params *p;
>> +
>>         /*
>>          * On 32-bit, early load occurs before paging is turned on so
>we need
>>          * to use physical addresses.
>>          */
>> -       if (!(read_cr0() & X86_CR0_PG)) {
>> -               struct boot_params *p;
>> -               p  = (struct boot_params
>*)__pa_nodebug(&boot_params);
>> -               cd = find_cpio_data((char *)__pa_nodebug(ucode_path),
>> -                       (void *)p->hdr.ramdisk_image,
>p->hdr.ramdisk_size,
>> -                       &offset);
>> -       } else
>> +       p       = (struct boot_params *)__pa_nodebug(&boot_params);
>> +       path    = (char *)__pa_nodebug(ucode_path);
>> +       start   = (void *)p->hdr.ramdisk_image;
>> +       size    = p->hdr.ramdisk_size;
>> +       uoffset = (unsigned long *)__pa_nodebug(&ucode_offset);
>> +       usize   = (size_t *)__pa_nodebug(&ucode_size);
>> +#else
>> +       path    = ucode_path;
>> +       start   = (void *)(boot_params.hdr.ramdisk_image +
>PAGE_OFFSET);
>> +       size    = boot_params.hdr.ramdisk_size;
>> +       uoffset = &ucode_offset;
>> +       usize   = &ucode_size;
>>  #endif
>> -               cd = find_cpio_data(ucode_path,
>> -                       (void *)(boot_params.hdr.ramdisk_image +
>PAGE_OFFSET),
>> -                       boot_params.hdr.ramdisk_size, &offset);
>> +
>> +       cd = find_cpio_data(path, start, size, &offset);
>> +       if (!cd.data)
>> +               return cd;
>>
>>         if (*(u32 *)cd.data != UCODE_MAGIC) {
>>                 cd.data = NULL;
>>                 cd.size = 0;
>> +               return cd;
>>         }
>>
>> +       *uoffset = (u8 *)cd.data - (u8 *)start;
>> +       *usize   = cd.size;
>> +
>>         return cd;
>>  }
>>
>> @@ -62,9 +82,8 @@ static struct cpio_data __cpuinit
>find_ucode_in_initrd(void)
>>   * load_microcode_amd() to save equivalent cpu table and microcode
>patches in
>>   * kernel heap memory.
>>   */
>> -static void __cpuinit apply_ucode_in_initrd(void)
>> +static void __cpuinit apply_ucode_in_initrd(void *ucode, size_t
>size)
>>  {
>> -       struct cpio_data cd;
>>         struct equiv_cpu_entry *eq;
>>         u32 *header;
>>         u8  *data;
>> @@ -78,12 +97,9 @@ static void __cpuinit apply_ucode_in_initrd(void)
>>  #else
>>         new_rev = &ucode_new_rev;
>>  #endif
>> -       cd = find_ucode_in_initrd();
>> -       if (!cd.data)
>> -               return;
>>
>> -       data   = cd.data;
>> -       left   = cd.size;
>> +       data   = ucode;
>> +       left   = size;
>>         header = (u32 *)data;
>>
>>         /* find equiv cpu table */
>> @@ -129,7 +145,11 @@ static void __cpuinit
>apply_ucode_in_initrd(void)
>>
>>  void __init load_ucode_amd_bsp(void)
>>  {
>> -       apply_ucode_in_initrd();
>> +       struct cpio_data cd = find_ucode_in_initrd();
>> +       if (!cd.data)
>> +               return;
>> +
>> +       apply_ucode_in_initrd(cd.data, cd.size);
>>  }
>>
>>  #ifdef CONFIG_X86_32
>> @@ -145,12 +165,29 @@ u8 amd_bsp_mpb[MPB_MAX_SIZE];
>>  void __cpuinit load_ucode_amd_ap(void)
>>  {
>>         struct microcode_amd *mc;
>> +       unsigned long *initrd;
>> +       unsigned long *uoffset;
>> +       size_t *usize;
>> +       void *ucode;
>>
>> -       mc = (struct microcode_amd *)__pa_nodebug(amd_bsp_mpb);
>> -       if (mc->hdr.patch_id && mc->hdr.processor_rev_id)
>> +       mc = (struct microcode_amd *)__pa(amd_bsp_mpb);
>> +       if (mc->hdr.patch_id && mc->hdr.processor_rev_id) {
>>                 __apply_microcode_amd(mc);
>> -       else
>> -               apply_ucode_in_initrd();
>> +               return;
>> +       }
>> +
>> +       initrd  = (unsigned long *)__pa(&initrd_start);
>> +       uoffset = (unsigned long *)__pa(&ucode_offset);
>> +       usize   = (size_t *)__pa(&ucode_size);
>> +
>> +       if (!(*usize))
>> +               return;
>> +
>> +       if (!(*initrd))
>> +               return;
>
>could be save three lines if use
>       if (!(*initrd) || !(*usize))
>               return;
>
>> +
>> +       ucode = (void *)((unsigned long)__pa(*initrd) + *uoffset);
>> +       apply_ucode_in_initrd(ucode, *usize);
>>  }
>>
>>  static void __init collect_cpu_sig_on_bsp(void *arg)
>> @@ -181,8 +218,16 @@ void __cpuinit load_ucode_amd_ap(void)
>>         collect_cpu_info_amd_early(&cpu_data(cpu), ucode_cpu_info +
>cpu);
>>
>>         if (cpu && !ucode_loaded) {
>> -               struct cpio_data cd = find_ucode_in_initrd();
>> -               if (load_microcode_amd(0, cd.data, cd.size) !=
>UCODE_OK)
>> +               void *ucode;
>> +
>> +               if (!ucode_size)
>> +                       return;
>> +
>> +               if (!initrd_start)
>> +                       return;
>
>same
>
>> +
>> +               ucode = (void *)(initrd_start + ucode_offset);
>> +               if (load_microcode_amd(0, ucode, ucode_size) !=
>UCODE_OK)
>>                         return;
>>                 ucode_loaded = true;
>>         }
>> @@ -194,7 +239,7 @@ void __cpuinit load_ucode_amd_ap(void)
>>  int __init save_microcode_in_initrd_amd(void)
>>  {
>>         enum ucode_state ret;
>> -       struct cpio_data cd;
>> +       void *ucode;
>>  #ifdef CONFIG_X86_32
>>         unsigned int bsp = boot_cpu_data.cpu_index;
>>         struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
>> @@ -209,11 +254,14 @@ int __init save_microcode_in_initrd_amd(void)
>>         if (ucode_loaded)
>>                 return 0;
>>
>> -       cd = find_ucode_in_initrd();
>> -       if (!cd.data)
>> -               return -EINVAL;
>> +       if (!ucode_size)
>> +               return 0;
>> +
>> +       if (!initrd_start)
>> +               return 0;
>
>same
>
>>
>> -       ret = load_microcode_amd(0, cd.data, cd.size);
>> +       ucode = (void *)(initrd_start + ucode_offset);
>> +       ret = load_microcode_amd(0, ucode, ucode_size);
>>         if (ret != UCODE_OK)
>>                 return -EINVAL;
>>
>> --
>> 1.7.9.5
>>
>>

-- 
Sent from my mobile phone. Please excuse brevity and lack of formatting.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2013-06-06 20:12 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-06 19:45 [PATCH V2 0/2] x86/microcode/amd: early loading fixes Jacob Shin
2013-06-06 19:45 ` [PATCH V2 1/2] x86/microcode/amd: make find_ucode_in_initrd() __init Jacob Shin
2013-06-06 20:08   ` Yinghai Lu
2013-06-06 20:11     ` H. Peter Anvin
2013-06-06 19:45 ` [PATCH V2 2/2] x86/microcode/amd: allow multiple families' bin files appended together Jacob Shin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®