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:
Ingo Molnar 2023-10-11 22:48:46 +02:00
commit 8f4156d587
5 changed files with 74 additions and 23 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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;