source: mainline/kernel/arch/sparc32/include/arch/mm/page.h@ ef9a2a8

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ef9a2a8 was ef9a2a8, checked in by Jakub Klama <jakub.klama@…>, 12 years ago

Introduce early MMU support in kernel. At current state, it
is possible to create initial kernel address space, map kernel
identity into it and take over MMU control. ASID FIFO support
should also work.

  • Property mode set to 100644
File size: 7.8 KB
Line 
1/*
2 * Copyright (c) 2010 Martin Decky
3 * Copyright (c) 2013 Jakub Klama
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup sparc32mm
31 * @{
32 */
33/** @file
34 */
35
36#ifndef KERN_sparc32_PAGE_H_
37#define KERN_sparc32_PAGE_H_
38
39#include <arch/mm/frame.h>
40#include <trace.h>
41
42#define PAGE_WIDTH FRAME_WIDTH
43#define PAGE_SIZE FRAME_SIZE
44
45#define KA2PA(x) (((uintptr_t) (x)) - UINT32_C(0x40000000))
46#define PA2KA(x) (((uintptr_t) (x)) + UINT32_C(0x40000000))
47
48#define PTE_ET_INVALID 0
49#define PTE_ET_DESCRIPTOR 1
50#define PTE_ET_ENTRY 2
51
52#define PTE_ACC_USER_RO_KERNEL_RO 0
53#define PTE_ACC_USER_RW_KERNEL_RW 1
54#define PTE_ACC_USER_RX_KERNEL_RX 2
55#define PTE_ACC_USER_RWX_KERNEL_RWX 3
56#define PTE_ACC_USER_XO_KERNEL_XO 4
57#define PTE_ACC_USER_RO_KERNEL_RW 5
58#define PTE_ACC_USER_NO_KERNEL_RX 6
59#define PTE_ACC_USER_NO_KERNEL_RWX 7
60
61/* Number of entries in each level. */
62#define PTL0_ENTRIES_ARCH 256
63#define PTL1_ENTRIES_ARCH 0
64#define PTL2_ENTRIES_ARCH 64
65#define PTL3_ENTRIES_ARCH 64
66
67/* Page table sizes for each level. */
68#define PTL0_SIZE_ARCH ONE_FRAME
69#define PTL1_SIZE_ARCH 0
70#define PTL2_SIZE_ARCH ONE_FRAME
71#define PTL3_SIZE_ARCH ONE_FRAME
72
73/* Macros calculating indices for each level. */
74#define PTL0_INDEX_ARCH(vaddr) (((vaddr) >> 24) & 0xffU)
75#define PTL1_INDEX_ARCH(vaddr) 0
76#define PTL2_INDEX_ARCH(vaddr) (((vaddr) >> 18) & 0x3fU)
77#define PTL3_INDEX_ARCH(vaddr) (((vaddr) >> 12) & 0x3fU)
78
79/* Get PTE address accessors for each level. */
80#define GET_PTL1_ADDRESS_ARCH(ptl0, i) \
81 ((pte_t *) ((((pte_t *) (ptl0))[(i)].frame_address) << 12))
82#define GET_PTL2_ADDRESS_ARCH(ptl1, i) \
83 KA2PA(ptl1)
84#define GET_PTL3_ADDRESS_ARCH(ptl2, i) \
85 ((pte_t *) ((((pte_t *) (ptl2))[(i)].frame_address) << 12))
86#define GET_FRAME_ADDRESS_ARCH(ptl3, i) \
87 ((uintptr_t) ((((pte_t *) (ptl3))[(i)].frame_address) << 12))
88
89/* Set PTE address accessors for each level. */
90#define SET_PTL0_ADDRESS_ARCH(ptl0)
91#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a) \
92 (((pte_t *) (ptl0))[(i)].frame_address = (a) >> 12)
93#define SET_PTL2_ADDRESS_ARCH(ptl1, i, a)
94#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a) \
95 (((pte_t *) (ptl2))[(i)].frame_address = (a) >> 12)
96#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a) \
97 (((pte_t *) (ptl3))[(i)].frame_address = (a) >> 12)
98
99/* Get PTE flags accessors for each level. */
100#define GET_PTL1_FLAGS_ARCH(ptl0, i) \
101 get_pt_flags((pte_t *) (ptl0), (size_t) (i))
102#define GET_PTL2_FLAGS_ARCH(ptl1, i) \
103 PAGE_PRESENT
104#define GET_PTL3_FLAGS_ARCH(ptl2, i) \
105 get_pt_flags((pte_t *) (ptl2), (size_t) (i))
106#define GET_FRAME_FLAGS_ARCH(ptl3, i) \
107 get_pt_flags((pte_t *) (ptl3), (size_t) (i))
108
109/* Set PTE flags accessors for each level. */
110#define SET_PTL1_FLAGS_ARCH(ptl0, i, x)
111#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
112#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
113#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
114 set_pte_flags((pte_t *) (ptl3), (size_t) (i), (x))
115
116/* Set PTE present bit accessors for each level. */
117#define SET_PTL1_PRESENT_ARCH(ptl0, i) \
118 set_ptd_present((pte_t *) (ptl0), (size_t) (i))
119#define SET_PTL2_PRESENT_ARCH(ptl1, i)
120#define SET_PTL3_PRESENT_ARCH(ptl2, i) \
121 set_ptd_present((pte_t *) (ptl2), (size_t) (i))
122#define SET_FRAME_PRESENT_ARCH(ptl3, i) \
123 set_pte_present((pte_t *) (ptl3), (size_t) (i))
124
125/* Macros for querying the last level entries. */
126#define PTE_VALID_ARCH(p) \
127 (*((uint32_t *) (p)) != 0)
128#define PTE_PRESENT_ARCH(p) \
129 ((p)->et != 0)
130#define PTE_GET_FRAME_ARCH(p) \
131 ((p)->frame_address << FRAME_WIDTH)
132#define PTE_WRITABLE_ARCH(p) \
133 pte_is_writeable(p)
134#define PTE_EXECUTABLE_ARCH(p) \
135 pte_is_executable(p)
136
137#include <mm/mm.h>
138#include <arch/interrupt.h>
139#include <typedefs.h>
140
141/** Page Table Descriptor. */
142typedef struct {
143 unsigned int table_pointer: 30;
144 unsigned int et: 2;
145} __attribute__((packed)) ptd_t;
146
147/** Page Table Entry. */
148typedef struct {
149 unsigned int frame_address: 24;
150 unsigned int cacheable: 1;
151 unsigned int modified: 1;
152 unsigned int referenced: 1;
153 unsigned int acc: 3;
154 unsigned int et: 2;
155} __attribute__((packed)) pte_t;
156
157NO_TRACE static inline void set_ptl0_addr(pte_t *pt)
158{
159}
160
161NO_TRACE static inline bool pte_is_writeable(pte_t *pt)
162{
163 return (
164 pt->acc == PTE_ACC_USER_RW_KERNEL_RW ||
165 pt->acc == PTE_ACC_USER_RWX_KERNEL_RWX ||
166 pt->acc == PTE_ACC_USER_RO_KERNEL_RW ||
167 pt->acc == PTE_ACC_USER_NO_KERNEL_RWX
168 );
169}
170
171NO_TRACE static inline bool pte_is_executable(pte_t *pt)
172{
173 return (
174 pt->acc != PTE_ACC_USER_RO_KERNEL_RO &&
175 pt->acc != PTE_ACC_USER_RW_KERNEL_RW &&
176 pt->acc != PTE_ACC_USER_RO_KERNEL_RW
177 );
178}
179
180NO_TRACE static inline unsigned int get_pt_flags(pte_t *pt, size_t i)
181 REQUIRES_ARRAY_MUTABLE(pt, PTL0_ENTRIES_ARCH)
182{
183 pte_t *p = &pt[i];
184
185 bool notpresent = p->et == 0;
186
187 return (
188 (p->cacheable << PAGE_CACHEABLE_SHIFT) |
189 (notpresent << PAGE_PRESENT_SHIFT) |
190 ((p->acc != PTE_ACC_USER_NO_KERNEL_RX && p->acc != PTE_ACC_USER_NO_KERNEL_RWX) << PAGE_USER_SHIFT) |
191 (1 << PAGE_READ_SHIFT) |
192 ((
193 p->acc == PTE_ACC_USER_RW_KERNEL_RW ||
194 p->acc == PTE_ACC_USER_RWX_KERNEL_RWX ||
195 p->acc == PTE_ACC_USER_RO_KERNEL_RW ||
196 p->acc == PTE_ACC_USER_NO_KERNEL_RWX
197 ) << PAGE_WRITE_SHIFT) |
198 ((
199 p->acc != PTE_ACC_USER_RO_KERNEL_RO &&
200 p->acc != PTE_ACC_USER_RW_KERNEL_RW &&
201 p->acc != PTE_ACC_USER_RO_KERNEL_RW
202 ) << PAGE_EXEC_SHIFT) |
203 (1 << PAGE_GLOBAL_SHIFT)
204 );
205}
206
207NO_TRACE static inline void set_ptd_flags(pte_t *pt, size_t i, int flags)
208 WRITES(ARRAY_RANGE(pt, PTL0_ENTRIES_ARCH))
209 REQUIRES_ARRAY_MUTABLE(pt, PTL0_ENTRIES_ARCH)
210{
211 pte_t *p = &pt[i];
212
213 p->et = (flags & PAGE_NOT_PRESENT)
214 ? PTE_ET_INVALID
215 : PTE_ET_DESCRIPTOR;
216}
217
218NO_TRACE static inline void set_pte_flags(pte_t *pt, size_t i, int flags)
219 WRITES(ARRAY_RANGE(pt, PTL0_ENTRIES_ARCH))
220 REQUIRES_ARRAY_MUTABLE(pt, PTL0_ENTRIES_ARCH)
221{
222 pte_t *p = &pt[i];
223
224 p->et = PTE_ET_ENTRY;
225 p->acc = PTE_ACC_USER_NO_KERNEL_RWX;
226
227 if (flags & PAGE_USER) {
228 if (flags & PAGE_READ)
229 p->acc = PTE_ACC_USER_RO_KERNEL_RW;
230 if (flags & PAGE_WRITE)
231 p->acc = PTE_ACC_USER_RW_KERNEL_RW;
232 }
233
234 if (flags & PAGE_NOT_PRESENT)
235 p->et = PTE_ET_INVALID;
236
237 p->cacheable = (flags & PAGE_CACHEABLE) != 0;
238}
239
240NO_TRACE static inline void set_ptd_present(pte_t *pt, size_t i)
241 WRITES(ARRAY_RANGE(pt, PTL0_ENTRIES_ARCH))
242 REQUIRES_ARRAY_MUTABLE(pt, PTL0_ENTRIES_ARCH)
243{
244 pte_t *p = &pt[i];
245
246 p->et = PTE_ET_DESCRIPTOR;
247}
248
249NO_TRACE static inline void set_pte_present(pte_t *pt, size_t i)
250 WRITES(ARRAY_RANGE(pt, PTL0_ENTRIES_ARCH))
251 REQUIRES_ARRAY_MUTABLE(pt, PTL0_ENTRIES_ARCH)
252{
253 pte_t *p = &pt[i];
254
255 p->et = PTE_ET_ENTRY;
256}
257
258extern void page_arch_init(void);
259extern void page_fault(unsigned int, istate_t *);
260
261#endif
262
263/** @}
264 */
Note: See TracBrowser for help on using the repository browser.