17c478bd9Sstevel@tonic-gate/* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5651ee059Siskreen * Common Development and Distribution License (the "License"). 6651ee059Siskreen * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate/* 22651ee059Siskreen * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 26*c2b6e926Sae112802# ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate#include <sys/param.h> 297c478bd9Sstevel@tonic-gate#include <sys/errno.h> 307c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h> 317c478bd9Sstevel@tonic-gate#include <sys/vtrace.h> 327c478bd9Sstevel@tonic-gate#include <sys/machthread.h> 337c478bd9Sstevel@tonic-gate#include <sys/clock.h> 347c478bd9Sstevel@tonic-gate#include <sys/asi.h> 357c478bd9Sstevel@tonic-gate#include <sys/fsr.h> 367c478bd9Sstevel@tonic-gate#include <sys/privregs.h> 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate#if !defined(lint) 397c478bd9Sstevel@tonic-gate#include "assym.h" 407c478bd9Sstevel@tonic-gate#endif /* lint */ 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate/* 447c478bd9Sstevel@tonic-gate * Less then or equal this number of bytes we will always copy byte-for-byte 457c478bd9Sstevel@tonic-gate */ 467c478bd9Sstevel@tonic-gate#define SMALL_LIMIT 7 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate/* 49473b13d4Sae112802 * LOFAULT_SET : Flag set by kzero and kcopy to indicate that t_lofault 50473b13d4Sae112802 * handler was set 517c478bd9Sstevel@tonic-gate */ 527c478bd9Sstevel@tonic-gate#define LOFAULT_SET 2 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate/* 567c478bd9Sstevel@tonic-gate * Copy a block of storage, returning an error code if `from' or 577c478bd9Sstevel@tonic-gate * `to' takes a kernel pagefault which cannot be resolved. 587c478bd9Sstevel@tonic-gate * Returns errno value on pagefault error, 0 if all ok 597c478bd9Sstevel@tonic-gate */ 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate#if defined(lint) 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate/* ARGSUSED */ 667c478bd9Sstevel@tonic-gateint 677c478bd9Sstevel@tonic-gatekcopy(const void *from, void *to, size_t count) 687c478bd9Sstevel@tonic-gate{ return(0); } 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate#else /* lint */ 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate .seg ".text" 737c478bd9Sstevel@tonic-gate .align 4 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate ENTRY(kcopy) 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate save %sp, -SA(MINFRAME), %sp 78473b13d4Sae112802 set .copyerr, %l7 ! copyerr is lofault value 79473b13d4Sae112802 ldn [THREAD_REG + T_LOFAULT], %o5 ! save existing handler 80473b13d4Sae112802 or %o5, LOFAULT_SET, %o5 81473b13d4Sae112802 membar #Sync ! sync error barrier 827c478bd9Sstevel@tonic-gate b .do_copy ! common code 83473b13d4Sae112802 stn %l7, [THREAD_REG + T_LOFAULT] ! set t_lofault 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate/* 867c478bd9Sstevel@tonic-gate * We got here because of a fault during kcopy. 877c478bd9Sstevel@tonic-gate * Errno value is in %g1. 887c478bd9Sstevel@tonic-gate */ 897c478bd9Sstevel@tonic-gate.copyerr: 90473b13d4Sae112802 ! The kcopy() *always* sets a t_lofault handler and it ORs LOFAULT_SET 91473b13d4Sae112802 ! into %o5 to indicate it has set t_lofault handler. Need to clear 92473b13d4Sae112802 ! LOFAULT_SET flag before restoring the error handler. 93473b13d4Sae112802 andn %o5, LOFAULT_SET, %o5 947c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 957c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] ! restore old t_lofault 967c478bd9Sstevel@tonic-gate ret 977c478bd9Sstevel@tonic-gate restore %g1, 0, %o0 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate SET_SIZE(kcopy) 1007c478bd9Sstevel@tonic-gate#endif /* lint */ 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate/* 1047c478bd9Sstevel@tonic-gate * Copy a block of storage - must not overlap (from + len <= to). 1057c478bd9Sstevel@tonic-gate */ 1067c478bd9Sstevel@tonic-gate#if defined(lint) 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate/* ARGSUSED */ 1097c478bd9Sstevel@tonic-gatevoid 1107c478bd9Sstevel@tonic-gatebcopy(const void *from, void *to, size_t count) 1117c478bd9Sstevel@tonic-gate{} 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate#else /* lint */ 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate ENTRY(bcopy) 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate save %sp, -SA(MINFRAME), %sp 118473b13d4Sae112802 clr %o5 ! flag LOFAULT_SET is not set for bcopy 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate.do_copy: 121651ee059Siskreen mov %i1, %g5 ! save dest addr start 122651ee059Siskreen 123651ee059Siskreen mov %i2, %l6 ! save size 124651ee059Siskreen 1257c478bd9Sstevel@tonic-gate cmp %i2, 12 ! for small counts 1267c478bd9Sstevel@tonic-gate blu %ncc, .bytecp ! just copy bytes 1277c478bd9Sstevel@tonic-gate .empty 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate ! 1307c478bd9Sstevel@tonic-gate ! use aligned transfers where possible 1317c478bd9Sstevel@tonic-gate ! 1327c478bd9Sstevel@tonic-gate xor %i0, %i1, %o4 ! xor from and to address 1337c478bd9Sstevel@tonic-gate btst 7, %o4 ! if lower three bits zero 1347c478bd9Sstevel@tonic-gate bz .aldoubcp ! can align on double boundary 1357c478bd9Sstevel@tonic-gate .empty ! assembler complaints about label 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate xor %i0, %i1, %o4 ! xor from and to address 1387c478bd9Sstevel@tonic-gate btst 3, %o4 ! if lower two bits zero 1397c478bd9Sstevel@tonic-gate bz .alwordcp ! can align on word boundary 1407c478bd9Sstevel@tonic-gate btst 3, %i0 ! delay slot, from address unaligned? 1417c478bd9Sstevel@tonic-gate ! 1427c478bd9Sstevel@tonic-gate ! use aligned reads and writes where possible 1437c478bd9Sstevel@tonic-gate ! this differs from wordcp in that it copes 1447c478bd9Sstevel@tonic-gate ! with odd alignment between source and destnation 1457c478bd9Sstevel@tonic-gate ! using word reads and writes with the proper shifts 1467c478bd9Sstevel@tonic-gate ! in between to align transfers to and from memory 1477c478bd9Sstevel@tonic-gate ! i0 - src address, i1 - dest address, i2 - count 1487c478bd9Sstevel@tonic-gate ! i3, i4 - tmps for used generating complete word 1497c478bd9Sstevel@tonic-gate ! i5 (word to write) 1507c478bd9Sstevel@tonic-gate ! l0 size in bits of upper part of source word (US) 1517c478bd9Sstevel@tonic-gate ! l1 size in bits of lower part of source word (LS = 32 - US) 1527c478bd9Sstevel@tonic-gate ! l2 size in bits of upper part of destination word (UD) 1537c478bd9Sstevel@tonic-gate ! l3 size in bits of lower part of destination word (LD = 32 - UD) 1547c478bd9Sstevel@tonic-gate ! l4 number of bytes leftover after aligned transfers complete 1557c478bd9Sstevel@tonic-gate ! l5 the number 32 1567c478bd9Sstevel@tonic-gate ! 1577c478bd9Sstevel@tonic-gate mov 32, %l5 ! load an oft-needed constant 1587c478bd9Sstevel@tonic-gate bz .align_dst_only 1597c478bd9Sstevel@tonic-gate btst 3, %i1 ! is destnation address aligned? 1607c478bd9Sstevel@tonic-gate clr %i4 ! clear registers used in either case 1617c478bd9Sstevel@tonic-gate bz .align_src_only 1627c478bd9Sstevel@tonic-gate clr %l0 1637c478bd9Sstevel@tonic-gate ! 1647c478bd9Sstevel@tonic-gate ! both source and destination addresses are unaligned 1657c478bd9Sstevel@tonic-gate ! 1667c478bd9Sstevel@tonic-gate1: ! align source 1677c478bd9Sstevel@tonic-gate ldub [%i0], %i3 ! read a byte from source address 1687c478bd9Sstevel@tonic-gate add %i0, 1, %i0 ! increment source address 1697c478bd9Sstevel@tonic-gate or %i4, %i3, %i4 ! or in with previous bytes (if any) 1707c478bd9Sstevel@tonic-gate btst 3, %i0 ! is source aligned? 1717c478bd9Sstevel@tonic-gate add %l0, 8, %l0 ! increment size of upper source (US) 1727c478bd9Sstevel@tonic-gate bnz,a 1b 1737c478bd9Sstevel@tonic-gate sll %i4, 8, %i4 ! make room for next byte 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate sub %l5, %l0, %l1 ! generate shift left count (LS) 1767c478bd9Sstevel@tonic-gate sll %i4, %l1, %i4 ! prepare to get rest 1777c478bd9Sstevel@tonic-gate ld [%i0], %i3 ! read a word 1787c478bd9Sstevel@tonic-gate add %i0, 4, %i0 ! increment source address 1797c478bd9Sstevel@tonic-gate srl %i3, %l0, %i5 ! upper src bits into lower dst bits 1807c478bd9Sstevel@tonic-gate or %i4, %i5, %i5 ! merge 1817c478bd9Sstevel@tonic-gate mov 24, %l3 ! align destination 1827c478bd9Sstevel@tonic-gate1: 1837c478bd9Sstevel@tonic-gate srl %i5, %l3, %i4 ! prepare to write a single byte 1847c478bd9Sstevel@tonic-gate stb %i4, [%i1] ! write a byte 1857c478bd9Sstevel@tonic-gate add %i1, 1, %i1 ! increment destination address 1867c478bd9Sstevel@tonic-gate sub %i2, 1, %i2 ! decrement count 1877c478bd9Sstevel@tonic-gate btst 3, %i1 ! is destination aligned? 1887c478bd9Sstevel@tonic-gate bnz,a 1b 1897c478bd9Sstevel@tonic-gate sub %l3, 8, %l3 ! delay slot, decrement shift count (LD) 1907c478bd9Sstevel@tonic-gate sub %l5, %l3, %l2 ! generate shift left count (UD) 1917c478bd9Sstevel@tonic-gate sll %i5, %l2, %i5 ! move leftover into upper bytes 1927c478bd9Sstevel@tonic-gate cmp %l2, %l0 ! cmp # reqd to fill dst w old src left 1937c478bd9Sstevel@tonic-gate bgu %ncc, .more_needed ! need more to fill than we have 1947c478bd9Sstevel@tonic-gate nop 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate sll %i3, %l1, %i3 ! clear upper used byte(s) 1977c478bd9Sstevel@tonic-gate srl %i3, %l1, %i3 1987c478bd9Sstevel@tonic-gate ! get the odd bytes between alignments 1997c478bd9Sstevel@tonic-gate sub %l0, %l2, %l0 ! regenerate shift count 2007c478bd9Sstevel@tonic-gate sub %l5, %l0, %l1 ! generate new shift left count (LS) 2017c478bd9Sstevel@tonic-gate and %i2, 3, %l4 ! must do remaining bytes if count%4 > 0 2027c478bd9Sstevel@tonic-gate andn %i2, 3, %i2 ! # of aligned bytes that can be moved 2037c478bd9Sstevel@tonic-gate srl %i3, %l0, %i4 2047c478bd9Sstevel@tonic-gate or %i5, %i4, %i5 2057c478bd9Sstevel@tonic-gate st %i5, [%i1] ! write a word 2067c478bd9Sstevel@tonic-gate subcc %i2, 4, %i2 ! decrement count 2077c478bd9Sstevel@tonic-gate bz %ncc, .unalign_out 2087c478bd9Sstevel@tonic-gate add %i1, 4, %i1 ! increment destination address 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate b 2f 2117c478bd9Sstevel@tonic-gate sll %i3, %l1, %i5 ! get leftover into upper bits 2127c478bd9Sstevel@tonic-gate.more_needed: 2137c478bd9Sstevel@tonic-gate sll %i3, %l0, %i3 ! save remaining byte(s) 2147c478bd9Sstevel@tonic-gate srl %i3, %l0, %i3 2157c478bd9Sstevel@tonic-gate sub %l2, %l0, %l1 ! regenerate shift count 2167c478bd9Sstevel@tonic-gate sub %l5, %l1, %l0 ! generate new shift left count 2177c478bd9Sstevel@tonic-gate sll %i3, %l1, %i4 ! move to fill empty space 2187c478bd9Sstevel@tonic-gate b 3f 2197c478bd9Sstevel@tonic-gate or %i5, %i4, %i5 ! merge to complete word 2207c478bd9Sstevel@tonic-gate ! 2217c478bd9Sstevel@tonic-gate ! the source address is aligned and destination is not 2227c478bd9Sstevel@tonic-gate ! 2237c478bd9Sstevel@tonic-gate.align_dst_only: 2247c478bd9Sstevel@tonic-gate ld [%i0], %i4 ! read a word 2257c478bd9Sstevel@tonic-gate add %i0, 4, %i0 ! increment source address 2267c478bd9Sstevel@tonic-gate mov 24, %l0 ! initial shift alignment count 2277c478bd9Sstevel@tonic-gate1: 2287c478bd9Sstevel@tonic-gate srl %i4, %l0, %i3 ! prepare to write a single byte 2297c478bd9Sstevel@tonic-gate stb %i3, [%i1] ! write a byte 2307c478bd9Sstevel@tonic-gate add %i1, 1, %i1 ! increment destination address 2317c478bd9Sstevel@tonic-gate sub %i2, 1, %i2 ! decrement count 2327c478bd9Sstevel@tonic-gate btst 3, %i1 ! is destination aligned? 2337c478bd9Sstevel@tonic-gate bnz,a 1b 2347c478bd9Sstevel@tonic-gate sub %l0, 8, %l0 ! delay slot, decrement shift count 2357c478bd9Sstevel@tonic-gate.xfer: 2367c478bd9Sstevel@tonic-gate sub %l5, %l0, %l1 ! generate shift left count 2377c478bd9Sstevel@tonic-gate sll %i4, %l1, %i5 ! get leftover 2387c478bd9Sstevel@tonic-gate3: 2397c478bd9Sstevel@tonic-gate and %i2, 3, %l4 ! must do remaining bytes if count%4 > 0 2407c478bd9Sstevel@tonic-gate andn %i2, 3, %i2 ! # of aligned bytes that can be moved 2417c478bd9Sstevel@tonic-gate2: 2427c478bd9Sstevel@tonic-gate ld [%i0], %i3 ! read a source word 2437c478bd9Sstevel@tonic-gate add %i0, 4, %i0 ! increment source address 2447c478bd9Sstevel@tonic-gate srl %i3, %l0, %i4 ! upper src bits into lower dst bits 2457c478bd9Sstevel@tonic-gate or %i5, %i4, %i5 ! merge with upper dest bits (leftover) 2467c478bd9Sstevel@tonic-gate st %i5, [%i1] ! write a destination word 2477c478bd9Sstevel@tonic-gate subcc %i2, 4, %i2 ! decrement count 2487c478bd9Sstevel@tonic-gate bz %ncc, .unalign_out ! check if done 2497c478bd9Sstevel@tonic-gate add %i1, 4, %i1 ! increment destination address 2507c478bd9Sstevel@tonic-gate b 2b ! loop 2517c478bd9Sstevel@tonic-gate sll %i3, %l1, %i5 ! get leftover 2527c478bd9Sstevel@tonic-gate.unalign_out: 2537c478bd9Sstevel@tonic-gate tst %l4 ! any bytes leftover? 2547c478bd9Sstevel@tonic-gate bz %ncc, .cpdone 2557c478bd9Sstevel@tonic-gate .empty ! allow next instruction in delay slot 2567c478bd9Sstevel@tonic-gate1: 2577c478bd9Sstevel@tonic-gate sub %l0, 8, %l0 ! decrement shift 2587c478bd9Sstevel@tonic-gate srl %i3, %l0, %i4 ! upper src byte into lower dst byte 2597c478bd9Sstevel@tonic-gate stb %i4, [%i1] ! write a byte 2607c478bd9Sstevel@tonic-gate subcc %l4, 1, %l4 ! decrement count 2617c478bd9Sstevel@tonic-gate bz %ncc, .cpdone ! done? 2627c478bd9Sstevel@tonic-gate add %i1, 1, %i1 ! increment destination 2637c478bd9Sstevel@tonic-gate tst %l0 ! any more previously read bytes 2647c478bd9Sstevel@tonic-gate bnz %ncc, 1b ! we have leftover bytes 2657c478bd9Sstevel@tonic-gate mov %l4, %i2 ! delay slot, mv cnt where dbytecp wants 2667c478bd9Sstevel@tonic-gate b .dbytecp ! let dbytecp do the rest 2677c478bd9Sstevel@tonic-gate sub %i0, %i1, %i0 ! i0 gets the difference of src and dst 2687c478bd9Sstevel@tonic-gate ! 2697c478bd9Sstevel@tonic-gate ! the destination address is aligned and the source is not 2707c478bd9Sstevel@tonic-gate ! 2717c478bd9Sstevel@tonic-gate.align_src_only: 2727c478bd9Sstevel@tonic-gate ldub [%i0], %i3 ! read a byte from source address 2737c478bd9Sstevel@tonic-gate add %i0, 1, %i0 ! increment source address 2747c478bd9Sstevel@tonic-gate or %i4, %i3, %i4 ! or in with previous bytes (if any) 2757c478bd9Sstevel@tonic-gate btst 3, %i0 ! is source aligned? 2767c478bd9Sstevel@tonic-gate add %l0, 8, %l0 ! increment shift count (US) 2777c478bd9Sstevel@tonic-gate bnz,a .align_src_only 2787c478bd9Sstevel@tonic-gate sll %i4, 8, %i4 ! make room for next byte 2797c478bd9Sstevel@tonic-gate b,a .xfer 2807c478bd9Sstevel@tonic-gate ! 2817c478bd9Sstevel@tonic-gate ! if from address unaligned for double-word moves, 2827c478bd9Sstevel@tonic-gate ! move bytes till it is, if count is < 56 it could take 2837c478bd9Sstevel@tonic-gate ! longer to align the thing than to do the transfer 2847c478bd9Sstevel@tonic-gate ! in word size chunks right away 2857c478bd9Sstevel@tonic-gate ! 2867c478bd9Sstevel@tonic-gate.aldoubcp: 2877c478bd9Sstevel@tonic-gate cmp %i2, 56 ! if count < 56, use wordcp, it takes 2887c478bd9Sstevel@tonic-gate blu,a %ncc, .alwordcp ! longer to align doubles than words 2897c478bd9Sstevel@tonic-gate mov 3, %o0 ! mask for word alignment 2907c478bd9Sstevel@tonic-gate call .alignit ! copy bytes until aligned 2917c478bd9Sstevel@tonic-gate mov 7, %o0 ! mask for double alignment 2927c478bd9Sstevel@tonic-gate ! 2937c478bd9Sstevel@tonic-gate ! source and destination are now double-word aligned 2947c478bd9Sstevel@tonic-gate ! i3 has aligned count returned by alignit 2957c478bd9Sstevel@tonic-gate ! 2967c478bd9Sstevel@tonic-gate and %i2, 7, %i2 ! unaligned leftover count 2977c478bd9Sstevel@tonic-gate sub %i0, %i1, %i0 ! i0 gets the difference of src and dst 2987c478bd9Sstevel@tonic-gate5: 2997c478bd9Sstevel@tonic-gate ldx [%i0+%i1], %o4 ! read from address 3007c478bd9Sstevel@tonic-gate stx %o4, [%i1] ! write at destination address 3017c478bd9Sstevel@tonic-gate subcc %i3, 8, %i3 ! dec count 3027c478bd9Sstevel@tonic-gate bgu %ncc, 5b 3037c478bd9Sstevel@tonic-gate add %i1, 8, %i1 ! delay slot, inc to address 3047c478bd9Sstevel@tonic-gate cmp %i2, 4 ! see if we can copy a word 3057c478bd9Sstevel@tonic-gate blu %ncc, .dbytecp ! if 3 or less bytes use bytecp 3067c478bd9Sstevel@tonic-gate .empty 3077c478bd9Sstevel@tonic-gate ! 3087c478bd9Sstevel@tonic-gate ! for leftover bytes we fall into wordcp, if needed 3097c478bd9Sstevel@tonic-gate ! 3107c478bd9Sstevel@tonic-gate.wordcp: 3117c478bd9Sstevel@tonic-gate and %i2, 3, %i2 ! unaligned leftover count 3127c478bd9Sstevel@tonic-gate5: 3137c478bd9Sstevel@tonic-gate ld [%i0+%i1], %o4 ! read from address 3147c478bd9Sstevel@tonic-gate st %o4, [%i1] ! write at destination address 3157c478bd9Sstevel@tonic-gate subcc %i3, 4, %i3 ! dec count 3167c478bd9Sstevel@tonic-gate bgu %ncc, 5b 3177c478bd9Sstevel@tonic-gate add %i1, 4, %i1 ! delay slot, inc to address 3187c478bd9Sstevel@tonic-gate b,a .dbytecp 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate ! we come here to align copies on word boundaries 3217c478bd9Sstevel@tonic-gate.alwordcp: 3227c478bd9Sstevel@tonic-gate call .alignit ! go word-align it 3237c478bd9Sstevel@tonic-gate mov 3, %o0 ! bits that must be zero to be aligned 3247c478bd9Sstevel@tonic-gate b .wordcp 3257c478bd9Sstevel@tonic-gate sub %i0, %i1, %i0 ! i0 gets the difference of src and dst 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate ! 3287c478bd9Sstevel@tonic-gate ! byte copy, works with any alignment 3297c478bd9Sstevel@tonic-gate ! 3307c478bd9Sstevel@tonic-gate.bytecp: 3317c478bd9Sstevel@tonic-gate b .dbytecp 3327c478bd9Sstevel@tonic-gate sub %i0, %i1, %i0 ! i0 gets difference of src and dst 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate ! 3357c478bd9Sstevel@tonic-gate ! differenced byte copy, works with any alignment 3367c478bd9Sstevel@tonic-gate ! assumes dest in %i1 and (source - dest) in %i0 3377c478bd9Sstevel@tonic-gate ! 3387c478bd9Sstevel@tonic-gate1: 3397c478bd9Sstevel@tonic-gate stb %o4, [%i1] ! write to address 3407c478bd9Sstevel@tonic-gate inc %i1 ! inc to address 3417c478bd9Sstevel@tonic-gate.dbytecp: 3427c478bd9Sstevel@tonic-gate deccc %i2 ! dec count 3437c478bd9Sstevel@tonic-gate bgeu,a %ncc, 1b ! loop till done 3447c478bd9Sstevel@tonic-gate ldub [%i0+%i1], %o4 ! read from address 3457c478bd9Sstevel@tonic-gate.cpdone: 3467c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 347473b13d4Sae112802 ! Restore t_lofault handler, if came here from kcopy(). 348473b13d4Sae112802 tst %o5 349473b13d4Sae112802 bz %ncc, 1f 350473b13d4Sae112802 andn %o5, LOFAULT_SET, %o5 351473b13d4Sae112802 stn %o5, [THREAD_REG + T_LOFAULT] ! restore old t_lofault 352473b13d4Sae1128021: 353651ee059Siskreen mov %g5, %o0 ! copy dest address 354651ee059Siskreen call sync_icache 355651ee059Siskreen mov %l6, %o1 ! saved size 3567c478bd9Sstevel@tonic-gate ret 3577c478bd9Sstevel@tonic-gate restore %g0, 0, %o0 ! return (0) 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate/* 3607c478bd9Sstevel@tonic-gate * Common code used to align transfers on word and doubleword 3617c478bd9Sstevel@tonic-gate * boudaries. Aligns source and destination and returns a count 3627c478bd9Sstevel@tonic-gate * of aligned bytes to transfer in %i3 3637c478bd9Sstevel@tonic-gate */ 3647c478bd9Sstevel@tonic-gate1: 3657c478bd9Sstevel@tonic-gate inc %i0 ! inc from 3667c478bd9Sstevel@tonic-gate stb %o4, [%i1] ! write a byte 3677c478bd9Sstevel@tonic-gate inc %i1 ! inc to 3687c478bd9Sstevel@tonic-gate dec %i2 ! dec count 3697c478bd9Sstevel@tonic-gate.alignit: 3707c478bd9Sstevel@tonic-gate btst %o0, %i0 ! %o0 is bit mask to check for alignment 3717c478bd9Sstevel@tonic-gate bnz,a 1b 3727c478bd9Sstevel@tonic-gate ldub [%i0], %o4 ! read next byte 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate retl 3757c478bd9Sstevel@tonic-gate andn %i2, %o0, %i3 ! return size of aligned bytes 3767c478bd9Sstevel@tonic-gate SET_SIZE(bcopy) 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate#endif /* lint */ 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate/* 3817c478bd9Sstevel@tonic-gate * Block copy with possibly overlapped operands. 3827c478bd9Sstevel@tonic-gate */ 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate#if defined(lint) 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 3877c478bd9Sstevel@tonic-gatevoid 3887c478bd9Sstevel@tonic-gateovbcopy(const void *from, void *to, size_t count) 3897c478bd9Sstevel@tonic-gate{} 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate#else /* lint */ 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate ENTRY(ovbcopy) 3947c478bd9Sstevel@tonic-gate tst %o2 ! check count 3957c478bd9Sstevel@tonic-gate bgu,a %ncc, 1f ! nothing to do or bad arguments 3967c478bd9Sstevel@tonic-gate subcc %o0, %o1, %o3 ! difference of from and to address 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate retl ! return 3997c478bd9Sstevel@tonic-gate nop 4007c478bd9Sstevel@tonic-gate1: 4017c478bd9Sstevel@tonic-gate bneg,a %ncc, 2f 4027c478bd9Sstevel@tonic-gate neg %o3 ! if < 0, make it positive 4037c478bd9Sstevel@tonic-gate2: cmp %o2, %o3 ! cmp size and abs(from - to) 4047c478bd9Sstevel@tonic-gate bleu %ncc, bcopy ! if size <= abs(diff): use bcopy, 4057c478bd9Sstevel@tonic-gate .empty ! no overlap 4067c478bd9Sstevel@tonic-gate cmp %o0, %o1 ! compare from and to addresses 4077c478bd9Sstevel@tonic-gate blu %ncc, .ov_bkwd ! if from < to, copy backwards 4087c478bd9Sstevel@tonic-gate nop 4097c478bd9Sstevel@tonic-gate ! 4107c478bd9Sstevel@tonic-gate ! Copy forwards. 4117c478bd9Sstevel@tonic-gate ! 4127c478bd9Sstevel@tonic-gate.ov_fwd: 4137c478bd9Sstevel@tonic-gate ldub [%o0], %o3 ! read from address 4147c478bd9Sstevel@tonic-gate inc %o0 ! inc from address 4157c478bd9Sstevel@tonic-gate stb %o3, [%o1] ! write to address 4167c478bd9Sstevel@tonic-gate deccc %o2 ! dec count 4177c478bd9Sstevel@tonic-gate bgu %ncc, .ov_fwd ! loop till done 4187c478bd9Sstevel@tonic-gate inc %o1 ! inc to address 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate retl ! return 4217c478bd9Sstevel@tonic-gate nop 4227c478bd9Sstevel@tonic-gate ! 4237c478bd9Sstevel@tonic-gate ! Copy backwards. 4247c478bd9Sstevel@tonic-gate ! 4257c478bd9Sstevel@tonic-gate.ov_bkwd: 4267c478bd9Sstevel@tonic-gate deccc %o2 ! dec count 4277c478bd9Sstevel@tonic-gate ldub [%o0 + %o2], %o3 ! get byte at end of src 4287c478bd9Sstevel@tonic-gate bgu %ncc, .ov_bkwd ! loop till done 4297c478bd9Sstevel@tonic-gate stb %o3, [%o1 + %o2] ! delay slot, store at end of dst 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate retl ! return 4327c478bd9Sstevel@tonic-gate nop 4337c478bd9Sstevel@tonic-gate SET_SIZE(ovbcopy) 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate#endif /* lint */ 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate/* 4387c478bd9Sstevel@tonic-gate * hwblkpagecopy() 4397c478bd9Sstevel@tonic-gate * 4407c478bd9Sstevel@tonic-gate * Copies exactly one page. This routine assumes the caller (ppcopy) 4417c478bd9Sstevel@tonic-gate * has already disabled kernel preemption and has checked 4427c478bd9Sstevel@tonic-gate * use_hw_bcopy. 4437c478bd9Sstevel@tonic-gate */ 4447c478bd9Sstevel@tonic-gate#ifdef lint 4457c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 4467c478bd9Sstevel@tonic-gatevoid 4477c478bd9Sstevel@tonic-gatehwblkpagecopy(const void *src, void *dst) 4487c478bd9Sstevel@tonic-gate{ } 4497c478bd9Sstevel@tonic-gate#else /* lint */ 4507c478bd9Sstevel@tonic-gate ENTRY(hwblkpagecopy) 4517c478bd9Sstevel@tonic-gate save %sp, -SA(MINFRAME), %sp 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate ! %i0 - source address (arg) 4547c478bd9Sstevel@tonic-gate ! %i1 - destination address (arg) 4557c478bd9Sstevel@tonic-gate ! %i2 - length of region (not arg) 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate set PAGESIZE, %i2 458651ee059Siskreen mov %i1, %o0 ! store destination address for flushing 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate /* 4617c478bd9Sstevel@tonic-gate * Copying exactly one page and PAGESIZE is in mutliple of 0x80. 4627c478bd9Sstevel@tonic-gate */ 4637c478bd9Sstevel@tonic-gate1: 4647c478bd9Sstevel@tonic-gate ldx [%i0+0x0], %l0 4657c478bd9Sstevel@tonic-gate ldx [%i0+0x8], %l1 4667c478bd9Sstevel@tonic-gate ldx [%i0+0x10], %l2 4677c478bd9Sstevel@tonic-gate ldx [%i0+0x18], %l3 4687c478bd9Sstevel@tonic-gate ldx [%i0+0x20], %l4 4697c478bd9Sstevel@tonic-gate ldx [%i0+0x28], %l5 4707c478bd9Sstevel@tonic-gate ldx [%i0+0x30], %l6 4717c478bd9Sstevel@tonic-gate ldx [%i0+0x38], %l7 4727c478bd9Sstevel@tonic-gate stx %l0, [%i1+0x0] 4737c478bd9Sstevel@tonic-gate stx %l1, [%i1+0x8] 4747c478bd9Sstevel@tonic-gate stx %l2, [%i1+0x10] 4757c478bd9Sstevel@tonic-gate stx %l3, [%i1+0x18] 4767c478bd9Sstevel@tonic-gate stx %l4, [%i1+0x20] 4777c478bd9Sstevel@tonic-gate stx %l5, [%i1+0x28] 4787c478bd9Sstevel@tonic-gate stx %l6, [%i1+0x30] 4797c478bd9Sstevel@tonic-gate stx %l7, [%i1+0x38] 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate ldx [%i0+0x40], %l0 4827c478bd9Sstevel@tonic-gate ldx [%i0+0x48], %l1 4837c478bd9Sstevel@tonic-gate ldx [%i0+0x50], %l2 4847c478bd9Sstevel@tonic-gate ldx [%i0+0x58], %l3 4857c478bd9Sstevel@tonic-gate ldx [%i0+0x60], %l4 4867c478bd9Sstevel@tonic-gate ldx [%i0+0x68], %l5 4877c478bd9Sstevel@tonic-gate ldx [%i0+0x70], %l6 4887c478bd9Sstevel@tonic-gate ldx [%i0+0x78], %l7 4897c478bd9Sstevel@tonic-gate stx %l0, [%i1+0x40] 4907c478bd9Sstevel@tonic-gate stx %l1, [%i1+0x48] 4917c478bd9Sstevel@tonic-gate stx %l2, [%i1+0x50] 4927c478bd9Sstevel@tonic-gate stx %l3, [%i1+0x58] 4937c478bd9Sstevel@tonic-gate stx %l4, [%i1+0x60] 4947c478bd9Sstevel@tonic-gate stx %l5, [%i1+0x68] 4957c478bd9Sstevel@tonic-gate stx %l6, [%i1+0x70] 4967c478bd9Sstevel@tonic-gate stx %l7, [%i1+0x78] 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate add %i0, 0x80, %i0 4997c478bd9Sstevel@tonic-gate subcc %i2, 0x80, %i2 5007c478bd9Sstevel@tonic-gate bgu,pt %xcc, 1b 5017c478bd9Sstevel@tonic-gate add %i1, 0x80, %i1 5027c478bd9Sstevel@tonic-gate 503651ee059Siskreen ! %o0 contains the dest. address 504651ee059Siskreen set PAGESIZE, %o1 505651ee059Siskreen call sync_icache 506651ee059Siskreen nop 507651ee059Siskreen 5087c478bd9Sstevel@tonic-gate membar #Sync 5097c478bd9Sstevel@tonic-gate ret 5107c478bd9Sstevel@tonic-gate restore %g0, 0, %o0 5117c478bd9Sstevel@tonic-gate SET_SIZE(hwblkpagecopy) 5127c478bd9Sstevel@tonic-gate#endif /* lint */ 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate/* 5167c478bd9Sstevel@tonic-gate * Transfer data to and from user space - 5177c478bd9Sstevel@tonic-gate * Note that these routines can cause faults 5187c478bd9Sstevel@tonic-gate * It is assumed that the kernel has nothing at 5197c478bd9Sstevel@tonic-gate * less than KERNELBASE in the virtual address space. 5207c478bd9Sstevel@tonic-gate * 5217c478bd9Sstevel@tonic-gate * Note that copyin(9F) and copyout(9F) are part of the 5227c478bd9Sstevel@tonic-gate * DDI/DKI which specifies that they return '-1' on "errors." 5237c478bd9Sstevel@tonic-gate * 5247c478bd9Sstevel@tonic-gate * Sigh. 5257c478bd9Sstevel@tonic-gate * 5267c478bd9Sstevel@tonic-gate * So there's two extremely similar routines - xcopyin() and xcopyout() 5277c478bd9Sstevel@tonic-gate * which return the errno that we've faithfully computed. This 5287c478bd9Sstevel@tonic-gate * allows other callers (e.g. uiomove(9F)) to work correctly. 5297c478bd9Sstevel@tonic-gate * Given that these are used pretty heavily, we expand the calling 5307c478bd9Sstevel@tonic-gate * sequences inline for all flavours (rather than making wrappers). 5317c478bd9Sstevel@tonic-gate * 5327c478bd9Sstevel@tonic-gate * There are also stub routines for xcopyout_little and xcopyin_little, 5337c478bd9Sstevel@tonic-gate * which currently are intended to handle requests of <= 16 bytes from 5347c478bd9Sstevel@tonic-gate * do_unaligned. Future enhancement to make them handle 8k pages efficiently 5357c478bd9Sstevel@tonic-gate * is left as an exercise... 5367c478bd9Sstevel@tonic-gate */ 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate/* 5397c478bd9Sstevel@tonic-gate * Copy user data to kernel space (copyOP/xcopyOP/copyOP_noerr) 5407c478bd9Sstevel@tonic-gate * 5417c478bd9Sstevel@tonic-gate * General theory of operation: 5427c478bd9Sstevel@tonic-gate * 5437c478bd9Sstevel@tonic-gate * None of the copyops routines grab a window. 5447c478bd9Sstevel@tonic-gate * 5457c478bd9Sstevel@tonic-gate * Flow: 5467c478bd9Sstevel@tonic-gate * 5477c478bd9Sstevel@tonic-gate * If count == zero return zero. 5487c478bd9Sstevel@tonic-gate * 5497c478bd9Sstevel@tonic-gate * Store the previous lo_fault handler into %g6. 5507c478bd9Sstevel@tonic-gate * Place our secondary lofault handler into %g5. 5517c478bd9Sstevel@tonic-gate * Place the address of our fault handler into %o3. 5527c478bd9Sstevel@tonic-gate * 5537c478bd9Sstevel@tonic-gate * If count is less than or equal to SMALL_LIMIT (7) we 5547c478bd9Sstevel@tonic-gate * always do a byte for byte copy. 5557c478bd9Sstevel@tonic-gate * 5567c478bd9Sstevel@tonic-gate * If count is > SMALL_LIMIT, we check the alignment of the input 5577c478bd9Sstevel@tonic-gate * and output pointers. We store -count in %o3, we store the number 5587c478bd9Sstevel@tonic-gate * of chunks (8, 4, 2 or 1 byte) operated on in our basic copy loop 5597c478bd9Sstevel@tonic-gate * in %o2. Following this we branch to the appropriate copy loop and 5607c478bd9Sstevel@tonic-gate * copy that many chunks. Since we've been adding the chunk size 5617c478bd9Sstevel@tonic-gate * to %o3 each time through as well as decrementing %o2, we can tell 5627c478bd9Sstevel@tonic-gate * if any data is is left to be copied by examining %o3. If that is 5637c478bd9Sstevel@tonic-gate * zero, we're done and can go home. If not, we figure out what the 5647c478bd9Sstevel@tonic-gate * largest chunk size left to be copied is and branch to that copy 5657c478bd9Sstevel@tonic-gate * loop unless there's only one byte left. We load that as we're 5667c478bd9Sstevel@tonic-gate * branching to code that stores it just before we return. 5677c478bd9Sstevel@tonic-gate * 5687c478bd9Sstevel@tonic-gate * Fault handlers are invoked if we reference memory that has no 5697c478bd9Sstevel@tonic-gate * current mapping. All forms share the same copyio_fault handler. 5707c478bd9Sstevel@tonic-gate * This routine handles fixing up the stack and general housecleaning. 5717c478bd9Sstevel@tonic-gate * Each copy operation has a simple fault handler that is then called 5727c478bd9Sstevel@tonic-gate * to do the work specific to the invidual operation. The handler 5737c478bd9Sstevel@tonic-gate * for copyOP and xcopyOP are found at the end of individual function. 5747c478bd9Sstevel@tonic-gate * The handlers for xcopyOP_little are found at the end of xcopyin_little. 5757c478bd9Sstevel@tonic-gate * The handlers for copyOP_noerr are found at the end of copyin_noerr. 5767c478bd9Sstevel@tonic-gate */ 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate/* 5797c478bd9Sstevel@tonic-gate * Copy kernel data to user space (copyout/xcopyout/xcopyout_little). 5807c478bd9Sstevel@tonic-gate */ 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate#if defined(lint) 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 5857c478bd9Sstevel@tonic-gateint 5867c478bd9Sstevel@tonic-gatecopyout(const void *kaddr, void *uaddr, size_t count) 5877c478bd9Sstevel@tonic-gate{ return (0); } 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate#else /* lint */ 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate/* 5927c478bd9Sstevel@tonic-gate * We save the arguments in the following registers in case of a fault: 5937c478bd9Sstevel@tonic-gate * kaddr - %g2 5947c478bd9Sstevel@tonic-gate * uaddr - %g3 5957c478bd9Sstevel@tonic-gate * count - %g4 5967c478bd9Sstevel@tonic-gate */ 5977c478bd9Sstevel@tonic-gate#define SAVE_SRC %g2 5987c478bd9Sstevel@tonic-gate#define SAVE_DST %g3 5997c478bd9Sstevel@tonic-gate#define SAVE_COUNT %g4 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate#define REAL_LOFAULT %g5 6027c478bd9Sstevel@tonic-gate#define SAVED_LOFAULT %g6 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate/* 6057c478bd9Sstevel@tonic-gate * Generic copyio fault handler. This is the first line of defense when a 6067c478bd9Sstevel@tonic-gate * fault occurs in (x)copyin/(x)copyout. In order for this to function 6077c478bd9Sstevel@tonic-gate * properly, the value of the 'real' lofault handler should be in REAL_LOFAULT. 6087c478bd9Sstevel@tonic-gate * This allows us to share common code for all the flavors of the copy 6097c478bd9Sstevel@tonic-gate * operations, including the _noerr versions. 6107c478bd9Sstevel@tonic-gate * 6117c478bd9Sstevel@tonic-gate * Note that this function will restore the original input parameters before 6127c478bd9Sstevel@tonic-gate * calling REAL_LOFAULT. So the real handler can vector to the appropriate 6137c478bd9Sstevel@tonic-gate * member of the t_copyop structure, if needed. 6147c478bd9Sstevel@tonic-gate */ 6157c478bd9Sstevel@tonic-gate ENTRY(copyio_fault) 6167c478bd9Sstevel@tonic-gate membar #Sync 6177c478bd9Sstevel@tonic-gate stn SAVED_LOFAULT, [THREAD_REG + T_LOFAULT] ! restore old t_lofault 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate mov SAVE_SRC, %o0 6207c478bd9Sstevel@tonic-gate mov SAVE_DST, %o1 6217c478bd9Sstevel@tonic-gate jmp REAL_LOFAULT 6227c478bd9Sstevel@tonic-gate mov SAVE_COUNT, %o2 6237c478bd9Sstevel@tonic-gate SET_SIZE(copyio_fault) 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate ENTRY(copyout) 6267c478bd9Sstevel@tonic-gate sethi %hi(.copyout_err), REAL_LOFAULT 6277c478bd9Sstevel@tonic-gate or REAL_LOFAULT, %lo(.copyout_err), REAL_LOFAULT 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate.do_copyout: 6307c478bd9Sstevel@tonic-gate ! 6317c478bd9Sstevel@tonic-gate ! Check the length and bail if zero. 6327c478bd9Sstevel@tonic-gate ! 6337c478bd9Sstevel@tonic-gate tst %o2 6347c478bd9Sstevel@tonic-gate bnz,pt %ncc, 1f 6357c478bd9Sstevel@tonic-gate nop 6367c478bd9Sstevel@tonic-gate retl 6377c478bd9Sstevel@tonic-gate clr %o0 6387c478bd9Sstevel@tonic-gate1: 6397c478bd9Sstevel@tonic-gate sethi %hi(copyio_fault), %o3 6407c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_LOFAULT], SAVED_LOFAULT 6417c478bd9Sstevel@tonic-gate or %o3, %lo(copyio_fault), %o3 6427c478bd9Sstevel@tonic-gate membar #Sync 6437c478bd9Sstevel@tonic-gate stn %o3, [THREAD_REG + T_LOFAULT] 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate mov %o0, SAVE_SRC 6467c478bd9Sstevel@tonic-gate mov %o1, SAVE_DST 6477c478bd9Sstevel@tonic-gate mov %o2, SAVE_COUNT 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate ! 6507c478bd9Sstevel@tonic-gate ! Check to see if we're more than SMALL_LIMIT (7 bytes). 6517c478bd9Sstevel@tonic-gate ! Run in leaf mode, using the %o regs as our input regs. 6527c478bd9Sstevel@tonic-gate ! 6537c478bd9Sstevel@tonic-gate subcc %o2, SMALL_LIMIT, %o3 6547c478bd9Sstevel@tonic-gate bgu,a,pt %ncc, .dco_ns 6557c478bd9Sstevel@tonic-gate or %o0, %o1, %o3 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate.dcobcp: 6587c478bd9Sstevel@tonic-gate sub %g0, %o2, %o3 ! negate count 6597c478bd9Sstevel@tonic-gate add %o0, %o2, %o0 ! make %o0 point at the end 6607c478bd9Sstevel@tonic-gate add %o1, %o2, %o1 ! make %o1 point at the end 6617c478bd9Sstevel@tonic-gate ba,pt %ncc, .dcocl 6627c478bd9Sstevel@tonic-gate ldub [%o0 + %o3], %o4 ! load first byte 6637c478bd9Sstevel@tonic-gate ! 6647c478bd9Sstevel@tonic-gate ! %o0 and %o2 point at the end and remain pointing at the end 6657c478bd9Sstevel@tonic-gate ! of their buffers. We pull things out by adding %o3 (which is 6667c478bd9Sstevel@tonic-gate ! the negation of the length) to the buffer end which gives us 6677c478bd9Sstevel@tonic-gate ! the curent location in the buffers. By incrementing %o3 we walk 6687c478bd9Sstevel@tonic-gate ! through both buffers without having to bump each buffer's 6697c478bd9Sstevel@tonic-gate ! pointer. A very fast 4 instruction loop. 6707c478bd9Sstevel@tonic-gate ! 6717c478bd9Sstevel@tonic-gate .align 16 6727c478bd9Sstevel@tonic-gate.dcocl: 6737c478bd9Sstevel@tonic-gate stba %o4, [%o1 + %o3]ASI_USER 6747c478bd9Sstevel@tonic-gate inccc %o3 6757c478bd9Sstevel@tonic-gate bl,a,pt %ncc, .dcocl 6767c478bd9Sstevel@tonic-gate ldub [%o0 + %o3], %o4 6777c478bd9Sstevel@tonic-gate ! 6787c478bd9Sstevel@tonic-gate ! We're done. Go home. 6797c478bd9Sstevel@tonic-gate ! 6807c478bd9Sstevel@tonic-gate membar #Sync 6817c478bd9Sstevel@tonic-gate stn SAVED_LOFAULT, [THREAD_REG + T_LOFAULT] 6827c478bd9Sstevel@tonic-gate retl 6837c478bd9Sstevel@tonic-gate clr %o0 6847c478bd9Sstevel@tonic-gate ! 6857c478bd9Sstevel@tonic-gate ! Try aligned copies from here. 6867c478bd9Sstevel@tonic-gate ! 6877c478bd9Sstevel@tonic-gate.dco_ns: 6887c478bd9Sstevel@tonic-gate ! %o0 = kernel addr (to be copied from) 6897c478bd9Sstevel@tonic-gate ! %o1 = user addr (to be copied to) 6907c478bd9Sstevel@tonic-gate ! %o2 = length 6917c478bd9Sstevel@tonic-gate ! %o3 = %o1 | %o2 (used for alignment checking) 6927c478bd9Sstevel@tonic-gate ! %o4 is alternate lo_fault 6937c478bd9Sstevel@tonic-gate ! %o5 is original lo_fault 6947c478bd9Sstevel@tonic-gate ! 6957c478bd9Sstevel@tonic-gate ! See if we're single byte aligned. If we are, check the 6967c478bd9Sstevel@tonic-gate ! limit for single byte copies. If we're smaller or equal, 6977c478bd9Sstevel@tonic-gate ! bounce to the byte for byte copy loop. Otherwise do it in 6987c478bd9Sstevel@tonic-gate ! HW (if enabled). 6997c478bd9Sstevel@tonic-gate ! 7007c478bd9Sstevel@tonic-gate btst 1, %o3 7017c478bd9Sstevel@tonic-gate bz,pt %icc, .dcoh8 7027c478bd9Sstevel@tonic-gate btst 7, %o3 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate ba .dcobcp 7057c478bd9Sstevel@tonic-gate nop 7067c478bd9Sstevel@tonic-gate.dcoh8: 7077c478bd9Sstevel@tonic-gate ! 7087c478bd9Sstevel@tonic-gate ! 8 byte aligned? 7097c478bd9Sstevel@tonic-gate ! 7107c478bd9Sstevel@tonic-gate bnz,a %ncc, .dcoh4 7117c478bd9Sstevel@tonic-gate btst 3, %o3 7127c478bd9Sstevel@tonic-gate.dcos8: 7137c478bd9Sstevel@tonic-gate ! 7147c478bd9Sstevel@tonic-gate ! Housekeeping for copy loops. Uses same idea as in the byte for 7157c478bd9Sstevel@tonic-gate ! byte copy loop above. 7167c478bd9Sstevel@tonic-gate ! 7177c478bd9Sstevel@tonic-gate add %o0, %o2, %o0 7187c478bd9Sstevel@tonic-gate add %o1, %o2, %o1 7197c478bd9Sstevel@tonic-gate sub %g0, %o2, %o3 7207c478bd9Sstevel@tonic-gate ba,pt %ncc, .dodebc 7217c478bd9Sstevel@tonic-gate srl %o2, 3, %o2 ! Number of 8 byte chunks to copy 7227c478bd9Sstevel@tonic-gate ! 7237c478bd9Sstevel@tonic-gate ! 4 byte aligned? 7247c478bd9Sstevel@tonic-gate ! 7257c478bd9Sstevel@tonic-gate.dcoh4: 7267c478bd9Sstevel@tonic-gate bnz,pn %ncc, .dcoh2 7277c478bd9Sstevel@tonic-gate nop 7287c478bd9Sstevel@tonic-gate.dcos4: 7297c478bd9Sstevel@tonic-gate add %o0, %o2, %o0 7307c478bd9Sstevel@tonic-gate add %o1, %o2, %o1 7317c478bd9Sstevel@tonic-gate sub %g0, %o2, %o3 7327c478bd9Sstevel@tonic-gate ba,pt %ncc, .dodfbc 7337c478bd9Sstevel@tonic-gate srl %o2, 2, %o2 ! Number of 4 byte chunks to copy 7347c478bd9Sstevel@tonic-gate ! 7357c478bd9Sstevel@tonic-gate ! We must be 2 byte aligned. Off we go. 7367c478bd9Sstevel@tonic-gate ! The check for small copies was done in the 7377c478bd9Sstevel@tonic-gate ! delay at .dcoh4 7387c478bd9Sstevel@tonic-gate ! 7397c478bd9Sstevel@tonic-gate.dcoh2: 7407c478bd9Sstevel@tonic-gate.dcos2: 7417c478bd9Sstevel@tonic-gate add %o0, %o2, %o0 7427c478bd9Sstevel@tonic-gate add %o1, %o2, %o1 7437c478bd9Sstevel@tonic-gate sub %g0, %o2, %o3 7447c478bd9Sstevel@tonic-gate ba,pt %ncc, .dodtbc 7457c478bd9Sstevel@tonic-gate srl %o2, 1, %o2 ! Number of 2 byte chunks to copy 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate.dodebc: 7487c478bd9Sstevel@tonic-gate ldx [%o0 + %o3], %o4 7497c478bd9Sstevel@tonic-gate deccc %o2 7507c478bd9Sstevel@tonic-gate stxa %o4, [%o1 + %o3]ASI_USER 7517c478bd9Sstevel@tonic-gate bg,pt %ncc, .dodebc 7527c478bd9Sstevel@tonic-gate addcc %o3, 8, %o3 7537c478bd9Sstevel@tonic-gate ! 7547c478bd9Sstevel@tonic-gate ! End of copy loop. Check to see if we're done. Most 7557c478bd9Sstevel@tonic-gate ! eight byte aligned copies end here. 7567c478bd9Sstevel@tonic-gate ! 7577c478bd9Sstevel@tonic-gate bz,pt %ncc, .dcofh 7587c478bd9Sstevel@tonic-gate nop 7597c478bd9Sstevel@tonic-gate ! 7607c478bd9Sstevel@tonic-gate ! Something is left - do it byte for byte. 7617c478bd9Sstevel@tonic-gate ! 7627c478bd9Sstevel@tonic-gate ba,pt %ncc, .dcocl 7637c478bd9Sstevel@tonic-gate ldub [%o0 + %o3], %o4 ! load next byte 7647c478bd9Sstevel@tonic-gate ! 7657c478bd9Sstevel@tonic-gate ! Four byte copy loop. %o2 is the number of 4 byte chunks to copy. 7667c478bd9Sstevel@tonic-gate ! 7677c478bd9Sstevel@tonic-gate .align 32 7687c478bd9Sstevel@tonic-gate.dodfbc: 7697c478bd9Sstevel@tonic-gate lduw [%o0 + %o3], %o4 7707c478bd9Sstevel@tonic-gate deccc %o2 7717c478bd9Sstevel@tonic-gate sta %o4, [%o1 + %o3]ASI_USER 7727c478bd9Sstevel@tonic-gate bg,pt %ncc, .dodfbc 7737c478bd9Sstevel@tonic-gate addcc %o3, 4, %o3 7747c478bd9Sstevel@tonic-gate ! 7757c478bd9Sstevel@tonic-gate ! End of copy loop. Check to see if we're done. Most 7767c478bd9Sstevel@tonic-gate ! four byte aligned copies end here. 7777c478bd9Sstevel@tonic-gate ! 7787c478bd9Sstevel@tonic-gate bz,pt %ncc, .dcofh 7797c478bd9Sstevel@tonic-gate nop 7807c478bd9Sstevel@tonic-gate ! 7817c478bd9Sstevel@tonic-gate ! Something is left. Do it byte for byte. 7827c478bd9Sstevel@tonic-gate ! 7837c478bd9Sstevel@tonic-gate ba,pt %ncc, .dcocl 7847c478bd9Sstevel@tonic-gate ldub [%o0 + %o3], %o4 ! load next byte 7857c478bd9Sstevel@tonic-gate ! 7867c478bd9Sstevel@tonic-gate ! two byte aligned copy loop. %o2 is the number of 2 byte chunks to 7877c478bd9Sstevel@tonic-gate ! copy. 7887c478bd9Sstevel@tonic-gate ! 7897c478bd9Sstevel@tonic-gate .align 32 7907c478bd9Sstevel@tonic-gate.dodtbc: 7917c478bd9Sstevel@tonic-gate lduh [%o0 + %o3], %o4 7927c478bd9Sstevel@tonic-gate deccc %o2 7937c478bd9Sstevel@tonic-gate stha %o4, [%o1 + %o3]ASI_USER 7947c478bd9Sstevel@tonic-gate bg,pt %ncc, .dodtbc 7957c478bd9Sstevel@tonic-gate addcc %o3, 2, %o3 7967c478bd9Sstevel@tonic-gate ! 7977c478bd9Sstevel@tonic-gate ! End of copy loop. Anything left? 7987c478bd9Sstevel@tonic-gate ! 7997c478bd9Sstevel@tonic-gate bz,pt %ncc, .dcofh 8007c478bd9Sstevel@tonic-gate nop 8017c478bd9Sstevel@tonic-gate ! 8027c478bd9Sstevel@tonic-gate ! Deal with the last byte 8037c478bd9Sstevel@tonic-gate ! 8047c478bd9Sstevel@tonic-gate ldub [%o0 + %o3], %o4 8057c478bd9Sstevel@tonic-gate stba %o4, [%o1 + %o3]ASI_USER 8067c478bd9Sstevel@tonic-gate.dcofh: 8077c478bd9Sstevel@tonic-gate membar #Sync 8087c478bd9Sstevel@tonic-gate stn SAVED_LOFAULT, [THREAD_REG + T_LOFAULT] ! restore old t_lofault 8097c478bd9Sstevel@tonic-gate retl 8107c478bd9Sstevel@tonic-gate clr %o0 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate.copyout_err: 8137c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_COPYOPS], %o4 8147c478bd9Sstevel@tonic-gate brz %o4, 2f 8157c478bd9Sstevel@tonic-gate nop 8167c478bd9Sstevel@tonic-gate ldn [%o4 + CP_COPYOUT], %g2 8177c478bd9Sstevel@tonic-gate jmp %g2 8187c478bd9Sstevel@tonic-gate nop 8197c478bd9Sstevel@tonic-gate2: 8207c478bd9Sstevel@tonic-gate retl 8217c478bd9Sstevel@tonic-gate mov -1, %o0 8227c478bd9Sstevel@tonic-gate SET_SIZE(copyout) 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate#endif /* lint */ 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate#ifdef lint 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 8307c478bd9Sstevel@tonic-gateint 8317c478bd9Sstevel@tonic-gatexcopyout(const void *kaddr, void *uaddr, size_t count) 8327c478bd9Sstevel@tonic-gate{ return (0); } 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate#else /* lint */ 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate ENTRY(xcopyout) 8377c478bd9Sstevel@tonic-gate sethi %hi(.xcopyout_err), REAL_LOFAULT 8387c478bd9Sstevel@tonic-gate b .do_copyout 8397c478bd9Sstevel@tonic-gate or REAL_LOFAULT, %lo(.xcopyout_err), REAL_LOFAULT 8407c478bd9Sstevel@tonic-gate.xcopyout_err: 8417c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_COPYOPS], %o4 8427c478bd9Sstevel@tonic-gate brz %o4, 2f 8437c478bd9Sstevel@tonic-gate nop 8447c478bd9Sstevel@tonic-gate ldn [%o4 + CP_XCOPYOUT], %g2 8457c478bd9Sstevel@tonic-gate jmp %g2 8467c478bd9Sstevel@tonic-gate nop 8477c478bd9Sstevel@tonic-gate2: 8487c478bd9Sstevel@tonic-gate retl 8497c478bd9Sstevel@tonic-gate mov %g1, %o0 8507c478bd9Sstevel@tonic-gate SET_SIZE(xcopyout) 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate#endif /* lint */ 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate#ifdef lint 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 8577c478bd9Sstevel@tonic-gateint 8587c478bd9Sstevel@tonic-gatexcopyout_little(const void *kaddr, void *uaddr, size_t count) 8597c478bd9Sstevel@tonic-gate{ return (0); } 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate#else /* lint */ 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate ENTRY(xcopyout_little) 8647c478bd9Sstevel@tonic-gate sethi %hi(.little_err), %o4 8657c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_LOFAULT], %o5 8667c478bd9Sstevel@tonic-gate or %o4, %lo(.little_err), %o4 8677c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 8687c478bd9Sstevel@tonic-gate stn %o4, [THREAD_REG + T_LOFAULT] 8697c478bd9Sstevel@tonic-gate 8707c478bd9Sstevel@tonic-gate subcc %g0, %o2, %o3 8717c478bd9Sstevel@tonic-gate add %o0, %o2, %o0 8727c478bd9Sstevel@tonic-gate bz,pn %ncc, 2f ! check for zero bytes 8737c478bd9Sstevel@tonic-gate sub %o2, 1, %o4 8747c478bd9Sstevel@tonic-gate add %o0, %o4, %o0 ! start w/last byte 8757c478bd9Sstevel@tonic-gate add %o1, %o2, %o1 8767c478bd9Sstevel@tonic-gate ldub [%o0+%o3], %o4 8777c478bd9Sstevel@tonic-gate 8787c478bd9Sstevel@tonic-gate1: stba %o4, [%o1+%o3]ASI_AIUSL 8797c478bd9Sstevel@tonic-gate inccc %o3 8807c478bd9Sstevel@tonic-gate sub %o0, 2, %o0 ! get next byte 8817c478bd9Sstevel@tonic-gate bcc,a,pt %ncc, 1b 8827c478bd9Sstevel@tonic-gate ldub [%o0+%o3], %o4 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate2: membar #Sync ! sync error barrier 8857c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] ! restore old t_lofault 8867c478bd9Sstevel@tonic-gate retl 8877c478bd9Sstevel@tonic-gate mov %g0, %o0 ! return (0) 8887c478bd9Sstevel@tonic-gate SET_SIZE(xcopyout_little) 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate#endif /* lint */ 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate/* 8937c478bd9Sstevel@tonic-gate * Copy user data to kernel space (copyin/xcopyin/xcopyin_little) 8947c478bd9Sstevel@tonic-gate */ 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate#if defined(lint) 8977c478bd9Sstevel@tonic-gate 8987c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 8997c478bd9Sstevel@tonic-gateint 9007c478bd9Sstevel@tonic-gatecopyin(const void *uaddr, void *kaddr, size_t count) 9017c478bd9Sstevel@tonic-gate{ return (0); } 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate#else /* lint */ 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate ENTRY(copyin) 9067c478bd9Sstevel@tonic-gate sethi %hi(.copyin_err), REAL_LOFAULT 9077c478bd9Sstevel@tonic-gate or REAL_LOFAULT, %lo(.copyin_err), REAL_LOFAULT 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate.do_copyin: 9107c478bd9Sstevel@tonic-gate ! 9117c478bd9Sstevel@tonic-gate ! Check the length and bail if zero. 9127c478bd9Sstevel@tonic-gate ! 9137c478bd9Sstevel@tonic-gate tst %o2 9147c478bd9Sstevel@tonic-gate bnz,pt %ncc, 1f 9157c478bd9Sstevel@tonic-gate nop 9167c478bd9Sstevel@tonic-gate retl 9177c478bd9Sstevel@tonic-gate clr %o0 9187c478bd9Sstevel@tonic-gate1: 9197c478bd9Sstevel@tonic-gate sethi %hi(copyio_fault), %o3 9207c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_LOFAULT], SAVED_LOFAULT 9217c478bd9Sstevel@tonic-gate or %o3, %lo(copyio_fault), %o3 9227c478bd9Sstevel@tonic-gate membar #Sync 9237c478bd9Sstevel@tonic-gate stn %o3, [THREAD_REG + T_LOFAULT] 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate mov %o0, SAVE_SRC 9267c478bd9Sstevel@tonic-gate mov %o1, SAVE_DST 9277c478bd9Sstevel@tonic-gate mov %o2, SAVE_COUNT 9287c478bd9Sstevel@tonic-gate 9297c478bd9Sstevel@tonic-gate ! 9307c478bd9Sstevel@tonic-gate ! Check to see if we're more than SMALL_LIMIT. 9317c478bd9Sstevel@tonic-gate ! 9327c478bd9Sstevel@tonic-gate subcc %o2, SMALL_LIMIT, %o3 9337c478bd9Sstevel@tonic-gate bgu,a,pt %ncc, .dci_ns 9347c478bd9Sstevel@tonic-gate or %o0, %o1, %o3 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate.dcibcp: 9377c478bd9Sstevel@tonic-gate sub %g0, %o2, %o3 ! setup for copy loop 9387c478bd9Sstevel@tonic-gate add %o0, %o2, %o0 9397c478bd9Sstevel@tonic-gate add %o1, %o2, %o1 9407c478bd9Sstevel@tonic-gate ba,pt %ncc, .dcicl 9417c478bd9Sstevel@tonic-gate lduba [%o0 + %o3]ASI_USER, %o4 9427c478bd9Sstevel@tonic-gate ! 9437c478bd9Sstevel@tonic-gate ! %o0 and %o1 point at the end and remain pointing at the end 9447c478bd9Sstevel@tonic-gate ! of their buffers. We pull things out by adding %o3 (which is 9457c478bd9Sstevel@tonic-gate ! the negation of the length) to the buffer end which gives us 9467c478bd9Sstevel@tonic-gate ! the curent location in the buffers. By incrementing %o3 we walk 9477c478bd9Sstevel@tonic-gate ! through both buffers without having to bump each buffer's 9487c478bd9Sstevel@tonic-gate ! pointer. A very fast 4 instruction loop. 9497c478bd9Sstevel@tonic-gate ! 9507c478bd9Sstevel@tonic-gate .align 16 9517c478bd9Sstevel@tonic-gate.dcicl: 9527c478bd9Sstevel@tonic-gate stb %o4, [%o1 + %o3] 9537c478bd9Sstevel@tonic-gate inccc %o3 9547c478bd9Sstevel@tonic-gate bl,a,pt %ncc, .dcicl 9557c478bd9Sstevel@tonic-gate lduba [%o0 + %o3]ASI_USER, %o4 9567c478bd9Sstevel@tonic-gate ! 9577c478bd9Sstevel@tonic-gate ! We're done. Go home. 9587c478bd9Sstevel@tonic-gate ! 9597c478bd9Sstevel@tonic-gate membar #Sync 9607c478bd9Sstevel@tonic-gate stn SAVED_LOFAULT, [THREAD_REG + T_LOFAULT] 9617c478bd9Sstevel@tonic-gate retl 9627c478bd9Sstevel@tonic-gate clr %o0 9637c478bd9Sstevel@tonic-gate ! 9647c478bd9Sstevel@tonic-gate ! Try aligned copies from here. 9657c478bd9Sstevel@tonic-gate ! 9667c478bd9Sstevel@tonic-gate.dci_ns: 9677c478bd9Sstevel@tonic-gate ! 9687c478bd9Sstevel@tonic-gate ! See if we're single byte aligned. If we are, check the 9697c478bd9Sstevel@tonic-gate ! limit for single byte copies. If we're smaller, or equal, 9707c478bd9Sstevel@tonic-gate ! bounce to the byte for byte copy loop. Otherwise do it in 9717c478bd9Sstevel@tonic-gate ! HW (if enabled). 9727c478bd9Sstevel@tonic-gate ! 9737c478bd9Sstevel@tonic-gate btst 1, %o3 9747c478bd9Sstevel@tonic-gate bz,a,pt %icc, .dcih8 9757c478bd9Sstevel@tonic-gate btst 7, %o3 9767c478bd9Sstevel@tonic-gate ba .dcibcp 9777c478bd9Sstevel@tonic-gate nop 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate.dcih8: 9807c478bd9Sstevel@tonic-gate ! 9817c478bd9Sstevel@tonic-gate ! 8 byte aligned? 9827c478bd9Sstevel@tonic-gate ! 9837c478bd9Sstevel@tonic-gate bnz,a %ncc, .dcih4 9847c478bd9Sstevel@tonic-gate btst 3, %o3 9857c478bd9Sstevel@tonic-gate.dcis8: 9867c478bd9Sstevel@tonic-gate ! 9877c478bd9Sstevel@tonic-gate ! Housekeeping for copy loops. Uses same idea as in the byte for 9887c478bd9Sstevel@tonic-gate ! byte copy loop above. 9897c478bd9Sstevel@tonic-gate ! 9907c478bd9Sstevel@tonic-gate add %o0, %o2, %o0 9917c478bd9Sstevel@tonic-gate add %o1, %o2, %o1 9927c478bd9Sstevel@tonic-gate sub %g0, %o2, %o3 9937c478bd9Sstevel@tonic-gate ba,pt %ncc, .didebc 9947c478bd9Sstevel@tonic-gate srl %o2, 3, %o2 ! Number of 8 byte chunks to copy 9957c478bd9Sstevel@tonic-gate ! 9967c478bd9Sstevel@tonic-gate ! 4 byte aligned? 9977c478bd9Sstevel@tonic-gate ! 9987c478bd9Sstevel@tonic-gate.dcih4: 9997c478bd9Sstevel@tonic-gate bnz %ncc, .dcih2 10007c478bd9Sstevel@tonic-gate nop 10017c478bd9Sstevel@tonic-gate.dcis4: 10027c478bd9Sstevel@tonic-gate ! 10037c478bd9Sstevel@tonic-gate ! Housekeeping for copy loops. Uses same idea as in the byte 10047c478bd9Sstevel@tonic-gate ! for byte copy loop above. 10057c478bd9Sstevel@tonic-gate ! 10067c478bd9Sstevel@tonic-gate add %o0, %o2, %o0 10077c478bd9Sstevel@tonic-gate add %o1, %o2, %o1 10087c478bd9Sstevel@tonic-gate sub %g0, %o2, %o3 10097c478bd9Sstevel@tonic-gate ba,pt %ncc, .didfbc 10107c478bd9Sstevel@tonic-gate srl %o2, 2, %o2 ! Number of 4 byte chunks to copy 10117c478bd9Sstevel@tonic-gate.dcih2: 10127c478bd9Sstevel@tonic-gate.dcis2: 10137c478bd9Sstevel@tonic-gate add %o0, %o2, %o0 10147c478bd9Sstevel@tonic-gate add %o1, %o2, %o1 10157c478bd9Sstevel@tonic-gate sub %g0, %o2, %o3 10167c478bd9Sstevel@tonic-gate ba,pt %ncc, .didtbc 10177c478bd9Sstevel@tonic-gate srl %o2, 1, %o2 ! Number of 2 byte chunks to copy 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate.didebc: 10207c478bd9Sstevel@tonic-gate ldxa [%o0 + %o3]ASI_USER, %o4 10217c478bd9Sstevel@tonic-gate deccc %o2 10227c478bd9Sstevel@tonic-gate stx %o4, [%o1 + %o3] 10237c478bd9Sstevel@tonic-gate bg,pt %ncc, .didebc 10247c478bd9Sstevel@tonic-gate addcc %o3, 8, %o3 10257c478bd9Sstevel@tonic-gate ! 10267c478bd9Sstevel@tonic-gate ! End of copy loop. Most 8 byte aligned copies end here. 10277c478bd9Sstevel@tonic-gate ! 10287c478bd9Sstevel@tonic-gate bz,pt %ncc, .dcifh 10297c478bd9Sstevel@tonic-gate nop 10307c478bd9Sstevel@tonic-gate ! 10317c478bd9Sstevel@tonic-gate ! Something is left. Do it byte for byte. 10327c478bd9Sstevel@tonic-gate ! 10337c478bd9Sstevel@tonic-gate ba,pt %ncc, .dcicl 10347c478bd9Sstevel@tonic-gate lduba [%o0 + %o3]ASI_USER, %o4 10357c478bd9Sstevel@tonic-gate ! 10367c478bd9Sstevel@tonic-gate ! 4 byte copy loop. %o2 is number of 4 byte chunks to copy. 10377c478bd9Sstevel@tonic-gate ! 10387c478bd9Sstevel@tonic-gate .align 32 10397c478bd9Sstevel@tonic-gate.didfbc: 10407c478bd9Sstevel@tonic-gate lduwa [%o0 + %o3]ASI_USER, %o4 10417c478bd9Sstevel@tonic-gate deccc %o2 10427c478bd9Sstevel@tonic-gate st %o4, [%o1 + %o3] 10437c478bd9Sstevel@tonic-gate bg,pt %ncc, .didfbc 10447c478bd9Sstevel@tonic-gate addcc %o3, 4, %o3 10457c478bd9Sstevel@tonic-gate ! 10467c478bd9Sstevel@tonic-gate ! End of copy loop. Most 4 byte aligned copies end here. 10477c478bd9Sstevel@tonic-gate ! 10487c478bd9Sstevel@tonic-gate bz,pt %ncc, .dcifh 10497c478bd9Sstevel@tonic-gate nop 10507c478bd9Sstevel@tonic-gate ! 10517c478bd9Sstevel@tonic-gate ! Something is left. Do it byte for byte. 10527c478bd9Sstevel@tonic-gate ! 10537c478bd9Sstevel@tonic-gate ba,pt %ncc, .dcicl 10547c478bd9Sstevel@tonic-gate lduba [%o0 + %o3]ASI_USER, %o4 10557c478bd9Sstevel@tonic-gate ! 10567c478bd9Sstevel@tonic-gate ! 2 byte aligned copy loop. %o2 is number of 2 byte chunks to 10577c478bd9Sstevel@tonic-gate ! copy. 10587c478bd9Sstevel@tonic-gate ! 10597c478bd9Sstevel@tonic-gate .align 32 10607c478bd9Sstevel@tonic-gate.didtbc: 10617c478bd9Sstevel@tonic-gate lduha [%o0 + %o3]ASI_USER, %o4 10627c478bd9Sstevel@tonic-gate deccc %o2 10637c478bd9Sstevel@tonic-gate sth %o4, [%o1 + %o3] 10647c478bd9Sstevel@tonic-gate bg,pt %ncc, .didtbc 10657c478bd9Sstevel@tonic-gate addcc %o3, 2, %o3 10667c478bd9Sstevel@tonic-gate ! 10677c478bd9Sstevel@tonic-gate ! End of copy loop. Most 2 byte aligned copies end here. 10687c478bd9Sstevel@tonic-gate ! 10697c478bd9Sstevel@tonic-gate bz,pt %ncc, .dcifh 10707c478bd9Sstevel@tonic-gate nop 10717c478bd9Sstevel@tonic-gate ! 10727c478bd9Sstevel@tonic-gate ! Deal with the last byte 10737c478bd9Sstevel@tonic-gate ! 10747c478bd9Sstevel@tonic-gate lduba [%o0 + %o3]ASI_USER, %o4 10757c478bd9Sstevel@tonic-gate stb %o4, [%o1 + %o3] 10767c478bd9Sstevel@tonic-gate.dcifh: 10777c478bd9Sstevel@tonic-gate membar #Sync 10787c478bd9Sstevel@tonic-gate stn SAVED_LOFAULT, [THREAD_REG + T_LOFAULT] ! restore old t_lofault 10797c478bd9Sstevel@tonic-gate retl 10807c478bd9Sstevel@tonic-gate clr %o0 10817c478bd9Sstevel@tonic-gate 10827c478bd9Sstevel@tonic-gate.copyin_err: 10837c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_COPYOPS], %o4 10847c478bd9Sstevel@tonic-gate brz %o4, 2f 10857c478bd9Sstevel@tonic-gate nop 10867c478bd9Sstevel@tonic-gate ldn [%o4 + CP_COPYIN], %g2 10877c478bd9Sstevel@tonic-gate jmp %g2 10887c478bd9Sstevel@tonic-gate nop 10897c478bd9Sstevel@tonic-gate2: 10907c478bd9Sstevel@tonic-gate retl 10917c478bd9Sstevel@tonic-gate mov -1, %o0 10927c478bd9Sstevel@tonic-gate SET_SIZE(copyin) 10937c478bd9Sstevel@tonic-gate 10947c478bd9Sstevel@tonic-gate#endif /* lint */ 10957c478bd9Sstevel@tonic-gate 10967c478bd9Sstevel@tonic-gate#ifdef lint 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 10997c478bd9Sstevel@tonic-gateint 11007c478bd9Sstevel@tonic-gatexcopyin(const void *uaddr, void *kaddr, size_t count) 11017c478bd9Sstevel@tonic-gate{ return (0); } 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate#else /* lint */ 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate ENTRY(xcopyin) 11067c478bd9Sstevel@tonic-gate sethi %hi(.xcopyin_err), REAL_LOFAULT 11077c478bd9Sstevel@tonic-gate b .do_copyin 11087c478bd9Sstevel@tonic-gate or REAL_LOFAULT, %lo(.xcopyin_err), REAL_LOFAULT 11097c478bd9Sstevel@tonic-gate.xcopyin_err: 11107c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_COPYOPS], %o4 11117c478bd9Sstevel@tonic-gate brz %o4, 2f 11127c478bd9Sstevel@tonic-gate nop 11137c478bd9Sstevel@tonic-gate ldn [%o4 + CP_XCOPYIN], %g2 11147c478bd9Sstevel@tonic-gate jmp %g2 11157c478bd9Sstevel@tonic-gate nop 11167c478bd9Sstevel@tonic-gate2: 11177c478bd9Sstevel@tonic-gate retl 11187c478bd9Sstevel@tonic-gate mov %g1, %o0 11197c478bd9Sstevel@tonic-gate SET_SIZE(xcopyin) 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate#endif /* lint */ 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate#ifdef lint 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 11267c478bd9Sstevel@tonic-gateint 11277c478bd9Sstevel@tonic-gatexcopyin_little(const void *uaddr, void *kaddr, size_t count) 11287c478bd9Sstevel@tonic-gate{ return (0); } 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate#else /* lint */ 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate ENTRY(xcopyin_little) 11337c478bd9Sstevel@tonic-gate sethi %hi(.little_err), %o4 11347c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_LOFAULT], %o5 11357c478bd9Sstevel@tonic-gate or %o4, %lo(.little_err), %o4 11367c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 11377c478bd9Sstevel@tonic-gate stn %o4, [THREAD_REG + T_LOFAULT] 11387c478bd9Sstevel@tonic-gate 11397c478bd9Sstevel@tonic-gate subcc %g0, %o2, %o3 11407c478bd9Sstevel@tonic-gate add %o0, %o2, %o0 11417c478bd9Sstevel@tonic-gate bz,pn %ncc, 2f ! check for zero bytes 11427c478bd9Sstevel@tonic-gate sub %o2, 1, %o4 11437c478bd9Sstevel@tonic-gate add %o0, %o4, %o0 ! start w/last byte 11447c478bd9Sstevel@tonic-gate add %o1, %o2, %o1 11457c478bd9Sstevel@tonic-gate lduba [%o0+%o3]ASI_AIUSL, %o4 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate1: stb %o4, [%o1+%o3] 11487c478bd9Sstevel@tonic-gate inccc %o3 11497c478bd9Sstevel@tonic-gate sub %o0, 2, %o0 ! get next byte 11507c478bd9Sstevel@tonic-gate bcc,a,pt %ncc, 1b 11517c478bd9Sstevel@tonic-gate lduba [%o0+%o3]ASI_AIUSL, %o4 11527c478bd9Sstevel@tonic-gate 11537c478bd9Sstevel@tonic-gate2: membar #Sync ! sync error barrier 11547c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] ! restore old t_lofault 11557c478bd9Sstevel@tonic-gate retl 11567c478bd9Sstevel@tonic-gate mov %g0, %o0 ! return (0) 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate.little_err: 11597c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 11607c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] ! restore old t_lofault 11617c478bd9Sstevel@tonic-gate retl 11627c478bd9Sstevel@tonic-gate mov %g1, %o0 11637c478bd9Sstevel@tonic-gate SET_SIZE(xcopyin_little) 11647c478bd9Sstevel@tonic-gate 11657c478bd9Sstevel@tonic-gate#endif /* lint */ 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate/* 11697c478bd9Sstevel@tonic-gate * Copy a block of storage - must not overlap (from + len <= to). 11707c478bd9Sstevel@tonic-gate * No fault handler installed (to be called under on_fault()) 11717c478bd9Sstevel@tonic-gate */ 11727c478bd9Sstevel@tonic-gate#if defined(lint) 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate/* ARGSUSED */ 11757c478bd9Sstevel@tonic-gatevoid 11767c478bd9Sstevel@tonic-gatecopyin_noerr(const void *ufrom, void *kto, size_t count) 11777c478bd9Sstevel@tonic-gate{} 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate#else /* lint */ 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate ENTRY(copyin_noerr) 11827c478bd9Sstevel@tonic-gate sethi %hi(.copyio_noerr), REAL_LOFAULT 11837c478bd9Sstevel@tonic-gate b .do_copyin 11847c478bd9Sstevel@tonic-gate or REAL_LOFAULT, %lo(.copyio_noerr), REAL_LOFAULT 11857c478bd9Sstevel@tonic-gate.copyio_noerr: 11867c478bd9Sstevel@tonic-gate jmp SAVED_LOFAULT 11877c478bd9Sstevel@tonic-gate nop 11887c478bd9Sstevel@tonic-gate SET_SIZE(copyin_noerr) 11897c478bd9Sstevel@tonic-gate 11907c478bd9Sstevel@tonic-gate#endif /* lint */ 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate/* 11937c478bd9Sstevel@tonic-gate * Copy a block of storage - must not overlap (from + len <= to). 11947c478bd9Sstevel@tonic-gate * No fault handler installed (to be called under on_fault()) 11957c478bd9Sstevel@tonic-gate */ 11967c478bd9Sstevel@tonic-gate 11977c478bd9Sstevel@tonic-gate#if defined(lint) 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate/* ARGSUSED */ 12007c478bd9Sstevel@tonic-gatevoid 12017c478bd9Sstevel@tonic-gatecopyout_noerr(const void *kfrom, void *uto, size_t count) 12027c478bd9Sstevel@tonic-gate{} 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate#else /* lint */ 12057c478bd9Sstevel@tonic-gate 12067c478bd9Sstevel@tonic-gate ENTRY(copyout_noerr) 12077c478bd9Sstevel@tonic-gate sethi %hi(.copyio_noerr), REAL_LOFAULT 12087c478bd9Sstevel@tonic-gate b .do_copyout 12097c478bd9Sstevel@tonic-gate or REAL_LOFAULT, %lo(.copyio_noerr), REAL_LOFAULT 12107c478bd9Sstevel@tonic-gate SET_SIZE(copyout_noerr) 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate#endif /* lint */ 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate#if defined(lint) 12157c478bd9Sstevel@tonic-gate 12167c478bd9Sstevel@tonic-gateint use_hw_bcopy = 1; 12177c478bd9Sstevel@tonic-gateint use_hw_bzero = 1; 12187c478bd9Sstevel@tonic-gate 12197c478bd9Sstevel@tonic-gate#else /* !lint */ 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate .align 4 12227c478bd9Sstevel@tonic-gate DGDEF(use_hw_bcopy) 12237c478bd9Sstevel@tonic-gate .word 1 12247c478bd9Sstevel@tonic-gate DGDEF(use_hw_bzero) 12257c478bd9Sstevel@tonic-gate .word 1 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate .align 64 12287c478bd9Sstevel@tonic-gate .section ".text" 12297c478bd9Sstevel@tonic-gate#endif /* !lint */ 12307c478bd9Sstevel@tonic-gate 12317c478bd9Sstevel@tonic-gate 12327c478bd9Sstevel@tonic-gate/* 12337c478bd9Sstevel@tonic-gate * hwblkclr - clears block-aligned, block-multiple-sized regions that are 1234*c2b6e926Sae112802 * longer than 256 bytes in length. For the generic module we will simply 1235*c2b6e926Sae112802 * call bzero and return 1 to ensure that the pages in cache should be 1236a4070553Siskreen * flushed to ensure integrity. 12377c478bd9Sstevel@tonic-gate * Caller is responsible for ensuring use_hw_bzero is true and that 12387c478bd9Sstevel@tonic-gate * kpreempt_disable() has been called. 12397c478bd9Sstevel@tonic-gate */ 12407c478bd9Sstevel@tonic-gate#ifdef lint 12417c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 12427c478bd9Sstevel@tonic-gateint 12437c478bd9Sstevel@tonic-gatehwblkclr(void *addr, size_t len) 12447c478bd9Sstevel@tonic-gate{ 12457c478bd9Sstevel@tonic-gate return(0); 12467c478bd9Sstevel@tonic-gate} 12477c478bd9Sstevel@tonic-gate#else /* lint */ 12487c478bd9Sstevel@tonic-gate ! %i0 - start address 12497c478bd9Sstevel@tonic-gate ! %i1 - length of region (multiple of 64) 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate ENTRY(hwblkclr) 12527c478bd9Sstevel@tonic-gate save %sp, -SA(MINFRAME), %sp 12537c478bd9Sstevel@tonic-gate 1254*c2b6e926Sae112802 ! Simply call bzero and notify the caller that bzero was used 12557c478bd9Sstevel@tonic-gate mov %i0, %o0 12567c478bd9Sstevel@tonic-gate call bzero 12577c478bd9Sstevel@tonic-gate mov %i1, %o1 12587c478bd9Sstevel@tonic-gate ret 12597c478bd9Sstevel@tonic-gate restore %g0, 1, %o0 ! return (1) - did not use block operations 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate SET_SIZE(hwblkclr) 12627c478bd9Sstevel@tonic-gate#endif /* lint */ 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate#ifdef lint 12657c478bd9Sstevel@tonic-gate/* Copy 32 bytes of data from src to dst using physical addresses */ 12667c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 12677c478bd9Sstevel@tonic-gatevoid 12687c478bd9Sstevel@tonic-gatehw_pa_bcopy32(uint64_t src, uint64_t dst) 12697c478bd9Sstevel@tonic-gate{} 12707c478bd9Sstevel@tonic-gate#else /*!lint */ 12717c478bd9Sstevel@tonic-gate 12727c478bd9Sstevel@tonic-gate /* 12737c478bd9Sstevel@tonic-gate * Copy 32 bytes of data from src (%o0) to dst (%o1) 12747c478bd9Sstevel@tonic-gate * using physical addresses. 12757c478bd9Sstevel@tonic-gate */ 12767c478bd9Sstevel@tonic-gate ENTRY_NP(hw_pa_bcopy32) 12777c478bd9Sstevel@tonic-gate rdpr %pstate, %g1 12787c478bd9Sstevel@tonic-gate andn %g1, PSTATE_IE, %g2 12797c478bd9Sstevel@tonic-gate wrpr %g0, %g2, %pstate 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate ldxa [%o0]ASI_MEM, %o2 12827c478bd9Sstevel@tonic-gate add %o0, 8, %o0 12837c478bd9Sstevel@tonic-gate ldxa [%o0]ASI_MEM, %o3 12847c478bd9Sstevel@tonic-gate add %o0, 8, %o0 12857c478bd9Sstevel@tonic-gate ldxa [%o0]ASI_MEM, %o4 12867c478bd9Sstevel@tonic-gate add %o0, 8, %o0 12877c478bd9Sstevel@tonic-gate ldxa [%o0]ASI_MEM, %o5 12887c478bd9Sstevel@tonic-gate stxa %o2, [%o1]ASI_MEM 12897c478bd9Sstevel@tonic-gate add %o1, 8, %o1 12907c478bd9Sstevel@tonic-gate stxa %o3, [%o1]ASI_MEM 12917c478bd9Sstevel@tonic-gate add %o1, 8, %o1 12927c478bd9Sstevel@tonic-gate stxa %o4, [%o1]ASI_MEM 12937c478bd9Sstevel@tonic-gate add %o1, 8, %o1 12947c478bd9Sstevel@tonic-gate stxa %o5, [%o1]ASI_MEM 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate membar #Sync 12977c478bd9Sstevel@tonic-gate retl 12987c478bd9Sstevel@tonic-gate wrpr %g0, %g1, %pstate 12997c478bd9Sstevel@tonic-gate SET_SIZE(hw_pa_bcopy32) 13007c478bd9Sstevel@tonic-gate#endif /* lint */ 13017c478bd9Sstevel@tonic-gate 13027c478bd9Sstevel@tonic-gate/* 13037c478bd9Sstevel@tonic-gate * Zero a block of storage. 13047c478bd9Sstevel@tonic-gate * 13057c478bd9Sstevel@tonic-gate * uzero is used by the kernel to zero a block in user address space. 13067c478bd9Sstevel@tonic-gate */ 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate#if defined(lint) 13107c478bd9Sstevel@tonic-gate 13117c478bd9Sstevel@tonic-gate/* ARGSUSED */ 13127c478bd9Sstevel@tonic-gateint 13137c478bd9Sstevel@tonic-gatekzero(void *addr, size_t count) 13147c478bd9Sstevel@tonic-gate{ return(0); } 13157c478bd9Sstevel@tonic-gate 13167c478bd9Sstevel@tonic-gate/* ARGSUSED */ 13177c478bd9Sstevel@tonic-gatevoid 13187c478bd9Sstevel@tonic-gateuzero(void *addr, size_t count) 13197c478bd9Sstevel@tonic-gate{} 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate#else /* lint */ 13227c478bd9Sstevel@tonic-gate 13237c478bd9Sstevel@tonic-gate ENTRY(uzero) 13247c478bd9Sstevel@tonic-gate ! 13257c478bd9Sstevel@tonic-gate ! Set a new lo_fault handler only if we came in with one 13267c478bd9Sstevel@tonic-gate ! already specified. 13277c478bd9Sstevel@tonic-gate ! 13287c478bd9Sstevel@tonic-gate wr %g0, ASI_USER, %asi 13297c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_LOFAULT], %o5 13307c478bd9Sstevel@tonic-gate tst %o5 13317c478bd9Sstevel@tonic-gate bz,pt %ncc, .do_zero 13327c478bd9Sstevel@tonic-gate sethi %hi(.zeroerr), %o2 13337c478bd9Sstevel@tonic-gate or %o2, %lo(.zeroerr), %o2 13347c478bd9Sstevel@tonic-gate membar #Sync 13357c478bd9Sstevel@tonic-gate ba,pt %ncc, .do_zero 13367c478bd9Sstevel@tonic-gate stn %o2, [THREAD_REG + T_LOFAULT] 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate ENTRY(kzero) 13397c478bd9Sstevel@tonic-gate ! 13407c478bd9Sstevel@tonic-gate ! Always set a lo_fault handler 13417c478bd9Sstevel@tonic-gate ! 13427c478bd9Sstevel@tonic-gate wr %g0, ASI_P, %asi 13437c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_LOFAULT], %o5 13447c478bd9Sstevel@tonic-gate sethi %hi(.zeroerr), %o2 13457c478bd9Sstevel@tonic-gate or %o5, LOFAULT_SET, %o5 13467c478bd9Sstevel@tonic-gate or %o2, %lo(.zeroerr), %o2 13477c478bd9Sstevel@tonic-gate membar #Sync 13487c478bd9Sstevel@tonic-gate ba,pt %ncc, .do_zero 13497c478bd9Sstevel@tonic-gate stn %o2, [THREAD_REG + T_LOFAULT] 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate/* 13527c478bd9Sstevel@tonic-gate * We got here because of a fault during kzero or if 13537c478bd9Sstevel@tonic-gate * uzero or bzero was called with t_lofault non-zero. 13547c478bd9Sstevel@tonic-gate * Otherwise we've already run screaming from the room. 13557c478bd9Sstevel@tonic-gate * Errno value is in %g1. Note that we're here iff 13567c478bd9Sstevel@tonic-gate * we did set t_lofault. 13577c478bd9Sstevel@tonic-gate */ 13587c478bd9Sstevel@tonic-gate.zeroerr: 13597c478bd9Sstevel@tonic-gate ! 13607c478bd9Sstevel@tonic-gate ! Undo asi register setting. Just set it to be the 13617c478bd9Sstevel@tonic-gate ! kernel default without checking. 13627c478bd9Sstevel@tonic-gate ! 13637c478bd9Sstevel@tonic-gate wr %g0, ASI_P, %asi 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate ! 13667c478bd9Sstevel@tonic-gate ! We did set t_lofault. It may well have been zero coming in. 13677c478bd9Sstevel@tonic-gate ! 13687c478bd9Sstevel@tonic-gate1: 13697c478bd9Sstevel@tonic-gate tst %o5 13707c478bd9Sstevel@tonic-gate membar #Sync 13717c478bd9Sstevel@tonic-gate bne,pn %ncc, 3f 13727c478bd9Sstevel@tonic-gate andncc %o5, LOFAULT_SET, %o5 13737c478bd9Sstevel@tonic-gate2: 13747c478bd9Sstevel@tonic-gate ! 13757c478bd9Sstevel@tonic-gate ! Old handler was zero. Just return the error. 13767c478bd9Sstevel@tonic-gate ! 13777c478bd9Sstevel@tonic-gate retl ! return 13787c478bd9Sstevel@tonic-gate mov %g1, %o0 ! error code from %g1 13797c478bd9Sstevel@tonic-gate3: 13807c478bd9Sstevel@tonic-gate ! 13817c478bd9Sstevel@tonic-gate ! We're here because %o5 was non-zero. It was non-zero 13827c478bd9Sstevel@tonic-gate ! because either LOFAULT_SET was present, a previous fault 13837c478bd9Sstevel@tonic-gate ! handler was present or both. In all cases we need to reset 13847c478bd9Sstevel@tonic-gate ! T_LOFAULT to the value of %o5 after clearing LOFAULT_SET 13857c478bd9Sstevel@tonic-gate ! before we either simply return the error or we invoke the 13867c478bd9Sstevel@tonic-gate ! previously specified handler. 13877c478bd9Sstevel@tonic-gate ! 13887c478bd9Sstevel@tonic-gate be %ncc, 2b 13897c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] 13907c478bd9Sstevel@tonic-gate jmp %o5 ! goto real handler 13917c478bd9Sstevel@tonic-gate nop 13927c478bd9Sstevel@tonic-gate SET_SIZE(kzero) 13937c478bd9Sstevel@tonic-gate SET_SIZE(uzero) 13947c478bd9Sstevel@tonic-gate 13957c478bd9Sstevel@tonic-gate#endif /* lint */ 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate/* 13987c478bd9Sstevel@tonic-gate * Zero a block of storage. 13997c478bd9Sstevel@tonic-gate */ 14007c478bd9Sstevel@tonic-gate 14017c478bd9Sstevel@tonic-gate#if defined(lint) 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate/* ARGSUSED */ 14047c478bd9Sstevel@tonic-gatevoid 14057c478bd9Sstevel@tonic-gatebzero(void *addr, size_t count) 14067c478bd9Sstevel@tonic-gate{} 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate#else /* lint */ 14097c478bd9Sstevel@tonic-gate 14107c478bd9Sstevel@tonic-gate ENTRY(bzero) 14117c478bd9Sstevel@tonic-gate wr %g0, ASI_P, %asi 14127c478bd9Sstevel@tonic-gate 14137c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_LOFAULT], %o5 ! save old vector 14147c478bd9Sstevel@tonic-gate tst %o5 14157c478bd9Sstevel@tonic-gate bz,pt %ncc, .do_zero 14167c478bd9Sstevel@tonic-gate sethi %hi(.zeroerr), %o2 14177c478bd9Sstevel@tonic-gate or %o2, %lo(.zeroerr), %o2 14187c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 14197c478bd9Sstevel@tonic-gate stn %o2, [THREAD_REG + T_LOFAULT] ! install new vector 14207c478bd9Sstevel@tonic-gate 14217c478bd9Sstevel@tonic-gate.do_zero: 14227c478bd9Sstevel@tonic-gate cmp %o1, 7 14237c478bd9Sstevel@tonic-gate blu,pn %ncc, .byteclr 14247c478bd9Sstevel@tonic-gate nop 14257c478bd9Sstevel@tonic-gate 14267c478bd9Sstevel@tonic-gate cmp %o1, 15 14277c478bd9Sstevel@tonic-gate blu,pn %ncc, .wdalign 14287c478bd9Sstevel@tonic-gate nop 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate andcc %o0, 7, %o3 ! is add aligned on a 8 byte bound 14317c478bd9Sstevel@tonic-gate bz,pt %ncc, .blkalign ! already double aligned 14327c478bd9Sstevel@tonic-gate sub %o3, 8, %o3 ! -(bytes till double aligned) 14337c478bd9Sstevel@tonic-gate add %o1, %o3, %o1 ! update o1 with new count 14347c478bd9Sstevel@tonic-gate 14357c478bd9Sstevel@tonic-gate1: 14367c478bd9Sstevel@tonic-gate stba %g0, [%o0]%asi 14377c478bd9Sstevel@tonic-gate inccc %o3 14387c478bd9Sstevel@tonic-gate bl,pt %ncc, 1b 14397c478bd9Sstevel@tonic-gate inc %o0 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate ! Now address is double aligned 14427c478bd9Sstevel@tonic-gate.blkalign: 14437c478bd9Sstevel@tonic-gate cmp %o1, 0x80 ! check if there are 128 bytes to set 14447c478bd9Sstevel@tonic-gate blu,pn %ncc, .bzero_small 14457c478bd9Sstevel@tonic-gate mov %o1, %o3 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate andcc %o0, 0x3f, %o3 ! is block aligned? 14487c478bd9Sstevel@tonic-gate bz,pt %ncc, .bzero_blk 14497c478bd9Sstevel@tonic-gate sub %o3, 0x40, %o3 ! -(bytes till block aligned) 14507c478bd9Sstevel@tonic-gate add %o1, %o3, %o1 ! o1 is the remainder 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate ! Clear -(%o3) bytes till block aligned 14537c478bd9Sstevel@tonic-gate1: 14547c478bd9Sstevel@tonic-gate stxa %g0, [%o0]%asi 14557c478bd9Sstevel@tonic-gate addcc %o3, 8, %o3 14567c478bd9Sstevel@tonic-gate bl,pt %ncc, 1b 14577c478bd9Sstevel@tonic-gate add %o0, 8, %o0 14587c478bd9Sstevel@tonic-gate 14597c478bd9Sstevel@tonic-gate.bzero_blk: 14607c478bd9Sstevel@tonic-gate and %o1, 0x3f, %o3 ! calc bytes left after blk clear 14617c478bd9Sstevel@tonic-gate andn %o1, 0x3f, %o4 ! calc size of blocks in bytes 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate cmp %o4, 0x100 ! 256 bytes or more 14647c478bd9Sstevel@tonic-gate blu,pn %ncc, 3f 14657c478bd9Sstevel@tonic-gate nop 14667c478bd9Sstevel@tonic-gate 14677c478bd9Sstevel@tonic-gate2: 14687c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x0]%asi 14697c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x40]%asi 14707c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x80]%asi 14717c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0xc0]%asi 14727c478bd9Sstevel@tonic-gate 14737c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x8]%asi 14747c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x10]%asi 14757c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x18]%asi 14767c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x20]%asi 14777c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x28]%asi 14787c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x30]%asi 14797c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x38]%asi 14807c478bd9Sstevel@tonic-gate 14817c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x48]%asi 14827c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x50]%asi 14837c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x58]%asi 14847c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x60]%asi 14857c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x68]%asi 14867c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x70]%asi 14877c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x78]%asi 14887c478bd9Sstevel@tonic-gate 14897c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x88]%asi 14907c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x90]%asi 14917c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x98]%asi 14927c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0xa0]%asi 14937c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0xa8]%asi 14947c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0xb0]%asi 14957c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0xb8]%asi 14967c478bd9Sstevel@tonic-gate 14977c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0xc8]%asi 14987c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0xd0]%asi 14997c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0xd8]%asi 15007c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0xe0]%asi 15017c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0xe8]%asi 15027c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0xf0]%asi 15037c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0xf8]%asi 15047c478bd9Sstevel@tonic-gate 15057c478bd9Sstevel@tonic-gate sub %o4, 0x100, %o4 15067c478bd9Sstevel@tonic-gate cmp %o4, 0x100 15077c478bd9Sstevel@tonic-gate bgu,pt %ncc, 2b 15087c478bd9Sstevel@tonic-gate add %o0, 0x100, %o0 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate3: 15117c478bd9Sstevel@tonic-gate ! ... check if 64 bytes to set 15127c478bd9Sstevel@tonic-gate cmp %o4, 0x40 15137c478bd9Sstevel@tonic-gate blu %ncc, .bzero_blk_done 15147c478bd9Sstevel@tonic-gate nop 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate4: 15177c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x0]%asi 15187c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x8]%asi 15197c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x10]%asi 15207c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x18]%asi 15217c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x20]%asi 15227c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x28]%asi 15237c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x30]%asi 15247c478bd9Sstevel@tonic-gate stxa %g0, [%o0+0x38]%asi 15257c478bd9Sstevel@tonic-gate 15267c478bd9Sstevel@tonic-gate subcc %o4, 0x40, %o4 15277c478bd9Sstevel@tonic-gate bgu,pt %ncc, 3b 15287c478bd9Sstevel@tonic-gate add %o0, 0x40, %o0 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate.bzero_blk_done: 15317c478bd9Sstevel@tonic-gate membar #Sync 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate.bzero_small: 15347c478bd9Sstevel@tonic-gate ! Set the remaining doubles 15357c478bd9Sstevel@tonic-gate subcc %o3, 8, %o3 ! Can we store any doubles? 15367c478bd9Sstevel@tonic-gate blu,pn %ncc, .byteclr 15377c478bd9Sstevel@tonic-gate and %o1, 7, %o1 ! calc bytes left after doubles 15387c478bd9Sstevel@tonic-gate 15397c478bd9Sstevel@tonic-gate.dbclr: 15407c478bd9Sstevel@tonic-gate stxa %g0, [%o0]%asi ! Clear the doubles 15417c478bd9Sstevel@tonic-gate subcc %o3, 8, %o3 15427c478bd9Sstevel@tonic-gate bgeu,pt %ncc, .dbclr 15437c478bd9Sstevel@tonic-gate add %o0, 8, %o0 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate ba .byteclr 15467c478bd9Sstevel@tonic-gate nop 15477c478bd9Sstevel@tonic-gate 15487c478bd9Sstevel@tonic-gate.wdalign: 15497c478bd9Sstevel@tonic-gate andcc %o0, 3, %o3 ! is add aligned on a word boundary 15507c478bd9Sstevel@tonic-gate bz,pn %ncc, .wdclr 15517c478bd9Sstevel@tonic-gate andn %o1, 3, %o3 ! create word sized count in %o3 15527c478bd9Sstevel@tonic-gate 15537c478bd9Sstevel@tonic-gate dec %o1 ! decrement count 15547c478bd9Sstevel@tonic-gate stba %g0, [%o0]%asi ! clear a byte 15557c478bd9Sstevel@tonic-gate ba .wdalign 15567c478bd9Sstevel@tonic-gate inc %o0 ! next byte 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate.wdclr: 15597c478bd9Sstevel@tonic-gate sta %g0, [%o0]%asi ! 4-byte clearing loop 15607c478bd9Sstevel@tonic-gate subcc %o3, 4, %o3 15617c478bd9Sstevel@tonic-gate bnz,pt %ncc, .wdclr 15627c478bd9Sstevel@tonic-gate inc 4, %o0 15637c478bd9Sstevel@tonic-gate 15647c478bd9Sstevel@tonic-gate and %o1, 3, %o1 ! leftover count, if any 15657c478bd9Sstevel@tonic-gate 15667c478bd9Sstevel@tonic-gate.byteclr: 15677c478bd9Sstevel@tonic-gate ! Set the leftover bytes 15687c478bd9Sstevel@tonic-gate brz %o1, .bzero_exit 15697c478bd9Sstevel@tonic-gate nop 15707c478bd9Sstevel@tonic-gate 15717c478bd9Sstevel@tonic-gate7: 15727c478bd9Sstevel@tonic-gate deccc %o1 ! byte clearing loop 15737c478bd9Sstevel@tonic-gate stba %g0, [%o0]%asi 15747c478bd9Sstevel@tonic-gate bgu,pt %ncc, 7b 15757c478bd9Sstevel@tonic-gate inc %o0 15767c478bd9Sstevel@tonic-gate 15777c478bd9Sstevel@tonic-gate.bzero_exit: 15787c478bd9Sstevel@tonic-gate ! 15797c478bd9Sstevel@tonic-gate ! We're just concerned with whether t_lofault was set 15807c478bd9Sstevel@tonic-gate ! when we came in. We end up here from either kzero() 15817c478bd9Sstevel@tonic-gate ! or bzero(). kzero() *always* sets a lofault handler. 15827c478bd9Sstevel@tonic-gate ! It ors LOFAULT_SET into %o5 to indicate it has done 15837c478bd9Sstevel@tonic-gate ! this even if the value of %o5 is otherwise zero. 15847c478bd9Sstevel@tonic-gate ! bzero() sets a lofault handler *only* if one was 15857c478bd9Sstevel@tonic-gate ! previously set. Accordingly we need to examine 15867c478bd9Sstevel@tonic-gate ! %o5 and if it is non-zero be sure to clear LOFAULT_SET 15877c478bd9Sstevel@tonic-gate ! before resetting the error handler. 15887c478bd9Sstevel@tonic-gate ! 15897c478bd9Sstevel@tonic-gate tst %o5 15907c478bd9Sstevel@tonic-gate bz %ncc, 1f 15917c478bd9Sstevel@tonic-gate andn %o5, LOFAULT_SET, %o5 15927c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 15937c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] ! restore old t_lofault 15947c478bd9Sstevel@tonic-gate1: 15957c478bd9Sstevel@tonic-gate retl 15967c478bd9Sstevel@tonic-gate clr %o0 ! return (0) 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate SET_SIZE(bzero) 15997c478bd9Sstevel@tonic-gate#endif /* lint */ 1600