ultra.S 17.4 KB
Newer Older
A
Adrian Bunk 已提交
1
/*
L
Linus Torvalds 已提交
2 3
 * ultra.S: Don't expand these all over the place...
 *
4
 * Copyright (C) 1997, 2000, 2008 David S. Miller (davem@davemloft.net)
L
Linus Torvalds 已提交
5 6 7 8 9 10 11
 */

#include <asm/asi.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/spitfire.h>
#include <asm/mmu_context.h>
12
#include <asm/mmu.h>
L
Linus Torvalds 已提交
13 14 15 16
#include <asm/pil.h>
#include <asm/head.h>
#include <asm/thread_info.h>
#include <asm/cacheflush.h>
17
#include <asm/hypervisor.h>
18
#include <asm/cpudata.h>
L
Linus Torvalds 已提交
19 20 21 22 23 24 25 26 27 28 29 30 31 32

	/* Basically, most of the Spitfire vs. Cheetah madness
	 * has to do with the fact that Cheetah does not support
	 * IMMU flushes out of the secondary context.  Someone needs
	 * to throw a south lake birthday party for the folks
	 * in Microelectronics who refused to fix this shit.
	 */

	/* This file is meant to be read efficiently by the CPU, not humans.
	 * Staraj sie tego nikomu nie pierdolnac...
	 */
	.text
	.align		32
	.globl		__flush_tlb_mm
33 34
__flush_tlb_mm:		/* 18 insns */
	/* %o0=(ctx & TAG_CONTEXT_BITS), %o1=SECONDARY_CONTEXT */
L
Linus Torvalds 已提交
35 36 37 38 39 40
	ldxa		[%o1] ASI_DMMU, %g2
	cmp		%g2, %o0
	bne,pn		%icc, __spitfire_flush_tlb_mm_slow
	 mov		0x50, %g3
	stxa		%g0, [%g3] ASI_DMMU_DEMAP
	stxa		%g0, [%g3] ASI_IMMU_DEMAP
41 42
	sethi		%hi(KERNBASE), %g3
	flush		%g3
L
Linus Torvalds 已提交
43
	retl
44
	 nop
L
Linus Torvalds 已提交
45 46 47 48 49 50 51
	nop
	nop
	nop
	nop
	nop
	nop
	nop
52 53
	nop
	nop
L
Linus Torvalds 已提交
54 55 56

	.align		32
	.globl		__flush_tlb_pending
57
__flush_tlb_pending:	/* 26 insns */
L
Linus Torvalds 已提交
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
	/* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
	rdpr		%pstate, %g7
	sllx		%o1, 3, %o1
	andn		%g7, PSTATE_IE, %g2
	wrpr		%g2, %pstate
	mov		SECONDARY_CONTEXT, %o4
	ldxa		[%o4] ASI_DMMU, %g2
	stxa		%o0, [%o4] ASI_DMMU
1:	sub		%o1, (1 << 3), %o1
	ldx		[%o2 + %o1], %o3
	andcc		%o3, 1, %g0
	andn		%o3, 1, %o3
	be,pn		%icc, 2f
	 or		%o3, 0x10, %o3
	stxa		%g0, [%o3] ASI_IMMU_DEMAP
2:	stxa		%g0, [%o3] ASI_DMMU_DEMAP
	membar		#Sync
	brnz,pt		%o1, 1b
	 nop
	stxa		%g2, [%o4] ASI_DMMU
78 79
	sethi		%hi(KERNBASE), %o4
	flush		%o4
L
Linus Torvalds 已提交
80 81
	retl
	 wrpr		%g7, 0x0, %pstate
82
	nop
83 84 85
	nop
	nop
	nop
L
Linus Torvalds 已提交
86 87 88

	.align		32
	.globl		__flush_tlb_kernel_range
89
__flush_tlb_kernel_range:	/* 16 insns */
90
	/* %o0=start, %o1=end */
L
Linus Torvalds 已提交
91 92 93 94 95 96 97 98 99 100 101
	cmp		%o0, %o1
	be,pn		%xcc, 2f
	 sethi		%hi(PAGE_SIZE), %o4
	sub		%o1, %o0, %o3
	sub		%o3, %o4, %o3
	or		%o0, 0x20, %o0		! Nucleus
1:	stxa		%g0, [%o0 + %o3] ASI_DMMU_DEMAP
	stxa		%g0, [%o0 + %o3] ASI_IMMU_DEMAP
	membar		#Sync
	brnz,pt		%o3, 1b
	 sub		%o3, %o4, %o3
