From patchwork Sat Jan 21 00:15:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110726 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 63141C05027 for ; Sat, 21 Jan 2023 00:16:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229685AbjAUAQT (ORCPT ); Fri, 20 Jan 2023 19:16:19 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51760 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229636AbjAUAQS (ORCPT ); Fri, 20 Jan 2023 19:16:18 -0500 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B39C6917C8 for ; Fri, 20 Jan 2023 16:16:15 -0800 (PST) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-4c2d68b6969so65059767b3.7 for ; Fri, 20 Jan 2023 16:16:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=ubxGTk6gAS1cIf2CC99mo1vpnAlsFSvC6HXfL0FfYMo=; b=IB1WGTuvu8nhLqPJU6KIdsFohzOBKSI4NnuM0fwFx8tGKjnp0lx6I8O1+Ev+HPMvNt KtBBAMvONZubRoRoIahe13qF3I7FnV79jYBJVhT21MPmGWCWSormgW0W4/8sY2Bfrivh VGH+WQwesc8Ed/S2AIivkxK84nf6Ldyb0/jWJrqi36WR6ZIMyLRy/E8VD4zeDtqM3N8J BNaDwctQ7qJWu6xRrSOW0/oLrLgIvf+R8pMO5/YAZoPuy3ZKXsRGnA85QLxFtVPGqNNB wYucvMLaUOTUCPUT3GEv5oJAzhoKFt/zNUBRjX+oPVmggUmLN91tMe1jGx2/afChYK1F +0ZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=ubxGTk6gAS1cIf2CC99mo1vpnAlsFSvC6HXfL0FfYMo=; b=mwKo1lK8ufOSPq6C2iKi49omYkSqWcM0iKhOPIOLVqvmpTSYvKcJmQ+bjp2vqCGB1i DI/T6pHnURuvu/fYdcUwCRIrATmH+Y9pNeS0OFVlrk88JLL3cGxJ8vj46cNRhK1QOMY4 CYgionBw8wv+hTj4P0AHZ63pp9W0IZzX6KJJSC+smM/tT2RCsaBmilGuElXA82jjmKVW iL75ClouL1wv+9RD9/qptf/WKgR15Z7SB+NAOPb4qx24onn4CoMGfkjbHnh40dBFk4Ek J/FKmVvxHbSeyHNgjLsPRYvAkzX5JKapOVbao1JEZI6ls61Dvr2qvBTq2KM6whG+qv0p ynNw== X-Gm-Message-State: AFqh2kolQrBpdNDK5ucpE7bp2ja3r3kVOfq/+4P3LR9a+5CaiCZtBLYE B9XWOX5yHVQmNqnl+vs1aURkYTt07m8UImFt7A== X-Google-Smtp-Source: AMrXdXvR4ngP8OHu6BGxNu6WmvbrozuSzGpPfbhE1kHKUamx/22mwB0GXXs6Zy+c1rqPTIpgCwWWkaq6iKRnwG5Eqg== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a25:d10a:0:b0:7ff:48e9:4d09 with SMTP id i10-20020a25d10a000000b007ff48e94d09mr506496ybg.440.1674260174863; Fri, 20 Jan 2023 16:16:14 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:12 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-2-ackerleytng@google.com> Subject: [RFC PATCH v3 01/31] KVM: selftests: Add function to allow one-to-one GVA to GPA mappings From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org One-to-one GVA to GPA mappings can be used in the guest to set up boot sequences during which paging is enabled, hence requiring a transition from using physical to virtual addresses in consecutive instructions. Signed-off-by: Ackerley Tng --- .../selftests/kvm/include/kvm_util_base.h | 2 ++ tools/testing/selftests/kvm/lib/kvm_util.c | 35 ++++++++++++++++--- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index 8dac0f49d20b9..0db5cd4b8383a 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -402,6 +402,8 @@ void vm_mem_region_delete(struct kvm_vm *vm, uint32_t slot); struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id); vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min); vm_vaddr_t vm_vaddr_alloc_shared(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min); +vm_vaddr_t vm_vaddr_alloc_1to1(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, + uint32_t data_memslot); vm_vaddr_t vm_vaddr_alloc_pages(struct kvm_vm *vm, int nr_pages); vm_vaddr_t vm_vaddr_alloc_page(struct kvm_vm *vm); diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index fa8aea97cdb62..5257bce6f546d 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1237,6 +1237,8 @@ static vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm *vm, size_t sz, * vm - Virtual Machine * sz - Size in bytes * vaddr_min - Minimum starting virtual address + * paddr_min - Minimum starting physical address + * data_memslot - memslot number to allocate in * encrypt - Whether the region should be handled as encrypted * * Output Args: None @@ -1251,14 +1253,15 @@ static vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm *vm, size_t sz, * a page. */ static vm_vaddr_t -_vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, bool encrypt) +_vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, + vm_paddr_t paddr_min, uint32_t data_memslot, bool encrypt) { uint64_t pages = (sz >> vm->page_shift) + ((sz % vm->page_size) != 0); virt_pgd_alloc(vm); vm_paddr_t paddr = _vm_phy_pages_alloc(vm, pages, - KVM_UTIL_MIN_PFN * vm->page_size, - 0, encrypt); + paddr_min, + data_memslot, encrypt); /* * Find an unused range of virtual page addresses of at least @@ -1281,12 +1284,34 @@ _vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, bool encrypt vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min) { - return _vm_vaddr_alloc(vm, sz, vaddr_min, vm->protected); + return _vm_vaddr_alloc(vm, sz, vaddr_min, + KVM_UTIL_MIN_PFN * vm->page_size, 0, + vm->protected); } vm_vaddr_t vm_vaddr_alloc_shared(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min) { - return _vm_vaddr_alloc(vm, sz, vaddr_min, false); + return _vm_vaddr_alloc(vm, sz, vaddr_min, + KVM_UTIL_MIN_PFN * vm->page_size, 0, false); +} + +/** + * Allocate memory in @vm of size @sz in memslot with id @data_memslot, + * beginning with the desired address of @vaddr_min. + * + * If there isn't enough memory at @vaddr_min, find the next possible address + * that can meet the requested size in the given memslot. + * + * Return the address where the memory is allocated. + */ +vm_vaddr_t vm_vaddr_alloc_1to1(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, + uint32_t data_memslot) +{ + vm_vaddr_t gva = _vm_vaddr_alloc(vm, sz, vaddr_min, (vm_paddr_t) vaddr_min, + data_memslot, vm->protected); + ASSERT_EQ(gva, addr_gva2gpa(vm, gva)); + + return gva; } /* From patchwork Sat Jan 21 00:15:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110727 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 79FBDC05027 for ; Sat, 21 Jan 2023 00:16:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229882AbjAUAQg (ORCPT ); Fri, 20 Jan 2023 19:16:36 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52192 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229661AbjAUAQa (ORCPT ); Fri, 20 Jan 2023 19:16:30 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F38009FDE0 for ; Fri, 20 Jan 2023 16:16:19 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id w14-20020a25ac0e000000b007d519140f18so7435919ybi.3 for ; Fri, 20 Jan 2023 16:16:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=T7o4vSmm7ZL1KEassKDMWSbS80FYjDRO3LkEb1B3l7A=; b=Ol7HjVscoT8ho/9hbUrrCazQ67jYdiv/WqZ3xCCEBOmLMoRYL3BVBpX9yE4cKVDNaM k2Bs1B5PSpElX8QFPMjeAqEYDtW6CtPgpDi+gHVAujrUnMRQfAvsZpqSatGSNrRowTaY qWOU0SderZMc9TdF+m65z5N/Gy26LtNslf/DkyoJYelWAo3xwiQtDsGz+8R91hjiD+1B l5KYpyddlEv1NtUoggfZL9Kb5LuD9WrfVdLaMcy96u+xYmf8sycyvox4f0JLDUf/+mvX dEbJG3xxtHu7lbyab1L26tQFECJWcXKTfIsiqYhE4WfGeXUMwnPZA6OXAjwJsBj9Ko2T /7RA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=T7o4vSmm7ZL1KEassKDMWSbS80FYjDRO3LkEb1B3l7A=; b=KTjitksu6CaTdx7DFj/98yltmZqgnO+1p32BPyL9pkU1TmoCJuCz8OakkqsSB3CoXS CdOZ6yl332033GH0mis8AD/dvm0B/cMzlSw788+tnChQ+22vijsIXdXHct7tThccChvv Wi/qAnCGTcT3fTujvQYVTj6j9qGna5N1Lt2fJDC8jKiJ5a2D2GboeuJwjqA9bsq9H+WJ fXuUG87d2ySVedfDPKg0eZgVje6kDYsNQvwHyqIQCs5litVBlNU7B0OYQwzCSxSHSRot d5mE4J9LcNWqh1hbZPiV2m49TI35ZoiIIxF2xH3jZ0t0/JNQpxyTe+lzMNs4byxeOctG UJUg== X-Gm-Message-State: AFqh2kq5L3E0zJwK1OhtYn8tx4l8KCFIl0Fm6wNZnt04WlV6RN2QcLzI ynMhnsPxuIRY6P6Ixx2r1WR9fCtrI2hvezNvpw== X-Google-Smtp-Source: AMrXdXvb6e+7GbFt53kF2e0bJ3VgqeUIfUKaID4GUf2ASLS61yYJrydHuxqaqc5U/Mq13V5eDDpJ8IqcnwLc8SZnBQ== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a0d:d5c6:0:b0:4ef:ce3a:a54 with SMTP id x189-20020a0dd5c6000000b004efce3a0a54mr2181857ywd.485.1674260179077; Fri, 20 Jan 2023 16:16:19 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:13 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-3-ackerleytng@google.com> Subject: [RFC PATCH v3 02/31] KVM: selftests: Add support for creating non-default type VMs From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Erdem Aktas Currently vm_create function only creates KVM_VM_TYPE_DEFAULT type VMs. Adding type parameter to ____vm_create to create new VM types. Signed-off-by: Erdem Aktas Reviewed-by: David Matlack Signed-off-by: Ryan Afranji Signed-off-by: Sagi Shahar Signed-off-by: Ackerley Tng --- tools/testing/selftests/kvm/include/kvm_util_base.h | 6 ++++-- tools/testing/selftests/kvm/lib/kvm_util.c | 6 +++--- tools/testing/selftests/kvm/lib/x86_64/sev.c | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index 0db5cd4b8383a..0fa4dab3d8e52 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -27,6 +27,8 @@ #define NSEC_PER_SEC 1000000000L +#define KVM_VM_TYPE_DEFAULT 0 + typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */ typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */ @@ -686,13 +688,13 @@ uint64_t vm_nr_pages_required(enum vm_guest_mode mode, * __vm_create() does NOT create vCPUs, @nr_runnable_vcpus is used purely to * calculate the amount of memory needed for per-vCPU data, e.g. stacks. */ -struct kvm_vm *____vm_create(enum vm_guest_mode mode, uint64_t nr_pages); +struct kvm_vm *____vm_create(enum vm_guest_mode mode, uint64_t nr_pages, int type); struct kvm_vm *__vm_create(enum vm_guest_mode mode, uint32_t nr_runnable_vcpus, uint64_t nr_extra_pages); static inline struct kvm_vm *vm_create_barebones(void) { - return ____vm_create(VM_MODE_DEFAULT, 0); + return ____vm_create(VM_MODE_DEFAULT, 0, KVM_VM_TYPE_DEFAULT); } static inline struct kvm_vm *vm_create(uint32_t nr_runnable_vcpus) diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 5257bce6f546d..14246f0fd2e78 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -185,7 +185,7 @@ const struct vm_guest_mode_params vm_guest_mode_params[] = { _Static_assert(sizeof(vm_guest_mode_params)/sizeof(struct vm_guest_mode_params) == NUM_VM_MODES, "Missing new mode params?"); -struct kvm_vm *____vm_create(enum vm_guest_mode mode, uint64_t nr_pages) +struct kvm_vm *____vm_create(enum vm_guest_mode mode, uint64_t nr_pages, int type) { struct kvm_vm *vm; @@ -201,7 +201,7 @@ struct kvm_vm *____vm_create(enum vm_guest_mode mode, uint64_t nr_pages) hash_init(vm->regions.slot_hash); vm->mode = mode; - vm->type = 0; + vm->type = type; vm->pa_bits = vm_guest_mode_params[mode].pa_bits; vm->va_bits = vm_guest_mode_params[mode].va_bits; @@ -337,7 +337,7 @@ struct kvm_vm *__vm_create(enum vm_guest_mode mode, uint32_t nr_runnable_vcpus, struct userspace_mem_region *slot0; struct kvm_vm *vm; - vm = ____vm_create(mode, nr_pages); + vm = ____vm_create(mode, nr_pages, KVM_VM_TYPE_DEFAULT); kvm_vm_elf_load(vm, program_invocation_name); diff --git a/tools/testing/selftests/kvm/lib/x86_64/sev.c b/tools/testing/selftests/kvm/lib/x86_64/sev.c index faed2ebe63ac9..dedfd9f45cfb3 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/sev.c +++ b/tools/testing/selftests/kvm/lib/x86_64/sev.c @@ -221,7 +221,7 @@ struct kvm_vm *vm_sev_create_with_one_vcpu(uint32_t policy, void *guest_code, uint64_t nr_pages = vm_nr_pages_required(mode, 1, 0); struct kvm_vm *vm; - vm = ____vm_create(mode, nr_pages); + vm = ____vm_create(mode, nr_pages, KVM_VM_TYPE_DEFAULT); kvm_sev_ioctl(vm, KVM_SEV_INIT, NULL); From patchwork Sat Jan 21 00:15:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110728 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DFA24C05027 for ; Sat, 21 Jan 2023 00:16:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229840AbjAUAQj (ORCPT ); Fri, 20 Jan 2023 19:16:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52308 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229877AbjAUAQg (ORCPT ); Fri, 20 Jan 2023 19:16:36 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1C176B4E29 for ; Fri, 20 Jan 2023 16:16:24 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id i17-20020a25bc11000000b007b59a5b74aaso7384618ybh.7 for ; Fri, 20 Jan 2023 16:16:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=BLjdusZm+xjhNzljGhXw4f9568iWucER7Te8w8OqhFs=; b=TDIaCVqYeIkQPZRKMJoacHO6RWwqZ2saZD80hqMq+dsF0MaeVOmsLzBudmhT2LAPx6 zXDGZGPegVLI4pfT2pxUSy2kD77TugYTngV83uqsZH0JbgQjUo3PECb0APIQb47XYCU9 FqwQQ0drC8OvMGcqLF17TkJ2k0eZfsT1Zrg/5meqhIngWjQD5BqlijWlRxExc0y3Uu4d IIJ6t3o1ybuEgQVMCJCJG2Jxzi/FF9RYYuTrxEZU/uPetZKthsFlpDy6vDTBeTw+dVz5 xnBH5JLrC3+jM+Bgx5gy7skPT/bfFSb6GNucSPJw/48hiZ7D2UOe1g//87WZ714vK9yr 5zXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=BLjdusZm+xjhNzljGhXw4f9568iWucER7Te8w8OqhFs=; b=WAeV5Ph3BBf1n6K9fLfaeGBNC8qJlmoQh8PFgLb7Er1yhCHb/ch2D9Xcv28bfsr24w QbjsPwgLzNyfaP93ukVTyIUjvSbyThO9/IUn+5fGT/EYtsfEX92MkR9HZnhWZ6mnAazz XPDW+unbWss5c0FLS/lr8utoTrThYykzoSfgqpOIob3i0BgC+b2p7T2OzZ36cBMjnNus /S96B9gy9Qt3acHys3GXjFguwDppJP7NpXmczjYJSAKKflRF70GqkdNS6Pdq79mvFD+E 154jgmq+FE/UzN0Q3tcTYAB5sh3aD1ULIxaxKIF9ULwAi6FioAh61lba7LiUP08jgwPM sAEg== X-Gm-Message-State: AFqh2kqlaMHsMrY51xR/CY0jPfaMcNdXS2xMP4/fScjYcwW76EMLI68q bBBSH2mPabve/k5Putt+qMsEjGc1QAtOtlrBsQ== X-Google-Smtp-Source: AMrXdXsHP5+f2fpfYzE99STHEa4P9O08B98yUTieK273C17++g9izQw4HiDu7GbrwsdBFOcun4exBxIBpIXN2zIitg== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a25:dc8f:0:b0:768:2e4c:9799 with SMTP id y137-20020a25dc8f000000b007682e4c9799mr2014885ybe.481.1674260183238; Fri, 20 Jan 2023 16:16:23 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:14 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-4-ackerleytng@google.com> Subject: [RFC PATCH v3 03/31] KVM: selftests: Expose function that sets up sregs based on VM's mode From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This allows initializing sregs without setting vCPU registers in KVM. No functional change intended. Signed-off-by: Ackerley Tng --- .../selftests/kvm/include/x86_64/processor.h | 2 + .../selftests/kvm/lib/x86_64/processor.c | 39 ++++++++++--------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h index e8ca0d8a6a7e0..74e0d3698f30c 100644 --- a/tools/testing/selftests/kvm/include/x86_64/processor.h +++ b/tools/testing/selftests/kvm/include/x86_64/processor.h @@ -644,6 +644,8 @@ const struct kvm_cpuid_entry2 *get_cpuid_entry(const struct kvm_cpuid2 *cpuid, void vcpu_init_cpuid(struct kvm_vcpu *vcpu, const struct kvm_cpuid2 *cpuid); void vcpu_set_hv_cpuid(struct kvm_vcpu *vcpu); +void vcpu_setup_mode_sregs(struct kvm_vm *vm, struct kvm_sregs *sregs); + static inline struct kvm_cpuid_entry2 *__vcpu_get_cpuid_entry(struct kvm_vcpu *vcpu, uint32_t function, uint32_t index) diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c index ed811181320de..1bb07d3c025b0 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c @@ -589,35 +589,38 @@ static void kvm_setup_tss_64bit(struct kvm_vm *vm, struct kvm_segment *segp, kvm_seg_fill_gdt_64bit(vm, segp); } -static void vcpu_setup(struct kvm_vm *vm, struct kvm_vcpu *vcpu) +void vcpu_setup_mode_sregs(struct kvm_vm *vm, struct kvm_sregs *sregs) { - struct kvm_sregs sregs; - - /* Set mode specific system register values. */ - vcpu_sregs_get(vcpu, &sregs); - - sregs.idt.limit = 0; + sregs->idt.limit = 0; - kvm_setup_gdt(vm, &sregs.gdt); + kvm_setup_gdt(vm, &sregs->gdt); switch (vm->mode) { case VM_MODE_PXXV48_4K: - sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG; - sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR; - sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX); - - kvm_seg_set_unusable(&sregs.ldt); - kvm_seg_set_kernel_code_64bit(vm, DEFAULT_CODE_SELECTOR, &sregs.cs); - kvm_seg_set_kernel_data_64bit(vm, DEFAULT_DATA_SELECTOR, &sregs.ds); - kvm_seg_set_kernel_data_64bit(vm, DEFAULT_DATA_SELECTOR, &sregs.es); - kvm_setup_tss_64bit(vm, &sregs.tr, 0x18); + sregs->cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG; + sregs->cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR; + sregs->efer |= (EFER_LME | EFER_LMA | EFER_NX); + + kvm_seg_set_unusable(&sregs->ldt); + kvm_seg_set_kernel_code_64bit(vm, DEFAULT_CODE_SELECTOR, &sregs->cs); + kvm_seg_set_kernel_data_64bit(vm, DEFAULT_DATA_SELECTOR, &sregs->ds); + kvm_seg_set_kernel_data_64bit(vm, DEFAULT_DATA_SELECTOR, &sregs->es); + kvm_setup_tss_64bit(vm, &sregs->tr, 0x18); break; default: TEST_FAIL("Unknown guest mode, mode: 0x%x", vm->mode); } - sregs.cr3 = vm->pgd; + sregs->cr3 = vm->pgd; +} + +static void vcpu_setup(struct kvm_vm *vm, struct kvm_vcpu *vcpu) +{ + struct kvm_sregs sregs; + + vcpu_sregs_get(vcpu, &sregs); + vcpu_setup_mode_sregs(vm, &sregs); vcpu_sregs_set(vcpu, &sregs); } From patchwork Sat Jan 21 00:15:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110729 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1F132C27C76 for ; Sat, 21 Jan 2023 00:16:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229864AbjAUAQy (ORCPT ); Fri, 20 Jan 2023 19:16:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52806 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229566AbjAUAQx (ORCPT ); Fri, 20 Jan 2023 19:16:53 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8B27DBF5C4 for ; Fri, 20 Jan 2023 16:16:29 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id h136-20020a25d08e000000b007e1b1a30d5dso7411076ybg.15 for ; Fri, 20 Jan 2023 16:16:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=/APv3/dZy7Uqys8Jgj7g1WItGoK9cC/vyW/fiLSrtbM=; b=ZFdMejAyz/1eZEWr6CE1KV/fJwKp4C6f4WL5WtXgG88Np70btURm7pCninpSBJojSB KK4E1iX1M3bD1CrMEe4+TSvBz0j4p7sloEuWZiK9VTejKWAIi7iFN2TD2wx9bXQUiHIb +N9i7a3cCH8iuJMbmDKcH1m+HVakzAaXEoTeuCn1D4sqK0IYS60MuIdP8R8qi/dtoP6G shrtjQKccnaUQ32fGfOFnCMAJInqvLEq80PrMtih/PuI5gl5APa3sS9i9AwrKjFF9haB 0dezXLc/gkEEnKcCbbPzFws3RnU+sOo817JJSWaDmG2u6vrvIAwWsroUE7nZMwqMaw4b tXCQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=/APv3/dZy7Uqys8Jgj7g1WItGoK9cC/vyW/fiLSrtbM=; b=qnUqY8I1N6M6P7RLvFQdrYIjGsrCfliTIRPZN9jCM7TukRmctlWNYkqhrh1AhkfbdU BGiOzCQvZKC1XslJl6CekErngZzLD6TCV5W4TySRv5G+oKJtucD733Hcdwaoyivzds9Y 9hJEuxe5+avxtpz4BkiSLrA9CfXyjioxlVPUuKjYac9i2rpKDIpa1+JLgpyI4G/K2Lrn 6+qnq8xo3IcHU1rAcKtmt/dQ1GexPV5mleo3oiiSSEJrLGQuQqzvm3ti+Cht8ttS0OYW 0pbNcs8EqcRWot9MyRYHX7AILqmAbXo6hYnjCUFHM8tcwEl5bKV/aXunOjw+yTv6jr4P Ut0g== X-Gm-Message-State: AFqh2kriFKA99GJ/kIDqXC/GBPh00VhtTZyR/+cJNVJhBtI52N6ybmiq Bg0HWySaFk1dobX1yDujG72dNPtYMDJ9UPOyDQ== X-Google-Smtp-Source: AMrXdXumVBpMD1wS8t96TrOMSwGj8T1nGqZGed5JUaR2MYkla7J53/4pjMUrQ09V611Z1bZNhJPET1aOdRMlceefig== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a25:2bc1:0:b0:7fe:35ff:fddb with SMTP id r184-20020a252bc1000000b007fe35fffddbmr791742ybr.466.1674260188336; Fri, 20 Jan 2023 16:16:28 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:15 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-5-ackerleytng@google.com> Subject: [RFC PATCH v3 04/31] KVM: selftests: Store initial stack address in struct kvm_vcpu From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org TDX guests' registers cannot be initialized directly using vcpu_regs_set(), hence the stack pointer needs to be initialized by the guest itself, running boot code beginning at the reset vector. We store the stack address as part of struct kvm_vcpu so that it can be accessible later to be passed to the boot code for rsp initialization. Signed-off-by: Ackerley Tng --- tools/testing/selftests/kvm/include/kvm_util_base.h | 1 + tools/testing/selftests/kvm/lib/x86_64/processor.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index 0fa4dab3d8e52..cdc204cfeb4c2 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -54,6 +54,7 @@ struct kvm_vcpu { int fd; struct kvm_vm *vm; struct kvm_run *run; + vm_vaddr_t initial_stack_addr; #ifdef __x86_64__ struct kvm_cpuid2 *cpuid; #endif diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c index 1bb07d3c025b0..3046b555fee49 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c @@ -673,10 +673,12 @@ struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id, vcpu_init_cpuid(vcpu, kvm_get_supported_cpuid()); vcpu_setup(vm, vcpu); + vcpu->initial_stack_addr = stack_vaddr + (DEFAULT_STACK_PGS * getpagesize()); + /* Setup guest general purpose registers */ vcpu_regs_get(vcpu, ®s); regs.rflags = regs.rflags | 0x2; - regs.rsp = stack_vaddr + (DEFAULT_STACK_PGS * getpagesize()); + regs.rsp = vcpu->initial_stack_addr; regs.rip = (unsigned long) guest_code; vcpu_regs_set(vcpu, ®s); From patchwork Sat Jan 21 00:15:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110730 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0214CC25B50 for ; Sat, 21 Jan 2023 00:17:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229684AbjAUARA (ORCPT ); Fri, 20 Jan 2023 19:17:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52904 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229604AbjAUAQ7 (ORCPT ); Fri, 20 Jan 2023 19:16:59 -0500 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B4602C4EBA for ; Fri, 20 Jan 2023 16:16:33 -0800 (PST) Received: by mail-pj1-x104a.google.com with SMTP id oo13-20020a17090b1c8d00b0022936a63a22so5841656pjb.8 for ; Fri, 20 Jan 2023 16:16:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=QxiTKLEOm+oMFK9aaHGMPXI17btDBmCLc/NZqm71Tbk=; b=ltg8p9DEmbRdkxoxc6sGLalH7h0V44/ZmiZXmsQJH6kv+DbmFIWf5KGM42u6kDqI1C kJrNb8zRDReE8eeRiN8umkJCpsFiX+UYIu+pGuoluI1Zuek9LVJsFIykRih4Xw1SQm72 OIcEima7xZ1R1ZJYnf0j5FZPl6Dr94ZMPGNKFmBeR+L8GqvRWIx0t0Y7l8uAFFjkt/Gg j1fv9SYiKYWxSPStjIQRcJAwCJFpf+iEOWEw4MwV70sQfJN7vm9CGFM1/JzgS4MEn3td dcgTt8nvI3TeKTgF0Af3BzAV/Ox4IwvVmxyRyqYz7fbV6XDJoOorffqL27rXS6JNXrWd xFzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=QxiTKLEOm+oMFK9aaHGMPXI17btDBmCLc/NZqm71Tbk=; b=0YiTBSmuzmRVUHydf+5dtoCcqnDLq1k+veeJOQrM0sRqNxtRjHkwN+WA+nTPuDmoVR jC/egq/CszZj5PKxNm0CtMOBVJ3ioblSXDoI2oW8eOprAo4oRKI4cR/NMr4Y/dzhMDDt T4uiPCofN1UVoF75BA5ZdoyyExF9b7oS6Risx1W8qRWpcIw0VIRl7c0g7NJo8DrXoPdj nb+JNmoSd2mRDuKYfuKWCcJYDnHRtBu9LPwxb/FV2RlySODvIEeEgiB9mxPhrezTfKwY rny0EXekrzu5ffNkeBLBAfNxUYOe2vxn3vXidA5z8clxfNs9JLo/RzcdspaNpleqHOnP 7bYg== X-Gm-Message-State: AFqh2kqstIiS95C983Q/uchI7LQC1OKzXJCD7IMFay5EjWNYaeRt7OdK QPTCHrd/BCAWHHxFuu+A1KfEwEq+QxYGCFFS7w== X-Google-Smtp-Source: AMrXdXv3LAmIr5JKeM8fvEWbKjfhX1gzLGtTUG4MGSdye8JI6uNnwFl9V9QefgMRzXdW7pmlEuZDNWb1BB8eEn9p6w== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a17:902:9a81:b0:194:6f35:db45 with SMTP id w1-20020a1709029a8100b001946f35db45mr1817207plp.27.1674260192836; Fri, 20 Jan 2023 16:16:32 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:16 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-6-ackerleytng@google.com> Subject: [RFC PATCH v3 05/31] KVM: selftests: Refactor steps in vCPU descriptor table initialization From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Split the vCPU descriptor table initialization process into a few steps and expose them: + Setting up the IDT + Syncing exception handlers into the guest In kvm_setup_idt(), we conditionally allocate guest memory for vm->idt to avoid double allocation when kvm_setup_idt() is used after vm_init_descriptor_tables(). Signed-off-by: Ackerley Tng --- .../selftests/kvm/include/x86_64/processor.h | 2 ++ .../selftests/kvm/lib/x86_64/processor.c | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h index 74e0d3698f30c..abaaab4d885c1 100644 --- a/tools/testing/selftests/kvm/include/x86_64/processor.h +++ b/tools/testing/selftests/kvm/include/x86_64/processor.h @@ -750,6 +750,8 @@ struct ex_regs { uint64_t rflags; }; +void kvm_setup_idt(struct kvm_vm *vm, struct kvm_dtable *dt); +void sync_exception_handlers_to_guest(struct kvm_vm *vm); void vm_init_descriptor_tables(struct kvm_vm *vm); void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu); void vm_install_exception_handler(struct kvm_vm *vm, int vector, diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c index 3046b555fee49..1ea1019d48c13 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c @@ -1174,19 +1174,32 @@ void vm_init_descriptor_tables(struct kvm_vm *vm) DEFAULT_CODE_SELECTOR); } +void kvm_setup_idt(struct kvm_vm *vm, struct kvm_dtable *dt) +{ + if (!vm->idt) + vm->idt = vm_vaddr_alloc_page(vm); + + dt->base = vm->idt; + dt->limit = NUM_INTERRUPTS * sizeof(struct idt_entry) - 1; +} + +void sync_exception_handlers_to_guest(struct kvm_vm *vm) +{ + *(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers; +} + void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu) { struct kvm_vm *vm = vcpu->vm; struct kvm_sregs sregs; vcpu_sregs_get(vcpu, &sregs); - sregs.idt.base = vm->idt; - sregs.idt.limit = NUM_INTERRUPTS * sizeof(struct idt_entry) - 1; + kvm_setup_idt(vcpu->vm, &sregs.idt); sregs.gdt.base = vm->gdt; sregs.gdt.limit = getpagesize() - 1; kvm_seg_set_kernel_data_64bit(NULL, DEFAULT_DATA_SELECTOR, &sregs.gs); vcpu_sregs_set(vcpu, &sregs); - *(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers; + sync_exception_handlers_to_guest(vm); } void vm_install_exception_handler(struct kvm_vm *vm, int vector, From patchwork Sat Jan 21 00:15:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110731 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 32417C05027 for ; Sat, 21 Jan 2023 00:17:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229912AbjAUARO (ORCPT ); Fri, 20 Jan 2023 19:17:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53032 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229604AbjAUARJ (ORCPT ); Fri, 20 Jan 2023 19:17:09 -0500 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2AF9DBFF47 for ; Fri, 20 Jan 2023 16:16:38 -0800 (PST) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-4fee82718afso34924177b3.5 for ; Fri, 20 Jan 2023 16:16:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:from:to:cc:subject:date:message-id :reply-to; bh=tMPwncQ1gJtbGz/ljguovcCY9rJ5FMvKrUuU8X2W2Bo=; b=GUyfjPJR9+g/Sg7H2zGwYF8aYccrNPb7vCAFqOQFCBcyn+IQRPGJ5nXtZepkEdAdod UbAqqP4uNzDT11t+P538NStpIM/mSdj3V3qDtbOINskTymF4zugnF9F4B0aYVVo8WSso YZBcW3zxFdKAxpz0jr2e1YCFf2Bx5v3TqomUqdIzLeY/gl66AqtQKN6Raf/9l3xPw5fy nCLbbMZpwEHFtmcPLYGvgoBcVDPNOhKPmxT6bdpvJzFumMTaqkiV5QcaNWFEFYqoF1+U 8UJKhWS8VEVeFylcyCLTINPOlJ1pqX7v9JmlNHZKj2Jm/hCB/Mhq5XAfPC3ZBTYYCGc8 PEhw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to; bh=tMPwncQ1gJtbGz/ljguovcCY9rJ5FMvKrUuU8X2W2Bo=; b=0Erpte/ROaw8LWrPZ31VL7/ASf3ISM57ZhOTIV/+0ZkV3KAsfUugTb4h3LRegyAkET nlVpdqLm/q3Km7V/FHa4SQ4KAaCGIMXg8G7iPd9KI1YKGxhw9E5oZBZD7w/WvsOhfN/t lM8oQHMquevFgLOTZxR0MSgzt+CGDGt62HKfTv6Is0MMK/lAOpfrxgaJfUUCe+Fcvww2 617T0NQ+FzdRVkJI2BOCl+t3a3LEmf8eF93cJOCrbUntBk+Evjxzw2xY/P/CF/9FazSj LOV+EioYKdqzqmlF+NHdkQtD2IQMmK2R+nf32SMyp2t5RRbZVVio83Msuz3io25QO9e1 3pXw== X-Gm-Message-State: AFqh2kp9BbkIaHQjvzBnyy5ydgBXy/WKXEhJwcpsfxVX3x81QmQEzwKe ym0DYobbHOl5D2Q3FYSHyk98MjEjm6nxLNZNIQ== X-Google-Smtp-Source: AMrXdXvUzdVeIPaSonRk94pmuklfVRVqZpOfB8xRmZ0eJgOBhWmMIiHDW94gJm7JAEUsn0iqpXyEEIwnHaBCCU/9nA== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a0d:e610:0:b0:3d6:bc67:ddb9 with SMTP id p16-20020a0de610000000b003d6bc67ddb9mr2402266ywe.98.1674260197404; Fri, 20 Jan 2023 16:16:37 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:17 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-7-ackerleytng@google.com> Subject: [RFC PATCH v3 06/31] KVM: selftests: Add helper functions to create TDX VMs From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Erdem Aktas TDX requires additional IOCTLs to initialize VM and vCPUs to add private memory and to finalize the VM memory. Also additional utility functions are provided to manipulate a TD, similar to those that manipulate a VM in the current selftest framework. A TD's initial register state cannot be manipulated directly by setting the VM's memory, hence boot code is provided at the TD's reset vector. This boot code takes boot parameters loaded in the TD's memory and sets up the TD for the selftest. Signed-off-by: Erdem Aktas Signed-off-by: Ryan Afranji Signed-off-by: Sagi Shahar Co-developed-by: Ackerley Tng Signed-off-by: Ackerley Tng --- Changes RFCv2 -> RFCv3 + Refactored out required cpuid changes as tdx_apply_cpuid_restrictions (a more meaningful function) + Also fixed logic for setting LBR and CET features to use sub-leaf 1 instead of 0 previously + Renamed ioctl calls to match names used in the kernel for easy referencing --- tools/testing/selftests/kvm/Makefile | 2 + .../kvm/include/x86_64/tdx/td_boot.h | 82 ++++ .../kvm/include/x86_64/tdx/td_boot_asm.h | 16 + .../kvm/include/x86_64/tdx/tdx_util.h | 16 + .../selftests/kvm/lib/x86_64/tdx/td_boot.S | 101 ++++ .../selftests/kvm/lib/x86_64/tdx/tdx_util.c | 438 ++++++++++++++++++ 6 files changed, 655 insertions(+) create mode 100644 tools/testing/selftests/kvm/include/x86_64/tdx/td_boot.h create mode 100644 tools/testing/selftests/kvm/include/x86_64/tdx/td_boot_asm.h create mode 100644 tools/testing/selftests/kvm/include/x86_64/tdx/tdx_util.h create mode 100644 tools/testing/selftests/kvm/lib/x86_64/tdx/td_boot.S create mode 100644 tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c -- 2.39.0.246.g2a6d74b583-goog diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 1eb9b2aa7c220..317927d9c55bd 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -59,6 +59,8 @@ LIBKVM_x86_64 += lib/x86_64/svm.c LIBKVM_x86_64 += lib/x86_64/ucall.c LIBKVM_x86_64 += lib/x86_64/vmx.c LIBKVM_x86_64 += lib/x86_64/sev.c +LIBKVM_x86_64 += lib/x86_64/tdx/tdx_util.c +LIBKVM_x86_64 += lib/x86_64/tdx/td_boot.S LIBKVM_aarch64 += lib/aarch64/gic.c LIBKVM_aarch64 += lib/aarch64/gic_v3.c diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/td_boot.h b/tools/testing/selftests/kvm/include/x86_64/tdx/td_boot.h new file mode 100644 index 0000000000000..148057e569d69 --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/td_boot.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef SELFTEST_TDX_TD_BOOT_H +#define SELFTEST_TDX_TD_BOOT_H + +#include +#include "tdx/td_boot_asm.h" + +/* + * Layout for boot section (not to scale) + * + * GPA + * ┌─────────────────────────────┬──0x1_0000_0000 (4GB) + * │ Boot code trampoline │ + * ├─────────────────────────────┼──0x0_ffff_fff0: Reset vector (16B below 4GB) + * │ Boot code │ + * ├─────────────────────────────┼──td_boot will be copied here, so that the + * │ │ jmp to td_boot is exactly at the reset vector + * │ Empty space │ + * │ │ + * ├─────────────────────────────┤ + * │ │ + * │ │ + * │ Boot parameters │ + * │ │ + * │ │ + * └─────────────────────────────┴──0x0_ffff_0000: TD_BOOT_PARAMETERS_GPA + */ +#define FOUR_GIGABYTES_GPA (4ULL << 30) + +/** + * The exact memory layout for LGDT or LIDT instructions. + */ +struct __packed td_boot_parameters_dtr { + uint16_t limit; + uint32_t base; +}; + +/** + * The exact layout in memory required for a ljmp, including the selector for + * changing code segment. + */ +struct __packed td_boot_parameters_ljmp_target { + uint32_t eip_gva; + uint16_t code64_sel; +}; + +/** + * Allows each vCPU to be initialized with different eip and esp. + */ +struct __packed td_per_vcpu_parameters { + uint32_t esp_gva; + struct td_boot_parameters_ljmp_target ljmp_target; +}; + +/** + * Boot parameters for the TD. + * + * Unlike a regular VM, we can't ask KVM to set registers such as esp, eip, etc + * before boot, so to run selftests, these registers' values have to be + * initialized by the TD. + * + * This struct is loaded in TD private memory at TD_BOOT_PARAMETERS_GPA. + * + * The TD boot code will read off parameters from this struct and set up the + * vcpu for executing selftests. + */ +struct __packed td_boot_parameters { + uint32_t cr0; + uint32_t cr3; + uint32_t cr4; + struct td_boot_parameters_dtr gdtr; + struct td_boot_parameters_dtr idtr; + struct td_per_vcpu_parameters per_vcpu[]; +}; + +extern void td_boot(void); +extern void reset_vector(void); +extern void td_boot_code_end(void); + +#define TD_BOOT_CODE_SIZE (td_boot_code_end - td_boot) + +#endif /* SELFTEST_TDX_TD_BOOT_H */ diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/td_boot_asm.h b/tools/testing/selftests/kvm/include/x86_64/tdx/td_boot_asm.h new file mode 100644 index 0000000000000..0a07104f7debf --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/td_boot_asm.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef SELFTEST_TDX_TD_BOOT_ASM_H +#define SELFTEST_TDX_TD_BOOT_ASM_H + +/* + * GPA where TD boot parameters wil lbe loaded. + * + * TD_BOOT_PARAMETERS_GPA is arbitrarily chosen to + * + * + be within the 4GB address space + * + provide enough contiguous memory for the struct td_boot_parameters such + * that there is one struct td_per_vcpu_parameters for KVM_MAX_VCPUS + */ +#define TD_BOOT_PARAMETERS_GPA 0xffff0000 + +#endif // SELFTEST_TDX_TD_BOOT_ASM_H diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx_util.h b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx_util.h new file mode 100644 index 0000000000000..274b245f200bf --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx_util.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef SELFTESTS_TDX_KVM_UTIL_H +#define SELFTESTS_TDX_KVM_UTIL_H + +#include + +#include "kvm_util_base.h" + +struct kvm_vcpu *td_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id, void *guest_code); + +struct kvm_vm *td_create(void); +void td_initialize(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type, + uint64_t attributes); +void td_finalize(struct kvm_vm *vm); + +#endif // SELFTESTS_TDX_KVM_UTIL_H diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/td_boot.S b/tools/testing/selftests/kvm/lib/x86_64/tdx/td_boot.S new file mode 100644 index 0000000000000..800e09264d4ec --- /dev/null +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/td_boot.S @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "tdx/td_boot_asm.h" + +/* Offsets for reading struct td_boot_parameters */ +#define TD_BOOT_PARAMETERS_CR0 0 +#define TD_BOOT_PARAMETERS_CR3 4 +#define TD_BOOT_PARAMETERS_CR4 8 +#define TD_BOOT_PARAMETERS_GDT 12 +#define TD_BOOT_PARAMETERS_IDT 18 +#define TD_BOOT_PARAMETERS_PER_VCPU 24 + +/* Offsets for reading struct td_per_vcpu_parameters */ +#define TD_PER_VCPU_PARAMETERS_ESP_GVA 0 +#define TD_PER_VCPU_PARAMETERS_LJMP_TARGET 4 + +#define SIZEOF_TD_PER_VCPU_PARAMETERS 10 + +.code32 + +.globl td_boot +td_boot: + /* In this procedure, edi is used as a temporary register */ + cli + + /* Paging is off */ + + movl $TD_BOOT_PARAMETERS_GPA, %ebx + + /* + * Find the address of struct td_per_vcpu_parameters for this + * vCPU based on esi (TDX spec: initialized with vcpu id). Put + * struct address into register for indirect addressing + */ + movl $SIZEOF_TD_PER_VCPU_PARAMETERS, %eax + mul %esi + leal TD_BOOT_PARAMETERS_PER_VCPU(%ebx), %edi + addl %edi, %eax + + /* Setup stack */ + movl TD_PER_VCPU_PARAMETERS_ESP_GVA(%eax), %esp + + /* Setup GDT */ + leal TD_BOOT_PARAMETERS_GDT(%ebx), %edi + lgdt (%edi) + + /* Setup IDT */ + leal TD_BOOT_PARAMETERS_IDT(%ebx), %edi + lidt (%edi) + + /* + * Set up control registers (There are no instructions to + * mov from memory to control registers, hence we need to use ebx + * as a scratch register) + */ + movl TD_BOOT_PARAMETERS_CR4(%ebx), %edi + movl %edi, %cr4 + movl TD_BOOT_PARAMETERS_CR3(%ebx), %edi + movl %edi, %cr3 + movl TD_BOOT_PARAMETERS_CR0(%ebx), %edi + movl %edi, %cr0 + + /* Paging is on after setting the most significant bit on cr0 */ + + /* + * Jump to selftest guest code. Far jumps read from . This location has + * already been set up in boot parameters, and we can read boot + * parameters because boot code and boot parameters are loaded so + * that GVA and GPA are mapped 1:1. + */ + ljmp *TD_PER_VCPU_PARAMETERS_LJMP_TARGET(%eax) + +.globl reset_vector +reset_vector: + jmp td_boot + /* + * Pad reset_vector to its full size of 16 bytes so that this + * can be loaded with the end of reset_vector aligned to GPA=4G + */ + int3 + int3 + int3 + int3 + int3 + int3 + int3 + int3 + int3 + int3 + int3 + int3 + int3 + int3 + +/* Leave marker so size of td_boot code can be computed */ +.globl td_boot_code_end +td_boot_code_end: + +/* Disable executable stack */ +.section .note.GNU-stack,"",%progbits diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c new file mode 100644 index 0000000000000..3564059c0b89b --- /dev/null +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c @@ -0,0 +1,438 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include "kvm_util.h" +#include "test_util.h" +#include "tdx/td_boot.h" +#include "kvm_util_base.h" +#include "processor.h" + +/* + * TDX ioctls + */ + +static char *tdx_cmd_str[] = { + "KVM_TDX_CAPABILITIES", + "KVM_TDX_INIT_VM", + "KVM_TDX_INIT_VCPU", + "KVM_TDX_INIT_MEM_REGION", + "KVM_TDX_FINALIZE_VM" +}; +#define TDX_MAX_CMD_STR (ARRAY_SIZE(tdx_cmd_str)) + +static void tdx_ioctl(int fd, int ioctl_no, uint32_t flags, void *data) +{ + struct kvm_tdx_cmd tdx_cmd; + int r; + + TEST_ASSERT(ioctl_no < TDX_MAX_CMD_STR, "Unknown TDX CMD : %d\n", + ioctl_no); + + memset(&tdx_cmd, 0x0, sizeof(tdx_cmd)); + tdx_cmd.id = ioctl_no; + tdx_cmd.flags = flags; + tdx_cmd.data = (uint64_t)data; + + r = ioctl(fd, KVM_MEMORY_ENCRYPT_OP, &tdx_cmd); + TEST_ASSERT(r == 0, "%s failed: %d %d", tdx_cmd_str[ioctl_no], r, + errno); +} + +#define XFEATURE_LBR 15 +#define XFEATURE_XTILECFG 17 +#define XFEATURE_XTILEDATA 18 +#define XFEATURE_CET_U 11 +#define XFEATURE_CET_S 12 + +#define XFEATURE_MASK_LBR (1 << XFEATURE_LBR) +#define XFEATURE_MASK_CET_U (1 << XFEATURE_CET_U) +#define XFEATURE_MASK_CET_S (1 << XFEATURE_CET_S) +#define XFEATURE_MASK_CET (XFEATURE_MASK_CET_U | XFEATURE_MASK_CET_S) +#define XFEATURE_MASK_XTILECFG (1 << XFEATURE_XTILECFG) +#define XFEATURE_MASK_XTILEDATA (1 << XFEATURE_XTILEDATA) +#define XFEATURE_MASK_XTILE (XFEATURE_MASK_XTILECFG | XFEATURE_MASK_XTILEDATA) + +static void tdx_apply_cpuid_restrictions(struct kvm_cpuid2 *cpuid_data) +{ + for (int i = 0; i < cpuid_data->nent; i++) { + struct kvm_cpuid_entry2 *e = &cpuid_data->entries[i]; + + if (e->function == 0xd && e->index == 0) { + /* + * TDX module requires both XTILE_{CFG, DATA} to be set. + * Both bits are required for AMX to be functional. + */ + if ((e->eax & XFEATURE_MASK_XTILE) != + XFEATURE_MASK_XTILE) { + e->eax &= ~XFEATURE_MASK_XTILE; + } + } + if (e->function == 0xd && e->index == 1) { + /* + * TDX doesn't support LBR yet. + * Disable bits from the XCR0 register. + */ + e->ecx &= ~XFEATURE_MASK_LBR; + /* + * TDX modules requires both CET_{U, S} to be set even + * if only one is supported. + */ + if (e->ecx & XFEATURE_MASK_CET) + e->ecx |= XFEATURE_MASK_CET; + } + } +} + +static void tdx_td_init(struct kvm_vm *vm, uint64_t attributes) +{ + const struct kvm_cpuid2 *cpuid; + struct kvm_tdx_init_vm init_vm; + + memset(&init_vm, 0, sizeof(struct kvm_tdx_init_vm)); + + cpuid = kvm_get_supported_cpuid(); + + memcpy(&init_vm.cpuid, cpuid, kvm_cpuid2_size(cpuid->nent)); + init_vm.attributes = attributes; + + tdx_apply_cpuid_restrictions(&init_vm.cpuid); + + tdx_ioctl(vm->fd, KVM_TDX_INIT_VM, 0, &init_vm); +} + +static void tdx_td_vcpu_init(struct kvm_vcpu *vcpu) +{ + const struct kvm_cpuid2 *cpuid = kvm_get_supported_cpuid(); + + vcpu_init_cpuid(vcpu, cpuid); + tdx_ioctl(vcpu->fd, KVM_TDX_INIT_VCPU, 0, NULL); +} + +static void tdx_init_mem_region(struct kvm_vm *vm, void *source_pages, + uint64_t gpa, uint64_t size) +{ + struct kvm_tdx_init_mem_region mem_region = { + .source_addr = (uint64_t)source_pages, + .gpa = gpa, + .nr_pages = size / PAGE_SIZE, + }; + uint32_t metadata = KVM_TDX_MEASURE_MEMORY_REGION; + + TEST_ASSERT((mem_region.nr_pages > 0) && + ((mem_region.nr_pages * PAGE_SIZE) == size), + "Cannot add partial pages to the guest memory.\n"); + TEST_ASSERT(((uint64_t)source_pages & (PAGE_SIZE - 1)) == 0, + "Source memory buffer is not page aligned\n"); + tdx_ioctl(vm->fd, KVM_TDX_INIT_MEM_REGION, metadata, &mem_region); +} + +static void tdx_td_finalizemr(struct kvm_vm *vm) +{ + tdx_ioctl(vm->fd, KVM_TDX_FINALIZE_VM, 0, NULL); +} + +/* + * TD creation/setup/finalization + */ + +static void tdx_enable_capabilities(struct kvm_vm *vm) +{ + int rc; + + rc = kvm_check_cap(KVM_CAP_X2APIC_API); + TEST_ASSERT(rc, "TDX: KVM_CAP_X2APIC_API is not supported!"); + rc = kvm_check_cap(KVM_CAP_SPLIT_IRQCHIP); + TEST_ASSERT(rc, "TDX: KVM_CAP_SPLIT_IRQCHIP is not supported!"); + + vm_enable_cap(vm, KVM_CAP_X2APIC_API, + KVM_X2APIC_API_USE_32BIT_IDS | + KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK); + vm_enable_cap(vm, KVM_CAP_SPLIT_IRQCHIP, 24); +} + +static void tdx_configure_memory_encryption(struct kvm_vm *vm) +{ + /* Configure shared/enCrypted bit for this VM according to TDX spec */ + vm->arch.s_bit = 1ULL << (vm->pa_bits - 1); + vm->arch.c_bit = 0; + /* Set gpa_protected_mask so that tagging/untagging of GPAs works */ + vm->gpa_protected_mask = vm->arch.s_bit; + /* There's no need to mask any encryption bits for PTEs */ + vm->arch.pte_me_mask = 0; + /* This VM is protected (has memory encryption) */ + vm->protected = true; +} + +static void tdx_apply_cr4_restrictions(struct kvm_sregs *sregs) +{ + /* TDX spec 11.6.2: CR4 bit MCE is fixed to 1 */ + sregs->cr4 |= X86_CR4_MCE; + + /* Set this because UEFI also sets this up, to handle XMM exceptions */ + sregs->cr4 |= X86_CR4_OSXMMEXCPT; + + /* TDX spec 11.6.2: CR4 bit VMXE and SMXE are fixed to 0 */ + sregs->cr4 &= ~(X86_CR4_VMXE | X86_CR4_SMXE); +} + +static void load_td_boot_code(struct kvm_vm *vm) +{ + void *boot_code_hva = addr_gpa2hva(vm, FOUR_GIGABYTES_GPA - TD_BOOT_CODE_SIZE); + + TEST_ASSERT(td_boot_code_end - reset_vector == 16, + "The reset vector must be 16 bytes in size."); + memcpy(boot_code_hva, td_boot, TD_BOOT_CODE_SIZE); +} + +static void load_td_per_vcpu_parameters(struct td_boot_parameters *params, + struct kvm_sregs *sregs, + struct kvm_vcpu *vcpu, + void *guest_code) +{ + /* Store vcpu_index to match what the TDX module would store internally */ + static uint32_t vcpu_index; + + struct td_per_vcpu_parameters *vcpu_params = ¶ms->per_vcpu[vcpu_index]; + + TEST_ASSERT(vcpu->initial_stack_addr != 0, + "initial stack address should not be 0"); + TEST_ASSERT(vcpu->initial_stack_addr <= 0xffffffff, + "initial stack address must fit in 32 bits"); + TEST_ASSERT((uint64_t)guest_code <= 0xffffffff, + "guest_code must fit in 32 bits"); + TEST_ASSERT(sregs->cs.selector != 0, "cs.selector should not be 0"); + + vcpu_params->esp_gva = (uint32_t)(uint64_t)vcpu->initial_stack_addr; + vcpu_params->ljmp_target.eip_gva = (uint32_t)(uint64_t)guest_code; + vcpu_params->ljmp_target.code64_sel = sregs->cs.selector; + + vcpu_index++; +} + +static void load_td_common_parameters(struct td_boot_parameters *params, + struct kvm_sregs *sregs) +{ + /* Set parameters! */ + params->cr0 = sregs->cr0; + params->cr3 = sregs->cr3; + params->cr4 = sregs->cr4; + params->gdtr.limit = sregs->gdt.limit; + params->gdtr.base = sregs->gdt.base; + params->idtr.limit = sregs->idt.limit; + params->idtr.base = sregs->idt.base; + + TEST_ASSERT(params->cr0 != 0, "cr0 should not be 0"); + TEST_ASSERT(params->cr3 != 0, "cr3 should not be 0"); + TEST_ASSERT(params->cr4 != 0, "cr4 should not be 0"); + TEST_ASSERT(params->gdtr.base != 0, "gdt base address should not be 0"); +} + +static void load_td_boot_parameters(struct td_boot_parameters *params, + struct kvm_vcpu *vcpu, void *guest_code) +{ + struct kvm_sregs sregs; + + /* Assemble parameters in sregs */ + memset(&sregs, 0, sizeof(struct kvm_sregs)); + vcpu_setup_mode_sregs(vcpu->vm, &sregs); + tdx_apply_cr4_restrictions(&sregs); + kvm_setup_idt(vcpu->vm, &sregs.idt); + + if (!params->cr0) + load_td_common_parameters(params, &sregs); + + load_td_per_vcpu_parameters(params, &sregs, vcpu, guest_code); +} + +/** + * Adds a vCPU to a TD (Trusted Domain) with minimum defaults. It will not set + * up any general purpose registers as they will be initialized by the TDX. In + * TDX, vCPUs RIP is set to 0xFFFFFFF0. See Intel TDX EAS Section "Initial State + * of Guest GPRs" for more information on vCPUs initial register values when + * entering the TD first time. + * + * Input Args: + * vm - Virtual Machine + * vcpuid - The id of the VCPU to add to the VM. + */ +struct kvm_vcpu *td_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id, void *guest_code) +{ + struct kvm_vcpu *vcpu; + + /* + * TD setup will not use the value of rip set in vm_vcpu_add anyway, so + * NULL can be used for guest_code. + */ + vcpu = vm_vcpu_add(vm, vcpu_id, NULL); + + tdx_td_vcpu_init(vcpu); + + load_td_boot_parameters(addr_gpa2hva(vm, TD_BOOT_PARAMETERS_GPA), + vcpu, guest_code); + + return vcpu; +} + +/** + * Iterate over set ranges within sparsebit @s. In each iteration, + * @range_begin and @range_end will take the beginning and end of the set range, + * which are of type sparsebit_idx_t. + * + * For example, if the range [3, 7] (inclusive) is set, within the iteration, + * @range_begin will take the value 3 and @range_end will take the value 7. + * + * Ensure that there is at least one bit set before using this macro with + * sparsebit_any_set(), because sparsebit_first_set() will abort if none are + * set. + */ +#define sparsebit_for_each_set_range(s, range_begin, range_end) \ + for (range_begin = sparsebit_first_set(s), \ + range_end = sparsebit_next_clear(s, range_begin) - 1; \ + range_begin && range_end; \ + range_begin = sparsebit_next_set(s, range_end), \ + range_end = sparsebit_next_clear(s, range_begin) - 1) +/* + * sparsebit_next_clear() can return 0 if [x, 2**64-1] are all set, and the -1 + * would then cause an underflow back to 2**64 - 1. This is expected and + * correct. + * + * If the last range in the sparsebit is [x, y] and we try to iterate, + * sparsebit_next_set() will return 0, and sparsebit_next_clear() will try and + * find the first range, but that's correct because the condition expression + * would cause us to quit the loop. + */ + +static void load_td_memory_region(struct kvm_vm *vm, + struct userspace_mem_region *region) +{ + const struct sparsebit *pages = region->protected_phy_pages; + const uint64_t hva_base = region->region.userspace_addr; + const vm_paddr_t gpa_base = region->region.guest_phys_addr; + const sparsebit_idx_t lowest_page_in_region = gpa_base >> + vm->page_shift; + + sparsebit_idx_t i; + sparsebit_idx_t j; + + if (!sparsebit_any_set(pages)) + return; + + sparsebit_for_each_set_range(pages, i, j) { + const uint64_t size_to_load = (j - i + 1) * vm->page_size; + const uint64_t offset = + (i - lowest_page_in_region) * vm->page_size; + const uint64_t hva = hva_base + offset; + const uint64_t gpa = gpa_base + offset; + void *source_addr; + + /* + * KVM_TDX_INIT_MEM_REGION ioctl cannot encrypt memory in place, + * hence we have to make a copy if there's only one backing + * memory source + */ + source_addr = mmap(NULL, size_to_load, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + TEST_ASSERT( + source_addr, + "Could not allocate memory for loading memory region"); + + memcpy(source_addr, (void *)hva, size_to_load); + + tdx_init_mem_region(vm, source_addr, gpa, size_to_load); + + munmap(source_addr, size_to_load); + } +} + +static void load_td_private_memory(struct kvm_vm *vm) +{ + int ctr; + struct userspace_mem_region *region; + + hash_for_each(vm->regions.slot_hash, ctr, region, slot_node) { + load_td_memory_region(vm, region); + } +} + +struct kvm_vm *td_create(void) +{ + return ____vm_create(VM_MODE_DEFAULT, 0, KVM_X86_TDX_VM); +} + +static void td_setup_boot_code(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type) +{ + vm_vaddr_t addr; + size_t boot_code_allocation = round_up(TD_BOOT_CODE_SIZE, PAGE_SIZE); + vm_paddr_t boot_code_base_gpa = FOUR_GIGABYTES_GPA - boot_code_allocation; + size_t npages = DIV_ROUND_UP(boot_code_allocation, PAGE_SIZE); + + vm_userspace_mem_region_add(vm, src_type, boot_code_base_gpa, 1, npages, 0); + addr = vm_vaddr_alloc_1to1(vm, boot_code_allocation, boot_code_base_gpa, 1); + ASSERT_EQ(addr, boot_code_base_gpa); + + load_td_boot_code(vm); +} + +static size_t td_boot_parameters_size(void) +{ + int max_vcpus = kvm_check_cap(KVM_CAP_MAX_VCPUS); + size_t total_per_vcpu_parameters_size = + max_vcpus * sizeof(struct td_per_vcpu_parameters); + + return sizeof(struct td_boot_parameters) + total_per_vcpu_parameters_size; +} + +static void td_setup_boot_parameters(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type) +{ + vm_vaddr_t addr; + size_t boot_params_size = td_boot_parameters_size(); + int npages = DIV_ROUND_UP(boot_params_size, PAGE_SIZE); + size_t total_size = npages * PAGE_SIZE; + + vm_userspace_mem_region_add(vm, src_type, TD_BOOT_PARAMETERS_GPA, 2, npages, 0); + addr = vm_vaddr_alloc_1to1(vm, total_size, TD_BOOT_PARAMETERS_GPA, 2); + ASSERT_EQ(addr, TD_BOOT_PARAMETERS_GPA); +} + +void td_initialize(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type, + uint64_t attributes) +{ + uint64_t nr_pages_required; + + tdx_enable_capabilities(vm); + + tdx_configure_memory_encryption(vm); + + tdx_td_init(vm, attributes); + + nr_pages_required = vm_nr_pages_required(VM_MODE_DEFAULT, 1, 0); + + /* + * Add memory (add 0th memslot) for TD. This will be used to setup the + * CPU (provide stack space for the CPU) and to load the elf file. + */ + vm_userspace_mem_region_add(vm, src_type, 0, 0, nr_pages_required, 0); + + kvm_vm_elf_load(vm, program_invocation_name); + + vm_init_descriptor_tables(vm); + + td_setup_boot_code(vm, src_type); + td_setup_boot_parameters(vm, src_type); +} + +void td_finalize(struct kvm_vm *vm) +{ + sync_exception_handlers_to_guest(vm); + + load_td_private_memory(vm); + + tdx_td_finalizemr(vm); +} From patchwork Sat Jan 21 00:15:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110732 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 959FCC38A23 for ; Sat, 21 Jan 2023 00:17:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229813AbjAUART (ORCPT ); Fri, 20 Jan 2023 19:17:19 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53072 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229934AbjAUARQ (ORCPT ); Fri, 20 Jan 2023 19:17:16 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9B9EEE0507 for ; Fri, 20 Jan 2023 16:16:42 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id n203-20020a2572d4000000b0078f09db9888so7425905ybc.18 for ; Fri, 20 Jan 2023 16:16:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=KI3lc8Qa4odfGOnk3uFPbmARvL0LzJJulpfkNFBemzE=; b=j/DoN5zQelvEIRLCNJ8mAtnltfQSsXNmZd7BctX5fFtP93iKxLb9ixSdg2WNzWXI78 Ymx4YT8j6gfC4S6iRGU2Mv9y37Y4oNY9lD65dIbpSdOS6kCagdOWk3kCH9NHdtlMKpBK zrab/5Y4g5ZpSDO89l27WlSh7FWKZvCBoO+ngfQJqga0zg0Xv6OOuKB+CskX3EQBKUDL 4NMMkETMJiH0CE9dHx6V7b+dTQ8/fNKEXvzF9sKarkFVYUTEIV3xV6y7vlWErO+ikPCX S1PKylJo4o8pamn+0IEOijoaChvstVTTV/6yT2yRWDAIWakbcRSApbdS84IF+dz5R0DS ZAbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=KI3lc8Qa4odfGOnk3uFPbmARvL0LzJJulpfkNFBemzE=; b=5+MuqV04WFpDK0sbH2GNILni7ejCdTkr65SpMZPUs5fgmNB/KYOQCAEdculqcR+Rxh nrcj4KZKGfFkWMfBSv3hfgGSYkeEE3MJ8iJPeLUCmnU1Z0riSJB4RZDhbiPFXb3RWGpw dFMJzXecJbY7Gw6N8Lq1Rj8fCCm85n3jOd/21v5FXt9JKaakhMBEz3A7okJbnKiZeslp 0jvAc0I9DSVFUq79fdQ8hxqQszHxVA2vkTR1aK9RLmNwT6cIQS8ztmTUJUfjbriIZwGF lTCbBcAMFKmx5yfBy2T/h2ReNogkK31YuJAWtrG9CC0Cgj0hjwRKtJ7o4vS3H5VG1d+i prbg== X-Gm-Message-State: AFqh2kobYEruOYZsVEjMVi6MTKwq3NUiHv61guKzmHfYSSo76AcftbRk +YjWQeO/AY2C2b/84Fhp4HY96xzw3FB0DY8ytA== X-Google-Smtp-Source: AMrXdXtydJEIawtxpXOqiqaHbL6Dx7DCG8iZopOtBwRlFXexLweXPTHCILvbivdlZGIN05ch6GxDlBjxhQwV/oNYRg== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a81:9257:0:b0:3df:ba1d:f51a with SMTP id j84-20020a819257000000b003dfba1df51amr2347624ywg.64.1674260201622; Fri, 20 Jan 2023 16:16:41 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:18 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-8-ackerleytng@google.com> Subject: [RFC PATCH v3 07/31] KVM: selftests: TDX: Use KVM_TDX_CAPABILITIES to validate TDs' attribute configuration From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This also exercises the KVM_TDX_CAPABILITIES ioctl. Suggested-by: Isaku Yamahata Signed-off-by: Ackerley Tng --- .../selftests/kvm/lib/x86_64/tdx/tdx_util.c | 75 ++++++++++++++++++- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c index 3564059c0b89b..2e9679d24a843 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c @@ -27,10 +27,9 @@ static char *tdx_cmd_str[] = { }; #define TDX_MAX_CMD_STR (ARRAY_SIZE(tdx_cmd_str)) -static void tdx_ioctl(int fd, int ioctl_no, uint32_t flags, void *data) +static int _tdx_ioctl(int fd, int ioctl_no, uint32_t flags, void *data) { struct kvm_tdx_cmd tdx_cmd; - int r; TEST_ASSERT(ioctl_no < TDX_MAX_CMD_STR, "Unknown TDX CMD : %d\n", ioctl_no); @@ -40,11 +39,63 @@ static void tdx_ioctl(int fd, int ioctl_no, uint32_t flags, void *data) tdx_cmd.flags = flags; tdx_cmd.data = (uint64_t)data; - r = ioctl(fd, KVM_MEMORY_ENCRYPT_OP, &tdx_cmd); + return ioctl(fd, KVM_MEMORY_ENCRYPT_OP, &tdx_cmd); +} + +static void tdx_ioctl(int fd, int ioctl_no, uint32_t flags, void *data) +{ + int r; + + r = _tdx_ioctl(fd, ioctl_no, flags, data); TEST_ASSERT(r == 0, "%s failed: %d %d", tdx_cmd_str[ioctl_no], r, errno); } +static struct kvm_tdx_capabilities *tdx_read_capabilities(void) +{ + int i; + int rc = -1; + int nr_cpuid_configs = 4; + struct kvm_tdx_capabilities *tdx_cap = NULL; + int kvm_fd; + + kvm_fd = open_kvm_dev_path_or_exit(); + + do { + nr_cpuid_configs *= 2; + + tdx_cap = realloc( + tdx_cap, sizeof(*tdx_cap) + + nr_cpuid_configs * sizeof(*tdx_cap->cpuid_configs)); + TEST_ASSERT(tdx_cap != NULL, + "Could not allocate memory for tdx capability nr_cpuid_configs %d\n", + nr_cpuid_configs); + + tdx_cap->nr_cpuid_configs = nr_cpuid_configs; + rc = _tdx_ioctl(kvm_fd, KVM_TDX_CAPABILITIES, 0, tdx_cap); + } while (rc < 0 && errno == E2BIG); + + TEST_ASSERT(rc == 0, "KVM_TDX_CAPABILITIES failed: %d %d", + rc, errno); + + pr_debug("tdx_cap: attrs: fixed0 0x%016llx fixed1 0x%016llx\n" + "tdx_cap: xfam fixed0 0x%016llx fixed1 0x%016llx\n", + tdx_cap->attrs_fixed0, tdx_cap->attrs_fixed1, + tdx_cap->xfam_fixed0, tdx_cap->xfam_fixed1); + + for (i = 0; i < tdx_cap->nr_cpuid_configs; i++) { + const struct kvm_tdx_cpuid_config *config = + &tdx_cap->cpuid_configs[i]; + pr_debug("cpuid config[%d]: leaf 0x%x sub_leaf 0x%x eax 0x%08x ebx 0x%08x ecx 0x%08x edx 0x%08x\n", + i, config->leaf, config->sub_leaf, + config->eax, config->ebx, config->ecx, config->edx); + } + + close(kvm_fd); + + return tdx_cap; +} + #define XFEATURE_LBR 15 #define XFEATURE_XTILECFG 17 #define XFEATURE_XTILEDATA 18 @@ -90,6 +141,21 @@ static void tdx_apply_cpuid_restrictions(struct kvm_cpuid2 *cpuid_data) } } +static void tdx_check_attributes(uint64_t attributes) +{ + struct kvm_tdx_capabilities *tdx_cap; + + tdx_cap = tdx_read_capabilities(); + + /* TDX spec: any bits 0 in attrs_fixed0 must be 0 in attributes */ + ASSERT_EQ(attributes & ~tdx_cap->attrs_fixed0, 0); + + /* TDX spec: any bits 1 in attrs_fixed1 must be 1 in attributes */ + ASSERT_EQ(attributes & tdx_cap->attrs_fixed1, tdx_cap->attrs_fixed1); + + free(tdx_cap); +} + static void tdx_td_init(struct kvm_vm *vm, uint64_t attributes) { const struct kvm_cpuid2 *cpuid; @@ -100,6 +166,9 @@ static void tdx_td_init(struct kvm_vm *vm, uint64_t attributes) cpuid = kvm_get_supported_cpuid(); memcpy(&init_vm.cpuid, cpuid, kvm_cpuid2_size(cpuid->nent)); + + tdx_check_attributes(attributes); + init_vm.attributes = attributes; tdx_apply_cpuid_restrictions(&init_vm.cpuid); From patchwork Sat Jan 21 00:15:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110733 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A1251C25B50 for ; Sat, 21 Jan 2023 00:17:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229955AbjAUARb (ORCPT ); Fri, 20 Jan 2023 19:17:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53288 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229954AbjAUARV (ORCPT ); Fri, 20 Jan 2023 19:17:21 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3FE8ABAF2A for ; Fri, 20 Jan 2023 16:16:54 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id g73-20020a25db4c000000b00802b0159bccso2584933ybf.22 for ; Fri, 20 Jan 2023 16:16:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=iSSiGqnlhzGiDLCzSAtleJIHOm3o/jPruEIVdPoSPmM=; b=i3bQf8fOpOKYn4DsIRRzCUmnsCj+LMJV96+HJVERlyQV50GGhU4m9vph9dFvXLxh33 a6PijOok3GOHph4F2aF0Uo8zDnzeIuzhlwcNn/lmpe5ODxgUHA6krkenLMHAVsTMVG8A DQOBErL8T8utFKaa2hBwsfFZN+8NkBWs2+uZyhMMxhKrvH43FYJ7I3M1J/lUsHYsC3JO fw9Xc1e8mfpAWmMp8YsemFubhIbnl6sBYlN9R8OgKxypq4dN68xuIBEA7FNjAMYzR1gV Yu5F1WkIRQy/QQlujBYRghEm0b6qOSbdB7fBbpYVu8C0LSyi/b3WnM5jtqRfovPdsPgx hPeA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=iSSiGqnlhzGiDLCzSAtleJIHOm3o/jPruEIVdPoSPmM=; b=gBTms66VFiH389GYOy8rZ0XML0d7DGKU1ttV7Ol6IT9NG/9z0yd6VsXiWG9Yjheulc PlTVE9MACFV/KZ/9OggrOdYbplN7Z3rx+yVgVWy0sin3Ck9DwLeDXEOlzY22LaZNaIp2 /NH3dafAIGbpfWxfUC554OXBnLgmOvDlO+58WZ9rzp+CLNoYVjZsuGtA48QEETtoth3D PpE5OnWRHvQ3Jj89ol2LqRSoHGf1nArYTtYqbPSy7PDzn+J76dvDZC/a7A7+J7eaCKPR pspYnuzgekvlEcGIHRNvMGKF2UksFW1yxXm/e7U1Ar9kF0SxnsZ8Mg6AAUejol03WKHe N9+g== X-Gm-Message-State: AFqh2kqX/uOTA60Vi4GbFTs0d8qhytutmbglOCJu59HqWyu1r1yW777z tM+8EdjHYvL+LfM/RIRy8greEDFj5511DYRvkg== X-Google-Smtp-Source: AMrXdXtNm9J3NZyrFD1KxSqYxPFs466v/i5MLLy+izXPoRIE2JNGfeNALA/eYTNAOnPBcLdA/BrRIezn5OXkpRyumg== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a81:bc9:0:b0:471:d0:fcdf with SMTP id 192-20020a810bc9000000b0047100d0fcdfmr1932256ywl.108.1674260206107; Fri, 20 Jan 2023 16:16:46 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:19 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-9-ackerleytng@google.com> Subject: [RFC PATCH v3 08/31] KVM: selftests: Require GCC to realign stacks on function entry From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Some SSE instructions assume a 16-byte aligned stack, and GCC compiles assuming the stack is aligned: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=40838. This combination results in a #GP in guests. Adding this compiler flag will generate an alternate prologue and epilogue to realign the runtime stack, which makes selftest code slower and bigger, but this is okay since we do not need selftest code to be extremely performant. Similar issue discussed at https://lore.kernel.org/all/CAGtprH9yKvuaF5yruh3BupQe4BxDGiBQk3ExtY2m39yP-tppsg@mail.gmail.com/ Signed-off-by: Ackerley Tng --- tools/testing/selftests/kvm/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 317927d9c55bd..5f9cc1e6ee67e 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -205,7 +205,7 @@ LINUX_TOOL_ARCH_INCLUDE = $(top_srcdir)/tools/arch/x86/include else LINUX_TOOL_ARCH_INCLUDE = $(top_srcdir)/tools/arch/$(ARCH)/include endif -CFLAGS += -Wall -Wstrict-prototypes -Wuninitialized -O2 -g -std=gnu99 \ +CFLAGS += -mstackrealign -Wall -Wstrict-prototypes -Wuninitialized -O2 -g -std=gnu99 \ -fno-stack-protector -fno-PIE -I$(LINUX_TOOL_INCLUDE) \ -I$(LINUX_TOOL_ARCH_INCLUDE) -I$(LINUX_HDR_PATH) -Iinclude \ -I$( X-Patchwork-Id: 13110734 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3DDA2C25B50 for ; Sat, 21 Jan 2023 00:17:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229993AbjAUARf (ORCPT ); Fri, 20 Jan 2023 19:17:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53418 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229494AbjAUAR3 (ORCPT ); Fri, 20 Jan 2023 19:17:29 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ADA26BF8AF for ; Fri, 20 Jan 2023 16:17:01 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id d17-20020a5b0611000000b00801a0e3e117so3398004ybq.13 for ; Fri, 20 Jan 2023 16:17:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:from:to:cc:subject:date:message-id :reply-to; bh=e8fVu8QqTyecSUV8C3Vx7eVvdYsMLP9B/z2QHEeyWh0=; b=i5XEImBpyUeHSwTbKwhHcRZgMwVEdGe03n+MFsqTosDso+tBjMIOrGOnjLAM8/yky5 N4xhtWLwaFTCrzTc1/jhO8PJF3LDPjMBTYLowMXjeYy3ymUQmO35tlGr1y8GHmtAL2sH sfUB4Ydijv5hmx9wqVMWbLUo216Dcss6FPXZXeM5lm5CUQdAx6DwntdQLGBama8eC7r8 HSzcNAHXMYaquf6UWlPzQqgklPqhhRTF+U9yotPs103TVSsBYlOEoJKyXRFp2dWpM4TT 4eifnWcKS1kd5S3guDUMqKBoGzwfieLeEnFzoL1iONxvvnVHsG59qiJLJ5KK4TKEiHWd oKVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to; bh=e8fVu8QqTyecSUV8C3Vx7eVvdYsMLP9B/z2QHEeyWh0=; b=TSOjY6PWLhWpbHnOm5F126yJQmcT90UaFjIIk7VLNVyAVHGPxvzWLELvvyTRH0lkg6 QbNQ+s8eL3PH4lKBVkAKVAXIzdgALIauolNP9k6z8PZG/7+F7hfAPGU0S74o1ylw7EOp mT1pGF0AJrMTPCynPj6zgF+PVNWz0NaIQhZF92Iy6dAzRS5W2jR8Mh+9w6OkYhrZ92fI qjBN4xRKZjyPnO+6mEtNkJmFdv6/z0nr9xFP9YpbrlUWbwKcJzWZm5fiGILwShfYeqQd +SgQRkBtNxoXx24+Bzvp9I3vEKdKkjD8BnTWQyyL01JUsWi/GWnjqMhlzwcKybYppEp5 eFVA== X-Gm-Message-State: AFqh2kqqZGSF+NtBWKv+DyHdnrEwm6NIOhXBZWi4W1H3iz2z+fvB6+nk PmFBuQkuWHzfTraaCPxlOuNA/c3umW30iGjZ6Q== X-Google-Smtp-Source: AMrXdXs4cYCD+h7+e40ddRslg/axY93Tvds7sBJEjfQJwo0v5rVjQMzFA5/S09H+XvohVO57EXS5SSV7wzwv6fTLcw== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a0d:dd4e:0:b0:4eb:e96a:1c63 with SMTP id g75-20020a0ddd4e000000b004ebe96a1c63mr1986522ywe.82.1674260210698; Fri, 20 Jan 2023 16:16:50 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:20 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-10-ackerleytng@google.com> Subject: [RFC PATCH v3 09/31] KVM: selftests: TDX: Add TDX lifecycle test From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Erdem Aktas Adding a test to verify TDX lifecycle by creating a TD and running a dummy TDG.VP.VMCALL inside it. Signed-off-by: Erdem Aktas Signed-off-by: Ryan Afranji Signed-off-by: Sagi Shahar Co-developed-by: Ackerley Tng Signed-off-by: Ackerley Tng --- Changes RFCv2 -> RFCv3 + Add gitignore for tdx_vm_tests binary + Thanks to Isaku for the comment about saving rbp separately for gcc! In this revision, the assembly that wraps tdcall has been mostly taken from the kernel’s implementation, which would be familiar to you! + TDX test-related code is now grouped in tools/testing/selftests/kvm/include/x86_64/tdx/test_util.{c,h} and test-related functions and macros are prefixed with tdx_test to indicate its purpose. --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 4 + .../selftests/kvm/include/x86_64/tdx/tdcall.h | 35 ++++++++ .../selftests/kvm/include/x86_64/tdx/tdx.h | 12 +++ .../kvm/include/x86_64/tdx/test_util.h | 52 +++++++++++ .../selftests/kvm/lib/x86_64/tdx/tdcall.S | 90 +++++++++++++++++++ .../selftests/kvm/lib/x86_64/tdx/tdx.c | 27 ++++++ .../selftests/kvm/lib/x86_64/tdx/test_util.c | 34 +++++++ .../selftests/kvm/x86_64/tdx_vm_tests.c | 45 ++++++++++ 9 files changed, 300 insertions(+) create mode 100644 tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h create mode 100644 tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h create mode 100644 tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h create mode 100644 tools/testing/selftests/kvm/lib/x86_64/tdx/tdcall.S create mode 100644 tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c create mode 100644 tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c create mode 100644 tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c -- 2.39.0.246.g2a6d74b583-goog diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore index 813e7610619d9..370d6430b32b4 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -65,6 +65,7 @@ /x86_64/xss_msr_test /x86_64/vmx_pmu_caps_test /x86_64/triple_fault_event_test +/x86_64/tdx_vm_tests /access_tracking_perf_test /demand_paging_test /dirty_log_test diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 5f9cc1e6ee67e..9f289322a4933 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -61,6 +61,9 @@ LIBKVM_x86_64 += lib/x86_64/vmx.c LIBKVM_x86_64 += lib/x86_64/sev.c LIBKVM_x86_64 += lib/x86_64/tdx/tdx_util.c LIBKVM_x86_64 += lib/x86_64/tdx/td_boot.S +LIBKVM_x86_64 += lib/x86_64/tdx/tdcall.S +LIBKVM_x86_64 += lib/x86_64/tdx/tdx.c +LIBKVM_x86_64 += lib/x86_64/tdx/test_util.c LIBKVM_aarch64 += lib/aarch64/gic.c LIBKVM_aarch64 += lib/aarch64/gic_v3.c @@ -148,6 +151,7 @@ TEST_GEN_PROGS_x86_64 += set_memory_region_test TEST_GEN_PROGS_x86_64 += steal_time TEST_GEN_PROGS_x86_64 += kvm_binary_stats_test TEST_GEN_PROGS_x86_64 += system_counter_offset_test +TEST_GEN_PROGS_x86_64 += x86_64/tdx_vm_tests # Compiled outputs used by test targets TEST_GEN_PROGS_EXTENDED_x86_64 += x86_64/nx_huge_pages_test diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h b/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h new file mode 100644 index 0000000000000..78001bfec9c8d --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Adapted from arch/x86/include/asm/shared/tdx.h */ + +#ifndef SELFTESTS_TDX_TDCALL_H +#define SELFTESTS_TDX_TDCALL_H + +#include +#include + +#define TDG_VP_VMCALL_INSTRUCTION_IO_READ 0 +#define TDG_VP_VMCALL_INSTRUCTION_IO_WRITE 1 + +#define TDX_HCALL_HAS_OUTPUT BIT(0) + +#define TDX_HYPERCALL_STANDARD 0 + +/* + * Used in __tdx_hypercall() to pass down and get back registers' values of + * the TDCALL instruction when requesting services from the VMM. + * + * This is a software only structure and not part of the TDX module/VMM ABI. + */ +struct tdx_hypercall_args { + u64 r10; + u64 r11; + u64 r12; + u64 r13; + u64 r14; + u64 r15; +}; + +/* Used to request services from the VMM */ +u64 __tdx_hypercall(struct tdx_hypercall_args *args, unsigned long flags); + +#endif // SELFTESTS_TDX_TDCALL_H diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h new file mode 100644 index 0000000000000..a7161efe4ee2e --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef SELFTEST_TDX_TDX_H +#define SELFTEST_TDX_TDX_H + +#include + +#define TDG_VP_VMCALL_INSTRUCTION_IO 30 + +uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size, + uint64_t write, uint64_t *data); + +#endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h b/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h new file mode 100644 index 0000000000000..b570b6d978ff1 --- /dev/null +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef SELFTEST_TDX_TEST_UTIL_H +#define SELFTEST_TDX_TEST_UTIL_H + +#include + +#include "tdcall.h" + +#define TDX_TEST_SUCCESS_PORT 0x30 +#define TDX_TEST_SUCCESS_SIZE 4 + +/** + * Assert that tdx_test_success() was called in the guest. + */ +#define TDX_TEST_ASSERT_SUCCESS(VCPU) \ + (TEST_ASSERT( \ + ((VCPU)->run->exit_reason == KVM_EXIT_IO) && \ + ((VCPU)->run->io.port == TDX_TEST_SUCCESS_PORT) && \ + ((VCPU)->run->io.size == TDX_TEST_SUCCESS_SIZE) && \ + ((VCPU)->run->io.direction == \ + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE), \ + "Unexpected exit values while waiting for test completion: %u (%s) %d %d %d\n", \ + (VCPU)->run->exit_reason, \ + exit_reason_str((VCPU)->run->exit_reason), \ + (VCPU)->run->io.port, (VCPU)->run->io.size, \ + (VCPU)->run->io.direction)) + +/** + * Run a test in a new process. + * + * There might be multiple tests we are running and if one test fails, it will + * prevent the subsequent tests to run due to how tests are failing with + * TEST_ASSERT function. The run_in_new_process function will run a test in a + * new process context and wait for it to finish or fail to prevent TEST_ASSERT + * to kill the main testing process. + */ +void run_in_new_process(void (*func)(void)); + +/** + * Verify that the TDX is supported by KVM. + */ +bool is_tdx_enabled(void); + +/** + * Report test success to userspace. + * + * Use TDX_TEST_ASSERT_SUCCESS() to assert that this function was called in the + * guest. + */ +void tdx_test_success(void); + +#endif // SELFTEST_TDX_TEST_UTIL_H diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdcall.S b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdcall.S new file mode 100644 index 0000000000000..df9c1ed4bb2d1 --- /dev/null +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdcall.S @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Adapted from arch/x86/coco/tdx/tdcall.S */ + +#define TDX_HYPERCALL_r10 0 /* offsetof(struct tdx_hypercall_args, r10) */ +#define TDX_HYPERCALL_r11 8 /* offsetof(struct tdx_hypercall_args, r11) */ +#define TDX_HYPERCALL_r12 16 /* offsetof(struct tdx_hypercall_args, r12) */ +#define TDX_HYPERCALL_r13 24 /* offsetof(struct tdx_hypercall_args, r13) */ +#define TDX_HYPERCALL_r14 32 /* offsetof(struct tdx_hypercall_args, r14) */ +#define TDX_HYPERCALL_r15 40 /* offsetof(struct tdx_hypercall_args, r15) */ + +/* + * Bitmasks of exposed registers (with VMM). + */ +#define TDX_R10 0x400 +#define TDX_R11 0x800 +#define TDX_R12 0x1000 +#define TDX_R13 0x2000 +#define TDX_R14 0x4000 +#define TDX_R15 0x8000 + +#define TDX_HCALL_HAS_OUTPUT 0x1 + +/* + * These registers are clobbered to hold arguments for each + * TDVMCALL. They are safe to expose to the VMM. + * Each bit in this mask represents a register ID. Bit field + * details can be found in TDX GHCI specification, section + * titled "TDCALL [TDG.VP.VMCALL] leaf". + */ +#define TDVMCALL_EXPOSE_REGS_MASK ( TDX_R10 | TDX_R11 | \ + TDX_R12 | TDX_R13 | \ + TDX_R14 | TDX_R15 ) + +.code64 +.section .text + +.globl __tdx_hypercall +.type __tdx_hypercall, @function +__tdx_hypercall: + /* Set up stack frame */ + push %rbp + movq %rsp, %rbp + + /* Save callee-saved GPRs as mandated by the x86_64 ABI */ + push %r15 + push %r14 + push %r13 + push %r12 + + /* Mangle function call ABI into TDCALL ABI: */ + /* Set TDCALL leaf ID (TDVMCALL (0)) in RAX */ + xor %eax, %eax + + /* Copy hypercall registers from arg struct: */ + movq TDX_HYPERCALL_r10(%rdi), %r10 + movq TDX_HYPERCALL_r11(%rdi), %r11 + movq TDX_HYPERCALL_r12(%rdi), %r12 + movq TDX_HYPERCALL_r13(%rdi), %r13 + movq TDX_HYPERCALL_r14(%rdi), %r14 + movq TDX_HYPERCALL_r15(%rdi), %r15 + + movl $TDVMCALL_EXPOSE_REGS_MASK, %ecx + + tdcall + + /* TDVMCALL leaf return code is in R10 */ + movq %r10, %rax + + /* Copy hypercall result registers to arg struct if needed */ + testq $TDX_HCALL_HAS_OUTPUT, %rsi + jz .Lout + + movq %r10, TDX_HYPERCALL_r10(%rdi) + movq %r11, TDX_HYPERCALL_r11(%rdi) + movq %r12, TDX_HYPERCALL_r12(%rdi) + movq %r13, TDX_HYPERCALL_r13(%rdi) + movq %r14, TDX_HYPERCALL_r14(%rdi) + movq %r15, TDX_HYPERCALL_r15(%rdi) +.Lout: + /* Restore callee-saved GPRs as mandated by the x86_64 ABI */ + pop %r12 + pop %r13 + pop %r14 + pop %r15 + + pop %rbp + ret + +/* Disable executable stack */ +.section .note.GNU-stack,"",%progbits diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c new file mode 100644 index 0000000000000..c2414523487a7 --- /dev/null +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include "tdx/tdcall.h" +#include "tdx/tdx.h" + +uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size, + uint64_t write, uint64_t *data) +{ + uint64_t ret; + struct tdx_hypercall_args args = { + .r10 = TDX_HYPERCALL_STANDARD, + .r11 = TDG_VP_VMCALL_INSTRUCTION_IO, + .r12 = size, + .r13 = write, + .r14 = port, + }; + + if (write) + args.r15 = *data; + + ret = __tdx_hypercall(&args, write ? 0 : TDX_HCALL_HAS_OUTPUT); + + if (!write) + *data = args.r11; + + return ret; +} diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c b/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c new file mode 100644 index 0000000000000..6905d0ca38774 --- /dev/null +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include + +#include "kvm_util_base.h" +#include "tdx/tdx.h" +#include "tdx/test_util.h" + +void run_in_new_process(void (*func)(void)) +{ + if (fork() == 0) { + func(); + exit(0); + } + wait(NULL); +} + +bool is_tdx_enabled(void) +{ + return !!(kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(KVM_X86_TDX_VM)); +} + +void tdx_test_success(void) +{ + uint64_t code = 0; + + tdg_vp_vmcall_instruction_io(TDX_TEST_SUCCESS_PORT, + TDX_TEST_SUCCESS_SIZE, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE, &code); +} diff --git a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c new file mode 100644 index 0000000000000..a18d1c9d60264 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include "kvm_util_base.h" +#include "tdx/tdx_util.h" +#include "tdx/test_util.h" +#include "test_util.h" + +void guest_code_lifecycle(void) +{ + tdx_test_success(); +} + +void verify_td_lifecycle(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + + vm = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = td_vcpu_add(vm, 0, guest_code_lifecycle); + td_finalize(vm); + + printf("Verifying TD lifecycle:\n"); + + vcpu_run(vcpu); + TDX_TEST_ASSERT_SUCCESS(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + +int main(int argc, char **argv) +{ + setbuf(stdout, NULL); + + if (!is_tdx_enabled()) { + print_skip("TDX is not supported by the KVM"); + exit(KSFT_SKIP); + } + + run_in_new_process(&verify_td_lifecycle); + + return 0; +} From patchwork Sat Jan 21 00:15:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110735 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EBC5FC38159 for ; Sat, 21 Jan 2023 00:17:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229447AbjAUARi (ORCPT ); Fri, 20 Jan 2023 19:17:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53282 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230002AbjAUARa (ORCPT ); Fri, 20 Jan 2023 19:17:30 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BD381C13C5 for ; Fri, 20 Jan 2023 16:17:02 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id k204-20020a256fd5000000b007b8b040bc50so7395895ybc.1 for ; Fri, 20 Jan 2023 16:17:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=8GFYGGx0+c/JTGAK76bVwpACnJQuQ5mSfW/fyx26JT0=; b=HumOf0ifUS3YfnDJXNhoBdtmg9FJoE6wlCqVa+T161sRt1hq9HViWgqfj58zoHAvEy N1gnFBZrQ+eGpdu4uvsajl/JhWzXFRMweDw5B7cLPR2DetJwNStCJNUgHTshrQrqn/vM 6p1U06lQUhSYRltYVveoaOS4Hm0lQTnA1D6DxIbA+JYpeR8ooszyhN+GlEG6BzICjwNv +Ov1qZ1buIRk1iuCpq0nxacfe1z0jB4LFQWwjPz2eS+q/R+IyU6HXcVuSRHKiu66/7N9 JdQZshBP4SEBmSt+Y+2useYdIsEUupcBJJkbyA1JiDKDDwa+LNl7fHz4T6gjSu5w/J6V SNKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=8GFYGGx0+c/JTGAK76bVwpACnJQuQ5mSfW/fyx26JT0=; b=anS6BnyZ/S1pHQ0q76DeFKdad+lEAHBwMUMSJGoC0NMzzWbtO95qs+X9512tc3aa3v qJBkHTZwVnoVibMVt1eQF2BZ+0dNxlrnSwgH047acoVw2/baLriVW1mvBmLY9xJgXHWy IhyAfPB9KgpysqPbAAszYSAsN3rDcwZSX2ReWuqrecX+dkiJ3btJkXA9XVcSXi+N3/r8 LQIAO/NsJBCzPsZJSloHRXdOwNdBxJ1t+0dorYwGCx1eNHWb/ZN3SWjF58qv+Ovc9jn9 2wkvhwN20i+6UpxqmjVDM3H/rBX0pm914apIq8A+z9ZdinX0OASW+CgfrZ2KjwRsVI1v 1IMw== X-Gm-Message-State: AFqh2kq30Wky7uBMh4sigyo4C4taYN5DvrBYSQPKLMT5rgWbc9xzL8iF iuSTMmWnVjtsXcyZ0Te9xY/ZyQNdgXO/p1LnYQ== X-Google-Smtp-Source: AMrXdXtzwGmgyX9XH8aXpbr891TmJe7G0QtxHKbFHE3C/5WFHHCdxWQnUZ0bfAsxZqyreJBq9m1qDrFhBr37yEpLuw== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a05:6902:8f:b0:800:748:7d05 with SMTP id h15-20020a056902008f00b0080007487d05mr683891ybs.15.1674260215175; Fri, 20 Jan 2023 16:16:55 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:21 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-11-ackerleytng@google.com> Subject: [RFC PATCH v3 10/31] KVM: selftests: TDX: Add report_fatal_error test From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Sagi Shahar The test checks report_fatal_error functionality. Signed-off-by: Sagi Shahar Signed-off-by: Ackerley Tng --- .../selftests/kvm/include/x86_64/tdx/tdx.h | 3 ++ .../kvm/include/x86_64/tdx/test_util.h | 19 ++++++++ .../selftests/kvm/lib/x86_64/tdx/tdx.c | 18 ++++++++ .../selftests/kvm/lib/x86_64/tdx/test_util.c | 10 +++++ .../selftests/kvm/x86_64/tdx_vm_tests.c | 44 +++++++++++++++++++ 5 files changed, 94 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 a7161efe4ee2e..28959bdb07628 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h @@ -4,9 +4,12 @@ #include +#define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 + #define TDG_VP_VMCALL_INSTRUCTION_IO 30 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); #endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h b/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h index b570b6d978ff1..6d69921136bd2 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h @@ -49,4 +49,23 @@ bool is_tdx_enabled(void); */ void tdx_test_success(void); +/** + * Report an error with @error_code to userspace. + * + * Return value from tdg_vp_vmcall_report_fatal_error is ignored since execution + * is not expected to continue beyond this point. + */ +void tdx_test_fatal(uint64_t error_code); + +/** + * Report an error with @error_code to userspace. + * + * @data_gpa may point to an optional shared guest memory holding the error + * string. + * + * Return value from tdg_vp_vmcall_report_fatal_error is ignored since execution + * is not expected to continue beyond this point. + */ +void tdx_test_fatal_with_data(uint64_t error_code, uint64_t data_gpa); + #endif // SELFTEST_TDX_TEST_UTIL_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 c2414523487a7..e8c399f2277cf 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only +#include + #include "tdx/tdcall.h" #include "tdx/tdx.h" @@ -25,3 +27,19 @@ uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size, return ret; } + +void tdg_vp_vmcall_report_fatal_error(uint64_t error_code, uint64_t data_gpa) +{ + struct tdx_hypercall_args args; + + memset(&args, 0, sizeof(struct tdx_hypercall_args)); + + if (data_gpa) + error_code |= 0x8000000000000000; + + args.r11 = TDG_VP_VMCALL_REPORT_FATAL_ERROR; + args.r12 = error_code; + args.r13 = data_gpa; + + __tdx_hypercall(&args, 0); +} diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c b/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c index 6905d0ca38774..7f3cd8089cea3 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c @@ -32,3 +32,13 @@ void tdx_test_success(void) TDX_TEST_SUCCESS_SIZE, TDG_VP_VMCALL_INSTRUCTION_IO_WRITE, &code); } + +void tdx_test_fatal_with_data(uint64_t error_code, uint64_t data_gpa) +{ + tdg_vp_vmcall_report_fatal_error(error_code, data_gpa); +} + +void tdx_test_fatal(uint64_t error_code) +{ + tdx_test_fatal_with_data(error_code, 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 a18d1c9d60264..627d60b573bb6 100644 --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c @@ -2,6 +2,7 @@ #include #include "kvm_util_base.h" +#include "tdx/tdx.h" #include "tdx/tdx_util.h" #include "tdx/test_util.h" #include "test_util.h" @@ -30,6 +31,48 @@ void verify_td_lifecycle(void) printf("\t ... PASSED\n"); } +void guest_code_report_fatal_error(void) +{ + uint64_t err; + + /* + * Note: err should follow the GHCI spec definition: + * bits 31:0 should be set to 0. + * bits 62:32 are used for TD-specific extended error code. + * bit 63 is used to mark additional information in shared memory. + */ + err = 0x0BAAAAAD00000000; + if (err) + tdx_test_fatal(err); + + tdx_test_success(); +} +void verify_report_fatal_error(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + + vm = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = td_vcpu_add(vm, 0, guest_code_report_fatal_error); + td_finalize(vm); + + printf("Verifying report_fatal_error:\n"); + + vcpu_run(vcpu); + ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_SYSTEM_EVENT); + ASSERT_EQ(vcpu->run->system_event.ndata, 3); + ASSERT_EQ(vcpu->run->system_event.data[0], TDG_VP_VMCALL_REPORT_FATAL_ERROR); + ASSERT_EQ(vcpu->run->system_event.data[1], 0x0BAAAAAD00000000); + ASSERT_EQ(vcpu->run->system_event.data[2], 0); + + vcpu_run(vcpu); + TDX_TEST_ASSERT_SUCCESS(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { setbuf(stdout, NULL); @@ -40,6 +83,7 @@ int main(int argc, char **argv) } run_in_new_process(&verify_td_lifecycle); + run_in_new_process(&verify_report_fatal_error); return 0; } From patchwork Sat Jan 21 00:15:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110736 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 699DEC05027 for ; Sat, 21 Jan 2023 00:17:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230092AbjAUARw (ORCPT ); Fri, 20 Jan 2023 19:17:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53402 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229986AbjAUARd (ORCPT ); Fri, 20 Jan 2023 19:17:33 -0500 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9ED37CC5C9 for ; Fri, 20 Jan 2023 16:17:10 -0800 (PST) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-50232845661so17854207b3.19 for ; Fri, 20 Jan 2023 16:17:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=EC2eVAKw5chE0JhJXlD1+MmiDErdw2lzMwJWsfEJffs=; b=X/BTnHPRI0KSxecnxIVHmWDH6w6f+DxWnjjSrMtMe2JlJrUKWmKU1ub1lVQuTb4GUy WqE6l0j/QytLan9Ix3EXZ9Gxbd9gZ0kkNwPysoMtmBq8n+lforCzB5DlEneN7VjDx43z Hfdk7kbMenghMMrSWfS1S1PHUwdSfv4fl8uCKKZ4eT4n5GNnzLri4jpCvbCJQKrfAgJz LscvoW9GDaRYlOFM2DU9J9XqYw6vCt0DytT2V6/0DC66CnDbhom9eLhsJnK7aMe2ayBa lGsYo07CWm6lLnw2AekdvE+dIO3AY3tqLqnG5HMTEgNZjA6X/rorMfltBuVCVyB9/iSj HtUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=EC2eVAKw5chE0JhJXlD1+MmiDErdw2lzMwJWsfEJffs=; b=op1rJjkp7UJ8ajrAoWXMvEJyDo0JNXgRCQPwQG4jouc4xzaumVlskekfF+d6OZ5ERw HHZfQwRbVwVQ/pFHiZ3J8bdC2j3w8ZAVRGjD7Yb+5dmcVBRsaDZdtodYeQoBLLv6zr9G l3ZYg7F7zsUAhwNhSLMILB8AdX5O2VHnTrQ9rGi06pgHQuJh9tQT9GEAWHY40jIscljd YfAAMlr56bc4ByQikkWT+6PUCmesjaN6Wo7e37fsxRS4vmK+agmR/KRM4GsS7zTLkE9c 5DaULEXDQRo5rmstxXmLt8t007d838nyY/z9GbaPzElsuDJ9qFdF9hC7nj5LXwW7LCwB EjTw== X-Gm-Message-State: AFqh2kri9WVEr5qPC2MVRpOVyzPSdjsbwL6BQpx77oFDYtUWUeVIBGoJ 2qaaoYvJUoLGm/WD2ksiXXJ2hRjJteN899txcw== X-Google-Smtp-Source: AMrXdXvECtv2OVE4yH2VV4gatly+5G5v4fXTnNgN4aEsp+twouX6j1MXGn/5UpxGAcY1UnIT25ptBjaye89JecjzIg== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a81:1990:0:b0:3c7:edf8:6eb with SMTP id 138-20020a811990000000b003c7edf806ebmr1896073ywz.9.1674260219981; Fri, 20 Jan 2023 16:16:59 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:22 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-12-ackerleytng@google.com> Subject: [RFC PATCH v3 11/31] KVM: selftests: TDX: Adding test case for TDX port IO From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Erdem Aktas Verifies TDVMCALL READ and WRITE operations. Signed-off-by: Erdem Aktas Signed-off-by: Sagi Shahar Signed-off-by: Ackerley Tng --- .../kvm/include/x86_64/tdx/test_util.h | 34 ++++++++ .../selftests/kvm/x86_64/tdx_vm_tests.c | 82 +++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h b/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h index 6d69921136bd2..95a5d5be7f0bf 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h @@ -9,6 +9,40 @@ #define TDX_TEST_SUCCESS_PORT 0x30 #define TDX_TEST_SUCCESS_SIZE 4 +/** + * Assert that some IO operation involving tdg_vp_vmcall_instruction_io() was + * called in the guest. + */ +#define TDX_TEST_ASSERT_IO(VCPU, PORT, SIZE, DIR) \ + do { \ + TEST_ASSERT((VCPU)->run->exit_reason == KVM_EXIT_IO, \ + "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", \ + (VCPU)->run->exit_reason, \ + exit_reason_str((VCPU)->run->exit_reason)); \ + \ + TEST_ASSERT(((VCPU)->run->exit_reason == KVM_EXIT_IO) && \ + ((VCPU)->run->io.port == (PORT)) && \ + ((VCPU)->run->io.size == (SIZE)) && \ + ((VCPU)->run->io.direction == (DIR)), \ + "Got unexpected IO exit values: %u (%s) %d %d %d\n", \ + (VCPU)->run->exit_reason, \ + exit_reason_str((VCPU)->run->exit_reason), \ + (VCPU)->run->io.port, (VCPU)->run->io.size, \ + (VCPU)->run->io.direction); \ + } while (0) + +/** + * Check and report if there was some failure in the guest, either an exception + * like a triple fault, or if a tdx_test_fatal() was hit. + */ +#define TDX_TEST_CHECK_GUEST_FAILURE(VCPU) \ + do { \ + if ((VCPU)->run->exit_reason == KVM_EXIT_SYSTEM_EVENT) \ + TEST_FAIL("Guest reported error. error code: %lld (0x%llx)\n", \ + (VCPU)->run->system_event.data[1], \ + (VCPU)->run->system_event.data[1]); \ + } while (0) + /** * Assert that tdx_test_success() was called in the guest. */ 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 627d60b573bb6..885c2b6bb1b96 100644 --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c @@ -2,6 +2,7 @@ #include #include "kvm_util_base.h" +#include "tdx/tdcall.h" #include "tdx/tdx.h" #include "tdx/tdx_util.h" #include "tdx/test_util.h" @@ -73,6 +74,86 @@ void verify_report_fatal_error(void) printf("\t ... PASSED\n"); } +#define TDX_IOEXIT_TEST_PORT 0x50 + +/* + * Verifies IO functionality by writing a |value| to a predefined port. + * Verifies that the read value is |value| + 1 from the same port. + * If all the tests are passed then write a value to port TDX_TEST_PORT + */ +void guest_ioexit(void) +{ + uint64_t data_out, data_in, delta; + uint64_t ret; + + data_out = 0xAB; + ret = tdg_vp_vmcall_instruction_io(TDX_IOEXIT_TEST_PORT, 1, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE, + &data_out); + if (ret) + tdx_test_fatal(ret); + + ret = tdg_vp_vmcall_instruction_io(TDX_IOEXIT_TEST_PORT, 1, + TDG_VP_VMCALL_INSTRUCTION_IO_READ, + &data_in); + if (ret) + tdx_test_fatal(ret); + + delta = data_in - data_out; + if (delta != 1) + tdx_test_fatal(ret); + + tdx_test_success(); +} + +void verify_td_ioexit(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + + uint32_t port_data; + + vm = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = td_vcpu_add(vm, 0, guest_ioexit); + td_finalize(vm); + + printf("Verifying TD IO Exit:\n"); + + /* Wait for guest to do a IO write */ + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_IOEXIT_TEST_PORT, 1, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + port_data = *(uint8_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + printf("\t ... IO WRITE: OK\n"); + + /* + * Wait for the guest to do a IO read. Provide the previous written data + * + 1 back to the guest + */ + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_IOEXIT_TEST_PORT, 1, + TDG_VP_VMCALL_INSTRUCTION_IO_READ); + *(uint8_t *)((void *)vcpu->run + vcpu->run->io.data_offset) = port_data + 1; + + printf("\t ... IO READ: OK\n"); + + /* + * Wait for the guest to complete execution successfully. The read + * value is checked within the guest. + */ + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_SUCCESS(vcpu); + + printf("\t ... IO verify read/write values: OK\n"); + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { setbuf(stdout, NULL); @@ -84,6 +165,7 @@ int main(int argc, char **argv) run_in_new_process(&verify_td_lifecycle); run_in_new_process(&verify_report_fatal_error); + run_in_new_process(&verify_td_ioexit); return 0; } From patchwork Sat Jan 21 00:15:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110737 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4052CC27C76 for ; Sat, 21 Jan 2023 00:18:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230080AbjAUASD (ORCPT ); Fri, 20 Jan 2023 19:18:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54020 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229969AbjAUARp (ORCPT ); Fri, 20 Jan 2023 19:17:45 -0500 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E0D92C9272 for ; Fri, 20 Jan 2023 16:17:20 -0800 (PST) Received: by mail-pg1-x54a.google.com with SMTP id y37-20020a634b25000000b004b1d90ea947so3271082pga.15 for ; Fri, 20 Jan 2023 16:17:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=i5oNII0+lLuKlf86/kD2DoUVJCXq3iLqKc12JrydmuE=; b=LAEhu7IkGXJf2FuHkgdLDDQdJw5VBwJJZc2AEokK24pr3alf+8FDMjZ2pinHR4ciHa +Oq98y722TU4COUPfEnyjM4uESO8QJBDHGnVB3w6Vsuux0DUHEz27ZW7Z3KKfc5LBvD8 TGs5+WTQPbgaRa5Y3/V8V2K514JbDDUqjQ3m39BfWJbauqvu05Mz8MsoZFqLp80t/lzN p4XfjNXi14DaUj2JEj4WJHNZvW0x9dZZJWn3caDoDhkAbuVwAfoCkLVg3WZUCRoY9ahk AK1EDaJ3UMuYTScpM3TZgKN1hKf76Im39SagK1u0d1eq13O6iYyZj6fK+iIYcqPVDZg6 FTKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=i5oNII0+lLuKlf86/kD2DoUVJCXq3iLqKc12JrydmuE=; b=EXp6DQZbkNaLaPJdTOcqkr/cE2NtWTkAsMy37jaqYQjt2D37BWmlnyALisaPqmTGJn rHByT4hFEi9LVAMLJkz/oAvJvYwjulx624nTygsBA3yS9xGEZGwyFRg9P9+8H8ls7aE9 jmmEQeLnsKbVf/Pf/RCX4hE74gwk+pAjByDCkB966tFi58mEsiuUGfm8w+wtyNqpRtBa 7KyvF5z6TZ7EPC3LZu827OmtyqTlBpJP6zdYLBAgm5SiU27NDdXFBeQQF/ieNo7lhcXL ZA+ltPcofY+/M7cXCzQbHUwsImTf74N7WcmCFQ2Cg2tZevaDVugZEhXpvRFKpJ/MmBQC 4QsA== X-Gm-Message-State: AFqh2kq+GatIRZ4g7Ny5bpEBCV2Nd/PB62uyV7MxkSYja6Gd0qZlndti QGLKS2zIKi8mQysXCNpCgW0ivKyfzaQxsZPSGw== X-Google-Smtp-Source: AMrXdXuTfxIVAzTb1jlUYpnuT5J/zUqBDcX1N7GbIRzVdvA7coUgCHn/bU54/8cQLxM96lqf3TWWbP1uxHSoMjoYsA== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a62:ae10:0:b0:580:9b0b:4fde with SMTP id q16-20020a62ae10000000b005809b0b4fdemr1894341pff.49.1674260224601; Fri, 20 Jan 2023 16:17:04 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:23 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-13-ackerleytng@google.com> Subject: [RFC PATCH v3 12/31] KVM: selftests: TDX: Add basic TDX CPUID test From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Sagi Shahar The test reads CPUID values from inside a TD VM and compare them to expected values. The test targets CPUID values which are virtualized as "As Configured", "As Configured (if Native)", "Calculated", "Fixed" and "Native" according to the TDX spec. Signed-off-by: Sagi Shahar Signed-off-by: Ackerley Tng --- Changes RFCv2 -> RFCv3 + Manually inlined cpuid function in cpuid test. This highlights the purpose of this test - to test the result of the cpuid instruction. + Replace find_cpuid_entry with kvm_get_supported_cpuid_entry from tools/testing/selftests/kvm/lib/x86_64/processor.c --- .../kvm/include/x86_64/tdx/test_util.h | 9 ++ .../selftests/kvm/lib/x86_64/tdx/test_util.c | 11 ++ .../selftests/kvm/x86_64/tdx_vm_tests.c | 106 ++++++++++++++++++ 3 files changed, 126 insertions(+) -- 2.39.0.246.g2a6d74b583-goog diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h b/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h index 95a5d5be7f0bf..af0ddbfe8d71b 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h @@ -9,6 +9,9 @@ #define TDX_TEST_SUCCESS_PORT 0x30 #define TDX_TEST_SUCCESS_SIZE 4 +#define TDX_TEST_REPORT_PORT 0x31 +#define TDX_TEST_REPORT_SIZE 4 + /** * Assert that some IO operation involving tdg_vp_vmcall_instruction_io() was * called in the guest. @@ -102,4 +105,10 @@ void tdx_test_fatal(uint64_t error_code); */ void tdx_test_fatal_with_data(uint64_t error_code, uint64_t data_gpa); +/** + * Report a 32 bit value from the guest to user space using TDG.VP.VMCALL + * call. Data is reported on port TDX_TEST_REPORT_PORT. + */ +uint64_t tdx_test_report_to_user_space(uint32_t data); + #endif // SELFTEST_TDX_TEST_UTIL_H diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c b/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c index 7f3cd8089cea3..55c5a1e634df7 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c @@ -42,3 +42,14 @@ void tdx_test_fatal(uint64_t error_code) { tdx_test_fatal_with_data(error_code, 0); } + +uint64_t tdx_test_report_to_user_space(uint32_t data) +{ + /* Upcast data to match tdg_vp_vmcall_instruction_io signature */ + uint64_t data_64 = data; + + return tdg_vp_vmcall_instruction_io(TDX_TEST_REPORT_PORT, + TDX_TEST_REPORT_SIZE, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE, + &data_64); +} 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 885c2b6bb1b96..b6072769967fa 100644 --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c @@ -2,6 +2,7 @@ #include #include "kvm_util_base.h" +#include "processor.h" #include "tdx/tdcall.h" #include "tdx/tdx.h" #include "tdx/tdx_util.h" @@ -154,6 +155,110 @@ void verify_td_ioexit(void) printf("\t ... PASSED\n"); } +/* + * Verifies CPUID functionality by reading CPUID values in guest. The guest + * will then send the values to userspace using an IO write to be checked + * against the expected values. + */ +void guest_code_cpuid(void) +{ + uint64_t err; + uint32_t ebx, ecx; + + /* Read CPUID leaf 0x1 */ + asm volatile ( + "cpuid" + : "=b" (ebx), "=c" (ecx) + : "a" (0x1) + : "edx"); + + err = tdx_test_report_to_user_space(ebx); + if (err) + tdx_test_fatal(err); + + err = tdx_test_report_to_user_space(ecx); + if (err) + tdx_test_fatal(err); + + tdx_test_success(); +} + +void verify_td_cpuid(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + + uint32_t ebx, ecx; + const struct kvm_cpuid_entry2 *cpuid_entry; + uint32_t guest_clflush_line_size; + uint32_t guest_max_addressable_ids, host_max_addressable_ids; + uint32_t guest_sse3_enabled; + uint32_t guest_fma_enabled; + uint32_t guest_initial_apic_id; + + vm = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = td_vcpu_add(vm, 0, guest_code_cpuid); + td_finalize(vm); + + printf("Verifying TD CPUID:\n"); + + /* Wait for guest to report ebx value */ + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_TEST_REPORT_PORT, 4, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + ebx = *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + /* Wait for guest to report either ecx value or error */ + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_TEST_REPORT_PORT, 4, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + ecx = *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + /* Wait for guest to complete execution */ + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_SUCCESS(vcpu); + + /* Verify the CPUID values we got from the guest. */ + printf("\t ... Verifying CPUID values from guest\n"); + + /* Get KVM CPUIDs for reference */ + cpuid_entry = kvm_get_supported_cpuid_entry(1); + TEST_ASSERT(cpuid_entry, "CPUID entry missing\n"); + + host_max_addressable_ids = (cpuid_entry->ebx >> 16) & 0xFF; + + guest_sse3_enabled = ecx & 0x1; // Native + guest_clflush_line_size = (ebx >> 8) & 0xFF; // Fixed + guest_max_addressable_ids = (ebx >> 16) & 0xFF; // As Configured + guest_fma_enabled = (ecx >> 12) & 0x1; // As Configured (if Native) + guest_initial_apic_id = (ebx >> 24) & 0xFF; // Calculated + + ASSERT_EQ(guest_sse3_enabled, 1); + ASSERT_EQ(guest_clflush_line_size, 8); + ASSERT_EQ(guest_max_addressable_ids, host_max_addressable_ids); + + /* TODO: This only tests the native value. To properly test + * "As Configured (if Native)" we need to override this value + * in the TD params + */ + ASSERT_EQ(guest_fma_enabled, 1); + + /* TODO: guest_initial_apic_id is calculated based on the number of + * VCPUs in the TD. From the spec: "Virtual CPU index, starting from 0 + * and allocated sequentially on each successful TDH.VP.INIT" + * To test non-trivial values we either need a TD with multiple VCPUs + * or to pick a different calculated value. + */ + ASSERT_EQ(guest_initial_apic_id, 0); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { setbuf(stdout, NULL); @@ -166,6 +271,7 @@ int main(int argc, char **argv) run_in_new_process(&verify_td_lifecycle); run_in_new_process(&verify_report_fatal_error); run_in_new_process(&verify_td_ioexit); + run_in_new_process(&verify_td_cpuid); return 0; } From patchwork Sat Jan 21 00:15:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110738 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BBFB7C38159 for ; Sat, 21 Jan 2023 00:18:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230107AbjAUASH (ORCPT ); Fri, 20 Jan 2023 19:18:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53082 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230093AbjAUARw (ORCPT ); Fri, 20 Jan 2023 19:17:52 -0500 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5DB2FDA8F6 for ; Fri, 20 Jan 2023 16:17:27 -0800 (PST) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-4fee82718afso34930027b3.5 for ; Fri, 20 Jan 2023 16:17:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=VfDFJ+/iyxAI3PGD3pUrIdU4TyKMDMQ1v8Rnr8gjcS8=; b=Ow7xLTNJ7rWpBHPrW8eCRek9b8bCgS2hzG4Hq0bJ5VO+ckVuiDumEDCCpEmhHJ4XHr 3rpwqyxkvQJMn76f2v+MmT8l2gC5Z7ueLnbbKv8iar3hP82Tppw00KfoZs5K3Pj+6rJA ZZmx53VNnB8yqA01NJ1jsRgThA4aw/MRMW/f+xyoyxOQKNPacLBO7ncB/IybPvuroSxi z2afvFEE4hCDP3dhztAfsVnrg0qJ+MlrsI0Mw47HmPbRefUb/bkvyj9EB5VSirVgeKsl RKFLa+EcCHFo78XkadVcuetutuQO003GEBZc0UIYfoPf2QfzmwNBFldGfFXHTnBKJ24T E2Jg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=VfDFJ+/iyxAI3PGD3pUrIdU4TyKMDMQ1v8Rnr8gjcS8=; b=MUWt5QTQR+K8F6x6/s4oLKolBTJMHpE82RQ7173I5hHGTHWWh85JcEUlKeAgR0Zy4H DOqlH2k8OjCeWbVW3C6w403FJI7kxywbLe3Uhvx4/GARS57PQo3QHxgPF4QoyYgKU+HY 7G+fSeH5NmH9PP8n+DZfmqUqbouGQ63i3MDhqqYRggOdDdr/sD601tzM4AASkN4YdkmS 3A85UKMjtaoQhW2USV8x3wFIkHWRENNfWEIZyg2g7MXl/l2nJLPA71p6VhzJDpS1i3aI HmvzYo4IWa+Jgx3mIf963za+PGYRW0ErReswOsrc0aoQbfyDKHa/UPW4T9jFffZ2asX5 d4nA== X-Gm-Message-State: AFqh2kpTBuRmKG6/sHtCe3pKYey3c7N+G6+SI6bzVceEvtgQzN3tsvPo X6bQ/xtX25DpXhuAemH5yO+drWzUEUt5hFZIpw== X-Google-Smtp-Source: AMrXdXtHeebCqRs3GM2cU8NHHPkaoFTXq7tzkkWCUQxlXI7dZnOWhcvQvwmKfOZnQB6MDB+5e5ExBanwRiPWIgzekA== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a81:7189:0:b0:360:7f0a:1620 with SMTP id m131-20020a817189000000b003607f0a1620mr2245734ywc.192.1674260228807; Fri, 20 Jan 2023 16:17:08 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:24 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-14-ackerleytng@google.com> Subject: [RFC PATCH v3 13/31] KVM: selftests: TDX: Add basic get_td_vmcall_info test From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Sagi Shahar The test calls get_td_vmcall_info from the guest and verifies the expected returned values. Signed-off-by: Sagi Shahar Signed-off-by: Ackerley Tng --- .../selftests/kvm/include/x86_64/tdx/tdx.h | 3 + .../kvm/include/x86_64/tdx/test_util.h | 27 +++++++ .../selftests/kvm/lib/x86_64/tdx/tdx.c | 23 ++++++ .../selftests/kvm/lib/x86_64/tdx/test_util.c | 46 +++++++++++ .../selftests/kvm/x86_64/tdx_vm_tests.c | 80 +++++++++++++++++++ 5 files changed, 179 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 28959bdb07628..37ad16943e299 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h @@ -4,6 +4,7 @@ #include +#define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 #define TDG_VP_VMCALL_INSTRUCTION_IO 30 @@ -11,5 +12,7 @@ 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); #endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h b/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h index af0ddbfe8d71b..8a9b6a1bec3eb 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h @@ -4,6 +4,7 @@ #include +#include "kvm_util_base.h" #include "tdcall.h" #define TDX_TEST_SUCCESS_PORT 0x30 @@ -111,4 +112,30 @@ void tdx_test_fatal_with_data(uint64_t error_code, uint64_t data_gpa); */ uint64_t tdx_test_report_to_user_space(uint32_t data); +/** + * Report a 64 bit value from the guest to user space using TDG.VP.VMCALL + * call. + * + * Data is sent to host in 2 calls. LSB is sent (and needs to be read) first. + */ +uint64_t tdx_test_send_64bit(uint64_t port, uint64_t data); + +/** + * Report a 64 bit value from the guest to user space using TDG.VP.VMCALL + * call. Data is reported on port TDX_TEST_REPORT_PORT. + */ +uint64_t tdx_test_report_64bit_to_user_space(uint64_t data); + +/** + * Read a 64 bit value from the guest in user space, sent using + * tdx_test_send_64bit(). + */ +uint64_t tdx_test_read_64bit(struct kvm_vcpu *vcpu, uint64_t port); + +/** + * Read a 64 bit value from the guest in user space, sent using + * tdx_test_report_64bit_to_user_space. + */ +uint64_t tdx_test_read_64bit_report_from_guest(struct kvm_vcpu *vcpu); + #endif // SELFTEST_TDX_TEST_UTIL_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 e8c399f2277cf..7254d61515db2 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c @@ -43,3 +43,26 @@ void tdg_vp_vmcall_report_fatal_error(uint64_t error_code, uint64_t data_gpa) __tdx_hypercall(&args, 0); } + +uint64_t tdg_vp_vmcall_get_td_vmcall_info(uint64_t *r11, uint64_t *r12, + uint64_t *r13, uint64_t *r14) +{ + uint64_t ret; + struct tdx_hypercall_args args = { + .r11 = TDG_VP_VMCALL_GET_TD_VM_CALL_INFO, + .r12 = 0, + }; + + ret = __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); + + if (r11) + *r11 = args.r11; + if (r12) + *r12 = args.r12; + if (r13) + *r13 = args.r13; + if (r14) + *r14 = args.r14; + + return ret; +} diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c b/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c index 55c5a1e634df7..3ae651cd5fac4 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/test_util.c @@ -7,6 +7,7 @@ #include #include "kvm_util_base.h" +#include "tdx/tdcall.h" #include "tdx/tdx.h" #include "tdx/test_util.h" @@ -53,3 +54,48 @@ uint64_t tdx_test_report_to_user_space(uint32_t data) TDG_VP_VMCALL_INSTRUCTION_IO_WRITE, &data_64); } + +uint64_t tdx_test_send_64bit(uint64_t port, uint64_t data) +{ + uint64_t err; + uint64_t data_lo = data & 0xFFFFFFFF; + uint64_t data_hi = (data >> 32) & 0xFFFFFFFF; + + err = tdg_vp_vmcall_instruction_io(port, 4, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE, + &data_lo); + if (err) + return err; + + return tdg_vp_vmcall_instruction_io(port, 4, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE, + &data_hi); +} + +uint64_t tdx_test_report_64bit_to_user_space(uint64_t data) +{ + return tdx_test_send_64bit(TDX_TEST_REPORT_PORT, data); +} + +uint64_t tdx_test_read_64bit(struct kvm_vcpu *vcpu, uint64_t port) +{ + uint32_t lo, hi; + uint64_t res; + + TDX_TEST_ASSERT_IO(vcpu, port, 4, TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + lo = *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + vcpu_run(vcpu); + + TDX_TEST_ASSERT_IO(vcpu, port, 4, TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + hi = *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + res = hi; + res = (res << 32) | lo; + return res; +} + +uint64_t tdx_test_read_64bit_report_from_guest(struct kvm_vcpu *vcpu) +{ + return tdx_test_read_64bit(vcpu, TDX_TEST_REPORT_PORT); +} 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 b6072769967fa..188442a734dca 100644 --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c @@ -259,6 +259,85 @@ void verify_td_cpuid(void) printf("\t ... PASSED\n"); } +/* + * Verifies get_td_vmcall_info functionality. + */ +void guest_code_get_td_vmcall_info(void) +{ + uint64_t err; + uint64_t r11, r12, r13, r14; + + err = tdg_vp_vmcall_get_td_vmcall_info(&r11, &r12, &r13, &r14); + if (err) + tdx_test_fatal(err); + + err = tdx_test_report_64bit_to_user_space(r11); + if (err) + tdx_test_fatal(err); + + err = tdx_test_report_64bit_to_user_space(r12); + if (err) + tdx_test_fatal(err); + + err = tdx_test_report_64bit_to_user_space(r13); + if (err) + tdx_test_fatal(err); + + err = tdx_test_report_64bit_to_user_space(r14); + if (err) + tdx_test_fatal(err); + + tdx_test_success(); +} + +void verify_get_td_vmcall_info(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + + uint64_t r11, r12, r13, r14; + + vm = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = td_vcpu_add(vm, 0, guest_code_get_td_vmcall_info); + td_finalize(vm); + + printf("Verifying TD get vmcall info:\n"); + + /* Wait for guest to report r11 value */ + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + r11 = tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r12 value */ + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + r12 = tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r13 value */ + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + r13 = tdx_test_read_64bit_report_from_guest(vcpu); + + /* Wait for guest to report r14 value */ + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + r14 = tdx_test_read_64bit_report_from_guest(vcpu); + + ASSERT_EQ(r11, 0); + ASSERT_EQ(r12, 0); + ASSERT_EQ(r13, 0); + ASSERT_EQ(r14, 0); + + /* Wait for guest to complete execution */ + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_SUCCESS(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { setbuf(stdout, NULL); @@ -272,6 +351,7 @@ int main(int argc, char **argv) run_in_new_process(&verify_report_fatal_error); run_in_new_process(&verify_td_ioexit); run_in_new_process(&verify_td_cpuid); + run_in_new_process(&verify_get_td_vmcall_info); return 0; } From patchwork Sat Jan 21 00:15:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110739 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94FECC05027 for ; Sat, 21 Jan 2023 00:18:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229796AbjAUASS (ORCPT ); Fri, 20 Jan 2023 19:18:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53886 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230032AbjAUAR4 (ORCPT ); Fri, 20 Jan 2023 19:17:56 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2F8DDA258F for ; Fri, 20 Jan 2023 16:17:34 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id z17-20020a256651000000b007907852ca4dso7465976ybm.16 for ; Fri, 20 Jan 2023 16:17:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=j6BV0YtQOiNrXMV5swymIknunfTEIhtzL+zfELVN7Ms=; b=l8az0f+ywIP6e260BtoZwU44Fhm7IcULO1Flblv5y1Y1LiZ/y7PKDffHyKWKkcxHNw KOWmv7uS/Xfu2NSm939NvnzW3uaCNDPHjv3W+IMXLDeZMzkhAJUE7lGBu2dPlPjNSPfL DeI6hQcFAF7QmYLhhlPjaOcp0Znt2M0/BEL4oesWn4F7j5jGAZm8nZ80ZtRDMmujgf+C CvkFThYu+v7NFEn7rLXXegNqaj9Jzw6M+w46LW8ueek/hizCwJecgABJOY/9v7PurAmZ yK/F1qsOl1p/Aoo8e7ext2gE2Q+0az8TOUQkMfg3cT/Ym33fPBlOkFZ+rX3yTSThtExj Rq1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=j6BV0YtQOiNrXMV5swymIknunfTEIhtzL+zfELVN7Ms=; b=OCedOv9U95ZZZRYzQvkYSkxytVhK/ILWaRzHLezjuyaiU5hzO+mhtZiHczP38+Wdqv w19X+8PC3WDkbsSKJu0OGcsRDLra/yi8hanHa9VIMmnaN4dZmTwkviWeQQlfiIsS7X3Q w/tOLsAX1EY8NGdosJXJR6ZG/bjkx3tpDPnk657xW7f5RVZmD14VJkEyjeVC9frbiZtf IeWp9XAaGlk+s002p6J2sHtOFdudVa7qY2kvp283Z8HAbEkecBBUAvPorVRwM/WBGyPf kDVHavP6H7BEGEWmAz4tCJfcSY1ZGwVyvjlOoomBYmi6rVP59qR5iSPsAaEvgFnBW+gd NhBQ== X-Gm-Message-State: AFqh2kpbH+Pr33lqA2Auymbim7vbIjfXt3Zs0PCkQ+nJxDLQUQrn8o52 MCz7faavqku6tNVtE6rkBE8+A9Gm/m5MF4BXhg== X-Google-Smtp-Source: AMrXdXufsM1UYiyJ7fOSO4EaXsXUPYSCdlhfrRAC6atQl4aixkchwbE7r5eeo2uBnFLuw4tNY0+2jTPRJ9IPEu7WMQ== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a5b:a0b:0:b0:6fb:42d2:69e4 with SMTP id k11-20020a5b0a0b000000b006fb42d269e4mr1808452ybq.436.1674260233016; Fri, 20 Jan 2023 16:17:13 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:25 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-15-ackerleytng@google.com> Subject: [RFC PATCH v3 14/31] KVM: selftests: TDX: Add TDX IO writes test From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Sagi Shahar The test verifies IO writes of various sizes from the guest to the host. Signed-off-by: Sagi Shahar Signed-off-by: Ackerley Tng --- .../selftests/kvm/include/x86_64/tdx/tdcall.h | 3 + .../selftests/kvm/x86_64/tdx_vm_tests.c | 91 +++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h b/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h index 78001bfec9c8d..b5e94b7c48fa5 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h @@ -10,6 +10,9 @@ #define TDG_VP_VMCALL_INSTRUCTION_IO_READ 0 #define TDG_VP_VMCALL_INSTRUCTION_IO_WRITE 1 +#define TDG_VP_VMCALL_SUCCESS 0x0000000000000000 +#define TDG_VP_VMCALL_INVALID_OPERAND 0x8000000000000000 + #define TDX_HCALL_HAS_OUTPUT BIT(0) #define TDX_HYPERCALL_STANDARD 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 188442a734dca..ac23d1ad1e687 100644 --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c @@ -338,6 +338,96 @@ void verify_get_td_vmcall_info(void) printf("\t ... PASSED\n"); } +#define TDX_IO_WRITES_TEST_PORT 0x51 + +/* + * Verifies IO functionality by writing values of different sizes + * to the host. + */ +void guest_io_writes(void) +{ + uint64_t byte_1 = 0xAB; + uint64_t byte_2 = 0xABCD; + uint64_t byte_4 = 0xFFABCDEF; + uint64_t ret; + + ret = tdg_vp_vmcall_instruction_io(TDX_IO_WRITES_TEST_PORT, 1, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE, + &byte_1); + if (ret) + tdx_test_fatal(ret); + + ret = tdg_vp_vmcall_instruction_io(TDX_IO_WRITES_TEST_PORT, 2, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE, + &byte_2); + if (ret) + tdx_test_fatal(ret); + + ret = tdg_vp_vmcall_instruction_io(TDX_IO_WRITES_TEST_PORT, 4, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE, + &byte_4); + if (ret) + tdx_test_fatal(ret); + + // Write an invalid number of bytes. + ret = tdg_vp_vmcall_instruction_io(TDX_IO_WRITES_TEST_PORT, 5, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE, + &byte_4); + if (ret) + tdx_test_fatal(ret); + + tdx_test_success(); +} + +void verify_guest_writes(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + + uint8_t byte_1; + uint16_t byte_2; + uint32_t byte_4; + + vm = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = td_vcpu_add(vm, 0, guest_io_writes); + td_finalize(vm); + + printf("Verifying guest writes:\n"); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_IO_WRITES_TEST_PORT, 1, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + byte_1 = *(uint8_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_IO_WRITES_TEST_PORT, 2, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + byte_2 = *(uint16_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_IO_WRITES_TEST_PORT, 4, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + byte_4 = *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + ASSERT_EQ(byte_1, 0xAB); + ASSERT_EQ(byte_2, 0xABCD); + ASSERT_EQ(byte_4, 0xFFABCDEF); + + vcpu_run(vcpu); + ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_SYSTEM_EVENT); + ASSERT_EQ(vcpu->run->system_event.data[1], TDG_VP_VMCALL_INVALID_OPERAND); + + vcpu_run(vcpu); + TDX_TEST_ASSERT_SUCCESS(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { setbuf(stdout, NULL); @@ -352,6 +442,7 @@ int main(int argc, char **argv) run_in_new_process(&verify_td_ioexit); run_in_new_process(&verify_td_cpuid); run_in_new_process(&verify_get_td_vmcall_info); + run_in_new_process(&verify_guest_writes); return 0; } From patchwork Sat Jan 21 00:15:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110740 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 24170C05027 for ; Sat, 21 Jan 2023 00:18:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230042AbjAUASW (ORCPT ); Fri, 20 Jan 2023 19:18:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53198 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230014AbjAUASF (ORCPT ); Fri, 20 Jan 2023 19:18:05 -0500 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 938CCC63B1 for ; Fri, 20 Jan 2023 16:17:40 -0800 (PST) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-4fa63c84621so64448557b3.20 for ; Fri, 20 Jan 2023 16:17:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=JbxOOqD+pwQw9GweUHv05gGISRszsuPq3GR2Y2VtJ2g=; b=tWSIGxxE0vaZiNmZxyVKpGgbuHSCV8Bs+2krR8P4CkG6Wk6ZJBEvprkyMZ46ROpBFr dtz/gVeX28QK8hr2zlBSJJX0elXAxsmTCByVEtwkV+yfBtOIuHh5lARNQWvKoF8jqvsJ QuvaGrvGtRvza/3LdTRpslfgTlpuCxCRKWgfGZRcuPQ80vZTkY3AWxaoi3aT5A2vd6kE q/624HqznaCWeXVU5MHfEJ5SMpQi0MfVWW71sLe99oNZapAMd6ftkXWUnwwqYNuOLFPZ Afi6R5epM+l3M2PIgDQHvG6hbBFDDRuYiv8a5r6EYPqNV0eN9gVrrD0eklr+dB3PLYMR 33nA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=JbxOOqD+pwQw9GweUHv05gGISRszsuPq3GR2Y2VtJ2g=; b=5A1s+pjfRSrTkzrug1WXIPBIqlvFKloLoVEZtnlTkJrORquLo6oKLVhpxBsW48lIKQ xlYbT1RfPZPfF0xwCiDPSFerID1oluvbmgwdGDBoWBTjME3k+rREyPxyk+w75dRnQtY3 ijihkgGFidbKbA+DutboneKjpIGLtlay2AjiJAD046Y86qgKl31pnDcVBK7GMbUGIRof k2cwq4sF0jTltEXSizncAA19tQ/PYZXBNZKNRnlnC3zvmF1MsyLsBbzyPoBIUHK3AvX8 J09lSrV0+7ZpeEZMnXydh9tNKLE/TxzI24+gj2mFA2nhNxTdL3bjq3JDFbMoHkM9dmKV FGmg== X-Gm-Message-State: AFqh2kpuEBH1b+/mp4H7lt279plto9M+wZ4VYz0Wz7QyRtEfME9PBrhh cyFp98ha/QuCSHN/Nvs+kN+f05lmMTgEjQnHwg== X-Google-Smtp-Source: AMrXdXteIywN3dWsGdBSd7kHWIeUZrhBm+8A+16wAnzf+wCy6Rbp8NIKiduVWk/xfFrrTDonNbk6QyimimoKOvCacw== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a25:7316:0:b0:802:5d7f:db9f with SMTP id o22-20020a257316000000b008025d7fdb9fmr292409ybc.182.1674260237241; Fri, 20 Jan 2023 16:17:17 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:26 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-16-ackerleytng@google.com> Subject: [RFC PATCH v3 15/31] KVM: selftests: TDX: Add TDX IO reads test From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Sagi Shahar The test verifies IO reads of various sizes from the host to the guest. Signed-off-by: Sagi Shahar Signed-off-by: Ackerley Tng --- .../selftests/kvm/x86_64/tdx_vm_tests.c | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) 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 ac23d1ad1e687..71aa4e5907a05 100644 --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c @@ -428,6 +428,92 @@ void verify_guest_writes(void) printf("\t ... PASSED\n"); } +#define TDX_IO_READS_TEST_PORT 0x52 + +/* + * Verifies IO functionality by reading values of different sizes + * from the host. + */ +void guest_io_reads(void) +{ + uint64_t data; + uint64_t ret; + + ret = tdg_vp_vmcall_instruction_io(TDX_IO_READS_TEST_PORT, 1, + TDG_VP_VMCALL_INSTRUCTION_IO_READ, + &data); + if (ret) + tdx_test_fatal(ret); + if (data != 0xAB) + tdx_test_fatal(1); + + ret = tdg_vp_vmcall_instruction_io(TDX_IO_READS_TEST_PORT, 2, + TDG_VP_VMCALL_INSTRUCTION_IO_READ, + &data); + if (ret) + tdx_test_fatal(ret); + if (data != 0xABCD) + tdx_test_fatal(2); + + ret = tdg_vp_vmcall_instruction_io(TDX_IO_READS_TEST_PORT, 4, + TDG_VP_VMCALL_INSTRUCTION_IO_READ, + &data); + if (ret) + tdx_test_fatal(ret); + if (data != 0xFFABCDEF) + tdx_test_fatal(4); + + // Read an invalid number of bytes. + ret = tdg_vp_vmcall_instruction_io(TDX_IO_READS_TEST_PORT, 5, + TDG_VP_VMCALL_INSTRUCTION_IO_READ, + &data); + if (ret) + tdx_test_fatal(ret); + + tdx_test_success(); +} + +void verify_guest_reads(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + + vm = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = td_vcpu_add(vm, 0, guest_io_reads); + td_finalize(vm); + + printf("Verifying guest reads:\n"); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_IO_READS_TEST_PORT, 1, + TDG_VP_VMCALL_INSTRUCTION_IO_READ); + *(uint8_t *)((void *)vcpu->run + vcpu->run->io.data_offset) = 0xAB; + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_IO_READS_TEST_PORT, 2, + TDG_VP_VMCALL_INSTRUCTION_IO_READ); + *(uint16_t *)((void *)vcpu->run + vcpu->run->io.data_offset) = 0xABCD; + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_IO_READS_TEST_PORT, 4, + TDG_VP_VMCALL_INSTRUCTION_IO_READ); + *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset) = 0xFFABCDEF; + + vcpu_run(vcpu); + ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_SYSTEM_EVENT); + ASSERT_EQ(vcpu->run->system_event.data[1], TDG_VP_VMCALL_INVALID_OPERAND); + + vcpu_run(vcpu); + TDX_TEST_ASSERT_SUCCESS(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { setbuf(stdout, NULL); @@ -443,6 +529,7 @@ int main(int argc, char **argv) run_in_new_process(&verify_td_cpuid); run_in_new_process(&verify_get_td_vmcall_info); run_in_new_process(&verify_guest_writes); + run_in_new_process(&verify_guest_reads); return 0; } From patchwork Sat Jan 21 00:15:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110741 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F2DD7C25B50 for ; Sat, 21 Jan 2023 00:18:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230133AbjAUAS3 (ORCPT ); Fri, 20 Jan 2023 19:18:29 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55030 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230136AbjAUASO (ORCPT ); Fri, 20 Jan 2023 19:18:14 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AE4E9DB7BF for ; Fri, 20 Jan 2023 16:17:45 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id z9-20020a25ba49000000b007d4416e3667so7513278ybj.23 for ; Fri, 20 Jan 2023 16:17:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=rfsY1LSMZWbkB3lzXo82d1IvFhV8JL2sADgvMPah8iE=; b=iOjwDOWBLA+75vHNu041s40M+FhZkzA3407S5hBkV79p5NSRaF7IU9DIGyOAlBbJoX z/14b1ayPGaPg6JBGlwHj9sU9hxIGQ5kxlc8GbUMUbicrfUe/hvPJKB80Pq/idC7RquH 5x3R+qd2Rp70khxwTrGlKox2h1VNHn/9ZHD4qMYkcO9fKLZjaJ/DI03P9QduZwtLZrrY 2IN4ubI9WsgtkW1fh3/5ettAd38ZWBW7uHzTWYy2ZKScSKvP+oDd4kjVEXs2DBvnbj9L 8wuLw+gIyWbQXjZ+vfluxPl9PiK6W29xbaU7Wwah+4v02L/mEcwftEmwq6puQdXuJI1p lHJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=rfsY1LSMZWbkB3lzXo82d1IvFhV8JL2sADgvMPah8iE=; b=R24B90BJhCYS3iZWlochFbCdSnGyy7HbrYXkbmRlF4eQe9Ejta6zpuFZbr2hGto6VV /mQpouNnk8AkLzOt9hmh6hk2lnz3MuRp3R3Tk1WprNpYUW2fZ68bierwo2wLnvkTMC2O zkImhWoAXilkpbIFSqVaqid3tABhqU5jPsTlVDriGk/kfURFCpo+gjNb/cucBAH3uHz8 YZT2cfD+nuYnXMKdLzGSAlSQCAXITWweM/azYWMsXZTCq1aeMMfGPEV3wZDUjonubnlp Hk+lVb5i9GqUKa5Q+802f2nF051RvH+9qfdnz4TgdJTV2Uy88D0SmRLiF90MEJct7D41 gkyw== X-Gm-Message-State: AFqh2kp/lMYlbJbCDu2iB/73BE7MFk8v8x1noSt3h09rPcI8FSlwPiAt irNRbsU7Dp1q9VoBfjrBn8AwkTQWd4nFMyiQSQ== X-Google-Smtp-Source: AMrXdXuGQ/uTHxxtm+W+laNGWc0n8lUwlm0ZAYDNMJSsXsmvJ1Xc5HBhOnuhLPLPAamVVKNduZp2XSu1xPjt2GsL5A== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a5b:58a:0:b0:7bb:3b2d:718f with SMTP id l10-20020a5b058a000000b007bb3b2d718fmr1765369ybp.302.1674260241431; Fri, 20 Jan 2023 16:17:21 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:27 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-17-ackerleytng@google.com> Subject: [RFC PATCH v3 16/31] KVM: selftests: TDX: Add TDX MSR read/write tests From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Sagi Shahar The test verifies reads and writes for MSR registers with different access level. Signed-off-by: Sagi Shahar Signed-off-by: Ackerley Tng --- Changes RFCv2 -> RFCv3 + Fixed typo in MTTR->MTRR --- .../selftests/kvm/include/x86_64/tdx/tdx.h | 4 + .../selftests/kvm/lib/x86_64/tdx/tdx.c | 27 +++ .../selftests/kvm/x86_64/tdx_vm_tests.c | 217 ++++++++++++++++++ 3 files changed, 248 insertions(+) -- 2.39.0.246.g2a6d74b583-goog 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 37ad16943e299..fbac1951cfe35 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h @@ -8,11 +8,15 @@ #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 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 7254d61515db2..43088d6f40b50 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c @@ -66,3 +66,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 71aa4e5907a05..65ca1ec2a6e82 100644 --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c @@ -514,6 +514,221 @@ void verify_guest_reads(void) printf("\t ... PASSED\n"); } +/* + * Define a filter which denies all MSR access except the following: + * MTTR_BASE_0: Allow read/write access + * MTTR_BASE_1: Allow read access + * MTTR_BASE_2: Allow write access + */ +static u64 tdx_msr_test_allow_bits = 0xFFFFFFFFFFFFFFFF; +#define MTTR_BASE_0 (0x200) +#define MTTR_BASE_1 (0x202) +#define MTTR_BASE_2 (0x204) +struct kvm_msr_filter tdx_msr_test_filter = { + .flags = KVM_MSR_FILTER_DEFAULT_DENY, + .ranges = { + { + .flags = KVM_MSR_FILTER_READ | + KVM_MSR_FILTER_WRITE, + .nmsrs = 1, + .base = MTTR_BASE_0, + .bitmap = (uint8_t *)&tdx_msr_test_allow_bits, + }, { + .flags = KVM_MSR_FILTER_READ, + .nmsrs = 1, + .base = MTTR_BASE_1, + .bitmap = (uint8_t *)&tdx_msr_test_allow_bits, + }, { + .flags = KVM_MSR_FILTER_WRITE, + .nmsrs = 1, + .base = MTTR_BASE_2, + .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(MTTR_BASE_0, &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(MTTR_BASE_1, &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 MTTR_BASE_2 is write only */ + ret = tdg_vp_vmcall_instruction_rdmsr(MTTR_BASE_2, &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 MTTR values\n"); + /* valid values for mtrr type are 0, 1, 4, 5, 6 */ + vcpu_set_msr(vcpu, MTTR_BASE_0, 4); + vcpu_set_msr(vcpu, MTTR_BASE_1, 5); + vcpu_set_msr(vcpu, MTTR_BASE_2, 6); + + printf("\t ... Running guest\n"); + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + data = tdx_test_read_64bit_report_from_guest(vcpu); + ASSERT_EQ(data, 4); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + data = tdx_test_read_64bit_report_from_guest(vcpu); + ASSERT_EQ(data, 5); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + data = tdx_test_read_64bit_report_from_guest(vcpu); + ASSERT_EQ(data, TDG_VP_VMCALL_INVALID_OPERAND); + + 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(MTTR_BASE_0, 4); + if (ret) + tdx_test_fatal(ret); + + /* We expect this call to fail since MTTR_BASE_1 is read only */ + ret = tdg_vp_vmcall_instruction_wrmsr(MTTR_BASE_1, 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(MTTR_BASE_2, 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 MTTR_BASE_1 should trigger an exit */ + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + data = tdx_test_read_64bit_report_from_guest(vcpu); + ASSERT_EQ(data, TDG_VP_VMCALL_INVALID_OPERAND); + + vcpu_run(vcpu); + TDX_TEST_ASSERT_SUCCESS(vcpu); + + printf("\t ... Verifying MTTR values writen by guest\n"); + + ASSERT_EQ(vcpu_get_msr(vcpu, MTTR_BASE_0), 4); + ASSERT_EQ(vcpu_get_msr(vcpu, MTTR_BASE_1), 0); + ASSERT_EQ(vcpu_get_msr(vcpu, MTTR_BASE_2), 6); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + + int main(int argc, char **argv) { setbuf(stdout, NULL); @@ -530,6 +745,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; } From patchwork Sat Jan 21 00:15:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110742 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E4839C25B50 for ; Sat, 21 Jan 2023 00:18:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230032AbjAUASc (ORCPT ); Fri, 20 Jan 2023 19:18:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53402 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230038AbjAUAST (ORCPT ); Fri, 20 Jan 2023 19:18:19 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A648D73ACD for ; Fri, 20 Jan 2023 16:17:52 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id k15-20020a5b0a0f000000b007eba3f8e3baso7403405ybq.4 for ; Fri, 20 Jan 2023 16:17:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=vWnv20fie/GQfacbGSS84A7f8gWQK0m5+WUyBewkaDU=; b=s/mE+Pd84jXkHm4/bsf0JUJY+Vp++e6y8PAPfYAiwDXQRJQ1LT+N4u/a1FMKW37+u/ boh/VILL9JRUzl83bGQNdfbCqD1Qvj7ynAwPya9Lq1ySN87DlcRVLqIFlqELUH0lKyNW LkmRCj2jnjIkZf9JzBU/n7ZcKrB1Ka+Q6tuAg0NHsP6anucVnK7Du+6a6iv3DWS4hCDg 7iQwjc50ACCRROa2td41eLaV5Idiw0HAtFp230LJ68yTISUJyQsJcmuKqHc3XWrWrQMz mQ5eS4mw2l7jgN7PMhMWvwN2Ea8kpEDd5ZpigUpLLz2PpbIhK8KTQvwuisc5TWbo4RSR T2KA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=vWnv20fie/GQfacbGSS84A7f8gWQK0m5+WUyBewkaDU=; b=63RbfiNCEZ9px7FS6gu/Y0uboUEhi/0xjjZ5LCYUW18lxbnWDVYgsBKX/KohF6Hq+f fQjklQZFAc1tIL44wQZc8YWoJ2jMOZrXIFlOuapIDvQWqKjihT/1cSs/Pbc7q2WLpZ2X zD4apYLaCuuIqujiSQfwlICdNnb3ncncaTPHNlmXz3p0iXoo9OpRIcYy2Dx3DKqg1z5v YuKqYutfTD1rKFhXstdPp2RLYT/E8PWBtSjPEJWntuDzf4yIPiF0MfStGaIBdqGJc4kg y48/QjKcGU/zK6ui5m9eF76EmKqTbAkBGV/6LWh/WJlycPndQkl8i+G9I8gNH7Ka98r4 PbZA== X-Gm-Message-State: AFqh2ko2Sx4SzvUFU0L0nMW6jFhl/r4TEmUH8DPk992e+sZmMxWtbvx7 oxzuI4iBK8OI1xk9lWm6sdSW5p6whTTl/KGXvw== X-Google-Smtp-Source: AMrXdXuz77o9QEUtjLGDv2jBofIrwITXkhKV5huEbQvXz8JbBqYFuHnpsehfmqc8g5e6CXejkPMtKlLjl7Y9quXa+A== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a81:c0e:0:b0:3b2:2653:d3b with SMTP id 14-20020a810c0e000000b003b226530d3bmr2091550ywm.86.1674260245563; Fri, 20 Jan 2023 16:17:25 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:28 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-18-ackerleytng@google.com> Subject: [RFC PATCH v3 17/31] KVM: selftests: TDX: Add TDX HLT exit test From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Sagi Shahar The test verifies that the guest runs TDVMCALL and the guest vCPU enters to the halted state. Signed-off-by: Erdem Aktas Signed-off-by: Sagi Shahar Signed-off-by: Ackerley Tng --- .../selftests/kvm/include/x86_64/tdx/tdx.h | 3 + .../selftests/kvm/lib/x86_64/tdx/tdx.c | 10 +++ .../selftests/kvm/x86_64/tdx_vm_tests.c | 78 +++++++++++++++++++ 3 files changed, 91 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 fbac1951cfe35..7eba9d80b3681 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h @@ -7,10 +7,12 @@ #define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 +#define TDG_VP_VMCALL_INSTRUCTION_HLT 12 #define TDG_VP_VMCALL_INSTRUCTION_IO 30 #define TDG_VP_VMCALL_INSTRUCTION_RDMSR 31 #define TDG_VP_VMCALL_INSTRUCTION_WRMSR 32 + 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); @@ -18,5 +20,6 @@ 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); +uint64_t tdg_vp_vmcall_instruction_hlt(uint64_t interrupt_blocked_flag); #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 43088d6f40b50..1af0626c2a4ad 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c @@ -93,3 +93,13 @@ uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, uint64_t value) return __tdx_hypercall(&args, 0); } + +uint64_t tdg_vp_vmcall_instruction_hlt(uint64_t interrupt_blocked_flag) +{ + struct tdx_hypercall_args args = { + .r11 = TDG_VP_VMCALL_INSTRUCTION_HLT, + .r12 = interrupt_blocked_flag, + }; + + 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 65ca1ec2a6e82..346c1e07af9c0 100644 --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c @@ -728,6 +728,83 @@ void verify_guest_msr_writes(void) printf("\t ... PASSED\n"); } +/* + * Verifies HLT functionality. + */ +void guest_hlt(void) +{ + uint64_t ret; + uint64_t interrupt_blocked_flag; + + interrupt_blocked_flag = 0; + ret = tdg_vp_vmcall_instruction_hlt(interrupt_blocked_flag); + if (ret) + tdx_test_fatal(ret); + + tdx_test_success(); +} + +void _verify_guest_hlt(int signum); + +void wake_me(int interval) +{ + struct sigaction action; + + action.sa_handler = _verify_guest_hlt; + sigemptyset(&action.sa_mask); + action.sa_flags = 0; + + TEST_ASSERT(sigaction(SIGALRM, &action, NULL) == 0, + "Could not set the alarm handler!"); + + alarm(interval); +} + +void _verify_guest_hlt(int signum) +{ + struct kvm_vm *vm; + static struct kvm_vcpu *vcpu; + + /* + * This function will also be called by SIGALRM handler to check the + * vCPU MP State. If vm has been initialized, then we are in the signal + * handler. Check the MP state and let the guest run again. + */ + if (vcpu != NULL) { + struct kvm_mp_state mp_state; + + vcpu_mp_state_get(vcpu, &mp_state); + ASSERT_EQ(mp_state.mp_state, KVM_MP_STATE_HALTED); + + /* Let the guest to run and finish the test.*/ + mp_state.mp_state = KVM_MP_STATE_RUNNABLE; + vcpu_mp_state_set(vcpu, &mp_state); + return; + } + + vm = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = td_vcpu_add(vm, 0, guest_hlt); + td_finalize(vm); + + printf("Verifying HLT:\n"); + + printf("\t ... Running guest\n"); + + /* Wait 1 second for guest to execute HLT */ + wake_me(1); + vcpu_run(vcpu); + + TDX_TEST_ASSERT_SUCCESS(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + +void verify_guest_hlt(void) +{ + _verify_guest_hlt(0); +} int main(int argc, char **argv) { @@ -747,6 +824,7 @@ int main(int argc, char **argv) run_in_new_process(&verify_guest_reads); run_in_new_process(&verify_guest_msr_writes); run_in_new_process(&verify_guest_msr_reads); + run_in_new_process(&verify_guest_hlt); return 0; } From patchwork Sat Jan 21 00:15:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110743 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7EED7C05027 for ; Sat, 21 Jan 2023 00:18:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229720AbjAUASg (ORCPT ); Fri, 20 Jan 2023 19:18:36 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55308 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230154AbjAUAS0 (ORCPT ); Fri, 20 Jan 2023 19:18:26 -0500 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E11DAC63BC for ; Fri, 20 Jan 2023 16:17:55 -0800 (PST) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-4fa63c84621so64451357b3.20 for ; Fri, 20 Jan 2023 16:17:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=WjO5rBwLb0cHzWThJNyOsO1URxlYZa7SL0LoJaae1iY=; b=DbRKdnP4x88VQmpI73F5HtgUxWbJ2hsDEBYdUyvS8NBGoTwSGWDKbPvp6spCy61JKa d8sCFnczxbj7XTIgC5qmDASbZuQUm4JaxsHKPw5mgwOTcf+5C7fOEgl8kKDjBaA5vDiL BzUxepdz3NOVVwzTyUgqjRDacw06zOUCEiAMbmYtayKjQ0EKf8XNVzpsKuRHJcd9LAcB 0lu7xGF0zPGrHg+/e0vv+lW6RaM488sqw/EJEPXs421fhv5UocYR+waxt3sO+VYZy3tH td827j6Sc07EQNlG9HbMRF7AN9NBjz6hjBomANw6zqJWyuma2V9QYMTIBwBpkZ12gUI3 a14Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=WjO5rBwLb0cHzWThJNyOsO1URxlYZa7SL0LoJaae1iY=; b=cYQ8giqIb4436xxWdJG6p1fN0gTy/hhD+W3vWshcpIWwQlSxUzlA28FrVE8B5/JmnG Xegh/TwPJOpMst4gmmpdg8PlRvvEECt/wnRoRFLToUqbQz2hsxuO/9dISyjUFUKmDjS2 UWbNz7SLiGy7Uz8xpGas4BU0gaAo+sHu0h8slu5MzS8KjWGbnewxqOB4UhxmyU/Zl8y+ XmfvT8ik9v1cr44XdENR74FflSqGEtBh/BDJfltAVcgwY7CTqoyPgBGXf7aTimjh+lx2 zMbJi46OuNWyD7o4C1LYN6Nhhv0zhQD9dZZgkItvwZbSf4PQSPNpsQoX60q2GkAOAKOW 2izA== X-Gm-Message-State: AFqh2koXe5b0Yabntg/S2yMYCv6fgKGa9ZwtrG8NdPssNhq0E4PW1fgD DevU8wSiW4BFMSSJtvnQmoEizfcakSnZHbUtUA== X-Google-Smtp-Source: AMrXdXs2Azizp8MgH3Huhhpq7IBWql1lWkjMllTIOkYSDytuaEr6jOkniKY65Y0teNdl7wi3iWIuU9V4MUkSE2rpow== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a81:648:0:b0:4ee:30ce:15e1 with SMTP id 69-20020a810648000000b004ee30ce15e1mr2152793ywg.53.1674260249914; Fri, 20 Jan 2023 16:17:29 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:29 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-19-ackerleytng@google.com> Subject: [RFC PATCH v3 18/31] KVM: selftests: TDX: Add TDX MMIO reads test From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Sagi Shahar The test verifies MMIO reads of various sizes from the host to the guest. Signed-off-by: Sagi Shahar Signed-off-by: Ackerley Tng --- .../selftests/kvm/include/x86_64/tdx/tdcall.h | 2 + .../selftests/kvm/include/x86_64/tdx/tdx.h | 3 + .../kvm/include/x86_64/tdx/test_util.h | 23 +++++ .../selftests/kvm/lib/x86_64/tdx/tdx.c | 19 ++++ .../selftests/kvm/x86_64/tdx_vm_tests.c | 87 +++++++++++++++++++ 5 files changed, 134 insertions(+) diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h b/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h index b5e94b7c48fa5..95fcdbd8404e9 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h @@ -9,6 +9,8 @@ #define TDG_VP_VMCALL_INSTRUCTION_IO_READ 0 #define TDG_VP_VMCALL_INSTRUCTION_IO_WRITE 1 +#define TDG_VP_VMCALL_VE_REQUEST_MMIO_READ 0 +#define TDG_VP_VMCALL_VE_REQUEST_MMIO_WRITE 1 #define TDG_VP_VMCALL_SUCCESS 0x0000000000000000 #define TDG_VP_VMCALL_INVALID_OPERAND 0x8000000000000000 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 7eba9d80b3681..8dd6a65485260 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h @@ -11,6 +11,7 @@ #define TDG_VP_VMCALL_INSTRUCTION_IO 30 #define TDG_VP_VMCALL_INSTRUCTION_RDMSR 31 #define TDG_VP_VMCALL_INSTRUCTION_WRMSR 32 +#define TDG_VP_VMCALL_VE_REQUEST_MMIO 48 uint64_t tdg_vp_vmcall_instruction_io(uint64_t port, uint64_t size, @@ -21,5 +22,7 @@ uint64_t tdg_vp_vmcall_get_td_vmcall_info(uint64_t *r11, uint64_t *r12, 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); uint64_t tdg_vp_vmcall_instruction_hlt(uint64_t interrupt_blocked_flag); +uint64_t tdg_vp_vmcall_ve_request_mmio_read(uint64_t address, uint64_t size, + uint64_t *data_out); #endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h b/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h index 8a9b6a1bec3eb..af412b7646049 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/test_util.h @@ -35,6 +35,29 @@ (VCPU)->run->io.direction); \ } while (0) + +/** + * Assert that some MMIO operation involving TDG.VP.VMCALL <#VERequestMMIO> was + * called in the guest. + */ +#define TDX_TEST_ASSERT_MMIO(VCPU, ADDR, SIZE, DIR) \ + do { \ + TEST_ASSERT((VCPU)->run->exit_reason == KVM_EXIT_MMIO, \ + "Got exit_reason other than KVM_EXIT_MMIO: %u (%s)\n", \ + (VCPU)->run->exit_reason, \ + exit_reason_str((VCPU)->run->exit_reason)); \ + \ + TEST_ASSERT(((VCPU)->run->exit_reason == KVM_EXIT_MMIO) && \ + ((VCPU)->run->mmio.phys_addr == (ADDR)) && \ + ((VCPU)->run->mmio.len == (SIZE)) && \ + ((VCPU)->run->mmio.is_write == (DIR)), \ + "Got an unexpected MMIO exit values: %u (%s) %llu %d %d\n", \ + (VCPU)->run->exit_reason, \ + exit_reason_str((VCPU)->run->exit_reason), \ + (VCPU)->run->mmio.phys_addr, (VCPU)->run->mmio.len, \ + (VCPU)->run->mmio.is_write); \ + } while (0) + /** * Check and report if there was some failure in the guest, either an exception * like a triple fault, or if a tdx_test_fatal() was hit. 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 1af0626c2a4ad..dcdacf08bcd60 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c @@ -103,3 +103,22 @@ uint64_t tdg_vp_vmcall_instruction_hlt(uint64_t interrupt_blocked_flag) return __tdx_hypercall(&args, 0); } + +uint64_t tdg_vp_vmcall_ve_request_mmio_read(uint64_t address, uint64_t size, + uint64_t *data_out) +{ + uint64_t ret; + struct tdx_hypercall_args args = { + .r11 = TDG_VP_VMCALL_VE_REQUEST_MMIO, + .r12 = size, + .r13 = TDG_VP_VMCALL_VE_REQUEST_MMIO_READ, + .r14 = address, + }; + + ret = __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); + + if (data_out) + *data_out = args.r11; + + return ret; +} 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 346c1e07af9c0..88f0429db0176 100644 --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c @@ -806,6 +806,92 @@ void verify_guest_hlt(void) _verify_guest_hlt(0); } +/* Pick any address that was not mapped into the guest to test MMIO */ +#define TDX_MMIO_TEST_ADDR 0x200000000 + +void guest_mmio_reads(void) +{ + uint64_t data; + uint64_t ret; + + ret = tdg_vp_vmcall_ve_request_mmio_read(TDX_MMIO_TEST_ADDR, 1, &data); + if (ret) + tdx_test_fatal(ret); + if (data != 0x12) + tdx_test_fatal(1); + + ret = tdg_vp_vmcall_ve_request_mmio_read(TDX_MMIO_TEST_ADDR, 2, &data); + if (ret) + tdx_test_fatal(ret); + if (data != 0x1234) + tdx_test_fatal(2); + + ret = tdg_vp_vmcall_ve_request_mmio_read(TDX_MMIO_TEST_ADDR, 4, &data); + if (ret) + tdx_test_fatal(ret); + if (data != 0x12345678) + tdx_test_fatal(4); + + ret = tdg_vp_vmcall_ve_request_mmio_read(TDX_MMIO_TEST_ADDR, 8, &data); + if (ret) + tdx_test_fatal(ret); + if (data != 0x1234567890ABCDEF) + tdx_test_fatal(8); + + // Read an invalid number of bytes. + ret = tdg_vp_vmcall_ve_request_mmio_read(TDX_MMIO_TEST_ADDR, 10, &data); + if (ret) + tdx_test_fatal(ret); + + tdx_test_success(); +} + +/* + * Varifies guest MMIO reads. + */ +void verify_mmio_reads(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + + vm = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = td_vcpu_add(vm, 0, guest_mmio_reads); + td_finalize(vm); + + printf("Verifying TD MMIO reads:\n"); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_MMIO(vcpu, TDX_MMIO_TEST_ADDR, 1, TDG_VP_VMCALL_VE_REQUEST_MMIO_READ); + *(uint8_t *)vcpu->run->mmio.data = 0x12; + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_MMIO(vcpu, TDX_MMIO_TEST_ADDR, 2, TDG_VP_VMCALL_VE_REQUEST_MMIO_READ); + *(uint16_t *)vcpu->run->mmio.data = 0x1234; + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_MMIO(vcpu, TDX_MMIO_TEST_ADDR, 4, TDG_VP_VMCALL_VE_REQUEST_MMIO_READ); + *(uint32_t *)vcpu->run->mmio.data = 0x12345678; + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_MMIO(vcpu, TDX_MMIO_TEST_ADDR, 8, TDG_VP_VMCALL_VE_REQUEST_MMIO_READ); + *(uint64_t *)vcpu->run->mmio.data = 0x1234567890ABCDEF; + + vcpu_run(vcpu); + ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_SYSTEM_EVENT); + ASSERT_EQ(vcpu->run->system_event.data[1], TDG_VP_VMCALL_INVALID_OPERAND); + + vcpu_run(vcpu); + TDX_TEST_ASSERT_SUCCESS(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { setbuf(stdout, NULL); @@ -825,6 +911,7 @@ int main(int argc, char **argv) run_in_new_process(&verify_guest_msr_writes); run_in_new_process(&verify_guest_msr_reads); run_in_new_process(&verify_guest_hlt); + run_in_new_process(&verify_mmio_reads); return 0; } From patchwork Sat Jan 21 00:15:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110757 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 99ED8C25B50 for ; Sat, 21 Jan 2023 00:18:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230150AbjAUASy (ORCPT ); Fri, 20 Jan 2023 19:18:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53978 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229967AbjAUASb (ORCPT ); Fri, 20 Jan 2023 19:18:31 -0500 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1310473AFD for ; Fri, 20 Jan 2023 16:18:01 -0800 (PST) Received: by mail-pl1-x64a.google.com with SMTP id u15-20020a170902a60f00b00194d7d89168so2744405plq.10 for ; Fri, 20 Jan 2023 16:18:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=WDRb3hUK3KL7DjIqYNoerTWOItA0XH5RYK6H+82j2oo=; b=XKdLbiTjQhc9QJq14SPOY4oxXeT+HysgYBLtbPoSyINx26ic5GcWQYVBXakE2mIlKz 3OrvzXQoJQ8F1SBQxDJ8tcSajMpWk1WvEXySGVZz5WMgpy9VIWczLuL5s+e2/u5Eqalp mNTWZliS4ITyJscyB4p3S0iuaQ7Wh9c2iLF2ASd2RtXUOf5/mG0b4/wF7eQtRovXL1L6 fuLxuYfQ2YAn9AlXtF14its/YFWf+KMNN4Zd3hlFp6ossx8R4A+zs23HvvI3tXLBMAAl xXSNsTdW7suXb/hQ17/sYvsVmr33WQjnbxMlkNHI4XhNAeM36E3fKtxgX9ErrxPZMtw8 Ai0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=WDRb3hUK3KL7DjIqYNoerTWOItA0XH5RYK6H+82j2oo=; b=twACkrs+e3k1byrfClG3cwQ42hSYmATXTlB3vAEENZozJEj+p7/nOm4KE6H3VwRTAB 1JO36vWQwzdwYc4cf6OiIRR0QLlpSTGc4ma/MY2w8FKDWzPway9o8UM6E5xtERJYoPj3 nrZoxdIPpjM+e8hXzNS2r9qE/c6y9JXczO1RhNMhYTFSZRLMe0pwOoVrE1ZGoW4RCkoY 4QzWVuybq8q3ohDWFXzCDUKKKbWPtr31P7zlb9s4yeYSgR0MLhpOZqCniGhBxnGCmlHj vZMu6ZrmA58/Se4q4Cpn0Z7fIMwbabUFgeTbaNWzc7MNEFvJzj3ZxCo58tZ8b/ETnQVq MdNA== X-Gm-Message-State: AFqh2kp4YcQG2rupeBOwu4blpr9lOYPSaKALOOjLorSvsWbkRbBcEuT3 kQaXdOv2zirTs2Yh28krj6wNKn1lw8B7wmV7uA== X-Google-Smtp-Source: AMrXdXt1XhMvepnOd4PkQEnRmj4etZEsfLhZH3dY0GE9wFptQNK6vFci+DDTmZgluotiO55Qn6Oa6u3+G7bcLHPvkw== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a17:902:7595:b0:193:3b70:e9a0 with SMTP id j21-20020a170902759500b001933b70e9a0mr1730374pll.6.1674260254883; Fri, 20 Jan 2023 16:17:34 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:30 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-20-ackerleytng@google.com> Subject: [RFC PATCH v3 19/31] KVM: selftests: TDX: Add TDX MMIO writes test From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Sagi Shahar The test verifies MMIO writes of various sizes from the guest to the host. Signed-off-by: Sagi Shahar Signed-off-by: Ackerley Tng --- .../selftests/kvm/include/x86_64/tdx/tdx.h | 2 + .../selftests/kvm/lib/x86_64/tdx/tdx.c | 14 +++ .../selftests/kvm/x86_64/tdx_vm_tests.c | 85 +++++++++++++++++++ 3 files changed, 101 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 8dd6a65485260..f2a90ad8a55c6 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h @@ -24,5 +24,7 @@ uint64_t tdg_vp_vmcall_instruction_wrmsr(uint64_t index, uint64_t value); uint64_t tdg_vp_vmcall_instruction_hlt(uint64_t interrupt_blocked_flag); uint64_t tdg_vp_vmcall_ve_request_mmio_read(uint64_t address, uint64_t size, uint64_t *data_out); +uint64_t tdg_vp_vmcall_ve_request_mmio_write(uint64_t address, uint64_t size, + uint64_t data_in); #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 dcdacf08bcd60..8b12ac7049572 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c @@ -122,3 +122,17 @@ uint64_t tdg_vp_vmcall_ve_request_mmio_read(uint64_t address, uint64_t size, return ret; } + +uint64_t tdg_vp_vmcall_ve_request_mmio_write(uint64_t address, uint64_t size, + uint64_t data_in) +{ + struct tdx_hypercall_args args = { + .r11 = TDG_VP_VMCALL_VE_REQUEST_MMIO, + .r12 = size, + .r13 = TDG_VP_VMCALL_VE_REQUEST_MMIO_WRITE, + .r14 = address, + .r15 = data_in, + }; + + 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 88f0429db0176..dcc0940a74e92 100644 --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c @@ -892,6 +892,90 @@ void verify_mmio_reads(void) printf("\t ... PASSED\n"); } +void guest_mmio_writes(void) +{ + uint64_t ret; + + ret = tdg_vp_vmcall_ve_request_mmio_write(TDX_MMIO_TEST_ADDR, 1, 0x12); + if (ret) + tdx_test_fatal(ret); + + ret = tdg_vp_vmcall_ve_request_mmio_write(TDX_MMIO_TEST_ADDR, 2, 0x1234); + if (ret) + tdx_test_fatal(ret); + + ret = tdg_vp_vmcall_ve_request_mmio_write(TDX_MMIO_TEST_ADDR, 4, 0x12345678); + if (ret) + tdx_test_fatal(ret); + + ret = tdg_vp_vmcall_ve_request_mmio_write(TDX_MMIO_TEST_ADDR, 8, 0x1234567890ABCDEF); + if (ret) + tdx_test_fatal(ret); + + // Write across page boundary. + ret = tdg_vp_vmcall_ve_request_mmio_write(PAGE_SIZE - 1, 8, 0); + if (ret) + tdx_test_fatal(ret); + + tdx_test_success(); +} + +/* + * Varifies guest MMIO writes. + */ +void verify_mmio_writes(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + + uint8_t byte_1; + uint16_t byte_2; + uint32_t byte_4; + uint64_t byte_8; + + vm = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = td_vcpu_add(vm, 0, guest_mmio_writes); + td_finalize(vm); + + printf("Verifying TD MMIO writes:\n"); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_MMIO(vcpu, TDX_MMIO_TEST_ADDR, 1, TDG_VP_VMCALL_VE_REQUEST_MMIO_WRITE); + byte_1 = *(uint8_t *)(vcpu->run->mmio.data); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_MMIO(vcpu, TDX_MMIO_TEST_ADDR, 2, TDG_VP_VMCALL_VE_REQUEST_MMIO_WRITE); + byte_2 = *(uint16_t *)(vcpu->run->mmio.data); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_MMIO(vcpu, TDX_MMIO_TEST_ADDR, 4, TDG_VP_VMCALL_VE_REQUEST_MMIO_WRITE); + byte_4 = *(uint32_t *)(vcpu->run->mmio.data); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_MMIO(vcpu, TDX_MMIO_TEST_ADDR, 8, TDG_VP_VMCALL_VE_REQUEST_MMIO_WRITE); + byte_8 = *(uint64_t *)(vcpu->run->mmio.data); + + ASSERT_EQ(byte_1, 0x12); + ASSERT_EQ(byte_2, 0x1234); + ASSERT_EQ(byte_4, 0x12345678); + ASSERT_EQ(byte_8, 0x1234567890ABCDEF); + + vcpu_run(vcpu); + ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_SYSTEM_EVENT); + ASSERT_EQ(vcpu->run->system_event.data[1], TDG_VP_VMCALL_INVALID_OPERAND); + + vcpu_run(vcpu); + TDX_TEST_ASSERT_SUCCESS(vcpu); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { setbuf(stdout, NULL); @@ -912,6 +996,7 @@ int main(int argc, char **argv) run_in_new_process(&verify_guest_msr_reads); run_in_new_process(&verify_guest_hlt); run_in_new_process(&verify_mmio_reads); + run_in_new_process(&verify_mmio_writes); return 0; } From patchwork Sat Jan 21 00:15:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110758 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C3161C38159 for ; Sat, 21 Jan 2023 00:18:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230175AbjAUAS5 (ORCPT ); Fri, 20 Jan 2023 19:18:57 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55514 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230160AbjAUASi (ORCPT ); Fri, 20 Jan 2023 19:18:38 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2CA8E73AE5 for ; Fri, 20 Jan 2023 16:18:04 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id k15-20020a5b0a0f000000b007eba3f8e3baso7403841ybq.4 for ; Fri, 20 Jan 2023 16:18:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=vOwGtki9KFPboHEALtokyYZ7SUKgOo9ywAkWpYTPLlY=; b=GNQli3vbWyBQzWxSUIC96W0IJYbF/Ojtzs3NaAk6EebJ69mMu9B+S0lR/AJ9VJNhM+ +P4JZw6H/PyqDMcyw3GGXZIdf/Mrzaek7lKsK5lapeiukAg4Q+GsGhb35Iveh2wG2Tqp /lI8101PQATC701yjLYNZ/0O+drh4usGew30l4ALSElGN4St029Q+bITRmxWi6h9N5C1 0c3FrL2OGNPIpjK9SEuo3Z/HOPkIMlGSs756uoHPN+TOgAfAnHFf3k7cjJv4oa+iakWO SiZJdc/Y+YwlsFlLLBMvrFt/tFkHq8Ovxm1JcaxykTQ8QxByz5py1XYnkLuq4pfN9ALw 780Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=vOwGtki9KFPboHEALtokyYZ7SUKgOo9ywAkWpYTPLlY=; b=xLq8KzNeJzKAfCu87bJPV+IzmDxUcZGCAZg1rWCT3fgqiCuCWY0/FTTCsD5iMNq6wb vpxXgYviQZxJUm8rINjZcZ2q/OxVnp6LhEQlFRFdwNDmheoEXbXNUnuFCBu2TOo3HL85 d+apbOKj+hzjD34CAV9r5TQakxEBj18HXMGNS7JNxOGDd4YkL9ZOduyh5XXBtkVEEz7n Pf+gpOf4W1GT0laEa5HRVc10R75bqX0dPhI+GKQ6EPBv3cz9hWBFqbQvJArP0ksK29Xo FcE57990PArClQfauv5gOs8CkfdoXu5m1CkQzVqT7xhuTAYac/2zABWOvRh0UbHMxEwo M5cw== X-Gm-Message-State: AFqh2kpGWu8nKTa1QKOaeNRO7khKFn3bqOWT1OE4O5d5MHP+fWAXdVpn x86uzW6hB2yoh/PsjQ9ncALTr+Xklv+zss4wFA== X-Google-Smtp-Source: AMrXdXuSW1/3B2FF32Z+SDnMOS3ZH7UUnyhC9T3Hm4i/Pcki1sMFzn9oqHPTA56gsX45+48sstycBezE8mJwl0r8/A== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a81:3985:0:b0:3ef:cbd2:224d with SMTP id g127-20020a813985000000b003efcbd2224dmr2465407ywa.459.1674260259812; Fri, 20 Jan 2023 16:17:39 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:31 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-21-ackerleytng@google.com> Subject: [RFC PATCH v3 20/31] KVM: selftests: TDX: Add TDX CPUID TDVMCALL test From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Sagi Shahar This test issues a CPUID TDVMCALL from inside the guest to get the CPUID values as seen by KVM. Signed-off-by: Sagi Shahar Signed-off-by: Ackerley Tng --- .../selftests/kvm/include/x86_64/tdx/tdx.h | 4 + .../selftests/kvm/lib/x86_64/tdx/tdx.c | 26 +++++ .../selftests/kvm/x86_64/tdx_vm_tests.c | 94 +++++++++++++++++++ 3 files changed, 124 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 f2a90ad8a55c6..e746372206a25 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h @@ -7,6 +7,7 @@ #define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 +#define TDG_VP_VMCALL_INSTRUCTION_CPUID 10 #define TDG_VP_VMCALL_INSTRUCTION_HLT 12 #define TDG_VP_VMCALL_INSTRUCTION_IO 30 #define TDG_VP_VMCALL_INSTRUCTION_RDMSR 31 @@ -26,5 +27,8 @@ uint64_t tdg_vp_vmcall_ve_request_mmio_read(uint64_t address, uint64_t size, uint64_t *data_out); uint64_t tdg_vp_vmcall_ve_request_mmio_write(uint64_t address, uint64_t size, uint64_t data_in); +uint64_t tdg_vp_vmcall_instruction_cpuid(uint32_t eax, uint32_t ecx, + uint32_t *ret_eax, uint32_t *ret_ebx, + uint32_t *ret_ecx, uint32_t *ret_edx); #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 8b12ac7049572..d9d60dd58dfdd 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c @@ -136,3 +136,29 @@ uint64_t tdg_vp_vmcall_ve_request_mmio_write(uint64_t address, uint64_t size, return __tdx_hypercall(&args, 0); } + +uint64_t tdg_vp_vmcall_instruction_cpuid(uint32_t eax, uint32_t ecx, + uint32_t *ret_eax, uint32_t *ret_ebx, + uint32_t *ret_ecx, uint32_t *ret_edx) +{ + uint64_t ret; + struct tdx_hypercall_args args = { + .r11 = TDG_VP_VMCALL_INSTRUCTION_CPUID, + .r12 = eax, + .r13 = ecx, + }; + + + ret = __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); + + if (ret_eax) + *ret_eax = args.r12; + if (ret_ebx) + *ret_ebx = args.r13; + if (ret_ecx) + *ret_ecx = args.r14; + if (ret_edx) + *ret_edx = args.r15; + + return ret; +} 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 dcc0940a74e92..b9d96b5f6521f 100644 --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c @@ -976,6 +976,99 @@ void verify_mmio_writes(void) printf("\t ... PASSED\n"); } +/* + * Verifies CPUID TDVMCALL functionality. + * The guest will then send the values to userspace using an IO write to be + * checked against the expected values. + */ +void guest_code_cpuid_tdcall(void) +{ + uint64_t err; + uint32_t eax, ebx, ecx, edx; + + // Read CPUID leaf 0x1 from host. + err = tdg_vp_vmcall_instruction_cpuid(/*eax=*/1, /*ecx=*/0, + &eax, &ebx, &ecx, &edx); + if (err) + tdx_test_fatal(err); + + err = tdx_test_report_to_user_space(eax); + if (err) + tdx_test_fatal(err); + + err = tdx_test_report_to_user_space(ebx); + if (err) + tdx_test_fatal(err); + + err = tdx_test_report_to_user_space(ecx); + if (err) + tdx_test_fatal(err); + + err = tdx_test_report_to_user_space(edx); + if (err) + tdx_test_fatal(err); + + tdx_test_success(); +} + +void verify_td_cpuid_tdcall(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + + uint32_t eax, ebx, ecx, edx; + const struct kvm_cpuid_entry2 *cpuid_entry; + + vm = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = td_vcpu_add(vm, 0, guest_code_cpuid_tdcall); + td_finalize(vm); + + printf("Verifying TD CPUID TDVMCALL:\n"); + + /* Wait for guest to report CPUID values */ + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_TEST_REPORT_PORT, 4, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + eax = *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_TEST_REPORT_PORT, 4, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + ebx = *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_TEST_REPORT_PORT, 4, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + ecx = *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_TEST_REPORT_PORT, 4, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + edx = *(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_SUCCESS(vcpu); + + /* Get KVM CPUIDs for reference */ + cpuid_entry = kvm_get_supported_cpuid_entry(1); + TEST_ASSERT(cpuid_entry, "CPUID entry missing\n"); + + ASSERT_EQ(cpuid_entry->eax, eax); + // Mask lapic ID when comparing ebx. + ASSERT_EQ(cpuid_entry->ebx & ~0xFF000000, ebx & ~0xFF000000); + ASSERT_EQ(cpuid_entry->ecx, ecx); + ASSERT_EQ(cpuid_entry->edx, edx); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { setbuf(stdout, NULL); @@ -997,6 +1090,7 @@ int main(int argc, char **argv) run_in_new_process(&verify_guest_hlt); run_in_new_process(&verify_mmio_reads); run_in_new_process(&verify_mmio_writes); + run_in_new_process(&verify_td_cpuid_tdcall); return 0; } From patchwork Sat Jan 21 00:15:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110759 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2AA1FC05027 for ; Sat, 21 Jan 2023 00:19:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230198AbjAUATJ (ORCPT ); Fri, 20 Jan 2023 19:19:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54256 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230020AbjAUASw (ORCPT ); Fri, 20 Jan 2023 19:18:52 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C62A2C79E4 for ; Fri, 20 Jan 2023 16:18:22 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id c2-20020a25a2c2000000b008016611ca77so3526938ybn.9 for ; Fri, 20 Jan 2023 16:18:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=aU8EEj4+t8QDE1+v+1nJSnMuiEYEWTVzh5HjN1v63xM=; b=CZyMH/wtFabSHYajD2rl/1mxAK8ImYuJhOe0qrxfZn1jd7qkK4ctPvfNnbYe4HpBgq +OR/+07KpRsHSpG+fM9YZr+zU8l76nuHBDYazfdCTQEfar0tsn3xWDHDds/NzG1ApMv8 VrQJ4D6HkoKG0bhi65WUS1xwmhqBbfCDLqWCQ3nM4QYElN20xvR+TIfA1tq3arTQEp0y pT27fs8Jn0SRvuAzmqtwTr2dQUbZXfNwctiUkumuD6AG94N6hbKrp+BqFJ35N67zn5L9 GEyF+ZK/QLVRN2IKVFSF2UC0fFvR+EhiH0lhTmf9VTk0LSkgWcCnE1144RjRk/eFJ15v RNMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=aU8EEj4+t8QDE1+v+1nJSnMuiEYEWTVzh5HjN1v63xM=; b=pX55UFsAAbliBIt7YenxBMarV3oEGQ6drpeFH8P0buWRLL5iNqS1kvJfZob7wYiiDL Lyhd3Y2+q/ad1Q2THL+VOULiCEKNpkBY9SVHPhQX4SgtKM5j4JK0e4tzBRLD44+PoQoo EvDte0oj93P8LosEYG7y38uV9vt4xAyJwOmhshG8jyrn1lYjT6Rhyslvs8KVZ9d2Khcq 1ngR+wHo4czON2gUKdjQLfqfZMFwrW2zprzqqTfQV2PcYORkEyYsWJCxEyC2TM38IGwE o7+IB8YJXBpqn86tGh56WSTexNS6h7PvKS778bmK3CZJnFr2Giw+mDhre1c5AehzSw60 G1ew== X-Gm-Message-State: AFqh2kpDl5MMbZQbbhHE3L7Nd/k0pF5c1fYTCoap5xW7dfstxl/fRZZt UaDeLD87CRQkIVEjhjX1OAmxMef0vZPaBLECCg== X-Google-Smtp-Source: AMrXdXtk2MSUQiuREtPrJbrkhCVDp53FqaOrQSLGcdLMLfPTeNPOYbS2c9PIzGKPwqn+QnqV+sL1ueCWG+nHRZkyrg== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a25:2c9:0:b0:803:bfff:635f with SMTP id 192-20020a2502c9000000b00803bfff635fmr246350ybc.90.1674260264239; Fri, 20 Jan 2023 16:17:44 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:32 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-22-ackerleytng@google.com> Subject: [RFC PATCH v3 21/31] KVM: selftests: TDX: Verify the behavior when host consumes a TD private memory From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Ryan Afranji The test checks that host can only read fixed values when trying to access the guest's private memory. Signed-off-by: Ryan Afranji Signed-off-by: Sagi Shahar Signed-off-by: Ackerley Tng --- .../selftests/kvm/x86_64/tdx_vm_tests.c | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) 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 b9d96b5f6521f..4c338206dbaf2 100644 --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c @@ -1069,6 +1069,90 @@ void verify_td_cpuid_tdcall(void) printf("\t ... PASSED\n"); } +/* + * Shared variables between guest and host for host reading private mem test + */ +static uint64_t tdx_test_host_read_private_mem_addr; +#define TDX_HOST_READ_PRIVATE_MEM_PORT_TEST 0x53 + +void guest_host_read_priv_mem(void) +{ + uint64_t ret; + uint64_t placeholder = 0; + + /* Set value */ + *((uint32_t *) tdx_test_host_read_private_mem_addr) = 0xABCD; + + /* Exit so host can read value */ + ret = tdg_vp_vmcall_instruction_io( + TDX_HOST_READ_PRIVATE_MEM_PORT_TEST, 4, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE, &placeholder); + if (ret) + tdx_test_fatal(ret); + + /* Update guest_var's value and have host reread it. */ + *((uint32_t *) tdx_test_host_read_private_mem_addr) = 0xFEDC; + + tdx_test_success(); +} + +void verify_host_reading_private_mem(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + + vm_vaddr_t test_page; + uint64_t *host_virt; + uint64_t first_host_read; + uint64_t second_host_read; + + vm = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = td_vcpu_add(vm, 0, guest_host_read_priv_mem); + + test_page = vm_vaddr_alloc_page(vm); + TEST_ASSERT(test_page < BIT_ULL(32), + "Test address should fit in 32 bits so it can be sent to the guest"); + + host_virt = addr_gva2hva(vm, test_page); + TEST_ASSERT(host_virt != NULL, + "Guest address not found in guest memory regions\n"); + + tdx_test_host_read_private_mem_addr = test_page; + sync_global_to_guest(vm, tdx_test_host_read_private_mem_addr); + + td_finalize(vm); + + printf("Verifying host's behavior when reading TD private memory:\n"); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_HOST_READ_PRIVATE_MEM_PORT_TEST, + 4, TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + printf("\t ... Guest's variable contains 0xABCD\n"); + + /* Host reads guest's variable. */ + first_host_read = *host_virt; + printf("\t ... Host's read attempt value: %lu\n", first_host_read); + + /* Guest updates variable and host rereads it. */ + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + printf("\t ... Guest's variable updated to 0xFEDC\n"); + + second_host_read = *host_virt; + printf("\t ... Host's second read attempt value: %lu\n", + second_host_read); + + TEST_ASSERT(first_host_read == second_host_read, + "Host did not read a fixed pattern\n"); + + printf("\t ... Fixed pattern was returned to the host\n"); + + kvm_vm_free(vm); + printf("\t ... PASSED\n"); +} + int main(int argc, char **argv) { setbuf(stdout, NULL); @@ -1091,6 +1175,7 @@ int main(int argc, char **argv) run_in_new_process(&verify_mmio_reads); run_in_new_process(&verify_mmio_writes); run_in_new_process(&verify_td_cpuid_tdcall); + run_in_new_process(&verify_host_reading_private_mem); return 0; } From patchwork Sat Jan 21 00:15:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110761 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D3FFDC05027 for ; Sat, 21 Jan 2023 00:19:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230148AbjAUATL (ORCPT ); Fri, 20 Jan 2023 19:19:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55608 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230160AbjAUAS6 (ORCPT ); Fri, 20 Jan 2023 19:18:58 -0500 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 06AE16AC83 for ; Fri, 20 Jan 2023 16:18:28 -0800 (PST) Received: by mail-pj1-x1049.google.com with SMTP id s22-20020a17090aad9600b002271d094c82so5841738pjq.7 for ; Fri, 20 Jan 2023 16:18:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=WKecfS8+aCqniCqQsmGPHH5353ve1A7On6Nm/ZOADmI=; b=YxTtusFyOuKDAaFVVkuYaK6JCrdmVg2hd8rfn7R3kpLiH7ws96PmQ8/ws5s11KIcIX zLEnTLc6KDmWTlMSrg9afGkAagNc87TrQtWMR6LCIK3Q6Wm/Olu9NvN5K9VO7izwCZTy ptHOWki55WOJBpgnNEP0HlvY0cft/52KiPRxdrqwNHiMsrdTOzxfz8mQPfRSZ+U453ki j0Ph42TE4os2wpwppD2t0oMaSH5fH0HrE0LRcvZpmmjWe1XWBGfgEJkp0qxqPA1yHBQQ 7gvefe7PCbubTZxyKDDvOfrXp6h79ox0prYOmYxB5mdXGflEg22Tva9g3TWJvd5C7aC+ 7r5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=WKecfS8+aCqniCqQsmGPHH5353ve1A7On6Nm/ZOADmI=; b=C0gBgnsChXPb2mj1Qw81sF3YPQxbtZ2QF4X5JgdTgQoH2bxNU7GRuvR7Uv58gePU1c 3TFzNxqKCIPH8maoLr/4/9jX4FHF61ZfriWA1r/Nm2iBIel0YRLTrIbS/20yA/4aN4x4 iC1O/lSdo4rA/hKB+M4LrWTuP1YuDM/eoS3KmpMUXGgdLq5xQ2VN5cdPFjONLbVKM4Bg yd5dZhbn8H8U75dlsKH7Q33Cie8g9nV1IJlopNXQ7oLtLwOluWvtbSKmGul92PJtL/6J ai5l0KrdzT79JbPxOt4PU5/oo3ac4sFbOzaA278ebtOpObG5CH6fPkzZIomb4o2wr+M5 3HPA== X-Gm-Message-State: AFqh2kqDJzgowWx/nIh5iwjZXwJOVbpoNM+OthImmbXyjwPNTWyQvqOp JuNmGSCQYImHWbCi1kmoJxrFQ9KAeQ/FXu1JkQ== X-Google-Smtp-Source: AMrXdXsL0BwUIitPOylfaYyud/HjRDUIjwS3hLjmd5OU0WR5b+zjn1m5iCaFoRoJ5nUO9HS0emXgUGIxakBYwGD6WQ== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a62:864b:0:b0:58d:be66:c31f with SMTP id x72-20020a62864b000000b0058dbe66c31fmr1941671pfd.73.1674260268576; Fri, 20 Jan 2023 16:17:48 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:33 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-23-ackerleytng@google.com> Subject: [RFC PATCH v3 22/31] KVM: selftests: TDX: Add TDG.VP.INFO test From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Roger Wang Adds a test for TDG.VP.INFO Signed-off-by: Roger Wang Signed-off-by: Sagi Shahar Signed-off-by: Ackerley Tng --- Changes RFCv2 -> RFCv3 + Use KVM_CAP_MAX_VCPUS to set max_vcpus, check that it was passed to the TDX module by reading it back --- .../selftests/kvm/include/x86_64/tdx/tdcall.h | 19 +++ .../selftests/kvm/include/x86_64/tdx/tdx.h | 6 + .../selftests/kvm/lib/x86_64/tdx/tdcall.S | 68 ++++++++ .../selftests/kvm/lib/x86_64/tdx/tdx.c | 27 ++++ .../selftests/kvm/x86_64/tdx_vm_tests.c | 148 ++++++++++++++++++ 5 files changed, 268 insertions(+) -- 2.39.0.246.g2a6d74b583-goog diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h b/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h index 95fcdbd8404e9..a65ce8f3c109b 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdcall.h @@ -37,4 +37,23 @@ struct tdx_hypercall_args { /* Used to request services from the VMM */ u64 __tdx_hypercall(struct tdx_hypercall_args *args, unsigned long flags); +/* + * Used to gather the output registers values of the TDCALL and SEAMCALL + * instructions when requesting services from the TDX module. + * + * This is a software only structure and not part of the TDX module/VMM ABI. + */ +struct tdx_module_output { + u64 rcx; + u64 rdx; + u64 r8; + u64 r9; + u64 r10; + u64 r11; +}; + +/* Used to communicate with the TDX module */ +u64 __tdx_module_call(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9, + struct tdx_module_output *out); + #endif // SELFTESTS_TDX_TDCALL_H 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 e746372206a25..ffab2c3ca312b 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h @@ -4,6 +4,8 @@ #include +#define TDG_VP_INFO 1 + #define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 @@ -31,4 +33,8 @@ uint64_t tdg_vp_vmcall_instruction_cpuid(uint32_t eax, uint32_t ecx, uint32_t *ret_eax, uint32_t *ret_ebx, uint32_t *ret_ecx, uint32_t *ret_edx); +uint64_t tdg_vp_info(uint64_t *rcx, uint64_t *rdx, + uint64_t *r8, uint64_t *r9, + uint64_t *r10, uint64_t *r11); + #endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdcall.S b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdcall.S index df9c1ed4bb2d1..601d715314434 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdcall.S +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdcall.S @@ -86,5 +86,73 @@ __tdx_hypercall: pop %rbp ret +#define TDX_MODULE_rcx 0 /* offsetof(struct tdx_module_output, rcx) */ +#define TDX_MODULE_rdx 8 /* offsetof(struct tdx_module_output, rdx) */ +#define TDX_MODULE_r8 16 /* offsetof(struct tdx_module_output, r8) */ +#define TDX_MODULE_r9 24 /* offsetof(struct tdx_module_output, r9) */ +#define TDX_MODULE_r10 32 /* offsetof(struct tdx_module_output, r10) */ +#define TDX_MODULE_r11 40 /* offsetof(struct tdx_module_output, r11) */ + +.globl __tdx_module_call +.type __tdx_module_call, @function +__tdx_module_call: + /* Set up stack frame */ + push %rbp + movq %rsp, %rbp + + /* Callee-saved, so preserve it */ + push %r12 + + /* + * Push output pointer to stack. + * After the operation, it will be fetched into R12 register. + */ + push %r9 + + /* Mangle function call ABI into TDCALL/SEAMCALL ABI: */ + /* Move Leaf ID to RAX */ + mov %rdi, %rax + /* Move input 4 to R9 */ + mov %r8, %r9 + /* Move input 3 to R8 */ + mov %rcx, %r8 + /* Move input 1 to RCX */ + mov %rsi, %rcx + /* Leave input param 2 in RDX */ + + tdcall + + /* + * Fetch output pointer from stack to R12 (It is used + * as temporary storage) + */ + pop %r12 + + /* + * Since this macro can be invoked with NULL as an output pointer, + * check if caller provided an output struct before storing output + * registers. + * + * Update output registers, even if the call failed (RAX != 0). + * Other registers may contain details of the failure. + */ + test %r12, %r12 + jz .Lno_output_struct + + /* Copy result registers to output struct: */ + movq %rcx, TDX_MODULE_rcx(%r12) + movq %rdx, TDX_MODULE_rdx(%r12) + movq %r8, TDX_MODULE_r8(%r12) + movq %r9, TDX_MODULE_r9(%r12) + movq %r10, TDX_MODULE_r10(%r12) + movq %r11, TDX_MODULE_r11(%r12) + +.Lno_output_struct: + /* Restore the state of R12 register */ + pop %r12 + + pop %rbp + ret + /* Disable executable stack */ .section .note.GNU-stack,"",%progbits 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 d9d60dd58dfdd..a280136634d3b 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c @@ -162,3 +162,30 @@ uint64_t tdg_vp_vmcall_instruction_cpuid(uint32_t eax, uint32_t ecx, return ret; } + +uint64_t tdg_vp_info(uint64_t *rcx, uint64_t *rdx, + uint64_t *r8, uint64_t *r9, + uint64_t *r10, uint64_t *r11) +{ + uint64_t ret; + struct tdx_module_output out; + + memset(&out, 0, sizeof(struct tdx_module_output)); + + ret = __tdx_module_call(TDG_VP_INFO, 0, 0, 0, 0, &out); + + if (rcx) + *rcx = out.rcx; + if (rdx) + *rdx = out.rdx; + if (r8) + *r8 = out.r8; + if (r9) + *r9 = out.r9; + if (r10) + *r10 = out.r10; + if (r11) + *r11 = out.r11; + + return ret; +} 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 4c338206dbaf2..e2dba3b5ee63e 100644 --- a/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c +++ b/tools/testing/selftests/kvm/x86_64/tdx_vm_tests.c @@ -1153,6 +1153,153 @@ void verify_host_reading_private_mem(void) printf("\t ... PASSED\n"); } +/* + * Do a TDG.VP.INFO call from the guest + */ +void guest_tdcall_vp_info(void) +{ + uint64_t err; + uint64_t rcx, rdx, r8, r9, r10, r11; + + err = tdg_vp_info(&rcx, &rdx, &r8, &r9, &r10, &r11); + if (err) + tdx_test_fatal(err); + + /* return values to user space host */ + err = tdx_test_report_64bit_to_user_space(rcx); + if (err) + tdx_test_fatal(err); + + err = tdx_test_report_64bit_to_user_space(rdx); + if (err) + tdx_test_fatal(err); + + err = tdx_test_report_64bit_to_user_space(r8); + if (err) + tdx_test_fatal(err); + + err = tdx_test_report_64bit_to_user_space(r9); + if (err) + tdx_test_fatal(err); + + err = tdx_test_report_64bit_to_user_space(r10); + if (err) + tdx_test_fatal(err); + + err = tdx_test_report_64bit_to_user_space(r11); + if (err) + tdx_test_fatal(err); + + tdx_test_success(); +} + +/* + * 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; + int ret; + + vm = td_create(); + + /* Set value for kvm->max_vcpus to be checked later */ +#define TEST_VP_INFO_MAX_VCPUS 75 + ret = kvm_check_cap(KVM_CAP_MAX_VCPUS); + TEST_ASSERT(ret, "TDX: KVM_CAP_MAX_VCPUS is not supported!"); + vm_enable_cap(vm, KVM_CAP_MAX_VCPUS, TEST_VP_INFO_MAX_VCPUS); + +#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 = kvm_get_supported_cpuid_entry(0x80000008); + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + ASSERT_EQ(rcx & 0x3F, max_pa); + /* next 63:6 bits of rcx is reserved and must be 0 */ + ASSERT_EQ(rcx >> 6, 0); + ASSERT_EQ(rdx, attributes); + ASSERT_EQ(ret_num_vcpus, num_vcpus); + ASSERT_EQ(ret_max_vcpus, TEST_VP_INFO_MAX_VCPUS); + /* VCPU_INDEX = i */ + ASSERT_EQ(r9, i); + /* verify reserved registers are 0 */ + ASSERT_EQ(r10, 0); + ASSERT_EQ(r11, 0); + + /* Wait for guest to complete execution */ + 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); @@ -1176,6 +1323,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; } From patchwork Sat Jan 21 00:15:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110762 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 951DEC25B50 for ; Sat, 21 Jan 2023 00:19:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230120AbjAUATW (ORCPT ); Fri, 20 Jan 2023 19:19:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56064 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230001AbjAUATQ (ORCPT ); Fri, 20 Jan 2023 19:19:16 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 32CF2C9256 for ; Fri, 20 Jan 2023 16:18:42 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id a14-20020a5b0ace000000b007bf99065fcbso7440130ybr.2 for ; Fri, 20 Jan 2023 16:18:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=4QuTb5nJFi65iX4g5W97FE6Ea1XkyHs5XNPvTOgo3Cc=; b=UoN7oYNcB9ZUXUj3VLUqEeWAjd8WXjLLKIujASWCpcXv/6MPWiGRy5E/XLLQHp5T7B ZIPa1MBys1QdPhnVC4ggNbBbjf4vb6C+We5ac3X0eP1xz0g2+qhzRQPJELPYbgEDixMz 0huqMRfYOYunOazIE6WAabUyUmZkKLUFO6zid/0U0mJPhgiSdEQq4EyHUbju1rDArI+H p5ymSLoP/1Cwb9fLopazeO5V6ekY6zQChnXld2Wv0n9dB/FhUHUAERBCanS2glAs37wO bY5G5xC0mDc1fcHbDMKNz1PGfVIE0EAlUm+Ch8vTOHLsdzhVOKDtxmT5ia6MwvbBQG9R OV8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=4QuTb5nJFi65iX4g5W97FE6Ea1XkyHs5XNPvTOgo3Cc=; b=LAGjtlZO6ACPNF/o9SagoPg7oQbDJqq8xnvgaY2QZ8ohPtYhKkSoXbKt2cJjZRA/Id N5HKpTc/cvk4D9ea08BJshansvLJcNUcGT+CLitr3y7Br6sJkqH0SeaKluEd+ftZ/OwY G9tfyc4/3uRVWiHT+4/JkrcqzVaoXg8yb1842KtwULHogz8APWPNlAUuPCEmZM8t9T1z PmhjtOAAaB8Hy3EU5GYGqX0Uh0bvkpuWhl0I1gDXCq7wWR8t5IZ+qiQ2OB/wrxGcBA91 mEDucuQ6Nuzj7hHg3o/gUjmfNETUslA6lWfM2Doq3HsrTikksDWzgdVvvqIdMqlXi2Us /Gog== X-Gm-Message-State: AFqh2kpo58FKVxU7ufMqlMpVOns4gwdsvia2pmLd2cNYFx200oLktr/r 99djNTWf5UWXhHgpvaS1Cng2cHj2kL20uw8+5A== X-Google-Smtp-Source: AMrXdXu0Z7p75YPFEyvZbtns+Bd9M7tYH4RDhZvbQxl9sIu16jxUrfhxXrbM/MdWbzpsvJ8jl1ncX/5TgmKDpJ7mwQ== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a0d:f446:0:b0:4fb:4e3e:e01a with SMTP id d67-20020a0df446000000b004fb4e3ee01amr832327ywf.55.1674260272954; Fri, 20 Jan 2023 16:17:52 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:34 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-24-ackerleytng@google.com> Subject: [RFC PATCH v3 23/31] KVM: selftests: Add functions to allow mapping as shared From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Signed-off-by: Ackerley Tng --- .../selftests/kvm/include/kvm_util_base.h | 24 ++++++++++++++ tools/testing/selftests/kvm/lib/kvm_util.c | 32 +++++++++++++++++++ .../selftests/kvm/lib/x86_64/processor.c | 15 +++++++-- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index cdc204cfeb4c2..30453e2de8396 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -412,6 +412,8 @@ vm_vaddr_t vm_vaddr_alloc_page(struct kvm_vm *vm); void virt_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, unsigned int npages); +void virt_map_shared(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, + unsigned int npages); void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa); void *addr_gva2hva(struct kvm_vm *vm, vm_vaddr_t gva); vm_paddr_t addr_hva2gpa(struct kvm_vm *vm, void *hva); @@ -843,6 +845,28 @@ static inline void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr virt_arch_pg_map(vm, vaddr, paddr); } +/* + * VM Virtual Page Map as Shared + * + * Input Args: + * vm - Virtual Machine + * vaddr - VM Virtual Address + * paddr - VM Physical Address + * memslot - Memory region slot for new virtual translation tables + * + * Output Args: None + * + * Return: None + * + * Within @vm, creates a virtual translation for the page starting + * at @vaddr to the page starting at @paddr. + */ +void virt_arch_pg_map_shared(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr); + +static inline void virt_pg_map_shared(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr) +{ + virt_arch_pg_map_shared(vm, vaddr, paddr); +} /* * Address Guest Virtual to Guest Physical diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 14246f0fd2e78..6673be2f49c31 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1384,6 +1384,38 @@ void virt_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, } } +/* + * Map a range of VM virtual address to the VM's physical address as shared + * + * Input Args: + * vm - Virtual Machine + * vaddr - Virtuall address to map + * paddr - VM Physical Address + * npages - The number of pages to map + * + * Output Args: None + * + * Return: None + * + * Within the VM given by @vm, creates a virtual translation for + * @npages starting at @vaddr to the page range starting at @paddr. + */ +void virt_map_shared(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, + unsigned int npages) +{ + size_t page_size = vm->page_size; + size_t size = npages * page_size; + + TEST_ASSERT(vaddr + size > vaddr, "Vaddr overflow"); + TEST_ASSERT(paddr + size > paddr, "Paddr overflow"); + + while (npages--) { + virt_pg_map_shared(vm, vaddr, paddr); + vaddr += page_size; + paddr += page_size; + } +} + /* * Address VM Physical to Host Virtual * diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c index 1ea1019d48c13..b4c18f7335dab 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c @@ -176,7 +176,8 @@ static uint64_t *virt_create_upper_pte(struct kvm_vm *vm, return pte; } -void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, int level) +static void ___virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, + int level, bool protected) { const uint64_t pg_size = PG_LEVEL_SIZE(level); uint64_t *pml4e, *pdpe, *pde; @@ -223,17 +224,27 @@ void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, int level) "PTE already present for 4k page at vaddr: 0x%lx\n", vaddr); *pte = PTE_PRESENT_MASK | PTE_WRITABLE_MASK | (paddr & PHYSICAL_PAGE_MASK); - if (vm_is_gpa_protected(vm, paddr)) + if (protected) *pte |= vm->arch.c_bit; else *pte |= vm->arch.s_bit; } +void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, int level) +{ + ___virt_pg_map(vm, vaddr, paddr, level, vm_is_gpa_protected(vm, paddr)); +} + void virt_arch_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr) { __virt_pg_map(vm, vaddr, paddr, PG_LEVEL_4K); } +void virt_arch_pg_map_shared(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr) +{ + ___virt_pg_map(vm, vaddr, paddr, PG_LEVEL_4K, false); +} + void virt_map_level(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, uint64_t nr_bytes, int level) { From patchwork Sat Jan 21 00:15:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110763 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 963CCC27C76 for ; Sat, 21 Jan 2023 00:19:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229824AbjAUATh (ORCPT ); Fri, 20 Jan 2023 19:19:37 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56198 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229789AbjAUATf (ORCPT ); Fri, 20 Jan 2023 19:19:35 -0500 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 57EFF73AFF for ; Fri, 20 Jan 2023 16:18:57 -0800 (PST) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-4ce566db73eso65721727b3.11 for ; Fri, 20 Jan 2023 16:18:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=qgs5pu4Pv7Wf9vNe8L7K5ZmvD76+tBP6dpa2LmoyCUU=; b=T4NQVLwp+ULAZcEcdAw57oxiGpFr/RONT531Im2TPN67OLpKTwUfxzgpkZZ8uunSMX dkyNSWQ/L7Tu+So5I7wbrkFzVfaW9IuwmY+yYJ7qhgKkvByN0obxXFtnIHEgPL0i2eq3 pxeBePkZ1l8I89pHNrMgnwBHqoIu/vblkDyBozkoTYEdRBBG/TCOQrvVBmYdEE8Tf9wv uYdu7UgfIp9qYPbySTgxB+/J1i2FKhYpbntfaEeg2V4tvmFHzv8sOdlAXRM6V2NcGvmv bt2gylOZJ/pfE1OfUAoscnV4B9H2qlJSiU1SlaRdBqlstu/GEr5FfLq7FB0Y9qcmlHMg e/wQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=qgs5pu4Pv7Wf9vNe8L7K5ZmvD76+tBP6dpa2LmoyCUU=; b=nfBN9dAscIkGessanRFf7kNQMmhawzUh0k4Pj2KWa0XRpyK8eas1YNgqALQWoLDBB8 kRxle/QFRiyk03U48rNErx4+g/545yDHvkHgdOXI1haXFR7DncGuwxqWS3JWpnjpXrFP xfejqTWZ7fqcZxbLgr91atzAQDwKS/6BP9pPPwyb6lTof3iZF2ZZMAWPBIS8GegRuFLI A+2Tynh2L+qbg/f+0GEfMrEbbhiFAxznVUlMawVgp7ktNdMUlLW2rgwvfr9BhnGAhALE 4JLBA/Tz/CkXhFv7c83FeSaBXZu9avo8crVj3EQ1jlsE6odmUsfr63ZGGVWcsvXKz/oZ I1Zg== X-Gm-Message-State: AFqh2krwh7sOaXXmtDmpOX+tDVsnI1TKvzteS7D29zWvOJ3dmYxyfa4Z NykeedsP8a5L62GLX9LSxWFgIj+AQJ0UZaQaQQ== X-Google-Smtp-Source: AMrXdXtBuwm+DqlckwCu71vZzLrG1Vgb32MTZndSh1dDwCy2nUyHqG8XU7x+YA1HKtT/8c5uvm3Q7OnQwe0YOQpoyw== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a0d:e786:0:b0:500:b5eb:cdd with SMTP id q128-20020a0de786000000b00500b5eb0cddmr446822ywe.95.1674260277278; Fri, 20 Jan 2023 16:17:57 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:35 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-25-ackerleytng@google.com> Subject: [RFC PATCH v3 24/31] KVM: selftests: TDX: Add shared memory test From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Ryan Afranji Adds a test that sets up shared memory between the host and guest. Signed-off-by: Ryan Afranji Signed-off-by: Sagi Shahar Signed-off-by: Ackerley Tng --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/include/x86_64/tdx/tdx.h | 2 + .../kvm/include/x86_64/tdx/tdx_util.h | 3 + .../selftests/kvm/lib/x86_64/tdx/tdx.c | 16 ++ .../selftests/kvm/lib/x86_64/tdx/tdx_util.c | 30 ++++ .../kvm/x86_64/tdx_shared_mem_test.c | 137 ++++++++++++++++++ 7 files changed, 190 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/tdx_shared_mem_test.c diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore index 370d6430b32b4..e1663b0f809b4 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -66,6 +66,7 @@ /x86_64/vmx_pmu_caps_test /x86_64/triple_fault_event_test /x86_64/tdx_vm_tests +/x86_64/tdx_shared_mem_test /access_tracking_perf_test /demand_paging_test /dirty_log_test diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 9f289322a4933..27e9148212fa5 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -152,6 +152,7 @@ TEST_GEN_PROGS_x86_64 += steal_time TEST_GEN_PROGS_x86_64 += kvm_binary_stats_test TEST_GEN_PROGS_x86_64 += system_counter_offset_test TEST_GEN_PROGS_x86_64 += x86_64/tdx_vm_tests +TEST_GEN_PROGS_x86_64 += x86_64/tdx_shared_mem_test # Compiled outputs used by test targets TEST_GEN_PROGS_EXTENDED_x86_64 += x86_64/nx_huge_pages_test 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 ffab2c3ca312b..857a297e51ac6 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h @@ -7,6 +7,7 @@ #define TDG_VP_INFO 1 #define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 +#define TDG_VP_VMCALL_MAP_GPA 0x10001 #define TDG_VP_VMCALL_REPORT_FATAL_ERROR 0x10003 #define TDG_VP_VMCALL_INSTRUCTION_CPUID 10 @@ -36,5 +37,6 @@ uint64_t tdg_vp_vmcall_instruction_cpuid(uint32_t eax, uint32_t ecx, uint64_t tdg_vp_info(uint64_t *rcx, uint64_t *rdx, uint64_t *r8, uint64_t *r9, uint64_t *r10, uint64_t *r11); +uint64_t tdg_vp_vmcall_map_gpa(uint64_t address, uint64_t size, uint64_t *data_out); #endif // SELFTEST_TDX_TDX_H diff --git a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx_util.h b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx_util.h index 274b245f200bf..58374453b4b7e 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx_util.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx_util.h @@ -13,4 +13,7 @@ void td_initialize(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type, uint64_t attributes); void td_finalize(struct kvm_vm *vm); +void handle_memory_conversion(struct kvm_vm *vm, uint64_t gpa, uint64_t size, + bool shared_to_private); + #endif // SELFTESTS_TDX_KVM_UTIL_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 a280136634d3b..e0a39f29a0662 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c @@ -189,3 +189,19 @@ uint64_t tdg_vp_info(uint64_t *rcx, uint64_t *rdx, return ret; } + +uint64_t tdg_vp_vmcall_map_gpa(uint64_t address, uint64_t size, uint64_t *data_out) +{ + uint64_t ret; + struct tdx_hypercall_args args = { + .r11 = TDG_VP_VMCALL_MAP_GPA, + .r12 = address, + .r13 = size + }; + + ret = __tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); + + if (data_out) + *data_out = args.r11; + return ret; +} diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c index 2e9679d24a843..4d6615b97770a 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c @@ -505,3 +505,33 @@ void td_finalize(struct kvm_vm *vm) tdx_td_finalizemr(vm); } + +/** + * Handle conversion of memory with @size beginning @gpa for @vm. Set + * @shared_to_private to true for shared to private conversions and false + * otherwise. + * + * Since this is just for selftests, we will just keep both pieces of backing + * memory allocated and not deallocate/allocate memory; we'll just do the + * minimum of calling KVM_MEMORY_ENCRYPT_REG_REGION and + * KVM_MEMORY_ENCRYPT_UNREG_REGION. + */ +void handle_memory_conversion(struct kvm_vm *vm, uint64_t gpa, uint64_t size, + bool shared_to_private) +{ + struct kvm_enc_region range; + char *ioctl_string = shared_to_private + ? "KVM_MEMORY_ENCRYPT_REG_REGION" + : "KVM_MEMORY_ENCRYPT_UNREG_REGION"; + + range.addr = gpa; + range.size = size; + + printf("\t ... calling %s ioctl with gpa=%#lx, size=%#lx\n", + ioctl_string, gpa, size); + + if (shared_to_private) + vm_ioctl(vm, KVM_MEMORY_ENCRYPT_REG_REGION, &range); + else + vm_ioctl(vm, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range); +} diff --git a/tools/testing/selftests/kvm/x86_64/tdx_shared_mem_test.c b/tools/testing/selftests/kvm/x86_64/tdx_shared_mem_test.c new file mode 100644 index 0000000000000..eb4cf64ae83a8 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/tdx_shared_mem_test.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include + +#include "kvm_util_base.h" +#include "processor.h" +#include "tdx/tdcall.h" +#include "tdx/tdx.h" +#include "tdx/tdx_util.h" +#include "tdx/test_util.h" +#include "test_util.h" + +#define TDX_SHARED_MEM_TEST_PRIVATE_GVA (0x80000000) +#define TDX_SHARED_MEM_TEST_VADDR_SHARED_MASK BIT_ULL(30) +#define TDX_SHARED_MEM_TEST_SHARED_GVA \ + (TDX_SHARED_MEM_TEST_PRIVATE_GVA | \ + TDX_SHARED_MEM_TEST_VADDR_SHARED_MASK) + +#define TDX_SHARED_MEM_TEST_GUEST_WRITE_VALUE (0xcafecafe) +#define TDX_SHARED_MEM_TEST_HOST_WRITE_VALUE (0xabcdabcd) + +#define TDX_SHARED_MEM_TEST_INFO_PORT 0x87 + +/* + * Shared variables between guest and host + */ +static uint64_t test_mem_private_gpa; +static uint64_t test_mem_shared_gpa; + +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); + 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 */ + /* TODO: MapGPA should exit to the host VMM, but now it doesn't */ + // vcpu_run(vcpu); + // ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_MEMORY_FAULT); + // handle_memory_conversion(vm, vcpu->run->memory.gpa, vcpu->run->memory.size, + // vcpu->run->memory.flags == KVM_MEMORY_EXIT_FLAG_PRIVATE); + + vcpu_run(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_SHARED_MEM_TEST_INFO_PORT, 4, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + ASSERT_EQ(*test_mem_hva, TDX_SHARED_MEM_TEST_GUEST_WRITE_VALUE); + + *test_mem_hva = TDX_SHARED_MEM_TEST_HOST_WRITE_VALUE; + vcpu_run(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_SHARED_MEM_TEST_INFO_PORT, 4, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + 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; +} + +int main(int argc, char **argv) +{ + if (!is_tdx_enabled()) { + printf("TDX is not supported by the KVM\n" + "Skipping the TDX tests.\n"); + return 0; + } + + return verify_shared_mem(); +} From patchwork Sat Jan 21 00:15:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110764 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E725FC38159 for ; Sat, 21 Jan 2023 00:19:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229511AbjAUATs (ORCPT ); Fri, 20 Jan 2023 19:19:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56528 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230001AbjAUATq (ORCPT ); Fri, 20 Jan 2023 19:19:46 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 23E549370A for ; Fri, 20 Jan 2023 16:19:08 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id z9-20020a25ba49000000b007d4416e3667so7514542ybj.23 for ; Fri, 20 Jan 2023 16:19:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=g5VuYA7TfsmgF2IHsazybR3ND1uceEDVTzczLitCcAI=; b=AELPrk1zBkNIV9cP+6+WXe2bVRfYoHvxNjoMs7iwc+ivh9gsI07Q+Bc/tiz/KjOul6 fDPoOU+FuoKeDVcWBv8OSHis/6i5iGmPc7YfJqjbM2IuEsKAVmO2YCXUslLxkpb5dDdg AOCiOLWNIb0NxWYVQZn4WUQwpXoAiLzKvjEGNXInDpjjzWkSasuDKjTa822uYkaHxbBG V0omf+WQMWPjk66vRiouDdId4GvlaMLGQw2CEqaurBUIl1DYGcpF9TOjjRG+uKF7mKIO LAqJ5Ie9Dz0YYsaqeX0PLyjoow/xxe4R0LzNB4BEa3C8eAaFZDOGS0Ak6U29A4+ubDOV 8JOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=g5VuYA7TfsmgF2IHsazybR3ND1uceEDVTzczLitCcAI=; b=XtfIYnZ7EhJiAVRXpG3nuvLT+RCnEBySxcSvKsl+tKhzpznnMXVbnz5ZdSZyv529D0 Up88AdnZK0ijMSvirMVQhOWyLCpABmHyw9aXj8GOOarnbBNn1P3lhwI7osOgueDdU/YT GRNN4EQS32UqmjVDp0GevMm3QmrNvLMd1ecKFOQkdOkKAgzk/WqTdUu1O1H8DWZ/AP6F 1eJZ8vd0f0ENhs9fI1ojwsKJNQEfn6g6merX6YowxXdbzE8S+s5cBJuw0BDOUV7xceCD YSZJcE6qFUL+fqZ/tjRKv61rwKfbkoLPqngFEJHbaIrsdRobCFWEA46V9uHbOiO6Wtyy ffnQ== X-Gm-Message-State: AFqh2kptVzDlwbSCV39GTJytQSSk4JVtd+AWUgCoHSXuNNhqIZPlpYv2 0+Fd3oLYIpsamgr33MqVkNSZ3Ff/8QiRqbbEtw== X-Google-Smtp-Source: AMrXdXvuSjsl6TR8kJdBnnBblDEK81ds6Q5bjRNVFbE846CCJXHQ5fcuyFgRXnB7ys47BAOCndeG1//KafcQ1cJ9ZQ== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a81:1754:0:b0:4fd:ff18:de6c with SMTP id 81-20020a811754000000b004fdff18de6cmr436255ywx.227.1674260281776; Fri, 20 Jan 2023 16:18:01 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:36 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-26-ackerleytng@google.com> Subject: [RFC PATCH v3 25/31] KVM: selftests: Add support for restricted memory From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org With this, vm_userspace_mem_region_add() can use restricted memory to back guest memory. Signed-off-by: Ackerley Tng --- .../selftests/kvm/include/kvm_util_base.h | 7 ++- .../testing/selftests/kvm/include/test_util.h | 2 + tools/testing/selftests/kvm/lib/kvm_util.c | 48 ++++++++++++++++--- tools/testing/selftests/kvm/lib/test_util.c | 7 +++ 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index 30453e2de8396..950fd337898e1 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -33,7 +33,10 @@ typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */ typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */ struct userspace_mem_region { - struct kvm_userspace_memory_region region; + union { + struct kvm_userspace_memory_region region; + struct kvm_userspace_memory_region_ext region_ext; + }; struct sparsebit *unused_phy_pages; struct sparsebit *protected_phy_pages; int fd; @@ -214,7 +217,7 @@ static inline bool kvm_has_cap(long cap) #define kvm_do_ioctl(fd, cmd, arg) \ ({ \ - static_assert(!_IOC_SIZE(cmd) || sizeof(*arg) == _IOC_SIZE(cmd), ""); \ + static_assert(!_IOC_SIZE(cmd) || sizeof(*arg) >= _IOC_SIZE(cmd), ""); \ ioctl(fd, cmd, arg); \ }) diff --git a/tools/testing/selftests/kvm/include/test_util.h b/tools/testing/selftests/kvm/include/test_util.h index befc754ce9b3b..01456a78b3a2e 100644 --- a/tools/testing/selftests/kvm/include/test_util.h +++ b/tools/testing/selftests/kvm/include/test_util.h @@ -94,6 +94,7 @@ enum vm_mem_backing_src_type { VM_MEM_SRC_ANONYMOUS_HUGETLB_1GB, VM_MEM_SRC_ANONYMOUS_HUGETLB_2GB, VM_MEM_SRC_ANONYMOUS_HUGETLB_16GB, + VM_MEM_SRC_ANONYMOUS_AND_RESTRICTED_MEMFD, VM_MEM_SRC_SHMEM, VM_MEM_SRC_SHARED_HUGETLB, NUM_SRC_TYPES, @@ -104,6 +105,7 @@ enum vm_mem_backing_src_type { struct vm_mem_backing_src_alias { const char *name; uint32_t flag; + bool need_restricted_memfd; }; #define MIN_RUN_DELAY_NS 200000UL diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 6673be2f49c31..4e5928fa71c44 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -15,7 +15,6 @@ #include #include #include -#include #define KVM_UTIL_MIN_PFN 2 @@ -799,6 +798,27 @@ void vm_set_user_memory_region(struct kvm_vm *vm, uint32_t slot, uint32_t flags, errno, strerror(errno)); } +/** + * Initialize memory in restricted_fd with size @memory_region_size and return + * the fd. + * + * Errors out if there's any error + */ +static int initialize_restricted_memfd(uint64_t memory_region_size) +{ + int ret; + int mfd = -1; + + mfd = syscall(__NR_memfd_restricted, 0); + TEST_ASSERT(mfd != -1, "Failed to create private memfd"); + ret = ftruncate(mfd, memory_region_size); + TEST_ASSERT(ret != -1, "Failed to resize memfd %d to %lx", mfd, memory_region_size); + ret = fallocate(mfd, 0, 0, memory_region_size); + TEST_ASSERT(ret != -1, "Failed to allocate %lx bytes in memfd %d", memory_region_size, mfd); + + return mfd; +} + /* * VM Userspace Memory Region Add * @@ -830,6 +850,7 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm, struct userspace_mem_region *region; size_t backing_src_pagesz = get_backing_src_pagesz(src_type); size_t alignment; + int restricted_memfd = -1; TEST_ASSERT(vm_adjust_num_guest_pages(vm->mode, npages) == npages, "Number of guest pages is not compatible with the host. " @@ -927,14 +948,24 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm, /* As needed perform madvise */ if ((src_type == VM_MEM_SRC_ANONYMOUS || - src_type == VM_MEM_SRC_ANONYMOUS_THP) && thp_configured()) { - ret = madvise(region->host_mem, npages * vm->page_size, - src_type == VM_MEM_SRC_ANONYMOUS ? MADV_NOHUGEPAGE : MADV_HUGEPAGE); + src_type == VM_MEM_SRC_ANONYMOUS_THP || + src_type == VM_MEM_SRC_ANONYMOUS_AND_RESTRICTED_MEMFD) && thp_configured()) { + int advice = src_type == VM_MEM_SRC_ANONYMOUS_THP + ? MADV_HUGEPAGE + : MADV_NOHUGEPAGE; + ret = madvise(region->host_mem, npages * vm->page_size, advice); TEST_ASSERT(ret == 0, "madvise failed, addr: %p length: 0x%lx src_type: %s", region->host_mem, npages * vm->page_size, vm_mem_backing_src_alias(src_type)->name); } + if (vm_mem_backing_src_alias(src_type)->need_restricted_memfd) { + restricted_memfd = initialize_restricted_memfd(npages * vm->page_size); + TEST_ASSERT(restricted_memfd != -1, + "Failed to create restricted memfd"); + flags |= KVM_MEM_PRIVATE; + } + region->unused_phy_pages = sparsebit_alloc(); region->protected_phy_pages = sparsebit_alloc(); sparsebit_set_num(region->unused_phy_pages, @@ -944,13 +975,16 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm, region->region.guest_phys_addr = guest_paddr; region->region.memory_size = npages * vm->page_size; region->region.userspace_addr = (uintptr_t) region->host_mem; - ret = __vm_ioctl(vm, KVM_SET_USER_MEMORY_REGION, ®ion->region); + region->region_ext.restricted_fd = restricted_memfd; + region->region_ext.restricted_offset = 0; + ret = __vm_ioctl(vm, KVM_SET_USER_MEMORY_REGION, ®ion->region_ext); TEST_ASSERT(ret == 0, "KVM_SET_USER_MEMORY_REGION IOCTL failed,\n" " rc: %i errno: %i\n" " slot: %u flags: 0x%x\n" - " guest_phys_addr: 0x%lx size: 0x%lx", + " guest_phys_addr: 0x%lx size: 0x%lx restricted_fd: %d", ret, errno, slot, flags, - guest_paddr, (uint64_t) region->region.memory_size); + guest_paddr, (uint64_t) region->region.memory_size, + restricted_memfd); /* Add to quick lookup data structures */ vm_userspace_mem_region_gpa_insert(&vm->regions.gpa_tree, region); diff --git a/tools/testing/selftests/kvm/lib/test_util.c b/tools/testing/selftests/kvm/lib/test_util.c index 6d23878bbfe1a..2d53e55d13565 100644 --- a/tools/testing/selftests/kvm/lib/test_util.c +++ b/tools/testing/selftests/kvm/lib/test_util.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -254,6 +255,11 @@ const struct vm_mem_backing_src_alias *vm_mem_backing_src_alias(uint32_t i) */ .flag = MAP_SHARED, }, + [VM_MEM_SRC_ANONYMOUS_AND_RESTRICTED_MEMFD] = { + .name = "anonymous_and_restricted_memfd", + .flag = ANON_FLAGS, + .need_restricted_memfd = true, + }, }; _Static_assert(ARRAY_SIZE(aliases) == NUM_SRC_TYPES, "Missing new backing src types?"); @@ -272,6 +278,7 @@ size_t get_backing_src_pagesz(uint32_t i) switch (i) { case VM_MEM_SRC_ANONYMOUS: case VM_MEM_SRC_SHMEM: + case VM_MEM_SRC_ANONYMOUS_AND_RESTRICTED_MEMFD: return getpagesize(); case VM_MEM_SRC_ANONYMOUS_THP: return get_trans_hugepagesz(); From patchwork Sat Jan 21 00:15:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110765 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 26A64C05027 for ; Sat, 21 Jan 2023 00:19:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230189AbjAUAT5 (ORCPT ); Fri, 20 Jan 2023 19:19:57 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56726 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230210AbjAUATy (ORCPT ); Fri, 20 Jan 2023 19:19:54 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EB5567314C for ; Fri, 20 Jan 2023 16:19:22 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id y66-20020a253245000000b007cb4f1e3e57so7418505yby.8 for ; Fri, 20 Jan 2023 16:19:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=CoXS9NR8J0lCDisdrTAQ77xqlurQK2TuY0Fdg8pUOxU=; b=E5VrJv2Hh0RmxBs1CPSwmu8xgt4qiqRciYcrXNA3andiehTlbQBzyXo+3IpgYQcFos uV4sCqmIxagqP/MnjPBDi0bAGuK0MDw0xKibN0uIeISt3SPn19Y3cYm9HWjtaq9KSG+6 Os2YgJr/XOBiIvcyGQ5QQ00hTP3uTT3ZZpoxL/UMb1wrjKZ9NrenmHZ+OXWIH9G8GEgq bLxNJVQgtdLYNyR7MrtyYZHSTpt4Is23wEhQbbtNNhI3suLr17GaEy3TFlHDk9jwtSi+ hDwvwsuG+iSlsogJYU+6ILeI+CiHuZQzrMVPV9gNi7X0emnR2Hy6GdmvLbpmMFUJz/k8 BTVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=CoXS9NR8J0lCDisdrTAQ77xqlurQK2TuY0Fdg8pUOxU=; b=hiAbaSS5+dKufjaDAOkSL6beXNxm3hBz2lnRZvgInjtfwNRpSkr7nMQK9eHaTOtofX J96ir2e5L1p4o5XlX84CTGUA7pLyeqmI8vGcApDVjRZ7RiK8NpMNpiTSff+dh+efCSf9 C8tC+YntmI0z1sNzMXD0xDK0MYxtMEEFfy5R7Z2AM3w4u63oEJFcFnrYYmwvtEYOsOFl 8wxTMeoS1E5dTDRdwbNOJIfuB8oWjG4dY3/t2c62R7MnAbEP5O5ytMv1S73tQTVtX8Yh mVRh3bE/hwbSOHagKH2YwMDeTDOgF+kWW+F8vK5YqA66NNwF19otZjBxmJHmncx4Mecx hOrQ== X-Gm-Message-State: AFqh2krv2wVJHh5D1RLtswD1dgRwWXf0AbMxfFpVjBro1zVlTJaHkwih R+YFgN20IW46RzRSpFeerUTczj6Pem7uR7GEzw== X-Google-Smtp-Source: AMrXdXurazezYjrKpa5c/030vxFCh3UjbXOe7Br4b1qlVLdlxJrd3xlTjXikwWEVFysI/oB8UEaKP5KBcn41GK/9+Q== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a81:8943:0:b0:46f:daaf:f81f with SMTP id z64-20020a818943000000b0046fdaaff81fmr2058115ywf.161.1674260285954; Fri, 20 Jan 2023 16:18:05 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:37 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-27-ackerleytng@google.com> Subject: [RFC PATCH v3 26/31] KVM: selftests: TDX: Update load_td_memory_region for VM memory backed by restricted memfd From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org If guest memory is backed by restricted memfd + UPM is being used, hence encrypted memory region has to be registered + Can avoid making a copy of guest memory before getting TDX to initialize the memory region Signed-off-by: Ackerley Tng --- .../selftests/kvm/lib/x86_64/tdx/tdx_util.c | 43 +++++++++++++++---- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c index 4d6615b97770a..77803b7a1d739 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx_util.c @@ -207,6 +207,23 @@ static void tdx_td_finalizemr(struct kvm_vm *vm) tdx_ioctl(vm->fd, KVM_TDX_FINALIZE_VM, 0, NULL); } +/* + * Other ioctls + */ + +/** + * Register a memory region that may contain encrypted data in KVM. + */ +static void register_encrypted_memory_region( + struct kvm_vm *vm, struct userspace_mem_region *region) +{ + struct kvm_enc_region range = { + .addr = region->region.guest_phys_addr, + .size = region->region.memory_size, + }; + vm_ioctl(vm, KVM_MEMORY_ENCRYPT_REG_REGION, &range); +} + /* * TD creation/setup/finalization */ @@ -393,30 +410,38 @@ static void load_td_memory_region(struct kvm_vm *vm, if (!sparsebit_any_set(pages)) return; + + if (region->region_ext.restricted_fd != -1) + register_encrypted_memory_region(vm, region); + sparsebit_for_each_set_range(pages, i, j) { const uint64_t size_to_load = (j - i + 1) * vm->page_size; const uint64_t offset = (i - lowest_page_in_region) * vm->page_size; const uint64_t hva = hva_base + offset; const uint64_t gpa = gpa_base + offset; - void *source_addr; + void *source_addr = (void *)hva; /* * KVM_TDX_INIT_MEM_REGION ioctl cannot encrypt memory in place, * hence we have to make a copy if there's only one backing * memory source */ - source_addr = mmap(NULL, size_to_load, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - TEST_ASSERT( - source_addr, - "Could not allocate memory for loading memory region"); - - memcpy(source_addr, (void *)hva, size_to_load); + if (region->region_ext.restricted_fd == -1) { + source_addr = mmap(NULL, size_to_load, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + TEST_ASSERT( + source_addr, + "Could not allocate memory for loading memory region"); + + memcpy(source_addr, (void *)hva, size_to_load); + memset((void *)hva, 0, size_to_load); + } tdx_init_mem_region(vm, source_addr, gpa, size_to_load); - munmap(source_addr, size_to_load); + if (region->region_ext.restricted_fd == -1) + munmap(source_addr, size_to_load); } } From patchwork Sat Jan 21 00:15:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110766 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C2553C38A23 for ; Sat, 21 Jan 2023 00:19:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230194AbjAUAT7 (ORCPT ); Fri, 20 Jan 2023 19:19:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56710 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229950AbjAUAT4 (ORCPT ); Fri, 20 Jan 2023 19:19:56 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3FE9973AE2 for ; Fri, 20 Jan 2023 16:19:27 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id u186-20020a2560c3000000b007c8e2cf3668so7483755ybb.14 for ; Fri, 20 Jan 2023 16:19:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=k1cq5TEY5bFZVJppj5PKXCCtP6lFgiUZJ/1ln+dN3QA=; b=d1BYzlQoyUn3i39+FvKM79uWm+WNumy+bfjZlFFt/ZeDDVwQWpIuwDbs8iEHxMAwsW KemJHYCtN/DXYLLL7eQMUQ5YoGIbIKVJyQbpifPKbv5sHtgugbasOAGzialVGpfRPQBs h4GLFakYbatPvZVmKsx9xS1aKnfRLeWB6nL2XS489S1AQ0FPgdgYIeaomBRx5A/5KSq4 5zmugkm9l1T4am+6d1w08U/IbwUDhbYYWwsov9TNA0OnGuXEi3eq6lgMQXFz9PW276mF Eb19dt3W55wzwsgepb006ykB8rV/nTqzjPvPN8ndjJB2tcFRGQs2nt8kfwwiLKEajqtm 2wZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=k1cq5TEY5bFZVJppj5PKXCCtP6lFgiUZJ/1ln+dN3QA=; b=WoNz69cuneFUPH1dJ1m6EmopindlyzFu7WUrgPGXiNnLI2iJkNAavfVYjLLQ3A8ZfH ukjcGGJcgS5T/36CJn0e5TS/P8nyBYu24o5wwL/zMW93MijUSiMSvCBAYt/rDKQcyLqA z/ADDOFiRP9CtXWoRpu6kpfQmR77j+GgINseA3EoMUY5WwP9QMQZ3MFmgKlNhPog/3M0 NjruBbBH80pRiUxZLrURt83SSeCgjDuxZf+KXunnxjlT/u9WdM/33wu3M3FxlL2/imdx JMDbf5l6fyVumc53GD57RW3c4c/LsjsFn4zjGvNn6X2XxqmCUW11/Uj75EhygXvM2B0h BXlw== X-Gm-Message-State: AFqh2kolm3G9ck18886Sf2btXXVCRj1W7Ehsaghv83tHpoLJiuBO1CMr LxvLjl7QMxMARESWHcyTYKjbxCLnWN411SXOIg== X-Google-Smtp-Source: AMrXdXsKPQ7RdQsZJh0HCn7FotF1wMUoexsS6TfkTsPP/Sd5BeAcVkKJWPwo+TQ+YiggVLrbHck2EozyECapRFWA7A== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a81:f908:0:b0:4fa:fa3a:72e with SMTP id x8-20020a81f908000000b004fafa3a072emr858885ywm.231.1674260290351; Fri, 20 Jan 2023 16:18:10 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:38 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-28-ackerleytng@google.com> Subject: [RFC PATCH v3 27/31] KVM: selftests: Expose _vm_vaddr_alloc From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org vm_vaddr_alloc always allocates memory in memslot 0. This allows users of this function to choose which memslot to allocate virtual memory in. Signed-off-by: Ackerley Tng --- tools/testing/selftests/kvm/include/kvm_util_base.h | 3 +++ tools/testing/selftests/kvm/lib/kvm_util.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index 950fd337898e1..abeffa5a47e88 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -406,6 +406,9 @@ void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags); void vm_mem_region_move(struct kvm_vm *vm, uint32_t slot, uint64_t new_gpa); void vm_mem_region_delete(struct kvm_vm *vm, uint32_t slot); struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id); +vm_vaddr_t +_vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, + vm_paddr_t paddr_min, uint32_t data_memslot, bool encrypt); vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min); vm_vaddr_t vm_vaddr_alloc_shared(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min); vm_vaddr_t vm_vaddr_alloc_1to1(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 4e5928fa71c44..2f1e592d29dfd 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1286,7 +1286,7 @@ static vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm *vm, size_t sz, * a unique set of pages, with the minimum real allocation being at least * a page. */ -static vm_vaddr_t +vm_vaddr_t _vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, vm_paddr_t paddr_min, uint32_t data_memslot, bool encrypt) { From patchwork Sat Jan 21 00:15:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110767 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AA3ACC27C76 for ; Sat, 21 Jan 2023 00:20:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230219AbjAUAUT (ORCPT ); Fri, 20 Jan 2023 19:20:19 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57152 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230240AbjAUAUN (ORCPT ); Fri, 20 Jan 2023 19:20:13 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 79F4973AF9 for ; Fri, 20 Jan 2023 16:19:48 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id a14-20020a5b0ace000000b007bf99065fcbso7440820ybr.2 for ; Fri, 20 Jan 2023 16:19:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=OSbqzQIHhtOUZi+XNLRvr0hBcTc63rTSHvkLvHdhRjs=; b=j+nuqFxlj28fkfuax2AYTnMDYPRfm95o2qjUDWXSKBksDH8jYemCh9w0e7ftn6QOsw vpC45E1/+deGYoDby3+FGoPiHS/LxF8nPJlBFrNMv7dO3xcEw9B5XVWgl0O5VgU3jgOn erfriF1fdySfCtOnV7cj/oaFKAgRrxKVOEzhHDO25dAOE3ttKTo9UtZOYVLCEg0QEyXW wA+NvIShIINGq/JGFEvnFz+GRzfD3HO9/HUL0rGzM1JR3hW/+R0Skr5OAs3FZLV6eI/I +q4fhfZYPwBOyIYJbBA4rPW7OYqyLr9hI0S+wNSVgcM3BAOP0WApHvrLpY4CzghElk6I t/1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=OSbqzQIHhtOUZi+XNLRvr0hBcTc63rTSHvkLvHdhRjs=; b=zwizrMDDXWppOcPH5v/iYAhZDGa9/xmknruWYv4Y8BAILJLeVsRVOHVfAe8N9aXN8B haA6CyOYo1/jogh/uUzAfnZ9sk1Uitu79jjtWcyPi/IoGf44RRBarXL6PQPC51ecdZnb XKJNWxFY0j3KvStRL4o++epQDPhc4F+cGUJpbZ6t48/mhWIpGawcUit8qmfPeAaF/IWX mc4pjoc3W4fO6mVCPn8eHXpV/GFfQW+Lh4LFARwRyxkX/0qJMAVc9og2hmppDK4+oLg8 wj/6vjBERgZLL/fFoGUt9t0JCTDyh4jxvOH6ciVfi+TRTVrqJNswUAqsFOU5WZz+Zklx 5XUw== X-Gm-Message-State: AFqh2kqNyucRazQwxwDeVMx9CNHlW8494gitEgeTb1IDdNcBIT+FsxA5 GhModR11uq6hAvaMx0UXLWFoaAZu5wNi4G4DRg== X-Google-Smtp-Source: AMrXdXu1DCnVzLJkLaux9FqMEFGGeDFnVXCqWlSa4HMsaQ9DZUE7PtkSZ+oUJjuui87VSyvC9iSnO+Q32CJrzh9ORQ== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a0d:eb93:0:b0:4fb:2084:1f62 with SMTP id u141-20020a0deb93000000b004fb20841f62mr956118ywe.513.1674260294752; Fri, 20 Jan 2023 16:18:14 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:39 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-29-ackerleytng@google.com> Subject: [RFC PATCH v3 28/31] KVM: selftests: TDX: Add support for TDG.MEM.PAGE.ACCEPT From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Signed-off-by: Ackerley Tng --- tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h | 2 ++ tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c | 5 +++++ 2 files changed, 7 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 857a297e51ac6..c8e4b9ce795ea 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h @@ -5,6 +5,7 @@ #include #define TDG_VP_INFO 1 +#define TDG_MEM_PAGE_ACCEPT 6 #define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 #define TDG_VP_VMCALL_MAP_GPA 0x10001 @@ -38,5 +39,6 @@ uint64_t tdg_vp_info(uint64_t *rcx, uint64_t *rdx, uint64_t *r8, uint64_t *r9, uint64_t *r10, uint64_t *r11); uint64_t tdg_vp_vmcall_map_gpa(uint64_t address, uint64_t size, uint64_t *data_out); +uint64_t tdg_mem_page_accept(uint64_t gpa, uint8_t level); #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 e0a39f29a0662..2ebc47e268779 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c @@ -205,3 +205,8 @@ uint64_t tdg_vp_vmcall_map_gpa(uint64_t address, uint64_t size, uint64_t *data_o *data_out = args.r11; return ret; } + +uint64_t tdg_mem_page_accept(uint64_t gpa, uint8_t level) +{ + return __tdx_module_call(TDG_MEM_PAGE_ACCEPT, gpa | level, 0, 0, 0, NULL); +} From patchwork Sat Jan 21 00:15:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110768 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0E709C25B50 for ; Sat, 21 Jan 2023 00:20:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230247AbjAUAUV (ORCPT ); Fri, 20 Jan 2023 19:20:21 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57206 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230223AbjAUAUQ (ORCPT ); Fri, 20 Jan 2023 19:20:16 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7C69073AF4 for ; Fri, 20 Jan 2023 16:19:52 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id n8-20020a258d08000000b007facaf67acfso7480310ybl.0 for ; Fri, 20 Jan 2023 16:19:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=AoLQ6HYLr8hLhvXe0so57mY+HUAjh6mBgI+e1/IQeng=; b=QDv9eBq1lt7YIEJZzgzCx+7X/eRNoD6R+YX07ysF2YQEyCGPjLbpF2Zk/+B6V0JmYp iOhVBV4999QsqCJ2dtSGxhRkxLnJJBBreJTZVdsAnpE+VZ17j7iDfuvsh03Lkp8iyJeA aARFOPNZjnB2E4meZsGWwu0ob3tJGhfB1jLd8eR9wfUu7xEapJC2W4LTPxaw/u7sO29Q cHWamv2K+Q9MUkeGpSmm/v/SRdJyZpZx2Vfpzpsqe6Oy4umv0qn3QDdMZjYnRVczl7PS dBzSBedrLPL6zYX5K6SpUnot+4hCMshgzariewcc9LqId9QonvzYc1b8RuZfzfk5sdif PtLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=AoLQ6HYLr8hLhvXe0so57mY+HUAjh6mBgI+e1/IQeng=; b=zFeZLnnaiqKSLHXzFZ1bhtKjaP02daMZdvcgkL/5JWl5LRiNOvAJrCCOTmiDqF/icy wBBHW6aSCYPdUchNUBI3cQzRlHTjrPotwz6sn0tUXW3XUglcAKfnvT0+3He4rogy39Zj z/yK1IL2/b885L+/9YOd0WzZW6dBaBfOWt7jgIAKfGjPtsxOo8DFut0iw1QmvkrfcIrZ D2nF2VQNjRPKY+wXfZcLoo3F00AN9SDZrXAIOiuita8YUYeru5x7CkLKvH5pguuL/azP RpN8/JzcvIC8JpPUZcZixODPBc80lutxGDUyCKVEWhmF5AF/nym8h3tkmCdjpY05isJs V8Kg== X-Gm-Message-State: AFqh2kreRB0ZtO77tnK6rjpfvobfYqtEXFzTEYItEDRwKMv4ni5kuXCI 1kxoCgYgWPygSNh6TPyI4iOIukfOqGDwsN7Rqg== X-Google-Smtp-Source: AMrXdXuI5KPIV+1bAjgQ7xtMLOmJeYkGw4nxJcYtu8wp10aKsTdw8pXY00wl8grNtb1i7r3jEL1o+T0AVWCvuDgM2w== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a25:bdce:0:b0:801:88a9:d5f with SMTP id g14-20020a25bdce000000b0080188a90d5fmr446952ybk.71.1674260299258; Fri, 20 Jan 2023 16:18:19 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:40 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-30-ackerleytng@google.com> Subject: [RFC PATCH v3 29/31] KVM: selftests: TDX: Add support for TDG.VP.VEINFO.GET From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Signed-off-by: Ackerley Tng --- .../selftests/kvm/include/x86_64/tdx/tdx.h | 21 +++++++++++++++++++ .../selftests/kvm/lib/x86_64/tdx/tdx.c | 19 +++++++++++++++++ 2 files changed, 40 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 c8e4b9ce795ea..2dfb9432c32f9 100644 --- a/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h +++ b/tools/testing/selftests/kvm/include/x86_64/tdx/tdx.h @@ -5,6 +5,7 @@ #include #define TDG_VP_INFO 1 +#define TDG_VP_VEINFO_GET 3 #define TDG_MEM_PAGE_ACCEPT 6 #define TDG_VP_VMCALL_GET_TD_VM_CALL_INFO 0x10000 @@ -41,4 +42,24 @@ uint64_t tdg_vp_info(uint64_t *rcx, uint64_t *rdx, uint64_t tdg_vp_vmcall_map_gpa(uint64_t address, uint64_t size, uint64_t *data_out); uint64_t tdg_mem_page_accept(uint64_t gpa, uint8_t level); +/* + * Used by the #VE exception handler to gather the #VE exception + * info from the TDX module. This is a software only structure + * and not part of the TDX module/VMM ABI. + * + * Adapted from arch/x86/include/asm/tdx.h + */ +struct ve_info { + uint64_t exit_reason; + uint64_t exit_qual; + /* Guest Linear (virtual) Address */ + uint64_t gla; + /* Guest Physical Address */ + uint64_t gpa; + uint32_t instr_len; + uint32_t instr_info; +}; + +uint64_t tdg_vp_veinfo_get(struct ve_info *ve); + #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 2ebc47e268779..11a19832758bb 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c +++ b/tools/testing/selftests/kvm/lib/x86_64/tdx/tdx.c @@ -210,3 +210,22 @@ uint64_t tdg_mem_page_accept(uint64_t gpa, uint8_t level) { return __tdx_module_call(TDG_MEM_PAGE_ACCEPT, gpa | level, 0, 0, 0, NULL); } + +uint64_t tdg_vp_veinfo_get(struct ve_info *ve) +{ + uint64_t ret; + struct tdx_module_output out; + + memset(&out, 0, sizeof(struct tdx_module_output)); + + ret = __tdx_module_call(TDG_VP_VEINFO_GET, 0, 0, 0, 0, &out); + + ve->exit_reason = out.rcx; + ve->exit_qual = out.rdx; + ve->gla = out.r8; + ve->gpa = out.r9; + ve->instr_len = out.r10 & 0xffffffff; + ve->instr_info = out.r10 >> 32; + + return ret; +} From patchwork Sat Jan 21 00:15:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110760 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 81DF2C25B50 for ; Sat, 21 Jan 2023 00:19:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230167AbjAUATK (ORCPT ); Fri, 20 Jan 2023 19:19:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54894 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230130AbjAUASy (ORCPT ); Fri, 20 Jan 2023 19:18:54 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1AA367314C for ; Fri, 20 Jan 2023 16:18:24 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id d21-20020a25add5000000b007ff8112e8b8so5535606ybe.17 for ; Fri, 20 Jan 2023 16:18:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Vk93+I6OSUVBwh4z5UqKhx2Qsqvlb7tzifbo6JQZrLA=; b=QSt/BGsIAVFgQS4TFoM+/Ns9P7myw95OR2fCkvn8AnXU5Qn4Ec/4VwQyL46QnjhOpx 88xKxceOjjsJUusCS3YtMySzB+tHJO3V4nvhLzHoYYcYMGba+zt/ST72NKlaIuTPft17 nho8JSX6MFo66QDC73OS16hJr7JbB9zkYHsu28VDDXJufKHFFU8DgHUWIB/vFjLD93sV xlDcmT9S1VTMxx9kXIGS6etIBjwfqRUz9f4kVnBpyrELjgcC9H5hsFiX/jAY/o6WEojr DjoIc2ny8sRKK56QsbR6DiN6oVOO7BJN5ZksftSU+pvwlQtqCT6Ggw7XbM+dUWiJdtcC DitQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Vk93+I6OSUVBwh4z5UqKhx2Qsqvlb7tzifbo6JQZrLA=; b=6jcWNu5Fa0ShtK2QDYDYzi9xiMYQXEYAAC1uf8gC3EHFS8hHMdMYahW8k6Q+Ii9qbp U9qvqKGvittFKgQheWAbhLEhd3WgiPHGvi+6oTGo+1irL01xQzY/4ZcuH8AlDwjnAN7l gSQiG0x9AH7B+YFzgwL1sIiooFNzq7gdXpECtCrES/NtA0Wa7NTZryWfPo+9sb4k/1TZ FcCquJxDl2UXqshg+YXGLAxxRua0sNu4gHrXaj0BLqn5oNQ7fxgh7wTgg3mfRgms4yAO LP3dzKSj3cLwtA614Ca8SLvsbxLNwGBuuJJhRqLHBHo1Q9wwRuhzF13zGtElXg+R/crA hIOg== X-Gm-Message-State: AFqh2krJIF0zyuhFJ5tPBKyVcRM4dodC00mhbz2v8Db54EqDzIoYsFT+ gFUP25GeIsa7LV3wYPpY4tYUpTyGhDnJ3UD4TQ== X-Google-Smtp-Source: AMrXdXvbhFjIbngJm8ErEeG/qhphnIdjZioJjL96XNDZforpLrNZ6apT1jSjI/H9OjskWAY5+lRmFIaj8cab5havgw== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a05:6902:11cd:b0:7d3:55e0:1cc6 with SMTP id n13-20020a05690211cd00b007d355e01cc6mr1843208ybu.435.1674260303753; Fri, 20 Jan 2023 16:18:23 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:41 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-31-ackerleytng@google.com> Subject: [RFC PATCH v3 30/31] KVM: selftests: TDX: Add TDX UPM selftest From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This tests the use of restricted memory with explicit MapGPA calls. Signed-off-by: Ackerley Tng --- tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/x86_64/tdx_upm_test.c | 392 ++++++++++++++++++ 3 files changed, 394 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/tdx_upm_test.c diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore index e1663b0f809b4..c1def2271f4cd 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -67,6 +67,7 @@ /x86_64/triple_fault_event_test /x86_64/tdx_vm_tests /x86_64/tdx_shared_mem_test +/x86_64/tdx_upm_test /access_tracking_perf_test /demand_paging_test /dirty_log_test diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 27e9148212fa5..2b1434368a0f2 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -153,6 +153,7 @@ TEST_GEN_PROGS_x86_64 += kvm_binary_stats_test TEST_GEN_PROGS_x86_64 += system_counter_offset_test TEST_GEN_PROGS_x86_64 += x86_64/tdx_vm_tests TEST_GEN_PROGS_x86_64 += x86_64/tdx_shared_mem_test +TEST_GEN_PROGS_x86_64 += x86_64/tdx_upm_test # Compiled outputs used by test targets TEST_GEN_PROGS_EXTENDED_x86_64 += x86_64/nx_huge_pages_test diff --git a/tools/testing/selftests/kvm/x86_64/tdx_upm_test.c b/tools/testing/selftests/kvm/x86_64/tdx_upm_test.c new file mode 100644 index 0000000000000..13914aebd7da7 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/tdx_upm_test.c @@ -0,0 +1,392 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include + +#include "kvm_util_base.h" +#include "processor.h" +#include "tdx/tdcall.h" +#include "tdx/tdx.h" +#include "tdx/tdx_util.h" +#include "tdx/test_util.h" +#include "test_util.h" + +/* TDX UPM test patterns */ +#define PATTERN_CONFIDENCE_CHECK (0x11) +#define PATTERN_HOST_FOCUS (0x22) +#define PATTERN_GUEST_GENERAL (0x33) +#define PATTERN_GUEST_FOCUS (0x44) + +/* + * 0x80000000 is arbitrarily selected. The selected address need not be the same + * as TDX_UPM_TEST_AREA_GVA_PRIVATE, but it should not overlap with selftest + * code or boot page. + */ +#define TDX_UPM_TEST_AREA_GPA (0x80000000) +/* Test area GPA is arbitrarily selected */ +#define TDX_UPM_TEST_AREA_GVA_PRIVATE (0x90000000) +/* Select any bit that can be used as a flag */ +#define TDX_UPM_TEST_AREA_GVA_SHARED_BIT (32) +/* + * TDX_UPM_TEST_AREA_GVA_SHARED is used to map the same GPA twice into the + * guest, once as shared and once as private + */ +#define TDX_UPM_TEST_AREA_GVA_SHARED \ + (TDX_UPM_TEST_AREA_GVA_PRIVATE | \ + BIT_ULL(TDX_UPM_TEST_AREA_GVA_SHARED_BIT)) + +/* The test area is 2MB in size */ +#define TDX_UPM_TEST_AREA_SIZE (2 << 20) +/* 0th general area is 1MB in size */ +#define TDX_UPM_GENERAL_AREA_0_SIZE (1 << 20) +/* Focus area is 40KB in size */ +#define TDX_UPM_FOCUS_AREA_SIZE (40 << 10) +/* 1st general area is the rest of the space in the test area */ +#define TDX_UPM_GENERAL_AREA_1_SIZE \ + (TDX_UPM_TEST_AREA_SIZE - TDX_UPM_GENERAL_AREA_0_SIZE - \ + TDX_UPM_FOCUS_AREA_SIZE) + +/* + * The test memory area is set up as two general areas, sandwiching a focus + * area. The general areas act as control areas. After they are filled, they + * are not expected to change throughout the tests. The focus area is memory + * permissions change from private to shared and vice-versa. + * + * The focus area is intentionally small, and sandwiched to test that when the + * focus area's permissions change, the other areas' permissions are not + * affected. + */ +struct __packed tdx_upm_test_area { + uint8_t general_area_0[TDX_UPM_GENERAL_AREA_0_SIZE]; + uint8_t focus_area[TDX_UPM_FOCUS_AREA_SIZE]; + uint8_t general_area_1[TDX_UPM_GENERAL_AREA_1_SIZE]; +}; + +static void fill_test_area(struct tdx_upm_test_area *test_area_base, + uint8_t pattern) +{ + memset(test_area_base, pattern, sizeof(*test_area_base)); +} + +static void fill_focus_area(struct tdx_upm_test_area *test_area_base, + uint8_t pattern) +{ + memset(test_area_base->focus_area, pattern, + sizeof(test_area_base->focus_area)); +} + +static bool check_area(uint8_t *base, uint64_t size, uint8_t expected_pattern) +{ + size_t i; + + for (i = 0; i < size; i++) { + if (base[i] != expected_pattern) + return false; + } + + return true; +} + +static bool check_general_areas(struct tdx_upm_test_area *test_area_base, + uint8_t expected_pattern) +{ + return (check_area(test_area_base->general_area_0, + sizeof(test_area_base->general_area_0), + expected_pattern) && + check_area(test_area_base->general_area_1, + sizeof(test_area_base->general_area_1), + expected_pattern)); +} + +static bool check_focus_area(struct tdx_upm_test_area *test_area_base, + uint8_t expected_pattern) +{ + return check_area(test_area_base->focus_area, + sizeof(test_area_base->focus_area), expected_pattern); +} + +static bool check_test_area(struct tdx_upm_test_area *test_area_base, + uint8_t expected_pattern) +{ + return (check_general_areas(test_area_base, expected_pattern) && + check_focus_area(test_area_base, expected_pattern)); +} + +static bool fill_and_check(struct tdx_upm_test_area *test_area_base, uint8_t pattern) +{ + fill_test_area(test_area_base, pattern); + + return check_test_area(test_area_base, pattern); +} + +#define TDX_UPM_TEST_ASSERT(x) \ + do { \ + if (!(x)) \ + tdx_test_fatal(__LINE__); \ + } while (0) + +/* + * Shared variables between guest and host + */ +static struct tdx_upm_test_area *test_area_gpa_private; +static struct tdx_upm_test_area *test_area_gpa_shared; + +/* + * Test stages for syncing with host + */ +enum { + SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST = 1, + SYNC_CHECK_READ_SHARED_MEMORY_FROM_HOST, + SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST_AGAIN, +}; + +#define TDX_UPM_TEST_ACCEPT_PRINT_PORT 0x87 + +/** + * Does vcpu_run, and also manages memory conversions if requested by the TD. + */ +void vcpu_run_and_manage_memory_conversions(struct kvm_vm *vm, + struct kvm_vcpu *vcpu) +{ + for (;;) { + vcpu_run(vcpu); + if ( + vcpu->run->exit_reason == KVM_EXIT_IO && + vcpu->run->io.port == TDX_UPM_TEST_ACCEPT_PRINT_PORT) { + uint64_t gpa = tdx_test_read_64bit( + vcpu, TDX_UPM_TEST_ACCEPT_PRINT_PORT); + printf("\t ... guest accepting 1 page at GPA: 0x%lx\n", gpa); + continue; + } + + break; + } +} + +static void guest_upm_explicit(void) +{ + uint64_t ret = 0; + uint64_t failed_gpa; + + struct tdx_upm_test_area *test_area_gva_private = + (struct tdx_upm_test_area *)TDX_UPM_TEST_AREA_GVA_PRIVATE; + struct tdx_upm_test_area *test_area_gva_shared = + (struct tdx_upm_test_area *)TDX_UPM_TEST_AREA_GVA_SHARED; + + /* Check: host reading private memory does not modify guest's view */ + fill_test_area(test_area_gva_private, PATTERN_GUEST_GENERAL); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST); + + TDX_UPM_TEST_ASSERT( + check_test_area(test_area_gva_private, PATTERN_GUEST_GENERAL)); + + /* Remap focus area as shared */ + ret = tdg_vp_vmcall_map_gpa((uint64_t)test_area_gpa_shared->focus_area, + sizeof(test_area_gpa_shared->focus_area), + &failed_gpa); + TDX_UPM_TEST_ASSERT(!ret); + + /* General areas should be unaffected by remapping */ + TDX_UPM_TEST_ASSERT( + check_general_areas(test_area_gva_private, PATTERN_GUEST_GENERAL)); + + /* + * Use memory contents to confirm that the memory allocated using mmap + * is used as backing memory for shared memory - PATTERN_CONFIDENCE_CHECK + * was written by the VMM at the beginning of this test. + */ + TDX_UPM_TEST_ASSERT( + check_focus_area(test_area_gva_shared, PATTERN_CONFIDENCE_CHECK)); + + /* Guest can use focus area after remapping as shared */ + fill_focus_area(test_area_gva_shared, PATTERN_GUEST_FOCUS); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_SHARED_MEMORY_FROM_HOST); + + /* Check that guest has the same view of shared memory */ + TDX_UPM_TEST_ASSERT( + check_focus_area(test_area_gva_shared, PATTERN_HOST_FOCUS)); + + /* Remap focus area back to private */ + ret = tdg_vp_vmcall_map_gpa((uint64_t)test_area_gpa_private->focus_area, + sizeof(test_area_gpa_private->focus_area), + &failed_gpa); + TDX_UPM_TEST_ASSERT(!ret); + + /* General areas should be unaffected by remapping */ + TDX_UPM_TEST_ASSERT( + check_general_areas(test_area_gva_private, PATTERN_GUEST_GENERAL)); + + /* Focus area should be zeroed after remapping */ + TDX_UPM_TEST_ASSERT(check_focus_area(test_area_gva_private, 0)); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST_AGAIN); + + /* Check that guest can use private memory after focus area is remapped as private */ + TDX_UPM_TEST_ASSERT( + fill_and_check(test_area_gva_private, PATTERN_GUEST_GENERAL)); + + tdx_test_success(); +} + +static void run_selftest(struct kvm_vm *vm, struct kvm_vcpu *vcpu, + struct tdx_upm_test_area *test_area_base_hva) +{ + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_TEST_REPORT_PORT, TDX_TEST_REPORT_SIZE, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + ASSERT_EQ(*(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset), + SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST); + + /* + * Check that host should read PATTERN_CONFIDENCE_CHECK from guest's + * private memory. This confirms that regular memory (userspace_addr in + * struct kvm_userspace_memory_region) is used to back the host's view + * of private memory, since PATTERN_CONFIDENCE_CHECK was written to that + * memory before starting the guest. + */ + TEST_ASSERT(check_test_area(test_area_base_hva, PATTERN_CONFIDENCE_CHECK), + "Host should read PATTERN_CONFIDENCE_CHECK from guest's private memory."); + + vcpu_run_and_manage_memory_conversions(vm, vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_TEST_REPORT_PORT, TDX_TEST_REPORT_SIZE, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + ASSERT_EQ(*(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset), + SYNC_CHECK_READ_SHARED_MEMORY_FROM_HOST); + + TEST_ASSERT(check_focus_area(test_area_base_hva, PATTERN_GUEST_FOCUS), + "Host should have the same view of shared memory as guest."); + TEST_ASSERT(check_general_areas(test_area_base_hva, PATTERN_CONFIDENCE_CHECK), + "Host's view of private memory should still be backed by regular memory."); + + /* Check that host can use shared memory */ + fill_focus_area(test_area_base_hva, PATTERN_HOST_FOCUS); + TEST_ASSERT(check_focus_area(test_area_base_hva, PATTERN_HOST_FOCUS), + "Host should be able to use shared memory."); + + vcpu_run_and_manage_memory_conversions(vm, vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_IO(vcpu, TDX_TEST_REPORT_PORT, TDX_TEST_REPORT_SIZE, + TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); + ASSERT_EQ(*(uint32_t *)((void *)vcpu->run + vcpu->run->io.data_offset), + SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST_AGAIN); + + TEST_ASSERT(check_general_areas(test_area_base_hva, PATTERN_CONFIDENCE_CHECK), + "Host's view of private memory should be backed by regular memory."); + TEST_ASSERT(check_focus_area(test_area_base_hva, PATTERN_HOST_FOCUS), + "Host's view of private memory should be backed by regular memory."); + + vcpu_run(vcpu); + TDX_TEST_CHECK_GUEST_FAILURE(vcpu); + TDX_TEST_ASSERT_SUCCESS(vcpu); + + printf("\t ... PASSED\n"); +} + +static bool address_between(uint64_t addr, void *lo, void *hi) +{ + return (uint64_t)lo <= addr && addr < (uint64_t)hi; +} + +static void guest_ve_handler(struct ex_regs *regs) +{ + uint64_t ret; + struct ve_info ve; + + ret = tdg_vp_veinfo_get(&ve); + TDX_UPM_TEST_ASSERT(!ret); + + /* For this test, we will only handle EXIT_REASON_EPT_VIOLATION */ + TDX_UPM_TEST_ASSERT(ve.exit_reason == EXIT_REASON_EPT_VIOLATION); + + /* Validate GPA in fault */ + TDX_UPM_TEST_ASSERT( + address_between(ve.gpa, + test_area_gpa_private->focus_area, + test_area_gpa_private->general_area_1)); + + tdx_test_send_64bit(TDX_UPM_TEST_ACCEPT_PRINT_PORT, ve.gpa); + +#define MEM_PAGE_ACCEPT_LEVEL_4K 0 +#define MEM_PAGE_ACCEPT_LEVEL_2M 1 + ret = tdg_mem_page_accept(ve.gpa, MEM_PAGE_ACCEPT_LEVEL_4K); + TDX_UPM_TEST_ASSERT(!ret); +} + +static void verify_upm_test(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + + vm_vaddr_t test_area_gva_private; + struct tdx_upm_test_area *test_area_base_hva; + uint64_t test_area_npages; + + vm = td_create(); + td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); + vcpu = td_vcpu_add(vm, 0, guest_upm_explicit); + + vm_install_exception_handler(vm, VE_VECTOR, guest_ve_handler); + + /* + * 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_area_npages = TDX_UPM_TEST_AREA_SIZE / vm->page_size; + vm_userspace_mem_region_add(vm, + VM_MEM_SRC_ANONYMOUS_AND_RESTRICTED_MEMFD, + TDX_UPM_TEST_AREA_GPA, 3, test_area_npages, + 0); + + test_area_gva_private = _vm_vaddr_alloc( + vm, TDX_UPM_TEST_AREA_SIZE, TDX_UPM_TEST_AREA_GVA_PRIVATE, + TDX_UPM_TEST_AREA_GPA, 3, true); + ASSERT_EQ(test_area_gva_private, TDX_UPM_TEST_AREA_GVA_PRIVATE); + + test_area_gpa_private = (struct tdx_upm_test_area *) + addr_gva2gpa(vm, test_area_gva_private); + virt_map_shared(vm, TDX_UPM_TEST_AREA_GVA_SHARED, + (uint64_t)test_area_gpa_private, + test_area_npages); + ASSERT_EQ(addr_gva2gpa(vm, TDX_UPM_TEST_AREA_GVA_SHARED), + (vm_paddr_t)test_area_gpa_private); + + test_area_base_hva = addr_gva2hva(vm, TDX_UPM_TEST_AREA_GVA_PRIVATE); + + TEST_ASSERT(fill_and_check(test_area_base_hva, PATTERN_CONFIDENCE_CHECK), + "Failed to mark memory intended as backing memory for TD shared memory"); + + sync_global_to_guest(vm, test_area_gpa_private); + test_area_gpa_shared = (struct tdx_upm_test_area *) + ((uint64_t)test_area_gpa_private | BIT_ULL(vm->pa_bits - 1)); + sync_global_to_guest(vm, test_area_gpa_shared); + + td_finalize(vm); + + printf("Verifying UPM functionality: explicit MapGPA\n"); + + run_selftest(vm, vcpu, test_area_base_hva); + + kvm_vm_free(vm); +} + +int main(int argc, char **argv) +{ + /* Disable stdout buffering */ + setbuf(stdout, NULL); + + if (!is_tdx_enabled()) { + printf("TDX is not supported by the KVM\n" + "Skipping the TDX tests.\n"); + return 0; + } + + run_in_new_process(&verify_upm_test); +} From patchwork Sat Jan 21 00:15:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ackerley Tng X-Patchwork-Id: 13110784 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A94BAC27C76 for ; Sat, 21 Jan 2023 00:27:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229788AbjAUA1x (ORCPT ); Fri, 20 Jan 2023 19:27:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39358 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229766AbjAUA1w (ORCPT ); Fri, 20 Jan 2023 19:27:52 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 748958B31D for ; Fri, 20 Jan 2023 16:27:19 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id r8-20020a252b08000000b007b989d5e105so7477574ybr.11 for ; Fri, 20 Jan 2023 16:27:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=7DCwT0vOmg1kvE5C/ZmiO0Q3IunPA+bJBAyC1WliYPU=; b=UKfUq51zNuwJ1s8RoAy4DKxdjfKNX60WlC3mQo2LPz454muDFSLBiSU6Lg104sdJ3h 1D2D4ZWi3MlujhpVjBeBYy/DVsxaYDDG/xY+ZTE6SUwCV/W5nixFHUH47KzNY5O5nMUd +V6OnoU5yuGHvDak/bGBvLf4EfNcXGq08rHgjcTSGe3laadp8N3fU+rNhnJeBAx2V2wG 0s9W8l12xEGM1MZTkc4KzrpQeVEM2/HVoThePaCNd5+yBm2BAHcuk3v31tMnCgAr0uzB x9w2hDFjNf1T0v4gBms5OXgjSUtaIvdZvNnZkKfqiru7e8/AXLVj/kDoihEnAvAM/ErV nRLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=7DCwT0vOmg1kvE5C/ZmiO0Q3IunPA+bJBAyC1WliYPU=; b=u4ox0ccTInauO2OGU3vVCFD7NC5VKvJ/tRbHBwmGGfVhP00F6QomJ1WKQgdX5NFHqx MMa57TLdj1lAfH2EZBj2ukE+meqHnY7Cu/zzepd3RLs21gRVis6Q728xGONyhUvANmQQ 2oUWID5OtaxVv5dB8FeUZQ2fD8XyKZztmzeUQgPA7ULC68W/oWkyA8xJ6WaOAo0T75uy pRHNS3fWZ8PWvgcOAb9TYvb+v/TsofL3A++4hcQt8KTlCPAoX9oW1loPr5jU5ZFZBdB3 NXEmPcHDbYTwbocdG3lZPP3Lv7649VN3kRhrk4CSIIa0HSWCmqia2bxX4KXK4kF/Ofk4 8V+w== X-Gm-Message-State: AFqh2krinqYbi8g9qLU6Itx/nMB8wkIrfuoNXsS9pA5sxCiClGLd0v3i PwVb6D9QWuLaQQN8loiGRA138YEURX5R1VaiyA== X-Google-Smtp-Source: AMrXdXuLbmhgtGWdFAgKnD+yNqKI8Xaq12OTyFBCP0UJI16En+uZ/3BxfhP5lOEKrFWt/DwBqtrpjBp5AD2mFLoVxA== X-Received: from ackerleytng-cloudtop-sg.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:b30]) (user=ackerleytng job=sendgmr) by 2002:a25:8d03:0:b0:7a0:7cd5:602d with SMTP id n3-20020a258d03000000b007a07cd5602dmr2002572ybl.426.1674260308219; Fri, 20 Jan 2023 16:18:28 -0800 (PST) Date: Sat, 21 Jan 2023 00:15:42 +0000 In-Reply-To: <20230121001542.2472357-1-ackerleytng@google.com> Mime-Version: 1.0 References: <20230121001542.2472357-1-ackerleytng@google.com> X-Mailer: git-send-email 2.39.0.246.g2a6d74b583-goog Message-ID: <20230121001542.2472357-32-ackerleytng@google.com> Subject: [RFC PATCH v3 31/31] KVM: selftests: TDX: Add TDX UPM selftests for implicit conversion From: Ackerley Tng To: linux-kselftest@vger.kernel.org Cc: pbonzini@redhat.com, seanjc@google.com, isaku.yamahata@intel.com, sagis@google.com, erdemaktas@google.com, afranji@google.com, runanwang@google.com, shuah@kernel.org, drjones@redhat.com, maz@kernel.org, bgardon@google.com, jmattson@google.com, dmatlack@google.com, peterx@redhat.com, oupton@google.com, ricarkol@google.com, yang.zhong@intel.com, wei.w.wang@intel.com, xiaoyao.li@intel.com, pgonda@google.com, marcorr@google.com, eesposit@redhat.com, borntraeger@de.ibm.com, eric.auger@redhat.com, wangyanan55@huawei.com, aaronlewis@google.com, vkuznets@redhat.com, pshier@google.com, axelrasmussen@google.com, zhenzhong.duan@intel.com, maciej.szmigiero@oracle.com, like.xu@linux.intel.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Ackerley Tng Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This tests the use of restricted memory without explicit MapGPA calls. Signed-off-by: Ackerley Tng --- .../selftests/kvm/x86_64/tdx_upm_test.c | 88 ++++++++++++++++--- 1 file changed, 78 insertions(+), 10 deletions(-) diff --git a/tools/testing/selftests/kvm/x86_64/tdx_upm_test.c b/tools/testing/selftests/kvm/x86_64/tdx_upm_test.c index 13914aebd7da7..56ba3d4fb15a5 100644 --- a/tools/testing/selftests/kvm/x86_64/tdx_upm_test.c +++ b/tools/testing/selftests/kvm/x86_64/tdx_upm_test.c @@ -149,11 +149,18 @@ enum { * Does vcpu_run, and also manages memory conversions if requested by the TD. */ void vcpu_run_and_manage_memory_conversions(struct kvm_vm *vm, - struct kvm_vcpu *vcpu) + struct kvm_vcpu *vcpu, bool handle_conversions) { for (;;) { vcpu_run(vcpu); - if ( + if (handle_conversions && + vcpu->run->exit_reason == KVM_EXIT_MEMORY_FAULT) { + handle_memory_conversion( + vm, vcpu->run->memory.gpa, + vcpu->run->memory.size, + vcpu->run->memory.flags == KVM_MEMORY_EXIT_FLAG_PRIVATE); + continue; + } else if ( vcpu->run->exit_reason == KVM_EXIT_IO && vcpu->run->io.port == TDX_UPM_TEST_ACCEPT_PRINT_PORT) { uint64_t gpa = tdx_test_read_64bit( @@ -233,8 +240,53 @@ static void guest_upm_explicit(void) tdx_test_success(); } +static void guest_upm_implicit(void) +{ + struct tdx_upm_test_area *test_area_gva_private = + (struct tdx_upm_test_area *)TDX_UPM_TEST_AREA_GVA_PRIVATE; + struct tdx_upm_test_area *test_area_gva_shared = + (struct tdx_upm_test_area *)TDX_UPM_TEST_AREA_GVA_SHARED; + + /* Check: host reading private memory does not modify guest's view */ + fill_test_area(test_area_gva_private, PATTERN_GUEST_GENERAL); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST); + + TDX_UPM_TEST_ASSERT( + check_test_area(test_area_gva_private, PATTERN_GUEST_GENERAL)); + + /* Use focus area as shared */ + fill_focus_area(test_area_gva_shared, PATTERN_GUEST_FOCUS); + + /* General areas should not be affected */ + TDX_UPM_TEST_ASSERT( + check_general_areas(test_area_gva_private, PATTERN_GUEST_GENERAL)); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_SHARED_MEMORY_FROM_HOST); + + /* Check that guest has the same view of shared memory */ + TDX_UPM_TEST_ASSERT( + check_focus_area(test_area_gva_shared, PATTERN_HOST_FOCUS)); + + /* Use focus area as private */ + fill_focus_area(test_area_gva_private, PATTERN_GUEST_FOCUS); + + /* General areas should be unaffected by remapping */ + TDX_UPM_TEST_ASSERT( + check_general_areas(test_area_gva_private, PATTERN_GUEST_GENERAL)); + + tdx_test_report_to_user_space(SYNC_CHECK_READ_PRIVATE_MEMORY_FROM_HOST_AGAIN); + + /* Check that guest can use private memory after focus area is remapped as private */ + TDX_UPM_TEST_ASSERT( + fill_and_check(test_area_gva_private, PATTERN_GUEST_GENERAL)); + + tdx_test_success(); +} + static void run_selftest(struct kvm_vm *vm, struct kvm_vcpu *vcpu, - struct tdx_upm_test_area *test_area_base_hva) + struct tdx_upm_test_area *test_area_base_hva, + bool implicit) { vcpu_run(vcpu); TDX_TEST_CHECK_GUEST_FAILURE(vcpu); @@ -253,7 +305,7 @@ static void run_selftest(struct kvm_vm *vm, struct kvm_vcpu *vcpu, TEST_ASSERT(check_test_area(test_area_base_hva, PATTERN_CONFIDENCE_CHECK), "Host should read PATTERN_CONFIDENCE_CHECK from guest's private memory."); - vcpu_run_and_manage_memory_conversions(vm, vcpu); + vcpu_run_and_manage_memory_conversions(vm, vcpu, implicit); TDX_TEST_CHECK_GUEST_FAILURE(vcpu); TDX_TEST_ASSERT_IO(vcpu, TDX_TEST_REPORT_PORT, TDX_TEST_REPORT_SIZE, TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); @@ -270,7 +322,7 @@ static void run_selftest(struct kvm_vm *vm, struct kvm_vcpu *vcpu, TEST_ASSERT(check_focus_area(test_area_base_hva, PATTERN_HOST_FOCUS), "Host should be able to use shared memory."); - vcpu_run_and_manage_memory_conversions(vm, vcpu); + vcpu_run_and_manage_memory_conversions(vm, vcpu, implicit); TDX_TEST_CHECK_GUEST_FAILURE(vcpu); TDX_TEST_ASSERT_IO(vcpu, TDX_TEST_REPORT_PORT, TDX_TEST_REPORT_SIZE, TDG_VP_VMCALL_INSTRUCTION_IO_WRITE); @@ -319,18 +371,20 @@ static void guest_ve_handler(struct ex_regs *regs) TDX_UPM_TEST_ASSERT(!ret); } -static void verify_upm_test(void) +static void verify_upm_test(bool implicit) { struct kvm_vm *vm; struct kvm_vcpu *vcpu; + void *guest_code; vm_vaddr_t test_area_gva_private; struct tdx_upm_test_area *test_area_base_hva; uint64_t test_area_npages; vm = td_create(); td_initialize(vm, VM_MEM_SRC_ANONYMOUS, 0); - vcpu = td_vcpu_add(vm, 0, guest_upm_explicit); + guest_code = implicit ? guest_upm_implicit : guest_upm_explicit; + vcpu = td_vcpu_add(vm, 0, guest_code); vm_install_exception_handler(vm, VE_VECTOR, guest_ve_handler); @@ -370,13 +424,26 @@ static void verify_upm_test(void) td_finalize(vm); - printf("Verifying UPM functionality: explicit MapGPA\n"); + if (implicit) + printf("Verifying UPM functionality: implicit conversion\n"); + else + printf("Verifying UPM functionality: explicit MapGPA\n"); - run_selftest(vm, vcpu, test_area_base_hva); + run_selftest(vm, vcpu, test_area_base_hva, implicit); kvm_vm_free(vm); } +void verify_upm_test_explicit(void) +{ + verify_upm_test(false); +} + +void verify_upm_test_implicit(void) +{ + verify_upm_test(true); +} + int main(int argc, char **argv) { /* Disable stdout buffering */ @@ -388,5 +455,6 @@ int main(int argc, char **argv) return 0; } - run_in_new_process(&verify_upm_test); + run_in_new_process(&verify_upm_test_explicit); + run_in_new_process(&verify_upm_test_implicit); }