Skip to content

Commit

Permalink
x86/microcode/AMD: Change load_microcode_amd()'s param to bool to fix…
Browse files Browse the repository at this point in the history
… preemptibility bug

commit dac6ca2 upstream.

With CONFIG_DEBUG_PREEMPT enabled, I get:

  BUG: using smp_processor_id() in preemptible [00000000] code: swapper/0/1
  caller is debug_smp_processor_id
  CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.12.0-rc2+ open-power-host-os#2
  Call Trace:
   dump_stack
   check_preemption_disabled
   debug_smp_processor_id
   save_microcode_in_initrd_amd
   ? microcode_init
   save_microcode_in_initrd
   ...

because, well, it says it above, we're using smp_processor_id() in
preemptible code.

But passing the CPU number is not really needed. It is only used to
determine whether we're on the BSP, and, if so, to save the microcode
patch for early loading.

 [ We don't absolutely need to do it on the BSP but we do that
   customarily there. ]

Instead, convert that function parameter to a boolean which denotes
whether the patch should be saved or not, thereby avoiding the use of
smp_processor_id() in preemptible code.

Signed-off-by: Borislav Petkov <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
[arnd: rebased to 4.9, after running into warning:
 arch/x86/kernel/cpu/microcode/amd.c:881:30: self-comparison always evaluates to true]
Signed-off-by: Arnd Bergmann <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
suryasaimadhu authored and gregkh committed Feb 25, 2018
1 parent 353727e commit 1acf767
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 7 deletions.
1 change: 0 additions & 1 deletion arch/x86/include/asm/microcode_amd.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,

extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
extern int apply_microcode_amd(int cpu);
extern enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size);

#define PATCH_MAX_SIZE PAGE_SIZE

Expand Down
17 changes: 11 additions & 6 deletions arch/x86/kernel/cpu/microcode/amd.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ static size_t compute_container_size(u8 *data, u32 total_size)
return size;
}

static enum ucode_state
load_microcode_amd(bool save, u8 family, const u8 *data, size_t size);

/*
* Early load occurs before we can vmalloc(). So we look for the microcode
* patch container file in initrd, traverse equivalent cpu table, look for a
Expand Down Expand Up @@ -451,7 +454,7 @@ int __init save_microcode_in_initrd_amd(void)
eax = cpuid_eax(0x00000001);
eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);

ret = load_microcode_amd(smp_processor_id(), eax, container, container_size);
ret = load_microcode_amd(true, eax, container, container_size);
if (ret != UCODE_OK)
retval = -EINVAL;

Expand Down Expand Up @@ -864,7 +867,8 @@ static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
return UCODE_OK;
}

enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size)
static enum ucode_state
load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
{
enum ucode_state ret;

Expand All @@ -878,8 +882,8 @@ enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, size_t s

#ifdef CONFIG_X86_32
/* save BSP's matching patch for early load */
if (cpu_data(cpu).cpu_index == boot_cpu_data.cpu_index) {
struct ucode_patch *p = find_patch(cpu);
if (save) {
struct ucode_patch *p = find_patch(0);
if (p) {
memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data),
Expand Down Expand Up @@ -911,11 +915,12 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
{
char fw_name[36] = "amd-ucode/microcode_amd.bin";
struct cpuinfo_x86 *c = &cpu_data(cpu);
bool bsp = c->cpu_index == boot_cpu_data.cpu_index;
enum ucode_state ret = UCODE_NFOUND;
const struct firmware *fw;

/* reload ucode container only on the boot cpu */
if (!refresh_fw || c->cpu_index != boot_cpu_data.cpu_index)
if (!refresh_fw || !bsp)
return UCODE_OK;

if (c->x86 >= 0x15)
Expand All @@ -932,7 +937,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
goto fw_release;
}

ret = load_microcode_amd(cpu, c->x86, fw->data, fw->size);
ret = load_microcode_amd(bsp, c->x86, fw->data, fw->size);

fw_release:
release_firmware(fw);
Expand Down

0 comments on commit 1acf767

Please sign in to comment.