2022-05-06 08:40:08

by Isaku Yamahata

[permalink] [raw]
Subject: [RFC PATCH v6 034/104] KVM: x86/mmu: Add address conversion functions for TDX shared bits

From: Rick Edgecombe <[email protected]>

TDX repurposes one GPA bits (51 bit or 47 bit based on configuration) to
indicate the GPA is private(if cleared) or shared (if set) with VMM. If
GPA.shared is set, GPA is converted existing conventional EPT pointed by
EPTP. If GPA.shared bit is cleared, GPA is converted by Secure-EPT(S-EPT)
TDX module manages. VMM has to issue SEAM call to TDX module to operate on
S-EPT. e.g. populating/zapping guest page or shadow page by TDH.PAGE.{ADD,
REMOVE} for guest page, TDH.PAGE.SEPT.{ADD, REMOVE} S-EPT etc.

Several hooks needs to be added to KVM MMU to support TDX. Add a function
to check if KVM MMU is running for TDX and several functions for address
conversation between private-GPA and shared-GPA.

Signed-off-by: Isaku Yamahata <[email protected]>
---
arch/x86/include/asm/kvm_host.h | 2 ++
arch/x86/kvm/mmu.h | 32 ++++++++++++++++++++++++++++++++
arch/x86/kvm/mmu/mmu.c | 6 ++++--
3 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 60a97ae55972..88fd3fd3e1a0 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1251,7 +1251,9 @@ struct kvm_arch {
*/
u32 max_vcpu_ids;

+#ifdef CONFIG_KVM_MMU_PRIVATE
gfn_t gfn_shared_mask;
+#endif
};

