Changeset 914e063 in mainline


Ignore:
Timestamp:
2012-03-12T19:50:20Z (12 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b99a5e8
Parents:
096d4a6b
Message:

arm32,mm: Add ARMv7 page table formats.

Location:
kernel/arch/arm32/include/mm
Files:
2 added
1 edited

Legend:

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

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