Index: head/sys/alpha/alpha/support.s =================================================================== --- head/sys/alpha/alpha/support.s (revision 130163) +++ head/sys/alpha/alpha/support.s (revision 130164) @@ -1,693 +1,691 @@ /*- * Copyright (c) 1998 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. * All rights reserved. * * Author: Chris G. Demetriou * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #include #include .text /**************************************************************************/ /* * intptr_t * casuptr(intptr_t *p, intptr_t old, intptr_t new) */ LEAF(casuptr, 3) LDGP(pv) ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ cmpult a0, t0, t1 beq t1, fusufault lda t0, fusufault /* trap faults */ ldq t2, PC_CURTHREAD(pcpup) ldq t2, TD_PCB(t2) stq t0, PCB_ONFAULT(t2) 1: ldq_l v0, 0(a0) /* try to load the old value */ cmpeq v0, a1, t0 /* compare */ beq t0, 2f /* exit if not equal */ mov a2, t0 /* setup value to write */ stq_c t0, 0(a0) /* write if address still locked */ beq t0, 1b /* if it failed, spin */ 2: stq zero, PCB_ONFAULT(t2) /* clean up */ RET END(casuptr) /* * fu{byte,word} : fetch a byte (word) from user memory */ LEAF(suword, 1) XLEAF(suword64, 1) LDGP(pv) ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ cmpult a0, t0, t1 beq t1, fusufault lda t0, fusufault /* trap faults */ ldq t2, PC_CURTHREAD(pcpup) ldq t2, TD_PCB(t2) stq t0, PCB_ONFAULT(t2) stq a1, 0(a0) /* try the store */ stq zero, PCB_ONFAULT(t2) /* clean up */ mov zero, v0 RET END(suword) LEAF(suword32, 2) LDGP(pv) ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ cmpult a0, t0, t1 beq t1, fusufault lda t0, fusufault /* trap faults */ ldq t2, PC_CURTHREAD(pcpup) ldq t2, TD_PCB(t2) stq t0, PCB_ONFAULT(t2) stl a1, 0(a0) /* try the store */ stq zero, PCB_ONFAULT(t2) /* clean up */ mov zero, v0 RET END(suword32) LEAF(subyte, 1) LDGP(pv) ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ cmpult a0, t0, t1 beq t1, fusufault lda t0, fusufault /* trap faults */ ldq t2, PC_CURTHREAD(pcpup) ldq t2, TD_PCB(t2) stq t0, PCB_ONFAULT(t2) zap a1, 0xfe, a1 /* mask off the byte to store */ insbl a1, a0, a1 /* shift it to the right place */ ldq_u t0, 0(a0) /* read the qword to store it in */ mskbl t0, a0, t0 /* make a place for our byte */ or a1, t0, a1 /* move it in */ stq_u a1, 0(a0) /* and put the byte back */ stq zero, PCB_ONFAULT(t2) /* clean up */ mov zero, v0 RET END(subyte) LEAF(fuword, 1) XLEAF(fuword64, 1) LDGP(pv) ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ cmpult a0, t0, t1 beq t1, fusufault lda t0, fusufault /* trap faults */ ldq t2, PC_CURTHREAD(pcpup) ldq t2, TD_PCB(t2) stq t0, PCB_ONFAULT(t2) ldq v0, 0(a0) /* try the fetch */ stq zero, PCB_ONFAULT(t2) /* clean up */ RET END(fuword) LEAF(fuword32, 1) LDGP(pv) ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ cmpult a0, t0, t1 beq t1, fusufault lda t0, fusufault /* trap faults */ ldq t2, PC_CURTHREAD(pcpup) ldq t2, TD_PCB(t2) stq t0, PCB_ONFAULT(t2) ldl v0, 0(a0) /* get the word containing our byte */ stq zero, PCB_ONFAULT(t2) /* clean up */ RET END(fuword32) LEAF(fubyte, 1) LDGP(pv) ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ cmpult a0, t0, t1 beq t1, fusufault lda t0, fusufault /* trap faults */ ldq t2, PC_CURTHREAD(pcpup) ldq t2, TD_PCB(t2) stq t0, PCB_ONFAULT(t2) ldq_u v0, 0(a0) /* get the word containing our byte */ extbl v0, a0, v0 /* extract the byte */ stq zero, PCB_ONFAULT(t2) /* clean up */ RET END(fubyte) LEAF(fusufault, 0) ldq t0, PC_CURTHREAD(pcpup) ldq t0, TD_PCB(t0) stq zero, PCB_ONFAULT(t0) ldiq v0, -1 RET END(fusufault) LEAF(fswintrberr, 0) XLEAF(fuswintr, 2) /* XXX 16 bit short for profiling */ XLEAF(suswintr, 2) /* XXX 16 bit short for profiling */ LDGP(pv) ldiq v0, -1 RET END(fswintrberr) /**************************************************************************/ /* * Copy a null-terminated string within the kernel's address space. * If lenp is not NULL, store the number of chars copied in *lenp * * int copystr(char *from, char *to, size_t len, size_t *lenp); */ LEAF(copystr, 4) LDGP(pv) mov a2, t0 /* t0 = i = len */ beq a2, Lcopystr2 /* if (len == 0), bail out */ Lcopystr1: ldq_u t1, 0(a0) /* t1 = *from */ extbl t1, a0, t1 ldq_u t3, 0(a1) /* set up t2 with quad around *to */ insbl t1, a1, t2 mskbl t3, a1, t3 or t3, t2, t3 /* add *from to quad around *to */ stq_u t3, 0(a1) /* write out that quad */ subl a2, 1, a2 /* len-- */ beq t1, Lcopystr2 /* if (*from == 0), bail out */ addq a1, 1, a1 /* to++ */ addq a0, 1, a0 /* from++ */ bne a2, Lcopystr1 /* if (len != 0) copy more */ Lcopystr2: beq a3, Lcopystr3 /* if (lenp != NULL) */ subl t0, a2, t0 /* *lenp = (i - len) */ stq t0, 0(a3) Lcopystr3: beq t1, Lcopystr4 /* *from == '\0'; leave quietly */ ldiq v0, ENAMETOOLONG /* *from != '\0'; error. */ RET Lcopystr4: mov zero, v0 /* return 0. */ RET END(copystr) NESTED(copyinstr, 4, 16, ra, 0, 0) LDGP(pv) lda sp, -16(sp) /* set up stack frame */ stq ra, (16-8)(sp) /* save ra */ ldiq t0, VM_MAXUSER_ADDRESS /* make sure that src addr */ cmpult a0, t0, t1 /* is in user space. */ beq t1, copyerr /* if it's not, error out. */ lda v0, copyerr /* set up fault handler. */ .set noat ldq at_reg, PC_CURTHREAD(pcpup) ldq at_reg, TD_PCB(at_reg) stq v0, PCB_ONFAULT(at_reg) .set at CALL(copystr) /* do the copy. */ .set noat ldq at_reg, PC_CURTHREAD(pcpup) /* kill the fault handler. */ ldq at_reg, TD_PCB(at_reg) stq zero, PCB_ONFAULT(at_reg) .set at ldq ra, (16-8)(sp) /* restore ra. */ lda sp, 16(sp) /* kill stack frame. */ RET /* v0 left over from copystr */ END(copyinstr) NESTED(copyoutstr, 4, 16, ra, 0, 0) LDGP(pv) lda sp, -16(sp) /* set up stack frame */ stq ra, (16-8)(sp) /* save ra */ ldiq t0, VM_MAXUSER_ADDRESS /* make sure that dest addr */ cmpult a1, t0, t1 /* is in user space. */ beq t1, copyerr /* if it's not, error out. */ lda v0, copyerr /* set up fault handler. */ .set noat ldq at_reg, PC_CURTHREAD(pcpup) ldq at_reg, TD_PCB(at_reg) stq v0, PCB_ONFAULT(at_reg) .set at CALL(copystr) /* do the copy. */ .set noat ldq at_reg, PC_CURTHREAD(pcpup) /* kill the fault handler. */ ldq at_reg, TD_PCB(at_reg) stq zero, PCB_ONFAULT(at_reg) .set at ldq ra, (16-8)(sp) /* restore ra. */ lda sp, 16(sp) /* kill stack frame. */ RET /* v0 left over from copystr */ END(copyoutstr) /* * Alternative memory mover */ LEAF(memcpy,3) mov a0,t0 mov a1,a0 mov t0,a1 br bcopy END(memcpy) /* * Copy a bytes within the kernel's address space. * Handles overlapping regions. * * void bcopy(char *from, char *to, size_t len); */ LEAF(bcopy,3) /* Check for negative length */ ble a2,bcopy_done /* Check for overlap */ subq a1,a0,t5 cmpult t5,a2,t5 bne t5,bcopy_overlap /* a3 = end address */ addq a0,a2,a3 /* Get the first word */ ldq_u t2,0(a0) /* Do they have the same alignment? */ xor a0,a1,t0 and t0,7,t0 and a1,7,t1 bne t0,bcopy_different_alignment /* src & dst have same alignment */ beq t1,bcopy_all_aligned ldq_u t3,0(a1) addq a2,t1,a2 mskqh t2,a0,t2 mskql t3,a0,t3 or t2,t3,t2 /* Dst is 8-byte aligned */ bcopy_all_aligned: /* If less than 8 bytes,skip loop */ subq a2,1,t0 and a2,7,a2 bic t0,7,t0 beq t0,bcopy_samealign_lp_end bcopy_samealign_lp: stq_u t2,0(a1) addq a1,8,a1 ldq_u t2,8(a0) subq t0,8,t0 addq a0,8,a0 bne t0,bcopy_samealign_lp bcopy_samealign_lp_end: /* If we're done, exit */ bne a2,bcopy_small_left stq_u t2,0(a1) RET bcopy_small_left: mskql t2,a2,t4 ldq_u t3,0(a1) mskqh t3,a2,t3 or t4,t3,t4 stq_u t4,0(a1) RET bcopy_different_alignment: /* * this is the fun part */ addq a0,a2,a3 cmpule a2,8,t0 bne t0,bcopy_da_finish beq t1,bcopy_da_noentry /* Do the initial partial word */ subq zero,a1,t0 and t0,7,t0 ldq_u t3,7(a0) extql t2,a0,t2 extqh t3,a0,t3 or t2,t3,t5 insql t5,a1,t5 ldq_u t6,0(a1) mskql t6,a1,t6 or t5,t6,t5 stq_u t5,0(a1) addq a0,t0,a0 addq a1,t0,a1 subq a2,t0,a2 ldq_u t2,0(a0) bcopy_da_noentry: subq a2,1,t0 bic t0,7,t0 and a2,7,a2 beq t0,bcopy_da_finish2 bcopy_da_lp: ldq_u t3,7(a0) addq a0,8,a0 extql t2,a0,t4 extqh t3,a0,t5 subq t0,8,t0 or t4,t5,t5 stq t5,0(a1) addq a1,8,a1 beq t0,bcopy_da_finish1 ldq_u t2,7(a0) addq a0,8,a0 extql t3,a0,t4 extqh t2,a0,t5 subq t0,8,t0 or t4,t5,t5 stq t5,0(a1) addq a1,8,a1 bne t0,bcopy_da_lp bcopy_da_finish2: /* Do the last new word */ mov t2,t3 bcopy_da_finish1: /* Do the last partial word */ ldq_u t2,-1(a3) extql t3,a0,t3 extqh t2,a0,t2 or t2,t3,t2 br zero,bcopy_samealign_lp_end bcopy_da_finish: /* Do the last word in the next source word */ ldq_u t3,-1(a3) extql t2,a0,t2 extqh t3,a0,t3 or t2,t3,t2 insqh t2,a1,t3 insql t2,a1,t2 lda t4,-1(zero) mskql t4,a2,t5 cmovne t5,t5,t4 insqh t4,a1,t5 insql t4,a1,t4 addq a1,a2,a4 ldq_u t6,0(a1) ldq_u t8,-1(a4) bic t6,t4,t6 bic t8,t5,t8 and t2,t4,t2 and t3,t5,t3 or t2,t6,t2 or t3,t8,t3 stq_u t3,-1(a4) stq_u t2,0(a1) RET bcopy_overlap: /* * Basically equivalent to previous case, only backwards. * Not quite as highly optimized */ addq a0,a2,a3 addq a1,a2,a4 /* less than 8 bytes - don't worry about overlap */ cmpule a2,8,t0 bne t0,bcopy_ov_short /* Possibly do a partial first word */ and a4,7,t4 beq t4,bcopy_ov_nostart2 subq a3,t4,a3 subq a4,t4,a4 ldq_u t1,0(a3) subq a2,t4,a2 ldq_u t2,7(a3) ldq t3,0(a4) extql t1,a3,t1 extqh t2,a3,t2 or t1,t2,t1 mskqh t3,t4,t3 mskql t1,t4,t1 or t1,t3,t1 stq t1,0(a4) bcopy_ov_nostart2: bic a2,7,t4 and a2,7,a2 beq t4,bcopy_ov_lp_end bcopy_ov_lp: /* This could be more pipelined, but it doesn't seem worth it */ ldq_u t0,-8(a3) subq a4,8,a4 ldq_u t1,-1(a3) subq a3,8,a3 extql t0,a3,t0 extqh t1,a3,t1 subq t4,8,t4 or t0,t1,t0 stq t0,0(a4) bne t4,bcopy_ov_lp bcopy_ov_lp_end: beq a2,bcopy_done ldq_u t0,0(a0) ldq_u t1,7(a0) ldq_u t2,0(a1) extql t0,a0,t0 extqh t1,a0,t1 or t0,t1,t0 insql t0,a1,t0 mskql t2,a1,t2 or t2,t0,t2 stq_u t2,0(a1) bcopy_done: RET bcopy_ov_short: ldq_u t2,0(a0) br zero,bcopy_da_finish END(bcopy) NESTED(copyin, 3, 16, ra, 0, 0) LDGP(pv) lda sp, -16(sp) /* set up stack frame */ stq ra, (16-8)(sp) /* save ra */ ldiq t0, VM_MAXUSER_ADDRESS /* make sure that src addr */ cmpult a0, t0, t1 /* is in user space. */ beq t1, copyerr /* if it's not, error out. */ lda v0, copyerr /* set up fault handler. */ .set noat ldq at_reg, PC_CURTHREAD(pcpup) ldq at_reg, TD_PCB(at_reg) stq v0, PCB_ONFAULT(at_reg) .set at CALL(bcopy) /* do the copy. */ .set noat ldq at_reg, PC_CURTHREAD(pcpup) /* kill the fault handler. */ ldq at_reg, TD_PCB(at_reg) stq zero, PCB_ONFAULT(at_reg) .set at ldq ra, (16-8)(sp) /* restore ra. */ lda sp, 16(sp) /* kill stack frame. */ mov zero, v0 /* return 0. */ RET END(copyin) NESTED(copyout, 3, 16, ra, 0, 0) LDGP(pv) lda sp, -16(sp) /* set up stack frame */ stq ra, (16-8)(sp) /* save ra */ ldiq t0, VM_MAXUSER_ADDRESS /* make sure that dest addr */ cmpult a1, t0, t1 /* is in user space. */ beq t1, copyerr /* if it's not, error out. */ lda v0, copyerr /* set up fault handler. */ .set noat ldq at_reg, PC_CURTHREAD(pcpup) ldq at_reg, TD_PCB(at_reg) stq v0, PCB_ONFAULT(at_reg) .set at CALL(bcopy) /* do the copy. */ .set noat ldq at_reg, PC_CURTHREAD(pcpup) /* kill the fault handler. */ ldq at_reg, TD_PCB(at_reg) stq zero, PCB_ONFAULT(at_reg) .set at ldq ra, (16-8)(sp) /* restore ra. */ lda sp, 16(sp) /* kill stack frame. */ mov zero, v0 /* return 0. */ RET END(copyout) LEAF(copyerr, 0) ldq t0, PC_CURTHREAD(pcpup) ldq t0, TD_PCB(t0) stq zero, PCB_ONFAULT(t0) /* reset fault handler. */ ldq ra, (16-8)(sp) /* restore ra. */ lda sp, 16(sp) /* kill stack frame. */ ldiq v0, EFAULT /* return EFAULT. */ RET END(copyerr) /**************************************************************************/ /* * Kernel setjmp and longjmp. Rather minimalist. * * longjmp(label_t *a) * will generate a "return (1)" from the last call to * setjmp(label_t *a) * by restoring registers from the stack, */ .set noreorder LEAF(setjmp, 1) LDGP(pv) stq ra, (0 * 8)(a0) /* return address */ stq s0, (1 * 8)(a0) /* callee-saved registers */ stq s1, (2 * 8)(a0) stq s2, (3 * 8)(a0) stq s3, (4 * 8)(a0) stq s4, (5 * 8)(a0) stq s5, (6 * 8)(a0) stq s6, (7 * 8)(a0) stq sp, (8 * 8)(a0) ldiq t0, 0xbeeffedadeadbabe /* set magic number */ stq t0, (9 * 8)(a0) mov zero, v0 /* return zero */ RET END(setjmp) LEAF(longjmp, 1) LDGP(pv) ldiq t0, 0xbeeffedadeadbabe /* check magic number */ ldq t1, (9 * 8)(a0) cmpeq t0, t1, t0 beq t0, longjmp_botch /* if bad, punt */ ldq ra, (0 * 8)(a0) /* return address */ ldq s0, (1 * 8)(a0) /* callee-saved registers */ ldq s1, (2 * 8)(a0) ldq s2, (3 * 8)(a0) ldq s3, (4 * 8)(a0) ldq s4, (5 * 8)(a0) ldq s5, (6 * 8)(a0) ldq s6, (7 * 8)(a0) ldq sp, (8 * 8)(a0) ldiq v0, 1 RET longjmp_botch: lda a0, longjmp_botchmsg - mov 0, a1 - mov 0, a2 - mov ra, a3 - CALL(__panic) + mov ra, a1 + CALL(panic) call_pal PAL_bugchk .data longjmp_botchmsg: .asciz "longjmp botch from %p" .text END(longjmp) Index: head/sys/arm/arm/exception.S =================================================================== --- head/sys/arm/arm/exception.S (revision 130163) +++ head/sys/arm/arm/exception.S (revision 130164) @@ -1,392 +1,379 @@ /* $NetBSD: exception.S,v 1.13 2003/10/31 16:30:15 scw Exp $ */ /* * Copyright (c) 1994-1997 Mark Brinicombe. * Copyright (c) 1994 Brini. * All rights reserved. * * This code is derived from software written for Brini by Mark Brinicombe * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Brini. * 4. The name of the company nor the name of the author may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * RiscBSD kernel project * * exception.S * * Low level handlers for exception vectors * * Created : 24/09/94 * * Based on kate/display/abort.s * */ #include "assym.s" #include #include #include __FBSDID("$FreeBSD$"); .text .align 0 AST_ALIGNMENT_FAULT_LOCALS /* * reset_entry: * * Handler for Reset exception. */ ASENTRY_NP(reset_entry) adr r0, Lreset_panicmsg - adr r1, Lfile - mov r2, #__LINE__ - bl _C_LABEL(__panic) + bl _C_LABEL(panic) /* NOTREACHED */ Lreset_panicmsg: .asciz "Reset vector called, LR = 0x%08x" -Lfile: - .asciz __FILE__ .balign 4 /* * swi_entry * * Handler for the Software Interrupt exception. */ ASENTRY_NP(swi_entry) PUSHFRAME ENABLE_ALIGNMENT_FAULTS mov r0, sp /* Pass the frame to any function */ bl _C_LABEL(swi_handler) /* It's a SWI ! */ DO_AST_AND_RESTORE_ALIGNMENT_FAULTS PULLFRAME movs pc, lr /* Exit */ /* * prefetch_abort_entry: * * Handler for the Prefetch Abort exception. */ ASENTRY_NP(prefetch_abort_entry) #ifdef __XSCALE__ nop /* Make absolutely sure any pending */ nop /* imprecise aborts have occurred. */ #endif sub lr, lr, #0x00000004 /* Adjust the lr */ PUSHFRAMEINSVC ENABLE_ALIGNMENT_FAULTS ldr r1, Lprefetch_abort_handler_address adr lr, exception_exit mov r0, sp /* pass the stack pointer as r0 */ ldr pc, [r1] Lprefetch_abort_handler_address: .word _C_LABEL(prefetch_abort_handler_address) .data .global _C_LABEL(prefetch_abort_handler_address) _C_LABEL(prefetch_abort_handler_address): .word abortprefetch .text abortprefetch: adr r0, abortprefetchmsg - adr r1, filee - mov r2, #__LINE__ - b _C_LABEL(__panic) + b _C_LABEL(panic) -filee: - .asciz __FILE__ - abortprefetchmsg: .asciz "abortprefetch" .align 0 /* * data_abort_entry: * * Handler for the Data Abort exception. */ ASENTRY_NP(data_abort_entry) #ifdef __XSCALE__ nop /* Make absolutely sure any pending */ nop /* imprecise aborts have occurred. */ #endif sub lr, lr, #0x00000008 /* Adjust the lr */ PUSHFRAMEINSVC /* Push trap frame and switch */ /* to SVC32 mode */ ENABLE_ALIGNMENT_FAULTS ldr r1, Ldata_abort_handler_address adr lr, exception_exit mov r0, sp /* pass the stack pointer as r0 */ ldr pc, [r1] Ldata_abort_handler_address: .word _C_LABEL(data_abort_handler_address) .data .global _C_LABEL(data_abort_handler_address) _C_LABEL(data_abort_handler_address): .word abortdata .text abortdata: adr r0, abortdatamsg - adr r1, file - mov r2, #__LINE__ - b _C_LABEL(__panic) + b _C_LABEL(panic) abortdatamsg: .asciz "abortdata" -file: - .asciz __FILE__ .align 0 /* * address_exception_entry: * * Handler for the Address Exception exception. * * NOTE: This exception isn't really used on arm32. We * print a warning message to the console and then treat * it like a Data Abort. */ ASENTRY_NP(address_exception_entry) mrs r1, cpsr_all mrs r2, spsr_all mov r3, lr adr r0, Laddress_exception_msg bl _C_LABEL(printf) /* XXX CLOBBERS LR!! */ b data_abort_entry Laddress_exception_msg: .asciz "Address Exception CPSR=0x%08x SPSR=0x%08x LR=0x%08x\n" .balign 4 /* * General exception exit handler * (Placed here to be within range of all the references to it) * * It exits straight away if not returning to USR mode. * This loops around delivering any pending ASTs. * Interrupts are disabled at suitable points to avoid ASTs * being posted between testing and exit to user mode. * * This function uses PULLFRAMEFROMSVCANDEXIT and * DO_AST_AND_RESTORE_ALIGNMENT_FAULTS thus should * only be called if the exception handler used PUSHFRAMEINSVC * followed by ENABLE_ALIGNMENT_FAULTS. */ exception_exit: DO_AST_AND_RESTORE_ALIGNMENT_FAULTS PULLFRAMEFROMSVCANDEXIT /* * undefined_entry: * * Handler for the Undefined Instruction exception. * * We indirect the undefined vector via the handler address * in the data area. Entry to the undefined handler must * look like direct entry from the vector. */ ASENTRY_NP(undefined_entry) #ifdef IPKDB /* * IPKDB must be hooked in at the earliest possible entry point. * */ /* * Make room for all registers saving real r0-r7 and r15. * The remaining registers are updated later. */ stmfd sp!, {r0,r1} /* psr & spsr */ stmfd sp!, {lr} /* pc */ stmfd sp!, {r0-r14} /* r0-r7, r8-r14 */ /* * Get previous psr. */ mrs r7, cpsr_all mrs r0, spsr_all str r0, [sp, #(16*4)] /* * Test for user mode. */ tst r0, #0xf bne .Lprenotuser_push add r1, sp, #(8*4) stmia r1,{r8-r14}^ /* store user mode r8-r14*/ b .Lgoipkdb /* * Switch to previous mode to get r8-r13. */ .Lprenotuser_push: orr r0, r0, #(I32_bit) /* disable interrupts */ msr cpsr_all, r0 mov r1, r8 mov r2, r9 mov r3, r10 mov r4, r11 mov r5, r12 mov r6, r13 msr cpsr_all, r7 /* back to undefined mode */ add r8, sp, #(8*4) stmia r8, {r1-r6} /* r8-r13 */ /* * Now back to previous mode to get r14 and spsr. */ msr cpsr_all, r0 mov r1, r14 mrs r2, spsr msr cpsr_all, r7 /* back to undefined mode */ str r1, [sp, #(14*4)] /* r14 */ str r2, [sp, #(17*4)] /* spsr */ /* * Now to IPKDB. */ .Lgoipkdb: mov r0, sp bl _C_LABEL(ipkdb_trap_glue) ldr r1, .Lipkdb_trap_return str r0,[r1] /* * Have to load all registers from the stack. * * Start with spsr and pc. */ ldr r0, [sp, #(16*4)] /* spsr */ ldr r1, [sp, #(15*4)] /* r15 */ msr spsr_all, r0 mov r14, r1 /* * Test for user mode. */ tst r0, #0xf bne .Lprenotuser_pull add r1, sp, #(8*4) ldmia r1, {r8-r14}^ /* load user mode r8-r14 */ b .Lpull_r0r7 .Lprenotuser_pull: /* * Now previous mode spsr and r14. */ ldr r1, [sp, #(17*4)] /* spsr */ ldr r2, [sp, #(14*4)] /* r14 */ orr r0, r0, #(I32_bit) msr cpsr_all, r0 /* switch to previous mode */ msr spsr_all, r1 mov r14, r2 msr cpsr_all, r7 /* back to undefined mode */ /* * Now r8-r13. */ add r8, sp, #(8*4) ldmia r8, {r1-r6} /* r8-r13 */ msr cpsr_all, r0 mov r8, r1 mov r9, r2 mov r10, r3 mov r11, r4 mov r12, r5 mov r13, r6 msr cpsr_all, r7 .Lpull_r0r7: /* * Now the rest of the registers. */ ldr r1,Lipkdb_trap_return ldr r0,[r1] tst r0,r0 ldmfd sp!, {r0-r7} /* r0-r7 */ add sp, sp, #(10*4) /* adjust sp */ /* * Did IPKDB handle it? */ movnes pc, lr /* return */ #endif stmfd sp!, {r0, r1} ldr r0, Lundefined_handler_indirection ldr r1, [sp], #0x0004 str r1, [r0, #0x0000] ldr r1, [sp], #0x0004 str r1, [r0, #0x0004] ldmia r0, {r0, r1, pc} #ifdef IPKDB Lipkdb_trap_return: .word Lipkdb_trap_return_data #endif Lundefined_handler_indirection: .word Lundefined_handler_indirection_data /* * assembly bounce code for calling the kernel * undefined instruction handler. This uses * a standard trap frame and is called in SVC mode. */ ENTRY_NP(undefinedinstruction_bounce) PUSHFRAMEINSVC ENABLE_ALIGNMENT_FAULTS mov r0, sp adr lr, exception_exit b _C_LABEL(undefinedinstruction) .data .align 0 #ifdef IPKDB Lipkdb_trap_return_data: .word 0 #endif /* * Indirection data * 2 words use for preserving r0 and r1 * 3rd word contains the undefined handler address. */ Lundefined_handler_indirection_data: .word 0 .word 0 .global _C_LABEL(undefined_handler_address) _C_LABEL(undefined_handler_address): .word _C_LABEL(undefinedinstruction_bounce) Index: head/sys/arm/arm/in_cksum_arm.S =================================================================== --- head/sys/arm/arm/in_cksum_arm.S (revision 130163) +++ head/sys/arm/arm/in_cksum_arm.S (revision 130164) @@ -1,474 +1,470 @@ /* $NetBSD: in_cksum_arm.S,v 1.2 2003/09/23 10:01:36 scw Exp $ */ /* * Copyright 2003 Wasabi Systems, Inc. * All rights reserved. * * Written by Steve C. Woodford for Wasabi Systems, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed for the NetBSD Project by * Wasabi Systems, Inc. * 4. The name of Wasabi Systems, Inc. may not be used to endorse * or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ /* * Hand-optimised in_cksum() and in4_cksum() implementations for ARM/Xscale */ #include "opt_inet.h" #include #include "assym.s" __FBSDID("$FreeBSD$"); /* * int in_cksum(struct mbuf *m, int len) * * Entry: * r0 m * r1 len * * NOTE: Assumes 'm' is *never* NULL. */ /* LINTSTUB: Func: int in_cksum(struct mbuf *, int) */ ENTRY(in_cksum) stmfd sp!, {r4-r11,lr} mov r8, #0x00 mov r9, r1 mov r10, #0x00 mov ip, r0 .Lin_cksum_loop: ldr r1, [ip, #(M_LEN)] ldr r0, [ip, #(M_DATA)] ldr ip, [ip, #(M_NEXT)] .Lin_cksum_entry4: cmp r9, r1 movlt r1, r9 sub r9, r9, r1 eor r11, r10, r0 add r10, r10, r1 adds r2, r1, #0x00 blne _ASM_LABEL(L_cksumdata) tst r11, #0x01 movne r2, r2, ror #8 adds r8, r8, r2 adc r8, r8, #0x00 cmp ip, #0x00 bne .Lin_cksum_loop mov r1, #0xff orr r1, r1, #0xff00 and r0, r8, r1 add r0, r0, r8, lsr #16 add r0, r0, r0, lsr #16 and r0, r0, r1 eor r0, r0, r1 ldmfd sp!, {r4-r11,pc} #ifdef INET /* * int in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len) * * Entry: * r0 m * r1 nxt * r2 off * r3 len */ /* LINTSTUB: Func: int in4_cksum(struct mbuf *, u_int8_t, int, int) */ ENTRY(in4_cksum) stmfd sp!, {r4-r11,lr} mov r8, #0x00 /* Accumulate sum in r8 */ /* * First, deal with a pseudo header, if present */ ldr r6, [r0, #(M_DATA)] cmp r1, #0x00 beq .Lin4_cksum_skip_entry #ifdef __XSCALE__ pld [r6, #(IP_SRC)] #endif add r4, r6, #(IP_SRC) ands r4, r4, #0x03 add r8, r1, r3 /* sum = nxt + len */ addne pc, pc, r4, lsl #5 /* Handle alignment of pseudo header */ nop /* 0x00: Data 32-bit aligned */ ldr r5, [r6, #(IP_SRC)] ldr r4, [r6, #(IP_DST)] b .Lin4_cksum_add_ips nop nop nop nop nop /* 0x01: Data 8-bit aligned */ ldr r4, [r6, #(IP_SRC - 1)] /* BE:r4 = x012 LE:r4 = 210x */ ldr r5, [r6, #(IP_SRC + 3)] /* BE:r5 = 3456 LE:r5 = 6543 */ ldrb r7, [r6, #(IP_SRC + 7)] /* r7 = ...7 */ #ifdef __ARMEB__ mov r4, r4, lsl #8 /* r4 = 012. */ orr r4, r4, r5, lsr #24 /* r4 = 0123 */ orr r5, r7, r5, lsl #8 /* r5 = 4567 */ b .Lin4_cksum_add_ips nop #else mov r4, r4, lsr #8 /* r4 = .210 */ orr r4, r4, r5, lsl #24 /* r4 = 3210 */ mov r5, r5, lsr #8 /* r5 = .654 */ orr r5, r5, r7, lsl #24 /* r5 = 7654 */ b .Lin4_cksum_add_ips #endif /* 0x02: Data 16-bit aligned */ #ifdef __XSCALE__ ldrh r5, [r6, #(IP_SRC)] /* BE:r5 = ..01 LE:r5 = ..10 */ ldrh r7, [r6, #(IP_DST + 2)] /* BE:r7 = ..67 LE:r7 = ..76 */ ldr r4, [r6, #(IP_SRC + 2)] /* BE:r4 = 2345 LE:r4 = 5432 */ orr r5, r7, r5, lsl #16 /* BE:r5 = 0167 LE:r5 = 1076 */ b .Lin4_cksum_add_ips nop nop nop #else ldr r4, [r6, #(IP_SRC - 2)] /* r4 = 10xx */ ldr r7, [r6, #(IP_DST - 2)] /* r7 = xx76 */ ldr r5, [r6, #(IP_SRC + 2)] /* r5 = 5432 */ mov r4, r4, lsr #16 /* r4 = ..10 */ orr r4, r4, r7, lsl #16 /* r4 = 7610 */ b .Lin4_cksum_add_ips nop nop #endif /* 0x03: Data 8-bit aligned */ ldrb r4, [r6, #(IP_SRC)] /* r4 = ...0 */ ldr r5, [r6, #(IP_SRC + 1)] /* BE:r5 = 1234 LE:r5 = 4321 */ ldr r7, [r6, #(IP_SRC + 5)] /* BE:r7 = 567x LE:r7 = x765 */ #ifdef __ARMEB__ mov r4, r4, lsl #24 /* r4 = 0... */ orr r4, r4, r5, lsr #8 /* r4 = 0123 */ mov r5, r5, lsl #24 /* r5 = 4... */ orr r5, r5, r7, lsr #8 /* r5 = 4567 */ #else orr r4, r4, r5, lsl #8 /* r4 = 3210 */ mov r5, r5, lsr #24 /* r4 = ...4 */ orr r5, r5, r7, lsl #8 /* r5 = 7654 */ #endif /* FALLTHROUGH */ .Lin4_cksum_add_ips: adds r5, r5, r4 #ifndef __ARMEB__ adcs r8, r5, r8, lsl #8 #else adcs r8, r5, r8 #endif adc r8, r8, #0x00 mov r1, #0x00 b .Lin4_cksum_skip_entry .Lin4_cksum_skip_loop: ldr r1, [r0, #(M_LEN)] ldr r6, [r0, #(M_DATA)] ldr r0, [r0, #(M_NEXT)] .Lin4_cksum_skip_entry: subs r2, r2, r1 blt .Lin4_cksum_skip_done cmp r0, #0x00 bne .Lin4_cksum_skip_loop b .Lin4_cksum_whoops .Lin4_cksum_skip_done: mov ip, r0 add r0, r2, r6 add r0, r0, r1 rsb r1, r2, #0x00 mov r9, r3 mov r10, #0x00 b .Lin_cksum_entry4 .Lin4_cksum_whoops: adr r0, .Lin4_cksum_whoops_str - adr r1, .LFile - mov r2, #__LINE__ - bl _C_LABEL(__panic) -.LFile: - .asciz __FILE__ + bl _C_LABEL(panic) .Lin4_cksum_whoops_str: .asciz "in4_cksum: out of mbufs\n" .align 5 #endif /* INET */ /* * The main in*_cksum() workhorse... * * Entry parameters: * r0 Pointer to buffer * r1 Buffer length * lr Return address * * Returns: * r2 Accumulated 32-bit sum * * Clobbers: * r0-r7 */ /* LINTSTUB: Ignore */ ASENTRY_NP(L_cksumdata) #ifdef __XSCALE__ pld [r0] /* Pre-fetch the start of the buffer */ #endif mov r2, #0 /* We first have to word-align the buffer. */ ands r7, r0, #0x03 beq .Lcksumdata_wordaligned rsb r7, r7, #0x04 cmp r1, r7 /* Enough bytes left to make it? */ blt .Lcksumdata_endgame cmp r7, #0x02 ldrb r4, [r0], #0x01 /* Fetch 1st byte */ ldrgeb r5, [r0], #0x01 /* Fetch 2nd byte */ movlt r5, #0x00 ldrgtb r6, [r0], #0x01 /* Fetch 3rd byte */ movle r6, #0x00 /* Combine the three bytes depending on endianness and alignment */ #ifdef __ARMEB__ orreq r2, r5, r4, lsl #8 orreq r2, r2, r6, lsl #24 orrne r2, r4, r5, lsl #8 orrne r2, r2, r6, lsl #16 #else orreq r2, r4, r5, lsl #8 orreq r2, r2, r6, lsl #16 orrne r2, r5, r4, lsl #8 orrne r2, r2, r6, lsl #24 #endif subs r1, r1, r7 /* Update length */ moveq pc, lr /* All done? */ /* Buffer is now word aligned */ .Lcksumdata_wordaligned: #ifdef __XSCALE__ cmp r1, #0x04 /* Less than 4 bytes left? */ blt .Lcksumdata_endgame /* Yup */ /* Now quad-align, if necessary */ ands r7, r0, #0x04 ldrne r7, [r0], #0x04 subne r1, r1, #0x04 subs r1, r1, #0x40 blt .Lcksumdata_bigloop_end /* Note: C flag clear if branch taken */ /* * Buffer is now quad aligned. Sum 64 bytes at a time. * Note: First ldrd is hoisted above the loop, together with * setting r6 to zero to avoid stalling for results in the * loop. (r7 is live, from above). */ ldrd r4, [r0], #0x08 mov r6, #0x00 .Lcksumdata_bigloop: pld [r0, #0x18] adds r2, r2, r6 adcs r2, r2, r7 ldrd r6, [r0], #0x08 adcs r2, r2, r4 adcs r2, r2, r5 ldrd r4, [r0], #0x08 adcs r2, r2, r6 adcs r2, r2, r7 ldrd r6, [r0], #0x08 adcs r2, r2, r4 adcs r2, r2, r5 ldrd r4, [r0], #0x08 adcs r2, r2, r6 adcs r2, r2, r7 pld [r0, #0x18] ldrd r6, [r0], #0x08 adcs r2, r2, r4 adcs r2, r2, r5 ldrd r4, [r0], #0x08 adcs r2, r2, r6 adcs r2, r2, r7 ldrd r6, [r0], #0x08 adcs r2, r2, r4 adcs r2, r2, r5 adc r2, r2, #0x00 subs r1, r1, #0x40 ldrged r4, [r0], #0x08 bge .Lcksumdata_bigloop adds r2, r2, r6 /* r6/r7 still need summing */ .Lcksumdata_bigloop_end: adcs r2, r2, r7 adc r2, r2, #0x00 #else /* !__XSCALE__ */ subs r1, r1, #0x40 blt .Lcksumdata_bigloop_end .Lcksumdata_bigloop: ldmia r0!, {r3, r4, r5, r6} adds r2, r2, r3 adcs r2, r2, r4 adcs r2, r2, r5 ldmia r0!, {r3, r4, r5, r7} adcs r2, r2, r6 adcs r2, r2, r3 adcs r2, r2, r4 adcs r2, r2, r5 ldmia r0!, {r3, r4, r5, r6} adcs r2, r2, r7 adcs r2, r2, r3 adcs r2, r2, r4 adcs r2, r2, r5 ldmia r0!, {r3, r4, r5, r7} adcs r2, r2, r6 adcs r2, r2, r3 adcs r2, r2, r4 adcs r2, r2, r5 adcs r2, r2, r7 adc r2, r2, #0x00 subs r1, r1, #0x40 bge .Lcksumdata_bigloop .Lcksumdata_bigloop_end: #endif adds r1, r1, #0x40 moveq pc, lr cmp r1, #0x20 #ifdef __XSCALE__ ldrged r4, [r0], #0x08 /* Avoid stalling pld and result */ blt .Lcksumdata_less_than_32 pld [r0, #0x18] ldrd r6, [r0], #0x08 adds r2, r2, r4 adcs r2, r2, r5 ldrd r4, [r0], #0x08 adcs r2, r2, r6 adcs r2, r2, r7 ldrd r6, [r0], #0x08 adcs r2, r2, r4 adcs r2, r2, r5 adcs r2, r2, r6 /* XXX: Unavoidable result stall */ adcs r2, r2, r7 #else blt .Lcksumdata_less_than_32 ldmia r0!, {r3, r4, r5, r6} adds r2, r2, r3 adcs r2, r2, r4 adcs r2, r2, r5 ldmia r0!, {r3, r4, r5, r7} adcs r2, r2, r6 adcs r2, r2, r3 adcs r2, r2, r4 adcs r2, r2, r5 adcs r2, r2, r7 #endif adc r2, r2, #0x00 subs r1, r1, #0x20 moveq pc, lr .Lcksumdata_less_than_32: /* There are less than 32 bytes left */ and r3, r1, #0x18 rsb r4, r3, #0x18 sub r1, r1, r3 adds r4, r4, r4, lsr #1 /* Side effect: Clear carry flag */ addne pc, pc, r4 nop /* * Note: We use ldm here, even on Xscale, since the combined issue/result * latencies for ldm and ldrd are the same. Using ldm avoids needless #ifdefs. */ /* At least 24 bytes remaining... */ ldmia r0!, {r4, r5} adcs r2, r2, r4 adcs r2, r2, r5 /* At least 16 bytes remaining... */ ldmia r0!, {r4, r5} adcs r2, r2, r4 adcs r2, r2, r5 /* At least 8 bytes remaining... */ ldmia r0!, {r4, r5} adcs r2, r2, r4 adcs r2, r2, r5 /* Less than 8 bytes remaining... */ adc r2, r2, #0x00 subs r1, r1, #0x04 blt .Lcksumdata_lessthan4 ldr r4, [r0], #0x04 sub r1, r1, #0x04 adds r2, r2, r4 adc r2, r2, #0x00 /* Deal with < 4 bytes remaining */ .Lcksumdata_lessthan4: adds r1, r1, #0x04 moveq pc, lr /* Deal with 1 to 3 remaining bytes, possibly misaligned */ .Lcksumdata_endgame: ldrb r3, [r0] /* Fetch first byte */ cmp r1, #0x02 ldrgeb r4, [r0, #0x01] /* Fetch 2nd and 3rd as necessary */ movlt r4, #0x00 ldrgtb r5, [r0, #0x02] movle r5, #0x00 /* Combine the three bytes depending on endianness and alignment */ tst r0, #0x01 #ifdef __ARMEB__ orreq r3, r4, r3, lsl #8 orreq r3, r3, r5, lsl #24 orrne r3, r3, r4, lsl #8 orrne r3, r3, r5, lsl #16 #else orreq r3, r3, r4, lsl #8 orreq r3, r3, r5, lsl #16 orrne r3, r4, r3, lsl #8 orrne r3, r3, r5, lsl #24 #endif adds r2, r2, r3 adc r2, r2, #0x00 mov pc, lr Index: head/sys/arm/arm/locore.S =================================================================== --- head/sys/arm/arm/locore.S (revision 130163) +++ head/sys/arm/arm/locore.S (revision 130164) @@ -1,312 +1,308 @@ /* $NetBSD: locore.S,v 1.14 2003/04/20 16:21:40 thorpej Exp $ */ /* * Copyright (C) 1994-1997 Mark Brinicombe * Copyright (C) 1994 Brini * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Brini. * 4. The name of Brini may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "assym.s" #include #include #include __FBSDID("$FreeBSD$"); /* What size should this really be ? It is only used by init_arm() */ #define INIT_ARM_STACK_SIZE 2048 /* * This is for kvm_mkdb, and should be the address of the beginning * of the kernel text segment (not necessarily the same as kernbase). */ #define CPWAIT_BRANCH \ sub pc, pc, #4 #define CPWAIT(tmp) \ mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ mov tmp, tmp /* wait for it to complete */ ;\ CPWAIT_BRANCH /* branch to next insn */ .text .align 0 .globl kernbase .set kernbase,KERNBASE ENTRY_NP(btext) ASENTRY_NP(_start) /* Check if we are running on RAM, if not move ourself to RAM */ cmp pc, #KERNPHYSADDR bhi start_inram /* XXX: This is wrong */ /* move me to RAM * XXX: we can use memcpy if it is PIC */ ldr r1, Lcopy_size adr r0, _C_LABEL(_start) add r1, r1, #3 mov r1, r1, LSR #2 mov r2, #KERNPHYSADDR add r2, r2, #0x00200000 mov r4, r2 5: ldr r3,[r0],#4 str r3,[r2],#4 subs r1,r1,#1 bhi 5b /* Jump to RAM */ ldr r0, Lstart_off add pc, r4, r0 Lcopy_size: .word _edata-_C_LABEL(_start) Lstart_off: .word start_inram-_C_LABEL(_start) start_inram: #ifdef STARTUP_PAGETABLE_ADDR adr r4, mmu_init_table2 mrc p15, 0, r2, c1, c0, 0 tst r2, #CPU_CONTROL_MMU_ENABLE /* we already have a page table? */ bne 3f /* build page table from scratch */ ldr r0, Lstartup_pagetable adr r4, mmu_init_table b 3f 2: str r3, [r0, r2] add r2, r2, #4 add r3, r3, #(L1_S_SIZE) adds r1, r1, #-1 bhi 2b 3: ldmia r4!, {r1,r2,r3} /* # of sections, PA|attr, VA */ cmp r1, #0 bne 2b mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ /* Set the Domain Access register. Very important! */ mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) mcr p15, 0, r0, c3, c0, 0 /* Enable MMU */ mrc p15, 0, r0, c1, c0, 0 orr r0, r0, #CPU_CONTROL_MMU_ENABLE mcr p15, 0, r0, c1, c0, 0 CPWAIT(r0) bl mmu_done mmu_done: #endif adr r1, .Lstart ldmia r1, {r1, r2, sp} /* Set initial stack and */ sub r2, r2, r1 /* get zero init data */ mov r3, #0 .L1: str r3, [r1], #0x0004 /* Zero the bss */ subs r2, r2, #4 bgt .L1 mov fp, #0xc0000000 /* trace back starts here */ bl _C_LABEL(initarm) /* Off we go */ /* init arm will return the new stack pointer. */ mov sp, r0 mov fp, #0x00000000 /* trace back starts here */ mov ip, sp stmfd sp!, {fp, ip, lr, pc} sub fp, ip, #4 bl _C_LABEL(mi_startup) /* call mi_startup()! */ adr r0, .Lmainreturned - adr r1, .LFile - mov r2, #__LINE__ - b _C_LABEL(__panic) + b _C_LABEL(panic) /* NOTEACHED */ #ifdef STARTUP_PAGETABLE_ADDR #define MMU_INIT(va,pa,n_sec,attr) \ .word n_sec ; \ .word 4*((va)>>L1_S_SHIFT) ; \ .word (pa)|(attr) ; Lstartup_pagetable: .word STARTUP_PAGETABLE_ADDR mmu_init_table: /* fill all table VA==PA */ MMU_INIT(0x00000000, 0x00000000, 1<<(32-L1_S_SHIFT), L1_TYPE_S|L1_S_AP(AP_KRW)) /* map SDRAM VA==PA, WT cacheable */ MMU_INIT(KERNPHYSADDR, KERNPHYSADDR, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) mmu_init_table2: /* map VA 0xc0000000..0xc3ffffff to PA 0xa0000000..0xa3ffffff */ MMU_INIT(0xc0000000, KERNPHYSADDR, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) .word 0 /* end of table */ #endif .Lstart: .word _edata .word _end .word svcstk + INIT_ARM_STACK_SIZE -.LFile: - .asciz __FILE__ .Lmainreturned: .asciz "main() returned" .align 0 .bss svcstk: .space INIT_ARM_STACK_SIZE .text .align 0 #ifndef OFW /* OFW based systems will used OF_boot() */ .Lcpufuncs: .word _C_LABEL(cpufuncs) ENTRY_NP(cpu_reset) mrs r2, cpsr bic r2, r2, #(PSR_MODE) orr r2, r2, #(PSR_SVC32_MODE) orr r2, r2, #(I32_bit | F32_bit) msr cpsr_all, r2 ldr r4, .Lcpu_reset_address ldr r4, [r4] ldr r0, .Lcpufuncs mov lr, pc ldr pc, [r0, #CF_IDCACHE_WBINV_ALL] /* * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's * necessary. */ ldr r1, .Lcpu_reset_needs_v4_MMU_disable ldr r1, [r1] cmp r1, #0 mov r2, #0 /* * MMU & IDC off, 32 bit program & data space * Hurl ourselves into the ROM */ mov r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE) mcr 15, 0, r0, c1, c0, 0 mcrne 15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */ mov pc, r4 /* * _cpu_reset_address contains the address to branch to, to complete * the cpu reset after turning the MMU off * This variable is provided by the hardware specific code */ .Lcpu_reset_address: .word _C_LABEL(cpu_reset_address) /* * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the * v4 MMU disable instruction needs executing... it is an illegal instruction * on f.e. ARM6/7 that locks up the computer in an endless illegal * instruction / data-abort / reset loop. */ .Lcpu_reset_needs_v4_MMU_disable: .word _C_LABEL(cpu_reset_needs_v4_MMU_disable) #endif /* OFW */ #ifdef IPKDB /* * Execute(inst, psr, args, sp) * * Execute INSTruction with PSR and ARGS[0] - ARGS[3] making * available stack at SP for next undefined instruction trap. * * Move the instruction onto the stack and jump to it. */ ENTRY_NP(Execute) mov ip, sp stmfd sp!, {r2, r4-r7, fp, ip, lr, pc} sub fp, ip, #4 mov ip, r3 ldr r7, .Lreturn stmfd sp!, {r0, r7} adr r7, #.LExec mov r5, r1 mrs r4, cpsr ldmia r2, {r0-r3} mov r6, sp mov sp, ip msr cpsr_all, r5 mov pc, r6 .LExec: mrs r5, cpsr /* XXX Cannot switch thus easily back from user mode */ msr cpsr_all, r4 add sp, r6, #8 ldmfd sp!, {r6} stmia r6, {r0-r3} mov r0, r5 ldmdb fp, {r4-r7, fp, sp, pc} .Lreturn: mov pc, r7 #endif /* * setjump + longjmp */ ENTRY(setjmp) stmia r0, {r4-r14} mov r0, #0x00000000 mov pc, lr ENTRY(longjmp) ldmia r0, {r4-r14} mov r0, #0x00000001 mov pc, lr .data .global _C_LABEL(esym) _C_LABEL(esym): .word _C_LABEL(end) ENTRY_NP(abort) b _C_LABEL(abort) /* End of locore.S */ Index: head/sys/i386/i386/swtch.s =================================================================== --- head/sys/i386/i386/swtch.s (revision 130163) +++ head/sys/i386/i386/swtch.s (revision 130164) @@ -1,388 +1,382 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include "opt_npx.h" #include #include "assym.s" /*****************************************************************************/ /* Scheduling */ /*****************************************************************************/ .text /* * cpu_throw() * * This is the second half of cpu_swtch(). It is used when the current * thread is either a dummy or slated to die, and we no longer care * about its state. This is only a slight optimization and is probably * not worth it anymore. Note that we need to clear the pm_active bits so * we do need the old proc if it still exists. * 0(%esp) = ret * 4(%esp) = oldtd * 8(%esp) = newtd */ ENTRY(cpu_throw) movl PCPU(CPUID), %esi movl 4(%esp),%ecx /* Old thread */ testl %ecx,%ecx /* no thread? */ jz 1f /* release bit from old pm_active */ movl PCPU(CURPMAP), %ebx #ifdef SMP lock #endif btrl %esi, PM_ACTIVE(%ebx) /* clear old */ 1: movl 8(%esp),%ecx /* New thread */ movl TD_PCB(%ecx),%edx movl PCB_CR3(%edx),%eax movl %eax,%cr3 /* new address space */ /* set bit in new pm_active */ movl TD_PROC(%ecx),%eax movl P_VMSPACE(%eax), %ebx addl $VM_PMAP, %ebx movl %ebx, PCPU(CURPMAP) #ifdef SMP lock #endif btsl %esi, PM_ACTIVE(%ebx) /* set new */ jmp sw1 /* * cpu_switch(old, new) * * Save the current thread state, then select the next thread to run * and load its state. * 0(%esp) = ret * 4(%esp) = oldtd * 8(%esp) = newtd */ ENTRY(cpu_switch) /* Switch to new thread. First, save context. */ movl 4(%esp),%ecx #ifdef INVARIANTS testl %ecx,%ecx /* no thread? */ jz badsw2 /* no, panic */ #endif movl TD_PCB(%ecx),%edx movl (%esp),%eax /* Hardware registers */ movl %eax,PCB_EIP(%edx) movl %ebx,PCB_EBX(%edx) movl %esp,PCB_ESP(%edx) movl %ebp,PCB_EBP(%edx) movl %esi,PCB_ESI(%edx) movl %edi,PCB_EDI(%edx) movl %gs,PCB_GS(%edx) pushfl /* PSL */ popl PCB_PSL(%edx) /* Check to see if we need to call a switchout function. */ movl PCB_SWITCHOUT(%edx),%eax cmpl $0, %eax je 1f call *%eax 1: /* Test if debug registers should be saved. */ testl $PCB_DBREGS,PCB_FLAGS(%edx) jz 1f /* no, skip over */ movl %dr7,%eax /* yes, do the save */ movl %eax,PCB_DR7(%edx) andl $0x0000fc00, %eax /* disable all watchpoints */ movl %eax,%dr7 movl %dr6,%eax movl %eax,PCB_DR6(%edx) movl %dr3,%eax movl %eax,PCB_DR3(%edx) movl %dr2,%eax movl %eax,PCB_DR2(%edx) movl %dr1,%eax movl %eax,PCB_DR1(%edx) movl %dr0,%eax movl %eax,PCB_DR0(%edx) 1: #ifdef DEV_NPX /* have we used fp, and need a save? */ cmpl %ecx,PCPU(FPCURTHREAD) jne 1f addl $PCB_SAVEFPU,%edx /* h/w bugs make saving complicated */ pushl %edx call npxsave /* do it in a big C function */ popl %eax 1: #endif /* Save is done. Now fire up new thread. Leave old vmspace. */ movl %ecx,%edi movl 8(%esp),%ecx /* New thread */ #ifdef INVARIANTS testl %ecx,%ecx /* no thread? */ jz badsw3 /* no, panic */ #endif movl TD_PCB(%ecx),%edx movl PCPU(CPUID), %esi /* switch address space */ movl PCB_CR3(%edx),%eax #ifdef PAE cmpl %eax,IdlePDPT /* Kernel address space? */ #else cmpl %eax,IdlePTD /* Kernel address space? */ #endif je sw1 movl %cr3,%ebx /* The same address space? */ cmpl %ebx,%eax je sw1 movl %eax,%cr3 /* new address space */ /* Release bit from old pmap->pm_active */ movl PCPU(CURPMAP), %ebx #ifdef SMP lock #endif btrl %esi, PM_ACTIVE(%ebx) /* clear old */ /* Set bit in new pmap->pm_active */ movl TD_PROC(%ecx),%eax /* newproc */ movl P_VMSPACE(%eax), %ebx addl $VM_PMAP, %ebx movl %ebx, PCPU(CURPMAP) #ifdef SMP lock #endif btsl %esi, PM_ACTIVE(%ebx) /* set new */ sw1: /* * At this point, we've switched address spaces and are ready * to load up the rest of the next context. */ cmpl $0, PCB_EXT(%edx) /* has pcb extension? */ je 1f /* If not, use the default */ btsl %esi, private_tss /* mark use of private tss */ movl PCB_EXT(%edx), %edi /* new tss descriptor */ jmp 2f /* Load it up */ 1: /* * Use the common default TSS instead of our own. * Set our stack pointer into the TSS, it's set to just * below the PCB. In C, common_tss.tss_esp0 = &pcb - 16; */ leal -16(%edx), %ebx /* leave space for vm86 */ movl %ebx, PCPU(COMMON_TSS) + TSS_ESP0 /* * Test this CPU's bit in the bitmap to see if this * CPU was using a private TSS. */ btrl %esi, private_tss /* Already using the common? */ jae 3f /* if so, skip reloading */ PCPU_ADDR(COMMON_TSSD, %edi) 2: /* Move correct tss descriptor into GDT slot, then reload tr. */ movl PCPU(TSS_GDT), %ebx /* entry in GDT */ movl 0(%edi), %eax movl %eax, 0(%ebx) movl 4(%edi), %eax movl %eax, 4(%ebx) movl $GPROC0_SEL*8, %esi /* GSEL(entry, SEL_KPL) */ ltr %si 3: /* Restore context. */ movl PCB_EBX(%edx),%ebx movl PCB_ESP(%edx),%esp movl PCB_EBP(%edx),%ebp movl PCB_ESI(%edx),%esi movl PCB_EDI(%edx),%edi movl PCB_EIP(%edx),%eax movl %eax,(%esp) pushl PCB_PSL(%edx) popfl movl %edx, PCPU(CURPCB) movl %ecx, PCPU(CURTHREAD) /* into next thread */ /* * Determine the LDT to use and load it if is the default one and * that is not the current one. */ movl TD_PROC(%ecx),%eax cmpl $0,P_MD+MD_LDT(%eax) jnz 1f movl _default_ldt,%eax cmpl PCPU(CURRENTLDT),%eax je 2f lldt _default_ldt movl %eax,PCPU(CURRENTLDT) jmp 2f 1: /* Load the LDT when it is not the default one. */ pushl %edx /* Preserve pointer to pcb. */ addl $P_MD,%eax /* Pointer to mdproc is arg. */ pushl %eax call set_user_ldt addl $4,%esp popl %edx 2: /* This must be done after loading the user LDT. */ .globl cpu_switch_load_gs cpu_switch_load_gs: movl PCB_GS(%edx),%gs /* Test if debug registers should be restored. */ testl $PCB_DBREGS,PCB_FLAGS(%edx) jz 1f /* * Restore debug registers. The special code for dr7 is to * preserve the current values of its reserved bits. */ movl PCB_DR6(%edx),%eax movl %eax,%dr6 movl PCB_DR3(%edx),%eax movl %eax,%dr3 movl PCB_DR2(%edx),%eax movl %eax,%dr2 movl PCB_DR1(%edx),%eax movl %eax,%dr1 movl PCB_DR0(%edx),%eax movl %eax,%dr0 movl %dr7,%eax andl $0x0000fc00,%eax movl PCB_DR7(%edx),%ecx andl $~0x0000fc00,%ecx orl %ecx,%eax movl %eax,%dr7 1: ret #ifdef INVARIANTS badsw1: pushal - pushl $0 - pushl $0 pushl $sw0_1 - call __panic + call panic sw0_1: .asciz "cpu_throw: no newthread supplied" badsw2: pushal - pushl $0 - pushl $0 pushl $sw0_2 - call __panic + call panic sw0_2: .asciz "cpu_switch: no curthread supplied" badsw3: pushal - pushl $0 - pushl $0 pushl $sw0_3 - call __panic + call panic sw0_3: .asciz "cpu_switch: no newthread supplied" #endif /* * savectx(pcb) * Update pcb, saving current processor state. */ ENTRY(savectx) /* Fetch PCB. */ movl 4(%esp),%ecx /* Save caller's return address. Child won't execute this routine. */ movl (%esp),%eax movl %eax,PCB_EIP(%ecx) movl %cr3,%eax movl %eax,PCB_CR3(%ecx) movl %ebx,PCB_EBX(%ecx) movl %esp,PCB_ESP(%ecx) movl %ebp,PCB_EBP(%ecx) movl %esi,PCB_ESI(%ecx) movl %edi,PCB_EDI(%ecx) movl %gs,PCB_GS(%ecx) pushfl popl PCB_PSL(%ecx) #ifdef DEV_NPX /* * If fpcurthread == NULL, then the npx h/w state is irrelevant and the * state had better already be in the pcb. This is true for forks * but not for dumps (the old book-keeping with FP flags in the pcb * always lost for dumps because the dump pcb has 0 flags). * * If fpcurthread != NULL, then we have to save the npx h/w state to * fpcurthread's pcb and copy it to the requested pcb, or save to the * requested pcb and reload. Copying is easier because we would * have to handle h/w bugs for reloading. We used to lose the * parent's npx state for forks by forgetting to reload. */ pushfl cli movl PCPU(FPCURTHREAD),%eax testl %eax,%eax je 1f pushl %ecx movl TD_PCB(%eax),%eax leal PCB_SAVEFPU(%eax),%eax pushl %eax pushl %eax call npxsave addl $4,%esp popl %eax popl %ecx pushl $PCB_SAVEFPU_SIZE leal PCB_SAVEFPU(%ecx),%ecx pushl %ecx pushl %eax call bcopy addl $12,%esp 1: popfl #endif /* DEV_NPX */ ret Index: head/sys/kern/kern_shutdown.c =================================================================== --- head/sys/kern/kern_shutdown.c (revision 130163) +++ head/sys/kern/kern_shutdown.c (revision 130164) @@ -1,624 +1,624 @@ /*- * Copyright (c) 1986, 1988, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_shutdown.c 8.3 (Berkeley) 1/21/94 */ #include __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include "opt_ddb_trace.h" #include "opt_ddb_unattended.h" #include "opt_hw_wdog.h" #include "opt_mac.h" #include "opt_panic.h" #include "opt_show_busybufs.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* smp_active */ #include #include #include #include #include #include #include #ifdef DDB #include #endif #ifndef PANIC_REBOOT_WAIT_TIME #define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */ #endif /* * Note that stdarg.h and the ANSI style va_start macro is used for both * ANSI and traditional C compilers. */ #include #ifdef DDB #ifdef DDB_UNATTENDED int debugger_on_panic = 0; #else int debugger_on_panic = 1; #endif SYSCTL_INT(_debug, OID_AUTO, debugger_on_panic, CTLFLAG_RW, &debugger_on_panic, 0, "Run debugger on kernel panic"); #ifdef DDB_TRACE int trace_on_panic = 1; #else int trace_on_panic = 0; #endif SYSCTL_INT(_debug, OID_AUTO, trace_on_panic, CTLFLAG_RW, &trace_on_panic, 0, "Print stack trace on kernel panic"); #endif int sync_on_panic = 1; SYSCTL_INT(_kern, OID_AUTO, sync_on_panic, CTLFLAG_RW, &sync_on_panic, 0, "Do a sync before rebooting from a panic"); SYSCTL_NODE(_kern, OID_AUTO, shutdown, CTLFLAG_RW, 0, "Shutdown environment"); #ifdef HW_WDOG /* * If there is a hardware watchdog, point this at the function needed to * hold it off. * It's needed when the kernel needs to do some lengthy operations. * e.g. in wd.c when dumping core.. It's most annoying to have * your precious core-dump only half written because the wdog kicked in. */ watchdog_tickle_fn wdog_tickler = NULL; #endif /* HW_WDOG */ /* * Variable panicstr contains argument to first call to panic; used as flag * to indicate that the kernel has already called panic. */ const char *panicstr; int dumping; /* system is dumping */ static struct dumperinfo dumper; /* our selected dumper */ static struct pcb dumppcb; /* "You Are Here" sign for dump-debuggers */ static void boot(int) __dead2; static void poweroff_wait(void *, int); static void shutdown_halt(void *junk, int howto); static void shutdown_panic(void *junk, int howto); static void shutdown_reset(void *junk, int howto); /* register various local shutdown events */ static void shutdown_conf(void *unused) { EVENTHANDLER_REGISTER(shutdown_final, poweroff_wait, NULL, SHUTDOWN_PRI_FIRST); EVENTHANDLER_REGISTER(shutdown_final, shutdown_halt, NULL, SHUTDOWN_PRI_LAST + 100); EVENTHANDLER_REGISTER(shutdown_final, shutdown_panic, NULL, SHUTDOWN_PRI_LAST + 100); EVENTHANDLER_REGISTER(shutdown_final, shutdown_reset, NULL, SHUTDOWN_PRI_LAST + 200); } SYSINIT(shutdown_conf, SI_SUB_INTRINSIC, SI_ORDER_ANY, shutdown_conf, NULL) /* * The system call that results in a reboot * * MPSAFE */ /* ARGSUSED */ int reboot(struct thread *td, struct reboot_args *uap) { int error; error = 0; #ifdef MAC error = mac_check_system_reboot(td->td_ucred, uap->opt); #endif if (error == 0) error = suser(td); if (error == 0) { mtx_lock(&Giant); boot(uap->opt); mtx_unlock(&Giant); } return (error); } /* * Called by events that want to shut down.. e.g on a PC */ static int shutdown_howto = 0; void shutdown_nice(int howto) { shutdown_howto = howto; /* Send a signal to init(8) and have it shutdown the world */ if (initproc != NULL) { PROC_LOCK(initproc); psignal(initproc, SIGINT); PROC_UNLOCK(initproc); } else { /* No init(8) running, so simply reboot */ boot(RB_NOSYNC); } return; } static int waittime = -1; static void print_uptime(void) { int f; struct timespec ts; getnanouptime(&ts); printf("Uptime: "); f = 0; if (ts.tv_sec >= 86400) { printf("%ldd", (long)ts.tv_sec / 86400); ts.tv_sec %= 86400; f = 1; } if (f || ts.tv_sec >= 3600) { printf("%ldh", (long)ts.tv_sec / 3600); ts.tv_sec %= 3600; f = 1; } if (f || ts.tv_sec >= 60) { printf("%ldm", (long)ts.tv_sec / 60); ts.tv_sec %= 60; f = 1; } printf("%lds\n", (long)ts.tv_sec); } static void doadump(void) { savectx(&dumppcb); dumping++; dumpsys(&dumper); } /* * Go through the rigmarole of shutting down.. * this used to be in machdep.c but I'll be dammned if I could see * anything machine dependant in it. */ static void boot(int howto) { /* collect extra flags that shutdown_nice might have set */ howto |= shutdown_howto; #ifdef DDB /* We are out of the debugger now. */ db_active = 0; #endif #ifdef SMP if (smp_active) printf("boot() called on cpu#%d\n", PCPU_GET(cpuid)); #endif /* * Do any callouts that should be done BEFORE syncing the filesystems. */ EVENTHANDLER_INVOKE(shutdown_pre_sync, howto); /* * Now sync filesystems */ if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) { register struct buf *bp; int iter, nbusy, pbusy; int subiter; waittime = 0; printf("\nsyncing disks, buffers remaining... "); sync(&thread0, NULL); /* * With soft updates, some buffers that are * written will be remarked as dirty until other * buffers are written. */ for (iter = pbusy = 0; iter < 20; iter++) { nbusy = 0; for (bp = &buf[nbuf]; --bp >= buf; ) { if ((bp->b_flags & B_INVAL) == 0 && BUF_REFCNT(bp) > 0) { nbusy++; } else if ((bp->b_flags & (B_DELWRI | B_INVAL)) == B_DELWRI) { /* bawrite(bp);*/ nbusy++; } } if (nbusy == 0) break; printf("%d ", nbusy); if (nbusy < pbusy) iter = 0; pbusy = nbusy; sync(&thread0, NULL); if (curthread != NULL) { DROP_GIANT(); for (subiter = 0; subiter < 50 * iter; subiter++) { mtx_lock_spin(&sched_lock); /* * Allow interrupt threads to run */ mi_switch(SW_VOL); mtx_unlock_spin(&sched_lock); DELAY(1000); } PICKUP_GIANT(); } else DELAY(50000 * iter); } printf("\n"); /* * Count only busy local buffers to prevent forcing * a fsck if we're just a client of a wedged NFS server */ nbusy = 0; for (bp = &buf[nbuf]; --bp >= buf; ) { if (((bp->b_flags&B_INVAL) == 0 && BUF_REFCNT(bp)) || ((bp->b_flags & (B_DELWRI|B_INVAL)) == B_DELWRI)) { if (bp->b_dev == NODEV) { TAILQ_REMOVE(&mountlist, bp->b_vp->v_mount, mnt_list); continue; } nbusy++; #if defined(SHOW_BUSYBUFS) || defined(DIAGNOSTIC) printf( "%d: dev:%s, flags:%0x, blkno:%ld, lblkno:%ld\n", nbusy, devtoname(bp->b_dev), bp->b_flags, (long)bp->b_blkno, (long)bp->b_lblkno); #endif } } if (nbusy) { /* * Failed to sync all blocks. Indicate this and don't * unmount filesystems (thus forcing an fsck on reboot). */ printf("giving up on %d buffers\n", nbusy); DELAY(5000000); /* 5 seconds */ } else { printf("done\n"); /* * Unmount filesystems */ if (panicstr == 0) vfs_unmountall(); } DELAY(100000); /* wait for console output to finish */ } print_uptime(); /* * Ok, now do things that assume all filesystem activity has * been completed. */ EVENTHANDLER_INVOKE(shutdown_post_sync, howto); splhigh(); if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP && !cold && dumper.dumper != NULL && !dumping) doadump(); /* Now that we're going to really halt the system... */ EVENTHANDLER_INVOKE(shutdown_final, howto); for(;;) ; /* safety against shutdown_reset not working */ /* NOTREACHED */ } /* * If the shutdown was a clean halt, behave accordingly. */ static void shutdown_halt(void *junk, int howto) { if (howto & RB_HALT) { printf("\n"); printf("The operating system has halted.\n"); printf("Please press any key to reboot.\n\n"); switch (cngetc()) { case -1: /* No console, just die */ cpu_halt(); /* NOTREACHED */ default: howto &= ~RB_HALT; break; } } } /* * Check to see if the system paniced, pause and then reboot * according to the specified delay. */ static void shutdown_panic(void *junk, int howto) { int loop; if (howto & RB_DUMP) { if (PANIC_REBOOT_WAIT_TIME != 0) { if (PANIC_REBOOT_WAIT_TIME != -1) { printf("Automatic reboot in %d seconds - " "press a key on the console to abort\n", PANIC_REBOOT_WAIT_TIME); for (loop = PANIC_REBOOT_WAIT_TIME * 10; loop > 0; --loop) { DELAY(1000 * 100); /* 1/10th second */ /* Did user type a key? */ if (cncheckc() != -1) break; } if (!loop) return; } } else { /* zero time specified - reboot NOW */ return; } printf("--> Press a key on the console to reboot,\n"); printf("--> or switch off the system now.\n"); cngetc(); } } /* * Everything done, now reset */ static void shutdown_reset(void *junk, int howto) { printf("Rebooting...\n"); DELAY(1000000); /* wait 1 sec for printf's to complete and be read */ /* cpu_boot(howto); */ /* doesn't do anything at the moment */ cpu_reset(); /* NOTREACHED */ /* assuming reset worked */ } /* * Print a backtrace if we can. */ void backtrace(void) { #ifdef DDB printf("Stack backtrace:\n"); db_print_backtrace(); #else printf("Sorry, need DDB option to print backtrace"); #endif } #ifdef SMP static u_int panic_cpu = NOCPU; #endif /* * Panic is called on unresolvable fatal errors. It prints "panic: mesg", * and then reboots. If we are called twice, then we avoid trying to sync * the disks as this often leads to recursive panics. * * MPSAFE */ void -__panic(const char *file, int line, const char *fmt, ...) +panic(const char *fmt, ...) { struct thread *td = curthread; int bootopt, newpanic; va_list ap; static char buf[256]; #ifdef SMP /* * We don't want multiple CPU's to panic at the same time, so we * use panic_cpu as a simple spinlock. We have to keep checking * panic_cpu if we are spinning in case the panic on the first * CPU is canceled. */ if (panic_cpu != PCPU_GET(cpuid)) while (atomic_cmpset_int(&panic_cpu, NOCPU, PCPU_GET(cpuid)) == 0) while (panic_cpu != NOCPU) ; /* nothing */ #endif bootopt = RB_AUTOBOOT | RB_DUMP; newpanic = 0; if (panicstr) bootopt |= RB_NOSYNC; else { panicstr = fmt; newpanic = 1; } va_start(ap, fmt); if (newpanic) { (void)vsnprintf(buf, sizeof(buf), fmt, ap); panicstr = buf; - printf("panic: %s\nat line %d in file %s\n", buf, line, file); + printf("panic: %s\n", buf); } else { printf("panic: "); vprintf(fmt, ap); - printf("\nat line %d in file %s", line, file); + printf("\n"); } va_end(ap); #ifdef SMP /* two separate prints in case of an unmapped page and trap */ printf("cpuid = %d; ", PCPU_GET(cpuid)); #ifdef APIC_IO printf("lapic.id = %08x\n", lapic.id); #else printf("\n"); #endif #endif #if defined(DDB) if (newpanic && trace_on_panic) backtrace(); if (debugger_on_panic) Debugger ("panic"); #ifdef RESTARTABLE_PANICS /* See if the user aborted the panic, in which case we continue. */ if (panicstr == NULL) { #ifdef SMP atomic_store_rel_int(&panic_cpu, NOCPU); #endif return; } #endif #endif mtx_lock_spin(&sched_lock); td->td_flags |= TDF_INPANIC; mtx_unlock_spin(&sched_lock); if (!sync_on_panic) bootopt |= RB_NOSYNC; boot(bootopt); } /* * Support for poweroff delay. */ #ifndef POWEROFF_DELAY # define POWEROFF_DELAY 5000 #endif static int poweroff_delay = POWEROFF_DELAY; SYSCTL_INT(_kern_shutdown, OID_AUTO, poweroff_delay, CTLFLAG_RW, &poweroff_delay, 0, ""); static void poweroff_wait(void *junk, int howto) { if (!(howto & RB_POWEROFF) || poweroff_delay <= 0) return; DELAY(poweroff_delay * 1000); } /* * Some system processes (e.g. syncer) need to be stopped at appropriate * points in their main loops prior to a system shutdown, so that they * won't interfere with the shutdown process (e.g. by holding a disk buf * to cause sync to fail). For each of these system processes, register * shutdown_kproc() as a handler for one of shutdown events. */ static int kproc_shutdown_wait = 60; SYSCTL_INT(_kern_shutdown, OID_AUTO, kproc_shutdown_wait, CTLFLAG_RW, &kproc_shutdown_wait, 0, ""); void kproc_shutdown(void *arg, int howto) { struct proc *p; int error; if (panicstr) return; p = (struct proc *)arg; printf("Waiting (max %d seconds) for system process `%s' to stop...", kproc_shutdown_wait, p->p_comm); error = kthread_suspend(p, kproc_shutdown_wait * hz); if (error == EWOULDBLOCK) printf("timed out\n"); else printf("stopped\n"); } /* Registration of dumpers */ int set_dumper(struct dumperinfo *di) { if (di == NULL) { bzero(&dumper, sizeof dumper); return (0); } if (dumper.dumper != NULL) return (EBUSY); dumper = *di; return (0); } #if defined(__powerpc__) void dumpsys(struct dumperinfo *di __unused) { printf("Kernel dumps not implemented on this architecture\n"); } #endif Index: head/sys/sparc64/include/asmacros.h =================================================================== --- head/sys/sparc64/include/asmacros.h (revision 130163) +++ head/sys/sparc64/include/asmacros.h (revision 130164) @@ -1,143 +1,141 @@ /*- * Copyright (c) 2001 Jake Burkholder. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_ASMACROS_H_ #define _MACHINE_ASMACROS_H_ #ifdef _KERNEL /* * Normal and alternate %g6 point to the pcb of the current process. Normal, & alternate and interrupt %g7 point to per-cpu data. */ #define PCB_REG %g6 #define PCPU_REG %g7 /* * Alternate %g5 points to a per-cpu panic stack, which is used as a last * resort, and for temporarily saving alternate globals. */ #define ASP_REG %g5 #ifdef LOCORE /* * Atomically decrement an integer in memory. */ #define ATOMIC_DEC_INT(r1, r2, r3) \ lduw [r1], r2 ; \ 9: sub r2, 1, r3 ; \ casa [r1] ASI_N, r2, r3 ; \ cmp r2, r3 ; \ bne,pn %icc, 9b ; \ mov r3, r2 /* * Atomically increment an integer in memory. */ #define ATOMIC_INC_INT(r1, r2, r3) \ lduw [r1], r2 ; \ 9: add r2, 1, r3 ; \ casa [r1] ASI_N, r2, r3 ; \ cmp r2, r3 ; \ bne,pn %icc, 9b ; \ mov r3, r2 /* * Atomically increment an u_long in memory. */ #define ATOMIC_INC_ULONG(r1, r2, r3) \ ldx [r1], r2 ; \ 9: add r2, 1, r3 ; \ casxa [r1] ASI_N, r2, r3 ; \ cmp r2, r3 ; \ bne,pn %icc, 9b ; \ mov r3, r2 /* * Atomically clear a number of bits of an integer in memory. */ #define ATOMIC_CLEAR_INT(r1, r2, r3, bits) \ lduw [r1], r2 ; \ 9: andn r2, bits, r3 ; \ casa [r1] ASI_N, r2, r3 ; \ cmp r2, r3 ; \ bne,pn %icc, 9b ; \ mov r3, r2 #define PCPU(member) PCPU_REG + PC_ ## member #define PCPU_ADDR(member, reg) \ add PCPU_REG, PC_ ## member, reg #define DEBUGGER() \ ta %xcc, 1 #define PANIC(msg, r1) \ .sect .rodata ; \ 9: .asciz msg ; \ .previous ; \ - SET(9b, r1, %o2) ; \ - clr %o1 ; \ - clr %o0 ; \ - call __panic ; \ + SET(9b, r1, %o0) ; \ + call panic ; \ nop #ifdef INVARIANTS #define KASSERT(r1, msg) \ brnz r1, 8f ; \ nop ; \ PANIC(msg, r1) ; \ 8: #else #define KASSERT(r1, msg) #endif #define PUTS(msg, r1) \ .sect .rodata ; \ 9: .asciz msg ; \ .previous ; \ SET(9b, r1, %o0) ; \ call printf ; \ nop #define _ALIGN_DATA .align 8 #define DATA(name) \ .data ; \ _ALIGN_DATA ; \ .globl name ; \ .type name, @object ; \ name: #define EMPTY #endif /* LOCORE */ #endif /* _KERNEL */ #endif /* !_MACHINE_ASMACROS_H_ */ Index: head/sys/sys/systm.h =================================================================== --- head/sys/sys/systm.h (revision 130163) +++ head/sys/sys/systm.h (revision 130164) @@ -1,330 +1,328 @@ /*- * Copyright (c) 1982, 1988, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)systm.h 8.7 (Berkeley) 3/29/95 * $FreeBSD$ */ #ifndef _SYS_SYSTM_H_ #define _SYS_SYSTM_H_ #include #include #include #include #include #include /* for people using printf mainly */ extern int securelevel; /* system security level (see init(8)) */ extern int suser_enabled; /* suser() is permitted to return 0 */ extern int cold; /* nonzero if we are doing a cold boot */ extern const char *panicstr; /* panic message */ extern char version[]; /* system version */ extern char copyright[]; /* system copyright */ extern int kstack_pages; /* number of kernel stack pages */ extern int uarea_pages; /* number of user struct pages */ extern int nswap; /* size of swap space */ extern u_int nselcoll; /* select collisions since boot */ extern struct mtx sellock; /* select lock variable */ extern struct cv selwait; /* select conditional variable */ extern long physmem; /* physical memory */ extern dev_t rootdev; /* root device */ extern dev_t rootdevs[2]; /* possible root devices */ extern char *rootdevnames[2]; /* names of possible root devices */ extern struct vnode *rootvp; /* vnode equivalent to above */ extern int boothowto; /* reboot flags, from console subsystem */ extern int bootverbose; /* nonzero to print verbose messages */ extern int maxusers; /* system tune hint */ #ifdef INVARIANTS /* The option is always available */ #define KASSERT(exp,msg) do { \ if (__predict_false(!(exp))) \ panic msg; \ } while (0) #else #define KASSERT(exp,msg) #endif #ifndef CTASSERT /* Allow lint to override */ #define CTASSERT(x) _CTASSERT(x, __LINE__) #define _CTASSERT(x, y) __CTASSERT(x, y) #define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1] #endif /* * XXX the hints declarations are even more misplaced than most declarations * in this file, since they are needed in one file (per arch) and only used * in two files. * XXX most of these variables should be const. */ extern int envmode; extern int hintmode; /* 0 = off. 1 = config, 2 = fallback */ extern int dynamic_kenv; extern struct sx kenv_lock; extern char *kern_envp; extern char static_env[]; extern char static_hints[]; /* by config for now */ extern char **kenvp; /* * General function declarations. */ struct clockframe; struct malloc_type; struct mtx; struct proc; struct kse; struct socket; struct thread; struct tty; struct ucred; struct uio; struct _jmp_buf; int setjmp(struct _jmp_buf *); void longjmp(struct _jmp_buf *, int) __dead2; void Debugger(const char *msg) __nonnull(1); int dumpstatus(vm_offset_t addr, off_t count); int nullop(void); int eopnotsupp(void); int ureadc(int, struct uio *); void hashdestroy(void *, struct malloc_type *, u_long); void *hashinit(int count, struct malloc_type *type, u_long *hashmask); void *phashinit(int count, struct malloc_type *type, u_long *nentries); #ifdef RESTARTABLE_PANICS -void __panic(const char *file, int line, const char *, ...) __printflike(3, 4); +void panic(const char *, ...) __printflike(1, 2); #else -void __panic(const char *file, int line, const char *, ...) __dead2 __printflike(3, 4); +void panic(const char *, ...) __dead2 __printflike(1, 2); #endif - -#define panic(...) __panic(__FILE__, __LINE__, __VA_ARGS__) void backtrace(void); void cpu_boot(int); void cpu_rootconf(void); extern uint32_t crc32_tab[]; uint32_t crc32(const void *buf, size_t size); void critical_enter(void); void critical_exit(void); void init_param1(void); void init_param2(long physpages); void init_param3(long kmempages); void tablefull(const char *); int kvprintf(char const *, void (*)(int, void*), void *, int, __va_list) __printflike(1, 0); void log(int, const char *, ...) __printflike(2, 3); void log_console(struct uio *); int printf(const char *, ...) __printflike(1, 2); int snprintf(char *, size_t, const char *, ...) __printflike(3, 4); int sprintf(char *buf, const char *, ...) __printflike(2, 3); int uprintf(const char *, ...) __printflike(1, 2); int vprintf(const char *, __va_list) __printflike(1, 0); int vsnprintf(char *, size_t, const char *, __va_list) __printflike(3, 0); int vsnrprintf(char *, size_t, int, const char *, __va_list) __printflike(4, 0); int vsprintf(char *buf, const char *, __va_list) __printflike(2, 0); int ttyprintf(struct tty *, const char *, ...) __printflike(2, 3); int sscanf(const char *, char const *, ...) __nonnull(1) __nonnull(2); int vsscanf(const char *, char const *, __va_list) __nonnull(1) __nonnull(2); long strtol(const char *, char **, int) __nonnull(1); u_long strtoul(const char *, char **, int) __nonnull(1); quad_t strtoq(const char *, char **, int) __nonnull(1); u_quad_t strtouq(const char *, char **, int) __nonnull(1); void tprintf(struct proc *p, int pri, const char *, ...) __printflike(3, 4); void hexdump(void *ptr, int length, const char *hdr, int flags); #define HD_COLUMN_MASK 0xff #define HD_DELIM_MASK 0xff00 #define HD_OMIT_COUNT (1 << 16) #define HD_OMIT_HEX (1 << 17) #define HD_OMIT_CHARS (1 << 18) #define ovbcopy(f, t, l) bcopy((f), (t), (l)) void bcopy(const void *from, void *to, size_t len) __nonnull(1) __nonnull(2); void bzero(void *buf, size_t len) __nonnull(1); void *memcpy(void *to, const void *from, size_t len) __nonnull(1) __nonnull(2); int copystr(const void * __restrict kfaddr, void * __restrict kdaddr, size_t len, size_t * __restrict lencopied) __nonnull(1) __nonnull(2); int copyinstr(const void * __restrict udaddr, void * __restrict kaddr, size_t len, size_t * __restrict lencopied) __nonnull(1) __nonnull(2); int copyin(const void * __restrict udaddr, void * __restrict kaddr, size_t len) __nonnull(1) __nonnull(2); int copyout(const void * __restrict kaddr, void * __restrict udaddr, size_t len) __nonnull(1) __nonnull(2); int fubyte(const void *base); long fuword(const void *base); int fuword16(void *base); int32_t fuword32(const void *base); int64_t fuword64(const void *base); int subyte(void *base, int byte); int suword(void *base, long word); int suword16(void *base, int word); int suword32(void *base, int32_t word); int suword64(void *base, int64_t word); intptr_t casuptr(intptr_t *p, intptr_t old, intptr_t new); void realitexpire(void *); void hardclock(struct clockframe *frame); void hardclock_process(struct clockframe *frame); void softclock(void *); void statclock(struct clockframe *frame); void profclock(struct clockframe *frame); void startprofclock(struct proc *); void stopprofclock(struct proc *); void cpu_startprofclock(void); void cpu_stopprofclock(void); /* flags for suser() and suser_cred() */ #define PRISON_ROOT 1 int suser(struct thread *td); int suser_cred(struct ucred *cred, int flag); int cr_cansee(struct ucred *u1, struct ucred *u2); int cr_canseesocket(struct ucred *cred, struct socket *so); char *getenv(const char *name); void freeenv(char *env); int getenv_int(const char *name, int *data); int getenv_string(const char *name, char *data, int size); int getenv_quad(const char *name, quad_t *data); int setenv(const char *name, const char *value); int unsetenv(const char *name); int testenv(const char *name); #ifdef APM_FIXUP_CALLTODO struct timeval; void adjust_timeout_calltodo(struct timeval *time_change); #endif /* APM_FIXUP_CALLTODO */ #include /* Initialize the world */ void consinit(void); void cpu_initclocks(void); void usrinfoinit(void); /* Finalize the world. */ void shutdown_nice(int); /* * Kernel to clock driver interface. */ void inittodr(time_t base); void resettodr(void); void startrtclock(void); /* Timeouts */ typedef void timeout_t(void *); /* timeout function type */ #define CALLOUT_HANDLE_INITIALIZER(handle) \ { NULL } void callout_handle_init(struct callout_handle *); struct callout_handle timeout(timeout_t *, void *, int); void untimeout(timeout_t *, void *, struct callout_handle); caddr_t kern_timeout_callwheel_alloc(caddr_t v); void kern_timeout_callwheel_init(void); /* Stubs for obsolete functions that used to be for interrupt management */ static __inline void spl0(void) { return; } static __inline intrmask_t splbio(void) { return 0; } static __inline intrmask_t splcam(void) { return 0; } static __inline intrmask_t splclock(void) { return 0; } static __inline intrmask_t splhigh(void) { return 0; } static __inline intrmask_t splimp(void) { return 0; } static __inline intrmask_t splnet(void) { return 0; } static __inline intrmask_t splsoftcam(void) { return 0; } static __inline intrmask_t splsoftclock(void) { return 0; } static __inline intrmask_t splsofttty(void) { return 0; } static __inline intrmask_t splsoftvm(void) { return 0; } static __inline intrmask_t splsofttq(void) { return 0; } static __inline intrmask_t splstatclock(void) { return 0; } static __inline intrmask_t spltty(void) { return 0; } static __inline intrmask_t splvm(void) { return 0; } static __inline void splx(intrmask_t ipl __unused) { return; } /* * Various callout lists. */ /* * Not exactly a callout LIST, but a callout entry. * Allow an external module to define a hardware watchdog tickler. * Normally a process would do this, but there are times when the * kernel needs to be able to hold off the watchdog, when the process * is not active, e.g., when dumping core. */ typedef void (*watchdog_tickle_fn)(void); extern watchdog_tickle_fn wdog_tickler; /* * Common `proc' functions are declared here so that proc.h can be included * less often. */ int msleep(void *chan, struct mtx *mtx, int pri, const char *wmesg, int timo); #define tsleep(chan, pri, wmesg, timo) msleep(chan, NULL, pri, wmesg, timo) void wakeup(void *chan) __nonnull(1); void wakeup_one(void *chan) __nonnull(1); /* * Common `dev_t' stuff are declared here to avoid #include poisoning */ int major(dev_t x); int minor(dev_t x); udev_t dev2udev(dev_t x); dev_t udev2dev(udev_t x); int uminor(udev_t dev); int umajor(udev_t dev); udev_t makeudev(int x, int y); /* XXX: Should be void nanodelay(u_int nsec); */ void DELAY(int usec); #endif /* !_SYS_SYSTM_H_ */