102 103 104 105
2:	sethi		%hi(KERNBASE), %o3
	flush		%o3
	retl
	 nop
106
	nop
L
Linus Torvalds 已提交
107 108 109 110 111 112 113 114 115

__spitfire_flush_tlb_mm_slow:
	rdpr		%pstate, %g1
	wrpr		%g1, PSTATE_IE, %pstate
	stxa		%o0, [%o1] ASI_DMMU
	stxa		%g0, [%g3] ASI_DMMU_DEMAP
	stxa		%g0, [%g3] ASI_IMMU_DEMAP
	flush		%g6
	stxa		%g2, [%o1] ASI_DMMU
116 117
	sethi		%hi(KERNBASE), %o1
	flush		%o1
L
Linus Torvalds 已提交
118 119 120 121 122 123
	retl
	 wrpr		%g1, 0, %pstate

/*
 * The following code flushes one page_size worth.
 */
124
	.section .kprobes.text, "ax"
L
Linus Torvalds 已提交
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
	.align		32
	.globl		__flush_icache_page
__flush_icache_page:	/* %o0 = phys_page */
	srlx		%o0, PAGE_SHIFT, %o0
	sethi		%uhi(PAGE_OFFSET), %g1
	sllx		%o0, PAGE_SHIFT, %o0
	sethi		%hi(PAGE_SIZE), %g2
	sllx		%g1, 32, %g1
	add		%o0, %g1, %o0
1:	subcc		%g2, 32, %g2
	bne,pt		%icc, 1b
	 flush		%o0 + %g2
	retl
	 nop

#ifdef DCACHE_ALIASING_POSSIBLE

#if (PAGE_SHIFT != 13)
#error only page shift of 13 is supported by dcache flush
#endif

#define DTAG_MASK 0x3

148 149 150
	/* This routine is Spitfire specific so the hardcoded
	 * D-cache size and line-size are OK.
	 */
L
Linus Torvalds 已提交
151 152 153 154 155
	.align		64
	.globl		__flush_dcache_page
__flush_dcache_page:	/* %o0=kaddr, %o1=flush_icache */
	sethi		%uhi(PAGE_OFFSET), %g1
	sllx		%g1, 32, %g1
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
	sub		%o0, %g1, %o0			! physical address
	srlx		%o0, 11, %o0			! make D-cache TAG
	sethi		%hi(1 << 14), %o2		! D-cache size
	sub		%o2, (1 << 5), %o2		! D-cache line size
1:	ldxa		[%o2] ASI_DCACHE_TAG, %o3	! load D-cache TAG
	andcc		%o3, DTAG_MASK, %g0		! Valid?
	be,pn		%xcc, 2f			! Nope, branch
	 andn		%o3, DTAG_MASK, %o3		! Clear valid bits
	cmp		%o3, %o0			! TAG match?
	bne,pt		%xcc, 2f			! Nope, branch
	 nop
	stxa		%g0, [%o2] ASI_DCACHE_TAG	! Invalidate TAG
	membar		#Sync
2:	brnz,pt		%o2, 1b
	 sub		%o2, (1 << 5), %o2		! D-cache line size
L
Linus Torvalds 已提交
171 172 173 174 175 176 177 178 179 180 181

	/* The I-cache does not snoop local stores so we
	 * better flush that too when necessary.
	 */
	brnz,pt		%o1, __flush_icache_page
	 sllx		%o0, 11, %o0
	retl
	 nop

#endif /* DCACHE_ALIASING_POSSIBLE */

182 183
	.previous

184
	/* Cheetah specific versions, patched at boot time. */
185
__cheetah_flush_tlb_mm: /* 19 insns */
L
Linus Torvalds 已提交
186 187 188 189 190 191 192
	rdpr		%pstate, %g7
	andn		%g7, PSTATE_IE, %g2
	wrpr		%g2, 0x0, %pstate
	wrpr		%g0, 1, %tl
	mov		PRIMARY_CONTEXT, %o2
	mov		0x40, %g3
	ldxa		[%o2] ASI_DMMU, %g2
193 194 195
	srlx		%g2, CTX_PGSZ1_NUC_SHIFT, %o1
	sllx		%o1, CTX_PGSZ1_NUC_SHIFT, %o1
	or		%o0, %o1, %o0	/* Preserve nucleus page size fields */
