From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3D474C5475B for ; Fri, 1 Mar 2024 12:00:40 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 82E216B0078; Fri, 1 Mar 2024 07:00:39 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 7DE3A6B007B; Fri, 1 Mar 2024 07:00:39 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 67F286B007D; Fri, 1 Mar 2024 07:00:39 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 573176B0078 for ; Fri, 1 Mar 2024 07:00:39 -0500 (EST) Received: from smtpin16.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 1DFF9141373 for ; Fri, 1 Mar 2024 12:00:39 +0000 (UTC) X-FDA: 81848328198.16.04FE3B6 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) by imf27.hostedemail.com (Postfix) with ESMTP id BB3E74000C for ; Fri, 1 Mar 2024 12:00:35 +0000 (UTC) Authentication-Results: imf27.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b="j961eMU/"; dmarc=pass (policy=none) header.from=intel.com; spf=none (imf27.hostedemail.com: domain of binbin.wu@linux.intel.com has no SPF policy when checking 192.198.163.13) smtp.mailfrom=binbin.wu@linux.intel.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1709294436; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=GzQRi+eA5+l6HakiTKeDIHtHAwi+J/TSaLzOC2cg6Ok=; b=2bBZhVOZTZf3w6Tz0C6OZplbA4RJX6LeLCyScBdWpMwRaDh6r1NGKuQbDhBoM+KHzOEaJg pjZnH9e7573SeLkB473UOtEIdAdCvjVF9D+brkKZdkcaUEtV4ptD9D8FARYzXp66xBaZ1U uNds3noxqrr5hKqtog0lsXDwsO1GGXA= ARC-Authentication-Results: i=1; imf27.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b="j961eMU/"; dmarc=pass (policy=none) header.from=intel.com; spf=none (imf27.hostedemail.com: domain of binbin.wu@linux.intel.com has no SPF policy when checking 192.198.163.13) smtp.mailfrom=binbin.wu@linux.intel.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1709294436; a=rsa-sha256; cv=none; b=nt4MMmkV9DjNhG4aCXqNENxVqUqFivw0ASpdOoRT379XJQhczmWVE9jk3CKJFaqLA784Z9 B+0oeq6P0zxisU0ktYh6ZRU1K72JKHxqgQShjK5fYUNQ7lvAxiPXJpKH1kH2U5Z3mFC1J1 oZtx1pNjrnYI9yX8/NF/9/IrA9dx6go= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1709294436; x=1740830436; h=message-id:date:mime-version:subject:to:cc:references: from:in-reply-to:content-transfer-encoding; bh=Bpm6hOspaqm5Ql7XCmGjGb3G6kC5f6KchwepD3KMdv4=; b=j961eMU//AH4nPuy30+Z42JVBqDECRhSGxp3z4XoXo0pYwA2TPakLzmC u2+UlYhv17AmS9o+PDPPAyqv0HlTZxSJRTnmjcL0DdhzD9mYd9ED+q7cF wXHFWwnOSEvtXXlfTBzPaCEhu14yvx2gzKo9yeVSwpW/EXrUOrJKzNXCO c5uXKiBqHT6wX2WerwapCwVVP9HrztZZT0M9CN+wHTror52SDbVQipX+a TsUx+yjwQIxuDRhIz/QUGDx90tYbx+yOOdcD8AonV4B6xPqhQO4xcozqX tdKJdGvRiwOIzU71Q/yAqNuhFay8MimYB3Ok4lIMIip7C25OZdc1o0/EE g==; X-IronPort-AV: E=McAfee;i="6600,9927,10999"; a="6780640" X-IronPort-AV: E=Sophos;i="6.06,196,1705392000"; d="scan'208";a="6780640" Received: from orviesa003.jf.intel.com ([10.64.159.143]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2024 04:00:28 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.06,196,1705392000"; d="scan'208";a="12863458" Received: from binbinwu-mobl.ccr.corp.intel.com (HELO [10.125.242.247]) ([10.125.242.247]) by ORVIESA003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Mar 2024 04:00:22 -0800 Message-ID: Date: Fri, 1 Mar 2024 20:00:19 +0800 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [RFC PATCH v5 15/29] KVM: selftests: TDX: Add TDX MSR read/write tests To: Sagi Shahar Cc: linux-kselftest@vger.kernel.org, Ackerley Tng , Ryan Afranji , Erdem Aktas , Isaku Yamahata , Sean Christopherson , Paolo Bonzini , Shuah Khan , Peter Gonda , Haibo Xu , Chao Peng , Vishal Annapurve , Roger Wang , Vipin Sharma , jmattson@google.com, dmatlack@google.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-mm@kvack.org References: <20231212204647.2170650-1-sagis@google.com> <20231212204647.2170650-16-sagis@google.com> From: Binbin Wu In-Reply-To: <20231212204647.2170650-16-sagis@google.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Rspamd-Queue-Id: BB3E74000C X-Rspam-User: X-Rspamd-Server: rspam02 X-Stat-Signature: o46mfb4pzu7w3fdwdtm753nrboft79fg X-HE-Tag: 1709294435-258411 X-HE-Meta: U2FsdGVkX19vpJBlT/MBvM+7n9ypFS5TdSjPhE94xZ3ELvIRALgcRl4L0vKyoR8VW6k3TTDIuZpM/uYwpYvAebWAss20gCtl5clb4JwlOgHruuVhCzyind1hItRWrw/byBoOhLOfxmrh26sJQC1ZH7RLY+gHYzmATYC3aGyDya8Xt0Lrs4E5RChyc7qGWGuZzgpZWB+6ZiPJAP7BhOXn6d4mqzKoH6SXzGYEP241HWFXFisOFHMQn8jVidHM6+SGf73ec06XXOGRodClx38OKewDFn/NyLLSZzk8zw2E98NseBWcO92bqKZxR2UFJqJYVnDDe8hZa6/xfFIF4UT95H2QwyEG5kQ/fO5Beez8j+OSoh7MvlQn3X/p/Ms7dJpKhUIH5SfimLK9VXzZXIWBVucV8GEqXlnJtmMoz8crGlqhkw8ls39Q5GK2+0vzDa9mmhg1OwesCiUlMDZR3jdbddvOv8CsTKtbhPFdrQjK9BwbrtGCkM6jJR0zFvbEoSWJHM9ZiwipRn49HsqoWLeA1V5b8I6FSiU1dc4iwMBVO/oEctCY0BuFpE1J9syr1UYSSdqNxSF1t4ohPWFXCmJDCgCvzpiLN1vBp/V37ekAIpGrtTarM8zrIFztUEn6NWvi4dZYyoM6g9xAsDHMf3TNb877DhTnEZfSg0LA5S75Jz0puVDOEHKdMT8r3e4ULJ9A7a+E4RrHAGw+8mzJE8UuEWJZoxT01dkckWYEbpWur/QTjHh3Q9YPun5Wx1men9Gmz6e17XisGb3AMqx67GYc++ZX/gydB8rKfsNLit0v1hEzX3SzFbViAUu6B88pEu9m6fRaIEfGCrXjvUVCzNLL7Lbja3Fpp3xQd2hPGqg1qs8x/cLwTTx9uu9xlPvNhre6/u8xkCYwvNN14EmBC0drBZX6S7ZhtnfalZQHAew4mV/cH7FK6tWAg8pqm7P7LKXZO2F/EQVHTeYvRFxKO9v gtl5aFxt 7h9fLLzPpoBahl6ZbrvNAY2PyJYemy8Nc+jg/267rTexBkkKKyeqW6N2RoIqQHGHyw0QsjE8K7HxA3JCWvzuzzzXriybnsq177CpSRF6h+HK8BtW1DtUsOoEWWZ2ajwjqTtj0VjqBsi4OK5ZknM0wla7+NPfJX/1zeeUmUD2Fxzk2wC1FzjhgYAEDvMkTQJoKwCG2 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: On 12/13/2023 4:46 AM, Sagi Shahar wrote: > The test verifies reads and writes for MSR registers with different access > level. > > Signed-off-by: Sagi Shahar > Signed-off-by: Ackerley Tng > Signed-off-by: Ryan Afranji > --- > .../selftests/kvm/include/x86_64/tdx/tdx.h | 5 + > .../selftests/kvm/lib/x86_64/tdx/tdx.c | 27 +++ > .../selftests/kvm/x86_64/tdx_vm_tests.c | 209 ++++++++++++++++++ > 3 files changed, 241 insertions(+) > > diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h > index 63788012bf94..85ba6aab79a7 100644 > --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h > +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h > @@ -9,11 +9,16 @@ > #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 > > #define TDG_VP_VMCALL_INSTRUCTION_IO 30 > +#define TDG_VP_VMCALL_INSTRUCTION_RDMSR 31 > +#define TDG_VP_VMCALL_INSTRUCTION_WRMSR 32 > + > void handle_userspace_tdg_vp_vmcall_exit(struct kvm_vcpu *vcpu); > uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size, > uint64_t write, uint64_t *data); > void tdg_vp_vmcall_report_fatal_error(uint64_t error_code, uint64_t data_gpa); > uint64_t tdg_vp_vmcall_get_td_vmcall_info(uint64_t *r11, uint64_t *r12, > uint64_t *r13, uint64_t *r14); > +uint64_t tdg_vp_vmcall_instruction_rdmsr(uint64_t index, uint64_t *ret_value); > +uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, uint64_t value); > > #endif // SELFTEST_TDX_TDX_H > diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c > index e5a9e13c62e2..88ea6f2a6469 100644 > --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c > +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c > @@ -87,3 +87,30 @@ uint64_t tdg_vp_vmcall_get_td_vmcall_info(uint64_t *r11, uint64_t *r12, > > return ret; > } > + > +uint64_t tdg_vp_vmcall_instruction_rdmsr(uint64_t index, uint64_t *ret_value) > +{ > + uint64_t ret; > + struct tdx_hypercall_args args = { > + .r11 = TDG_VP_VMCALL_INSTRUCTION_RDMSR, > + .r12 = index, > + }; > + > + ret = __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); > + > + if (ret_value) > + *ret_value = args.r11; > + > + return ret; > +} > + > +uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, uint64_t value) > +{ > + struct tdx_hypercall_args args = { > + .r11 = TDG_VP_VMCALL_INSTRUCTION_WRMSR, > + .r12 = index, > + .r13 = value, > + }; > + > + return __tdx_hypercall(&args, 0); > +} > diff --git a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c > index 699cba36e9ce..5db3701cc6d9 100644 > --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c > +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c > @@ -515,6 +515,213 @@ void verify_guest_reads(void) > printf("\t ... PASSED\n"); > } > > +/* > + * Define a filter which denies all MSR access except the following: > + * MSR_X2APIC_APIC_ICR: Allow read/write access (allowed by default) The default filtering behavior of tdx_msr_test_filter is KVM_MSR_FILTER_DEFAULT_DENY, and MSR_X2APIC_APIC_ICR is not covered by any specific range, shouldn't MSR_X2APIC_APIC_ICR be denied by default? > + * MSR_IA32_MISC_ENABLE: Allow read access > + * MSR_IA32_POWER_CTL: Allow write access > + */ > +#define MSR_X2APIC_APIC_ICR 0x830 > +static u64 tdx_msr_test_allow_bits = 0xFFFFFFFFFFFFFFFF; > +struct kvm_msr_filter tdx_msr_test_filter = { > + .flags = KVM_MSR_FILTER_DEFAULT_DENY, > + .ranges = { > + { > + .flags = KVM_MSR_FILTER_READ, > + .nmsrs = 1, > + .base = MSR_IA32_MISC_ENABLE, > + .bitmap = (uint8_t *)&tdx_msr_test_allow_bits, > + }, { > + .flags = KVM_MSR_FILTER_WRITE, > + .nmsrs = 1, > + .base = MSR_IA32_POWER_CTL, > + .bitmap = (uint8_t *)&tdx_msr_test_allow_bits, > + }, > + }, > +}; > + > +/* > + * Verifies MSR read functionality. > + */ > +void guest_msr_read(void) > +{ > + uint64_t data; > + uint64_t ret; > + > + ret = tdg_vp_vmcall_instruction_rdmsr(MSR_X2APIC_APIC_ICR, &data); > + if (ret) > + tdx_test_fatal(ret); > + > + ret = tdx_test_report_64bit_to_user_space(data); > + if (ret) > + tdx_test_fatal(ret); > + > + ret = tdg_vp_vmcall_instruction_rdmsr(MSR_IA32_MISC_ENABLE, &data); > + if (ret) > + tdx_test_fatal(ret); > + > + ret = tdx_test_report_64bit_to_user_space(data); > + if (ret) > + tdx_test_fatal(ret); > + > + /* We expect this call to fail since MSR_IA32_POWER_CTL is write only */ > + ret = tdg_vp_vmcall_instruction_rdmsr(MSR_IA32_POWER_CTL, &data); > + if (ret) { > + ret = tdx_test_report_64bit_to_user_space(ret); > + if (ret) > + tdx_test_fatal(ret); > + } else { > + tdx_test_fatal(-99); > + } > + > + tdx_test_success(); > +} > + > +void verify_guest_msr_reads(void) > +{ > + struct kvm_vm *vm; > + struct kvm_vcpu *vcpu; > + > + uint64_t data; > + int ret; > + > + vm = td_create(); > + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); > + > + /* > + * Set explicit MSR filter map to control access to the MSR registers > + * used in the test. > + */ > + printf("\t ... Setting test MSR filter\n"); > + ret = kvm_check_cap(KVM_CAP_X86_USER_SPACE_MSR); > + TEST_ASSERT(ret, "KVM_CAP_X86_USER_SPACE_MSR is unavailable"); > + vm_enable_cap(vm, KVM_CAP_X86_USER_SPACE_MSR, KVM_MSR_EXIT_REASON_FILTER); > + > + ret = kvm_check_cap(KVM_CAP_X86_MSR_FILTER); > + TEST_ASSERT(ret, "KVM_CAP_X86_MSR_FILTER is unavailable"); > + > + ret = ioctl(vm->fd, KVM_X86_SET_MSR_FILTER, &tdx_msr_test_filter); > + TEST_ASSERT(ret == 0, > + "KVM_X86_SET_MSR_FILTER failed, ret: %i errno: %i (%s)", > + ret, errno, strerror(errno)); > + > + vcpu = td_vcpu_add(vm, 0, guest_msr_read); > + td_finalize(vm); > + > + printf("Verifying guest msr reads:\n"); > + > + printf("\t ... Setting test MSR values\n"); > + /* Write arbitrary to the MSRs. */ > + vcpu_set_msr(vcpu, MSR_X2APIC_APIC_ICR, 4); > + vcpu_set_msr(vcpu, MSR_IA32_MISC_ENABLE, 5); > + vcpu_set_msr(vcpu, MSR_IA32_POWER_CTL, 6); > + > + printf("\t ... Running guest\n"); > + td_vcpu_run(vcpu); > + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); > + data = tdx_test_read_64bit_report_from_guest(vcpu); > + TEST_ASSERT_EQ(data, 4); > + > + td_vcpu_run(vcpu); > + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); > + data = tdx_test_read_64bit_report_from_guest(vcpu); > + TEST_ASSERT_EQ(data, 5); > + > + td_vcpu_run(vcpu); > + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); > + data = tdx_test_read_64bit_report_from_guest(vcpu); > + TEST_ASSERT_EQ(data, TDG_VP_VMCALL_INVALID_OPERAND); > + > + td_vcpu_run(vcpu); > + TDX_TEST_ASSERT_SUCCESS(vcpu); > + > + kvm_vm_free(vm); > + printf("\t ... PASSED\n"); > +} > + > +/* > + * Verifies MSR write functionality. > + */ > +void guest_msr_write(void) > +{ > + uint64_t ret; > + > + ret = tdg_vp_vmcall_instruction_wrmsr(MSR_X2APIC_APIC_ICR, 4); > + if (ret) > + tdx_test_fatal(ret); > + > + /* We expect this call to fail since MSR_IA32_MISC_ENABLE is read only */ > + ret = tdg_vp_vmcall_instruction_wrmsr(MSR_IA32_MISC_ENABLE, 5); > + if (ret) { > + ret = tdx_test_report_64bit_to_user_space(ret); > + if (ret) > + tdx_test_fatal(ret); > + } else { > + tdx_test_fatal(-99); > + } > + > + > + ret = tdg_vp_vmcall_instruction_wrmsr(MSR_IA32_POWER_CTL, 6); > + if (ret) > + tdx_test_fatal(ret); > + > + tdx_test_success(); > +} > + > +void verify_guest_msr_writes(void) > +{ > + struct kvm_vcpu *vcpu; > + struct kvm_vm *vm; > + > + uint64_t data; > + int ret; > + > + vm = td_create(); > + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); > + > + /* > + * Set explicit MSR filter map to control access to the MSR registers > + * used in the test. > + */ > + printf("\t ... Setting test MSR filter\n"); > + ret = kvm_check_cap(KVM_CAP_X86_USER_SPACE_MSR); > + TEST_ASSERT(ret, "KVM_CAP_X86_USER_SPACE_MSR is unavailable"); > + vm_enable_cap(vm, KVM_CAP_X86_USER_SPACE_MSR, KVM_MSR_EXIT_REASON_FILTER); > + > + ret = kvm_check_cap(KVM_CAP_X86_MSR_FILTER); > + TEST_ASSERT(ret, "KVM_CAP_X86_MSR_FILTER is unavailable"); > + > + ret = ioctl(vm->fd, KVM_X86_SET_MSR_FILTER, &tdx_msr_test_filter); > + TEST_ASSERT(ret == 0, > + "KVM_X86_SET_MSR_FILTER failed, ret: %i errno: %i (%s)", > + ret, errno, strerror(errno)); > + > + vcpu = td_vcpu_add(vm, 0, guest_msr_write); > + td_finalize(vm); > + > + printf("Verifying guest msr writes:\n"); > + > + printf("\t ... Running guest\n"); > + /* Only the write to MSR_IA32_MISC_ENABLE should trigger an exit */ > + td_vcpu_run(vcpu); > + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); > + data = tdx_test_read_64bit_report_from_guest(vcpu); > + TEST_ASSERT_EQ(data, TDG_VP_VMCALL_INVALID_OPERAND); > + > + td_vcpu_run(vcpu); > + TDX_TEST_ASSERT_SUCCESS(vcpu); > + > + printf("\t ... Verifying MSR values writen by guest\n"); > + > + TEST_ASSERT_EQ(vcpu_get_msr(vcpu, MSR_X2APIC_APIC_ICR), 4); > + TEST_ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_MISC_ENABLE), 0x1800); > + TEST_ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_POWER_CTL), 6); > + > + kvm_vm_free(vm); > + printf("\t ... PASSED\n"); > +} > + > + > int main(int argc, char **argv) > { > setbuf(stdout, NULL); > @@ -531,6 +738,8 @@ int main(int argc, char **argv) > run_in_new_process(&verify_get_td_vmcall_info); > run_in_new_process(&verify_guest_writes); > run_in_new_process(&verify_guest_reads); > + run_in_new_process(&verify_guest_msr_writes); > + run_in_new_process(&verify_guest_msr_reads); > > return 0; > }