/*1* arch/xtensa/mm/misc.S2*3* Miscellaneous assembly functions.4*5* This file is subject to the terms and conditions of the GNU General Public6* License. See the file "COPYING" in the main directory of this archive7* for more details.8*9* Copyright (C) 2001 - 2007 Tensilica Inc.10*11* Chris Zankel <[email protected]>12*/131415#include <linux/linkage.h>16#include <asm/page.h>17#include <asm/pgtable.h>18#include <asm/asmmacro.h>19#include <asm/cacheasm.h>20#include <asm/tlbflush.h>212223/*24* clear_page and clear_user_page are the same for non-cache-aliased configs.25*26* clear_page (unsigned long page)27* a228*/2930ENTRY(clear_page)31entry a1, 163233movi a3, 034__loopi a2, a7, PAGE_SIZE, 3235s32i a3, a2, 036s32i a3, a2, 437s32i a3, a2, 838s32i a3, a2, 1239s32i a3, a2, 1640s32i a3, a2, 2041s32i a3, a2, 2442s32i a3, a2, 2843__endla a2, a7, 324445retw4647/*48* copy_page and copy_user_page are the same for non-cache-aliased configs.49*50* copy_page (void *to, void *from)51* a2 a352*/5354ENTRY(copy_page)55entry a1, 165657__loopi a2, a4, PAGE_SIZE, 325859l32i a8, a3, 060l32i a9, a3, 461s32i a8, a2, 062s32i a9, a2, 46364l32i a8, a3, 865l32i a9, a3, 1266s32i a8, a2, 867s32i a9, a2, 126869l32i a8, a3, 1670l32i a9, a3, 2071s32i a8, a2, 1672s32i a9, a2, 207374l32i a8, a3, 2475l32i a9, a3, 2876s32i a8, a2, 2477s32i a9, a2, 287879addi a2, a2, 3280addi a3, a3, 328182__endl a2, a48384retw8586#ifdef CONFIG_MMU87/*88* If we have to deal with cache aliasing, we use temporary memory mappings89* to ensure that the source and destination pages have the same color as90* the virtual address. We use way 0 and 1 for temporary mappings in such cases.91*92* The temporary DTLB entries shouldn't be flushed by interrupts, but are93* flushed by preemptive task switches. Special code in the94* fast_second_level_miss handler re-established the temporary mapping.95* It requires that the PPNs for the destination and source addresses are96* in a6, and a7, respectively.97*/9899/* TLB miss exceptions are treated special in the following region */100101ENTRY(__tlbtemp_mapping_start)102103#if (DCACHE_WAY_SIZE > PAGE_SIZE)104105/*106* clear_user_page (void *addr, unsigned long vaddr, struct page *page)107* a2 a3 a4108*/109110ENTRY(clear_user_page)111entry a1, 32112113/* Mark page dirty and determine alias. */114115movi a7, (1 << PG_ARCH_1)116l32i a5, a4, PAGE_FLAGS117xor a6, a2, a3118extui a3, a3, PAGE_SHIFT, DCACHE_ALIAS_ORDER119extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER120or a5, a5, a7121slli a3, a3, PAGE_SHIFT122s32i a5, a4, PAGE_FLAGS123124/* Skip setting up a temporary DTLB if not aliased. */125126beqz a6, 1f127128/* Invalidate kernel page. */129130mov a10, a2131call8 __invalidate_dcache_page132133/* Setup a temporary DTLB with the color of the VPN */134135movi a4, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)136movi a5, TLBTEMP_BASE_1 # virt137add a6, a2, a4 # ppn138add a2, a5, a3 # add 'color'139140wdtlb a6, a2141dsync1421431: movi a3, 0144__loopi a2, a7, PAGE_SIZE, 32145s32i a3, a2, 0146s32i a3, a2, 4147s32i a3, a2, 8148s32i a3, a2, 12149s32i a3, a2, 16150s32i a3, a2, 20151s32i a3, a2, 24152s32i a3, a2, 28153__endla a2, a7, 32154155bnez a6, 1f156retw157158/* We need to invalidate the temporary idtlb entry, if any. */1591601: addi a2, a2, -PAGE_SIZE161idtlb a2162dsync163164retw165166/*167* copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)168* a2 a3 a4 a5169*/170171ENTRY(copy_user_page)172173entry a1, 32174175/* Mark page dirty and determine alias for destination. */176177movi a8, (1 << PG_ARCH_1)178l32i a9, a5, PAGE_FLAGS179xor a6, a2, a4180xor a7, a3, a4181extui a4, a4, PAGE_SHIFT, DCACHE_ALIAS_ORDER182extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER183extui a7, a7, PAGE_SHIFT, DCACHE_ALIAS_ORDER184or a9, a9, a8185slli a4, a4, PAGE_SHIFT186s32i a9, a5, PAGE_FLAGS187movi a5, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)188189beqz a6, 1f190191/* Invalidate dcache */192193mov a10, a2194call8 __invalidate_dcache_page195196/* Setup a temporary DTLB with a matching color. */197198movi a8, TLBTEMP_BASE_1 # base199add a6, a2, a5 # ppn200add a2, a8, a4 # add 'color'201202wdtlb a6, a2203dsync204205/* Skip setting up a temporary DTLB for destination if not aliased. */2062071: beqz a7, 1f208209/* Setup a temporary DTLB with a matching color. */210211movi a8, TLBTEMP_BASE_2 # base212add a7, a3, a5 # ppn213add a3, a8, a4214addi a8, a3, 1 # way1215216wdtlb a7, a8217dsync2182191: __loopi a2, a4, PAGE_SIZE, 32220221l32i a8, a3, 0222l32i a9, a3, 4223s32i a8, a2, 0224s32i a9, a2, 4225226l32i a8, a3, 8227l32i a9, a3, 12228s32i a8, a2, 8229s32i a9, a2, 12230231l32i a8, a3, 16232l32i a9, a3, 20233s32i a8, a2, 16234s32i a9, a2, 20235236l32i a8, a3, 24237l32i a9, a3, 28238s32i a8, a2, 24239s32i a9, a2, 28240241addi a2, a2, 32242addi a3, a3, 32243244__endl a2, a4245246/* We need to invalidate any temporary mapping! */247248bnez a6, 1f249bnez a7, 2f250retw2512521: addi a2, a2, -PAGE_SIZE253idtlb a2254dsync255bnez a7, 2f256retw2572582: addi a3, a3, -PAGE_SIZE+1259idtlb a3260dsync261262retw263264#endif265266#if (DCACHE_WAY_SIZE > PAGE_SIZE)267268/*269* void __flush_invalidate_dcache_page_alias (addr, phys)270* a2 a3271*/272273ENTRY(__flush_invalidate_dcache_page_alias)274entry sp, 16275276movi a7, 0 # required for exception handler277addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)278mov a4, a2279wdtlb a6, a2280dsync281282___flush_invalidate_dcache_page a2 a3283284idtlb a4285dsync286287retw288289#endif290291ENTRY(__tlbtemp_mapping_itlb)292293#if (ICACHE_WAY_SIZE > PAGE_SIZE)294295ENTRY(__invalidate_icache_page_alias)296entry sp, 16297298addi a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE)299mov a4, a2300witlb a6, a2301isync302303___invalidate_icache_page a2 a3304305iitlb a4306isync307retw308309#endif310311/* End of special treatment in tlb miss exception */312313ENTRY(__tlbtemp_mapping_end)314#endif /* CONFIG_MMU315316/*317* void __invalidate_icache_page(ulong start)318*/319320ENTRY(__invalidate_icache_page)321entry sp, 16322323___invalidate_icache_page a2 a3324isync325326retw327328/*329* void __invalidate_dcache_page(ulong start)330*/331332ENTRY(__invalidate_dcache_page)333entry sp, 16334335___invalidate_dcache_page a2 a3336dsync337338retw339340/*341* void __flush_invalidate_dcache_page(ulong start)342*/343344ENTRY(__flush_invalidate_dcache_page)345entry sp, 16346347___flush_invalidate_dcache_page a2 a3348349dsync350retw351352/*353* void __flush_dcache_page(ulong start)354*/355356ENTRY(__flush_dcache_page)357entry sp, 16358359___flush_dcache_page a2 a3360361dsync362retw363364/*365* void __invalidate_icache_range(ulong start, ulong size)366*/367368ENTRY(__invalidate_icache_range)369entry sp, 16370371___invalidate_icache_range a2 a3 a4372isync373374retw375376/*377* void __flush_invalidate_dcache_range(ulong start, ulong size)378*/379380ENTRY(__flush_invalidate_dcache_range)381entry sp, 16382383___flush_invalidate_dcache_range a2 a3 a4384dsync385386retw387388/*389* void _flush_dcache_range(ulong start, ulong size)390*/391392ENTRY(__flush_dcache_range)393entry sp, 16394395___flush_dcache_range a2 a3 a4396dsync397398retw399400/*401* void _invalidate_dcache_range(ulong start, ulong size)402*/403404ENTRY(__invalidate_dcache_range)405entry sp, 16406407___invalidate_dcache_range a2 a3 a4408409retw410411/*412* void _invalidate_icache_all(void)413*/414415ENTRY(__invalidate_icache_all)416entry sp, 16417418___invalidate_icache_all a2 a3419isync420421retw422423/*424* void _flush_invalidate_dcache_all(void)425*/426427ENTRY(__flush_invalidate_dcache_all)428entry sp, 16429430___flush_invalidate_dcache_all a2 a3431dsync432433retw434435/*436* void _invalidate_dcache_all(void)437*/438439ENTRY(__invalidate_dcache_all)440entry sp, 16441442___invalidate_dcache_all a2 a3443dsync444445retw446447448449