^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-feroceon.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2008 Marvell Semiconductors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This handles copy_user_highpage and clear_user_page on Feroceon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * more optimally than the generic implementations.
^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) static void feroceon_copy_user_page(void *kto, const void *kfrom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) asm volatile ("\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) 1: ldmia %1!, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) pld [%1, #0] \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) pld [%1, #32] \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) pld [%1, #64] \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) pld [%1, #96] \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) pld [%1, #128] \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) pld [%1, #160] \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) pld [%1, #192] \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) stmia %0, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) ldmia %1!, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) add %0, %0, #32 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) stmia %0, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) ldmia %1!, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) add %0, %0, #32 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) stmia %0, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) ldmia %1!, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) add %0, %0, #32 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) stmia %0, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) ldmia %1!, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) add %0, %0, #32 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) stmia %0, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) ldmia %1!, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) add %0, %0, #32 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) stmia %0, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ldmia %1!, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) add %0, %0, #32 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) stmia %0, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) ldmia %1!, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) add %0, %0, #32 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) stmia %0, {r2 - r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) subs %2, %2, #(32 * 8) \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) add %0, %0, #32 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) bne 1b \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) mcr p15, 0, %2, c7, c10, 4 @ drain WB"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) : "2" (PAGE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) : "r2", "r3", "r4", "r5", "r6", "r7", "ip", "lr");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) void feroceon_copy_user_highpage(struct page *to, struct page *from,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) unsigned long vaddr, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) void *kto, *kfrom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) kto = kmap_atomic(to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) kfrom = kmap_atomic(from);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) flush_cache_page(vma, vaddr, page_to_pfn(from));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) feroceon_copy_user_page(kto, kfrom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) kunmap_atomic(kfrom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) kunmap_atomic(kto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) void feroceon_clear_user_highpage(struct page *page, unsigned long vaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) void *ptr, *kaddr = kmap_atomic(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) asm volatile ("\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) mov r1, %2 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) mov r2, #0 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) mov r3, #0 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) mov r4, #0 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) mov r5, #0 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) mov r6, #0 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) mov r7, #0 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) mov ip, #0 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) mov lr, #0 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) 1: stmia %0, {r2-r7, ip, lr} \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) subs r1, r1, #1 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) add %0, %0, #32 \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) bne 1b \n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) mcr p15, 0, r1, c7, c10, 4 @ drain WB"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) : "=r" (ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) : "0" (kaddr), "I" (PAGE_SIZE / 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) : "r1", "r2", "r3", "r4", "r5", "r6", "r7", "ip", "lr");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) kunmap_atomic(kaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct cpu_user_fns feroceon_user_fns __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .cpu_clear_user_highpage = feroceon_clear_user_highpage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .cpu_copy_user_highpage = feroceon_copy_user_highpage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)