wrsm_copy.s revision a83cadce5d3331b64803bfc641036cec23602c74
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#if !defined(lint)
#include <sys/asm_linkage.h>
#include <sys/privregs.h>
#include <sys/machthread.h>
#include <sys/machparam.h>
#include <sys/wrsm_intr.h>
#include <sys/wrsm_intr_impl.h>
#include <wrsm_offsets.h>
#endif /* lint */
#if defined(lint)
#else /* lint */
#include "assym.h"
#endif /* lint */
/*
* Pseudo-code to aid in understanding the control flow of the
* wrsm_blkwrite
*
* On entry:
*
* %l6 = curthread->t_lofault;
* if (%l6 != NULL) {
* curthread->t_lofault = .copyerr;
* caller_error_handler = TRUE ! %l6 |= 1
* }
*
* if (curthread->t_lwp == NULL) {
* ! Kernel threads do not have pcb's in which to store
* ! the floating point state, disallow preemption during
* ! the copy.
* kpreempt_disable(curthread);
* }
*
* old_fprs = %fprs;
* old_gsr = %gsr;
* if (%fprs.fef) {
* ! If we need to save 3 blocks of fpregs then make sure
* ! the length is still appropriate for that extra overhead.
* if (length < (large_length + (64 * 3))) {
* if (curthread->t_lwp == NULL)
* kpreempt_enable(curthread);
* goto regular_copy;
* }
* %fprs.fef = 1;
* save current fpregs on stack using blockstore
* } else {
* %fprs.fef = 1;
* }
*
* if (length < HW_THRESHOLD)
* goto slow_copy;
*
*
* do blockcopy or slow_copy here;
*
*
* On exit (in lofault handler as well):
*
* %gsr = old_gsr;
* if (old_fprs & FPRS_FEF)
* restore fpregs from stack using blockload
* else
* zero fpregs
* %fprs = old_fprs;
* if (curthread->t_lwp == NULL)
* kpreempt_enable(curthread);
* curthread->t_lofault = (%l6 & ~1);
* return (0)
*/
/*
* Number of bytes needed to "break even" using VIS-accelerated
* memory operations.
*/
#define HW_THRESHOLD 256
/*
* Number of outstanding prefetches. 5 seems to be a good number
* right now.
*/
#define CHEETAH_PREFETCH 5
/*
* Size of stack frame in order to accomodate a 64-byte aligned
* floating-point register save area and 2 64-bit temp locations.
*/
#define VIS_BLOCKSIZE 64
/*
* Common macros used by the various versions of the block copy
* routines in this file.
*/
/*
* Zero the parts of the fpreg file that we actually use
* ( 2 or 3 sets of 8 registers )
*/
#define FZERO3 \
#define FZERO2 \
/*
* Copy a block of storage, returning an error code if `from' or
* `to' takes a kernel pagefault which cannot be resolved.
* Returns errno value on pagefault error, 0 if all ok
*/
#if defined(lint)
/* ARGSUSED */
void
{}
#else /* lint */
.seg ".text"
.align 4
/*
* We got here because of a fault during kcopy.
* Errno value is in %g1.
*/
.copyerr:
bz 4f
ba 2f
4:
1:
3:
.do_copy:
! kpreempt_disable();
1:
bz,a .do_blockcopy
#if CHEETAH_PREFETCH >= 4
#endif
#if CHEETAH_PREFETCH >= 5
#endif
#if CHEETAH_PREFETCH >= 6
#endif
#if CHEETAH_PREFETCH >= 7
#endif
.align 32
1:
3:
ba 4f
2:
ba 4f
4:
bz 4f
ba 2f
4:
1:
ba 1b
ba 3b
#endif /* lint */
/*
* wrsm_blkread
*
* disable preemption
* if FPREGS need to be saved, save them
* check alignment:
* if (64 alignment) go to loop 3
* if (8 alinment) go to loop 2
* else
* if done, go to exit
* block load 64 bytes into FPREGS
* store 64 bytes on the stack
* load 8 bytes into %l0
* store byte by byte
* repeat
*
* loop 2:
* if done, go to exit
* block load 64 bytes into FPREGS
* store the 8 - 8 byte values from FPREGS to mem
* repeat
*
* loop 3:
* if done, go to exit
* block load 64 bytes into FPREGS
* block store 64 bytes to memory
* repeat
*
* exit:
* restore FPREGS or clear them
* check for preemption requests
* return
*/
/* we need to save two blocks of 8 registers on the stack + alignment */
/* where we put FPREGS */
/* where we put data on stack during byte copy */
#if defined(lint)
/* ARGSUSED */
void
{}
#else /* !lint */
!
!
! %i2 = num_blocks
!
!
! kpreempt_disable();
bz,a 1f
.loop1:
.loop2:
.loop3:
bz,a 3f
ba 4f
3:
4: ! kpreempt_enable();
5: ret
#endif /* lint */