[XTENSA] Add support for cache-aliasing
[pandora-kernel.git] / arch / xtensa / kernel / entry.S
index 65741e3..91a689e 100644 (file)
@@ -7,7 +7,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004-2005 by Tensilica Inc.
+ * Copyright (C) 2004-2007 by Tensilica Inc.
  *
  * Chris Zankel <chris@zankel.net>
  *
@@ -169,7 +169,7 @@ _user_exception:
         * We have to save all registers up to the first '1' from
         * the right, except the current frame (bit 0).
         * Assume a2 is:  001001000110001
-        * All regiser frames starting from the top fiel to the marked '1'
+        * All register frames starting from the top field to the marked '1'
         * must be saved.
         */
 
@@ -1590,7 +1590,7 @@ ENTRY(fast_second_level_miss)
         * The messy computation for 'pteval' above really simplifies
         * into the following:
         *
-        * pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_KERNEL
+        * pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_DIRECTORY
         */
 
        movi    a1, -PAGE_OFFSET
@@ -1602,7 +1602,7 @@ ENTRY(fast_second_level_miss)
        or      a0, a0, a1              # ... | PAGE_DIRECTORY
 
        /*
-        * We utilize all three wired-ways (7-9( to hold pmd translations.
+        * We utilize all three wired-ways (7-9) to hold pmd translations.
         * Memory regions are mapped to the DTLBs according to bits 28 and 29.
         * This allows to map the three most common regions to three different
         * DTLBs:
@@ -1652,6 +1652,73 @@ ENTRY(fast_second_level_miss)
 9:     l32i    a0, a1, TASK_ACTIVE_MM  # unlikely case mm == 0
        j       8b
 
+#if (DCACHE_WAY_SIZE > PAGE_SIZE)
+
+2:     /* Special case for cache aliasing.
+        * We (should) only get here if a clear_user_page, copy_user_page
+        * or the aliased cache flush functions got preemptively interrupted 
+        * by another task. Re-establish temporary mapping to the 
+        * TLBTEMP_BASE areas.
+        */
+
+       /* We shouldn't be in a double exception */
+
+       l32i    a0, a2, PT_DEPC
+       bgeui   a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 2f
+
+       /* Make sure the exception originated in the special functions */
+
+       movi    a0, __tlbtemp_mapping_start
+       rsr     a3, EPC_1
+       bltu    a3, a0, 2f
+       movi    a0, __tlbtemp_mapping_end
+       bgeu    a3, a0, 2f
+
+       /* Check if excvaddr was in one of the TLBTEMP_BASE areas. */
+
+       movi    a3, TLBTEMP_BASE_1
+       rsr     a0, EXCVADDR
+       bltu    a0, a3, 2f
+
+       addi    a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT))
+       bgeu    a1, a3, 2f
+
+       /* Check if we have to restore an ITLB mapping. */
+
+       movi    a1, __tlbtemp_mapping_itlb
+       rsr     a3, EPC_1
+       sub     a3, a3, a1
+
+       /* Calculate VPN */
+
+       movi    a1, PAGE_MASK
+       and     a1, a1, a0
+
+       /* Jump for ITLB entry */
+
+       bgez    a3, 1f
+
+       /* We can use up to two TLBTEMP areas, one for src and one for dst. */
+
+       extui   a3, a0, PAGE_SHIFT + DCACHE_ALIAS_ORDER, 1
+       add     a1, a3, a1
+
+       /* PPN is in a6 for the first TLBTEMP area and in a7 for the second. */
+
+       mov     a0, a6
+       movnez  a0, a7, a3
+       j       3b
+
+       /* ITLB entry. We only use dst in a6. */
+
+1:     witlb   a6, a1
+       isync
+       j       4b
+
+
+#endif // DCACHE_WAY_SIZE > PAGE_SIZE
+
+
 2:     /* Invalid PGD, default exception handling */
 
        movi    a3, exc_table