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