Changeset da1bafb in mainline for kernel/genarch/src/mm/page_pt.c


Ignore:
Timestamp:
2010-05-24T18:57:31Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0095368
Parents:
666f492
Message:

major code revision

  • replace spinlocks taken with interrupts disabled with irq_spinlocks
  • change spacing (not indendation) to be tab-size independent
  • use unsigned integer types where appropriate (especially bit flags)
  • visual separation
  • remove argument names in function prototypes
  • string changes
  • correct some formating directives
  • replace various cryptic single-character variables (t, a, m, c, b, etc.) with proper identifiers (thread, task, timeout, as, itm, itc, etc.)
  • unify some assembler constructs
  • unused page table levels are now optimized out in compile time
  • replace several ints (with boolean semantics) with bools
  • use specifically sized types instead of generic types where appropriate (size_t, uint32_t, btree_key_t)
  • improve comments
  • split asserts with conjuction into multiple independent asserts
File:
1 edited

Legend:

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

    r666f492 rda1bafb  
    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 *as, uintptr_t page, uintptr_t frame, int flags);
    49 static void pt_mapping_remove(as_t *as, uintptr_t page);
    50 static pte_t *pt_mapping_find(as_t *as, uintptr_t page);
     48static void pt_mapping_insert(as_t *, uintptr_t, uintptr_t, unsigned int);
     49static void pt_mapping_remove(as_t *, uintptr_t);
     50static pte_t *pt_mapping_find(as_t *, uintptr_t);
    5151
    5252page_mapping_operations_t pt_mapping_operations = {
     
    6363 * The page table must be locked and interrupts must be disabled.
    6464 *
    65  * @param as Address space to wich page belongs.
    66  * @param page Virtual address of the page to be mapped.
     65 * @param as    Address space to wich page belongs.
     66 * @param page  Virtual address of the page to be mapped.
    6767 * @param frame Physical address of memory frame to which the mapping is done.
    6868 * @param flags Flags to be used for mapping.
    69  */
    70 void pt_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame, int flags)
     69 *
     70 */
     71void pt_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame,
     72    unsigned int flags)
    7173{
    72         pte_t *ptl0, *ptl1, *ptl2, *ptl3;
    73         pte_t *newpt;
    74 
    75         ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
    76 
     74        pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
     75       
    7776        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) {
    78                 newpt = (pte_t *)frame_alloc(PTL1_SIZE, FRAME_KA);
     77                pte_t *newpt = (pte_t *) frame_alloc(PTL1_SIZE, FRAME_KA);
    7978                memsetb(newpt, FRAME_SIZE << PTL1_SIZE, 0);
    8079                SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
    8180                SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
    8281        }
    83 
    84         ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
    85 
     82       
     83        pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
     84       
    8685        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) {
    87                 newpt = (pte_t *)frame_alloc(PTL2_SIZE, FRAME_KA);
     86                pte_t *newpt = (pte_t *) frame_alloc(PTL2_SIZE, FRAME_KA);
    8887                memsetb(newpt, FRAME_SIZE << PTL2_SIZE, 0);
    8988                SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
    9089                SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
    9190        }
    92 
    93         ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
    94 
     91       
     92        pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
     93       
    9594        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) {
    96                 newpt = (pte_t *)frame_alloc(PTL3_SIZE, FRAME_KA);
     95                pte_t *newpt = (pte_t *) frame_alloc(PTL3_SIZE, FRAME_KA);
    9796                memsetb(newpt, FRAME_SIZE << PTL3_SIZE, 0);
    9897                SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
    9998                SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
    10099        }
    101 
    102         ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
    103 
     100       
     101        pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
     102       
    104103        SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(page), frame);
    105104        SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags);
     
    116115 * The page table must be locked and interrupts must be disabled.
    117116 *
    118  * @param as Address space to wich page belongs.
     117 * @param as   Address space to wich page belongs.
    119118 * @param page Virtual address of the page to be demapped.
     119 *
    120120 */
    121121void pt_mapping_remove(as_t *as, uintptr_t page)
    122122{
    123         pte_t *ptl0, *ptl1, *ptl2, *ptl3;
    124         bool empty = true;
    125         int i;
    126 
    127123        /*
    128124         * First, remove the mapping, if it exists.
     125         *
    129126         */
    130 
    131         ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
    132 
     127       
     128        pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
    133129        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT)
    134130                return;
    135 
    136         ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
    137 
     131       
     132        pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
    138133        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT)
    139134                return;
    140 
    141         ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
    142 
     135       
     136        pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
    143137        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT)
    144138                return;
    145 
    146         ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
    147 
     139       
     140        pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
     141       
    148142        /* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */
    149143        memsetb(&ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0);
    150 
     144       
    151145        /*
    152146         * Second, free all empty tables along the way from PTL3 down to PTL0.
     147         *
    153148         */
    154149       
    155         /* check PTL3 */
     150        /* Check PTL3 */
     151        bool empty = true;
     152       
     153        unsigned int i;
    156154        for (i = 0; i < PTL3_ENTRIES; i++) {
    157155                if (PTE_VALID(&ptl3[i])) {
     
    160158                }
    161159        }
     160       
    162161        if (empty) {
    163162                /*
    164163                 * PTL3 is empty.
    165164                 * Release the frame and remove PTL3 pointer from preceding table.
     165                 *
    166166                 */
    167167                frame_free(KA2PA((uintptr_t) ptl3));
    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);
     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
    174175        } else {
    175176                /*
     
    177178                 * Therefore, there must be a path from PTL0 to PTL3 and
    178179                 * thus nothing to free in higher levels.
    179                  */
    180                 return;
    181         }
    182        
    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                         }
     180                 *
     181                 */
     182                return;
     183        }
     184       
     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;
    190191                }
    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);
     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       
     217        /* 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;
    201223                }
    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 
    212         /* check PTL1, empty is still true */
    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 
     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 */
    230236}
    231237
     
    236242 * The page table must be locked and interrupts must be disabled.
    237243 *
    238  * @param as Address space to which page belongs.
     244 * @param as   Address space to which page belongs.
    239245 * @param page Virtual page.
    240246 *
    241  * @return NULL if there is no such mapping; entry from PTL3 describing the mapping otherwise.
     247 * @return NULL if there is no such mapping; entry from PTL3 describing
     248 *         the mapping otherwise.
     249 *
    242250 */
    243251pte_t *pt_mapping_find(as_t *as, uintptr_t page)
    244252{
    245         pte_t *ptl0, *ptl1, *ptl2, *ptl3;
    246 
    247         ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
    248 
     253        pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
    249254        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT)
    250255                return NULL;
    251 
    252         ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
    253 
     256       
     257        pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
    254258        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT)
    255259                return NULL;
    256 
    257         ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
    258 
     260       
     261        pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
    259262        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT)
    260263                return NULL;
    261 
    262         ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
    263 
     264       
     265        pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
     266       
    264267        return &ptl3[PTL3_INDEX(page)];
    265268}
Note: See TracChangeset for help on using the changeset viewer.