L
Linus Torvalds 已提交
196 197 198 199
	stxa		%o0, [%o2] ASI_DMMU
	stxa		%g0, [%g3] ASI_DMMU_DEMAP
	stxa		%g0, [%g3] ASI_IMMU_DEMAP
	stxa		%g2, [%o2] ASI_DMMU
200 201
	sethi		%hi(KERNBASE), %o2
	flush		%o2
L
Linus Torvalds 已提交
202 203 204 205
	wrpr		%g0, 0, %tl
	retl
	 wrpr		%g7, 0x0, %pstate

206
__cheetah_flush_tlb_pending:	/* 27 insns */
L
Linus Torvalds 已提交
207 208 209 210 211 212 213 214
	/* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
	rdpr		%pstate, %g7
	sllx		%o1, 3, %o1
	andn		%g7, PSTATE_IE, %g2
	wrpr		%g2, 0x0, %pstate
	wrpr		%g0, 1, %tl
	mov		PRIMARY_CONTEXT, %o4
	ldxa		[%o4] ASI_DMMU, %g2
215 216 217
	srlx		%g2, CTX_PGSZ1_NUC_SHIFT, %o3
	sllx		%o3, CTX_PGSZ1_NUC_SHIFT, %o3
	or		%o0, %o3, %o0	/* Preserve nucleus page size fields */
L
Linus Torvalds 已提交
218 219 220 221 222 223 224 225
	stxa		%o0, [%o4] ASI_DMMU
1:	sub		%o1, (1 << 3), %o1
	ldx		[%o2 + %o1], %o3
	andcc		%o3, 1, %g0
	be,pn		%icc, 2f
	 andn		%o3, 1, %o3
	stxa		%g0, [%o3] ASI_IMMU_DEMAP
2:	stxa		%g0, [%o3] ASI_DMMU_DEMAP	
226
	membar		#Sync
L
Linus Torvalds 已提交
227
	brnz,pt		%o1, 1b
228
	 nop
L
Linus Torvalds 已提交
229
	stxa		%g2, [%o4] ASI_DMMU
230 231
	sethi		%hi(KERNBASE), %o4
	flush		%o4
L
Linus Torvalds 已提交
232 233 234 235 236
	wrpr		%g0, 0, %tl
	retl
	 wrpr		%g7, 0x0, %pstate

#ifdef DCACHE_ALIASING_POSSIBLE
237
__cheetah_flush_dcache_page: /* 11 insns */
L
Linus Torvalds 已提交
238 239 240 241 242 243 244 245 246 247 248 249 250
	sethi		%uhi(PAGE_OFFSET), %g1
	sllx		%g1, 32, %g1
	sub		%o0, %g1, %o0
	sethi		%hi(PAGE_SIZE), %o4
1:	subcc		%o4, (1 << 5), %o4
	stxa		%g0, [%o0 + %o4] ASI_DCACHE_INVALIDATE
	membar		#Sync
	bne,pt		%icc, 1b
	 nop
	retl		/* I-cache flush never needed on Cheetah, see callers. */
	 nop
#endif /* DCACHE_ALIASING_POSSIBLE */

251
	/* Hypervisor specific versions, patched at boot time.  */
252 253 254 255 256 257 258 259 260
__hypervisor_tlb_tl0_error:
	save		%sp, -192, %sp
	mov		%i0, %o0
	call		hypervisor_tlbop_error
	 mov		%i1, %o1
	ret
	 restore

__hypervisor_flush_tlb_mm: /* 10 insns */
261 262 263 264 265 266
	mov		%o0, %o2	/* ARG2: mmu context */
	mov		0, %o0		/* ARG0: CPU lists unimplemented */
	mov		0, %o1		/* ARG1: CPU lists unimplemented */
	mov		HV_MMU_ALL, %o3	/* ARG3: flags */
	mov		HV_FAST_MMU_DEMAP_CTX, %o5
	ta		HV_FAST_TRAP
267 268
	brnz,pn		%o0, __hypervisor_tlb_tl0_error
	 mov		HV_FAST_MMU_DEMAP_CTX, %o1
269 270 271
	retl
	 nop

272
__hypervisor_flush_tlb_pending: /* 16 insns */
273 274 275 276 277 278 279
	/* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
	sllx		%o1, 3, %g1
	mov		%o2, %g2
	mov		%o0, %g3
1:	sub		%g1, (1 << 3), %g1
	ldx		[%g2 + %g1], %o0      /* ARG0: vaddr + IMMU-bit */
	mov		%g3, %o1	      /* ARG1: mmu context */
