diff options
Diffstat (limited to 'arch/xtensa/kernel/entry.S')
-rw-r--r-- | arch/xtensa/kernel/entry.S | 115 |
1 files changed, 98 insertions, 17 deletions
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 8dc7a2c26ff9..91a689eca43d 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S | |||
@@ -7,7 +7,7 @@ | |||
7 | * License. See the file "COPYING" in the main directory of this archive | 7 | * License. See the file "COPYING" in the main directory of this archive |
8 | * for more details. | 8 | * for more details. |
9 | * | 9 | * |
10 | * Copyright (C) 2004-2005 by Tensilica Inc. | 10 | * Copyright (C) 2004-2007 by Tensilica Inc. |
11 | * | 11 | * |
12 | * Chris Zankel <chris@zankel.net> | 12 | * Chris Zankel <chris@zankel.net> |
13 | * | 13 | * |
@@ -169,7 +169,7 @@ _user_exception: | |||
169 | * We have to save all registers up to the first '1' from | 169 | * We have to save all registers up to the first '1' from |
170 | * the right, except the current frame (bit 0). | 170 | * the right, except the current frame (bit 0). |
171 | * Assume a2 is: 001001000110001 | 171 | * Assume a2 is: 001001000110001 |
172 | * All regiser frames starting from the top fiel to the marked '1' | 172 | * All register frames starting from the top field to the marked '1' |
173 | * must be saved. | 173 | * must be saved. |
174 | */ | 174 | */ |
175 | 175 | ||
@@ -1572,10 +1572,12 @@ ENTRY(fast_second_level_miss) | |||
1572 | l32i a0, a1, TASK_MM # tsk->mm | 1572 | l32i a0, a1, TASK_MM # tsk->mm |
1573 | beqz a0, 9f | 1573 | beqz a0, 9f |
1574 | 1574 | ||
1575 | 8: rsr a1, EXCVADDR # fault address | 1575 | |
1576 | _PGD_OFFSET(a0, a1, a1) | 1576 | /* We deliberately destroy a3 that holds the exception table. */ |
1577 | |||
1578 | 8: rsr a3, EXCVADDR # fault address | ||
1579 | _PGD_OFFSET(a0, a3, a1) | ||
1577 | l32i a0, a0, 0 # read pmdval | 1580 | l32i a0, a0, 0 # read pmdval |
1578 | //beqi a0, _PAGE_USER, 2f | ||
1579 | beqz a0, 2f | 1581 | beqz a0, 2f |
1580 | 1582 | ||
1581 | /* Read ptevaddr and convert to top of page-table page. | 1583 | /* Read ptevaddr and convert to top of page-table page. |
@@ -1588,7 +1590,7 @@ ENTRY(fast_second_level_miss) | |||
1588 | * The messy computation for 'pteval' above really simplifies | 1590 | * The messy computation for 'pteval' above really simplifies |
1589 | * into the following: | 1591 | * into the following: |
1590 | * | 1592 | * |
1591 | * pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_KERNEL | 1593 | * pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_DIRECTORY |
1592 | */ | 1594 | */ |
1593 | 1595 | ||
1594 | movi a1, -PAGE_OFFSET | 1596 | movi a1, -PAGE_OFFSET |
@@ -1596,20 +1598,34 @@ ENTRY(fast_second_level_miss) | |||
1596 | extui a1, a0, 0, PAGE_SHIFT # ... & PAGE_MASK | 1598 | extui a1, a0, 0, PAGE_SHIFT # ... & PAGE_MASK |
1597 | xor a0, a0, a1 | 1599 | xor a0, a0, a1 |
1598 | 1600 | ||
1599 | 1601 | movi a1, _PAGE_DIRECTORY | |
1600 | movi a1, PAGE_DIRECTORY | ||
1601 | or a0, a0, a1 # ... | PAGE_DIRECTORY | 1602 | or a0, a0, a1 # ... | PAGE_DIRECTORY |
1602 | 1603 | ||
1604 | /* | ||
1605 | * We utilize all three wired-ways (7-9) to hold pmd translations. | ||
1606 | * Memory regions are mapped to the DTLBs according to bits 28 and 29. | ||
1607 | * This allows to map the three most common regions to three different | ||
1608 | * DTLBs: | ||
1609 | * 0,1 -> way 7 program (0040.0000) and virtual (c000.0000) | ||
1610 | * 2 -> way 8 shared libaries (2000.0000) | ||
1611 | * 3 -> way 0 stack (3000.0000) | ||
1612 | */ | ||
1613 | |||
1614 | extui a3, a3, 28, 2 # addr. bit 28 and 29 0,1,2,3 | ||
1603 | rsr a1, PTEVADDR | 1615 | rsr a1, PTEVADDR |
1616 | addx2 a3, a3, a3 # -> 0,3,6,9 | ||
1604 | srli a1, a1, PAGE_SHIFT | 1617 | srli a1, a1, PAGE_SHIFT |
1618 | extui a3, a3, 2, 2 # -> 0,0,1,2 | ||
1605 | slli a1, a1, PAGE_SHIFT # ptevaddr & PAGE_MASK | 1619 | slli a1, a1, PAGE_SHIFT # ptevaddr & PAGE_MASK |
1606 | addi a1, a1, DTLB_WAY_PGD # ... + way_number | 1620 | addi a3, a3, DTLB_WAY_PGD |
1621 | add a1, a1, a3 # ... + way_number | ||
1607 | 1622 | ||
1608 | wdtlb a0, a1 | 1623 | 3: wdtlb a0, a1 |
1609 | dsync | 1624 | dsync |
1610 | 1625 | ||
1611 | /* Exit critical section. */ | 1626 | /* Exit critical section. */ |
1612 | 1627 | ||
1628 | 4: movi a3, exc_table # restore a3 | ||
1613 | movi a0, 0 | 1629 | movi a0, 0 |
1614 | s32i a0, a3, EXC_TABLE_FIXUP | 1630 | s32i a0, a3, EXC_TABLE_FIXUP |
1615 | 1631 | ||
@@ -1636,8 +1652,76 @@ ENTRY(fast_second_level_miss) | |||
1636 | 9: l32i a0, a1, TASK_ACTIVE_MM # unlikely case mm == 0 | 1652 | 9: l32i a0, a1, TASK_ACTIVE_MM # unlikely case mm == 0 |
1637 | j 8b | 1653 | j 8b |
1638 | 1654 | ||
1655 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) | ||
1656 | |||
1657 | 2: /* Special case for cache aliasing. | ||
1658 | * We (should) only get here if a clear_user_page, copy_user_page | ||
1659 | * or the aliased cache flush functions got preemptively interrupted | ||
1660 | * by another task. Re-establish temporary mapping to the | ||
1661 | * TLBTEMP_BASE areas. | ||
1662 | */ | ||
1663 | |||
1664 | /* We shouldn't be in a double exception */ | ||
1665 | |||
1666 | l32i a0, a2, PT_DEPC | ||
1667 | bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 2f | ||
1668 | |||
1669 | /* Make sure the exception originated in the special functions */ | ||
1670 | |||
1671 | movi a0, __tlbtemp_mapping_start | ||
1672 | rsr a3, EPC_1 | ||
1673 | bltu a3, a0, 2f | ||
1674 | movi a0, __tlbtemp_mapping_end | ||
1675 | bgeu a3, a0, 2f | ||
1676 | |||
1677 | /* Check if excvaddr was in one of the TLBTEMP_BASE areas. */ | ||
1678 | |||
1679 | movi a3, TLBTEMP_BASE_1 | ||
1680 | rsr a0, EXCVADDR | ||
1681 | bltu a0, a3, 2f | ||
1682 | |||
1683 | addi a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT)) | ||
1684 | bgeu a1, a3, 2f | ||
1685 | |||
1686 | /* Check if we have to restore an ITLB mapping. */ | ||
1687 | |||
1688 | movi a1, __tlbtemp_mapping_itlb | ||
1689 | rsr a3, EPC_1 | ||
1690 | sub a3, a3, a1 | ||
1691 | |||
1692 | /* Calculate VPN */ | ||
1693 | |||
1694 | movi a1, PAGE_MASK | ||
1695 | and a1, a1, a0 | ||
1696 | |||
1697 | /* Jump for ITLB entry */ | ||
1698 | |||
1699 | bgez a3, 1f | ||
1700 | |||
1701 | /* We can use up to two TLBTEMP areas, one for src and one for dst. */ | ||
1702 | |||
1703 | extui a3, a0, PAGE_SHIFT + DCACHE_ALIAS_ORDER, 1 | ||
1704 | add a1, a3, a1 | ||
1705 | |||
1706 | /* PPN is in a6 for the first TLBTEMP area and in a7 for the second. */ | ||
1707 | |||
1708 | mov a0, a6 | ||
1709 | movnez a0, a7, a3 | ||
1710 | j 3b | ||
1711 | |||
1712 | /* ITLB entry. We only use dst in a6. */ | ||
1713 | |||
1714 | 1: witlb a6, a1 | ||
1715 | isync | ||
1716 | j 4b | ||
1717 | |||
1718 | |||
1719 | #endif // DCACHE_WAY_SIZE > PAGE_SIZE | ||
1720 | |||
1721 | |||
1639 | 2: /* Invalid PGD, default exception handling */ | 1722 | 2: /* Invalid PGD, default exception handling */ |
1640 | 1723 | ||
1724 | movi a3, exc_table | ||
1641 | rsr a1, DEPC | 1725 | rsr a1, DEPC |
1642 | xsr a3, EXCSAVE_1 | 1726 | xsr a3, EXCSAVE_1 |
1643 | s32i a1, a2, PT_AREG2 | 1727 | s32i a1, a2, PT_AREG2 |
@@ -1682,15 +1766,15 @@ ENTRY(fast_store_prohibited) | |||
1682 | 8: rsr a1, EXCVADDR # fault address | 1766 | 8: rsr a1, EXCVADDR # fault address |
1683 | _PGD_OFFSET(a0, a1, a4) | 1767 | _PGD_OFFSET(a0, a1, a4) |
1684 | l32i a0, a0, 0 | 1768 | l32i a0, a0, 0 |
1685 | //beqi a0, _PAGE_USER, 2f # FIXME use _PAGE_INVALID | ||
1686 | beqz a0, 2f | 1769 | beqz a0, 2f |
1687 | 1770 | ||
1771 | /* Note that we assume _PAGE_WRITABLE_BIT is only set if pte is valid.*/ | ||
1772 | |||
1688 | _PTE_OFFSET(a0, a1, a4) | 1773 | _PTE_OFFSET(a0, a1, a4) |
1689 | l32i a4, a0, 0 # read pteval | 1774 | l32i a4, a0, 0 # read pteval |
1690 | movi a1, _PAGE_VALID | _PAGE_RW | 1775 | bbci.l a4, _PAGE_WRITABLE_BIT, 2f |
1691 | bnall a4, a1, 2f | ||
1692 | 1776 | ||
1693 | movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_WRENABLE | 1777 | movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE |
1694 | or a4, a4, a1 | 1778 | or a4, a4, a1 |
1695 | rsr a1, EXCVADDR | 1779 | rsr a1, EXCVADDR |
1696 | s32i a4, a0, 0 | 1780 | s32i a4, a0, 0 |
@@ -1700,10 +1784,7 @@ ENTRY(fast_store_prohibited) | |||
1700 | dhwb a0, 0 | 1784 | dhwb a0, 0 |
1701 | #endif | 1785 | #endif |
1702 | pdtlb a0, a1 | 1786 | pdtlb a0, a1 |
1703 | beqz a0, 1f | ||
1704 | idtlb a0 // FIXME do we need this? | ||
1705 | wdtlb a4, a0 | 1787 | wdtlb a4, a0 |
1706 | 1: | ||
1707 | 1788 | ||
1708 | /* Exit critical section. */ | 1789 | /* Exit critical section. */ |
1709 | 1790 | ||