lkml.org 
[lkml]   [2023]   [Dec]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC PATCH 06/42] KVM: Register/Unregister importers to KVM exported TDP
    Date
    Each TDP exported by KVM has its own list of importers. External components
    can register/unregister itself as an importer with a unique importer ops.

    The sequence for external components to register/unregister as importer is
    like:
    1. call kvm_tdp_fd_get() to get a KVM TDP fd object.
    2. call tdp_fd->ops->register_importer() to register itself as an importer.
    3. call tdp_fd->ops->unregister_importer() to unregister itself as
    importer.
    4. call kvm_tdp_fd_put() to put the KVM TDP fd object.

    When destroying a KVM TDP fd object, all importers are force-unregistered.
    There's no extra notification to the importers at that time because the
    force-unregister should only happen when importers calls kvm_tdp_fd_put()
    without calling tdp_fd->ops->unregister_importer() first.

    Signed-off-by: Yan Zhao <yan.y.zhao@intel.com>
    ---
    include/linux/kvm_host.h | 5 +++
    virt/kvm/tdp_fd.c | 68 +++++++++++++++++++++++++++++++++++++++-
    2 files changed, 72 insertions(+), 1 deletion(-)

    diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
    index 5a74b2b0ac81f..f73d32eef8833 100644
    --- a/include/linux/kvm_host.h
    +++ b/include/linux/kvm_host.h
    @@ -2334,6 +2334,11 @@ struct kvm_exported_tdp {

    struct kvm *kvm;
    u32 as_id;
    +
    + /* protect importers list */
    + spinlock_t importer_lock;
    + struct list_head importers;
    +
    /* head at kvm->exported_tdp_list */
    struct list_head list_node;
    };
    diff --git a/virt/kvm/tdp_fd.c b/virt/kvm/tdp_fd.c
    index 7e68199ea9643..3271da1a4b2c1 100644
    --- a/virt/kvm/tdp_fd.c
    +++ b/virt/kvm/tdp_fd.c
    @@ -13,6 +13,13 @@ static inline int is_tdp_fd_file(struct file *file);
    static const struct file_operations kvm_tdp_fd_fops;
    static const struct kvm_exported_tdp_ops exported_tdp_ops;

    +struct kvm_tdp_importer {
    + struct kvm_tdp_importer_ops *ops;
    + void *data;
    + struct list_head node;
    +};
    +static void kvm_tdp_unregister_all_importers(struct kvm_exported_tdp *tdp);
    +
    int kvm_create_tdp_fd(struct kvm *kvm, struct kvm_create_tdp_fd *ct)
    {
    struct kvm_exported_tdp *tdp;
    @@ -56,6 +63,9 @@ int kvm_create_tdp_fd(struct kvm *kvm, struct kvm_create_tdp_fd *ct)
    if (ret)
    goto out;

    + INIT_LIST_HEAD(&tdp->importers);
    + spin_lock_init(&tdp->importer_lock);
    +
    tdp_fd->file = anon_inode_getfile("tdp_fd", &kvm_tdp_fd_fops,
    tdp_fd, O_RDWR | O_CLOEXEC);
    if (!tdp_fd->file) {
    @@ -107,6 +117,7 @@ static int kvm_tdp_fd_release(struct inode *inode, struct file *file)
    list_del(&tdp->list_node);
    spin_unlock(&tdp->kvm->exported_tdplist_lock);

    + kvm_tdp_unregister_all_importers(tdp);
    kvm_arch_exported_tdp_destroy(tdp);
    kvm_put_kvm(tdp->kvm);
    kfree(tdp);
    @@ -141,12 +152,67 @@ static inline int is_tdp_fd_file(struct file *file)
    static int kvm_tdp_register_importer(struct kvm_tdp_fd *tdp_fd,
    struct kvm_tdp_importer_ops *ops, void *data)
    {
    - return -EOPNOTSUPP;
    + struct kvm_tdp_importer *importer, *tmp;
    + struct kvm_exported_tdp *tdp;
    +
    + if (!tdp_fd || !tdp_fd->priv || !ops)
    + return -EINVAL;
    +
    + tdp = tdp_fd->priv;
    + importer = kzalloc(sizeof(*importer), GFP_KERNEL);
    + if (!importer)
    + return -ENOMEM;
    +
    + spin_lock(&tdp->importer_lock);
    + list_for_each_entry(tmp, &tdp->importers, node) {
    + if (tmp->ops != ops)
    + continue;
    +
    + kfree(importer);
    + spin_unlock(&tdp->importer_lock);
    + return -EBUSY;
    + }
    +
    + importer->ops = ops;
    + importer->data = data;
    + list_add(&importer->node, &tdp->importers);
    +
    + spin_unlock(&tdp->importer_lock);
    +
    + return 0;
    }

    static void kvm_tdp_unregister_importer(struct kvm_tdp_fd *tdp_fd,
    struct kvm_tdp_importer_ops *ops)
    {
    + struct kvm_tdp_importer *importer, *n;
    + struct kvm_exported_tdp *tdp;
    +
    + if (!tdp_fd || !tdp_fd->priv)
    + return;
    +
    + tdp = tdp_fd->priv;
    + spin_lock(&tdp->importer_lock);
    + list_for_each_entry_safe(importer, n, &tdp->importers, node) {
    + if (importer->ops != ops)
    + continue;
    +
    + list_del(&importer->node);
    + kfree(importer);
    + }
    + spin_unlock(&tdp->importer_lock);
    +}
    +
    +static void kvm_tdp_unregister_all_importers(struct kvm_exported_tdp *tdp)
    +{
    + struct kvm_tdp_importer *importer, *n;
    +
    + spin_lock(&tdp->importer_lock);
    + list_for_each_entry_safe(importer, n, &tdp->importers, node) {
    + list_del(&importer->node);
    + kfree(importer);
    + }
    + spin_unlock(&tdp->importer_lock);
    }

    static void *kvm_tdp_get_metadata(struct kvm_tdp_fd *tdp_fd)
    --
    2.17.1
    \
     
     \ /
      Last update: 2023-12-02 10:46    [W:4.568 / U:0.180 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site