280 281 282
	mov		HV_MMU_ALL, %o2	      /* ARG2: flags */
	srlx		%o0, PAGE_SHIFT, %o0
	sllx		%o0, PAGE_SHIFT, %o0
283
	ta		HV_MMU_UNMAP_ADDR_TRAP
284 285
	brnz,pn		%o0, __hypervisor_tlb_tl0_error
	 mov		HV_MMU_UNMAP_ADDR_TRAP, %o1
286 287 288 289 290
	brnz,pt		%g1, 1b
	 nop
	retl
	 nop

291
__hypervisor_flush_tlb_kernel_range: /* 16 insns */
292 293 294 295 296 297 298 299 300 301 302
	/* %o0=start, %o1=end */
	cmp		%o0, %o1
	be,pn		%xcc, 2f
	 sethi		%hi(PAGE_SIZE), %g3
	mov		%o0, %g1
	sub		%o1, %g1, %g2
	sub		%g2, %g3, %g2
1:	add		%g1, %g2, %o0	/* ARG0: virtual address */
	mov		0, %o1		/* ARG1: mmu context */
	mov		HV_MMU_ALL, %o2	/* ARG2: flags */
	ta		HV_MMU_UNMAP_ADDR_TRAP
303 304
	brnz,pn		%o0, __hypervisor_tlb_tl0_error
	 mov		HV_MMU_UNMAP_ADDR_TRAP, %o1
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
	brnz,pt		%g2, 1b
	 sub		%g2, %g3, %g2
2:	retl
	 nop

#ifdef DCACHE_ALIASING_POSSIBLE
	/* XXX Niagara and friends have an 8K cache, so no aliasing is
	 * XXX possible, but nothing explicit in the Hypervisor API
	 * XXX guarantees this.
	 */
__hypervisor_flush_dcache_page:	/* 2 insns */
	retl
	 nop
#endif

tlb_patch_one:
L
Linus Torvalds 已提交
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
1:	lduw		[%o1], %g1
	stw		%g1, [%o0]
	flush		%o0
	subcc		%o2, 1, %o2
	add		%o1, 4, %o1
	bne,pt		%icc, 1b
	 add		%o0, 4, %o0
	retl
	 nop

	.globl		cheetah_patch_cachetlbops
cheetah_patch_cachetlbops:
	save		%sp, -128, %sp

	sethi		%hi(__flush_tlb_mm), %o0
	or		%o0, %lo(__flush_tlb_mm), %o0
	sethi		%hi(__cheetah_flush_tlb_mm), %o1
	or		%o1, %lo(__cheetah_flush_tlb_mm), %o1
339
	call		tlb_patch_one
340
	 mov		19, %o2
L
Linus Torvalds 已提交
341 342 343 344 345

	sethi		%hi(__flush_tlb_pending), %o0
	or		%o0, %lo(__flush_tlb_pending), %o0
	sethi		%hi(__cheetah_flush_tlb_pending), %o1
	or		%o1, %lo(__cheetah_flush_tlb_pending), %o1
346
	call		tlb_patch_one
347
	 mov		27, %o2
L
Linus Torvalds 已提交
348 349 350 351

#ifdef DCACHE_ALIASING_POSSIBLE
	sethi		%hi(__flush_dcache_page), %o0
	or		%o0, %lo(__flush_dcache_page), %o0
352 353
	sethi		%hi(__cheetah_flush_dcache_page), %o1
	or		%o1, %lo(__cheetah_flush_dcache_page), %o1
354
	call		tlb_patch_one
L
Linus Torvalds 已提交
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
	 mov		11, %o2
#endif /* DCACHE_ALIASING_POSSIBLE */

	ret
	 restore

#ifdef CONFIG_SMP
	/* These are all called by the slaves of a cross call, at
	 * trap level 1, with interrupts fully disabled.
	 *
	 * Register usage:
	 *   %g5	mm->context	(all tlb flushes)
	 *   %g1	address arg 1	(tlb page and range flushes)
	 *   %g7	address arg 2	(tlb range flush only)
	 *
370 371 372 373
	 *   %g6	scratch 1
	 *   %g2	scratch 2
	 *   %g3	scratch 3
	 *   %g4	scratch 4
L
Linus Torvalds 已提交
374 375 376
	 */
	.align		32
	.globl		xcall_flush_tlb_mm
