/* We only try to do i/d cache coherency on stuff that looks like * reasonably "normal" PTEs. We currently require a PTE to be present * and we avoid _PAGE_SPECIAL and cache inhibited pte. We also only do that * on userspace PTEs */ static inline int pte_looks_normal(pte_t pte) { #if defined(CONFIG_PPC_BOOK3S_64) if ((pte_val(pte) & (_PAGE_PRESENT | _PAGE_SPECIAL)) == _PAGE_PRESENT) { if (pte_ci(pte)) return 0; if (pte_user(pte)) return 1; } return 0; #else return (pte_val(pte) & (_PAGE_PRESENT | _PAGE_SPECIAL | _PAGE_NO_CACHE | _PAGE_USER)) == (_PAGE_PRESENT | _PAGE_USER); #endif }
/* * On 64-bit we don't want to invoke hash_page on user addresses from * interrupt context, so if the access faults, we read the page tables * to find which page (if any) is mapped and access it directly. */ static int read_user_stack_slow(void __user *ptr, void *buf, int nb) { int ret = -EFAULT; pgd_t *pgdir; pte_t *ptep, pte; unsigned shift; unsigned long addr = (unsigned long) ptr; unsigned long offset; unsigned long pfn, flags; void *kaddr; pgdir = current->mm->pgd; if (!pgdir) return -EFAULT; local_irq_save(flags); ptep = find_linux_pte_or_hugepte(pgdir, addr, NULL, &shift); if (!ptep) goto err_out; if (!shift) shift = PAGE_SHIFT; /* align address to page boundary */ offset = addr & ((1UL << shift) - 1); pte = READ_ONCE(*ptep); if (!pte_present(pte) || !pte_user(pte)) goto err_out; pfn = pte_pfn(pte); if (!page_is_ram(pfn)) goto err_out; /* no highmem to worry about here */ kaddr = pfn_to_kaddr(pfn); memcpy(buf, kaddr + offset, nb); ret = 0; err_out: local_irq_restore(flags); return ret; }
/* * This is lazy way to flush icache provided the CPU has the NX feature enabled. * This is called from set_pte. */ void mic_flush_icache_nx(pte_t *ptep, pte_t pte) { /* * Donot continue if the icache snoop is enabled * or if the NX feature doesnt exist */ if(icache_snoop || !is_nx_support) return; /* * Similar to the ia64 set_pte code * We only flush and set PG_arch_1 bit if the page is * present && page is user page && has backing page struct * && page is executable && * (page swapin or new page or page migration || * copy_on_write with page copying) */ if (pte_present(pte) && pte_user(pte) && pfn_valid(pte_pfn(pte)) && !pte_no_exec(pte) && (!pte_present(*ptep) || pte_pfn(*ptep) != pte_pfn(pte))) mic_flush_icache_lazy(pte_page(pte)); }
/* * Set up a variable-size TLB entry (tlbcam). The parameters are not checked; * in particular size must be a power of 4 between 4k and the max supported by * an implementation; max may further be limited by what can be represented in * an unsigned long (for example, 32-bit implementations cannot support a 4GB * size). */ void settlbcam(int index, unsigned long virt, phys_addr_t phys, unsigned long size, unsigned long flags, unsigned int pid) { unsigned int tsize; tsize = __ilog2(size) - 10; #ifdef CONFIG_SMP if ((flags & _PAGE_NO_CACHE) == 0) flags |= _PAGE_COHERENT; #endif TLBCAM[index].MAS0 = MAS0_TLBSEL(1) | MAS0_ESEL(index) | MAS0_NV(index+1); TLBCAM[index].MAS1 = MAS1_VALID | MAS1_IPROT | MAS1_TSIZE(tsize) | MAS1_TID(pid); TLBCAM[index].MAS2 = virt & PAGE_MASK; TLBCAM[index].MAS2 |= (flags & _PAGE_WRITETHRU) ? MAS2_W : 0; TLBCAM[index].MAS2 |= (flags & _PAGE_NO_CACHE) ? MAS2_I : 0; TLBCAM[index].MAS2 |= (flags & _PAGE_COHERENT) ? MAS2_M : 0; TLBCAM[index].MAS2 |= (flags & _PAGE_GUARDED) ? MAS2_G : 0; TLBCAM[index].MAS2 |= (flags & _PAGE_ENDIAN) ? MAS2_E : 0; TLBCAM[index].MAS3 = (phys & MAS3_RPN) | MAS3_SX | MAS3_SR; TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_SW : 0); if (mmu_has_feature(MMU_FTR_BIG_PHYS)) TLBCAM[index].MAS7 = (u64)phys >> 32; /* Below is unlikely -- only for large user pages or similar */ if (pte_user(flags)) { TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR; TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0); } tlbcam_addrs[index].start = virt; tlbcam_addrs[index].limit = virt + size - 1; tlbcam_addrs[index].phys = phys; loadcam_entry(index); }