Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/arm32/include/mm/page.h

    r936b72e r0d8269b  
    4646#define PAGE_SIZE       FRAME_SIZE
    4747
    48 #ifdef MACHINE_beagleboardxm
    49 #ifndef __ASM__
    50 #       define KA2PA(x) ((uintptr_t) (x))
    51 #       define PA2KA(x) ((uintptr_t) (x))
    52 #else
    53 #       define KA2PA(x) (x)
    54 #       define PA2KA(x) (x)
    55 #endif
    56 #else
    5748#ifndef __ASM__
    5849#       define KA2PA(x) (((uintptr_t) (x)) - 0x80000000)
     
    6253#       define PA2KA(x) ((x) + 0x80000000)
    6354#endif
    64 #endif
    6555
    6656/* Number of entries in each level. */
    67 #define PTL0_ENTRIES_ARCH       (1 << 12)       /* 4096 */
    68 #define PTL1_ENTRIES_ARCH       0
    69 #define PTL2_ENTRIES_ARCH       0
     57#define PTL0_ENTRIES_ARCH       (1 << 12)       /* 4096 */
     58#define PTL1_ENTRIES_ARCH       0
     59#define PTL2_ENTRIES_ARCH       0
    7060/* coarse page tables used (256 * 4 = 1KB per page) */
    71 #define PTL3_ENTRIES_ARCH       (1 << 8)        /* 256 */
     61#define PTL3_ENTRIES_ARCH       (1 << 8)        /* 256 */
    7262
    7363/* Page table sizes for each level. */
    74 #define PTL0_SIZE_ARCH          FOUR_FRAMES
    75 #define PTL1_SIZE_ARCH          0
    76 #define PTL2_SIZE_ARCH          0
    77 #define PTL3_SIZE_ARCH          ONE_FRAME
     64#define PTL0_SIZE_ARCH          FOUR_FRAMES
     65#define PTL1_SIZE_ARCH          0
     66#define PTL2_SIZE_ARCH          0
     67#define PTL3_SIZE_ARCH          ONE_FRAME
    7868
    7969/* Macros calculating indices into page tables for each level. */
    80 #define PTL0_INDEX_ARCH(vaddr)  (((vaddr) >> 20) & 0xfff)
    81 #define PTL1_INDEX_ARCH(vaddr)  0
    82 #define PTL2_INDEX_ARCH(vaddr)  0
    83 #define PTL3_INDEX_ARCH(vaddr)  (((vaddr) >> 12) & 0x0ff)
     70#define PTL0_INDEX_ARCH(vaddr)  (((vaddr) >> 20) & 0xfff)
     71#define PTL1_INDEX_ARCH(vaddr)  0
     72#define PTL2_INDEX_ARCH(vaddr)  0
     73#define PTL3_INDEX_ARCH(vaddr)  (((vaddr) >> 12) & 0x0ff)
    8474
    8575/* Get PTE address accessors for each level. */
    8676#define GET_PTL1_ADDRESS_ARCH(ptl0, i) \
    87         ((pte_t *) ((((pte_t *)(ptl0))[(i)].l0).coarse_table_addr << 10))
     77        ((pte_t *) ((((pte_t *)(ptl0))[(i)].l0).coarse_table_addr << 10))
    8878#define GET_PTL2_ADDRESS_ARCH(ptl1, i) \
    89         (ptl1)
     79        (ptl1)
    9080#define GET_PTL3_ADDRESS_ARCH(ptl2, i) \
    91         (ptl2)
     81        (ptl2)
    9282#define GET_FRAME_ADDRESS_ARCH(ptl3, i) \
    93         ((uintptr_t) ((((pte_t *)(ptl3))[(i)].l1).frame_base_addr << 12))
     83        ((uintptr_t) ((((pte_t *)(ptl3))[(i)].l1).frame_base_addr << 12))
    9484
    9585/* Set PTE address accessors for each level. */
    9686#define SET_PTL0_ADDRESS_ARCH(ptl0) \
    97         (set_ptl0_addr((pte_t *) (ptl0)))
     87        (set_ptl0_addr((pte_t *) (ptl0)))
    9888#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a) \
    99         (((pte_t *) (ptl0))[(i)].l0.coarse_table_addr = (a) >> 10)
     89        (((pte_t *) (ptl0))[(i)].l0.coarse_table_addr = (a) >> 10)
    10090#define SET_PTL2_ADDRESS_ARCH(ptl1, i, a)
    10191#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a)
    10292#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a) \
    103         (((pte_t *) (ptl3))[(i)].l1.frame_base_addr = (a) >> 12)
     93        (((pte_t *) (ptl3))[(i)].l1.frame_base_addr = (a) >> 12)
    10494
    10595/* Get PTE flags accessors for each level. */
    10696#define GET_PTL1_FLAGS_ARCH(ptl0, i) \
    107         get_pt_level0_flags((pte_t *) (ptl0), (size_t) (i))
     97        get_pt_level0_flags((pte_t *) (ptl0), (size_t) (i))
    10898#define GET_PTL2_FLAGS_ARCH(ptl1, i) \
    109         PAGE_PRESENT
     99        PAGE_PRESENT
    110100#define GET_PTL3_FLAGS_ARCH(ptl2, i) \
    111         PAGE_PRESENT
     101        PAGE_PRESENT
    112102#define GET_FRAME_FLAGS_ARCH(ptl3, i) \
    113         get_pt_level1_flags((pte_t *) (ptl3), (size_t) (i))
     103        get_pt_level1_flags((pte_t *) (ptl3), (size_t) (i))
    114104
    115105/* Set PTE flags accessors for each level. */
    116106#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \
    117         set_pt_level0_flags((pte_t *) (ptl0), (size_t) (i), (x))
     107        set_pt_level0_flags((pte_t *) (ptl0), (size_t) (i), (x))
    118108#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
    119109#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
     
    129119        set_pt_level1_present((pte_t *) (ptl3), (size_t) (i))
    130120
    131 #if defined(PROCESSOR_armv6) | defined(PROCESSOR_armv7_a)
    132 #include "page_armv6.h"
    133 #elif defined(PROCESSOR_armv4) | defined(PROCESSOR_armv5)
    134 #include "page_armv4.h"
    135 #else
    136 #error "Unsupported architecture"
     121/* Macros for querying the last-level PTE entries. */
     122#define PTE_VALID_ARCH(pte) \
     123        (*((uint32_t *) (pte)) != 0)
     124#define PTE_PRESENT_ARCH(pte) \
     125        (((pte_t *) (pte))->l0.descriptor_type != 0)
     126#define PTE_GET_FRAME_ARCH(pte) \
     127        (((pte_t *) (pte))->l1.frame_base_addr << FRAME_WIDTH)
     128#define PTE_WRITABLE_ARCH(pte) \
     129        (((pte_t *) (pte))->l1.access_permission_0 == PTE_AP_USER_RW_KERNEL_RW)
     130#define PTE_EXECUTABLE_ARCH(pte) \
     131        1
     132
     133#ifndef __ASM__
     134
     135/** Level 0 page table entry. */
     136typedef struct {
     137        /* 0b01 for coarse tables, see below for details */
     138        unsigned descriptor_type : 2;
     139        unsigned impl_specific : 3;
     140        unsigned domain : 4;
     141        unsigned should_be_zero : 1;
     142
     143        /* Pointer to the coarse 2nd level page table (holding entries for small
     144         * (4KB) or large (64KB) pages. ARM also supports fine 2nd level page
     145         * tables that may hold even tiny pages (1KB) but they are bigger (4KB
     146         * per table in comparison with 1KB per the coarse table)
     147         */
     148        unsigned coarse_table_addr : 22;
     149} ATTRIBUTE_PACKED pte_level0_t;
     150
     151/** Level 1 page table entry (small (4KB) pages used). */
     152typedef struct {
     153
     154        /* 0b10 for small pages */
     155        unsigned descriptor_type : 2;
     156        unsigned bufferable : 1;
     157        unsigned cacheable : 1;
     158
     159        /* access permissions for each of 4 subparts of a page
     160         * (for each 1KB when small pages used */
     161        unsigned access_permission_0 : 2;
     162        unsigned access_permission_1 : 2;
     163        unsigned access_permission_2 : 2;
     164        unsigned access_permission_3 : 2;
     165        unsigned frame_base_addr : 20;
     166} ATTRIBUTE_PACKED pte_level1_t;
     167
     168typedef union {
     169        pte_level0_t l0;
     170        pte_level1_t l1;
     171} pte_t;
     172
     173/* Level 1 page tables access permissions */
     174
     175/** User mode: no access, privileged mode: no access. */
     176#define PTE_AP_USER_NO_KERNEL_NO        0
     177
     178/** User mode: no access, privileged mode: read/write. */
     179#define PTE_AP_USER_NO_KERNEL_RW        1
     180
     181/** User mode: read only, privileged mode: read/write. */
     182#define PTE_AP_USER_RO_KERNEL_RW        2
     183
     184/** User mode: read/write, privileged mode: read/write. */
     185#define PTE_AP_USER_RW_KERNEL_RW        3
     186
     187
     188/* pte_level0_t and pte_level1_t descriptor_type flags */
     189
     190/** pte_level0_t and pte_level1_t "not present" flag (used in descriptor_type). */
     191#define PTE_DESCRIPTOR_NOT_PRESENT      0
     192
     193/** pte_level0_t coarse page table flag (used in descriptor_type). */
     194#define PTE_DESCRIPTOR_COARSE_TABLE     1
     195
     196/** pte_level1_t small page table flag (used in descriptor type). */
     197#define PTE_DESCRIPTOR_SMALL_PAGE       2
     198
     199
     200/** Sets the address of level 0 page table.
     201 *
     202 * @param pt Pointer to the page table to set.
     203 *
     204 */
     205NO_TRACE static inline void set_ptl0_addr(pte_t *pt)
     206{
     207        asm volatile (
     208                "mcr p15, 0, %[pt], c2, c0, 0\n"
     209                :: [pt] "r" (pt)
     210        );
     211}
     212
     213
     214/** Returns level 0 page table entry flags.
     215 *
     216 * @param pt Level 0 page table.
     217 * @param i  Index of the entry to return.
     218 *
     219 */
     220NO_TRACE static inline int get_pt_level0_flags(pte_t *pt, size_t i)
     221{
     222        pte_level0_t *p = &pt[i].l0;
     223        int np = (p->descriptor_type == PTE_DESCRIPTOR_NOT_PRESENT);
     224       
     225        return (np << PAGE_PRESENT_SHIFT) | (1 << PAGE_USER_SHIFT) |
     226            (1 << PAGE_READ_SHIFT) | (1 << PAGE_WRITE_SHIFT) |
     227            (1 << PAGE_EXEC_SHIFT) | (1 << PAGE_CACHEABLE_SHIFT);
     228}
     229
     230/** Returns level 1 page table entry flags.
     231 *
     232 * @param pt Level 1 page table.
     233 * @param i  Index of the entry to return.
     234 *
     235 */
     236NO_TRACE static inline int get_pt_level1_flags(pte_t *pt, size_t i)
     237{
     238        pte_level1_t *p = &pt[i].l1;
     239       
     240        int dt = p->descriptor_type;
     241        int ap = p->access_permission_0;
     242       
     243        return ((dt == PTE_DESCRIPTOR_NOT_PRESENT) << PAGE_PRESENT_SHIFT) |
     244            ((ap == PTE_AP_USER_RO_KERNEL_RW) << PAGE_READ_SHIFT) |
     245            ((ap == PTE_AP_USER_RW_KERNEL_RW) << PAGE_READ_SHIFT) |
     246            ((ap == PTE_AP_USER_RW_KERNEL_RW) << PAGE_WRITE_SHIFT) |
     247            ((ap != PTE_AP_USER_NO_KERNEL_RW) << PAGE_USER_SHIFT) |
     248            ((ap == PTE_AP_USER_NO_KERNEL_RW) << PAGE_READ_SHIFT) |
     249            ((ap == PTE_AP_USER_NO_KERNEL_RW) << PAGE_WRITE_SHIFT) |
     250            (1 << PAGE_EXEC_SHIFT) |
     251            (p->bufferable << PAGE_CACHEABLE);
     252}
     253
     254/** Sets flags of level 0 page table entry.
     255 *
     256 * @param pt    level 0 page table
     257 * @param i     index of the entry to be changed
     258 * @param flags new flags
     259 *
     260 */
     261NO_TRACE static inline void set_pt_level0_flags(pte_t *pt, size_t i, int flags)
     262{
     263        pte_level0_t *p = &pt[i].l0;
     264       
     265        if (flags & PAGE_NOT_PRESENT) {
     266                p->descriptor_type = PTE_DESCRIPTOR_NOT_PRESENT;
     267                /*
     268                 * Ensures that the entry will be recognized as valid when
     269                 * PTE_VALID_ARCH applied.
     270                 */
     271                p->should_be_zero = 1;
     272        } else {
     273                p->descriptor_type = PTE_DESCRIPTOR_COARSE_TABLE;
     274                p->should_be_zero = 0;
     275        }
     276}
     277
     278NO_TRACE static inline void set_pt_level0_present(pte_t *pt, size_t i)
     279{
     280        pte_level0_t *p = &pt[i].l0;
     281
     282        p->should_be_zero = 0;
     283        write_barrier();
     284        p->descriptor_type = PTE_DESCRIPTOR_COARSE_TABLE;
     285}
     286
     287/** Sets flags of level 1 page table entry.
     288 *
     289 * We use same access rights for the whole page. When page
     290 * is not preset we store 1 in acess_rigts_3 so that at least
     291 * one bit is 1 (to mark correct page entry, see #PAGE_VALID_ARCH).
     292 *
     293 * @param pt    Level 1 page table.
     294 * @param i     Index of the entry to be changed.
     295 * @param flags New flags.
     296 *
     297 */
     298NO_TRACE static inline void set_pt_level1_flags(pte_t *pt, size_t i, int flags)
     299{
     300        pte_level1_t *p = &pt[i].l1;
     301       
     302        if (flags & PAGE_NOT_PRESENT)
     303                p->descriptor_type = PTE_DESCRIPTOR_NOT_PRESENT;
     304        else
     305                p->descriptor_type = PTE_DESCRIPTOR_SMALL_PAGE;
     306       
     307        p->cacheable = p->bufferable = (flags & PAGE_CACHEABLE) != 0;
     308       
     309        /* default access permission */
     310        p->access_permission_0 = p->access_permission_1 =
     311            p->access_permission_2 = p->access_permission_3 =
     312            PTE_AP_USER_NO_KERNEL_RW;
     313       
     314        if (flags & PAGE_USER)  {
     315                if (flags & PAGE_READ) {
     316                        p->access_permission_0 = p->access_permission_1 =
     317                            p->access_permission_2 = p->access_permission_3 =
     318                            PTE_AP_USER_RO_KERNEL_RW;
     319                }
     320                if (flags & PAGE_WRITE) {
     321                        p->access_permission_0 = p->access_permission_1 =
     322                            p->access_permission_2 = p->access_permission_3 =
     323                            PTE_AP_USER_RW_KERNEL_RW;
     324                }
     325        }
     326}
     327
     328NO_TRACE static inline void set_pt_level1_present(pte_t *pt, size_t i)
     329{
     330        pte_level1_t *p = &pt[i].l1;
     331
     332        p->descriptor_type = PTE_DESCRIPTOR_SMALL_PAGE;
     333}
     334       
     335extern void page_arch_init(void);
     336
     337#endif /* __ASM__ */
     338
    137339#endif
    138340
    139 #endif
    140 
    141341/** @}
    142342 */
Note: See TracChangeset for help on using the changeset viewer.