page_ht.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Jakub Jermar
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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          * Virtual page addresses have roughly the same probability
00104          * of occurring. Least significant bits of VPN compose the
00105          * hash index.
00106          */
00107         index = ((page >> PAGE_WIDTH) & (PAGE_HT_ENTRIES-1));
00108         
00109         /*
00110          * Address space structures are likely to be allocated from
00111          * similar addresses. Least significant bits compose the
00112          * hash index.
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          * Convert item to PTE.
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          * Convert item to PTE.
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          * Note that removed PTE's will be freed
00217          * by remove_callback().
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 

Generated on Sun Jun 18 16:51:20 2006 for HelenOS Kernel (ia64) by  doxygen 1.4.6