page_pt.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_pt.h>
00039 #include <mm/page.h>
00040 #include <mm/frame.h>
00041 #include <mm/as.h>
00042 #include <arch/mm/page.h>
00043 #include <arch/mm/as.h>
00044 #include <arch/types.h>
00045 #include <typedefs.h>
00046 #include <arch/asm.h>
00047 #include <memstr.h>
00048 
00049 static void pt_mapping_insert(as_t *as, __address page, __address frame, int flags);
00050 static void pt_mapping_remove(as_t *as, __address page);
00051 static pte_t *pt_mapping_find(as_t *as, __address page);
00052 
00053 page_mapping_operations_t pt_mapping_operations = {
00054         .mapping_insert = pt_mapping_insert,
00055         .mapping_remove = pt_mapping_remove,
00056         .mapping_find = pt_mapping_find
00057 };
00058 
00071 void pt_mapping_insert(as_t *as, __address page, __address frame, int flags)
00072 {
00073         pte_t *ptl0, *ptl1, *ptl2, *ptl3;
00074         __address newpt;
00075 
00076         ptl0 = (pte_t *) PA2KA((__address) as->page_table);
00077 
00078         if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) {
00079                 newpt = PA2KA(PFN2ADDR(frame_alloc(ONE_FRAME, FRAME_KA)));
00080                 memsetb(newpt, PAGE_SIZE, 0);
00081                 SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
00082                 SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
00083         }
00084 
00085         ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
00086 
00087         if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) {
00088                 newpt = PA2KA(PFN2ADDR(frame_alloc(ONE_FRAME, FRAME_KA)));
00089                 memsetb(newpt, PAGE_SIZE, 0);
00090                 SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
00091                 SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
00092         }
00093 
00094         ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
00095 
00096         if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) {
00097                 newpt = PA2KA(PFN2ADDR(frame_alloc(ONE_FRAME, FRAME_KA)));
00098                 memsetb(newpt, PAGE_SIZE, 0);
00099                 SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
00100                 SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
00101         }
00102 
00103         ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
00104 
00105         SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(page), frame);
00106         SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags);
00107 }
00108 
00122 void pt_mapping_remove(as_t *as, __address page)
00123 {
00124         pte_t *ptl0, *ptl1, *ptl2, *ptl3;
00125         bool empty = true;
00126         int i;
00127 
00128         /*
00129          * First, remove the mapping, if it exists.
00130          */
00131 
00132         ptl0 = (pte_t *) PA2KA((__address) as->page_table);
00133 
00134         if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT)
00135                 return;
00136 
00137         ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
00138 
00139         if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT)
00140                 return;
00141 
00142         ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
00143 
00144         if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT)
00145                 return;
00146 
00147         ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
00148 
00149         /* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */
00150         memsetb((__address) &ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0);
00151 
00152         /*
00153          * Second, free all empty tables along the way from PTL3 down to PTL0.
00154          */
00155         
00156         /* check PTL3 */
00157         for (i = 0; i < PTL3_ENTRIES; i++) {
00158                 if (PTE_VALID(&ptl3[i])) {
00159                         empty = false;
00160                         break;
00161                 }
00162         }
00163         if (empty) {
00164                 /*
00165                  * PTL3 is empty.
00166                  * Release the frame and remove PTL3 pointer from preceding table.
00167                  */
00168                 frame_free(ADDR2PFN(KA2PA((__address) ptl3)));
00169                 if (PTL2_ENTRIES)
00170                         memsetb((__address) &ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0);
00171                 else if (PTL1_ENTRIES)
00172                         memsetb((__address) &ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
00173                 else
00174                         memsetb((__address) &ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
00175         } else {
00176                 /*
00177                  * PTL3 is not empty.
00178                  * Therefore, there must be a path from PTL0 to PTL3 and
00179                  * thus nothing to free in higher levels.
00180                  */
00181                 return;
00182         }
00183         
00184         /* check PTL2, empty is still true */
00185         if (PTL2_ENTRIES) {
00186                 for (i = 0; i < PTL2_ENTRIES; i++) {
00187                         if (PTE_VALID(&ptl2[i])) {
00188                                 empty = false;
00189                                 break;
00190                         }
00191                 }
00192                 if (empty) {
00193                         /*
00194                          * PTL2 is empty.
00195                          * Release the frame and remove PTL2 pointer from preceding table.
00196                          */
00197                         frame_free(ADDR2PFN(KA2PA((__address) ptl2)));
00198                         if (PTL1_ENTRIES)
00199                                 memsetb((__address) &ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
00200                         else
00201                                 memsetb((__address) &ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
00202                 }
00203                 else {
00204                         /*
00205                          * PTL2 is not empty.
00206                          * Therefore, there must be a path from PTL0 to PTL2 and
00207                          * thus nothing to free in higher levels.
00208                          */
00209                         return;
00210                 }
00211         }
00212 
00213         /* check PTL1, empty is still true */
00214         if (PTL1_ENTRIES) {
00215                 for (i = 0; i < PTL1_ENTRIES; i++) {
00216                         if (PTE_VALID(&ptl1[i])) {
00217                                 empty = false;
00218                                 break;
00219                         }
00220                 }
00221                 if (empty) {
00222                         /*
00223                          * PTL1 is empty.
00224                          * Release the frame and remove PTL1 pointer from preceding table.
00225                          */
00226                         frame_free(ADDR2PFN(KA2PA((__address) ptl1)));
00227                         memsetb((__address) &ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
00228                 }
00229         }
00230 
00231 }
00232 
00244 pte_t *pt_mapping_find(as_t *as, __address page)
00245 {
00246         pte_t *ptl0, *ptl1, *ptl2, *ptl3;
00247 
00248         ptl0 = (pte_t *) PA2KA((__address) as->page_table);
00249 
00250         if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT)
00251                 return NULL;
00252 
00253         ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
00254 
00255         if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT)
00256                 return NULL;
00257 
00258         ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
00259 
00260         if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT)
00261                 return NULL;
00262 
00263         ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
00264 
00265         return &ptl3[PTL3_INDEX(page)];
00266 }
00267 

Generated on Sun Jun 18 16:38:50 2006 for HelenOS Kernel (ia32) by  doxygen 1.4.6