Exemple #1
0
void arch_livepatch_revert(const struct livepatch_func *func)
{
    uint32_t *new_ptr;
    unsigned int len;

    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;

    len = livepatch_insn_len(func);
    memcpy(new_ptr, func->opaque, len);

    clean_and_invalidate_dcache_va_range(new_ptr, len);
}
Exemple #2
0
void arch_livepatch_apply(struct livepatch_func *func)
{
    uint32_t insn;
    uint32_t *new_ptr;
    unsigned int i, len;

    BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE > sizeof(func->opaque));
    BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE != sizeof(insn));

    ASSERT(vmap_of_xen_text);

    len = livepatch_insn_len(func);
    if ( !len )
        return;

    /* Save old ones. */
    memcpy(func->opaque, func->old_addr, len);

    if ( func->new_addr )
    {
        s32 delta;

        /*
         * PC is current address (old_addr) + 8 bytes. The semantics for a
         * unconditional branch is to jump to PC + imm32 (offset).
         *
         * ARM DDI 0406C.c, see A2.3 (pg 45) and A8.8.18 pg (pg 334,335)
         *
         */
        delta = (s32)func->new_addr - (s32)(func->old_addr + 8);

        /* The arch_livepatch_symbol_ok should have caught it. */
        ASSERT(delta >= -(s32)ARCH_LIVEPATCH_RANGE ||
               delta < (s32)ARCH_LIVEPATCH_RANGE);

        /* CPU shifts by two (left) when decoding, so we shift right by two. */
        delta = delta >> 2;
        /* Lets not modify the cond. */
        delta &= 0x00FFFFFF;

        insn = 0xea000000 | delta;
    }