1 /*
2  * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3  *
4  * SPDX-License-Identifier: GPL-2.0-only
5  */
6 
7 #include <config.h>
8 
9 #ifdef CONFIG_DEBUG_BUILD
10 
11 #include <arch/machine/capdl.h>
12 #include <string.h>
13 #include <kernel/cspace.h>
14 
get_tcb_sp(tcb_t * tcb)15 word_t get_tcb_sp(tcb_t *tcb)
16 {
17     return tcb->tcbArch.tcbContext.registers[RSP];
18 }
19 
20 #ifdef CONFIG_PRINTING
21 
22 static void obj_frame_print_attrs(paddr_t paddr, word_t page_size);
23 static void _cap_frame_print_attrs_vptr(word_t vptr, vspace_root_t *vspace);
24 static void cap_frame_print_attrs_vptr(word_t vptr, cap_t vspace);
25 static void obj_asidpool_print_attrs(cap_t asid_cap);
26 static void cap_frame_print_attrs_pdpt(pdpte_t *pdptSlot);
27 static void cap_frame_print_attrs_pd(pde_t *pdSlot);
28 static void cap_frame_print_attrs_pt(pte_t *ptSlot);
29 static void cap_frame_print_attrs_impl(word_t super_user, word_t read_write, word_t cache_disabled, word_t xd);
30 
31 /* use when only have access to pte of frames */
cap_frame_print_attrs_pdpt(pdpte_t * pdptSlot)32 static void cap_frame_print_attrs_pdpt(pdpte_t *pdptSlot)
33 {
34     cap_frame_print_attrs_impl(pdpte_pdpte_1g_ptr_get_super_user(pdptSlot),
35                                pdpte_pdpte_1g_ptr_get_read_write(pdptSlot),
36                                pdpte_pdpte_1g_ptr_get_cache_disabled(pdptSlot),
37                                pdpte_pdpte_1g_ptr_get_xd(pdptSlot));
38 }
cap_frame_print_attrs_pd(pde_t * pdSlot)39 static void cap_frame_print_attrs_pd(pde_t *pdSlot)
40 {
41     cap_frame_print_attrs_impl(pde_pde_large_ptr_get_super_user(pdSlot),
42                                pde_pde_large_ptr_get_read_write(pdSlot),
43                                pde_pde_large_ptr_get_cache_disabled(pdSlot),
44                                pde_pde_large_ptr_get_xd(pdSlot));
45 }
46 
cap_frame_print_attrs_pt(pte_t * ptSlot)47 static void cap_frame_print_attrs_pt(pte_t *ptSlot)
48 {
49     cap_frame_print_attrs_impl(pte_ptr_get_super_user(ptSlot),
50                                pte_ptr_get_read_write(ptSlot),
51                                pte_ptr_get_cache_disabled(ptSlot),
52                                pte_ptr_get_xd(ptSlot));
53 }
54 
cap_frame_print_attrs_impl(word_t super_user,word_t read_write,word_t cache_disabled,word_t xd)55 static void cap_frame_print_attrs_impl(word_t super_user, word_t read_write, word_t cache_disabled, word_t xd)
56 {
57     printf("(");
58 
59     /* rights */
60     if (read_write) {
61         printf("RW");
62     } else if (super_user) {
63         printf("R");
64     }
65 
66     if (!xd) {
67         printf("X");
68     }
69 
70     /* asid, mapping */
71 
72     if (cache_disabled) {
73         printf(", uncached");
74     }
75 
76     printf(")\n");
77 }
78 
obj_frame_print_attrs(paddr_t paddr,word_t page_size)79 static void obj_frame_print_attrs(paddr_t paddr, word_t page_size)
80 {
81     printf("(");
82 
83     /* VM size */
84     switch (page_size) {
85     case seL4_HugePageBits:
86         printf("1G");
87         break;
88     case seL4_LargePageBits:
89         printf("2M");
90         break;
91     case seL4_PageBits:
92         printf("4k");
93         break;
94     }
95 
96     printf(", paddr: 0x%p)\n", (void *)paddr);
97 }
98 
x86_64_obj_pt_print_slots(pde_t * pdSlot)99 static void x86_64_obj_pt_print_slots(pde_t *pdSlot)
100 {
101     paddr_t paddr;
102     word_t page_size;
103     pte_t *pt = paddr_to_pptr(pde_pde_pt_ptr_get_pt_base_address(pdSlot));
104 
105     for (word_t i = 0; i < BIT(PT_INDEX_OFFSET + PT_INDEX_BITS); i += (1UL << PT_INDEX_OFFSET)) {
106         pte_t *ptSlot = pt + GET_PT_INDEX(i);
107 
108         if (pte_ptr_get_present(ptSlot)) {
109             paddr = pte_ptr_get_page_base_address(ptSlot);
110             page_size = seL4_PageBits;
111             printf("frame_%p_%04lu = frame ", ptSlot, GET_PT_INDEX(i));
112             obj_frame_print_attrs(paddr, page_size);
113         }
114     }
115 }
116 
x86_64_obj_pd_print_slots(pdpte_t * pdptSlot)117 static void x86_64_obj_pd_print_slots(pdpte_t *pdptSlot)
118 {
119     paddr_t paddr;
120     word_t page_size;
121     pde_t *pd = paddr_to_pptr(pdpte_pdpte_pd_ptr_get_pd_base_address(pdptSlot));
122 
123     for (word_t i = 0; i < BIT(PD_INDEX_OFFSET + PD_INDEX_BITS); i += (1UL << PD_INDEX_OFFSET)) {
124         pde_t *pdSlot = pd + GET_PD_INDEX(i);
125 
126         if ((pde_ptr_get_page_size(pdSlot) == pde_pde_large) && pde_pde_large_ptr_get_present(pdSlot)) {
127             paddr = pde_pde_large_ptr_get_page_base_address(pdSlot);
128             page_size = seL4_LargePageBits;
129 
130             printf("frame_%p_%04lu = frame ", pdSlot, GET_PD_INDEX(i));
131             obj_frame_print_attrs(paddr, page_size);
132 
133         } else if (pde_pde_pt_ptr_get_present(pdSlot)) {
134             printf("pt_%p_%04lu = pt\n", pdSlot, GET_PD_INDEX(i));
135             x86_64_obj_pt_print_slots(pdSlot);
136         }
137     }
138 }
139 
x86_64_obj_pdpt_print_slots(pml4e_t * pml4Slot)140 static void x86_64_obj_pdpt_print_slots(pml4e_t *pml4Slot)
141 {
142     paddr_t paddr;
143     word_t page_size;
144     pdpte_t *pdpt = paddr_to_pptr(pml4e_ptr_get_pdpt_base_address(pml4Slot));
145 
146     for (word_t i = 0; i < BIT(PDPT_INDEX_OFFSET + PDPT_INDEX_BITS); i += (1UL << PDPT_INDEX_OFFSET)) {
147         pdpte_t *pdptSlot = pdpt + GET_PDPT_INDEX(i);
148 
149         if (pdpte_ptr_get_page_size(pdptSlot) == pdpte_pdpte_1g &&
150             pdpte_pdpte_1g_ptr_get_present(pdptSlot)) {
151             paddr = pdpte_pdpte_1g_ptr_get_page_base_address(pdptSlot);
152             page_size = seL4_HugePageBits;
153 
154             printf("frame_%p_%04lu = frame ", pdptSlot, GET_PDPT_INDEX(i));
155             obj_frame_print_attrs(paddr, page_size);
156 
157         } else if (pdpte_pdpte_pd_ptr_get_present(pdptSlot)) {
158             printf("pd_%p_%04lu = pd\n", pdptSlot, GET_PDPT_INDEX(i));
159             x86_64_obj_pd_print_slots(pdptSlot);
160         }
161     }
162 }
163 
x86_64_obj_pml4_print_slots(pml4e_t * pml4)164 static void x86_64_obj_pml4_print_slots(pml4e_t *pml4)
165 {
166     for (word_t i = 0; i < BIT(PML4_INDEX_OFFSET + PML4_INDEX_BITS); i += (1UL << PML4_INDEX_OFFSET)) {
167         pml4e_t *pml4Slot = lookupPML4Slot(pml4, i);
168         if (pml4e_ptr_get_present(pml4Slot)) {
169             printf("pdpt_%p_%04lu = pdpt\n", pml4Slot, GET_PML4_INDEX(i));
170             x86_64_obj_pdpt_print_slots(pml4Slot);
171         }
172     }
173 }
174 
obj_tcb_print_vtable(tcb_t * tcb)175 void obj_tcb_print_vtable(tcb_t *tcb)
176 {
177     /* levels: PML4 -> PDPT -> PD -> PT */
178     if (isValidVTableRoot(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap) && !seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap)) {
179         pml4e_t *pml4 = PML4E_PTR(cap_pml4_cap_get_capPML4BasePtr(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap));
180         add_to_seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
181         printf("%p_pd = pml4\n", pml4);
182         x86_64_obj_pml4_print_slots(pml4);
183     }
184 }
185 
186 /* use when only have access to vptr of frames */
_cap_frame_print_attrs_vptr(word_t vptr,vspace_root_t * vspace)187 static void _cap_frame_print_attrs_vptr(word_t vptr, vspace_root_t *vspace)
188 {
189     lookupPDPTSlot_ret_t pdptSlot = lookupPDPTSlot(vspace, vptr);
190     lookupPTSlot_ret_t ptSlot;
191     lookupPDSlot_ret_t pdSlot;
192 
193     if (pdptSlot.status == EXCEPTION_NONE &&
194         pdpte_ptr_get_page_size(pdptSlot.pdptSlot) == pdpte_pdpte_1g &&
195         pdpte_pdpte_1g_ptr_get_present(pdptSlot.pdptSlot)) {
196         printf("frame_%p_%04lu ", pdptSlot.pdptSlot, GET_PDPT_INDEX(vptr));
197         cap_frame_print_attrs_pdpt(pdptSlot.pdptSlot);
198     } else {
199         pdSlot = lookupPDSlot(vspace, vptr);
200         if (pdSlot.status == EXCEPTION_NONE &&
201             ((pde_ptr_get_page_size(pdSlot.pdSlot) == pde_pde_large) &&
202              pde_pde_large_ptr_get_present(pdSlot.pdSlot))) {
203             printf("frame_%p_%04lu ", pdSlot.pdSlot, GET_PD_INDEX(vptr));
204             cap_frame_print_attrs_pd(pdSlot.pdSlot);
205         } else {
206             ptSlot = lookupPTSlot(vspace, vptr);
207             assert(ptSlot.status == EXCEPTION_NONE && pte_ptr_get_present(ptSlot.ptSlot));
208             printf("frame_%p_%04lu ", ptSlot.ptSlot, GET_PT_INDEX(vptr));
209             cap_frame_print_attrs_pt(ptSlot.ptSlot);
210         }
211     }
212 }
213 
cap_frame_print_attrs_vptr(word_t vptr,cap_t vspace)214 static void cap_frame_print_attrs_vptr(word_t vptr, cap_t vspace)
215 {
216     asid_t asid = cap_pml4_cap_get_capPML4MappedASID(vspace);
217     findVSpaceForASID_ret_t find_ret = findVSpaceForASID(asid);
218     _cap_frame_print_attrs_vptr(vptr, find_ret.vspace_root);
219 }
220 
print_cap_arch(cap_t cap)221 void print_cap_arch(cap_t cap)
222 {
223     switch (cap_get_capType(cap)) {
224     /* arch specific caps */
225     case cap_page_table_cap: {
226         asid_t asid = cap_page_table_cap_get_capPTMappedASID(cap);
227         findVSpaceForASID_ret_t find_ret = findVSpaceForASID(asid);
228         vptr_t vptr = cap_page_table_cap_get_capPTMappedAddress(cap);
229         if (asid) {
230             printf("pt_%p_%04lu (asid: %lu)\n",
231                    lookupPDSlot(find_ret.vspace_root, vptr).pdSlot, GET_PD_INDEX(vptr), (long unsigned int)asid);
232         } else {
233             printf("pt_%p_%04lu\n", lookupPDSlot(find_ret.vspace_root, vptr).pdSlot, GET_PD_INDEX(vptr));
234         }
235         break;
236     }
237     case cap_page_directory_cap: {
238         asid_t asid = cap_page_directory_cap_get_capPDMappedASID(cap);
239         findVSpaceForASID_ret_t find_ret = findVSpaceForASID(asid);
240         vptr_t vptr = cap_page_directory_cap_get_capPDMappedAddress(cap);
241         if (asid) {
242             printf("pd_%p_%04lu (asid: %lu)\n",
243                    lookupPDPTSlot(find_ret.vspace_root, vptr).pdptSlot, GET_PDPT_INDEX(vptr), (long unsigned int)asid);
244         } else {
245             printf("pd_%p_%04lu\n", lookupPDPTSlot(find_ret.vspace_root, vptr).pdptSlot, GET_PDPT_INDEX(vptr));
246         }
247         break;
248     }
249     case cap_pdpt_cap: {
250         asid_t asid = cap_pdpt_cap_get_capPDPTMappedASID(cap);
251         findVSpaceForASID_ret_t find_ret = findVSpaceForASID(asid);
252         vptr_t vptr = cap_pdpt_cap_get_capPDPTMappedAddress(cap);
253         if (asid) {
254             printf("pdpt_%p_%04lu (asid: %lu)\n",
255                    lookupPML4Slot(find_ret.vspace_root, vptr), GET_PML4_INDEX(vptr), (long unsigned int)asid);
256         } else {
257             printf("pdpt_%p_%04lu\n", lookupPML4Slot(find_ret.vspace_root, vptr), GET_PML4_INDEX(vptr));
258         }
259         break;
260     }
261     case cap_pml4_cap: {
262         asid_t asid = cap_pml4_cap_get_capPML4MappedASID(cap);
263         findVSpaceForASID_ret_t find_ret = findVSpaceForASID(asid);
264         if (asid) {
265             printf("%p_pd (asid: %lu)\n",
266                    find_ret.vspace_root, (long unsigned int)asid);
267         } else {
268             printf("%p_pd\n", find_ret.vspace_root);
269         }
270         break;
271     }
272     case cap_asid_control_cap: {
273         /* only one in the system */
274         printf("asid_control\n");
275         break;
276     }
277     case cap_frame_cap: {
278         vptr_t vptr = cap_frame_cap_get_capFMappedAddress(cap);
279         findVSpaceForASID_ret_t find_ret = findVSpaceForASID(cap_frame_cap_get_capFMappedASID(cap));
280         assert(find_ret.status == EXCEPTION_NONE);
281         _cap_frame_print_attrs_vptr(vptr, find_ret.vspace_root);
282         break;
283     }
284     case cap_asid_pool_cap: {
285         printf("%p_asid_pool\n", (void *)cap_asid_pool_cap_get_capASIDPool(cap));
286         break;
287     }
288 #ifdef CONFIG_VTX
289     case cap_vcpu_cap: {
290         printf("%p_vcpu\n", (void *)cap_vcpu_cap_get_capVCPUPtr(cap));
291         break;
292     }
293 #endif
294     /* X86 specific caps */
295     case cap_io_port_cap: {
296         printf("%p%p_io_port\n", (void *)cap_io_port_cap_get_capIOPortFirstPort(cap),
297                (void *)cap_io_port_cap_get_capIOPortLastPort(cap));
298         break;
299     }
300 #ifdef CONFIG_IOMMU
301     case cap_io_space_cap: {
302         printf("%p_io_space\n", (void *)cap_io_space_cap_get_capPCIDevice(cap));
303         break;
304     }
305     case cap_io_page_table_cap: {
306         printf("%p_iopt\n", (void *)cap_io_page_table_cap_get_capIOPTBasePtr(cap));
307         break;
308     }
309 #endif
310     default: {
311         printf("[unknown cap %lu]\n", (long unsigned int)cap_get_capType(cap));
312         break;
313     }
314     }
315 }
316 
obj_asidpool_print_attrs(cap_t asid_cap)317 static void obj_asidpool_print_attrs(cap_t asid_cap)
318 {
319     asid_t asid = cap_asid_pool_cap_get_capASIDBase(asid_cap);
320     printf("(asid_high: 0x%lx)\n", ASID_HIGH(asid));
321 }
322 
print_object_arch(cap_t cap)323 void print_object_arch(cap_t cap)
324 {
325     switch (cap_get_capType(cap)) {
326     /* arch specific objects */
327     case cap_frame_cap:
328     case cap_page_table_cap:
329     case cap_page_directory_cap:
330     case cap_pdpt_cap:
331     case cap_pml4_cap:
332         /* don't need to deal with these objects since they get handled from vtable */
333         break;
334 
335     case cap_asid_pool_cap: {
336         printf("%p_asid_pool = asid_pool ",
337                (void *)cap_asid_pool_cap_get_capASIDPool(cap));
338         obj_asidpool_print_attrs(cap);
339         break;
340     }
341 #ifdef CONFIG_VTX
342     case cap_vcpu_cap: {
343         printf("%p_vcpu = vcpu\n", (void *)cap_vcpu_cap_get_capVCPUPtr(cap));
344         break;
345     }
346 #endif
347     /* X86 specific caps */
348     case cap_io_port_cap: {
349         printf("%p%p_io_port = io_port ",
350                (void *)cap_io_port_cap_get_capIOPortFirstPort(cap),
351                (void *)cap_io_port_cap_get_capIOPortLastPort(cap));
352         x86_obj_ioports_print_attrs(cap);
353         break;
354     }
355 #ifdef CONFIG_IOMMU
356     case cap_io_space_cap: {
357         printf("%p_io_space = io_space ", (void *)cap_io_space_cap_get_capPCIDevice(cap));
358         x86_obj_iospace_print_attrs(cap);
359         break;
360     }
361     case cap_io_page_table_cap: {
362         printf("%p_iopt = iopt ", (void *)cap_io_page_table_cap_get_capIOPTBasePtr(cap));
363         x86_obj_iopt_print_attrs(cap);
364         break;
365     }
366 #endif
367     default: {
368         printf("[unknown object %lu]\n", (long unsigned int)cap_get_capType(cap));
369         break;
370     }
371     }
372 }
373 
print_ipc_buffer_slot(tcb_t * tcb)374 void print_ipc_buffer_slot(tcb_t *tcb)
375 {
376     word_t vptr = tcb->tcbIPCBuffer;
377     printf("ipc_buffer_slot: ");
378     cap_frame_print_attrs_vptr(vptr, TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
379 }
380 
x86_64_cap_pt_print_slots(pde_t * pdSlot,vptr_t vptr)381 static void x86_64_cap_pt_print_slots(pde_t *pdSlot, vptr_t vptr)
382 {
383     pte_t *pt = paddr_to_pptr(pde_pde_pt_ptr_get_pt_base_address(pdSlot));
384     printf("pt_%p_%04lu {\n", pdSlot, GET_PD_INDEX(vptr));
385 
386     for (word_t i = 0; i < BIT(PT_INDEX_OFFSET + PT_INDEX_BITS); i += (1UL << PT_INDEX_OFFSET)) {
387         pte_t *ptSlot = pt + GET_PT_INDEX(i);
388 
389         if (pte_ptr_get_present(ptSlot)) {
390             printf("0x%lx: frame_%p_%04lu ", GET_PT_INDEX(i), ptSlot, GET_PT_INDEX(i));
391             cap_frame_print_attrs_pt(ptSlot);
392         }
393     }
394     printf("}\n"); /* pt */
395 }
396 
x86_64_cap_pd_print_slots(pdpte_t * pdptSlot,vptr_t vptr)397 static void x86_64_cap_pd_print_slots(pdpte_t *pdptSlot, vptr_t vptr)
398 {
399     pde_t *pd = paddr_to_pptr(pdpte_pdpte_pd_ptr_get_pd_base_address(pdptSlot));
400     printf("pd_%p_%04lu {\n", pdptSlot, GET_PDPT_INDEX(vptr));
401 
402     for (word_t i = 0; i < BIT(PD_INDEX_OFFSET + PD_INDEX_BITS); i += (1UL << PD_INDEX_OFFSET)) {
403         pde_t *pdSlot = pd + GET_PD_INDEX(i);
404 
405         if ((pde_ptr_get_page_size(pdSlot) == pde_pde_large) && pde_pde_large_ptr_get_present(pdSlot)) {
406             printf("0x%lx: frame_%p_%04lu ", GET_PD_INDEX(i), pdSlot, GET_PD_INDEX(i));
407             cap_frame_print_attrs_pd(pdSlot);
408 
409         } else if (pde_pde_pt_ptr_get_present(pdSlot)) {
410             printf("0x%lx: pt_%p_%04lu\n", GET_PD_INDEX(i), pdSlot, GET_PD_INDEX(i));
411         }
412     }
413     printf("}\n"); /* pd */
414 
415     for (word_t i = 0; i < BIT(PD_INDEX_OFFSET + PD_INDEX_BITS); i += (1UL << PD_INDEX_OFFSET)) {
416         pde_t *pdSlot = pd + GET_PD_INDEX(i);
417         if ((pde_ptr_get_page_size(pdSlot) == pde_pde_pt) && pde_pde_pt_ptr_get_present(pdSlot)) {
418             x86_64_cap_pt_print_slots(pdSlot, i);
419         }
420     }
421 }
422 
x86_64_cap_pdpt_print_slots(pml4e_t * pml4Slot,vptr_t vptr)423 static void x86_64_cap_pdpt_print_slots(pml4e_t *pml4Slot, vptr_t vptr)
424 {
425     pdpte_t *pdpt = paddr_to_pptr(pml4e_ptr_get_pdpt_base_address(pml4Slot));
426 
427     printf("pdpt_%p_%04lu {\n", pml4Slot, GET_PML4_INDEX(vptr));
428     for (word_t i = 0; i < BIT(PDPT_INDEX_OFFSET + PDPT_INDEX_BITS); i += (1UL << PDPT_INDEX_OFFSET)) {
429         pdpte_t *pdptSlot = pdpt + GET_PDPT_INDEX(i);
430 
431         if (pdpte_ptr_get_page_size(pdptSlot) == pdpte_pdpte_1g &&
432             pdpte_pdpte_1g_ptr_get_present(pdptSlot)) {
433             printf("0x%lx: frame_%p_%04lu ", GET_PDPT_INDEX(i), pdptSlot, GET_PDPT_INDEX(i));
434             cap_frame_print_attrs_pdpt(pdptSlot);
435 
436         } else if (pdpte_pdpte_pd_ptr_get_present(pdptSlot)) {
437             printf("0x%lx: pd_%p_%04lu\n", GET_PDPT_INDEX(i), pdptSlot, GET_PDPT_INDEX(i));
438         }
439     }
440     printf("}\n"); /* pdpt */
441 
442     for (word_t i = 0; i < BIT(PDPT_INDEX_OFFSET + PDPT_INDEX_BITS); i += (1UL << PDPT_INDEX_OFFSET)) {
443         pdpte_t *pdptSlot = pdpt + GET_PDPT_INDEX(i);
444 
445         if (pdpte_ptr_get_page_size(pdptSlot) == pdpte_pdpte_pd && pdpte_pdpte_pd_ptr_get_present(pdptSlot)) {
446             x86_64_cap_pd_print_slots(pdptSlot, i);
447         }
448     }
449 }
450 
x86_64_cap_pml4_print_slots(pml4e_t * pml4)451 static void x86_64_cap_pml4_print_slots(pml4e_t *pml4)
452 {
453     printf("%p_pd {\n", pml4);
454     for (word_t i = 0; i < BIT(PML4_INDEX_OFFSET + PML4_INDEX_BITS); i += (1UL << PML4_INDEX_OFFSET)) {
455         pml4e_t *pml4Slot = lookupPML4Slot(pml4, i);
456         if (pml4e_ptr_get_present(pml4Slot)) {
457             printf("0x%lx: pdpt_%p_%04lu\n", GET_PML4_INDEX(i), pml4Slot, GET_PML4_INDEX(i));
458         }
459     }
460     printf("}\n"); /* pml4 */
461 
462     for (word_t i = 0; i < BIT(PML4_INDEX_OFFSET + PML4_INDEX_BITS); i += (1UL << PML4_INDEX_OFFSET)) {
463         pml4e_t *pml4Slot = lookupPML4Slot(pml4, i);
464         if (pml4e_ptr_get_present(pml4Slot)) {
465             x86_64_cap_pdpt_print_slots(pml4Slot, i);
466         }
467     }
468 }
469 
obj_vtable_print_slots(tcb_t * tcb)470 void obj_vtable_print_slots(tcb_t *tcb)
471 {
472     /* levels: PML4 -> PDPT -> PD -> PT */
473     if (isValidVTableRoot(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap) && !seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap)) {
474         pml4e_t *pml4 = PML4E_PTR(cap_pml4_cap_get_capPML4BasePtr(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap));
475         add_to_seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
476         x86_64_cap_pml4_print_slots(pml4);
477     }
478 }
479 
480 #endif /* CONFIG_PRINTING */
481 
debug_capDL(void)482 void debug_capDL(void)
483 {
484     printf("arch x86_64\n");
485     printf("objects {\n");
486     print_objects();
487     printf("}\n");
488 
489     printf("caps {\n");
490 
491     /* reset the seen list */
492     reset_seen_list();
493 
494 #ifdef CONFIG_PRINTING
495     print_caps();
496     printf("}\n");
497 
498     obj_irq_print_maps();
499 #endif
500 }
501 
502 #endif /* CONFIG_DEBUG_BUILD */
503