Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/genarch/src/mm/page_pt.c

    r8f80c77 rd99c1d2  
    3333/**
    3434 * @file
    35  * @brief Virtual Address Translation for hierarchical 4-level page tables.
     35 * @brief       Virtual Address Translation for hierarchical 4-level page tables.
    3636 */
    3737
     
    4646#include <memstr.h>
    4747
    48 static void pt_mapping_insert(as_t *, uintptr_t, uintptr_t, unsigned int);
    49 static void pt_mapping_remove(as_t *, uintptr_t);
    50 static pte_t *pt_mapping_find(as_t *, uintptr_t);
     48static void pt_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame, int flags);
     49static void pt_mapping_remove(as_t *as, uintptr_t page);
     50static pte_t *pt_mapping_find(as_t *as, uintptr_t page);
    5151
    5252page_mapping_operations_t pt_mapping_operations = {
     
    6161 * using flags.
    6262 *
    63  * @param as    Address space to wich page belongs.
    64  * @param page  Virtual address of the page to be mapped.
     63 * The page table must be locked and interrupts must be disabled.
     64 *
     65 * @param as Address space to wich page belongs.
     66 * @param page Virtual address of the page to be mapped.
    6567 * @param frame Physical address of memory frame to which the mapping is done.
    6668 * @param flags Flags to be used for mapping.
    67  *
    68  */
    69 void pt_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame,
    70     unsigned int flags)
     69 */
     70void pt_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame, int flags)
    7171{
    72         pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
    73 
    74         ASSERT(interrupts_disabled());
    75         ASSERT(page_table_locked(as));
    76        
     72        pte_t *ptl0, *ptl1, *ptl2, *ptl3;
     73        pte_t *newpt;
     74
     75        ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
     76
    7777        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) {
    78                 pte_t *newpt = (pte_t *) frame_alloc(PTL1_SIZE, FRAME_KA);
     78                newpt = (pte_t *)frame_alloc(PTL1_SIZE, FRAME_KA);
    7979                memsetb(newpt, FRAME_SIZE << PTL1_SIZE, 0);
    8080                SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
    8181                SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
    8282        }
    83        
    84         pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
    85        
     83
     84        ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
     85
    8686        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) {
    87                 pte_t *newpt = (pte_t *) frame_alloc(PTL2_SIZE, FRAME_KA);
     87                newpt = (pte_t *)frame_alloc(PTL2_SIZE, FRAME_KA);
    8888                memsetb(newpt, FRAME_SIZE << PTL2_SIZE, 0);
    8989                SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
    9090                SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
    9191        }
    92        
    93         pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
    94        
     92
     93        ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
     94
    9595        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) {
    96                 pte_t *newpt = (pte_t *) frame_alloc(PTL3_SIZE, FRAME_KA);
     96                newpt = (pte_t *)frame_alloc(PTL3_SIZE, FRAME_KA);
    9797                memsetb(newpt, FRAME_SIZE << PTL3_SIZE, 0);
    9898                SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
    9999                SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
    100100        }
    101        
    102         pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
    103        
     101
     102        ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
     103
    104104        SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(page), frame);
    105105        SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags);
     
    114114 * Empty page tables except PTL0 are freed.
    115115 *
    116  * @param as   Address space to wich page belongs.
     116 * The page table must be locked and interrupts must be disabled.
     117 *
     118 * @param as Address space to wich page belongs.
    117119 * @param page Virtual address of the page to be demapped.
    118  *
    119120 */
    120121void pt_mapping_remove(as_t *as, uintptr_t page)
    121122{
    122         ASSERT(interrupts_disabled());
    123         ASSERT(page_table_locked(as));
     123        pte_t *ptl0, *ptl1, *ptl2, *ptl3;
     124        bool empty = true;
     125        int i;
    124126
    125127        /*
    126128         * First, remove the mapping, if it exists.
    127          *
     129         */
     130
     131        ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
     132
     133        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT)
     134                return;
     135
     136        ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
     137
     138        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT)
     139                return;
     140
     141        ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
     142
     143        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT)
     144                return;
     145
     146        ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
     147
     148        /* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */
     149        memsetb(&ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0);
     150
     151        /*
     152         * Second, free all empty tables along the way from PTL3 down to PTL0.
    128153         */
    129154       
    130         pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
    131         if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT)
    132                 return;
    133        
    134         pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
    135         if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT)
    136                 return;
    137        
    138         pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
    139         if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT)
    140                 return;
    141        
    142         pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
    143        
    144         /* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */
    145         memsetb(&ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0);
    146        
    147         /*
    148          * Second, free all empty tables along the way from PTL3 down to PTL0.
    149          *
    150          */
    151        
    152         /* Check PTL3 */
    153         bool empty = true;
    154        
    155         unsigned int i;
     155        /* check PTL3 */
    156156        for (i = 0; i < PTL3_ENTRIES; i++) {
    157157                if (PTE_VALID(&ptl3[i])) {
     
    160160                }
    161161        }
    162        
    163162        if (empty) {
    164163                /*
    165164                 * PTL3 is empty.
    166165                 * Release the frame and remove PTL3 pointer from preceding table.
    167                  *
    168166                 */
    169167                frame_free(KA2PA((uintptr_t) ptl3));
    170 #if (PTL2_ENTRIES != 0)
    171                 memsetb(&ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0);
    172 #elif (PTL1_ENTRIES != 0)
    173                 memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
    174 #else
    175                 memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    176 #endif
     168                if (PTL2_ENTRIES)
     169                        memsetb(&ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0);
     170                else if (PTL1_ENTRIES)
     171                        memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
     172                else
     173                        memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    177174        } else {
    178175                /*
     
    180177                 * Therefore, there must be a path from PTL0 to PTL3 and
    181178                 * thus nothing to free in higher levels.
    182                  *
    183179                 */
    184180                return;
    185181        }
    186182       
    187         /* Check PTL2, empty is still true */
    188 #if (PTL2_ENTRIES != 0)
    189         for (i = 0; i < PTL2_ENTRIES; i++) {
    190                 if (PTE_VALID(&ptl2[i])) {
    191                         empty = false;
    192                         break;
    193                 }
    194         }
    195        
    196         if (empty) {
    197                 /*
    198                  * PTL2 is empty.
    199                  * Release the frame and remove PTL2 pointer from preceding table.
    200                  *
    201                  */
    202                 frame_free(KA2PA((uintptr_t) ptl2));
    203 #if (PTL1_ENTRIES != 0)
    204                 memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
    205 #else
    206                 memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    207 #endif
    208         } else {
    209                 /*
    210                  * PTL2 is not empty.
    211                  * Therefore, there must be a path from PTL0 to PTL2 and
    212                  * thus nothing to free in higher levels.
    213                  *
    214                  */
    215                 return;
    216         }
    217 #endif /* PTL2_ENTRIES != 0 */
    218        
     183        /* check PTL2, empty is still true */
     184        if (PTL2_ENTRIES) {
     185                for (i = 0; i < PTL2_ENTRIES; i++) {
     186                        if (PTE_VALID(&ptl2[i])) {
     187                                empty = false;
     188                                break;
     189                        }
     190                }
     191                if (empty) {
     192                        /*
     193                         * PTL2 is empty.
     194                         * Release the frame and remove PTL2 pointer from preceding table.
     195                         */
     196                        frame_free(KA2PA((uintptr_t) ptl2));
     197                        if (PTL1_ENTRIES)
     198                                memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
     199                        else
     200                                memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
     201                }
     202                else {
     203                        /*
     204                         * PTL2 is not empty.
     205                         * Therefore, there must be a path from PTL0 to PTL2 and
     206                         * thus nothing to free in higher levels.
     207                         */
     208                        return;
     209                }
     210        }
     211
    219212        /* check PTL1, empty is still true */
    220 #if (PTL1_ENTRIES != 0)
    221         for (i = 0; i < PTL1_ENTRIES; i++) {
    222                 if (PTE_VALID(&ptl1[i])) {
    223                         empty = false;
    224                         break;
    225                 }
    226         }
    227        
    228         if (empty) {
    229                 /*
    230                  * PTL1 is empty.
    231                  * Release the frame and remove PTL1 pointer from preceding table.
    232                  *
    233                  */
    234                 frame_free(KA2PA((uintptr_t) ptl1));
    235                 memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    236         }
    237 #endif /* PTL1_ENTRIES != 0 */
     213        if (PTL1_ENTRIES) {
     214                for (i = 0; i < PTL1_ENTRIES; i++) {
     215                        if (PTE_VALID(&ptl1[i])) {
     216                                empty = false;
     217                                break;
     218                        }
     219                }
     220                if (empty) {
     221                        /*
     222                         * PTL1 is empty.
     223                         * Release the frame and remove PTL1 pointer from preceding table.
     224                         */
     225                        frame_free(KA2PA((uintptr_t) ptl1));
     226                        memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
     227                }
     228        }
     229
    238230}
    239231
     
    242234 * Find mapping for virtual page.
    243235 *
    244  * @param as   Address space to which page belongs.
     236 * The page table must be locked and interrupts must be disabled.
     237 *
     238 * @param as Address space to which page belongs.
    245239 * @param page Virtual page.
    246240 *
    247  * @return NULL if there is no such mapping; entry from PTL3 describing
    248  *         the mapping otherwise.
    249  *
     241 * @return NULL if there is no such mapping; entry from PTL3 describing the mapping otherwise.
    250242 */
    251243pte_t *pt_mapping_find(as_t *as, uintptr_t page)
    252244{
    253         ASSERT(interrupts_disabled());
    254         ASSERT(page_table_locked(as));
    255 
    256         pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
     245        pte_t *ptl0, *ptl1, *ptl2, *ptl3;
     246
     247        ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
     248
    257249        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT)
    258250                return NULL;
    259        
    260         pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
     251
     252        ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
     253
    261254        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT)
    262255                return NULL;
    263        
    264         pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
     256
     257        ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
     258
    265259        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT)
    266260                return NULL;
    267        
    268         pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
    269        
     261
     262        ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
     263
    270264        return &ptl3[PTL3_INDEX(page)];
    271265}
Note: See TracChangeset for help on using the changeset viewer.