This means that that `old_size` **MUST** be at least four bytes if patching
in trampoline.
+The instruction offset is limited on ARM32 to +/- 32MB to displacement
+and on ARM64 to +/- 128MB displacement.
+
The new code is placed in the 8M - 10M virtual address space while the
Xen code is in 2M - 4M. That gives us enough space.
else
insn = aarch64_insn_gen_nop();
+ /* Verified in livepatch_verify_distance. */
ASSERT(insn != AARCH64_BREAK_FAULT);
new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
rc = resolve_old_address(f, elf);
if ( rc )
return rc;
+
+ rc = livepatch_verify_distance(f);
+ if ( rc )
+ return rc;
}
sec = livepatch_elf_sec_by_name(elf, ".livepatch.hooks.load");
#ifndef __XEN_ARM_LIVEPATCH_H__
#define __XEN_ARM_LIVEPATCH_H__
+#include <xen/sizes.h> /* For SZ_* macros. */
+
/* On ARM32,64 instructions are always 4 bytes long. */
#define ARCH_PATCH_INSN_SIZE 4
*/
extern void *vmap_of_xen_text;
+/* These ranges are only for unconditional branches. */
+#ifdef CONFIG_ARM_32
+/* ARM32: A4.3 IN ARM DDI 0406C.c - we are using only ARM instructions in Xen.*/
+#define ARCH_LIVEPATCH_RANGE SZ_32M
+#else
+/* ARM64: C1.3.2 in ARM DDI 0487A.j */
+#define ARCH_LIVEPATCH_RANGE SZ_128M
+#endif
+
#endif /* __XEN_ARM_LIVEPATCH_H__ */
/*
#ifndef __XEN_X86_LIVEPATCH_H__
#define __XEN_X86_LIVEPATCH_H__
+#include <xen/sizes.h> /* For SZ_* macros. */
+
#define ARCH_PATCH_INSN_SIZE 5
+#define ARCH_LIVEPATCH_RANGE SZ_2G
#endif /* __XEN_X86_LIVEPATCH_H__ */
struct xen_sysctl_livepatch_op;
#include <xen/elfstructs.h>
+#include <xen/errno.h> /* For -ENOSYS or -EOVERFLOW */
#ifdef CONFIG_LIVEPATCH
/*
return ARCH_PATCH_INSN_SIZE;
}
+
+static inline int livepatch_verify_distance(const struct livepatch_func *func)
+{
+ long offset;
+ long range = ARCH_LIVEPATCH_RANGE;
+
+ if ( !func->new_addr ) /* Ignore NOPs. */
+ return 0;
+
+ offset = func->old_addr - func->new_addr;
+ if ( offset < -range || offset >= range )
+ return -EOVERFLOW;
+
+ return 0;
+}
/*
* These functions are called around the critical region patching live code,
* for an architecture to take make appropratie global state adjustments.
#define init_or_livepatch_data __initdata
#define init_or_livepatch __init
-#include <xen/errno.h> /* For -ENOSYS */
static inline int livepatch_op(struct xen_sysctl_livepatch_op *op)
{
return -ENOSYS;