xref: /titanic_51/usr/src/uts/sun4u/starcat/ml/drmach_asm.s (revision 07d06da50d310a325b457d6330165aebab1e0064)
103831d35Sstevel/*
203831d35Sstevel * CDDL HEADER START
303831d35Sstevel *
403831d35Sstevel * The contents of this file are subject to the terms of the
51e2e7a75Shuah * Common Development and Distribution License (the "License").
61e2e7a75Shuah * You may not use this file except in compliance with the License.
703831d35Sstevel *
803831d35Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
903831d35Sstevel * or http://www.opensolaris.org/os/licensing.
1003831d35Sstevel * See the License for the specific language governing permissions
1103831d35Sstevel * and limitations under the License.
1203831d35Sstevel *
1303831d35Sstevel * When distributing Covered Code, include this CDDL HEADER in each
1403831d35Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1503831d35Sstevel * If applicable, add the following below this CDDL HEADER, with the
1603831d35Sstevel * fields enclosed by brackets "[]" replaced with your own identifying
1703831d35Sstevel * information: Portions Copyright [yyyy] [name of copyright owner]
1803831d35Sstevel *
1903831d35Sstevel * CDDL HEADER END
2003831d35Sstevel */
2103831d35Sstevel/*
22*07d06da5SSurya Prakki * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2303831d35Sstevel * Use is subject to license terms.
2403831d35Sstevel */
2503831d35Sstevel
2603831d35Sstevel/*
2703831d35Sstevel * This file is through cpp before being used as
2803831d35Sstevel * an inline.  It contains support routines used
2903831d35Sstevel * only by DR.
3003831d35Sstevel */
3103831d35Sstevel
3203831d35Sstevel#if defined(lint)
3303831d35Sstevel#include <sys/types.h>
3403831d35Sstevel#else
3503831d35Sstevel#include "assym.h"
3603831d35Sstevel#endif /* lint */
3703831d35Sstevel
3803831d35Sstevel#include <sys/asm_linkage.h>
3903831d35Sstevel#include <sys/clock.h>
4003831d35Sstevel#include <sys/param.h>
4103831d35Sstevel#include <sys/privregs.h>
4203831d35Sstevel#include <sys/machasi.h>
4303831d35Sstevel#include <sys/mmu.h>
4403831d35Sstevel#include <sys/machthread.h>
4503831d35Sstevel#include <sys/pte.h>
4603831d35Sstevel#include <sys/stack.h>
4703831d35Sstevel#include <sys/vis.h>
4803831d35Sstevel#include <sys/cheetahregs.h>
4903831d35Sstevel#include <sys/cmpregs.h>
5003831d35Sstevel#include <sys/intreg.h>
5103831d35Sstevel#include <sys/cheetahasm.h>
5203831d35Sstevel
5303831d35Sstevel#if defined(lint)
5403831d35Sstevel
5503831d35Sstevel/*ARGSUSED*/
5603831d35Sstevelvoid
57*07d06da5SSurya Prakkidrmach_shutdown_asm(uint64_t estack, uint64_t flushaddr,
58*07d06da5SSurya Prakki    int size, int lsz, uint64_t physmem)
5903831d35Sstevel{}
6003831d35Sstevel
6103831d35Sstevel/*ARGSUSED*/
6203831d35Sstevelvoid
6303831d35Ssteveldrmach_rename(uint64_t *script, uint_t *err, uint64_t *id)
6403831d35Sstevel{}
6503831d35Sstevel
6603831d35Sstevelvoid
6703831d35Ssteveldrmach_rename_end(void)
6803831d35Sstevel{}
6903831d35Sstevel
7003831d35Sstevel/*ARGSUSED*/
7103831d35Sstevelvoid
7203831d35Ssteveldrmach_rename_wait(uint64_t not_used_0, uint64_t not_used_1)
7303831d35Sstevel{
7403831d35Sstevel}
7503831d35Sstevel
7603831d35Sstevel/*ARGSUSED*/
7703831d35Sstevelvoid
7803831d35Ssteveldrmach_rename_done(uint64_t not_used_0, uint64_t not_used_1)
7903831d35Sstevel{
8003831d35Sstevel}
8103831d35Sstevel
8203831d35Sstevel/*ARGSUSED*/
8303831d35Sstevelvoid
8403831d35Ssteveldrmach_rename_abort(uint64_t not_used_0, uint64_t not_used_1)
8503831d35Sstevel{
8603831d35Sstevel}
8703831d35Sstevel
8803831d35Sstevel/*ARGSUSED*/
8903831d35Ssteveluint64_t
90*07d06da5SSurya Prakkilddsafconfig(void)
9103831d35Sstevel{
9203831d35Sstevel	return (0x0ull);
9303831d35Sstevel}
9403831d35Sstevel
9503831d35Sstevel/* ARGSUSED */
9603831d35Ssteveluint32_t
9703831d35Ssteveldrmach_bc_bzero(void *addr, size_t size)
9803831d35Sstevel{
9903831d35Sstevel	return (0x0);
10003831d35Sstevel}
10103831d35Sstevel
10203831d35Sstevel#else /* lint */
10303831d35Sstevel
10403831d35Sstevel#define BUS_SYNC(reg1, reg2)					\
10503831d35Sstevel1:								;\
10603831d35Sstevel	ldx	[reg1], reg2					;\
10703831d35Sstevel	brz,pn	reg2, 2f					;\
10803831d35Sstevel	add	reg1, 8, reg1					;\
10903831d35Sstevel	ldxa	[reg2]ASI_MEM, %g0				;\
11003831d35Sstevel	ba,a	1b						;\
11103831d35Sstevel	nop							;\
11203831d35Sstevel2:
11303831d35Sstevel
11403831d35Sstevel#define LOAD_MB(cpuid, mb_data, reg1)				\
11503831d35Sstevel	set	drmach_xt_mb, reg1				;\
11603831d35Sstevel	ldx	[reg1], reg1					;\
11703831d35Sstevel	add	reg1, cpuid, reg1				;\
11803831d35Sstevel	ldub	[reg1], mb_data					;\
11903831d35Sstevel	stub	%g0, [reg1]
12003831d35Sstevel
12103831d35Sstevel#define LPA_MASK 0x7ff8
12203831d35Sstevel
12303831d35Sstevel#define SET_LPA(cmd, reg1, reg2)				\
12403831d35Sstevel	btst	0x80, cmd					;\
12503831d35Sstevel	bz	2f						;\
12603831d35Sstevel	nop							;\
12703831d35Sstevel	btst	0x40, cmd					;\
12803831d35Sstevel	bnz,a	1f						;\
12903831d35Sstevel	mov	%g0, cmd					;\
13003831d35Sstevel	and	cmd, 0x1f, cmd					;\
13103831d35Sstevel	sllx	cmd, 3, reg1					;\
13203831d35Sstevel	add	cmd, 1, cmd					;\
13303831d35Sstevel	sllx	cmd, 9, cmd					;\
13403831d35Sstevel	or	cmd, reg1, cmd					;\
13503831d35Sstevel1:								;\
13603831d35Sstevel	set	LPA_MASK, reg2					;\
13703831d35Sstevel	ldxa	[%g0]ASI_SAFARI_CONFIG, reg1			;\
13803831d35Sstevel	and	cmd, reg2, cmd					;\
13903831d35Sstevel	andn	reg1, reg2, reg1				;\
14003831d35Sstevel	or	reg1, cmd, reg1					;\
14103831d35Sstevel	stxa	reg1, [%g0]ASI_SAFARI_CONFIG			;\
14203831d35Sstevel	membar	#Sync						;\
14303831d35Sstevel2:								;\
14403831d35Sstevel
14503831d35Sstevel#define SET_NULL_LPA(reg1, reg2)				\
14603831d35Sstevel	set	LPA_MASK, reg2					;\
14703831d35Sstevel	ldxa	[%g0]ASI_SAFARI_CONFIG, reg1			;\
14803831d35Sstevel	andn	reg1, reg2, reg1				;\
14903831d35Sstevel	stxa	reg1, [%g0]ASI_SAFARI_CONFIG			;\
15003831d35Sstevel	membar	#Sync						;\
15103831d35Sstevel
15203831d35Sstevel	! ATOMIC_ADD_LONG
15303831d35Sstevel	! This code is run at TL > 0, being exec'd via a cross trap.
15403831d35Sstevel	! While running at trap level > 0, all memory accesses are
15503831d35Sstevel	! performed using NUCLEUS context, which is always 0.
15603831d35Sstevel	! Since the cross trap handler does not force PRIMARY context
15703831d35Sstevel	! to be zero, the following casxa instruction must specify
15803831d35Sstevel	! NUCLEUS ASI.
15903831d35Sstevel	! This ASI must be specified explicitly (via casxa), rather
16003831d35Sstevel	! than using casx. This is because of the fact that the
16103831d35Sstevel	! default casx specifies ASI_PRIMARY, which if non-zero, can
16203831d35Sstevel	! prevent the cpu from translating the address, leading to panic
16303831d35Sstevel	! on bad trap following repetitive dtlb misses.  This behavior
16403831d35Sstevel	! was encountered on MCPUs when using casx instruction.
16503831d35Sstevel#define ATOMIC_ADD_LONG(label, simm, reg1, reg2, reg3)		\
16603831d35Sstevel	set	label, reg1					;\
16703831d35Sstevel	ldx	[reg1], reg2					;\
16803831d35Sstevel1:								;\
16903831d35Sstevel	add	reg2, simm, reg3				;\
17003831d35Sstevel	casxa	[reg1]ASI_N, reg2, reg3				;\
17103831d35Sstevel	cmp	reg2, reg3					;\
17203831d35Sstevel	bne,a,pn %xcc, 1b					;\
17303831d35Sstevel	ldx	[reg1], reg2
17403831d35Sstevel
17503831d35Sstevel#define HERE(reg1, simm, reg2)					\
17603831d35Sstevel	rdpr	%tick, reg2					;\
17703831d35Sstevel	stx	reg2, [reg1 + simm]
17803831d35Sstevel
17903831d35Sstevel	!
18003831d35Sstevel	! Returns processor icache size and linesize in reg1 and
18103831d35Sstevel	! reg2, respectively.
18203831d35Sstevel	!
18303831d35Sstevel	! Panther has a larger icache compared to Cheetahplus and
18403831d35Sstevel	! Jaguar.
18503831d35Sstevel	!
18603831d35Sstevel#define	GET_ICACHE_PARAMS(reg1, reg2)				\
18703831d35Sstevel	GET_CPU_IMPL(reg1)					;\
18803831d35Sstevel	cmp	reg1, PANTHER_IMPL				;\
18903831d35Sstevel	bne	%xcc, 1f					;\
19003831d35Sstevel	  nop							;\
19103831d35Sstevel	set	PN_ICACHE_SIZE, reg1				;\
19203831d35Sstevel	set	PN_ICACHE_LSIZE, reg2				;\
19303831d35Sstevel	ba	2f						;\
19403831d35Sstevel	  nop							;\
19503831d35Sstevel1:								;\
19603831d35Sstevel	set	CH_ICACHE_SIZE, reg1				;\
19703831d35Sstevel	set	CH_ICACHE_LSIZE, reg2				;\
19803831d35Sstevel2:
19903831d35Sstevel
20003831d35Sstevel#define	DRMACH_MCU_IDLE_READS	3
20103831d35Sstevel
20203831d35Sstevel	! Macro to check if a Panther MC is idle.  The EMU Activity
20303831d35Sstevel	! Status register is first read to clear the MCU status bit.
20403831d35Sstevel	! The MCU status is then checked DRMACH_MCU_IDLE_READS times
20503831d35Sstevel	! to verify the MCU is indeed idle.  A single non-idle status
20603831d35Sstevel	! will fail the idle check.  This could be made more lenient
20703831d35Sstevel	! by adding a retry loop.
20803831d35Sstevel	!	addr:	Panther EMU Activity Status register read address.
20903831d35Sstevel	!		Assumed to be 0x18 for local ASI access or else
21003831d35Sstevel	!		FIREPLANE_ADDRESS_REG + 0x400050 for PIO access.
21103831d35Sstevel	!		0 is returned in this register if MCU is idle and
21203831d35Sstevel	!		queues are empty.  Otherwise, -1 is returned in this
21303831d35Sstevel	!		register.
21403831d35Sstevel	!	asi:	Immediate asi value.  Assumed to be ASI_SAFARI_CONFIG
21503831d35Sstevel	!		for local ASI or ASI_IO for PIO access.
21603831d35Sstevel	!	scr1:	Scratch
21703831d35Sstevel	!	scr2:	Scratch
21803831d35Sstevel	!
21903831d35Sstevel#define	CHECK_MCU_IDLE(addr, asi, scr1, scr2)			\
22003831d35Sstevel	ldxa	[addr]asi, %g0					;\
22103831d35Sstevel	ba	1f						;\
22203831d35Sstevel	  clr	scr2						;\
22303831d35Sstevel0:								;\
22403831d35Sstevel	btst	MCU_ACT_STATUS, scr1				;\
22503831d35Sstevel	bne,a	2f						;\
22603831d35Sstevel	  sub	%g0, 1, addr					;\
22703831d35Sstevel	inc	scr2						;\
22803831d35Sstevel1:								;\
22903831d35Sstevel	cmp	scr2, DRMACH_MCU_IDLE_READS			;\
23003831d35Sstevel	ble,a	0b						;\
23103831d35Sstevel	  ldxa    [addr]asi, scr1				;\
23203831d35Sstevel	clr	addr						;\
23303831d35Sstevel2:
23403831d35Sstevel
23503831d35Sstevel	! drmach_shutdown_asm
23603831d35Sstevel	!
23703831d35Sstevel	! inputs:
23803831d35Sstevel	!	%o0 = stack pointer
23903831d35Sstevel	!	%o1 = ecache flush address (ignored if cheetah+ processor)
24003831d35Sstevel	!	%o2 = ecache size
24103831d35Sstevel	!	%o3 = ecache line size
24203831d35Sstevel	!	%o4 = phys addr of byte to clear when finished
24303831d35Sstevel	!
24403831d35Sstevel	! output:
24503831d35Sstevel	!	Stores a zero at [%o4]ASI_MEM when the processor
24603831d35Sstevel	!	is ready to be removed from domain coherency.
24703831d35Sstevel	!
24803831d35Sstevel	ENTRY_NP(drmach_shutdown_asm)
24903831d35Sstevel	membar	#LoadStore		! parsley.
25003831d35Sstevel
25103831d35Sstevel	! Calculate pointer to data area. Determine size of
25203831d35Sstevel	! drmach_shutdown_asm, add to base address and align
25303831d35Sstevel	! to next 16 byte boundary. Leave result in %g6.
25403831d35Sstevel	set	drmach_shutdown_asm_end, %g6
25503831d35Sstevel	set	drmach_shutdown_asm, %g1
25603831d35Sstevel	set	drmach_cpu_sram_va, %g2
25703831d35Sstevel	ldx	[%g2], %g2
25803831d35Sstevel	sub	%g6, %g1, %g6
25903831d35Sstevel	add	%g6, %g2, %g6
26003831d35Sstevel	add	%g6, 15, %g6
26103831d35Sstevel	andn	%g6, 15, %g6
26203831d35Sstevel
26303831d35Sstevel	! Save parameters
26403831d35Sstevel	stx	%o0, [%g6 + 0]		! save stack pointer
26503831d35Sstevel	stx	%o1, [%g6 + 24]		! save E$ flush PA
26603831d35Sstevel	st	%o2, [%g6 + 32]		! save E$ size
26703831d35Sstevel	st	%o3, [%g6 + 36]		! save E$ linesize
26803831d35Sstevel	stx	%o4, [%g6 + 40]		! save phys addr of signal byte
26903831d35Sstevel
27003831d35Sstevel	set	dcache_size, %g1
27103831d35Sstevel	ld	[%g1], %g1
27203831d35Sstevel	st	%g1, [%g6 + 8]		! save dcache_size
27303831d35Sstevel	set	dcache_linesize, %g1
27403831d35Sstevel	ld	[%g1], %g1
27503831d35Sstevel	st	%g1, [%g6 + 12]		! save dcache_linesize
27603831d35Sstevel
27703831d35Sstevel	GET_ICACHE_PARAMS(%g1, %g2)
27803831d35Sstevel	st	%g1, [%g6 + 16]		! save icache_size
27903831d35Sstevel	st	%g2, [%g6 + 20]		! save icache_linesize
28003831d35Sstevel
28103831d35Sstevel	! Flushes all active windows except the current one.
28203831d35Sstevel	! Can cause spill traps to occur.
28303831d35Sstevel	flushw
28403831d35Sstevel
28503831d35Sstevel	! Make sure all asynchronous processing is complete.
28603831d35Sstevel	! Note: has no implications on pending bus transactions.
28703831d35Sstevel	membar	#Sync
28803831d35Sstevel
28903831d35Sstevel	! Move stack. Algorithm copied from t0stacktop setup of
29003831d35Sstevel	! %sp in sun4u/ml/locore.s
29103831d35Sstevel	! Replaces SWITCH_STACK() macro used in Starfire DR.
29203831d35Sstevel	ldx	[%g6 + 0], %g1
29303831d35Sstevel	sub	%g1, SA(KFPUSIZE+GSR_SIZE), %g2
29403831d35Sstevel 	and	%g2, 0x3f, %g3
29503831d35Sstevel 	sub	%g2, %g3, %o2
29603831d35Sstevel 	sub	%o2, SA(MPCBSIZE) + STACK_BIAS, %sp
29703831d35Sstevel	stx	%sp, [%g6 + 48]		! for debug
29803831d35Sstevel
29903831d35Sstevel	HERE(%g6, 128, %g1)		! initialization complete (for debug)
30003831d35Sstevel
30103831d35Sstevel	! Panther needs to flush the L2 cache before the L3
30203831d35Sstevel	! cache is flushed by the ecache flushall macro.
30303831d35Sstevel	PN_L2_FLUSHALL(%g1, %g2, %g3)
30403831d35Sstevel
30503831d35Sstevel	! Flush E$. The purpose of this flush is to rid the E$ of
30603831d35Sstevel	! lines in states O or Os. Implicitly flushes W$.
30703831d35Sstevel	ldx	[%g6 + 24], %g1		! *ecache_flushaddr
30803831d35Sstevel	ld	[%g6 + 32], %g2		! ecache_size
30903831d35Sstevel	ld	[%g6 + 36], %g3		! ecache_linesize
31003831d35Sstevel	ECACHE_FLUSHALL(%g2, %g3, %g1, %g4)
31103831d35Sstevel
31203831d35Sstevel	! Since the bus sync list read below does not guarantee
31303831d35Sstevel	! transaction completion on Panther domains, as an
31403831d35Sstevel	! optimization Panther skips the read and subsequent
31503831d35Sstevel	! E$ flush.
31603831d35Sstevel	GET_CPU_IMPL(%g1)
31703831d35Sstevel	cmp	%g1, PANTHER_IMPL
31803831d35Sstevel	be	%xcc, drmach_shutdown_ecache_flushed
31903831d35Sstevel	  nop
32003831d35Sstevel
32103831d35Sstevel	!
32203831d35Sstevel	! Ensure all outstanding writebacks have retired.  Following this
32303831d35Sstevel	! sync, all writes must be strictly managed.
32403831d35Sstevel	!
32503831d35Sstevel	set	drmach_bus_sync_list, %g1
32603831d35Sstevel	BUS_SYNC(%g1, %g2)
32703831d35Sstevel
32803831d35Sstevel	! Flush E$ again to victimize references to drmach_bus_sync_list.
32903831d35Sstevel	ldx     [%g6 + 24], %g1         ! *ecache_flushaddr
33003831d35Sstevel	ld	[%g6 + 32], %g2		! ecache_size
33103831d35Sstevel	ld	[%g6 + 36], %g3		! ecache_linesize
33203831d35Sstevel	ECACHE_FLUSHALL(%g2, %g3, %g1, %g4)
33303831d35Sstevel
33403831d35Ssteveldrmach_shutdown_ecache_flushed:
33503831d35Sstevel
33603831d35Sstevel	ld	[%g6 + 8], %g1		! flush dcache
33703831d35Sstevel	ld	[%g6 + 12], %g2
33803831d35Sstevel	CH_DCACHE_FLUSHALL(%g1, %g2, %g3)
33903831d35Sstevel
34003831d35Sstevel	ld	[%g6 + 16], %g1		! flush icache
34103831d35Sstevel	ld	[%g6 + 20], %g2
34203831d35Sstevel	CH_ICACHE_FLUSHALL(%g1, %g2, %g3, %g4)
34303831d35Sstevel
34403831d35Sstevel	PCACHE_FLUSHALL(%g1, %g2, %g3) ! flush pcache (no parameters)
34503831d35Sstevel
34603831d35Sstevel	!
34703831d35Sstevel	! Flush all unlocked dtlb and itlb entries.
34803831d35Sstevel	! Replaces TLB_FLUSH_UNLOCKED macro used in Starfire DR.
34903831d35Sstevel	!
35003831d35Sstevel	sethi	%hi(FLUSH_ADDR), %g1
35103831d35Sstevel	set	DEMAP_ALL_TYPE, %g2
35203831d35Sstevel	stxa	%g0, [%g2]ASI_DTLB_DEMAP
35303831d35Sstevel	stxa	%g0, [%g2]ASI_ITLB_DEMAP
35403831d35Sstevel	flush	%g1
35503831d35Sstevel
35603831d35Sstevel	!
35703831d35Sstevel	! Zero LPA by clearing CBASE and CBND. Following
35803831d35Sstevel	! this, all transactions to cachable address space
35903831d35Sstevel	! will be of the remote flavor.
36003831d35Sstevel	!
36103831d35Sstevel	SET_NULL_LPA(%g1, %g2)
36203831d35Sstevel
36303831d35Sstevel	HERE(%g6, 136, %g1)		! preparation complete (for debug)
36403831d35Sstevel
36503831d35Sstevel	!
36603831d35Sstevel	! Clear byte to signal finished.
36703831d35Sstevel	! NOTE: This store will allocate in the E$. It is
36803831d35Sstevel	! vitally important that this line is demoted to
36903831d35Sstevel	! state I before removing this processor from the
37003831d35Sstevel	! coherency.  The demotion is ensured by a synchronous
37103831d35Sstevel	! "steal back" that takes place in drmach_cpu_poweroff.
37203831d35Sstevel	ldx	[%g6 + 40], %g1
37303831d35Sstevel	stba	%g0, [%g1]ASI_MEM
37403831d35Sstevel5:
37503831d35Sstevel	HERE(%g6, 144, %g1)		! spin indicator (for debug)
37603831d35Sstevel	ba	5b
37703831d35Sstevel	  nop
37803831d35Sstevel
37903831d35Sstevel	.asciz	"drmach_shutdown_asm"		! for debug
38003831d35Sstevel	.align	4
38103831d35Sstevel	.global	drmach_shutdown_asm_end
38203831d35Ssteveldrmach_shutdown_asm_end:
38303831d35Sstevel	SET_SIZE(drmach_shutdown_asm)
38403831d35Sstevel
38503831d35Sstevel
38603831d35Sstevel	! lddsafconfig
38703831d35Sstevel	!
38803831d35Sstevel	! input:
38903831d35Sstevel	!	nothing
39003831d35Sstevel	!
39103831d35Sstevel	! output:
39203831d35Sstevel	!	%o0	content of this processor's SCR
39303831d35Sstevel	!
39403831d35Sstevel	!	Returns current value of this processor's Safari
39503831d35Sstevel	!	Configuration Register.
39603831d35Sstevel	!
39703831d35Sstevel	ENTRY(lddsafconfig)
39803831d35Sstevel        retl
39903831d35Sstevel        ldxa    [%g0]ASI_SAFARI_CONFIG, %o0
40003831d35Sstevel        SET_SIZE(lddsafconfig)
40103831d35Sstevel
40203831d35Sstevel	! drmach_rename
40303831d35Sstevel	!
40403831d35Sstevel	! input:
40503831d35Sstevel	!	%o0	pointer to register address/value compound list
40603831d35Sstevel	!	%o1	address for setting error code if rename did not
40703831d35Sstevel	!		complete.  Unmodified if no error.
40803831d35Sstevel	!	%o2	address for returning opaque memory controller id
40903831d35Sstevel	!		in case of error.  Unmodified if no error.
41003831d35Sstevel	!	Global	drmach_xt_mb[cpuid] is expected to be the new LPA.
41103831d35Sstevel	!
41203831d35Sstevel	! output:
41303831d35Sstevel	!	[%o1] =	1 if failed to idle memory controller, otherwise unmodified.
41403831d35Sstevel	!	[%o2] = id of failed memory controller, otherwise unmodified.
41503831d35Sstevel	!
41603831d35Sstevel	! Perform HW register reprogramming. This is the "rename" step for
41703831d35Sstevel	! the copy-rename process.  drmach_rename is copied to a cpu's sram
41803831d35Sstevel	! followed by register address/value pairs -- the text and data are
41903831d35Sstevel	! sourced from the sram while drmach_rename is executed.
42003831d35Sstevel	!
42103831d35Sstevel	! The parameter is assumed to point to a concatenation of six
42203831d35Sstevel	! zero-terminated lists located in non-cachable storage. The assumed
42303831d35Sstevel	! format (and purpose) of each list is as follows:
42403831d35Sstevel	!
42503831d35Sstevel	!	1) a copy of drmach_bus_sync_list. A list of PA for each
42603831d35Sstevel	!	   active memory bank in the domain. Used to infer the
42703831d35Sstevel	!	   the completion of all pending coherent transactions
42803831d35Sstevel	!	   initiated by this processor. Assumes MC work queue
42903831d35Sstevel	!	   does not implement read bypass. This is true of Cheetah,
43003831d35Sstevel	!	   Cheetah+, and Jaguar processors.  Panther does support
43103831d35Sstevel	!	   read bypass, so for Panther MCs with read-bypass-write
43203831d35Sstevel	!	   enabled, the read is issued but it does not guarantee
43303831d35Sstevel	!	   completion of outstanding writes in the MC queue.
43403831d35Sstevel	!	2) address/id pair for the local Panther EMU Activity Status
43503831d35Sstevel	!	   Register of this processor.  The register address is assumed
43603831d35Sstevel	!	   to be a VA which is polled via ASI_SAFARI_CONFIG until the
43703831d35Sstevel	!	   MC queues are empty.  The id is an opaque identifier which
43803831d35Sstevel	!	   must be returned along with an error code if the MCU status
43903831d35Sstevel	!	   does not go idle.  See the parameter description above.
44003831d35Sstevel	!	   This section will be empty if this processor is not a Panther.
44103831d35Sstevel	!	   Both the address and id are assumed to be 64 bit values.
44203831d35Sstevel	!	3) address/id pairs for non-local Panther EMU Activity Status
44303831d35Sstevel	!	   Registers on other source and target processors.  The register
44403831d35Sstevel	!	   address is assumed to be a PIO address which is polled via
44503831d35Sstevel	!	   ASI_IO to drain/idle the MCs on other Panther procs.  The
44603831d35Sstevel	!	   id is an opaque identifier which must be returned along with
44703831d35Sstevel	!	   an error code if a MC fails to go idle.  This section will
44803831d35Sstevel	!	   empty if there are no non-local Panther processors on the
44903831d35Sstevel	!	   source and target expanders.  Both the address and id are
45003831d35Sstevel	!	   assumed to be 64 bit values.
45103831d35Sstevel	!	4) address/value pairs for the Memory Address Decoder
45203831d35Sstevel	!	   register of this processor. The register address is
45303831d35Sstevel	!	   assumed to be a VA within ASM_MC_DECODE space. The
45403831d35Sstevel	!	   address and value elements are assumed to 64 bit values.
45503831d35Sstevel	!	5) address/value pairs for any 64 bit register accessible
45603831d35Sstevel	!	   via ASI_IO. The address and value fields are assumed to
45703831d35Sstevel	!	   be 64 bit values.
45803831d35Sstevel	!	   This list is typically used for reprogramming the Memory
45903831d35Sstevel	!	   Address Decoder Register of other cpus and for reprogram-
46003831d35Sstevel	!	   ming the Safari Configuration Register of I/O controllers.
46103831d35Sstevel	!	6) address/value pairs for any 32 bit register accessible
46203831d35Sstevel	!	   via ASI_IO. The address element is assumed to be a 64 bit
46303831d35Sstevel	!	   value. The value element is assumed to be a 64 bit word
46403831d35Sstevel	!	   containing a 32 bit value in the lower half.
46503831d35Sstevel	!	   This list typically contains address/value pairs for
46603831d35Sstevel	!	   AXQ CASM tables.
46703831d35Sstevel	!
46803831d35Sstevel	ENTRY_NP(drmach_rename)
46903831d35Sstevel
47003831d35Sstevel	mov	%o1, %o4		! save error code address
47103831d35Sstevel	mov	%o2, %o5		! save error id address
47203831d35Sstevel
47303831d35Sstevel	BUS_SYNC(%o0, %o1)		! run section 1
47403831d35Sstevel
47503831d35Sstevel	SET_NULL_LPA(%o1, %o2)		! prep for cachable transactions
47603831d35Sstevel					! after rename completes.
47703831d35Sstevel					! e.g.: the load_mb that occurs below
47803831d35Sstevel3:
47903831d35Sstevel	ldx	[%o0], %o1		! run section 2
48003831d35Sstevel	brz,a,pn %o1, 4f
48103831d35Sstevel	add	%o0, 8, %o0		! skip section 2 terminator
48203831d35Sstevel	CHECK_MCU_IDLE(%o1, ASI_SAFARI_CONFIG, %o2, %o3)
48303831d35Sstevel	cmp	%o1, 0			! idled?
48403831d35Sstevel	be,a	3b			! ok, advance
48503831d35Sstevel	  add	%o0, 16, %o0
48603831d35Sstevel	mov	1, %o1			! not idle, bailout
48703831d35Sstevel	stw	%o1, [%o4]		! set MC idle error code
48803831d35Sstevel	ldx	[%o0 + 8], %o1
48903831d35Sstevel	stx	%o1, [%o5]		! set MC idle error id
49003831d35Sstevel	retl
49103831d35Sstevel	  nop
49203831d35Sstevel4:
49303831d35Sstevel	ldx	[%o0], %o1		! run section 3
49403831d35Sstevel	brz,a,pn %o1, 5f
49503831d35Sstevel	add	%o0, 8, %o0		! skip section 3 terminator
49603831d35Sstevel	CHECK_MCU_IDLE(%o1, ASI_IO, %o2, %o3)
49703831d35Sstevel	cmp	%o1, 0			! idled?
49803831d35Sstevel	be,a	4b			! ok, advance
49903831d35Sstevel	  add	%o0, 16, %o0
50003831d35Sstevel	mov	1, %o1			! not idle, bailout
50103831d35Sstevel	stw	%o1, [%o4]		! set MC idle error code
50203831d35Sstevel	ldx	[%o0 + 8], %o1
50303831d35Sstevel	stx	%o1, [%o5]		! set MC idle error id
50403831d35Sstevel	retl
50503831d35Sstevel	  nop
50603831d35Sstevel5:
50703831d35Sstevel	ldx	[%o0], %o1		! run section 4
50803831d35Sstevel	brz,a,pn %o1, 6f
50903831d35Sstevel	add	%o0, 8, %o0		! skip section 4 terminator
51003831d35Sstevel	ldx	[%o0 + 8], %o2
51103831d35Sstevel	stxa	%o2, [%o1]ASI_MC_DECODE
51203831d35Sstevel	membar	#Sync
51303831d35Sstevel	ldxa	[%o1]ASI_MC_DECODE, %g0	! read back to insure written
51403831d35Sstevel	b	5b
51503831d35Sstevel	add	%o0, 16, %o0
51603831d35Sstevel6:
51703831d35Sstevel	ldx	[%o0], %o1		! run section 5
51803831d35Sstevel	brz,a,pn %o1, 7f
51903831d35Sstevel	add	%o0, 8, %o0		! skip section 5 terminator
52003831d35Sstevel	ldx	[%o0 + 8], %o2
52103831d35Sstevel	stxa	%o2, [%o1]ASI_IO
52203831d35Sstevel	ldxa	[%o1]ASI_IO, %g0	! read back to insure written
52303831d35Sstevel	b	6b
52403831d35Sstevel	add	%o0, 16, %o0
52503831d35Sstevel7:
52603831d35Sstevel	ldx	[%o0], %o1		! run section 6
52703831d35Sstevel	brz,a,pn %o1, 8f
52803831d35Sstevel	nop
52903831d35Sstevel	ldx	[%o0 + 8], %o2
53003831d35Sstevel	stwa	%o2, [%o1]ASI_IO
53103831d35Sstevel	lduwa	[%o1]ASI_IO, %g0	! read back to insure written
53203831d35Sstevel	b	7b
53303831d35Sstevel	add	%o0, 16, %o0
53403831d35Sstevel8:
53503831d35Sstevel	CPU_INDEX(%o0, %o1)
53603831d35Sstevel	LOAD_MB(%o0, %o1, %o2)
53703831d35Sstevel	SET_LPA(%o1, %o0, %o2)
53803831d35Sstevel
53903831d35Sstevel	retl
54003831d35Sstevel	nop
54103831d35Sstevel
54203831d35Sstevel	.asciz	"drmach_rename"		! for debug
54303831d35Sstevel	.align	4
54403831d35Sstevel	SET_SIZE(drmach_rename)
54503831d35Sstevel
54603831d35Sstevel	.global drmach_rename_end
54703831d35Ssteveldrmach_rename_end:
54803831d35Sstevel
54903831d35Sstevel
55003831d35Sstevel	! drmach_rename_wait
55103831d35Sstevel	!
55203831d35Sstevel	! input:
55303831d35Sstevel	!	nothing
55403831d35Sstevel	!
55503831d35Sstevel	! output:
55603831d35Sstevel	!	nothing
55703831d35Sstevel	!
55803831d35Sstevel	! drmach_rename_wait is a cross-trap function used to move a
55903831d35Sstevel	! cpu's execution out of coherent space while a copy-rename
56003831d35Sstevel	! operation is in progress.
56103831d35Sstevel	!
56203831d35Sstevel	! In each CPU SRAM exists an area (16KB on Cheetah+ boards,
56303831d35Sstevel	! 32KB on Jaguar/Panther boards) reserved for DR. This area is
56403831d35Sstevel	! logically divided by DR into 8KB pages, one page per CPU (or
56503831d35Sstevel	! core) in a port pair. (Two Safari ports share HW resources on
56603831d35Sstevel	! a CPU/MEM board. These are referred to as a port pair.)
56703831d35Sstevel	!
56803831d35Sstevel	! This routine begins by mapping the appropriate SRAM page,
56903831d35Sstevel	! transferring the machine code (between the labels
57003831d35Sstevel	! drmach_rename_wait_asm and drmach_rename_wait_asm_end), then
57103831d35Sstevel	! jumping to SRAM.  After returning from SRAM, the page is
57203831d35Sstevel	! demapped before the cross-call is exited (sic).
57303831d35Sstevel	!
57403831d35Sstevel	! The machine code flushes all caches, waits for a special
57503831d35Sstevel	! interrupt vector, then updates the processor's LPA and
57603831d35Sstevel	! resynchronizes caches with the new home memory.
57703831d35Sstevel	!
57803831d35Sstevel	! The special interrupt vector is assumed to be a cross-call to
57903831d35Sstevel	! drmach_rename_done sent by the master processor upon completing
58003831d35Sstevel	! the copy-rename operation. The interrupt is received and discarded;
58103831d35Sstevel	! The cross-call to drmach_rename_done is never executed.  Instead
58203831d35Sstevel	! the Interrupt Receive Status Register is employed, temporarily,
58303831d35Sstevel	! as a semaphore. This avoids unwanted bus traffic during the critical
58403831d35Sstevel	! rename operation.
58503831d35Sstevel	!
58603831d35Sstevel	ENTRY_NP(drmach_rename_wait)
58703831d35Sstevel
58803831d35Sstevel	CPU_INDEX(%g5, %g1)		! put cpuid in %g5
58903831d35Sstevel
59003831d35Sstevel	!
59103831d35Sstevel	! sfmmu_dtlb_ld(drmach_cpu_sram_va,
59203831d35Sstevel	!	KCONTEXT, drmach_cpu_sram_tte[cpuid]);
59303831d35Sstevel	! sfmmu_itlb_ld(drmach_cpu_sram_va,
59403831d35Sstevel	!	KCONTEXT, drmach_cpu_sram_tte[cpuid]);
59503831d35Sstevel	!
59603831d35Sstevel	set	drmach_cpu_sram_tte, %g1
59703831d35Sstevel	sllx	%g5, 3, %g2
59803831d35Sstevel	ldx	[%g1 + %g2], %g3
59903831d35Sstevel	set	drmach_cpu_sram_va, %g1
60003831d35Sstevel	ldx	[%g1], %g1
60103831d35Sstevel	or	%g1, KCONTEXT, %g2	! preserve %g1
60203831d35Sstevel	set	MMU_TAG_ACCESS, %g4
6031e2e7a75Shuah	set	cpu_impl_dual_pgsz, %g6
6041e2e7a75Shuah	ld      [%g6], %g6
60503831d35Sstevel	brz	%g6, 1f
60603831d35Sstevel	  nop
6071e2e7a75Shuah
6081e2e7a75Shuah	sethi	%hi(ksfmmup), %g6
6091e2e7a75Shuah	ldx	[%g6 + %lo(ksfmmup)], %g6
6101e2e7a75Shuah	ldub    [%g6 + SFMMU_CEXT], %g6
61103831d35Sstevel        sll     %g6, TAGACCEXT_SHIFT, %g6
6121e2e7a75Shuah
61303831d35Sstevel	set	MMU_TAG_ACCESS_EXT, %g7
61403831d35Sstevel	stxa	%g6, [%g7]ASI_DMMU
61503831d35Sstevel1:
61603831d35Sstevel	stxa	%g2, [%g4]ASI_DMMU
61703831d35Sstevel	stxa    %g3, [%g0]ASI_DTLB_IN
61803831d35Sstevel	membar	#Sync
61903831d35Sstevel	sethi	%hi(FLUSH_ADDR), %g6
62003831d35Sstevel	stxa	%g2, [%g4]ASI_IMMU
62103831d35Sstevel	stxa    %g3, [%g0]ASI_ITLB_IN
62203831d35Sstevel	flush	%g6
62303831d35Sstevel
62403831d35Sstevel	!
62503831d35Sstevel	! copy drmach_rename_wait_asm block to SRAM. Preserve entry
62603831d35Sstevel	! point in %g1. After the code has been copied, align %g6
62703831d35Sstevel	! (the destination pointer) to the next highest 16 byte
62803831d35Sstevel	! boundary. This will define the start of the data area.
62903831d35Sstevel	!
63003831d35Sstevel	mov	%g1, %g6
63103831d35Sstevel	set	drmach_rename_wait_asm, %g2
63203831d35Sstevel	set	drmach_rename_wait_asm_end, %g3
63303831d35Sstevel0:
63403831d35Sstevel	lduw	[%g2], %g4		! do copy
63503831d35Sstevel	stw	%g4, [%g6]
63603831d35Sstevel	add	%g2, 4, %g2
63703831d35Sstevel	cmp	%g2, %g3
63803831d35Sstevel	bne	0b
63903831d35Sstevel	add	%g6, 4, %g6
64003831d35Sstevel
64103831d35Sstevel	add	%g6, 15, %g6		! locate data area on next 16 byte
64203831d35Sstevel	andn	%g6, 15, %g6		! boundary following text
64303831d35Sstevel					! WARNING: no bounds checking
64403831d35Sstevel
64503831d35Sstevel	jmpl	%g1, %g7		! jump to code in cpu sram
64603831d35Sstevel	nop
64703831d35Sstevel
64803831d35Sstevel	set	drmach_cpu_sram_va, %g1	! vtab_flushpage_tl1(drmach_cpu_sram_va,
64903831d35Sstevel	ldx	[%g1], %g1		! 	KCONTEXT);
65003831d35Sstevel	set	KCONTEXT, %g2
65103831d35Sstevel	set	MMU_PCONTEXT, %g4
65203831d35Sstevel	or	%g1, DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %g1
65303831d35Sstevel	ldxa	[%g4]ASI_DMMU, %g5	/* rd old ctxnum */
65403831d35Sstevel	stxa	%g2, [%g4]ASI_DMMU	/* wr new ctxum */
65503831d35Sstevel	stxa	%g0, [%g1]ASI_DTLB_DEMAP
65603831d35Sstevel	stxa	%g0, [%g1]ASI_ITLB_DEMAP
65703831d35Sstevel	stxa	%g5, [%g4]ASI_DMMU	/* restore old ctxnum */
65803831d35Sstevel
65903831d35Sstevel	retry
66003831d35Sstevel
66103831d35Ssteveldrmach_rename_wait_asm:
66203831d35Sstevel	! the following code is copied to a cpu's sram and executed
66303831d35Sstevel	! from there.
66403831d35Sstevel	! Input:
66503831d35Sstevel	!	%g5 is cpuid
66603831d35Sstevel	!	%g6 is data area (follows text)
66703831d35Sstevel	!	%g7 is link address back to caller
66803831d35Sstevel	!
66903831d35Sstevel	st	%g5, [%g6 + 4]		! save cpuid (for debug)
67003831d35Sstevel
67103831d35Sstevel	set	dcache_size, %g1
67203831d35Sstevel	ld	[%g1], %g1
67303831d35Sstevel	st	%g1, [%g6 + 8]		! save dcache_size
67403831d35Sstevel	set	dcache_linesize, %g1
67503831d35Sstevel	ld	[%g1], %g1
67603831d35Sstevel	st	%g1, [%g6 + 12]		! save dcache_linesize
67703831d35Sstevel
67803831d35Sstevel	GET_ICACHE_PARAMS(%g1, %g2)
67903831d35Sstevel	st	%g1, [%g6 + 16]		! save icache_size
68003831d35Sstevel	st	%g2, [%g6 + 20]		! save icache_linesize
68103831d35Sstevel
68203831d35Sstevel	set	drmach_iocage_paddr, %g1
68303831d35Sstevel	ldx	[%g1], %g1
68403831d35Sstevel	stx	%g1, [%g6 + 24]		! save *ecache_flushadr
68503831d35Sstevel
68603831d35Sstevel	mulx	%g5, CPU_NODE_SIZE, %g1	! %g4 = &cpunodes[cpuid]
68703831d35Sstevel	set	cpunodes, %g4
68803831d35Sstevel	add	%g4, %g1, %g4
68903831d35Sstevel	ld	[%g4 + ECACHE_SIZE], %g1
69003831d35Sstevel	st	%g1, [%g6 + 32]		! save ecache_size
69103831d35Sstevel	ld	[%g4 + ECACHE_LINESIZE], %g1
69203831d35Sstevel	st	%g1, [%g6 + 36]		! save ecache_linesize
69303831d35Sstevel
69403831d35Sstevel	LOAD_MB(%g5, %g1, %g2)		! save mailbox data
69503831d35Sstevel	stb	%g1, [%g6 + 40]
69603831d35Sstevel
69703831d35Sstevel	membar	#Sync			! Complete any pending processing.
69803831d35Sstevel
69903831d35Sstevel	! Flush E$. The purpose of this flush is to rid the E$ of
70003831d35Sstevel	! lines in states O or Os. Implicitly flushes W$.
70103831d35Sstevel	! NOTE: Reading the bus sync list and r/w ops on drmach_xt_ready
70203831d35Sstevel	! will disturb the E$. The lines of the bus sync list will be
70303831d35Sstevel	! in state S. The line containing drmach_xt_ready will be in
70403831d35Sstevel	! state O. Before proceeding with the copy-rename, the master
70503831d35Sstevel	! processor will "steal back" the drmach_xt_ready (sic) line.
70603831d35Sstevel	! This will demote the state of the line in E$ to I.
70703831d35Sstevel	! However, the lines containing the bus sync list must be
70803831d35Sstevel	! victimized before returning to the OS. This is vital because
70903831d35Sstevel	! following copy-rename the corresponding lines in the new home
71003831d35Sstevel	! memory will be in state gM. The resulting S,gM state pair is
71103831d35Sstevel	! invalid and does represent a loss of coherency. Flushing the
71203831d35Sstevel	! E$ after the bus sync list is read will be sufficient to
71303831d35Sstevel	! avoid the invalid condition.
71403831d35Sstevel	!
71503831d35Sstevel	! For Panther, there is redundancy as both cores flush the shared
71603831d35Sstevel	! L2 and L3 caches.  As an optimization, only one core could do the
71703831d35Sstevel	! flush of the shared caches, however care must be taken that the
71803831d35Sstevel	! sibling core does not install owned lines once the flush begins.
71903831d35Sstevel	PN_L2_FLUSHALL(%g1, %g2, %g3)
72003831d35Sstevel	ldx	[%g6 + 24], %g1		! *ecache_flushaddr
72103831d35Sstevel	ld	[%g6 + 32], %g2		! ecache_size
72203831d35Sstevel	ld	[%g6 + 36], %g3		! ecache_linesize
72303831d35Sstevel	ECACHE_FLUSHALL(%g2, %g3, %g1, %g4)
72403831d35Sstevel
72503831d35Sstevel	! Make sure all outstanding transactions for this processor
72603831d35Sstevel	! have retired. See E$ note above.
72703831d35Sstevel	set	drmach_bus_sync_list, %g1
72803831d35Sstevel	BUS_SYNC(%g1, %g2)
72903831d35Sstevel
73003831d35Sstevel	HERE(%g6, 128, %g4)		! preparation complete (for debug)
73103831d35Sstevel
73203831d35Sstevel	! Signal this processor is ready for rename operation to begin.
73303831d35Sstevel	! See E$ note above.
73403831d35Sstevel	ATOMIC_ADD_LONG(drmach_xt_ready, 1, %g2, %g3, %g4)
73503831d35Sstevel
73603831d35Sstevel	! Loop on IRSR waiting for interrupt. The expected interrupt
73703831d35Sstevel	! is a cross-trap to drmach_wait_done. It is sent by the master
73803831d35Sstevel	! processor when the copy-rename operation is complete. The
73903831d35Sstevel	! received cross-trap is used only as a signal. It is not executed.
74003831d35Sstevel2:
74103831d35Sstevel	HERE(%g6, 136, %g4)		! last poll tick (for debug)
74203831d35Sstevel
74303831d35Sstevel	ldxa	[%g0]ASI_INTR_RECEIVE_STATUS, %g4	! wait for xt
74403831d35Sstevel	btst	IRSR_BUSY, %g4
74503831d35Sstevel	bz	2b
74603831d35Sstevel	nop
74703831d35Sstevel	stx	%g4, [%g6 + 64]		! save status and payload
74803831d35Sstevel	set	IRDR_0, %g2
74903831d35Sstevel	ldxa	[%g2]ASI_INTR_RECEIVE, %g2
75003831d35Sstevel	stx	%g2, [%g6 + 72]
75103831d35Sstevel	set	IRDR_1, %g2
75203831d35Sstevel	ldxa	[%g2]ASI_INTR_RECEIVE, %g2
75303831d35Sstevel	stx	%g2, [%g6 + 80]
75403831d35Sstevel	set	IRDR_2, %g2
75503831d35Sstevel	ldxa	[%g2]ASI_INTR_RECEIVE, %g2
75603831d35Sstevel	stx	%g2, [%g6 + 88]
75703831d35Sstevel
75803831d35Sstevel					! clear rcv status
75903831d35Sstevel	stxa	%g0, [%g0]ASI_INTR_RECEIVE_STATUS
76003831d35Sstevel	membar	#Sync
76103831d35Sstevel
76203831d35Sstevel	HERE(%g6, 144, %g4)		! signal rcvd tick (for debug)
76303831d35Sstevel
76403831d35Sstevel	! Check for copy-rename abort signal. If this signal is received,
76503831d35Sstevel	! the LPA change is skipped since the rename step was not done.
76603831d35Sstevel	! The cache flushes are still done as paranoia.
76703831d35Sstevel	set	drmach_rename_abort, %g1
76803831d35Sstevel	ldx	[%g6 + 72], %g2
76903831d35Sstevel	cmp 	%g1, %g2
77003831d35Sstevel	be	3f
77103831d35Sstevel	nop
77203831d35Sstevel
77303831d35Sstevel	! Resume waiting if this is not drmach_rename_done.
77403831d35Sstevel	set	drmach_rename_done, %g1
77503831d35Sstevel	cmp 	%g1, %g2
77603831d35Sstevel	bne	2b
77703831d35Sstevel	nop
77803831d35Sstevel
77903831d35Sstevel	ldub	[%g6 + 40], %g1		! get saved mailbox data
78003831d35Sstevel	SET_LPA(%g1, %g2, %g3)		! set LPA as indicated by the mb data
78103831d35Sstevel
78203831d35Sstevel3:
78303831d35Sstevel	! Flush all caches (E, D, I and P) to ensure each is resynchronized
78403831d35Sstevel	! with the corresponding states in the new home memory. (W$ is
78503831d35Sstevel	! implicitly flushed when the E$ is flushed.)
78603831d35Sstevel	!
78703831d35Sstevel	! Panther needs to flush the L2 cache before the L3
78803831d35Sstevel	! cache is flushed by the ecache flushall macro.
78903831d35Sstevel	PN_L2_FLUSHALL(%g1, %g2, %g3)
79003831d35Sstevel
79103831d35Sstevel	ldx	[%g6 + 24], %g1		! *ecache_flushaddr
79203831d35Sstevel	ld	[%g6 + 32], %g2		! ecache_size
79303831d35Sstevel	ld	[%g6 + 36], %g3		! ecache_linesize
79403831d35Sstevel	ECACHE_FLUSHALL(%g2, %g3, %g1, %g4)
79503831d35Sstevel
79603831d35Sstevel	ld	[%g6 + 8], %g1		! flush dcache
79703831d35Sstevel	ld	[%g6 + 12], %g2
79803831d35Sstevel	CH_DCACHE_FLUSHALL(%g1, %g2, %g3)
79903831d35Sstevel
80003831d35Sstevel	ld	[%g6 + 16], %g1		! flush icache
80103831d35Sstevel	ld	[%g6 + 20], %g2
80203831d35Sstevel	CH_ICACHE_FLUSHALL(%g1, %g2, %g3, %g4)
80303831d35Sstevel
80403831d35Sstevel	PCACHE_FLUSHALL(%g1, %g2, %g3)	! flush pcache (no parameters)
80503831d35Sstevel
80603831d35Sstevel	HERE(%g6, 152, %g4)		! done tick (for debug)
80703831d35Sstevel
80803831d35Sstevel	jmpl	%g7+8, %g0
80903831d35Sstevel	nop
81003831d35Sstevel
81103831d35Sstevel	.asciz	"drmach_rename_wait"	! for debug
81203831d35Sstevel	.align	4
81303831d35Ssteveldrmach_rename_wait_asm_end:
81403831d35Sstevel	SET_SIZE(drmach_rename_wait)
81503831d35Sstevel
81603831d35Sstevel
81703831d35Sstevel	! drmach_rename_done
81803831d35Sstevel	!
81903831d35Sstevel	! input:
82003831d35Sstevel	!	nothing
82103831d35Sstevel	!
82203831d35Sstevel	! output:
82303831d35Sstevel	!	nothing
82403831d35Sstevel	!
82503831d35Sstevel	! Used as signal data. See drmach_rename_wait.
82603831d35Sstevel	!
82703831d35Sstevel	ENTRY_NP(drmach_rename_done)
82803831d35Sstevel	retry
82903831d35Sstevel	SET_SIZE(drmach_rename_done)
83003831d35Sstevel
83103831d35Sstevel	! drmach_rename_abort
83203831d35Sstevel	!
83303831d35Sstevel	! input:
83403831d35Sstevel	!	nothing
83503831d35Sstevel	!
83603831d35Sstevel	! output:
83703831d35Sstevel	!	nothing
83803831d35Sstevel	!
83903831d35Sstevel	! Used as signal data. See drmach_rename_wait.
84003831d35Sstevel	!
84103831d35Sstevel	ENTRY_NP(drmach_rename_abort)
84203831d35Sstevel	retry
84303831d35Sstevel	SET_SIZE(drmach_rename_abort)
84403831d35Sstevel
84503831d35Sstevel
84603831d35Sstevel	! drmach_set_lpa
84703831d35Sstevel	!
84803831d35Sstevel	! input:
84903831d35Sstevel	!	Globals: drmach_xt_mb[cpuid] contains new LPA data
85003831d35Sstevel	!
85103831d35Sstevel	! output:
85203831d35Sstevel	!	nothing
85303831d35Sstevel	!
85403831d35Sstevel	! Sets the executing processor's LPA as indicated by the command
85503831d35Sstevel	! stored in drmach_xt_mb, a byte array indexed by cpuid. Assumes
85603831d35Sstevel	! the caller is preventing illegal LPA settings and transistions.
85703831d35Sstevel	!
85803831d35Sstevel	ENTRY_NP(drmach_set_lpa)
85903831d35Sstevel
86003831d35Sstevel	!
86103831d35Sstevel	! Set %g1 to this processor's cpuid.
86203831d35Sstevel	!
86303831d35Sstevel	CPU_INDEX(%g1, %g2)
86403831d35Sstevel
86503831d35Sstevel	!
86603831d35Sstevel	! Get LPA message from mailbox, leave in %g5.
86703831d35Sstevel	!
86803831d35Sstevel	LOAD_MB(%g1, %g5, %g2)
86903831d35Sstevel
87003831d35Sstevel	!
87103831d35Sstevel	! Set LPA, mailbox data in %g5.
87203831d35Sstevel	!
87303831d35Sstevel	SET_LPA(%g5, %g1, %g2)
87403831d35Sstevel
87503831d35Sstevel	!
87603831d35Sstevel	! Signal work is done.
87703831d35Sstevel	!
87803831d35Sstevel	ATOMIC_ADD_LONG(drmach_xt_ready, 1, %g1, %g2, %g3)
87903831d35Sstevel
88003831d35Sstevel	retry
88103831d35Sstevel	SET_SIZE(drmach_set_lpa)
88203831d35Sstevel
88303831d35Sstevel!
88403831d35Sstevel! drmach_bc_bzero
88503831d35Sstevel!
88603831d35Sstevel! inputs:
88703831d35Sstevel! 	%o0 = base vaddr of area to clear (must be 64-byte aligned)
88803831d35Sstevel!	%o1 = size of area to clear (must be multiple of 256 bytes)
88903831d35Sstevel!
89003831d35Sstevel! outputs:
89103831d35Sstevel!	%o0 =
89203831d35Sstevel!		0 (success)
89303831d35Sstevel!		1 (size too small or not modulo 256)
89403831d35Sstevel!		2 (vaddr not 64-byte aligned)
89503831d35Sstevel!
89603831d35Sstevel! Zero a block of storage using block commit stores.
89703831d35Sstevel! Nonzero return if caller's address or size are not
89803831d35Sstevel! block aligned.
89903831d35Sstevel!
90003831d35Sstevel
90103831d35Sstevel
90203831d35Sstevel	ENTRY(drmach_bc_bzero)
90303831d35Sstevel
90403831d35Sstevel	! verify size is >= 256 bytes
90503831d35Sstevel	cmp	%o1, 256
90603831d35Sstevel	blu,a	.bz_done
90703831d35Sstevel	mov	1, %o0			! error code 1 for invalid size
90803831d35Sstevel
90903831d35Sstevel	! verify size is a multiple of 256
91003831d35Sstevel	btst	(256-1), %o1
91103831d35Sstevel	bnz,a	.bz_done
91203831d35Sstevel	mov	1, %o0			! error code 1 for invalid size
91303831d35Sstevel
91403831d35Sstevel	! verify that vaddr is aligned for block stores
91503831d35Sstevel	btst	(64-1), %o0
91603831d35Sstevel	bnz,a	.bz_done
91703831d35Sstevel	mov	2, %o0			! error code 2 for invalid alignment
91803831d35Sstevel
91903831d35Sstevel	! save fprs for restore when finished
92003831d35Sstevel	rd	%fprs, %g1
92103831d35Sstevel
92203831d35Sstevel	! make sure FPU is enabled
92303831d35Sstevel	rdpr	%pstate, %g3
92403831d35Sstevel	btst	PSTATE_PEF, %g3
92503831d35Sstevel	bnz	.bz_block
92603831d35Sstevel	nop
92703831d35Sstevel	andn	%g3, PSTATE_PEF, %g4
92803831d35Sstevel	wrpr	%g4, PSTATE_PEF, %pstate
92903831d35Sstevel
93003831d35Sstevel.bz_block:
93103831d35Sstevel	membar	#StoreStore|#StoreLoad|#LoadStore
93203831d35Sstevel	wr	%g0, FPRS_FEF, %fprs
93303831d35Sstevel
93403831d35Sstevel	! Clear block
93503831d35Sstevel	fzero	%d0
93603831d35Sstevel	fzero	%d2
93703831d35Sstevel	fzero	%d4
93803831d35Sstevel	fzero	%d6
93903831d35Sstevel	fzero	%d8
94003831d35Sstevel	fzero	%d10
94103831d35Sstevel	fzero	%d12
94203831d35Sstevel	fzero	%d14
94303831d35Sstevel	wr	%g0, ASI_BLK_COMMIT_P, %asi
94403831d35Sstevel	mov	256, %o3
94503831d35Sstevel	ba	.bz_doblock
94603831d35Sstevel	nop
94703831d35Sstevel
94803831d35Sstevel.bz_blkstart:
94903831d35Sstevel      ! stda	%d0, [%o0+192]%asi  ! in dly slot of branch that got us here
95003831d35Sstevel	stda	%d0, [%o0+128]%asi
95103831d35Sstevel	stda	%d0, [%o0+64]%asi
95203831d35Sstevel	stda	%d0, [%o0]%asi
95303831d35Sstevel	add	%o0, %o3, %o0
95403831d35Sstevel	sub	%o1, %o3, %o1
95503831d35Sstevel.bz_doblock:
95603831d35Sstevel	cmp	%o1, 256
95703831d35Sstevel	bgeu,a	%ncc, .bz_blkstart
95803831d35Sstevel	stda	%d0, [%o0+192]%asi
95903831d35Sstevel
96003831d35Sstevel.bz_finish:
96103831d35Sstevel	membar	#StoreLoad|#StoreStore
96203831d35Sstevel	clr	%o0
96303831d35Sstevel	wr	%g1, %fprs		! restore fprs
96403831d35Sstevel	btst	PSTATE_PEF, %g3		! restore pstate if necessary
96503831d35Sstevel	bnz	.bz_done
96603831d35Sstevel	nop
96703831d35Sstevel	wrpr	%g3, %g0, %pstate
96803831d35Sstevel.bz_done:
96903831d35Sstevel	membar	#Sync
97003831d35Sstevel	retl
97103831d35Sstevel	nop
97203831d35Sstevel
97303831d35Sstevel	SET_SIZE(drmach_bc_bzero)
97403831d35Sstevel
97503831d35Sstevel#endif /* lint */
976