377
xcall_flush_tlb_mm:	/* 21 insns */
L
Linus Torvalds 已提交
378 379
	mov		PRIMARY_CONTEXT, %g2
	ldxa		[%g2] ASI_DMMU, %g3
380 381 382
	srlx		%g3, CTX_PGSZ1_NUC_SHIFT, %g4
	sllx		%g4, CTX_PGSZ1_NUC_SHIFT, %g4
	or		%g5, %g4, %g5	/* Preserve nucleus page size fields */
L
Linus Torvalds 已提交
383
	stxa		%g5, [%g2] ASI_DMMU
384
	mov		0x40, %g4
L
Linus Torvalds 已提交
385 386 387 388
	stxa		%g0, [%g4] ASI_DMMU_DEMAP
	stxa		%g0, [%g4] ASI_IMMU_DEMAP
	stxa		%g3, [%g2] ASI_DMMU
	retry
389 390 391 392 393 394 395
	nop
	nop
	nop
	nop
	nop
	nop
	nop
396 397 398
	nop
	nop
	nop
L
Linus Torvalds 已提交
399 400

	.globl		xcall_flush_tlb_pending
401
xcall_flush_tlb_pending:	/* 21 insns */
L
Linus Torvalds 已提交
402 403 404 405
	/* %g5=context, %g1=nr, %g7=vaddrs[] */
	sllx		%g1, 3, %g1
	mov		PRIMARY_CONTEXT, %g4
	ldxa		[%g4] ASI_DMMU, %g2
406 407 408 409
	srlx		%g2, CTX_PGSZ1_NUC_SHIFT, %g4
	sllx		%g4, CTX_PGSZ1_NUC_SHIFT, %g4
	or		%g5, %g4, %g5
	mov		PRIMARY_CONTEXT, %g4
L
Linus Torvalds 已提交
410 411 412 413 414 415 416 417 418 419 420 421 422 423
	stxa		%g5, [%g4] ASI_DMMU
1:	sub		%g1, (1 << 3), %g1
	ldx		[%g7 + %g1], %g5
	andcc		%g5, 0x1, %g0
	be,pn		%icc, 2f

	 andn		%g5, 0x1, %g5
	stxa		%g0, [%g5] ASI_IMMU_DEMAP
2:	stxa		%g0, [%g5] ASI_DMMU_DEMAP
	membar		#Sync
	brnz,pt		%g1, 1b
	 nop
	stxa		%g2, [%g4] ASI_DMMU
	retry
424
	nop
L
Linus Torvalds 已提交
425 426

	.globl		xcall_flush_tlb_kernel_range
427
xcall_flush_tlb_kernel_range:	/* 25 insns */
L
Linus Torvalds 已提交
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
	sethi		%hi(PAGE_SIZE - 1), %g2
	or		%g2, %lo(PAGE_SIZE - 1), %g2
	andn		%g1, %g2, %g1
	andn		%g7, %g2, %g7
	sub		%g7, %g1, %g3
	add		%g2, 1, %g2
	sub		%g3, %g2, %g3
	or		%g1, 0x20, %g1		! Nucleus
1:	stxa		%g0, [%g1 + %g3] ASI_DMMU_DEMAP
	stxa		%g0, [%g1 + %g3] ASI_IMMU_DEMAP
	membar		#Sync
	brnz,pt		%g3, 1b
	 sub		%g3, %g2, %g3
	retry
	nop
	nop
444 445 446 447 448 449
	nop
	nop
	nop
	nop
	nop
	nop
450 451 452
	nop
	nop
	nop
L
Linus Torvalds 已提交
453 454 455 456 457 458

	/* This runs in a very controlled environment, so we do
	 * not need to worry about BH races etc.
	 */
	.globl		xcall_sync_tick
xcall_sync_tick:
459 460

661:	rdpr		%pstate, %g2
L
Linus Torvalds 已提交
461
	wrpr		%g2, PSTATE_IG | PSTATE_AG, %pstate
462
	.section	.sun4v_2insn_patch, "ax"
463 464 465 466 467
	.word		661b
	nop
	nop
	.previous

L
Linus Torvalds 已提交
468
	rdpr		%pil, %g2
469
	wrpr		%g0, PIL_NORMAL_MAX, %pil
L
Linus Torvalds 已提交
470 471 472
	sethi		%hi(109f), %g7
	b,pt		%xcc, etrap_irq
