1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
|
Memory management for CRIS/MMU
------------------------------
HISTORY:
$Log: README.mm,v $
Revision 1.1 2001/12/17 13:59:27 bjornw
Initial revision
Revision 1.1 2000/07/10 16:25:21 bjornw
Initial revision
Revision 1.4 2000/01/17 02:31:59 bjornw
Added discussion of paging and VM.
Revision 1.3 1999/12/03 16:43:23 hp
Blurb about that the 3.5G-limitation is not a MMU limitation
Revision 1.2 1999/12/03 16:04:21 hp
Picky comment about not mapping the first page
Revision 1.1 1999/12/03 15:41:30 bjornw
First version of CRIS/MMU memory layout specification.
------------------------------
See the ETRAX-NG HSDD for reference.
We use the page-size of 8 kbytes, as opposed to the i386 page-size of 4 kbytes.
The MMU can, apart from the normal mapping of pages, also do a top-level
segmentation of the kernel memory space. We use this feature to avoid having
to use page-tables to map the physical memory into the kernel's address
space. We also use it to keep the user-mode virtual mapping in the same
map during kernel-mode, so that the kernel easily can access the corresponding
user-mode process' data.
As a comparison, the Linux/i386 2.0 puts the kernel and physical RAM at
address 0, overlapping with the user-mode virtual space, so that descriptor
registers are needed for each memory access to specify which MMU space to
map through. That changed in 2.2, putting the kernel/physical RAM at
0xc0000000, to co-exist with the user-mode mapping. We will do something
quite similar, but with the additional complexity of having to map the
internal chip I/O registers and the flash memory area (including SRAM
and peripherial chip-selets).
The kernel-mode segmentation map:
------------------------ ------------------------
FFFFFFFF| | => cached | |
| kernel seg_f | flash | |
F0000000|______________________| | |
EFFFFFFF| | => uncached | |
| kernel seg_e | flash | |
E0000000|______________________| | DRAM |
DFFFFFFF| | paged to any | Un-cached |
| kernel seg_d | =======> | |
D0000000|______________________| | |
CFFFFFFF| | | |
| kernel seg_c |==\ | |
C0000000|______________________| \ |______________________|
BFFFFFFF| | uncached | |
| kernel seg_b |=====\=========>| Registers |
B0000000|______________________| \c |______________________|
AFFFFFFF| | \a | |
| | \c | FLASH/SRAM/Peripheral|
| | \h |______________________|
| | \e | |
| | \d | |
| kernel seg_0 - seg_a | \==>| DRAM |
| | | Cached |
| | paged to any | |
| | =======> |______________________|
| | | |
| | | Illegal |
| | |______________________|
| | | |
| | | FLASH/SRAM/Peripheral|
00000000|______________________| |______________________|
In user-mode it looks the same except that only the space 0-AFFFFFFF is
available. Therefore, in this model, the virtual address space per process
is limited to 0xb0000000 bytes (minus 8192 bytes, since the first page,
0..8191, is never mapped, in order to trap NULL references).
It also means that the total physical RAM that can be mapped is 256 MB
(kseg_c above). More RAM can be mapped by choosing a different segmentation
and shrinking the user-mode memory space.
The MMU can map all 4 GB in user mode, but doing that would mean that a
few extra instructions would be needed for each access to user mode
memory.
The kernel needs access to both cached and uncached flash. Uncached is
necessary because of the special write/erase sequences. Also, the
peripherial chip-selects are decoded from that region.
The kernel also needs its own virtual memory space. That is kseg_d. It
is used by the vmalloc() kernel function to allocate virtual contiguous
chunks of memory not possible using the normal kmalloc physical RAM
allocator.
The setting of the actual MMU control registers to use this layout would
be something like this:
R_MMU_KSEG = ( ( seg_f, seg ) | // Flash cached
( seg_e, seg ) | // Flash uncached
( seg_d, page ) | // kernel vmalloc area
( seg_c, seg ) | // kernel linear segment
( seg_b, seg ) | // kernel linear segment
( seg_a, page ) |
( seg_9, page ) |
( seg_8, page ) |
( seg_7, page ) |
( seg_6, page ) |
( seg_5, page ) |
( seg_4, page ) |
( seg_3, page ) |
( seg_2, page ) |
( seg_1, page ) |
( seg_0, page ) );
R_MMU_KBASE_HI = ( ( base_f, 0x0 ) | // flash/sram/periph cached
( base_e, 0x8 ) | // flash/sram/periph uncached
( base_d, 0x0 ) | // don't care
( base_c, 0x4 ) | // physical RAM cached area
( base_b, 0xb ) | // uncached on-chip registers
( base_a, 0x0 ) | // don't care
( base_9, 0x0 ) | // don't care
( base_8, 0x0 ) ); // don't care
R_MMU_KBASE_LO = ( ( base_7, 0x0 ) | // don't care
( base_6, 0x0 ) | // don't care
( base_5, 0x0 ) | // don't care
( base_4, 0x0 ) | // don't care
( base_3, 0x0 ) | // don't care
( base_2, 0x0 ) | // don't care
( base_1, 0x0 ) | // don't care
( base_0, 0x0 ) ); // don't care
NOTE: while setting up the MMU, we run in a non-mapped mode in the DRAM (0x40
segment) and need to setup the seg_4 to a
|