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