1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * ultra.S: Don't expand these all over the place...
4 *
5 * Copyright (C) 1997, 2000, 2008 David S. Miller (davem@davemloft.net)
6 */
7
8#include <linux/pgtable.h>
9#include <asm/asi.h>
10#include <asm/page.h>
11#include <asm/spitfire.h>
12#include <asm/mmu_context.h>
13#include <asm/mmu.h>
14#include <asm/pil.h>
15#include <asm/head.h>
16#include <asm/thread_info.h>
17#include <asm/cacheflush.h>
18#include <asm/hypervisor.h>
19#include <asm/cpudata.h>
20
21	/* Basically, most of the Spitfire vs. Cheetah madness
22	 * has to do with the fact that Cheetah does not support
23	 * IMMU flushes out of the secondary context.  Someone needs
24	 * to throw a south lake birthday party for the folks
25	 * in Microelectronics who refused to fix this shit.
26	 */
27
28	/* This file is meant to be read efficiently by the CPU, not humans.
29	 * Staraj sie tego nikomu nie pierdolnac...
30	 */
31	.text
32	.align		32
33	.globl		__flush_tlb_mm
34__flush_tlb_mm:		/* 19 insns */
35	/* %o0=(ctx & TAG_CONTEXT_BITS), %o1=SECONDARY_CONTEXT */
36	ldxa		[%o1] ASI_DMMU, %g2
37	cmp		%g2, %o0
38	bne,pn		%icc, __spitfire_flush_tlb_mm_slow
39	 mov		0x50, %g3
40	stxa		%g0, [%g3] ASI_DMMU_DEMAP
41	stxa		%g0, [%g3] ASI_IMMU_DEMAP
42	sethi		%hi(KERNBASE), %g3
43	flush		%g3
44	retl
45	 nop
46	nop
47	nop
48	nop
49	nop
50	nop
51	nop
52	nop
53	nop
54	nop
55
56	.align		32
57	.globl		__flush_tlb_page
58__flush_tlb_page:	/* 22 insns */
59	/* %o0 = context, %o1 = vaddr */
60	rdpr		%pstate, %g7
61	andn		%g7, PSTATE_IE, %g2
62	wrpr		%g2, %pstate
63	mov		SECONDARY_CONTEXT, %o4
64	ldxa		[%o4] ASI_DMMU, %g2
65	stxa		%o0, [%o4] ASI_DMMU
66	andcc		%o1, 1, %g0
67	andn		%o1, 1, %o3
68	be,pn		%icc, 1f
69	 or		%o3, 0x10, %o3
70	stxa		%g0, [%o3] ASI_IMMU_DEMAP
711:	stxa		%g0, [%o3] ASI_DMMU_DEMAP
72	membar		#Sync
73	stxa		%g2, [%o4] ASI_DMMU
74	sethi		%hi(KERNBASE), %o4
75	flush		%o4
76	retl
77	 wrpr		%g7, 0x0, %pstate
78	nop
79	nop
80	nop
81	nop
82
83	.align		32
84	.globl		__flush_tlb_pending
85__flush_tlb_pending:	/* 27 insns */
86	/* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
87	rdpr		%pstate, %g7
88	sllx		%o1, 3, %o1
89	andn		%g7, PSTATE_IE, %g2
90	wrpr		%g2, %pstate
91	mov		SECONDARY_CONTEXT, %o4
92	ldxa		[%o4] ASI_DMMU, %g2
93	stxa		%o0, [%o4] ASI_DMMU
941:	sub		%o1, (1 << 3), %o1
95	ldx		[%o2 + %o1], %o3
96	andcc		%o3, 1, %g0
97	andn		%o3, 1, %o3
98	be,pn		%icc, 2f
99	 or		%o3, 0x10, %o3
100	stxa		%g0, [%o3] ASI_IMMU_DEMAP
1012:	stxa		%g0, [%o3] ASI_DMMU_DEMAP
102	membar		#Sync
103	brnz,pt		%o1, 1b
104	 nop
105	stxa		%g2, [%o4] ASI_DMMU
106	sethi		%hi(KERNBASE), %o4
107	flush		%o4
108	retl
109	 wrpr		%g7, 0x0, %pstate
110	nop
111	nop
112	nop
113	nop
114
115	.align		32
116	.globl		__flush_tlb_kernel_range
117__flush_tlb_kernel_range:	/* 31 insns */
118	/* %o0=start, %o1=end */
119	cmp		%o0, %o1
120	be,pn		%xcc, 2f
121	 sub		%o1, %o0, %o3
122	srlx		%o3, 18, %o4
123	brnz,pn		%o4, __spitfire_flush_tlb_kernel_range_slow
124	 sethi		%hi(PAGE_SIZE), %o4
125	sub		%o3, %o4, %o3
126	or		%o0, 0x20, %o0		! Nucleus
1271:	stxa		%g0, [%o0 + %o3] ASI_DMMU_DEMAP
128	stxa		%g0, [%o0 + %o3] ASI_IMMU_DEMAP
129	membar		#Sync
130	brnz,pt		%o3, 1b
131	 sub		%o3, %o4, %o3
1322:	sethi		%hi(KERNBASE), %o3
133	flush		%o3
134	retl
135	 nop
136	nop
137	nop
138	nop
139	nop
140	nop
141	nop
142	nop
143	nop
144	nop
145	nop
146	nop
147	nop
148	nop
149	nop
150
151__spitfire_flush_tlb_kernel_range_slow:
152	mov		63 * 8, %o4
1531:	ldxa		[%o4] ASI_ITLB_DATA_ACCESS, %o3
154	andcc		%o3, 0x40, %g0			/* _PAGE_L_4U */
155	bne,pn		%xcc, 2f
156	 mov		TLB_TAG_ACCESS, %o3
157	stxa		%g0, [%o3] ASI_IMMU
158	stxa		%g0, [%o4] ASI_ITLB_DATA_ACCESS
159	membar		#Sync
1602:	ldxa		[%o4] ASI_DTLB_DATA_ACCESS, %o3
161	andcc		%o3, 0x40, %g0
162	bne,pn		%xcc, 2f
163	 mov		TLB_TAG_ACCESS, %o3
164	stxa		%g0, [%o3] ASI_DMMU
165	stxa		%g0, [%o4] ASI_DTLB_DATA_ACCESS
166	membar		#Sync
1672:	sub		%o4, 8, %o4
168	brgez,pt	%o4, 1b
169	 nop
170	retl
171	 nop
172
173__spitfire_flush_tlb_mm_slow:
174	rdpr		%pstate, %g1
175	wrpr		%g1, PSTATE_IE, %pstate
176	stxa		%o0, [%o1] ASI_DMMU
177	stxa		%g0, [%g3] ASI_DMMU_DEMAP
178	stxa		%g0, [%g3] ASI_IMMU_DEMAP
179	flush		%g6
180	stxa		%g2, [%o1] ASI_DMMU
181	sethi		%hi(KERNBASE), %o1
182	flush		%o1
183	retl
184	 wrpr		%g1, 0, %pstate
185
186/*
187 * The following code flushes one page_size worth.
188 */
189	.section .kprobes.text, "ax"
190	.align		32
191	.globl		__flush_icache_page
192__flush_icache_page:	/* %o0 = phys_page */
193	srlx		%o0, PAGE_SHIFT, %o0
194	sethi		%hi(PAGE_OFFSET), %g1
195	sllx		%o0, PAGE_SHIFT, %o0
196	sethi		%hi(PAGE_SIZE), %g2
197	ldx		[%g1 + %lo(PAGE_OFFSET)], %g1
198	add		%o0, %g1, %o0
1991:	subcc		%g2, 32, %g2
200	bne,pt		%icc, 1b
201	 flush		%o0 + %g2
202	retl
203	 nop
204
205#ifdef DCACHE_ALIASING_POSSIBLE
206
207#if (PAGE_SHIFT != 13)
208#error only page shift of 13 is supported by dcache flush
209#endif
210
211#define DTAG_MASK 0x3
212
213	/* This routine is Spitfire specific so the hardcoded
214	 * D-cache size and line-size are OK.
215	 */
216	.align		64
217	.globl		__flush_dcache_page
218__flush_dcache_page:	/* %o0=kaddr, %o1=flush_icache */
219	sethi		%hi(PAGE_OFFSET), %g1
220	ldx		[%g1 + %lo(PAGE_OFFSET)], %g1
221	sub		%o0, %g1, %o0			! physical address
222	srlx		%o0, 11, %o0			! make D-cache TAG
223	sethi		%hi(1 << 14), %o2		! D-cache size
224	sub		%o2, (1 << 5), %o2		! D-cache line size
2251:	ldxa		[%o2] ASI_DCACHE_TAG, %o3	! load D-cache TAG
226	andcc		%o3, DTAG_MASK, %g0		! Valid?
227	be,pn		%xcc, 2f			! Nope, branch
228	 andn		%o3, DTAG_MASK, %o3		! Clear valid bits
229	cmp		%o3, %o0			! TAG match?
230	bne,pt		%xcc, 2f			! Nope, branch
231	 nop
232	stxa		%g0, [%o2] ASI_DCACHE_TAG	! Invalidate TAG
233	membar		#Sync
2342:	brnz,pt		%o2, 1b
235	 sub		%o2, (1 << 5), %o2		! D-cache line size
236
237	/* The I-cache does not snoop local stores so we
238	 * better flush that too when necessary.
239	 */
240	brnz,pt		%o1, __flush_icache_page
241	 sllx		%o0, 11, %o0
242	retl
243	 nop
244
245#endif /* DCACHE_ALIASING_POSSIBLE */
246
247	.previous
248
249	/* Cheetah specific versions, patched at boot time. */
250__cheetah_flush_tlb_mm: /* 19 insns */
251	rdpr		%pstate, %g7
252	andn		%g7, PSTATE_IE, %g2
253	wrpr		%g2, 0x0, %pstate
254	wrpr		%g0, 1, %tl
255	mov		PRIMARY_CONTEXT, %o2
256	mov		0x40, %g3
257	ldxa		[%o2] ASI_DMMU, %g2
258	srlx		%g2, CTX_PGSZ1_NUC_SHIFT, %o1
259	sllx		%o1, CTX_PGSZ1_NUC_SHIFT, %o1
260	or		%o0, %o1, %o0	/* Preserve nucleus page size fields */
261	stxa		%o0, [%o2] ASI_DMMU
262	stxa		%g0, [%g3] ASI_DMMU_DEMAP
263	stxa		%g0, [%g3] ASI_IMMU_DEMAP
264	stxa		%g2, [%o2] ASI_DMMU
265	sethi		%hi(KERNBASE), %o2
266	flush		%o2
267	wrpr		%g0, 0, %tl
268	retl
269	 wrpr		%g7, 0x0, %pstate
270
271__cheetah_flush_tlb_page:	/* 22 insns */
272	/* %o0 = context, %o1 = vaddr */
273	rdpr		%pstate, %g7
274	andn		%g7, PSTATE_IE, %g2
275	wrpr		%g2, 0x0, %pstate
276	wrpr		%g0, 1, %tl
277	mov		PRIMARY_CONTEXT, %o4
278	ldxa		[%o4] ASI_DMMU, %g2
279	srlx		%g2, CTX_PGSZ1_NUC_SHIFT, %o3
280	sllx		%o3, CTX_PGSZ1_NUC_SHIFT, %o3
281	or		%o0, %o3, %o0	/* Preserve nucleus page size fields */
282	stxa		%o0, [%o4] ASI_DMMU
283	andcc		%o1, 1, %g0
284	be,pn		%icc, 1f
285	 andn		%o1, 1, %o3
286	stxa		%g0, [%o3] ASI_IMMU_DEMAP
2871:	stxa		%g0, [%o3] ASI_DMMU_DEMAP
288	membar		#Sync
289	stxa		%g2, [%o4] ASI_DMMU
290	sethi		%hi(KERNBASE), %o4
291	flush		%o4
292	wrpr		%g0, 0, %tl
293	retl
294	 wrpr		%g7, 0x0, %pstate
295
296__cheetah_flush_tlb_pending:	/* 27 insns */
297	/* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
298	rdpr		%pstate, %g7
299	sllx		%o1, 3, %o1
300	andn		%g7, PSTATE_IE, %g2
301	wrpr		%g2, 0x0, %pstate
302	wrpr		%g0, 1, %tl
303	mov		PRIMARY_CONTEXT, %o4
304	ldxa		[%o4] ASI_DMMU, %g2
305	srlx		%g2, CTX_PGSZ1_NUC_SHIFT, %o3
306	sllx		%o3, CTX_PGSZ1_NUC_SHIFT, %o3
307	or		%o0, %o3, %o0	/* Preserve nucleus page size fields */
308	stxa		%o0, [%o4] ASI_DMMU
3091:	sub		%o1, (1 << 3), %o1
310	ldx		[%o2 + %o1], %o3
311	andcc		%o3, 1, %g0
312	be,pn		%icc, 2f
313	 andn		%o3, 1, %o3
314	stxa		%g0, [%o3] ASI_IMMU_DEMAP
3152:	stxa		%g0, [%o3] ASI_DMMU_DEMAP
316	membar		#Sync
317	brnz,pt		%o1, 1b
318	 nop
319	stxa		%g2, [%o4] ASI_DMMU
320	sethi		%hi(KERNBASE), %o4
321	flush		%o4
322	wrpr		%g0, 0, %tl
323	retl
324	 wrpr		%g7, 0x0, %pstate
325
326__cheetah_flush_tlb_kernel_range:	/* 31 insns */
327	/* %o0=start, %o1=end */
328	cmp		%o0, %o1
329	be,pn		%xcc, 2f
330	 sub		%o1, %o0, %o3
331	srlx		%o3, 18, %o4
332	brnz,pn		%o4, 3f
333	 sethi		%hi(PAGE_SIZE), %o4
334	sub		%o3, %o4, %o3
335	or		%o0, 0x20, %o0		! Nucleus
3361:	stxa		%g0, [%o0 + %o3] ASI_DMMU_DEMAP
337	stxa		%g0, [%o0 + %o3] ASI_IMMU_DEMAP
338	membar		#Sync
339	brnz,pt		%o3, 1b
340	 sub		%o3, %o4, %o3
3412:	sethi		%hi(KERNBASE), %o3
342	flush		%o3
343	retl
344	 nop
3453:	mov		0x80, %o4
346	stxa		%g0, [%o4] ASI_DMMU_DEMAP
347	membar		#Sync
348	stxa		%g0, [%o4] ASI_IMMU_DEMAP
349	membar		#Sync
350	retl
351	 nop
352	nop
353	nop
354	nop
355	nop
356	nop
357	nop
358	nop
359
360#ifdef DCACHE_ALIASING_POSSIBLE
361__cheetah_flush_dcache_page: /* 11 insns */
362	sethi		%hi(PAGE_OFFSET), %g1
363	ldx		[%g1 + %lo(PAGE_OFFSET)], %g1
364	sub		%o0, %g1, %o0
365	sethi		%hi(PAGE_SIZE), %o4
3661:	subcc		%o4, (1 << 5), %o4
367	stxa		%g0, [%o0 + %o4] ASI_DCACHE_INVALIDATE
368	membar		#Sync
369	bne,pt		%icc, 1b
370	 nop
371	retl		/* I-cache flush never needed on Cheetah, see callers. */
372	 nop
373#endif /* DCACHE_ALIASING_POSSIBLE */
374
375	/* Hypervisor specific versions, patched at boot time.  */
376__hypervisor_tlb_tl0_error:
377	save		%sp, -192, %sp
378	mov		%i0, %o0
379	call		hypervisor_tlbop_error
380	 mov		%i1, %o1
381	ret
382	 restore
383
384__hypervisor_flush_tlb_mm: /* 19 insns */
385	mov		%o0, %o2	/* ARG2: mmu context */
386	mov		0, %o0		/* ARG0: CPU lists unimplemented */
387	mov		0, %o1		/* ARG1: CPU lists unimplemented */
388	mov		HV_MMU_ALL, %o3	/* ARG3: flags */
389	mov		HV_FAST_MMU_DEMAP_CTX, %o5
390	ta		HV_FAST_TRAP
391	brnz,pn		%o0, 1f
392	 mov		HV_FAST_MMU_DEMAP_CTX, %o1
393	retl
394	 nop
3951:	sethi		%hi(__hypervisor_tlb_tl0_error), %o5
396	jmpl		%o5 + %lo(__hypervisor_tlb_tl0_error), %g0
397	 nop
398	nop
399	nop
400	nop
401	nop
402	nop
403	nop
404
405__hypervisor_flush_tlb_page: /* 22 insns */
406	/* %o0 = context, %o1 = vaddr */
407	mov		%o0, %g2
408	mov		%o1, %o0              /* ARG0: vaddr + IMMU-bit */
409	mov		%g2, %o1	      /* ARG1: mmu context */
410	mov		HV_MMU_ALL, %o2	      /* ARG2: flags */
411	srlx		%o0, PAGE_SHIFT, %o0
412	sllx		%o0, PAGE_SHIFT, %o0
413	ta		HV_MMU_UNMAP_ADDR_TRAP
414	brnz,pn		%o0, 1f
415	 mov		HV_MMU_UNMAP_ADDR_TRAP, %o1
416	retl
417	 nop
4181:	sethi		%hi(__hypervisor_tlb_tl0_error), %o2
419	jmpl		%o2 + %lo(__hypervisor_tlb_tl0_error), %g0
420	 nop
421	nop
422	nop
423	nop
424	nop
425	nop
426	nop
427	nop
428	nop
429
430__hypervisor_flush_tlb_pending: /* 27 insns */
431	/* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
432	sllx		%o1, 3, %g1
433	mov		%o2, %g2
434	mov		%o0, %g3
4351:	sub		%g1, (1 << 3), %g1
436	ldx		[%g2 + %g1], %o0      /* ARG0: vaddr + IMMU-bit */
437	mov		%g3, %o1	      /* ARG1: mmu context */
438	mov		HV_MMU_ALL, %o2	      /* ARG2: flags */
439	srlx		%o0, PAGE_SHIFT, %o0
440	sllx		%o0, PAGE_SHIFT, %o0
441	ta		HV_MMU_UNMAP_ADDR_TRAP
442	brnz,pn		%o0, 1f
443	 mov		HV_MMU_UNMAP_ADDR_TRAP, %o1
444	brnz,pt		%g1, 1b
445	 nop
446	retl
447	 nop
4481:	sethi		%hi(__hypervisor_tlb_tl0_error), %o2
449	jmpl		%o2 + %lo(__hypervisor_tlb_tl0_error), %g0
450	 nop
451	nop
452	nop
453	nop
454	nop
455	nop
456	nop
457	nop
458	nop
459
460__hypervisor_flush_tlb_kernel_range: /* 31 insns */
461	/* %o0=start, %o1=end */
462	cmp		%o0, %o1
463	be,pn		%xcc, 2f
464	 sub		%o1, %o0, %g2
465	srlx		%g2, 18, %g3
466	brnz,pn		%g3, 4f
467	 mov		%o0, %g1
468	sethi		%hi(PAGE_SIZE), %g3
469	sub		%g2, %g3, %g2
4701:	add		%g1, %g2, %o0	/* ARG0: virtual address */
471	mov		0, %o1		/* ARG1: mmu context */
472	mov		HV_MMU_ALL, %o2	/* ARG2: flags */
473	ta		HV_MMU_UNMAP_ADDR_TRAP
474	brnz,pn		%o0, 3f
475	 mov		HV_MMU_UNMAP_ADDR_TRAP, %o1
476	brnz,pt		%g2, 1b
477	 sub		%g2, %g3, %g2
4782:	retl
479	 nop
4803:	sethi		%hi(__hypervisor_tlb_tl0_error), %o2
481	jmpl		%o2 + %lo(__hypervisor_tlb_tl0_error), %g0
482	 nop
4834:	mov		0, %o0		/* ARG0: CPU lists unimplemented */
484	mov		0, %o1		/* ARG1: CPU lists unimplemented */
485	mov		0, %o2		/* ARG2: mmu context == nucleus */
486	mov		HV_MMU_ALL, %o3	/* ARG3: flags */
487	mov		HV_FAST_MMU_DEMAP_CTX, %o5
488	ta		HV_FAST_TRAP
489	brnz,pn		%o0, 3b
490	 mov		HV_FAST_MMU_DEMAP_CTX, %o1
491	retl
492	 nop
493
494#ifdef DCACHE_ALIASING_POSSIBLE
495	/* XXX Niagara and friends have an 8K cache, so no aliasing is
496	 * XXX possible, but nothing explicit in the Hypervisor API
497	 * XXX guarantees this.
498	 */
499__hypervisor_flush_dcache_page:	/* 2 insns */
500	retl
501	 nop
502#endif
503
504tlb_patch_one:
5051:	lduw		[%o1], %g1
506	stw		%g1, [%o0]
507	flush		%o0
508	subcc		%o2, 1, %o2
509	add		%o1, 4, %o1
510	bne,pt		%icc, 1b
511	 add		%o0, 4, %o0
512	retl
513	 nop
514
515#ifdef CONFIG_SMP
516	/* These are all called by the slaves of a cross call, at
517	 * trap level 1, with interrupts fully disabled.
518	 *
519	 * Register usage:
520	 *   %g5	mm->context	(all tlb flushes)
521	 *   %g1	address arg 1	(tlb page and range flushes)
522	 *   %g7	address arg 2	(tlb range flush only)
523	 *
524	 *   %g6	scratch 1
525	 *   %g2	scratch 2
526	 *   %g3	scratch 3
527	 *   %g4	scratch 4
528	 */
529	.align		32
530	.globl		xcall_flush_tlb_mm
531xcall_flush_tlb_mm:	/* 24 insns */
532	mov		PRIMARY_CONTEXT, %g2
533	ldxa		[%g2] ASI_DMMU, %g3
534	srlx		%g3, CTX_PGSZ1_NUC_SHIFT, %g4
535	sllx		%g4, CTX_PGSZ1_NUC_SHIFT, %g4
536	or		%g5, %g4, %g5	/* Preserve nucleus page size fields */
537	stxa		%g5, [%g2] ASI_DMMU
538	mov		0x40, %g4
539	stxa		%g0, [%g4] ASI_DMMU_DEMAP
540	stxa		%g0, [%g4] ASI_IMMU_DEMAP
541	stxa		%g3, [%g2] ASI_DMMU
542	retry
543	nop
544	nop
545	nop
546	nop
547	nop
548	nop
549	nop
550	nop
551	nop
552	nop
553	nop
554	nop
555	nop
556
557	.globl		xcall_flush_tlb_page
558xcall_flush_tlb_page:	/* 20 insns */
559	/* %g5=context, %g1=vaddr */
560	mov		PRIMARY_CONTEXT, %g4
561	ldxa		[%g4] ASI_DMMU, %g2
562	srlx		%g2, CTX_PGSZ1_NUC_SHIFT, %g4
563	sllx		%g4, CTX_PGSZ1_NUC_SHIFT, %g4
564	or		%g5, %g4, %g5
565	mov		PRIMARY_CONTEXT, %g4
566	stxa		%g5, [%g4] ASI_DMMU
567	andcc		%g1, 0x1, %g0
568	be,pn		%icc, 2f
569	 andn		%g1, 0x1, %g5
570	stxa		%g0, [%g5] ASI_IMMU_DEMAP
5712:	stxa		%g0, [%g5] ASI_DMMU_DEMAP
572	membar		#Sync
573	stxa		%g2, [%g4] ASI_DMMU
574	retry
575	nop
576	nop
577	nop
578	nop
579	nop
580
581	.globl		xcall_flush_tlb_kernel_range
582xcall_flush_tlb_kernel_range:	/* 44 insns */
583	sethi		%hi(PAGE_SIZE - 1), %g2
584	or		%g2, %lo(PAGE_SIZE - 1), %g2
585	andn		%g1, %g2, %g1
586	andn		%g7, %g2, %g7
587	sub		%g7, %g1, %g3
588	srlx		%g3, 18, %g2
589	brnz,pn		%g2, 2f
590	 sethi		%hi(PAGE_SIZE), %g2
591	sub		%g3, %g2, %g3
592	or		%g1, 0x20, %g1		! Nucleus
5931:	stxa		%g0, [%g1 + %g3] ASI_DMMU_DEMAP
594	stxa		%g0, [%g1 + %g3] ASI_IMMU_DEMAP
595	membar		#Sync
596	brnz,pt		%g3, 1b
597	 sub		%g3, %g2, %g3
598	retry
5992:	mov		63 * 8, %g1
6001:	ldxa		[%g1] ASI_ITLB_DATA_ACCESS, %g2
601	andcc		%g2, 0x40, %g0			/* _PAGE_L_4U */
602	bne,pn		%xcc, 2f
603	 mov		TLB_TAG_ACCESS, %g2
604	stxa		%g0, [%g2] ASI_IMMU
605	stxa		%g0, [%g1] ASI_ITLB_DATA_ACCESS
606	membar		#Sync
6072:	ldxa		[%g1] ASI_DTLB_DATA_ACCESS, %g2
608	andcc		%g2, 0x40, %g0
609	bne,pn		%xcc, 2f
610	 mov		TLB_TAG_ACCESS, %g2
611	stxa		%g0, [%g2] ASI_DMMU
612	stxa		%g0, [%g1] ASI_DTLB_DATA_ACCESS
613	membar		#Sync
6142:	sub		%g1, 8, %g1
615	brgez,pt	%g1, 1b
616	 nop
617	retry
618	nop
619	nop
620	nop
621	nop
622	nop
623	nop
624	nop
625	nop
626	nop
627
628	/* This runs in a very controlled environment, so we do
629	 * not need to worry about BH races etc.
630	 */
631	.globl		xcall_sync_tick
632xcall_sync_tick:
633
634661:	rdpr		%pstate, %g2
635	wrpr		%g2, PSTATE_IG | PSTATE_AG, %pstate
636	.section	.sun4v_2insn_patch, "ax"
637	.word		661b
638	nop
639	nop
640	.previous
641
642	rdpr		%pil, %g2
643	wrpr		%g0, PIL_NORMAL_MAX, %pil
644	sethi		%hi(109f), %g7
645	b,pt		%xcc, etrap_irq
646109:	 or		%g7, %lo(109b), %g7
647#ifdef CONFIG_TRACE_IRQFLAGS
648	call		trace_hardirqs_off
649	 nop
650#endif
651	call		smp_synchronize_tick_client
652	 nop
653	b		rtrap_xcall
654	 ldx		[%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
655
656	.globl		xcall_fetch_glob_regs
657xcall_fetch_glob_regs:
658	sethi		%hi(global_cpu_snapshot), %g1
659	or		%g1, %lo(global_cpu_snapshot), %g1
660	__GET_CPUID(%g2)
661	sllx		%g2, 6, %g3
662	add		%g1, %g3, %g1
663	rdpr		%tstate, %g7
664	stx		%g7, [%g1 + GR_SNAP_TSTATE]
665	rdpr		%tpc, %g7
666	stx		%g7, [%g1 + GR_SNAP_TPC]
667	rdpr		%tnpc, %g7
668	stx		%g7, [%g1 + GR_SNAP_TNPC]
669	stx		%o7, [%g1 + GR_SNAP_O7]
670	stx		%i7, [%g1 + GR_SNAP_I7]
671	/* Don't try this at home kids... */
672	rdpr		%cwp, %g3
673	sub		%g3, 1, %g7
674	wrpr		%g7, %cwp
675	mov		%i7, %g7
676	wrpr		%g3, %cwp
677	stx		%g7, [%g1 + GR_SNAP_RPC]
678	sethi		%hi(trap_block), %g7
679	or		%g7, %lo(trap_block), %g7
680	sllx		%g2, TRAP_BLOCK_SZ_SHIFT, %g2
681	add		%g7, %g2, %g7
682	ldx		[%g7 + TRAP_PER_CPU_THREAD], %g3
683	stx		%g3, [%g1 + GR_SNAP_THREAD]
684	retry
685
686	.globl		xcall_fetch_glob_pmu
687xcall_fetch_glob_pmu:
688	sethi		%hi(global_cpu_snapshot), %g1
689	or		%g1, %lo(global_cpu_snapshot), %g1
690	__GET_CPUID(%g2)
691	sllx		%g2, 6, %g3
692	add		%g1, %g3, %g1
693	rd		%pic, %g7
694	stx		%g7, [%g1 + (4 * 8)]
695	rd		%pcr, %g7
696	stx		%g7, [%g1 + (0 * 8)]
697	retry
698
699	.globl		xcall_fetch_glob_pmu_n4
700xcall_fetch_glob_pmu_n4:
701	sethi		%hi(global_cpu_snapshot), %g1
702	or		%g1, %lo(global_cpu_snapshot), %g1
703	__GET_CPUID(%g2)
704	sllx		%g2, 6, %g3
705	add		%g1, %g3, %g1
706
707	ldxa		[%g0] ASI_PIC, %g7
708	stx		%g7, [%g1 + (4 * 8)]
709	mov		0x08, %g3
710	ldxa		[%g3] ASI_PIC, %g7
711	stx		%g7, [%g1 + (5 * 8)]
712	mov		0x10, %g3
713	ldxa		[%g3] ASI_PIC, %g7
714	stx		%g7, [%g1 + (6 * 8)]
715	mov		0x18, %g3
716	ldxa		[%g3] ASI_PIC, %g7
717	stx		%g7, [%g1 + (7 * 8)]
718
719	mov		%o0, %g2
720	mov		%o1, %g3
721	mov		%o5, %g7
722
723	mov		HV_FAST_VT_GET_PERFREG, %o5
724	mov		3, %o0
725	ta		HV_FAST_TRAP
726	stx		%o1, [%g1 + (3 * 8)]
727	mov		HV_FAST_VT_GET_PERFREG, %o5
728	mov		2, %o0
729	ta		HV_FAST_TRAP
730	stx		%o1, [%g1 + (2 * 8)]
731	mov		HV_FAST_VT_GET_PERFREG, %o5
732	mov		1, %o0
733	ta		HV_FAST_TRAP
734	stx		%o1, [%g1 + (1 * 8)]
735	mov		HV_FAST_VT_GET_PERFREG, %o5
736	mov		0, %o0
737	ta		HV_FAST_TRAP
738	stx		%o1, [%g1 + (0 * 8)]
739
740	mov		%g2, %o0
741	mov		%g3, %o1
742	mov		%g7, %o5
743
744	retry
745
746__cheetah_xcall_flush_tlb_kernel_range:	/* 44 insns */
747	sethi		%hi(PAGE_SIZE - 1), %g2
748	or		%g2, %lo(PAGE_SIZE - 1), %g2
749	andn		%g1, %g2, %g1
750	andn		%g7, %g2, %g7
751	sub		%g7, %g1, %g3
752	srlx		%g3, 18, %g2
753	brnz,pn		%g2, 2f
754	 sethi		%hi(PAGE_SIZE), %g2
755	sub		%g3, %g2, %g3
756	or		%g1, 0x20, %g1		! Nucleus
7571:	stxa		%g0, [%g1 + %g3] ASI_DMMU_DEMAP
758	stxa		%g0, [%g1 + %g3] ASI_IMMU_DEMAP
759	membar		#Sync
760	brnz,pt		%g3, 1b
761	 sub		%g3, %g2, %g3
762	retry
7632:	mov		0x80, %g2
764	stxa		%g0, [%g2] ASI_DMMU_DEMAP
765	membar		#Sync
766	stxa		%g0, [%g2] ASI_IMMU_DEMAP
767	membar		#Sync
768	retry
769	nop
770	nop
771	nop
772	nop
773	nop
774	nop
775	nop
776	nop
777	nop
778	nop
779	nop
780	nop
781	nop
782	nop
783	nop
784	nop
785	nop
786	nop
787	nop
788	nop
789	nop
790	nop
791
792#ifdef DCACHE_ALIASING_POSSIBLE
793	.align		32
794	.globl		xcall_flush_dcache_page_cheetah
795xcall_flush_dcache_page_cheetah: /* %g1 == physical page address */
796	sethi		%hi(PAGE_SIZE), %g3
7971:	subcc		%g3, (1 << 5), %g3
798	stxa		%g0, [%g1 + %g3] ASI_DCACHE_INVALIDATE
799	membar		#Sync
800	bne,pt		%icc, 1b
801	 nop
802	retry
803	nop
804#endif /* DCACHE_ALIASING_POSSIBLE */
805
806	.globl		xcall_flush_dcache_page_spitfire
807xcall_flush_dcache_page_spitfire: /* %g1 == physical page address
808				     %g7 == kernel page virtual address
809				     %g5 == (page->mapping != NULL)  */
810#ifdef DCACHE_ALIASING_POSSIBLE
811	srlx		%g1, (13 - 2), %g1	! Form tag comparitor
812	sethi		%hi(L1DCACHE_SIZE), %g3	! D$ size == 16K
813	sub		%g3, (1 << 5), %g3	! D$ linesize == 32
8141:	ldxa		[%g3] ASI_DCACHE_TAG, %g2
815	andcc		%g2, 0x3, %g0
816	be,pn		%xcc, 2f
817	 andn		%g2, 0x3, %g2
818	cmp		%g2, %g1
819
820	bne,pt		%xcc, 2f
821	 nop
822	stxa		%g0, [%g3] ASI_DCACHE_TAG
823	membar		#Sync
8242:	cmp		%g3, 0
825	bne,pt		%xcc, 1b
826	 sub		%g3, (1 << 5), %g3
827
828	brz,pn		%g5, 2f
829#endif /* DCACHE_ALIASING_POSSIBLE */
830	 sethi		%hi(PAGE_SIZE), %g3
831
8321:	flush		%g7
833	subcc		%g3, (1 << 5), %g3
834	bne,pt		%icc, 1b
835	 add		%g7, (1 << 5), %g7
836
8372:	retry
838	nop
839	nop
840
841	/* %g5:	error
842	 * %g6:	tlb op
843	 */
844__hypervisor_tlb_xcall_error:
845	mov	%g5, %g4
846	mov	%g6, %g5
847	ba,pt	%xcc, etrap
848	 rd	%pc, %g7
849	mov	%l4, %o0
850	call	hypervisor_tlbop_error_xcall
851	 mov	%l5, %o1
852	ba,a,pt	%xcc, rtrap
853
854	.globl		__hypervisor_xcall_flush_tlb_mm
855__hypervisor_xcall_flush_tlb_mm: /* 24 insns */
856	/* %g5=ctx, g1,g2,g3,g4,g7=scratch, %g6=unusable */
857	mov		%o0, %g2
858	mov		%o1, %g3
859	mov		%o2, %g4
860	mov		%o3, %g1
861	mov		%o5, %g7
862	clr		%o0		/* ARG0: CPU lists unimplemented */
863	clr		%o1		/* ARG1: CPU lists unimplemented */
864	mov		%g5, %o2	/* ARG2: mmu context */
865	mov		HV_MMU_ALL, %o3	/* ARG3: flags */
866	mov		HV_FAST_MMU_DEMAP_CTX, %o5
867	ta		HV_FAST_TRAP
868	mov		HV_FAST_MMU_DEMAP_CTX, %g6
869	brnz,pn		%o0, 1f
870	 mov		%o0, %g5
871	mov		%g2, %o0
872	mov		%g3, %o1
873	mov		%g4, %o2
874	mov		%g1, %o3
875	mov		%g7, %o5
876	membar		#Sync
877	retry
8781:	sethi		%hi(__hypervisor_tlb_xcall_error), %g4
879	jmpl		%g4 + %lo(__hypervisor_tlb_xcall_error), %g0
880	 nop
881
882	.globl		__hypervisor_xcall_flush_tlb_page
883__hypervisor_xcall_flush_tlb_page: /* 20 insns */
884	/* %g5=ctx, %g1=vaddr */
885	mov		%o0, %g2
886	mov		%o1, %g3
887	mov		%o2, %g4
888	mov		%g1, %o0	        /* ARG0: virtual address */
889	mov		%g5, %o1		/* ARG1: mmu context */
890	mov		HV_MMU_ALL, %o2		/* ARG2: flags */
891	srlx		%o0, PAGE_SHIFT, %o0
892	sllx		%o0, PAGE_SHIFT, %o0
893	ta		HV_MMU_UNMAP_ADDR_TRAP
894	mov		HV_MMU_UNMAP_ADDR_TRAP, %g6
895	brnz,a,pn	%o0, 1f
896	 mov		%o0, %g5
897	mov		%g2, %o0
898	mov		%g3, %o1
899	mov		%g4, %o2
900	membar		#Sync
901	retry
9021:	sethi		%hi(__hypervisor_tlb_xcall_error), %g4
903	jmpl		%g4 + %lo(__hypervisor_tlb_xcall_error), %g0
904	 nop
905
906	.globl		__hypervisor_xcall_flush_tlb_kernel_range
907__hypervisor_xcall_flush_tlb_kernel_range: /* 44 insns */
908	/* %g1=start, %g7=end, g2,g3,g4,g5,g6=scratch */
909	sethi		%hi(PAGE_SIZE - 1), %g2
910	or		%g2, %lo(PAGE_SIZE - 1), %g2
911	andn		%g1, %g2, %g1
912	andn		%g7, %g2, %g7
913	sub		%g7, %g1, %g3
914	srlx		%g3, 18, %g7
915	add		%g2, 1, %g2
916	sub		%g3, %g2, %g3
917	mov		%o0, %g2
918	mov		%o1, %g4
919	brnz,pn		%g7, 2f
920	 mov		%o2, %g7
9211:	add		%g1, %g3, %o0	/* ARG0: virtual address */
922	mov		0, %o1		/* ARG1: mmu context */
923	mov		HV_MMU_ALL, %o2	/* ARG2: flags */
924	ta		HV_MMU_UNMAP_ADDR_TRAP
925	mov		HV_MMU_UNMAP_ADDR_TRAP, %g6
926	brnz,pn		%o0, 1f
927	 mov		%o0, %g5
928	sethi		%hi(PAGE_SIZE), %o2
929	brnz,pt		%g3, 1b
930	 sub		%g3, %o2, %g3
9315:	mov		%g2, %o0
932	mov		%g4, %o1
933	mov		%g7, %o2
934	membar		#Sync
935	retry
9361:	sethi		%hi(__hypervisor_tlb_xcall_error), %g4
937	jmpl		%g4 + %lo(__hypervisor_tlb_xcall_error), %g0
938	 nop
9392:	mov		%o3, %g1
940	mov		%o5, %g3
941	mov		0, %o0		/* ARG0: CPU lists unimplemented */
942	mov		0, %o1		/* ARG1: CPU lists unimplemented */
943	mov		0, %o2		/* ARG2: mmu context == nucleus */
944	mov		HV_MMU_ALL, %o3	/* ARG3: flags */
945	mov		HV_FAST_MMU_DEMAP_CTX, %o5
946	ta		HV_FAST_TRAP
947	mov		%g1, %o3
948	brz,pt		%o0, 5b
949	 mov		%g3, %o5
950	mov		HV_FAST_MMU_DEMAP_CTX, %g6
951	ba,pt		%xcc, 1b
952	 clr		%g5
953
954	/* These just get rescheduled to PIL vectors. */
955	.globl		xcall_call_function
956xcall_call_function:
957	wr		%g0, (1 << PIL_SMP_CALL_FUNC), %set_softint
958	retry
959
960	.globl		xcall_call_function_single
961xcall_call_function_single:
962	wr		%g0, (1 << PIL_SMP_CALL_FUNC_SNGL), %set_softint
963	retry
964
965	.globl		xcall_receive_signal
966xcall_receive_signal:
967	wr		%g0, (1 << PIL_SMP_RECEIVE_SIGNAL), %set_softint
968	retry
969
970	.globl		xcall_capture
971xcall_capture:
972	wr		%g0, (1 << PIL_SMP_CAPTURE), %set_softint
973	retry
974
975#ifdef CONFIG_KGDB
976	.globl		xcall_kgdb_capture
977xcall_kgdb_capture:
978	wr		%g0, (1 << PIL_KGDB_CAPTURE), %set_softint
979	retry
980#endif
981
982#endif /* CONFIG_SMP */
983
984	.globl		cheetah_patch_cachetlbops
985cheetah_patch_cachetlbops:
986	save		%sp, -128, %sp
987
988	sethi		%hi(__flush_tlb_mm), %o0
989	or		%o0, %lo(__flush_tlb_mm), %o0
990	sethi		%hi(__cheetah_flush_tlb_mm), %o1
991	or		%o1, %lo(__cheetah_flush_tlb_mm), %o1
992	call		tlb_patch_one
993	 mov		19, %o2
994
995	sethi		%hi(__flush_tlb_page), %o0
996	or		%o0, %lo(__flush_tlb_page), %o0
997	sethi		%hi(__cheetah_flush_tlb_page), %o1
998	or		%o1, %lo(__cheetah_flush_tlb_page), %o1
999	call		tlb_patch_one
1000	 mov		22, %o2
1001
1002	sethi		%hi(__flush_tlb_pending), %o0
1003	or		%o0, %lo(__flush_tlb_pending), %o0
1004	sethi		%hi(__cheetah_flush_tlb_pending), %o1
1005	or		%o1, %lo(__cheetah_flush_tlb_pending), %o1
1006	call		tlb_patch_one
1007	 mov		27, %o2
1008
1009	sethi		%hi(__flush_tlb_kernel_range), %o0
1010	or		%o0, %lo(__flush_tlb_kernel_range), %o0
1011	sethi		%hi(__cheetah_flush_tlb_kernel_range), %o1
1012	or		%o1, %lo(__cheetah_flush_tlb_kernel_range), %o1
1013	call		tlb_patch_one
1014	 mov		31, %o2
1015
1016#ifdef DCACHE_ALIASING_POSSIBLE
1017	sethi		%hi(__flush_dcache_page), %o0
1018	or		%o0, %lo(__flush_dcache_page), %o0
1019	sethi		%hi(__cheetah_flush_dcache_page), %o1
1020	or		%o1, %lo(__cheetah_flush_dcache_page), %o1
1021	call		tlb_patch_one
1022	 mov		11, %o2
1023#endif /* DCACHE_ALIASING_POSSIBLE */
1024
1025#ifdef CONFIG_SMP
1026	sethi		%hi(xcall_flush_tlb_kernel_range), %o0
1027	or		%o0, %lo(xcall_flush_tlb_kernel_range), %o0
1028	sethi		%hi(__cheetah_xcall_flush_tlb_kernel_range), %o1
1029	or		%o1, %lo(__cheetah_xcall_flush_tlb_kernel_range), %o1
1030	call		tlb_patch_one
1031	 mov		44, %o2
1032#endif /* CONFIG_SMP */
1033
1034	ret
1035	 restore
1036
1037	.globl		hypervisor_patch_cachetlbops
1038hypervisor_patch_cachetlbops:
1039	save		%sp, -128, %sp
1040
1041	sethi		%hi(__flush_tlb_mm), %o0
1042	or		%o0, %lo(__flush_tlb_mm), %o0
1043	sethi		%hi(__hypervisor_flush_tlb_mm), %o1
1044	or		%o1, %lo(__hypervisor_flush_tlb_mm), %o1
1045	call		tlb_patch_one
1046	 mov		19, %o2
1047
1048	sethi		%hi(__flush_tlb_page), %o0
1049	or		%o0, %lo(__flush_tlb_page), %o0
1050	sethi		%hi(__hypervisor_flush_tlb_page), %o1
1051	or		%o1, %lo(__hypervisor_flush_tlb_page), %o1
1052	call		tlb_patch_one
1053	 mov		22, %o2
1054
1055	sethi		%hi(__flush_tlb_pending), %o0
1056	or		%o0, %lo(__flush_tlb_pending), %o0
1057	sethi		%hi(__hypervisor_flush_tlb_pending), %o1
1058	or		%o1, %lo(__hypervisor_flush_tlb_pending), %o1
1059	call		tlb_patch_one
1060	 mov		27, %o2
1061
1062	sethi		%hi(__flush_tlb_kernel_range), %o0
1063	or		%o0, %lo(__flush_tlb_kernel_range), %o0
1064	sethi		%hi(__hypervisor_flush_tlb_kernel_range), %o1
1065	or		%o1, %lo(__hypervisor_flush_tlb_kernel_range), %o1
1066	call		tlb_patch_one
1067	 mov		31, %o2
1068
1069#ifdef DCACHE_ALIASING_POSSIBLE
1070	sethi		%hi(__flush_dcache_page), %o0
1071	or		%o0, %lo(__flush_dcache_page), %o0
1072	sethi		%hi(__hypervisor_flush_dcache_page), %o1
1073	or		%o1, %lo(__hypervisor_flush_dcache_page), %o1
1074	call		tlb_patch_one
1075	 mov		2, %o2
1076#endif /* DCACHE_ALIASING_POSSIBLE */
1077
1078#ifdef CONFIG_SMP
1079	sethi		%hi(xcall_flush_tlb_mm), %o0
1080	or		%o0, %lo(xcall_flush_tlb_mm), %o0
1081	sethi		%hi(__hypervisor_xcall_flush_tlb_mm), %o1
1082	or		%o1, %lo(__hypervisor_xcall_flush_tlb_mm), %o1
1083	call		tlb_patch_one
1084	 mov		24, %o2
1085
1086	sethi		%hi(xcall_flush_tlb_page), %o0
1087	or		%o0, %lo(xcall_flush_tlb_page), %o0
1088	sethi		%hi(__hypervisor_xcall_flush_tlb_page), %o1
1089	or		%o1, %lo(__hypervisor_xcall_flush_tlb_page), %o1
1090	call		tlb_patch_one
1091	 mov		20, %o2
1092
1093	sethi		%hi(xcall_flush_tlb_kernel_range), %o0
1094	or		%o0, %lo(xcall_flush_tlb_kernel_range), %o0
1095	sethi		%hi(__hypervisor_xcall_flush_tlb_kernel_range), %o1
1096	or		%o1, %lo(__hypervisor_xcall_flush_tlb_kernel_range), %o1
1097	call		tlb_patch_one
1098	 mov		44, %o2
1099#endif /* CONFIG_SMP */
1100
1101	ret
1102	 restore
1103