Home Home > GIT Browse
summaryrefslogtreecommitdiff
blob: db10250df6be66fc019e135604f761d9c947951c (plain)
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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
				 =================================
				 FR451 MMU LINUX MEMORY MANAGEMENT
				 =================================

============
MMU HARDWARE
============

FR451 MMU Linux puts the MMU into EDAT mode whilst running. This means that it uses both the SAT
registers and the DAT TLB to perform address translation.

There are 8 IAMLR/IAMPR register pairs and 16 DAMLR/DAMPR register pairs for SAT mode.

In DAT mode, there is also a TLB organised in cache format as 64 lines x 2 ways. Each line spans a
16KB range of addresses, but can match a larger region.


===========================
MEMORY MANAGEMENT REGISTERS
===========================

Certain control registers are used by the kernel memory management routines:

	REGISTERS		USAGE
	======================	==================================================
	IAMR0, DAMR0		Kernel image and data mappings
	IAMR1, DAMR1		First-chance TLB lookup mapping
	DAMR2			Page attachment for cache flush by page
	DAMR3			Current PGD mapping
	SCR0, DAMR4		Instruction TLB PGE/PTD cache
	SCR1, DAMR5		Data TLB PGE/PTD cache
	DAMR6-10		kmap_atomic() mappings
	DAMR11			I/O mapping
	CXNR			mm_struct context ID
	TTBR			Page directory (PGD) pointer (physical address)


=====================
GENERAL MEMORY LAYOUT
=====================

The physical memory layout is as follows:

  PHYSICAL ADDRESS	CONTROLLER	DEVICE
  ===================	==============	=======================================
  00000000 - BFFFFFFF	SDRAM		SDRAM area
  E0000000 - EFFFFFFF	L-BUS CS2#	VDK SLBUS/PCI window
  F0000000 - F0FFFFFF	L-BUS CS5#	MB93493 CSC area (DAV daughter board)
  F1000000 - F1FFFFFF	L-BUS CS7#	(CB70 CPU-card PCMCIA port I/O space)
  FC000000 - FC0FFFFF	L-BUS CS1#	VDK MB86943 config space
  FC100000 - FC1FFFFF	L-BUS CS6#	DM9000 NIC I/O space
  FC200000 - FC2FFFFF	L-BUS CS3#	MB93493 CSR area (DAV daughter board)
  FD000000 - FDFFFFFF	L-BUS CS4#	(CB70 CPU-card extra flash space)
  FE000000 - FEFFFFFF			Internal CPU peripherals
  FF000000 - FF1FFFFF	L-BUS CS0#	Flash 1
  FF200000 - FF3FFFFF	L-BUS CS0#	Flash 2
  FFC00000 - FFC0001F	L-BUS CS0#	FPGA

The virtual memory layout is:

  VIRTUAL ADDRESS    PHYSICAL	TRANSLATOR	FLAGS	SIZE	OCCUPATION
  =================  ========	==============	=======	=======	===================================
  00004000-BFFFFFFF  various	TLB,xAMR1	D-N-??V	3GB	Userspace
  C0000000-CFFFFFFF  00000000	xAMPR0		-L-S--V	256MB	Kernel image and data
  D0000000-D7FFFFFF  various	TLB,xAMR1	D-NS??V	128MB	vmalloc area
  D8000000-DBFFFFFF  various	TLB,xAMR1	D-NS??V	64MB	kmap() area
  DC000000-DCFFFFFF  various	TLB			1MB	Secondary kmap_atomic() frame
  DD000000-DD27FFFF  various	DAMR			160KB	Primary kmap_atomic() frame
  DD040000			DAMR2/IAMR2	-L-S--V	page	Page cache flush attachment point
  DD080000			DAMR3		-L-SC-V	page	Page Directory (PGD)
  DD0C0000			DAMR4		-L-SC-V	page	Cached insn TLB Page Table lookup
  DD100000			DAMR5		-L-SC-V	page	Cached data TLB Page Table lookup
  DD140000			DAMR6		-L-S--V	page	kmap_atomic(KM_BOUNCE_READ)
  DD180000			DAMR7		-L-S--V	page	kmap_atomic(KM_SKB_SUNRPC_DATA)
  DD1C0000			DAMR8		-L-S--V	page	kmap_atomic(KM_SKB_DATA_SOFTIRQ)
  DD200000			DAMR9		-L-S--V	page	kmap_atomic(KM_USER0)
  DD240000			DAMR10		-L-S--V	page	kmap_atomic(KM_USER1)
  E0000000-FFFFFFFF  E0000000	DAMR11		-L-SC-V	512MB	I/O region

