1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Sync File validation framework 4 * 5 * Copyright (C) 2012 Google, Inc. 6 */ 7 8 #include <linux/file.h> 9 #include <linux/fs.h> 10 #include <linux/uaccess.h> 11 #include <linux/slab.h> 12 #include <linux/sync_file.h> 13 14 #include "sync_debug.h" 15 16 #define CREATE_TRACE_POINTS 17 #include "sync_trace.h" 18 19 /* 20 * SW SYNC validation framework 21 * 22 * A sync object driver that uses a 32bit counter to coordinate 23 * synchronization. Useful when there is no hardware primitive backing 24 * the synchronization. 25 * 26 * To start the framework just open: 27 * 28 * <debugfs>/sync/sw_sync 29 * 30 * That will create a sync timeline, all fences created under this timeline 31 * file descriptor will belong to the this timeline. 32 * 33 * The 'sw_sync' file can be opened many times as to create different 34 * timelines. 35 * 36 * Fences can be created with SW_SYNC_IOC_CREATE_FENCE ioctl with struct 37 * sw_sync_create_fence_data as parameter. 38 * 39 * To increment the timeline counter, SW_SYNC_IOC_INC ioctl should be used 40 * with the increment as u32. This will update the last signaled value 41 * from the timeline and signal any fence that has a seqno smaller or equal 42 * to it. 43 * 44 * struct sw_sync_create_fence_data 45 * @value: the seqno to initialise the fence with 46 * @name: the name of the new sync point 47 * @fence: return the fd of the new sync_file with the created fence 48 */ 49 struct sw_sync_create_fence_data { 50 __u32 value; 51 char name[32]; 52 __s32 fence; /* fd of new fence */ 53 }; 54 55 #define SW_SYNC_IOC_MAGIC 'W' 56 57 #define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\ 58 struct sw_sync_create_fence_data) 59 60 #define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32) 61 62 static const struct dma_fence_ops timeline_fence_ops; 63 64 static inline struct sync_pt *dma_fence_to_sync_pt(struct dma_fence *fence) 65 { 66 if (fence->ops != &timeline_fence_ops) 67 return NULL; 68 return container_of(fence, struct sync_pt, base); 69 } 70 71 /** 72 * sync_timeline_create() - creates a sync object 73 * @name: sync_timeline name 74 * 75 * Creates a new sync_timeline. Returns the sync_timeline object or NULL in 76 * case of error. 77 */ 78 static struct sync_timeline *sync_timeline_create(const char *name) 79 { 80 struct sync_timeline *obj; 81 82 obj = kzalloc(sizeof(*obj), GFP_KERNEL); 83 if (!obj) 84 return NULL; 85 86 kref_init(&obj->kref); 87 obj->context = dma_fence_context_alloc(1); 88 strlcpy(obj->name, name, sizeof(obj->name)); 89 90 obj->pt_tree = RB_ROOT; 91 INIT_LIST_HEAD(&obj->pt_list); 92 spin_lock_init(&obj->lock); 93 94 sync_timeline_debug_add(obj); 95 96 return obj; 97 } 98 99 static void sync_timeline_free(struct kref *kref) 100 { 101 struct sync_timeline *obj = 102 container_of(kref, struct sync_timeline, kref); 103 104 sync_timeline_debug_remove(obj); 105 106 kfree(obj); 107 } 108 109 static void sync_timeline_get(struct sync_timeline *obj) 110 { 111 kref_get(&obj->kref); 112 } 113 114 static void sync_timeline_put(struct sync_timeline *obj) 115 { 116 kref_put(&obj->kref, sync_timeline_free); 117 } 118 119 static const char *timeline_fence_get_driver_name(struct dma_fence *fence) 120 { 121 return "sw_sync"; 122 } 123 124 static const char *timeline_fence_get_timeline_name(struct dma_fence *fence) 125 { 126 struct sync_timeline *parent = dma_fence_parent(fence); 127 128 return parent->name; 129 } 130 131 static void timeline_fence_release(struct dma_fence *fence) 132 { 133 struct sync_pt *pt = dma_fence_to_sync_pt(fence); 134 struct sync_timeline *parent = dma_fence_parent(fence); 135 unsigned long flags; 136 137 spin_lock_irqsave(fence->lock, flags); 138 if (!list_empty(&pt->link)) { 139 list_del(&pt->link); 140 rb_erase(&pt->node, &parent->pt_tree); 141 } 142 spin_unlock_irqrestore(fence->lock, flags); 143 144 sync_timeline_put(parent); 145 dma_fence_free(fence); 146 } 147 148 static bool timeline_fence_signaled(struct dma_fence *fence) 149 { 150 struct sync_timeline *parent = dma_fence_parent(fence); 151 152 return !__dma_fence_is_later(fence->seqno, parent->value, fence->ops); 153 } 154 155 static bool timeline_fence_enable_signaling(struct dma_fence *fence) 156 { 157 return true; 158 } 159 160 static void timeline_fence_value_str(struct dma_fence *fence, 161 char *str, int size) 162 { 163 snprintf(str, size, "%lld", fence->seqno); 164 } 165 166 static void timeline_fence_timeline_value_str(struct dma_fence *fence, 167 char *str, int size) 168 { 169 struct sync_timeline *parent = dma_fence_parent(fence); 170 171 snprintf(str, size, "%d", parent->value); 172 } 173 174 static const struct dma_fence_ops timeline_fence_ops = { 175 .get_driver_name = timeline_fence_get_driver_name, 176 .get_timeline_name = timeline_fence_get_timeline_name, 177 .enable_signaling = timeline_fence_enable_signaling, 178 .signaled = timeline_fence_signaled, 179 .release = timeline_fence_release, 180 .fence_value_str = timeline_fence_value_str, 181 .timeline_value_str = timeline_fence_timeline_value_str, 182 }; 183 184 /** 185 * sync_timeline_signal() - signal a status change on a sync_timeline 186 * @obj: sync_timeline to signal 187 * @inc: num to increment on timeline->value 188 * 189 * A sync implementation should call this any time one of it's fences 190 * has signaled or has an error condition. 191 */ 192 static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) 193 { 194 struct sync_pt *pt, *next; 195 196 trace_sync_timeline(obj); 197 198 spin_lock_irq(&obj->lock); 199 200 obj->value += inc; 201 202 list_for_each_entry_safe(pt, next, &obj->pt_list, link) { 203 if (!timeline_fence_signaled(&pt->base)) 204 break; 205 206 list_del_init(&pt->link); 207 rb_erase(&pt->node, &obj->pt_tree); 208 209 /* 210 * A signal callback may release the last reference to this 211 * fence, causing it to be freed. That operation has to be 212 * last to avoid a use after free inside this loop, and must 213 * be after we remove the fence from the timeline in order to 214 * prevent deadlocking on timeline->lock inside 215 * timeline_fence_release(). 216 */ 217 dma_fence_signal_locked(&pt->base); 218 } 219 220 spin_unlock_irq(&obj->lock); 221 } 222 223 /** 224 * sync_pt_create() - creates a sync pt 225 * @obj: parent sync_timeline 226 * @value: value of the fence 227 * 228 * Creates a new sync_pt (fence) as a child of @parent. @size bytes will be 229 * allocated allowing for implementation specific data to be kept after 230 * the generic sync_timeline struct. Returns the sync_pt object or 231 * NULL in case of error. 232 */ 233 static struct sync_pt *sync_pt_create(struct sync_timeline *obj, 234 unsigned int value) 235 { 236 struct sync_pt *pt; 237 238 pt = kzalloc(sizeof(*pt), GFP_KERNEL); 239 if (!pt) 240 return NULL; 241 242 sync_timeline_get(obj); 243 dma_fence_init(&pt->base, &timeline_fence_ops, &obj->lock, 244 obj->context, value); 245 INIT_LIST_HEAD(&pt->link); 246 247 spin_lock_irq(&obj->lock); 248 if (!dma_fence_is_signaled_locked(&pt->base)) { 249 struct rb_node **p = &obj->pt_tree.rb_node; 250 struct rb_node *parent = NULL; 251 252 while (*p) { 253 struct sync_pt *other; 254 int cmp; 255 256 parent = *p; 257 other = rb_entry(parent, typeof(*pt), node); 258 cmp = value - other->base.seqno; 259 if (cmp > 0) { 260 p = &parent->rb_right; 261 } else if (cmp < 0) { 262 p = &parent->rb_left; 263 } else { 264 if (dma_fence_get_rcu(&other->base)) { 265 sync_timeline_put(obj); 266 kfree(pt); 267 pt = other; 268 goto unlock; 269 } 270 p = &parent->rb_left; 271 } 272 } 273 rb_link_node(&pt->node, parent, p); 274 rb_insert_color(&pt->node, &obj->pt_tree); 275 276 parent = rb_next(&pt->node); 277 list_add_tail(&pt->link, 278 parent ? &rb_entry(parent, typeof(*pt), node)->link : &obj->pt_list); 279 } 280 unlock: 281 spin_unlock_irq(&obj->lock); 282 283 return pt; 284 } 285 286 /* 287 * *WARNING* 288 * 289 * improper use of this can result in deadlocking kernel drivers from userspace. 290 */ 291 292 /* opening sw_sync create a new sync obj */ 293 static int sw_sync_debugfs_open(struct inode *inode, struct file *file) 294 { 295 struct sync_timeline *obj; 296 char task_comm[TASK_COMM_LEN]; 297 298 get_task_comm(task_comm, current); 299 300 obj = sync_timeline_create(task_comm); 301 if (!obj) 302 return -ENOMEM; 303 304 file->private_data = obj; 305 306 return 0; 307 } 308 309 static int sw_sync_debugfs_release(struct inode *inode, struct file *file) 310 { 311 struct sync_timeline *obj = file->private_data; 312 struct sync_pt *pt, *next; 313 314 spin_lock_irq(&obj->lock); 315 316 list_for_each_entry_safe(pt, next, &obj->pt_list, link) { 317 dma_fence_set_error(&pt->base, -ENOENT); 318 dma_fence_signal_locked(&pt->base); 319 } 320 321 spin_unlock_irq(&obj->lock); 322 323 sync_timeline_put(obj); 324 return 0; 325 } 326 327 static long sw_sync_ioctl_create_fence(struct sync_timeline *obj, 328 unsigned long arg) 329 { 330 int fd = get_unused_fd_flags(O_CLOEXEC); 331 int err; 332 struct sync_pt *pt; 333 struct sync_file *sync_file; 334 struct sw_sync_create_fence_data data; 335 336 if (fd < 0) 337 return fd; 338 339 if (copy_from_user(&data, (void __user *)arg, sizeof(data))) { 340 err = -EFAULT; 341 goto err; 342 } 343 344 pt = sync_pt_create(obj, data.value); 345 if (!pt) { 346 err = -ENOMEM; 347 goto err; 348 } 349 350 sync_file = sync_file_create(&pt->base); 351 dma_fence_put(&pt->base); 352 if (!sync_file) { 353 err = -ENOMEM; 354 goto err; 355 } 356 357 data.fence = fd; 358 if (copy_to_user((void __user *)arg, &data, sizeof(data))) { 359 fput(sync_file->file); 360 err = -EFAULT; 361 goto err; 362 } 363 364 fd_install(fd, sync_file->file); 365 366 return 0; 367 368 err: 369 put_unused_fd(fd); 370 return err; 371 } 372 373 static long sw_sync_ioctl_inc(struct sync_timeline *obj, unsigned long arg) 374 { 375 u32 value; 376 377 if (copy_from_user(&value, (void __user *)arg, sizeof(value))) 378 return -EFAULT; 379 380 while (value > INT_MAX) { 381 sync_timeline_signal(obj, INT_MAX); 382 value -= INT_MAX; 383 } 384 385 sync_timeline_signal(obj, value); 386 387 return 0; 388 } 389 390 static long sw_sync_ioctl(struct file *file, unsigned int cmd, 391 unsigned long arg) 392 { 393 struct sync_timeline *obj = file->private_data; 394 395 switch (cmd) { 396 case SW_SYNC_IOC_CREATE_FENCE: 397 return sw_sync_ioctl_create_fence(obj, arg); 398 399 case SW_SYNC_IOC_INC: 400 return sw_sync_ioctl_inc(obj, arg); 401 402 default: 403 return -ENOTTY; 404 } 405 } 406 407 const struct file_operations sw_sync_debugfs_fops = { 408 .open = sw_sync_debugfs_open, 409 .release = sw_sync_debugfs_release, 410 .unlocked_ioctl = sw_sync_ioctl, 411 .compat_ioctl = compat_ptr_ioctl, 412 }; 413