#include <sys/systm.h>
#include <sys/sdt.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/cpufunc.h>
#include <machine/md_var.h>
#include <machine/vmparam.h>
bool
sdt_tracepoint_valid(uintptr_t patchpoint, uintptr_t target)
{
void *addr;
int64_t offset;
if (!arm64_get_writable_addr((void *)patchpoint, &addr))
return (false);
if (patchpoint == target ||
(patchpoint & (INSN_SIZE - 1)) != 0 ||
(target & (INSN_SIZE - 1)) != 0)
return (false);
offset = target - patchpoint;
if (offset < -(1 << 26) || offset > (1 << 26))
return (false);
return (true);
}
void
sdt_tracepoint_patch(uintptr_t patchpoint, uintptr_t target)
{
void *addr;
uint32_t instr;
KASSERT(sdt_tracepoint_valid(patchpoint, target),
("%s: invalid tracepoint %#lx -> %#lx",
__func__, patchpoint, target));
if (!arm64_get_writable_addr((void *)patchpoint, &addr))
panic("%s: Unable to write new instruction", __func__);
instr = (((target - patchpoint) >> 2) & 0x3fffffful) | 0x14000000;
memcpy(addr, &instr, sizeof(instr));
cpu_icache_sync_range((void *)patchpoint, INSN_SIZE);
}
void
sdt_tracepoint_restore(uintptr_t patchpoint)
{
void *addr;
uint32_t instr;
if (!arm64_get_writable_addr((void *)patchpoint, &addr))
panic("%s: Unable to write new instruction", __func__);
instr = 0xd503201f;
memcpy(addr, &instr, sizeof(instr));
cpu_icache_sync_range((void *)patchpoint, INSN_SIZE);
}