diff options
author | Sandrine Bailleux <sandrine.bailleux@arm.com> | 2018-10-09 11:12:55 +0200 |
---|---|---|
committer | Sandrine Bailleux <sandrine.bailleux@arm.com> | 2018-10-10 12:34:34 +0200 |
commit | 3cd87d77947ec4fc04440268ed122b4ed81c7781 (patch) | |
tree | 78fdee12b026b931029e434f29b4fe09835fe4c9 /include | |
download | tf-a-tests-3cd87d77947ec4fc04440268ed122b4ed81c7781.tar.gz |
Trusted Firmware-A Tests, version 2.0v2.0
This is the first public version of the tests for the Trusted
Firmware-A project. Please see the documentation provided in the
source tree for more details.
Change-Id: I6f3452046a1351ac94a71b3525c30a4ca8db7867
Signed-off-by: Sandrine Bailleux <sandrine.bailleux@arm.com>
Co-authored-by: amobal01 <amol.balasokamble@arm.com>
Co-authored-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
Co-authored-by: Asha R <asha.r@arm.com>
Co-authored-by: Chandni Cherukuri <chandni.cherukuri@arm.com>
Co-authored-by: David Cunado <david.cunado@arm.com>
Co-authored-by: Dimitris Papastamos <dimitris.papastamos@arm.com>
Co-authored-by: Douglas Raillard <douglas.raillard@arm.com>
Co-authored-by: dp-arm <dimitris.papastamos@arm.com>
Co-authored-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
Co-authored-by: Jonathan Wright <jonathan.wright@arm.com>
Co-authored-by: Kévin Petit <kevin.petit@arm.com>
Co-authored-by: Roberto Vargas <roberto.vargas@arm.com>
Co-authored-by: Sathees Balya <sathees.balya@arm.com>
Co-authored-by: Shawon Roy <Shawon.Roy@arm.com>
Co-authored-by: Soby Mathew <soby.mathew@arm.com>
Co-authored-by: Thomas Abraham <thomas.abraham@arm.com>
Co-authored-by: Vikram Kanigiri <vikram.kanigiri@arm.com>
Co-authored-by: Yatharth Kochar <yatharth.kochar@arm.com>
Diffstat (limited to 'include')
92 files changed, 10118 insertions, 0 deletions
diff --git a/include/common/aarch32/asm_macros.S b/include/common/aarch32/asm_macros.S new file mode 100644 index 000000000..2edf5b900 --- /dev/null +++ b/include/common/aarch32/asm_macros.S @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __ASM_MACROS_S__ +#define __ASM_MACROS_S__ + +#include <arch.h> +#include <asm_macros_common.S> + +#define TLB_INVALIDATE(_reg, _coproc) \ + stcopr _reg, _coproc + + /* + * Co processor register accessors + */ + .macro ldcopr reg, coproc, opc1, CRn, CRm, opc2 + mrc \coproc, \opc1, \reg, \CRn, \CRm, \opc2 + .endm + + .macro ldcopr16 reg1, reg2, coproc, opc1, CRm + mrrc \coproc, \opc1, \reg1, \reg2, \CRm + .endm + + .macro stcopr reg, coproc, opc1, CRn, CRm, opc2 + mcr \coproc, \opc1, \reg, \CRn, \CRm, \opc2 + .endm + + .macro stcopr16 reg1, reg2, coproc, opc1, CRm + mcrr \coproc, \opc1, \reg1, \reg2, \CRm + .endm + + /* Cache line size helpers */ + .macro dcache_line_size reg, tmp + ldcopr \tmp, CTR + ubfx \tmp, \tmp, #16, #4 + mov \reg, #4 + lsl \reg, \reg, \tmp + .endm + + .macro icache_line_size reg, tmp + ldcopr \tmp, CTR + and \tmp, \tmp, #0xf + mov \reg, #4 + lsl \reg, \reg, \tmp + .endm + + /* + * Declare the exception vector table, enforcing it is aligned on a + * 32 byte boundary. + */ + .macro vector_base label + .section .vectors, "ax" + .align 5 + \label: + .endm + + /* + * This macro calculates the base address of an MP stack using the + * platform_get_core_pos() index, the name of the stack storage and + * the size of each stack + * Out: r0 = physical address of stack base + * Clobber: r14, r1, r2 + */ + .macro get_mp_stack _name, _size + bl platform_get_core_pos + ldr r2, =(\_name + \_size) + mov r1, #\_size + mla r0, r0, r1, r2 + .endm + + /* + * This macro calculates the base address of a uniprocessor(UP) stack + * using the name of the stack storage and the size of the stack + * Out: r0 = physical address of stack base + */ + .macro get_up_stack _name, _size + ldr r0, =(\_name + \_size) + .endm + +#endif /* __ASM_MACROS_S__ */ + diff --git a/include/common/aarch32/assert_macros.S b/include/common/aarch32/assert_macros.S new file mode 100644 index 000000000..5dc9e6472 --- /dev/null +++ b/include/common/aarch32/assert_macros.S @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef __ASSERT_MACROS_S__ +#define __ASSERT_MACROS_S__ + + /* + * Assembler macro to enable asm_assert. We assume that the stack is + * initialized prior to invoking this macro. Please note that the + * macro makes use of label '300' to provide the logic and the + * caller should make sure that this label is not used to branch + * prior to calling this macro. + */ +#define ASM_ASSERT(_cc) \ +.ifndef .L_assert_filename ;\ + .pushsection .rodata.str1.1, "aS" ;\ + .L_assert_filename: ;\ + .string __FILE__ ;\ + .popsection ;\ +.endif ;\ + b##_cc 300f ;\ + ldr r0, =.L_assert_filename ;\ + mov r1, #__LINE__ ;\ + b asm_assert ;\ +300: + +#endif /* __ASSERT_MACROS_S__ */ diff --git a/include/common/aarch64/asm_macros.S b/include/common/aarch64/asm_macros.S new file mode 100644 index 000000000..ad4729018 --- /dev/null +++ b/include/common/aarch64/asm_macros.S @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __ASM_MACROS_S__ +#define __ASM_MACROS_S__ + +#include <arch.h> +#include <asm_macros_common.S> + +#define TLB_INVALIDATE(_type) \ + tlbi _type + + .macro func_prologue + stp x29, x30, [sp, #-0x10]! + mov x29,sp + .endm + + .macro func_epilogue + ldp x29, x30, [sp], #0x10 + .endm + + + .macro dcache_line_size reg, tmp + mrs \tmp, ctr_el0 + ubfx \tmp, \tmp, #16, #4 + mov \reg, #4 + lsl \reg, \reg, \tmp + .endm + + + .macro icache_line_size reg, tmp + mrs \tmp, ctr_el0 + and \tmp, \tmp, #0xf + mov \reg, #4 + lsl \reg, \reg, \tmp + .endm + + /* + * Declare the exception vector table, enforcing it is aligned on a + * 2KB boundary, as required by the ARMv8 architecture. + * Use zero bytes as the fill value to be stored in the padding bytes + * so that it inserts illegal AArch64 instructions. This increases + * security, robustness and potentially facilitates debugging. + */ + .macro vector_base label + .section .vectors, "ax" + .align 11, 0 + \label: + .endm + + /* + * Create an entry in the exception vector table, enforcing it is + * aligned on a 128-byte boundary, as required by the ARMv8 + * architecture. Use zero bytes as the fill value to be stored in the + * padding bytes so that it inserts illegal AArch64 instructions. + * This increases security, robustness and potentially facilitates + * debugging. + */ + .macro vector_entry label + .section .vectors, "ax" + .align 7, 0 + \label: + .endm + + /* + * This macro verifies that the a given vector doesn't exceed the + * architectural limit of 32 instructions. This is meant to be placed + * immedately after the last instruction in the vector. It takes the + * vector entry as the parameter + */ + .macro check_vector_size since + .if (. - \since) > (32 * 4) + .error "Vector exceeds 32 instructions" + .endif + .endm + + /* + * This macro calculates the base address of an MP stack using the + * platform_get_core_pos() index, the name of the stack storage and + * the size of each stack + * Out: X0 = physical address of stack base + * Clobber: X30, X1, X2 + */ + .macro get_mp_stack _name, _size + bl platform_get_core_pos + ldr x2, =(\_name + \_size) + mov x1, #\_size + madd x0, x0, x1, x2 + .endm + + /* + * This macro calculates the base address of a UP stack using the + * name of the stack storage and the size of the stack + * Out: X0 = physical address of stack base + */ + .macro get_up_stack _name, _size + ldr x0, =(\_name + \_size) + .endm + + /* + * Helper macro to generate the best mov/movk combinations according + * the value to be moved. The 16 bits from '_shift' are tested and + * if not zero, they are moved into '_reg' without affecting + * other bits. + */ + .macro _mov_imm16 _reg, _val, _shift + .if (\_val >> \_shift) & 0xffff + .if (\_val & (1 << \_shift - 1)) + movk \_reg, (\_val >> \_shift) & 0xffff, LSL \_shift + .else + mov \_reg, \_val & (0xffff << \_shift) + .endif + .endif + .endm + + /* + * Helper macro to load arbitrary values into 32 or 64-bit registers + * which generates the best mov/movk combinations. Many base addresses + * are 64KB aligned the macro will eliminate updating bits 15:0 in + * that case + */ + .macro mov_imm _reg, _val + .if (\_val) == 0 + mov \_reg, #0 + .else + _mov_imm16 \_reg, (\_val), 0 + _mov_imm16 \_reg, (\_val), 16 + _mov_imm16 \_reg, (\_val), 32 + _mov_imm16 \_reg, (\_val), 48 + .endif + .endm + + .macro asm_read_sysreg_el1_or_el2 sysreg + mrs x0, CurrentEL + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq 1f + cmp x0, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq 2f + b dead +1: + mrs x0, \sysreg\()_el1 + b 3f +2: + mrs x0, \sysreg\()_el2 +3: + .endm + + .macro asm_write_sysreg_el1_or_el2 sysreg scratch_reg + mrs \scratch_reg, CurrentEL + cmp \scratch_reg, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq 1f + cmp \scratch_reg, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq 2f + b dead +1: + msr \sysreg\()_el1, x0 + b 3f +2: + msr \sysreg\()_el2, x0 +3: + .endm + + .macro asm_read_sctlr_el1_or_el2 + asm_read_sysreg_el1_or_el2 sctlr + .endm + + .macro asm_write_sctlr_el1_or_el2 scratch_reg + asm_write_sysreg_el1_or_el2 sctlr \scratch_reg + .endm + + .macro asm_write_vbar_el1_or_el2 scratch_reg + asm_write_sysreg_el1_or_el2 vbar \scratch_reg + .endm + +/* + * Depending on the current exception level, jump to 'label_el1' or 'label_el2'. + * If the current exception level is neither EL1 nor EL2, jump to 'label_error' + * instead. + * The caller needs to provide the macro with a scratch 64-bit register to use. + * Its contents prior to calling this function will be lost. + */ + .macro JUMP_EL1_OR_EL2 scratch_reg, label_el1, label_el2, label_error + mrs \scratch_reg, CurrentEL + cmp \scratch_reg, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq \label_el1 + cmp \scratch_reg, #(MODE_EL2 << MODE_EL_SHIFT) + b.eq \label_el2 + b \label_error + .endm + +#endif /* __ASM_MACROS_S__ */ diff --git a/include/common/aarch64/assert_macros.S b/include/common/aarch64/assert_macros.S new file mode 100644 index 000000000..b91633163 --- /dev/null +++ b/include/common/aarch64/assert_macros.S @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __ASSERT_MACROS_S__ +#define __ASSERT_MACROS_S__ + + /* + * Assembler macro to enable asm_assert. Use this macro wherever + * assert is required in assembly. Please note that the macro makes + * use of label '300' to provide the logic and the caller + * should make sure that this label is not used to branch prior + * to calling this macro. + */ +#define ASM_ASSERT(_cc) \ +.ifndef .L_assert_filename ;\ + .pushsection .rodata.str1.1, "aS" ;\ + .L_assert_filename: ;\ + .string __FILE__ ;\ + .popsection ;\ +.endif ;\ + b._cc 300f ;\ + adr x0, .L_assert_filename ;\ + mov x1, __LINE__ ;\ + b asm_assert ;\ +300: + +#endif /* __ASSERT_MACROS_S__ */ diff --git a/include/common/asm_macros_common.S b/include/common/asm_macros_common.S new file mode 100644 index 000000000..d38dcce71 --- /dev/null +++ b/include/common/asm_macros_common.S @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __ASM_MACROS_COMMON_S__ +#define __ASM_MACROS_COMMON_S__ + + /* + * This macro is used to create a function label and place the + * code into a separate text section based on the function name + * to enable elimination of unused code during linking. It also adds + * basic debug information to enable call stack printing most of the + * time. + */ + .macro func _name + /* + * Add Call Frame Information entry in the .debug_frame section for + * debugger consumption. This enables callstack printing in debuggers. + * This does not use any space in the final loaded binary, only in the + * ELF file. + * Note that a function manipulating the CFA pointer location (i.e. the + * x29 frame pointer on AArch64) should declare it using the + * appropriate .cfi* directives, or be prepared to have a degraded + * debugging experience. + */ + .cfi_sections .debug_frame + .section .text.\_name, "ax" + .type \_name, %function + .func \_name + /* + * .cfi_startproc and .cfi_endproc are needed to output entries in + * .debug_frame + */ + .cfi_startproc + \_name: + .endm + + /* + * This macro is used to mark the end of a function. + */ + .macro endfunc _name + .endfunc + .cfi_endproc + .size \_name, . - \_name + .endm + + /* + * This macro declares an array of 1 or more stacks, properly + * aligned and in the requested section + */ +#define STACK_ALIGN 6 + + .macro declare_stack _name, _section, _size, _count + .if ((\_size & ((1 << STACK_ALIGN) - 1)) <> 0) + .error "Stack size not correctly aligned" + .endif + .section \_section, "aw", %nobits + .align STACK_ALIGN + \_name: + .space ((\_count) * (\_size)), 0 + .endm + +#endif /* __ASM_MACROS_COMMON_S__ */ + diff --git a/include/common/debug.h b/include/common/debug.h new file mode 100644 index 000000000..c5b0f8e3b --- /dev/null +++ b/include/common/debug.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2014-2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +#include <stdio.h> + +/* TODO: Deal with per-image printf functions in a cleaner way. */ + +#ifdef IMAGE_CACTUS +/* + * The register MPIDR_EL1 can't be read from EL0, which means that mp_printf() + * can't be used. + */ +#define mp_printf printf +#else +/* + * Print a formatted string on the UART. + * + * Does the same thing as the standard libc's printf() function but in a MP-safe + * manner, i.e. it can be called from several CPUs simultaneously without + * getting interleaved messages. + * + * The messages printed using mp_printf() won't be saved in the test results + * (use tftf_testcase_output() instead for that). mp_printf() is meant to be + * used for debug traces only. Unlike messages stored in the tests output which + * appear only at the end of the test session in the test report, messages + * printed using mp_printf() will be displayed straight away. + * + * Messaged will be prefixed by the CPU MPID issuing the call, like that: + * [cpu 0x0002] Sending SGI #1 to cpu 0 + */ +__attribute__((format(printf, 1, 2))) +void mp_printf(const char *fmt, ...); +#endif + +/* + * The log output macros print output to the console. These macros produce + * compiled log output only if the LOG_LEVEL defined in the makefile (or the + * make command line) is greater or equal than the level required for that + * type of log output. + * The format expected is similar to printf(). For example: + * INFO("Info %s.\n", "message") -> [cpu 0xxx] INFO: Info message. + * WARN("Warning %s.\n", "message") -> [cpu 0xxx] WARNING: Warning message. + */ +#define LOG_LEVEL_NONE 0 +#define LOG_LEVEL_ERROR 10 +#define LOG_LEVEL_NOTICE 20 +#define LOG_LEVEL_WARNING 30 +#define LOG_LEVEL_INFO 40 +#define LOG_LEVEL_VERBOSE 50 + +#if LOG_LEVEL >= LOG_LEVEL_NOTICE +# define NOTICE(...) mp_printf("NOTICE: " __VA_ARGS__) +#else +# define NOTICE(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_ERROR +# define ERROR(...) mp_printf("ERROR: " __VA_ARGS__) +#else +# define ERROR(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_WARNING +# define WARN(...) mp_printf("WARNING: " __VA_ARGS__) +#else +# define WARN(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_INFO +# define INFO(...) mp_printf("INFO: " __VA_ARGS__) +#else +# define INFO(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE +# define VERBOSE(...) mp_printf("VERBOSE: " __VA_ARGS__) +#else +# define VERBOSE(...) +#endif + +/* + * For the moment this Panic function is very basic, Report an error and + * spin. This can be expanded in the future to provide more information. + */ +#if DEBUG +void __attribute__((__noreturn__)) do_panic(const char *file, int line); +#define panic() do_panic(__FILE__, __LINE__) + +void __attribute__((__noreturn__)) do_bug_unreachable(const char *file, int line); +#define bug_unreachable() do_bug_unreachable(__FILE__, __LINE__) + +#else +void __attribute__((__noreturn__)) do_panic(void); +#define panic() do_panic() + +void __attribute__((__noreturn__)) do_bug_unreachable(void); +#define bug_unreachable() do_bug_unreachable() + +#endif + +#endif /* __DEBUG_H__ */ diff --git a/include/common/firmware_image_package.h b/include/common/firmware_image_package.h new file mode 100644 index 000000000..f168f236e --- /dev/null +++ b/include/common/firmware_image_package.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __FIRMWARE_IMAGE_PACKAGE_H__ +#define __FIRMWARE_IMAGE_PACKAGE_H__ + +#include <stdint.h> +#include <uuid.h> + +/* This is used as a signature to validate the blob header */ +#define TOC_HEADER_NAME 0xAA640001 + +/* ToC Entry UUIDs */ +#define UUID_FIRMWARE_UPDATE_SCP_BL2U \ + {0x03279265, 0x742f, 0x44e6, 0x8d, 0xff, {0x57, 0x9a, 0xc1, 0xff, 0x06, 0x10} } +#define UUID_FIRMWARE_UPDATE_BL2U \ + {0x37ebb360, 0xe5c1, 0x41ea, 0x9d, 0xf3, {0x19, 0xed, 0xa1, 0x1f, 0x68, 0x01} } +#define UUID_FIRMWARE_UPDATE_NS_BL2U \ + {0x111d514f, 0xe52b, 0x494e, 0xb4, 0xc5, {0x83, 0xc2, 0xf7, 0x15, 0x84, 0x0a} } +#define UUID_FIRMWARE_UPDATE_FWU_CERT \ + {0xb28a4071, 0xd618, 0x4c87, 0x8b, 0x2e, {0xc6, 0xdc, 0xcd, 0x50, 0xf0, 0x96} } + +typedef struct fip_toc_header { + uint32_t name; + uint32_t serial_number; + uint64_t flags; +} fip_toc_header_t; + +typedef struct fip_toc_entry { + uuid_t uuid; + uint64_t offset_address; + uint64_t size; + uint64_t flags; +} fip_toc_entry_t; + +#endif /* __FIRMWARE_IMAGE_PACKAGE_H__ */ diff --git a/include/common/fwu_nvm.h b/include/common/fwu_nvm.h new file mode 100644 index 000000000..923a5968d --- /dev/null +++ b/include/common/fwu_nvm.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __FWU_NVM_H__ +#define __FWU_NVM_H__ + +#include <nvm.h> +#include <platform_def.h> + +#define FIP_IMAGE_UPDATE_DONE_FLAG (0xDEADBEEF) +/* + * This is the temporary ddr address for loading backup fip.bin + * image from NVM which is used for replacing original fip.bin + * This address is chosen such that the NS_BL2U can be expanded + * in future and also considering the large size of fip.bin. + */ +#define FIP_IMAGE_TMP_DDR_ADDRESS (DRAM_BASE + 0x100000) +#define FWU_TFTF_TESTCASE_BUFFER_OFFSET \ + (TFTF_NVM_OFFSET + TFTF_STATE_OFFSET(testcase_buffer)) + +/* + * This offset is used to corrupt data in fip.bin + * The offset is from the base where fip.bin is + * located in NVM. This particular value is chosen + * to make sure the corruption is done beyond fip header. + */ +#define FIP_CORRUPT_OFFSET (0x300) + +/* + * This is the base address for backup fip.bin image in NVM + * which is used for replacing original fip.bin + * This address is chosen such that it can stay with all + * the other images in the NVM. + */ +#define FIP_BKP_ADDRESS (FLASH_BASE + 0x1000000) + +/* Writes the buffer to the flash at offset with length equal to + * size + * Returns: STATUS_FAIL, STATUS_SUCCESS, STATUS_OUT_OF_RESOURCES + */ +STATUS fwu_nvm_write(unsigned long long offset, const void *buffer, size_t size); + +/* Reads the flash into buffer at offset with length equal to + * size + * Returns: STATUS_FAIL, STATUS_SUCCESS, STATUS_OUT_OF_RESOURCES + */ +STATUS fwu_nvm_read(unsigned long long offset, void *buffer, size_t size); + +/* + * This function is used to replace the original fip.bin + * by the backup fip.bin passed through fip_addr argument. + */ +STATUS fwu_update_fip(unsigned long fip_addr); + +#endif /* __FWU_NVM_H__ */ diff --git a/include/common/image_loader.h b/include/common/image_loader.h new file mode 100644 index 000000000..032c00ec3 --- /dev/null +++ b/include/common/image_loader.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __IMAGE_LOADER_H__ +#define __IMAGE_LOADER_H__ + +#include <firmware_image_package.h> +#include <stddef.h> +#include <stdint.h> + +/* Generic function to get flash offset of an image */ +unsigned long get_image_offset(unsigned int image_id); + +/* Generic function to return the size of an image */ +unsigned long get_image_size(unsigned int image_id); + +/* + * Generic function to load an image at a specific address given an image id + * Returns 0 on success, a negative error code otherwise. + */ +int load_image(unsigned int image_id, + uintptr_t image_base); + +/* + * Generic function to load partial image at a specific address given + * an image id. The flag argument is used to indicate last block to be + * loaded in the partial loading scenario. If is_last_block == 0 then + * devices are closed else they are kept open for partial image loading. + * Returns 0 on success, a negative error code otherwise. + */ +int load_partial_image(unsigned int image_id, + uintptr_t image_base, + size_t image_size, + unsigned int is_last_block); + +/* This is to keep track of file related data. */ +typedef struct { + unsigned int file_pos; + fip_toc_entry_t entry; +} fip_file_state_t; + +#endif /* __IMAGE_LOADER_H__ */ diff --git a/include/common/param_header.h b/include/common/param_header.h new file mode 100644 index 000000000..32763ddc3 --- /dev/null +++ b/include/common/param_header.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PARAM_HEADER_H__ +#define __PARAM_HEADER_H__ + +/* Param header types */ +#define PARAM_EP 0x01 +#define PARAM_IMAGE_BINARY 0x02 +#define PARAM_BL31 0x03 +#define PARAM_BL_LOAD_INFO 0x04 +#define PARAM_BL_PARAMS 0x05 +#define PARAM_PSCI_LIB_ARGS 0x06 +#define PARAM_SP_IMAGE_BOOT_INFO 0x07 + +/* Param header version */ +#define VERSION_1 0x01 +#define VERSION_2 0x02 + +#define SET_PARAM_HEAD(_p, _type, _ver, _attr) do { \ + (_p)->h.type = (uint8_t)(_type); \ + (_p)->h.version = (uint8_t)(_ver); \ + (_p)->h.size = (uint16_t)sizeof(*_p); \ + (_p)->h.attr = (uint32_t)(_attr) ; \ + } while (0) + +/* Following is used for populating structure members statically. */ +#define SET_STATIC_PARAM_HEAD(_p, _type, _ver, _p_type, _attr) \ + ._p.h.type = (uint8_t)(_type), \ + ._p.h.version = (uint8_t)(_ver), \ + ._p.h.size = (uint16_t)sizeof(_p_type), \ + ._p.h.attr = (uint32_t)(_attr) + +#ifndef __ASSEMBLY__ + +#include <types.h> + +/*************************************************************************** + * This structure provides version information and the size of the + * structure, attributes for the structure it represents + ***************************************************************************/ +typedef struct param_header { + uint8_t type; /* type of the structure */ + uint8_t version; /* version of this structure */ + uint16_t size; /* size of this structure in bytes */ + uint32_t attr; /* attributes: unused bits SBZ */ +} param_header_t; + +#endif /*__ASSEMBLY__*/ + +#endif /* __PARAM_HEADER_H__ */ + diff --git a/include/common/test_helpers.h b/include/common/test_helpers.h new file mode 100644 index 000000000..942e9f835 --- /dev/null +++ b/include/common/test_helpers.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __TEST_HELPERS_H__ +#define __TEST_HELPERS_H__ + +#include <plat_topology.h> +#include <psci.h> +#include <tftf_lib.h> +#include <trusted_os.h> +#include <tsp.h> +#include <uuid.h> +#include <uuid_utils.h> + +typedef struct { + uintptr_t addr; + size_t size; + unsigned int attr; + void *arg; +} map_args_unmap_t; + +typedef test_result_t (*test_function_arg_t)(void *arg); + +#define SKIP_TEST_IF_LESS_THAN_N_CLUSTERS(n) \ + do { \ + unsigned int clusters_cnt; \ + clusters_cnt = tftf_get_total_clusters_count(); \ + if (clusters_cnt < (n)) { \ + tftf_testcase_printf( \ + "Need at least %u clusters, only found %u\n", \ + (n), clusters_cnt); \ + return TEST_RESULT_SKIPPED; \ + } \ + } while (0) + +#define SKIP_TEST_IF_LESS_THAN_N_CPUS(n) \ + do { \ + unsigned int cpus_cnt; \ + cpus_cnt = tftf_get_total_cpus_count(); \ + if (cpus_cnt < (n)) { \ + tftf_testcase_printf( \ + "Need at least %u CPUs, only found %u\n", \ + (n), cpus_cnt); \ + return TEST_RESULT_SKIPPED; \ + } \ + } while (0) + +#define SKIP_TEST_IF_TRUSTED_OS_NOT_PRESENT() \ + do { \ + uuid_t tos_uuid; \ + \ + if (!is_trusted_os_present(&tos_uuid)) { \ + tftf_testcase_printf("No Trusted OS detected\n"); \ + return TEST_RESULT_SKIPPED; \ + } \ + } while (0) + +#define SKIP_TEST_IF_TSP_NOT_PRESENT() \ + do { \ + uuid_t tos_uuid; \ + char tos_uuid_str[UUID_STR_SIZE]; \ + \ + if (!is_trusted_os_present(&tos_uuid)) { \ + tftf_testcase_printf("No Trusted OS detected\n"); \ + return TEST_RESULT_SKIPPED; \ + } \ + \ + if (!uuid_equal(&tos_uuid, &tsp_uuid)) { \ + tftf_testcase_printf( \ + "Trusted OS is not the TSP, its UUID is: %s\n", \ + uuid_to_str(&tos_uuid, tos_uuid_str)); \ + return TEST_RESULT_SKIPPED; \ + } \ + } while (0) + +#define SKIP_TEST_IF_MM_NOT_PRESENT() \ + do { \ + smc_args version_smc = { MM_VERSION_AARCH32 }; \ + smc_ret_values smc_ret = tftf_smc(&version_smc); \ + uint32_t version = smc_ret.ret0; \ + \ + if (version == (uint32_t) SMC_UNKNOWN) { \ + tftf_testcase_printf("SPM not detected.\n"); \ + return TEST_RESULT_SKIPPED; \ + } \ + } while (0) + +#define SKIP_TEST_IF_MM_VERSION_LESS_THAN(major, minor) \ + do { \ + smc_args version_smc = { MM_VERSION_AARCH32 }; \ + smc_ret_values smc_ret = tftf_smc(&version_smc); \ + uint32_t version = smc_ret.ret0; \ + \ + if (version == (uint32_t) SMC_UNKNOWN) { \ + tftf_testcase_printf("SPM not detected.\n"); \ + return TEST_RESULT_SKIPPED; \ + } \ + \ + if (version < MM_VERSION_FORM(major, minor)) { \ + tftf_testcase_printf("MM_VERSION returned %d.%d\n" \ + "The required version is %d.%d\n", \ + version >> MM_VERSION_MAJOR_SHIFT, \ + version & MM_VERSION_MINOR_MASK, \ + major, minor); \ + return TEST_RESULT_SKIPPED; \ + } \ + \ + VERBOSE("MM_VERSION returned %d.%d\n", \ + version >> MM_VERSION_MAJOR_SHIFT, \ + version & MM_VERSION_MINOR_MASK); \ + } while (0) + +/* Helper macro to verify if system suspend API is supported */ +#define is_psci_sys_susp_supported() \ + (tftf_get_psci_feature_info(SMC_PSCI_SYSTEM_SUSPEND) \ + == PSCI_E_SUCCESS) + +/* Helper macro to verify if PSCI_STAT_COUNT API is supported */ +#define is_psci_stat_count_supported() \ + (tftf_get_psci_feature_info(SMC_PSCI_STAT_COUNT) \ + == PSCI_E_SUCCESS) + +/* + * Helper function to verify the system state is ready for system + * suspend. i.e., a single CPU is running and all other CPUs are powered off. + * Returns 1 if the system is ready to suspend, 0 otherwise. + */ +int is_sys_suspend_state_ready(void); + +/* + * Helper function to reset the system. This function shouldn't return. + * It is not marked with __dead to help the test to catch some error in + * TF + */ +void psci_system_reset(void); + +/* + * Helper function that enables/disables the mem_protect mechanism + */ +int psci_mem_protect(int val); + + +/* + * Helper function to call PSCI MEM_PROTECT_CHECK + */ +int psci_mem_protect_check(uintptr_t addr, size_t size); + + +/* + * Helper function to get a sentinel address that can be used to test mem_protect + */ +unsigned char *psci_mem_prot_get_sentinel(void); + +/* + * Helper function to memory map and unmap a region needed by a test. + * + * Return TEST_RESULT_FAIL if the memory could not be successfully mapped or + * unmapped. Otherwise, return the test functions's result. + */ +test_result_t map_test_unmap(const map_args_unmap_t *args, + test_function_arg_t test); + +#endif /* __TEST_HELPERS_H__ */ diff --git a/include/drivers/arm/arm_gic.h b/include/drivers/arm/arm_gic.h new file mode 100644 index 000000000..1a6bc3d46 --- /dev/null +++ b/include/drivers/arm/arm_gic.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __ARM_GIC_H__ +#define __ARM_GIC_H__ + +#include <stdint.h> + +/*************************************************************************** + * Defines and prototypes for ARM GIC driver. + **************************************************************************/ +#define MAX_SGIS 16 +#define MIN_SGI_ID 0 +#define MAX_SGI_ID 15 +#define MIN_PPI_ID 16 +#define MAX_PPI_ID 31 +#define MIN_SPI_ID 32 +#define MAX_SPI_ID 1020 + +#define IS_SGI(irq_num) \ + (((irq_num) >= MIN_SGI_ID) && ((irq_num) <= MAX_SGI_ID)) + +#define IS_PPI(irq_num) \ + (((irq_num) >= MIN_PPI_ID) && ((irq_num) <= MAX_PPI_ID)) + +#define IS_SPI(irq_num) \ + (((irq_num) >= MIN_SPI_ID) && ((irq_num) <= MAX_SPI_ID)) + +#define IS_VALID_INTR_ID(irq_num) \ + (((irq_num) >= MIN_SGI_ID) && ((irq_num) <= MAX_SPI_ID)) + +#define GIC_HIGHEST_NS_PRIORITY 0 +#define GIC_LOWEST_NS_PRIORITY 254 /* 255 would disable an interrupt */ +#define GIC_SPURIOUS_INTERRUPT 1023 + +/****************************************************************************** + * Setup the global GIC interface. In case of GICv2, it would be the GIC + * Distributor and in case of GICv3 it would be GIC Distributor and + * Re-distributor. + *****************************************************************************/ +void arm_gic_setup_global(void); + +/****************************************************************************** + * Setup the GIC interface local to the CPU + *****************************************************************************/ +void arm_gic_setup_local(void); + +/****************************************************************************** + * Disable interrupts for this local CPU + *****************************************************************************/ +void arm_gic_disable_interrupts_local(void); + +/****************************************************************************** + * Enable interrupts for this local CPU + *****************************************************************************/ +void arm_gic_enable_interrupts_local(void); + +/****************************************************************************** + * Send SGI with ID `sgi_id` to a core with index `core_pos`. + *****************************************************************************/ +void arm_gic_send_sgi(unsigned int sgi_id, unsigned int core_pos); + +/****************************************************************************** + * Set the interrupt target of interrupt ID `num` to a core with index + * `core_pos` + *****************************************************************************/ +void arm_gic_set_intr_target(unsigned int num, unsigned int core_pos); + +/****************************************************************************** + * Get the priority of the interrupt ID `num`. + *****************************************************************************/ +unsigned int arm_gic_get_intr_priority(unsigned int num); + +/****************************************************************************** + * Set the priority of the interrupt ID `num` to `priority`. + *****************************************************************************/ +void arm_gic_set_intr_priority(unsigned int num, unsigned int priority); + +/****************************************************************************** + * Check if the interrupt ID `num` is enabled + *****************************************************************************/ +unsigned int arm_gic_intr_enabled(unsigned int num); + +/****************************************************************************** + * Enable the interrupt ID `num` + *****************************************************************************/ +void arm_gic_intr_enable(unsigned int num); + +/****************************************************************************** + * Disable the interrupt ID `num` + *****************************************************************************/ +void arm_gic_intr_disable(unsigned int num); + +/****************************************************************************** + * Acknowledge the highest pending interrupt. Return the interrupt ID of the + * acknowledged interrupt. The raw interrupt acknowledge register value will + * be populated in `raw_iar`. + *****************************************************************************/ +unsigned int arm_gic_intr_ack(unsigned int *raw_iar); + +/****************************************************************************** + * Signal the end of interrupt processing of a interrupt. The raw interrupt + * acknowledge register value returned by arm_gic_intr_ack() should be passed + * as argument to this function. + *****************************************************************************/ +void arm_gic_end_of_intr(unsigned int raw_iar); + +/****************************************************************************** + * Check if the interrupt with ID `num` is pending at the GIC. Returns 1 if + * interrupt is pending else returns 0. + *****************************************************************************/ +unsigned int arm_gic_is_intr_pending(unsigned int num); + +/****************************************************************************** + * Clear the pending status of the interrupt with ID `num` at the GIC. + *****************************************************************************/ +void arm_gic_intr_clear(unsigned int num); + +/****************************************************************************** + * Initialize the GIC Driver. This function will detect the GIC Architecture + * present on the system and initialize the appropriate driver. The + * `gicr_base` argument will be ignored on GICv2 systems. + *****************************************************************************/ +void arm_gic_init(uintptr_t gicc_base, uintptr_t gicd_base, uintptr_t gicr_base); + +/****************************************************************************** + * Save the GIC context local to this CPU (like GIC CPU Interface) which will + * be lost when this CPU is powered down. + *****************************************************************************/ +void arm_gic_save_context_local(void); + +/****************************************************************************** + * Restore the GIC context local to this CPU ((like GIC CPU Interface) which + * was lost when this CPU was powered down. + *****************************************************************************/ +void arm_gic_restore_context_local(void); + +/****************************************************************************** + * Save the global GIC context when GIC will be powered down (like GIC + * Distributor and Re-distributor) as a result of system suspend. + *****************************************************************************/ +void arm_gic_save_context_global(void); + +/****************************************************************************** + * Restore the global GIC context which was lost as a result of GIC power + * down (like GIC Distributor and Re-distributor) during system suspend. + *****************************************************************************/ +void arm_gic_restore_context_global(void); + +#endif /* __ARM_GIC_H__ */ diff --git a/include/drivers/arm/gic_common.h b/include/drivers/arm/gic_common.h new file mode 100644 index 000000000..ea0340c31 --- /dev/null +++ b/include/drivers/arm/gic_common.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __GIC_COMMON_H__ +#define __GIC_COMMON_H__ + +/*************************************************************************** + * Defines and prototypes common to GIC v2 and v3 drivers. + **************************************************************************/ +/* Distributor interface register offsets */ +#define GICD_CTLR 0x0 +#define GICD_TYPER 0x4 +#define GICD_ISENABLER 0x100 +#define GICD_ICENABLER 0x180 +#define GICD_ISPENDR 0x200 +#define GICD_ICPENDR 0x280 +#define GICD_ISACTIVER 0x300 +#define GICD_ICACTIVER 0x380 +#define GICD_IPRIORITYR 0x400 +#define GICD_ICFGR 0xC00 + +/* Distributor interface register shifts */ +#define ISENABLER_SHIFT 5 +#define ICENABLER_SHIFT ISENABLER_SHIFT +#define ISPENDR_SHIFT 5 +#define ICPENDR_SHIFT ISPENDR_SHIFT +#define ISACTIVER_SHIFT 5 +#define ICACTIVER_SHIFT ISACTIVER_SHIFT +#define IPRIORITYR_SHIFT 2 +#define ICFGR_SHIFT 4 + +/* GICD_TYPER bit definitions */ +#define IT_LINES_NO_MASK 0x1f + +/* GICD Priority register mask */ +#define GIC_PRI_MASK 0xff + +/* + * Number of per-cpu interrupts to save prior to system suspend. + * This comprises all SGIs and PPIs. + */ +#define NUM_PCPU_INTR 32 + +#ifndef __ASSEMBLY__ + +#include <mmio.h> + +/* Helper to detect the GIC mode (GICv2 or GICv3) configured in the system */ +unsigned int is_gicv3_mode(void); + +/******************************************************************************* + * Private GIC Distributor function prototypes for use by GIC drivers + ******************************************************************************/ +unsigned int gicd_read_isenabler(unsigned int base, unsigned int interrupt_id); +unsigned int gicd_read_icenabler(unsigned int base, unsigned int interrupt_id); +unsigned int gicd_read_ispendr(unsigned int base, unsigned int interrupt_id); +unsigned int gicd_read_icpendr(unsigned int base, unsigned int interrupt_id); +unsigned int gicd_read_isactiver(unsigned int base, unsigned int interrupt_id); +unsigned int gicd_read_icactiver(unsigned int base, unsigned int interrupt_id); +unsigned int gicd_read_ipriorityr(unsigned int base, unsigned int interrupt_id); +unsigned int gicd_get_ipriorityr(unsigned int base, unsigned int interrupt_id); +unsigned int gicd_read_icfgr(unsigned int base, unsigned int interrupt_id); +void gicd_write_isenabler(unsigned int base, unsigned int interrupt_id, + unsigned int val); +void gicd_write_icenabler(unsigned int base, unsigned int interrupt_id, + unsigned int val); +void gicd_write_ispendr(unsigned int base, unsigned int interrupt_id, + unsigned int val); +void gicd_write_icpendr(unsigned int base, unsigned int interrupt_id, + unsigned int val); +void gicd_write_isactiver(unsigned int base, unsigned int interrupt_id, + unsigned int val); +void gicd_write_icactiver(unsigned int base, unsigned int interrupt_id, + unsigned int val); +void gicd_write_ipriorityr(unsigned int base, unsigned int interrupt_id, + unsigned int val); +void gicd_write_icfgr(unsigned int base, unsigned int interrupt_id, + unsigned int val); +unsigned int gicd_get_isenabler(unsigned int base, unsigned int interrupt_id); +void gicd_set_isenabler(unsigned int base, unsigned int interrupt_id); +void gicd_set_icenabler(unsigned int base, unsigned int interrupt_id); +void gicd_set_ispendr(unsigned int base, unsigned int interrupt_id); +void gicd_set_icpendr(unsigned int base, unsigned int interrupt_id); +void gicd_set_isactiver(unsigned int base, unsigned int interrupt_id); +void gicd_set_icactiver(unsigned int base, unsigned int interrupt_id); +void gicd_set_ipriorityr(unsigned int base, unsigned int interrupt_id, + unsigned int priority); + +/******************************************************************************* + * Private GIC Distributor interface accessors for reading and writing + * entire registers + ******************************************************************************/ +static inline unsigned int gicd_read_ctlr(unsigned int base) +{ + return mmio_read_32(base + GICD_CTLR); +} + +static inline unsigned int gicd_read_typer(unsigned int base) +{ + return mmio_read_32(base + GICD_TYPER); +} + +static inline void gicd_write_ctlr(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICD_CTLR, val); +} + + +#endif /*__ASSEMBLY__*/ +#endif /* __GIC_COMMON_H__ */ diff --git a/include/drivers/arm/gic_v2.h b/include/drivers/arm/gic_v2.h new file mode 100644 index 000000000..8432a3fc6 --- /dev/null +++ b/include/drivers/arm/gic_v2.h @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __GIC_V2_H__ +#define __GIC_V2_H__ + +/*************************************************************************** + * Defines and prototypes specific to GIC v2. + **************************************************************************/ + +/* GICD_CTLR bit definitions */ +#define GICD_CTLR_ENABLE (1 << 0) + +/* Distributor interface register offsets */ +#define GICD_ITARGETSR 0x800 +#define GICD_SGIR 0xF00 +#define GICD_CPENDSGIR 0xF10 +#define GICD_SPENDSGIR 0xF20 + +/* GIC Distributor register shifts */ +#define ITARGETSR_SHIFT 2 +#define CPENDSGIR_SHIFT 2 +#define SPENDSGIR_SHIFT CPENDSGIR_SHIFT + +/* GICD_SGIR bit shifts */ +#define GICD_SGIR_INTID_SHIFT 0 +#define GICD_SGIR_CPUTL_SHIFT 16 + +/* Physical CPU Interface register offsets */ +#define GICC_CTLR 0x0 +#define GICC_PMR 0x4 +#define GICC_BPR 0x8 +#define GICC_IAR 0xC +#define GICC_EOIR 0x10 +#define GICC_RPR 0x14 +#define GICC_HPPIR 0x18 +#define GICC_AHPPIR 0x28 +#define GICC_IIDR 0xFC +#define GICC_DIR 0x1000 +#define GICC_PRIODROP GICC_EOIR + +/* GICC_IIDR bit masks and shifts */ +#define GICC_IIDR_PID_SHIFT 20 +#define GICC_IIDR_ARCH_SHIFT 16 +#define GICC_IIDR_REV_SHIFT 12 +#define GICC_IIDR_IMP_SHIFT 0 + +#define GICC_IIDR_PID_MASK 0xfff +#define GICC_IIDR_ARCH_MASK 0xf +#define GICC_IIDR_REV_MASK 0xf +#define GICC_IIDR_IMP_MASK 0xfff + +/* HYP view virtual CPU Interface register offsets */ +#define GICH_CTL 0x0 +#define GICH_VTR 0x4 +#define GICH_ELRSR0 0x30 +#define GICH_ELRSR1 0x34 +#define GICH_APR0 0xF0 +#define GICH_LR_BASE 0x100 + +/* Virtual CPU Interface register offsets */ +#define GICV_CTL 0x0 +#define GICV_PRIMASK 0x4 +#define GICV_BP 0x8 +#define GICV_INTACK 0xC +#define GICV_EOI 0x10 +#define GICV_RUNNINGPRI 0x14 +#define GICV_HIGHESTPEND 0x18 +#define GICV_DEACTIVATE 0x1000 + +/* GICC_IAR bit masks and shifts */ +#define GICC_IAR_INTID_SHIFT 0 +#define GICC_IAR_CPUID_SHIFT 10 + +#define GICC_IAR_INTID_MASK 0x3ff +#define GICC_IAR_CPUID_MASK 0x7 + +#define get_gicc_iar_intid(val) (((val) >> GICC_IAR_INTID_SHIFT) \ + & GICC_IAR_INTID_MASK) +#define get_gicc_iar_cpuid(val) (((val) >> GICC_IAR_CPUID_SHIFT) \ + & GICC_IAR_CPUID_MASK) + +/* + * GICC_CTLR is banked to provide Secure and Non-secure copies and the register + * bit assignments are different in the Secure and Non-secure copies. + * These are the bit assignments for the Non-secure copy. + */ +#define GICC_CTLR_ENABLE (1 << 0) +#define FIQ_BYP_DIS_GRP1 (1 << 5) +#define IRQ_BYP_DIS_GRP1 (1 << 6) +#define EOI_MODE_NS (1 << 9) + +#ifndef __ASSEMBLY__ + +#include <mmio.h> + +/******************************************************************************* + * Private Interfaces for internal use by the GICv2 driver + ******************************************************************************/ + +/******************************************************************************* + * GICv2 Distributor interface accessors for reading/writing entire registers + ******************************************************************************/ +static inline unsigned int gicd_read_sgir(unsigned int base) +{ + return mmio_read_32(base + GICD_SGIR); +} + +static inline void gicd_write_sgir(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICD_SGIR, val); +} + +/******************************************************************************* + * GICv2 CPU interface accessors for reading entire registers + ******************************************************************************/ + +static inline unsigned int gicc_read_ctlr(unsigned int base) +{ + return mmio_read_32(base + GICC_CTLR); +} + +static inline unsigned int gicc_read_pmr(unsigned int base) +{ + return mmio_read_32(base + GICC_PMR); +} + +static inline unsigned int gicc_read_bpr(unsigned int base) +{ + return mmio_read_32(base + GICC_BPR); +} + +static inline unsigned int gicc_read_iar(unsigned int base) +{ + return mmio_read_32(base + GICC_IAR); +} + +static inline unsigned int gicc_read_eoir(unsigned int base) +{ + return mmio_read_32(base + GICC_EOIR); +} + +static inline unsigned int gicc_read_hppir(unsigned int base) +{ + return mmio_read_32(base + GICC_HPPIR); +} + +static inline unsigned int gicc_read_ahppir(unsigned int base) +{ + return mmio_read_32(base + GICC_AHPPIR); +} + +static inline unsigned int gicc_read_dir(unsigned int base) +{ + return mmio_read_32(base + GICC_DIR); +} + +static inline unsigned int gicc_read_iidr(unsigned int base) +{ + return mmio_read_32(base + GICC_IIDR); +} + + +/******************************************************************************* + * GICv2 CPU interface accessors for writing entire registers + ******************************************************************************/ + +static inline void gicc_write_ctlr(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_CTLR, val); +} + +static inline void gicc_write_pmr(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_PMR, val); +} + +static inline void gicc_write_bpr(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_BPR, val); +} + + +static inline void gicc_write_iar(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_IAR, val); +} + +static inline void gicc_write_eoir(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_EOIR, val); +} + +static inline void gicc_write_hppir(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_HPPIR, val); +} + +static inline void gicc_write_dir(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_DIR, val); +} + +/****************************************************************************** + * GICv2 public driver API + *****************************************************************************/ + +/* + * Initialize the GICv2 driver. The base addresses of GIC CPU interface + * `gicc_base` and the Distributor interface `gicd_base` must be provided + * as arguments. + */ +void gicv2_init(uintptr_t gicc_base, uintptr_t gicd_base); + +/* + * Write the GICv2 EOIR register with `val` passed as argument. `val` + * should be the raw value read from IAR register. + */ +void gicv2_gicc_write_eoir(unsigned int val); + +/* + * Set the bit corresponding to `interrupt_id` in the GICD ISPENDR register. + */ +void gicv2_gicd_set_ispendr(unsigned int interrupt_id); + +/* + * Set the bit corresponding to `interrupt_id` in the GICD ICPENDR register. + */ +void gicv2_gicd_set_icpendr(unsigned int interrupt_id); + +/* + * Get the bit corresponding to `interrupt_id` from the GICD ISPENDR register. + */ +unsigned int gicv2_gicd_get_ispendr(unsigned int interrupt_id); + +/* + * Read and return the value in GICC IAR register + */ +unsigned int gicv2_gicc_read_iar(void); + +/* + * Set the bit corresponding to `num` in the GICD ICENABLER register. + */ +void gicv2_gicd_set_icenabler(unsigned int num); + +/* + * Get the bit corresponding to `num` in the GICD ISENABLER register. + */ +unsigned int gicv2_gicd_get_isenabler(unsigned int num); + +/* + * Set the bit corresponding to `num` in the GICD ISENABLER register. + */ +void gicv2_gicd_set_isenabler(unsigned int num); + +/* + * Set the target of interrupt ID `num` to core with index `core_pos`. + */ +void gicv2_set_itargetsr(unsigned int num, unsigned int core_pos); + +/* + * Set the target of interrupt ID `num` to the desired core mask. + */ +void gicv2_set_itargetsr_value(unsigned int num, unsigned int val); + +/* + * Send SGI with ID `sgi_id` to core with index `core_pos`. + */ +void gicv2_send_sgi(unsigned int sgi_id, unsigned int core_pos); + +/* + * Get the priority of the interrupt `interrupt_id`. + */ +unsigned int gicv2_gicd_get_ipriorityr(unsigned int interrupt_id); + +/* + * Set the priority of the interrupt `interrupt_id` to `priority`. + */ +void gicv2_gicd_set_ipriorityr(unsigned int interrupt_id, unsigned int priority); + +/* + * Setup the GIC Distributor interface. + */ +void gicv2_setup_distif(void); + +/* + * Save the GICv2 SGI and PPI context prior to powering down the + * GIC Distributor. + */ +void gicv2_save_sgi_ppi_context(void); + +/* + * Restore the GICv2 SGI and PPI context after powering up the + * GIC Distributor. + */ +void gicv2_restore_sgi_ppi_context(void); + +/* + * Disable the GIC CPU interface. + */ +void gicv2_disable_cpuif(void); + +/* + * Setup the GIC CPU interface. + */ +void gicv2_setup_cpuif(void); + +/* + * Enable the GIC CPU interface. + */ +void gicv2_enable_cpuif(void); + +/* + * Save the GICv2 CPU interface prior to powering down the CPU interface. + */ +void gicv2_save_cpuif_context(void); + +/* + * Restore the GICv2 CPU interface after powering up the CPU interface. + */ +void gicv2_restore_cpuif_context(void); + +/* + * Read the GICD ITARGETR0 to figure out the GIC ID for the current core. + * This function is required to be invoked on successful boot of a core. + * The GIC ID will be stored internally by the driver to convert core index + * to GIC CPU ID when required. + */ +void gicv2_probe_gic_cpu_id(void); + + +#endif /*__ASSEMBLY__*/ +#endif /* __GIC_V2_H__ */ diff --git a/include/drivers/arm/gic_v3.h b/include/drivers/arm/gic_v3.h new file mode 100644 index 000000000..1b028b6e8 --- /dev/null +++ b/include/drivers/arm/gic_v3.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __GIC_V3_H__ +#define __GIC_V3_H__ + +/*************************************************************************** + * Defines and prototypes specific to GIC v3. + *************************************************************************/ + +/* GICD register offsets */ +#define GICD_IROUTER 0x6000 + +/* GICD_CTLR bit definitions */ +#define GICD_CTLR_ENABLE_GRP1A (1 << 1) +#define GICD_CTLR_ARE_NS_SHIFT 4 +#define GICD_CTLR_ARE_NS_MASK 0x1 + +/* GICR_TYPER bit definitions */ +#define TYPER_AFF_VAL_SHIFT 32 +#define TYPER_PROC_NUM_SHIFT 8 +#define TYPER_LAST_SHIFT 4 + +#define TYPER_AFF_VAL_MASK 0xffffffff +#define TYPER_PROC_NUM_MASK 0xffff +#define TYPER_LAST_MASK 0x1 + +#define TYPER_LAST_BIT (1 << TYPER_LAST_SHIFT) + +/* GICD_IROUTER shifts and masks */ +#define IROUTER_IRM_SHIFT 31 +#define IROUTER_IRM_MASK 0x1 + +/******************************************************************************* + * GICv3 Re-distributor interface registers & constants + ******************************************************************************/ +#define GICR_PCPUBASE_SHIFT 0x11 +#define GICR_SGIBASE_OFFSET (1 << 0x10) /* 64 KB */ +#define GICR_CTLR 0x0 +#define GICR_TYPER 0x08 +#define GICR_WAKER 0x14 +#define GICR_IGROUPR0 (GICR_SGIBASE_OFFSET + 0x80) +#define GICR_ISENABLER0 (GICR_SGIBASE_OFFSET + 0x100) +#define GICR_ICENABLER0 (GICR_SGIBASE_OFFSET + 0x180) +#define GICR_ISPENDR0 (GICR_SGIBASE_OFFSET + 0x200) +#define GICR_ICPENDR0 (GICR_SGIBASE_OFFSET + 0x280) +#define GICR_IPRIORITYR (GICR_SGIBASE_OFFSET + 0x400) +#define GICR_ICFGR0 (GICR_SGIBASE_OFFSET + 0xc00) +#define GICR_ICFGR1 (GICR_SGIBASE_OFFSET + 0xc04) +#define GICR_IGRPMODR0 (GICR_SGIBASE_OFFSET + 0xd00) + +/******************************************************************************* + * GICv3 CPU interface registers & constants + ******************************************************************************/ +/* ICC_SRE bit definitions*/ +#define ICC_SRE_EN_BIT (1 << 3) +#define ICC_SRE_DIB_BIT (1 << 2) +#define ICC_SRE_DFB_BIT (1 << 1) +#define ICC_SRE_SRE_BIT (1 << 0) + +/* ICC_IAR1_EL1 bit definitions */ +#define IAR1_EL1_INTID_SHIFT 0 +#define IAR1_EL1_INTID_MASK 0xffffff + +/* ICC_SGI1R bit definitions */ +#define SGI1R_TARGET_LIST_MASK 0xffff +#define SGI1R_TARGET_LIST_SHIFT 0x0 +#define SGI1R_AFF_MASK 0xff +#define SGI1R_AFF1_SHIFT 16ULL +#define SGI1R_AFF2_SHIFT 32ULL +#ifndef AARCH32 +#define SGI1R_AFF3_SHIFT 48ULL +#endif +#define SGI1R_INTID_MASK 0xf +#define SGI1R_INTID_SHIFT 24 +#define SGI1R_IRM_MASK 0x1 +#define SGI1R_IRM_SHIFT 0x40 + +/* ICC_IGRPEN1_EL1 bit definitions */ +#define IGRPEN1_EL1_ENABLE_SHIFT 0 +#define IGRPEN1_EL1_ENABLE_BIT (1 << IGRPEN1_EL1_ENABLE_SHIFT) + +/* The highest affinity 0 that can be a SGI target*/ +#define SGI_TARGET_MAX_AFF0 16 + +#ifndef ASSEMBLY + +/******************************************************************************* + * Helper GICv3 macros + ******************************************************************************/ +#define gicv3_acknowledge_interrupt() read_icc_iar1_el1() &\ + IAR1_EL1_INTID_MASK +#define gicv3_end_of_interrupt(id) write_icc_eoir1_el1(id) + +#define is_sre_enabled() \ + (IS_IN_EL2() ? (read_icc_sre_el2() & ICC_SRE_SRE_BIT) :\ + (read_icc_sre_el1() & ICC_SRE_SRE_BIT)) + +/****************************************************************************** + * GICv3 public driver API + *****************************************************************************/ + /* + * Initialize the GICv3 driver. The base addresses of GIC Re-distributor + * interface `gicr_base` and the Distributor interface `gicd_base` must + * be provided as arguments. + */ +void gicv3_init(uintptr_t gicr_base, uintptr_t gicd_base); + +/* + * Setup the GIC Distributor interface. + */ +void gicv3_setup_distif(void); + +/* + * Probe the Re-distributor base corresponding to this core. + * This function is required to be invoked on successful boot of a core. + * The base address will be stored internally by the driver and will be + * used when accessing the Re-distributor interface. + */ +void gicv3_probe_redistif_addr(void); + +/* + * Set the bit corresponding to `interrupt_id` in the ICPENDR register + * at either Distributor or Re-distributor depending on the interrupt. + */ +void gicv3_set_icpendr(unsigned int interrupt_id); + +/* + * Get the bit corresponding to `interrupt_id` in the ISPENDR register + * at either Distributor or Re-distributor depending on the interrupt. + */ +unsigned int gicv3_get_ispendr(unsigned int interrupt_id); + +/* + * Set the bit corresponding to `interrupt_id` in the ICENABLER register + * at either Distributor or Re-distributor depending on the interrupt. + */ +void gicv3_set_icenabler(unsigned int interrupt_id); + +/* + * Get the bit corresponding to `interrupt_id` in the ISENABLER register + * at either Distributor or Re-distributor depending on the interrupt. + */ +unsigned int gicv3_get_isenabler(unsigned int interrupt_id); + +/* + * Set the bit corresponding to `interrupt_id` in the ISENABLER register + * at either Distributor or Re-distributor depending on the interrupt. + */ +void gicv3_set_isenabler(unsigned int interrupt_id); + +/* + * Set the `route` corresponding to `interrupt_id` in the IROUTER register + * at Distributor. + */ +void gicv3_set_intr_route(unsigned int interrupt_id, unsigned int core_pos); + +/* + * Send SGI with ID `sgi_id` to core with index `core_pos`. + */ +void gicv3_send_sgi(unsigned int sgi_id, unsigned int core_pos); + +/* + * Get the priority of the interrupt `interrupt_id`. + */ +unsigned int gicv3_get_ipriorityr(unsigned int interrupt_id); + +/* + * Set the priority of the interrupt `interrupt_id` to `priority`. + */ +void gicv3_set_ipriorityr(unsigned int interrupt_id, unsigned int priority); + +/* + * Restore the GICv3 SGI and PPI context after powering up the + * GIC Re-distributor. + */ +void gicv3_restore_sgi_ppi_context(void); + +/* + * Save the GICv3 SGI and PPI context prior to powering down the + * GIC Re-distributor. + */ +void gicv3_save_sgi_ppi_context(void); + +/* + * Restore the GICv3 CPU interface after powering up the CPU interface. + */ +void gicv3_restore_cpuif_context(void); + +/* + * Save the GICv3 CPU interface prior to powering down the CPU interface. + */ +void gicv3_save_cpuif_context(void); + +/* + * Disable the GIC CPU interface. + */ +void gicv3_disable_cpuif(void); + +/* + * Setup the GIC CPU interface. + */ +void gicv3_setup_cpuif(void); + +/* + * Enable the GIC CPU interface. + */ +void gicv3_enable_cpuif(void); + + +#endif /*__ASSEMBLY__*/ +#endif /* __GIC_V3_H__ */ diff --git a/include/drivers/arm/pl011.h b/include/drivers/arm/pl011.h new file mode 100644 index 000000000..cba325d5a --- /dev/null +++ b/include/drivers/arm/pl011.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PL011_H__ +#define __PL011_H__ + +/* PL011 Registers */ +#define UARTDR 0x000 +#define UARTRSR 0x004 +#define UARTECR 0x004 +#define UARTFR 0x018 +#define UARTILPR 0x020 +#define UARTIBRD 0x024 +#define UARTFBRD 0x028 +#define UARTLCR_H 0x02C +#define UARTCR 0x030 +#define UARTIFLS 0x034 +#define UARTIMSC 0x038 +#define UARTRIS 0x03C +#define UARTMIS 0x040 +#define UARTICR 0x044 +#define UARTDMACR 0x048 + +/* Data status bits */ +#define UART_DATA_ERROR_MASK 0x0F00 + +/* Status reg bits */ +#define UART_STATUS_ERROR_MASK 0x0F + +/* Flag reg bits */ +#define PL011_UARTFR_RI (1 << 8) /* Ring indicator */ +#define PL011_UARTFR_TXFE (1 << 7) /* Transmit FIFO empty */ +#define PL011_UARTFR_RXFF (1 << 6) /* Receive FIFO full */ +#define PL011_UARTFR_TXFF (1 << 5) /* Transmit FIFO full */ +#define PL011_UARTFR_RXFE (1 << 4) /* Receive FIFO empty */ +#define PL011_UARTFR_BUSY (1 << 3) /* UART busy */ +#define PL011_UARTFR_DCD (1 << 2) /* Data carrier detect */ +#define PL011_UARTFR_DSR (1 << 1) /* Data set ready */ +#define PL011_UARTFR_CTS (1 << 0) /* Clear to send */ + +#define PL011_UARTFR_TXFF_BIT 5 /* Transmit FIFO full bit in UARTFR register */ +#define PL011_UARTFR_RXFE_BIT 4 /* Receive FIFO empty bit in UARTFR register */ +#define PL011_UARTFR_BUSY_BIT 3 /* UART busy bit in UARTFR register */ + +/* Control reg bits */ +#define PL011_UARTCR_CTSEN (1 << 15) /* CTS hardware flow control enable */ +#define PL011_UARTCR_RTSEN (1 << 14) /* RTS hardware flow control enable */ +#define PL011_UARTCR_RTS (1 << 11) /* Request to send */ +#define PL011_UARTCR_DTR (1 << 10) /* Data transmit ready. */ +#define PL011_UARTCR_RXE (1 << 9) /* Receive enable */ +#define PL011_UARTCR_TXE (1 << 8) /* Transmit enable */ +#define PL011_UARTCR_LBE (1 << 7) /* Loopback enable */ +#define PL011_UARTCR_UARTEN (1 << 0) /* UART Enable */ + +#if !defined(PL011_LINE_CONTROL) +/* FIFO Enabled / No Parity / 8 Data bit / One Stop Bit */ +#define PL011_LINE_CONTROL (PL011_UARTLCR_H_FEN | PL011_UARTLCR_H_WLEN_8) +#endif + +/* Line Control Register Bits */ +#define PL011_UARTLCR_H_SPS (1 << 7) /* Stick parity select */ +#define PL011_UARTLCR_H_WLEN_8 (3 << 5) +#define PL011_UARTLCR_H_WLEN_7 (2 << 5) +#define PL011_UARTLCR_H_WLEN_6 (1 << 5) +#define PL011_UARTLCR_H_WLEN_5 (0 << 5) +#define PL011_UARTLCR_H_FEN (1 << 4) /* FIFOs Enable */ +#define PL011_UARTLCR_H_STP2 (1 << 3) /* Two stop bits select */ +#define PL011_UARTLCR_H_EPS (1 << 2) /* Even parity select */ +#define PL011_UARTLCR_H_PEN (1 << 1) /* Parity Enable */ +#define PL011_UARTLCR_H_BRK (1 << 0) /* Send break */ + +/* Constants */ +#define PL011_BAUDRATE 115200 + +#endif /* __PL011_H__ */ diff --git a/include/drivers/arm/private_timer.h b/include/drivers/arm/private_timer.h new file mode 100644 index 000000000..aff0b8ec5 --- /dev/null +++ b/include/drivers/arm/private_timer.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PRIVATE_TIMER_H__ +#define __PRIVATE_TIMER_H__ + +void private_timer_start(unsigned long timeo); +void private_timer_stop(void); +void private_timer_save(void); +void private_timer_restore(void); + +#endif /* __PRIVATE_TIMER_H__ */ diff --git a/include/drivers/arm/sp804.h b/include/drivers/arm/sp804.h new file mode 100644 index 000000000..7ca556762 --- /dev/null +++ b/include/drivers/arm/sp804.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SP804_H__ +#define __SP804_H__ + +#define SP804_LOAD_OFFSET 0x0 +#define SP804_CURRENT_VALUE_OFFSET 0x4 +#define SP804_CTRL_OFFSET 0x8 +#define SP804_INT_CLR_OFFSET 0xC +#define SP804_INT_STATUS_OFFSET 0x10 +#define SP804_MASKED_INT_STATUS_OFFSET 0x14 +#define SP804_BG_LOAD_OFFSET 0x18 + +/* SP804 Timer control register bit-fields */ +#define ONESHOT_MODE (0x1 << 0) /* Bit [0] */ +#define TIMER_SIZE (0x1 << 1) /* Bit [1] */ +#define TIMER_PRE_DIV1 (0x00 << 2) /* Bits [2:3] */ +#define INT_ENABLE (0x01 << 5) /* Bit [5] */ +#define TIMER_MODE_FREE_RUN (0x0 << 6) /* Bit [6] */ +#define TIMER_EN (0x01 << 7) /* Bit [7] */ + +/* + * Program sp804 timer to fire an interrupt after `time_out_ms` milliseconds. + * + * Always return 0 + */ +int sp804_timer_program(unsigned long time_out_ms); + +/* + * Cancel the currently programmed sp804 timer interrupt + * + * Always return 0 + */ +int sp804_timer_cancel(void); + +/* + * Initializes the sp804 timer so that it can be used for programming + * timer interrupt. + * Must be called by the primary CPU only. + * + * Always return 0 + */ +int sp804_timer_init(uintptr_t base_addr, unsigned int timer_freq); + +/* + * Handler to acknowledge and de-activate the sp804 timer interrupt + * + * Always return 0 + */ +int sp804_timer_handler(void); + +#endif /* __SP804_H__ */ diff --git a/include/drivers/arm/sp805.h b/include/drivers/arm/sp805.h new file mode 100644 index 000000000..c033ccfda --- /dev/null +++ b/include/drivers/arm/sp805.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SP805_H__ +#define __SP805_H__ + +/* SP805 register offset */ +#define SP805_WDOG_LOAD_OFF 0x000 +#define SP805_WDOG_VALUE_0FF 0x004 +#define SP805_WDOG_CTRL_OFF 0x008 +#define SP805_WDOG_INT_CLR_OFF 0x00c +#define SP805_WDOG_RIS_OFF 0x010 +#define SP805_WDOG_MIS_OFF 0x014 +#define SP805_WDOG_LOCK_OFF 0xc00 +#define SP805_WDOG_ITCR_OFF 0xf00 +#define SP805_WDOG_ITOP_OFF 0xf04 +#define SP805_WDOG_PERIPH_ID_OFF 0xfe0 +#define SP805_WDOG_PCELL_ID_OFF 0xff0 + +/* + * Magic word to unlock access to all other watchdog registers, Writing any other + * value locks them. + */ +#define SP805_WDOG_UNLOCK_ACCESS 0x1ACCE551 + +/* Register field definitions */ +#define SP805_WDOG_CTRL_MASK 0x03 +#define SP805_WDOG_CTRL_RESEN (1 << 1) +#define SP805_WDOG_CTRL_INTEN (1 << 0) +#define SP805_WDOG_RIS_WDOGRIS (1 << 0) +#define SP805_WDOG_RIS_MASK 0x1 +#define SP805_WDOG_MIS_WDOGMIS (1 << 0) +#define SP805_WDOG_MIS_MASK 0x1 +#define SP805_WDOG_ITCR_MASK 0x1 +#define SP805_WDOG_ITOP_MASK 0x3 +#define SP805_WDOG_PART_NUM_SHIFT 0 +#define SP805_WDOG_PART_NUM_MASK 0xfff +#define SP805_WDOG_DESIGNER_ID_SHIFT 12 +#define SP805_WDOG_DESIGNER_ID_MASK 0xff +#define SP805_WDOG_REV_SHIFT 20 +#define SP805_WDOG_REV_MASK 0xf +#define SP805_WDOG_CFG_SHIFT 24 +#define SP805_WDOG_CFG_MASK 0xff +#define SP805_WDOG_PCELL_ID_SHIFT 0 +#define SP805_WDOG_PCELL_ID_MASK 0xff + +void sp805_wdog_start(unsigned int wdog_cycles); +void sp805_wdog_stop(void); +void sp805_wdog_refresh(void); + +#endif /* __SP805_H__ */ + diff --git a/include/drivers/arm/system_timer.h b/include/drivers/arm/system_timer.h new file mode 100644 index 000000000..8cd0c8e69 --- /dev/null +++ b/include/drivers/arm/system_timer.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SYSTEM_TIMER_H__ +#define __SYSTEM_TIMER_H__ + +/* + * Program systimer to fire an interrupt after time_out_ms + * + * Always return 0 + */ +int program_systimer(unsigned long time_out_ms); +/* + * Cancel the currently programmed systimer interrupt + * + * Always return 0 + */ +int cancel_systimer(void); +/* + * Initialises the systimer so that it can be used for programming timer + * interrupt. + * Must be called by the primary CPU only. + * + * Always return 0 + */ +int init_systimer(uintptr_t systimer_base); +/* + * Handler to acknowledge and de-activate the systimer interrupt + * + * Always return 0 + */ +int handler_systimer(void); + +#endif /* __SYSTEM_TIMER_H__ */ diff --git a/include/drivers/console.h b/include/drivers/console.h new file mode 100644 index 000000000..abbe35612 --- /dev/null +++ b/include/drivers/console.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CONSOLE_H__ +#define __CONSOLE_H__ + +/* Returned by getc callbacks when receive FIFO is empty. */ +#define ERROR_NO_PENDING_CHAR -1 +/* Returned by console_xxx() if the registered console doesn't implement xxx. */ +#define ERROR_NO_VALID_CONSOLE (-128) + +#ifndef __ASSEMBLY__ + +#include <types.h> + +int console_init(uintptr_t base_addr, + unsigned int uart_clk, unsigned int baud_rate); +int console_putc(int c); +int console_getc(void); +int console_try_getc(void); +int console_flush(void); + +#endif /* __ASSEMBLY__ */ + +#endif /* __CONSOLE_H__ */ diff --git a/include/drivers/io/io_driver.h b/include/drivers/io/io_driver.h new file mode 100644 index 000000000..e2e2d52b6 --- /dev/null +++ b/include/drivers/io/io_driver.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __IO_DRIVER_H__ +#define __IO_DRIVER_H__ + +#include <io_storage.h> +#include <stdint.h> + + +/* Generic IO entity structure,representing an accessible IO construct on the + * device, such as a file */ +typedef struct io_entity { + struct io_dev_info *dev_handle; + uintptr_t info; +} io_entity_t; + + +/* Device info structure, providing device-specific functions and a means of + * adding driver-specific state */ +typedef struct io_dev_info { + const struct io_dev_funcs *funcs; + uintptr_t info; +} io_dev_info_t; + + +/* Structure used to create a connection to a type of device */ +typedef struct io_dev_connector { + /* dev_open opens a connection to a particular device driver */ + int (*dev_open)(const uintptr_t dev_spec, io_dev_info_t **dev_info); +} io_dev_connector_t; + + +/* Structure to hold device driver function pointers */ +typedef struct io_dev_funcs { + io_type_t (*type)(void); + int (*open)(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); + int (*seek)(io_entity_t *entity, int mode, ssize_t offset); + int (*size)(io_entity_t *entity, size_t *length); + int (*read)(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); + int (*write)(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written); + int (*close)(io_entity_t *entity); + int (*dev_init)(io_dev_info_t *dev_info, const uintptr_t init_params); + int (*dev_close)(io_dev_info_t *dev_info); +} io_dev_funcs_t; + + +/* Operations intended to be performed during platform initialisation */ + +/* Register an IO device */ +int io_register_device(const io_dev_info_t *dev_info); + +#endif /* __IO_DRIVER_H__ */ diff --git a/include/drivers/io/io_fip.h b/include/drivers/io/io_fip.h new file mode 100644 index 000000000..973515200 --- /dev/null +++ b/include/drivers/io/io_fip.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __IO_FIP_H__ +#define __IO_FIP_H__ + +#include <assert.h> + +struct io_dev_connector; + +int register_io_dev_fip(const struct io_dev_connector **dev_con); + +enum { + /* Non-Trusted Updater Firmware NS_BL1U */ + NS_BL1U_IMAGE_ID = 16, + + /* Trusted FWU Certificate */ + FWU_CERT_ID, + + /* SCP Firmware SCP_BL2U */ + SCP_BL2U_IMAGE_ID, + + /* Trusted Updater Firmware BL2U */ + BL2U_IMAGE_ID, + + /* Non-Trusted Updater Firmware NS_BL2U */ + NS_BL2U_IMAGE_ID, + + /* FWU Firmware Image Package */ + FWU_FIP_IMAGE_ID +}; + +static inline const char *get_image_name(unsigned int image_id) +{ + static const char *image_names[] = { + "Non-Trusted Updater Firmware (NS_BL1U)", + "Trusted FWU Certificate", + "SCP Firmware (SCP_BL2U)", + "Trusted Updater Firmware (BL2U)", + "Non-Trusted Updater Firmware (NS_BL2U)" + "FWU Firmware Image Package", + }; + assert((image_id >= NS_BL1U_IMAGE_ID) && (image_id <= FWU_FIP_IMAGE_ID)); + return image_names[image_id - NS_BL1U_IMAGE_ID]; +} + +#endif /* __IO_FIP_H__ */ diff --git a/include/drivers/io/io_memmap.h b/include/drivers/io/io_memmap.h new file mode 100644 index 000000000..2094b9396 --- /dev/null +++ b/include/drivers/io/io_memmap.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __IO_MEMMAP_H__ +#define __IO_MEMMAP_H__ + +struct io_dev_connector; + +int register_io_dev_memmap(const struct io_dev_connector **dev_con); + +#endif /* __IO_MEMMAP_H__ */ diff --git a/include/drivers/io/io_nor_flash.h b/include/drivers/io/io_nor_flash.h new file mode 100644 index 000000000..03058e9c9 --- /dev/null +++ b/include/drivers/io/io_nor_flash.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __IO_NOR_FLASH_H__ +#define __IO_NOR_FLASH_H__ + +#include <platform_def.h> + +#ifndef NOR_FLASH_BLOCK_SIZE + #error NOR_FLASH_BLOCK_SIZE must be defined as the block \ + size of the NOR Flash seen by the software +#endif + +/* IO NOR Flash specification - used to refer to data on a memory map device + * supporting block-like entities */ +typedef struct io_nor_spec { + /* Base Address of the NOR Flash device - it is required to program + * the flash */ + uintptr_t device_address; + uintptr_t region_address; + uint32_t block_size; + uint32_t block_count; +} io_nor_flash_spec_t; + +struct io_dev_connector; + +int register_io_dev_nor_flash(const struct io_dev_connector **dev_con); + +#endif /* __IO_NOR_FLASH_H__ */ diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h new file mode 100644 index 000000000..a537dcfee --- /dev/null +++ b/include/lib/aarch32/arch.h @@ -0,0 +1,595 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __ARCH_H__ +#define __ARCH_H__ + +#include <utils_def.h> + +/******************************************************************************* + * MIDR bit definitions + ******************************************************************************/ +#define MIDR_IMPL_MASK U(0xff) +#define MIDR_IMPL_SHIFT U(24) +#define MIDR_VAR_SHIFT U(20) +#define MIDR_VAR_BITS U(4) +#define MIDR_REV_SHIFT U(0) +#define MIDR_REV_BITS U(4) +#define MIDR_PN_MASK U(0xfff) +#define MIDR_PN_SHIFT U(4) + +/******************************************************************************* + * MPIDR macros + ******************************************************************************/ +#define MPIDR_MT_MASK (U(1) << 24) +#define MPIDR_CPU_MASK MPIDR_AFFLVL_MASK +#define MPIDR_CLUSTER_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS) +#define MPIDR_AFFINITY_BITS U(8) +#define MPIDR_AFFLVL_MASK U(0xff) +#define MPIDR_AFFLVL_SHIFT U(3) +#define MPIDR_AFF0_SHIFT U(0) +#define MPIDR_AFF1_SHIFT U(8) +#define MPIDR_AFF2_SHIFT U(16) +#define MPIDR_AFF_SHIFT(_n) MPIDR_AFF##_n##_SHIFT +#define MPIDR_AFFINITY_MASK U(0x00ffffff) +#define MPIDR_AFFLVL0 U(0) +#define MPIDR_AFFLVL1 U(1) +#define MPIDR_AFFLVL2 U(2) +#define MPIDR_AFFLVL(_n) MPIDR_AFFLVL##_n + +#define MPIDR_AFFLVL0_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK) +#define MPIDR_AFFLVL1_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK) +#define MPIDR_AFFLVL2_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK) + +#define MPIDR_AFF_ID(mpid, n) \ + (((mpid) >> MPIDR_AFF_SHIFT(n)) & MPIDR_AFFLVL_MASK) + +#define MPIDR_CLUSTER_ID(mpid) MPIDR_AFF_ID(mpid, 1) +#define MPIDR_CPU_ID(mpid) MPIDR_AFF_ID(mpid, 0) + +/* Constant to highlight the assumption that MPIDR allocation starts from 0 */ +#define FIRST_MPIDR U(0) + +#define MPID_MASK (MPIDR_MT_MASK |\ + (MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT)|\ + (MPIDR_AFFLVL_MASK << MPIDR_AFF1_SHIFT)|\ + (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) + +/* + * An invalid MPID. This value can be used by functions that return an MPID to + * indicate an error. + */ +#define INVALID_MPID U(0xFFFFFFFF) + +/* + * The MPIDR_MAX_AFFLVL count starts from 0. Take care to + * add one while using this macro to define array sizes. + */ +#define MPIDR_MAX_AFFLVL U(2) + +/* Data Cache set/way op type defines */ +#define DC_OP_ISW U(0x0) +#define DC_OP_CISW U(0x1) +#define DC_OP_CSW U(0x2) + +/******************************************************************************* + * Generic timer memory mapped registers & offsets + ******************************************************************************/ +#define CNTCR_OFF U(0x000) +#define CNTFID_OFF U(0x020) + +#define CNTCR_EN (U(1) << 0) +#define CNTCR_HDBG (U(1) << 1) +#define CNTCR_FCREQ(x) ((x) << 8) + +/******************************************************************************* + * System register bit definitions + ******************************************************************************/ +/* CLIDR definitions */ +#define LOUIS_SHIFT U(21) +#define LOC_SHIFT U(24) +#define CLIDR_FIELD_WIDTH U(3) + +/* CSSELR definitions */ +#define LEVEL_SHIFT U(1) + +/* ID_PFR0 definitions */ +#define ID_PFR0_AMU_SHIFT U(20) +#define ID_PFR0_AMU_LENGTH U(4) +#define ID_PFR0_AMU_MASK U(0xf) + +/* ID_PFR1 definitions */ +#define ID_PFR1_VIRTEXT_SHIFT U(12) +#define ID_PFR1_VIRTEXT_MASK U(0xf) +#define GET_VIRT_EXT(id) (((id) >> ID_PFR1_VIRTEXT_SHIFT) \ + & ID_PFR1_VIRTEXT_MASK) +#define ID_PFR1_GIC_SHIFT U(28) +#define ID_PFR1_GIC_MASK U(0xf) + +/* SCTLR definitions */ +#define SCTLR_RES1 ((U(1) << 23) | (U(1) << 22) | (U(1) << 11) | \ + (U(1) << 4) | (U(1) << 3) | SCTLR_CP15BEN_BIT \ + | SCTLR_NTWI_BIT | SCTLR_NTWE_BIT) +#define SCTLR_M_BIT (U(1) << 0) +#define SCTLR_A_BIT (U(1) << 1) +#define SCTLR_C_BIT (U(1) << 2) +#define SCTLR_CP15BEN_BIT (U(1) << 5) +#define SCTLR_ITD_BIT (U(1) << 7) +#define SCTLR_Z_BIT (U(1) << 11) +#define SCTLR_I_BIT (U(1) << 12) +#define SCTLR_V_BIT (U(1) << 13) +#define SCTLR_RR_BIT (U(1) << 14) +#define SCTLR_NTWI_BIT (U(1) << 16) +#define SCTLR_NTWE_BIT (U(1) << 18) +#define SCTLR_WXN_BIT (U(1) << 19) +#define SCTLR_UWXN_BIT (U(1) << 20) +#define SCTLR_EE_BIT (U(1) << 25) +#define SCTLR_TRE_BIT (U(1) << 28) +#define SCTLR_AFE_BIT (U(1) << 29) +#define SCTLR_TE_BIT (U(1) << 30) + +/* HSCTLR definitions */ +#define HSCTLR_RES1 ((U(1) << 29) | (U(1) << 28) | (U(1) << 23) | \ + (U(1) << 22) | (U(1) << 18) | (U(1) << 16) | \ + (U(1) << 11) | (U(1) << 4) | (U(1) << 3) | \ + HSCTLR_CP15BEN_BIT) +#define HSCTLR_M_BIT (U(1) << 0) +#define HSCTLR_A_BIT (U(1) << 1) +#define HSCTLR_C_BIT (U(1) << 2) +#define HSCTLR_CP15BEN_BIT (U(1) << 5) +#define HSCTLR_ITD_BIT (U(1) << 7) +#define HSCTLR_SED_BIT (U(1) << 8) +#define HSCTLR_I_BIT (U(1) << 12) +#define HSCTLR_WXN_BIT (U(1) << 19) +#define HSCTLR_EE_BIT (U(1) << 25) +#define HSCTLR_TE_BIT (U(1) << 30) + +/* CPACR definitions */ +#define CPACR_FPEN(x) ((x) << 20) +#define CPACR_FP_TRAP_PL0 U(0x1) +#define CPACR_FP_TRAP_ALL U(0x2) +#define CPACR_FP_TRAP_NONE U(0x3) + +/* SCR definitions */ +#define SCR_TWE_BIT (U(1) << 13) +#define SCR_TWI_BIT (U(1) << 12) +#define SCR_SIF_BIT (U(1) << 9) +#define SCR_HCE_BIT (U(1) << 8) +#define SCR_SCD_BIT (U(1) << 7) +#define SCR_NET_BIT (U(1) << 6) +#define SCR_AW_BIT (U(1) << 5) +#define SCR_FW_BIT (U(1) << 4) +#define SCR_EA_BIT (U(1) << 3) +#define SCR_FIQ_BIT (U(1) << 2) +#define SCR_IRQ_BIT (U(1) << 1) +#define SCR_NS_BIT (U(1) << 0) +#define SCR_VALID_BIT_MASK U(0x33ff) +#define SCR_RESET_VAL U(0x0) + +#define GET_NS_BIT(scr) ((scr) & SCR_NS_BIT) + +/* HCR definitions */ +#define HCR_TGE_BIT (U(1) << 27) +#define HCR_AMO_BIT (U(1) << 5) +#define HCR_IMO_BIT (U(1) << 4) +#define HCR_FMO_BIT (U(1) << 3) +#define HCR_RESET_VAL U(0x0) + +/* CNTHCTL definitions */ +#define CNTHCTL_RESET_VAL U(0x0) +#define EVNTEN_BIT (U(1) << 2) +#define PL1PCEN_BIT (U(1) << 1) +#define PL1PCTEN_BIT (U(1) << 0) + +/* CNTKCTL definitions */ +#define PL0PTEN_BIT (U(1) << 9) +#define PL0VTEN_BIT (U(1) << 8) +#define PL0PCTEN_BIT (U(1) << 0) +#define PL0VCTEN_BIT (U(1) << 1) +#define EVNTEN_BIT (U(1) << 2) +#define EVNTDIR_BIT (U(1) << 3) +#define EVNTI_SHIFT U(4) +#define EVNTI_MASK U(0xf) + +/* HCPTR definitions */ +#define HCPTR_RES1 ((U(1) << 13) | (U(1) << 12) | U(0x3ff)) +#define TCPAC_BIT (U(1) << 31) +#define TAM_BIT (U(1) << 30) +#define TTA_BIT (U(1) << 20) +#define TCP11_BIT (U(1) << 11) +#define TCP10_BIT (U(1) << 10) +#define HCPTR_RESET_VAL HCPTR_RES1 + +/* NASCR definitions */ +#define NSASEDIS_BIT (U(1) << 15) +#define NSTRCDIS_BIT (U(1) << 20) +#define NSACR_CP11_BIT (U(1) << 11) +#define NSACR_CP10_BIT (U(1) << 10) +#define NSACR_IMP_DEF_MASK (U(0x7) << 16) +#define NSACR_ENABLE_FP_ACCESS (NSACR_CP11_BIT | NSACR_CP10_BIT) +#define NSACR_RESET_VAL U(0x0) + +/* CPACR definitions */ +#define ASEDIS_BIT (U(1) << 31) +#define TRCDIS_BIT (U(1) << 28) +#define CPACR_CP11_SHIFT U(22) +#define CPACR_CP10_SHIFT U(20) +#define CPACR_ENABLE_FP_ACCESS ((U(0x3) << CPACR_CP11_SHIFT) |\ + (U(0x3) << CPACR_CP10_SHIFT)) +#define CPACR_RESET_VAL U(0x0) + +/* FPEXC definitions */ +#define FPEXC_RES1 ((U(1) << 10) | (U(1) << 9) | (U(1) << 8)) +#define FPEXC_EN_BIT (U(1) << 30) +#define FPEXC_RESET_VAL FPEXC_RES1 + +/* SPSR/CPSR definitions */ +#define SPSR_FIQ_BIT (U(1) << 0) +#define SPSR_IRQ_BIT (U(1) << 1) +#define SPSR_ABT_BIT (U(1) << 2) +#define SPSR_AIF_SHIFT U(6) +#define SPSR_AIF_MASK U(0x7) + +#define SPSR_E_SHIFT U(9) +#define SPSR_E_MASK U(0x1) +#define SPSR_E_LITTLE U(0) +#define SPSR_E_BIG U(1) + +#define SPSR_T_SHIFT U(5) +#define SPSR_T_MASK U(0x1) +#define SPSR_T_ARM U(0) +#define SPSR_T_THUMB U(1) + +#define SPSR_MODE_SHIFT U(0) +#define SPSR_MODE_MASK U(0x7) + +#define DISABLE_ALL_EXCEPTIONS \ + (SPSR_FIQ_BIT | SPSR_IRQ_BIT | SPSR_ABT_BIT) + +/* + * TTBCR definitions + */ +/* The translation tables library uses the long descriptor format */ +#define TTBCR_EAE_BIT (U(1) << 31) + +#define TTBCR_SH1_NON_SHAREABLE (U(0x0) << 28) +#define TTBCR_SH1_OUTER_SHAREABLE (U(0x2) << 28) +#define TTBCR_SH1_INNER_SHAREABLE (U(0x3) << 28) + +#define TTBCR_RGN1_OUTER_NC (U(0x0) << 26) +#define TTBCR_RGN1_OUTER_WBA (U(0x1) << 26) +#define TTBCR_RGN1_OUTER_WT (U(0x2) << 26) +#define TTBCR_RGN1_OUTER_WBNA (U(0x3) << 26) + +#define TTBCR_RGN1_INNER_NC (U(0x0) << 24) +#define TTBCR_RGN1_INNER_WBA (U(0x1) << 24) +#define TTBCR_RGN1_INNER_WT (U(0x2) << 24) +#define TTBCR_RGN1_INNER_WBNA (U(0x3) << 24) + +#define TTBCR_EPD1_BIT (U(1) << 23) +#define TTBCR_A1_BIT (U(1) << 22) + +#define TTBCR_T1SZ_SHIFT U(16) +#define TTBCR_T1SZ_MASK U(0x7) +#define TTBCR_TxSZ_MIN U(0) +#define TTBCR_TxSZ_MAX U(7) + +#define TTBCR_SH0_NON_SHAREABLE (U(0x0) << 12) +#define TTBCR_SH0_OUTER_SHAREABLE (U(0x2) << 12) +#define TTBCR_SH0_INNER_SHAREABLE (U(0x3) << 12) + +#define TTBCR_RGN0_OUTER_NC (U(0x0) << 10) +#define TTBCR_RGN0_OUTER_WBA (U(0x1) << 10) +#define TTBCR_RGN0_OUTER_WT (U(0x2) << 10) +#define TTBCR_RGN0_OUTER_WBNA (U(0x3) << 10) + +#define TTBCR_RGN0_INNER_NC (U(0x0) << 8) +#define TTBCR_RGN0_INNER_WBA (U(0x1) << 8) +#define TTBCR_RGN0_INNER_WT (U(0x2) << 8) +#define TTBCR_RGN0_INNER_WBNA (U(0x3) << 8) + +#define TTBCR_EPD0_BIT (U(1) << 7) +#define TTBCR_T0SZ_SHIFT U(0) +#define TTBCR_T0SZ_MASK U(0x7) + +/* + * HTCR definitions + */ +#define HTCR_RES1 ((1 << 31) | (1 << 23)) + +#define HTCR_SH0_NON_SHAREABLE (0x0 << 12) +#define HTCR_SH0_OUTER_SHAREABLE (0x2 << 12) +#define HTCR_SH0_INNER_SHAREABLE (0x3 << 12) + +#define HTCR_RGN0_OUTER_NC (0x0 << 10) +#define HTCR_RGN0_OUTER_WBA (0x1 << 10) +#define HTCR_RGN0_OUTER_WT (0x2 << 10) +#define HTCR_RGN0_OUTER_WBNA (0x3 << 10) + +#define HTCR_RGN0_INNER_NC (0x0 << 8) +#define HTCR_RGN0_INNER_WBA (0x1 << 8) +#define HTCR_RGN0_INNER_WT (0x2 << 8) +#define HTCR_RGN0_INNER_WBNA (0x3 << 8) + +#define HTCR_T0SZ_SHIFT 0 +#define HTCR_T0SZ_MASK (0x7) + +#define MODE_RW_SHIFT U(0x4) +#define MODE_RW_MASK U(0x1) +#define MODE_RW_32 U(0x1) + +#define MODE32_SHIFT U(0) +#define MODE32_MASK U(0x1f) +#define MODE32_usr U(0x10) +#define MODE32_fiq U(0x11) +#define MODE32_irq U(0x12) +#define MODE32_svc U(0x13) +#define MODE32_mon U(0x16) +#define MODE32_abt U(0x17) +#define MODE32_hyp U(0x1a) +#define MODE32_und U(0x1b) +#define MODE32_sys U(0x1f) + +#define GET_M32(mode) (((mode) >> MODE32_SHIFT) & MODE32_MASK) + +#define SPSR_MODE32(mode, isa, endian, aif) \ + (MODE_RW_32 << MODE_RW_SHIFT | \ + ((mode) & MODE32_MASK) << MODE32_SHIFT | \ + ((isa) & SPSR_T_MASK) << SPSR_T_SHIFT | \ + ((endian) & SPSR_E_MASK) << SPSR_E_SHIFT | \ + ((aif) & SPSR_AIF_MASK) << SPSR_AIF_SHIFT) + +/* + * TTBR definitions + */ +#define TTBR_CNP_BIT U(0x1) + +/******************************************************************************* + * Definitions of register offsets, fields and macros for CPU system + * instructions. + ******************************************************************************/ + +#define TLBI_ADDR_SHIFT U(0) +#define TLBI_ADDR_MASK U(0xFFFFF000) +#define TLBI_ADDR(x) (((x) >> TLBI_ADDR_SHIFT) & TLBI_ADDR_MASK) + +/******************************************************************************* + * Definitions of register offsets and fields in the CNTBaseN Frame of the + * system level implementation of the Generic Timer. + ******************************************************************************/ +/* Physical Count register. */ +#define CNTPCT_LO 0x0 +/* Counter Frequency register. */ +#define CNTBASEN_CNTFRQ 0x10 +/* Physical Timer CompareValue register. */ +#define CNTP_CVAL_LO 0x20 +/* Physical Timer Control register. */ +#define CNTP_CTL 0x2c + +/* Physical timer control register bit fields shifts and masks */ +#define CNTP_CTL_ENABLE_SHIFT 0 +#define CNTP_CTL_IMASK_SHIFT 1 +#define CNTP_CTL_ISTATUS_SHIFT 2 + +#define CNTP_CTL_ENABLE_MASK 1 +#define CNTP_CTL_IMASK_MASK 1 +#define CNTP_CTL_ISTATUS_MASK 1 + +#define get_cntp_ctl_enable(x) ((x >> CNTP_CTL_ENABLE_SHIFT) & \ + CNTP_CTL_ENABLE_MASK) +#define get_cntp_ctl_imask(x) ((x >> CNTP_CTL_IMASK_SHIFT) & \ + CNTP_CTL_IMASK_MASK) +#define get_cntp_ctl_istatus(x) ((x >> CNTP_CTL_ISTATUS_SHIFT) & \ + CNTP_CTL_ISTATUS_MASK) + +#define set_cntp_ctl_enable(x) (x |= 1 << CNTP_CTL_ENABLE_SHIFT) +#define set_cntp_ctl_imask(x) (x |= 1 << CNTP_CTL_IMASK_SHIFT) + +#define clr_cntp_ctl_enable(x) (x &= ~(1 << CNTP_CTL_ENABLE_SHIFT)) +#define clr_cntp_ctl_imask(x) (x &= ~(1 << CNTP_CTL_IMASK_SHIFT)) + +/* MAIR macros */ +#define MAIR0_ATTR_SET(attr, index) ((attr) << ((index) << U(3))) +#define MAIR1_ATTR_SET(attr, index) ((attr) << (((index) - U(3)) << U(3))) + +/* System register defines The format is: coproc, opt1, CRn, CRm, opt2 */ +#define SCR p15, 0, c1, c1, 0 +#define SCTLR p15, 0, c1, c0, 0 +#define MPIDR p15, 0, c0, c0, 5 +#define MIDR p15, 0, c0, c0, 0 +#define HVBAR p15, 4, c12, c0, 0 +#define VBAR p15, 0, c12, c0, 0 +#define MVBAR p15, 0, c12, c0, 1 +#define NSACR p15, 0, c1, c1, 2 +#define CPACR p15, 0, c1, c0, 2 +#define DCCIMVAC p15, 0, c7, c14, 1 +#define DCCMVAC p15, 0, c7, c10, 1 +#define DCIMVAC p15, 0, c7, c6, 1 +#define DCCISW p15, 0, c7, c14, 2 +#define DCCSW p15, 0, c7, c10, 2 +#define DCISW p15, 0, c7, c6, 2 +#define CTR p15, 0, c0, c0, 1 +#define CNTFRQ p15, 0, c14, c0, 0 +#define ID_PFR0 p15, 0, c0, c1, 0 +#define ID_PFR1 p15, 0, c0, c1, 1 +#define MAIR0 p15, 0, c10, c2, 0 +#define MAIR1 p15, 0, c10, c2, 1 +#define TTBCR p15, 0, c2, c0, 2 +#define TTBR0 p15, 0, c2, c0, 0 +#define TTBR1 p15, 0, c2, c0, 1 +#define TLBIALL p15, 0, c8, c7, 0 +#define TLBIALLH p15, 4, c8, c7, 0 +#define TLBIALLIS p15, 0, c8, c3, 0 +#define TLBIMVA p15, 0, c8, c7, 1 +#define TLBIMVAA p15, 0, c8, c7, 3 +#define TLBIMVAAIS p15, 0, c8, c3, 3 +#define TLBIMVAHIS p15, 4, c8, c3, 1 +#define BPIALLIS p15, 0, c7, c1, 6 +#define BPIALL p15, 0, c7, c5, 6 +#define HSCTLR p15, 4, c1, c0, 0 +#define HCR p15, 4, c1, c1, 0 +#define HCPTR p15, 4, c1, c1, 2 +#define CNTHCTL p15, 4, c14, c1, 0 +#define VPIDR p15, 4, c0, c0, 0 +#define VMPIDR p15, 4, c0, c0, 5 +#define ISR p15, 0, c12, c1, 0 +#define CLIDR p15, 1, c0, c0, 1 +#define CSSELR p15, 2, c0, c0, 0 +#define CCSIDR p15, 1, c0, c0, 0 +#define HTCR p15, 4, c2, c0, 2 +#define HMAIR0 p15, 4, c10, c2, 0 +#define CNTHP_CTL p15, 4, c14, c2, 1 +#define CNTHP_TVAL p15, 4, c14, c2, 0 + +/* GICv3 CPU Interface system register defines. The format is: coproc, opt1, CRn, CRm, opt2 */ +#define ICC_IAR1 p15, 0, c12, c12, 0 +#define ICC_IAR0 p15, 0, c12, c8, 0 +#define ICC_EOIR1 p15, 0, c12, c12, 1 +#define ICC_EOIR0 p15, 0, c12, c8, 1 +#define ICC_HPPIR1 p15, 0, c12, c12, 2 +#define ICC_HPPIR0 p15, 0, c12, c8, 2 +#define ICC_BPR1 p15, 0, c12, c12, 3 +#define ICC_BPR0 p15, 0, c12, c8, 3 +#define ICC_DIR p15, 0, c12, c11, 1 +#define ICC_PMR p15, 0, c4, c6, 0 +#define ICC_RPR p15, 0, c12, c11, 3 +#define ICC_CTLR p15, 0, c12, c12, 4 +#define ICC_MCTLR p15, 6, c12, c12, 4 +#define ICC_SRE p15, 0, c12, c12, 5 +#define ICC_HSRE p15, 4, c12, c9, 5 +#define ICC_MSRE p15, 6, c12, c12, 5 +#define ICC_IGRPEN0 p15, 0, c12, c12, 6 +#define ICC_IGRPEN1 p15, 0, c12, c12, 7 +#define ICC_MGRPEN1 p15, 6, c12, c12, 7 + +/* 64 bit system register defines The format is: coproc, opt1, CRm */ +#define TTBR0_64 p15, 0, c2 +#define TTBR1_64 p15, 1, c2 +#define CNTVOFF_64 p15, 4, c14 +#define VTTBR_64 p15, 6, c2 +#define CNTPCT_64 p15, 0, c14 +#define HTTBR_64 p15, 4, c2 +#define CNTHP_CVAL_64 p15, 6, c14 + +/* 64 bit GICv3 CPU Interface system register defines. The format is: coproc, opt1, CRm */ +#define ICC_SGI1R_EL1_64 p15, 0, c12 +#define ICC_ASGI1R_EL1_64 p15, 1, c12 +#define ICC_SGI0R_EL1_64 p15, 2, c12 + +/******************************************************************************* + * Definitions of MAIR encodings for device and normal memory + ******************************************************************************/ +/* + * MAIR encodings for device memory attributes. + */ +#define MAIR_DEV_nGnRnE U(0x0) +#define MAIR_DEV_nGnRE U(0x4) +#define MAIR_DEV_nGRE U(0x8) +#define MAIR_DEV_GRE U(0xc) + +/* + * MAIR encodings for normal memory attributes. + * + * Cache Policy + * WT: Write Through + * WB: Write Back + * NC: Non-Cacheable + * + * Transient Hint + * NTR: Non-Transient + * TR: Transient + * + * Allocation Policy + * RA: Read Allocate + * WA: Write Allocate + * RWA: Read and Write Allocate + * NA: No Allocation + */ +#define MAIR_NORM_WT_TR_WA U(0x1) +#define MAIR_NORM_WT_TR_RA U(0x2) +#define MAIR_NORM_WT_TR_RWA U(0x3) +#define MAIR_NORM_NC U(0x4) +#define MAIR_NORM_WB_TR_WA U(0x5) +#define MAIR_NORM_WB_TR_RA U(0x6) +#define MAIR_NORM_WB_TR_RWA U(0x7) +#define MAIR_NORM_WT_NTR_NA U(0x8) +#define MAIR_NORM_WT_NTR_WA U(0x9) +#define MAIR_NORM_WT_NTR_RA U(0xa) +#define MAIR_NORM_WT_NTR_RWA U(0xb) +#define MAIR_NORM_WB_NTR_NA U(0xc) +#define MAIR_NORM_WB_NTR_WA U(0xd) +#define MAIR_NORM_WB_NTR_RA U(0xe) +#define MAIR_NORM_WB_NTR_RWA U(0xf) + +#define MAIR_NORM_OUTER_SHIFT U(4) + +#define MAKE_MAIR_NORMAL_MEMORY(inner, outer) \ + ((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT)) + +/******************************************************************************* + * Definitions for system register interface to AMU for ARMv8.4 onwards + ******************************************************************************/ +#define AMCR p15, 0, c13, c2, 0 +#define AMCFGR p15, 0, c13, c2, 1 +#define AMCGCR p15, 0, c13, c2, 2 +#define AMUSERENR p15, 0, c13, c2, 3 +#define AMCNTENCLR0 p15, 0, c13, c2, 4 +#define AMCNTENSET0 p15, 0, c13, c2, 5 +#define AMCNTENCLR1 p15, 0, c13, c3, 0 +#define AMCNTENSET1 p15, 0, c13, c3, 1 + +/* Activity Monitor Group 0 Event Counter Registers */ +#define AMEVCNTR00 p15, 0, c0 +#define AMEVCNTR01 p15, 1, c0 +#define AMEVCNTR02 p15, 2, c0 +#define AMEVCNTR03 p15, 3, c0 + +/* Activity Monitor Group 0 Event Type Registers */ +#define AMEVTYPER00 p15, 0, c13, c6, 0 +#define AMEVTYPER01 p15, 0, c13, c6, 1 +#define AMEVTYPER02 p15, 0, c13, c6, 2 +#define AMEVTYPER03 p15, 0, c13, c6, 3 + +/* Activity Monitor Group 1 Event Counter Registers */ +#define AMEVCNTR10 p15, 0, c4 +#define AMEVCNTR11 p15, 1, c4 +#define AMEVCNTR12 p15, 2, c4 +#define AMEVCNTR13 p15, 3, c4 +#define AMEVCNTR14 p15, 4, c4 +#define AMEVCNTR15 p15, 5, c4 +#define AMEVCNTR16 p15, 6, c4 +#define AMEVCNTR17 p15, 7, c4 +#define AMEVCNTR18 p15, 0, c5 +#define AMEVCNTR19 p15, 1, c5 +#define AMEVCNTR1A p15, 2, c5 +#define AMEVCNTR1B p15, 3, c5 +#define AMEVCNTR1C p15, 4, c5 +#define AMEVCNTR1D p15, 5, c5 +#define AMEVCNTR1E p15, 6, c5 +#define AMEVCNTR1F p15, 7, c5 + +/* Activity Monitor Group 1 Event Type Registers */ +#define AMEVTYPER10 p15, 0, c13, c14, 0 +#define AMEVTYPER11 p15, 0, c13, c14, 1 +#define AMEVTYPER12 p15, 0, c13, c14, 2 +#define AMEVTYPER13 p15, 0, c13, c14, 3 +#define AMEVTYPER14 p15, 0, c13, c14, 4 +#define AMEVTYPER15 p15, 0, c13, c14, 5 +#define AMEVTYPER16 p15, 0, c13, c14, 6 +#define AMEVTYPER17 p15, 0, c13, c14, 7 +#define AMEVTYPER18 p15, 0, c13, c15, 0 +#define AMEVTYPER19 p15, 0, c13, c15, 1 +#define AMEVTYPER1A p15, 0, c13, c15, 2 +#define AMEVTYPER1B p15, 0, c13, c15, 3 +#define AMEVTYPER1C p15, 0, c13, c15, 4 +#define AMEVTYPER1D p15, 0, c13, c15, 5 +#define AMEVTYPER1E p15, 0, c13, c15, 6 +#define AMEVTYPER1F p15, 0, c13, c15, 7 + +#endif /* __ARCH_H__ */ diff --git a/include/lib/aarch32/arch_helpers.h b/include/lib/aarch32/arch_helpers.h new file mode 100644 index 000000000..7991711ff --- /dev/null +++ b/include/lib/aarch32/arch_helpers.h @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __ARCH_HELPERS_H__ +#define __ARCH_HELPERS_H__ + +#include <arch.h> /* for additional register definitions */ +#include <misc_utils.h> +#include <stdint.h> +#include <types.h> + +/********************************************************************** + * Macros which create inline functions to read or write CPU system + * registers + *********************************************************************/ + +#define _DEFINE_COPROCR_WRITE_FUNC(_name, coproc, opc1, CRn, CRm, opc2) \ +static inline void write_## _name(u_register_t v) \ +{ \ + __asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\ +} + +#define _DEFINE_COPROCR_READ_FUNC(_name, coproc, opc1, CRn, CRm, opc2) \ +static inline u_register_t read_ ## _name(void) \ +{ \ + u_register_t v; \ + __asm__ volatile ("mrc "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : "=r" (v));\ + return v; \ +} + +/* + * The undocumented %Q and %R extended asm are used to implemented the below + * 64 bit `mrrc` and `mcrr` instructions. + */ + +#define _DEFINE_COPROCR_WRITE_FUNC_64(_name, coproc, opc1, CRm) \ +static inline void write64_## _name(uint64_t v) \ +{ \ + __asm__ volatile ("mcrr "#coproc","#opc1", %Q0, %R0,"#CRm : : "r" (v));\ +} + +#define _DEFINE_COPROCR_READ_FUNC_64(_name, coproc, opc1, CRm) \ +static inline uint64_t read64_## _name(void) \ +{ uint64_t v; \ + __asm__ volatile ("mrrc "#coproc","#opc1", %Q0, %R0,"#CRm : "=r" (v));\ + return v; \ +} + +#define _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \ +static inline u_register_t read_ ## _name(void) \ +{ \ + u_register_t v; \ + __asm__ volatile ("mrs %0, " #_reg_name : "=r" (v)); \ + return v; \ +} + +#define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) \ +static inline void write_ ## _name(u_register_t v) \ +{ \ + __asm__ volatile ("msr " #_reg_name ", %0" : : "r" (v)); \ +} + +#define _DEFINE_SYSREG_WRITE_CONST_FUNC(_name, _reg_name) \ +static inline void write_ ## _name(const u_register_t v) \ +{ \ + __asm__ volatile ("msr " #_reg_name ", %0" : : "i" (v)); \ +} + +/* Define read function for coproc register */ +#define DEFINE_COPROCR_READ_FUNC(_name, ...) \ + _DEFINE_COPROCR_READ_FUNC(_name, __VA_ARGS__) + +/* Define read & write function for coproc register */ +#define DEFINE_COPROCR_RW_FUNCS(_name, ...) \ + _DEFINE_COPROCR_READ_FUNC(_name, __VA_ARGS__) \ + _DEFINE_COPROCR_WRITE_FUNC(_name, __VA_ARGS__) + +/* Define 64 bit read function for coproc register */ +#define DEFINE_COPROCR_READ_FUNC_64(_name, ...) \ + _DEFINE_COPROCR_READ_FUNC_64(_name, __VA_ARGS__) + +/* Define 64 bit write function for coproc register */ +#define DEFINE_COPROCR_WRITE_FUNC_64(_name, ...) \ + _DEFINE_COPROCR_WRITE_FUNC_64(_name, __VA_ARGS__) + +/* Define 64 bit read & write function for coproc register */ +#define DEFINE_COPROCR_RW_FUNCS_64(_name, ...) \ + _DEFINE_COPROCR_READ_FUNC_64(_name, __VA_ARGS__) \ + _DEFINE_COPROCR_WRITE_FUNC_64(_name, __VA_ARGS__) + +/* Define read & write function for system register */ +#define DEFINE_SYSREG_RW_FUNCS(_name) \ + _DEFINE_SYSREG_READ_FUNC(_name, _name) \ + _DEFINE_SYSREG_WRITE_FUNC(_name, _name) + +/********************************************************************** + * Macros to create inline functions for tlbi operations + *********************************************************************/ + +#define _DEFINE_TLBIOP_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \ +static inline void tlbi##_op(void) \ +{ \ + u_register_t v = 0; \ + __asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\ +} + +#define _DEFINE_TLBIOP_PARAM_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \ +static inline void tlbi##_op(u_register_t v) \ +{ \ + __asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\ +} + +#define _DEFINE_BPIOP_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \ +static inline void bpi##_op(void) \ +{ \ + u_register_t v = 0; \ + __asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\ +} + +/* Define function for simple TLBI operation */ +#define DEFINE_TLBIOP_FUNC(_op, ...) \ + _DEFINE_TLBIOP_FUNC(_op, __VA_ARGS__) + +/* Define function for TLBI operation with register parameter */ +#define DEFINE_TLBIOP_PARAM_FUNC(_op, ...) \ + _DEFINE_TLBIOP_PARAM_FUNC(_op, __VA_ARGS__) + +/* Define function for simple BPI operation */ +#define DEFINE_BPIOP_FUNC(_op, ...) \ + _DEFINE_BPIOP_FUNC(_op, __VA_ARGS__) + +/********************************************************************** + * Macros to create inline functions for DC operations + *********************************************************************/ +#define _DEFINE_DCOP_PARAM_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \ +static inline void dc##_op(u_register_t v) \ +{ \ + __asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\ +} + +/* Define function for DC operation with register parameter */ +#define DEFINE_DCOP_PARAM_FUNC(_op, ...) \ + _DEFINE_DCOP_PARAM_FUNC(_op, __VA_ARGS__) + +/********************************************************************** + * Macros to create inline functions for system instructions + *********************************************************************/ + /* Define function for simple system instruction */ +#define DEFINE_SYSOP_FUNC(_op) \ +static inline void _op(void) \ +{ \ + __asm__ (#_op); \ +} + + +/* Define function for system instruction with type specifier */ +#define DEFINE_SYSOP_TYPE_FUNC(_op, _type) \ +static inline void _op ## _type(void) \ +{ \ + __asm__ (#_op " " #_type); \ +} + +/* Define function for system instruction with register parameter */ +#define DEFINE_SYSOP_TYPE_PARAM_FUNC(_op, _type) \ +static inline void _op ## _type(u_register_t v) \ +{ \ + __asm__ (#_op " " #_type ", %0" : : "r" (v)); \ +} + +void flush_dcache_range(uintptr_t addr, size_t size); +void clean_dcache_range(uintptr_t addr, size_t size); +void inv_dcache_range(uintptr_t addr, size_t size); + +void dcsw_op_louis(u_register_t op_type); +void dcsw_op_all(u_register_t op_type); + +DEFINE_SYSOP_FUNC(wfi) +DEFINE_SYSOP_FUNC(wfe) +DEFINE_SYSOP_FUNC(sev) +DEFINE_SYSOP_TYPE_FUNC(dsb, sy) +DEFINE_SYSOP_TYPE_FUNC(dmb, sy) +DEFINE_SYSOP_TYPE_FUNC(dsb, ish) +DEFINE_SYSOP_TYPE_FUNC(dsb, ishst) +DEFINE_SYSOP_TYPE_FUNC(dmb, ish) +DEFINE_SYSOP_TYPE_FUNC(dmb, ishst) +DEFINE_SYSOP_FUNC(isb) + +DEFINE_SYSREG_RW_FUNCS(spsr) +DEFINE_SYSREG_RW_FUNCS(cpsr) + +/******************************************************************************* + * System register accessor prototypes + ******************************************************************************/ +DEFINE_COPROCR_READ_FUNC(mpidr, MPIDR) +DEFINE_COPROCR_READ_FUNC(midr, MIDR) +DEFINE_COPROCR_READ_FUNC(id_pfr0, ID_PFR0) +DEFINE_COPROCR_READ_FUNC(id_pfr1, ID_PFR1) +DEFINE_COPROCR_READ_FUNC(isr, ISR) +DEFINE_COPROCR_READ_FUNC(clidr, CLIDR) +DEFINE_COPROCR_READ_FUNC_64(cntpct, CNTPCT_64) + +DEFINE_COPROCR_RW_FUNCS(scr, SCR) +DEFINE_COPROCR_RW_FUNCS(sctlr, SCTLR) +DEFINE_COPROCR_RW_FUNCS(hsctlr, HSCTLR) +DEFINE_COPROCR_RW_FUNCS(hcr, HCR) +DEFINE_COPROCR_RW_FUNCS(hcptr, HCPTR) +DEFINE_COPROCR_RW_FUNCS(cntfrq, CNTFRQ) +DEFINE_COPROCR_RW_FUNCS(cnthctl, CNTHCTL) +DEFINE_COPROCR_RW_FUNCS(mair0, MAIR0) +DEFINE_COPROCR_RW_FUNCS(mair1, MAIR1) +DEFINE_COPROCR_RW_FUNCS(hmair0, HMAIR0) +DEFINE_COPROCR_RW_FUNCS(ttbcr, TTBCR) +DEFINE_COPROCR_RW_FUNCS(htcr, HTCR) +DEFINE_COPROCR_RW_FUNCS(ttbr0, TTBR0) +DEFINE_COPROCR_RW_FUNCS_64(ttbr0, TTBR0_64) +DEFINE_COPROCR_RW_FUNCS(ttbr1, TTBR1) +DEFINE_COPROCR_RW_FUNCS_64(httbr, HTTBR_64) +DEFINE_COPROCR_RW_FUNCS(vpidr, VPIDR) +DEFINE_COPROCR_RW_FUNCS(vmpidr, VMPIDR) +DEFINE_COPROCR_RW_FUNCS_64(vttbr, VTTBR_64) +DEFINE_COPROCR_RW_FUNCS_64(ttbr1, TTBR1_64) +DEFINE_COPROCR_RW_FUNCS_64(cntvoff, CNTVOFF_64) +DEFINE_COPROCR_RW_FUNCS(csselr, CSSELR) +DEFINE_COPROCR_RW_FUNCS(cnthp_ctl_el2, CNTHP_CTL) +DEFINE_COPROCR_RW_FUNCS(cnthp_tval_el2, CNTHP_TVAL) +DEFINE_COPROCR_RW_FUNCS_64(cnthp_cval_el2, CNTHP_CVAL_64) + +DEFINE_COPROCR_RW_FUNCS(icc_sre_el1, ICC_SRE) +DEFINE_COPROCR_RW_FUNCS(icc_sre_el2, ICC_HSRE) +DEFINE_COPROCR_RW_FUNCS(icc_sre_el3, ICC_MSRE) +DEFINE_COPROCR_RW_FUNCS(icc_pmr_el1, ICC_PMR) +DEFINE_COPROCR_RW_FUNCS(icc_igrpen1_el3, ICC_MGRPEN1) +DEFINE_COPROCR_RW_FUNCS(icc_igrpen1_el1, ICC_IGRPEN1) +DEFINE_COPROCR_RW_FUNCS(icc_igrpen0_el1, ICC_IGRPEN0) +DEFINE_COPROCR_RW_FUNCS(icc_hppir0_el1, ICC_HPPIR0) +DEFINE_COPROCR_RW_FUNCS(icc_hppir1_el1, ICC_HPPIR1) +DEFINE_COPROCR_RW_FUNCS(icc_iar0_el1, ICC_IAR0) +DEFINE_COPROCR_RW_FUNCS(icc_iar1_el1, ICC_IAR1) +DEFINE_COPROCR_RW_FUNCS(icc_eoir0_el1, ICC_EOIR0) +DEFINE_COPROCR_RW_FUNCS(icc_eoir1_el1, ICC_EOIR1) +DEFINE_COPROCR_WRITE_FUNC_64(icc_sgi1r, ICC_SGI1R_EL1_64) + +DEFINE_COPROCR_RW_FUNCS(amcntenset0, AMCNTENSET0) +DEFINE_COPROCR_RW_FUNCS(amcntenset1, AMCNTENSET1) +DEFINE_COPROCR_RW_FUNCS(amcntenclr0, AMCNTENCLR0) +DEFINE_COPROCR_RW_FUNCS(amcntenclr1, AMCNTENCLR1) + +DEFINE_COPROCR_RW_FUNCS_64(amevcntr00, AMEVCNTR00) +DEFINE_COPROCR_RW_FUNCS_64(amevcntr01, AMEVCNTR01) +DEFINE_COPROCR_RW_FUNCS_64(amevcntr02, AMEVCNTR02) +DEFINE_COPROCR_RW_FUNCS_64(amevcntr03, AMEVCNTR03) + +/* + * TLBI operation prototypes + */ +DEFINE_TLBIOP_FUNC(all, TLBIALL) +DEFINE_TLBIOP_FUNC(allis, TLBIALLIS) +DEFINE_TLBIOP_PARAM_FUNC(mva, TLBIMVA) +DEFINE_TLBIOP_PARAM_FUNC(mvaa, TLBIMVAA) +DEFINE_TLBIOP_PARAM_FUNC(mvaais, TLBIMVAAIS) +DEFINE_TLBIOP_PARAM_FUNC(mvahis, TLBIMVAHIS) + +/* + * BPI operation prototypes. + */ +DEFINE_BPIOP_FUNC(allis, BPIALLIS) + +/* + * DC operation prototypes + */ +DEFINE_DCOP_PARAM_FUNC(civac, DCCIMVAC) +DEFINE_DCOP_PARAM_FUNC(ivac, DCIMVAC) +DEFINE_DCOP_PARAM_FUNC(cvac, DCCMVAC) + +/* Helper functions to manipulate CPSR */ +static inline void enable_irq(void) +{ + /* + * The compiler memory barrier will prevent the compiler from + * scheduling non-volatile memory access after the write to the + * register. + * + * This could happen if some initialization code issues non-volatile + * accesses to an area used by an interrupt handler, in the assumption + * that it is safe as the interrupts are disabled at the time it does + * that (according to program order). However, non-volatile accesses + * are not necessarily in program order relatively with volatile inline + * assembly statements (and volatile accesses). + */ + COMPILER_BARRIER(); + __asm__ volatile ("cpsie i"); + isb(); +} + +static inline void enable_serror(void) +{ + COMPILER_BARRIER(); + __asm__ volatile ("cpsie a"); + isb(); +} + +static inline void enable_fiq(void) +{ + COMPILER_BARRIER(); + __asm__ volatile ("cpsie f"); + isb(); +} + +static inline void disable_irq(void) +{ + COMPILER_BARRIER(); + __asm__ volatile ("cpsid i"); + isb(); +} + +static inline void disable_serror(void) +{ + COMPILER_BARRIER(); + __asm__ volatile ("cpsid a"); + isb(); +} + +static inline void disable_fiq(void) +{ + COMPILER_BARRIER(); + __asm__ volatile ("cpsid f"); + isb(); +} + +/* Previously defined accessor functions with incomplete register names */ +#define dsb() dsbsy() + +/* + * Helper function to detect the processor mode. + */ +#define IS_IN_HYP() (GET_M32(read_cpsr()) == MODE32_hyp) +#define IS_IN_SVC() (GET_M32(read_cpsr()) == MODE32_svc) +#define IS_IN_MON() (GET_M32(read_cpsr()) == MODE32_mon) +#define IS_IN_EL2() IS_IN_HYP() + +/* Accessor functions defined for compatibility with AArch32 register names */ + +#define read_mpidr_el1() read_mpidr() +#define read_daif() read_cpsr() +#define write_daif(flags) write_cpsr(flags) +#define read_cntfrq_el0() read_cntfrq() +#define read_cntpct_el0() read64_cntpct() +#define read_cnthp_cval_el2() read64_cnthp_cval_el2() +#define write_cnthp_cval_el2(v) write64_cnthp_cval_el2(v) +#define read_amcntenset0_el0() read_amcntenset0() +#define read_amcntenset1_el0() read_amcntenset1() + +void disable_mmu_icache(void); + +#endif /* __ARCH_HELPERS_H__ */ diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h new file mode 100644 index 000000000..215730dfd --- /dev/null +++ b/include/lib/aarch64/arch.h @@ -0,0 +1,621 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __ARCH_H__ +#define __ARCH_H__ + +#include <utils_def.h> + +/******************************************************************************* + * MIDR bit definitions + ******************************************************************************/ +#define MIDR_IMPL_MASK U(0xff) +#define MIDR_IMPL_SHIFT U(0x18) +#define MIDR_VAR_SHIFT U(20) +#define MIDR_VAR_BITS U(4) +#define MIDR_VAR_MASK U(0xf) +#define MIDR_REV_SHIFT U(0) +#define MIDR_REV_BITS U(4) +#define MIDR_REV_MASK U(0xf) +#define MIDR_PN_MASK U(0xfff) +#define MIDR_PN_SHIFT U(0x4) + +/******************************************************************************* + * MPIDR macros + ******************************************************************************/ +#define MPIDR_MT_MASK (ULL(1) << 24) +#define MPIDR_CPU_MASK MPIDR_AFFLVL_MASK +#define MPIDR_CLUSTER_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS) +#define MPIDR_AFFINITY_BITS U(8) +#define MPIDR_AFFLVL_MASK ULL(0xff) +#define MPIDR_AFF0_SHIFT U(0) +#define MPIDR_AFF1_SHIFT U(8) +#define MPIDR_AFF2_SHIFT U(16) +#define MPIDR_AFF3_SHIFT U(32) +#define MPIDR_AFF_SHIFT(_n) MPIDR_AFF##_n##_SHIFT +#define MPIDR_AFFINITY_MASK ULL(0xff00ffffff) +#define MPIDR_AFFLVL_SHIFT U(3) +#define MPIDR_AFFLVL0 ULL(0x0) +#define MPIDR_AFFLVL1 ULL(0x1) +#define MPIDR_AFFLVL2 ULL(0x2) +#define MPIDR_AFFLVL3 ULL(0x3) +#define MPIDR_AFFLVL(_n) MPIDR_AFFLVL##_n +#define MPIDR_AFFLVL0_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK) +#define MPIDR_AFFLVL1_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK) +#define MPIDR_AFFLVL2_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK) +#define MPIDR_AFFLVL3_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF3_SHIFT) & MPIDR_AFFLVL_MASK) +/* + * The MPIDR_MAX_AFFLVL count starts from 0. Take care to + * add one while using this macro to define array sizes. + * TODO: Support only the first 3 affinity levels for now. + */ +#define MPIDR_MAX_AFFLVL U(2) + +/* Constant to highlight the assumption that MPIDR allocation starts from 0 */ +#define FIRST_MPIDR ULL(0) + +#define MPID_MASK (MPIDR_MT_MASK |\ + (MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT)|\ + (MPIDR_AFFLVL_MASK << MPIDR_AFF1_SHIFT)|\ + (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) + +#define MPIDR_AFF_ID(mpid, n) \ + (((mpid) >> MPIDR_AFF_SHIFT(n)) & MPIDR_AFFLVL_MASK) + +#define MPIDR_CLUSTER_ID(mpid) MPIDR_AFF_ID(mpid, 1) +#define MPIDR_CPU_ID(mpid) MPIDR_AFF_ID(mpid, 0) + +/* + * An invalid MPID. This value can be used by functions that return an MPID to + * indicate an error. + */ +#define INVALID_MPID 0xFFFFFFFF + +/******************************************************************************* + * Definitions for CPU system register interface to GICv3 + ******************************************************************************/ +#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7 +#define ICC_SGI1R S3_0_C12_C11_5 +#define ICC_SRE_EL1 S3_0_C12_C12_5 +#define ICC_SRE_EL2 S3_4_C12_C9_5 +#define ICC_SRE_EL3 S3_6_C12_C12_5 +#define ICC_CTLR_EL1 S3_0_C12_C12_4 +#define ICC_CTLR_EL3 S3_6_C12_C12_4 +#define ICC_PMR_EL1 S3_0_C4_C6_0 +#define ICC_RPR_EL1 S3_0_C12_C11_3 +#define ICC_IGRPEN1_EL3 S3_6_c12_c12_7 +#define ICC_IGRPEN0_EL1 S3_0_c12_c12_6 +#define ICC_HPPIR0_EL1 S3_0_c12_c8_2 +#define ICC_HPPIR1_EL1 S3_0_c12_c12_2 +#define ICC_IAR0_EL1 S3_0_c12_c8_0 +#define ICC_IAR1_EL1 S3_0_c12_c12_0 +#define ICC_EOIR0_EL1 S3_0_c12_c8_1 +#define ICC_EOIR1_EL1 S3_0_c12_c12_1 +#define ICC_SGI0R_EL1 S3_0_c12_c11_7 + +/******************************************************************************* + * Generic timer memory mapped registers & offsets + ******************************************************************************/ +#define CNTCR_OFF U(0x000) +#define CNTFID_OFF U(0x020) + +#define CNTCR_EN (U(1) << 0) +#define CNTCR_HDBG (U(1) << 1) +#define CNTCR_FCREQ(x) ((x) << 8) + +/******************************************************************************* + * System register bit definitions + ******************************************************************************/ +/* CLIDR definitions */ +#define LOUIS_SHIFT U(21) +#define LOC_SHIFT U(24) +#define CLIDR_FIELD_WIDTH U(3) + +/* CSSELR definitions */ +#define LEVEL_SHIFT U(1) + +/* Data cache set/way op type defines */ +#define DCISW U(0x0) +#define DCCISW U(0x1) +#define DCCSW U(0x2) + +/* ID_AA64PFR0_EL1 definitions */ +#define ID_AA64PFR0_EL0_SHIFT U(0) +#define ID_AA64PFR0_EL1_SHIFT U(4) +#define ID_AA64PFR0_EL2_SHIFT U(8) +#define ID_AA64PFR0_EL3_SHIFT U(12) +#define ID_AA64PFR0_AMU_SHIFT U(44) +#define ID_AA64PFR0_AMU_LENGTH U(4) +#define ID_AA64PFR0_AMU_MASK ULL(0xf) +#define ID_AA64PFR0_ELX_MASK ULL(0xf) +#define ID_AA64PFR0_SVE_SHIFT U(32) +#define ID_AA64PFR0_SVE_MASK ULL(0xf) +#define ID_AA64PFR0_SVE_LENGTH U(4) +#define ID_AA64PFR0_CSV2_SHIFT U(56) +#define ID_AA64PFR0_CSV2_MASK ULL(0xf) +#define ID_AA64PFR0_CSV2_LENGTH U(4) + +/* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */ +#define ID_AA64DFR0_PMS_SHIFT U(32) +#define ID_AA64DFR0_PMS_LENGTH U(4) +#define ID_AA64DFR0_PMS_MASK ULL(0xf) + +#define EL_IMPL_NONE ULL(0) +#define EL_IMPL_A64ONLY ULL(1) +#define EL_IMPL_A64_A32 ULL(2) + +#define ID_AA64PFR0_GIC_SHIFT U(24) +#define ID_AA64PFR0_GIC_WIDTH U(4) +#define ID_AA64PFR0_GIC_MASK ((ULL(1) << ID_AA64PFR0_GIC_WIDTH) - ULL(1)) + +/* ID_AA64MMFR0_EL1 definitions */ +#define ID_AA64MMFR0_EL1_PARANGE_SHIFT U(0) +#define ID_AA64MMFR0_EL1_PARANGE_MASK ULL(0xf) + +#define PARANGE_0000 U(32) +#define PARANGE_0001 U(36) +#define PARANGE_0010 U(40) +#define PARANGE_0011 U(42) +#define PARANGE_0100 U(44) +#define PARANGE_0101 U(48) +#define PARANGE_0110 U(52) + +#define ID_AA64MMFR0_EL1_TGRAN4_SHIFT U(28) +#define ID_AA64MMFR0_EL1_TGRAN4_MASK ULL(0xf) +#define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED ULL(0x0) +#define ID_AA64MMFR0_EL1_TGRAN4_NOT_SUPPORTED ULL(0xf) + +#define ID_AA64MMFR0_EL1_TGRAN64_SHIFT U(24) +#define ID_AA64MMFR0_EL1_TGRAN64_MASK ULL(0xf) +#define ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED ULL(0x0) +#define ID_AA64MMFR0_EL1_TGRAN64_NOT_SUPPORTED ULL(0xf) + +#define ID_AA64MMFR0_EL1_TGRAN16_SHIFT U(20) +#define ID_AA64MMFR0_EL1_TGRAN16_MASK ULL(0xf) +#define ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED ULL(0x1) +#define ID_AA64MMFR0_EL1_TGRAN16_NOT_SUPPORTED ULL(0x0) + +/* SCTLR definitions */ +#define SCTLR_EL2_RES1 ((U(1) << 29) | (U(1) << 28) | (U(1) << 23) | \ + (U(1) << 22) | (U(1) << 18) | (U(1) << 16) | \ + (U(1) << 11) | (U(1) << 5) | (U(1) << 4)) + +#define SCTLR_EL1_RES1 ((U(1) << 29) | (U(1) << 28) | (U(1) << 23) | \ + (U(1) << 22) | (U(1) << 20) | (U(1) << 11)) + +#define SCTLR_M_BIT (U(1) << 0) +#define SCTLR_A_BIT (U(1) << 1) +#define SCTLR_C_BIT (U(1) << 2) +#define SCTLR_SA_BIT (U(1) << 3) +#define SCTLR_SA0_BIT (U(1) << 4) +#define SCTLR_CP15BEN_BIT (U(1) << 5) +#define SCTLR_ITD_BIT (U(1) << 7) +#define SCTLR_SED_BIT (U(1) << 8) +#define SCTLR_UMA_BIT (U(1) << 9) +#define SCTLR_I_BIT (U(1) << 12) +#define SCTLR_V_BIT (U(1) << 13) +#define SCTLR_DZE_BIT (U(1) << 14) +#define SCTLR_UCT_BIT (U(1) << 15) +#define SCTLR_NTWI_BIT (U(1) << 16) +#define SCTLR_NTWE_BIT (U(1) << 18) +#define SCTLR_WXN_BIT (U(1) << 19) +#define SCTLR_UWXN_BIT (U(1) << 20) +#define SCTLR_E0E_BIT (U(1) << 24) +#define SCTLR_EE_BIT (U(1) << 25) +#define SCTLR_UCI_BIT (U(1) << 26) +#define SCTLR_TRE_BIT (U(1) << 28) +#define SCTLR_AFE_BIT (U(1) << 29) +#define SCTLR_TE_BIT (U(1) << 30) +#define SCTLR_RESET_VAL SCTLR_EL3_RES1 + +/* CPACR_El1 definitions */ +#define CPACR_EL1_FPEN(x) ((x) << 20) +#define CPACR_EL1_FP_TRAP_EL0 U(0x1) +#define CPACR_EL1_FP_TRAP_ALL U(0x2) +#define CPACR_EL1_FP_TRAP_NONE U(0x3) + +/* SCR definitions */ +#define SCR_RES1_BITS ((U(1) << 4) | (U(1) << 5)) +#define SCR_FIEN_BIT (U(1) << 21) +#define SCR_TWE_BIT (U(1) << 13) +#define SCR_TWI_BIT (U(1) << 12) +#define SCR_ST_BIT (U(1) << 11) +#define SCR_RW_BIT (U(1) << 10) +#define SCR_SIF_BIT (U(1) << 9) +#define SCR_HCE_BIT (U(1) << 8) +#define SCR_SMD_BIT (U(1) << 7) +#define SCR_EA_BIT (U(1) << 3) +#define SCR_FIQ_BIT (U(1) << 2) +#define SCR_IRQ_BIT (U(1) << 1) +#define SCR_NS_BIT (U(1) << 0) +#define SCR_VALID_BIT_MASK U(0x2f8f) +#define SCR_RESET_VAL SCR_RES1_BITS + +/* HCR definitions */ +#define HCR_RW_BIT (1ull << 31) +#define HCR_TGE_BIT (1 << 27) +#define HCR_AMO_BIT (1 << 5) +#define HCR_IMO_BIT (1 << 4) +#define HCR_FMO_BIT (1 << 3) + +/* CNTHCTL_EL2 definitions */ +#define EL1PCEN_BIT (1 << 1) +#define EL1PCTEN_BIT (1 << 0) + +/* CNTKCTL_EL1 definitions */ +#define EL0PTEN_BIT (U(1) << 9) +#define EL0VTEN_BIT (U(1) << 8) +#define EL0PCTEN_BIT (U(1) << 0) +#define EL0VCTEN_BIT (U(1) << 1) +#define EVNTEN_BIT (U(1) << 2) +#define EVNTDIR_BIT (U(1) << 3) +#define EVNTI_SHIFT U(4) +#define EVNTI_MASK U(0xf) + +/* CPTR_EL2 definitions */ +#define TCPAC_BIT (1 << 31) +#define TTA_BIT (1 << 20) +#define TFP_BIT (1 << 10) + +/* CPSR/SPSR definitions */ +#define DAIF_FIQ_BIT (U(1) << 0) +#define DAIF_IRQ_BIT (U(1) << 1) +#define DAIF_ABT_BIT (U(1) << 2) +#define DAIF_DBG_BIT (U(1) << 3) +#define SPSR_DAIF_SHIFT U(6) +#define SPSR_DAIF_MASK U(0xf) + +#define SPSR_AIF_SHIFT U(6) +#define SPSR_AIF_MASK U(0x7) + +#define SPSR_E_SHIFT U(9) +#define SPSR_E_MASK U(0x1) +#define SPSR_E_LITTLE U(0x0) +#define SPSR_E_BIG U(0x1) + +#define SPSR_T_SHIFT U(5) +#define SPSR_T_MASK U(0x1) +#define SPSR_T_ARM U(0x0) +#define SPSR_T_THUMB U(0x1) + +#define SPSR_M_SHIFT U(4) +#define SPSR_M_MASK U(0x1) +#define SPSR_M_AARCH64 U(0x0) +#define SPSR_M_AARCH32 U(0x1) + +#define DISABLE_ALL_EXCEPTIONS \ + (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT | DAIF_DBG_BIT) + +#define DISABLE_INTERRUPTS (DAIF_FIQ_BIT | DAIF_IRQ_BIT) + +/* + * TCR defintions + */ +#define TCR_EL2_RES1 ((ULL(1) << 31) | (ULL(1) << 23)) +#define TCR_EL3_RES1 ((U(1) << 31) | (U(1) << 23)) +#define TCR_EL1_IPS_SHIFT U(32) +#define TCR_EL2_PS_SHIFT U(16) +#define TCR_EL3_PS_SHIFT U(16) + +#define TCR_TxSZ_MIN ULL(16) +#define TCR_TxSZ_MAX ULL(39) + +/* (internal) physical address size bits in EL3/EL1 */ +#define TCR_PS_BITS_4GB ULL(0x0) +#define TCR_PS_BITS_64GB ULL(0x1) +#define TCR_PS_BITS_1TB ULL(0x2) +#define TCR_PS_BITS_4TB ULL(0x3) +#define TCR_PS_BITS_16TB ULL(0x4) +#define TCR_PS_BITS_256TB ULL(0x5) + +#define ADDR_MASK_48_TO_63 ULL(0xFFFF000000000000) +#define ADDR_MASK_44_TO_47 ULL(0x0000F00000000000) +#define ADDR_MASK_42_TO_43 ULL(0x00000C0000000000) +#define ADDR_MASK_40_TO_41 ULL(0x0000030000000000) +#define ADDR_MASK_36_TO_39 ULL(0x000000F000000000) +#define ADDR_MASK_32_TO_35 ULL(0x0000000F00000000) + +#define TCR_RGN_INNER_NC (ULL(0x0) << 8) +#define TCR_RGN_INNER_WBA (ULL(0x1) << 8) +#define TCR_RGN_INNER_WT (ULL(0x2) << 8) +#define TCR_RGN_INNER_WBNA (ULL(0x3) << 8) + +#define TCR_RGN_OUTER_NC (ULL(0x0) << 10) +#define TCR_RGN_OUTER_WBA (ULL(0x1) << 10) +#define TCR_RGN_OUTER_WT (ULL(0x2) << 10) +#define TCR_RGN_OUTER_WBNA (ULL(0x3) << 10) + +#define TCR_SH_NON_SHAREABLE (ULL(0x0) << 12) +#define TCR_SH_OUTER_SHAREABLE (ULL(0x2) << 12) +#define TCR_SH_INNER_SHAREABLE (ULL(0x3) << 12) + +#define TCR_TG0_SHIFT U(14) +#define TCR_TG0_MASK ULL(3) +#define TCR_TG0_4K (ULL(0) << TCR_TG0_SHIFT) +#define TCR_TG0_64K (ULL(1) << TCR_TG0_SHIFT) +#define TCR_TG0_16K (ULL(2) << TCR_TG0_SHIFT) + +#define TCR_EPD0_BIT (ULL(1) << 7) +#define TCR_EPD1_BIT (ULL(1) << 23) + +#define MODE_SP_SHIFT U(0x0) +#define MODE_SP_MASK U(0x1) +#define MODE_SP_EL0 U(0x0) +#define MODE_SP_ELX U(0x1) + +#define MODE_RW_SHIFT U(0x4) +#define MODE_RW_MASK U(0x1) +#define MODE_RW_64 U(0x0) +#define MODE_RW_32 U(0x1) + +#define MODE_EL_SHIFT U(0x2) +#define MODE_EL_MASK U(0x3) +#define MODE_EL3 U(0x3) +#define MODE_EL2 U(0x2) +#define MODE_EL1 U(0x1) +#define MODE_EL0 U(0x0) + +#define MODE32_SHIFT U(0) +#define MODE32_MASK U(0xf) +#define MODE32_usr U(0x0) +#define MODE32_fiq U(0x1) +#define MODE32_irq U(0x2) +#define MODE32_svc U(0x3) +#define MODE32_mon U(0x6) +#define MODE32_abt U(0x7) +#define MODE32_hyp U(0xa) +#define MODE32_und U(0xb) +#define MODE32_sys U(0xf) + +#define GET_RW(mode) (((mode) >> MODE_RW_SHIFT) & MODE_RW_MASK) +#define GET_EL(mode) (((mode) >> MODE_EL_SHIFT) & MODE_EL_MASK) +#define GET_SP(mode) (((mode) >> MODE_SP_SHIFT) & MODE_SP_MASK) +#define GET_M32(mode) (((mode) >> MODE32_SHIFT) & MODE32_MASK) + +#define SPSR_64(el, sp, daif) \ + ((MODE_RW_64 << MODE_RW_SHIFT) | \ + (((el) & MODE_EL_MASK) << MODE_EL_SHIFT) | \ + (((sp) & MODE_SP_MASK) << MODE_SP_SHIFT) | \ + (((daif) & SPSR_DAIF_MASK) << SPSR_DAIF_SHIFT)) + +#define SPSR_MODE32(mode, isa, endian, aif) \ + ((MODE_RW_32 << MODE_RW_SHIFT) | \ + (((mode) & MODE32_MASK) << MODE32_SHIFT) | \ + (((isa) & SPSR_T_MASK) << SPSR_T_SHIFT) | \ + (((endian) & SPSR_E_MASK) << SPSR_E_SHIFT) | \ + (((aif) & SPSR_AIF_MASK) << SPSR_AIF_SHIFT)) + +/* + * TTBR Definitions + */ +#define TTBR_CNP_BIT ULL(0x1) + +/* Physical timer control register bit fields shifts and masks */ +#define CNTP_CTL_ENABLE_SHIFT 0 +#define CNTP_CTL_IMASK_SHIFT 1 +#define CNTP_CTL_ISTATUS_SHIFT 2 + +#define CNTP_CTL_ENABLE_MASK 1 +#define CNTP_CTL_IMASK_MASK 1 +#define CNTP_CTL_ISTATUS_MASK 1 + +#define get_cntp_ctl_enable(x) ((x >> CNTP_CTL_ENABLE_SHIFT) & \ + CNTP_CTL_ENABLE_MASK) +#define get_cntp_ctl_imask(x) ((x >> CNTP_CTL_IMASK_SHIFT) & \ + CNTP_CTL_IMASK_MASK) +#define get_cntp_ctl_istatus(x) ((x >> CNTP_CTL_ISTATUS_SHIFT) & \ + CNTP_CTL_ISTATUS_MASK) + +#define set_cntp_ctl_enable(x) (x |= 1 << CNTP_CTL_ENABLE_SHIFT) +#define set_cntp_ctl_imask(x) (x |= 1 << CNTP_CTL_IMASK_SHIFT) + +#define clr_cntp_ctl_enable(x) (x &= ~(1 << CNTP_CTL_ENABLE_SHIFT)) +#define clr_cntp_ctl_imask(x) (x &= ~(1 << CNTP_CTL_IMASK_SHIFT)) + +/* Exception Syndrome register bits and bobs */ +#define ESR_EC_SHIFT U(26) +#define ESR_EC_MASK U(0x3f) +#define ESR_EC_LENGTH U(6) +#define EC_UNKNOWN U(0x0) +#define EC_WFE_WFI U(0x1) +#define EC_AARCH32_CP15_MRC_MCR U(0x3) +#define EC_AARCH32_CP15_MRRC_MCRR U(0x4) +#define EC_AARCH32_CP14_MRC_MCR U(0x5) +#define EC_AARCH32_CP14_LDC_STC U(0x6) +#define EC_FP_SIMD U(0x7) +#define EC_AARCH32_CP10_MRC U(0x8) +#define EC_AARCH32_CP14_MRRC_MCRR U(0xc) +#define EC_ILLEGAL U(0xe) +#define EC_AARCH32_SVC U(0x11) +#define EC_AARCH32_HVC U(0x12) +#define EC_AARCH32_SMC U(0x13) +#define EC_AARCH64_SVC U(0x15) +#define EC_AARCH64_HVC U(0x16) +#define EC_AARCH64_SMC U(0x17) +#define EC_AARCH64_SYS U(0x18) +#define EC_IABORT_LOWER_EL U(0x20) +#define EC_IABORT_CUR_EL U(0x21) +#define EC_PC_ALIGN U(0x22) +#define EC_DABORT_LOWER_EL U(0x24) +#define EC_DABORT_CUR_EL U(0x25) +#define EC_SP_ALIGN U(0x26) +#define EC_AARCH32_FP U(0x28) +#define EC_AARCH64_FP U(0x2c) +#define EC_SERROR U(0x2f) + +#define EC_BITS(x) (x >> ESR_EC_SHIFT) & ESR_EC_MASK + +/******************************************************************************* + * Definitions of register offsets, fields and macros for CPU system + * instructions. + ******************************************************************************/ + +#define TLBI_ADDR_SHIFT U(12) +#define TLBI_ADDR_MASK ULL(0x00000FFFFFFFFFFF) +#define TLBI_ADDR(x) (((x) >> TLBI_ADDR_SHIFT) & TLBI_ADDR_MASK) + +/******************************************************************************* + * Definitions of register offsets and fields in the CNTBaseN Frame of the + * system level implementation of the Generic Timer. + ******************************************************************************/ +/* Physical Count register. */ +#define CNTPCT_LO 0x0 +/* Counter Frequency register. */ +#define CNTBASEN_CNTFRQ 0x10 +/* Physical Timer CompareValue register. */ +#define CNTP_CVAL_LO 0x20 +/* Physical Timer Control register. */ +#define CNTP_CTL 0x2c + +/******************************************************************************* + * Definitions of MAIR encodings for device and normal memory + ******************************************************************************/ +/* + * MAIR encodings for device memory attributes. + */ +#define MAIR_DEV_nGnRnE ULL(0x0) +#define MAIR_DEV_nGnRE ULL(0x4) +#define MAIR_DEV_nGRE ULL(0x8) +#define MAIR_DEV_GRE ULL(0xc) + +/* + * MAIR encodings for normal memory attributes. + * + * Cache Policy + * WT: Write Through + * WB: Write Back + * NC: Non-Cacheable + * + * Transient Hint + * NTR: Non-Transient + * TR: Transient + * + * Allocation Policy + * RA: Read Allocate + * WA: Write Allocate + * RWA: Read and Write Allocate + * NA: No Allocation + */ +#define MAIR_NORM_WT_TR_WA ULL(0x1) +#define MAIR_NORM_WT_TR_RA ULL(0x2) +#define MAIR_NORM_WT_TR_RWA ULL(0x3) +#define MAIR_NORM_NC ULL(0x4) +#define MAIR_NORM_WB_TR_WA ULL(0x5) +#define MAIR_NORM_WB_TR_RA ULL(0x6) +#define MAIR_NORM_WB_TR_RWA ULL(0x7) +#define MAIR_NORM_WT_NTR_NA ULL(0x8) +#define MAIR_NORM_WT_NTR_WA ULL(0x9) +#define MAIR_NORM_WT_NTR_RA ULL(0xa) +#define MAIR_NORM_WT_NTR_RWA ULL(0xb) +#define MAIR_NORM_WB_NTR_NA ULL(0xc) +#define MAIR_NORM_WB_NTR_WA ULL(0xd) +#define MAIR_NORM_WB_NTR_RA ULL(0xe) +#define MAIR_NORM_WB_NTR_RWA ULL(0xf) + +#define MAIR_NORM_OUTER_SHIFT U(4) + +#define MAKE_MAIR_NORMAL_MEMORY(inner, outer) ((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT)) + +/* PAR_EL1 fields */ +#define PAR_F_SHIFT U(0) +#define PAR_F_MASK ULL(0x1) +#define PAR_ADDR_SHIFT U(12) +#define PAR_ADDR_MASK (BIT(40) - ULL(1)) /* 40-bits-wide page address */ + +/******************************************************************************* + * Definitions for system register interface to AMU for ARMv8.4 onwards + ******************************************************************************/ +#define AMCR_EL0 S3_3_C13_C2_0 +#define AMCFGR_EL0 S3_3_C13_C2_1 +#define AMCGCR_EL0 S3_3_C13_C2_2 +#define AMUSERENR_EL0 S3_3_C13_C2_3 +#define AMCNTENCLR0_EL0 S3_3_C13_C2_4 +#define AMCNTENSET0_EL0 S3_3_C13_C2_5 +#define AMCNTENCLR1_EL0 S3_3_C13_C3_0 +#define AMCNTENSET1_EL0 S3_3_C13_C3_1 + +/* Activity Monitor Group 0 Event Counter Registers */ +#define AMEVCNTR00_EL0 S3_3_C13_C4_0 +#define AMEVCNTR01_EL0 S3_3_C13_C4_1 +#define AMEVCNTR02_EL0 S3_3_C13_C4_2 +#define AMEVCNTR03_EL0 S3_3_C13_C4_3 + +/* Activity Monitor Group 0 Event Type Registers */ +#define AMEVTYPER00_EL0 S3_3_C13_C6_0 +#define AMEVTYPER01_EL0 S3_3_C13_C6_1 +#define AMEVTYPER02_EL0 S3_3_C13_C6_2 +#define AMEVTYPER03_EL0 S3_3_C13_C6_3 + +/* Activity Monitor Group 1 Event Counter Registers */ +#define AMEVCNTR10_EL0 S3_3_C13_C12_0 +#define AMEVCNTR11_EL0 S3_3_C13_C12_1 +#define AMEVCNTR12_EL0 S3_3_C13_C12_2 +#define AMEVCNTR13_EL0 S3_3_C13_C12_3 +#define AMEVCNTR14_EL0 S3_3_C13_C12_4 +#define AMEVCNTR15_EL0 S3_3_C13_C12_5 +#define AMEVCNTR16_EL0 S3_3_C13_C12_6 +#define AMEVCNTR17_EL0 S3_3_C13_C12_7 +#define AMEVCNTR18_EL0 S3_3_C13_C13_0 +#define AMEVCNTR19_EL0 S3_3_C13_C13_1 +#define AMEVCNTR1A_EL0 S3_3_C13_C13_2 +#define AMEVCNTR1B_EL0 S3_3_C13_C13_3 +#define AMEVCNTR1C_EL0 S3_3_C13_C13_4 +#define AMEVCNTR1D_EL0 S3_3_C13_C13_5 +#define AMEVCNTR1E_EL0 S3_3_C13_C13_6 +#define AMEVCNTR1F_EL0 S3_3_C13_C13_7 + +/* Activity Monitor Group 1 Event Type Registers */ +#define AMEVTYPER10_EL0 S3_3_C13_C14_0 +#define AMEVTYPER11_EL0 S3_3_C13_C14_1 +#define AMEVTYPER12_EL0 S3_3_C13_C14_2 +#define AMEVTYPER13_EL0 S3_3_C13_C14_3 +#define AMEVTYPER14_EL0 S3_3_C13_C14_4 +#define AMEVTYPER15_EL0 S3_3_C13_C14_5 +#define AMEVTYPER16_EL0 S3_3_C13_C14_6 +#define AMEVTYPER17_EL0 S3_3_C13_C14_7 +#define AMEVTYPER18_EL0 S3_3_C13_C15_0 +#define AMEVTYPER19_EL0 S3_3_C13_C15_1 +#define AMEVTYPER1A_EL0 S3_3_C13_C15_2 +#define AMEVTYPER1B_EL0 S3_3_C13_C15_3 +#define AMEVTYPER1C_EL0 S3_3_C13_C15_4 +#define AMEVTYPER1D_EL0 S3_3_C13_C15_5 +#define AMEVTYPER1E_EL0 S3_3_C13_C15_6 +#define AMEVTYPER1F_EL0 S3_3_C13_C15_7 + +/* AMCGCR_EL0 definitions */ +#define AMCGCR_EL0_CG1NC_SHIFT U(8) +#define AMCGCR_EL0_CG1NC_LENGTH U(8) +#define AMCGCR_EL0_CG1NC_MASK U(0xff) + +/******************************************************************************* + * RAS system registers + *******************************************************************************/ +#define DISR_EL1 S3_0_C12_C1_1 +#define DISR_A_BIT U(31) + +#define ERRIDR_EL1 S3_0_C5_C3_0 +#define ERRIDR_MASK U(0xffff) + +#define ERRSELR_EL1 S3_0_C5_C3_1 + +/* Fault injection registers */ +#define ERXPFGF_EL1 S3_0_C5_C4_4 +#define ERXCTLR_EL1 S3_0_C5_C4_1 +#define ERXPFGCTL_EL1 S3_0_C5_C4_5 +#define ERXPFGCDN_EL1 S3_0_C5_C4_6 + +#define ERXCTLR_ED_BIT (1 << 0) +#define ERXCTLR_UE_BIT (1 << 4) + +#define ERXPFGCTL_UC_BIT (1 << 1) +#define ERXPFGCTL_UEU_BIT (1 << 2) +#define ERXPFGCTL_CDEN_BIT (1 << 31) + +#endif /* __ARCH_H__ */ diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h new file mode 100644 index 000000000..c313d6098 --- /dev/null +++ b/include/lib/aarch64/arch_helpers.h @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __ARCH_HELPERS_H__ +#define __ARCH_HELPERS_H__ + +#include <arch.h> /* for additional register definitions */ +#include <cdefs.h> /* For __dead2 */ +#include <misc_utils.h> +#include <stdint.h> +#include <sys/types.h> + +/********************************************************************** + * Macros which create inline functions to read or write CPU system + * registers + *********************************************************************/ + +#define _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \ +static inline u_register_t read_ ## _name(void) \ +{ \ + u_register_t v; \ + __asm__ volatile ("mrs %0, " #_reg_name : "=r" (v)); \ + return v; \ +} + +#define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) \ +static inline void write_ ## _name(u_register_t v) \ +{ \ + __asm__ volatile ("msr " #_reg_name ", %0" : : "r" (v)); \ +} + +#define SYSREG_WRITE_CONST(reg_name, v) \ + __asm__ volatile ("msr " #reg_name ", %0" : : "i" (v)) + +/* Define read function for system register */ +#define DEFINE_SYSREG_READ_FUNC(_name) \ + _DEFINE_SYSREG_READ_FUNC(_name, _name) + +/* Define read & write function for system register */ +#define DEFINE_SYSREG_RW_FUNCS(_name) \ + _DEFINE_SYSREG_READ_FUNC(_name, _name) \ + _DEFINE_SYSREG_WRITE_FUNC(_name, _name) + +/* Define read & write function for renamed system register */ +#define DEFINE_RENAME_SYSREG_RW_FUNCS(_name, _reg_name) \ + _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \ + _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) + +/* Define read function for renamed system register */ +#define DEFINE_RENAME_SYSREG_READ_FUNC(_name, _reg_name) \ + _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) + +/* Define write function for renamed system register */ +#define DEFINE_RENAME_SYSREG_WRITE_FUNC(_name, _reg_name) \ + _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) + +/********************************************************************** + * Macros to create inline functions for system instructions + *********************************************************************/ + +/* Define function for simple system instruction */ +#define DEFINE_SYSOP_FUNC(_op) \ +static inline void _op(void) \ +{ \ + __asm__ (#_op); \ +} + +/* Define function for system instruction with type specifier */ +#define DEFINE_SYSOP_TYPE_FUNC(_op, _type) \ +static inline void _op ## _type(void) \ +{ \ + __asm__ (#_op " " #_type); \ +} + +/* Define function for system instruction with register parameter */ +#define DEFINE_SYSOP_TYPE_PARAM_FUNC(_op, _type) \ +static inline void _op ## _type(uint64_t v) \ +{ \ + __asm__ (#_op " " #_type ", %0" : : "r" (v)); \ +} + +/******************************************************************************* + * TLB maintenance accessor prototypes + ******************************************************************************/ + +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1is) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2is) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3is) +DEFINE_SYSOP_TYPE_FUNC(tlbi, vmalle1) + +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaae1is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaale1is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae2is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale2is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae3is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale3is) + +/******************************************************************************* + * Cache maintenance accessor prototypes + ******************************************************************************/ +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, isw) +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cisw) +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, csw) +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvac) +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, ivac) +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, civac) +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvau) +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, zva) + +void flush_dcache_range(uintptr_t addr, size_t size); +void clean_dcache_range(uintptr_t addr, size_t size); +void inv_dcache_range(uintptr_t addr, size_t size); + +void dcsw_op_louis(u_register_t op_type); +void dcsw_op_all(u_register_t op_type); + +void disable_mmu(void); +void disable_mmu_icache(void); + +/******************************************************************************* + * Misc. accessor prototypes + ******************************************************************************/ + +DEFINE_SYSREG_READ_FUNC(id_pfr1_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1) +DEFINE_SYSREG_READ_FUNC(CurrentEl) +DEFINE_SYSREG_READ_FUNC(ctr_el0) +DEFINE_SYSREG_RW_FUNCS(daif) +DEFINE_SYSREG_RW_FUNCS(spsr_el1) +DEFINE_SYSREG_RW_FUNCS(spsr_el2) +DEFINE_SYSREG_RW_FUNCS(elr_el1) +DEFINE_SYSREG_RW_FUNCS(elr_el2) + +DEFINE_SYSOP_FUNC(wfi) +DEFINE_SYSOP_FUNC(wfe) +DEFINE_SYSOP_FUNC(sev) +DEFINE_SYSOP_TYPE_FUNC(dsb, sy) +DEFINE_SYSOP_TYPE_FUNC(dsb, ish) +DEFINE_SYSOP_TYPE_FUNC(dsb, ishst) +DEFINE_SYSOP_FUNC(isb) +DEFINE_SYSOP_TYPE_FUNC(dmb, oshld) +DEFINE_SYSOP_TYPE_FUNC(dmb, oshst) +DEFINE_SYSOP_TYPE_FUNC(dmb, osh) +DEFINE_SYSOP_TYPE_FUNC(dmb, nshld) +DEFINE_SYSOP_TYPE_FUNC(dmb, nshst) +DEFINE_SYSOP_TYPE_FUNC(dmb, nsh) +DEFINE_SYSOP_TYPE_FUNC(dmb, ishld) +DEFINE_SYSOP_TYPE_FUNC(dmb, ishst) +DEFINE_SYSOP_TYPE_FUNC(dmb, ish) +DEFINE_SYSOP_TYPE_FUNC(dmb, ld) +DEFINE_SYSOP_TYPE_FUNC(dmb, st) +DEFINE_SYSOP_TYPE_FUNC(dmb, sy) + +#define write_daifclr(val) SYSREG_WRITE_CONST(daifclr, val) +#define write_daifset(val) SYSREG_WRITE_CONST(daifset, val) + +static inline void enable_irq(void) +{ + /* + * The compiler memory barrier will prevent the compiler from + * scheduling non-volatile memory access after the write to the + * register. + * + * This could happen if some initialization code issues non-volatile + * accesses to an area used by an interrupt handler, in the assumption + * that it is safe as the interrupts are disabled at the time it does + * that (according to program order). However, non-volatile accesses + * are not necessarily in program order relatively with volatile inline + * assembly statements (and volatile accesses). + */ + COMPILER_BARRIER(); + write_daifclr(DAIF_IRQ_BIT); + isb(); +} + +static inline void enable_fiq(void) +{ + COMPILER_BARRIER(); + write_daifclr(DAIF_FIQ_BIT); + isb(); +} + +static inline void enable_serror(void) +{ + COMPILER_BARRIER(); + write_daifclr(DAIF_ABT_BIT); + isb(); +} + +static inline void enable_debug_exceptions(void) +{ + COMPILER_BARRIER(); + write_daifclr(DAIF_DBG_BIT); + isb(); +} + +static inline void disable_irq(void) +{ + COMPILER_BARRIER(); + write_daifset(DAIF_IRQ_BIT); + isb(); +} + +static inline void disable_fiq(void) +{ + COMPILER_BARRIER(); + write_daifset(DAIF_FIQ_BIT); + isb(); +} + +static inline void disable_serror(void) +{ + COMPILER_BARRIER(); + write_daifset(DAIF_ABT_BIT); + isb(); +} + +static inline void disable_debug_exceptions(void) +{ + COMPILER_BARRIER(); + write_daifset(DAIF_DBG_BIT); + isb(); +} + +uint32_t get_afflvl_shift(uint32_t); +uint32_t mpidr_mask_lower_afflvls(uint64_t, uint32_t); + +void __dead2 eret(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3, + uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7); +void __dead2 smc(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3, + uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7); + +/******************************************************************************* + * System register accessor prototypes + ******************************************************************************/ +DEFINE_SYSREG_READ_FUNC(midr_el1) +DEFINE_SYSREG_READ_FUNC(mpidr_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64mmfr0_el1) + +DEFINE_SYSREG_RW_FUNCS(hcr_el2) + +DEFINE_SYSREG_RW_FUNCS(vbar_el1) +DEFINE_SYSREG_RW_FUNCS(vbar_el2) + +DEFINE_SYSREG_RW_FUNCS(sctlr_el1) +DEFINE_SYSREG_RW_FUNCS(sctlr_el2) +DEFINE_SYSREG_RW_FUNCS(sctlr_el3) + +DEFINE_SYSREG_RW_FUNCS(actlr_el1) +DEFINE_SYSREG_RW_FUNCS(actlr_el2) + +DEFINE_SYSREG_RW_FUNCS(esr_el1) +DEFINE_SYSREG_RW_FUNCS(esr_el2) + +DEFINE_SYSREG_RW_FUNCS(afsr0_el1) +DEFINE_SYSREG_RW_FUNCS(afsr0_el2) + +DEFINE_SYSREG_RW_FUNCS(afsr1_el1) +DEFINE_SYSREG_RW_FUNCS(afsr1_el2) + +DEFINE_SYSREG_RW_FUNCS(far_el1) +DEFINE_SYSREG_RW_FUNCS(far_el2) + +DEFINE_SYSREG_RW_FUNCS(mair_el1) +DEFINE_SYSREG_RW_FUNCS(mair_el2) + +DEFINE_SYSREG_RW_FUNCS(amair_el1) +DEFINE_SYSREG_RW_FUNCS(amair_el2) + +DEFINE_SYSREG_READ_FUNC(rvbar_el1) +DEFINE_SYSREG_READ_FUNC(rvbar_el2) + +DEFINE_SYSREG_RW_FUNCS(rmr_el1) +DEFINE_SYSREG_RW_FUNCS(rmr_el2) + +DEFINE_SYSREG_RW_FUNCS(tcr_el1) +DEFINE_SYSREG_RW_FUNCS(tcr_el2) + +DEFINE_SYSREG_RW_FUNCS(ttbr0_el1) +DEFINE_SYSREG_RW_FUNCS(ttbr0_el2) + +DEFINE_SYSREG_RW_FUNCS(ttbr1_el1) + +DEFINE_SYSREG_RW_FUNCS(cptr_el2) + +DEFINE_SYSREG_RW_FUNCS(cpacr_el1) +DEFINE_SYSREG_RW_FUNCS(cntfrq_el0) +DEFINE_SYSREG_RW_FUNCS(cnthp_ctl_el2) +DEFINE_SYSREG_RW_FUNCS(cnthp_tval_el2) +DEFINE_SYSREG_RW_FUNCS(cnthp_cval_el2) +DEFINE_SYSREG_RW_FUNCS(cntps_ctl_el1) +DEFINE_SYSREG_RW_FUNCS(cntps_tval_el1) +DEFINE_SYSREG_RW_FUNCS(cntps_cval_el1) +DEFINE_SYSREG_RW_FUNCS(cntp_ctl_el0) +DEFINE_SYSREG_RW_FUNCS(cntp_tval_el0) +DEFINE_SYSREG_RW_FUNCS(cntp_cval_el0) +DEFINE_SYSREG_READ_FUNC(cntpct_el0) +DEFINE_SYSREG_RW_FUNCS(cnthctl_el2) + +DEFINE_SYSREG_RW_FUNCS(vpidr_el2) +DEFINE_SYSREG_RW_FUNCS(vmpidr_el2) + +/* GICv3 System Registers */ + +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el2, ICC_SRE_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_pmr_el1, ICC_PMR_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen1_el1, ICC_IGRPEN1_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sgi1r, ICC_SGI1R) +DEFINE_RENAME_SYSREG_READ_FUNC(icc_hppir1_el1, ICC_HPPIR1_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(icc_iar1_el1, ICC_IAR1_EL1) +DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir1_el1, ICC_EOIR1_EL1) + +DEFINE_RENAME_SYSREG_RW_FUNCS(amcgcr_el0, AMCGCR_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr0_el0, AMCNTENCLR0_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset0_el0, AMCNTENSET0_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr1_el0, AMCNTENCLR1_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset1_el0, AMCNTENSET1_EL0) + +#define IS_IN_EL(x) \ + (GET_EL(read_CurrentEl()) == MODE_EL##x) + +#define IS_IN_EL1() IS_IN_EL(1) +#define IS_IN_EL2() IS_IN_EL(2) + +#endif /* __ARCH_HELPERS_H__ */ diff --git a/include/lib/cassert.h b/include/lib/cassert.h new file mode 100644 index 000000000..8844e8b02 --- /dev/null +++ b/include/lib/cassert.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CASSERT_H__ +#define __CASSERT_H__ + +/******************************************************************************* + * Macro to flag a compile time assertion. It uses the preprocessor to generate + * an invalid C construct if 'cond' evaluates to false. + * The following compilation error is triggered if the assertion fails: + * "error: size of array 'msg' is negative" + ******************************************************************************/ +#define CASSERT(cond, msg) typedef char msg[(cond) ? 1 : -1] + +#endif /* __CASSERT_H__ */ diff --git a/include/lib/events.h b/include/lib/events.h new file mode 100644 index 000000000..34c5b2f76 --- /dev/null +++ b/include/lib/events.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __EVENTS_H__ +#define __EVENTS_H__ + +#include <spinlock.h> + +typedef struct { + /* + * Counter that keeps track of the minimum number of recipients of the + * event. When the event is sent, this counter is incremented. When it + * is received, it is decremented. Therefore, a zero value means that + * the event hasn't been sent yet, or that all recipients have already + * received it. + * + * Volatile is needed as it will enforce ordering relatively to + * accesses to the lock. + */ + volatile unsigned int cnt; + + /* Lock used to avoid concurrent accesses to the counter */ + spinlock_t lock; +} event_t; + +/* + * Initialise an event. + * event: Address of the event to initialise + * + * This function can be used either to initialise a newly created event + * structure or to recycle one. + * + * Note: This function is not MP-safe. It can't use the event lock as it is + * responsible for initialising it. Care must be taken to ensure this function + * is called in the right circumstances. + */ +void tftf_init_event(event_t *event); + +/* + * Send an event to a CPU. + * event: Address of the variable that acts as a synchronisation object. + * + * Which CPU receives the event is determined on a first-come, first-served + * basis. If several CPUs are waiting for the same event then the first CPU + * which takes the event will reflect that in the event structure. + * + * Note: This is equivalent to calling: + * tftf_send_event_to(event, 1); + */ +void tftf_send_event(event_t *event); + +/* + * Send an event to all CPUs. + * event: Address of the variable that acts as a synchronisation object. + * + * Note: This is equivalent to calling: + * tftf_send_event_to(event, PLATFORM_CORE_COUNT); + */ +void tftf_send_event_to_all(event_t *event); + +/* + * Send an event to a given number of CPUs. + * event: Address of the variable that acts as a synchronisation object. + * cpus_count: Number of CPUs to send the event to. + * + * Which CPUs receive the event is determined on a first-come, first-served + * basis. If more than 'cpus_count' CPUs are waiting for the same event then the + * first 'cpus_count' CPUs which take the event will reflect that in the event + * structure. + */ +void tftf_send_event_to(event_t *event, unsigned int cpus_count); + +/* + * Wait for an event. + * event: Address of the variable that acts as a synchronisation object. + */ +void tftf_wait_for_event(event_t *event); + +#endif /* __EVENTS_H__ */ diff --git a/include/lib/extensions/amu.h b/include/lib/extensions/amu.h new file mode 100644 index 000000000..30714643b --- /dev/null +++ b/include/lib/extensions/amu.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __AMU_H__ +#define __AMU_H__ + +#include <platform_def.h> +#include <stdint.h> + +#define AMU_GROUP0_NR_COUNTERS 4 +#define AMU_GROUP0_COUNTERS_MASK 0xf + +#ifdef PLAT_AMU_GROUP1_COUNTERS_MASK +#define AMU_GROUP1_COUNTERS_MASK PLAT_AMU_GROUP1_COUNTERS_MASK +#else +#define AMU_GROUP1_COUNTERS_MASK 0 +#endif + +#ifdef PLAT_AMU_GROUP1_NR_COUNTERS +#define AMU_GROUP1_NR_COUNTERS PLAT_AMU_GROUP1_NR_COUNTERS +#else +#define AMU_GROUP1_NR_COUNTERS 0 +#endif + +#define AMU_GROUP0_MAX_NR_COUNTERS 4 +#define AMU_GROUP1_MAX_NR_COUNTERS 16 + +int amu_supported(void); +uint64_t amu_group0_cnt_read(int idx); +uint64_t amu_group1_cnt_read(int idx); + +#endif /* __AMU_H__ */ diff --git a/include/lib/extensions/amu_private.h b/include/lib/extensions/amu_private.h new file mode 100644 index 000000000..e6cd2906e --- /dev/null +++ b/include/lib/extensions/amu_private.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2017, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __AMU_PRIVATE_H__ +#define __AMU_PRIVATE_H__ + +#include <stdint.h> + +uint64_t amu_group0_cnt_read_internal(int idx); +uint64_t amu_group1_cnt_read_internal(int idx); + +#endif /* __AMU_PRIVATE_H__ */ diff --git a/include/lib/io_storage.h b/include/lib/io_storage.h new file mode 100644 index 000000000..42cebd3fd --- /dev/null +++ b/include/lib/io_storage.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __IO_H__ +#define __IO_H__ + +#include <stdint.h> +#include <stdio.h> /* For ssize_t */ +#include <uuid.h> + +/* Device type which can be used to enable policy decisions about which device + * to access */ +typedef enum { + IO_TYPE_INVALID, + IO_TYPE_FLASH, + IO_TYPE_MEMMAP, + IO_TYPE_FIRMWARE_IMAGE_PACKAGE, + IO_TYPE_MAX +} io_type_t; + + +/* Modes used when seeking data on a supported device */ +typedef enum { + IO_SEEK_INVALID, + IO_SEEK_SET, + IO_SEEK_END, + IO_SEEK_CUR, + IO_SEEK_MAX +} io_seek_mode_t; + + +/* Connector type, providing a means of identifying a device to open */ +struct io_dev_connector; + + +/* File specification - used to refer to data on a device supporting file-like + * entities */ +typedef struct io_file_spec { + const char *path; + unsigned int mode; +} io_file_spec_t; + +/* UUID specification - used to refer to data accessed using UUIDs (i.e. FIP + * images) */ +typedef struct io_uuid_spec { + const uuid_t uuid; +} io_uuid_spec_t; + + +/* Block specification - used to refer to data on a device supporting + * block-like entities */ +typedef struct io_block_spec { + size_t offset; + size_t length; +} io_block_spec_t; + + +/* Access modes used when accessing data on a device */ +#define IO_MODE_INVALID (0) +#define IO_MODE_RO (1 << 0) +#define IO_MODE_RW (1 << 1) + + +/* Return codes reported by 'io_*' APIs */ +#define IO_SUCCESS (0) +#define IO_FAIL (-1) +#define IO_NOT_SUPPORTED (-2) +#define IO_RESOURCES_EXHAUSTED (-3) + + +/* Open a connection to a device */ +int io_dev_open(const struct io_dev_connector *dev_con, + const uintptr_t dev_spec, + uintptr_t *dev_handle); + + +/* Initialise a device explicitly - to permit lazy initialisation or + * re-initialisation */ +int io_dev_init(uintptr_t dev_handle, const uintptr_t init_params); + +/* TODO: Consider whether an explicit "shutdown" API should be included */ + +/* Close a connection to a device */ +int io_dev_close(uintptr_t dev_handle); + + +/* Synchronous operations */ +int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle); + +int io_seek(uintptr_t handle, io_seek_mode_t mode, ssize_t offset); + +int io_size(uintptr_t handle, size_t *length); + +int io_read(uintptr_t handle, uintptr_t buffer, size_t length, + size_t *length_read); + +int io_write(uintptr_t handle, const uintptr_t buffer, size_t length, + size_t *length_written); + +int io_close(uintptr_t handle); + + +#endif /* __IO_H__ */ diff --git a/include/lib/irq.h b/include/lib/irq.h new file mode 100644 index 000000000..1628221a0 --- /dev/null +++ b/include/lib/irq.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __IRQ_H__ +#define __IRQ_H__ + +#include <platform_def.h> /* For CACHE_WRITEBACK_GRANULE */ +#include <stdint.h> + +/* + * SGI sent by the timer management framework to notify CPUs when the system + * timer fires off + */ +#define IRQ_WAKE_SGI IRQ_NS_SGI_7 + +#ifndef __ASSEMBLY__ + +/* Prototype of a handler function for an IRQ */ +typedef int (*irq_handler_t)(void *data); + +/* Keep track of the IRQ handler registered for a given SPI */ +typedef struct { + irq_handler_t handler; +} spi_desc; + +/* Keep track of the IRQ handler registered for a spurious interrupt */ +typedef irq_handler_t spurious_desc; + +/* + * PPIs and SGIs are interrupts that are private to a GIC CPU interface. These + * interrupts are banked in the GIC Distributor. Therefore, each CPU can + * set up a different IRQ handler for a given PPI/SGI. + * + * So we define a data structure representing an IRQ handler aligned on the + * size of a cache line. This guarantees that in an array of these, each element + * is loaded in a separate cache line. This allows efficient concurrent + * manipulation of these elements on different CPUs. + */ +typedef struct { + irq_handler_t handler; +} __aligned(CACHE_WRITEBACK_GRANULE) irq_handler_banked_t; + +typedef irq_handler_banked_t ppi_desc; +typedef irq_handler_banked_t sgi_desc; + +void tftf_irq_setup(void); + +/* + * Generic handler called upon reception of an IRQ. + * + * This function acknowledges the interrupt, calls the user-defined handler + * if one has been registered then marks the processing of the interrupt as + * complete. + */ +int tftf_irq_handler_dispatcher(void); + +/* + * Enable interrupt #irq_num for the calling core. + */ +void tftf_irq_enable(unsigned int irq_num, uint8_t irq_priority); + +/* + * Disable interrupt #irq_num for the calling core. + */ +void tftf_irq_disable(unsigned int irq_num); + +/* + * Register an interrupt handler for a given interrupt number. + * Will fail if there is already an interrupt handler registered for the same + * interrupt. + * + * Return 0 on success, a negative value otherwise. + */ +int tftf_irq_register_handler(unsigned int num, irq_handler_t irq_handler); + +/* + * Unregister an interrupt handler for a given interrupt number. + * Will fail if there is no interrupt handler registered for that interrupt. + * + * Return 0 on success, a negative value otherwise. + */ +int tftf_irq_unregister_handler(unsigned int irq_num); + +#endif /* __ASSEMBLY__ */ + +#endif /* __IRQ_H__ */ diff --git a/include/lib/mmio.h b/include/lib/mmio.h new file mode 100644 index 000000000..e8a7df02b --- /dev/null +++ b/include/lib/mmio.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __MMIO_H__ +#define __MMIO_H__ + +#include <stdint.h> + +static inline void mmio_write_8(uintptr_t addr, uint8_t value) +{ + *(volatile uint8_t*)addr = value; +} + +static inline uint8_t mmio_read_8(uintptr_t addr) +{ + return *(volatile uint8_t*)addr; +} + +static inline void mmio_write_32(uintptr_t addr, uint32_t value) +{ + *(volatile uint32_t*)addr = value; +} + +static inline uint32_t mmio_read_32(uintptr_t addr) +{ + return *(volatile uint32_t*)addr; +} + +static inline void mmio_write_64(uintptr_t addr, uint64_t value) +{ + *(volatile uint64_t*)addr = value; +} + +static inline uint64_t mmio_read_64(uintptr_t addr) +{ + return *(volatile uint64_t*)addr; +} + +#endif /* __MMIO_H__ */ diff --git a/include/lib/power_management.h b/include/lib/power_management.h new file mode 100644 index 000000000..d2d690144 --- /dev/null +++ b/include/lib/power_management.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __POWER_MANAGEMENT_H__ +#define __POWER_MANAGEMENT_H__ + +#include <platform_def.h> +#include <psci.h> +#include <spinlock.h> +#include <stdint.h> +#include <types.h> + +/* Set of states of an affinity node as seen by the Test Framework */ +typedef enum { + TFTF_AFFINITY_STATE_OFF = 0, + TFTF_AFFINITY_STATE_ON_PENDING, + TFTF_AFFINITY_STATE_ON, +} tftf_affinity_info_t; + +/* Structure for keeping track of CPU state */ +typedef struct { + volatile tftf_affinity_info_t state; + spinlock_t lock; +} __aligned(CACHE_WRITEBACK_GRANULE) tftf_cpu_state_t; + +/* + * Suspend information passed to the TFTF suspend helpers. + */ +typedef struct suspend_info { + /* The power state parameter to be passed to PSCI_CPU_SUSPEND */ + unsigned int power_state; + /* SMC function ID of the PSCI suspend call */ + unsigned int psci_api; + /* Whether the system context needs to be saved and restored */ + unsigned int save_system_context; +} suspend_info_t; + +/* + * Power up a core. + * This uses the PSCI CPU_ON API, which means it relies on the EL3 firmware's + * runtime services capabilities. + * The core will be boostrapped by the framework before handing it over + * to the entry point specified as the 2nd argument. + * + * target_cpu: MPID of the CPU to power up + * entrypoint: Address where the CPU will jump once the framework has + * initialized it + * context_id: Context identifier as defined by the PSCI specification + * + * Return: Return code of the PSCI CPU_ON call + * (refer to the PSCI specification for details) + */ +int32_t tftf_cpu_on(u_register_t target_cpu, + uintptr_t entrypoint, + u_register_t context_id); + +/* + * Tries to power up a core. + * This API is similar to tftf_cpu_on API with the difference being it + * does a SMC call to EL3 firmware without checking the status of the + * core with respect to the framework. + * + * A caller is expected to handle the return code given by the EL3 firmware. + * + * target_cpu: MPID of the CPU to power up + * entrypoint: Address where the CPU will jump once the framework has + * initialised it + * context_id: Context identifier as defined by the PSCI specification + * + * Return: Return code of the PSCI CPU_ON call + * (refer to the PSCI specification for details) + */ +int32_t tftf_try_cpu_on(u_register_t target_cpu, + uintptr_t entrypoint, + u_register_t context_id); + +/* + * Power down the calling core. + * This uses the PSCI CPU_OFF API, which means it relies on the EL3 firmware's + * runtime services capabilities. + * + * Return: This function does not return when successful. + * Otherwise, return the same error code as the PSCI CPU_OFF call + * (refer to the PSCI specification for details) + */ +int32_t tftf_cpu_off(void); + +/* + * It is an Api used to enter a suspend state. It does the following: + * - Allocates space for saving architectural and non-architectural CPU state on + * stack + * - Saves architecture state of the CPU in the space allocated which consists: + * a. Callee registers + * b. System control registers. ex: MMU, SCTLR_EL1 + * - Depending on the state of `save_system_context` flag in suspend_info + * saves the context of system peripherals like GIC, timer etc. + * - Sets context ID to the base of the stack allocated for saving context + * - Calls Secure Platform Firmware to enter suspend + * - If suspend fails, It restores the callee registers + * power state: PSCI power state to be sent via SMC + * Returns: PSCI_E_SUCCESS or PSCI_E_INVALID_PARAMS + * + * Note: This api might not test all use cases, as the context ID and resume + * entrypoint is in the control of the framework. + */ +int tftf_suspend(const suspend_info_t *info); + + +/* ---------------------------------------------------------------------------- + * The above APIs might not be suitable in all test scenarios. + * A test case could want to bypass those APIs i.e. call the PSCI APIs + * directly. In this case, it is the responsibility of the test case to preserve + * the state of the framework. The below APIs are provided to this end. + * ---------------------------------------------------------------------------- + */ + +/* + * The 3 following functions are used to manipulate the reference count tracking + * the number of CPUs participating in a test. + */ + +/* + * Increment the reference count. + * Return the new, incremented value. + */ +unsigned int tftf_inc_ref_cnt(void); + +/* + * Decrement the reference count. + * Return the new, decremented value. + */ +unsigned int tftf_dec_ref_cnt(void); + +/* Return the current reference count value */ +unsigned int tftf_get_ref_cnt(void); + +/* + * Set the calling CPU online/offline. This only adjusts the view of the core + * from the framework's point of view, it doesn't actually power up/down the + * core. + */ +void tftf_set_cpu_online(void); +void tftf_init_cpus_status_map(void); +void tftf_set_cpu_offline(void); + +/* + * Query the state of a core. + * Return: 1 if the core is online, 0 otherwise. + */ +unsigned int tftf_is_cpu_online(unsigned int mpid); + +unsigned int tftf_is_core_pos_online(unsigned int core_pos); + +/* TFTF Suspend helpers */ +static inline int tftf_cpu_suspend(unsigned int pwr_state) +{ + suspend_info_t info = { + .power_state = pwr_state, + .save_system_context = 0, + .psci_api = SMC_PSCI_CPU_SUSPEND, + }; + + return tftf_suspend(&info); +} + +static inline int tftf_cpu_suspend_save_sys_ctx(unsigned int pwr_state) +{ + suspend_info_t info = { + .power_state = pwr_state, + .save_system_context = 1, + .psci_api = SMC_PSCI_CPU_SUSPEND, + }; + + return tftf_suspend(&info); +} + + +static inline int tftf_system_suspend(void) +{ + suspend_info_t info = { + .power_state = 0, + .save_system_context = 1, + .psci_api = SMC_PSCI_SYSTEM_SUSPEND, + }; + + return tftf_suspend(&info); +} + +#endif /* __POWER_MANAGEMENT_H__ */ diff --git a/include/lib/semihosting.h b/include/lib/semihosting.h new file mode 100644 index 000000000..9938a566c --- /dev/null +++ b/include/lib/semihosting.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SEMIHOSTING_H__ +#define __SEMIHOSTING_H__ + +#include <stdint.h> +#include <stdio.h> /* For ssize_t */ + + +#define SEMIHOSTING_SYS_OPEN 0x01 +#define SEMIHOSTING_SYS_CLOSE 0x02 +#define SEMIHOSTING_SYS_WRITE0 0x04 +#define SEMIHOSTING_SYS_WRITEC 0x03 +#define SEMIHOSTING_SYS_WRITE 0x05 +#define SEMIHOSTING_SYS_READ 0x06 +#define SEMIHOSTING_SYS_READC 0x07 +#define SEMIHOSTING_SYS_SEEK 0x0A +#define SEMIHOSTING_SYS_FLEN 0x0C +#define SEMIHOSTING_SYS_REMOVE 0x0E +#define SEMIHOSTING_SYS_SYSTEM 0x12 +#define SEMIHOSTING_SYS_ERRNO 0x13 + +#define FOPEN_MODE_R 0x0 +#define FOPEN_MODE_RB 0x1 +#define FOPEN_MODE_RPLUS 0x2 +#define FOPEN_MODE_RPLUSB 0x3 +#define FOPEN_MODE_W 0x4 +#define FOPEN_MODE_WB 0x5 +#define FOPEN_MODE_WPLUS 0x6 +#define FOPEN_MODE_WPLUSB 0x7 +#define FOPEN_MODE_A 0x8 +#define FOPEN_MODE_AB 0x9 +#define FOPEN_MODE_APLUS 0xa +#define FOPEN_MODE_APLUSB 0xb + +long semihosting_connection_supported(void); +long semihosting_file_open(const char *file_name, size_t mode); +long semihosting_file_seek(long file_handle, ssize_t offset); +long semihosting_file_read(long file_handle, size_t *length, uintptr_t buffer); +long semihosting_file_write(long file_handle, + size_t *length, + const uintptr_t buffer); +long semihosting_file_close(long file_handle); +long semihosting_file_length(long file_handle); +long semihosting_system(char *command_line); +long semihosting_get_flen(const char *file_name); +long semihosting_download_file(const char *file_name, + size_t buf_size, + uintptr_t buf); +void semihosting_write_char(char character); +void semihosting_write_string(char *string); +char semihosting_read_char(void); + +#endif /* __SEMIHOSTING_H__ */ diff --git a/include/lib/sgi.h b/include/lib/sgi.h new file mode 100644 index 000000000..d2f4b37f4 --- /dev/null +++ b/include/lib/sgi.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SGI_H__ +#define __SGI_H__ + +/* Data associated with the reception of an SGI */ +typedef struct { + /* Interrupt ID of the signaled interrupt */ + unsigned int irq_id; +} sgi_data_t; + +/* + * Send an SGI to a given core. + */ +void tftf_send_sgi(unsigned int sgi_id, unsigned int core_pos); + +#endif /* __SGI_H__ */ diff --git a/include/lib/spinlock.h b/include/lib/spinlock.h new file mode 100644 index 000000000..27ea7305e --- /dev/null +++ b/include/lib/spinlock.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SPINLOCK_H__ +#define __SPINLOCK_H__ + +typedef struct spinlock { + volatile unsigned int lock; +} spinlock_t; + +void init_spinlock(spinlock_t *lock); +void spin_lock(spinlock_t *lock); +void spin_unlock(spinlock_t *lock); + +#endif /* __SPINLOCK_H__ */ diff --git a/include/lib/status.h b/include/lib/status.h new file mode 100644 index 000000000..8cb61456d --- /dev/null +++ b/include/lib/status.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __STATUS_H__ +#define __STATUS_H__ + +/* Status Code definitions */ +#define STATUS_SUCCESS 0x00 +#define STATUS_INVALID_PARAMETER 0x01 +#define STATUS_UNSUPPORTED 0x02 +#define STATUS_OUT_OF_RESOURCES 0x03 +#define STATUS_NOT_FOUND 0x04 +#define STATUS_ABORTED 0x05 +#define STATUS_LOAD_ERROR 0x06 +#define STATUS_NEVER_RETURN 0x07 +#define STATUS_BUSY 0x08 +#define STATUS_NOT_INIT 0x09 +#define STATUS_BUFFER_TOO_SMALL 0x0A +#define STATUS_COMPROMISED_DATA 0x0B +#define STATUS_ALREADY_LOADED 0x0C +#define STATUS_FAIL 0x0D + +typedef unsigned int STATUS; + +#endif /* __STATUS_H__ */ diff --git a/include/lib/stdlib/assert.h b/include/lib/stdlib/assert.h new file mode 100644 index 000000000..1bcd1ead5 --- /dev/null +++ b/include/lib/stdlib/assert.h @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * @(#)assert.h 8.2 (Berkeley) 1/21/94 + * $FreeBSD$ + */ +/* + * Portions copyright (c) 2017, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef _ASSERT_H_ +#define _ASSERT_H_ + +#include <sys/cdefs.h> + +#if ENABLE_ASSERTIONS +#define _assert(e) assert(e) +#define assert(e) ((e) ? (void)0 : __assert(__func__, __FILE__, \ + __LINE__, #e)) +#else +#define assert(e) ((void)0) +#define _assert(e) ((void)0) +#endif /* ENABLE_ASSERTIONS */ + +__BEGIN_DECLS +void __assert(const char *, const char *, int, const char *) __dead2; +__END_DECLS + +#endif /* !_ASSERT_H_ */ diff --git a/include/lib/stdlib/machine/_limits.h b/include/lib/stdlib/machine/_limits.h new file mode 100644 index 000000000..bf9488693 --- /dev/null +++ b/include/lib/stdlib/machine/_limits.h @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifdef AARCH64 +# include <machine/aarch64/_limits.h> +#else /* AARCH32 */ +# include <machine/aarch32/_limits.h> +#endif diff --git a/include/lib/stdlib/machine/_stdint.h b/include/lib/stdlib/machine/_stdint.h new file mode 100644 index 000000000..d8f38ff88 --- /dev/null +++ b/include/lib/stdlib/machine/_stdint.h @@ -0,0 +1,192 @@ +/*- + * Copyright (c) 2001, 2002 Mike Barcroft <mike@FreeBSD.org> + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Klaus Klein. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + * + * $FreeBSD$ + */ + +/* + * Portions copyright (c) 2016, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef _MACHINE__STDINT_H_ +#define _MACHINE__STDINT_H_ + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) + +#define INT8_C(c) (c) +#define INT16_C(c) (c) +#define INT32_C(c) (c) +#define INT64_C(c) (c ## LL) + +#define UINT8_C(c) (c) +#define UINT16_C(c) (c) +#define UINT32_C(c) (c ## U) +#define UINT64_C(c) (c ## ULL) + +#define INTMAX_C(c) INT64_C(c) +#define UINTMAX_C(c) UINT64_C(c) + +#endif /* !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) */ + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) + +/* + * ISO/IEC 9899:1999 + * 7.18.2.1 Limits of exact-width integer types + */ +/* Minimum values of exact-width signed integer types. */ +#define INT8_MIN (-0x7f-1) +#define INT16_MIN (-0x7fff-1) +#define INT32_MIN (-0x7fffffff-1) +#define INT64_MIN (-0x7fffffffffffffffLL-1) + +/* Maximum values of exact-width signed integer types. */ +#define INT8_MAX 0x7f +#define INT16_MAX 0x7fff +#define INT32_MAX 0x7fffffff +#define INT64_MAX 0x7fffffffffffffffLL + +/* Maximum values of exact-width unsigned integer types. */ +#define UINT8_MAX 0xff +#define UINT16_MAX 0xffff +#define UINT32_MAX 0xffffffffU +#define UINT64_MAX 0xffffffffffffffffULL + +/* + * ISO/IEC 9899:1999 + * 7.18.2.2 Limits of minimum-width integer types + */ +/* Minimum values of minimum-width signed integer types. */ +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +/* Maximum values of minimum-width signed integer types. */ +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +/* Maximum values of minimum-width unsigned integer types. */ +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* + * ISO/IEC 9899:1999 + * 7.18.2.3 Limits of fastest minimum-width integer types + */ +/* Minimum values of fastest minimum-width signed integer types. */ +#define INT_FAST8_MIN INT32_MIN +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST64_MIN INT64_MIN + +/* Maximum values of fastest minimum-width signed integer types. */ +#define INT_FAST8_MAX INT32_MAX +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MAX INT64_MAX + +/* Maximum values of fastest minimum-width unsigned integer types. */ +#define UINT_FAST8_MAX UINT32_MAX +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX +/* + * ISO/IEC 9899:1999 + * 7.18.2.5 Limits of greatest-width integer types + */ +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +#ifdef AARCH64 +/* + * ISO/IEC 9899:1999 + * 7.18.2.4 Limits of integer types capable of holding object pointers + */ +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX + +/* + * ISO/IEC 9899:1999 + * 7.18.3 Limits of other integer types + */ +/* Limits of ptrdiff_t. */ +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX + +/* Limit of size_t. */ +#define SIZE_MAX UINT64_MAX + +#else /* AARCH32 */ +/* + * ISO/IEC 9899:1999 + * 7.18.2.4 Limits of integer types capable of holding object pointers + */ +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX + +/* + * ISO/IEC 9899:1999 + * 7.18.3 Limits of other integer types + */ +/* Limits of ptrdiff_t. */ +#define PTRDIFF_MIN INT32_MIN +#define PTRDIFF_MAX INT32_MAX + +/* Limit of size_t. */ +#define SIZE_MAX UINT32_MAX + +#endif /* AARCH64 */ + + +/* Limits of sig_atomic_t. */ +#define SIG_ATOMIC_MIN INT32_MIN +#define SIG_ATOMIC_MAX INT32_MAX + +#ifndef WCHAR_MIN /* Also possibly defined in <wchar.h> */ +/* Limits of wchar_t. */ +#define WCHAR_MIN INT32_MIN +#define WCHAR_MAX INT32_MAX +#endif + +/* Limits of wint_t. */ +#define WINT_MIN INT32_MIN +#define WINT_MAX INT32_MAX + +#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */ + +#endif /* !_MACHINE__STDINT_H_ */ diff --git a/include/lib/stdlib/machine/_types.h b/include/lib/stdlib/machine/_types.h new file mode 100644 index 000000000..037fdf2f3 --- /dev/null +++ b/include/lib/stdlib/machine/_types.h @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org> + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * From: @(#)ansi.h 8.2 (Berkeley) 1/4/94 + * From: @(#)types.h 8.3 (Berkeley) 1/5/94 + * $FreeBSD$ + */ +/* + * Portions copyright (c) 2016, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +#ifndef _SYS_CDEFS_H_ +#error this file needs sys/cdefs.h as a prerequisite +#endif + +/* + * Basic types upon which most other types are built. + */ +typedef __signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +typedef long long __int64_t; +typedef unsigned long long __uint64_t; + +/* + * Standard type definitions. + */ +typedef __int32_t __clock_t; /* clock()... */ +typedef long __critical_t; +typedef double __double_t; +typedef float __float_t; +typedef long __intfptr_t; +typedef __int64_t __intmax_t; +typedef long __intptr_t; +typedef __int32_t __int_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __int8_t __int_least8_t; +typedef __int16_t __int_least16_t; +typedef __int32_t __int_least32_t; +typedef __int64_t __int_least64_t; +typedef long __ptrdiff_t; /* ptr1 - ptr2 */ +typedef long __register_t; +typedef long __segsz_t; /* segment size (in pages) */ +#ifdef AARCH32 +typedef unsigned int __size_t; /* sizeof() */ +typedef int __ssize_t; /* byte count or error */ +#elif defined AARCH64 +typedef unsigned long __size_t; /* sizeof() */ +typedef long __ssize_t; /* byte count or error */ +#else +#error "Only AArch32 or AArch64 supported" +#endif /* AARCH32 */ +typedef __int64_t __time_t; /* time()... */ +typedef unsigned long __uintfptr_t; +typedef __uint64_t __uintmax_t; +typedef unsigned long __uintptr_t; +typedef __uint32_t __uint_fast8_t; +typedef __uint32_t __uint_fast16_t; +typedef __uint32_t __uint_fast32_t; +typedef __uint64_t __uint_fast64_t; +typedef __uint8_t __uint_least8_t; +typedef __uint16_t __uint_least16_t; +typedef __uint32_t __uint_least32_t; +typedef __uint64_t __uint_least64_t; +typedef unsigned long __u_register_t; +typedef unsigned long __vm_offset_t; +typedef __int64_t __vm_ooffset_t; +typedef unsigned long __vm_paddr_t; +typedef __uint64_t __vm_pindex_t; +typedef unsigned long __vm_size_t; + +/* + * Unusual type definitions. + */ +#ifdef __GNUCLIKE_BUILTIN_VARARGS +typedef __builtin_va_list __va_list; /* internally known to gcc */ +#else +typedef char * __va_list; +#endif /* __GNUCLIKE_BUILTIN_VARARGS */ +#if defined(__GNUCLIKE_BUILTIN_VAALIST) && !defined(__GNUC_VA_LIST) \ + && !defined(__NO_GNUC_VA_LIST) +#define __GNUC_VA_LIST +typedef __va_list __gnuc_va_list; /* compatibility w/GNU headers*/ +#endif + +#endif /* !_MACHINE__TYPES_H_ */ diff --git a/include/lib/stdlib/machine/aarch32/_limits.h b/include/lib/stdlib/machine/aarch32/_limits.h new file mode 100644 index 000000000..fe816e50f --- /dev/null +++ b/include/lib/stdlib/machine/aarch32/_limits.h @@ -0,0 +1,89 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * @(#)limits.h 8.3 (Berkeley) 1/4/94 + * $FreeBSD$ + */ + +#ifndef _MACHINE__LIMITS_H_ +#define _MACHINE__LIMITS_H_ + +/* + * According to ANSI (section 2.2.4.2), the values below must be usable by + * #if preprocessing directives. Additionally, the expression must have the + * same type as would an expression that is an object of the corresponding + * type converted according to the integral promotions. The subtraction for + * INT_MIN, etc., is so the value is not unsigned; e.g., 0x80000000 is an + * unsigned int for 32-bit two's complement ANSI compilers (section 3.1.3.2). + */ + +#define __CHAR_BIT 8 /* number of bits in a char */ + +#define __SCHAR_MAX 0x7f /* max value for a signed char */ +#define __SCHAR_MIN (-0x7f - 1) /* min value for a signed char */ + +#define __UCHAR_MAX 0xff /* max value for an unsigned char */ + +#define __USHRT_MAX 0xffff /* max value for an unsigned short */ +#define __SHRT_MAX 0x7fff /* max value for a short */ +#define __SHRT_MIN (-0x7fff - 1) /* min value for a short */ + +#define __UINT_MAX 0xffffffff /* max value for an unsigned int */ +#define __INT_MAX 0x7fffffff /* max value for an int */ +#define __INT_MIN (-0x7fffffff - 1) /* min value for an int */ + +#define __ULONG_MAX 0xffffffffUL /* max value for an unsigned long */ +#define __LONG_MAX 0x7fffffffL /* max value for a long */ +#define __LONG_MIN (-0x7fffffffL - 1) /* min value for a long */ + + /* max value for an unsigned long long */ +#define __ULLONG_MAX 0xffffffffffffffffULL +#define __LLONG_MAX 0x7fffffffffffffffLL /* max value for a long long */ +#define __LLONG_MIN (-0x7fffffffffffffffLL - 1) /* min for a long long */ + +#define __SSIZE_MAX __INT_MAX /* max value for a ssize_t */ + +#define __SIZE_T_MAX __UINT_MAX /* max value for a size_t */ + +#define __OFF_MAX __LLONG_MAX /* max value for a off_t */ +#define __OFF_MIN __LLONG_MIN /* min value for a off_t */ + +/* Quads and long longs are the same size. Ensure they stay in sync. */ +#define __UQUAD_MAX __ULLONG_MAX /* max value for a uquad_t */ +#define __QUAD_MAX __LLONG_MAX /* max value for a quad_t */ +#define __QUAD_MIN __LLONG_MIN /* min value for a quad_t */ + +#define __LONG_BIT 32 +#define __WORD_BIT 32 + +/* Minimum signal stack size. */ +#define __MINSIGSTKSZ (1024 * 4) + +#endif /* !_MACHINE__LIMITS_H_ */ diff --git a/include/lib/stdlib/machine/aarch64/_limits.h b/include/lib/stdlib/machine/aarch64/_limits.h new file mode 100644 index 000000000..39f0bcf0f --- /dev/null +++ b/include/lib/stdlib/machine/aarch64/_limits.h @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * @(#)limits.h 8.3 (Berkeley) 1/4/94 + * $FreeBSD$ + */ + +#ifndef _MACHINE__LIMITS_H_ +#define _MACHINE__LIMITS_H_ + +/* + * According to ANSI (section 2.2.4.2), the values below must be usable by + * #if preprocessing directives. Additionally, the expression must have the + * same type as would an expression that is an object of the corresponding + * type converted according to the integral promotions. The subtraction for + * INT_MIN, etc., is so the value is not unsigned; e.g., 0x80000000 is an + * unsigned int for 32-bit two's complement ANSI compilers (section 3.1.3.2). + */ + +#define __CHAR_BIT 8 /* number of bits in a char */ + +#define __SCHAR_MAX 0x7f /* max value for a signed char */ +#define __SCHAR_MIN (-0x7f - 1) /* min value for a signed char */ + +#define __UCHAR_MAX 0xff /* max value for an unsigned char */ + +#define __USHRT_MAX 0xffff /* max value for an unsigned short */ +#define __SHRT_MAX 0x7fff /* max value for a short */ +#define __SHRT_MIN (-0x7fff - 1) /* min value for a short */ + +#define __UINT_MAX 0xffffffff /* max value for an unsigned int */ +#define __INT_MAX 0x7fffffff /* max value for an int */ +#define __INT_MIN (-0x7fffffff - 1) /* min value for an int */ + +#define __ULONG_MAX 0xffffffffffffffffUL /* max for an unsigned long */ +#define __LONG_MAX 0x7fffffffffffffffL /* max for a long */ +#define __LONG_MIN (-0x7fffffffffffffffL - 1) /* min for a long */ + +/* Long longs have the same size but not the same type as longs. */ + /* max for an unsigned long long */ +#define __ULLONG_MAX 0xffffffffffffffffULL +#define __LLONG_MAX 0x7fffffffffffffffLL /* max for a long long */ +#define __LLONG_MIN (-0x7fffffffffffffffLL - 1) /* min for a long long */ + +#define __SSIZE_MAX __LONG_MAX /* max value for a ssize_t */ + +#define __SIZE_T_MAX __ULONG_MAX /* max value for a size_t */ + +#define __OFF_MAX __LONG_MAX /* max value for an off_t */ +#define __OFF_MIN __LONG_MIN /* min value for an off_t */ + +/* Quads and longs are the same size. Ensure they stay in sync. */ +#define __UQUAD_MAX (__ULONG_MAX) /* max value for a uquad_t */ +#define __QUAD_MAX (__LONG_MAX) /* max value for a quad_t */ +#define __QUAD_MIN (__LONG_MIN) /* min value for a quad_t */ + +#define __LONG_BIT 64 +#define __WORD_BIT 32 + +/* Minimum signal stack size. */ +#define __MINSIGSTKSZ (1024 * 4) + +#endif /* !_MACHINE__LIMITS_H_ */ diff --git a/include/lib/stdlib/stdbool.h b/include/lib/stdlib/stdbool.h new file mode 100644 index 000000000..e39aef7d3 --- /dev/null +++ b/include/lib/stdlib/stdbool.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STDBOOL_H +#define STDBOOL_H + +#define bool _Bool + +#define true 1 +#define false 0 + +#define __bool_true_false_are_defined 1 + +#endif /* STDBOOL_H */ diff --git a/include/lib/stdlib/stddef.h b/include/lib/stdlib/stddef.h new file mode 100644 index 000000000..ea88214f7 --- /dev/null +++ b/include/lib/stdlib/stddef.h @@ -0,0 +1,64 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * @(#)stddef.h 8.1 (Berkeley) 6/2/93 + * + * $FreeBSD$ + */ + +#ifndef _STDDEF_H_ +#define _STDDEF_H_ + +#include <sys/cdefs.h> +#include <sys/_null.h> +#include <sys/_types.h> + +typedef __ptrdiff_t ptrdiff_t; + +#if __BSD_VISIBLE +#ifndef _RUNE_T_DECLARED +typedef __rune_t rune_t; +#define _RUNE_T_DECLARED +#endif +#endif + +#ifndef _SIZE_T_DECLARED +typedef __size_t size_t; +#define _SIZE_T_DECLARED +#endif + +#ifndef __cplusplus +#ifndef _WCHAR_T_DECLARED +typedef __wchar_t wchar_t; +#define _WCHAR_T_DECLARED +#endif +#endif + +#define offsetof(type, member) __offsetof(type, member) + +#endif /* _STDDEF_H_ */ diff --git a/include/lib/stdlib/stdio.h b/include/lib/stdlib/stdio.h new file mode 100644 index 000000000..80110a8b4 --- /dev/null +++ b/include/lib/stdlib/stdio.h @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * @(#)stdio.h 8.5 (Berkeley) 4/29/95 + * $FreeBSD$ + */ + +/* + * Portions copyright (c) 2013-2014, ARM Limited and Contributors. + * All rights reserved. + */ + + +#ifndef _STDIO_H_ +#define _STDIO_H_ + +#include <sys/cdefs.h> +#include <sys/_null.h> +#include <sys/_types.h> + +#ifndef _SIZE_T_DECLARED +typedef __size_t size_t; +#define _SIZE_T_DECLARED +#endif + +#ifndef _SSIZE_T_DECLARED +#define _SSIZE_T_DECLARED +typedef __ssize_t ssize_t; +#endif + +#define EOF (-1) + +int printf(const char * __restrict, ...) __printflike(1, 2); +int putchar(int); +int puts(const char *); +int sprintf(char * __restrict, const char * __restrict, ...) + __printflike(2, 3); +int vsprintf(char * __restrict, const char * __restrict, + __va_list) __printflike(2, 0); + +#if __ISO_C_VISIBLE >= 1999 +int snprintf(char * __restrict, size_t, const char * __restrict, + ...) __printflike(3, 4); +int vsnprintf(char * __restrict, size_t, const char * __restrict, + __va_list) __printflike(3, 0); +#endif + +#endif /* !_STDIO_H_ */ diff --git a/include/lib/stdlib/stdlib.h b/include/lib/stdlib/stdlib.h new file mode 100644 index 000000000..c02532f7a --- /dev/null +++ b/include/lib/stdlib/stdlib.h @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * @(#)stdlib.h 8.5 (Berkeley) 5/19/95 + * $FreeBSD$ + */ + +/* + * Portions copyright (c) 2014, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef _STDLIB_H_ +#define _STDLIB_H_ + +#include <sys/cdefs.h> +#include <sys/_null.h> +#include <sys/_types.h> + +#define RAND_MAX 0x7ffffffd + +__BEGIN_DECLS + +int rand(void); +void srand(unsigned); + +__END_DECLS + +#endif /* !_STDLIB_H_ */ diff --git a/include/lib/stdlib/string.h b/include/lib/stdlib/string.h new file mode 100644 index 000000000..5d3046721 --- /dev/null +++ b/include/lib/stdlib/string.h @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * @(#)string.h 8.1 (Berkeley) 6/2/93 + * $FreeBSD$ + */ + +/* + * Portions copyright (c) 2013-2014, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef _STRING_H_ +#define _STRING_H_ + +#include <sys/cdefs.h> +#include <sys/_null.h> +#include <sys/_types.h> + +#ifndef _SIZE_T_DECLARED +typedef __size_t size_t; +#define _SIZE_T_DECLARED +#endif + +__BEGIN_DECLS + +void *memchr(const void *, int, size_t) __pure; +int memcmp(const void *, const void *, size_t) __pure; +void *memcpy(void * __restrict, const void * __restrict, size_t); +void *memmove(void *, const void *, size_t); +void *memset(void *, int, size_t); + +char *strchr(const char *, int) __pure; +int strcmp(const char *, const char *) __pure; +size_t strlen(const char *) __pure; +int strncmp(const char *, const char *, size_t) __pure; +char *strncpy(char * __restrict, const char * __restrict, size_t); + +__END_DECLS + +#endif /* _STRING_H_ */ diff --git a/include/lib/stdlib/sys/_null.h b/include/lib/stdlib/sys/_null.h new file mode 100644 index 000000000..92706c6a0 --- /dev/null +++ b/include/lib/stdlib/sys/_null.h @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2003 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef NULL + +#if !defined(__cplusplus) +#define NULL ((void *)0) +#else +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__GNUG__) && defined(__GNUC__) && __GNUC__ >= 4 +#define NULL __null +#else +#if defined(__LP64__) +#define NULL (0L) +#else +#define NULL 0 +#endif /* __LP64__ */ +#endif /* __GNUG__ */ +#endif /* !__cplusplus */ + +#endif diff --git a/include/lib/stdlib/sys/_stdint.h b/include/lib/stdlib/sys/_stdint.h new file mode 100644 index 000000000..d0f92493b --- /dev/null +++ b/include/lib/stdlib/sys/_stdint.h @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2011 David E. O'Brien <obrien@FreeBSD.org> + * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _SYS__STDINT_H_ +#define _SYS__STDINT_H_ + +#ifndef _INT8_T_DECLARED +typedef __int8_t int8_t; +#define _INT8_T_DECLARED +#endif + +#ifndef _INT16_T_DECLARED +typedef __int16_t int16_t; +#define _INT16_T_DECLARED +#endif + +#ifndef _INT32_T_DECLARED +typedef __int32_t int32_t; +#define _INT32_T_DECLARED +#endif + +#ifndef _INT64_T_DECLARED +typedef __int64_t int64_t; +#define _INT64_T_DECLARED +#endif + +#ifndef _UINT8_T_DECLARED +typedef __uint8_t uint8_t; +#define _UINT8_T_DECLARED +#endif + +#ifndef _UINT16_T_DECLARED +typedef __uint16_t uint16_t; +#define _UINT16_T_DECLARED +#endif + +#ifndef _UINT32_T_DECLARED +typedef __uint32_t uint32_t; +#define _UINT32_T_DECLARED +#endif + +#ifndef _UINT64_T_DECLARED +typedef __uint64_t uint64_t; +#define _UINT64_T_DECLARED +#endif + +#ifndef _INTPTR_T_DECLARED +typedef __intptr_t intptr_t; +#define _INTPTR_T_DECLARED +#endif +#ifndef _UINTPTR_T_DECLARED +typedef __uintptr_t uintptr_t; +#define _UINTPTR_T_DECLARED +#endif + +#endif /* !_SYS__STDINT_H_ */ diff --git a/include/lib/stdlib/sys/_types.h b/include/lib/stdlib/sys/_types.h new file mode 100644 index 000000000..c59afd31c --- /dev/null +++ b/include/lib/stdlib/sys/_types.h @@ -0,0 +1,106 @@ +/*- + * Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _SYS__TYPES_H_ +#define _SYS__TYPES_H_ + +#include <sys/cdefs.h> +#include <machine/_types.h> + +/* + * Standard type definitions. + */ +typedef __uint32_t __blksize_t; /* file block size */ +typedef __int64_t __blkcnt_t; /* file block count */ +typedef __int32_t __clockid_t; /* clock_gettime()... */ +typedef __uint64_t __cap_rights_t; /* capability rights */ +typedef __uint32_t __fflags_t; /* file flags */ +typedef __uint64_t __fsblkcnt_t; +typedef __uint64_t __fsfilcnt_t; +typedef __uint32_t __gid_t; +typedef __int64_t __id_t; /* can hold a gid_t, pid_t, or uid_t */ +typedef __uint32_t __ino_t; /* inode number */ +typedef long __key_t; /* IPC key (for Sys V IPC) */ +typedef __int32_t __lwpid_t; /* Thread ID (a.k.a. LWP) */ +typedef __uint16_t __mode_t; /* permissions */ +typedef int __accmode_t; /* access permissions */ +typedef int __nl_item; +typedef __uint16_t __nlink_t; /* link count */ +typedef __int64_t __off_t; /* file offset */ +typedef __int32_t __pid_t; /* process [group] */ +typedef __int64_t __rlim_t; /* resource limit - intentionally */ + /* signed, because of legacy code */ + /* that uses -1 for RLIM_INFINITY */ +typedef __uint8_t __sa_family_t; +typedef __uint32_t __socklen_t; +typedef long __suseconds_t; /* microseconds (signed) */ +typedef struct __timer *__timer_t; /* timer_gettime()... */ +typedef struct __mq *__mqd_t; /* mq_open()... */ +typedef __uint32_t __uid_t; +typedef unsigned int __useconds_t; /* microseconds (unsigned) */ +typedef int __cpuwhich_t; /* which parameter for cpuset. */ +typedef int __cpulevel_t; /* level parameter for cpuset. */ +typedef int __cpusetid_t; /* cpuset identifier. */ + +/* + * Unusual type definitions. + */ +/* + * rune_t is declared to be an ``int'' instead of the more natural + * ``unsigned long'' or ``long''. Two things are happening here. It is not + * unsigned so that EOF (-1) can be naturally assigned to it and used. Also, + * it looks like 10646 will be a 31 bit standard. This means that if your + * ints cannot hold 32 bits, you will be in trouble. The reason an int was + * chosen over a long is that the is*() and to*() routines take ints (says + * ANSI C), but they use __ct_rune_t instead of int. + * + * NOTE: rune_t is not covered by ANSI nor other standards, and should not + * be instantiated outside of lib/libc/locale. Use wchar_t. wchar_t and + * rune_t must be the same type. Also, wint_t must be no narrower than + * wchar_t, and should be able to hold all members of the largest + * character set plus one extra value (WEOF), and must be at least 16 bits. + */ +typedef int __ct_rune_t; /* arg type for ctype funcs */ +typedef __ct_rune_t __rune_t; /* rune_t (see above) */ +typedef __ct_rune_t __wchar_t; /* wchar_t (see above) */ +typedef __ct_rune_t __wint_t; /* wint_t (see above) */ + +typedef __uint32_t __dev_t; /* device number */ + +typedef __uint32_t __fixpt_t; /* fixed point number */ + +/* + * mbstate_t is an opaque object to keep conversion state during multibyte + * stream conversions. + */ +typedef union { + char __mbstate8[128]; + __int64_t _mbstateL; /* for alignment */ +} __mbstate_t; + +#endif /* !_SYS__TYPES_H_ */ diff --git a/include/lib/stdlib/sys/cdefs.h b/include/lib/stdlib/sys/cdefs.h new file mode 100644 index 000000000..16fb15190 --- /dev/null +++ b/include/lib/stdlib/sys/cdefs.h @@ -0,0 +1,686 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Berkeley Software Design, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * @(#)cdefs.h 8.8 (Berkeley) 1/9/95 + * $FreeBSD$ + */ + +#ifndef _SYS_CDEFS_H_ +#define _SYS_CDEFS_H_ + +#if defined(__cplusplus) +#define __BEGIN_DECLS extern "C" { +#define __END_DECLS } +#else +#define __BEGIN_DECLS +#define __END_DECLS +#endif + +/* + * This code has been put in place to help reduce the addition of + * compiler specific defines in FreeBSD code. It helps to aid in + * having a compiler-agnostic source tree. + */ + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) + +#if __GNUC__ >= 3 || defined(__INTEL_COMPILER) +#define __GNUCLIKE_ASM 3 +#define __GNUCLIKE_MATH_BUILTIN_CONSTANTS +#else +#define __GNUCLIKE_ASM 2 +#endif +#define __GNUCLIKE___TYPEOF 1 +#define __GNUCLIKE___OFFSETOF 1 +#define __GNUCLIKE___SECTION 1 + +#ifndef __INTEL_COMPILER +# define __GNUCLIKE_CTOR_SECTION_HANDLING 1 +#endif + +#define __GNUCLIKE_BUILTIN_CONSTANT_P 1 +# if defined(__INTEL_COMPILER) && defined(__cplusplus) \ + && __INTEL_COMPILER < 800 +# undef __GNUCLIKE_BUILTIN_CONSTANT_P +# endif + +#if (__GNUC_MINOR__ > 95 || __GNUC__ >= 3) && !defined(__INTEL_COMPILER) +# define __GNUCLIKE_BUILTIN_VARARGS 1 +# define __GNUCLIKE_BUILTIN_STDARG 1 +# define __GNUCLIKE_BUILTIN_VAALIST 1 +#endif + +#if defined(__GNUC__) +# define __GNUC_VA_LIST_COMPATIBILITY 1 +#endif + +#ifndef __INTEL_COMPILER +# define __GNUCLIKE_BUILTIN_NEXT_ARG 1 +# define __GNUCLIKE_MATH_BUILTIN_RELOPS +#endif + +#define __GNUCLIKE_BUILTIN_MEMCPY 1 + +/* XXX: if __GNUC__ >= 2: not tested everywhere originally, where replaced */ +#define __CC_SUPPORTS_INLINE 1 +#define __CC_SUPPORTS___INLINE 1 +#define __CC_SUPPORTS___INLINE__ 1 + +#define __CC_SUPPORTS___FUNC__ 1 +#define __CC_SUPPORTS_WARNING 1 + +#define __CC_SUPPORTS_VARADIC_XXX 1 /* see varargs.h */ + +#define __CC_SUPPORTS_DYNAMIC_ARRAY_INIT 1 + +#endif /* __GNUC__ || __INTEL_COMPILER */ + +/* + * Macro to test if we're using a specific version of gcc or later. + */ +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) +#define __GNUC_PREREQ__(ma, mi) \ + (__GNUC__ > (ma) || __GNUC__ == (ma) && __GNUC_MINOR__ >= (mi)) +#else +#define __GNUC_PREREQ__(ma, mi) 0 +#endif + +/* + * The __CONCAT macro is used to concatenate parts of symbol names, e.g. + * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo. + * The __CONCAT macro is a bit tricky to use if it must work in non-ANSI + * mode -- there must be no spaces between its arguments, and for nested + * __CONCAT's, all the __CONCAT's must be at the left. __CONCAT can also + * concatenate double-quoted strings produced by the __STRING macro, but + * this only works with ANSI C. + * + * __XSTRING is like __STRING, but it expands any macros in its argument + * first. It is only available with ANSI C. + */ +#if defined(__STDC__) || defined(__cplusplus) +#define __P(protos) protos /* full-blown ANSI C */ +#define __CONCAT1(x,y) x ## y +#define __CONCAT(x,y) __CONCAT1(x,y) +#define __STRING(x) #x /* stringify without expanding x */ +#define __XSTRING(x) __STRING(x) /* expand x, then stringify */ + +#define __const const /* define reserved names to standard */ +#define __signed signed +#define __volatile volatile +#if defined(__cplusplus) +#define __inline inline /* convert to C++ keyword */ +#else +#if !(defined(__CC_SUPPORTS___INLINE)) +#define __inline /* delete GCC keyword */ +#endif /* ! __CC_SUPPORTS___INLINE */ +#endif /* !__cplusplus */ + +#else /* !(__STDC__ || __cplusplus) */ +#define __P(protos) () /* traditional C preprocessor */ +#define __CONCAT(x,y) x/**/y +#define __STRING(x) "x" + +#if !defined(__CC_SUPPORTS___INLINE) +#define __const /* delete pseudo-ANSI C keywords */ +#define __inline +#define __signed +#define __volatile +/* + * In non-ANSI C environments, new programs will want ANSI-only C keywords + * deleted from the program and old programs will want them left alone. + * When using a compiler other than gcc, programs using the ANSI C keywords + * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS. + * When using "gcc -traditional", we assume that this is the intent; if + * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone. + */ +#ifndef NO_ANSI_KEYWORDS +#define const /* delete ANSI C keywords */ +#define inline +#define signed +#define volatile +#endif /* !NO_ANSI_KEYWORDS */ +#endif /* !__CC_SUPPORTS___INLINE */ +#endif /* !(__STDC__ || __cplusplus) */ + +/* + * Compiler-dependent macros to help declare dead (non-returning) and + * pure (no side effects) functions, and unused variables. They are + * null except for versions of gcc that are known to support the features + * properly (old versions of gcc-2 supported the dead and pure features + * in a different (wrong) way). If we do not provide an implementation + * for a given compiler, let the compile fail if it is told to use + * a feature that we cannot live without. + */ +#ifdef lint +#define __dead2 +#define __pure2 +#define __unused +#define __packed +#define __aligned(x) +#define __section(x) +#else +#if !__GNUC_PREREQ__(2, 5) && !defined(__INTEL_COMPILER) +#define __dead2 +#define __pure2 +#define __unused +#endif +#if __GNUC__ == 2 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 7 && !defined(__INTEL_COMPILER) +#define __dead2 __attribute__((__noreturn__)) +#define __pure2 __attribute__((__const__)) +#define __unused +/* XXX Find out what to do for __packed, __aligned and __section */ +#endif +#if __GNUC_PREREQ__(2, 7) +#define __dead2 __attribute__((__noreturn__)) +#define __pure2 __attribute__((__const__)) +#define __unused __attribute__((__unused__)) +#define __used __attribute__((__used__)) +#define __packed __attribute__((__packed__)) +#define __aligned(x) __attribute__((__aligned__(x))) +#define __section(x) __attribute__((__section__(x))) +#endif +#if defined(__INTEL_COMPILER) +#define __dead2 __attribute__((__noreturn__)) +#define __pure2 __attribute__((__const__)) +#define __unused __attribute__((__unused__)) +#define __used __attribute__((__used__)) +#define __packed __attribute__((__packed__)) +#define __aligned(x) __attribute__((__aligned__(x))) +#define __section(x) __attribute__((__section__(x))) +#endif +#endif + +#if !__GNUC_PREREQ__(2, 95) +#define __alignof(x) __offsetof(struct { char __a; x __b; }, __b) +#endif + +/* + * Keywords added in C11. + */ +#if defined(__cplusplus) && __cplusplus >= 201103L +#define _Alignas(e) alignas(e) +#define _Alignof(e) alignof(e) +#define _Noreturn [[noreturn]] +#define _Static_assert(e, s) static_assert(e, s) +/* FIXME: change this to thread_local when clang in base supports it */ +#define _Thread_local __thread +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +/* Do nothing. They are language keywords. */ +#else +/* Not supported. Implement them using our versions. */ +#define _Alignas(x) __aligned(x) +#define _Alignof(x) __alignof(x) +#define _Noreturn __dead2 +#define _Thread_local __thread +#ifdef __COUNTER__ +#define _Static_assert(x, y) __Static_assert(x, __COUNTER__) +#define __Static_assert(x, y) ___Static_assert(x, y) +#define ___Static_assert(x, y) typedef char __assert_ ## y[(x) ? 1 : -1] +#else +#define _Static_assert(x, y) struct __hack +#endif +#endif + +/* + * Emulation of C11 _Generic(). Unlike the previously defined C11 + * keywords, it is not possible to implement this using exactly the same + * syntax. Therefore implement something similar under the name + * __generic(). Unlike _Generic(), this macro can only distinguish + * between a single type, so it requires nested invocations to + * distinguish multiple cases. + */ + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#define __generic(expr, t, yes, no) \ + _Generic(expr, t: yes, default: no) +#elif __GNUC_PREREQ__(3, 1) && !defined(__cplusplus) +#define __generic(expr, t, yes, no) \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof(expr), t), yes, no) +#endif + +#if __GNUC_PREREQ__(2, 96) +#define __malloc_like __attribute__((__malloc__)) +#define __pure __attribute__((__pure__)) +#else +#define __malloc_like +#define __pure +#endif + +#if __GNUC_PREREQ__(3, 1) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 800) +#define __always_inline __attribute__((__always_inline__)) +#else +#define __always_inline +#endif + +#if __GNUC_PREREQ__(3, 1) +#define __noinline __attribute__ ((__noinline__)) +#else +#define __noinline +#endif + +#if __GNUC_PREREQ__(3, 3) +#define __nonnull(x) __attribute__((__nonnull__(x))) +#else +#define __nonnull(x) +#endif + +#if __GNUC_PREREQ__(3, 4) +#define __fastcall __attribute__((__fastcall__)) +#else +#define __fastcall +#endif + +#if __GNUC_PREREQ__(4, 1) +#define __returns_twice __attribute__((__returns_twice__)) +#else +#define __returns_twice +#endif + +/* XXX: should use `#if __STDC_VERSION__ < 199901'. */ +#if !__GNUC_PREREQ__(2, 7) && !defined(__INTEL_COMPILER) +#define __func__ NULL +#endif + +#if (defined(__INTEL_COMPILER) || (defined(__GNUC__) && __GNUC__ >= 2)) && !defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901 +#define __LONG_LONG_SUPPORTED +#endif + +/* C++11 exposes a load of C99 stuff */ +#if defined(__cplusplus) && __cplusplus >= 201103L +#define __LONG_LONG_SUPPORTED +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +#define __STDC_CONSTANT_MACROS +#endif +#endif + +/* + * GCC 2.95 provides `__restrict' as an extension to C90 to support the + * C99-specific `restrict' type qualifier. We happen to use `__restrict' as + * a way to define the `restrict' type qualifier without disturbing older + * software that is unaware of C99 keywords. + */ +#if !(__GNUC__ == 2 && __GNUC_MINOR__ == 95) +#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901 || defined(lint) +#define __restrict +#else +#define __restrict restrict +#endif +#endif + +/* + * GNU C version 2.96 adds explicit branch prediction so that + * the CPU back-end can hint the processor and also so that + * code blocks can be reordered such that the predicted path + * sees a more linear flow, thus improving cache behavior, etc. + * + * The following two macros provide us with a way to utilize this + * compiler feature. Use __predict_true() if you expect the expression + * to evaluate to true, and __predict_false() if you expect the + * expression to evaluate to false. + * + * A few notes about usage: + * + * * Generally, __predict_false() error condition checks (unless + * you have some _strong_ reason to do otherwise, in which case + * document it), and/or __predict_true() `no-error' condition + * checks, assuming you want to optimize for the no-error case. + * + * * Other than that, if you don't know the likelihood of a test + * succeeding from empirical or other `hard' evidence, don't + * make predictions. + * + * * These are meant to be used in places that are run `a lot'. + * It is wasteful to make predictions in code that is run + * seldomly (e.g. at subsystem initialization time) as the + * basic block reordering that this affects can often generate + * larger code. + */ +#if __GNUC_PREREQ__(2, 96) +#define __predict_true(exp) __builtin_expect((exp), 1) +#define __predict_false(exp) __builtin_expect((exp), 0) +#else +#define __predict_true(exp) (exp) +#define __predict_false(exp) (exp) +#endif + +#if __GNUC_PREREQ__(4, 2) +#define __hidden __attribute__((__visibility__("hidden"))) +#define __exported __attribute__((__visibility__("default"))) +#else +#define __hidden +#define __exported +#endif + +/* + * We define this here since <stddef.h>, <sys/queue.h>, and <sys/types.h> + * require it. + */ +#if __GNUC_PREREQ__(4, 1) +#define __offsetof(type, field) __builtin_offsetof(type, field) +#else +#ifndef __cplusplus +#define __offsetof(type, field) \ + ((__size_t)(__uintptr_t)((const volatile void *)&((type *)0)->field)) +#else +#define __offsetof(type, field) \ + (__offsetof__ (reinterpret_cast <__size_t> \ + (&reinterpret_cast <const volatile char &> \ + (static_cast<type *> (0)->field)))) +#endif +#endif +#define __rangeof(type, start, end) \ + (__offsetof(type, end) - __offsetof(type, start)) + +/* + * Given the pointer x to the member m of the struct s, return + * a pointer to the containing structure. When using GCC, we first + * assign pointer x to a local variable, to check that its type is + * compatible with member m. + */ +#if __GNUC_PREREQ__(3, 1) +#define __containerof(x, s, m) ({ \ + const volatile __typeof(((s *)0)->m) *__x = (x); \ + __DEQUALIFY(s *, (const volatile char *)__x - __offsetof(s, m));\ +}) +#else +#define __containerof(x, s, m) \ + __DEQUALIFY(s *, (const volatile char *)(x) - __offsetof(s, m)) +#endif + +/* + * Compiler-dependent macros to declare that functions take printf-like + * or scanf-like arguments. They are null except for versions of gcc + * that are known to support the features properly (old versions of gcc-2 + * didn't permit keeping the keywords out of the application namespace). + */ +#if !__GNUC_PREREQ__(2, 7) && !defined(__INTEL_COMPILER) +#define __printflike(fmtarg, firstvararg) +#define __scanflike(fmtarg, firstvararg) +#define __format_arg(fmtarg) +#define __strfmonlike(fmtarg, firstvararg) +#define __strftimelike(fmtarg, firstvararg) +#else +#define __printflike(fmtarg, firstvararg) \ + __attribute__((__format__ (__printf__, fmtarg, firstvararg))) +#define __scanflike(fmtarg, firstvararg) \ + __attribute__((__format__ (__scanf__, fmtarg, firstvararg))) +#define __format_arg(fmtarg) __attribute__((__format_arg__ (fmtarg))) +#define __strfmonlike(fmtarg, firstvararg) \ + __attribute__((__format__ (__strfmon__, fmtarg, firstvararg))) +#define __strftimelike(fmtarg, firstvararg) \ + __attribute__((__format__ (__strftime__, fmtarg, firstvararg))) +#endif + +/* Compiler-dependent macros that rely on FreeBSD-specific extensions. */ +#if __FreeBSD_cc_version >= 300001 && defined(__GNUC__) && !defined(__INTEL_COMPILER) +#define __printf0like(fmtarg, firstvararg) \ + __attribute__((__format__ (__printf0__, fmtarg, firstvararg))) +#else +#define __printf0like(fmtarg, firstvararg) +#endif + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) +#ifndef __INTEL_COMPILER +#define __strong_reference(sym,aliassym) \ + extern __typeof (sym) aliassym __attribute__ ((__alias__ (#sym))) +#endif +#ifdef __STDC__ +#define __weak_reference(sym,alias) \ + __asm__(".weak " #alias); \ + __asm__(".equ " #alias ", " #sym) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." #sym); \ + __asm__(".asciz \"" msg "\""); \ + __asm__(".previous") +#define __sym_compat(sym,impl,verid) \ + __asm__(".symver " #impl ", " #sym "@" #verid) +#define __sym_default(sym,impl,verid) \ + __asm__(".symver " #impl ", " #sym "@@" #verid) +#else +#define __weak_reference(sym,alias) \ + __asm__(".weak alias"); \ + __asm__(".equ alias, sym") +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning.sym"); \ + __asm__(".asciz \"msg\""); \ + __asm__(".previous") +#define __sym_compat(sym,impl,verid) \ + __asm__(".symver impl, sym@verid") +#define __sym_default(impl,sym,verid) \ + __asm__(".symver impl, sym@@verid") +#endif /* __STDC__ */ +#endif /* __GNUC__ || __INTEL_COMPILER */ + +#define __GLOBL1(sym) __asm__(".globl " #sym) +#define __GLOBL(sym) __GLOBL1(sym) + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) +#define __IDSTRING(name,string) __asm__(".ident\t\"" string "\"") +#else +/* + * The following definition might not work well if used in header files, + * but it should be better than nothing. If you want a "do nothing" + * version, then it should generate some harmless declaration, such as: + * #define __IDSTRING(name,string) struct __hack + */ +#define __IDSTRING(name,string) static const char name[] __unused = string +#endif + +/* + * Embed the rcs id of a source file in the resulting library. Note that in + * more recent ELF binutils, we use .ident allowing the ID to be stripped. + * Usage: + * __FBSDID("$FreeBSD$"); + */ +#ifndef __FBSDID +#if !defined(lint) && !defined(STRIP_FBSDID) +#define __FBSDID(s) __IDSTRING(__CONCAT(__rcsid_,__LINE__),s) +#else +#define __FBSDID(s) struct __hack +#endif +#endif + +#ifndef __RCSID +#ifndef NO__RCSID +#define __RCSID(s) __IDSTRING(__CONCAT(__rcsid_,__LINE__),s) +#else +#define __RCSID(s) struct __hack +#endif +#endif + +#ifndef __RCSID_SOURCE +#ifndef NO__RCSID_SOURCE +#define __RCSID_SOURCE(s) __IDSTRING(__CONCAT(__rcsid_source_,__LINE__),s) +#else +#define __RCSID_SOURCE(s) struct __hack +#endif +#endif + +#ifndef __SCCSID +#ifndef NO__SCCSID +#define __SCCSID(s) __IDSTRING(__CONCAT(__sccsid_,__LINE__),s) +#else +#define __SCCSID(s) struct __hack +#endif +#endif + +#ifndef __COPYRIGHT +#ifndef NO__COPYRIGHT +#define __COPYRIGHT(s) __IDSTRING(__CONCAT(__copyright_,__LINE__),s) +#else +#define __COPYRIGHT(s) struct __hack +#endif +#endif + +#ifndef __DECONST +#define __DECONST(type, var) ((type)(__uintptr_t)(const void *)(var)) +#endif + +#ifndef __DEVOLATILE +#define __DEVOLATILE(type, var) ((type)(__uintptr_t)(volatile void *)(var)) +#endif + +#ifndef __DEQUALIFY +#define __DEQUALIFY(type, var) ((type)(__uintptr_t)(const volatile void *)(var)) +#endif + +/*- + * The following definitions are an extension of the behavior originally + * implemented in <sys/_posix.h>, but with a different level of granularity. + * POSIX.1 requires that the macros we test be defined before any standard + * header file is included. + * + * Here's a quick run-down of the versions: + * defined(_POSIX_SOURCE) 1003.1-1988 + * _POSIX_C_SOURCE == 1 1003.1-1990 + * _POSIX_C_SOURCE == 2 1003.2-1992 C Language Binding Option + * _POSIX_C_SOURCE == 199309 1003.1b-1993 + * _POSIX_C_SOURCE == 199506 1003.1c-1995, 1003.1i-1995, + * and the omnibus ISO/IEC 9945-1: 1996 + * _POSIX_C_SOURCE == 200112 1003.1-2001 + * _POSIX_C_SOURCE == 200809 1003.1-2008 + * + * In addition, the X/Open Portability Guide, which is now the Single UNIX + * Specification, defines a feature-test macro which indicates the version of + * that specification, and which subsumes _POSIX_C_SOURCE. + * + * Our macros begin with two underscores to avoid namespace screwage. + */ + +/* Deal with IEEE Std. 1003.1-1990, in which _POSIX_C_SOURCE == 1. */ +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 1 +#undef _POSIX_C_SOURCE /* Probably illegal, but beyond caring now. */ +#define _POSIX_C_SOURCE 199009 +#endif + +/* Deal with IEEE Std. 1003.2-1992, in which _POSIX_C_SOURCE == 2. */ +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 2 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 199209 +#endif + +/* Deal with various X/Open Portability Guides and Single UNIX Spec. */ +#ifdef _XOPEN_SOURCE +#if _XOPEN_SOURCE - 0 >= 700 +#define __XSI_VISIBLE 700 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200809 +#elif _XOPEN_SOURCE - 0 >= 600 +#define __XSI_VISIBLE 600 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200112 +#elif _XOPEN_SOURCE - 0 >= 500 +#define __XSI_VISIBLE 500 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 199506 +#endif +#endif + +/* + * Deal with all versions of POSIX. The ordering relative to the tests above is + * important. + */ +#if defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 198808 +#endif +#ifdef _POSIX_C_SOURCE +#if _POSIX_C_SOURCE >= 200809 +#define __POSIX_VISIBLE 200809 +#define __ISO_C_VISIBLE 1999 +#elif _POSIX_C_SOURCE >= 200112 +#define __POSIX_VISIBLE 200112 +#define __ISO_C_VISIBLE 1999 +#elif _POSIX_C_SOURCE >= 199506 +#define __POSIX_VISIBLE 199506 +#define __ISO_C_VISIBLE 1990 +#elif _POSIX_C_SOURCE >= 199309 +#define __POSIX_VISIBLE 199309 +#define __ISO_C_VISIBLE 1990 +#elif _POSIX_C_SOURCE >= 199209 +#define __POSIX_VISIBLE 199209 +#define __ISO_C_VISIBLE 1990 +#elif _POSIX_C_SOURCE >= 199009 +#define __POSIX_VISIBLE 199009 +#define __ISO_C_VISIBLE 1990 +#else +#define __POSIX_VISIBLE 198808 +#define __ISO_C_VISIBLE 0 +#endif /* _POSIX_C_SOURCE */ +#else +/*- + * Deal with _ANSI_SOURCE: + * If it is defined, and no other compilation environment is explicitly + * requested, then define our internal feature-test macros to zero. This + * makes no difference to the preprocessor (undefined symbols in preprocessing + * expressions are defined to have value zero), but makes it more convenient for + * a test program to print out the values. + * + * If a program mistakenly defines _ANSI_SOURCE and some other macro such as + * _POSIX_C_SOURCE, we will assume that it wants the broader compilation + * environment (and in fact we will never get here). + */ +#if defined(_ANSI_SOURCE) /* Hide almost everything. */ +#define __POSIX_VISIBLE 0 +#define __XSI_VISIBLE 0 +#define __BSD_VISIBLE 0 +#define __ISO_C_VISIBLE 1990 +#elif defined(_C99_SOURCE) /* Localism to specify strict C99 env. */ +#define __POSIX_VISIBLE 0 +#define __XSI_VISIBLE 0 +#define __BSD_VISIBLE 0 +#define __ISO_C_VISIBLE 1999 +#else /* Default environment: show everything. */ +#define __POSIX_VISIBLE 200809 +#define __XSI_VISIBLE 700 +#define __BSD_VISIBLE 1 +#define __ISO_C_VISIBLE 1999 +#endif +#endif + +#ifndef __has_feature +#define __has_feature(x) 0 +#endif +#ifndef __has_include +#define __has_include(x) 0 +#endif +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +#if defined(__mips) || defined(__powerpc64__) || defined(__arm__) +#define __NO_TLS 1 +#endif + +#endif /* !_SYS_CDEFS_H_ */ diff --git a/include/lib/stdlib/sys/ctype.h b/include/lib/stdlib/sys/ctype.h new file mode 100644 index 000000000..f2758b774 --- /dev/null +++ b/include/lib/stdlib/sys/ctype.h @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 1982, 1988, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * $FreeBSD$ + */ + +/* + * Portions copyright (c) 2009-2014, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef _SYS_CTYPE_H_ +#define _SYS_CTYPE_H_ + +#define isspace(c) ((c) == ' ' || ((c) >= '\t' && (c) <= '\r')) +#define isascii(c) (((c) & ~0x7f) == 0) +#define isupper(c) ((c) >= 'A' && (c) <= 'Z') +#define islower(c) ((c) >= 'a' && (c) <= 'z') +#define isalpha(c) (isupper(c) || islower(c)) +#define isdigit(c) ((c) >= '0' && (c) <= '9') +#define isxdigit(c) (isdigit(c) \ + || ((c) >= 'A' && (c) <= 'F') \ + || ((c) >= 'a' && (c) <= 'f')) +#define isprint(c) ((c) >= ' ' && (c) <= '~') + +#define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z'))) +#define tolower(c) ((c) + 0x20 * (((c) >= 'A') && ((c) <= 'Z'))) + +#endif /* !_SYS_CTYPE_H_ */ diff --git a/include/lib/stdlib/sys/errno.h b/include/lib/stdlib/sys/errno.h new file mode 100644 index 000000000..f59551451 --- /dev/null +++ b/include/lib/stdlib/sys/errno.h @@ -0,0 +1,193 @@ +/*- + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * @(#)errno.h 8.5 (Berkeley) 1/21/94 + * $FreeBSD$ + */ + +#ifndef _SYS_ERRNO_H_ +#define _SYS_ERRNO_H_ + +#ifndef _KERNEL +#include <sys/cdefs.h> +__BEGIN_DECLS +int * __error(void); +__END_DECLS +#define errno (* __error()) +#endif + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* Input/output error */ +#define ENXIO 6 /* Device not configured */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file descriptor */ +#define ECHILD 10 /* No child processes */ +#define EDEADLK 11 /* Resource deadlock avoided */ + /* 11 was EAGAIN */ +#define ENOMEM 12 /* Cannot allocate memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#ifndef _POSIX_SOURCE +#define ENOTBLK 15 /* Block device required */ +#endif +#define EBUSY 16 /* Device busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* Operation not supported by device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* Too many open files in system */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Inappropriate ioctl for device */ +#ifndef _POSIX_SOURCE +#define ETXTBSY 26 /* Text file busy */ +#endif +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only filesystem */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ + +/* math software */ +#define EDOM 33 /* Numerical argument out of domain */ +#define ERANGE 34 /* Result too large */ + +/* non-blocking and interrupt i/o */ +#define EAGAIN 35 /* Resource temporarily unavailable */ +#ifndef _POSIX_SOURCE +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define EINPROGRESS 36 /* Operation now in progress */ +#define EALREADY 37 /* Operation already in progress */ + +/* ipc/network software -- argument errors */ +#define ENOTSOCK 38 /* Socket operation on non-socket */ +#define EDESTADDRREQ 39 /* Destination address required */ +#define EMSGSIZE 40 /* Message too long */ +#define EPROTOTYPE 41 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 42 /* Protocol not available */ +#define EPROTONOSUPPORT 43 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 44 /* Socket type not supported */ +#define EOPNOTSUPP 45 /* Operation not supported */ +#define ENOTSUP EOPNOTSUPP /* Operation not supported */ +#define EPFNOSUPPORT 46 /* Protocol family not supported */ +#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */ +#define EADDRINUSE 48 /* Address already in use */ +#define EADDRNOTAVAIL 49 /* Can't assign requested address */ + +/* ipc/network software -- operational errors */ +#define ENETDOWN 50 /* Network is down */ +#define ENETUNREACH 51 /* Network is unreachable */ +#define ENETRESET 52 /* Network dropped connection on reset */ +#define ECONNABORTED 53 /* Software caused connection abort */ +#define ECONNRESET 54 /* Connection reset by peer */ +#define ENOBUFS 55 /* No buffer space available */ +#define EISCONN 56 /* Socket is already connected */ +#define ENOTCONN 57 /* Socket is not connected */ +#define ESHUTDOWN 58 /* Can't send after socket shutdown */ +#define ETOOMANYREFS 59 /* Too many references: can't splice */ +#define ETIMEDOUT 60 /* Operation timed out */ +#define ECONNREFUSED 61 /* Connection refused */ + +#define ELOOP 62 /* Too many levels of symbolic links */ +#endif /* _POSIX_SOURCE */ +#define ENAMETOOLONG 63 /* File name too long */ + +/* should be rearranged */ +#ifndef _POSIX_SOURCE +#define EHOSTDOWN 64 /* Host is down */ +#define EHOSTUNREACH 65 /* No route to host */ +#endif /* _POSIX_SOURCE */ +#define ENOTEMPTY 66 /* Directory not empty */ + +/* quotas & mush */ +#ifndef _POSIX_SOURCE +#define EPROCLIM 67 /* Too many processes */ +#define EUSERS 68 /* Too many users */ +#define EDQUOT 69 /* Disc quota exceeded */ + +/* Network File System */ +#define ESTALE 70 /* Stale NFS file handle */ +#define EREMOTE 71 /* Too many levels of remote in path */ +#define EBADRPC 72 /* RPC struct is bad */ +#define ERPCMISMATCH 73 /* RPC version wrong */ +#define EPROGUNAVAIL 74 /* RPC prog. not avail */ +#define EPROGMISMATCH 75 /* Program version wrong */ +#define EPROCUNAVAIL 76 /* Bad procedure for program */ +#endif /* _POSIX_SOURCE */ + +#define ENOLCK 77 /* No locks available */ +#define ENOSYS 78 /* Function not implemented */ + +#ifndef _POSIX_SOURCE +#define EFTYPE 79 /* Inappropriate file type or format */ +#define EAUTH 80 /* Authentication error */ +#define ENEEDAUTH 81 /* Need authenticator */ +#define EIDRM 82 /* Identifier removed */ +#define ENOMSG 83 /* No message of desired type */ +#define EOVERFLOW 84 /* Value too large to be stored in data type */ +#define ECANCELED 85 /* Operation canceled */ +#define EILSEQ 86 /* Illegal byte sequence */ +#define ENOATTR 87 /* Attribute not found */ + +#define EDOOFUS 88 /* Programming error */ +#endif /* _POSIX_SOURCE */ + +#define EBADMSG 89 /* Bad message */ +#define EMULTIHOP 90 /* Multihop attempted */ +#define ENOLINK 91 /* Link has been severed */ +#define EPROTO 92 /* Protocol error */ + +#ifndef _POSIX_SOURCE +#define ENOTCAPABLE 93 /* Capabilities insufficient */ +#define ECAPMODE 94 /* Not permitted in capability mode */ +#endif /* _POSIX_SOURCE */ + +#ifndef _POSIX_SOURCE +#define ELAST 94 /* Must be equal largest errno */ +#endif /* _POSIX_SOURCE */ + +#ifdef _KERNEL +/* pseudo-errors returned inside kernel to modify return to process */ +#define ERESTART (-1) /* restart syscall */ +#define EJUSTRETURN (-2) /* don't modify regs, just return */ +#define ENOIOCTL (-3) /* ioctl not handled by this layer */ +#define EDIRIOCTL (-4) /* do direct ioctl in GEOM */ +#endif + +#endif diff --git a/include/lib/stdlib/sys/limits.h b/include/lib/stdlib/sys/limits.h new file mode 100644 index 000000000..d4fb8b7e0 --- /dev/null +++ b/include/lib/stdlib/sys/limits.h @@ -0,0 +1,102 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * $FreeBSD$ + */ + +#ifndef _SYS_LIMITS_H_ +#define _SYS_LIMITS_H_ + +#include <sys/cdefs.h> +#include <machine/_limits.h> + +#define CHAR_BIT __CHAR_BIT /* number of bits in a char */ + +#define SCHAR_MAX __SCHAR_MAX /* max value for a signed char */ +#define SCHAR_MIN __SCHAR_MIN /* min value for a signed char */ + +#define UCHAR_MAX __UCHAR_MAX /* max value for an unsigned char */ + +#ifdef __CHAR_UNSIGNED__ +#define CHAR_MAX UCHAR_MAX /* max value for a char */ +#define CHAR_MIN 0 /* min value for a char */ +#else +#define CHAR_MAX SCHAR_MAX +#define CHAR_MIN SCHAR_MIN +#endif + +#define USHRT_MAX __USHRT_MAX /* max value for an unsigned short */ +#define SHRT_MAX __SHRT_MAX /* max value for a short */ +#define SHRT_MIN __SHRT_MIN /* min value for a short */ + +#define UINT_MAX __UINT_MAX /* max value for an unsigned int */ +#define INT_MAX __INT_MAX /* max value for an int */ +#define INT_MIN __INT_MIN /* min value for an int */ + +#define ULONG_MAX __ULONG_MAX /* max for an unsigned long */ +#define LONG_MAX __LONG_MAX /* max for a long */ +#define LONG_MIN __LONG_MIN /* min for a long */ + +#ifdef __LONG_LONG_SUPPORTED +#define ULLONG_MAX __ULLONG_MAX /* max for an unsigned long long */ +#define LLONG_MAX __LLONG_MAX /* max for a long long */ +#define LLONG_MIN __LLONG_MIN /* min for a long long */ +#endif + +#if __POSIX_VISIBLE || __XSI_VISIBLE +#define SSIZE_MAX __SSIZE_MAX /* max value for an ssize_t */ +#endif + +#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE +#define SIZE_T_MAX __SIZE_T_MAX /* max value for a size_t */ + +#define OFF_MAX __OFF_MAX /* max value for an off_t */ +#define OFF_MIN __OFF_MIN /* min value for an off_t */ +#endif + +#if __BSD_VISIBLE +#define GID_MAX UINT_MAX /* max value for a gid_t */ +#define UID_MAX UINT_MAX /* max value for a uid_t */ + +#define UQUAD_MAX (__UQUAD_MAX) /* max value for a uquad_t */ +#define QUAD_MAX (__QUAD_MAX) /* max value for a quad_t */ +#define QUAD_MIN (__QUAD_MIN) /* min value for a quad_t */ +#endif + +#if __XSI_VISIBLE || __POSIX_VISIBLE >= 200809 +#define LONG_BIT __LONG_BIT +#define WORD_BIT __WORD_BIT +#endif + +#if __POSIX_VISIBLE +#define MQ_PRIO_MAX 64 +#endif + +#endif /* !_SYS_LIMITS_H_ */ diff --git a/include/lib/stdlib/sys/stdarg.h b/include/lib/stdlib/sys/stdarg.h new file mode 100644 index 000000000..c315dfcee --- /dev/null +++ b/include/lib/stdlib/sys/stdarg.h @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2002 David E. O'Brien. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_STDARG_H_ +#define _MACHINE_STDARG_H_ + +#include <sys/cdefs.h> +#include <sys/_types.h> + +#ifndef _VA_LIST_DECLARED +#define _VA_LIST_DECLARED +typedef __va_list va_list; +#endif + +#ifdef __GNUCLIKE_BUILTIN_STDARG + +#define va_start(ap, last) \ + __builtin_va_start((ap), (last)) + +#define va_arg(ap, type) \ + __builtin_va_arg((ap), type) + +#define __va_copy(dest, src) \ + __builtin_va_copy((dest), (src)) + +#if __ISO_C_VISIBLE >= 1999 +#define va_copy(dest, src) \ + __va_copy(dest, src) +#endif + +#define va_end(ap) \ + __builtin_va_end(ap) + +#elif defined(lint) +/* Provide a fake implementation for lint's benefit */ +#define __va_size(type) \ + (((sizeof(type) + sizeof(long) - 1) / sizeof(long)) * sizeof(long)) +#define va_start(ap, last) \ + ((ap) = (va_list)&(last) + __va_size(last)) +#define va_arg(ap, type) \ + (*(type *)((ap) += __va_size(type), (ap) - __va_size(type))) +#define va_end(ap) + +#else +#error this file needs to be ported to your compiler +#endif + +#endif /* !_MACHINE_STDARG_H_ */ diff --git a/include/lib/stdlib/sys/stdint.h b/include/lib/stdlib/sys/stdint.h new file mode 100644 index 000000000..aa5ac81d1 --- /dev/null +++ b/include/lib/stdlib/sys/stdint.h @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _SYS_STDINT_H_ +#define _SYS_STDINT_H_ + +#include <sys/cdefs.h> +#include <sys/_types.h> + +#include <machine/_stdint.h> +#include <sys/_stdint.h> + +typedef __int_least8_t int_least8_t; +typedef __int_least16_t int_least16_t; +typedef __int_least32_t int_least32_t; +typedef __int_least64_t int_least64_t; + +typedef __uint_least8_t uint_least8_t; +typedef __uint_least16_t uint_least16_t; +typedef __uint_least32_t uint_least32_t; +typedef __uint_least64_t uint_least64_t; + +typedef __int_fast8_t int_fast8_t; +typedef __int_fast16_t int_fast16_t; +typedef __int_fast32_t int_fast32_t; +typedef __int_fast64_t int_fast64_t; + +typedef __uint_fast8_t uint_fast8_t; +typedef __uint_fast16_t uint_fast16_t; +typedef __uint_fast32_t uint_fast32_t; +typedef __uint_fast64_t uint_fast64_t; + +#ifndef _INTMAX_T_DECLARED +typedef __intmax_t intmax_t; +#define _INTMAX_T_DECLARED +#endif +#ifndef _UINTMAX_T_DECLARED +typedef __uintmax_t uintmax_t; +#define _UINTMAX_T_DECLARED +#endif + +/* GNU and Darwin define this and people seem to think it's portable */ +#if defined(UINTPTR_MAX) && defined(UINT64_MAX) && (UINTPTR_MAX == UINT64_MAX) +#define __WORDSIZE 64 +#else +#define __WORDSIZE 32 +#endif + +#endif /* !_SYS_STDINT_H_ */ diff --git a/include/lib/stdlib/sys/types.h b/include/lib/stdlib/sys/types.h new file mode 100644 index 000000000..ae2ea33a5 --- /dev/null +++ b/include/lib/stdlib/sys/types.h @@ -0,0 +1,245 @@ +/*- + * Copyright (c) 1982, 1986, 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * @(#)types.h 8.6 (Berkeley) 2/19/95 + * $FreeBSD$ + */ + +#ifndef _SYS_TYPES_H_ +#define _SYS_TYPES_H_ + +#include <sys/cdefs.h> + +/* Machine type dependent parameters. */ +#include <sys/_types.h> + +#if __BSD_VISIBLE +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; +#ifndef _KERNEL +typedef unsigned short ushort; /* Sys V compatibility */ +typedef unsigned int uint; /* Sys V compatibility */ +#endif +#endif + +/* + * XXX POSIX sized integrals that should appear only in <sys/stdint.h>. + */ +#include <sys/_stdint.h> + +typedef __uint8_t u_int8_t; /* unsigned integrals (deprecated) */ +typedef __uint16_t u_int16_t; +typedef __uint32_t u_int32_t; +typedef __uint64_t u_int64_t; + +typedef __uint64_t u_quad_t; /* quads (deprecated) */ +typedef __int64_t quad_t; +typedef quad_t *qaddr_t; + +typedef char *caddr_t; /* core address */ +typedef const char *c_caddr_t; /* core address, pointer to const */ + +#ifndef _BLKSIZE_T_DECLARED +typedef __blksize_t blksize_t; +#define _BLKSIZE_T_DECLARED +#endif + +typedef __cpuwhich_t cpuwhich_t; +typedef __cpulevel_t cpulevel_t; +typedef __cpusetid_t cpusetid_t; + +#ifndef _BLKCNT_T_DECLARED +typedef __blkcnt_t blkcnt_t; +#define _BLKCNT_T_DECLARED +#endif + +#ifndef _CLOCK_T_DECLARED +typedef __clock_t clock_t; +#define _CLOCK_T_DECLARED +#endif + +#ifndef _CLOCKID_T_DECLARED +typedef __clockid_t clockid_t; +#define _CLOCKID_T_DECLARED +#endif + +typedef __critical_t critical_t; /* Critical section value */ +typedef __int64_t daddr_t; /* disk address */ + +#ifndef _DEV_T_DECLARED +typedef __dev_t dev_t; /* device number or struct cdev */ +#define _DEV_T_DECLARED +#endif + +#ifndef _FFLAGS_T_DECLARED +typedef __fflags_t fflags_t; /* file flags */ +#define _FFLAGS_T_DECLARED +#endif + +typedef __fixpt_t fixpt_t; /* fixed point number */ + +#ifndef _FSBLKCNT_T_DECLARED /* for statvfs() */ +typedef __fsblkcnt_t fsblkcnt_t; +typedef __fsfilcnt_t fsfilcnt_t; +#define _FSBLKCNT_T_DECLARED +#endif + +#ifndef _GID_T_DECLARED +typedef __gid_t gid_t; /* group id */ +#define _GID_T_DECLARED +#endif + +#ifndef _IN_ADDR_T_DECLARED +typedef __uint32_t in_addr_t; /* base type for internet address */ +#define _IN_ADDR_T_DECLARED +#endif + +#ifndef _IN_PORT_T_DECLARED +typedef __uint16_t in_port_t; +#define _IN_PORT_T_DECLARED +#endif + +#ifndef _ID_T_DECLARED +typedef __id_t id_t; /* can hold a uid_t or pid_t */ +#define _ID_T_DECLARED +#endif + +#ifndef _INO_T_DECLARED +typedef __ino_t ino_t; /* inode number */ +#define _INO_T_DECLARED +#endif + +#ifndef _KEY_T_DECLARED +typedef __key_t key_t; /* IPC key (for Sys V IPC) */ +#define _KEY_T_DECLARED +#endif + +#ifndef _LWPID_T_DECLARED +typedef __lwpid_t lwpid_t; /* Thread ID (a.k.a. LWP) */ +#define _LWPID_T_DECLARED +#endif + +#ifndef _MODE_T_DECLARED +typedef __mode_t mode_t; /* permissions */ +#define _MODE_T_DECLARED +#endif + +#ifndef _ACCMODE_T_DECLARED +typedef __accmode_t accmode_t; /* access permissions */ +#define _ACCMODE_T_DECLARED +#endif + +#ifndef _NLINK_T_DECLARED +typedef __nlink_t nlink_t; /* link count */ +#define _NLINK_T_DECLARED +#endif + +#ifndef _OFF_T_DECLARED +typedef __off_t off_t; /* file offset */ +#define _OFF_T_DECLARED +#endif + +#ifndef _PID_T_DECLARED +typedef __pid_t pid_t; /* process id */ +#define _PID_T_DECLARED +#endif + +typedef __register_t register_t; + +#ifndef _RLIM_T_DECLARED +typedef __rlim_t rlim_t; /* resource limit */ +#define _RLIM_T_DECLARED +#endif + +typedef __int64_t sbintime_t; + +typedef __segsz_t segsz_t; /* segment size (in pages) */ + +#ifndef _SIZE_T_DECLARED +typedef __size_t size_t; +#define _SIZE_T_DECLARED +#endif + +#ifndef _SSIZE_T_DECLARED +typedef __ssize_t ssize_t; +#define _SSIZE_T_DECLARED +#endif + +#ifndef _SUSECONDS_T_DECLARED +typedef __suseconds_t suseconds_t; /* microseconds (signed) */ +#define _SUSECONDS_T_DECLARED +#endif + +#ifndef _TIME_T_DECLARED +typedef __time_t time_t; +#define _TIME_T_DECLARED +#endif + +#ifndef _TIMER_T_DECLARED +typedef __timer_t timer_t; +#define _TIMER_T_DECLARED +#endif + +#ifndef _MQD_T_DECLARED +typedef __mqd_t mqd_t; +#define _MQD_T_DECLARED +#endif + +typedef __u_register_t u_register_t; + +#ifndef _UID_T_DECLARED +typedef __uid_t uid_t; /* user id */ +#define _UID_T_DECLARED +#endif + +#ifndef _USECONDS_T_DECLARED +typedef __useconds_t useconds_t; /* microseconds (unsigned) */ +#define _USECONDS_T_DECLARED +#endif + +#ifndef _CAP_RIGHTS_T_DECLARED +#define _CAP_RIGHTS_T_DECLARED +struct cap_rights; + +typedef struct cap_rights cap_rights_t; +#endif + +typedef __vm_offset_t vm_offset_t; +typedef __vm_ooffset_t vm_ooffset_t; +typedef __vm_paddr_t vm_paddr_t; +typedef __vm_pindex_t vm_pindex_t; +typedef __vm_size_t vm_size_t; + +#endif /* !_SYS_TYPES_H_ */ diff --git a/include/lib/stdlib/sys/uuid.h b/include/lib/stdlib/sys/uuid.h new file mode 100644 index 000000000..934fb4fdf --- /dev/null +++ b/include/lib/stdlib/sys/uuid.h @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2002 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * $FreeBSD$ + */ + +/* + * Portions copyright (c) 2014, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef _SYS_UUID_H_ +#define _SYS_UUID_H_ + +#include <sys/cdefs.h> +#include <sys/_stdint.h> + +/* Length of a node address (an IEEE 802 address). */ +#define _UUID_NODE_LEN 6 + +/* + * See also: + * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt + * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm + * + * A DCE 1.1 compatible source representation of UUIDs. + */ +struct uuid { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq_hi_and_reserved; + uint8_t clock_seq_low; + uint8_t node[_UUID_NODE_LEN]; +}; + +typedef struct uuid uuid_t; + +#endif /* _SYS_UUID_H_ */ diff --git a/include/lib/tftf_lib.h b/include/lib/tftf_lib.h new file mode 100644 index 000000000..e5900b8a1 --- /dev/null +++ b/include/lib/tftf_lib.h @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __TFTF_LIB_H__ +#define __TFTF_LIB_H__ + +#ifndef __ASSEMBLY__ + +#include <arch.h> +#include <arch_helpers.h> +#include <stdbool.h> +#include <stdint.h> +#include <sys/types.h> + +/* + * Possible error codes for signaling the result of a test + * TEST_RESULT_MIN and TEST_RESULT_MAX are only used as bounds in the enum. + */ +typedef enum { + /* + * NA = Not applicable. + * Initial value for a test result. + * Used for CPUs that don't participate in the test. + */ + TEST_RESULT_NA = -1, + + TEST_RESULT_MIN = 0, + TEST_RESULT_SKIPPED = TEST_RESULT_MIN, + TEST_RESULT_SUCCESS, + TEST_RESULT_FAIL, + TEST_RESULT_CRASHED, + + TEST_RESULT_MAX +} test_result_t; + +const char *test_result_to_string(test_result_t result); + +#define TEST_RESULT_IS_VALID(result) \ + ((result >= TEST_RESULT_MIN) && (result < TEST_RESULT_MAX)) + +/* + * PSCI Function Wrappers + * + * SMC calls to PSCI functions + */ +int32_t tftf_psci_cpu_on(u_register_t target_cpu, + uintptr_t entry_point_address, + u_register_t context_id); +int32_t tftf_psci_cpu_off(void); +int32_t tftf_psci_affinity_info(u_register_t target_affinity, + uint32_t lowest_affinity_level); +int32_t tftf_psci_node_hw_state(u_register_t target_cpu, uint32_t power_level); +int32_t tftf_get_psci_feature_info(uint32_t psci_func_id); +u_register_t tftf_psci_stat_count(u_register_t target_cpu, + uint32_t power_state); +u_register_t tftf_psci_stat_residency(u_register_t target_cpu, + uint32_t power_state); + +/* + * PSCI Helper functions + */ + +/* + * Gets the context ID used when calling tftf_psci_cpu_on(). + */ +u_register_t tftf_get_cpu_on_ctx_id(unsigned int core_pos); + +/* + * Sets the context ID used when calling tftf_psci_cpu_on(). + */ +void tftf_set_cpu_on_ctx_id(unsigned int core_pos, u_register_t context_id); + +/* + * Gets the PSCI version of Trusted Firmware-A. The version number returned + * is a 32-bit unsigned integer, with the upper 16 bits denoting the major + * revision, and the lower 16 bits denoting the minor revision. + */ +unsigned int tftf_get_psci_version(void); + +/* + * Returns 0 if version is not a valid PSCI version supported by TFTF. + * Otherwise it returns a value different of 0. + */ +int tftf_is_valid_psci_version(unsigned int version); + + +/* + * The function constructs a composite state_id up-to the specified + * affinity level querying the relevant state property from the platform. + * It chooses the first matching state property from the array returned + * by platform. In case the requested affinity level is not supported by + * the platform, then this function uses DUMMY_STATE_ID as the local state + * for that level. This allows the tests to construct composite state-id + * for invalid affinity levels as well. It returns the expected return + * value from CPU SUSPEND call. + */ +int tftf_psci_make_composite_state_id(uint32_t affinity_level, + uint32_t state_type, uint32_t *state_id); + +/* + * This function composes the power state parameter in the right format + * needed by PSCI. The detection of the power state format is done during + * cold boot by tftf_detect_psci_pstate_format() function. + */ +uint32_t tftf_make_psci_pstate(uint32_t affinity_level, + uint32_t state_type, + uint32_t state_id); + +/* + * Returns 1, if the EL3 software supports PSCI's original format state ID as + * NULL else returns zero + */ +unsigned int tftf_is_psci_state_id_null(void); + +/* + * Returns 1, if the EL3 software supports PSCI's original state format else + * returns zero + */ +unsigned int tftf_is_psci_pstate_format_original(void); + +/* Functions to wait for a specified number of ms or us */ +void waitms(uint64_t ms); +void waitus(uint64_t us); + +/* + * SMC calls take a function identifier and up to 6 arguments. + * Additionally, for SMC calls that originate from EL2, an optional seventh + * argument can be added. Given that TFTF runs in EL2, we need to be able to + * specify it. + */ +typedef struct { + u_register_t arg0; + u_register_t arg1; + u_register_t arg2; + u_register_t arg3; + u_register_t arg4; + u_register_t arg5; + u_register_t arg6; + u_register_t arg7; +} smc_args; + +/* SMC calls can return up to 4 register values */ +typedef struct { + u_register_t ret0; + u_register_t ret1; + u_register_t ret2; + u_register_t ret3; +} smc_ret_values; + +/* + * Trigger an SMC call. + */ +smc_ret_values tftf_smc(const smc_args *args); + +/* + * Write a formatted string in the test output buffer. + * Just like the standard libc's printf() function, the string produced is under + * the control of a format string that specifies how subsequent arguments are + * converted. + * + * The string will appear in the test report. + * Use mp_printf() instead for volatile debug messages that are not meant to be + * stored into the test report. + * Note: The test output buffer referred here is a temporary buffer stored in + * RAM. This function doesn't write anything into NVM. + * + * Upon successful return, return the number of characters printed (not + * including the final '\0' character). If an output error is encountered, + * a negative value is returned. If the function is not able to print any + * character at all, this is considered as an output error. Note that a partial + * write (i.e. when the string is truncated) is not considered as an output + * error. + */ +__attribute__((format(printf, 1, 2))) +int tftf_testcase_printf(const char *format, ...); + +/* + * This function is meant to be used by tests. + * It tells the framework that the test is going to reset the platform. + * + * It the test omits to call this function before resetting, the framework will + * consider the test has crashed upon resumption. + */ +void tftf_notify_reboot(void); + +/* + * Returns 0 if the test function is executed for the first time, + * or 1 if the test rebooted the platform and the test function is being + * executed again. + * This function is used for tests that reboot the platform, so that they can + * execute different code paths on 1st execution and subsequent executions. + */ +unsigned int tftf_is_rebooted(void); + +static inline unsigned int make_mpid(unsigned int clusterid, + unsigned int coreid) +{ + /* + * If MT bit is set then need to shift the affinities and also set the + * MT bit. + */ + if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0) + return MPIDR_MT_MASK | + ((clusterid & MPIDR_AFFLVL_MASK) << MPIDR_AFF2_SHIFT) | + ((coreid & MPIDR_AFFLVL_MASK) << MPIDR_AFF1_SHIFT); + else + return ((clusterid & MPIDR_AFFLVL_MASK) << MPIDR_AFF1_SHIFT) | + ((coreid & MPIDR_AFFLVL_MASK) << MPIDR_AFF0_SHIFT); + +} + +#endif /* __ASSEMBLY__ */ +#endif /* __TFTF_LIB_H__ */ diff --git a/include/lib/timer.h b/include/lib/timer.h new file mode 100644 index 000000000..0bfff01e7 --- /dev/null +++ b/include/lib/timer.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __TIMER_H__ +#define __TIMER_H__ + +#include <irq.h> + +typedef struct plat_timer { + int (*program)(unsigned long time_out_ms); + int (*cancel)(void); + int (*handler)(void); + + /* + * Duration of the atomic time slice in milliseconds. All timer + * requests within the same time slice are merged into one. This value + * should be chosen such that it is greater than the time required to + * program the timer. + */ + unsigned int timer_step_value; + unsigned int timer_irq; +} plat_timer_t; + +/* + * Gets the platform specific timer implementation information and initialises + * the timer framework and peripheral. + * Returns 0 on success or return value of timer peripheral intialisation + * function. + */ +int tftf_initialise_timer(void); + +/* + * Requests the timer framework to send an interrupt after milli_secs. + * The interrupt is sent to the calling core of this api. The actual + * time the interrupt is received by the core can be greater than + * the requested time. + * Returns 0 on success and -1 on failure. + */ +int tftf_program_timer(unsigned long milli_secs); + +/* + * Requests the timer framework to send an interrupt after milli_secs and to + * suspend the CPU to the desired power state. The interrupt is sent to the + * calling core of this api. The actual time the interrupt is received by the + * core can be greater than the requested time. + * + * Return codes from tftf_program_timer calls and tftf_cpu_suspend are stored + * respectively in timer_rc and suspend_rc output parameters. + * If a function is not executed, the return value stored in the output + * parameters will be as if the correponding call succeeded. NULL pointers are + * accepted to discard the return codes. + * Returns 0 on success and -1 on failure. + */ + +int tftf_program_timer_and_suspend(unsigned long milli_secs, + unsigned int pwr_state, + int *timer_rc, int *suspend_rc); + +/* + * Requests the timer framework to send an interrupt after milli_secs and to + * suspend the system. The interrupt is sent to the calling core of this api. + * The actual time the interrupt is received by the core can be greater than + * the requested time. For the system suspend to succeed, all cores other than + * the calling core should be in the OFF state. + * + * Return codes from tftf_program_timer calls and tftf_cpu_system suspend + * are stored respectively in timer_rc and suspend_rc output parameters. + * If a function is not executed, the return value stored in the output + * parameters will be as if the correponding call succeeded. NULL pointers are + * accepted to discard the return codes. + * Returns 0 on success and -1 on failure. + */ +int tftf_program_timer_and_sys_suspend(unsigned long milli_secs, + int *timer_rc, int *suspend_rc); + +/* + * Suspends the calling CPU for specified milliseconds. + * + * Returns 0 on success, and -1 otherwise. + */ +int tftf_timer_sleep(unsigned long milli_secs); + +/* + * Common handler for servicing all the timer interrupts. It in turn calls the + * peripheral specific handler. It also sends WAKE_SGI to all the cores which + * requested an interrupt within a time frame of timer_step_value. + * Also, if there are pending interrupt requests, reprograms the timer + * accordingly to fire an interrupt at the right time. + * + * Returns 0 on success. + */ +int tftf_timer_framework_handler(void *data); + +/* + * Cancels the previously programmed value by the called core. + * This api should be used only for cancelling the self interrupt request + * by a core. + * Returns 0 on success, negative value otherwise. + */ +int tftf_cancel_timer(void); + +/* + * It is used to register a handler which needs to be called when a timer + * interrupt is fired. + * Returns 0 on success, negative value otherwise. + */ +int tftf_timer_register_handler(irq_handler_t irq_handler); + +/* + * It is used to unregister a previously registered handler. + * Returns 0 on success, negative value otherwise. + */ +int tftf_timer_unregister_handler(void); + +/* + * Return the IRQ Number of the registered timer interrupt + */ +unsigned int tftf_get_timer_irq(void); + +/* + * Returns the timer step value in a platform and is used by test cases. + */ +unsigned int tftf_get_timer_step_value(void); + +/* + * Restore the GIC state after wake-up from system suspend + */ +void tftf_timer_gic_state_restore(void); + +#endif /* __TIMER_H__ */ diff --git a/include/lib/utils/math_utils.h b/include/lib/utils/math_utils.h new file mode 100644 index 000000000..9d8e88d71 --- /dev/null +++ b/include/lib/utils/math_utils.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __MATH_UTILS_H__ +#define __MATH_UTILS_H__ + +#include <stdint.h> + +/* Simple utility to calculate `power` of a `base` number. */ +static inline unsigned int pow(unsigned int base, unsigned int power) +{ + unsigned int result = 1; + while (power) { + result *= base; + power--; + } + return result; +} + +#endif /* __MATH_UTILS_H__ */ diff --git a/include/lib/utils/misc_utils.h b/include/lib/utils/misc_utils.h new file mode 100644 index 000000000..0949816e0 --- /dev/null +++ b/include/lib/utils/misc_utils.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __MISC_UTILS_H__ +#define __MISC_UTILS_H__ + +#define COMPILER_BARRIER() __asm__ volatile ("" ::: "memory") + +#endif /* __MISC_UTILS_H__ */ diff --git a/include/lib/utils/uuid_utils.h b/include/lib/utils/uuid_utils.h new file mode 100644 index 000000000..dda824160 --- /dev/null +++ b/include/lib/utils/uuid_utils.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __UUID_UTILS_H__ +#define __UUID_UTILS_H__ + +#include <stdint.h> +#include <uuid.h> + +/* Size (in bytes) of a UUID string as formatted by uuid_to_str() */ +#define UUID_STR_SIZE 79 + +/* + * Convert a UUID into a string. + * + * The caller is responsible for allocating the output string buffer + * pointed by 'str'. It must be at least UUID_STR_SIZE bytes long. + * + * Return the UUID string. + */ +char *uuid_to_str(const uuid_t *uuid, char *str); + +/* + * Return 1 if uuid == uuid_null, 0 otherwise. + */ +unsigned int is_uuid_null(const uuid_t *uuid); + +/* + * Return 1 if uuid1 == uuid2, 0 otherwise. + */ +unsigned int uuid_equal(const uuid_t *uuid1, const uuid_t *uuid2); + +/* + * Take four 32-bit words of data and combine them into a UUID. + * + * The caller is responsible for allocating the output UUID variable + * pointed by 'uuid'. + * + * Return the UUID. + */ +uuid_t *make_uuid_from_4words(uuid_t *uuid, + uint32_t uuid0, + uint32_t uuid1, + uint32_t uuid2, + uint32_t uuid3); + +#endif /* __UUID_UTILS_H__ */ diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h new file mode 100644 index 000000000..5b4fd7808 --- /dev/null +++ b/include/lib/utils_def.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UTILS_DEF_H +#define UTILS_DEF_H + +/* Compute the number of elements in the given array */ +#define ARRAY_SIZE(a) \ + (sizeof(a) / sizeof((a)[0])) + +#define IS_POWER_OF_TWO(x) \ + (((x) & ((x) - 1)) == 0) + +#define SIZE_FROM_LOG2_WORDS(n) (4 << (n)) + +#define BIT_32(nr) (U(1) << (nr)) +#define BIT_64(nr) (ULL(1) << (nr)) + +#ifdef AARCH32 +#define BIT BIT_32 +#else +#define BIT BIT_64 +#endif + +/* + * Create a contiguous bitmask starting at bit position @l and ending at + * position @h. For example + * GENMASK_64(39, 21) gives us the 64bit vector 0x000000ffffe00000. + */ +#define GENMASK_32(h, l) \ + (((~UINT32_C(0)) << (l)) & (~UINT32_C(0) >> (32 - 1 - (h)))) + +#define GENMASK_64(h, l) \ + (((~UINT64_C(0)) << (l)) & (~UINT64_C(0) >> (64 - 1 - (h)))) + +#ifdef AARCH32 +#define GENMASK GENMASK_32 +#else +#define GENMASK GENMASK_64 +#endif + +/* + * This variant of div_round_up can be used in macro definition but should not + * be used in C code as the `div` parameter is evaluated twice. + */ +#define DIV_ROUND_UP_2EVAL(n, d) (((n) + (d) - 1) / (d)) + +#define div_round_up(val, div) __extension__ ({ \ + __typeof__(div) _div = (div); \ + ((val) + _div - 1) / _div; \ +}) + +#define MIN(x, y) __extension__ ({ \ + __typeof__(x) _x = (x); \ + __typeof__(y) _y = (y); \ + (void)(&_x == &_y); \ + _x < _y ? _x : _y; \ +}) + +#define MAX(x, y) __extension__ ({ \ + __typeof__(x) _x = (x); \ + __typeof__(y) _y = (y); \ + (void)(&_x == &_y); \ + _x > _y ? _x : _y; \ +}) + +/* + * The round_up() macro rounds up a value to the given boundary in a + * type-agnostic yet type-safe manner. The boundary must be a power of two. + * In other words, it computes the smallest multiple of boundary which is + * greater than or equal to value. + * + * round_down() is similar but rounds the value down instead. + */ +#define round_boundary(value, boundary) \ + ((__typeof__(value))((boundary) - 1)) + +#define round_up(value, boundary) \ + ((((value) - 1) | round_boundary(value, boundary)) + 1) + +#define round_down(value, boundary) \ + ((value) & ~round_boundary(value, boundary)) + +/* + * Evaluates to 1 if (ptr + inc) overflows, 0 otherwise. + * Both arguments must be unsigned pointer values (i.e. uintptr_t). + */ +#define check_uptr_overflow(_ptr, _inc) \ + ((_ptr) > (UINTPTR_MAX - (_inc))) + +/* + * Evaluates to 1 if (u32 + inc) overflows, 0 otherwise. + * Both arguments must be 32-bit unsigned integers (i.e. effectively uint32_t). + */ +#define check_u32_overflow(_u32, _inc) \ + ((_u32) > (UINT32_MAX - (_inc))) + +/* + * For those constants to be shared between C and other sources, apply a 'U', + * 'UL', 'ULL', 'L' or 'LL' suffix to the argument only in C, to avoid + * undefined or unintended behaviour. + * + * The GNU assembler and linker do not support these suffixes (it causes the + * build process to fail) therefore the suffix is omitted when used in linker + * scripts and assembler files. +*/ +#if defined(__LINKER__) || defined(__ASSEMBLY__) +# define U(_x) (_x) +# define UL(_x) (_x) +# define ULL(_x) (_x) +# define L(_x) (_x) +# define LL(_x) (_x) +#else +# define U(_x) (_x##U) +# define UL(_x) (_x##UL) +# define ULL(_x) (_x##ULL) +# define L(_x) (_x##L) +# define LL(_x) (_x##LL) +#endif + +/* Register size of the current architecture. */ +#ifdef AARCH32 +#define REGSZ U(4) +#else +#define REGSZ U(8) +#endif + +/* + * Test for the current architecture version to be at least the version + * expected. + */ +#define ARM_ARCH_AT_LEAST(_maj, _min) \ + ((ARM_ARCH_MAJOR > (_maj)) || \ + ((ARM_ARCH_MAJOR == (_maj)) && (ARM_ARCH_MINOR >= (_min)))) + +/* + * Import an assembly or linker symbol as a C expression with the specified + * type + */ +#define IMPORT_SYM(type, sym, name) \ + extern char sym[];\ + static const __attribute__((unused)) type name = (type) sym; + +/* + * When the symbol is used to hold a pointer, its alignment can be asserted + * with this macro. For example, if there is a linker symbol that is going to + * be used as a 64-bit pointer, the value of the linker symbol must also be + * aligned to 64 bit. This macro makes sure this is the case. + */ +#define ASSERT_SYM_PTR_ALIGN(sym) assert(((size_t)(sym) % __alignof__(*(sym))) == 0) + + +#endif /* UTILS_DEF_H */ diff --git a/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h b/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h new file mode 100644 index 000000000..37f3b53b7 --- /dev/null +++ b/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_AARCH32_H +#define XLAT_TABLES_AARCH32_H + +#include <arch.h> +#include <utils_def.h> +#include <xlat_tables_defs.h> + +#if !defined(PAGE_SIZE) +#error "PAGE_SIZE is not defined." +#endif + +/* + * In AArch32 state, the MMU only supports 4KB page granularity, which means + * that the first translation table level is either 1 or 2. Both of them are + * allowed to have block and table descriptors. See section G4.5.6 of the + * ARMv8-A Architecture Reference Manual (DDI 0487A.k) for more information. + * + * The define below specifies the first table level that allows block + * descriptors. + */ +#if PAGE_SIZE != PAGE_SIZE_4KB +#error "Invalid granule size. AArch32 supports 4KB pages only." +#endif + +#define MIN_LVL_BLOCK_DESC U(1) + +#define XLAT_TABLE_LEVEL_MIN U(1) + +/* + * Define the architectural limits of the virtual address space in AArch32 + * state. + * + * TTBCR.TxSZ is calculated as 32 minus the width of said address space. The + * value of TTBCR.TxSZ must be in the range 0 to 7 [1], which means that the + * virtual address space width must be in the range 32 to 25 bits. + * + * [1] See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more + * information, Section G4.6.5 + */ +#define MIN_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(32) - TTBCR_TxSZ_MAX)) +#define MAX_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(32) - TTBCR_TxSZ_MIN)) + +/* + * Here we calculate the initial lookup level from the value of the given + * virtual address space size. For a 4 KB page size, + * - level 1 supports virtual address spaces of widths 32 to 31 bits; + * - level 2 from 30 to 25. + * + * Wider or narrower address spaces are not supported. As a result, level 3 + * cannot be used as the initial lookup level with 4 KB granularity. + * See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more + * information, Section G4.6.5 + * + * For example, for a 31-bit address space (i.e. virt_addr_space_size == + * 1 << 31), TTBCR.TxSZ will be programmed to (32 - 31) = 1. According to Table + * G4-5 in the ARM ARM, the initial lookup level for an address space like that + * is 1. + * + * Note that this macro assumes that the given virtual address space size is + * valid. Therefore, the caller is expected to check it is the case using the + * CHECK_VIRT_ADDR_SPACE_SIZE() macro first. + */ +#define GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_sz) \ + (((_virt_addr_space_sz) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT)) ? \ + U(1) : U(2)) + +#endif /* XLAT_TABLES_AARCH32_H */ diff --git a/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h b/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h new file mode 100644 index 000000000..91ca8e477 --- /dev/null +++ b/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_AARCH64_H +#define XLAT_TABLES_AARCH64_H + +#include <arch.h> +#include <utils_def.h> +#include <xlat_tables_defs.h> + +#if !defined(PAGE_SIZE) +#error "PAGE_SIZE is not defined." +#endif + +/* + * Encode a Physical Address Space size for its use in TCR_ELx. + */ +unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr); + +/* + * In AArch64 state, the MMU may support 4 KB, 16 KB and 64 KB page + * granularity. For 4KB granularity, a level 0 table descriptor doesn't support + * block translation. For 16KB, the same thing happens to levels 0 and 1. For + * 64KB, same for level 1. See section D4.3.1 of the ARMv8-A Architecture + * Reference Manual (DDI 0487A.k) for more information. + * + * The define below specifies the first table level that allows block + * descriptors. + */ +#if PAGE_SIZE == PAGE_SIZE_4KB +# define MIN_LVL_BLOCK_DESC U(1) +#elif (PAGE_SIZE == PAGE_SIZE_16KB) || (PAGE_SIZE == PAGE_SIZE_64KB) +# define MIN_LVL_BLOCK_DESC U(2) +#endif + +#define XLAT_TABLE_LEVEL_MIN U(0) + +/* + * Define the architectural limits of the virtual address space in AArch64 + * state. + * + * TCR.TxSZ is calculated as 64 minus the width of said address space. + * The value of TCR.TxSZ must be in the range 16 to 39 [1], which means that + * the virtual address space width must be in the range 48 to 25 bits. + * + * [1] See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more + * information: + * Page 1730: 'Input address size', 'For all translation stages'. + */ +#define MIN_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(64) - TCR_TxSZ_MAX)) +#define MAX_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(64) - TCR_TxSZ_MIN)) + +/* + * Here we calculate the initial lookup level from the value of the given + * virtual address space size. For a 4 KB page size, + * - level 0 supports virtual address spaces of widths 48 to 40 bits; + * - level 1 from 39 to 31; + * - level 2 from 30 to 25. + * + * Wider or narrower address spaces are not supported. As a result, level 3 + * cannot be used as initial lookup level with 4 KB granularity. See section + * D4.2.5 in the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more + * information. + * + * For example, for a 35-bit address space (i.e. virt_addr_space_size == + * 1 << 35), TCR.TxSZ will be programmed to (64 - 35) = 29. According to Table + * D4-11 in the ARM ARM, the initial lookup level for an address space like that + * is 1. + * + * Note that this macro assumes that the given virtual address space size is + * valid. Therefore, the caller is expected to check it is the case using the + * CHECK_VIRT_ADDR_SPACE_SIZE() macro first. + */ +#define GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_sz) \ + (((_virt_addr_space_sz) > (ULL(1) << L0_XLAT_ADDRESS_SHIFT)) \ + ? 0U \ + : (((_virt_addr_space_sz) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT)) \ + ? 1U : 2U)) + +#endif /* XLAT_TABLES_AARCH64_H */ diff --git a/include/lib/xlat_tables/xlat_mmu_helpers.h b/include/lib/xlat_tables/xlat_mmu_helpers.h new file mode 100644 index 000000000..ffb5abe02 --- /dev/null +++ b/include/lib/xlat_tables/xlat_mmu_helpers.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_MMU_HELPERS_H +#define XLAT_MMU_HELPERS_H + +/* + * The following flags are passed to enable_mmu_xxx() to override the default + * values used to program system registers while enabling the MMU. + */ + +/* + * When this flag is used, all data access to Normal memory from this EL and all + * Normal memory accesses to the translation tables of this EL are non-cacheable + * for all levels of data and unified cache until the caches are enabled by + * setting the bit SCTLR_ELx.C. + */ +#define DISABLE_DCACHE (U(1) << 0) + +/* + * Mark the translation tables as non-cacheable for the MMU table walker, which + * is a different observer from the PE/CPU. If the flag is not specified, the + * tables are cacheable for the MMU table walker. + * + * Note that, as far as the PE/CPU observer is concerned, the attributes used + * are the ones specified in the translation tables themselves. The MAIR + * register specifies the cacheability through the field AttrIndx of the lower + * attributes of the translation tables. The shareability is specified in the SH + * field of the lower attributes. + * + * The MMU table walker uses the attributes specified in the fields ORGNn, IRGNn + * and SHn of the TCR register to access the translation tables. + * + * The attributes specified in the TCR register and the tables can be different + * as there are no checks to prevent that. Special care must be taken to ensure + * that there aren't mismatches. The behaviour in that case is described in the + * sections 'Mismatched memory attributes' in the ARMv8 ARM. + */ +#define XLAT_TABLE_NC (U(1) << 1) + +/* + * Offsets into a mmu_cfg_params array generated by setup_mmu_cfg(). All + * parameters are 64 bits wide. + */ +#define MMU_CFG_MAIR 0 +#define MMU_CFG_TCR 1 +#define MMU_CFG_TTBR0 2 +#define MMU_CFG_PARAM_MAX 3 + +#ifndef __ASSEMBLY__ + +#include <stdbool.h> +#include <stdint.h> +#include <sys/types.h> + +/* + * Return the values that the MMU configuration registers must contain for the + * specified translation context. `params` must be a pointer to array of size + * MMU_CFG_PARAM_MAX. + */ +void setup_mmu_cfg(uint64_t *params, unsigned int flags, + const uint64_t *base_table, unsigned long long max_pa, + uintptr_t max_va, int xlat_regime); + +#ifdef AARCH32 +/* AArch32 specific translation table API */ +void enable_mmu_svc_mon(unsigned int flags); +void enable_mmu_hyp(unsigned int flags); + +void enable_mmu_direct_svc_mon(unsigned int flags); +void enable_mmu_direct_hyp(unsigned int flags); +#else +/* AArch64 specific translation table APIs */ +void enable_mmu_el1(unsigned int flags); +void enable_mmu_el2(unsigned int flags); +void enable_mmu_el3(unsigned int flags); + +void enable_mmu_direct_el1(unsigned int flags); +void enable_mmu_direct_el2(unsigned int flags); +void enable_mmu_direct_el3(unsigned int flags); +#endif /* AARCH32 */ + +bool xlat_arch_is_granule_size_supported(size_t size); +size_t xlat_arch_get_max_supported_granule_size(void); + +#endif /* __ASSEMBLY__ */ + +#endif /* XLAT_MMU_HELPERS_H */ diff --git a/include/lib/xlat_tables/xlat_tables_arch.h b/include/lib/xlat_tables/xlat_tables_arch.h new file mode 100644 index 000000000..251b0206a --- /dev/null +++ b/include/lib/xlat_tables/xlat_tables_arch.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_ARCH_H +#define XLAT_TABLES_ARCH_H + +#ifdef AARCH32 +#include "aarch32/xlat_tables_aarch32.h" +#else +#include "aarch64/xlat_tables_aarch64.h" +#endif + +/* + * Evaluates to 1 if the given virtual address space size is valid, or 0 if it's + * not. + * + * A valid size is one that is a power of 2 and is within the architectural + * limits. Not that these limits are different for AArch32 and AArch64. + */ +#define CHECK_VIRT_ADDR_SPACE_SIZE(size) \ + (((unsigned long long)(size) >= MIN_VIRT_ADDR_SPACE_SIZE) && \ + ((unsigned long long)(size) <= MAX_VIRT_ADDR_SPACE_SIZE) && \ + IS_POWER_OF_TWO(size)) + +/* + * Evaluates to 1 if the given physical address space size is a power of 2, + * or 0 if it's not. + */ +#define CHECK_PHY_ADDR_SPACE_SIZE(size) \ + (IS_POWER_OF_TWO(size)) + +/* + * Compute the number of entries required at the initial lookup level to address + * the whole virtual address space. + */ +#define GET_NUM_BASE_LEVEL_ENTRIES(addr_space_size) \ + ((addr_space_size) >> \ + XLAT_ADDR_SHIFT(GET_XLAT_TABLE_LEVEL_BASE(addr_space_size))) + +#endif /* XLAT_TABLES_ARCH_H */ diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h new file mode 100644 index 000000000..d260c3ef0 --- /dev/null +++ b/include/lib/xlat_tables/xlat_tables_defs.h @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_DEFS_H +#define XLAT_TABLES_DEFS_H + +#include <arch.h> +#include <utils_def.h> +#include <xlat_mmu_helpers.h> + +/* Miscellaneous MMU related constants */ +#define NUM_2MB_IN_GB (U(1) << 9) +#define NUM_4K_IN_2MB (U(1) << 9) +#define NUM_GB_IN_4GB (U(1) << 2) + +#define TWO_MB_SHIFT U(21) +#define ONE_GB_SHIFT U(30) +#define FOUR_KB_SHIFT U(12) + +#define ONE_GB_INDEX(x) ((x) >> ONE_GB_SHIFT) +#define TWO_MB_INDEX(x) ((x) >> TWO_MB_SHIFT) +#define FOUR_KB_INDEX(x) ((x) >> FOUR_KB_SHIFT) + +#define PAGE_SIZE_4KB U(4096) +#define PAGE_SIZE_16KB U(16384) +#define PAGE_SIZE_64KB U(65536) + +#define INVALID_DESC U(0x0) +/* + * A block descriptor points to a region of memory bigger than the granule size + * (e.g. a 2MB region when the granule size is 4KB). + */ +#define BLOCK_DESC U(0x1) /* Table levels 0-2 */ +/* A table descriptor points to the next level of translation table. */ +#define TABLE_DESC U(0x3) /* Table levels 0-2 */ +/* + * A page descriptor points to a page, i.e. a memory region whose size is the + * translation granule size (e.g. 4KB). + */ +#define PAGE_DESC U(0x3) /* Table level 3 */ + +#define DESC_MASK U(0x3) + +#define FIRST_LEVEL_DESC_N ONE_GB_SHIFT +#define SECOND_LEVEL_DESC_N TWO_MB_SHIFT +#define THIRD_LEVEL_DESC_N FOUR_KB_SHIFT + +/* XN: Translation regimes that support one VA range (EL2 and EL3). */ +#define XN (ULL(1) << 2) +/* UXN, PXN: Translation regimes that support two VA ranges (EL1&0). */ +#define UXN (ULL(1) << 2) +#define PXN (ULL(1) << 1) +#define CONT_HINT (ULL(1) << 0) +#define UPPER_ATTRS(x) (((x) & ULL(0x7)) << 52) + +#define NON_GLOBAL (U(1) << 9) +#define ACCESS_FLAG (U(1) << 8) +#define NSH (U(0x0) << 6) +#define OSH (U(0x2) << 6) +#define ISH (U(0x3) << 6) + +#define TABLE_ADDR_MASK ULL(0x0000FFFFFFFFF000) + +/* + * The ARMv8-A architecture allows translation granule sizes of 4KB, 16KB or + * 64KB. However, only 4KB are supported at the moment. + */ +#define PAGE_SIZE_SHIFT FOUR_KB_SHIFT +#define PAGE_SIZE (U(1) << PAGE_SIZE_SHIFT) +#define PAGE_SIZE_MASK (PAGE_SIZE - U(1)) +#define IS_PAGE_ALIGNED(addr) (((addr) & PAGE_SIZE_MASK) == U(0)) + +#define XLAT_ENTRY_SIZE_SHIFT U(3) /* Each MMU table entry is 8 bytes (1 << 3) */ +#define XLAT_ENTRY_SIZE (U(1) << XLAT_ENTRY_SIZE_SHIFT) + +#define XLAT_TABLE_SIZE_SHIFT PAGE_SIZE_SHIFT /* Size of one complete table */ +#define XLAT_TABLE_SIZE (U(1) << XLAT_TABLE_SIZE_SHIFT) + +#define XLAT_TABLE_LEVEL_MAX U(3) + +/* Values for number of entries in each MMU translation table */ +#define XLAT_TABLE_ENTRIES_SHIFT (XLAT_TABLE_SIZE_SHIFT - XLAT_ENTRY_SIZE_SHIFT) +#define XLAT_TABLE_ENTRIES (U(1) << XLAT_TABLE_ENTRIES_SHIFT) +#define XLAT_TABLE_ENTRIES_MASK (XLAT_TABLE_ENTRIES - U(1)) + +/* Values to convert a memory address to an index into a translation table */ +#define L3_XLAT_ADDRESS_SHIFT PAGE_SIZE_SHIFT +#define L2_XLAT_ADDRESS_SHIFT (L3_XLAT_ADDRESS_SHIFT + XLAT_TABLE_ENTRIES_SHIFT) +#define L1_XLAT_ADDRESS_SHIFT (L2_XLAT_ADDRESS_SHIFT + XLAT_TABLE_ENTRIES_SHIFT) +#define L0_XLAT_ADDRESS_SHIFT (L1_XLAT_ADDRESS_SHIFT + XLAT_TABLE_ENTRIES_SHIFT) +#define XLAT_ADDR_SHIFT(level) (PAGE_SIZE_SHIFT + \ + ((XLAT_TABLE_LEVEL_MAX - (level)) * XLAT_TABLE_ENTRIES_SHIFT)) + +#define XLAT_BLOCK_SIZE(level) (UL(1) << XLAT_ADDR_SHIFT(level)) +/* Mask to get the bits used to index inside a block of a certain level */ +#define XLAT_BLOCK_MASK(level) (XLAT_BLOCK_SIZE(level) - UL(1)) +/* Mask to get the address bits common to a block of a certain table level*/ +#define XLAT_ADDR_MASK(level) (~XLAT_BLOCK_MASK(level)) +/* + * Extract from the given virtual address the index into the given lookup level. + * This macro assumes the system is using the 4KB translation granule. + */ +#define XLAT_TABLE_IDX(virtual_addr, level) \ + (((virtual_addr) >> XLAT_ADDR_SHIFT(level)) & ULL(0x1FF)) + +/* + * The ARMv8 translation table descriptor format defines AP[2:1] as the Access + * Permissions bits, and does not define an AP[0] bit. + * + * AP[1] is valid only for a stage 1 translation that supports two VA ranges + * (i.e. in the ARMv8A.0 architecture, that is the S-EL1&0 regime). It is RES1 + * when stage 1 translations can only support one VA range. + */ +#define AP2_SHIFT U(0x7) +#define AP2_RO ULL(0x1) +#define AP2_RW ULL(0x0) + +#define AP1_SHIFT U(0x6) +#define AP1_ACCESS_UNPRIVILEGED ULL(0x1) +#define AP1_NO_ACCESS_UNPRIVILEGED ULL(0x0) +#define AP1_RES1 ULL(0x1) + +/* + * The following definitions must all be passed to the LOWER_ATTRS() macro to + * get the right bitmask. + */ +#define AP_RO (AP2_RO << 5) +#define AP_RW (AP2_RW << 5) +#define AP_ACCESS_UNPRIVILEGED (AP1_ACCESS_UNPRIVILEGED << 4) +#define AP_NO_ACCESS_UNPRIVILEGED (AP1_NO_ACCESS_UNPRIVILEGED << 4) +#define AP_ONE_VA_RANGE_RES1 (AP1_RES1 << 4) +#define NS (U(0x1) << 3) +#define ATTR_NON_CACHEABLE_INDEX ULL(0x2) +#define ATTR_DEVICE_INDEX ULL(0x1) +#define ATTR_IWBWA_OWBWA_NTR_INDEX ULL(0x0) +#define LOWER_ATTRS(x) (((x) & U(0xfff)) << 2) + +/* Normal Memory, Outer Write-Through non-transient, Inner Non-cacheable */ +#define ATTR_NON_CACHEABLE MAKE_MAIR_NORMAL_MEMORY(MAIR_NORM_NC, MAIR_NORM_NC) +/* Device-nGnRE */ +#define ATTR_DEVICE MAIR_DEV_nGnRE +/* Normal Memory, Outer Write-Back non-transient, Inner Write-Back non-transient */ +#define ATTR_IWBWA_OWBWA_NTR MAKE_MAIR_NORMAL_MEMORY(MAIR_NORM_WB_NTR_RWA, MAIR_NORM_WB_NTR_RWA) +#define MAIR_ATTR_SET(attr, index) ((attr) << ((index) << 3)) +#define ATTR_INDEX_MASK U(0x3) +#define ATTR_INDEX_GET(attr) (((attr) >> 2) & ATTR_INDEX_MASK) + +/* + * Shift values for the attributes fields in a block or page descriptor. + * See section D4.3.3 in the ARMv8-A ARM (issue B.a). + */ + +/* Memory attributes index field, AttrIndx[2:0]. */ +#define ATTR_INDEX_SHIFT 2 +/* Non-secure bit, NS. */ +#define NS_SHIFT 5 +/* Shareability field, SH[1:0] */ +#define SHAREABILITY_SHIFT 8 +/* The Access Flag, AF. */ +#define ACCESS_FLAG_SHIFT 10 +/* The not global bit, nG. */ +#define NOT_GLOBAL_SHIFT 11 +/* Contiguous hint bit. */ +#define CONT_HINT_SHIFT 52 +/* Execute-never bits, XN. */ +#define PXN_SHIFT 53 +#define XN_SHIFT 54 +#define UXN_SHIFT XN_SHIFT + +#endif /* __XLAT_TABLES_DEFS_H__ */ diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h new file mode 100644 index 000000000..4299c3143 --- /dev/null +++ b/include/lib/xlat_tables/xlat_tables_v2.h @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_V2_H +#define XLAT_TABLES_V2_H + +#include <xlat_tables_defs.h> +#include <xlat_tables_v2_helpers.h> + +#ifndef __ASSEMBLY__ +#include <stddef.h> +#include <stdint.h> +#include <xlat_mmu_helpers.h> + +/* + * Default granularity size for an mmap_region_t. + * Useful when no specific granularity is required. + * + * By default, choose the biggest possible block size allowed by the + * architectural state and granule size in order to minimize the number of page + * tables required for the mapping. + */ +#define REGION_DEFAULT_GRANULARITY XLAT_BLOCK_SIZE(MIN_LVL_BLOCK_DESC) + +/* Helper macro to define an mmap_region_t. */ +#define MAP_REGION(_pa, _va, _sz, _attr) \ + MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, REGION_DEFAULT_GRANULARITY) + +/* Helper macro to define an mmap_region_t with an identity mapping. */ +#define MAP_REGION_FLAT(_adr, _sz, _attr) \ + MAP_REGION(_adr, _adr, _sz, _attr) + +/* + * Helper macro to define entries for mmap_region_t. It allows to define 'pa' + * and sets 'va' to 0 for each region. To be used with mmap_add_alloc_va(). + */ +#define MAP_REGION_ALLOC_VA(pa, sz, attr) MAP_REGION(pa, 0, sz, attr) + +/* + * Helper macro to define an mmap_region_t to map with the desired granularity + * of translation tables. + * + * The granularity value passed to this macro must be a valid block or page + * size. When using a 4KB translation granule, this might be 4KB, 2MB or 1GB. + * Passing REGION_DEFAULT_GRANULARITY is also allowed and means that the library + * is free to choose the granularity for this region. In this case, it is + * equivalent to the MAP_REGION() macro. + */ +#define MAP_REGION2(_pa, _va, _sz, _attr, _gr) \ + MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, _gr) + +/* + * Shifts and masks to access fields of an mmap attribute + */ +#define MT_TYPE_MASK U(0x7) +#define MT_TYPE(_attr) ((_attr) & MT_TYPE_MASK) +/* Access permissions (RO/RW) */ +#define MT_PERM_SHIFT U(3) +/* Security state (SECURE/NS) */ +#define MT_SEC_SHIFT U(4) +/* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */ +#define MT_EXECUTE_SHIFT U(5) +/* In the EL1&0 translation regime, User (EL0) or Privileged (EL1). */ +#define MT_USER_SHIFT U(6) +/* All other bits are reserved */ + +/* + * Memory mapping attributes + */ + +/* + * Memory types supported. + * These are organised so that, going down the list, the memory types are + * getting weaker; conversely going up the list the memory types are getting + * stronger. + */ +#define MT_DEVICE U(0) +#define MT_NON_CACHEABLE U(1) +#define MT_MEMORY U(2) +/* Values up to 7 are reserved to add new memory types in the future */ + +#define MT_RO (U(0) << MT_PERM_SHIFT) +#define MT_RW (U(1) << MT_PERM_SHIFT) + +#define MT_SECURE (U(0) << MT_SEC_SHIFT) +#define MT_NS (U(1) << MT_SEC_SHIFT) + +/* + * Access permissions for instruction execution are only relevant for normal + * read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored (and potentially + * overridden) otherwise: + * - Device memory is always marked as execute-never. + * - Read-write normal memory is always marked as execute-never. + */ +#define MT_EXECUTE (U(0) << MT_EXECUTE_SHIFT) +#define MT_EXECUTE_NEVER (U(1) << MT_EXECUTE_SHIFT) + +/* + * When mapping a region at EL0 or EL1, this attribute will be used to determine + * if a User mapping (EL0) will be created or a Privileged mapping (EL1). + */ +#define MT_USER (U(1) << MT_USER_SHIFT) +#define MT_PRIVILEGED (U(0) << MT_USER_SHIFT) + +/* Compound attributes for most common usages */ +#define MT_CODE (MT_MEMORY | MT_RO | MT_EXECUTE) +#define MT_RO_DATA (MT_MEMORY | MT_RO | MT_EXECUTE_NEVER) +#define MT_RW_DATA (MT_MEMORY | MT_RW | MT_EXECUTE_NEVER) + +#if !ERROR_DEPRECATED +typedef unsigned int mmap_attr_t; +#endif + +/* + * Structure for specifying a single region of memory. + */ +typedef struct mmap_region { + unsigned long long base_pa; + uintptr_t base_va; + size_t size; + unsigned int attr; + /* Desired granularity. See the MAP_REGION2() macro for more details. */ + size_t granularity; +} mmap_region_t; + +/* + * Translation regimes supported by this library. EL_REGIME_INVALID tells the + * library to detect it at runtime. + */ +#define EL1_EL0_REGIME 1 +#define EL2_REGIME 2 +#define EL3_REGIME 3 +#define EL_REGIME_INVALID -1 + +/* + * Declare the translation context type. + * Its definition is private. + */ +typedef struct xlat_ctx xlat_ctx_t; + +/* + * Statically allocate a translation context and associated structures. Also + * initialize them. + * + * _ctx_name: + * Prefix for the translation context variable. + * E.g. If _ctx_name is 'foo', the variable will be called 'foo_xlat_ctx'. + * Useful to distinguish multiple contexts from one another. + * + * _mmap_count: + * Number of mmap_region_t to allocate. + * Would typically be MAX_MMAP_REGIONS for the translation context describing + * the software image currently executing. + * + * _xlat_tables_count: + * Number of sub-translation tables to allocate. + * Would typically be MAX_XLAT_TABLES for the translation context describing + * the software image currently executing. + * Note that this is only for sub-tables ; at the initial lookup level, there + * is always a single table. + * + * _virt_addr_space_size, _phy_addr_space_size: + * Size (in bytes) of the virtual (resp. physical) address space. + * Would typically be PLAT_VIRT_ADDR_SPACE_SIZE + * (resp. PLAT_PHY_ADDR_SPACE_SIZE) for the translation context describing the + * software image currently executing. + */ +#define REGISTER_XLAT_CONTEXT(_ctx_name, _mmap_count, _xlat_tables_count, \ + _virt_addr_space_size, _phy_addr_space_size) \ + REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, (_mmap_count), \ + (_xlat_tables_count), \ + (_virt_addr_space_size), \ + (_phy_addr_space_size), \ + EL_REGIME_INVALID, "xlat_table") + +/* + * Same as REGISTER_XLAT_CONTEXT plus the additional parameters: + * + * _xlat_regime: + * Specify the translation regime managed by this xlat_ctx_t instance. The + * values are the one from the EL*_REGIME definitions. + * + * _section_name: + * Specify the name of the section where the translation tables have to be + * placed by the linker. + */ +#define REGISTER_XLAT_CONTEXT2(_ctx_name, _mmap_count, _xlat_tables_count, \ + _virt_addr_space_size, _phy_addr_space_size, \ + _xlat_regime, _section_name) \ + REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, (_mmap_count), \ + (_xlat_tables_count), \ + (_virt_addr_space_size), \ + (_phy_addr_space_size), \ + (_xlat_regime), (_section_name)) + +/****************************************************************************** + * Generic translation table APIs. + * Each API comes in 2 variants: + * - one that acts on the current translation context for this software image + * - another that acts on the given translation context instead. This variant + * is named after the 1st version, with an additional '_ctx' suffix. + *****************************************************************************/ + +/* + * Initialize translation tables from the current list of mmap regions. Calling + * this function marks the transition point after which static regions can no + * longer be added. + */ +void init_xlat_tables(void); +void init_xlat_tables_ctx(xlat_ctx_t *ctx); + +/* + * Add a static region with defined base PA and base VA. This function can only + * be used before initializing the translation tables. The region cannot be + * removed afterwards. + */ +void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, + size_t size, unsigned int attr); +void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm); + +/* + * Add an array of static regions with defined base PA and base VA. This + * function can only be used before initializing the translation tables. The + * regions cannot be removed afterwards. + */ +void mmap_add(const mmap_region_t *mm); +void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm); + +/* + * Add a region with defined base PA. Returns base VA calculated using the + * highest existing region in the mmap array even if it fails to allocate the + * region. + */ +void mmap_add_region_alloc_va(unsigned long long base_pa, uintptr_t *base_va, + size_t size, unsigned int attr); +void mmap_add_region_alloc_va_ctx(xlat_ctx_t *ctx, mmap_region_t *mm); + +/* + * Add an array of static regions with defined base PA, and fill the base VA + * field on the array of structs. This function can only be used before + * initializing the translation tables. The regions cannot be removed afterwards. + */ +void mmap_add_alloc_va(mmap_region_t *mm); + +#if PLAT_XLAT_TABLES_DYNAMIC +/* + * Add a dynamic region with defined base PA and base VA. This type of region + * can be added and removed even after the translation tables are initialized. + * + * Returns: + * 0: Success. + * EINVAL: Invalid values were used as arguments. + * ERANGE: Memory limits were surpassed. + * ENOMEM: Not enough space in the mmap array or not enough free xlat tables. + * EPERM: It overlaps another region in an invalid way. + */ +int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va, + size_t size, unsigned int attr); +int mmap_add_dynamic_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm); + +/* + * Add a dynamic region with defined base PA. Returns base VA calculated using + * the highest existing region in the mmap array even if it fails to allocate + * the region. + * + * mmap_add_dynamic_region_alloc_va() returns the allocated VA in 'base_va'. + * mmap_add_dynamic_region_alloc_va_ctx() returns it in 'mm->base_va'. + * + * It returns the same error values as mmap_add_dynamic_region(). + */ +int mmap_add_dynamic_region_alloc_va(unsigned long long base_pa, + uintptr_t *base_va, + size_t size, unsigned int attr); +int mmap_add_dynamic_region_alloc_va_ctx(xlat_ctx_t *ctx, mmap_region_t *mm); + +/* + * Remove a region with the specified base VA and size. Only dynamic regions can + * be removed, and they can be removed even if the translation tables are + * initialized. + * + * Returns: + * 0: Success. + * EINVAL: The specified region wasn't found. + * EPERM: Trying to remove a static region. + */ +int mmap_remove_dynamic_region(uintptr_t base_va, size_t size); +int mmap_remove_dynamic_region_ctx(xlat_ctx_t *ctx, + uintptr_t base_va, + size_t size); + +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +/* + * Change the memory attributes of the memory region starting from a given + * virtual address in a set of translation tables. + * + * This function can only be used after the translation tables have been + * initialized. + * + * The base address of the memory region must be aligned on a page boundary. + * The size of this memory region must be a multiple of a page size. + * The memory region must be already mapped by the given translation tables + * and it must be mapped at the granularity of a page. + * + * Return 0 on success, a negative value on error. + * + * In case of error, the memory attributes remain unchanged and this function + * has no effect. + * + * ctx + * Translation context to work on. + * base_va: + * Virtual address of the 1st page to change the attributes of. + * size: + * Size in bytes of the memory region. + * attr: + * New attributes of the page tables. The attributes that can be changed are + * data access (MT_RO/MT_RW), instruction access (MT_EXECUTE_NEVER/MT_EXECUTE) + * and user/privileged access (MT_USER/MT_PRIVILEGED) in the case of contexts + * that are used in the EL1&0 translation regime. Also, note that this + * function doesn't allow to remap a region as RW and executable, or to remap + * device memory as executable. + * + * NOTE: The caller of this function must be able to write to the translation + * tables, i.e. the memory where they are stored must be mapped with read-write + * access permissions. This function assumes it is the case. If this is not + * the case then this function might trigger a data abort exception. + * + * NOTE2: The caller is responsible for making sure that the targeted + * translation tables are not modified by any other code while this function is + * executing. + */ +int xlat_change_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, + size_t size, uint32_t attr); +int xlat_change_mem_attributes(uintptr_t base_va, size_t size, uint32_t attr); + +/* + * Query the memory attributes of a memory page in a set of translation tables. + * + * Return 0 on success, a negative error code on error. + * On success, the attributes are stored into *attr. + * + * ctx + * Translation context to work on. + * base_va + * Virtual address of the page to get the attributes of. + * There are no alignment restrictions on this address. The attributes of the + * memory page it lies within are returned. + * attr + * Output parameter where to store the attributes of the targeted memory page. + */ +int xlat_get_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, + uint32_t *attr); +int xlat_get_mem_attributes(uintptr_t base_va, uint32_t *attr); + +#endif /*__ASSEMBLY__*/ +#endif /* XLAT_TABLES_V2_H */ diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h new file mode 100644 index 000000000..fa8995886 --- /dev/null +++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * This header file contains internal definitions that are not supposed to be + * used outside of this library code. + */ + +#ifndef XLAT_TABLES_V2_HELPERS_H +#define XLAT_TABLES_V2_HELPERS_H + +#ifndef XLAT_TABLES_V2_H +#error "Do not include this header file directly. Include xlat_tables_v2.h instead." +#endif + +#ifndef __ASSEMBLY__ + +#include <cassert.h> +#include <platform_def.h> +#include <stdbool.h> +#include <stddef.h> +#include <xlat_tables_arch.h> +#include <xlat_tables_defs.h> + +/* Forward declaration */ +struct mmap_region; + +/* + * Helper macro to define an mmap_region_t. This macro allows to specify all + * the fields of the structure but its parameter list is not guaranteed to + * remain stable as we add members to mmap_region_t. + */ +#define MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, _gr) \ + { \ + .base_pa = (_pa), \ + .base_va = (_va), \ + .size = (_sz), \ + .attr = (_attr), \ + .granularity = (_gr), \ + } + +/* Struct that holds all information about the translation tables. */ +struct xlat_ctx { + /* + * Max allowed Virtual and Physical Addresses. + */ + unsigned long long pa_max_address; + uintptr_t va_max_address; + + /* + * Array of all memory regions stored in order of ascending end address + * and ascending size to simplify the code that allows overlapping + * regions. The list is terminated by the first entry with size == 0. + * The max size of the list is stored in `mmap_num`. `mmap` points to an + * array of mmap_num + 1 elements, so that there is space for the final + * null entry. + */ + struct mmap_region *mmap; + int mmap_num; + + /* + * Array of finer-grain translation tables. + * For example, if the initial lookup level is 1 then this array would + * contain both level-2 and level-3 entries. + */ + uint64_t (*tables)[XLAT_TABLE_ENTRIES]; + int tables_num; + /* + * Keep track of how many regions are mapped in each table. The base + * table can't be unmapped so it isn't needed to keep track of it. + */ +#if PLAT_XLAT_TABLES_DYNAMIC + int *tables_mapped_regions; +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + + int next_table; + + /* + * Base translation table. It doesn't need to have the same amount of + * entries as the ones used for other levels. + */ + uint64_t *base_table; + unsigned int base_table_entries; + + /* + * Max Physical and Virtual addresses currently in use by the + * translation tables. These might get updated as we map/unmap memory + * regions but they will never go beyond pa/va_max_address. + */ + unsigned long long max_pa; + uintptr_t max_va; + + /* Level of the base translation table. */ + unsigned int base_level; + + /* Set to true when the translation tables are initialized. */ + bool initialized; + + /* + * Translation regime managed by this xlat_ctx_t. It should be one of + * the EL*_REGIME defines. + */ + int xlat_regime; +}; + +#if PLAT_XLAT_TABLES_DYNAMIC +#define XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ + static int _ctx_name##_mapped_regions[_xlat_tables_count]; + +#define XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name) \ + .tables_mapped_regions = _ctx_name##_mapped_regions, +#else +#define XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ + /* do nothing */ + +#define XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name) \ + /* do nothing */ +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +#define REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, \ + _xlat_tables_count, _virt_addr_space_size, \ + _phy_addr_space_size, _xlat_regime, _section_name)\ + CASSERT(CHECK_VIRT_ADDR_SPACE_SIZE(_virt_addr_space_size), \ + assert_invalid_virtual_addr_space_size_for_##_ctx_name);\ + \ + CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size), \ + assert_invalid_physical_addr_space_sizefor_##_ctx_name);\ + \ + static mmap_region_t _ctx_name##_mmap[_mmap_count + 1]; \ + \ + static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count] \ + [XLAT_TABLE_ENTRIES] \ + __aligned(XLAT_TABLE_SIZE) __section(_section_name); \ + \ + static uint64_t _ctx_name##_base_xlat_table \ + [GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)] \ + __aligned(GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)\ + * sizeof(uint64_t)); \ + \ + XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ + \ + static xlat_ctx_t _ctx_name##_xlat_ctx = { \ + .va_max_address = (_virt_addr_space_size) - 1UL, \ + .pa_max_address = (_phy_addr_space_size) - 1ULL, \ + .mmap = _ctx_name##_mmap, \ + .mmap_num = (_mmap_count), \ + .base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\ + .base_table = _ctx_name##_base_xlat_table, \ + .base_table_entries = \ + GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size),\ + .tables = _ctx_name##_xlat_tables, \ + .tables_num = _xlat_tables_count, \ + XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name) \ + .xlat_regime = (_xlat_regime), \ + .max_pa = 0U, \ + .max_va = 0U, \ + .next_table = 0, \ + .initialized = false, \ + } + +#endif /*__ASSEMBLY__*/ + +#endif /* XLAT_TABLES_V2_HELPERS_H */ diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h new file mode 100644 index 000000000..a23fc506f --- /dev/null +++ b/include/plat/arm/common/arm_def.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __ARM_DEF_H__ +#define __ARM_DEF_H__ + +/****************************************************************************** + * Definitions common to all ARM standard platforms + *****************************************************************************/ + +/******************************************************************************* + * Location of the memory buffer shared between Normal World (i.e. TFTF) and the + * Secure Partition (e.g. Cactus) to pass data associated to secure service + * requests. + * Note: This address has to match the one used in TF (see ARM_SP_IMAGE_NS_BUF_* + * macros). + ******************************************************************************/ +#define ARM_SECURE_SERVICE_BUFFER_BASE 0xff600000ull +#define ARM_SECURE_SERVICE_BUFFER_SIZE 0x10000ull + +#endif /* __ARM_DEF_H__ */ diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h new file mode 100644 index 000000000..3b0b5a613 --- /dev/null +++ b/include/plat/arm/common/plat_arm.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_ARM_H__ +#define __PLAT_ARM_H__ + +/* + * Initialises the IO + * Returns: IO_SUCCESS + * IO_FAIL + * IO_NOT_SUPPORTED + * IO_RESOURCES_EXHAUSTED + */ +int arm_io_setup(void); + +/* Initialises the IO and the GIC. */ +void arm_platform_setup(void); + +/******************************************************************************* + * ARM platforms porting interfaces are located below. + ******************************************************************************/ + +/* Initialises the Generic Interrupt Controller (GIC). */ +void plat_arm_gic_init(void); + +#endif /* __PLAT_ARM_H__ */ diff --git a/include/plat/common/plat_topology.h b/include/plat/common/plat_topology.h new file mode 100644 index 000000000..1846b9173 --- /dev/null +++ b/include/plat/common/plat_topology.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_TOPOLOGY_H__ +#define __PLAT_TOPOLOGY_H__ + +#include <arch.h> +#include <platform_def.h> +#include <stdint.h> + +/* + * This is the initial value of the power domain index when used + * as argument to the tftf topology helpers. They are also used + * to indicate the end of iterative topology navigation when returned + * by the tftf topology helpers. + */ +#define PWR_DOMAIN_INIT ((unsigned int) -1) + +/* + * Return the total number of clusters in the system. + * Currently there is correspondence between power level and affinity + * level and hence cluster power level corresponds to affinity level 1. + */ +#define tftf_get_total_clusters_count() tftf_get_total_aff_count(1) + +/* + * Return the total number of CPUs in the system (across all clusters). + * Currently there is correspondence between power level and affinity + * level and hence CPU power level correspond to affinity level 0. + */ +#define tftf_get_total_cpus_count() tftf_get_total_aff_count(0) + +/* + * Converts a 'core_pos' into an MPIDR. The 'core_pos' is a unique number + * corresponding to a CPU as returned by platform_get_core_pos() API + */ +#define tftf_core_pos_to_mpidr(core_pos) \ + tftf_get_mpidr_from_node(core_pos + tftf_pwr_domain_start_idx[0]) + +/* + * The following array stores the start index of each level in the power + * domain topology tree. + */ +extern unsigned int tftf_pwr_domain_start_idx[PLATFORM_MAX_AFFLVL + 1]; + +/* + * The following data structure represents a TFTF power domain node. + */ +typedef struct tftf_pwr_domain_node { + /* + * Array index of the first CPU in the topology array for which this + * power domain is the parent. If this power domain is a CPU, then + * `cpu_start_node` will be its own index in the power domain + * topology array. + */ + unsigned int cpu_start_node; + + /* + * Number of CPU power domains which belong to this power domain. + * i.e. all the CPUs in the range 'cpu_start_node + * -> cpu_start_node + ncpus - 1 ' will belong to this power domain. + * If this power domain is a CPU then 'ncpus' will be 1. + */ + unsigned int ncpus; + + /* Valid only for CPU power domains */ + unsigned int mpidr; + + /* Index of the parent power domain node */ + unsigned int parent_node; + + /* + * The level of this power domain node in the power domain topology + * tree. It could correspond to the affinity level but the platform + * could have power levels which do not match affinity levels. + */ + unsigned int level; + + /* + * The 'is_present' field is used to cater for power domains + * which are absent. + */ + unsigned char is_present; +} tftf_pwr_domain_node_t; + +/* + * Detect and store the platform topology so that test cases can query it later. + */ +void tftf_init_topology(void); + +/* + * Return the number of affinity instances implemented at the affinity level + * passed as an argument. This function returns 0 for any other affinity + * level higher than that supported by the platform. + */ +unsigned int tftf_get_total_aff_count(unsigned int aff_lvl); + +/* + * Returns the index of the next power domain after `pwr_domain_idx` + * in the topology tree at the same `aff_lvl`. The `pwr_domain_idx` + * has to be initialized to PWR_DOMAIN_INIT to get the first entry. + * It returns PWR_DOMAIN_INIT if none is found. + */ +unsigned int tftf_get_next_peer_domain(unsigned int pwr_domain_idx, + unsigned int pwr_lvl); + +/* + * Returns the index of the next CPU after the current CPU `cpu_node` + * which belongs to the power domain `pwr_domain_idx`. The `cpu_node` + * has to be initialized to PWR_DOMAIN_INIT to get the first entry. + * It returns PWR_DOMAIN_INIT if none is found. + */ +unsigned int tftf_get_next_cpu_in_pwr_domain(unsigned int pwr_domain_idx, + unsigned int cpu_node); + +/* + * Return the node index of the next CPU after 'cpu_node' in the topology tree. + * Skip absent CPUs. + * cpu_node: Node index of the current CPU. + */ +unsigned int tftf_topology_next_cpu(unsigned int cpu_node); + +/* + * Iterate over every CPU. Skip absent CPUs. + * cpu: unsigned integer corresponding to the index of the cpu in + * the topology array. After the loop, cpu is equal to PWR_DOMAIN_INIT. + */ +#define for_each_cpu(cpu) \ + for ((cpu) = PWR_DOMAIN_INIT; \ + (cpu) = tftf_topology_next_cpu(cpu), \ + (cpu) != PWR_DOMAIN_INIT;) + +/* + * Iterate over every power domain idx for a given level. + * - idx: unsigned integer corresponding to the power domain index. After the + * loop, idx is equal to PWR_DOMAIN_INIT. + * - lvl: level + */ +#define for_each_power_domain_idx(idx, lvl) \ + for (idx = PWR_DOMAIN_INIT; \ + idx = tftf_get_next_peer_domain(idx, lvl), \ + idx != PWR_DOMAIN_INIT;) + +/* + * Iterate over every CPU in a power domain idx. + * - pwr_domain_idx: unsigned integer corresponding to the power domain index. + * After the loop, idx is equal to PWR_DOMAIN_INIT. + * - cpu_idx: CPU index + */ +#define for_each_cpu_in_power_domain(pwr_domain_idx, cpu_idx) \ + for (cpu_idx = PWR_DOMAIN_INIT; \ + cpu_idx = tftf_get_next_cpu_in_pwr_domain(pwr_domain_idx, cpu_idx),\ + cpu_idx != PWR_DOMAIN_INIT;) + +/* + * Returns the MPIDR of the CPU power domain node indexed by `cpu_node` + * or INVALID_MPID if it is absent. + */ +unsigned int tftf_get_mpidr_from_node(unsigned int cpu_node); + +/* + * Query the platform topology to find another CPU than the one specified + * as an argument. + * Return the MPID of this other CPU, or INVALID_MPID if none could be found. + */ +unsigned int tftf_find_any_cpu_other_than(unsigned int exclude_mpid); + +/* + * Query the platform topology to find a random CPU other than the one specified + * as an argument. + * The difference between this function and tftf_find_any_cpu_other_than is + * the randomness in selecting a CPU. + * Return the MPID of this other CPU, or INVALID_MPID if none could be found. + */ +unsigned int tftf_find_random_cpu_other_than(unsigned int exclude_mpid); + +#endif /* __PLAT_TOPOLOGY_H__ */ diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h new file mode 100644 index 000000000..d3a486c0a --- /dev/null +++ b/include/plat/common/platform.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLATFORM_H__ +#define __PLATFORM_H__ + +#include <stdint.h> +#include <timer.h> +#include <xlat_tables_v2.h> + +#define PLAT_PSCI_DUMMY_STATE_ID 0xF + +#define PWR_STATE_INIT_INDEX (-1) + +#define INIT_PWR_LEVEL_INDEX(array_name) \ + do { \ + unsigned int var; \ + assert(ARRAY_SIZE(array_name) == (PLAT_MAX_PWR_LEVEL + 1)); \ + for (var = 0; var <= PLAT_MAX_PWR_LEVEL; var++) \ + array_name[var] = PWR_STATE_INIT_INDEX; \ + } while (0) + +/* + * The platform structure to represent the valid local power state + * properties for a particular affinity level. The platform needs to + * export the array of valid local low power states for each affinity level + * it supports which can be queried by TFTF tests to construct the required + * composite power state. + * + * TODO: Currently the power levels are identity mapped to affinity level in + * TFTF which need to be decoupled. + */ +typedef struct plat_state_prop { + /* + * This field has a value in the increasing order of the suspend + * depth. Deeper the suspend state, higher the value. + */ + unsigned int suspend_depth; + /* The local state ID for the idle state at this level. */ + unsigned int state_ID; + /* Flag which indicates whether is a retention or power down state */ + unsigned int is_pwrdown; +} plat_state_prop_t; + +void tftf_plat_arch_setup(void); +void tftf_early_platform_setup(void); +void tftf_platform_setup(void); + +void tftf_plat_enable_mmu(void); +void tftf_plat_configure_mmu(void); + +void tftf_platform_end(void); +void tftf_platform_watchdog_set(void); +void tftf_platform_watchdog_reset(void); + +/* Gets a handle for the initialised IO entity */ +void plat_get_nvm_handle(uintptr_t *handle); + +/* + * Returns the platform topology description array. The size of this + * array should be PLATFORM_NUM_AFFS - PLATFORM_CORE_COUNT + 1. + */ +const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void); + +/* + * Function to query the MPIDR of a CPU identified by 'core_pos' which is + * the number returned by platform_get_core() API. + * In case the CPU is absent, then this API returns INVALID_MPID. This + * function will be queried only during topology setup in TFTF and thereafter + * the internal node data will be used to get the MPIDR corresponding + * to the 'core_pos'. + */ +uint64_t tftf_plat_get_mpidr(unsigned int core_pos); + +/* + * Get the state property array for all the valid states from platform for + * a specified 'level'. The array is expected to be NULL terminated after the + * last entry. + */ +const plat_state_prop_t *plat_get_state_prop(unsigned int level); + +/* + * Initialises state info data structures for generating various combinations + * of state ID's. It also calls tftf_detect_pstate_format() which detects the + * PSTATE format accepted by EL3 firmware. + * This function needs to be invoked once during cold boot prior to the + * invocation of any PSCI power state helper functions. + */ +void tftf_init_pstate_framework(void); + +/* + * This function is used to generate all possible combinations of composite + * state ID's possible for a given set of power states at each level. + * Ex: If a system implements 4 levels and each level has 3 local power states. + * Then, the total combinations of composite power down states possible are: + * 3 * 3 * 3 * 3 = 81 + * + * A single call to set_next_state_id_pointers(), sets pointer to pstate_id_idx + * at all levels for a possible combination out of 81. + * + * A caller can confirm when all combinations are completed by checking if + * pwr_lvel_state_indexes for power_level 0 is PWR_STATE_INIT_INDEX + */ +void tftf_set_next_state_id_idx(unsigned int power_level, + unsigned int pstate_id_idx[]); + +/* + * This function sets the index for the next state ID of the given power level + */ +void tftf_set_next_local_state_id_idx(unsigned int power_level, + unsigned int pstate_id_idx[]); + +/* + * This function sets the index corresponding to the deepest power state at + * a given power level. + */ +void tftf_set_deepest_pstate_idx(unsigned int power_level, + unsigned int pstate_id_idx[]); + +/* + * Helper function to get the state ID, state type, power level in power_state + * parameter of CPU_SUSPEND. The generated values are based on the + * pstate_id_idx values of a core. + * + * This helper expects a valid pstate_id_idx till the max valid levels + * and it detects the max valid level to be terminated by PWR_STATE_INIT value + * + * It returns the expected PSCI return value of a suspend request + */ +int tftf_get_pstate_vars(unsigned int *test_power_level, + unsigned int *test_suspend_type, + unsigned int *suspend_state_id, + unsigned int pstate_id_idx[]); + +/* + * This function gets the platform specific timer driver information and + * initialises platform specific drivers. + * Returns 0 on success. + */ +int plat_initialise_timer_ops(const plat_timer_t **timer_ops); + +struct mem_region { + uintptr_t addr; + size_t size; +}; + +typedef struct mem_region mem_region_t; + +/******************************************************************************* + * Optional functions. A default, weak implementation of those functions is + * provided, it may be overridden by platform code. + ******************************************************************************/ +unsigned int platform_get_core_pos(unsigned long mpid); +unsigned long platform_get_stack(unsigned long mpidr); +int plat_crash_console_init(void); +int plat_crash_console_putc(int c); +int plat_crash_console_flush(void); +/* + * plat_get_prot_regions: It returns a pointer to a + * set of regions used to test mem_protect_check. + * The number of elements are stored in the variable + * pointed by nelem. + */ +const mem_region_t *plat_get_prot_regions(int *nelem); + +void tftf_plat_reset(void); + +const mmap_region_t *tftf_platform_get_mmap(void); + +/* + * Return an IO device handle and specification which can be used + * to access an image. Use this to enforce platform load policy. + */ +int plat_get_image_source(unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec); + +void plat_fwu_io_setup(void); + +#endif /* __PLATFORM_H__ */ diff --git a/include/runtime_services/arm_arch_svc.h b/include/runtime_services/arm_arch_svc.h new file mode 100644 index 000000000..12358f8a6 --- /dev/null +++ b/include/runtime_services/arm_arch_svc.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __ARM_ARCH_SVC_H__ +#define __ARM_ARCH_SVC_H__ + +#define SMCCC_VERSION 0x80000000 +#define SMCCC_ARCH_FEATURES 0x80000001 +#define SMCCC_ARCH_WORKAROUND_1 0x80008000 +#define SMCCC_ARCH_WORKAROUND_2 0x80007FFF + +#endif /* __ARM_ARCH_SVC_H__ */ diff --git a/include/runtime_services/pmf.h b/include/runtime_services/pmf.h new file mode 100644 index 000000000..04f79c14f --- /dev/null +++ b/include/runtime_services/pmf.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PMF_H__ +#define __PMF_H__ + +#ifndef __ASSEMBLY__ +#include <assert.h> +#include <platform_def.h> +#include <stdbool.h> +#include <stdint.h> +#endif + +/* + * Constants used for/by PMF services. + */ +#define PMF_ARM_TIF_IMPL_ID 0x41 +#define PMF_TID_SHIFT 0 +#define PMF_TID_MASK (0xFF << PMF_TID_SHIFT) +#define PMF_SVC_ID_SHIFT 10 +#define PMF_SVC_ID_MASK (0x3F << PMF_SVC_ID_SHIFT) +#define PMF_IMPL_ID_SHIFT 24 +#define PMF_IMPL_ID_MASK (0xFFU << PMF_IMPL_ID_SHIFT) + +/* + * Flags passed to PMF_GET_TIMESTAMP_XXX and PMF_CAPTURE_TIMESTAMP + */ +#define PMF_CACHE_MAINT (1 << 0) +#define PMF_NO_CACHE_MAINT 0 + +/* + * Defines for PMF SMC function ids. + */ +#ifdef AARCH32 +#define PMF_SMC_GET_TIMESTAMP 0x82000010 +#else +#define PMF_SMC_GET_TIMESTAMP 0xC2000010 +#endif + +#define PMF_NUM_SMC_CALLS 2 + +/* Following are the supported PMF service IDs */ +#define PMF_PSCI_STAT_SVC_ID 0 +#define PMF_RT_INSTR_SVC_ID 1 + +#endif /* __PMF_H__ */ diff --git a/include/runtime_services/psci.h b/include/runtime_services/psci.h new file mode 100644 index 000000000..1ecfc63d6 --- /dev/null +++ b/include/runtime_services/psci.h @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Definitions related to the Power State Coordination Interface (PSCI) + * as per the SMC Calling Convention. + * + * PSCI calls are a subset of the Standard Service Calls. + */ + +#ifndef __PSCI_H__ +#define __PSCI_H__ + +#ifndef __ASSEMBLY__ +#include <assert.h> +#include <platform_def.h> +#include <stdbool.h> +#include <stdint.h> +#endif + +/******************************************************************************* + * Macro to create the array entry for psci_functions[] + ******************************************************************************/ +#define DEFINE_PSCI_FUNC(_func_id, _mandatory) \ + { SMC_##_func_id, _mandatory, "SMC_" # _func_id } + +/******************************************************************************* + * Defines for runtime services function ids + ******************************************************************************/ +#define SMC_PSCI_VERSION 0x84000000 +#define SMC_PSCI_CPU_SUSPEND_AARCH32 0x84000001 +#define SMC_PSCI_CPU_SUSPEND_AARCH64 0xc4000001 +#define SMC_PSCI_CPU_OFF 0x84000002 +#define SMC_PSCI_CPU_ON_AARCH32 0x84000003 +#define SMC_PSCI_CPU_ON_AARCH64 0xc4000003 +#define SMC_PSCI_AFFINITY_INFO_AARCH32 0x84000004 +#define SMC_PSCI_AFFINITY_INFO_AARCH64 0xc4000004 +#define SMC_PSCI_MIG_AARCH32 0x84000005 +#define SMC_PSCI_MIG_AARCH64 0xc4000005 +#define SMC_PSCI_MIG_INFO_TYPE 0x84000006 +#define SMC_PSCI_MIG_INFO_UP_CPU_AARCH32 0x84000007 +#define SMC_PSCI_MIG_INFO_UP_CPU_AARCH64 0xc4000007 +#define SMC_PSCI_SYSTEM_OFF 0x84000008 +#define SMC_PSCI_SYSTEM_RESET 0x84000009 +#define SMC_PSCI_FEATURES 0x8400000a +#define SMC_PSCI_CPU_FREEZE 0x8400000b +#define SMC_PSCI_CPU_DEFAULT_SUSPEND32 0x8400000c +#define SMC_PSCI_CPU_DEFAULT_SUSPEND64 0xc400000c +#define SMC_PSCI_CPU_HW_STATE32 0x8400000d +#define SMC_PSCI_CPU_HW_STATE64 0xc400000d +#define SMC_PSCI_SYSTEM_SUSPEND32 0x8400000e +#define SMC_PSCI_SYSTEM_SUSPEND64 0xc400000e +#define SMC_PSCI_SET_SUSPEND_MODE 0x8400000f +#define SMC_PSCI_STAT_RESIDENCY32 0x84000010 +#define SMC_PSCI_STAT_RESIDENCY64 0xc4000010 +#define SMC_PSCI_STAT_COUNT32 0x84000011 +#define SMC_PSCI_STAT_COUNT64 0xc4000011 +#define SMC_PSCI_RESET2_AARCH32 0x84000012 +#define SMC_PSCI_RESET2_AARCH64 0xc4000012 +#define SMC_PSCI_MEM_PROTECT 0x84000013 +#define SMC_PSCI_MEM_PROTECT_CHECK_RANGE32 0x84000014 +#define SMC_PSCI_MEM_PROTECT_CHECK_RANGE64 0xc4000014 + +/* + * Architecture-specific SMC function IDs + */ +#ifndef AARCH32 +#define SMC_PSCI_CPU_SUSPEND SMC_PSCI_CPU_SUSPEND_AARCH64 +#define SMC_PSCI_CPU_ON SMC_PSCI_CPU_ON_AARCH64 +#define SMC_PSCI_AFFINITY_INFO SMC_PSCI_AFFINITY_INFO_AARCH64 +#define SMC_PSCI_MIG SMC_PSCI_MIG_AARCH64 +#define SMC_PSCI_MIG_INFO_UP_CPU SMC_PSCI_MIG_INFO_UP_CPU_AARCH64 +#define SMC_PSCI_CPU_DEFAULT_SUSPEND SMC_PSCI_CPU_DEFAULT_SUSPEND64 +#define SMC_PSCI_CPU_HW_STATE SMC_PSCI_CPU_HW_STATE64 +#define SMC_PSCI_SYSTEM_SUSPEND SMC_PSCI_SYSTEM_SUSPEND64 +#define SMC_PSCI_STAT_RESIDENCY SMC_PSCI_STAT_RESIDENCY64 +#define SMC_PSCI_STAT_COUNT SMC_PSCI_STAT_COUNT64 +#define SMC_PSCI_RESET2 SMC_PSCI_RESET2_AARCH64 +#define SMC_PSCI_MEM_PROTECT_CHECK SMC_PSCI_MEM_PROTECT_CHECK_RANGE64 +#else +#define SMC_PSCI_CPU_SUSPEND SMC_PSCI_CPU_SUSPEND_AARCH32 +#define SMC_PSCI_CPU_ON SMC_PSCI_CPU_ON_AARCH32 +#define SMC_PSCI_AFFINITY_INFO SMC_PSCI_AFFINITY_INFO_AARCH32 +#define SMC_PSCI_MIG SMC_PSCI_MIG_AARCH32 +#define SMC_PSCI_MIG_INFO_UP_CPU SMC_PSCI_MIG_INFO_UP_CPU_AARCH32 +#define SMC_PSCI_CPU_DEFAULT_SUSPEND SMC_PSCI_CPU_DEFAULT_SUSPEND32 +#define SMC_PSCI_CPU_HW_STATE SMC_PSCI_CPU_HW_STATE32 +#define SMC_PSCI_SYSTEM_SUSPEND SMC_PSCI_SYSTEM_SUSPEND32 +#define SMC_PSCI_STAT_RESIDENCY SMC_PSCI_STAT_RESIDENCY32 +#define SMC_PSCI_STAT_COUNT SMC_PSCI_STAT_COUNT32 +#define SMC_PSCI_RESET2 SMC_PSCI_RESET2_AARCH32 +#define SMC_PSCI_MEM_PROTECT_CHECK SMC_PSCI_MEM_PROTECT_CHECK_RANGE32 +#endif + +/* + * Number of PSCI calls defined in the PSCI specification. + */ +#define PSCI_NUM_CALLS 33 + +#ifndef __ASSEMBLY__ +typedef struct { + uint32_t id; + bool mandatory; + const char *str; +} psci_function_t; + +extern const psci_function_t psci_functions[PSCI_NUM_CALLS]; +#endif /* __ASSEMBLY__ */ + +/******************************************************************************* + * PSCI Migrate specific defines + ******************************************************************************/ +#define PSCI_TOS_UP_MIG_CAP 0 +#define PSCI_TOS_NOT_UP_MIG_CAP 1 +#define PSCI_TOS_NOT_PRESENT_MP 2 + +/******************************************************************************* + * PSCI CPU_SUSPEND 'power_state' parameter specific defines + ******************************************************************************/ +/* Original format */ +#define PSTATE_ID_SHIFT 0 +#define PSTATE_TYPE_SHIFT 16 +#define PSTATE_AFF_LVL_SHIFT 24 +#define PSTATE_ID_MASK 0xFFFF +#define PSTATE_AFF_LVL_MASK 0x3 + +#define psci_state_id_valid(state_id) \ + (((state_id) & ~PSTATE_ID_MASK) == 0) + +#define psci_affinity_level_valid(aff_level) \ + (((aff_level) & ~PSTATE_AFF_LVL_MASK) == 0) + +/* Extended format */ +#define PSTATE_ID_SHIFT_EXT 0 +#define PSTATE_TYPE_SHIFT_EXT 30 +#define PSTATE_ID_MASK_EXT 0xFFFFFFF + +#define psci_state_id_ext_valid(state_id) \ + (((state_id) & ~PSTATE_ID_MASK_EXT) == 0) + +/* Definitions common to original and extended StateID formats */ +#define PSTATE_TYPE_MASK 0x1 + +#define PSTATE_TYPE_STANDBY 0x0 +#define PSTATE_TYPE_POWERDOWN 0x1 + +#define PSTATE_AFF_LVL_0 0 +#define PSTATE_AFF_LVL_1 1 +#define PSTATE_AFF_LVL_2 2 +#define PSTATE_AFF_LVL_3 3 + +#define psci_state_type_valid(state_type) \ + (((state_type) & ~PSTATE_TYPE_MASK) == 0) + +/******************************************************************************* + * PSCI 'Feature Flags' defines for CPU_SUSPEND + ******************************************************************************/ +#define CPU_SUSPEND_FEAT_OS_INIT_MODE_SHIFT 0 +#define CPU_SUSPEND_FEAT_PSTATE_FORMAT_SHIFT 1 +#define CPU_SUSPEND_FEAT_PSTATE_FORMAT_ORIGINAL 0 +#define CPU_SUSPEND_FEAT_PSTATE_FORMAT_EXTENDED 1 + +#define CPU_SUSPEND_FEAT_VALID_MASK \ + ((1 << CPU_SUSPEND_FEAT_OS_INIT_MODE_SHIFT) | \ + (1 << CPU_SUSPEND_FEAT_PSTATE_FORMAT_SHIFT)) + +/******************************************************************************* + * PSCI 'Feature Flags' defines for functions other than CPU_SUSPEND + ******************************************************************************/ +#define PSCI_FEATURE_FLAGS_ZERO 0 + +#ifndef __ASSEMBLY__ + +/* + * Construct the local State-ID for a particular level according to + * the platform specific local state-ID width. + */ +#define psci_make_local_state_id(level, local_state) \ + (((local_state) & ((1 << PLAT_LOCAL_PSTATE_WIDTH) - 1)) \ + << (PLAT_LOCAL_PSTATE_WIDTH * (level))) +#endif + +/******************************************************************************* + * PSCI version + ******************************************************************************/ +#define PSCI_MAJOR_VER 1 +#define PSCI_MINOR_VER 1 +#define PSCI_MAJOR_VER_SHIFT 16 +#define PSCI_MAJOR_VER_MASK 0xFFFF0000 +#define PSCI_VERSION(major, minor) ((major << PSCI_MAJOR_VER_SHIFT) \ + | minor) + +/******************************************************************************* + * PSCI error codes + ******************************************************************************/ +#define PSCI_E_SUCCESS 0 +#define PSCI_E_NOT_SUPPORTED -1 +#define PSCI_E_INVALID_PARAMS -2 +#define PSCI_E_DENIED -3 +#define PSCI_E_ALREADY_ON -4 +#define PSCI_E_ON_PENDING -5 +#define PSCI_E_INTERN_FAIL -6 +#define PSCI_E_NOT_PRESENT -7 +#define PSCI_E_DISABLED -8 +#define PSCI_E_INVALID_ADDRESS -9 + +/******************************************************************************* + * PSCI affinity state related constants. + ******************************************************************************/ +#define PSCI_STATE_ON 0x0 +#define PSCI_STATE_OFF 0x1 +#define PSCI_STATE_ON_PENDING 0x2 + +/******************************************************************************* + * PSCI node hardware state related constants. + ******************************************************************************/ +#define PSCI_HW_STATE_ON 0x0 +#define PSCI_HW_STATE_OFF 0x1 +#define PSCI_HW_STATE_STANDBY 0x2 + +#endif /* __PSCI_H__ */ diff --git a/include/runtime_services/sdei.h b/include/runtime_services/sdei.h new file mode 100644 index 000000000..0e0a24990 --- /dev/null +++ b/include/runtime_services/sdei.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SDEI_H__ +#define __SDEI_H__ + +#define SDEI_VERSION 0xC4000020 +#define SDEI_EVENT_REGISTER 0xC4000021 +#define SDEI_EVENT_ENABLE 0xC4000022 +#define SDEI_EVENT_DISABLE 0xC4000023 +#define SDEI_EVENT_CONTEXT 0xC4000024 +#define SDEI_EVENT_COMPLETE 0xC4000025 +#define SDEI_EVENT_COMPLETE_AND_RESUME 0xC4000026 + +#define SDEI_EVENT_UNREGISTER 0xC4000027 +#define SDEI_EVENT_STATUS 0xC4000028 +#define SDEI_EVENT_GET_INFO 0xC4000029 +#define SDEI_EVENT_ROUTING_SET 0xC400002A +#define SDEI_PE_MASK 0xC400002B +#define SDEI_PE_UNMASK 0xC400002C + +#define SDEI_INTERRUPT_BIND 0xC400002D +#define SDEI_INTERRUPT_RELEASE 0xC400002E +#define SDEI_EVENT_SIGNAL 0xC400002F +#define SDEI_FEATURES 0xC4000030 +#define SDEI_PRIVATE_RESET 0xC4000031 +#define SDEI_SHARED_RESET 0xC4000032 + +/* For debug */ +#define SDEI_SHOW_DEBUG 0xC400003F + +/* SDEI_EVENT_REGISTER flags */ +#define SDEI_REGF_RM_ANY 0 +#define SDEI_REGF_RM_PE 1 + +/* SDEI_EVENT_COMPLETE status flags */ +#define SDEI_EV_HANDLED 0 +#define SDEI_EV_FAILED 1 + +/* sde event status values in bit position */ +#define SDEI_STATF_REGISTERED 0 +#define SDEI_STATF_ENABLED 1 +#define SDEI_STATF_RUNNING 2 + +#define SDEI_INFOF_TYPE 0 +#define SDEI_INFOF_SIGNALABLE 1 +#define SDEI_INFOF_ROUTING_MODE 2 +#define SDEI_INFOF_ROUTING_AFF 3 + +#define SMC_EINVAL 2 +#define SMC_EDENY 3 +#define SMC_EPEND 5 +#define SMC_ENOMEM 10 + +#define MAKE_SDEI_VERSION(_major, _minor, _vendor) \ + (((uint64_t)(_major)) << 48 | \ + ((uint64_t)(_minor)) << 32 | \ + (_vendor)) + +#ifndef __ASSEMBLY__ +#include <stdint.h> + +struct sdei_intr_ctx { + unsigned int priority; + unsigned int num; + unsigned int enabled; +}; + +typedef int sdei_handler_t(int ev, uint64_t arg); + +void sdei_trigger_event(void); +void sdei_handler_done(void); + +int64_t sdei_version(void); +int64_t sdei_interrupt_bind(int intr, struct sdei_intr_ctx *intr_ctx); +int64_t sdei_interrupt_release(int intr, const struct sdei_intr_ctx *intr_ctx); +int64_t sdei_event_register(int ev, sdei_handler_t *ep, + uint64_t ep_arg, int flags, uint64_t mpidr); +int64_t sdei_event_unregister(int ev); +int64_t sdei_event_enable(int ev); +int64_t sdei_event_disable(int ev); +int64_t sdei_pe_mask(void); +int64_t sdei_pe_unmask(void); +int64_t sdei_private_reset(void); +int64_t sdei_shared_reset(void); +int64_t sdei_event_signal(uint64_t mpidr); +int64_t sdei_event_status(int32_t ev); +int64_t sdei_event_routing_set(int32_t ev, uint64_t flags); +int64_t sdei_event_context(uint32_t param); +int64_t sdei_event_complete(uint32_t flags); +int64_t sdei_event_complete_and_resume(uint64_t addr); +#endif /* __ASSEMBLY__ */ + +#endif /* __SDEI_H__ */ diff --git a/include/runtime_services/secure_el0_payloads/mm_svc.h b/include/runtime_services/secure_el0_payloads/mm_svc.h new file mode 100644 index 000000000..290fd7d1b --- /dev/null +++ b/include/runtime_services/secure_el0_payloads/mm_svc.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __MM_SVC_H__ +#define __MM_SVC_H__ + +#include <utils_def.h> + +#define MM_VERSION_MAJOR U(1) +#define MM_VERSION_MAJOR_SHIFT 16 +#define MM_VERSION_MAJOR_MASK U(0x7FFF) +#define MM_VERSION_MINOR U(0) +#define MM_VERSION_MINOR_SHIFT 0 +#define MM_VERSION_MINOR_MASK U(0xFFFF) +#define MM_VERSION_FORM(major, minor) ((major << MM_VERSION_MAJOR_SHIFT) | (minor)) +#define MM_VERSION_COMPILED MM_VERSION_FORM(MM_VERSION_MAJOR, MM_VERSION_MINOR) + +/* + * SMC IDs defined in [1] for accessing MM services from the Non-secure world. + * These FIDs occupy the range 0x40 - 0x5f. + * [1] DEN0060A_ARM_MM_Interface_Specification.pdf + */ +#define MM_VERSION_AARCH32 U(0x84000040) + +#define MM_COMMUNICATE_AARCH64 U(0xC4000041) +#define MM_COMMUNICATE_AARCH32 U(0x84000041) + +#endif /* __MM_SVC_H__ */ diff --git a/include/runtime_services/secure_el0_payloads/secure_partition.h b/include/runtime_services/secure_el0_payloads/secure_partition.h new file mode 100644 index 000000000..4ee466c80 --- /dev/null +++ b/include/runtime_services/secure_el0_payloads/secure_partition.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SECURE_PARTITION_H__ +#define __SECURE_PARTITION_H__ + +#ifndef __ASSEMBLY__ +#include <cassert.h> +#include <param_header.h> +#include <types.h> +#endif +#include <utils_def.h> + +/* + * Definitions used to access the members of secure_partition_boot_info from + * assembly code. + */ +#define SP_BOOT_INFO_STACK_BASE_OFFSET U(32) +#define SP_BOOT_INFO_IMAGE_SIZE_OFFSET U(64) +#define SP_BOOT_INFO_PCPU_STACK_SIZE_OFFSET U(72) + +#ifndef __ASSEMBLY__ + +/* + * Flags used by the secure_partition_mp_info structure to describe the + * characteristics of a cpu. Only a single flag is defined at the moment to + * indicate the primary cpu. + */ +#define MP_INFO_FLAG_PRIMARY_CPU U(0x00000001) + +/* + * This structure is used to provide information required to initialise a S-EL0 + * partition. + */ +typedef struct secure_partition_mp_info { + uint64_t mpidr; + uint32_t linear_id; + uint32_t flags; +} secure_partition_mp_info_t; + +typedef struct secure_partition_boot_info { + param_header_t h; + uint64_t sp_mem_base; + uint64_t sp_mem_limit; + uint64_t sp_image_base; + uint64_t sp_stack_base; + uint64_t sp_heap_base; + uint64_t sp_ns_comm_buf_base; + uint64_t sp_shared_buf_base; + uint64_t sp_image_size; + uint64_t sp_pcpu_stack_size; + uint64_t sp_heap_size; + uint64_t sp_ns_comm_buf_size; + uint64_t sp_shared_buf_size; + uint32_t num_sp_mem_regions; + uint32_t num_cpus; + secure_partition_mp_info_t *mp_info; +} secure_partition_boot_info_t; + +/* + * This structure is used to pass data associated to secure service requests. + */ +#define SPS_MAX_PAYLOAD_SIZE 32 +typedef struct secure_partition_request_info { + uint32_t id; + uint64_t data_size; + uint8_t data[SPS_MAX_PAYLOAD_SIZE]; +} secure_partition_request_info_t; + +/* Define some fast secure partition requests (SPS) IDs. */ +#define SPS_TIMER_SLEEP 1 +#define SPS_CHECK_ALIVE 2 + +#define CACTUS_FAST_REQUEST_SUCCESS 0xCACF900D + +secure_partition_request_info_t *create_sps_request(uint32_t id, + const void *data, + uint64_t data_size); + +/* + * Compile time assertions related to the 'secure_partition_boot_info' structure + * to ensure that the assembler and the compiler view of the offsets of the + * structure members is the same. + */ +CASSERT(SP_BOOT_INFO_STACK_BASE_OFFSET == + __builtin_offsetof(secure_partition_boot_info_t, sp_stack_base), \ + assert_secure_partition_boot_info_sp_stack_base_offset_mismatch); + +CASSERT(SP_BOOT_INFO_IMAGE_SIZE_OFFSET == + __builtin_offsetof(secure_partition_boot_info_t, sp_image_size), \ + assert_secure_partition_boot_info_sp_image_size_offset_mismatch); + +CASSERT(SP_BOOT_INFO_PCPU_STACK_SIZE_OFFSET == + __builtin_offsetof(secure_partition_boot_info_t, sp_pcpu_stack_size), \ + assert_secure_partition_boot_info_sp_pcpu_stack_size_offset_mismatch); + +#endif /* __ASSEMBLY__ */ + +#endif /* __SECURE_PARTITION_H__ */ diff --git a/include/runtime_services/secure_el0_payloads/spm_svc.h b/include/runtime_services/secure_el0_payloads/spm_svc.h new file mode 100644 index 000000000..e3b6cc517 --- /dev/null +++ b/include/runtime_services/secure_el0_payloads/spm_svc.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SPM_SVC_H__ +#define __SPM_SVC_H__ + +#include <utils_def.h> + +#define SPM_VERSION_MAJOR U(0) +#define SPM_VERSION_MAJOR_SHIFT 16 +#define SPM_VERSION_MAJOR_MASK U(0x7FFF) +#define SPM_VERSION_MINOR U(1) +#define SPM_VERSION_MINOR_SHIFT 0 +#define SPM_VERSION_MINOR_MASK U(0xFFFF) +#define SPM_VERSION_FORM(major, minor) ((major << SPM_VERSION_MAJOR_SHIFT) | (minor)) +#define SPM_VERSION_COMPILED SPM_VERSION_FORM(SPM_VERSION_MAJOR, SPM_VERSION_MINOR) + +/* The macros below are used to identify SPM calls from the SMC function ID */ +#define SPM_FID_MASK U(0xffff) +#define SPM_FID_MIN_VALUE U(0x40) +#define SPM_FID_MAX_VALUE U(0xbf) +#define is_spm_fid(_fid) \ + ((((_fid) & SPM_FID_MASK) >= SPM_FID_MIN_VALUE) && \ + (((_fid) & SPM_FID_MASK) <= SPM_FID_MAX_VALUE)) + +/* + * SMC IDs defined for accessing services implemented by the Secure Partition + * Manager from the Secure Partition(s). These services enable a partition to + * handle delegated events and request privileged operations from the manager. + * They occupy the range 0x60-0x7f. + */ +#define SPM_VERSION_AARCH32 U(0x84000060) +#define SP_EVENT_COMPLETE_AARCH64 U(0xC4000061) +#define SP_MEMORY_ATTRIBUTES_GET_AARCH64 U(0xC4000064) +#define SP_MEMORY_ATTRIBUTES_SET_AARCH64 U(0xC4000065) + +/* + * Macros used by SP_MEMORY_ATTRIBUTES_SET_AARCH64. + */ + +#define SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS U(0) +#define SP_MEMORY_ATTRIBUTES_ACCESS_RW U(1) +/* Value U(2) is reserved. */ +#define SP_MEMORY_ATTRIBUTES_ACCESS_RO U(3) +#define SP_MEMORY_ATTRIBUTES_ACCESS_MASK U(3) +#define SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT 0 + +#define SP_MEMORY_ATTRIBUTES_EXEC (U(0) << 2) +#define SP_MEMORY_ATTRIBUTES_NON_EXEC (U(1) << 2) + +/* SPM error codes. */ +#define SPM_SUCCESS 0 +#define SPM_NOT_SUPPORTED -1 +#define SPM_INVALID_PARAMETER -2 +#define SPM_DENIED -3 +#define SPM_NO_MEMORY -5 +#define SPM_NOT_PRESENT -7 + + +#endif /* __SPM_SVC_H__ */ diff --git a/include/runtime_services/secure_el1_payloads/tsp.h b/include/runtime_services/secure_el1_payloads/tsp.h new file mode 100644 index 000000000..6a4a3d6de --- /dev/null +++ b/include/runtime_services/secure_el1_payloads/tsp.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * This header file contains definitions related to the Trusted Firmware-A + * Test Secure-EL1 Payload (TSP). + */ + +#ifndef __TSP_H__ +#define __TSP_H__ + +#include <psci.h> +#include <uuid.h> + +static const uuid_t tsp_uuid = { + 0x5b3056a0, 0x3291, 0x427b, 0x98, 0x11, + { 0x71, 0x68, 0xca, 0x50, 0xf3, 0xfa } +}; + +/* + * Identifiers for various TSP services. Corresponding function IDs (whether + * fast or standard) are generated by macros defined below + */ +#define TSP_ADD 0x2000 +#define TSP_SUB 0x2001 +#define TSP_MUL 0x2002 +#define TSP_DIV 0x2003 +#define TSP_HANDLE_SEL1_INTR_AND_RETURN 0x2004 + +/* + * Identify a TSP service from function ID filtering the last 16 bits from the + * SMC function ID + */ +#define TSP_BARE_FID(fid) ((fid) & 0xffff) +/* + * Generate function IDs for TSP services to be used in SMC calls, by + * appropriately setting bit 31 to differentiate standard and fast SMC calls + */ +#define TSP_STD_FID(fid) ((TSP_BARE_FID(fid) | 0x72000000)) +#define TSP_FAST_FID(fid) ((TSP_BARE_FID(fid) | 0x72000000) | (1u << 31)) + +/* SMC function ID to request a previously preempted std smc */ +#define TSP_FID_RESUME TSP_STD_FID(0x3000) +/* + * SMC function ID to request abortion of a previously preempted std smc. A + * fast SMC is used so that the TSP abort handler does not have to be + * reentrant. + */ +#define TSP_FID_ABORT TSP_FAST_FID(0x3001) + +#define TSP_SMC_PREEMPTED -2 + +/* + * Total number of function IDs implemented for services offered to NS clients. + * The function IDs are defined above + */ +#define TSP_NUM_FID 0x5 + +/* TSP implementation revision numbers */ +#define TSP_REVISION_MAJOR 0x0 +#define TSP_REVISION_MINOR 0x1 + +/* TSP is multiprocessor capable so does not require migration */ +#define TSP_MIGRATE_INFO PSCI_TOS_NOT_PRESENT_MP + +#endif /* __TSP_H__ */ diff --git a/include/runtime_services/smccc.h b/include/runtime_services/smccc.h new file mode 100644 index 000000000..c8bc1b93f --- /dev/null +++ b/include/runtime_services/smccc.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SMCCC_H__ +#define __SMCCC_H__ + +#include <utils_def.h> + +#define SMCCC_VERSION_MAJOR_SHIFT U(16) +#define SMCCC_VERSION_MAJOR_MASK U(0x7FFF) +#define SMCCC_VERSION_MINOR_SHIFT U(0) +#define SMCCC_VERSION_MINOR_MASK U(0xFFFF) +#define MAKE_SMCCC_VERSION(_major, _minor) \ + ((((uint32_t)(_major) & SMCCC_VERSION_MAJOR_MASK) << \ + SMCCC_VERSION_MAJOR_SHIFT) \ + | (((uint32_t)(_minor) & SMCCC_VERSION_MINOR_MASK) << \ + SMCCC_VERSION_MINOR_SHIFT)) + +#define SMCCC_MAJOR_VERSION 1 +#define SMCCC_MINOR_VERSION 1 + +#define SMC_UNKNOWN -1 + +/* TODO: Import SMCCC 2.0 properly instead of having this */ +#define FUNCID_NAMESPACE_SHIFT U(28) +#define FUNCID_NAMESPACE_MASK U(0x3) +#define FUNCID_NAMESPACE_WIDTH U(2) +#define FUNCID_NAMESPACE_SPRT U(2) +#define FUNCID_NAMESPACE_SPCI U(3) + +/******************************************************************************* + * Bit definitions inside the function id as per the SMC calling convention + ******************************************************************************/ +#define FUNCID_TYPE_SHIFT 31 +#define FUNCID_CC_SHIFT 30 +#define FUNCID_OEN_SHIFT 24 +#define FUNCID_NUM_SHIFT 0 + +#define FUNCID_TYPE_MASK 0x1 +#define FUNCID_CC_MASK 0x1 +#define FUNCID_OEN_MASK 0x3f +#define FUNCID_NUM_MASK 0xffff + +#define FUNCID_TYPE_WIDTH 1 +#define FUNCID_CC_WIDTH 1 +#define FUNCID_OEN_WIDTH 6 +#define FUNCID_NUM_WIDTH 16 + +#define SMC_64 1 +#define SMC_32 0 +#define SMC_TYPE_FAST 1 +#define SMC_TYPE_STD 0 + +/******************************************************************************* + * Owning entity number definitions inside the function id as per the SMC + * calling convention + ******************************************************************************/ +#define OEN_ARM_START 0 +#define OEN_ARM_END 0 +#define OEN_CPU_START 1 +#define OEN_CPU_END 1 +#define OEN_SIP_START 2 +#define OEN_SIP_END 2 +#define OEN_OEM_START 3 +#define OEN_OEM_END 3 +#define OEN_STD_START 4 /* Standard Calls */ +#define OEN_STD_END 4 +#define OEN_TAP_START 48 /* Trusted Applications */ +#define OEN_TAP_END 49 +#define OEN_TOS_START 50 /* Trusted OS */ +#define OEN_TOS_END 63 +#define OEN_LIMIT 64 + +#endif /* __SMCCC_H__ */ diff --git a/include/runtime_services/sprt_svc.h b/include/runtime_services/sprt_svc.h new file mode 100644 index 000000000..e789880b5 --- /dev/null +++ b/include/runtime_services/sprt_svc.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SPRT_SVC_H__ +#define __SPRT_SVC_H__ + +#include <smccc.h> +#include <utils_def.h> + +/* SPRT_VERSION helpers */ +#define SPRT_VERSION_MAJOR U(0) +#define SPRT_VERSION_MAJOR_SHIFT 16 +#define SPRT_VERSION_MAJOR_MASK U(0x7FFF) +/* TODO: Move up minor version to 1 when SPRT is properly supported. */ +#define SPRT_VERSION_MINOR U(0) +#define SPRT_VERSION_MINOR_SHIFT 0 +#define SPRT_VERSION_MINOR_MASK U(0xFFFF) +#define SPRT_VERSION_FORM(major, minor) ((((major) & SPRT_VERSION_MAJOR_MASK) << SPRT_VERSION_MAJOR_SHIFT) | \ + ((minor) & SPRT_VERSION_MINOR_MASK)) +#define SPRT_VERSION_COMPILED SPRT_VERSION_FORM(SPRT_VERSION_MAJOR, SPRT_VERSION_MINOR) + +/* TODO: Check all values below are correct when they're specified in SPRT. */ + +/* SPRT function IDs */ +#define SPRT_FID_VERSION U(0x0) +#define SPRT_FID_RETURN_RESPONSE U(0x1) + +#define SPRT_FID_MASK U(0xFF) + +/* Definitions to build the complete SMC ID */ +#define SPRT_SMC_ID(sprt_fid) ((FUNCID_SERV_SPRT << FUNCID_SERV_SHIFT) | \ + (U(1) << 31) | ((sprt_fid) & SPRT_FID_MASK)) + +/* Complete SMC IDs */ +#define SPRT_VERSION SPRT_SMC_ID(SPRT_FID_VERSION) +#define SPRT_RETURN_RESPONSE SPRT_SMC_ID(SPRT_FID_RETURN_RESPONSE) + +/* SPRT error codes. */ +#define SPRT_SUCCESS 0 +#define SPRT_NOT_SUPPORTED -1 +#define SPRT_INVALID_PARAMETER -2 + +#endif /* __SPRT_SVC_H__ */ diff --git a/include/runtime_services/std_svc.h b/include/runtime_services/std_svc.h new file mode 100644 index 000000000..75ca4e61c --- /dev/null +++ b/include/runtime_services/std_svc.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Definitions related to the Standard Service as per the SMC Calling Convention + * + * Although PSCI calls are part of the Standard Service call range, PSCI-related + * definitions are not in this header file but in psci.h instead. + */ + +#ifndef __STD_SVC_H__ +#define __STD_SVC_H__ + +/* SMC function IDs for Standard Service queries */ +#define SMC_STD_SVC_CALL_COUNT 0x8400ff00 +#define SMC_STD_SVC_UID 0x8400ff01 +/* 0x8400ff02 is reserved */ +#define SMC_STD_SVC_REVISION 0x8400ff03 + +/* Standard Service Calls revision numbers */ +#define STD_SVC_REVISION_MAJOR 0x0 +#define STD_SVC_REVISION_MINOR 0x1 + +#endif /* __STD_SVC_H__ */ diff --git a/include/runtime_services/trusted_os.h b/include/runtime_services/trusted_os.h new file mode 100644 index 000000000..f480c6bcb --- /dev/null +++ b/include/runtime_services/trusted_os.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Definitions related to the Trusted OS Service as per the SMC Calling + * Convention. + */ + +#ifndef __TRUSTED_OS_H__ +#define __TRUSTED_OS_H__ + +#include <uuid.h> + +/* Trusted OS Function IDs that fall under Trusted OS call range */ +#define SMC_TOS_CALL_COUNT 0xbf00ff00 +#define SMC_TOS_UID 0xbf00ff01 +/* 0xbf00ff02 is reserved */ +#define SMC_TOS_REVISION 0xbf00ff03 + +/* + * Detect whether a Trusted OS is present in the software stack. + * This is implemented using the Trusted OS UID SMC call. + * + * If a Trusted OS is detected then this function returns 1 + * and populates 'tos_uuid' with the UUID of the detected Trusted OS. + * Otherwise, this function returns 0 and the value pointed by 'tos_uuid' + * should be ignored. + */ +unsigned int is_trusted_os_present(uuid_t *tos_uuid); + +#endif /* __TRUSTED_OS_H__ */ |