From 5dba8c2f23049aa68b777a9e7e9f76c12dd00012 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Fri, 4 Sep 2020 15:25:09 +0100 Subject: [PATCH] x86/pv: Simplify emulation for the 64bit base MSRs is_pv_32bit_domain() is an expensive predicate, but isn't used for speculative safety in this case. Swap to checking the Long Mode bit in the CPUID policy, which is the architecturally correct behaviour. is_canonical_address() is currently moderately simple, but it will become more complicated when 5-level support is added. Rearrange write_msr() to collapse the common checks. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich --- xen/arch/x86/pv/emul-priv-op.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/xen/arch/x86/pv/emul-priv-op.c b/xen/arch/x86/pv/emul-priv-op.c index 6be72efb5e..7cc16d6eda 100644 --- a/xen/arch/x86/pv/emul-priv-op.c +++ b/xen/arch/x86/pv/emul-priv-op.c @@ -877,6 +877,7 @@ static int read_msr(unsigned int reg, uint64_t *val, { struct vcpu *curr = current; const struct domain *currd = curr->domain; + const struct cpuid_policy *cp = currd->arch.cpuid; bool vpmu_msr = false; int ret; @@ -898,19 +899,19 @@ static int read_msr(unsigned int reg, uint64_t *val, return X86EMUL_OKAY; case MSR_FS_BASE: - if ( is_pv_32bit_domain(currd) ) + if ( !cp->extd.lm ) break; *val = read_fs_base(); return X86EMUL_OKAY; case MSR_GS_BASE: - if ( is_pv_32bit_domain(currd) ) + if ( !cp->extd.lm ) break; *val = read_gs_base(); return X86EMUL_OKAY; case MSR_SHADOW_GS_BASE: - if ( is_pv_32bit_domain(currd) ) + if ( !cp->extd.lm ) break; *val = curr->arch.pv.gs_base_user; return X86EMUL_OKAY; @@ -1006,6 +1007,7 @@ static int write_msr(unsigned int reg, uint64_t val, { struct vcpu *curr = current; const struct domain *currd = curr->domain; + const struct cpuid_policy *cp = currd->arch.cpuid; bool vpmu_msr = false; int ret; @@ -1022,22 +1024,22 @@ static int write_msr(unsigned int reg, uint64_t val, uint64_t temp; case MSR_FS_BASE: - if ( is_pv_32bit_domain(currd) || !is_canonical_address(val) ) - break; - write_fs_base(val); - return X86EMUL_OKAY; - case MSR_GS_BASE: - if ( is_pv_32bit_domain(currd) || !is_canonical_address(val) ) - break; - write_gs_base(val); - return X86EMUL_OKAY; - case MSR_SHADOW_GS_BASE: - if ( is_pv_32bit_domain(currd) || !is_canonical_address(val) ) + if ( !cp->extd.lm || !is_canonical_address(val) ) break; - write_gs_shadow(val); - curr->arch.pv.gs_base_user = val; + + if ( reg == MSR_FS_BASE ) + write_fs_base(val); + else if ( reg == MSR_GS_BASE ) + write_gs_base(val); + else if ( reg == MSR_SHADOW_GS_BASE ) + { + write_gs_shadow(val); + curr->arch.pv.gs_base_user = val; + } + else + ASSERT_UNREACHABLE(); return X86EMUL_OKAY; case MSR_EFER: -- 2.39.5