1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#include <config.h> 8#include <arch/machine/capdl.h> 9#include <string.h> 10#include <kernel/cspace.h> 11 12#ifdef CONFIG_DEBUG_BUILD 13 14#define MAX_UL 0xffffffff 15#define PT_INDEX(vptr) ((vptr >> PAGE_BITS) & MASK(PT_INDEX_BITS)) 16#define PD_INDEX(vptr) (vptr >> (PAGE_BITS + PT_INDEX_BITS)) 17 18static void obj_frame_print_attrs(resolve_ret_t ret); 19static void cap_frame_print_attrs_pt(pte_t *pte); 20static void cap_frame_print_attrs_pd(pde_t *pde); 21static void cap_frame_print_attrs_impl(word_t AP, word_t XN, word_t TEX); 22static void arm32_obj_pt_print_slots(pte_t *pt); 23static void arm32_cap_pt_print_slots(pte_t *pt); 24 25/* 26 * Caps 27 */ 28word_t get_tcb_sp(tcb_t *tcb) 29{ 30 return tcb->tcbArch.tcbContext.registers[SP]; 31} 32 33/* 34 * AP S R Privileged permissions User permissions 35 * 00 0 0 No access No access 36 * 00 1 0 Read-only No access 37 * 00 0 1 Read-only Read-only 38 * 00 1 1 Unpredictable Unpredictable 39 * 01 x x Read/write No access 40 * 10 x x Read/write Read-only 41 * 11 x x Read/write Read/write 42 */ 43/* use when only have access to pte of frames */ 44static void cap_frame_print_attrs_pt(pte_t *pte) 45{ 46 word_t AP, XN, TEX; 47 switch (pte_ptr_get_pteType(pte)) { 48 case pte_pte_small: 49#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT 50 AP = pte_pte_small_ptr_get_HAP(pte); 51 TEX = pte_pte_small_ptr_get_MemAttr(pte); 52#else 53 AP = pte_pte_small_ptr_get_AP(pte); 54 TEX = pte_pte_small_ptr_get_TEX(pte); 55#endif 56 XN = pte_pte_small_ptr_get_XN(pte); 57 break; 58 59#ifndef CONFIG_ARM_HYPERVISOR_SUPPORT 60 case pte_pte_large: 61 AP = pte_pte_large_ptr_get_AP(pte); 62 TEX = pte_pte_large_ptr_get_TEX(pte); 63 XN = pte_pte_large_ptr_get_XN(pte); 64 break; 65#endif 66 default: 67 assert(!"should not happend"); 68 } 69 cap_frame_print_attrs_impl(AP, XN, TEX); 70} 71 72static void cap_frame_print_attrs_pd(pde_t *pde) 73{ 74#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT 75 cap_frame_print_attrs_impl(pde_pde_section_ptr_get_HAP(pde), 76 pde_pde_section_ptr_get_XN(pde), 77 pde_pde_section_ptr_get_MemAttr(pde)); 78#else 79 cap_frame_print_attrs_impl(pde_pde_section_ptr_get_AP(pde), 80 pde_pde_section_ptr_get_XN(pde), 81 pde_pde_section_ptr_get_TEX(pde)); 82#endif 83} 84 85static void cap_frame_print_attrs_impl(word_t AP, word_t XN, word_t TEX) 86{ 87 printf("("); 88 89 /* rights */ 90 switch (AP) { 91 case 0b00: 92 case 0b01: 93 break; 94 case 0b10: 95 printf("R"); 96 break; 97 case 0b11: 98 printf("RW"); 99 default: 100 break; 101 } 102 103 if (!XN) { 104 printf("X"); 105 } 106 107 if (!TEX) { 108 printf(", uncached"); 109 } 110 111 printf(")\n"); 112} 113 114static void arm32_cap_pt_print_slots(pte_t *pt) 115{ 116 vm_page_size_t page_size; 117 word_t i = 0; 118 while (i < BIT(PT_INDEX_BITS + PAGE_BITS)) { 119 pte_t *pte = lookupPTSlot_nofail(pt, i); 120 switch (pte_ptr_get_pteType(pte)) { 121 case pte_pte_small: { 122#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT 123 if (pte_pte_small_ptr_get_contiguous_hint(pte)) { 124 page_size = ARMLargePage; 125 } else { 126 page_size = ARMSmallPage; 127 } 128#else 129 page_size = ARMSmallPage; 130#endif 131 printf("0x%lx: frame_%p_%04lu ", PT_INDEX(i), pte, PT_INDEX(i)); 132 cap_frame_print_attrs_pt(pte); 133 break; 134 } 135#ifndef CONFIG_ARM_HYPERVISOR_SUPPORT 136 case pte_pte_large: { 137 page_size = ARMLargePage; 138 printf("0x%lx: frame_%p_%04lu ", PT_INDEX(i), pte, PT_INDEX(i)); 139 cap_frame_print_attrs_pt(pte); 140 break; 141 } 142#endif 143 default: 144 page_size = ARMSmallPage; 145 } 146 i += (1 << pageBitsForSize(page_size)); 147 } 148} 149 150void obj_vtable_print_slots(tcb_t *tcb) 151{ 152 if (isValidVTableRoot(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap) && !seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap)) { 153 add_to_seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap); 154 pde_t *pd = (pde_t *)pptr_of_cap(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap); 155 vm_page_size_t page_size; 156 printf("%p_pd {\n", pd); 157 158 /* PD_INDEX_BITS + ARMSectionBits = 32, can't use left shift here */ 159 word_t i = 0; 160 while (i < MAX_UL) { 161 pde_t *pde = lookupPDSlot(pd, i); 162 switch (pde_ptr_get_pdeType(pde)) { 163 case pde_pde_section: { 164#ifndef CONFIG_ARM_HYPERVISOR_SUPPORT 165 if (pde_pde_section_ptr_get_size(pde)) { 166 page_size = ARMSuperSection; 167 } else { 168 page_size = ARMSection; 169 } 170#else 171 if (pde_pde_section_ptr_get_contiguous_hint(pde)) { 172 page_size = ARMSuperSection; 173 } else { 174 page_size = ARMSection; 175 } 176#endif 177 printf("0x%lx: frame_%p_%04lu ", PD_INDEX(i), pde, PD_INDEX(i)); 178 cap_frame_print_attrs_pd(pde); 179 break; 180 } 181 182 case pde_pde_coarse: { 183 printf("0x%lx: pt_%p_%04lu\n", PD_INDEX(i), pde, PD_INDEX(i)); 184 page_size = ARMSection; 185 break; 186 } 187 default: 188 page_size = ARMSection; 189 break; 190 } 191 i += (1 << pageBitsForSize(page_size)); 192 if (i < (1 << pageBitsForSize(page_size))) { 193 break; /* overflowed */ 194 } 195 } 196 printf("}\n"); /* pd */ 197 198 i = 0; 199 /* PD_INDEX_BITS + ARMSectionBits = 32, can't use left shift here */ 200 while (i < MAX_UL) { 201 pde_t *pde = lookupPDSlot(pd, i); 202 if (pde_ptr_get_pdeType(pde) == pde_pde_coarse) { 203 pte_t *pt = ptrFromPAddr(pde_pde_coarse_ptr_get_address(pde)); 204 printf("pt_%p_%04lu {\n", pde, PD_INDEX(i)); 205 arm32_cap_pt_print_slots(pt); 206 printf("}\n"); /* pt */ 207 } 208 i += (1 << pageBitsForSize(ARMSection)); 209 if (i < (1 << pageBitsForSize(ARMSection))) { 210 break; /* overflowed */ 211 } 212 } 213 } 214} 215 216/* use when only have access to vptr of frames */ 217static void cap_frame_print_attrs_vptr(word_t vptr, pde_t *pd) 218{ 219 pde_t *pde = lookupPDSlot(pd, vptr); 220 221 switch (pde_ptr_get_pdeType(pde)) { 222 case pde_pde_section: { 223 printf("frame_%p_%04lu ", pde, PD_INDEX(vptr)); 224 cap_frame_print_attrs_pd(pde); 225 break; 226 } 227 case pde_pde_coarse: { 228 pte_t *pt = ptrFromPAddr(pde_pde_coarse_ptr_get_address(pde)); 229 pte_t *pte = lookupPTSlot_nofail(pt, vptr); 230 switch (pte_ptr_get_pteType(pte)) { 231 case pte_pte_small: { 232 printf("frame_%p_%04lu ", pte, PT_INDEX(vptr)); 233 cap_frame_print_attrs_pt(pte); 234 break; 235 } 236 237#ifndef CONFIG_ARM_HYPERVISOR_SUPPORT 238 case pte_pte_large: { 239 printf("frame_%p_%04lu ", pte, PT_INDEX(vptr)); 240 cap_frame_print_attrs_pt(pte); 241 break; 242 } 243#endif 244 default: 245 assert(0); 246 } 247 break; 248 } 249 default: 250 assert(0); 251 } 252} 253 254void print_ipc_buffer_slot(tcb_t *tcb) 255{ 256 word_t vptr = tcb->tcbIPCBuffer; 257 asid_t asid = cap_page_directory_cap_get_capPDMappedASID(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap); 258 findPDForASID_ret_t find_ret = findPDForASID(asid); 259 printf("ipc_buffer_slot: "); 260 cap_frame_print_attrs_vptr(vptr, find_ret.pd); 261} 262 263void print_cap_arch(cap_t cap) 264{ 265 switch (cap_get_capType(cap)) { 266 case cap_page_table_cap: { 267 asid_t asid = cap_page_table_cap_get_capPTMappedASID(cap); 268 findPDForASID_ret_t find_ret = findPDForASID(asid); 269 vptr_t vptr = cap_page_table_cap_get_capPTMappedAddress(cap); 270 if (asid) { 271 printf("pt_%p_%04lu (asid: %lu)\n", 272 lookupPDSlot(find_ret.pd, vptr), PD_INDEX(vptr), (long unsigned int)asid); 273 } else { 274 printf("pt_%p_%04lu\n", lookupPDSlot(find_ret.pd, vptr), PD_INDEX(vptr)); 275 } 276 break; 277 } 278 case cap_page_directory_cap: { 279 asid_t asid = cap_page_directory_cap_get_capPDMappedASID(cap); 280 findPDForASID_ret_t find_ret = findPDForASID(asid); 281 if (asid) { 282 printf("%p_pd (asid: %lu)\n", 283 find_ret.pd, (long unsigned int)asid); 284 } else { 285 printf("%p_pd\n", find_ret.pd); 286 } 287 break; 288 } 289 case cap_asid_control_cap: { 290 /* only one in the system */ 291 printf("asid_control\n"); 292 break; 293 } 294 case cap_small_frame_cap: { 295 vptr_t vptr = cap_small_frame_cap_get_capFMappedAddress(cap); 296 findPDForASID_ret_t find_ret = findPDForASID(cap_small_frame_cap_get_capFMappedASID(cap)); 297 assert(find_ret.status == EXCEPTION_NONE); 298 cap_frame_print_attrs_vptr(vptr, find_ret.pd); 299 break; 300 } 301 case cap_frame_cap: { 302 vptr_t vptr = cap_frame_cap_get_capFMappedAddress(cap); 303 findPDForASID_ret_t find_ret = findPDForASID(cap_frame_cap_get_capFMappedASID(cap)); 304 assert(find_ret.status == EXCEPTION_NONE); 305 cap_frame_print_attrs_vptr(vptr, find_ret.pd); 306 break; 307 } 308 case cap_asid_pool_cap: { 309 printf("%p_asid_pool\n", (void *)cap_asid_pool_cap_get_capASIDPool(cap)); 310 break; 311 } 312#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT 313 case cap_vcpu_cap: { 314 printf("%p_vcpu\n", (void *)cap_vcpu_cap_get_capVCPUPtr(cap)); 315 break; 316 } 317#endif 318 319 /* ARM specific caps */ 320#ifdef CONFIG_TK1_SMMU 321 case cap_io_space_cap: { 322 printf("%p_io_space\n", (void *)cap_io_space_cap_get_capModuleID(cap)); 323 break; 324 } 325#endif 326 default: { 327 printf("[unknown cap %u]\n", cap_get_capType(cap)); 328 break; 329 } 330 } 331} 332 333void print_object_arch(cap_t cap) 334{ 335 336 switch (cap_get_capType(cap)) { 337 case cap_frame_cap: 338 case cap_small_frame_cap: 339 case cap_page_table_cap: 340 case cap_page_directory_cap: 341 /* don't need to deal with these objects since they get handled from vtable */ 342 break; 343 344 case cap_asid_pool_cap: { 345 printf("%p_asid_pool = asid_pool ", 346 (void *)cap_asid_pool_cap_get_capASIDPool(cap)); 347 obj_asidpool_print_attrs(cap); 348 break; 349 } 350#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT 351 case cap_vcpu_cap: { 352 printf("%p_vcpu = vcpu\n", (void *)cap_vcpu_cap_get_capVCPUPtr(cap)); 353 break; 354 } 355#endif 356 /* ARM specific objects */ 357#ifdef CONFIG_TK1_SMMU 358 case cap_io_space_cap: { 359 printf("%p_io_space = io_space ", (void *)cap_io_space_cap_get_capModuleID(cap)); 360 arm_obj_iospace_print_attrs(cap); 361 break; 362 } 363#endif 364 default: { 365 printf("[unknown object %u]\n", cap_get_capType(cap)); 366 break; 367 } 368 } 369} 370 371static void obj_frame_print_attrs(resolve_ret_t ret) 372{ 373 printf("("); 374 375 /* VM size */ 376 switch (ret.frameSize) { 377#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT 378 case ARMSection: 379 printf("2M"); 380 break; 381 case ARMSuperSection: 382 printf("32M"); 383 break; 384#else 385 case ARMSection: 386 printf("1M"); 387 break; 388 case ARMSuperSection: 389 printf("16M"); 390 break; 391#endif 392 case ARMLargePage: 393 printf("64k"); 394 break; 395 case ARMSmallPage: 396 printf("4k"); 397 break; 398 } 399 400 printf(", paddr: %p)\n", (void *)ret.frameBase); 401} 402 403static void arm32_obj_pt_print_slots(pte_t *pt) 404{ 405 resolve_ret_t ret; 406 word_t i = 0; 407 while (i < BIT(PT_INDEX_BITS + PAGE_BITS)) { 408 pte_t *pte = lookupPTSlot_nofail(pt, i); 409 switch (pte_ptr_get_pteType(pte)) { 410 case pte_pte_small: { 411 ret.frameBase = pte_pte_small_ptr_get_address(pte); 412#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT 413 if (pte_pte_small_ptr_get_contiguous_hint(pte)) { 414 /* Entries are represented as 16 contiguous small frames. We need to mask 415 to get the large frame base */ 416 ret.frameBase &= ~MASK(pageBitsForSize(ARMLargePage)); 417 ret.frameSize = ARMLargePage; 418 } else { 419 ret.frameSize = ARMSmallPage; 420 } 421#else 422 ret.frameSize = ARMSmallPage; 423#endif 424 printf("frame_%p_%04lu = frame ", pte, PT_INDEX(i)); 425 obj_frame_print_attrs(ret); 426 break; 427 } 428#ifndef CONFIG_ARM_HYPERVISOR_SUPPORT 429 case pte_pte_large: { 430 ret.frameBase = pte_pte_large_ptr_get_address(pte); 431 ret.frameSize = ARMLargePage; 432 printf("frame_%p_%04lu = frame ", pte, PT_INDEX(i)); 433 obj_frame_print_attrs(ret); 434 break; 435 } 436#endif 437 default: 438 ret.frameSize = ARMSmallPage; 439 } 440 i += (1 << pageBitsForSize(ret.frameSize)); 441 } 442} 443 444void obj_tcb_print_vtable(tcb_t *tcb) 445{ 446 if (isValidVTableRoot(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap) && !seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap)) { 447 add_to_seen(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap); 448 pde_t *pd = (pde_t *)pptr_of_cap(TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap); 449 resolve_ret_t ret = {}; 450 printf("%p_pd = pd\n", pd); 451 452 /* PD_INDEX_BITS + ARMSectionBits = 32, can't use left shift here */ 453 word_t i = 0; 454 while (i < MAX_UL) { 455 pde_t *pde = lookupPDSlot(pd, i); 456 switch (pde_ptr_get_pdeType(pde)) { 457 case pde_pde_section: { 458 ret.frameBase = pde_pde_section_ptr_get_address(pde); 459#ifndef CONFIG_ARM_HYPERVISOR_SUPPORT 460 if (pde_pde_section_ptr_get_size(pde)) { 461 ret.frameSize = ARMSuperSection; 462 } else { 463 ret.frameSize = ARMSection; 464 } 465#else 466 if (pde_pde_section_ptr_get_contiguous_hint(pde)) { 467 /* Entires are represented as 16 contiguous sections. We need to mask 468 to get the super section frame base */ 469 ret.frameBase &= ~MASK(pageBitsForSize(ARMSuperSection)); 470 ret.frameSize = ARMSuperSection; 471 } else { 472 ret.frameSize = ARMSection; 473 } 474#endif 475 printf("frame_%p_%04lu = frame ", pde, PD_INDEX(i)); 476 obj_frame_print_attrs(ret); 477 break; 478 } 479 480 case pde_pde_coarse: { 481 pte_t *pt = ptrFromPAddr(pde_pde_coarse_ptr_get_address(pde)); 482 printf("pt_%p_%04lu = pt\n", pde, PD_INDEX(i)); 483 arm32_obj_pt_print_slots(pt); 484 ret.frameSize = ARMSection; 485 break; 486 } 487 default: 488 ret.frameSize = ARMSection; 489 break; 490 } 491 i += (1 << pageBitsForSize(ret.frameSize)); 492 if (i < (1 << pageBitsForSize(ret.frameSize))) { 493 break; /* overflowed */ 494 } 495 } 496 } 497} 498 499void capDL(void) 500{ 501 printf("arch aarch32\n"); 502 printf("objects {\n"); 503 print_objects(); 504 printf("}\n"); 505 506 printf("caps {\n"); 507 508 /* reset the seen list */ 509 reset_seen_list(); 510 511 print_caps(); 512 printf("}\n"); 513 514 obj_irq_print_maps(); 515} 516 517#endif /* CONFIG_DEBUG_BUILD */ 518