^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/arch/arm/mm/copypage-xsc3.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2004 Intel Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Adapted for 3rd gen XScale core, no more mini-dcache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Author: Matt Gilbert (matthew.m.gilbert@intel.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/highmem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * General note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * We don't really want write-allocate cache behaviour for these functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * since that will just eat through 8K of the cache.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * XSC3 optimised copy_user_highpage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * The source page may have some clean entries in the cache already, but we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * can safely ignore them - break_cow() will flush them out of the cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * if we eventually end up using our copied page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static void xsc3_mc_copy_user_page(void *kto, const void *kfrom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) asm volatile ("\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) pld [%1, #0] \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) pld [%1, #32] \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) 1: pld [%1, #64] \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) pld [%1, #96] \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) 2: ldrd r2, r3, [%1], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) ldrd r4, r5, [%1], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) mcr p15, 0, %0, c7, c6, 1 @ invalidate\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) strd r2, r3, [%0], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) ldrd r2, r3, [%1], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) strd r4, r5, [%0], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) ldrd r4, r5, [%1], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) strd r2, r3, [%0], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) strd r4, r5, [%0], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) ldrd r2, r3, [%1], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ldrd r4, r5, [%1], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) mcr p15, 0, %0, c7, c6, 1 @ invalidate\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) strd r2, r3, [%0], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) ldrd r2, r3, [%1], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) subs %2, %2, #1 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) strd r4, r5, [%0], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) ldrd r4, r5, [%1], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) strd r2, r3, [%0], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) strd r4, r5, [%0], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) bgt 1b \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) beq 2b "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) : "2" (PAGE_SIZE / 64 - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) : "r2", "r3", "r4", "r5");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) void xsc3_mc_copy_user_highpage(struct page *to, struct page *from,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned long vaddr, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) void *kto, *kfrom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) kto = kmap_atomic(to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) kfrom = kmap_atomic(from);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) flush_cache_page(vma, vaddr, page_to_pfn(from));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) xsc3_mc_copy_user_page(kto, kfrom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) kunmap_atomic(kfrom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) kunmap_atomic(kto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * XScale optimised clear_user_page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) void xsc3_mc_clear_user_highpage(struct page *page, unsigned long vaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) void *ptr, *kaddr = kmap_atomic(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) asm volatile ("\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) mov r1, %2 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) mov r2, #0 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) mov r3, #0 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) 1: mcr p15, 0, %0, c7, c6, 1 @ invalidate line\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) strd r2, r3, [%0], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) strd r2, r3, [%0], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) strd r2, r3, [%0], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) strd r2, r3, [%0], #8 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) subs r1, r1, #1 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) bne 1b"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) : "=r" (ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) : "0" (kaddr), "I" (PAGE_SIZE / 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) : "r1", "r2", "r3");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) kunmap_atomic(kaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct cpu_user_fns xsc3_mc_user_fns __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .cpu_clear_user_highpage = xsc3_mc_clear_user_highpage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .cpu_copy_user_highpage = xsc3_mc_copy_user_highpage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) };