andis.  r10,r0,DBCR0_IC@h
        bnel-   load_dbcr0
 #endif
+#ifdef CONFIG_44x
+       lis     r4,icache_44x_need_flush@ha
+       lwz     r5,icache_44x_need_flush@l(r4)
+       cmplwi  cr0,r5,0
+       bne-    2f
+1:
+#endif /* CONFIG_44x */
        stwcx.  r0,0,r1                 /* to clear the reservation */
        lwz     r4,_LINK(r1)
        lwz     r5,_CCR(r1)
        mtspr   SPRN_SRR1,r8
        SYNC
        RFI
+#ifdef CONFIG_44x
+2:     li      r7,0
+       iccci   r0,r0
+       stw     r7,icache_44x_need_flush@l(r4)
+       b       1b
+#endif  /* CONFIG_44x */
 
 66:    li      r3,-ENOSYS
        b       ret_from_syscall
 
        /* interrupts are hard-disabled at this point */
 restore:
+#ifdef CONFIG_44x
+       lis     r4,icache_44x_need_flush@ha
+       lwz     r5,icache_44x_need_flush@l(r4)
+       cmplwi  cr0,r5,0
+       beq+    1f
+       li      r6,0
+       iccci   r0,r0
+       stw     r6,icache_44x_need_flush@l(r4)
+1:
+#endif  /* CONFIG_44x */
        lwz     r0,GPR0(r1)
        lwz     r2,GPR2(r1)
        REST_4GPRS(3, r1)
 
        addi    r3,r3,L1_CACHE_BYTES
        bdnz    0b
        sync
+#ifndef CONFIG_44x
+       /* We don't flush the icache on 44x. Those have a virtual icache
+        * and we don't have access to the virtual address here (it's
+        * not the page vaddr but where it's mapped in user space). The
+        * flushing of the icache on these is handled elsewhere, when
+        * a change in the address space occurs, before returning to
+        * user space
+        */
        mtctr   r4
 1:     icbi    0,r6
        addi    r6,r6,L1_CACHE_BYTES
        bdnz    1b
        sync
        isync
+#endif /* CONFIG_44x */
        blr
 
 /*
 
  */
 unsigned int tlb_44x_index; /* = 0 */
 unsigned int tlb_44x_hwater = PPC44x_TLB_SIZE - 1 - PPC44x_EARLY_TLBS;
+int icache_44x_need_flush;
 
 /*
  * "Pins" a 256MB TLB entry in AS0 for kernel lowmem
 
        andis.  r10,r0,DBCR0_IC@h
        bnel-   load_dbcr0
 #endif
+#ifdef CONFIG_44x
+       lis     r4,icache_44x_need_flush@ha
+       lwz     r5,icache_44x_need_flush@l(r4)
+       cmplwi  cr0,r5,0
+       bne-    2f
+1:
+#endif /* CONFIG_44x */
        stwcx.  r0,0,r1                 /* to clear the reservation */
        lwz     r4,_LINK(r1)
        lwz     r5,_CCR(r1)
        mtspr   SPRN_SRR1,r8
        SYNC
        RFI
+#ifdef CONFIG_44x
+2:     li      r7,0
+       iccci   r0,r0
+       stw     r7,icache_44x_need_flush@l(r4)
+       b       1b
+#endif  /* CONFIG_44x */
 
 66:    li      r3,-ENOSYS
        b       ret_from_syscall
 
        /* interrupts are hard-disabled at this point */
 restore:
+#ifdef CONFIG_44x
+       lis     r4,icache_44x_need_flush@ha
+       lwz     r5,icache_44x_need_flush@l(r4)
+       cmplwi  cr0,r5,0
+       beq+    1f
+       li      r6,0
+       iccci   r0,r0
+       stw     r6,icache_44x_need_flush@l(r4)
+1:
+#endif  /* CONFIG_44x */
        lwz     r0,GPR0(r1)
        lwz     r2,GPR2(r1)
        REST_4GPRS(3, r1)
 
        addi    r3,r3,L1_CACHE_BYTES
        bdnz    0b
        sync
+#ifndef CONFIG_44x
+       /* We don't flush the icache on 44x. Those have a virtual icache
+        * and we don't have access to the virtual address here (it's
+        * not the page vaddr but where it's mapped in user space). The
+        * flushing of the icache on these is handled elsewhere, when
+        * a change in the address space occurs, before returning to
+        * user space
+        */
        mtctr   r4
 1:     icbi    0,r6
        addi    r6,r6,L1_CACHE_BYTES
        bdnz    1b
        sync
        isync
+#endif /* CONFIG_44x */
        blr
 
 /*
 
  */
 unsigned int tlb_44x_index = 0;
 unsigned int tlb_44x_hwater = 62;
+int icache_44x_need_flush;
 
 /*
  * "Pins" a 256MB TLB entry in AS0 for kernel lowmem
 
 extern unsigned long va_to_phys(unsigned long address);
 extern pte_t *va_to_pte(unsigned long address);
 extern unsigned long ioremap_bot, ioremap_base;
+
+#ifdef CONFIG_44x
+extern int icache_44x_need_flush;
+#endif
+
 #endif /* __ASSEMBLY__ */
 
 /*
        : "=&r" (old), "=&r" (tmp), "=m" (*p)
        : "r" (p), "r" (clr), "r" (set), "m" (*p)
        : "cc" );
+#ifdef CONFIG_44x
+       if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC))
+               icache_44x_need_flush = 1;
+#endif
        return old;
 }
 #else
        : "=&r" (old), "=&r" (tmp), "=m" (*p)
        : "r" (p), "r" ((unsigned long)(p) + 4), "r" (clr), "r" (set), "m" (*p)
        : "cc" );
+#ifdef CONFIG_44x
+       if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC))
+               icache_44x_need_flush = 1;
+#endif
        return old;
 }
 #endif