diff --git a/arch/arm/include/asm/pie.h b/arch/arm/include/asm/pie.h
new file mode 100644
index 0000000..977f11d
--- /dev/null
+++ b/arch/arm/include/asm/pie.h
@@ -0,0 +1,42 @@
+/*
+ *  arch/arm/include/asm/pie.h
+ *
+ *  Copyright 2013 Texas Instruments, Inc
+ *	Russ Dill <russ.dill@ti.com>
+ *
+ * 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.
+ */
+
+#ifndef _ASMARM_PIE_H
+#define _ASMARM_PIE_H
+
+#include <linux/pie.h>
+
+#ifdef CONFIG_PIE
+extern void __pie_relocate(void);
+extern void __pie___pie_relocate(void);
+
+#define pie_relocate_from_pie()						\
+	__asm__ __volatile__("bl __pie_relocate\n"			\
+	: : : "cc", "memory", "lr", "r4", "r5", "r6", "r7", "r8", "r9");
+
+static inline void pie_relocate_from_kern(struct pie_chunk *chunk)
+{
+	void (*fn)(void) = fn_to_pie(chunk, &__pie___pie_relocate);
+	__asm__ __volatile__("" : : : "cc", "memory", "r4", "r5", "r6",
+				"r7", "r8", "r9");
+	fn();
+}
+#else
+
+#define pie_relocate_from_pie() do {} while(0)
+
+static inline void pie_relocate_from_kern(struct pie_chunk *chunk)
+{
+}
+
+#endif
+
+#endif
diff --git a/arch/arm/kernel/pie.c b/arch/arm/kernel/pie.c
index 5dff5d6..598562f 100644
--- a/arch/arm/kernel/pie.c
+++ b/arch/arm/kernel/pie.c
@@ -12,10 +12,12 @@
 #include <linux/elf.h>
 
 #include <asm/elf.h>
+#include <asm/pie.h>
 
 extern char __pie_rel_dyn_start[];
 extern char __pie_rel_dyn_end[];
 extern char __pie_tail_offset[];
+extern char __pie_reloc_offset[];
 
 struct arm_pie_tail {
 	int count;
@@ -72,12 +74,19 @@ int pie_arch_fixup(struct pie_chunk *chunk, void *base, void *tail,
 						unsigned long offset)
 {
 	struct arm_pie_tail *pie_tail = tail;
+	void *reloc;
 	int i;
 
 	/* Perform relocation fixups for given offset */
 	for (i = 0; i < pie_tail->count; i++)
 		*((uintptr_t *) (pie_tail->offset[i] + base)) += offset;
 
+	/* Store the PIE offset to tail and recol func */
+	*kern_to_pie(chunk, (uintptr_t *) __pie_tail_offset) = tail - base;
+	reloc = kern_to_pie(chunk,
+				(void *) fnptr_to_addr(&__pie___pie_relocate));
+	*kern_to_pie(chunk, (uintptr_t *) __pie_reloc_offset) = reloc - base;
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(pie_arch_fixup);
diff --git a/arch/arm/libpie/Makefile b/arch/arm/libpie/Makefile
index 5662e99..b1ac52a 100644
--- a/arch/arm/libpie/Makefile
+++ b/arch/arm/libpie/Makefile
@@ -3,7 +3,7 @@
 #
 ccflags-y	:= -fpic -mno-single-pic-base -fno-builtin
 
-obj-y		:= empty.o
+obj-y		:= relocate.o empty.o
 obj-y		+= lib1funcs.o ashldi3.o string.o
 
 # string library code (-Os is enforced to keep it much smaller)
diff --git a/arch/arm/libpie/relocate.S b/arch/arm/libpie/relocate.S
new file mode 100644
index 0000000..70cc36e
--- /dev/null
+++ b/arch/arm/libpie/relocate.S
@@ -0,0 +1,76 @@
+/*
+ * arch/arm/libpie/relocate.S - Relocation updating for PIEs
+ *
+ * Copyright 2013 Texas Instruments, Inc.
+ *	Russ Dill <russ.dill@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+
+/*
+ * Update relocations based on current pc
+ *
+ * On exit:
+ *  r4-r9 corrupted
+ */
+
+ENTRY(__pie_relocate)
+	/* Calculate offset of our code compared to existing relocations */
+	ldr	r4, pie_relocate_address
+	adr	r5, __pie_relocate
+	subs	r6, r5, r4
+	moveq	pc, lr			/* 0 offset, no need to do anything */
+
+	/* Base of PIE group */
+	ldr	r7, reloc_offset
+	sub	r5, r5, r7
+
+	/* Calculate address of tail */
+	ldr	r7, tail_offset
+	add	r7, r7, r5
+
+	/* First byte of tail is number of entries */
+	ldr	r8, [r7], #4
+	add	r8, r7, r8, lsl #2
+
+	/*
+	 * r5 - current base address of PIE group
+	 * r6 - fixup offset needed for relocs
+	 * r7 - relocs start
+	 * r8 - relocs end
+	 */
+
+1:
+	cmp	r7, r8
+	ldrne	r4, [r7], #4	/* Load next reloc offset */
+
+	addne	r4, r4, r5	/* Calculate address of reloc entry */
+	ldrne	r9, [r4]
+	addne	r9, r9, r6	/* Fixup reloc entry */
+	strne	r9, [r4]
+
+	bne	1b
+
+	mov	pc, lr
+ENDPROC(__pie_relocate)
+
+/*
+ * This ends up in the .rel.dyn section and can be used to read the current
+ * relocation offset
+ */
+pie_relocate_address:
+	.long 	__pie_relocate
+
+/* Offset from PIE section start to reloc function */
+.global reloc_offset
+reloc_offset:
+	.space	4
+
+/* Offset from PIE section start to tail */
+.globl tail_offset
+tail_offset:
+	.space	4
