Received: by 2002:a05:6359:c8b:b0:c7:702f:21d4 with SMTP id go11csp3442987rwb; Fri, 30 Sep 2022 03:47:23 -0700 (PDT) X-Google-Smtp-Source: AMsMyM61aOIfXKVtnbtC9ZNzneWCozqHmliewkLDodNzxC+xXVFbiaG6hSaU4yPAX++g0vfk7QXZ X-Received: by 2002:a05:6402:3c8:b0:454:44b3:2e2a with SMTP id t8-20020a05640203c800b0045444b32e2amr7248438edw.283.1664534843430; Fri, 30 Sep 2022 03:47:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1664534843; cv=none; d=google.com; s=arc-20160816; b=Ym1Sn/l1x2SI7pZr60lrQqYYqNgh5W2KpyQBojPpmAKc0Ftb51szomZJ56gy4+M0wW hjim5KU6/wGAjojp0l6BkBh4/WYXOIxe4ntvQ3sMm+yVfHpICyZmBfNJpiX1s9XIHrxk Xz/rHswS/D65HgBESPADiQCh/4ts0r/PC7ofij7Gq9YAVz6udVkvfaVlnKBaSn2jqxu8 YmQLEPmJYwLnKLcpCjmg4YETuuMqpBgnYoHz5bX+6eGZ8CrAozuv/mUekPmaHqEwwSwn 1cmzJrpZ/ETyy/VydJhjFh+jjtFEpkt9OA8nhW02eXYzL/AeGlEJ3MGuO9cxWxcHkh4f YTpA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=5L4tITnvObBv47DW7oZ/bXh0izdELzZqFaQjLEmyVQw=; b=d2h7Rbuy/YoDDNwP3h+xzlIumZ5Ye1339LF+q/SUnDgVNZMF2ytPBzzcbgDdFMGgFZ i07JZGx7ltfJ6fDXxjsVuUzO/vqCfPAI8MxHxrTUpnxYqNMtSCKsKJ4Y1Z0FL53Th6cq CGlsuYQkonEJyywSIgekWwvyxoYJi+sDmAjWCAkn0dqRjxnJKF9q16QxlpeGLiqmVx2S lwKea9r1h1nEIgCm1H6OJiJAfCYXfmVe0ydVOKRRT9vvi2lxHXpxSeSu1Lo/63cbnGfA WEZjEO694ELOONWrw+V7Euwrn2SsqCUWelGv3wmx12WHIQrYpZEemiOI6hK66q58WvyF qUaA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=bC+992OB; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id x69-20020a50bacb000000b00450c4d9a097si1633333ede.54.2022.09.30.03.46.51; Fri, 30 Sep 2022 03:47:23 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=bC+992OB; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232238AbiI3K0Y (ORCPT + 99 others); Fri, 30 Sep 2022 06:26:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33796 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231964AbiI3KVM (ORCPT ); Fri, 30 Sep 2022 06:21:12 -0400 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 497D515AB52; Fri, 30 Sep 2022 03:19:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1664533161; x=1696069161; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=/Veqw9EW8tUuQFbI7sS3UqOsMHilx9sG0zWvby86DKg=; b=bC+992OB2UZhTwqLpcwc+k4kcH/sJGOFHxAEm+YJU4ZUPXJljVA7TY/b 68u5NB2+NtG0UcfmhC73ZPUHnLsQTg4D7KolsCaaMwBD7uj2zIIkxRiaa xd1AKQAUsoPKXaew1rXhiIcdOBmMBbUFJUz86VW63wxpaIqKf0LiF5a5f kJR9rnChyXHNFu7P7sFdYFpD1TIjirjYPrihmBLna7UrO4cJ+GSlZ6uuF zodDIauSSG/qQ2Vz/S0QeXZxFdOqLa0s1iSX0ilIHlZiclpVmVTLHULPB 2afLoIl/7SAkol08w3++34EBKCBNB+ExHj6PH+boGxebZiTHBVnhtnWGb A==; X-IronPort-AV: E=McAfee;i="6500,9779,10485"; a="281870123" X-IronPort-AV: E=Sophos;i="5.93,358,1654585200"; d="scan'208";a="281870123" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Sep 2022 03:19:01 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10485"; a="726807696" X-IronPort-AV: E=Sophos;i="5.93,358,1654585200"; d="scan'208";a="726807696" Received: from ls.sc.intel.com (HELO localhost) ([143.183.96.54]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Sep 2022 03:19:01 -0700 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org, linux-kernel@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , erdemaktas@google.com, Sean Christopherson , Sagi Shahar Subject: [PATCH v9 059/105] KVM: x86/tdp_mmu: implement MapGPA hypercall for TDX Date: Fri, 30 Sep 2022 03:17:53 -0700 Message-Id: <79cfc130e36a7754977af7460dc752188073d103.1664530908.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-4.5 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, SPF_HELO_PASS,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Isaku Yamahata The TDX Guest-Hypervisor communication interface(GHCI) specification defines MapGPA hypercall for guest TD to request the host VMM to map given GPA range as private or shared. It means the guest TD uses the GPA as shared (or private). The GPA won't be used as private (or shared). VMM should enforce GPA usage. VMM doesn't have to map the GPA on the hypercall request. - Zap the aliased region. If shared (or private) GPA is requested, zap private (or shared) GPA (modulo shared bit). - Record the request GPA is shared (or private) by kvm.mem_attr_array. - Don't map GPA. The GPA is mapped on the next EPT violation. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/mmu.h | 5 ++++ arch/x86/kvm/mmu/mmu.c | 60 ++++++++++++++++++++++++++++++++++++++ arch/x86/kvm/mmu/tdp_mmu.c | 35 ++++++++++++++++++++++ arch/x86/kvm/mmu/tdp_mmu.h | 3 ++ 4 files changed, 103 insertions(+) diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 3cd969bf5b69..d67ca298983c 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -217,6 +217,11 @@ static inline u8 permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu); +int __kvm_mmu_map_gpa(struct kvm *kvm, gfn_t *startp, gfn_t end, + bool map_private); +int kvm_mmu_map_gpa(struct kvm_vcpu *vcpu, gfn_t *startp, gfn_t end, + bool map_private); + int kvm_mmu_post_init_vm(struct kvm *kvm); void kvm_mmu_pre_destroy_vm(struct kvm *kvm); diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index d463bc13c094..9a4acf2ad694 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -6743,6 +6743,66 @@ void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm, u64 gen) } } +int __kvm_mmu_map_gpa(struct kvm *kvm, gfn_t *startp, gfn_t end, + bool map_private) +{ + gfn_t start = *startp; + int attr; + int ret; + + if (!kvm_gfn_shared_mask(kvm)) + return -EOPNOTSUPP; + + attr = map_private ? KVM_MEM_ATTR_PRIVATE : KVM_MEM_ATTR_SHARED; + start = start & ~kvm_gfn_shared_mask(kvm); + end = end & ~kvm_gfn_shared_mask(kvm); + + /* + * To make the following kvm_vm_set_mem_attr() success within spinlock + * without memory allocation. + */ + ret = kvm_vm_reserve_mem_attr(kvm, start, end); + if (ret) + return ret; + + write_lock(&kvm->mmu_lock); + if (is_tdp_mmu_enabled(kvm)) { + gfn_t s = start; + + ret = kvm_tdp_mmu_map_gpa(kvm, &s, end, map_private); + if (!ret) { + KVM_BUG_ON(kvm_vm_set_mem_attr(kvm, attr, start, end), kvm); + } else if (ret == -EAGAIN) { + KVM_BUG_ON(kvm_vm_set_mem_attr(kvm, attr, start, s), kvm); + start = s; + } + } else { + ret = -EOPNOTSUPP; + } + write_unlock(&kvm->mmu_lock); + + if (ret == -EAGAIN) { + if (map_private) + *startp = kvm_gfn_private(kvm, start); + else + *startp = kvm_gfn_shared(kvm, start); + } + return ret; +} +EXPORT_SYMBOL_GPL(__kvm_mmu_map_gpa); + +int kvm_mmu_map_gpa(struct kvm_vcpu *vcpu, gfn_t *startp, gfn_t end, + bool map_private) +{ + struct kvm_mmu *mmu = vcpu->arch.mmu; + + if (!VALID_PAGE(mmu->root.hpa) || !VALID_PAGE(mmu->private_root_hpa)) + return -EINVAL; + + return __kvm_mmu_map_gpa(vcpu->kvm, startp, end, map_private); +} +EXPORT_SYMBOL_GPL(kvm_mmu_map_gpa); + static unsigned long mmu_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) { diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c index 784dcfaed505..7078c75d7103 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -2111,6 +2111,41 @@ bool kvm_tdp_mmu_write_protect_gfn(struct kvm *kvm, return spte_set; } +int kvm_tdp_mmu_map_gpa(struct kvm *kvm, + gfn_t *startp, gfn_t end, bool map_private) +{ + struct kvm_mmu_page *root; + gfn_t start = *startp; + bool flush = false; + int i; + + lockdep_assert_held_write(&kvm->mmu_lock); + KVM_BUG_ON(start & kvm_gfn_shared_mask(kvm), kvm); + KVM_BUG_ON(end & kvm_gfn_shared_mask(kvm), kvm); + + kvm_mmu_invalidate_begin(kvm, start, end); + for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) { + for_each_tdp_mmu_root_yield_safe(kvm, root, i) { + if (is_private_sp(root) == map_private) + continue; + + /* + * TODO: If necessary, return to the caller with -EAGAIN + * instead of yield-and-resume within + * tdp_mmu_zap_leafs(). + */ + flush = tdp_mmu_zap_leafs(kvm, root, start, end, + /*can_yield=*/true, flush, + /*zap_private=*/is_private_sp(root)); + } + } + if (flush) + kvm_flush_remote_tlbs_with_address(kvm, start, end - start); + kvm_mmu_invalidate_end(kvm, start, end); + + return 0; +} + /* * Return the level of the lowest level SPTE added to sptes. * That SPTE may be non-present. diff --git a/arch/x86/kvm/mmu/tdp_mmu.h b/arch/x86/kvm/mmu/tdp_mmu.h index 695175c921a5..cb13bc1c3679 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.h +++ b/arch/x86/kvm/mmu/tdp_mmu.h @@ -51,6 +51,9 @@ void kvm_tdp_mmu_try_split_huge_pages(struct kvm *kvm, gfn_t start, gfn_t end, int target_level, bool shared); +int kvm_tdp_mmu_map_gpa(struct kvm *kvm, + gfn_t *startp, gfn_t end, bool map_private); + static inline void kvm_tdp_mmu_walk_lockless_begin(void) { rcu_read_lock(); -- 2.25.1