Changeset 6b781c0 in mainline for kernel/arch/arm32/include/mm/page.h


Ignore:
Timestamp:
2007-06-08T15:02:49Z (18 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c03ee1c
Parents:
3ee8a075
Message:

Merge arm32 into trunk.

File:
1 edited

Legend:

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

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