109:	 or		%g7, %lo(109b), %g7
473 474 475 476
#ifdef CONFIG_TRACE_IRQFLAGS
	call		trace_hardirqs_off
	 nop
#endif
L
Linus Torvalds 已提交
477 478 479 480 481
	call		smp_synchronize_tick_client
	 nop
	b		rtrap_xcall
	 ldx		[%sp + PTREGS_OFF + PT_V9_TSTATE], %l1

482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
	.globl		xcall_fetch_glob_regs
xcall_fetch_glob_regs:
	sethi		%hi(global_reg_snapshot), %g1
	or		%g1, %lo(global_reg_snapshot), %g1
	__GET_CPUID(%g2)
	sllx		%g2, 6, %g3
	add		%g1, %g3, %g1
	rdpr		%tstate, %g7
	stx		%g7, [%g1 + GR_SNAP_TSTATE]
	rdpr		%tpc, %g7
	stx		%g7, [%g1 + GR_SNAP_TPC]
	rdpr		%tnpc, %g7
	stx		%g7, [%g1 + GR_SNAP_TNPC]
	stx		%o7, [%g1 + GR_SNAP_O7]
	stx		%i7, [%g1 + GR_SNAP_I7]
497 498 499 500 501 502 503
	/* Don't try this at home kids... */
	rdpr		%cwp, %g2
	sub		%g2, 1, %g7
	wrpr		%g7, %cwp
	mov		%i7, %g7
	wrpr		%g2, %cwp
	stx		%g7, [%g1 + GR_SNAP_RPC]
504 505 506 507 508 509 510 511
	sethi		%hi(trap_block), %g7
	or		%g7, %lo(trap_block), %g7
	sllx		%g2, TRAP_BLOCK_SZ_SHIFT, %g2
	add		%g7, %g2, %g7
	ldx		[%g7 + TRAP_PER_CPU_THREAD], %g3
	stx		%g3, [%g1 + GR_SNAP_THREAD]
	retry

L
Linus Torvalds 已提交
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
#ifdef DCACHE_ALIASING_POSSIBLE
	.align		32
	.globl		xcall_flush_dcache_page_cheetah
xcall_flush_dcache_page_cheetah: /* %g1 == physical page address */
	sethi		%hi(PAGE_SIZE), %g3
1:	subcc		%g3, (1 << 5), %g3
	stxa		%g0, [%g1 + %g3] ASI_DCACHE_INVALIDATE
	membar		#Sync
	bne,pt		%icc, 1b
	 nop
	retry
	nop
#endif /* DCACHE_ALIASING_POSSIBLE */

	.globl		xcall_flush_dcache_page_spitfire
xcall_flush_dcache_page_spitfire: /* %g1 == physical page address
				     %g7 == kernel page virtual address
				     %g5 == (page->mapping != NULL)  */
#ifdef DCACHE_ALIASING_POSSIBLE
	srlx		%g1, (13 - 2), %g1	! Form tag comparitor
	sethi		%hi(L1DCACHE_SIZE), %g3	! D$ size == 16K
	sub		%g3, (1 << 5), %g3	! D$ linesize == 32
1:	ldxa		[%g3] ASI_DCACHE_TAG, %g2
	andcc		%g2, 0x3, %g0
	be,pn		%xcc, 2f
	 andn		%g2, 0x3, %g2
	cmp		%g2, %g1

	bne,pt		%xcc, 2f
	 nop
	stxa		%g0, [%g3] ASI_DCACHE_TAG
	membar		#Sync
2:	cmp		%g3, 0
	bne,pt		%xcc, 1b
	 sub		%g3, (1 << 5), %g3

	brz,pn		%g5, 2f
#endif /* DCACHE_ALIASING_POSSIBLE */
	 sethi		%hi(PAGE_SIZE), %g3

1:	flush		%g7
	subcc		%g3, (1 << 5), %g3
	bne,pt		%icc, 1b
	 add		%g7, (1 << 5), %g7

2:	retry
	nop
	nop

561 562 563 564 565 566 567 568 569 570 571
	/* %g5:	error
	 * %g6:	tlb op
	 */
__hypervisor_tlb_xcall_error:
	mov	%g5, %g4
	mov	%g6, %g5
	ba,pt	%xcc, etrap
	 rd	%pc, %g7
	mov	%l4, %o0
	call	hypervisor_tlbop_error_xcall
	 mov	%l5, %o1
