Merge branch 'x86/urgent' into perf/core, to resolve conflict
Resolve an MSR enumeration conflict. Conflicts: arch/x86/include/asm/msr-index.h Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
8f4156d587
@ -637,11 +637,14 @@
|
|||||||
/* AMD Last Branch Record MSRs */
|
/* AMD Last Branch Record MSRs */
|
||||||
#define MSR_AMD64_LBR_SELECT 0xc000010e
|
#define MSR_AMD64_LBR_SELECT 0xc000010e
|
||||||
|
|
||||||
/* Fam 19h MSRs */
|
/* Fam 19h (Zen 4) MSRs */
|
||||||
#define MSR_F19H_UMC_PERF_CTL 0xc0010800
|
#define MSR_F19H_UMC_PERF_CTL 0xc0010800
|
||||||
#define MSR_F19H_UMC_PERF_CTR 0xc0010801
|
#define MSR_F19H_UMC_PERF_CTR 0xc0010801
|
||||||
|
|
||||||
/* Fam 17h MSRs */
|
#define MSR_ZEN4_BP_CFG 0xc001102e
|
||||||
|
#define MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT 5
|
||||||
|
|
||||||
|
/* Fam 17h (Zen 2) MSRs */
|
||||||
#define MSR_F17H_IRPERF 0xc00000e9
|
#define MSR_F17H_IRPERF 0xc00000e9
|
||||||
|
|
||||||
#define MSR_ZEN2_SPECTRAL_CHICKEN 0xc00110e3
|
#define MSR_ZEN2_SPECTRAL_CHICKEN 0xc00110e3
|
||||||
|
@ -80,6 +80,10 @@ static const int amd_div0[] =
|
|||||||
AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x00, 0x0, 0x2f, 0xf),
|
AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x00, 0x0, 0x2f, 0xf),
|
||||||
AMD_MODEL_RANGE(0x17, 0x50, 0x0, 0x5f, 0xf));
|
AMD_MODEL_RANGE(0x17, 0x50, 0x0, 0x5f, 0xf));
|
||||||
|
|
||||||
|
static const int amd_erratum_1485[] =
|
||||||
|
AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x19, 0x10, 0x0, 0x1f, 0xf),
|
||||||
|
AMD_MODEL_RANGE(0x19, 0x60, 0x0, 0xaf, 0xf));
|
||||||
|
|
||||||
static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
|
static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
|
||||||
{
|
{
|
||||||
int osvw_id = *erratum++;
|
int osvw_id = *erratum++;
|
||||||
@ -1149,6 +1153,10 @@ static void init_amd(struct cpuinfo_x86 *c)
|
|||||||
pr_notice_once("AMD Zen1 DIV0 bug detected. Disable SMT for full protection.\n");
|
pr_notice_once("AMD Zen1 DIV0 bug detected. Disable SMT for full protection.\n");
|
||||||
setup_force_cpu_bug(X86_BUG_DIV0);
|
setup_force_cpu_bug(X86_BUG_DIV0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!cpu_has(c, X86_FEATURE_HYPERVISOR) &&
|
||||||
|
cpu_has_amd_erratum(c, amd_erratum_1485))
|
||||||
|
msr_set_bit(MSR_ZEN4_BP_CFG, MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
|
@ -30,15 +30,15 @@ struct rmid_entry {
|
|||||||
struct list_head list;
|
struct list_head list;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* @rmid_free_lru A least recently used list of free RMIDs
|
* @rmid_free_lru - A least recently used list of free RMIDs
|
||||||
* These RMIDs are guaranteed to have an occupancy less than the
|
* These RMIDs are guaranteed to have an occupancy less than the
|
||||||
* threshold occupancy
|
* threshold occupancy
|
||||||
*/
|
*/
|
||||||
static LIST_HEAD(rmid_free_lru);
|
static LIST_HEAD(rmid_free_lru);
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* @rmid_limbo_count count of currently unused but (potentially)
|
* @rmid_limbo_count - count of currently unused but (potentially)
|
||||||
* dirty RMIDs.
|
* dirty RMIDs.
|
||||||
* This counts RMIDs that no one is currently using but that
|
* This counts RMIDs that no one is currently using but that
|
||||||
* may have a occupancy value > resctrl_rmid_realloc_threshold. User can
|
* may have a occupancy value > resctrl_rmid_realloc_threshold. User can
|
||||||
@ -46,7 +46,7 @@ static LIST_HEAD(rmid_free_lru);
|
|||||||
*/
|
*/
|
||||||
static unsigned int rmid_limbo_count;
|
static unsigned int rmid_limbo_count;
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* @rmid_entry - The entry in the limbo and free lists.
|
* @rmid_entry - The entry in the limbo and free lists.
|
||||||
*/
|
*/
|
||||||
static struct rmid_entry *rmid_ptrs;
|
static struct rmid_entry *rmid_ptrs;
|
||||||
|
@ -256,7 +256,7 @@ static int __sev_cpuid_hv(u32 fn, int reg_idx, u32 *reg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sev_cpuid_hv(struct cpuid_leaf *leaf)
|
static int __sev_cpuid_hv_msr(struct cpuid_leaf *leaf)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -279,6 +279,45 @@ static int sev_cpuid_hv(struct cpuid_leaf *leaf)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __sev_cpuid_hv_ghcb(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
|
||||||
|
{
|
||||||
|
u32 cr4 = native_read_cr4();
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ghcb_set_rax(ghcb, leaf->fn);
|
||||||
|
ghcb_set_rcx(ghcb, leaf->subfn);
|
||||||
|
|
||||||
|
if (cr4 & X86_CR4_OSXSAVE)
|
||||||
|
/* Safe to read xcr0 */
|
||||||
|
ghcb_set_xcr0(ghcb, xgetbv(XCR_XFEATURE_ENABLED_MASK));
|
||||||
|
else
|
||||||
|
/* xgetbv will cause #UD - use reset value for xcr0 */
|
||||||
|
ghcb_set_xcr0(ghcb, 1);
|
||||||
|
|
||||||
|
ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_CPUID, 0, 0);
|
||||||
|
if (ret != ES_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (!(ghcb_rax_is_valid(ghcb) &&
|
||||||
|
ghcb_rbx_is_valid(ghcb) &&
|
||||||
|
ghcb_rcx_is_valid(ghcb) &&
|
||||||
|
ghcb_rdx_is_valid(ghcb)))
|
||||||
|
return ES_VMM_ERROR;
|
||||||
|
|
||||||
|
leaf->eax = ghcb->save.rax;
|
||||||
|
leaf->ebx = ghcb->save.rbx;
|
||||||
|
leaf->ecx = ghcb->save.rcx;
|
||||||
|
leaf->edx = ghcb->save.rdx;
|
||||||
|
|
||||||
|
return ES_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sev_cpuid_hv(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
|
||||||
|
{
|
||||||
|
return ghcb ? __sev_cpuid_hv_ghcb(ghcb, ctxt, leaf)
|
||||||
|
: __sev_cpuid_hv_msr(leaf);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This may be called early while still running on the initial identity
|
* This may be called early while still running on the initial identity
|
||||||
* mapping. Use RIP-relative addressing to obtain the correct address
|
* mapping. Use RIP-relative addressing to obtain the correct address
|
||||||
@ -388,19 +427,20 @@ snp_cpuid_get_validated_func(struct cpuid_leaf *leaf)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void snp_cpuid_hv(struct cpuid_leaf *leaf)
|
static void snp_cpuid_hv(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
|
||||||
{
|
{
|
||||||
if (sev_cpuid_hv(leaf))
|
if (sev_cpuid_hv(ghcb, ctxt, leaf))
|
||||||
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_CPUID_HV);
|
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_CPUID_HV);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
|
static int snp_cpuid_postprocess(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
|
||||||
|
struct cpuid_leaf *leaf)
|
||||||
{
|
{
|
||||||
struct cpuid_leaf leaf_hv = *leaf;
|
struct cpuid_leaf leaf_hv = *leaf;
|
||||||
|
|
||||||
switch (leaf->fn) {
|
switch (leaf->fn) {
|
||||||
case 0x1:
|
case 0x1:
|
||||||
snp_cpuid_hv(&leaf_hv);
|
snp_cpuid_hv(ghcb, ctxt, &leaf_hv);
|
||||||
|
|
||||||
/* initial APIC ID */
|
/* initial APIC ID */
|
||||||
leaf->ebx = (leaf_hv.ebx & GENMASK(31, 24)) | (leaf->ebx & GENMASK(23, 0));
|
leaf->ebx = (leaf_hv.ebx & GENMASK(31, 24)) | (leaf->ebx & GENMASK(23, 0));
|
||||||
@ -419,7 +459,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
|
|||||||
break;
|
break;
|
||||||
case 0xB:
|
case 0xB:
|
||||||
leaf_hv.subfn = 0;
|
leaf_hv.subfn = 0;
|
||||||
snp_cpuid_hv(&leaf_hv);
|
snp_cpuid_hv(ghcb, ctxt, &leaf_hv);
|
||||||
|
|
||||||
/* extended APIC ID */
|
/* extended APIC ID */
|
||||||
leaf->edx = leaf_hv.edx;
|
leaf->edx = leaf_hv.edx;
|
||||||
@ -467,7 +507,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x8000001E:
|
case 0x8000001E:
|
||||||
snp_cpuid_hv(&leaf_hv);
|
snp_cpuid_hv(ghcb, ctxt, &leaf_hv);
|
||||||
|
|
||||||
/* extended APIC ID */
|
/* extended APIC ID */
|
||||||
leaf->eax = leaf_hv.eax;
|
leaf->eax = leaf_hv.eax;
|
||||||
@ -488,7 +528,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf)
|
|||||||
* Returns -EOPNOTSUPP if feature not enabled. Any other non-zero return value
|
* Returns -EOPNOTSUPP if feature not enabled. Any other non-zero return value
|
||||||
* should be treated as fatal by caller.
|
* should be treated as fatal by caller.
|
||||||
*/
|
*/
|
||||||
static int snp_cpuid(struct cpuid_leaf *leaf)
|
static int snp_cpuid(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
|
||||||
{
|
{
|
||||||
const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table();
|
const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table();
|
||||||
|
|
||||||
@ -522,7 +562,7 @@ static int snp_cpuid(struct cpuid_leaf *leaf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return snp_cpuid_postprocess(leaf);
|
return snp_cpuid_postprocess(ghcb, ctxt, leaf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -544,14 +584,14 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code)
|
|||||||
leaf.fn = fn;
|
leaf.fn = fn;
|
||||||
leaf.subfn = subfn;
|
leaf.subfn = subfn;
|
||||||
|
|
||||||
ret = snp_cpuid(&leaf);
|
ret = snp_cpuid(NULL, NULL, &leaf);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
goto cpuid_done;
|
goto cpuid_done;
|
||||||
|
|
||||||
if (ret != -EOPNOTSUPP)
|
if (ret != -EOPNOTSUPP)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (sev_cpuid_hv(&leaf))
|
if (__sev_cpuid_hv_msr(&leaf))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
cpuid_done:
|
cpuid_done:
|
||||||
@ -848,14 +888,15 @@ static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vc_handle_cpuid_snp(struct pt_regs *regs)
|
static int vc_handle_cpuid_snp(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
|
||||||
{
|
{
|
||||||
|
struct pt_regs *regs = ctxt->regs;
|
||||||
struct cpuid_leaf leaf;
|
struct cpuid_leaf leaf;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
leaf.fn = regs->ax;
|
leaf.fn = regs->ax;
|
||||||
leaf.subfn = regs->cx;
|
leaf.subfn = regs->cx;
|
||||||
ret = snp_cpuid(&leaf);
|
ret = snp_cpuid(ghcb, ctxt, &leaf);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
regs->ax = leaf.eax;
|
regs->ax = leaf.eax;
|
||||||
regs->bx = leaf.ebx;
|
regs->bx = leaf.ebx;
|
||||||
@ -874,7 +915,7 @@ static enum es_result vc_handle_cpuid(struct ghcb *ghcb,
|
|||||||
enum es_result ret;
|
enum es_result ret;
|
||||||
int snp_cpuid_ret;
|
int snp_cpuid_ret;
|
||||||
|
|
||||||
snp_cpuid_ret = vc_handle_cpuid_snp(regs);
|
snp_cpuid_ret = vc_handle_cpuid_snp(ghcb, ctxt);
|
||||||
if (!snp_cpuid_ret)
|
if (!snp_cpuid_ret)
|
||||||
return ES_OK;
|
return ES_OK;
|
||||||
if (snp_cpuid_ret != -EOPNOTSUPP)
|
if (snp_cpuid_ret != -EOPNOTSUPP)
|
||||||
|
@ -868,8 +868,7 @@ void snp_set_memory_private(unsigned long vaddr, unsigned long npages)
|
|||||||
|
|
||||||
void snp_accept_memory(phys_addr_t start, phys_addr_t end)
|
void snp_accept_memory(phys_addr_t start, phys_addr_t end)
|
||||||
{
|
{
|
||||||
unsigned long vaddr;
|
unsigned long vaddr, npages;
|
||||||
unsigned int npages;
|
|
||||||
|
|
||||||
if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
|
if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user