28 #include <linux/kernel.h>
29 #include <linux/list.h>
32 #include <linux/slab.h>
33 #include <linux/device.h>
36 #include <linux/timex.h>
38 #include <asm/processor.h>
41 #include <asm/uv/uv_hub.h>
43 #define gru_random() get_cycles()
60 static inline int get_off_blade_tgh(
struct gru_state *gru)
70 static inline int get_on_blade_tgh(
struct gru_state *gru)
83 n = get_on_blade_tgh(gru);
85 n = get_off_blade_tgh(gru);
94 unlock_tgh_handle(tgh);
169 pagesize = (1
UL << pageshift);
174 gru_dbg(
grudev,
"gms %p, start 0x%lx, len 0x%lx, asidmap 0x%lx\n", gms,
175 start, len, gms->ms_asidmap[0]);
184 STAT(flush_tlb_gru_tgh);
187 " FLUSH gruid %d, asid 0x%x, vaddr 0x%lx, vamask 0x%x, num %ld, cbmap 0x%x\n",
188 gid, asid, start, grupagesize, num, asids->
mt_ctxbitmap);
189 tgh = get_lock_tgh_handle(gru);
192 get_unlock_tgh_handle(tgh);
194 STAT(flush_tlb_gru_zero_asid);
198 " CLEARASID gruid %d, asid 0x%x, cbtmap 0x%x, asidmap 0x%lx\n",
214 tgh = get_lock_tgh_handle(gru);
216 get_unlock_tgh_handle(tgh);
222 static void gru_invalidate_range_start(
struct mmu_notifier *mn,
224 unsigned long start,
unsigned long end)
229 STAT(mmu_invalidate_range);
231 gru_dbg(
grudev,
"gms %p, start 0x%lx, end 0x%lx, act %d\n", gms,
236 static void gru_invalidate_range_end(
struct mmu_notifier *mn,
237 struct mm_struct *mm,
unsigned long start,
247 gru_dbg(
grudev,
"gms %p, start 0x%lx, end 0x%lx\n", gms, start, end);
250 static void gru_invalidate_page(
struct mmu_notifier *mn,
struct mm_struct *mm,
256 STAT(mmu_invalidate_page);
261 static void gru_release(
struct mmu_notifier *mn,
struct mm_struct *mm)
271 static const struct mmu_notifier_ops gru_mmuops = {
272 .invalidate_page = gru_invalidate_page,
273 .invalidate_range_start = gru_invalidate_range_start,
274 .invalidate_range_end = gru_invalidate_range_end,
275 .release = gru_release,
279 static struct mmu_notifier *mmu_find_ops(
struct mm_struct *mm,
280 const struct mmu_notifier_ops *ops)
282 struct mmu_notifier *mn, *gru_mn =
NULL;
285 if (mm->mmu_notifier_mm) {
287 hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list,
289 if (mn->ops == ops) {
301 struct mmu_notifier *mn;
304 mn = mmu_find_ops(
current->mm, &gru_mmuops);
353 #define MAX_LOCAL_TGH 16
357 int cpus, shift = 0,
n;
359 cpus = uv_blade_nr_possible_cpus(gru->
gs_blade_id);
363 n = 1 << fls(cpus - 1);