572
	ba,a,pt	%xcc, rtrap
573

574
	.globl		__hypervisor_xcall_flush_tlb_mm
575
__hypervisor_xcall_flush_tlb_mm: /* 21 insns */
576 577 578 579 580 581 582 583 584 585 586 587
	/* %g5=ctx, g1,g2,g3,g4,g7=scratch, %g6=unusable */
	mov		%o0, %g2
	mov		%o1, %g3
	mov		%o2, %g4
	mov		%o3, %g1
	mov		%o5, %g7
	clr		%o0		/* ARG0: CPU lists unimplemented */
	clr		%o1		/* ARG1: CPU lists unimplemented */
	mov		%g5, %o2	/* ARG2: mmu context */
	mov		HV_MMU_ALL, %o3	/* ARG3: flags */
	mov		HV_FAST_MMU_DEMAP_CTX, %o5
	ta		HV_FAST_TRAP
588 589 590
	mov		HV_FAST_MMU_DEMAP_CTX, %g6
	brnz,pn		%o0, __hypervisor_tlb_xcall_error
	 mov		%o0, %g5
591 592 593 594 595 596 597 598 599
	mov		%g2, %o0
	mov		%g3, %o1
	mov		%g4, %o2
	mov		%g1, %o3
	mov		%g7, %o5
	membar		#Sync
	retry

	.globl		__hypervisor_xcall_flush_tlb_pending
600 601
__hypervisor_xcall_flush_tlb_pending: /* 21 insns */
	/* %g5=ctx, %g1=nr, %g7=vaddrs[], %g2,%g3,%g4,g6=scratch */
602 603 604 605 606 607 608
	sllx		%g1, 3, %g1
	mov		%o0, %g2
	mov		%o1, %g3
	mov		%o2, %g4
1:	sub		%g1, (1 << 3), %g1
	ldx		[%g7 + %g1], %o0	/* ARG0: virtual address */
	mov		%g5, %o1		/* ARG1: mmu context */
609 610 611
	mov		HV_MMU_ALL, %o2		/* ARG2: flags */
	srlx		%o0, PAGE_SHIFT, %o0
	sllx		%o0, PAGE_SHIFT, %o0
612
	ta		HV_MMU_UNMAP_ADDR_TRAP
613 614 615
	mov		HV_MMU_UNMAP_ADDR_TRAP, %g6
	brnz,a,pn	%o0, __hypervisor_tlb_xcall_error
	 mov		%o0, %g5
616 617 618 619 620 621 622 623 624
	brnz,pt		%g1, 1b
	 nop
	mov		%g2, %o0
	mov		%g3, %o1
	mov		%g4, %o2
	membar		#Sync
	retry

	.globl		__hypervisor_xcall_flush_tlb_kernel_range
625 626
__hypervisor_xcall_flush_tlb_kernel_range: /* 25 insns */
	/* %g1=start, %g7=end, g2,g3,g4,g5,g6=scratch */
627 628 629 630 631 632 633 634 635
	sethi		%hi(PAGE_SIZE - 1), %g2
	or		%g2, %lo(PAGE_SIZE - 1), %g2
	andn		%g1, %g2, %g1
	andn		%g7, %g2, %g7
	sub		%g7, %g1, %g3
	add		%g2, 1, %g2
	sub		%g3, %g2, %g3
	mov		%o0, %g2
	mov		%o1, %g4
636
	mov		%o2, %g7
637 638 639 640
1:	add		%g1, %g3, %o0	/* ARG0: virtual address */
	mov		0, %o1		/* ARG1: mmu context */
	mov		HV_MMU_ALL, %o2	/* ARG2: flags */
	ta		HV_MMU_UNMAP_ADDR_TRAP
641 642 643
	mov		HV_MMU_UNMAP_ADDR_TRAP, %g6
	brnz,pn		%o0, __hypervisor_tlb_xcall_error
	 mov		%o0, %g5
644 645 646 647 648
	sethi		%hi(PAGE_SIZE), %o2
	brnz,pt		%g3, 1b
	 sub		%g3, %o2, %g3
	mov		%g2, %o0
	mov		%g4, %o1
649
	mov		%g7, %o2
650 651 652
	membar		#Sync
	retry

L
Linus Torvalds 已提交
653 654 655 656 657 658
	/* These just get rescheduled to PIL vectors. */
	.globl		xcall_call_function
xcall_call_function:
	wr		%g0, (1 << PIL_SMP_CALL_FUNC), %set_softint
	retry

