1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#pragma once 14 15#include <autoconf.h> 16 17#include <assert.h> 18#include <sel4/sel4.h> 19#include <sel4/macros.h> 20#include <simple/arch/simple.h> 21#include <stdlib.h> 22#include <utils/util.h> 23#include <stdbool.h> 24#include <vka/cspacepath_t.h> 25 26/* Simple does not address initial null caps. */ 27#define SIMPLE_NUM_INIT_CAPS (seL4_NumInitialCaps - SIMPLE_SKIPPED_INIT_CAPS) 28 29/** 30 * Get the cap to the physical frame of memory and put it at specified location 31 * 32 * @param data cookie for the underlying implementation 33 * 34 * @param page aligned physical address 35 * 36 * @param size of the region in bits 37 * 38 * @param The path to where to put this cap 39 */ 40typedef seL4_Error(*simple_get_frame_cap_fn)(void *data, void *paddr, int size_bits, cspacepath_t *path); 41 42/** 43 * Request mapped address to a region of physical memory. 44 * 45 * Note: This function will only return the mapped virtual address that it knows about. It does not do any mapping its self nor can it guess where mapping functions are going to map. 46 * 47 * @param data cookie for the underlying implementation 48 * 49 * @param page aligned physical address 50 * 51 * @param size of the region in bits 52 * 53 * Returns the virtual address to which this physical address is mapped or NULL if frame is unmapped 54 */ 55 56typedef void *(*simple_get_frame_mapping_fn)(void *data, void *paddr, int size_bits); 57 58/** 59 * Request data to a region of physical memory. 60 * 61 * Note: This function will only return the mapped virtual address that it knows about. It does not do any mapping its self nor can it guess where mapping functions are going to map. 62 * 63 * @param data cookie for the underlying implementation 64 * 65 * @param page aligned physical address for the frame 66 * 67 * @param size of the region in bits 68 * 69 * @param cap to the frame gets set. Will return the untyped cap unless the underlying implementation has access to the frame cap. Check with implementation but it should be a frame cap if and only if a vaddr is returned. 70 * 71 * @param (potentially) the offset within the untyped cap that was returned 72 * Returns the vritual address to which this physical address is mapped or NULL if frame is unmapped 73 */ 74typedef void *(*simple_get_frame_info_fn)(void *data, void *paddr, int size_bits, seL4_CPtr *cap, seL4_Word *ut_offset); 75 76/** 77 * Assign the vspace to the current threads ASID pool 78 * 79 * @param data cookie for the underlying implementation 80 * 81 * @param vspace to assign 82*/ 83typedef seL4_Error(*simple_ASIDPool_assign_fn)(void *data, seL4_CPtr vspace); 84 85/** 86 * Get the total number of caps this library can address 87 * 88 * @param data cookie for the underlying implementation 89*/ 90typedef int (*simple_get_cap_count_fn)(void *data); 91 92/** 93 * Get the nth cap that this library can address 94 * 95 * Addressable capabilities are numbered from 0, starting with the initial thread's capabilities, 96 * through caps provided by bootinfo. 97 * Initial capabilities that are null are not addressable, including seL4_CapNull, and other 98 * capabilities depending on the architecture and configuration. 99 * 100 * @param data cookie for the underlying implementation 101 * 102 * @param the nth starting at 0 103*/ 104typedef seL4_CPtr(*simple_get_nth_cap_fn)(void *data, int n); 105 106/** 107 * Get the cap to init caps with numbering based on bootinfo.h 108 * 109 * @param data for the underlying implementation 110 * 111 * @param the value of the enum matching in bootinfo.h 112*/ 113 114typedef seL4_CPtr(*simple_get_init_cap_fn)(void *data, seL4_CPtr cap); 115 116/** 117 * Get the size of the threads cnode in bits 118 * 119 * @param data for the underlying implementation 120*/ 121 122typedef uint8_t (*simple_get_cnode_size_fn)(void *data); 123 124/** 125 * Get the amount of untyped caps available 126 * 127 * @param data for the underlying implementation 128 * 129*/ 130 131typedef int (*simple_get_untyped_count_fn)(void *data); 132/** 133 * Get the nth untyped cap that this library can address 134 * 135 * @param data cookie for the underlying implementation 136 * 137 * @param the nth starting at 0 138 * 139 * @param the size of the untyped for the returned cap 140 * 141 * @param the physical address of the returned cap 142*/ 143 144typedef seL4_CPtr(*simple_get_nth_untyped_fn)(void *data, int n, size_t *size_bits, uintptr_t *paddr, bool *device); 145 146/** 147 * Get the amount of user image caps available 148 * 149 * @param data for the underlying implementation 150 * 151*/ 152 153typedef int (*simple_get_userimage_count_fn)(void *data); 154 155/** 156 * Get the nth untyped cap that this library can address 157 * 158 * @param data cookie for the underlying implementation 159 * 160 * @param the nth starting at 0 161 * 162*/ 163 164typedef seL4_CPtr(*simple_get_nth_userimage_fn)(void *data, int n); 165 166/** 167 * Get number of available cores 168 * 169 * @param data for the underlying implementation 170 * 171*/ 172 173typedef int (*simple_get_core_count_fn)(void *data); 174 175#ifdef CONFIG_IOMMU 176/** 177 * Get the IO space capability for the specified PCI device and domain ID 178 * 179 * @param data cookie for the underlying implementation 180 * @param domainID domain ID to request 181 * @param deviceID PCI device ID 182 * @param path Path to where to put this cap 183 * 184*/ 185typedef seL4_Error(*simple_get_iospace_fn)(void *data, uint16_t domainID, uint16_t deviceID, cspacepath_t *path); 186#endif 187 188/* 189 * Get the sched ctrl for the requested core (0 for uniprocessor). 190 * @return seL4_CapNull if CONFIG_RT is disabled 191 */ 192typedef seL4_CPtr(*simple_get_sched_ctrl_fn)(void *data, int core); 193 194 195/** 196 * 197 * Get simple to print all the information it has about its environment 198 */ 199typedef void (*simple_print_fn)(void *data); 200 201/** 202 * 203 * Retrieve the length of a particular kind of extended boot information. The information will always 204 * be prefixed with a seL4_BootInfoHeader, which is included in the length 205 * 206 * @param data cookie for the underlying implementation 207 * @param type Type corresponding to a valid 'id' in a seL4_BootInfoHeader 208 * 209 * @return Length of the header or -1 if the type could not be found 210 */ 211typedef ssize_t (*simple_get_extended_bootinfo_len_fn)(void *data, seL4_Word type); 212 213/** 214 * 215 * Retrieve a particular kind of extended boot information. The information will always 216 * be prefixed with a seL4_BootInfoHeader, which is included in the length 217 * 218 * @param data cookie for the underlying implementation 219 * @param type Type corresponding to a valid 'id' in a seL4_BootInfoHeader 220 * @param dest Destination to write the information to 221 * @param max_len Maximum length of the destination 222 * 223 * @return Length of the written information or -1 if the type could not be found 224 */ 225typedef ssize_t (*simple_get_extended_bootinfo_fn)(void *data, seL4_Word type, void *dest, ssize_t max_len); 226 227typedef struct simple_t { 228 void *data; 229 simple_get_frame_cap_fn frame_cap; 230 simple_get_frame_mapping_fn frame_mapping; 231 simple_get_frame_info_fn frame_info; 232 simple_ASIDPool_assign_fn ASID_assign; 233 simple_get_cap_count_fn cap_count; 234 simple_get_nth_cap_fn nth_cap; 235 simple_get_init_cap_fn init_cap; 236 simple_get_cnode_size_fn cnode_size; 237 simple_get_untyped_count_fn untyped_count; 238 simple_get_nth_untyped_fn nth_untyped; 239 simple_get_userimage_count_fn userimage_count; 240 simple_get_nth_userimage_fn nth_userimage; 241 simple_get_core_count_fn core_count; 242 simple_print_fn print; 243 simple_get_sched_ctrl_fn sched_ctrl; 244 simple_get_extended_bootinfo_len_fn extended_bootinfo_len; 245 simple_get_extended_bootinfo_fn extended_bootinfo; 246 arch_simple_t arch_simple; 247} simple_t; 248 249static inline void *simple_get_frame_info(simple_t *simple, void *paddr, int size_bits, seL4_CPtr *frame_cap, 250 seL4_Word *ut_offset) 251{ 252 if (!simple) { 253 ZF_LOGE("Simple is NULL"); 254 return NULL; 255 } 256 if (!simple->frame_info) { 257 ZF_LOGE("%s not implemented", __FUNCTION__); 258 return NULL; 259 } 260 261 return simple->frame_info(simple->data, paddr, size_bits, frame_cap, ut_offset); 262} 263 264static inline seL4_Error simple_get_frame_cap(simple_t *simple, void *paddr, int size_bits, cspacepath_t *path) 265{ 266 if (!simple) { 267 ZF_LOGE("Simple is NULL"); 268 return seL4_InvalidArgument; 269 } 270 if (!simple->frame_cap) { 271 ZF_LOGE("%s not implemented", __FUNCTION__); 272 return seL4_InvalidArgument; 273 } 274 return simple->frame_cap(simple->data, paddr, size_bits, path); 275} 276 277static inline void *simple_get_frame_vaddr(simple_t *simple, void *paddr, int size_bits) 278{ 279 if (!simple) { 280 ZF_LOGE("Simple is NULL"); 281 return NULL; 282 } 283 if (simple->frame_mapping) { 284 return simple->frame_mapping(simple->data, paddr, size_bits); 285 } else { 286 ZF_LOGE("%s not implemented", __FUNCTION__); 287 return NULL; 288 } 289} 290 291static inline seL4_Error SEL4_DEPRECATED("Use simple_get_IRQ_handler") 292simple_get_IRQ_control(simple_t *simple, int irq, cspacepath_t path) 293{ 294 if (!simple) { 295 ZF_LOGE("Simple is NULL"); 296 return seL4_InvalidArgument; 297 } 298 if (!simple->arch_simple.irq) { 299 ZF_LOGE("%s not implemented", __FUNCTION__); 300 return seL4_InvalidArgument; 301 } 302 return simple->arch_simple.irq(simple->data, irq, path.root, path.capPtr, path.capDepth); 303} 304 305static inline seL4_Error simple_get_IRQ_handler(simple_t *simple, int irq, cspacepath_t path) 306{ 307 if (!simple) { 308 ZF_LOGE("Simple is NULL"); 309 return seL4_InvalidArgument; 310 } 311 if (!simple->arch_simple.irq) { 312 ZF_LOGE("%s not implemented", __FUNCTION__); 313 return seL4_InvalidArgument; 314 } 315 return simple->arch_simple.irq(simple->data, irq, path.root, path.capPtr, path.capDepth); 316} 317 318static inline seL4_Error simple_ASIDPool_assign(simple_t *simple, seL4_CPtr vspace) 319{ 320 if (!simple) { 321 ZF_LOGE("Simple is NULL"); 322 return seL4_InvalidArgument; 323 } 324 if (!simple->ASID_assign) { 325 ZF_LOGE("%s not implemented", __FUNCTION__); 326 return seL4_InvalidArgument; 327 } 328 329 return simple->ASID_assign(simple->data, vspace); 330} 331 332static inline 333seL4_Error simple_get_IOPort_cap(simple_t *simple, uint16_t start_port, uint16_t end_port, seL4_Word root, 334 seL4_Word dest, seL4_Word depth) 335{ 336 if (!simple) { 337 ZF_LOGE("Simple is NULL"); 338 return seL4_InvalidArgument; 339 } 340 341 return arch_simple_get_IOPort_cap(&simple->arch_simple, start_port, end_port, root, dest, depth); 342} 343 344static inline int simple_get_cap_count(simple_t *simple) 345{ 346 if (!simple) { 347 ZF_LOGE("Simple is NULL"); 348 return -1; 349 } 350 if (!simple->cap_count) { 351 ZF_LOGE("%s not implemented", __FUNCTION__); 352 } 353 return simple->cap_count(simple->data); 354} 355 356static inline seL4_CPtr simple_get_nth_cap(simple_t *simple, int n) 357{ 358 if (!simple) { 359 ZF_LOGE("Simple is NULL"); 360 return seL4_CapNull; 361 } 362 363 if (!simple->nth_cap) { 364 ZF_LOGE("%s not implemented", __FUNCTION__); 365 return seL4_CapNull; 366 } 367 368 return simple->nth_cap(simple->data, n); 369} 370 371static inline int simple_get_cnode_size_bits(simple_t *simple) 372{ 373 if (!simple) { 374 ZF_LOGE("Simple is NULL"); 375 return -1; 376 } 377 if (!simple->cnode_size) { 378 ZF_LOGE("%s not implemented", __FUNCTION__); 379 return -1; 380 } 381 382 return simple->cnode_size(simple->data); 383} 384 385static inline seL4_CPtr simple_init_cap(simple_t *simple, seL4_CPtr cap) 386{ 387 if (!simple) { 388 ZF_LOGE("Simple is NULL"); 389 return seL4_CapNull; 390 } 391 392 if (!simple->init_cap) { 393 ZF_LOGE("%s not implemented", __FUNCTION__); 394 return seL4_CapNull; 395 } 396 397 return simple->init_cap(simple->data, cap); 398} 399 400static inline seL4_CPtr simple_get_cnode(simple_t *simple) 401{ 402 return simple_init_cap(simple, seL4_CapInitThreadCNode); 403} 404 405static inline seL4_CPtr simple_get_tcb(simple_t *simple) 406{ 407 return simple_init_cap(simple, seL4_CapInitThreadTCB); 408} 409 410static inline seL4_CPtr simple_get_sc(UNUSED simple_t *simple) 411{ 412#ifdef CONFIG_KERNEL_MCS 413 return simple_init_cap(simple, seL4_CapInitThreadSC); 414#else 415 return seL4_CapNull; 416#endif 417} 418 419static inline seL4_CPtr simple_get_pd(simple_t *simple) 420{ 421 return simple_init_cap(simple, seL4_CapInitThreadPD); 422} 423 424static inline seL4_CPtr simple_get_irq_ctrl(simple_t *simple) 425{ 426 return simple_init_cap(simple, seL4_CapIRQControl); 427} 428 429static inline seL4_CPtr simple_get_init_cap(simple_t *simple, seL4_CPtr cap) 430{ 431 return simple_init_cap(simple, cap); 432} 433 434static inline int simple_get_untyped_count(simple_t *simple) 435{ 436 if (!simple) { 437 ZF_LOGE("Simple is NULL"); 438 return -1; 439 } 440 if (!simple->untyped_count) { 441 ZF_LOGE("%s not implemented", __FUNCTION__); 442 return -1; 443 } 444 445 return simple->untyped_count(simple->data); 446} 447 448static inline seL4_CPtr simple_get_nth_untyped(simple_t *simple, int n, size_t *size_bits, uintptr_t *paddr, 449 bool *device) 450{ 451 if (!simple) { 452 ZF_LOGE("Simple is NULL"); 453 return seL4_CapNull; 454 } 455 if (!simple->nth_untyped) { 456 ZF_LOGE("%s not implemented", __FUNCTION__); 457 return seL4_CapNull; 458 } 459 460 return simple->nth_untyped(simple->data, n, size_bits, paddr, device); 461} 462 463static inline int simple_get_userimage_count(simple_t *simple) 464{ 465 if (!simple) { 466 ZF_LOGE("Simple is NULL"); 467 return -1; 468 } 469 if (!simple->userimage_count) { 470 ZF_LOGE("%s not implemented", __FUNCTION__); 471 return -1; 472 } 473 474 return simple->userimage_count(simple->data); 475} 476 477static inline seL4_CPtr simple_get_nth_userimage(simple_t *simple, int n) 478{ 479 if (!simple) { 480 ZF_LOGE("Simple is NULL"); 481 return seL4_CapNull; 482 } 483 if (!simple->nth_userimage) { 484 ZF_LOGE("%s Not implemented", __FUNCTION__); 485 return seL4_CapNull; 486 } 487 return simple->nth_userimage(simple->data, n); 488} 489 490static inline int simple_get_core_count(simple_t *simple) 491{ 492 if (!simple) { 493 ZF_LOGE("Simple is NULL"); 494 return -1; 495 } 496 if (!simple->core_count) { 497 ZF_LOGE("%s not implemented", __FUNCTION__); 498 return -1; 499 } 500 501 return simple->core_count(simple->data); 502} 503 504#ifdef CONFIG_IOMMU 505static inline seL4_CPtr simple_get_iospace(simple_t *simple, uint16_t domainID, uint16_t deviceID, cspacepath_t *path) 506{ 507 if (!simple) { 508 ZF_LOGE("Simple is NULL"); 509 return seL4_CapNull; 510 } 511 if (!simple->arch_simple.iospace) { 512 ZF_LOGE("%s not implemented", __FUNCTION__); 513 return seL4_CapNull; 514 } 515 516 return simple->arch_simple.iospace(simple->data, domainID, deviceID, path); 517} 518#endif 519 520 521#ifdef CONFIG_TK1_SMMU 522static inline seL4_Error simple_get_iospace_cap_count(simple_t *simple, int *count) 523{ 524 if (!simple) { 525 ZF_LOGE("Simple is NULL"); 526 return seL4_InvalidArgument; 527 } 528 if (!simple->data) { 529 ZF_LOGE("Simple data is NULL"); 530 return seL4_InvalidArgument; 531 } 532 if (!count) { 533 ZF_LOGE("NULL pointer"); 534 return seL4_InvalidArgument; 535 } 536 if (!simple->arch_simple.iospace_cap_count) { 537 ZF_LOGE("arch %s not implemented", __FUNCTION__); 538 return seL4_IllegalOperation; 539 } 540 541 return simple->arch_simple.iospace_cap_count(simple->data, count); 542} 543 544static inline seL4_CPtr simple_get_nth_iospace_cap(simple_t *simple, int n) 545{ 546 if (!simple) { 547 ZF_LOGE("Simple is NULL"); 548 return seL4_CapNull; 549 } 550 if (!simple->data) { 551 ZF_LOGE("Simple data is NULL"); 552 return seL4_CapNull; 553 } 554 if (!simple->arch_simple.iospace_get_nth_cap) { 555 ZF_LOGE("arch %s not implemented", __FUNCTION__); 556 return seL4_CapNull; 557 } 558 559 return simple->arch_simple.iospace_get_nth_cap(simple->data, n); 560} 561#endif 562 563#ifdef CONFIG_ARM_SMMU 564static inline seL4_CPtr simple_get_sid_ctrl(simple_t *simple) 565{ 566 return simple_init_cap(simple, seL4_CapSMMUSIDControl); 567} 568 569static inline seL4_CPtr simple_get_cb_ctrl(simple_t *simple) 570{ 571 return simple_init_cap(simple, seL4_CapSMMUCBControl); 572} 573#endif 574 575static inline void simple_print(simple_t *simple) 576{ 577 if (!simple) { 578 ZF_LOGE("Simple is NULL"); 579 return; 580 } 581 if (!simple->print) { 582 ZF_LOGE("%s not implemented", __FUNCTION__); 583 return; 584 } 585 586 simple->print(simple->data); 587} 588 589static inline seL4_CPtr simple_get_sched_ctrl(simple_t *simple, int core) 590{ 591 if (!simple) { 592 ZF_LOGE("Simple is NULL"); 593 return seL4_CapNull; 594 } 595 if (!simple->sched_ctrl) { 596 ZF_LOGE("%s not implemented", __FUNCTION__); 597 return seL4_CapNull; 598 } 599 if (core >= simple_get_core_count(simple)) { 600 ZF_LOGE("invalid core"); 601 return seL4_CapNull; 602 } 603 604 return simple->sched_ctrl(simple->data, core); 605} 606 607static inline ssize_t simple_get_extended_bootinfo_length(simple_t *simple, seL4_Word type) 608{ 609 if (!simple) { 610 ZF_LOGE("Simple is NULL"); 611 return -1; 612 } 613 if (!simple->extended_bootinfo_len) { 614 ZF_LOGE("%s not implemented", __FUNCTION__); 615 return -1; 616 } 617 return simple->extended_bootinfo_len(simple->data, type); 618} 619 620static inline ssize_t simple_get_extended_bootinfo(simple_t *simple, seL4_Word type, void *dest, ssize_t max_len) 621{ 622 if (!simple) { 623 ZF_LOGE("Simple is NULL"); 624 return -1; 625 } 626 if (!simple->extended_bootinfo) { 627 ZF_LOGE("%s not implemented", __FUNCTION__); 628 return -1; 629 } 630 return simple->extended_bootinfo(simple->data, type, dest, max_len); 631} 632 633