Use RIP-relative addressing to access cpuid maxes and ghcb version
Change-Id: Ifaac89a0a435bce2e2bf14f65fd98046a235c1f7
diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c
index 20c43e4..63c44d0 100644
--- a/arch/x86/kernel/sev-shared.c
+++ b/arch/x86/kernel/sev-shared.c
@@ -63,6 +63,17 @@
*/
static u16 ghcb_version __ro_after_init;
+static u16 *get_ghcb_version(void)
+{
+ void *ptr;
+
+ asm ("lea ghcb_version(%%rip), %0"
+ : "=r" (ptr)
+ : "p" (&ghcb_version));
+
+ return (u16*)ptr;
+}
+
/* Copy of the SNP firmware's CPUID page. */
static struct snp_cpuid_table cpuid_table_copy __ro_after_init;
@@ -72,9 +83,13 @@
* invalid/out-of-range leaves. This is needed since all-zero leaves
* still need to be post-processed.
*/
-static u32 cpuid_std_range_max __ro_after_init;
-static u32 cpuid_hyp_range_max __ro_after_init;
-static u32 cpuid_ext_range_max __ro_after_init;
+struct cpuid_maxes {
+ u32 std_range;
+ u32 hyp_range;
+ u32 ext_range;
+};
+
+static struct cpuid_maxes cpuid_range_maxes __ro_after_init;
static bool __init sev_es_check_cpu_features(void)
{
@@ -108,7 +123,7 @@
{
u64 val;
- if (ghcb_version < 2)
+ if (*get_ghcb_version() < 2)
return 0;
sev_es_wr_ghcb_msr(GHCB_MSR_HV_FT_REQ);
@@ -153,7 +168,7 @@
GHCB_MSR_PROTO_MIN(val) > GHCB_PROTOCOL_MAX)
return false;
- ghcb_version = min_t(size_t, GHCB_MSR_PROTO_MAX(val), GHCB_PROTOCOL_MAX);
+ *get_ghcb_version() = min_t(size_t, GHCB_MSR_PROTO_MAX(val), GHCB_PROTOCOL_MAX);
return true;
}
@@ -291,6 +306,17 @@
return ptr;
}
+static const struct cpuid_maxes *snp_cpuid_get_maxes(void)
+{
+ void *ptr;
+
+ asm ("lea cpuid_range_maxes(%%rip), %0"
+ : "=r" (ptr)
+ : "p" (&cpuid_range_maxes));
+
+ return ptr;
+}
+
/*
* The SNP Firmware ABI, Revision 0.9, Section 7.1, details the use of
* XCR0_IN and XSS_IN to encode multiple versions of 0xD subfunctions 0
@@ -486,6 +512,7 @@
static int snp_cpuid(struct cpuid_leaf *leaf)
{
const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table();
+ const struct cpuid_maxes *maxes = snp_cpuid_get_maxes();
if (!cpuid_table->count)
return -EOPNOTSUPP;
@@ -511,9 +538,9 @@
leaf->eax = leaf->ebx = leaf->ecx = leaf->edx = 0;
/* Skip post-processing for out-of-range zero leafs. */
- if (!(leaf->fn <= cpuid_std_range_max ||
- (leaf->fn >= 0x40000000 && leaf->fn <= cpuid_hyp_range_max) ||
- (leaf->fn >= 0x80000000 && leaf->fn <= cpuid_ext_range_max)))
+ if (!(leaf->fn <= maxes->std_range ||
+ (leaf->fn >= 0x40000000 && leaf->fn <= maxes->hyp_range) ||
+ (leaf->fn >= 0x80000000 && leaf->fn <= maxes->ext_range)))
return 0;
}
@@ -965,6 +992,8 @@
static void __init setup_cpuid_table(const struct cc_blob_sev_info *cc_info)
{
const struct snp_cpuid_table *cpuid_table_fw, *cpuid_table;
+ const struct cpuid_maxes *range_maxes;
+ struct cpuid_maxes local;
int i;
if (!cc_info || !cc_info->cpuid_phys || cc_info->cpuid_len < PAGE_SIZE)
@@ -975,6 +1004,7 @@
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_CPUID);
cpuid_table = snp_cpuid_get_table();
+ range_maxes = snp_cpuid_get_maxes();
memcpy((void *)cpuid_table, cpuid_table_fw, sizeof(*cpuid_table));
/* Initialize CPUID ranges for range-checking. */
@@ -982,10 +1012,11 @@
const struct snp_cpuid_fn *fn = &cpuid_table->fn[i];
if (fn->eax_in == 0x0)
- cpuid_std_range_max = fn->eax;
+ local.std_range = fn->eax;
else if (fn->eax_in == 0x40000000)
- cpuid_hyp_range_max = fn->eax;
+ local.hyp_range = fn->eax;
else if (fn->eax_in == 0x80000000)
- cpuid_ext_range_max = fn->eax;
+ local.ext_range = fn->eax;
}
+ memcpy((void *)range_maxes, &local, sizeof(*range_maxes));
}