capDL: Add kernel debugging tool for capDL

Add Arm debugging features of capDL Kernel Printing

Signed-off-by: Jingyao Zhou <Jingyao.Zhou@data61.csiro.au>
This commit is contained in:
Jingyao Zhou 2020-09-16 19:38:40 +10:00
parent 7c91c1c88a
commit 9feaba02fe
4 changed files with 1061 additions and 8 deletions

View file

@ -6,4 +6,18 @@
#pragma once
#include <machine/capdl.h>
#ifdef CONFIG_ARM_SMMU
static inline void arm_obj_iospace_print_attrs(cap_t iospace_cap)
{
printf("(armiospace: %lu)\n", (long unsigned int)cap_io_space_cap_get_capModuleID(io_space));
}
#endif
static inline void obj_asidpool_print_attrs(cap_t asid_cap)
{
printf("(asid_high: 0x%lx)\n", (long unsigned int)ASID_HIGH(cap_asid_pool_cap_get_capASIDBase(asid_cap)));
}
void capDL(void);

View file

@ -5,13 +5,513 @@
*/
#include <config.h>
#include <machine/capdl.h>
#include <arch/machine/capdl.h>
#include <string.h>
#include <kernel/cspace.h>
#ifdef CONFIG_DEBUG_BUILD
void capDL(void)
{
#define MAX_UL 0xffffffff
#define PT_INDEX(vptr) ((vptr >> PAGE_BITS) & MASK(PT_INDEX_BITS))
#define PD_INDEX(vptr) (vptr >> (PAGE_BITS + PT_INDEX_BITS))
static void obj_frame_print_attrs(resolve_ret_t ret);
static void cap_frame_print_attrs_pt(pte_t *pte);
static void cap_frame_print_attrs_pd(pde_t *pde);
static void cap_frame_print_attrs_impl(word_t AP, word_t XN, word_t TEX);
static void arm32_obj_pt_print_slots(pte_t *pt);
static void arm32_cap_pt_print_slots(pte_t *pt);
/*
* Caps
*/
word_t get_tcb_sp(tcb_t *tcb)
{
return tcb->tcbArch.tcbContext.registers[SP];
}
#endif
/*
* AP S R Privileged permissions User permissions
* 00 0 0 No access No access
* 00 1 0 Read-only No access
* 00 0 1 Read-only Read-only
* 00 1 1 Unpredictable Unpredictable
* 01 x x Read/write No access
* 10 x x Read/write Read-only
* 11 x x Read/write Read/write
*/
/* use when only have access to pte of frames */
static void cap_frame_print_attrs_pt(pte_t *pte)
{
word_t AP, XN, TEX;
switch (pte_ptr_get_pteType(pte)) {
case pte_pte_small:
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
AP = pte_pte_small_ptr_get_HAP(pte);
TEX = pte_pte_small_ptr_get_MemAttr(pte);
#else
AP = pte_pte_small_ptr_get_AP(pte);
TEX = pte_pte_small_ptr_get_TEX(pte);
#endif
XN = pte_pte_small_ptr_get_XN(pte);
break;
#ifndef CONFIG_ARM_HYPERVISOR_SUPPORT
case pte_pte_large:
AP = pte_pte_large_ptr_get_AP(pte);
TEX = pte_pte_large_ptr_get_TEX(pte);
XN = pte_pte_large_ptr_get_XN(pte);
break;
#endif
default:
assert(!"should not happend");
}
cap_frame_print_attrs_impl(AP, XN, TEX);
}
static void cap_frame_print_attrs_pd(pde_t *pde)
{
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
cap_frame_print_attrs_impl(pde_pde_section_ptr_get_HAP(pde),
pde_pde_section_ptr_get_XN(pde),
pde_pde_section_ptr_get_MemAttr(pde));
#else
cap_frame_print_attrs_impl(pde_pde_section_ptr_get_AP(pde),
pde_pde_section_ptr_get_XN(pde),
pde_pde_section_ptr_get_TEX(pde));
#endif
}
static void cap_frame_print_attrs_impl(word_t AP, word_t XN, word_t TEX)
{
printf("(");
/* rights */
switch (AP) {
case 0b00:
case 0b01:
break;
case 0b10:
printf("R");
break;
case 0b11:
printf("RW");
default:
break;
}
if (!XN) {
printf("X");
}
if (!TEX) {
printf(", uncached");
}
printf(")\n");
}
static void arm32_cap_pt_print_slots(pte_t *pt)
{
vm_page_size_t page_size;
word_t i = 0;
while (i < BIT(PT_INDEX_BITS + PAGE_BITS)) {
pte_t *pte = lookupPTSlot_nofail(pt, i);
switch (pte_ptr_get_pteType(pte)) {
case pte_pte_small: {
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
if (pte_pte_small_ptr_get_contiguous_hint(pte)) {
page_size = ARMLargePage;
} else {
page_size = ARMSmallPage;
}
#else
page_size = ARMSmallPage;
#endif
printf("0x%lx: frame_%p_%04lu ", PT_INDEX(i), pte, PT_INDEX(i));
cap_frame_print_attrs_pt(pte);
break;
}
#ifndef CONFIG_ARM_HYPERVISOR_SUPPORT
case pte_pte_large: {
page_size = ARMLargePage;
printf("0x%lx: frame_%p_%04lu ", PT_INDEX(i), pte, PT_INDEX(i));
cap_frame_print_attrs_pt(pte);
break;
}
#endif
default:
page_size = ARMSmallPage;
}
i += (1 << pageBitsForSize(page_size));
}
}
void obj_vtable_print_slots(tcb_t *tcb)
{
if (isValidVTableRoot(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap) && !seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap)) {
add_to_seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
pde_t *pd = (pde_t *)pptr_of_cap(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
vm_page_size_t page_size;
printf("%p_pd {\n", pd);
/* PD_INDEX_BITS + ARMSectionBits = 32, can't use left shift here */
word_t i = 0;
while (i < MAX_UL) {
pde_t *pde = lookupPDSlot(pd, i);
switch (pde_ptr_get_pdeType(pde)) {
case pde_pde_section: {
#ifndef CONFIG_ARM_HYPERVISOR_SUPPORT
if (pde_pde_section_ptr_get_size(pde)) {
page_size = ARMSuperSection;
} else {
page_size = ARMSection;
}
#else
if (pde_pde_section_ptr_get_contiguous_hint(pde)) {
page_size = ARMSuperSection;
} else {
page_size = ARMSection;
}
#endif
printf("0x%lx: frame_%p_%04lu ", PD_INDEX(i), pde, PD_INDEX(i));
cap_frame_print_attrs_pd(pde);
break;
}
case pde_pde_coarse: {
printf("0x%lx: pt_%p_%04lu\n", PD_INDEX(i), pde, PD_INDEX(i));
page_size = ARMSection;
break;
}
default:
page_size = ARMSection;
break;
}
i += (1 << pageBitsForSize(page_size));
if (i < (1 << pageBitsForSize(page_size))) {
break; /* overflowed */
}
}
printf("}\n"); /* pd */
i = 0;
/* PD_INDEX_BITS + ARMSectionBits = 32, can't use left shift here */
while (i < MAX_UL) {
pde_t *pde = lookupPDSlot(pd, i);
if (pde_ptr_get_pdeType(pde) == pde_pde_coarse) {
pte_t *pt = ptrFromPAddr(pde_pde_coarse_ptr_get_address(pde));
printf("pt_%p_%04lu {\n", pde, PD_INDEX(i));
arm32_cap_pt_print_slots(pt);
printf("}\n"); /* pt */
}
i += (1 << pageBitsForSize(ARMSection));
if (i < (1 << pageBitsForSize(ARMSection))) {
break; /* overflowed */
}
}
}
}
/* use when only have access to vptr of frames */
static void cap_frame_print_attrs_vptr(word_t vptr, pde_t *pd)
{
pde_t *pde = lookupPDSlot(pd, vptr);
switch (pde_ptr_get_pdeType(pde)) {
case pde_pde_section: {
printf("frame_%p_%04lu ", pde, PD_INDEX(vptr));
cap_frame_print_attrs_pd(pde);
break;
}
case pde_pde_coarse: {
pte_t *pt = ptrFromPAddr(pde_pde_coarse_ptr_get_address(pde));
pte_t *pte = lookupPTSlot_nofail(pt, vptr);
switch (pte_ptr_get_pteType(pte)) {
case pte_pte_small: {
printf("frame_%p_%04lu ", pte, PT_INDEX(vptr));
cap_frame_print_attrs_pt(pte);
break;
}
#ifndef CONFIG_ARM_HYPERVISOR_SUPPORT
case pte_pte_large: {
printf("frame_%p_%04lu ", pte, PT_INDEX(vptr));
cap_frame_print_attrs_pt(pte);
break;
}
#endif
default:
assert(0);
}
break;
}
default:
assert(0);
}
}
void print_ipc_buffer_slot(tcb_t *tcb)
{
word_t vptr = tcb->tcbIPCBuffer;
asid_t asid = cap_page_directory_cap_get_capPDMappedASID(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
findPDForASID_ret_t find_ret = findPDForASID(asid);
printf("ipc_buffer_slot: ");
cap_frame_print_attrs_vptr(vptr, find_ret.pd);
}
void print_cap_arch(cap_t cap)
{
switch (cap_get_capType(cap)) {
case cap_page_table_cap: {
asid_t asid = cap_page_table_cap_get_capPTMappedASID(cap);
findPDForASID_ret_t find_ret = findPDForASID(asid);
vptr_t vptr = cap_page_table_cap_get_capPTMappedAddress(cap);
if (asid) {
printf("pt_%p_%04lu (asid: %lu)\n",
lookupPDSlot(find_ret.pd, vptr), PD_INDEX(vptr), (long unsigned int)asid);
} else {
printf("pt_%p_%04lu\n", lookupPDSlot(find_ret.pd, vptr), PD_INDEX(vptr));
}
break;
}
case cap_page_directory_cap: {
asid_t asid = cap_page_directory_cap_get_capPDMappedASID(cap);
findPDForASID_ret_t find_ret = findPDForASID(asid);
if (asid) {
printf("%p_pd (asid: %lu)\n",
find_ret.pd, (long unsigned int)asid);
} else {
printf("%p_pd\n", find_ret.pd);
}
break;
}
case cap_asid_control_cap: {
/* only one in the system */
printf("asid_control\n");
break;
}
case cap_small_frame_cap: {
vptr_t vptr = cap_small_frame_cap_get_capFMappedAddress(cap);
findPDForASID_ret_t find_ret = findPDForASID(cap_small_frame_cap_get_capFMappedASID(cap));
assert(find_ret.status == EXCEPTION_NONE);
cap_frame_print_attrs_vptr(vptr, find_ret.pd);
break;
}
case cap_frame_cap: {
vptr_t vptr = cap_frame_cap_get_capFMappedAddress(cap);
findPDForASID_ret_t find_ret = findPDForASID(cap_frame_cap_get_capFMappedASID(cap));
assert(find_ret.status == EXCEPTION_NONE);
cap_frame_print_attrs_vptr(vptr, find_ret.pd);
break;
}
case cap_asid_pool_cap: {
printf("%p_asid_pool\n", (void *)cap_asid_pool_cap_get_capASIDPool(cap));
break;
}
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
case cap_vcpu_cap: {
printf("%p_vcpu\n", (void *)cap_vcpu_cap_get_capVCPUPtr(cap));
break;
}
#endif
/* ARM specific caps */
#ifdef CONFIG_ARM_SMMU
case cap_io_space_cap: {
printf("%p_io_space\n", (void *)cap_io_space_cap_get_capModuleID(cap));
break;
}
#endif
default: {
printf("[unknown cap %u]\n", cap_get_capType(cap));
break;
}
}
}
void print_object_arch(cap_t cap)
{
switch (cap_get_capType(cap)) {
case cap_frame_cap:
case cap_small_frame_cap:
case cap_page_table_cap:
case cap_page_directory_cap:
/* don't need to deal with these objects since they get handled from vtable */
break;
case cap_asid_pool_cap: {
printf("%p_asid_pool = asid_pool ",
(void *)cap_asid_pool_cap_get_capASIDPool(cap));
obj_asidpool_print_attrs(cap);
break;
}
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
case cap_vcpu_cap: {
printf("%p_vcpu = vcpu\n", (void *)cap_vcpu_cap_get_capVCPUPtr(cap));
break;
}
#endif
/* ARM specific objects */
#ifdef CONFIG_ARM_SMMU
case cap_io_space_cap: {
printf("%p_io_space = io_space ", (void *)cap_io_space_cap_get_capModuleID(cap));
arm_obj_iospace_print_attrs(cap);
break;
}
#endif
default: {
printf("[unknown object %u]\n", cap_get_capType(cap));
break;
}
}
}
static void obj_frame_print_attrs(resolve_ret_t ret)
{
printf("(");
/* VM size */
switch (ret.frameSize) {
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
case ARMSection:
printf("2M");
break;
case ARMSuperSection:
printf("32M");
break;
#else
case ARMSection:
printf("1M");
break;
case ARMSuperSection:
printf("16M");
break;
#endif
case ARMLargePage:
printf("64k");
break;
case ARMSmallPage:
printf("4k");
break;
}
printf(", paddr: %p)\n", (void *)ret.frameBase);
}
static void arm32_obj_pt_print_slots(pte_t *pt)
{
resolve_ret_t ret;
word_t i = 0;
while (i < BIT(PT_INDEX_BITS + PAGE_BITS)) {
pte_t *pte = lookupPTSlot_nofail(pt, i);
switch (pte_ptr_get_pteType(pte)) {
case pte_pte_small: {
ret.frameBase = pte_pte_small_ptr_get_address(pte);
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
if (pte_pte_small_ptr_get_contiguous_hint(pte)) {
/* Entries are represented as 16 contiguous small frames. We need to mask
to get the large frame base */
ret.frameBase &= ~MASK(pageBitsForSize(ARMLargePage));
ret.frameSize = ARMLargePage;
} else {
ret.frameSize = ARMSmallPage;
}
#else
ret.frameSize = ARMSmallPage;
#endif
printf("frame_%p_%04lu = frame ", pte, PT_INDEX(i));
obj_frame_print_attrs(ret);
break;
}
#ifndef CONFIG_ARM_HYPERVISOR_SUPPORT
case pte_pte_large: {
ret.frameBase = pte_pte_large_ptr_get_address(pte);
ret.frameSize = ARMLargePage;
printf("frame_%p_%04lu = frame ", pte, PT_INDEX(i));
obj_frame_print_attrs(ret);
break;
}
#endif
default:
ret.frameSize = ARMSmallPage;
}
i += (1 << pageBitsForSize(ret.frameSize));
}
}
void obj_tcb_print_vtable(tcb_t *tcb)
{
if (isValidVTableRoot(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap) && !seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap)) {
add_to_seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
pde_t *pd = (pde_t *)pptr_of_cap(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
resolve_ret_t ret = {};
printf("%p_pd = pd\n", pd);
/* PD_INDEX_BITS + ARMSectionBits = 32, can't use left shift here */
word_t i = 0;
while (i < MAX_UL) {
pde_t *pde = lookupPDSlot(pd, i);
switch (pde_ptr_get_pdeType(pde)) {
case pde_pde_section: {
ret.frameBase = pde_pde_section_ptr_get_address(pde);
#ifndef CONFIG_ARM_HYPERVISOR_SUPPORT
if (pde_pde_section_ptr_get_size(pde)) {
ret.frameSize = ARMSuperSection;
} else {
ret.frameSize = ARMSection;
}
#else
if (pde_pde_section_ptr_get_contiguous_hint(pde)) {
/* Entires are represented as 16 contiguous sections. We need to mask
to get the super section frame base */
ret.frameBase &= ~MASK(pageBitsForSize(ARMSuperSection));
ret.frameSize = ARMSuperSection;
} else {
ret.frameSize = ARMSection;
}
#endif
printf("frame_%p_%04lu = frame ", pde, PD_INDEX(i));
obj_frame_print_attrs(ret);
break;
}
case pde_pde_coarse: {
pte_t *pt = ptrFromPAddr(pde_pde_coarse_ptr_get_address(pde));
printf("pt_%p_%04lu = pt\n", pde, PD_INDEX(i));
arm32_obj_pt_print_slots(pt);
ret.frameSize = ARMSection;
break;
}
default:
ret.frameSize = ARMSection;
break;
}
i += (1 << pageBitsForSize(ret.frameSize));
if (i < (1 << pageBitsForSize(ret.frameSize))) {
break; /* overflowed */
}
}
}
}
void capDL(void)
{
printf("arch aarch32\n");
printf("objects {\n");
print_objects();
printf("}\n");
printf("caps {\n");
/* reset the seen list */
reset_seen_list();
print_caps();
printf("}\n");
obj_irq_print_maps();
}
#endif /* CONFIG_DEBUG_BUILD */

View file

@ -11,7 +11,6 @@ add_sources(
PREFIX src/arch/arm/64
CFILES
object/objecttype.c
machine/capdl.c
machine/registerset.c
machine/fpu.c
model/statedata.c
@ -21,3 +20,5 @@ add_sources(
kernel/vspace.c
ASMFILES head.S traps.S
)
add_sources(DEP "KernelSel4ArchAarch64;KernelDebugBuild" CFILES src/arch/arm/64/machine/capdl.c)

View file

@ -5,13 +5,551 @@
*/
#include <config.h>
#include <machine/capdl.h>
#include <arch/machine/capdl.h>
#include <string.h>
#include <kernel/cspace.h>
#ifdef CONFIG_DEBUG_BUILD
void capDL(void)
{
static void obj_frame_print_attrs(lookupFrame_ret_t ret);
static void cap_frame_print_attrs_pud(pude_t *pudSlot);
static void cap_frame_print_attrs_pd(pde_t *pdSlot);
static void cap_frame_print_attrs_pt(pte_t *ptSlot);
static void cap_frame_print_attrs_impl(word_t SH, word_t AP, word_t NXN);
static void cap_frame_print_attrs_vptr(word_t vptr, cap_t vspace);
static void _cap_frame_print_attrs_vptr(word_t vptr, vspace_root_t *vspaceRoot);
static void arm64_obj_pt_print_slots(pde_t *pdSlot);
static void arm64_obj_pd_print_slots(pude_t *pudSlot);
static void arm64_obj_pud_print_slots(void *pgdSlot_or_vspace);
static void arm64_cap_pt_print_slots(pde_t *pdSlot, vptr_t vptr);
static void arm64_cap_pd_print_slots(pude_t *pudSlot, vptr_t vptr);
static void arm64_cap_pud_print_slots(void *pgdSlot_or_vspace, vptr_t vptr);
word_t get_tcb_sp(tcb_t *tcb)
{
return tcb->tcbArch.tcbContext.registers[SP_EL0];
}
/* Stage-1 access permissions:
* AP[2:1] higer EL EL0
* 00 rw None
* 01 rw rw
* 10 r None
* 11 r r
*
* Stage-2 access permissions:
* S2AP Access from Nonsecure EL1 or Non-secure EL0
* 00 None
* 01 r
* 10 w
* 11 rw
*
* For VMs or native seL4 applications, if hypervisor support
* is enabled, we use the S2AP. The kernel itself running in
* EL2 still uses the Stage-1 AP format.
*/
/* use when only have access to pte of frames */
static void cap_frame_print_attrs_pud(pude_t *pudSlot)
{
cap_frame_print_attrs_impl(pude_pude_1g_ptr_get_SH(pudSlot),
pude_pude_1g_ptr_get_AP(pudSlot),
pude_pude_1g_ptr_get_UXN(pudSlot));
}
static void cap_frame_print_attrs_pd(pde_t *pdSlot)
{
cap_frame_print_attrs_impl(pde_pde_large_ptr_get_SH(pdSlot),
pde_pde_large_ptr_get_AP(pdSlot),
pde_pde_large_ptr_get_UXN(pdSlot));
}
static void cap_frame_print_attrs_pt(pte_t *ptSlot)
{
cap_frame_print_attrs_impl(pte_ptr_get_SH(ptSlot),
pte_ptr_get_AP(ptSlot),
pte_ptr_get_UXN(ptSlot));
}
static void cap_frame_print_attrs_impl(word_t SH, word_t AP, word_t NXN)
{
printf("(");
/* rights */
switch (AP) {
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
case 0b00:
break;
case 0b01:
printf("R");
break;
case 0b10:
printf("W");
break;
case 0b11:
printf("RW");
break;
#else
case 0b00:
break;
case 0b01:
printf("RW");
case 0b10:
break;
case 0b11:
printf("R");
#endif /* CONFIG_ARM_HYPERVISOR_SUPPORT */
default:
break;
}
if (!NXN) {
printf("X");
}
/* Only has effect if SMP enabled */
if (SH != SMP_TERNARY(SMP_SHARE, 0)) {
printf(", uncached");
}
printf(")\n");
}
/* use when only have access to vptr of frames */
static void _cap_frame_print_attrs_vptr(word_t vptr, vspace_root_t *vspace)
{
lookupPUDSlot_ret_t pudSlot = lookupPUDSlot(vspace, vptr);
if (pudSlot.status != EXCEPTION_NONE) {
return;
}
switch (pude_ptr_get_pude_type(pudSlot.pudSlot)) {
case pude_pude_1g:
printf("frame_%p_%04lu ", pudSlot.pudSlot, GET_PUD_INDEX(vptr));
cap_frame_print_attrs_pud(pudSlot.pudSlot);
break;
case pude_pude_pd: {
pde_t *pd = paddr_to_pptr(pude_pude_pd_ptr_get_pd_base_address(pudSlot.pudSlot));
pde_t *pdSlot = pd + GET_PD_INDEX(vptr);
switch (pde_ptr_get_pde_type(pdSlot)) {
case pde_pde_large:
printf("frame_%p_%04lu ", pdSlot, GET_PD_INDEX(vptr));
cap_frame_print_attrs_pd(pdSlot);
break;
case pde_pde_small: {
pte_t *pt = paddr_to_pptr(pde_pde_small_ptr_get_pt_base_address(pdSlot));
pte_t *ptSlot = pt + GET_PT_INDEX(vptr);
if (pte_ptr_get_present(ptSlot)) {
printf("frame_%p_%04lu ", ptSlot, GET_PT_INDEX(vptr));
cap_frame_print_attrs_pt(ptSlot);
break;
} else {
return;
}
}
default:
assert(0);
}
break;
}
default:
assert(0);
}
}
void cap_frame_print_attrs_vptr(word_t vptr, cap_t vspace)
{
_cap_frame_print_attrs_vptr(vptr, VSPACE_PTR(pptr_of_cap(vspace)));
}
/*
* print object slots
*/
static void arm64_cap_pt_print_slots(pde_t *pdSlot, vptr_t vptr)
{
pte_t *pt = paddr_to_pptr(pde_pde_small_ptr_get_pt_base_address(pdSlot));
printf("pt_%p_%04lu {\n", pdSlot, GET_PD_INDEX(vptr));
for (word_t i = 0; i < BIT(PT_INDEX_OFFSET + PT_INDEX_BITS); i += (1 << PT_INDEX_OFFSET)) {
pte_t *ptSlot = pt + GET_PT_INDEX(i);
if (pte_ptr_get_present(ptSlot)) {
// print pte entries
printf("0x%lx: frame_%p_%04lu", GET_PT_INDEX(i), ptSlot, GET_PT_INDEX(i));
cap_frame_print_attrs_pt(ptSlot);
}
}
printf("}\n"); /* pt */
}
static void arm64_cap_pd_print_slots(pude_t *pudSlot, vptr_t vptr)
{
printf("pd_%p_%04lu {\n", pudSlot, GET_PUD_INDEX(vptr));
pde_t *pd = paddr_to_pptr(pude_pude_pd_ptr_get_pd_base_address(pudSlot));
for (word_t i = 0; i < BIT(PD_INDEX_OFFSET + PD_INDEX_BITS); i += (1 << PD_INDEX_OFFSET)) {
pde_t *pdSlot = pd + GET_PD_INDEX(i);
switch (pde_ptr_get_pde_type(pdSlot)) {
case pde_pde_large:
printf("0x%lx: frame_%p_%04lu", GET_PD_INDEX(i), pdSlot, GET_PD_INDEX(i));
cap_frame_print_attrs_pd(pdSlot);
break;
case pde_pde_small:
printf("0x%lx: pt_%p_%04lu\n", GET_PD_INDEX(i), pdSlot, GET_PD_INDEX(i));
break;
}
}
printf("}\n"); /* pd */
for (word_t i = 0; i < BIT(PD_INDEX_OFFSET + PD_INDEX_BITS); i += (1 << PD_INDEX_OFFSET)) {
pde_t *pdSlot = pd + GET_PD_INDEX(i);
if (pde_ptr_get_pde_type(pdSlot) == pde_pde_small) {
arm64_cap_pt_print_slots(pdSlot, i);
}
}
}
static void arm64_cap_pud_print_slots(void *pgdSlot_or_vspace, vptr_t vptr)
{
#ifdef AARCH64_VSPACE_S2_START_L1
pude_t *pud = pgdSlot_or_vspace;
printf("%p_pd {\n", pgdSlot_or_vspace);
#else
pude_t *pud = paddr_to_pptr(pgde_pgde_pud_ptr_get_pud_base_address(pgdSlot_or_vspace));
printf("pud_%p_%04lu {\n", pgdSlot_or_vspace, GET_PGD_INDEX(vptr));
#endif
for (word_t i = 0; i < BIT(PUD_INDEX_OFFSET + UPUD_INDEX_BITS); i += (1 << PUD_INDEX_OFFSET)) {
pude_t *pudSlot = pud + GET_PUD_INDEX(i);
if (pude_ptr_get_pude_type(pudSlot) == pude_pude_pd) {
printf("0x%lx: pd_%p_%04lu\n", GET_PUD_INDEX(i), pudSlot, GET_PUD_INDEX(i));
}
}
printf("}\n"); /* pgd/pud */
for (word_t i = 0; i < BIT(PUD_INDEX_OFFSET + UPUD_INDEX_BITS); i += (1 << PUD_INDEX_OFFSET)) {
pude_t *pudSlot = pud + GET_PUD_INDEX(i);
if (pude_ptr_get_pude_type(pudSlot) == pude_pude_pd) {
arm64_cap_pd_print_slots(pudSlot, i);
}
}
}
void obj_vtable_print_slots(tcb_t *tcb)
{
if (isVTableRoot(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap) && !seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap)) {
add_to_seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
vspace_root_t *vspace = cap_vtable_root_get_basePtr(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
/*
* ARM hyp uses 3 level translation rather than the usual 4 level.
* levels: PGD -> UPD -> PD -> PT
*/
#ifdef AARCH64_VSPACE_S2_START_L1
arm64_cap_pud_print_slots(vspace, 0);
#else
printf("%p_pd {\n", vspace);
for (word_t i = 0; i < BIT(PGD_INDEX_OFFSET + PGD_INDEX_BITS); i += (1UL << PGD_INDEX_OFFSET)) {
lookupPGDSlot_ret_t pgdSlot = lookupPGDSlot(vspace, i);
if (pgde_pgde_pud_ptr_get_present(pgdSlot.pgdSlot)) {
printf("0x%lx: pud_%p_%04lu\n", GET_PGD_INDEX(i), pgdSlot.pgdSlot, GET_PGD_INDEX(i));
}
}
printf("}\n"); /* pd */
for (word_t i = 0; i < BIT(PGD_INDEX_OFFSET + PGD_INDEX_BITS); i += (1UL << PGD_INDEX_OFFSET)) {
lookupPGDSlot_ret_t pgdSlot = lookupPGDSlot(vspace, i);
if (pgde_pgde_pud_ptr_get_present(pgdSlot.pgdSlot)) {
arm64_cap_pud_print_slots(pgdSlot.pgdSlot, i);
}
}
#endif
}
}
void print_ipc_buffer_slot(tcb_t *tcb)
{
word_t vptr = tcb->tcbIPCBuffer;
printf("ipc_buffer_slot: ");
cap_frame_print_attrs_vptr(vptr, TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
}
void print_cap_arch(cap_t cap)
{
switch (cap_get_capType(cap)) {
case cap_page_table_cap: {
asid_t asid = cap_page_table_cap_get_capPTMappedASID(cap);
findVSpaceForASID_ret_t find_ret = findVSpaceForASID(asid);
vptr_t vptr = cap_page_table_cap_get_capPTMappedAddress(cap);
if (asid) {
printf("pt_%p_%04lu (asid: %lu)\n",
lookupPDSlot(find_ret.vspace_root, vptr).pdSlot, GET_PD_INDEX(vptr), (long unsigned int)asid);
} else {
printf("pt_%p_%04lu\n", lookupPDSlot(find_ret.vspace_root, vptr).pdSlot, GET_PD_INDEX(vptr));
}
break;
}
case cap_page_directory_cap: {
asid_t asid = cap_page_directory_cap_get_capPDMappedASID(cap);
findVSpaceForASID_ret_t find_ret = findVSpaceForASID(asid);
vptr_t vptr = cap_page_directory_cap_get_capPDMappedAddress(cap);
if (asid) {
printf("pd_%p_%04lu (asid: %lu)\n",
lookupPUDSlot(find_ret.vspace_root, vptr).pudSlot, GET_PUD_INDEX(vptr), (long unsigned int)asid);
} else {
printf("pd_%p_%04lu\n",
lookupPUDSlot(find_ret.vspace_root, vptr).pudSlot, GET_PUD_INDEX(vptr));
}
break;
}
case cap_page_upper_directory_cap: {
asid_t asid = cap_page_upper_directory_cap_get_capPUDMappedASID(cap);
findVSpaceForASID_ret_t find_ret = findVSpaceForASID(asid);
vptr_t vptr = cap_page_upper_directory_cap_get_capPUDMappedAddress(cap);
#ifdef AARCH64_VSPACE_S2_START_L1
if (asid) {
printf("pud_%p_%04lu (asid: %lu)\n",
find_ret.vspace_root, GET_PGD_INDEX(vptr), (long unsigned int)asid);
} else {
printf("pud_%p_%04lu\n", find_ret.vspace_root, GET_PGD_INDEX(vptr));
}
#else
if (asid) {
printf("pud_%p_%04lu (asid: %lu)\n",
lookupPGDSlot(find_ret.vspace_root, vptr).pgdSlot, GET_PGD_INDEX(vptr), (long unsigned int)asid);
} else {
printf("pud_%p_%04lu\n", lookupPGDSlot(find_ret.vspace_root, vptr).pgdSlot, GET_PGD_INDEX(vptr));
}
#endif
break;
}
case cap_page_global_directory_cap: {
asid_t asid = cap_page_global_directory_cap_get_capPGDMappedASID(cap);
findVSpaceForASID_ret_t find_ret = findVSpaceForASID(asid);
if (asid) {
printf("%p_pd (asid: %lu)\n",
find_ret.vspace_root, (long unsigned int)asid);
} else {
printf("%p_pd\n", find_ret.vspace_root);
}
break;
}
case cap_asid_control_cap: {
/* only one in the system */
printf("asid_control\n");
break;
}
case cap_frame_cap: {
vptr_t vptr = cap_frame_cap_get_capFMappedAddress(cap);
findVSpaceForASID_ret_t find_ret = findVSpaceForASID(cap_frame_cap_get_capFMappedASID(cap));
assert(find_ret.status == EXCEPTION_NONE);
_cap_frame_print_attrs_vptr(vptr, find_ret.vspace_root);
break;
}
case cap_asid_pool_cap: {
printf("%p_asid_pool\n", (void *)cap_asid_pool_cap_get_capASIDPool(cap));
break;
}
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
case cap_vcpu_cap: {
printf("%p_vcpu\n", (void *)cap_vcpu_cap_get_capVCPUPtr(cap));
break;
}
#endif
/* ARM specific caps */
#ifdef CONFIG_ARM_SMMU
case cap_io_space_cap: {
printf("%p_io_space\n", (void *)cap_io_space_cap_get_capModuleID(cap));
break;
}
#endif
default: {
printf("[unknown cap %lu]\n", (long unsigned int)cap_get_capType(cap));
break;
}
}
}
void print_object_arch(cap_t cap)
{
switch (cap_get_capType(cap)) {
case cap_frame_cap:
case cap_page_table_cap:
case cap_page_directory_cap:
case cap_page_upper_directory_cap:
case cap_page_global_directory_cap:
/* don't need to deal with these objects since they get handled from vtable */
break;
case cap_asid_pool_cap: {
printf("%p_asid_pool = asid_pool ",
(void *)cap_asid_pool_cap_get_capASIDPool(cap));
obj_asidpool_print_attrs(cap);
break;
}
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
case cap_vcpu_cap: {
printf("%p_vcpu = vcpu\n", (void *)cap_vcpu_cap_get_capVCPUPtr(cap));
break;
}
#endif
/* ARM specific objects */
#ifdef CONFIG_ARM_SMMU
case cap_io_space_cap: {
printf("%p_io_space = io_space ", (void *)cap_io_space_cap_get_capModuleID(cap));
arm_obj_iospace_print_attrs(cap);
break;
}
#endif
default: {
printf("[unknown object %lu]\n", (long unsigned int)cap_get_capType(cap));
break;
}
}
}
void obj_frame_print_attrs(lookupFrame_ret_t ret)
{
printf("(");
/* VM size */
switch (ret.frameSize) {
case ARMHugePage:
printf("1G");
break;
case ARMLargePage:
printf("2M");
break;
case ARMSmallPage:
printf("4k");
break;
}
printf(", paddr: 0x%p)\n", (void *)ret.frameBase);
}
void arm64_obj_pt_print_slots(pde_t *pdSlot)
{
lookupFrame_ret_t ret;
pte_t *pt = paddr_to_pptr(pde_pde_small_ptr_get_pt_base_address(pdSlot));
for (word_t i = 0; i < BIT(PT_INDEX_OFFSET + PT_INDEX_BITS); i += (1 << PT_INDEX_OFFSET)) {
pte_t *ptSlot = pt + GET_PT_INDEX(i);
if (pte_ptr_get_present(ptSlot)) {
ret.frameBase = pte_ptr_get_page_base_address(ptSlot);
ret.frameSize = ARMSmallPage;
printf("frame_%p_%04lu = frame ", ptSlot, GET_PT_INDEX(i));
obj_frame_print_attrs(ret);
}
}
}
void arm64_obj_pd_print_slots(pude_t *pudSlot)
{
lookupFrame_ret_t ret;
pde_t *pd = paddr_to_pptr(pude_pude_pd_ptr_get_pd_base_address(pudSlot));
for (word_t i = 0; i < BIT(PD_INDEX_OFFSET + PD_INDEX_BITS); i += (1 << PD_INDEX_OFFSET)) {
pde_t *pdSlot = pd + GET_PD_INDEX(i);
if (pde_ptr_get_pde_type(pdSlot) == pde_pde_large) {
ret.frameBase = pde_pde_large_ptr_get_page_base_address(pdSlot);
ret.frameSize = ARMLargePage;
printf("frame_%p_%04lu = frame ", pdSlot, GET_PD_INDEX(i));
obj_frame_print_attrs(ret);
}
if (pde_ptr_get_pde_type(pdSlot) == pde_pde_small) {
printf("pt_%p_%04lu = pt\n", pdSlot, GET_PD_INDEX(i));
arm64_obj_pt_print_slots(pdSlot);
}
}
}
void arm64_obj_pud_print_slots(void *pgdSlot_or_vspace)
{
lookupFrame_ret_t ret;
pude_t *pud = paddr_to_pptr(pgde_pgde_pud_ptr_get_pud_base_address(pgdSlot_or_vspace));
for (word_t i = 0; i < BIT(PUD_INDEX_OFFSET + UPUD_INDEX_BITS); i += (1 << PUD_INDEX_OFFSET)) {
pude_t *pudSlot = pud + GET_PUD_INDEX(i);
switch (pude_ptr_get_pude_type(pudSlot)) {
case pude_pude_1g:
ret.frameBase = pude_pude_1g_ptr_get_page_base_address(pudSlot);
ret.frameSize = ARMHugePage;
printf("frame_%p_%04lu = frame ", pudSlot, GET_PUD_INDEX(i));
obj_frame_print_attrs(ret);
break;
case pude_pude_pd: {
printf("pd_%p_%04lu = pd\n", pudSlot, GET_PUD_INDEX(i));
arm64_obj_pd_print_slots(pudSlot);
}
}
}
}
void obj_tcb_print_vtable(tcb_t *tcb)
{
if (isVTableRoot(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap) && !seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap)) {
add_to_seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
vspace_root_t *vspace = cap_vtable_root_get_basePtr(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap);
/*
* ARM hyp uses 3 level translation rather than the usual 4 level.
* levels: PGD -> PUD -> PD -> PT
*/
#ifdef AARCH64_VSPACE_S2_START_L1
printf("%p_pd = pud\n", vspace);
arm64_obj_pud_print_slots(vspace);
#else
printf("%p_pd = pgd\n", vspace);
for (word_t i = 0; i < BIT(PGD_INDEX_OFFSET + PGD_INDEX_BITS); i += (1UL << PGD_INDEX_OFFSET)) {
lookupPGDSlot_ret_t pgdSlot = lookupPGDSlot(vspace, i);
if (pgde_pgde_pud_ptr_get_present(pgdSlot.pgdSlot)) {
printf("pud_%p_%04lu = pud\n", pgdSlot.pgdSlot, GET_PGD_INDEX(i));
arm64_obj_pud_print_slots(pgdSlot.pgdSlot);
}
}
#endif
}
}
void capDL(void)
{
printf("arch aarch64\n");
printf("objects {\n");
print_objects();
printf("}\n");
printf("caps {\n");
/* reset the seen list */
reset_seen_list();
print_caps();
printf("}\n");
obj_irq_print_maps();
}
#endif /* CONFIG_DEBUG_BUILD */