IAMPR1 and DAMPR1 are used as an extension to the TLB.


====================
KMAP AND KMAP_ATOMIC
====================

To access pages in the page cache (which may not be directly accessible if highmem is available),
the kernel calls kmap(), does the access and then calls kunmap(); or it calls kmap_atomic(), does
the access and then calls kunmap_atomic().

kmap() creates an attachment between an arbitrary inaccessible page and a range of virtual
addresses by installing a PTE in a special page table. The kernel can then access this page as it
wills. When it's finished, the kernel calls kunmap() to clear the PTE.

kmap_atomic() does something slightly different. In the interests of speed, it chooses one of two
strategies:

 (1) If possible, kmap_atomic() attaches the requested page to one of DAMPR5 through DAMPR10
     register pairs; and the matching kunmap_atomic() clears the DAMPR. This makes high memory
     support really fast as there's no need to flush the TLB or modify the page tables. The DAMLR
     registers being used for this are preset during boot and don't change over the lifetime of the
     process. There's a direct mapping between the first few kmap_atomic() types, DAMR number and
     virtual address slot.

     However, there are more kmap_atomic() types defined than there are DAMR registers available,
     so we fall back to:

 (2) kmap_atomic() uses a slot in the secondary frame (determined by the type parameter), and then
     locks an entry in the TLB to translate that slot to the specified page. The number of slots is
     obviously limited, and their positions are controlled such that each slot is matched by a
     different line in the TLB. kunmap() ejects the entry from the TLB.

Note that the first three kmap atomic types are really just declared as placeholders. The DAMPR
registers involved are actually modified directly.

Also note that kmap() itself may sleep, kmap_atomic() may never sleep and both always succeed;
furthermore, a driver using kmap() may sleep before calling kunmap(), but may not sleep before
calling kunmap_atomic() if it had previously called kmap_atomic().


===============================
USING MORE THAN 256MB OF MEMORY
===============================

The kernel cannot access more than 256MB of memory directly. The physical layout, however, permits
up to 3GB of SDRAM (possibly 3.25GB) to be made available. By using CONFIG_HIGHMEM, the kernel can
allow userspace (by way of page tables) and itself (by way of kmap) to deal with the memory
allocation.

External devices can, of course, still DMA to and from all of the SDRAM, even if the kernel can't
see it directly. The kernel translates page references into real addresses for communicating to the
devices.


===================
PAGE TABLE TOPOLOGY
===================

The page tables are arranged in 2-layer format. There is a middle layer (PMD) that would be used in
3-layer format tables but that is folded into the top layer (PGD) and so consumes no extra memory
or processing power.

  +------+     PGD    PMD
  | TTBR |--->+-------------------+
  +------+    |      |      : STE |
              | PGE0 | PME0 : STE |
              |      |      : STE |
              +-------------------+              Page Table
              |      |      : STE -------------->+--------+ +0x0000
              | PGE1 | PME0 : STE -----------+   | PTE0   |
              |      |      : STE -------+   |   +--------+
              +-------------------+      |   |   | PTE63  |
              |      |      : STE |      |   +-->+--------+ +0x0100
              | PGE2 | PME0 : STE |      |       | PTE64  |
              |      |      : STE |      |       +--------+
              +-------------------+      |       | PTE127 |
              |      |      : STE |      +------>+--------+ +0x0200
              | PGE3 | PME0 : STE |              | PTE128 |
              |      |      : STE |              +--------+
              +-------------------+              | PTE191 |
                                                 +--------+ +0x0300

Each Page Directory (PGD) is 16KB (page size) in size and is divided into 64 entries (PGEs). Each
PGE contains one Page Mid Directory (PMD).

Each PMD is 256 bytes in size and contains a single entry (PME). Each PME holds 64 FR451 MMU
segment table entries of 4 bytes apiece. Each PME "points to" a page table. In practice, each STE
points to a subset of the page table, the first to PT+0x0000, the second to PT+0x0100, the third to
PT+0x200, and so on.

