^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * arch/sh/mm/tlb-pteaex.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * TLB operations for SH-X3 CPUs featuring PTE ASID Extensions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2009 Paul Mundt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * License. See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/mmu_context.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) unsigned long flags, pteval, vpn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Handle debugger faulting in for debugee.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) if (vma && current->active_mm != vma->vm_mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /* Set PTEH register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) vpn = address & MMU_VPN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) __raw_writel(vpn, MMU_PTEH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Set PTEAEX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) __raw_writel(get_asid(), MMU_PTEAEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) pteval = pte.pte_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* Set PTEA register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #ifdef CONFIG_X2TLB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * For the extended mode TLB this is trivial, only the ESZ and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * EPR bits need to be written out to PTEA, with the remainder of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * the protection bits (with the exception of the compat-mode SZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * and PR bits, which are cleared) being written out in PTEL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) __raw_writel(pte.pte_high, MMU_PTEA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* Set PTEL register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #ifdef CONFIG_CACHE_WRITETHROUGH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) pteval |= _PAGE_WT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* conveniently, we want all the software flags to be 0 anyway */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) __raw_writel(pteval, MMU_PTEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* Load the TLB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) local_irq_restore(flags);
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * While SH-X2 extended TLB mode splits out the memory-mapped I/UTLB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * data arrays, SH-X3 cores with PTEAEX split out the memory-mapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * address arrays. In compat mode the second array is inaccessible, while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * in extended mode, the legacy 8-bit ASID field in address array 1 has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * undefined behaviour.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) void local_flush_tlb_one(unsigned long asid, unsigned long page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) jump_to_uncached();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) __raw_writel(page, MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) __raw_writel(asid, MMU_UTLB_ADDRESS_ARRAY2 | MMU_PAGE_ASSOC_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) __raw_writel(page, MMU_ITLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) __raw_writel(asid, MMU_ITLB_ADDRESS_ARRAY2 | MMU_PAGE_ASSOC_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) back_to_cached();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) void local_flush_tlb_all(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned long flags, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * Flush all the TLB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) jump_to_uncached();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) status = __raw_readl(MMUCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) status = ((status & MMUCR_URB) >> MMUCR_URB_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (status == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) status = MMUCR_URB_NENTRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) for (i = 0; i < status; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) __raw_writel(0x0, MMU_UTLB_ADDRESS_ARRAY | (i << 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) __raw_writel(0x0, MMU_ITLB_ADDRESS_ARRAY | (i << 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) back_to_cached();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ctrl_barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }