Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers register_gateway.h Source File

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) &register_gateway; \
00096         (void) register_gateway_ptr; \
00097         \
00098         /* Call the actual gateway. */ \
00099         uint32_t result = ((uint32_t (*)(void)) ((uint32_t) &register_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) &register_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) &register_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__ */