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