├── .clang-format ├── .github └── workflows │ └── quic-organization-repolinter.yml ├── .gitignore ├── LICENSE ├── README.md ├── SConstruct ├── arch ├── armv8 │ ├── build.conf │ ├── include │ │ ├── arch_def.h │ │ ├── arch_reloc.h │ │ ├── asm │ │ │ ├── asm_defs.inc │ │ │ ├── cpu.h │ │ │ ├── device.h │ │ │ ├── event.h │ │ │ ├── interrupt.h │ │ │ ├── prefetch.h │ │ │ └── unistd.h │ │ └── el1.inc │ └── src │ │ ├── arch_syscall.h │ │ ├── boot.S │ │ ├── build.conf │ │ ├── generic_timer.c │ │ ├── gicv3.c │ │ ├── memcpy.S │ │ ├── memset.S │ │ ├── string.c │ │ ├── syscall.c │ │ └── vectors.S └── generic │ ├── build.conf │ ├── include │ ├── asm-generic │ │ ├── asm_defs.inc │ │ ├── prefetch.h │ │ └── vector.h │ └── panic.h │ └── src │ └── panic.c ├── build.conf ├── configure.py ├── include ├── assert.h ├── atomic.h ├── attributes.h ├── compiler.h ├── console.h ├── cpulocal.h ├── device.h ├── errno.h ├── exit_dev.h ├── fs.h ├── guest_hypresult.h ├── guest_interface.h ├── guest_rights.h ├── guest_types.h ├── hyperror.h ├── interrupt.h ├── log.h ├── platform_irq.h ├── platform_timer.h ├── reloc.h ├── string.h ├── string_util.h ├── sys │ ├── ioctl.h │ ├── types.h │ └── uio.h ├── syscall_defs.h ├── time.h ├── timer.h ├── tty.h ├── types.h ├── uapi │ ├── console.h │ ├── exit_dev.h │ └── interrupt.h └── util.h ├── repolint.json ├── src ├── auxvec.c ├── boot.c ├── build.conf ├── console.c ├── device_tree.c ├── device_tree.h ├── exit.c ├── exit_dev.c ├── fs.c ├── guest_accessors.c ├── guest_hypresult.c ├── guest_interface.c ├── interrupt.c ├── ioctl.c ├── log.c ├── log_buf.c ├── mmap.c ├── mmap.h ├── read_write.c ├── reloc.c ├── string.c ├── string_util.c ├── syscall.c ├── timer.c └── tty.c ├── tests └── qemu_run.sh └── 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 └── update_cscope.sh /.clang-format: -------------------------------------------------------------------------------- 1 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | # 5 | # Gunyah Coding Style - requires Clang Format >= 9 6 | # 7 | # For more information, see: 8 | # 9 | # https://clang.llvm.org/docs/ClangFormat.html 10 | # https://clang.llvm.org/docs/ClangFormatStyleOptions.html 11 | --- 12 | Language: Cpp 13 | AccessModifierOffset: -8 14 | AlignAfterOpenBracket: Align 15 | AlignArrayOfStructures: None 16 | AlignConsecutiveAssignments: 17 | Enabled: true 18 | AcrossEmptyLines: false 19 | AcrossComments: false 20 | AlignCompound: false 21 | PadOperators: true 22 | AlignConsecutiveBitFields: 23 | Enabled: false 24 | AcrossEmptyLines: false 25 | AcrossComments: false 26 | AlignCompound: false 27 | PadOperators: true 28 | AlignConsecutiveDeclarations: 29 | Enabled: true 30 | AcrossEmptyLines: false 31 | AcrossComments: false 32 | AlignCompound: false 33 | PadOperators: true 34 | AlignConsecutiveMacros: 35 | Enabled: true 36 | AcrossEmptyLines: false 37 | AcrossComments: false 38 | AlignCompound: false 39 | PadOperators: true 40 | AlignEscapedNewlines: Right 41 | AlignOperands: Align 42 | AlignTrailingComments: true 43 | AllowAllArgumentsOnNextLine: true 44 | AllowAllParametersOfDeclarationOnNextLine: false 45 | AllowShortEnumsOnASingleLine: true 46 | AllowShortBlocksOnASingleLine: Never 47 | AllowShortCaseLabelsOnASingleLine: false 48 | AllowShortFunctionsOnASingleLine: None 49 | AllowShortLambdasOnASingleLine: None 50 | AllowShortIfStatementsOnASingleLine: Never 51 | AllowShortLoopsOnASingleLine: false 52 | AlwaysBreakAfterDefinitionReturnType: None 53 | AlwaysBreakAfterReturnType: All 54 | AlwaysBreakBeforeMultilineStrings: false 55 | AlwaysBreakTemplateDeclarations: MultiLine 56 | AttributeMacros: 57 | - _Atomic 58 | - alignas 59 | BinPackArguments: true 60 | BinPackParameters: true 61 | BraceWrapping: 62 | AfterCaseLabel: false 63 | AfterClass: true 64 | AfterControlStatement: Never 65 | AfterEnum: false 66 | AfterFunction: true 67 | AfterNamespace: true 68 | AfterObjCDeclaration: false 69 | AfterStruct: false 70 | AfterUnion: false 71 | AfterExternBlock: false 72 | BeforeCatch: false 73 | BeforeElse: false 74 | BeforeLambdaBody: false 75 | BeforeWhile: false 76 | IndentBraces: false 77 | SplitEmptyFunction: true 78 | SplitEmptyRecord: true 79 | SplitEmptyNamespace: true 80 | BreakBeforeBinaryOperators: None 81 | BreakBeforeConceptDeclarations: Always 82 | BreakBeforeBraces: Custom 83 | BreakBeforeInheritanceComma: false 84 | BreakInheritanceList: BeforeComma 85 | BreakBeforeTernaryOperators: true 86 | BreakConstructorInitializersBeforeComma: false 87 | BreakConstructorInitializers: BeforeComma 88 | BreakAfterJavaFieldAnnotations: false 89 | BreakStringLiterals: false 90 | ColumnLimit: 80 91 | CommentPragmas: '^ FIXME:' 92 | QualifierAlignment: Left 93 | CompactNamespaces: false 94 | ConstructorInitializerIndentWidth: 8 95 | ContinuationIndentWidth: 8 96 | Cpp11BracedListStyle: false 97 | DeriveLineEnding: false 98 | DerivePointerAlignment: false 99 | DisableFormat: false 100 | EmptyLineAfterAccessModifier: Never 101 | EmptyLineBeforeAccessModifier: LogicalBlock 102 | ExperimentalAutoDetectBinPacking: false 103 | PackConstructorInitializers: BinPack 104 | BasedOnStyle: '' 105 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 106 | AllowAllConstructorInitializersOnNextLine: true 107 | FixNamespaceComments: true 108 | ForEachMacros: [] 109 | IfMacros: [] 110 | IncludeBlocks: Regroup 111 | IncludeCategories: 112 | - Regex: '^<(assert|limits|string|std.*|sys/.*|time)\.h>$' 113 | Priority: -100 114 | SortPriority: 0 115 | CaseSensitive: true 116 | - Regex: '^' 133 | Priority: -60 134 | SortPriority: 0 135 | CaseSensitive: true 136 | - Regex: '^' 137 | Priority: -55 138 | SortPriority: 0 139 | CaseSensitive: true 140 | - Regex: '^' 141 | Priority: -54 142 | SortPriority: 0 143 | CaseSensitive: true 144 | - Regex: '^' 145 | Priority: -52 146 | SortPriority: 0 147 | CaseSensitive: true 148 | - Regex: '^<' 149 | Priority: -20 150 | SortPriority: 0 151 | CaseSensitive: true 152 | - Regex: '^"' 153 | Priority: -1 154 | SortPriority: 0 155 | CaseSensitive: true 156 | IncludeIsMainRegex: '(Test)?$' 157 | IncludeIsMainSourceRegex: '' 158 | IndentAccessModifiers: false 159 | IndentCaseLabels: false 160 | IndentCaseBlocks: false 161 | IndentGotoLabels: true 162 | IndentPPDirectives: None 163 | IndentExternBlock: AfterExternBlock 164 | IndentRequiresClause: false 165 | IndentWidth: 8 166 | IndentWrappedFunctionNames: false 167 | InsertBraces: true 168 | InsertTrailingCommas: None 169 | JavaScriptQuotes: Leave 170 | JavaScriptWrapImports: true 171 | KeepEmptyLinesAtTheStartOfBlocks: false 172 | LambdaBodyIndentation: Signature 173 | MacroBlockBegin: '^BITMAP_(ATOMIC_)?FOREACH_(SET|CLEAR)_BEGIN$' 174 | MacroBlockEnd: '^BITMAP_(ATOMIC_)?FOREACH_(SET|CLEAR)_END$' 175 | MaxEmptyLinesToKeep: 1 176 | NamespaceIndentation: None 177 | ObjCBinPackProtocolList: Auto 178 | ObjCBlockIndentWidth: 2 179 | ObjCBreakBeforeNestedBlockParam: true 180 | ObjCSpaceAfterProperty: false 181 | ObjCSpaceBeforeProtocolList: true 182 | PenaltyBreakAssignment: 10 183 | PenaltyBreakBeforeFirstCallParameter: 30 184 | PenaltyBreakComment: 10 185 | PenaltyBreakFirstLessLess: 0 186 | PenaltyBreakOpenParenthesis: 0 187 | PenaltyBreakString: 10 188 | PenaltyBreakTemplateDeclaration: 10 189 | PenaltyExcessCharacter: 100 190 | PenaltyReturnTypeOnItsOwnLine: 0 191 | PenaltyIndentedWhitespace: 0 192 | PointerAlignment: Right 193 | PPIndentWidth: -1 194 | ReferenceAlignment: Pointer 195 | ReflowComments: true 196 | RemoveBracesLLVM: false 197 | RequiresClausePosition: OwnLine 198 | SeparateDefinitionBlocks: Always 199 | ShortNamespaceLines: 1 200 | SortIncludes: CaseSensitive 201 | SortJavaStaticImport: Before 202 | SortUsingDeclarations: false 203 | SpaceAfterCStyleCast: false 204 | SpaceAfterLogicalNot: false 205 | SpaceAfterTemplateKeyword: true 206 | SpaceBeforeAssignmentOperators: true 207 | SpaceBeforeCaseColon: false 208 | SpaceBeforeCpp11BracedList: false 209 | SpaceBeforeCtorInitializerColon: true 210 | SpaceBeforeInheritanceColon: true 211 | SpaceBeforeParens: ControlStatements 212 | SpaceBeforeParensOptions: 213 | AfterControlStatements: true 214 | AfterForeachMacros: true 215 | AfterFunctionDefinitionName: false 216 | AfterFunctionDeclarationName: false 217 | AfterIfMacros: true 218 | AfterOverloadedOperator: false 219 | AfterRequiresInClause: false 220 | AfterRequiresInExpression: false 221 | BeforeNonEmptyParentheses: false 222 | SpaceAroundPointerQualifiers: Default 223 | SpaceBeforeRangeBasedForLoopColon: false 224 | SpaceInEmptyBlock: true 225 | SpaceInEmptyParentheses: false 226 | SpacesBeforeTrailingComments: 1 227 | SpacesInAngles: Never 228 | SpacesInConditionalStatement: false 229 | SpacesInContainerLiterals: false 230 | SpacesInCStyleCastParentheses: false 231 | SpacesInLineCommentPrefix: 232 | Minimum: 1 233 | Maximum: 1 234 | SpacesInParentheses: false 235 | SpacesInSquareBrackets: false 236 | SpaceBeforeSquareBrackets: false 237 | BitFieldColonSpacing: Both 238 | Standard: Latest 239 | StatementMacros: 240 | - _Pragma 241 | StatementAttributeLikeMacros: [] 242 | TabWidth: 8 243 | UseCRLF: false 244 | UseTab: Always 245 | WhitespaceSensitiveMacros: [] 246 | ... 247 | -------------------------------------------------------------------------------- /.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@v2 15 | - name: Verify repolinter config file is present 16 | id: check_files 17 | uses: andstor/file-existence-action@v1 18 | with: 19 | files: "repolint.json" 20 | - name: Run Repolinter with local repolint.json 21 | if: steps.check_files.outputs.files_exists == 'true' 22 | with: 23 | config_file: "repolint.json" 24 | uses: newrelic/repolinter-action@v1 25 | - name: Run Repolinter with default ruleset 26 | if: steps.check_files.outputs.files_exists == 'false' 27 | uses: newrelic/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 | *.d 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 | 18 | # Ignore cppcheck dumps 19 | *.c.dump 20 | 21 | # Ignore Vim temporary files 22 | .*.sw[a-p] 23 | .*.un~ 24 | -------------------------------------------------------------------------------- /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 | # Gunyah C Runtime 2 | 3 | A runtime for light-weight OS-less application VMs supporting *bare metal* 4 | applications on the Gunyah Hypervisor. 5 | 6 | The runtime provides a minimal kernel emulation layer for Linux system calls 7 | which Musl libc internally uses. 8 | 9 | The runtime is compiled as stand alone ELF executable. It is loaded into memory 10 | along side a musl libc linked application and is executed with an argument to 11 | the application entry-point and a simple environment structure. It hooks the 12 | CPU exception vectors to provide system call and interrupt handling. The 13 | runtime does not reside at a higher privilege level and has no memory 14 | protection to isolate it from the application/libc (it is not a kernel). 15 | 16 | The runtime handles initialization and starting the application. It sets up the 17 | environment and stack that would normally be handled by a dynamic loader. 18 | 19 | ## Compile and Run 20 | 21 | The runtime is used by the Gunyah Hypervisor project. See 22 | https://github.com/quic/gunyah-hypervisor for details. 23 | 24 | Note, The C runtime should support any Linux targeted libc, however it has only 25 | been tested with the Gunyah hypervisor's Resource Manager, built with musl 26 | libc, and only implements the minimal set of syscalls this uses. 27 | 28 | ## System Overview 29 | 30 | ### Build system 31 | 32 | The build system is a simplified version of the hypervisor's, it has: 33 | 34 | * No explicit module configurations. 35 | * Only contains basic rules to compile C / assembly code into the target 36 | binary. 37 | * Uses a subset of the Gunyah configuration syntax. 38 | * Adds new configuration syntax to support customized rule/target. 39 | 40 | The project layout looks like: 41 | 42 | ``` 43 | root 44 | + 45 | | 46 | +--->build.conf 47 | | 48 | +--->README.md 49 | | 50 | +--->src 51 | | + 52 | | | 53 | | +--->build.conf 54 | | | 55 | | +--->source.c 56 | | | 57 | | +--->assemble.S 58 | | | 59 | | +--->package1 60 | | + 61 | | | 62 | | +--->build.conf 63 | | | 64 | | +--->src 65 | | | 66 | | +--->include 67 | | 68 | +--->include 69 | ``` 70 | 71 | The ```build.conf``` contains all compilation information, and it can refer to 72 | another configuration file in specified sub directory. 73 | 74 | 75 | ### Syscalls and Interrupts 76 | 77 | The runtime implements a syscall handling exception vector, however only a 78 | small subset of the Linux AArch64 ABI is implemented, and it includes some 79 | non-Linux like behaviour such as application interrupt handling support via 80 | special `/dev/` nodes using `ioctl()`. 81 | 82 | ### Exception vector table 83 | 84 | Only AArch64 64-bit SVCs are implemented. Interrupts are also supported. Other 85 | exceptions and unimplemented system calls result in a panic(). 86 | 87 | ### Application initialization 88 | 89 | Sets up the ELF execution environment and directly jumps to the application 90 | entry address. 91 | 92 | ## License 93 | 94 | SPDX-License-Identifier: BSD-3-Clause 95 | 96 | See [LICENSE](LICENSE) for the full license text. 97 | -------------------------------------------------------------------------------- /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 | } 14 | 15 | if 'QCOM_LLVM' in os.environ: 16 | env_vars['QCOM_LLVM'] = os.environ['QCOM_LLVM'] 17 | 18 | if 'LLVM' in os.environ: 19 | env_vars['LLVM'] = os.environ['LLVM'] 20 | 21 | env = Environment(tools={}, SCANNERS=[], BUILDERS={}, ENV=env_vars) 22 | configure.SConsBuild(env, Builder, Action, arguments=SCons.Script.ARGUMENTS)() 23 | -------------------------------------------------------------------------------- /arch/armv8/build.conf: -------------------------------------------------------------------------------- 1 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | 5 | arch_include aarch64 include 6 | 7 | sub_directory src 8 | -------------------------------------------------------------------------------- /arch/armv8/include/arch_def.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | typedef uint64_t register_t; 6 | 7 | typedef int64_t sregister_t; 8 | 9 | // 4K page size 10 | #define PAGE_SIZE (4096) 11 | -------------------------------------------------------------------------------- /arch/armv8/include/arch_reloc.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Architecture relocation types 6 | #define R_AARCH64_NONE 0 7 | #define R_AARCH64_RELATIVE 1027 8 | 9 | #define ARCH_CAN_PATCH(r_info) \ 10 | (((R_TYPE(r_info) == R_AARCH64_NONE) || \ 11 | (R_TYPE(r_info) == R_AARCH64_RELATIVE)) && \ 12 | (R_SYM(r_info) == 0)) 13 | -------------------------------------------------------------------------------- /arch/armv8/include/asm/asm_defs.inc: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | .macro vector vector_name:req 8 | function \vector_name, align=128, section=nosection 9 | .endm 10 | 11 | .macro vector_end vector_name:req 12 | function_end \vector_name 13 | .if (. - \vector_name) > 0x80 14 | .error #\vector_name is too big 15 | .endif 16 | .endm 17 | 18 | .macro abs64 reg:req val64:req 19 | movz \reg, (\val64) & 0xffff 20 | .ifne ((\val64) >> 16) & 0xffff 21 | movk \reg, ((\val64) >> 16) & 0xffff, LSL 16 22 | .endif 23 | .ifne ((\val64) >> 32) & 0xffff 24 | movk \reg, ((\val64) >> 32) & 0xffff, LSL 32 25 | .endif 26 | .ifne ((\val64) >> 48) & 0xffff 27 | movk \reg, ((\val64) >> 48) & 0xffff, LSL 48 28 | .endif 29 | .endm 30 | 31 | .macro adrl reg:req sym:req 32 | adrp \reg, \sym 33 | add \reg, \reg, :lo12:\sym 34 | .endm 35 | 36 | .macro get_tls_base , tls_base:req 37 | mrs \tls_base, TPIDR_EL1 38 | .endm 39 | 40 | // Get the address of a thread-local symbol 41 | .macro adr_threadlocal, reg:req, sym:req, tls_base 42 | .ifb \tls_base 43 | mrs \reg, TPIDR_EL1 44 | add \reg, \reg, :tprel_hi12:\sym 45 | .else 46 | add \reg, \tls_base, :tprel_hi12:\sym 47 | .endif 48 | add \reg, \reg, :tprel_lo12_nc:\sym 49 | .endm 50 | -------------------------------------------------------------------------------- /arch/armv8/include/asm/cpu.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Miscellaneous definitions describing the CPU implementation. 6 | 7 | // The size in address bits of a line in the innermost visible data cache. 8 | #define CPU_L1D_LINE_BITS 6U 9 | 10 | // The size in address bits of the CPU's DC ZVA block. This is nearly always 11 | // the same as CPU_L1D_LINE_BITS. 12 | #define CPU_DCZVA_BITS 6U 13 | 14 | // The largest difference between the source and destination pointers during 15 | // the optimised memcpy() for this CPU. This is here because it might depend 16 | // on CPU_L1D_LINE_BITS in some implementations. 17 | #define CPU_MEMCPY_STRIDE 256U 18 | -------------------------------------------------------------------------------- /arch/armv8/include/asm/device.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // The hypervisor cannot easily trap load and store instructions that update 6 | // their base registers. So, for devices that might be virtualised, we must 7 | // use asm directives to generate non-writeback load and store instructions 8 | // for relaxed accesses. 9 | // 10 | // This is not necessary for acquire / release accesses because there are no 11 | // writeback forms of those in AArch64. 12 | 13 | // clang-format off 14 | #define device_load_relaxed(p) _Generic( \ 15 | (p), \ 16 | _Atomic int8_t *: device_load8_relaxed, \ 17 | _Atomic uint8_t *: device_load8_relaxed, \ 18 | _Atomic uint16_t *: device_load16_relaxed, \ 19 | _Atomic int16_t *: device_load16_relaxed, \ 20 | _Atomic uint32_t *: device_load32_relaxed, \ 21 | _Atomic int32_t *: device_load32_relaxed, \ 22 | _Atomic uint64_t *: device_load64_relaxed, \ 23 | _Atomic int64_t *: device_load64_relaxed)(p) 24 | 25 | #define device_store_relaxed(p, v) _Generic( \ 26 | (p), \ 27 | _Atomic int8_t *: device_store8_relaxed, \ 28 | _Atomic uint8_t *: device_store8_relaxed, \ 29 | _Atomic uint16_t *: device_store16_relaxed, \ 30 | _Atomic int16_t *: device_store16_relaxed, \ 31 | _Atomic uint32_t *: device_store32_relaxed, \ 32 | _Atomic int32_t *: device_store32_relaxed, \ 33 | _Atomic uint64_t *: device_store64_relaxed, \ 34 | _Atomic int64_t *: device_store64_relaxed)(p, v) 35 | // clang-format off 36 | 37 | static inline __attribute__((always_inline)) uint8_t 38 | device_load8_relaxed(_Atomic uint8_t *p) 39 | { 40 | uint8_t ret; 41 | __asm__ volatile("ldrb %w0, %1" : "=r"(ret) : "m"(*p)); 42 | return ret; 43 | } 44 | 45 | static inline __attribute__((always_inline)) uint16_t 46 | device_load16_relaxed(_Atomic uint16_t *p) 47 | { 48 | uint16_t ret; 49 | __asm__ volatile("ldrh %w0, %1" : "=r"(ret) : "m"(*p)); 50 | return ret; 51 | } 52 | 53 | static inline __attribute__((always_inline)) uint32_t 54 | device_load32_relaxed(_Atomic uint32_t *p) 55 | { 56 | uint32_t ret; 57 | __asm__ volatile("ldr %w0, %1" : "=r"(ret) : "m"(*p)); 58 | return ret; 59 | } 60 | 61 | static inline __attribute__((always_inline)) uint64_t 62 | device_load64_relaxed(_Atomic uint64_t *p) 63 | { 64 | uint64_t ret; 65 | __asm__ volatile("ldr %0, %1" : "=r"(ret) : "m"(*p)); 66 | return ret; 67 | } 68 | 69 | static inline __attribute__((always_inline)) void 70 | device_store8_relaxed(_Atomic uint8_t *p, uint8_t v) 71 | { 72 | __asm__ volatile("strb %w1, %0" : "=m"(*p) : "rz"(v)); 73 | } 74 | 75 | static inline __attribute__((always_inline)) void 76 | device_store16_relaxed(_Atomic uint16_t *p, uint16_t v) 77 | { 78 | __asm__ volatile("strh %w1, %0" : "=m"(*p) : "rz"(v)); 79 | } 80 | 81 | static inline __attribute__((always_inline)) void 82 | device_store32_relaxed(_Atomic uint32_t *p, uint32_t v) 83 | { 84 | __asm__ volatile("str %w1, %0" : "=m"(*p) : "rz"(v)); 85 | } 86 | 87 | static inline __attribute__((always_inline)) void 88 | device_store64_relaxed(_Atomic uint64_t *p, uint64_t v) 89 | { 90 | __asm__ volatile("str %1, %0" : "=m"(*p) : "rz"(v)); 91 | } 92 | -------------------------------------------------------------------------------- /arch/armv8/include/asm/event.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define asm_event_wait(p) __asm__ volatile("wfe" ::"m"(*p)) 6 | -------------------------------------------------------------------------------- /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 | #define WORKAROUND_UNEXPECTED_ACTIVE_IRQ 1 6 | 7 | static inline __attribute__((always_inline)) void 8 | asm_wait_for_interrupt(char *asm_ordering) 9 | { 10 | #if defined(WORKAROUND_UNEXPECTED_ACTIVE_IRQ) && \ 11 | WORKAROUND_UNEXPECTED_ACTIVE_IRQ 12 | uint64_t rpr; 13 | __asm__("isb; mrs %[r], ICC_RPR_EL1" 14 | : "+m"(*asm_ordering), [r] "=r"(rpr)); 15 | if (__builtin_expect((rpr != 0xffU), 0)) { 16 | volatile static count_t rpr_non_idle_count = 0U; 17 | // We have a stray active priority. Log and clear it. 18 | rpr_non_idle_count++; 19 | __asm__ volatile("msr ICC_AP1R0_EL1, xzr; isb" 20 | : "+m"(*asm_ordering)); 21 | } 22 | #endif 23 | 24 | __asm__ volatile("dsb ish; wfi; isb" : "+m"(*asm_ordering)); 25 | } 26 | 27 | static inline __attribute__((always_inline)) void 28 | asm_wait_for_event(int *asm_ordering) 29 | { 30 | __asm__ volatile("dsb ish; wfe; isb" : "+m"(*asm_ordering)); 31 | } 32 | 33 | static inline __attribute__((always_inline)) bool 34 | asm_interrupt_pending(char *asm_ordering) 35 | { 36 | uint64_t isr; 37 | __asm__ volatile("mrs %[r], ISR_EL1" 38 | : "+m"(*asm_ordering), [r] "=r"(isr)); 39 | return (isr & 0x80U) != 0U; 40 | } 41 | -------------------------------------------------------------------------------- /arch/armv8/include/asm/prefetch.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | -------------------------------------------------------------------------------- /arch/armv8/include/asm/unistd.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define SYS_ioctl 29 6 | #define SYS_openat 56 7 | #define SYS_close 57 8 | #define SYS_writev 66 9 | #define SYS_ppoll 73 10 | #define SYS_exit 93 11 | #define SYS_exit_group 94 12 | #define SYS_set_tid_address 96 13 | #define SYS_clock_nanosleep 115 14 | #define SYS_tkill 130 15 | #define SYS_brk 214 16 | -------------------------------------------------------------------------------- /arch/armv8/include/el1.inc: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define TRAP_FRAME_FULL_SIZE (18 * 16) 6 | #define TRAP_FRAME_SYSCALL_SIZE (11 * 16) 7 | #define TRAP_FRAME_IRQ_SIZE (12 * 16) 8 | 9 | // Use this macro ONLY if jumping to panic afterwards. 10 | // 11 | // There is no macro to return from a full stack frame, but dump_trap_frame() 12 | // prints it to the console. 13 | .macro save_runtime_context_full 14 | // Check for stack overflow, and branch to handle_stack_fault 15 | // FIXME: 16 | 17 | // SP (SP_EL1) points to the kernel stack 18 | sub sp, sp, TRAP_FRAME_FULL_SIZE 19 | 20 | stp x0, x1, [sp, 0 * 16] 21 | stp x2, x3, [sp, 1 * 16] 22 | stp x4, x5, [sp, 2 * 16] 23 | stp x6, x7, [sp, 3 * 16] 24 | stp x8, x9, [sp, 4 * 16] 25 | stp x10, x11, [sp, 5 * 16] 26 | stp x12, x13, [sp, 6 * 16] 27 | stp x14, x15, [sp, 7 * 16] 28 | stp x16, x17, [sp, 8 * 16] 29 | stp x18, x19, [sp, 9 * 16] 30 | stp x20, x21, [sp, 10 * 16] 31 | stp x22, x23, [sp, 11 * 16] 32 | stp x24, x25, [sp, 12 * 16] 33 | stp x26, x27, [sp, 13 * 16] 34 | stp x28, x30, [sp, 14 * 16] 35 | mrs x0, SPSR_EL1 36 | mrs x1, ESR_EL1 37 | stp x0, x1, [sp, 15 * 16] 38 | mrs x0, SP_EL0 39 | add x1, sp, TRAP_FRAME_FULL_SIZE // original SP_EL1 40 | stp x0, x1, [sp, 16 * 16] 41 | mrs x1, ELR_EL1 42 | stp x29, x1, [sp, 17 * 16] 43 | add x29, sp, 17 * 16 44 | .endm 45 | 46 | // Save an exception stack frame containing fp, lr, spsr, elr, and x1-x18. 47 | // The caller should have decremented SP already. 48 | .macro save_runtime_context_x1_x18 49 | // This macro must not touch any of the syscall argument registers 50 | // x0-x7 other than to save them. Also, ELR_EL1 needs to be saved via 51 | // x30 so we can use the hint-encoded PACIASP instruction, which 52 | // executes as NOP on older CPUs. 53 | stp x17, x18, [sp, 1 * 16] 54 | stp x1, x2, [sp, 2 * 16] 55 | stp x3, x4, [sp, 3 * 16] 56 | mrs x17, SPSR_EL1 57 | stp x5, x6, [sp, 4 * 16] 58 | stp x30, x17, [sp, 5 * 16] 59 | stp x7, x8, [sp, 6 * 16] 60 | mrs x30, ELR_EL1 61 | stp x9, x10, [sp, 7 * 16] 62 | paciasp 63 | stp x11, x12, [sp, 8 * 16] 64 | stp x13, x14, [sp, 9 * 16] 65 | stp x15, x16, [sp, 10 * 16] 66 | stp x29, x30, [sp] 67 | mov x29, sp 68 | .endm 69 | 70 | // Restore an exception stack frame saved by save_runtime_context_x1_x18. 71 | // The caller should increment SP afterwards. 72 | .macro restore_runtime_context_x1_x18 73 | // ELR_EL1 needs to be restored via x30 so we can use the hint-encoded 74 | // AUTIASP instruction, which executes as NOP on older CPUs. 75 | ldp x29, x30, [sp] 76 | ldp x17, x18, [sp, 1 * 16] 77 | ldp x1, x2, [sp, 2 * 16] 78 | autiasp 79 | ldp x3, x4, [sp, 3 * 16] 80 | msr ELR_EL1, x30 81 | ldp x5, x6, [sp, 4 * 16] 82 | ldp x30, x15, [sp, 5 * 16] 83 | ldp x7, x8, [sp, 6 * 16] 84 | ldp x9, x10, [sp, 7 * 16] 85 | ldp x11, x12, [sp, 8 * 16] 86 | msr SPSR_EL1, x15 87 | ldp x13, x14, [sp, 9 * 16] 88 | ldp x15, x16, [sp, 10 * 16] 89 | .endm 90 | 91 | .macro save_runtime_context_syscall 92 | sub sp, sp, TRAP_FRAME_SYSCALL_SIZE 93 | save_runtime_context_x1_x18 94 | // x0 is not saved because it is used for the syscall return value. 95 | .endm 96 | 97 | .macro restore_runtime_context_syscall 98 | restore_runtime_context_x1_x18 99 | // x0 is not restored because it contains the syscall return value. 100 | add sp, sp, TRAP_FRAME_SYSCALL_SIZE 101 | .endm 102 | 103 | .macro save_runtime_context_irq 104 | sub sp, sp, TRAP_FRAME_IRQ_SIZE 105 | save_runtime_context_x1_x18 106 | stp x0, xzr, [sp, 11 * 16] 107 | .endm 108 | 109 | .macro restore_runtime_context_irq 110 | restore_runtime_context_x1_x18 111 | ldr x0, [sp, 11 * 16] 112 | add sp, sp, TRAP_FRAME_IRQ_SIZE 113 | .endm 114 | 115 | .macro panic_asm, panic_str:req 116 | .pushsection .rodata.panic_str\@, "aMS", @progbits, 1 117 | local panic_str\@: 118 | .asciz "\panic_str" 119 | .popsection 120 | adr x0, LOCAL(panic_str\@) 121 | bl panic 122 | .endm 123 | -------------------------------------------------------------------------------- /arch/armv8/src/arch_syscall.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include "arch_def.h" 6 | 7 | #pragma clang diagnostic push 8 | #pragma clang diagnostic ignored "-Wstrict-prototypes" 9 | typedef register_t (*const sys_call_ptr_t)(register_t arg0, register_t arg1, 10 | register_t arg2, register_t arg3, 11 | register_t arg4); 12 | 13 | #pragma clang diagnostic pop 14 | 15 | extern sys_call_ptr_t aarch64_sys_call_table[NR_syscall_max + 1]; 16 | 17 | register_t 18 | sys_set_tid_address_wrapper(register_t arg0, register_t arg1, register_t arg2, 19 | register_t arg3, register_t arg4); 20 | 21 | register_t 22 | sys_ppoll_wrapper(register_t arg0, register_t arg1, register_t arg2, 23 | register_t arg3, register_t arg4); 24 | 25 | register_t 26 | sys_openat_wrapper(register_t arg0, register_t arg1, register_t arg2, 27 | register_t arg3, register_t arg4); 28 | 29 | register_t 30 | sys_clock_nanosleep_wrapper(register_t arg0, register_t arg1, register_t arg2, 31 | register_t arg3, register_t arg4); 32 | 33 | register_t 34 | sys_tkill_wrapper(register_t arg0, register_t arg1, register_t arg2, 35 | register_t arg3, register_t arg4); 36 | 37 | register_t 38 | sys_exit_group_wrapper(register_t arg0, register_t arg1, register_t arg2, 39 | register_t arg3, register_t arg4); 40 | 41 | noreturn register_t 42 | sys_exit_wrapper(register_t arg0, register_t arg1, register_t arg2, 43 | register_t arg3, register_t arg4); 44 | 45 | register_t 46 | sys_brk_wrapper(register_t arg0, register_t arg1, register_t arg2, 47 | register_t arg3, register_t arg4); 48 | 49 | register_t 50 | sys_ioctl_wrapper(register_t arg0, register_t arg1, register_t arg2, 51 | register_t arg3, register_t arg4); 52 | 53 | register_t 54 | sys_writev_wrapper(register_t arg0, register_t arg1, register_t arg2, 55 | register_t arg3, register_t arg4); 56 | 57 | register_t 58 | sys_close_wrapper(register_t arg0, register_t arg1, register_t arg2, 59 | register_t arg3, register_t arg4); 60 | -------------------------------------------------------------------------------- /arch/armv8/src/boot.S: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | #include 7 | 8 | #define BOOT_STACK_SIZE (1024) 9 | #define BOOT_STACK_CANARY 0xeb3a23d54a5267ab 10 | 11 | #define CPACR_EL1_FPEN_MASK (0x3UL << 20) 12 | #define CPACR_EL1_FPEN_ENABLE_EL1_SIMD (0x1UL << 20) 13 | #define SCTLR_EL1_ENIA_MASK (0x1U << 31) 14 | 15 | #define SMCCC_FAST_CALL_SHIFT 31 16 | #define SMCCC_64BIT_CALL_SHIFT 30 17 | #define SMCCC_SERVICE_SHIFT 24 18 | #define SMCCC_FUNCTION_SHIFT 0 19 | 20 | #define SMCCC_SERVICE_ARM 0 21 | #define SMCCC_SERVICE_CPU 1 22 | #define SMCCC_SERVICE_SIP 2 23 | #define SMCCC_SERVICE_OEM 3 24 | #define SMCCC_SERVICE_STANDARD_SECURE 4 25 | #define SMCCC_SERVICE_STANDARD_HYP 5 26 | #define SMCCC_SERVICE_VENDOR_HYP 6 27 | 28 | #define SMCCC_FUNCTION_ID(fast, call64, service, function) \ 29 | ((((fast) != 0) << SMCCC_FAST_CALL_SHIFT) | \ 30 | (((call64) != 0) << SMCCC_64BIT_CALL_SHIFT) | \ 31 | ((service) << SMCCC_SERVICE_SHIFT) | \ 32 | ((function) << SMCCC_FUNCTION_SHIFT)) 33 | 34 | .section .text.boot 35 | function _start section=nosection 36 | // Entry arguments: 37 | // x0 = boot_env_data 38 | 39 | // Save the entry arguments 40 | adr x9, env_data 41 | str x0, [x9] 42 | 43 | // enable floating point and SIMD register access 44 | mrs x0, CPACR_EL1 45 | bic x0, x0, CPACR_EL1_FPEN_MASK 46 | orr x0, x0, CPACR_EL1_FPEN_ENABLE_EL1_SIMD 47 | msr CPACR_EL1, x0 48 | isb 49 | 50 | // assert current EL is el1 51 | mrs x0, CurrentEL 52 | cmp x0, (0x1UL << 2) 53 | bne LOCAL(hang) 54 | // Set Vector Base Address 55 | adr x1, vectors_aarch64 56 | msr VBAR_EL1, x1 57 | 58 | // use SP_EL1 59 | msr SPSel, 1 60 | 61 | // set initial boot stack 62 | adrl x0, aarch64_boot_stack_bottom 63 | add sp, x0, BOOT_STACK_SIZE 64 | 65 | // Set a canary at the end of the stack 66 | abs64 x1, BOOT_STACK_CANARY 67 | stp x1, x1, [x0] 68 | 69 | // relocate ourself first before calling C 70 | adrl x0, _DYNAMIC 71 | adr x9, env_data 72 | ldr x1, [x9] 73 | bl rel_fixup 74 | 75 | // Set up the PAuth IA key (the only one currently used) and enable 76 | // PAuth, if the CPU supports it. Failure to obtain random data is 77 | // not tolerated. 78 | mrs x0, ID_AA64ISAR1_EL1 79 | tst x0, 0xff0 // API and APA fields; both 0 means no PAC support 80 | b.eq LOCAL(pac_done) 81 | 82 | mov x0, 16 // num_bytes: 16 bytes / 128-bits 83 | mov x1, 0 // res0 84 | // gunyah_hyp_prng_get_entropy(0x6057, num_bytes, res0) 85 | hvc 0x6057 86 | cbnz x0, LOCAL(hang) 87 | 88 | bfi x1, x2, 32, 32 89 | bfi x3, x4, 32, 32 90 | 91 | .arch armv8.3-a // LLVM doesn't understand .arch_extension pauth yet 92 | msr APIAKeyLo_EL1, x1 93 | msr APIAKeyHi_EL1, x3 94 | 95 | mrs x0, SCTLR_EL1 96 | orr x0, x0, SCTLR_EL1_ENIA_MASK 97 | msr SCTLR_EL1, x0 98 | isb 99 | .arch armv8.2-a 100 | local pac_done: 101 | 102 | // Init runtime 103 | bl runtime_init 104 | 105 | // elf_setup returns application entry address 106 | // returned x0 is app entry. It will blr to that entry after 107 | // everything is done 108 | bl elf_setup 109 | 110 | // Check boot stack canary 111 | adrl x10, aarch64_boot_stack_bottom 112 | abs64 x11, BOOT_STACK_CANARY 113 | ldp x12, x13, [x10] 114 | cmp x11, x12 115 | ccmp x11, x13, #0, eq 116 | b.ne LOCAL(boot_stack_overflow) 117 | 118 | // setup application stack 119 | // Runtime exceptions (syscalls etc) and apps (including resource manager) 120 | // would use the same stack. 121 | adr x9, app_stack 122 | ldr x10, [x9] 123 | mov sp, x10 124 | 125 | // Enable IRQs 126 | msr DAIFClr, 0x7 127 | 128 | // start application 129 | blr x0 130 | 131 | // Application should not return here; it should call exit() instead. 132 | msr DAIFSet, 0x7 133 | panic_asm "Returned from app entry" 134 | 135 | local boot_stack_overflow: 136 | panic_asm "Detected boot stack overflow" 137 | local hang: 138 | // FIXME: 139 | wfe 140 | b LOCAL(hang) 141 | function_end _start 142 | 143 | .global aarch64_boot_stack_bottom 144 | .section .bss.boot_stack, "aw", @nobits 145 | .balign 16 146 | // This stack is used by runtime init. It must be large enough to run 147 | // all the initialization code. After this the runtime will use the 148 | // application stack. 149 | aarch64_boot_stack_bottom: 150 | .space BOOT_STACK_SIZE 151 | 152 | .section ".data.elf_parameters", "aw" 153 | .align 8 154 | .global env_data 155 | env_data: 156 | .space 8 157 | .global app_stack 158 | app_stack: 159 | .space 8 160 | -------------------------------------------------------------------------------- /arch/armv8/src/build.conf: -------------------------------------------------------------------------------- 1 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | 5 | arch_source aarch64 boot.S syscall.c vectors.S memcpy.S memset.S string.c 6 | arch_source aarch64 gicv3.c generic_timer.c 7 | 8 | # FIXME: 9 | configs PLATFORM_NUM_IRQS=1020U 10 | configs PLATFORM_TIMER_IRQ=27U 11 | configs PLATFORM_IRQ_DEV_PATH=\"/dev/gicv3\" 12 | configs PLATFORM_CONSOLE_DEV_PATH=\"/dev/console\" 13 | configs PLATFORM_EXIT_DEV_PATH=\"/dev/exit\" 14 | -------------------------------------------------------------------------------- /arch/armv8/src/generic_timer.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 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #define CNTV_CTL_ISTATUS (1U << 2) 16 | #define CNTV_CTL_IMASK (1U << 1) 17 | #define CNTV_CTL_ENABLE (1U << 0) 18 | 19 | static char timer_ordering; 20 | 21 | static void 22 | write_cntv_ctl(uint64_t cntv_ctl) 23 | { 24 | __asm__ volatile("msr CNTV_CTL_EL0, %[r]" 25 | : "+m"(timer_ordering) 26 | : [r] "r"(cntv_ctl)); 27 | } 28 | 29 | void 30 | platform_timer_init(uint64_t timer_freq) 31 | { 32 | uint64_t cntfrq; 33 | __asm__ volatile("mrs %[r], CNTFRQ_EL0" : [r] "=r"(cntfrq)); 34 | assert(cntfrq == timer_freq); 35 | 36 | uint64_t cntkctl = 0U; 37 | __asm__ volatile("msr CNTKCTL_EL1, %[r]" 38 | : "+m"(timer_ordering) 39 | : [r] "r"(cntkctl)); 40 | 41 | write_cntv_ctl(CNTV_CTL_IMASK); 42 | 43 | (void)platform_irq_set_trigger(PLATFORM_TIMER_IRQ, 44 | IRQ_TRIGGER_LEVEL_HIGH); 45 | platform_irq_enable(PLATFORM_TIMER_IRQ); 46 | } 47 | 48 | void 49 | platform_timer_set_timeout(uint64_t ticks) 50 | { 51 | __asm__ volatile("msr CNTV_CVAL_EL0, %[r]" 52 | : "+m"(timer_ordering) 53 | : [r] "r"(ticks)); 54 | 55 | write_cntv_ctl(CNTV_CTL_ENABLE); 56 | __asm__ volatile("isb" : "+m"(timer_ordering)); 57 | } 58 | 59 | void 60 | platform_timer_cancel_timeout(void) 61 | { 62 | write_cntv_ctl(CNTV_CTL_IMASK); 63 | __asm__ volatile("isb" : "+m"(timer_ordering)); 64 | } 65 | 66 | uint64_t 67 | platform_timer_get_current_ticks(void) 68 | { 69 | uint64_t ticks; 70 | 71 | __asm__ volatile("mrs %[r], CNTVCT_EL0" 72 | : "+m"(timer_ordering), [r] "=r"(ticks)); 73 | 74 | return ticks; 75 | } 76 | -------------------------------------------------------------------------------- /arch/armv8/src/gicv3.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 | 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #define GICD_SIZE 0x10000U 21 | #define GICR_SIZE 0x40000U 22 | 23 | // Set to 0 to use GICD_I[SC]PENDR writes; 1 to use SETSPI / CLRSPI 24 | #define PLATFORM_IRQ_USE_MSI 0 25 | 26 | // FIXME: should be generated into include/guest_types.h 27 | #define VIRQ_INVALID ~(virq_t)0U 28 | 29 | extern rt_env_data_t *env_data; 30 | 31 | struct gicd_s { 32 | uint32_t _Atomic ctlr; 33 | uint32_t _Atomic typer; 34 | uint32_t _Atomic iidr; 35 | uint8_t pad_to_statusr_[4]; 36 | uint32_t _Atomic statusr; 37 | uint8_t pad_to_setspi_nsr_[44]; 38 | uint32_t _Atomic setspi_nsr; 39 | uint8_t pad_to_clrspi_nsr_[4]; 40 | uint32_t _Atomic clrspi_nsr; 41 | // ignore {set,clr}spi_sr which are WI when DS=1 42 | uint8_t pad_to_igroupr_[52]; 43 | uint32_t _Atomic igroupr[32]; 44 | uint32_t _Atomic isenabler[32]; 45 | uint32_t _Atomic icenabler[32]; 46 | uint32_t _Atomic ispendr[32]; 47 | uint32_t _Atomic icpendr[32]; 48 | uint32_t _Atomic isactiver[32]; 49 | uint32_t _Atomic icactiver[32]; 50 | uint8_t _Atomic ipriorityr[1020]; 51 | // Ignore itargetsr 52 | uint8_t pad_to_icfgr_[1028]; 53 | uint32_t _Atomic icfgr[64]; 54 | uint32_t _Atomic igrpmodr[32]; 55 | // Ignore nascr, sgir, 56 | // {c,s}pendsgir, extended regs 57 | uint8_t pad_to_irouter_[21376]; 58 | uint64_t _Atomic irouter[988]; 59 | // Ignore extended irouter 60 | uint8_t pad_to_end_[32800]; 61 | }; 62 | 63 | struct gicr_s { 64 | // RD_base 65 | uint32_t _Atomic ctlr; 66 | uint32_t _Atomic iidr; 67 | uint64_t _Atomic typer; 68 | uint32_t _Atomic statusr; 69 | uint32_t _Atomic waker; 70 | // Ignore LPI regs 71 | uint8_t pad_to_sgi_base_[65512]; 72 | // SGI_base 73 | uint8_t pad_to_igroupr0_[128]; 74 | // Extended regs are ignored 75 | uint32_t _Atomic igroupr0; 76 | uint8_t pad_to_isenabler0_[124]; 77 | uint32_t _Atomic isenabler0; 78 | uint8_t pad_to_icenabler0_[124]; 79 | uint32_t _Atomic icenabler0; 80 | uint8_t pad_to_ispendr0_[124]; 81 | uint32_t _Atomic ispendr0; 82 | uint8_t pad_to_icpendr0_[124]; 83 | uint32_t _Atomic icpendr0; 84 | uint8_t pad_to_isactiver0_[124]; 85 | uint32_t _Atomic isactiver0; 86 | uint8_t pad_to_icactiver0_[124]; 87 | uint32_t _Atomic icactiver0; 88 | uint8_t pad_to_ipriorityr_[124]; 89 | uint8_t _Atomic ipriorityr[32]; 90 | uint8_t pad_to_icfgr0_[2016]; 91 | uint32_t _Atomic icfgr0; 92 | uint32_t _Atomic icfgr1; 93 | uint8_t pad_to_igrpmodr0_[248]; 94 | uint32_t _Atomic igrpmodr0; 95 | // Ignore nsacr 96 | uint8_t pad_to_vlpi_base_[62204]; 97 | // VLPI_base ignored 98 | uint8_t pad_to_end_[131072]; 99 | }; 100 | 101 | static_assert(sizeof(struct gicd_s) == GICD_SIZE, "gicd not sized correctly"); 102 | static_assert(sizeof(struct gicr_s) == GICR_SIZE, "gicr not sized correctly"); 103 | 104 | #define GIC_SGI_BASE 0U 105 | #define GIC_SGI_NUM 16U 106 | #define GIC_SGI_END (GIC_SGI_BASE + GIC_SGI_NUM) 107 | #define GIC_PPI_BASE 16U 108 | #define GIC_PPI_NUM 16U 109 | #define GIC_PPI_END (GIC_PPI_BASE + GIC_PPI_NUM) 110 | #define GIC_SPI_BASE 32U 111 | #define GIC_SPI_NUM 988U 112 | #define GIC_SPI_END (GIC_SPI_BASE + GIC_SPI_NUM) 113 | 114 | static_assert(GIC_SPI_END >= PLATFORM_NUM_IRQS, "Bad num irqs"); 115 | 116 | #define GIC_PRIORITY_DEFAULT 0xA0U 117 | 118 | #define GICD_CTLR_RWP (1U << 31) 119 | #define GICD_CTLR_ARE (1U << 4) 120 | #define GICD_CTLR_ENABLEGRP1 (1U << 1) 121 | 122 | #define GICR_CTLR_RWP (1U << 3) 123 | 124 | #define ICC_CTLR_EOIMODE (1U << 1) 125 | 126 | #define MPIDR_EL1_AFF0123_MASK (0xff00ffffffU) 127 | 128 | #define GICD_ENABLE_GET_N(x) ((x) >> 5) 129 | #define GIC_ENABLE_BIT(x) ((uint32_t)1U << (index_t)(x)) 130 | 131 | static char gic_ordering; 132 | 133 | static struct gicd_s *gicd; 134 | CPULOCAL_DECLARE_STATIC(struct gicr_s *, gicr); 135 | 136 | static uint32_t 137 | gicd_wait_for_write(void) 138 | { 139 | atomic_thread_fence(memory_order_acquire); 140 | uint32_t ctlr = device_load_relaxed(&gicd->ctlr); 141 | 142 | while ((ctlr & GICD_CTLR_RWP) != 0U) { 143 | ctlr = device_load_relaxed(&gicd->ctlr); 144 | } 145 | 146 | return ctlr; 147 | } 148 | 149 | static void 150 | gicr_wait_for_write(struct gicr_s *gicr) 151 | { 152 | uint32_t ctlr = device_load_relaxed(&gicr->ctlr); 153 | 154 | while ((ctlr & GICR_CTLR_RWP) != 0U) { 155 | ctlr = device_load_relaxed(&gicr->ctlr); 156 | } 157 | } 158 | 159 | #define ASM_MRS_MPIDR_EL1(a) __asm__("mrs %0, MPIDR_EL1" : "=r"((a))) 160 | #define ASM_MSR_ICC_SRE_EL1(a) \ 161 | __asm__ volatile("msr ICC_SRE_EL1, %0" ::"r"((a))) 162 | #define ASM_MSR_ICC_PMR_EL1(a) \ 163 | __asm__ volatile("msr ICC_PMR_EL1, %0" ::"r"((a))) 164 | #define ASM_MSR_ICC_BPR1_EL1(a) \ 165 | __asm__ volatile("msr ICC_BPR1_EL1, %0" ::"r"((a))) 166 | #define ASM_MRS_ICC_CTLR_EL1(a) __asm__("mrs %0, ICC_CTLR_EL1" : "=r"((a))) 167 | #define ASM_MSR_ICC_CTLR_EL1(a) __asm__("msr %0, ICC_CTLR_EL1" : "=r"((a))) 168 | #define ASM_MSR_ICC_IGRPEN1_EL1(a) \ 169 | __asm__ volatile("msr ICC_IGRPEN1_EL1, %0" ::"r"((a))) 170 | 171 | void 172 | platform_irq_init(void) 173 | { 174 | // FIXME: 175 | count_t num_irqs = PLATFORM_NUM_IRQS; 176 | 177 | // FIXME: map if using page table & not already mapped 178 | gicd = (struct gicd_s *)env_data->gicd_base; 179 | 180 | // FIXME: do proper typer lookup 181 | for (cpu_index_t i = 0U; cpulocal_index_valid(i); i++) { 182 | CPULOCAL_BY_INDEX(gicr, i) = 183 | ((struct gicr_s *)env_data->gicr_base) + i; 184 | } 185 | 186 | // Disable distributor 187 | uint32_t ctlr = 0U; 188 | device_store_relaxed(&gicd->ctlr, ctlr); 189 | ctlr = gicd_wait_for_write(); 190 | 191 | // Enable affinity routing 192 | ctlr |= GICD_CTLR_ARE; 193 | device_store_relaxed(&gicd->ctlr, ctlr); 194 | ctlr = gicd_wait_for_write(); 195 | 196 | // Disable all SPIs 197 | for (index_t i = 1U; i < (num_irqs / 32U); i++) { 198 | device_store_relaxed(&gicd->icenabler[i], 0xffffffffU); 199 | } 200 | ctlr = gicd_wait_for_write(); 201 | 202 | // Set SPI default priority 203 | for (index_t i = GIC_SPI_BASE; i < num_irqs; i++) { 204 | device_store_relaxed(&gicd->ipriorityr[i], 205 | GIC_PRIORITY_DEFAULT); 206 | } 207 | 208 | // Set SPI default trigger as edge 209 | for (index_t i = 2U; i < (num_irqs / 16U); i++) { 210 | device_store_relaxed(&gicd->icfgr[i], 0xaaaaaaaaU); 211 | } 212 | 213 | // Set SPIs as group 1 214 | for (index_t i = 1U; i < (num_irqs / 32U); i++) { 215 | device_store_relaxed(&gicd->igroupr[i], 0xffffffffU); 216 | } 217 | 218 | // Set SPI default route 219 | uint64_t mpidr; 220 | // System Register MPIDR_EL1 must be accessed via MRS/MSR 221 | ASM_MRS_MPIDR_EL1(mpidr); 222 | mpidr &= MPIDR_EL1_AFF0123_MASK; 223 | 224 | for (index_t i = 0U; i < (num_irqs - (index_t)GIC_SPI_BASE); i++) { 225 | device_store_relaxed(&gicd->irouter[i], mpidr); 226 | } 227 | 228 | // Enable Group 1 IRQs 229 | ctlr |= GICD_CTLR_ENABLEGRP1; 230 | device_store_relaxed(&gicd->ctlr, ctlr); 231 | 232 | // FIXME: per vcpu cold init 233 | struct gicr_s *gicr = CPULOCAL(gicr); 234 | 235 | // Disable SGIs/PPIs 236 | device_store_relaxed(&gicr->icenabler0, 0xffffffffU); 237 | gicr_wait_for_write(gicr); 238 | 239 | // Set SGI/PPI default priority 240 | for (index_t i = 0U; i < util_array_size(gicr->ipriorityr); i++) { 241 | device_store_relaxed(&gicr->ipriorityr[i], 242 | GIC_PRIORITY_DEFAULT); 243 | } 244 | 245 | // Set PPI default trigger as level 246 | device_store_relaxed(&gicr->icfgr1, 0U); 247 | 248 | // Set SGI/PPI group 1 249 | device_store_relaxed(&gicr->igroupr0, 0xffffffffU); 250 | 251 | // FIXME: warm init 252 | 253 | // Disable IRQ/FIQ bypass, sysreg enable 254 | uint64_t icc_sre = 0x7U; 255 | // System Register ICC_SRE_EL1 must be accessed via MRS/MSR 256 | ASM_MSR_ICC_SRE_EL1(icc_sre); 257 | 258 | // Allow all priorities 259 | uint64_t icc_pmr = 0xffU; 260 | // System Register ICC_PMR_EL1 must be accessed via MRS/MSR 261 | ASM_MSR_ICC_PMR_EL1(icc_pmr); 262 | 263 | // Prevent preemption during IRQ handling 264 | uint64_t icc_bpr = 0x7U; 265 | // System Register ICC_BPR1_EL1 must be accessed via MRS/MSR 266 | ASM_MSR_ICC_BPR1_EL1(icc_bpr); 267 | 268 | // Clear EOImode 269 | uint64_t icc_ctlr; 270 | // System Register ICC_CTLR_EL1 must be accessed via MRS/MSR 271 | ASM_MRS_ICC_CTLR_EL1(icc_ctlr); 272 | icc_ctlr &= ~(uint64_t)ICC_CTLR_EOIMODE; 273 | // System Register ICC_CTLR_EL1 must be accessed via MRS/MSR 274 | ASM_MSR_ICC_CTLR_EL1(icc_ctlr); 275 | 276 | // Enable group 1 IRQs 277 | uint64_t icc_igrpen1 = 0x1U; 278 | // System Register ICC_IGRPEN1_EL1 must be accessed via MRS/MSR 279 | ASM_MSR_ICC_IGRPEN1_EL1(icc_igrpen1); 280 | } 281 | 282 | void 283 | platform_irq_enable(virq_t irq) 284 | { 285 | if ((irq >= GIC_SGI_BASE) && (irq < GIC_PPI_END)) { 286 | struct gicr_s *gicr = CPULOCAL(gicr); 287 | device_store_release(&gicr->isenabler0, GIC_ENABLE_BIT(irq)); 288 | } else if ((irq >= GIC_SPI_BASE) && (irq < GIC_SPI_END)) { 289 | device_store_release(&gicd->isenabler[GICD_ENABLE_GET_N(irq)], 290 | GIC_ENABLE_BIT(irq)); 291 | } else { 292 | // Ignore others 293 | } 294 | } 295 | 296 | void 297 | platform_irq_disable(virq_t irq) 298 | { 299 | if ((irq >= GIC_SGI_BASE) && (irq < GIC_PPI_END)) { 300 | struct gicr_s *gicr = CPULOCAL(gicr); 301 | device_store_relaxed(&gicr->icenabler0, GIC_ENABLE_BIT(irq)); 302 | (void)gicr_wait_for_write(gicr); 303 | } else if ((irq >= GIC_SPI_BASE) && (irq < GIC_SPI_END)) { 304 | device_store_relaxed(&gicd->icenabler[GICD_ENABLE_GET_N(irq)], 305 | GIC_ENABLE_BIT(irq)); 306 | (void)gicd_wait_for_write(); 307 | } else { 308 | // Ignore others 309 | } 310 | } 311 | 312 | void 313 | platform_irq_assert(virq_t irq) 314 | { 315 | if ((irq >= GIC_SGI_BASE) && (irq < GIC_PPI_END)) { 316 | struct gicr_s *gicr = CPULOCAL(gicr); 317 | device_store_release(&gicr->ispendr0, GIC_ENABLE_BIT(irq)); 318 | } else if ((irq >= GIC_SPI_BASE) && (irq < GIC_SPI_END)) { 319 | #if PLATFORM_IRQ_USE_MSI 320 | device_store_relaxed(&gicd->setspi_nsr, irq); 321 | #else 322 | device_store_relaxed(&gicd->ispendr[GICD_ENABLE_GET_N(irq)], 323 | GIC_ENABLE_BIT(irq)); 324 | #endif 325 | } else { 326 | // Ignore others 327 | } 328 | } 329 | 330 | void 331 | platform_irq_clear(virq_t irq) 332 | { 333 | if ((irq >= GIC_SGI_BASE) && (irq < GIC_PPI_END)) { 334 | struct gicr_s *gicr = CPULOCAL(gicr); 335 | device_store_relaxed(&gicr->icpendr0, GIC_ENABLE_BIT(irq)); 336 | } else if ((irq >= GIC_SPI_BASE) && (irq < GIC_SPI_END)) { 337 | #if PLATFORM_IRQ_USE_MSI 338 | device_store_relaxed(&gicd->clrspi_nsr, irq); 339 | #else 340 | device_store_relaxed(&gicd->icpendr[GICD_ENABLE_GET_N(irq)], 341 | GIC_ENABLE_BIT(irq)); 342 | #endif 343 | } else { 344 | // Ignore others 345 | } 346 | } 347 | 348 | void 349 | platform_irq_disable_all(void) 350 | { 351 | // Disable Group 1 IRQs 352 | uint64_t icc_igrpen1 = 0U; 353 | __asm__ volatile("msr ICC_IGRPEN1_EL1, %0" ::"r"(icc_igrpen1)); 354 | } 355 | 356 | bool 357 | platform_irq_set_trigger(virq_t irq, int trigger) 358 | { 359 | bool edge, valid; 360 | 361 | switch (trigger) { 362 | case IRQ_TRIGGER_LEVEL_HIGH: 363 | edge = false; 364 | valid = true; 365 | break; 366 | case IRQ_TRIGGER_EDGE_RISING: 367 | edge = true; 368 | valid = true; 369 | break; 370 | case IRQ_TRIGGER_LEVEL_LOW: 371 | case IRQ_TRIGGER_EDGE_FALLING: 372 | case IRQ_TRIGGER_EDGE_BOTH: 373 | case IRQ_TRIGGER_MESSAGE: 374 | default: 375 | edge = false; 376 | valid = false; 377 | break; 378 | } 379 | 380 | if (!valid) { 381 | goto out; 382 | } 383 | 384 | if ((irq >= GIC_SGI_BASE) && (irq <= GIC_SGI_END)) { 385 | // SGIs always edge triggered 386 | valid = edge; 387 | } else if ((irq >= GIC_PPI_BASE) && (irq < GIC_PPI_END)) { 388 | struct gicr_s *gicr = CPULOCAL(gicr); 389 | uint32_t isenabler = device_load_relaxed(&gicr->isenabler0); 390 | bool enabled = (isenabler & GIC_ENABLE_BIT(irq)) != 0U; 391 | if (enabled) { 392 | platform_irq_disable(irq); 393 | } 394 | 395 | uint32_t icfgr = device_load_relaxed(&gicr->icfgr1); 396 | uint32_t index = (((uint32_t)irq % 16U) * 2U) + 1U; 397 | if (edge) { 398 | icfgr |= (uint32_t)1U << index; 399 | } else { 400 | icfgr &= ~(1U << index); 401 | } 402 | device_store_relaxed(&gicr->icfgr1, icfgr); 403 | 404 | if (enabled) { 405 | platform_irq_enable(irq); 406 | } 407 | } else if ((irq >= GIC_SPI_BASE) && (irq < GIC_SPI_END)) { 408 | uint32_t isenabler = device_load_relaxed( 409 | &gicd->isenabler[GICD_ENABLE_GET_N(irq)]); 410 | bool enabled = (isenabler & GIC_ENABLE_BIT(irq)) != 0U; 411 | 412 | if (enabled) { 413 | platform_irq_disable(irq); 414 | } 415 | 416 | uint32_t icfgr = device_load_relaxed(&gicd->icfgr[irq / 16]); 417 | uint32_t index = (((uint32_t)irq % 16U) * 2U) + 1U; 418 | if (edge) { 419 | icfgr |= (uint32_t)1U << index; 420 | } else { 421 | icfgr &= ~(1U << index); 422 | } 423 | device_store_relaxed(&gicd->icfgr[irq / 16], icfgr); 424 | 425 | if (enabled) { 426 | platform_irq_enable(irq); 427 | } 428 | } else { 429 | valid = false; 430 | } 431 | 432 | out: 433 | return valid; 434 | } 435 | 436 | virq_t 437 | platform_irq_acknowledge(void) 438 | { 439 | uint64_t icc_iar1; 440 | 441 | __asm__ volatile("mrs %[r], ICC_IAR1_EL1" 442 | : [r] "=r"(icc_iar1), "+m"(gic_ordering)); 443 | 444 | // Ensure IRQ is not handled before it is acknowledged in the GICD 445 | // (as that could cause loss of edge-triggered IRQs, especially SGIs) 446 | __asm__ volatile("isb; dsb sy" ::: "memory"); 447 | 448 | return (icc_iar1 < (uint64_t)GIC_SPI_END) ? (virq_t)icc_iar1 449 | : VIRQ_INVALID; 450 | } 451 | 452 | void 453 | platform_irq_priority_drop(virq_t irq) 454 | { 455 | (void)irq; 456 | } 457 | 458 | void 459 | platform_irq_deactivate(virq_t irq) 460 | { 461 | assert((irq >= 0) && (irq < GIC_SPI_END)); 462 | 463 | // An ISR may have unmasked IRQs, ensure they are masked 464 | __asm__ volatile("msr DAIFSet, 0x7" : "+m"(gic_ordering)); 465 | 466 | // Ensure irq handling is complete 467 | __asm__ volatile("dsb sy; isb" ::: "memory"); 468 | 469 | uint64_t icc_eoir1 = (uint64_t)irq; 470 | __asm__ volatile("msr ICC_EOIR1_EL1, %[r]" 471 | : "+m"(gic_ordering) 472 | : [r] "r"(icc_eoir1)); 473 | } 474 | -------------------------------------------------------------------------------- /arch/armv8/src/memcpy.S: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | #include 7 | 8 | 9 | // memcpy of no more than 31 bytes 10 | function memcpy_below32 11 | // Assume the target is size-aligned and do the largest copies first. 12 | tbz x2, 4, LOCAL(memcpy_below16) 13 | ldp x3, x4, [x1], 16 14 | stp x3, x4, [x0], 16 15 | local memcpy_below16: 16 | tbz x2, 3, 1f 17 | ldr x3, [x1], 8 18 | str x3, [x0], 8 19 | 1: 20 | tbz x2, 2, 1f 21 | ldr w3, [x1], 4 22 | str w3, [x0], 4 23 | 1: 24 | tbz x2, 1, 1f 25 | ldrh w3, [x1], 2 26 | strh w3, [x0], 2 27 | 1: 28 | tbz x2, 0, 1f 29 | ldrb w3, [x1] 30 | strb w3, [x0] 31 | 1: 32 | ret 33 | function_end memcpy_below32 34 | 35 | 36 | // memcpy of at least 31 bytes (i.e. large enough to align up to 16 and do at 37 | // least one 16-byte copy). 38 | function memcpy_alignable 39 | // Align up the target address to 16. We know that the size (x2) is at 40 | // least 16 here, so we don't have to check it during this alignment. 41 | tbz x0, 0, 1f 42 | ldrb w3, [x1], 1 43 | sub x2, x2, 1 44 | strb w3, [x0], 1 45 | 1: 46 | tbz x0, 1, 1f 47 | ldrh w3, [x1], 2 48 | sub x2, x2, 2 49 | strh w3, [x0], 2 50 | 1: 51 | tbz x0, 2, 1f 52 | ldr w3, [x1], 4 53 | sub x2, x2, 4 54 | str w3, [x0], 4 55 | 1: 56 | tbz x0, 3, 1f 57 | ldr x3, [x1], 8 58 | sub x2, x2, 8 59 | str x3, [x0], 8 60 | 1: 61 | // At this point we've copied up to 15 bytes, so we know there are at 62 | // least 16 left. We can safely fall through to _align16. 63 | prfm pldl1strm, [x1] 64 | prfm pstl1keep, [x0] 65 | function_chain memcpy_alignable, memcpy_align16 66 | // Use 128-byte chunks to do the copy, because we have 16 usable 67 | // temporary registers. Copy at least two chunks, so we can unroll the 68 | // loop and store one chunk while loading the next. Note that this is 69 | // slightly suboptimal for the A55, which can only dispatch one load 70 | // and one store each cycle. 71 | #if CPU_MEMCPY_STRIDE != 0x100 72 | #error CPU_MEMCPY_STRIDE is defined incorrectly 73 | #endif 74 | 75 | // The first line was prefetched by the caller; prefetch the rest of 76 | // the first chunk. 77 | .equ LOCAL(offset), 1 << CPU_L1D_LINE_BITS 78 | .rept (0x80 >> CPU_L1D_LINE_BITS) - 1 79 | prfm pldl1strm, [x1, LOCAL(offset)] 80 | prfm pstl1keep, [x0, LOCAL(offset)] 81 | .equ LOCAL(offset), LOCAL(offset) + (1 << CPU_L1D_LINE_BITS) 82 | .endr 83 | 84 | // If we don't have at least two chunks to copy, skip the loop. 85 | cmp x2, 0x100 86 | b.lt LOCAL(memcpy_below256) 87 | 88 | // Prefetch loads for the second chunk. 89 | .rept (0x80 >> CPU_L1D_LINE_BITS) 90 | prfm pldl1strm, [x1, LOCAL(offset)] 91 | .equ LOCAL(offset), LOCAL(offset) + (1 << CPU_L1D_LINE_BITS) 92 | .endr 93 | 94 | // Offset the destination pointer so that we can put an 0x80 byte 95 | // post-index writeback on the last store in the loop. 96 | add x0, x0, 0x70 97 | 98 | // Pre-calculate the size after the minimal copy, so that we can 99 | // decrement it by 0x80 and check for termination in a single 100 | // instruction during the copy loop. 101 | sub x2, x2, 0x100 102 | 103 | // Load the first chunk. The last load will pre-index writeback the 104 | // source pointer, which allows us to do the same on the last load in 105 | // the loop. 106 | ldp x3, x4, [x1, 0x0] 107 | ldp x5, x6, [x1, 0x10] 108 | ldp x7, x8, [x1, 0x20] 109 | ldp x9, x10, [x1, 0x30] 110 | ldp x11, x12, [x1, 0x40] 111 | ldp x13, x14, [x1, 0x50] 112 | ldp x15, x16, [x1, 0x60] 113 | ldp x17, x18, [x1, 0x70]! 114 | 115 | // Loop storing chunk n while loading chunk n+1 116 | local memcpy_chunk128_loop: 117 | // Reduce size by 128 (up to the end of chunk n+2); if it is still 118 | // positive we will continue the loop after chunk n+1 is loaded. 119 | subs x2, x2, 0x80 120 | 121 | // Prefetch loads for chunk n+2 and stores for chunk n+1 122 | .equ LOCAL(offset), 0 123 | .rept (0x80 >> CPU_L1D_LINE_BITS) 124 | prfm pstl1keep, [x0, LOCAL(offset) + 0x10] 125 | prfm pldl1strm, [x1, LOCAL(offset) + 0x90] 126 | .equ LOCAL(offset), LOCAL(offset) + (1 << CPU_L1D_LINE_BITS) 127 | .endr 128 | 129 | // Interleave the stores and loads; increment the pointers by 0x80 130 | // using the last instructions in the loop, to minimise stalls waiting 131 | // for the writebacks. 132 | stp x3, x4, [x0, -0x70] 133 | ldp x3, x4, [x1, 0x10] 134 | stp x5, x6, [x0, -0x60] 135 | ldp x5, x6, [x1, 0x20] 136 | stp x7, x8, [x0, -0x50] 137 | ldp x7, x8, [x1, 0x30] 138 | stp x9, x10, [x0, -0x40] 139 | ldp x9, x10, [x1, 0x40] 140 | stp x11, x12, [x0, -0x30] 141 | ldp x11, x12, [x1, 0x50] 142 | stp x13, x14, [x0, -0x20] 143 | ldp x13, x14, [x1, 0x60] 144 | stp x15, x16, [x0, -0x10] 145 | ldp x15, x16, [x1, 0x70] 146 | stp x17, x18, [x0], 0x80 147 | ldp x17, x18, [x1, 0x80]! 148 | 149 | // If the result of the subs above was non-negative then there's 150 | // another chunk to do 151 | b.ge LOCAL(memcpy_chunk128_loop) 152 | 153 | // Prefetch stores for the chunk after the end of the loop. 154 | .equ LOCAL(offset), 0 155 | .rept (0x80 >> CPU_L1D_LINE_BITS) 156 | prfm pstl1keep, [x0, LOCAL(offset) + 0x10] 157 | .equ LOCAL(offset), LOCAL(offset) + (1 << CPU_L1D_LINE_BITS) 158 | .endr 159 | // The size has an offset of -128 at this point; undo it so we can 160 | // fall through to the smaller copies below. 161 | adds x2, x2, 0x80 162 | 163 | // Store the last chunk. 164 | stp x3, x4, [x0, -0x70] 165 | stp x5, x6, [x0, -0x60] 166 | stp x7, x8, [x0, -0x50] 167 | stp x9, x10, [x0, -0x40] 168 | stp x11, x12, [x0, -0x30] 169 | stp x13, x14, [x0, -0x20] 170 | stp x15, x16, [x0, -0x10] 171 | stp x17, x18, [x0] 172 | 173 | // If there's nothing left to copy, just return. 174 | b.eq LOCAL(return) 175 | 176 | // At this point, we have -16-byte offsets on both pointers; undo them 177 | // so we can fall through. 178 | add x0, x0, 16 179 | add x1, x1, 16 180 | 181 | local memcpy_below256: 182 | // If there is at least one chunk left, copy one chunk. 183 | cmp x2, 0x80 184 | blt LOCAL(memcpy_below128) 185 | 186 | ldp x3, x4, [x1] 187 | ldp x5, x6, [x1, 0x10] 188 | ldp x7, x8, [x1, 0x20] 189 | ldp x9, x10, [x1, 0x30] 190 | stp x3, x4, [x0] 191 | ldp x11, x12, [x1, 0x40] 192 | stp x5, x6, [x0, 0x10] 193 | ldp x13, x14, [x1, 0x50] 194 | stp x7, x8, [x0, 0x20] 195 | ldp x15, x16, [x1, 0x60] 196 | stp x9, x10, [x0, 0x30] 197 | ldp x17, x18, [x1, 0x70] 198 | stp x11, x12, [x0, 0x40] 199 | stp x13, x14, [x0, 0x50] 200 | stp x15, x16, [x0, 0x60] 201 | stp x17, x18, [x0, 0x70] 202 | 203 | add x0, x0, 0x80 204 | add x1, x1, 0x80 205 | sub x2, x2, 0x80 206 | 207 | local memcpy_below128: 208 | // There are up to 7 16-byte blocks left to copy. Calculate jump 209 | // offsets into an ldp sequence and then an stp sequence to copy the 210 | // right number of them. Since there are only 7, we have two extra 211 | // temporary registers: x3 and x4. 212 | adr x3, 1f 213 | lsr x4, x2, 4 214 | add x0, x0, x4, lsl 4 215 | sub x3, x3, x4, lsl 2 216 | add x1, x1, x4, lsl 4 217 | sub x2, x2, x4, lsl 4 218 | br x3 219 | ldp x5, x6, [x1, -0x70] 220 | ldp x7, x8, [x1, -0x60] 221 | ldp x9, x10, [x1, -0x50] 222 | ldp x11, x12, [x1, -0x40] 223 | ldp x13, x14, [x1, -0x30] 224 | ldp x15, x16, [x1, -0x20] 225 | ldp x17, x18, [x1, -0x10] 226 | 1: 227 | adr x3, 1f 228 | sub x3, x3, x4, lsl 2 229 | br x3 230 | stp x5, x6, [x0, -0x70] 231 | stp x7, x8, [x0, -0x60] 232 | stp x9, x10, [x0, -0x50] 233 | stp x11, x12, [x0, -0x40] 234 | stp x13, x14, [x0, -0x30] 235 | stp x15, x16, [x0, -0x20] 236 | stp x17, x18, [x0, -0x10] 237 | 1: 238 | // There must be less than 16 bytes left now. 239 | cbnz x2, LOCAL(memcpy_below16) 240 | local return: 241 | ret 242 | function_end memcpy_align16 243 | 244 | 245 | // Slow memcpy, used by memmove() when the destination overlaps the source and 246 | // is between 1 and CPU_MEMCPY_STRIDE bytes above it. This should never be 247 | // used in the hypervisor so we don't care about its performance. It exists 248 | // only so the libc references to memmove() in the test program don't crash. 249 | function memcpy_bytes 250 | cbz x2, 2f 251 | 1: 252 | subs x2, x2, 1 253 | ldrb w3, [x1], 1 254 | strb w3, [x0], 1 255 | b.ne 1b 256 | 2: 257 | ret 258 | // Force a link failure if this function is used in hypervisor builds 259 | .word memcpy_bytes_is_defined_only_in_test_programs 260 | function_end memcpy_bytes 261 | -------------------------------------------------------------------------------- /arch/armv8/src/memset.S: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | #include 7 | 8 | 9 | // memset to zeros of no more than 31 bytes 10 | function memset_zeros_below32 11 | // Assume the target is size-aligned and do the largest stores first. 12 | tbz x1, 4, LOCAL(memset_zeros_below16) 13 | stp xzr, xzr, [x0], 16 14 | local memset_zeros_below16: 15 | tbz x1, 3, 1f 16 | str xzr, [x0], 8 17 | 1: 18 | tbz x1, 2, 1f 19 | str wzr, [x0], 4 20 | 1: 21 | tbz x1, 1, 1f 22 | strh wzr, [x0], 2 23 | 1: 24 | tbz x1, 0, 1f 25 | strb wzr, [x0] 26 | 1: 27 | ret 28 | function_end memset_zeros_below32 29 | 30 | // memset to zeros of at least 31 bytes (i.e. large enough to align up to 16 31 | // and do at least one 16-byte copy). 32 | function memset_zeros_alignable 33 | // Align up the target address to 16. We know that the size (x1) is at 34 | // least 16 here, so we don't have to check it during this alignment. 35 | tbz x0, 0, 1f 36 | strb wzr, [x0], 1 37 | sub x1, x1, 1 38 | 1: 39 | tbz x0, 1, 1f 40 | strh wzr, [x0], 2 41 | sub x1, x1, 2 42 | 1: 43 | tbz x0, 2, 1f 44 | str wzr, [x0], 4 45 | sub x1, x1, 4 46 | 1: 47 | tbz x0, 3, 1f 48 | str xzr, [x0], 8 49 | sub x1, x1, 8 50 | 1: 51 | // At this point we've cleared up to 15 bytes, so we know there are at 52 | // least 16 left. We can safely fall through to _align16. 53 | function_chain memset_zeros_alignable, memset_zeros_align16 54 | // Determine how many stores need to be done to align to DCZVA_BITS, 55 | // and also whether the remaining size is less than a DC ZVA block. 56 | neg x3, x0 57 | cmp x1, 1 << CPU_DCZVA_BITS 58 | and x2, x3, ((1 << CPU_DCZVA_BITS) - 1) 59 | 60 | // If we have less than a DC ZVA block left to copy, don't align up. 61 | b.lt LOCAL(memset_zeros_no_dczva) 62 | 63 | // Align up to the DC ZVA size by calculating a jump into an stp 64 | // sequence based on the number of 16-byte chunks needed for alignment 65 | // (which may be 0). By the time we finish this, we might again have 66 | // less than one DC ZVA block left, so redo the comparison. 67 | adr x5, 1f 68 | sub x1, x1, x2 69 | add x0, x0, x2 70 | sub x6, x5, x2, lsr #(4 - 2) 71 | cmp x1, 1 << CPU_DCZVA_BITS 72 | br x6 73 | .equ LOCAL(offset), 16 - (1 << CPU_DCZVA_BITS) 74 | .rept (1 << (CPU_DCZVA_BITS - 4) - 1) 75 | stp xzr, xzr, [x0, LOCAL(offset)] 76 | .equ LOCAL(offset), LOCAL(offset) + 16 77 | .endr 78 | 1: 79 | b.lt LOCAL(memset_zeros_no_dczva) 80 | function_chain memset_zeros_align16, memset_zeros_dczva 81 | bic x2, x1, ((1 << CPU_DCZVA_BITS) - 1) 82 | and x1, x1, ((1 << CPU_DCZVA_BITS) - 1) 83 | 1: 84 | subs x2, x2, (1 << CPU_DCZVA_BITS) 85 | dc zva, x0 86 | add x0, x0, (1 << CPU_DCZVA_BITS) 87 | b.ne 1b 88 | 89 | cbz x1, LOCAL(return) 90 | 91 | local memset_zeros_no_dczva: 92 | // Less than one DC ZVA block left, so calculate a jump into an stp 93 | // sequence based on the number of remaining 16-byte chunks. 94 | lsr x4, x1, 4 95 | adr x5, 1f 96 | sub x1, x1, x4, lsl 4 97 | add x0, x0, x4, lsl 4 98 | sub x6, x5, x4, lsl 2 99 | br x6 100 | .equ LOCAL(offset), 16 - (1 << CPU_DCZVA_BITS) 101 | .rept (1 << (CPU_DCZVA_BITS - 4)) - 1 102 | stp xzr, xzr, [x0, LOCAL(offset)] 103 | .equ LOCAL(offset), LOCAL(offset) + 16 104 | .endr 105 | 1: 106 | // There must be less than 16 bytes left now. 107 | cbnz x1, LOCAL(memset_zeros_below16) 108 | local return: 109 | ret 110 | function_end memset_zeros_dczva 111 | 112 | 113 | // memset to nonzero of no more than 31 bytes. Note that x1 has been expanded 114 | // to contain 8 copies of the nonzero byte to set. 115 | function memset_below32 116 | // Assume the target is size-aligned and do the largest stores first. 117 | tbz x2, 4, LOCAL(memset_below16) 118 | stp x1, x1, [x0], 16 119 | local memset_below16: 120 | tbz x2, 3, 1f 121 | str x1, [x0], 8 122 | 1: 123 | tbz x2, 2, 1f 124 | str w1, [x0], 4 125 | 1: 126 | tbz x2, 1, 1f 127 | strh w1, [x0], 2 128 | 1: 129 | tbz x2, 0, 1f 130 | strb w1, [x0] 131 | 1: 132 | ret 133 | function_end memset_below32 134 | 135 | // memset to nonzero of at least 31 bytes (i.e. large enough to align up to 16 136 | // and do at least one 16-byte copy). For the _align16 entry point, x1 has 137 | // been expanded to contain at 8 copies of the nonzero byte to set; for the 138 | // _alignable entry point, it has not been expanded yet, but has been 139 | // zero-extended from 8 bits if necessary. 140 | function memset_alignable 141 | // Align up the target address to 16, and simultaneously duplicate the 142 | // byte to set until we have 16 copies of it. We know that the size 143 | // (x2) is at least 16 here, so we don't have to check it during this 144 | // alignment. 145 | orr x3, x1, x1, lsl 8 146 | tbz x0, 0, 1f 147 | strb w1, [x0], 1 148 | sub x2, x2, 1 149 | 1: 150 | orr x1, x3, x3, lsl 16 151 | tbz x0, 1, 1f 152 | strh w3, [x0], 2 153 | sub x2, x2, 2 154 | 1: 155 | orr x3, x1, x1, lsl 32 156 | tbz x0, 2, 1f 157 | str w1, [x0], 4 158 | sub x2, x2, 4 159 | 1: 160 | mov x1, x3 161 | tbz x0, 3, 1f 162 | str x3, [x0], 8 163 | sub x2, x2, 8 164 | 1: 165 | // At this point we've cleared up to 15 bytes, so we know there are at 166 | // least 16 left; also we have expanded x1. We can safely fall through 167 | // to _align16. 168 | prfm pstl1keep, [x0] 169 | function_chain memset_alignable, memset_align16 170 | // Use the larger of 128-byte chunks or cache lines for large copies 171 | .equ LOCAL(chunk), 0x80 172 | .ifge (1 << CPU_L1D_LINE_BITS) - LOCAL(chunk) 173 | .equ LOCAL(chunk), 1 << CPU_L1D_LINE_BITS 174 | .endif 175 | // The first line was prefetched by the caller; prefetch the rest of 176 | // the first chunk. 177 | .equ LOCAL(offset), 1 << CPU_L1D_LINE_BITS 178 | .rept (LOCAL(chunk) >> CPU_L1D_LINE_BITS) - 1 179 | prfm pstl1keep, [x0, LOCAL(offset)] 180 | .equ LOCAL(offset), LOCAL(offset) + (1 << CPU_L1D_LINE_BITS) 181 | .endr 182 | 183 | // Unrolled loop copying chunks 184 | subs x3, x2, LOCAL(chunk) 185 | and x2, x2, LOCAL(chunk) - 1 186 | b.lt 2f 187 | 1: 188 | // Prefetch the next chunk. 189 | .rept (LOCAL(chunk) >> CPU_L1D_LINE_BITS) 190 | prfm pstl1keep, [x0, LOCAL(offset)] 191 | .equ LOCAL(offset), LOCAL(offset) + (1 << CPU_L1D_LINE_BITS) 192 | .endr 193 | // Write the chunk with a sequence of 16-byte stores. 194 | .equ LOCAL(offset), 0 195 | .rept (LOCAL(chunk) / 0x10) 196 | stp x1, x1, [x0, LOCAL(offset)] 197 | .equ LOCAL(offset), LOCAL(offset) + 0x10 198 | .endr 199 | subs x3, x3, LOCAL(chunk) 200 | add x0, x0, LOCAL(chunk) 201 | b.ge 1b 202 | 2: 203 | // Calculated jump for up to 7 16-byte chunks. 204 | lsr x4, x2, 4 205 | adr x5, 1f 206 | sub x2, x2, x4, lsl 4 207 | add x0, x0, x4, lsl 4 208 | sub x6, x5, x4, lsl 2 209 | br x6 210 | .equ LOCAL(offset), 0x10 - LOCAL(chunk) 211 | .rept (LOCAL(chunk) / 0x10) - 1 212 | stp x1, x1, [x0, LOCAL(offset)] 213 | .equ LOCAL(offset), LOCAL(offset) + 0x10 214 | .endr 215 | 1: 216 | // There must be less than 16 bytes left now. 217 | cbnz x2, LOCAL(memset_below16) 218 | ret 219 | function_end memset_align16 220 | -------------------------------------------------------------------------------- /arch/armv8/src/string.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 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | // Assembly functions. All of these come in at least three variants: 16 | // 17 | // - _align16 for at least 16 bytes with target known to be 16-aligned; 18 | // - _alignable for at least 31 bytes with unknown target alignment; 19 | // - _below32 for less than 32 bytes (i.e. one access of each size). 20 | // 21 | // Note the overlap between _alignable and _below32 at n==31; either variant 22 | // may be used at that size. We use _below32 because the logic to trigger its 23 | // first 16-byte copy is simpler. 24 | // 25 | // For memset to zero there is additionally a _dczva variant, where the target 26 | // is aligned to a DC ZVA block (typically a 64-byte cache line) and is at 27 | // least that size. 28 | // 29 | // The variants other than _below32 fall through to the more-aligned versions 30 | // once the necessary alignment has been established. 31 | 32 | // TODO: Clang does only simple constant propagation when LTO is enabled, 33 | // preferring to leave it until LTO. However, the LLVM IR has no way to 34 | // represent __builtin_constant_p(). So it is not really possible to use 35 | // __builtin_constant_p() here to avoid runtime checks, since it will nearly 36 | // always evaluate to 0. 37 | // 38 | // To make any static assertions or build-time variant selection actually 39 | // effective, we need to move all of the definitions below into inlines in a 40 | // header. We would then need to either include it here to generate extern 41 | // definitions for the backend to use, or else define them in the assembly. 42 | 43 | void 44 | memcpy_below32(void *restrict s1, const void *restrict s2, size_t n); 45 | 46 | void 47 | memcpy_alignable(void *restrict s1, const void *restrict s2, size_t n); 48 | 49 | void 50 | memcpy_align16(void *restrict s1, const void *restrict s2, size_t n); 51 | 52 | void 53 | memcpy_bytes(void *restrict s1, const void *restrict s2, size_t n); 54 | 55 | void 56 | memset_zeros_alignable(void *s, size_t n); 57 | 58 | void 59 | memset_zeros_below32(void *s, size_t n); 60 | 61 | void 62 | memset_zeros_align16(void *s, size_t n); 63 | 64 | void 65 | memset_zeros_dczva(void *s, size_t n); 66 | 67 | void 68 | memset_alignable(void *s, uint8_t c, size_t n); 69 | 70 | void 71 | memset_below32(void *s, uint64_t cs, size_t n); 72 | 73 | void 74 | memset_align16(void *s, uint64_t cs, size_t n); 75 | 76 | void * 77 | memcpy(void *restrict s1, const void *restrict s2, size_t n) 78 | { 79 | assert(compiler_sizeof_object(s1) >= n); 80 | assert(compiler_sizeof_object(s2) >= n); 81 | if (n == 0UL) { 82 | // Nothing to do. 83 | } else if (n < 32UL) { 84 | prefetch_store_keep(s1); 85 | prefetch_load_stream(s2); 86 | memcpy_below32(s1, s2, n); 87 | } else { 88 | prefetch_store_keep(s1); 89 | prefetch_load_stream(s2); 90 | uintptr_t a16 = (uintptr_t)s1 & (uintptr_t)15; 91 | if (a16 == 0UL) { 92 | memcpy_align16(s1, s2, n); 93 | } else { 94 | memcpy_alignable(s1, s2, n); 95 | } 96 | } 97 | 98 | return s1; 99 | } 100 | 101 | void * 102 | memmove(void *s1, const void *s2, size_t n) 103 | { 104 | // The hypervisor should never need memmove(), but unfortunately the 105 | // test program won't link if we don't define it. This is because 106 | // static glibc defines it in the same object as memcpy(), so if we 107 | // don't define it the calls in the glibc startup will pull in the 108 | // glibc version of memcpy() and cause duplicate definition errors. 109 | // 110 | // In cases where we know our fast memcpy will work, just call that. 111 | // Otherwise call a slow memcpy which is only defined in the test 112 | // program. 113 | if ((uintptr_t)s1 == (uintptr_t)s2) { 114 | // Nothing to do. 115 | } else if ((uintptr_t)s1 < (uintptr_t)s2) { 116 | (void)memcpy(s1, s2, n); 117 | } else if ((uintptr_t)s2 + CPU_MEMCPY_STRIDE < (uintptr_t)s1) { 118 | (void)memcpy(s1, s2, n); 119 | } else if (((uintptr_t)s1 + n <= (uintptr_t)s2) && 120 | ((uintptr_t)s2 + n <= (uintptr_t)s1)) { 121 | (void)memcpy(s1, s2, n); 122 | } else { 123 | (void)memcpy_bytes(s1, s2, n); 124 | } 125 | return s1; 126 | } 127 | 128 | void * 129 | memset(void *s, int c, size_t n) 130 | { 131 | assert(compiler_sizeof_object(s) >= n); 132 | uintptr_t a16 = (uintptr_t)s & (uintptr_t)15; 133 | 134 | if (n == 0UL) { 135 | // Nothing to do. 136 | } else if (c == 0) { 137 | uintptr_t a_zva = (uintptr_t)s & 138 | (uintptr_t)((1UL << CPU_DCZVA_BITS) - 1UL); 139 | if (n < 32UL) { 140 | prefetch_store_keep(s); 141 | memset_zeros_below32(s, n); 142 | } else if ((a_zva == 0UL) && ((n >> CPU_DCZVA_BITS) > 0UL)) { 143 | memset_zeros_dczva(s, n); 144 | } else if (a16 == 0UL) { 145 | prefetch_store_keep(s); 146 | memset_zeros_align16(s, n); 147 | } else { 148 | prefetch_store_keep(s); 149 | memset_zeros_alignable(s, n); 150 | } 151 | } else { 152 | uint64_t cs = (uint64_t)(uint8_t)c; 153 | cs |= cs << 8; 154 | cs |= cs << 16; 155 | cs |= cs << 32; 156 | if (n < 32UL) { 157 | prefetch_store_keep(s); 158 | memset_below32(s, cs, n); 159 | } else if (a16 == 0UL) { 160 | prefetch_store_keep(s); 161 | memset_align16(s, cs, n); 162 | } else { 163 | prefetch_store_keep(s); 164 | memset_alignable(s, (uint8_t)c, n); 165 | } 166 | } 167 | 168 | return s; 169 | } 170 | 171 | void * 172 | memchr(const void *s, int c, size_t n) 173 | { 174 | const unsigned char *ret = NULL; 175 | 176 | const unsigned char *str = s; 177 | unsigned char delim = (unsigned char)c; 178 | 179 | size_t remain = n; 180 | 181 | while (remain > 0UL) { 182 | if (*str == delim) { 183 | ret = str; 184 | break; 185 | } 186 | str++; 187 | remain--; 188 | } 189 | 190 | // Std C function forces cast to non-const 191 | return (void *)(uintptr_t)ret; 192 | } 193 | 194 | size_t 195 | strlen(const char *str) 196 | { 197 | const char *end = str; 198 | 199 | assert(str != NULL); 200 | 201 | for (; *end != '\0'; end++) { 202 | } 203 | 204 | return (size_t)((uintptr_t)end - (uintptr_t)str); 205 | } 206 | 207 | ssize_t 208 | strscpy(char *dest, const char *str, size_t count) 209 | { 210 | char *out = dest; 211 | const char *pos = str; 212 | size_t remain = count; 213 | ssize_t ret; 214 | 215 | if (count == 0UL) { 216 | ret = -E2BIG; 217 | goto out; 218 | } 219 | 220 | while ((*pos != '\0') && (remain > 1UL)) { 221 | *out = *pos; 222 | out++; 223 | pos++; 224 | remain--; 225 | } 226 | *out = '\0'; 227 | 228 | if (*pos != '\0') { 229 | ret = -E2BIG; 230 | } else { 231 | ret = (ssize_t)count - (ssize_t)remain; 232 | } 233 | 234 | out: 235 | return ret; 236 | } 237 | -------------------------------------------------------------------------------- /arch/armv8/src/syscall.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 | 10 | #include 11 | 12 | #include 13 | 14 | #include "arch_syscall.h" 15 | 16 | #define SYSCALL(x, y) [SYS_##x] = (sys_call_ptr_t)sys_##y##_wrapper 17 | 18 | sys_call_ptr_t aarch64_sys_call_table[NR_syscall_max + 1] = { 19 | SYSCALL(openat, openat), 20 | SYSCALL(ppoll, ppoll), 21 | SYSCALL(set_tid_address, set_tid_address), 22 | SYSCALL(exit_group, exit_group), 23 | SYSCALL(exit, exit), 24 | SYSCALL(brk, brk), 25 | SYSCALL(ioctl, ioctl), 26 | SYSCALL(writev, writev), 27 | SYSCALL(clock_nanosleep, clock_nanosleep), 28 | SYSCALL(tkill, tkill), 29 | SYSCALL(close, close), 30 | }; 31 | 32 | register_t 33 | sys_set_tid_address_wrapper(register_t arg0, register_t arg1, register_t arg2, 34 | register_t arg3, register_t arg4) 35 | { 36 | (void)arg1; 37 | (void)arg2; 38 | (void)arg3; 39 | (void)arg4; 40 | 41 | return (register_t)sys_set_tid_address((int *)arg0); 42 | } 43 | 44 | register_t 45 | sys_ppoll_wrapper(register_t arg0, register_t arg1, register_t arg2, 46 | register_t arg3, register_t arg4) 47 | { 48 | return (register_t)sys_ppoll((char *)arg0, (unsigned int)arg1, 49 | (const struct timespec *)arg2, 50 | (char *)arg3, (uint32_t)arg4); 51 | } 52 | 53 | register_t 54 | sys_openat_wrapper(register_t arg0, register_t arg1, register_t arg2, 55 | register_t arg3, register_t arg4) 56 | { 57 | (void)arg4; 58 | 59 | return (register_t)sys_openat((int)arg0, (const char *)arg1, (int)arg2, 60 | (umode_t)arg3); 61 | } 62 | 63 | register_t 64 | sys_clock_nanosleep_wrapper(register_t arg0, register_t arg1, register_t arg2, 65 | register_t arg3, register_t arg4) 66 | { 67 | (void)arg4; 68 | 69 | return (register_t)sys_clock_nanosleep((long)arg0, (int)arg1, 70 | (const struct timespec *)arg2, 71 | (struct timespec *)arg3); 72 | } 73 | 74 | register_t 75 | sys_tkill_wrapper(register_t arg0, register_t arg1, register_t arg2, 76 | register_t arg3, register_t arg4) 77 | { 78 | (void)arg2; 79 | (void)arg3; 80 | (void)arg4; 81 | 82 | return (register_t)sys_tkill((int)arg0, (int)arg1); 83 | } 84 | 85 | register_t 86 | sys_exit_group_wrapper(register_t arg0, register_t arg1, register_t arg2, 87 | register_t arg3, register_t arg4) 88 | { 89 | (void)arg1; 90 | (void)arg2; 91 | (void)arg3; 92 | (void)arg4; 93 | 94 | sys_exit_group((int)arg0); 95 | 96 | return (register_t)0UL; 97 | } 98 | 99 | noreturn register_t 100 | sys_exit_wrapper(register_t arg0, register_t arg1, register_t arg2, 101 | register_t arg3, register_t arg4) 102 | { 103 | (void)arg1; 104 | (void)arg2; 105 | (void)arg3; 106 | (void)arg4; 107 | 108 | sys_exit((int)arg0); 109 | } 110 | 111 | register_t 112 | sys_brk_wrapper(register_t arg0, register_t arg1, register_t arg2, 113 | register_t arg3, register_t arg4) 114 | { 115 | (void)arg1; 116 | (void)arg2; 117 | (void)arg3; 118 | (void)arg4; 119 | 120 | return (register_t)sys_brk((unsigned long)arg0); 121 | } 122 | 123 | register_t 124 | sys_ioctl_wrapper(register_t arg0, register_t arg1, register_t arg2, 125 | register_t arg3, register_t arg4) 126 | { 127 | (void)arg3; 128 | (void)arg4; 129 | 130 | return (register_t)sys_ioctl((unsigned int)arg0, (unsigned int)arg1, 131 | (unsigned long)arg2); 132 | } 133 | 134 | register_t 135 | sys_writev_wrapper(register_t arg0, register_t arg1, register_t arg2, 136 | register_t arg3, register_t arg4) 137 | { 138 | (void)arg3; 139 | (void)arg4; 140 | 141 | return (register_t)sys_writev((unsigned long)arg0, (uintptr_t)arg1, 142 | (unsigned long)arg2); 143 | } 144 | 145 | register_t 146 | sys_close_wrapper(register_t arg0, register_t arg1, register_t arg2, 147 | register_t arg3, register_t arg4) 148 | { 149 | (void)arg1; 150 | (void)arg2; 151 | (void)arg3; 152 | (void)arg4; 153 | 154 | return (register_t)sys_close((unsigned int)arg0); 155 | } 156 | -------------------------------------------------------------------------------- /arch/armv8/src/vectors.S: -------------------------------------------------------------------------------- 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 | 10 | #define ESR_EC_SHIFT (26) 11 | #define ESR_EC_SVC64 (0b010101) 12 | 13 | #define ESR_ISS_SVC_IMM16_MASK (0xffff) 14 | 15 | function handle_el1h_sync 16 | // Check if it's svc #0 17 | mrs x9, ESR_EL1 18 | lsr x10, x9, #ESR_EC_SHIFT 19 | and x11, x9, #ESR_ISS_SVC_IMM16_MASK 20 | cmp x10, #ESR_EC_SVC64 21 | ccmp x11, #0, #0, eq 22 | // FIXME: might need a proper handling for this case 23 | b.ne LOCAL(el1h_invalid) 24 | // check syscall table 25 | cmp x8, NR_syscall_max 26 | b.hi LOCAL(svc_not_implemented) 27 | adrl x11, aarch64_sys_call_table 28 | ldr x12, [x11, x8, lsl #3] 29 | cbz x12, LOCAL(svc_not_implemented) 30 | blr x12 31 | local svc_return: 32 | restore_runtime_context_syscall 33 | eret 34 | local svc_not_implemented: 35 | mov x0, #-ENOSYS 36 | b LOCAL(svc_return) 37 | local el1h_invalid: 38 | restore_runtime_context_syscall 39 | 40 | save_runtime_context_full 41 | mov x0, sp 42 | bl dump_trap_frame 43 | panic_asm "EL1h sync exception not handled" 44 | function_end handle_el1h_sync 45 | 46 | function handle_el1h_irq 47 | bl interrupt_dispatch 48 | restore_runtime_context_irq 49 | eret 50 | function_end handle_el1h_irq 51 | 52 | function __stack_chk_fail 53 | save_runtime_context_full 54 | mov x0, sp 55 | bl dump_trap_frame 56 | panic_asm "Stack corruption detected in runtime" 57 | function_end __stack_chk_fail 58 | 59 | .section .text.vectors 60 | .balign 2048 61 | .global vectors_aarch64 62 | vectors_aarch64: 63 | 64 | // only use Current EL with SPx sync vector, 65 | // other's are jump print registers 66 | // for general exception handling: 67 | // save kernel context full 68 | // panic 69 | vector vector_el1t_sync 70 | save_runtime_context_full 71 | mov x0, sp 72 | bl dump_trap_frame 73 | panic_asm "Current sp0 sync vector" 74 | vector_end vector_el1t_sync 75 | 76 | vector vector_el1t_irq 77 | save_runtime_context_full 78 | mov x0, sp 79 | bl dump_trap_frame 80 | panic_asm "Current sp0 irq vector" 81 | vector_end vector_el1t_irq 82 | 83 | vector vector_el1t_fiq 84 | save_runtime_context_full 85 | mov x0, sp 86 | bl dump_trap_frame 87 | panic_asm "Current sp0 fiq vector" 88 | vector_end vector_el1t_fiq 89 | 90 | vector vector_el1t_serror 91 | save_runtime_context_full 92 | mov x0, sp 93 | bl dump_trap_frame 94 | panic_asm "Current sp0 serror vector" 95 | vector_end vector_el1t_serror 96 | 97 | vector vector_el1h_sync 98 | save_runtime_context_syscall 99 | b handle_el1h_sync 100 | vector_end vector_el1h_sync 101 | 102 | vector vector_el1h_irq 103 | save_runtime_context_irq 104 | b handle_el1h_irq 105 | vector_end vector_el1h_irq 106 | 107 | vector vector_el1h_fiq 108 | save_runtime_context_full 109 | mov x0, sp 110 | bl dump_trap_frame 111 | panic_asm "Current spx fiq vector" 112 | vector_end vector_el1h_fiq 113 | 114 | vector vector_el1h_serror 115 | save_runtime_context_full 116 | mov x0, sp 117 | bl dump_trap_frame 118 | panic_asm "Current spx serror vector" 119 | vector_end vector_el1h_serror 120 | 121 | vector vector_guest64_sync_panic 122 | save_runtime_context_full 123 | panic_asm "Guest 64 sync vector" 124 | vector_end vector_guest64_sync_panic 125 | 126 | vector vector_guest64_irq_panic 127 | save_runtime_context_full 128 | panic_asm "Guest 64 ieq vector" 129 | vector_end vector_guest64_irq_panic 130 | 131 | vector vector_guest64_fiq_panic 132 | save_runtime_context_full 133 | panic_asm "Guest 64 fiq vector" 134 | vector_end vector_guest64_fiq_panic 135 | 136 | vector vector_guest64_serror_panic 137 | save_runtime_context_full 138 | panic_asm "Guest 64 serror vector" 139 | vector_end vector_guest64_serror_panic 140 | 141 | vector vector_guest32_sync_panic 142 | save_runtime_context_full 143 | panic_asm "Guest 32 sync vector" 144 | vector_end vector_guest32_sync_panic 145 | 146 | vector vector_guest32_irq_panic 147 | save_runtime_context_full 148 | panic_asm "Guest 32 irq vector" 149 | vector_end vector_guest32_irq_panic 150 | 151 | vector vector_guest32_fiq_panic 152 | save_runtime_context_full 153 | panic_asm "Guest 32 fiq vector" 154 | vector_end vector_guest32_fiq_panic 155 | 156 | vector vector_guest32_serror_panic 157 | save_runtime_context_full 158 | panic_asm "Guest 32 serror vector" 159 | vector_end vector_guest32_serror_panic 160 | -------------------------------------------------------------------------------- /arch/generic/build.conf: -------------------------------------------------------------------------------- 1 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | 5 | source src/panic.c 6 | 7 | # generic arch should be global 8 | include include 9 | -------------------------------------------------------------------------------- /arch/generic/include/asm-generic/asm_defs.inc: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // clang-format off 6 | .macro function func:req local="global" section="section" align="align" 7 | .ifeqs "\local", "local" 8 | .else 9 | .ifeqs "\local", "global" 10 | .global \func 11 | .else 12 | .err "invalid argument to function macro" 13 | .endif 14 | .endif 15 | .ifeqs "\section", "section" 16 | .section .text.\func, "ax", @progbits 17 | .else 18 | .ifeqs "\section", "nosection" 19 | .else 20 | .err "invalid argument to function macro" 21 | .endif 22 | .endif 23 | .ifeqs "\align", "align" 24 | .balign 8 25 | .else 26 | .ifeqs "\align", "noalign" 27 | .else 28 | .balign \align 29 | .endif 30 | .endif 31 | 32 | .type \func, STT_FUNC 33 | \func: 34 | .endm 35 | 36 | .macro function_end func:req 37 | .size \func, . - \func 38 | .endm 39 | 40 | .macro function_chain prev_func:req next_func:req 41 | function_end \prev_func 42 | function \next_func, section=nosection align=noalign 43 | .endm 44 | 45 | #define LOCAL(name) .L##name 46 | 47 | .macro local, label 48 | .L\label 49 | .endm 50 | 51 | .macro _data_sym sym:req size:req local="global" align="noalign" 52 | .ifeqs "\local", "local" 53 | .else 54 | .ifeqs "\local", "global" 55 | .global \sym 56 | .else 57 | .err "invalid argument to _data_sym macro" 58 | .endif 59 | .endif 60 | .ifeqs "\align", "noalign" 61 | .else 62 | .balign \align 63 | .endif 64 | .type \sym, STT_OBJECT 65 | .size \sym, \size 66 | .endm 67 | 68 | .macro _const sym:req size:req align:req local 69 | .section .rodata.\sym, "a", @progbits 70 | _data_sym \sym, size=\size, align=\align, local=\local 71 | \sym: 72 | .endm 73 | 74 | .macro _data sym:req size:req align:req local 75 | .section .data.\sym, "aw", @progbits 76 | _data_sym \sym, size=\size, align=\align, local=\local 77 | \sym: 78 | .endm 79 | 80 | .macro _bss sym:req size:req align:req local 81 | .section .bss.\sym, "aw", @nobits 82 | _data_sym \sym, size=\size, align=\align, local=\local 83 | \sym: 84 | .endm 85 | 86 | .macro const32 sym, value=0, local="global" 87 | _const \sym, 4, 4, \local 88 | .4byte \value 89 | .previous 90 | .endm 91 | 92 | .macro const64 sym, value=0, local="global" 93 | _const \sym, 8, 8, \local 94 | .8byte \value 95 | .previous 96 | .endm 97 | 98 | .macro data32 sym, value=0, local="global" 99 | _data \sym, 4, 4, \local 100 | .4byte \value 101 | .previous 102 | .endm 103 | 104 | .macro data64 sym, value=0, local="global" 105 | _data \sym, 8, 8, \local 106 | .8byte \value 107 | .previous 108 | .endm 109 | 110 | .macro bss32 sym, local="global" 111 | _bss \sym, 4, 4, \local 112 | .4byte 0 113 | .previous 114 | .endm 115 | 116 | .macro bss64 sym, local="global" 117 | _bss \sym, 8, 8, \local 118 | .8byte 0 119 | .previous 120 | .endm 121 | 122 | // clang-format on 123 | -------------------------------------------------------------------------------- /arch/generic/include/asm-generic/prefetch.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Prefetch operations. 6 | // 7 | // Calling these macros may cause the compiler to generate hint instructions 8 | // or otherwise reorder operations so that values are fetched by the CPU 9 | // eagerly when it is known that they will be needed in the near future. 10 | // 11 | // Prefetch instructions, where available, can typically distinguish between 12 | // addresses that will be loaded or stored; this distinction is useful on 13 | // cache-coherent multiprocessor systems, where a store prefetch will try to 14 | // bring the target cache line into an exclusive state. 15 | // 16 | // On some architectures, including ARMv8, the prefetch instructions can 17 | // further distinguish between temporal and non-temporal accesses. A temporal, 18 | // or "keep", prefetch means that the address will be accessed repeatedly and 19 | // should be kept in the cache (i.e. the default behaviour of most caches). A 20 | // non-temporal, or "stream", prefetch means that the address will be accessed 21 | // only once, so cache allocations for it should be kept to a minimum - e.g. 22 | // bypassing outer caches on eviction from the innermost cache. 23 | // 24 | // This is in an asm header to allow the macros to be replaced with asm 25 | // directives or no-ops for targets where the compiler makes a suboptimal 26 | // decision by default, typically because the target CPU has a broken 27 | // implementation of the prefetch instructions. 28 | 29 | #ifndef prefetch_load_keep 30 | #define prefetch_load_keep(addr) __builtin_prefetch(addr, 0, 3) 31 | #endif 32 | 33 | #ifndef prefetch_store_keep 34 | #define prefetch_store_keep(addr) __builtin_prefetch(addr, 1, 3) 35 | #endif 36 | 37 | #ifndef prefetch_load_stream 38 | #define prefetch_load_stream(addr) __builtin_prefetch(addr, 0, 0) 39 | #endif 40 | 41 | #ifndef prefetch_store_stream 42 | #define prefetch_store_stream(addr) __builtin_prefetch(addr, 1, 0) 43 | #endif 44 | -------------------------------------------------------------------------------- /arch/generic/include/asm-generic/vector.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | typedef struct trap_frame { 6 | uint64_t x[29]; 7 | uint64_t x30; 8 | uint64_t spsr; 9 | uint64_t esr; 10 | uint64_t sp_el0; 11 | uint64_t sp_el1; 12 | uint64_t _Alignas(16) x29; 13 | uint64_t elr; 14 | } trap_frame_t; 15 | -------------------------------------------------------------------------------- /arch/generic/include/panic.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | noreturn void 6 | panic(const char *str); 7 | 8 | void 9 | dump_trap_frame(trap_frame_t *frame); 10 | -------------------------------------------------------------------------------- /arch/generic/src/panic.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 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | void 21 | dump_trap_frame(trap_frame_t *frame) 22 | { 23 | LOG(ERROR, PANIC, "trap frame dump:\n"); 24 | LOG(ERROR, PANIC, "x0: {:#8x}\t x1: {:#8x}\t x2: {:#8x}\t x3: {:#8x}\n", 25 | frame->x[0], frame->x[1], frame->x[2], frame->x[3]); 26 | LOG(ERROR, PANIC, "x4: {:#8x}\t x5: {:#8x}\t x6: {:#8x}\t x7: {:#8x}\n", 27 | frame->x[4], frame->x[5], frame->x[6], frame->x[7]); 28 | LOG(ERROR, PANIC, "x8: {:#8x}\t x9: {:#8x}\t x10:{:#8x}\t x11:{:#8x}\n", 29 | frame->x[8], frame->x[9], frame->x[10], frame->x[11]); 30 | LOG(ERROR, PANIC, "x12:{:#8x}\t x13:{:#8x}\t x14:{:#8x}\t x15:{:#8x}\n", 31 | frame->x[12], frame->x[13], frame->x[14], frame->x[15]); 32 | LOG(ERROR, PANIC, "x16:{:#8x}\t x17:{:#8x}\t x18:{:#8x}\t x19:{:#8x}\n", 33 | frame->x[16], frame->x[17], frame->x[18], frame->x[19]); 34 | LOG(ERROR, PANIC, "x20:{:#8x}\t x21:{:#8x}\t x22:{:#8x}\t x23:{:#8x}\n", 35 | frame->x[20], frame->x[21], frame->x[22], frame->x[23]); 36 | LOG(ERROR, PANIC, "x24:{:#8x}\t x25:{:#8x}\t x26:{:#8x}\t x27:{:#8x}\n", 37 | frame->x[24], frame->x[25], frame->x[26], frame->x[27]); 38 | LOG(ERROR, PANIC, "x28:{:#8x}\t x29:{:#8x}\t x30:{:#8x}\n", 39 | frame->x[28], frame->x29, frame->x30); 40 | LOG(ERROR, PANIC, "spsr_el1:{:#8x}\t elr_el1:{:#8x}\t esr_el1:{:#8x}\n", 41 | frame->spsr, frame->elr, frame->esr); 42 | LOG(ERROR, PANIC, "sp_el0:{:#8x}\t sp_el1:{:#8x}\n", frame->sp_el0, 43 | frame->sp_el1); 44 | } 45 | 46 | noreturn void NOINLINE 47 | panic(const char *str) 48 | { 49 | void *from = __builtin_return_address(0); 50 | void *frame = __builtin_frame_address(0); 51 | 52 | LOG(ERROR, PANIC, "Panic: {:s} from PC {:#x}, FP {:#x}\n", 53 | (register_t)(uintptr_t)str, (register_t)(uintptr_t)from, 54 | (register_t)(uintptr_t)frame); 55 | 56 | sys_exit(1); 57 | } 58 | -------------------------------------------------------------------------------- /build.conf: -------------------------------------------------------------------------------- 1 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | 5 | program runtime 6 | arch aarch64 7 | 8 | #board qemu 9 | board qcom 10 | 11 | # code generation options 12 | target_triple aarch64-linux-gnu 13 | cflags -march=armv8.2-a -mtune=cortex-a75 14 | 15 | cflags -Os -g -flto -mbranch-protection=pac-ret+bti 16 | #configs NDEBUG 17 | 18 | cflags -std=gnu18 19 | # Turn all warnings on as errors by default 20 | cflags -Weverything 21 | cflags -Werror 22 | 23 | # depress the warning for header file from compiler 24 | # FIXME: double check if it's right 25 | cflags -Wno-reserved-id-macro 26 | 27 | # Unused macros are expected 28 | cflags -Wno-unused-macros 29 | 30 | # MISRA rule 16.4 requires default: in every switch, even if it is covered 31 | cflags -Wno-covered-switch-default 32 | 33 | # No need for C++ compatibility 34 | cflags -Wno-c++98-compat 35 | cflags -Wno-c++-compat 36 | 37 | # No need for pre-C99 compatibility; we always use C18 38 | cflags -Wno-declaration-after-statement 39 | 40 | # No need for GCC compatibility 41 | cflags -Wno-gcc-compat 42 | 43 | # Enable stack protection by default 44 | cflags -fstack-protector-strong 45 | 46 | # Section garbage collection, reduce size & do better job to remove dead code 47 | # it's better to disable them for gprof & debug. 48 | cflags -ffunction-sections 49 | cflags -fdata-sections 50 | 51 | # Avoid runtime touch float point register V0 - V31. So there's no need to 52 | # save and restore these registers. 53 | cflags -mgeneral-regs-only 54 | 55 | # target specific cflags 56 | cflags -ffreestanding -ftls-model=local-exec -fpie 57 | 58 | # Generate DWARF compatible with older T32 releases 59 | cflags -gdwarf-4 60 | 61 | # target specific ldflags 62 | ldflags -static-pie 63 | 64 | # Use C18. For the purposes of MISRA, the language is C99 and all differences 65 | # between C99 and C18 are language extensions permitted by a project deviation 66 | # from rule 1.2. 67 | ldflags -Wl,--gc-sections 68 | 69 | cppflags -nostdlibinc 70 | 71 | ldflags -nostdlib -fuse-ld=lld 72 | 73 | # Set the max-page-size to prevent large ELF alignments 74 | ldflags -Wl,-z,max-page-size=4096 75 | # Set separate-loadable-segments for ELF alignments 76 | ldflags -Wl,-z,separate-loadable-segments 77 | 78 | include include 79 | 80 | sub_directory arch/armv8 81 | sub_directory arch/generic 82 | sub_directory src 83 | 84 | #end_static_lib 85 | end_program 86 | -------------------------------------------------------------------------------- /include/assert.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Local version of the standard-defined assert.h 6 | 7 | #if !defined(HYP_STANDALONE_TEST) 8 | _Static_assert(__STDC_HOSTED__ == 0, 9 | "This file deviates from MISRA rule 21.2 in hosted mode"); 10 | #endif 11 | 12 | #define static_assert _Static_assert 13 | 14 | // Use a Clang extension to assert that an expression is true if its value 15 | // can be statically determined. 16 | static inline _Bool 17 | assert_if_const(_Bool x) 18 | __attribute__((diagnose_if(!(x), "Static assert failure", "error"))) 19 | { 20 | return x; 21 | } 22 | 23 | #if defined(NDEBUG) 24 | // Strictly this should be defined to ((void)0), but since assert_if_const() 25 | // has no runtime overhead we may as well use it. Also the fact that the 26 | // expression is evaluated means we don't need to put maybe-unused annotations 27 | // on variables that are only used in assert expressions. 28 | #define assert(x) (void)assert_if_const(x) 29 | #else 30 | _Noreturn void 31 | assert_failed(const char *file, int line, const char *func, const char *err); 32 | #define assert(x) \ 33 | (assert_if_const(x) ? (void)0 \ 34 | : assert_failed(__FILE__, __LINE__, __func__, #x)) 35 | #endif 36 | -------------------------------------------------------------------------------- /include/atomic.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #define atomic_load_relaxed(p) atomic_load_explicit((p), memory_order_relaxed) 8 | #define atomic_load_acquire(p) atomic_load_explicit((p), memory_order_acquire) 9 | #define atomic_store_relaxed(p, v) \ 10 | atomic_store_explicit((p), (v), memory_order_relaxed) 11 | #define atomic_store_release(p, v) \ 12 | atomic_store_explicit((p), (v), memory_order_release) 13 | -------------------------------------------------------------------------------- /include/attributes.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // This file documents the permitted function attributes, and defines short 6 | // names for them. Do not use any attribute specifier unless it is listed 7 | // below. 8 | // 9 | // An attribute that is listed here may be used directly (not via a macro) on an 10 | // inline function in an interface or asm header, to avoid introducing an 11 | // inconvenient dependency on this header. Attributes used this way must be 12 | // exactly as defined below; no extra whitespace or punctuation, and no listing 13 | // multiple attributes in a single __attribute__ specifier. 14 | // 15 | // This rule does not apply to language constructs that have an effect that is 16 | // similar or equivalent to an attribute, such as _Noreturn or _Alignas. 17 | 18 | // Don't inline the function. This is used to mark cold functions for which 19 | // inlining would be a waste of space and/or would make debugging inconvenient. 20 | #define NOINLINE __attribute__((noinline)) 21 | 22 | // Always inline the function. This is used for certain inline assembler 23 | // wrappers which cannot safely be wrapped in a function call, such as 24 | // load-exclusive instructions which might lose their exclusivity. 25 | #define ALWAYS_INLINE __attribute__((always_inline)) 26 | -------------------------------------------------------------------------------- /include/compiler.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Macros wrapping miscellaneous compiler builtins to make them easier to use 6 | // correctly. Note that this is not intended for compiler independence, only 7 | // for readability. 8 | 9 | // Branch probability hints. 10 | // 11 | // Note that the argument and result of each of these macros must be 12 | // essentially boolean (MISRA rule 14.4), but the argument and result of 13 | // __builtin_expect have type long. 14 | #define compiler_expected(x) (__builtin_expect((x) ? 1 : 0, 1) != 0) 15 | #define compiler_unexpected(x) (__builtin_expect((x) ? 1 : 0, 0) != 0) 16 | 17 | // Bit operations. 18 | // 19 | // On ARM, prefer clz and clrsb as they expand to single instructions (CLZ and 20 | // CLS). ffs and ctz need an extra RBIT first. 21 | // clang-format off 22 | #define compiler_ffs(x) (index_t)_Generic( \ 23 | (x), \ 24 | long long: __builtin_ffsll(x), \ 25 | unsigned long long: __builtin_ffsll((long long)(x)), \ 26 | long: __builtin_ffsl(x), \ 27 | unsigned long: __builtin_ffsl((long)(x)), \ 28 | int: __builtin_ffs(x), \ 29 | unsigned int: __builtin_ffs((int)(x))) 30 | 31 | #define compiler_clz(x) (assert((x) != 0U), (index_t)_Generic( \ 32 | (x), \ 33 | unsigned long long: __builtin_clzll, \ 34 | unsigned long: __builtin_clzl, \ 35 | unsigned int: __builtin_clz)(x)) 36 | 37 | #define compiler_ctz(x) (assert((x) != 0U), (index_t)_Generic( \ 38 | (x), \ 39 | unsigned long long: __builtin_ctzll, \ 40 | unsigned long: __builtin_ctzl, \ 41 | unsigned int: __builtin_ctz)(x)) 42 | 43 | #define compiler_clrsb(x) (index_t)_Generic( \ 44 | (x), long long: __builtin_clrsbll, \ 45 | long: __builtin_clrsbl, \ 46 | int: __builtin_clrsb)(x) 47 | 48 | // clang-format on 49 | 50 | // Object sizes, for use in minimum buffer size assertions. These return 51 | // (size_t)-1 if the size cannot be determined statically, so the assertion 52 | // should become a no-op in that case. LLVM has an intrinsic for this, so 53 | // the static determination can be made after inlining by LTO. 54 | #define compiler_sizeof_object(ptr) __builtin_object_size((ptr), 1) 55 | #define compiler_sizeof_container(ptr) __builtin_object_size((ptr), 0) 56 | -------------------------------------------------------------------------------- /include/console.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | void 8 | console_write(const char *msg, size_t sz); 9 | 10 | int 11 | console_register(console_t console); 12 | 13 | int 14 | console_deregister(void); 15 | 16 | long 17 | console_open(int flags); 18 | -------------------------------------------------------------------------------- /include/cpulocal.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Dummy implementation of cpulocal, supporting only a single VCPU. 6 | 7 | #define PLATFORM_MAX_CORES 1U 8 | 9 | // Declarators for CPU-local data 10 | #define CPULOCAL_DECLARE(type, name) type cpulocal_##name[PLATFORM_MAX_CORES] 11 | #define CPULOCAL_DECLARE_STATIC(type, name) \ 12 | static type cpulocal_##name[PLATFORM_MAX_CORES] 13 | 14 | // Accessors for CPU-local data 15 | #define CPULOCAL(name) cpulocal_##name[cpulocal_get_index()] 16 | #define CPULOCAL_BY_INDEX(name, index) \ 17 | cpulocal_##name[cpulocal_check_index(index)] 18 | 19 | static inline bool 20 | cpulocal_index_valid(cpu_index_t index) 21 | { 22 | return index < PLATFORM_MAX_CORES; 23 | } 24 | 25 | static inline cpu_index_t 26 | cpulocal_check_index(cpu_index_t index) 27 | { 28 | assert(cpulocal_index_valid(index)); 29 | return index; 30 | } 31 | 32 | static inline cpu_index_t 33 | cpulocal_get_index(void) 34 | { 35 | return cpulocal_check_index(0U); 36 | } 37 | -------------------------------------------------------------------------------- /include/device.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | #if !defined(device_load_relaxed) 8 | #define device_load_relaxed(p, v) atomic_load_relaxed(p, v) 9 | #endif 10 | 11 | #if !defined(device_store_relaxed) 12 | #define device_store_relaxed(p, v) atomic_store_relaxed(p, v) 13 | #endif 14 | 15 | #if !defined(device_load_acquire) 16 | #define device_load_acquire(p, v) atomic_load_acquire(p, v) 17 | #endif 18 | 19 | #if !defined(device_store_release) 20 | #define device_store_release(p, v) atomic_store_release(p, v) 21 | #endif 22 | -------------------------------------------------------------------------------- /include/errno.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define ENOENT 2 6 | #define EINTR 4 7 | #define EIO 5 8 | #define ENXIO 6 9 | #define E2BIG 7 10 | #define EBADF 9 11 | #define ENOMEM 12 12 | #define EBUSY 16 13 | #define ENODEV 19 14 | #define EINVAL 22 15 | #define ENFILE 23 16 | #define ENOSYS 38 17 | -------------------------------------------------------------------------------- /include/exit_dev.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | void 8 | exit_trigger(int exit_code); 9 | 10 | int 11 | exit_register(exit_t exit_func); 12 | 13 | int 14 | exit_deregister(void); 15 | 16 | long 17 | exit_open(int flags); 18 | -------------------------------------------------------------------------------- /include/fs.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | struct iovec; 6 | 7 | typedef long (*fs_writev_t)(const struct iovec *vec, unsigned long vlen); 8 | typedef long (*fs_ioctl_t)(unsigned int cmd, unsigned long arg); 9 | 10 | struct fs_ops { 11 | fs_writev_t writev; 12 | fs_ioctl_t ioctl; 13 | }; 14 | 15 | struct file { 16 | struct fs_ops *ops; 17 | }; 18 | 19 | struct file_p { 20 | struct file *file; 21 | long flags; 22 | }; 23 | 24 | #define FS_READ 0x1 25 | #define FS_WRITE 0x2 26 | 27 | void 28 | fs_init(void); 29 | 30 | long 31 | fs_alloc_fd(struct file *f, int o_flags); 32 | 33 | struct file_p * 34 | fs_lookup_file(unsigned long fd); 35 | -------------------------------------------------------------------------------- /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/hyperror.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Helper macros (replace with template expansion in autogen) 6 | #define HYPTYPES_DECLARE_RESULT_(name, type) \ 7 | typedef struct name##_result { \ 8 | type r; \ 9 | error_t alignas(register_t) e; \ 10 | } name##_result_t; \ 11 | static inline name##_result_t name##_result_error(error_t err) \ 12 | { \ 13 | return (name##_result_t){ .e = err }; \ 14 | } \ 15 | static inline name##_result_t name##_result_ok(type ret) \ 16 | { \ 17 | return (name##_result_t){ .r = ret, .e = OK }; \ 18 | } 19 | 20 | #define HYPTYPES_DECLARE_RESULT(type) HYPTYPES_DECLARE_RESULT_(type, type##_t) 21 | 22 | #define HYPTYPES_DECLARE_RESULT_PTR_(name, type) \ 23 | typedef struct name##_ptr_result { \ 24 | type *r; \ 25 | error_t alignas(register_t) e; \ 26 | } name##_ptr_result_t; \ 27 | static inline name##_ptr_result_t name##_ptr_result_error(error_t err) \ 28 | { \ 29 | return (name##_ptr_result_t){ .e = err }; \ 30 | } \ 31 | static inline name##_ptr_result_t name##_ptr_result_ok(type *ret) \ 32 | { \ 33 | return (name##_ptr_result_t){ .r = ret, .e = OK }; \ 34 | } 35 | 36 | #define HYPTYPES_DECLARE_RESULT_PTR(type) \ 37 | HYPTYPES_DECLARE_RESULT_PTR_(type, type##_t) 38 | -------------------------------------------------------------------------------- /include/interrupt.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | void 8 | interrupt_init(void); 9 | 10 | int 11 | interrupt_register_isr(virq_t irq, isr_t isr, void *data); 12 | 13 | int 14 | interrupt_deregister_isr(virq_t irq); 15 | 16 | void 17 | interrupt_dispatch(void); 18 | 19 | long 20 | interrupt_open(int flags); 21 | 22 | bool 23 | interrupt_wait(void); 24 | -------------------------------------------------------------------------------- /include/log.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // log level definition 6 | #define INFO (0) 7 | #define DEBUG (1) 8 | #define WARNING (2) 9 | #define ERROR (3) 10 | 11 | // action definition, unused yet 12 | #define PANIC (0) 13 | // just print message 14 | #define MSG (1) 15 | 16 | #define LOG_FUNC_I(level, action, a0, a1, a2, a3, a4, a5, n, ...) \ 17 | LOG_ADD##n(level, action, a0, a1, a2, a3, a4, a5, __VA_ARGS__) 18 | 19 | #define LOG_FUNC(...) \ 20 | LOG_FUNC_I(__VA_ARGS__, 6, 5, 4, 3, 2, 1, 0, _unspecified_id) 21 | 22 | #define LOG_ADD0(level, action, ...) log_msg(level, action, 0, 0, 0, 0, 0, 0) 23 | 24 | #define LOG_ADD1(level, a1, action, ...) \ 25 | log_msg(level, a1, action, 0, 0, 0, 0, 0) 26 | 27 | #define LOG_ADD2(level, action, a1, a2, ...) \ 28 | log_msg(level, action, a1, a2, 0, 0, 0, 0) 29 | 30 | #define LOG_ADD3(level, action, a1, a2, a3, ...) \ 31 | log_msg(level, action, a1, a2, a3, 0, 0, 0) 32 | 33 | #define LOG_ADD4(level, action, a1, a2, a3, a4, ...) \ 34 | log_msg(level, action, a1, a2, a3, a4, 0, 0) 35 | 36 | #define LOG_ADD5(level, action, a1, a2, a3, a4, a5, ...) \ 37 | log_msg(level, action, a1, a2, a3, a4, a5, 0) 38 | 39 | #define LOG_ADD6(level, action, a1, a2, a3, a4, a5, a6, ...) \ 40 | log_msg(level, action, a1, a2, a3, a4, a5, a6) 41 | 42 | #define LOG(level, action, ...) LOG_FUNC(level, action, __VA_ARGS__) 43 | 44 | void 45 | log_msg(uint64_t level, uint64_t action, const char *a1, size_t a2, 46 | register_t a3, register_t a4, register_t a5, register_t a6); 47 | 48 | extern void 49 | log_append(const char *msg, size_t sz); 50 | extern void 51 | log_set_buffer(uintptr_t new_addr, size_t area_sz); 52 | 53 | #define EARLY_SIZE (304) 54 | 55 | struct log_s { 56 | uint32_t write_idx; 57 | uint32_t size; 58 | 59 | char buffer[EARLY_SIZE]; 60 | }; 61 | 62 | extern struct log_s *log_buf; 63 | -------------------------------------------------------------------------------- /include/platform_irq.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | void 6 | platform_irq_init(void); 7 | 8 | void 9 | platform_irq_enable(virq_t irq); 10 | 11 | void 12 | platform_irq_disable(virq_t irq); 13 | 14 | void 15 | platform_irq_disable_all(void); 16 | 17 | bool 18 | platform_irq_set_trigger(virq_t irq, int32_t trigger); 19 | 20 | virq_t 21 | platform_irq_acknowledge(void); 22 | 23 | void 24 | platform_irq_priority_drop(virq_t irq); 25 | 26 | void 27 | platform_irq_deactivate(virq_t irq); 28 | 29 | void 30 | platform_irq_assert(virq_t irq); 31 | 32 | void 33 | platform_irq_clear(virq_t irq); 34 | -------------------------------------------------------------------------------- /include/platform_timer.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | void 6 | platform_timer_init(uint64_t platform_timer_freq); 7 | 8 | void 9 | platform_timer_set_timeout(uint64_t ticks); 10 | 11 | void 12 | platform_timer_cancel_timeout(void); 13 | 14 | uint64_t 15 | platform_timer_get_current_ticks(void); 16 | -------------------------------------------------------------------------------- /include/reloc.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define R_TYPE(r_info) ((r_info)&0x7fffffff) 6 | #define R_SYM(r_info) ((r_info) >> 32) 7 | 8 | // only record DT type up to DT_RELSZ == 18 9 | #define DT_CNT 19 10 | 11 | void 12 | rel_fixup(Elf64_Dyn *dyni, rt_env_data_t *env_data); 13 | -------------------------------------------------------------------------------- /include/string.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Local version of the standard-defined string.h 6 | // 7 | // Only the memory block manipulation functions (mem*()) are declared. The 8 | // hypervisor has no need to operate on real strings, so the string 9 | // manipulation functions (str*()) are left undefined. 10 | // 11 | // Note: MISRA Required Rule 21.2 states that reserved identifiers are not to 12 | // be declared, and gives a memcpy declaration as a specific non-conforming 13 | // example. However, the identifiers declared here (including memcpy) are 14 | // _not_ reserved: the hypervisor is built in freestanding mode (as asserted 15 | // below), which does not guarantee their presence and therefore must not give 16 | // them special behaviour (see C18 clause 4, item 6). The Clang/GCC option 17 | // -ffreestanding implies -fno-builtin for this reason. 18 | // 19 | // Also, we _must_ implement these functions ourselves with their standard 20 | // semantics (regardless of MISRA 21.2) because the LLVM and GCC backends 21 | // assume they are provided by the environment, and will generate calls to 22 | // them even when the frontend is in freestanding mode. 23 | 24 | #if !defined(HYP_STANDALONE_TEST) 25 | _Static_assert(__STDC_HOSTED__ == 0, 26 | "This file deviates from MISRA rule 21.2 in hosted mode"); 27 | #endif 28 | 29 | // Define size_t, ssize_t and NULL 30 | #include 31 | #define __NEED_ssize_t 32 | #include 33 | 34 | extern void * 35 | memcpy(void *restrict s1, const void *restrict s2, size_t n); 36 | 37 | extern void * 38 | memmove(void *s1, const void *s2, size_t n); 39 | 40 | extern void * 41 | memset(void *s, int c, size_t n); 42 | 43 | extern void * 44 | memchr(const void *s, int c, size_t n); 45 | 46 | extern int 47 | strcmp(const char *s1, const char *s2); 48 | 49 | extern size_t 50 | strlen(const char *str); 51 | 52 | extern ssize_t 53 | strscpy(char *dest, const char *str, size_t count); 54 | -------------------------------------------------------------------------------- /include/string_util.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // snprint produces null terminated output string, of maximum length not 6 | // exceeding size characters (including the terminating null). 7 | // 8 | // Unlike the C printf family of functions, the format string is however a 9 | // python format string like syntax. 10 | // For example "This is a hex value: {:x}" will print the hex representation 11 | // of the corresponding argument. 12 | // 13 | // Not all python format string syntax is implemented, including positional 14 | // arguments. The following approximate python format string syntax is 15 | // accepted. 16 | // [[fill]align][sign][#][0][minimumwidth][.precision][type] 17 | // 18 | // This function returns the count of bytes written, up to a maximum of size-1. 19 | // A return value of size or larger indicates that the output was truncated. 20 | 21 | size_result_t 22 | snprint(char *str, size_t size, const char *format, register_t arg0, 23 | register_t arg1, register_t arg2, register_t arg3, register_t arg4); 24 | -------------------------------------------------------------------------------- /include/sys/ioctl.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #define _IOC(a, b, c, d) (((a) << 30) | ((b) << 8) | (c) | ((d) << 16)) 6 | #define _IOC_NONE 0U 7 | #define _IOC_WRITE 1U 8 | #define _IOC_READ 2U 9 | 10 | #define _IO(a, b) _IOC(_IOC_NONE, (a), (b), 0) 11 | #define _IOW(a, b, c) _IOC(_IOC_WRITE, (a), (b), sizeof(c)) 12 | #define _IOR(a, b, c) _IOC(_IOC_READ, (a), (b), sizeof(c)) 13 | #define _IOWR(a, b, c) _IOC(_IOC_READ | _IOC_WRITE, (a), (b), sizeof(c)) 14 | 15 | #define TIOCGWINSZ 0x5413 16 | #define TIOCSETBUF 0x547f // Non-standard IOCTL!! 17 | 18 | struct winsize { 19 | uint16_t ws_row; 20 | uint16_t ws_col; 21 | uint16_t ws_xpixel; 22 | uint16_t ws_ypixel; 23 | }; 24 | 25 | // Our non-standard buffer control message 26 | struct tty_set_buffer_req { 27 | uintptr_t buffer; 28 | size_t size; 29 | }; 30 | -------------------------------------------------------------------------------- /include/sys/types.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | typedef unsigned short umode_t; 6 | -------------------------------------------------------------------------------- /include/sys/uio.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | struct iovec { 6 | void *iov_base; 7 | size_t iov_len; 8 | }; 9 | -------------------------------------------------------------------------------- /include/syscall_defs.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // FIXME: need to share certain definitions between musl and run time, should 6 | // we just copy from musl or there's another way. 7 | 8 | // FIXME: refine NR_syscall_max to maximum number (+1) of syscall 9 | 10 | #define NR_syscall_max 434 11 | 12 | #if !defined(__ASSEMBLER__) 13 | #define asmlinkage 14 | 15 | struct timespec; 16 | 17 | asmlinkage long 18 | sys_set_tid_address(int *tid_ptr); 19 | 20 | // Need to share 21 | asmlinkage long 22 | sys_ppoll(void *ufds, unsigned int nfds, const struct timespec *timeout, 23 | void *sigmask, uint32_t sigsetsize); 24 | 25 | asmlinkage long 26 | sys_openat(int dirfd, const char *pathname, int flags, umode_t mode); 27 | 28 | asmlinkage long 29 | sys_clock_nanosleep(long clock_id, int flags, const struct timespec *request, 30 | struct timespec *remain); 31 | 32 | asmlinkage int 33 | sys_tkill(int tid, int sig); 34 | 35 | asmlinkage void 36 | sys_exit_group(int ec); 37 | 38 | asmlinkage noreturn void 39 | sys_exit(int ec); 40 | 41 | asmlinkage long 42 | sys_brk(unsigned long brk); 43 | 44 | asmlinkage long 45 | sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); 46 | 47 | asmlinkage long 48 | sys_writev(unsigned long fd, uintptr_t vec, unsigned long vlen); 49 | 50 | asmlinkage long 51 | sys_close(unsigned int fd); 52 | #endif 53 | -------------------------------------------------------------------------------- /include/time.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | struct timespec { 6 | long tv_sec; 7 | long tv_nsec; 8 | }; 9 | 10 | #define CLOCK_REALTIME 0 11 | #define CLOCK_MONOTONIC 1 12 | 13 | #define TIMER_ABSTIME 0x01 14 | -------------------------------------------------------------------------------- /include/timer.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | struct timespec; 6 | 7 | void 8 | timer_init(void); 9 | 10 | long 11 | timer_set_and_wait(bool relative, const struct timespec *req, 12 | struct timespec *remain); 13 | -------------------------------------------------------------------------------- /include/tty.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | extern struct file *stdin_file; 6 | extern struct file *stdout_file; 7 | extern struct file *stderr_file; 8 | -------------------------------------------------------------------------------- /include/types.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | typedef uint32_t count_t; 6 | typedef uint32_t index_t; 7 | typedef uint16_t cpu_index_t; 8 | -------------------------------------------------------------------------------- /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 | #define IOCTL_ASSERT_IRQ _IOW(IRQ_MAGIC, 5U, int) 13 | #define IOCTL_CLEAR_IRQ _IOW(IRQ_MAGIC, 6U, int) 14 | 15 | typedef bool (*isr_t)(virq_t, void *); 16 | 17 | struct register_isr_req { 18 | isr_t isr; 19 | virq_t irq; 20 | int32_t res0; 21 | void *data; 22 | }; 23 | 24 | #define IRQ_TRIGGER_LEVEL_HIGH 0 25 | #define IRQ_TRIGGER_LEVEL_LOW 1 26 | #define IRQ_TRIGGER_EDGE_RISING 2 27 | #define IRQ_TRIGGER_EDGE_FALLING 3 28 | #define IRQ_TRIGGER_EDGE_BOTH 4 29 | #define IRQ_TRIGGER_MESSAGE 5 30 | 31 | struct irq_set_trigger_req { 32 | virq_t irq; 33 | int32_t trigger; 34 | }; 35 | -------------------------------------------------------------------------------- /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) - 1)) == 0U) 22 | #define util_add_overflows(a, b) ((a) > ~(b)) 23 | 24 | // Align up or down to bytes (which must be a power of two) 25 | #if defined(__TYPED_DSL__) 26 | #define util_balign_down(x, a) ((x) & ~((a)-1U)) 27 | #else 28 | #define util_balign_down(x, a) \ 29 | (assert(util_is_p2(a)), (x) & ~((__typeof__(x))(a)-1U)) 30 | #endif 31 | #define util_balign_up(x, a) util_balign_down((x) + ((a)-1U), a) 32 | 33 | // Align up or down to a power-of-two size (in bits) 34 | #define util_p2align_down(x, b) \ 35 | (assert((sizeof(x) * 8) > (b)), (((x) >> (b)) << (b))) 36 | #define util_p2align_up(x, b) util_p2align_down((x) + util_bit(b) - 1U, b) 37 | 38 | // Generate an identifier that can be declared inside a macro without 39 | // shadowing anything else declared in the same file, given a base name to 40 | // disambiguate uses within one macro expansion. Generally the name should be 41 | // prefixed with the name of the macro it's being used in. 42 | // 43 | // Note that this should only ever be used as a macro parameter; otherwise 44 | // it is difficult to determine what identifier it expanded to. 45 | #define util_cpp_unique_ident(name) util_cpp_paste_expanded(name, __LINE__) 46 | 47 | // Paste two tokens together, after macro-expansion of the arguments. 48 | #define util_cpp_paste_expanded(name, suffix) util_cpp_paste(name, suffix) 49 | 50 | // Paste two tokens together, before macro-expansion of the arguments. 51 | // 52 | // This is only really useful in util_cpp_paste_expanded(). In any other macro 53 | // definition, use ## directly, which is equivalent and more concise. 54 | #define util_cpp_paste(name, suffix) name##suffix 55 | 56 | // Return the number of elements in an array. 57 | #define util_array_size(a) (sizeof(a) / sizeof((a)[0])) 58 | -------------------------------------------------------------------------------- /repolint.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/todogroup/repolinter/master/rulesets/schema.json", 3 | "version": 2, 4 | "axioms": { 5 | "linguist": "language", 6 | "licensee": "license", 7 | "packagers": "packager" 8 | }, 9 | "rules": { 10 | "license-file-exists": { 11 | "level": "error", 12 | "rule": { 13 | "type": "file-existence", 14 | "options": { 15 | "globsAny": [ 16 | "LICENSE*" 17 | ], 18 | "nocase": true 19 | } 20 | } 21 | }, 22 | "readme-file-exists": { 23 | "level": "error", 24 | "rule": { 25 | "type": "file-existence", 26 | "options": { 27 | "globsAny": [ 28 | "README*" 29 | ], 30 | "nocase": true 31 | } 32 | } 33 | }, 34 | "contributing-file-exists": { 35 | "level": "warning", 36 | "rule": { 37 | "type": "file-existence", 38 | "options": { 39 | "globsAny": [ 40 | "CONTRIBUTING*" 41 | ], 42 | "nocase": true 43 | } 44 | } 45 | }, 46 | "code-of-conduct-file-exists": { 47 | "level": "warning", 48 | "rule": { 49 | "type": "file-existence", 50 | "options": { 51 | "globsAny": [ 52 | "CODE-OF-CONDUCT*" 53 | ], 54 | "nocase": true 55 | } 56 | } 57 | }, 58 | "changelog-file-exists": { 59 | "level": "warning", 60 | "rule": { 61 | "type": "file-existence", 62 | "options": { 63 | "globsAny": [ 64 | "CHANGELOG*" 65 | ], 66 | "nocase": true 67 | } 68 | } 69 | }, 70 | "readme-references-license": { 71 | "level": "error", 72 | "rule": { 73 | "type": "file-contents", 74 | "options": { 75 | "globsAll": [ 76 | "README*" 77 | ], 78 | "content": "license", 79 | "flags": "i" 80 | } 81 | } 82 | }, 83 | "binaries-not-present": { 84 | "level": "warning", 85 | "rule": { 86 | "type": "file-type-exclusion", 87 | "options": { 88 | "type": [ 89 | "**/*.exe", 90 | "**/*.dll", 91 | "**/*.o", 92 | "**/*.so", 93 | "!node_modules/**" 94 | ] 95 | } 96 | } 97 | }, 98 | "integrates-with-ci": { 99 | "level": "warning", 100 | "rule": { 101 | "type": "file-existence", 102 | "options": { 103 | "globsAny": [ 104 | ".gitlab-ci.yml", 105 | ".travis.yml", 106 | "appveyor.yml", 107 | ".appveyor.yml", 108 | "circle.yml", 109 | ".circleci/config.yml", 110 | "Jenkinsfile", 111 | ".drone.yml", 112 | ".github/workflows/*", 113 | "azure-pipelines.yml" 114 | ] 115 | } 116 | } 117 | }, 118 | "source-license-headers-exist": { 119 | "level": "error", 120 | "rule": { 121 | "type": "file-starts-with", 122 | "options": { 123 | "globsAll": [ 124 | "**/*.py", 125 | "**/*.js", 126 | "**/*.c", 127 | "**/*.cc", 128 | "**/*.cpp", 129 | "**/*.h", 130 | "**/*.ts", 131 | "**/*.sh", 132 | "**/*.rs" 133 | ], 134 | "skip-paths-matching": { 135 | "patterns": [ 136 | "tools/cpptest/gunyahkw.h", 137 | "tools/misc/convert-utf-8.sh" 138 | ] 139 | }, 140 | "lineCount": 20, 141 | "patterns": [ 142 | "© 20[2-9][0-9] Qualcomm Innovation Center, Inc", 143 | "SPDX-License-Identifier" 144 | ], 145 | "flags": "i" 146 | } 147 | } 148 | }, 149 | "github-issue-template-exists": { 150 | "level": "warning", 151 | "rule": { 152 | "type": "file-existence", 153 | "options": { 154 | "globsAny": [ 155 | "ISSUE_TEMPLATE*", 156 | ".github/ISSUE_TEMPLATE*" 157 | ] 158 | } 159 | } 160 | }, 161 | "github-pull-request-template-exists": { 162 | "level": "warning", 163 | "rule": { 164 | "type": "file-existence", 165 | "options": { 166 | "globsAny": [ 167 | "PULL_REQUEST_TEMPLATE*", 168 | ".github/PULL_REQUEST_TEMPLATE*" 169 | ] 170 | } 171 | } 172 | }, 173 | "javascript-package-metadata-exists": { 174 | "level": "warning", 175 | "where": [ 176 | "language=javascript" 177 | ], 178 | "rule": { 179 | "type": "file-existence", 180 | "options": { 181 | "globsAny": [ 182 | "package.json" 183 | ] 184 | } 185 | } 186 | }, 187 | "ruby-package-metadata-exists": { 188 | "level": "warning", 189 | "where": [ 190 | "language=ruby" 191 | ], 192 | "rule": { 193 | "type": "file-existence", 194 | "options": { 195 | "globsAny": [ 196 | "Gemfile" 197 | ] 198 | } 199 | } 200 | }, 201 | "java-package-metadata-exists": { 202 | "level": "warning", 203 | "where": [ 204 | "language=java" 205 | ], 206 | "rule": { 207 | "type": "file-existence", 208 | "options": { 209 | "globsAny": [ 210 | "pom.xml", 211 | "build.xml", 212 | "build.gradle" 213 | ] 214 | } 215 | } 216 | }, 217 | "python-package-metadata-exists": { 218 | "level": "warning", 219 | "where": [ 220 | "language=python" 221 | ], 222 | "rule": { 223 | "type": "file-existence", 224 | "options": { 225 | "globsAny": [ 226 | "setup.py", 227 | "requirements.txt" 228 | ] 229 | } 230 | } 231 | }, 232 | "rust-package-metadata-exists": { 233 | "level": "error", 234 | "where": [ 235 | "language=rust" 236 | ], 237 | "rule": { 238 | "type": "file-existence", 239 | "options": { 240 | "globsAny": [ 241 | "Cargo.toml", 242 | "Cargo.lock" 243 | ] 244 | } 245 | } 246 | }, 247 | "objective-c-package-metadata-exists": { 248 | "level": "warning", 249 | "where": [ 250 | "language=objective-c" 251 | ], 252 | "rule": { 253 | "type": "file-existence", 254 | "options": { 255 | "globsAny": [ 256 | "Cartfile", 257 | "Podfile", 258 | "*.podspec" 259 | ] 260 | } 261 | } 262 | }, 263 | "swift-package-metadata-exists": { 264 | "level": "warning", 265 | "where": [ 266 | "language=swift" 267 | ], 268 | "rule": { 269 | "type": "file-existence", 270 | "options": { 271 | "globsAny": [ 272 | "Package.swift" 273 | ] 274 | } 275 | } 276 | }, 277 | "erlang-package-metadata-exists": { 278 | "level": "warning", 279 | "where": [ 280 | "language=erlang" 281 | ], 282 | "rule": { 283 | "type": "file-existence", 284 | "options": { 285 | "globsAny": [ 286 | "rebar.config" 287 | ] 288 | } 289 | } 290 | }, 291 | "elixir-package-metadata-exists": { 292 | "level": "warning", 293 | "where": [ 294 | "language=elixir" 295 | ], 296 | "rule": { 297 | "type": "file-existence", 298 | "options": { 299 | "globsAny": [ 300 | "mix.exs" 301 | ] 302 | } 303 | } 304 | }, 305 | "license-detectable-by-licensee": { 306 | "level": "off", 307 | "where": [ 308 | "license=*" 309 | ], 310 | "rule": { 311 | "type": "license-detectable-by-licensee", 312 | "options": {} 313 | } 314 | } 315 | } 316 | } 317 | -------------------------------------------------------------------------------- /src/auxvec.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 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include "device_tree.h" 21 | #include "mmap.h" 22 | 23 | // FIXME: should we expose certain hw caps to app 24 | #define ELF_HWCAP (0x0) 25 | 26 | extern uintptr_t app_stack; 27 | 28 | extern rt_env_data_t *env_data; 29 | 30 | typedef uint64_t elf_addr_t; 31 | 32 | // FIXME: test code, remove it 33 | static const char *app_name = "app"; 34 | 35 | static uint32_t aux_entropy[4]; 36 | 37 | // return entry start address 38 | uintptr_t 39 | elf_setup(void); 40 | 41 | // initial auxiliary vector table 42 | static uintptr_t 43 | setup_auxvector(uint64_t **stack, uint64_t app_addr); 44 | 45 | static void 46 | setup_envs(uint64_t **stack, int envc, char **envp); 47 | 48 | static void 49 | setup_arguments(uint64_t **stack, int argc, char **arg_values); 50 | 51 | static bool 52 | get_aux_entropy(void) 53 | { 54 | gunyah_hyp_prng_get_entropy_result_t ret; 55 | 56 | ret = gunyah_hyp_prng_get_entropy(16U); 57 | if (ret.error == OK) { 58 | aux_entropy[0] = ret.data0; 59 | aux_entropy[1] = ret.data1; 60 | aux_entropy[2] = ret.data2; 61 | aux_entropy[3] = ret.data3; 62 | } 63 | 64 | return ret.error == OK; 65 | } 66 | 67 | static uint64_t * 68 | fill_entry(uint64_t *stack, uint64_t value) 69 | { 70 | uint64_t *p = stack - 1; 71 | *p = value; 72 | return p; 73 | } 74 | 75 | static uint64_t * 76 | fill_auxv_entry(uint64_t *stack, uint64_t key, uint64_t value) 77 | { 78 | uint64_t *p = stack; 79 | 80 | p = fill_entry(p, value); 81 | p = fill_entry(p, key); 82 | return p; 83 | } 84 | 85 | // FIXME: should we use asmlinkage for stack only 86 | static uintptr_t 87 | setup_auxvector(uint64_t **stack, uintptr_t app_addr) 88 | { 89 | Elf64_Ehdr *ehdr = (Elf64_Ehdr *)app_addr; 90 | uintptr_t phdr_addr = ehdr->e_phoff + app_addr; 91 | size_t ph_entry_cnt = ehdr->e_phnum; 92 | uintptr_t entry_addr = ehdr->e_entry + app_addr; 93 | uint64_t *p = *stack; 94 | 95 | p = fill_auxv_entry(p, AT_PAGESZ, PAGE_SIZE); 96 | 97 | p = fill_auxv_entry(p, AT_PHDR, phdr_addr); 98 | p = fill_auxv_entry(p, AT_PHENT, sizeof(Elf64_Phdr)); 99 | p = fill_auxv_entry(p, AT_PHNUM, ph_entry_cnt); 100 | p = fill_auxv_entry(p, AT_EXECFN, (uintptr_t)app_name); 101 | 102 | if (get_aux_entropy()) { 103 | p = fill_auxv_entry(p, AT_RANDOM, (uintptr_t)aux_entropy); 104 | } 105 | 106 | // update stack pointer 107 | *stack = p; 108 | 109 | return entry_addr; 110 | } 111 | 112 | static void 113 | setup_envs(uint64_t **stack, int envc, char **envp) 114 | { 115 | uint64_t *p = *stack; 116 | int idx = 0; 117 | 118 | assert(envc >= 0); 119 | 120 | // set terminator at the bottom 121 | p = fill_entry(p, 0UL); 122 | 123 | // fill envp 124 | for (idx = envc - 1; idx >= 0; idx--) { 125 | p = fill_entry(p, (uintptr_t)envp[idx]); 126 | } 127 | 128 | // update stack pointer 129 | *stack = p; 130 | } 131 | 132 | static void 133 | setup_arguments(uint64_t **stack, int argc, char **arg_values) 134 | { 135 | uint64_t *p = *stack; 136 | int idx = 0; 137 | 138 | assert(argc >= 0); 139 | 140 | // set stack 141 | p = fill_entry(p, 0UL); 142 | for (idx = argc - 1; idx >= 0; idx--) { 143 | p = fill_entry(p, (uintptr_t)arg_values[idx]); 144 | } 145 | p = fill_entry(p, (uint64_t)argc); 146 | 147 | // update stack pointer 148 | *stack = p; 149 | } 150 | 151 | // FIXME: we assume 16KiB stack is sufficient 152 | #define STACK_SIZE (16UL * 1024UL) 153 | 154 | uintptr_t 155 | elf_setup(void) 156 | { 157 | uint64_t app_address = env_data->app_ipa; 158 | size_t app_memory_size = env_data->app_heap_size; 159 | uintptr_t app_memory = env_data->app_heap_ipa; 160 | 161 | // Place the stack below the heap to avoid collisions 162 | assert(app_memory_size > STACK_SIZE); 163 | app_stack = app_memory + STACK_SIZE; 164 | 165 | // Add canary for overflow detection 166 | (void)memset((void *)app_memory, 0xeb, 64); 167 | 168 | app_memory += STACK_SIZE; 169 | app_memory_size -= STACK_SIZE; 170 | 171 | // calculate application stack and heap 172 | uintptr_t app_heap = app_memory; 173 | init_heap(app_heap, app_memory_size); 174 | 175 | // parse dtb to get commandline, arg count, env count, envs 176 | device_tree_info_t device_tree_info; 177 | device_tree_info = parse_device_tree(); 178 | 179 | uint64_t *stack = (uint64_t *)app_stack; 180 | 181 | // Set the end-marker 182 | stack = fill_entry(stack, 0UL); 183 | 184 | // FIXME: push argument and env strings here 185 | // ensure stack is aligned down back to uint64_t after this 186 | 187 | // Add padding to ensure we end with a 16-byte aligned stack. 188 | // argv and envp are the two variables to be concerned with. 189 | // We don't actually count auxv entries since each is already 16-byte 190 | // sized. 191 | uintptr_t aux_size_var = 192 | (2UL /* argc + NULL */ + device_tree_info.argc /* argv[] */ + 193 | device_tree_info.envc + 1UL /* envp[term] */) * 194 | sizeof(uintptr_t); 195 | 196 | count_t pad = (count_t)(((aux_size_var + (uintptr_t)stack) % 16UL) / 197 | sizeof(uintptr_t)); 198 | 199 | while (pad != 0U) { 200 | stack = fill_entry(stack, 0UL); 201 | pad -= 1U; 202 | } 203 | 204 | uintptr_t app_entry; 205 | app_entry = setup_auxvector(&stack, app_address); 206 | 207 | setup_envs(&stack, (int)device_tree_info.envc, device_tree_info.envp); 208 | 209 | setup_arguments(&stack, (int)device_tree_info.argc, 210 | device_tree_info.argv); 211 | 212 | // check stack is aligned to 16-bytes 213 | assert(util_is_baligned((uintptr_t)stack, 16U)); 214 | 215 | app_stack = (uintptr_t)stack; 216 | 217 | return app_entry; 218 | } 219 | -------------------------------------------------------------------------------- /src/boot.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 | #include 13 | 14 | #pragma clang diagnostic push 15 | #pragma clang diagnostic ignored "-Wreserved-identifier" 16 | extern uintptr_t __stack_chk_guard; 17 | uintptr_t __stack_chk_guard __attribute__((used, visibility("hidden"))); 18 | #pragma clang diagnostic pop 19 | 20 | void 21 | runtime_init(void); 22 | 23 | // We must disable stack protection for this function, as the compiler may not 24 | // optimise the call to gunyah_hyp_prng_get_entropy() and place the result on 25 | // the stack, which will trigger the use of the stack canary before it is 26 | // initialised and lead to a stack check failure. 27 | __attribute__((no_stack_protector)) void 28 | runtime_init(void) 29 | { 30 | // Get some entropy and init the stack canary. 31 | gunyah_hyp_prng_get_entropy_result_t ret = 32 | gunyah_hyp_prng_get_entropy(8U); 33 | 34 | uint64_t guard = (ret.error == OK) 35 | ? (ret.data0 | ((uint64_t)ret.data1 << 32)) 36 | : 0x1f2c38a9b459e37dUL; 37 | 38 | __stack_chk_guard = (uintptr_t)guard; 39 | 40 | // Initialise the rest of the runtime. 41 | interrupt_init(); 42 | fs_init(); 43 | timer_init(); 44 | } 45 | -------------------------------------------------------------------------------- /src/build.conf: -------------------------------------------------------------------------------- 1 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | 5 | source auxvec.c syscall.c log.c string_util.c mmap.c device_tree.c ioctl.c 6 | source read_write.c reloc.c interrupt.c fs.c tty.c string.c timer.c exit.c 7 | source log_buf.c console.c exit_dev.c boot.c 8 | 9 | # Hypervisor APIs 10 | source guest_interface.c guest_accessors.c guest_hypresult.c 11 | -------------------------------------------------------------------------------- /src/console.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 | 11 | #include 12 | #include 13 | #include 14 | 15 | static char prefix[16]; 16 | static ssize_t prefix_len = 0; 17 | 18 | static console_t console; 19 | 20 | void 21 | console_write(const char *msg, size_t sz) 22 | { 23 | if (console != NULL) { 24 | if (msg == NULL) { 25 | if (prefix_len > 0) { 26 | console(prefix, (size_t)prefix_len); 27 | } 28 | } else { 29 | console(msg, sz); 30 | } 31 | } 32 | } 33 | 34 | int 35 | console_register(console_t new_console) 36 | { 37 | int ret; 38 | 39 | if (console != NULL) { 40 | ret = -EBUSY; 41 | goto out; 42 | } 43 | 44 | console = new_console; 45 | ret = 0; 46 | 47 | out: 48 | return ret; 49 | } 50 | 51 | int 52 | console_deregister(void) 53 | { 54 | int ret; 55 | 56 | if (console == NULL) { 57 | ret = -ENOENT; 58 | goto out; 59 | } 60 | 61 | console = NULL; 62 | ret = 0; 63 | 64 | out: 65 | return ret; 66 | } 67 | 68 | static long 69 | console_ioctl(unsigned int cmd, unsigned long arg) 70 | { 71 | long ret; 72 | 73 | switch (cmd) { 74 | case IOCTL_REGISTER_CONSOLE: { 75 | struct register_console_req *data = 76 | (struct register_console_req *)arg; 77 | ret = console_register(data->console); 78 | break; 79 | } 80 | case IOCTL_DEREGISTER_CONSOLE: { 81 | ret = console_deregister(); 82 | break; 83 | } 84 | case IOCTL_SET_PREFIX_CONSOLE: { 85 | const char *uprefix = (char *)arg; 86 | prefix_len = strscpy(prefix, uprefix, 16); 87 | if (prefix_len < 0) { 88 | ret = prefix_len; 89 | prefix_len = 0; 90 | } else { 91 | ret = 0; 92 | } 93 | break; 94 | } 95 | default: 96 | ret = -ENOSYS; 97 | break; 98 | } 99 | 100 | return ret; 101 | } 102 | 103 | static struct fs_ops console_ops = { 104 | .ioctl = console_ioctl, 105 | }; 106 | 107 | static struct file console_file = { 108 | .ops = &console_ops, 109 | }; 110 | 111 | long 112 | console_open(int flags) 113 | { 114 | return fs_alloc_fd(&console_file, flags); 115 | } 116 | -------------------------------------------------------------------------------- /src/device_tree.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 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include "device_tree.h" 16 | 17 | #define ARGC 4 18 | #define ENVC 1 19 | 20 | extern rt_env_data_t *env_data; 21 | 22 | extern size_t early_log_buf_size; 23 | 24 | device_tree_info_t 25 | parse_device_tree(void) 26 | { 27 | static char *argv[ARGC]; 28 | static char exec_name[] = { "rootvm" }; 29 | static char *envp[ENVC] = { exec_name }; 30 | 31 | device_tree_info_t ret; 32 | 33 | argv[0] = envp[0]; 34 | 35 | argv[1] = (char *)env_data + sizeof(rt_env_data_t); 36 | 37 | // The address of the log buffer so RM can report it back to hypervisor 38 | argv[2] = (char *)log_buf; 39 | argv[3] = (char *)early_log_buf_size; 40 | 41 | ret.argv = argv; 42 | ret.argc = ARGC; 43 | 44 | ret.envc = ENVC; 45 | ret.envp = envp; 46 | 47 | return ret; 48 | } 49 | -------------------------------------------------------------------------------- /src/device_tree.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | typedef struct { 6 | size_t argc; 7 | char **argv; 8 | size_t envc; 9 | char **envp; 10 | } device_tree_info_t; 11 | 12 | device_tree_info_t 13 | parse_device_tree(void); 14 | -------------------------------------------------------------------------------- /src/exit.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 | 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | static noreturn void 22 | exit_loop(int ec) 23 | { 24 | LOG(ERROR, PANIC, "sys_exit/sys_exit_group: called\n"); 25 | 26 | platform_irq_disable_all(); 27 | exit_trigger(ec); 28 | 29 | for (;;) { 30 | // FIXME: 31 | asm_wait_for_event(&ec); 32 | } 33 | } 34 | 35 | asmlinkage noreturn void 36 | sys_exit(int ec) 37 | { 38 | exit_loop(ec); 39 | } 40 | 41 | asmlinkage noreturn void 42 | sys_exit_group(int ec) 43 | { 44 | exit_loop(ec); 45 | } 46 | -------------------------------------------------------------------------------- /src/exit_dev.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 | 9 | #include 10 | #include 11 | #include 12 | 13 | static exit_t exit_func; 14 | 15 | void 16 | exit_trigger(int exit_code) 17 | { 18 | if (exit_func != NULL) { 19 | exit_func(exit_code); 20 | } 21 | } 22 | 23 | int 24 | exit_register(exit_t new_exit_func) 25 | { 26 | int ret; 27 | 28 | if (exit_func != NULL) { 29 | ret = -EBUSY; 30 | } else { 31 | if (new_exit_func != NULL) { 32 | exit_func = new_exit_func; 33 | ret = 0; 34 | } else { 35 | ret = -EINVAL; 36 | } 37 | } 38 | 39 | return ret; 40 | } 41 | 42 | int 43 | exit_deregister(void) 44 | { 45 | int ret; 46 | 47 | if (exit_func == NULL) { 48 | ret = -ENOENT; 49 | } else { 50 | exit_func = NULL; 51 | ret = 0; 52 | } 53 | 54 | return ret; 55 | } 56 | 57 | static long 58 | exit_ioctl(unsigned int cmd, unsigned long arg) 59 | { 60 | long ret; 61 | 62 | switch (cmd) { 63 | case IOCTL_REGISTER_EXIT: { 64 | struct register_exit_req *data = 65 | (struct register_exit_req *)arg; 66 | ret = exit_register(data->exit_func); 67 | break; 68 | } 69 | case IOCTL_DEREGISTER_EXIT: { 70 | ret = exit_deregister(); 71 | break; 72 | } 73 | default: 74 | ret = -ENOSYS; 75 | break; 76 | } 77 | 78 | return ret; 79 | } 80 | 81 | static struct fs_ops exit_ops = { 82 | .ioctl = exit_ioctl, 83 | }; 84 | 85 | static struct file exit_file = { 86 | .ops = &exit_ops, 87 | }; 88 | 89 | long 90 | exit_open(int flags) 91 | { 92 | return fs_alloc_fd(&exit_file, flags); 93 | } 94 | -------------------------------------------------------------------------------- /src/fs.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 | #include 12 | #include 13 | 14 | #include 15 | 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 | 30 | #define NUM_FDS 32U 31 | 32 | static register_t fd_alloc; 33 | static_assert(sizeof(register_t) * CHAR_BIT >= NUM_FDS, 34 | "Too many FDs for allocator"); 35 | 36 | static struct file_p file_table[NUM_FDS]; 37 | 38 | void 39 | fs_init(void) 40 | { 41 | fd_alloc = (1U << STDIN_FILENO) | (1U << STDOUT_FILENO) | 42 | (1U << STDERR_FILENO); 43 | file_table[STDIN_FILENO] = (struct file_p){ 44 | .file = stdin_file, 45 | .flags = FS_READ, 46 | }; 47 | file_table[STDOUT_FILENO] = (struct file_p){ 48 | .file = stdout_file, 49 | .flags = FS_WRITE, 50 | }; 51 | file_table[STDERR_FILENO] = (struct file_p){ 52 | .file = stderr_file, 53 | .flags = FS_WRITE, 54 | }; 55 | } 56 | 57 | long 58 | fs_alloc_fd(struct file *f, int o_flags) 59 | { 60 | long ret; 61 | unsigned long fd; 62 | 63 | assert(f != NULL); 64 | 65 | if (fd_alloc == 0U) { 66 | fd = 0; 67 | } else { 68 | fd = compiler_ctz(~fd_alloc); 69 | } 70 | 71 | if (fd >= NUM_FDS) { 72 | ret = -ENFILE; 73 | goto out; 74 | } 75 | 76 | fd_alloc |= 1UL << fd; 77 | 78 | uint64_t flags = 0U; 79 | uint32_t accmode = (uint32_t)o_flags & (uint32_t)O_ACCMODE; 80 | if ((accmode == (uint32_t)O_RDONLY) || (accmode == (uint32_t)O_RDWR)) { 81 | flags |= (uint64_t)FS_READ; 82 | } 83 | if ((accmode == (uint32_t)O_WRONLY) || (accmode == (uint32_t)O_RDWR)) { 84 | flags |= (uint64_t)FS_WRITE; 85 | } 86 | 87 | file_table[fd].file = f; 88 | file_table[fd].flags = (long)flags; 89 | ret = (long)fd; 90 | 91 | out: 92 | return ret; 93 | } 94 | 95 | struct file_p * 96 | fs_lookup_file(unsigned long fd) 97 | { 98 | struct file_p *fp = NULL; 99 | 100 | if (fd < NUM_FDS && file_table[fd].file != NULL) { 101 | fp = &file_table[fd]; 102 | } 103 | 104 | return fp; 105 | } 106 | 107 | asmlinkage long 108 | sys_openat(int dirfd, const char *pathname, int flags, umode_t mode) 109 | { 110 | long ret; 111 | 112 | if (dirfd != AT_FDCWD) { 113 | ret = -EINVAL; 114 | goto out; 115 | } 116 | 117 | if (((uint32_t)flags & 118 | ~((uint32_t)O_ACCMODE | (uint32_t)O_LARGEFILE)) != 0U || 119 | mode != 0U) { 120 | ret = -EINVAL; 121 | goto out; 122 | } 123 | 124 | if (strcmp(pathname, PLATFORM_IRQ_DEV_PATH) == 0) { 125 | ret = interrupt_open(flags); 126 | } else if (strcmp(pathname, PLATFORM_CONSOLE_DEV_PATH) == 0) { 127 | ret = console_open(flags); 128 | } else if (strcmp(pathname, PLATFORM_EXIT_DEV_PATH) == 0) { 129 | ret = exit_open(flags); 130 | } else { 131 | ret = -ENOENT; 132 | } 133 | 134 | out: 135 | return ret; 136 | } 137 | 138 | asmlinkage long 139 | sys_close(unsigned int fd) 140 | { 141 | long ret; 142 | 143 | struct file_p *fp = fs_lookup_file(fd); 144 | if (fp == NULL) { 145 | ret = -EBADF; 146 | goto out; 147 | } 148 | 149 | (void)memset(fp, 0, sizeof(*fp)); 150 | fd_alloc &= ~((register_t)1U << fd); 151 | ret = 0; 152 | 153 | out: 154 | return ret; 155 | } 156 | -------------------------------------------------------------------------------- /src/interrupt.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 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | // FIXME: should be generated into include/guest_types.h 20 | #define VIRQ_INVALID ~(virq_t)0U 21 | 22 | static char irq_ordering; 23 | 24 | struct isr_entry { 25 | isr_t isr; 26 | void *data; 27 | }; 28 | 29 | static struct isr_entry isr_table[PLATFORM_NUM_IRQS]; 30 | 31 | void 32 | interrupt_init(void) 33 | { 34 | platform_irq_init(); 35 | } 36 | 37 | static bool 38 | have_isr(virq_t irq) 39 | { 40 | return isr_table[irq].isr != NULL; 41 | } 42 | 43 | int 44 | interrupt_register_isr(virq_t irq, isr_t isr, void *data) 45 | { 46 | int ret; 47 | 48 | if (irq >= PLATFORM_NUM_IRQS) { 49 | ret = -EINVAL; 50 | goto out; 51 | } 52 | 53 | if (have_isr(irq)) { 54 | ret = -EBUSY; 55 | goto out; 56 | } 57 | 58 | isr_table[irq].isr = isr; 59 | isr_table[irq].data = data; 60 | ret = 0; 61 | 62 | out: 63 | return ret; 64 | } 65 | 66 | int 67 | interrupt_deregister_isr(virq_t irq) 68 | { 69 | int ret; 70 | 71 | if (irq >= PLATFORM_NUM_IRQS) { 72 | ret = -EINVAL; 73 | goto out; 74 | } 75 | 76 | if (!have_isr(irq)) { 77 | ret = -ENOENT; 78 | goto out; 79 | } 80 | 81 | isr_table[irq].isr = NULL; 82 | isr_table[irq].data = NULL; 83 | ret = 0; 84 | 85 | out: 86 | return ret; 87 | } 88 | 89 | void 90 | interrupt_dispatch(void) 91 | { 92 | while (true) { 93 | virq_t irq = platform_irq_acknowledge(); 94 | 95 | if (irq == VIRQ_INVALID) { 96 | break; 97 | } 98 | 99 | struct isr_entry *i = &isr_table[irq]; 100 | if (i->isr == NULL) { 101 | platform_irq_disable(irq); 102 | platform_irq_deactivate(irq); 103 | continue; 104 | } 105 | 106 | bool handled = i->isr(irq, i->data); 107 | platform_irq_priority_drop(irq); 108 | if (!handled) { 109 | platform_irq_disable(irq); 110 | } 111 | platform_irq_deactivate(irq); 112 | } 113 | } 114 | 115 | static long 116 | update_irq(virq_t irq, bool enable) 117 | { 118 | long ret; 119 | 120 | if (!have_isr(irq)) { 121 | ret = -ENOENT; 122 | goto out; 123 | } 124 | 125 | if (enable) { 126 | platform_irq_enable(irq); 127 | } else { 128 | platform_irq_disable(irq); 129 | } 130 | 131 | ret = 0; 132 | 133 | out: 134 | return ret; 135 | } 136 | 137 | static long 138 | assert_irq(virq_t irq, bool assert) 139 | { 140 | long ret; 141 | 142 | if (!have_isr(irq)) { 143 | ret = -ENOENT; 144 | goto out; 145 | } 146 | 147 | if (assert) { 148 | platform_irq_assert(irq); 149 | } else { 150 | platform_irq_clear(irq); 151 | } 152 | 153 | ret = 0; 154 | 155 | out: 156 | return ret; 157 | } 158 | 159 | static long 160 | interrupt_ioctl(unsigned int cmd, unsigned long arg) 161 | { 162 | long ret; 163 | 164 | switch (cmd) { 165 | case IOCTL_ENABLE_IRQ: 166 | ret = update_irq(*(virq_t *)arg, true); 167 | break; 168 | case IOCTL_DISABLE_IRQ: 169 | ret = update_irq(*(virq_t *)arg, false); 170 | break; 171 | case IOCTL_ASSERT_IRQ: 172 | ret = assert_irq(*(virq_t *)arg, true); 173 | break; 174 | case IOCTL_CLEAR_IRQ: 175 | ret = assert_irq(*(virq_t *)arg, false); 176 | break; 177 | case IOCTL_REGISTER_ISR: { 178 | struct register_isr_req *data = (struct register_isr_req *)arg; 179 | ret = interrupt_register_isr(data->irq, data->isr, data->data); 180 | break; 181 | } 182 | case IOCTL_DEREGISTER_ISR: { 183 | ret = interrupt_deregister_isr(*(virq_t *)arg); 184 | break; 185 | } 186 | case IOCTL_SET_IRQ_TRIGGER: { 187 | struct irq_set_trigger_req *data = 188 | (struct irq_set_trigger_req *)arg; 189 | ret = (platform_irq_set_trigger(data->irq, data->trigger)) 190 | ? 0 191 | : -EINVAL; 192 | break; 193 | } 194 | default: 195 | ret = -ENOSYS; 196 | break; 197 | } 198 | 199 | return ret; 200 | } 201 | 202 | static struct fs_ops irq_ops = { 203 | .ioctl = interrupt_ioctl, 204 | }; 205 | 206 | static struct file irq_file = { 207 | .ops = &irq_ops, 208 | }; 209 | 210 | long 211 | interrupt_open(int flags) 212 | { 213 | return fs_alloc_fd(&irq_file, flags); 214 | } 215 | 216 | bool 217 | interrupt_wait(void) 218 | { 219 | asm_wait_for_interrupt(&irq_ordering); 220 | 221 | bool pending = asm_interrupt_pending(&irq_ordering); 222 | 223 | if (pending) { 224 | interrupt_dispatch(); 225 | } 226 | 227 | return pending; 228 | } 229 | -------------------------------------------------------------------------------- /src/ioctl.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 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | asmlinkage long 20 | sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) 21 | { 22 | long ret; 23 | 24 | struct file_p *fp = fs_lookup_file(fd); 25 | if (fp == NULL) { 26 | ret = -EBADF; 27 | goto out; 28 | } 29 | 30 | struct file *f = fp->file; 31 | assert(f != NULL); 32 | if (f->ops->ioctl == NULL) { 33 | ret = -EINVAL; 34 | goto out; 35 | } 36 | 37 | ret = f->ops->ioctl(cmd, arg); 38 | 39 | out: 40 | return ret; 41 | } 42 | -------------------------------------------------------------------------------- /src/log.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 | 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define SINGLE_LOG_MSG_SIZE (256) 20 | 21 | noreturn void 22 | assert_failed(const char *file, int line, const char *func, const char *err); 23 | 24 | void 25 | log_msg(uint64_t level, uint64_t action, const char *a1, size_t a2, 26 | register_t a3, register_t a4, register_t a5, register_t a6) 27 | { 28 | char tmp_log[SINGLE_LOG_MSG_SIZE]; 29 | 30 | // FIXME: ignore level and action 31 | (void)level; 32 | (void)action; 33 | size_result_t ret = 34 | snprint(tmp_log, SINGLE_LOG_MSG_SIZE, a1, a2, a3, a4, a5, a6); 35 | 36 | // send to console and log 37 | console_write(tmp_log, ret.r); 38 | log_append(tmp_log, ret.r); 39 | } 40 | 41 | #if !defined(NDEBUG) 42 | noreturn void 43 | assert_failed(const char *file, int line, const char *func, const char *err) 44 | { 45 | LOG(ERROR, PANIC, "assertion: {:s} in func({:s}) file({:s}:{:d})\n", 46 | (register_t)(uintptr_t)err, (register_t)(uintptr_t)func, 47 | (register_t)(uintptr_t)file, (register_t)line); 48 | 49 | panic("Failure for assertion\n"); 50 | } 51 | #endif 52 | -------------------------------------------------------------------------------- /src/log_buf.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 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | static struct log_s early_log_buf = { 0, EARLY_SIZE, { 0 } }; 17 | 18 | struct log_s *log_buf = &early_log_buf; 19 | 20 | extern size_t early_log_buf_size; 21 | size_t early_log_buf_size = sizeof(early_log_buf); 22 | 23 | void 24 | log_set_buffer(uintptr_t new_addr, size_t area_sz) 25 | { 26 | assert(new_addr != 0U); 27 | assert(area_sz > (sizeof(size_t) * 2)); 28 | assert(area_sz <= 524288); 29 | 30 | log_buf = (struct log_s *)new_addr; 31 | log_buf->write_idx = 0U; 32 | // Update size of log_buf->buffer[] 33 | log_buf->size = 34 | (uint32_t)(area_sz - sizeof(uint32_t) - sizeof(uint32_t)); 35 | } 36 | 37 | void 38 | log_append(const char *msg, size_t sz) 39 | { 40 | assert(log_buf != NULL); 41 | 42 | if (sz >= log_buf->size) { 43 | // truncate the log message 44 | msg = msg + sz - (log_buf->size - 1U); 45 | sz = log_buf->size - 1UL; 46 | } 47 | if (log_buf->write_idx + sz < log_buf->size) { 48 | (void)memcpy(log_buf->buffer + log_buf->write_idx, msg, sz); 49 | log_buf->write_idx += (uint32_t)sz; 50 | } else { 51 | size_t first_len, second_len; 52 | 53 | first_len = 54 | (size_t)(log_buf->size) - (size_t)log_buf->write_idx; 55 | second_len = sz - first_len; 56 | (void)memcpy(log_buf->buffer + log_buf->write_idx, msg, 57 | first_len); 58 | 59 | if (second_len > 0U) { 60 | (void)memcpy(log_buf->buffer, msg + first_len, 61 | second_len); 62 | } 63 | 64 | log_buf->write_idx = (uint32_t)second_len; 65 | } 66 | // Ensure log is always NULL terminated. 67 | log_buf->buffer[log_buf->write_idx] = '\0'; 68 | } 69 | -------------------------------------------------------------------------------- /src/mmap.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 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "mmap.h" 18 | 19 | static uintptr_t heap_bottom; 20 | static size_t heap_size; 21 | static uintptr_t cur_brk; 22 | 23 | void 24 | init_heap(uintptr_t base, size_t size) 25 | { 26 | // heap bottom should be PAGE aligned, musl aligns it if it's not. 27 | assert(util_is_baligned(base, PAGE_SIZE)); 28 | assert(util_is_baligned(size, PAGE_SIZE)); 29 | 30 | heap_bottom = base; 31 | cur_brk = base; 32 | heap_size = size; 33 | } 34 | 35 | asmlinkage long 36 | sys_brk(unsigned long brk) 37 | { 38 | uintptr_t new_brk = util_balign_up(brk, PAGE_SIZE); 39 | 40 | if ((new_brk >= heap_bottom) && (new_brk <= heap_bottom + heap_size)) { 41 | cur_brk = new_brk; 42 | } else if (brk != 0UL) { 43 | // brk not in heap range 44 | LOG(ERROR, MSG, "{:s}: invalid brk {:#x}\n", 45 | (register_t) __func__, brk); 46 | } else { 47 | // It's just query the heap top with brk == 0 48 | } 49 | 50 | return (long)cur_brk; 51 | } 52 | -------------------------------------------------------------------------------- /src/mmap.h: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | void 6 | init_heap(uintptr_t base, size_t size); 7 | -------------------------------------------------------------------------------- /src/read_write.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 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | asmlinkage long 22 | sys_writev(unsigned long fd, uintptr_t vec, unsigned long vlen) 23 | { 24 | const struct iovec *vecp = (const struct iovec *)vec; 25 | long ret; 26 | 27 | struct file_p *fp = fs_lookup_file(fd); 28 | if ((fp == NULL) || 29 | (((uint64_t)fp->flags & (uint64_t)FS_WRITE) == 0UL)) { 30 | ret = -EBADF; 31 | goto out; 32 | } 33 | 34 | struct file *f = fp->file; 35 | assert(f != NULL); 36 | if (f->ops->writev == NULL) { 37 | ret = -EINVAL; 38 | goto out; 39 | } 40 | 41 | ret = f->ops->writev(vecp, vlen); 42 | 43 | out: 44 | return ret; 45 | } 46 | -------------------------------------------------------------------------------- /src/reloc.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 | 13 | #include 14 | 15 | // We must disable stack protection for this function, because the compiler 16 | // might use a relocated absolute pointer to load the stack cookie in the 17 | // function prologue, which will crash because this function hasn't run yet. 18 | __attribute__((no_stack_protector)) void 19 | rel_fixup(Elf64_Dyn *dyni, rt_env_data_t *env_data) 20 | { 21 | Elf64_Addr base = env_data->runtime_ipa; 22 | 23 | Elf64_Addr dyn[DT_CNT] = { 0 }; 24 | Elf64_Rel *rel = NULL; 25 | Elf64_Rel *rel_end = NULL; 26 | Elf64_Rela *rela = NULL; 27 | Elf64_Rela *rela_end = NULL; 28 | 29 | for (; dyni->d_tag != DT_NULL; dyni += 1) { 30 | if (dyni->d_tag < DT_CNT) { 31 | dyn[dyni->d_tag] = dyni->d_un.d_ptr; 32 | } 33 | } 34 | 35 | rel = (Elf64_Rel *)(dyn[DT_REL] + base); 36 | rel_end = (Elf64_Rel *)(dyn[DT_REL] + base + dyn[DT_RELSZ]); 37 | // Loop will not execute if the toolchain does not generate DT_REL 38 | for (; rel < rel_end; rel++) { 39 | if (!ARCH_CAN_PATCH(rel->r_info)) { 40 | continue; 41 | } 42 | Elf64_Addr *r = (Elf64_Addr *)(rel->r_offset + base); 43 | *r += base; 44 | } 45 | 46 | rela = (Elf64_Rela *)(dyn[DT_RELA] + base); 47 | rela_end = (Elf64_Rela *)(dyn[DT_RELA] + base + dyn[DT_RELASZ]); 48 | // Loop will not execute if the toolchain does not generate DT_RELA 49 | for (; rela < rela_end; rela++) { 50 | if (!ARCH_CAN_PATCH(rela->r_info)) { 51 | continue; 52 | } 53 | Elf64_Addr *r = (Elf64_Addr *)(rela->r_offset + base); 54 | *r = base + (Elf64_Addr)rela->r_addend; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/string.c: -------------------------------------------------------------------------------- 1 | // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | #include 6 | 7 | int 8 | strcmp(const char *s1, const char *s2) 9 | { 10 | const char *l = s1, *r = s2; 11 | 12 | while ((*l != '\0') && (*l == *r)) { 13 | l++; 14 | r++; 15 | } 16 | 17 | return *l - *r; 18 | } 19 | -------------------------------------------------------------------------------- /src/syscall.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 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | asmlinkage long 22 | sys_set_tid_address(int *tid_ptr) 23 | { 24 | (void)tid_ptr; 25 | return 0xdeadbeefL; 26 | } 27 | 28 | asmlinkage long 29 | sys_ppoll(void *ufds, unsigned int nfds, const struct timespec *timeout, 30 | void *sigmask, uint32_t sigsetsize) 31 | { 32 | long ret; 33 | 34 | (void)ufds; 35 | (void)sigmask; 36 | (void)sigsetsize; 37 | 38 | if (nfds != 0U) { 39 | ret = -EINVAL; 40 | goto out; 41 | } 42 | 43 | if (timeout != NULL) { 44 | ret = timer_set_and_wait(true, timeout, NULL); 45 | } else { 46 | (void)interrupt_wait(); 47 | ret = -EINTR; 48 | } 49 | 50 | out: 51 | return ret; 52 | } 53 | 54 | asmlinkage long 55 | sys_clock_nanosleep(long clock_id, int flags, const struct timespec *request, 56 | struct timespec *remain) 57 | { 58 | long ret; 59 | 60 | if (clock_id != CLOCK_MONOTONIC) { 61 | // FIXME: Also accept CLOCK_REALTIME? 62 | ret = -EINVAL; 63 | goto out; 64 | } 65 | 66 | if (flags == 0) { 67 | ret = timer_set_and_wait(true, request, remain); 68 | } else if (flags == TIMER_ABSTIME) { 69 | ret = timer_set_and_wait(false, request, NULL); 70 | } else { 71 | ret = -EINVAL; 72 | } 73 | 74 | out: 75 | return ret; 76 | } 77 | 78 | asmlinkage int 79 | sys_tkill(int tid, int sig) 80 | { 81 | (void)tid; 82 | (void)sig; 83 | 84 | sys_exit(1); 85 | } 86 | -------------------------------------------------------------------------------- /src/timer.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 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #define NS_PER_S 1000000000 25 | 26 | #define TIMESPEC_MAX_NSEC (NS_PER_S - 1) 27 | 28 | extern rt_env_data_t *env_data; 29 | 30 | static uint64_t timer_freq; 31 | static long timespec_max_sec; 32 | 33 | CPULOCAL_DECLARE_STATIC(bool, timer_fired); 34 | 35 | static bool 36 | timer_isr(virq_t irq, void *data) 37 | { 38 | CPULOCAL(timer_fired) = true; 39 | platform_timer_cancel_timeout(); 40 | 41 | (void)irq; 42 | (void)data; 43 | 44 | return true; 45 | } 46 | 47 | void 48 | timer_init(void) 49 | { 50 | timer_freq = env_data->timer_freq; 51 | uint64_t u_timespec_max_sec = 52 | (UINT64_MAX - (uint64_t)TIMESPEC_MAX_NSEC) / timer_freq; 53 | assert(u_timespec_max_sec > 0U); 54 | timespec_max_sec = 55 | (long)util_min(u_timespec_max_sec, (uint64_t)LONG_MAX); 56 | 57 | platform_timer_init(timer_freq); 58 | (void)interrupt_register_isr(PLATFORM_TIMER_IRQ, &timer_isr, NULL); 59 | } 60 | 61 | static bool 62 | timespec_valid(const struct timespec *ts) 63 | { 64 | return (ts->tv_sec >= 0) && (ts->tv_nsec >= 0) && 65 | (ts->tv_sec <= timespec_max_sec) && 66 | (ts->tv_nsec <= TIMESPEC_MAX_NSEC); 67 | } 68 | 69 | static uint64_t 70 | timespec_to_ticks(const struct timespec *ts) 71 | { 72 | return ((uint32_t)ts->tv_sec * timer_freq) + 73 | (((uint32_t)ts->tv_nsec * timer_freq) / (uint32_t)NS_PER_S); 74 | } 75 | 76 | extern void 77 | ticks_to_timespec(uint64_t ticks, struct timespec *ts); 78 | 79 | void 80 | ticks_to_timespec(uint64_t ticks, struct timespec *ts) 81 | { 82 | assert(ts != NULL); 83 | 84 | ts->tv_sec = (long)ticks / (long)timer_freq; 85 | ts->tv_nsec = (((long)ticks % (long)timer_freq) * NS_PER_S) / 86 | (long)timer_freq; 87 | 88 | assert(timespec_valid(ts)); 89 | } 90 | 91 | long 92 | timer_set_and_wait(bool relative, const struct timespec *req, 93 | struct timespec *remain) 94 | { 95 | long ret; 96 | 97 | if (compiler_unexpected(!timespec_valid(req))) { 98 | ret = -EINVAL; 99 | goto out; 100 | } 101 | 102 | uint64_t curticks = platform_timer_get_current_ticks(); 103 | uint64_t timeout = timespec_to_ticks(req); 104 | 105 | if (relative) { 106 | timeout += curticks; 107 | } 108 | 109 | if (timeout <= curticks) { 110 | ret = 0; 111 | goto out; 112 | } 113 | 114 | platform_timer_set_timeout(timeout); 115 | 116 | (void)interrupt_wait(); 117 | 118 | if (CPULOCAL(timer_fired)) { 119 | CPULOCAL(timer_fired) = false; 120 | ret = 0; 121 | } else { 122 | platform_timer_cancel_timeout(); 123 | ret = -EINTR; 124 | } 125 | 126 | if (remain != NULL) { 127 | curticks = platform_timer_get_current_ticks(); 128 | uint64_t remticks = (timeout > curticks) ? (timeout - curticks) 129 | : 0U; 130 | ticks_to_timespec(remticks, remain); 131 | } 132 | out: 133 | return ret; 134 | } 135 | -------------------------------------------------------------------------------- /src/tty.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 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #define TIMESTAMPS 1 30 | 31 | extern void 32 | ticks_to_timespec(uint64_t ticks, struct timespec *ts); 33 | 34 | static long 35 | tty_writev(const struct iovec *vecp, unsigned long vlen) 36 | { 37 | index_t i; 38 | size_t ret_len = 0; 39 | 40 | for (i = 0; i < vlen; ++i) { 41 | const struct iovec *v = vecp + i; 42 | 43 | size_t remain = v->iov_len; 44 | const char *head = v->iov_base; 45 | 46 | do { 47 | static bool eol = true; 48 | 49 | if (eol) { 50 | #if TIMESTAMPS 51 | uint64_t curticks = 52 | platform_timer_get_current_ticks(); 53 | struct timespec ts; 54 | ticks_to_timespec(curticks, &ts); 55 | char stamp[16]; 56 | (void)snprint( 57 | stamp, sizeof(stamp), 58 | "{:d}.{:06d}: ", (register_t)ts.tv_sec, 59 | (register_t)ts.tv_nsec / 1000U, 0U, 0U, 60 | 0U); 61 | 62 | log_append(stamp, strlen(stamp)); 63 | #endif 64 | console_write(NULL, 0); 65 | 66 | eol = false; 67 | } 68 | 69 | char *next = memchr(head, (int)'\n', remain); 70 | size_t len; 71 | if (next == NULL) { 72 | len = remain; 73 | } else { 74 | len = (size_t)next - (size_t)head + 1UL; 75 | eol = true; 76 | } 77 | console_write(head, len); 78 | log_append(head, len); 79 | 80 | remain -= len; 81 | head = head + len; 82 | } while (remain > 0U); 83 | 84 | ret_len += v->iov_len; 85 | } 86 | 87 | return (long)ret_len; 88 | } 89 | 90 | static long 91 | tty_ioctl(unsigned int cmd, unsigned long arg) 92 | { 93 | long ret; 94 | 95 | switch (cmd) { 96 | case TIOCGWINSZ: { 97 | // FIXME: should we refine it with real value & handle 98 | // it in a separate function? 99 | struct winsize *w = (struct winsize *)arg; 100 | w->ws_row = 64; 101 | w->ws_col = 96; 102 | w->ws_xpixel = 1280; 103 | w->ws_ypixel = 760; 104 | 105 | ret = 0L; 106 | break; 107 | } 108 | case TIOCSETBUF: { // Non-standard IOCTL!! 109 | struct tty_set_buffer_req *req = 110 | (struct tty_set_buffer_req *)arg; 111 | log_set_buffer(req->buffer, req->size); 112 | 113 | ret = 0L; 114 | break; 115 | } 116 | 117 | default: 118 | LOG(ERROR, MSG, "{:s}: invalid tty ioctl cmd{:#x}\n", 119 | (register_t) __func__, cmd); 120 | 121 | ret = -EINVAL; 122 | break; 123 | } 124 | 125 | return ret; 126 | } 127 | 128 | static struct fs_ops ttyin_ops = { 129 | .ioctl = &tty_ioctl, 130 | }; 131 | 132 | static struct fs_ops ttyout_ops = { 133 | .ioctl = &tty_ioctl, 134 | .writev = &tty_writev, 135 | }; 136 | 137 | static struct file ttyin = { 138 | .ops = &ttyin_ops, 139 | }; 140 | 141 | static struct file ttyout = { 142 | .ops = &ttyout_ops, 143 | }; 144 | 145 | struct file *stdin_file = &ttyin; 146 | struct file *stdout_file = &ttyout; 147 | struct file *stderr_file = &ttyout; 148 | -------------------------------------------------------------------------------- /tests/qemu_run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 4 | # 5 | # SPDX-License-Identifier: BSD-3-Clause 6 | 7 | if [ $# -ne 2 ] 8 | then 9 | echo "$0 debug|run elf_image" 10 | exit 0 11 | fi 12 | 13 | if [ "$1" == "debug" ] 14 | then 15 | qemu-system-aarch64 -machine virt -cpu cortex-a72 -serial mon:stdio -nographic -m 1057 -smp 2 -kernel $2 -s -S 16 | else 17 | qemu-system-aarch64 -machine virt -cpu cortex-a72 -serial mon:stdio -nographic -m 1057 -smp 2 -kernel $2 18 | fi 19 | -------------------------------------------------------------------------------- /tools/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quic/gunyah-c-runtime/17c7348542df6ef5987a8092e71efb8a1c4f54c7/tools/__init__.py -------------------------------------------------------------------------------- /tools/build/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quic/gunyah-c-runtime/17c7348542df6ef5987a8092e71efb8a1c4f54c7/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 | # 24 | # Global variable & default settings 25 | # 26 | # Silence flake8 warnings about the externally-defined graph variable 27 | graph = graph # noqa: F821 28 | 29 | logging.basicConfig() 30 | logger = logging.getLogger(__name__) 31 | 32 | build_dir = graph.build_dir 33 | config_file_name = "build.conf" 34 | 35 | # 36 | # Build rules 37 | # 38 | 39 | 40 | # 41 | # General setup 42 | # 43 | def relpath(path): 44 | return os.path.relpath(path, start=graph.root_dir) 45 | 46 | 47 | # parse configure file 48 | # we should compile from repo top header 49 | config = cfg.Configuration(config_file_name, graph) 50 | config.process() 51 | 52 | # 53 | # Python dependencies 54 | # 55 | for m in sys.modules.values(): 56 | try: 57 | f = inspect.getsourcefile(m) 58 | except TypeError: 59 | continue 60 | if f is None: 61 | continue 62 | f = os.path.relpath(f) 63 | if f.startswith('../'): 64 | continue 65 | graph.add_gen_source(f) 66 | -------------------------------------------------------------------------------- /tools/build/config_file.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 | Configure file parsing. 9 | 10 | This script helps to parse configuration file. 11 | """ 12 | import logging 13 | import sys 14 | import os 15 | from io import open 16 | 17 | logger = logging.getLogger(__name__) 18 | 19 | 20 | class Configuration: 21 | """ 22 | This module helps to parse the configuration file and setup build graph. 23 | 24 | It accepts the following syntax: 25 | * all global macro defines: configs PLATFORM_PHYS_ADDR_BITS=34 26 | there's no space around '='. the space can be used to separate multiple 27 | definitions. 28 | 29 | * arch_source: arch_source armv8 pgtable.c 30 | graph.add_target(xxx) 31 | 32 | * board_source: board_source qemu pgtable.c 33 | set source for specific board 34 | 35 | * test_source: test_source testcase.c 36 | 37 | * source: source idle.c 38 | graph.add_target(xxx) 39 | 40 | * include: include dir 41 | set include directory to global cflags. 42 | 43 | * arch include: arch_include armv8 dir 44 | set include directory to global cflags if current architecture is armv8 45 | 46 | * board include: board_include qemu dir 47 | 48 | * local include: local_include dir 49 | set include directory in env dict with LOCAL_CPPFLAGS key. The dir should 50 | be a relative path based on where build.conf located. 51 | 52 | * local flags: local_flags -O -g 53 | set env dict with LOCAL_CPPFLAGS 54 | 55 | * arch flags: arch_flags aarch64 -O -g 56 | set env dict with LOCAL_CPPFLAGS 57 | 58 | * board flags: board_flags qemu -O -g 59 | set env for specific board 60 | 61 | * base target architecture: arch aarch64 62 | 63 | * board target set: board qemu 64 | set target board 65 | 66 | * target triple: target_triple aarch64-linux-gnu 67 | set target_triple 68 | 69 | * include sub directory: sub_directory relative_path_to_subdirectory 70 | include build.conf in that sub directory 71 | 72 | * link script: link_script armv8 file 73 | specify link specify file for a specific architecture 74 | 75 | * program: programe binary_name 76 | specify the binary name as current compilation target. 77 | It could trigger a new variant, and a new build graph to work on. And it's 78 | configuration file to link these two target together. 79 | 80 | * mark for end of program: end_program 81 | indicates that all the configurations for current program are collected. 82 | 83 | * static library: static_lib name 84 | specifiy the name of static library, the final name is "libname.a". 85 | 86 | * mark for end of lib: end_static_lib 87 | indicates that all the configurations for current static library are 88 | collected. 89 | 90 | * cflags: cflags -O -g 91 | set cflags for current program target 92 | 93 | * cppflags: cppflags -O -g 94 | set cppflags for current program target 95 | 96 | * ldflags: ldflags -O -g 97 | set ldflags for current program target 98 | 99 | It will parse the configuration file from the root, then load and parse 100 | sub directories by order of configuration file. 101 | """ 102 | 103 | def __init__(self, file_name, graph): 104 | self.file_name = file_name 105 | self.graph = graph 106 | self.target_triple = None 107 | self.arch = None 108 | self.board = None 109 | self.linker_script = None 110 | # the name of current configuration target 111 | self.binary_name = None 112 | # collect all object for current configuration target 113 | self.objects = set() 114 | # env should be set before set any source 115 | self.local_env = {} 116 | self.compdb_file_name = "compile_commands.json" 117 | self.child_configs = [] 118 | 119 | def process(self): 120 | """ 121 | Process configuration file line by line. 122 | """ 123 | # read top level config file first, handle line by line. 124 | config_file = self.file_name 125 | self.graph.add_gen_source(config_file) 126 | 127 | self.set_default_rule() 128 | self._parse_config(config_file) 129 | self._setup_toolchain() 130 | 131 | def _relpath(self, path): 132 | return os.path.relpath(path, start=self.graph.root_dir) 133 | 134 | def _parse_config(self, config_file): 135 | cur_dir = os.path.dirname(config_file) 136 | 137 | # clear all local configuration 138 | self.local_env.clear() 139 | 140 | with open(config_file, 'r', encoding='utf-8') as f: 141 | for s in f.readlines(): 142 | words = s.split() 143 | if not words or words[0].startswith('#'): 144 | # Skip comments or blank lines 145 | pass 146 | elif words[0] == "arch": 147 | self.arch = words[1] 148 | # FIXME: should we load arch configuration files? Not now. 149 | elif words[0] == "board": 150 | self.board = words[1] 151 | elif words[0] == "source": 152 | for w in words[1:]: 153 | # no auto generated header file by default, 154 | # so set requires as None 155 | self._add_source(cur_dir, w, None, self.local_env) 156 | elif words[0] == "include": 157 | for w in words[1:]: 158 | d = self._relpath(os.path.join(cur_dir, w)) 159 | self.graph.append_env("CFLAGS", "-I " + d) 160 | elif words[0] == "arch_include": 161 | if self.arch is not None and words[1] == self.arch: 162 | for w in words[2:]: 163 | d = self._relpath(os.path.join(cur_dir, w)) 164 | self.graph.append_env("CFLAGS", "-I " + d) 165 | elif words[0] == "board_include": 166 | if self.board is not None and words[1] == self.board: 167 | for w in words[2:]: 168 | d = self._relpath(os.path.join(cur_dir, w)) 169 | self.graph.append_env("CFLAGS", "-I " + d) 170 | elif words[0] == "local_include": 171 | for w in words[1:]: 172 | d = self._relpath(os.path.join(cur_dir, w)) 173 | self._add_include(d, self.local_env) 174 | elif words[0] == "local_flags": 175 | self._add_flags(words[1:], self.local_env) 176 | elif words[0] == "configs": 177 | for w in words[1:]: 178 | self._add_global_define(w) 179 | elif words[0] == "target_triple": 180 | self.target_triple = words[1] 181 | self.graph.add_env('TARGET_TRIPLE', self.target_triple) 182 | elif words[0] == "link_script": 183 | if self.arch is not None and words[1] == self.arch: 184 | self._set_link_script(cur_dir, words[2]) 185 | elif words[0] == "arch_source": 186 | if self.arch is not None and words[1] == self.arch: 187 | for w in words[2:]: 188 | self._add_source(cur_dir, w, None, self.local_env) 189 | elif words[0] == "board_source": 190 | if self.board is not None and words[1] == self.board: 191 | for w in words[2:]: 192 | self._add_source(cur_dir, w, None, self.local_env) 193 | elif words[0] == "program": 194 | assert self.binary_name is None 195 | self.binary_name = words[1] 196 | # FIXME: the add_variant API is not work as expected, need 197 | # double check if this program is helpful 198 | # 199 | # sub_graph_path = os.path.join(self.graph.build_dir, 200 | # self.binary_name) 201 | # sub_graph = self.graph.add_variant(sub_graph_path) 202 | # sub_graph() 203 | # self.graph.add_gen_source(self.file_name) 204 | # self.graph = sub_graph 205 | elif words[0] == "end_program": 206 | # only allowed one target, if need support multiple target, 207 | # just need to implement a stack 208 | assert self.binary_name is not None 209 | self._set_program() 210 | elif words[0] == "static_lib": 211 | self.binary_name = "lib" + words[0] + ".a" 212 | elif words[0] == "end_static_lib": 213 | assert self.binary_name is not None 214 | self._set_static_lib() 215 | elif words[0] == "cflags": 216 | self.graph.append_env("CFLAGS", ' '.join(words[1:])) 217 | elif words[0] == "cppflags": 218 | self.graph.append_env("CPPFLAGS", ' '.join(words[1:])) 219 | elif words[0] == "ldflags": 220 | self.graph.append_env("LDFLAGS", ' '.join(words[1:])) 221 | elif words[0] == "sub_directory": 222 | sub_config_file = os.path.join(cur_dir, words[1], 223 | self.file_name) 224 | self._parse_config(sub_config_file) 225 | self.graph.add_gen_source(sub_config_file) 226 | 227 | def _setup_toolchain(self): 228 | llvm_root = None 229 | try: 230 | llvm_root = self.graph.get_env('QCOM_LLVM') 231 | except KeyError: 232 | try: 233 | llvm_root = self.graph.get_env('LLVM') 234 | except KeyError: 235 | pass 236 | if not llvm_root: 237 | logger.error( 238 | "Please set $LLVM to the root of the LLVM toolchain") 239 | sys.exit(1) 240 | 241 | # Use a QC prebuilt LLVM 242 | self.graph.add_env('CLANG', os.path.join(llvm_root, 'bin', 'clang')) 243 | 244 | # On scons builds, the abs path may be put into the commandline, 245 | # strip it out of the __FILE__ macro. 246 | root = os.path.abspath(os.curdir) + os.sep 247 | self.graph.append_env('CFLAGS', 248 | '-fmacro-prefix-map={:s}={:s}'.format(root, '')) 249 | 250 | # FIXME: manually add the toolchain header file. Remove it. 251 | self.graph.append_env('CFLAGS', "-isystem " + os.path.join( 252 | llvm_root, 253 | self.target_triple, 254 | "libc/include")) 255 | 256 | self.graph.add_env( 257 | 'FORMATTER', 258 | os.path.join( 259 | llvm_root, 260 | 'bin', 261 | 'clang-format')) 262 | 263 | # Use Clang to compile. 264 | self.graph.add_env('TARGET_CC', '${CLANG} -target ${TARGET_TRIPLE}') 265 | self.graph.add_env('TEST_CC', '${CLANG} -target ${TARGET_TRIPLE}') 266 | self.graph.add_env('TARGET_AR', 267 | os.path.join(llvm_root, 'bin', 'llvm-ar')) 268 | 269 | # Use Clang with LLD to link. 270 | self.graph.add_env('TARGET_LD', '${TARGET_CC} -fuse-ld=lld') 271 | self.graph.add_env('TEST_LD', '${TEST_CC} -fuse-ld=lld') 272 | 273 | # Use Clang to preprocess DSL files. 274 | self.graph.add_env('CPP', '${CLANG}-cpp -target ${TARGET_TRIPLE}') 275 | 276 | sysroot = llvm_root + '/' + self.target_triple + '/libc/' 277 | self.graph.append_env("LDFLAGS", '--sysroot=' + sysroot) 278 | 279 | logger.warn("Test programs are disabled by default") 280 | 281 | def _add_source_file(self, src, obj, requires, local_env): 282 | self.graph.add_target([obj], 'cc', [src], requires=requires, 283 | **local_env) 284 | 285 | def _add_source(self, file_dir, src, requires, local_env): 286 | """ 287 | file_dir must be relative path to root 288 | """ 289 | out_dir = os.path.join(self.graph.build_dir, file_dir, 'obj') 290 | i = os.path.join(file_dir, src) 291 | o = os.path.join(out_dir, src + '.o') 292 | self._add_source_file(i, o, requires, local_env) 293 | self.objects.add(o) 294 | 295 | def _add_include_dir(self, d, local_env): 296 | if 'LOCAL_CPPFLAGS' in local_env: 297 | local_env['LOCAL_CPPFLAGS'] += ' ' 298 | else: 299 | local_env['LOCAL_CPPFLAGS'] = '' 300 | local_env['LOCAL_CPPFLAGS'] += '-iquote ' + d 301 | 302 | def _add_include(self, include, local_env): 303 | """ 304 | include is a relative path based on scon's work dir 305 | """ 306 | self._add_include_dir(include, local_env) 307 | 308 | def _add_flags(self, flags, local_env): 309 | if 'LOCAL_CFLAGS' in local_env: 310 | local_env['LOCAL_CFLAGS'] += ' ' 311 | else: 312 | local_env['LOCAL_CFLAGS'] = '' 313 | local_env['LOCAL_CFLAGS'] += ' '.join(flags) 314 | 315 | def _add_global_define(self, d): 316 | self.graph.append_env('CPPFLAGS', "-D" + d) 317 | self.graph.append_env('CODEGEN_CONFIGS', "-D" + d) 318 | 319 | def _set_link_script(self, d, link_file): 320 | linker_script_in = os.path.join(d, link_file) 321 | linker_script = os.path.join(self.graph.build_dir, link_file + '.pp') 322 | self.graph.add_target([linker_script], 'cpp-dsl', [linker_script_in]) 323 | self.graph.append_env('TARGET_LDFLAGS', 324 | '-Wl,-T,{:s}'.format(linker_script)) 325 | self.linker_script = linker_script 326 | 327 | def _set_program(self): 328 | bin_file = os.path.join(self.graph.build_dir, self.binary_name) 329 | deps = None 330 | if self.linker_script is not None: 331 | deps = [self.linker_script] 332 | assert len(self.objects) != 0 333 | self.graph.add_target([bin_file], 'ld', sorted(self.objects), 334 | depends=deps) 335 | self.graph.add_default_target(bin_file) 336 | 337 | def _set_static_lib(self): 338 | bin_file = os.path.join(self.graph.build_dir, self.binary_name) 339 | deps = None 340 | assert len(self.objects) != 0 341 | self.graph.add_target([bin_file], 'ar', sorted(self.objects), 342 | depends=deps) 343 | self.graph.add_default_target(bin_file) 344 | 345 | def set_default_rule(self): 346 | compdb_file = os.path.join(self.graph.build_dir, self.compdb_file_name) 347 | self.graph.add_compdb(compdb_file, form='clang') 348 | 349 | # Compile a target C file. 350 | self.graph.add_rule('cc', 351 | '$TARGET_CC $CFLAGS $CPPFLAGS $TARGET_CFLAGS ' 352 | '$TARGET_CPPFLAGS $LOCAL_CFLAGS $LOCAL_CPPFLAGS ' 353 | ' -MD -MF ${out}.d -c -o ${out} ${in}', 354 | depfile='${out}.d', compdbs=[compdb_file]) 355 | # Preprocess a DSL file. 356 | self.graph.add_rule('cpp-dsl', '${CPP} $CPPFLAGS $TARGET_CPPFLAGS ' 357 | '$LOCAL_CPPFLAGS -undef $DSL_DEFINES -x c ' 358 | '-P -MD -MF ${out}.d -MT ${out} ${in} > ${out}', 359 | depfile='${out}.d') 360 | # Link a target binary. 361 | self.graph.add_rule('ld', '$TARGET_LD $LDFLAGS $TARGET_LDFLAGS ' 362 | '$LOCAL_LDFLAGS ${in} -o ${out}') 363 | # Static library 364 | self.graph.add_rule('ar', '$TARGET_AR rc ${out} ${in}') 365 | -------------------------------------------------------------------------------- /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 GIT_VERSION \"`git rev-parse --short HEAD`$status\"" 11 | 12 | if [ -z "$status" ] 13 | then 14 | echo "#define BUILD_DATE \"`TZ=UTC git show -s --pretty="%cd" --date=local HEAD` UTC\"" 15 | else 16 | echo "#define BUILD_DATE \"`date -R`\"" 17 | fi 18 | -------------------------------------------------------------------------------- /tools/cpptest/Checkers_Man_All_Req.properties: -------------------------------------------------------------------------------- 1 | CERT_C-ENV33-a=true 2 | CERT_C-STR02-a=true 3 | CERT_C-STR02-b=true 4 | CERT_C-STR02-c=true 5 | CERT_C-STR07-a=true 6 | com.parasoft.xtest.checkers.api.common.fullBuild=false 7 | com.parasoft.xtest.checkers.api.common.incrementalBuild=false 8 | com.parasoft.xtest.checkers.api.config.name=MISRA C 2012 9 | com.parasoft.xtest.checkers.api.config.path=Compliance Packs/Automotive Pack 10 | com.parasoft.xtest.checkers.api.config.tool=3 11 | com.parasoft.xtest.checkers.api.config.version=9.5.0 12 | com.parasoft.xtest.checkers.api.config.xtestVersion=1.0.1 13 | com.parasoft.xtest.execution.api.enabled=false 14 | #com.parasoft.xtest.standards.api.cap_errors_per_rule=false 15 | com.parasoft.xtest.standards.api.enabled=true 16 | com.parasoft.xtest.standards.api.max_errors_per_rule=10000 17 | com.parasoft.xtest.testgen.api.enabled=false 18 | #Compliance Standard Misra C 2012 19 | MISRAC2012-DIR_4_10-a=true 20 | MISRAC2012-DIR_4_11-a=true 21 | MISRAC2012-DIR_4_12-a=false 22 | MISRAC2012-DIR_4_13-a=true 23 | MISRAC2012-DIR_4_13-b=true 24 | MISRAC2012-DIR_4_13-c=true 25 | MISRAC2012-DIR_4_13-d=true 26 | MISRAC2012-DIR_4_13-e=true 27 | MISRAC2012-DIR_4_14-a=true 28 | MISRAC2012-DIR_4_14-b=true 29 | MISRAC2012-DIR_4_14-c=true 30 | MISRAC2012-DIR_4_14-d=true 31 | MISRAC2012-DIR_4_14-e=true 32 | MISRAC2012-DIR_4_14-f=true 33 | MISRAC2012-DIR_4_14-g=true 34 | MISRAC2012-DIR_4_14-h=true 35 | MISRAC2012-DIR_4_14-i=true 36 | MISRAC2012-DIR_4_14-j=true 37 | MISRAC2012-DIR_4_14-k=true 38 | MISRAC2012-DIR_4_14-l=true 39 | MISRAC2012-DIR_4_15-a=true 40 | MISRAC2012-DIR_4_1-a=true 41 | MISRAC2012-DIR_4_1-b=true 42 | MISRAC2012-DIR_4_1-c=true 43 | MISRAC2012-DIR_4_1-d=true 44 | MISRAC2012-DIR_4_1-e=true 45 | MISRAC2012-DIR_4_1-f-arbitariesInInternalLinkage=false 46 | MISRAC2012-DIR_4_1-f=true 47 | MISRAC2012-DIR_4_1-f-visibilityThresholdEnabled=true 48 | MISRAC2012-DIR_4_1-f-visibilityThreshold=PRIVATE 49 | MISRAC2012-DIR_4_1-g=true 50 | MISRAC2012-DIR_4_1-h=true 51 | MISRAC2012-DIR_4_1-i=true 52 | MISRAC2012-DIR_4_1-j=true 53 | MISRAC2012-DIR_4_1-k=true 54 | MISRAC2012-DIR_4_1-l=true 55 | MISRAC2012-DIR_4_1-m=true 56 | MISRAC2012-DIR_4_2-a=true 57 | MISRAC2012-DIR_4_3-a=true 58 | MISRAC2012-DIR_4_4-a=true 59 | MISRAC2012-DIR_4_5-a=true 60 | MISRAC2012-DIR_4_6-a=true 61 | MISRAC2012-DIR_4_6-b=true 62 | MISRAC2012-DIR_4_6-c=true 63 | MISRAC2012-DIR_4_7-a=true 64 | MISRAC2012-DIR_4_7-b=true 65 | MISRAC2012-DIR_4_8-a=false 66 | MISRAC2012-DIR_4_9-a=false 67 | MISRAC2012-DIR_5_1-a=true 68 | MISRAC2012-DIR_5_1-b=true 69 | MISRAC2012-DIR_5_1-c=true 70 | MISRAC2012-DIR_5_2-a=true 71 | MISRAC2012-DIR_5_3-a=true 72 | MISRAC2012-RULE_10_1-a=true 73 | MISRAC2012-RULE_10_1-b=true 74 | MISRAC2012-RULE_10_1-c=true 75 | MISRAC2012-RULE_10_1-d=true 76 | MISRAC2012-RULE_10_1-e=true 77 | MISRAC2012-RULE_10_1-f=true 78 | MISRAC2012-RULE_10_1-g=true 79 | MISRAC2012-RULE_10_1-h=true 80 | MISRAC2012-RULE_10_2-a=true 81 | MISRAC2012-RULE_10_3-a=true 82 | MISRAC2012-RULE_10_3-b=true 83 | MISRAC2012-RULE_10_4-a=true 84 | MISRAC2012-RULE_10_4-b=true 85 | MISRAC2012-RULE_10_5-a=true 86 | MISRAC2012-RULE_10_5-b=true 87 | MISRAC2012-RULE_10_5-c=true 88 | MISRAC2012-RULE_10_6-a=true 89 | MISRAC2012-RULE_10_7-a=true 90 | MISRAC2012-RULE_10_7-b=true 91 | MISRAC2012-RULE_10_8-a=true 92 | MISRAC2012-RULE_11_10-a=true 93 | MISRAC2012-RULE_11_1-a=true 94 | MISRAC2012-RULE_11_1-b=true 95 | MISRAC2012-RULE_11_2-a=true 96 | MISRAC2012-RULE_11_3-a=true 97 | MISRAC2012-RULE_11_4-a=true 98 | MISRAC2012-RULE_11_5-a=true 99 | MISRAC2012-RULE_11_6-a=true 100 | MISRAC2012-RULE_11_7-a=true 101 | MISRAC2012-RULE_11_8-a=true 102 | MISRAC2012-RULE_11_9-a=true 103 | MISRAC2012-RULE_11_9-b=true 104 | MISRAC2012-RULE_1_1-a=false 105 | MISRAC2012-RULE_1_1-b=false 106 | MISRAC2012-RULE_1_1-c=false 107 | MISRAC2012-RULE_1_1-d=true 108 | MISRAC2012-RULE_12_1-a=true 109 | MISRAC2012-RULE_12_1-b=false 110 | MISRAC2012-RULE_12_1-c=true 111 | MISRAC2012-RULE_12_2-a=true 112 | MISRAC2012-RULE_12_3-a=false 113 | MISRAC2012-RULE_12_4-a=true 114 | MISRAC2012-RULE_12_4-b=true 115 | MISRAC2012-RULE_12_5-a=true 116 | MISRAC2012-RULE_12_6-a=true 117 | MISRAC2012-RULE_13_1-a=true 118 | MISRAC2012-RULE_13_2-a=true 119 | MISRAC2012-RULE_13_2-b=true 120 | MISRAC2012-RULE_13_2-c=true 121 | MISRAC2012-RULE_13_2-d=true 122 | MISRAC2012-RULE_13_2-e=true 123 | MISRAC2012-RULE_13_2-f=true 124 | MISRAC2012-RULE_13_2-g=true 125 | MISRAC2012-RULE_13_2-h=true 126 | MISRAC2012-RULE_13_3-a=true 127 | MISRAC2012-RULE_13_4-a=true 128 | MISRAC2012-RULE_13_5-a=true 129 | MISRAC2012-RULE_13_6-a=true 130 | MISRAC2012-RULE_13_6-b=true 131 | MISRAC2012-RULE_13_6-c=true 132 | MISRAC2012-RULE_1_3-a=true 133 | MISRAC2012-RULE_1_3-b=true 134 | MISRAC2012-RULE_1_3-c=true 135 | MISRAC2012-RULE_1_3-d=true 136 | MISRAC2012-RULE_1_3-e=true 137 | MISRAC2012-RULE_1_3-f=true 138 | MISRAC2012-RULE_1_3-g=true 139 | MISRAC2012-RULE_1_3-h=true 140 | MISRAC2012-RULE_1_3-i=true 141 | MISRAC2012-RULE_1_3-j=true 142 | MISRAC2012-RULE_1_3-k=true 143 | MISRAC2012-RULE_1_3-l=true 144 | MISRAC2012-RULE_1_3-m=true 145 | MISRAC2012-RULE_1_3-n=true 146 | MISRAC2012-RULE_1_3-o=true 147 | MISRAC2012-RULE_1_5-a=true 148 | MISRAC2012-RULE_1_5-b=true 149 | MISRAC2012-RULE_1_5-c=true 150 | MISRAC2012-RULE_1_5-d=true 151 | MISRAC2012-RULE_1_5-e=true 152 | MISRAC2012-RULE_1_5-f=true 153 | MISRAC2012-RULE_1_5-g=true 154 | MISRAC2012-RULE_14_1-a=true 155 | MISRAC2012-RULE_14_1-b=true 156 | MISRAC2012-RULE_14_2-a=true 157 | MISRAC2012-RULE_14_2-b=true 158 | MISRAC2012-RULE_14_2-c=true 159 | MISRAC2012-RULE_14_2-d=true 160 | MISRAC2012-RULE_14_3-aa=true 161 | MISRAC2012-RULE_14_3-ab=true 162 | MISRAC2012-RULE_14_3-ac=true 163 | MISRAC2012-RULE_14_3-ad=true 164 | MISRAC2012-RULE_14_3-a=true 165 | MISRAC2012-RULE_14_3-b=true 166 | MISRAC2012-RULE_14_3-c=true 167 | MISRAC2012-RULE_14_3-d=true 168 | MISRAC2012-RULE_14_3-e=true 169 | MISRAC2012-RULE_14_3-f=true 170 | MISRAC2012-RULE_14_3-g=true 171 | MISRAC2012-RULE_14_3-h=true 172 | MISRAC2012-RULE_14_3-i=true 173 | MISRAC2012-RULE_14_3-j=true 174 | MISRAC2012-RULE_14_3-k=true 175 | MISRAC2012-RULE_14_3-l=true 176 | MISRAC2012-RULE_14_3-m=true 177 | MISRAC2012-RULE_14_3-n=true 178 | MISRAC2012-RULE_14_3-o=true 179 | MISRAC2012-RULE_14_3-p=true 180 | MISRAC2012-RULE_14_3-q=true 181 | MISRAC2012-RULE_14_3-r=true 182 | MISRAC2012-RULE_14_3-s=true 183 | MISRAC2012-RULE_14_3-t=true 184 | MISRAC2012-RULE_14_3-u=true 185 | MISRAC2012-RULE_14_3-v=true 186 | MISRAC2012-RULE_14_3-w=true 187 | MISRAC2012-RULE_14_3-x=true 188 | MISRAC2012-RULE_14_3-y=true 189 | MISRAC2012-RULE_14_3-z=true 190 | MISRAC2012-RULE_14_4-a=true 191 | MISRAC2012-RULE_15_1-a=false 192 | MISRAC2012-RULE_15_2-a=true 193 | MISRAC2012-RULE_15_3-a=true 194 | MISRAC2012-RULE_15_4-a=false 195 | MISRAC2012-RULE_15_5-a=true 196 | MISRAC2012-RULE_15_6-a=true 197 | MISRAC2012-RULE_15_6-b=true 198 | MISRAC2012-RULE_15_7-a=true 199 | MISRAC2012-RULE_16_1-a=true 200 | MISRAC2012-RULE_16_1-b=true 201 | MISRAC2012-RULE_16_1-c=true 202 | MISRAC2012-RULE_16_1-d=true 203 | MISRAC2012-RULE_16_1-e=true 204 | MISRAC2012-RULE_16_1-f=true 205 | MISRAC2012-RULE_16_1-g=true 206 | MISRAC2012-RULE_16_1-h=true 207 | MISRAC2012-RULE_16_2-a=true 208 | MISRAC2012-RULE_16_3-a=true 209 | MISRAC2012-RULE_16_3-b=true 210 | MISRAC2012-RULE_16_4-a=true 211 | MISRAC2012-RULE_16_4-b=true 212 | MISRAC2012-RULE_16_5-a=true 213 | MISRAC2012-RULE_16_6-a=true 214 | MISRAC2012-RULE_16_7-a=true 215 | MISRAC2012-RULE_16_7-b=true 216 | MISRAC2012-RULE_17_10-a=true 217 | MISRAC2012-RULE_17_11-a=true 218 | MISRAC2012-RULE_17_12-a=true 219 | MISRAC2012-RULE_17_13-a=true 220 | MISRAC2012-RULE_17_1-a=true 221 | MISRAC2012-RULE_17_1-b=true 222 | MISRAC2012-RULE_17_2-a=true 223 | MISRAC2012-RULE_17_3-a=true 224 | MISRAC2012-RULE_17_4-a=true 225 | MISRAC2012-RULE_17_5-a=true 226 | MISRAC2012-RULE_17_6-a=true 227 | MISRAC2012-RULE_17_7-a=true 228 | MISRAC2012-RULE_17_7-b=true 229 | MISRAC2012-RULE_17_8-a=true 230 | MISRAC2012-RULE_17_9-a=true 231 | MISRAC2012-RULE_18_10-a=true 232 | MISRAC2012-RULE_18_1-a=true 233 | MISRAC2012-RULE_18_1-b=true 234 | MISRAC2012-RULE_18_1-c=true 235 | MISRAC2012-RULE_18_2-a=true 236 | MISRAC2012-RULE_18_3-a=true 237 | MISRAC2012-RULE_18_4-a=false 238 | MISRAC2012-RULE_18_5-a=true 239 | MISRAC2012-RULE_18_6-a=true 240 | MISRAC2012-RULE_18_6-b=true 241 | MISRAC2012-RULE_18_6-c=true 242 | MISRAC2012-RULE_18_7-a=true 243 | MISRAC2012-RULE_18_8-a=true 244 | MISRAC2012-RULE_18_9-a=true 245 | MISRAC2012-RULE_19_1-a=true 246 | MISRAC2012-RULE_19_1-b=true 247 | MISRAC2012-RULE_19_1-c=true 248 | MISRAC2012-RULE_19_2-a=false 249 | MISRAC2012-RULE_20_10-a=false 250 | MISRAC2012-RULE_20_11-a=true 251 | MISRAC2012-RULE_20_12-a=true 252 | MISRAC2012-RULE_20_13-a=true 253 | MISRAC2012-RULE_20_14-a=true 254 | MISRAC2012-RULE_20_1-a=true 255 | MISRAC2012-RULE_20_2-a=true 256 | MISRAC2012-RULE_20_2-b=true 257 | MISRAC2012-RULE_20_3-a=true 258 | MISRAC2012-RULE_20_4-a=true 259 | MISRAC2012-RULE_20_4-b=true 260 | MISRAC2012-RULE_20_5-a=true 261 | MISRAC2012-RULE_20_6-a=true 262 | MISRAC2012-RULE_20_7-a=true 263 | MISRAC2012-RULE_20_8-a=true 264 | MISRAC2012-RULE_20_9-a=true 265 | MISRAC2012-RULE_20_9-b=true 266 | MISRAC2012-RULE_21_10-a=true 267 | MISRAC2012-RULE_21_11-a=true 268 | MISRAC2012-RULE_21_12-a=true 269 | MISRAC2012-RULE_21_13-a=true 270 | MISRAC2012-RULE_21_14-a=true 271 | MISRAC2012-RULE_21_15-a=true 272 | MISRAC2012-RULE_21_16-a=true 273 | MISRAC2012-RULE_21_17-a=true 274 | MISRAC2012-RULE_21_17-b=true 275 | MISRAC2012-RULE_21_18-a=true 276 | MISRAC2012-RULE_21_19-a=true 277 | MISRAC2012-RULE_21_19-b=true 278 | MISRAC2012-RULE_21_1-a=true 279 | MISRAC2012-RULE_21_1-b=false 280 | MISRAC2012-RULE_21_1-c=true 281 | MISRAC2012-RULE_21_1-d=true 282 | MISRAC2012-RULE_21_20-a=true 283 | MISRAC2012-RULE_21_21-a=true 284 | MISRAC2012-RULE_21_22-a=true 285 | MISRAC2012-RULE_21_23-a=true 286 | MISRAC2012-RULE_21_24-a=true 287 | MISRAC2012-RULE_21_25-a=true 288 | MISRAC2012-RULE_21_26-a=true 289 | MISRAC2012-RULE_21_2-a=true 290 | MISRAC2012-RULE_21_2-b=false 291 | MISRAC2012-RULE_21_2-c=true 292 | MISRAC2012-RULE_21_3-a=false 293 | MISRAC2012-RULE_21_4-a=true 294 | MISRAC2012-RULE_21_4-b=true 295 | MISRAC2012-RULE_21_5-a=true 296 | MISRAC2012-RULE_21_5-b=true 297 | MISRAC2012-RULE_21_6-a=true 298 | MISRAC2012-RULE_21_7-a=true 299 | MISRAC2012-RULE_21_8-a=true 300 | MISRAC2012-RULE_21_9-a=true 301 | MISRAC2012-RULE_2_1-a=true 302 | MISRAC2012-RULE_2_1-b=true 303 | MISRAC2012-RULE_2_1-c=true 304 | MISRAC2012-RULE_2_1-d=true 305 | MISRAC2012-RULE_2_1-e=true 306 | MISRAC2012-RULE_2_1-f=true 307 | MISRAC2012-RULE_2_1-g=true 308 | MISRAC2012-RULE-22_10-a-reportOnMissingErrnoCheck=false 309 | MISRAC2012-RULE_22_10-a-reportWhenErrnoIsNotZero=false 310 | MISRAC2012-RULE_22_10-a=true 311 | MISRAC2012-RULE_22_11-a=true 312 | MISRAC2012-RULE_22_12-a=true 313 | MISRAC2012-RULE_22_13-a=true 314 | MISRAC2012-RULE_22_14-a=true 315 | MISRAC2012-RULE_22_14-b=true 316 | MISRAC2012-RULE_22_15-a=true 317 | MISRAC2012-RULE_22_16-a=true 318 | MISRAC2012-RULE_22_17-a=true 319 | MISRAC2012-RULE_22_18-a=true 320 | MISRAC2012-RULE_22_19-a=true 321 | MISRAC2012-RULE_22_1-a-fieldsStoreResources=false 322 | MISRAC2012-RULE_22_1-a-nonMemberMethodsStoreResource=false 323 | MISRAC2012-RULE_22_1-a-patternName=^malloc|calloc|realloc|fopen$ 324 | MISRAC2012-RULE_22_1-a-patternNameMethodsStore=true 325 | MISRAC2012-RULE_22_1-a-reportUnvalidatedViolations=false 326 | MISRAC2012-RULE_22_1-a-storeByTPMethods=false 327 | MISRAC2012-RULE_22_1-a=true 328 | MISRAC2012-RULE_22_20-a=true 329 | MISRAC2012-RULE_22_2-a=true 330 | MISRAC2012-RULE_22_2-b=true 331 | MISRAC2012-RULE_22_3-a=true 332 | MISRAC2012-RULE_22_4-a=true 333 | MISRAC2012-RULE_22_5-a=true 334 | MISRAC2012-RULE_22_5-b=true 335 | MISRAC2012-RULE_22_6-a=true 336 | MISRAC2012-RULE_22_7-a=true 337 | MISRAC2012-RULE_22_8-a-reportOnMissingErrnoCheck=false 338 | MISRAC2012-RULE_22_8-a-reportOnUnnecessaryErrnoCheck=false 339 | MISRAC2012-RULE_22_8-a=true 340 | MISRAC2012-RULE_22_9-a-reportOnUnnecessaryErrnoCheck=false 341 | MISRAC2012-RULE_22_9-a-reportWhenErrnoIsNotZero=false 342 | MISRAC2012-RULE_22_9-a=true 343 | MISRAC2012-RULE_23_1-a=true 344 | MISRAC2012-RULE_23_1-b=true 345 | MISRAC2012-RULE_23_2-a=true 346 | MISRAC2012-RULE_23_3-a=true 347 | MISRAC2012-RULE_23_4-a=true 348 | MISRAC2012-RULE_23_5-a=true 349 | MISRAC2012-RULE_23_6-a=true 350 | MISRAC2012-RULE_23_6-b=true 351 | MISRAC2012-RULE_23_7-a=true 352 | MISRAC2012-RULE_23_8-a=true 353 | MISRAC2012-RULE_2_2-a=true 354 | MISRAC2012-RULE_2_3-a=false 355 | MISRAC2012-RULE_2_3-b=false 356 | MISRAC2012-RULE_2_4-a=false 357 | MISRAC2012-RULE_2_4-b=false 358 | MISRAC2012-RULE_2_5-a=false 359 | MISRAC2012-RULE_2_6-a=false 360 | MISRAC2012-RULE_2_7-a=false 361 | MISRAC2012-RULE_2_8-a=true 362 | MISRAC2012-RULE_2_8-b=true 363 | MISRAC2012-RULE_2_8-c=true 364 | MISRAC2012-RULE_3_1-a=true 365 | MISRAC2012-RULE_3_1-b=true 366 | MISRAC2012-RULE_3_1-c=true 367 | MISRAC2012-RULE_3_2-a=true 368 | MISRAC2012-RULE_4_1-a=true 369 | MISRAC2012-RULE_4_2-a=true 370 | MISRAC2012-RULE_5_1-a=false 371 | MISRAC2012-RULE_5_2-a=false 372 | MISRAC2012-RULE_5_2-b=true 373 | MISRAC2012-RULE_5_2-c=false 374 | MISRAC2012-RULE_5_2-d=true 375 | MISRAC2012-RULE_5_3-a=true 376 | MISRAC2012-RULE_5_3-b=true 377 | MISRAC2012-RULE_5_4-a=false 378 | MISRAC2012-RULE_5_4-b=true 379 | MISRAC2012-RULE_5_4-c=false 380 | MISRAC2012-RULE_5_4-d=true 381 | MISRAC2012-RULE_5_5-a=false 382 | MISRAC2012-RULE_5_5-b=true 383 | MISRAC2012-RULE_5_6-a=true 384 | MISRAC2012-RULE_5_6-b=true 385 | MISRAC2012-RULE_5_7-a=true 386 | MISRAC2012-RULE_5_7-b=true 387 | MISRAC2012-RULE_5_8-a=true 388 | MISRAC2012-RULE_5_8-b=true 389 | MISRAC2012-RULE_5_9-a=true 390 | MISRAC2012-RULE_5_9-b=true 391 | MISRAC2012-RULE_6_1-a=true 392 | MISRAC2012-RULE_6_2-a=true 393 | MISRAC2012-RULE_6_3-a=true 394 | MISRAC2012-RULE_7_1-a=true 395 | MISRAC2012-RULE_7_2-a=true 396 | MISRAC2012-RULE_7_3-a=true 397 | MISRAC2012-RULE_7_4-a=true 398 | MISRAC2012-RULE_7_5-a=true 399 | MISRAC2012-RULE_7_6-a=true 400 | MISRAC2012-RULE_8_10-a=true 401 | MISRAC2012-RULE_8_11-a=true 402 | MISRAC2012-RULE_8_12-a=true 403 | MISRAC2012-RULE_8_13-a=true 404 | MISRAC2012-RULE_8_13-b=true 405 | MISRAC2012-RULE_8_14-a=true 406 | MISRAC2012-RULE_8_15-a=true 407 | MISRAC2012-RULE_8_15-b=true 408 | MISRAC2012-RULE_8_16-a=true 409 | MISRAC2012-RULE_8_17-a=true 410 | MISRAC2012-RULE_8_1-a=true 411 | MISRAC2012-RULE_8_1-b=true 412 | MISRAC2012-RULE_8_2-a=true 413 | MISRAC2012-RULE_8_2-b=true 414 | MISRAC2012-RULE_8_2-c=true 415 | MISRAC2012-RULE_8_3-a=true 416 | MISRAC2012-RULE_8_3-b=true 417 | MISRAC2012-RULE_8_4-a=true 418 | MISRAC2012-RULE_8_4-b=true 419 | MISRAC2012-RULE_8_5-a=true 420 | MISRAC2012-RULE_8_6-a=false 421 | MISRAC2012-RULE_8_7-a=true 422 | MISRAC2012-RULE_8_8-a=true 423 | MISRAC2012-RULE_8_9-a=true 424 | MISRAC2012-RULE_9_1-a=true 425 | MISRAC2012-RULE_9_2-a=true 426 | MISRAC2012-RULE_9_3-a=true 427 | MISRAC2012-RULE_9_4-a=true 428 | MISRAC2012-RULE_9_5-a=true 429 | MISRAC2012-RULE_9_6-a=true 430 | MISRAC2012-RULE_9_7-a=true 431 | -------------------------------------------------------------------------------- /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 | # False positive due to a builtin sizeof variant that does not evaluate its 46 | # argument, so there is no uninitialised use. 47 | 'MISRAC2012-RULE_9_1-a': [ 48 | (None, re.compile(r'passed to "__builtin_object_size"')), 49 | ], 50 | 'MISRAC2012-RULE_1_3-b': [ 51 | (None, re.compile(r'passed to "__builtin_object_size"')), 52 | ], 53 | # Compliance with rule 21.25 would have a significant performance impact. 54 | # All existing uses have been thoroughly analysed and tested, so we will 55 | # seek a project-wide deviation for this rule. 56 | 'MISRAC2012-RULE_21_25-a': [ 57 | (None, None), 58 | ], 59 | } 60 | 61 | 62 | def matches_deviation(v): 63 | rule = v.attrib['rule'] 64 | if rule not in deviation_map: 65 | return False 66 | 67 | msg = v.attrib['msg'] 68 | path = v.attrib['locFile'].split(os.sep, 2)[2] 69 | 70 | def check_constraint(constraint, value): 71 | if constraint is None: 72 | return True 73 | try: 74 | return constraint.search(value) 75 | except AttributeError: 76 | return constraint == value 77 | 78 | for d_path, d_msg in deviation_map[rule]: 79 | if check_constraint(d_path, path) and check_constraint(d_msg, msg): 80 | return True 81 | 82 | return False 83 | 84 | 85 | cc_viols = [ 86 | ({ 87 | "type": "issue", 88 | "categories": ["Bug Risk"], 89 | "severity": ('info' if matches_deviation(v) 90 | else severity_map[int(v.attrib['sev'])]), 91 | "check_name": v.attrib['rule'], 92 | "description": (v.attrib['msg'] + '. ' + 93 | v.attrib['rule.header'] + '. (' + 94 | v.attrib['rule'] + ')'), 95 | "fingerprint": v.attrib['unbViolId'], 96 | "location": { 97 | "path": v.attrib['locFile'].split(os.sep, 2)[2], 98 | "lines": { 99 | "begin": int(v.attrib['locStartln']), 100 | "end": int(v.attrib['locEndLn']) 101 | } 102 | } 103 | }) 104 | for v in parasoft_viols] 105 | 106 | args.output.write(json.dumps(cc_viols)) 107 | args.output.close() 108 | -------------------------------------------------------------------------------- /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/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 | --------------------------------------------------------------------------------