On Fri, Mar 01, 2024 at 08:02:43PM +0800, Yan Zhao wrote: > > +void guest_shared_mem(void) > > +{ > > + uint32_t *test_mem_shared_gva = > > + (uint32_t *)TDX_SHARED_MEM_TEST_SHARED_GVA; > > + > > + uint64_t placeholder; > > + uint64_t ret; > > + > > + /* Map gpa as shared */ > > + ret = tdg_vp_vmcall_map_gpa(test_mem_shared_gpa, PAGE_SIZE, > > + &placeholder); > > + if (ret) > > + tdx_test_fatal_with_data(ret, __LINE__); > > + > > + *test_mem_shared_gva = TDX_SHARED_MEM_TEST_GUEST_WRITE_VALUE; > > + > > + /* Exit so host can read shared value */ > > + ret = tdg_vp_vmcall_instruction_io(TDX_SHARED_MEM_TEST_INFO_PORT, 4, > > + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE, > > + &placeholder); > > + if (ret) > > + tdx_test_fatal_with_data(ret, __LINE__); > > + > > + /* Read value written by host and send it back out for verification */ > > + ret = tdg_vp_vmcall_instruction_io(TDX_SHARED_MEM_TEST_INFO_PORT, 4, > > + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE, > > + (uint64_t *)test_mem_shared_gva); > > + if (ret) > > + tdx_test_fatal_with_data(ret, __LINE__); > > +} > > + > > +int verify_shared_mem(void) > > +{ > > + struct kvm_vm *vm; > > + struct kvm_vcpu *vcpu; > > + > > + vm_vaddr_t test_mem_private_gva; > > + uint32_t *test_mem_hva; > > + > > + vm = td_create(); > > + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); > > + vcpu = td_vcpu_add(vm, 0, guest_shared_mem); > > + > > + /* > > + * Set up shared memory page for testing by first allocating as private > > + * and then mapping the same GPA again as shared. This way, the TD does > > + * not have to remap its page tables at runtime. > > + */ > > + test_mem_private_gva = vm_vaddr_alloc(vm, vm->page_size, > > + TDX_SHARED_MEM_TEST_PRIVATE_GVA); > > + TEST_ASSERT_EQ(test_mem_private_gva, TDX_SHARED_MEM_TEST_PRIVATE_GVA); > > + > > + test_mem_hva = addr_gva2hva(vm, test_mem_private_gva); > > + TEST_ASSERT(test_mem_hva != NULL, > > + "Guest address not found in guest memory regions\n"); > > + > > + test_mem_private_gpa = addr_gva2gpa(vm, test_mem_private_gva); > > + virt_pg_map_shared(vm, TDX_SHARED_MEM_TEST_SHARED_GVA, > > + test_mem_private_gpa); > > + > > + test_mem_shared_gpa = test_mem_private_gpa | BIT_ULL(vm->pa_bits - 1); > > + sync_global_to_guest(vm, test_mem_private_gpa); > > + sync_global_to_guest(vm, test_mem_shared_gpa); > > + > > + td_finalize(vm); > > + > > + printf("Verifying shared memory accesses for TDX\n"); > > + > > + /* Begin guest execution; guest writes to shared memory. */ > > + printf("\t ... Starting guest execution\n"); > > + > > + /* Handle map gpa as shared */ > > + td_vcpu_run(vcpu); > > + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); > The first VMExit should be caused by tdvmcall map gpa, so it's > impossible to be guest failure. > Ah, if KVM has bugs and returns to guest's map gpa tdvmcall as error without exiting to user space, then it's possible to meet guest failure here. > Move this line TDX_TEST_CHECK_GUEST_FAILURE(vcpu) to after the next td_vcpu_run() > is better. So, looks it's required to be checked after every vcpu run. Without checking it (as in below), the selftest will not be able to print out the guest reported fatal error. > > + > > + td_vcpu_run(vcpu); > > + TDX_TEST_ASSERT_IO(vcpu, TDX_SHARED_MEM_TEST_INFO_PORT, 4, > > + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); > > + TEST_ASSERT_EQ(*test_mem_hva, TDX_SHARED_MEM_TEST_GUEST_WRITE_VALUE); > > + > > + *test_mem_hva = TDX_SHARED_MEM_TEST_HOST_WRITE_VALUE; > > + td_vcpu_run(vcpu); > > + TDX_TEST_ASSERT_IO(vcpu, TDX_SHARED_MEM_TEST_INFO_PORT, 4, > > + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); > > + TEST_ASSERT_EQ( > > + *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset), > > + TDX_SHARED_MEM_TEST_HOST_WRITE_VALUE); > > + > > + printf("\t ... PASSED\n"); > > + > > + kvm_vm_free(vm); > > + > > + return 0; > > +} > >