aboutsummaryrefslogtreecommitdiffstats
path: root/include/drm/drm_vma_manager.h
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-08-25 12:28:57 -0400
committerDave Airlie <airlied@redhat.com>2013-08-26 21:54:54 -0400
commit88d7ebe59341dc3b82e662b80809694e3c6b3766 (patch)
treec9b89ab9ba6b2310e270b67600ca790cc85e24c3 /include/drm/drm_vma_manager.h
parent291d284c6004e3a63d0c2f6c31570ab2126843a8 (diff)
drm/vma: add access management helpers
The VMA offset manager uses a device-global address-space. Hence, any user can currently map any offset-node they want. They only need to guess the right offset. If we wanted per open-file offset spaces, we'd either need VM_NONLINEAR mappings or multiple "struct address_space" trees. As both doesn't really scale, we implement access management in the VMA manager itself. We use an rb-tree to store open-files for each VMA node. On each mmap call, GEM, TTM or the drivers must check whether the current user is allowed to map this file. We add a separate lock for each node as there is no generic lock available for the caller to protect the node easily. As we currently don't know whether an object may be used for mmap(), we have to do access management for all objects. If it turns out to slow down handle creation/deletion significantly, we can optimize it in several ways: - Most times only a single filp is added per bo so we could use a static "struct file *main_filp" which is checked/added/removed first before we fall back to the rbtree+drm_vma_offset_file. This could be even done lockless with rcu. - Let user-space pass a hint whether mmap() should be supported on the bo and avoid access-management if not. - .. there are probably more ideas once we have benchmarks .. v2: add drm_vma_node_verify_access() helper Signed-off-by: David Herrmann <dh.herrmann@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'include/drm/drm_vma_manager.h')
-rw-r--r--include/drm/drm_vma_manager.h39
1 files changed, 36 insertions, 3 deletions
diff --git a/include/drm/drm_vma_manager.h b/include/drm/drm_vma_manager.h
index 22eedac046ac..c18a593d1744 100644
--- a/include/drm/drm_vma_manager.h
+++ b/include/drm/drm_vma_manager.h
@@ -24,15 +24,24 @@
24 */ 24 */
25 25
26#include <drm/drm_mm.h> 26#include <drm/drm_mm.h>
27#include <linux/fs.h>
27#include <linux/mm.h> 28#include <linux/mm.h>
28#include <linux/module.h> 29#include <linux/module.h>
29#include <linux/rbtree.h> 30#include <linux/rbtree.h>
30#include <linux/spinlock.h> 31#include <linux/spinlock.h>
31#include <linux/types.h> 32#include <linux/types.h>
32 33
34struct drm_vma_offset_file {
35 struct rb_node vm_rb;
36 struct file *vm_filp;
37 unsigned long vm_count;
38};
39
33struct drm_vma_offset_node { 40struct drm_vma_offset_node {
41 rwlock_t vm_lock;
34 struct drm_mm_node vm_node; 42 struct drm_mm_node vm_node;
35 struct rb_node vm_rb; 43 struct rb_node vm_rb;
44 struct rb_root vm_files;
36}; 45};
37 46
38struct drm_vma_offset_manager { 47struct drm_vma_offset_manager {
@@ -56,6 +65,11 @@ int drm_vma_offset_add(struct drm_vma_offset_manager *mgr,
56void drm_vma_offset_remove(struct drm_vma_offset_manager *mgr, 65void drm_vma_offset_remove(struct drm_vma_offset_manager *mgr,
57 struct drm_vma_offset_node *node); 66 struct drm_vma_offset_node *node);
58 67
68int drm_vma_node_allow(struct drm_vma_offset_node *node, struct file *filp);
69void drm_vma_node_revoke(struct drm_vma_offset_node *node, struct file *filp);
70bool drm_vma_node_is_allowed(struct drm_vma_offset_node *node,
71 struct file *filp);
72
59/** 73/**
60 * drm_vma_offset_exact_lookup() - Look up node by exact address 74 * drm_vma_offset_exact_lookup() - Look up node by exact address
61 * @mgr: Manager object 75 * @mgr: Manager object
@@ -122,9 +136,8 @@ static inline void drm_vma_offset_unlock_lookup(struct drm_vma_offset_manager *m
122 * drm_vma_node_reset() - Initialize or reset node object 136 * drm_vma_node_reset() - Initialize or reset node object
123 * @node: Node to initialize or reset 137 * @node: Node to initialize or reset
124 * 138 *
125 * Reset a node to its initial state. This must be called if @node isn't 139 * Reset a node to its initial state. This must be called before using it with
126 * already cleared (eg., via kzalloc) before using it with any VMA offset 140 * any VMA offset manager.
127 * manager.
128 * 141 *
129 * This must not be called on an already allocated node, or you will leak 142 * This must not be called on an already allocated node, or you will leak
130 * memory. 143 * memory.
@@ -132,6 +145,8 @@ static inline void drm_vma_offset_unlock_lookup(struct drm_vma_offset_manager *m
132static inline void drm_vma_node_reset(struct drm_vma_offset_node *node) 145static inline void drm_vma_node_reset(struct drm_vma_offset_node *node)
133{ 146{
134 memset(node, 0, sizeof(*node)); 147 memset(node, 0, sizeof(*node));
148 node->vm_files = RB_ROOT;
149 rwlock_init(&node->vm_lock);
135} 150}
136 151
137/** 152/**
@@ -221,4 +236,22 @@ static inline void drm_vma_node_unmap(struct drm_vma_offset_node *node,
221 drm_vma_node_size(node) << PAGE_SHIFT, 1); 236 drm_vma_node_size(node) << PAGE_SHIFT, 1);
222} 237}
223 238
239/**
240 * drm_vma_node_verify_access() - Access verification helper for TTM
241 * @node: Offset node
242 * @filp: Open-file
243 *
244 * This checks whether @filp is granted access to @node. It is the same as
245 * drm_vma_node_is_allowed() but suitable as drop-in helper for TTM
246 * verify_access() callbacks.
247 *
248 * RETURNS:
249 * 0 if access is granted, -EACCES otherwise.
250 */
251static inline int drm_vma_node_verify_access(struct drm_vma_offset_node *node,
252 struct file *filp)
253{
254 return drm_vma_node_is_allowed(node, filp) ? 0 : -EACCES;
255}
256
224#endif /* __DRM_VMA_MANAGER_H__ */ 257#endif /* __DRM_VMA_MANAGER_H__ */