/** * Copyright (C) Mellanox Technologies Ltd. 2018. ALL RIGHTS RESERVED. * * See file LICENSE for terms. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif /* ******************************************************* * ARM processors family * * ***************************************************** */ #if defined(__aarch64__) #include #include #include #include #include #include #include #include #include #include /* Register number used to store indirect jump address. * r15 is the highest numbered temporary register, assuming this one is safe * to use. */ #define R15 15 #define _MOV(_reg, _shift, _val, _opcode) \ (((_opcode) << 23) + ((uint32_t)(_shift) << 21) + ((uint32_t)((_val) & 0xffff) << 5) + (_reg)) /** * @brief Generate a mov immediate instruction * * @param[in] _reg register number (0-31) * @param[in] _shift shift amount (0-3) * 16-bits * @param[in] _value immediate value */ #define MOVZ(_reg, _shift, _val) _MOV(_reg, _shift, _val, 0x1a5) /** * @brief Generate a mov immediate with keep instruction * * @param[in] _reg register number (0-31) * @param[in] _shift shift amount (0-3) * 16-bits * @param[in] _value immediate value */ #define MOVK(_reg, _shift, _val) _MOV(_reg, _shift, _val, 0x1e5) /** * @brief Branch to address stored in register * * @param[in] _reg register number (0-31) */ #define BR(_reg) ((0xd61f << 16) + ((_reg) << 5)) ucs_status_t ucm_bistro_patch(const char *symbol, void *hook, ucm_bistro_restore_point_t **rp) { void *func; ucs_status_t status; ucm_bistro_patch_t patch = { .reg3 = MOVZ(R15, 3, (uintptr_t)hook >> 48), .reg2 = MOVK(R15, 2, (uintptr_t)hook >> 32), .reg1 = MOVK(R15, 1, (uintptr_t)hook >> 16), .reg0 = MOVK(R15, 0, (uintptr_t)hook), .br = BR(R15) }; UCM_LOOKUP_SYMBOL(func, symbol); status = ucm_bistro_create_restore_point(func, rp); if (UCS_STATUS_IS_ERR(status)) { return status; } return ucm_bistro_apply_patch(func, &patch, sizeof(patch)); } #endif