kernel/x86_64: Add errata patching.

The patched errata are only the AMD ones FreeBSD patches
(it seems there are no Intel errata that can be patched
this way, they are all in microcode updates ... or can't
be patched in the CPU at all.)

This also seems to be roughly the point in the boot that
FreeBSD patches these, too, despite how "critical" some
of them seem.

Change-Id: I9065f8d025332418a21c2cdf39afd7d29405edcc
Reviewed-on: https://review.haiku-os.org/c/haiku/+/1740
Reviewed-by: Jessica Hamilton <jessica.l.hamilton@gmail.com>
This commit is contained in:
Augustin Cavalier 2019-08-24 15:32:24 -04:00 committed by Adrien Destugues
parent d7818b5aae
commit 26e0b0c8d6
5 changed files with 128 additions and 1 deletions

View File

@ -557,6 +557,8 @@ void __x86_setup_system_time(uint32 conversionFactor,
uint32 conversionFactorNsecs, bool conversionFactorNsecsShift);
#endif
status_t __x86_patch_errata_percpu(int cpu);
void x86_userspace_thread_exit(void);
void x86_end_userspace_thread_exit(void);

View File

@ -0,0 +1,18 @@
/*
* Copyright 2019, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Augustin Cavalier <waddlesplash>
*/
#include <cpu.h>
#include <arch_cpu.h>
status_t
__x86_patch_errata_percpu(int currentCPU)
{
// TODO.
return B_OK;
}

View File

@ -0,0 +1,105 @@
/*
* Copyright 2019, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Augustin Cavalier <waddlesplash>
*/
#include <cpu.h>
#include <arch_cpu.h>
static status_t
patch_errata_percpu_amd(int currentCPU, const cpu_ent* cpu)
{
// There are no errata to patch on a hypervisor, the host will have
// already taken care of everything for us.
if (x86_check_feature(IA32_FEATURE_EXT_HYPERVISOR, FEATURE_EXT))
return B_OK;
const uint32 family = cpu->arch.family + cpu->arch.extended_family,
model = (cpu->arch.extended_model << 4) | cpu->arch.model;
// Family 10h and 12h, Erratum 721:
//
// "Under a highly specific and detailed set of internal timing conditions,
// the processor may incorrectly update the stack pointer after a long
// series of push and/or near-call instructions, or a long series of pop
// and/or near-return instructions.
//
// https://www.amd.com/system/files/TechDocs/41322_10h_Rev_Gd.pdf
// https://www.amd.com/system/files/TechDocs/44739_12h_Rev_Gd.pdf
switch (family) {
case 0x10:
case 0x12:
x86_write_msr(0xc0011029, x86_read_msr(0xc0011029) | 1);
break;
}
// Family 16h ("Jaguar"), Erratum 793:
//
// "Under a highly specific and detailed set of internal timing conditions,
// a locked instruction may trigger a timing sequence whereby the write to
// a write combined memory type is not flushed, causing the locked instruction
// to stall indefinitely."
//
// https://www.amd.com/system/files/TechDocs/53072_Rev_Guide_16h_Models_30h-3Fh.pdf
if (family == 0x16 && model <= 0xf) {
x86_write_msr(0xc0011020, x86_read_msr(0xc0011020) | ((uint64)1 << 15));
}
// Family 17h ("Zen") Model 1h
// https://www.amd.com/system/files/TechDocs/55449_Fam_17h_M_00h-0Fh_Rev_Guide.pdf
if (family == 0x17 && model == 0x1) {
// Erratum 1021:
//
// "Under a highly specific and detailed set of internal timing
// conditions, a load operation may incorrectly receive stale data
// from an older store operation."
x86_write_msr(0xc0011029, x86_read_msr(0xc0011029) | (1 << 13));
// Erratum 1033:
//
// "Under a highly specific and detailed set of internal timing
// conditions, a Lock operation may cause the system to hang."
x86_write_msr(0xc0011020, x86_read_msr(0xc0011020) | (1 << 4));
// Erratum 1049:
//
// "Under a highly specific and detailed set of internal timing
// conditions, an FCMOV instruction may yield incorrect data if the
// following sequence of events occurs:
// * An FCOMI instruction
// * A non-FP instruction that modifies RFLAGS
// * An FCMOV instruction."
x86_write_msr(0xc0011028, x86_read_msr(0xc0011028) | (1 << 4));
// Erratum 1095:
//
// Under a highly detailed and specific set of internal timing
// conditions, a lock operation may not fence a younger load operation
// correctly when the following conditions are met:
// * SMT (Simultaneous Multithreading) is enabled, and
// * a lock operation on memory location A, followed by a load
// operation on memory location B are executing on one thread while
// * a lock operation on memory location B, followed by a load operation
// on memory location A are executing on the second thread on the
// same core.
// This may result in the load operations on both threads incorrectly
// receiving pre-lock data."
x86_write_msr(0xc0011020, x86_read_msr(0xc0011020) | ((uint64)1 << 57));
}
return B_OK;
}
status_t
__x86_patch_errata_percpu(int currentCPU)
{
const cpu_ent* cpu = get_cpu_struct();
if (cpu->arch.vendor == VENDOR_AMD)
return patch_errata_percpu_amd(currentCPU, cpu);
return B_OK;
}

View File

@ -24,6 +24,7 @@ if $(TARGET_ARCH) = x86_64 {
arch.S
cpuid.cpp
descriptors.cpp
errata.cpp
interrupts.S
signals.cpp
signals_asm.S
@ -49,6 +50,7 @@ if $(TARGET_ARCH) = x86_64 {
bios.cpp
cpuid.S
descriptors.cpp
errata.cpp
interrupts.S
signals.cpp
signals_asm.S

View File

@ -1135,7 +1135,7 @@ arch_cpu_init_percpu(kernel_args* args, int cpu)
gCpuIdleFunc = halt_idle;
}
return B_OK;
return __x86_patch_errata_percpu(cpu);
}