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 <machine/capdl.h>
12#include <arch/machine/capdl.h>
13
14static void obj_asidpool_print_attrs(cap_t asid_cap);
15static void obj_frame_print_attrs(paddr_t paddr);
16static void riscv_obj_pt_print_slots(pte_t *lvl1pt, pte_t *pt, int level);
17static void cap_frame_print_attrs_vptr(word_t vptr, pte_t *lvl1pt);
18static void cap_frame_print_attrs_pt(pte_t *ptSlot);
19
20static void obj_asidpool_print_attrs(cap_t asid_cap)
21{
22    asid_t asid = cap_asid_pool_cap_get_capASIDBase(asid_cap);
23    printf("(asid_high: 0x%lx)\n", ASID_HIGH(asid));
24}
25
26void print_ipc_buffer_slot(tcb_t *tcb)
27{
28    word_t vptr = tcb->tcbIPCBuffer;
29    asid_t asid = cap_page_table_cap_get_capPTMappedASID(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
30    findVSpaceForASID_ret_t find_ret = findVSpaceForASID(asid);
31
32    printf("ipc_buffer_slot: ");
33    cap_frame_print_attrs_vptr(vptr, find_ret.vspace_root);
34}
35
36static void riscv_cap_pt_print_slots(pte_t *upperPtSlot, word_t ptIndex, int level)
37{
38    pte_t *pt;
39    if (level == CONFIG_PT_LEVELS) {
40        printf("%p_pd {\n", upperPtSlot);
41        pt = upperPtSlot;
42    } else {
43        printf("pt_%p_%04lu {\n", upperPtSlot, ptIndex);
44        pt = getPPtrFromHWPTE(upperPtSlot);
45    }
46    level -= 1;
47
48    word_t ptBitsLeft = PT_INDEX_BITS * level + seL4_PageBits;
49
50    /* - 1 to avoid overflowing */
51    for (word_t i = 0; i < BIT(ptBitsLeft + PT_INDEX_BITS) - 1; i += (1 << (ptBitsLeft))) {
52        word_t ptSlotIndex = ((i >> ptBitsLeft) & MASK(PT_INDEX_BITS));
53        pte_t *ptSlot = pt + ptSlotIndex;
54        if (pte_ptr_get_valid(ptSlot)) {
55            if (level) { /* pt */
56                printf("0x%lx: pt_%p_%04lu\n", ptSlotIndex, ptSlot, ptSlotIndex);
57            } else { /* frame */
58                printf("0x%lx: frame_%p_%04lu", ptSlotIndex, ptSlot, ptSlotIndex);
59                cap_frame_print_attrs_pt(ptSlot);
60            }
61        }
62    }
63    printf("}\n"); /* lvl1pt/pt */
64
65    for (word_t i = 0; i < BIT(ptBitsLeft + PT_INDEX_BITS) - 1; i += (1 << (ptBitsLeft))) {
66        word_t ptSlotIndex = ((i >> ptBitsLeft) & MASK(PT_INDEX_BITS));
67        pte_t *ptSlot = pt + ptSlotIndex;
68        if (pte_ptr_get_valid(ptSlot)) {
69            if (level) { /* pt */
70                riscv_cap_pt_print_slots(ptSlot, ptSlotIndex, level);
71            }
72        }
73    }
74}
75
76void obj_vtable_print_slots(tcb_t *tcb)
77{
78    if (isValidVTableRoot(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap) && !seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap)) {
79        pte_t *lvl1pt = PTE_PTR(pptr_of_cap(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap));
80        add_to_seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
81        riscv_cap_pt_print_slots(lvl1pt, 0, CONFIG_PT_LEVELS);
82    }
83}
84
85word_t get_tcb_sp(tcb_t *tcb)
86{
87    return tcb->tcbArch.tcbContext.registers[SP];
88}
89
90static void cap_frame_print_attrs_pt(pte_t *ptSlot)
91{
92    printf("(");
93
94    /* rights */
95    if (pte_ptr_get_read(ptSlot)) {
96        printf("R");
97    }
98
99    if (pte_ptr_get_write(ptSlot)) {
100        printf("W");
101    }
102
103    if (pte_ptr_get_execute(ptSlot)) {
104        printf("X");
105    }
106
107    /* cacheable not supported yet */
108
109    printf(")\n");
110}
111
112static void cap_frame_print_attrs_vptr(word_t vptr, pte_t *lvl1pt)
113{
114    lookupPTSlot_ret_t lu_ret = lookupPTSlot(lvl1pt, vptr);
115    assert(lu_ret.ptBitsLeft == seL4_PageBits);
116    word_t slot = ((vptr >> lu_ret.ptBitsLeft) & MASK(PT_INDEX_BITS));
117
118    printf("frame_%p_%04lu ", lu_ret.ptSlot, slot);
119    cap_frame_print_attrs_pt(lu_ret.ptSlot);
120}
121
122void print_cap_arch(cap_t cap)
123{
124    switch (cap_get_capType(cap)) {
125    case cap_page_table_cap: {
126        asid_t asid = cap_page_table_cap_get_capPTMappedASID(cap);
127        findVSpaceForASID_ret_t find_ret = findVSpaceForASID(asid);
128        vptr_t vptr = cap_page_table_cap_get_capPTMappedAddress(cap);
129
130        word_t ptBitsLeft = PT_INDEX_BITS * CONFIG_PT_LEVELS + seL4_PageBits;
131        word_t slot = ((vptr >> ptBitsLeft) & MASK(PT_INDEX_BITS));
132        if (asid) {
133            printf("pt_%p_%04lu (asid: %lu)\n",
134                   lookupPTSlot(find_ret.vspace_root, vptr).ptSlot, slot, (long unsigned int)asid);
135        } else {
136            printf("pt_%p_%04lu\n", lookupPTSlot(find_ret.vspace_root, vptr).ptSlot, slot);
137        }
138        break;
139    }
140    case cap_asid_control_cap: {
141        /* only one in the system */
142        printf("asid_control\n");
143        break;
144    }
145    case cap_frame_cap: {
146        vptr_t vptr = cap_frame_cap_get_capFMappedAddress(cap);
147        findVSpaceForASID_ret_t find_ret = findVSpaceForASID(cap_frame_cap_get_capFMappedASID(cap));
148
149        assert(find_ret.status == EXCEPTION_NONE);
150        cap_frame_print_attrs_vptr(vptr, find_ret.vspace_root);
151        break;
152    }
153    case cap_asid_pool_cap: {
154        printf("%p_asid_pool\n", (void *)cap_asid_pool_cap_get_capASIDPool(cap));
155        break;
156    }
157    /* riscv specific caps */
158    /* nothing */
159    default: {
160        printf("[unknown cap %lu]\n", (long unsigned int)cap_get_capType(cap));
161        break;
162    }
163    }
164}
165
166static void obj_frame_print_attrs(paddr_t paddr)
167{
168    printf("(4k, paddr: 0x%p)\n", (void *)paddr);
169}
170
171void print_object_arch(cap_t cap)
172{
173    switch (cap_get_capType(cap)) {
174    case cap_frame_cap:
175    case cap_page_table_cap:
176        /* don't need to deal with these objects since they get handled from vtable */
177        break;
178
179    case cap_asid_pool_cap: {
180        printf("%p_asid_pool = asid_pool ",
181               (void *)cap_asid_pool_cap_get_capASIDPool(cap));
182        obj_asidpool_print_attrs(cap);
183        break;
184    }
185    /* riscv specific caps */
186    /* nothing */
187    default: {
188        printf("[unknown object %lu]\n", (long unsigned int)cap_get_capType(cap));
189        break;
190    }
191    }
192}
193
194static void riscv_obj_pt_print_slots(pte_t *lvl1pt, pte_t *pt, int level)
195{
196    word_t ptBitsLeft = PT_INDEX_BITS * level + seL4_PageBits;
197
198    for (word_t i = 0; i < BIT(ptBitsLeft + PT_INDEX_BITS); i += (1 << (ptBitsLeft))) {
199        word_t ptIndex = ((i >> ptBitsLeft) & MASK(PT_INDEX_BITS));
200        pte_t *ptSlot = pt + ptIndex;
201        if (pte_ptr_get_valid(ptSlot)) {
202            if (level) { /* pt */
203                printf("pt_%p_%04lu = pt\n", ptSlot, ptIndex);
204                riscv_obj_pt_print_slots(lvl1pt, getPPtrFromHWPTE(ptSlot), level - 1);
205            } else { /* frame */
206                paddr_t paddr = pte_ptr_get_ppn(ptSlot);
207                printf("frame_%p_%04lu = frame ", ptSlot, ptIndex);
208                obj_frame_print_attrs(paddr);
209            }
210        }
211    }
212}
213
214void obj_tcb_print_vtable(tcb_t *tcb)
215{
216    if (isValidVTableRoot(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap) && !seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap)) {
217        add_to_seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
218        pte_t *lvl1pt = PTE_PTR(pptr_of_cap(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap));
219        printf("%p_pd = pt\n", lvl1pt);
220        riscv_obj_pt_print_slots(lvl1pt, lvl1pt, CONFIG_PT_LEVELS - 1);
221    }
222}
223
224void capDL(void)
225{
226    printf("arch riscv32\n");
227    printf("objects {\n");
228    print_objects();
229    printf("}\n");
230
231    printf("caps {\n");
232
233    /* reset the seen list */
234    reset_seen_list();
235
236    print_caps();
237    printf("}\n");
238
239    obj_irq_print_maps();
240}
241
242#endif /* CONFIG_DEBUG_BUILD */
243