Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.17.
  1// SPDX-License-Identifier: GPL-2.0
  2// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
  3
  4#include <linux/init.h>
  5#include <linux/mm.h>
  6#include <linux/module.h>
  7#include <linux/sched.h>
  8
  9#include <asm/mmu_context.h>
 10#include <asm/setup.h>
 11
 12/*
 13 * One C-SKY MMU TLB entry contain two PFN/page entry, ie:
 14 * 1VPN -> 2PFN
 15 */
 16#define TLB_ENTRY_SIZE		(PAGE_SIZE * 2)
 17#define TLB_ENTRY_SIZE_MASK	(PAGE_MASK << 1)
 18
 19void flush_tlb_all(void)
 20{
 21	tlb_invalid_all();
 22}
 23
 24void flush_tlb_mm(struct mm_struct *mm)
 25{
 26#ifdef CONFIG_CPU_HAS_TLBI
 27	sync_is();
 28	asm volatile(
 29		"tlbi.asids %0	\n"
 30		"sync.i		\n"
 31		:
 32		: "r" (cpu_asid(mm))
 33		: "memory");
 34#else
 35	tlb_invalid_all();
 36#endif
 37}
 38
 39/*
 40 * MMU operation regs only could invalid tlb entry in jtlb and we
 41 * need change asid field to invalid I-utlb & D-utlb.
 42 */
 43#ifndef CONFIG_CPU_HAS_TLBI
 44#define restore_asid_inv_utlb(oldpid, newpid) \
 45do { \
 46	if (oldpid == newpid) \
 47		write_mmu_entryhi(oldpid + 1); \
 48	write_mmu_entryhi(oldpid); \
 49} while (0)
 50#endif
 51
 52void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 53			unsigned long end)
 54{
 55	unsigned long newpid = cpu_asid(vma->vm_mm);
 56
 57	start &= TLB_ENTRY_SIZE_MASK;
 58	end   += TLB_ENTRY_SIZE - 1;
 59	end   &= TLB_ENTRY_SIZE_MASK;
 60
 61#ifdef CONFIG_CPU_HAS_TLBI
 62	sync_is();
 63	while (start < end) {
 64		asm volatile(
 65			"tlbi.vas %0	\n"
 66			:
 67			: "r" (start | newpid)
 68			: "memory");
 69
 70		start += 2*PAGE_SIZE;
 71	}
 72	asm volatile("sync.i\n");
 73#else
 74	{
 75	unsigned long flags, oldpid;
 76
 77	local_irq_save(flags);
 78	oldpid = read_mmu_entryhi() & ASID_MASK;
 79	while (start < end) {
 80		int idx;
 81
 82		write_mmu_entryhi(start | newpid);
 83		start += 2*PAGE_SIZE;
 84		tlb_probe();
 85		idx = read_mmu_index();
 86		if (idx >= 0)
 87			tlb_invalid_indexed();
 88	}
 89	restore_asid_inv_utlb(oldpid, newpid);
 90	local_irq_restore(flags);
 91	}
 92#endif
 93}
 94
 95void flush_tlb_kernel_range(unsigned long start, unsigned long end)
 96{
 97	start &= TLB_ENTRY_SIZE_MASK;
 98	end   += TLB_ENTRY_SIZE - 1;
 99	end   &= TLB_ENTRY_SIZE_MASK;
100
101#ifdef CONFIG_CPU_HAS_TLBI
102	sync_is();
103	while (start < end) {
104		asm volatile(
105			"tlbi.vaas %0	\n"
106			:
107			: "r" (start)
108			: "memory");
109
110		start += 2*PAGE_SIZE;
111	}
112	asm volatile("sync.i\n");
113#else
114	{
115	unsigned long flags, oldpid;
116
117	local_irq_save(flags);
118	oldpid = read_mmu_entryhi() & ASID_MASK;
119	while (start < end) {
120		int idx;
121
122		write_mmu_entryhi(start | oldpid);
123		start += 2*PAGE_SIZE;
124		tlb_probe();
125		idx = read_mmu_index();
126		if (idx >= 0)
127			tlb_invalid_indexed();
128	}
129	restore_asid_inv_utlb(oldpid, oldpid);
130	local_irq_restore(flags);
131	}
132#endif
133}
134
135void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
136{
137	int newpid = cpu_asid(vma->vm_mm);
138
139	addr &= TLB_ENTRY_SIZE_MASK;
140
141#ifdef CONFIG_CPU_HAS_TLBI
142	sync_is();
143	asm volatile(
144		"tlbi.vas %0	\n"
145		"sync.i		\n"
146		:
147		: "r" (addr | newpid)
148		: "memory");
149#else
150	{
151	int oldpid, idx;
152	unsigned long flags;
153
154	local_irq_save(flags);
155	oldpid = read_mmu_entryhi() & ASID_MASK;
156	write_mmu_entryhi(addr | newpid);
157	tlb_probe();
158	idx = read_mmu_index();
159	if (idx >= 0)
160		tlb_invalid_indexed();
161
162	restore_asid_inv_utlb(oldpid, newpid);
163	local_irq_restore(flags);
164	}
165#endif
166}
167
168void flush_tlb_one(unsigned long addr)
169{
170	addr &= TLB_ENTRY_SIZE_MASK;
171
172#ifdef CONFIG_CPU_HAS_TLBI
173	sync_is();
174	asm volatile(
175		"tlbi.vaas %0	\n"
176		"sync.i		\n"
177		:
178		: "r" (addr)
179		: "memory");
180#else
181	{
182	int oldpid, idx;
183	unsigned long flags;
184
185	local_irq_save(flags);
186	oldpid = read_mmu_entryhi() & ASID_MASK;
187	write_mmu_entryhi(addr | oldpid);
188	tlb_probe();
189	idx = read_mmu_index();
190	if (idx >= 0)
191		tlb_invalid_indexed();
192
193	restore_asid_inv_utlb(oldpid, oldpid);
194	local_irq_restore(flags);
195	}
196#endif
197}
198EXPORT_SYMBOL(flush_tlb_one);