x86/ucode: load microcode earlier on boot CPU

Call early_microcode_init() straight after multiboot modules become
accessible. Modify it to load the ucode directly from the blob bypassing
populating microcode_cache because xmalloc is still not available at
that point during Xen boot.

Introduce early_microcode_init_cache() for populating microcode_cache.
It needs to rescan the modules in order to find the new virtual address
of the ucode blob because it changes during the boot process, e.g.
from 0x00000000010802fc to 0xffff83204dac52fc.

While at it, drop alternative_vcall() from early_microcode_init() since
it's not useful in an __init fuction.

Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Sergey Dyasli authored and Andrew Cooper committed 2022-12-20 19:33:04 +00:00
1 parent 44a6871a5b
commit dc380df12a
4 files changed
+76 -26

No files matched your search

+63 -19
View File
@@ -27,6 +27,7 @@
#include <xen/err.h>
#include <xen/guest_access.h>
#include <xen/init.h>
#include <xen/multiboot.h>
#include <xen/param.h>
#include <xen/spinlock.h>
#include <xen/stop_machine.h>
@@ -198,7 +199,8 @@ void __init microcode_scan_module(
bootstrap_map(NULL);
}
}
void __init microcode_grab_module(
static void __init microcode_grab_module(
unsigned long *module_map,
const multiboot_info_t *mbi)
{
@@ -732,25 +734,11 @@ int microcode_update_one(void)
return microcode_update_cpu(NULL);
}
/* BSP calls this function to parse ucode blob and then apply an update. */
static int __init early_microcode_update_cpu(void)
static int __init early_update_cache(const void *data, size_t len)
{
int rc = 0;
const void *data = NULL;
size_t len;
struct microcode_patch *patch;
if ( ucode_blob.size )
{
len = ucode_blob.size;
data = ucode_blob.data;
}
else if ( ucode_mod.mod_end )
{
len = ucode_mod.mod_end;
data = bootstrap_map(&ucode_mod);
}
if ( !data )
return -ENOMEM;
@@ -770,10 +758,64 @@ static int __init early_microcode_update_cpu(void)
spin_unlock(&microcode_mutex);
ASSERT(rc);
return microcode_update_one();
return rc;
}
int __init early_microcode_init(void)
int __init microcode_init_cache(unsigned long *module_map,
const struct multiboot_info *mbi)
{
int rc = 0;
if ( ucode_scan )
/* Need to rescan the modules because they might have been relocated */
microcode_scan_module(module_map, mbi);
if ( ucode_mod.mod_end )
rc = early_update_cache(bootstrap_map(&ucode_mod),
ucode_mod.mod_end);
else if ( ucode_blob.size )
rc = early_update_cache(ucode_blob.data, ucode_blob.size);
return rc;
}
/* BSP calls this function to parse ucode blob and then apply an update. */
static int __init early_microcode_update_cpu(void)
{
const void *data = NULL;
size_t len;
struct microcode_patch *patch;
if ( ucode_blob.size )
{
len = ucode_blob.size;
data = ucode_blob.data;
}
else if ( ucode_mod.mod_end )
{
len = ucode_mod.mod_end;
data = bootstrap_map(&ucode_mod);
}
if ( !data )
return -ENOMEM;
patch = ucode_ops.cpu_request_microcode(data, len, false);
if ( IS_ERR(patch) )
{
printk(XENLOG_WARNING "Parsing microcode blob error %ld\n",
PTR_ERR(patch));
return PTR_ERR(patch);
}
if ( !patch )
return -ENOENT;
return microcode_update_cpu(patch);
}
int __init early_microcode_init(unsigned long *module_map,
const struct multiboot_info *mbi)
{
const struct cpuinfo_x86 *c = &boot_cpu_data;
int rc = 0;
@@ -797,7 +839,9 @@ int __init early_microcode_init(void)
return -ENODEV;
}
alternative_vcall(ucode_ops.collect_cpu_info);
microcode_grab_module(module_map, mbi);
ucode_ops.collect_cpu_info();
if ( ucode_mod.mod_end || ucode_blob.size )
rc = early_microcode_update_cpu();
+6 -1
View File
@@ -6,6 +6,8 @@
#include <public/xen.h>
struct multiboot_info;
struct cpu_signature {
/* CPU signature (CPUID.1.EAX). */
unsigned int sig;
@@ -21,7 +23,10 @@ DECLARE_PER_CPU(struct cpu_signature, cpu_sig);
void microcode_set_module(unsigned int idx);
int microcode_update(XEN_GUEST_HANDLE(const_void), unsigned long len);
int early_microcode_init(void);
int early_microcode_init(unsigned long *module_map,
const struct multiboot_info *mbi);
int microcode_init_cache(unsigned long *module_map,
const struct multiboot_info *mbi);
int microcode_update_one(void);
#endif /* ASM_X86__MICROCODE_H */
-3
View File
@@ -44,9 +44,6 @@ void *bootstrap_map(const module_t *mod);
int xen_in_range(unsigned long mfn);
void microcode_grab_module(
unsigned long *, const multiboot_info_t *);
extern uint8_t kbd_shift_flags;
#ifdef NDEBUG
+7 -3
View File
@@ -1173,6 +1173,12 @@ void __init noreturn __start_xen(unsigned long mbi_p)
mod[i].reserved = 0;
}
/*
* TODO: load ucode earlier once multiboot modules become accessible
* at an earlier stage.
*/
early_microcode_init(module_map, mbi);
if ( xen_phys_start )
{
relocated = true;
@@ -1755,11 +1761,9 @@ void __init noreturn __start_xen(unsigned long mbi_p)
init_IRQ();
microcode_grab_module(module_map, mbi);
timer_init();
early_microcode_init();
microcode_init_cache(module_map, mbi); /* Needs xmalloc() */
tsx_init(); /* Needs microcode. May change HLE/RTM feature bits. */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.