659 660 661 662 663
	.globl		xcall_call_function_single
xcall_call_function_single:
	wr		%g0, (1 << PIL_SMP_CALL_FUNC_SNGL), %set_softint
	retry

L
Linus Torvalds 已提交
664 665 666 667 668 669 670 671 672 673
	.globl		xcall_receive_signal
xcall_receive_signal:
	wr		%g0, (1 << PIL_SMP_RECEIVE_SIGNAL), %set_softint
	retry

	.globl		xcall_capture
xcall_capture:
	wr		%g0, (1 << PIL_SMP_CAPTURE), %set_softint
	retry

674 675 676 677 678
	.globl		xcall_new_mmu_context_version
xcall_new_mmu_context_version:
	wr		%g0, (1 << PIL_SMP_CTX_NEW_VERSION), %set_softint
	retry

D
David S. Miller 已提交
679 680 681
#ifdef CONFIG_KGDB
	.globl		xcall_kgdb_capture
xcall_kgdb_capture:
682 683
	wr		%g0, (1 << PIL_KGDB_CAPTURE), %set_softint
	retry
D
David S. Miller 已提交
684 685
#endif

L
Linus Torvalds 已提交
686
#endif /* CONFIG_SMP */
687 688 689 690 691 692 693 694 695 696 697


	.globl		hypervisor_patch_cachetlbops
hypervisor_patch_cachetlbops:
	save		%sp, -128, %sp

	sethi		%hi(__flush_tlb_mm), %o0
	or		%o0, %lo(__flush_tlb_mm), %o0
	sethi		%hi(__hypervisor_flush_tlb_mm), %o1
	or		%o1, %lo(__hypervisor_flush_tlb_mm), %o1
	call		tlb_patch_one
698
	 mov		10, %o2
699 700 701 702 703 704

	sethi		%hi(__flush_tlb_pending), %o0
	or		%o0, %lo(__flush_tlb_pending), %o0
	sethi		%hi(__hypervisor_flush_tlb_pending), %o1
	or		%o1, %lo(__hypervisor_flush_tlb_pending), %o1
	call		tlb_patch_one
705
	 mov		16, %o2
706 707 708 709 710 711

	sethi		%hi(__flush_tlb_kernel_range), %o0
	or		%o0, %lo(__flush_tlb_kernel_range), %o0
	sethi		%hi(__hypervisor_flush_tlb_kernel_range), %o1
	or		%o1, %lo(__hypervisor_flush_tlb_kernel_range), %o1
	call		tlb_patch_one
712
	 mov		16, %o2
713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728

#ifdef DCACHE_ALIASING_POSSIBLE
	sethi		%hi(__flush_dcache_page), %o0
	or		%o0, %lo(__flush_dcache_page), %o0
	sethi		%hi(__hypervisor_flush_dcache_page), %o1
	or		%o1, %lo(__hypervisor_flush_dcache_page), %o1
	call		tlb_patch_one
	 mov		2, %o2
#endif /* DCACHE_ALIASING_POSSIBLE */

#ifdef CONFIG_SMP
	sethi		%hi(xcall_flush_tlb_mm), %o0
	or		%o0, %lo(xcall_flush_tlb_mm), %o0
	sethi		%hi(__hypervisor_xcall_flush_tlb_mm), %o1
	or		%o1, %lo(__hypervisor_xcall_flush_tlb_mm), %o1
	call		tlb_patch_one
729
	 mov		21, %o2
730 731 732 733 734 735

	sethi		%hi(xcall_flush_tlb_pending), %o0
	or		%o0, %lo(xcall_flush_tlb_pending), %o0
	sethi		%hi(__hypervisor_xcall_flush_tlb_pending), %o1
	or		%o1, %lo(__hypervisor_xcall_flush_tlb_pending), %o1
	call		tlb_patch_one
736
	 mov		21, %o2
737 738 739 740 741 742

	sethi		%hi(xcall_flush_tlb_kernel_range), %o0
	or		%o0, %lo(xcall_flush_tlb_kernel_range), %o0
	sethi		%hi(__hypervisor_xcall_flush_tlb_kernel_range), %o1
	or		%o1, %lo(__hypervisor_xcall_flush_tlb_kernel_range), %o1
	call		tlb_patch_one
743
	 mov		25, %o2
744 745 746 747
#endif /* CONFIG_SMP */

	ret
	 restore