Ignore:
File:
1 edited

Legend:

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

    rfdaad75d 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(page_table_locked(as));
    75        
     72        pte_t *ptl0, *ptl1, *ptl2, *ptl3;
     73        pte_t *newpt;
     74
     75        ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
     76
    7677        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) {
    77                 pte_t *newpt = (pte_t *) frame_alloc(PTL1_SIZE, FRAME_KA);
     78                newpt = (pte_t *)frame_alloc(PTL1_SIZE, FRAME_KA);
    7879                memsetb(newpt, FRAME_SIZE << PTL1_SIZE, 0);
    7980                SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
    8081                SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
    8182        }
    82        
    83         pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
    84        
     83
     84        ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
     85
    8586        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) {
    86                 pte_t *newpt = (pte_t *) frame_alloc(PTL2_SIZE, FRAME_KA);
     87                newpt = (pte_t *)frame_alloc(PTL2_SIZE, FRAME_KA);
    8788                memsetb(newpt, FRAME_SIZE << PTL2_SIZE, 0);
    8889                SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
    8990                SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
    9091        }
    91        
    92         pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
    93        
     92
     93        ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
     94
    9495        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) {
    95                 pte_t *newpt = (pte_t *) frame_alloc(PTL3_SIZE, FRAME_KA);
     96                newpt = (pte_t *)frame_alloc(PTL3_SIZE, FRAME_KA);
    9697                memsetb(newpt, FRAME_SIZE << PTL3_SIZE, 0);
    9798                SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
    9899                SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
    99100        }
    100        
    101         pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
    102        
     101
     102        ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
     103
    103104        SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(page), frame);
    104105        SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags);
     
    113114 * Empty page tables except PTL0 are freed.
    114115 *
    115  * @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.
    116119 * @param page Virtual address of the page to be demapped.
    117  *
    118120 */
    119121void pt_mapping_remove(as_t *as, uintptr_t page)
    120122{
    121         ASSERT(page_table_locked(as));
     123        pte_t *ptl0, *ptl1, *ptl2, *ptl3;
     124        bool empty = true;
     125        int i;
    122126
    123127        /*
    124128         * First, remove the mapping, if it exists.
    125          *
     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.
    126153         */
    127154       
    128         pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
    129         if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT)
    130                 return;
    131        
    132         pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
    133         if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT)
    134                 return;
    135        
    136         pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
    137         if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT)
    138                 return;
    139        
    140         pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
    141        
    142         /* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */
    143         memsetb(&ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0);
    144        
    145         /*
    146          * Second, free all empty tables along the way from PTL3 down to PTL0.
    147          *
    148          */
    149        
    150         /* Check PTL3 */
    151         bool empty = true;
    152        
    153         unsigned int i;
     155        /* check PTL3 */
    154156        for (i = 0; i < PTL3_ENTRIES; i++) {
    155157                if (PTE_VALID(&ptl3[i])) {
     
    158160                }
    159161        }
    160        
    161162        if (empty) {
    162163                /*
    163164                 * PTL3 is empty.
    164165                 * Release the frame and remove PTL3 pointer from preceding table.
    165                  *
    166166                 */
    167167                frame_free(KA2PA((uintptr_t) ptl3));
    168 #if (PTL2_ENTRIES != 0)
    169                 memsetb(&ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0);
    170 #elif (PTL1_ENTRIES != 0)
    171                 memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
    172 #else
    173                 memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    174 #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);
    175174        } else {
    176175                /*
     
    178177                 * Therefore, there must be a path from PTL0 to PTL3 and
    179178                 * thus nothing to free in higher levels.
    180                  *
    181179                 */
    182180                return;
    183181        }
    184182       
    185         /* Check PTL2, empty is still true */
    186 #if (PTL2_ENTRIES != 0)
    187         for (i = 0; i < PTL2_ENTRIES; i++) {
    188                 if (PTE_VALID(&ptl2[i])) {
    189                         empty = false;
    190                         break;
    191                 }
    192         }
    193        
    194         if (empty) {
    195                 /*
    196                  * PTL2 is empty.
    197                  * Release the frame and remove PTL2 pointer from preceding table.
    198                  *
    199                  */
    200                 frame_free(KA2PA((uintptr_t) ptl2));
    201 #if (PTL1_ENTRIES != 0)
    202                 memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
    203 #else
    204                 memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    205 #endif
    206         } else {
    207                 /*
    208                  * PTL2 is not empty.
    209                  * Therefore, there must be a path from PTL0 to PTL2 and
    210                  * thus nothing to free in higher levels.
    211                  *
    212                  */
    213                 return;
    214         }
    215 #endif /* PTL2_ENTRIES != 0 */
    216        
     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
    217212        /* check PTL1, empty is still true */
    218 #if (PTL1_ENTRIES != 0)
    219         for (i = 0; i < PTL1_ENTRIES; i++) {
    220                 if (PTE_VALID(&ptl1[i])) {
    221                         empty = false;
    222                         break;
    223                 }
    224         }
    225        
    226         if (empty) {
    227                 /*
    228                  * PTL1 is empty.
    229                  * Release the frame and remove PTL1 pointer from preceding table.
    230                  *
    231                  */
    232                 frame_free(KA2PA((uintptr_t) ptl1));
    233                 memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    234         }
    235 #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
    236230}
    237231
     
    240234 * Find mapping for virtual page.
    241235 *
    242  * @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.
    243239 * @param page Virtual page.
    244240 *
    245  * @return NULL if there is no such mapping; entry from PTL3 describing
    246  *         the mapping otherwise.
    247  *
     241 * @return NULL if there is no such mapping; entry from PTL3 describing the mapping otherwise.
    248242 */
    249243pte_t *pt_mapping_find(as_t *as, uintptr_t page)
    250244{
    251         ASSERT(page_table_locked(as));
    252 
    253         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
    254249        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT)
    255250                return NULL;
    256        
    257         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
    258254        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT)
    259255                return NULL;
    260        
    261         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
    262259        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT)
    263260                return NULL;
    264        
    265         pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
    266        
     261
     262        ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
     263
    267264        return &ptl3[PTL3_INDEX(page)];
    268265}
Note: See TracChangeset for help on using the changeset viewer.