Allow the formal engine to perform a same-cycle result in the ALU
[soc.git] / src / soc / experiment / radix_walk_example.txt
1 ================ Radix Walk Example =================================
2 SPRN_PTCR = 0x10004 : PATB = 0x10, PATS = 0x4
3 =====================================================================
4 Memory Layout
5 =====================================================================
6 PARTITION_TABLE
7 0x10000 : PARTITION_TABLE_1 | PARTITION_TABLE_2
8 0xc0000000000030ad | 0x800000000100000b
9 HR=1 PATB_GR=1
10 RTS1=0x2 PRTB=0x1000
11 RPDB=0x300 PRTS=0xb
12 RTS2=0x5
13 RPDS=0xd
14
15 RADIX_ROOT
16 0x30000 : RADIX_ROOT_PTE | RADIX_ROOT_KERNEL_PTE
17 0x8000000000040009 | 0x8000000000040005
18 V = 1 | V = 1
19 L = 0 | L = 0
20 NLB = 0x400 | NLB = 0x400
21 NLS = 9 | NLS = 5
22
23 RADIX_SECOND_LEVEL
24 0x40000 : RADIX_SECOND_LEVEL_PTE | RADIX_SECOND_LEVEL_KERNEL_PTE
25 0xc000000000000187 | 0x8000000000050004
26 V = 1 | V = 1
27 L = 1 | L = 0
28 SW = 0 | NLB = 0x500
29 RPN = 0 | NLS = 5
30 R = 1
31 C = 1
32 ATT = 0
33 EAA 0x7
34
35 RADIX_THIRD_LEVEL
36 0x50000: RADIX_THIRD_LEVEL_KERNEL_PTE
37 0xc000000000000187
38 V = 1
39 L = 1
40 SW = 0
41 RPN = 0
42 R = 1
43 C = 1
44 ATT = 0
45 EAA = 0x7
46
47
48 PROCESS_TABLE:
49 0x1000000 : PROCESS_TABLE_1 | PROCESS_TABLE_2 //Hypervisor Kernel
50 0x40000000000300ac | 0x0
51 RTS1 = 0x2
52 RPDB = 0x300
53 RTS2 = 0x5
54 RPDS = 12
55
56 0x1000010 : PROCESS_TABLE_3 | PROCESS_TABLE_3 //Hypervisor Userspace
57 0x40000000000300ad | 0x0
58 RTS1 = 0x2
59 RPDB = 0x300
60 RTS2 = 0x5
61 RPDS = 13
62
63 ================== Example 1 : Hypervisor Userspace =======================
64 MSR[HV] = 1, MSR[PR] = 1
65 vaddr = 0x1000 = 0x0000000000001000
66
67 PTCR : PATB = 0x10 = Partition Table Base
68 PATS = 0x4 = Partition Table Size
69
70 Getting the Partition Table Entry (PATE0 and PATE1)
71
72 Partition table base address is obtained by left-shifting
73 PATB by 12 bits. Because the Partition table base is always aligned
74 to 4k which is also the minimum size of the partition table.
75
76 patb_addr = PATB << 12 = 0x10000
77
78 effLPID = 0 // HV=1
79
80 pate1_offset = 0 * 16 + 8 = 8 // Partition Table second word is PATE1
81 // for this effLPID
82
83 pate1_addr = patb_addr + pate1_offset = 0x10008 = PARTITION_TABLE_2
84 From PARTITION_TABLE_2
85 PRTB = 0x1000
86
87 Process Table Base address is obtained by left-shifting PRTB by 12
88 bits. Because the Process table is size aligned and at least is 4k.
89 prtb_addr = PRTB << 12 = 0x1000000
90
91 effPID = SPRN_PIDR = 1 // HV=1, PR=1, QUADRANT_0b00
92
93 prte0_offset = effPID * 16 = 16 //First double word in Process Table
94 //Indexed by effPID
95 prte0_addr = prtb_addr + prte0_offset = 0x1000010 = PROCESS_TABLE_3
96
97 ------------------ The Walk Begins Now --------------------
98 From PROCESS_TABLE_3
99 RPDB = 0x300
100 RPDS = 13
101 RTS = RTS1 << 3 | RTS2 = 0x2 << 3 | 5 = 1 << 4 + 5 = 21
102 totalSize = RTS + 31 = 21 + 31 = 52 = virtual address space used
103 by software
104
105 Root Level
106 --------------
107 nextLevelBase = RPDB << 8 = 0x30000
108 nextLevelSize = RPDS = 13
109
110 // Call the lower totalSize bits of vaddr as the useful bits.
111 // The upper nextLevelSize bits of these useful bits
112 // has the index into the Page Table Directory
113 // Each entry is 8 bytes.
114 shift = totalSize - nextLevelSize = 52 - 13 = 39
115 mask = (1 << nextLeveSize) - 1 = 0xFFF
116 index = (vaddr >> shift ) & mask = 0
117
118 entry_addr = nextLevelBase + index * 8 = 0x30000 + 0 = 0x30000 = RADIX_ROOT_PTE
119
120 From RADIX_ROOT_PTE
121 V = 1
122 L = 0.
123 NLB = 0x400
124 NLS = 9
125
126 So this is a directory. Hence obtain NLB and NLS
127
128 First Level
129 ----------------
130
131 // We no longer need the upper nextLevelSize bits
132 // of the useful bits. Discard them.
133 // Call remaining bits of vaddr as useful bits.
134 totalSize = totalSize - nextLevelSize = 52 - 13 = 39
135
136 //Recompute the new Page Directory Base and the Size
137 nextLevelBase = NLB >> 8 = 0x40000
138 nextLevelSize = NLS = 9
139
140 // The upper nextLevelSize bits of the useful bits of vaddr
141 // has the index into the Page Table Directory
142 // Each entry is 8 bytes.
143 shift = totalSize - nextLevelSize = 39 - 9 = 30
144 mask = (1 << nextLevelSize) - 1 = 0xFF
145 index = (vaddr >> shift) & mask = 0
146
147 entry_addr = nextlevelBase + index * 8 = 0x40000 = RADIX_SECOND_LEVEL
148 V = 1
149 L = 1
150 RPN = 0
151 This is a leaf node.
152
153 Second Level
154 ----------------
155
156 // We no longer need the upper nextLevelSize useful bits
157 // in the vaddr. Discard them. Call remaining bits of vaddr as useful
158 // bits. These bits will tell us precisely which location in the
159 // real page should we fetch the data from.
160 totalSize = totalSize - nextLevelSize = 39 - 9 = 30
161
162 //Compute the real page number base.
163 rpn_addr = (RPN << 12) = 0
164 mask = (1ULL << totalSize) - 1 = 0x000000001fffffff
165 rpn_mask = ~mask = 0xffffffffe0000000
166
167 phys_addr = (rpn_addr & rpn_mask) | (vaddr & mask)
168 = (0 & 0xffffffffe0000000) | (0x1000 & 0x1fffffff)
169 = 0x1000
170
171
172 Hence Virtual address = Physical Address.
173
174 ================== Example 2 : Hypervisor Kernel =======================
175 Example 2:
176 MSR[HV] = 1, MSR[PR] = 0
177 vaddr = 0xc000010800003000
178
179 PTCR : PATB = 0x10 = Partition Table Base (right shifted by 12)
180 PATS = 0x4 = Partition Table Size (add 12)
181
182 Getting the Partition Table Entry (PATE0 and PATE1)
183
184 Partition table base address is obtained by left-shifting
185 PATB by 12 bits. Because the Partition table base is always aligned
186 to 4k which is also the minimum size of the partition table.
187
188 patb_addr = PATB << 12 = 0x10000
189
190 effLPID = 0 // Hypervisor HV=1.
191
192 pate1_offset = 0 * 16 + 8 = 8 // Partition Table second word is PATE1
193 // for this effLPID
194
195 pate1_addr = patb_addr + pate1_offset = 0x10008 = PARTITION_TABLE_2
196 From PARTITION_TABLE_2
197 PRTB = 0x1000
198 prtb_addr = PRTB << 12 = 0x1000000
199
200 effPID = SPRN_PIDR = 0 // HV=1,PR=0, Quadrant 0b11 = Hypervisor Kernel
201 prte0_offset = effPID * 16 = 0 //First double word in Process Table
202 // Indexed by effPID
203
204 prte0_addr = prtb_addr + prte0_offset = 0x1000000 = PROCESS_TABLE_1
205
206 ------------------ The Walk Begins Now --------------------
207
208 From PROCESS_TABLE_1
209 RPDB = 0x30
210 RPDS = 12
211 RTS = RTS1 << 3 | RTS2 = 0x2 << 3 | 5 = 1 << 4 + 5 = 21
212 totalSize = RTS + 31 = 21 + 31 = 52 = virtual address space used
213 by software
214
215 Root Level
216 ----------------
217
218 nextLevelBase = RPDB << 12 = 0x30000
219 nextLevelSize = RPDS = 12
220
221 // The lower totalSize bits of vaddr are the useful bits.
222 // The upper nextLevelSize bits these useful bits
223 // has the index into the Page Table Directory
224 // Each entry is 8 bytes.
225 shift = totalSize - nextLevelSize = 52 - 12 = 40
226 mask = (1 << nextLeveSize) - 1 = 0x1FFF
227 index = (vaddr >> shift ) & mask = (0xc000010800003000 >> 40) & 0xFFF
228 = (0b1100 0000 0000 0000 0000 0001) & 0xFFF
229 = (0xc000001) & 0xFFF
230 = 0x001
231
232 entry_addr = nextLevelBase + index * 8
233 = 0x30000 + 1*8 = 0x30008
234 = RADIX_ROOT_KERNEL_PTE
235 V = 1
236 L = 0
237 NLB = 0x400
238 NLS = 5
239
240 This a directory. Hence obtain NLB and NLS
241
242 First Level
243 ----------------
244
245 // We no longer need the upper nextLevelSize of the useful bits
246 // in the vaddr. Discard them. Call remaining bits of vaddr as useful bits.
247 totalSize = totalSize - nextLevelSize = 52 - 12 = 40
248
249 //Recompute the new Page Directory Base and the Size
250 nextLevelBase = NLB >> 8 = 0x40000
251 nextLevelSize = NLS = 5
252
253
254 // The upper nextLevelSize bits of the useful bits
255 // has the index into the Page Table Directory
256 // Each entry is 8 bytes.
257 shift = totalSize - nextLevelSize = 40 - 5 = 35
258 mask = (1 << nextLeveSize) - 1 = 0x1F
259 index = (vaddr >> shift ) & mask = (0xc000010800003000 >> 35) & 0x1F
260 = (0b0001 1000 0000 0000 0000 0000 0010 0001) & 0x1F
261 = (0x18000021) & 0x1F
262 = 0x01
263
264 entry_addr = nextLevelBase + index * 8
265 = 0x40000 + 1*8 = 0x40008
266 = RADIX_SECOND_LEVEL_KERNEL_PTE
267
268 V = 1
269 L = 0
270 NLB = 0x500
271 NLS = 5
272
273 Again this is a directory. Hence using the NLB and NLS go to the next
274 level
275
276 Second Level
277 ----------------
278
279 // We no longer need the upper nextLevelSize bits of the useful bits.
280 //in the vaddr. Discard them. Call remaining bits of vaddr as useful bits.
281 totalSize = totalSize - nextLevelSize = 40 - 5 = 35
282
283 //Recompute the new Page Directory Base and the Size
284 nextLevelBase = NLB >> 8 = 0x50000
285 nextLevelSize = NLS = 5
286
287 // The upper nextLevelSize bits of vaddr
288 // has the index into the Page Table Directory
289 // Each entry is 8 bytes.
290 shift = totalSize - nextLevelSize = 35 - 5 = 30
291 mask = (1 << nextLeveSize) - 1 = 0x1F
292
293 index = (vaddr >> shift ) & mask = (0xc000010800003000 >> 30) & 0xF
294 = (0b0001 1000 0000 0000 0000 0000 0010 0001 0000) & 0xF
295 = (0x18000210) & 0xF
296 = 0x0
297
298 entry_addr = nextLevelBase + index * 8
299 = 0x50000 + 0*8 = 0x50000
300 = RADIX_THIRD_LEVEL_KERNEL_PTE
301
302 V=1
303 L=1
304 RPN=0
305
306 This is the leaf level
307
308 Third Level
309 ----------------
310
311 // We no longer need the upper nextLevelSize useful bits.
312 // in the vaddr. Discard them. Call remaining bits of vaddr as useful
313 // bits. These bits will tell us precisely which location in the
314 // real page should we fetch the data from.
315 totalSize = totalSize - nextLevelSize = 35 - 5 = 30
316
317 //Compute the real page number base.
318 rpn_addr = (RPN << 12) = 0
319 mask = (1ULL << totalSize) - 1 = 0x000000001fffffff
320 rpn_mask = ~mask = 0xffffffffe0000000
321
322 phys_addr = (rpn_addr & rpn_mask) | (vaddr & mask)
323 = (0 & 0xffffffffe0000000) | (0xc000010800003000 & 0x1fffffff)
324 = 0x3000
325
326 Hence Virtual address 0xc000010800003000 is mapped to Physical Address
327 0x3000.