From: Isaku Yamahata <isaku.yamahata@xxxxxxxxx> MapGPA is a hypercall to convert GPA from/to private GPA to/from shared GPA. As the conversion function is already implemented as kvm_convert_memory, wire it to TDX hypercall exit. Signed-off-by: Isaku Yamahata <isaku.yamahata@xxxxxxxxx> Signed-off-by: Xiaoyao Li <xiaoyao.li@xxxxxxxxx> --- accel/kvm/kvm-all.c | 2 +- include/sysemu/kvm.h | 2 ++ target/i386/kvm/tdx.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 8d53c89e9dbf..b0a18800fd63 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3059,7 +3059,7 @@ static void kvm_eat_signals(CPUState *cpu) } while (sigismember(&chkset, SIG_IPI)); } -static int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private) +int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private) { MemoryRegionSection section; void *addr; diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index d89ec87072d7..7e0f56d1c5c5 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -584,4 +584,6 @@ uint32_t kvm_dirty_ring_size(void); int kvm_set_memory_attributes_private(hwaddr start, hwaddr size); int kvm_set_memory_attributes_shared(hwaddr start, hwaddr size); + +int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private); #endif diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c index fa658ce1f2e4..0c43c1f7759f 100644 --- a/target/i386/kvm/tdx.c +++ b/target/i386/kvm/tdx.c @@ -934,6 +934,7 @@ static void tdx_guest_class_init(ObjectClass *oc, void *data) { } +#define TDG_VP_VMCALL_MAP_GPA 0x10001ULL #define TDG_VP_VMCALL_GET_QUOTE 0x10002ULL #define TDG_VP_VMCALL_SETUP_EVENT_NOTIFY_INTERRUPT 0x10004ULL @@ -993,6 +994,39 @@ static hwaddr tdx_shared_bit(X86CPU *cpu) return (cpu->phys_bits > 48) ? BIT_ULL(51) : BIT_ULL(47); } +static void tdx_handle_map_gpa(X86CPU *cpu, struct kvm_tdx_vmcall *vmcall) +{ + hwaddr shared_bit = tdx_shared_bit(cpu); + hwaddr gpa = vmcall->in_r12 & ~shared_bit; + bool private = !(vmcall->in_r12 & shared_bit); + hwaddr size = vmcall->in_r13; + int ret = 0; + + vmcall->status_code = TDG_VP_VMCALL_INVALID_OPERAND; + + if (!QEMU_IS_ALIGNED(gpa, 4096) || !QEMU_IS_ALIGNED(size, 4096)) { + vmcall->status_code = TDG_VP_VMCALL_ALIGN_ERROR; + return; + } + + /* Overflow case. */ + if (gpa + size < gpa) { + return; + } + if (gpa >= (1ULL << cpu->phys_bits) || + gpa + size >= (1ULL << cpu->phys_bits)) { + return; + } + + if (size > 0) { + ret = kvm_convert_memory(gpa, size, private); + } + + if (!ret) { + vmcall->status_code = TDG_VP_VMCALL_SUCCESS; + } +} + struct tdx_get_quote_task { uint32_t apic_id; hwaddr gpa; @@ -1384,6 +1418,9 @@ static void tdx_handle_vmcall(X86CPU *cpu, struct kvm_tdx_vmcall *vmcall) } switch (vmcall->subfunction) { + case TDG_VP_VMCALL_MAP_GPA: + tdx_handle_map_gpa(cpu, vmcall); + break; case TDG_VP_VMCALL_GET_QUOTE: tdx_handle_get_quote(cpu, vmcall); break; -- 2.34.1