1 ================ Radix Walk Example =================================
2 SPRN_PTCR = 0x10004 : PATB = 0x10, PATS = 0x4
3 =====================================================================
5 =====================================================================
7 0x10000 : PARTITION_TABLE_1 | PARTITION_TABLE_2
8 0xc0000000000030ad | 0x800000000100000b
16 0x30000 : RADIX_ROOT_PTE | RADIX_ROOT_KERNEL_PTE
17 0x8000000000040009 | 0x8000000000040005
20 NLB = 0x400 | NLB = 0x400
24 0x40000 : RADIX_SECOND_LEVEL_PTE | RADIX_SECOND_LEVEL_KERNEL_PTE
25 0xc000000000000187 | 0x8000000000050004
36 0x50000: RADIX_THIRD_LEVEL_KERNEL_PTE
49 0x1000000 : PROCESS_TABLE_1 | PROCESS_TABLE_2 //Hypervisor Kernel
50 0x40000000000300ac | 0x0
56 PROCESS_TABLE_3 | PROCESS_TABLE_3 //Hypervisor Userspace
57 0x40000000000300ad | 0x0
63 ================== Example 1 : Hypervisor Userspace =======================
64 MSR[HV] = 1, MSR[PR] = 1
65 vaddr = 0x1000 = 0x0000000000001000
67 PTCR : PATB = 0x10 = Partition Table Base
68 PATS = 0x4 = Partition Table Size
70 Getting the Partition Table Entry (PATE0 and PATE1)
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.
76 patb_addr = PATB << 12 = 0x10000
80 pate1_offset = 0 * 16 + 8 = 8 // Partition Table second word is PATE1
83 pate1_addr = patb_addr + pate1_offset = 0x10008 = PARTITION_TABLE_2
84 From PARTITION_TABLE_2
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
91 effPID = SPRN_PIDR = 1 // HV=1, PR=1, QUADRANT_0b00
93 prte0_offset = effPID * 16 = 16 //First double word in Process Table
95 prte0_addr = prtb_addr + prte0_offset = 0x1000010 = PROCESS_TABLE_3
97 ------------------ The Walk Begins Now --------------------
101 RTS = RTS1 << 3 | RTS2 = 0x2 << 3 | 5 = 1 << 4 + 5 = 21
102 totalSize = RTS + 31 = 21 + 31 = 52 = virtual address space used
107 nextLevelBase = RPDB << 8 = 0x30000
108 nextLevelSize = RPDS = 13
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
118 entry_addr = nextLevelBase + index * 8 = 0x30000 + 0 = 0x30000 = RADIX_ROOT_PTE
126 So this is a directory. Hence obtain NLB and NLS
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
136 //Recompute the new Page Directory Base and the Size
137 nextLevelBase = NLB >> 8 = 0x40000
138 nextLevelSize = NLS = 9
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
147 entry_addr = nextlevelBase + index * 8 = 0x40000 = RADIX_SECOND_LEVEL
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
162 //Compute the real page number base.
163 rpn_addr = (RPN << 12) = 0
164 mask = (1ULL << totalSize) - 1 = 0x000000001fffffff
165 rpn_mask = ~mask = 0xffffffffe0000000
167 phys_addr = (rpn_addr & rpn_mask) | (vaddr & mask)
168 = (0 & 0xffffffffe0000000) | (0x1000 & 0x1fffffff)
172 Hence Virtual address = Physical Address.
174 ================== Example 2 : Hypervisor Kernel =======================
176 MSR[HV] = 1, MSR[PR] = 0
177 vaddr = 0xc000010800003000
179 PTCR : PATB = 0x10 = Partition Table Base (right shifted by 12)
180 PATS = 0x4 = Partition Table Size (add 12)
182 Getting the Partition Table Entry (PATE0 and PATE1)
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.
188 patb_addr = PATB << 12 = 0x10000
190 effLPID = 0 // Hypervisor HV=1.
192 pate1_offset = 0 * 16 + 8 = 8 // Partition Table second word is PATE1
195 pate1_addr = patb_addr + pate1_offset = 0x10008 = PARTITION_TABLE_2
196 From PARTITION_TABLE_2
198 prtb_addr = PRTB << 12 = 0x1000000
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
204 prte0_addr = prtb_addr + prte0_offset = 0x1000000 = PROCESS_TABLE_1
206 ------------------ The Walk Begins Now --------------------
211 RTS = RTS1 << 3 | RTS2 = 0x2 << 3 | 5 = 1 << 4 + 5 = 21
212 totalSize = RTS + 31 = 21 + 31 = 52 = virtual address space used
218 nextLevelBase = RPDB << 12 = 0x30000
219 nextLevelSize = RPDS = 12
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
232 entry_addr = nextLevelBase + index * 8
233 = 0x30000 + 1*8 = 0x30008
234 = RADIX_ROOT_KERNEL_PTE
240 This a directory. Hence obtain NLB and NLS
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
249 //Recompute the new Page Directory Base and the Size
250 nextLevelBase = NLB >> 8 = 0x40000
251 nextLevelSize = NLS = 5
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
264 entry_addr = nextLevelBase + index * 8
265 = 0x40000 + 1*8 = 0x40008
266 = RADIX_SECOND_LEVEL_KERNEL_PTE
273 Again this is a directory. Hence using the NLB and NLS go to the next
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
283 //Recompute the new Page Directory Base and the Size
284 nextLevelBase = NLB >> 8 = 0x50000
285 nextLevelSize = NLS = 5
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
293 index = (vaddr >> shift ) & mask = (0xc000010800003000 >> 30) & 0xF
294 = (0b0001 1000 0000 0000 0000 0000 0010 0001 0000) & 0xF
298 entry_addr = nextLevelBase + index * 8
299 = 0x50000 + 0*8 = 0x50000
300 = RADIX_THIRD_LEVEL_KERNEL_PTE
306 This is the leaf level
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
317 //Compute the real page number base.
318 rpn_addr = (RPN << 12) = 0
319 mask = (1ULL << totalSize) - 1 = 0x000000001fffffff
320 rpn_mask = ~mask = 0xffffffffe0000000
322 phys_addr = (rpn_addr & rpn_mask) | (vaddr & mask)
323 = (0 & 0xffffffffe0000000) | (0xc000010800003000 & 0x1fffffff)
326 Hence Virtual address 0xc000010800003000 is mapped to Physical Address