[RFC PATCH 01/42] KVM: Public header for KVM to export TDP

Yan Zhao
2023-12-02T09:42:30Z

Introduce public header for data structures and interfaces for KVM to
export TDP page table (EPT/NPT in x86) to external components of KVM.

KVM exposes a TDP FD object which allows external components to get page
table meta data, request mapping, and register invalidation callbacks to
the TDP page table exported by KVM.

Two symbols kvm_tdp_fd_get() and kvm_tdp_fd_put() are exported by KVM to
external components to get/put the TDP FD object.

New header file kvm_tdp_fd.h is added because kvm_host.h is not expected to
be included from outside of KVM in future AFAIK.

Signed-off-by: Yan Zhao <yan.y.zhao@intel.com>
---
include/linux/kvm_tdp_fd.h | 137 +++++++++++++++++++++++++++++++++++++
1 file changed, 137 insertions(+)
create mode 100644 include/linux/kvm_tdp_fd.h

diff --git a/include/linux/kvm_tdp_fd.h b/include/linux/kvm_tdp_fd.h
new file mode 100644
index 0000000000000..3661779dd8cf5
--- /dev/null
+++ b/include/linux/kvm_tdp_fd.h
@@ -0,0 +1,137 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __KVM_TDP_FD_H
+#define __KVM_TDP_FD_H
+
+#include <linux/types.h>
+#include <linux/mm.h>
+
+struct kvm_exported_tdp;
+struct kvm_exported_tdp_ops;
+struct kvm_tdp_importer_ops;
+
+/**
+ * struct kvm_tdp_fd - KVM TDP FD object
+ *
+ * Interface of exporting KVM TDP page table to external components of KVM.
+ *
+ * This KVM TDP FD object is created by KVM VM ioctl KVM_CREATE_TDP_FD.
+ * On object creation, KVM will find or create a TDP page table, mark it as
+ * exported and increase reference count of this exported TDP page table.
+ *
+ * On object destroy, the exported TDP page table is unmarked as exported with
+ * its reference count decreased.
+ *
+ * During the life cycle of KVM TDP FD object, ref count of KVM VM is hold.
+ *
+ * Components outside of KVM can get meta data (e.g. page table type, levels,
+ * root HPA,...), request page fault on the exported TDP page table and register
+ * themselves as importers to receive notification through kvm_exported_tdp_ops
+ * @ops.
+ *
+ * @file: struct file object associated with the KVM TDP FD object.
+ * @ops: kvm_exported_tdp_ops associated with the exported TDP page table.
+ * @priv: internal data structures used by KVM to manage TDP page table
+ * exported by KVM.
+ *
+ */
+struct kvm_tdp_fd {
+ /* Public */
+ struct file *file;
+ const struct kvm_exported_tdp_ops *ops;
+
+ /* private to KVM */
+ struct kvm_exported_tdp *priv;
+};
+
+/**
+ * kvm_tdp_fd_get - Public interface to get KVM TDP FD object.
+ *
+ * @fd: fd of the KVM TDP FD object.
+ * @return: KVM TDP FD object if @fd corresponds to a valid KVM TDP FD file.
+ * -EBADF if @fd does not correspond a struct file.
+ * -EINVAL if @fd does not correspond to a KVM TDP FD file.
+ *
+ * Callers of this interface will get a KVM TDP FD object with ref count
+ * increased.
+ */
+struct kvm_tdp_fd *kvm_tdp_fd_get(int fd);
+
+/**
+ * kvm_tdp_fd_put - Public interface to put ref count of a KVM TDP FD object.
+ *
+ * @tdp: KVM TDP FD object.
+ *
+ * Put reference count of the KVM TDP FD object.
+ * After the last reference count of the TDP FD object goes away,
+ * kvm_tdp_fd_release() will be called to decrease KVM VM ref count and destroy
+ * the KVM TDP FD object.
+ */
+void kvm_tdp_fd_put(struct kvm_tdp_fd *tdp);
+
+struct kvm_tdp_fault_type {
+ u32 read:1;
+ u32 write:1;
+ u32 exec:1;
+};
+
+/**
+ * struct kvm_exported_tdp_ops - operations possible on KVM TDP FD object.
+ * @register_importer: This is called from components outside of KVM to register
+ * importer callback ops and the importer data.
+ * This callback is a must.
+ * Returns: 0 on success, negative error code on failure.
+ * -EBUSY if the importer ops is already registered.
+ * @unregister_importer:This is called from components outside of KVM if it does
+ * not want to receive importer callbacks any more.
+ * This callback is a must.
+ * @fault: This is called from components outside of KVM to trigger
+ * page fault on a GPA and to map physical page into the
+ * TDP page tables exported by KVM.
+ * This callback is optional.
+ * If this callback is absent, components outside KVM will
+ * not be able to trigger page fault and map physical pages
+ * into the TDP page tables exported by KVM.
+ * @get_metadata: This is called from components outside of KVM to retrieve
+ * meta data of the TDP page tables exported by KVM, e.g.
+ * page table type,root HPA, levels, reserved zero bits...
+ * Returns: pointer to a vendor meta data on success.
+ * Error PTR on error.
+ * This callback is a must.
+ */
+struct kvm_exported_tdp_ops {
+ int (*register_importer)(struct kvm_tdp_fd *tdp_fd,
+ struct kvm_tdp_importer_ops *ops,
+ void *importer_data);
+
+ void (*unregister_importer)(struct kvm_tdp_fd *tdp_fd,
+ struct kvm_tdp_importer_ops *ops);
+
+ int (*fault)(struct kvm_tdp_fd *tdp_fd, struct mm_struct *mm,
+ unsigned long gfn, struct kvm_tdp_fault_type type);
+
+ void *(*get_metadata)(struct kvm_tdp_fd *tdp_fd);
+};
+
+/**
+ * struct kvm_tdp_importer_ops - importer callbacks
+ *
+ * Components outside of KVM can be registered as importers of KVM's exported
+ * TDP page tables via register_importer op in kvm_exported_tdp_ops of a KVM TDP
+ * FD object.
+ *
+ * Each importer must define its own importer callbacks and KVM will notify
+ * importers of changes of the exported TDP page tables.
+ */
+struct kvm_tdp_importer_ops {
+ /**
+ * This is called by KVM to notify the importer that a range of KVM
+ * TDP has been invalidated.
+ * When @start is 0 and @size is -1, a whole of KVM TDP is invalidated.
+ *
+ * @data: the importer private data.
+ * @start: start GPA of the invalidated range.
+ * @size: length of in the invalidated range.
+ */
+ void (*invalidate)(void *data, unsigned long start, unsigned long size);
+};
+#endif /* __KVM_TDP_FD_H */
--
2.17.1