struct kvm_vm_stat {
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 7e258cc94152..3647035a147e 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -373,4 +373,36 @@ static inline gpa_t kvm_translate_gpa(struct kvm_vcpu *vcpu,
return gpa;
return translate_nested_gpa(vcpu, gpa, access, exception);
}
+
+static inline gfn_t kvm_gfn_shared_mask(const struct kvm *kvm)
+{
+#ifdef CONFIG_KVM_MMU_PRIVATE
+ return kvm->arch.gfn_shared_mask;
+#else
+ return 0;
+#endif
+}
+
+static inline gfn_t kvm_gfn_shared(const struct kvm *kvm, gfn_t gfn)
+{
+ return gfn | kvm_gfn_shared_mask(kvm);
+}
+
+static inline gfn_t kvm_gfn_private(const struct kvm *kvm, gfn_t gfn)
+{
+ return gfn & ~kvm_gfn_shared_mask(kvm);
+}
+
+static inline gpa_t kvm_gpa_private(const struct kvm *kvm, gpa_t gpa)
+{
+ return gpa & ~gfn_to_gpa(kvm_gfn_shared_mask(kvm));
+}
+
+static inline bool kvm_is_private_gpa(const struct kvm *kvm, gpa_t gpa)
+{
+ gfn_t mask = kvm_gfn_shared_mask(kvm);
+
+ return mask && !(gpa_to_gfn(gpa) & mask);
+}
+
#endif
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 909372762363..d1c37295bb6e 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -264,8 +264,10 @@ static void kvm_flush_remote_tlbs_with_range(struct kvm *kvm,
{
int ret = -ENOTSUPP;

- if (range && kvm_x86_ops.tlb_remote_flush_with_range)
+ if (range && kvm_available_flush_tlb_with_range()) {
+ /* Callback should flush both private GFN and shared GFN. */
ret = static_call(kvm_x86_tlb_remote_flush_with_range)(kvm, range);
+ }

if (ret)
kvm_flush_remote_tlbs(kvm);
@@ -4048,7 +4050,7 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
unsigned long mmu_seq;
int r;

- fault->gfn = fault->addr >> PAGE_SHIFT;
+ fault->gfn = gpa_to_gfn(fault->addr) & ~kvm_gfn_shared_mask(vcpu->kvm);
fault->slot = kvm_vcpu_gfn_to_memslot(vcpu, fault->gfn);

if (page_fault_handle_page_track(vcpu, fault))
--
2.25.1



2022-05-10 11:05:05

by Kai Huang

[permalink] [raw]
Subject: Re: [RFC PATCH v6 034/104] KVM: x86/mmu: Add address conversion functions for TDX shared bits

On Thu, 2022-05-05 at 11:14 -0700, [email protected] wrote:
> From: Rick Edgecombe <[email protected]>
>
> TDX repurposes one GPA bits (51 bit or 47 bit based on configuration) to
> indicate the GPA is private(if cleared) or shared (if set) with VMM. If
> GPA.shared is set, GPA is converted existing conventional EPT pointed by
> EPTP. If GPA.shared bit is cleared, GPA is converted by Secure-EPT(S-EPT)
> TDX module manages. VMM has to issue SEAM call to TDX module to operate on
> S-EPT. e.g. populating/zapping guest page or shadow page by TDH.PAGE.{ADD,
> REMOVE} for guest page, TDH.PAGE.SEPT.{ADD, REMOVE} S-EPT etc.
>
> Several hooks needs to be added to KVM MMU to support TDX. Add a function
> to check if KVM MMU is running for TDX and several functions for address
> conversation between private-GPA and shared-GPA.
>
> Signed-off-by: Isaku Yamahata <[email protected]>
> ---
> arch/x86/include/asm/kvm_host.h | 2 ++
> arch/x86/kvm/mmu.h | 32 ++++++++++++++++++++++++++++++++
> arch/x86/kvm/mmu/mmu.c | 6 ++++--
> 3 files changed, 38 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index 60a97ae55972..88fd3fd3e1a0 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -1251,7 +1251,9 @@ struct kvm_arch {
> */
> u32 max_vcpu_ids;
>
> +#ifdef CONFIG_KVM_MMU_PRIVATE
> gfn_t gfn_shared_mask;
> +#endif
> };
>
> struct kvm_vm_stat {
> diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
> index 7e258cc94152..3647035a147e 100644
> --- a/arch/x86/kvm/mmu.h
> +++ b/arch/x86/kvm/mmu.h
> @@ -373,4 +373,36 @@ static inline gpa_t kvm_translate_gpa(struct kvm_vcpu *vcpu,
> return gpa;
> return translate_nested_gpa(vcpu, gpa, access, exception);
> }
> +
> +static inline gfn_t kvm_gfn_shared_mask(const struct kvm *kvm)
> +{
> +#ifdef CONFIG_KVM_MMU_PRIVATE
> + return kvm->arch.gfn_shared_mask;
> +#else
> + return 0;
> +#endif
> +}
> +
> +static inline gfn_t kvm_gfn_shared(const struct kvm *kvm, gfn_t gfn)
> +{
> + return gfn | kvm_gfn_shared_mask(kvm);
> +}
> +
> +static inline gfn_t kvm_gfn_private(const struct kvm *kvm, gfn_t gfn)
> +{
> + return gfn & ~kvm_gfn_shared_mask(kvm);
> +}
> +
> +static inline gpa_t kvm_gpa_private(const struct kvm *kvm, gpa_t gpa)
> +{
> + return gpa & ~gfn_to_gpa(kvm_gfn_shared_mask(kvm));
> +}
> +
> +static inline bool kvm_is_private_gpa(const struct kvm *kvm, gpa_t gpa)
> +{
> + gfn_t mask = kvm_gfn_shared_mask(kvm);
> +
> + return mask && !(gpa_to_gfn(gpa) & mask);
> +}
> +
> #endif
> diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
> index 909372762363..d1c37295bb6e 100644
> --- a/arch/x86/kvm/mmu/mmu.c
> +++ b/arch/x86/kvm/mmu/mmu.c
> @@ -264,8 +264,10 @@ static void kvm_flush_remote_tlbs_with_range(struct kvm *kvm,
> {
> int ret = -ENOTSUPP;
>
> - if (range && kvm_x86_ops.tlb_remote_flush_with_range)
> + if (range && kvm_available_flush_tlb_with_range()) {
> + /* Callback should flush both private GFN and shared GFN. */
> ret = static_call(kvm_x86_tlb_remote_flush_with_range)(kvm, range);
> + }

??

>
> if (ret)
> kvm_flush_remote_tlbs(kvm);
> @@ -4048,7 +4050,7 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
> unsigned long mmu_seq;
> int r;
>
> - fault->gfn = fault->addr >> PAGE_SHIFT;
> + fault->gfn = gpa_to_gfn(fault->addr) & ~kvm_gfn_shared_mask(vcpu->kvm);
> fault->slot = kvm_vcpu_gfn_to_memslot(vcpu, fault->gfn);
>
> if (page_fault_handle_page_track(vcpu, fault))

As I said in previous version, this above change alone is broken:

https://lore.kernel.org/lkml/[email protected]/T/#mcd5c235e3577f5129810f3183f151a1c5f63466e

Why cannot this patch be merged to other patch(es) which truly adds
private/shared mapping support?

Or did I get something wrong?

--
Thanks,
-Kai



2022-05-14 03:39:31

by Isaku Yamahata

[permalink] [raw]
Subject: Re: [RFC PATCH v6 034/104] KVM: x86/mmu: Add address conversion functions for TDX shared bits

On Tue, May 10, 2022 at 12:16:58PM +1200,
Kai Huang <[email protected]> wrote:

> On Thu, 2022-05-05 at 11:14 -0700, [email protected] wrote:
> > From: Rick Edgecombe <[email protected]>
...
> > diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
> > index 909372762363..d1c37295bb6e 100644
> > --- a/arch/x86/kvm/mmu/mmu.c
> > +++ b/arch/x86/kvm/mmu/mmu.c
> > @@ -264,8 +264,10 @@ static void kvm_flush_remote_tlbs_with_range(struct kvm *kvm,
> > {
> > int ret = -ENOTSUPP;
> >
> > - if (range && kvm_x86_ops.tlb_remote_flush_with_range)
> > + if (range && kvm_available_flush_tlb_with_range()) {
> > + /* Callback should flush both private GFN and shared GFN. */
> > ret = static_call(kvm_x86_tlb_remote_flush_with_range)(kvm, range);
> > + }
>
> ??

Dropped this hunk.


> > if (ret)
> > kvm_flush_remote_tlbs(kvm);
> > @@ -4048,7 +4050,7 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
> > unsigned long mmu_seq;
> > int r;
> >
> > - fault->gfn = fault->addr >> PAGE_SHIFT;
> > + fault->gfn = gpa_to_gfn(fault->addr) & ~kvm_gfn_shared_mask(vcpu->kvm);
> > fault->slot = kvm_vcpu_gfn_to_memslot(vcpu, fault->gfn);
> >
> > if (page_fault_handle_page_track(vcpu, fault))
>
> As I said in previous version, this above change alone is broken:
>
> https://lore.kernel.org/lkml/[email protected]/T/#mcd5c235e3577f5129810f3183f151a1c5f63466e
>
> Why cannot this patch be merged to other patch(es) which truly adds
> private/shared mapping support?
>
> Or did I get something wrong?

Oops. Somehow I missed this part. I moved this part to "TDP MMU TDX support".

--
Isaku Yamahata <[email protected]>