#ifndef __ASM_CACHEFLUSH_H
 #define __ASM_CACHEFLUSH_H
 
+#include <linux/kgdb.h>
 #include <linux/mm.h>
 
 /*
  *             - kaddr  - page address
  *             - size   - region size
  */
-extern void flush_icache_range(unsigned long start, unsigned long end);
+extern void __flush_icache_range(unsigned long start, unsigned long end);
 extern int  invalidate_icache_range(unsigned long start, unsigned long end);
 extern void __flush_dcache_area(void *addr, size_t len);
 extern void __inval_dcache_area(void *addr, size_t len);
 extern long __flush_cache_user_range(unsigned long start, unsigned long end);
 extern void sync_icache_aliases(void *kaddr, unsigned long len);
 
+static inline void flush_icache_range(unsigned long start, unsigned long end)
+{
+       __flush_icache_range(start, end);
+
+       /*
+        * IPI all online CPUs so that they undergo a context synchronization
+        * event and are forced to refetch the new instructions.
+        */
+#ifdef CONFIG_KGDB
+       /*
+        * KGDB performs cache maintenance with interrupts disabled, so we
+        * will deadlock trying to IPI the secondary CPUs. In theory, we can
+        * set CACHE_FLUSH_IS_SAFE to 0 to avoid this known issue, but that
+        * just means that KGDB will elide the maintenance altogether! As it
+        * turns out, KGDB uses IPIs to round-up the secondary CPUs during
+        * the patching operation, so we don't need extra IPIs here anyway.
+        * In which case, add a KGDB-specific bodge and return early.
+        */
+       if (kgdb_connected && irqs_disabled())
+               return;
+#endif
+       kick_all_cpus_sync();
+}
+
 static inline void flush_cache_mm(struct mm_struct *mm)
 {
 }
 
        for (i = 0; i < SZ_2K; i += 0x80)
                memcpy(dst + i, hyp_vecs_start, hyp_vecs_end - hyp_vecs_start);
 
-       flush_icache_range((uintptr_t)dst, (uintptr_t)dst + SZ_2K);
+       __flush_icache_range((uintptr_t)dst, (uintptr_t)dst + SZ_2K);
 }
 
 static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
 
 
        ret = aarch64_insn_write(tp, insn);
        if (ret == 0)
-               flush_icache_range((uintptr_t)tp,
-                                  (uintptr_t)tp + AARCH64_INSN_SIZE);
+               __flush_icache_range((uintptr_t)tp,
+                                    (uintptr_t)tp + AARCH64_INSN_SIZE);
 
        return ret;
 }
                if (ret)
                        return ret;
 
-               if (aarch64_insn_hotpatch_safe(insn, insns[0])) {
-                       /*
-                        * ARMv8 architecture doesn't guarantee all CPUs see
-                        * the new instruction after returning from function
-                        * aarch64_insn_patch_text_nosync(). So send IPIs to
-                        * all other CPUs to achieve instruction
-                        * synchronization.
-                        */
-                       ret = aarch64_insn_patch_text_nosync(addrs[0], insns[0]);
-                       kick_all_cpus_sync();
-                       return ret;
-               }
+               if (aarch64_insn_hotpatch_safe(insn, insns[0]))
+                       return aarch64_insn_patch_text_nosync(addrs[0], insns[0]);
        }
 
        return aarch64_insn_patch_text_sync(addrs, insns, cnt);
 
  *     - start   - virtual start address of region
  *     - end     - virtual end address of region
  */
-ENTRY(flush_icache_range)
+ENTRY(__flush_icache_range)
        /* FALLTHROUGH */
 
 /*
 9:
        mov     x0, #-EFAULT
        b       1b
-ENDPROC(flush_icache_range)
+ENDPROC(__flush_icache_range)
 ENDPROC(__flush_cache_user_range)
 
 /*