103831d35Sstevel/*
203831d35Sstevel * CDDL HEADER START
303831d35Sstevel *
403831d35Sstevel * The contents of this file are subject to the terms of the
503831d35Sstevel * Common Development and Distribution License (the "License").
603831d35Sstevel * 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
2203831d35Sstevel/*
2303831d35Sstevel * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
2403831d35Sstevel * Use is subject to license terms.
2503831d35Sstevel */
2603831d35Sstevel
2703831d35Sstevel/*
2803831d35Sstevel * This file is through cpp before being used as
2903831d35Sstevel * an inline.  It contains support routines used
3003831d35Sstevel * only by DR for the copy-rename sequence.
3103831d35Sstevel */
3203831d35Sstevel
3303831d35Sstevel#include "assym.h"
3403831d35Sstevel
3503831d35Sstevel#include <sys/asm_linkage.h>
3603831d35Sstevel#include <sys/param.h>
3703831d35Sstevel#include <sys/privregs.h>
3803831d35Sstevel#include <sys/machasi.h>
3903831d35Sstevel#include <sys/mmu.h>
4003831d35Sstevel#include <sys/machthread.h>
4103831d35Sstevel#include <sys/pte.h>
4203831d35Sstevel#include <sys/stack.h>
4303831d35Sstevel#include <sys/vis.h>
4403831d35Sstevel#include <sys/param.h>
4503831d35Sstevel#include <sys/errno.h>
4603831d35Sstevel#include <sys/vtrace.h>
4703831d35Sstevel#include <sys/clock.h>
4803831d35Sstevel#include <sys/asi.h>
4903831d35Sstevel#include <sys/fsr.h>
5003831d35Sstevel#include <sys/cheetahregs.h>
5103831d35Sstevel#include <sys/cheetahasm.h>
5203831d35Sstevel
5303831d35Sstevel/*
5403831d35Sstevel * Invalidating the E$ tags is only needed on Cheetah following
5503831d35Sstevel * the manual displacement flush.  The internal flush ASI used by
5603831d35Sstevel * Cheetahplus, Jaguar, and Panther will invalidate the cache lines.
5703831d35Sstevel *
5803831d35Sstevel * arg1 = ecache_size
5903831d35Sstevel * arg2 = ecache_linesize
6003831d35Sstevel */
6103831d35Sstevel#define ECACHE_FLUSHTAGS(arg1, arg2, tmp1)			\
6203831d35Sstevel	GET_CPU_IMPL(tmp1)					;\
6303831d35Sstevel	srlx	arg1, 1, arg1					;\
6403831d35Sstevel	cmp	tmp1, CHEETAH_IMPL				;\
6503831d35Sstevel        bne	1f						;\
6603831d35Sstevel	nop							;\
6703831d35Sstevel	sub	arg1, arg2, tmp1				;\
6803831d35Sstevel0:								;\
6903831d35Sstevel        stxa    %g0, [tmp1]ASI_EC_DIAG				;\
7003831d35Sstevel        membar  #Sync						;\
7103831d35Sstevel        cmp     %g0, tmp1					;\
7203831d35Sstevel        bne,pt  %icc, 0b					;\
7303831d35Sstevel        sub     tmp1, arg2, tmp1				;\
7403831d35Sstevel1:
7503831d35Sstevel
7603831d35Sstevel
7703831d35Sstevel#define SWITCH_STACK(estk)                                      \
7803831d35Sstevel        flushw                                                  ;\
7903831d35Sstevel        sub     estk, SA(KFPUSIZE+GSR_SIZE), estk              ;\
8003831d35Sstevel        andn    estk, 0x3f, estk                                ;\
8103831d35Sstevel        sub     estk, SA(MINFRAME) + STACK_BIAS, %sp            ;\
8203831d35Sstevel        mov     estk, %fp
8303831d35Sstevel
8403831d35Sstevel/*
8503831d35Sstevel * Returns icache size and linesize in reg1 and reg2, respectively.
8603831d35Sstevel * Panther has a larger icache compared to Cheetahplus and Jaguar.
8703831d35Sstevel */
8803831d35Sstevel#define	GET_ICACHE_PARAMS(reg1, reg2)				\
8903831d35Sstevel	GET_CPU_IMPL(reg1)					;\
9003831d35Sstevel	cmp	reg1, PANTHER_IMPL				;\
9103831d35Sstevel	bne	%xcc, 1f					;\
9203831d35Sstevel	  nop							;\
9303831d35Sstevel	set	PN_ICACHE_SIZE, reg1				;\
9403831d35Sstevel	set	PN_ICACHE_LSIZE, reg2				;\
9503831d35Sstevel	ba	2f						;\
9603831d35Sstevel	  nop							;\
9703831d35Sstevel1:								;\
9803831d35Sstevel	set	CH_ICACHE_SIZE, reg1				;\
9903831d35Sstevel	set	CH_ICACHE_LSIZE, reg2				;\
10003831d35Sstevel2:
10103831d35Sstevel
10203831d35Sstevel        ENTRY_NP(sbdp_shutdown_asm)
10303831d35Sstevel        ! %o0 = address of sbdp_shutdown_t structure passed in
10403831d35Sstevel        !
10503831d35Sstevel        ! struct sbdp_shutdown {
10603831d35Sstevel        !       uint64_t        estack;    -> %o0
10703831d35Sstevel        !       uint64_t        flushaddr; -> %o1
10803831d35Sstevel        !       uint32_t        size;      -> %o2
10903831d35Sstevel        !       uint32_t        linesize;  -> %g1
11003831d35Sstevel        !       uint64_t        physaddr;  -> %o0
11103831d35Sstevel        ! } sbdp_shutdown_t;
11203831d35Sstevel        !
11303831d35Sstevel        membar  #LoadStore
11403831d35Sstevel        mov     %o0, %o4
11503831d35Sstevel        ldx     [%o4], %o0
11603831d35Sstevel        ldx     [%o4 + 8], %o1
11703831d35Sstevel        ld      [%o4 + 16], %o2
11803831d35Sstevel        ld      [%o4 + 20], %g1
11903831d35Sstevel
12003831d35Sstevel        !
12103831d35Sstevel        ! Switch stack pointer to bbsram
12203831d35Sstevel        !
12303831d35Sstevel        SWITCH_STACK(%o0)
12403831d35Sstevel
12503831d35Sstevel        ldx     [%o4 + 24], %o0 !save physaddr in %o0
12603831d35Sstevel        !
12703831d35Sstevel        ! Get some globals
12803831d35Sstevel        !
12903831d35Sstevel	! ecache_linesize already in %g1
13003831d35Sstevel
13103831d35Sstevel        sethi   %hi(dcache_linesize), %g2
13203831d35Sstevel        ld      [%g2 + %lo(dcache_linesize)], %g2
13303831d35Sstevel
13403831d35Sstevel        sethi   %hi(dcache_size), %g3
13503831d35Sstevel        ld      [%g3 + %lo(dcache_size)], %g3
13603831d35Sstevel
13703831d35Sstevel	!
13803831d35Sstevel	! Save the E$ size
13903831d35Sstevel	!
14003831d35Sstevel	mov	%o2, %o5
14103831d35Sstevel        !
14203831d35Sstevel        ! Flush E$
14303831d35Sstevel        !
14403831d35Sstevel        rdpr    %pstate, %o3
14503831d35Sstevel        andn    %o3, PSTATE_IE | PSTATE_AM, %o4
14603831d35Sstevel        wrpr    %g0, %o4, %pstate
14703831d35Sstevel
148*55fea89dSDan Cross	! Panther needs to flush L2 before L3 cache.
14903831d35Sstevel	PN_L2_FLUSHALL(%o4, %g4, %g5)
15003831d35Sstevel
15103831d35Sstevel        ECACHE_FLUSHALL(%o2, %g1, %o1, %o4)
15203831d35Sstevel
15303831d35Sstevel        wrpr    %g0, %o3, %pstate
15403831d35Sstevel
15503831d35Sstevel	!
15603831d35Sstevel	! Invalidate the E$ tags (Cheetah only).
15703831d35Sstevel	!
15803831d35Sstevel	ECACHE_FLUSHTAGS(%o5, %g1, %o3)
15903831d35Sstevel
16003831d35Sstevel        !
16103831d35Sstevel        ! %o2 & %o3 now available
16203831d35Sstevel        !
16303831d35Sstevel
16403831d35Sstevel        membar  #Sync
16503831d35Sstevel
16603831d35Sstevel        !
16703831d35Sstevel        ! Flush D$
16803831d35Sstevel        !
16903831d35Sstevel        CH_DCACHE_FLUSHALL(%g3, %g2, %o3)
17003831d35Sstevel
17103831d35Sstevel        !
17203831d35Sstevel        ! Flush I$
17303831d35Sstevel        !
17403831d35Sstevel	GET_ICACHE_PARAMS(%g5, %g4)
17503831d35Sstevel        CH_ICACHE_FLUSHALL(%g5, %g4, %o3, %o4)
17603831d35Sstevel
17703831d35Sstevel        membar  #Sync
17803831d35Sstevel
17903831d35Sstevel        !
18003831d35Sstevel        ! Flush all unlocked dtlb's & itlb's
18103831d35Sstevel        !
18203831d35Sstevel	sethi	%hi(FLUSH_ADDR), %g3
18303831d35Sstevel	set	DEMAP_ALL_TYPE, %g1
18403831d35Sstevel	stxa	%g0, [%g1]ASI_DTLB_DEMAP
18503831d35Sstevel	stxa	%g0, [%g1]ASI_ITLB_DEMAP
18603831d35Sstevel	flush	%g3
18703831d35Sstevel
18803831d35Sstevel	sir	0
18903831d35Sstevel        SET_SIZE(sbdp_shutdown_asm)
19003831d35Sstevel
19103831d35Sstevel        .global sbdp_shutdown_asm_end
19203831d35Sstevel
19303831d35Sstevel        .skip   2048
19403831d35Sstevel
19503831d35Sstevelsbdp_shutdown_asm_end:
19603831d35Sstevel
19703831d35Sstevel
19803831d35Sstevel#include "assym.h"
19903831d35Sstevel
20003831d35Sstevel#define	TT_HSM	0x99
20103831d35Sstevel
20203831d35Sstevel!
20303831d35Sstevel! Move a single cache line of data.  Survive UE and CE on the read
20403831d35Sstevel!
20503831d35Sstevel! i0 = src va
20603831d35Sstevel! i1 = dst va
20703831d35Sstevel! i2 = line count
20803831d35Sstevel! i3 = line size
20903831d35Sstevel! i4 = cache of fpu state
21003831d35Sstevel!
21103831d35Sstevel	ENTRY(sgdr_mem_blkcopy)
21203831d35Sstevel
21303831d35Sstevel	! TODO: can we safely SAVE here
21403831d35Sstevel	save	%sp, -SA(MINFRAME + 2*64), %sp
21503831d35Sstevel
21603831d35Sstevel	! XXX do we need to save the state of the fpu?
21703831d35Sstevel	rd	%fprs, %i4
21803831d35Sstevel	btst	(FPRS_DU|FPRS_DL|FPRS_FEF), %i4
21903831d35Sstevel
22003831d35Sstevel	! always enable FPU
22103831d35Sstevel	wr	%g0, FPRS_FEF, %fprs
22203831d35Sstevel
22303831d35Sstevel	bz,a	1f
22403831d35Sstevel	 nop
22503831d35Sstevel
22603831d35Sstevel	! save in-use fpregs on stack
22703831d35Sstevel	membar	#Sync
22803831d35Sstevel	add	%fp, STACK_BIAS - 81, %o2
22903831d35Sstevel	and	%o2, -64, %o2
23003831d35Sstevel	stda	%d0, [%o2]ASI_BLK_P
23103831d35Sstevel	membar	#Sync
23203831d35Sstevel
23303831d35Sstevel1:
23403831d35Sstevel	brz,pn	%i2, 2f				! while (linecount) {
23503831d35Sstevel	 nop
23603831d35Sstevel	ldda	[%i0]ASI_BLK_P, %d0		! *dst = *src;
23703831d35Sstevel	membar	#Sync
23803831d35Sstevel	stda	%d0, [%i1]ASI_BLK_COMMIT_P
23903831d35Sstevel	membar	#Sync
24003831d35Sstevel
24103831d35Sstevel	add	%i0, %i3, %i0			! dst++, src++;
24203831d35Sstevel	add	%i1, %i3, %i1
24303831d35Sstevel
24403831d35Sstevel	ba	1b				! linecount-- }
24503831d35Sstevel	 dec	%i2
24603831d35Sstevel
24703831d35Sstevel2:
24803831d35Sstevel	membar	#Sync
24903831d35Sstevel
25003831d35Sstevel	! restore fp to the way we got it
25103831d35Sstevel	btst	(FPRS_DU|FPRS_DL|FPRS_FEF), %i4
25203831d35Sstevel	bz,a	3f
25303831d35Sstevel	 nop
25403831d35Sstevel
25503831d35Sstevel	! restore fpregs from stack
25603831d35Sstevel	add	%fp, STACK_BIAS - 81, %o2
25703831d35Sstevel	and	%o2, -64, %o2
25803831d35Sstevel	ldda	[%o2]ASI_BLK_P, %d0
25903831d35Sstevel	membar	#Sync
26003831d35Sstevel
26103831d35Sstevel3:
26203831d35Sstevel	wr	%g0, %i4, %fprs			! fpu back to the way it was
26303831d35Sstevel	ret
26403831d35Sstevel	restore
26503831d35Sstevel	SET_SIZE(sgdr_mem_blkcopy)
26603831d35Sstevel
26703831d35Sstevel        ! Store long word value at mc regs
26803831d35Sstevel        !
26903831d35Sstevel        ! void  stdmcdecode(uint64_t physaddr, uint64_t value)
27003831d35Sstevel        !
27103831d35Sstevel        ENTRY(stdmcdecode)
27203831d35Sstevel        /*
27303831d35Sstevel         * disable interrupts, clear Address Mask to access 64 bit physaddr
27403831d35Sstevel         */
27503831d35Sstevel        rdpr    %pstate, %o4
27603831d35Sstevel        andn    %o4, PSTATE_IE | PSTATE_AM, %o5
27703831d35Sstevel        wrpr    %o5, 0, %pstate         ! clear IE, AM bits
27803831d35Sstevel        stxa    %o1, [%o0]ASI_MC_DECODE
27903831d35Sstevel	membar	#Sync
28003831d35Sstevel        retl
28103831d35Sstevel        wrpr    %g0, %o4, %pstate       ! restore earlier pstate register value
28203831d35Sstevel        SET_SIZE(stdmcdecode)
28303831d35Sstevel
284