$(obj)/%.hyp.o: $(obj)/%.hyp.tmp.o FORCE
        $(call if_changed,hypcopy)
 
+# Disable reordering functions by GCC (enabled at -O2).
+# This pass puts functions into '.text.*' sections to aid the linker
+# in optimizing ELF layout. See HYPCOPY comment below for more info.
+ccflags-y += $(call cc-option,-fno-reorder-functions)
+
+# The HYPCOPY command uses `objcopy` to prefix all ELF symbol names
+# and relevant ELF section names to avoid clashes with VHE code/data.
+#
+# Hyp code is assumed to be in the '.text' section of the input object
+# files (with the exception of specialized sections such as
+# '.hyp.idmap.text'). This assumption may be broken by a compiler that
+# divides code into sections like '.text.unlikely' so as to optimize
+# ELF layout. HYPCOPY checks that no such sections exist in the input
+# using `objdump`, otherwise they would be linked together with other
+# kernel code and not memory-mapped correctly at runtime.
 quiet_cmd_hypcopy = HYPCOPY $@
-      cmd_hypcopy = $(OBJCOPY) --prefix-symbols=__kvm_nvhe_            \
-                               --rename-section=.text=.hyp.text        \
-                               $< $@
+      cmd_hypcopy =                                                    \
+       if $(OBJDUMP) -h $< | grep -F '.text.'; then                    \
+               echo "$@: function reordering not supported in nVHE hyp code" >&2; \
+               /bin/false;                                             \
+       fi;                                                             \
+       $(OBJCOPY) --prefix-symbols=__kvm_nvhe_                         \
+                  --rename-section=.text=.hyp.text                     \
+                  $< $@
 
 # Remove ftrace and Shadow Call Stack CFLAGS.
 # This is equivalent to the 'notrace' and '__noscs' annotations.