Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Sync File validation framework
0004  *
0005  * Copyright (C) 2012 Google, Inc.
0006  */
0007 
0008 #include <linux/file.h>
0009 #include <linux/fs.h>
0010 #include <linux/uaccess.h>
0011 #include <linux/slab.h>
0012 #include <linux/sync_file.h>
0013 
0014 #include "sync_debug.h"
0015 
0016 #define CREATE_TRACE_POINTS
0017 #include "sync_trace.h"
0018 
0019 /*
0020  * SW SYNC validation framework
0021  *
0022  * A sync object driver that uses a 32bit counter to coordinate
0023  * synchronization.  Useful when there is no hardware primitive backing
0024  * the synchronization.
0025  *
0026  * To start the framework just open:
0027  *
0028  * <debugfs>/sync/sw_sync
0029  *
0030  * That will create a sync timeline, all fences created under this timeline
0031  * file descriptor will belong to the this timeline.
0032  *
0033  * The 'sw_sync' file can be opened many times as to create different
0034  * timelines.
0035  *
0036  * Fences can be created with SW_SYNC_IOC_CREATE_FENCE ioctl with struct
0037  * sw_sync_create_fence_data as parameter.
0038  *
0039  * To increment the timeline counter, SW_SYNC_IOC_INC ioctl should be used
0040  * with the increment as u32. This will update the last signaled value
0041  * from the timeline and signal any fence that has a seqno smaller or equal
0042  * to it.
0043  *
0044  * struct sw_sync_create_fence_data
0045  * @value:  the seqno to initialise the fence with
0046  * @name:   the name of the new sync point
0047  * @fence:  return the fd of the new sync_file with the created fence
0048  */
0049 struct sw_sync_create_fence_data {
0050     __u32   value;
0051     char    name[32];
0052     __s32   fence; /* fd of new fence */
0053 };
0054 
0055 #define SW_SYNC_IOC_MAGIC   'W'
0056 
0057 #define SW_SYNC_IOC_CREATE_FENCE    _IOWR(SW_SYNC_IOC_MAGIC, 0,\
0058         struct sw_sync_create_fence_data)
0059 
0060 #define SW_SYNC_IOC_INC         _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
0061 
0062 static const struct dma_fence_ops timeline_fence_ops;
0063 
0064 static inline struct sync_pt *dma_fence_to_sync_pt(struct dma_fence *fence)
0065 {
0066     if (fence->ops != &timeline_fence_ops)
0067         return NULL;
0068     return container_of(fence, struct sync_pt, base);
0069 }
0070 
0071 /**
0072  * sync_timeline_create() - creates a sync object
0073  * @name:   sync_timeline name
0074  *
0075  * Creates a new sync_timeline. Returns the sync_timeline object or NULL in
0076  * case of error.
0077  */
0078 static struct sync_timeline *sync_timeline_create(const char *name)
0079 {
0080     struct sync_timeline *obj;
0081 
0082     obj = kzalloc(sizeof(*obj), GFP_KERNEL);
0083     if (!obj)
0084         return NULL;
0085 
0086     kref_init(&obj->kref);
0087     obj->context = dma_fence_context_alloc(1);
0088     strlcpy(obj->name, name, sizeof(obj->name));
0089 
0090     obj->pt_tree = RB_ROOT;
0091     INIT_LIST_HEAD(&obj->pt_list);
0092     spin_lock_init(&obj->lock);
0093 
0094     sync_timeline_debug_add(obj);
0095 
0096     return obj;
0097 }
0098 
0099 static void sync_timeline_free(struct kref *kref)
0100 {
0101     struct sync_timeline *obj =
0102         container_of(kref, struct sync_timeline, kref);
0103 
0104     sync_timeline_debug_remove(obj);
0105 
0106     kfree(obj);
0107 }
0108 
0109 static void sync_timeline_get(struct sync_timeline *obj)
0110 {
0111     kref_get(&obj->kref);
0112 }
0113 
0114 static void sync_timeline_put(struct sync_timeline *obj)
0115 {
0116     kref_put(&obj->kref, sync_timeline_free);
0117 }
0118 
0119 static const char *timeline_fence_get_driver_name(struct dma_fence *fence)
0120 {
0121     return "sw_sync";
0122 }
0123 
0124 static const char *timeline_fence_get_timeline_name(struct dma_fence *fence)
0125 {
0126     struct sync_timeline *parent = dma_fence_parent(fence);
0127 
0128     return parent->name;
0129 }
0130 
0131 static void timeline_fence_release(struct dma_fence *fence)
0132 {
0133     struct sync_pt *pt = dma_fence_to_sync_pt(fence);
0134     struct sync_timeline *parent = dma_fence_parent(fence);
0135     unsigned long flags;
0136 
0137     spin_lock_irqsave(fence->lock, flags);
0138     if (!list_empty(&pt->link)) {
0139         list_del(&pt->link);
0140         rb_erase(&pt->node, &parent->pt_tree);
0141     }
0142     spin_unlock_irqrestore(fence->lock, flags);
0143 
0144     sync_timeline_put(parent);
0145     dma_fence_free(fence);
0146 }
0147 
0148 static bool timeline_fence_signaled(struct dma_fence *fence)
0149 {
0150     struct sync_timeline *parent = dma_fence_parent(fence);
0151 
0152     return !__dma_fence_is_later(fence->seqno, parent->value, fence->ops);
0153 }
0154 
0155 static bool timeline_fence_enable_signaling(struct dma_fence *fence)
0156 {
0157     return true;
0158 }
0159 
0160 static void timeline_fence_value_str(struct dma_fence *fence,
0161                     char *str, int size)
0162 {
0163     snprintf(str, size, "%lld", fence->seqno);
0164 }
0165 
0166 static void timeline_fence_timeline_value_str(struct dma_fence *fence,
0167                          char *str, int size)
0168 {
0169     struct sync_timeline *parent = dma_fence_parent(fence);
0170 
0171     snprintf(str, size, "%d", parent->value);
0172 }
0173 
0174 static const struct dma_fence_ops timeline_fence_ops = {
0175     .get_driver_name = timeline_fence_get_driver_name,
0176     .get_timeline_name = timeline_fence_get_timeline_name,
0177     .enable_signaling = timeline_fence_enable_signaling,
0178     .signaled = timeline_fence_signaled,
0179     .release = timeline_fence_release,
0180     .fence_value_str = timeline_fence_value_str,
0181     .timeline_value_str = timeline_fence_timeline_value_str,
0182 };
0183 
0184 /**
0185  * sync_timeline_signal() - signal a status change on a sync_timeline
0186  * @obj:    sync_timeline to signal
0187  * @inc:    num to increment on timeline->value
0188  *
0189  * A sync implementation should call this any time one of it's fences
0190  * has signaled or has an error condition.
0191  */
0192 static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
0193 {
0194     struct sync_pt *pt, *next;
0195 
0196     trace_sync_timeline(obj);
0197 
0198     spin_lock_irq(&obj->lock);
0199 
0200     obj->value += inc;
0201 
0202     list_for_each_entry_safe(pt, next, &obj->pt_list, link) {
0203         if (!timeline_fence_signaled(&pt->base))
0204             break;
0205 
0206         list_del_init(&pt->link);
0207         rb_erase(&pt->node, &obj->pt_tree);
0208 
0209         /*
0210          * A signal callback may release the last reference to this
0211          * fence, causing it to be freed. That operation has to be
0212          * last to avoid a use after free inside this loop, and must
0213          * be after we remove the fence from the timeline in order to
0214          * prevent deadlocking on timeline->lock inside
0215          * timeline_fence_release().
0216          */
0217         dma_fence_signal_locked(&pt->base);
0218     }
0219 
0220     spin_unlock_irq(&obj->lock);
0221 }
0222 
0223 /**
0224  * sync_pt_create() - creates a sync pt
0225  * @obj:    parent sync_timeline
0226  * @value:  value of the fence
0227  *
0228  * Creates a new sync_pt (fence) as a child of @parent.  @size bytes will be
0229  * allocated allowing for implementation specific data to be kept after
0230  * the generic sync_timeline struct. Returns the sync_pt object or
0231  * NULL in case of error.
0232  */
0233 static struct sync_pt *sync_pt_create(struct sync_timeline *obj,
0234                       unsigned int value)
0235 {
0236     struct sync_pt *pt;
0237 
0238     pt = kzalloc(sizeof(*pt), GFP_KERNEL);
0239     if (!pt)
0240         return NULL;
0241 
0242     sync_timeline_get(obj);
0243     dma_fence_init(&pt->base, &timeline_fence_ops, &obj->lock,
0244                obj->context, value);
0245     INIT_LIST_HEAD(&pt->link);
0246 
0247     spin_lock_irq(&obj->lock);
0248     if (!dma_fence_is_signaled_locked(&pt->base)) {
0249         struct rb_node **p = &obj->pt_tree.rb_node;
0250         struct rb_node *parent = NULL;
0251 
0252         while (*p) {
0253             struct sync_pt *other;
0254             int cmp;
0255 
0256             parent = *p;
0257             other = rb_entry(parent, typeof(*pt), node);
0258             cmp = value - other->base.seqno;
0259             if (cmp > 0) {
0260                 p = &parent->rb_right;
0261             } else if (cmp < 0) {
0262                 p = &parent->rb_left;
0263             } else {
0264                 if (dma_fence_get_rcu(&other->base)) {
0265                     sync_timeline_put(obj);
0266                     kfree(pt);
0267                     pt = other;
0268                     goto unlock;
0269                 }
0270                 p = &parent->rb_left;
0271             }
0272         }
0273         rb_link_node(&pt->node, parent, p);
0274         rb_insert_color(&pt->node, &obj->pt_tree);
0275 
0276         parent = rb_next(&pt->node);
0277         list_add_tail(&pt->link,
0278                   parent ? &rb_entry(parent, typeof(*pt), node)->link : &obj->pt_list);
0279     }
0280 unlock:
0281     spin_unlock_irq(&obj->lock);
0282 
0283     return pt;
0284 }
0285 
0286 /*
0287  * *WARNING*
0288  *
0289  * improper use of this can result in deadlocking kernel drivers from userspace.
0290  */
0291 
0292 /* opening sw_sync create a new sync obj */
0293 static int sw_sync_debugfs_open(struct inode *inode, struct file *file)
0294 {
0295     struct sync_timeline *obj;
0296     char task_comm[TASK_COMM_LEN];
0297 
0298     get_task_comm(task_comm, current);
0299 
0300     obj = sync_timeline_create(task_comm);
0301     if (!obj)
0302         return -ENOMEM;
0303 
0304     file->private_data = obj;
0305 
0306     return 0;
0307 }
0308 
0309 static int sw_sync_debugfs_release(struct inode *inode, struct file *file)
0310 {
0311     struct sync_timeline *obj = file->private_data;
0312     struct sync_pt *pt, *next;
0313 
0314     spin_lock_irq(&obj->lock);
0315 
0316     list_for_each_entry_safe(pt, next, &obj->pt_list, link) {
0317         dma_fence_set_error(&pt->base, -ENOENT);
0318         dma_fence_signal_locked(&pt->base);
0319     }
0320 
0321     spin_unlock_irq(&obj->lock);
0322 
0323     sync_timeline_put(obj);
0324     return 0;
0325 }
0326 
0327 static long sw_sync_ioctl_create_fence(struct sync_timeline *obj,
0328                        unsigned long arg)
0329 {
0330     int fd = get_unused_fd_flags(O_CLOEXEC);
0331     int err;
0332     struct sync_pt *pt;
0333     struct sync_file *sync_file;
0334     struct sw_sync_create_fence_data data;
0335 
0336     if (fd < 0)
0337         return fd;
0338 
0339     if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
0340         err = -EFAULT;
0341         goto err;
0342     }
0343 
0344     pt = sync_pt_create(obj, data.value);
0345     if (!pt) {
0346         err = -ENOMEM;
0347         goto err;
0348     }
0349 
0350     sync_file = sync_file_create(&pt->base);
0351     dma_fence_put(&pt->base);
0352     if (!sync_file) {
0353         err = -ENOMEM;
0354         goto err;
0355     }
0356 
0357     data.fence = fd;
0358     if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
0359         fput(sync_file->file);
0360         err = -EFAULT;
0361         goto err;
0362     }
0363 
0364     fd_install(fd, sync_file->file);
0365 
0366     return 0;
0367 
0368 err:
0369     put_unused_fd(fd);
0370     return err;
0371 }
0372 
0373 static long sw_sync_ioctl_inc(struct sync_timeline *obj, unsigned long arg)
0374 {
0375     u32 value;
0376 
0377     if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
0378         return -EFAULT;
0379 
0380     while (value > INT_MAX)  {
0381         sync_timeline_signal(obj, INT_MAX);
0382         value -= INT_MAX;
0383     }
0384 
0385     sync_timeline_signal(obj, value);
0386 
0387     return 0;
0388 }
0389 
0390 static long sw_sync_ioctl(struct file *file, unsigned int cmd,
0391               unsigned long arg)
0392 {
0393     struct sync_timeline *obj = file->private_data;
0394 
0395     switch (cmd) {
0396     case SW_SYNC_IOC_CREATE_FENCE:
0397         return sw_sync_ioctl_create_fence(obj, arg);
0398 
0399     case SW_SYNC_IOC_INC:
0400         return sw_sync_ioctl_inc(obj, arg);
0401 
0402     default:
0403         return -ENOTTY;
0404     }
0405 }
0406 
0407 const struct file_operations sw_sync_debugfs_fops = {
0408     .open           = sw_sync_debugfs_open,
0409     .release        = sw_sync_debugfs_release,
0410     .unlocked_ioctl = sw_sync_ioctl,
0411     .compat_ioctl   = compat_ptr_ioctl,
0412 };