#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#if defined(__aarch64__)
#include <sys/mman.h>
#include <dlfcn.h>
#include <string.h>
#include <stdlib.h>
#include <ucm/bistro/bistro.h>
#include <ucm/bistro/bistro_int.h>
#include <ucm/util/sys.h>
#include <ucs/sys/math.h>
#include <ucs/arch/cpu.h>
#include <ucs/debug/assert.h>
#define R15 15
#define _MOV(_reg, _shift, _val, _opcode) \
(((_opcode) << 23) + ((uint32_t)(_shift) << 21) + ((uint32_t)((_val) & 0xffff) << 5) + (_reg))
#define MOVZ(_reg, _shift, _val) _MOV(_reg, _shift, _val, 0x1a5)
#define MOVK(_reg, _shift, _val) _MOV(_reg, _shift, _val, 0x1e5)
#define BR(_reg) ((0xd61f << 16) + ((_reg) << 5))
ucs_status_t ucm_bistro_patch(void *func_ptr, void *hook, const char *symbol,
void **orig_func_p,
ucm_bistro_restore_point_t **rp)
{
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)
};
ucs_status_t status;
if (orig_func_p != NULL) {
return UCS_ERR_UNSUPPORTED;
}
status = ucm_bistro_create_restore_point(func_ptr, sizeof(patch), rp);
if (UCS_STATUS_IS_ERR(status)) {
return status;
}
return ucm_bistro_apply_patch(func_ptr, &patch, sizeof(patch));
}
#endif