diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 2e023d1..43123e6 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -12,11 +12,11 @@ config ARM_32
 config ARM_64
 	def_bool y
 	depends on 64BIT
-	select HAS_ALTERNATIVE
 	select HAS_GICV3
 
 config ARM
 	def_bool y
+	select HAS_ALTERNATIVE
 	select HAS_ARM_HDLCD
 	select HAS_DEVICE_TREE
 	select HAS_MEM_ACCESS
diff --git a/xen/arch/arm/arm32/Makefile b/xen/arch/arm/arm32/Makefile
index 4395693..0ac254f 100644
--- a/xen/arch/arm/arm32/Makefile
+++ b/xen/arch/arm/arm32/Makefile
@@ -4,6 +4,7 @@ obj-$(EARLY_PRINTK) += debug.o
 obj-y += domctl.o
 obj-y += domain.o
 obj-y += entry.o
+obj-y += insn.o
 obj-$(CONFIG_LIVEPATCH) += livepatch.o
 obj-y += proc-v7.o proc-caxx.o
 obj-y += smpboot.o
diff --git a/xen/arch/arm/arm32/insn.c b/xen/arch/arm/arm32/insn.c
new file mode 100644
index 0000000..7a5dbc5
--- /dev/null
+++ b/xen/arch/arm/arm32/insn.c
@@ -0,0 +1,91 @@
+/*
+  * Copyright (C) 2017 ARM Ltd.
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  *
+  * You should have received a copy of the GNU General Public License
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  */
+#include <xen/lib.h>
+#include <xen/bitops.h>
+#include <xen/sizes.h>
+#include <asm/insn.h>
+
+/* Mask of branch instructions' immediate. */
+#define BRANCH_INSN_IMM_MASK    GENMASK(23, 0)
+/* Shift of branch instructions' immediate. */
+#define BRANCH_INSN_IMM_SHIFT   0
+
+static uint32_t branch_insn_encode_immediate(uint32_t insn, int32_t offset)
+{
+    uint32_t imm;
+
+    /*
+     * Encode the offset to imm. All ARM32 instructions must be word aligned.
+     * Therefore the offset value's bits [1:0] equal to zero.
+     * (see ARM DDI 0406C.c A8.8.18/A8.8.25 for more encode/decode details
+     * about ARM32 branch instructions)
+     */
+    imm = ((offset >> 2) & BRANCH_INSN_IMM_MASK) << BRANCH_INSN_IMM_SHIFT;
+
+    /* Update the immediate field. */
+    insn &= ~(BRANCH_INSN_IMM_MASK << BRANCH_INSN_IMM_SHIFT);
+    insn |= imm;
+
+    return insn;
+}
+
+/*
+ * Decode the branch offset from a branch instruction's imm field.
+ * The branch offset is a signed value, so it can be used to compute
+ * a new branch target.
+ */
+int32_t aarch32_get_branch_offset(uint32_t insn)
+{
+    uint32_t imm;
+
+    /* Retrieve imm from branch instruction. */
+    imm = ( insn >> BRANCH_INSN_IMM_SHIFT ) & BRANCH_INSN_IMM_MASK;
+
+    /*
+     * Check the imm signed bit. If the imm is a negative value, we
+     * have to extend the imm to a full 32 bit negative value.
+     */
+    if ( imm & BIT(23) )
+        imm |= GENMASK(31, 24);
+
+    return (int32_t)(imm << 2);
+}
+
+/*
+ * Encode the displacement of a branch in the imm field and return the
+ * updated instruction.
+ */
+uint32_t aarch32_set_branch_offset(uint32_t insn, int32_t offset)
+{
+    /* B/BL support [-32M, 32M) offset (see ARM DDI 0406C.c A4.3). */
+    if ( offset < -SZ_32M || offset >= SZ_32M )
+    {
+        printk(XENLOG_ERR
+               "%s: new branch offset out of range.\n", __func__);
+        return BUG_OPCODE;
+    }
+
+    return branch_insn_encode_immediate(insn, offset);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index 246e673..f14bcbc 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -25,6 +25,7 @@
 #include <xen/livepatch.h>
 #include <xen/livepatch_payload.h>
 
+#include <asm/alternative.h>
 #include <asm/event.h>
 
 /*
diff --git a/xen/include/asm-arm/arm32/insn.h b/xen/include/asm-arm/arm32/insn.h
new file mode 100644
index 0000000..c800cbf
--- /dev/null
+++ b/xen/include/asm-arm/arm32/insn.h
@@ -0,0 +1,71 @@
+/*
+  * Copyright (C) 2017 ARM Ltd.
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  *
+  * You should have received a copy of the GNU General Public License
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  */
+#ifndef __ARCH_ARM_ARM32_INSN
+#define __ARCH_ARM_ARM32_INSN
+
+#include <xen/types.h>
+
+int32_t aarch32_get_branch_offset(uint32_t insn);
+uint32_t aarch32_set_branch_offset(uint32_t insn, int32_t offset);
+
+/* Wrapper for common code */
+static inline bool insn_is_branch_imm(uint32_t insn)
+{
+    /*
+     * Xen is using ARM execution state only on ARM32 platform. So, the
+     * Thumb branch instructions (CBZ, CBNZ, TBB and TBH) will not be used
+     * in Xen. The left ARM32 branch instructions are BX, BLX, BL and B.
+     * BX is using register as parameter, we don't need to rewrite it. So,
+     * we only need to check BLX, BL and B encodings in this function.
+     *
+     * From ARM DDI 0406C.c Section A8.8.18 and A8.8.25, we can see these
+     * three branch instructions' encodings:
+     * - b   cccc1010xxxxxxxxxxxxxxxxxxxxxxxx
+     * - bl  cccc1011xxxxxxxxxxxxxxxxxxxxxxxx
+     * - blx 1111101Hxxxxxxxxxxxxxxxxxxxxxxxx
+     *
+     * The H bit of blx can be 0 or 1, it depends on the Instruction Sets of
+     * target instruction. Regardless, if we mask the conditional bits and
+     * bit 24 (H bit of blx), we can see all above branch instructions have
+     * the same value 0x0A000000.
+     *
+     * And from ARM DDI 0406C.c Section A5.7 Table A5-23, we can see that the
+     * blx is the only one unconditional instruction has the same value as
+     * conditional branch instructions. So, mask the conditional bits will not
+     * make other unconditional instruction to hit this check.
+     */
+    return ( (insn & 0x0E000000) == 0x0A000000 );
+}
+
+static inline int32_t insn_get_branch_offset(uint32_t insn)
+{
+    return aarch32_get_branch_offset(insn);
+}
+
+static inline uint32_t insn_set_branch_offset(uint32_t insn, int32_t offset)
+{
+    return aarch32_set_branch_offset(insn, offset);
+}
+
+#endif /* !__ARCH_ARM_ARM32_INSN */
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/insn.h b/xen/include/asm-arm/insn.h
index a205ceb..3489179 100644
--- a/xen/include/asm-arm/insn.h
+++ b/xen/include/asm-arm/insn.h
@@ -5,6 +5,8 @@
 
 #if defined(CONFIG_ARM_64)
 # include <asm/arm64/insn.h>
+#elif defined(CONFIG_ARM_32)
+# include <asm/arm32/insn.h>
 #else
 # error "unknown ARM variant"
 #endif