Each PGE and PME covers 64MB of the total virtual address space.

Each Page Table (PTD) is 16KB (page size) in size, and is divided into 4096 entries (PTEs). Each
entry can point to one 16KB page. In practice, each Linux page table is subdivided into 64 FR451
MMU page tables. But they are all grouped together to make management easier, in particular rmap
support is then trivial.

Grouping page tables in this fashion makes PGE caching in SCR0/SCR1 more efficient because the
coverage of the cached item is greater.

Page tables for the vmalloc area are allocated at boot time and shared between all mm_structs.


=================
USER SPACE LAYOUT
=================

For MMU capable Linux, the regions userspace code are allowed to access are kept entirely separate
from those dedicated to the kernel:

	VIRTUAL ADDRESS    SIZE   PURPOSE
	=================  =====  ===================================
	00000000-00003fff  4KB    NULL pointer access trap
	00004000-01ffffff  ~32MB  lower mmap space (grows up)
	02000000-021fffff  2MB    Stack space (grows down from top)
	02200000-nnnnnnnn         Executable mapping
        nnnnnnnn-                 brk space (grows up)
	        -bfffffff         upper mmap space (grows down)

This is so arranged so as to make best use of the 16KB page tables and the way in which PGEs/PMEs
are cached by the TLB handler. The lower mmap space is filled first, and then the upper mmap space
is filled.


===============================
GDB-STUB MMU DEBUGGING SERVICES
===============================

