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 136 if (!list_empty(&pt->link)) { 137 unsigned long flags; 138 139 spin_lock_irqsave(fence->lock, flags); 140 if (!list_empty(&pt->link)) { 141 list_del(&pt->link); 142 rb_erase(&pt->node, &parent->pt_tree); 143 } 144 spin_unlock_irqrestore(fence->lock, flags); 145 } 146 147 sync_timeline_put(parent); 148 dma_fence_free(fence); 149 } 150 151 static bool timeline_fence_signaled(struct dma_fence *fence) 152 { 153 struct sync_timeline *parent = dma_fence_parent(fence); 154 155 return !__dma_fence_is_later(fence->seqno, parent->value, fence->ops); 156 } 157 158 static bool timeline_fence_enable_signaling(struct dma_fence *fence) 159 { 160 return true; 161 } 162 163 static void timeline_fence_value_str(struct dma_fence *fence, 164 char *str, int size) 165 { 166 snprintf(str, size, "%lld", fence->seqno); 167 } 168 169 static void timeline_fence_timeline_value_str(struct dma_fence *fence, 170 char *str, int size) 171 { 172 struct sync_timeline *parent = dma_fence_parent(fence); 173 174 snprintf(str, size, "%d", parent->value); 175 } 176 177 static const struct dma_fence_ops timeline_fence_ops = { 178 .get_driver_name = timeline_fence_get_driver_name, 179 .get_timeline_name = timeline_fence_get_timeline_name, 180 .enable_signaling = timeline_fence_enable_signaling, 181 .signaled = timeline_fence_signaled, 182 .release = timeline_fence_release, 183 .fence_value_str = timeline_fence_value_str, 184 .timeline_value_str = timeline_fence_timeline_value_str, 185 }; 186 187 /** 188 * sync_timeline_signal() - signal a status change on a sync_timeline 189 * @obj: sync_timeline to signal 190 * @inc: num to increment on timeline->value 191 * 192 * A sync implementation should call this any time one of it's fences 193 * has signaled or has an error condition. 194 */ 195 static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) 196 { 197 struct sync_pt *pt, *next; 198 199 trace_sync_timeline(obj); 200 201 spin_lock_irq(&obj->lock); 202 203 obj->value += inc; 204 205 list_for_each_entry_safe(pt, next, &obj->pt_list, link) { 206 if (!timeline_fence_signaled(&pt->base)) 207 break; 208 209 list_del_init(&pt->link); 210 rb_erase(&pt->node, &obj->pt_tree); 211 212 /* 213 * A signal callback may release the last reference to this 214 * fence, causing it to be freed. That operation has to be 215 * last to avoid a use after free inside this loop, and must 216 * be after we remove the fence from the timeline in order to 217 * prevent deadlocking on timeline->lock inside 218 * timeline_fence_release(). 219 */ 220 dma_fence_signal_locked(&pt->base); 221 } 222 223 spin_unlock_irq(&obj->lock); 224 } 225 226 /** 227 * sync_pt_create() - creates a sync pt 228 * @obj: parent sync_timeline 229 * @value: value of the fence 230 * 231 * Creates a new sync_pt (fence) as a child of @parent. @size bytes will be 232 * allocated allowing for implementation specific data to be kept after 233 * the generic sync_timeline struct. Returns the sync_pt object or 234 * NULL in case of error. 235 */ 236 static struct sync_pt *sync_pt_create(struct sync_timeline *obj, 237 unsigned int value) 238 { 239 struct sync_pt *pt; 240 241 pt = kzalloc(sizeof(*pt), GFP_KERNEL); 242 if (!pt) 243 return NULL; 244 245 sync_timeline_get(obj); 246 dma_fence_init(&pt->base, &timeline_fence_ops, &obj->lock, 247 obj->context, value); 248 INIT_LIST_HEAD(&pt->link); 249 250 spin_lock_irq(&obj->lock); 251 if (!dma_fence_is_signaled_locked(&pt->base)) { 252 struct rb_node **p = &obj->pt_tree.rb_node; 253 struct rb_node *parent = NULL; 254 255 while (*p) { 256 struct sync_pt *other; 257 int cmp; 258 259 parent = *p; 260 other = rb_entry(parent, typeof(*pt), node); 261 cmp = value - other->base.seqno; 262 if (cmp > 0) { 263 p = &parent->rb_right; 264 } else if (cmp < 0) { 265 p = &parent->rb_left; 266 } else { 267 if (dma_fence_get_rcu(&other->base)) { 268 dma_fence_put(&pt->base); 269 pt = other; 270 goto unlock; 271 } 272 p = &parent->rb_left; 273 } 274 } 275 rb_link_node(&pt->node, parent, p); 276 rb_insert_color(&pt->node, &obj->pt_tree); 277 278 parent = rb_next(&pt->node); 279 list_add_tail(&pt->link, 280 parent ? &rb_entry(parent, typeof(*pt), node)->link : &obj->pt_list); 281 } 282 unlock: 283 spin_unlock_irq(&obj->lock); 284 285 return pt; 286 } 287 288 /* 289 * *WARNING* 290 * 291 * improper use of this can result in deadlocking kernel drivers from userspace. 292 */ 293 294 /* opening sw_sync create a new sync obj */ 295 static int sw_sync_debugfs_open(struct inode *inode, struct file *file) 296 { 297 struct sync_timeline *obj; 298 char task_comm[TASK_COMM_LEN]; 299 300 get_task_comm(task_comm, current); 301 302 obj = sync_timeline_create(task_comm); 303 if (!obj) 304 return -ENOMEM; 305 306 file->private_data = obj; 307 308 return 0; 309 } 310 311 static int sw_sync_debugfs_release(struct inode *inode, struct file *file) 312 { 313 struct sync_timeline *obj = file->private_data; 314 struct sync_pt *pt, *next; 315 316 spin_lock_irq(&obj->lock); 317 318 list_for_each_entry_safe(pt, next, &obj->pt_list, link) { 319 dma_fence_set_error(&pt->base, -ENOENT); 320 dma_fence_signal_locked(&pt->base); 321 } 322 323 spin_unlock_irq(&obj->lock); 324 325 sync_timeline_put(obj); 326 return 0; 327 } 328 329 static long sw_sync_ioctl_create_fence(struct sync_timeline *obj, 330 unsigned long arg) 331 { 332 int fd = get_unused_fd_flags(O_CLOEXEC); 333 int err; 334 struct sync_pt *pt; 335 struct sync_file *sync_file; 336 struct sw_sync_create_fence_data data; 337 338 if (fd < 0) 339 return fd; 340 341 if (copy_from_user(&data, (void __user *)arg, sizeof(data))) { 342 err = -EFAULT; 343 goto err; 344 } 345 346 pt = sync_pt_create(obj, data.value); 347 if (!pt) { 348 err = -ENOMEM; 349 goto err; 350 } 351 352 sync_file = sync_file_create(&pt->base); 353 dma_fence_put(&pt->base); 354 if (!sync_file) { 355 err = -ENOMEM; 356 goto err; 357 } 358 359 data.fence = fd; 360 if (copy_to_user((void __user *)arg, &data, sizeof(data))) { 361 fput(sync_file->file); 362 err = -EFAULT; 363 goto err; 364 } 365 366 fd_install(fd, sync_file->file); 367 368 return 0; 369 370 err: 371 put_unused_fd(fd); 372 return err; 373 } 374 375 static long sw_sync_ioctl_inc(struct sync_timeline *obj, unsigned long arg) 376 { 377 u32 value; 378 379 if (copy_from_user(&value, (void __user *)arg, sizeof(value))) 380 return -EFAULT; 381 382 while (value > INT_MAX) { 383 sync_timeline_signal(obj, INT_MAX); 384 value -= INT_MAX; 385 } 386 387 sync_timeline_signal(obj, value); 388 389 return 0; 390 } 391 392 static long sw_sync_ioctl(struct file *file, unsigned int cmd, 393 unsigned long arg) 394 { 395 struct sync_timeline *obj = file->private_data; 396 397 switch (cmd) { 398 case SW_SYNC_IOC_CREATE_FENCE: 399 return sw_sync_ioctl_create_fence(obj, arg); 400 401 case SW_SYNC_IOC_INC: 402 return sw_sync_ioctl_inc(obj, arg); 403 404 default: 405 return -ENOTTY; 406 } 407 } 408 409 const struct file_operations sw_sync_debugfs_fops = { 410 .open = sw_sync_debugfs_open, 411 .release = sw_sync_debugfs_release, 412 .unlocked_ioctl = sw_sync_ioctl, 413 .compat_ioctl = sw_sync_ioctl, 414 }; 415