Message ID | 20200320034342.26610-7-weijiang.yang@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Introduce support for guest CET feature | expand |
Hi Yang, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on kvm/linux-next] [also build test WARNING on next-20200319] [cannot apply to vhost/linux-next tip/auto-latest linux/master linus/master v5.6-rc6] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982] url: https://github.com/0day-ci/linux/commits/Yang-Weijiang/Introduce-support-for-guest-CET-feature/20200320-155517 base: https://git.kernel.org/pub/scm/virt/kvm/kvm.git linux-next reproduce: # apt-get install sparse # sparse version: v0.6.1-181-g83789bbc-dirty make ARCH=x86_64 allmodconfig make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' If you fix the issue, kindly add following tag Reported-by: kbuild test robot <lkp@intel.com> sparse warnings: (new ones prefixed by >>) arch/x86/kvm/x86.c:809:60: sparse: sparse: undefined identifier 'X86_CR4_CET' arch/x86/kvm/x86.c:1233:23: sparse: sparse: undefined identifier 'MSR_IA32_U_CET' arch/x86/kvm/x86.c:1233:39: sparse: sparse: undefined identifier 'MSR_IA32_S_CET' arch/x86/kvm/x86.c:1234:9: sparse: sparse: undefined identifier 'MSR_IA32_PL0_SSP' arch/x86/kvm/x86.c:1234:27: sparse: sparse: undefined identifier 'MSR_IA32_PL1_SSP' arch/x86/kvm/x86.c:1234:45: sparse: sparse: undefined identifier 'MSR_IA32_PL2_SSP' arch/x86/kvm/x86.c:1235:9: sparse: sparse: undefined identifier 'MSR_IA32_PL3_SSP' arch/x86/kvm/x86.c:1235:27: sparse: sparse: undefined identifier 'MSR_IA32_INT_SSP_TAB' arch/x86/kvm/x86.c:1512:14: sparse: sparse: undefined identifier 'MSR_IA32_PL0_SSP' arch/x86/kvm/x86.c:1512:35: sparse: sparse: undefined identifier 'MSR_IA32_PL3_SSP' arch/x86/kvm/x86.c:1513:14: sparse: sparse: undefined identifier 'MSR_IA32_U_CET' arch/x86/kvm/x86.c:1514:14: sparse: sparse: undefined identifier 'MSR_IA32_S_CET' arch/x86/kvm/x86.c:1515:14: sparse: sparse: undefined identifier 'MSR_IA32_INT_SSP_TAB' >> arch/x86/kvm/x86.c:1512:14: sparse: sparse: incompatible types for 'case' statement arch/x86/kvm/x86.c:1512:35: sparse: sparse: incompatible types for 'case' statement arch/x86/kvm/x86.c:1513:14: sparse: sparse: incompatible types for 'case' statement arch/x86/kvm/x86.c:1514:14: sparse: sparse: incompatible types for 'case' statement arch/x86/kvm/x86.c:1515:14: sparse: sparse: incompatible types for 'case' statement arch/x86/kvm/x86.c:2646:38: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void const [noderef] <asn:1> * @@ got const [noderef] <asn:1> * @@ arch/x86/kvm/x86.c:2646:38: sparse: expected void const [noderef] <asn:1> * arch/x86/kvm/x86.c:2646:38: sparse: got unsigned char [usertype] * arch/x86/kvm/x86.c:3267:25: sparse: sparse: undefined identifier 'MSR_IA32_U_CET' arch/x86/kvm/x86.c:7549:15: sparse: sparse: incompatible types in comparison expression (different address spaces): arch/x86/kvm/x86.c:7549:15: sparse: struct kvm_apic_map [noderef] <asn:4> * arch/x86/kvm/x86.c:7549:15: sparse: struct kvm_apic_map * arch/x86/kvm/x86.c:9678:44: sparse: sparse: undefined identifier 'XFEATURE_MASK_CET_USER' arch/x86/kvm/x86.c:9678:44: sparse: sparse: undefined identifier 'XFEATURE_MASK_CET_KERNEL' arch/x86/kvm/x86.c:9912:16: sparse: sparse: incompatible types in comparison expression (different address spaces): arch/x86/kvm/x86.c:9912:16: sparse: struct kvm_apic_map [noderef] <asn:4> * arch/x86/kvm/x86.c:9912:16: sparse: struct kvm_apic_map * arch/x86/kvm/x86.c:9913:15: sparse: sparse: incompatible types in comparison expression (different address spaces): arch/x86/kvm/x86.c:9913:15: sparse: struct kvm_pmu_event_filter [noderef] <asn:4> * arch/x86/kvm/x86.c:9913:15: sparse: struct kvm_pmu_event_filter * arch/x86/kvm/x86.c:1512:14: sparse: sparse: Expected constant expression in case statement arch/x86/kvm/x86.c:1512:35: sparse: sparse: Expected constant expression in case statement arch/x86/kvm/x86.c:1513:14: sparse: sparse: Expected constant expression in case statement arch/x86/kvm/x86.c:1514:14: sparse: sparse: Expected constant expression in case statement arch/x86/kvm/x86.c:1515:14: sparse: sparse: Expected constant expression in case statement vim +/case +1512 arch/x86/kvm/x86.c 1475 1476 /* 1477 * Write @data into the MSR specified by @index. Select MSR specific fault 1478 * checks are bypassed if @host_initiated is %true. 1479 * Returns 0 on success, non-0 otherwise. 1480 * Assumes vcpu_load() was already called. 1481 */ 1482 static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data, 1483 bool host_initiated) 1484 { 1485 struct msr_data msr; 1486 1487 switch (index) { 1488 case MSR_FS_BASE: 1489 case MSR_GS_BASE: 1490 case MSR_KERNEL_GS_BASE: 1491 case MSR_CSTAR: 1492 case MSR_LSTAR: 1493 if (is_noncanonical_address(data, vcpu)) 1494 return 1; 1495 break; 1496 case MSR_IA32_SYSENTER_EIP: 1497 case MSR_IA32_SYSENTER_ESP: 1498 /* 1499 * IA32_SYSENTER_ESP and IA32_SYSENTER_EIP cause #GP if 1500 * non-canonical address is written on Intel but not on 1501 * AMD (which ignores the top 32-bits, because it does 1502 * not implement 64-bit SYSENTER). 1503 * 1504 * 64-bit code should hence be able to write a non-canonical 1505 * value on AMD. Making the address canonical ensures that 1506 * vmentry does not fail on Intel after writing a non-canonical 1507 * value, and that something deterministic happens if the guest 1508 * invokes 64-bit SYSENTER. 1509 */ 1510 data = get_canonical(data, vcpu_virt_addr_bits(vcpu)); 1511 break; > 1512 case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP: 1513 case MSR_IA32_U_CET: 1514 case MSR_IA32_S_CET: 1515 case MSR_IA32_INT_SSP_TAB: 1516 if (is_noncanonical_address(data, vcpu)) 1517 return 1; 1518 } 1519 1520 msr.data = data; 1521 msr.index = index; 1522 msr.host_initiated = host_initiated; 1523 1524 return kvm_x86_ops->set_msr(vcpu, &msr); 1525 } 1526 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index e7ac776c808f..2654bd099fe6 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -1809,6 +1809,91 @@ static int vmx_get_msr_feature(struct kvm_msr_entry *msr) } } +static void vmx_get_xsave_msr(struct msr_data *msr_info) +{ + local_irq_disable(); + if (test_thread_flag(TIF_NEED_FPU_LOAD)) + switch_fpu_return(); + rdmsrl(msr_info->index, msr_info->data); + local_irq_enable(); +} + +static void vmx_set_xsave_msr(struct msr_data *msr_info) +{ + local_irq_disable(); + if (test_thread_flag(TIF_NEED_FPU_LOAD)) + switch_fpu_return(); + wrmsrl(msr_info->index, msr_info->data); + local_irq_enable(); +} + +#define CET_MSR_RSVD_BITS_1 GENMASK(1, 0) +#define CET_MSR_RSVD_BITS_2 GENMASK(9, 6) + +static bool cet_check_msr_write(struct kvm_vcpu *vcpu, + struct msr_data *msr, + u64 mask) +{ + u64 data = msr->data; + u32 high_word = data >> 32; + + if (data & mask) + return false; + + if (!is_64_bit_mode(vcpu) && high_word) + return false; + + return true; +} + +static bool cet_check_ssp_msr_access(struct kvm_vcpu *vcpu, + struct msr_data *msr) +{ + u32 index = msr->index; + + if (!boot_cpu_has(X86_FEATURE_SHSTK)) + return false; + + if (!msr->host_initiated && + !guest_cpuid_has(vcpu, X86_FEATURE_SHSTK)) + return false; + + if (index == MSR_IA32_INT_SSP_TAB) + return true; + + if (index == MSR_IA32_PL3_SSP) { + if (!(supported_xss & XFEATURE_MASK_CET_USER)) + return false; + } else if (!(supported_xss & XFEATURE_MASK_CET_KERNEL)) { + return false; + } + + return true; +} + +static bool cet_check_ctl_msr_access(struct kvm_vcpu *vcpu, + struct msr_data *msr) +{ + u32 index = msr->index; + + if (!boot_cpu_has(X86_FEATURE_SHSTK) && + !boot_cpu_has(X86_FEATURE_IBT)) + return false; + + if (!msr->host_initiated && + !guest_cpuid_has(vcpu, X86_FEATURE_SHSTK) && + !guest_cpuid_has(vcpu, X86_FEATURE_IBT)) + return false; + + if (index == MSR_IA32_U_CET) { + if (!(supported_xss & XFEATURE_MASK_CET_USER)) + return false; + } else if (!(supported_xss & XFEATURE_MASK_CET_KERNEL)) { + return false; + } + + return true; +} /* * Reads an msr value (of 'msr_index') into 'pdata'. * Returns 0 on success, non-0 otherwise. @@ -1941,6 +2026,26 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) else msr_info->data = vmx->pt_desc.guest.addr_a[index / 2]; break; + case MSR_IA32_S_CET: + if (!cet_check_ctl_msr_access(vcpu, msr_info)) + return 1; + msr_info->data = vmcs_readl(GUEST_S_CET); + break; + case MSR_IA32_INT_SSP_TAB: + if (!cet_check_ssp_msr_access(vcpu, msr_info)) + return 1; + msr_info->data = vmcs_readl(GUEST_INTR_SSP_TABLE); + break; + case MSR_IA32_U_CET: + if (!cet_check_ctl_msr_access(vcpu, msr_info)) + return 1; + vmx_get_xsave_msr(msr_info); + break; + case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP: + if (!cet_check_ssp_msr_access(vcpu, msr_info)) + return 1; + vmx_get_xsave_msr(msr_info); + break; case MSR_TSC_AUX: if (!msr_info->host_initiated && !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP)) @@ -2197,6 +2302,34 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) else vmx->pt_desc.guest.addr_a[index / 2] = data; break; + case MSR_IA32_S_CET: + if (!cet_check_ctl_msr_access(vcpu, msr_info)) + return 1; + if (!cet_check_msr_write(vcpu, msr_info, CET_MSR_RSVD_BITS_2)) + return 1; + vmcs_writel(GUEST_S_CET, data); + break; + case MSR_IA32_INT_SSP_TAB: + if (!cet_check_ctl_msr_access(vcpu, msr_info)) + return 1; + if (!is_64_bit_mode(vcpu)) + return 1; + vmcs_writel(GUEST_INTR_SSP_TABLE, data); + break; + case MSR_IA32_U_CET: + if (!cet_check_ctl_msr_access(vcpu, msr_info)) + return 1; + if (!cet_check_msr_write(vcpu, msr_info, CET_MSR_RSVD_BITS_2)) + return 1; + vmx_set_xsave_msr(msr_info); + break; + case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP: + if (!cet_check_ssp_msr_access(vcpu, msr_info)) + return 1; + if (!cet_check_msr_write(vcpu, msr_info, CET_MSR_RSVD_BITS_1)) + return 1; + vmx_set_xsave_msr(msr_info); + break; case MSR_TSC_AUX: if (!msr_info->host_initiated && !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP)) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 99e5b1df8555..3d5049faac58 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1229,6 +1229,10 @@ static const u32 msrs_to_save_all[] = { MSR_ARCH_PERFMON_EVENTSEL0 + 12, MSR_ARCH_PERFMON_EVENTSEL0 + 13, MSR_ARCH_PERFMON_EVENTSEL0 + 14, MSR_ARCH_PERFMON_EVENTSEL0 + 15, MSR_ARCH_PERFMON_EVENTSEL0 + 16, MSR_ARCH_PERFMON_EVENTSEL0 + 17, + + MSR_IA32_XSS, MSR_IA32_U_CET, MSR_IA32_S_CET, + MSR_IA32_PL0_SSP, MSR_IA32_PL1_SSP, MSR_IA32_PL2_SSP, + MSR_IA32_PL3_SSP, MSR_IA32_INT_SSP_TAB, }; static u32 msrs_to_save[ARRAY_SIZE(msrs_to_save_all)]; @@ -1504,6 +1508,13 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data, * invokes 64-bit SYSENTER. */ data = get_canonical(data, vcpu_virt_addr_bits(vcpu)); + break; + case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP: + case MSR_IA32_U_CET: + case MSR_IA32_S_CET: + case MSR_IA32_INT_SSP_TAB: + if (is_noncanonical_address(data, vcpu)) + return 1; } msr.data = data;
There're two different places storing Guest CET states, states managed with XSAVES/XRSTORS, as restored/saved in previous patch, can be read/write directly from/to the MSRs. For those stored in VMCS fields, they're access via vmcs_read/ vmcs_write. To correctly read/write the CET MSRs, it's necessary to check whether the kernel FPU context switch happened and reload guest FPU context if needed. Suggested-by: Sean Christopherson <sean.j.christopherson@intel.com> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com> --- arch/x86/kvm/vmx/vmx.c | 133 +++++++++++++++++++++++++++++++++++++++++ arch/x86/kvm/x86.c | 11 ++++ 2 files changed, 144 insertions(+)