mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-26 04:16:39 +00:00
- Fix mixed steppings support on AMD which got broken somewhere along
the way - Improve revision reporting - Properly check CPUID capabilities after late microcode upgrade to avoid false positives - A garden variety of other small fixes -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEzv7L6UO9uDPlPSfHEsHwGGHeVUoFAmPzs/sACgkQEsHwGGHe VUonGw//RgIVCZIkuytiZesFsAXD3sn4Mmji7WoRZvu3XooA0idOo+7ujBeNcJGw aFGjf0K5b7eAfiREqTXPlFSymPid7aN+7cPJD7iURJ5UEoDXca1vVh9Jeq7lhvRL M5CErroStya17vFqU5pz50EcUwGcao/N3wY+0rERk8Rkqu864PgI+KahS2V2D2PU XolD4CH/+JZMAJPaTG5dSkSf3gJevW/owZ+F2oqKKYNlFsQ6aYd/JZYwIQ2X7W9T HdVYzeASZs0tfBEPOsZUSobmIlqUU/MziefDyUuTYbO1DPJ525787RLpRyubhG9k b/7DWUNymR56B8AUq/RV6YE/Dw2YpcrP3Eu0pSbD5xUfEy8eFCcIr+cUL5M9+I4W iCZtYYGypNbDQf5NRkubtQu8xIwEbjOZNv444kMMBimZGzt/WDEGMHqgRbKpJ2MQ F2HoBnNVC5O2BddS0ErTpQDWK8B/c0+S4L1ZTkbh/y9CNhzITZ10sLAEGQawvBEk PBYeCQ98m72ijLcecz0vvVO81UHGicqyY86OqeqRx0FbGO9cZJg+8BqyTLxsRTSW OgxtB/moURdanWAAOdxZ91yUw40CYWn7qXhYxilZDtGgkFT6sUdA126uMxLJ8u2v WiOHmj/ymszHhkJiahcSMaD8gRFnLQ59jNatHNa/5Jyw0mi330g= =z8rd -----END PGP SIGNATURE----- Merge tag 'x86_microcode_for_v6.3_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull x86 microcode loader updates from Borislav Petkov: - Fix mixed steppings support on AMD which got broken somewhere along the way - Improve revision reporting - Properly check CPUID capabilities after late microcode upgrade to avoid false positives - A garden variety of other small fixes * tag 'x86_microcode_for_v6.3_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/microcode/core: Return an error only when necessary x86/microcode/AMD: Fix mixed steppings support x86/microcode/AMD: Add a @cpu parameter to the reloading functions x86/microcode/amd: Remove load_microcode_amd()'s bsp parameter x86/microcode: Allow only "1" as a late reload trigger value x86/microcode/intel: Print old and new revision during early boot x86/microcode/intel: Pass the microcode revision to print_ucode_info() directly x86/microcode: Adjust late loading result reporting message x86/microcode: Check CPU capabilities after late microcode update correctly x86/microcode: Add a parameter to microcode_check() to store CPU capabilities x86/microcode: Use the DEVICE_ATTR_RO() macro x86/microcode/AMD: Handle multiple glued containers properly x86/microcode/AMD: Rename a couple of functions
This commit is contained in:
commit
efebca0ba9
7 changed files with 117 additions and 104 deletions
|
@ -125,13 +125,13 @@ static inline unsigned int x86_cpuid_family(void)
|
|||
#ifdef CONFIG_MICROCODE
|
||||
extern void __init load_ucode_bsp(void);
|
||||
extern void load_ucode_ap(void);
|
||||
void reload_early_microcode(void);
|
||||
void reload_early_microcode(unsigned int cpu);
|
||||
extern bool initrd_gone;
|
||||
void microcode_bsp_resume(void);
|
||||
#else
|
||||
static inline void __init load_ucode_bsp(void) { }
|
||||
static inline void load_ucode_ap(void) { }
|
||||
static inline void reload_early_microcode(void) { }
|
||||
static inline void reload_early_microcode(unsigned int cpu) { }
|
||||
static inline void microcode_bsp_resume(void) { }
|
||||
#endif
|
||||
|
||||
|
|
|
@ -47,12 +47,12 @@ struct microcode_amd {
|
|||
extern void __init load_ucode_amd_bsp(unsigned int family);
|
||||
extern void load_ucode_amd_ap(unsigned int family);
|
||||
extern int __init save_microcode_in_initrd_amd(unsigned int family);
|
||||
void reload_ucode_amd(void);
|
||||
void reload_ucode_amd(unsigned int cpu);
|
||||
#else
|
||||
static inline void __init load_ucode_amd_bsp(unsigned int family) {}
|
||||
static inline void load_ucode_amd_ap(unsigned int family) {}
|
||||
static inline int __init
|
||||
save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
|
||||
static inline void reload_ucode_amd(void) {}
|
||||
static inline void reload_ucode_amd(unsigned int cpu) {}
|
||||
#endif
|
||||
#endif /* _ASM_X86_MICROCODE_AMD_H */
|
||||
|
|
|
@ -697,7 +697,8 @@ bool xen_set_default_idle(void);
|
|||
#endif
|
||||
|
||||
void __noreturn stop_this_cpu(void *dummy);
|
||||
void microcode_check(void);
|
||||
void microcode_check(struct cpuinfo_x86 *prev_info);
|
||||
void store_cpu_caps(struct cpuinfo_x86 *info);
|
||||
|
||||
enum l1tf_mitigations {
|
||||
L1TF_MITIGATION_OFF,
|
||||
|
|
|
@ -2302,30 +2302,45 @@ void cpu_init_secondary(void)
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_MICROCODE_LATE_LOADING
|
||||
/*
|
||||
/**
|
||||
* store_cpu_caps() - Store a snapshot of CPU capabilities
|
||||
* @curr_info: Pointer where to store it
|
||||
*
|
||||
* Returns: None
|
||||
*/
|
||||
void store_cpu_caps(struct cpuinfo_x86 *curr_info)
|
||||
{
|
||||
/* Reload CPUID max function as it might've changed. */
|
||||
curr_info->cpuid_level = cpuid_eax(0);
|
||||
|
||||
/* Copy all capability leafs and pick up the synthetic ones. */
|
||||
memcpy(&curr_info->x86_capability, &boot_cpu_data.x86_capability,
|
||||
sizeof(curr_info->x86_capability));
|
||||
|
||||
/* Get the hardware CPUID leafs */
|
||||
get_cpu_cap(curr_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* microcode_check() - Check if any CPU capabilities changed after an update.
|
||||
* @prev_info: CPU capabilities stored before an update.
|
||||
*
|
||||
* The microcode loader calls this upon late microcode load to recheck features,
|
||||
* only when microcode has been updated. Caller holds microcode_mutex and CPU
|
||||
* hotplug lock.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void microcode_check(void)
|
||||
void microcode_check(struct cpuinfo_x86 *prev_info)
|
||||
{
|
||||
struct cpuinfo_x86 info;
|
||||
struct cpuinfo_x86 curr_info;
|
||||
|
||||
perf_check_microcode();
|
||||
|
||||
/* Reload CPUID max function as it might've changed. */
|
||||
info.cpuid_level = cpuid_eax(0);
|
||||
store_cpu_caps(&curr_info);
|
||||
|
||||
/*
|
||||
* Copy all capability leafs to pick up the synthetic ones so that
|
||||
* memcmp() below doesn't fail on that. The ones coming from CPUID will
|
||||
* get overwritten in get_cpu_cap().
|
||||
*/
|
||||
memcpy(&info.x86_capability, &boot_cpu_data.x86_capability, sizeof(info.x86_capability));
|
||||
|
||||
get_cpu_cap(&info);
|
||||
|
||||
if (!memcmp(&info.x86_capability, &boot_cpu_data.x86_capability, sizeof(info.x86_capability)))
|
||||
if (!memcmp(&prev_info->x86_capability, &curr_info.x86_capability,
|
||||
sizeof(prev_info->x86_capability)))
|
||||
return;
|
||||
|
||||
pr_warn("x86/CPU: CPU features have changed after loading microcode, but might not take effect.\n");
|
||||
|
|
|
@ -55,7 +55,9 @@ struct cont_desc {
|
|||
};
|
||||
|
||||
static u32 ucode_new_rev;
|
||||
static u8 amd_ucode_patch[PATCH_MAX_SIZE];
|
||||
|
||||
/* One blob per node. */
|
||||
static u8 amd_ucode_patch[MAX_NUMNODES][PATCH_MAX_SIZE];
|
||||
|
||||
/*
|
||||
* Microcode patch container file is prepended to the initrd in cpio
|
||||
|
@ -330,8 +332,9 @@ static size_t parse_container(u8 *ucode, size_t size, struct cont_desc *desc)
|
|||
ret = verify_patch(x86_family(desc->cpuid_1_eax), buf, size, &patch_size, true);
|
||||
if (ret < 0) {
|
||||
/*
|
||||
* Patch verification failed, skip to the next
|
||||
* container, if there's one:
|
||||
* Patch verification failed, skip to the next container, if
|
||||
* there is one. Before exit, check whether that container has
|
||||
* found a patch already. If so, use it.
|
||||
*/
|
||||
goto out;
|
||||
} else if (ret > 0) {
|
||||
|
@ -350,6 +353,7 @@ static size_t parse_container(u8 *ucode, size_t size, struct cont_desc *desc)
|
|||
size -= patch_size + SECTION_HDR_SIZE;
|
||||
}
|
||||
|
||||
out:
|
||||
/*
|
||||
* If we have found a patch (desc->mc), it means we're looking at the
|
||||
* container which has a patch for this CPU so return 0 to mean, @ucode
|
||||
|
@ -364,7 +368,6 @@ static size_t parse_container(u8 *ucode, size_t size, struct cont_desc *desc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
out:
|
||||
return orig_size - size;
|
||||
}
|
||||
|
||||
|
@ -414,8 +417,7 @@ static int __apply_microcode_amd(struct microcode_amd *mc)
|
|||
*
|
||||
* Returns true if container found (sets @desc), false otherwise.
|
||||
*/
|
||||
static bool
|
||||
apply_microcode_early_amd(u32 cpuid_1_eax, void *ucode, size_t size, bool save_patch)
|
||||
static bool early_apply_microcode(u32 cpuid_1_eax, void *ucode, size_t size, bool save_patch)
|
||||
{
|
||||
struct cont_desc desc = { 0 };
|
||||
u8 (*patch)[PATCH_MAX_SIZE];
|
||||
|
@ -428,7 +430,7 @@ apply_microcode_early_amd(u32 cpuid_1_eax, void *ucode, size_t size, bool save_p
|
|||
patch = (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch);
|
||||
#else
|
||||
new_rev = &ucode_new_rev;
|
||||
patch = &amd_ucode_patch;
|
||||
patch = &amd_ucode_patch[0];
|
||||
#endif
|
||||
|
||||
desc.cpuid_1_eax = cpuid_1_eax;
|
||||
|
@ -481,7 +483,7 @@ static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family)
|
|||
return false;
|
||||
}
|
||||
|
||||
static void __load_ucode_amd(unsigned int cpuid_1_eax, struct cpio_data *ret)
|
||||
static void find_blobs_in_containers(unsigned int cpuid_1_eax, struct cpio_data *ret)
|
||||
{
|
||||
struct ucode_cpu_info *uci;
|
||||
struct cpio_data cp;
|
||||
|
@ -511,11 +513,11 @@ void __init load_ucode_amd_bsp(unsigned int cpuid_1_eax)
|
|||
{
|
||||
struct cpio_data cp = { };
|
||||
|
||||
__load_ucode_amd(cpuid_1_eax, &cp);
|
||||
find_blobs_in_containers(cpuid_1_eax, &cp);
|
||||
if (!(cp.data && cp.size))
|
||||
return;
|
||||
|
||||
apply_microcode_early_amd(cpuid_1_eax, cp.data, cp.size, true);
|
||||
early_apply_microcode(cpuid_1_eax, cp.data, cp.size, true);
|
||||
}
|
||||
|
||||
void load_ucode_amd_ap(unsigned int cpuid_1_eax)
|
||||
|
@ -546,15 +548,14 @@ void load_ucode_amd_ap(unsigned int cpuid_1_eax)
|
|||
}
|
||||
}
|
||||
|
||||
__load_ucode_amd(cpuid_1_eax, &cp);
|
||||
find_blobs_in_containers(cpuid_1_eax, &cp);
|
||||
if (!(cp.data && cp.size))
|
||||
return;
|
||||
|
||||
apply_microcode_early_amd(cpuid_1_eax, cp.data, cp.size, false);
|
||||
early_apply_microcode(cpuid_1_eax, cp.data, cp.size, false);
|
||||
}
|
||||
|
||||
static enum ucode_state
|
||||
load_microcode_amd(bool save, u8 family, const u8 *data, size_t size);
|
||||
static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
|
||||
|
||||
int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax)
|
||||
{
|
||||
|
@ -572,19 +573,19 @@ int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax)
|
|||
if (!desc.mc)
|
||||
return -EINVAL;
|
||||
|
||||
ret = load_microcode_amd(true, x86_family(cpuid_1_eax), desc.data, desc.size);
|
||||
ret = load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size);
|
||||
if (ret > UCODE_UPDATED)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void reload_ucode_amd(void)
|
||||
void reload_ucode_amd(unsigned int cpu)
|
||||
{
|
||||
struct microcode_amd *mc;
|
||||
u32 rev, dummy __always_unused;
|
||||
struct microcode_amd *mc;
|
||||
|
||||
mc = (struct microcode_amd *)amd_ucode_patch;
|
||||
mc = (struct microcode_amd *)amd_ucode_patch[cpu_to_node(cpu)];
|
||||
|
||||
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
|
||||
|
||||
|
@ -816,6 +817,7 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Scan the blob in @data and add microcode patches to the cache. */
|
||||
static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
|
||||
size_t size)
|
||||
{
|
||||
|
@ -850,9 +852,10 @@ static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
|
|||
return UCODE_OK;
|
||||
}
|
||||
|
||||
static enum ucode_state
|
||||
load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
|
||||
static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size)
|
||||
{
|
||||
struct cpuinfo_x86 *c;
|
||||
unsigned int nid, cpu;
|
||||
struct ucode_patch *p;
|
||||
enum ucode_state ret;
|
||||
|
||||
|
@ -865,23 +868,23 @@ load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
|
|||
return ret;
|
||||
}
|
||||
|
||||
p = find_patch(0);
|
||||
if (!p) {
|
||||
return ret;
|
||||
} else {
|
||||
if (boot_cpu_data.microcode >= p->patch_id)
|
||||
return ret;
|
||||
for_each_node(nid) {
|
||||
cpu = cpumask_first(cpumask_of_node(nid));
|
||||
c = &cpu_data(cpu);
|
||||
|
||||
p = find_patch(cpu);
|
||||
if (!p)
|
||||
continue;
|
||||
|
||||
if (c->microcode >= p->patch_id)
|
||||
continue;
|
||||
|
||||
ret = UCODE_NEW;
|
||||
|
||||
memset(&amd_ucode_patch[nid], 0, PATCH_MAX_SIZE);
|
||||
memcpy(&amd_ucode_patch[nid], p->data, min_t(u32, p->size, PATCH_MAX_SIZE));
|
||||
}
|
||||
|
||||
/* save BSP's matching patch for early load */
|
||||
if (!save)
|
||||
return ret;
|
||||
|
||||
memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
|
||||
memcpy(amd_ucode_patch, p->data, min_t(u32, p->size, PATCH_MAX_SIZE));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -905,14 +908,9 @@ 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 (!bsp)
|
||||
return UCODE_OK;
|
||||
|
||||
if (c->x86 >= 0x15)
|
||||
snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86);
|
||||
|
||||
|
@ -925,7 +923,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device)
|
|||
if (!verify_container(fw->data, fw->size, false))
|
||||
goto fw_release;
|
||||
|
||||
ret = load_microcode_amd(bsp, c->x86, fw->data, fw->size);
|
||||
ret = load_microcode_amd(c->x86, fw->data, fw->size);
|
||||
|
||||
fw_release:
|
||||
release_firmware(fw);
|
||||
|
|
|
@ -298,7 +298,7 @@ struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
|
|||
#endif
|
||||
}
|
||||
|
||||
void reload_early_microcode(void)
|
||||
void reload_early_microcode(unsigned int cpu)
|
||||
{
|
||||
int vendor, family;
|
||||
|
||||
|
@ -312,7 +312,7 @@ void reload_early_microcode(void)
|
|||
break;
|
||||
case X86_VENDOR_AMD:
|
||||
if (family >= 0x10)
|
||||
reload_ucode_amd();
|
||||
reload_ucode_amd(cpu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -409,10 +409,10 @@ static int __reload_late(void *info)
|
|||
goto wait_for_siblings;
|
||||
|
||||
if (err >= UCODE_NFOUND) {
|
||||
if (err == UCODE_ERROR)
|
||||
if (err == UCODE_ERROR) {
|
||||
pr_warn("Error reloading microcode on CPU %d\n", cpu);
|
||||
|
||||
ret = -1;
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
wait_for_siblings:
|
||||
|
@ -438,6 +438,7 @@ static int __reload_late(void *info)
|
|||
static int microcode_reload_late(void)
|
||||
{
|
||||
int old = boot_cpu_data.microcode, ret;
|
||||
struct cpuinfo_x86 prev_info;
|
||||
|
||||
pr_err("Attempting late microcode loading - it is dangerous and taints the kernel.\n");
|
||||
pr_err("You should switch to early loading, if possible.\n");
|
||||
|
@ -445,12 +446,21 @@ static int microcode_reload_late(void)
|
|||
atomic_set(&late_cpus_in, 0);
|
||||
atomic_set(&late_cpus_out, 0);
|
||||
|
||||
ret = stop_machine_cpuslocked(__reload_late, NULL, cpu_online_mask);
|
||||
if (ret == 0)
|
||||
microcode_check();
|
||||
/*
|
||||
* Take a snapshot before the microcode update in order to compare and
|
||||
* check whether any bits changed after an update.
|
||||
*/
|
||||
store_cpu_caps(&prev_info);
|
||||
|
||||
pr_info("Reload completed, microcode revision: 0x%x -> 0x%x\n",
|
||||
old, boot_cpu_data.microcode);
|
||||
ret = stop_machine_cpuslocked(__reload_late, NULL, cpu_online_mask);
|
||||
if (!ret) {
|
||||
pr_info("Reload succeeded, microcode revision: 0x%x -> 0x%x\n",
|
||||
old, boot_cpu_data.microcode);
|
||||
microcode_check(&prev_info);
|
||||
} else {
|
||||
pr_info("Reload failed, current microcode revision: 0x%x\n",
|
||||
boot_cpu_data.microcode);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -465,11 +475,8 @@ static ssize_t reload_store(struct device *dev,
|
|||
ssize_t ret = 0;
|
||||
|
||||
ret = kstrtoul(buf, 0, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val != 1)
|
||||
return size;
|
||||
if (ret || val != 1)
|
||||
return -EINVAL;
|
||||
|
||||
cpus_read_lock();
|
||||
|
||||
|
@ -507,7 +514,7 @@ static ssize_t version_show(struct device *dev,
|
|||
return sprintf(buf, "0x%x\n", uci->cpu_sig.rev);
|
||||
}
|
||||
|
||||
static ssize_t pf_show(struct device *dev,
|
||||
static ssize_t processor_flags_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
|
||||
|
@ -515,8 +522,8 @@ static ssize_t pf_show(struct device *dev,
|
|||
return sprintf(buf, "0x%x\n", uci->cpu_sig.pf);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(version, 0444, version_show, NULL);
|
||||
static DEVICE_ATTR(processor_flags, 0444, pf_show, NULL);
|
||||
static DEVICE_ATTR_RO(version);
|
||||
static DEVICE_ATTR_RO(processor_flags);
|
||||
|
||||
static struct attribute *mc_default_attrs[] = {
|
||||
&dev_attr_version.attr,
|
||||
|
@ -557,7 +564,7 @@ void microcode_bsp_resume(void)
|
|||
if (uci->mc)
|
||||
microcode_ops->apply_microcode(cpu);
|
||||
else
|
||||
reload_early_microcode();
|
||||
reload_early_microcode(cpu);
|
||||
}
|
||||
|
||||
static struct syscore_ops mc_syscore_ops = {
|
||||
|
|
|
@ -305,14 +305,11 @@ static bool load_builtin_intel_microcode(struct cpio_data *cp)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print ucode update info.
|
||||
*/
|
||||
static void
|
||||
print_ucode_info(struct ucode_cpu_info *uci, unsigned int date)
|
||||
static void print_ucode_info(int old_rev, int new_rev, unsigned int date)
|
||||
{
|
||||
pr_info_once("microcode updated early to revision 0x%x, date = %04x-%02x-%02x\n",
|
||||
uci->cpu_sig.rev,
|
||||
pr_info_once("updated early: 0x%x -> 0x%x, date = %04x-%02x-%02x\n",
|
||||
old_rev,
|
||||
new_rev,
|
||||
date & 0xffff,
|
||||
date >> 24,
|
||||
(date >> 16) & 0xff);
|
||||
|
@ -322,6 +319,7 @@ print_ucode_info(struct ucode_cpu_info *uci, unsigned int date)
|
|||
|
||||
static int delay_ucode_info;
|
||||
static int current_mc_date;
|
||||
static int early_old_rev;
|
||||
|
||||
/*
|
||||
* Print early updated ucode info after printk works. This is delayed info dump.
|
||||
|
@ -332,7 +330,7 @@ void show_ucode_info_early(void)
|
|||
|
||||
if (delay_ucode_info) {
|
||||
intel_cpu_collect_info(&uci);
|
||||
print_ucode_info(&uci, current_mc_date);
|
||||
print_ucode_info(early_old_rev, uci.cpu_sig.rev, current_mc_date);
|
||||
delay_ucode_info = 0;
|
||||
}
|
||||
}
|
||||
|
@ -341,40 +339,32 @@ void show_ucode_info_early(void)
|
|||
* At this point, we can not call printk() yet. Delay printing microcode info in
|
||||
* show_ucode_info_early() until printk() works.
|
||||
*/
|
||||
static void print_ucode(struct ucode_cpu_info *uci)
|
||||
static void print_ucode(int old_rev, int new_rev, int date)
|
||||
{
|
||||
struct microcode_intel *mc;
|
||||
int *delay_ucode_info_p;
|
||||
int *current_mc_date_p;
|
||||
|
||||
mc = uci->mc;
|
||||
if (!mc)
|
||||
return;
|
||||
int *early_old_rev_p;
|
||||
|
||||
delay_ucode_info_p = (int *)__pa_nodebug(&delay_ucode_info);
|
||||
current_mc_date_p = (int *)__pa_nodebug(¤t_mc_date);
|
||||
early_old_rev_p = (int *)__pa_nodebug(&early_old_rev);
|
||||
|
||||
*delay_ucode_info_p = 1;
|
||||
*current_mc_date_p = mc->hdr.date;
|
||||
*current_mc_date_p = date;
|
||||
*early_old_rev_p = old_rev;
|
||||
}
|
||||
#else
|
||||
|
||||
static inline void print_ucode(struct ucode_cpu_info *uci)
|
||||
static inline void print_ucode(int old_rev, int new_rev, int date)
|
||||
{
|
||||
struct microcode_intel *mc;
|
||||
|
||||
mc = uci->mc;
|
||||
if (!mc)
|
||||
return;
|
||||
|
||||
print_ucode_info(uci, mc->hdr.date);
|
||||
print_ucode_info(old_rev, new_rev, date);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
|
||||
{
|
||||
struct microcode_intel *mc;
|
||||
u32 rev;
|
||||
u32 rev, old_rev;
|
||||
|
||||
mc = uci->mc;
|
||||
if (!mc)
|
||||
|
@ -391,6 +381,8 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
|
|||
return UCODE_OK;
|
||||
}
|
||||
|
||||
old_rev = rev;
|
||||
|
||||
/*
|
||||
* Writeback and invalidate caches before updating microcode to avoid
|
||||
* internal issues depending on what the microcode is updating.
|
||||
|
@ -407,9 +399,9 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
|
|||
uci->cpu_sig.rev = rev;
|
||||
|
||||
if (early)
|
||||
print_ucode(uci);
|
||||
print_ucode(old_rev, uci->cpu_sig.rev, mc->hdr.date);
|
||||
else
|
||||
print_ucode_info(uci, mc->hdr.date);
|
||||
print_ucode_info(old_rev, uci->cpu_sig.rev, mc->hdr.date);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue