diff --git a/arch/Kconfig b/arch/Kconfig
index 29b0167c088b..16eb5ad1f83e 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -1032,7 +1032,9 @@ config HAVE_STACK_VALIDATION
 	bool
 	help
 	  Architecture supports the 'objtool check' host tool command, which
-	  performs compile-time stack metadata validation.
+	  performs compile-time stack metadata validation. Or, on architectures
+	  that use dynamic frame pointer validation, it supports the
+	  'objtool fpv generate' host tool command.
 
 config HAVE_RELIABLE_STACKTRACE
 	bool
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 57c4c995965f..e6a7bfc85ff9 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -223,6 +223,8 @@ config ARM64
 	select SWIOTLB
 	select SYSCTL_EXCEPTION_TRACE
 	select THREAD_INFO_IN_TASK
+	select HAVE_STACK_VALIDATION	if FRAME_POINTER_VALIDATION
+	select STACK_VALIDATION		if HAVE_STACK_VALIDATION
 	select HAVE_ARCH_USERFAULTFD_MINOR if USERFAULTFD
 	select TRACE_IRQFLAGS_SUPPORT
 	help
diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
index 265c4461031f..37a7a90331d0 100644
--- a/arch/arm64/Kconfig.debug
+++ b/arch/arm64/Kconfig.debug
@@ -20,4 +20,25 @@ config ARM64_RELOC_TEST
 	depends on m
 	tristate "Relocation testing module"
 
+config UNWINDER_ORC
+	bool "ORC unwinder"
+	depends on FRAME_POINTER_VALIDATION
+	select HAVE_MOD_ARCH_SPECIFIC
+	help
+	  This option enables ORC (Oops Rewind Capability) for ARM64. This
+	  allows the unwinder to look up ORC data for an instruction address
+	  and compute the frame pointer at that address. The computed frame
+	  pointer is used to validate the actual frame pointer.
+
+config FRAME_POINTER_VALIDATION
+	bool "Dynamic Frame pointer validation"
+	depends on FRAME_POINTER
+	select UNWINDER_ORC
+	help
+		This invokes objtool on every object file causing it to
+		generate ORC data for the object file. ORC data is in a custom
+		data format which is a simplified version of the DWARF
+		Call Frame Information standard. See UNWINDER_ORC for more
+		details.
+
 source "drivers/hwtracing/coresight/Kconfig"
diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h
index 4e7fa2623896..a15cddf11224 100644
--- a/arch/arm64/include/asm/module.h
+++ b/arch/arm64/include/asm/module.h
@@ -6,6 +6,7 @@
 #define __ASM_MODULE_H
 
 #include <asm-generic/module.h>
+#include <asm/orc_types.h>
 
 #ifdef CONFIG_ARM64_MODULE_PLTS
 struct mod_plt_sec {
@@ -13,15 +14,22 @@ struct mod_plt_sec {
 	int			plt_num_entries;
 	int			plt_max_entries;
 };
+#endif
 
 struct mod_arch_specific {
+#ifdef CONFIG_ARM64_MODULE_PLTS
 	struct mod_plt_sec	core;
 	struct mod_plt_sec	init;
 
 	/* for CONFIG_DYNAMIC_FTRACE */
 	struct plt_entry	*ftrace_trampolines;
-};
 #endif
+#ifdef CONFIG_UNWINDER_ORC
+	unsigned int num_orcs;
+	int *orc_unwind_ip;
+	struct orc_entry *orc_unwind;
+#endif
+};
 
 u64 module_emit_plt_entry(struct module *mod, Elf64_Shdr *sechdrs,
 			  void *loc, const Elf64_Rela *rela,
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index edaf0faf766f..7a4fa5404541 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -61,6 +61,7 @@
 #define RUNTIME_DISCARD_EXIT
 
 #include <asm-generic/vmlinux.lds.h>
+#include <asm-generic/orc_lookup.h>
 #include <asm/cache.h>
 #include <asm/kernel-pgtable.h>
 #include <asm/kexec.h>
@@ -291,6 +292,8 @@ SECTIONS
 		__mmuoff_data_end = .;
 	}
 
+	ORC_UNWIND_TABLE
+
 	PECOFF_EDATA_PADDING
 	__pecoff_data_rawsize = ABSOLUTE(. - __initdata_begin);
 	_edata = .;
diff --git a/scripts/Makefile b/scripts/Makefile
index ce5aa9030b74..abcda21c1bb9 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -20,8 +20,10 @@ HOSTLDLIBS_sign-file = $(shell pkg-config --libs libcrypto 2> /dev/null || echo
 ifdef CONFIG_UNWINDER_ORC
 ifeq ($(ARCH),x86_64)
 ARCH := x86
-endif
 HOSTCFLAGS_sorttable.o += -I$(srctree)/tools/arch/x86/include
+else
+HOSTCFLAGS_sorttable.o += -I$(srctree)/tools/arch/$(ARCH)/include
+endif
 HOSTCFLAGS_sorttable.o += -DUNWINDER_ORC_ENABLED
 endif
 
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 9717e6f6fb31..7d370b498a6b 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -226,6 +226,9 @@ ifdef CONFIG_STACK_VALIDATION
 
 objtool := $(objtree)/tools/objtool/objtool
 
+ifdef CONFIG_FRAME_POINTER_VALIDATION
+objtool_args = fpv generate
+else
 objtool_args =								\
 	$(if $(CONFIG_UNWINDER_ORC),orc generate,check)			\
 	$(if $(part-of-module), --module)				\
@@ -236,6 +239,7 @@ objtool_args =								\
 	$(if $(CONFIG_X86_SMAP), --uaccess)				\
 	$(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount)		\
 	$(if $(CONFIG_SLS), --sls)
+endif
 
 cmd_objtool = $(if $(objtool-enabled), ; $(objtool) $(objtool_args) $@)
 cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(objtool))' ; } >> $(dot-target).cmd)
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 20f44504a644..ea0a85370e0f 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -108,6 +108,13 @@ objtool_link()
 	local objtoolcmd;
 	local objtoolopt;
 
+	if is_enabled CONFIG_STACK_VALIDATION && \
+	   is_enabled CONFIG_FRAME_POINTER_VALIDATION && \
+	   is_enabled CONFIG_LTO_CLANG; then
+		tools/objtool/objtool fpv generate ${1}
+		return
+	fi
+
 	if is_enabled CONFIG_STACK_VALIDATION && \
 	   ( is_enabled CONFIG_LTO_CLANG || is_enabled CONFIG_X86_KERNEL_IBT ); then
 
