> +/* > + * TDG.VP.INFO call from the guest. Verify the right values are returned > + */ > +void verify_tdcall_vp_info(void) > +{ > + const int num_vcpus = 2; > + struct kvm_vcpu *vcpus[num_vcpus]; > + struct kvm_vm *vm; > + > + uint64_t rcx, rdx, r8, r9, r10, r11; > + uint32_t ret_num_vcpus, ret_max_vcpus; > + uint64_t attributes; > + uint32_t i; > + const struct kvm_cpuid_entry2 *cpuid_entry; > + int max_pa = -1; > + > + vm = td_create(); > + > +#define TDX_TDPARAM_ATTR_SEPT_VE_DISABLE_BIT (1UL << 28) > +#define TDX_TDPARAM_ATTR_PKS_BIT (1UL << 30) > + /* Setting attributes parameter used by TDH.MNG.INIT to 0x50000000 */ > + attributes = TDX_TDPARAM_ATTR_SEPT_VE_DISABLE_BIT | > + TDX_TDPARAM_ATTR_PKS_BIT; > + > + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, attributes); > + > + for (i = 0; i < num_vcpus; i++) > + vcpus[i] = td_vcpu_add(vm, i, guest_tdcall_vp_info); > + > + td_finalize(vm); > + > + printf("Verifying TDG.VP.INFO call:\n"); > + > + /* Get KVM CPUIDs for reference */ > + cpuid_entry = get_cpuid_entry(kvm_get_supported_cpuid(), 0x80000008, 0); > + TEST_ASSERT(cpuid_entry, "CPUID entry missing\n"); > + max_pa = cpuid_entry->eax & 0xff; > + > + for (i = 0; i < num_vcpus; i++) { > + struct kvm_vcpu *vcpu = vcpus[i]; > + > + /* Wait for guest to report rcx value */ > + td_vcpu_run(vcpu); > + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); > + rcx = tdx_test_read_64bit_report_from_guest(vcpu); > + > + /* Wait for guest to report rdx value */ > + td_vcpu_run(vcpu); > + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); > + rdx = tdx_test_read_64bit_report_from_guest(vcpu); > + > + /* Wait for guest to report r8 value */ > + td_vcpu_run(vcpu); > + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); > + r8 = tdx_test_read_64bit_report_from_guest(vcpu); > + > + /* Wait for guest to report r9 value */ > + td_vcpu_run(vcpu); > + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); > + r9 = tdx_test_read_64bit_report_from_guest(vcpu); > + > + /* Wait for guest to report r10 value */ > + td_vcpu_run(vcpu); > + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); > + r10 = tdx_test_read_64bit_report_from_guest(vcpu); > + > + /* Wait for guest to report r11 value */ > + td_vcpu_run(vcpu); > + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); > + r11 = tdx_test_read_64bit_report_from_guest(vcpu); > + > + ret_num_vcpus = r8 & 0xFFFFFFFF; > + ret_max_vcpus = (r8 >> 32) & 0xFFFFFFFF; > + > + /* first bits 5:0 of rcx represent the GPAW */ > + TEST_ASSERT_EQ(rcx & 0x3F, max_pa); > + /* next 63:6 bits of rcx is reserved and must be 0 */ > + TEST_ASSERT_EQ(rcx >> 6, 0); > + TEST_ASSERT_EQ(rdx, attributes); > + TEST_ASSERT_EQ(ret_num_vcpus, num_vcpus); > + TEST_ASSERT_EQ(ret_max_vcpus, 512); Better to assert of kvm_check_cap(KVM_CAP_MAX_VCPUS) here . > + /* VCPU_INDEX = i */ > + TEST_ASSERT_EQ(r9, i); > + /* > + * verify reserved bits are 0 > + * r10 bit 0 (SYS_RD) indicates that the TDG.SYS.RD/RDM/RDALL > + * functions are available and can be either 0 or 1. > + */ > + TEST_ASSERT_EQ(r10 & ~1, 0); > + TEST_ASSERT_EQ(r11, 0); > + > + /* Wait for guest to complete execution */ > + td_vcpu_run(vcpu); > + > + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); > + TDX_TEST_ASSERT_SUCCESS(vcpu); > + > + printf("\t ... Guest completed run on VCPU=%u\n", i); > + } > + > + kvm_vm_free(vm); > + printf("\t ... PASSED\n"); > +} > + > int main(int argc, char **argv) > { > setbuf(stdout, NULL); > @@ -1169,6 +1313,7 @@ int main(int argc, char **argv) > run_in_new_process(&verify_mmio_writes); > run_in_new_process(&verify_td_cpuid_tdcall); > run_in_new_process(&verify_host_reading_private_mem); > + run_in_new_process(&verify_tdcall_vp_info); > > return 0; > } > -- > 2.43.0.472.g3155946c3a-goog > >