xref: /onnv-gate/usr/src/uts/sun4u/starcat/ml/drmach_asm.s (revision 11311:639e7bc0b42f)
11708Sstevel/*
21708Sstevel * CDDL HEADER START
31708Sstevel *
41708Sstevel * The contents of this file are subject to the terms of the
52241Shuah * Common Development and Distribution License (the "License").
62241Shuah * You may not use this file except in compliance with the License.
71708Sstevel *
81708Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91708Sstevel * or http://www.opensolaris.org/os/licensing.
101708Sstevel * See the License for the specific language governing permissions
111708Sstevel * and limitations under the License.
121708Sstevel *
131708Sstevel * When distributing Covered Code, include this CDDL HEADER in each
141708Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151708Sstevel * If applicable, add the following below this CDDL HEADER, with the
161708Sstevel * fields enclosed by brackets "[]" replaced with your own identifying
171708Sstevel * information: Portions Copyright [yyyy] [name of copyright owner]
181708Sstevel *
191708Sstevel * CDDL HEADER END
201708Sstevel */
211708Sstevel/*
22*11311SSurya.Prakki@Sun.COM * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
231708Sstevel * Use is subject to license terms.
241708Sstevel */
251708Sstevel
261708Sstevel/*
271708Sstevel * This file is through cpp before being used as
281708Sstevel * an inline.  It contains support routines used
291708Sstevel * only by DR.
301708Sstevel */
311708Sstevel
321708Sstevel#if defined(lint)
331708Sstevel#include <sys/types.h>
341708Sstevel#else
351708Sstevel#include "assym.h"
361708Sstevel#endif /* lint */
371708Sstevel
381708Sstevel#include <sys/asm_linkage.h>
391708Sstevel#include <sys/clock.h>
401708Sstevel#include <sys/param.h>
411708Sstevel#include <sys/privregs.h>
421708Sstevel#include <sys/machasi.h>
431708Sstevel#include <sys/mmu.h>
441708Sstevel#include <sys/machthread.h>
451708Sstevel#include <sys/pte.h>
461708Sstevel#include <sys/stack.h>
471708Sstevel#include <sys/vis.h>
481708Sstevel#include <sys/cheetahregs.h>
491708Sstevel#include <sys/cmpregs.h>
501708Sstevel#include <sys/intreg.h>
511708Sstevel#include <sys/cheetahasm.h>
521708Sstevel
531708Sstevel#if defined(lint)
541708Sstevel
551708Sstevel/*ARGSUSED*/
561708Sstevelvoid
57*11311SSurya.Prakki@Sun.COMdrmach_shutdown_asm(uint64_t estack, uint64_t flushaddr,
58*11311SSurya.Prakki@Sun.COM    int size, int lsz, uint64_t physmem)
591708Sstevel{}
601708Sstevel
611708Sstevel/*ARGSUSED*/
621708Sstevelvoid
631708Ssteveldrmach_rename(uint64_t *script, uint_t *err, uint64_t *id)
641708Sstevel{}
651708Sstevel
661708Sstevelvoid
671708Ssteveldrmach_rename_end(void)
681708Sstevel{}
691708Sstevel
701708Sstevel/*ARGSUSED*/
711708Sstevelvoid
721708Ssteveldrmach_rename_wait(uint64_t not_used_0, uint64_t not_used_1)
731708Sstevel{
741708Sstevel}
751708Sstevel
761708Sstevel/*ARGSUSED*/
771708Sstevelvoid
781708Ssteveldrmach_rename_done(uint64_t not_used_0, uint64_t not_used_1)
791708Sstevel{
801708Sstevel}
811708Sstevel
821708Sstevel/*ARGSUSED*/
831708Sstevelvoid
841708Ssteveldrmach_rename_abort(uint64_t not_used_0, uint64_t not_used_1)
851708Sstevel{
861708Sstevel}
871708Sstevel
881708Sstevel/*ARGSUSED*/
891708Ssteveluint64_t
90*11311SSurya.Prakki@Sun.COMlddsafconfig(void)
911708Sstevel{
921708Sstevel	return (0x0ull);
931708Sstevel}
941708Sstevel
951708Sstevel/* ARGSUSED */
961708Ssteveluint32_t
971708Ssteveldrmach_bc_bzero(void *addr, size_t size)
981708Sstevel{
991708Sstevel	return (0x0);
1001708Sstevel}
1011708Sstevel
1021708Sstevel#else /* lint */
1031708Sstevel
1041708Sstevel#define BUS_SYNC(reg1, reg2)					\
1051708Sstevel1:								;\
1061708Sstevel	ldx	[reg1], reg2					;\
1071708Sstevel	brz,pn	reg2, 2f					;\
1081708Sstevel	add	reg1, 8, reg1					;\
1091708Sstevel	ldxa	[reg2]ASI_MEM, %g0				;\
1101708Sstevel	ba,a	1b						;\
1111708Sstevel	nop							;\
1121708Sstevel2:
1131708Sstevel
1141708Sstevel#define LOAD_MB(cpuid, mb_data, reg1)				\
1151708Sstevel	set	drmach_xt_mb, reg1				;\
1161708Sstevel	ldx	[reg1], reg1					;\
1171708Sstevel	add	reg1, cpuid, reg1				;\
1181708Sstevel	ldub	[reg1], mb_data					;\
1191708Sstevel	stub	%g0, [reg1]
1201708Sstevel
1211708Sstevel#define LPA_MASK 0x7ff8
1221708Sstevel
1231708Sstevel#define SET_LPA(cmd, reg1, reg2)				\
1241708Sstevel	btst	0x80, cmd					;\
1251708Sstevel	bz	2f						;\
1261708Sstevel	nop							;\
1271708Sstevel	btst	0x40, cmd					;\
1281708Sstevel	bnz,a	1f						;\
1291708Sstevel	mov	%g0, cmd					;\
1301708Sstevel	and	cmd, 0x1f, cmd					;\
1311708Sstevel	sllx	cmd, 3, reg1					;\
1321708Sstevel	add	cmd, 1, cmd					;\
1331708Sstevel	sllx	cmd, 9, cmd					;\
1341708Sstevel	or	cmd, reg1, cmd					;\
1351708Sstevel1:								;\
1361708Sstevel	set	LPA_MASK, reg2					;\
1371708Sstevel	ldxa	[%g0]ASI_SAFARI_CONFIG, reg1			;\
1381708Sstevel	and	cmd, reg2, cmd					;\
1391708Sstevel	andn	reg1, reg2, reg1				;\
1401708Sstevel	or	reg1, cmd, reg1					;\
1411708Sstevel	stxa	reg1, [%g0]ASI_SAFARI_CONFIG			;\
1421708Sstevel	membar	#Sync						;\
1431708Sstevel2:								;\
1441708Sstevel
1451708Sstevel#define SET_NULL_LPA(reg1, reg2)				\
1461708Sstevel	set	LPA_MASK, reg2					;\
1471708Sstevel	ldxa	[%g0]ASI_SAFARI_CONFIG, reg1			;\
1481708Sstevel	andn	reg1, reg2, reg1				;\
1491708Sstevel	stxa	reg1, [%g0]ASI_SAFARI_CONFIG			;\
1501708Sstevel	membar	#Sync						;\
1511708Sstevel
1521708Sstevel	! ATOMIC_ADD_LONG
1531708Sstevel	! This code is run at TL > 0, being exec'd via a cross trap.
1541708Sstevel	! While running at trap level > 0, all memory accesses are
1551708Sstevel	! performed using NUCLEUS context, which is always 0.
1561708Sstevel	! Since the cross trap handler does not force PRIMARY context
1571708Sstevel	! to be zero, the following casxa instruction must specify
1581708Sstevel	! NUCLEUS ASI.
1591708Sstevel	! This ASI must be specified explicitly (via casxa), rather
1601708Sstevel	! than using casx. This is because of the fact that the
1611708Sstevel	! default casx specifies ASI_PRIMARY, which if non-zero, can
1621708Sstevel	! prevent the cpu from translating the address, leading to panic
1631708Sstevel	! on bad trap following repetitive dtlb misses.  This behavior
1641708Sstevel	! was encountered on MCPUs when using casx instruction.
1651708Sstevel#define ATOMIC_ADD_LONG(label, simm, reg1, reg2, reg3)		\
1661708Sstevel	set	label, reg1					;\
1671708Sstevel	ldx	[reg1], reg2					;\
1681708Sstevel1:								;\
1691708Sstevel	add	reg2, simm, reg3				;\
1701708Sstevel	casxa	[reg1]ASI_N, reg2, reg3				;\
1711708Sstevel	cmp	reg2, reg3					;\
1721708Sstevel	bne,a,pn %xcc, 1b					;\
1731708Sstevel	ldx	[reg1], reg2
1741708Sstevel
1751708Sstevel#define HERE(reg1, simm, reg2)					\
1761708Sstevel	rdpr	%tick, reg2					;\
1771708Sstevel	stx	reg2, [reg1 + simm]
1781708Sstevel
1791708Sstevel	!
1801708Sstevel	! Returns processor icache size and linesize in reg1 and
1811708Sstevel	! reg2, respectively.
1821708Sstevel	!
1831708Sstevel	! Panther has a larger icache compared to Cheetahplus and
1841708Sstevel	! Jaguar.
1851708Sstevel	!
1861708Sstevel#define	GET_ICACHE_PARAMS(reg1, reg2)				\
1871708Sstevel	GET_CPU_IMPL(reg1)					;\
1881708Sstevel	cmp	reg1, PANTHER_IMPL				;\
1891708Sstevel	bne	%xcc, 1f					;\
1901708Sstevel	  nop							;\
1911708Sstevel	set	PN_ICACHE_SIZE, reg1				;\
1921708Sstevel	set	PN_ICACHE_LSIZE, reg2				;\
1931708Sstevel	ba	2f						;\
1941708Sstevel	  nop							;\
1951708Sstevel1:								;\
1961708Sstevel	set	CH_ICACHE_SIZE, reg1				;\
1971708Sstevel	set	CH_ICACHE_LSIZE, reg2				;\
1981708Sstevel2:
1991708Sstevel
2001708Sstevel#define	DRMACH_MCU_IDLE_READS	3
2011708Sstevel
2021708Sstevel	! Macro to check if a Panther MC is idle.  The EMU Activity
2031708Sstevel	! Status register is first read to clear the MCU status bit.
2041708Sstevel	! The MCU status is then checked DRMACH_MCU_IDLE_READS times
2051708Sstevel	! to verify the MCU is indeed idle.  A single non-idle status
2061708Sstevel	! will fail the idle check.  This could be made more lenient
2071708Sstevel	! by adding a retry loop.
2081708Sstevel	!	addr:	Panther EMU Activity Status register read address.
2091708Sstevel	!		Assumed to be 0x18 for local ASI access or else
2101708Sstevel	!		FIREPLANE_ADDRESS_REG + 0x400050 for PIO access.
2111708Sstevel	!		0 is returned in this register if MCU is idle and
2121708Sstevel	!		queues are empty.  Otherwise, -1 is returned in this
2131708Sstevel	!		register.
2141708Sstevel	!	asi:	Immediate asi value.  Assumed to be ASI_SAFARI_CONFIG
2151708Sstevel	!		for local ASI or ASI_IO for PIO access.
2161708Sstevel	!	scr1:	Scratch
2171708Sstevel	!	scr2:	Scratch
2181708Sstevel	!
2191708Sstevel#define	CHECK_MCU_IDLE(addr, asi, scr1, scr2)			\
2201708Sstevel	ldxa	[addr]asi, %g0					;\
2211708Sstevel	ba	1f						;\
2221708Sstevel	  clr	scr2						;\
2231708Sstevel0:								;\
2241708Sstevel	btst	MCU_ACT_STATUS, scr1				;\
2251708Sstevel	bne,a	2f						;\
2261708Sstevel	  sub	%g0, 1, addr					;\
2271708Sstevel	inc	scr2						;\
2281708Sstevel1:								;\
2291708Sstevel	cmp	scr2, DRMACH_MCU_IDLE_READS			;\
2301708Sstevel	ble,a	0b						;\
2311708Sstevel	  ldxa    [addr]asi, scr1				;\
2321708Sstevel	clr	addr						;\
2331708Sstevel2:
2341708Sstevel
2351708Sstevel	! drmach_shutdown_asm
2361708Sstevel	!
2371708Sstevel	! inputs:
2381708Sstevel	!	%o0 = stack pointer
2391708Sstevel	!	%o1 = ecache flush address (ignored if cheetah+ processor)
2401708Sstevel	!	%o2 = ecache size
2411708Sstevel	!	%o3 = ecache line size
2421708Sstevel	!	%o4 = phys addr of byte to clear when finished
2431708Sstevel	!
2441708Sstevel	! output:
2451708Sstevel	!	Stores a zero at [%o4]ASI_MEM when the processor
2461708Sstevel	!	is ready to be removed from domain coherency.
2471708Sstevel	!
2481708Sstevel	ENTRY_NP(drmach_shutdown_asm)
2491708Sstevel	membar	#LoadStore		! parsley.
2501708Sstevel
2511708Sstevel	! Calculate pointer to data area. Determine size of
2521708Sstevel	! drmach_shutdown_asm, add to base address and align
2531708Sstevel	! to next 16 byte boundary. Leave result in %g6.
2541708Sstevel	set	drmach_shutdown_asm_end, %g6
2551708Sstevel	set	drmach_shutdown_asm, %g1
2561708Sstevel	set	drmach_cpu_sram_va, %g2
2571708Sstevel	ldx	[%g2], %g2
2581708Sstevel	sub	%g6, %g1, %g6
2591708Sstevel	add	%g6, %g2, %g6
2601708Sstevel	add	%g6, 15, %g6
2611708Sstevel	andn	%g6, 15, %g6
2621708Sstevel
2631708Sstevel	! Save parameters
2641708Sstevel	stx	%o0, [%g6 + 0]		! save stack pointer
2651708Sstevel	stx	%o1, [%g6 + 24]		! save E$ flush PA
2661708Sstevel	st	%o2, [%g6 + 32]		! save E$ size
2671708Sstevel	st	%o3, [%g6 + 36]		! save E$ linesize
2681708Sstevel	stx	%o4, [%g6 + 40]		! save phys addr of signal byte
2691708Sstevel
2701708Sstevel	set	dcache_size, %g1
2711708Sstevel	ld	[%g1], %g1
2721708Sstevel	st	%g1, [%g6 + 8]		! save dcache_size
2731708Sstevel	set	dcache_linesize, %g1
2741708Sstevel	ld	[%g1], %g1
2751708Sstevel	st	%g1, [%g6 + 12]		! save dcache_linesize
2761708Sstevel
2771708Sstevel	GET_ICACHE_PARAMS(%g1, %g2)
2781708Sstevel	st	%g1, [%g6 + 16]		! save icache_size
2791708Sstevel	st	%g2, [%g6 + 20]		! save icache_linesize
2801708Sstevel
2811708Sstevel	! Flushes all active windows except the current one.
2821708Sstevel	! Can cause spill traps to occur.
2831708Sstevel	flushw
2841708Sstevel
2851708Sstevel	! Make sure all asynchronous processing is complete.
2861708Sstevel	! Note: has no implications on pending bus transactions.
2871708Sstevel	membar	#Sync
2881708Sstevel
2891708Sstevel	! Move stack. Algorithm copied from t0stacktop setup of
2901708Sstevel	! %sp in sun4u/ml/locore.s
2911708Sstevel	! Replaces SWITCH_STACK() macro used in Starfire DR.
2921708Sstevel	ldx	[%g6 + 0], %g1
2931708Sstevel	sub	%g1, SA(KFPUSIZE+GSR_SIZE), %g2
2941708Sstevel 	and	%g2, 0x3f, %g3
2951708Sstevel 	sub	%g2, %g3, %o2
2961708Sstevel 	sub	%o2, SA(MPCBSIZE) + STACK_BIAS, %sp
2971708Sstevel	stx	%sp, [%g6 + 48]		! for debug
2981708Sstevel
2991708Sstevel	HERE(%g6, 128, %g1)		! initialization complete (for debug)
3001708Sstevel
3011708Sstevel	! Panther needs to flush the L2 cache before the L3
3021708Sstevel	! cache is flushed by the ecache flushall macro.
3031708Sstevel	PN_L2_FLUSHALL(%g1, %g2, %g3)
3041708Sstevel
3051708Sstevel	! Flush E$. The purpose of this flush is to rid the E$ of
3061708Sstevel	! lines in states O or Os. Implicitly flushes W$.
3071708Sstevel	ldx	[%g6 + 24], %g1		! *ecache_flushaddr
3081708Sstevel	ld	[%g6 + 32], %g2		! ecache_size
3091708Sstevel	ld	[%g6 + 36], %g3		! ecache_linesize
3101708Sstevel	ECACHE_FLUSHALL(%g2, %g3, %g1, %g4)
3111708Sstevel
3121708Sstevel	! Since the bus sync list read below does not guarantee
3131708Sstevel	! transaction completion on Panther domains, as an
3141708Sstevel	! optimization Panther skips the read and subsequent
3151708Sstevel	! E$ flush.
3161708Sstevel	GET_CPU_IMPL(%g1)
3171708Sstevel	cmp	%g1, PANTHER_IMPL
3181708Sstevel	be	%xcc, drmach_shutdown_ecache_flushed
3191708Sstevel	  nop
3201708Sstevel
3211708Sstevel	!
3221708Sstevel	! Ensure all outstanding writebacks have retired.  Following this
3231708Sstevel	! sync, all writes must be strictly managed.
3241708Sstevel	!
3251708Sstevel	set	drmach_bus_sync_list, %g1
3261708Sstevel	BUS_SYNC(%g1, %g2)
3271708Sstevel
3281708Sstevel	! Flush E$ again to victimize references to drmach_bus_sync_list.
3291708Sstevel	ldx     [%g6 + 24], %g1         ! *ecache_flushaddr
3301708Sstevel	ld	[%g6 + 32], %g2		! ecache_size
3311708Sstevel	ld	[%g6 + 36], %g3		! ecache_linesize
3321708Sstevel	ECACHE_FLUSHALL(%g2, %g3, %g1, %g4)
3331708Sstevel
3341708Ssteveldrmach_shutdown_ecache_flushed:
3351708Sstevel
3361708Sstevel	ld	[%g6 + 8], %g1		! flush dcache
3371708Sstevel	ld	[%g6 + 12], %g2
3381708Sstevel	CH_DCACHE_FLUSHALL(%g1, %g2, %g3)
3391708Sstevel
3401708Sstevel	ld	[%g6 + 16], %g1		! flush icache
3411708Sstevel	ld	[%g6 + 20], %g2
3421708Sstevel	CH_ICACHE_FLUSHALL(%g1, %g2, %g3, %g4)
3431708Sstevel
3441708Sstevel	PCACHE_FLUSHALL(%g1, %g2, %g3) ! flush pcache (no parameters)
3451708Sstevel
3461708Sstevel	!
3471708Sstevel	! Flush all unlocked dtlb and itlb entries.
3481708Sstevel	! Replaces TLB_FLUSH_UNLOCKED macro used in Starfire DR.
3491708Sstevel	!
3501708Sstevel	sethi	%hi(FLUSH_ADDR), %g1
3511708Sstevel	set	DEMAP_ALL_TYPE, %g2
3521708Sstevel	stxa	%g0, [%g2]ASI_DTLB_DEMAP
3531708Sstevel	stxa	%g0, [%g2]ASI_ITLB_DEMAP
3541708Sstevel	flush	%g1
3551708Sstevel
3561708Sstevel	!
3571708Sstevel	! Zero LPA by clearing CBASE and CBND. Following
3581708Sstevel	! this, all transactions to cachable address space
3591708Sstevel	! will be of the remote flavor.
3601708Sstevel	!
3611708Sstevel	SET_NULL_LPA(%g1, %g2)
3621708Sstevel
3631708Sstevel	HERE(%g6, 136, %g1)		! preparation complete (for debug)
3641708Sstevel
3651708Sstevel	!
3661708Sstevel	! Clear byte to signal finished.
3671708Sstevel	! NOTE: This store will allocate in the E$. It is
3681708Sstevel	! vitally important that this line is demoted to
3691708Sstevel	! state I before removing this processor from the
3701708Sstevel	! coherency.  The demotion is ensured by a synchronous
3711708Sstevel	! "steal back" that takes place in drmach_cpu_poweroff.
3721708Sstevel	ldx	[%g6 + 40], %g1
3731708Sstevel	stba	%g0, [%g1]ASI_MEM
3741708Sstevel5:
3751708Sstevel	HERE(%g6, 144, %g1)		! spin indicator (for debug)
3761708Sstevel	ba	5b
3771708Sstevel	  nop
3781708Sstevel
3791708Sstevel	.asciz	"drmach_shutdown_asm"		! for debug
3801708Sstevel	.align	4
3811708Sstevel	.global	drmach_shutdown_asm_end
3821708Ssteveldrmach_shutdown_asm_end:
3831708Sstevel	SET_SIZE(drmach_shutdown_asm)
3841708Sstevel
3851708Sstevel
3861708Sstevel	! lddsafconfig
3871708Sstevel	!
3881708Sstevel	! input:
3891708Sstevel	!	nothing
3901708Sstevel	!
3911708Sstevel	! output:
3921708Sstevel	!	%o0	content of this processor's SCR
3931708Sstevel	!
3941708Sstevel	!	Returns current value of this processor's Safari
3951708Sstevel	!	Configuration Register.
3961708Sstevel	!
3971708Sstevel	ENTRY(lddsafconfig)
3981708Sstevel        retl
3991708Sstevel        ldxa    [%g0]ASI_SAFARI_CONFIG, %o0
4001708Sstevel        SET_SIZE(lddsafconfig)
4011708Sstevel
4021708Sstevel	! drmach_rename
4031708Sstevel	!
4041708Sstevel	! input:
4051708Sstevel	!	%o0	pointer to register address/value compound list
4061708Sstevel	!	%o1	address for setting error code if rename did not
4071708Sstevel	!		complete.  Unmodified if no error.
4081708Sstevel	!	%o2	address for returning opaque memory controller id
4091708Sstevel	!		in case of error.  Unmodified if no error.
4101708Sstevel	!	Global	drmach_xt_mb[cpuid] is expected to be the new LPA.
4111708Sstevel	!
4121708Sstevel	! output:
4131708Sstevel	!	[%o1] =	1 if failed to idle memory controller, otherwise unmodified.
4141708Sstevel	!	[%o2] = id of failed memory controller, otherwise unmodified.
4151708Sstevel	!
4161708Sstevel	! Perform HW register reprogramming. This is the "rename" step for
4171708Sstevel	! the copy-rename process.  drmach_rename is copied to a cpu's sram
4181708Sstevel	! followed by register address/value pairs -- the text and data are
4191708Sstevel	! sourced from the sram while drmach_rename is executed.
4201708Sstevel	!
4211708Sstevel	! The parameter is assumed to point to a concatenation of six
4221708Sstevel	! zero-terminated lists located in non-cachable storage. The assumed
4231708Sstevel	! format (and purpose) of each list is as follows:
4241708Sstevel	!
4251708Sstevel	!	1) a copy of drmach_bus_sync_list. A list of PA for each
4261708Sstevel	!	   active memory bank in the domain. Used to infer the
4271708Sstevel	!	   the completion of all pending coherent transactions
4281708Sstevel	!	   initiated by this processor. Assumes MC work queue
4291708Sstevel	!	   does not implement read bypass. This is true of Cheetah,
4301708Sstevel	!	   Cheetah+, and Jaguar processors.  Panther does support
4311708Sstevel	!	   read bypass, so for Panther MCs with read-bypass-write
4321708Sstevel	!	   enabled, the read is issued but it does not guarantee
4331708Sstevel	!	   completion of outstanding writes in the MC queue.
4341708Sstevel	!	2) address/id pair for the local Panther EMU Activity Status
4351708Sstevel	!	   Register of this processor.  The register address is assumed
4361708Sstevel	!	   to be a VA which is polled via ASI_SAFARI_CONFIG until the
4371708Sstevel	!	   MC queues are empty.  The id is an opaque identifier which
4381708Sstevel	!	   must be returned along with an error code if the MCU status
4391708Sstevel	!	   does not go idle.  See the parameter description above.
4401708Sstevel	!	   This section will be empty if this processor is not a Panther.
4411708Sstevel	!	   Both the address and id are assumed to be 64 bit values.
4421708Sstevel	!	3) address/id pairs for non-local Panther EMU Activity Status
4431708Sstevel	!	   Registers on other source and target processors.  The register
4441708Sstevel	!	   address is assumed to be a PIO address which is polled via
4451708Sstevel	!	   ASI_IO to drain/idle the MCs on other Panther procs.  The
4461708Sstevel	!	   id is an opaque identifier which must be returned along with
4471708Sstevel	!	   an error code if a MC fails to go idle.  This section will
4481708Sstevel	!	   empty if there are no non-local Panther processors on the
4491708Sstevel	!	   source and target expanders.  Both the address and id are
4501708Sstevel	!	   assumed to be 64 bit values.
4511708Sstevel	!	4) address/value pairs for the Memory Address Decoder
4521708Sstevel	!	   register of this processor. The register address is
4531708Sstevel	!	   assumed to be a VA within ASM_MC_DECODE space. The
4541708Sstevel	!	   address and value elements are assumed to 64 bit values.
4551708Sstevel	!	5) address/value pairs for any 64 bit register accessible
4561708Sstevel	!	   via ASI_IO. The address and value fields are assumed to
4571708Sstevel	!	   be 64 bit values.
4581708Sstevel	!	   This list is typically used for reprogramming the Memory
4591708Sstevel	!	   Address Decoder Register of other cpus and for reprogram-
4601708Sstevel	!	   ming the Safari Configuration Register of I/O controllers.
4611708Sstevel	!	6) address/value pairs for any 32 bit register accessible
4621708Sstevel	!	   via ASI_IO. The address element is assumed to be a 64 bit
4631708Sstevel	!	   value. The value element is assumed to be a 64 bit word
4641708Sstevel	!	   containing a 32 bit value in the lower half.
4651708Sstevel	!	   This list typically contains address/value pairs for
4661708Sstevel	!	   AXQ CASM tables.
4671708Sstevel	!
4681708Sstevel	ENTRY_NP(drmach_rename)
4691708Sstevel
4701708Sstevel	mov	%o1, %o4		! save error code address
4711708Sstevel	mov	%o2, %o5		! save error id address
4721708Sstevel
4731708Sstevel	BUS_SYNC(%o0, %o1)		! run section 1
4741708Sstevel
4751708Sstevel	SET_NULL_LPA(%o1, %o2)		! prep for cachable transactions
4761708Sstevel					! after rename completes.
4771708Sstevel					! e.g.: the load_mb that occurs below
4781708Sstevel3:
4791708Sstevel	ldx	[%o0], %o1		! run section 2
4801708Sstevel	brz,a,pn %o1, 4f
4811708Sstevel	add	%o0, 8, %o0		! skip section 2 terminator
4821708Sstevel	CHECK_MCU_IDLE(%o1, ASI_SAFARI_CONFIG, %o2, %o3)
4831708Sstevel	cmp	%o1, 0			! idled?
4841708Sstevel	be,a	3b			! ok, advance
4851708Sstevel	  add	%o0, 16, %o0
4861708Sstevel	mov	1, %o1			! not idle, bailout
4871708Sstevel	stw	%o1, [%o4]		! set MC idle error code
4881708Sstevel	ldx	[%o0 + 8], %o1
4891708Sstevel	stx	%o1, [%o5]		! set MC idle error id
4901708Sstevel	retl
4911708Sstevel	  nop
4921708Sstevel4:
4931708Sstevel	ldx	[%o0], %o1		! run section 3
4941708Sstevel	brz,a,pn %o1, 5f
4951708Sstevel	add	%o0, 8, %o0		! skip section 3 terminator
4961708Sstevel	CHECK_MCU_IDLE(%o1, ASI_IO, %o2, %o3)
4971708Sstevel	cmp	%o1, 0			! idled?
4981708Sstevel	be,a	4b			! ok, advance
4991708Sstevel	  add	%o0, 16, %o0
5001708Sstevel	mov	1, %o1			! not idle, bailout
5011708Sstevel	stw	%o1, [%o4]		! set MC idle error code
5021708Sstevel	ldx	[%o0 + 8], %o1
5031708Sstevel	stx	%o1, [%o5]		! set MC idle error id
5041708Sstevel	retl
5051708Sstevel	  nop
5061708Sstevel5:
5071708Sstevel	ldx	[%o0], %o1		! run section 4
5081708Sstevel	brz,a,pn %o1, 6f
5091708Sstevel	add	%o0, 8, %o0		! skip section 4 terminator
5101708Sstevel	ldx	[%o0 + 8], %o2
5111708Sstevel	stxa	%o2, [%o1]ASI_MC_DECODE
5121708Sstevel	membar	#Sync
5131708Sstevel	ldxa	[%o1]ASI_MC_DECODE, %g0	! read back to insure written
5141708Sstevel	b	5b
5151708Sstevel	add	%o0, 16, %o0
5161708Sstevel6:
5171708Sstevel	ldx	[%o0], %o1		! run section 5
5181708Sstevel	brz,a,pn %o1, 7f
5191708Sstevel	add	%o0, 8, %o0		! skip section 5 terminator
5201708Sstevel	ldx	[%o0 + 8], %o2
5211708Sstevel	stxa	%o2, [%o1]ASI_IO
5221708Sstevel	ldxa	[%o1]ASI_IO, %g0	! read back to insure written
5231708Sstevel	b	6b
5241708Sstevel	add	%o0, 16, %o0
5251708Sstevel7:
5261708Sstevel	ldx	[%o0], %o1		! run section 6
5271708Sstevel	brz,a,pn %o1, 8f
5281708Sstevel	nop
5291708Sstevel	ldx	[%o0 + 8], %o2
5301708Sstevel	stwa	%o2, [%o1]ASI_IO
5311708Sstevel	lduwa	[%o1]ASI_IO, %g0	! read back to insure written
5321708Sstevel	b	7b
5331708Sstevel	add	%o0, 16, %o0
5341708Sstevel8:
5351708Sstevel	CPU_INDEX(%o0, %o1)
5361708Sstevel	LOAD_MB(%o0, %o1, %o2)
5371708Sstevel	SET_LPA(%o1, %o0, %o2)
5381708Sstevel
5391708Sstevel	retl
5401708Sstevel	nop
5411708Sstevel
5421708Sstevel	.asciz	"drmach_rename"		! for debug
5431708Sstevel	.align	4
5441708Sstevel	SET_SIZE(drmach_rename)
5451708Sstevel
5461708Sstevel	.global drmach_rename_end
5471708Ssteveldrmach_rename_end:
5481708Sstevel
5491708Sstevel
5501708Sstevel	! drmach_rename_wait
5511708Sstevel	!
5521708Sstevel	! input:
5531708Sstevel	!	nothing
5541708Sstevel	!
5551708Sstevel	! output:
5561708Sstevel	!	nothing
5571708Sstevel	!
5581708Sstevel	! drmach_rename_wait is a cross-trap function used to move a
5591708Sstevel	! cpu's execution out of coherent space while a copy-rename
5601708Sstevel	! operation is in progress.
5611708Sstevel	!
5621708Sstevel	! In each CPU SRAM exists an area (16KB on Cheetah+ boards,
5631708Sstevel	! 32KB on Jaguar/Panther boards) reserved for DR. This area is
5641708Sstevel	! logically divided by DR into 8KB pages, one page per CPU (or
5651708Sstevel	! core) in a port pair. (Two Safari ports share HW resources on
5661708Sstevel	! a CPU/MEM board. These are referred to as a port pair.)
5671708Sstevel	!
5681708Sstevel	! This routine begins by mapping the appropriate SRAM page,
5691708Sstevel	! transferring the machine code (between the labels
5701708Sstevel	! drmach_rename_wait_asm and drmach_rename_wait_asm_end), then
5711708Sstevel	! jumping to SRAM.  After returning from SRAM, the page is
5721708Sstevel	! demapped before the cross-call is exited (sic).
5731708Sstevel	!
5741708Sstevel	! The machine code flushes all caches, waits for a special
5751708Sstevel	! interrupt vector, then updates the processor's LPA and
5761708Sstevel	! resynchronizes caches with the new home memory.
5771708Sstevel	!
5781708Sstevel	! The special interrupt vector is assumed to be a cross-call to
5791708Sstevel	! drmach_rename_done sent by the master processor upon completing
5801708Sstevel	! the copy-rename operation. The interrupt is received and discarded;
5811708Sstevel	! The cross-call to drmach_rename_done is never executed.  Instead
5821708Sstevel	! the Interrupt Receive Status Register is employed, temporarily,
5831708Sstevel	! as a semaphore. This avoids unwanted bus traffic during the critical
5841708Sstevel	! rename operation.
5851708Sstevel	!
5861708Sstevel	ENTRY_NP(drmach_rename_wait)
5871708Sstevel
5881708Sstevel	CPU_INDEX(%g5, %g1)		! put cpuid in %g5
5891708Sstevel
5901708Sstevel	!
5911708Sstevel	! sfmmu_dtlb_ld(drmach_cpu_sram_va,
5921708Sstevel	!	KCONTEXT, drmach_cpu_sram_tte[cpuid]);
5931708Sstevel	! sfmmu_itlb_ld(drmach_cpu_sram_va,
5941708Sstevel	!	KCONTEXT, drmach_cpu_sram_tte[cpuid]);
5951708Sstevel	!
5961708Sstevel	set	drmach_cpu_sram_tte, %g1
5971708Sstevel	sllx	%g5, 3, %g2
5981708Sstevel	ldx	[%g1 + %g2], %g3
5991708Sstevel	set	drmach_cpu_sram_va, %g1
6001708Sstevel	ldx	[%g1], %g1
6011708Sstevel	or	%g1, KCONTEXT, %g2	! preserve %g1
6021708Sstevel	set	MMU_TAG_ACCESS, %g4
6032241Shuah	set	cpu_impl_dual_pgsz, %g6
6042241Shuah	ld      [%g6], %g6
6051708Sstevel	brz	%g6, 1f
6061708Sstevel	  nop
6072241Shuah
6082241Shuah	sethi	%hi(ksfmmup), %g6
6092241Shuah	ldx	[%g6 + %lo(ksfmmup)], %g6
6102241Shuah	ldub    [%g6 + SFMMU_CEXT], %g6
6112241Shuah        sll     %g6, TAGACCEXT_SHIFT, %g6
6122241Shuah
6131708Sstevel	set	MMU_TAG_ACCESS_EXT, %g7
6141708Sstevel	stxa	%g6, [%g7]ASI_DMMU
6151708Sstevel1:
6161708Sstevel	stxa	%g2, [%g4]ASI_DMMU
6171708Sstevel	stxa    %g3, [%g0]ASI_DTLB_IN
6181708Sstevel	membar	#Sync
6191708Sstevel	sethi	%hi(FLUSH_ADDR), %g6
6201708Sstevel	stxa	%g2, [%g4]ASI_IMMU
6211708Sstevel	stxa    %g3, [%g0]ASI_ITLB_IN
6221708Sstevel	flush	%g6
6231708Sstevel
6241708Sstevel	!
6251708Sstevel	! copy drmach_rename_wait_asm block to SRAM. Preserve entry
6261708Sstevel	! point in %g1. After the code has been copied, align %g6
6271708Sstevel	! (the destination pointer) to the next highest 16 byte
6281708Sstevel	! boundary. This will define the start of the data area.
6291708Sstevel	!
6301708Sstevel	mov	%g1, %g6
6311708Sstevel	set	drmach_rename_wait_asm, %g2
6321708Sstevel	set	drmach_rename_wait_asm_end, %g3
6331708Sstevel0:
6341708Sstevel	lduw	[%g2], %g4		! do copy
6351708Sstevel	stw	%g4, [%g6]
6361708Sstevel	add	%g2, 4, %g2
6371708Sstevel	cmp	%g2, %g3
6381708Sstevel	bne	0b
6391708Sstevel	add	%g6, 4, %g6
6401708Sstevel
6411708Sstevel	add	%g6, 15, %g6		! locate data area on next 16 byte
6421708Sstevel	andn	%g6, 15, %g6		! boundary following text
6431708Sstevel					! WARNING: no bounds checking
6441708Sstevel
6451708Sstevel	jmpl	%g1, %g7		! jump to code in cpu sram
6461708Sstevel	nop
6471708Sstevel
6481708Sstevel	set	drmach_cpu_sram_va, %g1	! vtab_flushpage_tl1(drmach_cpu_sram_va,
6491708Sstevel	ldx	[%g1], %g1		! 	KCONTEXT);
6501708Sstevel	set	KCONTEXT, %g2
6511708Sstevel	set	MMU_PCONTEXT, %g4
6521708Sstevel	or	%g1, DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %g1
6531708Sstevel	ldxa	[%g4]ASI_DMMU, %g5	/* rd old ctxnum */
6541708Sstevel	stxa	%g2, [%g4]ASI_DMMU	/* wr new ctxum */
6551708Sstevel	stxa	%g0, [%g1]ASI_DTLB_DEMAP
6561708Sstevel	stxa	%g0, [%g1]ASI_ITLB_DEMAP
6571708Sstevel	stxa	%g5, [%g4]ASI_DMMU	/* restore old ctxnum */
6581708Sstevel
6591708Sstevel	retry
6601708Sstevel
6611708Ssteveldrmach_rename_wait_asm:
6621708Sstevel	! the following code is copied to a cpu's sram and executed
6631708Sstevel	! from there.
6641708Sstevel	! Input:
6651708Sstevel	!	%g5 is cpuid
6661708Sstevel	!	%g6 is data area (follows text)
6671708Sstevel	!	%g7 is link address back to caller
6681708Sstevel	!
6691708Sstevel	st	%g5, [%g6 + 4]		! save cpuid (for debug)
6701708Sstevel
6711708Sstevel	set	dcache_size, %g1
6721708Sstevel	ld	[%g1], %g1
6731708Sstevel	st	%g1, [%g6 + 8]		! save dcache_size
6741708Sstevel	set	dcache_linesize, %g1
6751708Sstevel	ld	[%g1], %g1
6761708Sstevel	st	%g1, [%g6 + 12]		! save dcache_linesize
6771708Sstevel
6781708Sstevel	GET_ICACHE_PARAMS(%g1, %g2)
6791708Sstevel	st	%g1, [%g6 + 16]		! save icache_size
6801708Sstevel	st	%g2, [%g6 + 20]		! save icache_linesize
6811708Sstevel
6821708Sstevel	set	drmach_iocage_paddr, %g1
6831708Sstevel	ldx	[%g1], %g1
6841708Sstevel	stx	%g1, [%g6 + 24]		! save *ecache_flushadr
6851708Sstevel
6861708Sstevel	mulx	%g5, CPU_NODE_SIZE, %g1	! %g4 = &cpunodes[cpuid]
6871708Sstevel	set	cpunodes, %g4
6881708Sstevel	add	%g4, %g1, %g4
6891708Sstevel	ld	[%g4 + ECACHE_SIZE], %g1
6901708Sstevel	st	%g1, [%g6 + 32]		! save ecache_size
6911708Sstevel	ld	[%g4 + ECACHE_LINESIZE], %g1
6921708Sstevel	st	%g1, [%g6 + 36]		! save ecache_linesize
6931708Sstevel
6941708Sstevel	LOAD_MB(%g5, %g1, %g2)		! save mailbox data
6951708Sstevel	stb	%g1, [%g6 + 40]
6961708Sstevel
6971708Sstevel	membar	#Sync			! Complete any pending processing.
6981708Sstevel
6991708Sstevel	! Flush E$. The purpose of this flush is to rid the E$ of
7001708Sstevel	! lines in states O or Os. Implicitly flushes W$.
7011708Sstevel	! NOTE: Reading the bus sync list and r/w ops on drmach_xt_ready
7021708Sstevel	! will disturb the E$. The lines of the bus sync list will be
7031708Sstevel	! in state S. The line containing drmach_xt_ready will be in
7041708Sstevel	! state O. Before proceeding with the copy-rename, the master
7051708Sstevel	! processor will "steal back" the drmach_xt_ready (sic) line.
7061708Sstevel	! This will demote the state of the line in E$ to I.
7071708Sstevel	! However, the lines containing the bus sync list must be
7081708Sstevel	! victimized before returning to the OS. This is vital because
7091708Sstevel	! following copy-rename the corresponding lines in the new home
7101708Sstevel	! memory will be in state gM. The resulting S,gM state pair is
7111708Sstevel	! invalid and does represent a loss of coherency. Flushing the
7121708Sstevel	! E$ after the bus sync list is read will be sufficient to
7131708Sstevel	! avoid the invalid condition.
7141708Sstevel	!
7151708Sstevel	! For Panther, there is redundancy as both cores flush the shared
7161708Sstevel	! L2 and L3 caches.  As an optimization, only one core could do the
7171708Sstevel	! flush of the shared caches, however care must be taken that the
7181708Sstevel	! sibling core does not install owned lines once the flush begins.
7191708Sstevel	PN_L2_FLUSHALL(%g1, %g2, %g3)
7201708Sstevel	ldx	[%g6 + 24], %g1		! *ecache_flushaddr
7211708Sstevel	ld	[%g6 + 32], %g2		! ecache_size
7221708Sstevel	ld	[%g6 + 36], %g3		! ecache_linesize
7231708Sstevel	ECACHE_FLUSHALL(%g2, %g3, %g1, %g4)
7241708Sstevel
7251708Sstevel	! Make sure all outstanding transactions for this processor
7261708Sstevel	! have retired. See E$ note above.
7271708Sstevel	set	drmach_bus_sync_list, %g1
7281708Sstevel	BUS_SYNC(%g1, %g2)
7291708Sstevel
7301708Sstevel	HERE(%g6, 128, %g4)		! preparation complete (for debug)
7311708Sstevel
7321708Sstevel	! Signal this processor is ready for rename operation to begin.
7331708Sstevel	! See E$ note above.
7341708Sstevel	ATOMIC_ADD_LONG(drmach_xt_ready, 1, %g2, %g3, %g4)
7351708Sstevel
7361708Sstevel	! Loop on IRSR waiting for interrupt. The expected interrupt
7371708Sstevel	! is a cross-trap to drmach_wait_done. It is sent by the master
7381708Sstevel	! processor when the copy-rename operation is complete. The
7391708Sstevel	! received cross-trap is used only as a signal. It is not executed.
7401708Sstevel2:
7411708Sstevel	HERE(%g6, 136, %g4)		! last poll tick (for debug)
7421708Sstevel
7431708Sstevel	ldxa	[%g0]ASI_INTR_RECEIVE_STATUS, %g4	! wait for xt
7441708Sstevel	btst	IRSR_BUSY, %g4
7451708Sstevel	bz	2b
7461708Sstevel	nop
7471708Sstevel	stx	%g4, [%g6 + 64]		! save status and payload
7481708Sstevel	set	IRDR_0, %g2
7491708Sstevel	ldxa	[%g2]ASI_INTR_RECEIVE, %g2
7501708Sstevel	stx	%g2, [%g6 + 72]
7511708Sstevel	set	IRDR_1, %g2
7521708Sstevel	ldxa	[%g2]ASI_INTR_RECEIVE, %g2
7531708Sstevel	stx	%g2, [%g6 + 80]
7541708Sstevel	set	IRDR_2, %g2
7551708Sstevel	ldxa	[%g2]ASI_INTR_RECEIVE, %g2
7561708Sstevel	stx	%g2, [%g6 + 88]
7571708Sstevel
7581708Sstevel					! clear rcv status
7591708Sstevel	stxa	%g0, [%g0]ASI_INTR_RECEIVE_STATUS
7601708Sstevel	membar	#Sync
7611708Sstevel
7621708Sstevel	HERE(%g6, 144, %g4)		! signal rcvd tick (for debug)
7631708Sstevel
7641708Sstevel	! Check for copy-rename abort signal. If this signal is received,
7651708Sstevel	! the LPA change is skipped since the rename step was not done.
7661708Sstevel	! The cache flushes are still done as paranoia.
7671708Sstevel	set	drmach_rename_abort, %g1
7681708Sstevel	ldx	[%g6 + 72], %g2
7691708Sstevel	cmp 	%g1, %g2
7701708Sstevel	be	3f
7711708Sstevel	nop
7721708Sstevel
7731708Sstevel	! Resume waiting if this is not drmach_rename_done.
7741708Sstevel	set	drmach_rename_done, %g1
7751708Sstevel	cmp 	%g1, %g2
7761708Sstevel	bne	2b
7771708Sstevel	nop
7781708Sstevel
7791708Sstevel	ldub	[%g6 + 40], %g1		! get saved mailbox data
7801708Sstevel	SET_LPA(%g1, %g2, %g3)		! set LPA as indicated by the mb data
7811708Sstevel
7821708Sstevel3:
7831708Sstevel	! Flush all caches (E, D, I and P) to ensure each is resynchronized
7841708Sstevel	! with the corresponding states in the new home memory. (W$ is
7851708Sstevel	! implicitly flushed when the E$ is flushed.)
7861708Sstevel	!
7871708Sstevel	! Panther needs to flush the L2 cache before the L3
7881708Sstevel	! cache is flushed by the ecache flushall macro.
7891708Sstevel	PN_L2_FLUSHALL(%g1, %g2, %g3)
7901708Sstevel
7911708Sstevel	ldx	[%g6 + 24], %g1		! *ecache_flushaddr
7921708Sstevel	ld	[%g6 + 32], %g2		! ecache_size
7931708Sstevel	ld	[%g6 + 36], %g3		! ecache_linesize
7941708Sstevel	ECACHE_FLUSHALL(%g2, %g3, %g1, %g4)
7951708Sstevel
7961708Sstevel	ld	[%g6 + 8], %g1		! flush dcache
7971708Sstevel	ld	[%g6 + 12], %g2
7981708Sstevel	CH_DCACHE_FLUSHALL(%g1, %g2, %g3)
7991708Sstevel
8001708Sstevel	ld	[%g6 + 16], %g1		! flush icache
8011708Sstevel	ld	[%g6 + 20], %g2
8021708Sstevel	CH_ICACHE_FLUSHALL(%g1, %g2, %g3, %g4)
8031708Sstevel
8041708Sstevel	PCACHE_FLUSHALL(%g1, %g2, %g3)	! flush pcache (no parameters)
8051708Sstevel
8061708Sstevel	HERE(%g6, 152, %g4)		! done tick (for debug)
8071708Sstevel
8081708Sstevel	jmpl	%g7+8, %g0
8091708Sstevel	nop
8101708Sstevel
8111708Sstevel	.asciz	"drmach_rename_wait"	! for debug
8121708Sstevel	.align	4
8131708Ssteveldrmach_rename_wait_asm_end:
8141708Sstevel	SET_SIZE(drmach_rename_wait)
8151708Sstevel
8161708Sstevel
8171708Sstevel	! drmach_rename_done
8181708Sstevel	!
8191708Sstevel	! input:
8201708Sstevel	!	nothing
8211708Sstevel	!
8221708Sstevel	! output:
8231708Sstevel	!	nothing
8241708Sstevel	!
8251708Sstevel	! Used as signal data. See drmach_rename_wait.
8261708Sstevel	!
8271708Sstevel	ENTRY_NP(drmach_rename_done)
8281708Sstevel	retry
8291708Sstevel	SET_SIZE(drmach_rename_done)
8301708Sstevel
8311708Sstevel	! drmach_rename_abort
8321708Sstevel	!
8331708Sstevel	! input:
8341708Sstevel	!	nothing
8351708Sstevel	!
8361708Sstevel	! output:
8371708Sstevel	!	nothing
8381708Sstevel	!
8391708Sstevel	! Used as signal data. See drmach_rename_wait.
8401708Sstevel	!
8411708Sstevel	ENTRY_NP(drmach_rename_abort)
8421708Sstevel	retry
8431708Sstevel	SET_SIZE(drmach_rename_abort)
8441708Sstevel
8451708Sstevel
8461708Sstevel	! drmach_set_lpa
8471708Sstevel	!
8481708Sstevel	! input:
8491708Sstevel	!	Globals: drmach_xt_mb[cpuid] contains new LPA data
8501708Sstevel	!
8511708Sstevel	! output:
8521708Sstevel	!	nothing
8531708Sstevel	!
8541708Sstevel	! Sets the executing processor's LPA as indicated by the command
8551708Sstevel	! stored in drmach_xt_mb, a byte array indexed by cpuid. Assumes
8561708Sstevel	! the caller is preventing illegal LPA settings and transistions.
8571708Sstevel	!
8581708Sstevel	ENTRY_NP(drmach_set_lpa)
8591708Sstevel
8601708Sstevel	!
8611708Sstevel	! Set %g1 to this processor's cpuid.
8621708Sstevel	!
8631708Sstevel	CPU_INDEX(%g1, %g2)
8641708Sstevel
8651708Sstevel	!
8661708Sstevel	! Get LPA message from mailbox, leave in %g5.
8671708Sstevel	!
8681708Sstevel	LOAD_MB(%g1, %g5, %g2)
8691708Sstevel
8701708Sstevel	!
8711708Sstevel	! Set LPA, mailbox data in %g5.
8721708Sstevel	!
8731708Sstevel	SET_LPA(%g5, %g1, %g2)
8741708Sstevel
8751708Sstevel	!
8761708Sstevel	! Signal work is done.
8771708Sstevel	!
8781708Sstevel	ATOMIC_ADD_LONG(drmach_xt_ready, 1, %g1, %g2, %g3)
8791708Sstevel
8801708Sstevel	retry
8811708Sstevel	SET_SIZE(drmach_set_lpa)
8821708Sstevel
8831708Sstevel!
8841708Sstevel! drmach_bc_bzero
8851708Sstevel!
8861708Sstevel! inputs:
8871708Sstevel! 	%o0 = base vaddr of area to clear (must be 64-byte aligned)
8881708Sstevel!	%o1 = size of area to clear (must be multiple of 256 bytes)
8891708Sstevel!
8901708Sstevel! outputs:
8911708Sstevel!	%o0 =
8921708Sstevel!		0 (success)
8931708Sstevel!		1 (size too small or not modulo 256)
8941708Sstevel!		2 (vaddr not 64-byte aligned)
8951708Sstevel!
8961708Sstevel! Zero a block of storage using block commit stores.
8971708Sstevel! Nonzero return if caller's address or size are not
8981708Sstevel! block aligned.
8991708Sstevel!
9001708Sstevel
9011708Sstevel
9021708Sstevel	ENTRY(drmach_bc_bzero)
9031708Sstevel
9041708Sstevel	! verify size is >= 256 bytes
9051708Sstevel	cmp	%o1, 256
9061708Sstevel	blu,a	.bz_done
9071708Sstevel	mov	1, %o0			! error code 1 for invalid size
9081708Sstevel
9091708Sstevel	! verify size is a multiple of 256
9101708Sstevel	btst	(256-1), %o1
9111708Sstevel	bnz,a	.bz_done
9121708Sstevel	mov	1, %o0			! error code 1 for invalid size
9131708Sstevel
9141708Sstevel	! verify that vaddr is aligned for block stores
9151708Sstevel	btst	(64-1), %o0
9161708Sstevel	bnz,a	.bz_done
9171708Sstevel	mov	2, %o0			! error code 2 for invalid alignment
9181708Sstevel
9191708Sstevel	! save fprs for restore when finished
9201708Sstevel	rd	%fprs, %g1
9211708Sstevel
9221708Sstevel	! make sure FPU is enabled
9231708Sstevel	rdpr	%pstate, %g3
9241708Sstevel	btst	PSTATE_PEF, %g3
9251708Sstevel	bnz	.bz_block
9261708Sstevel	nop
9271708Sstevel	andn	%g3, PSTATE_PEF, %g4
9281708Sstevel	wrpr	%g4, PSTATE_PEF, %pstate
9291708Sstevel
9301708Sstevel.bz_block:
9311708Sstevel	membar	#StoreStore|#StoreLoad|#LoadStore
9321708Sstevel	wr	%g0, FPRS_FEF, %fprs
9331708Sstevel
9341708Sstevel	! Clear block
9351708Sstevel	fzero	%d0
9361708Sstevel	fzero	%d2
9371708Sstevel	fzero	%d4
9381708Sstevel	fzero	%d6
9391708Sstevel	fzero	%d8
9401708Sstevel	fzero	%d10
9411708Sstevel	fzero	%d12
9421708Sstevel	fzero	%d14
9431708Sstevel	wr	%g0, ASI_BLK_COMMIT_P, %asi
9441708Sstevel	mov	256, %o3
9451708Sstevel	ba	.bz_doblock
9461708Sstevel	nop
9471708Sstevel
9481708Sstevel.bz_blkstart:
9491708Sstevel      ! stda	%d0, [%o0+192]%asi  ! in dly slot of branch that got us here
9501708Sstevel	stda	%d0, [%o0+128]%asi
9511708Sstevel	stda	%d0, [%o0+64]%asi
9521708Sstevel	stda	%d0, [%o0]%asi
9531708Sstevel	add	%o0, %o3, %o0
9541708Sstevel	sub	%o1, %o3, %o1
9551708Sstevel.bz_doblock:
9561708Sstevel	cmp	%o1, 256
9571708Sstevel	bgeu,a	%ncc, .bz_blkstart
9581708Sstevel	stda	%d0, [%o0+192]%asi
9591708Sstevel
9601708Sstevel.bz_finish:
9611708Sstevel	membar	#StoreLoad|#StoreStore
9621708Sstevel	clr	%o0
9631708Sstevel	wr	%g1, %fprs		! restore fprs
9641708Sstevel	btst	PSTATE_PEF, %g3		! restore pstate if necessary
9651708Sstevel	bnz	.bz_done
9661708Sstevel	nop
9671708Sstevel	wrpr	%g3, %g0, %pstate
9681708Sstevel.bz_done:
9691708Sstevel	membar	#Sync
9701708Sstevel	retl
9711708Sstevel	nop
9721708Sstevel
9731708Sstevel	SET_SIZE(drmach_bc_bzero)
9741708Sstevel
9751708Sstevel#endif /* lint */
976