2 * This confidential and proprietary software may be used only as
3 * authorised by a licensing agreement from ARM Limited
4 * (C) COPYRIGHT 2008-2011, 2013-2015 ARM Limited
6 * The entire notice above must be reproduced on all authorised
7 * copies and copies may only be made to the extent permitted
8 * by a licensing agreement from ARM Limited.
11 #include "mali_kernel_common.h"
14 #include "ump_kernel_common.h"
15 #include "ump_kernel_types.h"
16 #include "ump_kernel_random_mapping.h"
18 #include <linux/random.h>
19 #include <linux/rbtree.h>
20 #include <linux/sched.h>
21 #include <linux/jiffies.h>
24 static ump_dd_mem
*search(struct rb_root
*root
, int id
)
26 struct rb_node
*node
= root
->rb_node
;
29 ump_dd_mem
*e
= container_of(node
, ump_dd_mem
, node
);
31 if (id
< e
->secure_id
) {
33 } else if (id
> e
->secure_id
) {
34 node
= node
->rb_right
;
43 static mali_bool
insert(struct rb_root
*root
, int id
, ump_dd_mem
*mem
)
45 struct rb_node
**new = &(root
->rb_node
);
46 struct rb_node
*parent
= NULL
;
49 ump_dd_mem
*this = container_of(*new, ump_dd_mem
, node
);
52 if (id
< this->secure_id
) {
53 new = &((*new)->rb_left
);
54 } else if (id
> this->secure_id
) {
55 new = &((*new)->rb_right
);
57 pr_warn("UMP: ID already used %x\n", id
);
62 rb_link_node(&mem
->node
, parent
, new);
63 rb_insert_color(&mem
->node
, root
);
69 ump_random_mapping
*ump_random_mapping_create(void)
71 ump_random_mapping
*map
= _mali_osk_calloc(1, sizeof(ump_random_mapping
));
76 map
->lock
= _mali_osk_mutex_rw_init(_MALI_OSK_LOCKFLAG_ORDERED
,
77 _MALI_OSK_LOCK_ORDER_DESCRIPTOR_MAP
);
78 if (NULL
!= map
->lock
) {
80 #if UMP_RANDOM_MAP_DELAY
81 map
->failed
.count
= 0;
82 map
->failed
.timestamp
= jiffies
;
89 void ump_random_mapping_destroy(ump_random_mapping
*map
)
91 _mali_osk_mutex_rw_term(map
->lock
);
95 int ump_random_mapping_insert(ump_random_mapping
*map
, ump_dd_mem
*mem
)
97 _mali_osk_mutex_rw_wait(map
->lock
, _MALI_OSK_LOCKMODE_RW
);
102 get_random_bytes(&id
, sizeof(id
));
104 /* Try a new random number if id happened to be the invalid
106 if (unlikely(id
== UMP_INVALID_SECURE_ID
))
109 /* Insert into the tree. If the id was already in use, get a
110 * new random id and try again. */
111 if (insert(&map
->root
, id
, mem
)) {
116 _mali_osk_mutex_rw_signal(map
->lock
, _MALI_OSK_LOCKMODE_RW
);
121 ump_dd_mem
*ump_random_mapping_get(ump_random_mapping
*map
, int id
)
123 ump_dd_mem
*mem
= NULL
;
124 #if UMP_RANDOM_MAP_DELAY
130 _mali_osk_mutex_rw_wait(map
->lock
, _MALI_OSK_LOCKMODE_RO
);
131 mem
= search(&map
->root
, id
);
133 if (unlikely(NULL
== mem
)) {
134 #if UMP_RANDOM_MAP_DELAY
137 if (time_is_before_jiffies(map
->failed
.timestamp
+
138 UMP_FAILED_LOOKUP_DELAY
* HZ
)) {
139 /* If it is a long time since last failure, reset
140 * the counter and skip the delay this time. */
141 map
->failed
.count
= 0;
142 } else if (map
->failed
.count
> UMP_FAILED_LOOKUPS_ALLOWED
) {
146 map
->failed
.timestamp
= jiffies
;
147 #endif /* UMP_RANDOM_MAP_DELAY */
149 ump_dd_reference_add(mem
);
151 _mali_osk_mutex_rw_signal(map
->lock
, _MALI_OSK_LOCKMODE_RO
);
153 #if UMP_RANDOM_MAP_DELAY
156 schedule_timeout_killable(UMP_FAILED_LOOKUP_DELAY
);
158 #endif /* UMP_RANDOM_MAP_DELAY */
163 static ump_dd_mem
*ump_random_mapping_remove_internal(ump_random_mapping
*map
, int id
)
165 ump_dd_mem
*mem
= NULL
;
167 mem
= search(&map
->root
, id
);
170 rb_erase(&mem
->node
, &map
->root
);
176 void ump_random_mapping_put(ump_dd_mem
*mem
)
180 _mali_osk_mutex_rw_wait(device
.secure_id_map
->lock
, _MALI_OSK_LOCKMODE_RW
);
182 new_ref
= _ump_osk_atomic_dec_and_read(&mem
->ref_count
);
183 DBG_MSG(5, ("Memory reference decremented. ID: %u, new value: %d\n",
184 mem
->secure_id
, new_ref
));
187 DBG_MSG(3, ("Final release of memory. ID: %u\n", mem
->secure_id
));
189 ump_random_mapping_remove_internal(device
.secure_id_map
, mem
->secure_id
);
191 mem
->release_func(mem
->ctx
, mem
);
195 _mali_osk_mutex_rw_signal(device
.secure_id_map
->lock
, _MALI_OSK_LOCKMODE_RW
);
198 ump_dd_mem
*ump_random_mapping_remove(ump_random_mapping
*map
, int descriptor
)
202 _mali_osk_mutex_rw_wait(map
->lock
, _MALI_OSK_LOCKMODE_RW
);
203 mem
= ump_random_mapping_remove_internal(map
, descriptor
);
204 _mali_osk_mutex_rw_signal(map
->lock
, _MALI_OSK_LOCKMODE_RW
);