Subversion Repositories HelenOS

Rev

Rev 2128 | Rev 2467 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2128 Rev 2465
Line 1... Line 1...
1
/*
1
/*
2
 * Copyright (c) 2003-2007 Jakub Jermar
2
 * Copyright (c) 2007 Pavel Jancik, Michal Kebrt
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
Line 28... Line 28...
28
 
28
 
29
/** @addtogroup arm32mm
29
/** @addtogroup arm32mm
30
 * @{
30
 * @{
31
 */
31
 */
32
/** @file
32
/** @file
-
 
33
 *  @brief Paging related declarations.
33
 */
34
 */
34
 
35
 
35
#ifndef KERN_arm32_PAGE_H_
36
#ifndef KERN_arm32_PAGE_H_
36
#define KERN_arm32_PAGE_H_
37
#define KERN_arm32_PAGE_H_
37
 
38
 
38
#include <arch/mm/frame.h>
39
#include <arch/mm/frame.h>
-
 
40
#include <mm/mm.h>
-
 
41
#include <arch/exception.h>
39
 
42
 
40
#define PAGE_WIDTH  FRAME_WIDTH
43
#define PAGE_WIDTH  FRAME_WIDTH
41
#define PAGE_SIZE   FRAME_SIZE
44
#define PAGE_SIZE   FRAME_SIZE
42
 
45
 
43
#define PAGE_COLOR_BITS 0           /* dummy */
46
#define PAGE_COLOR_BITS 0           /* dummy */
Line 50... Line 53...
50
#   define PA2KA(x) ((x) + 0x80000000)
53
#   define PA2KA(x) ((x) + 0x80000000)
51
#endif
54
#endif
52
 
55
 
53
#ifdef KERNEL
56
#ifdef KERNEL
54
 
57
 
55
#define PTL0_ENTRIES_ARCH   0   /* TODO */
58
#define PTL0_ENTRIES_ARCH   (2 << 12)   /* 4096 */
56
#define PTL1_ENTRIES_ARCH   0   /* TODO */
59
#define PTL1_ENTRIES_ARCH   0
57
#define PTL2_ENTRIES_ARCH   0   /* TODO */
60
#define PTL2_ENTRIES_ARCH   0
-
 
61
 
-
 
62
/* coarse page tables used (256 * 4 = 1KB per page) */
58
#define PTL3_ENTRIES_ARCH   0   /* TODO */
63
#define PTL3_ENTRIES_ARCH   (2 << 8)    /* 256 */
59
 
64
 
60
#define PTL0_INDEX_ARCH(vaddr)  0   /* TODO */ 
65
#define PTL0_SIZE_ARCH      FOUR_FRAMES
61
#define PTL1_INDEX_ARCH(vaddr)  0   /* TODO */
66
#define PTL1_SIZE_ARCH      0
62
#define PTL2_INDEX_ARCH(vaddr)  0   /* TODO */
67
#define PTL2_SIZE_ARCH      0
63
#define PTL3_INDEX_ARCH(vaddr)  0   /* TODO */
68
#define PTL3_SIZE_ARCH      ONE_FRAME
64
 
69
 
-
 
70
#define PTL0_INDEX_ARCH(vaddr)  (((vaddr) >> 20) & 0xfff)
-
 
71
#define PTL1_INDEX_ARCH(vaddr)  0
65
#define SET_PTL0_ADDRESS_ARCH(ptl0)
72
#define PTL2_INDEX_ARCH(vaddr)  0
-
 
73
#define PTL3_INDEX_ARCH(vaddr)  (((vaddr) >> 12) & 0x0ff)
66
 
74
 
67
#define GET_PTL1_ADDRESS_ARCH(ptl0, i)      0   /* TODO */
75
#define GET_PTL1_ADDRESS_ARCH(ptl0, i) \
-
 
76
    ((pte_t *) ((((pte_level0_t *)(ptl0))[(i)]).coarse_table_addr << 10))
68
#define GET_PTL2_ADDRESS_ARCH(ptl1, i)      0   /* TODO */
77
#define GET_PTL2_ADDRESS_ARCH(ptl1, i) \
-
 
78
    (ptl1)
69
#define GET_PTL3_ADDRESS_ARCH(ptl2, i)      0   /* TODO */
79
#define GET_PTL3_ADDRESS_ARCH(ptl2, i) \
-
 
80
    (ptl2)
70
#define GET_FRAME_ADDRESS_ARCH(ptl3, i)     0   /* TODO */
81
#define GET_FRAME_ADDRESS_ARCH(ptl3, i) \
-
 
82
    ((uintptr_t) ((((pte_level1_t *)(ptl3))[(i)]).frame_base_addr << 12))
71
 
83
 
-
 
84
#define SET_PTL0_ADDRESS_ARCH(ptl0) \
-
 
85
    (set_ptl0_addr((pte_level0_t *) (ptl0)))
72
#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a)   /* TODO */
86
#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a) \
-
 