The gdb-stub included in this kernel provides a number of services to aid in the debugging of MMU
related kernel services:

 (*) Every time the kernel stops, certain state information is dumped into __debug_mmu. This
     variable is defined in arch/frv/kernel/gdb-stub.c. Note that the gdbinit file in this
     directory has some useful macros for dealing with this.

     (*) __debug_mmu.tlb[]

	 This receives the current TLB contents. This can be viewed with the _tlb GDB macro:

		(gdb) _tlb
		tlb[0x00]: 01000005 00718203  01000002 00718203
		tlb[0x01]: 01004002 006d4201  01004005 006d4203
		tlb[0x02]: 01008002 006d0201  01008006 00004200
		tlb[0x03]: 0100c006 007f4202  0100c002 0064c202
		tlb[0x04]: 01110005 00774201  01110002 00774201
		tlb[0x05]: 01114005 00770201  01114002 00770201
		tlb[0x06]: 01118002 0076c201  01118005 0076c201
		...
		tlb[0x3d]: 010f4002 00790200  001f4002 0054ca02
		tlb[0x3e]: 010f8005 0078c201  010f8002 0078c201
		tlb[0x3f]: 001fc002 0056ca01  001fc005 00538a01

     (*) __debug_mmu.iamr[]
     (*) __debug_mmu.damr[]

	 These receive the current IAMR and DAMR contents. These can be viewed with the _amr
	 GDB macro:

		(gdb) _amr
		AMRx           DAMR                    IAMR
		====   =====================   =====================
		amr0 : L:c0000000 P:00000cb9 : L:c0000000 P:000004b9
		amr1 : L:01070005 P:006f9203 : L:0102c005 P:006a1201
		amr2 : L:d8d00000 P:00000000 : L:d8d00000 P:00000000
		amr3 : L:d8d04000 P:00534c0d : L:00000000 P:00000000
		amr4 : L:d8d08000 P:00554c0d : L:00000000 P:00000000
		amr5 : L:d8d0c000 P:00554c0d : L:00000000 P:00000000
		amr6 : L:d8d10000 P:00000000 : L:00000000 P:00000000
		amr7 : L:d8d14000 P:00000000 : L:00000000 P:00000000
		amr8 : L:d8d18000 P:00000000
		amr9 : L:d8d1c000 P:00000000
		amr10: L:d8d20000 P:00000000
		amr11: L:e0000000 P:e0000ccd

 (*) The current task's page directory is bound to DAMR3.

     This can be viewed with the _pgd GDB macro:

	(gdb) _pgd
	$3 = {{pge = {{ste = {0x554001, 0x554101, 0x554201, 0x554301, 0x554401,
		  0x554501, 0x554601, 0x554701, 0x554801, 0x554901, 0x554a01,
		  0x554b01, 0x554c01, 0x554d01, 0x554e01, 0x554f01, 0x555001,
		  0x555101, 0x555201, 0x555301, 0x555401, 0x555501, 0x555601,
		  0x555701, 0x555801, 0x555901, 0x555a01, 0x555b01, 0x555c01,
		  0x555d01, 0x555e01, 0x555f01, 0x556001, 0x556101, 0x556201,
		  0x556301, 0x556401, 0x556501, 0x556601, 0x556701, 0x556801,
		  0x556901, 0x556a01, 0x556b01, 0x556c01, 0x556d01, 0x556e01,
		  0x556f01, 0x557001, 0x557101, 0x557201, 0x557301, 0x557401,
		  0x557501, 0x557601, 0x557701, 0x557801, 0x557901, 0x557a01,
		  0x557b01, 0x557c01, 0x557d01, 0x557e01, 0x557f01}}}}, {pge = {{
		ste = {0x0 <repeats 64 times>}}}} <repeats 51 times>, {pge = {{ste = {
		  0x248001, 0x248101, 0x248201, 0x248301, 0x248401, 0x248501,
		  0x248601, 0x248701, 0x248801, 0x248901, 0x248a01, 0x248b01,
		  0x248c01, 0x248d01, 0x248e01, 0x248f01, 0x249001, 0x249101,
		  0x249201, 0x249301, 0x249401, 0x249501, 0x249601, 0x249701,
		  0x249801, 0x249901, 0x249a01, 0x249b01, 0x249c01, 0x249d01,
		  0x249e01, 0x249f01, 0x24a001, 0x24a101, 0x24a201, 0x24a301,
		  0x24a401, 0x24a501, 0x24a601, 0x24a701, 0x24a801, 0x24a901,
		  0x24aa01, 0x24ab01, 0x24ac01, 0x24ad01, 0x24ae01, 0x24af01,
		  0x24b001, 0x24b101, 0x24b201, 0x24b301, 0x24b401, 0x24b501,
		  0x24b601, 0x24b701, 0x24b801, 0x24b901, 0x24ba01, 0x24bb01,
		  0x24bc01, 0x24bd01, 0x24be01, 0x24bf01}}}}, {pge = {{ste = {
		  0x0 <repeats 64 times>}}}} <repeats 11 times>}

 (*) The PTD last used by the instruction TLB miss handler is attached to DAMR4.
 (*) The PTD last used by the data TLB miss handler is attached to DAMR5.

     These can be viewed with the _ptd_i and _ptd_d GDB macros:

	(gdb) _ptd_d
	$5 = {{pte = 0x0} <repeats 127 times>, {pte = 0x539b01}, {
	    pte = 0x0} <repeats 896 times>, {pte = 0x719303}, {pte = 0x6d5303}, {
	    pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {
	    pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x6a1303}, {
	    pte = 0x0} <repeats 12 times>, {pte = 0x709303}, {pte = 0x0}, {pte = 0x0},
	  {pte = 0x6fd303}, {pte = 0x6f9303}, {pte = 0x6f5303}, {pte = 0x0}, {
	    pte = 0x6ed303}, {pte = 0x531b01}, {pte = 0x50db01}, {
	    pte = 0x0} <repeats 13 times>, {pte = 0x5303}, {pte = 0x7f5303}, {
	    pte = 0x509b01}, {pte = 0x505b01}, {pte = 0x7c9303}, {pte = 0x7b9303}, {
	    pte = 0x7b5303}, {pte = 0x7b1303}, {pte = 0x7ad303}, {pte = 0x0}, {
	    pte = 0x0}, {pte = 0x7a1303}, {pte = 0x0}, {pte = 0x795303}, {pte = 0x0}, {
	    pte = 0x78d303}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {
	    pte = 0x0}, {pte = 0x775303}, {pte = 0x771303}, {pte = 0x76d303}, {
	    pte = 0x0}, {pte = 0x765303}, {pte = 0x7c5303}, {pte = 0x501b01}, {
	    pte = 0x4f1b01}, {pte = 0x4edb01}, {pte = 0x0}, {pte = 0x4f9b01}, {
	    pte = 0x4fdb01}, {pte = 0x0} <repeats 2992 times>}