00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00038 #include <genarch/mm/page_ht.h>
00039 #include <mm/page.h>
00040 #include <arch/mm/page.h>
00041 #include <mm/frame.h>
00042 #include <mm/slab.h>
00043 #include <mm/as.h>
00044 #include <arch/mm/asid.h>
00045 #include <arch/types.h>
00046 #include <typedefs.h>
00047 #include <arch/asm.h>
00048 #include <synch/spinlock.h>
00049 #include <arch.h>
00050 #include <debug.h>
00051 #include <memstr.h>
00052 #include <adt/hash_table.h>
00053 #include <align.h>
00054
00055 static index_t hash(__native key[]);
00056 static bool compare(__native key[], count_t keys, link_t *item);
00057 static void remove_callback(link_t *item);
00058
00059 static void ht_mapping_insert(as_t *as, __address page, __address frame, int flags);
00060 static void ht_mapping_remove(as_t *as, __address page);
00061 static pte_t *ht_mapping_find(as_t *as, __address page);
00062
00068 mutex_t page_ht_lock;
00069
00074 hash_table_t page_ht;
00075
00077 hash_table_operations_t ht_operations = {
00078 .hash = hash,
00079 .compare = compare,
00080 .remove_callback = remove_callback
00081 };
00082
00084 page_mapping_operations_t ht_mapping_operations = {
00085 .mapping_insert = ht_mapping_insert,
00086 .mapping_remove = ht_mapping_remove,
00087 .mapping_find = ht_mapping_find
00088 };
00089
00096 index_t hash(__native key[])
00097 {
00098 as_t *as = (as_t *) key[KEY_AS];
00099 __address page = (__address) key[KEY_PAGE];
00100 index_t index;
00101
00102
00103
00104
00105
00106
00107 index = ((page >> PAGE_WIDTH) & (PAGE_HT_ENTRIES-1));
00108
00109
00110
00111
00112
00113
00114 index |= ((__native) as) & (PAGE_HT_ENTRIES-1);
00115
00116 return index;
00117 }
00118
00127 bool compare(__native key[], count_t keys, link_t *item)
00128 {
00129 pte_t *t;
00130
00131 ASSERT(item);
00132 ASSERT((keys > 0) && (keys <= PAGE_HT_KEYS));
00133
00134
00135
00136
00137 t = hash_table_get_instance(item, pte_t, link);
00138
00139 if (keys == PAGE_HT_KEYS) {
00140 return (key[KEY_AS] == (__address) t->as) && (key[KEY_PAGE] == t->page);
00141 } else {
00142 return (key[KEY_AS] == (__address) t->as);
00143 }
00144 }
00145
00150 void remove_callback(link_t *item)
00151 {
00152 pte_t *t;
00153
00154 ASSERT(item);
00155
00156
00157
00158
00159 t = hash_table_get_instance(item, pte_t, link);
00160
00161 free(t);
00162 }
00163
00176 void ht_mapping_insert(as_t *as, __address page, __address frame, int flags)
00177 {
00178 pte_t *t;
00179 __native key[2] = { (__address) as, page = ALIGN_DOWN(page, PAGE_SIZE) };
00180
00181 if (!hash_table_find(&page_ht, key)) {
00182 t = (pte_t *) malloc(sizeof(pte_t), FRAME_ATOMIC);
00183 ASSERT(t != NULL);
00184
00185 t->g = (flags & PAGE_GLOBAL) != 0;
00186 t->x = (flags & PAGE_EXEC) != 0;
00187 t->w = (flags & PAGE_WRITE) != 0;
00188 t->k = !(flags & PAGE_USER);
00189 t->c = (flags & PAGE_CACHEABLE) != 0;
00190 t->p = !(flags & PAGE_NOT_PRESENT);
00191
00192 t->as = as;
00193 t->page = ALIGN_DOWN(page, PAGE_SIZE);
00194 t->frame = ALIGN_DOWN(frame, FRAME_SIZE);
00195
00196 hash_table_insert(&page_ht, key, &t->link);
00197 }
00198 }
00199
00211 void ht_mapping_remove(as_t *as, __address page)
00212 {
00213 __native key[2] = { (__address) as, page = ALIGN_DOWN(page, PAGE_SIZE) };
00214
00215
00216
00217
00218
00219 hash_table_remove(&page_ht, key, 2);
00220 }
00221
00222
00234 pte_t *ht_mapping_find(as_t *as, __address page)
00235 {
00236 link_t *hlp;
00237 pte_t *t = NULL;
00238 __native key[2] = { (__address) as, page = ALIGN_DOWN(page, PAGE_SIZE) };
00239
00240 hlp = hash_table_find(&page_ht, key);
00241 if (hlp)
00242 t = hash_table_get_instance(hlp, pte_t, link);
00243
00244 return t;
00245 }
00246