87
    (((pte_level0_t *) (ptl0))[(i)].coarse_table_addr = (a) >> 10)
73
#define SET_PTL2_ADDRESS_ARCH(ptl1, i, a)   /* TODO */
88
#define SET_PTL2_ADDRESS_ARCH(ptl1, i, a)
74
#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a)   /* TODO */
89
#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a)
75
#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a)  /* TODO */
90
#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a) \
-
 
91
    (((pte_level1_t *) (ptl3))[(i)].frame_base_addr = (a) >> 12)
76
 
92
 
77
#define GET_PTL1_FLAGS_ARCH(ptl0, i)        0   /* TODO */
93
#define GET_PTL1_FLAGS_ARCH(ptl0, i) \
-
 
94
    get_pt_level0_flags((pte_level0_t *) (ptl0), (index_t) (i))
78
#define GET_PTL2_FLAGS_ARCH(ptl1, i)        0   /* TODO */
95
#define GET_PTL2_FLAGS_ARCH(ptl1, i) \
-
 
96
    PAGE_PRESENT
79
#define GET_PTL3_FLAGS_ARCH(ptl2, i)        0   /* TODO */
97
#define GET_PTL3_FLAGS_ARCH(ptl2, i) \
-
 
98
    PAGE_PRESENT
80
#define GET_FRAME_FLAGS_ARCH(ptl3, i)       0   /* TODO */
99
#define GET_FRAME_FLAGS_ARCH(ptl3, i) \
-
 
100
    get_pt_level1_flags((pte_level1_t *) (ptl3), (index_t) (i))
81
 
101
 
82
#define SET_PTL1_FLAGS_ARCH(ptl0, i, x)     /* TODO */
102
#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \
-
 
103
    set_pt_level0_flags((pte_level0_t *) (ptl0), (index_t) (i), (x))
83
#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)     /* TODO */
104
#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
84
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)     /* TODO */
105
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
85
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x)    /* TODO */
106
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
-
 
107
    set_pt_level1_flags((pte_level1_t *) (ptl3), (index_t) (i), (x))
86
 
108
 
87
#define PTE_VALID_ARCH(pte)         0   /* TODO */
109
#define PTE_VALID_ARCH(pte) \
-
 
110
    (*((uint32_t *) (pte)) != 0)
88
#define PTE_PRESENT_ARCH(pte)           0   /* TODO */
111
#define PTE_PRESENT_ARCH(pte) \
-
 
112
    (((pte_level0_t *) (pte))->descriptor_type != 0)
-
 
113
 
-
 
114
/* pte should point into ptl3 */
89
#define PTE_GET_FRAME_ARCH(pte)         0   /* TODO */
115
#define PTE_GET_FRAME_ARCH(pte) \
-
 
116
    (((pte_level1_t *) (pte))->frame_base_addr << FRAME_WIDTH)
-
 
117
 
-
 
118
/* pte should point into ptl3 */
90
#define PTE_WRITABLE_ARCH(pte)          0   /* TODO */
119
#define PTE_WRITABLE_ARCH(pte) \
-
 
120
    (((pte_level1_t *) (pte))->access_permission_0 == \
-
 
121
        PTE_AP_USER_RW_KERNEL_RW)
-
 
122
 
91
#define PTE_EXECUTABLE_ARCH(pte)        0   /* TODO */
123
#define PTE_EXECUTABLE_ARCH(pte) \
-
 
124
    1
92
 
125
 
93
#ifndef __ASM__
126
#ifndef __ASM__
94
 
127
 
-
 
128
/** Level 0 page table entry. */
95
#include <mm/mm.h>
129
typedef 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). */
-
 
145
typedef 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;
96
#include <arch/exception.h>
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
 */  
-
 
193
static 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
 */
-
 
208
static 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
 */
-
 
223
static inline int get_pt_level1_flags(pte_level1_t *pt, index_t i)
-
 
224
{
-
 
225
    pte_level1_t *p = &pt[i];
97
 
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
 */
98
static inline int get_pt_flags(pte_t *pt, index_t i)
248
static inline void set_pt_level0_flags(pte_level0_t *pt, index_t i, int flags)
99
{
249
{
100
    return 0;   /* TODO */
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
    }
101
}
263
}
102
 
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
 */  
103
static inline void set_pt_flags(pte_t *pt, index_t i, int flags)
276
static inline void set_pt_level1_flags(pte_level1_t *pt, index_t i, int flags)
104
{
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;
105
    /* TODO */
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;
106
    return;
305
        }
-
 
306
    }
107
}
307
}
108
 
308
 
-
 
309
 
109
extern void page_arch_init(void);
310
extern void page_arch_init(void);
110
 
311
 
-
 
312
 
111
#endif /* __ASM__ */
313
#endif /* __ASM__ */
112
 
314
 
113
#endif /* KERNEL */
315
#endif /* KERNEL */
114
 
316
 
115
#endif
317
#endif