...
 
Commits (2)
......@@ -576,8 +576,33 @@ int
deinit_enclave_iommu(struct pisces_enclave * enclave)
{
struct enclave_iommu_state * iommu = &(enclave->iommu_state);
struct hashtable_iter * iter = NULL;
BUG_ON(atomic_read(&(iommu->nr_domains)) != 0);
if (atomic_read(&(iommu->nr_domains)) != 0) {
printk(KERN_ERR "Deinit enclave IOMMU mappings with %d domains active\n", atomic_read(&(iommu->nr_domains)));
printk(KERN_ERR "Force removing these mappings\n");
iter = create_htable_iter(iommu->domain_table);
if (iter == NULL) {
printk(KERN_ERR "Out of memory\n");
return -1;
}
BUG_ON(iter->entry == NULL);
do {
uint32_t dev_id = (uint32_t)htable_get_iter_key(iter);
int status;
status = __enclave_iommu_free_domain(enclave, dev_id);
if (status != 0) {
printk(KERN_ERR "Could not free IOMMU domain for VM %d\n", dev_id);
}
} while (htable_iter_advance(iter));
free_htable_iter(iter);
BUG_ON(atomic_read(&(iommu->nr_domains)) != 0);
}
free_htable(iommu->domain_table, 1, 0);
......
......@@ -684,3 +684,188 @@ free_htable(struct hashtable * htable,
kfree(htable);
}
/* HASH TABLE ITERATORS */
struct hashtable_iter *
create_htable_iter(struct hashtable * htable)
{
u32 i;
u32 table_length;
struct hashtable_iter * iter = (struct hashtable_iter *)kmalloc(sizeof(struct hashtable_iter),
GFP_KERNEL);
if (iter == NULL) {
return NULL;
}
iter->htable = htable;
iter->entry = NULL;
iter->parent = NULL;
table_length = htable->table_length;
iter->index = table_length;
if (htable->entry_count == 0) {
return iter;
}
for (i = 0; i < table_length; i++) {
if (htable->table[i] != NULL) {
iter->entry = htable->table[i];
iter->index = i;
break;
}
}
return iter;
}
void
free_htable_iter(struct hashtable_iter * iter)
{
kfree(iter);
}
uintptr_t
htable_get_iter_key(struct hashtable_iter * iter)
{
return iter->entry->key;
}
uintptr_t
htable_get_iter_value(struct hashtable_iter * iter)
{
return iter->entry->value;
}
/* advance - advance the iterator to the next element
* returns zero if advanced to end of table */
int
htable_iter_advance(struct hashtable_iter * iter)
{
u32 j;
u32 table_length;
struct hash_entry ** table;
struct hash_entry * next;
if (iter->entry == NULL) {
return 0; /* stupidity check */
}
next = iter->entry->next;
if (next != NULL) {
iter->parent = iter->entry;
iter->entry = next;
return -1;
}
table_length = iter->htable->table_length;
iter->parent = NULL;
if (table_length <= (j = ++(iter->index))) {
iter->entry = NULL;
return 0;
}
table = iter->htable->table;
while ((next = table[j]) == NULL) {
if (++j >= table_length) {
iter->index = table_length;
iter->entry = NULL;
return 0;
}
}
iter->index = j;
iter->entry = next;
return -1;
}
/* remove - remove the entry at the current iterator position
* and advance the iterator, if there is a successive
* element.
* If you want the value, read it before you remove:
* beware memory leaks if you don't.
* Returns zero if end of iteration. */
int
htable_iter_remove(struct hashtable_iter * iter,
int free_key)
{
struct hash_entry * remember_entry;
struct hash_entry * remember_parent;
int ret;
/* Do the removal */
if ((iter->parent) == NULL) {
/* element is head of a chain */
iter->htable->table[iter->index] = iter->entry->next;
} else {
/* element is mid-chain */
iter->parent->next = iter->entry->next;
}
/* itr->e is now outside the hashtable */
remember_entry = iter->entry;
iter->htable->entry_count--;
if (free_key) {
freekey((void *)(remember_entry->key));
}
/* Advance the iterator, correcting the parent */
remember_parent = iter->parent;
ret = htable_iter_advance(iter);
if (iter->parent == remember_entry) {
iter->parent = remember_parent;
}
kfree(remember_entry);
return ret;
}
/* returns zero if not found */
int
htable_iter_search(struct hashtable_iter * iter,
struct hashtable * htable,
uintptr_t key)
{
struct hash_entry * entry;
struct hash_entry * parent;
u32 hash_value;
u32 index;
hash_value = do_hash(htable, key);
index = indexFor(htable->table_length, hash_value);
entry = htable->table[index];
parent = NULL;
while (entry != NULL) {
/* Check hash value to short circuit heavier comparison */
if ((hash_value == entry->hash) &&
(htable->eq_fn(key, entry->key))) {
iter->index = index;
iter->entry = entry;
iter->parent = parent;
iter->htable = htable;
return -1;
}
parent = entry;
entry = entry->next;
}
return 0;
}
......@@ -106,4 +106,62 @@ int htable_inc(struct hashtable * htable, uintptr_t key, uintptr_t value);
int htable_dec(struct hashtable * htable, uintptr_t key, uintptr_t value);
/* ************ */
/* ITERATOR API */
/* ************ */
/*****************************************************************************/
/* This struct is only concrete here to allow the inlining of two of the
* accessor functions. */
struct hashtable_iter {
struct hashtable * htable;
struct hash_entry * entry;
struct hash_entry * parent;
uint32_t index;
};
struct hashtable_iter * create_htable_iter(struct hashtable * htable);
void free_htable_iter(struct hashtable_iter * iter);
/* - return the value of the (key,value) pair at the current position */
//extern inline
uintptr_t htable_get_iter_key(struct hashtable_iter * iter);
/* {
return iter->entry->key;
}
*/
/* value - return the value of the (key,value) pair at the current position */
//extern inline
uintptr_t htable_get_iter_value(struct hashtable_iter * iter);
/* {
return iter->entry->value;
}
*/
/* returns zero if advanced to end of table */
int htable_iter_advance(struct hashtable_iter * iter);
/* remove current element and advance the iterator to the next element
* NB: if you need the value to free it, read it before
* removing. ie: beware memory leaks!
* returns zero if advanced to end of table
*/
int htable_iter_remove(struct hashtable_iter * iter, int free_key);
/* search - overwrite the supplied iterator, to point to the entry
* matching the supplied key.
* returns zero if not found. */
int htable_iter_search(struct hashtable_iter * iter, struct hashtable * htable, uintptr_t key);
#endif /* __UTIL_HASHTABLE_H__ */