BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
register_gateway.h
00001 /* 00002 * Copyright (c) 2015-2015, ARM Limited, All Rights Reserved 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00006 * not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 #ifndef __UVISOR_API_REGISTER_GATEWAY_H__ 00018 #define __UVISOR_API_REGISTER_GATEWAY_H__ 00019 00020 #include "api/inc/register_gateway_exports.h" 00021 #include "api/inc/uvisor_exports.h" 00022 #include "api/inc/svc_exports.h" 00023 #include <stdint.h> 00024 00025 /** Get the offset of a struct member. 00026 * @internal 00027 */ 00028 #define __UVISOR_OFFSETOF(type, member) ((uint32_t) (&(((type *)(0))->member))) 00029 00030 /** Generate the SVCall opcode from the SVC ID. */ 00031 #define UVISOR_SVC_OPCODE(id) ((uint16_t) (0xDF00 | ((id) & 0xFF))) 00032 00033 /** Generate the opcode of the 16-bit Thumb-2 16-bit T2 encoding of the branch 00034 * instruction. 00035 * @internal 00036 * @note The branch instruction is encoded according to the Thumb-2 immediate 00037 * encoding rules: 00038 * <instr_addr>: B.N <label> 00039 * imm = (<label>_addr - PC) / 2 00040 * Where: 00041 * PC = <instr>_addr + 4 00042 * The +4 is to account for the pipelined PC at the time of the branch 00043 * instruction. See ARM DDI 0403E.b page A4-102 for more details. 00044 * @param instr[in] Address of the branch instruction 00045 * @param label[in] Address of the label 00046 * @returns the 16-bit encoding of the B.N <label> instruction. 00047 */ 00048 #define BRANCH_OPCODE(instr, label) \ 00049 (uint16_t) (0xE000 | (uint8_t) ((((uint32_t) (label) - ((uint32_t) (instr) + 4)) / 2) & 0xFF)) 00050 00051 /** `BX LR` encoding 00052 * @internal 00053 */ 00054 #define BXLR ((uint16_t) 0x4770) 00055 00056 /** Register Gateway - Read operation 00057 * 00058 * This macro provides an API to perform 32-bit read operations on restricted 00059 * registers. Such accesses are assembled into a read-only flash structure that 00060 * is read and validated by uVisor before performing the operation. 00061 * 00062 * @warning This API currently only supports link-time known value for the 00063 * address, operation and mask. 00064 * 00065 * @param box_name[in] The name of the source box as decalred in 00066 * `UVISOR_BOX_CONFIG`. 00067 * @param shared[in] Whether the gateway can be shared with other boxes or 00068 * not. Two values are available: UVISOR_RGW_SHARED, 00069 * UVISOR_RGW_EXCLUSIVE. 00070 * @param addr[in] The address for the data access. 00071 * @param operation[in] The operation to perform at the address for the read. It 00072 * is chosen among the `UVISOR_RGW_OP_*` macros. 00073 * @param mask[in] The mask to apply for the read operation. 00074 * @returns The value read from address using the operation and mask provided 00075 * (or their respective defaults if they have not been provided). 00076 */ 00077 #define uvisor_read(box_name, shared, addr, op, msk) \ 00078 ({ \ 00079 /* Instanstiate the gateway. This gets resolved at link-time. */ \ 00080 UVISOR_ALIGN(4) static TRegisterGateway const register_gateway = { \ 00081 .svc_opcode = UVISOR_SVC_OPCODE(UVISOR_SVC_ID_REGISTER_GATEWAY), \ 00082 .branch = BRANCH_OPCODE(__UVISOR_OFFSETOF(TRegisterGateway, branch), \ 00083 __UVISOR_OFFSETOF(TRegisterGateway, bxlr)), \ 00084 .magic = UVISOR_REGISTER_GATEWAY_MAGIC, \ 00085 .box_ptr = (uint32_t) & box_name ## _cfg_ptr, \ 00086 .address = (uint32_t) addr, \ 00087 .mask = msk, \ 00088 .operation = UVISOR_RGW_OP(op, sizeof(*addr), shared), \ 00089 .bxlr = BXLR \ 00090 }; \ 00091 \ 00092 /* Pointer to the register gateway we just created. The pointer is 00093 * located in a discoverable linker section. */ \ 00094 __attribute__((section(".keep.uvisor.register_gateway_ptr"))) \ 00095 static uint32_t const register_gateway_ptr = (uint32_t) ®ister_gateway; \ 00096 (void) register_gateway_ptr; \ 00097 \ 00098 /* Call the actual gateway. */ \ 00099 uint32_t result = ((uint32_t (*)(void)) ((uint32_t) ®ister_gateway | 1))(); \ 00100 (typeof(*addr)) result; \ 00101 }) 00102 00103 /** Register Gateway - Write operation 00104 * 00105 * This macro provides an API to perform 32-bit write operations on restricted 00106 * registers. Such accesses are assembled into a read-only flash structure that 00107 * is read and validated by uVisor before performing the operation. 00108 * 00109 * @warning This API currently only supports link-time known value for the 00110 * address, operation and mask. 00111 * 00112 * @param box_name[in] The name of the source box as decalred in 00113 * `UVISOR_BOX_CONFIG`. 00114 * @param shared[in] Whether the gateway can be shared with other boxes or 00115 * not. Two values are available: UVISOR_RGW_SHARED, 00116 * UVISOR_RGW_EXCLUSIVE. 00117 * @param addr[in] The address for the data access. 00118 * @param val[in] The value to write at address. 00119 * @param operation[in] The operation to perform at the address for the read. It 00120 * is chosen among the `UVISOR_RGW_OP_*` macros. 00121 * @param mask[in] The mask to apply for the write operation. 00122 */ 00123 #define uvisor_write(box_name, shared, addr, val, op, msk) \ 00124 { \ 00125 /* Instanstiate the gateway. This gets resolved at link-time. */ \ 00126 UVISOR_ALIGN(4) static TRegisterGateway const register_gateway = { \ 00127 .svc_opcode = UVISOR_SVC_OPCODE(UVISOR_SVC_ID_REGISTER_GATEWAY), \ 00128 .branch = BRANCH_OPCODE(__UVISOR_OFFSETOF(TRegisterGateway, branch), \ 00129 __UVISOR_OFFSETOF(TRegisterGateway, bxlr)), \ 00130 .magic = UVISOR_REGISTER_GATEWAY_MAGIC, \ 00131 .box_ptr = (uint32_t) & box_name ## _cfg_ptr, \ 00132 .address = (uint32_t) addr, \ 00133 .mask = msk, \ 00134 .operation = UVISOR_RGW_OP(op, sizeof(*addr), shared), \ 00135 .bxlr = BXLR \ 00136 }; \ 00137 \ 00138 /* Pointer to the register gateway we just created. The pointer is 00139 * located in a discoverable linker section. */ \ 00140 __attribute__((section(".keep.uvisor.register_gateway_ptr"))) \ 00141 static uint32_t const register_gateway_ptr = (uint32_t) ®ister_gateway; \ 00142 (void) register_gateway_ptr; \ 00143 \ 00144 /* Call the actual gateway. 00145 * The value is passed as the first argument. */ \ 00146 ((void (*)(uint32_t)) ((uint32_t) ((uint32_t) ®ister_gateway | 1)))((uint32_t) (val)); \ 00147 } 00148 00149 /** Get the selected bits at the target address. 00150 * @param box_name[in] Box name as defined by the uVisor box configuration 00151 * macro `UVISOR_BOX_CONFIG` 00152 * @param shared[in] Whether the gateway can be shared with other boxes or 00153 * not. Two values are available: UVISOR_RGW_SHARED, 00154 * UVISOR_RGW_EXCLUSIVE. 00155 * @param address[in] Target address 00156 * @param mask[in] Bits to select out of the target address 00157 * @returns The value `*address & mask`. 00158 */ 00159 #define UVISOR_BITS_GET(box_name, shared, address, mask) \ 00160 /* Register gateway implementation: 00161 * *address & mask */ \ 00162 uvisor_read(box_name, shared, address, UVISOR_RGW_OP_READ_AND, mask) 00163 00164 /** Check the selected bits at the target address. 00165 * @param box_name[in] Box name as defined by the uVisor box configuration 00166 * macro `UVISOR_BOX_CONFIG` 00167 * @param shared[in] Whether the gateway can be shared with other boxes or 00168 * not. Two values are available: UVISOR_RGW_SHARED, 00169 * UVISOR_RGW_EXCLUSIVE. 00170 * @param address[in] Address at which to check the bits 00171 * @param mask[in] Bits to select out of the target address 00172 * @returns The value `((*address & mask) == mask)`. 00173 */ 00174 #define UVISOR_BITS_CHECK(box_name, shared, address, mask) \ 00175 ((UVISOR_BITS_GET(box_name, shared, address, mask)) == (mask)) 00176 00177 /** Set the selected bits to 1 at the target address. 00178 * 00179 * Equivalent to: `*address |= mask`. 00180 * @param box_name[in] Box name as defined by the uVisor box configuration 00181 * macro `UVISOR_BOX_CONFIG` 00182 * @param shared[in] Whether the gateway can be shared with other boxes or 00183 * not. Two values are available: UVISOR_RGW_SHARED, 00184 * UVISOR_RGW_EXCLUSIVE. 00185 * @param address[in] Target address 00186 * @param mask[in] Bits to select out of the target address 00187 */ 00188 #define UVISOR_BITS_SET(box_name, shared, address, mask) \ 00189 /* Register gateway implementation: 00190 * *address |= (mask & mask) */ \ 00191 uvisor_write(box_name, shared, address, mask, UVISOR_RGW_OP_WRITE_OR, mask) 00192 00193 /** Clear the selected bits at the target address. 00194 * 00195 * Equivalent to: `*address &= ~mask`. 00196 * @param box_name[in] Box name as defined by the uVisor box configuration 00197 * macro `UVISOR_BOX_CONFIG` 00198 * @param shared[in] Whether the gateway can be shared with other boxes or 00199 * not. Two values are available: UVISOR_RGW_SHARED, 00200 * UVISOR_RGW_EXCLUSIVE. 00201 * @param address[in] Target address 00202 * @param mask[in] Bits to select out of the target address 00203 */ 00204 #define UVISOR_BITS_CLEAR(box_name, shared, address, mask) \ 00205 /* Register gateway implementation: 00206 * *address &= (0x00000000 | ~mask) */ \ 00207 uvisor_write(box_name, shared, address, 0x00000000, UVISOR_RGW_OP_WRITE_AND, mask) 00208 00209 /** Set the selected bits at the target address to the given value. 00210 * 00211 * Equivalent to: `*address = (*address & ~mask) | (value & mask)`. 00212 * @param box_name[in] Box name as defined by the uVisor box configuration 00213 * macro `UVISOR_BOX_CONFIG` 00214 * @param shared[in] Whether the gateway can be shared with other boxes or 00215 * not. Two values are available: UVISOR_RGW_SHARED, 00216 * UVISOR_RGW_EXCLUSIVE. 00217 * @param address[in] Target address 00218 * @param mask[in] Bits to select out of the target address 00219 * @param value[in] Value to write at the address location. Note: The value 00220 * must be already shifted to the correct bit position 00221 */ 00222 #define UVISOR_BITS_SET_VALUE(box_name, shared, address, mask, value) \ 00223 /* Register gateway implementation: 00224 * *address = (*address & ~mask) | (value & mask) */ \ 00225 uvisor_write(box_name, shared, address, value, UVISOR_RGW_OP_WRITE_REPLACE, mask) 00226 00227 /** Toggle the selected bits at the target address. 00228 * 00229 * Equivalent to: `*address ^= mask`. 00230 * @param box_name[in] Box name as defined by the uVisor box configuration 00231 * macro `UVISOR_BOX_CONFIG` 00232 * @param shared[in] Whether the gateway can be shared with other boxes or 00233 * not. Two values are available: UVISOR_RGW_SHARED, 00234 * UVISOR_RGW_EXCLUSIVE. 00235 * @param address[in] Target address 00236 * @param mask[in] Bits to select out of the target address 00237 */ 00238 #define UVISOR_BITS_TOGGLE(box_name, shared, address, mask) \ 00239 /* Register gateway implementation: 00240 * *address ^= (0xFFFFFFFF & mask) */ \ 00241 uvisor_write(box_name, shared, address, 0xFFFFFFFF, UVISOR_RGW_OP_WRITE_XOR, mask) 00242 00243 #endif /* __UVISOR_API_REGISTER_GATEWAY_H__ */
Generated on Tue Jul 12 2022 12:22:18 by
