├── .clang-format ├── .editorconfig ├── .github └── workflows │ └── quic-organization-repolinter.yml ├── .gitignore ├── LICENSE ├── README.md ├── SConstruct ├── arch ├── armv8 │ ├── build.conf │ ├── include │ │ ├── asm │ │ │ ├── arm_smccc.h │ │ │ └── interrupt.h │ │ └── cache.h │ └── src │ │ ├── cache.c │ │ ├── smc.c │ │ └── timestamp.c └── gicv3 │ ├── build.conf │ ├── include │ └── irq_arch.h │ └── src │ └── irq_gic.c ├── build.conf ├── config ├── arch │ ├── armv8.conf │ ├── armv9.conf │ ├── gicv3.conf │ └── qemu.conf ├── platform │ └── qemu.conf └── quality │ ├── debug.conf │ └── production.conf ├── configure.py ├── include ├── assert.h ├── compiler.h ├── cpio.h ├── dt_linux.h ├── dt_overlay.h ├── dtb_parser.h ├── elf.h ├── event.h ├── exit_dev.h ├── guest_hypresult.h ├── guest_interface.h ├── guest_rights.h ├── guest_types.h ├── irq_manager.h ├── irq_message.h ├── log.h ├── mem_region.h ├── memextent.h ├── memparcel.h ├── memparcel_msg.h ├── panic.h ├── platform.h ├── platform_env.h ├── preempt.h ├── random.h ├── resource-manager.h ├── rm-rpc-fifo.h ├── rm-rpc.h ├── rm_env_data.h ├── rm_types.h ├── uapi │ ├── console.h │ ├── exit_dev.h │ └── interrupt.h ├── uart.h ├── util.h ├── utils │ ├── address_range_allocator.h │ ├── circular_buf.h │ ├── dict.h │ ├── list.h │ ├── range_list.h │ └── vector.h ├── virq.h ├── vm_config.h ├── vm_config_parser.h ├── vm_config_struct.h ├── vm_console.h ├── vm_console_message.h ├── vm_creation.h ├── vm_creation_dt.h ├── vm_creation_message.h ├── vm_dt.h ├── vm_elf.h ├── vm_firmware.h ├── vm_firmware_message.h ├── vm_ipa.h ├── vm_ipa_message.h ├── vm_memory.h ├── vm_mgnt.h ├── vm_mgnt_message.h ├── vm_passthrough_config.h ├── vm_resource_msg.h ├── vm_resources.h └── vm_vcpu.h ├── platform └── qemu │ ├── build.conf │ ├── include │ ├── platform_dt.h │ ├── platform_dt_parser.h │ ├── platform_qemu.h │ ├── platform_vm_config.h │ ├── platform_vm_config_parser.h │ ├── platform_vm_memory.h │ ├── vgic.h │ └── vm_client.h │ └── src │ ├── exit │ └── exit.c │ ├── platform_qemu.c │ ├── platform_rtc.c │ ├── uart_qemu.c │ ├── uart_qemu.h │ ├── vgic.c │ ├── vm_client.c │ ├── vm_config.c │ ├── vm_config_parser.c │ ├── vm_dt.c │ └── vm_memory.c ├── repolint.json ├── src ├── assert.c ├── build.conf ├── dt │ ├── dt_overlay.c │ └── dto_construct.c ├── elf │ └── elf.c ├── event │ ├── event-epoll.c │ └── event-isr.c ├── exit │ └── exit.c ├── guest_accessors.c ├── guest_hypresult.c ├── guest_interface.c ├── hyp │ └── memextent.c ├── interrupt.c ├── irq_manager │ └── irq_manager.c ├── log.c ├── memparcel │ ├── mem_region.c │ └── memparcel.c ├── preempt │ └── preempt.c ├── process_env.c ├── random.c ├── resource-manager.c ├── rpc │ ├── rm-rpc-fifo.c │ ├── rm-rpc-internal.h │ ├── rm-rpc-msgqueue.c │ ├── rm-rpc-socket.c │ └── rm-rpc.c ├── uart │ └── uart.c ├── utils │ ├── address_range_allocator.c │ ├── circular_buf.c │ ├── dict.c │ ├── range_list.c │ └── vector.c ├── virq.c ├── vm_config │ ├── dtb_parser.c │ ├── vm_config.c │ ├── vm_config_parser.c │ ├── vm_config_rtc.c │ ├── vm_config_rtc.h │ ├── vm_get_resources.c │ └── vm_parser_rtc.h ├── vm_console │ └── vm_console_simple.c ├── vm_creation │ ├── dto_construct.c │ ├── dto_construct.h │ ├── hlos_vm.c │ ├── rm_vm.c │ ├── second_vm.c │ ├── vm_creation.c │ ├── vm_creation_pv_time.c │ ├── vm_creation_rtc.c │ └── vm_elf.c ├── vm_dt │ └── vm_dt.c ├── vm_firmware │ └── vm_firmware.c ├── vm_ipa │ └── vm_ipa.c ├── vm_mgnt │ └── vm_mgnt.c └── vm_passthrough_config │ └── vm_passthrough_config.c └── tools ├── __init__.py ├── build ├── __init__.py ├── __main__.py ├── config_file.py └── gen_ver.sh ├── cpptest ├── Checkers_Man_All_Req.properties ├── Cyclomatic.properties ├── cyclomatic_xml_to_json.py ├── gunyahkw.h ├── gunyahkw.kb ├── klocwork_xml_to_json.py └── misra_xml_to_json.py └── misc ├── convert-utf-8.sh ├── get_genfiles.py ├── setversion.sh └── update_cscope.sh /.editorconfig: -------------------------------------------------------------------------------- 1 | root = True 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | charset = utf-8 8 | tab_width = 8 9 | 10 | [*.{c,h,S}] 11 | indent_style = tab 12 | indent_size = 8 13 | 14 | [*.{py,md}] 15 | indent_style = space 16 | indent_size = 4 17 | -------------------------------------------------------------------------------- /.github/workflows/quic-organization-repolinter.yml: -------------------------------------------------------------------------------- 1 | name: QuIC Organization Repolinter 2 | 3 | on: 4 | push: 5 | branches: [ develop ] 6 | pull_request: 7 | branches: [ develop ] 8 | 9 | jobs: 10 | repolinter: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout Repo 14 | uses: actions/checkout@v4 15 | - name: Verify repolinter config file is present 16 | id: check_files 17 | uses: andstor/file-existence-action@v3 18 | with: 19 | files: "repolint.json" 20 | - name: Run Repolinter with local repolint.json 21 | if: steps.check_files.outputs.files_exists == 'true' 22 | uses: todogroup/repolinter-action@v1 23 | with: 24 | config_file: "repolint.json" 25 | - name: Run Repolinter with default ruleset 26 | if: steps.check_files.outputs.files_exists == 'false' 27 | uses: todogroup/repolinter-action@v1 28 | with: 29 | config_url: "https://raw.githubusercontent.com/quic/.github/main/repolint.json" 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore build products 2 | /build.ninja 3 | /.ninja_deps 4 | /.ninja_log 5 | /.sconsign.dblite 6 | /build*/ 7 | *.[od] 8 | 9 | # Ignore Python precompiled bitcode 10 | *.pyc 11 | 12 | # Ignore local editor configurations 13 | /compile_commands.json 14 | /.syntastic_* 15 | /.dir-locals.el 16 | /cscope* 17 | /.vscode 18 | 19 | # Ignore cppcheck dumps 20 | *.c.dump 21 | 22 | # Ignore Vim temporary files 23 | .*.sw[a-p] 24 | .*.un~ 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | 13 | ==================================================================================================================== 14 | Note: Individual files contain the following tag instead of the full license text. 15 | 16 | SPDX-License-Identifier: BSD-3-Clause 17 | 18 | This enables machine processing of license information based on the SPDX License Identifiers that are available here: http://spdx.org/licenses/ 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Resource Manager 2 | 3 | This is a simple VM manager for use with the Gunyah Hypervisor. 4 | 5 | > See https://github.com/quic/gunyah-hypervisor for additional documentation. 6 | 7 | The Resource Manager is used as the *Root VM* and acts as an extension of the hypervisor. It provides the functionality to create the primary VM (HLOS) and any other static boot-time configuration or partitioning as required. 8 | 9 | The Resource Manager provides a run-time service for secure dynamic VM loading and management. It provides APIs for creating and destroying VMs, secure memory management and sharing/lending memory between VMs, and setup of inter-VM communication. 10 | 11 | The Resource Manager is built as a bare metal VM with musl libc and requires the [Gunyah libc Runtime](https://github.com/quic/gunyah-c-runtime). 12 | 13 | ## License 14 | 15 | SPDX-License-Identifier: BSD-3-Clause 16 | 17 | See [LICENSE](LICENSE) for the full license text. 18 | -------------------------------------------------------------------------------- /SConstruct: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | # 3 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | 7 | import SCons.Script 8 | import configure 9 | import os 10 | 11 | env_vars = { 12 | 'PATH': os.environ['PATH'], 13 | 'LOCAL_SYSROOT': os.environ['LOCAL_SYSROOT'], 14 | } 15 | 16 | if 'QCOM_LLVM' in os.environ: 17 | env_vars['QCOM_LLVM'] = os.environ['QCOM_LLVM'] 18 | 19 | if 'LLVM' in os.environ: 20 | env_vars['LLVM'] = os.environ['LLVM'] 21 | 22 | env = Environment(tools={}, SCANNERS=[], BUILDERS={}, ENV=env_vars) 23 | configure.SConsBuild(env, Builder, Action, arguments=SCons.Script.ARGUMENTS)() 24 | -------------------------------------------------------------------------------- /arch/armv8/build.conf: -------------------------------------------------------------------------------- 1 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | 5 | include include 6 | 7 | source src/smc.c 8 | source src/timestamp.c 9 | source src/cache.c 10 | -------------------------------------------------------------------------------- /arch/armv8/include/asm/arm_smccc.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define SMCCC_USE_SMC 6 | // #define SMCCC_USE_HVC 7 | 8 | #define SMCCC_FAST_CALL_SHIFT 31 9 | #define SMCCC_64BIT_CALL_SHIFT 30 10 | #define SMCCC_SERVICE_BITS 6 11 | #define SMCCC_SERVICE_SHIFT 24 12 | #define SMCCC_FUNCTION_BITS 16 13 | #define SMCCC_FUNCTION_SHIFT 0 14 | 15 | #define SMCCC_SERVICE_MASK \ 16 | (((1U << SMCCC_SERVICE_BITS) - 1U) << SMCCC_SERVICE_SHIFT) 17 | #define SMCCC_FUNCTION_MASK ((1U << SMCCC_FUNCTION_BITS) - 1U) 18 | 19 | #define SMCCC_SERVICE_ARM 0 20 | #define SMCCC_SERVICE_CPU 1 21 | #define SMCCC_SERVICE_SIP 2 22 | #define SMCCC_SERVICE_OEM 3 23 | #define SMCCC_SERVICE_STANDARD_SECURE 4 24 | #define SMCCC_SERVICE_STANDARD_HYP 5 25 | #define SMCCC_SERVICE_VENDOR_HYP 6 26 | 27 | #define SMCCC_FUNCTION_ID(fast, call64, service_call, function) \ 28 | (((uint64_t)((fast) != 0) << SMCCC_FAST_CALL_SHIFT) | \ 29 | ((uint64_t)((call64) != 0) << SMCCC_64BIT_CALL_SHIFT) | \ 30 | ((service_call) << SMCCC_SERVICE_SHIFT) | \ 31 | ((function) << SMCCC_FUNCTION_SHIFT)) 32 | 33 | #define SMCCC_FUNCTION_ID_IS_FAST(func_id) \ 34 | ((bool)((func_id >> SMCCC_FAST_CALL_SHIFT) & 1)) 35 | #define SMCCC_FUNCTION_ID_IS_64BIT(func_id) \ 36 | ((bool)((func_id >> SMCCC_64BIT_CALL_SHIFT) & 1)) 37 | #define SMCCC_FUNCTION_ID_GET_SERVICE(func_id) \ 38 | ((uint32_t)((func_id & SMCCC_SERVICE_MASK) >> SMCCC_SERVICE_SHIFT)) 39 | #define SMCCC_FUNCTION_ID_GET_FUNCTION(func_id) \ 40 | ((uint32_t)((func_id & SMCCC_FUNCTION_MASK) >> SMCCC_FUNCTION_SHIFT)) 41 | 42 | uint64_t 43 | arm_smccc11_call(uint64_t func_id, uint64_t (*param)[7], uint64_t (*result)[4]); 44 | 45 | uint64_t 46 | arm_smccc12_call(uint64_t func_id, uint64_t (*param)[17], 47 | uint64_t (*result)[18]); 48 | -------------------------------------------------------------------------------- /arch/armv8/include/asm/interrupt.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Enable all interrupts, with a compiler release fence. 6 | #define asm_interrupt_enable_release(flag_ptr) \ 7 | do { \ 8 | atomic_signal_fence(memory_order_release); \ 9 | __asm__ volatile("msr daifclr, 0x7" : "+m"(*(flag_ptr))); \ 10 | } while ((_Bool)0) 11 | 12 | // Disable all interrupts, with a compiler acquire fence. 13 | #define asm_interrupt_disable_acquire(flag_ptr) \ 14 | do { \ 15 | __asm__ volatile("msr daifset, 0x7" ::"m"(*(flag_ptr))); \ 16 | atomic_signal_fence(memory_order_acquire); \ 17 | } while ((_Bool)0) 18 | -------------------------------------------------------------------------------- /arch/armv8/include/cache.h: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Ensure that any writes by RM through the specified pointer that lie in the 6 | // specified memory range have been written back to main memory and are visible 7 | // to all data and instruction accesses made by VMs with any cache attribute. 8 | // This is typically used after zeroing memory to sanitise it, or after copying 9 | // code into memory for access by a VM. 10 | void 11 | cache_clean_by_va(void *va, size_t size); 12 | 13 | // Ensure that all data accesses to the specified memory range by any VM with 14 | // any cache attribute are visible to accesses by RM through the specifed 15 | // pointer. This is typically used before accessing data provided by another VM. 16 | void 17 | cache_flush_by_va(void *va, size_t size); 18 | 19 | // Invalidate all of the instruction cache so it is coherent with any previous 20 | // data cache clean or flush. 21 | void 22 | cache_invalidate_inst_all(void); 23 | -------------------------------------------------------------------------------- /arch/armv8/src/cache.c: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | 13 | static uint64_t 14 | read_ctr(void) 15 | { 16 | uint64_t ctr_el0; 17 | 18 | // Read the Cache Type Register. 19 | __asm__("mrs %0, ctr_el0\n" : "=r"(ctr_el0)); 20 | 21 | return ctr_el0; 22 | } 23 | 24 | void 25 | cache_clean_by_va(void *ptr, size_t size) 26 | { 27 | uint64_t ctr_el0 = read_ctr(); 28 | const count_t line_size_p2 = (count_t)((ctr_el0 >> 16U) & 0xfU); 29 | const bool dic = ((ctr_el0 & util_bit(29U)) != 0U); 30 | 31 | uintptr_t aligned_va = util_p2align_down((uintptr_t)ptr, line_size_p2); 32 | uintptr_t end = (uintptr_t)ptr + size - 1U; 33 | 34 | // No barrier is needed before the CMOs, because we are cleaning writes 35 | // made through the same mapping. 36 | 37 | const size_t line_size = util_bit(line_size_p2); 38 | for (uintptr_t addr = aligned_va; addr <= end; addr += line_size) { 39 | // Clean one cache line by VA to the point of coherency. 40 | __asm__ volatile("dc cvac, %0\n" : : "r"(addr) : "memory"); 41 | } 42 | 43 | // A DSB is needed to synchronise any future reads by instruction 44 | // accesses. The implied DMB is also needed to synchronise any future 45 | // reads by data accesses with different cache attributes. 46 | __asm__ volatile("dsb ish" ::: "memory"); 47 | 48 | if (!dic) { 49 | // This CPU requires explicit instruction cache maintenance. 50 | // Invalidate all instruction caches, and execute another DSB 51 | // to ensure that future reads by instruction accesses are 52 | // ordered after completion of the invalidate. 53 | __asm__ volatile("ic ialluis" ::: "memory"); 54 | __asm__ volatile("dsb ish" ::: "memory"); 55 | } 56 | } 57 | 58 | void 59 | cache_flush_by_va(void *ptr, size_t size) 60 | { 61 | uint64_t ctr_el0 = read_ctr(); 62 | const count_t line_size_p2 = (count_t)((ctr_el0 >> 16U) & 0xfU); 63 | 64 | uintptr_t aligned_va = util_p2align_down((uintptr_t)ptr, line_size_p2); 65 | uintptr_t end = (uintptr_t)ptr + size - 1U; 66 | 67 | // A DMB is needed to synchronise any earlier writes to the range that 68 | // were made with different cache attributes. 69 | __asm__ volatile("dmb ish" ::: "memory"); 70 | 71 | const size_t line_size = util_bit(line_size_p2); 72 | for (uintptr_t addr = aligned_va; addr <= end; addr += line_size) { 73 | // Clean and invalidate one cache line by VA to the point of 74 | // coherency. 75 | __asm__ volatile("dc civac, %0\n" : : "r"(addr) : "memory"); 76 | } 77 | 78 | // No barrier is needed after the CMOs, because we are flushing lines to 79 | // be accessed by RM through the same mapping. 80 | } 81 | 82 | void 83 | cache_invalidate_inst_all(void) 84 | { 85 | uint64_t ctr_el0 = read_ctr(); 86 | const bool dic = ((ctr_el0 & util_bit(29U)) != 0U); 87 | 88 | if (!dic) { 89 | // See comment in cache_clean_by_va(). 90 | __asm__ volatile("ic ialluis; dsb ish" ::: "memory"); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /arch/armv8/src/smc.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | // ARM SMCCC Call version 1.1 12 | uint64_t 13 | arm_smccc11_call(uint64_t func_id, uint64_t (*param)[7], uint64_t (*result)[4]) 14 | { 15 | assert(param != NULL); 16 | assert(result != NULL); 17 | 18 | register uint64_t x0 __asm__("x0") = func_id; 19 | register uint64_t x1 __asm__("x1") = (*param)[0]; 20 | register uint64_t x2 __asm__("x2") = (*param)[1]; 21 | register uint64_t x3 __asm__("x3") = (*param)[2]; 22 | register uint64_t x4 __asm__("x4") = (*param)[3]; 23 | register uint64_t x5 __asm__("x5") = (*param)[4]; 24 | register uint64_t x6 __asm__("x6") = (*param)[5]; 25 | register uint64_t x7 __asm__("x7") = (*param)[6]; 26 | 27 | __asm__ volatile( 28 | #if defined(SMCCC_USE_SMC) 29 | "smc #0\n" 30 | #elif defined(SMCCC_USE_HVC) 31 | "hvc #0\n" 32 | #endif 33 | : "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3) 34 | : "r"(x4), "r"(x5), "r"(x6), "r"(x7) 35 | : "memory"); 36 | 37 | (*result)[0] = x0; 38 | (*result)[1] = x1; 39 | (*result)[2] = x2; 40 | (*result)[3] = x3; 41 | 42 | return x0; 43 | } 44 | 45 | // ARM SMCCC Call version 1.2 46 | uint64_t 47 | arm_smccc12_call(uint64_t func_id, uint64_t (*param)[17], 48 | uint64_t (*result)[18]) 49 | { 50 | assert(param != NULL); 51 | assert(result != NULL); 52 | 53 | register uint64_t x0 __asm__("x0") = func_id; 54 | register uint64_t x1 __asm__("x1") = (*param)[0]; 55 | register uint64_t x2 __asm__("x2") = (*param)[1]; 56 | register uint64_t x3 __asm__("x3") = (*param)[2]; 57 | register uint64_t x4 __asm__("x4") = (*param)[3]; 58 | register uint64_t x5 __asm__("x5") = (*param)[4]; 59 | register uint64_t x6 __asm__("x6") = (*param)[5]; 60 | register uint64_t x7 __asm__("x7") = (*param)[6]; 61 | register uint64_t x8 __asm__("x8") = (*param)[7]; 62 | register uint64_t x9 __asm__("x9") = (*param)[8]; 63 | register uint64_t x10 __asm__("x10") = (*param)[9]; 64 | register uint64_t x11 __asm__("x11") = (*param)[10]; 65 | register uint64_t x12 __asm__("x12") = (*param)[11]; 66 | register uint64_t x13 __asm__("x13") = (*param)[12]; 67 | register uint64_t x14 __asm__("x14") = (*param)[13]; 68 | register uint64_t x15 __asm__("x15") = (*param)[14]; 69 | register uint64_t x16 __asm__("x16") = (*param)[15]; 70 | register uint64_t x17 __asm__("x17") = (*param)[16]; 71 | 72 | __asm__ volatile( 73 | #if defined(SMCCC_USE_SMC) 74 | "smc #0\n" 75 | #elif defined(SMCCC_USE_HVC) 76 | "hvc #0\n" 77 | #endif 78 | : "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3), "+r"(x4), "+r"(x5), 79 | "+r"(x6), "+r"(x7), "+r"(x8), "+r"(x9), "+r"(x10), "+r"(x11), 80 | "+r"(x12), "+r"(x13), "+r"(x14), "+r"(x15), "+r"(x16), 81 | "+r"(x17)::"memory"); 82 | 83 | (*result)[0] = x0; 84 | (*result)[1] = x1; 85 | (*result)[2] = x2; 86 | (*result)[3] = x3; 87 | (*result)[4] = x4; 88 | (*result)[5] = x5; 89 | (*result)[6] = x6; 90 | (*result)[7] = x7; 91 | (*result)[8] = x8; 92 | (*result)[9] = x9; 93 | (*result)[10] = x10; 94 | (*result)[11] = x11; 95 | (*result)[12] = x12; 96 | (*result)[13] = x13; 97 | (*result)[14] = x14; 98 | (*result)[15] = x15; 99 | (*result)[16] = x16; 100 | (*result)[17] = x17; 101 | 102 | return x0; 103 | } 104 | -------------------------------------------------------------------------------- /arch/armv8/src/timestamp.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | #include 7 | 8 | uint64_t 9 | read_timestamp(void); 10 | 11 | uint64_t 12 | read_timestamp(void) 13 | { 14 | uint64_t ret; 15 | __asm__ __volatile__("mrs %0, cntvct_el0" : "=r"(ret)); 16 | return ret; 17 | } 18 | -------------------------------------------------------------------------------- /arch/gicv3/build.conf: -------------------------------------------------------------------------------- 1 | # © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | 5 | include include 6 | 7 | source src/irq_gic.c 8 | 9 | configs PLATFORM_IRQ_MAX=8191U 10 | -------------------------------------------------------------------------------- /arch/gicv3/include/irq_arch.h: -------------------------------------------------------------------------------- 1 | // © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | bool 6 | arch_irq_cpulocal_valid(uint32_t irq); 7 | bool 8 | arch_irq_global_valid(uint32_t irq); 9 | 10 | uint32_t 11 | arch_irq_cpulocal_max(void); 12 | uint32_t 13 | arch_irq_global_max(void); 14 | 15 | // Return the next valid irq number, starting from the provided input. 16 | // 17 | // The provided input must be an invalid global irq number. 18 | // 19 | // Returns 0 on failure. 20 | uint32_t 21 | arch_irq_cpulocal_next_valid(uint32_t irq); 22 | uint32_t 23 | arch_irq_global_next_valid(uint32_t irq); 24 | -------------------------------------------------------------------------------- /arch/gicv3/src/irq_gic.c: -------------------------------------------------------------------------------- 1 | // © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | bool 12 | arch_irq_cpulocal_valid(uint32_t irq) 13 | { 14 | // TODO: support extended PPIs 15 | return (irq >= 16U) && (irq <= 31U); 16 | } 17 | 18 | bool 19 | arch_irq_global_valid(uint32_t irq) 20 | { 21 | // TODO: support extended SPIs 22 | return (irq >= 32U) && (irq <= 1019U); 23 | } 24 | 25 | uint32_t 26 | arch_irq_cpulocal_max(void) 27 | { 28 | // TODO: support extended PPIs 29 | return 31U; 30 | } 31 | 32 | uint32_t 33 | arch_irq_global_max(void) 34 | { 35 | // TODO: support extended SPIs 36 | return 1019U; 37 | } 38 | 39 | uint32_t 40 | arch_irq_cpulocal_next_valid(uint32_t irq) 41 | { 42 | uint32_t next; 43 | 44 | assert(!arch_irq_cpulocal_valid(irq)); 45 | 46 | // TODO: support extended PPIs 47 | if (irq < 16U) { 48 | next = 16U; 49 | } else { 50 | next = 0U; // Failure 51 | } 52 | return next; 53 | } 54 | 55 | uint32_t 56 | arch_irq_global_next_valid(uint32_t irq) 57 | { 58 | uint32_t next; 59 | 60 | assert(!arch_irq_global_valid(irq)); 61 | 62 | // TODO: support extended SPIs 63 | if (irq < 32U) { 64 | next = 32U; 65 | } else { 66 | next = 0U; // Failure 67 | } 68 | return next; 69 | } 70 | -------------------------------------------------------------------------------- /build.conf: -------------------------------------------------------------------------------- 1 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | 5 | program resource-manager 6 | 7 | # to override musl libc register_t 8 | configs __DEFINED_register_t 9 | 10 | cflags -std=gnu18 11 | # Turn all warnings on as errors by default 12 | cflags -Weverything 13 | cflags -Werror 14 | 15 | # suppress the warning for header file from compiler 16 | # FIXME: double check if it's right 17 | #cflags -Wno-reserved-id-macro 18 | 19 | # Unused macros are expected 20 | #cflags -Wno-unused-macros 21 | 22 | # MISRA rule 16.4 requires default: in every switch, even if it is covered 23 | cflags -Wno-covered-switch-default 24 | 25 | # No need for C++ compatibility 26 | cflags -Wno-c++98-compat 27 | cflags -Wno-c++-compat 28 | 29 | # No need for pre-C99 compatibility; we always use C18 30 | cflags -Wno-declaration-after-statement 31 | 32 | # No need for GCC compatibility 33 | cflags -Wno-gcc-compat 34 | 35 | # Assume undefined macro as 0 36 | cflags -Wno-undef 37 | 38 | # Enable stack protection by default 39 | cflags -fstack-protector-strong 40 | 41 | # Section garbage collection, reduce size & do better job to remove dead code 42 | # it's better to disable them for gprof & debug. 43 | cflags -ffunction-sections 44 | cflags -fdata-sections 45 | 46 | # target specific cflags 47 | cflags -fpie 48 | 49 | # Generate DWARF compatible with older T32 releases 50 | cflags -gdwarf-4 51 | 52 | # target specific ldflags 53 | ldflags -static-pie 54 | 55 | # Use C18. For the purposes of MISRA, the language is C99 and all differences 56 | # between C99 and C18 are language extensions permitted by a project deviation 57 | # from rule 1.2. 58 | ldflags -Wl,--gc-sections 59 | 60 | ldflags -static 61 | ldflags -fuse-ld=lld --rtlib=compiler-rt 62 | 63 | # Set the max-page-size to prevent large ELF alignments 64 | ldflags -Wl,-z,max-page-size=4096 65 | # Set the separate-loadable-segments for ELF alignments 66 | ldflags -Wl,-z,separate-loadable-segments 67 | 68 | include include 69 | 70 | sub_directory src 71 | 72 | end_program 73 | -------------------------------------------------------------------------------- /config/arch/armv8.conf: -------------------------------------------------------------------------------- 1 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | 5 | base_arch gicv3 6 | 7 | target_triple aarch64-linux-gnu 8 | sub_directory arch/armv8 9 | -------------------------------------------------------------------------------- /config/arch/armv9.conf: -------------------------------------------------------------------------------- 1 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | 5 | base_arch gicv3 6 | 7 | # ARMv8 source is reused for ARMv9 8 | sub_directory arch/armv8 9 | 10 | # ARMv9 always supports PAuth and BTI extensions 11 | cflags -mbranch-protection=pac-ret+bti 12 | 13 | # SD-LLVM 12 uses the target triple to select a libc built with pacret+bti 14 | target_triple aarch64-pacret-bti-linux-gnu 15 | -------------------------------------------------------------------------------- /config/arch/gicv3.conf: -------------------------------------------------------------------------------- 1 | sub_directory arch/gicv3 2 | -------------------------------------------------------------------------------- /config/arch/qemu.conf: -------------------------------------------------------------------------------- 1 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | 5 | configs PLATFORM_QEMU=1 6 | 7 | configs LOG_AREA_SIZE=8192 8 | configs LOG_AREA_ALIGN=4096 9 | 10 | sub_directory platform/qemu 11 | -------------------------------------------------------------------------------- /config/platform/qemu.conf: -------------------------------------------------------------------------------- 1 | # © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | 5 | base_arch qemu 6 | base_arch armv8 7 | 8 | cflags -march=armv8.5-a+rng -mcpu=cortex-x1 9 | ldflags -mcpu=cortex-x1 10 | 11 | configs PLATFORM_QEMU=1 12 | 13 | configs PLATFORM_SVM_IPA_BASE=0x28800000 14 | configs PLATFORM_SVM_IPA_SIZE=0x07ffffff 15 | 16 | # Free range in HLOS map for virtio. Qemu places all its peripherals below 0x1000_0000 17 | # and has PCIe at 0x1000_0000, single controller with 256 max bus will span till 0x2000_0000 18 | # so consider taking from 0x3000_0000, right beside DDR range so that there is some 19 | # space remaining for other HW peripherals if required 20 | configs PLATFORM_HLOS_VIRTIO_FREE_IPA_BASE=0x30000000 21 | configs PLATFORM_HLOS_VIRTIO_FREE_IPA_SIZE=0x10000000 22 | 23 | configs PLATFORM_VM_DEBUG_ACCESS_ALLOWED=1 24 | 25 | configs PLATFORM_ALLOW_IOMEM_STATIC_SHARE=1 26 | -------------------------------------------------------------------------------- /config/quality/debug.conf: -------------------------------------------------------------------------------- 1 | # Debug build config 2 | 3 | configs CONFIG_DEBUG=1 4 | configs POST_BOOT_UART_DISABLE=1 5 | 6 | cflags -Os -g 7 | -------------------------------------------------------------------------------- /config/quality/production.conf: -------------------------------------------------------------------------------- 1 | # Production build config 2 | 3 | configs POST_BOOT_UART_DISABLE=1 4 | 5 | cflags -Os -flto -g 6 | -------------------------------------------------------------------------------- /include/assert.h: -------------------------------------------------------------------------------- 1 | // © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | typedef int line_number_t; 6 | 7 | #if defined(CONFIG_DEBUG) 8 | // Lightweight assert message without the function name 9 | #define assert(x) ((void)((x) || (rm_assert_fail((#x), __FILE__, __LINE__), 0))) 10 | 11 | _Noreturn void 12 | rm_assert_fail(const char *cond_fail, const char *file, line_number_t line); 13 | #else 14 | // Lightweight assert message without the condition and function name 15 | #define assert(x) ((void)((x) || (rm_assert_fail(__FILE__, __LINE__), 0))) 16 | 17 | _Noreturn void 18 | rm_assert_fail(const char *file, line_number_t line); 19 | #endif 20 | 21 | #define static_assert _Static_assert 22 | -------------------------------------------------------------------------------- /include/compiler.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // clang-format off 6 | #define compiler_ffs(x) (index_t)_Generic( \ 7 | (x), \ 8 | long long: __builtin_ffsll(x), \ 9 | unsigned long long: __builtin_ffsll((long long)(x)), \ 10 | long: __builtin_ffsl(x), \ 11 | unsigned long: __builtin_ffsl((long)(x)), \ 12 | int: __builtin_ffs(x), \ 13 | unsigned int: __builtin_ffs((int)(x))) 14 | 15 | #define compiler_clz(x) (assert((x) != 0U), (index_t)_Generic( \ 16 | (x), \ 17 | unsigned long long: __builtin_clzll, \ 18 | unsigned long: __builtin_clzl, \ 19 | unsigned int: __builtin_clz)(x)) 20 | 21 | #define compiler_ctz(x) (assert((x) != 0U), (index_t)_Generic( \ 22 | (x), \ 23 | unsigned long long: __builtin_ctzll, \ 24 | unsigned long: __builtin_ctzl, \ 25 | unsigned int: __builtin_ctz)(x)) 26 | 27 | #define compiler_clrsb(x) (index_t)_Generic( \ 28 | (x), long long: __builtin_clrsbll, \ 29 | long: __builtin_clrsbl, \ 30 | int: __builtin_clrsb)(x) 31 | // clang-format on 32 | -------------------------------------------------------------------------------- /include/cpio.h: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define CPIO_HEADER_MAGIC "070701" 6 | #define CPIO_FOOTER_MAGIC "TRAILER!!!" 7 | #define CPIO_CMDLINE ".cmdline" 8 | #define CPIO_ALIGNMENT 4U 9 | #define CPIO_FILE_MAXSIZE 0x10000U 10 | 11 | struct cpio_header { 12 | char c_magic[6]; 13 | char c_ino[8]; 14 | char c_mode[8]; 15 | char c_uid[8]; 16 | char c_gid[8]; 17 | char c_nlink[8]; 18 | char c_mtime[8]; 19 | char c_filesize[8]; 20 | char c_devmajor[8]; 21 | char c_devminor[8]; 22 | char c_rdevmajor[8]; 23 | char c_rdevminor[8]; 24 | char c_namesize[8]; 25 | char c_check[8]; 26 | }; 27 | -------------------------------------------------------------------------------- /include/dt_linux.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Interrupt specifier cell 0 6 | #define DT_GIC_SPI 0U 7 | #define DT_GIC_PPI 1U 8 | #define DT_GIC_ESPI 2U 9 | #define DT_GIC_EPPI 3U 10 | 11 | // Interrupt specifier cell 2 12 | #define DT_GIC_IRQ_TYPE_EDGE_RISING 1U 13 | #define DT_GIC_IRQ_TYPE_LEVEL_HIGH 4U 14 | -------------------------------------------------------------------------------- /include/dt_overlay.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Wrappers for device tree binary overlay creation. 6 | // This set of APIs are implmeneted based on libfdt library. It supports the 7 | // basic operation to add/modify the existing device tree node/property. 8 | // Most of the API use full path to refer a node/property. 9 | // Due to the libfdt only support sequential write, the API are defined as a 10 | // sequential write style. 11 | 12 | #define DTB_NODE_NAME_MAX 128U 13 | #define DTBO_MAX_SIZE (4U * PAGE_SIZE) 14 | 15 | // Mark unset phandles with only the high bit, because this is unlikely to 16 | // silently turn into an incorrect valid phandle during overlay application due 17 | // to local fixups. If we set it to -1 it would be replaced by the last valid 18 | // phandle in the base DTB, which is not what we want. 19 | // 20 | // This is used for internal references. For external refererences, we use an 21 | // invalid value of -1. 22 | #define DTO_PHANDLE_UNSET (uint32_t)0x80000000U 23 | 24 | typedef struct dto_s dto_t; 25 | 26 | #define CHECK_DTO(ret_val, dto_call) \ 27 | do { \ 28 | ret_val = (dto_call); \ 29 | if (ret_val != OK) { \ 30 | goto out; \ 31 | } \ 32 | } while (0) 33 | 34 | dto_t * 35 | dto_init(void *external_memory, size_t memory_size); 36 | 37 | // Start to modify a node, it will create a fragment for that target. 38 | // And return it's path to buf 39 | error_t 40 | dto_modify_begin(dto_t *dto, const char *target); 41 | 42 | error_t 43 | dto_modify_end(dto_t *dto, const char *target); 44 | 45 | error_t 46 | dto_modify_begin_by_path(dto_t *dto, const char *target); 47 | 48 | error_t 49 | dto_modify_end_by_path(dto_t *dto, const char *target); 50 | 51 | error_t 52 | dto_modify_begin_by_phandle(dto_t *dto, uint32_t target); 53 | 54 | error_t 55 | dto_modify_end_by_phandle(dto_t *dto, uint32_t target); 56 | 57 | error_t 58 | dto_node_begin(dto_t *dto, const char *name); 59 | 60 | error_t 61 | dto_node_end(dto_t *dto, const char *name); 62 | 63 | error_t 64 | dto_property_add_u32(dto_t *dto, const char *name, uint32_t val); 65 | 66 | error_t 67 | dto_property_add_u64(dto_t *dto, const char *name, uint64_t val); 68 | 69 | error_t 70 | dto_property_add_u32array(dto_t *dto, const char *name, uint32_t vals[], 71 | count_t cnt); 72 | 73 | error_t 74 | dto_property_add_u64array(dto_t *dto, const char *name, uint64_t vals[], 75 | count_t cnt); 76 | 77 | // Blob is a user defined format, so the data size bigger than char needs to 78 | // be converted to fdt order(endian) before adding. 79 | error_t 80 | dto_property_add_blob(dto_t *dto, const char *name, uint8_t vals[], 81 | count_t cnt); 82 | 83 | error_t 84 | dto_property_add_string(dto_t *dto, const char *name, const char *val); 85 | 86 | error_t 87 | dto_property_add_stringlist(dto_t *dto, const char *name, const char *vals[], 88 | count_t cnt); 89 | 90 | // In order to be referred by others, a node must add a phandle property. 91 | // It will generate a phandle under current node. 92 | error_t 93 | dto_property_add_phandle(dto_t *dto, uint32_t *pphandle); 94 | 95 | // Add an address range property, given the values of the parent node's 96 | // #addr-cells and #size-cells properties. Note that for overlays these might 97 | // need to be obtained from a parent node in the base device tree. 98 | error_t 99 | dto_property_add_addrrange(dto_t *dto, const char *name, count_t addr_cells, 100 | uint64_t addr, count_t size_cells, uint64_t size); 101 | 102 | // An address range for dto_property_add_addrrange_array(). 103 | typedef struct { 104 | uint64_t addr; 105 | uint64_t size; 106 | } dto_addrrange_t; 107 | 108 | // Add an array of address range properties, given the values of the parent 109 | // node's #addr-cells and #size-cells properties. Note that for overlays these 110 | // might need to be obtained from a parent node in the base device tree. 111 | error_t 112 | dto_property_add_addrrange_array(dto_t *dto, const char *name, 113 | const dto_addrrange_t ranges[], 114 | count_t entries, count_t addr_cells, 115 | count_t size_cells); 116 | 117 | // Add an array of interrupts, normally for the "interrupts" property. 118 | error_t 119 | dto_property_add_interrupts_array(dto_t *dto, const char *name, 120 | const interrupt_data_t *interrupts, 121 | count_t entries); 122 | 123 | // Add an external reference, it's a phandle property, the value is set to 124 | // 0xFFFFFFFF, and a fixup entry is added. 125 | error_t 126 | dto_property_ref_external(dto_t *dto, const char *property_name, 127 | const char *target_label); 128 | 129 | // Just helper utility to ref internal. 130 | error_t 131 | dto_property_ref_internal(dto_t *dto, const char *name, uint32_t phandle); 132 | 133 | error_t 134 | dto_property_add_empty(dto_t *dto, const char *name); 135 | 136 | // Construct modification path node. 137 | // This call starts a new overlay fragment at root '/', and then constructs the 138 | // path nodes one by one. 139 | // Note: dto_construct_begin_path cannot be nested. 140 | error_t 141 | dto_construct_begin_path(dto_t *dto, const char *path); 142 | 143 | // This call ends the dto fragment node and finalizes the modification. 144 | error_t 145 | dto_construct_end_path(dto_t *dto, const char *path); 146 | 147 | error_t 148 | dto_finalise(dto_t *dto); 149 | 150 | void * 151 | dto_get_dtbo(dto_t *dto); 152 | 153 | size_t 154 | dto_get_size(dto_t *dto); 155 | 156 | void 157 | dto_deinit(dto_t *dto); 158 | -------------------------------------------------------------------------------- /include/dtb_parser.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Parse vm config device tree node, and trigger visitors based on provided 6 | // condition. 7 | 8 | RM_PADDED(typedef struct { 9 | count_t addr_cells; 10 | count_t size_cells; 11 | bool addr_is_phys; 12 | 13 | count_t child_addr_cells; 14 | count_t child_size_cells; 15 | bool child_addr_is_phys; 16 | bool child_cells_default; 17 | } ctx_t) 18 | 19 | typedef enum { 20 | BY_PATH, 21 | BY_STRING_PROP, 22 | BY_COMPATIBLE, 23 | } listener_trigger_type_t; 24 | 25 | typedef enum { 26 | RET_CONTINUE, 27 | RET_ERROR, 28 | RET_STOP, 29 | RET_CLAIMED, 30 | } listener_return_t; 31 | 32 | struct dtb_parser_data_s; 33 | typedef struct dtb_parser_data_s dtb_parser_data_t; 34 | typedef listener_return_t (*action_t)(dtb_parser_data_t *data, const void *fdt, 35 | int node_ofs, const ctx_t *ctx); 36 | 37 | struct dtb_parser_alloc_params_s; 38 | typedef struct dtb_parser_alloc_params_s dtb_parser_alloc_params_t; 39 | typedef dtb_parser_data_t *(*dtb_parser_data_alloc_t)( 40 | const dtb_parser_alloc_params_t *params); 41 | 42 | typedef void (*dtb_parser_data_free_t)(dtb_parser_data_t *data); 43 | 44 | typedef struct { 45 | listener_trigger_type_t type; 46 | uint8_t type_padding[4]; 47 | 48 | union { 49 | char *expected_path; 50 | 51 | struct { 52 | char *string_prop_name; 53 | char *expected_string; 54 | }; 55 | 56 | char *compatible_string; 57 | }; 58 | 59 | action_t action; 60 | } dtb_listener_t; 61 | 62 | struct dtb_parser_ops { 63 | dtb_parser_data_alloc_t alloc; 64 | 65 | dtb_listener_t *listeners; 66 | 67 | size_t listener_cnt; 68 | 69 | dtb_parser_data_free_t free; 70 | }; 71 | typedef struct dtb_parser_ops dtb_parser_ops_t; 72 | 73 | RM_PADDED(typedef struct { 74 | error_t err; 75 | dtb_parser_data_t *r; 76 | } dtb_parser_parse_dtb_ret_t) 77 | 78 | dtb_parser_parse_dtb_ret_t 79 | dtb_parser_parse_dtb(const void *fdt, const dtb_parser_ops_t *ops, 80 | const dtb_parser_alloc_params_t *params); 81 | 82 | error_t 83 | dtb_parser_free(const dtb_parser_ops_t *ops, dtb_parser_data_t *data); 84 | 85 | // utilities 86 | 87 | void 88 | dtb_parser_update_ctx(const void *fdt, int node_ofs, const ctx_t *parent, 89 | ctx_t *child); 90 | 91 | ctx_t 92 | dtb_parser_get_ctx(const void *fdt, int node_ofs); 93 | 94 | uint64_t 95 | fdt_read_num(const fdt32_t *data, size_t cell_cnt); 96 | 97 | error_t 98 | fdt_getprop_u32(const void *fdt, int node_ofs, const char *propname, 99 | uint32_t *val); 100 | 101 | error_t 102 | fdt_getprop_s32(const void *fdt, int node_ofs, const char *propname, 103 | int32_t *val); 104 | 105 | error_t 106 | fdt_getprop_u64(const void *fdt, int node_ofs, const char *propname, 107 | uint64_t *val); 108 | 109 | error_t 110 | fdt_getprop_u32_array(const void *fdt, int node_ofs, const char *propname, 111 | uint32_t *array, size_t array_size, count_t *count); 112 | 113 | error_t 114 | fdt_getprop_num(const void *fdt, int node_ofs, const char *propname, 115 | count_t cells, uint64_t *val); 116 | 117 | bool 118 | fdt_getprop_bool(const void *fdt, int node_ofs, const char *propname); 119 | -------------------------------------------------------------------------------- /include/elf.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | typedef uint16_t Elf_Half; 6 | typedef uint32_t Elf_Word; 7 | typedef int32_t Elf_Sword; 8 | typedef int64_t Elf_Sxword; 9 | typedef uint64_t Elf_Xword; 10 | 11 | typedef uint32_t Elf32_Addr; 12 | typedef uint32_t Elf32_Off; 13 | typedef uint64_t Elf64_Addr; 14 | typedef uint64_t Elf64_Off; 15 | 16 | typedef unsigned Elf_Class; 17 | typedef unsigned char Elf_Ident; 18 | 19 | #define EI_NIDENT 16U 20 | 21 | #define EI_MAG_STR \ 22 | "\x7f" \ 23 | "ELF" 24 | #define EI_MAG_SIZE 4U 25 | 26 | #define EI_CLASS 4U 27 | #define EI_DATA 5U 28 | #define EI_VERSION 6U 29 | #define EI_OSABI 7U 30 | #define EI_ABIVERSION 8U 31 | #define EI_PAD 9U 32 | 33 | #define ELF_CLASS_NONE 0U 34 | #define ELF_CLASS_32 1U 35 | #define ELF_CLASS_64 2U 36 | 37 | #define ELF_DATA_NONE 0U 38 | #define ELF_DATA_2LSB 1U 39 | #define ELF_DATA_2MSB 2U 40 | 41 | #define EV_NONE 0U 42 | #define EV_CURRENT 1U 43 | 44 | #define ET_NONE 0U 45 | #define ET_REL 1U 46 | #define ET_EXEC 2U 47 | #define ET_DYN 3U 48 | #define ET_CORE 4U 49 | 50 | #define PT_NULL 0U 51 | #define PT_LOAD 1U 52 | #define PT_DYNAMIC 2U 53 | #define PT_INTERP 3U 54 | #define PT_NOTE 4U 55 | #define PT_SHLIB 5U 56 | #define PT_PHDR 6U 57 | #define PT_TLS 7U 58 | #define PT_NUM 8U 59 | 60 | #define PF_X 1U 61 | #define PF_W 2U 62 | #define PF_R 4U 63 | #define PF_QCOM_RELOCATABLE 0x08000000U 64 | 65 | typedef struct { 66 | Elf_Ident e_ident[EI_NIDENT]; 67 | 68 | Elf_Half e_type; 69 | Elf_Half e_machine; 70 | Elf_Word e_version; 71 | Elf32_Addr e_entry; 72 | Elf32_Off e_phoff; 73 | Elf32_Off e_shoff; 74 | Elf_Word e_flags; 75 | 76 | Elf_Half e_ehsize; 77 | Elf_Half e_phentsize; 78 | Elf_Half e_phnum; 79 | Elf_Half e_shentsize; 80 | Elf_Half e_shnum; 81 | Elf_Half e_shstrndx; 82 | } Elf32_Ehdr; 83 | 84 | typedef struct { 85 | Elf_Word p_type; 86 | Elf32_Off p_offset; 87 | Elf32_Addr p_vaddr; 88 | Elf32_Addr p_paddr; 89 | Elf_Word p_filesz; 90 | Elf_Word p_memsz; 91 | Elf_Word p_flags; 92 | Elf_Word p_align; 93 | } Elf32_Phdr; 94 | 95 | typedef struct { 96 | Elf_Ident e_ident[EI_NIDENT]; 97 | 98 | Elf_Half e_type; 99 | Elf_Half e_machine; 100 | Elf_Word e_version; 101 | Elf64_Addr e_entry; 102 | Elf64_Off e_phoff; 103 | Elf64_Off e_shoff; 104 | Elf_Word e_flags; 105 | 106 | Elf_Half e_ehsize; 107 | Elf_Half e_phentsize; 108 | Elf_Half e_phnum; 109 | Elf_Half e_shentsize; 110 | Elf_Half e_shnum; 111 | Elf_Half e_shstrndx; 112 | } Elf64_Ehdr; 113 | 114 | typedef struct { 115 | Elf_Word p_type; 116 | Elf_Word p_flags; 117 | Elf64_Off p_offset; 118 | Elf64_Addr p_vaddr; 119 | Elf64_Addr p_paddr; 120 | Elf_Xword p_filesz; 121 | Elf_Xword p_memsz; 122 | Elf_Xword p_align; 123 | } Elf64_Phdr; 124 | 125 | typedef union { 126 | Elf32_Ehdr *ehdr32; 127 | Elf64_Ehdr *ehdr64; 128 | } Elf_Ehdr_ptr; 129 | 130 | typedef union { 131 | Elf32_Phdr *phdr32; 132 | Elf64_Phdr *phdr64; 133 | } Elf_Phdr_ptr; 134 | 135 | // These macros assume the pointer is valid and CLASS has been checked as 136 | // supported. 137 | #define elf_get_ehdr_field(ehdr, field) \ 138 | ((elf_get_ehdr_class(ehdr) == ELF_CLASS_32) ? ((ehdr).ehdr32->field) \ 139 | : ((ehdr).ehdr64->field)) 140 | 141 | #define elf_get_phdr_field(class, phdr, i, field) \ 142 | (((class) == ELF_CLASS_32) ? ((phdr).phdr32[(i)].field) \ 143 | : ((phdr).phdr64[(i)].field)) 144 | 145 | Elf_Class 146 | elf_get_ehdr_class(Elf_Ehdr_ptr ehdr); 147 | 148 | size_t 149 | elf_ehdr_size(Elf_Ehdr_ptr ehdr); 150 | 151 | bool 152 | elf_ehdr_valid(Elf_Ehdr_ptr ehdr); 153 | 154 | bool 155 | elf_ehdr_is_class(Elf_Ehdr_ptr ehdr, Elf_Class class); 156 | 157 | rm_error_t 158 | elf_get_phdr_offset(Elf_Ehdr_ptr ehdr, size_t image_size, size_t *e_phoff); 159 | 160 | bool 161 | elf_segment_is_loadable(Elf_Class class, Elf_Phdr_ptr phdrs, index_t seg_num); 162 | 163 | bool 164 | elf_segment_is_relocatable(Elf_Class class, Elf_Phdr_ptr phdrs, 165 | index_t seg_num); 166 | 167 | bool 168 | elf_valid_ptload_segment(index_t seg_num, size_t p_memsz, size_t segment_offset, 169 | index_t segment_count, 170 | const boot_env_phys_range_t *vm_segments, 171 | vmaddr_t mem_size); 172 | 173 | bool 174 | elf_segment_contains_dt(const uint32_t *first_word, bool *single_dtb); 175 | -------------------------------------------------------------------------------- /include/event.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define EVENT_FD_READ (1 << 0) 6 | #define EVENT_FD_WRITE (1 << 1) 7 | 8 | typedef struct event_s event_t; 9 | typedef void (*event_callback_t)(event_t *event, void *data); 10 | 11 | #pragma clang diagnostic push 12 | #pragma clang diagnostic ignored "-Wpadded" 13 | 14 | struct event_s { 15 | event_t *next; 16 | event_t *prev; 17 | event_callback_t callback; 18 | bool pending; 19 | void *data; 20 | int fd; 21 | }; 22 | 23 | #pragma clang diagnostic pop 24 | 25 | error_t 26 | event_init(void); 27 | 28 | void 29 | event_loop_enter(void); 30 | 31 | void 32 | event_loop_enter_suspend(int timeout); 33 | 34 | void 35 | event_loop_exit(void); 36 | 37 | bool 38 | event_is_pending(void); 39 | 40 | bool 41 | event_is_registered(event_t *event); 42 | 43 | void 44 | event_flush_pending(void); 45 | 46 | bool 47 | event_wait_pending(int timeout); 48 | 49 | error_t 50 | event_register(event_t *event, event_callback_t callback, void *data); 51 | 52 | error_t 53 | event_set_fd_trigger(event_t *event, int fd, int flags); 54 | 55 | bool 56 | event_deregister(event_t *event); 57 | 58 | bool 59 | event_trigger(event_t *event); 60 | -------------------------------------------------------------------------------- /include/exit_dev.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | rm_error_t 6 | register_exit(void); 7 | 8 | rm_error_t 9 | deregister_exit(void); 10 | -------------------------------------------------------------------------------- /include/guest_rights.h: -------------------------------------------------------------------------------- 1 | // Automatically generated. Do not modify. 2 | // 3 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 4 | // 5 | // SPDX-License-Identifier: BSD-3-Clause 6 | 7 | // Hypervisor Cap Rights 8 | 9 | #define CAP_RIGHTS_GENERIC_OBJECT_ACTIVATE (cap_rights_t)0x80000000U 10 | #define CAP_RIGHTS_GENERIC_ALL (cap_rights_t)0x80000000U 11 | 12 | #define CAP_RIGHTS_ADDRSPACE_ATTACH (cap_rights_t)0x1U 13 | #define CAP_RIGHTS_ADDRSPACE_MAP (cap_rights_t)0x2U 14 | #define CAP_RIGHTS_ADDRSPACE_LOOKUP (cap_rights_t)0x4U 15 | #define CAP_RIGHTS_ADDRSPACE_ADD_VMMIO_RANGE (cap_rights_t)0x8U 16 | #define CAP_RIGHTS_ADDRSPACE_OBJECT_ACTIVATE (cap_rights_t)0x80000000U 17 | #define CAP_RIGHTS_ADDRSPACE_ALL (cap_rights_t)0x8000000fU 18 | 19 | #define CAP_RIGHTS_CSPACE_CAP_CREATE (cap_rights_t)0x1U 20 | #define CAP_RIGHTS_CSPACE_CAP_DELETE (cap_rights_t)0x2U 21 | #define CAP_RIGHTS_CSPACE_CAP_COPY (cap_rights_t)0x4U 22 | #define CAP_RIGHTS_CSPACE_ATTACH (cap_rights_t)0x8U 23 | #define CAP_RIGHTS_CSPACE_CAP_REVOKE (cap_rights_t)0x10U 24 | #define CAP_RIGHTS_CSPACE_OBJECT_ACTIVATE (cap_rights_t)0x80000000U 25 | #define CAP_RIGHTS_CSPACE_ALL (cap_rights_t)0x8000001fU 26 | 27 | #define CAP_RIGHTS_DOORBELL_SEND (cap_rights_t)0x1U 28 | #define CAP_RIGHTS_DOORBELL_RECEIVE (cap_rights_t)0x2U 29 | #define CAP_RIGHTS_DOORBELL_BIND (cap_rights_t)0x4U 30 | #define CAP_RIGHTS_DOORBELL_OBJECT_ACTIVATE (cap_rights_t)0x80000000U 31 | #define CAP_RIGHTS_DOORBELL_ALL (cap_rights_t)0x80000007U 32 | 33 | #define CAP_RIGHTS_HWIRQ_BIND_VIC (cap_rights_t)0x2U 34 | #define CAP_RIGHTS_HWIRQ_OBJECT_ACTIVATE (cap_rights_t)0x80000000U 35 | #define CAP_RIGHTS_HWIRQ_ALL (cap_rights_t)0x80000002U 36 | 37 | #define CAP_RIGHTS_MEMEXTENT_MAP (cap_rights_t)0x1U 38 | #define CAP_RIGHTS_MEMEXTENT_DERIVE (cap_rights_t)0x2U 39 | #define CAP_RIGHTS_MEMEXTENT_ATTACH (cap_rights_t)0x4U 40 | #define CAP_RIGHTS_MEMEXTENT_LOOKUP (cap_rights_t)0x8U 41 | #define CAP_RIGHTS_MEMEXTENT_DONATE (cap_rights_t)0x10U 42 | #define CAP_RIGHTS_MEMEXTENT_OBJECT_ACTIVATE (cap_rights_t)0x80000000U 43 | #define CAP_RIGHTS_MEMEXTENT_ALL (cap_rights_t)0x8000001fU 44 | 45 | #define CAP_RIGHTS_MSGQUEUE_SEND (cap_rights_t)0x1U 46 | #define CAP_RIGHTS_MSGQUEUE_RECEIVE (cap_rights_t)0x2U 47 | #define CAP_RIGHTS_MSGQUEUE_BIND_SEND (cap_rights_t)0x4U 48 | #define CAP_RIGHTS_MSGQUEUE_BIND_RECEIVE (cap_rights_t)0x8U 49 | #define CAP_RIGHTS_MSGQUEUE_OBJECT_ACTIVATE (cap_rights_t)0x80000000U 50 | #define CAP_RIGHTS_MSGQUEUE_ALL (cap_rights_t)0x8000000fU 51 | 52 | #define CAP_RIGHTS_PARTITION_OBJECT_CREATE (cap_rights_t)0x1U 53 | #define CAP_RIGHTS_PARTITION_DONATE (cap_rights_t)0x2U 54 | #define CAP_RIGHTS_PARTITION_OBJECT_ACTIVATE (cap_rights_t)0x80000000U 55 | #define CAP_RIGHTS_PARTITION_ALL (cap_rights_t)0x80000003U 56 | 57 | #define CAP_RIGHTS_THREAD_POWER (cap_rights_t)0x1U 58 | #define CAP_RIGHTS_THREAD_AFFINITY (cap_rights_t)0x2U 59 | #define CAP_RIGHTS_THREAD_PRIORITY (cap_rights_t)0x4U 60 | #define CAP_RIGHTS_THREAD_TIMESLICE (cap_rights_t)0x8U 61 | #define CAP_RIGHTS_THREAD_YIELD_TO (cap_rights_t)0x10U 62 | #define CAP_RIGHTS_THREAD_BIND_VIRQ (cap_rights_t)0x20U 63 | #define CAP_RIGHTS_THREAD_STATE (cap_rights_t)0x40U 64 | #define CAP_RIGHTS_THREAD_LIFECYCLE (cap_rights_t)0x80U 65 | #define CAP_RIGHTS_THREAD_WRITE_CONTEXT (cap_rights_t)0x100U 66 | #define CAP_RIGHTS_THREAD_DISABLE (cap_rights_t)0x200U 67 | #define CAP_RIGHTS_THREAD_OBJECT_ACTIVATE (cap_rights_t)0x80000000U 68 | #define CAP_RIGHTS_THREAD_ALL (cap_rights_t)0x800003ffU 69 | 70 | #define CAP_RIGHTS_VIC_BIND_SOURCE (cap_rights_t)0x1U 71 | #define CAP_RIGHTS_VIC_ATTACH_VCPU (cap_rights_t)0x2U 72 | #define CAP_RIGHTS_VIC_ATTACH_VDEVICE (cap_rights_t)0x4U 73 | #define CAP_RIGHTS_VIC_OBJECT_ACTIVATE (cap_rights_t)0x80000000U 74 | #define CAP_RIGHTS_VIC_ALL (cap_rights_t)0x80000007U 75 | 76 | #define CAP_RIGHTS_VIRTIO_MMIO_BIND_BACKEND_VIRQ (cap_rights_t)0x1U 77 | #define CAP_RIGHTS_VIRTIO_MMIO_BIND_FRONTEND_VIRQ (cap_rights_t)0x2U 78 | #define CAP_RIGHTS_VIRTIO_MMIO_ASSERT_VIRQ (cap_rights_t)0x4U 79 | #define CAP_RIGHTS_VIRTIO_MMIO_CONFIG (cap_rights_t)0x8U 80 | #define CAP_RIGHTS_VIRTIO_MMIO_OBJECT_ACTIVATE (cap_rights_t)0x80000000U 81 | #define CAP_RIGHTS_VIRTIO_MMIO_ALL (cap_rights_t)0x8000000fU 82 | 83 | #define CAP_RIGHTS_VPM_GROUP_ATTACH_VCPU (cap_rights_t)0x1U 84 | #define CAP_RIGHTS_VPM_GROUP_BIND_VIRQ (cap_rights_t)0x2U 85 | #define CAP_RIGHTS_VPM_GROUP_QUERY (cap_rights_t)0x4U 86 | #define CAP_RIGHTS_VPM_GROUP_OBJECT_ACTIVATE (cap_rights_t)0x80000000U 87 | #define CAP_RIGHTS_VPM_GROUP_ALL (cap_rights_t)0x80000007U 88 | 89 | #define CAP_RIGHTS_VRTC_CONFIGURE (cap_rights_t)0x1U 90 | #define CAP_RIGHTS_VRTC_ATTACH_ADDRSPACE (cap_rights_t)0x2U 91 | #define CAP_RIGHTS_VRTC_SET_TIME_BASE (cap_rights_t)0x4U 92 | #define CAP_RIGHTS_VRTC_OBJECT_ACTIVATE (cap_rights_t)0x80000000U 93 | #define CAP_RIGHTS_VRTC_ALL (cap_rights_t)0x80000007U 94 | -------------------------------------------------------------------------------- /include/irq_manager.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // IRQ manager design: 6 | // 7 | // Requirements: 8 | // 1. Track HW IRQ ownership 9 | // 2. Track HW IRQ lending state 10 | // 3. Manage VM's IRQ namespace 11 | // 4. Manage VM's virqs (partial) 12 | // 5. Track reserved IRQ numbers for future HW assignments / lends etc. 13 | // 6. Handle IRQ lending, accepting, release, return protocol 14 | // IRQ handles etc. 15 | // 16 | // We don't handle cpulocal irq partitions (IRQs bound to a single or group of 17 | // CPUs). 18 | // We don't support lending a VM's virqs. 19 | // 20 | // Every IRQ, whether it is cpulocal or global (or cpulocal partitioned) has a 21 | // unique HW irq number in the irq_manager interface. The mapping to HW irqs is 22 | // platform specific. 23 | // 24 | // IRQ types are handled separately in the API only where the difference is 25 | // important. 26 | 27 | // Initialize the irq_manager globally 28 | error_t 29 | irq_manager_init(const rm_env_data_t *env_data); 30 | 31 | // De-initialize the irq_manager 32 | void 33 | irq_manager_deinit(void); 34 | 35 | // Add a HW IRQ to the irq_manager 36 | // Requires cap-id and owner VMID 37 | error_t 38 | irq_manager_hwirq_add(uint32_t hw_irq_number, cap_id_t capid, vmid_t owner); 39 | 40 | // Donate a HW IRQ to another VMID 41 | // The HW IRQ must not be mapped or currently lending 42 | error_t 43 | irq_manager_hwirq_donate(uint32_t hw_irq_number, vmid_t owner); 44 | 45 | // Lookup the owner of a HW global IRQ 46 | vmid_result_t 47 | irq_manager_hwirq_get_owner(uint32_t hw_irq_number); 48 | 49 | // Initialize the irq_manager structures for a VM 50 | error_t 51 | irq_manager_vm_init(vm_t *vm, cap_id_t vic, count_t max_irq); 52 | 53 | // Indicate to the irq_manager that the VM is being reset 54 | void 55 | irq_manager_vm_reset(vm_t *vm); 56 | 57 | // De-initialize and clean-up VM irq_manager structures 58 | // Requires all interrupts to be unmapped from the VM 59 | void 60 | irq_manager_vm_deinit(vm_t *vm); 61 | 62 | // Allocate and reserve a global IRQ number in the VM. A reserved IRQ won't be 63 | // available for subsequent allocation, however it may be used when mapping 64 | // interrupts. 65 | uint32_result_t 66 | irq_manager_vm_alloc_global(const vm_t *vm); 67 | 68 | // Reserve a global IRQ number in the VM. A reserved IRQ won't be available for 69 | // subsequent allocation, however it may be used when mapping interrupts. 70 | error_t 71 | irq_manager_vm_reserve_global(const vm_t *vm, uint32_t irq_number); 72 | 73 | // Un-reserve / free a reserved global IRQ. 74 | // The IRQ may not be mapped or currently lending. 75 | error_t 76 | irq_manager_vm_free_global(const vm_t *vm, uint32_t irq_number); 77 | 78 | // Map all IRQs owned by the VM as direct (1:1) 79 | // Typically only used for HLOS init. 80 | error_t 81 | irq_manager_vm_hwirq_map_all_direct(const vm_t *vm); 82 | 83 | // Map a HW IRQ to the VM. 84 | // If `alloc` is true, the irq_number is assumed to be unused and is allocated. 85 | // If false, it is assumed that the IRQ number previously allocated, such as 86 | // via irq_manager_vm_alloc_global(). 87 | // Note, this does not actually map the virq, since binding virqs is source 88 | // specific. 89 | error_t 90 | irq_manager_vm_hwirq_map(const vm_t *vm, uint32_t irq_number, 91 | uint32_t hw_irq_number, bool alloc); 92 | 93 | // Unmap a HW IRQ from a VM. 94 | // If `free_irq` is true, the irq_number is deallocated. If false, the IRQ 95 | // number becomes reserved. 96 | // Note, this does not actually map the virq, since binding virqs is source 97 | // specific. 98 | error_t 99 | irq_manager_vm_hwirq_unmap(const vm_t *vm, uint32_t irq_number, bool free_irq); 100 | 101 | // Add a virq to the VM's irq_manager tracking. 102 | // If `alloc` is true, the irq_number is assumed to be unused and is allocated. 103 | // If false, it is assumed that the IRQ number previously allocated, such as 104 | // via irq_manager_vm_alloc_global(). 105 | // Note, this does not actually map the virq, since binding virqs is source 106 | // specific. 107 | error_t 108 | irq_manager_vm_virq_map(const vm_t *vm, uint32_t irq_number, bool alloc); 109 | 110 | // Remove an VIRQ from the VM's irq_manager tracking. 111 | // If `free_irq` is true, the IRQ number is freed, otherwise it remains a 112 | // reserved IRQ number. 113 | error_t 114 | irq_manager_vm_virq_unmap(const vm_t *vm, uint32_t irq_number, bool free_irq); 115 | 116 | // Lend a restricted IRQ to a VM. 117 | // This is a temporary API, will be removed once restricted IRQs are replaced 118 | // with IRQ ownership configuration. 119 | error_t 120 | irq_manager_vm_restricted_lend(const vm_t *vm, uint32_t irq_number, 121 | uint32_t hw_irq_number); 122 | 123 | // Static lend an HLOS IRQ to a trusted VM. 124 | // This is a temporary API, will be removed once static lend IRQs are replaced 125 | // with dynamic IRQ lends. 126 | error_t 127 | irq_manager_vm_static_lend(const vm_t *vm, uint32_t irq_number, 128 | uint32_t hw_irq_number); 129 | 130 | // Handle VM reset and release all borrowed IRQs 131 | bool 132 | vm_reset_handle_release_irqs(vmid_t vmid); 133 | 134 | // IRQ-lending handling 135 | bool 136 | irq_manager_lending_msg_handler(vmid_t client_id, uint32_t msg_id, 137 | uint16_t seq_num, void *buf, size_t len); 138 | -------------------------------------------------------------------------------- /include/irq_message.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define VM_IRQ_ACCEPT 0x56000050 6 | #define VM_IRQ_LEND 0x56000051 7 | #define VM_IRQ_RELEASE 0x56000052 8 | #define VM_IRQ_RECLAIM 0x56000053 9 | #define VM_IRQ_NOTIFY 0x56000054 10 | #define VM_IRQ_UNMAP 0x56000055 11 | 12 | #define NOTIFY_VM_IRQ_LENT 0x56100011 13 | #define NOTIFY_VM_IRQ_RELEASED 0x56100012 14 | #define NOTIFY_VM_IRQ_ACCEPTED 0x56100013 15 | 16 | typedef uint16_t cpu_idx_t; 17 | typedef uint32_t virq_handle_t; // remove 18 | typedef uint32_t irq_handle_t; 19 | typedef uint32_t label_t; 20 | typedef uint32_t virq_notify_flag_t; 21 | typedef uint32_t msg_id_t; 22 | 23 | #define VIRQ_NOTIFY_FLAG_LENT 1U 24 | #define VIRQ_NOTIFY_FLAG_RELEASED 2U 25 | #define VIRQ_NOTIFY_FLAG_ACCEPTED 4U 26 | 27 | typedef struct { 28 | virq_handle_t handle; 29 | virq_t virq_num; 30 | } rm_irq_accept_req_t; 31 | 32 | typedef struct { 33 | virq_t virq_num; 34 | } rm_irq_accept_reply_t; 35 | 36 | typedef struct { 37 | vmid_t borrower; 38 | char _pad[2]; 39 | virq_t virq_num; 40 | label_t label; 41 | } rm_irq_lend_req_t; 42 | 43 | typedef struct { 44 | virq_handle_t handle; 45 | } rm_irq_lend_reply_t; 46 | 47 | typedef struct { 48 | virq_handle_t handle; 49 | } rm_irq_release_req_t; 50 | 51 | typedef struct { 52 | virq_handle_t handle; 53 | } rm_irq_reclaim_req_t; 54 | 55 | typedef struct { 56 | vmid_t vmid; 57 | char _pad[2]; 58 | } rm_irq_notify_vmid_t; 59 | 60 | typedef struct { 61 | virq_handle_t handle; 62 | virq_notify_flag_t flags; 63 | } rm_irq_notify_req_t; 64 | 65 | typedef struct { 66 | rm_irq_notify_req_t req; 67 | uint16_t notify_vmid_entries; 68 | char _pad[2]; 69 | rm_irq_notify_vmid_t notify_vmids[]; 70 | } rm_irq_notify_lent_req_t; 71 | 72 | typedef struct { 73 | size_t virq_entry_cnt; 74 | virq_t virq_nums[]; 75 | } rm_irq_unmap_req_t; 76 | 77 | typedef struct { 78 | vmid_t owner; 79 | char _pad[2]; 80 | virq_handle_t virq_handle; 81 | label_t virq_label; 82 | } rm_irq_lent_notify_t; 83 | 84 | typedef struct { 85 | virq_handle_t virq_handle; 86 | } rm_irq_owner_notify_t; 87 | -------------------------------------------------------------------------------- /include/log.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define LOG(fmt, ...) (void)printf(fmt, __VA_ARGS__) 6 | 7 | #define LOG_LOC(msg) (void)printf("%s %d: %s\n", __FILE__, __LINE__, msg) 8 | #define LOG_ERR(err) (void)printf("Error: %s %d: %d\n", __FILE__, __LINE__, err) 9 | 10 | typedef uint32_t rm_error_t; 11 | 12 | rm_error_t 13 | log_reconfigure(uintptr_t *log_buf, size_t size); 14 | 15 | rm_error_t 16 | log_expose_to_hlos(uintptr_t log_buf, size_t size); 17 | -------------------------------------------------------------------------------- /include/mem_region.h: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | typedef struct mem_region { 6 | uint32_t phys_pn; 7 | uint32_t size_pn; 8 | uint32_t ipa_pn; 9 | uint32_t mpd_sanitise_refcount; 10 | } mem_region_t; 11 | 12 | mem_region_t 13 | mem_region_init(paddr_t phys, size_t size, vmaddr_t owner_ipa); 14 | 15 | paddr_t 16 | mem_region_get_phys(mem_region_t region); 17 | 18 | size_t 19 | mem_region_get_size(mem_region_t region); 20 | 21 | vmaddr_t 22 | mem_region_get_owner_ipa(mem_region_t region); 23 | 24 | uint32_t 25 | mem_region_get_mpd_sanitise_refcount(const mem_region_t *region); 26 | 27 | void 28 | mem_region_increment_mpd_sanitise_refcount(mem_region_t *region); 29 | 30 | void 31 | mem_region_decrement_mpd_sanitise_refcount(mem_region_t *region); 32 | 33 | typedef struct ipa_region { 34 | uint32_t ipa_pn; 35 | } ipa_region_t; 36 | 37 | ipa_region_t 38 | ipa_region_init(vmaddr_t ipa); 39 | 40 | vmaddr_t 41 | ipa_region_get_ipa(ipa_region_t region); 42 | 43 | typedef struct region_list_s region_list_t; 44 | 45 | region_list_t * 46 | region_list_init(void); 47 | 48 | void 49 | region_list_destroy(region_list_t *list); 50 | 51 | count_t 52 | region_list_get_len(region_list_t *list); 53 | 54 | rm_error_t 55 | region_list_push_back(region_list_t *list, mem_region_t region); 56 | 57 | mem_region_t 58 | region_list_pop_back(region_list_t *list); 59 | 60 | rm_error_t 61 | region_list_finalize(region_list_t *list); 62 | 63 | mem_region_t 64 | region_list_at(region_list_t *list, index_t i); 65 | 66 | mem_region_t * 67 | region_list_at_ptr(region_list_t *list, index_t i); 68 | 69 | #define region_list_loop_range(list, region, i, start_idx, end_idx) \ 70 | for (i = start_idx, region = region_list_at(list, i); i < end_idx; \ 71 | i++, region = region_list_at(list, i)) 72 | 73 | #define region_list_loop(list, region, i) \ 74 | region_list_loop_range(list, region, i, 0U, region_list_get_len(list)) 75 | -------------------------------------------------------------------------------- /include/memextent.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // When creating an extent from a parent, the phys_base should really be the 6 | // offset of the (base address to be used - base address of parent extent). 7 | cap_id_result_t 8 | memextent_create(paddr_t phy_base, size_t size, memextent_type_t type, 9 | pgtable_access_t access, memextent_memtype_t memtype, 10 | cap_id_t parent); 11 | 12 | error_t 13 | memextent_donate_child(cap_id_t parent, cap_id_t child, size_t offset, 14 | size_t size); 15 | 16 | error_t 17 | memextent_donate_parent(cap_id_t parent, cap_id_t child, size_t offset, 18 | size_t size); 19 | 20 | error_t 21 | memextent_donate_sibling(cap_id_t from, cap_id_t to, size_t offset, 22 | size_t size); 23 | 24 | error_t 25 | memextent_map(cap_id_t me_cap, cap_id_t addrspace_cap, vmaddr_t vbase, 26 | pgtable_access_t access, pgtable_vm_memtype_t memtype_map); 27 | 28 | error_t 29 | memextent_map_partial(cap_id_t me_cap, cap_id_t addrspace_cap, vmaddr_t vbase, 30 | size_t offset, size_t size, pgtable_access_t access, 31 | pgtable_vm_memtype_t memtype_map); 32 | 33 | error_t 34 | memextent_unmap(cap_id_t me_cap, cap_id_t addrspace_cap, vmaddr_t vbase); 35 | 36 | error_t 37 | memextent_unmap_partial(cap_id_t me_cap, cap_id_t addrspace_cap, vmaddr_t vbase, 38 | size_t offset, size_t size); 39 | 40 | error_t 41 | memextent_update_access(cap_id_t me_cap, cap_id_t addrspace_cap, vmaddr_t vbase, 42 | pgtable_access_t access); 43 | 44 | error_t 45 | memextent_update_access_partial(cap_id_t me_cap, cap_id_t addrspace_cap, 46 | vmaddr_t vbase, size_t offset, size_t size, 47 | pgtable_access_t access); 48 | 49 | // When creating an extent from a parent, the phys_base should really be the 50 | // offset of the (base address to be used - base address of parent extent). 51 | // This function always creates a basic memextent. 52 | cap_id_result_t 53 | memextent_create_and_map(cap_id_t addrspace_cap, paddr_t phy_base, 54 | vmaddr_t vbase, size_t size, pgtable_access_t access, 55 | memextent_memtype_t memtype, 56 | pgtable_vm_memtype_t memtype_map, cap_id_t parent); 57 | 58 | void 59 | memextent_delete(cap_id_t me); 60 | 61 | error_t 62 | memextent_unmap_all(cap_id_t me); 63 | 64 | error_t 65 | memextent_zero_range(cap_id_t me, size_t offset, size_t size); 66 | 67 | error_t 68 | memextent_cache_clean_range(cap_id_t me, size_t offset, size_t size); 69 | 70 | error_t 71 | memextent_cache_flush_range(cap_id_t me, size_t offset, size_t size); 72 | 73 | // Synchronize all previous extent operations. 74 | // This applies to all extents, regardless of the extent given. 75 | void 76 | memextent_sync_all(cap_id_t me); 77 | -------------------------------------------------------------------------------- /include/memparcel.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define MAX_LIST_ENTRIES 512U 6 | 7 | typedef uint32_t mem_handle_t; 8 | typedef struct vector_s vector_t; 9 | typedef struct region_list_s region_list_t; 10 | 11 | bool 12 | memparcel_msg_handler(vmid_t client_id, uint32_t msg_id, uint16_t seq_num, 13 | void *buf, size_t len); 14 | 15 | uintptr_result_t 16 | memparcel_map_rm(mem_handle_t mp_handle, size_t offset, size_t size); 17 | 18 | error_t 19 | memparcel_unmap_rm(mem_handle_t handle); 20 | 21 | error_t 22 | memparcel_sanitize(mem_handle_t handle, size_t offset, size_t size); 23 | 24 | error_t 25 | memparcel_cache_clean(mem_handle_t handle, size_t offset, size_t size); 26 | 27 | error_t 28 | memparcel_cache_flush(mem_handle_t handle, size_t offset, size_t size); 29 | 30 | RM_PADDED(typedef struct { 31 | void *ptr; 32 | size_t size; 33 | rm_error_t err; 34 | } memparcel_accept_rm_donation_ret_t) 35 | 36 | memparcel_accept_rm_donation_ret_t 37 | memparcel_accept_rm_donation(mem_handle_t handle, uint8_t rights, 38 | uint8_t mem_type); 39 | 40 | typedef struct memparcel memparcel_t; 41 | typedef struct mem_region mem_region_t; 42 | typedef uint32_t label_t; 43 | 44 | mem_handle_t 45 | memparcel_get_handle(const memparcel_t *mp); 46 | 47 | vmid_t 48 | memparcel_get_owner(const memparcel_t *mp); 49 | 50 | label_t 51 | memparcel_get_label(const memparcel_t *mp); 52 | 53 | uint8_t 54 | memparcel_get_mem_type(const memparcel_t *mp); 55 | 56 | uint8_t 57 | memparcel_get_trans_type(const memparcel_t *mp); 58 | 59 | count_t 60 | memparcel_get_num_regions(const memparcel_t *mp); 61 | 62 | count_result_t 63 | memparcel_get_num_mappings(const memparcel_t *mp, vmid_t vmid); 64 | 65 | paddr_result_t 66 | memparcel_get_phys(const memparcel_t *mp, index_t region_idx); 67 | 68 | vmaddr_result_t 69 | memparcel_get_mapped_ipa(const memparcel_t *mp, vmid_t vmid, 70 | index_t mapping_idx); 71 | 72 | bool 73 | memparcel_is_shared(const memparcel_t *mp, vmid_t vmid); 74 | 75 | bool 76 | memparcel_is_exclusive(const memparcel_t *mp, vmid_t vmid); 77 | 78 | bool 79 | memparcel_is_private(const memparcel_t *mp, vmid_t vmid); 80 | 81 | error_t 82 | memparcel_get_shared_vmids(const memparcel_t *mp, vector_t *vmids); 83 | 84 | size_t 85 | memparcel_get_size(const memparcel_t *mp); 86 | 87 | size_result_t 88 | memparcel_get_region_size(const memparcel_t *mp, index_t region_idx); 89 | 90 | region_list_t * 91 | memparcel_get_regions_list(const memparcel_t *mp); 92 | 93 | size_result_t 94 | memparcel_get_mapped_size(const memparcel_t *mp, vmid_t vmid, 95 | index_t mapping_idx); 96 | 97 | memparcel_t * 98 | memparcel_iter_by_target_vmid(memparcel_t *after, vmid_t vmid); 99 | 100 | error_t 101 | memparcel_get_shared_vmids(const memparcel_t *mp, vector_t *vmids); 102 | 103 | void 104 | memparcel_set_phandle(memparcel_t *mp, vmid_t vmid, uint32_t phandle, 105 | bool is_external); 106 | 107 | uint8_result_t 108 | memparcel_get_vm_rights(const memparcel_t *mp, vmid_t vmid); 109 | 110 | uint16_result_t 111 | memparcel_get_vm_attrs(memparcel_t *mp, vmid_t vmid); 112 | 113 | uint32_t 114 | memparcel_get_phandle(memparcel_t *mp, vmid_t vmid, bool *is_external); 115 | 116 | cap_id_result_t 117 | memparcel_get_me_cap(const memparcel_t *mp); 118 | 119 | void 120 | memparcel_set_mem_info_tag(memparcel_t *mp, label_t tag); 121 | 122 | bool 123 | vm_reset_handle_release_memparcels(vmid_t vmid); 124 | 125 | #define foreach_memparcel_by_target_vmid(mp, vmid) \ 126 | for ((mp) = memparcel_iter_by_target_vmid(NULL, (vmid)); (mp) != NULL; \ 127 | (mp) = memparcel_iter_by_target_vmid((mp), (vmid))) 128 | 129 | static inline memparcel_t * 130 | memparcel_lookup_by_target_vmid(vmid_t vmid, mem_handle_t handle) 131 | { 132 | memparcel_t *mp; 133 | 134 | foreach_memparcel_by_target_vmid (mp, vmid) { 135 | if (memparcel_get_handle(mp) == handle) { 136 | break; 137 | } 138 | } 139 | 140 | return mp; 141 | } 142 | 143 | rm_error_t 144 | platform_memparcel_accept(memparcel_t *mp, vm_t *vm); 145 | 146 | rm_error_t 147 | platform_memparcel_release(memparcel_t *mp, vm_t *vm); 148 | 149 | bool 150 | memparcel_get_sanitize_reclaim(const memparcel_t *mp); 151 | 152 | void 153 | memparcel_set_lock(memparcel_t *mp, bool lock); 154 | 155 | bool 156 | memparcel_is_locked(const memparcel_t *mp); 157 | 158 | uint32_t 159 | memparcel_get_mpd_sanitise_refcount(const memparcel_t *mp, index_t region_idx); 160 | 161 | void 162 | memparcel_increment_mpd_sanitise_refcount(const memparcel_t *mp, 163 | index_t region_idx); 164 | 165 | void 166 | memparcel_decrement_mpd_sanitise_refcount(const memparcel_t *mp, 167 | index_t region_idx); 168 | -------------------------------------------------------------------------------- /include/panic.h: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | noreturn void 6 | panic(const char *msg); 7 | -------------------------------------------------------------------------------- /include/platform.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | struct dtb_parser_data_s; 6 | typedef struct dtb_parser_data_s vm_config_parser_data_t; 7 | 8 | error_t 9 | platform_env_init(platform_env_data_t **platform_env); 10 | 11 | error_t 12 | platform_hlos_create(vm_t *vm, const rm_env_data_t *env_data); 13 | 14 | bool 15 | platform_msg_callback(vmid_t vm_id, uint32_t msg_id, uint16_t seq_num, 16 | void *buf, size_t len); 17 | 18 | bool 19 | platform_notif_callback(vmid_t vm_id, uint32_t notification_id, void *buf, 20 | size_t len); 21 | 22 | __attribute__((weak)) error_t 23 | platform_hyp_rpc_send_packet(cap_id_t tx_cap, void *buf, size_t len); 24 | 25 | __attribute__((weak)) error_t 26 | platform_hyp_rpc_recv_packet(cap_id_t rx_cap, void *buf, size_t buf_len, 27 | size_t *recv_size); 28 | 29 | error_t 30 | platform_config_update_parsed(vm_config_t *vmcfg, 31 | vm_config_parser_data_t *data); 32 | 33 | // return true if running on a security enabled device 34 | bool 35 | platform_get_security_state(void); 36 | 37 | bool 38 | platform_expose_log_to_hlos(void); 39 | 40 | const char * 41 | platform_get_sign_authority_string(uint32_t signer_info); 42 | 43 | error_t 44 | platform_init(rm_env_data_t *env_data, vmaddr_t log_buf, size_t log_buf_size); 45 | 46 | error_t 47 | platform_init_complete(void); 48 | 49 | error_t 50 | platform_vm_create(const vm_t *vm, bool hlos); 51 | 52 | error_t 53 | platform_vm_dt_create_hlos(vm_t *vm); 54 | 55 | typedef struct vm_auth_param vm_auth_param_t; 56 | 57 | rm_error_t 58 | platform_vm_auth(vm_t *vm, count_t num_auth_params, 59 | vm_auth_param_t *auth_params); 60 | 61 | rm_error_t 62 | platform_vm_init(vm_t *vm); 63 | 64 | error_t 65 | platform_vm_takedown(vm_t *vm); 66 | 67 | error_t 68 | platform_vm_exit(const vm_t *vm); 69 | 70 | error_t 71 | platform_vm_destroy(vm_t *vm, bool hlos); 72 | 73 | error_t 74 | platform_handle_destroy_vdevices(const vm_t *vm); 75 | 76 | void 77 | platform_exit_handler(int exit_code); 78 | 79 | // TODO: Cleanly define a platform API that allows a platform to mark a range 80 | // of VMIDs as platform reserved, and remove secondary and peripheral VMIDs 81 | // here. 82 | 83 | // Bitmap of platform VMIDs which are managed by RM. 84 | uint64_t 85 | platform_get_secondary_vmids(void); 86 | 87 | // Bitmap of platform peripheral VMIDs which are not managed by RM. 88 | uint64_t 89 | platform_get_peripheral_vmids(void); 90 | 91 | error_t 92 | platform_primary_vm_init(rm_env_data_t *env_data, uintptr_t log_buf, 93 | size_t log_buf_size); 94 | 95 | uint64_t 96 | platform_get_os_boot_arg(vm_t *vm); 97 | 98 | error_t 99 | platform_rtc_set_time_base(cap_id_t rtc_cap, uint64_t time_base, 100 | uint64_t sys_timer_ref); 101 | 102 | error_t 103 | platform_vrtc_attach_addrspace(cap_id_t rtc_cap, cap_id_t addrspace_cap); 104 | 105 | bool 106 | platform_has_vrtc_support(void); 107 | 108 | bool 109 | platform_has_vsmmu_v2_support(void); 110 | 111 | cap_id_result_t 112 | platform_vrtc_create_and_configure(cap_id_t p_cap, cap_id_t cs_cap, 113 | vmaddr_t ipa); 114 | 115 | error_t 116 | platform_pre_hlos_vm_init(const rm_env_data_t *env_data); 117 | -------------------------------------------------------------------------------- /include/preempt.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | void 6 | preempt_disable(void); 7 | 8 | void 9 | preempt_enable(void); 10 | 11 | void 12 | assert_preempt_disabled(void); 13 | 14 | void 15 | assert_preempt_enabled(void); 16 | -------------------------------------------------------------------------------- /include/random.h: -------------------------------------------------------------------------------- 1 | // © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | uint64_result_t 6 | random_get_entropy64(void); 7 | -------------------------------------------------------------------------------- /include/resource-manager.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | typedef struct gunyah_hyp_hypervisor_identify_result 6 | gunyah_hyp_hypervisor_identify_result_t; 7 | 8 | extern gunyah_hyp_hypervisor_identify_result_t hyp_id; 9 | 10 | paddr_t 11 | rm_ipa_to_pa(uintptr_t ipa); 12 | 13 | cap_id_t 14 | rm_get_rm_addrspace(void); 15 | 16 | cap_id_t 17 | rm_get_rm_cspace(void); 18 | 19 | cap_id_t 20 | rm_get_rm_partition(void); 21 | 22 | cap_id_t 23 | rm_get_rm_vic(void); 24 | 25 | cap_id_t 26 | rm_get_device_me_cap(void); 27 | 28 | paddr_t 29 | rm_get_device_me_base(void); 30 | 31 | size_t 32 | rm_get_device_me_size(void); 33 | 34 | cap_id_t 35 | rm_get_me(void); 36 | 37 | vmaddr_t 38 | rm_get_hlos_entry(void); 39 | 40 | bool 41 | rm_get_watchdog_supported(void); 42 | 43 | paddr_t 44 | rm_get_watchdog_address(void); 45 | 46 | cap_id_t 47 | rm_get_restricted_hwirq(virq_t irq, vmid_t vmid); 48 | 49 | count_t 50 | rm_get_platform_max_cores(void); 51 | 52 | index_t 53 | rm_get_platform_root_vcpu_index(void); 54 | 55 | bool 56 | rm_is_core_usable(cpu_index_t i); 57 | 58 | vmaddr_t 59 | rm_get_me_ipa_base(void); 60 | 61 | vmaddr_t 62 | rm_get_hlos_dt_base(void); 63 | 64 | cap_id_t 65 | rm_get_uart_me(void); 66 | 67 | platform_env_data_t * 68 | rm_get_platform_env_data(void); 69 | 70 | const vm_device_assignments_t * 71 | rm_get_vm_device_assignments(void); 72 | -------------------------------------------------------------------------------- /include/rm-rpc-fifo.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | rm_error_t 6 | rm_rpc_fifo_init(void); 7 | 8 | rm_error_t 9 | rm_rpc_fifo_create(vmid_t peer); 10 | 11 | rm_error_t 12 | rm_rpc_fifo_destroy(vmid_t peer); 13 | 14 | rm_error_t 15 | rm_rpc_fifo_reply(vmid_t vm_id, uint32_t msg_id, uint16_t seq_num, void *buf, 16 | size_t len); 17 | 18 | rm_error_t 19 | rm_rpc_fifo_send_notification(vmid_t vm_id, uint32_t notif_id, void *buf, 20 | size_t len, bool allow_pending); 21 | 22 | void 23 | rm_rpc_fifo_tx_callback(vmid_t vm_id); 24 | 25 | void 26 | rm_rpc_fifo_deinit(void); 27 | 28 | typedef struct { 29 | rm_error_t err; 30 | } rm_standard_rep_t; 31 | 32 | // Helper function to perform a reply with a specified error and data 33 | // using rm_rpc_fifo_reply(). 34 | // 35 | // data input is copied to a new buffer, and may be safely reused when this 36 | // call returns, pointers to stack data are thus also permitted. 37 | void 38 | rm_reply_error(vmid_t client_id, uint32_t msg_id, uint16_t seq_num, 39 | rm_error_t err, void *data, size_t len); 40 | 41 | // Helper function to perform a reply with error RM_OK and data using 42 | // rm_rpc_fifo_reply(). 43 | // 44 | // data input is copied to a new buffer, and may be safely reused when this 45 | // call returns, pointers to stack data are thus also permitted. 46 | static inline void 47 | rm_reply(vmid_t client_id, uint32_t msg_id, uint16_t seq_num, void *data, 48 | size_t len) 49 | { 50 | rm_reply_error(client_id, msg_id, seq_num, RM_OK, data, len); 51 | } 52 | 53 | // Helper function to perform a standard reply (i.e. send 54 | // an error code) using rm_rpc_fifo_reply(). 55 | static inline void 56 | rm_standard_reply(vmid_t client_id, uint32_t msg_id, uint16_t seq_num, 57 | rm_error_t err) 58 | { 59 | rm_reply_error(client_id, msg_id, seq_num, err, NULL, 0U); 60 | } 61 | 62 | // Helper function that takes a copy of data. 63 | void 64 | rm_notify(vmid_t client_id, uint32_t notif_id, void *data, size_t len); 65 | 66 | // Helper function to check if a client can receive RM RPC. 67 | bool 68 | rm_can_rpc(vmid_t client_id); 69 | -------------------------------------------------------------------------------- /include/rm-rpc.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define RM_RPC_MESSAGE_SIZE 240U 6 | 7 | #define RM_RPC_API_VERSION 1U 8 | #define RM_RPC_HEADER_SIZE 8U 9 | #define RM_RPC_HEADER_WORDS (RM_RPC_HEADER_SIZE / 4U) 10 | #define RM_RPC_MAX_CONTENT (RM_RPC_MESSAGE_SIZE - RM_RPC_HEADER_SIZE) 11 | #define RM_RPC_MAX_FRAGMENTS 62U 12 | #define RM_RPC_MAX_MSG_SIZE (RM_RPC_MAX_CONTENT * (RM_RPC_MAX_FRAGMENTS + 1U)) 13 | 14 | #define RM_RPC_MSG_TYPE_CONTINUED 0U 15 | #define RM_RPC_MSG_TYPE_REQUEST 1U 16 | #define RM_RPC_MSG_TYPE_REPLY 2U 17 | #define RM_RPC_MSG_TYPE_NOTIFICATION 3U 18 | 19 | rm_error_t 20 | rm_error_from_hyp(error_t err); 21 | 22 | rm_error_t 23 | rm_rpc_init_server(vmid_t my_id); 24 | 25 | rm_error_t 26 | rm_rpc_server_add_link(vmid_t client_id); 27 | 28 | rm_error_t 29 | rm_rpc_server_remove_link(vmid_t client_id); 30 | 31 | // Note: this is an unpacked version of the RPC header, and is not to be 32 | // directly copied to message buffers without marshalling. 33 | RM_PADDED(typedef struct { 34 | uint8_t api_version; 35 | uint8_t header_words; 36 | uint8_t msg_type; 37 | uint8_t num_fragments; 38 | uint16_t seq_num; 39 | uint32_t msg_id; 40 | } rm_rpc_header_t) 41 | 42 | rm_error_t 43 | rm_rpc_send_notification(vmid_t vm_id, uint32_t notification_id, void *buf, 44 | size_t len); 45 | 46 | rm_error_t 47 | rm_rpc_reply(vmid_t vm_id, uint32_t msg_id, uint16_t seq_num, void *buf, 48 | size_t len); 49 | 50 | // Free a message buffer allocated by rm-rpc. 51 | void 52 | rm_rpc_free(void *buf); 53 | 54 | typedef void (*rm_rpc_msg_callback_t)(vmid_t vm_id, uint32_t msg_id, 55 | uint16_t seq_num, uint8_t msg_type, 56 | void *buf, size_t len); 57 | 58 | rm_error_t 59 | rm_rpc_register_msg_handler(rm_rpc_msg_callback_t callback); 60 | 61 | typedef void (*rm_rpc_notif_callback_t)(vmid_t vm_id, uint32_t notification_id, 62 | void *buf, size_t len); 63 | 64 | rm_error_t 65 | rm_rpc_register_notif_handler(rm_rpc_notif_callback_t callback); 66 | 67 | typedef void (*rm_rpc_tx_callback_t)(rm_error_t tx_err, vmid_t vm_id, void *buf, 68 | size_t len); 69 | 70 | // Register a handler which is called when a TX has finished. 71 | // If additional TX needs to be performed, an event must be triggered; the 72 | // rm-rpc library will reject any attempts to TX in the callback. 73 | rm_error_t 74 | rm_rpc_register_tx_complete_handler(rm_rpc_tx_callback_t callback); 75 | 76 | void 77 | rm_rpc_wait(int suspend_timeout); 78 | 79 | // Utility function to get an RM RPC list (array)'s data start address and 80 | // length. 81 | // 82 | // An RM RPC list has a 16-bit length value, followed by a data array starting 83 | // at the next 32-bit aligned boundary. This helper function gets list length 84 | // and data from the input [buf, buf + len) memory region. 85 | // 86 | // The list's data array start address is returned in `*list`, and length is 87 | // returned in `*entries`. The element size of this list is `entry_size`. The 88 | // list should only contain no more than `max_entries` elements. 89 | // 90 | // A pointer to the address of the next buffer after the list is returned in 91 | // `next_buf`. 92 | // 93 | // Returns `error != RM_OK` on error. 94 | rm_error_t 95 | rm_rpc_read_list(uint8_t *buf, size_t len, uint16_t *entries, 96 | uint32_t max_entries, uintptr_t *list, size_t entry_size, 97 | uint8_t **next_buf); 98 | -------------------------------------------------------------------------------- /include/rm_env_data.h: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | typedef struct rm_irq_env_data_s { 6 | cap_id_t vic_hwirq[1020]; 7 | cap_id_t vic_msi_source[16]; 8 | } rm_irq_env_data_t; 9 | 10 | // This structure is used only locally in RM as shared temporary data 11 | RM_PADDED(struct rm_env_data_s { 12 | platform_env_data_t *platform_env; 13 | 14 | cap_id_t addrspace_capid; 15 | paddr_t uart_address; 16 | count_t num_reserved_dev_irqs; 17 | virq_t reserved_dev_irq[8]; 18 | count_t free_ranges_count; 19 | boot_env_phys_range_t free_ranges[32]; 20 | cap_id_t vcpu_capid; 21 | vmaddr_t entry_hlos; 22 | cap_id_t device_me_capid; 23 | paddr_t device_me_base; 24 | size_t device_me_size; 25 | vmaddr_t mpd_region_addr; 26 | size_t mpd_region_size; 27 | paddr_t wdt_address; 28 | cap_id_t partition_capid; 29 | cap_id_t cspace_capid; 30 | cap_id_t me_capid; 31 | vmaddr_t me_ipa_base; 32 | size_t me_size; 33 | uintptr_t ipa_offset; 34 | uint64_t usable_cores; 35 | paddr_t hlos_dt_base; 36 | paddr_t hlos_vm_base; 37 | size_t hlos_vm_size; 38 | paddr_t hlos_ramfs_base; 39 | cap_id_t smc_wqs[2]; 40 | cap_id_t vic; 41 | 42 | rm_irq_env_data_t *irq_env; 43 | 44 | cap_id_t uart_me_capid; 45 | cpu_index_t boot_core; 46 | bool sve_supported; 47 | bool watchdog_supported; 48 | bool hlos_handles_ras; 49 | vm_device_assignments_t *device_assignments; 50 | }) 51 | 52 | typedef struct rm_env_data_s rm_env_data_t; 53 | -------------------------------------------------------------------------------- /include/rm_types.h: -------------------------------------------------------------------------------- 1 | // © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define VMID_HYP 0x0U 6 | #define VMID_HLOS 0x3U 7 | #define VMID_DYNAMIC_BASE 0x80U 8 | #define VMID_DYNAMIC_END 0xBFU 9 | #define VMID_RM 0xFFU 10 | 11 | // Special VMIDs 12 | #define VMID_LAST 0xFFU // Last usable VMID 13 | #define VMID_ANY 0xFFFEU // For resources without specific owner 14 | #define VMID_PEER_DEFAULT 0xFFFFU 15 | 16 | #define INVALID_ADDRESS (~0UL) 17 | 18 | #define VM_MAX_NAME_LEN 80 19 | #define VM_GUID_LEN 16 20 | #define VM_MAX_URI_LEN 80 21 | 22 | // Macros to instruct the compiler not to warn about padding. These should only 23 | // be used on structures that are either internal to the RM or else have been 24 | // unmarshalled from a packed on-the-wire representation. 25 | #define RM_PADDED_BEGIN \ 26 | _Pragma("clang diagnostic push") \ 27 | _Pragma("clang diagnostic ignored \"-Wpadded\"") 28 | #define RM_PADDED_END _Pragma("clang diagnostic pop") 29 | 30 | #define RM_PADDED(struct_body) \ 31 | RM_PADDED_BEGIN \ 32 | struct_body; \ 33 | RM_PADDED_END 34 | 35 | struct rm_env_data_s; 36 | typedef struct rm_env_data_s rm_env_data_t; 37 | 38 | struct platform_env_data_s; 39 | typedef struct platform_env_data_s platform_env_data_t; 40 | 41 | struct vm_s; 42 | typedef struct vm_s vm_t; 43 | 44 | struct vm_config; 45 | typedef struct vm_config vm_config_t; 46 | 47 | struct vm_device_descriptor_s; 48 | typedef struct vm_device_descriptor_s vm_device_descriptor_t; 49 | 50 | struct vm_device_assignments_s; 51 | typedef struct vm_device_assignments_s vm_device_assignments_t; 52 | 53 | struct vdevice_node; 54 | 55 | typedef enum { 56 | VM_ID_TYPE_GUID = 0, 57 | VM_ID_TYPE_URI = 1, 58 | VM_ID_TYPE_NAME = 2, 59 | VM_ID_TYPE_SIGN_AUTH = 3, 60 | } vm_id_type_t; 61 | 62 | typedef enum { 63 | VM_AUTH_TYPE_NONE = 0, 64 | VM_AUTH_TYPE_PLATFORM = 1, 65 | VM_AUTH_TYPE_ANDROID = 2, 66 | } vm_auth_type_t; 67 | 68 | RM_PADDED(typedef struct interrupt_data { 69 | virq_t irq; 70 | bool is_cpu_local; 71 | bool is_edge_triggering; 72 | } interrupt_data_t) 73 | 74 | typedef uint32_t rm_error_t; 75 | 76 | #define RM_OK ((rm_error_t)0x0U) 77 | #define RM_ERROR_UNIMPLEMENTED ((rm_error_t)0xffffffffU) 78 | #define RM_ERROR_NOMEM ((rm_error_t)0x1U) 79 | #define RM_ERROR_NORESOURCE ((rm_error_t)0x2U) 80 | #define RM_ERROR_DENIED ((rm_error_t)0x3U) 81 | #define RM_ERROR_MSG_INVALID ((rm_error_t)0x4U) 82 | #define RM_ERROR_BUSY ((rm_error_t)0x5U) 83 | #define RM_ERROR_ARGUMENT_INVALID ((rm_error_t)0x6U) 84 | #define RM_ERROR_HANDLE_INVALID ((rm_error_t)0x7U) 85 | #define RM_ERROR_VALIDATE_FAILED ((rm_error_t)0x8U) 86 | #define RM_ERROR_MAP_FAILED ((rm_error_t)0x9U) 87 | #define RM_ERROR_MEM_INVALID ((rm_error_t)0xaU) 88 | #define RM_ERROR_MEM_INUSE ((rm_error_t)0xbU) 89 | #define RM_ERROR_MEM_RELEASED ((rm_error_t)0xcU) 90 | #define RM_ERROR_VMID_INVALID ((rm_error_t)0xdU) 91 | #define RM_ERROR_LOOKUP_FAILED ((rm_error_t)0xeU) 92 | #define RM_ERROR_IRQ_INVALID ((rm_error_t)0xfU) 93 | #define RM_ERROR_IRQ_INUSE ((rm_error_t)0x10U) 94 | #define RM_ERROR_IRQ_RELEASED ((rm_error_t)0x11U) 95 | #define RM_ERROR_IN_USE ((rm_error_t)0x12U) 96 | #define RM_ERROR_IRQ_NOT_MAPPED ((rm_error_t)0x13U) 97 | #define RM_ERROR_VM_STATE ((rm_error_t)0x14U) 98 | -------------------------------------------------------------------------------- /include/uapi/console.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define CONSOLE_MAGIC 0x43U 6 | 7 | #define IOCTL_REGISTER_CONSOLE \ 8 | _IOW(CONSOLE_MAGIC, 0U, struct register_console_req) 9 | #define IOCTL_DEREGISTER_CONSOLE _IOW(CONSOLE_MAGIC, 1U, int) 10 | #define IOCTL_SET_PREFIX_CONSOLE _IOW(CONSOLE_MAGIC, 2U, const char *) 11 | 12 | typedef void (*console_t)(const char *out, size_t size); 13 | 14 | struct register_console_req { 15 | console_t console; 16 | }; 17 | -------------------------------------------------------------------------------- /include/uapi/exit_dev.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define EXIT_MAGIC 0x44U 6 | 7 | #define IOCTL_REGISTER_EXIT _IOW(EXIT_MAGIC, 0U, struct register_exit_req) 8 | #define IOCTL_DEREGISTER_EXIT _IOW(EXIT_MAGIC, 1U, int) 9 | 10 | typedef void (*exit_t)(int exit_code); 11 | 12 | struct register_exit_req { 13 | exit_t exit_func; 14 | }; 15 | -------------------------------------------------------------------------------- /include/uapi/interrupt.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define IRQ_MAGIC 0x49U 6 | 7 | #define IOCTL_ENABLE_IRQ _IOW(IRQ_MAGIC, 0U, int) 8 | #define IOCTL_DISABLE_IRQ _IOW(IRQ_MAGIC, 1U, int) 9 | #define IOCTL_REGISTER_ISR _IOW(IRQ_MAGIC, 2U, struct register_isr_req) 10 | #define IOCTL_SET_IRQ_TRIGGER _IOW(IRQ_MAGIC, 3U, struct irq_set_trigger_req) 11 | #define IOCTL_DEREGISTER_ISR _IOW(IRQ_MAGIC, 4U, int) 12 | 13 | typedef bool (*isr_t)(int, void *); 14 | 15 | struct register_isr_req { 16 | isr_t isr; 17 | int irq; 18 | int res0; 19 | void *data; 20 | }; 21 | 22 | #define IRQ_TRIGGER_LEVEL_HIGH 0 23 | #define IRQ_TRIGGER_LEVEL_LOW 1 24 | #define IRQ_TRIGGER_EDGE_RISING 2 25 | #define IRQ_TRIGGER_EDGE_FALLING 3 26 | #define IRQ_TRIGGER_EDGE_BOTH 4 27 | #define IRQ_TRIGGER_MESSAGE 5 28 | 29 | struct irq_set_trigger_req { 30 | int irq; 31 | int trigger; 32 | }; 33 | 34 | rm_error_t 35 | register_isr(virq_t virq, int trigger, isr_t isr, void *data); 36 | 37 | rm_error_t 38 | register_event_isr(virq_t virq, event_t *event); 39 | 40 | rm_error_t 41 | deregister_isr(virq_t virq); 42 | -------------------------------------------------------------------------------- /include/uart.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | void 6 | platform_uart_map(rm_env_data_t *env_data); 7 | 8 | rm_error_t 9 | register_uart(void); 10 | 11 | rm_error_t 12 | deregister_uart(void); 13 | 14 | void 15 | uart_putc(const char c); 16 | 17 | void 18 | uart_write(const char *out, size_t size); 19 | -------------------------------------------------------------------------------- /include/util.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Miscellaneous utility macros. 6 | // 7 | // These all have simple definitions - no compiler builtins or other language 8 | // extensions. Look in compiler.h for those. 9 | 10 | #define util_bit(b) ((uintmax_t)1U << (b)) 11 | #define util_sbit(b) ((intmax_t)1 << (b)) 12 | #define util_mask(n) (util_bit(n) - 1) 13 | 14 | #define util_max(x, y) (((x) > (y)) ? (x) : (y)) 15 | #define util_min(x, y) (((x) < (y)) ? (x) : (y)) 16 | 17 | // Arithmetic predicates with intent that is not obvious when open-coded 18 | #define util_is_p2_or_zero(x) (((x) & ((x)-1U)) == 0U) 19 | #define util_is_p2(x) (((x) != 0U) && util_is_p2_or_zero(x)) 20 | #define util_is_baligned(x, a) (assert(util_is_p2(a)), (((x) & ((a)-1U)) == 0U)) 21 | #define util_is_p2aligned(x, b) (((x) & (util_bit(b) - 1U)) == 0U) 22 | #define util_add_overflows(a, b) ((a) > ~(__typeof__((a) + (b)))(b)) 23 | 24 | #define util_mult_integer_overflows(a, b) \ 25 | (bool)_Generic((a) * (b), uint32_t \ 26 | : (((uint64_t)(a) * (b)) > UINT32_MAX), uint64_t \ 27 | : (((__uint128_t)(a) * (b)) > UINT64_MAX)) 28 | 29 | // Align up or down to bytes (which must be a power of two) 30 | #define util_balign_down(x, a) \ 31 | (assert(util_is_p2(a)), (x) & ~((__typeof__(x))(a)-1U)) 32 | #define util_balign_up(x, a) util_balign_down((x) + ((a)-1U), a) 33 | 34 | // Align up or down to a power-of-two size (in bits) 35 | #define util_p2align_down(x, b) \ 36 | (assert((sizeof(x) * 8) > (b)), (((x) >> (b)) << (b))) 37 | #define util_p2align_up(x, b) util_p2align_down((x) + util_bit(b) - 1U, b) 38 | 39 | // Return the number of elements in an array. 40 | #define util_array_size(a) (sizeof(a) / sizeof((a)[0])) 41 | -------------------------------------------------------------------------------- /include/utils/address_range_allocator.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // A generic address range allocator that supports free range allocation and 6 | // explicit tagged range allocations. 7 | // 8 | // Tagged regions must be allocated from explicitly, and will not be allocated 9 | // from when requesting any free range. 10 | 11 | #define ADDRESS_RANGE_LIMIT (1UL << 52) 12 | #define ADDRESS_RANGE_NO_ALIGNMENT 0UL 13 | 14 | struct address_range_allocator; 15 | typedef struct address_range_allocator address_range_allocator_t; 16 | 17 | typedef uint32_t address_range_tag_t; 18 | #define ADDRESS_RANGE_NO_TAG (address_range_tag_t)0UL 19 | 20 | typedef struct { 21 | uint64_t base_address; 22 | size_t size; 23 | // Tagged range tag information (for allocation within a tagged range) 24 | address_range_tag_t tag; 25 | 26 | error_t err; 27 | } address_range_allocator_ret_t; 28 | 29 | // Initialize an Address Range Allocator 30 | // 31 | // base_address and size must be PAGE_SIZE aligned. 32 | // base_address + size may not exceed ADDRESS_RANGE_LIMIT. 33 | address_range_allocator_t * 34 | address_range_allocator_init(uint64_t base_address, size_t size); 35 | 36 | // Allocate a range from the Address Range Allocator 37 | // 38 | // Either an explicit range or any free range may be requested. 39 | // If base_address is INVALID_ADDRESS then any free range with sufficient size 40 | // will be allocated, but NOT within a tagged range. Otherwise we allocate the 41 | // specified range (base_address++size) if it's possible. 42 | // 43 | // When base_address is INVALID_ADDRESS, the alignment parameter requests an 44 | // aligned base to be allocated, and alignment must be a power of two. 45 | // 46 | // A requested range may not partially overlap a tagged allocator range. 47 | address_range_allocator_ret_t 48 | address_range_allocator_alloc(address_range_allocator_t *allocator, 49 | uint64_t base_address, size_t size, 50 | size_t alignment); 51 | 52 | // Tag a region of the Address Range Allocator 53 | // 54 | // base_address, size must specify an unallocated tagged range in the 55 | // allocator. 56 | // 57 | // Once the region is tagged, it can only be allocated explicitly by requesting 58 | // a range within it. 59 | error_t 60 | address_range_allocator_tag(address_range_allocator_t *allocator, 61 | uint64_t base_address, size_t size, 62 | address_range_tag_t tag); 63 | 64 | // Tag a region of the Address Range Allocator 65 | // 66 | // Once the region is tagged, it can only be allocated explicitly by requesting 67 | // a range within it. 68 | // 69 | // constrain_base, constrain_size: specify an optional constraint on the address 70 | // range of the allocator to search for a free range. If constrain_base is set 71 | // to INVALID_ADDRESS, the constrain_size is ignored, the full free range of the 72 | // allocator may be used. 73 | address_range_allocator_ret_t 74 | address_range_allocator_tag_region(address_range_allocator_t *allocator, 75 | uint64_t constrain_base, 76 | size_t constrain_size, size_t size, 77 | size_t alignment, address_range_tag_t tag); 78 | 79 | // Return a range to the allocator. 80 | error_t 81 | address_range_allocator_free(address_range_allocator_t *allocator, 82 | uint64_t base_address, size_t size); 83 | 84 | // Return a tagged range to the allocator. 85 | // 86 | // The tagged range must be unallocated. 87 | error_t 88 | address_range_allocator_untag(address_range_allocator_t *allocator, 89 | uint64_t base_address, size_t size, 90 | address_range_tag_t tag); 91 | 92 | // Destroy a range allocator. 93 | void 94 | address_range_allocator_deinit(address_range_allocator_t *allocator); 95 | 96 | #ifndef NDEBUG 97 | void 98 | address_range_allocator_dump(address_range_allocator_t *allocator); 99 | #endif 100 | -------------------------------------------------------------------------------- /include/utils/circular_buf.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | struct cbuf; 6 | typedef struct cbuf cbuf_t; 7 | 8 | cbuf_t * 9 | cbuf_init(size_t capacity); 10 | 11 | // Write write_len bytes from data into the circular buffer. If the write_len 12 | // is larger than the buffer, then the write head will overwrite the tail and 13 | // only the last will remain. 14 | size_t 15 | cbuf_write(cbuf_t *cbuf, const void *data, size_t write_len); 16 | 17 | // Read up to read_len bytes from data into the output buffer. Returns the 18 | // number of bytes read. 19 | size_t 20 | cbuf_read(cbuf_t *cbuf, void *output, size_t read_len); 21 | 22 | // Returns the amount of data currently in the circular buffer. 23 | size_t 24 | cbuf_used(cbuf_t *cbuf); 25 | 26 | // Returns the amount of space available in the circular buffer before 27 | // overwrites will occur. 28 | size_t 29 | cbuf_available(cbuf_t *cbuf); 30 | 31 | void 32 | cbuf_deinit(cbuf_t *cbuf); 33 | -------------------------------------------------------------------------------- /include/utils/dict.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | typedef uint32_t dict_key_t; 6 | typedef struct dict_s dict_t; 7 | 8 | typedef struct { 9 | error_t err; 10 | dict_key_t key; 11 | } dict_key_ret_t; 12 | 13 | // Dictionary iterator callback 14 | // key - the current key 15 | // data - the current data 16 | // arg - user provided argument passed from dict_iterate 17 | // return true to stop iteration 18 | typedef bool (*dict_iter_callback_t)(dict_key_t key, void *data, void *arg); 19 | 20 | // Initialize a new dictionary 21 | dict_t * 22 | dict_init(dict_key_t key_min, dict_key_t key_max); 23 | 24 | // Does the key exist in the dictionary 25 | bool 26 | dict_contains(dict_t *dict, dict_key_t key); 27 | 28 | // Get the data for a specified key, or NULL 29 | void * 30 | dict_get(dict_t *dict, dict_key_t key); 31 | 32 | // Find the first unused key in the dictionary 33 | dict_key_ret_t 34 | dict_get_first_free_key(dict_t *dict); 35 | 36 | // Find the first unused key in the dictionary, starting from 37 | dict_key_ret_t 38 | dict_get_first_free_key_from(dict_t *dict, dict_key_t from); 39 | 40 | // Add an entry to the dictionary, data may not be NULL 41 | error_t 42 | dict_add(dict_t *dict, dict_key_t key, void *data); 43 | 44 | // Remove key from dict. Returns the stored value in *data if data is not NULL 45 | // The caller is responsible to free the returned data. 46 | error_t 47 | dict_remove(dict_t *dict, dict_key_t key, void **data); 48 | 49 | // Iterate all keys in the dictionary, calling the provided function for each. 50 | // Returns ERROR_NORESOURCES if the dict is empty. 51 | error_t 52 | dict_iterate(dict_t *dict, dict_iter_callback_t fn, void *arg); 53 | 54 | void 55 | dict_deinit(dict_t **dict_p); 56 | 57 | dict_key_t 58 | dict_get_min_key(dict_t *dict); 59 | 60 | dict_key_t 61 | dict_get_max_key(dict_t *dict); 62 | 63 | // A simple iterator that performs a lookup for each possible key in the dict's 64 | // range. It is less efficient that dict_iterate() however can be used inline 65 | // without requiring a callback function pointer. 66 | #define dict_foreach(info, key, dict) \ 67 | for (key = dict_get_min_key(dict), info = dict_get(dict, key); \ 68 | key <= dict_get_max_key(dict); key++, info = dict_get(dict, key)) 69 | -------------------------------------------------------------------------------- /include/utils/range_list.h: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define INVALID_DATA (0UL) 6 | 7 | struct range_s; 8 | typedef struct range_s range_t; 9 | 10 | struct range_list_s; 11 | typedef struct range_list_s range_list_t; 12 | 13 | typedef struct { 14 | uint64_t base_address; 15 | size_t size; 16 | 17 | error_t err; 18 | uint8_t err_padding[4]; 19 | } range_list_remove_ret_t; 20 | 21 | uint64_t 22 | range_list_get_base_address(range_list_t *list); 23 | 24 | size_t 25 | range_list_get_size(range_list_t *list); 26 | 27 | uintptr_t 28 | range_list_get_range_data(range_t *range); 29 | 30 | bool 31 | range_list_is_empty(range_list_t *list); 32 | 33 | // Init range list 34 | // 35 | // Specify [base_address, base_address + size) range to manage. as_empty 36 | // indicates that the list is initialized as empty, no range can be removed 37 | // from this list initially. 38 | // 39 | // Returns a list or NULL if failed. 40 | range_list_t * 41 | range_list_init(uint64_t base_address, size_t size, bool as_empty); 42 | 43 | // Remove a range from range list 44 | // 45 | // Remove [base_address, base_address + size) from the list. 46 | // base_address can be as INVALID_ADDRESS, range list will choose a range by 47 | // size/alignment to remove. 48 | // Only range with the same data can be removed. 49 | // 50 | // Returns the removed range as [base_address, base_address + size) if 51 | // success, or err when failed. 52 | range_list_remove_ret_t 53 | range_list_remove(range_list_t *list, uint64_t base_address, size_t size, 54 | size_t alignment, uintptr_t data); 55 | 56 | // Add a range into range list 57 | // 58 | // Add [base_address, base_address + size) to the list. The added range 59 | // is marked with data. 60 | // 61 | // Returns error if there's any, or OK when success. 62 | error_t 63 | range_list_insert(range_list_t *list, uint64_t base_address, size_t size, 64 | uintptr_t data); 65 | 66 | // Update a range with data 67 | // 68 | // Update data for the range [base_address, base_address + size) in 69 | // selected_range. The specified range must inside the selected_range. 70 | // 71 | // Returns error if there's any, or OK when success. 72 | error_t 73 | range_list_update(range_list_t *list, uint64_t base_address, size_t size, 74 | range_t *selected_range, uintptr_t data); 75 | 76 | // Destroy the range list 77 | // 78 | // It will free all internal resource allocated. 79 | void 80 | range_list_deinit(range_list_t *list); 81 | 82 | typedef struct { 83 | vmaddr_t base_address; 84 | range_t *selected_range; 85 | 86 | error_t err; 87 | uint8_t err_padding[4]; 88 | } range_list_find_ret_t; 89 | 90 | // Find a proper range under region/alignment/data constrains. 91 | // 92 | // [region_base, region_base + region_size)/alignment constrains the base 93 | // address. With range_size, it can return a proper range which has the 94 | // same data. 95 | // 96 | // Returns the based address of the range, and the range node contains such 97 | // range. Or err if failed. 98 | range_list_find_ret_t 99 | range_list_find_range_by_region(range_list_t *allocator, uint64_t region_base, 100 | size_t region_size, size_t range_size, 101 | size_t alignment, uintptr_t data); 102 | 103 | // Find range which is not assigned with any data. 104 | // 105 | // [base_address, base_address + size)/alignment specify the range 106 | // it would like. base_address can be INVALID_ADDRESS, then it can select 107 | // the range based on size/alignment. 108 | // 109 | // Returns the based address of the range, and the range node contains such 110 | // range. Or err if failed. 111 | range_list_find_ret_t 112 | range_list_find_range(range_list_t *allocator, uint64_t base_address, 113 | size_t size, size_t alignment); 114 | 115 | // Check if there're ranges in the list which has the data. 116 | // 117 | // Returns true if there's. 118 | bool 119 | range_list_has_data(range_list_t *list, uintptr_t data); 120 | 121 | #ifndef NDEBUG 122 | void 123 | range_list_dump(range_list_t *list, const char *prefix); 124 | #endif 125 | -------------------------------------------------------------------------------- /include/utils/vector.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // A simple dynamic array. Memory may or maynot be contiguous. 6 | // It's not thread safe. 7 | 8 | typedef struct vector_s vector_t; 9 | 10 | // Initialize a vector, with min_capacity in units of items 11 | // and capacity_step_sz in units of items. If capacity_step_sz 12 | // or min_capacity are zero, defaults are used. 13 | #define vector_init(type, min_capacity, capacity_step_sz) \ 14 | vector_init_internal(min_capacity, capacity_step_sz, sizeof(type)) 15 | 16 | vector_t * 17 | vector_init_internal(count_t init_capacity, count_t capacity_step_sz, 18 | size_t element_sz); 19 | 20 | void 21 | vector_deinit(vector_t *vector); 22 | 23 | #define vector_push_back_imm(type, vector, val, err) \ 24 | do { \ 25 | type tmp = val; \ 26 | err = vector_push_back_internal(vector, &tmp); \ 27 | } while (0) 28 | 29 | #define vector_push_back(vector, val) vector_push_back_internal(vector, &val) 30 | 31 | error_t 32 | vector_push_back_internal(vector_t *vector, const void *val); 33 | 34 | #define vector_pop_back(type, vector) ((type *)vector_pop_back_internal(vector)) 35 | 36 | void * 37 | vector_pop_back_internal(vector_t *vector); 38 | 39 | // Swap to tail first, then delete the tail. Avoid normal deletion cost, but 40 | // the order is not kept. 41 | void 42 | vector_delete(vector_t *vector, index_t idx); 43 | 44 | void 45 | vector_delete_keep_order(vector_t *vector, index_t idx); 46 | 47 | void 48 | vector_swap(vector_t *vector, index_t idx1, index_t idx2); 49 | 50 | count_t 51 | vector_size(const vector_t *vector); 52 | 53 | #define vector_at(type, vector, idx) (*(type *)vector_at_internal(vector, idx)) 54 | 55 | #define vector_at_ptr(type, vector, idx) \ 56 | ((type *)vector_at_internal(vector, idx)) 57 | 58 | void * 59 | vector_at_internal(const vector_t *vector, index_t idx); 60 | 61 | void * 62 | vector_raw_data(const vector_t *vector); 63 | 64 | index_t 65 | vector_end(const vector_t *vector); 66 | 67 | bool 68 | vector_is_empty(const vector_t *vector); 69 | 70 | typedef bool (*vector_find_check_t)(void *val, void *target); 71 | 72 | bool 73 | vector_find(const vector_t *vector, vector_find_check_t func, void *target, 74 | index_t *idx); 75 | 76 | #define foreach_vector_ptr(element_type, vector, idx, element_ptr) \ 77 | for ((idx) = 0, \ 78 | (element_ptr) = vector_at_ptr(element_type, (vector), (idx)); \ 79 | (idx) < vector_size((vector)); ++(idx), \ 80 | (element_ptr) = vector_at_ptr(element_type, (vector), (idx))) 81 | 82 | #define foreach_vector(element_type, vector, idx, element) \ 83 | for ((idx) = 0, \ 84 | (element) = vector_size((vector)) == 0 \ 85 | ? (element_type){ 0 } \ 86 | : vector_at(element_type, (vector), (idx)); \ 87 | (idx) < vector_size((vector)); \ 88 | ++(idx), \ 89 | (element) = (idx) < vector_size((vector)) \ 90 | ? vector_at(element_type, (vector), (idx)) \ 91 | : (element_type){ 0 }) 92 | -------------------------------------------------------------------------------- /include/virq.h: -------------------------------------------------------------------------------- 1 | // © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | static const virq_t VIRQ_NUM_INVALID = ~(virq_t)0U; 6 | 7 | #define VIRQ_INVALID ((interrupt_data_t){ .irq = VIRQ_NUM_INVALID }) 8 | 9 | bool 10 | virq_is_valid(interrupt_data_t virq); 11 | 12 | interrupt_data_t 13 | virq_edge(virq_t virq_num); 14 | 15 | interrupt_data_t 16 | virq_level(virq_t virq_num); 17 | 18 | virq_t 19 | virq_get_number(interrupt_data_t virq); 20 | -------------------------------------------------------------------------------- /include/vm_config.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | extern const char *gunyah_api_version; 6 | 7 | typedef uint32_t label_t; 8 | 9 | struct vdevice_node; 10 | typedef struct vdevice_node vdevice_node_t; 11 | 12 | struct vm_console; 13 | typedef struct vm_console vm_console_t; 14 | 15 | struct rm_rpc_data; 16 | typedef struct rm_rpc_data rm_rpc_data_t; 17 | 18 | struct dtb_parser_ops; 19 | typedef struct dtb_parser_ops dtb_parser_ops_t; 20 | 21 | struct dtb_parser_data_s; 22 | typedef struct dtb_parser_data_s vm_config_parser_data_t; 23 | 24 | struct dtb_parser_alloc_params_s; 25 | typedef struct dtb_parser_alloc_params_s vm_config_parser_params_t; 26 | 27 | struct general_data; 28 | typedef struct general_data general_data_t; 29 | 30 | typedef uint32_t resource_handle_t; 31 | 32 | typedef struct vector_s vector_t; 33 | 34 | #define VDEVICE_MAX_COMPATIBLE_LEN 256U 35 | #define VDEVICE_MAX_PUSH_COMPATIBLES 6U 36 | 37 | rm_error_t 38 | vm_config_init(rm_env_data_t *env_data); 39 | 40 | vm_config_t * 41 | vm_config_alloc(vm_t *vm, cap_id_t cspace, cap_id_t partition); 42 | 43 | void 44 | vm_config_dealloc(vm_t *vm); 45 | 46 | void 47 | vm_config_hlos_vdevices_setup(vm_config_t *vmcfg, cap_id_t vic); 48 | 49 | void 50 | vm_config_add_vdevices(vm_config_t *vmcfg); 51 | 52 | rm_error_t 53 | vm_config_parse_dt(vm_config_t *vmcfg, void *fdt); 54 | 55 | error_t 56 | vm_config_add_vcpu(vm_config_t *vmcfg, cap_id_t rm_cap, uint32_t affinity_index, 57 | bool boot_vcpu, const char *patch); 58 | 59 | vector_t * 60 | vm_config_get_vcpus(const vm_config_t *vmcfg); 61 | 62 | void 63 | vm_config_destroy(vm_config_t *vmcfg); 64 | 65 | void 66 | vm_config_deinit(void); 67 | 68 | error_t 69 | handle_compatibles(vdevice_node_t *vdevice, const general_data_t *data); 70 | 71 | // APIs to help vm query 72 | rm_error_t 73 | vm_config_get_resource_descs(vmid_t self, vmid_t vmid, vector_t *descs); 74 | 75 | #pragma clang diagnostic push 76 | #pragma clang diagnostic ignored "-Wpadded" 77 | 78 | typedef struct { 79 | rm_error_t err; 80 | 81 | cap_id_t tx_capid; 82 | cap_id_t rx_capid; 83 | 84 | virq_t tx_virq; 85 | virq_t rx_virq; 86 | } vm_config_get_rm_rpc_msg_queue_info_ret_t; 87 | 88 | #pragma clang diagnostic pop 89 | 90 | vm_config_get_rm_rpc_msg_queue_info_ret_t 91 | vm_config_get_rm_rpc_msg_queue_info(vmid_t self, vmid_t peer_id); 92 | 93 | __attribute__((weak)) vm_config_get_rm_rpc_msg_queue_info_ret_t 94 | platform_get_hyp_rpc_msg_queue_info(void); 95 | 96 | void 97 | vm_config_set_console(vm_config_t *vmcfg, vm_console_t *console); 98 | 99 | struct vm_console * 100 | vm_config_get_console(vmid_t self); 101 | 102 | bool 103 | vm_config_check_console_allowed(vmid_t self); 104 | 105 | void 106 | vm_config_flush_rm_rpc(vmid_t self); 107 | 108 | dtb_parser_ops_t * 109 | vm_config_parser_get_ops(void); 110 | 111 | vm_config_parser_params_t 112 | vm_config_parser_get_params(const vm_t *vm); 113 | 114 | error_t 115 | vm_config_update_parsed(vm_config_t *vmcfg, vm_config_parser_data_t *data); 116 | 117 | error_t 118 | vm_config_create_vdevices(vm_config_t *vmcfg, vm_config_parser_data_t *data); 119 | 120 | void 121 | vm_config_destroy_vm_objects(vm_t *vm); 122 | 123 | void 124 | vm_config_handle_exit(const vm_t *vm); 125 | 126 | bool 127 | vm_reset_handle_init(const vm_t *vm); 128 | 129 | bool 130 | vm_reset_handle_destroy_vdevices(const vm_t *vm); 131 | 132 | void 133 | vm_config_delete_vdevice_node(vm_config_t *vmcfg, vdevice_node_t **node); 134 | 135 | void 136 | vm_config_destroy_vdevices(vm_t *vm); 137 | 138 | extern vmid_t ras_handler_vm; 139 | 140 | error_t 141 | vm_config_vrtc_set_time_base(vm_t *vm, uint64_t time_base, 142 | uint64_t sys_timer_ref); 143 | -------------------------------------------------------------------------------- /include/vm_console.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | struct vm_console; 6 | typedef struct vm_console vm_console_t; 7 | 8 | rm_error_t 9 | vm_console_init(void); 10 | 11 | vm_console_t * 12 | vm_console_create(vm_t *vm); 13 | 14 | bool 15 | vm_console_msg_handler(vmid_t client_id, uint32_t msg_id, uint16_t seq_num, 16 | void *buf, size_t len); 17 | 18 | void 19 | vm_console_destroy(vm_console_t *console); 20 | 21 | void 22 | vm_console_deinit(void); 23 | -------------------------------------------------------------------------------- /include/vm_console_message.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define VM_CONSOLE_OPEN 0x56000081 6 | #define VM_CONSOLE_CLOSE 0x56000082 7 | #define VM_CONSOLE_WRITE 0x56000083 8 | #define VM_CONSOLE_FLUSH 0x56000084 9 | 10 | #define NOTIFY_VM_CONSOLE_CHARS 0x56100080 11 | 12 | typedef struct { 13 | vmid_t target; 14 | uint16_t res0; 15 | } vm_console_open_req_t; 16 | 17 | typedef struct { 18 | vmid_t target; 19 | uint16_t res0; 20 | } vm_console_close_req_t; 21 | 22 | typedef struct { 23 | vmid_t target; 24 | uint16_t num_bytes; 25 | 26 | // with content tailing 27 | } vm_console_write_req_t; 28 | 29 | typedef struct { 30 | vmid_t target; 31 | uint16_t res0; 32 | } vm_console_flush_req_t; 33 | 34 | typedef struct { 35 | vmid_t from; 36 | 37 | uint16_t num_bytes; 38 | 39 | // with content tailing 40 | } vm_console_chars_notify_t; 41 | -------------------------------------------------------------------------------- /include/vm_creation.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define MAX_CAPS 1024 6 | #define GIC_SPI_NUM 988 7 | #define GIC_LPI_NUM 8192 8 | 9 | error_t 10 | rm_vm_create(const rm_env_data_t *env_data); 11 | 12 | error_t 13 | hlos_vm_create(const rm_env_data_t *env_data); 14 | 15 | error_t 16 | hlos_vm_start(void); 17 | 18 | rm_error_t 19 | vm_creation_config_image(vm_t *vm, vm_auth_type_t auth, 20 | resource_handle_t image_mp_handle, 21 | uint64_t image_offset, uint64_t image_size, 22 | uint64_t dt_offset, uint64_t dt_size); 23 | 24 | typedef struct vm_auth_param { 25 | uint32_t auth_param_type; 26 | uint32_t auth_param; 27 | } vm_auth_param_t; 28 | 29 | rm_error_t 30 | vm_creation_auth(vm_t *vm, count_t num_auth_params, 31 | vm_auth_param_t *auth_params); 32 | 33 | rm_error_t 34 | vm_creation_init(vm_t *vm); 35 | 36 | void 37 | svm_takedown(vmid_t vmid); 38 | 39 | void 40 | svm_destroy(vmid_t vmid); 41 | 42 | error_t 43 | svm_create(vm_t *svm); 44 | 45 | bool 46 | vm_creation_msg_handler(vmid_t client_id, uint32_t msg_id, uint16_t seq_num, 47 | void *buf, size_t len); 48 | 49 | error_t 50 | vm_creation_process_resource(vm_t *vm); 51 | 52 | typedef struct memparcel memparcel_t; 53 | 54 | error_t 55 | vm_creation_process_memparcel(vm_t *vm, memparcel_t *mp); 56 | 57 | uintptr_result_t 58 | map_dtb(size_t dtb_offset, size_t dtb_size, uint32_t mp_handle, 59 | size_t ipa_size); 60 | 61 | error_t 62 | unmap_dtb(uint32_t mp_handle); 63 | 64 | error_t 65 | vm_creation_config_vm_info_area(vm_config_t *vmcfg); 66 | 67 | error_t 68 | vm_creation_map_vm_info_area(vm_config_t *vmcfg); 69 | 70 | void 71 | vm_creation_vm_info_area_teardown(vm_config_t *vmcfg); 72 | 73 | bool 74 | vm_reset_handle_cleanup(vm_t *vm); 75 | 76 | bool 77 | vm_reset_handle_destroy(vm_t *vm); 78 | -------------------------------------------------------------------------------- /include/vm_creation_dt.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | error_t 6 | vm_creation_add_compatibles(const struct vdevice_node *node, 7 | const char *const compatibles[], 8 | count_t compatible_cnt, dto_t *dto); 9 | 10 | char * 11 | vm_creation_node_name_capid(const char *generate, cap_id_t cap_id); 12 | -------------------------------------------------------------------------------- /include/vm_creation_message.h: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define VM_CONFIG_IMAGE 0x56000009 6 | #define VM_AUTH_IMAGE 0x5600000a 7 | #define VM_INIT 0x5600000b 8 | 9 | typedef struct { 10 | vmid_t target; 11 | uint16_t auth_type; 12 | 13 | resource_handle_t image_mp_handle; 14 | 15 | uint64_t image_offset; 16 | uint64_t image_size; 17 | uint64_t dt_offset; 18 | uint64_t dt_size; 19 | } vm_config_image_req_t; 20 | 21 | typedef struct { 22 | vmid_t target; 23 | uint16_t num_auth_params; 24 | vm_auth_param_t auth_params[]; 25 | } vm_auth_req_t; 26 | 27 | typedef struct { 28 | vmid_t target; 29 | uint16_t res0; 30 | } vm_init_req_t; 31 | -------------------------------------------------------------------------------- /include/vm_dt.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define HLOS_MAX_NUM_DTBOS 2 6 | 7 | RM_PADDED(struct boot_dtbo_info_s { 8 | void *base; 9 | size_t size; 10 | }) 11 | 12 | typedef struct boot_dtbo_info_s boot_dtbo_info_t; 13 | 14 | RM_PADDED(typedef struct { 15 | error_t err; 16 | count_t num_dtbos; 17 | boot_dtbo_info_t dtbos[HLOS_MAX_NUM_DTBOS]; 18 | } vm_dt_create_hlos_ret_t) 19 | 20 | vm_dt_create_hlos_ret_t 21 | vm_dt_create_hlos(void *base, size_t size, vmaddr_t log_ipa, size_t log_size); 22 | 23 | error_t 24 | vm_dt_apply_hlos_overlay(vm_t *hlos_vm, paddr_t hlos_dtb, size_t dtb_size); 25 | -------------------------------------------------------------------------------- /include/vm_elf.h: -------------------------------------------------------------------------------- 1 | // © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | rm_error_t 6 | vm_elf_process_ptload_segments(Elf_Ehdr_ptr ehdr, Elf_Phdr_ptr phdrs, 7 | uintptr_t mem_base, vmaddr_t mem_size, 8 | paddr_t phys_base, 9 | boot_env_phys_range_t *vm_segments, 10 | size_t num_vm_segments, size_t *segment_count, 11 | paddr_t *entry_offset, paddr_t *dt_offset, 12 | size_t *dt_size, bool *single_dtb); 13 | -------------------------------------------------------------------------------- /include/vm_firmware.h: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | bool 6 | vm_firmware_msg_handler(vmid_t client_id, uint32_t msg_id, uint16_t seq_num, 7 | void *buf, size_t len); 8 | 9 | rm_error_t 10 | vm_firmware_vm_set_mem(vm_t *vm, resource_handle_t fw_mp_handle, 11 | size_t fw_offset, size_t fw_size); 12 | 13 | rm_error_t 14 | vm_firmware_vm_start(vm_t *vm); 15 | -------------------------------------------------------------------------------- /include/vm_firmware_message.h: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define FW_MILESTONE 0x51000020 6 | #define FW_SET_VM_FIRMWARE 0x51000021 7 | 8 | typedef struct { 9 | uint16_t auth_type; 10 | uint16_t res0; 11 | 12 | resource_handle_t image_mp_handle; 13 | uint64_t image_offset; 14 | uint64_t image_size; 15 | } fw_set_vm_firmware_req_t; 16 | -------------------------------------------------------------------------------- /include/vm_ipa.h: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | bool 6 | vm_ipa_msg_handler(vmid_t client_id, uint32_t msg_id, uint16_t seq_num, 7 | void *buf, size_t len); 8 | -------------------------------------------------------------------------------- /include/vm_ipa_message.h: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define IPA_RESERVE 0x560000B0 6 | #define IPA_UNRESERVE 0x560000B1 7 | 8 | typedef enum ipa_reserve_req_type_e { 9 | IPA_RESERVE_REQ_FIXED_LIST = 0, 10 | IPA_RESERVE_REQ_ALLOC_LIST = 1, 11 | } ipa_reserve_req_type_t; 12 | 13 | #define IPA_GENERIC_CONSTRAINT_NONE 0x0U 14 | #define IPA_GENERIC_CONSTRAINT_ECC 0x1U 15 | #define IPA_GENERIC_CONSTRAINT_TAGGED 0x2U 16 | #define IPA_GENERIC_CONSTRAINT_NORMAL 0x4U 17 | #define IPA_GENERIC_CONSTRAINT_IO 0x8U 18 | #define IPA_GENERIC_CONSTRAINT_OWNER_VM_VISIBLE 0x10U 19 | #define IPA_GENERIC_CONSTRAINT_EXTERNAL_BUS_VISIBLE 0x20U 20 | #define IPA_GENERIC_CONSTRAINT_BASE_MEMORY_COMPATIBLE 0x40U 21 | 22 | #define IPA_PLATFORM_CONSTRAINT_NONE 0x0U 23 | 24 | typedef struct { 25 | uint8_t alloc_type; 26 | uint8_t res0_0; 27 | uint16_t res0_1; 28 | uint32_t generic_constraints; 29 | uint32_t platform_constraints; 30 | uint32_t entries; 31 | } ipa_reserve_req_t; 32 | 33 | typedef struct { 34 | uint64_t base; 35 | uint64_t size; 36 | } ipa_reserve_req_fixed_list_t; 37 | 38 | typedef struct { 39 | uint64_t region_base; 40 | uint64_t region_size; 41 | uint64_t size; 42 | uint64_t alignment; 43 | } ipa_reserve_req_alloc_list_t; 44 | 45 | typedef struct { 46 | uint32_t reserved_entires; 47 | } ipa_reserve_alloc_resp_t; 48 | -------------------------------------------------------------------------------- /include/vm_mgnt.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // 16 byte, each costs 2 char, 4 char for '-', 1 for terminator 6 | #define VM_MAX_GUID_STRING_LEN (16 * 2 + 4 + 1) 7 | 8 | #define VM_MAX_CRASH_MSG_LEN 192 9 | 10 | typedef enum { 11 | VM_STATE_NONE = 0, 12 | VM_STATE_INIT = 1, 13 | VM_STATE_READY = 2, 14 | VM_STATE_RUNNING = 3, 15 | VM_STATE_PAUSED = 4, 16 | VM_STATE_LOAD = 5, 17 | VM_STATE_AUTH = 6, 18 | // 7 reserved 19 | VM_STATE_INIT_FAILED = 8, 20 | VM_STATE_EXITED = 9, 21 | VM_STATE_RESETTING = 10, 22 | VM_STATE_RESET = 11, 23 | } vm_state_t; 24 | 25 | typedef enum { 26 | OS_STATE_NONE = 0, 27 | OS_STATE_EARLY_BOOT = 1, 28 | OS_STATE_BOOT = 2, 29 | OS_STATE_INIT = 3, 30 | OS_STATE_RUN = 4, 31 | OS_STATE_SHUTDOWN = 5, 32 | OS_STATE_HALTED = 6, 33 | OS_STATE_CRASHED = 7, 34 | } os_state_t; 35 | 36 | typedef uint16_t app_status_t; 37 | 38 | typedef enum { 39 | EXIT_TYPE_VM_EXIT = 0, 40 | EXIT_TYPE_PLATFORM_OFF = 1, 41 | EXIT_TYPE_PLATFORM_RESET = 2, 42 | EXIT_TYPE_PSCI_SYSTEM_RESET2 = 3, 43 | EXIT_TYPE_WATCHDOG_BITE = 4, 44 | EXIT_TYPE_SOFTWARE_ERROR = 5, 45 | EXIT_TYPE_ASYNC_HW_ERROR = 6, 46 | EXIT_TYPE_VM_STOP_FORCED = 7, 47 | } exit_type_t; 48 | 49 | // EXIT_FLAGS bit numbering 50 | typedef enum { 51 | EXIT_FLAG_RESTART = 0, 52 | } exit_flags_t; 53 | 54 | typedef enum { 55 | EXIT_CODE_NORMAL = 0, 56 | EXIT_CODE_SOFTWARE_ERROR = 1, 57 | EXIT_CODE_UNKNOWN_ERROR = 2, 58 | EXIT_CODE_BUS_ERROR = 3, 59 | EXIT_CODE_DEVICE_ERROR = 4, 60 | } exit_code_t; 61 | 62 | typedef enum { 63 | VM_EVENT_SRC_WDOG_BITE = 0, 64 | VM_EVENT_SRC_VCPU_HALT = 1, 65 | } vm_event_src_t; 66 | 67 | typedef enum { 68 | VM_RESET_STAGE_INIT = 0, 69 | VM_RESET_STAGE_DESTROY_VDEVICES = 1, 70 | VM_RESET_STAGE_RELEASE_MEMPARCELS = 2, 71 | VM_RESET_STAGE_RELEASE_IRQS = 3, 72 | VM_RESET_STAGE_DESTROY_VM = 4, 73 | VM_RESET_STAGE_CLEANUP_VM = 5, 74 | VM_RESET_STAGE_COMPLETED = 6, 75 | } vm_reset_stage_t; 76 | 77 | struct address_range_allocator; 78 | typedef struct address_range_allocator address_range_allocator_t; 79 | typedef uint32_t address_range_tag_t; 80 | 81 | struct vm_mem_range; 82 | typedef struct vm_mem_range vm_mem_range_t; 83 | 84 | struct irq_manager_vm; 85 | typedef struct irq_manager_vm irq_manager_vm_t; 86 | 87 | #pragma clang diagnostic push 88 | #pragma clang diagnostic ignored "-Wpadded" 89 | 90 | struct vm_s { 91 | vmid_t vmid; 92 | vmid_t owner; 93 | 94 | vector_t *peers; 95 | 96 | char name[VM_MAX_NAME_LEN]; 97 | uint16_t name_len; 98 | 99 | bool has_uri; 100 | char uri[VM_MAX_URI_LEN]; 101 | uint16_t uri_len; 102 | 103 | bool has_guid; 104 | uint8_t guid[VM_GUID_LEN]; 105 | 106 | vm_state_t vm_state; 107 | os_state_t os_state; 108 | app_status_t app_status; 109 | 110 | vm_config_t *vm_config; 111 | 112 | irq_manager_vm_t *irq_manager; 113 | 114 | address_range_allocator_t *as_allocator; 115 | paddr_t as_size; 116 | 117 | vm_mem_range_t *mem_list; 118 | 119 | vm_auth_type_t auth_type; 120 | // VM base memory 121 | uint32_t mem_mp_handle; 122 | address_range_tag_t mem_base_tag; 123 | 124 | paddr_t image_offset; 125 | size_t image_size; 126 | 127 | paddr_t ramfs_offset; 128 | size_t ramfs_size; 129 | 130 | paddr_t cfgcpio_offset; 131 | size_t cfgcpio_size; 132 | vector_t *cfgcpio_cmdline; 133 | size_t cfgcpio_cmdline_len; 134 | 135 | paddr_t entry_offset; 136 | 137 | paddr_t dt_offset; 138 | size_t dt_size; 139 | 140 | vmaddr_t ipa_base; 141 | paddr_t mem_base; 142 | vmaddr_t mem_size; 143 | 144 | uint32_t fw_mp_handle; 145 | size_t fw_offset; 146 | size_t fw_size; 147 | 148 | vmaddr_t vm_info_area_ipa; 149 | size_t vm_info_area_size; 150 | vmaddr_t vm_info_area_rm_ipa; 151 | 152 | cap_id_t owned_ddr_me; 153 | cap_id_t owned_device_me; 154 | 155 | uint32_t chip_id; 156 | uint32_t chip_version; 157 | uint32_t foundry_id; 158 | uint32_t platform_type; 159 | uint32_t platform_version; 160 | uint32_t platform_subtype; 161 | uint32_t hlos_subtype; 162 | 163 | uint32_t signer_info; 164 | 165 | priority_t priority; 166 | event_t wdog_bite_event; 167 | 168 | count_t mp_count; 169 | 170 | char *crash_msg; 171 | uint16_t crash_msg_len; 172 | 173 | bool sensitive; 174 | bool crash_fatal; 175 | bool no_shutdown; 176 | bool no_reset; 177 | bool qtee_registered; 178 | 179 | vm_reset_stage_t reset_stage; 180 | event_t reset_event; 181 | }; 182 | 183 | #pragma clang diagnostic pop 184 | 185 | rm_error_t 186 | vm_mgnt_init(void); 187 | 188 | bool 189 | vm_mgnt_msg_handler(vmid_t client_id, uint32_t msg_id, uint16_t seq_num, 190 | void *buf, size_t len); 191 | 192 | void 193 | vm_mgnt_set_name(vm_t *vm, const char *name); 194 | 195 | vm_t * 196 | vm_lookup(vmid_t vmid); 197 | 198 | bool 199 | vm_is_secondary_vm(vmid_t vmid); 200 | 201 | bool 202 | vm_is_peripheral_vm(vmid_t vmid); 203 | 204 | bool 205 | vm_is_dynamic_vm(vmid_t vmid); 206 | 207 | error_t 208 | vm_register_peers(vm_t *vm1, vm_t *vm2); 209 | 210 | void 211 | vm_deregister_peers(vm_t *vm1, vm_t *vm2); 212 | 213 | void 214 | vm_deregister_all_peers(vm_t *vm); 215 | 216 | vm_t * 217 | vm_lookup_by_id(const char *peer_id); 218 | 219 | rm_error_t 220 | vm_mgnt_send_state(vm_t *vm); 221 | 222 | bool 223 | vm_mgnt_is_vm_sensitive(vmid_t vmid); 224 | 225 | bool 226 | vm_mgnt_state_change_valid(const vm_t *vm, vm_state_t vm_state); 227 | 228 | rm_error_t 229 | vm_mgnt_register_event(vm_event_src_t event_src, event_t *event, void *data, 230 | virq_t virq); 231 | 232 | void 233 | vm_mgnt_deregister_event(event_t *event, virq_t virq); 234 | 235 | void 236 | vm_mgnt_clear_crash_msg(vmid_t client_id); 237 | 238 | rm_error_t 239 | vm_mgnt_new_vm(vmid_t vmid, vmid_t owner); 240 | -------------------------------------------------------------------------------- /include/vm_mgnt_message.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define VM_ALLOCATE 0x56000001U 6 | #define VM_DEALLOCATE 0x56000002U 7 | #define VM_START 0x56000004U 8 | #define VM_STOP 0x56000005U 9 | #define VM_RESET 0x56000006U 10 | // #define VM_SUSPEND 0x56000007 11 | // #define VM_RESUME 0x56000008 12 | 13 | #define VM_GET_ID 0x56000010U 14 | #define VM_LOOKUP_URI 0x56000011U 15 | #define VM_LOOKUP_GUID 0x56000012U 16 | #define VM_LOOKUP_NAME 0x56000013U 17 | #define VM_GET_OWNER 0x56000015U 18 | 19 | #define VM_GET_STATE 0x56000017U 20 | #define VM_GET_CRASH_MSG 0x56000019U 21 | #define VM_GET_HYP_RESOURCES 0x56000020U 22 | #define VM_GET_HYP_CAPIDS 0x56000021U 23 | #define VM_GET_HYP_IRQS 0x56000022U 24 | #define VM_GET_VMID 0x56000024U 25 | #define VM_GET_PEERS 0x56000025U 26 | 27 | #define VM_SET_TIME_BASE 0x56000030U 28 | #define VM_SET_CONTEXT 0x56000031U 29 | #define VM_SET_FIRMWARE_MEM 0x56000032U 30 | 31 | #define VM_SET_STATUS 0x56000080U 32 | #define VM_EXIT 0x56000085U 33 | #define VM_SET_CRASH_MSG 0x56000086U 34 | #define VM_HOST_GET_TYPE 0x560000A0U 35 | 36 | #define NOTIFY_VM_EXITED 0x56100001U 37 | #define NOTIFY_VM_SHUTDOWN 0x56100002U 38 | #define NOTIFY_VM_STATUS 0x56100008U 39 | 40 | typedef struct rm_notify_vm_status { 41 | uint16_t vm_vmid; 42 | uint16_t res0; 43 | uint8_t vm_status; 44 | uint8_t os_status; 45 | uint16_t app_status; 46 | } rm_notify_vm_status_t; 47 | 48 | typedef struct { 49 | vmid_t target; 50 | uint16_t res0; 51 | 52 | resource_handle_t fw_mp_handle; 53 | uint64_t fw_offset; 54 | uint64_t fw_size; 55 | } vm_set_firmware_mem_t; 56 | 57 | typedef struct rm_notify_vm_exited { 58 | uint16_t vmid; 59 | uint16_t exit_type; 60 | uint32_t exit_reason_size; 61 | // exit_reason 62 | } rm_notify_vm_exited_t; 63 | 64 | #define VM_STOP_FLAG_FORCE 1U 65 | -------------------------------------------------------------------------------- /include/vm_passthrough_config.h: -------------------------------------------------------------------------------- 1 | // © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | RM_PADDED(struct vm_device_descriptor_s { 6 | vmid_t vmid; 7 | count_t num_irqs; 8 | count_t num_mmio_ranges; 9 | uint32_t *irqs; 10 | root_env_mmio_range_descriptor_t *mmio_ranges; 11 | }) 12 | 13 | RM_PADDED(struct vm_device_assignments_s { 14 | count_t num_devices; 15 | vm_device_descriptor_t *devices; 16 | }) 17 | 18 | error_t 19 | vm_passthrough_config_unmap_ioranges(const rm_env_data_t *env_data); 20 | 21 | void 22 | vm_passthrough_config_validate(const rm_env_data_t *env_data); 23 | 24 | void 25 | vm_passthrough_config_deinit(const rm_env_data_t *env_data); 26 | 27 | bool 28 | vm_passthrough_config_is_addr_in_range(vmid_t vmid, vmaddr_t ipa, size_t size, 29 | pgtable_access_t access); 30 | 31 | count_t 32 | vm_passthrough_get_num_devices(void); 33 | 34 | count_t 35 | vm_passthrough_device_get_num_mmio_ranges(index_t dev_id); 36 | 37 | const root_env_mmio_range_descriptor_t * 38 | vm_passthrough_get_device_mmio_ranges(index_t dev_id); 39 | 40 | vmid_t 41 | vm_passthrough_device_get_vmid(index_t dev_id); 42 | -------------------------------------------------------------------------------- /include/vm_resource_msg.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | typedef enum { 6 | RSC_DOORBELL_SRC = 0, 7 | RSC_DOORBELL = 1, 8 | RSC_MSG_QUEUE_SEND = 2, 9 | RSC_MSG_QUEUE_RECV = 3, 10 | RSC_VIRTUAL_CPU = 4, 11 | RSC_VIRTUAL_PM = 5, 12 | RSC_VIRTIO_MMIO = 6, 13 | RSC_VRTC = 7, 14 | RSC_WATCHDOG = 8, 15 | } resource_type_t; 16 | 17 | typedef uint32_t resource_label_t; 18 | 19 | struct rm_hyp_resource_resp { 20 | uint8_t resource_type; 21 | uint8_t res0; 22 | uint16_t partner_vmid; 23 | 24 | resource_handle_t resource_handle; 25 | resource_label_t resource_label; 26 | 27 | uint32_t resource_capid_low; 28 | uint32_t resource_capid_high; 29 | 30 | uint32_t resource_virq_handle; 31 | uint32_t resource_virq_number; 32 | 33 | uint32_t resource_base_address_low; 34 | uint32_t resource_base_address_high; 35 | 36 | uint32_t resource_size_low; 37 | uint32_t resource_size_high; 38 | }; 39 | 40 | typedef struct rm_hyp_resource_resp rm_hyp_resource_resp_t; 41 | -------------------------------------------------------------------------------- /include/vm_resources.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | bool 6 | vm_get_resources_handler(vmid_t client_id, uint32_t msg_id, uint16_t seq_num, 7 | void *buf, size_t len); 8 | -------------------------------------------------------------------------------- /include/vm_vcpu.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #pragma clang diagnostic push 6 | #pragma clang diagnostic ignored "-Wpadded" 7 | 8 | struct vcpu_s { 9 | // Cap in RM's cspace 10 | cap_id_t master_cap; 11 | 12 | // Possibly turn this into a list of tuples (vmid, cap) 13 | cap_id_t owner_cap; 14 | cap_id_t vm_cap; 15 | 16 | uint32_t affinity_index; 17 | 18 | interrupt_data_t proxy_virq; 19 | 20 | bool boot_vcpu; 21 | char *patch; 22 | 23 | vmid_t vmid; 24 | 25 | interrupt_data_t halt_virq; 26 | event_t halt_event; 27 | 28 | bool exited; 29 | }; 30 | typedef struct vcpu_s vcpu_t; 31 | 32 | #pragma clang diagnostic pop 33 | -------------------------------------------------------------------------------- /platform/qemu/build.conf: -------------------------------------------------------------------------------- 1 | # © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | 5 | include include 6 | local_include src 7 | source src/vm_dt.c 8 | source src/vm_client.c 9 | source src/uart_qemu.c 10 | source src/platform_qemu.c 11 | source src/platform_rtc.c 12 | source src/vm_config_parser.c 13 | source src/vm_config.c 14 | source src/exit/exit.c 15 | source src/vm_memory.c 16 | source src/vgic.c 17 | -------------------------------------------------------------------------------- /platform/qemu/include/platform_dt.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Apply generic platform transformations to the VM DT. 6 | // This applies to HLOS and secondary VMs. 7 | error_t 8 | platform_dto_finalise(dto_t *dto, vm_t *vm, const void *base_dtb); 9 | 10 | error_t 11 | platform_dto_add_platform_props(dto_t *dto, vm_t *cur_vm); 12 | 13 | error_t 14 | platform_dto_create(struct vdevice_node *node, dto_t *dto, vmid_t self); 15 | -------------------------------------------------------------------------------- /platform/qemu/include/platform_dt_parser.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | struct dtb_parser_data_s; 6 | typedef struct dtb_parser_data_s vm_config_parser_data_t; 7 | 8 | listener_return_t 9 | platform_parse_interrupts(vm_config_parser_data_t *data, const void *fdt, 10 | int node_ofs, const ctx_t *ctx); 11 | 12 | listener_return_t 13 | platform_parse_root(vm_config_parser_data_t *data, const void *fdt, 14 | int node_ofs, const ctx_t *ctx); 15 | 16 | // clang-format off 17 | #define PLATFORM_LISTENERS \ 18 | { \ 19 | .type = BY_PATH, \ 20 | .expected_path = "^/(qcom,|gunyah-)vm-config/interrupts$", \ 21 | .action = platform_parse_interrupts, \ 22 | }, \ 23 | { \ 24 | .type = BY_PATH, \ 25 | .expected_path = "^/$", \ 26 | .action = platform_parse_root, \ 27 | }, 28 | 29 | // clang-format on 30 | 31 | typedef struct platform_data { 32 | uintptr_t type; 33 | void *data; 34 | } platform_data_t; 35 | -------------------------------------------------------------------------------- /platform/qemu/include/platform_qemu.h: -------------------------------------------------------------------------------- 1 | // © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | RM_PADDED(typedef struct boot_env_gic_phys_range_s { 6 | paddr_t base; 7 | count_t count; 8 | } boot_env_gic_phys_range_t) 9 | 10 | RM_PADDED(struct platform_env_data_s { 11 | paddr_t gicd_base; 12 | 13 | size_t gicr_stride; 14 | count_t gicr_ranges_count; 15 | boot_env_gic_phys_range_t gicr_ranges[2]; 16 | }) 17 | -------------------------------------------------------------------------------- /platform/qemu/include/platform_vm_config.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // We are able to parse the VIC configuration from the DT 6 | #define PLATFORM_VIC_DEFAULT_ADDR false 7 | 8 | RM_PADDED(typedef struct platform_vm_config_s { 9 | index_t primary_vm_index; 10 | 11 | int ramfs_idx; 12 | 13 | vmaddr_t vgic_gicd_base; 14 | vmaddr_t vgic_gicr_base; 15 | vmaddr_t vgic_gicr_stride; 16 | uint32_t vgic_phandle; 17 | count_t vgic_addr_cells; 18 | count_t vgic_size_cells; 19 | bool vgic_patch_dt; 20 | } platform_vm_config_t) 21 | 22 | struct dtb_parser_data_s; 23 | typedef struct dtb_parser_data_s vm_config_parser_data_t; 24 | 25 | error_t 26 | platform_vm_config_create_vdevices(vm_config_t *vmcfg, 27 | vm_config_parser_data_t *data); 28 | 29 | error_t 30 | platform_vm_config_hlos_vdevices_setup(vm_config_t *vmcfg); 31 | -------------------------------------------------------------------------------- /platform/qemu/include/platform_vm_config_parser.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | RM_PADDED(struct platform_vm_config_parser_data { 6 | index_t primary_vm_index; 7 | int ramfs_idx; 8 | vmaddr_t vgic_gicd_base; 9 | vmaddr_t vgic_gicr_base; 10 | vmaddr_t vgic_gicr_stride; 11 | uint32_t vgic_phandle; 12 | count_t vgic_addr_cells; 13 | count_t vgic_size_cells; 14 | bool vgic_patch_dt; 15 | }) 16 | 17 | typedef struct platform_vm_config_parser_data platform_vm_config_parser_data_t; 18 | 19 | rm_error_t 20 | platform_alloc_parser_data(vm_config_parser_data_t *vd); 21 | 22 | void 23 | platform_free_parser_data(vm_config_parser_data_t *vd); 24 | -------------------------------------------------------------------------------- /platform/qemu/include/platform_vm_memory.h: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Donate memory between the RM partition and a DDR memextent. 6 | error_t 7 | platform_vm_memory_donate_ddr(cap_id_t me_cap, paddr_t phys, size_t size, 8 | bool to_cap); 9 | -------------------------------------------------------------------------------- /platform/qemu/include/vgic.h: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | error_t 6 | vgic_init(const rm_env_data_t *env_data); 7 | 8 | error_t 9 | vgic_vm_config_add(vm_config_t *vmcfg, const vm_config_parser_data_t *data); 10 | 11 | error_t 12 | vgic_dto_finalise(dto_t *dto, const vm_t *vm); 13 | 14 | static const size_t vgic_gicd_size = (size_t)1U << 16; 15 | static const size_t vgic_gicr_size = (size_t)2U << 16; 16 | static const size_t vgic_alignment = (size_t)1U << 16; 17 | -------------------------------------------------------------------------------- /platform/qemu/include/vm_client.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | typedef enum { 6 | VM_SIGN_INIT = 0, /* Image is not initialized */ 7 | VM_SIGN_UNAUTHORIZED = 1, /* Image is not signed */ 8 | } vm_sign_t; 9 | -------------------------------------------------------------------------------- /platform/qemu/src/exit/exit.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | void 14 | platform_exit_handler(int exit_code) 15 | { 16 | (void)exit_code; 17 | 18 | // TODO: Trigger the HW watchdog to reset the system 19 | } 20 | -------------------------------------------------------------------------------- /platform/qemu/src/platform_rtc.c: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | bool 23 | platform_has_vrtc_support(void) 24 | { 25 | bool ret = false; 26 | 27 | return ret; 28 | } 29 | 30 | error_t 31 | platform_vrtc_attach_addrspace(cap_id_t rtc_cap, cap_id_t addrspace_cap) 32 | { 33 | (void)rtc_cap; 34 | (void)addrspace_cap; 35 | 36 | return ERROR_UNIMPLEMENTED; 37 | } 38 | 39 | error_t 40 | platform_rtc_set_time_base(cap_id_t rtc_cap, uint64_t time_base, 41 | uint64_t sys_timer_ref) 42 | { 43 | error_t err = ERROR_UNIMPLEMENTED; 44 | 45 | (void)rtc_cap; 46 | (void)time_base; 47 | (void)sys_timer_ref; 48 | return err; 49 | } 50 | 51 | cap_id_result_t 52 | platform_vrtc_create_and_configure(cap_id_t p_cap, cap_id_t cs_cap, 53 | vmaddr_t ipa) 54 | { 55 | cap_id_result_t ret = { .e = ERROR_UNIMPLEMENTED, 56 | .r = CSPACE_CAP_INVALID }; 57 | 58 | (void)p_cap; 59 | (void)cs_cap; 60 | (void)ipa; 61 | return ret; 62 | } 63 | -------------------------------------------------------------------------------- /platform/qemu/src/uart_qemu.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "uart_qemu.h" 18 | 19 | static bool g_uart_log_en = false; 20 | static vmaddr_t uart_address; 21 | 22 | void 23 | uart_putc(const char c) 24 | { 25 | if (!g_uart_log_en) { 26 | goto out; 27 | } 28 | 29 | volatile uint32_t *tfr = (uint32_t *)(uart_address + UART_TFR); 30 | volatile uint32_t *dr = (uint32_t *)(uart_address + UART_DR); 31 | 32 | while ((*tfr & ((uint32_t)1U << 5)) != 0U) { 33 | } 34 | *dr = c; 35 | 36 | out: 37 | return; 38 | } 39 | 40 | void 41 | uart_write(const char *out, size_t size) 42 | { 43 | if (!g_uart_log_en) { 44 | goto out; 45 | } 46 | 47 | size_t remain = size; 48 | const char *pos = out; 49 | 50 | while (remain > 0) { 51 | char c; 52 | 53 | if (*pos == '\n') { 54 | c = '\r'; 55 | uart_putc(c); 56 | } 57 | 58 | c = *pos; 59 | uart_putc(c); 60 | pos++; 61 | remain--; 62 | } 63 | 64 | out: 65 | return; 66 | } 67 | 68 | void 69 | platform_uart_map(rm_env_data_t *env_data) 70 | { 71 | error_t ret = OK; 72 | 73 | if (env_data->uart_address != 0U) { 74 | ret = memextent_map(rm_get_uart_me(), env_data->addrspace_capid, 75 | env_data->uart_address, PGTABLE_ACCESS_RW, 76 | PGTABLE_VM_MEMTYPE_DEVICE_NGNRE); 77 | if (ret != OK) { 78 | (void)printf("UART mapping failed\n"); 79 | exit(1); 80 | } 81 | 82 | uart_address = env_data->uart_address; 83 | g_uart_log_en = true; 84 | } else { 85 | (void)printf("No uart_address configured"); 86 | g_uart_log_en = false; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /platform/qemu/src/uart_qemu.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define UART_BASE 0x9000000U 6 | #define UART_SIZE 0x1000U 7 | #define UART_DR 0x0U 8 | #define UART_TFR 0x18U 9 | -------------------------------------------------------------------------------- /platform/qemu/src/vm_client.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | error_t 26 | platform_config_update_parsed(vm_config_t *vmcfg, vm_config_parser_data_t *data) 27 | { 28 | (void)vmcfg; 29 | (void)data; 30 | return OK; 31 | } 32 | 33 | const char * 34 | platform_get_sign_authority_string(vm_sign_t sign) 35 | { 36 | char *ret = NULL; 37 | 38 | switch (sign) { 39 | case VM_SIGN_INIT: 40 | ret = "N/A"; 41 | break; 42 | case VM_SIGN_UNAUTHORIZED: 43 | ret = "None"; 44 | break; 45 | default: 46 | (void)printf("Error: invalid sign %d\n", sign); 47 | ret = NULL; 48 | break; 49 | } 50 | 51 | return ret; 52 | } 53 | -------------------------------------------------------------------------------- /platform/qemu/src/vm_config.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | error_t 19 | platform_vm_config_create_vdevices(vm_config_t *vmcfg, 20 | vm_config_parser_data_t *data) 21 | { 22 | error_t ret = OK; 23 | 24 | ret = vgic_vm_config_add(vmcfg, data); 25 | if (ret != OK) { 26 | (void)printf("Error: failed to handle virtual GIC\n"); 27 | goto out; 28 | } 29 | 30 | out: 31 | return ret; 32 | } 33 | 34 | error_t 35 | platform_vm_config_hlos_vdevices_setup(vm_config_t *vmcfg) 36 | { 37 | error_t ret = OK; 38 | (void)vmcfg; 39 | 40 | ret = vgic_vm_config_add(vmcfg, NULL); 41 | if (ret != OK) { 42 | (void)printf("Error: failed to handle virtual GIC\n"); 43 | goto out; 44 | } 45 | 46 | out: 47 | return ret; 48 | } 49 | -------------------------------------------------------------------------------- /platform/qemu/src/vm_config_parser.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #pragma clang diagnostic push 17 | #pragma clang diagnostic ignored "-Wzero-length-array" 18 | #pragma clang diagnostic ignored "-Wbad-function-cast" 19 | #pragma clang diagnostic ignored "-Wsign-conversion" 20 | #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" 21 | #pragma clang diagnostic ignored "-Wextra-semi" 22 | #include 23 | #pragma clang diagnostic pop 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | 39 | listener_return_t 40 | platform_parse_vm_config(void *data, void *fdt, int node_ofs, ctx_t *ctx); 41 | 42 | static error_t 43 | parse_segments(vm_config_parser_data_t *vd, void *fdt, int node_ofs); 44 | 45 | rm_error_t 46 | platform_alloc_parser_data(vm_config_parser_data_t *vd) 47 | { 48 | (void)vd; 49 | return RM_OK; 50 | } 51 | 52 | void 53 | platform_free_parser_data(vm_config_parser_data_t *vd) 54 | { 55 | (void)vd; 56 | } 57 | 58 | listener_return_t 59 | platform_parse_vm_config(void *data, void *fdt, int node_ofs, ctx_t *ctx) 60 | { 61 | listener_return_t ret = RET_CLAIMED; 62 | 63 | vm_config_parser_data_t *vd = (vm_config_parser_data_t *)(data); 64 | 65 | error_t segments_ret = parse_segments(vd, fdt, node_ofs); 66 | if (segments_ret != OK) { 67 | ret = RET_ERROR; 68 | goto out; 69 | } 70 | 71 | // put remaining vm_config's platform parsers here! 72 | 73 | out: 74 | if (ret == RET_ERROR) { 75 | vd->platform.primary_vm_index = 0U; 76 | } 77 | 78 | (void)data; 79 | (void)fdt; 80 | (void)node_ofs; 81 | (void)ctx; 82 | return ret; 83 | } 84 | 85 | error_t 86 | parse_segments(vm_config_parser_data_t *vd, void *fdt, int node_ofs) 87 | { 88 | error_t ret = OK; 89 | 90 | int segments_ofs = fdt_subnode_offset(fdt, node_ofs, "segments"); 91 | if (segments_ofs < 0) { 92 | goto out; 93 | } 94 | 95 | if (fdt_getprop_s32(fdt, segments_ofs, "ramdisk", 96 | &vd->platform.ramfs_idx) != OK) { 97 | (void)printf("Warning: ramdisk segment index\n"); 98 | 99 | vd->platform.ramfs_idx = -1; 100 | } 101 | 102 | out: 103 | return ret; 104 | } 105 | -------------------------------------------------------------------------------- /repolint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "https://raw.githubusercontent.com/quic/.github/main/repolint.json", 3 | "rules": { 4 | "source-license-headers-exist": { 5 | "level": "error", 6 | "rule": { 7 | "type": "file-starts-with", 8 | "options": { 9 | "globsAll": [ 10 | "**/*.py", 11 | "**/*.js", 12 | "**/*.c", 13 | "**/*.cc", 14 | "**/*.cpp", 15 | "**/*.h", 16 | "**/*.ts", 17 | "**/*.sh", 18 | "**/*.rs", 19 | "**/*.java", 20 | "**/*.go", 21 | "**/*.bbclass", 22 | "**/*.S" 23 | ], 24 | "skip-paths-matching": { 25 | "patterns": [ 26 | "tools/cpptest/gunyahkw.h", 27 | "tools/misc/convert-utf-8.sh" 28 | ] 29 | }, 30 | "lineCount": 60, 31 | "patterns": [ 32 | "(Copyright|©).*Qualcomm Innovation Center, Inc|Copyright (\\(c\\)|©) (20(1[2-9]|2[0-2])(-|,|\\s)*)+ The Linux Foundation", 33 | "SPDX-License-Identifier|Redistribution and use in source and binary forms, with or without" 34 | ], 35 | "flags": "i" 36 | } 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/assert.c: -------------------------------------------------------------------------------- 1 | // © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | // These debug/production variants are defined differently to optimize calling 10 | // argument setup in the production builds. 11 | #if defined(CONFIG_DEBUG) 12 | _Noreturn void 13 | rm_assert_fail(const char *cond_fail, const char *file, line_number_t line) 14 | { 15 | (void)printf("assert(%s) failed: %s:%d\n", cond_fail, file, line); 16 | 17 | exit(1); 18 | } 19 | #else 20 | _Noreturn void 21 | rm_assert_fail(const char *file, line_number_t line) 22 | { 23 | (void)printf("assert failed: %s:%d\n", file, line); 24 | 25 | exit(1); 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /src/build.conf: -------------------------------------------------------------------------------- 1 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | 5 | source assert.c 6 | source dt/dt_overlay.c 7 | source dt/dto_construct.c 8 | source elf/elf.c 9 | source event/event-isr.c 10 | source exit/exit.c 11 | source guest_interface.c guest_accessors.c guest_hypresult.c 12 | source hyp/memextent.c 13 | source interrupt.c 14 | source irq_manager/irq_manager.c 15 | source memparcel/memparcel.c memparcel/mem_region.c 16 | source preempt/preempt.c 17 | source random.c 18 | source resource-manager.c 19 | source rpc/rm-rpc.c rpc/rm-rpc-msgqueue.c 20 | source rpc/rm-rpc-fifo.c 21 | source uart/uart.c 22 | source utils/address_range_allocator.c utils/range_list.c 23 | source utils/dict.c 24 | source utils/vector.c 25 | source virq.c 26 | source vm_config/vm_config.c 27 | source vm_config/vm_get_resources.c 28 | source vm_config/dtb_parser.c 29 | source vm_config/vm_config_parser.c 30 | source vm_config/vm_config_rtc.c 31 | source vm_console/vm_console_simple.c 32 | source vm_creation/rm_vm.c 33 | source vm_creation/hlos_vm.c 34 | source vm_creation/second_vm.c 35 | source vm_creation/vm_creation.c 36 | source vm_creation/dto_construct.c 37 | source vm_creation/vm_creation_rtc.c 38 | source vm_creation/vm_creation_pv_time.c 39 | source vm_creation/vm_elf.c 40 | source vm_dt/vm_dt.c 41 | source vm_firmware/vm_firmware.c 42 | source vm_mgnt/vm_mgnt.c 43 | source vm_ipa/vm_ipa.c 44 | source vm_passthrough_config/vm_passthrough_config.c 45 | source log.c 46 | source process_env.c 47 | 48 | ldflags -lfdt -Wl,-Bstatic -lqcbor 49 | 50 | configs PAGE_BITS=12U 51 | configs PAGE_SIZE=4096U 52 | -------------------------------------------------------------------------------- /src/dt/dto_construct.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | error_t 16 | dto_construct_begin_path(dto_t *dto, const char *path) 17 | { 18 | error_t ret = OK; 19 | 20 | char *target = strdup(path); 21 | if (target == NULL) { 22 | ret = ERROR_NOMEM; 23 | goto out; 24 | } 25 | 26 | const char separator = '/'; 27 | 28 | assert(target[0] == separator); 29 | 30 | char *name_start = target + 1; 31 | 32 | assert(*name_start != '\0'); 33 | 34 | CHECK_DTO(ret, dto_modify_begin_by_path(dto, "/")); 35 | 36 | char *name_end = NULL; 37 | do { 38 | name_end = strchr(name_start, (int32_t)separator); 39 | if (name_end == NULL) { 40 | break; 41 | } 42 | 43 | *name_end = '\0'; 44 | 45 | ret = dto_node_begin(dto, name_start); 46 | if (ret != OK) { 47 | goto out; 48 | } 49 | 50 | name_start = name_end + 1; 51 | } while (name_end != NULL); 52 | 53 | // the generate should specify a node name 54 | // we can change it to return error latter 55 | assert(*name_start != '\0'); 56 | 57 | // create the last node 58 | ret = dto_node_begin(dto, name_start); 59 | 60 | out: 61 | free(target); 62 | return ret; 63 | } 64 | 65 | error_t 66 | dto_construct_end_path(dto_t *dto, const char *path) 67 | { 68 | error_t ret = OK; 69 | 70 | size_t sz = strlen(path); 71 | 72 | char *target = strdup(path); 73 | if (target == NULL) { 74 | ret = ERROR_NOMEM; 75 | goto out; 76 | } 77 | 78 | const char separator = '/'; 79 | 80 | assert(target[0] == separator); 81 | 82 | // should have a node name 83 | assert(target[sz - 1] != '/'); 84 | 85 | // remove the node name 86 | char *name_start = NULL; 87 | 88 | do { 89 | name_start = strrchr(target, (int32_t)separator); 90 | if (name_start == NULL) { 91 | break; 92 | } 93 | 94 | *name_start = '\0'; 95 | 96 | ret = dto_node_end(dto, &name_start[1]); 97 | if (ret != OK) { 98 | goto out; 99 | } 100 | } while (name_start != NULL); 101 | 102 | CHECK_DTO(ret, dto_modify_end_by_path(dto, "/")); 103 | out: 104 | free(target); 105 | return ret; 106 | } 107 | -------------------------------------------------------------------------------- /src/elf/elf.c: -------------------------------------------------------------------------------- 1 | // © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #define DT_TABLE_MAGIC betoh32(0xd7b7ab1eU) 19 | #define DT_MAGIC betoh32(0xd00dfeedU) 20 | 21 | Elf_Class 22 | elf_get_ehdr_class(Elf_Ehdr_ptr ehdr) 23 | { 24 | assert(ehdr.ehdr32 != NULL); 25 | 26 | return ehdr.ehdr32->e_ident[EI_CLASS]; 27 | } 28 | 29 | size_t 30 | elf_ehdr_size(Elf_Ehdr_ptr ehdr) 31 | { 32 | return (elf_get_ehdr_class(ehdr) == ELF_CLASS_32) ? sizeof(Elf32_Ehdr) 33 | : sizeof(Elf64_Ehdr); 34 | } 35 | 36 | static size_t 37 | elf_get_phdr_size(Elf_Ehdr_ptr ehdr) 38 | { 39 | return (elf_get_ehdr_class(ehdr) == ELF_CLASS_32) ? sizeof(Elf32_Phdr) 40 | : sizeof(Elf64_Phdr); 41 | } 42 | 43 | bool 44 | elf_ehdr_is_class(Elf_Ehdr_ptr ehdr, Elf_Class class) 45 | { 46 | return (elf_get_ehdr_class(ehdr) == class); 47 | } 48 | 49 | bool 50 | elf_ehdr_valid(Elf_Ehdr_ptr ehdr) 51 | { 52 | bool valid = false; 53 | 54 | // Flush the max header size (ELF64) 55 | cache_flush_by_va(ehdr.ehdr64, sizeof(Elf64_Ehdr)); 56 | 57 | // Validate the ELF image 58 | if ((memcmp((const Elf_Ident *)EI_MAG_STR, 59 | elf_get_ehdr_field(ehdr, e_ident), EI_MAG_SIZE) == 0) && 60 | (elf_ehdr_is_class(ehdr, ELF_CLASS_32) || 61 | elf_ehdr_is_class(ehdr, ELF_CLASS_64)) && 62 | (elf_get_ehdr_field(ehdr, e_ident[EI_DATA]) == ELF_DATA_2LSB) && 63 | (elf_get_ehdr_field(ehdr, e_ident[EI_VERSION]) == EV_CURRENT) && 64 | (elf_get_ehdr_field(ehdr, e_ident[EI_OSABI]) == 0U) && 65 | (elf_get_ehdr_field(ehdr, e_ident[EI_ABIVERSION]) == 0U) && 66 | (elf_get_ehdr_field(ehdr, e_phentsize) == 67 | elf_get_phdr_size(ehdr))) { 68 | valid = true; 69 | } else { 70 | (void)printf("Error: unexpected value in ehdr\n"); 71 | } 72 | 73 | return valid; 74 | } 75 | 76 | rm_error_t 77 | elf_get_phdr_offset(Elf_Ehdr_ptr ehdr, size_t image_size, size_t *offset) 78 | { 79 | rm_error_t rm_err = RM_ERROR_ARGUMENT_INVALID; 80 | 81 | size_t e_phoff = elf_get_ehdr_field(ehdr, e_phoff); 82 | size_t e_phentsize = elf_get_ehdr_field(ehdr, e_phentsize); 83 | count_t e_phnum = elf_get_ehdr_field(ehdr, e_phnum); 84 | 85 | // The e_phoff field is relative to the ehdr. We require that the phdrs 86 | // are copied along with the ehdr as a single block. A real ELF file is 87 | // not guaranteed to have them close together, so the loader may need to 88 | // move the phdrs closer and adjust e_phoff. 89 | if (util_mult_integer_overflows(e_phentsize, e_phnum) || 90 | util_add_overflows(e_phoff, e_phentsize * e_phnum) || 91 | (image_size < (e_phoff + (e_phentsize * e_phnum)))) { 92 | (void)printf("Error: phdr size or location is out of range\n"); 93 | } else { 94 | *offset = e_phoff; 95 | rm_err = RM_OK; 96 | } 97 | 98 | return rm_err; 99 | } 100 | 101 | bool 102 | elf_segment_is_loadable(Elf_Class class, Elf_Phdr_ptr phdrs, index_t seg_num) 103 | { 104 | return elf_get_phdr_field(class, phdrs, seg_num, p_type) == PT_LOAD; 105 | } 106 | 107 | bool 108 | elf_segment_is_relocatable(Elf_Class class, Elf_Phdr_ptr phdrs, index_t seg_num) 109 | { 110 | return (elf_get_phdr_field(class, phdrs, seg_num, p_flags) & 111 | PF_QCOM_RELOCATABLE) != 0U; 112 | } 113 | 114 | bool 115 | elf_valid_ptload_segment(index_t seg_num, size_t p_memsz, size_t segment_offset, 116 | index_t segment_count, 117 | const boot_env_phys_range_t *vm_segments, 118 | vmaddr_t mem_size) 119 | { 120 | bool valid = false; 121 | 122 | // Check that the segment is within the image memparcel. 123 | if (util_add_overflows(p_memsz, segment_offset) || 124 | ((p_memsz + segment_offset) > mem_size)) { 125 | (void)printf("Error: phdr %d is outside image memparcel\n", 126 | seg_num); 127 | goto out; 128 | } 129 | 130 | // Check for overlapping segments 131 | for (index_t s = 0; s < segment_count; s++) { 132 | paddr_t s_base = vm_segments[s].base; 133 | size_t s_size = vm_segments[s].size; 134 | if (((segment_offset < s_base) && 135 | ((segment_offset + p_memsz) > s_base)) || 136 | ((segment_offset >= s_base) && 137 | (segment_offset < (s_base + s_size)))) { 138 | (void)printf("Error: phdr %d is overlapping phdr %d\n", 139 | seg_num, s); 140 | goto out; 141 | } 142 | } 143 | 144 | valid = true; 145 | 146 | out: 147 | return valid; 148 | } 149 | 150 | bool 151 | elf_segment_contains_dt(const uint32_t *first_word, bool *single_dtb) 152 | { 153 | bool found = false; 154 | 155 | if (*first_word == DT_TABLE_MAGIC) { 156 | *single_dtb = false; 157 | found = true; 158 | } else if (*first_word == DT_MAGIC) { 159 | *single_dtb = true; 160 | found = true; 161 | } else { 162 | // no DTB segment found 163 | } 164 | 165 | return found; 166 | } 167 | -------------------------------------------------------------------------------- /src/event/event-epoll.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define MAX_EVENTS 5 22 | 23 | #define NS_PER_MS 1000000 24 | 25 | #pragma clang diagnostic push 26 | #pragma clang diagnostic ignored "-Wpadded" 27 | 28 | struct event_data_s { 29 | int epoll_fd; 30 | event_t *head; 31 | event_t *tail; 32 | bool exit_loop; 33 | bool initialised; 34 | }; 35 | 36 | #pragma clang diagnostic pop 37 | 38 | static struct event_data_s event_data; 39 | 40 | error_t 41 | event_init(void) 42 | { 43 | if (!event_data.initialised) { 44 | int epoll_fd = epoll_create1(0); 45 | assert(epoll_fd >= 0); 46 | 47 | event_data.epoll_fd = epoll_fd; 48 | event_data.exit_loop = false; 49 | event_data.initialised = true; 50 | } 51 | 52 | return OK; 53 | } 54 | 55 | error_t 56 | event_register(event_t *event, event_callback_t callback, void *data) 57 | { 58 | assert(event != NULL); 59 | 60 | event->next = NULL; 61 | event->prev = NULL; 62 | event->callback = callback; 63 | event->data = data; 64 | event->fd = -1; 65 | event->pending = false; 66 | 67 | return OK; 68 | } 69 | 70 | bool 71 | event_deregister(event_t *event) 72 | { 73 | bool was_pending = event->pending; 74 | 75 | if (was_pending) { 76 | event_t *next = event->next; 77 | event_t *prev = event->prev; 78 | 79 | if (next != NULL) { 80 | next->prev = prev; 81 | } else { 82 | event_data.tail = prev; 83 | } 84 | 85 | if (prev != NULL) { 86 | prev->next = next; 87 | } else { 88 | event_data.head = next; 89 | } 90 | 91 | event->next = NULL; 92 | event->prev = NULL; 93 | event->pending = false; 94 | } 95 | 96 | if (event->fd != -1) { 97 | int ret = epoll_ctl(event_data.epoll_fd, EPOLL_CTL_DEL, 98 | event->fd, NULL); 99 | assert(ret == 0); 100 | event->fd = -1; 101 | } 102 | 103 | return was_pending; 104 | } 105 | 106 | error_t 107 | event_set_fd_trigger(event_t *event, int fd, int flags) 108 | { 109 | assert(event != NULL); 110 | 111 | if (event->fd != -1) { 112 | return ERROR_BUSY; 113 | } 114 | 115 | struct epoll_event ee; 116 | 117 | ee.data.ptr = (void *)event; 118 | ee.events = EPOLLET; 119 | if (flags & EVENT_FD_READ) { 120 | ee.events |= EPOLLIN; 121 | } 122 | if (flags & EVENT_FD_WRITE) { 123 | ee.events |= EPOLLOUT; 124 | } 125 | 126 | int ret = epoll_ctl(event_data.epoll_fd, EPOLL_CTL_ADD, fd, &ee); 127 | 128 | if (ret == 0) { 129 | event->fd = fd; 130 | } 131 | 132 | return (error_t)ret; 133 | } 134 | 135 | static bool 136 | add_event_to_pending_list(event_t *event) 137 | { 138 | event_t **tail = &event_data.tail; 139 | bool was_pending = event->pending; 140 | 141 | if (!was_pending) { 142 | if (*tail != NULL) { 143 | (*tail)->next = event; 144 | } else { 145 | event_data.head = event; 146 | } 147 | 148 | event->prev = *tail; 149 | *tail = event; 150 | event->pending = true; 151 | } 152 | 153 | return was_pending; 154 | } 155 | 156 | static event_t * 157 | get_next_pending_event(void) 158 | { 159 | event_t **head = &event_data.head; 160 | event_t *ev; 161 | 162 | assert(*head != NULL); 163 | 164 | ev = *head; 165 | *head = ev->next; 166 | ev->next = NULL; 167 | 168 | if (*head != NULL) { 169 | (*head)->prev = NULL; 170 | } else { 171 | event_data.tail = NULL; 172 | } 173 | 174 | return ev; 175 | } 176 | 177 | static int 178 | do_epoll_wait(int timeout) 179 | { 180 | struct epoll_event ee[MAX_EVENTS]; 181 | int ret, total = 0; 182 | 183 | do { 184 | ret = epoll_wait(event_data.epoll_fd, ee, MAX_EVENTS, 185 | timeout / NS_PER_MS); 186 | if (ret < 0) { 187 | assert(errno == EINTR); 188 | continue; 189 | } 190 | 191 | for (int i = 0; i < ret; i++) { 192 | event_t *event = (event_t *)ee[i].data.ptr; 193 | // FIXME: ignore EPOLLHUP in Linux hosted test case 194 | if ((ee[i].events & ~(unsigned)EPOLLHUP) != 0U) { 195 | (void)add_event_to_pending_list(event); 196 | } 197 | } 198 | 199 | total += ret; 200 | timeout = 0; 201 | } while (ret == MAX_EVENTS); 202 | 203 | return total; 204 | } 205 | 206 | bool 207 | event_is_pending(void) 208 | { 209 | (void)do_epoll_wait(0); 210 | return (event_data.head != NULL); 211 | } 212 | 213 | bool 214 | event_wait_pending(int timeout) 215 | { 216 | int ret = do_epoll_wait(timeout); 217 | 218 | return (ret > 0); 219 | } 220 | 221 | static void 222 | flush_pending_list(void) 223 | { 224 | while (event_data.head != NULL) { 225 | event_t *ev = get_next_pending_event(); 226 | ev->pending = false; 227 | ev->callback(ev, ev->data); 228 | } 229 | } 230 | 231 | void 232 | event_flush_pending(void) 233 | { 234 | (void)do_epoll_wait(0); 235 | flush_pending_list(); 236 | } 237 | 238 | static void 239 | event_loop_common(int timeout) 240 | { 241 | event_data.exit_loop = false; 242 | 243 | for (;;) { 244 | flush_pending_list(); 245 | 246 | if (event_data.exit_loop) { 247 | break; 248 | } 249 | 250 | int ret = do_epoll_wait(timeout); 251 | if (ret == 0) { 252 | // FIXME: 253 | // Implement PSCI CPU suspend call 254 | (void)do_epoll_wait(-1); 255 | } 256 | } 257 | } 258 | 259 | void 260 | event_loop_enter(void) 261 | { 262 | event_loop_common(-1); 263 | } 264 | 265 | void 266 | event_loop_enter_suspend(int timeout) 267 | { 268 | event_loop_common(timeout); 269 | } 270 | 271 | void 272 | event_loop_exit(void) 273 | { 274 | event_data.exit_loop = true; 275 | } 276 | 277 | bool 278 | event_trigger(event_t *event) 279 | { 280 | return add_event_to_pending_list(event); 281 | } 282 | -------------------------------------------------------------------------------- /src/event/event-isr.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define NS_PER_S 1000000000 20 | 21 | #pragma clang diagnostic push 22 | #pragma clang diagnostic ignored "-Wpadded" 23 | 24 | struct event_data_s { 25 | event_t *head; 26 | event_t *tail; 27 | bool exit_loop; 28 | }; 29 | 30 | #pragma clang diagnostic pop 31 | 32 | static struct event_data_s event_data; 33 | 34 | error_t 35 | event_init(void) 36 | { 37 | return OK; 38 | } 39 | 40 | static void 41 | flush_pending_list(void) 42 | { 43 | assert_preempt_disabled(); 44 | 45 | while (event_data.head != NULL) { 46 | event_t *ev = event_data.head; 47 | event_t *next = ev->next; 48 | 49 | assert(ev->prev == NULL); 50 | 51 | event_data.head = next; 52 | 53 | if (next != NULL) { 54 | next->prev = NULL; 55 | } else { 56 | event_data.tail = NULL; 57 | } 58 | 59 | ev->next = NULL; 60 | ev->pending = false; 61 | 62 | event_callback_t cb = ev->callback; 63 | void *data = ev->data; 64 | 65 | preempt_enable(); 66 | cb(ev, data); 67 | preempt_disable(); 68 | } 69 | } 70 | 71 | static bool 72 | do_event_wait(int32_t timeout) 73 | { 74 | assert_preempt_disabled(); 75 | 76 | int32_t ret; 77 | 78 | do { 79 | if (timeout > 0) { 80 | struct timespec ts = { 81 | .tv_sec = (int64_t)timeout / NS_PER_S, 82 | .tv_nsec = (int64_t)timeout % NS_PER_S, 83 | }; 84 | ret = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL); 85 | } else if (timeout < 0) { 86 | ret = pause(); 87 | } else { 88 | break; 89 | } 90 | 91 | // If we were interrupted but no event 92 | // was triggered, retry the wait. 93 | } while ((event_data.head == NULL) && (ret == -EINTR)); 94 | 95 | return event_data.head != NULL; 96 | } 97 | 98 | static void 99 | event_loop_common(int32_t timeout) 100 | { 101 | preempt_disable(); 102 | 103 | event_data.exit_loop = false; 104 | 105 | for (;;) { 106 | flush_pending_list(); 107 | 108 | if (event_data.exit_loop) { 109 | break; 110 | } 111 | 112 | if (!do_event_wait(timeout)) { 113 | // FIXME: 114 | // Implement PSCI CPU suspend call 115 | (void)do_event_wait(-1); 116 | } 117 | } 118 | 119 | preempt_enable(); 120 | } 121 | 122 | void 123 | event_loop_enter(void) 124 | { 125 | event_loop_common(-1); 126 | } 127 | 128 | void 129 | event_loop_enter_suspend(int32_t timeout) 130 | { 131 | event_loop_common(timeout); 132 | } 133 | 134 | void 135 | event_loop_exit(void) 136 | { 137 | preempt_disable(); 138 | event_data.exit_loop = true; 139 | preempt_enable(); 140 | } 141 | 142 | bool 143 | event_is_pending(void) 144 | { 145 | bool pending; 146 | 147 | preempt_disable(); 148 | pending = event_data.head != NULL; 149 | preempt_enable(); 150 | 151 | return pending; 152 | } 153 | 154 | void 155 | event_flush_pending(void) 156 | { 157 | preempt_disable(); 158 | flush_pending_list(); 159 | preempt_enable(); 160 | } 161 | 162 | bool 163 | event_wait_pending(int32_t timeout) 164 | { 165 | bool pending; 166 | 167 | preempt_disable(); 168 | pending = (event_data.head != NULL) || do_event_wait(timeout); 169 | preempt_enable(); 170 | 171 | return pending; 172 | } 173 | 174 | bool 175 | event_is_registered(event_t *event) 176 | { 177 | return (event->callback != NULL); 178 | } 179 | 180 | error_t 181 | event_register(event_t *event, event_callback_t callback, void *data) 182 | { 183 | assert(event != NULL); 184 | assert(callback != NULL); 185 | 186 | event->next = NULL; 187 | event->prev = NULL; 188 | event->callback = callback; 189 | event->data = data; 190 | event->pending = false; 191 | event->fd = -1; 192 | 193 | return OK; 194 | } 195 | 196 | error_t 197 | event_set_fd_trigger(event_t *event, int fd, int flags) 198 | { 199 | (void)event; 200 | (void)fd; 201 | (void)flags; 202 | 203 | return ERROR_UNIMPLEMENTED; 204 | } 205 | 206 | bool 207 | event_deregister(event_t *event) 208 | { 209 | preempt_disable(); 210 | 211 | bool was_pending = event->pending; 212 | 213 | if (was_pending) { 214 | event_t *next = event->next; 215 | event_t *prev = event->prev; 216 | 217 | if (next != NULL) { 218 | next->prev = prev; 219 | } else { 220 | event_data.tail = prev; 221 | } 222 | 223 | if (prev != NULL) { 224 | prev->next = next; 225 | } else { 226 | event_data.head = next; 227 | } 228 | 229 | event->next = NULL; 230 | event->prev = NULL; 231 | event->pending = false; 232 | } 233 | 234 | preempt_enable(); 235 | 236 | event->callback = NULL; 237 | event->data = NULL; 238 | event->fd = -1; 239 | 240 | return was_pending; 241 | } 242 | 243 | bool 244 | event_trigger(event_t *event) 245 | { 246 | preempt_disable(); 247 | 248 | bool was_pending = event->pending; 249 | 250 | if (!was_pending) { 251 | event_t *tail = event_data.tail; 252 | 253 | if (tail != NULL) { 254 | tail->next = event; 255 | } else { 256 | event_data.head = event; 257 | } 258 | 259 | event->prev = tail; 260 | event_data.tail = event; 261 | event->pending = true; 262 | } 263 | 264 | preempt_enable(); 265 | 266 | return was_pending; 267 | } 268 | -------------------------------------------------------------------------------- /src/exit/exit.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | rm_error_t 23 | register_exit(void) 24 | { 25 | const char *dev = "/dev/exit"; 26 | 27 | rm_error_t error = RM_OK; 28 | 29 | int fd = open(dev, O_RDONLY); 30 | if (fd == -1) { 31 | error = RM_ERROR_DENIED; 32 | goto err; 33 | } 34 | 35 | struct register_exit_req req_register_exit = { 36 | .exit_func = platform_exit_handler, 37 | }; 38 | int ret = ioctl(fd, (int)IOCTL_REGISTER_EXIT, 39 | (uint64_t)&req_register_exit); 40 | if (ret != 0) { 41 | error = RM_ERROR_DENIED; 42 | } 43 | 44 | (void)close(fd); 45 | 46 | err: 47 | return error; 48 | } 49 | 50 | rm_error_t 51 | deregister_exit(void) 52 | { 53 | const char *dev = "/dev/exit"; 54 | 55 | rm_error_t error = RM_OK; 56 | 57 | int fd = open(dev, O_RDWR); 58 | if (fd == -1) { 59 | error = RM_ERROR_DENIED; 60 | goto err; 61 | } 62 | 63 | int ret = ioctl(fd, (int)IOCTL_DEREGISTER_EXIT, 0); 64 | if (ret != 0) { 65 | error = RM_ERROR_DENIED; 66 | } 67 | 68 | (void)close(fd); 69 | 70 | err: 71 | return error; 72 | } 73 | 74 | noreturn void 75 | panic(const char *msg) 76 | { 77 | (void)printf("panic: %s\n", msg); 78 | exit(1); 79 | } 80 | -------------------------------------------------------------------------------- /src/interrupt.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | rm_error_t 28 | register_isr(virq_t virq, int32_t trigger, isr_t isr, void *data) 29 | { 30 | const char *dev = "/dev/gicv3"; 31 | 32 | rm_error_t e = RM_OK; 33 | // simple solution to open it multiple times 34 | int fd = open(dev, O_RDWR); 35 | if (fd == -1) { 36 | e = RM_ERROR_DENIED; 37 | goto err; 38 | } 39 | 40 | struct irq_set_trigger_req req_set_trigger = { 41 | .irq = (int32_t)virq, 42 | .trigger = trigger, 43 | }; 44 | 45 | int ret = 0; 46 | ret = ioctl(fd, (int)IOCTL_SET_IRQ_TRIGGER, (uint64_t)&req_set_trigger); 47 | if (ret != 0) { 48 | e = RM_ERROR_DENIED; 49 | goto err1; 50 | } 51 | 52 | struct register_isr_req req_register_isr = { 53 | .isr = isr, 54 | .irq = (int32_t)virq, 55 | .data = data, 56 | }; 57 | 58 | ret = ioctl(fd, (int)IOCTL_REGISTER_ISR, (uint64_t)&req_register_isr); 59 | if (ret != 0) { 60 | e = RM_ERROR_DENIED; 61 | goto err1; 62 | } 63 | 64 | ret = ioctl(fd, (int)IOCTL_ENABLE_IRQ, (uint64_t)&virq); 65 | if (ret != 0) { 66 | e = RM_ERROR_DENIED; 67 | } 68 | 69 | err1: 70 | (void)close(fd); 71 | err: 72 | return e; 73 | } 74 | 75 | static bool 76 | isr_simple(int32_t virq_num, void *data) 77 | { 78 | bool ret = false; 79 | 80 | (void)virq_num; 81 | 82 | event_t *event = (event_t *)data; 83 | if (event == NULL) { 84 | goto out; 85 | } 86 | 87 | (void)event_trigger(event); 88 | ret = true; 89 | 90 | out: 91 | return ret; 92 | } 93 | 94 | rm_error_t 95 | register_event_isr(virq_t virq, event_t *event) 96 | { 97 | rm_error_t e = RM_OK; 98 | 99 | e = register_isr(virq, IRQ_TRIGGER_EDGE_RISING, isr_simple, 100 | (void *)event); 101 | 102 | return e; 103 | } 104 | 105 | rm_error_t 106 | deregister_isr(virq_t virq) 107 | { 108 | const char *dev = "/dev/gicv3"; 109 | 110 | rm_error_t e = RM_OK; 111 | 112 | // simple solution to open it multiple times 113 | int fd = open(dev, O_RDWR); 114 | if (fd == -1) { 115 | e = RM_ERROR_DENIED; 116 | goto err; 117 | } 118 | 119 | int ret = ioctl(fd, (int)IOCTL_DISABLE_IRQ, (uint64_t)&virq); 120 | if (ret != 0) { 121 | e = RM_ERROR_DENIED; 122 | } 123 | 124 | ret = ioctl(fd, (int)IOCTL_DEREGISTER_ISR, (uint64_t)&virq); 125 | if (ret != 0) { 126 | e = RM_ERROR_DENIED; 127 | } 128 | 129 | (void)close(fd); 130 | err: 131 | return e; 132 | } 133 | -------------------------------------------------------------------------------- /src/log.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #define TIOCSETBUF 0x547f // Non-standard IOCTL!! 33 | 34 | #if ((LOG_AREA_ALIGN - 1) & LOG_AREA_ALIGN) != 0 35 | #error LOG_AREA_ALIGN must be a power of 2 36 | #endif 37 | 38 | // Our non-standard buffer control message 39 | struct tty_set_buffer_req { 40 | uintptr_t buffer; 41 | size_t size; 42 | }; 43 | 44 | static char *rm_log_area; 45 | 46 | rm_error_t 47 | log_reconfigure(uintptr_t *log_buf, size_t size) 48 | { 49 | rm_error_t ret = RM_OK; 50 | 51 | assert(log_buf != NULL); 52 | assert(size >= 256); 53 | 54 | // Allocate a new buffer 55 | rm_log_area = aligned_alloc(LOG_AREA_ALIGN, size); 56 | if (rm_log_area != NULL) { 57 | (void)memset(rm_log_area, 0, size); 58 | 59 | struct tty_set_buffer_req req = { (uintptr_t)rm_log_area, 60 | size }; 61 | 62 | int result = 63 | ioctl(STDOUT_FILENO, TIOCSETBUF, (unsigned long)&req); 64 | if (result != 0) { 65 | ret = RM_ERROR_NORESOURCE; 66 | } 67 | 68 | *log_buf = (uintptr_t)rm_log_area; 69 | } 70 | 71 | return ret; 72 | } 73 | 74 | rm_error_t 75 | log_expose_to_hlos(uintptr_t log_buf, size_t size) 76 | { 77 | rm_error_t ret = RM_OK; 78 | 79 | assert(size >= 256); 80 | 81 | // need size aligned to page size for map 82 | assert(util_is_baligned(size, PAGE_SIZE)); 83 | 84 | vm_t *hlos = vm_lookup(VMID_HLOS); 85 | assert(hlos != NULL); 86 | 87 | paddr_t paddr = rm_ipa_to_pa(log_buf); 88 | 89 | // assume it's always 1:1 mapping 90 | assert(paddr == log_buf); 91 | vmaddr_t ipa = paddr; 92 | 93 | vm_address_range_result_t as_ret = 94 | vm_address_range_alloc(hlos, VM_MEMUSE_BOOTINFO, ipa, paddr, 95 | size, ADDRESS_RANGE_NO_ALIGNMENT); 96 | if (as_ret.err != OK) { 97 | ret = RM_ERROR_DENIED; 98 | goto out; 99 | } 100 | 101 | size_t offset = log_buf - rm_get_me_ipa_base(); 102 | 103 | cap_id_result_t cap_ret = vm_memory_create_and_map( 104 | hlos, VM_MEMUSE_BOOTINFO, rm_get_me(), offset, size, ipa, 105 | MEMEXTENT_MEMTYPE_ANY, PGTABLE_ACCESS_R, 106 | PGTABLE_VM_MEMTYPE_NORMAL_WB); 107 | if (cap_ret.e != OK) { 108 | error_t err = vm_address_range_free(hlos, VM_MEMUSE_BOOTINFO, 109 | ipa, size); 110 | assert(err == OK); 111 | ret = RM_ERROR_DENIED; 112 | goto out; 113 | } 114 | 115 | out: 116 | return ret; 117 | } 118 | -------------------------------------------------------------------------------- /src/preempt/preempt.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | // FIXME: 17 | static uint32_t preempt_disable_count; 18 | 19 | void 20 | preempt_disable(void) 21 | { 22 | asm_interrupt_disable_acquire(&preempt_disable_count); 23 | preempt_disable_count++; 24 | assert_preempt_disabled(); 25 | } 26 | 27 | void 28 | preempt_enable(void) 29 | { 30 | assert_preempt_disabled(); 31 | preempt_disable_count--; 32 | if (preempt_disable_count == 0U) { 33 | asm_interrupt_enable_release(&preempt_disable_count); 34 | } 35 | } 36 | 37 | void 38 | assert_preempt_disabled(void) 39 | { 40 | assert(preempt_disable_count != 0U); 41 | } 42 | 43 | void 44 | assert_preempt_enabled(void) 45 | { 46 | assert(preempt_disable_count == 0U); 47 | } 48 | -------------------------------------------------------------------------------- /src/random.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | uint64_result_t 16 | random_get_entropy64(void) 17 | { 18 | uint64_result_t ret = { .e = ERROR_UNIMPLEMENTED }; 19 | 20 | if (hyp_api_flags0_get_prng(&hyp_id.api_flags_0)) { 21 | gunyah_hyp_prng_get_entropy_result_t prng; 22 | do { 23 | prng = gunyah_hyp_prng_get_entropy( 24 | (count_t)sizeof(uint32_t) * 2U); 25 | } while (prng.error == ERROR_BUSY); 26 | 27 | ret.e = prng.error; 28 | if (ret.e == OK) { 29 | ret.r = (uint64_t)prng.data0; 30 | ret.r |= (uint64_t)prng.data1 << 32; 31 | } 32 | } 33 | 34 | return ret; 35 | } 36 | -------------------------------------------------------------------------------- /src/rpc/rm-rpc-internal.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #pragma clang diagnostic push 6 | #pragma clang diagnostic ignored "-Wpadded" 7 | 8 | typedef struct { 9 | uint32_t msg_id; 10 | uint16_t seq_num; 11 | uint8_t num_fragments; 12 | uint8_t msg_type; 13 | uint8_t *buf; 14 | size_t len; 15 | size_t pos; 16 | size_t rem; 17 | } rm_rpc_tx_data_t; 18 | 19 | typedef struct { 20 | bool partial; 21 | uint32_t msg_id; 22 | uint16_t seq_num; 23 | uint8_t msg_type; 24 | uint8_t num_fragments; 25 | uint8_t rem_fragments; 26 | uint8_t *buf; 27 | size_t len; 28 | size_t alloc_size; 29 | } rm_rpc_rx_data_t; 30 | 31 | #pragma clang diagnostic pop 32 | 33 | // App Layer 34 | void 35 | rm_rpc_init_rx_data(vmid_t vm_id, rm_rpc_rx_data_t *rx_data); 36 | 37 | void 38 | rm_rpc_init_tx_data(vmid_t vm_id, rm_rpc_tx_data_t *tx_data); 39 | 40 | void 41 | rm_rpc_tx_callback(vmid_t vm_id, rm_rpc_tx_data_t *tx_data); 42 | 43 | void 44 | rm_rpc_rx_callback(vmid_t vm_id, rm_rpc_rx_data_t *rx_data); 45 | 46 | // Transport Layer 47 | rm_error_t 48 | rm_rpc_init_server_transport(vmid_t my_id); 49 | 50 | rm_rpc_rx_data_t * 51 | rm_rpc_get_rx_data(vmid_t vm_id); 52 | 53 | rm_rpc_tx_data_t * 54 | rm_rpc_get_tx_data(vmid_t vm_id); 55 | 56 | rm_error_t 57 | rm_rpc_send_packet(rm_rpc_tx_data_t *tx, void *buf, size_t len); 58 | 59 | rm_error_t 60 | rm_rpc_recv_packet(rm_rpc_rx_data_t *rx, void *buf, size_t *len); 61 | -------------------------------------------------------------------------------- /src/uart/uart.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | static bool uart_registered; 21 | 22 | rm_error_t 23 | register_uart(void) 24 | { 25 | const char *dev = "/dev/console"; 26 | const char *banner = "[RM]"; 27 | 28 | rm_error_t e = RM_OK; 29 | 30 | if (uart_registered || platform_get_security_state()) { 31 | goto err; 32 | } 33 | 34 | // simple solution to open it multiple times 35 | int fd = open(dev, O_RDWR); 36 | if (fd == -1) { 37 | e = RM_ERROR_DENIED; 38 | goto err; 39 | } 40 | 41 | int ret = 0; 42 | 43 | struct register_console_req req_register_console = { 44 | .console = uart_write, 45 | }; 46 | 47 | ret = ioctl(fd, (int)IOCTL_REGISTER_CONSOLE, 48 | (uint64_t)&req_register_console); 49 | if (ret != 0) { 50 | e = RM_ERROR_DENIED; 51 | goto err1; 52 | } 53 | 54 | ret = ioctl(fd, (int)IOCTL_SET_PREFIX_CONSOLE, banner); 55 | if (ret != 0) { 56 | e = RM_ERROR_DENIED; 57 | goto err1; 58 | } 59 | 60 | uart_registered = true; 61 | 62 | err1: 63 | (void)close(fd); 64 | err: 65 | return e; 66 | } 67 | 68 | rm_error_t 69 | deregister_uart(void) 70 | { 71 | const char *dev = "/dev/console"; 72 | 73 | rm_error_t e = RM_OK; 74 | 75 | if (!uart_registered) { 76 | goto err; 77 | } 78 | 79 | // simple solution to open it multiple times 80 | int fd = open(dev, O_RDWR); 81 | if (fd == -1) { 82 | e = RM_ERROR_DENIED; 83 | goto err; 84 | } 85 | 86 | int ret = ioctl(fd, (int)IOCTL_DEREGISTER_CONSOLE, 0); 87 | if (ret != 0) { 88 | e = RM_ERROR_DENIED; 89 | } 90 | 91 | uart_registered = false; 92 | 93 | (void)close(fd); 94 | err: 95 | return e; 96 | } 97 | -------------------------------------------------------------------------------- /src/utils/circular_buf.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | struct cbuf { 16 | size_t capacity; 17 | 18 | // the index we can start reading 19 | index_t read_idx; 20 | // the index we can start writing 21 | index_t write_idx; 22 | 23 | uint8_t *data; 24 | }; 25 | 26 | cbuf_t * 27 | cbuf_init(size_t capacity) 28 | { 29 | cbuf_t *ret = malloc(sizeof(*ret)); 30 | if (ret == NULL) { 31 | goto err; 32 | } 33 | 34 | ret->capacity = capacity; 35 | 36 | ret->read_idx = 0U; 37 | ret->write_idx = 0U; 38 | 39 | ret->data = malloc(capacity); 40 | if (ret->data == NULL) { 41 | goto err1; 42 | } 43 | 44 | return ret; 45 | err1: 46 | free(ret); 47 | err: 48 | return NULL; 49 | } 50 | 51 | size_t 52 | cbuf_write(cbuf_t *cbuf, const void *data, size_t data_len) 53 | { 54 | const uint8_t *start = (const uint8_t *)data; 55 | size_t write_len = data_len; 56 | 57 | // check if whole buffer fits the data 58 | // NOTE: only writes the part which would not be overwriten. Check if 59 | // it's expected behavior. 60 | if (write_len > cbuf->capacity) { 61 | // if not, adjust data and write_len 62 | size_t offset = write_len - cbuf->capacity; 63 | start += offset; 64 | write_len = cbuf->capacity; 65 | } 66 | 67 | // check if overwrite occurs 68 | size_t remaining_sz = 69 | cbuf->read_idx < cbuf->write_idx 70 | ? cbuf->capacity - (cbuf->write_idx - cbuf->read_idx) 71 | : cbuf->read_idx - cbuf->write_idx; 72 | // if so, mark it, set read idx after write_idx + 1 before return 73 | bool overwriten = remaining_sz < write_len; 74 | 75 | // check if remaining space (to the end of buf) fits the data 76 | size_t sz_to_buf_end = cbuf->capacity - cbuf->write_idx; 77 | if (sz_to_buf_end >= write_len) { 78 | // if so, write to the remaining space 79 | memcpy(cbuf->data + cbuf->write_idx, start, write_len); 80 | 81 | cbuf->write_idx += write_len; 82 | } else { 83 | // if not, write first part to the remaining space 84 | memcpy(cbuf->data + cbuf->write_idx, start, sz_to_buf_end); 85 | 86 | // write the second part to the wrap space 87 | size_t rest = write_len - sz_to_buf_end; 88 | memcpy(cbuf->data, start + sz_to_buf_end, rest); 89 | 90 | cbuf->write_idx = (index_t)rest; 91 | } 92 | 93 | // set read idx base on if overwrite 94 | if (overwriten) { 95 | cbuf->read_idx = cbuf->write_idx; 96 | } 97 | 98 | return write_len; 99 | } 100 | 101 | size_t 102 | cbuf_read(cbuf_t *cbuf, void *output, size_t output_len) 103 | { 104 | uint8_t *start = (uint8_t *)output; 105 | size_t read_len = output_len; 106 | 107 | // check if need output more than the size of content in buf 108 | size_t content_sz = cbuf_used(cbuf); 109 | // NOTE: can only reads no more than existing bytes. 110 | if (read_len > content_sz) { 111 | read_len = content_sz; 112 | } 113 | 114 | // check if need to wrap the buffer 115 | size_t sz_to_buf_end = cbuf->capacity - cbuf->read_idx; 116 | if (sz_to_buf_end >= read_len) { 117 | // if not, read to buffer 118 | memcpy(output, start + cbuf->read_idx, read_len); 119 | 120 | cbuf->read_idx += read_len; 121 | } else { 122 | // if so, read the fist part to the end of the buf 123 | memcpy(start, cbuf->data + cbuf->read_idx, sz_to_buf_end); 124 | 125 | // read the seconf part from the start of the buf 126 | size_t rest = read_len - sz_to_buf_end; 127 | memcpy(start + sz_to_buf_end, cbuf->data, rest); 128 | 129 | cbuf->read_idx = (index_t)rest; 130 | } 131 | 132 | return read_len; 133 | } 134 | 135 | size_t 136 | cbuf_used(cbuf_t *cbuf) 137 | { 138 | return cbuf->read_idx < cbuf->write_idx 139 | ? cbuf->write_idx - cbuf->read_idx 140 | : cbuf->capacity - (cbuf->read_idx - cbuf->write_idx); 141 | } 142 | 143 | size_t 144 | cbuf_available(cbuf_t *cbuf) 145 | { 146 | return cbuf->capacity - cbuf_used(cbuf); 147 | } 148 | 149 | void 150 | cbuf_deinit(cbuf_t *cbuf) 151 | { 152 | if (cbuf->data != NULL) { 153 | free(cbuf->data); 154 | } 155 | 156 | free(cbuf); 157 | } 158 | -------------------------------------------------------------------------------- /src/virq.c: -------------------------------------------------------------------------------- 1 | // © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | bool 12 | virq_is_valid(interrupt_data_t virq) 13 | { 14 | return virq.irq != VIRQ_NUM_INVALID; 15 | } 16 | 17 | interrupt_data_t 18 | virq_edge(virq_t virq_num) 19 | { 20 | return (interrupt_data_t){ 21 | .irq = virq_num, 22 | .is_edge_triggering = true, 23 | }; 24 | } 25 | 26 | interrupt_data_t 27 | virq_level(virq_t virq_num) 28 | { 29 | return (interrupt_data_t){ 30 | .irq = virq_num, 31 | .is_edge_triggering = false, 32 | }; 33 | } 34 | 35 | virq_t 36 | virq_get_number(interrupt_data_t virq) 37 | { 38 | return virq.irq; 39 | } 40 | -------------------------------------------------------------------------------- /src/vm_config/vm_config_rtc.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define RTC_IPA_SIZE 0x1000 6 | 7 | error_t 8 | handle_rtc(vm_config_t *vmcfg, vm_config_parser_data_t *data); 9 | 10 | error_t 11 | handle_rtc_teardown(vm_config_t *vmcfg, vdevice_node_t **node); 12 | -------------------------------------------------------------------------------- /src/vm_config/vm_get_resources.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | // after vm_resources.h 23 | #include 24 | #include 25 | 26 | static void 27 | vm_get_hyp_resources(vmid_t client_id, uint32_t msg_id, uint16_t seq_num, 28 | void *buf, size_t len) 29 | { 30 | rm_error_t ret; 31 | vmid_t vmid; 32 | 33 | if (len != 4U) { 34 | ret = RM_ERROR_MSG_INVALID; 35 | goto out; 36 | } 37 | 38 | uint8_t *buf8 = (uint8_t *)buf; 39 | vmid = (vmid_t)(buf8[0] | (buf8[1] << 8)); 40 | 41 | // Lookup resources 42 | uint32_t resource_entries = 0; 43 | 44 | vector_t *descs = vector_init(rm_hyp_resource_resp_t, 16, 16); 45 | if (descs == NULL) { 46 | ret = RM_ERROR_NOMEM; 47 | goto out_deinit; 48 | } 49 | 50 | ret = vm_config_get_resource_descs(client_id, vmid, descs); 51 | if (ret != RM_OK) { 52 | goto out_deinit; 53 | } 54 | 55 | resource_entries = (uint32_t)vector_size(descs); 56 | 57 | size_t resp_size = (2U * sizeof(uint32_t)) + 58 | (resource_entries * sizeof(rm_hyp_resource_resp_t)); 59 | char *resp = calloc(1, resp_size); 60 | if (resp == NULL) { 61 | ret = RM_ERROR_NOMEM; 62 | goto out_deinit; 63 | } 64 | 65 | memcpy(resp, &ret, sizeof(ret)); 66 | memcpy(resp + sizeof(uint32_t), &resource_entries, 67 | sizeof(resource_entries)); 68 | (void)memcpy((void *)(resp + (2U * sizeof(uint32_t))), 69 | vector_raw_data(descs), 70 | resource_entries * sizeof(rm_hyp_resource_resp_t)); 71 | 72 | rm_error_t rpc_err = 73 | rm_rpc_fifo_reply(client_id, msg_id, seq_num, resp, resp_size); 74 | // We cannot recover from errors here 75 | if (rpc_err != RM_OK) { 76 | (void)printf("get_hyp_resources: err(%d)\n", rpc_err); 77 | exit(1); 78 | } 79 | 80 | out_deinit: 81 | if (descs != NULL) { 82 | vector_deinit(descs); 83 | } 84 | 85 | out: 86 | if (ret != RM_OK) { 87 | rm_standard_reply(client_id, msg_id, seq_num, ret); 88 | } 89 | } 90 | 91 | bool 92 | vm_get_resources_handler(vmid_t client_id, uint32_t msg_id, uint16_t seq_num, 93 | void *buf, size_t len) 94 | { 95 | bool handled = false; 96 | 97 | if (client_id == VMID_HYP) { 98 | goto out; 99 | } 100 | 101 | switch (msg_id) { 102 | case VM_GET_HYP_RESOURCES: 103 | vm_get_hyp_resources(client_id, msg_id, seq_num, buf, len); 104 | handled = true; 105 | break; 106 | case VM_GET_HYP_CAPIDS: 107 | // FIXME: implement in v2 108 | break; 109 | case VM_GET_HYP_IRQS: 110 | // FIXME: implement in v2 111 | break; 112 | default: 113 | // not a get-resources message 114 | break; 115 | } 116 | 117 | out: 118 | return handled; 119 | } 120 | -------------------------------------------------------------------------------- /src/vm_config/vm_parser_rtc.h: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | listener_return_t 6 | parse_vrtc(vm_config_parser_data_t *vd, const void *fdt, int node_ofs, 7 | const ctx_t *ctx); 8 | -------------------------------------------------------------------------------- /src/vm_creation/dto_construct.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | error_t 6 | dto_create_doorbell(struct vdevice_node *node, dto_t *dto, uint32_t *phandle); 7 | 8 | error_t 9 | dto_create_msg_queue(struct vdevice_node *node, dto_t *dto); 10 | 11 | error_t 12 | dto_create_shm(struct vdevice_node *node, dto_t *dto, vmid_t self); 13 | 14 | error_t 15 | dto_create_msg_queue_pair(struct vdevice_node *node, dto_t *dto); 16 | 17 | error_t 18 | dto_create_watchdog(struct vdevice_node *node, dto_t *dto); 19 | 20 | error_t 21 | dto_create_virtio_mmio(struct vdevice_node *node, dto_t *dto, vmid_t self); 22 | 23 | error_t 24 | dto_create_vrtc(struct vdevice_node *node, dto_t *dto); 25 | 26 | error_t 27 | patch_smmu_v2_nodes(const void *base_dtb, dto_t *dto, vmid_t vmid); 28 | 29 | error_t 30 | dto_guid_to_string(uint8_t *guid, size_t guid_len, char *output, 31 | size_t output_len); 32 | 33 | error_t 34 | add_compatibles(struct vdevice_node *node, char *compatibles[], 35 | count_t compatible_cnt, dto_t *dto); 36 | -------------------------------------------------------------------------------- /src/vm_creation/rm_vm.c: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | error_t 32 | rm_vm_create(const rm_env_data_t *env_data) 33 | { 34 | error_t ret = OK; 35 | 36 | vm_t *rm = vm_lookup(VMID_RM); 37 | assert(rm != NULL); 38 | 39 | cap_id_t rm_partition_cap = rm_get_rm_partition(); 40 | cap_id_t rm_cspace_cap = rm_get_rm_cspace(); 41 | 42 | // Create the VM config. 43 | // 44 | // This is only used to allow RM to receive memory donations, so it only 45 | // needs the basic three caps for cspace, partition and addrspace. 46 | vm_config_t *vmcfg = 47 | vm_config_alloc(rm, rm_cspace_cap, rm_partition_cap); 48 | if (vmcfg == NULL) { 49 | ret = ERROR_NOMEM; 50 | LOG_ERR(ret); 51 | goto out; 52 | } 53 | vmcfg->addrspace = env_data->addrspace_capid; 54 | rm->priority = ROOTVM_PRIORITY; 55 | 56 | ret = vm_config_add_vcpu(vmcfg, env_data->vcpu_capid, 57 | env_data->boot_core, true, NULL); 58 | if (ret != OK) { 59 | LOG_ERR(ret); 60 | goto out; 61 | } 62 | 63 | ret = vm_memory_setup(rm); 64 | if (ret != OK) { 65 | LOG_ERR(ret); 66 | goto out; 67 | } 68 | 69 | ret = vm_address_range_init(rm).e; 70 | if (ret != OK) { 71 | LOG_ERR(ret); 72 | goto out; 73 | } 74 | 75 | // Reserve one page at 0 (if it wasn't already reserved for the root 76 | // application or device MEs) to ensure that NULL doesn't get allocated 77 | // as a valid address in the RM address space 78 | if ((env_data->me_ipa_base != 0U) && (env_data->device_me_base != 0U)) { 79 | ret = vm_address_range_alloc(rm, VM_MEMUSE_NORMAL, 0U, 0U, 80 | PAGE_SIZE, PAGE_SIZE) 81 | .err; 82 | if (ret != OK) { 83 | LOG_ERR(ret); 84 | goto out; 85 | } 86 | } 87 | 88 | // Reserve the pre-mapped memextent containing the RM code & heap 89 | ret = vm_address_range_alloc(rm, VM_MEMUSE_NORMAL, 90 | env_data->me_ipa_base, 91 | env_data->me_ipa_base, env_data->me_size, 92 | 0U) 93 | .err; 94 | if (ret != OK) { 95 | LOG_ERR(ret); 96 | goto out; 97 | } 98 | 99 | out: 100 | return ret; 101 | } 102 | -------------------------------------------------------------------------------- /src/vm_creation/vm_creation_pv_time.c: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | error_t 32 | vm_creation_config_vm_info_area(vm_config_t *vmcfg) 33 | { 34 | error_t ret = OK; 35 | 36 | // We need to dynamically allocate some pages for the info area and 37 | // attach them to a memextent. For this, we have to derive a memextent 38 | // from the RM's memextent and map this allocated range as read-only to 39 | // the VM. 40 | // For now allocate one page. In the future we could have multiple. 41 | // Warning: Prone to rowhammer attacks. 42 | // FIXME: 43 | size_t size = PAGE_SIZE; 44 | 45 | vmcfg->vm->vm_info_area_size = 0; 46 | vmcfg->vm->vm_info_area_ipa = ~0UL; 47 | vmcfg->vm->vm_info_area_rm_ipa = ~0UL; 48 | vmcfg->vm_info_area_me_cap = CSPACE_CAP_INVALID; 49 | 50 | void *rm_ipa = aligned_alloc(PAGE_SIZE, size); 51 | if (rm_ipa == NULL) { 52 | ret = ERROR_NOMEM; 53 | goto out; 54 | } 55 | (void)memset(rm_ipa, 0, size); 56 | 57 | size_t offset = (size_t)((vmaddr_t)rm_ipa - rm_get_me_ipa_base()); 58 | 59 | cap_id_result_t me_ret = memextent_create( 60 | offset, size, MEMEXTENT_TYPE_BASIC, PGTABLE_ACCESS_RW, 61 | MEMEXTENT_MEMTYPE_ANY, rm_get_me()); 62 | if (me_ret.e != OK) { 63 | ret = me_ret.e; 64 | goto error_free_rm_ipa; 65 | } 66 | 67 | // Allocate IPA 68 | vm_address_range_result_t alloc_ret = vm_address_range_alloc( 69 | vmcfg->vm, VM_MEMUSE_VDEVICE, INVALID_ADDRESS, INVALID_ADDRESS, 70 | size, PAGE_SIZE); 71 | if (alloc_ret.err != OK) { 72 | ret = alloc_ret.err; 73 | (void)printf( 74 | "Failed to allocate IPA for stats area, error %" PRId32 75 | "\n", 76 | (int32_t)ret); 77 | goto error_delete_me_cap; 78 | } 79 | 80 | vmcfg->vm->vm_info_area_ipa = alloc_ret.base; 81 | vmcfg->vm->vm_info_area_rm_ipa = (uintptr_t)rm_ipa; 82 | vmcfg->vm->vm_info_area_size = size; 83 | vmcfg->vm_info_area_me_cap = me_ret.r; 84 | 85 | goto out; 86 | 87 | error_delete_me_cap: 88 | memextent_delete(me_ret.r); 89 | error_free_rm_ipa: 90 | free(rm_ipa); 91 | out: 92 | return ret; 93 | } 94 | 95 | error_t 96 | vm_creation_map_vm_info_area(vm_config_t *vmcfg) 97 | { 98 | error_t err; 99 | 100 | if ((vmcfg->vm->vm_info_area_ipa == ~0UL) || 101 | (vmcfg->vm->vm_info_area_rm_ipa == ~0UL) || 102 | (vmcfg->vm_info_area_me_cap == CSPACE_CAP_INVALID)) { 103 | err = ERROR_ADDR_INVALID; 104 | goto out; 105 | } 106 | 107 | // Map it to the VM read-only 108 | err = vm_memory_map(vmcfg->vm, VM_MEMUSE_VDEVICE, 109 | vmcfg->vm_info_area_me_cap, 110 | vmcfg->vm->vm_info_area_ipa, PGTABLE_ACCESS_R, 111 | PGTABLE_VM_MEMTYPE_NORMAL_WB); 112 | 113 | out: 114 | return err; 115 | } 116 | 117 | void 118 | vm_creation_vm_info_area_teardown(vm_config_t *vmcfg) 119 | { 120 | if (vmcfg->vm->vm_info_area_size != 0UL) { 121 | if (vmcfg->vm->vm_info_area_ipa != ~0UL) { 122 | error_t err = vm_address_range_free( 123 | vmcfg->vm, VM_MEMUSE_VDEVICE, 124 | vmcfg->vm->vm_info_area_ipa, 125 | vmcfg->vm->vm_info_area_size); 126 | assert(err == OK); 127 | } 128 | 129 | if (vmcfg->vm_info_area_me_cap != CSPACE_CAP_INVALID) { 130 | memextent_delete(vmcfg->vm_info_area_me_cap); 131 | } 132 | 133 | if (vmcfg->vm->vm_info_area_rm_ipa != ~0UL) { 134 | free((void *)vmcfg->vm->vm_info_area_rm_ipa); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/vm_creation/vm_creation_rtc.c: -------------------------------------------------------------------------------- 1 | // © 2022 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #pragma clang diagnostic push 25 | #pragma clang diagnostic ignored "-Wzero-length-array" 26 | #pragma clang diagnostic ignored "-Wbad-function-cast" 27 | #pragma clang diagnostic ignored "-Wsign-conversion" 28 | #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" 29 | #pragma clang diagnostic ignored "-Wextra-semi" 30 | #include 31 | #pragma clang diagnostic pop 32 | 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | #include "dto_construct.h" 40 | 41 | error_t 42 | dto_create_vrtc(struct vdevice_node *node, dto_t *dto) 43 | { 44 | error_t ret; 45 | error_t e = OK; 46 | uint32_t phandle = 0U; 47 | 48 | struct vdevice_rtc *cfg = (struct vdevice_rtc *)node->config; 49 | 50 | size_t sz = strlen(node->generate) + DTB_NODE_NAME_MAX; 51 | char *path = (char *)malloc(sz); 52 | if (path == NULL) { 53 | (void)printf("Error: failed to allocate path for RTC\n"); 54 | e = ERROR_NOMEM; 55 | goto err_begin; 56 | } 57 | 58 | // The kernel driver for PL031 needs a clock node associated with the 59 | // AMBA device or it will fail to probe, so we create a dummy clock node 60 | // with a unique phandle value to associate with the RTC node. 61 | (void)snprintf(path, sz, "%s/vrtc-pclk", node->generate); 62 | e = dto_construct_begin_path(dto, path); 63 | if (e != OK) { 64 | goto err_free; 65 | } 66 | e = dto_property_add_u32(dto, "#clock-cells", 0); 67 | if (e != OK) { 68 | goto err; 69 | } 70 | e = dto_property_add_string(dto, "compatible", "fixed-clock"); 71 | if (e != OK) { 72 | goto err; 73 | } 74 | e = dto_property_add_u32(dto, "clock-frequency", 1); 75 | if (e != OK) { 76 | goto err; 77 | } 78 | e = dto_property_add_phandle(dto, &phandle); 79 | if (e != OK) { 80 | goto err; 81 | } 82 | e = dto_construct_end_path(dto, path); 83 | if (e != OK) { 84 | goto err_free; 85 | } 86 | 87 | // Now create the vRTC node 88 | (void)snprintf(path, sz, "%s/vrtc", node->generate); 89 | e = dto_construct_begin_path(dto, path); 90 | if (e != OK) { 91 | goto err_free; 92 | } 93 | 94 | const char *c[] = { "arm,pl031", "arm,primecell" }; 95 | e = vm_creation_add_compatibles(node, c, util_array_size(c), dto); 96 | if (e != OK) { 97 | goto err; 98 | } 99 | 100 | uint64_t reg[2] = { cfg->ipa, cfg->ipa_size }; 101 | e = dto_property_add_u64array(dto, "reg", reg, 2); 102 | if (e != OK) { 103 | goto err; 104 | } 105 | 106 | e = dto_property_add_string(dto, "clock-names", "apb_pclk"); 107 | if (e != OK) { 108 | goto err; 109 | } 110 | 111 | e = dto_property_ref_internal(dto, "clocks", phandle); 112 | 113 | err: 114 | ret = dto_construct_end_path(dto, path); 115 | if (e == OK) { 116 | e = ret; 117 | } 118 | err_free: 119 | free(path); 120 | err_begin: 121 | return e; 122 | } 123 | -------------------------------------------------------------------------------- /src/vm_creation/vm_elf.c: -------------------------------------------------------------------------------- 1 | // © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | rm_error_t 18 | vm_elf_process_ptload_segments(Elf_Ehdr_ptr ehdr, Elf_Phdr_ptr phdrs, 19 | uintptr_t mem_base, vmaddr_t mem_size, 20 | paddr_t phys_base, 21 | boot_env_phys_range_t *vm_segments, 22 | size_t num_vm_segments, size_t *vm_segment_count, 23 | paddr_t *entry_offset, paddr_t *dt_offset, 24 | size_t *dt_size, bool *single_dtb) 25 | { 26 | rm_error_t ret = RM_ERROR_MEM_INVALID; 27 | 28 | Elf_Class class = elf_get_ehdr_class(ehdr); 29 | if ((class != ELF_CLASS_32) && (class != ELF_CLASS_64)) { 30 | goto out; 31 | } 32 | 33 | count_t e_phnum = elf_get_ehdr_field(ehdr, e_phnum); 34 | 35 | // Flush the max header size (ELF64) 36 | cache_flush_by_va(phdrs.phdr64, sizeof(Elf64_Phdr) * e_phnum); 37 | 38 | // Check all the PT_LOAD segments. 39 | index_t segment_count = 0U; 40 | bool relocatable = false; 41 | for (index_t i = 0U; i < e_phnum; i++) { 42 | // Ignore non-loadable segments. 43 | if (!elf_segment_is_loadable(class, phdrs, i)) { 44 | continue; 45 | } 46 | 47 | // Find the segment address relative to the start of the parcel. 48 | // Segments marked relocatable are already loaded relative to 49 | // the start; otherwise they are loaded at their absolute 50 | // physical address (assuming the loading VM had it mapped 1:1 51 | // or else knew the real physical base; authentication of 52 | // absolute addressed images will fail otherwise). 53 | size_t segment_offset = 54 | elf_get_phdr_field(class, phdrs, i, p_paddr); 55 | 56 | // If there is at least one relocatable segment, we need 57 | // to tell TZ the offset, and also apply it to the entry 58 | // point. 59 | relocatable = elf_segment_is_relocatable(class, phdrs, i); 60 | if (!relocatable) { 61 | // Note: underflow of this subtraction will be 62 | // caught by the range check below 63 | segment_offset -= phys_base; 64 | } 65 | 66 | size_t p_memsz = elf_get_phdr_field(class, phdrs, i, p_memsz); 67 | if (!elf_valid_ptload_segment(i, p_memsz, segment_offset, 68 | segment_count, vm_segments, 69 | mem_size)) { 70 | goto out; 71 | } 72 | 73 | // Save the segment for use during VM init, mostly for locating 74 | // the Linux initrd. Note that segment numbers in the DT only 75 | // count PT_LOAD segments; they're not simple phdr indices. 76 | if (segment_count < num_vm_segments) { 77 | vm_segments[segment_count].base = segment_offset; 78 | vm_segments[segment_count].size = p_memsz; 79 | segment_count++; 80 | } 81 | 82 | // Check whether the segment contains the DT. 83 | uint32_t *first_word = (uint32_t *)(mem_base + segment_offset); 84 | cache_flush_by_va(first_word, sizeof(*first_word)); 85 | if (elf_segment_contains_dt(first_word, single_dtb)) { 86 | *dt_offset = segment_offset; 87 | *dt_size = 88 | elf_get_phdr_field(class, phdrs, i, p_filesz); 89 | } 90 | } 91 | *vm_segment_count = segment_count; 92 | 93 | if (*dt_size == 0U) { 94 | (void)printf("Error: no DTB segment found\n"); 95 | goto out; 96 | } 97 | 98 | *entry_offset = elf_get_ehdr_field(ehdr, e_entry); 99 | if (!relocatable) { 100 | *entry_offset -= phys_base; 101 | } 102 | 103 | ret = RM_OK; 104 | 105 | out: 106 | return ret; 107 | } 108 | -------------------------------------------------------------------------------- /tools/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quic/gunyah-resource-manager/1b23ceb0dfa010b3b6b5a5f7a4ec1e95b93ab99d/tools/__init__.py -------------------------------------------------------------------------------- /tools/build/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quic/gunyah-resource-manager/1b23ceb0dfa010b3b6b5a5f7a4ec1e95b93ab99d/tools/build/__init__.py -------------------------------------------------------------------------------- /tools/build/__main__.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | # 3 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | 7 | """ 8 | Gunyah general build system. 9 | 10 | This module is invoked by configure.py with the global variable `graph` set to 11 | an instance of AbstractBuildGraph, which can be used to add rules, targets and 12 | variables to the build graph. 13 | """ 14 | 15 | import os 16 | import sys 17 | import logging 18 | import inspect 19 | 20 | from . import config_file as cfg 21 | 22 | # 23 | # Global variable & default settings 24 | # 25 | # Silence flake8 warnings about the externally-defined graph variable 26 | graph = graph # noqa: F821 27 | 28 | logging.basicConfig() 29 | logger = logging.getLogger(__name__) 30 | 31 | build_dir = graph.build_dir 32 | config_file_name = "build.conf" 33 | 34 | # 35 | # Build rules 36 | # 37 | 38 | 39 | # 40 | # General setup 41 | # 42 | def relpath(path): 43 | return os.path.relpath(path, start=graph.root_dir) 44 | 45 | 46 | # 47 | # Variant setup 48 | # 49 | true_strings = ('true', 't', '1', 'yes', 'y') 50 | false_strings = ('false', 'f', '0', 'no', 'n') 51 | all_arg = graph.get_argument('all', 'false').lower() 52 | if all_arg in true_strings: 53 | default_all_variants = True 54 | elif all_arg in false_strings: 55 | default_all_variants = False 56 | else: 57 | logger.error("Argument all= must have a boolean value, not '%s'", all_arg) 58 | sys.exit(1) 59 | 60 | variant_config = {} 61 | missing_variant = False 62 | for variant_key in ('platform', 'quality'): 63 | try: 64 | variant_value = graph.get_env('VARIANT_' + variant_key) 65 | except KeyError: 66 | variant_arg = graph.get_argument( 67 | variant_key, 'all' if default_all_variants else None) 68 | 69 | import glob 70 | known_variants = frozenset( 71 | os.path.splitext(os.path.basename(f))[0] 72 | for f in glob.iglob(os.path.join('config', variant_key, '*.conf'))) 73 | if not known_variants: 74 | logger.error('No variants known for key "%s"', variant_key) 75 | sys.exit(1) 76 | 77 | if variant_arg is None: 78 | logger.error('No variant specified for key %s; choices: %s', 79 | variant_key, ', '.join(known_variants)) 80 | missing_variant = True 81 | continue 82 | 83 | if variant_arg == 'all': 84 | selected_variants = known_variants 85 | else: 86 | selected_variants = frozenset(variant_arg.split(',')) 87 | if not (selected_variants <= known_variants): 88 | logger.error("Unknown variants specified for key %s: %s; " 89 | "choices: %s", variant_key, 90 | ', '.join(selected_variants - known_variants), 91 | ', '.join(known_variants)) 92 | missing_variant = True 93 | continue 94 | 95 | for val in selected_variants: 96 | graph.add_variant(os.path.join(build_dir, val))(**{ 97 | 'VARIANT_' + variant_key: val 98 | }) 99 | 100 | # Don't build anything until all variants are configured 101 | sys.exit() 102 | 103 | variant_config[variant_key] = variant_value 104 | 105 | if missing_variant: 106 | sys.exit(1) 107 | 108 | # parse configure file 109 | config = cfg.Configuration(config_file_name, graph, **variant_config) 110 | config.process() 111 | 112 | # 113 | # Python dependencies 114 | # 115 | for m in sys.modules.values(): 116 | try: 117 | f = inspect.getsourcefile(m) 118 | except TypeError: 119 | continue 120 | if f is None: 121 | continue 122 | f = os.path.relpath(f) 123 | if f.startswith('../'): 124 | continue 125 | graph.add_gen_source(f) 126 | -------------------------------------------------------------------------------- /tools/build/gen_ver.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 3 | # 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | 6 | status=`git diff HEAD --quiet || echo '-dirty'` 7 | 8 | echo '// This file is automatically generated.' 9 | echo '// Do not manually resolve conflicts! Contact hypervisor.team for assistance.' 10 | echo "#define RM_GIT_VERSION \"`git rev-parse --short HEAD`$status\"" 11 | 12 | if [ -z "$status" ] 13 | then 14 | echo "#define RM_BUILD_DATE \"`TZ=UTC git show -s --pretty="%cd" --date=local HEAD` UTC\"" 15 | else 16 | echo "#define RM_BUILD_DATE \"`date -R`\"" 17 | fi 18 | -------------------------------------------------------------------------------- /tools/cpptest/Cyclomatic.properties: -------------------------------------------------------------------------------- 1 | #For more details on cyclomatic complexity see 2 | #https://emenda.com/wp-content/uploads/2017/07/HIS-sc-metriken.1.3.1_e.pdf 3 | 4 | #Comment Density >=20% 5 | #Comment Density "COMF" 6 | METRIC.CLLOCRIM=false 7 | #METRIC.CLLOCRIM.ThresholdEnabled=true 8 | #METRIC.CLLOCRIM.Threshold=g .2 9 | 10 | 11 | #Cyclomatic Complexity <=10 12 | #Cyclomatic Complexity "v(G)" 13 | #METRIC.CC=true 14 | #METRIC.CC.ThresholdEnabled=true 15 | #METRIC.CC.Threshold=l 21 16 | 17 | #number of parameters <=5 18 | #Number of function parameters "PARAM" 19 | METRIC.NOPAR=false 20 | #METRIC.NOPAR.ThresholdEnabled=true 21 | #METRIC.NOPAR.Threshold=l 6 22 | 23 | 24 | #of instructions <=50 25 | #Number of Instructions per function "STMT" 26 | METRIC.NOLLOCIF=false 27 | #METRIC.NOLLOCIF.ThresholdEnabled=true 28 | #METRIC.NOLLOCIF.Threshold=l 51 29 | 30 | #of call levels <=4 31 | #Number of call Levels "LEVEL" 32 | METRIC.NBD=false 33 | #METRIC.NBD.ThresholdEnabled=true 34 | #METRIC.NBD.Threshold=l 5 35 | 36 | METRIC.DIF=false 37 | #METRIC.DIF.ThresholdEnabled=true 38 | #METRIC.DIF.Threshold=l 5 39 | 40 | 41 | #Number of return Points "RETURN" 42 | #Error on != 1 43 | METRIC.NORET=false 44 | #METRIC.NORET.ThresholdEnabled=true 45 | #METRIC.NORET.Threshold=l 2 46 | 47 | 48 | #All the other metrics that do not have thresholds 49 | METRIC.NOF=false 50 | METRIC.NOC=false 51 | METRIC.NOPLIF=false 52 | METRIC.NOPLIT=false 53 | METRIC.NOPLIM=false 54 | METRIC.NOSLIF=false 55 | METRIC.NOSLIT=false 56 | METRIC.NOSLIM=false 57 | METRIC.NOLLOCIT=false 58 | METRIC.NOLLOCIM=false 59 | METRIC.NOCLIF=false 60 | METRIC.NOCLIT=false 61 | METRIC.NOCLIM=false 62 | METRIC.NOBLIF=false 63 | METRIC.NOBLIT=false 64 | METRIC.NOBLIM=false 65 | METRIC.CLLOCRIT=false 66 | METRIC.CLLOCRIF=false 67 | METRIC.SCC=false 68 | METRIC.MCC=true 69 | METRIC.MCC.ThresholdEnabled=true 70 | METRIC.MCC.Threshold=l 15 71 | 72 | METRIC.ECC=false 73 | METRIC.NOT=false 74 | METRIC.NOMIT=false 75 | METRIC.NOPUBMIT=false 76 | METRIC.NOPROTMIT=false 77 | METRIC.NOPRIVMIT=false 78 | METRIC.IDOC=false 79 | METRIC.CBO=false 80 | METRIC.LCOM=false 81 | METRIC.FO=false 82 | METRIC.MI=false 83 | METRIC.RFC=false 84 | METRIC.WMC=false 85 | METRIC.HDIFM=false 86 | METRIC.HEFM=false 87 | METRIC.HICM=false 88 | METRIC.HLENM=false 89 | METRIC.HLEVM=false 90 | METRIC.HNOBM=false 91 | METRIC.HTTPM=false 92 | METRIC.HVOCM=false 93 | METRIC.HVOLM=false 94 | 95 | 96 | cpptest.analyzer.metrics.enabled=true 97 | # Test configuration metadata 98 | com.parasoft.xtest.checkers.api.config.name=Modified Cyclomatic 99 | com.parasoft.xtest.checkers.api.config.path=Static Analysis 100 | com.parasoft.xtest.checkers.api.config.tool=3 101 | com.parasoft.xtest.checkers.api.config.version=9.5.0 102 | com.parasoft.xtest.checkers.api.config.xtestVersion=1.0.1 103 | com.parasoft.xtest.checkers.api.common.fullBuild=false 104 | com.parasoft.xtest.checkers.api.common.incrementalBuild=false 105 | com.parasoft.xtest.standards.api.enabled=true 106 | com.parasoft.xtest.execution.api.enabled=false 107 | com.parasoft.xtest.testgen.api.enabled=false 108 | com.parasoft.xtest.standards.api.max_errors_per_rule=10000 109 | -------------------------------------------------------------------------------- /tools/cpptest/cyclomatic_xml_to_json.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # coding: utf-8 3 | # 4 | # © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 5 | # 6 | # SPDX-License-Identifier: BSD-3-Clause 7 | 8 | """ 9 | Run as a part of gitlab CI, after Parasoft reports have been generated. 10 | 11 | This script converts the Parasoft XML-format report to a Code Climate 12 | compatible json file, that gitlab code quality can interpret. 13 | """ 14 | 15 | import xml.etree.ElementTree as ET 16 | import json 17 | import argparse 18 | import sys 19 | import os 20 | 21 | argparser = argparse.ArgumentParser( 22 | description="Convert Parasoft XML to Code Climate JSON") 23 | argparser.add_argument('input', type=argparse.FileType('r'), nargs='?', 24 | default=sys.stdin, help="the Parasoft XML input") 25 | argparser.add_argument('--output', '-o', type=argparse.FileType('w'), 26 | default=sys.stdout, help="the Code Climate JSON output") 27 | args = argparser.parse_args() 28 | 29 | tree = ET.parse(args.input) 30 | 31 | parasoft_viols = tree.findall(".//MetViol") 32 | 33 | cc_viols = [] 34 | 35 | severity_map = { 36 | 1: "blocker", 37 | 2: "critical", 38 | 3: "major", 39 | 4: "minor", 40 | 5: "info", 41 | } 42 | 43 | # info warning between 15-20 44 | start__threshold = 15 45 | end__threshold = 20 46 | 47 | 48 | def cc_info_warning(msg, sev): 49 | warning = int(msg.split(" ")[1]) 50 | if (warning >= start__threshold) and (warning <= end__threshold): 51 | return 5 52 | else: 53 | return sev 54 | 55 | 56 | cc_viols = [ 57 | ({ 58 | "type": "issue", 59 | "categories": ["Bug Risk"], 60 | "severity": (severity_map[cc_info_warning(v.attrib['msg'], 61 | int(v.attrib['sev']))]), 62 | "check_name": v.attrib['rule'], 63 | "description": (v.attrib['msg'] + '. ' + 64 | v.attrib['rule.header'] + '. (' + 65 | v.attrib['rule'] + ')'), 66 | "fingerprint": v.attrib['unbViolId'], 67 | "location": { 68 | "path": v.attrib['locFile'].split(os.sep, 2)[2], 69 | "lines": { 70 | "begin": int(v.attrib['locStartln']), 71 | "end": int(v.attrib['locEndLn']) 72 | } 73 | } 74 | }) 75 | for v in parasoft_viols] 76 | 77 | args.output.write(json.dumps(cc_viols)) 78 | args.output.close() 79 | -------------------------------------------------------------------------------- /tools/cpptest/gunyahkw.h: -------------------------------------------------------------------------------- 1 | #ifndef __KW_MODERN_ENGINE__ 2 | int 3 | __builtin_ffsll(unsigned long long x); 4 | #kw_override compiler_ffs(x) __builtin_ffsll(x) 5 | 6 | /* FPs caused by KW not understanding __builtin_expect(), overrides suggested by 7 | * TomZ '22 */ 8 | #kw_override compiler_expected(x)(x) 9 | #kw_override compiler_unexpected(x)(x) 10 | 11 | #kw_override HYP_LOG_FATAL(xx_fmt, ...)(abort()) 12 | #endif 13 | -------------------------------------------------------------------------------- /tools/cpptest/gunyahkw.kb: -------------------------------------------------------------------------------- 1 | partition_alloc - ALLOC hyp:$1, $2 GT(0):$$.r:$$.e NE(0) 2 | partition_alloc - BPS charlength($$.r)=infinity 3 | partition_alloc - BPS bytesize($$.r)=$1 4 | partition_alloc - NPD.SRC env : $$.r : $$.e NE(0) 5 | partition_alloc - UNINIT.HEAP 1 : *($$.r) : 1 6 | partition_alloc - UnsafeAllocSizeAccepter $2 7 | partition_free - FREE hyp $2 8 | -------------------------------------------------------------------------------- /tools/cpptest/klocwork_xml_to_json.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # coding: utf-8 3 | # 4 | # © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 5 | # 6 | # SPDX-License-Identifier: BSD-3-Clause 7 | 8 | """ 9 | Run as a part of gitlab CI, after Klocwork reports have been generated. 10 | 11 | This script converts the Klocwork JSON-format report to a Code Climate 12 | compatible json file, that gitlab code quality can interpret. 13 | """ 14 | 15 | import json 16 | import argparse 17 | import sys 18 | import os 19 | import hashlib 20 | 21 | argparser = argparse.ArgumentParser( 22 | description="Convert Klocwork JSON to Code Climate JSON") 23 | argparser.add_argument('input', type=argparse.FileType('r'), nargs='?', 24 | default=sys.stdin, help="the Klocwork JSON input") 25 | argparser.add_argument('--output', '-o', type=argparse.FileType('w'), 26 | default=sys.stdout, help="the Code Climate JSON output") 27 | args = argparser.parse_args() 28 | 29 | json_input_file = "" 30 | 31 | kw_violations = [] 32 | issue = {} 33 | 34 | severity_map = { 35 | 1: "blocker", 36 | 2: "critical", 37 | 3: "major", 38 | 4: "minor", 39 | 5: "info", 40 | } 41 | 42 | 43 | def get_severity(v): 44 | if (v > 5): 45 | return severity_map[5] 46 | else: 47 | return severity_map[v] 48 | 49 | 50 | with open(args.input.name, 'r') as json_file: 51 | json_input_file = json.load(json_file) 52 | 53 | for v in range(len(json_input_file)): 54 | # print(json_input_file[v]) 55 | issue["type"] = "issue" 56 | issue["categories"] = ["Bug Risk"] 57 | issue["severity"] = get_severity( 58 | int(json_input_file[v]['severityCode'])) 59 | issue["check_name"] = json_input_file[v]['code'] 60 | issue["description"] = json_input_file[v]['message'] + '. ' + \ 61 | json_input_file[v]['severity'] + \ 62 | '. (' + json_input_file[v]['code'] + ')' 63 | issue["location"] = {} 64 | issue["location"]["path"] = os.path.relpath(json_input_file[v]['file']) 65 | issue["location"]["lines"] = {} 66 | issue["location"]["lines"]["begin"] = int(json_input_file[v]['line']) 67 | issue["location"]["lines"]["end"] = int(json_input_file[v]['line']) 68 | dump_issue = json.dumps(issue) 69 | issue["fingerprint"] = hashlib.md5(dump_issue.encode('utf-8')).hexdigest() 70 | # print(issue) 71 | kw_violations.append(issue) 72 | issue = {} # was getting wired result without clearing it 73 | args.output.write(json.dumps(kw_violations)) 74 | -------------------------------------------------------------------------------- /tools/cpptest/misra_xml_to_json.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # coding: utf-8 3 | # 4 | # © 2023 Qualcomm Innovation Center, Inc. All rights reserved. 5 | # 6 | # SPDX-License-Identifier: BSD-3-Clause 7 | 8 | """ 9 | Run as a part of gitlab CI, after Parasoft reports have been generated. 10 | 11 | This script converts the Parasoft XML-format report to a Code Climate 12 | compatible json file, that gitlab code quality can interpret. 13 | """ 14 | 15 | import xml.etree.ElementTree as ET 16 | import json 17 | import argparse 18 | import sys 19 | import os 20 | import re 21 | 22 | argparser = argparse.ArgumentParser( 23 | description="Convert Parasoft XML to Code Climate JSON") 24 | argparser.add_argument('input', type=argparse.FileType('r'), nargs='?', 25 | default=sys.stdin, help="the Parasoft XML input") 26 | argparser.add_argument('--output', '-o', type=argparse.FileType('w'), 27 | default=sys.stdout, help="the Code Climate JSON output") 28 | args = argparser.parse_args() 29 | 30 | tree = ET.parse(args.input) 31 | 32 | parasoft_viols = tree.findall(".//StdViol") + tree.findall(".//FlowViol") 33 | 34 | cc_viols = [] 35 | 36 | severity_map = { 37 | 1: "blocker", 38 | 2: "critical", 39 | 3: "major", 40 | 4: "minor", 41 | 5: "info", 42 | } 43 | 44 | deviation_map = { 45 | # Deviation because the behaviour proscribed by the rule is exactly the 46 | # intended behaviour of assert(): it prints the unexpanded expression. 47 | 'MISRAC2012-RULE_20_12-a': [ 48 | (None, re.compile(r"parameter of potential macro 'assert'")), 49 | ], 50 | 'MISRAC2012-RULE_21_6-a': [ 51 | (None, re.compile(r"Usage of 'printf' function")), 52 | ], 53 | # False positives due to __c11 builtins taking int memory order arguments 54 | # instead of enum in the Clang implementation. 55 | 'MISRAC2012-RULE_10_3-b': [ 56 | (None, re.compile(r"number '1'.*'essentially Enum'.*" 57 | r"'__c11_atomic_(thread|signal)_fence'.*" 58 | r"'essentially signed'")), 59 | (None, re.compile(r"number '2'.*'essentially Enum'.*" 60 | r"'__c11_atomic_load'.*'essentially signed'")), 61 | (None, re.compile(r"number '3'.*'essentially Enum'.*" 62 | r"'__c11_atomic_(store'|exchange'|fetch_).*" 63 | r"'essentially signed'")), 64 | (None, re.compile(r"number '[45]'.*'essentially Enum'.*" 65 | r"'__c11_atomic_compare_exchange_(strong|weak)'.*" 66 | r"'essentially signed'")), 67 | ], 68 | 'MISRAC2012-RULE_8_13-a': [ 69 | # False positives due to the could-be-const check not understanding 70 | # that an inline assembly output constraint that dereferences a 71 | # pointer is a write to that pointer. 72 | (re.compile(r'^src/guest_accessors\.c$'), 73 | re.compile(r'parameter "b1"')), 74 | ], 75 | # False positive due to a builtin sizeof variant that does not evaluate its 76 | # argument, so there is no uninitialised use. 77 | 'MISRAC2012-RULE_9_1-a': [ 78 | (None, re.compile(r'passed to "__builtin_object_size"')), 79 | ], 80 | 'MISRAC2012-RULE_1_3-b': [ 81 | (None, re.compile(r'passed to "__builtin_object_size"')), 82 | ], 83 | # Compliance with rule 21.25 would have a significant performance impact. 84 | # All existing uses have been thoroughly analysed and tested, so we will 85 | # seek a project-wide deviation for this rule. 86 | 'MISRAC2012-RULE_21_25-a': [ 87 | (None, None), 88 | ], 89 | } 90 | 91 | 92 | def matches_deviation(v): 93 | rule = v.attrib['rule'] 94 | if rule not in deviation_map: 95 | return False 96 | 97 | msg = v.attrib['msg'] 98 | path = v.attrib['locFile'].split(os.sep, 2)[2] 99 | 100 | def check_constraint(constraint, value): 101 | if constraint is None: 102 | return True 103 | try: 104 | return constraint.search(value) 105 | except AttributeError: 106 | return constraint == value 107 | 108 | for d_path, d_msg in deviation_map[rule]: 109 | if check_constraint(d_path, path) and check_constraint(d_msg, msg): 110 | return True 111 | 112 | return False 113 | 114 | 115 | cc_viols = [ 116 | ({ 117 | "type": "issue", 118 | "categories": ["Bug Risk"], 119 | "severity": ('info' if matches_deviation(v) 120 | else severity_map[int(v.attrib['sev'])]), 121 | "check_name": v.attrib['rule'], 122 | "description": (v.attrib['msg'] + '. ' + 123 | v.attrib['rule.header'] + '. (' + 124 | v.attrib['rule'] + ')'), 125 | "fingerprint": v.attrib['unbViolId'], 126 | "location": { 127 | "path": v.attrib['locFile'].split(os.sep, 2)[2], 128 | "lines": { 129 | "begin": int(v.attrib['locStartln']), 130 | "end": int(v.attrib['locEndLn']) 131 | } 132 | } 133 | }) 134 | for v in parasoft_viols] 135 | 136 | args.output.write(json.dumps(cc_viols)) 137 | args.output.close() 138 | -------------------------------------------------------------------------------- /tools/misc/convert-utf-8.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | enc=$(file --mime-encoding "$1" | sed -E 's/.*: //g') 6 | if [[ $enc == "binary" ]]; then 7 | exit 0 8 | fi 9 | if [[ $enc != "utf-8" ]]; then 10 | iconv -f $enc -t utf-8 "$1" -o "$1.tmp" 11 | cat "$1.tmp" > "$1" 12 | rm "$1.tmp" 13 | fi 14 | -------------------------------------------------------------------------------- /tools/misc/get_genfiles.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # coding: utf-8 3 | # 4 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 5 | # 6 | # SPDX-License-Identifier: BSD-3-Clause 7 | 8 | """ 9 | Simple script to parse the compile_commands to extract generated source and 10 | header files, to pass to cscope or other source indexing tools. 11 | """ 12 | 13 | build_dir = 'build' 14 | -------------------------------------------------------------------------------- /tools/misc/setversion.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 3 | # 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | 6 | outputpath=../../include/version.h 7 | echo "updating Resource Manager version #...." 8 | echo "Remember to checkin version.h into P4" 9 | echo chmod 777 ${outputpath} 10 | echo $(source ../build/gen_ver.sh ./ > ${outputpath}) 11 | echo "Done! "${outputpath}" is updated!" 12 | -------------------------------------------------------------------------------- /tools/misc/update_cscope.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 3 | # 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | 6 | git ls-files "*.[ch]" > cscope.in 7 | tools/misc/get_genfiles.py >> cscope.in 8 | 9 | cscope -bk -i cscope.in 10 | --------------------------------------------------------------------------------