Index: projects/sendfile/Makefile.inc1 =================================================================== --- projects/sendfile/Makefile.inc1 (revision 276056) +++ projects/sendfile/Makefile.inc1 (revision 276057) @@ -1,2136 +1,2151 @@ # # $FreeBSD$ # # Make command line options: # -DNO_CLEANDIR run ${MAKE} clean, instead of ${MAKE} cleandir # -DNO_CLEAN do not clean at all # -DDB_FROM_SRC use the user/group databases in src/etc instead of # the system database when installing. # -DNO_SHARE do not go into share subdir # -DKERNFAST define NO_KERNEL{CONFIG,CLEAN,DEPEND,OBJ} # -DNO_KERNELCONFIG do not run config in ${MAKE} buildkernel # -DNO_KERNELCLEAN do not run ${MAKE} clean in ${MAKE} buildkernel # -DNO_KERNELDEPEND do not run ${MAKE} depend in ${MAKE} buildkernel # -DNO_KERNELOBJ do not run ${MAKE} obj in ${MAKE} buildkernel # -DNO_PORTSUPDATE do not update ports in ${MAKE} update # -DNO_ROOT install without using root privilege # -DNO_DOCUPDATE do not update doc in ${MAKE} update # -DWITHOUT_CTF do not run the DTrace CTF conversion tools on built objects # LOCAL_DIRS="list of dirs" to add additional dirs to the SUBDIR list # LOCAL_ITOOLS="list of tools" to add additional tools to the ITOOLS list # LOCAL_LIB_DIRS="list of dirs" to add additional dirs to libraries target # LOCAL_MTREE="list of mtree files" to process to allow local directories # to be created before files are installed # LOCAL_TOOL_DIRS="list of dirs" to add additional dirs to the build-tools # list # METALOG="path to metadata log" to write permission and ownership # when NO_ROOT is set. (default: ${DESTDIR}/METALOG) # TARGET="machine" to crossbuild world for a different machine type # TARGET_ARCH= may be required when a TARGET supports multiple endians # BUILDENV_SHELL= shell to launch for the buildenv target (def:/bin/sh) # WORLD_FLAGS= additional flags to pass to make(1) during buildworld # KERNEL_FLAGS= additional flags to pass to make(1) during buildkernel # # The intended user-driven targets are: # buildworld - rebuild *everything*, including glue to help do upgrades # installworld- install everything built by "buildworld" # doxygen - build API documentation of the kernel # update - convenient way to update your source tree (eg: svn/svnup) # # Standard targets (not defined here) are documented in the makefiles in # /usr/share/mk. These include: # obj depend all install clean cleandepend cleanobj .if !defined(TARGET) || !defined(TARGET_ARCH) .error "Both TARGET and TARGET_ARCH must be defined." .endif .include "share/mk/src.opts.mk" .include .include # We must do share/info early so that installation of info `dir' # entries works correctly. Do it first since it is less likely to # grow dependencies on include and lib than vice versa. # # We must do lib/ and libexec/ before bin/, because if installworld # installs a new /bin/sh, the 'make' command will *immediately* # use that new version. And the new (dynamically-linked) /bin/sh # will expect to find appropriate libraries in /lib and /libexec. # SRCDIR?= ${.CURDIR} .if defined(SUBDIR_OVERRIDE) SUBDIR= ${SUBDIR_OVERRIDE} .else SUBDIR= share/info lib libexec SUBDIR+=bin .if ${MK_GAMES} != "no" SUBDIR+=games .endif .if ${MK_CDDL} != "no" SUBDIR+=cddl .endif SUBDIR+=gnu include .if ${MK_KERBEROS} != "no" SUBDIR+=kerberos5 .endif .if ${MK_RESCUE} != "no" SUBDIR+=rescue .endif SUBDIR+=sbin .if ${MK_CRYPT} != "no" SUBDIR+=secure .endif .if !defined(NO_SHARE) SUBDIR+=share .endif SUBDIR+=sys usr.bin usr.sbin .if ${MK_TESTS} != "no" SUBDIR+= tests .endif .if ${MK_OFED} != "no" SUBDIR+=contrib/ofed .endif # # We must do etc/ last for install/distribute to work. # SUBDIR+=etc # Local directories are last, since it is nice to at least get the base # system rebuilt before you do them. .for _DIR in ${LOCAL_DIRS} .if exists(${.CURDIR}/${_DIR}/Makefile) SUBDIR+= ${_DIR} .endif .endfor # Add LOCAL_LIB_DIRS, but only if they will not be picked up as a SUBDIR # of a LOCAL_DIRS directory. This allows LOCAL_DIRS=foo and # LOCAL_LIB_DIRS=foo/lib to behave as expected. .for _DIR in ${LOCAL_DIRS:M*/} ${LOCAL_DIRS:N*/:S|$|/|} _REDUNDENT_LIB_DIRS+= ${LOCAL_LIB_DIRS:M${_DIR}*} .endfor .for _DIR in ${LOCAL_LIB_DIRS} .if empty(_REDUNDENT_LIB_DIRS:M${_DIR}) && exists(${.CURDIR}/${_DIR}/Makefile) SUBDIR+= ${_DIR} .else .warning ${_DIR} not added to SUBDIR list. See UPDATING 20141121. .endif .endfor .endif .if defined(NOCLEAN) NO_CLEAN= ${NOCLEAN} .endif .if defined(NO_CLEANDIR) CLEANDIR= clean cleandepend .else CLEANDIR= cleandir .endif LOCAL_TOOL_DIRS?= BUILDENV_SHELL?=/bin/sh SVN?= /usr/local/bin/svn SVNFLAGS?= -r HEAD MAKEOBJDIRPREFIX?= /usr/obj .if !defined(OSRELDATE) .if exists(/usr/include/osreldate.h) OSRELDATE!= awk '/^\#define[[:space:]]*__FreeBSD_version/ { print $$3 }' \ /usr/include/osreldate.h .else OSRELDATE= 0 .endif .endif .if !defined(VERSION) REVISION!= ${MAKE} -C ${SRCDIR}/release -V REVISION BRANCH!= ${MAKE} -C ${SRCDIR}/release -V BRANCH SRCRELDATE!= awk '/^\#define[[:space:]]*__FreeBSD_version/ { print $$3 }' \ ${SRCDIR}/sys/sys/param.h VERSION= FreeBSD ${REVISION}-${BRANCH:C/-p[0-9]+$//} ${TARGET_ARCH} ${SRCRELDATE} .endif KNOWN_ARCHES?= amd64 arm armeb/arm armv6/arm armv6hf/arm i386 i386/pc98 mips mipsel/mips mips64el/mips mips64/mips mipsn32el/mips mipsn32/mips powerpc powerpc64/powerpc sparc64 .if ${TARGET} == ${TARGET_ARCH} _t= ${TARGET} .else _t= ${TARGET_ARCH}/${TARGET} .endif .for _t in ${_t} .if empty(KNOWN_ARCHES:M${_t}) .error Unknown target ${TARGET_ARCH}:${TARGET}. .endif .endfor .if ${TARGET} == ${MACHINE} TARGET_CPUTYPE?=${CPUTYPE} .else TARGET_CPUTYPE?= .endif .if !empty(TARGET_CPUTYPE) _TARGET_CPUTYPE=${TARGET_CPUTYPE} .else _TARGET_CPUTYPE=dummy .endif _CPUTYPE!= MAKEFLAGS= CPUTYPE=${_TARGET_CPUTYPE} ${MAKE} \ -f /dev/null -m ${.CURDIR}/share/mk -V CPUTYPE .if ${_CPUTYPE} != ${_TARGET_CPUTYPE} .error CPUTYPE global should be set with ?=. .endif .if make(buildworld) BUILD_ARCH!= uname -p .if ${MACHINE_ARCH} != ${BUILD_ARCH} .error To cross-build, set TARGET_ARCH. .endif .endif .if ${MACHINE} == ${TARGET} && ${MACHINE_ARCH} == ${TARGET_ARCH} && !defined(CROSS_BUILD_TESTING) OBJTREE= ${MAKEOBJDIRPREFIX} .else OBJTREE= ${MAKEOBJDIRPREFIX}/${TARGET}.${TARGET_ARCH} .endif WORLDTMP= ${OBJTREE}${.CURDIR}/tmp # /usr/games added for fortune which depend on strfile BPATH= ${WORLDTMP}/legacy/usr/sbin:${WORLDTMP}/legacy/usr/bin:${WORLDTMP}/legacy/usr/games:${WORLDTMP}/legacy/bin XPATH= ${WORLDTMP}/usr/sbin:${WORLDTMP}/usr/bin:${WORLDTMP}/usr/games STRICTTMPPATH= ${BPATH}:${XPATH} TMPPATH= ${STRICTTMPPATH}:${PATH} # # Avoid running mktemp(1) unless actually needed. # It may not be functional, e.g., due to new ABI # when in the middle of installing over this system. # .if make(distributeworld) || make(installworld) INSTALLTMP!= /usr/bin/mktemp -d -u -t install .endif # # Building a world goes through the following stages # # 1. legacy stage [BMAKE] # This stage is responsible for creating compatibility # shims that are needed by the bootstrap-tools, # build-tools and cross-tools stages. # 1. bootstrap-tools stage [BMAKE] # This stage is responsible for creating programs that # are needed for backward compatibility reasons. They # are not built as cross-tools. # 2. build-tools stage [TMAKE] # This stage is responsible for creating the object # tree and building any tools that are needed during # the build process. # 3. cross-tools stage [XMAKE] # This stage is responsible for creating any tools that # are needed for cross-builds. A cross-compiler is one # of them. # 4. world stage [WMAKE] # This stage actually builds the world. # 5. install stage (optional) [IMAKE] # This stage installs a previously built world. # BOOTSTRAPPING?= 0 # Common environment for world related stages CROSSENV= MAKEOBJDIRPREFIX=${OBJTREE} \ MACHINE_ARCH=${TARGET_ARCH} \ MACHINE=${TARGET} \ CPUTYPE=${TARGET_CPUTYPE} .if ${MK_GROFF} != "no" CROSSENV+= GROFF_BIN_PATH=${WORLDTMP}/legacy/usr/bin \ GROFF_FONT_PATH=${WORLDTMP}/legacy/usr/share/groff_font \ GROFF_TMAC_PATH=${WORLDTMP}/legacy/usr/share/tmac .endif .if defined(TARGET_CFLAGS) CROSSENV+= ${TARGET_CFLAGS} .endif # bootstrap-tools stage BMAKEENV= INSTALL="sh ${.CURDIR}/tools/install.sh" \ PATH=${BPATH}:${PATH} \ WORLDTMP=${WORLDTMP} \ VERSION="${VERSION}" \ MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}" BMAKE= MAKEOBJDIRPREFIX=${WORLDTMP} \ ${BMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \ DESTDIR= \ BOOTSTRAPPING=${OSRELDATE} \ SSP_CFLAGS= \ MK_HTML=no MK_INFO=no NO_LINT=yes MK_MAN=no \ -DNO_PIC MK_PROFILE=no -DNO_SHARED \ -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \ MK_CLANG_EXTRAS=no MK_CLANG_FULL=no \ MK_LLDB=no MK_TESTS=no # build-tools stage TMAKE= MAKEOBJDIRPREFIX=${OBJTREE} \ ${BMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \ TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ DESTDIR= \ BOOTSTRAPPING=${OSRELDATE} \ SSP_CFLAGS= \ -DNO_LINT \ -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \ MK_CLANG_EXTRAS=no MK_CLANG_FULL=no \ MK_LLDB=no MK_TESTS=no # cross-tools stage XMAKE= TOOLS_PREFIX=${WORLDTMP} ${BMAKE} \ TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ MK_GDB=no MK_TESTS=no # kernel-tools stage KTMAKEENV= INSTALL="sh ${.CURDIR}/tools/install.sh" \ PATH=${BPATH}:${PATH} \ WORLDTMP=${WORLDTMP} \ VERSION="${VERSION}" KTMAKE= TOOLS_PREFIX=${WORLDTMP} MAKEOBJDIRPREFIX=${WORLDTMP} \ ${KTMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \ DESTDIR= \ BOOTSTRAPPING=${OSRELDATE} \ SSP_CFLAGS= \ MK_HTML=no MK_INFO=no -DNO_LINT MK_MAN=no \ -DNO_PIC MK_PROFILE=no -DNO_SHARED \ -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no # world stage WMAKEENV= ${CROSSENV} \ _SHLIBDIRPREFIX=${WORLDTMP} \ _LDSCRIPTROOT= \ VERSION="${VERSION}" \ INSTALL="sh ${.CURDIR}/tools/install.sh" \ PATH=${TMPPATH} # make hierarchy HMAKE= PATH=${TMPPATH} ${MAKE} LOCAL_MTREE=${LOCAL_MTREE:Q} .if defined(NO_ROOT) HMAKE+= PATH=${TMPPATH} METALOG=${METALOG} -DNO_ROOT .endif .if ${MK_CDDL} == "no" WMAKEENV+= MK_CTF=no .endif .if defined(CROSS_TOOLCHAIN) LOCALBASE?= /usr/local .include "${LOCALBASE}/share/toolchains/${CROSS_TOOLCHAIN}.mk" .endif .if defined(CROSS_TOOLCHAIN_PREFIX) CROSS_COMPILER_PREFIX?=${CROSS_TOOLCHAIN_PREFIX} CROSS_BINUTILS_PREFIX?=${CROSS_TOOLCHAIN_PREFIX} .endif XCOMPILERS= CC CXX CPP .for COMPILER in ${XCOMPILERS} .if defined(CROSS_COMPILER_PREFIX) X${COMPILER}?= ${CROSS_COMPILER_PREFIX}${${COMPILER}} .else X${COMPILER}?= ${${COMPILER}} .endif .endfor XBINUTILS= AS AR LD NM OBJCOPY OBJDUMP RANLIB SIZE STRINGS .for BINUTIL in ${XBINUTILS} .if defined(CROSS_BINUTILS_PREFIX) X${BINUTIL}?= ${CROSS_BINUTILS_PREFIX}${${BINUTIL}} .else X${BINUTIL}?= ${${BINUTIL}} .endif .endfor WMAKEENV+= CC="${XCC} ${XCFLAGS}" CXX="${XCXX} ${XCFLAGS} ${XCXXFLAGS}" \ DEPFLAGS="${DEPFLAGS}" \ CPP="${XCPP} ${XCFLAGS}" \ AS="${XAS}" AR="${XAR}" LD="${XLD}" NM=${XNM} \ OBJDUMP=${XOBJDUMP} OBJCOPY="${XOBJCOPY}" \ RANLIB=${XRANLIB} STRINGS=${XSTRINGS} \ SIZE="${XSIZE}" .if ${XCC:M/*} XFLAGS= --sysroot=${WORLDTMP} .if defined(CROSS_BINUTILS_PREFIX) # In the case of xdev-build tools, CROSS_BINUTILS_PREFIX won't be a # directory, but the compiler will look in the right place for it's # tools so we don't need to tell it where to look. .if exists(${CROSS_BINUTILS_PREFIX}) XFLAGS+= -B${CROSS_BINUTILS_PREFIX} .endif .else XFLAGS+= -B${WORLDTMP}/usr/bin .endif .if ${TARGET} == "arm" .if ${TARGET_ARCH:M*hf*} != "" TARGET_ABI= gnueabihf .else TARGET_ABI= gnueabi .endif .endif .if defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == gcc XCFLAGS+= -isystem ${WORLDTMP}/usr/include -L${WORLDTMP}/usr/lib XCXXFLAGS+= -I${WORLDTMP}/usr/include/c++/v1 -std=gnu++11 -L${WORLDTMP}/../lib/libc++ DEPFLAGS+= -I${WORLDTMP}/usr/include/c++/v1 .else TARGET_ABI?= unknown TARGET_TRIPLE?= ${TARGET_ARCH:C/amd64/x86_64/}-${TARGET_ABI}-freebsd11.0 XCFLAGS+= -target ${TARGET_TRIPLE} .endif .endif WMAKE= ${WMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 DESTDIR=${WORLDTMP} .if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "powerpc64" # 32 bit world LIB32_OBJTREE= ${OBJTREE}${.CURDIR}/world32 LIB32TMP= ${OBJTREE}${.CURDIR}/lib32 .if ${TARGET_ARCH} == "amd64" .if empty(TARGET_CPUTYPE) LIB32CPUFLAGS= -march=i686 -mmmx -msse -msse2 .else LIB32CPUFLAGS= -march=${TARGET_CPUTYPE} .endif LIB32WMAKEENV= MACHINE=i386 MACHINE_ARCH=i386 \ MACHINE_CPU="i686 mmx sse sse2" LIB32WMAKEFLAGS= \ AS="${AS} --32" \ LD="${LD} -m elf_i386_fbsd -Y P,${LIB32TMP}/usr/lib32" .elif ${TARGET_ARCH} == "powerpc64" .if empty(TARGET_CPUTYPE) LIB32CPUFLAGS= -mcpu=powerpc .else LIB32CPUFLAGS= -mcpu=${TARGET_CPUTYPE} .endif LIB32WMAKEENV= MACHINE=powerpc MACHINE_ARCH=powerpc LIB32WMAKEFLAGS= \ LD="${LD} -m elf32ppc_fbsd" .endif LIB32FLAGS= -m32 ${LIB32CPUFLAGS} -DCOMPAT_32BIT \ -isystem ${LIB32TMP}/usr/include/ \ -L${LIB32TMP}/usr/lib32 \ -B${LIB32TMP}/usr/lib32 .if ${XCC:M/*} LIB32FLAGS+= --sysroot=${WORLDTMP} .endif # Yes, the flags are redundant. LIB32WMAKEENV+= MAKEOBJDIRPREFIX=${LIB32_OBJTREE} \ _SHLIBDIRPREFIX=${LIB32TMP} \ _LDSCRIPTROOT=${LIB32TMP} \ VERSION="${VERSION}" \ INSTALL="sh ${.CURDIR}/tools/install.sh" \ PATH=${TMPPATH} \ LIBDIR=/usr/lib32 \ SHLIBDIR=/usr/lib32 \ LIBPRIVATEDIR=/usr/lib32/private \ DTRACE="${DTRACE} -32" LIB32WMAKEFLAGS+= CC="${XCC} ${LIB32FLAGS}" \ CXX="${XCXX} ${LIB32FLAGS}" \ DESTDIR=${LIB32TMP} \ -DCOMPAT_32BIT \ -DLIBRARIES_ONLY \ -DNO_CPU_CFLAGS \ MK_CTF=no \ -DNO_LINT \ MK_TESTS=no LIB32WMAKE= ${LIB32WMAKEENV} ${MAKE} ${LIB32WMAKEFLAGS} \ MK_MAN=no MK_INFO=no MK_HTML=no LIB32IMAKE= ${LIB32WMAKE:NINSTALL=*:NDESTDIR=*:N_LDSCRIPTROOT=*} \ MK_TOOLCHAIN=no ${IMAKE_INSTALL} .endif IMAKEENV= ${CROSSENV:N_LDSCRIPTROOT=*} IMAKE= ${IMAKEENV} ${MAKE} -f Makefile.inc1 \ ${IMAKE_INSTALL} ${IMAKE_MTREE} .if empty(.MAKEFLAGS:M-n) IMAKEENV+= PATH=${STRICTTMPPATH}:${INSTALLTMP} \ LD_LIBRARY_PATH=${INSTALLTMP} \ PATH_LOCALE=${INSTALLTMP}/locale IMAKE+= __MAKE_SHELL=${INSTALLTMP}/sh .else IMAKEENV+= PATH=${TMPPATH}:${INSTALLTMP} .endif .if defined(DB_FROM_SRC) INSTALLFLAGS+= -N ${.CURDIR}/etc MTREEFLAGS+= -N ${.CURDIR}/etc .endif _INSTALL_DDIR= ${DESTDIR}/${DISTDIR} INSTALL_DDIR= ${_INSTALL_DDIR:S://:/:g:C:/$::} .if defined(NO_ROOT) METALOG?= ${DESTDIR}/${DISTDIR}/METALOG IMAKE+= -DNO_ROOT METALOG=${METALOG} INSTALLFLAGS+= -U -M ${METALOG} -D ${INSTALL_DDIR} MTREEFLAGS+= -W .endif .if defined(DB_FROM_SRC) || defined(NO_ROOT) IMAKE_INSTALL= INSTALL="install ${INSTALLFLAGS}" IMAKE_MTREE= MTREE_CMD="mtree ${MTREEFLAGS}" .endif # kernel stage KMAKEENV= ${WMAKEENV} KMAKE= ${KMAKEENV} ${MAKE} ${.MAKEFLAGS} ${KERNEL_FLAGS} KERNEL=${INSTKERNNAME} # # buildworld # # Attempt to rebuild the entire system, with reasonable chance of # success, regardless of how old your existing system is. # _worldtmp: .if ${.CURDIR:C/[^,]//g} != "" # The m4 build of sendmail files doesn't like it if ',' is used # anywhere in the path of it's files. @echo @echo "*** Error: path to source tree contains a comma ','" @echo false .endif @echo @echo "--------------------------------------------------------------" @echo ">>> Rebuilding the temporary build tree" @echo "--------------------------------------------------------------" .if !defined(NO_CLEAN) rm -rf ${WORLDTMP} .if defined(LIB32TMP) rm -rf ${LIB32TMP} .endif .else rm -rf ${WORLDTMP}/legacy/usr/include # XXX - These three can depend on any header file. rm -f ${OBJTREE}${.CURDIR}/usr.bin/kdump/ioctl.c rm -f ${OBJTREE}${.CURDIR}/usr.bin/kdump/kdump_subr.c rm -f ${OBJTREE}${.CURDIR}/usr.bin/truss/ioctl.c .endif .for _dir in \ lib usr legacy/bin legacy/usr mkdir -p ${WORLDTMP}/${_dir} .endfor mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${WORLDTMP}/legacy/usr >/dev/null .if ${MK_GROFF} != "no" mtree -deU -f ${.CURDIR}/etc/mtree/BSD.groff.dist \ -p ${WORLDTMP}/legacy/usr >/dev/null .endif mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${WORLDTMP}/usr >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \ -p ${WORLDTMP}/usr/include >/dev/null ln -sf ${.CURDIR}/sys ${WORLDTMP} .if ${MK_DEBUG_FILES} != "no" # We could instead disable debug files for these build stages mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \ -p ${WORLDTMP}/legacy/usr/lib >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \ -p ${WORLDTMP}/usr/lib >/dev/null .endif .if ${MK_TESTS} != "no" mkdir -p ${WORLDTMP}${TESTSBASE} mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \ -p ${WORLDTMP}${TESTSBASE} >/dev/null .endif .for _mtree in ${LOCAL_MTREE} mtree -deU -f ${.CURDIR}/${_mtree} -p ${WORLDTMP} > /dev/null .endfor _legacy: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 1.1: legacy release compatibility shims" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${BMAKE} legacy _bootstrap-tools: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 1.2: bootstrap tools" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${BMAKE} bootstrap-tools _cleanobj: .if !defined(NO_CLEAN) @echo @echo "--------------------------------------------------------------" @echo ">>> stage 2.1: cleaning up the object tree" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${WMAKE} ${CLEANDIR:S/^/par-/} .if defined(LIB32TMP) ${_+_}cd ${.CURDIR}; ${LIB32WMAKE} -f Makefile.inc1 ${CLEANDIR:S/^/par-/} .endif .endif _obj: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 2.2: rebuilding the object tree" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${WMAKE} par-obj _build-tools: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 2.3: build tools" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${TMAKE} build-tools _cross-tools: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 3: cross tools" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${XMAKE} cross-tools ${_+_}cd ${.CURDIR}; ${XMAKE} kernel-tools _includes: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 4.1: building includes" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${WMAKE} SHARED=symlinks par-includes _libraries: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 4.2: building libraries" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; \ ${WMAKE} -DNO_FSCHG MK_HTML=no MK_INFO=no -DNO_LINT MK_MAN=no \ MK_PROFILE=no MK_TESTS=no MK_TESTS_SUPPORT=${MK_TESTS} libraries _depend: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 4.3: make dependencies" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${WMAKE} par-depend everything: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 4.4: building everything" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${WMAKE} par-all .if defined(LIB32TMP) build32: @echo @echo "--------------------------------------------------------------" @echo ">>> stage 5.1: building 32 bit shim libraries" @echo "--------------------------------------------------------------" mkdir -p ${LIB32TMP}/usr/include mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${LIB32TMP}/usr >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \ -p ${LIB32TMP}/usr/include >/dev/null .if ${MK_DEBUG_FILES} != "no" mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \ -p ${LIB32TMP}/usr/lib >/dev/null .endif mkdir -p ${WORLDTMP} ln -sf ${.CURDIR}/sys ${WORLDTMP} .for _t in obj includes cd ${.CURDIR}/include; ${LIB32WMAKE} DIRPRFX=include/ ${_t} cd ${.CURDIR}/lib; ${LIB32WMAKE} DIRPRFX=lib/ ${_t} .if ${MK_CDDL} != "no" cd ${.CURDIR}/cddl/lib; ${LIB32WMAKE} DIRPRFX=cddl/lib/ ${_t} .endif cd ${.CURDIR}/gnu/lib; ${LIB32WMAKE} DIRPRFX=gnu/lib/ ${_t} .if ${MK_CRYPT} != "no" cd ${.CURDIR}/secure/lib; ${LIB32WMAKE} DIRPRFX=secure/lib/ ${_t} .endif .if ${MK_KERBEROS} != "no" cd ${.CURDIR}/kerberos5/lib; ${LIB32WMAKE} DIRPRFX=kerberos5/lib ${_t} .endif .endfor .for _dir in usr.bin/lex/lib cd ${.CURDIR}/${_dir}; ${LIB32WMAKE} DIRPRFX=${_dir}/ obj .endfor .for _dir in lib/ncurses/ncurses lib/ncurses/ncursesw lib/libmagic cd ${.CURDIR}/${_dir}; \ WORLDTMP=${WORLDTMP} \ MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}" \ MAKEOBJDIRPREFIX=${LIB32_OBJTREE} ${MAKE} SSP_CFLAGS= DESTDIR= \ DIRPRFX=${_dir}/ -DNO_LINT -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \ build-tools .endfor cd ${.CURDIR}; \ ${LIB32WMAKE} -f Makefile.inc1 libraries .for _t in obj depend all cd ${.CURDIR}/libexec/rtld-elf; PROG=ld-elf32.so.1 ${LIB32WMAKE} \ DIRPRFX=libexec/rtld-elf/ ${_t} cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIB32WMAKE} \ DIRPRFX=usr.bin/ldd ${_t} .endfor distribute32 install32: cd ${.CURDIR}/lib; ${LIB32IMAKE} ${.TARGET:S/32$//} .if ${MK_CDDL} != "no" cd ${.CURDIR}/cddl/lib; ${LIB32IMAKE} ${.TARGET:S/32$//} .endif cd ${.CURDIR}/gnu/lib; ${LIB32IMAKE} ${.TARGET:S/32$//} .if ${MK_CRYPT} != "no" cd ${.CURDIR}/secure/lib; ${LIB32IMAKE} ${.TARGET:S/32$//} .endif .if ${MK_KERBEROS} != "no" cd ${.CURDIR}/kerberos5/lib; ${LIB32IMAKE} ${.TARGET:S/32$//} .endif cd ${.CURDIR}/libexec/rtld-elf; \ PROG=ld-elf32.so.1 ${LIB32IMAKE} ${.TARGET:S/32$//} cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIB32IMAKE} ${.TARGET:S/32$//} .endif WMAKE_TGTS= .if !defined(SUBDIR_OVERRIDE) WMAKE_TGTS+= _worldtmp _legacy _bootstrap-tools .endif WMAKE_TGTS+= _cleanobj _obj _build-tools .if !defined(SUBDIR_OVERRIDE) WMAKE_TGTS+= _cross-tools .endif WMAKE_TGTS+= _includes _libraries _depend everything .if defined(LIB32TMP) && ${MK_LIB32} != "no" WMAKE_TGTS+= build32 .endif buildworld: buildworld_prologue ${WMAKE_TGTS} buildworld_epilogue .ORDER: buildworld_prologue ${WMAKE_TGTS} buildworld_epilogue buildworld_prologue: @echo "--------------------------------------------------------------" @echo ">>> World build started on `LC_ALL=C date`" @echo "--------------------------------------------------------------" buildworld_epilogue: @echo @echo "--------------------------------------------------------------" @echo ">>> World build completed on `LC_ALL=C date`" @echo "--------------------------------------------------------------" # # We need to have this as a target because the indirection between Makefile # and Makefile.inc1 causes the correct PATH to be used, rather than a # modification of the current environment's PATH. In addition, we need # to quote multiword values. # buildenvvars: @echo ${WMAKEENV:Q} .if ${.TARGETS:Mbuildenv} .if ${.MAKEFLAGS:M-j} .error The buildenv target is incompatible with -j .endif .endif buildenv: @echo Entering world for ${TARGET_ARCH}:${TARGET} @cd ${.CURDIR} && env ${WMAKEENV} ${BUILDENV_SHELL} || true TOOLCHAIN_TGTS= ${WMAKE_TGTS:N_depend:Neverything:Nbuild32} toolchain: ${TOOLCHAIN_TGTS} kernel-toolchain: ${TOOLCHAIN_TGTS:N_includes:N_libraries} # # installcheck # # Checks to be sure system is ready for installworld/installkernel. # installcheck: _installcheck_world _installcheck_kernel _installcheck_world: _installcheck_kernel: # # Require DESTDIR to be set if installing for a different architecture or # using the user/group database in the source tree. # .if ${TARGET_ARCH} != ${MACHINE_ARCH} || ${TARGET} != ${MACHINE} || \ defined(DB_FROM_SRC) .if !make(distributeworld) _installcheck_world: __installcheck_DESTDIR _installcheck_kernel: __installcheck_DESTDIR __installcheck_DESTDIR: .if !defined(DESTDIR) || empty(DESTDIR) @echo "ERROR: Please set DESTDIR!"; \ false .endif .endif .endif .if !defined(DB_FROM_SRC) # # Check for missing UIDs/GIDs. # CHECK_UIDS= auditdistd CHECK_GIDS= audit .if ${MK_SENDMAIL} != "no" CHECK_UIDS+= smmsp CHECK_GIDS+= smmsp .endif .if ${MK_PF} != "no" CHECK_UIDS+= proxy CHECK_GIDS+= proxy authpf .endif .if ${MK_UNBOUND} != "no" CHECK_UIDS+= unbound CHECK_GIDS+= unbound .endif _installcheck_world: __installcheck_UGID __installcheck_UGID: .for uid in ${CHECK_UIDS} @if ! `id -u ${uid} >/dev/null 2>&1`; then \ echo "ERROR: Required ${uid} user is missing, see /usr/src/UPDATING."; \ false; \ fi .endfor .for gid in ${CHECK_GIDS} @if ! `find / -prune -group ${gid} >/dev/null 2>&1`; then \ echo "ERROR: Required ${gid} group is missing, see /usr/src/UPDATING."; \ false; \ fi .endfor .endif # # Required install tools to be saved in a scratch dir for safety. # .if ${MK_INFO} != "no" _install-info= install-info .endif .if ${MK_ZONEINFO} != "no" _zoneinfo= zic tzsetup .endif ITOOLS= [ awk cap_mkdb cat chflags chmod chown \ date echo egrep find grep id install ${_install-info} \ ln lockf make mkdir mtree mv pwd_mkdb \ rm sed services_mkdb sh strip sysctl test true uname wc ${_zoneinfo} \ ${LOCAL_ITOOLS} # Needed for share/man .if ${MK_MAN} != "no" ITOOLS+=makewhatis .endif # # distributeworld # # Distributes everything compiled by a `buildworld'. # # installworld # # Installs everything compiled by a 'buildworld'. # # Non-base distributions produced by the base system EXTRA_DISTRIBUTIONS= doc .if ${MK_GAMES} != "no" EXTRA_DISTRIBUTIONS+= games .endif .if defined(LIB32TMP) && ${MK_LIB32} != "no" EXTRA_DISTRIBUTIONS+= lib32 .endif .if ${MK_TESTS} != "no" EXTRA_DISTRIBUTIONS+= tests .endif DEBUG_DISTRIBUTIONS= .if ${MK_DEBUG_FILES} != "no" DEBUG_DISTRIBUTIONS+= base ${EXTRA_DISTRIBUTIONS:S,doc,,} .endif MTREE_MAGIC?= mtree 2.0 distributeworld installworld: _installcheck_world mkdir -p ${INSTALLTMP} progs=$$(for prog in ${ITOOLS}; do \ if progpath=`which $$prog`; then \ echo $$progpath; \ else \ echo "Required tool $$prog not found in PATH." >&2; \ exit 1; \ fi; \ done); \ libs=$$(ldd -f "%o %p\n" -f "%o %p\n" $$progs 2>/dev/null | sort -u | \ while read line; do \ set -- $$line; \ if [ "$$2 $$3" != "not found" ]; then \ echo $$2; \ else \ echo "Required library $$1 not found." >&2; \ exit 1; \ fi; \ done); \ cp $$libs $$progs ${INSTALLTMP} cp -R $${PATH_LOCALE:-"/usr/share/locale"} ${INSTALLTMP}/locale .if defined(NO_ROOT) echo "#${MTREE_MAGIC}" > ${METALOG} .endif .if make(distributeworld) .for dist in ${EXTRA_DISTRIBUTIONS} -mkdir ${DESTDIR}/${DISTDIR}/${dist} mtree -deU -f ${.CURDIR}/etc/mtree/BSD.root.dist \ -p ${DESTDIR}/${DISTDIR}/${dist} >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${DESTDIR}/${DISTDIR}/${dist}/usr >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \ -p ${DESTDIR}/${DISTDIR}/${dist}/usr/include >/dev/null .if ${MK_DEBUG_FILES} != "no" mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \ -p ${DESTDIR}/${DISTDIR}/${dist}/usr/lib >/dev/null .endif .if ${MK_TESTS} != "no" && ${dist} == "tests" -mkdir -p ${DESTDIR}/${DISTDIR}/${dist}${TESTSBASE} mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \ -p ${DESTDIR}/${DISTDIR}/${dist}${TESTSBASE} >/dev/null .endif .if defined(NO_ROOT) ${IMAKEENV} mtree -C -f ${.CURDIR}/etc/mtree/BSD.root.dist | \ sed -e 's#^\./#./${dist}/#' >> ${METALOG} ${IMAKEENV} mtree -C -f ${.CURDIR}/etc/mtree/BSD.usr.dist | \ sed -e 's#^\./#./${dist}/usr/#' >> ${METALOG} ${IMAKEENV} mtree -C -f ${.CURDIR}/etc/mtree/BSD.include.dist | \ sed -e 's#^\./#./${dist}/usr/include/#' >> ${METALOG} .endif .endfor -mkdir ${DESTDIR}/${DISTDIR}/base cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ METALOG=${METALOG} ${IMAKE_INSTALL} ${IMAKE_MTREE} \ DISTBASE=/base DESTDIR=${DESTDIR}/${DISTDIR}/base \ LOCAL_MTREE=${LOCAL_MTREE:Q} distrib-dirs .endif ${_+_}cd ${.CURDIR}; ${IMAKE} re${.TARGET:S/world$//}; \ ${IMAKEENV} rm -rf ${INSTALLTMP} .if make(distributeworld) .for dist in ${EXTRA_DISTRIBUTIONS} find ${DESTDIR}/${DISTDIR}/${dist} -mindepth 1 -empty -delete .endfor .if defined(NO_ROOT) .for dist in base ${EXTRA_DISTRIBUTIONS} @# For each file that exists in this dist, print the corresponding @# line from the METALOG. This relies on the fact that @# a line containing only the filename will sort immediatly before @# the relevant mtree line. cd ${DESTDIR}/${DISTDIR}; \ find ./${dist} | sort -u ${METALOG} - | \ awk 'BEGIN { print "#${MTREE_MAGIC}" } !/ type=/ { file = $$1 } / type=/ { if ($$1 == file) { sub(/^\.\/${dist}\//, "./"); print } }' > \ ${DESTDIR}/${DISTDIR}/${dist}.meta .endfor .for dist in ${DEBUG_DISTRIBUTIONS} @# For each file that exists in this dist, print the corresponding @# line from the METALOG. This relies on the fact that @# a line containing only the filename will sort immediatly before @# the relevant mtree line. cd ${DESTDIR}/${DISTDIR}; \ find ./${dist}/usr/lib/debug | sort -u ${METALOG} - | \ awk 'BEGIN { print "#${MTREE_MAGIC}" } !/ type=/ { file = $$1 } / type=/ { if ($$1 == file) { sub(/^\.\/${dist}\//, "./"); print } }' > \ ${DESTDIR}/${DISTDIR}/${dist}.debug.meta .endfor .endif .endif packageworld: .for dist in base ${EXTRA_DISTRIBUTIONS} .if defined(NO_ROOT) ${_+_}cd ${DESTDIR}/${DISTDIR}/${dist}; \ tar cvJf ${DESTDIR}/${DISTDIR}/${dist}.txz \ --exclude usr/lib/debug \ @${DESTDIR}/${DISTDIR}/${dist}.meta .else ${_+_}cd ${DESTDIR}/${DISTDIR}/${dist}; \ tar cvJf ${DESTDIR}/${DISTDIR}/${dist}.txz \ --exclude usr/lib/debug . .endif .endfor .for dist in ${DEBUG_DISTRIBUTIONS} . if defined(NO_ROOT) ${_+_}cd ${DESTDIR}/${DISTDIR}/${dist}; \ tar cvJf ${DESTDIR}/${DISTDIR}/${dist}-dbg.txz \ @${DESTDIR}/${DISTDIR}/${dist}.debug.meta . else ${_+_}cd ${DESTDIR}/${DISTDIR}/${dist}; \ tar cvJfL ${DESTDIR}/${DISTDIR}/${dist}-dbg.txz \ usr/lib/debug . endif .endfor # # reinstall # # If you have a build server, you can NFS mount the source and obj directories # and do a 'make reinstall' on the *client* to install new binaries from the # most recent server build. # reinstall: .MAKE @echo "--------------------------------------------------------------" @echo ">>> Making hierarchy" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 \ LOCAL_MTREE=${LOCAL_MTREE:Q} hierarchy @echo @echo "--------------------------------------------------------------" @echo ">>> Installing everything" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 install .if defined(LIB32TMP) && ${MK_LIB32} != "no" ${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 install32 .endif redistribute: .MAKE @echo "--------------------------------------------------------------" @echo ">>> Distributing everything" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 distribute .if defined(LIB32TMP) && ${MK_LIB32} != "no" ${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 distribute32 \ DISTRIBUTION=lib32 .endif distrib-dirs distribution: .MAKE cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ ${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET} # # buildkernel and installkernel # # Which kernels to build and/or install is specified by setting # KERNCONF. If not defined a GENERIC kernel is built/installed. # Only the existing (depending TARGET) config files are used # for building kernels and only the first of these is designated # as the one being installed. # # Note that we have to use TARGET instead of TARGET_ARCH when # we're in kernel-land. Since only TARGET_ARCH is (expected) to # be set to cross-build, we have to make sure TARGET is set # properly. .if defined(KERNFAST) NO_KERNELCLEAN= t NO_KERNELCONFIG= t NO_KERNELDEPEND= t NO_KERNELOBJ= t # Shortcut for KERNCONF=Blah -DKERNFAST is now KERNFAST=Blah .if !defined(KERNCONF) && ${KERNFAST} != "1" KERNCONF=${KERNFAST} .endif .endif .if ${TARGET_ARCH} == "powerpc64" KERNCONF?= GENERIC64 .else KERNCONF?= GENERIC .endif INSTKERNNAME?= kernel KERNSRCDIR?= ${.CURDIR}/sys KRNLCONFDIR= ${KERNSRCDIR}/${TARGET}/conf KRNLOBJDIR= ${OBJTREE}${KERNSRCDIR} KERNCONFDIR?= ${KRNLCONFDIR} BUILDKERNELS= INSTALLKERNEL= .for _kernel in ${KERNCONF} .if exists(${KERNCONFDIR}/${_kernel}) BUILDKERNELS+= ${_kernel} .if empty(INSTALLKERNEL) INSTALLKERNEL= ${_kernel} .endif .endif .endfor buildkernel ${WMAKE_TGTS} ${.ALLTARGETS:M_*}: .MAKE # # buildkernel # # Builds all kernels defined by BUILDKERNELS. # buildkernel: .if empty(BUILDKERNELS) @echo "ERROR: Missing kernel configuration file(s) (${KERNCONF})."; \ false .endif @echo .for _kernel in ${BUILDKERNELS} @echo "--------------------------------------------------------------" @echo ">>> Kernel build for ${_kernel} started on `LC_ALL=C date`" @echo "--------------------------------------------------------------" @echo "===> ${_kernel}" mkdir -p ${KRNLOBJDIR} .if !defined(NO_KERNELCONFIG) @echo @echo "--------------------------------------------------------------" @echo ">>> stage 1: configuring the kernel" @echo "--------------------------------------------------------------" cd ${KRNLCONFDIR}; \ PATH=${TMPPATH} \ config ${CONFIGARGS} -d ${KRNLOBJDIR}/${_kernel} \ -I '${KERNCONFDIR}' '${KERNCONFDIR}/${_kernel}' .endif .if !defined(NO_CLEAN) && !defined(NO_KERNELCLEAN) @echo @echo "--------------------------------------------------------------" @echo ">>> stage 2.1: cleaning up the object tree" @echo "--------------------------------------------------------------" cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} ${CLEANDIR} .endif .if !defined(NO_KERNELOBJ) @echo @echo "--------------------------------------------------------------" @echo ">>> stage 2.2: rebuilding the object tree" @echo "--------------------------------------------------------------" cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} obj .endif @echo @echo "--------------------------------------------------------------" @echo ">>> stage 2.3: build tools" @echo "--------------------------------------------------------------" ${_+_}cd ${.CURDIR}; ${KTMAKE} kernel-tools .if !defined(NO_KERNELDEPEND) @echo @echo "--------------------------------------------------------------" @echo ">>> stage 3.1: making dependencies" @echo "--------------------------------------------------------------" cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} depend -DNO_MODULES_OBJ .endif @echo @echo "--------------------------------------------------------------" @echo ">>> stage 3.2: building everything" @echo "--------------------------------------------------------------" cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} all -DNO_MODULES_OBJ @echo "--------------------------------------------------------------" @echo ">>> Kernel build for ${_kernel} completed on `LC_ALL=C date`" @echo "--------------------------------------------------------------" .endfor # # installkernel, etc. # # Install the kernel defined by INSTALLKERNEL # installkernel installkernel.debug \ reinstallkernel reinstallkernel.debug: _installcheck_kernel .if empty(INSTALLKERNEL) @echo "ERROR: No kernel \"${KERNCONF}\" to install."; \ false .endif @echo "--------------------------------------------------------------" @echo ">>> Installing kernel ${INSTALLKERNEL}" @echo "--------------------------------------------------------------" cd ${KRNLOBJDIR}/${INSTALLKERNEL}; \ ${CROSSENV} PATH=${TMPPATH} \ ${MAKE} ${IMAKE_INSTALL} KERNEL=${INSTKERNNAME} ${.TARGET:S/kernel//} distributekernel distributekernel.debug: .if empty(INSTALLKERNEL) @echo "ERROR: No kernel \"${KERNCONF}\" to install."; \ false .endif mkdir -p ${DESTDIR}/${DISTDIR} .if defined(NO_ROOT) echo "#${MTREE_MAGIC}" > ${DESTDIR}/${DISTDIR}/kernel.premeta .endif cd ${KRNLOBJDIR}/${INSTALLKERNEL}; \ ${IMAKEENV} ${IMAKE_INSTALL:S/METALOG/kernel.premeta/} \ ${IMAKE_MTREE} PATH=${TMPPATH} ${MAKE} KERNEL=${INSTKERNNAME} \ DESTDIR=${INSTALL_DDIR}/kernel \ ${.TARGET:S/distributekernel/install/} .if defined(NO_ROOT) sed -e 's|^./kernel|.|' ${DESTDIR}/${DISTDIR}/kernel.premeta > \ ${DESTDIR}/${DISTDIR}/kernel.meta .endif .for _kernel in ${BUILDKERNELS:S/${INSTALLKERNEL}//} .if defined(NO_ROOT) echo "#${MTREE_MAGIC}" > ${DESTDIR}/${DISTDIR}/kernel.${_kernel}.premeta .endif cd ${KRNLOBJDIR}/${_kernel}; \ ${IMAKEENV} ${IMAKE_INSTALL:S/METALOG/kernel.${_kernel}.premeta/} \ ${IMAKE_MTREE} PATH=${TMPPATH} ${MAKE} \ KERNEL=${INSTKERNNAME}.${_kernel} \ DESTDIR=${INSTALL_DDIR}/kernel.${_kernel} \ ${.TARGET:S/distributekernel/install/} .if defined(NO_ROOT) sed -e 's|^./kernel|.|' \ ${DESTDIR}/${DISTDIR}/kernel.${_kernel}.premeta > \ ${DESTDIR}/${DISTDIR}/kernel.${_kernel}.meta .endif .endfor packagekernel: .if defined(NO_ROOT) cd ${DESTDIR}/${DISTDIR}/kernel; \ tar cvJf ${DESTDIR}/${DISTDIR}/kernel.txz \ @${DESTDIR}/${DISTDIR}/kernel.meta .for _kernel in ${BUILDKERNELS:S/${INSTALLKERNEL}//} cd ${DESTDIR}/${DISTDIR}/kernel.${_kernel}; \ tar cvJf ${DESTDIR}/${DISTDIR}/kernel.${_kernel}.txz \ @${DESTDIR}/${DISTDIR}/kernel.${_kernel}.meta .endfor .else cd ${DESTDIR}/${DISTDIR}/kernel; \ tar cvJf ${DESTDIR}/${DISTDIR}/kernel.txz . .for _kernel in ${BUILDKERNELS:S/${INSTALLKERNEL}//} cd ${DESTDIR}/${DISTDIR}/kernel.${_kernel}; \ tar cvJf ${DESTDIR}/${DISTDIR}/kernel.${_kernel}.txz . .endfor .endif # # doxygen # # Build the API documentation with doxygen # doxygen: @if [ ! -x `/usr/bin/which doxygen` ]; then \ echo "You need doxygen (devel/doxygen) to generate the API documentation of the kernel." | /usr/bin/fmt; \ exit 1; \ fi cd ${.CURDIR}/tools/kerneldoc/subsys && ${MAKE} obj all # # update # # Update the source tree(s), by running svn/svnup to update to the # latest copy. # update: .if (defined(CVS_UPDATE) || defined(SUP_UPDATE)) && !defined(SVN_UPDATE) @echo "--------------------------------------------------------------" @echo "CVS_UPDATE and SUP_UPDATE are no longer supported." @echo "Please see: https://wiki.freebsd.org/CvsIsDeprecated" @echo "--------------------------------------------------------------" @exit 1 .endif .if defined(SVN_UPDATE) @echo "--------------------------------------------------------------" @echo ">>> Updating ${.CURDIR} using Subversion" @echo "--------------------------------------------------------------" @(cd ${.CURDIR} && ${SVN} update ${SVNFLAGS}) .endif # # ------------------------------------------------------------------------ # # From here onwards are utility targets used by the 'make world' and # related targets. If your 'world' breaks, you may like to try to fix # the problem and manually run the following targets to attempt to # complete the build. Beware, this is *not* guaranteed to work, you # need to have a pretty good grip on the current state of the system # to attempt to manually finish it. If in doubt, 'make world' again. # # # legacy: Build compatibility shims for the next three targets # legacy: .if ${BOOTSTRAPPING} < 800107 && ${BOOTSTRAPPING} != 0 @echo "ERROR: Source upgrades from versions prior to 8.0 not supported."; \ false .endif .for _tool in tools/build ${_+_}@${ECHODIR} "===> ${_tool} (obj,includes,depend,all,install)"; \ cd ${.CURDIR}/${_tool} && \ ${MAKE} DIRPRFX=${_tool}/ obj && \ ${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX}/legacy includes && \ ${MAKE} DIRPRFX=${_tool}/ depend && \ ${MAKE} DIRPRFX=${_tool}/ all && \ ${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX}/legacy install .endfor # # bootstrap-tools: Build tools needed for compatibility # .if ${MK_GAMES} != "no" _strfile= games/fortune/strfile .endif .if ${MK_CXX} != "no" _gperf= gnu/usr.bin/gperf .endif .if ${MK_GROFF} != "no" _groff= gnu/usr.bin/groff .endif .if ${MK_VT} != "no" _vtfontcvt= usr.bin/vtfontcvt .endif .if ${BOOTSTRAPPING} < 900002 _sed= usr.bin/sed .endif .if ${BOOTSTRAPPING} < 1000002 _m4= lib/libohash \ usr.bin/m4 .endif .if ${BOOTSTRAPPING} < 1000013 _yacc= lib/liby \ usr.bin/yacc .endif .if ${BOOTSTRAPPING} < 1000014 _crunch= usr.sbin/crunch .endif .if ${BOOTSTRAPPING} < 1000026 _nmtree= lib/libnetbsd \ usr.sbin/nmtree .endif .if ${BOOTSTRAPPING} < 1000027 _cat= bin/cat .endif .if ${BOOTSTRAPPING} < 1000033 _lex= usr.bin/lex .endif .if ${BOOTSTRAPPING} >= 900040 && ${BOOTSTRAPPING} < 900041 _awk= usr.bin/awk .endif .if ${MK_BSNMP} != "no" _gensnmptree= usr.sbin/bsnmpd/gensnmptree .endif # We need to build tblgen when we're building clang either as # the bootstrap compiler, or as the part of the normal build. .if ${MK_CLANG_BOOTSTRAP} != "no" || ${MK_CLANG} != "no" _clang_tblgen= \ lib/clang/libllvmsupport \ lib/clang/libllvmtablegen \ usr.bin/clang/tblgen \ usr.bin/clang/clang-tblgen .endif # dtrace tools are required for older bootstrap env and cross-build # pre libdwarf .if ${MK_CDDL} != "no" && (${BOOTSTRAPPING} < 1100006 \ || (${MACHINE} != ${TARGET} || ${MACHINE_ARCH} != ${TARGET_ARCH})) _dtrace_tools= cddl/usr.bin/sgsmsg cddl/lib/libctf lib/libelf \ lib/libdwarf cddl/usr.bin/ctfconvert cddl/usr.bin/ctfmerge .endif # Default to building the GPL DTC, but build the BSDL one if users explicitly # request it. _dtc= usr.bin/dtc .if ${MK_GPL_DTC} != "no" _dtc= gnu/usr.bin/dtc .endif .if ${MK_KERBEROS} != "no" _kerberos5_bootstrap_tools= \ kerberos5/tools/make-roken \ kerberos5/lib/libroken \ kerberos5/lib/libvers \ kerberos5/tools/asn1_compile \ kerberos5/tools/slc \ usr.bin/compile_et .endif # Please document (add comment) why something is in 'bootstrap-tools'. # Try to bound the building of the bootstrap-tool to just the # FreeBSD versions that need the tool built at this stage of the build. bootstrap-tools: .MAKE .for _tool in \ ${_clang_tblgen} \ ${_kerberos5_bootstrap_tools} \ ${_dtrace_tools} \ ${_strfile} \ ${_gperf} \ ${_groff} \ ${_dtc} \ ${_awk} \ ${_cat} \ usr.bin/lorder \ usr.bin/makewhatis \ usr.bin/rpcgen \ ${_sed} \ ${_yacc} \ ${_m4} \ ${_lex} \ lib/libmd \ usr.bin/xinstall \ ${_gensnmptree} \ usr.sbin/config \ ${_crunch} \ ${_nmtree} \ ${_vtfontcvt} ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_tool} && \ ${MAKE} DIRPRFX=${_tool}/ obj && \ ${MAKE} DIRPRFX=${_tool}/ depend && \ ${MAKE} DIRPRFX=${_tool}/ all && \ ${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX}/legacy install .endfor # # build-tools: Build special purpose build tools # .if !defined(NO_SHARE) _share= share/syscons/scrnmaps .endif .if ${MK_GCC} != "no" _gcc_tools= gnu/usr.bin/cc/cc_tools .endif +.if ${MK_INFO} != "no" +_texinfo= gnu/usr.bin/texinfo/libtxi \ + gnu/usr.bin/texinfo/makeinfo +.endif + .if ${MK_RESCUE} != "no" _rescue= rescue/rescue .endif build-tools: .MAKE .for _tool in \ bin/csh \ bin/sh \ ${_rescue} \ ${LOCAL_TOOL_DIRS} \ lib/ncurses/ncurses \ lib/ncurses/ncursesw \ ${_share} \ usr.bin/awk \ lib/libmagic \ usr.bin/mkesdb_static \ usr.bin/mkcsmapper_static \ usr.bin/vi/catalog ${_+_}@${ECHODIR} "===> ${_tool} (obj,build-tools)"; \ cd ${.CURDIR}/${_tool} && \ ${MAKE} DIRPRFX=${_tool}/ obj && \ ${MAKE} DIRPRFX=${_tool}/ build-tools .endfor .for _tool in \ ${_gcc_tools} ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all)"; \ cd ${.CURDIR}/${_tool} && \ ${MAKE} DIRPRFX=${_tool}/ obj && \ ${MAKE} DIRPRFX=${_tool}/ depend && \ ${MAKE} DIRPRFX=${_tool}/ all .endfor +.for _tool in \ + ${_texinfo} + ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \ + cd ${.CURDIR}/${_tool} && \ + ${MAKE} DIRPRFX=${_tool}/ obj && \ + ${MAKE} DIRPRFX=${_tool}/ depend && \ + ${MAKE} DIRPRFX=${_tool}/ all && \ + ${MAKE} DIRPRFX=${_tool}/ install DESTDIR=${WORLDTMP} +.endfor + # # kernel-tools: Build kernel-building tools # kernel-tools: .MAKE mkdir -p ${MAKEOBJDIRPREFIX}/usr mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${MAKEOBJDIRPREFIX}/usr >/dev/null # # cross-tools: Build cross-building tools # .if ${TARGET_ARCH} != ${MACHINE_ARCH} .if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "i386" _btxld= usr.sbin/btxld .endif .endif .if ${TARGET_ARCH} != ${MACHINE_ARCH} .if ${MK_RESCUE} != "no" || defined(RELEASEDIR) _crunchide= usr.sbin/crunch/crunchide .endif .if ${TARGET_ARCH} == "i386" && defined(RELEASEDIR) _kgzip= usr.sbin/kgzip .endif .endif # If we're given an XAS, don't build binutils. .if ${XAS:M/*} == "" && ${MK_BINUTILS_BOOTSTRAP} != "no" _binutils= gnu/usr.bin/binutils .if ${MK_ELFTOOLCHAIN_TOOLS} != "no" _elftctools= lib/libelftc \ usr.bin/addr2line \ usr.bin/elfcopy \ usr.bin/nm \ usr.bin/size \ usr.bin/strings .endif .endif # If an full path to an external cross compiler is given, don't build # a cross compiler. .if ${XCC:M/*} == "" && ${MK_CROSS_COMPILER} != "no" .if ${MK_CLANG_BOOTSTRAP} != "no" _clang= usr.bin/clang _clang_libs= lib/clang .endif .if ${MK_GCC_BOOTSTRAP} != "no" _cc= gnu/usr.bin/cc .endif .endif cross-tools: .MAKE .for _tool in \ ${_clang_libs} \ ${_clang} \ ${_binutils} \ ${_elftctools} \ ${_cc} \ usr.bin/xlint/lint1 usr.bin/xlint/lint2 usr.bin/xlint/xlint \ ${_btxld} \ ${_crunchide} \ ${_kgzip} \ sys/boot/usb/tools ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_tool} && \ ${MAKE} DIRPRFX=${_tool}/ obj && \ ${MAKE} DIRPRFX=${_tool}/ depend && \ ${MAKE} DIRPRFX=${_tool}/ all && \ ${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX} install .endfor NXBENV= MAKEOBJDIRPREFIX=${OBJTREE}/nxb \ INSTALL="sh ${.CURDIR}/tools/install.sh" \ VERSION="${VERSION}" NXBMAKE= ${NXBENV} ${MAKE} \ TBLGEN=${OBJTREE}/nxb-bin/usr/bin/tblgen \ CLANG_TBLGEN=${OBJTREE}/nxb-bin/usr/bin/clang-tblgen \ MACHINE=${TARGET} MACHINE_ARCH=${TARGET_ARCH} \ MK_GDB=no MK_TESTS=no \ SSP_CFLAGS= \ MK_HTML=no MK_INFO=no NO_LINT=yes MK_MAN=no \ -DNO_PIC MK_PROFILE=no -DNO_SHARED \ -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \ MK_CLANG_EXTRAS=no MK_CLANG_FULL=no \ MK_LLDB=no native-xtools: .MAKE mkdir -p ${OBJTREE}/nxb-bin/bin mkdir -p ${OBJTREE}/nxb-bin/sbin mkdir -p ${OBJTREE}/nxb-bin/usr mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${OBJTREE}/nxb-bin/usr >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \ -p ${OBJTREE}/nxb-bin/usr/include >/dev/null .for _tool in \ bin/cat \ bin/chmod \ bin/cp \ bin/csh \ bin/echo \ bin/expr \ bin/hostname \ bin/ln \ bin/ls \ bin/mkdir \ bin/mv \ bin/ps \ bin/realpath \ bin/rm \ bin/rmdir \ bin/sh \ bin/sleep \ ${_clang_tblgen} \ usr.bin/ar \ ${_binutils} \ ${_elftctools} \ ${_cc} \ ${_gcc_tools} \ ${_clang_libs} \ ${_clang} \ sbin/md5 \ sbin/sysctl \ gnu/usr.bin/diff \ usr.bin/awk \ usr.bin/basename \ usr.bin/bmake \ usr.bin/bzip2 \ usr.bin/cmp \ usr.bin/dirname \ usr.bin/env \ usr.bin/fetch \ usr.bin/find \ usr.bin/grep \ usr.bin/gzip \ usr.bin/id \ usr.bin/lex \ usr.bin/lorder \ usr.bin/mktemp \ usr.bin/mt \ usr.bin/patch \ usr.bin/sed \ usr.bin/sort \ usr.bin/tar \ usr.bin/touch \ usr.bin/tr \ usr.bin/true \ usr.bin/uniq \ usr.bin/unzip \ usr.bin/xargs \ usr.bin/xinstall \ usr.bin/xz \ usr.bin/yacc \ usr.sbin/chown ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_tool} && \ ${NXBMAKE} DIRPRFX=${_tool}/ obj && \ ${NXBMAKE} DIRPRFX=${_tool}/ depend && \ ${NXBMAKE} DIRPRFX=${_tool}/ all && \ ${NXBMAKE} DIRPRFX=${_tool}/ DESTDIR=${OBJTREE}/nxb-bin install .endfor # # hierarchy - ensure that all the needed directories are present # hierarchy hier: .MAKE cd ${.CURDIR}/etc && ${HMAKE} distrib-dirs # # libraries - build all libraries, and install them under ${DESTDIR}. # # The list of libraries with dependents (${_prebuild_libs}) and their # interdependencies (__L) are built automatically by the # ${.CURDIR}/tools/make_libdeps.sh script. # libraries: .MAKE cd ${.CURDIR} && \ ${MAKE} -f Makefile.inc1 _prereq_libs && \ ${MAKE} -f Makefile.inc1 _startup_libs && \ ${MAKE} -f Makefile.inc1 _prebuild_libs && \ ${MAKE} -f Makefile.inc1 _generic_libs # # static libgcc.a prerequisite for shared libc # _prereq_libs= gnu/lib/libssp/libssp_nonshared gnu/lib/libgcc lib/libcompiler_rt # These dependencies are not automatically generated: # # gnu/lib/csu, gnu/lib/libgcc, lib/csu and lib/libc must be built before # all shared libraries for ELF. # _startup_libs= gnu/lib/csu .if exists(${.CURDIR}/lib/csu/${MACHINE_ARCH}-elf) _startup_libs+= lib/csu/${MACHINE_ARCH}-elf .elif exists(${.CURDIR}/lib/csu/${MACHINE_ARCH}) _startup_libs+= lib/csu/${MACHINE_ARCH} .else _startup_libs+= lib/csu/${MACHINE_CPUARCH} .endif _startup_libs+= gnu/lib/libgcc _startup_libs+= lib/libcompiler_rt _startup_libs+= lib/libc _startup_libs+= lib/libc_nonshared .if ${MK_LIBCPLUSPLUS} != "no" _startup_libs+= lib/libcxxrt .endif gnu/lib/libgcc__L: lib/libc__L gnu/lib/libgcc__L: lib/libc_nonshared__L .if ${MK_LIBCPLUSPLUS} != "no" lib/libcxxrt__L: gnu/lib/libgcc__L .endif _prebuild_libs= ${_kerberos5_lib_libasn1} \ ${_kerberos5_lib_libhdb} \ ${_kerberos5_lib_libheimbase} \ ${_kerberos5_lib_libheimntlm} \ ${_kerberos5_lib_libheimsqlite} \ ${_kerberos5_lib_libheimipcc} \ ${_kerberos5_lib_libhx509} ${_kerberos5_lib_libkrb5} \ ${_kerberos5_lib_libroken} \ ${_kerberos5_lib_libwind} \ lib/libbz2 ${_libcom_err} lib/libcrypt \ lib/libelf lib/libexpat \ lib/libfigpar \ ${_lib_libgssapi} \ lib/libkiconv lib/libkvm lib/liblzma lib/libmd lib/libnv \ ${_lib_libcapsicum} \ lib/ncurses/ncurses lib/ncurses/ncursesw \ lib/libopie lib/libpam ${_lib_libthr} \ lib/libradius lib/libsbuf lib/libtacplus \ lib/libgeom \ ${_cddl_lib_libumem} ${_cddl_lib_libnvpair} \ ${_cddl_lib_libuutil} \ ${_cddl_lib_libavl} \ ${_cddl_lib_libzfs_core} \ ${_cddl_lib_libctf} \ lib/libutil lib/libpjdlog ${_lib_libypclnt} lib/libz lib/msun \ ${_secure_lib_libcrypto} ${_lib_libldns} \ ${_secure_lib_libssh} ${_secure_lib_libssl} \ gnu/lib/libdialog .if ${MK_GNUCXX} != "no" _prebuild_libs+= gnu/lib/libstdc++ gnu/lib/libsupc++ gnu/lib/libstdc++__L: lib/msun__L gnu/lib/libsupc++__L: gnu/lib/libstdc++__L .endif lib/libgeom__L: lib/libexpat__L .if ${MK_LIBTHR} != "no" _lib_libthr= lib/libthr .endif .if ${MK_OFED} != "no" _ofed_lib= contrib/ofed/usr.lib/ .endif .if ${MK_CASPER} != "no" _lib_libcapsicum=lib/libcapsicum .endif lib/libcapsicum__L: lib/libnv__L lib/libpjdlog__L: lib/libutil__L _generic_libs= ${_cddl_lib} gnu/lib ${_kerberos5_lib} lib ${_secure_lib} usr.bin/lex/lib ${_ofed_lib} .for _DIR in ${LOCAL_LIB_DIRS} .if exists(${.CURDIR}/${_DIR}/Makefile) _generic_libs+= ${_DIR} .endif .endfor lib/libopie__L lib/libtacplus__L: lib/libmd__L .if ${MK_CDDL} != "no" _cddl_lib_libumem= cddl/lib/libumem _cddl_lib_libnvpair= cddl/lib/libnvpair _cddl_lib_libavl= cddl/lib/libavl _cddl_lib_libuutil= cddl/lib/libuutil _cddl_lib_libzfs_core= cddl/lib/libzfs_core _cddl_lib_libctf= cddl/lib/libctf _cddl_lib= cddl/lib cddl/lib/libzfs_core__L: cddl/lib/libnvpair__L cddl/lib/libzfs__L: lib/libgeom__L cddl/lib/libctf__L: lib/libz__L .endif .if ${MK_CRYPT} != "no" .if ${MK_OPENSSL} != "no" _secure_lib_libcrypto= secure/lib/libcrypto _secure_lib_libssl= secure/lib/libssl lib/libradius__L secure/lib/libssl__L: secure/lib/libcrypto__L .if ${MK_LDNS} != "no" _lib_libldns= lib/libldns lib/libldns__L: secure/lib/libcrypto__L .endif .if ${MK_OPENSSH} != "no" _secure_lib_libssh= secure/lib/libssh secure/lib/libssh__L: lib/libz__L secure/lib/libcrypto__L lib/libcrypt__L .if ${MK_LDNS} != "no" secure/lib/libssh__L: lib/libldns__L .endif .if ${MK_KERBEROS_SUPPORT} != "no" secure/lib/libssh__L: lib/libgssapi__L kerberos5/lib/libkrb5__L \ kerberos5/lib/libhx509__L kerberos5/lib/libasn1__L lib/libcom_err__L \ lib/libmd__L kerberos5/lib/libroken__L .endif .endif .endif _secure_lib= secure/lib .endif .if ${MK_KERBEROS} != "no" kerberos5/lib/libasn1__L: lib/libcom_err__L kerberos5/lib/libroken__L kerberos5/lib/libhdb__L: kerberos5/lib/libasn1__L lib/libcom_err__L \ kerberos5/lib/libkrb5__L kerberos5/lib/libroken__L \ kerberos5/lib/libwind__L kerberos5/lib/libheimsqlite__L kerberos5/lib/libheimntlm__L: secure/lib/libcrypto__L kerberos5/lib/libkrb5__L \ kerberos5/lib/libroken__L lib/libcom_err__L kerberos5/lib/libhx509__L: kerberos5/lib/libasn1__L lib/libcom_err__L \ secure/lib/libcrypto__L kerberos5/lib/libroken__L kerberos5/lib/libwind__L kerberos5/lib/libkrb5__L: kerberos5/lib/libasn1__L lib/libcom_err__L \ lib/libcrypt__L secure/lib/libcrypto__L kerberos5/lib/libhx509__L \ kerberos5/lib/libroken__L kerberos5/lib/libwind__L \ kerberos5/lib/libheimbase__L kerberos5/lib/libheimipcc__L kerberos5/lib/libroken__L: lib/libcrypt__L kerberos5/lib/libwind__L: kerberos5/lib/libroken__L lib/libcom_err__L kerberos5/lib/libheimbase__L: lib/libthr__L kerberos5/lib/libheimipcc__L: kerberos5/lib/libroken__L kerberos5/lib/libheimbase__L lib/libthr__L kerberos5/lib/libheimsqlite__L: lib/libthr__L .endif .if ${MK_GSSAPI} != "no" _lib_libgssapi= lib/libgssapi .endif .if ${MK_KERBEROS} != "no" _kerberos5_lib= kerberos5/lib _kerberos5_lib_libasn1= kerberos5/lib/libasn1 _kerberos5_lib_libhdb= kerberos5/lib/libhdb _kerberos5_lib_libheimbase= kerberos5/lib/libheimbase _kerberos5_lib_libkrb5= kerberos5/lib/libkrb5 _kerberos5_lib_libhx509= kerberos5/lib/libhx509 _kerberos5_lib_libroken= kerberos5/lib/libroken _kerberos5_lib_libheimntlm= kerberos5/lib/libheimntlm _kerberos5_lib_libheimsqlite= kerberos5/lib/libheimsqlite _kerberos5_lib_libheimipcc= kerberos5/lib/libheimipcc _kerberos5_lib_libwind= kerberos5/lib/libwind _libcom_err= lib/libcom_err .endif .if ${MK_NIS} != "no" _lib_libypclnt= lib/libypclnt .endif .if ${MK_OPENSSL} == "no" lib/libradius__L: lib/libmd__L .endif gnu/lib/libdialog__L: lib/msun__L lib/ncurses/ncursesw__L .for _lib in ${_prereq_libs} ${_lib}__PL: .PHONY .MAKE .if exists(${.CURDIR}/${_lib}) ${_+_}@${ECHODIR} "===> ${_lib} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_lib} && \ ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj && \ ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ depend && \ ${MAKE} MK_TESTS=no MK_PROFILE=no -DNO_PIC \ DIRPRFX=${_lib}/ all && \ ${MAKE} MK_TESTS=no MK_PROFILE=no -DNO_PIC \ DIRPRFX=${_lib}/ install .endif .endfor .for _lib in ${_startup_libs} ${_prebuild_libs:Nlib/libpam} ${_generic_libs} ${_lib}__L: .PHONY .MAKE .if exists(${.CURDIR}/${_lib}) ${_+_}@${ECHODIR} "===> ${_lib} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_lib} && \ ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj && \ ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ depend && \ ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ all && \ ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ install .endif .endfor # libpam is special: we need to build static PAM modules before # static PAM library, and dynamic PAM library before dynamic PAM # modules. lib/libpam__L: .PHONY .MAKE ${_+_}@${ECHODIR} "===> lib/libpam (obj,depend,all,install)"; \ cd ${.CURDIR}/lib/libpam && \ ${MAKE} MK_TESTS=no DIRPRFX=lib/libpam/ obj && \ ${MAKE} MK_TESTS=no DIRPRFX=lib/libpam/ depend && \ ${MAKE} MK_TESTS=no DIRPRFX=lib/libpam/ \ -D_NO_LIBPAM_SO_YET all && \ ${MAKE} MK_TESTS=no DIRPRFX=lib/libpam/ \ -D_NO_LIBPAM_SO_YET install _prereq_libs: ${_prereq_libs:S/$/__PL/} _startup_libs: ${_startup_libs:S/$/__L/} _prebuild_libs: ${_prebuild_libs:S/$/__L/} _generic_libs: ${_generic_libs:S/$/__L/} .for __target in all clean cleandepend cleandir depend includes obj .for entry in ${SUBDIR} ${entry}.${__target}__D: .PHONY .MAKE ${_+_}@set -e; if test -d ${.CURDIR}/${entry}.${MACHINE_ARCH}; then \ ${ECHODIR} "===> ${DIRPRFX}${entry}.${MACHINE_ARCH} (${__target})"; \ edir=${entry}.${MACHINE_ARCH}; \ cd ${.CURDIR}/$${edir}; \ else \ ${ECHODIR} "===> ${DIRPRFX}${entry} (${__target})"; \ edir=${entry}; \ cd ${.CURDIR}/$${edir}; \ fi; \ ${MAKE} ${__target} DIRPRFX=${DIRPRFX}$${edir}/ .endfor par-${__target}: ${SUBDIR:S/$/.${__target}__D/} .endfor .include .if make(check-old) || make(check-old-dirs) || \ make(check-old-files) || make(check-old-libs) || \ make(delete-old) || make(delete-old-dirs) || \ make(delete-old-files) || make(delete-old-libs) # # check for / delete old files section # .include "ObsoleteFiles.inc" OLD_LIBS_MESSAGE="Please be sure no application still uses those libraries, \ else you can not start such an application. Consult UPDATING for more \ information regarding how to cope with the removal/revision bump of a \ specific library." .if !defined(BATCH_DELETE_OLD_FILES) RM_I=-i .else RM_I=-v .endif delete-old-files: @echo ">>> Removing old files (only deletes safe to delete libs)" # Ask for every old file if the user really wants to remove it. # It's annoying, but better safe than sorry. # NB: We cannot pass the list of OLD_FILES as a parameter because the # argument list will get too long. Using .for/.endfor make "loops" will make # the Makefile parser segfault. @exec 3<&0; \ cd ${.CURDIR}; \ ${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \ -V OLD_FILES -V "OLD_FILES:Musr/share/*.gz:R" | xargs -n1 | \ while read file; do \ if [ -f "${DESTDIR}/$${file}" -o -L "${DESTDIR}/$${file}" ]; then \ chflags noschg "${DESTDIR}/$${file}" 2>/dev/null || true; \ rm ${RM_I} "${DESTDIR}/$${file}" <&3; \ fi; \ done # Remove catpages without corresponding manpages. @exec 3<&0; \ find ${DESTDIR}/usr/share/man/cat* ! -type d | \ sed -ep -e's:${DESTDIR}/usr/share/man/cat:${DESTDIR}/usr/share/man/man:' | \ while read catpage; do \ read manpage; \ if [ ! -e "$${manpage}" ]; then \ rm ${RM_I} $${catpage} <&3; \ fi; \ done @echo ">>> Old files removed" check-old-files: @echo ">>> Checking for old files" @cd ${.CURDIR}; \ ${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \ -V OLD_FILES -V "OLD_FILES:Musr/share/*.gz:R" | xargs -n1 | \ while read file; do \ if [ -f "${DESTDIR}/$${file}" -o -L "${DESTDIR}/$${file}" ]; then \ echo "${DESTDIR}/$${file}"; \ fi; \ done # Check for catpages without corresponding manpages. @find ${DESTDIR}/usr/share/man/cat* ! -type d | \ sed -ep -e's:${DESTDIR}/usr/share/man/cat:${DESTDIR}/usr/share/man/man:' | \ while read catpage; do \ read manpage; \ if [ ! -e "$${manpage}" ]; then \ echo $${catpage}; \ fi; \ done delete-old-libs: @echo ">>> Removing old libraries" @echo "${OLD_LIBS_MESSAGE}" | fmt @exec 3<&0; \ cd ${.CURDIR}; \ ${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \ -V OLD_LIBS | xargs -n1 | \ while read file; do \ if [ -f "${DESTDIR}/$${file}" -o -L "${DESTDIR}/$${file}" ]; then \ chflags noschg "${DESTDIR}/$${file}" 2>/dev/null || true; \ rm ${RM_I} "${DESTDIR}/$${file}" <&3; \ fi; \ for ext in debug symbols; do \ if ! [ -e "${DESTDIR}/$${file}" ] && [ -f \ "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}" ]; then \ rm ${RM_I} "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}" \ <&3; \ fi; \ done; \ done @echo ">>> Old libraries removed" check-old-libs: @echo ">>> Checking for old libraries" @cd ${.CURDIR}; \ ${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \ -V OLD_LIBS | xargs -n1 | \ while read file; do \ if [ -f "${DESTDIR}/$${file}" -o -L "${DESTDIR}/$${file}" ]; then \ echo "${DESTDIR}/$${file}"; \ fi; \ for ext in debug symbols; do \ if [ -f "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}" ]; then \ echo "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}"; \ fi; \ done; \ done delete-old-dirs: @echo ">>> Removing old directories" @cd ${.CURDIR}; \ ${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \ -V OLD_DIRS | xargs -n1 | sort -r | \ while read dir; do \ if [ -d "${DESTDIR}/$${dir}" ]; then \ rmdir -v "${DESTDIR}/$${dir}" || true; \ elif [ -L "${DESTDIR}/$${dir}" ]; then \ echo "${DESTDIR}/$${dir} is a link, please remove everything manually."; \ fi; \ done @echo ">>> Old directories removed" check-old-dirs: @echo ">>> Checking for old directories" @cd ${.CURDIR}; \ ${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \ -V OLD_DIRS | xargs -n1 | \ while read dir; do \ if [ -d "${DESTDIR}/$${dir}" ]; then \ echo "${DESTDIR}/$${dir}"; \ elif [ -L "${DESTDIR}/$${dir}" ]; then \ echo "${DESTDIR}/$${dir} is a link, please remove everything manually."; \ fi; \ done delete-old: delete-old-files delete-old-dirs @echo "To remove old libraries run '${MAKE} delete-old-libs'." check-old: check-old-files check-old-libs check-old-dirs @echo "To remove old files and directories run '${MAKE} delete-old'." @echo "To remove old libraries run '${MAKE} delete-old-libs'." .endif # # showconfig - show build configuration. # showconfig: @(${MAKE} -n -f ${.CURDIR}/sys/conf/kern.opts.mk -V dummy -dg1; \ ${MAKE} -n -f ${.CURDIR}/share/mk/src.opts.mk -V dummy -dg1) 2>&1 | grep ^MK_ | sort -u .if !empty(KRNLOBJDIR) && !empty(KERNCONF) DTBOUTPUTPATH= ${KRNLOBJDIR}/${KERNCONF}/ .if !defined(FDT_DTS_FILE) || empty(FDT_DTS_FILE) .if exists(${KERNCONFDIR}/${KERNCONF}) FDT_DTS_FILE!= awk 'BEGIN {FS="="} /^makeoptions[[:space:]]+FDT_DTS_FILE/ {print $$2}' \ '${KERNCONFDIR}/${KERNCONF}' ; echo .endif .endif .endif .if !defined(DTBOUTPUTPATH) || !exists(${DTBOUTPUTPATH}) DTBOUTPUTPATH= ${.CURDIR} .endif # # Build 'standalone' Device Tree Blob # builddtb: @PATH=${TMPPATH} MACHINE=${TARGET} \ ${.CURDIR}/sys/tools/fdt/make_dtb.sh ${.CURDIR}/sys \ "${FDT_DTS_FILE}" ${DTBOUTPUTPATH} ############### .if defined(TARGET) && defined(TARGET_ARCH) .if ${TARGET} == ${MACHINE} && ${TARGET_ARCH} == ${MACHINE_ARCH} XDEV_CPUTYPE?=${CPUTYPE} .else XDEV_CPUTYPE?=${TARGET_CPUTYPE} .endif NOFUN=-DNO_FSCHG MK_HTML=no MK_INFO=no -DNO_LINT \ MK_MAN=no MK_NLS=no MK_PROFILE=no \ MK_KERBEROS=no MK_RESCUE=no MK_TESTS=no MK_WARNS=no \ TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ CPUTYPE=${XDEV_CPUTYPE} XDDIR=${TARGET_ARCH}-freebsd XDTP?=/usr/${XDDIR} .if ${XDTP:N/*} .error XDTP variable should be an absolute path .endif CDBENV=MAKEOBJDIRPREFIX=${MAKEOBJDIRPREFIX}/${XDDIR} \ INSTALL="sh ${.CURDIR}/tools/install.sh" CDENV= ${CDBENV} \ _SHLIBDIRPREFIX=${XDDESTDIR} \ TOOLS_PREFIX=${XDTP} CD2CFLAGS=-isystem ${XDDESTDIR}/usr/include -L${XDDESTDIR}/usr/lib \ --sysroot=${XDDESTDIR}/ -B${XDDESTDIR}/usr/libexec \ -B${XDDESTDIR}/usr/bin -B${XDDESTDIR}/usr/lib CD2ENV=${CDENV} CC="${CC} ${CD2CFLAGS}" CXX="${CXX} ${CD2CFLAGS}" \ CPP="${CPP} ${CD2CFLAGS}" \ MACHINE=${TARGET} MACHINE_ARCH=${TARGET_ARCH} CDTMP= ${MAKEOBJDIRPREFIX}/${XDDIR}/${.CURDIR}/tmp CDMAKE=${CDENV} PATH=${CDTMP}/usr/bin:${PATH} ${MAKE} ${NOFUN} CD2MAKE=${CD2ENV} PATH=${CDTMP}/usr/bin:${XDDESTDIR}/usr/bin:${PATH} ${MAKE} ${NOFUN} XDDESTDIR=${DESTDIR}/${XDTP} .if !defined(OSREL) OSREL!= uname -r | sed -e 's/[-(].*//' .endif .ORDER: xdev-build xdev-install xdev-links xdev: xdev-build xdev-install .ORDER: _xb-worldtmp _xb-bootstrap-tools _xb-build-tools _xb-cross-tools xdev-build: _xb-worldtmp _xb-bootstrap-tools _xb-build-tools _xb-cross-tools _xb-worldtmp: mkdir -p ${CDTMP}/usr mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${CDTMP}/usr >/dev/null _xb-bootstrap-tools: .for _tool in \ ${_clang_tblgen} \ ${_gperf} ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_tool} && \ ${CDMAKE} DIRPRFX=${_tool}/ obj && \ ${CDMAKE} DIRPRFX=${_tool}/ depend && \ ${CDMAKE} DIRPRFX=${_tool}/ all && \ ${CDMAKE} DIRPRFX=${_tool}/ DESTDIR=${CDTMP} install .endfor _xb-build-tools: ${_+_}@cd ${.CURDIR}; \ ${CDBENV} ${MAKE} -f Makefile.inc1 ${NOFUN} build-tools _xb-cross-tools: .for _tool in \ ${_binutils} \ ${_elftctools} \ usr.bin/ar \ ${_clang_libs} \ ${_clang} \ ${_cc} ${_+_}@${ECHODIR} "===> xdev ${_tool} (obj,depend,all)"; \ cd ${.CURDIR}/${_tool} && \ ${CDMAKE} DIRPRFX=${_tool}/ obj && \ ${CDMAKE} DIRPRFX=${_tool}/ depend && \ ${CDMAKE} DIRPRFX=${_tool}/ all .endfor _xi-mtree: ${_+_}@${ECHODIR} "mtree populating ${XDDESTDIR}" mkdir -p ${XDDESTDIR} mtree -deU -f ${.CURDIR}/etc/mtree/BSD.root.dist \ -p ${XDDESTDIR} >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ -p ${XDDESTDIR}/usr >/dev/null mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \ -p ${XDDESTDIR}/usr/include >/dev/null .if ${MK_TESTS} != "no" mkdir -p ${XDDESTDIR}${TESTSBASE} mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \ -p ${XDDESTDIR}${TESTSBASE} >/dev/null .endif .ORDER: xdev-build _xi-mtree _xi-cross-tools _xi-includes _xi-libraries xdev-install: xdev-build _xi-mtree _xi-cross-tools _xi-includes _xi-libraries _xi-cross-tools: @echo "_xi-cross-tools" .for _tool in \ ${_binutils} \ ${_elftctools} \ usr.bin/ar \ ${_clang_libs} \ ${_clang} \ ${_cc} ${_+_}@${ECHODIR} "===> xdev ${_tool} (install)"; \ cd ${.CURDIR}/${_tool}; \ ${CDMAKE} DIRPRFX=${_tool}/ install DESTDIR=${XDDESTDIR} .endfor _xi-includes: ${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 par-includes \ DESTDIR=${XDDESTDIR} _xi-libraries: ${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 libraries \ DESTDIR=${XDDESTDIR} xdev-links: ${_+_}cd ${XDDESTDIR}/usr/bin; \ mkdir -p ../../../../usr/bin; \ for i in *; do \ ln -sf ../../${XDTP}/usr/bin/$$i \ ../../../../usr/bin/${XDDIR}-$$i; \ ln -sf ../../${XDTP}/usr/bin/$$i \ ../../../../usr/bin/${XDDIR}${OSREL}-$$i; \ done .else xdev xdev-build xdev-install xdev-links: @echo "*** Error: Both TARGET and TARGET_ARCH must be defined for \"${.TARGET}\" target" .endif Index: projects/sendfile/bin/sh/error.c =================================================================== --- projects/sendfile/bin/sh/error.c (revision 276056) +++ projects/sendfile/bin/sh/error.c (revision 276057) @@ -1,207 +1,199 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * 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. */ #ifndef lint #if 0 static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); /* * Errors and exceptions. */ #include "shell.h" #include "main.h" #include "options.h" #include "output.h" #include "error.h" #include "nodes.h" /* show.h needs nodes.h */ #include "show.h" #include "trap.h" #include #include #include #include /* * Code to handle exceptions in C. */ struct jmploc *handler; volatile sig_atomic_t exception; volatile sig_atomic_t suppressint; volatile sig_atomic_t intpending; char *commandname; static void exverror(int, const char *, va_list) __printf0like(2, 0) __dead2; /* * Called to raise an exception. Since C doesn't include exceptions, we * just do a longjmp to the exception handler. The type of exception is * stored in the global variable "exception". * * Interrupts are disabled; they should be reenabled when the exception is * caught. */ void exraise(int e) { INTOFF; if (handler == NULL) abort(); exception = e; longjmp(handler->loc, 1); } /* - * Called from trap.c when a SIGINT is received. (If the user specifies - * that SIGINT is to be trapped or ignored using the trap builtin, then - * this routine is not called.) Suppressint is nonzero when interrupts - * are held using the INTOFF macro. If SIGINTs are not suppressed and - * the shell is not a root shell, then we want to be terminated if we - * get here, as if we were terminated directly by a SIGINT. Arrange for - * this here. + * Called from trap.c when a SIGINT is received and not suppressed, or when + * an interrupt is pending and interrupts are re-enabled using INTON. + * (If the user specifies that SIGINT is to be trapped or ignored using the + * trap builtin, then this routine is not called.) Suppressint is nonzero + * when interrupts are held using the INTOFF macro. If SIGINTs are not + * suppressed and the shell is not a root shell, then we want to be + * terminated if we get here, as if we were terminated directly by a SIGINT. + * Arrange for this here. */ void onint(void) { sigset_t sigs; - /* - * The !in_dotrap here is safe. The only way we can arrive here - * with in_dotrap set is that a trap handler set SIGINT to SIG_DFL - * and killed itself. - */ - - if (suppressint && !in_dotrap) { - intpending++; - return; - } intpending = 0; sigemptyset(&sigs); sigprocmask(SIG_SETMASK, &sigs, NULL); /* * This doesn't seem to be needed, since main() emits a newline. */ #if 0 if (tcgetpgrp(0) == getpid()) write(STDERR_FILENO, "\n", 1); #endif if (rootshell && iflag) exraise(EXINT); else { signal(SIGINT, SIG_DFL); kill(getpid(), SIGINT); + _exit(128 + SIGINT); } } static void vwarning(const char *msg, va_list ap) { if (commandname) outfmt(out2, "%s: ", commandname); else if (arg0) outfmt(out2, "%s: ", arg0); doformat(out2, msg, ap); out2fmt_flush("\n"); } void warning(const char *msg, ...) { va_list ap; va_start(ap, msg); vwarning(msg, ap); va_end(ap); } /* * Exverror is called to raise the error exception. If the first argument * is not NULL then error prints an error message using printf style * formatting. It then raises the error exception. */ static void exverror(int cond, const char *msg, va_list ap) { /* * An interrupt trumps an error. Certain places catch error * exceptions or transform them to a plain nonzero exit code * in child processes, and if an error exception can be handled, * an interrupt can be handled as well. * * exraise() will disable interrupts for the exception handler. */ FORCEINTON; #ifdef DEBUG if (msg) TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid())); else TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid())); #endif if (msg) vwarning(msg, ap); flushall(); exraise(cond); } void error(const char *msg, ...) { va_list ap; va_start(ap, msg); exverror(EXERROR, msg, ap); va_end(ap); } void exerror(int cond, const char *msg, ...) { va_list ap; va_start(ap, msg); exverror(cond, msg, ap); va_end(ap); } Index: projects/sendfile/bin/sh/error.h =================================================================== --- projects/sendfile/bin/sh/error.h (revision 276056) +++ projects/sendfile/bin/sh/error.h (revision 276057) @@ -1,94 +1,95 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * 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. * * @(#)error.h 8.2 (Berkeley) 5/4/95 * $FreeBSD$ */ /* * We enclose jmp_buf in a structure so that we can declare pointers to * jump locations. The global variable handler contains the location to * jump to when an exception occurs, and the global variable exception * contains a code identifying the exception. To implement nested * exception handlers, the user should save the value of handler on entry * to an inner scope, set handler to point to a jmploc structure for the * inner scope, and restore handler on exit from the scope. */ #include #include struct jmploc { jmp_buf loc; }; extern struct jmploc *handler; extern volatile sig_atomic_t exception; /* exceptions */ #define EXINT 0 /* SIGINT received */ #define EXERROR 1 /* a generic error */ #define EXEXEC 2 /* command execution failed */ #define EXEXIT 3 /* call exitshell(exitstatus) */ /* * These macros allow the user to suspend the handling of interrupt signals * over a period of time. This is similar to SIGHOLD to or sigblock, but * much more efficient and portable. (But hacking the kernel is so much * more fun than worrying about efficiency and portability. :-)) */ extern volatile sig_atomic_t suppressint; extern volatile sig_atomic_t intpending; #define INTOFF suppressint++ #define INTON { if (--suppressint == 0 && intpending) onint(); } #define is_int_on() suppressint #define SETINTON(s) suppressint = (s) #define FORCEINTON {suppressint = 0; if (intpending) onint();} +#define SET_PENDING_INT intpending = 1 #define CLEAR_PENDING_INT intpending = 0 #define int_pending() intpending void exraise(int) __dead2; -void onint(void); +void onint(void) __dead2; void warning(const char *, ...) __printflike(1, 2); void error(const char *, ...) __printf0like(1, 2) __dead2; void exerror(int, const char *, ...) __printf0like(2, 3) __dead2; /* * BSD setjmp saves the signal mask, which violates ANSI C and takes time, * so we use _setjmp instead. */ #define setjmp(jmploc) _setjmp(jmploc) #define longjmp(jmploc, val) _longjmp(jmploc, val) Index: projects/sendfile/bin/sh/eval.c =================================================================== --- projects/sendfile/bin/sh/eval.c (revision 276056) +++ projects/sendfile/bin/sh/eval.c (revision 276057) @@ -1,1382 +1,1382 @@ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * 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. */ #ifndef lint #if 0 static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include /* For WIFSIGNALED(status) */ #include /* * Evaluate a command. */ #include "shell.h" #include "nodes.h" #include "syntax.h" #include "expand.h" #include "parser.h" #include "jobs.h" #include "eval.h" #include "builtins.h" #include "options.h" #include "exec.h" #include "redir.h" #include "input.h" #include "output.h" #include "trap.h" #include "var.h" #include "memalloc.h" #include "error.h" #include "show.h" #include "mystring.h" #ifndef NO_HISTORY #include "myhistedit.h" #endif int evalskip; /* set if we are skipping commands */ int skipcount; /* number of levels to skip */ static int loopnest; /* current loop nesting level */ int funcnest; /* depth of function calls */ static int builtin_flags; /* evalcommand flags for builtins */ char *commandname; struct strlist *cmdenviron; int exitstatus; /* exit status of last command */ int oexitstatus; /* saved exit status */ static void evalloop(union node *, int); static void evalfor(union node *, int); static union node *evalcase(union node *); static void evalsubshell(union node *, int); static void evalredir(union node *, int); static void exphere(union node *, struct arglist *); static void expredir(union node *); static void evalpipe(union node *); static int is_valid_fast_cmdsubst(union node *n); static void evalcommand(union node *, int, struct backcmd *); static void prehash(union node *); /* * Called to reset things after an exception. */ void reseteval(void) { evalskip = 0; loopnest = 0; } /* * The eval command. */ int evalcmd(int argc, char **argv) { char *p; char *concat; char **ap; if (argc > 1) { p = argv[1]; if (argc > 2) { STARTSTACKSTR(concat); ap = argv + 2; for (;;) { STPUTS(p, concat); if ((p = *ap++) == NULL) break; STPUTC(' ', concat); } STPUTC('\0', concat); p = grabstackstr(concat); } evalstring(p, builtin_flags); } else exitstatus = 0; return exitstatus; } /* * Execute a command or commands contained in a string. */ void evalstring(char *s, int flags) { union node *n; struct stackmark smark; int flags_exit; int any; flags_exit = flags & EV_EXIT; flags &= ~EV_EXIT; any = 0; setstackmark(&smark); setinputstring(s, 1); while ((n = parsecmd(0)) != NEOF) { if (n != NULL && !nflag) { if (flags_exit && preadateof()) evaltree(n, flags | EV_EXIT); else evaltree(n, flags); any = 1; if (evalskip) break; } popstackmark(&smark); setstackmark(&smark); } popfile(); popstackmark(&smark); if (!any) exitstatus = 0; if (flags_exit) exraise(EXEXIT); } /* * Evaluate a parse tree. The value is left in the global variable * exitstatus. */ void evaltree(union node *n, int flags) { int do_etest; union node *next; struct stackmark smark; setstackmark(&smark); do_etest = 0; if (n == NULL) { TRACE(("evaltree(NULL) called\n")); exitstatus = 0; goto out; } do { next = NULL; #ifndef NO_HISTORY displayhist = 1; /* show history substitutions done with fc */ #endif TRACE(("evaltree(%p: %d) called\n", (void *)n, n->type)); switch (n->type) { case NSEMI: evaltree(n->nbinary.ch1, flags & ~EV_EXIT); if (evalskip) goto out; next = n->nbinary.ch2; break; case NAND: evaltree(n->nbinary.ch1, EV_TESTED); if (evalskip || exitstatus != 0) { goto out; } next = n->nbinary.ch2; break; case NOR: evaltree(n->nbinary.ch1, EV_TESTED); if (evalskip || exitstatus == 0) goto out; next = n->nbinary.ch2; break; case NREDIR: evalredir(n, flags); break; case NSUBSHELL: evalsubshell(n, flags); do_etest = !(flags & EV_TESTED); break; case NBACKGND: evalsubshell(n, flags); break; case NIF: { evaltree(n->nif.test, EV_TESTED); if (evalskip) goto out; if (exitstatus == 0) next = n->nif.ifpart; else if (n->nif.elsepart) next = n->nif.elsepart; else exitstatus = 0; break; } case NWHILE: case NUNTIL: evalloop(n, flags & ~EV_EXIT); break; case NFOR: evalfor(n, flags & ~EV_EXIT); break; case NCASE: next = evalcase(n); break; case NCLIST: next = n->nclist.body; break; case NCLISTFALLTHRU: if (n->nclist.body) { evaltree(n->nclist.body, flags & ~EV_EXIT); if (evalskip) goto out; } next = n->nclist.next; break; case NDEFUN: defun(n->narg.text, n->narg.next); exitstatus = 0; break; case NNOT: evaltree(n->nnot.com, EV_TESTED); if (evalskip) goto out; exitstatus = !exitstatus; break; case NPIPE: evalpipe(n); do_etest = !(flags & EV_TESTED); break; case NCMD: evalcommand(n, flags, (struct backcmd *)NULL); do_etest = !(flags & EV_TESTED); break; default: out1fmt("Node type = %d\n", n->type); flushout(&output); break; } n = next; popstackmark(&smark); setstackmark(&smark); } while (n != NULL); out: popstackmark(&smark); if (pendingsig) dotrap(); if (eflag && exitstatus != 0 && do_etest) exitshell(exitstatus); if (flags & EV_EXIT) exraise(EXEXIT); } static void evalloop(union node *n, int flags) { int status; loopnest++; status = 0; for (;;) { if (!evalskip) evaltree(n->nbinary.ch1, EV_TESTED); if (evalskip) { if (evalskip == SKIPCONT && --skipcount <= 0) { evalskip = 0; continue; } if (evalskip == SKIPBREAK && --skipcount <= 0) evalskip = 0; if (evalskip == SKIPRETURN) status = exitstatus; break; } if (n->type == NWHILE) { if (exitstatus != 0) break; } else { if (exitstatus == 0) break; } evaltree(n->nbinary.ch2, flags); status = exitstatus; } loopnest--; exitstatus = status; } static void evalfor(union node *n, int flags) { struct arglist arglist; union node *argp; struct strlist *sp; int status; arglist.lastp = &arglist.list; for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { oexitstatus = exitstatus; expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); } *arglist.lastp = NULL; loopnest++; status = 0; for (sp = arglist.list ; sp ; sp = sp->next) { setvar(n->nfor.var, sp->text, 0); evaltree(n->nfor.body, flags); status = exitstatus; if (evalskip) { if (evalskip == SKIPCONT && --skipcount <= 0) { evalskip = 0; continue; } if (evalskip == SKIPBREAK && --skipcount <= 0) evalskip = 0; break; } } loopnest--; exitstatus = status; } /* * Evaluate a case statement, returning the selected tree. * * The exit status needs care to get right. */ static union node * evalcase(union node *n) { union node *cp; union node *patp; struct arglist arglist; arglist.lastp = &arglist.list; oexitstatus = exitstatus; expandarg(n->ncase.expr, &arglist, EXP_TILDE); for (cp = n->ncase.cases ; cp ; cp = cp->nclist.next) { for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { if (casematch(patp, arglist.list->text)) { while (cp->nclist.next && cp->type == NCLISTFALLTHRU && cp->nclist.body == NULL) cp = cp->nclist.next; if (cp->nclist.next && cp->type == NCLISTFALLTHRU) return (cp); if (cp->nclist.body == NULL) exitstatus = 0; return (cp->nclist.body); } } } exitstatus = 0; return (NULL); } /* * Kick off a subshell to evaluate a tree. */ static void evalsubshell(union node *n, int flags) { struct job *jp; int backgnd = (n->type == NBACKGND); oexitstatus = exitstatus; expredir(n->nredir.redirect); if ((!backgnd && flags & EV_EXIT && !have_traps()) || forkshell(jp = makejob(n, 1), n, backgnd) == 0) { if (backgnd) flags &=~ EV_TESTED; redirect(n->nredir.redirect, 0); evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */ } else if (! backgnd) { INTOFF; exitstatus = waitforjob(jp, (int *)NULL); INTON; } else exitstatus = 0; } /* * Evaluate a redirected compound command. */ static void evalredir(union node *n, int flags) { struct jmploc jmploc; struct jmploc *savehandler; volatile int in_redirect = 1; oexitstatus = exitstatus; expredir(n->nredir.redirect); savehandler = handler; if (setjmp(jmploc.loc)) { int e; handler = savehandler; e = exception; popredir(); if (e == EXERROR || e == EXEXEC) { if (in_redirect) { exitstatus = 2; return; } } longjmp(handler->loc, 1); } else { INTOFF; handler = &jmploc; redirect(n->nredir.redirect, REDIR_PUSH); in_redirect = 0; INTON; evaltree(n->nredir.n, flags); } INTOFF; handler = savehandler; popredir(); INTON; } static void exphere(union node *redir, struct arglist *fn) { struct jmploc jmploc; struct jmploc *savehandler; struct localvar *savelocalvars; int need_longjmp = 0; redir->nhere.expdoc = nullstr; savelocalvars = localvars; localvars = NULL; forcelocal++; savehandler = handler; if (setjmp(jmploc.loc)) need_longjmp = exception != EXERROR && exception != EXEXEC; else { handler = &jmploc; expandarg(redir->nhere.doc, fn, 0); redir->nhere.expdoc = fn->list->text; INTOFF; } handler = savehandler; forcelocal--; poplocalvars(); localvars = savelocalvars; if (need_longjmp) longjmp(handler->loc, 1); INTON; } /* * Compute the names of the files in a redirection list. */ static void expredir(union node *n) { union node *redir; for (redir = n ; redir ; redir = redir->nfile.next) { struct arglist fn; fn.lastp = &fn.list; switch (redir->type) { case NFROM: case NTO: case NFROMTO: case NAPPEND: case NCLOBBER: - expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); + expandarg(redir->nfile.fname, &fn, EXP_TILDE); redir->nfile.expfname = fn.list->text; break; case NFROMFD: case NTOFD: if (redir->ndup.vname) { - expandarg(redir->ndup.vname, &fn, EXP_TILDE | EXP_REDIR); + expandarg(redir->ndup.vname, &fn, EXP_TILDE); fixredir(redir, fn.list->text, 1); } break; case NXHERE: exphere(redir, &fn); break; } } } /* * Evaluate a pipeline. All the processes in the pipeline are children * of the process creating the pipeline. (This differs from some versions * of the shell, which make the last process in a pipeline the parent * of all the rest.) */ static void evalpipe(union node *n) { struct job *jp; struct nodelist *lp; int pipelen; int prevfd; int pip[2]; TRACE(("evalpipe(%p) called\n", (void *)n)); pipelen = 0; for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) pipelen++; INTOFF; jp = makejob(n, pipelen); prevfd = -1; for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { prehash(lp->n); pip[1] = -1; if (lp->next) { if (pipe(pip) < 0) { if (prevfd >= 0) close(prevfd); error("Pipe call failed: %s", strerror(errno)); } } if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) { INTON; if (prevfd > 0) { dup2(prevfd, 0); close(prevfd); } if (pip[1] >= 0) { if (!(prevfd >= 0 && pip[0] == 0)) close(pip[0]); if (pip[1] != 1) { dup2(pip[1], 1); close(pip[1]); } } evaltree(lp->n, EV_EXIT); } if (prevfd >= 0) close(prevfd); prevfd = pip[0]; if (pip[1] != -1) close(pip[1]); } INTON; if (n->npipe.backgnd == 0) { INTOFF; exitstatus = waitforjob(jp, (int *)NULL); TRACE(("evalpipe: job done exit status %d\n", exitstatus)); INTON; } else exitstatus = 0; } static int is_valid_fast_cmdsubst(union node *n) { return (n->type == NCMD); } /* * Execute a command inside back quotes. If it's a builtin command, we * want to save its output in a block obtained from malloc. Otherwise * we fork off a subprocess and get the output of the command via a pipe. * Should be called with interrupts off. */ void evalbackcmd(union node *n, struct backcmd *result) { int pip[2]; struct job *jp; struct stackmark smark; struct jmploc jmploc; struct jmploc *savehandler; struct localvar *savelocalvars; result->fd = -1; result->buf = NULL; result->nleft = 0; result->jp = NULL; if (n == NULL) { exitstatus = 0; return; } setstackmark(&smark); exitstatus = oexitstatus; if (is_valid_fast_cmdsubst(n)) { savelocalvars = localvars; localvars = NULL; forcelocal++; savehandler = handler; if (setjmp(jmploc.loc)) { if (exception == EXERROR || exception == EXEXEC) exitstatus = 2; else if (exception != 0) { handler = savehandler; forcelocal--; poplocalvars(); localvars = savelocalvars; longjmp(handler->loc, 1); } } else { handler = &jmploc; evalcommand(n, EV_BACKCMD, result); } handler = savehandler; forcelocal--; poplocalvars(); localvars = savelocalvars; } else { if (pipe(pip) < 0) error("Pipe call failed: %s", strerror(errno)); jp = makejob(n, 1); if (forkshell(jp, n, FORK_NOJOB) == 0) { FORCEINTON; close(pip[0]); if (pip[1] != 1) { dup2(pip[1], 1); close(pip[1]); } evaltree(n, EV_EXIT); } close(pip[1]); result->fd = pip[0]; result->jp = jp; } popstackmark(&smark); TRACE(("evalbackcmd done: fd=%d buf=%p nleft=%d jp=%p\n", result->fd, result->buf, result->nleft, result->jp)); } static int mustexpandto(const char *argtext, const char *mask) { for (;;) { if (*argtext == CTLQUOTEMARK || *argtext == CTLQUOTEEND) { argtext++; continue; } if (*argtext == CTLESC) argtext++; else if (BASESYNTAX[(int)*argtext] == CCTL) return (0); if (*argtext != *mask) return (0); if (*argtext == '\0') return (1); argtext++; mask++; } } static int isdeclarationcmd(struct narg *arg) { int have_command = 0; if (arg == NULL) return (0); while (mustexpandto(arg->text, "command")) { have_command = 1; arg = &arg->next->narg; if (arg == NULL) return (0); /* * To also allow "command -p" and "command --" as part of * a declaration command, add code here. * We do not do this, as ksh does not do it either and it * is not required by POSIX. */ } return (mustexpandto(arg->text, "export") || mustexpandto(arg->text, "readonly") || (mustexpandto(arg->text, "local") && (have_command || !isfunc("local")))); } static void xtracecommand(struct arglist *varlist, struct arglist *arglist) { struct strlist *sp; char sep = 0; const char *p, *ps4; ps4 = expandstr(ps4val()); out2str(ps4 != NULL ? ps4 : ps4val()); for (sp = varlist->list ; sp ; sp = sp->next) { if (sep != 0) out2c(' '); p = strchr(sp->text, '='); if (p != NULL) { p++; outbin(sp->text, p - sp->text, out2); out2qstr(p); } else out2qstr(sp->text); sep = ' '; } for (sp = arglist->list ; sp ; sp = sp->next) { if (sep != 0) out2c(' '); out2qstr(sp->text); sep = ' '; } out2c('\n'); flushout(&errout); } /* * Check if a builtin can safely be executed in the same process, * even though it should be in a subshell (command substitution). * Note that jobid, jobs, times and trap can show information not * available in a child process; this is deliberate. * The arguments should already have been expanded. */ static int safe_builtin(int idx, int argc, char **argv) { if (idx == BLTINCMD || idx == COMMANDCMD || idx == ECHOCMD || idx == FALSECMD || idx == JOBIDCMD || idx == JOBSCMD || idx == KILLCMD || idx == PRINTFCMD || idx == PWDCMD || idx == TESTCMD || idx == TIMESCMD || idx == TRUECMD || idx == TYPECMD) return (1); if (idx == EXPORTCMD || idx == TRAPCMD || idx == ULIMITCMD || idx == UMASKCMD) return (argc <= 1 || (argc == 2 && argv[1][0] == '-')); if (idx == SETCMD) return (argc <= 1 || (argc == 2 && (argv[1][0] == '-' || argv[1][0] == '+') && argv[1][1] == 'o' && argv[1][2] == '\0')); return (0); } /* * Execute a simple command. * Note: This may or may not return if (flags & EV_EXIT). */ static void evalcommand(union node *cmd, int flags, struct backcmd *backcmd) { union node *argp; struct arglist arglist; struct arglist varlist; char **argv; int argc; char **envp; int varflag; struct strlist *sp; int mode; int pip[2]; struct cmdentry cmdentry; struct job *jp; struct jmploc jmploc; struct jmploc *savehandler; char *savecmdname; struct shparam saveparam; struct localvar *savelocalvars; struct parsefile *savetopfile; volatile int e; char *lastarg; int realstatus; int do_clearcmdentry; const char *path = pathval(); /* First expand the arguments. */ TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags)); arglist.lastp = &arglist.list; varlist.lastp = &varlist.list; varflag = 1; jp = NULL; do_clearcmdentry = 0; oexitstatus = exitstatus; exitstatus = 0; for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { if (varflag && isassignment(argp->narg.text)) { expandarg(argp, varflag == 1 ? &varlist : &arglist, EXP_VARTILDE); continue; } else if (varflag == 1) varflag = isdeclarationcmd(&argp->narg) ? 2 : 0; expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); } *arglist.lastp = NULL; *varlist.lastp = NULL; expredir(cmd->ncmd.redirect); argc = 0; for (sp = arglist.list ; sp ; sp = sp->next) argc++; /* Add one slot at the beginning for tryexec(). */ argv = stalloc(sizeof (char *) * (argc + 2)); argv++; for (sp = arglist.list ; sp ; sp = sp->next) { TRACE(("evalcommand arg: %s\n", sp->text)); *argv++ = sp->text; } *argv = NULL; lastarg = NULL; if (iflag && funcnest == 0 && argc > 0) lastarg = argv[-1]; argv -= argc; /* Print the command if xflag is set. */ if (xflag) xtracecommand(&varlist, &arglist); /* Now locate the command. */ if (argc == 0) { /* Variable assignment(s) without command */ cmdentry.cmdtype = CMDBUILTIN; cmdentry.u.index = BLTINCMD; cmdentry.special = 0; } else { static const char PATH[] = "PATH="; int cmd_flags = 0, bltinonly = 0; /* * Modify the command lookup path, if a PATH= assignment * is present */ for (sp = varlist.list ; sp ; sp = sp->next) if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) { path = sp->text + sizeof(PATH) - 1; /* * On `PATH=... command`, we need to make * sure that the command isn't using the * non-updated hash table of the outer PATH * setting and we need to make sure that * the hash table isn't filled with items * from the temporary setting. * * It would be better to forbit using and * updating the table while this command * runs, by the command finding mechanism * is heavily integrated with hash handling, * so we just delete the hash before and after * the command runs. Partly deleting like * changepatch() does doesn't seem worth the * bookinging effort, since most such runs add * directories in front of the new PATH. */ clearcmdentry(); do_clearcmdentry = 1; } for (;;) { if (bltinonly) { cmdentry.u.index = find_builtin(*argv, &cmdentry.special); if (cmdentry.u.index < 0) { cmdentry.u.index = BLTINCMD; argv--; argc++; break; } } else find_command(argv[0], &cmdentry, cmd_flags, path); /* implement the bltin and command builtins here */ if (cmdentry.cmdtype != CMDBUILTIN) break; if (cmdentry.u.index == BLTINCMD) { if (argc == 1) break; argv++; argc--; bltinonly = 1; } else if (cmdentry.u.index == COMMANDCMD) { if (argc == 1) break; if (!strcmp(argv[1], "-p")) { if (argc == 2) break; if (argv[2][0] == '-') { if (strcmp(argv[2], "--")) break; if (argc == 3) break; argv += 3; argc -= 3; } else { argv += 2; argc -= 2; } path = _PATH_STDPATH; clearcmdentry(); do_clearcmdentry = 1; } else if (!strcmp(argv[1], "--")) { if (argc == 2) break; argv += 2; argc -= 2; } else if (argv[1][0] == '-') break; else { argv++; argc--; } cmd_flags |= DO_NOFUNC; bltinonly = 0; } else break; } /* * Special builtins lose their special properties when * called via 'command'. */ if (cmd_flags & DO_NOFUNC) cmdentry.special = 0; } /* Fork off a child process if necessary. */ if (((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN) && ((flags & EV_EXIT) == 0 || have_traps())) || ((flags & EV_BACKCMD) != 0 && (cmdentry.cmdtype != CMDBUILTIN || !safe_builtin(cmdentry.u.index, argc, argv)))) { jp = makejob(cmd, 1); mode = FORK_FG; if (flags & EV_BACKCMD) { mode = FORK_NOJOB; if (pipe(pip) < 0) error("Pipe call failed: %s", strerror(errno)); } if (cmdentry.cmdtype == CMDNORMAL && cmd->ncmd.redirect == NULL && varlist.list == NULL && (mode == FORK_FG || mode == FORK_NOJOB) && !disvforkset() && !iflag && !mflag) { vforkexecshell(jp, argv, environment(), path, cmdentry.u.index, flags & EV_BACKCMD ? pip : NULL); goto parent; } if (forkshell(jp, cmd, mode) != 0) goto parent; /* at end of routine */ if (flags & EV_BACKCMD) { FORCEINTON; close(pip[0]); if (pip[1] != 1) { dup2(pip[1], 1); close(pip[1]); } flags &= ~EV_BACKCMD; } flags |= EV_EXIT; } /* This is the child process if a fork occurred. */ /* Execute the command. */ if (cmdentry.cmdtype == CMDFUNCTION) { #ifdef DEBUG trputs("Shell function: "); trargs(argv); #endif saveparam = shellparam; shellparam.malloc = 0; shellparam.reset = 1; shellparam.nparam = argc - 1; shellparam.p = argv + 1; shellparam.optp = NULL; shellparam.optnext = NULL; INTOFF; savelocalvars = localvars; localvars = NULL; reffunc(cmdentry.u.func); savehandler = handler; if (setjmp(jmploc.loc)) { freeparam(&shellparam); shellparam = saveparam; popredir(); unreffunc(cmdentry.u.func); poplocalvars(); localvars = savelocalvars; funcnest--; handler = savehandler; longjmp(handler->loc, 1); } handler = &jmploc; funcnest++; redirect(cmd->ncmd.redirect, REDIR_PUSH); INTON; for (sp = varlist.list ; sp ; sp = sp->next) mklocal(sp->text); exitstatus = oexitstatus; evaltree(getfuncnode(cmdentry.u.func), flags & (EV_TESTED | EV_EXIT)); INTOFF; unreffunc(cmdentry.u.func); poplocalvars(); localvars = savelocalvars; freeparam(&shellparam); shellparam = saveparam; handler = savehandler; funcnest--; popredir(); INTON; if (evalskip == SKIPRETURN) { evalskip = 0; skipcount = 0; } if (jp) exitshell(exitstatus); } else if (cmdentry.cmdtype == CMDBUILTIN) { #ifdef DEBUG trputs("builtin command: "); trargs(argv); #endif mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH; if (flags == EV_BACKCMD) { memout.nleft = 0; memout.nextc = memout.buf; memout.bufsize = 64; mode |= REDIR_BACKQ; } savecmdname = commandname; savetopfile = getcurrentfile(); cmdenviron = varlist.list; e = -1; savehandler = handler; if (setjmp(jmploc.loc)) { e = exception; if (e == EXINT) exitstatus = SIGINT+128; else if (e != EXEXIT) exitstatus = 2; goto cmddone; } handler = &jmploc; redirect(cmd->ncmd.redirect, mode); outclearerror(out1); /* * If there is no command word, redirection errors should * not be fatal but assignment errors should. */ if (argc == 0) cmdentry.special = 1; listsetvar(cmdenviron, cmdentry.special ? 0 : VNOSET); if (argc > 0) bltinsetlocale(); commandname = argv[0]; argptr = argv + 1; nextopt_optptr = NULL; /* initialize nextopt */ builtin_flags = flags; exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv); flushall(); if (outiserror(out1)) { warning("write error on stdout"); if (exitstatus == 0 || exitstatus == 1) exitstatus = 2; } cmddone: if (argc > 0) bltinunsetlocale(); cmdenviron = NULL; out1 = &output; out2 = &errout; freestdout(); handler = savehandler; commandname = savecmdname; if (jp) exitshell(exitstatus); if (flags == EV_BACKCMD) { backcmd->buf = memout.buf; backcmd->nleft = memout.nextc - memout.buf; memout.buf = NULL; } if (cmdentry.u.index != EXECCMD) popredir(); if (e != -1) { if ((e != EXERROR && e != EXEXEC) || cmdentry.special) exraise(e); popfilesupto(savetopfile); if (flags != EV_BACKCMD) FORCEINTON; } } else { #ifdef DEBUG trputs("normal command: "); trargs(argv); #endif redirect(cmd->ncmd.redirect, 0); for (sp = varlist.list ; sp ; sp = sp->next) setvareq(sp->text, VEXPORT|VSTACK); envp = environment(); shellexec(argv, envp, path, cmdentry.u.index); /*NOTREACHED*/ } goto out; parent: /* parent process gets here (if we forked) */ if (mode == FORK_FG) { /* argument to fork */ INTOFF; exitstatus = waitforjob(jp, &realstatus); INTON; if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) { evalskip = SKIPBREAK; skipcount = loopnest; } } else if (mode == FORK_NOJOB) { backcmd->fd = pip[0]; close(pip[1]); backcmd->jp = jp; } out: if (lastarg) setvar("_", lastarg, 0); if (do_clearcmdentry) clearcmdentry(); } /* * Search for a command. This is called before we fork so that the * location of the command will be available in the parent as well as * the child. The check for "goodname" is an overly conservative * check that the name will not be subject to expansion. */ static void prehash(union node *n) { struct cmdentry entry; if (n && n->type == NCMD && n->ncmd.args) if (goodname(n->ncmd.args->narg.text)) find_command(n->ncmd.args->narg.text, &entry, 0, pathval()); } /* * Builtin commands. Builtin commands whose functions are closely * tied to evaluation are implemented here. */ /* * No command given, a bltin command with no arguments, or a bltin command * with an invalid name. */ int bltincmd(int argc, char **argv) { if (argc > 1) { out2fmt_flush("%s: not found\n", argv[1]); return 127; } /* * Preserve exitstatus of a previous possible redirection * as POSIX mandates */ return exitstatus; } /* * Handle break and continue commands. Break, continue, and return are * all handled by setting the evalskip flag. The evaluation routines * above all check this flag, and if it is set they start skipping * commands rather than executing them. The variable skipcount is * the number of loops to break/continue, or the number of function * levels to return. (The latter is always 1.) It should probably * be an error to break out of more loops than exist, but it isn't * in the standard shell so we don't make it one here. */ int breakcmd(int argc, char **argv) { long n; char *end; if (argc > 1) { /* Allow arbitrarily large numbers. */ n = strtol(argv[1], &end, 10); if (!is_digit(argv[1][0]) || *end != '\0') error("Illegal number: %s", argv[1]); } else n = 1; if (n > loopnest) n = loopnest; if (n > 0) { evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK; skipcount = n; } return 0; } /* * The `command' command. */ int commandcmd(int argc __unused, char **argv __unused) { const char *path; int ch; int cmd = -1; path = bltinlookup("PATH", 1); while ((ch = nextopt("pvV")) != '\0') { switch (ch) { case 'p': path = _PATH_STDPATH; break; case 'v': cmd = TYPECMD_SMALLV; break; case 'V': cmd = TYPECMD_BIGV; break; } } if (cmd != -1) { if (*argptr == NULL || argptr[1] != NULL) error("wrong number of arguments"); return typecmd_impl(2, argptr - 1, cmd, path); } if (*argptr != NULL) error("commandcmd bad call"); /* * Do nothing successfully if no command was specified; * ksh also does this. */ return 0; } /* * The return command. */ int returncmd(int argc, char **argv) { int ret = argc > 1 ? number(argv[1]) : oexitstatus; evalskip = SKIPRETURN; skipcount = 1; return ret; } int falsecmd(int argc __unused, char **argv __unused) { return 1; } int truecmd(int argc __unused, char **argv __unused) { return 0; } int execcmd(int argc, char **argv) { /* * Because we have historically not supported any options, * only treat "--" specially. */ if (argc > 1 && strcmp(argv[1], "--") == 0) argc--, argv++; if (argc > 1) { struct strlist *sp; iflag = 0; /* exit on error */ mflag = 0; optschanged(); for (sp = cmdenviron; sp ; sp = sp->next) setvareq(sp->text, VEXPORT|VSTACK); shellexec(argv + 1, environment(), pathval(), 0); } return 0; } int timescmd(int argc __unused, char **argv __unused) { struct rusage ru; long shumins, shsmins, chumins, chsmins; double shusecs, shssecs, chusecs, chssecs; if (getrusage(RUSAGE_SELF, &ru) < 0) return 1; shumins = ru.ru_utime.tv_sec / 60; shusecs = ru.ru_utime.tv_sec % 60 + ru.ru_utime.tv_usec / 1000000.; shsmins = ru.ru_stime.tv_sec / 60; shssecs = ru.ru_stime.tv_sec % 60 + ru.ru_stime.tv_usec / 1000000.; if (getrusage(RUSAGE_CHILDREN, &ru) < 0) return 1; chumins = ru.ru_utime.tv_sec / 60; chusecs = ru.ru_utime.tv_sec % 60 + ru.ru_utime.tv_usec / 1000000.; chsmins = ru.ru_stime.tv_sec / 60; chssecs = ru.ru_stime.tv_sec % 60 + ru.ru_stime.tv_usec / 1000000.; out1fmt("%ldm%.3fs %ldm%.3fs\n%ldm%.3fs %ldm%.3fs\n", shumins, shusecs, shsmins, shssecs, chumins, chusecs, chsmins, chssecs); return 0; } Index: projects/sendfile/bin/sh/expand.c =================================================================== --- projects/sendfile/bin/sh/expand.c (revision 276056) +++ projects/sendfile/bin/sh/expand.c (revision 276057) @@ -1,1678 +1,1672 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 1997-2005 * Herbert Xu . All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * 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. */ #ifndef lint #if 0 static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Routines to expand arguments to commands. We have to deal with * backquotes, shell variables, and file metacharacters. */ #include "shell.h" #include "main.h" #include "nodes.h" #include "eval.h" #include "expand.h" #include "syntax.h" #include "parser.h" #include "jobs.h" #include "options.h" #include "var.h" #include "input.h" #include "output.h" #include "memalloc.h" #include "error.h" #include "mystring.h" #include "arith.h" #include "show.h" #include "builtins.h" /* * Structure specifying which parts of the string should be searched * for IFS characters. */ struct ifsregion { struct ifsregion *next; /* next region in list */ int begoff; /* offset of start of region */ int endoff; /* offset of end of region */ int inquotes; /* search for nul bytes only */ }; static char *expdest; /* output of current string */ static struct nodelist *argbackq; /* list of back quote expressions */ static struct ifsregion ifsfirst; /* first struct in list of ifs regions */ static struct ifsregion *ifslastp; /* last struct in list */ static struct arglist exparg; /* holds expanded arg list */ static char *argstr(char *, int); static char *exptilde(char *, int); static char *expari(char *); static void expbackq(union node *, int, int); static int subevalvar(char *, char *, int, int, int, int, int); static char *evalvar(char *, int); static int varisset(const char *, int); static void varvalue(const char *, int, int, int); static void recordregion(int, int, int); static void removerecordregions(int); static void ifsbreakup(char *, struct arglist *); static void expandmeta(struct strlist *, int); static void expmeta(char *, char *); static void addfname(char *); static struct strlist *expsort(struct strlist *); static struct strlist *msort(struct strlist *, int); static int patmatch(const char *, const char *, int); static char *cvtnum(int, char *); static int collate_range_cmp(wchar_t, wchar_t); static int collate_range_cmp(wchar_t c1, wchar_t c2) { static wchar_t s1[2], s2[2]; s1[0] = c1; s2[0] = c2; return (wcscoll(s1, s2)); } static char * stputs_quotes(const char *data, const char *syntax, char *p) { while (*data) { CHECKSTRSPACE(2, p); if (syntax[(int)*data] == CCTL) USTPUTC(CTLESC, p); USTPUTC(*data++, p); } return (p); } #define STPUTS_QUOTES(data, syntax, p) p = stputs_quotes((data), syntax, p) /* * Perform expansions on an argument, placing the resulting list of arguments * in arglist. Parameter expansion, command substitution and arithmetic * expansion are always performed; additional expansions can be requested * via flag (EXP_*). * The result is left in the stack string. * When arglist is NULL, perform here document expansion. * * Caution: this function uses global state and is not reentrant. * However, a new invocation after an interrupted invocation is safe * and will reset the global state for the new call. */ void expandarg(union node *arg, struct arglist *arglist, int flag) { struct strlist *sp; char *p; argbackq = arg->narg.backquote; STARTSTACKSTR(expdest); ifsfirst.next = NULL; ifslastp = NULL; argstr(arg->narg.text, flag); if (arglist == NULL) { STACKSTRNUL(expdest); return; /* here document expanded */ } STPUTC('\0', expdest); p = grabstackstr(expdest); exparg.lastp = &exparg.list; - /* - * TODO - EXP_REDIR - */ if (flag & EXP_FULL) { ifsbreakup(p, &exparg); *exparg.lastp = NULL; exparg.lastp = &exparg.list; expandmeta(exparg.list, flag); } else { - if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */ - rmescapes(p); sp = (struct strlist *)stalloc(sizeof (struct strlist)); sp->text = p; *exparg.lastp = sp; exparg.lastp = &sp->next; } while (ifsfirst.next != NULL) { struct ifsregion *ifsp; INTOFF; ifsp = ifsfirst.next->next; ckfree(ifsfirst.next); ifsfirst.next = ifsp; INTON; } *exparg.lastp = NULL; if (exparg.list) { *arglist->lastp = exparg.list; arglist->lastp = exparg.lastp; } } /* * Perform parameter expansion, command substitution and arithmetic * expansion, and tilde expansion if requested via EXP_TILDE/EXP_VARTILDE. * Processing ends at a CTLENDVAR or CTLENDARI character as well as '\0'. * This is used to expand word in ${var+word} etc. - * If EXP_FULL, EXP_CASE or EXP_REDIR are set, keep and/or generate CTLESC + * If EXP_FULL or EXP_CASE are set, keep and/or generate CTLESC * characters to allow for further processing. * If EXP_FULL is set, also preserve CTLQUOTEMARK characters. */ static char * argstr(char *p, int flag) { char c; - int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); /* do CTLESC */ + int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */ int firsteq = 1; int split_lit; int lit_quoted; split_lit = flag & EXP_SPLIT_LIT; lit_quoted = flag & EXP_LIT_QUOTED; flag &= ~(EXP_SPLIT_LIT | EXP_LIT_QUOTED); if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE))) p = exptilde(p, flag); for (;;) { CHECKSTRSPACE(2, expdest); switch (c = *p++) { case '\0': return (p - 1); case CTLENDVAR: case CTLENDARI: return (p); case CTLQUOTEMARK: lit_quoted = 1; /* "$@" syntax adherence hack */ if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=') break; if ((flag & EXP_FULL) != 0) USTPUTC(c, expdest); break; case CTLQUOTEEND: lit_quoted = 0; break; case CTLESC: if (quotes) USTPUTC(c, expdest); c = *p++; USTPUTC(c, expdest); if (split_lit && !lit_quoted) recordregion(expdest - stackblock() - (quotes ? 2 : 1), expdest - stackblock(), 0); break; case CTLVAR: p = evalvar(p, flag); break; case CTLBACKQ: case CTLBACKQ|CTLQUOTE: expbackq(argbackq->n, c & CTLQUOTE, flag); argbackq = argbackq->next; break; case CTLARI: p = expari(p); break; case ':': case '=': /* * sort of a hack - expand tildes in variable * assignments (after the first '=' and after ':'s). */ USTPUTC(c, expdest); if (split_lit && !lit_quoted) recordregion(expdest - stackblock() - 1, expdest - stackblock(), 0); if (flag & EXP_VARTILDE && *p == '~' && (c != '=' || firsteq)) { if (c == '=') firsteq = 0; p = exptilde(p, flag); } break; default: USTPUTC(c, expdest); if (split_lit && !lit_quoted) recordregion(expdest - stackblock() - 1, expdest - stackblock(), 0); } } } /* * Perform tilde expansion, placing the result in the stack string and * returning the next position in the input string to process. */ static char * exptilde(char *p, int flag) { char c, *startp = p; struct passwd *pw; char *home; - int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); + int quotes = flag & (EXP_FULL | EXP_CASE); while ((c = *p) != '\0') { switch(c) { case CTLESC: /* This means CTL* are always considered quoted. */ case CTLVAR: case CTLBACKQ: case CTLBACKQ | CTLQUOTE: case CTLARI: case CTLENDARI: case CTLQUOTEMARK: return (startp); case ':': if (flag & EXP_VARTILDE) goto done; break; case '/': case CTLENDVAR: goto done; } p++; } done: *p = '\0'; if (*(startp+1) == '\0') { home = lookupvar("HOME"); } else { pw = getpwnam(startp+1); home = pw != NULL ? pw->pw_dir : NULL; } *p = c; if (home == NULL || *home == '\0') return (startp); if (quotes) STPUTS_QUOTES(home, DQSYNTAX, expdest); else STPUTS(home, expdest); return (p); } static void removerecordregions(int endoff) { if (ifslastp == NULL) return; if (ifsfirst.endoff > endoff) { while (ifsfirst.next != NULL) { struct ifsregion *ifsp; INTOFF; ifsp = ifsfirst.next->next; ckfree(ifsfirst.next); ifsfirst.next = ifsp; INTON; } if (ifsfirst.begoff > endoff) ifslastp = NULL; else { ifslastp = &ifsfirst; ifsfirst.endoff = endoff; } return; } ifslastp = &ifsfirst; while (ifslastp->next && ifslastp->next->begoff < endoff) ifslastp=ifslastp->next; while (ifslastp->next != NULL) { struct ifsregion *ifsp; INTOFF; ifsp = ifslastp->next->next; ckfree(ifslastp->next); ifslastp->next = ifsp; INTON; } if (ifslastp->endoff > endoff) ifslastp->endoff = endoff; } /* * Expand arithmetic expression. * Note that flag is not required as digits never require CTLESC characters. */ static char * expari(char *p) { char *q, *start; arith_t result; int begoff; int quoted; int adj; quoted = *p++ == '"'; begoff = expdest - stackblock(); p = argstr(p, 0); removerecordregions(begoff); STPUTC('\0', expdest); start = stackblock() + begoff; q = grabstackstr(expdest); result = arith(start); ungrabstackstr(q, expdest); start = stackblock() + begoff; adj = start - expdest; STADJUST(adj, expdest); CHECKSTRSPACE((int)(DIGITS(result) + 1), expdest); fmtstr(expdest, DIGITS(result), ARITH_FORMAT_STR, result); adj = strlen(expdest); STADJUST(adj, expdest); if (!quoted) recordregion(begoff, expdest - stackblock(), 0); return p; } /* * Perform command substitution. */ static void expbackq(union node *cmd, int quoted, int flag) { struct backcmd in; int i; char buf[128]; char *p; char *dest = expdest; struct ifsregion saveifs, *savelastp; struct nodelist *saveargbackq; char lastc; int startloc = dest - stackblock(); char const *syntax = quoted? DQSYNTAX : BASESYNTAX; - int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); + int quotes = flag & (EXP_FULL | EXP_CASE); size_t nnl; INTOFF; saveifs = ifsfirst; savelastp = ifslastp; saveargbackq = argbackq; p = grabstackstr(dest); evalbackcmd(cmd, &in); ungrabstackstr(p, dest); ifsfirst = saveifs; ifslastp = savelastp; argbackq = saveargbackq; p = in.buf; lastc = '\0'; nnl = 0; /* Don't copy trailing newlines */ for (;;) { if (--in.nleft < 0) { if (in.fd < 0) break; while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR); TRACE(("expbackq: read returns %d\n", i)); if (i <= 0) break; p = buf; in.nleft = i - 1; } lastc = *p++; if (lastc != '\0') { if (lastc == '\n') { nnl++; } else { CHECKSTRSPACE(nnl + 2, dest); while (nnl > 0) { nnl--; USTPUTC('\n', dest); } if (quotes && syntax[(int)lastc] == CCTL) USTPUTC(CTLESC, dest); USTPUTC(lastc, dest); } } } if (in.fd >= 0) close(in.fd); if (in.buf) ckfree(in.buf); if (in.jp) exitstatus = waitforjob(in.jp, (int *)NULL); if (quoted == 0) recordregion(startloc, dest - stackblock(), 0); TRACE(("expbackq: size=%td: \"%.*s\"\n", ((dest - stackblock()) - startloc), (int)((dest - stackblock()) - startloc), stackblock() + startloc)); expdest = dest; INTON; } static int subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes) { char *startp; char *loc = NULL; char *q; int c = 0; struct nodelist *saveargbackq = argbackq; int amount; argstr(p, (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX || subtype == VSTRIMRIGHT || subtype == VSTRIMRIGHTMAX ? EXP_CASE : 0) | EXP_TILDE); STACKSTRNUL(expdest); argbackq = saveargbackq; startp = stackblock() + startloc; if (str == NULL) str = stackblock() + strloc; switch (subtype) { case VSASSIGN: setvar(str, startp, 0); amount = startp - expdest; STADJUST(amount, expdest); varflags &= ~VSNUL; return 1; case VSQUESTION: if (*p != CTLENDVAR) { outfmt(out2, "%s\n", startp); error((char *)NULL); } error("%.*s: parameter %snot set", (int)(p - str - 1), str, (varflags & VSNUL) ? "null or " : nullstr); return 0; case VSTRIMLEFT: for (loc = startp; loc < str; loc++) { c = *loc; *loc = '\0'; if (patmatch(str, startp, quotes)) { *loc = c; goto recordleft; } *loc = c; if (quotes && *loc == CTLESC) loc++; } return 0; case VSTRIMLEFTMAX: for (loc = str - 1; loc >= startp;) { c = *loc; *loc = '\0'; if (patmatch(str, startp, quotes)) { *loc = c; goto recordleft; } *loc = c; loc--; if (quotes && loc > startp && *(loc - 1) == CTLESC) { for (q = startp; q < loc; q++) if (*q == CTLESC) q++; if (q > loc) loc--; } } return 0; case VSTRIMRIGHT: for (loc = str - 1; loc >= startp;) { if (patmatch(str, loc, quotes)) { amount = loc - expdest; STADJUST(amount, expdest); return 1; } loc--; if (quotes && loc > startp && *(loc - 1) == CTLESC) { for (q = startp; q < loc; q++) if (*q == CTLESC) q++; if (q > loc) loc--; } } return 0; case VSTRIMRIGHTMAX: for (loc = startp; loc < str - 1; loc++) { if (patmatch(str, loc, quotes)) { amount = loc - expdest; STADJUST(amount, expdest); return 1; } if (quotes && *loc == CTLESC) loc++; } return 0; default: abort(); } recordleft: amount = ((str - 1) - (loc - startp)) - expdest; STADJUST(amount, expdest); while (loc != str - 1) *startp++ = *loc++; return 1; } /* * Expand a variable, and return a pointer to the next character in the * input string. */ static char * evalvar(char *p, int flag) { int subtype; int varflags; char *var; const char *val; int patloc; int c; int set; int special; int startloc; int varlen; int varlenb; int easy; - int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); + int quotes = flag & (EXP_FULL | EXP_CASE); varflags = (unsigned char)*p++; subtype = varflags & VSTYPE; var = p; special = 0; if (! is_name(*p)) special = 1; p = strchr(p, '=') + 1; again: /* jump here after setting a variable with ${var=text} */ if (varflags & VSLINENO) { set = 1; special = 1; val = NULL; } else if (special) { set = varisset(var, varflags & VSNUL); val = NULL; } else { val = bltinlookup(var, 1); if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) { val = NULL; set = 0; } else set = 1; } varlen = 0; startloc = expdest - stackblock(); if (!set && uflag && *var != '@' && *var != '*') { switch (subtype) { case VSNORMAL: case VSTRIMLEFT: case VSTRIMLEFTMAX: case VSTRIMRIGHT: case VSTRIMRIGHTMAX: case VSLENGTH: error("%.*s: parameter not set", (int)(p - var - 1), var); } } if (set && subtype != VSPLUS) { /* insert the value of the variable */ if (special) { if (varflags & VSLINENO) STPUTBIN(var, p - var - 1, expdest); else varvalue(var, varflags & VSQUOTE, subtype, flag); if (subtype == VSLENGTH) { varlenb = expdest - stackblock() - startloc; varlen = varlenb; if (localeisutf8) { val = stackblock() + startloc; for (;val != expdest; val++) if ((*val & 0xC0) == 0x80) varlen--; } STADJUST(-varlenb, expdest); } } else { char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX : BASESYNTAX; if (subtype == VSLENGTH) { for (;*val; val++) if (!localeisutf8 || (*val & 0xC0) != 0x80) varlen++; } else { if (quotes) STPUTS_QUOTES(val, syntax, expdest); else STPUTS(val, expdest); } } } if (subtype == VSPLUS) set = ! set; easy = ((varflags & VSQUOTE) == 0 || (*var == '@' && shellparam.nparam != 1)); switch (subtype) { case VSLENGTH: expdest = cvtnum(varlen, expdest); goto record; case VSNORMAL: if (!easy) break; record: recordregion(startloc, expdest - stackblock(), varflags & VSQUOTE || (ifsset() && ifsval()[0] == '\0' && (*var == '@' || *var == '*'))); break; case VSPLUS: case VSMINUS: if (!set) { argstr(p, flag | (flag & EXP_FULL ? EXP_SPLIT_LIT : 0) | (varflags & VSQUOTE ? EXP_LIT_QUOTED : 0)); break; } if (easy) goto record; break; case VSTRIMLEFT: case VSTRIMLEFTMAX: case VSTRIMRIGHT: case VSTRIMRIGHTMAX: if (!set) break; /* * Terminate the string and start recording the pattern * right after it */ STPUTC('\0', expdest); patloc = expdest - stackblock(); if (subevalvar(p, NULL, patloc, subtype, startloc, varflags, quotes) == 0) { int amount = (expdest - stackblock() - patloc) + 1; STADJUST(-amount, expdest); } /* Remove any recorded regions beyond start of variable */ removerecordregions(startloc); goto record; case VSASSIGN: case VSQUESTION: if (!set) { if (subevalvar(p, var, 0, subtype, startloc, varflags, quotes)) { varflags &= ~VSNUL; /* * Remove any recorded regions beyond * start of variable */ removerecordregions(startloc); goto again; } break; } if (easy) goto record; break; case VSERROR: c = p - var - 1; error("${%.*s%s}: Bad substitution", c, var, (c > 0 && *p != CTLENDVAR) ? "..." : ""); default: abort(); } if (subtype != VSNORMAL) { /* skip to end of alternative */ int nesting = 1; for (;;) { if ((c = *p++) == CTLESC) p++; else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) { if (set) argbackq = argbackq->next; } else if (c == CTLVAR) { if ((*p++ & VSTYPE) != VSNORMAL) nesting++; } else if (c == CTLENDVAR) { if (--nesting == 0) break; } } } return p; } /* * Test whether a specialized variable is set. */ static int varisset(const char *name, int nulok) { if (*name == '!') return backgndpidset(); else if (*name == '@' || *name == '*') { if (*shellparam.p == NULL) return 0; if (nulok) { char **av; for (av = shellparam.p; *av; av++) if (**av != '\0') return 1; return 0; } } else if (is_digit(*name)) { char *ap; long num; errno = 0; num = strtol(name, NULL, 10); if (errno != 0 || num > shellparam.nparam) return 0; if (num == 0) ap = arg0; else ap = shellparam.p[num - 1]; if (nulok && (ap == NULL || *ap == '\0')) return 0; } return 1; } static void strtodest(const char *p, int flag, int subtype, int quoted) { - if (flag & (EXP_FULL | EXP_CASE | EXP_REDIR) && subtype != VSLENGTH) + if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH) STPUTS_QUOTES(p, quoted ? DQSYNTAX : BASESYNTAX, expdest); else STPUTS(p, expdest); } /* * Add the value of a specialized variable to the stack string. */ static void varvalue(const char *name, int quoted, int subtype, int flag) { int num; char *p; int i; char sep[2]; char **ap; switch (*name) { case '$': num = rootpid; break; case '?': num = oexitstatus; break; case '#': num = shellparam.nparam; break; case '!': num = backgndpidval(); break; case '-': for (i = 0 ; i < NOPTS ; i++) { if (optlist[i].val) STPUTC(optlist[i].letter, expdest); } return; case '@': if (flag & EXP_FULL && quoted) { for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { strtodest(p, flag, subtype, quoted); if (*ap) STPUTC('\0', expdest); } return; } /* FALLTHROUGH */ case '*': if (ifsset()) sep[0] = ifsval()[0]; else sep[0] = ' '; sep[1] = '\0'; for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { strtodest(p, flag, subtype, quoted); if (!*ap) break; if (sep[0]) strtodest(sep, flag, subtype, quoted); else if (flag & EXP_FULL && !quoted && **ap != '\0') STPUTC('\0', expdest); } return; default: if (is_digit(*name)) { num = atoi(name); if (num == 0) p = arg0; else if (num > 0 && num <= shellparam.nparam) p = shellparam.p[num - 1]; else return; strtodest(p, flag, subtype, quoted); } return; } expdest = cvtnum(num, expdest); } /* * Record the fact that we have to scan this region of the * string for IFS characters. */ static void recordregion(int start, int end, int inquotes) { struct ifsregion *ifsp; INTOFF; if (ifslastp == NULL) { ifsp = &ifsfirst; } else { if (ifslastp->endoff == start && ifslastp->inquotes == inquotes) { /* extend previous area */ ifslastp->endoff = end; INTON; return; } ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion)); ifslastp->next = ifsp; } ifslastp = ifsp; ifslastp->next = NULL; ifslastp->begoff = start; ifslastp->endoff = end; ifslastp->inquotes = inquotes; INTON; } /* * Break the argument string into pieces based upon IFS and add the * strings to the argument list. The regions of the string to be * searched for IFS characters have been stored by recordregion. * CTLESC characters are preserved but have little effect in this pass * other than escaping CTL* characters. In particular, they do not escape * IFS characters: that should be done with the ifsregion mechanism. * CTLQUOTEMARK characters are used to preserve empty quoted strings. * This pass treats them as a regular character, making the string non-empty. * Later, they are removed along with the other CTL* characters. */ static void ifsbreakup(char *string, struct arglist *arglist) { struct ifsregion *ifsp; struct strlist *sp; char *start; char *p; char *q; const char *ifs; const char *ifsspc; int had_param_ch = 0; start = string; if (ifslastp == NULL) { /* Return entire argument, IFS doesn't apply to any of it */ sp = (struct strlist *)stalloc(sizeof *sp); sp->text = start; *arglist->lastp = sp; arglist->lastp = &sp->next; return; } ifs = ifsset() ? ifsval() : " \t\n"; for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) { p = string + ifsp->begoff; while (p < string + ifsp->endoff) { q = p; if (*p == CTLESC) p++; if (ifsp->inquotes) { /* Only NULs (should be from "$@") end args */ had_param_ch = 1; if (*p != 0) { p++; continue; } ifsspc = NULL; } else { if (!strchr(ifs, *p)) { had_param_ch = 1; p++; continue; } ifsspc = strchr(" \t\n", *p); /* Ignore IFS whitespace at start */ if (q == start && ifsspc != NULL) { p++; start = p; continue; } had_param_ch = 0; } /* Save this argument... */ *q = '\0'; sp = (struct strlist *)stalloc(sizeof *sp); sp->text = start; *arglist->lastp = sp; arglist->lastp = &sp->next; p++; if (ifsspc != NULL) { /* Ignore further trailing IFS whitespace */ for (; p < string + ifsp->endoff; p++) { q = p; if (*p == CTLESC) p++; if (strchr(ifs, *p) == NULL) { p = q; break; } if (strchr(" \t\n", *p) == NULL) { p++; break; } } } start = p; } } /* * Save anything left as an argument. * Traditionally we have treated 'IFS=':'; set -- x$IFS' as * generating 2 arguments, the second of which is empty. * Some recent clarification of the Posix spec say that it * should only generate one.... */ if (had_param_ch || *start != 0) { sp = (struct strlist *)stalloc(sizeof *sp); sp->text = start; *arglist->lastp = sp; arglist->lastp = &sp->next; } } static char expdir[PATH_MAX]; #define expdir_end (expdir + sizeof(expdir)) /* * Perform pathname generation and remove control characters. * At this point, the only control characters should be CTLESC and CTLQUOTEMARK. * The results are stored in the list exparg. */ static void expandmeta(struct strlist *str, int flag __unused) { char *p; struct strlist **savelastp; struct strlist *sp; char c; - /* TODO - EXP_REDIR */ while (str) { savelastp = exparg.lastp; if (!fflag) { p = str->text; for (; (c = *p) != '\0'; p++) { /* fast check for meta chars */ if (c == '*' || c == '?' || c == '[') { INTOFF; expmeta(expdir, str->text); INTON; break; } } } if (exparg.lastp == savelastp) { /* * no matches */ *exparg.lastp = str; rmescapes(str->text); exparg.lastp = &str->next; } else { *exparg.lastp = NULL; *savelastp = sp = expsort(*savelastp); while (sp->next != NULL) sp = sp->next; exparg.lastp = &sp->next; } str = str->next; } } /* * Do metacharacter (i.e. *, ?, [...]) expansion. */ static void expmeta(char *enddir, char *name) { const char *p; const char *q; const char *start; char *endname; int metaflag; struct stat statb; DIR *dirp; struct dirent *dp; int atend; int matchdot; int esc; int namlen; metaflag = 0; start = name; for (p = name; esc = 0, *p; p += esc + 1) { if (*p == '*' || *p == '?') metaflag = 1; else if (*p == '[') { q = p + 1; if (*q == '!' || *q == '^') q++; for (;;) { while (*q == CTLQUOTEMARK) q++; if (*q == CTLESC) q++; if (*q == '/' || *q == '\0') break; if (*++q == ']') { metaflag = 1; break; } } } else if (*p == '\0') break; else if (*p == CTLQUOTEMARK) continue; else { if (*p == CTLESC) esc++; if (p[esc] == '/') { if (metaflag) break; start = p + esc + 1; } } } if (metaflag == 0) { /* we've reached the end of the file name */ if (enddir != expdir) metaflag++; for (p = name ; ; p++) { if (*p == CTLQUOTEMARK) continue; if (*p == CTLESC) p++; *enddir++ = *p; if (*p == '\0') break; if (enddir == expdir_end) return; } if (metaflag == 0 || lstat(expdir, &statb) >= 0) addfname(expdir); return; } endname = name + (p - name); if (start != name) { p = name; while (p < start) { while (*p == CTLQUOTEMARK) p++; if (*p == CTLESC) p++; *enddir++ = *p++; if (enddir == expdir_end) return; } } if (enddir == expdir) { p = "."; } else if (enddir == expdir + 1 && *expdir == '/') { p = "/"; } else { p = expdir; enddir[-1] = '\0'; } if ((dirp = opendir(p)) == NULL) return; if (enddir != expdir) enddir[-1] = '/'; if (*endname == 0) { atend = 1; } else { atend = 0; *endname = '\0'; endname += esc + 1; } matchdot = 0; p = start; while (*p == CTLQUOTEMARK) p++; if (*p == CTLESC) p++; if (*p == '.') matchdot++; while (! int_pending() && (dp = readdir(dirp)) != NULL) { if (dp->d_name[0] == '.' && ! matchdot) continue; if (patmatch(start, dp->d_name, 0)) { namlen = dp->d_namlen; if (enddir + namlen + 1 > expdir_end) continue; memcpy(enddir, dp->d_name, namlen + 1); if (atend) addfname(expdir); else { if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_DIR && dp->d_type != DT_LNK) continue; if (enddir + namlen + 2 > expdir_end) continue; enddir[namlen] = '/'; enddir[namlen + 1] = '\0'; expmeta(enddir + namlen + 1, endname); } } } closedir(dirp); if (! atend) endname[-esc - 1] = esc ? CTLESC : '/'; } /* * Add a file name to the list. */ static void addfname(char *name) { char *p; struct strlist *sp; size_t len; len = strlen(name); p = stalloc(len + 1); memcpy(p, name, len + 1); sp = (struct strlist *)stalloc(sizeof *sp); sp->text = p; *exparg.lastp = sp; exparg.lastp = &sp->next; } /* * Sort the results of file name expansion. It calculates the number of * strings to sort and then calls msort (short for merge sort) to do the * work. */ static struct strlist * expsort(struct strlist *str) { int len; struct strlist *sp; len = 0; for (sp = str ; sp ; sp = sp->next) len++; return msort(str, len); } static struct strlist * msort(struct strlist *list, int len) { struct strlist *p, *q = NULL; struct strlist **lpp; int half; int n; if (len <= 1) return list; half = len >> 1; p = list; for (n = half ; --n >= 0 ; ) { q = p; p = p->next; } q->next = NULL; /* terminate first half of list */ q = msort(list, half); /* sort first half of list */ p = msort(p, len - half); /* sort second half */ lpp = &list; for (;;) { if (strcmp(p->text, q->text) < 0) { *lpp = p; lpp = &p->next; if ((p = *lpp) == NULL) { *lpp = q; break; } } else { *lpp = q; lpp = &q->next; if ((q = *lpp) == NULL) { *lpp = p; break; } } } return list; } static wchar_t get_wc(const char **p) { wchar_t c; int chrlen; chrlen = mbtowc(&c, *p, 4); if (chrlen == 0) return 0; else if (chrlen == -1) c = 0; else *p += chrlen; return c; } /* * See if a character matches a character class, starting at the first colon * of "[:class:]". * If a valid character class is recognized, a pointer to the next character * after the final closing bracket is stored into *end, otherwise a null * pointer is stored into *end. */ static int match_charclass(const char *p, wchar_t chr, const char **end) { char name[20]; const char *nameend; wctype_t cclass; *end = NULL; p++; nameend = strstr(p, ":]"); if (nameend == NULL || (size_t)(nameend - p) >= sizeof(name) || nameend == p) return 0; memcpy(name, p, nameend - p); name[nameend - p] = '\0'; *end = nameend + 2; cclass = wctype(name); /* An unknown class matches nothing but is valid nevertheless. */ if (cclass == 0) return 0; return iswctype(chr, cclass); } /* * Returns true if the pattern matches the string. */ static int patmatch(const char *pattern, const char *string, int squoted) { const char *p, *q, *end; const char *bt_p, *bt_q; char c; wchar_t wc, wc2; p = pattern; q = string; bt_p = NULL; bt_q = NULL; for (;;) { switch (c = *p++) { case '\0': if (*q != '\0') goto backtrack; return 1; case CTLESC: if (squoted && *q == CTLESC) q++; if (*q++ != *p++) goto backtrack; break; case CTLQUOTEMARK: continue; case '?': if (squoted && *q == CTLESC) q++; if (*q == '\0') return 0; if (localeisutf8) { wc = get_wc(&q); /* * A '?' does not match invalid UTF-8 but a * '*' does, so backtrack. */ if (wc == 0) goto backtrack; } else wc = (unsigned char)*q++; break; case '*': c = *p; while (c == CTLQUOTEMARK || c == '*') c = *++p; /* * If the pattern ends here, we know the string * matches without needing to look at the rest of it. */ if (c == '\0') return 1; /* * First try the shortest match for the '*' that * could work. We can forget any earlier '*' since * there is no way having it match more characters * can help us, given that we are already here. */ bt_p = p; bt_q = q; break; case '[': { const char *endp; int invert, found; wchar_t chr; endp = p; if (*endp == '!' || *endp == '^') endp++; for (;;) { while (*endp == CTLQUOTEMARK) endp++; if (*endp == 0) goto dft; /* no matching ] */ if (*endp == CTLESC) endp++; if (*++endp == ']') break; } invert = 0; if (*p == '!' || *p == '^') { invert++; p++; } found = 0; if (squoted && *q == CTLESC) q++; if (*q == '\0') return 0; if (localeisutf8) { chr = get_wc(&q); if (chr == 0) goto backtrack; } else chr = (unsigned char)*q++; c = *p++; do { if (c == CTLQUOTEMARK) continue; if (c == '[' && *p == ':') { found |= match_charclass(p, chr, &end); if (end != NULL) p = end; } if (c == CTLESC) c = *p++; if (localeisutf8 && c & 0x80) { p--; wc = get_wc(&p); if (wc == 0) /* bad utf-8 */ return 0; } else wc = (unsigned char)c; if (*p == '-' && p[1] != ']') { p++; while (*p == CTLQUOTEMARK) p++; if (*p == CTLESC) p++; if (localeisutf8) { wc2 = get_wc(&p); if (wc2 == 0) /* bad utf-8 */ return 0; } else wc2 = (unsigned char)*p++; if ( collate_range_cmp(chr, wc) >= 0 && collate_range_cmp(chr, wc2) <= 0 ) found = 1; } else { if (chr == wc) found = 1; } } while ((c = *p++) != ']'); if (found == invert) goto backtrack; break; } dft: default: if (squoted && *q == CTLESC) q++; if (*q == '\0') return 0; if (*q++ == c) break; backtrack: /* * If we have a mismatch (other than hitting the end * of the string), go back to the last '*' seen and * have it match one additional character. */ if (bt_p == NULL) return 0; if (squoted && *bt_q == CTLESC) bt_q++; if (*bt_q == '\0') return 0; bt_q++; p = bt_p; q = bt_q; break; } } } /* * Remove any CTLESC and CTLQUOTEMARK characters from a string. */ void rmescapes(char *str) { char *p, *q; p = str; while (*p != CTLESC && *p != CTLQUOTEMARK && *p != CTLQUOTEEND) { if (*p++ == '\0') return; } q = p; while (*p) { if (*p == CTLQUOTEMARK || *p == CTLQUOTEEND) { p++; continue; } if (*p == CTLESC) p++; *q++ = *p++; } *q = '\0'; } /* * See if a pattern matches in a case statement. */ int casematch(union node *pattern, const char *val) { struct stackmark smark; int result; char *p; setstackmark(&smark); argbackq = pattern->narg.backquote; STARTSTACKSTR(expdest); ifslastp = NULL; argstr(pattern->narg.text, EXP_TILDE | EXP_CASE); STPUTC('\0', expdest); p = grabstackstr(expdest); result = patmatch(p, val, 0); popstackmark(&smark); return result; } /* * Our own itoa(). */ static char * cvtnum(int num, char *buf) { char temp[32]; int neg = num < 0; char *p = temp + 31; temp[31] = '\0'; do { *--p = num % 10 + '0'; } while ((num /= 10) != 0); if (neg) *--p = '-'; STPUTS(p, buf); return buf; } /* * Do most of the work for wordexp(3). */ int wordexpcmd(int argc, char **argv) { size_t len; int i; out1fmt("%08x", argc - 1); for (i = 1, len = 0; i < argc; i++) len += strlen(argv[i]); out1fmt("%08x", (int)len); for (i = 1; i < argc; i++) outbin(argv[i], strlen(argv[i]) + 1, out1); return (0); } Index: projects/sendfile/bin/sh/expand.h =================================================================== --- projects/sendfile/bin/sh/expand.h (revision 276056) +++ projects/sendfile/bin/sh/expand.h (revision 276057) @@ -1,62 +1,61 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * 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. * * @(#)expand.h 8.2 (Berkeley) 5/4/95 * $FreeBSD$ */ struct strlist { struct strlist *next; char *text; }; struct arglist { struct strlist *list; struct strlist **lastp; }; /* * expandarg() flags */ #define EXP_FULL 0x1 /* perform word splitting & file globbing */ #define EXP_TILDE 0x2 /* do normal tilde expansion */ #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */ -#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */ #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */ #define EXP_SPLIT_LIT 0x20 /* IFS split literal text ${v+-a b c} */ #define EXP_LIT_QUOTED 0x40 /* for EXP_SPLIT_LIT, start off quoted */ union node; void expandarg(union node *, struct arglist *, int); void rmescapes(char *); int casematch(union node *, const char *); Index: projects/sendfile/bin/sh/trap.c =================================================================== --- projects/sendfile/bin/sh/trap.c (revision 276056) +++ projects/sendfile/bin/sh/trap.c (revision 276057) @@ -1,542 +1,550 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * 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. */ #ifndef lint #if 0 static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); #include #include #include #include "shell.h" #include "main.h" #include "nodes.h" /* for other headers */ #include "eval.h" #include "jobs.h" #include "show.h" #include "options.h" #include "syntax.h" #include "output.h" #include "memalloc.h" #include "error.h" #include "trap.h" #include "mystring.h" #include "builtins.h" #include "myhistedit.h" /* * Sigmode records the current value of the signal handlers for the various * modes. A value of zero means that the current handler is not known. * S_HARD_IGN indicates that the signal was ignored on entry to the shell, */ #define S_DFL 1 /* default signal handling (SIG_DFL) */ #define S_CATCH 2 /* signal is caught */ #define S_IGN 3 /* signal is ignored (SIG_IGN) */ #define S_HARD_IGN 4 /* signal is ignored permanently */ #define S_RESET 5 /* temporary - to reset a hard ignored sig */ static char sigmode[NSIG]; /* current value of signal */ volatile sig_atomic_t pendingsig; /* indicates some signal received */ volatile sig_atomic_t pendingsig_waitcmd; /* indicates SIGINT/SIGQUIT received */ -int in_dotrap; /* do we execute in a trap handler? */ +static int in_dotrap; /* do we execute in a trap handler? */ static char *volatile trap[NSIG]; /* trap handler commands */ static volatile sig_atomic_t gotsig[NSIG]; /* indicates specified signal received */ static int ignore_sigchld; /* Used while handling SIGCHLD traps. */ static int last_trapsig; static int exiting; /* exitshell() has been called */ static int exiting_exitstatus; /* value passed to exitshell() */ static int getsigaction(int, sig_t *); /* * Map a string to a signal number. * * Note: the signal number may exceed NSIG. */ static int sigstring_to_signum(char *sig) { if (is_number(sig)) { int signo; signo = atoi(sig); return ((signo >= 0 && signo < NSIG) ? signo : (-1)); } else if (strcasecmp(sig, "EXIT") == 0) { return (0); } else { int n; if (strncasecmp(sig, "SIG", 3) == 0) sig += 3; for (n = 1; n < sys_nsig; n++) if (sys_signame[n] && strcasecmp(sys_signame[n], sig) == 0) return (n); } return (-1); } /* * Print a list of valid signal names. */ static void printsignals(void) { int n, outlen; outlen = 0; for (n = 1; n < sys_nsig; n++) { if (sys_signame[n]) { out1fmt("%s", sys_signame[n]); outlen += strlen(sys_signame[n]); } else { out1fmt("%d", n); outlen += 3; /* good enough */ } ++outlen; if (outlen > 71 || n == sys_nsig - 1) { out1str("\n"); outlen = 0; } else { out1c(' '); } } } /* * The trap builtin. */ int trapcmd(int argc __unused, char **argv) { char *action; int signo; int errors = 0; int i; while ((i = nextopt("l")) != '\0') { switch (i) { case 'l': printsignals(); return (0); } } argv = argptr; if (*argv == NULL) { for (signo = 0 ; signo < sys_nsig ; signo++) { if (signo < NSIG && trap[signo] != NULL) { out1str("trap -- "); out1qstr(trap[signo]); if (signo == 0) { out1str(" EXIT\n"); } else if (sys_signame[signo]) { out1fmt(" %s\n", sys_signame[signo]); } else { out1fmt(" %d\n", signo); } } } return 0; } action = NULL; if (*argv && sigstring_to_signum(*argv) == -1) { if (strcmp(*argv, "-") == 0) argv++; else { action = *argv; argv++; } } for (; *argv; argv++) { if ((signo = sigstring_to_signum(*argv)) == -1) { warning("bad signal %s", *argv); errors = 1; continue; } INTOFF; if (action) action = savestr(action); if (trap[signo]) ckfree(trap[signo]); trap[signo] = action; if (signo != 0) setsignal(signo); INTON; } return errors; } /* * Clear traps on a fork. */ void clear_traps(void) { char *volatile *tp; for (tp = trap ; tp <= &trap[NSIG - 1] ; tp++) { if (*tp && **tp) { /* trap not NULL or SIG_IGN */ INTOFF; ckfree(*tp); *tp = NULL; if (tp != &trap[0]) setsignal(tp - trap); INTON; } } } /* * Check if we have any traps enabled. */ int have_traps(void) { char *volatile *tp; for (tp = trap ; tp <= &trap[NSIG - 1] ; tp++) { if (*tp && **tp) /* trap not NULL or SIG_IGN */ return 1; } return 0; } /* * Set the signal handler for the specified signal. The routine figures * out what it should be set to. */ void setsignal(int signo) { int action; sig_t sigact = SIG_DFL; struct sigaction sa; char *t; if ((t = trap[signo]) == NULL) action = S_DFL; else if (*t != '\0') action = S_CATCH; else action = S_IGN; if (action == S_DFL) { switch (signo) { case SIGINT: action = S_CATCH; break; case SIGQUIT: #ifdef DEBUG { extern int debug; if (debug) break; } #endif action = S_CATCH; break; case SIGTERM: if (rootshell && iflag) action = S_IGN; break; #if JOBS case SIGTSTP: case SIGTTOU: if (rootshell && mflag) action = S_IGN; break; #endif } } t = &sigmode[signo]; if (*t == 0) { /* * current setting unknown */ if (!getsigaction(signo, &sigact)) { /* * Pretend it worked; maybe we should give a warning * here, but other shells don't. We don't alter * sigmode, so that we retry every time. */ return; } if (sigact == SIG_IGN) { if (mflag && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)) { *t = S_IGN; /* don't hard ignore these */ } else *t = S_HARD_IGN; } else { *t = S_RESET; /* force to be set */ } } if (*t == S_HARD_IGN || *t == action) return; switch (action) { case S_DFL: sigact = SIG_DFL; break; case S_CATCH: sigact = onsig; break; case S_IGN: sigact = SIG_IGN; break; } *t = action; sa.sa_handler = sigact; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(signo, &sa, NULL); } /* * Return the current setting for sig w/o changing it. */ static int getsigaction(int signo, sig_t *sigact) { struct sigaction sa; if (sigaction(signo, (struct sigaction *)0, &sa) == -1) return 0; *sigact = (sig_t) sa.sa_handler; return 1; } /* * Ignore a signal. */ void ignoresig(int signo) { if (sigmode[signo] == 0) setsignal(signo); if (sigmode[signo] != S_IGN && sigmode[signo] != S_HARD_IGN) { signal(signo, SIG_IGN); sigmode[signo] = S_IGN; } } int issigchldtrapped(void) { return (trap[SIGCHLD] != NULL && *trap[SIGCHLD] != '\0'); } /* * Signal handler. */ void onsig(int signo) { if (signo == SIGINT && trap[SIGINT] == NULL) { - onint(); + /* + * The !in_dotrap here is safe. The only way we can arrive + * here with in_dotrap set is that a trap handler set SIGINT to + * SIG_DFL and killed itself. + */ + if (suppressint && !in_dotrap) + SET_PENDING_INT; + else + onint(); return; } /* If we are currently in a wait builtin, prepare to break it */ if (signo == SIGINT || signo == SIGQUIT) pendingsig_waitcmd = signo; if (trap[signo] != NULL && trap[signo][0] != '\0' && (signo != SIGCHLD || !ignore_sigchld)) { gotsig[signo] = 1; pendingsig = signo; } } /* * Called to execute a trap. Perhaps we should avoid entering new trap * handlers while we are executing a trap handler. */ void dotrap(void) { int i; int savestatus, prev_evalskip, prev_skipcount; in_dotrap++; for (;;) { pendingsig = 0; pendingsig_waitcmd = 0; for (i = 1; i < NSIG; i++) { if (gotsig[i]) { gotsig[i] = 0; if (trap[i]) { /* * Ignore SIGCHLD to avoid infinite * recursion if the trap action does * a fork. */ if (i == SIGCHLD) ignore_sigchld++; /* * Backup current evalskip * state and reset it before * executing a trap, so that the * trap is not disturbed by an * ongoing break/continue/return * statement. */ prev_evalskip = evalskip; prev_skipcount = skipcount; evalskip = 0; last_trapsig = i; savestatus = exitstatus; evalstring(trap[i], 0); /* * If such a command was not * already in progress, allow a * break/continue/return in the * trap action to have an effect * outside of it. */ if (evalskip == 0 || prev_evalskip != 0) { evalskip = prev_evalskip; skipcount = prev_skipcount; exitstatus = savestatus; } if (i == SIGCHLD) ignore_sigchld--; } break; } } if (i >= NSIG) break; } in_dotrap--; } /* * Controls whether the shell is interactive or not. */ void setinteractive(int on) { static int is_interactive = -1; if (on == is_interactive) return; setsignal(SIGINT); setsignal(SIGQUIT); setsignal(SIGTERM); is_interactive = on; } /* * Called to exit the shell. */ void exitshell(int status) { TRACE(("exitshell(%d) pid=%d\n", status, getpid())); exiting = 1; exiting_exitstatus = status; exitshell_savedstatus(); } void exitshell_savedstatus(void) { struct jmploc loc1, loc2; char *p; int sig = 0; sigset_t sigs; if (!exiting) { if (in_dotrap && last_trapsig) { sig = last_trapsig; exiting_exitstatus = sig + 128; } else exiting_exitstatus = oexitstatus; } exitstatus = oexitstatus = exiting_exitstatus; if (!setjmp(loc1.loc)) { handler = &loc1; if ((p = trap[0]) != NULL && *p != '\0') { /* * Reset evalskip, or the trap on EXIT could be * interrupted if the last command was a "return". */ evalskip = 0; trap[0] = NULL; evalstring(p, 0); } } if (!setjmp(loc2.loc)) { handler = &loc2; /* probably unnecessary */ flushall(); #if JOBS setjobctl(0); #endif } if (sig != 0 && sig != SIGSTOP && sig != SIGTSTP && sig != SIGTTIN && sig != SIGTTOU) { signal(sig, SIG_DFL); sigemptyset(&sigs); sigaddset(&sigs, sig); sigprocmask(SIG_UNBLOCK, &sigs, NULL); kill(getpid(), sig); /* If the default action is to ignore, fall back to _exit(). */ } _exit(exiting_exitstatus); } Index: projects/sendfile/bin/sh/trap.h =================================================================== --- projects/sendfile/bin/sh/trap.h (revision 276056) +++ projects/sendfile/bin/sh/trap.h (revision 276057) @@ -1,49 +1,48 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * 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. * * @(#)trap.h 8.3 (Berkeley) 6/5/95 * $FreeBSD$ */ extern volatile sig_atomic_t pendingsig; extern volatile sig_atomic_t pendingsig_waitcmd; -extern int in_dotrap; void clear_traps(void); int have_traps(void); void setsignal(int); void ignoresig(int); int issigchldtrapped(void); void onsig(int); void dotrap(void); void setinteractive(int); void exitshell(int) __dead2; void exitshell_savedstatus(void) __dead2; Index: projects/sendfile/contrib/gcc/config/arm/arm.c =================================================================== --- projects/sendfile/contrib/gcc/config/arm/arm.c (revision 276056) +++ projects/sendfile/contrib/gcc/config/arm/arm.c (revision 276057) @@ -1,15748 +1,15750 @@ /* Output routines for GCC for ARM. Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) and Martin Simmons (@harleqn.co.uk). More major hacks by Richard Earnshaw (rearnsha@arm.com). This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "config.h" #include "system.h" #include "coretypes.h" #include "tm.h" #include "rtl.h" #include "tree.h" #include "obstack.h" #include "regs.h" #include "hard-reg-set.h" #include "real.h" #include "insn-config.h" #include "conditions.h" #include "output.h" #include "insn-attr.h" #include "flags.h" #include "reload.h" #include "function.h" #include "expr.h" #include "optabs.h" #include "toplev.h" #include "recog.h" #include "ggc.h" #include "except.h" #include "c-pragma.h" #include "integrate.h" #include "tm_p.h" #include "target.h" #include "target-def.h" #include "debug.h" #include "langhooks.h" /* Forward definitions of types. */ typedef struct minipool_node Mnode; typedef struct minipool_fixup Mfix; const struct attribute_spec arm_attribute_table[]; /* Forward function declarations. */ static arm_stack_offsets *arm_get_frame_offsets (void); static void arm_add_gc_roots (void); static int arm_gen_constant (enum rtx_code, enum machine_mode, rtx, HOST_WIDE_INT, rtx, rtx, int, int); static unsigned bit_count (unsigned long); static int arm_address_register_rtx_p (rtx, int); static int arm_legitimate_index_p (enum machine_mode, rtx, RTX_CODE, int); static int thumb_base_register_rtx_p (rtx, enum machine_mode, int); inline static int thumb_index_register_rtx_p (rtx, int); static int thumb_far_jump_used_p (void); static bool thumb_force_lr_save (void); static int const_ok_for_op (HOST_WIDE_INT, enum rtx_code); static rtx emit_sfm (int, int); static int arm_size_return_regs (void); #ifndef AOF_ASSEMBLER static bool arm_assemble_integer (rtx, unsigned int, int); #endif static const char *fp_const_from_val (REAL_VALUE_TYPE *); static arm_cc get_arm_condition_code (rtx); static HOST_WIDE_INT int_log2 (HOST_WIDE_INT); static rtx is_jump_table (rtx); static const char *output_multi_immediate (rtx *, const char *, const char *, int, HOST_WIDE_INT); static const char *shift_op (rtx, HOST_WIDE_INT *); static struct machine_function *arm_init_machine_status (void); static void thumb_exit (FILE *, int); static rtx is_jump_table (rtx); static HOST_WIDE_INT get_jump_table_size (rtx); static Mnode *move_minipool_fix_forward_ref (Mnode *, Mnode *, HOST_WIDE_INT); static Mnode *add_minipool_forward_ref (Mfix *); static Mnode *move_minipool_fix_backward_ref (Mnode *, Mnode *, HOST_WIDE_INT); static Mnode *add_minipool_backward_ref (Mfix *); static void assign_minipool_offsets (Mfix *); static void arm_print_value (FILE *, rtx); static void dump_minipool (rtx); static int arm_barrier_cost (rtx); static Mfix *create_fix_barrier (Mfix *, HOST_WIDE_INT); static void push_minipool_barrier (rtx, HOST_WIDE_INT); static void push_minipool_fix (rtx, HOST_WIDE_INT, rtx *, enum machine_mode, rtx); static void arm_reorg (void); static bool note_invalid_constants (rtx, HOST_WIDE_INT, int); static int current_file_function_operand (rtx); static unsigned long arm_compute_save_reg0_reg12_mask (void); static unsigned long arm_compute_save_reg_mask (void); static unsigned long arm_isr_value (tree); static unsigned long arm_compute_func_type (void); static tree arm_handle_fndecl_attribute (tree *, tree, tree, int, bool *); static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *); #if TARGET_DLLIMPORT_DECL_ATTRIBUTES static tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *); #endif static void arm_output_function_epilogue (FILE *, HOST_WIDE_INT); static void arm_output_function_prologue (FILE *, HOST_WIDE_INT); static void thumb_output_function_prologue (FILE *, HOST_WIDE_INT); static int arm_comp_type_attributes (tree, tree); static void arm_set_default_type_attributes (tree); static int arm_adjust_cost (rtx, rtx, rtx, int); static int count_insns_for_constant (HOST_WIDE_INT, int); static int arm_get_strip_length (int); static bool arm_function_ok_for_sibcall (tree, tree); static void arm_internal_label (FILE *, const char *, unsigned long); static void arm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree); static int arm_rtx_costs_1 (rtx, enum rtx_code, enum rtx_code); static bool arm_size_rtx_costs (rtx, int, int, int *); static bool arm_slowmul_rtx_costs (rtx, int, int, int *); static bool arm_fastmul_rtx_costs (rtx, int, int, int *); static bool arm_xscale_rtx_costs (rtx, int, int, int *); static bool arm_9e_rtx_costs (rtx, int, int, int *); static int arm_address_cost (rtx); static bool arm_memory_load_p (rtx); static bool arm_cirrus_insn_p (rtx); static void cirrus_reorg (rtx); static void arm_init_builtins (void); static rtx arm_expand_builtin (tree, rtx, rtx, enum machine_mode, int); static void arm_init_iwmmxt_builtins (void); static rtx safe_vector_operand (rtx, enum machine_mode); static rtx arm_expand_binop_builtin (enum insn_code, tree, rtx); static rtx arm_expand_unop_builtin (enum insn_code, tree, rtx, int); static rtx arm_expand_builtin (tree, rtx, rtx, enum machine_mode, int); static void emit_constant_insn (rtx cond, rtx pattern); static rtx emit_set_insn (rtx, rtx); static int arm_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, tree, bool); #ifdef OBJECT_FORMAT_ELF static void arm_elf_asm_constructor (rtx, int); #endif #ifndef ARM_PE static void arm_encode_section_info (tree, rtx, int); #endif static void arm_file_end (void); static void arm_file_start (void); #ifdef AOF_ASSEMBLER static void aof_globalize_label (FILE *, const char *); static void aof_dump_imports (FILE *); static void aof_dump_pic_table (FILE *); static void aof_file_start (void); static void aof_file_end (void); static void aof_asm_init_sections (void); #endif static void arm_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int); static bool arm_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, tree, bool); static bool arm_promote_prototypes (tree); static bool arm_default_short_enums (void); static bool arm_align_anon_bitfield (void); static bool arm_return_in_msb (tree); static bool arm_must_pass_in_stack (enum machine_mode, tree); #ifdef TARGET_UNWIND_INFO static void arm_unwind_emit (FILE *, rtx); static bool arm_output_ttype (rtx); #endif static tree arm_cxx_guard_type (void); static bool arm_cxx_guard_mask_bit (void); static tree arm_get_cookie_size (tree); static bool arm_cookie_has_size (void); static bool arm_cxx_cdtor_returns_this (void); static bool arm_cxx_key_method_may_be_inline (void); static void arm_cxx_determine_class_data_visibility (tree); static bool arm_cxx_class_data_always_comdat (void); static bool arm_cxx_use_aeabi_atexit (void); static void arm_init_libfuncs (void); static bool arm_handle_option (size_t, const char *, int); static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode); static bool arm_cannot_copy_insn_p (rtx); static bool arm_tls_symbol_p (rtx x); /* Initialize the GCC target structure. */ #if TARGET_DLLIMPORT_DECL_ATTRIBUTES #undef TARGET_MERGE_DECL_ATTRIBUTES #define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes #endif #undef TARGET_ATTRIBUTE_TABLE #define TARGET_ATTRIBUTE_TABLE arm_attribute_table #undef TARGET_ASM_FILE_START #define TARGET_ASM_FILE_START arm_file_start #undef TARGET_ASM_FILE_END #define TARGET_ASM_FILE_END arm_file_end #ifdef AOF_ASSEMBLER #undef TARGET_ASM_BYTE_OP #define TARGET_ASM_BYTE_OP "\tDCB\t" #undef TARGET_ASM_ALIGNED_HI_OP #define TARGET_ASM_ALIGNED_HI_OP "\tDCW\t" #undef TARGET_ASM_ALIGNED_SI_OP #define TARGET_ASM_ALIGNED_SI_OP "\tDCD\t" #undef TARGET_ASM_GLOBALIZE_LABEL #define TARGET_ASM_GLOBALIZE_LABEL aof_globalize_label #undef TARGET_ASM_FILE_START #define TARGET_ASM_FILE_START aof_file_start #undef TARGET_ASM_FILE_END #define TARGET_ASM_FILE_END aof_file_end #else #undef TARGET_ASM_ALIGNED_SI_OP #define TARGET_ASM_ALIGNED_SI_OP NULL #undef TARGET_ASM_INTEGER #define TARGET_ASM_INTEGER arm_assemble_integer #endif #undef TARGET_ASM_FUNCTION_PROLOGUE #define TARGET_ASM_FUNCTION_PROLOGUE arm_output_function_prologue #undef TARGET_ASM_FUNCTION_EPILOGUE #define TARGET_ASM_FUNCTION_EPILOGUE arm_output_function_epilogue #undef TARGET_DEFAULT_TARGET_FLAGS #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | MASK_SCHED_PROLOG) #undef TARGET_HANDLE_OPTION #define TARGET_HANDLE_OPTION arm_handle_option #undef TARGET_COMP_TYPE_ATTRIBUTES #define TARGET_COMP_TYPE_ATTRIBUTES arm_comp_type_attributes #undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES #define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES arm_set_default_type_attributes #undef TARGET_SCHED_ADJUST_COST #define TARGET_SCHED_ADJUST_COST arm_adjust_cost #undef TARGET_ENCODE_SECTION_INFO #ifdef ARM_PE #define TARGET_ENCODE_SECTION_INFO arm_pe_encode_section_info #else #define TARGET_ENCODE_SECTION_INFO arm_encode_section_info #endif #undef TARGET_STRIP_NAME_ENCODING #define TARGET_STRIP_NAME_ENCODING arm_strip_name_encoding #undef TARGET_ASM_INTERNAL_LABEL #define TARGET_ASM_INTERNAL_LABEL arm_internal_label #undef TARGET_FUNCTION_OK_FOR_SIBCALL #define TARGET_FUNCTION_OK_FOR_SIBCALL arm_function_ok_for_sibcall #undef TARGET_ASM_OUTPUT_MI_THUNK #define TARGET_ASM_OUTPUT_MI_THUNK arm_output_mi_thunk #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall /* This will be overridden in arm_override_options. */ #undef TARGET_RTX_COSTS #define TARGET_RTX_COSTS arm_slowmul_rtx_costs #undef TARGET_ADDRESS_COST #define TARGET_ADDRESS_COST arm_address_cost #undef TARGET_SHIFT_TRUNCATION_MASK #define TARGET_SHIFT_TRUNCATION_MASK arm_shift_truncation_mask #undef TARGET_VECTOR_MODE_SUPPORTED_P #define TARGET_VECTOR_MODE_SUPPORTED_P arm_vector_mode_supported_p #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG arm_reorg #undef TARGET_INIT_BUILTINS #define TARGET_INIT_BUILTINS arm_init_builtins #undef TARGET_EXPAND_BUILTIN #define TARGET_EXPAND_BUILTIN arm_expand_builtin #undef TARGET_INIT_LIBFUNCS #define TARGET_INIT_LIBFUNCS arm_init_libfuncs #undef TARGET_PROMOTE_FUNCTION_ARGS #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true #undef TARGET_PROMOTE_FUNCTION_RETURN #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES arm_promote_prototypes #undef TARGET_PASS_BY_REFERENCE #define TARGET_PASS_BY_REFERENCE arm_pass_by_reference #undef TARGET_ARG_PARTIAL_BYTES #define TARGET_ARG_PARTIAL_BYTES arm_arg_partial_bytes #undef TARGET_SETUP_INCOMING_VARARGS #define TARGET_SETUP_INCOMING_VARARGS arm_setup_incoming_varargs #undef TARGET_DEFAULT_SHORT_ENUMS #define TARGET_DEFAULT_SHORT_ENUMS arm_default_short_enums #undef TARGET_ALIGN_ANON_BITFIELD #define TARGET_ALIGN_ANON_BITFIELD arm_align_anon_bitfield #undef TARGET_NARROW_VOLATILE_BITFIELD #define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false #undef TARGET_CXX_GUARD_TYPE #define TARGET_CXX_GUARD_TYPE arm_cxx_guard_type #undef TARGET_CXX_GUARD_MASK_BIT #define TARGET_CXX_GUARD_MASK_BIT arm_cxx_guard_mask_bit #undef TARGET_CXX_GET_COOKIE_SIZE #define TARGET_CXX_GET_COOKIE_SIZE arm_get_cookie_size #undef TARGET_CXX_COOKIE_HAS_SIZE #define TARGET_CXX_COOKIE_HAS_SIZE arm_cookie_has_size #undef TARGET_CXX_CDTOR_RETURNS_THIS #define TARGET_CXX_CDTOR_RETURNS_THIS arm_cxx_cdtor_returns_this #undef TARGET_CXX_KEY_METHOD_MAY_BE_INLINE #define TARGET_CXX_KEY_METHOD_MAY_BE_INLINE arm_cxx_key_method_may_be_inline #undef TARGET_CXX_USE_AEABI_ATEXIT #define TARGET_CXX_USE_AEABI_ATEXIT arm_cxx_use_aeabi_atexit #undef TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY #define TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY \ arm_cxx_determine_class_data_visibility #undef TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT #define TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT arm_cxx_class_data_always_comdat #undef TARGET_RETURN_IN_MSB #define TARGET_RETURN_IN_MSB arm_return_in_msb #undef TARGET_MUST_PASS_IN_STACK #define TARGET_MUST_PASS_IN_STACK arm_must_pass_in_stack #ifdef TARGET_UNWIND_INFO #undef TARGET_UNWIND_EMIT #define TARGET_UNWIND_EMIT arm_unwind_emit /* EABI unwinding tables use a different format for the typeinfo tables. */ #undef TARGET_ASM_TTYPE #define TARGET_ASM_TTYPE arm_output_ttype #undef TARGET_ARM_EABI_UNWINDER #define TARGET_ARM_EABI_UNWINDER true #endif /* TARGET_UNWIND_INFO */ #undef TARGET_CANNOT_COPY_INSN_P #define TARGET_CANNOT_COPY_INSN_P arm_cannot_copy_insn_p #ifdef HAVE_AS_TLS #undef TARGET_HAVE_TLS #define TARGET_HAVE_TLS true #endif #undef TARGET_CANNOT_FORCE_CONST_MEM #define TARGET_CANNOT_FORCE_CONST_MEM arm_tls_referenced_p struct gcc_target targetm = TARGET_INITIALIZER; /* Obstack for minipool constant handling. */ static struct obstack minipool_obstack; static char * minipool_startobj; /* The maximum number of insns skipped which will be conditionalised if possible. */ static int max_insns_skipped = 5; extern FILE * asm_out_file; /* True if we are currently building a constant table. */ int making_const_table; /* Define the information needed to generate branch insns. This is stored from the compare operation. */ rtx arm_compare_op0, arm_compare_op1; /* The processor for which instructions should be scheduled. */ enum processor_type arm_tune = arm_none; /* The default processor used if not overriden by commandline. */ static enum processor_type arm_default_cpu = arm_none; /* Which floating point model to use. */ enum arm_fp_model arm_fp_model; /* Which floating point hardware is available. */ enum fputype arm_fpu_arch; /* Which floating point hardware to schedule for. */ enum fputype arm_fpu_tune; /* Whether to use floating point hardware. */ enum float_abi_type arm_float_abi; /* Which ABI to use. */ enum arm_abi_type arm_abi; /* Which thread pointer model to use. */ enum arm_tp_type target_thread_pointer = TP_AUTO; /* Used to parse -mstructure_size_boundary command line option. */ int arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY; /* Used for Thumb call_via trampolines. */ rtx thumb_call_via_label[14]; static int thumb_call_reg_needed; /* Bit values used to identify processor capabilities. */ #define FL_CO_PROC (1 << 0) /* Has external co-processor bus */ #define FL_ARCH3M (1 << 1) /* Extended multiply */ #define FL_MODE26 (1 << 2) /* 26-bit mode support */ #define FL_MODE32 (1 << 3) /* 32-bit mode support */ #define FL_ARCH4 (1 << 4) /* Architecture rel 4 */ #define FL_ARCH5 (1 << 5) /* Architecture rel 5 */ #define FL_THUMB (1 << 6) /* Thumb aware */ #define FL_LDSCHED (1 << 7) /* Load scheduling necessary */ #define FL_STRONG (1 << 8) /* StrongARM */ #define FL_ARCH5E (1 << 9) /* DSP extensions to v5 */ #define FL_XSCALE (1 << 10) /* XScale */ #define FL_CIRRUS (1 << 11) /* Cirrus/DSP. */ #define FL_ARCH6 (1 << 12) /* Architecture rel 6. Adds media instructions. */ #define FL_VFPV2 (1 << 13) /* Vector Floating Point V2. */ #define FL_WBUF (1 << 14) /* Schedule for write buffer ops. Note: ARM6 & 7 derivatives only. */ #define FL_ARCH6K (1 << 15) /* Architecture rel 6 K extensions. */ #define FL_IWMMXT (1 << 29) /* XScale v2 or "Intel Wireless MMX technology". */ #define FL_FOR_ARCH2 0 #define FL_FOR_ARCH3 FL_MODE32 #define FL_FOR_ARCH3M (FL_FOR_ARCH3 | FL_ARCH3M) #define FL_FOR_ARCH4 (FL_FOR_ARCH3M | FL_ARCH4) #define FL_FOR_ARCH4T (FL_FOR_ARCH4 | FL_THUMB) #define FL_FOR_ARCH5 (FL_FOR_ARCH4 | FL_ARCH5) #define FL_FOR_ARCH5T (FL_FOR_ARCH5 | FL_THUMB) #define FL_FOR_ARCH5E (FL_FOR_ARCH5 | FL_ARCH5E) #define FL_FOR_ARCH5TE (FL_FOR_ARCH5E | FL_THUMB) #define FL_FOR_ARCH5TEJ FL_FOR_ARCH5TE #define FL_FOR_ARCH6 (FL_FOR_ARCH5TE | FL_ARCH6) #define FL_FOR_ARCH6J FL_FOR_ARCH6 #define FL_FOR_ARCH6K (FL_FOR_ARCH6 | FL_ARCH6K) #define FL_FOR_ARCH6Z FL_FOR_ARCH6 #define FL_FOR_ARCH6ZK FL_FOR_ARCH6K /* The bits in this mask specify which instructions we are allowed to generate. */ static unsigned long insn_flags = 0; /* The bits in this mask specify which instruction scheduling options should be used. */ static unsigned long tune_flags = 0; /* The following are used in the arm.md file as equivalents to bits in the above two flag variables. */ /* Nonzero if this chip supports the ARM Architecture 3M extensions. */ int arm_arch3m = 0; /* Nonzero if this chip supports the ARM Architecture 4 extensions. */ int arm_arch4 = 0; /* Nonzero if this chip supports the ARM Architecture 4t extensions. */ int arm_arch4t = 0; /* Nonzero if this chip supports the ARM Architecture 5 extensions. */ int arm_arch5 = 0; /* Nonzero if this chip supports the ARM Architecture 5E extensions. */ int arm_arch5e = 0; /* Nonzero if this chip supports the ARM Architecture 6 extensions. */ int arm_arch6 = 0; /* Nonzero if this chip supports the ARM 6K extensions. */ int arm_arch6k = 0; /* Nonzero if this chip can benefit from load scheduling. */ int arm_ld_sched = 0; /* Nonzero if this chip is a StrongARM. */ int arm_tune_strongarm = 0; /* Nonzero if this chip is a Cirrus variant. */ int arm_arch_cirrus = 0; /* Nonzero if this chip supports Intel Wireless MMX technology. */ int arm_arch_iwmmxt = 0; /* Nonzero if this chip is an XScale. */ int arm_arch_xscale = 0; /* Nonzero if tuning for XScale */ int arm_tune_xscale = 0; /* Nonzero if we want to tune for stores that access the write-buffer. This typically means an ARM6 or ARM7 with MMU or MPU. */ int arm_tune_wbuf = 0; /* Nonzero if generating Thumb instructions. */ int thumb_code = 0; /* Nonzero if we should define __THUMB_INTERWORK__ in the preprocessor. XXX This is a bit of a hack, it's intended to help work around problems in GLD which doesn't understand that armv5t code is interworking clean. */ int arm_cpp_interwork = 0; /* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we must report the mode of the memory reference from PRINT_OPERAND to PRINT_OPERAND_ADDRESS. */ enum machine_mode output_memory_reference_mode; /* The register number to be used for the PIC offset register. */ unsigned arm_pic_register = INVALID_REGNUM; /* Set to 1 when a return insn is output, this means that the epilogue is not needed. */ int return_used_this_function; /* Set to 1 after arm_reorg has started. Reset to start at the start of the next function. */ static int after_arm_reorg = 0; /* The maximum number of insns to be used when loading a constant. */ static int arm_constant_limit = 3; /* For an explanation of these variables, see final_prescan_insn below. */ int arm_ccfsm_state; enum arm_cond_code arm_current_cc; rtx arm_target_insn; int arm_target_label; /* The condition codes of the ARM, and the inverse function. */ static const char * const arm_condition_codes[] = { "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt", "le", "al", "nv" }; #define streq(string1, string2) (strcmp (string1, string2) == 0) /* Initialization code. */ struct processors { const char *const name; enum processor_type core; const char *arch; const unsigned long flags; bool (* rtx_costs) (rtx, int, int, int *); }; /* Not all of these give usefully different compilation alternatives, but there is no simple way of generalizing them. */ static const struct processors all_cores[] = { /* ARM Cores */ #define ARM_CORE(NAME, IDENT, ARCH, FLAGS, COSTS) \ {NAME, arm_none, #ARCH, FLAGS | FL_FOR_ARCH##ARCH, arm_##COSTS##_rtx_costs}, #include "arm-cores.def" #undef ARM_CORE {NULL, arm_none, NULL, 0, NULL} }; static const struct processors all_architectures[] = { /* ARM Architectures */ /* We don't specify rtx_costs here as it will be figured out from the core. */ {"armv2", arm2, "2", FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH2, NULL}, {"armv2a", arm2, "2", FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH2, NULL}, {"armv3", arm6, "3", FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3, NULL}, {"armv3m", arm7m, "3M", FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3M, NULL}, {"armv4", arm7tdmi, "4", FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH4, NULL}, /* Strictly, FL_MODE26 is a permitted option for v4t, but there are no implementations that support it, so we will leave it out for now. */ {"armv4t", arm7tdmi, "4T", FL_CO_PROC | FL_FOR_ARCH4T, NULL}, {"armv5", arm10tdmi, "5", FL_CO_PROC | FL_FOR_ARCH5, NULL}, {"armv5t", arm10tdmi, "5T", FL_CO_PROC | FL_FOR_ARCH5T, NULL}, {"armv5e", arm1026ejs, "5E", FL_CO_PROC | FL_FOR_ARCH5E, NULL}, {"armv5te", arm1026ejs, "5TE", FL_CO_PROC | FL_FOR_ARCH5TE, NULL}, {"armv6", arm1136js, "6", FL_CO_PROC | FL_FOR_ARCH6, NULL}, {"armv6j", arm1136js, "6J", FL_CO_PROC | FL_FOR_ARCH6J, NULL}, {"armv6k", mpcore, "6K", FL_CO_PROC | FL_FOR_ARCH6K, NULL}, {"armv6z", arm1176jzs, "6Z", FL_CO_PROC | FL_FOR_ARCH6Z, NULL}, {"armv6zk", arm1176jzs, "6ZK", FL_CO_PROC | FL_FOR_ARCH6ZK, NULL}, + /* Clang compatibility... define __ARM_ARCH_7A__, but codegen is still 6ZK. */ + {"armv7a", arm1176jzs, "7A", FL_CO_PROC | FL_FOR_ARCH6ZK, NULL}, {"ep9312", ep9312, "4T", FL_LDSCHED | FL_CIRRUS | FL_FOR_ARCH4, NULL}, {"iwmmxt", iwmmxt, "5TE", FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT , NULL}, {NULL, arm_none, NULL, 0 , NULL} }; struct arm_cpu_select { const char * string; const char * name; const struct processors * processors; }; /* This is a magic structure. The 'string' field is magically filled in with a pointer to the value specified by the user on the command line assuming that the user has specified such a value. */ static struct arm_cpu_select arm_select[] = { /* string name processors */ { NULL, "-mcpu=", all_cores }, { NULL, "-march=", all_architectures }, { NULL, "-mtune=", all_cores } }; /* Defines representing the indexes into the above table. */ #define ARM_OPT_SET_CPU 0 #define ARM_OPT_SET_ARCH 1 #define ARM_OPT_SET_TUNE 2 /* The name of the preprocessor macro to define for this architecture. */ char arm_arch_name[] = "__ARM_ARCH_0UNK__"; struct fpu_desc { const char * name; enum fputype fpu; }; /* Available values for -mfpu=. */ static const struct fpu_desc all_fpus[] = { {"fpa", FPUTYPE_FPA}, {"fpe2", FPUTYPE_FPA_EMU2}, {"fpe3", FPUTYPE_FPA_EMU2}, {"maverick", FPUTYPE_MAVERICK}, {"vfp", FPUTYPE_VFP} }; /* Floating point models used by the different hardware. See fputype in arm.h. */ static const enum fputype fp_model_for_fpu[] = { /* No FP hardware. */ ARM_FP_MODEL_UNKNOWN, /* FPUTYPE_NONE */ ARM_FP_MODEL_FPA, /* FPUTYPE_FPA */ ARM_FP_MODEL_FPA, /* FPUTYPE_FPA_EMU2 */ ARM_FP_MODEL_FPA, /* FPUTYPE_FPA_EMU3 */ ARM_FP_MODEL_MAVERICK, /* FPUTYPE_MAVERICK */ ARM_FP_MODEL_VFP /* FPUTYPE_VFP */ }; struct float_abi { const char * name; enum float_abi_type abi_type; }; /* Available values for -mfloat-abi=. */ static const struct float_abi all_float_abis[] = { {"soft", ARM_FLOAT_ABI_SOFT}, {"softfp", ARM_FLOAT_ABI_SOFTFP}, {"hard", ARM_FLOAT_ABI_HARD} }; struct abi_name { const char *name; enum arm_abi_type abi_type; }; /* Available values for -mabi=. */ static const struct abi_name arm_all_abis[] = { {"apcs-gnu", ARM_ABI_APCS}, {"atpcs", ARM_ABI_ATPCS}, {"aapcs", ARM_ABI_AAPCS}, {"iwmmxt", ARM_ABI_IWMMXT}, {"aapcs-linux", ARM_ABI_AAPCS_LINUX} }; /* Supported TLS relocations. */ enum tls_reloc { TLS_GD32, TLS_LDM32, TLS_LDO32, TLS_IE32, TLS_LE32 }; /* Emit an insn that's a simple single-set. Both the operands must be known to be valid. */ inline static rtx emit_set_insn (rtx x, rtx y) { return emit_insn (gen_rtx_SET (VOIDmode, x, y)); } /* Return the number of bits set in VALUE. */ static unsigned bit_count (unsigned long value) { unsigned long count = 0; while (value) { count++; value &= value - 1; /* Clear the least-significant set bit. */ } return count; } /* Set up library functions unique to ARM. */ static void arm_init_libfuncs (void) { /* There are no special library functions unless we are using the ARM BPABI. */ if (!TARGET_BPABI) return; /* The functions below are described in Section 4 of the "Run-Time ABI for the ARM architecture", Version 1.0. */ /* Double-precision floating-point arithmetic. Table 2. */ set_optab_libfunc (add_optab, DFmode, "__aeabi_dadd"); set_optab_libfunc (sdiv_optab, DFmode, "__aeabi_ddiv"); set_optab_libfunc (smul_optab, DFmode, "__aeabi_dmul"); set_optab_libfunc (neg_optab, DFmode, "__aeabi_dneg"); set_optab_libfunc (sub_optab, DFmode, "__aeabi_dsub"); /* Double-precision comparisons. Table 3. */ set_optab_libfunc (eq_optab, DFmode, "__aeabi_dcmpeq"); set_optab_libfunc (ne_optab, DFmode, NULL); set_optab_libfunc (lt_optab, DFmode, "__aeabi_dcmplt"); set_optab_libfunc (le_optab, DFmode, "__aeabi_dcmple"); set_optab_libfunc (ge_optab, DFmode, "__aeabi_dcmpge"); set_optab_libfunc (gt_optab, DFmode, "__aeabi_dcmpgt"); set_optab_libfunc (unord_optab, DFmode, "__aeabi_dcmpun"); /* Single-precision floating-point arithmetic. Table 4. */ set_optab_libfunc (add_optab, SFmode, "__aeabi_fadd"); set_optab_libfunc (sdiv_optab, SFmode, "__aeabi_fdiv"); set_optab_libfunc (smul_optab, SFmode, "__aeabi_fmul"); set_optab_libfunc (neg_optab, SFmode, "__aeabi_fneg"); set_optab_libfunc (sub_optab, SFmode, "__aeabi_fsub"); /* Single-precision comparisons. Table 5. */ set_optab_libfunc (eq_optab, SFmode, "__aeabi_fcmpeq"); set_optab_libfunc (ne_optab, SFmode, NULL); set_optab_libfunc (lt_optab, SFmode, "__aeabi_fcmplt"); set_optab_libfunc (le_optab, SFmode, "__aeabi_fcmple"); set_optab_libfunc (ge_optab, SFmode, "__aeabi_fcmpge"); set_optab_libfunc (gt_optab, SFmode, "__aeabi_fcmpgt"); set_optab_libfunc (unord_optab, SFmode, "__aeabi_fcmpun"); /* Floating-point to integer conversions. Table 6. */ set_conv_libfunc (sfix_optab, SImode, DFmode, "__aeabi_d2iz"); set_conv_libfunc (ufix_optab, SImode, DFmode, "__aeabi_d2uiz"); set_conv_libfunc (sfix_optab, DImode, DFmode, "__aeabi_d2lz"); set_conv_libfunc (ufix_optab, DImode, DFmode, "__aeabi_d2ulz"); set_conv_libfunc (sfix_optab, SImode, SFmode, "__aeabi_f2iz"); set_conv_libfunc (ufix_optab, SImode, SFmode, "__aeabi_f2uiz"); set_conv_libfunc (sfix_optab, DImode, SFmode, "__aeabi_f2lz"); set_conv_libfunc (ufix_optab, DImode, SFmode, "__aeabi_f2ulz"); /* Conversions between floating types. Table 7. */ set_conv_libfunc (trunc_optab, SFmode, DFmode, "__aeabi_d2f"); set_conv_libfunc (sext_optab, DFmode, SFmode, "__aeabi_f2d"); /* Integer to floating-point conversions. Table 8. */ set_conv_libfunc (sfloat_optab, DFmode, SImode, "__aeabi_i2d"); set_conv_libfunc (ufloat_optab, DFmode, SImode, "__aeabi_ui2d"); set_conv_libfunc (sfloat_optab, DFmode, DImode, "__aeabi_l2d"); set_conv_libfunc (ufloat_optab, DFmode, DImode, "__aeabi_ul2d"); set_conv_libfunc (sfloat_optab, SFmode, SImode, "__aeabi_i2f"); set_conv_libfunc (ufloat_optab, SFmode, SImode, "__aeabi_ui2f"); set_conv_libfunc (sfloat_optab, SFmode, DImode, "__aeabi_l2f"); set_conv_libfunc (ufloat_optab, SFmode, DImode, "__aeabi_ul2f"); /* Long long. Table 9. */ set_optab_libfunc (smul_optab, DImode, "__aeabi_lmul"); set_optab_libfunc (sdivmod_optab, DImode, "__aeabi_ldivmod"); set_optab_libfunc (udivmod_optab, DImode, "__aeabi_uldivmod"); set_optab_libfunc (ashl_optab, DImode, "__aeabi_llsl"); set_optab_libfunc (lshr_optab, DImode, "__aeabi_llsr"); set_optab_libfunc (ashr_optab, DImode, "__aeabi_lasr"); set_optab_libfunc (cmp_optab, DImode, "__aeabi_lcmp"); set_optab_libfunc (ucmp_optab, DImode, "__aeabi_ulcmp"); /* Integer (32/32->32) division. \S 4.3.1. */ set_optab_libfunc (sdivmod_optab, SImode, "__aeabi_idivmod"); set_optab_libfunc (udivmod_optab, SImode, "__aeabi_uidivmod"); /* The divmod functions are designed so that they can be used for plain division, even though they return both the quotient and the remainder. The quotient is returned in the usual location (i.e., r0 for SImode, {r0, r1} for DImode), just as would be expected for an ordinary division routine. Because the AAPCS calling conventions specify that all of { r0, r1, r2, r3 } are callee-saved registers, there is no need to tell the compiler explicitly that those registers are clobbered by these routines. */ set_optab_libfunc (sdiv_optab, DImode, "__aeabi_ldivmod"); set_optab_libfunc (udiv_optab, DImode, "__aeabi_uldivmod"); /* For SImode division the ABI provides div-without-mod routines, which are faster. */ set_optab_libfunc (sdiv_optab, SImode, "__aeabi_idiv"); set_optab_libfunc (udiv_optab, SImode, "__aeabi_uidiv"); /* We don't have mod libcalls. Fortunately gcc knows how to use the divmod libcalls instead. */ set_optab_libfunc (smod_optab, DImode, NULL); set_optab_libfunc (umod_optab, DImode, NULL); set_optab_libfunc (smod_optab, SImode, NULL); set_optab_libfunc (umod_optab, SImode, NULL); } /* Implement TARGET_HANDLE_OPTION. */ static bool arm_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED) { switch (code) { case OPT_march_: arm_select[1].string = arg; return true; case OPT_mcpu_: arm_select[0].string = arg; return true; case OPT_mhard_float: target_float_abi_name = "hard"; return true; case OPT_msoft_float: target_float_abi_name = "soft"; return true; case OPT_mtune_: arm_select[2].string = arg; return true; default: return true; } } /* Fix up any incompatible options that the user has specified. This has now turned into a maze. */ void arm_override_options (void) { unsigned i; enum processor_type target_arch_cpu = arm_none; /* Set up the flags based on the cpu/architecture selected by the user. */ for (i = ARRAY_SIZE (arm_select); i--;) { struct arm_cpu_select * ptr = arm_select + i; if (ptr->string != NULL && ptr->string[0] != '\0') { const struct processors * sel; for (sel = ptr->processors; sel->name != NULL; sel++) if (streq (ptr->string, sel->name)) { /* Set the architecture define. */ if (i != ARM_OPT_SET_TUNE) sprintf (arm_arch_name, "__ARM_ARCH_%s__", sel->arch); /* Determine the processor core for which we should tune code-generation. */ if (/* -mcpu= is a sensible default. */ i == ARM_OPT_SET_CPU /* -mtune= overrides -mcpu= and -march=. */ || i == ARM_OPT_SET_TUNE) arm_tune = (enum processor_type) (sel - ptr->processors); /* Remember the CPU associated with this architecture. If no other option is used to set the CPU type, we'll use this to guess the most suitable tuning options. */ if (i == ARM_OPT_SET_ARCH) target_arch_cpu = sel->core; if (i != ARM_OPT_SET_TUNE) { /* If we have been given an architecture and a processor make sure that they are compatible. We only generate a warning though, and we prefer the CPU over the architecture. */ if (insn_flags != 0 && (insn_flags ^ sel->flags)) warning (0, "switch -mcpu=%s conflicts with -march= switch", ptr->string); insn_flags = sel->flags; } break; } if (sel->name == NULL) error ("bad value (%s) for %s switch", ptr->string, ptr->name); } } /* Guess the tuning options from the architecture if necessary. */ if (arm_tune == arm_none) arm_tune = target_arch_cpu; /* If the user did not specify a processor, choose one for them. */ if (insn_flags == 0) { const struct processors * sel; unsigned int sought; enum processor_type cpu; cpu = TARGET_CPU_DEFAULT; if (cpu == arm_none) { #ifdef SUBTARGET_CPU_DEFAULT /* Use the subtarget default CPU if none was specified by configure. */ cpu = SUBTARGET_CPU_DEFAULT; #endif /* Default to ARM6. */ if (cpu == arm_none) cpu = arm6; } sel = &all_cores[cpu]; insn_flags = sel->flags; /* Now check to see if the user has specified some command line switch that require certain abilities from the cpu. */ sought = 0; if (TARGET_INTERWORK || TARGET_THUMB) { sought |= (FL_THUMB | FL_MODE32); /* There are no ARM processors that support both APCS-26 and interworking. Therefore we force FL_MODE26 to be removed from insn_flags here (if it was set), so that the search below will always be able to find a compatible processor. */ insn_flags &= ~FL_MODE26; } if (sought != 0 && ((sought & insn_flags) != sought)) { /* Try to locate a CPU type that supports all of the abilities of the default CPU, plus the extra abilities requested by the user. */ for (sel = all_cores; sel->name != NULL; sel++) if ((sel->flags & sought) == (sought | insn_flags)) break; if (sel->name == NULL) { unsigned current_bit_count = 0; const struct processors * best_fit = NULL; /* Ideally we would like to issue an error message here saying that it was not possible to find a CPU compatible with the default CPU, but which also supports the command line options specified by the programmer, and so they ought to use the -mcpu= command line option to override the default CPU type. If we cannot find a cpu that has both the characteristics of the default cpu and the given command line options we scan the array again looking for a best match. */ for (sel = all_cores; sel->name != NULL; sel++) if ((sel->flags & sought) == sought) { unsigned count; count = bit_count (sel->flags & insn_flags); if (count >= current_bit_count) { best_fit = sel; current_bit_count = count; } } gcc_assert (best_fit); sel = best_fit; } insn_flags = sel->flags; } sprintf (arm_arch_name, "__ARM_ARCH_%s__", sel->arch); arm_default_cpu = (enum processor_type) (sel - all_cores); if (arm_tune == arm_none) arm_tune = arm_default_cpu; } /* The processor for which we should tune should now have been chosen. */ gcc_assert (arm_tune != arm_none); tune_flags = all_cores[(int)arm_tune].flags; if (optimize_size) targetm.rtx_costs = arm_size_rtx_costs; else targetm.rtx_costs = all_cores[(int)arm_tune].rtx_costs; /* Make sure that the processor choice does not conflict with any of the other command line choices. */ if (TARGET_INTERWORK && !(insn_flags & FL_THUMB)) { warning (0, "target CPU does not support interworking" ); target_flags &= ~MASK_INTERWORK; } if (TARGET_THUMB && !(insn_flags & FL_THUMB)) { warning (0, "target CPU does not support THUMB instructions"); target_flags &= ~MASK_THUMB; } if (TARGET_APCS_FRAME && TARGET_THUMB) { /* warning (0, "ignoring -mapcs-frame because -mthumb was used"); */ target_flags &= ~MASK_APCS_FRAME; } /* Callee super interworking implies thumb interworking. Adding this to the flags here simplifies the logic elsewhere. */ if (TARGET_THUMB && TARGET_CALLEE_INTERWORKING) target_flags |= MASK_INTERWORK; /* TARGET_BACKTRACE calls leaf_function_p, which causes a crash if done from here where no function is being compiled currently. */ if ((TARGET_TPCS_FRAME || TARGET_TPCS_LEAF_FRAME) && TARGET_ARM) warning (0, "enabling backtrace support is only meaningful when compiling for the Thumb"); if (TARGET_ARM && TARGET_CALLEE_INTERWORKING) warning (0, "enabling callee interworking support is only meaningful when compiling for the Thumb"); if (TARGET_ARM && TARGET_CALLER_INTERWORKING) warning (0, "enabling caller interworking support is only meaningful when compiling for the Thumb"); if (TARGET_APCS_STACK && !TARGET_APCS_FRAME) { warning (0, "-mapcs-stack-check incompatible with -mno-apcs-frame"); target_flags |= MASK_APCS_FRAME; } if (TARGET_POKE_FUNCTION_NAME) target_flags |= MASK_APCS_FRAME; if (TARGET_APCS_REENT && flag_pic) error ("-fpic and -mapcs-reent are incompatible"); if (TARGET_APCS_REENT) warning (0, "APCS reentrant code not supported. Ignored"); /* If this target is normally configured to use APCS frames, warn if they are turned off and debugging is turned on. */ if (TARGET_ARM && write_symbols != NO_DEBUG && !TARGET_APCS_FRAME && (TARGET_DEFAULT & MASK_APCS_FRAME)) warning (0, "-g with -mno-apcs-frame may not give sensible debugging"); /* If stack checking is disabled, we can use r10 as the PIC register, which keeps r9 available. */ if (flag_pic && TARGET_SINGLE_PIC_BASE) arm_pic_register = TARGET_APCS_STACK ? 9 : 10; if (TARGET_APCS_FLOAT) warning (0, "passing floating point arguments in fp regs not yet supported"); /* Initialize boolean versions of the flags, for use in the arm.md file. */ arm_arch3m = (insn_flags & FL_ARCH3M) != 0; arm_arch4 = (insn_flags & FL_ARCH4) != 0; arm_arch4t = arm_arch4 & ((insn_flags & FL_THUMB) != 0); arm_arch5 = (insn_flags & FL_ARCH5) != 0; arm_arch5e = (insn_flags & FL_ARCH5E) != 0; arm_arch6 = (insn_flags & FL_ARCH6) != 0; arm_arch6k = (insn_flags & FL_ARCH6K) != 0; arm_arch_xscale = (insn_flags & FL_XSCALE) != 0; arm_arch_cirrus = (insn_flags & FL_CIRRUS) != 0; arm_ld_sched = (tune_flags & FL_LDSCHED) != 0; arm_tune_strongarm = (tune_flags & FL_STRONG) != 0; thumb_code = (TARGET_ARM == 0); arm_tune_wbuf = (tune_flags & FL_WBUF) != 0; arm_tune_xscale = (tune_flags & FL_XSCALE) != 0; arm_arch_iwmmxt = (insn_flags & FL_IWMMXT) != 0; /* V5 code we generate is completely interworking capable, so we turn off TARGET_INTERWORK here to avoid many tests later on. */ /* XXX However, we must pass the right pre-processor defines to CPP or GLD can get confused. This is a hack. */ if (TARGET_INTERWORK) arm_cpp_interwork = 1; if (arm_arch5) target_flags &= ~MASK_INTERWORK; if (target_abi_name) { for (i = 0; i < ARRAY_SIZE (arm_all_abis); i++) { if (streq (arm_all_abis[i].name, target_abi_name)) { arm_abi = arm_all_abis[i].abi_type; break; } } if (i == ARRAY_SIZE (arm_all_abis)) error ("invalid ABI option: -mabi=%s", target_abi_name); } else arm_abi = ARM_DEFAULT_ABI; if (TARGET_IWMMXT && !ARM_DOUBLEWORD_ALIGN) error ("iwmmxt requires an AAPCS compatible ABI for proper operation"); if (TARGET_IWMMXT_ABI && !TARGET_IWMMXT) error ("iwmmxt abi requires an iwmmxt capable cpu"); arm_fp_model = ARM_FP_MODEL_UNKNOWN; if (target_fpu_name == NULL && target_fpe_name != NULL) { if (streq (target_fpe_name, "2")) target_fpu_name = "fpe2"; else if (streq (target_fpe_name, "3")) target_fpu_name = "fpe3"; else error ("invalid floating point emulation option: -mfpe=%s", target_fpe_name); } if (target_fpu_name != NULL) { /* The user specified a FPU. */ for (i = 0; i < ARRAY_SIZE (all_fpus); i++) { if (streq (all_fpus[i].name, target_fpu_name)) { arm_fpu_arch = all_fpus[i].fpu; arm_fpu_tune = arm_fpu_arch; arm_fp_model = fp_model_for_fpu[arm_fpu_arch]; break; } } if (arm_fp_model == ARM_FP_MODEL_UNKNOWN) error ("invalid floating point option: -mfpu=%s", target_fpu_name); } else { #ifdef FPUTYPE_DEFAULT /* Use the default if it is specified for this platform. */ arm_fpu_arch = FPUTYPE_DEFAULT; arm_fpu_tune = FPUTYPE_DEFAULT; #else /* Pick one based on CPU type. */ /* ??? Some targets assume FPA is the default. if ((insn_flags & FL_VFP) != 0) arm_fpu_arch = FPUTYPE_VFP; else */ if (arm_arch_cirrus) arm_fpu_arch = FPUTYPE_MAVERICK; else arm_fpu_arch = FPUTYPE_FPA_EMU2; #endif if (tune_flags & FL_CO_PROC && arm_fpu_arch == FPUTYPE_FPA_EMU2) arm_fpu_tune = FPUTYPE_FPA; else arm_fpu_tune = arm_fpu_arch; arm_fp_model = fp_model_for_fpu[arm_fpu_arch]; gcc_assert (arm_fp_model != ARM_FP_MODEL_UNKNOWN); } if (target_float_abi_name != NULL) { /* The user specified a FP ABI. */ for (i = 0; i < ARRAY_SIZE (all_float_abis); i++) { if (streq (all_float_abis[i].name, target_float_abi_name)) { arm_float_abi = all_float_abis[i].abi_type; break; } } if (i == ARRAY_SIZE (all_float_abis)) error ("invalid floating point abi: -mfloat-abi=%s", target_float_abi_name); } else arm_float_abi = TARGET_DEFAULT_FLOAT_ABI; if (arm_float_abi == ARM_FLOAT_ABI_HARD && TARGET_VFP) sorry ("-mfloat-abi=hard and VFP"); /* FPA and iWMMXt are incompatible because the insn encodings overlap. VFP and iWMMXt can theoretically coexist, but it's unlikely such silicon will ever exist. GCC makes no attempt to support this combination. */ if (TARGET_IWMMXT && !TARGET_SOFT_FLOAT) sorry ("iWMMXt and hardware floating point"); /* If soft-float is specified then don't use FPU. */ if (TARGET_SOFT_FLOAT) arm_fpu_arch = FPUTYPE_NONE; /* For arm2/3 there is no need to do any scheduling if there is only a floating point emulator, or we are doing software floating-point. */ if ((TARGET_SOFT_FLOAT || arm_fpu_tune == FPUTYPE_FPA_EMU2 || arm_fpu_tune == FPUTYPE_FPA_EMU3) && (tune_flags & FL_MODE32) == 0) flag_schedule_insns = flag_schedule_insns_after_reload = 0; if (target_thread_switch) { if (strcmp (target_thread_switch, "soft") == 0) target_thread_pointer = TP_SOFT; else if (strcmp (target_thread_switch, "auto") == 0) target_thread_pointer = TP_AUTO; else if (strcmp (target_thread_switch, "cp15") == 0) target_thread_pointer = TP_CP15; else error ("invalid thread pointer option: -mtp=%s", target_thread_switch); } /* Use the cp15 method if it is available. */ if (target_thread_pointer == TP_AUTO) { if (arm_arch6k && !TARGET_THUMB) target_thread_pointer = TP_CP15; else target_thread_pointer = TP_SOFT; } if (TARGET_HARD_TP && TARGET_THUMB) error ("can not use -mtp=cp15 with -mthumb"); /* Override the default structure alignment for AAPCS ABI. */ if (TARGET_AAPCS_BASED) arm_structure_size_boundary = 8; if (structure_size_string != NULL) { int size = strtol (structure_size_string, NULL, 0); if (size == 8 || size == 32 || (ARM_DOUBLEWORD_ALIGN && size == 64)) arm_structure_size_boundary = size; else warning (0, "structure size boundary can only be set to %s", ARM_DOUBLEWORD_ALIGN ? "8, 32 or 64": "8 or 32"); } if (arm_pic_register_string != NULL) { int pic_register = decode_reg_name (arm_pic_register_string); if (!flag_pic) warning (0, "-mpic-register= is useless without -fpic"); /* Prevent the user from choosing an obviously stupid PIC register. */ else if (pic_register < 0 || call_used_regs[pic_register] || pic_register == HARD_FRAME_POINTER_REGNUM || pic_register == STACK_POINTER_REGNUM || pic_register >= PC_REGNUM) error ("unable to use '%s' for PIC register", arm_pic_register_string); else arm_pic_register = pic_register; } if (TARGET_THUMB && flag_schedule_insns) { /* Don't warn since it's on by default in -O2. */ flag_schedule_insns = 0; } if (optimize_size) { arm_constant_limit = 1; /* If optimizing for size, bump the number of instructions that we are prepared to conditionally execute (even on a StrongARM). */ max_insns_skipped = 6; } else { /* For processors with load scheduling, it never costs more than 2 cycles to load a constant, and the load scheduler may well reduce that to 1. */ if (arm_ld_sched) arm_constant_limit = 1; /* On XScale the longer latency of a load makes it more difficult to achieve a good schedule, so it's faster to synthesize constants that can be done in two insns. */ if (arm_tune_xscale) arm_constant_limit = 2; /* StrongARM has early execution of branches, so a sequence that is worth skipping is shorter. */ if (arm_tune_strongarm) max_insns_skipped = 3; } /* Register global variables with the garbage collector. */ arm_add_gc_roots (); } static void arm_add_gc_roots (void) { gcc_obstack_init(&minipool_obstack); minipool_startobj = (char *) obstack_alloc (&minipool_obstack, 0); } /* A table of known ARM exception types. For use with the interrupt function attribute. */ typedef struct { const char *const arg; const unsigned long return_value; } isr_attribute_arg; static const isr_attribute_arg isr_attribute_args [] = { { "IRQ", ARM_FT_ISR }, { "irq", ARM_FT_ISR }, { "FIQ", ARM_FT_FIQ }, { "fiq", ARM_FT_FIQ }, { "ABORT", ARM_FT_ISR }, { "abort", ARM_FT_ISR }, { "ABORT", ARM_FT_ISR }, { "abort", ARM_FT_ISR }, { "UNDEF", ARM_FT_EXCEPTION }, { "undef", ARM_FT_EXCEPTION }, { "SWI", ARM_FT_EXCEPTION }, { "swi", ARM_FT_EXCEPTION }, { NULL, ARM_FT_NORMAL } }; /* Returns the (interrupt) function type of the current function, or ARM_FT_UNKNOWN if the type cannot be determined. */ static unsigned long arm_isr_value (tree argument) { const isr_attribute_arg * ptr; const char * arg; /* No argument - default to IRQ. */ if (argument == NULL_TREE) return ARM_FT_ISR; /* Get the value of the argument. */ if (TREE_VALUE (argument) == NULL_TREE || TREE_CODE (TREE_VALUE (argument)) != STRING_CST) return ARM_FT_UNKNOWN; arg = TREE_STRING_POINTER (TREE_VALUE (argument)); /* Check it against the list of known arguments. */ for (ptr = isr_attribute_args; ptr->arg != NULL; ptr++) if (streq (arg, ptr->arg)) return ptr->return_value; /* An unrecognized interrupt type. */ return ARM_FT_UNKNOWN; } /* Computes the type of the current function. */ static unsigned long arm_compute_func_type (void) { unsigned long type = ARM_FT_UNKNOWN; tree a; tree attr; gcc_assert (TREE_CODE (current_function_decl) == FUNCTION_DECL); /* Decide if the current function is volatile. Such functions never return, and many memory cycles can be saved by not storing register values that will never be needed again. This optimization was added to speed up context switching in a kernel application. */ if (optimize > 0 && (TREE_NOTHROW (current_function_decl) || !(flag_unwind_tables || (flag_exceptions && !USING_SJLJ_EXCEPTIONS))) && TREE_THIS_VOLATILE (current_function_decl)) type |= ARM_FT_VOLATILE; if (cfun->static_chain_decl != NULL) type |= ARM_FT_NESTED; attr = DECL_ATTRIBUTES (current_function_decl); a = lookup_attribute ("naked", attr); if (a != NULL_TREE) type |= ARM_FT_NAKED; a = lookup_attribute ("isr", attr); if (a == NULL_TREE) a = lookup_attribute ("interrupt", attr); if (a == NULL_TREE) type |= TARGET_INTERWORK ? ARM_FT_INTERWORKED : ARM_FT_NORMAL; else type |= arm_isr_value (TREE_VALUE (a)); return type; } /* Returns the type of the current function. */ unsigned long arm_current_func_type (void) { if (ARM_FUNC_TYPE (cfun->machine->func_type) == ARM_FT_UNKNOWN) cfun->machine->func_type = arm_compute_func_type (); return cfun->machine->func_type; } /* Return 1 if it is possible to return using a single instruction. If SIBLING is non-null, this is a test for a return before a sibling call. SIBLING is the call insn, so we can examine its register usage. */ int use_return_insn (int iscond, rtx sibling) { int regno; unsigned int func_type; unsigned long saved_int_regs; unsigned HOST_WIDE_INT stack_adjust; arm_stack_offsets *offsets; /* Never use a return instruction before reload has run. */ if (!reload_completed) return 0; func_type = arm_current_func_type (); /* Naked functions and volatile functions need special consideration. */ if (func_type & (ARM_FT_VOLATILE | ARM_FT_NAKED)) return 0; /* So do interrupt functions that use the frame pointer. */ if (IS_INTERRUPT (func_type) && frame_pointer_needed) return 0; offsets = arm_get_frame_offsets (); stack_adjust = offsets->outgoing_args - offsets->saved_regs; /* As do variadic functions. */ if (current_function_pretend_args_size || cfun->machine->uses_anonymous_args /* Or if the function calls __builtin_eh_return () */ || current_function_calls_eh_return /* Or if the function calls alloca */ || current_function_calls_alloca /* Or if there is a stack adjustment. However, if the stack pointer is saved on the stack, we can use a pre-incrementing stack load. */ || !(stack_adjust == 0 || (frame_pointer_needed && stack_adjust == 4))) return 0; saved_int_regs = arm_compute_save_reg_mask (); /* Unfortunately, the insn ldmib sp, {..., sp, ...} triggers a bug on most SA-110 based devices, such that the stack pointer won't be correctly restored if the instruction takes a page fault. We work around this problem by popping r3 along with the other registers, since that is never slower than executing another instruction. We test for !arm_arch5 here, because code for any architecture less than this could potentially be run on one of the buggy chips. */ if (stack_adjust == 4 && !arm_arch5) { /* Validate that r3 is a call-clobbered register (always true in the default abi) ... */ if (!call_used_regs[3]) return 0; /* ... that it isn't being used for a return value ... */ if (arm_size_return_regs () >= (4 * UNITS_PER_WORD)) return 0; /* ... or for a tail-call argument ... */ if (sibling) { gcc_assert (GET_CODE (sibling) == CALL_INSN); if (find_regno_fusage (sibling, USE, 3)) return 0; } /* ... and that there are no call-saved registers in r0-r2 (always true in the default ABI). */ if (saved_int_regs & 0x7) return 0; } /* Can't be done if interworking with Thumb, and any registers have been stacked. */ if (TARGET_INTERWORK && saved_int_regs != 0) return 0; /* On StrongARM, conditional returns are expensive if they aren't taken and multiple registers have been stacked. */ if (iscond && arm_tune_strongarm) { /* Conditional return when just the LR is stored is a simple conditional-load instruction, that's not expensive. */ if (saved_int_regs != 0 && saved_int_regs != (1 << LR_REGNUM)) return 0; if (flag_pic && arm_pic_register != INVALID_REGNUM && regs_ever_live[PIC_OFFSET_TABLE_REGNUM]) return 0; } /* If there are saved registers but the LR isn't saved, then we need two instructions for the return. */ if (saved_int_regs && !(saved_int_regs & (1 << LR_REGNUM))) return 0; /* Can't be done if any of the FPA regs are pushed, since this also requires an insn. */ if (TARGET_HARD_FLOAT && TARGET_FPA) for (regno = FIRST_FPA_REGNUM; regno <= LAST_FPA_REGNUM; regno++) if (regs_ever_live[regno] && !call_used_regs[regno]) return 0; /* Likewise VFP regs. */ if (TARGET_HARD_FLOAT && TARGET_VFP) for (regno = FIRST_VFP_REGNUM; regno <= LAST_VFP_REGNUM; regno++) if (regs_ever_live[regno] && !call_used_regs[regno]) return 0; if (TARGET_REALLY_IWMMXT) for (regno = FIRST_IWMMXT_REGNUM; regno <= LAST_IWMMXT_REGNUM; regno++) if (regs_ever_live[regno] && ! call_used_regs [regno]) return 0; return 1; } /* Return TRUE if int I is a valid immediate ARM constant. */ int const_ok_for_arm (HOST_WIDE_INT i) { int lowbit; /* For machines with >32 bit HOST_WIDE_INT, the bits above bit 31 must be all zero, or all one. */ if ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff) != 0 && ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff) != ((~(unsigned HOST_WIDE_INT) 0) & ~(unsigned HOST_WIDE_INT) 0xffffffff))) return FALSE; i &= (unsigned HOST_WIDE_INT) 0xffffffff; /* Fast return for 0 and small values. We must do this for zero, since the code below can't handle that one case. */ if ((i & ~(unsigned HOST_WIDE_INT) 0xff) == 0) return TRUE; /* Get the number of trailing zeros, rounded down to the nearest even number. */ lowbit = (ffs ((int) i) - 1) & ~1; if ((i & ~(((unsigned HOST_WIDE_INT) 0xff) << lowbit)) == 0) return TRUE; else if (lowbit <= 4 && ((i & ~0xc000003f) == 0 || (i & ~0xf000000f) == 0 || (i & ~0xfc000003) == 0)) return TRUE; return FALSE; } /* Return true if I is a valid constant for the operation CODE. */ static int const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code) { if (const_ok_for_arm (i)) return 1; switch (code) { case PLUS: return const_ok_for_arm (ARM_SIGN_EXTEND (-i)); case MINUS: /* Should only occur with (MINUS I reg) => rsb */ case XOR: case IOR: return 0; case AND: return const_ok_for_arm (ARM_SIGN_EXTEND (~i)); default: gcc_unreachable (); } } /* Emit a sequence of insns to handle a large constant. CODE is the code of the operation required, it can be any of SET, PLUS, IOR, AND, XOR, MINUS; MODE is the mode in which the operation is being performed; VAL is the integer to operate on; SOURCE is the other operand (a register, or a null-pointer for SET); SUBTARGETS means it is safe to create scratch registers if that will either produce a simpler sequence, or we will want to cse the values. Return value is the number of insns emitted. */ int arm_split_constant (enum rtx_code code, enum machine_mode mode, rtx insn, HOST_WIDE_INT val, rtx target, rtx source, int subtargets) { rtx cond; if (insn && GET_CODE (PATTERN (insn)) == COND_EXEC) cond = COND_EXEC_TEST (PATTERN (insn)); else cond = NULL_RTX; if (subtargets || code == SET || (GET_CODE (target) == REG && GET_CODE (source) == REG && REGNO (target) != REGNO (source))) { /* After arm_reorg has been called, we can't fix up expensive constants by pushing them into memory so we must synthesize them in-line, regardless of the cost. This is only likely to be more costly on chips that have load delay slots and we are compiling without running the scheduler (so no splitting occurred before the final instruction emission). Ref: gcc -O1 -mcpu=strongarm gcc.c-torture/compile/980506-2.c */ if (!after_arm_reorg && !cond && (arm_gen_constant (code, mode, NULL_RTX, val, target, source, 1, 0) > arm_constant_limit + (code != SET))) { if (code == SET) { /* Currently SET is the only monadic value for CODE, all the rest are diadic. */ emit_set_insn (target, GEN_INT (val)); return 1; } else { rtx temp = subtargets ? gen_reg_rtx (mode) : target; emit_set_insn (temp, GEN_INT (val)); /* For MINUS, the value is subtracted from, since we never have subtraction of a constant. */ if (code == MINUS) emit_set_insn (target, gen_rtx_MINUS (mode, temp, source)); else emit_set_insn (target, gen_rtx_fmt_ee (code, mode, source, temp)); return 2; } } } return arm_gen_constant (code, mode, cond, val, target, source, subtargets, 1); } static int count_insns_for_constant (HOST_WIDE_INT remainder, int i) { HOST_WIDE_INT temp1; int num_insns = 0; do { int end; if (i <= 0) i += 32; if (remainder & (3 << (i - 2))) { end = i - 8; if (end < 0) end += 32; temp1 = remainder & ((0x0ff << end) | ((i < end) ? (0xff >> (32 - end)) : 0)); remainder &= ~temp1; num_insns++; i -= 6; } i -= 2; } while (remainder); return num_insns; } /* Emit an instruction with the indicated PATTERN. If COND is non-NULL, conditionalize the execution of the instruction on COND being true. */ static void emit_constant_insn (rtx cond, rtx pattern) { if (cond) pattern = gen_rtx_COND_EXEC (VOIDmode, copy_rtx (cond), pattern); emit_insn (pattern); } /* As above, but extra parameter GENERATE which, if clear, suppresses RTL generation. */ static int arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond, HOST_WIDE_INT val, rtx target, rtx source, int subtargets, int generate) { int can_invert = 0; int can_negate = 0; int can_negate_initial = 0; int can_shift = 0; int i; int num_bits_set = 0; int set_sign_bit_copies = 0; int clear_sign_bit_copies = 0; int clear_zero_bit_copies = 0; int set_zero_bit_copies = 0; int insns = 0; unsigned HOST_WIDE_INT temp1, temp2; unsigned HOST_WIDE_INT remainder = val & 0xffffffff; /* Find out which operations are safe for a given CODE. Also do a quick check for degenerate cases; these can occur when DImode operations are split. */ switch (code) { case SET: can_invert = 1; can_shift = 1; can_negate = 1; break; case PLUS: can_negate = 1; can_negate_initial = 1; break; case IOR: if (remainder == 0xffffffff) { if (generate) emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, GEN_INT (ARM_SIGN_EXTEND (val)))); return 1; } if (remainder == 0) { if (reload_completed && rtx_equal_p (target, source)) return 0; if (generate) emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, source)); return 1; } break; case AND: if (remainder == 0) { if (generate) emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, const0_rtx)); return 1; } if (remainder == 0xffffffff) { if (reload_completed && rtx_equal_p (target, source)) return 0; if (generate) emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, source)); return 1; } can_invert = 1; break; case XOR: if (remainder == 0) { if (reload_completed && rtx_equal_p (target, source)) return 0; if (generate) emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, source)); return 1; } /* We don't know how to handle other cases yet. */ gcc_assert (remainder == 0xffffffff); if (generate) emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, gen_rtx_NOT (mode, source))); return 1; case MINUS: /* We treat MINUS as (val - source), since (source - val) is always passed as (source + (-val)). */ if (remainder == 0) { if (generate) emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, gen_rtx_NEG (mode, source))); return 1; } if (const_ok_for_arm (val)) { if (generate) emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, gen_rtx_MINUS (mode, GEN_INT (val), source))); return 1; } can_negate = 1; break; default: gcc_unreachable (); } /* If we can do it in one insn get out quickly. */ if (const_ok_for_arm (val) || (can_negate_initial && const_ok_for_arm (-val)) || (can_invert && const_ok_for_arm (~val))) { if (generate) emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, (source ? gen_rtx_fmt_ee (code, mode, source, GEN_INT (val)) : GEN_INT (val)))); return 1; } /* Calculate a few attributes that may be useful for specific optimizations. */ for (i = 31; i >= 0; i--) { if ((remainder & (1 << i)) == 0) clear_sign_bit_copies++; else break; } for (i = 31; i >= 0; i--) { if ((remainder & (1 << i)) != 0) set_sign_bit_copies++; else break; } for (i = 0; i <= 31; i++) { if ((remainder & (1 << i)) == 0) clear_zero_bit_copies++; else break; } for (i = 0; i <= 31; i++) { if ((remainder & (1 << i)) != 0) set_zero_bit_copies++; else break; } switch (code) { case SET: /* See if we can do this by sign_extending a constant that is known to be negative. This is a good, way of doing it, since the shift may well merge into a subsequent insn. */ if (set_sign_bit_copies > 1) { if (const_ok_for_arm (temp1 = ARM_SIGN_EXTEND (remainder << (set_sign_bit_copies - 1)))) { if (generate) { rtx new_src = subtargets ? gen_reg_rtx (mode) : target; emit_constant_insn (cond, gen_rtx_SET (VOIDmode, new_src, GEN_INT (temp1))); emit_constant_insn (cond, gen_ashrsi3 (target, new_src, GEN_INT (set_sign_bit_copies - 1))); } return 2; } /* For an inverted constant, we will need to set the low bits, these will be shifted out of harm's way. */ temp1 |= (1 << (set_sign_bit_copies - 1)) - 1; if (const_ok_for_arm (~temp1)) { if (generate) { rtx new_src = subtargets ? gen_reg_rtx (mode) : target; emit_constant_insn (cond, gen_rtx_SET (VOIDmode, new_src, GEN_INT (temp1))); emit_constant_insn (cond, gen_ashrsi3 (target, new_src, GEN_INT (set_sign_bit_copies - 1))); } return 2; } } /* See if we can calculate the value as the difference between two valid immediates. */ if (clear_sign_bit_copies + clear_zero_bit_copies <= 16) { int topshift = clear_sign_bit_copies & ~1; temp1 = ARM_SIGN_EXTEND ((remainder + (0x00800000 >> topshift)) & (0xff000000 >> topshift)); /* If temp1 is zero, then that means the 9 most significant bits of remainder were 1 and we've caused it to overflow. When topshift is 0 we don't need to do anything since we can borrow from 'bit 32'. */ if (temp1 == 0 && topshift != 0) temp1 = 0x80000000 >> (topshift - 1); temp2 = ARM_SIGN_EXTEND (temp1 - remainder); if (const_ok_for_arm (temp2)) { if (generate) { rtx new_src = subtargets ? gen_reg_rtx (mode) : target; emit_constant_insn (cond, gen_rtx_SET (VOIDmode, new_src, GEN_INT (temp1))); emit_constant_insn (cond, gen_addsi3 (target, new_src, GEN_INT (-temp2))); } return 2; } } /* See if we can generate this by setting the bottom (or the top) 16 bits, and then shifting these into the other half of the word. We only look for the simplest cases, to do more would cost too much. Be careful, however, not to generate this when the alternative would take fewer insns. */ if (val & 0xffff0000) { temp1 = remainder & 0xffff0000; temp2 = remainder & 0x0000ffff; /* Overlaps outside this range are best done using other methods. */ for (i = 9; i < 24; i++) { if ((((temp2 | (temp2 << i)) & 0xffffffff) == remainder) && !const_ok_for_arm (temp2)) { rtx new_src = (subtargets ? (generate ? gen_reg_rtx (mode) : NULL_RTX) : target); insns = arm_gen_constant (code, mode, cond, temp2, new_src, source, subtargets, generate); source = new_src; if (generate) emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, gen_rtx_IOR (mode, gen_rtx_ASHIFT (mode, source, GEN_INT (i)), source))); return insns + 1; } } /* Don't duplicate cases already considered. */ for (i = 17; i < 24; i++) { if (((temp1 | (temp1 >> i)) == remainder) && !const_ok_for_arm (temp1)) { rtx new_src = (subtargets ? (generate ? gen_reg_rtx (mode) : NULL_RTX) : target); insns = arm_gen_constant (code, mode, cond, temp1, new_src, source, subtargets, generate); source = new_src; if (generate) emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, gen_rtx_IOR (mode, gen_rtx_LSHIFTRT (mode, source, GEN_INT (i)), source))); return insns + 1; } } } break; case IOR: case XOR: /* If we have IOR or XOR, and the constant can be loaded in a single instruction, and we can find a temporary to put it in, then this can be done in two instructions instead of 3-4. */ if (subtargets /* TARGET can't be NULL if SUBTARGETS is 0 */ || (reload_completed && !reg_mentioned_p (target, source))) { if (const_ok_for_arm (ARM_SIGN_EXTEND (~val))) { if (generate) { rtx sub = subtargets ? gen_reg_rtx (mode) : target; emit_constant_insn (cond, gen_rtx_SET (VOIDmode, sub, GEN_INT (val))); emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, gen_rtx_fmt_ee (code, mode, source, sub))); } return 2; } } if (code == XOR) break; if (set_sign_bit_copies > 8 && (val & (-1 << (32 - set_sign_bit_copies))) == val) { if (generate) { rtx sub = subtargets ? gen_reg_rtx (mode) : target; rtx shift = GEN_INT (set_sign_bit_copies); emit_constant_insn (cond, gen_rtx_SET (VOIDmode, sub, gen_rtx_NOT (mode, gen_rtx_ASHIFT (mode, source, shift)))); emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, gen_rtx_NOT (mode, gen_rtx_LSHIFTRT (mode, sub, shift)))); } return 2; } if (set_zero_bit_copies > 8 && (remainder & ((1 << set_zero_bit_copies) - 1)) == remainder) { if (generate) { rtx sub = subtargets ? gen_reg_rtx (mode) : target; rtx shift = GEN_INT (set_zero_bit_copies); emit_constant_insn (cond, gen_rtx_SET (VOIDmode, sub, gen_rtx_NOT (mode, gen_rtx_LSHIFTRT (mode, source, shift)))); emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, gen_rtx_NOT (mode, gen_rtx_ASHIFT (mode, sub, shift)))); } return 2; } if (const_ok_for_arm (temp1 = ARM_SIGN_EXTEND (~val))) { if (generate) { rtx sub = subtargets ? gen_reg_rtx (mode) : target; emit_constant_insn (cond, gen_rtx_SET (VOIDmode, sub, gen_rtx_NOT (mode, source))); source = sub; if (subtargets) sub = gen_reg_rtx (mode); emit_constant_insn (cond, gen_rtx_SET (VOIDmode, sub, gen_rtx_AND (mode, source, GEN_INT (temp1)))); emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, gen_rtx_NOT (mode, sub))); } return 3; } break; case AND: /* See if two shifts will do 2 or more insn's worth of work. */ if (clear_sign_bit_copies >= 16 && clear_sign_bit_copies < 24) { HOST_WIDE_INT shift_mask = ((0xffffffff << (32 - clear_sign_bit_copies)) & 0xffffffff); if ((remainder | shift_mask) != 0xffffffff) { if (generate) { rtx new_src = subtargets ? gen_reg_rtx (mode) : target; insns = arm_gen_constant (AND, mode, cond, remainder | shift_mask, new_src, source, subtargets, 1); source = new_src; } else { rtx targ = subtargets ? NULL_RTX : target; insns = arm_gen_constant (AND, mode, cond, remainder | shift_mask, targ, source, subtargets, 0); } } if (generate) { rtx new_src = subtargets ? gen_reg_rtx (mode) : target; rtx shift = GEN_INT (clear_sign_bit_copies); emit_insn (gen_ashlsi3 (new_src, source, shift)); emit_insn (gen_lshrsi3 (target, new_src, shift)); } return insns + 2; } if (clear_zero_bit_copies >= 16 && clear_zero_bit_copies < 24) { HOST_WIDE_INT shift_mask = (1 << clear_zero_bit_copies) - 1; if ((remainder | shift_mask) != 0xffffffff) { if (generate) { rtx new_src = subtargets ? gen_reg_rtx (mode) : target; insns = arm_gen_constant (AND, mode, cond, remainder | shift_mask, new_src, source, subtargets, 1); source = new_src; } else { rtx targ = subtargets ? NULL_RTX : target; insns = arm_gen_constant (AND, mode, cond, remainder | shift_mask, targ, source, subtargets, 0); } } if (generate) { rtx new_src = subtargets ? gen_reg_rtx (mode) : target; rtx shift = GEN_INT (clear_zero_bit_copies); emit_insn (gen_lshrsi3 (new_src, source, shift)); emit_insn (gen_ashlsi3 (target, new_src, shift)); } return insns + 2; } break; default: break; } for (i = 0; i < 32; i++) if (remainder & (1 << i)) num_bits_set++; if (code == AND || (can_invert && num_bits_set > 16)) remainder = (~remainder) & 0xffffffff; else if (code == PLUS && num_bits_set > 16) remainder = (-remainder) & 0xffffffff; else { can_invert = 0; can_negate = 0; } /* Now try and find a way of doing the job in either two or three instructions. We start by looking for the largest block of zeros that are aligned on a 2-bit boundary, we then fill up the temps, wrapping around to the top of the word when we drop off the bottom. In the worst case this code should produce no more than four insns. */ { int best_start = 0; int best_consecutive_zeros = 0; for (i = 0; i < 32; i += 2) { int consecutive_zeros = 0; if (!(remainder & (3 << i))) { while ((i < 32) && !(remainder & (3 << i))) { consecutive_zeros += 2; i += 2; } if (consecutive_zeros > best_consecutive_zeros) { best_consecutive_zeros = consecutive_zeros; best_start = i - consecutive_zeros; } i -= 2; } } /* So long as it won't require any more insns to do so, it's desirable to emit a small constant (in bits 0...9) in the last insn. This way there is more chance that it can be combined with a later addressing insn to form a pre-indexed load or store operation. Consider: *((volatile int *)0xe0000100) = 1; *((volatile int *)0xe0000110) = 2; We want this to wind up as: mov rA, #0xe0000000 mov rB, #1 str rB, [rA, #0x100] mov rB, #2 str rB, [rA, #0x110] rather than having to synthesize both large constants from scratch. Therefore, we calculate how many insns would be required to emit the constant starting from `best_start', and also starting from zero (i.e. with bit 31 first to be output). If `best_start' doesn't yield a shorter sequence, we may as well use zero. */ if (best_start != 0 && ((((unsigned HOST_WIDE_INT) 1) << best_start) < remainder) && (count_insns_for_constant (remainder, 0) <= count_insns_for_constant (remainder, best_start))) best_start = 0; /* Now start emitting the insns. */ i = best_start; do { int end; if (i <= 0) i += 32; if (remainder & (3 << (i - 2))) { end = i - 8; if (end < 0) end += 32; temp1 = remainder & ((0x0ff << end) | ((i < end) ? (0xff >> (32 - end)) : 0)); remainder &= ~temp1; if (generate) { rtx new_src, temp1_rtx; if (code == SET || code == MINUS) { new_src = (subtargets ? gen_reg_rtx (mode) : target); if (can_invert && code != MINUS) temp1 = ~temp1; } else { if (remainder && subtargets) new_src = gen_reg_rtx (mode); else new_src = target; if (can_invert) temp1 = ~temp1; else if (can_negate) temp1 = -temp1; } temp1 = trunc_int_for_mode (temp1, mode); temp1_rtx = GEN_INT (temp1); if (code == SET) ; else if (code == MINUS) temp1_rtx = gen_rtx_MINUS (mode, temp1_rtx, source); else temp1_rtx = gen_rtx_fmt_ee (code, mode, source, temp1_rtx); emit_constant_insn (cond, gen_rtx_SET (VOIDmode, new_src, temp1_rtx)); source = new_src; } if (code == SET) { can_invert = 0; code = PLUS; } else if (code == MINUS) code = PLUS; insns++; i -= 6; } i -= 2; } while (remainder); } return insns; } /* Canonicalize a comparison so that we are more likely to recognize it. This can be done for a few constant compares, where we can make the immediate value easier to load. */ enum rtx_code arm_canonicalize_comparison (enum rtx_code code, enum machine_mode mode, rtx * op1) { unsigned HOST_WIDE_INT i = INTVAL (*op1); unsigned HOST_WIDE_INT maxval; maxval = (((unsigned HOST_WIDE_INT) 1) << (GET_MODE_BITSIZE(mode) - 1)) - 1; switch (code) { case EQ: case NE: return code; case GT: case LE: if (i != maxval && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1)))) { *op1 = GEN_INT (i + 1); return code == GT ? GE : LT; } break; case GE: case LT: if (i != ~maxval && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1)))) { *op1 = GEN_INT (i - 1); return code == GE ? GT : LE; } break; case GTU: case LEU: if (i != ~((unsigned HOST_WIDE_INT) 0) && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1)))) { *op1 = GEN_INT (i + 1); return code == GTU ? GEU : LTU; } break; case GEU: case LTU: if (i != 0 && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1)))) { *op1 = GEN_INT (i - 1); return code == GEU ? GTU : LEU; } break; default: gcc_unreachable (); } return code; } /* Define how to find the value returned by a function. */ rtx arm_function_value(tree type, tree func ATTRIBUTE_UNUSED) { enum machine_mode mode; int unsignedp ATTRIBUTE_UNUSED; rtx r ATTRIBUTE_UNUSED; mode = TYPE_MODE (type); /* Promote integer types. */ if (INTEGRAL_TYPE_P (type)) PROMOTE_FUNCTION_MODE (mode, unsignedp, type); /* Promotes small structs returned in a register to full-word size for big-endian AAPCS. */ if (arm_return_in_msb (type)) { HOST_WIDE_INT size = int_size_in_bytes (type); if (size % UNITS_PER_WORD != 0) { size += UNITS_PER_WORD - size % UNITS_PER_WORD; mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0); } } return LIBCALL_VALUE(mode); } /* Determine the amount of memory needed to store the possible return registers of an untyped call. */ int arm_apply_result_size (void) { int size = 16; if (TARGET_ARM) { if (TARGET_HARD_FLOAT_ABI) { if (TARGET_FPA) size += 12; if (TARGET_MAVERICK) size += 8; } if (TARGET_IWMMXT_ABI) size += 8; } return size; } /* Decide whether a type should be returned in memory (true) or in a register (false). This is called by the macro RETURN_IN_MEMORY. */ int arm_return_in_memory (tree type) { HOST_WIDE_INT size; if (!AGGREGATE_TYPE_P (type) && (TREE_CODE (type) != VECTOR_TYPE) && !(TARGET_AAPCS_BASED && TREE_CODE (type) == COMPLEX_TYPE)) /* All simple types are returned in registers. For AAPCS, complex types are treated the same as aggregates. */ return 0; size = int_size_in_bytes (type); if (arm_abi != ARM_ABI_APCS) { /* ATPCS and later return aggregate types in memory only if they are larger than a word (or are variable size). */ return (size < 0 || size > UNITS_PER_WORD); } /* To maximize backwards compatibility with previous versions of gcc, return vectors up to 4 words in registers. */ if (TREE_CODE (type) == VECTOR_TYPE) return (size < 0 || size > (4 * UNITS_PER_WORD)); /* For the arm-wince targets we choose to be compatible with Microsoft's ARM and Thumb compilers, which always return aggregates in memory. */ #ifndef ARM_WINCE /* All structures/unions bigger than one word are returned in memory. Also catch the case where int_size_in_bytes returns -1. In this case the aggregate is either huge or of variable size, and in either case we will want to return it via memory and not in a register. */ if (size < 0 || size > UNITS_PER_WORD) return 1; if (TREE_CODE (type) == RECORD_TYPE) { tree field; /* For a struct the APCS says that we only return in a register if the type is 'integer like' and every addressable element has an offset of zero. For practical purposes this means that the structure can have at most one non bit-field element and that this element must be the first one in the structure. */ /* Find the first field, ignoring non FIELD_DECL things which will have been created by C++. */ for (field = TYPE_FIELDS (type); field && TREE_CODE (field) != FIELD_DECL; field = TREE_CHAIN (field)) continue; if (field == NULL) return 0; /* An empty structure. Allowed by an extension to ANSI C. */ /* Check that the first field is valid for returning in a register. */ /* ... Floats are not allowed */ if (FLOAT_TYPE_P (TREE_TYPE (field))) return 1; /* ... Aggregates that are not themselves valid for returning in a register are not allowed. */ if (RETURN_IN_MEMORY (TREE_TYPE (field))) return 1; /* Now check the remaining fields, if any. Only bitfields are allowed, since they are not addressable. */ for (field = TREE_CHAIN (field); field; field = TREE_CHAIN (field)) { if (TREE_CODE (field) != FIELD_DECL) continue; if (!DECL_BIT_FIELD_TYPE (field)) return 1; } return 0; } if (TREE_CODE (type) == UNION_TYPE) { tree field; /* Unions can be returned in registers if every element is integral, or can be returned in an integer register. */ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) { if (TREE_CODE (field) != FIELD_DECL) continue; if (FLOAT_TYPE_P (TREE_TYPE (field))) return 1; if (RETURN_IN_MEMORY (TREE_TYPE (field))) return 1; } return 0; } #endif /* not ARM_WINCE */ /* Return all other types in memory. */ return 1; } /* Indicate whether or not words of a double are in big-endian order. */ int arm_float_words_big_endian (void) { if (TARGET_MAVERICK) return 0; /* For FPA, float words are always big-endian. For VFP, floats words follow the memory system mode. */ if (TARGET_FPA) { return 1; } if (TARGET_VFP) return (TARGET_BIG_END ? 1 : 0); return 1; } /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. For a library call, FNTYPE is NULL. */ void arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype, rtx libname ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNUSED) { /* On the ARM, the offset starts at 0. */ pcum->nregs = 0; pcum->iwmmxt_nregs = 0; pcum->can_split = true; pcum->call_cookie = CALL_NORMAL; if (TARGET_LONG_CALLS) pcum->call_cookie = CALL_LONG; /* Check for long call/short call attributes. The attributes override any command line option. */ if (fntype) { if (lookup_attribute ("short_call", TYPE_ATTRIBUTES (fntype))) pcum->call_cookie = CALL_SHORT; else if (lookup_attribute ("long_call", TYPE_ATTRIBUTES (fntype))) pcum->call_cookie = CALL_LONG; } /* Varargs vectors are treated the same as long long. named_count avoids having to change the way arm handles 'named' */ pcum->named_count = 0; pcum->nargs = 0; if (TARGET_REALLY_IWMMXT && fntype) { tree fn_arg; for (fn_arg = TYPE_ARG_TYPES (fntype); fn_arg; fn_arg = TREE_CHAIN (fn_arg)) pcum->named_count += 1; if (! pcum->named_count) pcum->named_count = INT_MAX; } } /* Return true if mode/type need doubleword alignment. */ bool arm_needs_doubleword_align (enum machine_mode mode, tree type) { return (GET_MODE_ALIGNMENT (mode) > PARM_BOUNDARY || (type && TYPE_ALIGN (type) > PARM_BOUNDARY)); } /* Determine where to put an argument to a function. Value is zero to push the argument on the stack, or a hard register in which to store the argument. MODE is the argument's machine mode. TYPE is the data type of the argument (as a tree). This is null for libcalls where that information may not be available. CUM is a variable of type CUMULATIVE_ARGS which gives info about the preceding args and about the function being called. NAMED is nonzero if this argument is a named parameter (otherwise it is an extra parameter matching an ellipsis). */ rtx arm_function_arg (CUMULATIVE_ARGS *pcum, enum machine_mode mode, tree type, int named) { int nregs; /* Varargs vectors are treated the same as long long. named_count avoids having to change the way arm handles 'named' */ if (TARGET_IWMMXT_ABI && arm_vector_mode_supported_p (mode) && pcum->named_count > pcum->nargs + 1) { if (pcum->iwmmxt_nregs <= 9) return gen_rtx_REG (mode, pcum->iwmmxt_nregs + FIRST_IWMMXT_REGNUM); else { pcum->can_split = false; return NULL_RTX; } } /* Put doubleword aligned quantities in even register pairs. */ if (pcum->nregs & 1 && ARM_DOUBLEWORD_ALIGN && arm_needs_doubleword_align (mode, type)) pcum->nregs++; if (mode == VOIDmode) /* Compute operand 2 of the call insn. */ return GEN_INT (pcum->call_cookie); /* Only allow splitting an arg between regs and memory if all preceding args were allocated to regs. For args passed by reference we only count the reference pointer. */ if (pcum->can_split) nregs = 1; else nregs = ARM_NUM_REGS2 (mode, type); if (!named || pcum->nregs + nregs > NUM_ARG_REGS) return NULL_RTX; return gen_rtx_REG (mode, pcum->nregs); } static int arm_arg_partial_bytes (CUMULATIVE_ARGS *pcum, enum machine_mode mode, tree type, bool named ATTRIBUTE_UNUSED) { int nregs = pcum->nregs; if (arm_vector_mode_supported_p (mode)) return 0; if (NUM_ARG_REGS > nregs && (NUM_ARG_REGS < nregs + ARM_NUM_REGS2 (mode, type)) && pcum->can_split) return (NUM_ARG_REGS - nregs) * UNITS_PER_WORD; return 0; } /* Variable sized types are passed by reference. This is a GCC extension to the ARM ABI. */ static bool arm_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, tree type, bool named ATTRIBUTE_UNUSED) { return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST; } /* Encode the current state of the #pragma [no_]long_calls. */ typedef enum { OFF, /* No #pragma [no_]long_calls is in effect. */ LONG, /* #pragma long_calls is in effect. */ SHORT /* #pragma no_long_calls is in effect. */ } arm_pragma_enum; static arm_pragma_enum arm_pragma_long_calls = OFF; void arm_pr_long_calls (struct cpp_reader * pfile ATTRIBUTE_UNUSED) { arm_pragma_long_calls = LONG; } void arm_pr_no_long_calls (struct cpp_reader * pfile ATTRIBUTE_UNUSED) { arm_pragma_long_calls = SHORT; } void arm_pr_long_calls_off (struct cpp_reader * pfile ATTRIBUTE_UNUSED) { arm_pragma_long_calls = OFF; } /* Table of machine attributes. */ const struct attribute_spec arm_attribute_table[] = { /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ /* Function calls made to this symbol must be done indirectly, because it may lie outside of the 26 bit addressing range of a normal function call. */ { "long_call", 0, 0, false, true, true, NULL }, /* Whereas these functions are always known to reside within the 26 bit addressing range. */ { "short_call", 0, 0, false, true, true, NULL }, /* Interrupt Service Routines have special prologue and epilogue requirements. */ { "isr", 0, 1, false, false, false, arm_handle_isr_attribute }, { "interrupt", 0, 1, false, false, false, arm_handle_isr_attribute }, { "naked", 0, 0, true, false, false, arm_handle_fndecl_attribute }, #ifdef ARM_PE /* ARM/PE has three new attributes: interfacearm - ? dllexport - for exporting a function/variable that will live in a dll dllimport - for importing a function/variable from a dll Microsoft allows multiple declspecs in one __declspec, separating them with spaces. We do NOT support this. Instead, use __declspec multiple times. */ { "dllimport", 0, 0, true, false, false, NULL }, { "dllexport", 0, 0, true, false, false, NULL }, { "interfacearm", 0, 0, true, false, false, arm_handle_fndecl_attribute }, #elif TARGET_DLLIMPORT_DECL_ATTRIBUTES { "dllimport", 0, 0, false, false, false, handle_dll_attribute }, { "dllexport", 0, 0, false, false, false, handle_dll_attribute }, { "notshared", 0, 0, false, true, false, arm_handle_notshared_attribute }, #endif { NULL, 0, 0, false, false, false, NULL } }; /* Handle an attribute requiring a FUNCTION_DECL; arguments as in struct attribute_spec.handler. */ static tree arm_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) { if (TREE_CODE (*node) != FUNCTION_DECL) { warning (OPT_Wattributes, "%qs attribute only applies to functions", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } return NULL_TREE; } /* Handle an "interrupt" or "isr" attribute; arguments as in struct attribute_spec.handler. */ static tree arm_handle_isr_attribute (tree *node, tree name, tree args, int flags, bool *no_add_attrs) { if (DECL_P (*node)) { if (TREE_CODE (*node) != FUNCTION_DECL) { warning (OPT_Wattributes, "%qs attribute only applies to functions", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } /* FIXME: the argument if any is checked for type attributes; should it be checked for decl ones? */ } else { if (TREE_CODE (*node) == FUNCTION_TYPE || TREE_CODE (*node) == METHOD_TYPE) { if (arm_isr_value (args) == ARM_FT_UNKNOWN) { warning (OPT_Wattributes, "%qs attribute ignored", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } } else if (TREE_CODE (*node) == POINTER_TYPE && (TREE_CODE (TREE_TYPE (*node)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE) && arm_isr_value (args) != ARM_FT_UNKNOWN) { *node = build_variant_type_copy (*node); TREE_TYPE (*node) = build_type_attribute_variant (TREE_TYPE (*node), tree_cons (name, args, TYPE_ATTRIBUTES (TREE_TYPE (*node)))); *no_add_attrs = true; } else { /* Possibly pass this attribute on from the type to a decl. */ if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT | (int) ATTR_FLAG_ARRAY_NEXT)) { *no_add_attrs = true; return tree_cons (name, args, NULL_TREE); } else { warning (OPT_Wattributes, "%qs attribute ignored", IDENTIFIER_POINTER (name)); } } } return NULL_TREE; } #if TARGET_DLLIMPORT_DECL_ATTRIBUTES /* Handle the "notshared" attribute. This attribute is another way of requesting hidden visibility. ARM's compiler supports "__declspec(notshared)"; we support the same thing via an attribute. */ static tree arm_handle_notshared_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) { tree decl = TYPE_NAME (*node); if (decl) { DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; DECL_VISIBILITY_SPECIFIED (decl) = 1; *no_add_attrs = false; } return NULL_TREE; } #endif /* Return 0 if the attributes for two types are incompatible, 1 if they are compatible, and 2 if they are nearly compatible (which causes a warning to be generated). */ static int arm_comp_type_attributes (tree type1, tree type2) { int l1, l2, s1, s2; /* Check for mismatch of non-default calling convention. */ if (TREE_CODE (type1) != FUNCTION_TYPE) return 1; /* Check for mismatched call attributes. */ l1 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1)) != NULL; l2 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2)) != NULL; s1 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1)) != NULL; s2 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2)) != NULL; /* Only bother to check if an attribute is defined. */ if (l1 | l2 | s1 | s2) { /* If one type has an attribute, the other must have the same attribute. */ if ((l1 != l2) || (s1 != s2)) return 0; /* Disallow mixed attributes. */ if ((l1 & s2) || (l2 & s1)) return 0; } /* Check for mismatched ISR attribute. */ l1 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type1)) != NULL; if (! l1) l1 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type1)) != NULL; l2 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type2)) != NULL; if (! l2) l1 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type2)) != NULL; if (l1 != l2) return 0; return 1; } /* Encode long_call or short_call attribute by prefixing symbol name in DECL with a special character FLAG. */ void arm_encode_call_attribute (tree decl, int flag) { const char * str = XSTR (XEXP (DECL_RTL (decl), 0), 0); int len = strlen (str); char * newstr; /* Do not allow weak functions to be treated as short call. */ if (DECL_WEAK (decl) && flag == SHORT_CALL_FLAG_CHAR) return; newstr = alloca (len + 2); newstr[0] = flag; strcpy (newstr + 1, str); newstr = (char *) ggc_alloc_string (newstr, len + 1); XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr; } /* Assigns default attributes to newly defined type. This is used to set short_call/long_call attributes for function types of functions defined inside corresponding #pragma scopes. */ static void arm_set_default_type_attributes (tree type) { /* Add __attribute__ ((long_call)) to all functions, when inside #pragma long_calls or __attribute__ ((short_call)), when inside #pragma no_long_calls. */ if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE) { tree type_attr_list, attr_name; type_attr_list = TYPE_ATTRIBUTES (type); if (arm_pragma_long_calls == LONG) attr_name = get_identifier ("long_call"); else if (arm_pragma_long_calls == SHORT) attr_name = get_identifier ("short_call"); else return; type_attr_list = tree_cons (attr_name, NULL_TREE, type_attr_list); TYPE_ATTRIBUTES (type) = type_attr_list; } } /* Return 1 if the operand is a SYMBOL_REF for a function known to be defined within the current compilation unit. If this cannot be determined, then 0 is returned. */ static int current_file_function_operand (rtx sym_ref) { /* This is a bit of a fib. A function will have a short call flag applied to its name if it has the short call attribute, or it has already been defined within the current compilation unit. */ if (ENCODED_SHORT_CALL_ATTR_P (XSTR (sym_ref, 0))) return 1; /* The current function is always defined within the current compilation unit. If it s a weak definition however, then this may not be the real definition of the function, and so we have to say no. */ if (sym_ref == XEXP (DECL_RTL (current_function_decl), 0) && !DECL_WEAK (current_function_decl)) return 1; /* We cannot make the determination - default to returning 0. */ return 0; } /* Return nonzero if a 32 bit "long_call" should be generated for this call. We generate a long_call if the function: a. has an __attribute__((long call)) or b. is within the scope of a #pragma long_calls or c. the -mlong-calls command line switch has been specified . and either: 1. -ffunction-sections is in effect or 2. the current function has __attribute__ ((section)) or 3. the target function has __attribute__ ((section)) However we do not generate a long call if the function: d. has an __attribute__ ((short_call)) or e. is inside the scope of a #pragma no_long_calls or f. is defined within the current compilation unit. This function will be called by C fragments contained in the machine description file. SYM_REF and CALL_COOKIE correspond to the matched rtl operands. CALL_SYMBOL is used to distinguish between two different callers of the function. It is set to 1 in the "call_symbol" and "call_symbol_value" patterns and to 0 in the "call" and "call_value" patterns. This is because of the difference in the SYM_REFs passed by these patterns. */ int arm_is_longcall_p (rtx sym_ref, int call_cookie, int call_symbol) { if (!call_symbol) { if (GET_CODE (sym_ref) != MEM) return 0; sym_ref = XEXP (sym_ref, 0); } if (GET_CODE (sym_ref) != SYMBOL_REF) return 0; if (call_cookie & CALL_SHORT) return 0; if (TARGET_LONG_CALLS) { if (flag_function_sections || DECL_SECTION_NAME (current_function_decl)) /* c.3 is handled by the definition of the ARM_DECLARE_FUNCTION_SIZE macro. */ return 1; } if (current_file_function_operand (sym_ref)) return 0; return (call_cookie & CALL_LONG) || ENCODED_LONG_CALL_ATTR_P (XSTR (sym_ref, 0)) || TARGET_LONG_CALLS; } /* Return nonzero if it is ok to make a tail-call to DECL. */ static bool arm_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) { int call_type = TARGET_LONG_CALLS ? CALL_LONG : CALL_NORMAL; if (cfun->machine->sibcall_blocked) return false; /* Never tailcall something for which we have no decl, or if we are in Thumb mode. */ if (decl == NULL || TARGET_THUMB) return false; /* Get the calling method. */ if (lookup_attribute ("short_call", TYPE_ATTRIBUTES (TREE_TYPE (decl)))) call_type = CALL_SHORT; else if (lookup_attribute ("long_call", TYPE_ATTRIBUTES (TREE_TYPE (decl)))) call_type = CALL_LONG; /* Cannot tail-call to long calls, since these are out of range of a branch instruction. However, if not compiling PIC, we know we can reach the symbol if it is in this compilation unit. */ if (call_type == CALL_LONG && (flag_pic || !TREE_ASM_WRITTEN (decl))) return false; /* If we are interworking and the function is not declared static then we can't tail-call it unless we know that it exists in this compilation unit (since it might be a Thumb routine). */ if (TARGET_INTERWORK && TREE_PUBLIC (decl) && !TREE_ASM_WRITTEN (decl)) return false; /* Never tailcall from an ISR routine - it needs a special exit sequence. */ if (IS_INTERRUPT (arm_current_func_type ())) return false; /* Everything else is ok. */ return true; } /* Addressing mode support functions. */ /* Return nonzero if X is a legitimate immediate operand when compiling for PIC. We know that X satisfies CONSTANT_P and flag_pic is true. */ int legitimate_pic_operand_p (rtx x) { if (GET_CODE (x) == SYMBOL_REF || (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)) return 0; return 1; } rtx legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) { if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF) { #ifndef AOF_ASSEMBLER rtx pic_ref, address; #endif rtx insn; int subregs = 0; /* If this function doesn't have a pic register, create one now. A lot of the logic here is made obscure by the fact that this routine gets called as part of the rtx cost estimation process. We don't want those calls to affect any assumptions about the real function; and further, we can't call entry_of_function() until we start the real expansion process. */ if (!current_function_uses_pic_offset_table) { gcc_assert (!no_new_pseudos); if (arm_pic_register != INVALID_REGNUM) { if (!cfun->machine->pic_reg) cfun->machine->pic_reg = gen_rtx_REG (Pmode, arm_pic_register); /* Play games to avoid marking the function as needing pic if we are being called as part of the cost-estimation process. */ if (!ir_type()) current_function_uses_pic_offset_table = 1; } else { rtx seq; if (!cfun->machine->pic_reg) cfun->machine->pic_reg = gen_reg_rtx (Pmode); /* Play games to avoid marking the function as needing pic if we are being called as part of the cost-estimation process. */ if (!ir_type()) { current_function_uses_pic_offset_table = 1; start_sequence (); arm_load_pic_register (0UL); seq = get_insns (); end_sequence (); emit_insn_after (seq, entry_of_function ()); } } } if (reg == 0) { gcc_assert (!no_new_pseudos); reg = gen_reg_rtx (Pmode); subregs = 1; } #ifdef AOF_ASSEMBLER /* The AOF assembler can generate relocations for these directly, and understands that the PIC register has to be added into the offset. */ insn = emit_insn (gen_pic_load_addr_based (reg, orig)); #else if (subregs) address = gen_reg_rtx (Pmode); else address = reg; if (TARGET_ARM) emit_insn (gen_pic_load_addr_arm (address, orig)); else emit_insn (gen_pic_load_addr_thumb (address, orig)); if ((GET_CODE (orig) == LABEL_REF || (GET_CODE (orig) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (orig))) && NEED_GOT_RELOC) pic_ref = gen_rtx_PLUS (Pmode, cfun->machine->pic_reg, address); else { pic_ref = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, cfun->machine->pic_reg, address)); } insn = emit_move_insn (reg, pic_ref); #endif /* Put a REG_EQUAL note on this insn, so that it can be optimized by loop. */ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig, REG_NOTES (insn)); return reg; } else if (GET_CODE (orig) == CONST) { rtx base, offset; if (GET_CODE (XEXP (orig, 0)) == PLUS && XEXP (XEXP (orig, 0), 0) == cfun->machine->pic_reg) return orig; if (GET_CODE (XEXP (orig, 0)) == UNSPEC && XINT (XEXP (orig, 0), 1) == UNSPEC_TLS) return orig; if (reg == 0) { gcc_assert (!no_new_pseudos); reg = gen_reg_rtx (Pmode); } gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS); base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg); offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode, base == reg ? 0 : reg); if (GET_CODE (offset) == CONST_INT) { /* The base register doesn't really matter, we only want to test the index for the appropriate mode. */ if (!arm_legitimate_index_p (mode, offset, SET, 0)) { gcc_assert (!no_new_pseudos); offset = force_reg (Pmode, offset); } if (GET_CODE (offset) == CONST_INT) return plus_constant (base, INTVAL (offset)); } if (GET_MODE_SIZE (mode) > 4 && (GET_MODE_CLASS (mode) == MODE_INT || TARGET_SOFT_FLOAT)) { emit_insn (gen_addsi3 (reg, base, offset)); return reg; } return gen_rtx_PLUS (Pmode, base, offset); } return orig; } /* Find a spare low register to use during the prolog of a function. */ static int thumb_find_work_register (unsigned long pushed_regs_mask) { int reg; /* Check the argument registers first as these are call-used. The register allocation order means that sometimes r3 might be used but earlier argument registers might not, so check them all. */ for (reg = LAST_ARG_REGNUM; reg >= 0; reg --) if (!regs_ever_live[reg]) return reg; /* Before going on to check the call-saved registers we can try a couple more ways of deducing that r3 is available. The first is when we are pushing anonymous arguments onto the stack and we have less than 4 registers worth of fixed arguments(*). In this case r3 will be part of the variable argument list and so we can be sure that it will be pushed right at the start of the function. Hence it will be available for the rest of the prologue. (*): ie current_function_pretend_args_size is greater than 0. */ if (cfun->machine->uses_anonymous_args && current_function_pretend_args_size > 0) return LAST_ARG_REGNUM; /* The other case is when we have fixed arguments but less than 4 registers worth. In this case r3 might be used in the body of the function, but it is not being used to convey an argument into the function. In theory we could just check current_function_args_size to see how many bytes are being passed in argument registers, but it seems that it is unreliable. Sometimes it will have the value 0 when in fact arguments are being passed. (See testcase execute/20021111-1.c for an example). So we also check the args_info.nregs field as well. The problem with this field is that it makes no allowances for arguments that are passed to the function but which are not used. Hence we could miss an opportunity when a function has an unused argument in r3. But it is better to be safe than to be sorry. */ if (! cfun->machine->uses_anonymous_args && current_function_args_size >= 0 && current_function_args_size <= (LAST_ARG_REGNUM * UNITS_PER_WORD) && cfun->args_info.nregs < 4) return LAST_ARG_REGNUM; /* Otherwise look for a call-saved register that is going to be pushed. */ for (reg = LAST_LO_REGNUM; reg > LAST_ARG_REGNUM; reg --) if (pushed_regs_mask & (1 << reg)) return reg; /* Something went wrong - thumb_compute_save_reg_mask() should have arranged for a suitable register to be pushed. */ gcc_unreachable (); } static GTY(()) int pic_labelno; /* Generate code to load the PIC register. In thumb mode SCRATCH is a low register. */ void arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED) { #ifndef AOF_ASSEMBLER rtx l1, labelno, pic_tmp, pic_tmp2, pic_rtx; rtx global_offset_table; if (current_function_uses_pic_offset_table == 0 || TARGET_SINGLE_PIC_BASE) return; gcc_assert (flag_pic); /* We use an UNSPEC rather than a LABEL_REF because this label never appears in the code stream. */ labelno = GEN_INT (pic_labelno++); l1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL); l1 = gen_rtx_CONST (VOIDmode, l1); global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); /* On the ARM the PC register contains 'dot + 8' at the time of the addition, on the Thumb it is 'dot + 4'. */ pic_tmp = plus_constant (l1, TARGET_ARM ? 8 : 4); if (GOT_PCREL) pic_tmp2 = gen_rtx_CONST (VOIDmode, gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx)); else pic_tmp2 = gen_rtx_CONST (VOIDmode, global_offset_table); pic_rtx = gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, pic_tmp2, pic_tmp)); if (TARGET_ARM) { emit_insn (gen_pic_load_addr_arm (cfun->machine->pic_reg, pic_rtx)); emit_insn (gen_pic_add_dot_plus_eight (cfun->machine->pic_reg, cfun->machine->pic_reg, labelno)); } else { if (arm_pic_register != INVALID_REGNUM && REGNO (cfun->machine->pic_reg) > LAST_LO_REGNUM) { /* We will have pushed the pic register, so we should always be able to find a work register. */ pic_tmp = gen_rtx_REG (SImode, thumb_find_work_register (saved_regs)); emit_insn (gen_pic_load_addr_thumb (pic_tmp, pic_rtx)); emit_insn (gen_movsi (pic_offset_table_rtx, pic_tmp)); } else emit_insn (gen_pic_load_addr_thumb (cfun->machine->pic_reg, pic_rtx)); emit_insn (gen_pic_add_dot_plus_four (cfun->machine->pic_reg, cfun->machine->pic_reg, labelno)); } /* Need to emit this whether or not we obey regdecls, since setjmp/longjmp can cause life info to screw up. */ emit_insn (gen_rtx_USE (VOIDmode, cfun->machine->pic_reg)); #endif /* AOF_ASSEMBLER */ } /* Return nonzero if X is valid as an ARM state addressing register. */ static int arm_address_register_rtx_p (rtx x, int strict_p) { int regno; if (GET_CODE (x) != REG) return 0; regno = REGNO (x); if (strict_p) return ARM_REGNO_OK_FOR_BASE_P (regno); return (regno <= LAST_ARM_REGNUM || regno >= FIRST_PSEUDO_REGISTER || regno == FRAME_POINTER_REGNUM || regno == ARG_POINTER_REGNUM); } /* Return TRUE if this rtx is the difference of a symbol and a label, and will reduce to a PC-relative relocation in the object file. Expressions like this can be left alone when generating PIC, rather than forced through the GOT. */ static int pcrel_constant_p (rtx x) { if (GET_CODE (x) == MINUS) return symbol_mentioned_p (XEXP (x, 0)) && label_mentioned_p (XEXP (x, 1)); return FALSE; } /* Return nonzero if X is a valid ARM state address operand. */ int arm_legitimate_address_p (enum machine_mode mode, rtx x, RTX_CODE outer, int strict_p) { bool use_ldrd; enum rtx_code code = GET_CODE (x); if (arm_address_register_rtx_p (x, strict_p)) return 1; use_ldrd = (TARGET_LDRD && (mode == DImode || (mode == DFmode && (TARGET_SOFT_FLOAT || TARGET_VFP)))); if (code == POST_INC || code == PRE_DEC || ((code == PRE_INC || code == POST_DEC) && (use_ldrd || GET_MODE_SIZE (mode) <= 4))) return arm_address_register_rtx_p (XEXP (x, 0), strict_p); else if ((code == POST_MODIFY || code == PRE_MODIFY) && arm_address_register_rtx_p (XEXP (x, 0), strict_p) && GET_CODE (XEXP (x, 1)) == PLUS && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0))) { rtx addend = XEXP (XEXP (x, 1), 1); /* Don't allow ldrd post increment by register because it's hard to fixup invalid register choices. */ if (use_ldrd && GET_CODE (x) == POST_MODIFY && GET_CODE (addend) == REG) return 0; return ((use_ldrd || GET_MODE_SIZE (mode) <= 4) && arm_legitimate_index_p (mode, addend, outer, strict_p)); } /* After reload constants split into minipools will have addresses from a LABEL_REF. */ else if (reload_completed && (code == LABEL_REF || (code == CONST && GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))) return 1; else if (mode == TImode) return 0; else if (code == PLUS) { rtx xop0 = XEXP (x, 0); rtx xop1 = XEXP (x, 1); return ((arm_address_register_rtx_p (xop0, strict_p) && arm_legitimate_index_p (mode, xop1, outer, strict_p)) || (arm_address_register_rtx_p (xop1, strict_p) && arm_legitimate_index_p (mode, xop0, outer, strict_p))); } #if 0 /* Reload currently can't handle MINUS, so disable this for now */ else if (GET_CODE (x) == MINUS) { rtx xop0 = XEXP (x, 0); rtx xop1 = XEXP (x, 1); return (arm_address_register_rtx_p (xop0, strict_p) && arm_legitimate_index_p (mode, xop1, outer, strict_p)); } #endif else if (GET_MODE_CLASS (mode) != MODE_FLOAT && code == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x) && ! (flag_pic && symbol_mentioned_p (get_pool_constant (x)) && ! pcrel_constant_p (get_pool_constant (x)))) return 1; return 0; } /* Return nonzero if INDEX is valid for an address index operand in ARM state. */ static int arm_legitimate_index_p (enum machine_mode mode, rtx index, RTX_CODE outer, int strict_p) { HOST_WIDE_INT range; enum rtx_code code = GET_CODE (index); /* Standard coprocessor addressing modes. */ if (TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_MAVERICK) && (GET_MODE_CLASS (mode) == MODE_FLOAT || (TARGET_MAVERICK && mode == DImode))) return (code == CONST_INT && INTVAL (index) < 1024 && INTVAL (index) > -1024 && (INTVAL (index) & 3) == 0); if (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (mode)) { /* For DImode assume values will usually live in core regs and only allow LDRD addressing modes. */ if (!TARGET_LDRD || mode != DImode) return (code == CONST_INT && INTVAL (index) < 1024 && INTVAL (index) > -1024 && (INTVAL (index) & 3) == 0); } if (arm_address_register_rtx_p (index, strict_p) && (GET_MODE_SIZE (mode) <= 4)) return 1; if (mode == DImode || mode == DFmode) { if (code == CONST_INT) { HOST_WIDE_INT val = INTVAL (index); if (TARGET_LDRD) return val > -256 && val < 256; else return val > -4096 && val < 4092; } return TARGET_LDRD && arm_address_register_rtx_p (index, strict_p); } if (GET_MODE_SIZE (mode) <= 4 && ! (arm_arch4 && (mode == HImode || (mode == QImode && outer == SIGN_EXTEND)))) { if (code == MULT) { rtx xiop0 = XEXP (index, 0); rtx xiop1 = XEXP (index, 1); return ((arm_address_register_rtx_p (xiop0, strict_p) && power_of_two_operand (xiop1, SImode)) || (arm_address_register_rtx_p (xiop1, strict_p) && power_of_two_operand (xiop0, SImode))); } else if (code == LSHIFTRT || code == ASHIFTRT || code == ASHIFT || code == ROTATERT) { rtx op = XEXP (index, 1); return (arm_address_register_rtx_p (XEXP (index, 0), strict_p) && GET_CODE (op) == CONST_INT && INTVAL (op) > 0 && INTVAL (op) <= 31); } } /* For ARM v4 we may be doing a sign-extend operation during the load. */ if (arm_arch4) { if (mode == HImode || (outer == SIGN_EXTEND && mode == QImode)) range = 256; else range = 4096; } else range = (mode == HImode) ? 4095 : 4096; return (code == CONST_INT && INTVAL (index) < range && INTVAL (index) > -range); } /* Return nonzero if X is valid as a Thumb state base register. */ static int thumb_base_register_rtx_p (rtx x, enum machine_mode mode, int strict_p) { int regno; if (GET_CODE (x) != REG) return 0; regno = REGNO (x); if (strict_p) return THUMB_REGNO_MODE_OK_FOR_BASE_P (regno, mode); return (regno <= LAST_LO_REGNUM || regno > LAST_VIRTUAL_REGISTER || regno == FRAME_POINTER_REGNUM || (GET_MODE_SIZE (mode) >= 4 && (regno == STACK_POINTER_REGNUM || regno >= FIRST_PSEUDO_REGISTER || x == hard_frame_pointer_rtx || x == arg_pointer_rtx))); } /* Return nonzero if x is a legitimate index register. This is the case for any base register that can access a QImode object. */ inline static int thumb_index_register_rtx_p (rtx x, int strict_p) { return thumb_base_register_rtx_p (x, QImode, strict_p); } /* Return nonzero if x is a legitimate Thumb-state address. The AP may be eliminated to either the SP or the FP, so we use the least common denominator, e.g. SImode, and offsets from 0 to 64. ??? Verify whether the above is the right approach. ??? Also, the FP may be eliminated to the SP, so perhaps that needs special handling also. ??? Look at how the mips16 port solves this problem. It probably uses better ways to solve some of these problems. Although it is not incorrect, we don't accept QImode and HImode addresses based on the frame pointer or arg pointer until the reload pass starts. This is so that eliminating such addresses into stack based ones won't produce impossible code. */ int thumb_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p) { /* ??? Not clear if this is right. Experiment. */ if (GET_MODE_SIZE (mode) < 4 && !(reload_in_progress || reload_completed) && (reg_mentioned_p (frame_pointer_rtx, x) || reg_mentioned_p (arg_pointer_rtx, x) || reg_mentioned_p (virtual_incoming_args_rtx, x) || reg_mentioned_p (virtual_outgoing_args_rtx, x) || reg_mentioned_p (virtual_stack_dynamic_rtx, x) || reg_mentioned_p (virtual_stack_vars_rtx, x))) return 0; /* Accept any base register. SP only in SImode or larger. */ else if (thumb_base_register_rtx_p (x, mode, strict_p)) return 1; /* This is PC relative data before arm_reorg runs. */ else if (GET_MODE_SIZE (mode) >= 4 && CONSTANT_P (x) && GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x) && !flag_pic) return 1; /* This is PC relative data after arm_reorg runs. */ else if (GET_MODE_SIZE (mode) >= 4 && reload_completed && (GET_CODE (x) == LABEL_REF || (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))) return 1; /* Post-inc indexing only supported for SImode and larger. */ else if (GET_CODE (x) == POST_INC && GET_MODE_SIZE (mode) >= 4 && thumb_index_register_rtx_p (XEXP (x, 0), strict_p)) return 1; else if (GET_CODE (x) == PLUS) { /* REG+REG address can be any two index registers. */ /* We disallow FRAME+REG addressing since we know that FRAME will be replaced with STACK, and SP relative addressing only permits SP+OFFSET. */ if (GET_MODE_SIZE (mode) <= 4 && XEXP (x, 0) != frame_pointer_rtx && XEXP (x, 1) != frame_pointer_rtx && thumb_index_register_rtx_p (XEXP (x, 0), strict_p) && thumb_index_register_rtx_p (XEXP (x, 1), strict_p)) return 1; /* REG+const has 5-7 bit offset for non-SP registers. */ else if ((thumb_index_register_rtx_p (XEXP (x, 0), strict_p) || XEXP (x, 0) == arg_pointer_rtx) && GET_CODE (XEXP (x, 1)) == CONST_INT && thumb_legitimate_offset_p (mode, INTVAL (XEXP (x, 1)))) return 1; /* REG+const has 10 bit offset for SP, but only SImode and larger is supported. */ /* ??? Should probably check for DI/DFmode overflow here just like GO_IF_LEGITIMATE_OFFSET does. */ else if (GET_CODE (XEXP (x, 0)) == REG && REGNO (XEXP (x, 0)) == STACK_POINTER_REGNUM && GET_MODE_SIZE (mode) >= 4 && GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) >= 0 && INTVAL (XEXP (x, 1)) + GET_MODE_SIZE (mode) <= 1024 && (INTVAL (XEXP (x, 1)) & 3) == 0) return 1; else if (GET_CODE (XEXP (x, 0)) == REG && REGNO (XEXP (x, 0)) == FRAME_POINTER_REGNUM && GET_MODE_SIZE (mode) >= 4 && GET_CODE (XEXP (x, 1)) == CONST_INT && (INTVAL (XEXP (x, 1)) & 3) == 0) return 1; } else if (GET_MODE_CLASS (mode) != MODE_FLOAT && GET_MODE_SIZE (mode) == 4 && GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x) && ! (flag_pic && symbol_mentioned_p (get_pool_constant (x)) && ! pcrel_constant_p (get_pool_constant (x)))) return 1; return 0; } /* Return nonzero if VAL can be used as an offset in a Thumb-state address instruction of mode MODE. */ int thumb_legitimate_offset_p (enum machine_mode mode, HOST_WIDE_INT val) { switch (GET_MODE_SIZE (mode)) { case 1: return val >= 0 && val < 32; case 2: return val >= 0 && val < 64 && (val & 1) == 0; default: return (val >= 0 && (val + GET_MODE_SIZE (mode)) <= 128 && (val & 3) == 0); } } /* Build the SYMBOL_REF for __tls_get_addr. */ static GTY(()) rtx tls_get_addr_libfunc; static rtx get_tls_get_addr (void) { if (!tls_get_addr_libfunc) tls_get_addr_libfunc = init_one_libfunc ("__tls_get_addr"); return tls_get_addr_libfunc; } static rtx arm_load_tp (rtx target) { if (!target) target = gen_reg_rtx (SImode); if (TARGET_HARD_TP) { /* Can return in any reg. */ emit_insn (gen_load_tp_hard (target)); } else { /* Always returned in r0. Immediately copy the result into a pseudo, otherwise other uses of r0 (e.g. setting up function arguments) may clobber the value. */ rtx tmp; emit_insn (gen_load_tp_soft ()); tmp = gen_rtx_REG (SImode, 0); emit_move_insn (target, tmp); } return target; } static rtx load_tls_operand (rtx x, rtx reg) { rtx tmp; if (reg == NULL_RTX) reg = gen_reg_rtx (SImode); tmp = gen_rtx_CONST (SImode, x); emit_move_insn (reg, tmp); return reg; } static rtx arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc) { rtx insns, label, labelno, sum; start_sequence (); labelno = GEN_INT (pic_labelno++); label = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL); label = gen_rtx_CONST (VOIDmode, label); sum = gen_rtx_UNSPEC (Pmode, gen_rtvec (4, x, GEN_INT (reloc), label, GEN_INT (TARGET_ARM ? 8 : 4)), UNSPEC_TLS); reg = load_tls_operand (sum, reg); if (TARGET_ARM) emit_insn (gen_pic_add_dot_plus_eight (reg, reg, labelno)); else emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno)); *valuep = emit_library_call_value (get_tls_get_addr (), NULL_RTX, LCT_PURE, /* LCT_CONST? */ Pmode, 1, reg, Pmode); insns = get_insns (); end_sequence (); return insns; } rtx legitimize_tls_address (rtx x, rtx reg) { rtx dest, tp, label, labelno, sum, insns, ret, eqv, addend; unsigned int model = SYMBOL_REF_TLS_MODEL (x); switch (model) { case TLS_MODEL_GLOBAL_DYNAMIC: insns = arm_call_tls_get_addr (x, reg, &ret, TLS_GD32); dest = gen_reg_rtx (Pmode); emit_libcall_block (insns, dest, ret, x); return dest; case TLS_MODEL_LOCAL_DYNAMIC: insns = arm_call_tls_get_addr (x, reg, &ret, TLS_LDM32); /* Attach a unique REG_EQUIV, to allow the RTL optimizers to share the LDM result with other LD model accesses. */ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const1_rtx), UNSPEC_TLS); dest = gen_reg_rtx (Pmode); emit_libcall_block (insns, dest, ret, eqv); /* Load the addend. */ addend = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (TLS_LDO32)), UNSPEC_TLS); addend = force_reg (SImode, gen_rtx_CONST (SImode, addend)); return gen_rtx_PLUS (Pmode, dest, addend); case TLS_MODEL_INITIAL_EXEC: labelno = GEN_INT (pic_labelno++); label = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL); label = gen_rtx_CONST (VOIDmode, label); sum = gen_rtx_UNSPEC (Pmode, gen_rtvec (4, x, GEN_INT (TLS_IE32), label, GEN_INT (TARGET_ARM ? 8 : 4)), UNSPEC_TLS); reg = load_tls_operand (sum, reg); if (TARGET_ARM) emit_insn (gen_tls_load_dot_plus_eight (reg, reg, labelno)); else { emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno)); emit_move_insn (reg, gen_const_mem (SImode, reg)); } tp = arm_load_tp (NULL_RTX); return gen_rtx_PLUS (Pmode, tp, reg); case TLS_MODEL_LOCAL_EXEC: tp = arm_load_tp (NULL_RTX); reg = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (TLS_LE32)), UNSPEC_TLS); reg = force_reg (SImode, gen_rtx_CONST (SImode, reg)); return gen_rtx_PLUS (Pmode, tp, reg); default: abort (); } } /* Try machine-dependent ways of modifying an illegitimate address to be legitimate. If we find one, return the new, valid address. */ rtx arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode) { if (arm_tls_symbol_p (x)) return legitimize_tls_address (x, NULL_RTX); if (GET_CODE (x) == PLUS) { rtx xop0 = XEXP (x, 0); rtx xop1 = XEXP (x, 1); if (CONSTANT_P (xop0) && !symbol_mentioned_p (xop0)) xop0 = force_reg (SImode, xop0); if (CONSTANT_P (xop1) && !symbol_mentioned_p (xop1)) xop1 = force_reg (SImode, xop1); if (ARM_BASE_REGISTER_RTX_P (xop0) && GET_CODE (xop1) == CONST_INT) { HOST_WIDE_INT n, low_n; rtx base_reg, val; n = INTVAL (xop1); /* VFP addressing modes actually allow greater offsets, but for now we just stick with the lowest common denominator. */ if (mode == DImode || ((TARGET_SOFT_FLOAT || TARGET_VFP) && mode == DFmode)) { low_n = n & 0x0f; n &= ~0x0f; if (low_n > 4) { n += 16; low_n -= 16; } } else { low_n = ((mode) == TImode ? 0 : n >= 0 ? (n & 0xfff) : -((-n) & 0xfff)); n -= low_n; } base_reg = gen_reg_rtx (SImode); val = force_operand (plus_constant (xop0, n), NULL_RTX); emit_move_insn (base_reg, val); x = plus_constant (base_reg, low_n); } else if (xop0 != XEXP (x, 0) || xop1 != XEXP (x, 1)) x = gen_rtx_PLUS (SImode, xop0, xop1); } /* XXX We don't allow MINUS any more -- see comment in arm_legitimate_address_p (). */ else if (GET_CODE (x) == MINUS) { rtx xop0 = XEXP (x, 0); rtx xop1 = XEXP (x, 1); if (CONSTANT_P (xop0)) xop0 = force_reg (SImode, xop0); if (CONSTANT_P (xop1) && ! symbol_mentioned_p (xop1)) xop1 = force_reg (SImode, xop1); if (xop0 != XEXP (x, 0) || xop1 != XEXP (x, 1)) x = gen_rtx_MINUS (SImode, xop0, xop1); } /* Make sure to take full advantage of the pre-indexed addressing mode with absolute addresses which often allows for the base register to be factorized for multiple adjacent memory references, and it might even allows for the mini pool to be avoided entirely. */ else if (GET_CODE (x) == CONST_INT && optimize > 0) { unsigned int bits; HOST_WIDE_INT mask, base, index; rtx base_reg; /* ldr and ldrb can use a 12 bit index, ldrsb and the rest can only use a 8 bit index. So let's use a 12 bit index for SImode only and hope that arm_gen_constant will enable ldrb to use more bits. */ bits = (mode == SImode) ? 12 : 8; mask = (1 << bits) - 1; base = INTVAL (x) & ~mask; index = INTVAL (x) & mask; if (bit_count (base & 0xffffffff) > (32 - bits)/2) { /* It'll most probably be more efficient to generate the base with more bits set and use a negative index instead. */ base |= mask; index -= mask; } base_reg = force_reg (SImode, GEN_INT (base)); x = plus_constant (base_reg, index); } if (flag_pic) { /* We need to find and carefully transform any SYMBOL and LABEL references; so go back to the original address expression. */ rtx new_x = legitimize_pic_address (orig_x, mode, NULL_RTX); if (new_x != orig_x) x = new_x; } return x; } /* Try machine-dependent ways of modifying an illegitimate Thumb address to be legitimate. If we find one, return the new, valid address. */ rtx thumb_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode) { if (arm_tls_symbol_p (x)) return legitimize_tls_address (x, NULL_RTX); if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT && (INTVAL (XEXP (x, 1)) >= 32 * GET_MODE_SIZE (mode) || INTVAL (XEXP (x, 1)) < 0)) { rtx xop0 = XEXP (x, 0); rtx xop1 = XEXP (x, 1); HOST_WIDE_INT offset = INTVAL (xop1); /* Try and fold the offset into a biasing of the base register and then offsetting that. Don't do this when optimizing for space since it can cause too many CSEs. */ if (optimize_size && offset >= 0 && offset < 256 + 31 * GET_MODE_SIZE (mode)) { HOST_WIDE_INT delta; if (offset >= 256) delta = offset - (256 - GET_MODE_SIZE (mode)); else if (offset < 32 * GET_MODE_SIZE (mode) + 8) delta = 31 * GET_MODE_SIZE (mode); else delta = offset & (~31 * GET_MODE_SIZE (mode)); xop0 = force_operand (plus_constant (xop0, offset - delta), NULL_RTX); x = plus_constant (xop0, delta); } else if (offset < 0 && offset > -256) /* Small negative offsets are best done with a subtract before the dereference, forcing these into a register normally takes two instructions. */ x = force_operand (x, NULL_RTX); else { /* For the remaining cases, force the constant into a register. */ xop1 = force_reg (SImode, xop1); x = gen_rtx_PLUS (SImode, xop0, xop1); } } else if (GET_CODE (x) == PLUS && s_register_operand (XEXP (x, 1), SImode) && !s_register_operand (XEXP (x, 0), SImode)) { rtx xop0 = force_operand (XEXP (x, 0), NULL_RTX); x = gen_rtx_PLUS (SImode, xop0, XEXP (x, 1)); } if (flag_pic) { /* We need to find and carefully transform any SYMBOL and LABEL references; so go back to the original address expression. */ rtx new_x = legitimize_pic_address (orig_x, mode, NULL_RTX); if (new_x != orig_x) x = new_x; } return x; } rtx thumb_legitimize_reload_address (rtx *x_p, enum machine_mode mode, int opnum, int type, int ind_levels ATTRIBUTE_UNUSED) { rtx x = *x_p; if (GET_CODE (x) == PLUS && GET_MODE_SIZE (mode) < 4 && REG_P (XEXP (x, 0)) && XEXP (x, 0) == stack_pointer_rtx && GET_CODE (XEXP (x, 1)) == CONST_INT && !thumb_legitimate_offset_p (mode, INTVAL (XEXP (x, 1)))) { rtx orig_x = x; x = copy_rtx (x); push_reload (orig_x, NULL_RTX, x_p, NULL, MODE_BASE_REG_CLASS (mode), Pmode, VOIDmode, 0, 0, opnum, type); return x; } /* If both registers are hi-regs, then it's better to reload the entire expression rather than each register individually. That only requires one reload register rather than two. */ if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)) && !REG_MODE_OK_FOR_REG_BASE_P (XEXP (x, 0), mode) && !REG_MODE_OK_FOR_REG_BASE_P (XEXP (x, 1), mode)) { rtx orig_x = x; x = copy_rtx (x); push_reload (orig_x, NULL_RTX, x_p, NULL, MODE_BASE_REG_CLASS (mode), Pmode, VOIDmode, 0, 0, opnum, type); return x; } return NULL; } /* Test for various thread-local symbols. */ /* Return TRUE if X is a thread-local symbol. */ static bool arm_tls_symbol_p (rtx x) { if (! TARGET_HAVE_TLS) return false; if (GET_CODE (x) != SYMBOL_REF) return false; return SYMBOL_REF_TLS_MODEL (x) != 0; } /* Helper for arm_tls_referenced_p. */ static int arm_tls_operand_p_1 (rtx *x, void *data ATTRIBUTE_UNUSED) { if (GET_CODE (*x) == SYMBOL_REF) return SYMBOL_REF_TLS_MODEL (*x) != 0; /* Don't recurse into UNSPEC_TLS looking for TLS symbols; these are TLS offsets, not real symbol references. */ if (GET_CODE (*x) == UNSPEC && XINT (*x, 1) == UNSPEC_TLS) return -1; return 0; } /* Return TRUE if X contains any TLS symbol references. */ bool arm_tls_referenced_p (rtx x) { if (! TARGET_HAVE_TLS) return false; return for_each_rtx (&x, arm_tls_operand_p_1, NULL); } #define REG_OR_SUBREG_REG(X) \ (GET_CODE (X) == REG \ || (GET_CODE (X) == SUBREG && GET_CODE (SUBREG_REG (X)) == REG)) #define REG_OR_SUBREG_RTX(X) \ (GET_CODE (X) == REG ? (X) : SUBREG_REG (X)) #ifndef COSTS_N_INSNS #define COSTS_N_INSNS(N) ((N) * 4 - 2) #endif static inline int thumb_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer) { enum machine_mode mode = GET_MODE (x); switch (code) { case ASHIFT: case ASHIFTRT: case LSHIFTRT: case ROTATERT: case PLUS: case MINUS: case COMPARE: case NEG: case NOT: return COSTS_N_INSNS (1); case MULT: if (GET_CODE (XEXP (x, 1)) == CONST_INT) { int cycles = 0; unsigned HOST_WIDE_INT i = INTVAL (XEXP (x, 1)); while (i) { i >>= 2; cycles++; } return COSTS_N_INSNS (2) + cycles; } return COSTS_N_INSNS (1) + 16; case SET: return (COSTS_N_INSNS (1) + 4 * ((GET_CODE (SET_SRC (x)) == MEM) + GET_CODE (SET_DEST (x)) == MEM)); case CONST_INT: if (outer == SET) { if ((unsigned HOST_WIDE_INT) INTVAL (x) < 256) return 0; if (thumb_shiftable_const (INTVAL (x))) return COSTS_N_INSNS (2); return COSTS_N_INSNS (3); } else if ((outer == PLUS || outer == COMPARE) && INTVAL (x) < 256 && INTVAL (x) > -256) return 0; else if (outer == AND && INTVAL (x) < 256 && INTVAL (x) >= -256) return COSTS_N_INSNS (1); else if (outer == ASHIFT || outer == ASHIFTRT || outer == LSHIFTRT) return 0; return COSTS_N_INSNS (2); case CONST: case CONST_DOUBLE: case LABEL_REF: case SYMBOL_REF: return COSTS_N_INSNS (3); case UDIV: case UMOD: case DIV: case MOD: return 100; case TRUNCATE: return 99; case AND: case XOR: case IOR: /* XXX guess. */ return 8; case MEM: /* XXX another guess. */ /* Memory costs quite a lot for the first word, but subsequent words load at the equivalent of a single insn each. */ return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD) + ((GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x)) ? 4 : 0)); case IF_THEN_ELSE: /* XXX a guess. */ if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC) return 14; return 2; case ZERO_EXTEND: /* XXX still guessing. */ switch (GET_MODE (XEXP (x, 0))) { case QImode: return (1 + (mode == DImode ? 4 : 0) + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); case HImode: return (4 + (mode == DImode ? 4 : 0) + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); case SImode: return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); default: return 99; } default: return 99; } } /* Worker routine for arm_rtx_costs. */ static inline int arm_rtx_costs_1 (rtx x, enum rtx_code code, enum rtx_code outer) { enum machine_mode mode = GET_MODE (x); enum rtx_code subcode; int extra_cost; switch (code) { case MEM: /* Memory costs quite a lot for the first word, but subsequent words load at the equivalent of a single insn each. */ return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD) + (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x) ? 4 : 0)); case DIV: case MOD: case UDIV: case UMOD: return optimize_size ? COSTS_N_INSNS (2) : 100; case ROTATE: if (mode == SImode && GET_CODE (XEXP (x, 1)) == REG) return 4; /* Fall through */ case ROTATERT: if (mode != SImode) return 8; /* Fall through */ case ASHIFT: case LSHIFTRT: case ASHIFTRT: if (mode == DImode) return (8 + (GET_CODE (XEXP (x, 1)) == CONST_INT ? 0 : 8) + ((GET_CODE (XEXP (x, 0)) == REG || (GET_CODE (XEXP (x, 0)) == SUBREG && GET_CODE (SUBREG_REG (XEXP (x, 0))) == REG)) ? 0 : 8)); return (1 + ((GET_CODE (XEXP (x, 0)) == REG || (GET_CODE (XEXP (x, 0)) == SUBREG && GET_CODE (SUBREG_REG (XEXP (x, 0))) == REG)) ? 0 : 4) + ((GET_CODE (XEXP (x, 1)) == REG || (GET_CODE (XEXP (x, 1)) == SUBREG && GET_CODE (SUBREG_REG (XEXP (x, 1))) == REG) || (GET_CODE (XEXP (x, 1)) == CONST_INT)) ? 0 : 4)); case MINUS: if (mode == DImode) return (4 + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 8) + ((REG_OR_SUBREG_REG (XEXP (x, 0)) || (GET_CODE (XEXP (x, 0)) == CONST_INT && const_ok_for_arm (INTVAL (XEXP (x, 0))))) ? 0 : 8)); if (GET_MODE_CLASS (mode) == MODE_FLOAT) return (2 + ((REG_OR_SUBREG_REG (XEXP (x, 1)) || (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE && arm_const_double_rtx (XEXP (x, 1)))) ? 0 : 8) + ((REG_OR_SUBREG_REG (XEXP (x, 0)) || (GET_CODE (XEXP (x, 0)) == CONST_DOUBLE && arm_const_double_rtx (XEXP (x, 0)))) ? 0 : 8)); if (((GET_CODE (XEXP (x, 0)) == CONST_INT && const_ok_for_arm (INTVAL (XEXP (x, 0))) && REG_OR_SUBREG_REG (XEXP (x, 1)))) || (((subcode = GET_CODE (XEXP (x, 1))) == ASHIFT || subcode == ASHIFTRT || subcode == LSHIFTRT || subcode == ROTATE || subcode == ROTATERT || (subcode == MULT && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT && ((INTVAL (XEXP (XEXP (x, 1), 1)) & (INTVAL (XEXP (XEXP (x, 1), 1)) - 1)) == 0))) && REG_OR_SUBREG_REG (XEXP (XEXP (x, 1), 0)) && (REG_OR_SUBREG_REG (XEXP (XEXP (x, 1), 1)) || GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT) && REG_OR_SUBREG_REG (XEXP (x, 0)))) return 1; /* Fall through */ case PLUS: if (GET_CODE (XEXP (x, 0)) == MULT) { extra_cost = rtx_cost (XEXP (x, 0), code); if (!REG_OR_SUBREG_REG (XEXP (x, 1))) extra_cost += 4 * ARM_NUM_REGS (mode); return extra_cost; } if (GET_MODE_CLASS (mode) == MODE_FLOAT) return (2 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 8) + ((REG_OR_SUBREG_REG (XEXP (x, 1)) || (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE && arm_const_double_rtx (XEXP (x, 1)))) ? 0 : 8)); /* Fall through */ case AND: case XOR: case IOR: extra_cost = 0; /* Normally the frame registers will be spilt into reg+const during reload, so it is a bad idea to combine them with other instructions, since then they might not be moved outside of loops. As a compromise we allow integration with ops that have a constant as their second operand. */ if ((REG_OR_SUBREG_REG (XEXP (x, 0)) && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x, 0))) && GET_CODE (XEXP (x, 1)) != CONST_INT) || (REG_OR_SUBREG_REG (XEXP (x, 0)) && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x, 0))))) extra_cost = 4; if (mode == DImode) return (4 + extra_cost + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 8) + ((REG_OR_SUBREG_REG (XEXP (x, 1)) || (GET_CODE (XEXP (x, 1)) == CONST_INT && const_ok_for_op (INTVAL (XEXP (x, 1)), code))) ? 0 : 8)); if (REG_OR_SUBREG_REG (XEXP (x, 0))) return (1 + (GET_CODE (XEXP (x, 1)) == CONST_INT ? 0 : extra_cost) + ((REG_OR_SUBREG_REG (XEXP (x, 1)) || (GET_CODE (XEXP (x, 1)) == CONST_INT && const_ok_for_op (INTVAL (XEXP (x, 1)), code))) ? 0 : 4)); else if (REG_OR_SUBREG_REG (XEXP (x, 1))) return (1 + extra_cost + ((((subcode = GET_CODE (XEXP (x, 0))) == ASHIFT || subcode == LSHIFTRT || subcode == ASHIFTRT || subcode == ROTATE || subcode == ROTATERT || (subcode == MULT && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT && ((INTVAL (XEXP (XEXP (x, 0), 1)) & (INTVAL (XEXP (XEXP (x, 0), 1)) - 1)) == 0))) && (REG_OR_SUBREG_REG (XEXP (XEXP (x, 0), 0))) && ((REG_OR_SUBREG_REG (XEXP (XEXP (x, 0), 1))) || GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)) ? 0 : 4)); return 8; case MULT: /* This should have been handled by the CPU specific routines. */ gcc_unreachable (); case TRUNCATE: if (arm_arch3m && mode == SImode && GET_CODE (XEXP (x, 0)) == LSHIFTRT && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1))) && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND || GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND)) return 8; return 99; case NEG: if (GET_MODE_CLASS (mode) == MODE_FLOAT) return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 6); /* Fall through */ case NOT: if (mode == DImode) return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4); return 1 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4); case IF_THEN_ELSE: if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC) return 14; return 2; case COMPARE: return 1; case ABS: return 4 + (mode == DImode ? 4 : 0); case SIGN_EXTEND: if (GET_MODE (XEXP (x, 0)) == QImode) return (4 + (mode == DImode ? 4 : 0) + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); /* Fall through */ case ZERO_EXTEND: switch (GET_MODE (XEXP (x, 0))) { case QImode: return (1 + (mode == DImode ? 4 : 0) + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); case HImode: return (4 + (mode == DImode ? 4 : 0) + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); case SImode: return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); case V8QImode: case V4HImode: case V2SImode: case V4QImode: case V2HImode: return 1; default: gcc_unreachable (); } gcc_unreachable (); case CONST_INT: if (const_ok_for_arm (INTVAL (x))) return outer == SET ? 2 : -1; else if (outer == AND && const_ok_for_arm (~INTVAL (x))) return -1; else if ((outer == COMPARE || outer == PLUS || outer == MINUS) && const_ok_for_arm (-INTVAL (x))) return -1; else return 5; case CONST: case LABEL_REF: case SYMBOL_REF: return 6; case CONST_DOUBLE: if (arm_const_double_rtx (x)) return outer == SET ? 2 : -1; else if ((outer == COMPARE || outer == PLUS) && neg_const_double_rtx_ok_for_fpa (x)) return -1; return 7; default: return 99; } } /* RTX costs when optimizing for size. */ static bool arm_size_rtx_costs (rtx x, int code, int outer_code, int *total) { enum machine_mode mode = GET_MODE (x); if (TARGET_THUMB) { /* XXX TBD. For now, use the standard costs. */ *total = thumb_rtx_costs (x, code, outer_code); return true; } switch (code) { case MEM: /* A memory access costs 1 insn if the mode is small, or the address is a single register, otherwise it costs one insn per word. */ if (REG_P (XEXP (x, 0))) *total = COSTS_N_INSNS (1); else *total = COSTS_N_INSNS (ARM_NUM_REGS (mode)); return true; case DIV: case MOD: case UDIV: case UMOD: /* Needs a libcall, so it costs about this. */ *total = COSTS_N_INSNS (2); return false; case ROTATE: if (mode == SImode && GET_CODE (XEXP (x, 1)) == REG) { *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), code); return true; } /* Fall through */ case ROTATERT: case ASHIFT: case LSHIFTRT: case ASHIFTRT: if (mode == DImode && GET_CODE (XEXP (x, 1)) == CONST_INT) { *total = COSTS_N_INSNS (3) + rtx_cost (XEXP (x, 0), code); return true; } else if (mode == SImode) { *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), code); /* Slightly disparage register shifts, but not by much. */ if (GET_CODE (XEXP (x, 1)) != CONST_INT) *total += 1 + rtx_cost (XEXP (x, 1), code); return true; } /* Needs a libcall. */ *total = COSTS_N_INSNS (2); return false; case MINUS: if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT) { *total = COSTS_N_INSNS (1); return false; } if (mode == SImode) { enum rtx_code subcode0 = GET_CODE (XEXP (x, 0)); enum rtx_code subcode1 = GET_CODE (XEXP (x, 1)); if (subcode0 == ROTATE || subcode0 == ROTATERT || subcode0 == ASHIFT || subcode0 == LSHIFTRT || subcode0 == ASHIFTRT || subcode1 == ROTATE || subcode1 == ROTATERT || subcode1 == ASHIFT || subcode1 == LSHIFTRT || subcode1 == ASHIFTRT) { /* It's just the cost of the two operands. */ *total = 0; return false; } *total = COSTS_N_INSNS (1); return false; } *total = COSTS_N_INSNS (ARM_NUM_REGS (mode)); return false; case PLUS: if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT) { *total = COSTS_N_INSNS (1); return false; } /* Fall through */ case AND: case XOR: case IOR: if (mode == SImode) { enum rtx_code subcode = GET_CODE (XEXP (x, 0)); if (subcode == ROTATE || subcode == ROTATERT || subcode == ASHIFT || subcode == LSHIFTRT || subcode == ASHIFTRT || (code == AND && subcode == NOT)) { /* It's just the cost of the two operands. */ *total = 0; return false; } } *total = COSTS_N_INSNS (ARM_NUM_REGS (mode)); return false; case MULT: *total = COSTS_N_INSNS (ARM_NUM_REGS (mode)); return false; case NEG: if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT) *total = COSTS_N_INSNS (1); /* Fall through */ case NOT: *total = COSTS_N_INSNS (ARM_NUM_REGS (mode)); return false; case IF_THEN_ELSE: *total = 0; return false; case COMPARE: if (cc_register (XEXP (x, 0), VOIDmode)) * total = 0; else *total = COSTS_N_INSNS (1); return false; case ABS: if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT) *total = COSTS_N_INSNS (1); else *total = COSTS_N_INSNS (1 + ARM_NUM_REGS (mode)); return false; case SIGN_EXTEND: *total = 0; if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) < 4) { if (!(arm_arch4 && MEM_P (XEXP (x, 0)))) *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2); } if (mode == DImode) *total += COSTS_N_INSNS (1); return false; case ZERO_EXTEND: *total = 0; if (!(arm_arch4 && MEM_P (XEXP (x, 0)))) { switch (GET_MODE (XEXP (x, 0))) { case QImode: *total += COSTS_N_INSNS (1); break; case HImode: *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2); case SImode: break; default: *total += COSTS_N_INSNS (2); } } if (mode == DImode) *total += COSTS_N_INSNS (1); return false; case CONST_INT: if (const_ok_for_arm (INTVAL (x))) *total = COSTS_N_INSNS (outer_code == SET ? 1 : 0); else if (const_ok_for_arm (~INTVAL (x))) *total = COSTS_N_INSNS (outer_code == AND ? 0 : 1); else if (const_ok_for_arm (-INTVAL (x))) { if (outer_code == COMPARE || outer_code == PLUS || outer_code == MINUS) *total = 0; else *total = COSTS_N_INSNS (1); } else *total = COSTS_N_INSNS (2); return true; case CONST: case LABEL_REF: case SYMBOL_REF: *total = COSTS_N_INSNS (2); return true; case CONST_DOUBLE: *total = COSTS_N_INSNS (4); return true; default: if (mode != VOIDmode) *total = COSTS_N_INSNS (ARM_NUM_REGS (mode)); else *total = COSTS_N_INSNS (4); /* How knows? */ return false; } } /* RTX costs for cores with a slow MUL implementation. */ static bool arm_slowmul_rtx_costs (rtx x, int code, int outer_code, int *total) { enum machine_mode mode = GET_MODE (x); if (TARGET_THUMB) { *total = thumb_rtx_costs (x, code, outer_code); return true; } switch (code) { case MULT: if (GET_MODE_CLASS (mode) == MODE_FLOAT || mode == DImode) { *total = 30; return true; } if (GET_CODE (XEXP (x, 1)) == CONST_INT) { unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1)) & (unsigned HOST_WIDE_INT) 0xffffffff); int cost, const_ok = const_ok_for_arm (i); int j, booth_unit_size; /* Tune as appropriate. */ cost = const_ok ? 4 : 8; booth_unit_size = 2; for (j = 0; i && j < 32; j += booth_unit_size) { i >>= booth_unit_size; cost += 2; } *total = cost; return true; } *total = 30 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4) + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4); return true; default: *total = arm_rtx_costs_1 (x, code, outer_code); return true; } } /* RTX cost for cores with a fast multiply unit (M variants). */ static bool arm_fastmul_rtx_costs (rtx x, int code, int outer_code, int *total) { enum machine_mode mode = GET_MODE (x); if (TARGET_THUMB) { *total = thumb_rtx_costs (x, code, outer_code); return true; } switch (code) { case MULT: /* There is no point basing this on the tuning, since it is always the fast variant if it exists at all. */ if (mode == DImode && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1))) && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND)) { *total = 8; return true; } if (GET_MODE_CLASS (mode) == MODE_FLOAT || mode == DImode) { *total = 30; return true; } if (GET_CODE (XEXP (x, 1)) == CONST_INT) { unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1)) & (unsigned HOST_WIDE_INT) 0xffffffff); int cost, const_ok = const_ok_for_arm (i); int j, booth_unit_size; /* Tune as appropriate. */ cost = const_ok ? 4 : 8; booth_unit_size = 8; for (j = 0; i && j < 32; j += booth_unit_size) { i >>= booth_unit_size; cost += 2; } *total = cost; return true; } *total = 8 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4) + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4); return true; default: *total = arm_rtx_costs_1 (x, code, outer_code); return true; } } /* RTX cost for XScale CPUs. */ static bool arm_xscale_rtx_costs (rtx x, int code, int outer_code, int *total) { enum machine_mode mode = GET_MODE (x); if (TARGET_THUMB) { *total = thumb_rtx_costs (x, code, outer_code); return true; } switch (code) { case MULT: /* There is no point basing this on the tuning, since it is always the fast variant if it exists at all. */ if (mode == DImode && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1))) && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND)) { *total = 8; return true; } if (GET_MODE_CLASS (mode) == MODE_FLOAT || mode == DImode) { *total = 30; return true; } if (GET_CODE (XEXP (x, 1)) == CONST_INT) { unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1)) & (unsigned HOST_WIDE_INT) 0xffffffff); int cost, const_ok = const_ok_for_arm (i); unsigned HOST_WIDE_INT masked_const; /* The cost will be related to two insns. First a load of the constant (MOV or LDR), then a multiply. */ cost = 2; if (! const_ok) cost += 1; /* LDR is probably more expensive because of longer result latency. */ masked_const = i & 0xffff8000; if (masked_const != 0 && masked_const != 0xffff8000) { masked_const = i & 0xf8000000; if (masked_const == 0 || masked_const == 0xf8000000) cost += 1; else cost += 2; } *total = cost; return true; } *total = 8 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4) + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4); return true; case COMPARE: /* A COMPARE of a MULT is slow on XScale; the muls instruction will stall until the multiplication is complete. */ if (GET_CODE (XEXP (x, 0)) == MULT) *total = 4 + rtx_cost (XEXP (x, 0), code); else *total = arm_rtx_costs_1 (x, code, outer_code); return true; default: *total = arm_rtx_costs_1 (x, code, outer_code); return true; } } /* RTX costs for 9e (and later) cores. */ static bool arm_9e_rtx_costs (rtx x, int code, int outer_code, int *total) { enum machine_mode mode = GET_MODE (x); int nonreg_cost; int cost; if (TARGET_THUMB) { switch (code) { case MULT: *total = COSTS_N_INSNS (3); return true; default: *total = thumb_rtx_costs (x, code, outer_code); return true; } } switch (code) { case MULT: /* There is no point basing this on the tuning, since it is always the fast variant if it exists at all. */ if (mode == DImode && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1))) && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND)) { *total = 3; return true; } if (GET_MODE_CLASS (mode) == MODE_FLOAT) { *total = 30; return true; } if (mode == DImode) { cost = 7; nonreg_cost = 8; } else { cost = 2; nonreg_cost = 4; } *total = cost + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : nonreg_cost) + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : nonreg_cost); return true; default: *total = arm_rtx_costs_1 (x, code, outer_code); return true; } } /* All address computations that can be done are free, but rtx cost returns the same for practically all of them. So we weight the different types of address here in the order (most pref first): PRE/POST_INC/DEC, SHIFT or NON-INT sum, INT sum, REG, MEM or LABEL. */ static inline int arm_arm_address_cost (rtx x) { enum rtx_code c = GET_CODE (x); if (c == PRE_INC || c == PRE_DEC || c == POST_INC || c == POST_DEC) return 0; if (c == MEM || c == LABEL_REF || c == SYMBOL_REF) return 10; if (c == PLUS || c == MINUS) { if (GET_CODE (XEXP (x, 0)) == CONST_INT) return 2; if (ARITHMETIC_P (XEXP (x, 0)) || ARITHMETIC_P (XEXP (x, 1))) return 3; return 4; } return 6; } static inline int arm_thumb_address_cost (rtx x) { enum rtx_code c = GET_CODE (x); if (c == REG) return 1; if (c == PLUS && GET_CODE (XEXP (x, 0)) == REG && GET_CODE (XEXP (x, 1)) == CONST_INT) return 1; return 2; } static int arm_address_cost (rtx x) { return TARGET_ARM ? arm_arm_address_cost (x) : arm_thumb_address_cost (x); } static int arm_adjust_cost (rtx insn, rtx link, rtx dep, int cost) { rtx i_pat, d_pat; /* Some true dependencies can have a higher cost depending on precisely how certain input operands are used. */ if (arm_tune_xscale && REG_NOTE_KIND (link) == 0 && recog_memoized (insn) >= 0 && recog_memoized (dep) >= 0) { int shift_opnum = get_attr_shift (insn); enum attr_type attr_type = get_attr_type (dep); /* If nonzero, SHIFT_OPNUM contains the operand number of a shifted operand for INSN. If we have a shifted input operand and the instruction we depend on is another ALU instruction, then we may have to account for an additional stall. */ if (shift_opnum != 0 && (attr_type == TYPE_ALU_SHIFT || attr_type == TYPE_ALU_SHIFT_REG)) { rtx shifted_operand; int opno; /* Get the shifted operand. */ extract_insn (insn); shifted_operand = recog_data.operand[shift_opnum]; /* Iterate over all the operands in DEP. If we write an operand that overlaps with SHIFTED_OPERAND, then we have increase the cost of this dependency. */ extract_insn (dep); preprocess_constraints (); for (opno = 0; opno < recog_data.n_operands; opno++) { /* We can ignore strict inputs. */ if (recog_data.operand_type[opno] == OP_IN) continue; if (reg_overlap_mentioned_p (recog_data.operand[opno], shifted_operand)) return 2; } } } /* XXX This is not strictly true for the FPA. */ if (REG_NOTE_KIND (link) == REG_DEP_ANTI || REG_NOTE_KIND (link) == REG_DEP_OUTPUT) return 0; /* Call insns don't incur a stall, even if they follow a load. */ if (REG_NOTE_KIND (link) == 0 && GET_CODE (insn) == CALL_INSN) return 1; if ((i_pat = single_set (insn)) != NULL && GET_CODE (SET_SRC (i_pat)) == MEM && (d_pat = single_set (dep)) != NULL && GET_CODE (SET_DEST (d_pat)) == MEM) { rtx src_mem = XEXP (SET_SRC (i_pat), 0); /* This is a load after a store, there is no conflict if the load reads from a cached area. Assume that loads from the stack, and from the constant pool are cached, and that others will miss. This is a hack. */ if ((GET_CODE (src_mem) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (src_mem)) || reg_mentioned_p (stack_pointer_rtx, src_mem) || reg_mentioned_p (frame_pointer_rtx, src_mem) || reg_mentioned_p (hard_frame_pointer_rtx, src_mem)) return 1; } return cost; } static int fp_consts_inited = 0; /* Only zero is valid for VFP. Other values are also valid for FPA. */ static const char * const strings_fp[8] = { "0", "1", "2", "3", "4", "5", "0.5", "10" }; static REAL_VALUE_TYPE values_fp[8]; static void init_fp_table (void) { int i; REAL_VALUE_TYPE r; if (TARGET_VFP) fp_consts_inited = 1; else fp_consts_inited = 8; for (i = 0; i < fp_consts_inited; i++) { r = REAL_VALUE_ATOF (strings_fp[i], DFmode); values_fp[i] = r; } } /* Return TRUE if rtx X is a valid immediate FP constant. */ int arm_const_double_rtx (rtx x) { REAL_VALUE_TYPE r; int i; if (!fp_consts_inited) init_fp_table (); REAL_VALUE_FROM_CONST_DOUBLE (r, x); if (REAL_VALUE_MINUS_ZERO (r)) return 0; for (i = 0; i < fp_consts_inited; i++) if (REAL_VALUES_EQUAL (r, values_fp[i])) return 1; return 0; } /* Return TRUE if rtx X is a valid immediate FPA constant. */ int neg_const_double_rtx_ok_for_fpa (rtx x) { REAL_VALUE_TYPE r; int i; if (!fp_consts_inited) init_fp_table (); REAL_VALUE_FROM_CONST_DOUBLE (r, x); r = REAL_VALUE_NEGATE (r); if (REAL_VALUE_MINUS_ZERO (r)) return 0; for (i = 0; i < 8; i++) if (REAL_VALUES_EQUAL (r, values_fp[i])) return 1; return 0; } /* Predicates for `match_operand' and `match_operator'. */ /* Return nonzero if OP is a valid Cirrus memory address pattern. */ int cirrus_memory_offset (rtx op) { /* Reject eliminable registers. */ if (! (reload_in_progress || reload_completed) && ( reg_mentioned_p (frame_pointer_rtx, op) || reg_mentioned_p (arg_pointer_rtx, op) || reg_mentioned_p (virtual_incoming_args_rtx, op) || reg_mentioned_p (virtual_outgoing_args_rtx, op) || reg_mentioned_p (virtual_stack_dynamic_rtx, op) || reg_mentioned_p (virtual_stack_vars_rtx, op))) return 0; if (GET_CODE (op) == MEM) { rtx ind; ind = XEXP (op, 0); /* Match: (mem (reg)). */ if (GET_CODE (ind) == REG) return 1; /* Match: (mem (plus (reg) (const))). */ if (GET_CODE (ind) == PLUS && GET_CODE (XEXP (ind, 0)) == REG && REG_MODE_OK_FOR_BASE_P (XEXP (ind, 0), VOIDmode) && GET_CODE (XEXP (ind, 1)) == CONST_INT) return 1; } return 0; } /* Return TRUE if OP is a valid coprocessor memory address pattern. WB if true if writeback address modes are allowed. */ int arm_coproc_mem_operand (rtx op, bool wb) { rtx ind; /* Reject eliminable registers. */ if (! (reload_in_progress || reload_completed) && ( reg_mentioned_p (frame_pointer_rtx, op) || reg_mentioned_p (arg_pointer_rtx, op) || reg_mentioned_p (virtual_incoming_args_rtx, op) || reg_mentioned_p (virtual_outgoing_args_rtx, op) || reg_mentioned_p (virtual_stack_dynamic_rtx, op) || reg_mentioned_p (virtual_stack_vars_rtx, op))) return FALSE; /* Constants are converted into offsets from labels. */ if (GET_CODE (op) != MEM) return FALSE; ind = XEXP (op, 0); if (reload_completed && (GET_CODE (ind) == LABEL_REF || (GET_CODE (ind) == CONST && GET_CODE (XEXP (ind, 0)) == PLUS && GET_CODE (XEXP (XEXP (ind, 0), 0)) == LABEL_REF && GET_CODE (XEXP (XEXP (ind, 0), 1)) == CONST_INT))) return TRUE; /* Match: (mem (reg)). */ if (GET_CODE (ind) == REG) return arm_address_register_rtx_p (ind, 0); /* Autoincremment addressing modes. */ if (wb && (GET_CODE (ind) == PRE_INC || GET_CODE (ind) == POST_INC || GET_CODE (ind) == PRE_DEC || GET_CODE (ind) == POST_DEC)) return arm_address_register_rtx_p (XEXP (ind, 0), 0); if (wb && (GET_CODE (ind) == POST_MODIFY || GET_CODE (ind) == PRE_MODIFY) && arm_address_register_rtx_p (XEXP (ind, 0), 0) && GET_CODE (XEXP (ind, 1)) == PLUS && rtx_equal_p (XEXP (XEXP (ind, 1), 0), XEXP (ind, 0))) ind = XEXP (ind, 1); /* Match: (plus (reg) (const)). */ if (GET_CODE (ind) == PLUS && GET_CODE (XEXP (ind, 0)) == REG && REG_MODE_OK_FOR_BASE_P (XEXP (ind, 0), VOIDmode) && GET_CODE (XEXP (ind, 1)) == CONST_INT && INTVAL (XEXP (ind, 1)) > -1024 && INTVAL (XEXP (ind, 1)) < 1024 && (INTVAL (XEXP (ind, 1)) & 3) == 0) return TRUE; return FALSE; } /* Return true if X is a register that will be eliminated later on. */ int arm_eliminable_register (rtx x) { return REG_P (x) && (REGNO (x) == FRAME_POINTER_REGNUM || REGNO (x) == ARG_POINTER_REGNUM || (REGNO (x) >= FIRST_VIRTUAL_REGISTER && REGNO (x) <= LAST_VIRTUAL_REGISTER)); } /* Return GENERAL_REGS if a scratch register required to reload x to/from coprocessor registers. Otherwise return NO_REGS. */ enum reg_class coproc_secondary_reload_class (enum machine_mode mode, rtx x, bool wb) { if (arm_coproc_mem_operand (x, wb) || s_register_operand (x, mode)) return NO_REGS; return GENERAL_REGS; } /* Values which must be returned in the most-significant end of the return register. */ static bool arm_return_in_msb (tree valtype) { return (TARGET_AAPCS_BASED && BYTES_BIG_ENDIAN && (AGGREGATE_TYPE_P (valtype) || TREE_CODE (valtype) == COMPLEX_TYPE)); } /* Returns TRUE if INSN is an "LDR REG, ADDR" instruction. Use by the Cirrus Maverick code which has to workaround a hardware bug triggered by such instructions. */ static bool arm_memory_load_p (rtx insn) { rtx body, lhs, rhs;; if (insn == NULL_RTX || GET_CODE (insn) != INSN) return false; body = PATTERN (insn); if (GET_CODE (body) != SET) return false; lhs = XEXP (body, 0); rhs = XEXP (body, 1); lhs = REG_OR_SUBREG_RTX (lhs); /* If the destination is not a general purpose register we do not have to worry. */ if (GET_CODE (lhs) != REG || REGNO_REG_CLASS (REGNO (lhs)) != GENERAL_REGS) return false; /* As well as loads from memory we also have to react to loads of invalid constants which will be turned into loads from the minipool. */ return (GET_CODE (rhs) == MEM || GET_CODE (rhs) == SYMBOL_REF || note_invalid_constants (insn, -1, false)); } /* Return TRUE if INSN is a Cirrus instruction. */ static bool arm_cirrus_insn_p (rtx insn) { enum attr_cirrus attr; /* get_attr cannot accept USE or CLOBBER. */ if (!insn || GET_CODE (insn) != INSN || GET_CODE (PATTERN (insn)) == USE || GET_CODE (PATTERN (insn)) == CLOBBER) return 0; attr = get_attr_cirrus (insn); return attr != CIRRUS_NOT; } /* Cirrus reorg for invalid instruction combinations. */ static void cirrus_reorg (rtx first) { enum attr_cirrus attr; rtx body = PATTERN (first); rtx t; int nops; /* Any branch must be followed by 2 non Cirrus instructions. */ if (GET_CODE (first) == JUMP_INSN && GET_CODE (body) != RETURN) { nops = 0; t = next_nonnote_insn (first); if (arm_cirrus_insn_p (t)) ++ nops; if (arm_cirrus_insn_p (next_nonnote_insn (t))) ++ nops; while (nops --) emit_insn_after (gen_nop (), first); return; } /* (float (blah)) is in parallel with a clobber. */ if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0) body = XVECEXP (body, 0, 0); if (GET_CODE (body) == SET) { rtx lhs = XEXP (body, 0), rhs = XEXP (body, 1); /* cfldrd, cfldr64, cfstrd, cfstr64 must be followed by a non Cirrus insn. */ if (get_attr_cirrus (first) == CIRRUS_DOUBLE) { if (arm_cirrus_insn_p (next_nonnote_insn (first))) emit_insn_after (gen_nop (), first); return; } else if (arm_memory_load_p (first)) { unsigned int arm_regno; /* Any ldr/cfmvdlr, ldr/cfmvdhr, ldr/cfmvsr, ldr/cfmv64lr, ldr/cfmv64hr combination where the Rd field is the same in both instructions must be split with a non Cirrus insn. Example: ldr r0, blah nop cfmvsr mvf0, r0. */ /* Get Arm register number for ldr insn. */ if (GET_CODE (lhs) == REG) arm_regno = REGNO (lhs); else { gcc_assert (GET_CODE (rhs) == REG); arm_regno = REGNO (rhs); } /* Next insn. */ first = next_nonnote_insn (first); if (! arm_cirrus_insn_p (first)) return; body = PATTERN (first); /* (float (blah)) is in parallel with a clobber. */ if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0)) body = XVECEXP (body, 0, 0); if (GET_CODE (body) == FLOAT) body = XEXP (body, 0); if (get_attr_cirrus (first) == CIRRUS_MOVE && GET_CODE (XEXP (body, 1)) == REG && arm_regno == REGNO (XEXP (body, 1))) emit_insn_after (gen_nop (), first); return; } } /* get_attr cannot accept USE or CLOBBER. */ if (!first || GET_CODE (first) != INSN || GET_CODE (PATTERN (first)) == USE || GET_CODE (PATTERN (first)) == CLOBBER) return; attr = get_attr_cirrus (first); /* Any coprocessor compare instruction (cfcmps, cfcmpd, ...) must be followed by a non-coprocessor instruction. */ if (attr == CIRRUS_COMPARE) { nops = 0; t = next_nonnote_insn (first); if (arm_cirrus_insn_p (t)) ++ nops; if (arm_cirrus_insn_p (next_nonnote_insn (t))) ++ nops; while (nops --) emit_insn_after (gen_nop (), first); return; } } /* Return TRUE if X references a SYMBOL_REF. */ int symbol_mentioned_p (rtx x) { const char * fmt; int i; if (GET_CODE (x) == SYMBOL_REF) return 1; /* UNSPEC_TLS entries for a symbol include the SYMBOL_REF, but they are constant offsets, not symbols. */ if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS) return 0; fmt = GET_RTX_FORMAT (GET_CODE (x)); for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) { if (fmt[i] == 'E') { int j; for (j = XVECLEN (x, i) - 1; j >= 0; j--) if (symbol_mentioned_p (XVECEXP (x, i, j))) return 1; } else if (fmt[i] == 'e' && symbol_mentioned_p (XEXP (x, i))) return 1; } return 0; } /* Return TRUE if X references a LABEL_REF. */ int label_mentioned_p (rtx x) { const char * fmt; int i; if (GET_CODE (x) == LABEL_REF) return 1; /* UNSPEC_TLS entries for a symbol include a LABEL_REF for the referencing instruction, but they are constant offsets, not symbols. */ if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS) return 0; fmt = GET_RTX_FORMAT (GET_CODE (x)); for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) { if (fmt[i] == 'E') { int j; for (j = XVECLEN (x, i) - 1; j >= 0; j--) if (label_mentioned_p (XVECEXP (x, i, j))) return 1; } else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i))) return 1; } return 0; } int tls_mentioned_p (rtx x) { switch (GET_CODE (x)) { case CONST: return tls_mentioned_p (XEXP (x, 0)); case UNSPEC: if (XINT (x, 1) == UNSPEC_TLS) return 1; default: return 0; } } /* Must not copy a SET whose source operand is PC-relative. */ static bool arm_cannot_copy_insn_p (rtx insn) { rtx pat = PATTERN (insn); if (GET_CODE (pat) == PARALLEL && GET_CODE (XVECEXP (pat, 0, 0)) == SET) { rtx rhs = SET_SRC (XVECEXP (pat, 0, 0)); if (GET_CODE (rhs) == UNSPEC && XINT (rhs, 1) == UNSPEC_PIC_BASE) return TRUE; if (GET_CODE (rhs) == MEM && GET_CODE (XEXP (rhs, 0)) == UNSPEC && XINT (XEXP (rhs, 0), 1) == UNSPEC_PIC_BASE) return TRUE; } return FALSE; } enum rtx_code minmax_code (rtx x) { enum rtx_code code = GET_CODE (x); switch (code) { case SMAX: return GE; case SMIN: return LE; case UMIN: return LEU; case UMAX: return GEU; default: gcc_unreachable (); } } /* Return 1 if memory locations are adjacent. */ int adjacent_mem_locations (rtx a, rtx b) { /* We don't guarantee to preserve the order of these memory refs. */ if (volatile_refs_p (a) || volatile_refs_p (b)) return 0; if ((GET_CODE (XEXP (a, 0)) == REG || (GET_CODE (XEXP (a, 0)) == PLUS && GET_CODE (XEXP (XEXP (a, 0), 1)) == CONST_INT)) && (GET_CODE (XEXP (b, 0)) == REG || (GET_CODE (XEXP (b, 0)) == PLUS && GET_CODE (XEXP (XEXP (b, 0), 1)) == CONST_INT))) { HOST_WIDE_INT val0 = 0, val1 = 0; rtx reg0, reg1; int val_diff; if (GET_CODE (XEXP (a, 0)) == PLUS) { reg0 = XEXP (XEXP (a, 0), 0); val0 = INTVAL (XEXP (XEXP (a, 0), 1)); } else reg0 = XEXP (a, 0); if (GET_CODE (XEXP (b, 0)) == PLUS) { reg1 = XEXP (XEXP (b, 0), 0); val1 = INTVAL (XEXP (XEXP (b, 0), 1)); } else reg1 = XEXP (b, 0); /* Don't accept any offset that will require multiple instructions to handle, since this would cause the arith_adjacentmem pattern to output an overlong sequence. */ if (!const_ok_for_op (PLUS, val0) || !const_ok_for_op (PLUS, val1)) return 0; /* Don't allow an eliminable register: register elimination can make the offset too large. */ if (arm_eliminable_register (reg0)) return 0; val_diff = val1 - val0; if (arm_ld_sched) { /* If the target has load delay slots, then there's no benefit to using an ldm instruction unless the offset is zero and we are optimizing for size. */ return (optimize_size && (REGNO (reg0) == REGNO (reg1)) && (val0 == 0 || val1 == 0 || val0 == 4 || val1 == 4) && (val_diff == 4 || val_diff == -4)); } return ((REGNO (reg0) == REGNO (reg1)) && (val_diff == 4 || val_diff == -4)); } return 0; } int load_multiple_sequence (rtx *operands, int nops, int *regs, int *base, HOST_WIDE_INT *load_offset) { int unsorted_regs[4]; HOST_WIDE_INT unsorted_offsets[4]; int order[4]; int base_reg = -1; int i; /* Can only handle 2, 3, or 4 insns at present, though could be easily extended if required. */ gcc_assert (nops >= 2 && nops <= 4); /* Loop over the operands and check that the memory references are suitable (i.e. immediate offsets from the same base register). At the same time, extract the target register, and the memory offsets. */ for (i = 0; i < nops; i++) { rtx reg; rtx offset; /* Convert a subreg of a mem into the mem itself. */ if (GET_CODE (operands[nops + i]) == SUBREG) operands[nops + i] = alter_subreg (operands + (nops + i)); gcc_assert (GET_CODE (operands[nops + i]) == MEM); /* Don't reorder volatile memory references; it doesn't seem worth looking for the case where the order is ok anyway. */ if (MEM_VOLATILE_P (operands[nops + i])) return 0; offset = const0_rtx; if ((GET_CODE (reg = XEXP (operands[nops + i], 0)) == REG || (GET_CODE (reg) == SUBREG && GET_CODE (reg = SUBREG_REG (reg)) == REG)) || (GET_CODE (XEXP (operands[nops + i], 0)) == PLUS && ((GET_CODE (reg = XEXP (XEXP (operands[nops + i], 0), 0)) == REG) || (GET_CODE (reg) == SUBREG && GET_CODE (reg = SUBREG_REG (reg)) == REG)) && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1)) == CONST_INT))) { if (i == 0) { base_reg = REGNO (reg); unsorted_regs[0] = (GET_CODE (operands[i]) == REG ? REGNO (operands[i]) : REGNO (SUBREG_REG (operands[i]))); order[0] = 0; } else { if (base_reg != (int) REGNO (reg)) /* Not addressed from the same base register. */ return 0; unsorted_regs[i] = (GET_CODE (operands[i]) == REG ? REGNO (operands[i]) : REGNO (SUBREG_REG (operands[i]))); if (unsorted_regs[i] < unsorted_regs[order[0]]) order[0] = i; } /* If it isn't an integer register, or if it overwrites the base register but isn't the last insn in the list, then we can't do this. */ if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14 || (i != nops - 1 && unsorted_regs[i] == base_reg)) return 0; unsorted_offsets[i] = INTVAL (offset); } else /* Not a suitable memory address. */ return 0; } /* All the useful information has now been extracted from the operands into unsorted_regs and unsorted_offsets; additionally, order[0] has been set to the lowest numbered register in the list. Sort the registers into order, and check that the memory offsets are ascending and adjacent. */ for (i = 1; i < nops; i++) { int j; order[i] = order[i - 1]; for (j = 0; j < nops; j++) if (unsorted_regs[j] > unsorted_regs[order[i - 1]] && (order[i] == order[i - 1] || unsorted_regs[j] < unsorted_regs[order[i]])) order[i] = j; /* Have we found a suitable register? if not, one must be used more than once. */ if (order[i] == order[i - 1]) return 0; /* Is the memory address adjacent and ascending? */ if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4) return 0; } if (base) { *base = base_reg; for (i = 0; i < nops; i++) regs[i] = unsorted_regs[order[i]]; *load_offset = unsorted_offsets[order[0]]; } if (unsorted_offsets[order[0]] == 0) return 1; /* ldmia */ if (unsorted_offsets[order[0]] == 4) return 2; /* ldmib */ if (unsorted_offsets[order[nops - 1]] == 0) return 3; /* ldmda */ if (unsorted_offsets[order[nops - 1]] == -4) return 4; /* ldmdb */ /* For ARM8,9 & StrongARM, 2 ldr instructions are faster than an ldm if the offset isn't small enough. The reason 2 ldrs are faster is because these ARMs are able to do more than one cache access in a single cycle. The ARM9 and StrongARM have Harvard caches, whilst the ARM8 has a double bandwidth cache. This means that these cores can do both an instruction fetch and a data fetch in a single cycle, so the trick of calculating the address into a scratch register (one of the result regs) and then doing a load multiple actually becomes slower (and no smaller in code size). That is the transformation ldr rd1, [rbase + offset] ldr rd2, [rbase + offset + 4] to add rd1, rbase, offset ldmia rd1, {rd1, rd2} produces worse code -- '3 cycles + any stalls on rd2' instead of '2 cycles + any stalls on rd2'. On ARMs with only one cache access per cycle, the first sequence could never complete in less than 6 cycles, whereas the ldm sequence would only take 5 and would make better use of sequential accesses if not hitting the cache. We cheat here and test 'arm_ld_sched' which we currently know to only be true for the ARM8, ARM9 and StrongARM. If this ever changes, then the test below needs to be reworked. */ if (nops == 2 && arm_ld_sched) return 0; /* Can't do it without setting up the offset, only do this if it takes no more than one insn. */ return (const_ok_for_arm (unsorted_offsets[order[0]]) || const_ok_for_arm (-unsorted_offsets[order[0]])) ? 5 : 0; } const char * emit_ldm_seq (rtx *operands, int nops) { int regs[4]; int base_reg; HOST_WIDE_INT offset; char buf[100]; int i; switch (load_multiple_sequence (operands, nops, regs, &base_reg, &offset)) { case 1: strcpy (buf, "ldm%?ia\t"); break; case 2: strcpy (buf, "ldm%?ib\t"); break; case 3: strcpy (buf, "ldm%?da\t"); break; case 4: strcpy (buf, "ldm%?db\t"); break; case 5: if (offset >= 0) sprintf (buf, "add%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX, reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg], (long) offset); else sprintf (buf, "sub%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX, reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg], (long) -offset); output_asm_insn (buf, operands); base_reg = regs[0]; strcpy (buf, "ldm%?ia\t"); break; default: gcc_unreachable (); } sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX, reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]); for (i = 1; i < nops; i++) sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX, reg_names[regs[i]]); strcat (buf, "}\t%@ phole ldm"); output_asm_insn (buf, operands); return ""; } int store_multiple_sequence (rtx *operands, int nops, int *regs, int *base, HOST_WIDE_INT * load_offset) { int unsorted_regs[4]; HOST_WIDE_INT unsorted_offsets[4]; int order[4]; int base_reg = -1; int i; /* Can only handle 2, 3, or 4 insns at present, though could be easily extended if required. */ gcc_assert (nops >= 2 && nops <= 4); /* Loop over the operands and check that the memory references are suitable (i.e. immediate offsets from the same base register). At the same time, extract the target register, and the memory offsets. */ for (i = 0; i < nops; i++) { rtx reg; rtx offset; /* Convert a subreg of a mem into the mem itself. */ if (GET_CODE (operands[nops + i]) == SUBREG) operands[nops + i] = alter_subreg (operands + (nops + i)); gcc_assert (GET_CODE (operands[nops + i]) == MEM); /* Don't reorder volatile memory references; it doesn't seem worth looking for the case where the order is ok anyway. */ if (MEM_VOLATILE_P (operands[nops + i])) return 0; offset = const0_rtx; if ((GET_CODE (reg = XEXP (operands[nops + i], 0)) == REG || (GET_CODE (reg) == SUBREG && GET_CODE (reg = SUBREG_REG (reg)) == REG)) || (GET_CODE (XEXP (operands[nops + i], 0)) == PLUS && ((GET_CODE (reg = XEXP (XEXP (operands[nops + i], 0), 0)) == REG) || (GET_CODE (reg) == SUBREG && GET_CODE (reg = SUBREG_REG (reg)) == REG)) && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1)) == CONST_INT))) { if (i == 0) { base_reg = REGNO (reg); unsorted_regs[0] = (GET_CODE (operands[i]) == REG ? REGNO (operands[i]) : REGNO (SUBREG_REG (operands[i]))); order[0] = 0; } else { if (base_reg != (int) REGNO (reg)) /* Not addressed from the same base register. */ return 0; unsorted_regs[i] = (GET_CODE (operands[i]) == REG ? REGNO (operands[i]) : REGNO (SUBREG_REG (operands[i]))); if (unsorted_regs[i] < unsorted_regs[order[0]]) order[0] = i; } /* If it isn't an integer register, then we can't do this. */ if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14) return 0; unsorted_offsets[i] = INTVAL (offset); } else /* Not a suitable memory address. */ return 0; } /* All the useful information has now been extracted from the operands into unsorted_regs and unsorted_offsets; additionally, order[0] has been set to the lowest numbered register in the list. Sort the registers into order, and check that the memory offsets are ascending and adjacent. */ for (i = 1; i < nops; i++) { int j; order[i] = order[i - 1]; for (j = 0; j < nops; j++) if (unsorted_regs[j] > unsorted_regs[order[i - 1]] && (order[i] == order[i - 1] || unsorted_regs[j] < unsorted_regs[order[i]])) order[i] = j; /* Have we found a suitable register? if not, one must be used more than once. */ if (order[i] == order[i - 1]) return 0; /* Is the memory address adjacent and ascending? */ if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4) return 0; } if (base) { *base = base_reg; for (i = 0; i < nops; i++) regs[i] = unsorted_regs[order[i]]; *load_offset = unsorted_offsets[order[0]]; } if (unsorted_offsets[order[0]] == 0) return 1; /* stmia */ if (unsorted_offsets[order[0]] == 4) return 2; /* stmib */ if (unsorted_offsets[order[nops - 1]] == 0) return 3; /* stmda */ if (unsorted_offsets[order[nops - 1]] == -4) return 4; /* stmdb */ return 0; } const char * emit_stm_seq (rtx *operands, int nops) { int regs[4]; int base_reg; HOST_WIDE_INT offset; char buf[100]; int i; switch (store_multiple_sequence (operands, nops, regs, &base_reg, &offset)) { case 1: strcpy (buf, "stm%?ia\t"); break; case 2: strcpy (buf, "stm%?ib\t"); break; case 3: strcpy (buf, "stm%?da\t"); break; case 4: strcpy (buf, "stm%?db\t"); break; default: gcc_unreachable (); } sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX, reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]); for (i = 1; i < nops; i++) sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX, reg_names[regs[i]]); strcat (buf, "}\t%@ phole stm"); output_asm_insn (buf, operands); return ""; } /* Routines for use in generating RTL. */ rtx arm_gen_load_multiple (int base_regno, int count, rtx from, int up, int write_back, rtx basemem, HOST_WIDE_INT *offsetp) { HOST_WIDE_INT offset = *offsetp; int i = 0, j; rtx result; int sign = up ? 1 : -1; rtx mem, addr; /* XScale has load-store double instructions, but they have stricter alignment requirements than load-store multiple, so we cannot use them. For XScale ldm requires 2 + NREGS cycles to complete and blocks the pipeline until completion. NREGS CYCLES 1 3 2 4 3 5 4 6 An ldr instruction takes 1-3 cycles, but does not block the pipeline. NREGS CYCLES 1 1-3 2 2-6 3 3-9 4 4-12 Best case ldr will always win. However, the more ldr instructions we issue, the less likely we are to be able to schedule them well. Using ldr instructions also increases code size. As a compromise, we use ldr for counts of 1 or 2 regs, and ldm for counts of 3 or 4 regs. */ if (arm_tune_xscale && count <= 2 && ! optimize_size) { rtx seq; start_sequence (); for (i = 0; i < count; i++) { addr = plus_constant (from, i * 4 * sign); mem = adjust_automodify_address (basemem, SImode, addr, offset); emit_move_insn (gen_rtx_REG (SImode, base_regno + i), mem); offset += 4 * sign; } if (write_back) { emit_move_insn (from, plus_constant (from, count * 4 * sign)); *offsetp = offset; } seq = get_insns (); end_sequence (); return seq; } result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + (write_back ? 1 : 0))); if (write_back) { XVECEXP (result, 0, 0) = gen_rtx_SET (VOIDmode, from, plus_constant (from, count * 4 * sign)); i = 1; count++; } for (j = 0; i < count; i++, j++) { addr = plus_constant (from, j * 4 * sign); mem = adjust_automodify_address_nv (basemem, SImode, addr, offset); XVECEXP (result, 0, i) = gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, base_regno + j), mem); offset += 4 * sign; } if (write_back) *offsetp = offset; return result; } rtx arm_gen_store_multiple (int base_regno, int count, rtx to, int up, int write_back, rtx basemem, HOST_WIDE_INT *offsetp) { HOST_WIDE_INT offset = *offsetp; int i = 0, j; rtx result; int sign = up ? 1 : -1; rtx mem, addr; /* See arm_gen_load_multiple for discussion of the pros/cons of ldm/stm usage for XScale. */ if (arm_tune_xscale && count <= 2 && ! optimize_size) { rtx seq; start_sequence (); for (i = 0; i < count; i++) { addr = plus_constant (to, i * 4 * sign); mem = adjust_automodify_address (basemem, SImode, addr, offset); emit_move_insn (mem, gen_rtx_REG (SImode, base_regno + i)); offset += 4 * sign; } if (write_back) { emit_move_insn (to, plus_constant (to, count * 4 * sign)); *offsetp = offset; } seq = get_insns (); end_sequence (); return seq; } result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + (write_back ? 1 : 0))); if (write_back) { XVECEXP (result, 0, 0) = gen_rtx_SET (VOIDmode, to, plus_constant (to, count * 4 * sign)); i = 1; count++; } for (j = 0; i < count; i++, j++) { addr = plus_constant (to, j * 4 * sign); mem = adjust_automodify_address_nv (basemem, SImode, addr, offset); XVECEXP (result, 0, i) = gen_rtx_SET (VOIDmode, mem, gen_rtx_REG (SImode, base_regno + j)); offset += 4 * sign; } if (write_back) *offsetp = offset; return result; } int arm_gen_movmemqi (rtx *operands) { HOST_WIDE_INT in_words_to_go, out_words_to_go, last_bytes; HOST_WIDE_INT srcoffset, dstoffset; int i; rtx src, dst, srcbase, dstbase; rtx part_bytes_reg = NULL; rtx mem; if (GET_CODE (operands[2]) != CONST_INT || GET_CODE (operands[3]) != CONST_INT || INTVAL (operands[2]) > 64 || INTVAL (operands[3]) & 3) return 0; dstbase = operands[0]; srcbase = operands[1]; dst = copy_to_mode_reg (SImode, XEXP (dstbase, 0)); src = copy_to_mode_reg (SImode, XEXP (srcbase, 0)); in_words_to_go = ARM_NUM_INTS (INTVAL (operands[2])); out_words_to_go = INTVAL (operands[2]) / 4; last_bytes = INTVAL (operands[2]) & 3; dstoffset = srcoffset = 0; if (out_words_to_go != in_words_to_go && ((in_words_to_go - 1) & 3) != 0) part_bytes_reg = gen_rtx_REG (SImode, (in_words_to_go - 1) & 3); for (i = 0; in_words_to_go >= 2; i+=4) { if (in_words_to_go > 4) emit_insn (arm_gen_load_multiple (0, 4, src, TRUE, TRUE, srcbase, &srcoffset)); else emit_insn (arm_gen_load_multiple (0, in_words_to_go, src, TRUE, FALSE, srcbase, &srcoffset)); if (out_words_to_go) { if (out_words_to_go > 4) emit_insn (arm_gen_store_multiple (0, 4, dst, TRUE, TRUE, dstbase, &dstoffset)); else if (out_words_to_go != 1) emit_insn (arm_gen_store_multiple (0, out_words_to_go, dst, TRUE, (last_bytes == 0 ? FALSE : TRUE), dstbase, &dstoffset)); else { mem = adjust_automodify_address (dstbase, SImode, dst, dstoffset); emit_move_insn (mem, gen_rtx_REG (SImode, 0)); if (last_bytes != 0) { emit_insn (gen_addsi3 (dst, dst, GEN_INT (4))); dstoffset += 4; } } } in_words_to_go -= in_words_to_go < 4 ? in_words_to_go : 4; out_words_to_go -= out_words_to_go < 4 ? out_words_to_go : 4; } /* OUT_WORDS_TO_GO will be zero here if there are byte stores to do. */ if (out_words_to_go) { rtx sreg; mem = adjust_automodify_address (srcbase, SImode, src, srcoffset); sreg = copy_to_reg (mem); mem = adjust_automodify_address (dstbase, SImode, dst, dstoffset); emit_move_insn (mem, sreg); in_words_to_go--; gcc_assert (!in_words_to_go); /* Sanity check */ } if (in_words_to_go) { gcc_assert (in_words_to_go > 0); mem = adjust_automodify_address (srcbase, SImode, src, srcoffset); part_bytes_reg = copy_to_mode_reg (SImode, mem); } gcc_assert (!last_bytes || part_bytes_reg); if (BYTES_BIG_ENDIAN && last_bytes) { rtx tmp = gen_reg_rtx (SImode); /* The bytes we want are in the top end of the word. */ emit_insn (gen_lshrsi3 (tmp, part_bytes_reg, GEN_INT (8 * (4 - last_bytes)))); part_bytes_reg = tmp; while (last_bytes) { mem = adjust_automodify_address (dstbase, QImode, plus_constant (dst, last_bytes - 1), dstoffset + last_bytes - 1); emit_move_insn (mem, gen_lowpart (QImode, part_bytes_reg)); if (--last_bytes) { tmp = gen_reg_rtx (SImode); emit_insn (gen_lshrsi3 (tmp, part_bytes_reg, GEN_INT (8))); part_bytes_reg = tmp; } } } else { if (last_bytes > 1) { mem = adjust_automodify_address (dstbase, HImode, dst, dstoffset); emit_move_insn (mem, gen_lowpart (HImode, part_bytes_reg)); last_bytes -= 2; if (last_bytes) { rtx tmp = gen_reg_rtx (SImode); emit_insn (gen_addsi3 (dst, dst, const2_rtx)); emit_insn (gen_lshrsi3 (tmp, part_bytes_reg, GEN_INT (16))); part_bytes_reg = tmp; dstoffset += 2; } } if (last_bytes) { mem = adjust_automodify_address (dstbase, QImode, dst, dstoffset); emit_move_insn (mem, gen_lowpart (QImode, part_bytes_reg)); } } return 1; } /* Select a dominance comparison mode if possible for a test of the general form (OP (COND_OR (X) (Y)) (const_int 0)). We support three forms. COND_OR == DOM_CC_X_AND_Y => (X && Y) COND_OR == DOM_CC_NX_OR_Y => ((! X) || Y) COND_OR == DOM_CC_X_OR_Y => (X || Y) In all cases OP will be either EQ or NE, but we don't need to know which here. If we are unable to support a dominance comparison we return CC mode. This will then fail to match for the RTL expressions that generate this call. */ enum machine_mode arm_select_dominance_cc_mode (rtx x, rtx y, HOST_WIDE_INT cond_or) { enum rtx_code cond1, cond2; int swapped = 0; /* Currently we will probably get the wrong result if the individual comparisons are not simple. This also ensures that it is safe to reverse a comparison if necessary. */ if ((arm_select_cc_mode (cond1 = GET_CODE (x), XEXP (x, 0), XEXP (x, 1)) != CCmode) || (arm_select_cc_mode (cond2 = GET_CODE (y), XEXP (y, 0), XEXP (y, 1)) != CCmode)) return CCmode; /* The if_then_else variant of this tests the second condition if the first passes, but is true if the first fails. Reverse the first condition to get a true "inclusive-or" expression. */ if (cond_or == DOM_CC_NX_OR_Y) cond1 = reverse_condition (cond1); /* If the comparisons are not equal, and one doesn't dominate the other, then we can't do this. */ if (cond1 != cond2 && !comparison_dominates_p (cond1, cond2) && (swapped = 1, !comparison_dominates_p (cond2, cond1))) return CCmode; if (swapped) { enum rtx_code temp = cond1; cond1 = cond2; cond2 = temp; } switch (cond1) { case EQ: if (cond_or == DOM_CC_X_AND_Y) return CC_DEQmode; switch (cond2) { case EQ: return CC_DEQmode; case LE: return CC_DLEmode; case LEU: return CC_DLEUmode; case GE: return CC_DGEmode; case GEU: return CC_DGEUmode; default: gcc_unreachable (); } case LT: if (cond_or == DOM_CC_X_AND_Y) return CC_DLTmode; switch (cond2) { case LT: return CC_DLTmode; case LE: return CC_DLEmode; case NE: return CC_DNEmode; default: gcc_unreachable (); } case GT: if (cond_or == DOM_CC_X_AND_Y) return CC_DGTmode; switch (cond2) { case GT: return CC_DGTmode; case GE: return CC_DGEmode; case NE: return CC_DNEmode; default: gcc_unreachable (); } case LTU: if (cond_or == DOM_CC_X_AND_Y) return CC_DLTUmode; switch (cond2) { case LTU: return CC_DLTUmode; case LEU: return CC_DLEUmode; case NE: return CC_DNEmode; default: gcc_unreachable (); } case GTU: if (cond_or == DOM_CC_X_AND_Y) return CC_DGTUmode; switch (cond2) { case GTU: return CC_DGTUmode; case GEU: return CC_DGEUmode; case NE: return CC_DNEmode; default: gcc_unreachable (); } /* The remaining cases only occur when both comparisons are the same. */ case NE: gcc_assert (cond1 == cond2); return CC_DNEmode; case LE: gcc_assert (cond1 == cond2); return CC_DLEmode; case GE: gcc_assert (cond1 == cond2); return CC_DGEmode; case LEU: gcc_assert (cond1 == cond2); return CC_DLEUmode; case GEU: gcc_assert (cond1 == cond2); return CC_DGEUmode; default: gcc_unreachable (); } } enum machine_mode arm_select_cc_mode (enum rtx_code op, rtx x, rtx y) { /* All floating point compares return CCFP if it is an equality comparison, and CCFPE otherwise. */ if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) { switch (op) { case EQ: case NE: case UNORDERED: case ORDERED: case UNLT: case UNLE: case UNGT: case UNGE: case UNEQ: case LTGT: return CCFPmode; case LT: case LE: case GT: case GE: if (TARGET_HARD_FLOAT && TARGET_MAVERICK) return CCFPmode; return CCFPEmode; default: gcc_unreachable (); } } /* A compare with a shifted operand. Because of canonicalization, the comparison will have to be swapped when we emit the assembler. */ if (GET_MODE (y) == SImode && GET_CODE (y) == REG && (GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT || GET_CODE (x) == LSHIFTRT || GET_CODE (x) == ROTATE || GET_CODE (x) == ROTATERT)) return CC_SWPmode; /* This operation is performed swapped, but since we only rely on the Z flag we don't need an additional mode. */ if (GET_MODE (y) == SImode && REG_P (y) && GET_CODE (x) == NEG && (op == EQ || op == NE)) return CC_Zmode; /* This is a special case that is used by combine to allow a comparison of a shifted byte load to be split into a zero-extend followed by a comparison of the shifted integer (only valid for equalities and unsigned inequalities). */ if (GET_MODE (x) == SImode && GET_CODE (x) == ASHIFT && GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == 24 && GET_CODE (XEXP (x, 0)) == SUBREG && GET_CODE (SUBREG_REG (XEXP (x, 0))) == MEM && GET_MODE (SUBREG_REG (XEXP (x, 0))) == QImode && (op == EQ || op == NE || op == GEU || op == GTU || op == LTU || op == LEU) && GET_CODE (y) == CONST_INT) return CC_Zmode; /* A construct for a conditional compare, if the false arm contains 0, then both conditions must be true, otherwise either condition must be true. Not all conditions are possible, so CCmode is returned if it can't be done. */ if (GET_CODE (x) == IF_THEN_ELSE && (XEXP (x, 2) == const0_rtx || XEXP (x, 2) == const1_rtx) && COMPARISON_P (XEXP (x, 0)) && COMPARISON_P (XEXP (x, 1))) return arm_select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1), INTVAL (XEXP (x, 2))); /* Alternate canonicalizations of the above. These are somewhat cleaner. */ if (GET_CODE (x) == AND && COMPARISON_P (XEXP (x, 0)) && COMPARISON_P (XEXP (x, 1))) return arm_select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1), DOM_CC_X_AND_Y); if (GET_CODE (x) == IOR && COMPARISON_P (XEXP (x, 0)) && COMPARISON_P (XEXP (x, 1))) return arm_select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1), DOM_CC_X_OR_Y); /* An operation (on Thumb) where we want to test for a single bit. This is done by shifting that bit up into the top bit of a scratch register; we can then branch on the sign bit. */ if (TARGET_THUMB && GET_MODE (x) == SImode && (op == EQ || op == NE) && GET_CODE (x) == ZERO_EXTRACT && XEXP (x, 1) == const1_rtx) return CC_Nmode; /* An operation that sets the condition codes as a side-effect, the V flag is not set correctly, so we can only use comparisons where this doesn't matter. (For LT and GE we can use "mi" and "pl" instead.) */ if (GET_MODE (x) == SImode && y == const0_rtx && (op == EQ || op == NE || op == LT || op == GE) && (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS || GET_CODE (x) == AND || GET_CODE (x) == IOR || GET_CODE (x) == XOR || GET_CODE (x) == MULT || GET_CODE (x) == NOT || GET_CODE (x) == NEG || GET_CODE (x) == LSHIFTRT || GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT || GET_CODE (x) == ROTATERT || (TARGET_ARM && GET_CODE (x) == ZERO_EXTRACT))) return CC_NOOVmode; if (GET_MODE (x) == QImode && (op == EQ || op == NE)) return CC_Zmode; if (GET_MODE (x) == SImode && (op == LTU || op == GEU) && GET_CODE (x) == PLUS && (rtx_equal_p (XEXP (x, 0), y) || rtx_equal_p (XEXP (x, 1), y))) return CC_Cmode; return CCmode; } /* X and Y are two things to compare using CODE. Emit the compare insn and return the rtx for register 0 in the proper mode. FP means this is a floating point compare: I don't think that it is needed on the arm. */ rtx arm_gen_compare_reg (enum rtx_code code, rtx x, rtx y) { enum machine_mode mode = SELECT_CC_MODE (code, x, y); rtx cc_reg = gen_rtx_REG (mode, CC_REGNUM); emit_set_insn (cc_reg, gen_rtx_COMPARE (mode, x, y)); return cc_reg; } /* Generate a sequence of insns that will generate the correct return address mask depending on the physical architecture that the program is running on. */ rtx arm_gen_return_addr_mask (void) { rtx reg = gen_reg_rtx (Pmode); emit_insn (gen_return_addr_mask (reg)); return reg; } void arm_reload_in_hi (rtx *operands) { rtx ref = operands[1]; rtx base, scratch; HOST_WIDE_INT offset = 0; if (GET_CODE (ref) == SUBREG) { offset = SUBREG_BYTE (ref); ref = SUBREG_REG (ref); } if (GET_CODE (ref) == REG) { /* We have a pseudo which has been spilt onto the stack; there are two cases here: the first where there is a simple stack-slot replacement and a second where the stack-slot is out of range, or is used as a subreg. */ if (reg_equiv_mem[REGNO (ref)]) { ref = reg_equiv_mem[REGNO (ref)]; base = find_replacement (&XEXP (ref, 0)); } else /* The slot is out of range, or was dressed up in a SUBREG. */ base = reg_equiv_address[REGNO (ref)]; } else base = find_replacement (&XEXP (ref, 0)); /* Handle the case where the address is too complex to be offset by 1. */ if (GET_CODE (base) == MINUS || (GET_CODE (base) == PLUS && GET_CODE (XEXP (base, 1)) != CONST_INT)) { rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1); emit_set_insn (base_plus, base); base = base_plus; } else if (GET_CODE (base) == PLUS) { /* The addend must be CONST_INT, or we would have dealt with it above. */ HOST_WIDE_INT hi, lo; offset += INTVAL (XEXP (base, 1)); base = XEXP (base, 0); /* Rework the address into a legal sequence of insns. */ /* Valid range for lo is -4095 -> 4095 */ lo = (offset >= 0 ? (offset & 0xfff) : -((-offset) & 0xfff)); /* Corner case, if lo is the max offset then we would be out of range once we have added the additional 1 below, so bump the msb into the pre-loading insn(s). */ if (lo == 4095) lo &= 0x7ff; hi = ((((offset - lo) & (HOST_WIDE_INT) 0xffffffff) ^ (HOST_WIDE_INT) 0x80000000) - (HOST_WIDE_INT) 0x80000000); gcc_assert (hi + lo == offset); if (hi != 0) { rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1); /* Get the base address; addsi3 knows how to handle constants that require more than one insn. */ emit_insn (gen_addsi3 (base_plus, base, GEN_INT (hi))); base = base_plus; offset = lo; } } /* Operands[2] may overlap operands[0] (though it won't overlap operands[1]), that's why we asked for a DImode reg -- so we can use the bit that does not overlap. */ if (REGNO (operands[2]) == REGNO (operands[0])) scratch = gen_rtx_REG (SImode, REGNO (operands[2]) + 1); else scratch = gen_rtx_REG (SImode, REGNO (operands[2])); emit_insn (gen_zero_extendqisi2 (scratch, gen_rtx_MEM (QImode, plus_constant (base, offset)))); emit_insn (gen_zero_extendqisi2 (gen_rtx_SUBREG (SImode, operands[0], 0), gen_rtx_MEM (QImode, plus_constant (base, offset + 1)))); if (!BYTES_BIG_ENDIAN) emit_set_insn (gen_rtx_SUBREG (SImode, operands[0], 0), gen_rtx_IOR (SImode, gen_rtx_ASHIFT (SImode, gen_rtx_SUBREG (SImode, operands[0], 0), GEN_INT (8)), scratch)); else emit_set_insn (gen_rtx_SUBREG (SImode, operands[0], 0), gen_rtx_IOR (SImode, gen_rtx_ASHIFT (SImode, scratch, GEN_INT (8)), gen_rtx_SUBREG (SImode, operands[0], 0))); } /* Handle storing a half-word to memory during reload by synthesizing as two byte stores. Take care not to clobber the input values until after we have moved them somewhere safe. This code assumes that if the DImode scratch in operands[2] overlaps either the input value or output address in some way, then that value must die in this insn (we absolutely need two scratch registers for some corner cases). */ void arm_reload_out_hi (rtx *operands) { rtx ref = operands[0]; rtx outval = operands[1]; rtx base, scratch; HOST_WIDE_INT offset = 0; if (GET_CODE (ref) == SUBREG) { offset = SUBREG_BYTE (ref); ref = SUBREG_REG (ref); } if (GET_CODE (ref) == REG) { /* We have a pseudo which has been spilt onto the stack; there are two cases here: the first where there is a simple stack-slot replacement and a second where the stack-slot is out of range, or is used as a subreg. */ if (reg_equiv_mem[REGNO (ref)]) { ref = reg_equiv_mem[REGNO (ref)]; base = find_replacement (&XEXP (ref, 0)); } else /* The slot is out of range, or was dressed up in a SUBREG. */ base = reg_equiv_address[REGNO (ref)]; } else base = find_replacement (&XEXP (ref, 0)); scratch = gen_rtx_REG (SImode, REGNO (operands[2])); /* Handle the case where the address is too complex to be offset by 1. */ if (GET_CODE (base) == MINUS || (GET_CODE (base) == PLUS && GET_CODE (XEXP (base, 1)) != CONST_INT)) { rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1); /* Be careful not to destroy OUTVAL. */ if (reg_overlap_mentioned_p (base_plus, outval)) { /* Updating base_plus might destroy outval, see if we can swap the scratch and base_plus. */ if (!reg_overlap_mentioned_p (scratch, outval)) { rtx tmp = scratch; scratch = base_plus; base_plus = tmp; } else { rtx scratch_hi = gen_rtx_REG (HImode, REGNO (operands[2])); /* Be conservative and copy OUTVAL into the scratch now, this should only be necessary if outval is a subreg of something larger than a word. */ /* XXX Might this clobber base? I can't see how it can, since scratch is known to overlap with OUTVAL, and must be wider than a word. */ emit_insn (gen_movhi (scratch_hi, outval)); outval = scratch_hi; } } emit_set_insn (base_plus, base); base = base_plus; } else if (GET_CODE (base) == PLUS) { /* The addend must be CONST_INT, or we would have dealt with it above. */ HOST_WIDE_INT hi, lo; offset += INTVAL (XEXP (base, 1)); base = XEXP (base, 0); /* Rework the address into a legal sequence of insns. */ /* Valid range for lo is -4095 -> 4095 */ lo = (offset >= 0 ? (offset & 0xfff) : -((-offset) & 0xfff)); /* Corner case, if lo is the max offset then we would be out of range once we have added the additional 1 below, so bump the msb into the pre-loading insn(s). */ if (lo == 4095) lo &= 0x7ff; hi = ((((offset - lo) & (HOST_WIDE_INT) 0xffffffff) ^ (HOST_WIDE_INT) 0x80000000) - (HOST_WIDE_INT) 0x80000000); gcc_assert (hi + lo == offset); if (hi != 0) { rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1); /* Be careful not to destroy OUTVAL. */ if (reg_overlap_mentioned_p (base_plus, outval)) { /* Updating base_plus might destroy outval, see if we can swap the scratch and base_plus. */ if (!reg_overlap_mentioned_p (scratch, outval)) { rtx tmp = scratch; scratch = base_plus; base_plus = tmp; } else { rtx scratch_hi = gen_rtx_REG (HImode, REGNO (operands[2])); /* Be conservative and copy outval into scratch now, this should only be necessary if outval is a subreg of something larger than a word. */ /* XXX Might this clobber base? I can't see how it can, since scratch is known to overlap with outval. */ emit_insn (gen_movhi (scratch_hi, outval)); outval = scratch_hi; } } /* Get the base address; addsi3 knows how to handle constants that require more than one insn. */ emit_insn (gen_addsi3 (base_plus, base, GEN_INT (hi))); base = base_plus; offset = lo; } } if (BYTES_BIG_ENDIAN) { emit_insn (gen_movqi (gen_rtx_MEM (QImode, plus_constant (base, offset + 1)), gen_lowpart (QImode, outval))); emit_insn (gen_lshrsi3 (scratch, gen_rtx_SUBREG (SImode, outval, 0), GEN_INT (8))); emit_insn (gen_movqi (gen_rtx_MEM (QImode, plus_constant (base, offset)), gen_lowpart (QImode, scratch))); } else { emit_insn (gen_movqi (gen_rtx_MEM (QImode, plus_constant (base, offset)), gen_lowpart (QImode, outval))); emit_insn (gen_lshrsi3 (scratch, gen_rtx_SUBREG (SImode, outval, 0), GEN_INT (8))); emit_insn (gen_movqi (gen_rtx_MEM (QImode, plus_constant (base, offset + 1)), gen_lowpart (QImode, scratch))); } } /* Return true if a type must be passed in memory. For AAPCS, small aggregates (padded to the size of a word) should be passed in a register. */ static bool arm_must_pass_in_stack (enum machine_mode mode, tree type) { if (TARGET_AAPCS_BASED) return must_pass_in_stack_var_size (mode, type); else return must_pass_in_stack_var_size_or_pad (mode, type); } /* For use by FUNCTION_ARG_PADDING (MODE, TYPE). Return true if an argument passed on the stack should be padded upwards, i.e. if the least-significant byte has useful data. For legacy APCS ABIs we use the default. For AAPCS based ABIs small aggregate types are placed in the lowest memory address. */ bool arm_pad_arg_upward (enum machine_mode mode, tree type) { if (!TARGET_AAPCS_BASED) return DEFAULT_FUNCTION_ARG_PADDING(mode, type) == upward; if (type && BYTES_BIG_ENDIAN && INTEGRAL_TYPE_P (type)) return false; return true; } /* Similarly, for use by BLOCK_REG_PADDING (MODE, TYPE, FIRST). For non-AAPCS, return !BYTES_BIG_ENDIAN if the least significant byte of the register has useful data, and return the opposite if the most significant byte does. For AAPCS, small aggregates and small complex types are always padded upwards. */ bool arm_pad_reg_upward (enum machine_mode mode ATTRIBUTE_UNUSED, tree type, int first ATTRIBUTE_UNUSED) { if (TARGET_AAPCS_BASED && BYTES_BIG_ENDIAN && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE) && int_size_in_bytes (type) <= 4) return true; /* Otherwise, use default padding. */ return !BYTES_BIG_ENDIAN; } /* Print a symbolic form of X to the debug file, F. */ static void arm_print_value (FILE *f, rtx x) { switch (GET_CODE (x)) { case CONST_INT: fprintf (f, HOST_WIDE_INT_PRINT_HEX, INTVAL (x)); return; case CONST_DOUBLE: fprintf (f, "<0x%lx,0x%lx>", (long)XWINT (x, 2), (long)XWINT (x, 3)); return; case CONST_VECTOR: { int i; fprintf (f, "<"); for (i = 0; i < CONST_VECTOR_NUNITS (x); i++) { fprintf (f, HOST_WIDE_INT_PRINT_HEX, INTVAL (CONST_VECTOR_ELT (x, i))); if (i < (CONST_VECTOR_NUNITS (x) - 1)) fputc (',', f); } fprintf (f, ">"); } return; case CONST_STRING: fprintf (f, "\"%s\"", XSTR (x, 0)); return; case SYMBOL_REF: fprintf (f, "`%s'", XSTR (x, 0)); return; case LABEL_REF: fprintf (f, "L%d", INSN_UID (XEXP (x, 0))); return; case CONST: arm_print_value (f, XEXP (x, 0)); return; case PLUS: arm_print_value (f, XEXP (x, 0)); fprintf (f, "+"); arm_print_value (f, XEXP (x, 1)); return; case PC: fprintf (f, "pc"); return; default: fprintf (f, "????"); return; } } /* Routines for manipulation of the constant pool. */ /* Arm instructions cannot load a large constant directly into a register; they have to come from a pc relative load. The constant must therefore be placed in the addressable range of the pc relative load. Depending on the precise pc relative load instruction the range is somewhere between 256 bytes and 4k. This means that we often have to dump a constant inside a function, and generate code to branch around it. It is important to minimize this, since the branches will slow things down and make the code larger. Normally we can hide the table after an existing unconditional branch so that there is no interruption of the flow, but in the worst case the code looks like this: ldr rn, L1 ... b L2 align L1: .long value L2: ... ldr rn, L3 ... b L4 align L3: .long value L4: ... We fix this by performing a scan after scheduling, which notices which instructions need to have their operands fetched from the constant table and builds the table. The algorithm starts by building a table of all the constants that need fixing up and all the natural barriers in the function (places where a constant table can be dropped without breaking the flow). For each fixup we note how far the pc-relative replacement will be able to reach and the offset of the instruction into the function. Having built the table we then group the fixes together to form tables that are as large as possible (subject to addressing constraints) and emit each table of constants after the last barrier that is within range of all the instructions in the group. If a group does not contain a barrier, then we forcibly create one by inserting a jump instruction into the flow. Once the table has been inserted, the insns are then modified to reference the relevant entry in the pool. Possible enhancements to the algorithm (not implemented) are: 1) For some processors and object formats, there may be benefit in aligning the pools to the start of cache lines; this alignment would need to be taken into account when calculating addressability of a pool. */ /* These typedefs are located at the start of this file, so that they can be used in the prototypes there. This comment is to remind readers of that fact so that the following structures can be understood more easily. typedef struct minipool_node Mnode; typedef struct minipool_fixup Mfix; */ struct minipool_node { /* Doubly linked chain of entries. */ Mnode * next; Mnode * prev; /* The maximum offset into the code that this entry can be placed. While pushing fixes for forward references, all entries are sorted in order of increasing max_address. */ HOST_WIDE_INT max_address; /* Similarly for an entry inserted for a backwards ref. */ HOST_WIDE_INT min_address; /* The number of fixes referencing this entry. This can become zero if we "unpush" an entry. In this case we ignore the entry when we come to emit the code. */ int refcount; /* The offset from the start of the minipool. */ HOST_WIDE_INT offset; /* The value in table. */ rtx value; /* The mode of value. */ enum machine_mode mode; /* The size of the value. With iWMMXt enabled sizes > 4 also imply an alignment of 8-bytes. */ int fix_size; }; struct minipool_fixup { Mfix * next; rtx insn; HOST_WIDE_INT address; rtx * loc; enum machine_mode mode; int fix_size; rtx value; Mnode * minipool; HOST_WIDE_INT forwards; HOST_WIDE_INT backwards; }; /* Fixes less than a word need padding out to a word boundary. */ #define MINIPOOL_FIX_SIZE(mode) \ (GET_MODE_SIZE ((mode)) >= 4 ? GET_MODE_SIZE ((mode)) : 4) static Mnode * minipool_vector_head; static Mnode * minipool_vector_tail; static rtx minipool_vector_label; static int minipool_pad; /* The linked list of all minipool fixes required for this function. */ Mfix * minipool_fix_head; Mfix * minipool_fix_tail; /* The fix entry for the current minipool, once it has been placed. */ Mfix * minipool_barrier; /* Determines if INSN is the start of a jump table. Returns the end of the TABLE or NULL_RTX. */ static rtx is_jump_table (rtx insn) { rtx table; if (GET_CODE (insn) == JUMP_INSN && JUMP_LABEL (insn) != NULL && ((table = next_real_insn (JUMP_LABEL (insn))) == next_real_insn (insn)) && table != NULL && GET_CODE (table) == JUMP_INSN && (GET_CODE (PATTERN (table)) == ADDR_VEC || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC)) return table; return NULL_RTX; } #ifndef JUMP_TABLES_IN_TEXT_SECTION #define JUMP_TABLES_IN_TEXT_SECTION 0 #endif static HOST_WIDE_INT get_jump_table_size (rtx insn) { /* ADDR_VECs only take room if read-only data does into the text section. */ if (JUMP_TABLES_IN_TEXT_SECTION || readonly_data_section == text_section) { rtx body = PATTERN (insn); int elt = GET_CODE (body) == ADDR_DIFF_VEC ? 1 : 0; return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, elt); } return 0; } /* Move a minipool fix MP from its current location to before MAX_MP. If MAX_MP is NULL, then MP doesn't need moving, but the addressing constraints may need updating. */ static Mnode * move_minipool_fix_forward_ref (Mnode *mp, Mnode *max_mp, HOST_WIDE_INT max_address) { /* The code below assumes these are different. */ gcc_assert (mp != max_mp); if (max_mp == NULL) { if (max_address < mp->max_address) mp->max_address = max_address; } else { if (max_address > max_mp->max_address - mp->fix_size) mp->max_address = max_mp->max_address - mp->fix_size; else mp->max_address = max_address; /* Unlink MP from its current position. Since max_mp is non-null, mp->prev must be non-null. */ mp->prev->next = mp->next; if (mp->next != NULL) mp->next->prev = mp->prev; else minipool_vector_tail = mp->prev; /* Re-insert it before MAX_MP. */ mp->next = max_mp; mp->prev = max_mp->prev; max_mp->prev = mp; if (mp->prev != NULL) mp->prev->next = mp; else minipool_vector_head = mp; } /* Save the new entry. */ max_mp = mp; /* Scan over the preceding entries and adjust their addresses as required. */ while (mp->prev != NULL && mp->prev->max_address > mp->max_address - mp->prev->fix_size) { mp->prev->max_address = mp->max_address - mp->prev->fix_size; mp = mp->prev; } return max_mp; } /* Add a constant to the minipool for a forward reference. Returns the node added or NULL if the constant will not fit in this pool. */ static Mnode * add_minipool_forward_ref (Mfix *fix) { /* If set, max_mp is the first pool_entry that has a lower constraint than the one we are trying to add. */ Mnode * max_mp = NULL; HOST_WIDE_INT max_address = fix->address + fix->forwards - minipool_pad; Mnode * mp; /* If the minipool starts before the end of FIX->INSN then this FIX can not be placed into the current pool. Furthermore, adding the new constant pool entry may cause the pool to start FIX_SIZE bytes earlier. */ if (minipool_vector_head && (fix->address + get_attr_length (fix->insn) >= minipool_vector_head->max_address - fix->fix_size)) return NULL; /* Scan the pool to see if a constant with the same value has already been added. While we are doing this, also note the location where we must insert the constant if it doesn't already exist. */ for (mp = minipool_vector_head; mp != NULL; mp = mp->next) { if (GET_CODE (fix->value) == GET_CODE (mp->value) && fix->mode == mp->mode && (GET_CODE (fix->value) != CODE_LABEL || (CODE_LABEL_NUMBER (fix->value) == CODE_LABEL_NUMBER (mp->value))) && rtx_equal_p (fix->value, mp->value)) { /* More than one fix references this entry. */ mp->refcount++; return move_minipool_fix_forward_ref (mp, max_mp, max_address); } /* Note the insertion point if necessary. */ if (max_mp == NULL && mp->max_address > max_address) max_mp = mp; /* If we are inserting an 8-bytes aligned quantity and we have not already found an insertion point, then make sure that all such 8-byte aligned quantities are placed at the start of the pool. */ if (ARM_DOUBLEWORD_ALIGN && max_mp == NULL && fix->fix_size == 8 && mp->fix_size != 8) { max_mp = mp; max_address = mp->max_address; } } /* The value is not currently in the minipool, so we need to create a new entry for it. If MAX_MP is NULL, the entry will be put on the end of the list since the placement is less constrained than any existing entry. Otherwise, we insert the new fix before MAX_MP and, if necessary, adjust the constraints on the other entries. */ mp = XNEW (Mnode); mp->fix_size = fix->fix_size; mp->mode = fix->mode; mp->value = fix->value; mp->refcount = 1; /* Not yet required for a backwards ref. */ mp->min_address = -65536; if (max_mp == NULL) { mp->max_address = max_address; mp->next = NULL; mp->prev = minipool_vector_tail; if (mp->prev == NULL) { minipool_vector_head = mp; minipool_vector_label = gen_label_rtx (); } else mp->prev->next = mp; minipool_vector_tail = mp; } else { if (max_address > max_mp->max_address - mp->fix_size) mp->max_address = max_mp->max_address - mp->fix_size; else mp->max_address = max_address; mp->next = max_mp; mp->prev = max_mp->prev; max_mp->prev = mp; if (mp->prev != NULL) mp->prev->next = mp; else minipool_vector_head = mp; } /* Save the new entry. */ max_mp = mp; /* Scan over the preceding entries and adjust their addresses as required. */ while (mp->prev != NULL && mp->prev->max_address > mp->max_address - mp->prev->fix_size) { mp->prev->max_address = mp->max_address - mp->prev->fix_size; mp = mp->prev; } return max_mp; } static Mnode * move_minipool_fix_backward_ref (Mnode *mp, Mnode *min_mp, HOST_WIDE_INT min_address) { HOST_WIDE_INT offset; /* The code below assumes these are different. */ gcc_assert (mp != min_mp); if (min_mp == NULL) { if (min_address > mp->min_address) mp->min_address = min_address; } else { /* We will adjust this below if it is too loose. */ mp->min_address = min_address; /* Unlink MP from its current position. Since min_mp is non-null, mp->next must be non-null. */ mp->next->prev = mp->prev; if (mp->prev != NULL) mp->prev->next = mp->next; else minipool_vector_head = mp->next; /* Reinsert it after MIN_MP. */ mp->prev = min_mp; mp->next = min_mp->next; min_mp->next = mp; if (mp->next != NULL) mp->next->prev = mp; else minipool_vector_tail = mp; } min_mp = mp; offset = 0; for (mp = minipool_vector_head; mp != NULL; mp = mp->next) { mp->offset = offset; if (mp->refcount > 0) offset += mp->fix_size; if (mp->next && mp->next->min_address < mp->min_address + mp->fix_size) mp->next->min_address = mp->min_address + mp->fix_size; } return min_mp; } /* Add a constant to the minipool for a backward reference. Returns the node added or NULL if the constant will not fit in this pool. Note that the code for insertion for a backwards reference can be somewhat confusing because the calculated offsets for each fix do not take into account the size of the pool (which is still under construction. */ static Mnode * add_minipool_backward_ref (Mfix *fix) { /* If set, min_mp is the last pool_entry that has a lower constraint than the one we are trying to add. */ Mnode *min_mp = NULL; /* This can be negative, since it is only a constraint. */ HOST_WIDE_INT min_address = fix->address - fix->backwards; Mnode *mp; /* If we can't reach the current pool from this insn, or if we can't insert this entry at the end of the pool without pushing other fixes out of range, then we don't try. This ensures that we can't fail later on. */ if (min_address >= minipool_barrier->address || (minipool_vector_tail->min_address + fix->fix_size >= minipool_barrier->address)) return NULL; /* Scan the pool to see if a constant with the same value has already been added. While we are doing this, also note the location where we must insert the constant if it doesn't already exist. */ for (mp = minipool_vector_tail; mp != NULL; mp = mp->prev) { if (GET_CODE (fix->value) == GET_CODE (mp->value) && fix->mode == mp->mode && (GET_CODE (fix->value) != CODE_LABEL || (CODE_LABEL_NUMBER (fix->value) == CODE_LABEL_NUMBER (mp->value))) && rtx_equal_p (fix->value, mp->value) /* Check that there is enough slack to move this entry to the end of the table (this is conservative). */ && (mp->max_address > (minipool_barrier->address + minipool_vector_tail->offset + minipool_vector_tail->fix_size))) { mp->refcount++; return move_minipool_fix_backward_ref (mp, min_mp, min_address); } if (min_mp != NULL) mp->min_address += fix->fix_size; else { /* Note the insertion point if necessary. */ if (mp->min_address < min_address) { /* For now, we do not allow the insertion of 8-byte alignment requiring nodes anywhere but at the start of the pool. */ if (ARM_DOUBLEWORD_ALIGN && fix->fix_size == 8 && mp->fix_size != 8) return NULL; else min_mp = mp; } else if (mp->max_address < minipool_barrier->address + mp->offset + fix->fix_size) { /* Inserting before this entry would push the fix beyond its maximum address (which can happen if we have re-located a forwards fix); force the new fix to come after it. */ min_mp = mp; min_address = mp->min_address + fix->fix_size; } /* If we are inserting an 8-bytes aligned quantity and we have not already found an insertion point, then make sure that all such 8-byte aligned quantities are placed at the start of the pool. */ else if (ARM_DOUBLEWORD_ALIGN && min_mp == NULL && fix->fix_size == 8 && mp->fix_size < 8) { min_mp = mp; min_address = mp->min_address + fix->fix_size; } } } /* We need to create a new entry. */ mp = XNEW (Mnode); mp->fix_size = fix->fix_size; mp->mode = fix->mode; mp->value = fix->value; mp->refcount = 1; mp->max_address = minipool_barrier->address + 65536; mp->min_address = min_address; if (min_mp == NULL) { mp->prev = NULL; mp->next = minipool_vector_head; if (mp->next == NULL) { minipool_vector_tail = mp; minipool_vector_label = gen_label_rtx (); } else mp->next->prev = mp; minipool_vector_head = mp; } else { mp->next = min_mp->next; mp->prev = min_mp; min_mp->next = mp; if (mp->next != NULL) mp->next->prev = mp; else minipool_vector_tail = mp; } /* Save the new entry. */ min_mp = mp; if (mp->prev) mp = mp->prev; else mp->offset = 0; /* Scan over the following entries and adjust their offsets. */ while (mp->next != NULL) { if (mp->next->min_address < mp->min_address + mp->fix_size) mp->next->min_address = mp->min_address + mp->fix_size; if (mp->refcount) mp->next->offset = mp->offset + mp->fix_size; else mp->next->offset = mp->offset; mp = mp->next; } return min_mp; } static void assign_minipool_offsets (Mfix *barrier) { HOST_WIDE_INT offset = 0; Mnode *mp; minipool_barrier = barrier; for (mp = minipool_vector_head; mp != NULL; mp = mp->next) { mp->offset = offset; if (mp->refcount > 0) offset += mp->fix_size; } } /* Output the literal table */ static void dump_minipool (rtx scan) { Mnode * mp; Mnode * nmp; int align64 = 0; if (ARM_DOUBLEWORD_ALIGN) for (mp = minipool_vector_head; mp != NULL; mp = mp->next) if (mp->refcount > 0 && mp->fix_size == 8) { align64 = 1; break; } if (dump_file) fprintf (dump_file, ";; Emitting minipool after insn %u; address %ld; align %d (bytes)\n", INSN_UID (scan), (unsigned long) minipool_barrier->address, align64 ? 8 : 4); scan = emit_label_after (gen_label_rtx (), scan); scan = emit_insn_after (align64 ? gen_align_8 () : gen_align_4 (), scan); scan = emit_label_after (minipool_vector_label, scan); for (mp = minipool_vector_head; mp != NULL; mp = nmp) { if (mp->refcount > 0) { if (dump_file) { fprintf (dump_file, ";; Offset %u, min %ld, max %ld ", (unsigned) mp->offset, (unsigned long) mp->min_address, (unsigned long) mp->max_address); arm_print_value (dump_file, mp->value); fputc ('\n', dump_file); } switch (mp->fix_size) { #ifdef HAVE_consttable_1 case 1: scan = emit_insn_after (gen_consttable_1 (mp->value), scan); break; #endif #ifdef HAVE_consttable_2 case 2: scan = emit_insn_after (gen_consttable_2 (mp->value), scan); break; #endif #ifdef HAVE_consttable_4 case 4: scan = emit_insn_after (gen_consttable_4 (mp->value), scan); break; #endif #ifdef HAVE_consttable_8 case 8: scan = emit_insn_after (gen_consttable_8 (mp->value), scan); break; #endif default: gcc_unreachable (); } } nmp = mp->next; free (mp); } minipool_vector_head = minipool_vector_tail = NULL; scan = emit_insn_after (gen_consttable_end (), scan); scan = emit_barrier_after (scan); } /* Return the cost of forcibly inserting a barrier after INSN. */ static int arm_barrier_cost (rtx insn) { /* Basing the location of the pool on the loop depth is preferable, but at the moment, the basic block information seems to be corrupt by this stage of the compilation. */ int base_cost = 50; rtx next = next_nonnote_insn (insn); if (next != NULL && GET_CODE (next) == CODE_LABEL) base_cost -= 20; switch (GET_CODE (insn)) { case CODE_LABEL: /* It will always be better to place the table before the label, rather than after it. */ return 50; case INSN: case CALL_INSN: return base_cost; case JUMP_INSN: return base_cost - 10; default: return base_cost + 10; } } /* Find the best place in the insn stream in the range (FIX->address,MAX_ADDRESS) to forcibly insert a minipool barrier. Create the barrier by inserting a jump and add a new fix entry for it. */ static Mfix * create_fix_barrier (Mfix *fix, HOST_WIDE_INT max_address) { HOST_WIDE_INT count = 0; rtx barrier; rtx from = fix->insn; /* The instruction after which we will insert the jump. */ rtx selected = NULL; int selected_cost; /* The address at which the jump instruction will be placed. */ HOST_WIDE_INT selected_address; Mfix * new_fix; HOST_WIDE_INT max_count = max_address - fix->address; rtx label = gen_label_rtx (); selected_cost = arm_barrier_cost (from); selected_address = fix->address; while (from && count < max_count) { rtx tmp; int new_cost; /* This code shouldn't have been called if there was a natural barrier within range. */ gcc_assert (GET_CODE (from) != BARRIER); /* Count the length of this insn. */ count += get_attr_length (from); /* If there is a jump table, add its length. */ tmp = is_jump_table (from); if (tmp != NULL) { count += get_jump_table_size (tmp); /* Jump tables aren't in a basic block, so base the cost on the dispatch insn. If we select this location, we will still put the pool after the table. */ new_cost = arm_barrier_cost (from); if (count < max_count && (!selected || new_cost <= selected_cost)) { selected = tmp; selected_cost = new_cost; selected_address = fix->address + count; } /* Continue after the dispatch table. */ from = NEXT_INSN (tmp); continue; } new_cost = arm_barrier_cost (from); if (count < max_count && (!selected || new_cost <= selected_cost)) { selected = from; selected_cost = new_cost; selected_address = fix->address + count; } from = NEXT_INSN (from); } /* Make sure that we found a place to insert the jump. */ gcc_assert (selected); /* Create a new JUMP_INSN that branches around a barrier. */ from = emit_jump_insn_after (gen_jump (label), selected); JUMP_LABEL (from) = label; barrier = emit_barrier_after (from); emit_label_after (label, barrier); /* Create a minipool barrier entry for the new barrier. */ new_fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (* new_fix)); new_fix->insn = barrier; new_fix->address = selected_address; new_fix->next = fix->next; fix->next = new_fix; return new_fix; } /* Record that there is a natural barrier in the insn stream at ADDRESS. */ static void push_minipool_barrier (rtx insn, HOST_WIDE_INT address) { Mfix * fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (* fix)); fix->insn = insn; fix->address = address; fix->next = NULL; if (minipool_fix_head != NULL) minipool_fix_tail->next = fix; else minipool_fix_head = fix; minipool_fix_tail = fix; } /* Record INSN, which will need fixing up to load a value from the minipool. ADDRESS is the offset of the insn since the start of the function; LOC is a pointer to the part of the insn which requires fixing; VALUE is the constant that must be loaded, which is of type MODE. */ static void push_minipool_fix (rtx insn, HOST_WIDE_INT address, rtx *loc, enum machine_mode mode, rtx value) { Mfix * fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (* fix)); #ifdef AOF_ASSEMBLER /* PIC symbol references need to be converted into offsets into the based area. */ /* XXX This shouldn't be done here. */ if (flag_pic && GET_CODE (value) == SYMBOL_REF) value = aof_pic_entry (value); #endif /* AOF_ASSEMBLER */ fix->insn = insn; fix->address = address; fix->loc = loc; fix->mode = mode; fix->fix_size = MINIPOOL_FIX_SIZE (mode); fix->value = value; fix->forwards = get_attr_pool_range (insn); fix->backwards = get_attr_neg_pool_range (insn); fix->minipool = NULL; /* If an insn doesn't have a range defined for it, then it isn't expecting to be reworked by this code. Better to stop now than to generate duff assembly code. */ gcc_assert (fix->forwards || fix->backwards); /* If an entry requires 8-byte alignment then assume all constant pools require 4 bytes of padding. Trying to do this later on a per-pool basis is awkward because existing pool entries have to be modified. */ if (ARM_DOUBLEWORD_ALIGN && fix->fix_size == 8) minipool_pad = 4; if (dump_file) { fprintf (dump_file, ";; %smode fixup for i%d; addr %lu, range (%ld,%ld): ", GET_MODE_NAME (mode), INSN_UID (insn), (unsigned long) address, -1 * (long)fix->backwards, (long)fix->forwards); arm_print_value (dump_file, fix->value); fprintf (dump_file, "\n"); } /* Add it to the chain of fixes. */ fix->next = NULL; if (minipool_fix_head != NULL) minipool_fix_tail->next = fix; else minipool_fix_head = fix; minipool_fix_tail = fix; } /* Return the cost of synthesizing a 64-bit constant VAL inline. Returns the number of insns needed, or 99 if we don't know how to do it. */ int arm_const_double_inline_cost (rtx val) { rtx lowpart, highpart; enum machine_mode mode; mode = GET_MODE (val); if (mode == VOIDmode) mode = DImode; gcc_assert (GET_MODE_SIZE (mode) == 8); lowpart = gen_lowpart (SImode, val); highpart = gen_highpart_mode (SImode, mode, val); gcc_assert (GET_CODE (lowpart) == CONST_INT); gcc_assert (GET_CODE (highpart) == CONST_INT); return (arm_gen_constant (SET, SImode, NULL_RTX, INTVAL (lowpart), NULL_RTX, NULL_RTX, 0, 0) + arm_gen_constant (SET, SImode, NULL_RTX, INTVAL (highpart), NULL_RTX, NULL_RTX, 0, 0)); } /* Return true if it is worthwhile to split a 64-bit constant into two 32-bit operations. This is the case if optimizing for size, or if we have load delay slots, or if one 32-bit part can be done with a single data operation. */ bool arm_const_double_by_parts (rtx val) { enum machine_mode mode = GET_MODE (val); rtx part; if (optimize_size || arm_ld_sched) return true; if (mode == VOIDmode) mode = DImode; part = gen_highpart_mode (SImode, mode, val); gcc_assert (GET_CODE (part) == CONST_INT); if (const_ok_for_arm (INTVAL (part)) || const_ok_for_arm (~INTVAL (part))) return true; part = gen_lowpart (SImode, val); gcc_assert (GET_CODE (part) == CONST_INT); if (const_ok_for_arm (INTVAL (part)) || const_ok_for_arm (~INTVAL (part))) return true; return false; } /* Scan INSN and note any of its operands that need fixing. If DO_PUSHES is false we do not actually push any of the fixups needed. The function returns TRUE if any fixups were needed/pushed. This is used by arm_memory_load_p() which needs to know about loads of constants that will be converted into minipool loads. */ static bool note_invalid_constants (rtx insn, HOST_WIDE_INT address, int do_pushes) { bool result = false; int opno; extract_insn (insn); if (!constrain_operands (1)) fatal_insn_not_found (insn); if (recog_data.n_alternatives == 0) return false; /* Fill in recog_op_alt with information about the constraints of this insn. */ preprocess_constraints (); for (opno = 0; opno < recog_data.n_operands; opno++) { /* Things we need to fix can only occur in inputs. */ if (recog_data.operand_type[opno] != OP_IN) continue; /* If this alternative is a memory reference, then any mention of constants in this alternative is really to fool reload into allowing us to accept one there. We need to fix them up now so that we output the right code. */ if (recog_op_alt[opno][which_alternative].memory_ok) { rtx op = recog_data.operand[opno]; if (CONSTANT_P (op)) { if (do_pushes) push_minipool_fix (insn, address, recog_data.operand_loc[opno], recog_data.operand_mode[opno], op); result = true; } else if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (XEXP (op, 0))) { if (do_pushes) { rtx cop = avoid_constant_pool_reference (op); /* Casting the address of something to a mode narrower than a word can cause avoid_constant_pool_reference() to return the pool reference itself. That's no good to us here. Lets just hope that we can use the constant pool value directly. */ if (op == cop) cop = get_pool_constant (XEXP (op, 0)); push_minipool_fix (insn, address, recog_data.operand_loc[opno], recog_data.operand_mode[opno], cop); } result = true; } } } return result; } /* Gcc puts the pool in the wrong place for ARM, since we can only load addresses a limited distance around the pc. We do some special munging to move the constant pool values to the correct point in the code. */ static void arm_reorg (void) { rtx insn; HOST_WIDE_INT address = 0; Mfix * fix; minipool_fix_head = minipool_fix_tail = NULL; /* The first insn must always be a note, or the code below won't scan it properly. */ insn = get_insns (); gcc_assert (GET_CODE (insn) == NOTE); minipool_pad = 0; /* Scan all the insns and record the operands that will need fixing. */ for (insn = next_nonnote_insn (insn); insn; insn = next_nonnote_insn (insn)) { if (TARGET_CIRRUS_FIX_INVALID_INSNS && (arm_cirrus_insn_p (insn) || GET_CODE (insn) == JUMP_INSN || arm_memory_load_p (insn))) cirrus_reorg (insn); if (GET_CODE (insn) == BARRIER) push_minipool_barrier (insn, address); else if (INSN_P (insn)) { rtx table; note_invalid_constants (insn, address, true); address += get_attr_length (insn); /* If the insn is a vector jump, add the size of the table and skip the table. */ if ((table = is_jump_table (insn)) != NULL) { address += get_jump_table_size (table); insn = table; } } } fix = minipool_fix_head; /* Now scan the fixups and perform the required changes. */ while (fix) { Mfix * ftmp; Mfix * fdel; Mfix * last_added_fix; Mfix * last_barrier = NULL; Mfix * this_fix; /* Skip any further barriers before the next fix. */ while (fix && GET_CODE (fix->insn) == BARRIER) fix = fix->next; /* No more fixes. */ if (fix == NULL) break; last_added_fix = NULL; for (ftmp = fix; ftmp; ftmp = ftmp->next) { if (GET_CODE (ftmp->insn) == BARRIER) { if (ftmp->address >= minipool_vector_head->max_address) break; last_barrier = ftmp; } else if ((ftmp->minipool = add_minipool_forward_ref (ftmp)) == NULL) break; last_added_fix = ftmp; /* Keep track of the last fix added. */ } /* If we found a barrier, drop back to that; any fixes that we could have reached but come after the barrier will now go in the next mini-pool. */ if (last_barrier != NULL) { /* Reduce the refcount for those fixes that won't go into this pool after all. */ for (fdel = last_barrier->next; fdel && fdel != ftmp; fdel = fdel->next) { fdel->minipool->refcount--; fdel->minipool = NULL; } ftmp = last_barrier; } else { /* ftmp is first fix that we can't fit into this pool and there no natural barriers that we could use. Insert a new barrier in the code somewhere between the previous fix and this one, and arrange to jump around it. */ HOST_WIDE_INT max_address; /* The last item on the list of fixes must be a barrier, so we can never run off the end of the list of fixes without last_barrier being set. */ gcc_assert (ftmp); max_address = minipool_vector_head->max_address; /* Check that there isn't another fix that is in range that we couldn't fit into this pool because the pool was already too large: we need to put the pool before such an instruction. The pool itself may come just after the fix because create_fix_barrier also allows space for a jump instruction. */ if (ftmp->address < max_address) max_address = ftmp->address + 1; last_barrier = create_fix_barrier (last_added_fix, max_address); } assign_minipool_offsets (last_barrier); while (ftmp) { if (GET_CODE (ftmp->insn) != BARRIER && ((ftmp->minipool = add_minipool_backward_ref (ftmp)) == NULL)) break; ftmp = ftmp->next; } /* Scan over the fixes we have identified for this pool, fixing them up and adding the constants to the pool itself. */ for (this_fix = fix; this_fix && ftmp != this_fix; this_fix = this_fix->next) if (GET_CODE (this_fix->insn) != BARRIER) { rtx addr = plus_constant (gen_rtx_LABEL_REF (VOIDmode, minipool_vector_label), this_fix->minipool->offset); *this_fix->loc = gen_rtx_MEM (this_fix->mode, addr); } dump_minipool (last_barrier->insn); fix = ftmp; } /* From now on we must synthesize any constants that we can't handle directly. This can happen if the RTL gets split during final instruction generation. */ after_arm_reorg = 1; /* Free the minipool memory. */ obstack_free (&minipool_obstack, minipool_startobj); } /* Routines to output assembly language. */ /* If the rtx is the correct value then return the string of the number. In this way we can ensure that valid double constants are generated even when cross compiling. */ const char * fp_immediate_constant (rtx x) { REAL_VALUE_TYPE r; int i; if (!fp_consts_inited) init_fp_table (); REAL_VALUE_FROM_CONST_DOUBLE (r, x); for (i = 0; i < 8; i++) if (REAL_VALUES_EQUAL (r, values_fp[i])) return strings_fp[i]; gcc_unreachable (); } /* As for fp_immediate_constant, but value is passed directly, not in rtx. */ static const char * fp_const_from_val (REAL_VALUE_TYPE *r) { int i; if (!fp_consts_inited) init_fp_table (); for (i = 0; i < 8; i++) if (REAL_VALUES_EQUAL (*r, values_fp[i])) return strings_fp[i]; gcc_unreachable (); } /* Output the operands of a LDM/STM instruction to STREAM. MASK is the ARM register set mask of which only bits 0-15 are important. REG is the base register, either the frame pointer or the stack pointer, INSTR is the possibly suffixed load or store instruction. */ static void print_multi_reg (FILE *stream, const char *instr, unsigned reg, unsigned long mask) { unsigned i; bool not_first = FALSE; fputc ('\t', stream); asm_fprintf (stream, instr, reg); fputs (", {", stream); for (i = 0; i <= LAST_ARM_REGNUM; i++) if (mask & (1 << i)) { if (not_first) fprintf (stream, ", "); asm_fprintf (stream, "%r", i); not_first = TRUE; } fprintf (stream, "}\n"); } /* Output a FLDMX instruction to STREAM. BASE if the register containing the address. REG and COUNT specify the register range. Extra registers may be added to avoid hardware bugs. */ static void arm_output_fldmx (FILE * stream, unsigned int base, int reg, int count) { int i; /* Workaround ARM10 VFPr1 bug. */ if (count == 2 && !arm_arch6) { if (reg == 15) reg--; count++; } fputc ('\t', stream); asm_fprintf (stream, "fldmfdx\t%r!, {", base); for (i = reg; i < reg + count; i++) { if (i > reg) fputs (", ", stream); asm_fprintf (stream, "d%d", i); } fputs ("}\n", stream); } /* Output the assembly for a store multiple. */ const char * vfp_output_fstmx (rtx * operands) { char pattern[100]; int p; int base; int i; strcpy (pattern, "fstmfdx\t%m0!, {%P1"); p = strlen (pattern); gcc_assert (GET_CODE (operands[1]) == REG); base = (REGNO (operands[1]) - FIRST_VFP_REGNUM) / 2; for (i = 1; i < XVECLEN (operands[2], 0); i++) { p += sprintf (&pattern[p], ", d%d", base + i); } strcpy (&pattern[p], "}"); output_asm_insn (pattern, operands); return ""; } /* Emit RTL to save block of VFP register pairs to the stack. Returns the number of bytes pushed. */ static int vfp_emit_fstmx (int base_reg, int count) { rtx par; rtx dwarf; rtx tmp, reg; int i; /* Workaround ARM10 VFPr1 bug. Data corruption can occur when exactly two register pairs are stored by a store multiple insn. We avoid this by pushing an extra pair. */ if (count == 2 && !arm_arch6) { if (base_reg == LAST_VFP_REGNUM - 3) base_reg -= 2; count++; } /* ??? The frame layout is implementation defined. We describe standard format 1 (equivalent to a FSTMD insn and unused pad word). We really need some way of representing the whole block so that the unwinder can figure it out at runtime. */ par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1)); reg = gen_rtx_REG (DFmode, base_reg); base_reg += 2; XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, gen_frame_mem (BLKmode, gen_rtx_PRE_DEC (BLKmode, stack_pointer_rtx)), gen_rtx_UNSPEC (BLKmode, gen_rtvec (1, reg), UNSPEC_PUSH_MULT)); tmp = gen_rtx_SET (VOIDmode, stack_pointer_rtx, plus_constant (stack_pointer_rtx, -(count * 8 + 4))); RTX_FRAME_RELATED_P (tmp) = 1; XVECEXP (dwarf, 0, 0) = tmp; tmp = gen_rtx_SET (VOIDmode, gen_frame_mem (DFmode, stack_pointer_rtx), reg); RTX_FRAME_RELATED_P (tmp) = 1; XVECEXP (dwarf, 0, 1) = tmp; for (i = 1; i < count; i++) { reg = gen_rtx_REG (DFmode, base_reg); base_reg += 2; XVECEXP (par, 0, i) = gen_rtx_USE (VOIDmode, reg); tmp = gen_rtx_SET (VOIDmode, gen_frame_mem (DFmode, plus_constant (stack_pointer_rtx, i * 8)), reg); RTX_FRAME_RELATED_P (tmp) = 1; XVECEXP (dwarf, 0, i + 1) = tmp; } par = emit_insn (par); REG_NOTES (par) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf, REG_NOTES (par)); RTX_FRAME_RELATED_P (par) = 1; return count * 8 + 4; } /* Output a 'call' insn. */ const char * output_call (rtx *operands) { gcc_assert (!arm_arch5); /* Patterns should call blx directly. */ /* Handle calls to lr using ip (which may be clobbered in subr anyway). */ if (REGNO (operands[0]) == LR_REGNUM) { operands[0] = gen_rtx_REG (SImode, IP_REGNUM); output_asm_insn ("mov%?\t%0, %|lr", operands); } output_asm_insn ("mov%?\t%|lr, %|pc", operands); if (TARGET_INTERWORK || arm_arch4t) output_asm_insn ("bx%?\t%0", operands); else output_asm_insn ("mov%?\t%|pc, %0", operands); return ""; } /* Output a 'call' insn that is a reference in memory. */ const char * output_call_mem (rtx *operands) { if (TARGET_INTERWORK && !arm_arch5) { output_asm_insn ("ldr%?\t%|ip, %0", operands); output_asm_insn ("mov%?\t%|lr, %|pc", operands); output_asm_insn ("bx%?\t%|ip", operands); } else if (regno_use_in (LR_REGNUM, operands[0])) { /* LR is used in the memory address. We load the address in the first instruction. It's safe to use IP as the target of the load since the call will kill it anyway. */ output_asm_insn ("ldr%?\t%|ip, %0", operands); if (arm_arch5) output_asm_insn ("blx%?\t%|ip", operands); else { output_asm_insn ("mov%?\t%|lr, %|pc", operands); if (arm_arch4t) output_asm_insn ("bx%?\t%|ip", operands); else output_asm_insn ("mov%?\t%|pc, %|ip", operands); } } else { output_asm_insn ("mov%?\t%|lr, %|pc", operands); output_asm_insn ("ldr%?\t%|pc, %0", operands); } return ""; } /* Output a move from arm registers to an fpa registers. OPERANDS[0] is an fpa register. OPERANDS[1] is the first registers of an arm register pair. */ const char * output_mov_long_double_fpa_from_arm (rtx *operands) { int arm_reg0 = REGNO (operands[1]); rtx ops[3]; gcc_assert (arm_reg0 != IP_REGNUM); ops[0] = gen_rtx_REG (SImode, arm_reg0); ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0); ops[2] = gen_rtx_REG (SImode, 2 + arm_reg0); output_asm_insn ("stm%?fd\t%|sp!, {%0, %1, %2}", ops); output_asm_insn ("ldf%?e\t%0, [%|sp], #12", operands); return ""; } /* Output a move from an fpa register to arm registers. OPERANDS[0] is the first registers of an arm register pair. OPERANDS[1] is an fpa register. */ const char * output_mov_long_double_arm_from_fpa (rtx *operands) { int arm_reg0 = REGNO (operands[0]); rtx ops[3]; gcc_assert (arm_reg0 != IP_REGNUM); ops[0] = gen_rtx_REG (SImode, arm_reg0); ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0); ops[2] = gen_rtx_REG (SImode, 2 + arm_reg0); output_asm_insn ("stf%?e\t%1, [%|sp, #-12]!", operands); output_asm_insn ("ldm%?fd\t%|sp!, {%0, %1, %2}", ops); return ""; } /* Output a move from arm registers to arm registers of a long double OPERANDS[0] is the destination. OPERANDS[1] is the source. */ const char * output_mov_long_double_arm_from_arm (rtx *operands) { /* We have to be careful here because the two might overlap. */ int dest_start = REGNO (operands[0]); int src_start = REGNO (operands[1]); rtx ops[2]; int i; if (dest_start < src_start) { for (i = 0; i < 3; i++) { ops[0] = gen_rtx_REG (SImode, dest_start + i); ops[1] = gen_rtx_REG (SImode, src_start + i); output_asm_insn ("mov%?\t%0, %1", ops); } } else { for (i = 2; i >= 0; i--) { ops[0] = gen_rtx_REG (SImode, dest_start + i); ops[1] = gen_rtx_REG (SImode, src_start + i); output_asm_insn ("mov%?\t%0, %1", ops); } } return ""; } /* Output a move from arm registers to an fpa registers. OPERANDS[0] is an fpa register. OPERANDS[1] is the first registers of an arm register pair. */ const char * output_mov_double_fpa_from_arm (rtx *operands) { int arm_reg0 = REGNO (operands[1]); rtx ops[2]; gcc_assert (arm_reg0 != IP_REGNUM); ops[0] = gen_rtx_REG (SImode, arm_reg0); ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0); output_asm_insn ("stm%?fd\t%|sp!, {%0, %1}", ops); output_asm_insn ("ldf%?d\t%0, [%|sp], #8", operands); return ""; } /* Output a move from an fpa register to arm registers. OPERANDS[0] is the first registers of an arm register pair. OPERANDS[1] is an fpa register. */ const char * output_mov_double_arm_from_fpa (rtx *operands) { int arm_reg0 = REGNO (operands[0]); rtx ops[2]; gcc_assert (arm_reg0 != IP_REGNUM); ops[0] = gen_rtx_REG (SImode, arm_reg0); ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0); output_asm_insn ("stf%?d\t%1, [%|sp, #-8]!", operands); output_asm_insn ("ldm%?fd\t%|sp!, {%0, %1}", ops); return ""; } /* Output a move between double words. It must be REG<-REG, REG<-CONST_DOUBLE, REG<-CONST_INT, REG<-MEM or MEM<-REG and all MEMs must be offsettable addresses. */ const char * output_move_double (rtx *operands) { enum rtx_code code0 = GET_CODE (operands[0]); enum rtx_code code1 = GET_CODE (operands[1]); rtx otherops[3]; if (code0 == REG) { int reg0 = REGNO (operands[0]); otherops[0] = gen_rtx_REG (SImode, 1 + reg0); gcc_assert (code1 == MEM); /* Constraints should ensure this. */ switch (GET_CODE (XEXP (operands[1], 0))) { case REG: output_asm_insn ("ldm%?ia\t%m1, %M0", operands); break; case PRE_INC: gcc_assert (TARGET_LDRD); output_asm_insn ("ldr%?d\t%0, [%m1, #8]!", operands); break; case PRE_DEC: output_asm_insn ("ldm%?db\t%m1!, %M0", operands); break; case POST_INC: output_asm_insn ("ldm%?ia\t%m1!, %M0", operands); break; case POST_DEC: gcc_assert (TARGET_LDRD); output_asm_insn ("ldr%?d\t%0, [%m1], #-8", operands); break; case PRE_MODIFY: case POST_MODIFY: otherops[0] = operands[0]; otherops[1] = XEXP (XEXP (XEXP (operands[1], 0), 1), 0); otherops[2] = XEXP (XEXP (XEXP (operands[1], 0), 1), 1); if (GET_CODE (XEXP (operands[1], 0)) == PRE_MODIFY) { if (reg_overlap_mentioned_p (otherops[0], otherops[2])) { /* Registers overlap so split out the increment. */ output_asm_insn ("add%?\t%1, %1, %2", otherops); output_asm_insn ("ldr%?d\t%0, [%1] @split", otherops); } else { /* IWMMXT allows offsets larger than ldrd can handle, fix these up with a pair of ldr. */ if (GET_CODE (otherops[2]) == CONST_INT && (INTVAL(otherops[2]) <= -256 || INTVAL(otherops[2]) >= 256)) { output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops); otherops[0] = gen_rtx_REG (SImode, 1 + reg0); output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops); } else output_asm_insn ("ldr%?d\t%0, [%1, %2]!", otherops); } } else { /* IWMMXT allows offsets larger than ldrd can handle, fix these up with a pair of ldr. */ if (GET_CODE (otherops[2]) == CONST_INT && (INTVAL(otherops[2]) <= -256 || INTVAL(otherops[2]) >= 256)) { otherops[0] = gen_rtx_REG (SImode, 1 + reg0); output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops); otherops[0] = operands[0]; output_asm_insn ("ldr%?\t%0, [%1], %2", otherops); } else /* We only allow constant increments, so this is safe. */ output_asm_insn ("ldr%?d\t%0, [%1], %2", otherops); } break; case LABEL_REF: case CONST: output_asm_insn ("adr%?\t%0, %1", operands); output_asm_insn ("ldm%?ia\t%0, %M0", operands); break; default: if (arm_add_operand (XEXP (XEXP (operands[1], 0), 1), GET_MODE (XEXP (XEXP (operands[1], 0), 1)))) { otherops[0] = operands[0]; otherops[1] = XEXP (XEXP (operands[1], 0), 0); otherops[2] = XEXP (XEXP (operands[1], 0), 1); if (GET_CODE (XEXP (operands[1], 0)) == PLUS) { if (GET_CODE (otherops[2]) == CONST_INT) { switch ((int) INTVAL (otherops[2])) { case -8: output_asm_insn ("ldm%?db\t%1, %M0", otherops); return ""; case -4: output_asm_insn ("ldm%?da\t%1, %M0", otherops); return ""; case 4: output_asm_insn ("ldm%?ib\t%1, %M0", otherops); return ""; } } if (TARGET_LDRD && (GET_CODE (otherops[2]) == REG || (GET_CODE (otherops[2]) == CONST_INT && INTVAL (otherops[2]) > -256 && INTVAL (otherops[2]) < 256))) { if (reg_overlap_mentioned_p (otherops[0], otherops[2])) { /* Swap base and index registers over to avoid a conflict. */ otherops[1] = XEXP (XEXP (operands[1], 0), 1); otherops[2] = XEXP (XEXP (operands[1], 0), 0); } /* If both registers conflict, it will usually have been fixed by a splitter. */ if (reg_overlap_mentioned_p (otherops[0], otherops[2])) { output_asm_insn ("add%?\t%1, %1, %2", otherops); output_asm_insn ("ldr%?d\t%0, [%1]", otherops); } else output_asm_insn ("ldr%?d\t%0, [%1, %2]", otherops); return ""; } if (GET_CODE (otherops[2]) == CONST_INT) { if (!(const_ok_for_arm (INTVAL (otherops[2])))) output_asm_insn ("sub%?\t%0, %1, #%n2", otherops); else output_asm_insn ("add%?\t%0, %1, %2", otherops); } else output_asm_insn ("add%?\t%0, %1, %2", otherops); } else output_asm_insn ("sub%?\t%0, %1, %2", otherops); return "ldm%?ia\t%0, %M0"; } else { otherops[1] = adjust_address (operands[1], SImode, 4); /* Take care of overlapping base/data reg. */ if (reg_mentioned_p (operands[0], operands[1])) { output_asm_insn ("ldr%?\t%0, %1", otherops); output_asm_insn ("ldr%?\t%0, %1", operands); } else { output_asm_insn ("ldr%?\t%0, %1", operands); output_asm_insn ("ldr%?\t%0, %1", otherops); } } } } else { /* Constraints should ensure this. */ gcc_assert (code0 == MEM && code1 == REG); gcc_assert (REGNO (operands[1]) != IP_REGNUM); switch (GET_CODE (XEXP (operands[0], 0))) { case REG: output_asm_insn ("stm%?ia\t%m0, %M1", operands); break; case PRE_INC: gcc_assert (TARGET_LDRD); output_asm_insn ("str%?d\t%1, [%m0, #8]!", operands); break; case PRE_DEC: output_asm_insn ("stm%?db\t%m0!, %M1", operands); break; case POST_INC: output_asm_insn ("stm%?ia\t%m0!, %M1", operands); break; case POST_DEC: gcc_assert (TARGET_LDRD); output_asm_insn ("str%?d\t%1, [%m0], #-8", operands); break; case PRE_MODIFY: case POST_MODIFY: otherops[0] = operands[1]; otherops[1] = XEXP (XEXP (XEXP (operands[0], 0), 1), 0); otherops[2] = XEXP (XEXP (XEXP (operands[0], 0), 1), 1); /* IWMMXT allows offsets larger than ldrd can handle, fix these up with a pair of ldr. */ if (GET_CODE (otherops[2]) == CONST_INT && (INTVAL(otherops[2]) <= -256 || INTVAL(otherops[2]) >= 256)) { rtx reg1; reg1 = gen_rtx_REG (SImode, 1 + REGNO (operands[1])); if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY) { output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops); otherops[0] = reg1; output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops); } else { otherops[0] = reg1; output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops); otherops[0] = operands[1]; output_asm_insn ("ldr%?\t%0, [%1], %2", otherops); } } else if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY) output_asm_insn ("str%?d\t%0, [%1, %2]!", otherops); else output_asm_insn ("str%?d\t%0, [%1], %2", otherops); break; case PLUS: otherops[2] = XEXP (XEXP (operands[0], 0), 1); if (GET_CODE (otherops[2]) == CONST_INT) { switch ((int) INTVAL (XEXP (XEXP (operands[0], 0), 1))) { case -8: output_asm_insn ("stm%?db\t%m0, %M1", operands); return ""; case -4: output_asm_insn ("stm%?da\t%m0, %M1", operands); return ""; case 4: output_asm_insn ("stm%?ib\t%m0, %M1", operands); return ""; } } if (TARGET_LDRD && (GET_CODE (otherops[2]) == REG || (GET_CODE (otherops[2]) == CONST_INT && INTVAL (otherops[2]) > -256 && INTVAL (otherops[2]) < 256))) { otherops[0] = operands[1]; otherops[1] = XEXP (XEXP (operands[0], 0), 0); output_asm_insn ("str%?d\t%0, [%1, %2]", otherops); return ""; } /* Fall through */ default: otherops[0] = adjust_address (operands[0], SImode, 4); otherops[1] = gen_rtx_REG (SImode, 1 + REGNO (operands[1])); output_asm_insn ("str%?\t%1, %0", operands); output_asm_insn ("str%?\t%1, %0", otherops); } } return ""; } /* Output an ADD r, s, #n where n may be too big for one instruction. If adding zero to one register, output nothing. */ const char * output_add_immediate (rtx *operands) { HOST_WIDE_INT n = INTVAL (operands[2]); if (n != 0 || REGNO (operands[0]) != REGNO (operands[1])) { if (n < 0) output_multi_immediate (operands, "sub%?\t%0, %1, %2", "sub%?\t%0, %0, %2", 2, -n); else output_multi_immediate (operands, "add%?\t%0, %1, %2", "add%?\t%0, %0, %2", 2, n); } return ""; } /* Output a multiple immediate operation. OPERANDS is the vector of operands referred to in the output patterns. INSTR1 is the output pattern to use for the first constant. INSTR2 is the output pattern to use for subsequent constants. IMMED_OP is the index of the constant slot in OPERANDS. N is the constant value. */ static const char * output_multi_immediate (rtx *operands, const char *instr1, const char *instr2, int immed_op, HOST_WIDE_INT n) { #if HOST_BITS_PER_WIDE_INT > 32 n &= 0xffffffff; #endif if (n == 0) { /* Quick and easy output. */ operands[immed_op] = const0_rtx; output_asm_insn (instr1, operands); } else { int i; const char * instr = instr1; /* Note that n is never zero here (which would give no output). */ for (i = 0; i < 32; i += 2) { if (n & (3 << i)) { operands[immed_op] = GEN_INT (n & (255 << i)); output_asm_insn (instr, operands); instr = instr2; i += 6; } } } return ""; } /* Return the appropriate ARM instruction for the operation code. The returned result should not be overwritten. OP is the rtx of the operation. SHIFT_FIRST_ARG is TRUE if the first argument of the operator was shifted. */ const char * arithmetic_instr (rtx op, int shift_first_arg) { switch (GET_CODE (op)) { case PLUS: return "add"; case MINUS: return shift_first_arg ? "rsb" : "sub"; case IOR: return "orr"; case XOR: return "eor"; case AND: return "and"; default: gcc_unreachable (); } } /* Ensure valid constant shifts and return the appropriate shift mnemonic for the operation code. The returned result should not be overwritten. OP is the rtx code of the shift. On exit, *AMOUNTP will be -1 if the shift is by a register, or a constant shift. */ static const char * shift_op (rtx op, HOST_WIDE_INT *amountp) { const char * mnem; enum rtx_code code = GET_CODE (op); switch (GET_CODE (XEXP (op, 1))) { case REG: case SUBREG: *amountp = -1; break; case CONST_INT: *amountp = INTVAL (XEXP (op, 1)); break; default: gcc_unreachable (); } switch (code) { case ASHIFT: mnem = "asl"; break; case ASHIFTRT: mnem = "asr"; break; case LSHIFTRT: mnem = "lsr"; break; case ROTATE: gcc_assert (*amountp != -1); *amountp = 32 - *amountp; /* Fall through. */ case ROTATERT: mnem = "ror"; break; case MULT: /* We never have to worry about the amount being other than a power of 2, since this case can never be reloaded from a reg. */ gcc_assert (*amountp != -1); *amountp = int_log2 (*amountp); return "asl"; default: gcc_unreachable (); } if (*amountp != -1) { /* This is not 100% correct, but follows from the desire to merge multiplication by a power of 2 with the recognizer for a shift. >=32 is not a valid shift for "asl", so we must try and output a shift that produces the correct arithmetical result. Using lsr #32 is identical except for the fact that the carry bit is not set correctly if we set the flags; but we never use the carry bit from such an operation, so we can ignore that. */ if (code == ROTATERT) /* Rotate is just modulo 32. */ *amountp &= 31; else if (*amountp != (*amountp & 31)) { if (code == ASHIFT) mnem = "lsr"; *amountp = 32; } /* Shifts of 0 are no-ops. */ if (*amountp == 0) return NULL; } return mnem; } /* Obtain the shift from the POWER of two. */ static HOST_WIDE_INT int_log2 (HOST_WIDE_INT power) { HOST_WIDE_INT shift = 0; while ((((HOST_WIDE_INT) 1 << shift) & power) == 0) { gcc_assert (shift <= 31); shift++; } return shift; } /* Output a .ascii pseudo-op, keeping track of lengths. This is because /bin/as is horribly restrictive. The judgement about whether or not each character is 'printable' (and can be output as is) or not (and must be printed with an octal escape) must be made with reference to the *host* character set -- the situation is similar to that discussed in the comments above pp_c_char in c-pretty-print.c. */ #define MAX_ASCII_LEN 51 void output_ascii_pseudo_op (FILE *stream, const unsigned char *p, int len) { int i; int len_so_far = 0; fputs ("\t.ascii\t\"", stream); for (i = 0; i < len; i++) { int c = p[i]; if (len_so_far >= MAX_ASCII_LEN) { fputs ("\"\n\t.ascii\t\"", stream); len_so_far = 0; } if (ISPRINT (c)) { if (c == '\\' || c == '\"') { putc ('\\', stream); len_so_far++; } putc (c, stream); len_so_far++; } else { fprintf (stream, "\\%03o", c); len_so_far += 4; } } fputs ("\"\n", stream); } /* Compute the register save mask for registers 0 through 12 inclusive. This code is used by arm_compute_save_reg_mask. */ static unsigned long arm_compute_save_reg0_reg12_mask (void) { unsigned long func_type = arm_current_func_type (); unsigned long save_reg_mask = 0; unsigned int reg; if (IS_INTERRUPT (func_type)) { unsigned int max_reg; /* Interrupt functions must not corrupt any registers, even call clobbered ones. If this is a leaf function we can just examine the registers used by the RTL, but otherwise we have to assume that whatever function is called might clobber anything, and so we have to save all the call-clobbered registers as well. */ if (ARM_FUNC_TYPE (func_type) == ARM_FT_FIQ) /* FIQ handlers have registers r8 - r12 banked, so we only need to check r0 - r7, Normal ISRs only bank r14 and r15, so we must check up to r12. r13 is the stack pointer which is always preserved, so we do not need to consider it here. */ max_reg = 7; else max_reg = 12; for (reg = 0; reg <= max_reg; reg++) if (regs_ever_live[reg] || (! current_function_is_leaf && call_used_regs [reg])) save_reg_mask |= (1 << reg); /* Also save the pic base register if necessary. */ if (flag_pic && !TARGET_SINGLE_PIC_BASE && arm_pic_register != INVALID_REGNUM && current_function_uses_pic_offset_table) save_reg_mask |= 1 << PIC_OFFSET_TABLE_REGNUM; } else { /* In the normal case we only need to save those registers which are call saved and which are used by this function. */ for (reg = 0; reg <= 10; reg++) if (regs_ever_live[reg] && ! call_used_regs [reg]) save_reg_mask |= (1 << reg); /* Handle the frame pointer as a special case. */ if (! TARGET_APCS_FRAME && ! frame_pointer_needed && regs_ever_live[HARD_FRAME_POINTER_REGNUM] && ! call_used_regs[HARD_FRAME_POINTER_REGNUM]) save_reg_mask |= 1 << HARD_FRAME_POINTER_REGNUM; /* If we aren't loading the PIC register, don't stack it even though it may be live. */ if (flag_pic && !TARGET_SINGLE_PIC_BASE && arm_pic_register != INVALID_REGNUM && (regs_ever_live[PIC_OFFSET_TABLE_REGNUM] || current_function_uses_pic_offset_table)) save_reg_mask |= 1 << PIC_OFFSET_TABLE_REGNUM; } /* Save registers so the exception handler can modify them. */ if (current_function_calls_eh_return) { unsigned int i; for (i = 0; ; i++) { reg = EH_RETURN_DATA_REGNO (i); if (reg == INVALID_REGNUM) break; save_reg_mask |= 1 << reg; } } return save_reg_mask; } /* Compute a bit mask of which registers need to be saved on the stack for the current function. */ static unsigned long arm_compute_save_reg_mask (void) { unsigned int save_reg_mask = 0; unsigned long func_type = arm_current_func_type (); if (IS_NAKED (func_type)) /* This should never really happen. */ return 0; /* If we are creating a stack frame, then we must save the frame pointer, IP (which will hold the old stack pointer), LR and the PC. */ if (frame_pointer_needed) save_reg_mask |= (1 << ARM_HARD_FRAME_POINTER_REGNUM) | (1 << IP_REGNUM) | (1 << LR_REGNUM) | (1 << PC_REGNUM); /* Volatile functions do not return, so there is no need to save any other registers. */ if (IS_VOLATILE (func_type)) return save_reg_mask; save_reg_mask |= arm_compute_save_reg0_reg12_mask (); /* Decide if we need to save the link register. Interrupt routines have their own banked link register, so they never need to save it. Otherwise if we do not use the link register we do not need to save it. If we are pushing other registers onto the stack however, we can save an instruction in the epilogue by pushing the link register now and then popping it back into the PC. This incurs extra memory accesses though, so we only do it when optimizing for size, and only if we know that we will not need a fancy return sequence. */ if (regs_ever_live [LR_REGNUM] || (save_reg_mask && optimize_size && ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL && !current_function_calls_eh_return)) save_reg_mask |= 1 << LR_REGNUM; if (cfun->machine->lr_save_eliminated) save_reg_mask &= ~ (1 << LR_REGNUM); if (TARGET_REALLY_IWMMXT && ((bit_count (save_reg_mask) + ARM_NUM_INTS (current_function_pretend_args_size)) % 2) != 0) { unsigned int reg; /* The total number of registers that are going to be pushed onto the stack is odd. We need to ensure that the stack is 64-bit aligned before we start to save iWMMXt registers, and also before we start to create locals. (A local variable might be a double or long long which we will load/store using an iWMMXt instruction). Therefore we need to push another ARM register, so that the stack will be 64-bit aligned. We try to avoid using the arg registers (r0 -r3) as they might be used to pass values in a tail call. */ for (reg = 4; reg <= 12; reg++) if ((save_reg_mask & (1 << reg)) == 0) break; if (reg <= 12) save_reg_mask |= (1 << reg); else { cfun->machine->sibcall_blocked = 1; save_reg_mask |= (1 << 3); } } return save_reg_mask; } /* Compute a bit mask of which registers need to be saved on the stack for the current function. */ static unsigned long thumb_compute_save_reg_mask (void) { unsigned long mask; unsigned reg; mask = 0; for (reg = 0; reg < 12; reg ++) if (regs_ever_live[reg] && !call_used_regs[reg]) mask |= 1 << reg; if (flag_pic && !TARGET_SINGLE_PIC_BASE && arm_pic_register != INVALID_REGNUM && current_function_uses_pic_offset_table) mask |= 1 << PIC_OFFSET_TABLE_REGNUM; /* See if we might need r11 for calls to _interwork_r11_call_via_rN(). */ if (!frame_pointer_needed && CALLER_INTERWORKING_SLOT_SIZE > 0) mask |= 1 << ARM_HARD_FRAME_POINTER_REGNUM; /* LR will also be pushed if any lo regs are pushed. */ if (mask & 0xff || thumb_force_lr_save ()) mask |= (1 << LR_REGNUM); /* Make sure we have a low work register if we need one. We will need one if we are going to push a high register, but we are not currently intending to push a low register. */ if ((mask & 0xff) == 0 && ((mask & 0x0f00) || TARGET_BACKTRACE)) { /* Use thumb_find_work_register to choose which register we will use. If the register is live then we will have to push it. Use LAST_LO_REGNUM as our fallback choice for the register to select. */ reg = thumb_find_work_register (1 << LAST_LO_REGNUM); if (! call_used_regs[reg]) mask |= 1 << reg; } return mask; } /* Return the number of bytes required to save VFP registers. */ static int arm_get_vfp_saved_size (void) { unsigned int regno; int count; int saved; saved = 0; /* Space for saved VFP registers. */ if (TARGET_HARD_FLOAT && TARGET_VFP) { count = 0; for (regno = FIRST_VFP_REGNUM; regno < LAST_VFP_REGNUM; regno += 2) { if ((!regs_ever_live[regno] || call_used_regs[regno]) && (!regs_ever_live[regno + 1] || call_used_regs[regno + 1])) { if (count > 0) { /* Workaround ARM10 VFPr1 bug. */ if (count == 2 && !arm_arch6) count++; saved += count * 8 + 4; } count = 0; } else count++; } if (count > 0) { if (count == 2 && !arm_arch6) count++; saved += count * 8 + 4; } } return saved; } /* Generate a function exit sequence. If REALLY_RETURN is false, then do everything bar the final return instruction. */ const char * output_return_instruction (rtx operand, int really_return, int reverse) { char conditional[10]; char instr[100]; unsigned reg; unsigned long live_regs_mask; unsigned long func_type; arm_stack_offsets *offsets; func_type = arm_current_func_type (); if (IS_NAKED (func_type)) return ""; if (IS_VOLATILE (func_type) && TARGET_ABORT_NORETURN) { /* If this function was declared non-returning, and we have found a tail call, then we have to trust that the called function won't return. */ if (really_return) { rtx ops[2]; /* Otherwise, trap an attempted return by aborting. */ ops[0] = operand; ops[1] = gen_rtx_SYMBOL_REF (Pmode, NEED_PLT_RELOC ? "abort(PLT)" : "abort"); assemble_external_libcall (ops[1]); output_asm_insn (reverse ? "bl%D0\t%a1" : "bl%d0\t%a1", ops); } return ""; } gcc_assert (!current_function_calls_alloca || really_return); sprintf (conditional, "%%?%%%c0", reverse ? 'D' : 'd'); return_used_this_function = 1; live_regs_mask = arm_compute_save_reg_mask (); if (live_regs_mask) { const char * return_reg; /* If we do not have any special requirements for function exit (e.g. interworking, or ISR) then we can load the return address directly into the PC. Otherwise we must load it into LR. */ if (really_return && ! TARGET_INTERWORK) return_reg = reg_names[PC_REGNUM]; else return_reg = reg_names[LR_REGNUM]; if ((live_regs_mask & (1 << IP_REGNUM)) == (1 << IP_REGNUM)) { /* There are three possible reasons for the IP register being saved. 1) a stack frame was created, in which case IP contains the old stack pointer, or 2) an ISR routine corrupted it, or 3) it was saved to align the stack on iWMMXt. In case 1, restore IP into SP, otherwise just restore IP. */ if (frame_pointer_needed) { live_regs_mask &= ~ (1 << IP_REGNUM); live_regs_mask |= (1 << SP_REGNUM); } else gcc_assert (IS_INTERRUPT (func_type) || TARGET_REALLY_IWMMXT); } /* On some ARM architectures it is faster to use LDR rather than LDM to load a single register. On other architectures, the cost is the same. In 26 bit mode, or for exception handlers, we have to use LDM to load the PC so that the CPSR is also restored. */ for (reg = 0; reg <= LAST_ARM_REGNUM; reg++) if (live_regs_mask == (1U << reg)) break; if (reg <= LAST_ARM_REGNUM && (reg != LR_REGNUM || ! really_return || ! IS_INTERRUPT (func_type))) { sprintf (instr, "ldr%s\t%%|%s, [%%|sp], #4", conditional, (reg == LR_REGNUM) ? return_reg : reg_names[reg]); } else { char *p; int first = 1; /* Generate the load multiple instruction to restore the registers. Note we can get here, even if frame_pointer_needed is true, but only if sp already points to the base of the saved core registers. */ if (live_regs_mask & (1 << SP_REGNUM)) { unsigned HOST_WIDE_INT stack_adjust; offsets = arm_get_frame_offsets (); stack_adjust = offsets->outgoing_args - offsets->saved_regs; gcc_assert (stack_adjust == 0 || stack_adjust == 4); if (stack_adjust && arm_arch5) sprintf (instr, "ldm%sib\t%%|sp, {", conditional); else { /* If we can't use ldmib (SA110 bug), then try to pop r3 instead. */ if (stack_adjust) live_regs_mask |= 1 << 3; sprintf (instr, "ldm%sfd\t%%|sp, {", conditional); } } else sprintf (instr, "ldm%sfd\t%%|sp!, {", conditional); p = instr + strlen (instr); for (reg = 0; reg <= SP_REGNUM; reg++) if (live_regs_mask & (1 << reg)) { int l = strlen (reg_names[reg]); if (first) first = 0; else { memcpy (p, ", ", 2); p += 2; } memcpy (p, "%|", 2); memcpy (p + 2, reg_names[reg], l); p += l + 2; } if (live_regs_mask & (1 << LR_REGNUM)) { sprintf (p, "%s%%|%s}", first ? "" : ", ", return_reg); /* If returning from an interrupt, restore the CPSR. */ if (IS_INTERRUPT (func_type)) strcat (p, "^"); } else strcpy (p, "}"); } output_asm_insn (instr, & operand); /* See if we need to generate an extra instruction to perform the actual function return. */ if (really_return && func_type != ARM_FT_INTERWORKED && (live_regs_mask & (1 << LR_REGNUM)) != 0) { /* The return has already been handled by loading the LR into the PC. */ really_return = 0; } } if (really_return) { switch ((int) ARM_FUNC_TYPE (func_type)) { case ARM_FT_ISR: case ARM_FT_FIQ: sprintf (instr, "sub%ss\t%%|pc, %%|lr, #4", conditional); break; case ARM_FT_INTERWORKED: sprintf (instr, "bx%s\t%%|lr", conditional); break; case ARM_FT_EXCEPTION: sprintf (instr, "mov%ss\t%%|pc, %%|lr", conditional); break; default: /* Use bx if it's available. */ if (arm_arch5 || arm_arch4t) sprintf (instr, "bx%s\t%%|lr", conditional); else sprintf (instr, "mov%s\t%%|pc, %%|lr", conditional); break; } output_asm_insn (instr, & operand); } return ""; } /* Write the function name into the code section, directly preceding the function prologue. Code will be output similar to this: t0 .ascii "arm_poke_function_name", 0 .align t1 .word 0xff000000 + (t1 - t0) arm_poke_function_name mov ip, sp stmfd sp!, {fp, ip, lr, pc} sub fp, ip, #4 When performing a stack backtrace, code can inspect the value of 'pc' stored at 'fp' + 0. If the trace function then looks at location pc - 12 and the top 8 bits are set, then we know that there is a function name embedded immediately preceding this location and has length ((pc[-3]) & 0xff000000). We assume that pc is declared as a pointer to an unsigned long. It is of no benefit to output the function name if we are assembling a leaf function. These function types will not contain a stack backtrace structure, therefore it is not possible to determine the function name. */ void arm_poke_function_name (FILE *stream, const char *name) { unsigned long alignlength; unsigned long length; rtx x; length = strlen (name) + 1; alignlength = ROUND_UP_WORD (length); ASM_OUTPUT_ASCII (stream, name, length); ASM_OUTPUT_ALIGN (stream, 2); x = GEN_INT ((unsigned HOST_WIDE_INT) 0xff000000 + alignlength); assemble_aligned_integer (UNITS_PER_WORD, x); } /* Place some comments into the assembler stream describing the current function. */ static void arm_output_function_prologue (FILE *f, HOST_WIDE_INT frame_size) { unsigned long func_type; if (!TARGET_ARM) { thumb_output_function_prologue (f, frame_size); return; } /* Sanity check. */ gcc_assert (!arm_ccfsm_state && !arm_target_insn); func_type = arm_current_func_type (); switch ((int) ARM_FUNC_TYPE (func_type)) { default: case ARM_FT_NORMAL: break; case ARM_FT_INTERWORKED: asm_fprintf (f, "\t%@ Function supports interworking.\n"); break; case ARM_FT_ISR: asm_fprintf (f, "\t%@ Interrupt Service Routine.\n"); break; case ARM_FT_FIQ: asm_fprintf (f, "\t%@ Fast Interrupt Service Routine.\n"); break; case ARM_FT_EXCEPTION: asm_fprintf (f, "\t%@ ARM Exception Handler.\n"); break; } if (IS_NAKED (func_type)) asm_fprintf (f, "\t%@ Naked Function: prologue and epilogue provided by programmer.\n"); if (IS_VOLATILE (func_type)) asm_fprintf (f, "\t%@ Volatile: function does not return.\n"); if (IS_NESTED (func_type)) asm_fprintf (f, "\t%@ Nested: function declared inside another function.\n"); asm_fprintf (f, "\t%@ args = %d, pretend = %d, frame = %wd\n", current_function_args_size, current_function_pretend_args_size, frame_size); asm_fprintf (f, "\t%@ frame_needed = %d, uses_anonymous_args = %d\n", frame_pointer_needed, cfun->machine->uses_anonymous_args); if (cfun->machine->lr_save_eliminated) asm_fprintf (f, "\t%@ link register save eliminated.\n"); if (current_function_calls_eh_return) asm_fprintf (f, "\t@ Calls __builtin_eh_return.\n"); #ifdef AOF_ASSEMBLER if (flag_pic) asm_fprintf (f, "\tmov\t%r, %r\n", IP_REGNUM, PIC_OFFSET_TABLE_REGNUM); #endif return_used_this_function = 0; } const char * arm_output_epilogue (rtx sibling) { int reg; unsigned long saved_regs_mask; unsigned long func_type; /* Floats_offset is the offset from the "virtual" frame. In an APCS frame that is $fp + 4 for a non-variadic function. */ int floats_offset = 0; rtx operands[3]; FILE * f = asm_out_file; unsigned int lrm_count = 0; int really_return = (sibling == NULL); int start_reg; arm_stack_offsets *offsets; /* If we have already generated the return instruction then it is futile to generate anything else. */ if (use_return_insn (FALSE, sibling) && return_used_this_function) return ""; func_type = arm_current_func_type (); if (IS_NAKED (func_type)) /* Naked functions don't have epilogues. */ return ""; if (IS_VOLATILE (func_type) && TARGET_ABORT_NORETURN) { rtx op; /* A volatile function should never return. Call abort. */ op = gen_rtx_SYMBOL_REF (Pmode, NEED_PLT_RELOC ? "abort(PLT)" : "abort"); assemble_external_libcall (op); output_asm_insn ("bl\t%a0", &op); return ""; } /* If we are throwing an exception, then we really must be doing a return, so we can't tail-call. */ gcc_assert (!current_function_calls_eh_return || really_return); offsets = arm_get_frame_offsets (); saved_regs_mask = arm_compute_save_reg_mask (); if (TARGET_IWMMXT) lrm_count = bit_count (saved_regs_mask); floats_offset = offsets->saved_args; /* Compute how far away the floats will be. */ for (reg = 0; reg <= LAST_ARM_REGNUM; reg++) if (saved_regs_mask & (1 << reg)) floats_offset += 4; if (frame_pointer_needed) { /* This variable is for the Virtual Frame Pointer, not VFP regs. */ int vfp_offset = offsets->frame; if (arm_fpu_arch == FPUTYPE_FPA_EMU2) { for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--) if (regs_ever_live[reg] && !call_used_regs[reg]) { floats_offset += 12; asm_fprintf (f, "\tldfe\t%r, [%r, #-%d]\n", reg, FP_REGNUM, floats_offset - vfp_offset); } } else { start_reg = LAST_FPA_REGNUM; for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--) { if (regs_ever_live[reg] && !call_used_regs[reg]) { floats_offset += 12; /* We can't unstack more than four registers at once. */ if (start_reg - reg == 3) { asm_fprintf (f, "\tlfm\t%r, 4, [%r, #-%d]\n", reg, FP_REGNUM, floats_offset - vfp_offset); start_reg = reg - 1; } } else { if (reg != start_reg) asm_fprintf (f, "\tlfm\t%r, %d, [%r, #-%d]\n", reg + 1, start_reg - reg, FP_REGNUM, floats_offset - vfp_offset); start_reg = reg - 1; } } /* Just in case the last register checked also needs unstacking. */ if (reg != start_reg) asm_fprintf (f, "\tlfm\t%r, %d, [%r, #-%d]\n", reg + 1, start_reg - reg, FP_REGNUM, floats_offset - vfp_offset); } if (TARGET_HARD_FLOAT && TARGET_VFP) { int saved_size; /* The fldmx insn does not have base+offset addressing modes, so we use IP to hold the address. */ saved_size = arm_get_vfp_saved_size (); if (saved_size > 0) { floats_offset += saved_size; asm_fprintf (f, "\tsub\t%r, %r, #%d\n", IP_REGNUM, FP_REGNUM, floats_offset - vfp_offset); } start_reg = FIRST_VFP_REGNUM; for (reg = FIRST_VFP_REGNUM; reg < LAST_VFP_REGNUM; reg += 2) { if ((!regs_ever_live[reg] || call_used_regs[reg]) && (!regs_ever_live[reg + 1] || call_used_regs[reg + 1])) { if (start_reg != reg) arm_output_fldmx (f, IP_REGNUM, (start_reg - FIRST_VFP_REGNUM) / 2, (reg - start_reg) / 2); start_reg = reg + 2; } } if (start_reg != reg) arm_output_fldmx (f, IP_REGNUM, (start_reg - FIRST_VFP_REGNUM) / 2, (reg - start_reg) / 2); } if (TARGET_IWMMXT) { /* The frame pointer is guaranteed to be non-double-word aligned. This is because it is set to (old_stack_pointer - 4) and the old_stack_pointer was double word aligned. Thus the offset to the iWMMXt registers to be loaded must also be non-double-word sized, so that the resultant address *is* double-word aligned. We can ignore floats_offset since that was already included in the live_regs_mask. */ lrm_count += (lrm_count % 2 ? 2 : 1); for (reg = LAST_IWMMXT_REGNUM; reg >= FIRST_IWMMXT_REGNUM; reg--) if (regs_ever_live[reg] && !call_used_regs[reg]) { asm_fprintf (f, "\twldrd\t%r, [%r, #-%d]\n", reg, FP_REGNUM, lrm_count * 4); lrm_count += 2; } } /* saved_regs_mask should contain the IP, which at the time of stack frame generation actually contains the old stack pointer. So a quick way to unwind the stack is just pop the IP register directly into the stack pointer. */ gcc_assert (saved_regs_mask & (1 << IP_REGNUM)); saved_regs_mask &= ~ (1 << IP_REGNUM); saved_regs_mask |= (1 << SP_REGNUM); /* There are two registers left in saved_regs_mask - LR and PC. We only need to restore the LR register (the return address), but to save time we can load it directly into the PC, unless we need a special function exit sequence, or we are not really returning. */ if (really_return && ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL && !current_function_calls_eh_return) /* Delete the LR from the register mask, so that the LR on the stack is loaded into the PC in the register mask. */ saved_regs_mask &= ~ (1 << LR_REGNUM); else saved_regs_mask &= ~ (1 << PC_REGNUM); /* We must use SP as the base register, because SP is one of the registers being restored. If an interrupt or page fault happens in the ldm instruction, the SP might or might not have been restored. That would be bad, as then SP will no longer indicate the safe area of stack, and we can get stack corruption. Using SP as the base register means that it will be reset correctly to the original value, should an interrupt occur. If the stack pointer already points at the right place, then omit the subtraction. */ if (offsets->outgoing_args != (1 + (int) bit_count (saved_regs_mask)) || current_function_calls_alloca) asm_fprintf (f, "\tsub\t%r, %r, #%d\n", SP_REGNUM, FP_REGNUM, 4 * bit_count (saved_regs_mask)); print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask); if (IS_INTERRUPT (func_type)) /* Interrupt handlers will have pushed the IP onto the stack, so restore it now. */ print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, 1 << IP_REGNUM); } else { /* Restore stack pointer if necessary. */ if (offsets->outgoing_args != offsets->saved_regs) { operands[0] = operands[1] = stack_pointer_rtx; operands[2] = GEN_INT (offsets->outgoing_args - offsets->saved_regs); output_add_immediate (operands); } if (arm_fpu_arch == FPUTYPE_FPA_EMU2) { for (reg = FIRST_FPA_REGNUM; reg <= LAST_FPA_REGNUM; reg++) if (regs_ever_live[reg] && !call_used_regs[reg]) asm_fprintf (f, "\tldfe\t%r, [%r], #12\n", reg, SP_REGNUM); } else { start_reg = FIRST_FPA_REGNUM; for (reg = FIRST_FPA_REGNUM; reg <= LAST_FPA_REGNUM; reg++) { if (regs_ever_live[reg] && !call_used_regs[reg]) { if (reg - start_reg == 3) { asm_fprintf (f, "\tlfmfd\t%r, 4, [%r]!\n", start_reg, SP_REGNUM); start_reg = reg + 1; } } else { if (reg != start_reg) asm_fprintf (f, "\tlfmfd\t%r, %d, [%r]!\n", start_reg, reg - start_reg, SP_REGNUM); start_reg = reg + 1; } } /* Just in case the last register checked also needs unstacking. */ if (reg != start_reg) asm_fprintf (f, "\tlfmfd\t%r, %d, [%r]!\n", start_reg, reg - start_reg, SP_REGNUM); } if (TARGET_HARD_FLOAT && TARGET_VFP) { start_reg = FIRST_VFP_REGNUM; for (reg = FIRST_VFP_REGNUM; reg < LAST_VFP_REGNUM; reg += 2) { if ((!regs_ever_live[reg] || call_used_regs[reg]) && (!regs_ever_live[reg + 1] || call_used_regs[reg + 1])) { if (start_reg != reg) arm_output_fldmx (f, SP_REGNUM, (start_reg - FIRST_VFP_REGNUM) / 2, (reg - start_reg) / 2); start_reg = reg + 2; } } if (start_reg != reg) arm_output_fldmx (f, SP_REGNUM, (start_reg - FIRST_VFP_REGNUM) / 2, (reg - start_reg) / 2); } if (TARGET_IWMMXT) for (reg = FIRST_IWMMXT_REGNUM; reg <= LAST_IWMMXT_REGNUM; reg++) if (regs_ever_live[reg] && !call_used_regs[reg]) asm_fprintf (f, "\twldrd\t%r, [%r], #8\n", reg, SP_REGNUM); /* If we can, restore the LR into the PC. */ if (ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL && really_return && current_function_pretend_args_size == 0 && saved_regs_mask & (1 << LR_REGNUM) && !current_function_calls_eh_return) { saved_regs_mask &= ~ (1 << LR_REGNUM); saved_regs_mask |= (1 << PC_REGNUM); } /* Load the registers off the stack. If we only have one register to load use the LDR instruction - it is faster. */ if (saved_regs_mask == (1 << LR_REGNUM)) { asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM); } else if (saved_regs_mask) { if (saved_regs_mask & (1 << SP_REGNUM)) /* Note - write back to the stack register is not enabled (i.e. "ldmfd sp!..."). We know that the stack pointer is in the list of registers and if we add writeback the instruction becomes UNPREDICTABLE. */ print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask); else print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask); } if (current_function_pretend_args_size) { /* Unwind the pre-pushed regs. */ operands[0] = operands[1] = stack_pointer_rtx; operands[2] = GEN_INT (current_function_pretend_args_size); output_add_immediate (operands); } } /* We may have already restored PC directly from the stack. */ if (!really_return || saved_regs_mask & (1 << PC_REGNUM)) return ""; /* Stack adjustment for exception handler. */ if (current_function_calls_eh_return) asm_fprintf (f, "\tadd\t%r, %r, %r\n", SP_REGNUM, SP_REGNUM, ARM_EH_STACKADJ_REGNUM); /* Generate the return instruction. */ switch ((int) ARM_FUNC_TYPE (func_type)) { case ARM_FT_ISR: case ARM_FT_FIQ: asm_fprintf (f, "\tsubs\t%r, %r, #4\n", PC_REGNUM, LR_REGNUM); break; case ARM_FT_EXCEPTION: asm_fprintf (f, "\tmovs\t%r, %r\n", PC_REGNUM, LR_REGNUM); break; case ARM_FT_INTERWORKED: asm_fprintf (f, "\tbx\t%r\n", LR_REGNUM); break; default: if (arm_arch5 || arm_arch4t) asm_fprintf (f, "\tbx\t%r\n", LR_REGNUM); else asm_fprintf (f, "\tmov\t%r, %r\n", PC_REGNUM, LR_REGNUM); break; } return ""; } static void arm_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED, HOST_WIDE_INT frame_size ATTRIBUTE_UNUSED) { arm_stack_offsets *offsets; if (TARGET_THUMB) { int regno; /* Emit any call-via-reg trampolines that are needed for v4t support of call_reg and call_value_reg type insns. */ for (regno = 0; regno < LR_REGNUM; regno++) { rtx label = cfun->machine->call_via[regno]; if (label != NULL) { switch_to_section (function_section (current_function_decl)); targetm.asm_out.internal_label (asm_out_file, "L", CODE_LABEL_NUMBER (label)); asm_fprintf (asm_out_file, "\tbx\t%r\n", regno); } } /* ??? Probably not safe to set this here, since it assumes that a function will be emitted as assembly immediately after we generate RTL for it. This does not happen for inline functions. */ return_used_this_function = 0; } else { /* We need to take into account any stack-frame rounding. */ offsets = arm_get_frame_offsets (); gcc_assert (!use_return_insn (FALSE, NULL) || !return_used_this_function || offsets->saved_regs == offsets->outgoing_args || frame_pointer_needed); /* Reset the ARM-specific per-function variables. */ after_arm_reorg = 0; } } /* Generate and emit an insn that we will recognize as a push_multi. Unfortunately, since this insn does not reflect very well the actual semantics of the operation, we need to annotate the insn for the benefit of DWARF2 frame unwind information. */ static rtx emit_multi_reg_push (unsigned long mask) { int num_regs = 0; int num_dwarf_regs; int i, j; rtx par; rtx dwarf; int dwarf_par_index; rtx tmp, reg; for (i = 0; i <= LAST_ARM_REGNUM; i++) if (mask & (1 << i)) num_regs++; gcc_assert (num_regs && num_regs <= 16); /* We don't record the PC in the dwarf frame information. */ num_dwarf_regs = num_regs; if (mask & (1 << PC_REGNUM)) num_dwarf_regs--; /* For the body of the insn we are going to generate an UNSPEC in parallel with several USEs. This allows the insn to be recognized by the push_multi pattern in the arm.md file. The insn looks something like this: (parallel [ (set (mem:BLK (pre_dec:BLK (reg:SI sp))) (unspec:BLK [(reg:SI r4)] UNSPEC_PUSH_MULT)) (use (reg:SI 11 fp)) (use (reg:SI 12 ip)) (use (reg:SI 14 lr)) (use (reg:SI 15 pc)) ]) For the frame note however, we try to be more explicit and actually show each register being stored into the stack frame, plus a (single) decrement of the stack pointer. We do it this way in order to be friendly to the stack unwinding code, which only wants to see a single stack decrement per instruction. The RTL we generate for the note looks something like this: (sequence [ (set (reg:SI sp) (plus:SI (reg:SI sp) (const_int -20))) (set (mem:SI (reg:SI sp)) (reg:SI r4)) (set (mem:SI (plus:SI (reg:SI sp) (const_int 4))) (reg:SI fp)) (set (mem:SI (plus:SI (reg:SI sp) (const_int 8))) (reg:SI ip)) (set (mem:SI (plus:SI (reg:SI sp) (const_int 12))) (reg:SI lr)) ]) This sequence is used both by the code to support stack unwinding for exceptions handlers and the code to generate dwarf2 frame debugging. */ par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs)); dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_dwarf_regs + 1)); dwarf_par_index = 1; for (i = 0; i <= LAST_ARM_REGNUM; i++) { if (mask & (1 << i)) { reg = gen_rtx_REG (SImode, i); XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, gen_frame_mem (BLKmode, gen_rtx_PRE_DEC (BLKmode, stack_pointer_rtx)), gen_rtx_UNSPEC (BLKmode, gen_rtvec (1, reg), UNSPEC_PUSH_MULT)); if (i != PC_REGNUM) { tmp = gen_rtx_SET (VOIDmode, gen_frame_mem (SImode, stack_pointer_rtx), reg); RTX_FRAME_RELATED_P (tmp) = 1; XVECEXP (dwarf, 0, dwarf_par_index) = tmp; dwarf_par_index++; } break; } } for (j = 1, i++; j < num_regs; i++) { if (mask & (1 << i)) { reg = gen_rtx_REG (SImode, i); XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg); if (i != PC_REGNUM) { tmp = gen_rtx_SET (VOIDmode, gen_frame_mem (SImode, plus_constant (stack_pointer_rtx, 4 * j)), reg); RTX_FRAME_RELATED_P (tmp) = 1; XVECEXP (dwarf, 0, dwarf_par_index++) = tmp; } j++; } } par = emit_insn (par); tmp = gen_rtx_SET (VOIDmode, stack_pointer_rtx, plus_constant (stack_pointer_rtx, -4 * num_regs)); RTX_FRAME_RELATED_P (tmp) = 1; XVECEXP (dwarf, 0, 0) = tmp; REG_NOTES (par) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf, REG_NOTES (par)); return par; } /* Calculate the size of the return value that is passed in registers. */ static int arm_size_return_regs (void) { enum machine_mode mode; if (current_function_return_rtx != 0) mode = GET_MODE (current_function_return_rtx); else mode = DECL_MODE (DECL_RESULT (current_function_decl)); return GET_MODE_SIZE (mode); } static rtx emit_sfm (int base_reg, int count) { rtx par; rtx dwarf; rtx tmp, reg; int i; par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1)); reg = gen_rtx_REG (XFmode, base_reg++); XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, gen_frame_mem (BLKmode, gen_rtx_PRE_DEC (BLKmode, stack_pointer_rtx)), gen_rtx_UNSPEC (BLKmode, gen_rtvec (1, reg), UNSPEC_PUSH_MULT)); tmp = gen_rtx_SET (VOIDmode, gen_frame_mem (XFmode, stack_pointer_rtx), reg); RTX_FRAME_RELATED_P (tmp) = 1; XVECEXP (dwarf, 0, 1) = tmp; for (i = 1; i < count; i++) { reg = gen_rtx_REG (XFmode, base_reg++); XVECEXP (par, 0, i) = gen_rtx_USE (VOIDmode, reg); tmp = gen_rtx_SET (VOIDmode, gen_frame_mem (XFmode, plus_constant (stack_pointer_rtx, i * 12)), reg); RTX_FRAME_RELATED_P (tmp) = 1; XVECEXP (dwarf, 0, i + 1) = tmp; } tmp = gen_rtx_SET (VOIDmode, stack_pointer_rtx, plus_constant (stack_pointer_rtx, -12 * count)); RTX_FRAME_RELATED_P (tmp) = 1; XVECEXP (dwarf, 0, 0) = tmp; par = emit_insn (par); REG_NOTES (par) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf, REG_NOTES (par)); return par; } /* Return true if the current function needs to save/restore LR. */ static bool thumb_force_lr_save (void) { return !cfun->machine->lr_save_eliminated && (!leaf_function_p () || thumb_far_jump_used_p () || regs_ever_live [LR_REGNUM]); } /* Compute the distance from register FROM to register TO. These can be the arg pointer (26), the soft frame pointer (25), the stack pointer (13) or the hard frame pointer (11). In thumb mode r7 is used as the soft frame pointer, if needed. Typical stack layout looks like this: old stack pointer -> | | ---- | | \ | | saved arguments for | | vararg functions | | / -- hard FP & arg pointer -> | | \ | | stack | | frame | | / -- | | \ | | call saved | | registers soft frame pointer -> | | / -- | | \ | | local | | variables locals base pointer -> | | / -- | | \ | | outgoing | | arguments current stack pointer -> | | / -- For a given function some or all of these stack components may not be needed, giving rise to the possibility of eliminating some of the registers. The values returned by this function must reflect the behavior of arm_expand_prologue() and arm_compute_save_reg_mask(). The sign of the number returned reflects the direction of stack growth, so the values are positive for all eliminations except from the soft frame pointer to the hard frame pointer. SFP may point just inside the local variables block to ensure correct alignment. */ /* Calculate stack offsets. These are used to calculate register elimination offsets and in prologue/epilogue code. */ static arm_stack_offsets * arm_get_frame_offsets (void) { struct arm_stack_offsets *offsets; unsigned long func_type; int leaf; int saved; HOST_WIDE_INT frame_size; offsets = &cfun->machine->stack_offsets; /* We need to know if we are a leaf function. Unfortunately, it is possible to be called after start_sequence has been called, which causes get_insns to return the insns for the sequence, not the function, which will cause leaf_function_p to return the incorrect result. to know about leaf functions once reload has completed, and the frame size cannot be changed after that time, so we can safely use the cached value. */ if (reload_completed) return offsets; /* Initially this is the size of the local variables. It will translated into an offset once we have determined the size of preceding data. */ frame_size = ROUND_UP_WORD (get_frame_size ()); leaf = leaf_function_p (); /* Space for variadic functions. */ offsets->saved_args = current_function_pretend_args_size; offsets->frame = offsets->saved_args + (frame_pointer_needed ? 4 : 0); if (TARGET_ARM) { unsigned int regno; saved = bit_count (arm_compute_save_reg_mask ()) * 4; /* We know that SP will be doubleword aligned on entry, and we must preserve that condition at any subroutine call. We also require the soft frame pointer to be doubleword aligned. */ if (TARGET_REALLY_IWMMXT) { /* Check for the call-saved iWMMXt registers. */ for (regno = FIRST_IWMMXT_REGNUM; regno <= LAST_IWMMXT_REGNUM; regno++) if (regs_ever_live [regno] && ! call_used_regs [regno]) saved += 8; } func_type = arm_current_func_type (); if (! IS_VOLATILE (func_type)) { /* Space for saved FPA registers. */ for (regno = FIRST_FPA_REGNUM; regno <= LAST_FPA_REGNUM; regno++) if (regs_ever_live[regno] && ! call_used_regs[regno]) saved += 12; /* Space for saved VFP registers. */ if (TARGET_HARD_FLOAT && TARGET_VFP) saved += arm_get_vfp_saved_size (); } } else /* TARGET_THUMB */ { saved = bit_count (thumb_compute_save_reg_mask ()) * 4; if (TARGET_BACKTRACE) saved += 16; } /* Saved registers include the stack frame. */ offsets->saved_regs = offsets->saved_args + saved; offsets->soft_frame = offsets->saved_regs + CALLER_INTERWORKING_SLOT_SIZE; /* A leaf function does not need any stack alignment if it has nothing on the stack. */ if (leaf && frame_size == 0) { offsets->outgoing_args = offsets->soft_frame; offsets->locals_base = offsets->soft_frame; return offsets; } /* Ensure SFP has the correct alignment. */ if (ARM_DOUBLEWORD_ALIGN && (offsets->soft_frame & 7)) offsets->soft_frame += 4; offsets->locals_base = offsets->soft_frame + frame_size; offsets->outgoing_args = (offsets->locals_base + current_function_outgoing_args_size); if (ARM_DOUBLEWORD_ALIGN) { /* Ensure SP remains doubleword aligned. */ if (offsets->outgoing_args & 7) offsets->outgoing_args += 4; gcc_assert (!(offsets->outgoing_args & 7)); } return offsets; } /* Calculate the relative offsets for the different stack pointers. Positive offsets are in the direction of stack growth. */ HOST_WIDE_INT arm_compute_initial_elimination_offset (unsigned int from, unsigned int to) { arm_stack_offsets *offsets; offsets = arm_get_frame_offsets (); /* OK, now we have enough information to compute the distances. There must be an entry in these switch tables for each pair of registers in ELIMINABLE_REGS, even if some of the entries seem to be redundant or useless. */ switch (from) { case ARG_POINTER_REGNUM: switch (to) { case THUMB_HARD_FRAME_POINTER_REGNUM: return 0; case FRAME_POINTER_REGNUM: /* This is the reverse of the soft frame pointer to hard frame pointer elimination below. */ return offsets->soft_frame - offsets->saved_args; case ARM_HARD_FRAME_POINTER_REGNUM: /* If there is no stack frame then the hard frame pointer and the arg pointer coincide. */ if (offsets->frame == offsets->saved_regs) return 0; /* FIXME: Not sure about this. Maybe we should always return 0 ? */ return (frame_pointer_needed && cfun->static_chain_decl != NULL && ! cfun->machine->uses_anonymous_args) ? 4 : 0; case STACK_POINTER_REGNUM: /* If nothing has been pushed on the stack at all then this will return -4. This *is* correct! */ return offsets->outgoing_args - (offsets->saved_args + 4); default: gcc_unreachable (); } gcc_unreachable (); case FRAME_POINTER_REGNUM: switch (to) { case THUMB_HARD_FRAME_POINTER_REGNUM: return 0; case ARM_HARD_FRAME_POINTER_REGNUM: /* The hard frame pointer points to the top entry in the stack frame. The soft frame pointer to the bottom entry in the stack frame. If there is no stack frame at all, then they are identical. */ return offsets->frame - offsets->soft_frame; case STACK_POINTER_REGNUM: return offsets->outgoing_args - offsets->soft_frame; default: gcc_unreachable (); } gcc_unreachable (); default: /* You cannot eliminate from the stack pointer. In theory you could eliminate from the hard frame pointer to the stack pointer, but this will never happen, since if a stack frame is not needed the hard frame pointer will never be used. */ gcc_unreachable (); } } /* Generate the prologue instructions for entry into an ARM function. */ void arm_expand_prologue (void) { int reg; rtx amount; rtx insn; rtx ip_rtx; unsigned long live_regs_mask; unsigned long func_type; int fp_offset = 0; int saved_pretend_args = 0; int saved_regs = 0; unsigned HOST_WIDE_INT args_to_push; arm_stack_offsets *offsets; func_type = arm_current_func_type (); /* Naked functions don't have prologues. */ if (IS_NAKED (func_type)) return; /* Make a copy of c_f_p_a_s as we may need to modify it locally. */ args_to_push = current_function_pretend_args_size; /* Compute which register we will have to save onto the stack. */ live_regs_mask = arm_compute_save_reg_mask (); ip_rtx = gen_rtx_REG (SImode, IP_REGNUM); if (frame_pointer_needed) { if (IS_INTERRUPT (func_type)) { /* Interrupt functions must not corrupt any registers. Creating a frame pointer however, corrupts the IP register, so we must push it first. */ insn = emit_multi_reg_push (1 << IP_REGNUM); /* Do not set RTX_FRAME_RELATED_P on this insn. The dwarf stack unwinding code only wants to see one stack decrement per function, and this is not it. If this instruction is labeled as being part of the frame creation sequence then dwarf2out_frame_debug_expr will die when it encounters the assignment of IP to FP later on, since the use of SP here establishes SP as the CFA register and not IP. Anyway this instruction is not really part of the stack frame creation although it is part of the prologue. */ } else if (IS_NESTED (func_type)) { /* The Static chain register is the same as the IP register used as a scratch register during stack frame creation. To get around this need to find somewhere to store IP whilst the frame is being created. We try the following places in order: 1. The last argument register. 2. A slot on the stack above the frame. (This only works if the function is not a varargs function). 3. Register r3, after pushing the argument registers onto the stack. Note - we only need to tell the dwarf2 backend about the SP adjustment in the second variant; the static chain register doesn't need to be unwound, as it doesn't contain a value inherited from the caller. */ if (regs_ever_live[3] == 0) insn = emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx); else if (args_to_push == 0) { rtx dwarf; insn = gen_rtx_PRE_DEC (SImode, stack_pointer_rtx); insn = emit_set_insn (gen_frame_mem (SImode, insn), ip_rtx); fp_offset = 4; /* Just tell the dwarf backend that we adjusted SP. */ dwarf = gen_rtx_SET (VOIDmode, stack_pointer_rtx, plus_constant (stack_pointer_rtx, -fp_offset)); RTX_FRAME_RELATED_P (insn) = 1; REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf, REG_NOTES (insn)); } else { /* Store the args on the stack. */ if (cfun->machine->uses_anonymous_args) insn = emit_multi_reg_push ((0xf0 >> (args_to_push / 4)) & 0xf); else insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (- args_to_push))); RTX_FRAME_RELATED_P (insn) = 1; saved_pretend_args = 1; fp_offset = args_to_push; args_to_push = 0; /* Now reuse r3 to preserve IP. */ emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx); } } insn = emit_set_insn (ip_rtx, plus_constant (stack_pointer_rtx, fp_offset)); RTX_FRAME_RELATED_P (insn) = 1; } if (args_to_push) { /* Push the argument registers, or reserve space for them. */ if (cfun->machine->uses_anonymous_args) insn = emit_multi_reg_push ((0xf0 >> (args_to_push / 4)) & 0xf); else insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (- args_to_push))); RTX_FRAME_RELATED_P (insn) = 1; } /* If this is an interrupt service routine, and the link register is going to be pushed, and we are not creating a stack frame, (which would involve an extra push of IP and a pop in the epilogue) subtracting four from LR now will mean that the function return can be done with a single instruction. */ if ((func_type == ARM_FT_ISR || func_type == ARM_FT_FIQ) && (live_regs_mask & (1 << LR_REGNUM)) != 0 && ! frame_pointer_needed) { rtx lr = gen_rtx_REG (SImode, LR_REGNUM); emit_set_insn (lr, plus_constant (lr, -4)); } if (live_regs_mask) { insn = emit_multi_reg_push (live_regs_mask); saved_regs += bit_count (live_regs_mask) * 4; RTX_FRAME_RELATED_P (insn) = 1; } if (TARGET_IWMMXT) for (reg = LAST_IWMMXT_REGNUM; reg >= FIRST_IWMMXT_REGNUM; reg--) if (regs_ever_live[reg] && ! call_used_regs [reg]) { insn = gen_rtx_PRE_DEC (V2SImode, stack_pointer_rtx); insn = gen_frame_mem (V2SImode, insn); insn = emit_set_insn (insn, gen_rtx_REG (V2SImode, reg)); RTX_FRAME_RELATED_P (insn) = 1; saved_regs += 8; } if (! IS_VOLATILE (func_type)) { int start_reg; /* Save any floating point call-saved registers used by this function. */ if (arm_fpu_arch == FPUTYPE_FPA_EMU2) { for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--) if (regs_ever_live[reg] && !call_used_regs[reg]) { insn = gen_rtx_PRE_DEC (XFmode, stack_pointer_rtx); insn = gen_frame_mem (XFmode, insn); insn = emit_set_insn (insn, gen_rtx_REG (XFmode, reg)); RTX_FRAME_RELATED_P (insn) = 1; saved_regs += 12; } } else { start_reg = LAST_FPA_REGNUM; for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--) { if (regs_ever_live[reg] && !call_used_regs[reg]) { if (start_reg - reg == 3) { insn = emit_sfm (reg, 4); RTX_FRAME_RELATED_P (insn) = 1; saved_regs += 48; start_reg = reg - 1; } } else { if (start_reg != reg) { insn = emit_sfm (reg + 1, start_reg - reg); RTX_FRAME_RELATED_P (insn) = 1; saved_regs += (start_reg - reg) * 12; } start_reg = reg - 1; } } if (start_reg != reg) { insn = emit_sfm (reg + 1, start_reg - reg); saved_regs += (start_reg - reg) * 12; RTX_FRAME_RELATED_P (insn) = 1; } } if (TARGET_HARD_FLOAT && TARGET_VFP) { start_reg = FIRST_VFP_REGNUM; for (reg = FIRST_VFP_REGNUM; reg < LAST_VFP_REGNUM; reg += 2) { if ((!regs_ever_live[reg] || call_used_regs[reg]) && (!regs_ever_live[reg + 1] || call_used_regs[reg + 1])) { if (start_reg != reg) saved_regs += vfp_emit_fstmx (start_reg, (reg - start_reg) / 2); start_reg = reg + 2; } } if (start_reg != reg) saved_regs += vfp_emit_fstmx (start_reg, (reg - start_reg) / 2); } } if (frame_pointer_needed) { /* Create the new frame pointer. */ insn = GEN_INT (-(4 + args_to_push + fp_offset)); insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, ip_rtx, insn)); RTX_FRAME_RELATED_P (insn) = 1; if (IS_NESTED (func_type)) { /* Recover the static chain register. */ if (regs_ever_live [3] == 0 || saved_pretend_args) insn = gen_rtx_REG (SImode, 3); else /* if (current_function_pretend_args_size == 0) */ { insn = plus_constant (hard_frame_pointer_rtx, 4); insn = gen_frame_mem (SImode, insn); } emit_set_insn (ip_rtx, insn); /* Add a USE to stop propagate_one_insn() from barfing. */ emit_insn (gen_prologue_use (ip_rtx)); } } offsets = arm_get_frame_offsets (); if (offsets->outgoing_args != offsets->saved_args + saved_regs) { /* This add can produce multiple insns for a large constant, so we need to get tricky. */ rtx last = get_last_insn (); amount = GEN_INT (offsets->saved_args + saved_regs - offsets->outgoing_args); insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, amount)); do { last = last ? NEXT_INSN (last) : get_insns (); RTX_FRAME_RELATED_P (last) = 1; } while (last != insn); /* If the frame pointer is needed, emit a special barrier that will prevent the scheduler from moving stores to the frame before the stack adjustment. */ if (frame_pointer_needed) insn = emit_insn (gen_stack_tie (stack_pointer_rtx, hard_frame_pointer_rtx)); } if (flag_pic && arm_pic_register != INVALID_REGNUM) arm_load_pic_register (0UL); /* If we are profiling, make sure no instructions are scheduled before the call to mcount. Similarly if the user has requested no scheduling in the prolog. Similarly if we want non-call exceptions using the EABI unwinder, to prevent faulting instructions from being swapped with a stack adjustment. */ if (current_function_profile || !TARGET_SCHED_PROLOG || (ARM_EABI_UNWIND_TABLES && flag_non_call_exceptions)) emit_insn (gen_blockage ()); /* If the link register is being kept alive, with the return address in it, then make sure that it does not get reused by the ce2 pass. */ if ((live_regs_mask & (1 << LR_REGNUM)) == 0) { emit_insn (gen_prologue_use (gen_rtx_REG (SImode, LR_REGNUM))); cfun->machine->lr_save_eliminated = 1; } } /* If CODE is 'd', then the X is a condition operand and the instruction should only be executed if the condition is true. if CODE is 'D', then the X is a condition operand and the instruction should only be executed if the condition is false: however, if the mode of the comparison is CCFPEmode, then always execute the instruction -- we do this because in these circumstances !GE does not necessarily imply LT; in these cases the instruction pattern will take care to make sure that an instruction containing %d will follow, thereby undoing the effects of doing this instruction unconditionally. If CODE is 'N' then X is a floating point operand that must be negated before output. If CODE is 'B' then output a bitwise inverted value of X (a const int). If X is a REG and CODE is `M', output a ldm/stm style multi-reg. */ void arm_print_operand (FILE *stream, rtx x, int code) { switch (code) { case '@': fputs (ASM_COMMENT_START, stream); return; case '_': fputs (user_label_prefix, stream); return; case '|': fputs (REGISTER_PREFIX, stream); return; case '?': if (arm_ccfsm_state == 3 || arm_ccfsm_state == 4) { if (TARGET_THUMB) { output_operand_lossage ("predicated Thumb instruction"); break; } if (current_insn_predicate != NULL) { output_operand_lossage ("predicated instruction in conditional sequence"); break; } fputs (arm_condition_codes[arm_current_cc], stream); } else if (current_insn_predicate) { enum arm_cond_code code; if (TARGET_THUMB) { output_operand_lossage ("predicated Thumb instruction"); break; } code = get_arm_condition_code (current_insn_predicate); fputs (arm_condition_codes[code], stream); } return; case 'N': { REAL_VALUE_TYPE r; REAL_VALUE_FROM_CONST_DOUBLE (r, x); r = REAL_VALUE_NEGATE (r); fprintf (stream, "%s", fp_const_from_val (&r)); } return; case 'B': if (GET_CODE (x) == CONST_INT) { HOST_WIDE_INT val; val = ARM_SIGN_EXTEND (~INTVAL (x)); fprintf (stream, HOST_WIDE_INT_PRINT_DEC, val); } else { putc ('~', stream); output_addr_const (stream, x); } return; case 'i': fprintf (stream, "%s", arithmetic_instr (x, 1)); return; /* Truncate Cirrus shift counts. */ case 's': if (GET_CODE (x) == CONST_INT) { fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0x3f); return; } arm_print_operand (stream, x, 0); return; case 'I': fprintf (stream, "%s", arithmetic_instr (x, 0)); return; case 'S': { HOST_WIDE_INT val; const char *shift; if (!shift_operator (x, SImode)) { output_operand_lossage ("invalid shift operand"); break; } shift = shift_op (x, &val); if (shift) { fprintf (stream, ", %s ", shift); if (val == -1) arm_print_operand (stream, XEXP (x, 1), 0); else fprintf (stream, "#" HOST_WIDE_INT_PRINT_DEC, val); } } return; /* An explanation of the 'Q', 'R' and 'H' register operands: In a pair of registers containing a DI or DF value the 'Q' operand returns the register number of the register containing the least significant part of the value. The 'R' operand returns the register number of the register containing the most significant part of the value. The 'H' operand returns the higher of the two register numbers. On a run where WORDS_BIG_ENDIAN is true the 'H' operand is the same as the 'Q' operand, since the most significant part of the value is held in the lower number register. The reverse is true on systems where WORDS_BIG_ENDIAN is false. The purpose of these operands is to distinguish between cases where the endian-ness of the values is important (for example when they are added together), and cases where the endian-ness is irrelevant, but the order of register operations is important. For example when loading a value from memory into a register pair, the endian-ness does not matter. Provided that the value from the lower memory address is put into the lower numbered register, and the value from the higher address is put into the higher numbered register, the load will work regardless of whether the value being loaded is big-wordian or little-wordian. The order of the two register loads can matter however, if the address of the memory location is actually held in one of the registers being overwritten by the load. */ case 'Q': if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM) { output_operand_lossage ("invalid operand for code '%c'", code); return; } asm_fprintf (stream, "%r", REGNO (x) + (WORDS_BIG_ENDIAN ? 1 : 0)); return; case 'R': if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM) { output_operand_lossage ("invalid operand for code '%c'", code); return; } asm_fprintf (stream, "%r", REGNO (x) + (WORDS_BIG_ENDIAN ? 0 : 1)); return; case 'H': if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM) { output_operand_lossage ("invalid operand for code '%c'", code); return; } asm_fprintf (stream, "%r", REGNO (x) + 1); return; case 'm': asm_fprintf (stream, "%r", GET_CODE (XEXP (x, 0)) == REG ? REGNO (XEXP (x, 0)) : REGNO (XEXP (XEXP (x, 0), 0))); return; case 'M': asm_fprintf (stream, "{%r-%r}", REGNO (x), REGNO (x) + ARM_NUM_REGS (GET_MODE (x)) - 1); return; case 'd': /* CONST_TRUE_RTX means always -- that's the default. */ if (x == const_true_rtx) return; if (!COMPARISON_P (x)) { output_operand_lossage ("invalid operand for code '%c'", code); return; } fputs (arm_condition_codes[get_arm_condition_code (x)], stream); return; case 'D': /* CONST_TRUE_RTX means not always -- i.e. never. We shouldn't ever want to do that. */ if (x == const_true_rtx) { output_operand_lossage ("instruction never exectued"); return; } if (!COMPARISON_P (x)) { output_operand_lossage ("invalid operand for code '%c'", code); return; } fputs (arm_condition_codes[ARM_INVERSE_CONDITION_CODE (get_arm_condition_code (x))], stream); return; /* Cirrus registers can be accessed in a variety of ways: single floating point (f) double floating point (d) 32bit integer (fx) 64bit integer (dx). */ case 'W': /* Cirrus register in F mode. */ case 'X': /* Cirrus register in D mode. */ case 'Y': /* Cirrus register in FX mode. */ case 'Z': /* Cirrus register in DX mode. */ gcc_assert (GET_CODE (x) == REG && REGNO_REG_CLASS (REGNO (x)) == CIRRUS_REGS); fprintf (stream, "mv%s%s", code == 'W' ? "f" : code == 'X' ? "d" : code == 'Y' ? "fx" : "dx", reg_names[REGNO (x)] + 2); return; /* Print cirrus register in the mode specified by the register's mode. */ case 'V': { int mode = GET_MODE (x); if (GET_CODE (x) != REG || REGNO_REG_CLASS (REGNO (x)) != CIRRUS_REGS) { output_operand_lossage ("invalid operand for code '%c'", code); return; } fprintf (stream, "mv%s%s", mode == DFmode ? "d" : mode == SImode ? "fx" : mode == DImode ? "dx" : "f", reg_names[REGNO (x)] + 2); return; } case 'U': if (GET_CODE (x) != REG || REGNO (x) < FIRST_IWMMXT_GR_REGNUM || REGNO (x) > LAST_IWMMXT_GR_REGNUM) /* Bad value for wCG register number. */ { output_operand_lossage ("invalid operand for code '%c'", code); return; } else fprintf (stream, "%d", REGNO (x) - FIRST_IWMMXT_GR_REGNUM); return; /* Print an iWMMXt control register name. */ case 'w': if (GET_CODE (x) != CONST_INT || INTVAL (x) < 0 || INTVAL (x) >= 16) /* Bad value for wC register number. */ { output_operand_lossage ("invalid operand for code '%c'", code); return; } else { static const char * wc_reg_names [16] = { "wCID", "wCon", "wCSSF", "wCASF", "wC4", "wC5", "wC6", "wC7", "wCGR0", "wCGR1", "wCGR2", "wCGR3", "wC12", "wC13", "wC14", "wC15" }; fprintf (stream, wc_reg_names [INTVAL (x)]); } return; /* Print a VFP double precision register name. */ case 'P': { int mode = GET_MODE (x); int num; if (mode != DImode && mode != DFmode) { output_operand_lossage ("invalid operand for code '%c'", code); return; } if (GET_CODE (x) != REG || !IS_VFP_REGNUM (REGNO (x))) { output_operand_lossage ("invalid operand for code '%c'", code); return; } num = REGNO(x) - FIRST_VFP_REGNUM; if (num & 1) { output_operand_lossage ("invalid operand for code '%c'", code); return; } fprintf (stream, "d%d", num >> 1); } return; default: if (x == 0) { output_operand_lossage ("missing operand"); return; } switch (GET_CODE (x)) { case REG: asm_fprintf (stream, "%r", REGNO (x)); break; case MEM: output_memory_reference_mode = GET_MODE (x); output_address (XEXP (x, 0)); break; case CONST_DOUBLE: fprintf (stream, "#%s", fp_immediate_constant (x)); break; default: gcc_assert (GET_CODE (x) != NEG); fputc ('#', stream); output_addr_const (stream, x); break; } } } #ifndef AOF_ASSEMBLER /* Target hook for assembling integer objects. The ARM version needs to handle word-sized values specially. */ static bool arm_assemble_integer (rtx x, unsigned int size, int aligned_p) { if (size == UNITS_PER_WORD && aligned_p) { fputs ("\t.word\t", asm_out_file); output_addr_const (asm_out_file, x); /* Mark symbols as position independent. We only do this in the .text segment, not in the .data segment. */ if (NEED_GOT_RELOC && flag_pic && making_const_table && (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)) { if (GET_CODE (x) == SYMBOL_REF && (CONSTANT_POOL_ADDRESS_P (x) || SYMBOL_REF_LOCAL_P (x))) fputs ("(GOTOFF)", asm_out_file); else if (GET_CODE (x) == LABEL_REF) fputs ("(GOTOFF)", asm_out_file); else fputs ("(GOT)", asm_out_file); } fputc ('\n', asm_out_file); return true; } if (arm_vector_mode_supported_p (GET_MODE (x))) { int i, units; gcc_assert (GET_CODE (x) == CONST_VECTOR); units = CONST_VECTOR_NUNITS (x); switch (GET_MODE (x)) { case V2SImode: size = 4; break; case V4HImode: size = 2; break; case V8QImode: size = 1; break; default: gcc_unreachable (); } for (i = 0; i < units; i++) { rtx elt; elt = CONST_VECTOR_ELT (x, i); assemble_integer (elt, size, i == 0 ? BIGGEST_ALIGNMENT : size * BITS_PER_UNIT, 1); } return true; } return default_assemble_integer (x, size, aligned_p); } /* Add a function to the list of static constructors. */ static void arm_elf_asm_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED) { if (!TARGET_AAPCS_BASED) { default_named_section_asm_out_constructor (symbol, priority); return; } /* Put these in the .init_array section, using a special relocation. */ switch_to_section (ctors_section); assemble_align (POINTER_SIZE); fputs ("\t.word\t", asm_out_file); output_addr_const (asm_out_file, symbol); fputs ("(target1)\n", asm_out_file); } #endif /* A finite state machine takes care of noticing whether or not instructions can be conditionally executed, and thus decrease execution time and code size by deleting branch instructions. The fsm is controlled by final_prescan_insn, and controls the actions of ASM_OUTPUT_OPCODE. */ /* The state of the fsm controlling condition codes are: 0: normal, do nothing special 1: make ASM_OUTPUT_OPCODE not output this instruction 2: make ASM_OUTPUT_OPCODE not output this instruction 3: make instructions conditional 4: make instructions conditional State transitions (state->state by whom under condition): 0 -> 1 final_prescan_insn if the `target' is a label 0 -> 2 final_prescan_insn if the `target' is an unconditional branch 1 -> 3 ASM_OUTPUT_OPCODE after not having output the conditional branch 2 -> 4 ASM_OUTPUT_OPCODE after not having output the conditional branch 3 -> 0 (*targetm.asm_out.internal_label) if the `target' label is reached (the target label has CODE_LABEL_NUMBER equal to arm_target_label). 4 -> 0 final_prescan_insn if the `target' unconditional branch is reached (the target insn is arm_target_insn). If the jump clobbers the conditions then we use states 2 and 4. A similar thing can be done with conditional return insns. XXX In case the `target' is an unconditional branch, this conditionalising of the instructions always reduces code size, but not always execution time. But then, I want to reduce the code size to somewhere near what /bin/cc produces. */ /* Returns the index of the ARM condition code string in `arm_condition_codes'. COMPARISON should be an rtx like `(eq (...) (...))'. */ static enum arm_cond_code get_arm_condition_code (rtx comparison) { enum machine_mode mode = GET_MODE (XEXP (comparison, 0)); int code; enum rtx_code comp_code = GET_CODE (comparison); if (GET_MODE_CLASS (mode) != MODE_CC) mode = SELECT_CC_MODE (comp_code, XEXP (comparison, 0), XEXP (comparison, 1)); switch (mode) { case CC_DNEmode: code = ARM_NE; goto dominance; case CC_DEQmode: code = ARM_EQ; goto dominance; case CC_DGEmode: code = ARM_GE; goto dominance; case CC_DGTmode: code = ARM_GT; goto dominance; case CC_DLEmode: code = ARM_LE; goto dominance; case CC_DLTmode: code = ARM_LT; goto dominance; case CC_DGEUmode: code = ARM_CS; goto dominance; case CC_DGTUmode: code = ARM_HI; goto dominance; case CC_DLEUmode: code = ARM_LS; goto dominance; case CC_DLTUmode: code = ARM_CC; dominance: gcc_assert (comp_code == EQ || comp_code == NE); if (comp_code == EQ) return ARM_INVERSE_CONDITION_CODE (code); return code; case CC_NOOVmode: switch (comp_code) { case NE: return ARM_NE; case EQ: return ARM_EQ; case GE: return ARM_PL; case LT: return ARM_MI; default: gcc_unreachable (); } case CC_Zmode: switch (comp_code) { case NE: return ARM_NE; case EQ: return ARM_EQ; default: gcc_unreachable (); } case CC_Nmode: switch (comp_code) { case NE: return ARM_MI; case EQ: return ARM_PL; default: gcc_unreachable (); } case CCFPEmode: case CCFPmode: /* These encodings assume that AC=1 in the FPA system control byte. This allows us to handle all cases except UNEQ and LTGT. */ switch (comp_code) { case GE: return ARM_GE; case GT: return ARM_GT; case LE: return ARM_LS; case LT: return ARM_MI; case NE: return ARM_NE; case EQ: return ARM_EQ; case ORDERED: return ARM_VC; case UNORDERED: return ARM_VS; case UNLT: return ARM_LT; case UNLE: return ARM_LE; case UNGT: return ARM_HI; case UNGE: return ARM_PL; /* UNEQ and LTGT do not have a representation. */ case UNEQ: /* Fall through. */ case LTGT: /* Fall through. */ default: gcc_unreachable (); } case CC_SWPmode: switch (comp_code) { case NE: return ARM_NE; case EQ: return ARM_EQ; case GE: return ARM_LE; case GT: return ARM_LT; case LE: return ARM_GE; case LT: return ARM_GT; case GEU: return ARM_LS; case GTU: return ARM_CC; case LEU: return ARM_CS; case LTU: return ARM_HI; default: gcc_unreachable (); } case CC_Cmode: switch (comp_code) { case LTU: return ARM_CS; case GEU: return ARM_CC; default: gcc_unreachable (); } case CCmode: switch (comp_code) { case NE: return ARM_NE; case EQ: return ARM_EQ; case GE: return ARM_GE; case GT: return ARM_GT; case LE: return ARM_LE; case LT: return ARM_LT; case GEU: return ARM_CS; case GTU: return ARM_HI; case LEU: return ARM_LS; case LTU: return ARM_CC; default: gcc_unreachable (); } default: gcc_unreachable (); } } void arm_final_prescan_insn (rtx insn) { /* BODY will hold the body of INSN. */ rtx body = PATTERN (insn); /* This will be 1 if trying to repeat the trick, and things need to be reversed if it appears to fail. */ int reverse = 0; /* JUMP_CLOBBERS will be one implies that the conditions if a branch is taken are clobbered, even if the rtl suggests otherwise. It also means that we have to grub around within the jump expression to find out what the conditions are when the jump isn't taken. */ int jump_clobbers = 0; /* If we start with a return insn, we only succeed if we find another one. */ int seeking_return = 0; /* START_INSN will hold the insn from where we start looking. This is the first insn after the following code_label if REVERSE is true. */ rtx start_insn = insn; /* If in state 4, check if the target branch is reached, in order to change back to state 0. */ if (arm_ccfsm_state == 4) { if (insn == arm_target_insn) { arm_target_insn = NULL; arm_ccfsm_state = 0; } return; } /* If in state 3, it is possible to repeat the trick, if this insn is an unconditional branch to a label, and immediately following this branch is the previous target label which is only used once, and the label this branch jumps to is not too far off. */ if (arm_ccfsm_state == 3) { if (simplejump_p (insn)) { start_insn = next_nonnote_insn (start_insn); if (GET_CODE (start_insn) == BARRIER) { /* XXX Isn't this always a barrier? */ start_insn = next_nonnote_insn (start_insn); } if (GET_CODE (start_insn) == CODE_LABEL && CODE_LABEL_NUMBER (start_insn) == arm_target_label && LABEL_NUSES (start_insn) == 1) reverse = TRUE; else return; } else if (GET_CODE (body) == RETURN) { start_insn = next_nonnote_insn (start_insn); if (GET_CODE (start_insn) == BARRIER) start_insn = next_nonnote_insn (start_insn); if (GET_CODE (start_insn) == CODE_LABEL && CODE_LABEL_NUMBER (start_insn) == arm_target_label && LABEL_NUSES (start_insn) == 1) { reverse = TRUE; seeking_return = 1; } else return; } else return; } gcc_assert (!arm_ccfsm_state || reverse); if (GET_CODE (insn) != JUMP_INSN) return; /* This jump might be paralleled with a clobber of the condition codes the jump should always come first */ if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0) body = XVECEXP (body, 0, 0); if (reverse || (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE)) { int insns_skipped; int fail = FALSE, succeed = FALSE; /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */ int then_not_else = TRUE; rtx this_insn = start_insn, label = 0; /* If the jump cannot be done with one instruction, we cannot conditionally execute the instruction in the inverse case. */ if (get_attr_conds (insn) == CONDS_JUMP_CLOB) { jump_clobbers = 1; return; } /* Register the insn jumped to. */ if (reverse) { if (!seeking_return) label = XEXP (SET_SRC (body), 0); } else if (GET_CODE (XEXP (SET_SRC (body), 1)) == LABEL_REF) label = XEXP (XEXP (SET_SRC (body), 1), 0); else if (GET_CODE (XEXP (SET_SRC (body), 2)) == LABEL_REF) { label = XEXP (XEXP (SET_SRC (body), 2), 0); then_not_else = FALSE; } else if (GET_CODE (XEXP (SET_SRC (body), 1)) == RETURN) seeking_return = 1; else if (GET_CODE (XEXP (SET_SRC (body), 2)) == RETURN) { seeking_return = 1; then_not_else = FALSE; } else gcc_unreachable (); /* See how many insns this branch skips, and what kind of insns. If all insns are okay, and the label or unconditional branch to the same label is not too far away, succeed. */ for (insns_skipped = 0; !fail && !succeed && insns_skipped++ < max_insns_skipped;) { rtx scanbody; this_insn = next_nonnote_insn (this_insn); if (!this_insn) break; switch (GET_CODE (this_insn)) { case CODE_LABEL: /* Succeed if it is the target label, otherwise fail since control falls in from somewhere else. */ if (this_insn == label) { if (jump_clobbers) { arm_ccfsm_state = 2; this_insn = next_nonnote_insn (this_insn); } else arm_ccfsm_state = 1; succeed = TRUE; } else fail = TRUE; break; case BARRIER: /* Succeed if the following insn is the target label. Otherwise fail. If return insns are used then the last insn in a function will be a barrier. */ this_insn = next_nonnote_insn (this_insn); if (this_insn && this_insn == label) { if (jump_clobbers) { arm_ccfsm_state = 2; this_insn = next_nonnote_insn (this_insn); } else arm_ccfsm_state = 1; succeed = TRUE; } else fail = TRUE; break; case CALL_INSN: /* The AAPCS says that conditional calls should not be used since they make interworking inefficient (the linker can't transform BL into BLX). That's only a problem if the machine has BLX. */ if (arm_arch5) { fail = TRUE; break; } /* Succeed if the following insn is the target label, or if the following two insns are a barrier and the target label. */ this_insn = next_nonnote_insn (this_insn); if (this_insn && GET_CODE (this_insn) == BARRIER) this_insn = next_nonnote_insn (this_insn); if (this_insn && this_insn == label && insns_skipped < max_insns_skipped) { if (jump_clobbers) { arm_ccfsm_state = 2; this_insn = next_nonnote_insn (this_insn); } else arm_ccfsm_state = 1; succeed = TRUE; } else fail = TRUE; break; case JUMP_INSN: /* If this is an unconditional branch to the same label, succeed. If it is to another label, do nothing. If it is conditional, fail. */ /* XXX Probably, the tests for SET and the PC are unnecessary. */ scanbody = PATTERN (this_insn); if (GET_CODE (scanbody) == SET && GET_CODE (SET_DEST (scanbody)) == PC) { if (GET_CODE (SET_SRC (scanbody)) == LABEL_REF && XEXP (SET_SRC (scanbody), 0) == label && !reverse) { arm_ccfsm_state = 2; succeed = TRUE; } else if (GET_CODE (SET_SRC (scanbody)) == IF_THEN_ELSE) fail = TRUE; } /* Fail if a conditional return is undesirable (e.g. on a StrongARM), but still allow this if optimizing for size. */ else if (GET_CODE (scanbody) == RETURN && !use_return_insn (TRUE, NULL) && !optimize_size) fail = TRUE; else if (GET_CODE (scanbody) == RETURN && seeking_return) { arm_ccfsm_state = 2; succeed = TRUE; } else if (GET_CODE (scanbody) == PARALLEL) { switch (get_attr_conds (this_insn)) { case CONDS_NOCOND: break; default: fail = TRUE; break; } } else fail = TRUE; /* Unrecognized jump (e.g. epilogue). */ break; case INSN: /* Instructions using or affecting the condition codes make it fail. */ scanbody = PATTERN (this_insn); if (!(GET_CODE (scanbody) == SET || GET_CODE (scanbody) == PARALLEL) || get_attr_conds (this_insn) != CONDS_NOCOND) fail = TRUE; /* A conditional cirrus instruction must be followed by a non Cirrus instruction. However, since we conditionalize instructions in this function and by the time we get here we can't add instructions (nops), because shorten_branches() has already been called, we will disable conditionalizing Cirrus instructions to be safe. */ if (GET_CODE (scanbody) != USE && GET_CODE (scanbody) != CLOBBER && get_attr_cirrus (this_insn) != CIRRUS_NOT) fail = TRUE; break; default: break; } } if (succeed) { if ((!seeking_return) && (arm_ccfsm_state == 1 || reverse)) arm_target_label = CODE_LABEL_NUMBER (label); else { gcc_assert (seeking_return || arm_ccfsm_state == 2); while (this_insn && GET_CODE (PATTERN (this_insn)) == USE) { this_insn = next_nonnote_insn (this_insn); gcc_assert (!this_insn || (GET_CODE (this_insn) != BARRIER && GET_CODE (this_insn) != CODE_LABEL)); } if (!this_insn) { /* Oh, dear! we ran off the end.. give up. */ recog (PATTERN (insn), insn, NULL); arm_ccfsm_state = 0; arm_target_insn = NULL; return; } arm_target_insn = this_insn; } if (jump_clobbers) { gcc_assert (!reverse); arm_current_cc = get_arm_condition_code (XEXP (XEXP (XEXP (SET_SRC (body), 0), 0), 1)); if (GET_CODE (XEXP (XEXP (SET_SRC (body), 0), 0)) == AND) arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc); if (GET_CODE (XEXP (SET_SRC (body), 0)) == NE) arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc); } else { /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from what it was. */ if (!reverse) arm_current_cc = get_arm_condition_code (XEXP (SET_SRC (body), 0)); } if (reverse || then_not_else) arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc); } /* Restore recog_data (getting the attributes of other insns can destroy this array, but final.c assumes that it remains intact across this call; since the insn has been recognized already we call recog direct). */ recog (PATTERN (insn), insn, NULL); } } /* Returns true if REGNO is a valid register for holding a quantity of type MODE. */ int arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode) { if (GET_MODE_CLASS (mode) == MODE_CC) return (regno == CC_REGNUM || (TARGET_HARD_FLOAT && TARGET_VFP && regno == VFPCC_REGNUM)); if (TARGET_THUMB) /* For the Thumb we only allow values bigger than SImode in registers 0 - 6, so that there is always a second low register available to hold the upper part of the value. We probably we ought to ensure that the register is the start of an even numbered register pair. */ return (ARM_NUM_REGS (mode) < 2) || (regno < LAST_LO_REGNUM); if (TARGET_HARD_FLOAT && TARGET_MAVERICK && IS_CIRRUS_REGNUM (regno)) /* We have outlawed SI values in Cirrus registers because they reside in the lower 32 bits, but SF values reside in the upper 32 bits. This causes gcc all sorts of grief. We can't even split the registers into pairs because Cirrus SI values get sign extended to 64bits-- aldyh. */ return (GET_MODE_CLASS (mode) == MODE_FLOAT) || (mode == DImode); if (TARGET_HARD_FLOAT && TARGET_VFP && IS_VFP_REGNUM (regno)) { if (mode == SFmode || mode == SImode) return TRUE; /* DFmode values are only valid in even register pairs. */ if (mode == DFmode) return ((regno - FIRST_VFP_REGNUM) & 1) == 0; return FALSE; } if (TARGET_REALLY_IWMMXT) { if (IS_IWMMXT_GR_REGNUM (regno)) return mode == SImode; if (IS_IWMMXT_REGNUM (regno)) return VALID_IWMMXT_REG_MODE (mode); } /* We allow any value to be stored in the general registers. Restrict doubleword quantities to even register pairs so that we can use ldrd. */ if (regno <= LAST_ARM_REGNUM) return !(TARGET_LDRD && GET_MODE_SIZE (mode) > 4 && (regno & 1) != 0); if (regno == FRAME_POINTER_REGNUM || regno == ARG_POINTER_REGNUM) /* We only allow integers in the fake hard registers. */ return GET_MODE_CLASS (mode) == MODE_INT; /* The only registers left are the FPA registers which we only allow to hold FP values. */ return (TARGET_HARD_FLOAT && TARGET_FPA && GET_MODE_CLASS (mode) == MODE_FLOAT && regno >= FIRST_FPA_REGNUM && regno <= LAST_FPA_REGNUM); } int arm_regno_class (int regno) { if (TARGET_THUMB) { if (regno == STACK_POINTER_REGNUM) return STACK_REG; if (regno == CC_REGNUM) return CC_REG; if (regno < 8) return LO_REGS; return HI_REGS; } if ( regno <= LAST_ARM_REGNUM || regno == FRAME_POINTER_REGNUM || regno == ARG_POINTER_REGNUM) return GENERAL_REGS; if (regno == CC_REGNUM || regno == VFPCC_REGNUM) return NO_REGS; if (IS_CIRRUS_REGNUM (regno)) return CIRRUS_REGS; if (IS_VFP_REGNUM (regno)) return VFP_REGS; if (IS_IWMMXT_REGNUM (regno)) return IWMMXT_REGS; if (IS_IWMMXT_GR_REGNUM (regno)) return IWMMXT_GR_REGS; return FPA_REGS; } /* Handle a special case when computing the offset of an argument from the frame pointer. */ int arm_debugger_arg_offset (int value, rtx addr) { rtx insn; /* We are only interested if dbxout_parms() failed to compute the offset. */ if (value != 0) return 0; /* We can only cope with the case where the address is held in a register. */ if (GET_CODE (addr) != REG) return 0; /* If we are using the frame pointer to point at the argument, then an offset of 0 is correct. */ if (REGNO (addr) == (unsigned) HARD_FRAME_POINTER_REGNUM) return 0; /* If we are using the stack pointer to point at the argument, then an offset of 0 is correct. */ if ((TARGET_THUMB || !frame_pointer_needed) && REGNO (addr) == SP_REGNUM) return 0; /* Oh dear. The argument is pointed to by a register rather than being held in a register, or being stored at a known offset from the frame pointer. Since GDB only understands those two kinds of argument we must translate the address held in the register into an offset from the frame pointer. We do this by searching through the insns for the function looking to see where this register gets its value. If the register is initialized from the frame pointer plus an offset then we are in luck and we can continue, otherwise we give up. This code is exercised by producing debugging information for a function with arguments like this: double func (double a, double b, int c, double d) {return d;} Without this code the stab for parameter 'd' will be set to an offset of 0 from the frame pointer, rather than 8. */ /* The if() statement says: If the insn is a normal instruction and if the insn is setting the value in a register and if the register being set is the register holding the address of the argument and if the address is computing by an addition that involves adding to a register which is the frame pointer a constant integer then... */ for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) { if ( GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET && REGNO (XEXP (PATTERN (insn), 0)) == REGNO (addr) && GET_CODE (XEXP (PATTERN (insn), 1)) == PLUS && GET_CODE (XEXP (XEXP (PATTERN (insn), 1), 0)) == REG && REGNO (XEXP (XEXP (PATTERN (insn), 1), 0)) == (unsigned) HARD_FRAME_POINTER_REGNUM && GET_CODE (XEXP (XEXP (PATTERN (insn), 1), 1)) == CONST_INT ) { value = INTVAL (XEXP (XEXP (PATTERN (insn), 1), 1)); break; } } if (value == 0) { debug_rtx (addr); warning (0, "unable to compute real location of stacked parameter"); value = 8; /* XXX magic hack */ } return value; } #define def_mbuiltin(MASK, NAME, TYPE, CODE) \ do \ { \ if ((MASK) & insn_flags) \ lang_hooks.builtin_function ((NAME), (TYPE), (CODE), \ BUILT_IN_MD, NULL, NULL_TREE); \ } \ while (0) struct builtin_description { const unsigned int mask; const enum insn_code icode; const char * const name; const enum arm_builtins code; const enum rtx_code comparison; const unsigned int flag; }; static const struct builtin_description bdesc_2arg[] = { #define IWMMXT_BUILTIN(code, string, builtin) \ { FL_IWMMXT, CODE_FOR_##code, "__builtin_arm_" string, \ ARM_BUILTIN_##builtin, 0, 0 }, IWMMXT_BUILTIN (addv8qi3, "waddb", WADDB) IWMMXT_BUILTIN (addv4hi3, "waddh", WADDH) IWMMXT_BUILTIN (addv2si3, "waddw", WADDW) IWMMXT_BUILTIN (subv8qi3, "wsubb", WSUBB) IWMMXT_BUILTIN (subv4hi3, "wsubh", WSUBH) IWMMXT_BUILTIN (subv2si3, "wsubw", WSUBW) IWMMXT_BUILTIN (ssaddv8qi3, "waddbss", WADDSSB) IWMMXT_BUILTIN (ssaddv4hi3, "waddhss", WADDSSH) IWMMXT_BUILTIN (ssaddv2si3, "waddwss", WADDSSW) IWMMXT_BUILTIN (sssubv8qi3, "wsubbss", WSUBSSB) IWMMXT_BUILTIN (sssubv4hi3, "wsubhss", WSUBSSH) IWMMXT_BUILTIN (sssubv2si3, "wsubwss", WSUBSSW) IWMMXT_BUILTIN (usaddv8qi3, "waddbus", WADDUSB) IWMMXT_BUILTIN (usaddv4hi3, "waddhus", WADDUSH) IWMMXT_BUILTIN (usaddv2si3, "waddwus", WADDUSW) IWMMXT_BUILTIN (ussubv8qi3, "wsubbus", WSUBUSB) IWMMXT_BUILTIN (ussubv4hi3, "wsubhus", WSUBUSH) IWMMXT_BUILTIN (ussubv2si3, "wsubwus", WSUBUSW) IWMMXT_BUILTIN (mulv4hi3, "wmulul", WMULUL) IWMMXT_BUILTIN (smulv4hi3_highpart, "wmulsm", WMULSM) IWMMXT_BUILTIN (umulv4hi3_highpart, "wmulum", WMULUM) IWMMXT_BUILTIN (eqv8qi3, "wcmpeqb", WCMPEQB) IWMMXT_BUILTIN (eqv4hi3, "wcmpeqh", WCMPEQH) IWMMXT_BUILTIN (eqv2si3, "wcmpeqw", WCMPEQW) IWMMXT_BUILTIN (gtuv8qi3, "wcmpgtub", WCMPGTUB) IWMMXT_BUILTIN (gtuv4hi3, "wcmpgtuh", WCMPGTUH) IWMMXT_BUILTIN (gtuv2si3, "wcmpgtuw", WCMPGTUW) IWMMXT_BUILTIN (gtv8qi3, "wcmpgtsb", WCMPGTSB) IWMMXT_BUILTIN (gtv4hi3, "wcmpgtsh", WCMPGTSH) IWMMXT_BUILTIN (gtv2si3, "wcmpgtsw", WCMPGTSW) IWMMXT_BUILTIN (umaxv8qi3, "wmaxub", WMAXUB) IWMMXT_BUILTIN (smaxv8qi3, "wmaxsb", WMAXSB) IWMMXT_BUILTIN (umaxv4hi3, "wmaxuh", WMAXUH) IWMMXT_BUILTIN (smaxv4hi3, "wmaxsh", WMAXSH) IWMMXT_BUILTIN (umaxv2si3, "wmaxuw", WMAXUW) IWMMXT_BUILTIN (smaxv2si3, "wmaxsw", WMAXSW) IWMMXT_BUILTIN (uminv8qi3, "wminub", WMINUB) IWMMXT_BUILTIN (sminv8qi3, "wminsb", WMINSB) IWMMXT_BUILTIN (uminv4hi3, "wminuh", WMINUH) IWMMXT_BUILTIN (sminv4hi3, "wminsh", WMINSH) IWMMXT_BUILTIN (uminv2si3, "wminuw", WMINUW) IWMMXT_BUILTIN (sminv2si3, "wminsw", WMINSW) IWMMXT_BUILTIN (iwmmxt_anddi3, "wand", WAND) IWMMXT_BUILTIN (iwmmxt_nanddi3, "wandn", WANDN) IWMMXT_BUILTIN (iwmmxt_iordi3, "wor", WOR) IWMMXT_BUILTIN (iwmmxt_xordi3, "wxor", WXOR) IWMMXT_BUILTIN (iwmmxt_uavgv8qi3, "wavg2b", WAVG2B) IWMMXT_BUILTIN (iwmmxt_uavgv4hi3, "wavg2h", WAVG2H) IWMMXT_BUILTIN (iwmmxt_uavgrndv8qi3, "wavg2br", WAVG2BR) IWMMXT_BUILTIN (iwmmxt_uavgrndv4hi3, "wavg2hr", WAVG2HR) IWMMXT_BUILTIN (iwmmxt_wunpckilb, "wunpckilb", WUNPCKILB) IWMMXT_BUILTIN (iwmmxt_wunpckilh, "wunpckilh", WUNPCKILH) IWMMXT_BUILTIN (iwmmxt_wunpckilw, "wunpckilw", WUNPCKILW) IWMMXT_BUILTIN (iwmmxt_wunpckihb, "wunpckihb", WUNPCKIHB) IWMMXT_BUILTIN (iwmmxt_wunpckihh, "wunpckihh", WUNPCKIHH) IWMMXT_BUILTIN (iwmmxt_wunpckihw, "wunpckihw", WUNPCKIHW) IWMMXT_BUILTIN (iwmmxt_wmadds, "wmadds", WMADDS) IWMMXT_BUILTIN (iwmmxt_wmaddu, "wmaddu", WMADDU) #define IWMMXT_BUILTIN2(code, builtin) \ { FL_IWMMXT, CODE_FOR_##code, NULL, ARM_BUILTIN_##builtin, 0, 0 }, IWMMXT_BUILTIN2 (iwmmxt_wpackhss, WPACKHSS) IWMMXT_BUILTIN2 (iwmmxt_wpackwss, WPACKWSS) IWMMXT_BUILTIN2 (iwmmxt_wpackdss, WPACKDSS) IWMMXT_BUILTIN2 (iwmmxt_wpackhus, WPACKHUS) IWMMXT_BUILTIN2 (iwmmxt_wpackwus, WPACKWUS) IWMMXT_BUILTIN2 (iwmmxt_wpackdus, WPACKDUS) IWMMXT_BUILTIN2 (ashlv4hi3_di, WSLLH) IWMMXT_BUILTIN2 (ashlv4hi3, WSLLHI) IWMMXT_BUILTIN2 (ashlv2si3_di, WSLLW) IWMMXT_BUILTIN2 (ashlv2si3, WSLLWI) IWMMXT_BUILTIN2 (ashldi3_di, WSLLD) IWMMXT_BUILTIN2 (ashldi3_iwmmxt, WSLLDI) IWMMXT_BUILTIN2 (lshrv4hi3_di, WSRLH) IWMMXT_BUILTIN2 (lshrv4hi3, WSRLHI) IWMMXT_BUILTIN2 (lshrv2si3_di, WSRLW) IWMMXT_BUILTIN2 (lshrv2si3, WSRLWI) IWMMXT_BUILTIN2 (lshrdi3_di, WSRLD) IWMMXT_BUILTIN2 (lshrdi3_iwmmxt, WSRLDI) IWMMXT_BUILTIN2 (ashrv4hi3_di, WSRAH) IWMMXT_BUILTIN2 (ashrv4hi3, WSRAHI) IWMMXT_BUILTIN2 (ashrv2si3_di, WSRAW) IWMMXT_BUILTIN2 (ashrv2si3, WSRAWI) IWMMXT_BUILTIN2 (ashrdi3_di, WSRAD) IWMMXT_BUILTIN2 (ashrdi3_iwmmxt, WSRADI) IWMMXT_BUILTIN2 (rorv4hi3_di, WRORH) IWMMXT_BUILTIN2 (rorv4hi3, WRORHI) IWMMXT_BUILTIN2 (rorv2si3_di, WRORW) IWMMXT_BUILTIN2 (rorv2si3, WRORWI) IWMMXT_BUILTIN2 (rordi3_di, WRORD) IWMMXT_BUILTIN2 (rordi3, WRORDI) IWMMXT_BUILTIN2 (iwmmxt_wmacuz, WMACUZ) IWMMXT_BUILTIN2 (iwmmxt_wmacsz, WMACSZ) }; static const struct builtin_description bdesc_1arg[] = { IWMMXT_BUILTIN (iwmmxt_tmovmskb, "tmovmskb", TMOVMSKB) IWMMXT_BUILTIN (iwmmxt_tmovmskh, "tmovmskh", TMOVMSKH) IWMMXT_BUILTIN (iwmmxt_tmovmskw, "tmovmskw", TMOVMSKW) IWMMXT_BUILTIN (iwmmxt_waccb, "waccb", WACCB) IWMMXT_BUILTIN (iwmmxt_wacch, "wacch", WACCH) IWMMXT_BUILTIN (iwmmxt_waccw, "waccw", WACCW) IWMMXT_BUILTIN (iwmmxt_wunpckehub, "wunpckehub", WUNPCKEHUB) IWMMXT_BUILTIN (iwmmxt_wunpckehuh, "wunpckehuh", WUNPCKEHUH) IWMMXT_BUILTIN (iwmmxt_wunpckehuw, "wunpckehuw", WUNPCKEHUW) IWMMXT_BUILTIN (iwmmxt_wunpckehsb, "wunpckehsb", WUNPCKEHSB) IWMMXT_BUILTIN (iwmmxt_wunpckehsh, "wunpckehsh", WUNPCKEHSH) IWMMXT_BUILTIN (iwmmxt_wunpckehsw, "wunpckehsw", WUNPCKEHSW) IWMMXT_BUILTIN (iwmmxt_wunpckelub, "wunpckelub", WUNPCKELUB) IWMMXT_BUILTIN (iwmmxt_wunpckeluh, "wunpckeluh", WUNPCKELUH) IWMMXT_BUILTIN (iwmmxt_wunpckeluw, "wunpckeluw", WUNPCKELUW) IWMMXT_BUILTIN (iwmmxt_wunpckelsb, "wunpckelsb", WUNPCKELSB) IWMMXT_BUILTIN (iwmmxt_wunpckelsh, "wunpckelsh", WUNPCKELSH) IWMMXT_BUILTIN (iwmmxt_wunpckelsw, "wunpckelsw", WUNPCKELSW) }; /* Set up all the iWMMXt builtins. This is not called if TARGET_IWMMXT is zero. */ static void arm_init_iwmmxt_builtins (void) { const struct builtin_description * d; size_t i; tree endlink = void_list_node; tree V2SI_type_node = build_vector_type_for_mode (intSI_type_node, V2SImode); tree V4HI_type_node = build_vector_type_for_mode (intHI_type_node, V4HImode); tree V8QI_type_node = build_vector_type_for_mode (intQI_type_node, V8QImode); tree int_ftype_int = build_function_type (integer_type_node, tree_cons (NULL_TREE, integer_type_node, endlink)); tree v8qi_ftype_v8qi_v8qi_int = build_function_type (V8QI_type_node, tree_cons (NULL_TREE, V8QI_type_node, tree_cons (NULL_TREE, V8QI_type_node, tree_cons (NULL_TREE, integer_type_node, endlink)))); tree v4hi_ftype_v4hi_int = build_function_type (V4HI_type_node, tree_cons (NULL_TREE, V4HI_type_node, tree_cons (NULL_TREE, integer_type_node, endlink))); tree v2si_ftype_v2si_int = build_function_type (V2SI_type_node, tree_cons (NULL_TREE, V2SI_type_node, tree_cons (NULL_TREE, integer_type_node, endlink))); tree v2si_ftype_di_di = build_function_type (V2SI_type_node, tree_cons (NULL_TREE, long_long_integer_type_node, tree_cons (NULL_TREE, long_long_integer_type_node, endlink))); tree di_ftype_di_int = build_function_type (long_long_integer_type_node, tree_cons (NULL_TREE, long_long_integer_type_node, tree_cons (NULL_TREE, integer_type_node, endlink))); tree di_ftype_di_int_int = build_function_type (long_long_integer_type_node, tree_cons (NULL_TREE, long_long_integer_type_node, tree_cons (NULL_TREE, integer_type_node, tree_cons (NULL_TREE, integer_type_node, endlink)))); tree int_ftype_v8qi = build_function_type (integer_type_node, tree_cons (NULL_TREE, V8QI_type_node, endlink)); tree int_ftype_v4hi = build_function_type (integer_type_node, tree_cons (NULL_TREE, V4HI_type_node, endlink)); tree int_ftype_v2si = build_function_type (integer_type_node, tree_cons (NULL_TREE, V2SI_type_node, endlink)); tree int_ftype_v8qi_int = build_function_type (integer_type_node, tree_cons (NULL_TREE, V8QI_type_node, tree_cons (NULL_TREE, integer_type_node, endlink))); tree int_ftype_v4hi_int = build_function_type (integer_type_node, tree_cons (NULL_TREE, V4HI_type_node, tree_cons (NULL_TREE, integer_type_node, endlink))); tree int_ftype_v2si_int = build_function_type (integer_type_node, tree_cons (NULL_TREE, V2SI_type_node, tree_cons (NULL_TREE, integer_type_node, endlink))); tree v8qi_ftype_v8qi_int_int = build_function_type (V8QI_type_node, tree_cons (NULL_TREE, V8QI_type_node, tree_cons (NULL_TREE, integer_type_node, tree_cons (NULL_TREE, integer_type_node, endlink)))); tree v4hi_ftype_v4hi_int_int = build_function_type (V4HI_type_node, tree_cons (NULL_TREE, V4HI_type_node, tree_cons (NULL_TREE, integer_type_node, tree_cons (NULL_TREE, integer_type_node, endlink)))); tree v2si_ftype_v2si_int_int = build_function_type (V2SI_type_node, tree_cons (NULL_TREE, V2SI_type_node, tree_cons (NULL_TREE, integer_type_node, tree_cons (NULL_TREE, integer_type_node, endlink)))); /* Miscellaneous. */ tree v8qi_ftype_v4hi_v4hi = build_function_type (V8QI_type_node, tree_cons (NULL_TREE, V4HI_type_node, tree_cons (NULL_TREE, V4HI_type_node, endlink))); tree v4hi_ftype_v2si_v2si = build_function_type (V4HI_type_node, tree_cons (NULL_TREE, V2SI_type_node, tree_cons (NULL_TREE, V2SI_type_node, endlink))); tree v2si_ftype_v4hi_v4hi = build_function_type (V2SI_type_node, tree_cons (NULL_TREE, V4HI_type_node, tree_cons (NULL_TREE, V4HI_type_node, endlink))); tree v2si_ftype_v8qi_v8qi = build_function_type (V2SI_type_node, tree_cons (NULL_TREE, V8QI_type_node, tree_cons (NULL_TREE, V8QI_type_node, endlink))); tree v4hi_ftype_v4hi_di = build_function_type (V4HI_type_node, tree_cons (NULL_TREE, V4HI_type_node, tree_cons (NULL_TREE, long_long_integer_type_node, endlink))); tree v2si_ftype_v2si_di = build_function_type (V2SI_type_node, tree_cons (NULL_TREE, V2SI_type_node, tree_cons (NULL_TREE, long_long_integer_type_node, endlink))); tree void_ftype_int_int = build_function_type (void_type_node, tree_cons (NULL_TREE, integer_type_node, tree_cons (NULL_TREE, integer_type_node, endlink))); tree di_ftype_void = build_function_type (long_long_unsigned_type_node, endlink); tree di_ftype_v8qi = build_function_type (long_long_integer_type_node, tree_cons (NULL_TREE, V8QI_type_node, endlink)); tree di_ftype_v4hi = build_function_type (long_long_integer_type_node, tree_cons (NULL_TREE, V4HI_type_node, endlink)); tree di_ftype_v2si = build_function_type (long_long_integer_type_node, tree_cons (NULL_TREE, V2SI_type_node, endlink)); tree v2si_ftype_v4hi = build_function_type (V2SI_type_node, tree_cons (NULL_TREE, V4HI_type_node, endlink)); tree v4hi_ftype_v8qi = build_function_type (V4HI_type_node, tree_cons (NULL_TREE, V8QI_type_node, endlink)); tree di_ftype_di_v4hi_v4hi = build_function_type (long_long_unsigned_type_node, tree_cons (NULL_TREE, long_long_unsigned_type_node, tree_cons (NULL_TREE, V4HI_type_node, tree_cons (NULL_TREE, V4HI_type_node, endlink)))); tree di_ftype_v4hi_v4hi = build_function_type (long_long_unsigned_type_node, tree_cons (NULL_TREE, V4HI_type_node, tree_cons (NULL_TREE, V4HI_type_node, endlink))); /* Normal vector binops. */ tree v8qi_ftype_v8qi_v8qi = build_function_type (V8QI_type_node, tree_cons (NULL_TREE, V8QI_type_node, tree_cons (NULL_TREE, V8QI_type_node, endlink))); tree v4hi_ftype_v4hi_v4hi = build_function_type (V4HI_type_node, tree_cons (NULL_TREE, V4HI_type_node, tree_cons (NULL_TREE, V4HI_type_node, endlink))); tree v2si_ftype_v2si_v2si = build_function_type (V2SI_type_node, tree_cons (NULL_TREE, V2SI_type_node, tree_cons (NULL_TREE, V2SI_type_node, endlink))); tree di_ftype_di_di = build_function_type (long_long_unsigned_type_node, tree_cons (NULL_TREE, long_long_unsigned_type_node, tree_cons (NULL_TREE, long_long_unsigned_type_node, endlink))); /* Add all builtins that are more or less simple operations on two operands. */ for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++) { /* Use one of the operands; the target can have a different mode for mask-generating compares. */ enum machine_mode mode; tree type; if (d->name == 0) continue; mode = insn_data[d->icode].operand[1].mode; switch (mode) { case V8QImode: type = v8qi_ftype_v8qi_v8qi; break; case V4HImode: type = v4hi_ftype_v4hi_v4hi; break; case V2SImode: type = v2si_ftype_v2si_v2si; break; case DImode: type = di_ftype_di_di; break; default: gcc_unreachable (); } def_mbuiltin (d->mask, d->name, type, d->code); } /* Add the remaining MMX insns with somewhat more complicated types. */ def_mbuiltin (FL_IWMMXT, "__builtin_arm_wzero", di_ftype_void, ARM_BUILTIN_WZERO); def_mbuiltin (FL_IWMMXT, "__builtin_arm_setwcx", void_ftype_int_int, ARM_BUILTIN_SETWCX); def_mbuiltin (FL_IWMMXT, "__builtin_arm_getwcx", int_ftype_int, ARM_BUILTIN_GETWCX); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsllh", v4hi_ftype_v4hi_di, ARM_BUILTIN_WSLLH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsllw", v2si_ftype_v2si_di, ARM_BUILTIN_WSLLW); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wslld", di_ftype_di_di, ARM_BUILTIN_WSLLD); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsllhi", v4hi_ftype_v4hi_int, ARM_BUILTIN_WSLLHI); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsllwi", v2si_ftype_v2si_int, ARM_BUILTIN_WSLLWI); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wslldi", di_ftype_di_int, ARM_BUILTIN_WSLLDI); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrlh", v4hi_ftype_v4hi_di, ARM_BUILTIN_WSRLH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrlw", v2si_ftype_v2si_di, ARM_BUILTIN_WSRLW); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrld", di_ftype_di_di, ARM_BUILTIN_WSRLD); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrlhi", v4hi_ftype_v4hi_int, ARM_BUILTIN_WSRLHI); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrlwi", v2si_ftype_v2si_int, ARM_BUILTIN_WSRLWI); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrldi", di_ftype_di_int, ARM_BUILTIN_WSRLDI); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrah", v4hi_ftype_v4hi_di, ARM_BUILTIN_WSRAH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsraw", v2si_ftype_v2si_di, ARM_BUILTIN_WSRAW); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrad", di_ftype_di_di, ARM_BUILTIN_WSRAD); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrahi", v4hi_ftype_v4hi_int, ARM_BUILTIN_WSRAHI); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsrawi", v2si_ftype_v2si_int, ARM_BUILTIN_WSRAWI); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsradi", di_ftype_di_int, ARM_BUILTIN_WSRADI); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wrorh", v4hi_ftype_v4hi_di, ARM_BUILTIN_WRORH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wrorw", v2si_ftype_v2si_di, ARM_BUILTIN_WRORW); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wrord", di_ftype_di_di, ARM_BUILTIN_WRORD); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wrorhi", v4hi_ftype_v4hi_int, ARM_BUILTIN_WRORHI); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wrorwi", v2si_ftype_v2si_int, ARM_BUILTIN_WRORWI); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wrordi", di_ftype_di_int, ARM_BUILTIN_WRORDI); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wshufh", v4hi_ftype_v4hi_int, ARM_BUILTIN_WSHUFH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsadb", v2si_ftype_v8qi_v8qi, ARM_BUILTIN_WSADB); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsadh", v2si_ftype_v4hi_v4hi, ARM_BUILTIN_WSADH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsadbz", v2si_ftype_v8qi_v8qi, ARM_BUILTIN_WSADBZ); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wsadhz", v2si_ftype_v4hi_v4hi, ARM_BUILTIN_WSADHZ); def_mbuiltin (FL_IWMMXT, "__builtin_arm_textrmsb", int_ftype_v8qi_int, ARM_BUILTIN_TEXTRMSB); def_mbuiltin (FL_IWMMXT, "__builtin_arm_textrmsh", int_ftype_v4hi_int, ARM_BUILTIN_TEXTRMSH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_textrmsw", int_ftype_v2si_int, ARM_BUILTIN_TEXTRMSW); def_mbuiltin (FL_IWMMXT, "__builtin_arm_textrmub", int_ftype_v8qi_int, ARM_BUILTIN_TEXTRMUB); def_mbuiltin (FL_IWMMXT, "__builtin_arm_textrmuh", int_ftype_v4hi_int, ARM_BUILTIN_TEXTRMUH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_textrmuw", int_ftype_v2si_int, ARM_BUILTIN_TEXTRMUW); def_mbuiltin (FL_IWMMXT, "__builtin_arm_tinsrb", v8qi_ftype_v8qi_int_int, ARM_BUILTIN_TINSRB); def_mbuiltin (FL_IWMMXT, "__builtin_arm_tinsrh", v4hi_ftype_v4hi_int_int, ARM_BUILTIN_TINSRH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_tinsrw", v2si_ftype_v2si_int_int, ARM_BUILTIN_TINSRW); def_mbuiltin (FL_IWMMXT, "__builtin_arm_waccb", di_ftype_v8qi, ARM_BUILTIN_WACCB); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wacch", di_ftype_v4hi, ARM_BUILTIN_WACCH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_waccw", di_ftype_v2si, ARM_BUILTIN_WACCW); def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmovmskb", int_ftype_v8qi, ARM_BUILTIN_TMOVMSKB); def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmovmskh", int_ftype_v4hi, ARM_BUILTIN_TMOVMSKH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmovmskw", int_ftype_v2si, ARM_BUILTIN_TMOVMSKW); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wpackhss", v8qi_ftype_v4hi_v4hi, ARM_BUILTIN_WPACKHSS); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wpackhus", v8qi_ftype_v4hi_v4hi, ARM_BUILTIN_WPACKHUS); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wpackwus", v4hi_ftype_v2si_v2si, ARM_BUILTIN_WPACKWUS); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wpackwss", v4hi_ftype_v2si_v2si, ARM_BUILTIN_WPACKWSS); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wpackdus", v2si_ftype_di_di, ARM_BUILTIN_WPACKDUS); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wpackdss", v2si_ftype_di_di, ARM_BUILTIN_WPACKDSS); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckehub", v4hi_ftype_v8qi, ARM_BUILTIN_WUNPCKEHUB); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckehuh", v2si_ftype_v4hi, ARM_BUILTIN_WUNPCKEHUH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckehuw", di_ftype_v2si, ARM_BUILTIN_WUNPCKEHUW); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckehsb", v4hi_ftype_v8qi, ARM_BUILTIN_WUNPCKEHSB); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckehsh", v2si_ftype_v4hi, ARM_BUILTIN_WUNPCKEHSH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckehsw", di_ftype_v2si, ARM_BUILTIN_WUNPCKEHSW); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckelub", v4hi_ftype_v8qi, ARM_BUILTIN_WUNPCKELUB); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckeluh", v2si_ftype_v4hi, ARM_BUILTIN_WUNPCKELUH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckeluw", di_ftype_v2si, ARM_BUILTIN_WUNPCKELUW); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckelsb", v4hi_ftype_v8qi, ARM_BUILTIN_WUNPCKELSB); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckelsh", v2si_ftype_v4hi, ARM_BUILTIN_WUNPCKELSH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wunpckelsw", di_ftype_v2si, ARM_BUILTIN_WUNPCKELSW); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wmacs", di_ftype_di_v4hi_v4hi, ARM_BUILTIN_WMACS); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wmacsz", di_ftype_v4hi_v4hi, ARM_BUILTIN_WMACSZ); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wmacu", di_ftype_di_v4hi_v4hi, ARM_BUILTIN_WMACU); def_mbuiltin (FL_IWMMXT, "__builtin_arm_wmacuz", di_ftype_v4hi_v4hi, ARM_BUILTIN_WMACUZ); def_mbuiltin (FL_IWMMXT, "__builtin_arm_walign", v8qi_ftype_v8qi_v8qi_int, ARM_BUILTIN_WALIGN); def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmia", di_ftype_di_int_int, ARM_BUILTIN_TMIA); def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmiaph", di_ftype_di_int_int, ARM_BUILTIN_TMIAPH); def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmiabb", di_ftype_di_int_int, ARM_BUILTIN_TMIABB); def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmiabt", di_ftype_di_int_int, ARM_BUILTIN_TMIABT); def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmiatb", di_ftype_di_int_int, ARM_BUILTIN_TMIATB); def_mbuiltin (FL_IWMMXT, "__builtin_arm_tmiatt", di_ftype_di_int_int, ARM_BUILTIN_TMIATT); } static void arm_init_tls_builtins (void) { tree ftype; tree nothrow = tree_cons (get_identifier ("nothrow"), NULL, NULL); tree const_nothrow = tree_cons (get_identifier ("const"), NULL, nothrow); ftype = build_function_type (ptr_type_node, void_list_node); lang_hooks.builtin_function ("__builtin_thread_pointer", ftype, ARM_BUILTIN_THREAD_POINTER, BUILT_IN_MD, NULL, const_nothrow); } static void arm_init_builtins (void) { arm_init_tls_builtins (); if (TARGET_REALLY_IWMMXT) arm_init_iwmmxt_builtins (); } /* Errors in the source file can cause expand_expr to return const0_rtx where we expect a vector. To avoid crashing, use one of the vector clear instructions. */ static rtx safe_vector_operand (rtx x, enum machine_mode mode) { if (x != const0_rtx) return x; x = gen_reg_rtx (mode); emit_insn (gen_iwmmxt_clrdi (mode == DImode ? x : gen_rtx_SUBREG (DImode, x, 0))); return x; } /* Subroutine of arm_expand_builtin to take care of binop insns. */ static rtx arm_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target) { rtx pat; tree arg0 = TREE_VALUE (arglist); tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); rtx op0 = expand_normal (arg0); rtx op1 = expand_normal (arg1); enum machine_mode tmode = insn_data[icode].operand[0].mode; enum machine_mode mode0 = insn_data[icode].operand[1].mode; enum machine_mode mode1 = insn_data[icode].operand[2].mode; if (VECTOR_MODE_P (mode0)) op0 = safe_vector_operand (op0, mode0); if (VECTOR_MODE_P (mode1)) op1 = safe_vector_operand (op1, mode1); if (! target || GET_MODE (target) != tmode || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) target = gen_reg_rtx (tmode); gcc_assert (GET_MODE (op0) == mode0 && GET_MODE (op1) == mode1); if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) op0 = copy_to_mode_reg (mode0, op0); if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) op1 = copy_to_mode_reg (mode1, op1); pat = GEN_FCN (icode) (target, op0, op1); if (! pat) return 0; emit_insn (pat); return target; } /* Subroutine of arm_expand_builtin to take care of unop insns. */ static rtx arm_expand_unop_builtin (enum insn_code icode, tree arglist, rtx target, int do_load) { rtx pat; tree arg0 = TREE_VALUE (arglist); rtx op0 = expand_normal (arg0); enum machine_mode tmode = insn_data[icode].operand[0].mode; enum machine_mode mode0 = insn_data[icode].operand[1].mode; if (! target || GET_MODE (target) != tmode || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) target = gen_reg_rtx (tmode); if (do_load) op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0)); else { if (VECTOR_MODE_P (mode0)) op0 = safe_vector_operand (op0, mode0); if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) op0 = copy_to_mode_reg (mode0, op0); } pat = GEN_FCN (icode) (target, op0); if (! pat) return 0; emit_insn (pat); return target; } /* Expand an expression EXP that calls a built-in function, with result going to TARGET if that's convenient (and in mode MODE if that's convenient). SUBTARGET may be used as the target for computing one of EXP's operands. IGNORE is nonzero if the value is to be ignored. */ static rtx arm_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED) { const struct builtin_description * d; enum insn_code icode; tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); tree arglist = TREE_OPERAND (exp, 1); tree arg0; tree arg1; tree arg2; rtx op0; rtx op1; rtx op2; rtx pat; int fcode = DECL_FUNCTION_CODE (fndecl); size_t i; enum machine_mode tmode; enum machine_mode mode0; enum machine_mode mode1; enum machine_mode mode2; switch (fcode) { case ARM_BUILTIN_TEXTRMSB: case ARM_BUILTIN_TEXTRMUB: case ARM_BUILTIN_TEXTRMSH: case ARM_BUILTIN_TEXTRMUH: case ARM_BUILTIN_TEXTRMSW: case ARM_BUILTIN_TEXTRMUW: icode = (fcode == ARM_BUILTIN_TEXTRMSB ? CODE_FOR_iwmmxt_textrmsb : fcode == ARM_BUILTIN_TEXTRMUB ? CODE_FOR_iwmmxt_textrmub : fcode == ARM_BUILTIN_TEXTRMSH ? CODE_FOR_iwmmxt_textrmsh : fcode == ARM_BUILTIN_TEXTRMUH ? CODE_FOR_iwmmxt_textrmuh : CODE_FOR_iwmmxt_textrmw); arg0 = TREE_VALUE (arglist); arg1 = TREE_VALUE (TREE_CHAIN (arglist)); op0 = expand_normal (arg0); op1 = expand_normal (arg1); tmode = insn_data[icode].operand[0].mode; mode0 = insn_data[icode].operand[1].mode; mode1 = insn_data[icode].operand[2].mode; if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) op0 = copy_to_mode_reg (mode0, op0); if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) { /* @@@ better error message */ error ("selector must be an immediate"); return gen_reg_rtx (tmode); } if (target == 0 || GET_MODE (target) != tmode || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) target = gen_reg_rtx (tmode); pat = GEN_FCN (icode) (target, op0, op1); if (! pat) return 0; emit_insn (pat); return target; case ARM_BUILTIN_TINSRB: case ARM_BUILTIN_TINSRH: case ARM_BUILTIN_TINSRW: icode = (fcode == ARM_BUILTIN_TINSRB ? CODE_FOR_iwmmxt_tinsrb : fcode == ARM_BUILTIN_TINSRH ? CODE_FOR_iwmmxt_tinsrh : CODE_FOR_iwmmxt_tinsrw); arg0 = TREE_VALUE (arglist); arg1 = TREE_VALUE (TREE_CHAIN (arglist)); arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); op0 = expand_normal (arg0); op1 = expand_normal (arg1); op2 = expand_normal (arg2); tmode = insn_data[icode].operand[0].mode; mode0 = insn_data[icode].operand[1].mode; mode1 = insn_data[icode].operand[2].mode; mode2 = insn_data[icode].operand[3].mode; if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) op0 = copy_to_mode_reg (mode0, op0); if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) op1 = copy_to_mode_reg (mode1, op1); if (! (*insn_data[icode].operand[3].predicate) (op2, mode2)) { /* @@@ better error message */ error ("selector must be an immediate"); return const0_rtx; } if (target == 0 || GET_MODE (target) != tmode || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) target = gen_reg_rtx (tmode); pat = GEN_FCN (icode) (target, op0, op1, op2); if (! pat) return 0; emit_insn (pat); return target; case ARM_BUILTIN_SETWCX: arg0 = TREE_VALUE (arglist); arg1 = TREE_VALUE (TREE_CHAIN (arglist)); op0 = force_reg (SImode, expand_normal (arg0)); op1 = expand_normal (arg1); emit_insn (gen_iwmmxt_tmcr (op1, op0)); return 0; case ARM_BUILTIN_GETWCX: arg0 = TREE_VALUE (arglist); op0 = expand_normal (arg0); target = gen_reg_rtx (SImode); emit_insn (gen_iwmmxt_tmrc (target, op0)); return target; case ARM_BUILTIN_WSHUFH: icode = CODE_FOR_iwmmxt_wshufh; arg0 = TREE_VALUE (arglist); arg1 = TREE_VALUE (TREE_CHAIN (arglist)); op0 = expand_normal (arg0); op1 = expand_normal (arg1); tmode = insn_data[icode].operand[0].mode; mode1 = insn_data[icode].operand[1].mode; mode2 = insn_data[icode].operand[2].mode; if (! (*insn_data[icode].operand[1].predicate) (op0, mode1)) op0 = copy_to_mode_reg (mode1, op0); if (! (*insn_data[icode].operand[2].predicate) (op1, mode2)) { /* @@@ better error message */ error ("mask must be an immediate"); return const0_rtx; } if (target == 0 || GET_MODE (target) != tmode || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) target = gen_reg_rtx (tmode); pat = GEN_FCN (icode) (target, op0, op1); if (! pat) return 0; emit_insn (pat); return target; case ARM_BUILTIN_WSADB: return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadb, arglist, target); case ARM_BUILTIN_WSADH: return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadh, arglist, target); case ARM_BUILTIN_WSADBZ: return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadbz, arglist, target); case ARM_BUILTIN_WSADHZ: return arm_expand_binop_builtin (CODE_FOR_iwmmxt_wsadhz, arglist, target); /* Several three-argument builtins. */ case ARM_BUILTIN_WMACS: case ARM_BUILTIN_WMACU: case ARM_BUILTIN_WALIGN: case ARM_BUILTIN_TMIA: case ARM_BUILTIN_TMIAPH: case ARM_BUILTIN_TMIATT: case ARM_BUILTIN_TMIATB: case ARM_BUILTIN_TMIABT: case ARM_BUILTIN_TMIABB: icode = (fcode == ARM_BUILTIN_WMACS ? CODE_FOR_iwmmxt_wmacs : fcode == ARM_BUILTIN_WMACU ? CODE_FOR_iwmmxt_wmacu : fcode == ARM_BUILTIN_TMIA ? CODE_FOR_iwmmxt_tmia : fcode == ARM_BUILTIN_TMIAPH ? CODE_FOR_iwmmxt_tmiaph : fcode == ARM_BUILTIN_TMIABB ? CODE_FOR_iwmmxt_tmiabb : fcode == ARM_BUILTIN_TMIABT ? CODE_FOR_iwmmxt_tmiabt : fcode == ARM_BUILTIN_TMIATB ? CODE_FOR_iwmmxt_tmiatb : fcode == ARM_BUILTIN_TMIATT ? CODE_FOR_iwmmxt_tmiatt : CODE_FOR_iwmmxt_walign); arg0 = TREE_VALUE (arglist); arg1 = TREE_VALUE (TREE_CHAIN (arglist)); arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); op0 = expand_normal (arg0); op1 = expand_normal (arg1); op2 = expand_normal (arg2); tmode = insn_data[icode].operand[0].mode; mode0 = insn_data[icode].operand[1].mode; mode1 = insn_data[icode].operand[2].mode; mode2 = insn_data[icode].operand[3].mode; if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) op0 = copy_to_mode_reg (mode0, op0); if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) op1 = copy_to_mode_reg (mode1, op1); if (! (*insn_data[icode].operand[3].predicate) (op2, mode2)) op2 = copy_to_mode_reg (mode2, op2); if (target == 0 || GET_MODE (target) != tmode || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) target = gen_reg_rtx (tmode); pat = GEN_FCN (icode) (target, op0, op1, op2); if (! pat) return 0; emit_insn (pat); return target; case ARM_BUILTIN_WZERO: target = gen_reg_rtx (DImode); emit_insn (gen_iwmmxt_clrdi (target)); return target; case ARM_BUILTIN_THREAD_POINTER: return arm_load_tp (target); default: break; } for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++) if (d->code == (const enum arm_builtins) fcode) return arm_expand_binop_builtin (d->icode, arglist, target); for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++) if (d->code == (const enum arm_builtins) fcode) return arm_expand_unop_builtin (d->icode, arglist, target, 0); /* @@@ Should really do something sensible here. */ return NULL_RTX; } /* Return the number (counting from 0) of the least significant set bit in MASK. */ inline static int number_of_first_bit_set (unsigned mask) { int bit; for (bit = 0; (mask & (1 << bit)) == 0; ++bit) continue; return bit; } /* Emit code to push or pop registers to or from the stack. F is the assembly file. MASK is the registers to push or pop. PUSH is nonzero if we should push, and zero if we should pop. For debugging output, if pushing, adjust CFA_OFFSET by the amount of space added to the stack. REAL_REGS should have the same number of bits set as MASK, and will be used instead (in the same order) to describe which registers were saved - this is used to mark the save slots when we push high registers after moving them to low registers. */ static void thumb_pushpop (FILE *f, unsigned long mask, int push, int *cfa_offset, unsigned long real_regs) { int regno; int lo_mask = mask & 0xFF; int pushed_words = 0; gcc_assert (mask); if (lo_mask == 0 && !push && (mask & (1 << PC_REGNUM))) { /* Special case. Do not generate a POP PC statement here, do it in thumb_exit() */ thumb_exit (f, -1); return; } if (ARM_EABI_UNWIND_TABLES && push) { fprintf (f, "\t.save\t{"); for (regno = 0; regno < 15; regno++) { if (real_regs & (1 << regno)) { if (real_regs & ((1 << regno) -1)) fprintf (f, ", "); asm_fprintf (f, "%r", regno); } } fprintf (f, "}\n"); } fprintf (f, "\t%s\t{", push ? "push" : "pop"); /* Look at the low registers first. */ for (regno = 0; regno <= LAST_LO_REGNUM; regno++, lo_mask >>= 1) { if (lo_mask & 1) { asm_fprintf (f, "%r", regno); if ((lo_mask & ~1) != 0) fprintf (f, ", "); pushed_words++; } } if (push && (mask & (1 << LR_REGNUM))) { /* Catch pushing the LR. */ if (mask & 0xFF) fprintf (f, ", "); asm_fprintf (f, "%r", LR_REGNUM); pushed_words++; } else if (!push && (mask & (1 << PC_REGNUM))) { /* Catch popping the PC. */ if (TARGET_INTERWORK || TARGET_BACKTRACE || current_function_calls_eh_return) { /* The PC is never poped directly, instead it is popped into r3 and then BX is used. */ fprintf (f, "}\n"); thumb_exit (f, -1); return; } else { if (mask & 0xFF) fprintf (f, ", "); asm_fprintf (f, "%r", PC_REGNUM); } } fprintf (f, "}\n"); if (push && pushed_words && dwarf2out_do_frame ()) { char *l = dwarf2out_cfi_label (); int pushed_mask = real_regs; *cfa_offset += pushed_words * 4; dwarf2out_def_cfa (l, SP_REGNUM, *cfa_offset); pushed_words = 0; pushed_mask = real_regs; for (regno = 0; regno <= 14; regno++, pushed_mask >>= 1) { if (pushed_mask & 1) dwarf2out_reg_save (l, regno, 4 * pushed_words++ - *cfa_offset); } } } /* Generate code to return from a thumb function. If 'reg_containing_return_addr' is -1, then the return address is actually on the stack, at the stack pointer. */ static void thumb_exit (FILE *f, int reg_containing_return_addr) { unsigned regs_available_for_popping; unsigned regs_to_pop; int pops_needed; unsigned available; unsigned required; int mode; int size; int restore_a4 = FALSE; /* Compute the registers we need to pop. */ regs_to_pop = 0; pops_needed = 0; if (reg_containing_return_addr == -1) { regs_to_pop |= 1 << LR_REGNUM; ++pops_needed; } if (TARGET_BACKTRACE) { /* Restore the (ARM) frame pointer and stack pointer. */ regs_to_pop |= (1 << ARM_HARD_FRAME_POINTER_REGNUM) | (1 << SP_REGNUM); pops_needed += 2; } /* If there is nothing to pop then just emit the BX instruction and return. */ if (pops_needed == 0) { if (current_function_calls_eh_return) asm_fprintf (f, "\tadd\t%r, %r\n", SP_REGNUM, ARM_EH_STACKADJ_REGNUM); asm_fprintf (f, "\tbx\t%r\n", reg_containing_return_addr); return; } /* Otherwise if we are not supporting interworking and we have not created a backtrace structure and the function was not entered in ARM mode then just pop the return address straight into the PC. */ else if (!TARGET_INTERWORK && !TARGET_BACKTRACE && !is_called_in_ARM_mode (current_function_decl) && !current_function_calls_eh_return) { asm_fprintf (f, "\tpop\t{%r}\n", PC_REGNUM); return; } /* Find out how many of the (return) argument registers we can corrupt. */ regs_available_for_popping = 0; /* If returning via __builtin_eh_return, the bottom three registers all contain information needed for the return. */ if (current_function_calls_eh_return) size = 12; else { /* If we can deduce the registers used from the function's return value. This is more reliable that examining regs_ever_live[] because that will be set if the register is ever used in the function, not just if the register is used to hold a return value. */ if (current_function_return_rtx != 0) mode = GET_MODE (current_function_return_rtx); else mode = DECL_MODE (DECL_RESULT (current_function_decl)); size = GET_MODE_SIZE (mode); if (size == 0) { /* In a void function we can use any argument register. In a function that returns a structure on the stack we can use the second and third argument registers. */ if (mode == VOIDmode) regs_available_for_popping = (1 << ARG_REGISTER (1)) | (1 << ARG_REGISTER (2)) | (1 << ARG_REGISTER (3)); else regs_available_for_popping = (1 << ARG_REGISTER (2)) | (1 << ARG_REGISTER (3)); } else if (size <= 4) regs_available_for_popping = (1 << ARG_REGISTER (2)) | (1 << ARG_REGISTER (3)); else if (size <= 8) regs_available_for_popping = (1 << ARG_REGISTER (3)); } /* Match registers to be popped with registers into which we pop them. */ for (available = regs_available_for_popping, required = regs_to_pop; required != 0 && available != 0; available &= ~(available & - available), required &= ~(required & - required)) -- pops_needed; /* If we have any popping registers left over, remove them. */ if (available > 0) regs_available_for_popping &= ~available; /* Otherwise if we need another popping register we can use the fourth argument register. */ else if (pops_needed) { /* If we have not found any free argument registers and reg a4 contains the return address, we must move it. */ if (regs_available_for_popping == 0 && reg_containing_return_addr == LAST_ARG_REGNUM) { asm_fprintf (f, "\tmov\t%r, %r\n", LR_REGNUM, LAST_ARG_REGNUM); reg_containing_return_addr = LR_REGNUM; } else if (size > 12) { /* Register a4 is being used to hold part of the return value, but we have dire need of a free, low register. */ restore_a4 = TRUE; asm_fprintf (f, "\tmov\t%r, %r\n",IP_REGNUM, LAST_ARG_REGNUM); } if (reg_containing_return_addr != LAST_ARG_REGNUM) { /* The fourth argument register is available. */ regs_available_for_popping |= 1 << LAST_ARG_REGNUM; --pops_needed; } } /* Pop as many registers as we can. */ thumb_pushpop (f, regs_available_for_popping, FALSE, NULL, regs_available_for_popping); /* Process the registers we popped. */ if (reg_containing_return_addr == -1) { /* The return address was popped into the lowest numbered register. */ regs_to_pop &= ~(1 << LR_REGNUM); reg_containing_return_addr = number_of_first_bit_set (regs_available_for_popping); /* Remove this register for the mask of available registers, so that the return address will not be corrupted by further pops. */ regs_available_for_popping &= ~(1 << reg_containing_return_addr); } /* If we popped other registers then handle them here. */ if (regs_available_for_popping) { int frame_pointer; /* Work out which register currently contains the frame pointer. */ frame_pointer = number_of_first_bit_set (regs_available_for_popping); /* Move it into the correct place. */ asm_fprintf (f, "\tmov\t%r, %r\n", ARM_HARD_FRAME_POINTER_REGNUM, frame_pointer); /* (Temporarily) remove it from the mask of popped registers. */ regs_available_for_popping &= ~(1 << frame_pointer); regs_to_pop &= ~(1 << ARM_HARD_FRAME_POINTER_REGNUM); if (regs_available_for_popping) { int stack_pointer; /* We popped the stack pointer as well, find the register that contains it. */ stack_pointer = number_of_first_bit_set (regs_available_for_popping); /* Move it into the stack register. */ asm_fprintf (f, "\tmov\t%r, %r\n", SP_REGNUM, stack_pointer); /* At this point we have popped all necessary registers, so do not worry about restoring regs_available_for_popping to its correct value: assert (pops_needed == 0) assert (regs_available_for_popping == (1 << frame_pointer)) assert (regs_to_pop == (1 << STACK_POINTER)) */ } else { /* Since we have just move the popped value into the frame pointer, the popping register is available for reuse, and we know that we still have the stack pointer left to pop. */ regs_available_for_popping |= (1 << frame_pointer); } } /* If we still have registers left on the stack, but we no longer have any registers into which we can pop them, then we must move the return address into the link register and make available the register that contained it. */ if (regs_available_for_popping == 0 && pops_needed > 0) { regs_available_for_popping |= 1 << reg_containing_return_addr; asm_fprintf (f, "\tmov\t%r, %r\n", LR_REGNUM, reg_containing_return_addr); reg_containing_return_addr = LR_REGNUM; } /* If we have registers left on the stack then pop some more. We know that at most we will want to pop FP and SP. */ if (pops_needed > 0) { int popped_into; int move_to; thumb_pushpop (f, regs_available_for_popping, FALSE, NULL, regs_available_for_popping); /* We have popped either FP or SP. Move whichever one it is into the correct register. */ popped_into = number_of_first_bit_set (regs_available_for_popping); move_to = number_of_first_bit_set (regs_to_pop); asm_fprintf (f, "\tmov\t%r, %r\n", move_to, popped_into); regs_to_pop &= ~(1 << move_to); --pops_needed; } /* If we still have not popped everything then we must have only had one register available to us and we are now popping the SP. */ if (pops_needed > 0) { int popped_into; thumb_pushpop (f, regs_available_for_popping, FALSE, NULL, regs_available_for_popping); popped_into = number_of_first_bit_set (regs_available_for_popping); asm_fprintf (f, "\tmov\t%r, %r\n", SP_REGNUM, popped_into); /* assert (regs_to_pop == (1 << STACK_POINTER)) assert (pops_needed == 1) */ } /* If necessary restore the a4 register. */ if (restore_a4) { if (reg_containing_return_addr != LR_REGNUM) { asm_fprintf (f, "\tmov\t%r, %r\n", LR_REGNUM, LAST_ARG_REGNUM); reg_containing_return_addr = LR_REGNUM; } asm_fprintf (f, "\tmov\t%r, %r\n", LAST_ARG_REGNUM, IP_REGNUM); } if (current_function_calls_eh_return) asm_fprintf (f, "\tadd\t%r, %r\n", SP_REGNUM, ARM_EH_STACKADJ_REGNUM); /* Return to caller. */ asm_fprintf (f, "\tbx\t%r\n", reg_containing_return_addr); } void thumb_final_prescan_insn (rtx insn) { if (flag_print_asm_name) asm_fprintf (asm_out_file, "%@ 0x%04x\n", INSN_ADDRESSES (INSN_UID (insn))); } int thumb_shiftable_const (unsigned HOST_WIDE_INT val) { unsigned HOST_WIDE_INT mask = 0xff; int i; if (val == 0) /* XXX */ return 0; for (i = 0; i < 25; i++) if ((val & (mask << i)) == val) return 1; return 0; } /* Returns nonzero if the current function contains, or might contain a far jump. */ static int thumb_far_jump_used_p (void) { rtx insn; /* This test is only important for leaf functions. */ /* assert (!leaf_function_p ()); */ /* If we have already decided that far jumps may be used, do not bother checking again, and always return true even if it turns out that they are not being used. Once we have made the decision that far jumps are present (and that hence the link register will be pushed onto the stack) we cannot go back on it. */ if (cfun->machine->far_jump_used) return 1; /* If this function is not being called from the prologue/epilogue generation code then it must be being called from the INITIAL_ELIMINATION_OFFSET macro. */ if (!(ARM_DOUBLEWORD_ALIGN || reload_completed)) { /* In this case we know that we are being asked about the elimination of the arg pointer register. If that register is not being used, then there are no arguments on the stack, and we do not have to worry that a far jump might force the prologue to push the link register, changing the stack offsets. In this case we can just return false, since the presence of far jumps in the function will not affect stack offsets. If the arg pointer is live (or if it was live, but has now been eliminated and so set to dead) then we do have to test to see if the function might contain a far jump. This test can lead to some false negatives, since before reload is completed, then length of branch instructions is not known, so gcc defaults to returning their longest length, which in turn sets the far jump attribute to true. A false negative will not result in bad code being generated, but it will result in a needless push and pop of the link register. We hope that this does not occur too often. If we need doubleword stack alignment this could affect the other elimination offsets so we can't risk getting it wrong. */ if (regs_ever_live [ARG_POINTER_REGNUM]) cfun->machine->arg_pointer_live = 1; else if (!cfun->machine->arg_pointer_live) return 0; } /* Check to see if the function contains a branch insn with the far jump attribute set. */ for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) { if (GET_CODE (insn) == JUMP_INSN /* Ignore tablejump patterns. */ && GET_CODE (PATTERN (insn)) != ADDR_VEC && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC && get_attr_far_jump (insn) == FAR_JUMP_YES ) { /* Record the fact that we have decided that the function does use far jumps. */ cfun->machine->far_jump_used = 1; return 1; } } return 0; } /* Return nonzero if FUNC must be entered in ARM mode. */ int is_called_in_ARM_mode (tree func) { gcc_assert (TREE_CODE (func) == FUNCTION_DECL); /* Ignore the problem about functions whose address is taken. */ if (TARGET_CALLEE_INTERWORKING && TREE_PUBLIC (func)) return TRUE; #ifdef ARM_PE return lookup_attribute ("interfacearm", DECL_ATTRIBUTES (func)) != NULL_TREE; #else return FALSE; #endif } /* The bits which aren't usefully expanded as rtl. */ const char * thumb_unexpanded_epilogue (void) { int regno; unsigned long live_regs_mask = 0; int high_regs_pushed = 0; int had_to_push_lr; int size; if (return_used_this_function) return ""; if (IS_NAKED (arm_current_func_type ())) return ""; live_regs_mask = thumb_compute_save_reg_mask (); high_regs_pushed = bit_count (live_regs_mask & 0x0f00); /* If we can deduce the registers used from the function's return value. This is more reliable that examining regs_ever_live[] because that will be set if the register is ever used in the function, not just if the register is used to hold a return value. */ size = arm_size_return_regs (); /* The prolog may have pushed some high registers to use as work registers. e.g. the testsuite file: gcc/testsuite/gcc/gcc.c-torture/execute/complex-2.c compiles to produce: push {r4, r5, r6, r7, lr} mov r7, r9 mov r6, r8 push {r6, r7} as part of the prolog. We have to undo that pushing here. */ if (high_regs_pushed) { unsigned long mask = live_regs_mask & 0xff; int next_hi_reg; /* The available low registers depend on the size of the value we are returning. */ if (size <= 12) mask |= 1 << 3; if (size <= 8) mask |= 1 << 2; if (mask == 0) /* Oh dear! We have no low registers into which we can pop high registers! */ internal_error ("no low registers available for popping high registers"); for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++) if (live_regs_mask & (1 << next_hi_reg)) break; while (high_regs_pushed) { /* Find lo register(s) into which the high register(s) can be popped. */ for (regno = 0; regno <= LAST_LO_REGNUM; regno++) { if (mask & (1 << regno)) high_regs_pushed--; if (high_regs_pushed == 0) break; } mask &= (2 << regno) - 1; /* A noop if regno == 8 */ /* Pop the values into the low register(s). */ thumb_pushpop (asm_out_file, mask, 0, NULL, mask); /* Move the value(s) into the high registers. */ for (regno = 0; regno <= LAST_LO_REGNUM; regno++) { if (mask & (1 << regno)) { asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", next_hi_reg, regno); for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++) if (live_regs_mask & (1 << next_hi_reg)) break; } } } live_regs_mask &= ~0x0f00; } had_to_push_lr = (live_regs_mask & (1 << LR_REGNUM)) != 0; live_regs_mask &= 0xff; if (current_function_pretend_args_size == 0 || TARGET_BACKTRACE) { /* Pop the return address into the PC. */ if (had_to_push_lr) live_regs_mask |= 1 << PC_REGNUM; /* Either no argument registers were pushed or a backtrace structure was created which includes an adjusted stack pointer, so just pop everything. */ if (live_regs_mask) thumb_pushpop (asm_out_file, live_regs_mask, FALSE, NULL, live_regs_mask); /* We have either just popped the return address into the PC or it is was kept in LR for the entire function. */ if (!had_to_push_lr) thumb_exit (asm_out_file, LR_REGNUM); } else { /* Pop everything but the return address. */ if (live_regs_mask) thumb_pushpop (asm_out_file, live_regs_mask, FALSE, NULL, live_regs_mask); if (had_to_push_lr) { if (size > 12) { /* We have no free low regs, so save one. */ asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", IP_REGNUM, LAST_ARG_REGNUM); } /* Get the return address into a temporary register. */ thumb_pushpop (asm_out_file, 1 << LAST_ARG_REGNUM, 0, NULL, 1 << LAST_ARG_REGNUM); if (size > 12) { /* Move the return address to lr. */ asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", LR_REGNUM, LAST_ARG_REGNUM); /* Restore the low register. */ asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", LAST_ARG_REGNUM, IP_REGNUM); regno = LR_REGNUM; } else regno = LAST_ARG_REGNUM; } else regno = LR_REGNUM; /* Remove the argument registers that were pushed onto the stack. */ asm_fprintf (asm_out_file, "\tadd\t%r, %r, #%d\n", SP_REGNUM, SP_REGNUM, current_function_pretend_args_size); thumb_exit (asm_out_file, regno); } return ""; } /* Functions to save and restore machine-specific function data. */ static struct machine_function * arm_init_machine_status (void) { struct machine_function *machine; machine = (machine_function *) ggc_alloc_cleared (sizeof (machine_function)); #if ARM_FT_UNKNOWN != 0 machine->func_type = ARM_FT_UNKNOWN; #endif return machine; } /* Return an RTX indicating where the return address to the calling function can be found. */ rtx arm_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) { if (count != 0) return NULL_RTX; return get_hard_reg_initial_val (Pmode, LR_REGNUM); } /* Do anything needed before RTL is emitted for each function. */ void arm_init_expanders (void) { /* Arrange to initialize and mark the machine per-function status. */ init_machine_status = arm_init_machine_status; /* This is to stop the combine pass optimizing away the alignment adjustment of va_arg. */ /* ??? It is claimed that this should not be necessary. */ if (cfun) mark_reg_pointer (arg_pointer_rtx, PARM_BOUNDARY); } /* Like arm_compute_initial_elimination offset. Simpler because there isn't an ABI specified frame pointer for Thumb. Instead, we set it to point at the base of the local variables after static stack space for a function has been allocated. */ HOST_WIDE_INT thumb_compute_initial_elimination_offset (unsigned int from, unsigned int to) { arm_stack_offsets *offsets; offsets = arm_get_frame_offsets (); switch (from) { case ARG_POINTER_REGNUM: switch (to) { case STACK_POINTER_REGNUM: return offsets->outgoing_args - offsets->saved_args; case FRAME_POINTER_REGNUM: return offsets->soft_frame - offsets->saved_args; case ARM_HARD_FRAME_POINTER_REGNUM: return offsets->saved_regs - offsets->saved_args; case THUMB_HARD_FRAME_POINTER_REGNUM: return offsets->locals_base - offsets->saved_args; default: gcc_unreachable (); } break; case FRAME_POINTER_REGNUM: switch (to) { case STACK_POINTER_REGNUM: return offsets->outgoing_args - offsets->soft_frame; case ARM_HARD_FRAME_POINTER_REGNUM: return offsets->saved_regs - offsets->soft_frame; case THUMB_HARD_FRAME_POINTER_REGNUM: return offsets->locals_base - offsets->soft_frame; default: gcc_unreachable (); } break; default: gcc_unreachable (); } } /* Generate the rest of a function's prologue. */ void thumb_expand_prologue (void) { rtx insn, dwarf; HOST_WIDE_INT amount; arm_stack_offsets *offsets; unsigned long func_type; int regno; unsigned long live_regs_mask; func_type = arm_current_func_type (); /* Naked functions don't have prologues. */ if (IS_NAKED (func_type)) return; if (IS_INTERRUPT (func_type)) { error ("interrupt Service Routines cannot be coded in Thumb mode"); return; } live_regs_mask = thumb_compute_save_reg_mask (); /* Load the pic register before setting the frame pointer, so we can use r7 as a temporary work register. */ if (flag_pic && arm_pic_register != INVALID_REGNUM) arm_load_pic_register (live_regs_mask); if (!frame_pointer_needed && CALLER_INTERWORKING_SLOT_SIZE > 0) emit_move_insn (gen_rtx_REG (Pmode, ARM_HARD_FRAME_POINTER_REGNUM), stack_pointer_rtx); offsets = arm_get_frame_offsets (); amount = offsets->outgoing_args - offsets->saved_regs; if (amount) { if (amount < 512) { insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (- amount))); RTX_FRAME_RELATED_P (insn) = 1; } else { rtx reg; /* The stack decrement is too big for an immediate value in a single insn. In theory we could issue multiple subtracts, but after three of them it becomes more space efficient to place the full value in the constant pool and load into a register. (Also the ARM debugger really likes to see only one stack decrement per function). So instead we look for a scratch register into which we can load the decrement, and then we subtract this from the stack pointer. Unfortunately on the thumb the only available scratch registers are the argument registers, and we cannot use these as they may hold arguments to the function. Instead we attempt to locate a call preserved register which is used by this function. If we can find one, then we know that it will have been pushed at the start of the prologue and so we can corrupt it now. */ for (regno = LAST_ARG_REGNUM + 1; regno <= LAST_LO_REGNUM; regno++) if (live_regs_mask & (1 << regno) && !(frame_pointer_needed && (regno == THUMB_HARD_FRAME_POINTER_REGNUM))) break; if (regno > LAST_LO_REGNUM) /* Very unlikely. */ { rtx spare = gen_rtx_REG (SImode, IP_REGNUM); /* Choose an arbitrary, non-argument low register. */ reg = gen_rtx_REG (SImode, LAST_LO_REGNUM); /* Save it by copying it into a high, scratch register. */ emit_insn (gen_movsi (spare, reg)); /* Add a USE to stop propagate_one_insn() from barfing. */ emit_insn (gen_prologue_use (spare)); /* Decrement the stack. */ emit_insn (gen_movsi (reg, GEN_INT (- amount))); insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg)); RTX_FRAME_RELATED_P (insn) = 1; dwarf = gen_rtx_SET (VOIDmode, stack_pointer_rtx, plus_constant (stack_pointer_rtx, -amount)); RTX_FRAME_RELATED_P (dwarf) = 1; REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf, REG_NOTES (insn)); /* Restore the low register's original value. */ emit_insn (gen_movsi (reg, spare)); /* Emit a USE of the restored scratch register, so that flow analysis will not consider the restore redundant. The register won't be used again in this function and isn't restored by the epilogue. */ emit_insn (gen_prologue_use (reg)); } else { reg = gen_rtx_REG (SImode, regno); emit_insn (gen_movsi (reg, GEN_INT (- amount))); insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg)); RTX_FRAME_RELATED_P (insn) = 1; dwarf = gen_rtx_SET (VOIDmode, stack_pointer_rtx, plus_constant (stack_pointer_rtx, -amount)); RTX_FRAME_RELATED_P (dwarf) = 1; REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf, REG_NOTES (insn)); } } } if (frame_pointer_needed) { amount = offsets->outgoing_args - offsets->locals_base; if (amount < 1024) insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, stack_pointer_rtx, GEN_INT (amount))); else { emit_insn (gen_movsi (hard_frame_pointer_rtx, GEN_INT (amount))); insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, hard_frame_pointer_rtx, stack_pointer_rtx)); dwarf = gen_rtx_SET (VOIDmode, hard_frame_pointer_rtx, plus_constant (stack_pointer_rtx, amount)); RTX_FRAME_RELATED_P (dwarf) = 1; REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf, REG_NOTES (insn)); } RTX_FRAME_RELATED_P (insn) = 1; } /* If we are profiling, make sure no instructions are scheduled before the call to mcount. Similarly if the user has requested no scheduling in the prolog. Similarly if we want non-call exceptions using the EABI unwinder, to prevent faulting instructions from being swapped with a stack adjustment. */ if (current_function_profile || !TARGET_SCHED_PROLOG || (ARM_EABI_UNWIND_TABLES && flag_non_call_exceptions)) emit_insn (gen_blockage ()); cfun->machine->lr_save_eliminated = !thumb_force_lr_save (); if (live_regs_mask & 0xff) cfun->machine->lr_save_eliminated = 0; /* If the link register is being kept alive, with the return address in it, then make sure that it does not get reused by the ce2 pass. */ if (cfun->machine->lr_save_eliminated) emit_insn (gen_prologue_use (gen_rtx_REG (SImode, LR_REGNUM))); } void thumb_expand_epilogue (void) { HOST_WIDE_INT amount; arm_stack_offsets *offsets; int regno; /* Naked functions don't have prologues. */ if (IS_NAKED (arm_current_func_type ())) return; offsets = arm_get_frame_offsets (); amount = offsets->outgoing_args - offsets->saved_regs; if (frame_pointer_needed) { emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx)); amount = offsets->locals_base - offsets->saved_regs; } gcc_assert (amount >= 0); if (amount) { if (amount < 512) emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (amount))); else { /* r3 is always free in the epilogue. */ rtx reg = gen_rtx_REG (SImode, LAST_ARG_REGNUM); emit_insn (gen_movsi (reg, GEN_INT (amount))); emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg)); } } /* Emit a USE (stack_pointer_rtx), so that the stack adjustment will not be deleted. */ emit_insn (gen_prologue_use (stack_pointer_rtx)); if (current_function_profile || !TARGET_SCHED_PROLOG) emit_insn (gen_blockage ()); /* Emit a clobber for each insn that will be restored in the epilogue, so that flow2 will get register lifetimes correct. */ for (regno = 0; regno < 13; regno++) if (regs_ever_live[regno] && !call_used_regs[regno]) emit_insn (gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, regno))); if (! regs_ever_live[LR_REGNUM]) emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, LR_REGNUM))); } static void thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED) { unsigned long live_regs_mask = 0; unsigned long l_mask; unsigned high_regs_pushed = 0; int cfa_offset = 0; int regno; if (IS_NAKED (arm_current_func_type ())) return; if (is_called_in_ARM_mode (current_function_decl)) { const char * name; gcc_assert (GET_CODE (DECL_RTL (current_function_decl)) == MEM); gcc_assert (GET_CODE (XEXP (DECL_RTL (current_function_decl), 0)) == SYMBOL_REF); name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0); /* Generate code sequence to switch us into Thumb mode. */ /* The .code 32 directive has already been emitted by ASM_DECLARE_FUNCTION_NAME. */ asm_fprintf (f, "\torr\t%r, %r, #1\n", IP_REGNUM, PC_REGNUM); asm_fprintf (f, "\tbx\t%r\n", IP_REGNUM); /* Generate a label, so that the debugger will notice the change in instruction sets. This label is also used by the assembler to bypass the ARM code when this function is called from a Thumb encoded function elsewhere in the same file. Hence the definition of STUB_NAME here must agree with the definition in gas/config/tc-arm.c. */ #define STUB_NAME ".real_start_of" fprintf (f, "\t.code\t16\n"); #ifdef ARM_PE if (arm_dllexport_name_p (name)) name = arm_strip_name_encoding (name); #endif asm_fprintf (f, "\t.globl %s%U%s\n", STUB_NAME, name); fprintf (f, "\t.thumb_func\n"); asm_fprintf (f, "%s%U%s:\n", STUB_NAME, name); } if (current_function_pretend_args_size) { /* Output unwind directive for the stack adjustment. */ if (ARM_EABI_UNWIND_TABLES) fprintf (f, "\t.pad #%d\n", current_function_pretend_args_size); if (cfun->machine->uses_anonymous_args) { int num_pushes; fprintf (f, "\tpush\t{"); num_pushes = ARM_NUM_INTS (current_function_pretend_args_size); for (regno = LAST_ARG_REGNUM + 1 - num_pushes; regno <= LAST_ARG_REGNUM; regno++) asm_fprintf (f, "%r%s", regno, regno == LAST_ARG_REGNUM ? "" : ", "); fprintf (f, "}\n"); } else asm_fprintf (f, "\tsub\t%r, %r, #%d\n", SP_REGNUM, SP_REGNUM, current_function_pretend_args_size); /* We don't need to record the stores for unwinding (would it help the debugger any if we did?), but record the change in the stack pointer. */ if (dwarf2out_do_frame ()) { char *l = dwarf2out_cfi_label (); cfa_offset = cfa_offset + current_function_pretend_args_size; dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset); } } /* Get the registers we are going to push. */ live_regs_mask = thumb_compute_save_reg_mask (); /* Extract a mask of the ones we can give to the Thumb's push instruction. */ l_mask = live_regs_mask & 0x40ff; /* Then count how many other high registers will need to be pushed. */ high_regs_pushed = bit_count (live_regs_mask & 0x0f00); if (TARGET_BACKTRACE) { unsigned offset; unsigned work_register; /* We have been asked to create a stack backtrace structure. The code looks like this: 0 .align 2 0 func: 0 sub SP, #16 Reserve space for 4 registers. 2 push {R7} Push low registers. 4 add R7, SP, #20 Get the stack pointer before the push. 6 str R7, [SP, #8] Store the stack pointer (before reserving the space). 8 mov R7, PC Get hold of the start of this code plus 12. 10 str R7, [SP, #16] Store it. 12 mov R7, FP Get hold of the current frame pointer. 14 str R7, [SP, #4] Store it. 16 mov R7, LR Get hold of the current return address. 18 str R7, [SP, #12] Store it. 20 add R7, SP, #16 Point at the start of the backtrace structure. 22 mov FP, R7 Put this value into the frame pointer. */ work_register = thumb_find_work_register (live_regs_mask); if (ARM_EABI_UNWIND_TABLES) asm_fprintf (f, "\t.pad #16\n"); asm_fprintf (f, "\tsub\t%r, %r, #16\t%@ Create stack backtrace structure\n", SP_REGNUM, SP_REGNUM); if (dwarf2out_do_frame ()) { char *l = dwarf2out_cfi_label (); cfa_offset = cfa_offset + 16; dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset); } if (l_mask) { thumb_pushpop (f, l_mask, 1, &cfa_offset, l_mask); offset = bit_count (l_mask) * UNITS_PER_WORD; } else offset = 0; asm_fprintf (f, "\tadd\t%r, %r, #%d\n", work_register, SP_REGNUM, offset + 16 + current_function_pretend_args_size); asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM, offset + 4); /* Make sure that the instruction fetching the PC is in the right place to calculate "start of backtrace creation code + 12". */ if (l_mask) { asm_fprintf (f, "\tmov\t%r, %r\n", work_register, PC_REGNUM); asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM, offset + 12); asm_fprintf (f, "\tmov\t%r, %r\n", work_register, ARM_HARD_FRAME_POINTER_REGNUM); asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM, offset); } else { asm_fprintf (f, "\tmov\t%r, %r\n", work_register, ARM_HARD_FRAME_POINTER_REGNUM); asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM, offset); asm_fprintf (f, "\tmov\t%r, %r\n", work_register, PC_REGNUM); asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM, offset + 12); } asm_fprintf (f, "\tmov\t%r, %r\n", work_register, LR_REGNUM); asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM, offset + 8); asm_fprintf (f, "\tadd\t%r, %r, #%d\n", work_register, SP_REGNUM, offset + 12); asm_fprintf (f, "\tmov\t%r, %r\t\t%@ Backtrace structure created\n", ARM_HARD_FRAME_POINTER_REGNUM, work_register); } /* Optimization: If we are not pushing any low registers but we are going to push some high registers then delay our first push. This will just be a push of LR and we can combine it with the push of the first high register. */ else if ((l_mask & 0xff) != 0 || (high_regs_pushed == 0 && l_mask)) thumb_pushpop (f, l_mask, 1, &cfa_offset, l_mask); if (high_regs_pushed) { unsigned pushable_regs; unsigned next_hi_reg; for (next_hi_reg = 12; next_hi_reg > LAST_LO_REGNUM; next_hi_reg--) if (live_regs_mask & (1 << next_hi_reg)) break; pushable_regs = l_mask & 0xff; if (pushable_regs == 0) pushable_regs = 1 << thumb_find_work_register (live_regs_mask); while (high_regs_pushed > 0) { unsigned long real_regs_mask = 0; for (regno = LAST_LO_REGNUM; regno >= 0; regno --) { if (pushable_regs & (1 << regno)) { asm_fprintf (f, "\tmov\t%r, %r\n", regno, next_hi_reg); high_regs_pushed --; real_regs_mask |= (1 << next_hi_reg); if (high_regs_pushed) { for (next_hi_reg --; next_hi_reg > LAST_LO_REGNUM; next_hi_reg --) if (live_regs_mask & (1 << next_hi_reg)) break; } else { pushable_regs &= ~((1 << regno) - 1); break; } } } /* If we had to find a work register and we have not yet saved the LR then add it to the list of regs to push. */ if (l_mask == (1 << LR_REGNUM)) { thumb_pushpop (f, pushable_regs | (1 << LR_REGNUM), 1, &cfa_offset, real_regs_mask | (1 << LR_REGNUM)); l_mask = 0; } else thumb_pushpop (f, pushable_regs, 1, &cfa_offset, real_regs_mask); } } } /* Handle the case of a double word load into a low register from a computed memory address. The computed address may involve a register which is overwritten by the load. */ const char * thumb_load_double_from_address (rtx *operands) { rtx addr; rtx base; rtx offset; rtx arg1; rtx arg2; gcc_assert (GET_CODE (operands[0]) == REG); gcc_assert (GET_CODE (operands[1]) == MEM); /* Get the memory address. */ addr = XEXP (operands[1], 0); /* Work out how the memory address is computed. */ switch (GET_CODE (addr)) { case REG: operands[2] = adjust_address (operands[1], SImode, 4); if (REGNO (operands[0]) == REGNO (addr)) { output_asm_insn ("ldr\t%H0, %2", operands); output_asm_insn ("ldr\t%0, %1", operands); } else { output_asm_insn ("ldr\t%0, %1", operands); output_asm_insn ("ldr\t%H0, %2", operands); } break; case CONST: /* Compute
+ 4 for the high order load. */ operands[2] = adjust_address (operands[1], SImode, 4); output_asm_insn ("ldr\t%0, %1", operands); output_asm_insn ("ldr\t%H0, %2", operands); break; case PLUS: arg1 = XEXP (addr, 0); arg2 = XEXP (addr, 1); if (CONSTANT_P (arg1)) base = arg2, offset = arg1; else base = arg1, offset = arg2; gcc_assert (GET_CODE (base) == REG); /* Catch the case of
= + */ if (GET_CODE (offset) == REG) { int reg_offset = REGNO (offset); int reg_base = REGNO (base); int reg_dest = REGNO (operands[0]); /* Add the base and offset registers together into the higher destination register. */ asm_fprintf (asm_out_file, "\tadd\t%r, %r, %r", reg_dest + 1, reg_base, reg_offset); /* Load the lower destination register from the address in the higher destination register. */ asm_fprintf (asm_out_file, "\tldr\t%r, [%r, #0]", reg_dest, reg_dest + 1); /* Load the higher destination register from its own address plus 4. */ asm_fprintf (asm_out_file, "\tldr\t%r, [%r, #4]", reg_dest + 1, reg_dest + 1); } else { /* Compute
+ 4 for the high order load. */ operands[2] = adjust_address (operands[1], SImode, 4); /* If the computed address is held in the low order register then load the high order register first, otherwise always load the low order register first. */ if (REGNO (operands[0]) == REGNO (base)) { output_asm_insn ("ldr\t%H0, %2", operands); output_asm_insn ("ldr\t%0, %1", operands); } else { output_asm_insn ("ldr\t%0, %1", operands); output_asm_insn ("ldr\t%H0, %2", operands); } } break; case LABEL_REF: /* With no registers to worry about we can just load the value directly. */ operands[2] = adjust_address (operands[1], SImode, 4); output_asm_insn ("ldr\t%H0, %2", operands); output_asm_insn ("ldr\t%0, %1", operands); break; default: gcc_unreachable (); } return ""; } const char * thumb_output_move_mem_multiple (int n, rtx *operands) { rtx tmp; switch (n) { case 2: if (REGNO (operands[4]) > REGNO (operands[5])) { tmp = operands[4]; operands[4] = operands[5]; operands[5] = tmp; } output_asm_insn ("ldmia\t%1!, {%4, %5}", operands); output_asm_insn ("stmia\t%0!, {%4, %5}", operands); break; case 3: if (REGNO (operands[4]) > REGNO (operands[5])) { tmp = operands[4]; operands[4] = operands[5]; operands[5] = tmp; } if (REGNO (operands[5]) > REGNO (operands[6])) { tmp = operands[5]; operands[5] = operands[6]; operands[6] = tmp; } if (REGNO (operands[4]) > REGNO (operands[5])) { tmp = operands[4]; operands[4] = operands[5]; operands[5] = tmp; } output_asm_insn ("ldmia\t%1!, {%4, %5, %6}", operands); output_asm_insn ("stmia\t%0!, {%4, %5, %6}", operands); break; default: gcc_unreachable (); } return ""; } /* Output a call-via instruction for thumb state. */ const char * thumb_call_via_reg (rtx reg) { int regno = REGNO (reg); rtx *labelp; gcc_assert (regno < LR_REGNUM); /* If we are in the normal text section we can use a single instance per compilation unit. If we are doing function sections, then we need an entry per section, since we can't rely on reachability. */ if (in_section == text_section) { thumb_call_reg_needed = 1; if (thumb_call_via_label[regno] == NULL) thumb_call_via_label[regno] = gen_label_rtx (); labelp = thumb_call_via_label + regno; } else { if (cfun->machine->call_via[regno] == NULL) cfun->machine->call_via[regno] = gen_label_rtx (); labelp = cfun->machine->call_via + regno; } output_asm_insn ("bl\t%a0", labelp); return ""; } /* Routines for generating rtl. */ void thumb_expand_movmemqi (rtx *operands) { rtx out = copy_to_mode_reg (SImode, XEXP (operands[0], 0)); rtx in = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); HOST_WIDE_INT len = INTVAL (operands[2]); HOST_WIDE_INT offset = 0; while (len >= 12) { emit_insn (gen_movmem12b (out, in, out, in)); len -= 12; } if (len >= 8) { emit_insn (gen_movmem8b (out, in, out, in)); len -= 8; } if (len >= 4) { rtx reg = gen_reg_rtx (SImode); emit_insn (gen_movsi (reg, gen_rtx_MEM (SImode, in))); emit_insn (gen_movsi (gen_rtx_MEM (SImode, out), reg)); len -= 4; offset += 4; } if (len >= 2) { rtx reg = gen_reg_rtx (HImode); emit_insn (gen_movhi (reg, gen_rtx_MEM (HImode, plus_constant (in, offset)))); emit_insn (gen_movhi (gen_rtx_MEM (HImode, plus_constant (out, offset)), reg)); len -= 2; offset += 2; } if (len) { rtx reg = gen_reg_rtx (QImode); emit_insn (gen_movqi (reg, gen_rtx_MEM (QImode, plus_constant (in, offset)))); emit_insn (gen_movqi (gen_rtx_MEM (QImode, plus_constant (out, offset)), reg)); } } void thumb_reload_out_hi (rtx *operands) { emit_insn (gen_thumb_movhi_clobber (operands[0], operands[1], operands[2])); } /* Handle reading a half-word from memory during reload. */ void thumb_reload_in_hi (rtx *operands ATTRIBUTE_UNUSED) { gcc_unreachable (); } /* Return the length of a function name prefix that starts with the character 'c'. */ static int arm_get_strip_length (int c) { switch (c) { ARM_NAME_ENCODING_LENGTHS default: return 0; } } /* Return a pointer to a function's name with any and all prefix encodings stripped from it. */ const char * arm_strip_name_encoding (const char *name) { int skip; while ((skip = arm_get_strip_length (* name))) name += skip; return name; } /* If there is a '*' anywhere in the name's prefix, then emit the stripped name verbatim, otherwise prepend an underscore if leading underscores are being used. */ void arm_asm_output_labelref (FILE *stream, const char *name) { int skip; int verbatim = 0; while ((skip = arm_get_strip_length (* name))) { verbatim |= (*name == '*'); name += skip; } if (verbatim) fputs (name, stream); else asm_fprintf (stream, "%U%s", name); } static void arm_file_start (void) { int val; if (TARGET_BPABI) { const char *fpu_name; if (arm_select[0].string) asm_fprintf (asm_out_file, "\t.cpu %s\n", arm_select[0].string); else if (arm_select[1].string) asm_fprintf (asm_out_file, "\t.arch %s\n", arm_select[1].string); else asm_fprintf (asm_out_file, "\t.cpu %s\n", all_cores[arm_default_cpu].name); if (TARGET_SOFT_FLOAT) { if (TARGET_VFP) fpu_name = "softvfp"; else fpu_name = "softfpa"; } else { switch (arm_fpu_arch) { case FPUTYPE_FPA: fpu_name = "fpa"; break; case FPUTYPE_FPA_EMU2: fpu_name = "fpe2"; break; case FPUTYPE_FPA_EMU3: fpu_name = "fpe3"; break; case FPUTYPE_MAVERICK: fpu_name = "maverick"; break; case FPUTYPE_VFP: if (TARGET_HARD_FLOAT) asm_fprintf (asm_out_file, "\t.eabi_attribute 27, 3\n"); if (TARGET_HARD_FLOAT_ABI) asm_fprintf (asm_out_file, "\t.eabi_attribute 28, 1\n"); fpu_name = "vfp"; break; default: abort(); } } asm_fprintf (asm_out_file, "\t.fpu %s\n", fpu_name); /* Some of these attributes only apply when the corresponding features are used. However we don't have any easy way of figuring this out. Conservatively record the setting that would have been used. */ /* Tag_ABI_PCS_wchar_t. */ asm_fprintf (asm_out_file, "\t.eabi_attribute 18, %d\n", (int)WCHAR_TYPE_SIZE / BITS_PER_UNIT); /* Tag_ABI_FP_rounding. */ if (flag_rounding_math) asm_fprintf (asm_out_file, "\t.eabi_attribute 19, 1\n"); if (!flag_unsafe_math_optimizations) { /* Tag_ABI_FP_denomal. */ asm_fprintf (asm_out_file, "\t.eabi_attribute 20, 1\n"); /* Tag_ABI_FP_exceptions. */ asm_fprintf (asm_out_file, "\t.eabi_attribute 21, 1\n"); } /* Tag_ABI_FP_user_exceptions. */ if (flag_signaling_nans) asm_fprintf (asm_out_file, "\t.eabi_attribute 22, 1\n"); /* Tag_ABI_FP_number_model. */ asm_fprintf (asm_out_file, "\t.eabi_attribute 23, %d\n", flag_finite_math_only ? 1 : 3); /* Tag_ABI_align8_needed. */ asm_fprintf (asm_out_file, "\t.eabi_attribute 24, 1\n"); /* Tag_ABI_align8_preserved. */ asm_fprintf (asm_out_file, "\t.eabi_attribute 25, 1\n"); /* Tag_ABI_enum_size. */ asm_fprintf (asm_out_file, "\t.eabi_attribute 26, %d\n", flag_short_enums ? 1 : 2); /* Tag_ABI_optimization_goals. */ if (optimize_size) val = 4; else if (optimize >= 2) val = 2; else if (optimize) val = 1; else val = 6; asm_fprintf (asm_out_file, "\t.eabi_attribute 30, %d\n", val); } default_file_start(); } static void arm_file_end (void) { int regno; if (! thumb_call_reg_needed) return; switch_to_section (text_section); asm_fprintf (asm_out_file, "\t.code 16\n"); ASM_OUTPUT_ALIGN (asm_out_file, 1); for (regno = 0; regno < LR_REGNUM; regno++) { rtx label = thumb_call_via_label[regno]; if (label != 0) { targetm.asm_out.internal_label (asm_out_file, "L", CODE_LABEL_NUMBER (label)); asm_fprintf (asm_out_file, "\tbx\t%r\n", regno); } } } rtx aof_pic_label; #ifdef AOF_ASSEMBLER /* Special functions only needed when producing AOF syntax assembler. */ struct pic_chain { struct pic_chain * next; const char * symname; }; static struct pic_chain * aof_pic_chain = NULL; rtx aof_pic_entry (rtx x) { struct pic_chain ** chainp; int offset; if (aof_pic_label == NULL_RTX) { aof_pic_label = gen_rtx_SYMBOL_REF (Pmode, "x$adcons"); } for (offset = 0, chainp = &aof_pic_chain; *chainp; offset += 4, chainp = &(*chainp)->next) if ((*chainp)->symname == XSTR (x, 0)) return plus_constant (aof_pic_label, offset); *chainp = (struct pic_chain *) xmalloc (sizeof (struct pic_chain)); (*chainp)->next = NULL; (*chainp)->symname = XSTR (x, 0); return plus_constant (aof_pic_label, offset); } void aof_dump_pic_table (FILE *f) { struct pic_chain * chain; if (aof_pic_chain == NULL) return; asm_fprintf (f, "\tAREA |%r$$adcons|, BASED %r\n", PIC_OFFSET_TABLE_REGNUM, PIC_OFFSET_TABLE_REGNUM); fputs ("|x$adcons|\n", f); for (chain = aof_pic_chain; chain; chain = chain->next) { fputs ("\tDCD\t", f); assemble_name (f, chain->symname); fputs ("\n", f); } } int arm_text_section_count = 1; /* A get_unnamed_section callback for switching to the text section. */ static void aof_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED) { fprintf (asm_out_file, "\tAREA |C$$code%d|, CODE, READONLY", arm_text_section_count++); if (flag_pic) fprintf (asm_out_file, ", PIC, REENTRANT"); fprintf (asm_out_file, "\n"); } static int arm_data_section_count = 1; /* A get_unnamed_section callback for switching to the data section. */ static void aof_output_data_section_asm_op (const void *data ATTRIBUTE_UNUSED) { fprintf (asm_out_file, "\tAREA |C$$data%d|, DATA\n", arm_data_section_count++); } /* Implement TARGET_ASM_INIT_SECTIONS. AOF Assembler syntax is a nightmare when it comes to areas, since once we change from one area to another, we can't go back again. Instead, we must create a new area with the same attributes and add the new output to that. Unfortunately, there is nothing we can do here to guarantee that two areas with the same attributes will be linked adjacently in the resulting executable, so we have to be careful not to do pc-relative addressing across such boundaries. */ static void aof_asm_init_sections (void) { text_section = get_unnamed_section (SECTION_CODE, aof_output_text_section_asm_op, NULL); data_section = get_unnamed_section (SECTION_WRITE, aof_output_data_section_asm_op, NULL); readonly_data_section = text_section; } void zero_init_section (void) { static int zero_init_count = 1; fprintf (asm_out_file, "\tAREA |C$$zidata%d|,NOINIT\n", zero_init_count++); in_section = NULL; } /* The AOF assembler is religiously strict about declarations of imported and exported symbols, so that it is impossible to declare a function as imported near the beginning of the file, and then to export it later on. It is, however, possible to delay the decision until all the functions in the file have been compiled. To get around this, we maintain a list of the imports and exports, and delete from it any that are subsequently defined. At the end of compilation we spit the remainder of the list out before the END directive. */ struct import { struct import * next; const char * name; }; static struct import * imports_list = NULL; void aof_add_import (const char *name) { struct import * new; for (new = imports_list; new; new = new->next) if (new->name == name) return; new = (struct import *) xmalloc (sizeof (struct import)); new->next = imports_list; imports_list = new; new->name = name; } void aof_delete_import (const char *name) { struct import ** old; for (old = &imports_list; *old; old = & (*old)->next) { if ((*old)->name == name) { *old = (*old)->next; return; } } } int arm_main_function = 0; static void aof_dump_imports (FILE *f) { /* The AOF assembler needs this to cause the startup code to be extracted from the library. Brining in __main causes the whole thing to work automagically. */ if (arm_main_function) { switch_to_section (text_section); fputs ("\tIMPORT __main\n", f); fputs ("\tDCD __main\n", f); } /* Now dump the remaining imports. */ while (imports_list) { fprintf (f, "\tIMPORT\t"); assemble_name (f, imports_list->name); fputc ('\n', f); imports_list = imports_list->next; } } static void aof_globalize_label (FILE *stream, const char *name) { default_globalize_label (stream, name); if (! strcmp (name, "main")) arm_main_function = 1; } static void aof_file_start (void) { fputs ("__r0\tRN\t0\n", asm_out_file); fputs ("__a1\tRN\t0\n", asm_out_file); fputs ("__a2\tRN\t1\n", asm_out_file); fputs ("__a3\tRN\t2\n", asm_out_file); fputs ("__a4\tRN\t3\n", asm_out_file); fputs ("__v1\tRN\t4\n", asm_out_file); fputs ("__v2\tRN\t5\n", asm_out_file); fputs ("__v3\tRN\t6\n", asm_out_file); fputs ("__v4\tRN\t7\n", asm_out_file); fputs ("__v5\tRN\t8\n", asm_out_file); fputs ("__v6\tRN\t9\n", asm_out_file); fputs ("__sl\tRN\t10\n", asm_out_file); fputs ("__fp\tRN\t11\n", asm_out_file); fputs ("__ip\tRN\t12\n", asm_out_file); fputs ("__sp\tRN\t13\n", asm_out_file); fputs ("__lr\tRN\t14\n", asm_out_file); fputs ("__pc\tRN\t15\n", asm_out_file); fputs ("__f0\tFN\t0\n", asm_out_file); fputs ("__f1\tFN\t1\n", asm_out_file); fputs ("__f2\tFN\t2\n", asm_out_file); fputs ("__f3\tFN\t3\n", asm_out_file); fputs ("__f4\tFN\t4\n", asm_out_file); fputs ("__f5\tFN\t5\n", asm_out_file); fputs ("__f6\tFN\t6\n", asm_out_file); fputs ("__f7\tFN\t7\n", asm_out_file); switch_to_section (text_section); } static void aof_file_end (void) { if (flag_pic) aof_dump_pic_table (asm_out_file); arm_file_end (); aof_dump_imports (asm_out_file); fputs ("\tEND\n", asm_out_file); } #endif /* AOF_ASSEMBLER */ #ifndef ARM_PE /* Symbols in the text segment can be accessed without indirecting via the constant pool; it may take an extra binary operation, but this is still faster than indirecting via memory. Don't do this when not optimizing, since we won't be calculating al of the offsets necessary to do this simplification. */ static void arm_encode_section_info (tree decl, rtx rtl, int first) { /* This doesn't work with AOF syntax, since the string table may be in a different AREA. */ #ifndef AOF_ASSEMBLER if (optimize > 0 && TREE_CONSTANT (decl)) SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; #endif /* If we are referencing a function that is weak then encode a long call flag in the function name, otherwise if the function is static or or known to be defined in this file then encode a short call flag. */ if (first && DECL_P (decl)) { if (TREE_CODE (decl) == FUNCTION_DECL && DECL_WEAK (decl)) arm_encode_call_attribute (decl, LONG_CALL_FLAG_CHAR); else if (! TREE_PUBLIC (decl)) arm_encode_call_attribute (decl, SHORT_CALL_FLAG_CHAR); } default_encode_section_info (decl, rtl, first); } #endif /* !ARM_PE */ static void arm_internal_label (FILE *stream, const char *prefix, unsigned long labelno) { if (arm_ccfsm_state == 3 && (unsigned) arm_target_label == labelno && !strcmp (prefix, "L")) { arm_ccfsm_state = 0; arm_target_insn = NULL; } default_internal_label (stream, prefix, labelno); } /* Output code to add DELTA to the first argument, and then jump to FUNCTION. Used for C++ multiple inheritance. */ static void arm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED, tree function) { static int thunk_label = 0; char label[256]; char labelpc[256]; int mi_delta = delta; const char *const mi_op = mi_delta < 0 ? "sub" : "add"; int shift = 0; int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function) ? 1 : 0); if (mi_delta < 0) mi_delta = - mi_delta; if (TARGET_THUMB) { int labelno = thunk_label++; ASM_GENERATE_INTERNAL_LABEL (label, "LTHUMBFUNC", labelno); fputs ("\tldr\tr12, ", file); assemble_name (file, label); fputc ('\n', file); if (flag_pic) { /* If we are generating PIC, the ldr instruction below loads "(target - 7) - .LTHUNKPCn" into r12. The pc reads as the address of the add + 8, so we have: r12 = (target - 7) - .LTHUNKPCn + (.LTHUNKPCn + 8) = target + 1. Note that we have "+ 1" because some versions of GNU ld don't set the low bit of the result for R_ARM_REL32 relocations against thumb function symbols. */ ASM_GENERATE_INTERNAL_LABEL (labelpc, "LTHUNKPC", labelno); assemble_name (file, labelpc); fputs (":\n", file); fputs ("\tadd\tr12, pc, r12\n", file); } } while (mi_delta != 0) { if ((mi_delta & (3 << shift)) == 0) shift += 2; else { asm_fprintf (file, "\t%s\t%r, %r, #%d\n", mi_op, this_regno, this_regno, mi_delta & (0xff << shift)); mi_delta &= ~(0xff << shift); shift += 8; } } if (TARGET_THUMB) { fprintf (file, "\tbx\tr12\n"); ASM_OUTPUT_ALIGN (file, 2); assemble_name (file, label); fputs (":\n", file); if (flag_pic) { /* Output ".word .LTHUNKn-7-.LTHUNKPCn". */ rtx tem = XEXP (DECL_RTL (function), 0); tem = gen_rtx_PLUS (GET_MODE (tem), tem, GEN_INT (-7)); tem = gen_rtx_MINUS (GET_MODE (tem), tem, gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (labelpc))); assemble_integer (tem, 4, BITS_PER_WORD, 1); } else /* Output ".word .LTHUNKn". */ assemble_integer (XEXP (DECL_RTL (function), 0), 4, BITS_PER_WORD, 1); } else { fputs ("\tb\t", file); assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0)); if (NEED_PLT_RELOC) fputs ("(PLT)", file); fputc ('\n', file); } } int arm_emit_vector_const (FILE *file, rtx x) { int i; const char * pattern; gcc_assert (GET_CODE (x) == CONST_VECTOR); switch (GET_MODE (x)) { case V2SImode: pattern = "%08x"; break; case V4HImode: pattern = "%04x"; break; case V8QImode: pattern = "%02x"; break; default: gcc_unreachable (); } fprintf (file, "0x"); for (i = CONST_VECTOR_NUNITS (x); i--;) { rtx element; element = CONST_VECTOR_ELT (x, i); fprintf (file, pattern, INTVAL (element)); } return 1; } const char * arm_output_load_gr (rtx *operands) { rtx reg; rtx offset; rtx wcgr; rtx sum; if (GET_CODE (operands [1]) != MEM || GET_CODE (sum = XEXP (operands [1], 0)) != PLUS || GET_CODE (reg = XEXP (sum, 0)) != REG || GET_CODE (offset = XEXP (sum, 1)) != CONST_INT || ((INTVAL (offset) < 1024) && (INTVAL (offset) > -1024))) return "wldrw%?\t%0, %1"; /* Fix up an out-of-range load of a GR register. */ output_asm_insn ("str%?\t%0, [sp, #-4]!\t@ Start of GR load expansion", & reg); wcgr = operands[0]; operands[0] = reg; output_asm_insn ("ldr%?\t%0, %1", operands); operands[0] = wcgr; operands[1] = reg; output_asm_insn ("tmcr%?\t%0, %1", operands); output_asm_insn ("ldr%?\t%0, [sp], #4\t@ End of GR load expansion", & reg); return ""; } /* Worker function for TARGET_SETUP_INCOMING_VARARGS. On the ARM, PRETEND_SIZE is set in order to have the prologue push the last named arg and all anonymous args onto the stack. XXX I know the prologue shouldn't be pushing registers, but it is faster that way. */ static void arm_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED, int *pretend_size, int second_time ATTRIBUTE_UNUSED) { cfun->machine->uses_anonymous_args = 1; if (cum->nregs < NUM_ARG_REGS) *pretend_size = (NUM_ARG_REGS - cum->nregs) * UNITS_PER_WORD; } /* Return nonzero if the CONSUMER instruction (a store) does not need PRODUCER's value to calculate the address. */ int arm_no_early_store_addr_dep (rtx producer, rtx consumer) { rtx value = PATTERN (producer); rtx addr = PATTERN (consumer); if (GET_CODE (value) == COND_EXEC) value = COND_EXEC_CODE (value); if (GET_CODE (value) == PARALLEL) value = XVECEXP (value, 0, 0); value = XEXP (value, 0); if (GET_CODE (addr) == COND_EXEC) addr = COND_EXEC_CODE (addr); if (GET_CODE (addr) == PARALLEL) addr = XVECEXP (addr, 0, 0); addr = XEXP (addr, 0); return !reg_overlap_mentioned_p (value, addr); } /* Return nonzero if the CONSUMER instruction (an ALU op) does not have an early register shift value or amount dependency on the result of PRODUCER. */ int arm_no_early_alu_shift_dep (rtx producer, rtx consumer) { rtx value = PATTERN (producer); rtx op = PATTERN (consumer); rtx early_op; if (GET_CODE (value) == COND_EXEC) value = COND_EXEC_CODE (value); if (GET_CODE (value) == PARALLEL) value = XVECEXP (value, 0, 0); value = XEXP (value, 0); if (GET_CODE (op) == COND_EXEC) op = COND_EXEC_CODE (op); if (GET_CODE (op) == PARALLEL) op = XVECEXP (op, 0, 0); op = XEXP (op, 1); early_op = XEXP (op, 0); /* This is either an actual independent shift, or a shift applied to the first operand of another operation. We want the whole shift operation. */ if (GET_CODE (early_op) == REG) early_op = op; return !reg_overlap_mentioned_p (value, early_op); } /* Return nonzero if the CONSUMER instruction (an ALU op) does not have an early register shift value dependency on the result of PRODUCER. */ int arm_no_early_alu_shift_value_dep (rtx producer, rtx consumer) { rtx value = PATTERN (producer); rtx op = PATTERN (consumer); rtx early_op; if (GET_CODE (value) == COND_EXEC) value = COND_EXEC_CODE (value); if (GET_CODE (value) == PARALLEL) value = XVECEXP (value, 0, 0); value = XEXP (value, 0); if (GET_CODE (op) == COND_EXEC) op = COND_EXEC_CODE (op); if (GET_CODE (op) == PARALLEL) op = XVECEXP (op, 0, 0); op = XEXP (op, 1); early_op = XEXP (op, 0); /* This is either an actual independent shift, or a shift applied to the first operand of another operation. We want the value being shifted, in either case. */ if (GET_CODE (early_op) != REG) early_op = XEXP (early_op, 0); return !reg_overlap_mentioned_p (value, early_op); } /* Return nonzero if the CONSUMER (a mul or mac op) does not have an early register mult dependency on the result of PRODUCER. */ int arm_no_early_mul_dep (rtx producer, rtx consumer) { rtx value = PATTERN (producer); rtx op = PATTERN (consumer); if (GET_CODE (value) == COND_EXEC) value = COND_EXEC_CODE (value); if (GET_CODE (value) == PARALLEL) value = XVECEXP (value, 0, 0); value = XEXP (value, 0); if (GET_CODE (op) == COND_EXEC) op = COND_EXEC_CODE (op); if (GET_CODE (op) == PARALLEL) op = XVECEXP (op, 0, 0); op = XEXP (op, 1); return (GET_CODE (op) == PLUS && !reg_overlap_mentioned_p (value, XEXP (op, 0))); } /* We can't rely on the caller doing the proper promotion when using APCS or ATPCS. */ static bool arm_promote_prototypes (tree t ATTRIBUTE_UNUSED) { return !TARGET_AAPCS_BASED; } /* AAPCS based ABIs use short enums by default. */ static bool arm_default_short_enums (void) { return TARGET_AAPCS_BASED && arm_abi != ARM_ABI_AAPCS_LINUX; } /* AAPCS requires that anonymous bitfields affect structure alignment. */ static bool arm_align_anon_bitfield (void) { return TARGET_AAPCS_BASED; } /* The generic C++ ABI says 64-bit (long long). The EABI says 32-bit. */ static tree arm_cxx_guard_type (void) { return TARGET_AAPCS_BASED ? integer_type_node : long_long_integer_type_node; } /* The EABI says test the least significant bit of a guard variable. */ static bool arm_cxx_guard_mask_bit (void) { return TARGET_AAPCS_BASED; } /* The EABI specifies that all array cookies are 8 bytes long. */ static tree arm_get_cookie_size (tree type) { tree size; if (!TARGET_AAPCS_BASED) return default_cxx_get_cookie_size (type); size = build_int_cst (sizetype, 8); return size; } /* The EABI says that array cookies should also contain the element size. */ static bool arm_cookie_has_size (void) { return TARGET_AAPCS_BASED; } /* The EABI says constructors and destructors should return a pointer to the object constructed/destroyed. */ static bool arm_cxx_cdtor_returns_this (void) { return TARGET_AAPCS_BASED; } /* The EABI says that an inline function may never be the key method. */ static bool arm_cxx_key_method_may_be_inline (void) { return !TARGET_AAPCS_BASED; } static void arm_cxx_determine_class_data_visibility (tree decl) { if (!TARGET_AAPCS_BASED) return; /* In general, \S 3.2.5.5 of the ARM EABI requires that class data is exported. However, on systems without dynamic vague linkage, \S 3.2.5.6 says that COMDAT class data has hidden linkage. */ if (!TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P && DECL_COMDAT (decl)) DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; else DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; DECL_VISIBILITY_SPECIFIED (decl) = 1; } static bool arm_cxx_class_data_always_comdat (void) { /* \S 3.2.5.4 of the ARM C++ ABI says that class data only have vague linkage if the class has no key function. */ return !TARGET_AAPCS_BASED; } /* The EABI says __aeabi_atexit should be used to register static destructors. */ static bool arm_cxx_use_aeabi_atexit (void) { return TARGET_AAPCS_BASED; } void arm_set_return_address (rtx source, rtx scratch) { arm_stack_offsets *offsets; HOST_WIDE_INT delta; rtx addr; unsigned long saved_regs; saved_regs = arm_compute_save_reg_mask (); if ((saved_regs & (1 << LR_REGNUM)) == 0) emit_move_insn (gen_rtx_REG (Pmode, LR_REGNUM), source); else { if (frame_pointer_needed) addr = plus_constant(hard_frame_pointer_rtx, -4); else { /* LR will be the first saved register. */ offsets = arm_get_frame_offsets (); delta = offsets->outgoing_args - (offsets->frame + 4); if (delta >= 4096) { emit_insn (gen_addsi3 (scratch, stack_pointer_rtx, GEN_INT (delta & ~4095))); addr = scratch; delta &= 4095; } else addr = stack_pointer_rtx; addr = plus_constant (addr, delta); } emit_move_insn (gen_frame_mem (Pmode, addr), source); } } void thumb_set_return_address (rtx source, rtx scratch) { arm_stack_offsets *offsets; HOST_WIDE_INT delta; int reg; rtx addr; unsigned long mask; emit_insn (gen_rtx_USE (VOIDmode, source)); mask = thumb_compute_save_reg_mask (); if (mask & (1 << LR_REGNUM)) { offsets = arm_get_frame_offsets (); /* Find the saved regs. */ if (frame_pointer_needed) { delta = offsets->soft_frame - offsets->saved_args; reg = THUMB_HARD_FRAME_POINTER_REGNUM; } else { delta = offsets->outgoing_args - offsets->saved_args; reg = SP_REGNUM; } /* Allow for the stack frame. */ if (TARGET_BACKTRACE) delta -= 16; /* The link register is always the first saved register. */ delta -= 4; /* Construct the address. */ addr = gen_rtx_REG (SImode, reg); if ((reg != SP_REGNUM && delta >= 128) || delta >= 1024) { emit_insn (gen_movsi (scratch, GEN_INT (delta))); emit_insn (gen_addsi3 (scratch, scratch, stack_pointer_rtx)); addr = scratch; } else addr = plus_constant (addr, delta); emit_move_insn (gen_frame_mem (Pmode, addr), source); } else emit_move_insn (gen_rtx_REG (Pmode, LR_REGNUM), source); } /* Implements target hook vector_mode_supported_p. */ bool arm_vector_mode_supported_p (enum machine_mode mode) { if ((mode == V2SImode) || (mode == V4HImode) || (mode == V8QImode)) return true; return false; } /* Implement TARGET_SHIFT_TRUNCATION_MASK. SImode shifts use normal ARM insns and therefore guarantee that the shift count is modulo 256. DImode shifts (those implemented by lib1funcs.asm or by optabs.c) guarantee no particular behavior for out-of-range counts. */ static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode mode) { return mode == SImode ? 255 : 0; } /* Map internal gcc register numbers to DWARF2 register numbers. */ unsigned int arm_dbx_register_number (unsigned int regno) { if (regno < 16) return regno; /* TODO: Legacy targets output FPA regs as registers 16-23 for backwards compatibility. The EABI defines them as registers 96-103. */ if (IS_FPA_REGNUM (regno)) return (TARGET_AAPCS_BASED ? 96 : 16) + regno - FIRST_FPA_REGNUM; if (IS_VFP_REGNUM (regno)) return 64 + regno - FIRST_VFP_REGNUM; if (IS_IWMMXT_GR_REGNUM (regno)) return 104 + regno - FIRST_IWMMXT_GR_REGNUM; if (IS_IWMMXT_REGNUM (regno)) return 112 + regno - FIRST_IWMMXT_REGNUM; gcc_unreachable (); } #ifdef TARGET_UNWIND_INFO /* Emit unwind directives for a store-multiple instruction. This should only ever be generated by the function prologue code, so we expect it to have a particular form. */ static void arm_unwind_emit_stm (FILE * asm_out_file, rtx p) { int i; HOST_WIDE_INT offset; HOST_WIDE_INT nregs; int reg_size; unsigned reg; unsigned lastreg; rtx e; /* First insn will adjust the stack pointer. */ e = XVECEXP (p, 0, 0); if (GET_CODE (e) != SET || GET_CODE (XEXP (e, 0)) != REG || REGNO (XEXP (e, 0)) != SP_REGNUM || GET_CODE (XEXP (e, 1)) != PLUS) abort (); offset = -INTVAL (XEXP (XEXP (e, 1), 1)); nregs = XVECLEN (p, 0) - 1; reg = REGNO (XEXP (XVECEXP (p, 0, 1), 1)); if (reg < 16) { /* The function prologue may also push pc, but not annotate it as it is never restored. We turn this into a stack pointer adjustment. */ if (nregs * 4 == offset - 4) { fprintf (asm_out_file, "\t.pad #4\n"); offset -= 4; } reg_size = 4; } else if (IS_VFP_REGNUM (reg)) { /* FPA register saves use an additional word. */ offset -= 4; reg_size = 8; } else if (reg >= FIRST_FPA_REGNUM && reg <= LAST_FPA_REGNUM) { /* FPA registers are done differently. */ asm_fprintf (asm_out_file, "\t.save %r, %wd\n", reg, nregs); return; } else /* Unknown register type. */ abort (); /* If the stack increment doesn't match the size of the saved registers, something has gone horribly wrong. */ if (offset != nregs * reg_size) abort (); fprintf (asm_out_file, "\t.save {"); offset = 0; lastreg = 0; /* The remaining insns will describe the stores. */ for (i = 1; i <= nregs; i++) { /* Expect (set (mem ) (reg)). Where is (reg:SP) or (plus (reg:SP) (const_int)). */ e = XVECEXP (p, 0, i); if (GET_CODE (e) != SET || GET_CODE (XEXP (e, 0)) != MEM || GET_CODE (XEXP (e, 1)) != REG) abort (); reg = REGNO (XEXP (e, 1)); if (reg < lastreg) abort (); if (i != 1) fprintf (asm_out_file, ", "); /* We can't use %r for vfp because we need to use the double precision register names. */ if (IS_VFP_REGNUM (reg)) asm_fprintf (asm_out_file, "d%d", (reg - FIRST_VFP_REGNUM) / 2); else asm_fprintf (asm_out_file, "%r", reg); #ifdef ENABLE_CHECKING /* Check that the addresses are consecutive. */ e = XEXP (XEXP (e, 0), 0); if (GET_CODE (e) == PLUS) { offset += reg_size; if (GET_CODE (XEXP (e, 0)) != REG || REGNO (XEXP (e, 0)) != SP_REGNUM || GET_CODE (XEXP (e, 1)) != CONST_INT || offset != INTVAL (XEXP (e, 1))) abort (); } else if (i != 1 || GET_CODE (e) != REG || REGNO (e) != SP_REGNUM) abort (); #endif } fprintf (asm_out_file, "}\n"); } /* Emit unwind directives for a SET. */ static void arm_unwind_emit_set (FILE * asm_out_file, rtx p) { rtx e0; rtx e1; e0 = XEXP (p, 0); e1 = XEXP (p, 1); switch (GET_CODE (e0)) { case MEM: /* Pushing a single register. */ if (GET_CODE (XEXP (e0, 0)) != PRE_DEC || GET_CODE (XEXP (XEXP (e0, 0), 0)) != REG || REGNO (XEXP (XEXP (e0, 0), 0)) != SP_REGNUM) abort (); asm_fprintf (asm_out_file, "\t.save "); if (IS_VFP_REGNUM (REGNO (e1))) asm_fprintf(asm_out_file, "{d%d}\n", (REGNO (e1) - FIRST_VFP_REGNUM) / 2); else asm_fprintf(asm_out_file, "{%r}\n", REGNO (e1)); break; case REG: if (REGNO (e0) == SP_REGNUM) { /* A stack increment. */ if (GET_CODE (e1) != PLUS || GET_CODE (XEXP (e1, 0)) != REG || REGNO (XEXP (e1, 0)) != SP_REGNUM || GET_CODE (XEXP (e1, 1)) != CONST_INT) abort (); asm_fprintf (asm_out_file, "\t.pad #%wd\n", -INTVAL (XEXP (e1, 1))); } else if (REGNO (e0) == HARD_FRAME_POINTER_REGNUM) { HOST_WIDE_INT offset; unsigned reg; if (GET_CODE (e1) == PLUS) { if (GET_CODE (XEXP (e1, 0)) != REG || GET_CODE (XEXP (e1, 1)) != CONST_INT) abort (); reg = REGNO (XEXP (e1, 0)); offset = INTVAL (XEXP (e1, 1)); asm_fprintf (asm_out_file, "\t.setfp %r, %r, #%wd\n", HARD_FRAME_POINTER_REGNUM, reg, INTVAL (XEXP (e1, 1))); } else if (GET_CODE (e1) == REG) { reg = REGNO (e1); asm_fprintf (asm_out_file, "\t.setfp %r, %r\n", HARD_FRAME_POINTER_REGNUM, reg); } else abort (); } else if (GET_CODE (e1) == REG && REGNO (e1) == SP_REGNUM) { /* Move from sp to reg. */ asm_fprintf (asm_out_file, "\t.movsp %r\n", REGNO (e0)); } else if (GET_CODE (e1) == PLUS && GET_CODE (XEXP (e1, 0)) == REG && REGNO (XEXP (e1, 0)) == SP_REGNUM && GET_CODE (XEXP (e1, 1)) == CONST_INT) { /* Set reg to offset from sp. */ asm_fprintf (asm_out_file, "\t.movsp %r, #%d\n", REGNO (e0), (int)INTVAL(XEXP (e1, 1))); } else abort (); break; default: abort (); } } /* Emit unwind directives for the given insn. */ static void arm_unwind_emit (FILE * asm_out_file, rtx insn) { rtx pat; if (!ARM_EABI_UNWIND_TABLES) return; if (GET_CODE (insn) == NOTE || !RTX_FRAME_RELATED_P (insn)) return; pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX); if (pat) pat = XEXP (pat, 0); else pat = PATTERN (insn); switch (GET_CODE (pat)) { case SET: arm_unwind_emit_set (asm_out_file, pat); break; case SEQUENCE: /* Store multiple. */ arm_unwind_emit_stm (asm_out_file, pat); break; default: abort(); } } /* Output a reference from a function exception table to the type_info object X. The EABI specifies that the symbol should be relocated by an R_ARM_TARGET2 relocation. */ static bool arm_output_ttype (rtx x) { fputs ("\t.word\t", asm_out_file); output_addr_const (asm_out_file, x); /* Use special relocations for symbol references. */ if (GET_CODE (x) != CONST_INT) fputs ("(TARGET2)", asm_out_file); fputc ('\n', asm_out_file); return TRUE; } #endif /* TARGET_UNWIND_INFO */ /* Output unwind directives for the start/end of a function. */ void arm_output_fn_unwind (FILE * f, bool prologue) { if (!ARM_EABI_UNWIND_TABLES) return; if (prologue) fputs ("\t.fnstart\n", f); else fputs ("\t.fnend\n", f); } static bool arm_emit_tls_decoration (FILE *fp, rtx x) { enum tls_reloc reloc; rtx val; val = XVECEXP (x, 0, 0); reloc = INTVAL (XVECEXP (x, 0, 1)); output_addr_const (fp, val); switch (reloc) { case TLS_GD32: fputs ("(tlsgd)", fp); break; case TLS_LDM32: fputs ("(tlsldm)", fp); break; case TLS_LDO32: fputs ("(tlsldo)", fp); break; case TLS_IE32: fputs ("(gottpoff)", fp); break; case TLS_LE32: fputs ("(tpoff)", fp); break; default: gcc_unreachable (); } switch (reloc) { case TLS_GD32: case TLS_LDM32: case TLS_IE32: fputs (" + (. - ", fp); output_addr_const (fp, XVECEXP (x, 0, 2)); fputs (" - ", fp); output_addr_const (fp, XVECEXP (x, 0, 3)); fputc (')', fp); break; default: break; } return TRUE; } bool arm_output_addr_const_extra (FILE *fp, rtx x) { if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS) return arm_emit_tls_decoration (fp, x); else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_PIC_LABEL) { char label[256]; int labelno = INTVAL (XVECEXP (x, 0, 0)); ASM_GENERATE_INTERNAL_LABEL (label, "LPIC", labelno); assemble_name_raw (fp, label); return TRUE; } else if (GET_CODE (x) == CONST_VECTOR) return arm_emit_vector_const (fp, x); return FALSE; } #include "gt-arm.h" Index: projects/sendfile/contrib/gcc =================================================================== --- projects/sendfile/contrib/gcc (revision 276056) +++ projects/sendfile/contrib/gcc (revision 276057) Property changes on: projects/sendfile/contrib/gcc ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/contrib/gcc:r275989-276056 Index: projects/sendfile/contrib/netbsd-tests/lib/libc/stdlib/t_hsearch.c =================================================================== --- projects/sendfile/contrib/netbsd-tests/lib/libc/stdlib/t_hsearch.c (revision 276056) +++ projects/sendfile/contrib/netbsd-tests/lib/libc/stdlib/t_hsearch.c (revision 276057) @@ -1,407 +1,411 @@ /* $NetBSD: t_hsearch.c,v 1.4 2014/07/20 20:17:21 christos Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. */ /* * Copyright (c) 2001 Christopher G. Demetriou * 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 for the * NetBSD Project. See http://www.NetBSD.org/ for * information about NetBSD. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 __COPYRIGHT("@(#) Copyright (c) 2008\ The NetBSD Foundation, inc. All rights reserved."); __RCSID("$NetBSD: t_hsearch.c,v 1.4 2014/07/20 20:17:21 christos Exp $"); #include #include #include #include #include #include #define REQUIRE_ERRNO(x) ATF_REQUIRE_MSG(x, "%s", strerror(errno)) #ifdef __NetBSD__ ATF_TC(hsearch_basic); ATF_TC_HEAD(hsearch_basic, tc) { atf_tc_set_md_var(tc, "descr", "Checks basic insertions and searching"); } ATF_TC_BODY(hsearch_basic, tc) { ENTRY e, *ep; char ch[2]; int i; REQUIRE_ERRNO(hcreate(16) != 0); /* ch[1] should be constant from here on down. */ ch[1] = '\0'; /* Basic insertions. Check enough that there'll be collisions. */ for (i = 0; i < 26; i++) { ch[0] = 'a' + i; e.key = strdup(ch); /* ptr to provided key is kept! */ ATF_REQUIRE(e.key != NULL); e.data = (void *)(intptr_t)i; ep = hsearch(e, ENTER); ATF_REQUIRE(ep != NULL); ATF_REQUIRE_STREQ(ep->key, ch); ATF_REQUIRE_EQ((intptr_t)ep->data, i); } /* e.key should be constant from here on down. */ e.key = ch; /* Basic lookups. */ for (i = 0; i < 26; i++) { ch[0] = 'a' + i; ep = hsearch(e, FIND); ATF_REQUIRE(ep != NULL); ATF_REQUIRE_STREQ(ep->key, ch); ATF_REQUIRE_EQ((intptr_t)ep->data, i); } hdestroy1(free, NULL); } #endif ATF_TC(hsearch_duplicate); ATF_TC_HEAD(hsearch_duplicate, tc) { atf_tc_set_md_var(tc, "descr", "Checks that inserting duplicate " "doesn't overwrite existing data"); } ATF_TC_BODY(hsearch_duplicate, tc) { ENTRY e, *ep; REQUIRE_ERRNO(hcreate(16)); e.key = __UNCONST("a"); e.data = (void *)(intptr_t) 0; ep = hsearch(e, ENTER); ATF_REQUIRE(ep != NULL); ATF_REQUIRE_STREQ(ep->key, "a"); ATF_REQUIRE_EQ((intptr_t)ep->data, 0); e.data = (void *)(intptr_t)12345; ep = hsearch(e, ENTER); ep = hsearch(e, FIND); ATF_REQUIRE(ep != NULL); ATF_REQUIRE_STREQ(ep->key, "a"); ATF_REQUIRE_EQ((intptr_t)ep->data, 0); hdestroy(); } ATF_TC(hsearch_nonexistent); ATF_TC_HEAD(hsearch_nonexistent, tc) { atf_tc_set_md_var(tc, "descr", "Checks searching for non-existent entry"); } ATF_TC_BODY(hsearch_nonexistent, tc) { ENTRY e, *ep; REQUIRE_ERRNO(hcreate(16)); e.key = __UNCONST("A"); ep = hsearch(e, FIND); ATF_REQUIRE_EQ(ep, NULL); hdestroy(); } ATF_TC(hsearch_two); ATF_TC_HEAD(hsearch_two, tc) { atf_tc_set_md_var(tc, "descr", "Checks that searching doesn't overwrite previous search results"); } ATF_TC_BODY(hsearch_two, tc) { ENTRY e, *ep, *ep2; REQUIRE_ERRNO(hcreate(16)); e.key = __UNCONST("a"); e.data = (void*)(intptr_t)0; ep = hsearch(e, ENTER); ATF_REQUIRE(ep != NULL); ATF_REQUIRE_STREQ(ep->key, "a"); ATF_REQUIRE_EQ((intptr_t)ep->data, 0); e.key = __UNCONST("b"); e.data = (void*)(intptr_t)1; ep = hsearch(e, ENTER); ATF_REQUIRE(ep != NULL); ATF_REQUIRE_STREQ(ep->key, "b"); ATF_REQUIRE_EQ((intptr_t)ep->data, 1); e.key = __UNCONST("a"); ep = hsearch(e, FIND); e.key = __UNCONST("b"); ep2 = hsearch(e, FIND); ATF_REQUIRE(ep != NULL); ATF_REQUIRE_STREQ(ep->key, "a"); ATF_REQUIRE_EQ((intptr_t)ep->data, 0); ATF_REQUIRE(ep2 != NULL); ATF_REQUIRE_STREQ(ep2->key, "b"); ATF_REQUIRE_EQ((intptr_t)ep2->data, 1); hdestroy(); } +#if defined(__FreeBSD__) && 1100027 <= __FreeBSD_version #ifdef __NetBSD__ ATF_TC(hsearch_r_basic); ATF_TC_HEAD(hsearch_r_basic, tc) { atf_tc_set_md_var(tc, "descr", "Checks basic insertions and searching"); } ATF_TC_BODY(hsearch_r_basic, tc) { ENTRY e, *ep; char ch[2]; int i; struct hsearch_data t; REQUIRE_ERRNO(hcreate_r(16, &t) != 0); /* ch[1] should be constant from here on down. */ ch[1] = '\0'; /* Basic insertions. Check enough that there'll be collisions. */ for (i = 0; i < 26; i++) { ch[0] = 'a' + i; e.key = strdup(ch); /* ptr to provided key is kept! */ ATF_REQUIRE(e.key != NULL); e.data = (void *)(intptr_t)i; ATF_REQUIRE(hsearch_r(e, ENTER, &ep, &t) == 1); ATF_REQUIRE(ep != NULL); ATF_REQUIRE_STREQ(ep->key, ch); ATF_REQUIRE_EQ((intptr_t)ep->data, i); } /* e.key should be constant from here on down. */ e.key = ch; /* Basic lookups. */ for (i = 0; i < 26; i++) { ch[0] = 'a' + i; ATF_REQUIRE(hsearch_r(e, FIND, &ep, &t) == 1); ATF_REQUIRE(ep != NULL); ATF_REQUIRE_STREQ(ep->key, ch); ATF_REQUIRE_EQ((intptr_t)ep->data, i); } hdestroy1_r(&t, free, NULL); } #endif ATF_TC(hsearch_r_duplicate); ATF_TC_HEAD(hsearch_r_duplicate, tc) { atf_tc_set_md_var(tc, "descr", "Checks that inserting duplicate " "doesn't overwrite existing data"); } ATF_TC_BODY(hsearch_r_duplicate, tc) { ENTRY e, *ep; struct hsearch_data t; REQUIRE_ERRNO(hcreate_r(16, &t)); e.key = __UNCONST("a"); e.data = (void *)(intptr_t) 0; ATF_REQUIRE(hsearch_r(e, ENTER, &ep, &t) == 1); ATF_REQUIRE(ep != NULL); ATF_REQUIRE_STREQ(ep->key, "a"); ATF_REQUIRE_EQ((intptr_t)ep->data, 0); e.data = (void *)(intptr_t)12345; ATF_REQUIRE(hsearch_r(e, ENTER, &ep, &t) == 1); ATF_REQUIRE(hsearch_r(e, FIND, &ep, &t) == 1); ATF_REQUIRE(ep != NULL); ATF_REQUIRE_STREQ(ep->key, "a"); ATF_REQUIRE_EQ((intptr_t)ep->data, 0); hdestroy_r(&t); } ATF_TC(hsearch_r_nonexistent); ATF_TC_HEAD(hsearch_r_nonexistent, tc) { atf_tc_set_md_var(tc, "descr", "Checks searching for non-existent entry"); } ATF_TC_BODY(hsearch_r_nonexistent, tc) { ENTRY e, *ep; struct hsearch_data t; REQUIRE_ERRNO(hcreate_r(16, &t)); e.key = __UNCONST("A"); ATF_REQUIRE(hsearch_r(e, FIND, &ep, &t) == 1); ATF_REQUIRE_EQ(ep, NULL); hdestroy_r(&t); } ATF_TC(hsearch_r_two); ATF_TC_HEAD(hsearch_r_two, tc) { atf_tc_set_md_var(tc, "descr", "Checks that searching doesn't overwrite previous search results"); } ATF_TC_BODY(hsearch_r_two, tc) { ENTRY e, *ep, *ep2; struct hsearch_data t; REQUIRE_ERRNO(hcreate_r(16, &t)); e.key = __UNCONST("a"); e.data = (void*)(intptr_t)0; ATF_REQUIRE(hsearch_r(e, ENTER, &ep, &t) == 1); ATF_REQUIRE(ep != NULL); ATF_REQUIRE_STREQ(ep->key, "a"); ATF_REQUIRE_EQ((intptr_t)ep->data, 0); e.key = __UNCONST("b"); e.data = (void*)(intptr_t)1; ATF_REQUIRE(hsearch_r(e, ENTER, &ep, &t) == 1); ATF_REQUIRE(ep != NULL); ATF_REQUIRE_STREQ(ep->key, "b"); ATF_REQUIRE_EQ((intptr_t)ep->data, 1); e.key = __UNCONST("a"); ATF_REQUIRE(hsearch_r(e, FIND, &ep, &t) == 1); e.key = __UNCONST("b"); ATF_REQUIRE(hsearch_r(e, FIND, &ep2, &t) == 1); ATF_REQUIRE(ep != NULL); ATF_REQUIRE_STREQ(ep->key, "a"); ATF_REQUIRE_EQ((intptr_t)ep->data, 0); ATF_REQUIRE(ep2 != NULL); ATF_REQUIRE_STREQ(ep2->key, "b"); ATF_REQUIRE_EQ((intptr_t)ep2->data, 1); hdestroy_r(&t); } +#endif ATF_TP_ADD_TCS(tp) { #ifdef __NetBSD__ ATF_TP_ADD_TC(tp, hsearch_basic); #endif ATF_TP_ADD_TC(tp, hsearch_duplicate); ATF_TP_ADD_TC(tp, hsearch_nonexistent); ATF_TP_ADD_TC(tp, hsearch_two); - + +#if defined(__FreeBSD__) && 1100027 <= __FreeBSD_version #ifdef __NetBSD__ ATF_TP_ADD_TC(tp, hsearch_r_basic); #endif ATF_TP_ADD_TC(tp, hsearch_r_duplicate); ATF_TP_ADD_TC(tp, hsearch_r_nonexistent); ATF_TP_ADD_TC(tp, hsearch_r_two); +#endif return atf_no_error(); } Index: projects/sendfile/lib/libc/gen/cap_rights_get.3 =================================================================== --- projects/sendfile/lib/libc/gen/cap_rights_get.3 (revision 276056) +++ projects/sendfile/lib/libc/gen/cap_rights_get.3 (revision 276057) @@ -1,119 +1,119 @@ .\" .\" Copyright (c) 2013 The FreeBSD Foundation .\" All rights reserved. .\" .\" This documentation was written by Pawel Jakub Dawidek under sponsorship .\" from the FreeBSD Foundation. .\" .\" 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$ .\" .Dd March 27, 2014 .Dt CAP_RIGHTS_GET 3 .Os .Sh NAME .Nm cap_rights_get .Nd obtain capability rights .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In sys/capsicum.h .Ft int .Fn cap_rights_get "int fd" "cap_rights_t *rights" .Sh DESCRIPTION The .Nm cap_rights_get function allows to obtain current capability rights for the given descriptor. The function will fill the .Fa rights argument with all capability rights if they were not limited or capability rights configured during the last successful call of .Xr cap_rights_limit 2 on the given descriptor. .Pp The .Fa rights argument can be inspected using .Xr cap_rights_init 3 family of functions. .Pp The complete list of the capability rights can be found in the .Xr rights 4 manual page. .Sh RETURN VALUES .Rv -std .Sh EXAMPLES The following example demonstrates how to limit file descriptor capability rights and how to obtain them. .Bd -literal cap_rights_t setrights, getrights; int fd; memset(&setrights, 0, sizeof(setrights)); memset(&getrights, 0, sizeof(getrights)); fd = open("/tmp/foo", O_RDONLY); if (fd < 0) err(1, "open() failed"); cap_rights_init(&setrights, CAP_FSTAT, CAP_READ); if (cap_rights_limit(fd, &setrights) < 0 && errno != ENOSYS) err(1, "cap_rights_limit() failed"); if (cap_rights_get(fd, &getrights) < 0 && errno != ENOSYS) err(1, "cap_rights_get() failed"); assert(memcmp(&setrights, &getrights, sizeof(setrights)) == 0); .Ed .Sh ERRORS .Fn cap_rights_get succeeds unless: .Bl -tag -width Er .It Bq Er EBADF The .Fa fd argument is not a valid active descriptor. .It Bq Er EFAULT The .Fa rights argument points at an invalid address. .El .Sh SEE ALSO .Xr cap_rights_limit 2 , -.Xr cap_rights_init 3 , .Xr errno 2 , .Xr open 2 , .Xr assert 3 , +.Xr cap_rights_init 3 , .Xr err 3 , .Xr memcmp 3 , .Xr memset 3 , .Xr capsicum 4 , .Xr rights 4 .Sh HISTORY Support for capabilities and capabilities mode was developed as part of the .Tn TrustedBSD Project. .Sh AUTHORS This function was created by .An Pawel Jakub Dawidek Aq Mt pawel@dawidek.net under sponsorship of the FreeBSD Foundation. Index: projects/sendfile/lib/libc/gen/ftok.3 =================================================================== --- projects/sendfile/lib/libc/gen/ftok.3 (revision 276056) +++ projects/sendfile/lib/libc/gen/ftok.3 (revision 276057) @@ -1,83 +1,83 @@ .\" Copyright (c) 1994 SigmaSoft, Th. Lockert .\" 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. The name of the author may not be used to endorse or promote products .\" derived from this software without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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$ .Dd July 9, 2009 .Dt FTOK 3 .Os .Sh NAME .Nm ftok .Nd create IPC identifier from path name .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In sys/types.h .In sys/ipc.h .Ft key_t .Fn ftok "const char *path" "int id" .Sh DESCRIPTION The .Fn ftok function attempts to create a unique key suitable for use with the .Xr msgget 2 , .Xr semget 2 and .Xr shmget 2 functions given the .Fa path of an existing file and a user-selectable .Fa id . .Pp The specified .Fa path must specify an existing file that is accessible to the calling process or the call will fail. Also, note that links to files will return the same key, given the same .Fa id . .Sh RETURN VALUES The .Fn ftok function will return -1 if .Fa path does not exist or if it cannot be accessed by the calling process. .Sh SEE ALSO +.Xr msgget 2 , .Xr semget 2 , -.Xr shmget 2 , -.Xr msgget 2 +.Xr shmget 2 .Sh HISTORY The .Fn ftok function originates with System V and is typically used by programs that use the System V IPC routines. .Sh AUTHORS .An Thorsten Lockert Aq Mt tholo@sigmasoft.com .Sh BUGS The returned key is computed based on the device minor number and inode of the specified .Fa path in combination with the lower 8 bits of the given .Fa id . Thus it is quite possible for the routine to return duplicate keys. Index: projects/sendfile/lib/libc/gen/ftw.3 =================================================================== --- projects/sendfile/lib/libc/gen/ftw.3 (revision 276056) +++ projects/sendfile/lib/libc/gen/ftw.3 (revision 276057) @@ -1,216 +1,218 @@ .\" $OpenBSD: ftw.3,v 1.5 2004/01/25 14:48:32 jmc Exp $ .\" .\" Copyright (c) 2003 Todd C. Miller .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .\" Sponsored in part by the Defense Advanced Research Projects .\" Agency (DARPA) and Air Force Research Laboratory, Air Force .\" Materiel Command, USAF, under agreement number F39502-99-1-0512. .\" .\" $FreeBSD$ .\" .Dd July 5, 2004 .Dt FTW 3 .Os .Sh NAME .Nm ftw , nftw .Nd traverse (walk) a file tree .Sh SYNOPSIS .In ftw.h .Ft int .Fo ftw .Fa "const char *path" .Fa "int \*[lp]*fn\*[rp]\*[lp]const char *, const struct stat *, int\*[rp]" .Fa "int maxfds" .Fc .Ft int .Fo nftw .Fa "const char *path" .Fa "int \*[lp]*fn\*[rp]\*[lp]const char *, const struct stat *, int, struct FTW *\*[rp]" .Fa "int maxfds" .Fa "int flags" .Fc .Sh DESCRIPTION The .Fn ftw and .Fn nftw functions traverse (walk) the directory hierarchy rooted in .Fa path . For each object in the hierarchy, these functions call the function pointed to by .Fa fn . The .Fn ftw function passes this function a pointer to a .Dv NUL Ns -terminated string containing the name of the object, a pointer to a .Vt stat structure corresponding to the object, and an integer flag. The .Fn nftw function passes the aforementioned arguments plus a pointer to a .Vt FTW structure as defined by .In ftw.h (shown below): .Bd -literal struct FTW { int base; /* offset of basename into pathname */ int level; /* directory depth relative to starting point */ }; .Ed .Pp Possible values for the flag passed to .Fa fn are: .Bl -tag -width ".Dv FTW_DNR" .It Dv FTW_F A regular file. .It Dv FTW_D A directory being visited in pre-order. .It Dv FTW_DNR A directory which cannot be read. The directory will not be descended into. .It Dv FTW_DP A directory being visited in post-order -.Fn ( nftw -only). +.Po Fn nftw +only +.Pc . .It Dv FTW_NS A file for which no .Xr stat 2 information was available. The contents of the .Vt stat structure are undefined. .It Dv FTW_SL A symbolic link. .It Dv FTW_SLN A symbolic link with a non-existent target -.Fn ( nftw -only). +.Po Fn nftw +only +.Pc . .El .Pp The .Fn ftw function traverses the tree in pre-order. That is, it processes the directory before the directory's contents. .Pp The .Fa maxfds argument specifies the maximum number of file descriptors to keep open while traversing the tree. It has no effect in this implementation. .Pp The .Fn nftw function has an additional .Fa flags argument with the following possible values: .Bl -tag -width ".Dv FTW_MOUNT" .It Dv FTW_PHYS Physical walk, do not follow symbolic links. .It Dv FTW_MOUNT The walk will not cross a mount point. .It FTW_DEPTH Process directories in post-order. Contents of a directory are visited before the directory itself. By default, .Fn nftw traverses the tree in pre-order. .It FTW_CHDIR Change to a directory before reading it. By default, .Fn nftw will change its starting directory. The current working directory will be restored to its original value before .Fn nftw returns. .El .Sh RETURN VALUES If the tree was traversed successfully, the .Fn ftw and .Fn nftw functions return 0. If the function pointed to by .Fa fn returns a non-zero value, .Fn ftw and .Fn nftw will stop processing the tree and return the value from .Fa fn . Both functions return \-1 if an error is detected. .Sh ERRORS The .Fn ftw and .Fn nftw functions may fail and set .Va errno for any of the errors specified for the library functions .Xr close 2 , .Xr open 2 , .Xr stat 2 , .Xr malloc 3 , .Xr opendir 3 and .Xr readdir 3 . If the .Dv FTW_CHDIR flag is set, the .Fn nftw function may fail and set .Va errno for any of the errors specified for .Xr chdir 2 . In addition, either function may fail and set .Va errno as follows: .Bl -tag -width Er .It Bq Er EINVAL The .Fa maxfds argument is less than 1. .El .Sh SEE ALSO .Xr chdir 2 , .Xr close 2 , .Xr open 2 , .Xr stat 2 , .Xr fts 3 , .Xr malloc 3 , .Xr opendir 3 , .Xr readdir 3 .Sh STANDARDS The .Fn ftw and .Fn nftw functions conform to .St -p1003.1-2001 . .Sh HISTORY These functions first appeared in .At V.3 . Their first .Fx appearance was in .Fx 5.3 . .Sh BUGS The .Fa maxfds argument is currently ignored. Index: projects/sendfile/lib/libc/gen/getcap.3 =================================================================== --- projects/sendfile/lib/libc/gen/getcap.3 (revision 276056) +++ projects/sendfile/lib/libc/gen/getcap.3 (revision 276057) @@ -1,568 +1,569 @@ .\" Copyright (c) 1992, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" Casey Leedom of Lawrence Livermore National Laboratory. .\" .\" 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. .\" .\" @(#)getcap.3 8.4 (Berkeley) 5/13/94 .\" $FreeBSD$ .\" .Dd March 22, 2002 .Dt GETCAP 3 .Os .Sh NAME .Nm cgetent , .Nm cgetset , .Nm cgetmatch , .Nm cgetcap , .Nm cgetnum , .Nm cgetstr , .Nm cgetustr , .Nm cgetfirst , .Nm cgetnext , .Nm cgetclose .Nd capability database access routines .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In stdlib.h .Ft int .Fn cgetent "char **buf" "char **db_array" "const char *name" .Ft int .Fn cgetset "const char *ent" .Ft int .Fn cgetmatch "const char *buf" "const char *name" .Ft char * .Fn cgetcap "char *buf" "const char *cap" "int type" .Ft int .Fn cgetnum "char *buf" "const char *cap" "long *num" .Ft int .Fn cgetstr "char *buf" "const char *cap" "char **str" .Ft int .Fn cgetustr "char *buf" "const char *cap" "char **str" .Ft int .Fn cgetfirst "char **buf" "char **db_array" .Ft int .Fn cgetnext "char **buf" "char **db_array" .Ft int .Fn cgetclose "void" .Sh DESCRIPTION The .Fn cgetent function extracts the capability .Fa name from the database specified by the .Dv NULL terminated file array .Fa db_array and returns a pointer to a .Xr malloc 3 Ns \&'d copy of it in .Fa buf . The .Fn cgetent function will first look for files ending in .Pa .db (see .Xr cap_mkdb 1 ) before accessing the ASCII file. The .Fa buf argument must be retained through all subsequent calls to .Fn cgetmatch , .Fn cgetcap , .Fn cgetnum , .Fn cgetstr , and .Fn cgetustr , but may then be .Xr free 3 Ns \&'d . On success 0 is returned, 1 if the returned record contains an unresolved .Ic tc expansion, \-1 if the requested record could not be found, \-2 if a system error was encountered (could not open/read a file, etc.) also setting .Va errno , and \-3 if a potential reference loop is detected (see .Ic tc= comments below). .Pp The .Fn cgetset function enables the addition of a character buffer containing a single capability record entry to the capability database. Conceptually, the entry is added as the first ``file'' in the database, and is therefore searched first on the call to .Fn cgetent . The entry is passed in .Fa ent . If .Fa ent is .Dv NULL , the current entry is removed from the database. A call to .Fn cgetset must precede the database traversal. It must be called before the .Fn cgetent call. If a sequential access is being performed (see below), it must be called before the first sequential access call -.Fn ( cgetfirst +.Po Fn cgetfirst or -.Fn cgetnext ) , +.Fn cgetnext +.Pc , or be directly preceded by a .Fn cgetclose call. On success 0 is returned and \-1 on failure. .Pp The .Fn cgetmatch function will return 0 if .Fa name is one of the names of the capability record .Fa buf , \-1 if not. .Pp The .Fn cgetcap function searches the capability record .Fa buf for the capability .Fa cap with type .Fa type . A .Fa type is specified using any single character. If a colon (`:') is used, an untyped capability will be searched for (see below for explanation of types). A pointer to the value of .Fa cap in .Fa buf is returned on success, .Dv NULL if the requested capability could not be found. The end of the capability value is signaled by a `:' or .Tn ASCII .Dv NUL (see below for capability database syntax). .Pp The .Fn cgetnum function retrieves the value of the numeric capability .Fa cap from the capability record pointed to by .Fa buf . The numeric value is returned in the .Ft long pointed to by .Fa num . 0 is returned on success, \-1 if the requested numeric capability could not be found. .Pp The .Fn cgetstr function retrieves the value of the string capability .Fa cap from the capability record pointed to by .Fa buf . A pointer to a decoded, .Dv NUL terminated, .Xr malloc 3 Ns \&'d copy of the string is returned in the .Ft char * pointed to by .Fa str . The number of characters in the decoded string not including the trailing .Dv NUL is returned on success, \-1 if the requested string capability could not be found, \-2 if a system error was encountered (storage allocation failure). .Pp The .Fn cgetustr function is identical to .Fn cgetstr except that it does not expand special characters, but rather returns each character of the capability string literally. .Pp The .Fn cgetfirst and .Fn cgetnext functions comprise a function group that provides for sequential access of the .Dv NULL pointer terminated array of file names, .Fa db_array . The .Fn cgetfirst function returns the first record in the database and resets the access to the first record. The .Fn cgetnext function returns the next record in the database with respect to the record returned by the previous .Fn cgetfirst or .Fn cgetnext call. If there is no such previous call, the first record in the database is returned. Each record is returned in a .Xr malloc 3 Ns \&'d copy pointed to by .Fa buf . .Ic Tc expansion is done (see .Ic tc= comments below). Upon completion of the database 0 is returned, 1 is returned upon successful return of record with possibly more remaining (we have not reached the end of the database yet), 2 is returned if the record contains an unresolved .Ic tc expansion, \-1 is returned if a system error occurred, and \-2 is returned if a potential reference loop is detected (see .Ic tc= comments below). Upon completion of database (0 return) the database is closed. .Pp The .Fn cgetclose function closes the sequential access and frees any memory and file descriptors being used. Note that it does not erase the buffer pushed by a call to .Fn cgetset . .Sh CAPABILITY DATABASE SYNTAX Capability databases are normally .Tn ASCII and may be edited with standard text editors. Blank lines and lines beginning with a `#' are comments and are ignored. Lines ending with a `\|\e' indicate that the next line is a continuation of the current line; the `\|\e' and following newline are ignored. Long lines are usually continued onto several physical lines by ending each line except the last with a `\|\e'. .Pp Capability databases consist of a series of records, one per logical line. Each record contains a variable number of `:'-separated fields (capabilities). Empty fields consisting entirely of white space characters (spaces and tabs) are ignored. .Pp The first capability of each record specifies its names, separated by `|' characters. These names are used to reference records in the database. By convention, the last name is usually a comment and is not intended as a lookup tag. For example, the .Em vt100 record from the .Xr termcap 5 database begins: .Pp .Dl "d0\||\|vt100\||\|vt100-am\||\|vt100am\||\|dec vt100:" .Pp giving four names that can be used to access the record. .Pp The remaining non-empty capabilities describe a set of (name, value) bindings, consisting of a names optionally followed by a typed value: .Pp .Bl -tag -width "nameTvalue" -compact .It name typeless [boolean] capability .Em name No "is present [true]" .It name Ns Em \&T Ns value capability .Pq Em name , \&T has value .Em value .It name@ no capability .Em name No exists .It name Ns Em T Ns \&@ capability .Pq Em name , T does not exist .El .Pp Names consist of one or more characters. Names may contain any character except `:', but it is usually best to restrict them to the printable characters and avoid use of graphics like `#', `=', `%', `@', etc. Types are single characters used to separate capability names from their associated typed values. Types may be any character except a `:'. Typically, graphics like `#', `=', `%', etc.\& are used. Values may be any number of characters and may contain any character except `:'. .Sh CAPABILITY DATABASE SEMANTICS Capability records describe a set of (name, value) bindings. Names may have multiple values bound to them. Different values for a name are distinguished by their .Fa types . The .Fn cgetcap function will return a pointer to a value of a name given the capability name and the type of the value. .Pp The types `#' and `=' are conventionally used to denote numeric and string typed values, but no restriction on those types is enforced. The functions .Fn cgetnum and .Fn cgetstr can be used to implement the traditional syntax and semantics of `#' and `='. Typeless capabilities are typically used to denote boolean objects with presence or absence indicating truth and false values respectively. This interpretation is conveniently represented by: .Pp .Dl "(getcap(buf, name, ':') != NULL)" .Pp A special capability, .Ic tc= name , is used to indicate that the record specified by .Fa name should be substituted for the .Ic tc capability. .Ic Tc capabilities may interpolate records which also contain .Ic tc capabilities and more than one .Ic tc capability may be used in a record. A .Ic tc expansion scope (i.e., where the argument is searched for) contains the file in which the .Ic tc is declared and all subsequent files in the file array. .Pp When a database is searched for a capability record, the first matching record in the search is returned. When a record is scanned for a capability, the first matching capability is returned; the capability .Ic :nameT@: will hide any following definition of a value of type .Em T for .Fa name ; and the capability .Ic :name@: will prevent any following values of .Fa name from being seen. .Pp These features combined with .Ic tc capabilities can be used to generate variations of other databases and records by either adding new capabilities, overriding definitions with new definitions, or hiding following definitions via `@' capabilities. .Sh EXAMPLES .Bd -unfilled -offset indent example\||\|an example of binding multiple values to names:\e :foo%bar:foo^blah:foo@:\e :abc%xyz:abc^frap:abc$@:\e :tc=more: .Ed .Pp The capability foo has two values bound to it (bar of type `%' and blah of type `^') and any other value bindings are hidden. The capability abc also has two values bound but only a value of type `$' is prevented from being defined in the capability record more. .Bd -unfilled -offset indent file1: new\||\|new_record\||\|a modification of "old":\e :fript=bar:who-cares@:tc=old:blah:tc=extensions: file2: old\||\|old_record\||\|an old database record:\e :fript=foo:who-cares:glork#200: .Ed .Pp The records are extracted by calling .Fn cgetent with file1 preceding file2. In the capability record new in file1, fript=bar overrides the definition of fript=foo interpolated from the capability record old in file2, who-cares@ prevents the definition of any who-cares definitions in old from being seen, glork#200 is inherited from old, and blah and anything defined by the record extensions is added to those definitions in old. Note that the position of the fript=bar and who-cares@ definitions before tc=old is important here. If they were after, the definitions in old would take precedence. .Sh CGETNUM AND CGETSTR SYNTAX AND SEMANTICS Two types are predefined by .Fn cgetnum and .Fn cgetstr : .Pp .Bl -tag -width "nameXnumber" -compact .It Em name Ns \&# Ns Em number numeric capability .Em name has value .Em number .It Em name Ns = Ns Em string string capability .Em name has value .Em string .It Em name Ns \&#@ the numeric capability .Em name does not exist .It Em name Ns \&=@ the string capability .Em name does not exist .El .Pp Numeric capability values may be given in one of three numeric bases. If the number starts with either .Ql 0x or .Ql 0X it is interpreted as a hexadecimal number (both upper and lower case a-f may be used to denote the extended hexadecimal digits). Otherwise, if the number starts with a .Ql 0 it is interpreted as an octal number. Otherwise the number is interpreted as a decimal number. .Pp String capability values may contain any character. Non-printable .Dv ASCII codes, new lines, and colons may be conveniently represented by the use of escape sequences: .Bl -column "\e\|X,X\e\|X" "(ASCII octal nnn)" ^X ('X' & 037) control-X \e\|b, \e\|B (ASCII 010) backspace \e\|t, \e\|T (ASCII 011) tab \e\|n, \e\|N (ASCII 012) line feed (newline) \e\|f, \e\|F (ASCII 014) form feed \e\|r, \e\|R (ASCII 015) carriage return \e\|e, \e\|E (ASCII 027) escape \e\|c, \e\|C (:) colon \e\|\e (\e\|) back slash \e\|^ (^) caret \e\|nnn (ASCII octal nnn) .El .Pp A `\|\e' may be followed by up to three octal digits directly specifies the numeric code for a character. The use of .Tn ASCII .Dv NUL Ns s , while easily encoded, causes all sorts of problems and must be used with care since .Dv NUL Ns s are typically used to denote the end of strings; many applications use `\e\|200' to represent a .Dv NUL . .Sh DIAGNOSTICS The .Fn cgetent , .Fn cgetset , .Fn cgetmatch , .Fn cgetnum , .Fn cgetstr , .Fn cgetustr , .Fn cgetfirst , and .Fn cgetnext functions return a value greater than or equal to 0 on success and a value less than 0 on failure. The .Fn cgetcap function returns a character pointer on success and a .Dv NULL on failure. .Pp The .Fn cgetent , and .Fn cgetset functions may fail and set .Va errno for any of the errors specified for the library functions: .Xr fopen 3 , .Xr fclose 3 , .Xr open 2 , and .Xr close 2 . .Pp The .Fn cgetent , .Fn cgetset , .Fn cgetstr , and .Fn cgetustr functions may fail and set .Va errno as follows: .Bl -tag -width Er .It Bq Er ENOMEM No memory to allocate. .El .Sh SEE ALSO .Xr cap_mkdb 1 , .Xr malloc 3 .Sh BUGS Colons (`:') cannot be used in names, types, or values. .Pp There are no checks for .Ic tc Ns = Ns Ic name loops in .Fn cgetent . .Pp The buffer added to the database by a call to .Fn cgetset is not unique to the database but is rather prepended to any database used. Index: projects/sendfile/lib/libc/gen/posix_spawn.3 =================================================================== --- projects/sendfile/lib/libc/gen/posix_spawn.3 (revision 276056) +++ projects/sendfile/lib/libc/gen/posix_spawn.3 (revision 276057) @@ -1,460 +1,460 @@ .\" Copyright (c) 2008 Ed Schouten .\" 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. .\" .\" Portions of this text are reprinted and reproduced in electronic form .\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- .\" Portable Operating System Interface (POSIX), The Open Group Base .\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of .\" Electrical and Electronics Engineers, Inc and The Open Group. In the .\" event of any discrepancy between this version and the original IEEE and .\" The Open Group Standard, the original IEEE and The Open Group Standard is .\" the referee document. The original Standard can be obtained online at .\" http://www.opengroup.org/unix/online.html. .\" .\" $FreeBSD$ .\" .Dd June 17, 2011 .Dt POSIX_SPAWN 3 .Os .Sh NAME .Nm posix_spawn , .Nm posix_spawnp .Nd "spawn a process" .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In spawn.h .Ft int .Fn posix_spawn "pid_t *restrict pid" "const char *restrict path" "const posix_spawn_file_actions_t *file_actions" "const posix_spawnattr_t *restrict attrp" "char *const argv[restrict]" "char *const envp[restrict]" .Ft int .Fn posix_spawnp "pid_t *restrict pid" "const char *restrict file" "const posix_spawn_file_actions_t *file_actions" "const posix_spawnattr_t *restrict attrp" "char *const argv[restrict]" "char *const envp[restrict]" .Sh DESCRIPTION The .Fn posix_spawn and .Fn posix_spawnp functions create a new process (child process) from the specified process image. The new process image is constructed from a regular executable file called the new process image file. .Pp When a C program is executed as the result of this call, it is entered as a C-language function call as follows: .Bd -literal -offset indent int main(int argc, char *argv[]); .Ed .Pp where .Fa argc is the argument count and .Fa argv is an array of character pointers to the arguments themselves. In addition, the variable: .Bd -literal -offset indent extern char **environ; .Ed .Pp points to an array of character pointers to the environment strings. .Pp The argument .Fa argv is an array of character pointers to null-terminated strings. The last member of this array is a null pointer and is not counted in .Fa argc . These strings constitute the argument list available to the new process image. The value in .Fa argv Ns [0] should point to a filename that is associated with the process image being started by the .Fn posix_spawn or .Fn posix_spawnp function. .Pp The argument .Fa envp is an array of character pointers to null-terminated strings. These strings constitute the environment for the new process image. The environment array is terminated by a null pointer. .Pp The .Fa path argument to .Fn posix_spawn is a pathname that identifies the new process image file to execute. .Pp The .Fa file parameter to .Fn posix_spawnp is used to construct a pathname that identifies the new process image file. If the file parameter contains a slash character, the file parameter is used as the pathname for the new process image file. Otherwise, the path prefix for this file is obtained by a search of the directories passed as the environment variable .Dq Ev PATH . If this variable is not specified, the default path is set according to the .Dv _PATH_DEFPATH definition in .In paths.h , which is set to .Dq Ev /usr/bin:/bin . .Pp If .Fa file_actions is a null pointer, then file descriptors open in the calling process remain open in the child process, except for those whose close-on-exec flag .Dv FD_CLOEXEC is set (see .Fn fcntl ) . For those file descriptors that remain open, all attributes of the corresponding open file descriptions, including file locks (see .Fn fcntl ) , remain unchanged. .Pp If .Fa file_actions is not NULL, then the file descriptors open in the child process are those open in the calling process as modified by the spawn file actions object pointed to by .Fa file_actions and the .Dv FD_CLOEXEC flag of each remaining open file descriptor after the spawn file actions have been processed. The effective order of processing the spawn file actions are: .Bl -enum .It The set of open file descriptors for the child process initially are the same set as is open for the calling process. All attributes of the corresponding open file descriptions, including file locks (see .Fn fcntl ) , remain unchanged. .It The signal mask, signal default actions, and the effective user and group IDs for the child process are changed as specified in the attributes object referenced by .Fa attrp . .It The file actions specified by the spawn file actions object are performed in the order in which they were added to the spawn file actions object. .It Any file descriptor that has its .Dv FD_CLOEXEC flag set (see .Fn fcntl ) is closed. .El .Pp The .Vt posix_spawnattr_t spawn attributes object type is defined in .In spawn.h . It contains the attributes defined below. .Pp If the .Dv POSIX_SPAWN_SETPGROUP flag is set in the spawn-flags attribute of the object referenced by .Fa attrp , and the spawn-pgroup attribute of the same object is non-zero, then the child's process group is as specified in the spawn-pgroup attribute of the object referenced by .Fa attrp . .Pp As a special case, if the .Dv POSIX_SPAWN_SETPGROUP flag is set in the spawn-flags attribute of the object referenced by .Fa attrp , and the spawn-pgroup attribute of the same object is set to zero, then the child is in a new process group with a process group ID equal to its process ID. .Pp If the .Dv POSIX_SPAWN_SETPGROUP flag is not set in the spawn-flags attribute of the object referenced by .Fa attrp , the new child process inherits the parent's process group. .Pp If the .Dv POSIX_SPAWN_SETSCHEDPARAM flag is set in the spawn-flags attribute of the object referenced by .Fa attrp , but .Dv POSIX_SPAWN_SETSCHEDULER is not set, the new process image initially has the scheduling policy of the calling process with the scheduling parameters specified in the spawn-schedparam attribute of the object referenced by .Fa attrp . .Pp If the .Dv POSIX_SPAWN_SETSCHEDULER flag is set in the spawn-flags attribute of the object referenced by .Fa attrp (regardless of the setting of the .Dv POSIX_SPAWN_SETSCHEDPARAM flag), the new process image initially has the scheduling policy specified in the spawn-schedpolicy attribute of the object referenced by .Fa attrp and the scheduling parameters specified in the spawn-schedparam attribute of the same object. .Pp The .Dv POSIX_SPAWN_RESETIDS flag in the spawn-flags attribute of the object referenced by .Fa attrp governs the effective user ID of the child process. If this flag is not set, the child process inherits the parent process' effective user ID. If this flag is set, the child process' effective user ID is reset to the parent's real user ID. In either case, if the set-user-ID mode bit of the new process image file is set, the effective user ID of the child process becomes that file's owner ID before the new process image begins execution. .Pp The .Dv POSIX_SPAWN_RESETIDS flag in the spawn-flags attribute of the object referenced by .Fa attrp also governs the effective group ID of the child process. If this flag is not set, the child process inherits the parent process' effective group ID. If this flag is set, the child process' effective group ID is reset to the parent's real group ID. In either case, if the set-group-ID mode bit of the new process image file is set, the effective group ID of the child process becomes that file's group ID before the new process image begins execution. .Pp If the .Dv POSIX_SPAWN_SETSIGMASK flag is set in the spawn-flags attribute of the object referenced by .Fa attrp , the child process initially has the signal mask specified in the spawn-sigmask attribute of the object referenced by .Fa attrp . .Pp If the .Dv POSIX_SPAWN_SETSIGDEF flag is set in the spawn-flags attribute of the object referenced by .Fa attrp , the signals specified in the spawn-sigdefault attribute of the same object is set to their default actions in the child process. Signals set to the default action in the parent process is set to the default action in the child process. .Pp Signals set to be caught by the calling process is set to the default action in the child process. .Pp Signals set to be ignored by the calling process image is set to be ignored by the child process, unless otherwise specified by the .Dv POSIX_SPAWN_SETSIGDEF flag being set in the spawn-flags attribute of the object referenced by .Fa attrp and the signals being indicated in the spawn-sigdefault attribute of the object referenced by .Fa attrp . .Pp If the value of the .Fa attrp pointer is NULL, then the default values are used. .Pp All process attributes, other than those influenced by the attributes set in the object referenced by .Fa attrp as specified above or by the file descriptor manipulations specified in .Fa file_actions , appear in the new process image as though .Fn vfork had been called to create a child process and then .Fn execve had been called by the child process to execute the new process image. .Pp The implementation uses vfork(), thus the fork handlers are not run when .Fn posix_spawn or .Fn posix_spawnp is called. .Sh RETURN VALUES Upon successful completion, .Fn posix_spawn and .Fn posix_spawnp return the process ID of the child process to the parent process, in the variable pointed to by a non-NULL .Fa pid argument, and return zero as the function return value. Otherwise, no child process is created, no value is stored into the variable pointed to by .Fa pid , and an error number is returned as the function return value to indicate the error. If the .Fa pid argument is a null pointer, the process ID of the child is not returned to the caller. .Sh ERRORS .Bl -enum .It If .Fn posix_spawn and .Fn posix_spawnp fail for any of the reasons that would cause .Fn vfork or one of the .Nm exec to fail, an error value is returned as described by .Fn vfork and .Nm exec , respectively (or, if the error occurs after the calling process successfully returns, the child process exits with exit status 127). .It If .Nm POSIX_SPAWN_SETPGROUP is set in the spawn-flags attribute of the object referenced by attrp, and .Fn posix_spawn or .Fn posix_spawnp fails while changing the child's process group, an error value is returned as described by .Fn setpgid (or, if the error occurs after the calling process successfully returns, the child process exits with exit status 127). .It If .Nm POSIX_SPAWN_SETSCHEDPARAM is set and .Nm POSIX_SPAWN_SETSCHEDULER is not set in the spawn-flags attribute of the object referenced by attrp, then if .Fn posix_spawn or .Fn posix_spawnp fails for any of the reasons that would cause .Fn sched_setparam to fail, an error value is returned as described by .Fn sched_setparam (or, if the error occurs after the calling process successfully returns, the child process exits with exit status 127). .It If .Nm POSIX_SPAWN_SETSCHEDULER is set in the spawn-flags attribute of the object referenced by attrp, and if .Fn posix_spawn or .Fn posix_spawnp fails for any of the reasons that would cause .Fn sched_setscheduler to fail, an error value is returned as described by .Fn sched_setscheduler (or, if the error occurs after the calling process successfully returns, the child process exits with exit status 127). .It If the .Fa file_actions argument is not NULL, and specifies any dup2 or open actions to be performed, and if .Fn posix_spawn or .Fn posix_spawnp fails for any of the reasons that would cause .Fn dup2 or .Fn open to fail, an error value is returned as described by .Fn dup2 and .Fn open , respectively (or, if the error occurs after the calling process successfully returns, the child process exits with exit status 127). An open file action may, by itself, result in any of the errors described by .Fn dup2 , in addition to those described by .Fn open . This implementation ignores any errors from .Fn close , including trying to close a descriptor that is not open. .El .Sh SEE ALSO .Xr close 2 , .Xr dup2 2 , .Xr execve 2 , .Xr fcntl 2 , .Xr open 2 , +.Xr sched_setparam 2 , +.Xr sched_setscheduler 2 , +.Xr setpgid 2 , +.Xr vfork 2 , .Xr posix_spawn_file_actions_addclose 3 , .Xr posix_spawn_file_actions_adddup2 3 , .Xr posix_spawn_file_actions_addopen 3 , .Xr posix_spawn_file_actions_destroy 3 , .Xr posix_spawn_file_actions_init 3 , .Xr posix_spawnattr_destroy 3 , .Xr posix_spawnattr_getflags 3 , .Xr posix_spawnattr_getpgroup 3 , .Xr posix_spawnattr_getschedparam 3 , .Xr posix_spawnattr_getschedpolicy 3 , .Xr posix_spawnattr_getsigdefault 3 , .Xr posix_spawnattr_getsigmask 3 , .Xr posix_spawnattr_init 3 , .Xr posix_spawnattr_setflags 3 , .Xr posix_spawnattr_setpgroup 3 , .Xr posix_spawnattr_setschedparam 3 , .Xr posix_spawnattr_setschedpolicy 3 , .Xr posix_spawnattr_setsigdefault 3 , -.Xr posix_spawnattr_setsigmask 3 , -.Xr sched_setparam 2 , -.Xr sched_setscheduler 2 , -.Xr setpgid 2 , -.Xr vfork 2 +.Xr posix_spawnattr_setsigmask 3 .Sh STANDARDS The .Fn posix_spawn and .Fn posix_spawnp functions conform to .St -p1003.1-2001 , except that they ignore all errors from .Fn close . A future update of the Standard is expected to require that these functions not fail because a file descriptor to be closed (via .Fn posix_spawn_file_actions_addclose ) is not open. .Sh HISTORY The .Fn posix_spawn and .Fn posix_spawnp functions first appeared in .Fx 8.0 . .Sh AUTHORS .An Ed Schouten Aq Mt ed@FreeBSD.org Index: projects/sendfile/lib/libc/gen/scandir.3 =================================================================== --- projects/sendfile/lib/libc/gen/scandir.3 (revision 276056) +++ projects/sendfile/lib/libc/gen/scandir.3 (revision 276057) @@ -1,117 +1,117 @@ .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. 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. .\" 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. .\" .\" @(#)scandir.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" .Dd January 3, 2010 .Dt SCANDIR 3 .Os .Sh NAME .Nm scandir , .Nm alphasort .Nd scan a directory .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In dirent.h .Ft int .Fn scandir "const char *dirname" "struct dirent ***namelist" "int \*(lp*select\*(rp\*(lpconst struct dirent *\*(rp" "int \*(lp*compar\*(rp\*(lpconst struct dirent **, const struct dirent **\*(rp" .Ft int .Fn scandir_b "const char *dirname" "struct dirent ***namelist" "int \*(lp*select\^(rp\*(lpconst struct dirent *\*(rp" "int \*(lp^compar\*(rp\*(lpconst struct dirent **, const struct dirent **\*(rp" .Ft int .Fn alphasort "const struct dirent **d1" "const struct dirent **d2" .Sh DESCRIPTION The .Fn scandir function reads the directory .Fa dirname and builds an array of pointers to directory entries using .Xr malloc 3 . It returns the number of entries in the array. A pointer to the array of directory entries is stored in the location referenced by .Fa namelist . .Pp The .Fa select argument is a pointer to a user supplied subroutine which is called by .Fn scandir to select which entries are to be included in the array. The select routine is passed a pointer to a directory entry and should return a non-zero value if the directory entry is to be included in the array. If .Fa select is null, then all the directory entries will be included. .Pp The .Fa compar argument is a pointer to a user supplied subroutine which is passed to .Xr qsort 3 to sort the completed array. If this pointer is null, the array is not sorted. .Pp The .Fn alphasort function is a routine which can be used for the .Fa compar argument to sort the array alphabetically using .Xr strcoll 3 . .Pp The memory allocated for the array can be deallocated with .Xr free 3 , by freeing each pointer in the array and then the array itself. .Pp The .Fn scandir_b -function behaves in the same way as +function behaves in the same way as .Fn scandir , but takes blocks as arguments instead of function pointers and calls .Fn qsort_b rather than .Fn qsort . .Sh DIAGNOSTICS Returns \-1 if the directory cannot be opened for reading or if .Xr malloc 3 cannot allocate enough memory to hold all the data structures. .Sh SEE ALSO .Xr directory 3 , .Xr malloc 3 , .Xr qsort 3 , -.Xr dir 5 , -.Xr strcoll 3 +.Xr strcoll 3 , +.Xr dir 5 .Sh HISTORY The .Fn scandir and .Fn alphasort functions appeared in .Bx 4.2 . Index: projects/sendfile/lib/libc/net/getaddrinfo.3 =================================================================== --- projects/sendfile/lib/libc/net/getaddrinfo.3 (revision 276056) +++ projects/sendfile/lib/libc/net/getaddrinfo.3 (revision 276057) @@ -1,460 +1,460 @@ .\" $KAME: getaddrinfo.3,v 1.36 2005/01/05 03:23:05 itojun Exp $ .\" $OpenBSD: getaddrinfo.3,v 1.35 2004/12/21 03:40:31 jaredy Exp $ .\" .\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000, 2001 Internet Software Consortium. .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH .\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY .\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, .\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM .\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" .\" $FreeBSD$ .\" .Dd February 14, 2013 .Dt GETADDRINFO 3 .Os .Sh NAME .Nm getaddrinfo , .Nm freeaddrinfo .Nd socket address structure to host and service name .Sh SYNOPSIS .In sys/types.h .In sys/socket.h .In netdb.h .Ft int .Fo getaddrinfo .Fa "const char *hostname" "const char *servname" .Fa "const struct addrinfo *hints" "struct addrinfo **res" .Fc .Ft void .Fn freeaddrinfo "struct addrinfo *ai" .Sh DESCRIPTION The .Fn getaddrinfo function is used to get a list of .Tn IP addresses and port numbers for host .Fa hostname and service .Fa servname . It is a replacement for and provides more flexibility than the .Xr gethostbyname 3 and .Xr getservbyname 3 functions. .Pp The .Fa hostname and .Fa servname arguments are either pointers to NUL-terminated strings or the null pointer. An acceptable value for .Fa hostname is either a valid host name or a numeric host address string consisting of a dotted decimal IPv4 address or an IPv6 address. The .Fa servname is either a decimal port number or a service name listed in .Xr services 5 . At least one of .Fa hostname and .Fa servname must be non-null. .Pp .Fa hints is an optional pointer to a .Li struct addrinfo , as defined by .Aq Pa netdb.h : .Bd -literal struct addrinfo { int ai_flags; /* input flags */ int ai_family; /* protocol family for socket */ int ai_socktype; /* socket type */ int ai_protocol; /* protocol for socket */ socklen_t ai_addrlen; /* length of socket-address */ struct sockaddr *ai_addr; /* socket-address for socket */ char *ai_canonname; /* canonical name for service location */ struct addrinfo *ai_next; /* pointer to next in list */ }; .Ed .Pp This structure can be used to provide hints concerning the type of socket that the caller supports or wishes to use. The caller can supply the following structure elements in .Fa hints : .Bl -tag -width "ai_socktypeXX" .It Fa ai_family The protocol family that should be used. When .Fa ai_family is set to .Dv PF_UNSPEC , it means the caller will accept any protocol family supported by the operating system. .It Fa ai_socktype Denotes the type of socket that is wanted: .Dv SOCK_STREAM , .Dv SOCK_DGRAM , or .Dv SOCK_RAW . When .Fa ai_socktype is zero the caller will accept any socket type. .It Fa ai_protocol Indicates which transport protocol is desired, .Dv IPPROTO_UDP or .Dv IPPROTO_TCP . If .Fa ai_protocol is zero the caller will accept any protocol. .It Fa ai_flags The .Fa ai_flags field to which the .Fa hints parameter points shall be set to zero or be the bitwise-inclusive OR of one or more of the values .Dv AI_ADDRCONFIG , .Dv AI_CANONNAME , .Dv AI_NUMERICHOST , .Dv AI_NUMERICSERV and .Dv AI_PASSIVE . .Bl -tag -width "AI_CANONNAMEXX" .It Dv AI_ADDRCONFIG If the .Dv AI_ADDRCONFIG bit is set, IPv4 addresses shall be returned only if an IPv4 address is configured on the local system, and IPv6 addresses shall be returned only if an IPv6 address is configured on the local system. .It Dv AI_CANONNAME If the .Dv AI_CANONNAME bit is set, a successful call to .Fn getaddrinfo will return a NUL-terminated string containing the canonical name of the specified hostname in the .Fa ai_canonname element of the first .Li addrinfo structure returned. .It Dv AI_NUMERICHOST If the .Dv AI_NUMERICHOST bit is set, it indicates that .Fa hostname should be treated as a numeric string defining an IPv4 or IPv6 address and no name resolution should be attempted. .It Dv AI_NUMERICSERV If the .Dv AI_NUMERICSERV bit is set, then a non-null .Fa servname string supplied shall be a numeric port string. Otherwise, an .Dv EAI_NONAME error shall be returned. This bit shall prevent any type of name resolution service (for example, NIS+) from being invoked. .It Dv AI_PASSIVE If the .Dv AI_PASSIVE bit is set it indicates that the returned socket address structure is intended for use in a call to .Xr bind 2 . In this case, if the .Fa hostname argument is the null pointer, then the IP address portion of the socket address structure will be set to .Dv INADDR_ANY for an IPv4 address or .Dv IN6ADDR_ANY_INIT for an IPv6 address. .Pp If the .Dv AI_PASSIVE bit is not set, the returned socket address structure will be ready for use in a call to .Xr connect 2 for a connection-oriented protocol or .Xr connect 2 , .Xr sendto 2 , or .Xr sendmsg 2 if a connectionless protocol was chosen. The .Tn IP address portion of the socket address structure will be set to the loopback address if .Fa hostname is the null pointer and .Dv AI_PASSIVE is not set. .El .El .Pp All other elements of the .Li addrinfo structure passed via .Fa hints must be zero or the null pointer. .Pp If .Fa hints is the null pointer, .Fn getaddrinfo behaves as if the caller provided a .Li struct addrinfo with .Fa ai_family set to .Dv PF_UNSPEC and all other elements set to zero or .Dv NULL . .Pp After a successful call to .Fn getaddrinfo , .Fa *res is a pointer to a linked list of one or more .Li addrinfo structures. The list can be traversed by following the .Fa ai_next pointer in each .Li addrinfo structure until a null pointer is encountered. The three members -.Fa ai_family, -.Fa ai_socktype, +.Fa ai_family , +.Fa ai_socktype , and .Fa ai_protocol in each returned .Li addrinfo structure are suitable for a call to .Xr socket 2 . For each .Li addrinfo structure in the list, the .Fa ai_addr member points to a filled-in socket address structure of length .Fa ai_addrlen . .Pp This implementation of .Fn getaddrinfo allows numeric IPv6 address notation with scope identifier, as documented in chapter 11 of RFC 4007. By appending the percent character and scope identifier to addresses, one can fill the .Li sin6_scope_id field for addresses. This would make management of scoped addresses easier and allows cut-and-paste input of scoped addresses. .Pp At this moment the code supports only link-local addresses with the format. The scope identifier is hardcoded to the name of the hardware interface associated with the link .Po such as .Li ne0 .Pc . An example is .Dq Li fe80::1%ne0 , which means .Do .Li fe80::1 on the link associated with the .Li ne0 interface .Dc . .Pp The current implementation assumes a one-to-one relationship between the interface and link, which is not necessarily true from the specification. .Pp All of the information returned by .Fn getaddrinfo is dynamically allocated: the .Li addrinfo structures themselves as well as the socket address structures and the canonical host name strings included in the .Li addrinfo structures. .Pp Memory allocated for the dynamically allocated structures created by a successful call to .Fn getaddrinfo is released by the .Fn freeaddrinfo function. The .Fa ai pointer should be a .Li addrinfo structure created by a call to .Fn getaddrinfo . .Sh RETURN VALUES .Fn getaddrinfo returns zero on success or one of the error codes listed in .Xr gai_strerror 3 if an error occurs. .Sh EXAMPLES The following code tries to connect to .Dq Li www.kame.net service .Dq Li http via a stream socket. It loops through all the addresses available, regardless of address family. If the destination resolves to an IPv4 address, it will use an .Dv AF_INET socket. Similarly, if it resolves to IPv6, an .Dv AF_INET6 socket is used. Observe that there is no hardcoded reference to a particular address family. The code works even if .Fn getaddrinfo returns addresses that are not IPv4/v6. .Bd -literal -offset indent struct addrinfo hints, *res, *res0; int error; int s; const char *cause = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo("www.kame.net", "http", &hints, &res0); if (error) { errx(1, "%s", gai_strerror(error)); /* NOTREACHED */ } s = -1; for (res = res0; res; res = res->ai_next) { s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s < 0) { cause = "socket"; continue; } if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { cause = "connect"; close(s); s = -1; continue; } break; /* okay we got one */ } if (s < 0) { err(1, "%s", cause); /* NOTREACHED */ } freeaddrinfo(res0); .Ed .Pp The following example tries to open a wildcard listening socket onto service .Dq Li http , for all the address families available. .Bd -literal -offset indent struct addrinfo hints, *res, *res0; int error; int s[MAXSOCK]; int nsock; const char *cause = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; error = getaddrinfo(NULL, "http", &hints, &res0); if (error) { errx(1, "%s", gai_strerror(error)); /* NOTREACHED */ } nsock = 0; for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) { s[nsock] = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s[nsock] < 0) { cause = "socket"; continue; } if (bind(s[nsock], res->ai_addr, res->ai_addrlen) < 0) { cause = "bind"; close(s[nsock]); continue; } (void) listen(s[nsock], 5); nsock++; } if (nsock == 0) { err(1, "%s", cause); /* NOTREACHED */ } freeaddrinfo(res0); .Ed .Sh SEE ALSO .Xr bind 2 , .Xr connect 2 , .Xr send 2 , .Xr socket 2 , .Xr gai_strerror 3 , .Xr gethostbyname 3 , .Xr getnameinfo 3 , .Xr getservbyname 3 , .Xr resolver 3 , .Xr hosts 5 , .Xr resolv.conf 5 , .Xr services 5 , .Xr hostname 7 , .Xr named 8 .Rs .%A R. Gilligan .%A S. Thomson .%A J. Bound .%A J. McCann .%A W. Stevens .%T Basic Socket Interface Extensions for IPv6 .%R RFC 3493 .%D February 2003 .Re .Rs .%A S. Deering .%A B. Haberman .%A T. Jinmei .%A E. Nordmark .%A B. Zill .%T "IPv6 Scoped Address Architecture" .%R RFC 4007 .%D March 2005 .Re .Rs .%A Craig Metz .%T Protocol Independence Using the Sockets API .%B "Proceedings of the freenix track: 2000 USENIX annual technical conference" .%D June 2000 .Re .Sh STANDARDS The .Fn getaddrinfo function is defined by the .St -p1003.1-2004 specification and documented in .Dv "RFC 3493" , .Dq Basic Socket Interface Extensions for IPv6 . Index: projects/sendfile/lib/libc/net/sctp_recvmsg.3 =================================================================== --- projects/sendfile/lib/libc/net/sctp_recvmsg.3 (revision 276056) +++ projects/sendfile/lib/libc/net/sctp_recvmsg.3 (revision 276057) @@ -1,294 +1,294 @@ .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. 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. 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$ .\" .Dd August 13, 2007 .Dt SCTP_RECVMSG 3 .Os .Sh NAME .Nm sctp_recvmsg .Nd receive a message from an SCTP socket .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In sys/types.h .In sys/socket.h .In netinet/sctp.h .Ft ssize_t .Fo sctp_recvmsg .Fa "int s" "void *msg" "size_t len" "struct sockaddr * restrict from" .Fa "socklen_t * restrict fromlen" "struct sctp_sndrcvinfo *sinfo" "int *flags" .Fc .Sh DESCRIPTION The .Fn sctp_recvmsg system call is used to receive a message from another SCTP endpoint. The .Fn sctp_recvmsg call is used by one-to-one (SOCK_STREAM) type sockets after a successful .Fn connect call or after the application has performed a .Fn listen followed by a successful .Fn accept . For a one-to-many (SOCK_SEQPACKET) type socket, an endpoint may call .Fn sctp_recvmsg after having implicitly started an association via one of the send calls including .Fn sctp_sendmsg , .Fn sendto and .Fn sendmsg . Or, an application may also receive a message after having called .Fn listen with a positive backlog to enable the reception of new associations. .Pp The address of the sender is held in the .Fa from argument with .Fa fromlen specifying its size. At the completion of a successful .Fn sctp_recvmsg call .Fa from will hold the address of the peer and .Fa fromlen will hold the length of that address. Note that the address is bounded by the initial value of .Fa fromlen which is used as an in/out variable. .Pp The length of the message .Fa msg to be received is bounded by .Fa len . If the message is too long to fit in the users receive buffer, then the .Fa flags argument will .Em not have the .Dv MSG_EOF flag applied. If the message is a complete message then the .Fa flags argument will have .Dv MSG_EOF set. Locally detected errors are indicated by a return value of -1 with .Va errno set accordingly. The .Fa flags argument may also hold the value .Dv MSG_NOTIFICATION . When this occurs it indicates that the message received is .Em not from the peer endpoint, but instead is a notification from the SCTP stack (see .Xr sctp 4 for more details). Note that no notifications are ever given unless the user subscribes to such notifications using the .Dv SCTP_EVENTS socket option. .Pp If no messages are available at the socket then .Fn sctp_recvmsg normally blocks on the reception of a message or NOTIFICATION, unless the socket has been placed in non-blocking I/O mode. The .Xr select 2 system call may be used to determine when it is possible to receive a message. .Pp The .Fa sinfo argument is defined as follows. .Bd -literal struct sctp_sndrcvinfo { uint16_t sinfo_stream; /* Stream arriving on */ uint16_t sinfo_ssn; /* Stream Sequence Number */ uint16_t sinfo_flags; /* Flags on the incoming message */ uint32_t sinfo_ppid; /* The ppid field */ uint32_t sinfo_context; /* context field */ uint32_t sinfo_timetolive; /* not used by sctp_recvmsg */ uint32_t sinfo_tsn; /* The transport sequence number */ uint32_t sinfo_cumtsn; /* The cumulative acknowledgment point */ sctp_assoc_t sinfo_assoc_id; /* The association id of the peer */ }; .Ed .Pp The .Fa sinfo->sinfo_ppid field is an opaque 32 bit value that is passed transparently through the stack from the peer endpoint. Note that the stack passes this value without regard to byte order. .Pp The .Fa sinfo->sinfo_flags field may include the following: .Bd -literal #define SCTP_UNORDERED 0x0400 /* Message is un-ordered */ .Ed .Pp The .Dv SCTP_UNORDERED flag is used to specify that the message arrived with no specific order and was delivered to the peer application as soon as possible. When this flag is absent the message was delivered in order within the stream it was received. .Pp The .Fa sinfo->sinfo_stream field is the SCTP stream that the message was received on. Streams in SCTP are reliable (or partially reliable) flows of ordered messages. .Pp The .Fa sinfo->sinfo_context field is used only if the local application set an association level context with the .Dv SCTP_CONTEXT socket option. Optionally a user process can use this value to index some application specific data structure for all data coming from a specific association. .Pp The .Fa sinfo->sinfo_ssn field will hold the stream sequence number assigned by the peer endpoint if the message is .Em not unordered. For unordered messages this field holds an undefined value. .Pp The .Fa sinfo->sinfo_tsn field holds a transport sequence number (TSN) that was assigned to this message by the peer endpoint. For messages that fit in or less than the path MTU this will be the only TSN assigned. Note that for messages that span multiple TSNs this value will be one of the TSNs that was used on the message. .Pp The .Fa sinfo->sinfo_cumtsn field holds the current cumulative acknowledgment point of the transport association. Note that this may be larger or smaller than the TSN assigned to the message itself. .Pp The .Fa sinfo->sinfo_assoc_id is the unique association identification that was assigned to the association. For one-to-many (SOCK_SEQPACKET) type sockets this value can be used to send data to the peer without the use of an address field. It is also quite useful in setting various socket options on the specific association (see .Xr sctp 4 ) . .Pp The .Fa sinfo->info_timetolive field is not used by .Fn sctp_recvmsg . .Sh RETURN VALUES The call returns the number of bytes received, or -1 if an error occurred. .Sh ERRORS The .Fn sctp_recvmsg system call fails if: .Bl -tag -width Er .It Bq Er EBADF An invalid descriptor was specified. .It Bq Er ENOTSOCK The argument .Fa s is not a socket. .It Bq Er EFAULT An invalid user space address was specified for an argument. .It Bq Er EMSGSIZE The socket requires that message be sent atomically, and the size of the message to be sent made this impossible. .It Bq Er EAGAIN The socket is marked non-blocking and the requested operation would block. .It Bq Er ENOBUFS The system was unable to allocate an internal buffer. The operation may succeed when buffers become available. .It Bq Er ENOBUFS The output queue for a network interface was full. This generally indicates that the interface has stopped sending, but may be caused by transient congestion. .It Bq Er EHOSTUNREACH The remote host was unreachable. .It Bq Er ENOTCONN On a one-to-one style socket no association exists. .It Bq Er ECONNRESET An abort was received by the stack while the user was attempting to send data to the peer. .It Bq Er ENOENT On a one to many style socket no address is specified so that the association cannot be located or the SCTP_ABORT flag was specified on a non-existing association. .It Bq Er EPIPE The socket is unable to send anymore data .Dv ( SBS_CANTSENDMORE has been set on the socket). This typically means that the socket is not connected and is a one-to-one style socket. .El .Sh SEE ALSO +.Xr getsockopt 2 , .Xr recv 2 , .Xr select 2 , +.Xr setsockopt 2 , .Xr socket 2 , .Xr write 2 , -.Xr getsockopt 2 , -.Xr setsockopt 2 , .Xr sctp_send 3 , .Xr sctp_sendmsg 3 , .Xr sendmsg 3 , .Xr sctp 4 Index: projects/sendfile/lib/libc/net/sctp_send.3 =================================================================== --- projects/sendfile/lib/libc/net/sctp_send.3 (revision 276056) +++ projects/sendfile/lib/libc/net/sctp_send.3 (revision 276057) @@ -1,350 +1,350 @@ .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. 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. 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$ .\" .Dd December 15, 2006 .Dt SCTP_SEND 3 .Os .Sh NAME .Nm sctp_send , .Nm sctp_sendx .Nd send a message from an SCTP socket .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In sys/types.h .In sys/socket.h .In netinet/sctp.h .Ft ssize_t .Fo sctp_send .Fa "int sd" "const void *msg" "size_t len" .Fa "const struct sctp_sndrcvinfo *sinfo" "int flags" .Fc .Ft ssize_t .Fo sctp_sendx .Fa "int sd" "const void *msg" "size_t len" "struct sockaddr *addrs" .Fa "int addrcnt" "const struct sctp_sndrcvinfo *sinfo" "int flags" .Fc .Sh DESCRIPTION The .Fn sctp_send system call is used to transmit a message to another SCTP endpoint. .Fn sctp_send may be used to send data to an existing association for both one-to-many (SOCK_SEQPACKET) and one-to-one (SOCK_STREAM) socket types. The length of the message .Fa msg is given by .Fa len . If the message is too long to pass atomically through the underlying protocol, .Va errno is set to .Er EMSGSIZE , -1 is returned, and the message is not transmitted. .Pp No indication of failure to deliver is implicit in a .Fn sctp_send . Locally detected errors are indicated by a return value of -1. .Pp If no space is available at the socket to hold the message to be transmitted, then .Fn sctp_send normally blocks, unless the socket has been placed in non-blocking I/O mode. The .Xr select 2 system call may be used to determine when it is possible to send more data on one-to-one type (SOCK_STREAM) sockets. .Pp The .Fa sinfo structure is used to control various SCTP features and has the following format: .Bd -literal struct sctp_sndrcvinfo { uint16_t sinfo_stream; /* Stream sending to */ uint16_t sinfo_ssn; /* valid for recv only */ uint16_t sinfo_flags; /* flags to control sending */ uint32_t sinfo_ppid; /* ppid field */ uint32_t sinfo_context; /* context field */ uint32_t sinfo_timetolive; /* timetolive for PR-SCTP */ uint32_t sinfo_tsn; /* valid for recv only */ uint32_t sinfo_cumtsn; /* valid for recv only */ sctp_assoc_t sinfo_assoc_id; /* The association id */ }; .Ed .Pp The .Fa sinfo->sinfo_ppid argument is an opaque 32 bit value that is passed transparently through the stack to the peer endpoint. It will be available on reception of a message (see .Xr sctp_recvmsg 3 ) . Note that the stack passes this value without regard to byte order. .Pp The .Fa sinfo->sinfo_flags argument may include one or more of the following: .Bd -literal #define SCTP_EOF 0x0100 /* Start a shutdown procedures */ #define SCTP_ABORT 0x0200 /* Send an ABORT to peer */ #define SCTP_UNORDERED 0x0400 /* Message is un-ordered */ #define SCTP_ADDR_OVER 0x0800 /* Override the primary-address */ #define SCTP_SENDALL 0x1000 /* Send this on all associations */ /* for the endpoint */ /* The lower byte is an enumeration of PR-SCTP policies */ #define SCTP_PR_SCTP_TTL 0x0001 /* Time based PR-SCTP */ #define SCTP_PR_SCTP_BUF 0x0002 /* Buffer based PR-SCTP */ #define SCTP_PR_SCTP_RTX 0x0003 /* Number of retransmissions based PR-SCTP */ .Ed .Pp The flag .Dv SCTP_EOF is used to instruct the SCTP stack to queue this message and then start a graceful shutdown of the association. All remaining data in queue will be sent after which the association will be shut down. .Pp .Dv SCTP_ABORT is used to immediately terminate an association. An abort is sent to the peer and the local TCB is destroyed. .Pp .Dv SCTP_UNORDERED is used to specify that the message being sent has no specific order and should be delivered to the peer application as soon as possible. When this flag is absent messages are delivered in order within the stream they are sent, but without respect to order to peer streams. .Pp The flag .Dv SCTP_ADDR_OVER is used to specify that a specific address should be used. Normally SCTP will use only one of a multi-homed peers addresses as the primary address to send to. By default, no matter what the .Fa to argument is, this primary address is used to send data. By specifying this flag, the user is asking the stack to ignore the primary address and instead use the specified address not only as a lookup mechanism to find the association but also as the actual address to send to. .Pp For a one-to-many type (SOCK_SEQPACKET) socket the flag .Dv SCTP_SENDALL can be used as a convenient way to make one send call and have all associations that are under the socket get a copy of the message. Note that this mechanism is quite efficient and makes only one actual copy of the data which is shared by all the associations for sending. .Pp The remaining flags are used for the partial reliability extension (RFC3758) and will only be effective if the peer endpoint supports this extension. This option specifies what local policy the local endpoint should use in skipping data. If none of these options are set, then data is never skipped over. .Pp .Dv SCTP_PR_SCTP_TTL is used to indicate that a time based lifetime is being applied to the data. The .Fa sinfo->sinfo_timetolive argument is then a number of milliseconds for which the data is attempted to be transmitted. If that many milliseconds elapse and the peer has not acknowledged the data, the data will be skipped and no longer transmitted. Note that this policy does not even assure that the data will ever be sent. In times of a congestion with large amounts of data being queued, the .Fa sinfo->sinfo_timetolive may expire before the first transmission is ever made. .Pp The .Dv SCTP_PR_SCTP_BUF based policy transforms the .Fa sinfo->sinfo_timetolive field into a total number of bytes allowed on the outbound send queue. If that number or more bytes are in queue, then other buffer-based sends are looked to be removed and skipped. Note that this policy may also result in the data never being sent if no buffer based sends are in queue and the maximum specified by .Fa timetolive bytes is in queue. .Pp The .Dv SCTP_PR_SCTP_RTX policy transforms the .Fa sinfo->sinfo_timetolive into a number of retransmissions to allow. This policy always assures that at a minimum one send attempt is made of the data. After which no more than .Fa sinfo->sinfo_timetolive retransmissions will be made before the data is skipped. .Pp .Fa sinfo->sinfo_stream is the SCTP stream that you wish to send the message on. Streams in SCTP are reliable (or partially reliable) flows of ordered messages. .Pp The .Fa sinfo->sinfo_assoc_id field is used to select the association to send to on a one-to-many socket. For a one-to-one socket, this field is ignored. .Pp The .Fa sinfo->sinfo_context field is used only in the event the message cannot be sent. This is an opaque value that the stack retains and will give to the user when a failed send is given if that notification is enabled (see .Xr sctp 4 ) . Normally a user process can use this value to index some application specific data structure when a send cannot be fulfilled. .Pp The .Fa flags argument holds the same meaning and values as those found in .Xr sendmsg 2 but is generally ignored by SCTP. .Pp The fields .Fa sinfo->sinfo_ssn , .Fa sinfo->sinfo_tsn , and .Fa sinfo->sinfo_cumtsn are used only when receiving messages and are thus ignored by .Fn sctp_send . The function .Fn sctp_sendx has the same properties as .Fn sctp_send with the additional arguments of an array of sockaddr structures passed in. With the .Fa addrs argument being given as an array of addresses to be sent to and the .Fa addrcnt argument indicating how many socket addresses are in the passed in array. Note that all of the addresses will only be used when an implicit association is being set up. This allows the user the equivalent behavior as doing a .Fn sctp_connectx followed by a .Fn sctp_send to the association. Note that if the .Fa sinfo->sinfo_assoc_id field is 0, then the first address will be used to look up the association in place of the association id. If both an address and an association id are specified, the association id has priority. .Sh RETURN VALUES The call returns the number of characters sent, or -1 if an error occurred. .Sh ERRORS The .Fn sctp_send system call fails if: .Bl -tag -width Er .It Bq Er EBADF An invalid descriptor was specified. .It Bq Er ENOTSOCK The argument .Fa s is not a socket. .It Bq Er EFAULT An invalid user space address was specified for an argument. .It Bq Er EMSGSIZE The socket requires that message be sent atomically, and the size of the message to be sent made this impossible. .It Bq Er EAGAIN The socket is marked non-blocking and the requested operation would block. .It Bq Er ENOBUFS The system was unable to allocate an internal buffer. The operation may succeed when buffers become available. .It Bq Er ENOBUFS The output queue for a network interface was full. This generally indicates that the interface has stopped sending, but may be caused by transient congestion. .It Bq Er EHOSTUNREACH The remote host was unreachable. .It Bq Er ENOTCONN On a one-to-one style socket no association exists. .It Bq Er ECONNRESET An abort was received by the stack while the user was attempting to send data to the peer. .It Bq Er ENOENT On a one-to-many style socket no address is specified so that the association cannot be located or the SCTP_ABORT flag was specified on a non-existing association. .It Bq Er EPIPE The socket is unable to send anymore data .Dv ( SBS_CANTSENDMORE has been set on the socket). This typically means that the socket is not connected and is a one-to-one style socket. .El .Sh SEE ALSO .Xr getsockopt 2 , .Xr recv 2 , .Xr select 2 , .Xr sendmsg 2 , .Xr socket 2 , -.Xr write 2 +.Xr write 2 , .Xr sctp_connectx 3 , .Xr sctp_recvmsg 3 , .Xr sctp_sendmsg 3 , .Xr sctp 4 .Sh BUGS Because .Fn sctp_send may have multiple associations under one endpoint, a select on write will only work for a one-to-one style socket. Index: projects/sendfile/lib/libc/posix1e/acl_set_flagset_np.3 =================================================================== --- projects/sendfile/lib/libc/posix1e/acl_set_flagset_np.3 (revision 276056) +++ projects/sendfile/lib/libc/posix1e/acl_set_flagset_np.3 (revision 276057) @@ -1,85 +1,85 @@ .\"- .\" Copyright (c) 2008, 2009 Edward Tomasz Napierala .\" 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$ .\" .Dd October 30, 2014 .Dt ACL_SET_FLAGSET_NP 3 .Os .Sh NAME .Nm acl_set_flagset_np .Nd set the flags of an NFSv4 ACL entry .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In sys/types.h .In sys/acl.h .Ft int .Fn acl_set_flagset_np "acl_entry_t entry_d" "acl_flagset_t flagset_d" .Sh DESCRIPTION The .Fn acl_set_flagset_np function is a non-portable call that sets the flags of NFSv4 ACL entry .Fa entry_d with the flags contained in .Fa flagset_d . .Pp This call brands the ACL as NFSv4. .Sh RETURN VALUES .Rv -std acl_set_flagset_np .Sh ERRORS The .Fn acl_set_flagset_np function fails if: .Bl -tag -width Er .It Bq Er EINVAL Argument .Fa entry_d is not a valid descriptor for an ACL entry. ACL is already branded as POSIX.1e. .El .Sh SEE ALSO .Xr acl 3 , .Xr acl_add_flag_np 3 , -.Xr acl_get_brand_np 3 , .Xr acl_clear_flags_np 3 , .Xr acl_delete_flag_np 3 , +.Xr acl_get_brand_np 3 , .Xr acl_get_flagset_np 3 , .Xr posix1e 3 .Sh STANDARDS POSIX.1e is described in IEEE POSIX.1e draft 17. .Sh HISTORY POSIX.1e support was introduced in .Fx 4.0 . The .Fn acl_set_flagset_np function was added in .Fx 8.0 . .Sh AUTHORS The .Fn acl_set_flagset_np function was written by .An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org . Index: projects/sendfile/lib/libc/stdlib/atexit.3 =================================================================== --- projects/sendfile/lib/libc/stdlib/atexit.3 (revision 276056) +++ projects/sendfile/lib/libc/stdlib/atexit.3 (revision 276057) @@ -1,103 +1,103 @@ .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" Chris Torek and the American National Standards Committee X3, .\" on Information Processing Systems. .\" .\" 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. 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. .\" .\" @(#)atexit.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" .Dd September 6, 2002 .Dt ATEXIT 3 .Os .Sh NAME .Nm atexit .Nd register a function to be called on exit .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In stdlib.h .Ft int .Fn atexit "void (*function)(void)" .Ft int .Fn atexit_b "void (^function)(void)" .Sh DESCRIPTION The .Fn atexit function registers the given .Fa function to be called at program exit, whether via .Xr exit 3 or via return from the program's .Fn main . Functions so registered are called in reverse order; no arguments are passed. .Pp These functions must not call .Fn exit ; if it should be necessary to terminate the process while in such a function, the .Xr _exit 2 function should be used. (Alternatively, the function may cause abnormal process termination, for example by calling .Xr abort 3 . ) .Pp At least 32 functions can always be registered, and more are allowed as long as sufficient memory can be allocated. .Pp The .Fn atexit_b function behaves identically to .Fn atexit , except that it takes a block, rather than a function pointer. .\" XXX {ATEXIT_MAX} is not implemented yet .Sh RETURN VALUES .Rv -std atexit .Sh ERRORS .Bl -tag -width Er .It Bq Er ENOMEM No memory was available to add the function to the list. The existing list of functions is unmodified. .It Bq Er ENOSYS The .Fn atexit_b -function was called by a program that did not supply a +function was called by a program that did not supply a .Fn _Block_copy implementation. .El .Sh SEE ALSO -.Xr at_quick_exit 3 +.Xr at_quick_exit 3 , .Xr exit 3 .Sh STANDARDS The .Fn atexit function conforms to .St -isoC . Index: projects/sendfile/lib/libc/stdlib/exit.3 =================================================================== --- projects/sendfile/lib/libc/stdlib/exit.3 (revision 276056) +++ projects/sendfile/lib/libc/stdlib/exit.3 (revision 276057) @@ -1,132 +1,132 @@ .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" the American National Standards Committee X3, on Information .\" Processing Systems. .\" .\" 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. 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. .\" .\" @(#)exit.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" .Dd September 9, 2002 .Dt EXIT 3 .Os .Sh NAME .Nm exit , _Exit .Nd perform normal program termination .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In stdlib.h .Ft void .Fn exit "int status" .Ft void .Fn _Exit "int status" .Sh DESCRIPTION The .Fn exit and .Fn _Exit functions terminate a process. .Pp Before termination, .Fn exit performs the following functions in the order listed: .Bl -enum -offset indent .It Call the functions registered with the .Xr atexit 3 function, in the reverse order of their registration. .It Flush all open output streams. .It Close all open streams. .It Unlink all files created with the .Xr tmpfile 3 function. .El .Pp The .Fn _Exit function terminates without calling the functions registered with the .Xr atexit 3 function, and may or may not perform the other actions listed. Both functions make the low-order eight bits of the .Fa status argument available to a parent process which has called a .Xr wait 2 Ns -family function. .Pp The C Standard .Pq St -isoC-99 defines the values .Li 0 , .Dv EXIT_SUCCESS , and .Dv EXIT_FAILURE as possible values of .Fa status . Cooperating processes may use other values; in a program which might be called by a mail transfer agent, the values described in .Xr sysexits 3 may be used to provide more information to the parent process. .Pp Note that .Fn exit does nothing to prevent bottomless recursion should a function registered using .Xr atexit 3 itself call .Fn exit . Such functions must call .Fn _Exit instead (although this has other effects as well which may not be desired). .Sh RETURN VALUES The .Fn exit and .Fn _Exit functions never return. .Sh SEE ALSO .Xr _exit 2 , .Xr wait 2 , -.Xr atexit 3 , .Xr at_quick_exit 3 , +.Xr atexit 3 , .Xr intro 3 , .Xr quick_exit 3 , .Xr sysexits 3 , .Xr tmpfile 3 .Sh STANDARDS The .Fn exit and .Fn _Exit functions conform to .St -isoC-99 . Index: projects/sendfile/lib/libc/string/strspn.3 =================================================================== --- projects/sendfile/lib/libc/string/strspn.3 (revision 276056) +++ projects/sendfile/lib/libc/string/strspn.3 (revision 276057) @@ -1,111 +1,111 @@ .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" Chris Torek and the American National Standards Committee X3, .\" on Information Processing Systems. .\" .\" 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. 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. .\" .\" @(#)strspn.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" .Dd May 24, 2014 .Dt STRSPN 3 .Os .Sh NAME .Nm strspn , .Nm strcspn .Nd span a string .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In string.h .Ft size_t .Fn strspn "const char *s" "const char *charset" .Ft size_t .Fn strcspn "const char *s" "const char *charset" .Sh DESCRIPTION The .Fn strspn function spans the initial part of the null-terminated string .Fa s as long as the characters from .Fa s occur in the null-terminated string .Fa charset . In other words, it computes the string array index of the first character of .Fa s which is not in .Fa charset , else the index of the first null character. .Pp The .Fn strcspn function spans the initial part of the null-terminated string .Fa s as long as the characters from .Fa s -.Sy do not +.Sy do not occur in the null-terminated string .Fa charset .Po it spans the .Sy complement of .Fa charset .Pc . In other words, it computes the string array index of the first character of .Fa s which is also in .Fa charset , else the index of the first null character. .Sh RETURN VALUES The .Fn strspn and .Fn strcspn functions return the number of characters spanned. .Sh SEE ALSO .Xr memchr 3 , .Xr strchr 3 , .Xr strpbrk 3 , .Xr strrchr 3 , .Xr strsep 3 , .Xr strstr 3 , .Xr strtok 3 , .Xr wcsspn 3 .Sh STANDARDS The .Fn strspn and .Fn strcspn functions conform to .St -isoC . Index: projects/sendfile/lib/libc/sys/access.2 =================================================================== --- projects/sendfile/lib/libc/sys/access.2 (revision 276056) +++ projects/sendfile/lib/libc/sys/access.2 (revision 276057) @@ -1,243 +1,243 @@ .\" Copyright (c) 1980, 1991, 1993 .\" The Regents of the University of California. 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. .\" 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. .\" .\" @(#)access.2 8.2 (Berkeley) 4/1/94 .\" $FreeBSD$ .\" .Dd September 15, 2014 .Dt ACCESS 2 .Os .Sh NAME .Nm access , .Nm eaccess , .Nm faccessat .Nd check accessibility of a file .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In unistd.h .Ft int .Fn access "const char *path" "int mode" .Ft int .Fn eaccess "const char *path" "int mode" .Ft int .Fn faccessat "int fd" "const char *path" "int mode" "int flag" .Sh DESCRIPTION The .Fn access and .Fn eaccess system calls check the accessibility of the file named by the .Fa path argument for the access permissions indicated by the .Fa mode argument. The value of .Fa mode is either the bitwise-inclusive OR of the access permissions to be checked .Dv ( R_OK for read permission, .Dv W_OK for write permission, and .Dv X_OK for execute/search permission), or the existence test .Pq Dv F_OK . .Pp For additional information, see the .Sx "File Access Permission" section of .Xr intro 2 . .Pp The .Fn eaccess system call uses the effective user ID and the group access list to authorize the request; the .Fn access system call uses the real user ID in place of the effective user ID, the real group ID in place of the effective group ID, and the rest of the group access list. .Pp The .Fn faccessat system call is equivalent to .Fn access except in the case where .Fa path specifies a relative path. In this case the file whose accessibility is to be determined is located relative to the directory associated with the file descriptor .Fa fd instead of the current working directory. If .Fn faccessat is passed the special value .Dv AT_FDCWD in the .Fa fd parameter, the current working directory is used and the behavior is identical to a call to .Fn access . Values for .Fa flag are constructed by a bitwise-inclusive OR of flags from the following list, defined in .In fcntl.h : .Bl -tag -width indent .It Dv AT_EACCESS The checks for accessibility are performed using the effective user and group IDs instead of the real user and group ID as required in a call to .Fn access . .El .Pp Even if a process's real or effective user has appropriate privileges and indicates success for .Dv X_OK , the file may not actually have execute permission bits set. Likewise for .Dv R_OK and .Dv W_OK . .Sh RETURN VALUES .Rv -std .Sh ERRORS .Fn access , .Fn eaccess , or -.Fn faccessat +.Fn faccessat will fail if: .Bl -tag -width Er .It Bq Er EINVAL The value of the .Fa mode argument is invalid. .It Bq Er ENOTDIR A component of the path prefix is not a directory. .It Bq Er ENAMETOOLONG A component of a pathname exceeded 255 characters, or an entire path name exceeded 1023 characters. .It Bq Er ENOENT The named file does not exist. .It Bq Er ELOOP Too many symbolic links were encountered in translating the pathname. .It Bq Er EROFS Write access is requested for a file on a read-only file system. .It Bq Er ETXTBSY Write access is requested for a pure procedure (shared text) file presently being executed. .It Bq Er EACCES Permission bits of the file mode do not permit the requested access, or search permission is denied on a component of the path prefix. .It Bq Er EFAULT The .Fa path argument points outside the process's allocated address space. .It Bq Er EIO An I/O error occurred while reading from or writing to the file system. .El .Pp Also, the .Fn faccessat system call may fail if: .Bl -tag -width Er .It Bq Er EBADF The .Fa path argument does not specify an absolute path and the .Fa fd argument is neither .Dv AT_FDCWD nor a valid file descriptor. .It Bq Er EINVAL The value of the .Fa flag argument is not valid. .It Bq Er ENOTDIR The .Fa path argument is not an absolute path and .Fa fd is neither .Dv AT_FDCWD nor a file descriptor associated with a directory. .El .Sh SEE ALSO .Xr chmod 2 , .Xr intro 2 , .Xr stat 2 .Sh STANDARDS The .Fn access system call is expected to conform to .St -p1003.1-90 . The .Fn faccessat system call follows The Open Group Extended API Set 2 specification. .Sh HISTORY The .Fn access function appeared in .At v7 . The .Fn faccessat system call appeared in .Fx 8.0 . .Sh SECURITY CONSIDERATIONS The .Fn access system call is a potential security hole due to race conditions and should never be used. Set-user-ID and set-group-ID applications should restore the effective user or group ID, and perform actions directly rather than use .Fn access to simulate access checks for the real user or group ID. The .Fn eaccess system call likewise may be subject to races if used inappropriately. .Pp .Fn access remains useful for providing clues to users as to whether operations make sense for particular filesystem objects (e.g. 'delete' menu item only highlighted in a writable folder ... avoiding interpretation of the st_mode bits that the application might not understand -- e.g. in the case of AFS). It also allows a cheaper file existence test than .Xr stat 2 . Index: projects/sendfile/lib/libc/sys/getdirentries.2 =================================================================== --- projects/sendfile/lib/libc/sys/getdirentries.2 (revision 276056) +++ projects/sendfile/lib/libc/sys/getdirentries.2 (revision 276057) @@ -1,185 +1,186 @@ .\" Copyright (c) 1989, 1991, 1993 .\" The Regents of the University of California. 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. .\" 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. .\" .\" @(#)getdirentries.2 8.2 (Berkeley) 5/3/95 .\" $FreeBSD$ .\" .Dd May 3, 1995 .Dt GETDIRENTRIES 2 .Os .Sh NAME .Nm getdirentries , .Nm getdents .Nd "get directory entries in a file system independent format" .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In sys/types.h .In dirent.h .Ft int .Fn getdirentries "int fd" "char *buf" "int nbytes" "long *basep" .Ft int .Fn getdents "int fd" "char *buf" "int nbytes" .Sh DESCRIPTION The .Fn getdirentries and .Fn getdents system calls read directory entries from the directory referenced by the file descriptor .Fa fd into the buffer pointed to by .Fa buf , in a file system independent format. Up to .Fa nbytes of data will be transferred. The .Fa nbytes argument must be greater than or equal to the block size associated with the file, see .Xr stat 2 . Some file systems may not support these system calls with buffers smaller than this size. .Pp The data in the buffer is a series of .Vt dirent structures each containing the following entries: .Bd -literal -offset indent uint32_t d_fileno; uint16_t d_reclen; uint8_t d_type; uint8_t d_namlen; char d_name[MAXNAMELEN + 1]; /* see below */ .Ed .Pp The .Fa d_fileno entry is a number which is unique for each distinct file in the file system. Files that are linked by hard links (see .Xr link 2 ) have the same .Fa d_fileno . The .Fa d_reclen entry is the length, in bytes, of the directory record. The .Fa d_type entry is the type of the file pointed to by the directory record. The file type values are defined in .Fa . The .Fa d_name entry contains a null terminated file name. The .Fa d_namlen entry specifies the length of the file name excluding the null byte. Thus the actual size of .Fa d_name may vary from 1 to .Dv MAXNAMELEN \&+ 1. .Pp Entries may be separated by extra space. The .Fa d_reclen entry may be used as an offset from the start of a .Fa dirent structure to the next structure, if any. .Pp The actual number of bytes transferred is returned. The current position pointer associated with .Fa fd is set to point to the next block of entries. The pointer may not advance by the number of bytes returned by .Fn getdirentries or .Fn getdents . A value of zero is returned when the end of the directory has been reached. .Pp The .Fn getdirentries system call writes the position of the block read into the location pointed to by .Fa basep . Alternatively, the current position pointer may be set and retrieved by .Xr lseek 2 . The current position pointer should only be set to a value returned by .Xr lseek 2 , a value returned in the location pointed to by .Fa basep -.Fn ( getdirentries -only) +.Po Fn getdirentries +only +.Pc or zero. .Sh RETURN VALUES If successful, the number of bytes actually transferred is returned. Otherwise, -1 is returned and the global variable .Va errno is set to indicate the error. .Sh ERRORS The .Fn getdirentries system call will fail if: .Bl -tag -width Er .It Bq Er EBADF The .Fa fd argument is not a valid file descriptor open for reading. .It Bq Er EFAULT Either .Fa buf or .Fa basep point outside the allocated address space. .It Bq Er EINVAL The file referenced by .Fa fd is not a directory, or .Fa nbytes is too small for returning a directory entry or block of entries, or the current position pointer is invalid. .It Bq Er EIO An .Tn I/O error occurred while reading from or writing to the file system. .El .Sh SEE ALSO .Xr lseek 2 , .Xr open 2 .Sh HISTORY The .Fn getdirentries system call first appeared in .Bx 4.4 . The .Fn getdents system call first appeared in .Fx 3.0 . Index: projects/sendfile/lib/libc/sys/getrlimit.2 =================================================================== --- projects/sendfile/lib/libc/sys/getrlimit.2 (revision 276056) +++ projects/sendfile/lib/libc/sys/getrlimit.2 (revision 276057) @@ -1,205 +1,205 @@ .\" Copyright (c) 1980, 1991, 1993 .\" The Regents of the University of California. 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. .\" 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. .\" .\" @(#)getrlimit.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" .Dd August 20, 2008 .Dt GETRLIMIT 2 .Os .Sh NAME .Nm getrlimit , .Nm setrlimit .Nd control maximum system resource consumption .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In sys/types.h .In sys/time.h .In sys/resource.h .Ft int .Fn getrlimit "int resource" "struct rlimit *rlp" .Ft int .Fn setrlimit "int resource" "const struct rlimit *rlp" .Sh DESCRIPTION Limits on the consumption of system resources by the current process and each process it creates may be obtained with the .Fn getrlimit system call, and set with the .Fn setrlimit system call. .Pp The .Fa resource argument is one of the following: .Bl -tag -width RLIMIT_FSIZEAA .It Dv RLIMIT_AS The maximum amount (in bytes) of virtual memory the process is allowed to map. .It Dv RLIMIT_CORE The largest size (in bytes) .Xr core 5 file that may be created. .It Dv RLIMIT_CPU The maximum amount of cpu time (in seconds) to be used by each process. .It Dv RLIMIT_DATA The maximum size (in bytes) of the data segment for a process; this defines how far a program may extend its break with the .Xr sbrk 2 function. .It Dv RLIMIT_FSIZE The largest size (in bytes) file that may be created. .It Dv RLIMIT_MEMLOCK The maximum size (in bytes) which a process may lock into memory using the .Xr mlock 2 system call. .It Dv RLIMIT_NOFILE The maximum number of open files for this process. .It Dv RLIMIT_NPROC The maximum number of simultaneous processes for this user id. .It Dv RLIMIT_RSS The maximum size (in bytes) to which a process's resident set size may grow. This imposes a limit on the amount of physical memory to be given to a process; if memory is tight, the system will prefer to take memory from processes that are exceeding their declared resident set size. .It Dv RLIMIT_SBSIZE The maximum size (in bytes) of socket buffer usage for this user. This limits the amount of network memory, and hence the amount of mbufs, that this user may hold at any time. .It Dv RLIMIT_STACK The maximum size (in bytes) of the stack segment for a process; this defines how far a program's stack segment may be extended. Stack extension is performed automatically by the system. .It Dv RLIMIT_SWAP The maximum size (in bytes) of the swap space that may be reserved or used by all of this user id's processes. This limit is enforced only if bit 1 of the .Va vm.overcommit sysctl is set. Please see .Xr tuning 7 for a complete description of this sysctl. .It Dv RLIMIT_NPTS The maximum number of pseudo-terminals created by this user id. .It Dv RLIMIT_KQUEUES The maximum number of kqueues created by this user id. .El .Pp A resource limit is specified as a soft limit and a hard limit. When a soft limit is exceeded a process may receive a signal (for example, if the cpu time or file size is exceeded), but it will be allowed to continue execution until it reaches the hard limit (or modifies its resource limit). The .Vt rlimit structure is used to specify the hard and soft limits on a resource, .Bd -literal -offset indent struct rlimit { rlim_t rlim_cur; /* current (soft) limit */ rlim_t rlim_max; /* maximum value for rlim_cur */ }; .Ed .Pp Only the super-user may raise the maximum limits. Other users may only alter .Fa rlim_cur within the range from 0 to .Fa rlim_max or (irreversibly) lower .Fa rlim_max . .Pp An .Dq infinite value for a limit is defined as .Dv RLIM_INFINITY . .Pp Because this information is stored in the per-process information, this system call must be executed directly by the shell if it is to affect all future processes created by the shell; .Ic limit is thus a built-in command to .Xr csh 1 . .Pp The system refuses to extend the data or stack space when the limits would be exceeded in the normal way: a .Xr brk 2 function fails if the data space limit is reached. When the stack limit is reached, the process receives a segmentation fault .Pq Dv SIGSEGV ; if this signal is not caught by a handler using the signal stack, this signal will kill the process. .Pp A file I/O operation that would create a file larger that the process' soft limit will cause the write to fail and a signal .Dv SIGXFSZ to be generated; this normally terminates the process, but may be caught. When the soft cpu time limit is exceeded, a signal .Dv SIGXCPU is sent to the offending process. .Sh RETURN VALUES .Rv -std .Sh ERRORS The .Fn getrlimit and .Fn setrlimit system calls will fail if: .Bl -tag -width Er .It Bq Er EFAULT The address specified for .Fa rlp is invalid. .It Bq Er EPERM The limit specified to .Fn setrlimit would have raised the maximum limit value, and the caller is not the super-user. .El .Sh SEE ALSO .Xr csh 1 , .Xr quota 1 , .Xr quotactl 2 , -.Xr sigaltstack 2 , .Xr sigaction 2 , +.Xr sigaltstack 2 , .Xr sysctl 3 , .Xr ulimit 3 .Sh HISTORY The .Fn getrlimit system call appeared in .Bx 4.2 . Index: projects/sendfile/lib/libc/sys/poll.2 =================================================================== --- projects/sendfile/lib/libc/sys/poll.2 (revision 276056) +++ projects/sendfile/lib/libc/sys/poll.2 (revision 276057) @@ -1,273 +1,273 @@ .\" $NetBSD: poll.2,v 1.3 1996/09/07 21:53:08 mycroft Exp $ .\" $FreeBSD$ .\" .\" Copyright (c) 1996 Charles M. Hannum. 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 Charles M. Hannum. .\" 4. The name of the author may not be used to endorse or promote products .\" derived from this software without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. .\" .Dd November 13, 2014 .Dt POLL 2 .Os .Sh NAME .Nm poll .Nd synchronous I/O multiplexing .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In poll.h .Ft int .Fn poll "struct pollfd fds[]" "nfds_t nfds" "int timeout" .Ft int .Fo ppoll .Fa "struct pollfd fds[]" .Fa "nfds_t nfds" .Fa "const struct timespec * restrict timeout" .Fa "const sigset_t * restrict newsigmask" .Fc .Sh DESCRIPTION The .Fn poll system call examines a set of file descriptors to see if some of them are ready for I/O. The .Fa fds argument is a pointer to an array of pollfd structures as defined in .In poll.h (shown below). The .Fa nfds argument determines the size of the .Fa fds array. .Bd -literal struct pollfd { int fd; /* file descriptor */ short events; /* events to look for */ short revents; /* events returned */ }; .Ed .Pp The fields of .Fa struct pollfd are as follows: .Bl -tag -width XXXrevents .It fd File descriptor to poll. If fd is equal to -1 then .Fa revents is cleared (set to zero), and that pollfd is not checked. .It events Events to poll for. (See below.) .It revents Events which may occur. (See below.) .El .Pp The event bitmasks in .Fa events and .Fa revents have the following bits: .Bl -tag -width XXXPOLLWRNORM .It POLLIN Data other than high priority data may be read without blocking. .It POLLRDNORM Normal data may be read without blocking. .It POLLRDBAND Data with a non-zero priority may be read without blocking. .It POLLPRI High priority data may be read without blocking. .It POLLOUT .It POLLWRNORM Normal data may be written without blocking. .It POLLWRBAND Data with a non-zero priority may be written without blocking. .It POLLERR An exceptional condition has occurred on the device or socket. This flag is always checked, even if not present in the .Fa events bitmask. .It POLLHUP The device or socket has been disconnected. This flag is always checked, even if not present in the .Fa events bitmask. Note that POLLHUP and POLLOUT should never be present in the .Fa revents bitmask at the same time. .It POLLNVAL The file descriptor is not open. This flag is always checked, even if not present in the .Fa events bitmask. .El .Pp If .Fa timeout is neither zero nor INFTIM (-1), it specifies a maximum interval to wait for any file descriptor to become ready, in milliseconds. If .Fa timeout is INFTIM (-1), the poll blocks indefinitely. If .Fa timeout is zero, then .Fn poll will return without blocking. .Pp The -.Fn ppoll -system call, unlike +.Fn ppoll +system call, unlike .Fn poll , is used to safely wait until either a set of file descriptors becomes ready or until a signal is caught. The .Fa fds and .Fa nfds arguments are identical to the analogous arguments of .Fn poll . The .Fa timeout argument in .Fn ppoll points to a .Vt "const struct timespec" which is defined in .In sys/timespec.h (shown below) rather than the .Vt "int timeout" used by .Fn poll . A null pointer may be passed to indicate that .Fn ppoll should wait indefinitely. -Finally, +Finally, .Fa newsigmask specifies a signal mask which is set while waiting for input. -When +When .Fn ppoll returns, the original signal mask is restored. .Bd -literal struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* and nanoseconds */ }; .Ed .Sh RETURN VALUES The .Fn poll system call returns the number of descriptors that are ready for I/O, or -1 if an error occurred. If the time limit expires, .Fn poll returns 0. If .Fn poll returns with an error, including one due to an interrupted system call, the .Fa fds array will be unmodified. .Sh COMPATIBILITY This implementation differs from the historical one in that a given file descriptor may not cause .Fn poll to return with an error. In cases where this would have happened in the historical implementation (e.g.\& trying to poll a .Xr revoke 2 Ns ed descriptor), this implementation instead copies the .Fa events bitmask to the .Fa revents bitmask. Attempting to perform I/O on this descriptor will then return an error. This behaviour is believed to be more useful. .Sh ERRORS An error return from .Fn poll indicates: .Bl -tag -width Er .It Bq Er EFAULT The .Fa fds argument points outside the process's allocated address space. .It Bq Er EINTR A signal was delivered before the time limit expired and before any of the selected events occurred. .It Bq Er EINVAL The specified time limit is invalid. One of its components is negative or too large. .El .Sh SEE ALSO .Xr accept 2 , .Xr connect 2 , .Xr kqueue 2 , .Xr pselect 2 , .Xr read 2 , .Xr recv 2 , .Xr select 2 , .Xr send 2 , .Xr write 2 .Sh STANDARDS The -.Fn poll +.Fn poll function conforms to .St -p1003.1-2001 . The -.Fn ppoll +.Fn ppoll is not specified by POSIX. .Sh HISTORY The .Fn poll function appeared in .At V . This manual page and the core of the implementation was taken from .Nx . The .Fn ppoll -function first appeared in -.Fx 11.0 +function first appeared in +.Fx 11.0 .Sh BUGS The distinction between some of the fields in the .Fa events and .Fa revents bitmasks is really not useful without STREAMS. The fields are defined for compatibility with existing software. Index: projects/sendfile/lib/libc/sys/posix_openpt.2 =================================================================== --- projects/sendfile/lib/libc/sys/posix_openpt.2 (revision 276056) +++ projects/sendfile/lib/libc/sys/posix_openpt.2 (revision 276057) @@ -1,140 +1,140 @@ .\" Copyright (c) 2008 Ed Schouten .\" All rights reserved. .\" .\" Portions of this software were developed under sponsorship from Snow .\" B.V., the Netherlands. .\" .\" 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. .\" .\" Portions of this text are reprinted and reproduced in electronic form .\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- .\" Portable Operating System Interface (POSIX), The Open Group Base .\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of .\" Electrical and Electronics Engineers, Inc and The Open Group. In the .\" event of any discrepancy between this version and the original IEEE and .\" The Open Group Standard, the original IEEE and The Open Group Standard is .\" the referee document. The original Standard can be obtained online at .\" http://www.opengroup.org/unix/online.html. .\" .\" $FreeBSD$ .\" .Dd March 21, 2013 .Dt POSIX_OPENPT 2 .Os .Sh NAME .Nm posix_openpt .Nd "open a pseudo-terminal device" .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In stdlib.h .In fcntl.h .Ft int .Fn posix_openpt "int oflag" .Sh DESCRIPTION The .Fn posix_openpt function allocates a new pseudo-terminal and establishes a connection with its master device. A slave device shall be created in .Pa /dev/pts . After the pseudo-terminal has been allocated, the slave device should have the proper permissions before it can be used (see .Xr grantpt 3 ) . The name of the slave device can be determined by calling .Xr ptsname 3 . .Pp The file status flags and file access modes of the open file description shall be set according to the value of .Fa oflag . Values for .Fa oflag are constructed by a bitwise-inclusive OR of flags from the following list, defined in .In fcntl.h : .Bl -tag -width ".Dv O_CLOEXEC" .It Dv O_RDWR Open for reading and writing. .It Dv O_NOCTTY If set .Fn posix_openpt shall not cause the terminal device to become the controlling terminal for the process. .It Dv O_CLOEXEC Set the close-on-exec flag for the new file descriptor. .El .Pp The .Fn posix_openpt function shall fail when .Fa oflag contains other values. .Sh RETURN VALUES Upon successful completion, the .Fn posix_openpt function shall allocate a new pseudo-terminal device and return a non-negative integer representing a file descriptor, which is connected to its master device. Otherwise, -1 shall be returned and errno set to indicate the error. .Sh ERRORS The .Fn posix_openpt function shall fail if: .Bl -tag -width Er .It Bq Er ENFILE The system file table is full. .It Bq Er EINVAL The value of .Fa oflag is not valid. .It Bq Er EAGAIN Out of pseudo-terminal resources. .El .Sh SEE ALSO -.Xr pts 4 , .Xr ptsname 3 , +.Xr pts 4 , .Xr tty 4 .Sh STANDARDS The .Fn posix_openpt function conforms to .St -p1003.1-2001 . The ability to use .Dv O_CLOEXEC is an extension to the standard. .Sh HISTORY The .Fn posix_openpt function appeared in .Fx 5.0 . In .Fx 8.0 , this function was changed to a system call. .Sh NOTES The flag .Dv O_NOCTTY is included for compatibility; in .Fx , opening a terminal does not cause it to become a process's controlling terminal. .Sh AUTHORS .An Ed Schouten Aq Mt ed@FreeBSD.org Index: projects/sendfile/lib/libc/sys/procctl.2 =================================================================== --- projects/sendfile/lib/libc/sys/procctl.2 (revision 276056) +++ projects/sendfile/lib/libc/sys/procctl.2 (revision 276057) @@ -1,359 +1,359 @@ .\" Copyright (c) 2013 Advanced Computing Technologies LLC .\" Written by: John H. Baldwin .\" All rights reserved. .\" .\" Copyright (c) 2014 The FreeBSD Foundation .\" Portions of this documentation were written by Konstantin Belousov .\" under sponsorship from the FreeBSD Foundation. .\" .\" 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$ .\" .Dd December 16, 2014 .Dt PROCCTL 2 .Os .Sh NAME .Nm procctl .Nd control processes .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In sys/procctl.h .Ft int .Fn procctl "idtype_t idtype" "id_t id" "int cmd" "void *arg" .Sh DESCRIPTION The .Fn procctl system call provides for control over processes. The .Fa idtype and .Fa id arguments specify the set of processes to control. If multiple processes match the identifier, .Nm will make a .Dq best effort to control as many of the selected processes as possible. An error is only returned if no selected processes successfully complete the request. The following identifier types are supported: .Bl -tag -width "Dv P_PGID" .It Dv P_PID Control the process with the process ID .Fa id . .It Dv P_PGID Control processes belonging to the process group with the ID .Fa id . .El .Pp The control request to perform is specified by the .Fa cmd argument. The following commands are supported: .Bl -tag -width "Dv PROC_REAP_GETPIDS" .It Dv PROC_SPROTECT Set process protection state. This is used to mark a process as protected from being killed if the system exhausts available memory and swap. The .Fa arg parameter must point to an integer containing an operation and zero or more optional flags. The following operations are supported: .Bl -tag -width "Dv PPROT_CLEAR" .It Dv PPROT_SET Mark the selected processes as protected. .It Dv PPROT_CLEAR Clear the protected state of selected processes. .El .Pp The following optional flags are supported: .Bl -tag -width "Dv PPROT_DESCE" .It Dv PPROT_DESCEND Apply the requested operation to all child processes of each selected process in addition to each selected process. .It Dv PPROT_INHERIT When used with .Dv PPROT_SET , mark all future child processes of each selected process as protected. Future child processes will also mark all of their future child processes. .El .It Dv PROC_REAP_ACQUIRE Acquires the reaper status for the current process. The status means that children orphaned by the reaper's descendants that were forked after the acquisition of the status are reparented to the reaper. After the system initialization, .Xr init 8 is the default reaper. -.Pp .It Dv PROC_REAP_RELEASE Releases the reaper state for the current process. The reaper of the current process becomes the new reaper of the current process's descendants. .It Dv PROC_REAP_STATUS Provides the information about the reaper of the specified process, or the process itself when it is a reaper. The .Fa data argument must point to a .Vt procctl_reaper_status structure which is filled in by the syscall on successful return. .Bd -literal struct procctl_reaper_status { u_int rs_flags; u_int rs_children; u_int rs_descendants; pid_t rs_reaper; pid_t rs_pid; }; .Ed The .Fa rs_flags may have the following flags returned: .Bl -tag -width "Dv REAPER_STATUS_REALINIT" .It Dv REAPER_STATUS_OWNED The specified process has acquired the reaper status and has not released it. When the flag is returned, the specified process .Fa id , pid, identifies the reaper, otherwise the .Fa rs_reaper field of the structure is set to the pid of the reaper for the specified process id. .It Dv REAPER_STATUS_REALINIT The specified process is the root of the reaper tree, i.e. .Xr init 8 . .El +.Pp The .Fa rs_children field returns the number of children of the reaper. The .Fa rs_descendants field returns the total number of descendants of the reaper(s), not counting descendants of the reaper in the subtree. The .Fa rs_reaper field returns the reaper pid. The .Fa rs_pid returns the pid of one reaper child if there are any descendants. .It Dv PROC_REAP_GETPIDS Queries the list of descendants of the reaper of the specified process. The request takes a pointer to a .Vt procctl_reaper_pids structure in the .Fa data parameter. .Bd -literal struct procctl_reaper_pids { u_int rp_count; struct procctl_reaper_pidinfo *rp_pids; }; .Ed When called, the .Fa rp_pids field must point to an array of .Vt procctl_reaper_pidinfo structures, to be filled in on return, and the .Fa rp_count field must specify the size of the array, into which no more than .Fa rp_count elements will be filled in by the kernel. .Pp The .Vt "struct procctl_reaper_pidinfo" structure provides some information about one of the reaper's descendants. Note that for a descendant that is not a child, it may be incorrectly identified because of a race in which the original child process exited and the exited process's pid was reused for an unrelated process. .Bd -literal struct procctl_reaper_pidinfo { pid_t pi_pid; pid_t pi_subtree; u_int pi_flags; }; .Ed The .Fa pi_pid field is the process id of the descendant. The .Fa pi_subtree field provides the pid of the child of the reaper, which is the (grand-)parent of the process. The .Fa pi_flags field returns the following flags, further describing the descendant: .Bl -tag -width "Dv REAPER_PIDINFO_VALID" .It Dv REAPER_PIDINFO_VALID Set to indicate that the .Vt procctl_reaper_pidinfo structure was filled in by the kernel. Zero-filling the .Fa rp_pids array and testing the .Dv REAPER_PIDINFO_VALID flag allows the caller to detect the end of the returned array. .It Dv REAPER_PIDINFO_CHILD The .Fa pi_pid field identifies the direct child of the reaper. .El .It Dv PROC_REAP_KILL Request to deliver a signal to some subset of the descendants of the reaper. The .Fa data parameter must point to a .Vt procctl_reaper_kill structure, which is used both for parameters and status return. .Bd -literal struct procctl_reaper_kill { int rk_sig; u_int rk_flags; pid_t rk_subtree; u_int rk_killed; pid_t rk_fpid; }; .Ed The .Fa rk_sig field specifies the signal to be delivered. Zero is not a valid signal number, unlike .Xr kill 2 . The .Fa rk_flags field further directs the operation. It is or-ed from the following flags: .Bl -tag -width "Dv REAPER_KILL_CHILDREN" .It Dv REAPER_KILL_CHILDREN Deliver the specified signal only to direct children of the reaper. .It Dv REAPER_KILL_SUBTREE Deliver the specified signal only to descendants that were forked by the direct child with pid specified in the .Fa rk_subtree field. .El If neither the .Dv REAPER_KILL_CHILDREN nor the .Dv REAPER_KILL_SUBTREE flags are specified, all current descendants of the reaper are signalled. .Pp If a signal was delivered to any process, the return value from the request is zero. In this case, the .Fa rk_killed field identifies the number of processes signalled. The .Fa rk_fpid field is set to the pid of the first process for which signal delivery failed, e.g. due to the permission problems. If no such process exist, the .Fa rk_fpid field is set to -1. .El .Sh RETURN VALUES If an error occurs, a value of -1 is returned and .Va errno is set to indicate the error. .Sh ERRORS The .Fn procctl system call will fail if: .Bl -tag -width Er .It Bq Er EFAULT The .Fa arg parameter points outside the process's allocated address space. .It Bq Er EINVAL The .Fa cmd argument specifies an unsupported command. .Pp The .Fa idtype argument specifies an unsupported identifier type. .It Bq Er EPERM The calling process does not have permission to perform the requested operation on any of the selected processes. .It Bq Er ESRCH No processes matched the requested .Fa idtype and .Fa id . .It Bq Er EINVAL An invalid operation or flag was passed in .Fa arg for a .Dv PROC_SPROTECT command. .It Bq Er EPERM The .Fa idtype argument is not equal to .Dv P_PID , or .Fa id is not equal to the pid of the calling process, for .Dv PROC_REAP_ACQUIRE or .Dv PROC_REAP_RELEASE requests. .It Bq Er EINVAL Invalid or undefined flags were passed to a .Dv PROC_REAP_KILL request. .It Bq Er EINVAL An invalid or zero signal number was requested for a .Dv PROC_REAP_KILL request. .It Bq Er EINVAL The .Dv PROC_REAP_RELEASE request was issued by the .Xr init 8 process. .It Bq Er EBUSY The .Dv PROC_REAP_ACQUIRE request was issued by a process that had already acquired reaper status and has not yet released it. .El .Sh SEE ALSO .Xr kill 2 , .Xr ptrace 2 , .Xr wait 2 , .Xr init 8 .Sh HISTORY The .Fn procctl function appeared in .Fx 10.0 . The reaper facility is based on a similar feature of Linux and DragonflyBSD, and first appeared in .Fx 10.2 . Index: projects/sendfile/lib/libc/sys/revoke.2 =================================================================== --- projects/sendfile/lib/libc/sys/revoke.2 (revision 276056) +++ projects/sendfile/lib/libc/sys/revoke.2 (revision 276057) @@ -1,106 +1,106 @@ .\" Copyright (c) 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" Berkeley Software Design, 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. .\" .\" @(#)revoke.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" .Dd June 4, 1993 .Dt REVOKE 2 .Os .Sh NAME .Nm revoke .Nd revoke file access .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In unistd.h .Ft int .Fn revoke "const char *path" .Sh DESCRIPTION The .Fn revoke system call invalidates all current open file descriptors in the system for the file named by .Fa path . Subsequent operations on any such descriptors fail, with the exceptions that a .Fn read from a character device file which has been revoked returns a count of zero (end of file), and a .Fn close system call will succeed. If the file is a special file for a device which is open, the device close function is called as if all open references to the file had been closed. .Pp Access to a file may be revoked only by its owner or the super user. The .Fn revoke system call is currently supported only for block and character special device files. It is normally used to prepare a terminal device for a new login session, preventing any access by a previous user of the terminal. .Sh RETURN VALUES .Rv -std revoke .Sh ERRORS Access to the named file is revoked unless one of the following: .Bl -tag -width Er .It Bq Er ENOTDIR A component of the path prefix is not a directory. .It Bq Er ENAMETOOLONG A component of a pathname exceeded 255 characters, or an entire path name exceeded 1024 characters. .It Bq Er ENOENT The named file or a component of the path name does not exist. .It Bq Er EACCES Search permission is denied for a component of the path prefix. .It Bq Er ELOOP Too many symbolic links were encountered in translating the pathname. .It Bq Er EFAULT The .Fa path argument points outside the process's allocated address space. .It Bq Er EINVAL The implementation does not support the .Fn revoke operation on the named file. .It Bq Er EPERM The caller is neither the owner of the file nor the super user. .El .Sh SEE ALSO -.Xr close 2 , -.Xr revoke 1 +.Xr revoke 1 , +.Xr close 2 .Sh HISTORY The .Fn revoke system call first appeared in .Bx 4.3 Reno . Index: projects/sendfile/lib/libc/sys/sched_setscheduler.2 =================================================================== --- projects/sendfile/lib/libc/sys/sched_setscheduler.2 (revision 276056) +++ projects/sendfile/lib/libc/sys/sched_setscheduler.2 (revision 276057) @@ -1,166 +1,166 @@ .\" $FreeBSD$ .\" Copyright (c) 1998 HD Associates, Inc. .\" 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. .\" .Dd March 12, 1998 .Dt SCHED_SETSCHEDULER 2 .Os .Sh NAME .Nm sched_setscheduler , .Nm sched_getscheduler .Nd set/get scheduling policy and scheduler parameters .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In sched.h .Ft int .Fn sched_setscheduler "pid_t pid" "int policy" "const struct sched_param *param" .Ft int .Fn sched_getscheduler "pid_t pid" .Sh DESCRIPTION The .Fn sched_setscheduler system call sets the scheduling policy and scheduling parameters of the process specified by .Fa pid to .Fa policy and the parameters specified in the .Vt sched_param structure pointed to by .Fa param , respectively. The value of the .Fa sched_priority member in the .Fa param structure must be any integer within the inclusive priority range for the scheduling policy specified by .Fa policy . .Pp In this implementation, if the value of .Fa pid is negative the system call will fail. .Pp If a process specified by .Fa pid exists and if the calling process has permission, the scheduling policy and scheduling parameters will be set for the process whose process ID is equal to .Fa pid . .Pp If .Fa pid is zero, the scheduling policy and scheduling parameters are set for the calling process. .Pp In this implementation, the policy of when a process can affect the scheduling parameters of another process is specified in .St -p1003.1b-93 as a write-style operation. .Pp The scheduling policies are in .Fa : .Bl -tag -width [SCHED_OTHER] .It Bq Er SCHED_FIFO First-in-first-out fixed priority scheduling with no round robin scheduling; .It Bq Er SCHED_OTHER The standard time sharing scheduler; .It Bq Er SCHED_RR Round-robin scheduling across same priority processes. .El .Pp The .Vt sched_param structure is defined in .Fa : .Bd -literal -offset indent struct sched_param { int sched_priority; /* scheduling priority */ }; .Ed .Pp The .Fn sched_getscheduler system call returns the scheduling policy of the process specified by .Fa pid . .Pp If a process specified by .Fa pid exists and if the calling process has permission, the scheduling parameters for the process whose process ID is equal to .Fa pid are returned. .Pp In this implementation, the policy of when a process can obtain the scheduling parameters of another process are detailed in .St -p1003.1b-93 as a read-style operation. .Pp If .Fa pid is zero, the scheduling parameters for the calling process will be returned. In this implementation, the .Fa sched_getscheduler system call will fail if .Fa pid is negative. .Sh RETURN VALUES .Rv -std .Sh ERRORS On failure .Va errno will be set to the corresponding value: .Bl -tag -width Er .It Bq Er ENOSYS The system is not configured to support this functionality. .It Bq Er EPERM The requesting process doesn not have permission as detailed in .St -p1003.1b-93 . .It Bq Er ESRCH No process can be found corresponding to that specified by .Fa pid . .It Bq Er EINVAL The value of the .Fa policy argument is invalid, or one or more of the parameters contained in .Fa param is outside the valid range for the specified scheduling policy. .El .Sh SEE ALSO -.Xr sched_getparam 2 , .Xr sched_get_priority_max 2 , .Xr sched_get_priority_min 2 , +.Xr sched_getparam 2 , .Xr sched_rr_get_interval 2 , .Xr sched_setparam 2 , .Xr sched_yield 2 .Sh STANDARDS The .Fn sched_setscheduler and .Fn sched_getscheduler system calls conform to .St -p1003.1b-93 . Index: projects/sendfile/lib/libc/sys/sigwaitinfo.2 =================================================================== --- projects/sendfile/lib/libc/sys/sigwaitinfo.2 (revision 276056) +++ projects/sendfile/lib/libc/sys/sigwaitinfo.2 (revision 276057) @@ -1,206 +1,206 @@ .\" Copyright (c) 2005 David Xu .\" 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(s), this list of conditions and the following disclaimer as .\" the first lines of this file unmodified other than the possible .\" addition of one or more copyright notices. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice(s), 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 COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ .\" .Dd September 27, 2012 .Dt SIGTIMEDWAIT 2 .Os .Sh NAME .Nm sigtimedwait , sigwaitinfo .Nd "wait for queued signals (REALTIME)" .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In signal.h .Ft int .Fo sigtimedwait .Fa "const sigset_t *restrict set" "siginfo_t *restrict info" .Fa "const struct timespec *restrict timeout" .Fc .Ft int .Fn sigwaitinfo "const sigset_t * restrict set" "siginfo_t * restrict info" .Sh DESCRIPTION The .Fn sigtimedwait system call is equivalent to .Fn sigwaitinfo except that if none of the signals specified by .Fa set are pending, .Fn sigtimedwait waits for the time interval specified in the .Vt timespec structure referenced by .Fa timeout . If the .Vt timespec structure pointed to by .Fa timeout is zero-valued and if none of the signals specified by .Fa set are pending, then .Fn sigtimedwait returns immediately with an error. If .Fa timeout is the .Dv NULL pointer, the behavior is unspecified. .Dv CLOCK_MONOTONIC clock is used to measure the time interval specified by the .Fa timeout argument. .Pp The .Fn sigwaitinfo system call selects the pending signal from the set specified by .Fa set . Should any of multiple pending signals in the range .Dv SIGRTMIN to .Dv SIGRTMAX be selected, it shall be the lowest numbered one. The selection order between realtime and non-realtime signals, or between multiple pending non-realtime signals, is unspecified. If no signal in .Fa set is pending at the time of the call, the calling thread is suspended until one or more signals in .Fa set become pending or until it is interrupted by an unblocked, caught signal. .Pp The .Fn sigwaitinfo system call is equivalent to the .Fn sigwait system call if the .Fa info argument is .Dv NULL . If the .Fa info argument is .Pf non- Dv NULL , the .Fn sigwaitinfo function is equivalent to .Fn sigwait , except that the selected signal number shall be stored in the .Va si_signo member, and the cause of the signal shall be stored in the .Va si_code member. Besides this, the .Fn sigwaitinfo and .Fn sigtimedwait system calls may return .Er EINTR if interrupted by signal, which is not allowed for the .Fn sigwait function. .Pp If any value is queued to the selected signal, the first such queued value is dequeued and, if the info argument is .Pf non- Dv NULL , the value is stored in the .Va si_value member of .Fa info . The system resource used to queue the signal is released and returned to the system for other use. If no value is queued, the content of the .Va si_value member is zero-valued. If no further signals are queued for the selected signal, the pending indication for that signal is reset. .Sh RETURN VALUES Upon successful completion (that is, one of the signals specified by .Fa set is pending or is generated) .Fn sigwaitinfo and .Fn sigtimedwait return the selected signal number. Otherwise, the functions return a value of \-1 and set the global variable .Va errno to indicate the error. .Sh ERRORS The .Fn sigtimedwait system call will fail if: .Bl -tag -width Er .It Bq Er EAGAIN No signal specified by set was generated within the specified timeout period. .El .Pp The .Fn sigtimedwait and .Fn sigwaitinfo system calls fail if: .Bl -tag -width Er .It Bq Er EINTR The wait was interrupted by an unblocked, caught signal. -.Pp .El +.Pp The .Fn sigtimedwait system call may also fail if: .Bl -tag -width Er .It Bq Er EINVAL The .Fa timeout argument specified a .Va tv_nsec value less than zero or greater than or equal to 1000 million. Kernel only checks for this error if no signal is pending in set and it is necessary to wait. .El .Sh SEE ALSO .Xr sigaction 2 , .Xr sigpending 2 , .Xr sigqueue 2 , .Xr sigsuspend 2 , .Xr sigwait 2 , .Xr pause 3 , .Xr pthread_sigmask 3 , .Xr siginfo 3 .Sh STANDARDS The .Fn sigtimedwait and .Fn sigwaitinfo system calls conform to .St -p1003.1-96 . Index: projects/sendfile/lib/libc/sys/vfork.2 =================================================================== --- projects/sendfile/lib/libc/sys/vfork.2 (revision 276056) +++ projects/sendfile/lib/libc/sys/vfork.2 (revision 276057) @@ -1,129 +1,129 @@ .\" Copyright (c) 1980, 1991, 1993 .\" The Regents of the University of California. 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. .\" 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. .\" .\" @(#)vfork.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" .Dd November 13, 2009 .Dt VFORK 2 .Os .Sh NAME .Nm vfork .Nd create a new process without copying the address space .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In unistd.h .Ft pid_t .Fn vfork void .Sh DESCRIPTION The .Fn vfork system call can be used to create new processes without fully copying the address space of the old process, which is horrendously inefficient in a paged environment. It is useful when the purpose of .Xr fork 2 would have been to create a new system context for an .Xr execve 2 . The .Fn vfork system call differs from .Xr fork 2 in that the child borrows the parent's memory and thread of control until a call to .Xr execve 2 or an exit (either by a call to .Xr _exit 2 or abnormally). The parent process is suspended while the child is using its resources. .Pp The .Fn vfork system call returns 0 in the child's context and (later) the pid of the child in the parent's context. .Pp The .Fn vfork system call can normally be used just like .Xr fork 2 . It does not work, however, to return while running in the child's context from the procedure that called .Fn vfork since the eventual return from .Fn vfork would then return to a no longer existent stack frame. Be careful, also, to call .Xr _exit 2 rather than .Xr exit 3 if you cannot .Xr execve 2 , since .Xr exit 3 will flush and close standard I/O channels, and thereby mess up the parent processes standard I/O data structures. (Even with .Xr fork 2 it is wrong to call .Xr exit 3 since buffered data would then be flushed twice.) .Sh RETURN VALUES Same as for .Xr fork 2 . .Sh SEE ALSO -.Xr execve 2 , .Xr _exit 2 , +.Xr execve 2 , .Xr fork 2 , .Xr rfork 2 , .Xr sigaction 2 , .Xr wait 2 , .Xr exit 3 .Sh HISTORY The .Fn vfork system call appeared in .Bx 2.9 . .Sh BUGS To avoid a possible deadlock situation, processes that are children in the middle of a .Fn vfork are never sent .Dv SIGTTOU or .Dv SIGTTIN signals; rather, output or .Xr ioctl 2 calls are allowed and input attempts result in an end-of-file indication. Index: projects/sendfile/lib/libc =================================================================== --- projects/sendfile/lib/libc (revision 276056) +++ projects/sendfile/lib/libc (revision 276057) Property changes on: projects/sendfile/lib/libc ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/lib/libc:r275989-276056 Index: projects/sendfile/share/man/man4/altera_atse.4 =================================================================== --- projects/sendfile/share/man/man4/altera_atse.4 (revision 276056) +++ projects/sendfile/share/man/man4/altera_atse.4 (revision 276057) @@ -1,119 +1,119 @@ .\"- .\" Copyright (c) 2013-2014 SRI International .\" All rights reserved. .\" .\" This software was developed by SRI International and the University of .\" Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) .\" ("CTSRD"), as part of the DARPA CRASH research programme. .\" .\" 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$ .\" .Dd May 21, 2014 .Dt ALTERA_ATSE 4 .Os .Sh NAME .Nm atse .Nd driver for the Altera Triple-Speed Ethernet MegaCore .Sh SYNOPSIS .Cd "device atse" .Cd "options ATSE_CFI_HACK" .Pp In .Pa /boot/device.hints : .Cd hint.atse.0.at="nexus0" .Cd hint.atse.0.maddr=0x7f007000 .Cd hint.atse.0.msize=0x540 .Cd hint.atse.0.rc_irq=1 .Cd hint.atse.0.rx_maddr=0x7f007500 .Cd hint.atse.0.rx_msize=0x8 .Cd hint.atse.0.rxc_maddr=0x7f007520 .Cd hint.atse.0.rxc_msize=0x20 .Cd hint.atse.0.tx_irq=2 .Cd hint.atse.0.tx_maddr=0x7f007400 .Cd hint.atse.0.tx_msize=0x8 .Cd hint.atse.0.txc_maddr=0x7f007420 .Cd hint.atse.0.txc_msize=0x20 .Cd hint.e1000phy.0.at="miibus0" .Cd hint.e1000phy.0.phyno=0 .Sh DESCRIPTION The .Nm device driver provides support for the Altera Triple-Speed Ethernet MegaCore. .Sh HARDWARE The current version of the .Nm driver supports the Ethernet MegaCore as described in version 11.1 of Altera's documentation when the device is configured with internal FIFOs. .Sh MAC SELECTION The default MAC address for each .Nm interface is derived from a value stored in .Xr cfi 4 flash. The value is managed by the .Xr atsectl 8 utility. .Pp Only a single MAC address may be stored in flash. If the address begins with the Altera prefix 00:07:ed and ends in 00 then up to 16 addresses will be derived from it by adding the unit number of the interface to the stored address. -For other prefixes, the address will be assigned to atse0 and random +For other prefixes, the address will be assigned to atse0 and random addresses will be used for other interfaces. If the stored address is invalid, for example all zero's, multicast, or the default address shipped on all DE4 boards (00:07:ed:ff:ed:15) then a random address is generated when the device is attached. .Sh SEE ALSO .Xr miibus 4 , .Xr netintro 4 , .Xr ifconfig 8 .Rs .%T Triple-Speed Ethernet MegaCore Function User Guide .%D November 2011 .%I Altera Corporation .Re .Sh HISTORY The .Nm device driver first appeared in .Fx 10.0 . .Sh AUTHORS The .Nm device driver and this manual page were developed by SRI International and the University of Cambridge Computer Laboratory under DARPA/AFRL contract .Pq FA8750-10-C-0237 .Pq Do CTSRD Dc , as part of the DARPA CRASH research programme. This device driver was written by .An Bjoern A. Zeeb . .Sh BUGS The .Nm driver only supports a single configuration of the MegaCore as installed on the Terasic Technologies Altera DE4 Development and Education Board. .Pp Only gigabit Ethernet speeds are currently supported. Index: projects/sendfile/share/man/man4/aout.4 =================================================================== --- projects/sendfile/share/man/man4/aout.4 (revision 276056) +++ projects/sendfile/share/man/man4/aout.4 (revision 276057) @@ -1,146 +1,146 @@ .\" Copyright (c) 2012 Konstantin Belousov .\" .\" 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 ``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 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$ .\" .Dd August 14, 2012 .Dt AOUT 4 .Os .Sh NAME .Nm aout .Nd kernel support for executing binary files in legacy a.out format .Sh SYNOPSIS .Bd -literal -offset indent kldload a.out .Ed .Sh DESCRIPTION The .Xr a.out 5 executable format was used before the release of .Fx 3.0 . Since i386 was the only supported architecture at that time, .Xr a.out 5 executables can only be activated on platforms that support execution of i386 code, such as i386 and amd64. .Pp To add kernel support for old syscalls and old syscall invocation methods, place the following options in the kernel configuration file: .Bd -ragged -offset indent .Cd "options COMPAT_43" .br .Cd "options COMPAT_FREEBSD32" .Ed .Pp The .Va COMPAT_FREEBSD32 option is only required on 64-bit CPU architectures. .Pp The .Va aout.ko module needs to be loaded with the .Xr kldload 8 utility in order to support the .Xr a.out 5 image activator: .Bd -ragged -offset indent .Ic kldload aout .Ed .Pp Alternatively, to load the module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent aout_load="YES" .Ed .Pp The .Xr a.out 5 format was mainstream quite a long time ago. Reasonable default settings and security requirements of modern operating systems today contradict the default environment of that time and require adjustments of the system to mimic natural environment for old binaries. .Pp The following .Xr sysctl 8 tunables are useful for this: .Bl -tag -offset indent -width "XXXXXXXXXXXXXXXXXXXXXXXXX" .It Xo Va security.bsd.map_at_zero .Xc Set to 1 to allow mapping of process pages at address 0. Some very old .Va ZMAGIC executable images require text mapping at address 0. .It Xo Va kern.pid_max .Xc Old versions of .Fx used signed 16-bit type for .Vt pid_t . Current kernels use 32-bit type for .Vt pid_t , and allow process id's up to 99999. Such values cannot be represented by old .Vt pid_t , mostly causing issues for processes using .Xr wait 2 syscalls, for example shells. Set the sysctl to 30000 to work around the problem. .It Xo Va kern.elf32.read_exec .Xc Set to 1 to force any accessible memory mapping performed by 32-bit process to allow execution, see .Xr mmap 2 . Old i386 CPUs did not have a bit in PTE which disallowed execution from the page, so many old programs did not specify .Va PROT_EXEC even for mapping of executable code. The sysctl forces .Va PROT_EXEC if mapping has any access allowed at all. The setting is only needed if the host architecture allows non-executable mappings. .El .Sh SEE ALSO .Xr execve 2 , .Xr a.out 5 , .Xr elf 5 , -.Xr sysctl 8 . +.Xr sysctl 8 .Sh HISTORY The .Xr a.out 5 executable format was used on ancient .At and served as the main executable format for .Fx from the beginning up to .Fx 2.2.9 . In .Fx 3.0 it was superseded by .Xr elf 5 . .Sh AUTHORS The .Nm manual page was written by .An Konstantin Belousov Aq Mt kib@FreeBSD.org . .Sh BUGS On 64bit architectures, not all wrappers for older syscalls are implemented. Index: projects/sendfile/share/man/man4/ath_ahb.4 =================================================================== --- projects/sendfile/share/man/man4/ath_ahb.4 (revision 276056) +++ projects/sendfile/share/man/man4/ath_ahb.4 (revision 276057) @@ -1,60 +1,60 @@ .\"- .\" Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd .\" 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, .\" without modification. .\" 2. Redistributions in binary form must reproduce at minimum a disclaimer .\" similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any .\" redistribution must be conditioned upon including a substantially .\" similar Disclaimer requirement for further binary redistribution. .\" .\" NO WARRANTY .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT .\" LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY .\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL .\" THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. .\" .\" $FreeBSD$ .\"/ .Dd May 30, 2011 .Dt ATH_AHB 4 .Os .Sh NAME .Nm ath_ahb .Nd "Atheros AHB device glue" .Sh SYNOPSIS .Cd "device ath_ahb" .Sh DESCRIPTION This module provides the AHB bus glue needed for the devices supported by the .Xr ath 4 and .Xr ath_hal 4 drivers. .Pp This is only relevant for embedded System-on-Chip (SoC) devices such as the Atheros AR913x series, which include an Atheros wireless MAC on-die. .Sh SEE ALSO -.Xr ath 4 +.Xr ath 4 , .Xr ath_hal 4 .Sh HISTORY The .Nm module first appeared in .Fx 9.0 . .Sh BUGS See .Xr ath 4 for known bugs. Index: projects/sendfile/share/man/man4/ath_pci.4 =================================================================== --- projects/sendfile/share/man/man4/ath_pci.4 (revision 276056) +++ projects/sendfile/share/man/man4/ath_pci.4 (revision 276057) @@ -1,57 +1,57 @@ .\"- .\" Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd .\" 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, .\" without modification. .\" 2. Redistributions in binary form must reproduce at minimum a disclaimer .\" similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any .\" redistribution must be conditioned upon including a substantially .\" similar Disclaimer requirement for further binary redistribution. .\" .\" NO WARRANTY .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT .\" LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY .\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL .\" THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. .\" .\" $FreeBSD$ .\"/ .Dd May 30, 2011 .Dt ATH_PCI 4 .Os .Sh NAME .Nm ath_pci .Nd "Atheros PCI device glue" .Sh SYNOPSIS .Cd "device ath_pci" .Sh DESCRIPTION This module provides the PCI/PCIe bus glue needed for the devices supported by the .Xr ath 4 and .Xr ath_hal 4 drivers. .Sh SEE ALSO -.Xr ath 4 +.Xr ath 4 , .Xr ath_hal 4 .Sh HISTORY The .Nm module first appeared in .Fx 9.0 . .Sh BUGS See .Xr ath 4 for known bugs. Index: projects/sendfile/share/man/man4/carp.4 =================================================================== --- projects/sendfile/share/man/man4/carp.4 (revision 276056) +++ projects/sendfile/share/man/man4/carp.4 (revision 276057) @@ -1,323 +1,323 @@ .\" $OpenBSD: carp.4,v 1.16 2004/12/07 23:41:35 jmc Exp $ .\" .\" Copyright (c) 2003, Ryan McBride. All rights reserved. .\" Copyright (c) 2011, Gleb Smirnoff .\" .\" 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 PROJECT 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 PROJECT 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$ .\" .Dd February 21, 2013 .Dt CARP 4 .Os .Sh NAME .Nm carp .Nd Common Address Redundancy Protocol .Sh SYNOPSIS .Cd "device carp" .Sh DESCRIPTION The CARP allows multiple hosts on the same local network to share a set of IPv4 and/or IPv6 addresses. Its primary purpose is to ensure that these addresses are always available. .Pp To use .Nm , the administrator needs to configure at a minimum a common virtual host ID (vhid), and attach at least one IP address to this vhid on each machine which is to take part in the virtual group. Additional parameters can also be set on a per-vhid basis: .Cm advbase and .Cm advskew , which are used to control how frequently the host sends advertisements when it is the master for a virtual host, and .Cm pass which is used to authenticate .Nm advertisements. The .Cm advbase parameter stands for .Dq "advertisement base" . It is measured in seconds and specifies the base of the advertisement interval. The .Cm advskew parameter stands for .Dq "advertisement skew" . It is measured in 1/256 of seconds. It is added to the base advertisement interval to make one host advertise a bit slower that the other does. Both .Cm advbase and .Cm advskew are put inside CARP advertisements. These values can be configured using .Xr ifconfig 8 , or through the .Dv SIOCSVH .Xr ioctl 2 . .Pp CARP virtual hosts can be configured on multicast-capable interfaces: Ethernet, layer 2 VLAN, FDDI and Token Ring. An arbitrary number of virtual host IDs can be configured on an interface. An arbitrary number of IPv4 or IPv6 addresses can be attached to a particular vhid. It is important that all hosts participating in a vhid have the same list of prefixes configured on the vhid, since all prefixes are included in the cryptographic checksum supplied in each advertisement. Multiple vhids running on one interface participate in master/backup elections independently. .Pp Additionally, there are a number of global parameters which can be set using .Xr sysctl 8 : .Bl -tag -width ".Va net.inet.carp.ifdown_demotion_factor" .It Va net.inet.carp.allow Accept incoming .Nm packets. Enabled by default. .It Va net.inet.carp.preempt Allow virtual hosts to preempt each other. When enabled, a vhid in a backup state would preempt a master that is announcing itself with a lower advskew. Disabled by default. .It Va net.inet.carp.log Determines what events relating to .Nm vhids are logged. A value of 0 disables any logging. A value of 1 enables logging state changes of .Nm vhids. Values above 1 enable logging of bad .Nm packets. The default value is 1. .It Va net.inet.carp.demotion This value shows current level of CARP demotion. The value is added to the actual advskew sent in announcements for all vhids. At normal system operation the demotion factor is zero. However, problematic conditions raise its level: when .Nm experiences problem with sending announcements, when an interface running a vhid goes down, or while the .Xr pfsync 4 interface is not synchronized. The demotion factor can be adjusted writing to the sysctl oid. The signed value supplied to the .Xr sysctl 8 command is added to current demotion factor. This allows to control .Nm behaviour depending on some external conditions, for example on the status of some daemon utility. .It Va net.inet.carp.ifdown_demotion_factor This value is added to .Va net.inet.carp.demotion when an interface running a vhid goes down. The default value is 240 (the maximum advskew value). .It Va net.inet.carp.senderr_demotion_factor This value is added to .Va net.inet.carp.demotion when .Nm experiences errors sending its announcements. The default value is 240 (the maximum advskew value). .El .\".Sh ARP level load balancing .\"A .\".Nm .\"interface has limited abilities for load balancing incoming connections .\"between hosts in an Ethernet network. .\"For load-balancing operation, one needs several CARP interfaces that .\"are configured to the same IP address, but to a different vhids. .\"Once an ARP request is received, the CARP protocol will use a hashing .\"function against the source IP address in the ARP request to determine .\"which vhid the request will be assigned to. .\"If the corresponding CARP interface is the current .\"master interface, a reply will .\"be sent to the ARP request; .\"otherwise it will be ignored. .\"See the .\".Sx EXAMPLES .\"section for a practical example of load balancing. .\".Pp .\"The ARP load balancing implemented in .\".Nm .\"has some limitations. .\"First, ARP balancing only works on the local network segment. .\"It cannot balance traffic that crosses a router, because the .\"router itself will always be balanced to the same virtual host. .\"Second, ARP load balancing can lead to asymmetric routing .\"of incoming and outgoing traffic, and thus combining it with .\".Xr pfsync 4 .\"is dangerous, because this creates a race condition between .\"balanced routers and a host they are serving. .\"Imagine an incoming packet creating state on the first router, being .\"forwarded to its destination, and the destination replying faster .\"than the state information is packed and synced with the second router. .\"If the reply would be load balanced to second router, it will be .\"dropped since the second router has not yet received information about .\"the connection state. .Sh STATE CHANGE NOTIFICATIONS Sometimes it is useful to get notified about .Nm status change events. This can be accomplished by using .Xr devd 8 hooks. Master/slave events are signalled under system .Dv CARP . The subsystem specifies the vhid and name of the interface where the master/slave event occurred. The type of the message displays the new state of the vhid. Please see .Xr devd.conf 5 and the .Sx EXAMPLES section for more information. .Sh EXAMPLES For firewalls and routers with multiple interfaces, it is desirable to failover all of the addresses running .Nm together, when one of the physical interfaces goes down. This is achieved by the use of the preempt option. Enable it on both hosts A and B: .Pp .Dl sysctl net.inet.carp.preempt=1 .Pp Assume that host A is the preferred master and we are running the 192.168.1.0/24 prefix on em0 and 192.168.2.0/24 on em1. This is the setup for host A (advskew is above 0 so it could be overwritten in the emergency situation from the other host): .Bd -literal -offset indent ifconfig em0 vhid 1 advskew 100 pass mekmitasdigoat 192.168.1.1/24 ifconfig em1 vhid 2 advskew 100 pass mekmitasdigoat 192.168.2.1/24 .Ed .Pp The setup for host B is identical, but it has a higher .Cm advskew : .Bd -literal -offset indent ifconfig em0 vhid 1 advskew 200 pass mekmitasdigoat 192.168.1.1/24 ifconfig em1 vhid 2 advskew 200 pass mekmitasdigoat 192.168.2.1/24 .Ed .Pp When one of the physical interfaces of host A fails, .Cm advskew is demoted to a configured value on all its .Nm vhids. Due to the preempt option, host B would start announcing itself, and thus preempt host A on both interfaces instead of just the failed one. .\".Pp .\"In order to set up an ARP balanced virtual host, it is necessary to configure .\"one virtual host for each physical host which would respond to ARP requests .\"and thus handle the traffic. .\"In the following example, two virtual hosts are configured on two hosts to .\"provide balancing and failover for the IP address 192.168.1.10. .\".Pp .\"First the .\".Nm .\"interfaces on host A are configured. .\"The .\".Cm advskew .\"of 100 on the second virtual host means that its advertisements will be sent .\"out slightly less frequently. .\".Bd -literal -offset indent .\"ifconfig carp0 create .\"ifconfig carp0 vhid 1 advskew 100 pass mekmitasdigoat 192.168.1.10/24 .\"ifconfig carp1 create .\"ifconfig carp1 vhid 2 advskew 200 pass mekmitasdigoat 192.168.1.10/24 .\".Ed .\".Pp .\"The configuration for host B is identical, except the .\".Cm advskew .\"is on virtual host 1 rather than virtual host 2. .\".Bd -literal -offset indent .\"ifconfig carp0 create .\"ifconfig carp0 vhid 1 advskew 200 pass mekmitasdigoat 192.168.1.10/24 .\"ifconfig carp1 create .\"ifconfig carp1 vhid 2 advskew 100 pass mekmitasdigoat 192.168.1.10/24 .\".Ed .\".Pp .\"Finally, the ARP balancing feature must be enabled on both hosts: .\".Pp .\".Dl sysctl net.inet.carp.arpbalance=1 .\".Pp .\"When the hosts receive an ARP request for 192.168.1.10, the source IP address .\"of the request is used to compute which virtual host should answer the request. .\"The host which is master of the selected virtual host will reply to the .\"request, the other(s) will ignore it. .\".Pp .\"This way, locally connected systems will receive different ARP replies and .\"subsequent IP traffic will be balanced among the hosts. .\"If one of the hosts fails, the other will take over the virtual MAC address, .\"and begin answering ARP requests on its behalf. .Pp Processing of .Nm status change events can be set up by using the following devd.conf rule: .Bd -literal -offset indent notify 0 { match "system" "CARP"; match "subsystem" "[0-9]+@[0-9a-z]+"; match "type" "(MASTER|BACKUP)"; action "/root/carpcontrol.sh $subsystem $type"; }; .Ed .Pp To see .Nm packets decoded in .Xr tcpdump 8 output, one needs to specify .Fl T Ar carp option, otherwise .Xr tcpdump 8 tries to interpret them as VRRP packets: .Bd -literal -offset indent tcpdump -npi vlan0 -T carp .Ed .Sh SEE ALSO .Xr inet 4 , .Xr pfsync 4 , .Xr rc.conf 5 , .Xr devd.conf 5 , .Xr ifconfig 8 , -.Xr sysctl 8 +.Xr sysctl 8 , .Xr tcpdump 8 .Sh HISTORY The .Nm device first appeared in .Ox 3.5 . The .Nm device was imported into .Fx 5.4 . In .Fx 10.0 , .Nm was significantly rewritten, and is no longer a pseudo-interface. Index: projects/sendfile/share/man/man4/crypto.4 =================================================================== --- projects/sendfile/share/man/man4/crypto.4 (revision 276056) +++ projects/sendfile/share/man/man4/crypto.4 (revision 276057) @@ -1,434 +1,433 @@ .\" $NetBSD: crypto.4,v 1.24 2014/01/27 21:23:59 pgoyette Exp $ .\" .\" Copyright (c) 2008 The NetBSD Foundation, Inc. .\" Copyright (c) 2014 The FreeBSD Foundation .\" All rights reserved. .\" .\" Portions of this documentation were written by John-Mark Gurney .\" under sponsorship of the FreeBSD Foundation and .\" Rubicon Communications, LLC (Netgate). .\" .\" This code is derived from software contributed to The NetBSD Foundation .\" by Coyote Point 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. .\" .\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. .\" .\" .\" .\" Copyright (c) 2004 .\" Jonathan Stone . 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 Jonathan Stone 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 Jonathan Stone OR THE VOICES IN HIS HEAD .\" 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$ .\" .Dd December 12, 2014 .Dt CRYPTO 4 .Os .Sh NAME .Nm crypto , .Nm cryptodev .Nd user-mode access to hardware-accelerated cryptography .Sh SYNOPSIS .Cd device crypto .Cd device cryptodev .Pp .In sys/ioctl.h .In sys/time.h .In crypto/cryptodev.h .Sh DESCRIPTION The .Nm driver gives user-mode applications access to hardware-accelerated cryptographic transforms, as implemented by the .Xr opencrypto 9 in-kernel interface. .Pp The .Pa /dev/crypto special device provides an .Xr ioctl 2 based interface. User-mode applications should open the special device, then issue .Xr ioctl 2 calls on the descriptor. User-mode access to .Pa /dev/crypto is controlled by three .Xr sysctl 8 variables, .Ic kern.userasymcrypto and .Ic kern.cryptodevallowsoft . See .Xr sysctl 7 for additional details. .Pp The .Nm device provides two distinct modes of operation: one mode for symmetric-keyed cryptographic requests, and a second mode for both asymmetric-key (public-key/private-key) requests, and for modular arithmetic (for Diffie-Hellman key exchange and other cryptographic protocols). The two modes are described separately below. .Sh THEORY OF OPERATION Regardless of whether symmetric-key or asymmetric-key operations are to be performed, use of the device requires a basic series of steps: -.Pp .Bl -enum .It Open a file descriptor for the device. See .Xr open 2 . .It If any symmetric operation will be performed, create one session, with .Dv CIOCGSESSION . Most applications will require at least one symmetric session. Since cipher and MAC keys are tied to sessions, many applications will require more. Asymmetric operations do not use sessions. .It Submit requests, synchronously with .Dv CIOCCRYPT (symmetric) or .Dv CIOCKEY (asymmetric). .It Destroy one session with .Dv CIOCFSESSION . .It Close the device with .Xr close 2 . .El .Sh SYMMETRIC-KEY OPERATION The symmetric-key operation mode provides a context-based API to traditional symmetric-key encryption (or privacy) algorithms, or to keyed and unkeyed one-way hash (HMAC and MAC) algorithms. The symmetric-key mode also permits fused operation, where the hardware performs both a privacy algorithm and an integrity-check algorithm in a single pass over the data: either a fused encrypt/HMAC-generate operation, or a fused HMAC-verify/decrypt operation. .Pp To use symmetric mode, you must first create a session specifying the algorithm(s) and key(s) to use; then issue encrypt or decrypt requests against the session. .Ss Algorithms For a list of supported algorithms, see .Xr crypto 7 and .Xr crypto 9 . .Ss IOCTL Request Descriptions .\" .Bl -tag -width CIOCGSESSION .\" .It Dv CRIOGET Fa int *fd Clone the fd argument to .Xr ioctl 2 , yielding a new file descriptor for the creation of sessions. .\" .It Dv CIOCFINDDEV Fa struct crypt_find_op *fop .Bd -literal struct crypt_find_op { int crid; /* driver id + flags */ char name[32]; /* device/driver name */ }; .Ed If .Fa crid is -1, then find the driver named .Fa name and return the id in .Fa crid . If .Fa crid is not -1, return the name of the driver with .Fa crid in .Fa name . In either case, if the driver is not found, .Dv ENOENT is returned. .It Dv CIOCGSESSION Fa struct session_op *sessp .Bd -literal struct session_op { u_int32_t cipher; /* e.g. CRYPTO_DES_CBC */ u_int32_t mac; /* e.g. CRYPTO_MD5_HMAC */ u_int32_t keylen; /* cipher key */ void * key; int mackeylen; /* mac key */ void * mackey; u_int32_t ses; /* returns: ses # */ }; .Ed Create a new cryptographic session on a file descriptor for the device; that is, a persistent object specific to the chosen privacy algorithm, integrity algorithm, and keys specified in .Fa sessp . The special value 0 for either privacy or integrity is reserved to indicate that the indicated operation (privacy or integrity) is not desired for this session. .Pp Multiple sessions may be bound to a single file descriptor. The session ID returned in .Fa sessp-\*[Gt]ses is supplied as a required field in the symmetric-operation structure .Fa crypt_op for future encryption or hashing requests. .\" .Pp .\" This implementation will never return a session ID of 0 for a successful .\" creation of a session, which is a .\" .Nx .\" extension. .Pp For non-zero symmetric-key privacy algorithms, the privacy algorithm must be specified in .Fa sessp-\*[Gt]cipher , the key length in .Fa sessp-\*[Gt]keylen , and the key value in the octets addressed by .Fa sessp-\*[Gt]key . .Pp For keyed one-way hash algorithms, the one-way hash must be specified in .Fa sessp-\*[Gt]mac , the key length in .Fa sessp-\*[Gt]mackey , and the key value in the octets addressed by .Fa sessp-\*[Gt]mackeylen . .\" .Pp Support for a specific combination of fused privacy and integrity-check algorithms depends on whether the underlying hardware supports that combination. Not all combinations are supported by all hardware, even if the hardware supports each operation as a stand-alone non-fused operation. .It Dv CIOCCRYPT Fa struct crypt_op *cr_op .Bd -literal struct crypt_op { u_int32_t ses; u_int16_t op; /* e.g. COP_ENCRYPT */ u_int16_t flags; u_int len; caddr_t src, dst; caddr_t mac; /* must be large enough for result */ caddr_t iv; }; .Ed Request a symmetric-key (or hash) operation. The file descriptor argument to .Xr ioctl 2 must have been bound to a valid session. To encrypt, set .Fa cr_op-\*[Gt]op to .Dv COP_ENCRYPT . To decrypt, set .Fa cr_op-\*[Gt]op to .Dv COP_DECRYPT . The field .Fa cr_op-\*[Gt]len supplies the length of the input buffer; the fields .Fa cr_op-\*[Gt]src , .Fa cr_op-\*[Gt]dst , .Fa cr_op-\*[Gt]mac , .Fa cr_op-\*[Gt]iv supply the addresses of the input buffer, output buffer, one-way hash, and initialization vector, respectively. .It Dv CIOCCRYPTAEAD Fa struct crypt_aead *cr_aead .Bd -literal struct crypt_aead { u_int32_t ses; u_int16_t op; /* e.g. COP_ENCRYPT */ u_int16_t flags; u_int len; u_int aadlen; u_int ivlen; caddr_t src, dst; caddr_t aad; caddr_t tag; /* must be large enough for result */ caddr_t iv; }; .Ed The .Dv CIOCCRYPTAEAD is similar to the .Dv CIOCCRYPT but provides additional data in .Fa cr_aead-\*[Gt]aad to include in the authentication mode. .It Dv CIOCFSESSION Fa u_int32_t ses_id Destroys the /dev/crypto session associated with the file-descriptor argument. .It Dv CIOCNFSESSION Fa struct crypt_sfop *sfop ; .Bd -literal struct crypt_sfop { size_t count; u_int32_t *sesid; }; .Ed Destroys the .Fa sfop-\*[Gt]count sessions specified by the .Fa sfop array of session identifiers. .El .\" .Sh ASYMMETRIC-KEY OPERATION .Ss Asymmetric-key algorithms Contingent upon hardware support, the following asymmetric (public-key/private-key; or key-exchange subroutine) operations may also be available: .Pp .Bl -column "CRK_DH_COMPUTE_KEY" "Input parameter" "Output parameter" -offset indent -compact .It Em "Algorithm" Ta "Input parameter" Ta "Output parameter" .It Em " " Ta "Count" Ta "Count" .It Dv CRK_MOD_EXP Ta 3 Ta 1 .It Dv CRK_MOD_EXP_CRT Ta 6 Ta 1 .It Dv CRK_DSA_SIGN Ta 5 Ta 2 .It Dv CRK_DSA_VERIFY Ta 7 Ta 0 .It Dv CRK_DH_COMPUTE_KEY Ta 3 Ta 1 .El .Pp See below for discussion of the input and output parameter counts. .Ss Asymmetric-key commands .Bl -tag -width CIOCKEY .It Dv CIOCASYMFEAT Fa int *feature_mask Returns a bitmask of supported asymmetric-key operations. Each of the above-listed asymmetric operations is present if and only if the bit position numbered by the code for that operation is set. For example, .Dv CRK_MOD_EXP is available if and only if the bit .Pq 1 \*[Lt]\*[Lt] Dv CRK_MOD_EXP is set. .It Dv CIOCKEY Fa struct crypt_kop *kop .Bd -literal struct crypt_kop { u_int crk_op; /* e.g. CRK_MOD_EXP */ u_int crk_status; /* return status */ u_short crk_iparams; /* # of input params */ u_short crk_oparams; /* # of output params */ u_int crk_pad1; struct crparam crk_param[CRK_MAXPARAM]; }; /* Bignum parameter, in packed bytes. */ struct crparam { void * crp_p; u_int crp_nbits; }; .Ed Performs an asymmetric-key operation from the list above. The specific operation is supplied in .Fa kop-\*[Gt]crk_op ; final status for the operation is returned in .Fa kop-\*[Gt]crk_status . The number of input arguments and the number of output arguments is specified in .Fa kop-\*[Gt]crk_iparams and .Fa kop-\*[Gt]crk_iparams , respectively. The field .Fa crk_param[] must be filled in with exactly .Fa kop-\*[Gt]crk_iparams + kop-\*[Gt]crk_oparams arguments, each encoded as a .Fa struct crparam (address, bitlength) pair. .Pp The semantics of these arguments are currently undocumented. .El .Sh SEE ALSO .Xr aesni 4 , .Xr hifn 4 , .Xr ipsec 4 , .Xr padlock 4 , .Xr safe 4 , .Xr ubsec 4 , .Xr crypto 7 , .Xr geli 8 , .Xr crypto 9 .Sh HISTORY The .Nm driver first appeared in .Ox 3.0 . The .Nm driver was imported to .Fx 5.0 . .Sh BUGS Error checking and reporting is weak. .Pp The values specified for symmetric-key key sizes to .Dv CIOCGSESSION must exactly match the values expected by .Xr opencrypto 9 . The output buffer and MAC buffers supplied to .Dv CIOCCRYPT must follow whether privacy or integrity algorithms were specified for session: if you request a .No non- Ns Dv NULL algorithm, you must supply a suitably-sized buffer. .Pp The scheme for passing arguments for asymmetric requests is baroque. .Pp The naming inconsistency between .Dv CRIOGET and the various .Dv CIOC Ns \&* names is an unfortunate historical artifact. Index: projects/sendfile/share/man/man4/gpioled.4 =================================================================== --- projects/sendfile/share/man/man4/gpioled.4 (revision 276056) +++ projects/sendfile/share/man/man4/gpioled.4 (revision 276057) @@ -1,156 +1,156 @@ .\" Copyright (c) 2013, Luiz Otavio O Souza .\" 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$ .\" .Dd May 14, 2014 .Dt GPIOLED 4 .Os .Sh NAME .Nm gpioled .Nd GPIO LED generic device driver .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device gpio" .Cd "device gpioled" .Ed .Sh DESCRIPTION The .Nm driver provides glue to attach a .Xr led 4 compatible device to a GPIO pin. Each LED in the system has a .Pa name which is used to export a device as .Pa /dev/led/ . The GPIO pin can then be controlled by writing to this device as described in .Xr led 4 . .Pp -On a -.Xr device.hints 5 +On a +.Xr device.hints 5 based system, like .Li MIPS , these values are configurable for .Nm : .Bl -tag -width ".Va hint.gpioiic.%d.atXXX" .It Va hint.gpioled.%d.at The gpiobus you are attaching to. Normally assigned to gpiobus0. .It Va hint.gpioled.%d.name Arbitrary name of device in .Pa /dev/led/ to create for .Xr led 4 . .It Va hint.gpioled.%d.pins Which pin on the GPIO interface to map to this instance. Please note that this mask should only ever have one bit set (any other bits - i.e., pins - will be ignored). .El .Pp On a .Xr FDT 4 based system, like .Li ARM , the DTS part for a .Nm gpioled device usually looks like: .Bd -literal gpio: gpio { gpio-controller; ... led0 { compatible = "gpioled"; gpios = <&gpio 16 2 0>; /* GPIO pin 16. */ name = "ok"; }; led1 { compatible = "gpioled"; gpios = <&gpio 17 2 0>; /* GPIO pin 17. */ name = "user-led1"; }; }; .Ed .Pp Optionally, you can choose to combine all the LEDs under a single .Dq gpio-leds compatible node: .Bd -literal simplebus0 { ... leds { compatible = "gpio-leds"; led0 { gpios = <&gpio 16 2 0>; name = "ok" }; led1 { gpios = <&gpio 17 2 0>; name = "user-led1" }; }; }; .Ed .Pp Both methods are equally supported and it is possible to have the LEDs defined with any sort of mix between the methods. The only restriction is that a GPIO pin cannot be mapped by two different (gpio)leds. .Pp For more details about the .Va gpios property, please consult .Pa /usr/src/sys/boot/fdt/dts/bindings-gpio.txt . .Pp The property .Va name is the arbitrary name of the device in .Pa /dev/led/ to create for .Xr led 4 . .Sh SEE ALSO .Xr fdt 4 , .Xr gpio 4 , .Xr gpioiic 4 , .Xr led 4 .Sh HISTORY The .Nm manual page first appeared in .Fx 10.1 . .Sh AUTHORS This manual page was written by .An Luiz Otavio O Souza . Index: projects/sendfile/share/man/man4/iicbus.4 =================================================================== --- projects/sendfile/share/man/man4/iicbus.4 (revision 276056) +++ projects/sendfile/share/man/man4/iicbus.4 (revision 276057) @@ -1,167 +1,167 @@ .\" Copyright (c) 1998, Nicolas Souchu .\" 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$ .\" .Dd November 17, 2014 .Dt IICBUS 4 .Os .Sh NAME .Nm iicbus .Nd I2C bus system .Sh SYNOPSIS .Cd "device iicbus" .Cd "device iicbb" .Pp .Cd "device iic" .Cd "device ic" .Cd "device iicsmb" .Sh DESCRIPTION The .Em iicbus system provides a uniform, modular and architecture-independent system for the implementation of drivers to control various I2C devices and to utilize different I2C controllers. .Sh I2C I2C is an acronym for Inter Integrated Circuit bus. The I2C bus was developed in the early 1980's by Philips semiconductors. Its purpose was to provide an easy way to connect a CPU to peripheral chips in a TV-set. .Pp The BUS physically consists of 2 active wires and a ground connection. The active wires, SDA and SCL, are both bidirectional. Where SDA is the Serial DAta line and SCL is the Serial CLock line. .Pp Every component hooked up to the bus has its own unique address whether it is a CPU, LCD driver, memory, or complex function chip. Each of these chips can act as a receiver and/or transmitter depending on its functionality. Obviously an LCD driver is only a receiver, while a memory or I/O chip can both be transmitter and receiver. Furthermore there may be one or more BUS MASTERs. .Pp The BUS MASTER is the chip issuing the commands on the BUS. In the I2C protocol specification it is stated that the IC that initiates a data transfer on the bus is considered the BUS MASTER. At that time all the others are regarded to as the BUS SLAVEs. As mentioned before, the IC bus is a Multi-MASTER BUS. This means that more than one IC capable of initiating data transfer can be connected to it. .Sh DEVICES Some I2C device drivers are available: .Pp .Bl -column "Device drivers" -compact .It Em Devices Ta Em Description .It Sy iic Ta "general i/o operation" .It Sy ic Ta "network IP interface" .It Sy iicsmb Ta "I2C to SMB software bridge" .El .Sh INTERFACES The I2C protocol may be implemented by hardware or software. Software interfaces rely on very simple hardware, usually two lines twiddled by 2 registers. Hardware interfaces are more intelligent and receive 8-bit characters they write to the bus according to the I2C protocol. .Pp I2C interfaces may act on the bus as slave devices, allowing spontaneous bidirectional communications, thanks to the multi-master capabilities of the I2C protocol. .Pp Some I2C interfaces are available: .Pp .Bl -column "Interface drivers" -compact .It Em Interface Ta Em Description .It Sy pcf Ta "Philips PCF8584 master/slave interface" .It Sy iicbb Ta "generic bit-banging master-only driver" .It Sy lpbb Ta "parallel port specific bit-banging interface" .It Sy bktr Ta "Brooktree848 video chipset, hardware and software master-only interface" .El .Sh BUS FREQUENCY CONFIGURATION The operating frequency of an I2C bus may be fixed or configurable. The bus may be used as part of some larger standard interface, and that -interface specification may require a fixed frequency. -The driver for that hardware would not honor an attempt to configure a +interface specification may require a fixed frequency. +The driver for that hardware would not honor an attempt to configure a different speed. A general purpose I2C bus, such as those found in many embedded systems, -will often support multiple bus frequencies. +will often support multiple bus frequencies. .Pp When a system supports multiple I2C busses, a different frequency can be configured for each bus by number, represented by the .Va %d in the variable names below. Busses can be configured using any combination of device hints, Flattened Device Tree (FDT) data, tunables set via .Xr loader 8 , or at runtime using .Xr sysctl 8 . When configuration is supplied using more than one method, FDT and hint data will be overridden by a tunable, which can be overriden by .Xr sysctl 8 . .Ss Device Hints Set .Va hint.iicbus.%d.frequency to the frequency in Hz, on systems that use device hints to configure I2C devices. The hint is also honored by systems that use FDT data if no frequency is configured using FDT. .Ss Flattened Device Tree Data Configure the I2C bus speed using the FDT standard .Va clock-frequency property of the node describing the I2C controller hardware. .Ss Sysctl and Tunable Set .Va dev.iicbus.%d.frequency in .Xr loader.conf 5 . The same variable can be changed at any time with .Xr sysctl 8 . Reset the bus using .Xr i2c 8 or the -.Xr iic 4 +.Xr iic 4 .Va I2CRSTCARD ioctl to make the change take effect. .Sh SEE ALSO .Xr bktr 4 , .Xr fdt 4 , .Xr iic 4 , .Xr iicbb 4 , .Xr lpbb 4 , .Xr pcf 4 , .Xr i2c 8 .Sh HISTORY The .Nm manual page first appeared in .Fx 3.0 . .Sh AUTHORS This manual page was written by .An Nicolas Souchu . Index: projects/sendfile/share/man/man4/ip.4 =================================================================== --- projects/sendfile/share/man/man4/ip.4 (revision 276056) +++ projects/sendfile/share/man/man4/ip.4 (revision 276057) @@ -1,903 +1,903 @@ .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. 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. 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. .\" .\" @(#)ip.4 8.2 (Berkeley) 11/30/93 .\" $FreeBSD$ .\" .Dd September 1, 2014 .Dt IP 4 .Os .Sh NAME .Nm ip .Nd Internet Protocol .Sh SYNOPSIS .In sys/types.h .In sys/socket.h .In netinet/in.h .Ft int .Fn socket AF_INET SOCK_RAW proto .Sh DESCRIPTION .Tn IP is the transport layer protocol used by the Internet protocol family. Options may be set at the .Tn IP level when using higher-level protocols that are based on .Tn IP (such as .Tn TCP and .Tn UDP ) . It may also be accessed through a .Dq raw socket when developing new protocols, or special-purpose applications. .Pp There are several .Tn IP-level .Xr setsockopt 2 and .Xr getsockopt 2 options. .Dv IP_OPTIONS may be used to provide .Tn IP options to be transmitted in the .Tn IP header of each outgoing packet or to examine the header options on incoming packets. .Tn IP options may be used with any socket type in the Internet family. The format of .Tn IP options to be sent is that specified by the .Tn IP protocol specification (RFC-791), with one exception: the list of addresses for Source Route options must include the first-hop gateway at the beginning of the list of gateways. The first-hop gateway address will be extracted from the option list and the size adjusted accordingly before use. To disable previously specified options, use a zero-length buffer: .Bd -literal setsockopt(s, IPPROTO_IP, IP_OPTIONS, NULL, 0); .Ed .Pp .Dv IP_TOS and .Dv IP_TTL may be used to set the type-of-service and time-to-live fields in the .Tn IP header for .Dv SOCK_STREAM , SOCK_DGRAM , and certain types of .Dv SOCK_RAW sockets. For example, .Bd -literal int tos = IPTOS_LOWDELAY; /* see */ setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); int ttl = 60; /* max = 255 */ setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); .Ed .Pp .Dv IP_MINTTL may be used to set the minimum acceptable TTL a packet must have when received on a socket. All packets with a lower TTL are silently dropped. This option is only really useful when set to 255, preventing packets from outside the directly connected networks reaching local listeners on sockets. .Pp .Dv IP_DONTFRAG may be used to set the Don't Fragment flag on IP packets. Currently this option is respected only on .Xr udp 4 and raw .Xr ip 4 sockets, unless the .Dv IP_HDRINCL option has been set. On .Xr tcp 4 sockets, the Don't Fragment flag is controlled by the Path MTU Discovery option. Sending a packet larger than the MTU size of the egress interface, determined by the destination address, returns an .Er EMSGSIZE error. .Pp If the .Dv IP_RECVDSTADDR option is enabled on a .Dv SOCK_DGRAM socket, the .Xr recvmsg 2 call will return the destination .Tn IP address for a .Tn UDP datagram. The .Vt msg_control field in the .Vt msghdr structure points to a buffer that contains a .Vt cmsghdr structure followed by the .Tn IP address. The .Vt cmsghdr fields have the following values: .Bd -literal cmsg_len = CMSG_LEN(sizeof(struct in_addr)) cmsg_level = IPPROTO_IP cmsg_type = IP_RECVDSTADDR .Ed .Pp The source address to be used for outgoing .Tn UDP datagrams on a socket can be specified as ancillary data with a type code of .Dv IP_SENDSRCADDR . The msg_control field in the msghdr structure should point to a buffer that contains a .Vt cmsghdr structure followed by the .Tn IP address. The cmsghdr fields should have the following values: .Bd -literal cmsg_len = CMSG_LEN(sizeof(struct in_addr)) cmsg_level = IPPROTO_IP cmsg_type = IP_SENDSRCADDR .Ed .Pp The socket should be either bound to .Dv INADDR_ANY and a local port, and the address supplied with .Dv IP_SENDSRCADDR should't be .Dv INADDR_ANY , or the socket should be bound to a local address and the address supplied with .Dv IP_SENDSRCADDR should be .Dv INADDR_ANY . In the latter case bound address is overriden via generic source address selection logic, which would choose IP address of interface closest to destination. .Pp For convenience, .Dv IP_SENDSRCADDR is defined to have the same value as .Dv IP_RECVDSTADDR , so the .Dv IP_RECVDSTADDR control message from .Xr recvmsg 2 can be used directly as a control message for .Xr sendmsg 2 . .\" .Pp If the .Dv IP_ONESBCAST option is enabled on a .Dv SOCK_DGRAM or a .Dv SOCK_RAW socket, the destination address of outgoing broadcast datagrams on that socket will be forced to the undirected broadcast address, .Dv INADDR_BROADCAST , before transmission. This is in contrast to the default behavior of the system, which is to transmit undirected broadcasts via the first network interface with the .Dv IFF_BROADCAST flag set. .Pp This option allows applications to choose which interface is used to transmit an undirected broadcast datagram. For example, the following code would force an undirected broadcast to be transmitted via the interface configured with the broadcast address 192.168.2.255: .Bd -literal char msg[512]; struct sockaddr_in sin; int onesbcast = 1; /* 0 = disable (default), 1 = enable */ setsockopt(s, IPPROTO_IP, IP_ONESBCAST, &onesbcast, sizeof(onesbcast)); sin.sin_addr.s_addr = inet_addr("192.168.2.255"); sin.sin_port = htons(1234); sendto(s, msg, sizeof(msg), 0, &sin, sizeof(sin)); .Ed .Pp It is the application's responsibility to set the .Dv IP_TTL option to an appropriate value in order to prevent broadcast storms. The application must have sufficient credentials to set the .Dv SO_BROADCAST socket level option, otherwise the .Dv IP_ONESBCAST option has no effect. .Pp If the .Dv IP_BINDANY option is enabled on a .Dv SOCK_STREAM , .Dv SOCK_DGRAM or a .Dv SOCK_RAW socket, one can .Xr bind 2 to any address, even one not bound to any available network interface in the system. This functionality (in conjunction with special firewall rules) can be used for implementing a transparent proxy. The .Dv PRIV_NETINET_BINDANY privilege is needed to set this option. .Pp If the .Dv IP_RECVTTL option is enabled on a .Dv SOCK_DGRAM socket, the .Xr recvmsg 2 call will return the .Tn IP .Tn TTL (time to live) field for a .Tn UDP datagram. The msg_control field in the msghdr structure points to a buffer that contains a cmsghdr structure followed by the .Tn TTL . The cmsghdr fields have the following values: .Bd -literal cmsg_len = CMSG_LEN(sizeof(u_char)) cmsg_level = IPPROTO_IP cmsg_type = IP_RECVTTL .Ed .\" .Pp If the .Dv IP_RECVTOS option is enabled on a .Dv SOCK_DGRAM socket, the .Xr recvmsg 2 call will return the .Tn IP .Tn TOS (type of service) field for a .Tn UDP datagram. The msg_control field in the msghdr structure points to a buffer that contains a cmsghdr structure followed by the .Tn TOS . The cmsghdr fields have the following values: .Bd -literal cmsg_len = CMSG_LEN(sizeof(u_char)) cmsg_level = IPPROTO_IP cmsg_type = IP_RECVTOS .Ed .\" .Pp If the .Dv IP_RECVIF option is enabled on a .Dv SOCK_DGRAM socket, the .Xr recvmsg 2 call returns a .Vt "struct sockaddr_dl" corresponding to the interface on which the packet was received. The .Va msg_control field in the .Vt msghdr structure points to a buffer that contains a .Vt cmsghdr structure followed by the .Vt "struct sockaddr_dl" . The .Vt cmsghdr fields have the following values: .Bd -literal cmsg_len = CMSG_LEN(sizeof(struct sockaddr_dl)) cmsg_level = IPPROTO_IP cmsg_type = IP_RECVIF .Ed .Pp .Dv IP_PORTRANGE may be used to set the port range used for selecting a local port number on a socket with an unspecified (zero) port number. It has the following possible values: .Bl -tag -width IP_PORTRANGE_DEFAULT .It Dv IP_PORTRANGE_DEFAULT use the default range of values, normally .Dv IPPORT_HIFIRSTAUTO through .Dv IPPORT_HILASTAUTO . This is adjustable through the sysctl setting: .Va net.inet.ip.portrange.first and .Va net.inet.ip.portrange.last . .It Dv IP_PORTRANGE_HIGH use a high range of values, normally .Dv IPPORT_HIFIRSTAUTO and .Dv IPPORT_HILASTAUTO . This is adjustable through the sysctl setting: .Va net.inet.ip.portrange.hifirst and .Va net.inet.ip.portrange.hilast . .It Dv IP_PORTRANGE_LOW use a low range of ports, which are normally restricted to privileged processes on .Ux systems. The range is normally from .Dv IPPORT_RESERVED \- 1 down to .Li IPPORT_RESERVEDSTART in descending order. This is adjustable through the sysctl setting: .Va net.inet.ip.portrange.lowfirst and .Va net.inet.ip.portrange.lowlast . .El .Pp The range of privileged ports which only may be opened by root-owned processes may be modified by the .Va net.inet.ip.portrange.reservedlow and .Va net.inet.ip.portrange.reservedhigh sysctl settings. The values default to the traditional range, 0 through .Dv IPPORT_RESERVED \- 1 (0 through 1023), respectively. Note that these settings do not affect and are not accounted for in the use or calculation of the other .Va net.inet.ip.portrange values above. Changing these values departs from .Ux tradition and has security consequences that the administrator should carefully evaluate before modifying these settings. .Pp Ports are allocated at random within the specified port range in order to increase the difficulty of random spoofing attacks. In scenarios such as benchmarking, this behavior may be undesirable. In these cases, .Va net.inet.ip.portrange.randomized can be used to toggle randomization off. If more than .Va net.inet.ip.portrange.randomcps ports have been allocated in the last second, then return to sequential port allocation. Return to random allocation only once the current port allocation rate drops below .Va net.inet.ip.portrange.randomcps for at least .Va net.inet.ip.portrange.randomtime seconds. The default values for .Va net.inet.ip.portrange.randomcps and .Va net.inet.ip.portrange.randomtime are 10 port allocations per second and 45 seconds correspondingly. .Ss "Multicast Options" .Tn IP multicasting is supported only on .Dv AF_INET sockets of type .Dv SOCK_DGRAM and .Dv SOCK_RAW , and only on networks where the interface driver supports multicasting. .Pp The .Dv IP_MULTICAST_TTL option changes the time-to-live (TTL) for outgoing multicast datagrams in order to control the scope of the multicasts: .Bd -literal u_char ttl; /* range: 0 to 255, default = 1 */ setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); .Ed .Pp Datagrams with a TTL of 1 are not forwarded beyond the local network. Multicast datagrams with a TTL of 0 will not be transmitted on any network, but may be delivered locally if the sending host belongs to the destination group and if multicast loopback has not been disabled on the sending socket (see below). Multicast datagrams with TTL greater than 1 may be forwarded to other networks if a multicast router is attached to the local network. .Pp For hosts with multiple interfaces, where an interface has not been specified for a multicast group membership, each multicast transmission is sent from the primary network interface. The .Dv IP_MULTICAST_IF option overrides the default for subsequent transmissions from a given socket: .Bd -literal struct in_addr addr; setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr)); .Ed .Pp where "addr" is the local .Tn IP address of the desired interface or .Dv INADDR_ANY to specify the default interface. .Pp To specify an interface by index, an instance of .Vt ip_mreqn may be passed instead. The .Vt imr_ifindex member should be set to the index of the desired interface, or 0 to specify the default interface. The kernel differentiates between these two structures by their size. .Pp The use of .Vt IP_MULTICAST_IF is .Em not recommended , as multicast memberships are scoped to each individual interface. It is supported for legacy use only by applications, such as routing daemons, which expect to be able to transmit link-local IPv4 multicast datagrams (224.0.0.0/24) on multiple interfaces, without requesting an individual membership for each interface. .Pp .\" An interface's local IP address and multicast capability can be obtained via the .Dv SIOCGIFCONF and .Dv SIOCGIFFLAGS ioctls. Normal applications should not need to use this option. .Pp If a multicast datagram is sent to a group to which the sending host itself belongs (on the outgoing interface), a copy of the datagram is, by default, looped back by the IP layer for local delivery. The .Dv IP_MULTICAST_LOOP option gives the sender explicit control over whether or not subsequent datagrams are looped back: .Bd -literal u_char loop; /* 0 = disable, 1 = enable (default) */ setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)); .Ed .Pp This option improves performance for applications that may have no more than one instance on a single host (such as a routing daemon), by eliminating the overhead of receiving their own transmissions. It should generally not be used by applications for which there may be more than one instance on a single host (such as a conferencing program) or for which the sender does not belong to the destination group (such as a time querying program). .Pp The sysctl setting .Va net.inet.ip.mcast.loop controls the default setting of the .Dv IP_MULTICAST_LOOP socket option for new sockets. .Pp A multicast datagram sent with an initial TTL greater than 1 may be delivered to the sending host on a different interface from that on which it was sent, if the host belongs to the destination group on that other interface. The loopback control option has no effect on such delivery. .Pp A host must become a member of a multicast group before it can receive datagrams sent to the group. To join a multicast group, use the .Dv IP_ADD_MEMBERSHIP option: .Bd -literal struct ip_mreq mreq; setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); .Ed .Pp where .Fa mreq is the following structure: .Bd -literal struct ip_mreq { struct in_addr imr_multiaddr; /* IP multicast address of group */ struct in_addr imr_interface; /* local IP address of interface */ } .Ed .Pp .Va imr_interface should be set to the .Tn IP address of a particular multicast-capable interface if the host is multihomed. It may be set to .Dv INADDR_ANY to choose the default interface, although this is not recommended; this is considered to be the first interface corresponding to the default route. Otherwise, the first multicast-capable interface configured in the system will be used. .Pp Prior to .Fx 7.0 , if the .Va imr_interface member is within the network range .Li 0.0.0.0/8 , it is treated as an interface index in the system interface MIB, as per the RIP Version 2 MIB Extension (RFC-1724). In versions of .Fx since 7.0, this behavior is no longer supported. Developers should instead use the RFC 3678 multicast source filter APIs; in particular, .Dv MCAST_JOIN_GROUP . .Pp Up to .Dv IP_MAX_MEMBERSHIPS memberships may be added on a single socket. Membership is associated with a single interface; programs running on multihomed hosts may need to join the same group on more than one interface. .Pp To drop a membership, use: .Bd -literal struct ip_mreq mreq; setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); .Ed .Pp where .Fa mreq contains the same values as used to add the membership. Memberships are dropped when the socket is closed or the process exits. .\" TODO: Update this piece when IPv4 source-address selection is implemented. .Pp The IGMP protocol uses the primary IP address of the interface as its identifier for group membership. This is the first IP address configured on the interface. If this address is removed or changed, the results are undefined, as the IGMP membership state will then be inconsistent. If multiple IP aliases are configured on the same interface, they will be ignored. .Pp This shortcoming was addressed in IPv6; MLDv2 requires that the unique link-local address for an interface is used to identify an MLDv2 listener. .Ss "Source-Specific Multicast Options" Since .Fx 8.0 , the use of Source-Specific Multicast (SSM) is supported. These extensions require an IGMPv3 multicast router in order to make best use of them. If a legacy multicast router is present on the link, .Fx will simply downgrade to the version of IGMP spoken by the router, and the benefits of source filtering on the upstream link will not be present, although the kernel will continue to squelch transmissions from blocked sources. .Pp Each group membership on a socket now has a filter mode: .Bl -tag -width MCAST_EXCLUDE .It Dv MCAST_EXCLUDE Datagrams sent to this group are accepted, unless the source is in a list of blocked source addresses. .It Dv MCAST_INCLUDE Datagrams sent to this group are accepted only if the source is in a list of accepted source addresses. .El .Pp Groups joined using the legacy .Dv IP_ADD_MEMBERSHIP option are placed in exclusive-mode, and are able to request that certain sources are blocked or allowed. This is known as the .Em delta-based API . .Pp To block a multicast source on an existing group membership: .Bd -literal struct ip_mreq_source mreqs; setsockopt(s, IPPROTO_IP, IP_BLOCK_SOURCE, &mreqs, sizeof(mreqs)); .Ed .Pp where .Fa mreqs is the following structure: .Bd -literal struct ip_mreq_source { struct in_addr imr_multiaddr; /* IP multicast address of group */ struct in_addr imr_sourceaddr; /* IP address of source */ struct in_addr imr_interface; /* local IP address of interface */ } .Ed .Va imr_sourceaddr should be set to the address of the source to be blocked. .Pp To unblock a multicast source on an existing group: .Bd -literal struct ip_mreq_source mreqs; setsockopt(s, IPPROTO_IP, IP_UNBLOCK_SOURCE, &mreqs, sizeof(mreqs)); .Ed .Pp The .Dv IP_BLOCK_SOURCE and .Dv IP_UNBLOCK_SOURCE options are .Em not permitted for inclusive-mode group memberships. .Pp To join a multicast group in .Dv MCAST_INCLUDE mode with a single source, or add another source to an existing inclusive-mode membership: .Bd -literal struct ip_mreq_source mreqs; setsockopt(s, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, &mreqs, sizeof(mreqs)); .Ed .Pp To leave a single source from an existing group in inclusive mode: .Bd -literal struct ip_mreq_source mreqs; setsockopt(s, IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP, &mreqs, sizeof(mreqs)); .Ed If this is the last accepted source for the group, the membership will be dropped. .Pp The .Dv IP_ADD_SOURCE_MEMBERSHIP and .Dv IP_DROP_SOURCE_MEMBERSHIP options are .Em not accepted for exclusive-mode group memberships. However, both exclusive and inclusive mode memberships support the use of the .Em full-state API documented in RFC 3678. For management of source filter lists using this API, please refer to .Xr sourcefilter 3 . .Pp The sysctl settings .Va net.inet.ip.mcast.maxsocksrc and .Va net.inet.ip.mcast.maxgrpsrc are used to specify an upper limit on the number of per-socket and per-group source filter entries which the kernel may allocate. .\"----------------------- .Ss "Raw IP Sockets" Raw .Tn IP sockets are connectionless, and are normally used with the .Xr sendto 2 and .Xr recvfrom 2 calls, though the .Xr connect 2 call may also be used to fix the destination for future packets (in which case the .Xr read 2 or .Xr recv 2 and .Xr write 2 or .Xr send 2 system calls may be used). .Pp If .Fa proto is 0, the default protocol .Dv IPPROTO_RAW is used for outgoing packets, and only incoming packets destined for that protocol are received. If .Fa proto is non-zero, that protocol number will be used on outgoing packets and to filter incoming packets. .Pp Outgoing packets automatically have an .Tn IP header prepended to them (based on the destination address and the protocol number the socket is created with), unless the .Dv IP_HDRINCL option has been set. Unlike in previous .Bx releases, incoming packets are received with .Tn IP header and options intact, leaving all fields in network byte order. .Pp .Dv IP_HDRINCL indicates the complete IP header is included with the data and may be used only with the .Dv SOCK_RAW type. .Bd -literal #include #include int hincl = 1; /* 1 = on, 0 = off */ setsockopt(s, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl)); .Ed .Pp Unlike previous .Bx releases, the program must set all the fields of the IP header, including the following: .Bd -literal ip->ip_v = IPVERSION; ip->ip_hl = hlen >> 2; ip->ip_id = 0; /* 0 means kernel set appropriate value */ ip->ip_off = htons(offset); ip->ip_len = htons(len); .Ed .Pp The packet should be provided as is to be sent over wire. This implies all fields, including .Va ip_len and .Va ip_off to be in network byte order. See .Xr byteorder 3 for more information on network byte order. If the .Va ip_id field is set to 0 then the kernel will choose an appropriate value. If the header source address is set to .Dv INADDR_ANY , the kernel will choose an appropriate address. .Sh ERRORS A socket operation may fail with one of the following errors returned: .Bl -tag -width Er .It Bq Er EISCONN when trying to establish a connection on a socket which already has one, or when trying to send a datagram with the destination address specified and the socket is already connected; .It Bq Er ENOTCONN when trying to send a datagram, but no destination address is specified, and the socket has not been connected; .It Bq Er ENOBUFS when the system runs out of memory for an internal data structure; .It Bq Er EADDRNOTAVAIL when an attempt is made to create a socket with a network address for which no network interface exists. .It Bq Er EACCES when an attempt is made to create a raw IP socket by a non-privileged process. .El .Pp The following errors specific to .Tn IP may occur when setting or getting .Tn IP options: .Bl -tag -width Er .It Bq Er EINVAL An unknown socket option name was given. .It Bq Er EINVAL The IP option field was improperly formed; an option field was shorter than the minimum value or longer than the option buffer provided. .El .Pp The following errors may occur when attempting to send .Tn IP datagrams via a .Dq raw socket with the .Dv IP_HDRINCL option set: .Bl -tag -width Er .It Bq Er EINVAL The user-supplied .Va ip_len field was not equal to the length of the datagram written to the socket. .El .Sh SEE ALSO .Xr getsockopt 2 , .Xr recv 2 , .Xr send 2 , .Xr byteorder 3 , +.Xr sourcefilter 3 , .Xr icmp 4 , .Xr igmp 4 , .Xr inet 4 , .Xr intro 4 , -.Xr multicast 4 , -.Xr sourcefilter 3 +.Xr multicast 4 .Rs .%A D. Thaler .%A B. Fenner .%A B. Quinn .%T "Socket Interface Extensions for Multicast Source Filters" .%N RFC 3678 .%D Jan 2004 .Re .Sh HISTORY The .Nm protocol appeared in .Bx 4.2 . The .Vt ip_mreqn structure appeared in .Tn Linux 2.4 . .Sh BUGS Before .Fx 10.0 packets received on raw IP sockets had the .Va ip_hl subtracted from the .Va ip_len field. .Pp Before .Fx 11.0 packets received on raw IP sockets had the .Va ip_len and .Va ip_off fields converted to host byte order. Packets written to raw IP sockets were expected to have .Va ip_len and .Va ip_off in host byte order. Index: projects/sendfile/share/man/man4/ipheth.4 =================================================================== --- projects/sendfile/share/man/man4/ipheth.4 (revision 276056) +++ projects/sendfile/share/man/man4/ipheth.4 (revision 276057) @@ -1,105 +1,105 @@ .\" Copyright (c) 2014 Gavin Atkinson .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" .\" - Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" - 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 COPYRIGHT HOLDERS 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 .\" COPYRIGHT HOLDERS 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$ .\" .Dd September 30, 2014 .Dt IPHETH 4 .Os .Sh NAME .Nm ipheth .Nd "USB Apple iPhone/iPad tethered Ethernet driver" .Sh SYNOPSIS To load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent if_ipheth_load="YES" .Ed .Pp Alternatively, to compile this driver into the kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device uhci" .Cd "device ohci" .Cd "device usb" .Cd "device ipheth" .Ed .Sh DESCRIPTION The .Nm driver provides support for network access through Apple iPhone and iPad devices, often referred to as USB tethering. .Pp .Nm should work with any Apple iPhone or iPad device. In most cases this must be explicitly enabled on the device first. .Pp For more information on configuring this device, see .Xr ifconfig 8 . The device does not support different media types or options. .Sh HARDWARE The following devices are supported by the .Nm driver: .Pp .Bl -bullet -compact .It Apple iPhone tethering (all models) .It Apple iPad tethering (all models) .El .Sh SEE ALSO .Xr arp 4 , .Xr cdce 4 , .Xr intro 4 , .Xr netintro 4 , .Xr urndis 4 , .Xr usb 4 , -.Xr ifconfig 8 +.Xr ifconfig 8 , .Xr usbconfig 8 .Sh HISTORY The .Nm device driver first appeared in .Fx 8.2 . .Sh AUTHORS .An -nosplit The .Nm driver was written by .An Hans Petter Selasky Aq Mt hselasky@FreeBSD.org . .Sh BUGS Some devices may need to be manually configured to use an alternative configuration with the .Xr usbconfig 8 utility. A command similar to .Dl usbconfig -u 1 -a 2 set_config 3 may be required if the device is not recognised automatically by .Nm after it is connected. Index: projects/sendfile/share/man/man4/iscsi_initiator.4 =================================================================== --- projects/sendfile/share/man/man4/iscsi_initiator.4 (revision 276056) +++ projects/sendfile/share/man/man4/iscsi_initiator.4 (revision 276057) @@ -1,117 +1,118 @@ .\" Copyright (c) 2007-2010 Daniel Braniss .\" 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$ .\" .Dd October 9, 2014 .Dt ISCSI_INITIATOR 4 .Os .Sh NAME .Nm iscsi_initiator .Nd kernel driver for the iSCSI protocol .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device iscsi_initiator" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent iscsi_initiator_load="YES" .Ed .Sh DESCRIPTION .Bf -symbolic This driver, along with its userspace counterpart -.Xr iscontrol 8 , +.Xr iscontrol 8 , is obsolete. Users are advised to use .Xr iscsi 4 instead. .Ef .Pp The .Nm implements the kernel side of the Internet SCSI (iSCSI) network protocol standard, the user land companion is .Xr iscontrol 8 , and permits access to remote .Em virtual SCSI devices via .Xr cam 4 . .Sh SYSCTL VARIABLES .Bl -tag -width ".Va net.iscsi.n.targeaddress" .It Va debug.iscsi_initiator set the debug-level, 0 means no debugging, 9 for maximum. .It Va net.iscsi.isid the initiator part of the Session Identifier. .It Va "kern.cam.cam_srch_hi=1" allow search above LUN 7 for SCSI3 and greater devices. .It "the following are informative only:" .It Va net.iscsi.driver_version the current version of the driver. .It Va net.iscsi.sessions the number of current active sessions. .It Va net.iscsi.n.targetname is the targe name of session .Em n . .It Va net.iscsi.n.targeaddress is the IP address of the target of session .Em n . .It Va net.iscsi.n.stats are some statistics for session .Em n .It Va net.iscsi.n.pid is the .Em "process id" of the userland side of session .Em n , see .Xr iscontrol 8 . .El .Sh FILES The .Nm driver creates the following: .Pp .Bl -tag -width ".Pa /dev/iscsi%dxx" -compact .It Pa /dev/iscsi used to create new sessions. .It Pa /dev/iscsi%d for each new session. .El .Sh SEE ALSO .Xr cam 4 , .Xr camcontrol 8 , .Xr iscontrol 8 .Sh STANDARDS iSCSI RFC 3720 .\" .Sh HISTORY .Sh AUTHORS -This software was written by Daniel Braniss +This software was written by +.An Daniel Braniss Aq Mt danny@cs.huji.ac.il .Sh BUGS The lun discovery method is old-fashioned. Index: projects/sendfile/share/man/man4/isp.4 =================================================================== --- projects/sendfile/share/man/man4/isp.4 (revision 276056) +++ projects/sendfile/share/man/man4/isp.4 (revision 276057) @@ -1,242 +1,244 @@ .\" $NetBSD: isp.4,v 1.5 1999/12/18 18:33:05 mjacob Exp $ .\" .\" Copyright (c) 1998, 1999, 2001 .\" Matthew Jacob, for NASA/Ames Research Center .\" .\" 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. The name of the author may not be used to endorse or promote products .\" derived from this software without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. .\" .\" Additional Copyright (c) 2006 by Marcus Alves Grando .\" .\" $FreeBSD$ .\" .Dd December 1, 2014 .Dt ISP 4 .Os .Sh NAME .Nm isp .Nd Qlogic based SCSI and FibreChannel SCSI Host Adapters .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device scbus" .Cd "device isp" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent isp_load="YES" .Ed .Sh DESCRIPTION This driver provides access to .Tn SCSI or .Tn FibreChannel devices. .Pp SCSI features include support for Ultra SCSI and wide mode transactions for .Tn SCSI , Ultra2 LVD (for the ISP1080 and ISP1280), and Ultra3 LVD (for the ISP12160). .Pp Fibre Channel support uses FCP SCSI profile for .Tn FibreChannel , and utilizes Class 3 and Class 2 connections (Qlogic 2100 is Class 3 only, minor patches to the Qlogic 2200 to force Class 2 mode). Support is available for Public and Private loops, and for point-to-point connections (Qlogic 2200 only). The newer 2-Gigabit cards (2300, 2312, 2322) and 4-Gigabit (2422, 2432) are also supported. Command tagging is supported for all (in fact, .Tn FibreChannel requires tagging). Fabric support is enabled by default for other than 2100 cards. Fabric support for 2100 cards has been so problematic and these cards are so old now that it is just not worth your time to try it. .Sh FIRMWARE Firmware is available if the .Xr ispfw 4 module is loaded during bootstrap (q.v.). .Pp It is .Ar strongly recommended that you use the firmware available from .Xr ispfw 4 as it is the most likely to have been tested with this driver. .Sh HARDWARE Cards supported by the .Nm driver include: .Bl -tag -width xxxxxx -offset indent .It ISP1000 SBus Fast Wide, Ultra Fast Wide cards, Single Ended or Differential cards. .It ISP1020 Qlogic 1020 Fast Wide and Differential Fast Wide PCI cards. .It ISP1040 Qlogic 1040 Ultra Wide and Differential Ultra Wide PCI cards. Also known as the DEC KZPBA-CA (single ended) and KZPBA-CB (HVD differential). .It Qlogic 1240 Qlogic 1240 Dual Bus Ultra Wide and Differential Ultra Wide PCI cards. .It Qlogic 1020 Qlogic 1020 SCSI cards. .It Qlogic 1040 Qlogic 1040 Ultra SCSI cards. .It Qlogic 1080 Qlogic 1280 LVD Ultra2 Wide PCI cards. .It Qlogic 1280 Qlogic 1280 Dual Bus LVD Ultra2 Wide PCI cards. .It Qlogic 12160 Qlogic 12160 Dual Bus LVD Ultra3 Wide PCI cards. .It Qlogic 210X Qlogic 2100 and 2100A Copper and Optical Fibre Channel Arbitrated Loop (single, dual). .It Qlogic 220X Qlogic 2200 Copper and Optical Fibre Channel Arbitrated Loop PCI cards (single, dual, quad). .It Qlogic 2300 Qlogic 2300 Optical Fibre Channel PCI cards. .It Qlogic 2312 Qlogic 2312 Optical Fibre Channel PCI cards. .It Qlogic 234X Qlogic 234X Optical Fibre Channel PCI cards (2312 chipset, single and dual attach). .It Qlogic 2322 Qlogic 2322 Optical Fibre Channel PCIe cards. .It Qlogic 200 Dell Branded version of the QLogic 2312 Fibre Channel PCI cards. .It Qlogic 2422 Qlogic 2422 Optical Fibre Channel PCI cards (4 Gigabit) .It Qlogic 2432 Qlogic 2432 Optical Fibre Channel PCIe cards (4 Gigabit) .It Qlogic 2432 Qlogic 2532 Optical Fibre Channel PCIe cards (8 Gigabit) .El .Sh CONFIGURATION OPTIONS Target mode support may be enabled with the .Pp .Cd options ISP_TARGET_MODE .Pp option. .Sh BOOT OPTIONS The following options are switchable by setting values in .Pa /boot/device.hints . .Pp They are: .Bl -tag -width indent .It Va hint.isp.0.disable A hint value to disable driver in kernel. .It Va hint.isp.0.fwload_disable A hint value to disable loading of firmware .Xr ispfw 4 . .It Va hint.isp.0.prefer_memmap A hint value to use PCI memory space instead of I/O space access for. .It Va hint.isp.0.prefer_iomap A hint value to use PCI I/O space instead of Memory space access for. .It Va hint.isp.0.ignore_nvram A hint value to ignore board NVRAM settings for. Otherwise use NVRAM settings. .It Va hint.isp.0.fullduplex A hint value to set full duplex mode. .It Va hint.isp.0.topology A hint value to select topology of connection. Supported values are: .Pp .Bl -tag -width ".Li lport-only" -compact .It Li lport Prefer loopback and fallback to point to point. .It Li nport Prefer point to point and fallback to loopback. .It Li lport-only Loopback only. .It Li nport-only Point to point only. .El .It Va hint.isp.0.portwwn This should be the full 64 bit World Wide Port Name you would like to use, overriding the value in NVRAM for the card. .It Va hint.isp.0.nodewwn This should be the full 64 bit World Wide Node Name you would like to use, overriding the value in NVRAM for the card. .It Va hint.isp.0.iid A hint to override or set the Initiator ID or Loop ID. For Fibre Channel cards in Local Loop topologies it is .Ar strongly recommended that you set this value to non-zero. .It Va hint.isp.0.role A hint to define default role for isp instance (target, initiator, both). .It Va hint.isp.0.debug A hint value for a driver debug level (see the file .Pa /usr/src/sys/dev/isp/ispvar.h for the values. .It Va hint.isp.0.vports A hint to create specified number of additional virtual ports. .El .Sh SYSCTL OPTIONS .Bl -tag -width indent .It Va dev.isp.N.loop_down_limit This value says how long to wait in seconds after loop has gone down before giving up and expiring all of the devices that were visible. The default is 300 seconds (5 minutes). A separate (nonadjustable) timeout is used when booting to not stop booting on lack of FC connectivity. .It Va dev.isp.N.gone_device_time This value says how long to wait for devices to reappear if they (temporarily) disappear due to loop or fabric events. While this timeout is running, I/O to those devices will simply be held. .It Va dev.isp.N.wwnn This is the readonly World Wide Node Name value for this port. .It Va dev.isp.N.wwpn This is the readonly World Wide Port Name value for this port. .El .Sh SEE ALSO .Xr da 4 , .Xr intro 4 , .Xr ispfw 4 , .Xr sa 4 , .Xr scsi 4 , .Xr gmultipath 8 .Sh AUTHORS The .Nm -driver was written by Matthew Jacob originally for NetBSD at +driver was written by +.An Matthew Jacob +originally for NetBSD at NASA/Ames Research Center. .Sh BUGS The driver currently ignores some NVRAM settings. .Pp Target mode support is not completely reliable yet. It works reasonably well for Fibre Channel, somewhat well for Qlogic 1040 cards, but does not yet work for the other cards (due to last minute unannounced changes in firmware interfaces). Index: projects/sendfile/share/man/man4/ispfw.4 =================================================================== --- projects/sendfile/share/man/man4/ispfw.4 (revision 276056) +++ projects/sendfile/share/man/man4/ispfw.4 (revision 276057) @@ -1,59 +1,60 @@ .\" Copyright (c) 2000 .\" Matthew Jacob .\" .\" 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. The name of the author may not be used to endorse or promote products .\" derived from this software without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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$ .\" .Dd July 20, 2000 .Dt ISPFW 4 .Os .Sh NAME .Nm ispfw .Nd "Firmware Module for Qlogic based SCSI and FibreChannel SCSI Host Adapters" .Sh SYNOPSIS To compile this driver into the kernel, place the following line in your kernel configuration file: .Bd -ragged -offset indent .Cd "device ispfw" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent ispfw_load="YES" .Ed .Sh DESCRIPTION This trivial driver provides access to firmware sets for the Qlogic based SCSI and FibreChannel SCSI Host Adapters. It may either be statically linked into the kernel, or loaded as a module. In either case, the .Xr isp 4 driver will notice that firmware is available to be downloaded onto Qlogic cards (to replace the usually out of date firmware on the cards). This will kick the f/w into getting unstuck. .Sh SEE ALSO .Xr isp 4 .Sh AUTHORS -This driver was written by Matthew Jacob. +This driver was written by +.An Matthew Jacob . Index: projects/sendfile/share/man/man4/iwi.4 =================================================================== --- projects/sendfile/share/man/man4/iwi.4 (revision 276056) +++ projects/sendfile/share/man/man4/iwi.4 (revision 276057) @@ -1,160 +1,160 @@ .\" Copyright (c) 2004-2006 .\" Damien Bergamini . 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 unmodified, 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$ .\" .Dd April 13, 2008 .Dt IWI 4 .Os .Sh NAME .Nm iwi .Nd "Intel PRO/Wireless 2200BG/2225BG/2915ABG IEEE 802.11 driver" .Sh SYNOPSIS To compile this driver into the kernel, include the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device iwi" .Cd "device iwifw" .Cd "device pci" .Cd "device wlan" .Cd "device firmware" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent if_iwi_load="YES" .Ed .Pp In both cases, place the following line in .Xr loader.conf 5 to acknowledge the firmware license (see below): .Bd -literal -offset indent legal.intel_iwi.license_ack=1 .Ed .Sh DESCRIPTION The .Nm driver provides support for .Tn Intel PRO/Wireless 2200BG/2915ABG MiniPCI and 2225BG PCI network adapters. .Nm supports .Cm station , .Cm adhoc , and .Cm monitor mode operation. Only one virtual interface may be configured at any time. For more information on configuring this device, see .Xr ifconfig 8 . .Pp This driver requires the firmware built with the .Nm iwifw module to work. For the loaded firmware to be enabled for use the license at .Pa /usr/share/doc/legal/intel_iwi/LICENSE must be agreed by adding the following line to .Xr loader.conf 5 : .Pp .Dl "legal.intel_iwi.license_ack=1" .Sh FILES .Bl -tag -width ".Pa /usr/share/doc/legal/intel_iwi/LICENSE" -compact .It Pa /usr/share/doc/legal/intel_iwi/LICENSE .Nm firmware license .El .Sh EXAMPLES Join an existing BSS network (i.e., connect to an access point): .Bd -literal -offset indent ifconfig wlan create wlandev iwi0 inet 192.168.0.20 \e netmask 0xffffff00 .Ed .Pp Join a specific BSS network with network name .Dq Li my_net : .Pp .Dl "ifconfig wlan create wlandev iwi0 ssid my_net up" .Pp Join a specific BSS network with 64-bit WEP encryption: .Bd -literal -offset indent ifconfig wlan create wlandev iwi0 ssid my_net \e wepmode on wepkey 0x1234567890 weptxkey 1 up .Ed .Pp Join a specific BSS network with 128-bit WEP encryption: .Bd -literal -offset indent ifconfig wlan create wlandev iwi0 wlanmode adhoc ssid my_net \e wepmode on wepkey 0x01020304050607080910111213 weptxkey 1 .Ed .Sh DIAGNOSTICS .Bl -diag .It "iwi%d: device timeout" The driver will reset the hardware. This should not happen. .It "iwi%d: firmware error" The onboard microcontroller crashed for some reason. The driver will reset the hardware. This should not happen. .It "iwi%d: timeout waiting for firmware initialization to complete" The onboard microcontroller failed to initialize in time. This should not happen. .It "iwi%d: could not load firmware image '%s'" The driver failed to load the firmware image using the .Xr firmware 9 subsystem. Verify the .Xr iwifw 4 firmware module is installed and the license agreement .Xr loader 8 tunable has been set. .It "iwi%d: could not load boot firmware" An attempt to upload the boot firmware image to the onboard microcontroller failed. This should not happen. .It "iwi%d: could not load microcode" An attempt to upload the microcode image to the onboard microcontroller failed. This should not happen. .It "iwi%d: could not load main firmware" An attempt to upload the main firmware image to the onboard microcontroller failed. This should not happen. .El .Sh SEE ALSO .Xr iwifw 4 , .Xr pci 4 , .Xr wlan 4 , .Xr wlan_ccmp 4 , .Xr wlan_tkip 4 , .Xr wlan_wep 4 , .Xr ifconfig 8 , -.Xr wpa_supplicant 8 . +.Xr wpa_supplicant 8 .Sh AUTHORS The original .Nm driver was written by .An Damien Bergamini Aq Mt damien.bergamini@free.fr . Index: projects/sendfile/share/man/man4/mpr.4 =================================================================== --- projects/sendfile/share/man/man4/mpr.4 (revision 276056) +++ projects/sendfile/share/man/man4/mpr.4 (revision 276057) @@ -1,229 +1,229 @@ .\" .\" Copyright (c) 2010 Spectra Logic Corporation .\" Copyright (c) 2014 LSI Corp .\" 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, .\" without modification. .\" 2. Redistributions in binary form must reproduce at minimum a disclaimer .\" substantially similar to the "NO WARRANTY" disclaimer below .\" ("Disclaimer") and any redistribution must be conditioned upon .\" including a substantially similar Disclaimer requirement for further .\" binary redistribution. .\" .\" NO WARRANTY .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS .\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT .\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR .\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT .\" HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. .\" .\" mpr driver man page. .\" .\" Author: Ken Merry .\" Author: Stephen McConnell .\" .\" $Id$ .\" $FreeBSD$ .\" .Dd May 2, 2014 .Dt MPR 4 .Os .Sh NAME .Nm mpr .Nd "LSI Fusion-MPT 3 IT/IR 12Gb/s Serial Attached SCSI/SATA driver" .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device pci" .Cd "device scbus" .Cd "device mpr" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent mpr_load="YES" .Ed .Sh DESCRIPTION The -.Nm +.Nm driver provides support for LSI Fusion-MPT 3 IT/IR .Tn SAS controllers. .Sh HARDWARE The following controllers are supported by the .Nm driver: .Pp .Bl -bullet -compact .It LSI SAS 3004 (4 Port SAS) .It LSI SAS 3008 (8 Port SAS) .It LSI SAS 3108 (8 Port SAS) .El .Sh CONFIGURATION To disable MSI interrupts for all .Nm driver instances, set the following tunable value in .Xr loader.conf 5 : .Bd -literal -offset indent hw.mpr.disable_msi=1 .Ed .Pp To disable MSI interrupts for a specific .Nm driver instance, set the following tunable value in .Xr loader.conf 5 : .Bd -literal -offset indent dev.mpr.X.disable_msi=1 .Ed .Pp where X is the adapter number. .Pp To disable MSI-X interrupts for all .Nm driver instances, set the following tunable value in .Xr loader.conf 5 : .Bd -literal -offset indent hw.mpr.disable_msix=1 .Ed .Pp To disable MSI-X interrupts for a specific .Nm driver instance, set the following tunable value in .Xr loader.conf 5 : .Bd -literal -offset indent dev.mpr.X.disable_msix=1 .Ed .Pp To set the maximum number of DMA chains allocated for all adapters, set the following variable in .Xr loader.conf 5 : .Bd -literal -offset indent hw.mpr.max_chains=NNNN .Ed .Pp To set the maximum number of DMA chains allocated for a specific adapter, set the following variable in .Xr loader.conf 5 : .Bd -literal -offset indent dev.mpr.X.max_chains=NNNN .Ed .Pp This variable may also be viewed via .Xr sysctl 8 to see the maximum set for a given adapter. .Pp The current number of free chain frames may be seen via the dev.mpr.X.chain_free .Xr sysctl 8 variable. .Pp The lowest number of free chain frames may be seen via the dev.mpr.X.chain_free_lowwater .Xr sysctl 8 variable. .Pp The current number of active I/O commands is shown in the dev.mpr.X.io_cmds_active .Xr sysctl 8 variable. .Pp The maximum number of active I/O commands seen since boot is shown in the dev.mpr.X.io_cmds_highwater .Xr sysctl 8 variable. .Pp Devices can be excluded from .Nm control for all adapters by setting the following variable in .Xr loader.conf 5 : .Bd -literal -offset indent hw.mpr.exclude_ids=Y .Ed .Pp where Y is the target ID of the device. If more than one device is to be excluded, target ID's are separated by commas. .Pp Devices can be excluded from .Nm control for a specific adapter by setting the following variable in .Xr loader.conf 5 : .Bd -literal -offset indent dev.mpr.X.exclude_ids=Y .Ed .Pp where X is the adapter number and Y is the target ID of the device. If more than one device is to be excluded, target ID's are separated by commas. .Sh DEBUGGING To enable debugging prints from the .Nm driver, set the .Bd -literal -offset indent hw.mpr.X.debug_level .Ed .Pp variable, where X is the adapter number, either in .Xr loader.conf 5 or via .Xr sysctl 8 . The following bits have the described effects: .Bd -literal -offset indent 0x0001 Enable informational prints. 0x0002 Enable prints for driver faults. 0x0004 Enable prints for controller events. 0x0008 Enable prints for controller logging. 0x0010 Enable prints for tracing recovery operations. 0x0020 Enable prints for parameter errors and programming bugs. 0x0040 Enable prints for system initialization operations. 0x0080 Enable prints for more detailed information. 0x0100 Enable prints for user-generated commands. 0x0200 Enable prints for device mapping. 0x0400 Enable prints for tracing through driver functions. .Ed .Sh SEE ALSO .Xr cam 4 , .Xr cd 4 , .Xr ch 4 , .Xr da 4 , .Xr mps 4 , .Xr mpt 4 , .Xr pci 4 , .Xr sa 4 , .Xr scsi 4 , .Xr targ 4 , .Xr loader.conf 5 , .Xr sysctl 8 .Sh HISTORY The .Nm driver first appeared in FreeBSD 9.3. .Sh AUTHORS The .Nm driver was originally written by .An -nosplit .An Scott Long Aq Mt scottl@FreeBSD.org . It has been improved and tested by LSI Corporation. .Pp This man page was written by .An Ken Merry Aq Mt ken@FreeBSD.org with additional input from .An Stephen McConnell Aq Mt stephen.mcconnell@lsi.com . Index: projects/sendfile/share/man/man4/mrsas.4 =================================================================== --- projects/sendfile/share/man/man4/mrsas.4 (revision 276056) +++ projects/sendfile/share/man/man4/mrsas.4 (revision 276057) @@ -1,403 +1,403 @@ .\" Copyright (c) 2014 LSI Corp .\" All rights reserved. .\" Author: Kashyap Desai .\" Support: freebsdraid@lsi.com .\" .\" 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. Neither the name of the 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 COPYRIGHT HOLDERS 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 .\" COPYRIGHT HOLDER 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. -.\" +.\" .\" The views and conclusions contained in the software and documentation .\" are those of the authors and should not be interpreted as representing .\" official policies, either expressed or implied, of the FreeBSD Project. .\" .\" $FreeBSD$ .\" .Dd May 8, 2014 .Dt MRSAS 4 .Os .Sh NAME .Nm mrsas .Nd "LSI MegaRAID 6Gb/s and 12Gb/s SAS+SATA RAID controller driver" .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device pci" .Cd "device mrsas" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent mrsas_load="YES" .Ed .Sh DESCRIPTION The -.Nm +.Nm driver will detect LSI's next generation (6Gb/s and 12Gb/s) PCI Express SAS/SATA RAID controllers. See the .Nm HARDWARE section for the supported devices list. -A disk (virtual disk/physical disk) attached to the +A disk (virtual disk/physical disk) attached to the .Nm -driver will be visible to the user through +driver will be visible to the user through .Xr camcontrol 8 as .Pa /dev/da? device nodes. A simple management interface is also provided on a per-controller basis via the .Pa /dev/mrsas? device node. .Pp The .Nm name is derived from the phrase "MegaRAID SAS HBA", which is substantially different than the old "MegaRAID" Driver .Xr mfi 4 -which does not connect targets -to the +which does not connect targets +to the .Xr cam 4 -layer and thus requires a new driver which attaches targets to the -.Xr cam 4 +layer and thus requires a new driver which attaches targets to the +.Xr cam 4 layer. Older MegaRAID controllers are supported by .Xr mfi 4 and will not work with .Nm , but both the .Xr mfi 4 -and +and .Nm drivers can detect and manage the LSI MegaRAID SAS 2208/2308/3008/3108 series of controllers. .Pp The .Xr device.hints 5 option is provided to tune the .Nm driver's behavior for LSI MegaRAID SAS 2208/2308/3008/3108 controllers. By default, the .Xr mfi 4 driver will detect these controllers. -See the -.Nm PRIORITY +See the +.Nm PRIORITY section to know more about driver priority for MR-Fusion devices. .Pp .Nm will provide a priority of (-30) (between .Dv BUS_PROBE_DEFAULT and .Dv BUS_PROBE_LOW_PRIORITY ) at probe call for device id's 0x005B, 0x005D, and 0x005F so that .Nm does not take control of these devices without user intervention. .Sh HARDWARE The .Nm driver supports the following hardware: .Pp [ Thunderbolt 6Gb/s MR controller ] .Bl -bullet -compact .It LSI MegaRAID SAS 9265 .It LSI MegaRAID SAS 9266 .It LSI MegaRAID SAS 9267 .It LSI MegaRAID SAS 9270 .It LSI MegaRAID SAS 9271 .It LSI MegaRAID SAS 9272 .It LSI MegaRAID SAS 9285 .It LSI MegaRAID SAS 9286 .It DELL PERC H810 .It DELL PERC H710/P .El .Pp [ Invader/Fury 12Gb/s MR controller ] .Bl -bullet -compact .It LSI MegaRAID SAS 9380 .It LSI MegaRAID SAS 9361 .It LSI MegaRAID SAS 9341 .It DELL PERC H830 .It DELL PERC H730/P .It DELL PERC H330 .El .Sh CONFIGURATION To disable Online Controller Reset(OCR) for a specific .Nm -driver instance, set the +driver instance, set the following tunable value in .Xr loader.conf 5 : .Bd -literal -offset indent -dev.mrsas.X.disable_ocr=1 +dev.mrsas.X.disable_ocr=1 .Ed .Pp where X is the adapter number. .Pp -To change the I/O timeout value for a specific +To change the I/O timeout value for a specific .Nm driver instance, set the following tunable value in .Xr loader.conf 5 : .Bd -literal -offset indent dev.mrsas.X.mrsas_io_timeout=NNNNNN .Ed .Pp where NNNNNN is the timeout value in milli-seconds. .Pp To change the firmware fault check timer value for a specific .Nm driver instance, set the following tunable value in .Xr loader.conf 5 : .Bd -literal -offset indent dev.mrsas.X.mrsas_fw_fault_check_delay=NN .Ed .Pp where NN is the fault check delay value in seconds. .Pp The current number of active I/O commands is shown in the .Va dev.mrsas.X.fw_outstanding .Xr sysctl 8 variable. .Sh DEBUGGING To enable debugging prints from the .Nm driver, set the .Va hw.mrsas.X.debug_level variable, where X is the adapter number, either in .Xr loader.conf 5 or via .Xr sysctl 8 . The following bits have the described effects: .Bl -tag -width indent -offset indent .It 0x01 Enable informational prints. .It 0x02 Enable tracing prints. .It 0x04 Enable prints for driver faults. .It 0x08 Enable prints for OCR and I/O timeout. .It 0x10 Enable prints for AEN events. .El .Sh PRIORITY The .Nm driver will always set a default (-30) priority in the PCI subsystem for selection of MR-Fusion cards. (It is between .Dv BUS_PROBE_DEFAULT and .Dv BUS_PROBE_LOW_PRIORITY ) . MR-Fusion Controllers include all cards with the Device IDs - -0x005B, +0x005B, 0x005D, 0x005F. .Pp The -.Xr mfi 4 +.Xr mfi 4 driver will set a priority of either .Dv BUS_PROBE_DEFAULT or .Dv BUS_PROBE_LOW_PRIORITY (depending on the device.hints setting) in the PCI subsystem for selection of MR-Fusion cards. With the above design in place, the .Xr mfi 4 driver will attach to a MR-Fusion card given that it has a higher priority than .Nm . .Pp Using .Pa /boot/device.hints (as mentioned below), the user can provide a preference for the .Nm driver to detect a MR-Fusion card instead of the .Xr mfi 4 -driver. +driver. .Bd -ragged -offset indent .Cd hw.mfi.mrsas_enable="1" .Ed .Pp At boot time, the -.Xr mfi 4 +.Xr mfi 4 driver will get priority to detect MR-Fusion controllers by default. Before changing this default driver selection policy, LSI advises users to understand how the driver selection policy works. LSI's policy is to provide priority to the .Xr mfi 4 driver to detect MR-Fusion cards, but allow for the ability to choose the .Nm driver to detect MR-Fusion cards. .Pp LSI recommends setting hw.mfi.mrsas_enable="0" for customers who are using the -older -.Xr mfi 4 -driver and do not want to switch to +older +.Xr mfi 4 +driver and do not want to switch to .Nm . For those customers who are using a MR-Fusion controller for the first time, LSI recommends using the .Nm driver and setting hw.mfi.mrsas_enable="1". .Pp Changing the default behavior is well tested under most conditions, but unexpected behavior may pop up if more complex and unrealistic operations are executed by switching between the .Xr mfi 4 -and -.Nm +and +.Nm drivers for MR-Fusion. Switching drivers is designed to happen only one time. Although multiple switching is possible, it is not recommended. The user should decide from .Nm Start of Day which driver they want to use for the MR-Fusion card. .Pp -The user may see different device names when switching from -.Xr mfi 4 -to +The user may see different device names when switching from +.Xr mfi 4 +to .Nm . This behavior is .Nm Functions As Designed and the user needs to change the .Xr fstab 5 -entry manually if they are doing any experiments with -.Xr mfi 4 +entry manually if they are doing any experiments with +.Xr mfi 4 and .Nm interoperability. .Sh FILES .Bl -tag -width ".Pa /dev/mrsas?" -compact .It Pa /dev/da? array/logical disk interface .It Pa /dev/mrsas? management interface .El .Sh SEE ALSO .Xr cam 4 , .Xr mfi 4 , .Xr pci 4 , .Xr device.hints 5 , .Xr camcontrol 8 .Sh HISTORY The .Nm driver first appeared in .Fx 10.1 . .Bd -ragged .Cd "mfi Driver:" .Xr mfi 4 is the old .Fx driver which started with support for Gen-1 Controllers and was extended to support up to MR-Fusion (Device ID = 0x005B, 0x005D, 0x005F). .Ed .Bd -ragged .Cd "mrsas Driver:" .Nm is the new driver reworked by LSI which supports Thunderbolt and onward products. The SAS+SATA RAID controller with device id 0x005b is referred to as the Thunderbolt controller throughout this man page. -.Ed +.Ed .Bd -ragged .Nm cam aware HBA drivers: .Fx has a .Xr cam 4 layer which attaches storage devices and provides a common access mechanism to storage controllers and attached devices. The -.Nm +.Nm driver is .Xr cam 4 -aware and devices associated with -.Nm -can be seen using +aware and devices associated with +.Nm +can be seen using .Xr camcontrol 8 . The .Xr mfi 4 driver does not understand the .Xr cam 4 layer and it directly associates storage disks to the block layer. .Pp -.Nm Thunderbolt Controller: +.Nm Thunderbolt Controller: This is the 6Gb/s MegaRAID HBA card which has device id 0x005B. .Pp -.Nm Invader Controller: +.Nm Invader Controller: This is 12Gb/s MegaRAID HBA card which has device id 0x005D. .Pp -.Nm Fury Controller: +.Nm Fury Controller: This is the 12Gb/s MegaRAID HBA card which has device id 0x005F. .Ed .Sh AUTHORS The .Nm driver and this manual page were written by .An Kashyap Desai Aq Mt Kashyap.Desai@lsi.com . .Sh TODO The driver does not support big-endian architectures at this time. .Pp The driver does not support alias for device name (it is required when the user switches between two drivers and does not want to edit .Pa /etc/fstab manually). .Pp The -.Nm +.Nm driver exposes devices as .Pa /dev/da? , -whereas -.Xr mfi 4 +whereas +.Xr mfi 4 exposes devices as .Pa /dev/mfid? . .Pp .Nm does not support the Linux Emulator interface. .Pp .Nm will not work with .Xr mfiutil 8 . Index: projects/sendfile/share/man/man4/multicast.4 =================================================================== --- projects/sendfile/share/man/man4/multicast.4 (revision 276056) +++ projects/sendfile/share/man/man4/multicast.4 (revision 276057) @@ -1,1011 +1,1011 @@ .\" Copyright (c) 2001-2003 International Computer Science Institute .\" .\" Permission is hereby granted, free of charge, to any person obtaining a .\" copy of this software and associated documentation files (the "Software"), .\" to deal in the Software without restriction, including without limitation .\" the rights to use, copy, modify, merge, publish, distribute, sublicense, .\" and/or sell copies of the Software, and to permit persons to whom the .\" Software is furnished to do so, subject to the following conditions: .\" .\" The above copyright notice and this permission notice shall be included in .\" all copies or substantial portions of the Software. .\" .\" The names and trademarks of copyright holders may not be used in .\" advertising or publicity pertaining to the software without specific .\" prior permission. Title to copyright in this software and any associated .\" documentation will at all times remain with the copyright holders. .\" .\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR .\" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, .\" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE .\" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER .\" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING .\" FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER .\" DEALINGS IN THE SOFTWARE. .\" .\" $FreeBSD$ .\" .Dd May 27, 2009 .Dt MULTICAST 4 .Os .\" .Sh NAME .Nm multicast .Nd Multicast Routing .\" .Sh SYNOPSIS .Cd "options MROUTING" .Pp .In sys/types.h .In sys/socket.h .In netinet/in.h .In netinet/ip_mroute.h .In netinet6/ip6_mroute.h .Ft int .Fn getsockopt "int s" IPPROTO_IP MRT_INIT "void *optval" "socklen_t *optlen" .Ft int .Fn setsockopt "int s" IPPROTO_IP MRT_INIT "const void *optval" "socklen_t optlen" .Ft int .Fn getsockopt "int s" IPPROTO_IPV6 MRT6_INIT "void *optval" "socklen_t *optlen" .Ft int .Fn setsockopt "int s" IPPROTO_IPV6 MRT6_INIT "const void *optval" "socklen_t optlen" .Sh DESCRIPTION .Tn "Multicast routing" is used to efficiently propagate data packets to a set of multicast listeners in multipoint networks. If unicast is used to replicate the data to all listeners, then some of the network links may carry multiple copies of the same data packets. With multicast routing, the overhead is reduced to one copy (at most) per network link. .Pp All multicast-capable routers must run a common multicast routing protocol. It is recommended that either Protocol Independent Multicast - Sparse Mode (PIM-SM), or Protocol Independent Multicast - Dense Mode (PIM-DM) are used, as these are now the generally accepted protocols in the Internet community. The .Sx HISTORY section discusses previous multicast routing protocols. .Pp To start multicast routing, the user must enable multicast forwarding in the kernel (see .Sx SYNOPSIS about the kernel configuration options), and must run a multicast routing capable user-level process. From developer's point of view, the programming guide described in the .Sx "Programming Guide" section should be used to control the multicast forwarding in the kernel. .\" .Ss Programming Guide This section provides information about the basic multicast routing API. The so-called .Dq advanced multicast API is described in the .Sx "Advanced Multicast API Programming Guide" section. .Pp First, a multicast routing socket must be open. That socket would be used to control the multicast forwarding in the kernel. Note that most operations below require certain privilege (i.e., root privilege): .Bd -literal /* IPv4 */ int mrouter_s4; mrouter_s4 = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); .Ed .Bd -literal int mrouter_s6; mrouter_s6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); .Ed .Pp Note that if the router needs to open an IGMP or ICMPv6 socket (in case of IPv4 and IPv6 respectively) for sending or receiving of IGMP or MLD multicast group membership messages, then the same .Va mrouter_s4 or .Va mrouter_s6 sockets should be used for sending and receiving respectively IGMP or MLD messages. In case of .Bx Ns -derived kernel, it may be possible to open separate sockets for IGMP or MLD messages only. However, some other kernels (e.g., .Tn Linux ) require that the multicast routing socket must be used for sending and receiving of IGMP or MLD messages. Therefore, for portability reason the multicast routing socket should be reused for IGMP and MLD messages as well. .Pp After the multicast routing socket is open, it can be used to enable or disable multicast forwarding in the kernel: .Bd -literal /* IPv4 */ int v = 1; /* 1 to enable, or 0 to disable */ setsockopt(mrouter_s4, IPPROTO_IP, MRT_INIT, (void *)&v, sizeof(v)); .Ed .Bd -literal /* IPv6 */ int v = 1; /* 1 to enable, or 0 to disable */ setsockopt(mrouter_s6, IPPROTO_IPV6, MRT6_INIT, (void *)&v, sizeof(v)); \&... /* If necessary, filter all ICMPv6 messages */ struct icmp6_filter filter; ICMP6_FILTER_SETBLOCKALL(&filter); setsockopt(mrouter_s6, IPPROTO_ICMPV6, ICMP6_FILTER, (void *)&filter, sizeof(filter)); .Ed .Pp After multicast forwarding is enabled, the multicast routing socket can be used to enable PIM processing in the kernel if we are running PIM-SM or PIM-DM (see .Xr pim 4 ) . .Pp For each network interface (e.g., physical or a virtual tunnel) that would be used for multicast forwarding, a corresponding multicast interface must be added to the kernel: .Bd -literal /* IPv4 */ struct vifctl vc; memset(&vc, 0, sizeof(vc)); /* Assign all vifctl fields as appropriate */ vc.vifc_vifi = vif_index; vc.vifc_flags = vif_flags; vc.vifc_threshold = min_ttl_threshold; vc.vifc_rate_limit = 0; memcpy(&vc.vifc_lcl_addr, &vif_local_address, sizeof(vc.vifc_lcl_addr)); setsockopt(mrouter_s4, IPPROTO_IP, MRT_ADD_VIF, (void *)&vc, sizeof(vc)); .Ed .Pp The .Va vif_index must be unique per vif. The .Va vif_flags contains the .Dv VIFF_* flags as defined in .In netinet/ip_mroute.h . The .Dv VIFF_TUNNEL flag is no longer supported by .Fx . Users who wish to forward multicast datagrams over a tunnel should consider configuring a .Xr gif 4 or .Xr gre 4 tunnel and using it as a physical interface. .Pp The .Va min_ttl_threshold contains the minimum TTL a multicast data packet must have to be forwarded on that vif. Typically, it would have value of 1. .Pp The .Va max_rate_limit argument is no longer supported in .Fx and should be set to 0. Users who wish to rate-limit multicast datagrams should consider the use of .Xr dummynet 4 or .Xr altq 4 . .Pp The .Va vif_local_address contains the local IP address of the corresponding local interface. The .Va vif_remote_address contains the remote IP address in case of DVMRP multicast tunnels. .Bd -literal /* IPv6 */ struct mif6ctl mc; memset(&mc, 0, sizeof(mc)); /* Assign all mif6ctl fields as appropriate */ mc.mif6c_mifi = mif_index; mc.mif6c_flags = mif_flags; mc.mif6c_pifi = pif_index; setsockopt(mrouter_s6, IPPROTO_IPV6, MRT6_ADD_MIF, (void *)&mc, sizeof(mc)); .Ed .Pp The .Va mif_index must be unique per vif. The .Va mif_flags contains the .Dv MIFF_* flags as defined in .In netinet6/ip6_mroute.h . The .Va pif_index is the physical interface index of the corresponding local interface. .Pp A multicast interface is deleted by: .Bd -literal /* IPv4 */ vifi_t vifi = vif_index; setsockopt(mrouter_s4, IPPROTO_IP, MRT_DEL_VIF, (void *)&vifi, sizeof(vifi)); .Ed .Bd -literal /* IPv6 */ mifi_t mifi = mif_index; setsockopt(mrouter_s6, IPPROTO_IPV6, MRT6_DEL_MIF, (void *)&mifi, sizeof(mifi)); .Ed .Pp After the multicast forwarding is enabled, and the multicast virtual interfaces are added, the kernel may deliver upcall messages (also called signals later in this text) on the multicast routing socket that was open earlier with .Dv MRT_INIT or .Dv MRT6_INIT . The IPv4 upcalls have .Vt "struct igmpmsg" header (see .In netinet/ip_mroute.h ) with field .Va im_mbz set to zero. Note that this header follows the structure of .Vt "struct ip" with the protocol field .Va ip_p set to zero. The IPv6 upcalls have .Vt "struct mrt6msg" header (see .In netinet6/ip6_mroute.h ) with field .Va im6_mbz set to zero. Note that this header follows the structure of .Vt "struct ip6_hdr" with the next header field .Va ip6_nxt set to zero. .Pp The upcall header contains field .Va im_msgtype and .Va im6_msgtype with the type of the upcall .Dv IGMPMSG_* and .Dv MRT6MSG_* for IPv4 and IPv6 respectively. The values of the rest of the upcall header fields and the body of the upcall message depend on the particular upcall type. .Pp If the upcall message type is .Dv IGMPMSG_NOCACHE or .Dv MRT6MSG_NOCACHE , this is an indication that a multicast packet has reached the multicast router, but the router has no forwarding state for that packet. Typically, the upcall would be a signal for the multicast routing user-level process to install the appropriate Multicast Forwarding Cache (MFC) entry in the kernel. .Pp An MFC entry is added by: .Bd -literal /* IPv4 */ struct mfcctl mc; memset(&mc, 0, sizeof(mc)); memcpy(&mc.mfcc_origin, &source_addr, sizeof(mc.mfcc_origin)); memcpy(&mc.mfcc_mcastgrp, &group_addr, sizeof(mc.mfcc_mcastgrp)); mc.mfcc_parent = iif_index; for (i = 0; i < maxvifs; i++) mc.mfcc_ttls[i] = oifs_ttl[i]; setsockopt(mrouter_s4, IPPROTO_IP, MRT_ADD_MFC, (void *)&mc, sizeof(mc)); .Ed .Bd -literal /* IPv6 */ struct mf6cctl mc; memset(&mc, 0, sizeof(mc)); memcpy(&mc.mf6cc_origin, &source_addr, sizeof(mc.mf6cc_origin)); memcpy(&mc.mf6cc_mcastgrp, &group_addr, sizeof(mf6cc_mcastgrp)); mc.mf6cc_parent = iif_index; for (i = 0; i < maxvifs; i++) if (oifs_ttl[i] > 0) IF_SET(i, &mc.mf6cc_ifset); setsockopt(mrouter_s6, IPPROTO_IPV6, MRT6_ADD_MFC, (void *)&mc, sizeof(mc)); .Ed .Pp The .Va source_addr and .Va group_addr are the source and group address of the multicast packet (as set in the upcall message). The .Va iif_index is the virtual interface index of the multicast interface the multicast packets for this specific source and group address should be received on. The .Va oifs_ttl[] array contains the minimum TTL (per interface) a multicast packet should have to be forwarded on an outgoing interface. If the TTL value is zero, the corresponding interface is not included in the set of outgoing interfaces. Note that in case of IPv6 only the set of outgoing interfaces can be specified. .Pp An MFC entry is deleted by: .Bd -literal /* IPv4 */ struct mfcctl mc; memset(&mc, 0, sizeof(mc)); memcpy(&mc.mfcc_origin, &source_addr, sizeof(mc.mfcc_origin)); memcpy(&mc.mfcc_mcastgrp, &group_addr, sizeof(mc.mfcc_mcastgrp)); setsockopt(mrouter_s4, IPPROTO_IP, MRT_DEL_MFC, (void *)&mc, sizeof(mc)); .Ed .Bd -literal /* IPv6 */ struct mf6cctl mc; memset(&mc, 0, sizeof(mc)); memcpy(&mc.mf6cc_origin, &source_addr, sizeof(mc.mf6cc_origin)); memcpy(&mc.mf6cc_mcastgrp, &group_addr, sizeof(mf6cc_mcastgrp)); setsockopt(mrouter_s6, IPPROTO_IPV6, MRT6_DEL_MFC, (void *)&mc, sizeof(mc)); .Ed .Pp The following method can be used to get various statistics per installed MFC entry in the kernel (e.g., the number of forwarded packets per source and group address): .Bd -literal /* IPv4 */ struct sioc_sg_req sgreq; memset(&sgreq, 0, sizeof(sgreq)); memcpy(&sgreq.src, &source_addr, sizeof(sgreq.src)); memcpy(&sgreq.grp, &group_addr, sizeof(sgreq.grp)); ioctl(mrouter_s4, SIOCGETSGCNT, &sgreq); .Ed .Bd -literal /* IPv6 */ struct sioc_sg_req6 sgreq; memset(&sgreq, 0, sizeof(sgreq)); memcpy(&sgreq.src, &source_addr, sizeof(sgreq.src)); memcpy(&sgreq.grp, &group_addr, sizeof(sgreq.grp)); ioctl(mrouter_s6, SIOCGETSGCNT_IN6, &sgreq); .Ed .Pp The following method can be used to get various statistics per multicast virtual interface in the kernel (e.g., the number of forwarded packets per interface): .Bd -literal /* IPv4 */ struct sioc_vif_req vreq; memset(&vreq, 0, sizeof(vreq)); vreq.vifi = vif_index; ioctl(mrouter_s4, SIOCGETVIFCNT, &vreq); .Ed .Bd -literal /* IPv6 */ struct sioc_mif_req6 mreq; memset(&mreq, 0, sizeof(mreq)); mreq.mifi = vif_index; ioctl(mrouter_s6, SIOCGETMIFCNT_IN6, &mreq); .Ed .Ss Advanced Multicast API Programming Guide If we want to add new features in the kernel, it becomes difficult to preserve backward compatibility (binary and API), and at the same time to allow user-level processes to take advantage of the new features (if the kernel supports them). .Pp One of the mechanisms that allows us to preserve the backward compatibility is a sort of negotiation between the user-level process and the kernel: .Bl -enum .It The user-level process tries to enable in the kernel the set of new features (and the corresponding API) it would like to use. .It The kernel returns the (sub)set of features it knows about and is willing to be enabled. .It The user-level process uses only that set of features the kernel has agreed on. .El .\" .Pp To support backward compatibility, if the user-level process does not ask for any new features, the kernel defaults to the basic multicast API (see the .Sx "Programming Guide" section). .\" XXX: edit as appropriate after the advanced multicast API is .\" supported under IPv6 Currently, the advanced multicast API exists only for IPv4; in the future there will be IPv6 support as well. .Pp Below is a summary of the expandable API solution. Note that all new options and structures are defined in .In netinet/ip_mroute.h and .In netinet6/ip6_mroute.h , unless stated otherwise. .Pp The user-level process uses new .Fn getsockopt Ns / Ns Fn setsockopt options to perform the API features negotiation with the kernel. This negotiation must be performed right after the multicast routing socket is open. The set of desired/allowed features is stored in a bitset (currently, in .Vt uint32_t ; i.e., maximum of 32 new features). The new .Fn getsockopt Ns / Ns Fn setsockopt options are .Dv MRT_API_SUPPORT and .Dv MRT_API_CONFIG . Example: .Bd -literal uint32_t v; getsockopt(sock, IPPROTO_IP, MRT_API_SUPPORT, (void *)&v, sizeof(v)); .Ed .Pp would set in .Va v the pre-defined bits that the kernel API supports. The eight least significant bits in .Vt uint32_t are same as the eight possible flags .Dv MRT_MFC_FLAGS_* that can be used in .Va mfcc_flags as part of the new definition of .Vt "struct mfcctl" (see below about those flags), which leaves 24 flags for other new features. The value returned by .Fn getsockopt MRT_API_SUPPORT is read-only; in other words, .Fn setsockopt MRT_API_SUPPORT would fail. .Pp To modify the API, and to set some specific feature in the kernel, then: .Bd -literal uint32_t v = MRT_MFC_FLAGS_DISABLE_WRONGVIF; if (setsockopt(sock, IPPROTO_IP, MRT_API_CONFIG, (void *)&v, sizeof(v)) != 0) { return (ERROR); } if (v & MRT_MFC_FLAGS_DISABLE_WRONGVIF) return (OK); /* Success */ else return (ERROR); .Ed .Pp In other words, when .Fn setsockopt MRT_API_CONFIG is called, the argument to it specifies the desired set of features to be enabled in the API and the kernel. The return value in .Va v is the actual (sub)set of features that were enabled in the kernel. To obtain later the same set of features that were enabled, then: .Bd -literal getsockopt(sock, IPPROTO_IP, MRT_API_CONFIG, (void *)&v, sizeof(v)); .Ed .Pp The set of enabled features is global. In other words, .Fn setsockopt MRT_API_CONFIG should be called right after .Fn setsockopt MRT_INIT . .Pp Currently, the following set of new features is defined: .Bd -literal #define MRT_MFC_FLAGS_DISABLE_WRONGVIF (1 << 0) /* disable WRONGVIF signals */ #define MRT_MFC_FLAGS_BORDER_VIF (1 << 1) /* border vif */ #define MRT_MFC_RP (1 << 8) /* enable RP address */ #define MRT_MFC_BW_UPCALL (1 << 9) /* enable bw upcalls */ .Ed .\" .Pp .\" In the future there might be: .\" .Bd -literal .\" #define MRT_MFC_GROUP_SPECIFIC (1 << 10) /* allow (*,G) MFC entries */ .\" .Ed .\" .Pp .\" to allow (*,G) MFC entries (i.e., group-specific entries) in the kernel. .\" For now this is left-out until it is clear whether .\" (*,G) MFC support is the preferred solution instead of something more generic .\" solution for example. .\" .\" 2. The newly defined struct mfcctl2. .\" .Pp The advanced multicast API uses a newly defined .Vt "struct mfcctl2" instead of the traditional .Vt "struct mfcctl" . The original .Vt "struct mfcctl" is kept as is. The new .Vt "struct mfcctl2" is: .Bd -literal /* * The new argument structure for MRT_ADD_MFC and MRT_DEL_MFC overlays * and extends the old struct mfcctl. */ struct mfcctl2 { /* the mfcctl fields */ struct in_addr mfcc_origin; /* ip origin of mcasts */ struct in_addr mfcc_mcastgrp; /* multicast group associated*/ vifi_t mfcc_parent; /* incoming vif */ u_char mfcc_ttls[MAXVIFS];/* forwarding ttls on vifs */ /* extension fields */ uint8_t mfcc_flags[MAXVIFS];/* the MRT_MFC_FLAGS_* flags*/ struct in_addr mfcc_rp; /* the RP address */ }; .Ed .Pp The new fields are .Va mfcc_flags[MAXVIFS] and .Va mfcc_rp . Note that for compatibility reasons they are added at the end. .Pp The .Va mfcc_flags[MAXVIFS] field is used to set various flags per interface per (S,G) entry. Currently, the defined flags are: .Bd -literal #define MRT_MFC_FLAGS_DISABLE_WRONGVIF (1 << 0) /* disable WRONGVIF signals */ #define MRT_MFC_FLAGS_BORDER_VIF (1 << 1) /* border vif */ .Ed .Pp The .Dv MRT_MFC_FLAGS_DISABLE_WRONGVIF flag is used to explicitly disable the .Dv IGMPMSG_WRONGVIF kernel signal at the (S,G) granularity if a multicast data packet arrives on the wrong interface. Usually, this signal is used to complete the shortest-path switch in case of PIM-SM multicast routing, or to trigger a PIM assert message. However, it should not be delivered for interfaces that are not in the outgoing interface set, and that are not expecting to become an incoming interface. Hence, if the .Dv MRT_MFC_FLAGS_DISABLE_WRONGVIF flag is set for some of the interfaces, then a data packet that arrives on that interface for that MFC entry will NOT trigger a WRONGVIF signal. If that flag is not set, then a signal is triggered (the default action). .Pp The .Dv MRT_MFC_FLAGS_BORDER_VIF flag is used to specify whether the Border-bit in PIM Register messages should be set (in case when the Register encapsulation is performed inside the kernel). If it is set for the special PIM Register kernel virtual interface (see .Xr pim 4 ) , the Border-bit in the Register messages sent to the RP will be set. .Pp The remaining six bits are reserved for future usage. .Pp The .Va mfcc_rp field is used to specify the RP address (in case of PIM-SM multicast routing) for a multicast group G if we want to perform kernel-level PIM Register encapsulation. The .Va mfcc_rp field is used only if the .Dv MRT_MFC_RP advanced API flag/capability has been successfully set by .Fn setsockopt MRT_API_CONFIG . .Pp .\" .\" 3. Kernel-level PIM Register encapsulation .\" If the .Dv MRT_MFC_RP flag was successfully set by .Fn setsockopt MRT_API_CONFIG , then the kernel will attempt to perform the PIM Register encapsulation itself instead of sending the multicast data packets to user level (inside .Dv IGMPMSG_WHOLEPKT upcalls) for user-level encapsulation. The RP address would be taken from the .Va mfcc_rp field inside the new .Vt "struct mfcctl2" . However, even if the .Dv MRT_MFC_RP flag was successfully set, if the .Va mfcc_rp field was set to .Dv INADDR_ANY , then the kernel will still deliver an .Dv IGMPMSG_WHOLEPKT upcall with the multicast data packet to the user-level process. .Pp In addition, if the multicast data packet is too large to fit within a single IP packet after the PIM Register encapsulation (e.g., if its size was on the order of 65500 bytes), the data packet will be fragmented, and then each of the fragments will be encapsulated separately. Note that typically a multicast data packet can be that large only if it was originated locally from the same hosts that performs the encapsulation; otherwise the transmission of the multicast data packet over Ethernet for example would have fragmented it into much smaller pieces. .\" .\" Note that if this code is ported to IPv6, we may need the kernel to .\" perform MTU discovery to the RP, and keep those discoveries inside .\" the kernel so the encapsulating router may send back ICMP .\" Fragmentation Required if the size of the multicast data packet is .\" too large (see "Encapsulating data packets in the Register Tunnel" .\" in Section 4.4.1 in the PIM-SM spec .\" draft-ietf-pim-sm-v2-new-05.{txt,ps}). .\" For IPv4 we may be able to get away without it, but for IPv6 we need .\" that. .\" .\" 4. Mechanism for "multicast bandwidth monitoring and upcalls". .\" .Pp Typically, a multicast routing user-level process would need to know the forwarding bandwidth for some data flow. For example, the multicast routing process may want to timeout idle MFC entries, or in case of PIM-SM it can initiate (S,G) shortest-path switch if the bandwidth rate is above a threshold for example. .Pp The original solution for measuring the bandwidth of a dataflow was that a user-level process would periodically query the kernel about the number of forwarded packets/bytes per (S,G), and then based on those numbers it would estimate whether a source has been idle, or whether the source's transmission bandwidth is above a threshold. That solution is far from being scalable, hence the need for a new mechanism for bandwidth monitoring. .Pp Below is a description of the bandwidth monitoring mechanism. .Bl -bullet .It If the bandwidth of a data flow satisfies some pre-defined filter, the kernel delivers an upcall on the multicast routing socket to the multicast routing process that has installed that filter. .It The bandwidth-upcall filters are installed per (S,G). There can be more than one filter per (S,G). .It Instead of supporting all possible comparison operations (i.e., < <= == != > >= ), there is support only for the <= and >= operations, because this makes the kernel-level implementation simpler, and because practically we need only those two. Further, the missing operations can be simulated by secondary user-level filtering of those <= and >= filters. For example, to simulate !=, then we need to install filter .Dq bw <= 0xffffffff , and after an upcall is received, we need to check whether .Dq measured_bw != expected_bw . .It The bandwidth-upcall mechanism is enabled by .Fn setsockopt MRT_API_CONFIG for the .Dv MRT_MFC_BW_UPCALL flag. .It The bandwidth-upcall filters are added/deleted by the new .Fn setsockopt MRT_ADD_BW_UPCALL and .Fn setsockopt MRT_DEL_BW_UPCALL respectively (with the appropriate .Vt "struct bw_upcall" argument of course). .El .Pp From application point of view, a developer needs to know about the following: .Bd -literal /* * Structure for installing or delivering an upcall if the * measured bandwidth is above or below a threshold. * * User programs (e.g. daemons) may have a need to know when the * bandwidth used by some data flow is above or below some threshold. * This interface allows the userland to specify the threshold (in * bytes and/or packets) and the measurement interval. Flows are * all packet with the same source and destination IP address. * At the moment the code is only used for multicast destinations * but there is nothing that prevents its use for unicast. * * The measurement interval cannot be shorter than some Tmin (currently, 3s). * The threshold is set in packets and/or bytes per_interval. * * Measurement works as follows: * * For >= measurements: * The first packet marks the start of a measurement interval. * During an interval we count packets and bytes, and when we * pass the threshold we deliver an upcall and we are done. * The first packet after the end of the interval resets the * count and restarts the measurement. * * For <= measurement: * We start a timer to fire at the end of the interval, and * then for each incoming packet we count packets and bytes. * When the timer fires, we compare the value with the threshold, * schedule an upcall if we are below, and restart the measurement * (reschedule timer and zero counters). */ struct bw_data { struct timeval b_time; uint64_t b_packets; uint64_t b_bytes; }; struct bw_upcall { struct in_addr bu_src; /* source address */ struct in_addr bu_dst; /* destination address */ uint32_t bu_flags; /* misc flags (see below) */ #define BW_UPCALL_UNIT_PACKETS (1 << 0) /* threshold (in packets) */ #define BW_UPCALL_UNIT_BYTES (1 << 1) /* threshold (in bytes) */ #define BW_UPCALL_GEQ (1 << 2) /* upcall if bw >= threshold */ #define BW_UPCALL_LEQ (1 << 3) /* upcall if bw <= threshold */ #define BW_UPCALL_DELETE_ALL (1 << 4) /* delete all upcalls for s,d*/ struct bw_data bu_threshold; /* the bw threshold */ struct bw_data bu_measured; /* the measured bw */ }; /* max. number of upcalls to deliver together */ #define BW_UPCALLS_MAX 128 /* min. threshold time interval for bandwidth measurement */ #define BW_UPCALL_THRESHOLD_INTERVAL_MIN_SEC 3 #define BW_UPCALL_THRESHOLD_INTERVAL_MIN_USEC 0 .Ed .Pp The .Vt bw_upcall structure is used as an argument to .Fn setsockopt MRT_ADD_BW_UPCALL and .Fn setsockopt MRT_DEL_BW_UPCALL . Each .Fn setsockopt MRT_ADD_BW_UPCALL installs a filter in the kernel for the source and destination address in the .Vt bw_upcall argument, and that filter will trigger an upcall according to the following pseudo-algorithm: .Bd -literal if (bw_upcall_oper IS ">=") { if (((bw_upcall_unit & PACKETS == PACKETS) && (measured_packets >= threshold_packets)) || ((bw_upcall_unit & BYTES == BYTES) && (measured_bytes >= threshold_bytes))) SEND_UPCALL("measured bandwidth is >= threshold"); } if (bw_upcall_oper IS "<=" && measured_interval >= threshold_interval) { if (((bw_upcall_unit & PACKETS == PACKETS) && (measured_packets <= threshold_packets)) || ((bw_upcall_unit & BYTES == BYTES) && (measured_bytes <= threshold_bytes))) SEND_UPCALL("measured bandwidth is <= threshold"); } .Ed .Pp In the same .Vt bw_upcall the unit can be specified in both BYTES and PACKETS. However, the GEQ and LEQ flags are mutually exclusive. .Pp Basically, an upcall is delivered if the measured bandwidth is >= or <= the threshold bandwidth (within the specified measurement interval). For practical reasons, the smallest value for the measurement interval is 3 seconds. If smaller values are allowed, then the bandwidth estimation may be less accurate, or the potentially very high frequency of the generated upcalls may introduce too much overhead. For the >= operation, the answer may be known before the end of .Va threshold_interval , therefore the upcall may be delivered earlier. For the <= operation however, we must wait until the threshold interval has expired to know the answer. .Pp Example of usage: .Bd -literal struct bw_upcall bw_upcall; /* Assign all bw_upcall fields as appropriate */ memset(&bw_upcall, 0, sizeof(bw_upcall)); memcpy(&bw_upcall.bu_src, &source, sizeof(bw_upcall.bu_src)); memcpy(&bw_upcall.bu_dst, &group, sizeof(bw_upcall.bu_dst)); bw_upcall.bu_threshold.b_data = threshold_interval; bw_upcall.bu_threshold.b_packets = threshold_packets; bw_upcall.bu_threshold.b_bytes = threshold_bytes; if (is_threshold_in_packets) bw_upcall.bu_flags |= BW_UPCALL_UNIT_PACKETS; if (is_threshold_in_bytes) bw_upcall.bu_flags |= BW_UPCALL_UNIT_BYTES; do { if (is_geq_upcall) { bw_upcall.bu_flags |= BW_UPCALL_GEQ; break; } if (is_leq_upcall) { bw_upcall.bu_flags |= BW_UPCALL_LEQ; break; } return (ERROR); } while (0); setsockopt(mrouter_s4, IPPROTO_IP, MRT_ADD_BW_UPCALL, (void *)&bw_upcall, sizeof(bw_upcall)); .Ed .Pp To delete a single filter, then use .Dv MRT_DEL_BW_UPCALL , and the fields of bw_upcall must be set exactly same as when .Dv MRT_ADD_BW_UPCALL was called. .Pp To delete all bandwidth filters for a given (S,G), then only the .Va bu_src and .Va bu_dst fields in .Vt "struct bw_upcall" need to be set, and then just set only the .Dv BW_UPCALL_DELETE_ALL flag inside field .Va bw_upcall.bu_flags . .Pp The bandwidth upcalls are received by aggregating them in the new upcall message: .Bd -literal #define IGMPMSG_BW_UPCALL 4 /* BW monitoring upcall */ .Ed .Pp This message is an array of .Vt "struct bw_upcall" elements (up to .Dv BW_UPCALLS_MAX = 128). The upcalls are delivered when there are 128 pending upcalls, or when 1 second has expired since the previous upcall (whichever comes first). In an .Vt "struct upcall" element, the .Va bu_measured field is filled-in to indicate the particular measured values. However, because of the way the particular intervals are measured, the user should be careful how .Va bu_measured.b_time is used. For example, if the filter is installed to trigger an upcall if the number of packets is >= 1, then .Va bu_measured may have a value of zero in the upcalls after the first one, because the measured interval for >= filters is .Dq clocked by the forwarded packets. Hence, this upcall mechanism should not be used for measuring the exact value of the bandwidth of the forwarded data. To measure the exact bandwidth, the user would need to get the forwarded packets statistics with the .Fn ioctl SIOCGETSGCNT mechanism (see the .Sx Programming Guide section) . .Pp Note that the upcalls for a filter are delivered until the specific filter is deleted, but no more frequently than once per .Va bu_threshold.b_time . For example, if the filter is specified to deliver a signal if bw >= 1 packet, the first packet will trigger a signal, but the next upcall will be triggered no earlier than .Va bu_threshold.b_time after the previous upcall. .\" .Sh SEE ALSO -.Xr altq 4 , -.Xr dummynet 4 , .Xr getsockopt 2 , -.Xr gif 4 , -.Xr gre 4 , .Xr recvfrom 2 , .Xr recvmsg 2 , .Xr setsockopt 2 , .Xr socket 2 , .Xr sourcefilter 3 , +.Xr altq 4 , +.Xr dummynet 4 , +.Xr gif 4 , +.Xr gre 4 , .Xr icmp6 4 , .Xr igmp 4 , .Xr inet 4 , .Xr inet6 4 , .Xr intro 4 , .Xr ip 4 , .Xr ip6 4 , .Xr mld 4 , .Xr pim 4 .\" .Sh HISTORY The Distance Vector Multicast Routing Protocol (DVMRP) was the first developed multicast routing protocol. Later, other protocols such as Multicast Extensions to OSPF (MOSPF) and Core Based Trees (CBT), were developed as well. Routers at autonomous system boundaries may now exchange multicast routes with peers via the Border Gateway Protocol (BGP). Many other routing protocols are able to redistribute multicast routes for use with .Dv PIM-SM and .Dv PIM-DM . .Sh AUTHORS .An -nosplit The original multicast code was written by .An David Waitzman (BBN Labs), and later modified by the following individuals: .An Steve Deering (Stanford), .An Mark J. Steiglitz (Stanford), .An Van Jacobson (LBL), .An Ajit Thyagarajan (PARC), .An Bill Fenner (PARC). The IPv6 multicast support was implemented by the KAME project .Pq Pa http://www.kame.net , and was based on the IPv4 multicast code. The advanced multicast API and the multicast bandwidth monitoring were implemented by .An Pavlin Radoslavov (ICSI) in collaboration with .An Chris Brown (NextHop). The IGMPv3 and MLDv2 multicast support was implemented by .An Bruce Simpson . .Pp This manual page was written by .An Pavlin Radoslavov (ICSI). Index: projects/sendfile/share/man/man4/net80211.4 =================================================================== --- projects/sendfile/share/man/man4/net80211.4 (revision 276056) +++ projects/sendfile/share/man/man4/net80211.4 (revision 276057) @@ -1,1318 +1,1318 @@ .\"- .\" Copyright (c) 2009 Sam Leffler, Errno Consulting .\" 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, .\" without modification. .\" 2. Redistributions in binary form must reproduce at minimum a disclaimer .\" similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any .\" redistribution must be conditioned upon including a substantially .\" similar Disclaimer requirement for further binary redistribution. .\" .\" NO WARRANTY .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT .\" LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY .\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL .\" THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. .\" .\" $FreeBSD$ .\" .Dd July 10, 2009 .Dt NET80211 4 .Os .Sh NAME .Nm net80211 .Nd standard interface to IEEE 802.11 devices .Sh SYNOPSIS .In sys/types.h .In sys/socket.h .In net/if.h .In net/ethernet.h .In net80211/ieee80211_ioctl.h .Sh DESCRIPTION This section describes the standard programming interface to configure and retrieve status information for IEEE 802.11 devices that depend on the .Xr wlan 4 module for operation. The interface is via one of the following .Xr ioctl 2 calls on a socket: .Bl -tag -width ".Dv SIOCG80211" .It Dv SIOCG80211 Get configuration or status information. .It Dv SIOCS80211 Set configuration information. .El .Pp These requests are made via a modified .Vt ifreq structure. This structure is defined as follows: .Bd -literal struct ieee80211req { char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ uint16_t i_type; /* req type */ int16_t i_val; /* Index or simple value */ int16_t i_len; /* Index or simple value */ void *i_data; /* Extra data */ }; .Ed .Pp Requests that are not supported by the underlying device return -1 and set the global variable errno to .Er EOPNOTSUPP . .Dv SIOCG80211 requests that return data to an application place small values in .Va i_val or in a user-specified buffer pointed to by .Va i_data . When an indirect buffer is used .Va i_len specifies how large the indirect buffer is and on return it is set by the system to the actual amount of data returned. .Dv SIOCS80211 requests use a similar scheme with data passed to the system taken either from .Va i_val or an indirect buffer pointed to by .Va i_data . .Pp For .Dv SIOCG80211 the following values of .Va i_type are valid: .Bl -tag -width indent .It Dv IEEE80211_IOC_AMPDU Return whether or not AMPDU is enabled in .Va i_val . AMPDU is an aggregation scheme that is part of the 802.11n specification and is used only when operating on an HT channel. The value returned is one of: 0 (AMPDU disabled), 1 (AMPDU enabled for transmit), 2 (AMPDU enabled for receive), and 3 (AMPDU enabled for transmit and receive). The 802.11n specification says a compliant station must receive AMPDU but may not support transmitting AMPDU frames. Disabling AMPDU receive is mainly useful for testing and working around bugs. .It Dv IEEE80211_IOC_AMPDU_DENSITY Return the minimum density for bursting AMPDU frames in .Va i_val . The value returned is one of: 0 (no time restriction), 1 (1/4 usec), 2 (1/2 usec), 3 (1 usec), 4 (2 usec), 5 (4 usec), 6 (8 usec), and 7 (16 usec). .It Dv IEEE80211_IOC_AMPDU_LIMIT Return the limit on the size of AMPDU frames in .Va i_val . The value returned is one of: 0 (8 kilobytes), 1 (16 kilobytes), 2 (32 kilobytes), and 3 (64 kilobytes). .It Dv IEEE80211_IOC_AMSDU Return whether or not AMSDU is enabled in .Va i_val . AMSDU is an aggregation scheme that is part of the 802.11n specification and is used only when operating on an HT channel. The value returned is one of: 0 (AMSDU disabled), 1 (AMSDU enabled for transmit), 2 (AMSDU enabled for receive), and 3 (AMSDU enabled for transmit and receive). The 802.11n specification says a compliant station must receive AMSDU but may not support transmitting AMSDU frames. Disabling AMSDU receive is mainly useful for testing and working around bugs. .It Dv IEEE80211_IOC_AMSDU_LIMIT Return the limit on the size of AMSDU frames in .Va i_val . The value returned is one of: 3839 (bytes) and 7935 (bytes). Note these values are specified by 802.11n; arbitrary values are not allowed. .It Dv IEEE80211_IOC_APBRIDGE Return whether AP bridging is enabled in .Va i_val . Normally packets sent between stations associated to the same access point are delivered without going through system layers that do packet filtering; when AP bridging is disabled packets are passed up the system to be forwarded using some other mechanism. This value will be non-zero when AP bridging is enabled and otherwise zero. .It Dv IEEE80211_IOC_APPIE Return an application information element via .Va i_data . Application IE's are maintained for many 802.11 frames; the request must identify the frame to return an IE for in .Va i_val . For example, to retrieve the IE sent in each Beacon frame .Va i_val would be set to .Va IEEE80211_FC0_SUBTYPE_BEACON | IEEE80211_FC0_TYPE_MGT . If no information element is installed then .Er EINVAL is returned. If the data buffer for returning data is too small to hold the information element the value is truncated; this permits querying the presence of data by requesting zero bytes of data be returned. .It Dv IEEE80211_IOC_AUTHMODE Return the current authentication mode in .Va i_val . Valid values are .Dv IEEE80211_AUTH_NONE (no authentication), .Dv IEEE80211_AUTH_OPEN (open authentication), .Dv IEEE80211_AUTH_SHARED (shared key authentication), .Dv IEEE80211_AUTH_8021X (802.1x only authentication), and .Dv IEEE80211_AUTH_WPA (WPA/802.11i/802.1x authentication). .It Dv IEEE80211_IOC_BEACON_INTERVAL Return the time between Beacon frames (in TU) in .Va i_val . .It Dv IEEE80211_IOC_BGSCAN Return whether background scanning is enabled in .Va i_val . When this value is non-zero and operating in station mode the station will periodically leave the current channel and scan for neighboring stations. See also .Dv IEEE80211_IOC_BGSCAN_IDLE and .Dv IEEE80211_IOC_BGSCAN_INTERVAL . .It Dv IEEE80211_IOC_BGSCAN_IDLE Return in .Va i_val the minimum time (msecs) a station must be idle (i.e. not transmitting or receiving frames) before it will do a background scan. See also .Dv IEEE80211_IOC_BGSCAN_INTERVAL . .It Dv IEEE80211_IOC_BGSCAN_INTERVAL Return in .Va i_val the minimum time (seconds) between background scan operations. See also .Dv IEEE80211_IOC_BGSCAN_IDLE . .It Dv IEEE80211_IOC_BMISSTHRESHOLD Return in .Va i_val the number of consecutive missed Beacon frames before the system will attempt to roam to a different/better access point. .It Dv IEEE80211_IOC_BSSID Return the MAC address for the current BSS identifier via .Va i_data . When the interface is running, the bssid is either the value configured locally (e.g. for an IBSS network started by the local station) or the value adopted when joining an existing network. For WDS interfaces this value is the address of the remote station. When the interface is not running, the bssid returned is the desired bssid, if any, that has been configured. .It Dv IEEE80211_IOC_BURST Return whether or not packet bursting is enabled in .Va i_val . If this value is non-zero then the system will try to send packets closely spaced to improve throughput. .It Dv IEEE80211_IOC_CHANINFO Return the set of available channels via .Va i_data . Note this data should be used by user applications to map between channel specifications (frequency and attributes) and IEEE channel numbers as user applications may not have the necessary information to do this directly (e.g. for 900MHz radios, operation in the Public Safety Band). .It Dv IEEE80211_IOC_CHANLIST Return the current list of usable channels via .Va i_data . The channel list is returned as a bit vector with bit N set to 1 if IEEE channel number N is available for use. .It Dv IEEE80211_IOC_CHANNEL Return the IEEE channel number of the current channel in .Va i_val . Note this request is deprecated; use .Dv IEEE80211_IOC_CURCHAN instead. .It Dv IEEE80211_IOC_COUNTERMEASURES Return whether TKIP Countermeasures are enabled in .Va i_val . This value will be non-zero when Countermeasures are enabled and otherwise zero. .It Dv IEEE80211_IOC_CURCHAN Return information for the current channel via .Va i_data . This information includes the IEEE channel number, the frequency, and attributes that describe the operating constraints (e.g. Passive Scan, DFS, usage restrictions). .It Dv IEEE80211_IOC_DEVCAPS Return device capabilities in the data buffer pointed at by .Va i_data . The buffer must be large enough to return the number of available channels but otherwise may be made small to limit how much information is returned. .It Dv IEEE80211_IOC_DFS Return whether or not Dynamic Frequency Selection (DFS) is enabled in .Va i_val . DFS embodies several facilities including detection of overlapping radar signals, dynamic transmit power control, and channel selection according to a least-congested criteria. DFS support is mandatory for some 5GHz frequencies in certain locales (e.g. ETSI). By default DFS is enabled according to the regulatory definitions and the current country code, regdomain, and channel. .It Dv IEEE80211_IOC_DOTD Return whether or not 802.11d support is enabled in .Va i_val . When 802.11d is enabled in station mode, Beacon frames that advertise a country code different than the currently configured country code will cause an event to be dispatched to user applications. This event can be used by the station to adopt that country code and operate according to the associated regulatory constraints. When operating as an access point with 802.11d enabled the Beacon and ProbeResponse frames transmitted will advertise the current regulatory domain settings. .It Dv IEEE80211_IOC_DOTH Return whether 802.11h support is enabled in .Va i_val . When 802.11h is enabled Beacon and ProbeResponse frames will have the SpectrumMgt bit set in the capabilities field and country and power constraint information elements will be present. 802.11h support also includes handling Channel Switch Announcements (CSA) which are a mechanism to coordinate channel changes by an access point. By default 802.11h is enabled if the device is capable. .It Dv IEEE80211_IOC_DROPUNENCRYPTED Return, in .Va i_val , whether unencrypted packets transmit/received should be discarded. This value will be zero if unencrypted packets will be accepted and non-zero if they are to be discarded. .It Dv IEEE80211_IOC_DTIM_PERIOD Return the period (in beacon intervals) between DTIM events in .Va i_val . .It Dv IEEE80211_IOC_DWDS Return, in .Va i_val , whether or not Dynamic WDS support is enabled. Dynamic WDS is a facility by which packets may be tunneled over normal Infrastructure BSS associations using 4-address (WDS) frames. .It Dv IEEE80211_IOC_FF Return, in .Va i_val , whether Atheros fast-frames support is enabled. Fast-frames is a non-standard protocol extension that aggregates multiple frames to improve throughput. Note that enabling fast-frames support does not guarantee use; the client and access point must negotiate its use. .It Dv IEEE80211_IOC_FRAGTHRESHOLD Return, in .Va i_val , the threshold (in bytes) for enabling fragmentation frames. Packets larger than this value will automatically be split into multiple fragmented frames that are sent one after the other. .It Dv IEEE80211_IOC_GREENFIELD Return, in .Va i_val , whether or not Greenfield preamble use is enabled. This setting is meaningful only when operating with 802.11n on an HT channel. .It Dv IEEE80211_IOC_HIDESSID Return, in .Va i_val , whether SSID hiding/cloaking is enabled. SSID hiding is only meaningful when operating as an access point. When this is enabled Beacon frames do not include the SSID and ProbeRequest frames are not answered unless they include the AP's SSID. This value will be non-zero when SSID hiding is enabled and otherwise zero. .It Dv IEEE80211_IOC_HTCOMPAT Return, in .Va i_val , whether or not 802.11n compatibility support is enabled. The 802.11n protocol specification went through several incompatible iterations. Some vendors implemented 11n support to older specifications that will not interoperate with a purely 11n-compliant station. In particular the information elements included in management frames for old devices are different. When compatibility support is enabled both standard and compatible data will be provided and/or accepted. .It Dv IEEE80211_IOC_HTCONF Return the setting for automatic promotion of HT channels in .Va i_val . Promotion happens when the system must select a channel and may choose between legacy, HT20, and HT40 operation (e.g. when scanning). Valid values are: 0 (do not promote, use legacy), 1 (promote to HT20), and 2 (promote to HT40). .It Dv IEEE80211_IOC_HTPROTMODE Return, in .Va i_val , the technique used to protect HT frames in a mixed 802.11n network. Valid values are: .Dv IEEE80211_PROTMODE_OFF (no protection enabled) and .Dv IEEE80211_PROTMODE_RTSCTS (send RTS and wait for CTS). .It Dv IEEE80211_IOC_HWMP_MAXHOPS Return the maximum acceptable hop count in an HWMP path in .Va i_val . .It Dv IEEE80211_IOC_HWMP_ROOTMODE Return the setting for Mesh root mode operation in .Va i_val . Valid values are: .Dv IEEE80211_HWMP_ROOTMODE_DISABLED (root mode is disabled), .Dv IEEE80211_HWMP_ROOTMODE_NORMAL (send broadcast Path Request frames), .Dv IEEE80211_HWMP_ROOTMODE_PROACTIVE (send broadcast Path Request frames and force replies) and .Dv IEEE80211_HWMP_ROOTMODE_RANN (send broadcast Root Announcement (RANN) frames). .It Dv IEEE80211_IOC_INACTIVITY Return whether or not the system handles inactivity processing in .Va i_val . When inactivity processing is enabled the system will track stations that have not transmitted frames and periodically probe them to check if they are still present. Stations that are inactive and do not respond to probes are dropped. .It Dv IEEE80211_IOC_MACCMD Return information about the state of the MAC address access control list (ACL) system. There are two requests supported: .Dv IEEE80211_MACCMD_POLICY (to retrieve the current policy in .Va i_val ), and .Dv IEEE80211_MACCMD_LIST to retrieve the list installed/active ACL's via .Va i_data . The .Xr wlan_acl 4 module must be installed and enabled or .Er EINVAL will be returned. .It Dv IEEE80211_IOC_MESH_AP Return whether or not Mesh AP support is enabled in .Va i_val . .It Dv IEEE80211_IOC_MESH_ID Return the Mesh ID in the buffer pointed to by .Va i_data . .It Dv IEEE80211_IOC_MESH_FWRD Return whether or not packet forwarding support is enabled in .Va i_val . .It Dv IEEE80211_IOC_MESH_PP_METRIC Return the link metric protocol in the buffer pointed to by .Va i_data . .It Dv IEEE80211_IOC_MESH_PP_PATH Return the path selection protocol in the buffer pointed to by .Va i_data . .It Dv IEEE80211_IOC_MESH_RTCMD Return information about the state of the Mesh routing tables. One request is supported: .Dv IEEE80211_MESH_RTCMD_LIST to retrieve the contents of the routing table in the buffer pointed to by .Va i_data . .It Dv IEEE80211_IOC_MESH_TTL Return, in .Va i_val , the Mesh Time To Live (TTL) setting installed in packets transmitted by this mesh node. .It Dv IEEE80211_IOC_NUMSSIDS Return the number of SSIDs supported in .Va i_val . .It Dv IEEE80211_IOC_NUMWEPKEYS Return the number of WEP keys supported in .Va i_val . .It Dv IEEE80211_IOC_POWERSAVE Return the current powersaving mode in .Va i_val . Valid values are .Dv IEEE80211_POWERSAVE_OFF (power save operation is disabled) and .Dv IEEE80211_POWERSAVE_ON (power save operation is enabled). .It Dv IEEE80211_IOC_POWERSAVESLEEP Return the powersave sleep time in TU in .Va i_val . This value is also termed the listen interval and represents the maximum time a station will sleep before waking to retrieve packets buffered by an access point. .It Dv IEEE80211_IOC_PRIVACY Return the current MLME setting for PRIVACY in .Va i_val . When PRIVACY is enabled all data packets must be encrypted. This value will be zero if PRIVACY is disabled and non-zero when PRIVACY is enabled. .It Dv IEEE80211_IOC_PROTMODE Return the current 802.11g protection mode in .Va i_val . Protection is the mechanism used to safeguard 802.11b stations operating on an 802.11g network. Valid values are .Dv IEEE80211_PROTMODE_OFF (no protection enabled), .Dv IEEE80211_PROTMODE_CTS (send CTS to yourself), and .Dv IEEE80211_PROTMODE_RTSCTS (send RTS and wait for CTS). .It Dv IEEE80211_IOC_PUREG Return whether ``pure 11g'' mode is enabled in .Va i_val . This setting is meaningful only for access point operation; when non-zero, 802.11b stations will not be allowed to associate. .It Dv IEEE80211_IOC_PUREN Return whether ``pure 11n'' mode is enabled in .Va i_val . This setting is meaningful only for access point operation; when non-zero, legacy (non-11n capable) stations will not be allowed to associate. .It Dv IEEE80211_IOC_REGDOMAIN Return the regulatory state in the buffer pointed to by .Va i_data . .It Dv IEEE80211_IOC_RIFS Return whether or not Reduced InterFrame Spacing (RIFS) is enabled in .Va i_val . This setting is meaningful only when operating with 802.11n on an HT channel. .It Dv IEEE80211_IOC_ROAM Return station roaming parameters in the buffer pointed to by .Va i_data . .It Dv IEEE80211_IOC_ROAMING Return the current roaming mode in .Va i_val . Roaming mode specifies which entity controls operation of the MLME state machine when operating as a station in an Infrastructure BSS. Valid values are: .Dv IEEE80211_ROAMING_DEVICE (driver/firmware is in control), .Dv IEEE80211_ROAMING_AUTO (host 802.11 layer is in control), and .Dv IEEE80211_ROAMING_MANUAL (application is in control). .It Dv IEEE80211_IOC_RTSTHRESHOLD Return the threshold (in bytes) for enabling transmission of RTS frames in .Va i_val . Packets larger than this value will automatically have an RTS frame sent preceding it to reduce the likelihood of packet loss. .It Dv IEEE80211_IOC_SCAN_RESULTS Return the current contents of the scan cache in the data area pointed to by .Va i_data . .It Dv IEEE80211_IOC_SCANVALID Return in .Va i_val how long (in seconds) results from a scan operation will be considered valid. When scan results are no longer valid and they are needed (e.g. to roam) the system will initiate a scan operation to replenish the scan cache. .It Dv IEEE80211_IOC_SHORTGI Return whether or not Short Guard Interval (SGI) is enabled in .Va i_val . Note SGI is only used when operating with 802.11n on an HT channel. .It Dv IEEE80211_IOC_SMPS Return the Spatial Multiplexing Power Save (SMPS) setting in .Va i_val . This setting is meaningful only when operating with 802.11n on an HT channel. Valid values are: .Dv IEEE80211_HTCAP_SMPS_DYNAMIC (Dynamic SMPS is enabled), .Dv IEEE80211_HTCAP_SMPS_ENA (Static SMPS is enabled), and .Dv IEEE80211_HTCAP_SMPS_OFF (SMPS is disabled). .It Dv IEEE80211_IOC_SSID Return the requested SSID in the buffer pointed to by .Va i_data . If .Va i_val is \(>= 0 then the request refers to the configured value for that slot. Generally, 0 is the only valid value, but some interfaces support more SSIDs. .It Dv IEEE80211_IOC_STA_INFO Return information about the current state of the specified station(s) via .Va i_data . The MAC address of a single station may be passed in or, if the broadcast address is supplied, information about all stations will be returned. If a single station is requested and the MAC address is unknown then .Er ENOENT will be returned. .It Dv IEEE80211_IOC_STA_STATS Return collected statistics for the specified station via .Va i_data . The MAC address of the desired station is passed in; if it is unknown .Er ENOENT will be returned. .It Dv IEEE80211_IOC_STA_VLAN Return any VLAN tag assigned to a station via .Va i_data . .It Dv IEEE80211_IOC_TDMA_SLOT Return the slot number for the station in .Va i_val . Slot number zero is the master station in a TDMA network. .It Dv IEEE80211_IOC_TDMA_SLOTCNT Return the count of slots in the TDMA network in .Va i_val . .It Dv IEEE80211_IOC_TDMA_SLOTLEN Return the length (in usecs) of the TDMA slot assigned to each station in the network in .Va i_val . .It Dv IEEE80211_IOC_TDMA_BINTERVAL Return the number of superframes between Beacon frames in .Va i_val . A TDMA network with N slots and slot length T has a superframe of NxT. .It Dv IEEE80211_IOC_TSN Return whether or not Transitional Security Network (TSN) is enabled in .Va i_val . .It Dv IEEE80211_IOC_TURBOP Return whether Atheros Dynamic Turbo mode is enabled in .Va i_val . Dynamic Turbo mode is a non-standard protocol extension available only on Atheros devices where channel width is dynamically changed between 20MHz and 40MHz. Note that enabling Dynamic Turbo mode support does not guarantee use; both client and access point must use Atheros devices and support must be enabled on both sides. .It Dv IEEE80211_IOC_TXPARAMS Return transmit parameters in the buffer pointed to by .Va i_data . .It Dv IEEE80211_IOC_TXPOWER Return the transmit power limit in .5 dBm units in .Va i_val . This value represents the effective maximum and is calculated according to the maximum power allowed by local regulations, any user-specified power limit, and the maximum power the device is capable of. .It Dv IEEE80211_IOC_TXPOWMAX Return the user-specified maximum transmit power in .5 dBm units in .Va i_val . The maximum setting is applied after any regulatory cap. .It Dv IEEE80211_IOC_WEP Return the current WEP status in .Va i_val . Valid values are: .Dv IEEE80211_WEP_ON (enabled for all packets sent and received), .Dv IEEE80211_WEP_OFF (disabled), and .Dv IEEE80211_WEP_MIXED (enabled for transmit and receive but also willing to receive unencrypted frames). This request is deprecated; use .Dv IEEE80211_IOC_PRIVACY and .Dv IEEE80211_IOC_UNENCRYPTED instead. .It Dv IEEE80211_IOC_WEPKEY Return the requested WEP key via .Va i_data . The key number is specified in .Va i_val and may be 0-3. If the device does not support returning the WEP key or the user is not root then the key may be returned as all zeros. This request is deprecated in favor of .Dv IEEE80211_IOC_WPAKEY . .It Dv IEEE80211_IOC_WEPTXKEY Return the number of the WEP key used for transmission in .Va i_val . .It Dv IEEE80211_IOC_WME Return whether 802.11e/WME/WMM support is enabled in .Va i_val . This value will be non-zero when support is enabled and otherwise zero. .It Dv IEEE80211_IOC_WME_CWMIN Return the WME CWmin setting (log2) for the specified Access Class (AC) in .Va i_val . The AC is passed in through .Va i_len together with an optional IEEE80211_WMEPARAM_BSS flag to indicate if the parameter for the BSS or the channel is desired. If WME is not supported then .Er EINVAL will be returned. .It Dv IEEE80211_IOC_WME_CWMAX Return the WME CWmax setting (log2) for the specified Access Class (AC) in .Va i_val . See .Dv IEEE80211_IOC_WME_CWMIN above for more details. .It Dv IEEE80211_IOC_WME_AIFS Return the WME AIFS setting for the specified Access Class (AC) in .Va i_val . See .Dv IEEE80211_IOC_WME_CWMIN above for more details. .It Dv IEEE80211_IOC_WME_TXOPLIMIT Return the WME TxOpLimit (msec) for the specified Access Class (AC) in .Va i_val . See .Dv IEEE80211_IOC_WME_CWMIN above for more details. .It Dv IEEE80211_IOC_WME_ACM Return the WME Admission Control Mechanism (ACM) setting for the specified Access Class (AC) in .Va i_val . This value is meaningful only for the BSS (not channel). See .Dv IEEE80211_IOC_WME_CWMIN above for more details. .It Dv IEEE80211_IOC_WME_ACKPOLICY Return the WME ACK Policy setting for the specified Access Class (AC) in .Va i_val . When this value is zero frames will be transmitted without waiting for an Acknowledgement. This value is meaningful only for the channel (not BSS). See .Dv IEEE80211_IOC_WME_CWMIN above for more details. .It Dv IEEE80211_IOC_WPA Return the WPA configuration in .Va i_val . Valid values are 0 (WPA is not enabled), 1 (WPA1 is enabled), 2 (WPA2/802.11i is enabled), and 3 (WPA1 and WPA2/802.11i are both enabled). .It Dv IEEE80211_IOC_WPAIE Return any WPA information element for an associated station via .Va i_data . The request passed in through .Va i_data identifies the MAC address of the desired station. If an RSN (802.11i) element is present it is returned; otherwise any WPA element is returned. Note this request is deprecated; use .Dv IEEE80211_IOC_WPAIE2 instead. .It Dv IEEE80211_IOC_WPAIE2 Return any WPA information elements for an associated station via .Va i_data . The request passed in through .Va i_data identifies the MAC address of the desired station. One or both of RSN (802.11i) and WPA elements may be returned. .It Dv IEEE80211_IOC_WPAKEY Return the requested cryptographic key in the buffer pointed to by .Va i_data . The key number is specified in .Va i_val and may be 0-3. A key number of zero is used to retrieve a station's unicast cipher key when operating with WPA enabled. If the user is not root then the key data returned is all zeros. .It Dv IEEE80211_IOC_WPS Return whether or not Wi-FI Protected Setup (WPS) is enabled in .Va i_val . .El .Pp For .Dv SIOCS80211 the following values of .Va i_type are valid. Note that changing a value on an interface that is running may cause the interface to be .Sq reset . Resets may be handled without altering the state if the parameter does not affect the MLME state (e.g. RTS threshold), but in some cases the interface may need to scan for a new network or clear state (including any associated stations); in that case the interface is said to be .Sq restarted (it is equivalent to marking the interface down and back up). The information below identifies whether changing a value affects the state of a running interface. .Bl -tag -width indent .It Dv IEEE80211_IOC_ADDMAC Add an entry to the MAC address Access Control List (ACL) database using the value pointed to by .Va i_data . The .Xr wlan_acl 4 module must be installed and enabled or .Er EINVAL will be returned. .It Dv IEEE80211_IOC_AMPDU Set whether or not AMPDU is enabled for transmit and/or receive using the value in .Va i_val . This request causes a running interface operating on an HT channel to be reset. See .Dv IEEE80211_IOC_AMPDU above for details. .It Dv IEEE80211_IOC_AMPDU_DENSITY Set the minimum density for bursting AMPDU frames to the value in .Va i_val . This request causes a running interface to be reset. See .Dv IEEE80211_IOC_AMPDU_DENSITY above for details. .It Dv IEEE80211_IOC_AMPDU_LIMIT Set the limit on the size of AMPDU frames to the value in .Va i_val . This request causes a running interface to be reset. See .Dv IEEE80211_IOC_AMPDU_LIMIT above for details. .It Dv IEEE80211_IOC_AMSDU Set whether or not AMSDU is enabled for transmit and/or receive using the value in .Va i_val . This request causes a running interface operating on an HT channel to be reset. See .Dv IEEE80211_IOC_AMSDU above for details. .It Dv IEEE80211_IOC_AMSDU_LIMIT Set the limit on the size of AMSDU frames to the value in .Va i_val . This request causes a running interface to be reset. See .Dv IEEE80211_IOC_AMSDU_LIMIT above for details. .It Dv IEEE80211_IOC_APBRIDGE Set whether AP bridging is enabled using the value in .Va i_val . See .Dv IEEE80211_IOC_APBRIDGE above for details. .It Dv IEEE80211_IOC_APPIE Set an application information element using the data pointed to by .Va i_data . This request causes a running interface to be restarted if the WPA information element is changed. See .Dv IEEE80211_IOC_APPIE above for details. .It Dv IEEE80211_IOC_AUTHMODE Set the current authentication mode using the value in .Va i_val . This request causes a running interface to be restarted. See .Dv IEEE80211_IOC_AUTHMODE above for details. This request causes a running interface to be restarted. .It Dv IEEE80211_IOC_BEACON_INTERVAL Set the time between Beacon frames (in TU) to the value in .Va i_val . This request causes a running interface to be restarted. .It Dv IEEE80211_IOC_BGSCAN Set whether background scanning is enabled using the value in .Va i_val . .It Dv IEEE80211_IOC_BGSCAN_IDLE Set the minimum time (in msecs) a station must be idle before it will do a background scan to the value in .Va i_val . .It Dv IEEE80211_IOC_BGSCAN_INTERVAL Set the minimum time (seconds) between background scan operations to the value in .Va i_val . .It Dv IEEE80211_IOC_BMISSTHRESHOLD Set the number of consecutive missed Beacon frames before the system will attempt to roam to the value in .Va i_val . This request causes a running interface to be reset. .It Dv IEEE80211_IOC_BSSID Set the 802.11 MAC address for the desired BSS identifier according to .Va i_data . This request causes a running interface to be restarted. .It Dv IEEE80211_IOC_BURST Set whether or not packet bursting is enabled using the value in .Va i_val . This request causes a running interface to be reset. .It Dv IEEE80211_IOC_CHANNEL Set the desired/current channel to the value given by .Va i_val . This request causes a running interface to immediately change to the specified channel if possible; otherwise the interface will be restarted. Note this request is deprecated; use .Dv IEEE80211_IOC_CURCHAN instead. .It Dv IEEE80211_IOC_CHANLIST Set the list of available channels using the channel list pointed to by .Va i_data . The channel list is a bit vector with bit N set to 1 if IEEE channel number N is available for use. The specified channel list is checked against the set of supported channels and any channels not supported are silently ignored. If the intersection of the channel list and the supported channels is empty .Er EINVAL is returned. Note the current channel may be marked invalid after installing a new channel list. This request causes a running interface to be restarted. .It Dv IEEE80211_IOC_COUNTERMEASURES Set whether TKIP Countermeasures are enabled using the value in .Va i_val . This request can only be used when the authentication mode is set WPA; otherwise .Er EOPNOTSUPP will be returned. .It Dv IEEE80211_IOC_CURCHAN Set the current channel using the information referenced by .Va i_data . This request causes a running interface to immediately change to the specified channel if possible; otherwise the interface will be restarted. .It Dv IEEE80211_IOC_DELKEY Delete the key specified by the information referenced by .Va i_data . .It Dv IEEE80211_IOC_DELMAC Remove an entry in the MAC address Access Control List (ACL) database using the value pointed to by .Va i_data . The .Xr wlan_acl 4 module must be installed and enabled or .Er EINVAL will be returned. .It Dv IEEE80211_IOC_DFS Set whether or not Dynamic Frequency Selection (DFS) is enabled using the value in .Va i_val . This request will fail with .Er EINVAL if 802.11h support is not enabled. See .Dv IEEE80211_IOC_DFS above for details. .It Dv IEEE80211_IOC_DOTD Set whether or not 802.11d support is enabled using the value in .Va i_val . This request causes a running interface to be restarted. See .Dv IEEE80211_IOC_DOTD above for details. .It Dv IEEE80211_IOC_DOTH Return whether 802.11h support is enabled using the value in .Va i_val . See .Dv IEEE80211_IOC_DOTH above for details. .It Dv IEEE80211_IOC_DROPUNENCRYPTED Set whether unencrypted packets transmit/received should be discarded using the value in .Va i_val . .It Dv IEEE80211_IOC_DTIM_PERIOD Set the period (in beacon intervals) between DTIM events to the value in .Va i_val . This request causes a running interface to be restarted. .It Dv IEEE80211_IOC_DWDS Set whether or not Dynamic WDS support is enabled using the value in .Va i_val . See .Dv IEEE80211_IOC_DWDS above for details. .It Dv IEEE80211_IOC_FF Set whether Atheros fast-frames support is enabled using the value in .Va i_val . This request causes a running interface to be restarted. See .Dv IEEE80211_IOC_FF above for details. .It Dv IEEE80211_IOC_FRAGTHRESHOLD Set the threshold (in bytes) for enabling fragmentation frames using the value in .Va i_val . This request causes a running interface to be reset. See .Dv IEEE80211_IOC_FRAGTHRESHOLD above for details. .It Dv IEEE80211_IOC_GREENFIELD Set whether or not Greenfield preamble use is enabled using the value in .Va i_val . This request causes a running interface to be reset. See .Dv IEEE80211_IOC_GREENFIELD above for details. .It Dv IEEE80211_IOC_HIDESSID Set whether SSID hiding/cloaking is enabled using the value in .Va i_val . This request causes a running interface to be reset. See .Dv IEEE80211_IOC_HIDESSID above for details. .It Dv IEEE80211_IOC_HTCOMPAT Set whether or not 802.11n compatibility support is enabled using the value in .Va i_val . This request causes a running interface to be reset if operating on HT channel. See .Dv IEEE80211_IOC_HTCOMPAT above for details. .It Dv IEEE80211_IOC_HTCONF Set automatic promotion of HT channels using the value in .Va i_val . This request causes a running interface to be restarted. See .Dv IEEE80211_IOC_HTCONF above for details. .It Dv IEEE80211_IOC_HTPROTMODE Set the technique used to protect HT frames in a mixed 802.11n network using the value in .Va i_val . This request causes a running interface to be reset. See .Dv IEEE80211_IOC_HTPROTMODE above for details. .It Dv IEEE80211_IOC_HWMP_MAXHOPS Set the maximum acceptable hop count in an HWMP path according to .Va i_val . Values must be in the range [0-255]. .It Dv IEEE80211_IOC_HWMP_ROOTMODE Set the Mesh root mode operation according to .Va i_val . Valid values are .Dv IEEE80211_HWMP_ROOTMODE_DISABLED (root mode is disabled), .Dv IEEE80211_HWMP_ROOTMODE_NORMAL (send broadcast Path Request frames), .Dv IEEE80211_HWMP_ROOTMODE_PROACTIVE (send broadcast Path Request frames and force replies) and .Dv IEEE80211_HWMP_ROOTMODE_RANN (send broadcast Root Announcement (RANN) frames). .It Dv IEEE80211_IOC_INACTIVITY Set whether or not the system handles inactivity processing using the value in .Va i_val . When inactivity processing is enabled the system will track stations that have not transmitted frames and periodically probe them to check if they are still present. Stations that are inactive and do not respond to probes are dropped. .It Dv IEEE80211_IOC_MACCMD Change the state of the MAC address Access Control List (ACL) system. There are several requests supported: .Dv IEEE80211_MACCMD_POLICY_OPEN (set the current policy to disable ACL use), .Dv IEEE80211_MACCMD_POLICY_ALLOW (set the current policy to allow only addresses listed in the database), .Dv IEEE80211_MACCMD_POLICY_DENY (set the current policy to deny addresses listed in the database), .Dv IEEE80211_MACCMD_POLICY_RADUS (set the current policy to enable use of a RADIUS backend), .Dv IEEE80211_MACCMD_FLUSH (flush all addresses from the database), and .Dv IEEE80211_MACCMD_DETACH (detach the ACL subsystem, disabling it). The .Xr wlan_acl 4 module must be installed or .Er EINVAL will be returned. .It Dv IEEE80211_IOC_MESH_AP Set whether or not Mesh AP support is enabled using .Va i_val . .It Dv IEEE80211_IOC_MESH_FWRD Set whether or not packet forwarding support is enabled using .Va i_val . .It Dv IEEE80211_IOC_MESH_ID Set the Mesh ID using the value pointed to by .Va i_data . A Mesh ID can be up to .Dv IEEE80211_MESHID_LEN bytes long. .It Dv IEEE80211_IOC_MESH_PP_METRIC Set the link metric protocol using the value pointed to by .Va i_data . .It Dv IEEE80211_IOC_MESH_PP_PATH Set the path selection protocol using the value pointed to by .Va i_data . .It Dv IEEE80211_IOC_MESH_RTCMD Manipulate the state of the Mesh routing tables. Several requests are supported: .Dv IEEE80211_MESH_RTCMD_FLUSH (flush the contents of the routing table), .Dv IEEE80211_MESH_RTCMD_ADD (add an entry for the MAC address specified in .Va i_data and start the Peer discovery process), and .Dv IEEE80211_MESH_RTCMD_DELETE (delete the entry corresponding to the MAC address specified in .Va i_data ). .It Dv IEEE80211_IOC_MESH_TTL Set the Mesh Time To Live (TTL) setting installed in packets transmitted by this mesh node using .Va i_val . .It Dv IEEE80211_IOC_MLME Explicitly control the MLME state machine for a station using the MLME request pointed to by .Va i_data . There are several MLME operations supported: .Dv IEEE80211_MLME_ASSOC (request association to an access point), .Dv IEEE80211_MLME_DIASSOC (diassociate the specified station), .Dv IEEE80211_MLME_DEAUTH (deauthenticate the specified station), .Dv IEEE80211_MLME_AUHORIZE (mark the specified station authorized to pass data frames), .Dv IEEE80211_MLME_UNAUTHORIZE (revoke the specified station's ability to pass data frames), and .Dv IEEE80211_MLME_AUTH (request authentication to an access point). Note when this facility is used for stations operating in infrastructure mode the roaming mode should be set to manual. .It Dv IEEE80211_IOC_POWERSAVE Set the current powersaving mode to the value in .Va i_val . See .Dv IEEE80211_IOC_POWERSAVE above for valid values. This request causes a running interface to be reset. .It Dv IEEE80211_IOC_POWERSAVESLEEP Set the powersave sleep time in TU to the value in .Va i_val . This request causes a running interface to be reset. .It Dv IEEE80211_IOC_PRIVACY Set the current MLME setting for PRIVACY using the value in .Va i_val . See .Dv IEEE80211_IOC_PRIVACY above for details. .It Dv IEEE80211_IOC_PROTMODE Set the current 802.11g protection mode to the value in .Va i_val . This request causes a running interface to be reset. See .Dv IEEE80211_IOC_PROTMODE above for details. This request causes a running interface to be reset. .It Dv IEEE80211_IOC_PUREG Set whether ``pure 11g'' mode is enabled using the value in .Va i_val . This request causes a running interface to be restarted. See .Dv IEEE80211_IOC_PUREG above for details. .It Dv IEEE80211_IOC_PUREN Set whether ``pure 11n'' mode is enabled using the value in .Va i_val . This request causes a running interface to be restarted. See .Dv IEEE80211_IOC_PUREN above for details. .It Dv IEEE80211_IOC_REGDOMAIN Set the regulatory state using the data referenced by .Va i_data . This request can only be issued when all interfaces cloned from the underlying physical device are marked down; otherwise .Er EBUSY is returned. Note the new regulatory data may invalidate any desired channel. .It Dv IEEE80211_IOC_RIFS Set whether or not Reduced InterFrame Spacing (RIFS) is enabled using the value in .Va i_val . This setting is meaningful only when operating with 802.11n on an HT channel. This request causes a running interface to be reset. .It Dv IEEE80211_IOC_ROAM Set station roaming parameters using the data pointed to by .Va i_data . .It Dv IEEE80211_IOC_ROAMING Set the current roaming mode to the value in .Va i_val . See .Dv IEEE80211_IOC_ROAMING above for details. .It Dv IEEE80211_IOC_RTSTHRESHOLD Set the threshold (in bytes) for enabling transmission of RTS frames to the value in .Va i_val . This request causes a running interface to be reset. See .Dv IEEE80211_IOC_RTSTHRESHOLD above for details. .It Dv IEEE80211_IOC_SCANVALID Set the age (in seconds) that results from a scan operation will be considered valid. When scan results are no longer valid and they are needed (e.g. to roam) the system will initiate a scan operation to replenish the scan cache. .It Dv IEEE80211_IOC_SCAN_REQ Request a scan operation using the parameters pointed to by .Va i_val . The underlying device must be running or .Er ENXIO will be returned. Values for .Va sr_duration , .Va sr_mindwell , and .Va sr_maxdwell shorter than 1 clock tick are rounded up to a tick. If more SSID's are supplied than the system is capable of handling the extra ones are silently ignored. If a scan operation is already in progress the request will be (silently) ignored. .It Dv IEEE80211_IOC_SCAN_CANCEL Cancel any pending/active scan operation. .It Dv IEEE80211_IOC_SHORTGI Set whether or not Short Guard Interval (SGI) is enabled using the value in .Va i_val . Note SGI is only used when operating on an HT (802.11n) channel. This request causes a running interface to be reset. .It Dv IEEE80211_IOC_SMPS Set the Spatial Multiplexing Power Save (SMPS) setting to the value in .Va i_val . This request causes a running interface to be reset. See .Dv IEEE80211_IOC_SMPS above for details. .It Dv IEEE80211_IOC_SSID Set the desired SSID using the value pointed to by .Va i_data . The string may be at most IEEE80211_NWID_LEN bytes. This request causes a running interface to be restarted. .It Dv IEEE80211_IOC_STA_STATS Clear accumulated statistics for the specified station. .It Dv IEEE80211_IOC_STA_VLAN Set the VLAN tag for the specified station using the information pointed to by .Va i_data . .It Dv IEEE80211_IOC_TDMA_BINTERVAL Set the interval between Beacon frames to the value in .Va i_val . Values must be positive. This request causes a running interface to be reset. .It Dv IEEE80211_IOC_TDMA_SLOT Set the current TDMA slot to the value in .Va i_val . Values must be in the range [0-slotcnt]. Slot 0 identifies the master in the TDMA network; if it running it will immediately start sending Beacon frames. .It Dv IEEE80211_IOC_TDMA_SLOTCNT Set the number of slots in the TDMA network to the value in .Va i_val . This request causes a running interface to be reset. .It Dv IEEE80211_IOC_TDMA_SLOTLEN Set the length of the TDMA slot assigned to each station in the network to the value in .Va i_val . Slot lengths must be in the range 200 usecs to 1024 milliseconds (though values outside the range 1-200ms are unlikely to work well). This request causes a running interface to be reset. .It Dv IEEE80211_IOC_TSN Set whether or not Transitional Security Network (TSN) is enabled using the value in .Va i_val . .It Dv IEEE80211_IOC_TURBOP Set whether Atheros Dynamic Turbo mode is enabled using the value in .Va i_val . This request causes a running interface to be restarted. .It Dv IEEE80211_IOC_TXPARAMS Set transmit parameters using the data pointed to be .Va i_data . This request causes a running interface to be restarted. .It Dv IEEE80211_IOC_TXPOWER Set the maximum transmit power limit in .5 dBm units to the value in .Va i_val . This request causes a running interface to be reset. .It Dv IEEE80211_IOC_WEP Set the current WEP mode to the value in .Va i_val . See .Dv IEEE80211_IOC_WEP above for valid values. This request causes a running interface to be restarted. Note this request is deprecated; use .Dv IEEE80211_IOC_PRIVACY and .Dv IEEE80211_IOC_DROPUNENCRYPTED instead. .It Dv IEEE80211_IOC_WEPKEY Set the WEP key indicated by .Va i_val using the data pointed to by .Va i_data . Note this request is deprecated; use .Dv IEEE80211_IOC_WPAKEY instead. .It Dv IEEE80211_IOC_WEPTXKEY Set the default transmit key used for transmission to the value in .Va i_val . .It Dv IEEE80211_IOC_WME Set whether or not WME/WMM support is enabled using the value in .Va i_val . This request causes a running interface to be reset. .It Dv IEEE80211_IOC_WME_ACKPOLICY Set the WME ACK Policy for the Access Class (AC) specified in .Va i_len using the value in .Va i_val . .It Dv IEEE80211_IOC_WME_ACM Set the WME Admission Control Mechanism for the Access Class (AC) specified in .Va i_len using the value in .Va i_val . .It Dv IEEE80211_IOC_WME_AIFS Set the WME AIFS parameter for the Access Class (AC) specified in .Va i_len using the value in .Va i_val . .It Dv IEEE80211_IOC_WME_CWMAX Set the WME CWmax parameter for the Access Class (AC) specified in .Va i_len using the value in .Va i_val . .It Dv IEEE80211_IOC_WME_CWMIN Set the WME CWmin parameter for the Access Class (AC) specified in .Va i_len using the value in .Va i_val . .It Dv IEEE80211_IOC_WME_TXOPLIMIT Set the WME TxOpLimit parameter for the Access Class (AC) specified in .Va i_len using the value in .Va i_val . .It Dv IEEE80211_IOC_WPA Set the WPA configuration using the value in .Va i_val . This request causes a running interface to be reset. See .Dv IEEE80211_IOC_WPA above for details. .It Dv IEEE80211_IOC_WPAKEY Set the requested cryptographic key using data in the buffer pointed to by .Va i_data . See .Dv IEEE80211_IOC_WPAKEY for details. .It Dv IEEE80211_IOC_WPS Set whether or not Wi-FI Protected Setup (WPS) is enabled using the value in .Va i_val . .El .Sh SEE ALSO .Xr ioctl 2 , .Xr wlan 4 , .Xr wlan_acl 4 , .Xr wlan_xauth 4 , -.Xr ifconfig 8 , .Xr hostapd 8 , -.Xr wpa_supplicant 8 . +.Xr ifconfig 8 , +.Xr wpa_supplicant 8 Index: projects/sendfile/share/man/man4/netmap.4 =================================================================== --- projects/sendfile/share/man/man4/netmap.4 (revision 276056) +++ projects/sendfile/share/man/man4/netmap.4 (revision 276057) @@ -1,1075 +1,1067 @@ .\" Copyright (c) 2011-2014 Matteo Landi, Luigi Rizzo, Universita` di Pisa .\" 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. .\" .\" This document is derived in part from the enet man page (enet.4) .\" distributed with 4.3BSD Unix. .\" .\" $FreeBSD$ .\" .Dd February 13, 2014 .Dt NETMAP 4 .Os .Sh NAME .Nm netmap .Nd a framework for fast packet I/O .br .Nm VALE .Nd a fast VirtuAl Local Ethernet using the netmap API .br .Nm netmap pipes .Nd a shared memory packet transport channel .Sh SYNOPSIS .Cd device netmap .Sh DESCRIPTION .Nm is a framework for extremely fast and efficient packet I/O for both userspace and kernel clients. It runs on FreeBSD and Linux, and includes .Nm VALE , a very fast and modular in-kernel software switch/dataplane, and .Nm netmap pipes , a shared memory packet transport channel. All these are accessed interchangeably with the same API. .Pp .Nm , VALE and .Nm netmap pipes are at least one order of magnitude faster than standard OS mechanisms (sockets, bpf, tun/tap interfaces, native switches, pipes), reaching 14.88 million packets per second (Mpps) with much less than one core on a 10 Gbit NIC, about 20 Mpps per core for VALE ports, and over 100 Mpps for netmap pipes. .Pp Userspace clients can dynamically switch NICs into .Nm mode and send and receive raw packets through memory mapped buffers. Similarly, .Nm VALE switch instances and ports, and .Nm netmap pipes can be created dynamically, providing high speed packet I/O between processes, virtual machines, NICs and the host stack. .Pp .Nm suports both non-blocking I/O through .Xr ioctls() , synchronization and blocking I/O through a file descriptor and standard OS mechanisms such as .Xr select 2 , .Xr poll 2 , .Xr epoll 2 , .Xr kqueue 2 . .Nm VALE and .Nm netmap pipes are implemented by a single kernel module, which also emulates the .Nm API over standard drivers for devices without native .Nm support. For best performance, .Nm requires explicit support in device drivers. .Pp In the rest of this (long) manual page we document various aspects of the .Nm and .Nm VALE architecture, features and usage. -.Pp .Sh ARCHITECTURE .Nm supports raw packet I/O through a .Em port , which can be connected to a physical interface .Em ( NIC ) , to the host stack, or to a .Nm VALE switch). Ports use preallocated circular queues of buffers .Em ( rings ) residing in an mmapped region. There is one ring for each transmit/receive queue of a NIC or virtual port. An additional ring pair connects to the host stack. .Pp After binding a file descriptor to a port, a .Nm client can send or receive packets in batches through the rings, and possibly implement zero-copy forwarding between ports. .Pp All NICs operating in .Nm mode use the same memory region, accessible to all processes who own .Nm /dev/netmap file descriptors bound to NICs. Independent .Nm VALE and .Nm netmap pipe ports by default use separate memory regions, but can be independently configured to share memory. -.Pp .Sh ENTERING AND EXITING NETMAP MODE The following section describes the system calls to create and control -.Nm netmap +.Nm netmap ports (including .Nm VALE and .Nm netmap pipe ports). Simpler, higher level functions are described in section .Xr LIBRARIES . .Pp Ports and rings are created and controlled through a file descriptor, created by opening a special device .Dl fd = open("/dev/netmap"); and then bound to a specific port with an .Dl ioctl(fd, NIOCREGIF, (struct nmreq *)arg); .Pp .Nm has multiple modes of operation controlled by the .Vt struct nmreq argument. .Va arg.nr_name specifies the port name, as follows: .Bl -tag -width XXXX .It Dv OS network interface name (e.g. 'em0', 'eth1', ... ) the data path of the NIC is disconnected from the host stack, and the file descriptor is bound to the NIC (one or all queues), or to the host stack; .It Dv valeXXX:YYY (arbitrary XXX and YYY) the file descriptor is bound to port YYY of a VALE switch called XXX, both dynamically created if necessary. The string cannot exceed IFNAMSIZ characters, and YYY cannot be the name of any existing OS network interface. .El .Pp On return, .Va arg indicates the size of the shared memory region, and the number, size and location of all the .Nm data structures, which can be accessed by mmapping the memory .Dl char *mem = mmap(0, arg.nr_memsize, fd); .Pp Non blocking I/O is done with special .Xr ioctl 2 .Xr select 2 and .Xr poll 2 on the file descriptor permit blocking I/O. .Xr epoll 2 and .Xr kqueue 2 are not supported on .Nm file descriptors. .Pp While a NIC is in .Nm mode, the OS will still believe the interface is up and running. OS-generated packets for that NIC end up into a .Nm ring, and another ring is used to send packets into the OS network stack. A .Xr close 2 on the file descriptor removes the binding, and returns the NIC to normal mode (reconnecting the data path to the host stack), or destroys the virtual port. -.Pp .Sh DATA STRUCTURES The data structures in the mmapped memory region are detailed in .Xr sys/net/netmap.h , which is the ultimate reference for the .Nm API. The main structures and fields are indicated below: .Bl -tag -width XXX .It Dv struct netmap_if (one per interface) .Bd -literal struct netmap_if { ... const uint32_t ni_flags; /* properties */ ... const uint32_t ni_tx_rings; /* NIC tx rings */ const uint32_t ni_rx_rings; /* NIC rx rings */ uint32_t ni_bufs_head; /* head of extra bufs list */ ... }; .Ed .Pp Indicates the number of available rings .Pa ( struct netmap_rings ) and their position in the mmapped region. The number of tx and rx rings .Pa ( ni_tx_rings , ni_rx_rings ) normally depends on the hardware. NICs also have an extra tx/rx ring pair connected to the host stack. .Em NIOCREGIF can also request additional unbound buffers in the same memory space, to be used as temporary storage for packets. .Pa ni_bufs_head contains the index of the first of these free rings, which are connected in a list (the first uint32_t of each buffer being the index of the next buffer in the list). A 0 indicates the end of the list. .Pp .It Dv struct netmap_ring (one per ring) .Bd -literal struct netmap_ring { ... const uint32_t num_slots; /* slots in each ring */ const uint32_t nr_buf_size; /* size of each buffer */ ... uint32_t head; /* (u) first buf owned by user */ uint32_t cur; /* (u) wakeup position */ const uint32_t tail; /* (k) first buf owned by kernel */ ... uint32_t flags; struct timeval ts; /* (k) time of last rxsync() */ ... struct netmap_slot slot[0]; /* array of slots */ } .Ed .Pp Implements transmit and receive rings, with read/write pointers, metadata and and an array of .Pa slots describing the buffers. .Pp .It Dv struct netmap_slot (one per buffer) .Bd -literal struct netmap_slot { uint32_t buf_idx; /* buffer index */ uint16_t len; /* packet length */ uint16_t flags; /* buf changed, etc. */ uint64_t ptr; /* address for indirect buffers */ }; .Ed .Pp Describes a packet buffer, which normally is identified by an index and resides in the mmapped region. .It Dv packet buffers Fixed size (normally 2 KB) packet buffers allocated by the kernel. .El .Pp The offset of the .Pa struct netmap_if in the mmapped region is indicated by the .Pa nr_offset field in the structure returned by .Pa NIOCREGIF . From there, all other objects are reachable through relative references (offsets or indexes). Macros and functions in help converting them into actual pointers: .Pp .Dl struct netmap_if *nifp = NETMAP_IF(mem, arg.nr_offset); .Dl struct netmap_ring *txr = NETMAP_TXRING(nifp, ring_index); .Dl struct netmap_ring *rxr = NETMAP_RXRING(nifp, ring_index); .Pp .Dl char *buf = NETMAP_BUF(ring, buffer_index); .Sh RINGS, BUFFERS AND DATA I/O .Va Rings are circular queues of packets with three indexes/pointers .Va ( head , cur , tail ) ; one slot is always kept empty. The ring size .Va ( num_slots ) should not be assumed to be a power of two. .br (NOTE: older versions of netmap used head/count format to indicate the content of a ring). .Pp .Va head is the first slot available to userspace; .br .Va cur is the wakeup point: select/poll will unblock when .Va tail passes .Va cur ; .br .Va tail is the first slot reserved to the kernel. .Pp Slot indexes MUST only move forward; for convenience, the function .Dl nm_ring_next(ring, index) returns the next index modulo the ring size. .Pp .Va head and .Va cur are only modified by the user program; .Va tail is only modified by the kernel. The kernel only reads/writes the .Vt struct netmap_ring slots and buffers during the execution of a netmap-related system call. The only exception are slots (and buffers) in the range .Va tail\ . . . head-1 , that are explicitly assigned to the kernel. .Pp .Ss TRANSMIT RINGS On transmit rings, after a .Nm system call, slots in the range .Va head\ . . . tail-1 are available for transmission. User code should fill the slots sequentially and advance .Va head and .Va cur past slots ready to transmit. .Va cur may be moved further ahead if the user code needs more slots before further transmissions (see .Sx SCATTER GATHER I/O ) . .Pp At the next NIOCTXSYNC/select()/poll(), slots up to .Va head-1 are pushed to the port, and .Va tail may advance if further slots have become available. Below is an example of the evolution of a TX ring: .Pp .Bd -literal after the syscall, slots between cur and tail are (a)vailable head=cur tail | | v v TX [.....aaaaaaaaaaa.............] user creates new packets to (T)ransmit head=cur tail | | v v TX [.....TTTTTaaaaaa.............] NIOCTXSYNC/poll()/select() sends packets and reports new slots head=cur tail | | v v TX [..........aaaaaaaaaaa........] .Ed .Pp select() and poll() wlll block if there is no space in the ring, i.e. .Dl ring->cur == ring->tail and return when new slots have become available. .Pp High speed applications may want to amortize the cost of system calls by preparing as many packets as possible before issuing them. .Pp A transmit ring with pending transmissions has .Dl ring->head != ring->tail + 1 (modulo the ring size). The function .Va int nm_tx_pending(ring) implements this test. -.Pp .Ss RECEIVE RINGS On receive rings, after a .Nm system call, the slots in the range .Va head\& . . . tail-1 contain received packets. User code should process them and advance .Va head and .Va cur past slots it wants to return to the kernel. .Va cur may be moved further ahead if the user code wants to wait for more packets without returning all the previous slots to the kernel. .Pp At the next NIOCRXSYNC/select()/poll(), slots up to .Va head-1 are returned to the kernel for further receives, and .Va tail may advance to report new incoming packets. .br Below is an example of the evolution of an RX ring: .Bd -literal after the syscall, there are some (h)eld and some (R)eceived slots head cur tail | | | v v v RX [..hhhhhhRRRRRRRR..........] user advances head and cur, releasing some slots and holding others head cur tail | | | v v v RX [..*****hhhRRRRRR...........] NICRXSYNC/poll()/select() recovers slots and reports new packets head cur tail | | | v v v RX [.......hhhRRRRRRRRRRRR....] .Ed -.Pp .Sh SLOTS AND PACKET BUFFERS Normally, packets should be stored in the netmap-allocated buffers assigned to slots when ports are bound to a file descriptor. One packet is fully contained in a single buffer. .Pp The following flags affect slot and buffer processing: .Bl -tag -width XXX .It NS_BUF_CHANGED it MUST be used when the buf_idx in the slot is changed. This can be used to implement zero-copy forwarding, see .Sx ZERO-COPY FORWARDING . .Pp .It NS_REPORT reports when this buffer has been transmitted. Normally, .Nm notifies transmit completions in batches, hence signals can be delayed indefinitely. This flag helps detecting when packets have been send and a file descriptor can be closed. .It NS_FORWARD When a ring is in 'transparent' mode (see .Sx TRANSPARENT MODE ) , packets marked with this flags are forwarded to the other endpoint at the next system call, thus restoring (in a selective way) the connection between a NIC and the host stack. .It NS_NO_LEARN tells the forwarding code that the SRC MAC address for this packet must not be used in the learning bridge code. .It NS_INDIRECT indicates that the packet's payload is in a user-supplied buffer, whose user virtual address is in the 'ptr' field of the slot. The size can reach 65535 bytes. .br This is only supported on the transmit ring of .Nm VALE ports, and it helps reducing data copies in the interconnection of virtual machines. .It NS_MOREFRAG indicates that the packet continues with subsequent buffers; the last buffer in a packet must have the flag clear. .El .Sh SCATTER GATHER I/O Packets can span multiple slots if the .Va NS_MOREFRAG flag is set in all but the last slot. The maximum length of a chain is 64 buffers. This is normally used with .Nm VALE ports when connecting virtual machines, as they generate large TSO segments that are not split unless they reach a physical device. .Pp NOTE: The length field always refers to the individual fragment; there is no place with the total length of a packet. .Pp On receive rings the macro .Va NS_RFRAGS(slot) indicates the remaining number of slots for this packet, including the current one. Slots with a value greater than 1 also have NS_MOREFRAG set. .Sh IOCTLS .Nm uses two ioctls (NIOCTXSYNC, NIOCRXSYNC) for non-blocking I/O. They take no argument. Two more ioctls (NIOCGINFO, NIOCREGIF) are used to query and configure ports, with the following argument: .Bd -literal struct nmreq { char nr_name[IFNAMSIZ]; /* (i) port name */ uint32_t nr_version; /* (i) API version */ uint32_t nr_offset; /* (o) nifp offset in mmap region */ uint32_t nr_memsize; /* (o) size of the mmap region */ uint32_t nr_tx_slots; /* (i/o) slots in tx rings */ uint32_t nr_rx_slots; /* (i/o) slots in rx rings */ uint16_t nr_tx_rings; /* (i/o) number of tx rings */ uint16_t nr_rx_rings; /* (i/o) number of tx rings */ uint16_t nr_ringid; /* (i/o) ring(s) we care about */ uint16_t nr_cmd; /* (i) special command */ uint16_t nr_arg1; /* (i/o) extra arguments */ uint16_t nr_arg2; /* (i/o) extra arguments */ uint32_t nr_arg3; /* (i/o) extra arguments */ uint32_t nr_flags /* (i/o) open mode */ ... }; .Ed .Pp A file descriptor obtained through .Pa /dev/netmap also supports the ioctl supported by network devices, see .Xr netintro 4 . .Pp .Bl -tag -width XXXX .It Dv NIOCGINFO returns EINVAL if the named port does not support netmap. Otherwise, it returns 0 and (advisory) information about the port. Note that all the information below can change before the interface is actually put in netmap mode. .Pp .Bl -tag -width XX .It Pa nr_memsize indicates the size of the .Nm memory region. NICs in .Nm mode all share the same memory region, whereas .Nm VALE ports have independent regions for each port. .It Pa nr_tx_slots , nr_rx_slots indicate the size of transmit and receive rings. .It Pa nr_tx_rings , nr_rx_rings indicate the number of transmit and receive rings. Both ring number and sizes may be configured at runtime using interface-specific functions (e.g. .Xr ethtool ). .El .It Dv NIOCREGIF binds the port named in .Va nr_name to the file descriptor. For a physical device this also switches it into .Nm mode, disconnecting it from the host stack. Multiple file descriptors can be bound to the same port, with proper synchronization left to the user. .Pp .Dv NIOCREGIF can also bind a file descriptor to one endpoint of a .Em netmap pipe , consisting of two netmap ports with a crossover connection. A netmap pipe share the same memory space of the parent port, and is meant to enable configuration where a master process acts as a dispatcher towards slave processes. .Pp To enable this function, the .Pa nr_arg1 field of the structure can be used as a hint to the kernel to indicate how many pipes we expect to use, and reserve extra space in the memory region. .Pp On return, it gives the same info as NIOCGINFO, with .Pa nr_ringid and .Pa nr_flags indicating the identity of the rings controlled through the file descriptor. .Pp .Va nr_flags .Va nr_ringid selects which rings are controlled through this file descriptor. Possible values of .Pa nr_flags are indicated below, together with the naming schemes that application libraries (such as the .Nm nm_open indicated below) can use to indicate the specific set of rings. In the example below, "netmap:foo" is any valid netmap port name. .Pp .Bl -tag -width XXXXX .It NR_REG_ALL_NIC "netmap:foo" (default) all hardware ring pairs .It NR_REG_SW "netmap:foo^" the ``host rings'', connecting to the host stack. .It NR_REG_NIC_SW "netmap:foo+" all hardware rings and the host rings .It NR_REG_ONE_NIC "netmap:foo-i" only the i-th hardware ring pair, where the number is in .Pa nr_ringid ; .It NR_REG_PIPE_MASTER "netmap:foo{i" the master side of the netmap pipe whose identifier (i) is in .Pa nr_ringid ; .It NR_REG_PIPE_SLAVE "netmap:foo}i" the slave side of the netmap pipe whose identifier (i) is in .Pa nr_ringid . .Pp The identifier of a pipe must be thought as part of the pipe name, and does not need to be sequential. On return the pipe will only have a single ring pair with index 0, irrespective of the value of i. .El .Pp By default, a .Xr poll 2 or .Xr select 2 call pushes out any pending packets on the transmit ring, even if no write events are specified. The feature can be disabled by or-ing .Va NETMAP_NO_TX_POLL to the value written to .Va nr_ringid. When this feature is used, packets are transmitted only on .Va ioctl(NIOCTXSYNC) or select()/poll() are called with a write event (POLLOUT/wfdset) or a full ring. .Pp When registering a virtual interface that is dynamically created to a .Xr vale 4 switch, we can specify the desired number of rings (1 by default, and currently up to 16) on it using nr_tx_rings and nr_rx_rings fields. .It Dv NIOCTXSYNC tells the hardware of new packets to transmit, and updates the number of slots available for transmission. .It Dv NIOCRXSYNC tells the hardware of consumed packets, and asks for newly available packets. .El .Sh SELECT, POLL, EPOLL, KQUEUE. .Xr select 2 and .Xr poll 2 on a .Nm file descriptor process rings as indicated in .Sx TRANSMIT RINGS and .Sx RECEIVE RINGS , respectively when write (POLLOUT) and read (POLLIN) events are requested. Both block if no slots are available in the ring .Va ( ring->cur == ring->tail ) . Depending on the platform, .Xr epoll 2 and .Xr kqueue 2 are supported too. .Pp Packets in transmit rings are normally pushed out (and buffers reclaimed) even without requesting write events. Passing the NETMAP_NO_TX_POLL flag to .Em NIOCREGIF disables this feature. By default, receive rings are processed only if read events are requested. Passing the NETMAP_DO_RX_POLL flag to .Em NIOCREGIF updates receive rings even without read events. Note that on epoll and kqueue, NETMAP_NO_TX_POLL and NETMAP_DO_RX_POLL only have an effect when some event is posted for the file descriptor. .Sh LIBRARIES The .Nm API is supposed to be used directly, both because of its simplicity and for efficient integration with applications. .Pp For conveniency, the .Va header provides a few macros and functions to ease creating a file descriptor and doing I/O with a .Nm port. These are loosely modeled after the .Xr pcap 3 API, to ease porting of libpcap-based applications to .Nm . To use these extra functions, programs should .Dl #define NETMAP_WITH_LIBS before .Dl #include .Pp The following functions are available: .Bl -tag -width XXXXX .It Va struct nm_desc * nm_open(const char *ifname, const struct nmreq *req, uint64_t flags, const struct nm_desc *arg) similar to .Xr pcap_open , binds a file descriptor to a port. .Bl -tag -width XX .It Va ifname is a port name, in the form "netmap:XXX" for a NIC and "valeXXX:YYY" for a .Nm VALE port. .It Va req provides the initial values for the argument to the NIOCREGIF ioctl. The nm_flags and nm_ringid values are overwritten by parsing ifname and flags, and other fields can be overridden through the other two arguments. .It Va arg points to a struct nm_desc containing arguments (e.g. from a previously open file descriptor) that should override the defaults. The fields are used as described below .It Va flags can be set to a combination of the following flags: .Va NETMAP_NO_TX_POLL , .Va NETMAP_DO_RX_POLL (copied into nr_ringid); .Va NM_OPEN_NO_MMAP (if arg points to the same memory region, avoids the mmap and uses the values from it); .Va NM_OPEN_IFNAME (ignores ifname and uses the values in arg); .Va NM_OPEN_ARG1 , .Va NM_OPEN_ARG2 , .Va NM_OPEN_ARG3 (uses the fields from arg); .Va NM_OPEN_RING_CFG (uses the ring number and sizes from arg). .El .It Va int nm_close(struct nm_desc *d) closes the file descriptor, unmaps memory, frees resources. .It Va int nm_inject(struct nm_desc *d, const void *buf, size_t size) similar to pcap_inject(), pushes a packet to a ring, returns the size of the packet is successful, or 0 on error; .It Va int nm_dispatch(struct nm_desc *d, int cnt, nm_cb_t cb, u_char *arg) similar to pcap_dispatch(), applies a callback to incoming packets .It Va u_char * nm_nextpkt(struct nm_desc *d, struct nm_pkthdr *hdr) similar to pcap_next(), fetches the next packet -.Pp .El .Sh SUPPORTED DEVICES .Nm natively supports the following devices: .Pp On FreeBSD: .Xr em 4 , .Xr igb 4 , .Xr ixgbe 4 , .Xr lem 4 , .Xr re 4 . .Pp On Linux .Xr e1000 4 , .Xr e1000e 4 , .Xr igb 4 , .Xr ixgbe 4 , .Xr mlx4 4 , .Xr forcedeth 4 , .Xr r8169 4 . .Pp NICs without native support can still be used in .Nm mode through emulation. Performance is inferior to native netmap mode but still significantly higher than sockets, and approaching that of in-kernel solutions such as Linux's .Xr pktgen . .Pp Emulation is also available for devices with native netmap support, which can be used for testing or performance comparison. The sysctl variable .Va dev.netmap.admode globally controls how netmap mode is implemented. .Sh SYSCTL VARIABLES AND MODULE PARAMETERS Some aspect of the operation of .Nm are controlled through sysctl variables on FreeBSD .Em ( dev.netmap.* ) and module parameters on Linux .Em ( /sys/module/netmap_lin/parameters/* ) : .Pp .Bl -tag -width indent .It Va dev.netmap.admode: 0 Controls the use of native or emulated adapter mode. 0 uses the best available option, 1 forces native and fails if not available, 2 forces emulated hence never fails. .It Va dev.netmap.generic_ringsize: 1024 Ring size used for emulated netmap mode .It Va dev.netmap.generic_mit: 100000 Controls interrupt moderation for emulated mode .It Va dev.netmap.mmap_unreg: 0 .It Va dev.netmap.fwd: 0 Forces NS_FORWARD mode .It Va dev.netmap.flags: 0 .It Va dev.netmap.txsync_retry: 2 .It Va dev.netmap.no_pendintr: 1 Forces recovery of transmit buffers on system calls .It Va dev.netmap.mitigate: 1 Propagates interrupt mitigation to user processes .It Va dev.netmap.no_timestamp: 0 Disables the update of the timestamp in the netmap ring .It Va dev.netmap.verbose: 0 Verbose kernel messages .It Va dev.netmap.buf_num: 163840 .It Va dev.netmap.buf_size: 2048 .It Va dev.netmap.ring_num: 200 .It Va dev.netmap.ring_size: 36864 .It Va dev.netmap.if_num: 100 .It Va dev.netmap.if_size: 1024 Sizes and number of objects (netmap_if, netmap_ring, buffers) for the global memory region. The only parameter worth modifying is .Va dev.netmap.buf_num as it impacts the total amount of memory used by netmap. .It Va dev.netmap.buf_curr_num: 0 .It Va dev.netmap.buf_curr_size: 0 .It Va dev.netmap.ring_curr_num: 0 .It Va dev.netmap.ring_curr_size: 0 .It Va dev.netmap.if_curr_num: 0 .It Va dev.netmap.if_curr_size: 0 Actual values in use. .It Va dev.netmap.bridge_batch: 1024 Batch size used when moving packets across a .Nm VALE switch. Values above 64 generally guarantee good performance. .El .Sh SYSTEM CALLS .Nm uses .Xr select 2 , .Xr poll 2 , .Xr epoll and .Xr kqueue to wake up processes when significant events occur, and .Xr mmap 2 to map memory. .Xr ioctl 2 is used to configure ports and .Nm VALE switches . .Pp Applications may need to create threads and bind them to specific cores to improve performance, using standard OS primitives, see .Xr pthread 3 . In particular, .Xr pthread_setaffinity_np 3 may be of use. .Sh CAVEATS No matter how fast the CPU and OS are, achieving line rate on 10G and faster interfaces requires hardware with sufficient performance. Several NICs are unable to sustain line rate with small packet sizes. Insufficient PCIe or memory bandwidth can also cause reduced performance. .Pp Another frequent reason for low performance is the use of flow control on the link: a slow receiver can limit the transmit speed. Be sure to disable flow control when running high speed experiments. .Pp .Ss SPECIAL NIC FEATURES .Nm is orthogonal to some NIC features such as multiqueue, schedulers, packet filters. .Pp Multiple transmit and receive rings are supported natively and can be configured with ordinary OS tools, such as .Xr ethtool or device-specific sysctl variables. The same goes for Receive Packet Steering (RPS) and filtering of incoming traffic. .Pp .Nm .Em does not use features such as .Em checksum offloading , TCP segmentation offloading , .Em encryption , VLAN encapsulation/decapsulation , etc. . When using netmap to exchange packets with the host stack, make sure to disable these features. .Sh EXAMPLES .Ss TEST PROGRAMS .Nm comes with a few programs that can be used for testing or simple applications. See the .Va examples/ directory in .Nm distributions, or .Va tools/tools/netmap/ directory in FreeBSD distributions. .Pp .Xr pkt-gen is a general purpose traffic source/sink. .Pp As an example .Dl pkt-gen -i ix0 -f tx -l 60 can generate an infinite stream of minimum size packets, and .Dl pkt-gen -i ix0 -f rx is a traffic sink. Both print traffic statistics, to help monitor how the system performs. .Pp .Xr pkt-gen has many options can be uses to set packet sizes, addresses, rates, and use multiple send/receive threads and cores. .Pp .Xr bridge is another test program which interconnects two .Nm ports. It can be used for transparent forwarding between interfaces, as in .Dl bridge -i ix0 -i ix1 or even connect the NIC to the host stack using netmap .Dl bridge -i ix0 -i ix0 .Ss USING THE NATIVE API The following code implements a traffic generator .Pp .Bd -literal -compact #include ... void sender(void) { struct netmap_if *nifp; struct netmap_ring *ring; struct nmreq nmr; struct pollfd fds; fd = open("/dev/netmap", O_RDWR); bzero(&nmr, sizeof(nmr)); strcpy(nmr.nr_name, "ix0"); nmr.nm_version = NETMAP_API; ioctl(fd, NIOCREGIF, &nmr); p = mmap(0, nmr.nr_memsize, fd); nifp = NETMAP_IF(p, nmr.nr_offset); ring = NETMAP_TXRING(nifp, 0); fds.fd = fd; fds.events = POLLOUT; for (;;) { poll(&fds, 1, -1); while (!nm_ring_empty(ring)) { i = ring->cur; buf = NETMAP_BUF(ring, ring->slot[i].buf_index); ... prepare packet in buf ... ring->slot[i].len = ... packet length ... ring->head = ring->cur = nm_ring_next(ring, i); } } } .Ed .Ss HELPER FUNCTIONS A simple receiver can be implemented using the helper functions .Bd -literal -compact #define NETMAP_WITH_LIBS #include ... void receiver(void) { struct nm_desc *d; struct pollfd fds; u_char *buf; struct nm_pkthdr h; ... d = nm_open("netmap:ix0", NULL, 0, 0); fds.fd = NETMAP_FD(d); fds.events = POLLIN; for (;;) { poll(&fds, 1, -1); while ( (buf = nm_nextpkt(d, &h)) ) consume_pkt(buf, h->len); } nm_close(d); } .Ed .Ss ZERO-COPY FORWARDING Since physical interfaces share the same memory region, it is possible to do packet forwarding between ports swapping buffers. The buffer from the transmit ring is used to replenish the receive ring: .Bd -literal -compact uint32_t tmp; struct netmap_slot *src, *dst; ... src = &src_ring->slot[rxr->cur]; dst = &dst_ring->slot[txr->cur]; tmp = dst->buf_idx; dst->buf_idx = src->buf_idx; dst->len = src->len; dst->flags = NS_BUF_CHANGED; src->buf_idx = tmp; src->flags = NS_BUF_CHANGED; rxr->head = rxr->cur = nm_ring_next(rxr, rxr->cur); txr->head = txr->cur = nm_ring_next(txr, txr->cur); ... .Ed .Ss ACCESSING THE HOST STACK The host stack is for all practical purposes just a regular ring pair, which you can access with the netmap API (e.g. with .Dl nm_open("netmap:eth0^", ... ) ; All packets that the host would send to an interface in .Nm mode end up into the RX ring, whereas all packets queued to the TX ring are send up to the host stack. .Ss VALE SWITCH A simple way to test the performance of a .Nm VALE switch is to attach a sender and a receiver to it, e.g. running the following in two different terminals: .Dl pkt-gen -i vale1:a -f rx # receiver .Dl pkt-gen -i vale1:b -f tx # sender The same example can be used to test netmap pipes, by simply changing port names, e.g. .Dl pkt-gen -i vale:x{3 -f rx # receiver on the master side .Dl pkt-gen -i vale:x}3 -f tx # sender on the slave side .Pp The following command attaches an interface and the host stack to a switch: .Dl vale-ctl -h vale2:em0 Other .Nm clients attached to the same switch can now communicate with the network card or the host. -.Pp .Sh SEE ALSO -.Pp -http://info.iet.unipi.it/~luigi/netmap/ +.Pa http://info.iet.unipi.it/~luigi/netmap/ .Pp Luigi Rizzo, Revisiting network I/O APIs: the netmap framework, Communications of the ACM, 55 (3), pp.45-51, March 2012 .Pp Luigi Rizzo, netmap: a novel framework for fast packet I/O, Usenix ATC'12, June 2012, Boston .Pp Luigi Rizzo, Giuseppe Lettieri, VALE, a switched ethernet for virtual machines, ACM CoNEXT'12, December 2012, Nice .Pp Luigi Rizzo, Giuseppe Lettieri, Vincenzo Maffione, Speeding up packet I/O in virtual machines, ACM/IEEE ANCS'13, October 2013, San Jose .Sh AUTHORS .An -nosplit The .Nm framework has been originally designed and implemented at the Universita` di Pisa in 2011 by .An Luigi Rizzo , and further extended with help from .An Matteo Landi , .An Gaetano Catalli , .An Giuseppe Lettieri , .An Vincenzo Maffione . .Pp .Nm and .Nm VALE have been funded by the European Commission within FP7 Projects CHANGE (257422) and OPENLAB (287581). Index: projects/sendfile/share/man/man4/nfe.4 =================================================================== --- projects/sendfile/share/man/man4/nfe.4 (revision 276056) +++ projects/sendfile/share/man/man4/nfe.4 (revision 276057) @@ -1,200 +1,200 @@ .\" $OpenBSD: nfe.4,v 1.7 2006/02/28 08:13:47 jsg Exp $ .\" .\" Copyright (c) 2006 Jonathan Gray .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .\" $FreeBSD$ .\" .Dd January 15, 2011 .Dt NFE 4 .Os .Sh NAME .Nm nfe .Nd "NVIDIA nForce MCP Ethernet driver" .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device miibus" .Cd "device nfe" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent if_nfe_load="YES" .Ed .Sh DESCRIPTION The .Nm driver supports PCI Ethernet adapters based on the NVIDIA nForce Media and Communications Processors (MCP), such as the nForce, nForce 2, nForce 3, CK804, MCP04, MCP51, MCP55, MCP61, MCP65, MCP67, MCP73, MCP77 and MCP79 Ethernet controller chips. .Pp Supported features include (hardware support provided): .Pp .Bl -bullet -compact .It Receive/Transmit IP/TCP/UDP checksum offload .It Hardware VLAN tag insertion/stripping .It TCP segmentation offload (TSO) .It MSI/MSI-X .It Jumbo Frames .El .Pp Support for Jumbo Frames is provided via the interface MTU setting. Selecting an MTU larger than 1500 bytes with the .Xr ifconfig 8 utility configures the adapter to receive and transmit Jumbo Frames. .Pp The .Nm driver supports the following media types: .Bl -tag -width "10baseT/UTP" .It Cm autoselect Enable autoselection of the media type and options. .It Cm 10baseT/UTP Set 10Mbps operation. .It Cm 100baseTX Set 100Mbps (Fast Ethernet) operation. .It Cm 1000baseT Set 1000Mbps (Gigabit Ethernet) operation (recent models only). .El .Pp The .Nm driver supports the following media options: .Bl -tag -width ".Cm 10baseT/UTP" .It Cm half-duplex Force half duplex operation. .It Cm full-duplex Force full duplex operation. .El .Pp For more information on configuring this device, see .Xr ifconfig 8 . .Sh HARDWARE The .Nm driver supports the following NVIDIA MCP onboard adapters: .Pp .Bl -bullet -compact .It NVIDIA nForce MCP Networking Adapter .It NVIDIA nForce MCP04 Networking Adapter .It NVIDIA nForce 430 MCP12 Networking Adapter .It NVIDIA nForce 430 MCP13 Networking Adapter .It NVIDIA nForce MCP51 Networking Adapter .It NVIDIA nForce MCP55 Networking Adapter .It NVIDIA nForce MCP61 Networking Adapter .It NVIDIA nForce MCP65 Networking Adapter .It NVIDIA nForce MCP67 Networking Adapter .It NVIDIA nForce MCP73 Networking Adapter .It NVIDIA nForce MCP77 Networking Adapter .It NVIDIA nForce MCP79 Networking Adapter .It NVIDIA nForce2 MCP2 Networking Adapter .It NVIDIA nForce2 400 MCP4 Networking Adapter .It NVIDIA nForce2 400 MCP5 Networking Adapter .It NVIDIA nForce3 MCP3 Networking Adapter .It NVIDIA nForce3 250 MCP6 Networking Adapter .It NVIDIA nForce3 MCP7 Networking Adapter .It NVIDIA nForce4 CK804 MCP8 Networking Adapter .It NVIDIA nForce4 CK804 MCP9 Networking Adapter .El .Sh LOADER TUNABLES Tunables can be set at the .Xr loader 8 prompt before booting the kernel or stored in .Xr loader.conf 5 . .Bl -tag -width indent .It Va hw.nfe.msi_disable Whether or not MSI support is enabled in the driver. The default value is 0. .It Va hw.nfe.msix_disable Whether or not MSI-X support is enabled in the driver. The default value is 0. .El .Sh SYSCTL VARIABLES The following .Xr sysctl 8 variables can be used to modify or monitor .Nm behavior. .Bl -tag -width indent .It Va dev.nfe.%d.process_limit Maximum number of Rx events to be processed in the event loop before rescheduling a taskqueue. The accepted range is 50 to 255, the default value is 192. The interface does not need to be brought down and up again before a change takes effect. .El .Sh SEE ALSO .Xr altq 4 , .Xr arp 4 , .Xr intro 4 , .Xr miibus 4 , .Xr netintro 4 , .Xr pci 4 , .Xr polling 4 , .Xr rgephy 4 , -.Xr sysctl 8 , -.Xr ifconfig 8 +.Xr ifconfig 8 , +.Xr sysctl 8 .Sh HISTORY The .Nm device driver first appeared in .Ox 3.9 , and then in .Fx 7.0 . .Sh AUTHORS .An -nosplit The .Nm driver was written by .An Jonathan Gray Aq Mt jsg@openbsd.org and .An Damien Bergamini Aq Mt damien@openbsd.org . The .Nm driver was ported to .Fx by .An Shigeaki Tagashira Aq Mt shigeaki@se.hiroshima-u.ac.jp . Index: projects/sendfile/share/man/man4/ng_ether_echo.4 =================================================================== --- projects/sendfile/share/man/man4/ng_ether_echo.4 (revision 276056) +++ projects/sendfile/share/man/man4/ng_ether_echo.4 (revision 276057) @@ -1,77 +1,77 @@ .\" Copyright (c) 1996-1999 Whistle Communications, Inc. .\" All rights reserved. .\" .\" Subject to the following obligations and disclaimer of warranty, use and .\" redistribution of this software, in source or object code forms, with or .\" without modifications are expressly permitted by Whistle Communications; .\" provided, however, that: .\" 1. Any and all reproductions of the source or object code must include the .\" copyright notice above and the following disclaimer of warranties; and .\" 2. No rights are granted, in any manner or form, to use Whistle .\" Communications, Inc. trademarks, including the mark "WHISTLE .\" COMMUNICATIONS" on advertising, endorsements, or otherwise except as .\" such appears in the above copyright notice or in the software. .\" .\" THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND .\" TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO .\" REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, .\" INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. .\" WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY .\" REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS .\" SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. .\" IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES .\" RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING .\" WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, .\" PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR .\" SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY .\" OF SUCH DAMAGE. .\" .\" Author: Archie Cobbs .\" .\" $FreeBSD$ .\" $Whistle: ng_echo.8,v 1.4 1999/01/25 23:46:26 archie Exp $ .\" .Dd December 24, 2008 .Dt NG_ETHER_ECHO 4 .Os .Sh NAME .Nm ng_ether_echo .Nd netgraph ether_echo node type .Sh SYNOPSIS .In netgraph/ng_ether_echo.h .Sh DESCRIPTION The .Nm ether_echo node type reflects all data and control messages back to the sender. It assumes (and does not check) that the packet is an ethernet frame, and swaps the source and destination addresses before echoing it. This node type is used for testing and debugging. .Sh HOOKS A .Nm ether_echo node accepts any request to connect, regardless of the hook name, as long as the name is unique. .Sh CONTROL MESSAGES This node type supports only the generic control messages. Any other control messages are reflected back to the sender. .Sh SHUTDOWN This node shuts down upon receipt of a .Dv NGM_SHUTDOWN control message, or when all hooks have been disconnected. .Sh SEE ALSO .Xr netgraph 4 , -.Xr ng_hole 4 , .Xr ng_echo 4 , .Xr ng_ether 4 , +.Xr ng_hole 4 , .Xr ngctl 8 .Sh HISTORY The .Nm node type was implemented in .Fx 8.0 . .Sh AUTHORS .An Julian Elischer Aq Mt julian@FreeBSD.org Index: projects/sendfile/share/man/man4/ng_netflow.4 =================================================================== --- projects/sendfile/share/man/man4/ng_netflow.4 (revision 276056) +++ projects/sendfile/share/man/man4/ng_netflow.4 (revision 276057) @@ -1,356 +1,356 @@ .\" Copyright (c) 2004-2005 Gleb Smirnoff .\" 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$ .\" .Dd December 10, 2012 .Dt NG_NETFLOW 4 .Os .Sh NAME .Nm ng_netflow .Nd Cisco's NetFlow implementation .Sh SYNOPSIS .In sys/types.h .In netinet/in.h .In netgraph/netflow/ng_netflow.h .Sh DESCRIPTION The .Nm node implements Cisco's NetFlow export protocol on a router running .Fx . The .Nm node listens for incoming traffic and identifies unique flows in it. Flows are distinguished by endpoint IP addresses, TCP/UDP port numbers, ToS and input interface. Expired flows are exported out of the node in NetFlow version 5/9 UDP datagrams. Expiration reason can be one of the following: .Bl -dash .It RST or FIN TCP segment. .It Active timeout. Flows cannot live more than the specified period of time. The default is 1800 seconds (30 minutes). .It Inactive timeout. A flow was inactive for the specified period of time. The default is 15 seconds. .El .Pp Node supports IPv6 accounting (NetFlow v9 only) and is aware of multiple fibs. Different fibs are mapped to different domain_id in NetFlow V9 and different engine_id in NetFlow V5. .Sh HOOKS This node type supports up to .Dv NG_NETFLOW_MAXIFACES (default 65536) hooks named .Va iface0 , iface1 , etc., and the same number of hooks named .Va out0 , out1 , etc., plus two export hooks: .Va export (for NetFlow version 5) and .Va export9 (for NetFlow version 9). Export can be done simultaneously for all supported export hooks. By default (ingress NetFlow enabled) node does NetFlow accounting of data received on .Va iface* hooks. If corresponding .Va out hook is connected, unmodified data is bypassed to it, otherwise data is freed. If data is received on .Va out hook, it is bypassed to corresponding .Va iface hook without any processing (egress NetFlow disabled by default). When full export datagram for an export protocol is built it is sent to the .Va export or .Va export9 hook. In normal operation, one (or more) export hook is connected to the .Va inet/dgram/udp hook of the .Xr ng_ksocket 4 node. .Sh CONTROL MESSAGES This node type supports the generic control messages, plus the following: .Bl -tag -width foo .It Dv NGM_NETFLOW_INFO Pq Ic info Returns some node statistics and the current timeout values in a .Vt "struct ng_netflow_info" . .It Dv NGM_NETFLOW_IFINFO Pq Ic ifinfo Returns information about the .Va iface Ns Ar N hook. The hook number is passed as an argument. .It Dv NGM_NETFLOW_SETDLT Pq Ic setdlt Sets data link type on the .Va iface Ns Ar N hook. Currently, supported types are .Cm DLT_RAW (raw IP datagrams) and .Cm DLT_EN10MB (Ethernet). DLT_ definitions can be found in .In net/bpf.h header. Currently used values are 1 for .Cm DLT_EN10MB and 12 for .Cm DLT_RAW . This message type uses .Vt "struct ng_netflow_setdlt" as an argument: .Bd -literal -offset 4n struct ng_netflow_setdlt { uint16_t iface; /* which iface dlt change */ uint8_t dlt; /* DLT_XXX from bpf.h */ }; .Ed .Pp The requested .Va iface Ns Ar N hook must already be connected, otherwise message send operation will return an error. .It Dv NGM_NETFLOW_SETIFINDEX Pq Ic setifindex In some cases, .Nm may be unable to determine the input interface index of a packet. This can happen if traffic enters the .Nm node before it comes to the system interface's input queue. An example of such a setup is capturing a traffic .Em between synchronous data line and .Xr ng_iface 4 . In this case, the input index should be associated with a given hook. The interface's index can be determined via .Xr if_nametoindex 3 from userland. This message requires .Vt "struct ng_netflow_setifindex" as an argument: .Bd -literal -offset 4n struct ng_netflow_setifindex { uint16_t iface; /* which iface index change */ uint16_t index; /* new index */ }; .Ed .Pp The requested .Va iface Ns Ar N hook must already be connected, otherwise the message send operation will return an error. .It Dv NGM_NETFLOW_SETTIMEOUTS Pq Ic settimeouts Sets values in seconds for NetFlow active/inactive timeouts. This message requires .Vt "struct ng_netflow_settimeouts" as an argument: .Bd -literal -offset 4n struct ng_netflow_settimeouts { uint32_t inactive_timeout; /* flow inactive timeout */ uint32_t active_timeout; /* flow active timeout */ }; .Ed .It Dv NGM_NETFLOW_SETCONFIG Pq Ic setconfig Sets configuration for the specified interface. This message requires .Vt "struct ng_netflow_setconfig" as an argument: .Bd -literal -offset 4n struct ng_netflow_setconfig { uint16_t iface; /* which iface config change */ uint32_t conf; /* new config */ #define NG_NETFLOW_CONF_INGRESS 1 #define NG_NETFLOW_CONF_EGRESS 2 #define NG_NETFLOW_CONF_ONCE 4 #define NG_NETFLOW_CONF_THISONCE 8 #define NG_NETFLOW_CONF_NOSRCLOOKUP 16 #define NG_NETFLOW_CONF_NODSTLOOKUP 32 }; .Ed .Pp Configuration is a bitmask of several options. Option NG_NETFLOW_CONF_INGRESS enabled by default enables ingress NetFlow generation (for data coming from ifaceX hook). Option .Va NG_NETFLOW_CONF_EGRESS enables egress NetFlow (for data coming from outX hook). Option .Va NG_NETFLOW_CONF_ONCE defines that packet should be accounted only once if it several times passes via netflow node. Option .Va NG_NETFLOW_CONF_THISONCE defines that packet should be accounted only once if it several times passes via exactly this netflow node. These two options are important to avoid duplicate accounting when both ingress and egress NetFlow are enabled. Option .Va NG_NETFLOW_CONF_NOSRCLOOKUP skips radix lookup on flow source address used to fill in network mask. Option .Va NG_NETFLOW_CONF_NODSTLOOKUP skips radix lookup on destination (which fills egress interface id, destination mask and gateway). If one doesn't need data provided by lookups, he/she can disable them, to reduce load on routers. .It Dv NGM_NETFLOW_SETTEMPLATE Pq Ic settemplate Sets various timeouts to announce data flow templates (NetFlow v9-specific). This message requires .Vt "struct ng_netflow_settemplate" as an argument: .Bd -literal -offset 4n struct ng_netflow_settemplate { uint16_t time; /* max time between announce */ uint16_t packets; /* max packets between announce */ }; .Ed .Pp Value of time field represents time in seconds to re-announce data templates. Value of packets field represents maximum packets count between re-announcing data templates. .It Dv NGM_NETFLOW_SETMTU Pq Ic setmtu Sets export interface MTU to build packets of specified size (NetFlow v9-specific). This message requires .Vt "struct ng_netflow_setmtu" as an argument: .Bd -literal -offset 4n struct ng_netflow_setemtu { uint16_t mtu; /* MTU for packet */ }; .Ed .Pp Default is 1500 bytes. .It Dv NGM_NETFLOW_SHOW This control message asks a node to dump the entire contents of the flow cache. It is called from .Xr flowctl 8 , not directly from .Xr ngctl 8 . .It Dv NGM_NETFLOW_V9INFO Pq Ic v9info Returns some NetFlow v9 related values in a .Bd -literal -offset 4n struct ng_netflow_v9info { uint16_t templ_packets; /* v9 template packets */ uint16_t templ_time; /* v9 template time */ uint16_t mtu; /* v9 MTU */ }; .Ed .El .Sh SHUTDOWN This node shuts down upon receipt of a .Dv NGM_SHUTDOWN control message, or when all hooks have been disconnected. .Sh EXAMPLES The simplest possible configuration is one Ethernet interface, where flow collecting is enabled. .Bd -literal -offset indent /usr/sbin/ngctl -f- <<-SEQ mkpeer fxp0: netflow lower iface0 name fxp0:lower netflow connect fxp0: netflow: upper out0 mkpeer netflow: ksocket export inet/dgram/udp msg netflow:export connect inet/10.0.0.1:4444 SEQ .Ed .Pp This is a more complicated example of a router with 2 NetFlow-enabled interfaces .Li fxp0 and .Li ng0 . Note that the .Va ng0: node in this example is connected to .Xr ng_tee 4 . The latter sends us a copy of IP packets, which we analyze and free. On .Va fxp0: we do not use tee, but send packets back to either node. .Bd -literal -offset indent /usr/sbin/ngctl -f- <<-SEQ # connect ng0's tee to iface0 hook mkpeer ng0:inet netflow right2left iface0 name ng0:inet.right2left netflow # set DLT to raw mode msg netflow: setdlt { iface=0 dlt=12 } # set interface index (5 in this example) msg netflow: setifindex { iface=0 index=5 } # Connect fxp0: to iface1 and out1 hook connect fxp0: netflow: lower iface1 connect fxp0: netflow: upper out1 # Create ksocket node on export hook, and configure it # to send exports to proper destination mkpeer netflow: ksocket export inet/dgram/udp msg netflow:export connect inet/10.0.0.1:4444 SEQ .Ed .Sh SEE ALSO -.Xr netgraph 4 , .Xr setfib 2 , +.Xr netgraph 4 , .Xr ng_ether 4 , .Xr ng_iface 4 , .Xr ng_ksocket 4 , .Xr ng_tee 4 , .Xr flowctl 8 , .Xr ngctl 8 .Rs .%A B. Claise, Ed .%T "Cisco Systems NetFlow Services Export Version 9" .%O RFC 3954 .Re .Pp .Pa http://www.cisco.com/en/US/docs/ios/solutions_docs/netflow/nfwhite.html .Sh AUTHORS .An -nosplit The .Nm node type was written by .An Gleb Smirnoff Aq Mt glebius@FreeBSD.org , .An Alexander Motin Aq Mt mav@FreeBSD.org , .An Alexander Chernikov Aq Mt melifaro@ipfw.ru . The initial code was based on .Nm ng_ipacct written by .An Roman V. Palagin Aq Mt romanp@unshadow.net . .Sh BUGS Cache snapshot obtained via .Dv NGM_NETFLOW_SHOW command may lack some percentage of entries under severe load. .Pp The .Nm node type does not fill in AS numbers. This is due to the lack of necessary information in the kernel routing table. However, this information can be injected into the kernel from a routing daemon such as GNU Zebra. This functionality may become available in future releases. Index: projects/sendfile/share/man/man4/nvram2env.4 =================================================================== --- projects/sendfile/share/man/man4/nvram2env.4 (revision 276056) +++ projects/sendfile/share/man/man4/nvram2env.4 (revision 276057) @@ -1,116 +1,116 @@ .\" Copyright (c) 2011 Aleksandr Rybalko .\" 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$ .\" .Dd April 3, 2011 .Dt NVRAM2ENV 4 .Os .Sh NAME .Nm nvram2env .Nd "copy nvram-like data into kernel environment" .Sh SYNOPSIS .Cd "device nvram2env" .Sh DESCRIPTION .Nm implements a simple method of reading the NVRAM-like data and information stored in flash and storing it in the kernel environment. It can then be used by various device drivers at boot-time. .Pp The NVRAM-like data is an array of zero terminated strings. Each string contains the string name, "=" delimiter and the string value. .Pp .Nm copies the environment values into kernel environment using the kernel setenv call. .Pp Configuration of .Nm is done in .Xr device.hints 5 defining the NVRAM base address, fallback base address, maxsize and flags. .Pp .Nm is currently MIPS-specific. .Ss base base - physical address where data block is stored. .Ss fallbackbase fallbackbase - physical address where data block is stored, but only if not found at base. .Ss maxsize maxsize - maximum size of data block. .Ss flags flags - control flags, used to select nvram type and enable/disable CRC check. .Bl -tag -width indent .It Fa 0x0001 Avoid CRC checking. Currently CRC checking is not implemented, so to be future compatible, please set it to "1". .It Fa 0x0002 Use format "Generic", skip uint32_t field, then zero terminating array of strings. .It Fa 0x0004 Use Broadcom CFE format. uint32_t signature "FLSH", uint32_t size, three unused fields uint32_t, then data. .It Fa 0x0008 Use U-Boot format, uint32_t crc, then zero terminating array of strings. .El .Sh EXAMPLES Usage in U-Boot case: .Bd -literal -offset indent hint.nvram.0.base=0x1f030000 hint.nvram.0.maxsize=0x2000 hint.nvram.0.flags=3 # 1 = No check, 2 = Format Generic hint.nvram.1.base=0x1f032000 hint.nvram.1.maxsize=0x4000 hint.nvram.1.flags=3 # 1 = No check, 2 = Format Generic .Ed .Pp CFE nvram with fallback: .Bd -literal -offset indent hint.nvram.0.base=0x1fff8000 hint.nvram.0.fallbackbase=0x1fc00400 hint.nvram.0.flags=4 # 4 = Format Broadcom .Ed .Pp but seems for CFE nvram preferred to read both blocks: .Pp NVRAM partition: Static, CFE internal .Bd -literal -offset indent hint.nvram.0.flags=0x05 # Broadcom + nocheck hint.nvram.0.base=0x1fc00400 .Ed .Pp Dynamic, editable form CFE, override values from first .Bd -literal -offset indent hint.nvram.1.flags=0x05 # Broadcom + nocheck hint.nvram.1.base=0x1cff8000 .Ed .Sh SEE ALSO .Xr kenv 1 , -.Xr kenv 2 . +.Xr kenv 2 .Sh HISTORY .Nm first appeared in .Fx 9.0 . .Sh AUTHORS .An Aleksandr Rybalko Aq Mt ray@ddteam.net Index: projects/sendfile/share/man/man4/pass.4 =================================================================== --- projects/sendfile/share/man/man4/pass.4 (revision 276056) +++ projects/sendfile/share/man/man4/pass.4 (revision 276057) @@ -1,120 +1,120 @@ .\" .\" Copyright (c) 1998, 1999 Kenneth D. Merry. .\" 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. The name of the author may not be used to endorse or promote products .\" derived from this software without specific prior written permission. .\" .\" 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$ .\" .Dd October 10, 1998 .Dt PASS 4 .Os .Sh NAME .Nm pass .Nd CAM application passthrough driver .Sh SYNOPSIS .Cd device pass .Sh DESCRIPTION The .Nm driver provides a way for userland applications to issue CAM CCBs to the kernel. .Pp Since the .Nm driver allows direct access to the CAM subsystem, system administrators should exercise caution when granting access to this driver. If used improperly, this driver can allow userland applications to crash a machine or cause data loss. .Pp The .Nm driver attaches to every .Tn SCSI device found in the system. Since it attaches to every device, it provides a generic means of accessing .Tn SCSI devices, and allows the user to access devices which have no "standard" peripheral driver associated with them. .Sh KERNEL CONFIGURATION It is only necessary to configure one .Nm device in the kernel; .Nm devices are automatically allocated as .Tn SCSI devices are found. .Sh IOCTLS .Bl -tag -width 012345678901234 .It CAMIOCOMMAND This ioctl takes most kinds of CAM CCBs and passes them through to the CAM transport layer for action. Note that some CCB types are not allowed through the passthrough device, and must be sent through the .Xr xpt 4 device instead. Some examples of xpt-only CCBs are XPT_SCAN_BUS, XPT_DEV_MATCH, XPT_RESET_BUS, XPT_SCAN_LUN, XPT_ENG_INQ, and XPT_ENG_EXEC. These CCB types have various attributes that make it illogical or impossible to service them through the passthrough interface. .It CAMGETPASSTHRU This ioctl takes an XPT_GDEVLIST CCB, and returns the passthrough device corresponding to the device in question. Although this ioctl is available through the .Nm driver, it is of limited use, since the caller must already know that the device in question is a passthrough device if they are issuing this ioctl. It is probably more useful to issue this ioctl through the .Xr xpt 4 device. .El .Sh FILES .Bl -tag -width /dev/passn -compact .It Pa /dev/pass Ns Ar n Character device nodes for the .Nm driver. There should be one of these for each device accessed through the CAM subsystem. .El .Sh DIAGNOSTICS None. .Sh SEE ALSO .Xr cam 3 , -.Xr cam 4 , .Xr cam_cdbparse 3 , +.Xr cam 4 , .Xr xpt 4 , .Xr camcontrol 8 .Sh HISTORY The CAM passthrough driver first appeared in .Fx 3.0 . .Sh AUTHORS .An Kenneth Merry Aq Mt ken@FreeBSD.org .Sh BUGS It might be nice to have a way to asynchronously send CCBs through the passthrough driver. This would probably require some sort of read/write interface or an asynchronous ioctl interface. Index: projects/sendfile/share/man/man4/pccbb.4 =================================================================== --- projects/sendfile/share/man/man4/pccbb.4 (revision 276056) +++ projects/sendfile/share/man/man4/pccbb.4 (revision 276057) @@ -1,183 +1,183 @@ .\" .\" Copyright (c) 2002-2003 M. Warner Losh .\" 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. The name of the author may not be used to endorse or promote products .\" derived from this software without specific prior written permission. .\" .\" 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$ .\" .Dd July 21, 2004 .Dt PCCBB 4 .Os .Sh NAME .Nm pccbb .Nd cardbus bridge driver .Sh SYNOPSIS .Cd device cbb .Cd device pccard .Cd device cardbus .Cd device exca .Sh DESCRIPTION The .Nm driver implements the Yenta specification for CardBus bridges. .Pp The following PCI cardbus and pcmcia bridges are supported: .Pp .Bl -item -compact .It Cirrus Logic PD6832 .It Cirrus Logic PD6833 .It Cirrus Logic PD6834 .Pp .It O2micro OZ6812 .It O2micro OZ6832 .It O2micro OZ6833 .It O2micro OZ6836 .It O2micro OZ6860 .It O2micro OZ6872 .It O2micro OZ6912 .It O2micro OZ6922 .It O2micro OZ6933 .It O2micro OZ6972 .It O2Micro OZ711E1 .It O2Micro OZ711M1 .El .Bl -item -compact .It Ricoh RL4C475 .It Ricoh RL4C476 .It Ricoh RL4C477 .It Ricoh RL4C478 .Pp .It TI PCI-1031 .It TI PCI-1130 .It TI PCI-1131 .It TI PCI-1210 .It TI PCI-1211 .It TI PCI-1220 .It TI PCI-1221 .It TI PCI-1225 .It TI PCI-1250 .It TI PCI-1251 .It TI PCI-1251B .It TI PCI-1260 .It TI PCI-1260B .It TI PCI-1410 .It TI PCI-1420 .It TI PCI-1450 .It TI PCI-1451 .It TI PCI-1510 .It TI PCI-1515 .It TI PCI-1520 .It TI PCI-1530 .It TI PCI-1620 .It TI PCI-4410 .It TI PCI-4450 .It TI PCI-4451 .It TI PCI-4510 .It TI PCI-4520 .It TI PCI-[67]x[12]1 .It TI PCI-[67]x20 .It ENE CB710 .It ENE CB720 .It ENE CB1211 .It ENE CB1255 .It ENE CB1410 .It ENE CB1420 .Pp .It Toshiba ToPIC95 .It Toshiba ToPIC95B .It Toshiba ToPIC97 .It Toshiba ToPIC100 .El .Sh TUNABLES The driver supports the following tunable parameters, which may be added to .Pa /boot/loader.conf or set via the .Xr sysctl 8 command: .Bl -tag -width ".Cm hw.cbb.debug" -compact .It Cm hw.cbb.debug Non-zero values cause more verbose information to be printed to aid in debugging problems with the bridge chipset. .El .Sh SEE ALSO .Xr cardbus 4 , -.Xr pccard 4 , -.Xr exca 4 +.Xr exca 4 , +.Xr pccard 4 Index: projects/sendfile/share/man/man4/pflog.4 =================================================================== --- projects/sendfile/share/man/man4/pflog.4 (revision 276056) +++ projects/sendfile/share/man/man4/pflog.4 (revision 276057) @@ -1,107 +1,107 @@ .\" $OpenBSD: pflog.4,v 1.10 2007/05/31 19:19:51 jmc Exp $ .\" .\" Copyright (c) 2001 Tobias Weingartner .\" 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 ``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 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$ .\" -.Dd May 31 2007 +.Dd May 31, 2007 .Dt PFLOG 4 .Os .Sh NAME .Nm pflog .Nd packet filter logging interface .Sh SYNOPSIS .Cd "device pflog" .Sh DESCRIPTION The .Nm pflog interface is a device which makes visible all packets logged by the packet filter, .Xr pf 4 . Logged packets can easily be monitored in real time by invoking .Xr tcpdump 1 on the .Nm interface, or stored to disk using .Xr pflogd 8 . .Pp The pflog0 interface is created automatically at boot if both .Xr pf 4 and .Xr pflogd 8 are enabled; further instances can be created using .Xr ifconfig 8 . .Pp Each packet retrieved on this interface has a header associated with it of length .Dv PFLOG_HDRLEN . This header documents the address family, interface name, rule number, reason, action, and direction of the packet that was logged. This structure, defined in .Aq Pa net/if_pflog.h looks like .Bd -literal -offset indent struct pfloghdr { u_int8_t length; sa_family_t af; u_int8_t action; u_int8_t reason; char ifname[IFNAMSIZ]; char ruleset[PF_RULESET_NAME_SIZE]; u_int32_t rulenr; u_int32_t subrulenr; uid_t uid; pid_t pid; uid_t rule_uid; pid_t rule_pid; u_int8_t dir; u_int8_t pad[3]; }; .Ed .Sh EXAMPLES Create a .Nm interface and monitor all packets logged on it: .Bd -literal -offset indent # ifconfig pflog1 up # tcpdump -n -e -ttt -i pflog1 .Ed .Sh SEE ALSO .Xr inet 4 , .Xr inet6 4 , .Xr netintro 4 , .Xr pf 4 , .Xr ifconfig 8 , .Xr pflogd 8 , .Xr tcpdump 1 .Sh HISTORY The .Nm device first appeared in .Ox 3.0 . .\" .Sh BUGS .\" Anything here? Index: projects/sendfile/share/man/man4/pfsync.4 =================================================================== --- projects/sendfile/share/man/man4/pfsync.4 (revision 276056) +++ projects/sendfile/share/man/man4/pfsync.4 (revision 276057) @@ -1,229 +1,229 @@ .\" $OpenBSD: pfsync.4,v 1.28 2009/02/17 10:05:18 dlg Exp $ .\" .\" Copyright (c) 2002 Michael Shalayeff .\" Copyright (c) 2003-2004 Ryan McBride .\" 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 ``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 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 MIND, .\" 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$ .\" -.Dd December 20 2011 +.Dd December 20, 2011 .Dt PFSYNC 4 .Os .Sh NAME .Nm pfsync .Nd packet filter state table sychronisation interface .Sh SYNOPSIS .Cd "device pfsync" .Sh DESCRIPTION The .Nm interface is a pseudo-device which exposes certain changes to the state table used by .Xr pf 4 . State changes can be viewed by invoking .Xr tcpdump 1 on the .Nm interface. If configured with a physical synchronisation interface, .Nm will also send state changes out on that interface, and insert state changes received on that interface from other systems into the state table. .Pp By default, all local changes to the state table are exposed via .Nm . State changes from packets received by .Nm over the network are not rebroadcast. Updates to states created by a rule marked with the .Ar no-sync keyword are ignored by the .Nm interface (see .Xr pf.conf 5 for details). .Pp The .Nm interface will attempt to collapse multiple state updates into a single packet where possible. The maximum number of times a single state can be updated before a .Nm packet will be sent out is controlled by the .Ar maxupd parameter to ifconfig (see .Xr ifconfig 8 and the example below for more details). The sending out of a .Nm packet will be delayed by a maximum of one second. .Sh NETWORK SYNCHRONISATION States can be synchronised between two or more firewalls using this interface, by specifying a synchronisation interface using .Xr ifconfig 8 . For example, the following command sets fxp0 as the synchronisation interface: .Bd -literal -offset indent # ifconfig pfsync0 syncdev fxp0 .Ed .Pp By default, state change messages are sent out on the synchronisation interface using IP multicast packets to the 244.0.0.240 group address. An alternative destination address for .Nm packets can be specified using the .Ic syncpeer keyword. This can be used in combination with .Xr ipsec 4 to protect the synchronisation traffic. In such a configuration, the syncdev should be set to the .Xr enc 4 interface, as this is where the traffic arrives when it is decapsulated, e.g.: .Bd -literal -offset indent # ifconfig pfsync0 syncpeer 10.0.0.2 syncdev enc0 .Ed .Pp It is important that the pfsync traffic be well secured as there is no authentication on the protocol and it would be trivial to spoof packets which create states, bypassing the pf ruleset. Either run the pfsync protocol on a trusted network \- ideally a network dedicated to pfsync messages such as a crossover cable between two firewalls, or specify a peer address and protect the traffic with .Xr ipsec 4 . .Pp .Nm has the following .Xr sysctl 8 tunables: .Bl -tag -width ".Va net.pfsync" .It Va net.pfsync.carp_demotion_factor Value added to .Va net.inet.carp.demotion while .Nm tries to perform its bulk update. See .Xr carp 4 for more information. Default value is 240. .El .Sh EXAMPLES .Nm and .Xr carp 4 can be used together to provide automatic failover of a pair of firewalls configured in parallel. One firewall will handle all traffic until it dies, is shut down, or is manually demoted, at which point the second firewall will take over automatically. .Pp Both firewalls in this example have three .Xr sis 4 interfaces. sis0 is the external interface, on the 10.0.0.0/24 subnet; sis1 is the internal interface, on the 192.168.0.0/24 subnet; and sis2 is the .Nm interface, using the 192.168.254.0/24 subnet. A crossover cable connects the two firewalls via their sis2 interfaces. On all three interfaces, firewall A uses the .254 address, while firewall B uses .253. The interfaces are configured as follows (firewall A unless otherwise indicated): .Pp Interfaces configuration in .Pa /etc/rc.conf : .Bd -literal -offset indent network_interfaces="lo0 sis0 sis1 sis2" ifconfig_sis0="10.0.0.254/24" ifconfig_sis0_alias0="inet 10.0.0.1/24 vhid 1 pass foo" ifconfig_sis1="192.168.0.254/24" ifconfig_sis1_alias0="inet 192.168.0.1/24 vhid 2 pass bar" ifconfig_sis2="192.168.254.254/24" pfsync_enable="YES" pfsync_syncdev="sis2" .Ed .Pp .Xr pf 4 must also be configured to allow .Nm and .Xr carp 4 traffic through. The following should be added to the top of .Pa /etc/pf.conf : .Bd -literal -offset indent pass quick on { sis2 } proto pfsync keep state (no-sync) pass on { sis0 sis1 } proto carp keep state (no-sync) .Ed .Pp It is preferable that one firewall handle the forwarding of all the traffic, therefore the .Ar advskew on the backup firewall's .Xr carp 4 vhids should be set to something higher than the primary's. For example, if firewall B is the backup, its carp1 configuration would look like this: would look like this: .Bd -literal -offset indent ifconfig_sis1_alias0="inet 192.168.0.1/24 vhid 2 pass bar advskew 100" .Ed .Pp The following must also be added to .Pa /etc/sysctl.conf : .Bd -literal -offset indent net.inet.carp.preempt=1 .Ed .Sh SEE ALSO .Xr bpf 4 , .Xr carp 4 , .Xr enc 4 , .Xr inet 4 , .Xr inet6 4 , .Xr ipsec 4 , .Xr netintro 4 , .Xr pf 4 , .Xr pf.conf 5 , .Xr protocols 5 , .Xr rc.conf 5 , .Xr ifconfig 8 , .Xr tcpdump 1 .Sh HISTORY The .Nm device first appeared in .Ox 3.3 . It was first imported to .Fx 5.3 . .Pp The .Nm protocol and kernel implementation were significantly modified in .Fx 9.0 . The newer protocol is not compatible with older one and will not interoperate with it. Index: projects/sendfile/share/man/man4/pts.4 =================================================================== --- projects/sendfile/share/man/man4/pts.4 (revision 276056) +++ projects/sendfile/share/man/man4/pts.4 (revision 276057) @@ -1,158 +1,158 @@ .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. 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. 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. .\" .\" @(#)pty.4 8.2 (Berkeley) 11/30/93 .\" $FreeBSD$ .\" .Dd August 20, 2008 .Dt PTS 4 .Os .Sh NAME .Nm pts .Nd pseudo-terminal driver .Sh DESCRIPTION The .Nm driver provides support for a device-pair termed a .Em pseudo-terminal . A pseudo-terminal is a pair of character devices, a .Em master device and a .Em slave device. The slave device provides to a process an interface identical to that described in .Xr tty 4 . However, whereas all other devices which provide the interface described in .Xr tty 4 have a hardware device of some sort behind them, the slave device has, instead, another process manipulating it through the master half of the pseudo-terminal. That is, anything written on the master device is given to the slave device as input and anything written on the slave device is presented as input on the master device. .Pp The following .Xr ioctl 2 calls apply only to pseudo-terminals: .Bl -tag -width TIOCPTMASTER .It Dv TIOCPKT Enable/disable .Em packet mode. Packet mode is enabled by specifying (by reference) a nonzero parameter and disabled by specifying (by reference) a zero parameter. When applied to the master side of a pseudo-terminal, each subsequent .Xr read 2 from the terminal will return data written on the slave part of the pseudo-terminal preceded by a zero byte (symbolically defined as .Dv TIOCPKT_DATA ) , or a single byte reflecting control status information. In the latter case, the byte is an inclusive-or of zero or more of the bits: .Bl -tag -width TIOCPKT_FLUSHWRITE .It Dv TIOCPKT_FLUSHREAD whenever the read queue for the terminal is flushed. .It Dv TIOCPKT_FLUSHWRITE whenever the write queue for the terminal is flushed. .It Dv TIOCPKT_STOP whenever output to the terminal is stopped a la .Ql ^S . .It Dv TIOCPKT_START whenever output to the terminal is restarted. .It Dv TIOCPKT_DOSTOP whenever .Dv VSTOP is .Ql ^S and .Dv VSTART is .Ql ^Q . .It Dv TIOCPKT_NOSTOP whenever the start and stop characters are not .Ql ^S/^Q . .El .Pp While this mode is in use, the presence of control status information to be read from the master side may be detected by a .Xr select 2 for exceptional conditions. .Pp This mode is used by .Xr rlogin 1 and .Xr rlogind 8 to implement a remote-echoed, locally .Ql ^S/^Q flow-controlled remote login with proper back-flushing of output; it can be used by other similar programs. .It Dv TIOCGPTN Obtain device unit number, which can be used to generate the filename of the pseudo-terminal slave device. This .Xr ioctl 2 should not be used directly. Instead, the .Xr ptsname 3 function should be used. .It Dv TIOCPTMASTER Determine whether the file descriptor is pointing to a pseudo-terminal master device. This .Xr ioctl 2 should not be used directly. It is used to implement routines like .Xr grantpt 3 . .El .Sh FILES The files used by this pseudo-terminals implementation are: .Bl -tag -width ".Pa /dev/pts/[num]" .It Pa /dev/pts/[num] Pseudo-terminal slave devices. .El .Sh DIAGNOSTICS None. .Sh SEE ALSO -.Xr grantpt 3 , .Xr posix_openpt 2 , +.Xr grantpt 3 , .Xr ptsname 3 , .Xr pty 4 , .Xr tty 4 .Sh HISTORY A pseudo-terminal driver appeared in .Bx 4.2 . In .Fx 8.0 , it was replaced with the .Nm driver. Index: projects/sendfile/share/man/man4/sa.4 =================================================================== --- projects/sendfile/share/man/man4/sa.4 (revision 276056) +++ projects/sendfile/share/man/man4/sa.4 (revision 276057) @@ -1,311 +1,311 @@ .\" Copyright (c) 1996 .\" Julian Elischer . 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$ .\" .Dd August 23, 2013 .Dt SA 4 .Os .Sh NAME .Nm sa .Nd SCSI Sequential Access device driver .Sh SYNOPSIS .Cd device sa .Sh DESCRIPTION The .Nm driver provides support for all .Tn SCSI devices of the sequential access class that are attached to the system through a supported .Tn SCSI Host Adapter. The sequential access class includes tape and other linear access devices. .Pp A .Tn SCSI Host adapter must also be separately configured into the system before a .Tn SCSI sequential access device can be configured. .Sh MOUNT SESSIONS The .Nm driver is based around the concept of a .Dq Em mount session , which is defined as the period between the time that a tape is mounted, and the time when it is unmounted. Any parameters set during a mount session remain in effect for the remainder of the session or until replaced. The tape can be unmounted, bringing the session to a close in several ways. These include: .Bl -enum .It Closing a `rewind device', referred to as sub-mode 00 below. An example is .Pa /dev/sa0 . .It Using the MTOFFL .Xr ioctl 2 command, reachable through the .Sq Cm offline command of .Xr mt 1 . .El .Pp It should be noted that tape devices are exclusive open devices, except in the case where a control mode device is opened. In the latter case, exclusive access is only sought when needed (e.g., to set parameters). .Sh SUB-MODES Bits 0 and 1 of the minor number are interpreted as .Sq sub-modes . The sub-modes differ in the action taken when the device is closed: .Bl -tag -width XXXX .It 00 A close will rewind the device; if the tape has been written, then a file mark will be written before the rewind is requested. The device is unmounted. .It 01 A close will leave the tape mounted. If the tape was written to, a file mark will be written. No other head positioning takes place. Any further reads or writes will occur directly after the last read, or the written file mark. .It 10 A close will rewind the device. If the tape has been written, then a file mark will be written before the rewind is requested. On completion of the rewind an unload command will be issued. The device is unmounted. .El .Sh BLOCKING MODES .Tn SCSI tapes may run in either .Sq Em variable or .Sq Em fixed block-size modes. Most .Tn QIC Ns -type devices run in fixed block-size mode, where most nine-track tapes and many new cartridge formats allow variable block-size. The difference between the two is as follows: .Bl -inset .It Variable block-size: Each write made to the device results in a single logical record written to the tape. One can never read or write .Em part of a record from tape (though you may request a larger block and read a smaller record); nor can one read multiple blocks. Data from a single write is therefore read by a single read. The block size used may be any value supported by the device, the .Tn SCSI adapter and the system (usually between 1 byte and 64 Kbytes, sometimes more). .Pp When reading a variable record/block from the tape, the head is logically considered to be immediately after the last item read, and before the next item after that. If the next item is a file mark, but it was never read, then the next process to read will immediately hit the file mark and receive an end-of-file notification. .It Fixed block-size: Data written by the user is passed to the tape as a succession of fixed size blocks. It may be contiguous in memory, but it is considered to be a series of independent blocks. One may never write an amount of data that is not an exact multiple of the blocksize. One may read and write the same data as a different set of records. In other words, blocks that were written together may be read separately, and vice-versa. .Pp If one requests more blocks than remain in the file, the drive will encounter the file mark. As there is some data to return (unless there were no records before the file mark), the read will succeed, returning that data. The next read will return immediately with a value of 0. (As above, if the file mark is never read, it remains for the next process to read if in no-rewind mode.) .El .Sh BLOCK SIZES By default, the driver will NOT accept reads or writes to a tape device that are larger than may be written to or read from the mounted tape using a single write or read request. Because of this, the application author may have confidence that his wishes are respected in terms of the block size written to tape. For example, if the user tries to write a 256KB block to the tape, but the controller can handle no more than 128KB, the write will fail. The previous .Fx behavior, prior to .Fx 10.0, was to break up large reads or writes into smaller blocks when going to the tape. The problem with that behavior, though, is that it hides the actual on-tape block size from the application writer, at least in variable block mode. .Pp If the user would like his large reads and writes broken up into separate pieces, he may set the following loader tunables. Note that these tunables WILL GO AWAY in .Fx 11.0 . They are provided for transition purposes only. .Bl -tag -width 12 .It kern.cam.sa.allow_io_split .Pp This variable, when set to 1, will configure all .Nm devices to split large buffers into smaller pieces when needed. .It kern.cam.sa.%d.allow_io_split .Pp This variable, when set to 1, will configure the given .Nm unit to split large buffers into multiple pieces. This will override the global setting, if it exists. .El .Pp There are several .Xr sysctl 8 variables available to view block handling parameters: .Bl -tag -width 12 .It kern.cam.sa.%d.allow_io_split .Pp This variable allows the user to see, but not modify, the current I/O split setting. The user is not permitted to modify this setting so that there is no chance of behavior changing for the application while a tape is mounted. .It kern.cam.sa.%d.maxio .Pp This variable shows the maximum I/O size in bytes that is allowed by the combination of kernel tuning parameters (MAXPHYS, DFLTPHYS) and the capabilities of the controller that is attached to the tape drive. Applications may look at this value for a guide on how large an I/O may be permitted, but should keep in mind that the actual maximum may be restricted further by the tape drive via the .Tn SCSI READ BLOCK LIMITS command. .It kern.cam.sa.%d.cpi_maxio .Pp This variable shows the maximum I/O size supported by the controller, in bytes, that is reported via the CAM Path Inquiry CCB (XPT_PATH_INQ). If this is 0, that means that the controller has not reported a maximum I/O size. .El .Sh FILE MARK HANDLING The handling of file marks on write is automatic. If the user has written to the tape, and has not done a read since the last write, then a file mark will be written to the tape when the device is closed. If a rewind is requested after a write, then the driver assumes that the last file on the tape has been written, and ensures that there are two file marks written to the tape. The exception to this is that there seems to be a standard (which we follow, but do not understand why) that certain types of tape do not actually write two file marks to tape, but when read, report a `phantom' file mark when the last file is read. These devices include the QIC family of devices. (It might be that this set of devices is the same set as that of fixed block devices. This has not been determined yet, and they are treated as separate behaviors by the driver at this time.) .Sh IOCTLS The .Nm driver supports all of the ioctls of .Xr mtio 4 . .Sh FILES .Bl -tag -width /dev/[n][e]sa[0-9] -compact .It Pa /dev/[n][e]sa[0-9] general form: .It Pa /dev/sa0 Rewind on close .It Pa /dev/nsa0 No rewind on close .It Pa /dev/esa0 Eject on close (if capable) .It Pa /dev/sa0.ctl Control mode device (to examine state while another program is accessing the device, e.g.). .El .Sh DIAGNOSTICS None. .Sh SEE ALSO -.Xr cam 4 , -.Xr mt 1 +.Xr mt 1 , +.Xr cam 4 .Sh AUTHORS .An -nosplit The .Nm driver was written for the .Tn CAM .Tn SCSI subsystem by .An Justin T. Gibbs and .An Kenneth Merry . Many ideas were gleaned from the .Nm st device driver written and ported from .Tn Mach 2.5 by .An Julian Elischer . .Pp The current owner of record is .An Matthew Jacob who has suffered too many years of breaking tape drivers. .Sh BUGS This driver lacks many of the hacks required to deal with older devices. Many older .Tn SCSI-1 devices may not work properly with this driver yet. .Pp Additionally, certain tapes (QIC tapes mostly) that were written under .Fx 2.X are not automatically read correctly with this driver: you may need to explicitly set variable block mode or set to the blocksize that works best for your device in order to read tapes written under .Fx 2.X. .Pp Fine grained density and compression mode support that is bound to specific device names needs to be added. .Pp Support for fast indexing by use of partitions is missing. Index: projects/sendfile/share/man/man4/send.4 =================================================================== --- projects/sendfile/share/man/man4/send.4 (revision 276056) +++ projects/sendfile/share/man/man4/send.4 (revision 276057) @@ -1,214 +1,214 @@ .\"- .\" Copyright (c) 2010 Ana Kukec .\" 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$ .\" .Dd September 19, 2010 .Dt SEND 4 .Os .Sh NAME .Nm send .Nd "Kernel side support for Secure Neighbor Discovery (SeND)" .Sh SYNOPSIS .In sys/socket.h .In netinet/in.h .In netinet6/send.h .Ft int .Fn socket PF_INET6 SOCK_RAW IPPROTO_SEND .Pp To load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent send_load="YES" .Ed .Sh DESCRIPTION IPv6 nodes use the Neighbor Discovery Protocol (NDP) to discover other nodes on the link, to determine their link-layer addresses to find routers, and to maintain reachability information about the paths to active members. NDP is vulnerable to various attacks [RFC3756]. Secure Neighbor Discovery is a set of extensions to NDP that counter threats to NDP [RFC3971]. .Pp Kernel side support for SeND consists of a kernel module with hooks that divert relevant packets (Neighbor Solicitations, Neighbor Advertisements, Router Solicitations, Router Advertisements and Redirects) from the NDP stack, send them to user space on a dedicated socket and reinject them back for further processing. Hooks are triggered only if the .Nm module is loaded. .Pp The native SeND socket is similar to a raw IP socket, but with its own, internal pseudo-protocol (IPPROTO_SEND). Struct sockaddr_send is defined in .In netinet6/send.h . It defines the total length of the structure, the address family, packet's incoming or outgoing direction from the interface's point of view, and the interface index. .Bd -literal struct sockaddr_send { unsigned char send_len; /* total length */ sa_family_t send_family; /* address family */ int send_direction; int send_ifidx; char send_zero[8]; }; .Ed .Pp The address family is always .Va AF_INET6 . The .Va send_direction variable denotes the direction of the packet from the interface's point of view and has either the value .Dv SND_IN or .Dv SND_OUT . The .Va send_ifidx variable is the interface index of the receiving or sending interface. The .Va send_zero variable is padding and must always be zero. .Pp In case that no user space application is connected to the send socket, processing continues normally as if the module was not loaded. .Sh INPUT HOOK The input hook is named after the input path of the incoming or outgoing NDP packets, on the way from the wire, through the nd6 stack, to user space. Relevant packets are identified by adding an mbuf_tag (see .Xr mbuf_tags 9 ) to the .Xr mbuf 9 , if the .Nm module is loaded. It is then passed on to the kernel-userland interface for either cryptographic protection or validation by the SeND application. The hook takes an argument that describes the direction of the packet, both in case of incoming and outgoing packets. .Dv SND_IN is the direction of the incoming packets that are usually protected by the SeND options and then sent to user space for cryptographic validation. .Dv SND_OUT is the outgoing direction. It describes both reply and locally originated outgoing packets that are sent to user space for the addition of SeND options. .Sh INCOMING PACKETS The incoming ND packet from the wire: .Bd -literal kernelspace ( userspace ) incoming SeND/ND packet ( | ) v ( SND_IN ) ( icmp6_input() -> send_input_hook ---> send socket ----+ : ) | : # # ( | normal : # # ) v processing : # send.ko # ( SeND application path : # # ) | : # # ( | v ) | icmp6/nd6_??_input() <- protocol switch <--- send socket <---+ | structure (IPPPROTO_SEND) ) | ( SND_IN ) ( v ) continue normal ND processing ( .Ed .Sh OUTGOING PACKETS Outgoing ND packet (reply or locally triggered): .Bd -literal kernelspace ( userspace ) nd6_na_input() ( +PACKET_TAG_ND_OUTGOING ) | ) | outgoing packet ( | | ) | v ( | icmp6_redirect_output() ) | nd6_ns_output() ( | nd6_na_output() ) | +PACKET_TAG_ND_OUTGOING ( | | ) | +-----------<- rip6_output() <----------)----- rtsol/rtadvd/.. | | +PACKET_TAG_ND_OUTGOING ( | v ) | ip6_output() ( | | ) +-------->-+ ( | ) v ( SND_OUT ) ( nd6_output_lle() -> send_input_hook ---> send socket ----+ -PACKET_TAG_ND_OUTGOING ) | : # # ( | normal : # # ) v processing : # send.ko # ( SeND application path : # # ) | : # # ( | v ) | (*ifp->if_output)() <- protocol switch <--- send socket <---+ | structure (IPPPROTO_SEND) ) | ( SND_OUT ) ( v ) continue with normal packet output ( .Ed .Sh ERRORS A socket operation may fail with one of the following errors returned: .Bl -tag -width Er .It Bq Er EEXIST Another user space SeND application is bound to the socket. .It Bq Er ENOBUFS Shortage of space to receive the incoming (SeND-protected) or outgoing (SeND-validated) packet from the SeND application. .It Bq Er ENOSYS A packet received from user space and passed to the NDP stack for further processing is neither Neighbor Solicitation, Neighbor Advertisement, Router Solicitation, Router Advertisement nor Redirect. .It Bq Er ENOENT Occurs if interface output routines fail to send the packet out of the interface. .El .Sh SEE ALSO -.Xr recvfrom 2 -.Xr sendto 2 -.Xr socket 2 +.Xr recvfrom 2 , +.Xr sendto 2 , +.Xr socket 2 , .Xr loader.conf 5 .Sh HISTORY The .Nm module first appeared in .Fx 9.0 . .Sh AUTHORS .An Ana Kukec Aq Mt anchie@FreeBSD.org , University of Zagreb .Sh BUGS Due to the lack of NDP locking, it is currently not possible to unload the .Nm module. Index: projects/sendfile/share/man/man4/sfxge.4 =================================================================== --- projects/sendfile/share/man/man4/sfxge.4 (revision 276056) +++ projects/sendfile/share/man/man4/sfxge.4 (revision 276057) @@ -1,129 +1,129 @@ .\" Copyright (c) 2011 Solarflare Communications, Inc. .\" 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$ .\" .Dd September 30, 2014 .Dt SFXGE 4 .Os .Sh NAME .Nm sfxge .Nd "Solarflare 10Gb Ethernet adapter driver" .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device sfxge" .Ed .Pp To load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent sfxge_load="YES" .Ed .Sh DESCRIPTION The .Nm driver provides support for 10Gb Ethernet adapters based on Solarflare SFC9000 family controllers. The driver supports jumbo frames, transmit/receive checksum offload, TCP Segmentation Offload (TSO), Large Receive Offload (LRO), VLAN checksum offload, VLAN TSO, and Receive Side Scaling (RSS) using MSI-X interrupts. .Pp The driver allocates 1 receive queue, transmit queue, event queue and IRQ per CPU up to a maximum of 64. IRQ affinities should be spread out using .Xr cpuset 1 . Interrupt moderation may be controlled through the sysctl .Va dev.sfxge.%d.int_mod (units are microseconds). .Pp For more information on configuring this device, see .Xr ifconfig 8 . .Pp A large number of MAC, PHY and data path statistics are available under the sysctl .Va dev.sfxge.%d.stats . The adapter's VPD fields including its serial number are available under the sysctl .Va dev.sfxge.%d.vpd . .Sh HARDWARE The .Nm driver supports all 10Gb Ethernet adapters based on Solarflare SFC9000 family controllers. .Sh LOADER TUNABLES Tunables can be set at the .Xr loader 8 prompt before booting the kernel or stored in .Xr loader.conf 5 . Actual values can be obtained using .Xr sysctl 8 . .Bl -tag -width indent .It Va hw.sfxge.rx_ring The maximum number of descriptors in a receive queue ring. Supported values are: 512, 1024, 2048 and 4096. .It Va hw.sfxge.tx_ring The maximum number of descriptors in a transmit queue ring. Supported values are: 512, 1024, 2048 and 4096. .It Va hw.sfxge.tx_dpl_get_max The maximum length of the deferred packet .Dq get-list for queued transmit packets, used only if the transmit queue lock can be acquired. If a packet is dropped, the .Va tx_early_drops counter is incremented and the local sender receives ENOBUFS. The value must be greater than 0. .It Va hw.sfxge.tx_dpl_put_max The maximum length of the deferred packet .Dq put-list for queued transmit packets, used if the transmit queue lock cannot be acquired. If a packet is dropped, the .Va tx_early_drops counter is incremented and the local sender receives ENOBUFS. The value must be greater than or equal to 0. .El .Sh SUPPORT For general information and support, go to the Solarflare support website at: .Pa https://support.solarflare.com . .Sh SEE ALSO +.Xr cpuset 1 , .Xr arp 4 , .Xr netintro 4 , .Xr ng_ether 4 , .Xr vlan 4 , -.Xr cpuset 1 , .Xr ifconfig 8 .Sh AUTHORS The .Nm driver was written by .An Philip Paeps and .An Solarflare Communications, Inc. Index: projects/sendfile/share/man/man4/snd_hda.4 =================================================================== --- projects/sendfile/share/man/man4/snd_hda.4 (revision 276056) +++ projects/sendfile/share/man/man4/snd_hda.4 (revision 276057) @@ -1,635 +1,635 @@ .\" Copyright (c) 2006-2008 Joel Dahl .\" Copyright (c) 2008 Alexander Motin .\" 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$ .\" .Dd January 25, 2012 .Dt SND_HDA 4 .Os .Sh NAME .Nm snd_hda .Nd "Intel High Definition Audio bridge device driver" .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device sound" .Cd "device snd_hda" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent snd_hda_load="YES" .Ed .Sh DESCRIPTION The High Definition (HD) Audio specification was developed by Intel as the logical successor of the old AC'97 specification and has several advantages, such as higher bandwidth which allows more channels and more detailed formats, support for several logical audio devices, and general purpose DMA channels. .Pp The .Nm driver includes HDA bus controller driver (hdac), HDA codec driver (hdacc) and HDA codecs audio functions bridge driver (hdaa) that allows the generic audio driver, .Xr sound 4 , to be used with this hardware. Only audio functions are supported by .Nm . Modem and other possible functions are not implemented. .Pp The .Nm driver supports hardware that conforms with revision 1.0 of the Intel High Definition Audio specification and tries to behave much like the Microsoft Universal Audio Architecture (UAA) draft (revision 0.7b) for handling audio devices. .Pp According to HDA and UAA specifications, depending on the number of HDA buses and codecs present in system, their audio capabilities and BIOS provided configuration, the .Nm driver often provides several PCM audio devices. For example, one device for main rear 7.1 output and inputs, one device for independent headset connectors at front and one device for SPDIF or HDMI audio input/output. The assignment of audio inputs and outputs may be tuned with .Xr device.hints 5 or .Xr sysctl 8 . The driver's verbose boot messages provide a lot of information about the operation of the driver and present audio setup. .Pp The default audio device may be tuned by setting the .Ar hw.snd.default_unit sysctl, as described in .Xr sound 4 , or explicitly specified in application settings. .Ss Boot-time Configuration The following variables are available at boot-time through the .Xr device.hints 5 file: .Bl -tag -width ".Va hint.hdac.%d.config"-offset indent .It Va hint.hdac.%d.config Configures a range of possible controller options. Possible values are: .Dq Li 64bit , .Dq Li dmapos , .Dq Li msi . An option prefixed with .Dq Li no , such as .Dq Li nomsi , will do the opposite and takes precedence. Options can be separated by whitespace and commas. .It Va hint.hdac.%d.msi Controls MSI (Message Signaled Interrupts) support. .It Va hint.hdac.%d.cad%d.nid%d.config Same as .Va hint.hdaa.%d.nid%d.config .It Va hint.hdaa.%d.config Configures a range of possible audio function options. Possible values are: .Dq Li eapdinv , .Dq Li ivref , .Dq Li ivref50 , .Dq Li ivref80 , .Dq Li ivref100 , .Dq Li fixedrate , .Dq Li forcestereo , .Dq Li ovref , .Dq Li ovref50 , .Dq Li ovref80 , .Dq Li ovref100 , .Dq Li senseinv , .Dq Li softpcmvol , and .Dq Li vref . An option prefixed with .Dq Li no , such as .Dq Li nofixedrate , will do the opposite and takes precedence. Options can be separated by whitespace and commas. .Pp The .Dq Li eapdinv option inverts External Amplifier Power Down signal. The .Dq Li fixedrate denies all sampling rates except 48KHz. The .Dq Li forcestereo denies mono playback/recording. The .Dq Li senseinv option inverts jack sensing logic. The .Dq Li ivref Ns Ar X and .Dq Li ovref Ns Ar X options control the voltage used to power external microphones. .It Va hint.hdaa.%d.gpio_config Overrides audio function GPIO pins configuration set by BIOS. May be specified as a set of space-separated .Dq Ar num Ns = Ns Ar value pairs, where .Ar num is GPIO line number, and .Ar value is one of: .Dq Li keep , .Dq Li set , .Dq Li clear , .Dq Li disable and .Dq Li input . .Pp .Dq Li GPIO Ns s are a codec's General Purpose I/O pins which system integrators sometimes use to control external muters, amplifiers and so on. If you have no sound, or sound volume is not adequate, you may have to experiment a bit with the GPIO setup to find the optimal setup for your system. .It Va hint.hdaa.%d.nid%d.config Overrides audio function pin configuration set by BIOS. May be specified as a 32-bit hexadecimal value with a leading .Dq 0x , or as a set of space-separated .Dq Ar option Ns = Ns Ar value pairs. .It Va hint.pcm.%d.rec.autosrc Controls automatic recording source feature: .Bl -tag -width 2n -compact .It 0 disabled, .It 1 once on attach, .It 2 enabled. .El When enabled, driver will automatically set recording source of the mixer to connected input using jack presence detection statuses. .El .Pp Pin configuration is the UAA driver's main source of information about codec usage. This information is usually provided by the codec manufacturer and tuned by system integrators for specific system requirements. The .Nm driver allows users to override it to fix integrator mistakes or to use the available codec in alternative ways (for example to get stereo output and 2 inputs instead of a single 5.1 output). .Pp The following options are supported: .Bl -tag -width ".Va device=" -offset indent .It Va as Association number. Associations are used to group individual pins to form a complex multi-pin device. For example, to group 4 connectors for 7.1 input/output, or to treat several input connectors as sources for the same input device. Association numbers can be specified as numeric values from 0 to 15. A value of 0 means disabled pin. A value of 15 is a set of independent unassociated pins. Each association includes only pins of the same direction (in/out) and is detected atomically (all pins or none). A separate PCM audio device is created for every pair of input and output associations. .It Va seq Sequence number. A unique, per-association number used to order pins inside the particular association. Sequence numbers can be specified as numeric values from 0 to 15. .Pp The sequence number 15 has a special meaning for output associations. Output pins with this number and device type .Dq Ar Headphones will duplicate (with automatic mute if jack detection is supported) the first pin in that association. .Pp The sequence numbers 14 and 15 has a special meaning for input associations. Their presence in association defines it as multiplexed or mixed respectively. If none of them are present and there are more than one pin in association, the association will provide multichannel input. .Pp For multichannel input/output associations sequence numbers encode channel pairs positions: 0 - Front, 1 - Center/LFE, 2 - Back, 3 - Front Wide Center, 4 - Side. Standard combinations are: (0) - Stereo; (0, 2), (0, 4) - Quadro; (0, 1, 2), (0, 1, 4) - 5.1; (0, 1, 2, 4) - 7.1. .It Va device Device type. Can be specified as a number from 0 to 15 or as a name: .Dq Li Line-out , .Dq Li Speaker , .Dq Li Headphones, .Dq Li CD , .Dq Li SPDIF-out , .Dq Li Digital-out , .Dq Li Modem-line , .Dq Li Modem-handset , .Dq Li Line-in , .Dq Li AUX , .Dq Li Mic , .Dq Li Telephony , .Dq Li SPDIF-in , .Dq Li Digital-in , .Dq Li Res.E , or .Dq Li Other . The device type also describes the pin direction (in/out). For example, .Dq Li CD always means an input pin, while .Dq Li Headphones always means an output. .It Va conn Connection type. Can be specified as a number from 0 to 3. The connection type can also be specified as one of the special names .Dq Li Jack , .Dq Li None , .Dq Li Fixed , or .Dq Li Both . Pins with a connection type of .Dq Li None are disabled. .It Va ctype Connector physical type. Can be specified as a number from 0 to 15. This is a reference only value. It is ignored by the .Nm driver. .It Va color Connector color. Can be specified as a number from 0 to 15 or as one of the names .Dq Li Unknown , .Dq Li Black , .Dq Li Grey , .Dq Li Blue , .Dq Li Green , .Dq Li Red , .Dq Li Orange , .Dq Li Yellow , .Dq Li Purple , .Dq Li Pink , .Dq Li Res.A , .Dq Li Res.B , .Dq Li Res.C , .Dq Li Res.D , .Dq Li White , or .Dq Li Other . This is a reference only value. It is ignored by the .Nm driver. .It Va loc Connector physical location. Can be specified as a number from 0 to 63. This is a reference only value. It is ignored by the .Nm driver. .It Va misc Misc bits. Can be specified as a number from 0 to 15. Bit 0 has a special meaning. When set it means that jack detection is not implemented in hardware. .El .Ss Runtime Configuration The following .Xr sysctl 8 variables are available in addition to those available to all .Xr sound 4 devices: .Bl -tag -width ".Va dev.hdaa.%d.nid%d_original" -offset indent .It Va dev.hdac.%d.pindump Setting this to a non-zero value dumps the current pin configuration, main capabilities and jack sense status of all audio functions on the controller to console and syslog. .It Va dev.hdac.%d.polling Enables polling mode. In this mode the driver operates by querying the device state on timer ticks using .Xr callout 9 instead of interrupts. Polling is disabled by default. Do not enable it unless you are facing weird interrupt problems or if the device cannot generate interrupts at all. .It Va dev.hdaa.%d.config Run-time equivalent of the .Va hint.hdaa.%d.config tunable. .It Va dev.hdaa.%d.gpi_state Current state of GPI lines. .It Va dev.hdaa.%d.gpio_state Current state of GPIO lines. .It Va dev.hdaa.%d.gpio_config Run-time equivalent of the .Va hint.hdaa.%d.gpio.config tunable. .It Va dev.hdaa.%d.gpo_state Current state of GPO lines. .It Va dev.hdaa.%d.nid%d_config Run-time equivalent of the .Va hint.hdaa.%d.nid%d.config tunable. .It Va dev.hdaa.%d.nid%d_original Original pin configuration written by BIOS. .It Va dev.hdaa.%d.reconfig Setting this to a non-zero value makes driver to destroy existing pcm devices and process new pins configuration set via .Va dev.hdaa.%d.nid%d_config . .It Va dev.pcm.%d.play.32bit , dev.pcm.%d.rec.32bit HDA controller uses 32bit representation for all samples of more then 16 bits. These variables allow to specify how many bits of these 32 should be used by CODEC. Depending on codec capabilities, possible values are 20, 24 and 32 bit. The default value is 24. .It Va dev.pcm.%d.rec.autosrc Run-time equivalent of the .Va hint.pcm.%d.rec.autosrc tunable. .El .Sh EXAMPLES Taking HP Compaq DX2300 with Realtek ALC888 HDA codec for example. This system has two audio connectors on a front side, three audio connectors on a rear side and one internal speaker. According to verbose driver output and the codec datasheet, this codec has five stereo DACs and two stereo ADCs, all of them are routable to any codec pin (external connector). All codec pins are reversible (could be configured either as input or output). .Pp So high codec uniformity and flexibility allow driver to configure it in many different ways, depending on requested pins usage described by pins configuration. The driver reports such default pin configuration when verbose messages enabled: .Bd -literal hdaa0: nid 0x as seq device conn jack loc color misc hdaa0: 20 01014020 2 0 Line-out Jack 1/8 Rear Green 0 hdaa0: 21 99130110 1 0 Speaker Fixed ATAPI Onboard Unknown 1 hdaa0: 22 411111f0 15 0 Speaker None 1/8 Rear Black 1 DISA hdaa0: 23 411111f0 15 0 Speaker None 1/8 Rear Black 1 DISA hdaa0: 24 01a19830 3 0 Mic Jack 1/8 Rear Pink 8 hdaa0: 25 02a1983f 3 15 Mic Jack 1/8 Front Pink 8 hdaa0: 26 01813031 3 1 Line-in Jack 1/8 Rear Blue 0 hdaa0: 27 0221401f 1 15 Headphones Jack 1/8 Front Green 0 hdaa0: 28 411111f0 15 0 Speaker None 1/8 Rear Black 1 DISA hdaa0: 30 411111f0 15 0 Speaker None 1/8 Rear Black 1 DISA hdaa0: 31 411111f0 15 0 Speaker None 1/8 Rear Black 1 DISA .Ed .Pp Here we can see, that the nodes with ID (nid) 25 and 27 are front panel connectors (Jack, Front), nids 20, 24 and 26 are rear panel connectors (Jack, Rear) and nid 21 is a built-in speaker (Fixed, Onboard). Pins with nids 22, 23, 28, 30 and 31 will be disabled by driver due to "None" connectivity. So the pin count and description matches to connectors that we have. .Pp Using association (as) and sequence (seq) fields values pins are grouped into 3 associations: .Bd -literal hdaa0: Association 0 (1) out: hdaa0: Pin nid=21 seq=0 hdaa0: Pin nid=27 seq=15 hdaa0: Association 1 (2) out: hdaa0: Pin nid=20 seq=0 hdaa0: Association 2 (3) in: hdaa0: Pin nid=24 seq=0 hdaa0: Pin nid=26 seq=1 hdaa0: Pin nid=25 seq=15 .Ed .Pp Each .Xr pcm 4 device uses two associations: one for playback and one for recording. Associations processed and assigned to .Xr pcm 4 devices in increasing numerical order. In this case association #0 (1) will become .Li pcm0 device playback, using the internal speakers and .Ar Headphones jack with speaker automute on the headphones jack connection. Association #1 (2) will become .Li pcm1 playback, using the .Ar Line-out jack. Association #2 (3) will become .Li pcm0 recording, using the external microphones and the .Ar Line-in jack. .Pp The .Nm driver provides extensive verbose messages to diagnose its operation logic and describe its current codec configuration. .Pp Using .Xr device.hints 5 it is possible to modify the configuration of the existing pins, allowing a broad range of different audio setups. Here are a few examples of some setups possible for this particular hardware: .Ss Example 1 Setting the .Xr device.hints 5 options .Bd -literal hint.hdac.0.cad0.nid20.config="as=1" hint.hdac.0.cad0.nid21.config="as=2" .Ed .Pp will swap line-out and speaker functions. So the .Li pcm0 device will play to the line-out and headphones jacks. Line-out will be muted on the headphones jack connection. Recording on .Li pcm0 will go from two external microphones and line-in jacks. .Li pcm1 playback will go to the internal speaker. .Ss Example 2 Setting the .Xr device.hints 5 options .Bd -literal hint.hdac.0.cad0.nid20.config="as=1 seq=15 device=Headphones" hint.hdac.0.cad0.nid27.config="as=2 seq=0" hint.hdac.0.cad0.nid25.config="as=4 seq=0" .Ed .Pp will split the headphones and one of the microphones to a separate device. The .Li pcm0 device will play to the internal speaker and to the line-out jack, with speaker automute on the line-out jack connection. Recording on .Li pcm0 will use input from one external microphone and the line-in jacks. The .Li pcm1 device will be completely dedicated to a headset (headphones and mic) connected to the front connectors. .Ss Example 3 Setting the .Xr device.hints 5 options .Bd -literal hint.hdac.0.cad0.nid20.config="as=1 seq=0" hint.hdac.0.cad0.nid26.config="as=2 seq=0" hint.hdac.0.cad0.nid27.config="as=3 seq=0" hint.hdac.0.cad0.nid25.config="as=4 seq=0" hint.hdac.0.cad0.nid24.config="as=5 seq=0 device=Line-out" hint.hdac.0.cad0.nid21.config="as=6 seq=0" .Ed .Pp will give 4 independent devices: .Li pcm0 .Pq line-out and line-in , .Li pcm1 .Pq headphones and mic , .Li pcm2 .Pq additional line-out via retasked rear mic jack , and .Li pcm3 .Pq internal speaker . .Ss Example 4 Setting the .Xr device.hints 5 options .Bd -literal hint.hdac.0.cad0.nid20.config="as=1 seq=0" hint.hdac.0.cad0.nid24.config="as=1 seq=1 device=Line-out" hint.hdac.0.cad0.nid26.config="as=1 seq=2 device=Line-out" hint.hdac.0.cad0.nid21.config="as=2 seq=0" .Ed .Pp will give 2 devices: .Li pcm0 for 5.1 playback via 3 rear connectors (line-out and retasked mic and line-in) and headset (headphones and mic) at front connectors. .Li pcm1 for internal speaker playback. On headphones connection rear connectors will be muted. .Sh MIXER CONTROLS Depending on codec configuration, these controls and signal sources could be reported to .Xr sound 4 : .Bl -tag -width ".Va speaker" -offset indent .It Va vol overall output level (volume) .It Va rec overall recording level .It Va igain input-to-output monitoring loopback level .It Va ogain external amplifier control .It Va pcm PCM playback .It Va mix input mix .It Va mic first external or second internal microphone input .It Va monitor first internal or second external microphone input .It Va line , Va line1 , Va line2, Va line3 analog (line) inputs .It Va dig1 , Va dig2 , Va dig3 digital (S/PDIF, HDMI or DisplayPort) inputs .It Va cd CD input .It Va speaker PC speaker input .It Va phin , Va phout , Va radio . Va video other random inputs .El .Pp Controls have different precision. Some could be just an on/off triggers. Most of controls use logarithmic scale. .Sh HARDWARE The .Nm driver supports controllers having PCI class 4 (multimedia) and subclass 3 (HDA), compatible with Intel HDA specification. .Pp The .Nm driver supports more than two hundred different controllers and CODECs. There is no sense to list all of them here, as in most cases specific CODEC configuration and wiring are more important then type of the CODEC itself. .Sh SEE ALSO -.Xr sound 4 , .Xr snd_ich 4 , +.Xr sound 4 , .Xr device.hints 5 , .Xr loader.conf 5 , .Xr sysctl 8 .Sh HISTORY The .Nm device driver first appeared in .Fx 6.3 . .Sh AUTHORS .An -nosplit The .Nm driver was written by .An Stephane E. Potvin Aq Mt sepotvin@videotron.ca , .An Ariff Abdullah Aq Mt ariff@FreeBSD.org and .An Alexander Motin Aq Mt mav@FreeBSD.org . This manual page was written by .An Joel Dahl Aq Mt joel@FreeBSD.org , .An Alexander Motin Aq Mt mav@FreeBSD.org and .An Giorgos Keramidas Aq Mt keramida@FreeBSD.org . .Sh BUGS Some Hardware/OEM vendors tend to screw up BIOS settings or use custom unusual CODEC wiring that create problems to the driver. This may result in missing pcm devices, or a state where the .Nm driver seems to attach and work, but no sound is played. Some cases can be solved by tuning .Pa loader.conf variables. But before trying to fix problem that way, make sure that there really is a problem and that the PCM audio device in use really corresponds to the expected audio connector. .Pp Some vendors use non-standardized General Purpose I/O (GPIO) pins of the codec to control external amplifiers. In some cases setting a combination of GPIO bits may be needed to make sound work on a specific device. .Pp HDMI and DisplayPort audio may also require support from video driver. Index: projects/sendfile/share/man/man4/snd_ich.4 =================================================================== --- projects/sendfile/share/man/man4/snd_ich.4 (revision 276056) +++ projects/sendfile/share/man/man4/snd_ich.4 (revision 276057) @@ -1,111 +1,111 @@ .\" Copyright (c) 2004 Jorge Mario G. Mazo .\" 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$ .\" .Dd January 6, 2009 .Dt SND_ICH 4 .Os .Sh NAME .Nm snd_ich .Nd "Intel ICH AC'97 and compatible bridge device driver" .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device sound" .Cd "device snd_ich" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent snd_ich_load="YES" .Ed .Sh DESCRIPTION The .Nm bridge driver allows the generic audio driver .Xr sound 4 to attach to Intel ICH AC'97 and compatible audio devices. .Pp Some later chips, like ICH6/ICH7, depending on wiring can instead implement newer Intel HD Audio specification, which is supported by .Xr snd_hda 4 driver. .Sh HARDWARE The .Nm driver supports the following audio devices: .Pp .Bl -bullet -compact .It AMD 768 .It AMD 8111 .It Intel 443MX .It Intel ICH .It Intel ICH revision 1 .It Intel ICH2 .It Intel ICH3 .It Intel ICH4 .It Intel ICH5 .It Intel ICH6 .It Intel ICH7 .It NVIDIA nForce .It NVIDIA nForce2 .It NVIDIA nForce2 400 .It NVIDIA nForce3 .It NVIDIA nForce3 250 .It NVIDIA nForce4 .It SiS 7012 .El .Sh SEE ALSO -.Xr sound 4 , -.Xr snd_hda 4 +.Xr snd_hda 4 , +.Xr sound 4 .Sh HISTORY The .Nm device driver first appeared in .Fx 4.2 . .Sh AUTHORS This manual page was written by .An Jorge Mario G. Mazo Aq Mt jgutie11@eafit.edu.co . Index: projects/sendfile/share/man/man4/tap.4 =================================================================== --- projects/sendfile/share/man/man4/tap.4 (revision 276056) +++ projects/sendfile/share/man/man4/tap.4 (revision 276057) @@ -1,329 +1,329 @@ .\" $FreeBSD$ .\" Based on PR#2411 .\" .Dd November 30, 2014 .Dt TAP 4 .Os .Sh NAME .Nm tap .Nd Ethernet tunnel software network interface .Sh SYNOPSIS .Cd device tap .Sh DESCRIPTION The .Nm interface is a software loopback mechanism that can be loosely described as the network interface analog of the .Xr pty 4 , that is, .Nm does for network interfaces what the .Xr pty 4 driver does for terminals. .Pp The .Nm driver, like the .Xr pty 4 driver, provides two interfaces: an interface like the usual facility it is simulating (an Ethernet network interface in the case of .Nm , or a terminal for .Xr pty 4 ) , and a character-special device .Dq control interface. -A client program transfers Ethernet frames to or from the +A client program transfers Ethernet frames to or from the .Nm .Dq control interface. The .Xr tun 4 interface provides similar functionality at the network layer: a client will transfer IP (by default) packets to or from a .Xr tun 4 .Dq control interface. .Pp The network interfaces are named .Dq Li tap0 , .Dq Li tap1 , etc., one for each control device that has been opened. These Ethernet network interfaces persist until .Pa if_tap.ko module is unloaded, or until removed with "ifconfig destroy" (see below). .Pp .Nm devices are created using interface cloning. This is done using the .Dq ifconfig tap Ns Sy N No create command. This is the preferred method of creating .Nm devices. The same method allows removal of interfaces. For this, use the .Dq ifconfig tap Ns Sy N No destroy command. .Pp If the .Xr sysctl 8 variable .Va net.link.tap.devfs_cloning is non-zero, the .Nm interface permits opens on the special control device .Pa /dev/tap . When this device is opened, .Nm will return a handle for the lowest unused .Nm device (use .Xr devname 3 to determine which). .Pp .Bf Em Disabling the legacy devfs cloning functionality may break existing applications which use .Nm , such as .Tn VMware and .Xr ssh 1 . It therefore defaults to being enabled until further notice. .Ef .Pp Control devices (once successfully opened) persist until .Pa if_tap.ko is unloaded or the interface is destroyed. .Pp Each interface supports the usual Ethernet network interface .Xr ioctl 2 Ns s and thus can be used with .Xr ifconfig 8 like any other Ethernet interface. When the system chooses to transmit an Ethernet frame on the network interface, the frame can be read from the control device (it appears as .Dq input there); writing an Ethernet frame to the control device generates an input frame on the network interface, as if the (non-existent) hardware had just received it. .Pp The Ethernet tunnel device, normally .Pa /dev/tap Ns Sy N , is exclusive-open (it cannot be opened if it is already open) and is restricted to the super-user, unless the .Xr sysctl 8 variable .Va net.link.tap.user_open is non-zero. If the .Xr sysctl 8 variable .Va net.link.tap.up_on_open is non-zero, the tunnel device will be marked .Dq up when the control device is opened. A .Fn read call will return an error .Pq Er EHOSTDOWN if the interface is not .Dq ready . Once the interface is ready, .Fn read will return an Ethernet frame if one is available; if not, it will either block until one is or return .Er EWOULDBLOCK , depending on whether non-blocking I/O has been enabled. If the frame is longer than is allowed for in the buffer passed to .Fn read , the extra data will be silently dropped. .Pp A .Xr write 2 call passes an Ethernet frame in to be .Dq received on the pseudo-interface. Each .Fn write call supplies exactly one frame; the frame length is taken from the amount of data provided to .Fn write . Writes will not block; if the frame cannot be accepted for a transient reason (e.g., no buffer space available), it is silently dropped; if the reason is not transient (e.g., frame too large), an error is returned. The following .Xr ioctl 2 calls are supported (defined in .In net/if_tap.h ) : .Bl -tag -width VMIO_SIOCSETMACADDR .It Dv TAPSIFINFO Set network interface information (line speed, MTU and type). The argument should be a pointer to a .Va struct tapinfo . .It Dv TAPGIFINFO Retrieve network interface information (line speed, MTU and type). The argument should be a pointer to a .Va struct tapinfo . .It Dv TAPSDEBUG The argument should be a pointer to an .Va int ; this sets the internal debugging variable to that value. What, if anything, this variable controls is not documented here; see the source code. .It Dv TAPGDEBUG The argument should be a pointer to an .Va int ; this stores the internal debugging variable's value into it. .It Dv TAPGIFNAME Retrieve network interface name. The argument should be a pointer to a .Va struct ifreq . The interface name will be returned in the .Va ifr_name field. .It Dv FIONBIO Turn non-blocking I/O for reads off or on, according as the argument .Va int Ns 's value is or is not zero (Writes are always nonblocking). .It Dv FIOASYNC Turn asynchronous I/O for reads (i.e., generation of .Dv SIGIO when data is available to be read) off or on, according as the argument .Va int Ns 's value is or is not zero. .It Dv FIONREAD If any frames are queued to be read, store the size of the first one into the argument .Va int ; otherwise, store zero. .It Dv TIOCSPGRP Set the process group to receive .Dv SIGIO signals, when asynchronous I/O is enabled, to the argument .Va int value. .It Dv TIOCGPGRP Retrieve the process group value for .Dv SIGIO signals into the argument .Va int value. .It Dv SIOCGIFADDR Retrieve the Media Access Control .Pq Dv MAC address of the .Dq remote side. This command is used by the VMware port and expected to be executed on descriptor, associated with control device (usually .Pa /dev/vmnet Ns Sy N or .Pa /dev/tap Ns Sy N ) . The .Va buffer , which is passed as the argument, is expected to have enough space to store the .Dv MAC address. At the open time both .Dq local and .Dq remote .Dv MAC addresses are the same, so this command could be used to retrieve the .Dq local .Dv MAC address. .It Dv SIOCSIFADDR Set the Media Access Control .Pq Dv MAC address of the .Dq remote side. This command is used by VMware port and expected to be executed on a descriptor, associated with control device (usually .Pa /dev/vmnet Ns Sy N ) . .El .Pp The control device also supports .Xr select 2 for read; selecting for write is pointless, and always succeeds, since writes are always non-blocking. .Pp On the last close of the data device, the interface is brought down (as if with .Dq ifconfig tap Ns Sy N No down ) unless the device is a .Em VMnet device. All queued frames are thrown away. If the interface is up when the data device is not open, output frames are thrown away rather than letting them pile up. .Pp The .Nm device can also be used with the VMware port as a replacement for the old .Em VMnet device driver. The driver uses the minor number to select between .Nm and .Nm vmnet devices. .Em VMnet minor numbers begin at .Va 0x800000 + .Va N ; where .Va N is a .Em VMnet unit number. In this case the control device is expected to be .Pa /dev/vmnet Ns Sy N , and the network interface will be .Sy vmnet Ns Ar N . Additionally, .Em VMnet devices do not .Xr ifconfig 8 themselves down when the control device is closed. Everything else is the same. .Pp In addition to the above mentioned .Xr ioctl 2 calls, there is an additional one for the VMware port. .Bl -tag -width VMIO_SIOCSETMACADDR .It Dv VMIO_SIOCSIFFLAGS VMware .Dv SIOCSIFFLAGS . .El .Sh SEE ALSO .Xr inet 4 , .Xr intro 4 , .Xr tun 4 Index: projects/sendfile/share/man/man4/tun.4 =================================================================== --- projects/sendfile/share/man/man4/tun.4 (revision 276056) +++ projects/sendfile/share/man/man4/tun.4 (revision 276057) @@ -1,325 +1,325 @@ .\" $NetBSD: tun.4,v 1.1 1996/06/25 22:17:37 pk Exp $ .\" $FreeBSD$ .\" Based on PR#2411 .\" .Dd November 30, 2014 .Dt TUN 4 .Os .Sh NAME .Nm tun .Nd tunnel software network interface .Sh SYNOPSIS .Cd device tun .Sh DESCRIPTION The .Nm interface is a software loopback mechanism that can be loosely described as the network interface analog of the .Xr pty 4 , that is, .Nm does for network interfaces what the .Xr pty 4 driver does for terminals. .Pp The .Nm driver, like the .Xr pty 4 driver, provides two interfaces: an interface like the usual facility it is simulating (a network interface in the case of .Nm , or a terminal for .Xr pty 4 ) , and a character-special device .Dq control interface. -A client program transfers IP (by default) packets to or from the +A client program transfers IP (by default) packets to or from the .Nm .Dq control interface. The .Xr tap 4 interface provides similar functionality at the Ethernet layer: a client will transfer Ethernet frames to or from a .Xr tap 4 .Dq control interface. .Pp The network interfaces are named .Dq Li tun0 , .Dq Li tun1 , etc., one for each control device that has been opened. These network interfaces persist until the .Pa if_tun.ko module is unloaded, or until removed with the .Xr ifconfig 8 command. .Pp .Nm devices are created using interface cloning. This is done using the .Dq ifconfig tun Ns Sy N No create command. This is the preferred method of creating .Nm devices. The same method allows removal of interfaces. For this, use the .Dq ifconfig tun Ns Sy N No destroy command. .Pp If the .Xr sysctl 8 variable .Va net.link.tun.devfs_cloning is non-zero, the .Nm interface permits opens on the special control device .Pa /dev/tun . When this device is opened, .Nm will return a handle for the lowest unused .Nm device (use .Xr devname 3 to determine which). .Pp .Bf Em Disabling the legacy devfs cloning functionality may break existing applications which use .Nm , such as .Xr ppp 8 and .Xr ssh 1 . It therefore defaults to being enabled until further notice. .Ef .Pp Control devices (once successfully opened) persist until .Pa if_tun.ko is unloaded in the same way that network interfaces persist (see above). .Pp Each interface supports the usual network-interface .Xr ioctl 2 Ns s , such as .Dv SIOCAIFADDR and thus can be used with .Xr ifconfig 8 like any other interface. At boot time, they are .Dv POINTOPOINT interfaces, but this can be changed; see the description of the control device, below. When the system chooses to transmit a packet on the network interface, the packet can be read from the control device (it appears as .Dq input there); writing a packet to the control device generates an input packet on the network interface, as if the (non-existent) hardware had just received it. .Pp The tunnel device .Pq Pa /dev/tun Ns Ar N is exclusive-open (it cannot be opened if it is already open). A .Xr read 2 call will return an error .Pq Er EHOSTDOWN if the interface is not .Dq ready (which means that the control device is open and the interface's address has been set). .Pp Once the interface is ready, .Xr read 2 will return a packet if one is available; if not, it will either block until one is or return .Er EWOULDBLOCK , depending on whether non-blocking I/O has been enabled. If the packet is longer than is allowed for in the buffer passed to .Xr read 2 , the extra data will be silently dropped. .Pp If the .Dv TUNSLMODE ioctl has been set, packets read from the control device will be prepended with the destination address as presented to the network interface output routine, .Fn tunoutput . The destination address is in .Vt struct sockaddr format. The actual length of the prepended address is in the member .Va sa_len . If the .Dv TUNSIFHEAD ioctl has been set, packets will be prepended with a four byte address family in network byte order. .Dv TUNSLMODE and .Dv TUNSIFHEAD are mutually exclusive. In any case, the packet data follows immediately. .Pp A .Xr write 2 call passes a packet in to be .Dq received on the pseudo-interface. If the .Dv TUNSIFHEAD ioctl has been set, the address family must be prepended, otherwise the packet is assumed to be of type .Dv AF_INET . Each .Xr write 2 call supplies exactly one packet; the packet length is taken from the amount of data provided to .Xr write 2 (minus any supplied address family). Writes will not block; if the packet cannot be accepted for a transient reason (e.g., no buffer space available), it is silently dropped; if the reason is not transient (e.g., packet too large), an error is returned. .Pp The following .Xr ioctl 2 calls are supported (defined in .In net/if_tun.h ) : .Bl -tag -width ".Dv TUNSIFMODE" .It Dv TUNSDEBUG The argument should be a pointer to an .Vt int ; this sets the internal debugging variable to that value. What, if anything, this variable controls is not documented here; see the source code. .It Dv TUNGDEBUG The argument should be a pointer to an .Vt int ; this stores the internal debugging variable's value into it. .It Dv TUNSIFINFO The argument should be a pointer to an .Vt struct tuninfo and allows setting the MTU, the type, and the baudrate of the tunnel device. The .Vt struct tuninfo is declared in .In net/if_tun.h . .Pp The use of this ioctl is restricted to the super-user. .It Dv TUNGIFINFO The argument should be a pointer to an .Vt struct tuninfo , where the current MTU, type, and baudrate will be stored. .It Dv TUNSIFMODE The argument should be a pointer to an .Vt int ; its value must be either .Dv IFF_POINTOPOINT or .Dv IFF_BROADCAST and should have .Dv IFF_MULTICAST OR'd into the value if multicast support is required. The type of the corresponding .Dq Li tun Ns Ar N interface is set to the supplied type. If the value is outside the above range, an .Er EINVAL error is returned. The interface must be down at the time; if it is up, an .Er EBUSY error is returned. .It Dv TUNSLMODE The argument should be a pointer to an .Vt int ; a non-zero value turns off .Dq multi-af mode and turns on .Dq link-layer mode, causing packets read from the tunnel device to be prepended with the network destination address (see above). .It Dv TUNSIFPID Will set the pid owning the tunnel device to the current process's pid. .It Dv TUNSIFHEAD The argument should be a pointer to an .Vt int ; a non-zero value turns off .Dq link-layer mode, and enables .Dq multi-af mode, where every packet is preceded with a four byte address family. .It Dv TUNGIFHEAD The argument should be a pointer to an .Vt int ; the ioctl sets the value to one if the device is in .Dq multi-af mode, and zero otherwise. .It Dv FIONBIO Turn non-blocking I/O for reads off or on, according as the argument .Vt int Ns 's value is or is not zero. (Writes are always non-blocking.) .It Dv FIOASYNC Turn asynchronous I/O for reads (i.e., generation of .Dv SIGIO when data is available to be read) off or on, according as the argument .Vt int Ns 's value is or is not zero. .It Dv FIONREAD If any packets are queued to be read, store the size of the first one into the argument .Vt int ; otherwise, store zero. .It Dv TIOCSPGRP Set the process group to receive .Dv SIGIO signals, when asynchronous I/O is enabled, to the argument .Vt int value. .It Dv TIOCGPGRP Retrieve the process group value for .Dv SIGIO signals into the argument .Vt int value. .El .Pp The control device also supports .Xr select 2 for read; selecting for write is pointless, and always succeeds, since writes are always non-blocking. .Pp On the last close of the data device, by default, the interface is brought down (as if with .Nm ifconfig Ar tunN Cm down ) . All queued packets are thrown away. If the interface is up when the data device is not open output packets are always thrown away rather than letting them pile up. .Sh SEE ALSO .Xr ioctl 2 , .Xr read 2 , .Xr select 2 , .Xr write 2 , .Xr devname 3 , .Xr inet 4 , .Xr intro 4 , .Xr pty 4 , .Xr tap 4 , .Xr ifconfig 8 .Sh AUTHORS This manual page was originally obtained from .Nx . Index: projects/sendfile/share/man/man4/umass.4 =================================================================== --- projects/sendfile/share/man/man4/umass.4 (revision 276056) +++ projects/sendfile/share/man/man4/umass.4 (revision 276057) @@ -1,262 +1,262 @@ .\" Copyright (c) 1999 .\" Nick Hibma . 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$ .\" .Dd April 19, 2014 .Dt UMASS 4 .Os .Sh NAME .Nm umass .Nd USB Mass Storage Devices driver .Sh SYNOPSIS To compile this driver into the kernel, place the following line in your kernel configuration file: .Bd -ragged -offset indent .Cd "device scbus" .Cd "device usb" .Cd "device umass" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent umass_load="YES" .Ed .Sh DESCRIPTION The .Nm driver provides support for Mass Storage devices that attach to the USB port. .Pp To use the .Nm driver, .Xr usb 4 and one of .Xr uhci 4 or .Xr ohci 4 or .Xr ehci 4 -or +or .Xr xhci 4 must be configured in the kernel. Additionally, since .Nm uses the SCSI subsystem and sometimes acts as a SCSI device, it requires .Xr da 4 and .Xr scbus 4 to be included in the kernel. .Sh HARDWARE The .Nm driver supports USB Mass Storage devices, including: .Pp .Bl -bullet -compact .It ADTEC Stick Drive AD-UST32M, 64M, 128M, 256M .It Denno FireWire/USB2 Removable 2.5-inch HDD Case MIFU-25CB20 .It FujiFilm Zip USB Drive ZDR100 USB A .It GREEN HOUSE USB Flash Memory "PicoDrive" GH-UFD32M, 64M, 128M .It Huawei Mobile (SD slot) .It IBM 32MB USB Memory Key (P/N 22P5296) .It IBM 256MB USB Drive (MSYSTEM DiskOnKey2) .It IBM ThinkPad USB Portable CD-ROM Drive (P/N 33L5151) .It I-O DATA USB CD/CD-R/CD-RW/DVD-R/DVD-RW/DVD-RAM/DVD-ROM Drive DVR-iUH2 (CDROM, DVD-RAM only) .It I-O DATA USB x6 CD-RW Drive CDRW-i64/USB (CDROM only) .It I-O DATA USB/IEEE1394 Portable HD Drive HDP-i30P/CI, HDP-i40P/CI .It Iomega USB Zip 100/250 drive .It Iomega Zip750 USB2.0 drive .It Keian USB1.1/2.0 3.5-inch HDD Case KU350A .It Kurouto Shikou USB 2.5-inch HDD Case GAWAP2.5PS-USB2.0 .It LaCie P3 HardDrive USB 200GB .It Logitec LDR-H443U2 DVD-RAM/-R/+R/-RW/+RW drive .It Logitec Mobile USB Memory LMC-256UD .It Logitec USB1.1/2.0 HDD Unit SHD-E60U2 .It Logitec USB Double-Speed Floppy Drive LFD-31U2 .It Logitec USB/IEEE1394 DVD-RAM/R/RW Unit LDR-N21FU2 (CDROM only) .It MELCO USB Flash Disk "ClipDrive", RUF-C32M, -C64M, -C128M, -C256M, -C512M .It MELCO USB Flash Disk "PetitDrive", RUF-32M, -64M, -128M, -256Mm .It MELCO USB2.0 Flash Disk "PetitDrive2", RUF-256M/U2, -512M/U2 .It MELCO USB2.0 MO Drive MO-CH640U2 .It Matshita CF-VFDU03 floppy drive .It Merlin SM300 MP3/WMA Player (256Mb) .It Microtech International, Inc.\& USB-SCSI-HD 50 USB to SCSI cable .It Motorola E398 Mobile Phone (TransFlash memory card) .It NOVAC USB2.0 2.5/3.5-inch HDD Case NV-HD351U .It PNY Attache Flash Drive .It Panasonic ("Matshita FDD CF-VFDU03") .It Panasonic KXL-CB20AN Portable DVD-ROM/CD-R/RW .It Panasonic KXL-CB35AN (DVD-ROM & CD-R/RW) .It Panasonic USB2.0 Portable CD-RW Drive KXL-RW40AN (CDROM only) .It Panasonic floppy drive .It Qware BeatZkey!\& Pro .It RATOC Systems USB2.0 Removable HDD Case U2-MDK1, U2-MDK1B .It SanDisk SDDR-31 (Compact Flash) .It SanDisk SDDR-75 (only Compact Flash port works) .It Sitecom CN-300 MultiFlash (MMC/SD, SmartMedia, CF, MemoryStick) .It Sony Portable CD-R/RW Drive CRX10U (CDROM only) .It TEAC Portable USB CD-ROM Unit CD-110PU/210PU .It Time DPA20B MP3 Player (1Gb) .It Trek Thumbdrive 8MB .It VAIO floppy drive (includes Y-E Data Flashbuster-U) .It Y-E Data floppy drive (720/1.44/2.88Mb) .El .Pp Among the supported digital cameras are: .Pp .Bl -bullet -compact .It Asahi Optical (PENTAX) Optio 230 & 330 .El .Sh EXAMPLES .Bd -literal -offset indent device umass device scbus device da device pass .Ed .Pp Add the .Nm driver to the kernel. .Pp .Dl "camcontrol rescan 0" .Pp Rescan a Zip drive that was added after boot. The command above assumes that the Zip drive is on the first SCSI bus in the system. .Bd -literal -offset indent camcontrol rescan 0:0:0 camcontrol rescan 0:0:1 camcontrol rescan 0:0:2 camcontrol rescan 0:0:3 .Ed .Pp Rescan all slots on a multi-slot flash reader, where the slots map to separate LUNs on a single SCSI ID. Typically only the first slot will be enabled at boot time. Again, this assumes that the flash reader is the first SCSI bus in the system. .Bd -literal -offset indent bsdlabel -w da0 zip100 newfs da0c mount -t ufs /dev/da0c /mnt .Ed .Pp Write a disklabel to the Zip drive (see .Xr vpo 4 for the .Xr disktab 5 entry), creates the file system and mounts the new file system on /mnt. .Pp .Dl "newfs_msdos /dev/da0" .Pp Create a new FAT type file system. Care should be taken not to run .Xr newfs 8 on devices that already contain data, as this will result in the information being lost. .Pp Many consumer devices such as digital cameras automatically create .Tn MS-DOS based file systems when storing information such as images and videos. These file systems can be accessed by specifying the file system type as .Cm msdosfs when using .Xr mount 8 . .Sh SEE ALSO .Xr ehci 4 , .Xr xhci 4 , .Xr ohci 4 , .Xr uhci 4 , .Xr usb 4 , .Xr vpo 4 , .Xr disktab 5 , .Xr bsdlabel 8 , .Xr camcontrol 8 .\".Sh HISTORY .Sh AUTHORS .An -nosplit The .Nm driver was written by .An MAEKAWA Masahide Aq Mt bishop@rr.iij4u.or.jp and .An Nick Hibma Aq Mt n_hibma@FreeBSD.org . .Pp This manual page was written by .An Nick Hibma Aq Mt n_hibma@FreeBSD.org . Index: projects/sendfile/share/man/man4/ural.4 =================================================================== --- projects/sendfile/share/man/man4/ural.4 (revision 276056) +++ projects/sendfile/share/man/man4/ural.4 (revision 276057) @@ -1,165 +1,165 @@ .\" Copyright (c) 2005, 2006 .\" Damien Bergamini .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .\" $FreeBSD$ .\" .Dd April 13, 2008 .Dt URAL 4 .Os .Sh NAME .Nm ural .Nd "Ralink Technology RT2500USB IEEE 802.11 driver" .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device ehci" .Cd "device uhci" .Cd "device ohci" .Cd "device usb" .Cd "device ural" .Cd "device wlan" .Cd "device wlan_amrr" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent if_ural_load="YES" .Ed .Sh DESCRIPTION The .Nm driver supports USB 2.0 wireless adapters based on the RT2500USB chipset. .Pp The RT2500USB chipset consists of two integrated chips, a RT2570 MAC/BBP and a radio transceiver (the model of which depends on the card revision). .Pp The RT2522, RT2523, RT2524, RT2525, RT2525e and RT2526 radio transceivers operate in the 2.4GHz band (802.11b/g) whereas the RT5222 is a dual-band radio transceiver that can operate in the 2.4GHz and 5.2GHz bands (802.11a). .Pp .Nm supports .Cm station , .Cm adhoc , .Cm hostap , and .Cm monitor mode operation. Only one virtual interface may be configured at any time. For more information on configuring this device, see .Xr ifconfig 8 . .Sh HARDWARE The .Nm driver supports USB 2.0 wireless adapters based on the Ralink Technology RT2500USB chipset, including: .Pp .Bl -column -compact ".Li Atlantis Land A02-PCM-W54" "Bus" .It Em Card Ta Em Bus .It "AMIT WL532U" Ta USB .It "ASUS WL-167g" Ta USB .It "Belkin F5D7050 v2000" Ta USB .It "Buffalo WLI-U2-KG54-AI" Ta USB .It "CNet CWD-854" Ta USB .It "Compex WLU54G 2A1100" Ta USB .It "Conceptronic C54RU" Ta USB .It "D-Link DWL-G122 b1" Ta USB .It "Dynalink WLG25USB" Ta USB .It "E-Tech WGUS02" Ta USB .It "Gigabyte GN-WBKG" Ta USB .It "Hercules HWGUSB2-54" Ta USB .It "KCORP LifeStyle KLS-685" Ta USB .It "Linksys WUSB54G v4" Ta USB .It "Linksys WUSB54GP v4" Ta USB .It "MSI MS-6861" Ta USB .It "MSI MS-6865" Ta USB .It "MSI MS-6869" Ta USB .It "NovaTech NV-902" Ta USB .It "OvisLink Evo-W54USB" Ta USB .It "SerComm UB801R" Ta USB .It "SparkLAN WL-685R" Ta USB .It "Surecom EP-9001-g" Ta USB .It "Sweex LC100060" Ta USB .It "Tonze UW-6200C" Ta USB .It "Zinwell ZWX-G261" Ta USB .It "Zonet ZEW2500P" Ta USB .El .Pp An up to date list can be found at .Pa http://ralink.rapla.net/ . .Sh EXAMPLES Join an existing BSS network (i.e., connect to an access point): .Bd -literal -offset indent ifconfig wlan create wlandev ural0 inet 192.168.0.20 \e netmask 0xffffff00 .Ed .Pp Join a specific BSS network with network name .Dq Li my_net : .Pp .Dl "ifconfig wlan create wlandev ural0 ssid my_net up" .Pp Join a specific BSS network with 64-bit WEP encryption: .Bd -literal -offset indent ifconfig wlan create wlandev ural0 ssid my_net \e wepmode on wepkey 0x1234567890 weptxkey 1 up .Ed .Pp Join a specific BSS network with 128-bit WEP encryption: .Bd -literal -offset indent ifconfig wlan create wlandev ural0 wlanmode adhoc ssid my_net \e wepmode on wepkey 0x01020304050607080910111213 weptxkey 1 .Ed .Sh DIAGNOSTICS .Bl -diag .It "ural%d: device timeout" The driver will reset the hardware. This should not happen. .El .Sh SEE ALSO .Xr intro 4 , .Xr netintro 4 , .Xr usb 4 , .Xr wlan 4 , .Xr wlan_amrr 4 , .Xr wlan_ccmp 4 , .Xr wlan_tkip 4 , .Xr wlan_wep 4 , .Xr wlan_xauth 4 , -.Xr ifconfig 8 , .Xr hostapd 8 , -.Xr wpa_supplicant 8 . +.Xr ifconfig 8 , +.Xr wpa_supplicant 8 .Rs .%T "Ralink Technology" .%U http://www.ralinktech.com/ .Re .Sh HISTORY The .Nm driver first appeared in .Ox 3.7 . .Sh AUTHORS The original .Nm driver was written by .An Damien Bergamini Aq Mt damien.bergamini@free.fr . .Sh BUGS Host AP mode doesn't support client power save. Clients using power save mode will experience packet loss (disabling power saving on the client will fix this). Index: projects/sendfile/share/man/man4/usfs.4 =================================================================== --- projects/sendfile/share/man/man4/usfs.4 (revision 276056) +++ projects/sendfile/share/man/man4/usfs.4 (revision 276057) @@ -1,62 +1,62 @@ .\" .\" Copyright (c) 2014 Hans Petter Selasky .\" 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$ .\" .Dd March 18, 2014 .Dt USFS 4 .Os .Sh NAME .Nm usfs .Nd USB device side support for bulk only transport mass storage .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device usb" .Cd "device usfs" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent usfs_load="YES" .Ed .Sh DESCRIPTION The .Nm driver provides support for emulating an USB mass storage device when the USB stack is activated in USB device side mode. .Pp Upon attach the driver creates a RAM disk which can be read and written. .Sh SEE ALSO -.Xr umass 4 +.Xr umass 4 , .Xr usb 4 .Sh HISTORY The .Nm driver appeared in FreeBSD 8. Index: projects/sendfile/share/man/man4/virtio_console.4 =================================================================== --- projects/sendfile/share/man/man4/virtio_console.4 (revision 276056) +++ projects/sendfile/share/man/man4/virtio_console.4 (revision 276057) @@ -1,67 +1,67 @@ .\" Copyright (c) 2014 Bryan Venteicher .\" 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$ .\" .Dd October 22, 2014 .Dt VIRTIO_CONSOLE 4 .Os .Sh NAME .Nm virtio_console .Nd VirtIO Console driver .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device virtio_console" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent virtio_console_load="YES" .Ed .Sh DESCRIPTION The .Nm device driver provides support for VirtIO console devices. .Pp The console device may have one or more ports. Each port is similar to a simple serial interface, and each port is accessible through .Xr tty 4 . .Sh FILES .Bl -tag -width ".Pa /dev/ttyV?.??" -compact .It Pa /dev/ttyV?.?? .El .Sh SEE ALSO -.Xr tty 4 +.Xr tty 4 , .Xr virtio 4 .Sh HISTORY The .Nm driver was written by .An Bryan Venteicher Aq bryanv@FreeBSD.org . Index: projects/sendfile/share/man/man4/virtio_random.4 =================================================================== --- projects/sendfile/share/man/man4/virtio_random.4 (revision 276056) +++ projects/sendfile/share/man/man4/virtio_random.4 (revision 276057) @@ -1,61 +1,61 @@ .\" Copyright (c) 2013 Bryan Venteicher .\" 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$ .\" .Dd December 28, 2013 .Dt VIRTIO_RANDOM 4 .Os .Sh NAME .Nm virtio_random .Nd VirtIO Entropy driver .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device virtio_random" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent virtio_random_load="YES" .Ed .Sh DESCRIPTION The .Nm device driver provides support for VirtIO entropy devices. .Pp The entropy device supplies high-quality randomness from the hypervisor to the guest. .Sh SEE ALSO -.Xr random 4 +.Xr random 4 , .Xr virtio 4 .Sh HISTORY The .Nm driver was written by .An Bryan Venteicher Aq Mt bryanv@FreeBSD.org . Index: projects/sendfile/share/man/man4/vxlan.4 =================================================================== --- projects/sendfile/share/man/man4/vxlan.4 (revision 276056) +++ projects/sendfile/share/man/man4/vxlan.4 (revision 276057) @@ -1,235 +1,235 @@ .\" Copyright (c) 2014 Bryan Venteicher .\" 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$ .\" .Dd December 16, 2014 .Dt VXLAN 4 .Os .Sh NAME .Nm vxlan .Nd "Virtual eXtensible LAN interface" .Sh SYNOPSIS To compile this driver into the kernel, place the following line in your kernel configuration file: .Bd -ragged -offset indent .Cd "device vxlan" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent if_vxlan_load="YES" .Ed .Sh DESCRIPTION The .Nm driver creates a virtual tunnel endpoint in a .Nm segment. A .Nm segment is a virtual Layer 2 (Ethernet) network that is overlaid in a Layer 3 (IP/UDP) network. .Nm is analogous to .Xr vlan 4 but is designed to be better suited for large, multiple tenant data center environments. .Pp Each .Nm interface is created at runtime using interface cloning. This is most easily done with the .Xr ifconfig 8 .Cm create command or using the .Va cloned_interfaces variable in .Xr rc.conf 5 . The interface may be removed with the .Xr ifconfig 8 .Cm destroy command. .Pp The .Nm driver creates a pseudo Ethernet network interface that supports the usual network .Xr ioctl 2 Ns s and is thus can be used with .Xr ifconfig 8 like any other Ethernet interface. The .Nm interface encapsulates the Ethernet frame by prepending IP/UDP and .Nm headers. Thus, the encapsulated (inner) frame is able to transmitted over a routed, Layer 3 network to the remote host. .Pp The .Nm interface may be configured in either unicast or multicast mode. When in unicast mode, the interface creates a tunnel to a single remote host, and all traffic is transmitted to that host. When in multicast mode, the interface joins an IP multicast group, and receives packets sent to the group address, and transmits packets to either the multicast group address, or directly the remote host if there is an appropriate forwarding table entry. .Pp When the .Nm interface is brought up, a .Xr UDP 4 .Xr socket 9 is created based on the configuration, such as the local address for unicast mode or the group address for multicast mode, and the listening (local) port number. Since multiple .Nm interfaces may be created that either use the same local address or join the same group address, and use the same port, the driver may share a socket among multiple interfaces. However, each interface within a socket must belong to a unique .Nm segment. The analogous .Xr vlan 4 configuration would be a physical interface configured as the parent device for multiple VLAN interfaces, each with a unique VLAN tag. Each .Nm segment is identified by a 24-bit value in the .Nm header called the .Dq VXLAN Network Identifier , or VNI. .Pp When configured with the .Xr ifconfig 8 .Cm vxlanlearn parameter, the interface dynamically creates forwarding table entries from received packets. An entry in the forwarding table maps the inner source MAC address to the outer remote IP address. During transmit, the interface attempts to lookup an entry for the encapsulated destination MAC address. If an entry is found, the IP address in the entry is used to directly transmit the encapsulated frame to the destination. Otherwise, when configured in multicast mode, the interface must flood the frame to all hosts in the group. The maximum number of entries in the table is configurable with the .Xr ifconfig 8 .Cm vxlanmaxaddr command. Stale entries in the table periodically pruned. The timeout is configurable with the .Xr ifconfig 8 .Cm vxlantimeout command. The table may be viewed with the .Xr sysctl 8 .Cm net.link.vxlan.N.ftable.dump command. .Sh MTU Since the .Nm interface encapsulates the Ethernet frame with an IP, UDP, and .Nm header, the resulting frame may be larger than the MTU of the physical network. The .Nm specification recommends the physical network MTU be configured to use jumbo frames to accommodate the encapsulated frame size. Alternatively, the .Xr ifconfig 8 .Cm mtu command may be used to reduce the MTU size on the .Nm interface to allow the encapsulated frame to fit in the current MTU of the physical network. .Sh EXAMPLES Create a .Nm interface in unicast mode with the .Cm vxlanlocal tunnel address of 192.168.100.1, and the .Cm vxlanremote tunnel address of 192.168.100.2. .Bd -literal -offset indent ifconfig vxlan create vxlanid 108 vxlanlocal 192.168.100.1 vxlanremote 192.168.100.2 .Ed .Pp Create a .Nm interface in multicast mode, with the .Cm local address of 192.168.10.95, and the .Cm group address of 224.0.2.6. The em0 interface will be used to transmit multicast packets. .Bd -literal -offset indent ifconfig vxlan create vxlanid 42 vxlanlocal 192.168.10.95 vxlangroup 224.0.2.6 vxlandev em0 .Ed .Pp Once created, the .Nm interface can be configured with .Xr ifconfig 8 . .Sh SEE ALSO -.Xr ifconfig 8 , .Xr inet 4 , -.Xr inet 6 , +.Xr inet6 4 , +.Xr ifconfig 8 , .Xr sysctl 8 , .Xr vlan 8 .Rs .%A "M. Mahalingam" .%A "et al" .%T "Virtual eXtensible Local Area Network (VXLAN): A Framework for Overlaying Virtualized Layer 2 Networks over Layer 3 Networks" .%D August 2014 .%O "RFC 7348" .Re .Sh AUTHOR .An -nosplit The .Nm driver was written by .An Bryan Venteicher Aq bryanv@freebsd.org . Index: projects/sendfile/share/man/man4/wpi.4 =================================================================== --- projects/sendfile/share/man/man4/wpi.4 (revision 276056) +++ projects/sendfile/share/man/man4/wpi.4 (revision 276057) @@ -1,144 +1,144 @@ .\" Copyright (c) 2004-2007 .\" Damien Bergamini . All rights reserved. .\" Benjamin Close . 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 unmodified, 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$ .\" .Dd October 5, 2008 .Dt WPI 4 .Os .Sh NAME .Nm wpi .Nd "Intel 3945ABG Wireless LAN IEEE 802.11 driver" .Sh SYNOPSIS To compile this driver into the kernel, place the following lines in your kernel configuration file: .Bd -ragged -offset indent .Cd "device wpi" .Cd "device wpifw" .Cd "device pci" .Cd "device wlan" .Cd "device wlan_amrr" .Cd "device firmware" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent if_wpi_load="YES" .Ed .Sh DESCRIPTION The .Nm driver provides support for the .Tn Intel 3945ABG Wireless network adapter. .Nm supports .Cm station , .Cm adhoc , and .Cm monitor mode operation. Only one virtual interface may be configured at any time. For more information on configuring this device, see .Xr ifconfig 8 . .Pp This driver requires the firmware built with the .Nm wpifw module to work. .Sh FILES .Bl -tag -width ".Pa /usr/share/doc/legal/intel_wpi/LICENSE" -compact .It Pa /usr/share/doc/legal/intel_wpi/LICENSE .Nm firmware license .El .Sh EXAMPLES Join an existing BSS network (i.e., connect to an access point): .Bd -literal -offset indent ifconfig wlan0 create wlandev wpi0 inet 192.168.0.20 \e netmask 0xffffff00 .Ed .Pp Join a specific BSS network with network name .Dq Li my_net : .Pp .Dl "ifconfig wlan0 create wlandev wpi0 ssid my_net up" .Pp Join a specific BSS network with 64-bit WEP encryption: .Bd -literal -offset indent ifconfig wlan0 create wlandev wpi0 ssid my_net \e wepmode on wepkey 0x1234567890 weptxkey 1 up .Ed .Pp Join a specific BSS network with 128-bit WEP encryption: .Bd -literal -offset indent ifconfig wlan0 create wlandev wpi0 wlanmode adhoc ssid my_net \e wepmode on wepkey 0x01020304050607080910111213 weptxkey 1 .Ed .Sh DIAGNOSTICS .Bl -diag .It "wpi%d: could not load firmware image '%s'" The driver failed to load the firmware image using the .Xr firmware 9 subsystem. Verify the .Xr wpifw firmware module is installed. .It "wpi%d: fatal firmware error" An unknown error has occurred in the uploaded firmware, you may have to unload/reload the driver to continue. .It "wpi%d: Radio transmitter is switched off" The hardware switch controlling the radio is currently turned off. Data transmission is not possible in this state. .El .Sh SEE ALSO -.Xr wpifw 4 , .Xr pci 4 , .Xr wlan 4 , .Xr wlan_ccmp 4 , .Xr wlan_tkip 4 , .Xr wlan_wep 4 , +.Xr wpifw 4 , .Xr ifconfig 8 , .Xr wpa_supplicant 8 .Sh AUTHORS .An -nosplit The original .Nm driver was written for .Ox by .An Damien Bergamini Aq Mt damien.bergamini@free.fr . .An Benjamin Close Aq Mt benjsc@FreeBSD.org ported .Nm to .Fx . .Sh BUGS Not all the error messages are documented here. .Pp Background scanning is not currently supported. Index: projects/sendfile/share/man/man4/wsp.4 =================================================================== --- projects/sendfile/share/man/man4/wsp.4 (revision 276056) +++ projects/sendfile/share/man/man4/wsp.4 (revision 276057) @@ -1,90 +1,90 @@ .\" Copyright (c) 2014 Hans Petter Selasky . .\" 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$ .\" .Dd February 7, 2014 .Dt WSP 4 .Os .Sh NAME .Nm wsp .Nd Wellspring touchpad driver .Sh SYNOPSIS To compile this driver into the kernel, place the following lines into your kernel configuration file: .Bd -ragged -offset indent .Cd "device wsp" .Cd "device usb" .Ed .Pp Alternatively, to load the driver as a module at boot time, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent wsp_load="YES" .Ed .Sh DESCRIPTION The .Nm driver provides support for the Apple Internal Trackpad device found in many Apple laptops. .Pp The driver simulates a three-button mouse using multi-finger tap detection. -A single-finger press generates a left button click. +A single-finger press generates a left button click. A two-finger tap maps to the right button; whereas a three-finger tap gets treated as a middle button click. .Pp .Nm supports dynamic reconfiguration using .Xr sysctl 8 through nodes under .Nm hw.usb.wsp . Pointer sensitivity can be controlled using the sysctl tunable .Nm hw.usb.wsp.scale_factor . .Sh FILES .Nm creates a blocking pseudo-device file, .Pa /dev/wsp0 , which presents the mouse as a .Em sysmouse or .Em mousesystems type device--see .Xr moused 8 for an explanation of these mouse types. .Sh SEE ALSO .Xr sysmouse 4 , .Xr usb 4 , .Xr loader.conf 5 , .Xr xorg.conf 5 Pq Pa ports/x11/xorg , .Xr moused 8 , .Xr sysctl 8 .Sh AUTHORS .An -nosplit The .Nm driver was written by .An Huang Wen Hui Aq Mt huanghwh@gmail.com . Index: projects/sendfile/share/man/man4 =================================================================== --- projects/sendfile/share/man/man4 (revision 276056) +++ projects/sendfile/share/man/man4 (revision 276057) Property changes on: projects/sendfile/share/man/man4 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/share/man/man4:r275989-276056 Index: projects/sendfile/share/man/man5/periodic.conf.5 =================================================================== --- projects/sendfile/share/man/man5/periodic.conf.5 (revision 276056) +++ projects/sendfile/share/man/man5/periodic.conf.5 (revision 276057) @@ -1,976 +1,976 @@ .\"- .\" Copyright (c) 2000 Brian Somers .\" 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$ .\" .Dd December 25, 2013 .Dt PERIODIC.CONF 5 .Os .Sh NAME .Nm periodic.conf .Nd periodic job configuration information .Sh DESCRIPTION The file .Nm contains a description of how daily, weekly and monthly system maintenance jobs should run. It resides in the .Pa /etc/defaults directory and parts may be overridden by a file of the same name in .Pa /etc , which itself may be overridden by the .Pa /etc/periodic.conf.local file. .Pp The .Nm file is actually sourced as a shell script from each of the periodic scripts and is intended to simply provide default configuration variables. .Pp The following variables are used by .Xr periodic 8 itself: .Bl -tag -offset 4n -width 2n .It Va local_periodic .Pq Vt str List of directories to search for periodic scripts. This list is always prefixed with .Pa /etc/periodic , and is only used when an argument to .Xr periodic 8 is not an absolute directory name. .It Ao Ar dir Ac Ns Va _output .Pq Vt path No or Vt list What to do with the output of the scripts executed from the directory .Ar dir . If this variable is set to an absolute path name, output is logged to that file, otherwise it is taken as one or more space separated email addresses and mailed to those users. If this variable is not set or is empty, output is sent to standard output. .Pp For an unattended machine, suitable values for .Va daily_output , .Va weekly_output , and .Va monthly_output might be .Dq Li /var/log/daily.log , .Dq Li /var/log/weekly.log , and .Dq Li /var/log/monthly.log respectively, as .Xr newsyslog 8 will rotate these files (if they exists) at the appropriate times. .It Ao Ar dir Ac Ns Va _show_success .It Ao Ar dir Ac Ns Va _show_info .It Ao Ar dir Ac Ns Va _show_badconfig .Pq Vt bool These variables control whether .Xr periodic 8 will mask the output of the executed scripts based on their return code (where .Ar dir is the base directory name in which each script resides). If the return code of a script is .Sq 0 and .Ao Ar dir Ac Ns Va _show_success is set to .Dq Li NO , .Xr periodic 8 will mask the script's output. If the return code of a script is .Sq 1 and .Ao Ar dir Ac Ns Va _show_info is set to .Dq Li NO , .Xr periodic 8 will mask the script's output. If the return code of a script is .Sq 2 and .Ao Ar dir Ac Ns Va _show_badconfig is set to .Dq Li NO , .Xr periodic 8 will mask the script's output. If these variables are set to neither .Dq Li YES nor .Dq Li NO , they default to .Dq Li YES , .Dq Li YES and .Dq Li NO respectively. .Pp Refer to the .Xr periodic 8 manual page for how script return codes are interpreted. .El .Pp The following variables are used by the standard scripts that reside in .Pa /etc/periodic/daily : .Bl -tag -offset 4n -width 2n .It Va daily_clean_disks_enable .Pq Vt bool Set to .Dq Li YES if you want to remove all files matching .Va daily_clean_disks_files daily. .It Va daily_clean_disks_files .Pq Vt str Set to a list of file names to match. Wild cards are permitted. .It Va daily_clean_disks_days .Pq Vt num When .Va daily_clean_disks_enable is set to .Dq Li YES , this must also be set to the number of days old that a file's access and modification times must be before it is deleted. .It Va daily_clean_disks_verbose .Pq Vt bool Set to .Dq Li YES if you want the removed files to be reported in your daily output. .It Va daily_clean_tmps_enable .Pq Vt bool Set to .Dq Li YES if you want to clear temporary directories daily. .It Va daily_clean_tmps_dirs .Pq Vt str Set to the list of directories to clear if .Va daily_clean_tmps_enable is set to .Dq Li YES . .It Va daily_clean_tmps_days .Pq Vt num When .Va daily_clean_tmps_enable is set, this must also be set to the number of days old that a file's access and modification times must be before it is deleted. .It Va daily_clean_tmps_ignore .Pq Vt str Set to the list of files that should not be deleted when .Va daily_clean_tmps_enable is set to .Dq Li YES . Wild card characters are permitted. .It Va daily_clean_tmps_verbose .Pq Vt bool Set to .Dq Li YES if you want the removed files to be reported in your daily output. .It Va daily_clean_preserve_enable .Pq Vt bool Set to .Dq Li YES if you wish to remove old files from .Pa /var/preserve . .It Va daily_clean_preserve_days .Pq Vt num Set to the number of days that files must not have been modified before they are deleted. .It Va daily_clean_preserve_verbose .Pq Vt bool Set to .Dq Li YES if you want the removed files to be reported in your daily output. .It Va daily_clean_msgs_enable .Pq Vt bool Set to .Dq Li YES if you wish old system messages to be purged. .It Va daily_clean_msgs_days .Pq Vt num Set to the number of days that files must not have been modified before they are deleted. If this variable is left blank, the .Xr msgs 1 default is used. .It Va daily_clean_rwho_enable .Pq Vt bool Set to .Dq Li YES if you wish old files in .Pa /var/who to be purged. .It Va daily_clean_rwho_days .Pq Vt num Set to the number of days that files must not have been modified before they are deleted. .It Va daily_clean_rwho_verbose .Pq Vt bool Set to .Dq Li YES if you want the removed files to be reported in your daily output. .It Va daily_clean_hoststat_enable .Pq Vt bool Set to .Dq Li YES to run .Nm sendmail Fl bH to automatically purge stale entries from .Xr sendmail 8 Ns 's host status cache. Files will be deleted using the same criteria as .Xr sendmail 8 would normally use when determining whether to believe the cached information, as configured in .Pa /etc/mail/sendmail.cf . .It Va daily_backup_passwd_enable .Pq Vt bool Set to .Dq Li YES if you want the .Pa /etc/master.passwd and .Pa /etc/group files backed up and reported on. Reporting consists of checking both files for modifications and running .Xr chkgrp 8 on the .Pa group file. .It Va daily_backup_aliases_enable .Pq Vt bool Set to .Dq Li YES if you want the .Pa /etc/mail/aliases file backed up and modifications to be displayed in your daily output. .It Va daily_calendar_enable .Pq Vt bool Set to .Dq Li YES if you want to run .Nm calendar Fl a daily. .It Va daily_accounting_enable .Pq Vt bool Set to .Dq Li YES if you want to rotate your daily accounting files. No rotations are necessary unless .Va accounting_enable is enabled in .Xr rc.conf 5 . .It Va daily_accounting_compress .Pq Vt bool Set to .Dq Li YES if you want your daily accounting files to be compressed using .Xr gzip 1 . .It Va daily_accounting_save .Pq Vt num When .Va daily_accounting_enable is set, this may also be set to the number of daily accounting files that are to be saved. The default is .Dq Li 3 . .It Va daily_accounting_flags .Pq Vt str Set to the arguments to pass to the .Xr sa 8 utility (in addition to .Fl s ) when .Va daily_accounting_enable is set to .Dq Li YES . The default is .Fl q . .It Va daily_news_expire_enable .Pq Vt bool Set to .Dq Li YES if you want to run .Pa /etc/news.expire . .It Va daily_status_disks_enable .Pq Vt bool Set to .Dq Li YES if you want to run .Xr df 1 (with the arguments supplied in .Va daily_status_disks_df_flags ) and .Nm dump Fl W . .It Va daily_status_disks_df_flags .Pq Vt str Set to the arguments for the .Xr df 1 utility when .Va daily_status_disks_enable is set to .Dq Li YES . .It Va daily_status_zfs_enable .Pq Vt bool Set to .Dq Li YES if you want to run .Nm zpool Cm status on your .Xr zfs 8 pools. .It Va daily_status_zfs_zpool_list_enable .Pq Vt bool Set to .Dq Li YES if you want to run .Nm zpool Cm list on your .Xr zfs 8 pools. Requires .Va daily_status_zfs_enable to be set to .Li YES . .It Va daily_status_gmirror_enable .Pq Vt bool Set to .Dq Li YES if you want to run .Nm gmirror Cm status on your .Xr gmirror 8 devices. .It Va daily_status_graid3_enable .Pq Vt bool Set to .Dq Li YES if you want to run .Nm graid3 Cm status on your .Xr graid3 8 devices. .It Va daily_status_gstripe_enable .Pq Vt bool Set to .Dq Li YES if you want to run .Nm gstripe Cm status on your .Xr gstripe 8 devices. .It Va daily_status_gconcat_enable .Pq Vt bool Set to .Dq Li YES if you want to run .Nm gconcat Cm status on your .Xr gconcat 8 devices. .It Va daily_status_network_enable .Pq Vt bool Set to .Dq Li YES if you want to run .Nm netstat Fl i . .It Va daily_status_network_usedns .Pq Vt bool Set to .Dq Li YES if you want to run .Xr netstat 1 without the .Fl n option (to do DNS lookups). .It Va daily_status_rwho_enable .Pq Vt bool Set to .Dq Li YES if you want to run .Xr uptime 1 (or .Xr ruptime 1 if .Va rwhod_enable is set to .Dq Li YES in .Pa /etc/rc.conf ) . .It Va daily_status_mailq_enable .Pq Vt bool Set to .Dq Li YES if you want to run .Xr mailq 1 . .It Va daily_status_mailq_shorten .Pq Vt bool Set to .Dq Li YES if you want to shorten the .Xr mailq 1 output when .Va daily_status_mailq_enable is set to .Dq Li YES . .It Va daily_status_include_submit_mailq .Pq Vt bool Set to .Dq Li YES if you also want to run .Xr mailq 1 on the submit mail queue when .Va daily_status_mailq_enable is set to .Dq Li YES . This may not work with MTAs other than .Xr sendmail 8 . .It Va daily_status_security_enable .Pq Vt bool Set to .Dq Li YES if you want to run the security check. The security check is another set of .Xr periodic 8 scripts. The system defaults are in .Pa /etc/periodic/security . Local scripts should be placed in .Pa /usr/local/etc/periodic/security . See the .Xr periodic 8 manual page for more information. .It Va daily_status_security_inline .Pq Vt bool Set to .Dq Li YES if you want the security check output inline. The default is to either mail or log the output according to the value of .Va daily_status_security_output . .It Va daily_status_security_output .Pq Vt str Where to send the output of the security check if .Va daily_status_security_inline is set to .Dq Li NO . This variable behaves in the same way as the .Va *_output variables above, namely it can be set either to one or more email addresses or to an absolute file name. .It Va daily_status_mail_rejects_enable .Pq Vt bool Set to .Dq Li YES if you want to summarise mail rejections logged to .Pa /var/log/maillog for the previous day. .It Va daily_status_mail_rejects_logs .Pq Vt num Set to the number of maillog files that should be checked for yesterday's mail rejects. .It Va daily_status_ntpd .Pq Vt bool Set to .Dq Li YES if you want to enable NTP status check. .It Va daily_queuerun_enable .Pq Vt bool Set to .Dq Li YES if you want to manually run the mail queue at least once a day. .It Va daily_submit_queuerun .Pq Vt bool Set to .Dq Li YES if you also want to manually run the submit mail queue at least once a day when .Va daily_queuerun_enable is set to .Dq Li YES . .It Va daily_scrub_zfs_enable .Pq Vt bool Set to .Dq Li YES if you want to run a zfs scrub periodically. .It Va daily_scrub_zfs_pools .Pq Vt str A space separated list of names of zfs pools to scrub. If the list is empty or not set, all zfs pools are scrubbed. .It Va daily_scrub_zfs_default_threshold .Pq Vt int Number of days between a scrub if no pool-specific threshold is set. If not set, the default value is 35, corresponding to 5 weeks. .It Va daily_scrub_zfs_ Ns Ao Ar poolname Ac Ns Va _threshold .Pq Vt int The same as .Va daily_scrub_zfs_default_threshold but specific to the pool .Ao Ar poolname Ac Ns . .It Va daily_local .Pq Vt str Set to a list of extra scripts that should be run after all other daily scripts. All scripts must be absolute path names. .El .Pp The following variables are used by the standard scripts that reside in .Pa /etc/periodic/weekly : .Bl -tag -offset 4n -width 2n .It Va weekly_locate_enable .Pq Vt bool Set to .Dq Li YES if you want to run .Pa /usr/libexec/locate.updatedb . This script is run using .Nm nice Fl 5 as user .Dq Li nobody , and generates the table used by the .Xr locate 1 command. .It Va weekly_whatis_enable .Pq Vt bool Set to .Dq Li YES if you want to run .Pa /usr/libexec/makewhatis.local . This script regenerates the database used by the .Xr apropos 1 command. .It Va weekly_catman_enable .Pq Vt bool Set to .Dq Li YES if you want to run .Pa /usr/libexec/catman.local . This script processes all out of date manual pages, speeding up the .Xr man 1 command at the expense of disk space. .It Va weekly_noid_enable .Pq Vt bool Set to .Dq Li YES if you want to locate orphaned files on the system. An orphaned file is one with an invalid owner or group. .It Va weekly_noid_dirs .Pq Vt str A list of directories under which orphaned files are searched for. This would usually be set to .Pa / . .It Va weekly_status_security_enable .Pq Vt bool Weekly counterpart of .Va daily_status_securiy_enable . .It Va weekly_status_security_inline .Pq Vt bool Weekly counterpart of .Va daily_status_securiy_inline . .It Va weekly_status_security_output .Pq Vt str Weekly counterpart of .Va daily_status_securiy_output . .It Va weekly_status_pkg_enable .Pq Vt bool Set to .Dq Li YES if you want to use .Xr pkg_version 1 to list installed packages which are out of date. .It Va pkg_version .Pq Vt str When .Va weekly_status_pkg_enable is set to .Dq Li YES , this variable specifies the program that is used to determine the out of date packages. If unset, the .Xr pkg_version 1 program is used. As an example, this variable might be set to .Dq Li portversion if the .Pa ports/sysutils/portupgrade port has been installed. .It Va pkg_version_index .Pq Vt str This variable specifies the .Pa INDEX file from .Pa /usr/ports that should be used by .Xr pkg_version 1 . Because the dependency tree may be substantially different between versions of .Fx , there may be more than one .Pa INDEX file in .Pa /usr/ports . .Pp Note, if the .Va pkg_version variable is set to .Dq Li portversion , it will also be necessary to arrange that the correct .Pa INDEX file is specified using environment variables and that .Va pkg_version_index is cleared in .Pa /etc/periodic.conf .Pq Dq Li pkg_version_index= . .It Va weekly_local .Pq Vt str Set to a list of extra scripts that should be run after all other weekly scripts. All scripts must be absolute path names. .El .Pp The following variables are used by the standard scripts that reside in .Pa /etc/periodic/monthly : .Bl -tag -offset 4n -width 2n .It Va monthly_accounting_enable .Pq Vt bool Set to .Dq Li YES if you want to do login accounting using the .Xr ac 8 command. .It Va monthly_status_security_enable .Pq Vt bool Monthly counterpart of .Va daily_status_securiy_enable . .It Va monthly_status_security_inline .Pq Vt bool Monthly counterpart of .Va daily_status_securiy_inline . .It Va monthly_status_security_output .Pq Vt str Monthly counterpart of .Va daily_status_securiy_output . .It Va monthly_local .Pq Vt str Set to a list of extra scripts that should be run after all other monthly scripts. All scripts must be absolute path names. .El .Pp The following variables are used by the standard scripts that reside in .Pa /etc/periodic/security . Those scripts are usually run from daily .Pq Va daily_status_security_enable , weekly .Pq Va weekly_status_security_enable , and monthly .Pq Va monthly_status_security_enable periodic hooks. The .Va ..._period of each script can be configured as .Dq daily , .Dq weekly , .Dq monthly or .Dq NO . Note that when periodic security scripts are run from .Xr crontab 5 , they will be always run unless their .Va ..._enable or .Va ..._period variable is set to -.Dq No . +.Dq NO . .Bl -tag -offset 4n -width 2n .It Va security_status_diff_flags .Pq Vt str Set to the arguments to pass to the .Xr diff 1 utility when generating differences. The default is .Fl b u . .It Va security_status_chksetuid_enable .Pq Vt bool Set to .Dq Li YES to compare the modes and modification times of setuid executables with the previous day's values. .It Va security_status_chksetuid_period .Pq Vt str Set to either .Dq Li daily , .Dq Li weekly , .Dq Li monthly or .Dq Li NO . .It Va security_status_chkportsum_enable .Pq Vt bool Set to .Dq Li YES to verify checksums of all installed packages against the known checksums in .Pa /var/db/pkg . .It Va security_status_chkportsum_period .Pq Vt str Set to either .Dq Li daily , .Dq Li weekly , .Dq Li monthly or .Dq Li NO . .It Va security_status_neggrpperm_enable .Pq Vt bool Set to .Dq Li YES to check for files where the group of a file has less permissions than the world at large. When users are in more than 14 supplemental groups these negative permissions may not be enforced via NFS shares. .It Va security_status_neggrpperm_period .Pq Vt str Set to either .Dq Li daily , .Dq Li weekly , .Dq Li monthly or .Dq Li NO . .It Va security_status_chkmounts_enable .Pq Vt bool Set to .Dq Li YES to check for changes mounted file systems to the previous day's values. .It Va security_status_chkmounts_period .Pq Vt str Set to either .Dq Li daily , .Dq Li weekly , .Dq Li monthly or .Dq Li NO . .It Va security_status_noamd .Pq Vt bool Set to .Dq Li YES if you want to ignore .Xr amd 8 mounts when comparing against yesterday's file system mounts in the .Va security_status_chkmounts_enable check. .It Va security_status_chkuid0_enable .Pq Vt bool Set to .Dq Li YES to check .Pa /etc/master.passwd for accounts with UID 0. .It Va security_status_chkuid0_period .Pq Vt str Set to either .Dq Li daily , .Dq Li weekly , .Dq Li monthly or .Dq Li NO . .It Va security_status_passwdless_enable .Pq Vt bool Set to .Dq Li YES to check .Pa /etc/master.passwd for accounts with empty passwords. .It Va security_status_passwdless_period .Pq Vt str Set to either .Dq Li daily , .Dq Li weekly , .Dq Li monthly or .Dq Li NO . .It Va security_status_logincheck_enable .Pq Vt bool Set to .Dq Li YES to check .Pa /etc/login.conf ownership, see .Xr login.conf 5 for more information. .It Va security_status_logincheck_period .Pq Vt str Set to either .Dq Li daily , .Dq Li weekly , .Dq Li monthly or .Dq Li NO . .It Va security_status_ipfwdenied_enable .Pq Vt bool Set to .Dq Li YES to show log entries for packets denied by .Xr ipfw 8 since yesterday's check. .It Va security_status_ipfwdenied_period .Pq Vt str Set to either .Dq Li daily , .Dq Li weekly , .Dq Li monthly or .Dq Li NO . .It Va security_status_ipfdenied_enable .Pq Vt bool Set to .Dq Li YES to show log entries for packets denied by .Xr ipf 8 since yesterday's check. .It Va security_status_ipfdenied_period .Pq Vt str Set to either .Dq Li daily , .Dq Li weekly , .Dq Li monthly or .Dq Li NO . .It Va security_status_pfdenied_enable .Pq Vt bool Set to .Dq Li YES to show log entries for packets denied by .Xr pf 4 since yesterday's check. .It Va security_status_pfdenied_period .Pq Vt str Set to either .Dq Li daily , .Dq Li weekly , .Dq Li monthly or .Dq Li NO . .It Va security_status_ipfwlimit_enable .Pq Vt bool Set to .Dq Li YES to display .Xr ipfw 8 rules that have reached their verbosity limit. .It Va security_status_ipfwlimit_period .Pq Vt str Set to either .Dq Li daily , .Dq Li weekly , .Dq Li monthly or .Dq Li NO . .It Va security_status_kernelmsg_enable .Pq Vt bool Set to .Dq Li YES to show new .Xr dmesg 8 entries since yesterday's check. .It Va security_status_kernelmsg_period .Pq Vt str Set to either .Dq Li daily , .Dq Li weekly , .Dq Li monthly or .Dq Li NO . .It Va security_status_loginfail_enable .Pq Vt bool Set to .Dq Li YES to display failed logins from .Pa /var/log/messages in the previous day. .It Va security_status_loginfail_period .Pq Vt str Set to either .Dq Li daily , .Dq Li weekly , .Dq Li monthly or .Dq Li NO . .It Va security_status_tcpwrap_enable .Pq Vt bool Set to .Dq Li YES to display connections denied by tcpwrappers (see .Xr hosts_access 5 ) from .Pa /var/log/messages during the previous day. .It Va security_status_tcpwrap_period .Pq Vt str Set to either .Dq Li daily , .Dq Li weekly , .Dq Li monthly or .Dq Li NO . .El .Sh FILES .Bl -tag -width ".Pa /etc/defaults/periodic.conf" .It Pa /etc/defaults/periodic.conf The default configuration file. This file contains all default variables and values. .It Pa /etc/periodic.conf The usual system specific variable override file. .It Pa /etc/periodic.conf.local An additional override file, useful when .Pa /etc/periodic.conf is shared or distributed. .El .Sh SEE ALSO .Xr apropos 1 , .Xr calendar 1 , .Xr df 1 , .Xr diff 1 , .Xr gzip 1 , .Xr locate 1 , .Xr man 1 , .Xr msgs 1 , .Xr netstat 1 , .Xr nice 1 , .Xr pkg_version 1 , .Xr login.conf 5 , .Xr rc.conf 5 , .Xr ac 8 , .Xr chkgrp 8 , .Xr dump 8 , .Xr newsyslog 8 , .Xr periodic 8 , .Xr sendmail 8 .Sh HISTORY The .Nm file appeared in .Fx 4.1 . .Sh AUTHORS .An Brian Somers Aq Mt brian@Awfulhak.org Index: projects/sendfile/share/man/man5/pf.conf.5 =================================================================== --- projects/sendfile/share/man/man5/pf.conf.5 (revision 276056) +++ projects/sendfile/share/man/man5/pf.conf.5 (revision 276057) @@ -1,3059 +1,3059 @@ .\" $FreeBSD$ .\" $OpenBSD: pf.conf.5,v 1.406 2009/01/31 19:37:12 sobrado Exp $ .\" .\" Copyright (c) 2002, Daniel Hartmeier .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" .\" - Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" - 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 COPYRIGHT HOLDERS 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 .\" COPYRIGHT HOLDERS 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. .\" -.Dd June 29 2012 +.Dd June 29, 2012 .Dt PF.CONF 5 .Os .Sh NAME .Nm pf.conf .Nd packet filter configuration file .Sh DESCRIPTION The .Xr pf 4 packet filter modifies, drops or passes packets according to rules or definitions specified in .Nm pf.conf . .Sh STATEMENT ORDER There are seven types of statements in .Nm pf.conf : .Bl -tag -width xxxx .It Cm Macros User-defined variables may be defined and used later, simplifying the configuration file. Macros must be defined before they are referenced in .Nm pf.conf . .It Cm Tables Tables provide a mechanism for increasing the performance and flexibility of rules with large numbers of source or destination addresses. .It Cm Options Options tune the behaviour of the packet filtering engine. .It Cm Traffic Normalization Li (e.g. Em scrub ) Traffic normalization protects internal machines against inconsistencies in Internet protocols and implementations. .It Cm Queueing Queueing provides rule-based bandwidth control. .It Cm Translation Li (Various forms of NAT) Translation rules specify how addresses are to be mapped or redirected to other addresses. .It Cm Packet Filtering Packet filtering provides rule-based blocking or passing of packets. .El .Pp With the exception of .Cm macros and .Cm tables , the types of statements should be grouped and appear in .Nm pf.conf in the order shown above, as this matches the operation of the underlying packet filtering engine. By default .Xr pfctl 8 enforces this order (see .Ar set require-order below). .Pp Comments can be put anywhere in the file using a hash mark .Pq Sq # , and extend to the end of the current line. .Pp Additional configuration files can be included with the .Ic include keyword, for example: .Bd -literal -offset indent include "/etc/pf/sub.filter.conf" .Ed .Sh MACROS Macros can be defined that will later be expanded in context. Macro names must start with a letter, and may contain letters, digits and underscores. Macro names may not be reserved words (for example .Ar pass , .Ar in , .Ar out ) . Macros are not expanded inside quotes. .Pp For example, .Bd -literal -offset indent ext_if = \&"kue0\&" all_ifs = \&"{\&" $ext_if lo0 \&"}\&" pass out on $ext_if from any to any pass in on $ext_if proto tcp from any to any port 25 .Ed .Sh TABLES Tables are named structures which can hold a collection of addresses and networks. Lookups against tables in .Xr pf 4 are relatively fast, making a single rule with tables much more efficient, in terms of processor usage and memory consumption, than a large number of rules which differ only in IP address (either created explicitly or automatically by rule expansion). .Pp Tables can be used as the source or destination of filter rules, .Ar scrub rules or translation rules such as .Ar nat or .Ar rdr (see below for details on the various rule types). Tables can also be used for the redirect address of .Ar nat and .Ar rdr rules and in the routing options of filter rules, but only for .Ar round-robin pools. .Pp Tables can be defined with any of the following .Xr pfctl 8 mechanisms. As with macros, reserved words may not be used as table names. .Bl -tag -width "manually" .It Ar manually Persistent tables can be manually created with the .Ar add or .Ar replace option of .Xr pfctl 8 , before or after the ruleset has been loaded. .It Pa pf.conf Table definitions can be placed directly in this file, and loaded at the same time as other rules are loaded, atomically. Table definitions inside .Nm pf.conf use the .Ar table statement, and are especially useful to define non-persistent tables. The contents of a pre-existing table defined without a list of addresses to initialize it is not altered when .Nm pf.conf is loaded. A table initialized with the empty list, .Li { } , will be cleared on load. .El .Pp Tables may be defined with the following attributes: .Bl -tag -width persist .It Ar persist The .Ar persist flag forces the kernel to keep the table even when no rules refer to it. If the flag is not set, the kernel will automatically remove the table when the last rule referring to it is flushed. .It Ar const The .Ar const flag prevents the user from altering the contents of the table once it has been created. Without that flag, .Xr pfctl 8 can be used to add or remove addresses from the table at any time, even when running with .Xr securelevel 7 = 2. .It Ar counters The .Ar counters flag enables per-address packet and byte counters which can be displayed with .Xr pfctl 8 . .El .Pp For example, .Bd -literal -offset indent table \*(Ltprivate\*(Gt const { 10/8, 172.16/12, 192.168/16 } table \*(Ltbadhosts\*(Gt persist block on fxp0 from { \*(Ltprivate\*(Gt, \*(Ltbadhosts\*(Gt } to any .Ed .Pp creates a table called private, to hold RFC 1918 private network blocks, and a table called badhosts, which is initially empty. A filter rule is set up to block all traffic coming from addresses listed in either table. The private table cannot have its contents changed and the badhosts table will exist even when no active filter rules reference it. Addresses may later be added to the badhosts table, so that traffic from these hosts can be blocked by using .Bd -literal -offset indent # pfctl -t badhosts -Tadd 204.92.77.111 .Ed .Pp A table can also be initialized with an address list specified in one or more external files, using the following syntax: .Bd -literal -offset indent table \*(Ltspam\*(Gt persist file \&"/etc/spammers\&" file \&"/etc/openrelays\&" block on fxp0 from \*(Ltspam\*(Gt to any .Ed .Pp The files .Pa /etc/spammers and .Pa /etc/openrelays list IP addresses, one per line. Any lines beginning with a # are treated as comments and ignored. In addition to being specified by IP address, hosts may also be specified by their hostname. When the resolver is called to add a hostname to a table, .Em all resulting IPv4 and IPv6 addresses are placed into the table. IP addresses can also be entered in a table by specifying a valid interface name, a valid interface group or the .Em self keyword, in which case all addresses assigned to the interface(s) will be added to the table. .Sh OPTIONS .Xr pf 4 may be tuned for various situations using the .Ar set command. .Bl -tag -width xxxx .It Ar set timeout .Pp .Bl -tag -width "src.track" -compact .It Ar interval Interval between purging expired states and fragments. .It Ar frag Seconds before an unassembled fragment is expired. .It Ar src.track Length of time to retain a source tracking entry after the last state expires. .El .Pp When a packet matches a stateful connection, the seconds to live for the connection will be updated to that of the .Ar proto.modifier which corresponds to the connection state. Each packet which matches this state will reset the TTL. Tuning these values may improve the performance of the firewall at the risk of dropping valid idle connections. .Pp .Bl -tag -width xxxx -compact .It Ar tcp.first The state after the first packet. .It Ar tcp.opening The state before the destination host ever sends a packet. .It Ar tcp.established The fully established state. .It Ar tcp.closing The state after the first FIN has been sent. .It Ar tcp.finwait The state after both FINs have been exchanged and the connection is closed. Some hosts (notably web servers on Solaris) send TCP packets even after closing the connection. Increasing .Ar tcp.finwait (and possibly .Ar tcp.closing ) can prevent blocking of such packets. .It Ar tcp.closed The state after one endpoint sends an RST. .El .Pp ICMP and UDP are handled in a fashion similar to TCP, but with a much more limited set of states: .Pp .Bl -tag -width xxxx -compact .It Ar udp.first The state after the first packet. .It Ar udp.single The state if the source host sends more than one packet but the destination host has never sent one back. .It Ar udp.multiple The state if both hosts have sent packets. .It Ar icmp.first The state after the first packet. .It Ar icmp.error The state after an ICMP error came back in response to an ICMP packet. .El .Pp Other protocols are handled similarly to UDP: .Pp .Bl -tag -width xxxx -compact .It Ar other.first .It Ar other.single .It Ar other.multiple .El .Pp Timeout values can be reduced adaptively as the number of state table entries grows. .Pp .Bl -tag -width xxxx -compact .It Ar adaptive.start When the number of state entries exceeds this value, adaptive scaling begins. All timeout values are scaled linearly with factor (adaptive.end - number of states) / (adaptive.end - adaptive.start). .It Ar adaptive.end When reaching this number of state entries, all timeout values become zero, effectively purging all state entries immediately. This value is used to define the scale factor, it should not actually be reached (set a lower state limit, see below). .El .Pp Adaptive timeouts are enabled by default, with an adaptive.start value equal to 60% of the state limit, and an adaptive.end value equal to 120% of the state limit. They can be disabled by setting both adaptive.start and adaptive.end to 0. .Pp The adaptive timeout values can be defined both globally and for each rule. When used on a per-rule basis, the values relate to the number of states created by the rule, otherwise to the total number of states. .Pp For example: .Bd -literal -offset indent set timeout tcp.first 120 set timeout tcp.established 86400 set timeout { adaptive.start 6000, adaptive.end 12000 } set limit states 10000 .Ed .Pp With 9000 state table entries, the timeout values are scaled to 50% (tcp.first 60, tcp.established 43200). .It Ar set loginterface Enable collection of packet and byte count statistics for the given interface or interface group. These statistics can be viewed using .Bd -literal -offset indent # pfctl -s info .Ed .Pp In this example .Xr pf 4 collects statistics on the interface named dc0: .Bd -literal -offset indent set loginterface dc0 .Ed .Pp One can disable the loginterface using: .Bd -literal -offset indent set loginterface none .Ed .It Ar set limit Sets hard limits on the memory pools used by the packet filter. See .Xr zone 9 for an explanation of memory pools. .Pp For example, .Bd -literal -offset indent set limit states 20000 .Ed .Pp sets the maximum number of entries in the memory pool used by state table entries (generated by .Ar pass rules which do not specify .Ar no state ) to 20000. Using .Bd -literal -offset indent set limit frags 20000 .Ed .Pp sets the maximum number of entries in the memory pool used for fragment reassembly (generated by .Ar scrub rules) to 20000. Using .Bd -literal -offset indent set limit src-nodes 2000 .Ed .Pp sets the maximum number of entries in the memory pool used for tracking source IP addresses (generated by the .Ar sticky-address and .Ar src.track options) to 2000. Using .Bd -literal -offset indent set limit tables 1000 set limit table-entries 100000 .Ed .Pp sets limits on the memory pools used by tables. The first limits the number of tables that can exist to 1000. The second limits the overall number of addresses that can be stored in tables to 100000. .Pp Various limits can be combined on a single line: .Bd -literal -offset indent set limit { states 20000, frags 20000, src-nodes 2000 } .Ed .It Ar set ruleset-optimization .Bl -tag -width xxxxxxxx -compact .It Ar none Disable the ruleset optimizer. .It Ar basic Enable basic ruleset optimization. This is the default behaviour. Basic ruleset optimization does four things to improve the performance of ruleset evaluations: .Pp .Bl -enum -compact .It remove duplicate rules .It remove rules that are a subset of another rule .It combine multiple rules into a table when advantageous .It re-order the rules to improve evaluation performance .El .Pp .It Ar profile Uses the currently loaded ruleset as a feedback profile to tailor the ordering of quick rules to actual network traffic. .El .Pp It is important to note that the ruleset optimizer will modify the ruleset to improve performance. A side effect of the ruleset modification is that per-rule accounting statistics will have different meanings than before. If per-rule accounting is important for billing purposes or whatnot, either the ruleset optimizer should not be used or a label field should be added to all of the accounting rules to act as optimization barriers. .Pp Optimization can also be set as a command-line argument to .Xr pfctl 8 , overriding the settings in .Nm . .It Ar set optimization Optimize state timeouts for one of the following network environments: .Pp .Bl -tag -width xxxx -compact .It Ar normal A normal network environment. Suitable for almost all networks. .It Ar high-latency A high-latency environment (such as a satellite connection). .It Ar satellite Alias for .Ar high-latency . .It Ar aggressive Aggressively expire connections. This can greatly reduce the memory usage of the firewall at the cost of dropping idle connections early. .It Ar conservative Extremely conservative settings. Avoid dropping legitimate connections at the expense of greater memory utilization (possibly much greater on a busy network) and slightly increased processor utilization. .El .Pp For example: .Bd -literal -offset indent set optimization aggressive .Ed .It Ar set block-policy The .Ar block-policy option sets the default behaviour for the packet .Ar block action: .Pp .Bl -tag -width xxxxxxxx -compact .It Ar drop Packet is silently dropped. .It Ar return A TCP RST is returned for blocked TCP packets, an ICMP UNREACHABLE is returned for blocked UDP packets, and all other packets are silently dropped. .El .Pp For example: .Bd -literal -offset indent set block-policy return .Ed .It Ar set state-policy The .Ar state-policy option sets the default behaviour for states: .Pp .Bl -tag -width group-bound -compact .It Ar if-bound States are bound to interface. .It Ar floating States can match packets on any interfaces (the default). .El .Pp For example: .Bd -literal -offset indent set state-policy if-bound .Ed .It Ar set state-defaults The .Ar state-defaults option sets the state options for states created from rules without an explicit .Ar keep state . For example: .Bd -literal -offset indent set state-defaults pflow, no-sync .Ed .It Ar set hostid The 32-bit .Ar hostid identifies this firewall's state table entries to other firewalls in a .Xr pfsync 4 failover cluster. By default the hostid is set to a pseudo-random value, however it may be desirable to manually configure it, for example to more easily identify the source of state table entries. .Bd -literal -offset indent set hostid 1 .Ed .Pp The hostid may be specified in either decimal or hexadecimal. .It Ar set require-order By default .Xr pfctl 8 enforces an ordering of the statement types in the ruleset to: .Em options , .Em normalization , .Em queueing , .Em translation , .Em filtering . Setting this option to .Ar no disables this enforcement. There may be non-trivial and non-obvious implications to an out of order ruleset. Consider carefully before disabling the order enforcement. .It Ar set fingerprints Load fingerprints of known operating systems from the given filename. By default fingerprints of known operating systems are automatically loaded from .Xr pf.os 5 in .Pa /etc but can be overridden via this option. Setting this option may leave a small period of time where the fingerprints referenced by the currently active ruleset are inconsistent until the new ruleset finishes loading. .Pp For example: .Pp .Dl set fingerprints \&"/etc/pf.os.devel\&" .It Ar set skip on Aq Ar ifspec List interfaces for which packets should not be filtered. Packets passing in or out on such interfaces are passed as if pf was disabled, i.e. pf does not process them in any way. This can be useful on loopback and other virtual interfaces, when packet filtering is not desired and can have unexpected effects. For example: .Pp .Dl set skip on lo0 .It Ar set debug Set the debug .Ar level to one of the following: .Pp .Bl -tag -width xxxxxxxxxxxx -compact .It Ar none Don't generate debug messages. .It Ar urgent Generate debug messages only for serious errors. .It Ar misc Generate debug messages for various errors. .It Ar loud Generate debug messages for common conditions. .El .El .Sh TRAFFIC NORMALIZATION Traffic normalization is used to sanitize packet content in such a way that there are no ambiguities in packet interpretation on the receiving side. The normalizer does IP fragment reassembly to prevent attacks that confuse intrusion detection systems by sending overlapping IP fragments. Packet normalization is invoked with the .Ar scrub directive. .Pp .Ar scrub has the following options: .Bl -tag -width xxxx .It Ar no-df Clears the .Ar dont-fragment bit from a matching IP packet. Some operating systems are known to generate fragmented packets with the .Ar dont-fragment bit set. This is particularly true with NFS. .Ar Scrub will drop such fragmented .Ar dont-fragment packets unless .Ar no-df is specified. .Pp Unfortunately some operating systems also generate their .Ar dont-fragment packets with a zero IP identification field. Clearing the .Ar dont-fragment bit on packets with a zero IP ID may cause deleterious results if an upstream router later fragments the packet. Using the .Ar random-id modifier (see below) is recommended in combination with the .Ar no-df modifier to ensure unique IP identifiers. .It Ar min-ttl Aq Ar number Enforces a minimum TTL for matching IP packets. .It Ar max-mss Aq Ar number Enforces a maximum MSS for matching TCP packets. .It Xo Ar set-tos Aq Ar string .No \*(Ba Aq Ar number .Xc Enforces a .Em TOS for matching IP packets. .Em TOS may be given as one of .Ar lowdelay , .Ar throughput , .Ar reliability , or as either hex or decimal. .It Ar random-id Replaces the IP identification field with random values to compensate for predictable values generated by many hosts. This option only applies to packets that are not fragmented after the optional fragment reassembly. .It Ar fragment reassemble Using .Ar scrub rules, fragments can be reassembled by normalization. In this case, fragments are buffered until they form a complete packet, and only the completed packet is passed on to the filter. The advantage is that filter rules have to deal only with complete packets, and can ignore fragments. The drawback of caching fragments is the additional memory cost. But the full reassembly method is the only method that currently works with NAT. This is the default behavior of a .Ar scrub rule if no fragmentation modifier is supplied. .It Ar fragment crop The default fragment reassembly method is expensive, hence the option to crop is provided. In this case, .Xr pf 4 will track the fragments and cache a small range descriptor. Duplicate fragments are dropped and overlaps are cropped. Thus data will only occur once on the wire with ambiguities resolving to the first occurrence. Unlike the .Ar fragment reassemble modifier, fragments are not buffered, they are passed as soon as they are received. The .Ar fragment crop reassembly mechanism does not yet work with NAT. .It Ar fragment drop-ovl This option is similar to the .Ar fragment crop modifier except that all overlapping or duplicate fragments will be dropped, and all further corresponding fragments will be dropped as well. .It Ar reassemble tcp Statefully normalizes TCP connections. .Ar scrub reassemble tcp rules may not have the direction (in/out) specified. .Ar reassemble tcp performs the following normalizations: .Pp .Bl -tag -width timeout -compact .It ttl Neither side of the connection is allowed to reduce their IP TTL. An attacker may send a packet such that it reaches the firewall, affects the firewall state, and expires before reaching the destination host. .Ar reassemble tcp will raise the TTL of all packets back up to the highest value seen on the connection. .It timestamp modulation Modern TCP stacks will send a timestamp on every TCP packet and echo the other endpoint's timestamp back to them. Many operating systems will merely start the timestamp at zero when first booted, and increment it several times a second. The uptime of the host can be deduced by reading the timestamp and multiplying by a constant. Also observing several different timestamps can be used to count hosts behind a NAT device. And spoofing TCP packets into a connection requires knowing or guessing valid timestamps. Timestamps merely need to be monotonically increasing and not derived off a guessable base time. .Ar reassemble tcp will cause .Ar scrub to modulate the TCP timestamps with a random number. .It extended PAWS checks There is a problem with TCP on long fat pipes, in that a packet might get delayed for longer than it takes the connection to wrap its 32-bit sequence space. In such an occurrence, the old packet would be indistinguishable from a new packet and would be accepted as such. The solution to this is called PAWS: Protection Against Wrapped Sequence numbers. It protects against it by making sure the timestamp on each packet does not go backwards. .Ar reassemble tcp also makes sure the timestamp on the packet does not go forward more than the RFC allows. By doing this, .Xr pf 4 artificially extends the security of TCP sequence numbers by 10 to 18 bits when the host uses appropriately randomized timestamps, since a blind attacker would have to guess the timestamp as well. .El .El .Pp For example, .Bd -literal -offset indent scrub in on $ext_if all fragment reassemble .Ed .Pp The .Ar no option prefixed to a scrub rule causes matching packets to remain unscrubbed, much in the same way as .Ar drop quick works in the packet filter (see below). This mechanism should be used when it is necessary to exclude specific packets from broader scrub rules. .Sh QUEUEING The ALTQ system is currently not available in the GENERIC kernel nor as loadable modules. In order to use the herein after called queueing options one has to use a custom built kernel. Please refer to .Xr altq 4 to learn about the related kernel options. .Pp Packets can be assigned to queues for the purpose of bandwidth control. At least two declarations are required to configure queues, and later any packet filtering rule can reference the defined queues by name. During the filtering component of .Nm pf.conf , the last referenced .Ar queue name is where any packets from .Ar pass rules will be queued, while for .Ar block rules it specifies where any resulting ICMP or TCP RST packets should be queued. The .Ar scheduler defines the algorithm used to decide which packets get delayed, dropped, or sent out immediately. There are three .Ar schedulers currently supported. .Bl -tag -width xxxx .It Ar cbq Class Based Queueing. .Ar Queues attached to an interface build a tree, thus each .Ar queue can have further child .Ar queues . Each queue can have a .Ar priority and a .Ar bandwidth assigned. .Ar Priority mainly controls the time packets take to get sent out, while .Ar bandwidth has primarily effects on throughput. .Ar cbq achieves both partitioning and sharing of link bandwidth by hierarchically structured classes. Each class has its own .Ar queue and is assigned its share of .Ar bandwidth . A child class can borrow bandwidth from its parent class as long as excess bandwidth is available (see the option .Ar borrow , below). .It Ar priq Priority Queueing. .Ar Queues are flat attached to the interface, thus, .Ar queues cannot have further child .Ar queues . Each .Ar queue has a unique .Ar priority assigned, ranging from 0 to 15. Packets in the .Ar queue with the highest .Ar priority are processed first. .It Ar hfsc Hierarchical Fair Service Curve. .Ar Queues attached to an interface build a tree, thus each .Ar queue can have further child .Ar queues . Each queue can have a .Ar priority and a .Ar bandwidth assigned. .Ar Priority mainly controls the time packets take to get sent out, while .Ar bandwidth primarily affects throughput. .Ar hfsc supports both link-sharing and guaranteed real-time services. It employs a service curve based QoS model, and its unique feature is an ability to decouple .Ar delay and .Ar bandwidth allocation. .El .Pp The interfaces on which queueing should be activated are declared using the .Ar altq on declaration. .Ar altq on has the following keywords: .Bl -tag -width xxxx .It Aq Ar interface Queueing is enabled on the named interface. .It Aq Ar scheduler Specifies which queueing scheduler to use. Currently supported values are .Ar cbq for Class Based Queueing, .Ar priq for Priority Queueing and .Ar hfsc for the Hierarchical Fair Service Curve scheduler. .It Ar bandwidth Aq Ar bw The maximum bitrate for all queues on an interface may be specified using the .Ar bandwidth keyword. The value can be specified as an absolute value or as a percentage of the interface bandwidth. When using an absolute value, the suffixes .Ar b , .Ar Kb , .Ar Mb , and .Ar Gb are used to represent bits, kilobits, megabits, and gigabits per second, respectively. The value must not exceed the interface bandwidth. If .Ar bandwidth is not specified, the interface bandwidth is used (but take note that some interfaces do not know their bandwidth, or can adapt their bandwidth rates). .It Ar qlimit Aq Ar limit The maximum number of packets held in the queue. The default is 50. .It Ar tbrsize Aq Ar size Adjusts the size, in bytes, of the token bucket regulator. If not specified, heuristics based on the interface bandwidth are used to determine the size. .It Ar queue Aq Ar list Defines a list of subqueues to create on an interface. .El .Pp In the following example, the interface dc0 should queue up to 5Mbps in four second-level queues using Class Based Queueing. Those four queues will be shown in a later example. .Bd -literal -offset indent altq on dc0 cbq bandwidth 5Mb queue { std, http, mail, ssh } .Ed .Pp Once interfaces are activated for queueing using the .Ar altq directive, a sequence of .Ar queue directives may be defined. The name associated with a .Ar queue must match a queue defined in the .Ar altq directive (e.g. mail), or, except for the .Ar priq .Ar scheduler , in a parent .Ar queue declaration. The following keywords can be used: .Bl -tag -width xxxx .It Ar on Aq Ar interface Specifies the interface the queue operates on. If not given, it operates on all matching interfaces. .It Ar bandwidth Aq Ar bw Specifies the maximum bitrate to be processed by the queue. This value must not exceed the value of the parent .Ar queue and can be specified as an absolute value or a percentage of the parent queue's bandwidth. If not specified, defaults to 100% of the parent queue's bandwidth. The .Ar priq scheduler does not support bandwidth specification. .It Ar priority Aq Ar level Between queues a priority level can be set. For .Ar cbq and .Ar hfsc , the range is 0 to 7 and for .Ar priq , the range is 0 to 15. The default for all is 1. .Ar Priq queues with a higher priority are always served first. .Ar Cbq and .Ar Hfsc queues with a higher priority are preferred in the case of overload. .It Ar qlimit Aq Ar limit The maximum number of packets held in the queue. The default is 50. .El .Pp The .Ar scheduler can get additional parameters with .Xo Aq Ar scheduler .Pf ( Aq Ar parameters ) . .Xc Parameters are as follows: .Bl -tag -width Fl .It Ar default Packets not matched by another queue are assigned to this one. Exactly one default queue is required. .It Ar red Enable RED (Random Early Detection) on this queue. RED drops packets with a probability proportional to the average queue length. .It Ar rio Enables RIO on this queue. RIO is RED with IN/OUT, thus running RED two times more than RIO would achieve the same effect. RIO is currently not supported in the GENERIC kernel. .It Ar ecn Enables ECN (Explicit Congestion Notification) on this queue. ECN implies RED. .El .Pp The .Ar cbq .Ar scheduler supports an additional option: .Bl -tag -width Fl .It Ar borrow The queue can borrow bandwidth from the parent. .El .Pp The .Ar hfsc .Ar scheduler supports some additional options: .Bl -tag -width Fl .It Ar realtime Aq Ar sc The minimum required bandwidth for the queue. .It Ar upperlimit Aq Ar sc The maximum allowed bandwidth for the queue. .It Ar linkshare Aq Ar sc The bandwidth share of a backlogged queue. .El .Pp .Aq Ar sc is an acronym for .Ar service curve . .Pp The format for service curve specifications is .Ar ( m1 , d , m2 ) . .Ar m2 controls the bandwidth assigned to the queue. .Ar m1 and .Ar d are optional and can be used to control the initial bandwidth assignment. For the first .Ar d milliseconds the queue gets the bandwidth given as .Ar m1 , afterwards the value given in .Ar m2 . .Pp Furthermore, with .Ar cbq and .Ar hfsc , child queues can be specified as in an .Ar altq declaration, thus building a tree of queues using a part of their parent's bandwidth. .Pp Packets can be assigned to queues based on filter rules by using the .Ar queue keyword. Normally only one .Ar queue is specified; when a second one is specified it will instead be used for packets which have a .Em TOS of .Em lowdelay and for TCP ACKs with no data payload. .Pp To continue the previous example, the examples below would specify the four referenced queues, plus a few child queues. Interactive .Xr ssh 1 sessions get priority over bulk transfers like .Xr scp 1 and .Xr sftp 1 . The queues may then be referenced by filtering rules (see .Sx PACKET FILTERING below). .Bd -literal queue std bandwidth 10% cbq(default) queue http bandwidth 60% priority 2 cbq(borrow red) \e { employees, developers } queue developers bandwidth 75% cbq(borrow) queue employees bandwidth 15% queue mail bandwidth 10% priority 0 cbq(borrow ecn) queue ssh bandwidth 20% cbq(borrow) { ssh_interactive, ssh_bulk } queue ssh_interactive bandwidth 50% priority 7 cbq(borrow) queue ssh_bulk bandwidth 50% priority 0 cbq(borrow) block return out on dc0 inet all queue std pass out on dc0 inet proto tcp from $developerhosts to any port 80 \e queue developers pass out on dc0 inet proto tcp from $employeehosts to any port 80 \e queue employees pass out on dc0 inet proto tcp from any to any port 22 \e queue(ssh_bulk, ssh_interactive) pass out on dc0 inet proto tcp from any to any port 25 \e queue mail .Ed .Sh TRANSLATION Translation rules modify either the source or destination address of the packets associated with a stateful connection. A stateful connection is automatically created to track packets matching such a rule as long as they are not blocked by the filtering section of .Nm pf.conf . The translation engine modifies the specified address and/or port in the packet, recalculates IP, TCP and UDP checksums as necessary, and passes it to the packet filter for evaluation. .Pp Since translation occurs before filtering the filter engine will see packets as they look after any addresses and ports have been translated. Filter rules will therefore have to filter based on the translated address and port number. Packets that match a translation rule are only automatically passed if the .Ar pass modifier is given, otherwise they are still subject to .Ar block and .Ar pass rules. .Pp The state entry created permits .Xr pf 4 to keep track of the original address for traffic associated with that state and correctly direct return traffic for that connection. .Pp Various types of translation are possible with pf: .Bl -tag -width xxxx .It Ar binat A .Ar binat rule specifies a bidirectional mapping between an external IP netblock and an internal IP netblock. .It Ar nat A .Ar nat rule specifies that IP addresses are to be changed as the packet traverses the given interface. This technique allows one or more IP addresses on the translating host to support network traffic for a larger range of machines on an "inside" network. Although in theory any IP address can be used on the inside, it is strongly recommended that one of the address ranges defined by RFC 1918 be used. These netblocks are: .Bd -literal 10.0.0.0 - 10.255.255.255 (all of net 10, i.e., 10/8) 172.16.0.0 - 172.31.255.255 (i.e., 172.16/12) 192.168.0.0 - 192.168.255.255 (i.e., 192.168/16) .Ed .It Pa rdr The packet is redirected to another destination and possibly a different port. .Ar rdr rules can optionally specify port ranges instead of single ports. rdr ... port 2000:2999 -\*(Gt ... port 4000 redirects ports 2000 to 2999 (inclusive) to port 4000. rdr ... port 2000:2999 -\*(Gt ... port 4000:* redirects port 2000 to 4000, 2001 to 4001, ..., 2999 to 4999. .El .Pp In addition to modifying the address, some translation rules may modify source or destination ports for .Xr tcp 4 or .Xr udp 4 connections; implicitly in the case of .Ar nat rules and explicitly in the case of .Ar rdr rules. Port numbers are never translated with a .Ar binat rule. .Pp Evaluation order of the translation rules is dependent on the type of the translation rules and of the direction of a packet. .Ar binat rules are always evaluated first. Then either the .Ar rdr rules are evaluated on an inbound packet or the .Ar nat rules on an outbound packet. Rules of the same type are evaluated in the same order in which they appear in the ruleset. The first matching rule decides what action is taken. .Pp The .Ar no option prefixed to a translation rule causes packets to remain untranslated, much in the same way as .Ar drop quick works in the packet filter (see below). If no rule matches the packet it is passed to the filter engine unmodified. .Pp Translation rules apply only to packets that pass through the specified interface, and if no interface is specified, translation is applied to packets on all interfaces. For instance, redirecting port 80 on an external interface to an internal web server will only work for connections originating from the outside. Connections to the address of the external interface from local hosts will not be redirected, since such packets do not actually pass through the external interface. Redirections cannot reflect packets back through the interface they arrive on, they can only be redirected to hosts connected to different interfaces or to the firewall itself. .Pp Note that redirecting external incoming connections to the loopback address, as in .Bd -literal -offset indent rdr on ne3 inet proto tcp to port smtp -\*(Gt 127.0.0.1 port spamd .Ed .Pp will effectively allow an external host to connect to daemons bound solely to the loopback address, circumventing the traditional blocking of such connections on a real interface. Unless this effect is desired, any of the local non-loopback addresses should be used as redirection target instead, which allows external connections only to daemons bound to this address or not bound to any address. .Pp See .Sx TRANSLATION EXAMPLES below. .Sh PACKET FILTERING .Xr pf 4 has the ability to .Ar block and .Ar pass packets based on attributes of their layer 3 (see .Xr ip 4 and .Xr ip6 4 ) and layer 4 (see .Xr icmp 4 , .Xr icmp6 4 , .Xr tcp 4 , .Xr udp 4 ) headers. In addition, packets may also be assigned to queues for the purpose of bandwidth control. .Pp For each packet processed by the packet filter, the filter rules are evaluated in sequential order, from first to last. The last matching rule decides what action is taken. If no rule matches the packet, the default action is to pass the packet. .Pp The following actions can be used in the filter: .Bl -tag -width xxxx .It Ar block The packet is blocked. There are a number of ways in which a .Ar block rule can behave when blocking a packet. The default behaviour is to .Ar drop packets silently, however this can be overridden or made explicit either globally, by setting the .Ar block-policy option, or on a per-rule basis with one of the following options: .Pp .Bl -tag -width xxxx -compact .It Ar drop The packet is silently dropped. .It Ar return-rst This applies only to .Xr tcp 4 packets, and issues a TCP RST which closes the connection. .It Ar return-icmp .It Ar return-icmp6 This causes ICMP messages to be returned for packets which match the rule. By default this is an ICMP UNREACHABLE message, however this can be overridden by specifying a message as a code or number. .It Ar return This causes a TCP RST to be returned for .Xr tcp 4 packets and an ICMP UNREACHABLE for UDP and other packets. .El .Pp Options returning ICMP packets currently have no effect if .Xr pf 4 operates on a .Xr if_bridge 4 , as the code to support this feature has not yet been implemented. .Pp The simplest mechanism to block everything by default and only pass packets that match explicit rules is specify a first filter rule of: .Bd -literal -offset indent block all .Ed .It Ar pass The packet is passed; state is created unless the .Ar no state option is specified. .El .Pp By default .Xr pf 4 filters packets statefully; the first time a packet matches a .Ar pass rule, a state entry is created; for subsequent packets the filter checks whether the packet matches any state. If it does, the packet is passed without evaluation of any rules. After the connection is closed or times out, the state entry is automatically removed. .Pp This has several advantages. For TCP connections, comparing a packet to a state involves checking its sequence numbers, as well as TCP timestamps if a .Ar scrub reassemble tcp rule applies to the connection. If these values are outside the narrow windows of expected values, the packet is dropped. This prevents spoofing attacks, such as when an attacker sends packets with a fake source address/port but does not know the connection's sequence numbers. Similarly, .Xr pf 4 knows how to match ICMP replies to states. For example, .Bd -literal -offset indent pass out inet proto icmp all icmp-type echoreq .Ed .Pp allows echo requests (such as those created by .Xr ping 8 ) out statefully, and matches incoming echo replies correctly to states. .Pp Also, looking up states is usually faster than evaluating rules. If there are 50 rules, all of them are evaluated sequentially in O(n). Even with 50000 states, only 16 comparisons are needed to match a state, since states are stored in a binary search tree that allows searches in O(log2 n). .Pp Furthermore, correct handling of ICMP error messages is critical to many protocols, particularly TCP. .Xr pf 4 matches ICMP error messages to the correct connection, checks them against connection parameters, and passes them if appropriate. For example if an ICMP source quench message referring to a stateful TCP connection arrives, it will be matched to the state and get passed. .Pp Finally, state tracking is required for .Ar nat , binat No and Ar rdr rules, in order to track address and port translations and reverse the translation on returning packets. .Pp .Xr pf 4 will also create state for other protocols which are effectively stateless by nature. UDP packets are matched to states using only host addresses and ports, and other protocols are matched to states using only the host addresses. .Pp If stateless filtering of individual packets is desired, the .Ar no state keyword can be used to specify that state will not be created if this is the last matching rule. A number of parameters can also be set to affect how .Xr pf 4 handles state tracking. See .Sx STATEFUL TRACKING OPTIONS below for further details. .Sh PARAMETERS The rule parameters specify the packets to which a rule applies. A packet always comes in on, or goes out through, one interface. Most parameters are optional. If a parameter is specified, the rule only applies to packets with matching attributes. Certain parameters can be expressed as lists, in which case .Xr pfctl 8 generates all needed rule combinations. .Bl -tag -width xxxx .It Ar in No or Ar out This rule applies to incoming or outgoing packets. If neither .Ar in nor .Ar out are specified, the rule will match packets in both directions. .It Ar log In addition to the action specified, a log message is generated. Only the packet that establishes the state is logged, unless the .Ar no state option is specified. The logged packets are sent to a .Xr pflog 4 interface, by default .Ar pflog0 . This interface is monitored by the .Xr pflogd 8 logging daemon, which dumps the logged packets to the file .Pa /var/log/pflog in .Xr pcap 3 binary format. .It Ar log (all) Used to force logging of all packets for a connection. This is not necessary when .Ar no state is explicitly specified. As with .Ar log , packets are logged to .Xr pflog 4 . .It Ar log (user) Logs the .Ux user ID of the user that owns the socket and the PID of the process that has the socket open where the packet is sourced from or destined to (depending on which socket is local). This is in addition to the normal information logged. .Pp Only the first packet logged via .Ar log (all, user) will have the user credentials logged when using stateful matching. .It Ar log (to Aq Ar interface ) Send logs to the specified .Xr pflog 4 interface instead of .Ar pflog0 . .It Ar quick If a packet matches a rule which has the .Ar quick option set, this rule is considered the last matching rule, and evaluation of subsequent rules is skipped. .It Ar on Aq Ar interface This rule applies only to packets coming in on, or going out through, this particular interface or interface group. For more information on interface groups, see the .Ic group keyword in .Xr ifconfig 8 . .It Aq Ar af This rule applies only to packets of this address family. Supported values are .Ar inet and .Ar inet6 . .It Ar proto Aq Ar protocol This rule applies only to packets of this protocol. Common protocols are .Xr icmp 4 , .Xr icmp6 4 , .Xr tcp 4 , and .Xr udp 4 . For a list of all the protocol name to number mappings used by .Xr pfctl 8 , see the file .Pa /etc/protocols . .It Xo .Ar from Aq Ar source .Ar port Aq Ar source .Ar os Aq Ar source .Ar to Aq Ar dest .Ar port Aq Ar dest .Xc This rule applies only to packets with the specified source and destination addresses and ports. .Pp Addresses can be specified in CIDR notation (matching netblocks), as symbolic host names, interface names or interface group names, or as any of the following keywords: .Pp .Bl -tag -width xxxxxxxxxxxxxx -compact .It Ar any Any address. .It Ar no-route Any address which is not currently routable. .It Ar urpf-failed Any source address that fails a unicast reverse path forwarding (URPF) check, i.e. packets coming in on an interface other than that which holds the route back to the packet's source address. .It Aq Ar table Any address that matches the given table. .El .Pp Ranges of addresses are specified by using the .Sq - operator. For instance: .Dq 10.1.1.10 - 10.1.1.12 means all addresses from 10.1.1.10 to 10.1.1.12, hence addresses 10.1.1.10, 10.1.1.11, and 10.1.1.12. .Pp Interface names and interface group names can have modifiers appended: .Pp .Bl -tag -width xxxxxxxxxxxx -compact .It Ar :network Translates to the network(s) attached to the interface. .It Ar :broadcast Translates to the interface's broadcast address(es). .It Ar :peer Translates to the point-to-point interface's peer address(es). .It Ar :0 Do not include interface aliases. .El .Pp Host names may also have the .Ar :0 option appended to restrict the name resolution to the first of each v4 and v6 address found. .Pp Host name resolution and interface to address translation are done at ruleset load-time. When the address of an interface (or host name) changes (under DHCP or PPP, for instance), the ruleset must be reloaded for the change to be reflected in the kernel. Surrounding the interface name (and optional modifiers) in parentheses changes this behaviour. When the interface name is surrounded by parentheses, the rule is automatically updated whenever the interface changes its address. The ruleset does not need to be reloaded. This is especially useful with .Ar nat . .Pp Ports can be specified either by number or by name. For example, port 80 can be specified as .Em www . For a list of all port name to number mappings used by .Xr pfctl 8 , see the file .Pa /etc/services . .Pp Ports and ranges of ports are specified by using these operators: .Bd -literal -offset indent = (equal) != (unequal) \*(Lt (less than) \*(Le (less than or equal) \*(Gt (greater than) \*(Ge (greater than or equal) : (range including boundaries) \*(Gt\*(Lt (range excluding boundaries) \*(Lt\*(Gt (except range) .Ed .Pp .Sq \*(Gt\*(Lt , .Sq \*(Lt\*(Gt and .Sq \&: are binary operators (they take two arguments). For instance: .Bl -tag -width Fl .It Ar port 2000:2004 means .Sq all ports \*(Ge 2000 and \*(Le 2004 , hence ports 2000, 2001, 2002, 2003 and 2004. .It Ar port 2000 \*(Gt\*(Lt 2004 means .Sq all ports \*(Gt 2000 and \*(Lt 2004 , hence ports 2001, 2002 and 2003. .It Ar port 2000 \*(Lt\*(Gt 2004 means .Sq all ports \*(Lt 2000 or \*(Gt 2004 , hence ports 1-1999 and 2005-65535. .El .Pp The operating system of the source host can be specified in the case of TCP rules with the .Ar OS modifier. See the .Sx OPERATING SYSTEM FINGERPRINTING section for more information. .Pp The host, port and OS specifications are optional, as in the following examples: .Bd -literal -offset indent pass in all pass in from any to any pass in proto tcp from any port \*(Le 1024 to any pass in proto tcp from any to any port 25 pass in proto tcp from 10.0.0.0/8 port \*(Gt 1024 \e to ! 10.1.2.3 port != ssh pass in proto tcp from any os "OpenBSD" .Ed .It Ar all This is equivalent to "from any to any". .It Ar group Aq Ar group Similar to .Ar user , this rule only applies to packets of sockets owned by the specified group. .It Ar user Aq Ar user This rule only applies to packets of sockets owned by the specified user. For outgoing connections initiated from the firewall, this is the user that opened the connection. For incoming connections to the firewall itself, this is the user that listens on the destination port. For forwarded connections, where the firewall is not a connection endpoint, the user and group are .Em unknown . .Pp All packets, both outgoing and incoming, of one connection are associated with the same user and group. Only TCP and UDP packets can be associated with users; for other protocols these parameters are ignored. .Pp User and group refer to the effective (as opposed to the real) IDs, in case the socket is created by a setuid/setgid process. User and group IDs are stored when a socket is created; when a process creates a listening socket as root (for instance, by binding to a privileged port) and subsequently changes to another user ID (to drop privileges), the credentials will remain root. .Pp User and group IDs can be specified as either numbers or names. The syntax is similar to the one for ports. The value .Em unknown matches packets of forwarded connections. .Em unknown can only be used with the operators .Cm = and .Cm != . Other constructs like .Cm user \*(Ge unknown are invalid. Forwarded packets with unknown user and group ID match only rules that explicitly compare against .Em unknown with the operators .Cm = or .Cm != . For instance .Cm user \*(Ge 0 does not match forwarded packets. The following example allows only selected users to open outgoing connections: .Bd -literal -offset indent block out proto { tcp, udp } all pass out proto { tcp, udp } all user { \*(Lt 1000, dhartmei } .Ed .It Xo Ar flags Aq Ar a .Pf / Ns Aq Ar b .No \*(Ba / Ns Aq Ar b .No \*(Ba any .Xc This rule only applies to TCP packets that have the flags .Aq Ar a set out of set .Aq Ar b . Flags not specified in .Aq Ar b are ignored. For stateful connections, the default is .Ar flags S/SA . To indicate that flags should not be checked at all, specify .Ar flags any . The flags are: (F)IN, (S)YN, (R)ST, (P)USH, (A)CK, (U)RG, (E)CE, and C(W)R. .Bl -tag -width Fl .It Ar flags S/S Flag SYN is set. The other flags are ignored. .It Ar flags S/SA This is the default setting for stateful connections. Out of SYN and ACK, exactly SYN may be set. SYN, SYN+PSH and SYN+RST match, but SYN+ACK, ACK and ACK+RST do not. This is more restrictive than the previous example. .It Ar flags /SFRA If the first set is not specified, it defaults to none. All of SYN, FIN, RST and ACK must be unset. .El .Pp Because .Ar flags S/SA is applied by default (unless .Ar no state is specified), only the initial SYN packet of a TCP handshake will create a state for a TCP connection. It is possible to be less restrictive, and allow state creation from intermediate .Pq non-SYN packets, by specifying .Ar flags any . This will cause .Xr pf 4 to synchronize to existing connections, for instance if one flushes the state table. However, states created from such intermediate packets may be missing connection details such as the TCP window scaling factor. States which modify the packet flow, such as those affected by .Ar nat , binat No or Ar rdr rules, .Ar modulate No or Ar synproxy state options, or scrubbed with .Ar reassemble tcp will also not be recoverable from intermediate packets. Such connections will stall and time out. .It Xo Ar icmp-type Aq Ar type .Ar code Aq Ar code .Xc .It Xo Ar icmp6-type Aq Ar type .Ar code Aq Ar code .Xc This rule only applies to ICMP or ICMPv6 packets with the specified type and code. Text names for ICMP types and codes are listed in .Xr icmp 4 and .Xr icmp6 4 . This parameter is only valid for rules that cover protocols ICMP or ICMP6. The protocol and the ICMP type indicator .Po .Ar icmp-type or .Ar icmp6-type .Pc must match. .It Xo Ar tos Aq Ar string .No \*(Ba Aq Ar number .Xc This rule applies to packets with the specified .Em TOS bits set. .Em TOS may be given as one of .Ar lowdelay , .Ar throughput , .Ar reliability , or as either hex or decimal. .Pp For example, the following rules are identical: .Bd -literal -offset indent pass all tos lowdelay pass all tos 0x10 pass all tos 16 .Ed .It Ar allow-opts By default, IPv4 packets with IP options or IPv6 packets with routing extension headers are blocked. When .Ar allow-opts is specified for a .Ar pass rule, packets that pass the filter based on that rule (last matching) do so even if they contain IP options or routing extension headers. For packets that match state, the rule that initially created the state is used. The implicit .Ar pass rule that is used when a packet does not match any rules does not allow IP options. .It Ar label Aq Ar string Adds a label (name) to the rule, which can be used to identify the rule. For instance, pfctl -s labels shows per-rule statistics for rules that have labels. .Pp The following macros can be used in labels: .Pp .Bl -tag -width $srcaddr -compact -offset indent .It Ar $if The interface. .It Ar $srcaddr The source IP address. .It Ar $dstaddr The destination IP address. .It Ar $srcport The source port specification. .It Ar $dstport The destination port specification. .It Ar $proto The protocol name. .It Ar $nr The rule number. .El .Pp For example: .Bd -literal -offset indent ips = \&"{ 1.2.3.4, 1.2.3.5 }\&" pass in proto tcp from any to $ips \e port \*(Gt 1023 label \&"$dstaddr:$dstport\&" .Ed .Pp expands to .Bd -literal -offset indent pass in inet proto tcp from any to 1.2.3.4 \e port \*(Gt 1023 label \&"1.2.3.4:\*(Gt1023\&" pass in inet proto tcp from any to 1.2.3.5 \e port \*(Gt 1023 label \&"1.2.3.5:\*(Gt1023\&" .Ed .Pp The macro expansion for the .Ar label directive occurs only at configuration file parse time, not during runtime. .It Xo Ar queue Aq Ar queue .No \*(Ba ( Aq Ar queue , .Aq Ar queue ) .Xc Packets matching this rule will be assigned to the specified queue. If two queues are given, packets which have a .Em TOS of .Em lowdelay and TCP ACKs with no data payload will be assigned to the second one. See .Sx QUEUEING for setup details. .Pp For example: .Bd -literal -offset indent pass in proto tcp to port 25 queue mail pass in proto tcp to port 22 queue(ssh_bulk, ssh_prio) .Ed .It Ar tag Aq Ar string Packets matching this rule will be tagged with the specified string. The tag acts as an internal marker that can be used to identify these packets later on. This can be used, for example, to provide trust between interfaces and to determine if packets have been processed by translation rules. Tags are .Qq sticky , meaning that the packet will be tagged even if the rule is not the last matching rule. Further matching rules can replace the tag with a new one but will not remove a previously applied tag. A packet is only ever assigned one tag at a time. Packet tagging can be done during .Ar nat , .Ar rdr , or .Ar binat rules in addition to filter rules. Tags take the same macros as labels (see above). .It Ar tagged Aq Ar string Used with filter, translation or scrub rules to specify that packets must already be tagged with the given tag in order to match the rule. Inverse tag matching can also be done by specifying the .Cm !\& operator before the .Ar tagged keyword. .It Ar rtable Aq Ar number Used to select an alternate routing table for the routing lookup. Only effective before the route lookup happened, i.e. when filtering inbound. .It Xo Ar divert-to Aq Ar host .Ar port Aq Ar port .Xc Used to redirect packets to a local socket bound to .Ar host and .Ar port . The packets will not be modified, so .Xr getsockname 2 on the socket will return the original destination address of the packet. .It Ar divert-reply Used to receive replies for sockets that are bound to addresses which are not local to the machine. See .Xr setsockopt 2 for information on how to bind these sockets. .It Ar probability Aq Ar number A probability attribute can be attached to a rule, with a value set between 0 and 1, bounds not included. In that case, the rule will be honoured using the given probability value only. For example, the following rule will drop 20% of incoming ICMP packets: .Bd -literal -offset indent block in proto icmp probability 20% .Ed .El .Sh ROUTING If a packet matches a rule with a route option set, the packet filter will route the packet according to the type of route option. When such a rule creates state, the route option is also applied to all packets matching the same connection. .Bl -tag -width xxxx .It Ar fastroute The .Ar fastroute option does a normal route lookup to find the next hop for the packet. .It Ar route-to The .Ar route-to option routes the packet to the specified interface with an optional address for the next hop. When a .Ar route-to rule creates state, only packets that pass in the same direction as the filter rule specifies will be routed in this way. Packets passing in the opposite direction (replies) are not affected and are routed normally. .It Ar reply-to The .Ar reply-to option is similar to .Ar route-to , but routes packets that pass in the opposite direction (replies) to the specified interface. Opposite direction is only defined in the context of a state entry, and .Ar reply-to is useful only in rules that create state. It can be used on systems with multiple external connections to route all outgoing packets of a connection through the interface the incoming connection arrived through (symmetric routing enforcement). .It Ar dup-to The .Ar dup-to option creates a duplicate of the packet and routes it like .Ar route-to . The original packet gets routed as it normally would. .El .Sh POOL OPTIONS For .Ar nat and .Ar rdr rules, (as well as for the .Ar route-to , .Ar reply-to and .Ar dup-to rule options) for which there is a single redirection address which has a subnet mask smaller than 32 for IPv4 or 128 for IPv6 (more than one IP address), a variety of different methods for assigning this address can be used: .Bl -tag -width xxxx .It Ar bitmask The .Ar bitmask option applies the network portion of the redirection address to the address to be modified (source with .Ar nat , destination with .Ar rdr ) . .It Ar random The .Ar random option selects an address at random within the defined block of addresses. .It Ar source-hash The .Ar source-hash option uses a hash of the source address to determine the redirection address, ensuring that the redirection address is always the same for a given source. An optional key can be specified after this keyword either in hex or as a string; by default .Xr pfctl 8 randomly generates a key for source-hash every time the ruleset is reloaded. .It Ar round-robin The .Ar round-robin option loops through the redirection address(es). .Pp When more than one redirection address is specified, .Ar round-robin is the only permitted pool type. .It Ar static-port With .Ar nat rules, the .Ar static-port option prevents .Xr pf 4 from modifying the source port on TCP and UDP packets. .El .Pp Additionally, the .Ar sticky-address option can be specified to help ensure that multiple connections from the same source are mapped to the same redirection address. This option can be used with the .Ar random and .Ar round-robin pool options. Note that by default these associations are destroyed as soon as there are no longer states which refer to them; in order to make the mappings last beyond the lifetime of the states, increase the global options with .Ar set timeout src.track . See .Sx STATEFUL TRACKING OPTIONS for more ways to control the source tracking. .Sh STATE MODULATION Much of the security derived from TCP is attributable to how well the initial sequence numbers (ISNs) are chosen. Some popular stack implementations choose .Em very poor ISNs and thus are normally susceptible to ISN prediction exploits. By applying a .Ar modulate state rule to a TCP connection, .Xr pf 4 will create a high quality random sequence number for each connection endpoint. .Pp The .Ar modulate state directive implicitly keeps state on the rule and is only applicable to TCP connections. .Pp For instance: .Bd -literal -offset indent block all pass out proto tcp from any to any modulate state pass in proto tcp from any to any port 25 flags S/SFRA modulate state .Ed .Pp Note that modulated connections will not recover when the state table is lost (firewall reboot, flushing the state table, etc...). .Xr pf 4 will not be able to infer a connection again after the state table flushes the connection's modulator. When the state is lost, the connection may be left dangling until the respective endpoints time out the connection. It is possible on a fast local network for the endpoints to start an ACK storm while trying to resynchronize after the loss of the modulator. The default .Ar flags settings (or a more strict equivalent) should be used on .Ar modulate state rules to prevent ACK storms. .Pp Note that alternative methods are available to prevent loss of the state table and allow for firewall failover. See .Xr carp 4 and .Xr pfsync 4 for further information. .Sh SYN PROXY By default, .Xr pf 4 passes packets that are part of a .Xr tcp 4 handshake between the endpoints. The .Ar synproxy state option can be used to cause .Xr pf 4 itself to complete the handshake with the active endpoint, perform a handshake with the passive endpoint, and then forward packets between the endpoints. .Pp No packets are sent to the passive endpoint before the active endpoint has completed the handshake, hence so-called SYN floods with spoofed source addresses will not reach the passive endpoint, as the sender can't complete the handshake. .Pp The proxy is transparent to both endpoints, they each see a single connection from/to the other endpoint. .Xr pf 4 chooses random initial sequence numbers for both handshakes. Once the handshakes are completed, the sequence number modulators (see previous section) are used to translate further packets of the connection. .Ar synproxy state includes .Ar modulate state . .Pp Rules with .Ar synproxy will not work if .Xr pf 4 operates on a .Xr bridge 4 . .Pp Example: .Bd -literal -offset indent pass in proto tcp from any to any port www synproxy state .Ed .Sh STATEFUL TRACKING OPTIONS A number of options related to stateful tracking can be applied on a per-rule basis. .Ar keep state , .Ar modulate state and .Ar synproxy state support these options, and .Ar keep state must be specified explicitly to apply options to a rule. .Pp .Bl -tag -width xxxx -compact .It Ar max Aq Ar number Limits the number of concurrent states the rule may create. When this limit is reached, further packets that would create state will not match this rule until existing states time out. .It Ar no-sync Prevent state changes for states created by this rule from appearing on the .Xr pfsync 4 interface. .It Xo Aq Ar timeout .Aq Ar seconds .Xc Changes the timeout values used for states created by this rule. For a list of all valid timeout names, see .Sx OPTIONS above. .It Ar sloppy Uses a sloppy TCP connection tracker that does not check sequence numbers at all, which makes insertion and ICMP teardown attacks way easier. This is intended to be used in situations where one does not see all packets of a connection, e.g. in asymmetric routing situations. Cannot be used with modulate or synproxy state. .It Ar pflow States created by this rule are exported on the .Xr pflow 4 interface. .El .Pp Multiple options can be specified, separated by commas: .Bd -literal -offset indent pass in proto tcp from any to any \e port www keep state \e (max 100, source-track rule, max-src-nodes 75, \e max-src-states 3, tcp.established 60, tcp.closing 5) .Ed .Pp When the .Ar source-track keyword is specified, the number of states per source IP is tracked. .Pp .Bl -tag -width xxxx -compact .It Ar source-track rule The maximum number of states created by this rule is limited by the rule's .Ar max-src-nodes and .Ar max-src-states options. Only state entries created by this particular rule count toward the rule's limits. .It Ar source-track global The number of states created by all rules that use this option is limited. Each rule can specify different .Ar max-src-nodes and .Ar max-src-states options, however state entries created by any participating rule count towards each individual rule's limits. .El .Pp The following limits can be set: .Pp .Bl -tag -width xxxx -compact .It Ar max-src-nodes Aq Ar number Limits the maximum number of source addresses which can simultaneously have state table entries. .It Ar max-src-states Aq Ar number Limits the maximum number of simultaneous state entries that a single source address can create with this rule. .El .Pp For stateful TCP connections, limits on established connections (connections which have completed the TCP 3-way handshake) can also be enforced per source IP. .Pp .Bl -tag -width xxxx -compact .It Ar max-src-conn Aq Ar number Limits the maximum number of simultaneous TCP connections which have completed the 3-way handshake that a single host can make. .It Xo Ar max-src-conn-rate Aq Ar number .No / Aq Ar seconds .Xc Limit the rate of new connections over a time interval. The connection rate is an approximation calculated as a moving average. .El .Pp Because the 3-way handshake ensures that the source address is not being spoofed, more aggressive action can be taken based on these limits. With the .Ar overload Aq Ar table state option, source IP addresses which hit either of the limits on established connections will be added to the named table. This table can be used in the ruleset to block further activity from the offending host, redirect it to a tarpit process, or restrict its bandwidth. .Pp The optional .Ar flush keyword kills all states created by the matching rule which originate from the host which exceeds these limits. The .Ar global modifier to the flush command kills all states originating from the offending host, regardless of which rule created the state. .Pp For example, the following rules will protect the webserver against hosts making more than 100 connections in 10 seconds. Any host which connects faster than this rate will have its address added to the .Aq bad_hosts table and have all states originating from it flushed. Any new packets arriving from this host will be dropped unconditionally by the block rule. .Bd -literal -offset indent block quick from \*(Ltbad_hosts\*(Gt pass in on $ext_if proto tcp to $webserver port www keep state \e (max-src-conn-rate 100/10, overload \*(Ltbad_hosts\*(Gt flush global) .Ed .Sh OPERATING SYSTEM FINGERPRINTING Passive OS Fingerprinting is a mechanism to inspect nuances of a TCP connection's initial SYN packet and guess at the host's operating system. Unfortunately these nuances are easily spoofed by an attacker so the fingerprint is not useful in making security decisions. But the fingerprint is typically accurate enough to make policy decisions upon. .Pp The fingerprints may be specified by operating system class, by version, or by subtype/patchlevel. The class of an operating system is typically the vendor or genre and would be .Ox for the .Xr pf 4 firewall itself. The version of the oldest available .Ox release on the main FTP site would be 2.6 and the fingerprint would be written .Pp .Dl \&"OpenBSD 2.6\&" .Pp The subtype of an operating system is typically used to describe the patchlevel if that patch led to changes in the TCP stack behavior. In the case of .Ox , the only subtype is for a fingerprint that was normalized by the .Ar no-df scrub option and would be specified as .Pp .Dl \&"OpenBSD 3.3 no-df\&" .Pp Fingerprints for most popular operating systems are provided by .Xr pf.os 5 . Once .Xr pf 4 is running, a complete list of known operating system fingerprints may be listed by running: .Pp .Dl # pfctl -so .Pp Filter rules can enforce policy at any level of operating system specification assuming a fingerprint is present. Policy could limit traffic to approved operating systems or even ban traffic from hosts that aren't at the latest service pack. .Pp The .Ar unknown class can also be used as the fingerprint which will match packets for which no operating system fingerprint is known. .Pp Examples: .Bd -literal -offset indent pass out proto tcp from any os OpenBSD block out proto tcp from any os Doors block out proto tcp from any os "Doors PT" block out proto tcp from any os "Doors PT SP3" block out from any os "unknown" pass on lo0 proto tcp from any os "OpenBSD 3.3 lo0" .Ed .Pp Operating system fingerprinting is limited only to the TCP SYN packet. This means that it will not work on other protocols and will not match a currently established connection. .Pp Caveat: operating system fingerprints are occasionally wrong. There are three problems: an attacker can trivially craft his packets to appear as any operating system he chooses; an operating system patch could change the stack behavior and no fingerprints will match it until the database is updated; and multiple operating systems may have the same fingerprint. .Sh BLOCKING SPOOFED TRAFFIC "Spoofing" is the faking of IP addresses, typically for malicious purposes. The .Ar antispoof directive expands to a set of filter rules which will block all traffic with a source IP from the network(s) directly connected to the specified interface(s) from entering the system through any other interface. .Pp For example, the line .Bd -literal -offset indent antispoof for lo0 .Ed .Pp expands to .Bd -literal -offset indent block drop in on ! lo0 inet from 127.0.0.1/8 to any block drop in on ! lo0 inet6 from ::1 to any .Ed .Pp For non-loopback interfaces, there are additional rules to block incoming packets with a source IP address identical to the interface's IP(s). For example, assuming the interface wi0 had an IP address of 10.0.0.1 and a netmask of 255.255.255.0, the line .Bd -literal -offset indent antispoof for wi0 inet .Ed .Pp expands to .Bd -literal -offset indent block drop in on ! wi0 inet from 10.0.0.0/24 to any block drop in inet from 10.0.0.1 to any .Ed .Pp Caveat: Rules created by the .Ar antispoof directive interfere with packets sent over loopback interfaces to local addresses. One should pass these explicitly. .Sh FRAGMENT HANDLING The size of IP datagrams (packets) can be significantly larger than the maximum transmission unit (MTU) of the network. In cases when it is necessary or more efficient to send such large packets, the large packet will be fragmented into many smaller packets that will each fit onto the wire. Unfortunately for a firewalling device, only the first logical fragment will contain the necessary header information for the subprotocol that allows .Xr pf 4 to filter on things such as TCP ports or to perform NAT. .Pp Besides the use of .Ar scrub rules as described in .Sx TRAFFIC NORMALIZATION above, there are three options for handling fragments in the packet filter. .Pp One alternative is to filter individual fragments with filter rules. If no .Ar scrub rule applies to a fragment, it is passed to the filter. Filter rules with matching IP header parameters decide whether the fragment is passed or blocked, in the same way as complete packets are filtered. Without reassembly, fragments can only be filtered based on IP header fields (source/destination address, protocol), since subprotocol header fields are not available (TCP/UDP port numbers, ICMP code/type). The .Ar fragment option can be used to restrict filter rules to apply only to fragments, but not complete packets. Filter rules without the .Ar fragment option still apply to fragments, if they only specify IP header fields. For instance, the rule .Bd -literal -offset indent pass in proto tcp from any to any port 80 .Ed .Pp never applies to a fragment, even if the fragment is part of a TCP packet with destination port 80, because without reassembly this information is not available for each fragment. This also means that fragments cannot create new or match existing state table entries, which makes stateful filtering and address translation (NAT, redirection) for fragments impossible. .Pp It's also possible to reassemble only certain fragments by specifying source or destination addresses or protocols as parameters in .Ar scrub rules. .Pp In most cases, the benefits of reassembly outweigh the additional memory cost, and it's recommended to use .Ar scrub rules to reassemble all fragments via the .Ar fragment reassemble modifier. .Pp The memory allocated for fragment caching can be limited using .Xr pfctl 8 . Once this limit is reached, fragments that would have to be cached are dropped until other entries time out. The timeout value can also be adjusted. .Pp Currently, only IPv4 fragments are supported and IPv6 fragments are blocked unconditionally. .Sh ANCHORS Besides the main ruleset, .Xr pfctl 8 can load rulesets into .Ar anchor attachment points. An .Ar anchor is a container that can hold rules, address tables, and other anchors. .Pp An .Ar anchor has a name which specifies the path where .Xr pfctl 8 can be used to access the anchor to perform operations on it, such as attaching child anchors to it or loading rules into it. Anchors may be nested, with components separated by .Sq / characters, similar to how file system hierarchies are laid out. The main ruleset is actually the default anchor, so filter and translation rules, for example, may also be contained in any anchor. .Pp An anchor can reference another .Ar anchor attachment point using the following kinds of rules: .Bl -tag -width xxxx .It Ar nat-anchor Aq Ar name Evaluates the .Ar nat rules in the specified .Ar anchor . .It Ar rdr-anchor Aq Ar name Evaluates the .Ar rdr rules in the specified .Ar anchor . .It Ar binat-anchor Aq Ar name Evaluates the .Ar binat rules in the specified .Ar anchor . .It Ar anchor Aq Ar name Evaluates the filter rules in the specified .Ar anchor . .It Xo Ar load anchor .Aq Ar name .Ar from Aq Ar file .Xc Loads the rules from the specified file into the anchor .Ar name . .El .Pp When evaluation of the main ruleset reaches an .Ar anchor rule, .Xr pf 4 will proceed to evaluate all rules specified in that anchor. .Pp Matching filter and translation rules marked with the .Ar quick option are final and abort the evaluation of the rules in other anchors and the main ruleset. If the .Ar anchor itself is marked with the .Ar quick option, ruleset evaluation will terminate when the anchor is exited if the packet is matched by any rule within the anchor. .Pp .Ar anchor rules are evaluated relative to the anchor in which they are contained. For example, all .Ar anchor rules specified in the main ruleset will reference anchor attachment points underneath the main ruleset, and .Ar anchor rules specified in a file loaded from a .Ar load anchor rule will be attached under that anchor point. .Pp Rules may be contained in .Ar anchor attachment points which do not contain any rules when the main ruleset is loaded, and later such anchors can be manipulated through .Xr pfctl 8 without reloading the main ruleset or other anchors. For example, .Bd -literal -offset indent ext_if = \&"kue0\&" block on $ext_if all anchor spam pass out on $ext_if all pass in on $ext_if proto tcp from any \e to $ext_if port smtp .Ed .Pp blocks all packets on the external interface by default, then evaluates all rules in the .Ar anchor named "spam", and finally passes all outgoing connections and incoming connections to port 25. .Bd -literal -offset indent # echo \&"block in quick from 1.2.3.4 to any\&" \&| \e pfctl -a spam -f - .Ed .Pp This loads a single rule into the .Ar anchor , which blocks all packets from a specific address. .Pp The anchor can also be populated by adding a .Ar load anchor rule after the .Ar anchor rule: .Bd -literal -offset indent anchor spam load anchor spam from "/etc/pf-spam.conf" .Ed .Pp When .Xr pfctl 8 loads .Nm pf.conf , it will also load all the rules from the file .Pa /etc/pf-spam.conf into the anchor. .Pp Optionally, .Ar anchor rules can specify packet filtering parameters using the same syntax as filter rules. When parameters are used, the .Ar anchor rule is only evaluated for matching packets. This allows conditional evaluation of anchors, like: .Bd -literal -offset indent block on $ext_if all anchor spam proto tcp from any to any port smtp pass out on $ext_if all pass in on $ext_if proto tcp from any to $ext_if port smtp .Ed .Pp The rules inside .Ar anchor spam are only evaluated for .Ar tcp packets with destination port 25. Hence, .Bd -literal -offset indent # echo \&"block in quick from 1.2.3.4 to any" \&| \e pfctl -a spam -f - .Ed .Pp will only block connections from 1.2.3.4 to port 25. .Pp Anchors may end with the asterisk .Pq Sq * character, which signifies that all anchors attached at that point should be evaluated in the alphabetical ordering of their anchor name. For example, .Bd -literal -offset indent anchor "spam/*" .Ed .Pp will evaluate each rule in each anchor attached to the .Li spam anchor. Note that it will only evaluate anchors that are directly attached to the .Li spam anchor, and will not descend to evaluate anchors recursively. .Pp Since anchors are evaluated relative to the anchor in which they are contained, there is a mechanism for accessing the parent and ancestor anchors of a given anchor. Similar to file system path name resolution, if the sequence .Dq .. appears as an anchor path component, the parent anchor of the current anchor in the path evaluation at that point will become the new current anchor. As an example, consider the following: .Bd -literal -offset indent # echo ' anchor "spam/allowed" ' | pfctl -f - # echo -e ' anchor "../banned" \en pass' | \e pfctl -a spam/allowed -f - .Ed .Pp Evaluation of the main ruleset will lead into the .Li spam/allowed anchor, which will evaluate the rules in the .Li spam/banned anchor, if any, before finally evaluating the .Ar pass rule. .Pp Filter rule .Ar anchors can also be loaded inline in the ruleset within a brace ('{' '}') delimited block. Brace delimited blocks may contain rules or other brace-delimited blocks. When anchors are loaded this way the anchor name becomes optional. .Bd -literal -offset indent anchor "external" on egress { block anchor out { pass proto tcp from any to port { 25, 80, 443 } } pass in proto tcp to any port 22 } .Ed .Pp Since the parser specification for anchor names is a string, any reference to an anchor name containing .Sq / characters will require double quote .Pq Sq \&" characters around the anchor name. .Sh TRANSLATION EXAMPLES This example maps incoming requests on port 80 to port 8080, on which a daemon is running (because, for example, it is not run as root, and therefore lacks permission to bind to port 80). .Bd -literal # use a macro for the interface name, so it can be changed easily ext_if = \&"ne3\&" # map daemon on 8080 to appear to be on 80 rdr on $ext_if proto tcp from any to any port 80 -\*(Gt 127.0.0.1 port 8080 .Ed .Pp If the .Ar pass modifier is given, packets matching the translation rule are passed without inspecting the filter rules: .Bd -literal rdr pass on $ext_if proto tcp from any to any port 80 -\*(Gt 127.0.0.1 \e port 8080 .Ed .Pp In the example below, vlan12 is configured as 192.168.168.1; the machine translates all packets coming from 192.168.168.0/24 to 204.92.77.111 when they are going out any interface except vlan12. This has the net effect of making traffic from the 192.168.168.0/24 network appear as though it is the Internet routable address 204.92.77.111 to nodes behind any interface on the router except for the nodes on vlan12. (Thus, 192.168.168.1 can talk to the 192.168.168.0/24 nodes.) .Bd -literal nat on ! vlan12 from 192.168.168.0/24 to any -\*(Gt 204.92.77.111 .Ed .Pp In the example below, the machine sits between a fake internal 144.19.74.* network, and a routable external IP of 204.92.77.100. The .Ar no nat rule excludes protocol AH from being translated. .Bd -literal # NO NAT no nat on $ext_if proto ah from 144.19.74.0/24 to any nat on $ext_if from 144.19.74.0/24 to any -\*(Gt 204.92.77.100 .Ed .Pp In the example below, packets bound for one specific server, as well as those generated by the sysadmins are not proxied; all other connections are. .Bd -literal # NO RDR no rdr on $int_if proto { tcp, udp } from any to $server port 80 no rdr on $int_if proto { tcp, udp } from $sysadmins to any port 80 rdr on $int_if proto { tcp, udp } from any to any port 80 -\*(Gt 127.0.0.1 \e port 80 .Ed .Pp This longer example uses both a NAT and a redirection. The external interface has the address 157.161.48.183. On localhost, we are running .Xr ftp-proxy 8 , waiting for FTP sessions to be redirected to it. The three mandatory anchors for .Xr ftp-proxy 8 are omitted from this example; see the .Xr ftp-proxy 8 manpage. .Bd -literal # NAT # Translate outgoing packets' source addresses (any protocol). # In this case, any address but the gateway's external address is mapped. nat on $ext_if inet from ! ($ext_if) to any -\*(Gt ($ext_if) # NAT PROXYING # Map outgoing packets' source port to an assigned proxy port instead of # an arbitrary port. # In this case, proxy outgoing isakmp with port 500 on the gateway. nat on $ext_if inet proto udp from any port = isakmp to any -\*(Gt ($ext_if) \e port 500 # BINAT # Translate outgoing packets' source address (any protocol). # Translate incoming packets' destination address to an internal machine # (bidirectional). binat on $ext_if from 10.1.2.150 to any -\*(Gt $ext_if # RDR # Translate incoming packets' destination addresses. # As an example, redirect a TCP and UDP port to an internal machine. rdr on $ext_if inet proto tcp from any to ($ext_if) port 8080 \e -\*(Gt 10.1.2.151 port 22 rdr on $ext_if inet proto udp from any to ($ext_if) port 8080 \e -\*(Gt 10.1.2.151 port 53 # RDR # Translate outgoing ftp control connections to send them to localhost # for proxying with ftp-proxy(8) running on port 8021. rdr on $int_if proto tcp from any to any port 21 -\*(Gt 127.0.0.1 port 8021 .Ed .Pp In this example, a NAT gateway is set up to translate internal addresses using a pool of public addresses (192.0.2.16/28) and to redirect incoming web server connections to a group of web servers on the internal network. .Bd -literal # NAT LOAD BALANCE # Translate outgoing packets' source addresses using an address pool. # A given source address is always translated to the same pool address by # using the source-hash keyword. nat on $ext_if inet from any to any -\*(Gt 192.0.2.16/28 source-hash # RDR ROUND ROBIN # Translate incoming web server connections to a group of web servers on # the internal network. rdr on $ext_if proto tcp from any to any port 80 \e -\*(Gt { 10.1.2.155, 10.1.2.160, 10.1.2.161 } round-robin .Ed .Sh FILTER EXAMPLES .Bd -literal # The external interface is kue0 # (157.161.48.183, the only routable address) # and the private network is 10.0.0.0/8, for which we are doing NAT. # use a macro for the interface name, so it can be changed easily ext_if = \&"kue0\&" # normalize all incoming traffic scrub in on $ext_if all fragment reassemble # block and log everything by default block return log on $ext_if all # block anything coming from source we have no back routes for block in from no-route to any # block packets whose ingress interface does not match the one in # the route back to their source address block in from urpf-failed to any # block and log outgoing packets that do not have our address as source, # they are either spoofed or something is misconfigured (NAT disabled, # for instance), we want to be nice and do not send out garbage. block out log quick on $ext_if from ! 157.161.48.183 to any # silently drop broadcasts (cable modem noise) block in quick on $ext_if from any to 255.255.255.255 # block and log incoming packets from reserved address space and invalid # addresses, they are either spoofed or misconfigured, we cannot reply to # them anyway (hence, no return-rst). block in log quick on $ext_if from { 10.0.0.0/8, 172.16.0.0/12, \e 192.168.0.0/16, 255.255.255.255/32 } to any # ICMP # pass out/in certain ICMP queries and keep state (ping) # state matching is done on host addresses and ICMP id (not type/code), # so replies (like 0/0 for 8/0) will match queries # ICMP error messages (which always refer to a TCP/UDP packet) are # handled by the TCP/UDP states pass on $ext_if inet proto icmp all icmp-type 8 code 0 # UDP # pass out all UDP connections and keep state pass out on $ext_if proto udp all # pass in certain UDP connections and keep state (DNS) pass in on $ext_if proto udp from any to any port domain # TCP # pass out all TCP connections and modulate state pass out on $ext_if proto tcp all modulate state # pass in certain TCP connections and keep state (SSH, SMTP, DNS, IDENT) pass in on $ext_if proto tcp from any to any port { ssh, smtp, domain, \e auth } # Do not allow Windows 9x SMTP connections since they are typically # a viral worm. Alternately we could limit these OSes to 1 connection each. block in on $ext_if proto tcp from any os {"Windows 95", "Windows 98"} \e to any port smtp # IPv6 # pass in/out all IPv6 traffic: note that we have to enable this in two # different ways, on both our physical interface and our tunnel pass quick on gif0 inet6 pass quick on $ext_if proto ipv6 # Packet Tagging # three interfaces: $int_if, $ext_if, and $wifi_if (wireless). NAT is # being done on $ext_if for all outgoing packets. tag packets in on # $int_if and pass those tagged packets out on $ext_if. all other # outgoing packets (i.e., packets from the wireless network) are only # permitted to access port 80. pass in on $int_if from any to any tag INTNET pass in on $wifi_if from any to any block out on $ext_if from any to any pass out quick on $ext_if tagged INTNET pass out on $ext_if proto tcp from any to any port 80 # tag incoming packets as they are redirected to spamd(8). use the tag # to pass those packets through the packet filter. rdr on $ext_if inet proto tcp from \*(Ltspammers\*(Gt to port smtp \e tag SPAMD -\*(Gt 127.0.0.1 port spamd block in on $ext_if pass in on $ext_if inet proto tcp tagged SPAMD .Ed .Sh GRAMMAR Syntax for .Nm in BNF: .Bd -literal line = ( option | pf-rule | nat-rule | binat-rule | rdr-rule | antispoof-rule | altq-rule | queue-rule | trans-anchors | anchor-rule | anchor-close | load-anchor | table-rule | include ) option = "set" ( [ "timeout" ( timeout | "{" timeout-list "}" ) ] | [ "ruleset-optimization" [ "none" | "basic" | "profile" ]] | [ "optimization" [ "default" | "normal" | "high-latency" | "satellite" | "aggressive" | "conservative" ] ] [ "limit" ( limit-item | "{" limit-list "}" ) ] | [ "loginterface" ( interface-name | "none" ) ] | [ "block-policy" ( "drop" | "return" ) ] | [ "state-policy" ( "if-bound" | "floating" ) ] [ "state-defaults" state-opts ] [ "require-order" ( "yes" | "no" ) ] [ "fingerprints" filename ] | [ "skip on" ifspec ] | [ "debug" ( "none" | "urgent" | "misc" | "loud" ) ] ) pf-rule = action [ ( "in" | "out" ) ] [ "log" [ "(" logopts ")"] ] [ "quick" ] [ "on" ifspec ] [ "fastroute" | route ] [ af ] [ protospec ] hosts [ filteropt-list ] logopts = logopt [ "," logopts ] logopt = "all" | "user" | "to" interface-name filteropt-list = filteropt-list filteropt | filteropt filteropt = user | group | flags | icmp-type | icmp6-type | "tos" tos | ( "no" | "keep" | "modulate" | "synproxy" ) "state" [ "(" state-opts ")" ] | "fragment" | "no-df" | "min-ttl" number | "set-tos" tos | "max-mss" number | "random-id" | "reassemble tcp" | fragmentation | "allow-opts" | "label" string | "tag" string | [ ! ] "tagged" string | "queue" ( string | "(" string [ [ "," ] string ] ")" ) | "rtable" number | "probability" number"%" nat-rule = [ "no" ] "nat" [ "pass" [ "log" [ "(" logopts ")" ] ] ] [ "on" ifspec ] [ af ] [ protospec ] hosts [ "tag" string ] [ "tagged" string ] [ "-\*(Gt" ( redirhost | "{" redirhost-list "}" ) [ portspec ] [ pooltype ] [ "static-port" ] ] binat-rule = [ "no" ] "binat" [ "pass" [ "log" [ "(" logopts ")" ] ] ] [ "on" interface-name ] [ af ] [ "proto" ( proto-name | proto-number ) ] "from" address [ "/" mask-bits ] "to" ipspec [ "tag" string ] [ "tagged" string ] [ "-\*(Gt" address [ "/" mask-bits ] ] rdr-rule = [ "no" ] "rdr" [ "pass" [ "log" [ "(" logopts ")" ] ] ] [ "on" ifspec ] [ af ] [ protospec ] hosts [ "tag" string ] [ "tagged" string ] [ "-\*(Gt" ( redirhost | "{" redirhost-list "}" ) [ portspec ] [ pooltype ] ] antispoof-rule = "antispoof" [ "log" ] [ "quick" ] "for" ifspec [ af ] [ "label" string ] table-rule = "table" "\*(Lt" string "\*(Gt" [ tableopts-list ] tableopts-list = tableopts-list tableopts | tableopts tableopts = "persist" | "const" | "counters" | "file" string | "{" [ tableaddr-list ] "}" tableaddr-list = tableaddr-list [ "," ] tableaddr-spec | tableaddr-spec tableaddr-spec = [ "!" ] tableaddr [ "/" mask-bits ] tableaddr = hostname | ifspec | "self" | ipv4-dotted-quad | ipv6-coloned-hex altq-rule = "altq on" interface-name queueopts-list "queue" subqueue queue-rule = "queue" string [ "on" interface-name ] queueopts-list subqueue anchor-rule = "anchor" [ string ] [ ( "in" | "out" ) ] [ "on" ifspec ] [ af ] [ protospec ] [ hosts ] [ filteropt-list ] [ "{" ] anchor-close = "}" trans-anchors = ( "nat-anchor" | "rdr-anchor" | "binat-anchor" ) string [ "on" ifspec ] [ af ] [ "proto" ] [ protospec ] [ hosts ] load-anchor = "load anchor" string "from" filename queueopts-list = queueopts-list queueopts | queueopts queueopts = [ "bandwidth" bandwidth-spec ] | [ "qlimit" number ] | [ "tbrsize" number ] | [ "priority" number ] | [ schedulers ] schedulers = ( cbq-def | priq-def | hfsc-def ) bandwidth-spec = "number" ( "b" | "Kb" | "Mb" | "Gb" | "%" ) action = "pass" | "block" [ return ] | [ "no" ] "scrub" return = "drop" | "return" | "return-rst" [ "( ttl" number ")" ] | "return-icmp" [ "(" icmpcode [ [ "," ] icmp6code ] ")" ] | "return-icmp6" [ "(" icmp6code ")" ] icmpcode = ( icmp-code-name | icmp-code-number ) icmp6code = ( icmp6-code-name | icmp6-code-number ) ifspec = ( [ "!" ] ( interface-name | interface-group ) ) | "{" interface-list "}" interface-list = [ "!" ] ( interface-name | interface-group ) [ [ "," ] interface-list ] route = ( "route-to" | "reply-to" | "dup-to" ) ( routehost | "{" routehost-list "}" ) [ pooltype ] af = "inet" | "inet6" protospec = "proto" ( proto-name | proto-number | "{" proto-list "}" ) proto-list = ( proto-name | proto-number ) [ [ "," ] proto-list ] hosts = "all" | "from" ( "any" | "no-route" | "urpf-failed" | "self" | host | "{" host-list "}" ) [ port ] [ os ] "to" ( "any" | "no-route" | "self" | host | "{" host-list "}" ) [ port ] ipspec = "any" | host | "{" host-list "}" host = [ "!" ] ( address [ "/" mask-bits ] | "\*(Lt" string "\*(Gt" ) redirhost = address [ "/" mask-bits ] routehost = "(" interface-name [ address [ "/" mask-bits ] ] ")" address = ( interface-name | interface-group | "(" ( interface-name | interface-group ) ")" | hostname | ipv4-dotted-quad | ipv6-coloned-hex ) host-list = host [ [ "," ] host-list ] redirhost-list = redirhost [ [ "," ] redirhost-list ] routehost-list = routehost [ [ "," ] routehost-list ] port = "port" ( unary-op | binary-op | "{" op-list "}" ) portspec = "port" ( number | name ) [ ":" ( "*" | number | name ) ] os = "os" ( os-name | "{" os-list "}" ) user = "user" ( unary-op | binary-op | "{" op-list "}" ) group = "group" ( unary-op | binary-op | "{" op-list "}" ) unary-op = [ "=" | "!=" | "\*(Lt" | "\*(Le" | "\*(Gt" | "\*(Ge" ] ( name | number ) binary-op = number ( "\*(Lt\*(Gt" | "\*(Gt\*(Lt" | ":" ) number op-list = ( unary-op | binary-op ) [ [ "," ] op-list ] os-name = operating-system-name os-list = os-name [ [ "," ] os-list ] flags = "flags" ( [ flag-set ] "/" flag-set | "any" ) flag-set = [ "F" ] [ "S" ] [ "R" ] [ "P" ] [ "A" ] [ "U" ] [ "E" ] [ "W" ] icmp-type = "icmp-type" ( icmp-type-code | "{" icmp-list "}" ) icmp6-type = "icmp6-type" ( icmp-type-code | "{" icmp-list "}" ) icmp-type-code = ( icmp-type-name | icmp-type-number ) [ "code" ( icmp-code-name | icmp-code-number ) ] icmp-list = icmp-type-code [ [ "," ] icmp-list ] tos = ( "lowdelay" | "throughput" | "reliability" | [ "0x" ] number ) state-opts = state-opt [ [ "," ] state-opts ] state-opt = ( "max" number | "no-sync" | timeout | "sloppy" | "pflow" | "source-track" [ ( "rule" | "global" ) ] | "max-src-nodes" number | "max-src-states" number | "max-src-conn" number | "max-src-conn-rate" number "/" number | "overload" "\*(Lt" string "\*(Gt" [ "flush" ] | "if-bound" | "floating" ) fragmentation = [ "fragment reassemble" | "fragment crop" | "fragment drop-ovl" ] timeout-list = timeout [ [ "," ] timeout-list ] timeout = ( "tcp.first" | "tcp.opening" | "tcp.established" | "tcp.closing" | "tcp.finwait" | "tcp.closed" | "udp.first" | "udp.single" | "udp.multiple" | "icmp.first" | "icmp.error" | "other.first" | "other.single" | "other.multiple" | "frag" | "interval" | "src.track" | "adaptive.start" | "adaptive.end" ) number limit-list = limit-item [ [ "," ] limit-list ] limit-item = ( "states" | "frags" | "src-nodes" ) number pooltype = ( "bitmask" | "random" | "source-hash" [ ( hex-key | string-key ) ] | "round-robin" ) [ sticky-address ] subqueue = string | "{" queue-list "}" queue-list = string [ [ "," ] string ] cbq-def = "cbq" [ "(" cbq-opt [ [ "," ] cbq-opt ] ")" ] priq-def = "priq" [ "(" priq-opt [ [ "," ] priq-opt ] ")" ] hfsc-def = "hfsc" [ "(" hfsc-opt [ [ "," ] hfsc-opt ] ")" ] cbq-opt = ( "default" | "borrow" | "red" | "ecn" | "rio" ) priq-opt = ( "default" | "red" | "ecn" | "rio" ) hfsc-opt = ( "default" | "red" | "ecn" | "rio" | linkshare-sc | realtime-sc | upperlimit-sc ) linkshare-sc = "linkshare" sc-spec realtime-sc = "realtime" sc-spec upperlimit-sc = "upperlimit" sc-spec sc-spec = ( bandwidth-spec | "(" bandwidth-spec number bandwidth-spec ")" ) include = "include" filename .Ed .Sh FILES .Bl -tag -width "/etc/protocols" -compact .It Pa /etc/hosts Host name database. .It Pa /etc/pf.conf Default location of the ruleset file. .It Pa /etc/pf.os Default location of OS fingerprints. .It Pa /etc/protocols Protocol name database. .It Pa /etc/services Service name database. .El .Sh SEE ALSO .Xr altq 4 , .Xr carp 4 , .Xr icmp 4 , .Xr icmp6 4 , .Xr ip 4 , .Xr ip6 4 , .Xr pf 4 , .Xr pflow 4 , .Xr pfsync 4 , .Xr tcp 4 , .Xr udp 4 , .Xr hosts 5 , .Xr pf.os 5 , .Xr protocols 5 , .Xr services 5 , .Xr ftp-proxy 8 , .Xr pfctl 8 , .Xr pflogd 8 .Sh HISTORY The .Nm file format first appeared in .Ox 3.0 . Index: projects/sendfile/share/man/man5/pf.os.5 =================================================================== --- projects/sendfile/share/man/man5/pf.os.5 (revision 276056) +++ projects/sendfile/share/man/man5/pf.os.5 (revision 276057) @@ -1,223 +1,223 @@ .\" $OpenBSD: pf.os.5,v 1.8 2007/05/31 19:19:58 jmc Exp $ .\" .\" Copyright (c) 2003 Mike Frantzen .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .\" $FreeBSD$ .\" -.Dd May 31 2007 +.Dd May 31, 2007 .Dt PF.OS 5 .Os .Sh NAME .Nm pf.os .Nd format of the operating system fingerprints file .Sh DESCRIPTION The .Xr pf 4 firewall and the .Xr tcpdump 1 program can both fingerprint the operating system of hosts that originate an IPv4 TCP connection. The file consists of newline-separated records, one per fingerprint, containing nine colon .Pq Ql \&: separated fields. These fields are as follows: .Pp .Bl -tag -width Description -offset indent -compact .It window The TCP window size. .It TTL The IP time to live. .It df The presence of the IPv4 don't fragment bit. .It packet size The size of the initial TCP packet. .It TCP options An ordered list of the TCP options. .It class The class of operating system. .It version The version of the operating system. .It subtype The subtype of patchlevel of the operating system. .It description The overall textual description of the operating system, version and subtype. .El .Pp The .Ar window field corresponds to the th->th_win field in the TCP header and is the source host's advertised TCP window size. It may be between zero and 65,535 inclusive. The window size may be given as a multiple of a constant by prepending the size with a percent sign .Sq % and the value will be used as a modulus. Three special values may be used for the window size: .Pp .Bl -tag -width xxx -offset indent -compact .It * An asterisk will wildcard the value so any window size will match. .It S Allow any window size which is a multiple of the maximum segment size (MSS). .It T Allow any window size which is a multiple of the maximum transmission unit (MTU). .El .Pp The .Ar ttl value is the initial time to live in the IP header. The fingerprint code will account for the volatility of the packet's TTL as it traverses a network. .Pp The .Ar df bit corresponds to the Don't Fragment bit in an IPv4 header. It tells intermediate routers not to fragment the packet and is used for path MTU discovery. It may be either a zero or a one. .Pp The .Ar packet size is the literal size of the full IP packet and is a function of all of the IP and TCP options. .Pp The .Ar TCP options field is an ordered list of the individual TCP options that appear in the SYN packet. Each option is described by a single character separated by a comma and certain ones may include a value. The options are: .Pp .Bl -tag -width Description -offset indent -compact .It Mnnn maximum segment size (MSS) option. The value is the maximum packet size of the network link which may include the .Sq % modulus or match all MSSes with the .Sq * value. .It N the NOP option (NO Operation). .It T[0] the timestamp option. Certain operating systems always start with a zero timestamp in which case a zero value is added to the option; otherwise no value is appended. .It S the Selective ACKnowledgement OK (SACKOK) option. .It Wnnn window scaling option. The value is the size of the window scaling which may include the .Sq % modulus or match all window scalings with the .Sq * value. .El .Pp No TCP options in the fingerprint may be given with a single dot .Sq \&. . .Pp An example of OpenBSD's TCP options are: .Pp .Dl M*,N,N,S,N,W0,N,N,T .Pp The first option .Ar M* is the MSS option and will match all values. The second and third options .Ar N will match two NOPs. The fourth option .Ar S will match the SACKOK option. The fifth .Ar N will match another NOP. The sixth .Ar W0 will match a window scaling option with a zero scaling size. The seventh and eighth .Ar N options will match two NOPs. And the ninth and final option .Ar T will match the timestamp option with any time value. .Pp The TCP options in a fingerprint will only match packets with the exact same TCP options in the same order. .Pp The .Ar class field is the class, genre or vendor of the operating system. .Pp The .Ar version is the version of the operating system. It is used to distinguish between different fingerprints of operating systems of the same class but different versions. .Pp The .Ar subtype is the subtype or patch level of the operating system version. It is used to distinguish between different fingerprints of operating systems of the same class and same version but slightly different patches or tweaking. .Pp The .Ar description is a general description of the operating system, its version, patchlevel and any further useful details. .Sh EXAMPLES The fingerprint of a plain .Ox 3.3 host is: .Bd -literal 16384:64:1:64:M*,N,N,S,N,W0,N,N,T:OpenBSD:3.3::OpenBSD 3.3 .Ed .Pp The fingerprint of an .Ox 3.3 host behind a PF scrubbing firewall with a no-df rule would be: .Bd -literal 16384:64:0:64:M*,N,N,S,N,W0,N,N,T:OpenBSD:3.3:!df:OpenBSD 3.3 scrub no-df .Ed .Pp An absolutely braindead embedded operating system fingerprint could be: .Bd -literal 65535:255:0:40:.:DUMMY:1.1:p3:Dummy embedded OS v1.1p3 .Ed .Pp The .Xr tcpdump 1 output of .Bd -literal # tcpdump -s128 -c1 -nv 'tcp[13] == 2' 03:13:48.118526 10.0.0.1.3377 > 10.0.0.2.80: S [tcp sum ok] \e 534596083:534596083(0) win 57344 (DF) [tos 0x10] \e (ttl 64, id 11315, len 44) .Ed .Pp almost translates into the following fingerprint .Bd -literal 57344:64:1:44:M1460: exampleOS:1.0::exampleOS 1.0 .Ed .Sh SEE ALSO +.Xr tcpdump 1 , .Xr pf 4 , .Xr pf.conf 5 , -.Xr pfctl 8 , -.Xr tcpdump 1 +.Xr pfctl 8 Index: projects/sendfile/share/man/man5/rc.conf.5 =================================================================== --- projects/sendfile/share/man/man5/rc.conf.5 (revision 276056) +++ projects/sendfile/share/man/man5/rc.conf.5 (revision 276057) @@ -1,4574 +1,4574 @@ .\" Copyright (c) 1995 .\" Jordan K. Hubbard .\" .\" 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 ``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 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$ .\" .Dd September 11, 2014 .Dt RC.CONF 5 .Os .Sh NAME .Nm rc.conf .Nd system configuration information .Sh DESCRIPTION The file .Nm contains descriptive information about the local host name, configuration details for any potential network interfaces and which services should be started up at system initial boot time. In new installations, the .Nm file is generally initialized by the system installation utility. .Pp The purpose of .Nm is not to run commands or perform system startup actions directly. Instead, it is included by the various generic startup scripts in .Pa /etc which conditionalize their internal actions according to the settings found there. .Pp The .Pa /etc/rc.conf file is included from the file .Pa /etc/defaults/rc.conf , which specifies the default settings for all the available options. Options need only be specified in .Pa /etc/rc.conf when the system administrator wishes to override these defaults. The file .Pa /etc/rc.conf.local is used to override settings in .Pa /etc/rc.conf for historical reasons. .Pp In addition to .Pa /etc/rc.conf.local you can also place smaller configuration files for each .Xr rc 8 script in the .Pa /etc/rc.conf.d directory or .Ao Ar dir Ac Ns Pa /rc.conf.d directories specified in .Va local_startup , which will be included by the .Va load_rc_config function. For jail configurations you could use the file .Pa /etc/rc.conf.d/jail to store jail specific configuration options. If .Va local_startup contains .Pa /usr/local/etc/rc.d and .Pa /opt/conf , .Pa /usr/local/rc.conf.d/jail and .Pa /opt/conf/rc.conf.d/jail will be loaded. If .Ao Ar dir Ac Ns Pa /rc.conf.d/ Ns Ao Ar name Ac is a directory, all of files in the directory will be loaded. Also see the .Va rc_conf_files variable below. .Pp Options are set with .Dq Ar name Ns Li = Ns Ar value assignments that use .Xr sh 1 syntax. The following list provides a name and short description for each variable that can be set in the .Nm file: .Bl -tag -width indent-two .It Va rc_debug .Pq Vt bool If set to .Dq Li YES , enable output of debug messages from rc scripts. This variable can be helpful in diagnosing mistakes when editing or integrating new scripts. Beware that this produces copious output to the terminal and .Xr syslog 3 . .It Va rc_info .Pq Vt bool If set to .Dq Li NO , disable informational messages from the rc scripts. Informational messages are displayed when a condition that is not serious enough to warrant a warning or an error occurs. .It Va rc_startmsgs .Pq Vt bool If set to .Dq Li YES , show .Dq Starting foo: when faststart is used (e.g., at boot time). .It Va early_late_divider .Pq Vt str The name of the script that should be used as the delimiter between the .Dq early and .Dq late stages of the boot process. The early stage should contain all the services needed to get the disks (local or remote) mounted so that the late stage can include scripts contained in the directories listed in the .Va local_startup variable (see below). Thus, the two likely candidates for this value are .Pa mountcritlocal for the typical system, and .Pa mountcritremote if the system needs remote file systems mounted to get access to the .Va local_startup directories; for example when .Pa /usr/local is NFS mounted. For .Pa rc.conf within a .Xr jail 8 .Pa NETWORKING is likely to be an appropriate value. Extreme care should be taken when changing this value, and before changing it one should ensure that there are adequate provisions to recover from a failed boot (such as physical contact with the machine, or reliable remote console access). .It Va always_force_depends .Pq Vt bool Various .Pa rc.d scripts use the force_depend function to check whether required services are already running, and to start them if necessary. By default during boot time this check is bypassed if the required service is enabled in .Pa /etc/rc.conf[.local] . Setting this option will bypass that check at boot time and always test whether or not the service is actually running. Enabling this option is likely to increase your boot time if services are enabled that utilize the force_depend check. .It Ao Ar name Ac Ns Va _chroot .Pq Vt str .Xr chroot to this directory before running the service. .It Ao Ar name Ac Ns Va _user .Pq Vt str Run the service under this user account. .It Ao Ar name Ac Ns Va _group .Pq Vt str Run the chrooted service under this system group. Unlike the _user setting, this setting has no effect if the service is not chrooted. .It Ao Ar name Ac Ns Va _fib .Pq Vt int The .Xr setfib 1 value to run the service under. .It Ao Ar name Ac Ns Va _nice .Pq Vt int The .Xr nice 1 value to run the service under. .It Va apm_enable .Pq Vt bool If set to .Dq Li YES , enable support for Automatic Power Management with the .Xr apm 8 command. .It Va apmd_enable .Pq Vt bool Run .Xr apmd 8 to handle APM event from userland. This also enables support for APM. .It Va apmd_flags .Pq Vt str If .Va apmd_enable is set to .Dq Li YES , these are the flags to pass to the .Xr apmd 8 daemon. .It Va devd_enable .Pq Vt bool Run .Xr devd 8 to handle device added, removed or unknown events from the kernel. .It Va ddb_enable .Pq Vt bool Run .Xr ddb 8 to install .Xr ddb 4 scripts at boot time. .It Va ddb_config .Pq Vt str Configuration file for .Xr ddb 8 . Default .Pa /etc/ddb.conf . .It Va kld_list .Pq Vt str A list of kernel modules to load right after the local disks are mounted. Loading modules at this point in the boot process is much faster than doing it via .Pa /boot/loader.conf for those modules not necessary for mounting local disk. .It Va kldxref_enable .Pq Vt bool Set to .Dq Li NO by default. Set to .Dq Li YES to automatically rebuild .Pa linker.hints files with .Xr kldxref 8 at boot time. .It Va kldxref_clobber .Pq Vt bool Set to .Dq Li NO by default. If .Va kldxref_enable is true, setting to .Dq Li YES will overwrite existing .Pa linker.hints files at boot time. Otherwise, only missing .Pa linker.hints files are generated. .It Va kldxref_module_path .Pq Vt str Empty by default. A semi-colon .Pq Ql \&; delimited list of paths containing .Xr kld 4 modules. If empty, the contents of the .Va kern.module_path .Xr sysctl 8 are used. .It Va powerd_enable .Pq Vt bool If set to .Dq Li YES , enable the system power control facility with the .Xr powerd 8 daemon. .It Va powerd_flags .Pq Vt str If .Va powerd_enable is set to .Dq Li YES , these are the flags to pass to the .Xr powerd 8 daemon. .It Va tmpmfs Controls the creation of a .Pa /tmp memory file system. Always happens if set to .Dq Li YES and never happens if set to .Dq Li NO . If set to anything else, a memory file system is created if .Pa /tmp is not writable. .It Va tmpsize Controls the size of a created .Pa /tmp memory file system. .It Va tmpmfs_flags Extra options passed to the .Xr mdmfs 8 utility when the memory file system for .Pa /tmp is created. The default is .Dq Li "-S" , which inhibits the use of softupdates on .Pa /tmp so that file system space is freed without delay after file truncation or deletion. See .Xr mdmfs 8 for other options you can use in .Va tmpmfs_flags . .It Va varmfs Controls the creation of a .Pa /var memory file system. Always happens if set to .Dq Li YES and never happens if set to .Dq Li NO . If set to anything else, a memory file system is created if .Pa /var is not writable. .It Va varsize Controls the size of a created .Pa /var memory file system. .It Va varmfs_flags Extra options passed to the .Xr mdmfs 8 utility when the memory file system for .Pa /var is created. The default is .Dq Li "-S" , which inhibits the use of softupdates on .Pa /var so that file system space is freed without delay after file truncation or deletion. See .Xr mdmfs 8 for other options you can use in .Va varmfs_flags . .It Va populate_var Controls the automatic population of the .Pa /var file system. Always happens if set to .Dq Li YES and never happens if set to .Dq Li NO . If set to anything else, a memory file system is created if .Pa /var is not writable. Note that this process requires access to certain commands in .Pa /usr before .Pa /usr is mounted on normal systems. .It Va cleanvar_enable .Pq Vt bool Clean the .Pa /var directory. .It Va local_startup .Pq Vt str List of directories to search for startup script files. .It Va script_name_sep .Pq Vt str The field separator to use for breaking down the list of startup script files into individual filenames. The default is a space. It is not necessary to change this unless there are startup scripts with names containing spaces. .It Va hostapd_enable .Pq Vt bool Set to .Dq Li YES to start .Xr hostapd 8 at system boot time. .It Va hostname .Pq Vt str The fully qualified domain name (FQDN) of this host on the network. This should almost certainly be set to something meaningful, even if there is no network connection. If .Xr dhclient 8 is used to set the hostname via DHCP, this variable should be set to an empty string. If this value remains unset when the system is done booting your console login will display the default hostname of .Dq Amnesiac . .It Va nisdomainname .Pq Vt str The NIS domain name of this host, or .Dq Li NO if NIS is not used. .It Va dhclient_program .Pq Vt str Path to the DHCP client program .Pa ( /sbin/dhclient , the .Ox DHCP client, is the default). .It Va dhclient_flags .Pq Vt str Additional flags to pass to the DHCP client program. For the .Ox DHCP client, see the .Xr dhclient 8 manpage for a description of the command line options available. .It Va dhclient_flags_ Ns Aq Ar iface Additional flags to pass to the DHCP client program running on .Ar iface only. When specified, this variable overrides .Va dhclient_flags . .It Va background_dhclient .Pq Vt bool Set to .Dq Li YES to start the DHCP client in background. This can cause trouble with applications depending on a working network, but it will provide a faster startup in many cases. .It Va background_dhclient_ Ns Aq Ar iface When specified, this variable overrides the .Va background_dhclient variable for interface .Ar iface only. .It Va synchronous_dhclient .Pq Vt bool Set to .Dq Li YES to start .Xr dhclient 8 synchronously at startup. This behavior can be overridden on a per-interface basis by replacing the .Dq Li DHCP keyword in the .Va ifconfig_ Ns Aq Ar interface variable with .Dq Li SYNCDHCP or .Dq Li NOSYNCDHCP . .It Va defaultroute_delay .Pq Vt int When set to a positive value, wait up to this long after configuring DHCP interfaces at startup to give the interfaces time to receive a lease. .It Va firewall_enable .Pq Vt bool Set to .Dq Li YES to load firewall rules at startup. If the kernel was not built with .Cd "options IPFIREWALL" , the .Pa ipfw.ko kernel module will be loaded. See also .Va ipfilter_enable . .It Va firewall_script .Pq Vt str This variable specifies the full path to the firewall script to run. The default is .Pa /etc/rc.firewall . .It Va firewall_type .Pq Vt str Names the firewall type from the selection in .Pa /etc/rc.firewall , or the file which contains the local firewall ruleset. Valid selections from .Pa /etc/rc.firewall are: .Pp .Bl -tag -width ".Li simple" -compact .It Li open unrestricted IP access .It Li closed all IP services disabled, except via .Dq Li lo0 .It Li client basic protection for a workstation .It Li simple basic protection for a LAN. .El .Pp If a filename is specified, the full path must be given. .It Va firewall_quiet .Pq Vt bool Set to .Dq Li YES to disable the display of firewall rules on the console during boot. .It Va firewall_logging .Pq Vt bool Set to .Dq Li YES to enable firewall event logging. This is equivalent to the .Dv IPFIREWALL_VERBOSE kernel option. .It Va firewall_logif .Pq Vt bool Set to .Dq Li YES to create pseudo interface .Li ipfw0 for logging. For more details, see .Xr ipfw 8 manual page. .It Va firewall_flags .Pq Vt str Flags passed to .Xr ipfw 8 if .Va firewall_type specifies a filename. .It Va firewall_coscripts .Pq Vt str List of executables and/or rc scripts to run after firewall starts/stops. Default is empty. .\" ----- firewall_nat_enable setting -------------------------------- .It Va firewall_nat_enable .Pq Vt bool The .Xr ipfw 8 equivalent of .Va natd_enable . Setting this to .Dq Li YES enables kernel NAT. .Va firewall_enable must also be set to .Dq Li YES . .It Va firewall_nat_interface .Pq Vt str The .Xr ipfw 8 equivalent of .Va natd_interface . This is the name of the public interface or IP address on which kernel NAT should run. .It Va firewall_nat_flags .Pq Vt str Additional configuration parameters for kernel NAT should be placed here. .It Va dummynet_enable .Pq Vt bool Setting this to .Dq Li YES will automatically load the .Xr dummynet 4 module if .Va firewall_enable is also set to .Dq Li YES . .\" ------------------------------------------------------------------- .It Va natd_program .Pq Vt str Path to .Xr natd 8 . .It Va natd_enable .Pq Vt bool Set to .Dq Li YES to enable .Xr natd 8 . .Va firewall_enable must also be set to .Dq Li YES , and .Xr divert 4 sockets must be enabled in the kernel. If the kernel was not built with .Cd "options IPDIVERT" , the .Pa ipdivert.ko kernel module will be loaded. .It Va natd_interface .Pq Vt str This is the name of the public interface on which .Xr natd 8 should run. The interface may be given as an interface name or as an IP address. .It Va natd_flags .Pq Vt str Additional .Xr natd 8 flags should be placed here. The .Fl n or .Fl a flag is automatically added with the above .Va natd_interface as an argument. .\" ----- ipfilter_enable setting -------------------------------- .It Va ipfilter_enable .Pq Vt bool Set to .Dq Li NO by default. Setting this to .Dq Li YES enables .Xr ipf 8 packet filtering. .Pp Typical usage will require putting .Bd -literal ipfilter_enable="YES" ipnat_enable="YES" ipmon_enable="YES" ipfs_enable="YES" .Ed .Pp into .Pa /etc/rc.conf and editing .Pa /etc/ipf.rules and .Pa /etc/ipnat.rules appropriately. .Pp Note that .Va ipfilter_enable and .Va ipnat_enable can be enabled independently. .Va ipmon_enable and .Va ipfs_enable both require at least one of .Va ipfilter_enable and .Va ipnat_enable to be enabled. .Pp Having .Bd -literal options IPFILTER options IPFILTER_LOG options IPFILTER_DEFAULT_BLOCK .Ed .Pp in the kernel configuration file is a good idea, too. .\" ----- ipfilter_program setting ------------------------------ .It Va ipfilter_program .Pq Vt str Path to .Xr ipf 8 (default .Pa /sbin/ipf ) . .\" ----- ipfilter_rules setting -------------------------------- .It Va ipfilter_rules .Pq Vt str Set to .Pa /etc/ipf.rules by default. This variable contains the name of the filter rule definition file. The file is expected to be readable for the .Xr ipf 8 command to execute. .\" ----- ipv6_ipfilter_rules setting --------------------------- .It Va ipv6_ipfilter_rules .Pq Vt str Set to .Pa /etc/ipf6.rules by default. This variable contains the IPv6 filter rule definition file. The file is expected to be readable for the .Xr ipf 8 command to execute. .\" ----- ipfilter_flags setting -------------------------------- .It Va ipfilter_flags .Pq Vt str Empty by default. This variable contains flags passed to the .Xr ipf 8 program. .\" ----- ipnat_enable setting ---------------------------------- .It Va ipnat_enable .Pq Vt bool Set to .Dq Li NO by default. Set it to .Dq Li YES to enable .Xr ipnat 8 network address translation. See .Va ipfilter_enable for a detailed discussion. .\" ----- ipnat_program setting --------------------------------- .It Va ipnat_program .Pq Vt str Path to .Xr ipnat 8 (default .Pa /sbin/ipnat ) . .\" ----- ipnat_rules setting ----------------------------------- .It Va ipnat_rules .Pq Vt str Set to .Pa /etc/ipnat.rules by default. This variable contains the name of the file holding the network address translation definition. This file is expected to be readable for the .Xr ipnat 8 command to execute. .\" ----- ipnat_flags setting ----------------------------------- .It Va ipnat_flags .Pq Vt str Empty by default. This variable contains flags passed to the .Xr ipnat 8 program. .\" ----- ipmon_enable setting ---------------------------------- .It Va ipmon_enable .Pq Vt bool Set to .Dq Li NO by default. Set it to .Dq Li YES to enable .Xr ipmon 8 monitoring (logging .Xr ipf 8 and .Xr ipnat 8 events). Setting this variable needs setting .Va ipfilter_enable or .Va ipnat_enable too. See .Va ipfilter_enable for a detailed discussion. .\" ----- ipmon_program setting --------------------------------- .It Va ipmon_program .Pq Vt str Path to .Xr ipmon 8 (default .Pa /sbin/ipmon ) . .\" ----- ipmon_flags setting ----------------------------------- .It Va ipmon_flags .Pq Vt str Set to .Dq Li -Ds by default. This variable contains flags passed to the .Xr ipmon 8 program. Another typical example would be .Dq Fl D Pa /var/log/ipflog to have .Xr ipmon 8 log directly to a file bypassing .Xr syslogd 8 . Make sure to adjust .Pa /etc/newsyslog.conf in such case like this: .Bd -literal /var/log/ipflog 640 10 100 * Z /var/run/ipmon.pid .Ed .\" ----- ipfs_enable setting ----------------------------------- .It Va ipfs_enable .Pq Vt bool Set to .Dq Li NO by default. Set it to .Dq Li YES to enable .Xr ipfs 8 saving the filter and NAT state tables during shutdown and reloading them during startup again. Setting this variable needs setting .Va ipfilter_enable or .Va ipnat_enable to .Dq Li YES too. See .Va ipfilter_enable for a detailed discussion. Note that if .Va kern_securelevel is set to 3, .Va ipfs_enable cannot be used because the raised securelevel will prevent .Xr ipfs 8 from saving the state tables at shutdown time. .\" ----- ipfs_program setting ---------------------------------- .It Va ipfs_program .Pq Vt str Path to .Xr ipfs 8 (default .Pa /sbin/ipfs ) . .\" ----- ipfs_flags setting ------------------------------------ .It Va ipfs_flags .Pq Vt str Empty by default. This variable contains flags passed to the .Xr ipfs 8 program. .\" ----- end of added ipf hook --------------------------------- .It Va pf_enable .Pq Vt bool Set to .Dq Li NO by default. Setting this to .Dq Li YES enables .Xr pf 4 packet filtering. .Pp Typical usage will require putting .Pp .Dl pf_enable="YES" .Pp into .Pa /etc/rc.conf and editing .Pa /etc/pf.conf appropriately. Adding .Pp .Dl "device pf" .Pp builds support for .Xr pf 4 into the kernel, otherwise the kernel module will be loaded. .It Va pf_rules .Pq Vt str Path to .Xr pf 4 ruleset configuration file (default .Pa /etc/pf.conf ) . .It Va pf_program .Pq Vt str Path to .Xr pfctl 8 (default .Pa /sbin/pfctl ) . .It Va pf_flags .Pq Vt str If .Va pf_enable is set to .Dq Li YES , these flags are passed to the .Xr pfctl 8 program when loading the ruleset. .It Va pflog_enable .Pq Vt bool Set to .Dq Li NO by default. Setting this to .Dq Li YES enables .Xr pflogd 8 which logs packets from the .Xr pf 4 packet filter. .It Va pflog_logfile .Pq Vt str If .Va pflog_enable is set to .Dq Li YES this controls where .Xr pflogd 8 stores the logfile (default .Pa /var/log/pflog ) . Check .Pa /etc/newsyslog.conf to adjust logfile rotation for this. .It Va pflog_program .Pq Vt str Path to .Xr pflogd 8 (default .Pa /sbin/pflogd ) . .It Va pflog_flags .Pq Vt str Empty by default. This variable contains additional flags passed to the .Xr pflogd 8 program. .It Va pflog_instances .Pq Vt str If logging to more than one .Xr pflog 4 interface is desired, .Va pflog_instances is set to the list of .Xr pflogd 8 instances that should be started at system boot time. If .Va pflog_instances is set, for each whitespace-seperated .Ar element in the list, .Ao Ar element Ac Ns Va _dev and .Ao Ar element Ac Ns Va _logfile elements are assumed to exist. .Ao Ar element Ac Ns Va _dev must contain the .Xr pflog 4 interface to be watched by the named .Xr pflogd 8 instance. .Ao Ar element Ac Ns Va _logfile must contain the name of the logfile that will be used by the .Xr pflogd 8 instance. .It Va ftpproxy_enable .Pq Vt bool Set to .Dq Li NO by default. Setting this to .Dq Li YES enables .Xr ftp-proxy 8 which supports the .Xr pf 4 packet filter in translating ftp connections. .It Va ftpproxy_flags .Pq Vt str Empty by default. This variable contains additional flags passed to the .Xr ftp-proxy 8 program. .It Va ftpproxy_instances .Pq Vt str Empty by default. If multiple instances of .Xr ftp-proxy 8 are desired at boot time, .Va ftpproxy_instances should contain a whitespace-seperated list of instance names. For each .Ar element in the list, a variable named .Ao Ar element Ac Ns Va _flags should be defined, containing the command-line flags to be passed to the .Xr ftp-proxy 8 instance. .It Va pfsync_enable .Pq Vt bool Set to .Dq Li NO by default. Setting this to .Dq Li YES enables exposing .Xr pf 4 state changes to other hosts over the network by means of .Xr pfsync 4 . The .Va pfsync_syncdev variable must also be set then. .It Va pfsync_syncdev .Pq Vt str Empty by default. This variable specifies the name of the network interface .Xr pfsync 4 should operate through. It must be set accordingly if .Va pfsync_enable is set to .Dq Li YES . .It Va pfsync_syncpeer .Pq Vt str Empty by default. This variable is optional. By default, state change messages are sent out on the synchronisation interface using IP multicast packets. The protocol is IP protocol 240, PFSYNC, and the multicast group used is 224.0.0.240. When a peer address is specified using the .Va pfsync_syncpeer option, the peer address is used as a destination for the pfsync traffic, and the traffic can then be protected using .Xr ipsec 4 . See the .Xr pfsync 4 manpage for more details about using .Xr ipsec 4 with .Xr pfsync 4 interfaces. .It Va pfsync_ifconfig .Pq Vt str Empty by default. This variable can contain additional options to be passed to the .Xr ifconfig 8 command used to set up .Xr pfsync 4 . .It Va tcp_extensions .Pq Vt bool Set to .Dq Li YES by default. Setting this to .Dq Li NO disables certain TCP options as described by .Rs .%T "RFC 1323" .Re Setting this to .Dq Li NO might help remedy such problems with connections as randomly hanging or other weird behavior. Some network devices are known to be broken with respect to these options. .It Va log_in_vain .Pq Vt int Set to 0 by default. The .Xr sysctl 8 variables, .Va net.inet.tcp.log_in_vain and .Va net.inet.udp.log_in_vain , as described in .Xr tcp 4 and .Xr udp 4 , are set to the given value. .It Va tcp_keepalive .Pq Vt bool Set to .Dq Li YES by default. Setting to .Dq Li NO will disable probing idle TCP connections to verify that the peer is still up and reachable. .It Va tcp_drop_synfin .Pq Vt bool Set to .Dq Li NO by default. Setting to .Dq Li YES will cause the kernel to ignore TCP frames that have both the SYN and FIN flags set. This prevents OS fingerprinting, but may break some legitimate applications. .It Va icmp_drop_redirect .Pq Vt bool Set to .Dq Li NO by default. Setting to .Dq Li YES will cause the kernel to ignore ICMP REDIRECT packets. Refer to .Xr icmp 4 for more information. .It Va icmp_log_redirect .Pq Vt bool Set to .Dq Li NO by default. Setting to .Dq Li YES will cause the kernel to log ICMP REDIRECT packets. Note that the log messages are not rate-limited, so this option should only be used for troubleshooting networks. Refer to .Xr icmp 4 for more information. .It Va icmp_bmcastecho .Pq Vt bool Set to .Dq Li YES to respond to broadcast or multicast ICMP ping packets. Refer to .Xr icmp 4 for more information. .It Va ip_portrange_first .Pq Vt int If not set to .Dq Li NO , this is the first port in the default portrange. Refer to .Xr ip 4 for more information. .It Va ip_portrange_last .Pq Vt int If not set to .Dq Li NO , this is the last port in the default portrange. Refer to .Xr ip 4 for more information. .It Va network_interfaces .Pq Vt str Set to the list of network interfaces to configure on this host or .Dq Li AUTO (the default) for all current interfaces. Setting the .Va network_interfaces variable to anything other than the default is deprecated. Interfaces that the administrator wishes to store configuration for, but not start at boot should be configured with the .Dq Li NOAUTO keyword in their .Va ifconfig_ Ns Aq Ar interface variables as described below. .Pp An .Va ifconfig_ Ns Aq Ar interface variable is also assumed to exist for each value of .Ar interface . When an interface name contains any of the characters .Dq Li .-/+ they are translated to .Dq Li _ before lookup. The variable can contain arguments to .Xr ifconfig 8 , as well as special case-insensitive keywords described below. Such keywords are removed before passing the value to .Xr ifconfig 8 while the order of the other arguments is preserved. .Pp It is possible to add IP alias entries using .Xr ifconfig 8 syntax with the address family keyword such as .Li inet . Assuming that the interface in question was .Li ed0 , it might look something like this: .Bd -literal ifconfig_ed0_alias0="inet 127.0.0.253 netmask 0xffffffff" ifconfig_ed0_alias1="inet 127.0.0.254 netmask 0xffffffff" .Ed .Pp It also possible to configure multiple IP addresses in Classless Inter-Domain Routing .Pq CIDR address notation, whose each address component can be a range like .Li inet 192.0.2.5-23/24 or .Li inet6 2001:db8:1-f::1/64 . This notation allows address and prefix length part only, not the other address modifiers. Note that the maximum number of the generated addresses from a range specification is limited to an integer value specified in .Va netif_ipexpand_max in .Xr rc.conf 5 because a small typo can unexpectedly generate a large number of addresses. The default value is .Li 2048 . It can be increased by adding the following line into .Xr rc.conf 5 : .Bd -literal netif_ipexpand_max="4096" .Ed .Pp In the case of .Li 192.0.2.5-23/24 , the address 192.0.2.5 will be configured with the netmask /24 and the addresses 192.0.2.6 to 192.0.2.23 with the non-conflicting netmask /32 as explained in the .Xr ifconfig 8 alias section. Note that this special netmask handling is only for .Li inet , not for the other address families such as .Li inet6 . .Pp With the interface in question being .Li ed0 , an example could look like: .Bd -literal ifconfig_ed0_alias2="inet 192.0.2.129/27" ifconfig_ed0_alias3="inet 192.0.2.1-5/28" .Ed .Pp and so on. .Pp Note that .Va ipv4_addrs_ Ns Aq Ar interface variable was supported for IPv4 CIDR address notation. It is now deprecated because the functionality was integrated into .Va ifconfig_ Ns Ao Ar interface Ac Ns Va _alias Ns Aq Ar n though .Va ipv4_addrs_ Ns Aq Ar interface is still supported for backward compatibility. .Pp For each .Va ifconfig_ Ns Ao Ar interface Ac Ns Va _alias Ns Aq Ar n entry with an address family keyword, its contents are passed to .Xr ifconfig 8 . Execution stops at the first unsuccessful access, so if something like this is present: .Bd -literal ifconfig_ed0_alias0="inet 127.0.0.251 netmask 0xffffffff" ifconfig_ed0_alias1="inet 127.0.0.252 netmask 0xffffffff" ifconfig_ed0_alias2="inet 127.0.0.253 netmask 0xffffffff" ifconfig_ed0_alias4="inet 127.0.0.254 netmask 0xffffffff" .Ed .Pp Then note that alias4 would .Em not be added since the search would stop with the missing .Dq Li alias3 entry. Because of this difficult to manage behavior, there is .Va ifconfig_ Ns Ao Ar interface Ac Ns Va _aliases variable, which has the same functionality as .Va ifconfig_ Ns Ao Ar interface Ac Ns Va _alias Ns Aq Ar n and can have all of entries in a variable like the following: .Bd -literal ifconfig_ed0_aliases="\\ inet 127.0.0.251 netmask 0xffffffff \\ inet 127.0.0.252 netmask 0xffffffff \\ inet 127.0.0.253 netmask 0xffffffff \\ inet 127.0.0.254 netmask 0xffffffff" .Ed .Pp It also supports CIDR notation. .Pp If the .Pa /etc/start_if. Ns Aq Ar interface file is present, it is read and executed by the .Xr sh 1 interpreter before configuring the interface as specified in the .Va ifconfig_ Ns Aq Ar interface and .Va ifconfig_ Ns Ao Ar interface Ac Ns Va _alias Ns Aq Ar n variables. .Pp If a .Va vlans_ Ns Aq Ar interface variable is set, a .Xr vlan 4 interface will be created for each item in the list with the .Ar vlandev argument set to .Ar interface . If a vlan interface's name is a number, then that number is used as the vlan tag and the new vlan interface is named .Ar interface . Ns Ar tag . Otherwise, the vlan tag must be specified via a .Va vlan parameter in the .Va create_args_ Ns Aq Ar interface variable. .Pp To create a vlan device named .Li em0.101 on .Li em0 with the vlan tag 101 and the optional the IPv4 address 192.0.2.1/24: .Bd -literal vlans_em0="101" ifconfig_em0_101="inet 192.0.2.1/24" .Ed .Pp To create a vlan device named .Li myvlan on .Li em0 with the vlan tag 102: .Bd -literal vlans_em0="myvlan" create_args_myvlan="vlan 102" .Ed .Pp If a .Va wlans_ Ns Aq Ar interface variable is set, an .Xr wlan 4 interface will be created for each item in the list with the .Ar wlandev argument set to .Ar interface . Further wlan cloning arguments may be passed to the .Xr ifconfig 8 .Cm create command by setting the .Va create_args_ Ns Aq Ar interface variable. One or more .Xr wlan 4 devices must be created for each wireless devices as of .Fx 8.0 . Debugging flags for .Xr wlan 4 devices as set by .Xr wlandebug 8 may be specified with an .Va wlandebug_ Ns Aq Ar interface variable. The contents of this variable will be passed directly to .Xr wlandebug 8 . .Pp If the .Va ifconfig_ Ns Aq Ar interface contains the keyword .Dq Li NOAUTO then the interface will not be configured at boot or by .Pa /etc/pccard_ether when .Va network_interfaces is set to .Dq Li AUTO . .Pp It is possible to bring up an interface with DHCP by adding .Dq Li DHCP to the .Va ifconfig_ Ns Aq Ar interface variable. For instance, to initialize the .Li ed0 device via DHCP, it is possible to use something like: .Bd -literal ifconfig_ed0="DHCP" .Ed .Pp If you want to configure your wireless interface with .Xr wpa_supplicant 8 for use with WPA, EAP/LEAP or WEP, you need to add .Dq Li WPA to the .Va ifconfig_ Ns Aq Ar interface variable. .Pp On the other hand, if you want to configure your wireless interface with .Xr hostapd 8 , you need to add .Dq Li HOSTAP to the .Va ifconfig_ Ns Aq Ar interface variable. .Xr hostapd 8 will use the settings from .Pa /etc/hostapd- Ns Ao Ar interface Ac Ns .conf .Pp Finally, you can add .Xr ifconfig 8 options in this variable, in addition to the .Pa /etc/start_if. Ns Aq Ar interface file. For instance, to configure an .Xr ath 4 wireless device in station mode with an address obtained via DHCP, using WPA authentication and 802.11b mode, it is possible to use something like: .Bd -literal wlans_ath0="wlan0" ifconfig_wlan0="DHCP WPA mode 11b" .Ed .Pp In addition to the .Va ifconfig_ Ns Aq Ar interface form, a fallback variable .Va ifconfig_DEFAULT may be configured. It will be used for all interfaces with no .Va ifconfig_ Ns Aq Ar interface variable. This is intended to replace the no longer supported .Va pccard_ifconfig variable. .Pp It is also possible to rename an interface by doing: .Bd -literal ifconfig_ed0_name="net0" ifconfig_net0="inet 192.0.2.1 netmask 0xffffff00" .Ed .It Va ipv6_enable .Pq Vt bool This variable is deprecated. Use .Va ifconfig_ Ns Ao Ar interface Ac Ns _ipv6 and .Va ipv6_activate_all_interfaces if necessary. .Pp If the variable is .Dq Li YES , .Dq Li inet6 accept_rtadv is added to all of .Va ifconfig_ Ns Ao Ar interface Ac Ns _ipv6 and the .Va ipv6_activate_all_interfaces is defined as .Dq Li YES . .It Va ipv6_prefer .Pq Vt bool This variable is deprecated. Use .Va ip6addrctl_policy instead. .Pp If the variable is .Dq Li YES , the default address selection policy table set by .Xr ip6addrctl 8 will be IPv6-preferred. .Pp If the variable is .Dq Li NO , the default address selection policy table set by .Xr ip6addrctl 8 will be IPv4-preferred. .It Va ipv6_activate_all_interfaces .Pq Vt bool This controls initial configuration on IPv6-capable interfaces with no corresponding .Va ifconfig_ Ns Ao Ar interface Ac Ns _ipv6 variable. Note that it is not always necessary to set this variable to .Dq YES to use IPv6 functionality on .Fx . In most cases, just configuring .Va ifconfig_ Ns Ao Ar interface Ac Ns _ipv6 variables works. .Pp If the variable is .Dq Li NO , all interfaces which do not have a corresponding .Va ifconfig_ Ns Ao Ar interface Ac Ns _ipv6 variable will be marked as .Dq Li IFDISABLED at creation. This means that all of IPv6 functionality on that interface is completely disabled to enforce a security policy. If the variable is set to .Dq YES , the flag will be cleared on all of the interfaces. .Pp In most cases, just defining an .Va ifconfig_ Ns Ao Ar interface Ac Ns _ipv6 for an IPv6-capable interface should be sufficient. However, if an interface is added dynamically .Pq by some tunneling protocols such as PPP, for example , it is often difficult to define the variable in advance. In such a case, configuring the .Dq Li IFDISABLED flag can be disabled by setting this variable to .Dq YES . .Pp For more details of the .Dq Li IFDISABLED flag and keywords .Dq Li inet6 ifdisabled , see .Xr ifconfig 8 . .Pp Default is .Dq Li NO . .It Va ipv6_privacy .Pq Vt bool If the variable is .Dq Li YES privacy addresses will be generated for each IPv6 interface as described in RFC 4941. .It Va ipv6_network_interfaces .Pq Vt str This is the IPv6 equivalent of .Va network_interfaces . Normally manual configuration of this variable is not needed. .It Va ipv6_cpe_wanif .Pq Vt str If the variable is set to an interface name, the .Xr ifconfig 8 options .Dq inet6 -no_radr accept_rtadv will be added to the specified interface automatically before evaluating .Va ifconfig_ Ns Ao Ar interface Ac Ns _ipv6 , and two .Xr sysctl 8 variables .Va net.inet6.ip6.rfc6204w3 and .Va net.inet6.ip6.no_radr will be set to 1. .Pp This means the specified interface will accept ICMPv6 Router Advertisement messages on that link and add the discovered routers into the Default Router List. While the other interfaces can still accept RA messages if the .Dq inet6 accept_rtadv option is specified, adding routes into the Default Router List will be disabled by .Dq inet6 no_radr option by default. See .Xr ifconfig 8 for more details. .Pp Note that ICMPv6 Router Advertisement messages will be accepted even when .Va net.inet6.ip6.forwarding is 1 .Pq packet forwarding is enabled when .Va net.inet6.ip6.rfc6204w3 is set to 1. .Pp Default is .Dq Li NO . .It Va ifconfig_ Ns Ao Ar interface Ac Ns _ipv6 .Pq Vt str IPv6 functionality on an interface should be configured by .Va ifconfig_ Ns Ao Ar interface Ac Ns _ipv6 , instead of setting ifconfig parameters in .Va ifconfig_ Ns Aq Ar interface . If this variable is empty, all of IPv6 configurations on the specified interface by other variables such as .Va ipv6_prefix_ Ns Ao Ar interface Ac will be ignored. .Pp Aliases should be set by .Va ifconfig_ Ns Ao Ar interface Ac Ns Va _alias Ns Aq Ar n with .Dq Li inet6 keyword. For example: .Bd -literal ifconfig_ed0_ipv6="inet6 2001:db8:1::1 prefixlen 64" ifconfig_ed0_alias0="inet6 2001:db8:2::1 prefixlen 64" .Ed .Pp Interfaces that have an .Dq Li inet6 accept_rtadv keyword in .Va ifconfig_ Ns Ao Ar interface Ac Ns _ipv6 setting will be automatically configured by SLAAC .Pq StateLess Address AutoConfiguration described in .Rs .%T "RFC 4862" .Re .Pp Note that a link-local address will be automatically configured in addition to the configured global-scope addresses because the IPv6 specifications require it on each link. The address is calculated from the MAC address by using an algorithm defined in .Rs .%T "RFC 4862" .%O "Section 5.3" .Re .Pp If only a link-local address is needed on the interface, the following configuration can be used: .Bd -literal ifconfig_ed0_ipv6="inet6 auto_linklocal" .Ed .Pp A link-local address can also be configured manually. This is useful for the default router address of an IPv6 router so that it does not change when the network interface card is replaced. For example: .Bd -literal ifconfig_ed0_ipv6="inet6 fe80::1 prefixlen 64" .Ed .It Va ipv6_prefix_ Ns Aq Ar interface .Pq Vt str If one or more prefixes are defined in .Va ipv6_prefix_ Ns Aq Ar interface addresses based on each prefix and the EUI-64 interface index will be configured on that interface. Note that this variable will be ignored when .Va ifconfig_ Ns Ao Ar interface Ac Ns _ipv6 is empty. .Pp For example, the following configuration .Bd -literal ipv6_prefix_ed0="2001:db8:1:0 2001:db8:2:0" .Ed .Pp is equivalent to the following: .Bd -literal ifconfig_ed0_alias0="inet6 2001:db8:1:: eui64 prefixlen 64" ifconfig_ed0_alias1="inet6 2001:db8:1:: prefixlen 64 anycast" ifconfig_ed0_alias2="inet6 2001:db8:2:: eui64 prefixlen 64" ifconfig_ed0_alias3="inet6 2001:db8:2:: prefixlen 64 anycast" .Ed .Pp These Subnet-Router anycast addresses will be added only when .Va ipv6_gateway_enable is YES. .It Va ipv6_default_interface .Pq Vt str If not set to .Dq Li NO , this is the default output interface for scoped addresses. This works only with ipv6_gateway_enable="NO". .It Va ip6addrctl_enable .Pq Vt bool This variable is to enable configuring default address selection policy table .Pq RFC 3484 . The table can be specified in another variable .Va ip6addrctl_policy . For .Va ip6addrctl_policy the following keywords can be specified: .Dq Li ipv4_prefer , .Dq Li ipv6_prefer , or .Dq Li AUTO . .Pp If .Dq Li ipv4_prefer or .Dq Li ipv6_prefer is specified, .Xr ip6addrctl 8 installs a pre-defined policy table described in Section 2.1 .Pq IPv6-preferred or 10.3 .Pq IPv4-preferred of RFC 3484. .Pp If .Dq Li AUTO is specified, it attempts to read a file .Pa /etc/ip6addrctl.conf first. If this file is found, .Xr ip6addrctl 8 reads and installs it. If not found, a policy is automatically set according to .Va ipv6_activate_all_interfaces variable; if the variable is set to .Dq Li YES the IPv6-preferred one is used. Otherwise IPv4-preferred. .Pp The default value of .Va ip6addrctl_enable and .Va ip6addrctl_policy are .Dq Li YES and .Dq Li AUTO , respectively. .It Va cloned_interfaces .Pq Vt str Set to the list of clonable network interfaces to create on this host. Further cloning arguments may be passed to the .Xr ifconfig 8 .Cm create command for each interface by setting the .Va create_args_ Ns Aq Ar interface variable. If an interface name is specified with .Dq :sticky keyword, the interface will not be destroyed even when .Pa rc.d/netif script is invoked with .Dq stop argument. This is useful when reconfiguring the interface without destroying it. Entries in .Va cloned_interfaces are automatically appended to .Va network_interfaces for configuration. .It Va cloned_interfaces_sticky .Pq Vt bool This variable is to globally enable functionality of .Dq :sticky keyword in .Va cloned_interfaces for all interfaces. The default value is .Dq NO . Even if this variable is specified to .Dq YES , .Dq :nosticky keyword can be used to override it on per interface basis. .It Va gif_interfaces .Pq Vt str This variable is deprecated in favor of .Va cloned_interfaces . Set to the list of .Xr gif 4 tunnel interfaces to configure on this host. A .Va gifconfig_ Ns Aq Ar interface variable is assumed to exist for each value of .Ar interface . The value of this variable is used to configure the link layer of the tunnel according to the syntax of the .Cm tunnel option to .Xr ifconfig 8 . Additionally, this option ensures that each listed interface is created via the .Cm create option to .Xr ifconfig 8 before attempting to configure it. .It Va sppp_interfaces .Pq Vt str Set to the list of .Xr sppp 4 interfaces to configure on this host. A .Va spppconfig_ Ns Aq Ar interface variable is assumed to exist for each value of .Ar interface . Each interface should also be configured by a general .Va ifconfig_ Ns Aq Ar interface setting. Refer to .Xr spppcontrol 8 for more information about available options. .It Va ppp_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr ppp 8 daemon. .It Va ppp_profile .Pq Vt str The name of the profile to use from .Pa /etc/ppp/ppp.conf . Also used for per-profile overrides of .Va ppp_mode and .Va ppp_nat , and .Va ppp_ Ns Ao Ar profile Ac Ns _unit . When the profile name contains any of the characters .Dq Li .-/+ they are translated to .Dq Li _ for the proposes of the override variable names. .It Va ppp_mode .Pq Vt str Mode in which to run the .Xr ppp 8 daemon. .It Va ppp_ Ns Ao Ar profile Ac Ns _mode .Pq Vt str Overrides the global .Va ppp_mode for .Ar profile . Accepted modes are .Dq Li auto , .Dq Li ddial , .Dq Li direct and .Dq Li dedicated . See the manual for a full description. .It Va ppp_nat .Pq Vt bool If set to .Dq Li YES , enables network address translation. Used in conjunction with .Va gateway_enable allows hosts on private network addresses access to the Internet using this host as a network address translating router. .It Va ppp_ Ns Ao Ar profile Ac Ns _nat .Pq Vt str Overrides the global .Va ppp_nat for .Ar profile . .It Va ppp_ Ns Ao Ar profile Ac Ns _unit .Pq Vt int Set the unit number to be used for this profile. See the manual description of .Fl unit Ns Ar N for details. .It Va ppp_user .Pq Vt str The name of the user under which .Xr ppp 8 should be started. By default, .Xr ppp 8 is started as .Dq Li root . .It Va rc_conf_files .Pq Vt str This option is used to specify a list of files that will override the settings in .Pa /etc/defaults/rc.conf . The files will be read in the order in which they are specified and should include the full path to the file. By default, the files specified are .Pa /etc/rc.conf and .Pa /etc/rc.conf.local .It Va zfs_enable .Pq Vt bool If set to .Dq Li YES , .Pa /etc/rc.d/zfs will attempt to automatically mount ZFS file systems and initialize ZFS volumes (ZVOLs). .It Va gptboot_enable .Pq Vt bool If set to .Dq Li YES , .Pa /etc/rc.d/gptboot will log if the system successfully (or not) booted from a GPT partition, which had the .Ar bootonce attribute set using .Xr gpart 8 utility. .It Va gbde_autoattach_all .Pq Vt bool If set to .Dq Li YES , .Pa /etc/rc.d/gbde will attempt to automatically initialize your .bde devices in .Pa /etc/fstab . .It Va gbde_devices .Pq Vt str List the devices that the script should try to attach, or .Dq Li AUTO . .It Va gbde_lockdir .Pq Vt str The directory where the .Xr gbde 4 lockfiles are located. The default lockfile directory is .Pa /etc . .Pp The lockfile for each individual .Xr gbde 4 device can be overridden by setting the variable .Va gbde_lock_ Ns Aq Ar device , where .Ar device is the encrypted device without the .Dq Pa /dev/ and .Dq Pa .bde parts. .It Va gbde_attach_attempts .Pq Vt int Number of times to attempt attaching to a .Xr gbde 4 device, i.e., how many times the user is asked for the pass-phrase. Default is 3. .It Va geli_devices .Pq Vt str List of devices to automatically attach on boot. Note that .eli devices from .Pa /etc/fstab are automatically appended to this list. .It Va geli_tries .Pq Vt int Number of times user is asked for the pass-phrase. If empty, it will be taken from .Va kern.geom.eli.tries sysctl variable. .It Va geli_default_flags .Pq Vt str Default flags to use by .Xr geli 8 when configuring disk encryption. Flags can be configured for every device separately by defining .Va geli_ Ns Ao Ar device Ac Ns Va _flags variable. .It Va geli_autodetach .Pq Vt str Specifies if GELI devices should be marked for detach on last close after file systems are mounted. Default is .Dq Li YES . This can be changed for every device separately by defining .Va geli_ Ns Ao Ar device Ac Ns Va _autodetach variable. .It Va root_rw_mount .Pq Vt bool Set to .Dq Li YES by default. After the file systems are checked at boot time, the root file system is remounted as read-write if this is set to .Dq Li YES . Diskless systems that mount their root file system from a read-only remote NFS share should set this to .Dq Li NO in their .Pa rc.conf . .It Va fsck_y_enable .Pq Vt bool If set to .Dq Li YES , .Xr fsck 8 will be run with the .Fl y flag if the initial preen of the file systems fails. .It Va background_fsck .Pq Vt bool If set to .Dq Li YES , the system will attempt to run .Xr fsck 8 in the background where possible. .It Va background_fsck_delay .Pq Vt int The amount of time in seconds to sleep before starting a background .Xr fsck 8 . It defaults to sixty seconds to allow large applications such as the X server to start before disk I/O bandwidth is monopolized by .Xr fsck 8 . If set to a negative number, the background file system check will be delayed indefinitely to allow the administrator to run it at a more convenient time. For example it may be run from .Xr cron 8 by adding a line like .Pp .Dl "0 4 * * * root /etc/rc.d/bgfsck forcestart" .Pp to .Pa /etc/crontab . .It Va netfs_types .Pq Vt str List of file system types that are network-based. This list should generally not be modified by end users. Use .Va extra_netfs_types instead. .It Va extra_netfs_types .Pq Vt str If set to something other than .Dq Li NO (the default), this variable extends the list of file system types for which automatic mounting at startup by .Xr rc 8 should be delayed until the network is initialized. It should contain a whitespace-separated list of network file system descriptor pairs, each consisting of a file system type as passed to .Xr mount 8 and a human-readable, one-word description, joined with a colon .Pq Ql \&: . Extending the default list in this way is only necessary when third party file system types are used. .It Va syslogd_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr syslogd 8 daemon. .It Va syslogd_program .Pq Vt str Path to .Xr syslogd 8 (default .Pa /usr/sbin/syslogd ) . .It Va syslogd_flags .Pq Vt str If .Va syslogd_enable is set to .Dq Li YES , these are the flags to pass to .Xr syslogd 8 . .It Va inetd_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr inetd 8 daemon. .It Va inetd_program .Pq Vt str Path to .Xr inetd 8 (default .Pa /usr/sbin/inetd ) . .It Va inetd_flags .Pq Vt str If .Va inetd_enable is set to .Dq Li YES , these are the flags to pass to .Xr inetd 8 . .It Va hastd_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr hastd 8 daemon. .It Va hastd_program .Pq Vt str Path to .Xr hastd 8 (default .Pa /sbin/hastd ) . .It Va hastd_flags .Pq Vt str If .Va hastd_enable is set to .Dq Li YES , these are the flags to pass to .Xr hastd 8 . .It Va local_unbound_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr unbound 8 daemon as a local caching resolver. .It Va kerberos5_server_enable .Pq Vt bool Set to .Dq Li YES to start a Kerberos 5 authentication server at boot time. .It Va kerberos5_server .Pq Vt str If .Va kerberos5_server_enable is set to .Dq Li YES this is the path to Kerberos 5 Authentication Server. .It Va kerberos5_server_flags .Pq Vt str Empty by default. This variable contains additional flags to be passed to the Kerberos 5 authentication server. .It Va kadmind5_server_enable .Pq Vt bool Set to .Dq Li YES to start .Xr kadmind 8 , the Kerberos 5 Administration Daemon; set to .Dq Li NO on a slave server. .It Va kadmind5_server .Pq Vt str If .Va kadmind5_server_enable is set to .Dq Li YES this is the path to Kerberos 5 Administration Daemon. .It Va kpasswdd_server_enable .Pq Vt bool Set to .Dq Li YES to start .Xr kpasswdd 8 , the Kerberos 5 Password-Changing Daemon; set to .Dq Li NO on a slave server. .It Va kpasswdd_server .Pq Vt str If .Va kpasswdd_server_enable is set to .Dq Li YES this is the path to Kerberos 5 Password-Changing Daemon. .It Va kfd_enable .Pq Vt bool Set to .Dq Li YES to start .Xr kfd 8 , the Kerberos 5 ticket forwarding daemon, at the boot time. .It Va kfd_program .Pq Vt str Path to .Xr kfd 8 (default .Pa /usr/libexec/kfd ) . .It Va rwhod_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr rwhod 8 daemon at boot time. .It Va rwhod_flags .Pq Vt str If .Va rwhod_enable is set to .Dq Li YES , these are the flags to pass to it. .It Va amd_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr amd 8 daemon at boot time. .It Va amd_flags .Pq Vt str If .Va amd_enable is set to .Dq Li YES , these are the flags to pass to it. See the .Xr amd 8 manpage for more information. .It Va amd_map_program .Pq Vt str If set, the specified program is run to get the list of .Xr amd 8 maps. For example, if the .Xr amd 8 maps are stored in NIS, one can set this to run .Xr ypcat 1 to get a list of .Xr amd 8 maps from the .Pa amd.master NIS map. .It Va update_motd .Pq Vt bool If set to .Dq Li YES , .Pa /etc/motd will be updated at boot time to reflect the kernel release being run. If set to .Dq Li NO , .Pa /etc/motd will not be updated. .It Va nfs_client_enable .Pq Vt bool If set to .Dq Li YES , run the NFS client daemons at boot time. .It Va nfs_access_cache .Pq Vt int If .Va nfs_client_enable is set to .Dq Li YES , this can be set to .Dq Li 0 to disable NFS ACCESS RPC caching, or to the number of seconds for which NFS ACCESS results should be cached. A value of 2-10 seconds will substantially reduce network traffic for many NFS operations. .It Va nfs_server_enable .Pq Vt bool If set to .Dq Li YES , run the NFS server daemons at boot time. .It Va nfs_server_flags .Pq Vt str If .Va nfs_server_enable is set to .Dq Li YES , these are the flags to pass to the .Xr nfsd 8 daemon. .It Va nfsv4_server_enable .Pq Vt bool If .Va nfs_server_enable is set to .Dq Li YES and .Va nfsv4_server_enable are set to .Dq Li YES , enable the server for NFSv4 as well as NFSv2 and NFSv3. .It Va nfsuserd_enable .Pq Vt bool If .Va nfsuserd_enable is set to .Dq Li YES , run the nfsuserd daemon, which is needed for NFSv4 in order to map between user/group names vs uid/gid numbers. If .Va nfsv4_server_enable is set to .Dq Li YES , this will be forced enabled. .It Va nfsuserd_flags .Pq Vt str If .Va nfsuserd_enable is set to .Dq Li YES , these are the flags to pass to the .Xr nfsuserd 8 daemon. .It Va nfscbd_enable .Pq Vt bool If .Va nfscbd_enable is set to .Dq Li YES , run the nfscbd daemon, which enables callbacks/delegations for the NFSv4 client. .It Va nfscbd_flags .Pq Vt str If .Va nfscbd_enable is set to .Dq Li YES , these are the flags to pass to the .Xr nfscbd 8 daemon. .It Va oldnfs_server_enable .Pq Vt bool If .Va oldnfs_server_enable is set to .Dq Li YES , force the NFS server daemons to run the old NFS server code that does not support NFSv4. .It Va mountd_enable .Pq Vt bool If set to .Dq Li YES , and no .Va nfs_server_enable is set, start .Xr mountd 8 , but not .Xr nfsd 8 daemon. It is commonly needed to run CFS without real NFS used. .It Va mountd_flags .Pq Vt str If .Va mountd_enable is set to .Dq Li YES , these are the flags to pass to the .Xr mountd 8 daemon. .It Va weak_mountd_authentication .Pq Vt bool If set to .Dq Li YES , allow services like PCNFSD to make non-privileged mount requests. .It Va nfs_reserved_port_only .Pq Vt bool If set to .Dq Li YES , provide NFS services only on a secure port. .It Va nfs_bufpackets .Pq Vt int If set to a number, indicates the number of packets worth of socket buffer space to reserve on an NFS client. The kernel default is typically 4. Using a higher number may be useful on gigabit networks to improve performance. The minimum value is 2 and the maximum is 64. .It Va rpc_lockd_enable .Pq Vt bool If set to .Dq Li YES and also an NFS server or client, run .Xr rpc.lockd 8 at boot time. .It Va rpc_lockd_flags .Pq Vt str If .Va rpc_lockd_enable is set to .Dq Li YES , these are the flags to pass to the .Xr rpc.lockd 8 daemon. .It Va rpc_statd_enable .Pq Vt bool If set to .Dq Li YES and also an NFS server or client, run .Xr rpc.statd 8 at boot time. .It Va rpc_statd_flags .Pq Vt str If .Va rpc_statd_enable is set to .Dq Li YES , these are the flags to pass to the .Xr rpc.statd 8 daemon. .It Va rpcbind_program .Pq Vt str Path to .Xr rpcbind 8 (default .Pa /usr/sbin/rpcbind ) . .It Va rpcbind_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr rpcbind 8 service at boot time. .It Va rpcbind_flags .Pq Vt str If .Va rpcbind_enable is set to .Dq Li YES , these are the flags to pass to the .Xr rpcbind 8 daemon. .It Va keyserv_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr keyserv 8 daemon on boot for running Secure RPC. .It Va keyserv_flags .Pq Vt str If .Va keyserv_enable is set to .Dq Li YES , these are the flags to pass to .Xr keyserv 8 daemon. .It Va pppoed_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr pppoed 8 daemon at boot time to provide PPP over Ethernet services. .It Va pppoed_ Ns Aq Ar provider .Pq Vt str .Xr pppoed 8 listens to requests to this .Ar provider and ultimately runs .Xr ppp 8 with a .Ar system argument of the same name. .It Va pppoed_flags .Pq Vt str Additional flags to pass to .Xr pppoed 8 . .It Va pppoed_interface .Pq Vt str The network interface to run .Xr pppoed 8 on. This is mandatory when .Va pppoed_enable is set to .Dq Li YES . .It Va timed_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr timed 8 service at boot time. This command is intended for networks of machines where a consistent .Dq "network time" for all hosts must be established. This is often useful in large NFS environments where time stamps on files are expected to be consistent network-wide. .It Va timed_flags .Pq Vt str If .Va timed_enable is set to .Dq Li YES , these are the flags to pass to the .Xr timed 8 service. .It Va ntpdate_enable .Pq Vt bool If set to .Dq Li YES , run .Xr ntpdate 8 at system startup. This command is intended to synchronize the system clock only .Em once from some standard reference. .It Va ntpdate_config .Pq Vt str Configuration file for .Xr ntpdate 8 . Default .Pa /etc/ntp.conf . .It Va ntpdate_hosts .Pq Vt str A whitespace-separated list of NTP servers to synchronize with at startup. The default is to use the servers listed in .Va ntpdate_config , if that file exists. .It Va ntpdate_program .Pq Vt str Path to .Xr ntpdate 8 (default .Pa /usr/sbin/ntpdate ) . .It Va ntpdate_flags .Pq Vt str If .Va ntpdate_enable is set to .Dq Li YES , these are the flags to pass to the .Xr ntpdate 8 command (typically a hostname). .It Va ntpd_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr ntpd 8 command at boot time. .It Va ntpd_program .Pq Vt str Path to .Xr ntpd 8 (default .Pa /usr/sbin/ntpd ) . .It Va ntpd_config .Pq Vt str Path to .Xr ntpd 8 configuration file. Default .Pa /etc/ntp.conf . .It Va ntpd_flags .Pq Vt str If .Va ntpd_enable is set to .Dq Li YES , these are the flags to pass to the .Xr ntpd 8 daemon. .It Va ntpd_sync_on_start .Pq Vt bool If set to .Dq Li YES , .Xr ntpd 8 is run with the .Fl g flag, which syncs the system's clock on startup. See .Xr ntpd 8 for more information regarding the .Fl g option. This is a preferred alternative to using .Xr ntpdate 8 or specifying the .Va ntpdate_enable variable. .It Va nis_client_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr ypbind 8 service at system boot time. .It Va nis_client_flags .Pq Vt str If .Va nis_client_enable is set to .Dq Li YES , these are the flags to pass to the .Xr ypbind 8 service. .It Va nis_ypset_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr ypset 8 daemon at system boot time. .It Va nis_ypset_flags .Pq Vt str If .Va nis_ypset_enable is set to .Dq Li YES , these are the flags to pass to the .Xr ypset 8 daemon. .It Va nis_server_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr ypserv 8 daemon at system boot time. .It Va nis_server_flags .Pq Vt str If .Va nis_server_enable is set to .Dq Li YES , these are the flags to pass to the .Xr ypserv 8 daemon. .It Va nis_ypxfrd_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr rpc.ypxfrd 8 daemon at system boot time. .It Va nis_ypxfrd_flags .Pq Vt str If .Va nis_ypxfrd_enable is set to .Dq Li YES , these are the flags to pass to the .Xr rpc.ypxfrd 8 daemon. .It Va nis_yppasswdd_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr rpc.yppasswdd 8 daemon at system boot time. .It Va nis_yppasswdd_flags .Pq Vt str If .Va nis_yppasswdd_enable is set to .Dq Li YES , these are the flags to pass to the .Xr rpc.yppasswdd 8 daemon. .It Va rpc_ypupdated_enable .Pq Vt bool If set to .Dq Li YES , run the .Nm rpc.ypupdated daemon at system boot time. .It Va bsnmpd_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr bsnmpd 1 daemon at system boot time. Be sure to understand the security implications of running SNMP daemon on your host. .It Va bsnmpd_flags .Pq Vt str If .Va bsnmpd_enable is set to .Dq Li YES , these are the flags to pass to the .Xr bsnmpd 1 daemon. .It Va defaultrouter .Pq Vt str If not set to .Dq Li NO , create a default route to this host name or IP address (use an IP address if this router is also required to get to the name server!). .It Va ipv6_defaultrouter .Pq Vt str The IPv6 equivalent of .Va defaultrouter . .It Va static_arp_pairs .Pq Vt str Set to the list of static ARP pairs that are to be added at system boot time. For each whitespace separated .Ar element in the value, a .Va static_arp_ Ns Aq Ar element variable is assumed to exist whose contents will later be passed to a .Dq Nm arp Cm -S operation. For example .Bd -literal static_arp_pairs="gw" static_arp_gw="192.168.1.1 00:01:02:03:04:05" .Ed .It Va static_ndp_pairs .Pq Vt str Set to the list of static NDP pairs that are to be added at system boot time. For each whitespace separated .Ar element in the value, a .Va static_ndp_ Ns Aq Ar element variable is assumed to exist whose contents will later be passed to a .Dq Nm ndp Cm -s operation. For example .Bd -literal static_ndp_pairs="gw" static_ndp_gw="2001:db8:3::1 00:01:02:03:04:05" .Ed .It Va static_routes .Pq Vt str Set to the list of static routes that are to be added at system boot time. If not set to .Dq Li NO then for each whitespace separated .Ar element in the value, a .Va route_ Ns Aq Ar element variable is assumed to exist whose contents will later be passed to a .Dq Nm route Cm add operation. For example: .Bd -literal static_routes="ext mcast:gif0 gif0local:gif0" route_ext="-net 10.0.0.0/24 -gateway 192.168.0.1" route_mcast="-net 224.0.0.0/4 -iface gif0" route_gif0local="-host 169.254.1.1 -iface lo0" .Ed .Pp When an .Ar element is in the form of .Li name:ifname , the route is specific to the interface .Li ifname . .It Va ipv6_static_routes .Pq Vt str The IPv6 equivalent of .Va static_routes . If not set to .Dq Li NO then for each whitespace separated .Ar element in the value, a .Va ipv6_route_ Ns Aq Ar element variable is assumed to exist whose contents will later be passed to a .Dq Nm route Cm add Fl inet6 operation. .It Va natm_static_routes .Pq Vt str The .Xr natmip 4 equivalent of .Va static_routes . If not empty then for each whitespace separated .Ar element in the value, a .Va route_ Ns Aq Ar element variable is assumed to exist whose contents will later be passed to a .Dq Nm atmconfig Cm natm Cm add operation. .It Va gateway_enable .Pq Vt bool If set to .Dq Li YES , configure host to act as an IP router, e.g.\& to forward packets between interfaces. .It Va ipv6_gateway_enable .Pq Vt bool The IPv6 equivalent of .Va gateway_enable . .It Va routed_enable .Pq Vt bool If set to .Dq Li YES , run a routing daemon of some sort, based on the settings of .Va routed_program and .Va routed_flags . .It Va route6d_enable .Pq Vt bool The IPv6 equivalent of .Va routed_enable . If set to .Dq Li YES , run a routing daemon of some sort, based on the settings of .Va route6d_program and .Va route6d_flags . .It Va routed_program .Pq Vt str If .Va routed_enable is set to .Dq Li YES , this is the name of the routing daemon to use. .It Va route6d_program .Pq Vt str The IPv6 equivalent of .Va routed_program . .It Va routed_flags .Pq Vt str If .Va routed_enable is set to .Dq Li YES , these are the flags to pass to the routing daemon. .It Va route6d_flags .Pq Vt str The IPv6 equivalent of .Va routed_flags . .It Va mrouted_enable .Pq Vt bool If set to .Dq Li YES , run the multicast routing daemon, .Xr mrouted 8 . .It Va mroute6d_enable .Pq Vt bool The IPv6 equivalent of .Va mrouted_enable . If set to .Dq Li YES , run the IPv6 multicast routing daemon. .Pp Note that multicast routing daemons are no longer included in the .Fx base system, however, both .Xr mrouted 8 and .Xr pim6dd 8 may be installed from the .Fx Ports Collection. .It Va mrouted_flags .Pq Vt str If .Va mrouted_enable is set to .Dq Li YES , these are the flags to pass to the .Xr mrouted 8 daemon. .It Va mroute6d_flags .Pq Vt str The IPv6 equivalent of .Va mrouted_flags . If .Va mroute6d_enable is set to .Dq Li YES , these are the flags passed to the IPv6 multicast routing daemon. .It Va mroute6d_program .Pq Vt str If .Va mroute6d_enable is set to .Dq Li YES , this is the path to the IPv6 multicast routing daemon. .It Va rtadvd_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr rtadvd 8 daemon at boot time. The .Xr rtadvd 8 utility sends ICMPv6 Router Advertisement messages to the interfaces specified in .Va rtadvd_interfaces . This should only be enabled with great care. You may want to fine-tune .Xr rtadvd.conf 5 . .It Va rtadvd_interfaces .Pq Vt str If .Va rtadvd_enable is set to .Dq Li YES this is the list of interfaces to use. .It Va arpproxy_all .Pq Vt bool If set to .Dq Li YES , enable global proxy ARP. .It Va forward_sourceroute .Pq Vt bool If set to .Dq Li YES and .Va gateway_enable is also set to .Dq Li YES , source-routed packets are forwarded. .It Va accept_sourceroute .Pq Vt bool If set to .Dq Li YES , the system will accept source-routed packets directed at it. .It Va rarpd_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr rarpd 8 daemon at system boot time. .It Va rarpd_flags .Pq Vt str If .Va rarpd_enable is set to .Dq Li YES , these are the flags to pass to the .Xr rarpd 8 daemon. .It Va bootparamd_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr bootparamd 8 daemon at system boot time. .It Va bootparamd_flags .Pq Vt str If .Va bootparamd_enable is set to .Dq Li YES , these are the flags to pass to the .Xr bootparamd 8 daemon. .It Va stf_interface_ipv4addr .Pq Vt str If not set to .Dq Li NO , this is the local IPv4 address for 6to4 (IPv6 over IPv4 tunneling interface). Specify this entry to enable the 6to4 interface. .It Va stf_interface_ipv4plen .Pq Vt int Prefix length for 6to4 IPv4 addresses, to limit peer address range. An effective value is 0-31. .It Va stf_interface_ipv6_ifid .Pq Vt str IPv6 interface ID for .Xr stf 4 . This can be set to .Dq Li AUTO . .It Va stf_interface_ipv6_slaid .Pq Vt str IPv6 Site Level Aggregator for .Xr stf 4 . .It Va ipv6_ipv4mapping .Pq Vt bool If set to .Dq Li YES this enables IPv4 mapped IPv6 address communication (like .Li ::ffff:a.b.c.d ) . .It Va rtsold_enable .Pq Vt bool Set to .Dq Li YES to enable the .Xr rtsold 8 daemon to send ICMPv6 Router Solicitation messages. .It Va rtsold_flags .Pq Vt str If .Va rtsold_enable is set to .Dq Li YES , these are the flags to pass to .Xr rtsold 8 . .It Va rtsol_flags .Pq Vt str For interfaces configured with the .Dq Li inet6 accept_rtadv keyword, these are the flags to pass to .Xr rtsol 8 . .Pp Note that .Va rtsold_enable is mutually exclusive to .Va rtsol_flags ; .Va rtsold_enable takes precedence. .It Va atm_enable .Pq Vt bool Set to .Dq Li YES to enable the configuration of ATM interfaces at system boot time. For all of the ATM variables described below, please refer to the .Xr atm 8 manual page for further details on the available command parameters. Also refer to the files in .Pa /usr/share/examples/atm for more detailed configuration information. .It Va atm_load .Pq Vt str This is a list of physical ATM interface drivers to load. Typical values are .Dq Li hfa_pci and/or .Dq Li hea_pci . .It Va atm_netif_ Ns Aq Ar intf .Pq Vt str For the ATM physical interface .Ar intf , this variable defines the name prefix and count for the ATM network interfaces to be created. The value will be passed as the parameters of an .Dq Nm atm Cm "set netif" Ar intf command. .It Va atm_sigmgr_ Ns Aq Ar intf .Pq Vt str For the ATM physical interface .Ar intf , this variable defines the ATM signalling manager to be used. The value will be passed as the parameters of an .Dq Nm atm Cm attach Ar intf command. .It Va atm_prefix_ Ns Aq Ar intf .Pq Vt str For the ATM physical interface .Ar intf , this variable defines the NSAP prefix for interfaces using a UNI signalling manager. If set to .Dq Li ILMI , the prefix will automatically be set via the .Xr ilmid 8 daemon. Otherwise, the value will be passed as the parameters of an .Dq Nm atm Cm "set prefix" Ar intf command. .It Va atm_macaddr_ Ns Aq Ar intf .Pq Vt str For the ATM physical interface .Ar intf , this variable defines the MAC address for interfaces using a UNI signalling manager. If set to .Dq Li NO , the hardware MAC address contained in the ATM interface card will be used. Otherwise, the value will be passed as the parameters of an .Dq Nm atm Cm "set mac" Ar intf command. .It Va atm_arpserver_ Ns Aq Ar netif .Pq Vt str For the ATM network interface .Ar netif , this variable defines the ATM address for a host which is to provide ATMARP service. This variable is only applicable to interfaces using a UNI signalling manager. If set to .Dq Li local , this host will become an ATMARP server. The value will be passed as the parameters of an .Dq Nm atm Cm "set arpserver" Ar netif command. .It Va atm_scsparp_ Ns Aq Ar netif .Pq Vt bool If set to .Dq Li YES , SCSP/ATMARP service for the network interface .Ar netif will be initiated using the .Xr scspd 8 and .Xr atmarpd 8 daemons. This variable is only applicable if .Va atm_arpserver_ Ns Aq Ar netif is set to .Dq Li local . .It Va atm_pvcs .Pq Vt str Set to the list of ATM PVCs to be added at system boot time. For each whitespace separated .Ar element in the value, an .Va atm_pvc_ Ns Aq Ar element variable is assumed to exist. The value of each of these variables will be passed as the parameters of an .Dq Nm atm Cm "add pvc" command. .It Va atm_arps .Pq Vt str Set to the list of permanent ATM ARP entries to be added at system boot time. For each whitespace separated .Ar element in the value, an .Va atm_arp_ Ns Aq Ar element variable is assumed to exist. The value of each of these variables will be passed as the parameters of an .Dq Nm atm Cm "add arp" command. .It Va natm_interfaces .Pq Vt str Set to the list of .Xr natm 4 interfaces that will also be used for HARP through .Xr harp 4 . If this list is not empty all interfaces in the list will be brought up with .Xr ifconfig 8 and .Xr harp 4 will be loaded. For this to work the interface drivers must be either compiled into the kernel or must reside on the root partition. .It Va keybell .Pq Vt str The keyboard bell sound. Set to .Dq Li normal , .Dq Li visual , .Dq Li off , or .Dq Li NO if the default behavior is desired. For details, refer to the .Xr kbdcontrol 1 manpage. .It Va keyboard .Pq Vt str If set to a non-null string, the virtual console's keyboard input is set to this device. .It Va keymap .Pq Vt str If set to .Dq Li NO , no keymap is installed, otherwise the value is used to install the keymap file found in .Pa /usr/share/syscons/keymaps/ Ns Ao Ar value Ac Ns Pa .kbd (if using .Xr syscons 4 ) or .Pa /usr/share/vt/keymaps/ Ns Ao Ar value Ac Ns Pa .kbd (if using .Xr vt 4 ) . .It Va keyrate .Pq Vt str The keyboard repeat speed. Set to .Dq Li slow , .Dq Li normal , .Dq Li fast , or .Dq Li NO if the default behavior is desired. .It Va keychange .Pq Vt str If not set to .Dq Li NO , attempt to program the function keys with the value. The value should be a single string of the form: .Dq Ar funkey_number new_value Op Ar funkey_number new_value ... . .It Va cursor .Pq Vt str Can be set to the value of .Dq Li normal , .Dq Li blink , .Dq Li destructive , or .Dq Li NO to set the cursor behavior explicitly or choose the default behavior. .It Va scrnmap .Pq Vt str If set to .Dq Li NO , no screen map is installed, otherwise the value is used to install the screen map file in .Pa /usr/share/syscons/scrnmaps/ Ns Aq Ar value . This parameter is ignored when using .Xr vt 4 as the console driver. .It Va font8x16 .Pq Vt str If set to .Dq Li NO , the default 8x16 font value is used for screen size requests, otherwise the value in .Pa /usr/share/syscons/fonts/ Ns Aq Ar value or .Pa /usr/share/vt/fonts/ Ns Aq Ar value is used (depending on the console driver being used). .It Va font8x14 .Pq Vt str If set to .Dq Li NO , the default 8x14 font value is used for screen size requests, otherwise the value in .Pa /usr/share/syscons/fonts/ Ns Aq Ar value or .Pa /usr/share/vt/fonts/ Ns Aq Ar value is used (depending on the console driver being used). .It Va font8x8 .Pq Vt str If set to .Dq Li NO , the default 8x8 font value is used for screen size requests, otherwise the value in .Pa /usr/share/syscons/fonts/ Ns Aq Ar value or .Pa /usr/share/vt/fonts/ Ns Aq Ar value is used (depending on the console driver being used). .It Va blanktime .Pq Vt int If set to .Dq Li NO , the default screen blanking interval is used, otherwise it is set to .Ar value seconds. .It Va saver .Pq Vt str If not set to .Dq Li NO , this is the actual screen saver to use .Li ( blank , snake , daemon , etc). .It Va moused_nondefault_enable .Pq Vt str If set to .Dq Li NO , the mouse device specified on the command line is not automatically treated as enabled by the .Pa /etc/rc.d/moused script. Having this variable set to .Dq Li YES allows a .Xr usb 4 mouse, for example, to be enabled as soon as it is plugged in. .It Va moused_enable .Pq Vt str If set to .Dq Li YES , the .Xr moused 8 daemon is started for doing cut/paste selection on the console. .It Va moused_type .Pq Vt str This is the protocol type of the mouse connected to this host. This variable must be set if .Va moused_enable is set to .Dq Li YES . The .Xr moused 8 daemon is able to detect the appropriate mouse type automatically in many cases. Set this variable to .Dq Li auto to let the daemon detect it, or select one from the following list if the automatic detection fails. .Pp If the mouse is attached to the PS/2 mouse port, choose .Dq Li auto or .Dq Li ps/2 , regardless of the brand and model of the mouse. Likewise, if the mouse is attached to the bus mouse port, choose .Dq Li auto or .Dq Li busmouse . All other protocols are for serial mice and will not work with the PS/2 and bus mice. If this is a USB mouse, .Dq Li auto is the only protocol type which will work. .Pp .Bl -tag -width ".Li x10mouseremote" -compact .It Li microsoft Microsoft mouse (serial) .It Li intellimouse Microsoft IntelliMouse (serial) .It Li mousesystems Mouse systems Corp.\& mouse (serial) .It Li mmseries MM Series mouse (serial) .It Li logitech Logitech mouse (serial) .It Li busmouse A bus mouse .It Li mouseman Logitech MouseMan and TrackMan (serial) .It Li glidepoint ALPS GlidePoint (serial) .It Li thinkingmouse Kensington ThinkingMouse (serial) .It Li ps/2 PS/2 mouse .It Li mmhittab MM HitTablet (serial) .It Li x10mouseremote X10 MouseRemote (serial) .It Li versapad Interlink VersaPad (serial) .El .Pp Even if the mouse is not in the above list, it may be compatible with one in the list. Refer to the manual page for .Xr moused 8 for compatibility information. .Pp It should also be noted that while this is enabled, any other client of the mouse (such as an X server) should access the mouse through the virtual mouse device, .Pa /dev/sysmouse , and configure it as a .Dq Li sysmouse type mouse, since all mouse data is converted to this single canonical format when using .Xr moused 8 . If the client program does not support the .Dq Li sysmouse type, specify the .Dq Li mousesystems type. It is the second preferred type. .It Va moused_port .Pq Vt str If .Va moused_enable is set to .Dq Li YES , this is the actual port the mouse is on. It might be .Pa /dev/cuau0 for a COM1 serial mouse, .Pa /dev/psm0 for a PS/2 mouse or .Pa /dev/mse0 for a bus mouse, for example. .It Va moused_flags .Pq Vt str If .Va moused_flags is set, its value is used as an additional set of flags to pass to the .Xr moused 8 daemon. .It Va "moused_" Ns Ar XXX Ns Va "_flags" When .Va moused_nondefault_enable is enabled, and a .Xr moused 8 daemon is started for a non-default port, the .Va "moused_" Ns Ar XXX Ns Va "_flags" set of options has precedence over and replaces the default .Va moused_flags (where .Ar XXX is the name of the non-default port, i.e.,\& .Ar ums0 ) . By setting .Va "moused_" Ns Ar XXX Ns Va "_flags" it is possible to set up a different set of default flags for each .Xr moused 8 instance. For example, you can use .Dq Li "-3" for the default .Va moused_flags to make your laptop's touchpad more comfortable to use, but an empty set of options for .Va moused_ums0_flags when your .Xr usb 4 mouse has three or more buttons. .It Va mousechar_start .Pq Vt int If set to .Dq Li NO , the default mouse cursor character range .Li 0xd0 Ns - Ns Li 0xd3 is used, otherwise the range start is set to .Ar value character, see .Xr vidcontrol 1 . Use if the default range is occupied in the language code table. .It Va allscreens_flags .Pq Vt str If set, .Xr vidcontrol 1 is run with these options for each of the virtual terminals .Pq Pa /dev/ttyv* . For example, .Dq Fl m Cm on will enable the mouse pointer on all virtual terminals if .Va moused_enable is set to .Dq Li YES . .It Va allscreens_kbdflags .Pq Vt str If set, .Xr kbdcontrol 1 is run with these options for each of the virtual terminals .Pq Pa /dev/ttyv* . For example, .Dq Fl h Li 200 will set the .Xr syscons 4 or .Xr vt 4 scrollback (history) buffer to 200 lines. .It Va cron_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr cron 8 daemon at system boot time. .It Va cron_program .Pq Vt str Path to .Xr cron 8 (default .Pa /usr/sbin/cron ) . .It Va cron_flags .Pq Vt str If .Va cron_enable is set to .Dq Li YES , these are the flags to pass to .Xr cron 8 . .It Va cron_dst .Pq Vt bool If set to .Dq Li YES , enable the special handling of transitions to and from the Daylight Saving Time in .Xr cron 8 (equivalent to using the flag .Fl s ) . .It Va lpd_program .Pq Vt str Path to .Xr lpd 8 (default .Pa /usr/sbin/lpd ) . .It Va lpd_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr lpd 8 daemon at system boot time. .It Va lpd_flags .Pq Vt str If .Va lpd_enable is set to .Dq Li YES , these are the flags to pass to the .Xr lpd 8 daemon. .It Va chkprintcap_enable .Pq Vt bool If set to .Dq Li YES , run the .Xr chkprintcap 8 command before starting the .Xr lpd 8 daemon. .It Va chkprintcap_flags .Pq Vt str If .Va lpd_enable and .Va chkprintcap_enable are set to .Dq Li YES , these are the flags to pass to the .Xr chkprintcap 8 program. The default is .Dq Li -d , which causes missing directories to be created. .It Va mta_start_script .Pq Vt str This variable specifies the full path to the script to run to start a mail transfer agent. The default is .Pa /etc/rc.sendmail . The .Va sendmail_* variables which .Pa /etc/rc.sendmail uses are documented in the .Xr rc.sendmail 8 manual page. .It Va dumpdev .Pq Vt str Indicates the device (usually a swap partition) to which a crash dump should be written in the event of a system crash. If the value of this variable is .Dq Li AUTO , the first suitable swap device listed in .Pa /etc/fstab will be used as dump device. Otherwise, the value of this variable is passed as the argument to .Xr dumpon 8 . To disable crash dumps, set this variable to .Dq Li NO . .It Va dumpdir .Pq Vt str When the system reboots after a crash and a crash dump is found on the device specified by the .Va dumpdev variable, .Xr savecore 8 will save that crash dump and a copy of the kernel to the directory specified by the .Va dumpdir variable. The default value is .Pa /var/crash . Set to .Dq Li NO to not run .Xr savecore 8 at boot time when .Va dumpdir is set. .It Va savecore_flags .Pq Vt str If crash dumps are enabled, these are the flags to pass to the .Xr savecore 8 utility. .It Va quota_enable .Pq Vt bool Set to .Dq Li YES to turn on user and group disk quotas on system startup via the .Xr quotaon 8 command for all file systems marked as having quotas enabled in .Pa /etc/fstab . The kernel must be built with .Cd "options QUOTA" for disk quotas to function. .It Va check_quotas .Pq Vt bool Set to .Dq Li YES to enable user and group disk quota checking via the .Xr quotacheck 8 command. .It Va quotacheck_flags .Pq Vt str If .Va quota_enable is set to .Dq Li YES , and .Va check_quotas is set to .Dq Li YES , these are the flags to pass to the .Xr quotacheck 8 utility. The default is .Dq Li "-a" , which checks quotas for all file systems with quotas enabled in .Pa /etc/fstab . .It Va quotaon_flags .Pq Vt str If .Va quota_enable is set to .Dq Li YES , these are the flags to pass to the .Xr quotaon 8 utility. The default is .Dq Li "-a" , which enables quotas for all file systems with quotas enabled in .Pa /etc/fstab . .It Va quotaoff_flags .Pq Vt str If .Va quota_enable is set to .Dq Li YES , these are the flags to pass to the .Xr quotaoff 8 utility when shutting down the quota system. The default is .Dq Li "-a" , which disables quotas for all file systems with quotas enabled in .Pa /etc/fstab . .It Va accounting_enable .Pq Vt bool Set to .Dq Li YES to enable system accounting through the .Xr accton 8 facility. .It Va ibcs2_enable .Pq Vt bool Set to .Dq Li YES to enable iBCS2 (SCO) binary emulation at system initial boot time. .It Va ibcs2_loaders .Pq Vt str If not set to .Dq Li NO and if .Va ibcs2_enable is set to .Dq Li YES , this specifies a list of additional iBCS2 loaders to enable. .It Va firstboot_sentinel .Pq Vt str This variable specifies the full path to a .Dq first boot sentinel file. If a file exists with this path, .Pa rc.d scripts with the .Dq firstboot keyword will be run on startup and the sentinel file will be deleted after the boot process completes. The sentinel file must be located on a writable file system which is mounted no later than .Va early_late_divider to function properly. The default is .Pa /firstboot . .It Va linux_enable .Pq Vt bool Set to .Dq Li YES to enable Linux/ELF binary emulation at system initial boot time. .It Va svr4_enable .Pq Vt bool If set to .Dq Li YES , enable SysVR4 emulation at boot time. .It Va sysvipc_enable .Pq Vt bool If set to .Dq Li YES , load System V IPC primitives at boot time. .It Va clear_tmp_enable .Pq Vt bool Set to .Dq Li YES to have .Pa /tmp cleaned at startup. .It Va clear_tmp_X .Pq Vt bool Set to .Dq Li NO to disable removing of X11 lock files, and the removal and (secure) recreation of the various socket directories for X11 related programs. .It Va ldconfig_paths .Pq Vt str Set to the list of shared library paths to use with .Xr ldconfig 8 . NOTE: .Pa /usr/lib will always be added first, so it need not appear in this list. .It Va ldconfig32_paths .Pq Vt str Set to the list of 32-bit compatibility shared library paths to use with .Xr ldconfig 8 . .It Va ldconfig_paths_aout .Pq Vt str Set to the list of shared library paths to use with .Xr ldconfig 8 legacy .Xr a.out 5 support. .It Va ldconfig_insecure .Pq Vt bool The .Xr ldconfig 8 utility normally refuses to use directories which are writable by anyone except root. Set this variable to .Dq Li YES to disable that security check during system startup. .It Va ldconfig_local_dirs .Pq Vt str Set to the list of local .Xr ldconfig 8 directories. The names of all files in the directories listed will be passed as arguments to .Xr ldconfig 8 . .It Va ldconfig_local32_dirs .Pq Vt str Set to the list of local 32-bit compatibility .Xr ldconfig 8 directories. The names of all files in the directories listed will be passed as arguments to .Dq Nm ldconfig Fl 32 . .It Va kern_securelevel_enable .Pq Vt bool Set to .Dq Li YES to set the kernel security level at system startup. .It Va kern_securelevel .Pq Vt int The kernel security level to set at startup. The allowed range of .Ar value ranges from \-1 (the compile time default) to 3 (the most secure). See .Xr security 7 for the list of possible security levels and their effect on system operation. .It Va sshd_program .Pq Vt str Path to the SSH server program .Pa ( /usr/sbin/sshd is the default). .It Va sshd_enable .Pq Vt bool Set to .Dq Li YES to start .Xr sshd 8 at system boot time. .It Va sshd_flags .Pq Vt str If .Va sshd_enable is set to .Dq Li YES , these are the flags to pass to the .Xr sshd 8 daemon. .It Va ftpd_program .Pq Vt str Path to the FTP server program .Pa ( /usr/libexec/ftpd is the default). .It Va ftpd_enable .Pq Vt bool Set to .Dq Li YES to start .Xr ftpd 8 as a stand-alone daemon at system boot time. .It Va ftpd_flags .Pq Vt str If .Va ftpd_enable is set to .Dq Li YES , these are the additional flags to pass to the .Xr ftpd 8 daemon. .It Va watchdogd_enable .Pq Vt bool If set to .Dq Li YES , start the .Xr watchdogd 8 daemon at boot time. This requires that the kernel have been compiled with a .Xr watchdog 4 compatible device. .It Va watchdogd_flags .Pq Vt str If .Va watchdogd_enable is set to .Dq Li YES , these are the flags passed to the .Xr watchdogd 8 daemon. .It Va devfs_rulesets .Pq Vt str List of files containing sets of rules for .Xr devfs 8 . .It Va devfs_system_ruleset .Pq Vt str Rule name(s) to apply to the system .Pa /dev itself. .It Va devfs_set_rulesets .Pq Vt str Pairs of already-mounted .Pa dev directories and rulesets that should be applied to them. For example: /mount/dev=ruleset_name .It Va devfs_load_rulesets .Pq Vt bool If set, always load the default rulesets listed in .Va devfs_rulesets . .It Va performance_cx_lowest .Pq Vt str CPU idle state to use while on AC power. The string .Dq Li LOW indicates that .Xr acpi 4 should use the lowest power state available while .Dq Li HIGH indicates that the lowest latency state (less power savings) should be used. .It Va performance_cpu_freq .Pq Vt str CPU clock frequency to use while on AC power. The string .Dq Li LOW indicates that .Xr cpufreq 4 should use the lowest frequency available while .Dq Li HIGH indicates that the highest frequency (less power savings) should be used. .It Va economy_cx_lowest .Pq Vt str CPU idle state to use when off AC power. The string .Dq Li LOW indicates that .Xr acpi 4 should use the lowest power state available while .Dq Li HIGH indicates that the lowest latency state (less power savings) should be used. .It Va economy_cpu_freq .Pq Vt str CPU clock frequency to use when off AC power. The string .Dq Li LOW indicates that .Xr cpufreq 4 should use the lowest frequency available while .Dq Li HIGH indicates that the highest frequency (less power savings) should be used. .It Va jail_enable .Pq Vt bool If set to .Dq Li NO , any configured jails will not be started. .It Va jail_conf .Pq Vt str The configuration filename used by .Xr jail 8 utility. The default value is .Pa /etc/jail.conf . .It Va jail_parallel_start .Pq Vt bool If set to .Dq Li YES , all configured jails will be started in the background (in parallel). .It Va jail_flags .Pq Vt str Unset by default. When set, use as default value for .Va jail_ Ns Ao Ar jname Ac Ns Va _flags for every jail in .Va jail_list . .It Va jail_list .Pq Vt str A space separated list of names for jails. If this variable is empty, all of .Xr jail 8 instances in the configuration file will be configured. This is purely a configuration aid to help identify and configure multiple jails. The names specified in this list will be used to identify settings common to an instance of a jail, and should contain alphanumeric characters only. The literal jail name of .Dq Li 0 .Pq zero is not allowed. .It Va jail_* variables Note that older releases supported per-jail configuration via .Xr rc.conf 5 variables. For example, hostname of a jail named .Li vjail was able to be set by .Li jail_vjail_hostname . These per-jail configuration variables are now obsolete in favor of .Xr jail 8 configuration file. For backward compatibility, when per-jail configuration variables are defined, .Xr jail 8 configuration files are created as .Pa /var/run/jail. Ns Ao Ar jname Ac Ns Pa .conf and used. .Pp The following per-jail parameters are handled by .Pa rc.d/jail script out of their corresponding .Nm variables. In addition to them, parameters in .Va jail_ Ns Ao Ar jname Ac Ns Va _parameters will be added to the configuration file. They must be a semi-colon .Pq Ql \&; delimited list of .Dq key=value . For more details, see .Xr jail 8 manual page. .Bl -tag -width "host.hostname" -offset indent .It Li path set from .Va jail_ Ns Ao Ar jname Ac Ns Va _rootdir .It Li host.hostname set from .Va jail_ Ns Ao Ar jname Ac Ns Va _hostname .It Li exec.consolelog set from .Va jail_ Ns Ao Ar jname Ac Ns Va _consolelog . The default value is .Pa /var/log/jail_ Ao Ar jname Ac Pa _console.log . .It Li interface set from .Va jail_ Ns Ao Ar jname Ac Ns Va _interface . .It Li vnet.interface set from .Va jail_ Ns Ao Ar jname Ac Ns Va _vnet_interface . This implies .Li vnet parameter will be enabled and cannot be specified with .Va jail_ Ns Ao Ar jname Ac Ns Va _interface , .Va jail_ Ns Ao Ar jname Ac Ns Va _ip and/or .Va jail_ Ns Ao Ar jname Ac Ns Va _ip_multi Ns Aq Ar n at the same time. .It Li fstab set from .Va jail_ Ns Ao Ar jname Ac Ns Va _fstab .It Li mount set from .Va jail_ Ns Ao Ar jname Ac Ns Va _procfs_enable . .It Li exec.fib set from .Va jail_ Ns Ao Ar jname Ac Ns Va _fib .It Li exec.start set from .Va jail_ Ns Ao Ar jname Ac Ns Va _exec_start . The parameter name was .Li command in some older releases. .It Li exec.prestart set from .Va jail_ Ns Ao Ar jname Ac Ns Va _exec_prestart .It Li exec.poststart set from .Va jail_ Ns Ao Ar jname Ac Ns Va _exec_poststart .It Li exec.stop set from .Va jail_ Ns Ao Ar jname Ac Ns Va _exec_stop .It Li exec.prestop set from .Va jail_ Ns Ao Ar jname Ac Ns Va _exec_prestop .It Li exec.poststop set from .Va jail_ Ns Ao Ar jname Ac Ns Va _exec_poststop .It Li ip4.addr set if .Va jail_ Ns Ao Ar jname Ac Ns Va _ip or .Va jail_ Ns Ao Ar jname Ac Ns Va _ip_multi Ns Aq Ar n contain IPv4 addresses .It Li ip6.addr set if .Va jail_ Ns Ao Ar jname Ac Ns Va _ip or .Va jail_ Ns Ao Ar jname Ac Ns Va _ip_multi Ns Aq Ar n contain IPv6 addresses .It Li allow.mount set from .Va jail_ Ns Ao Ar jname Ac Ns Va _mount_enable .It Li mount.devfs set from .Va jail_ Ns Ao Ar jname Ac Ns Va _devfs_enable .It Li devfs_ruleset set from .Va jail_ Ns Ao Ar jname Ac Ns Va _devfs_ruleset . This must be an integer, not a string. .It Li mount.fdescfs set from .Va jail_ Ns Ao Ar jname Ac Ns Va _fdescfs_enable .It Li allow.set_hostname set from .Va jail_ Ns Ao Ar jname Ac Ns Va _set_hostname_allow .It Li allow.rawsocket set from .Va jail_ Ns Ao Ar jname Ac Ns Va _socket_unixiproute_only .It Li allow.sysvipc set from .Va jail_ Ns Ao Ar jname Ac Ns Va _sysvipc_allow .El .\" ----------------------------------------------------- .It Va harvest_interrupt .Pq Vt bool Set to .Dq Li YES to use hardware interrupts as an entropy source. Refer to .Xr random 4 for more information. .It Va harvest_ethernet .Pq Vt bool Set to .Dq Li YES to use LAN traffic as an entropy source. Refer to .Xr random 4 for more information. .It Va harvest_p_to_p .Pq Vt bool Set to .Dq Li YES to use serial line traffic as an entropy source. Refer to .Xr random 4 for more information. .It Va entropy_dir .Pq Vt str Set to .Dq Li NO to disable caching entropy via .Xr cron 8 . Otherwise set to the directory used to store entropy files in. .It Va entropy_file .Pq Vt str Set to .Dq Li NO to disable caching entropy through reboots. Otherwise set to the filename used to store cached entropy through reboots. This file should be located on the root file system to seed the .Xr random 4 device as early as possible in the boot process. .It Va entropy_save_sz .Pq Vt int Size of the entropy cache files saved by .Nm save-entropy periodically. .It Va entropy_save_num .Pq Vt int Number of entropy cache files to save by .Nm save-entropy periodically. .It Va ipsec_enable .Pq Vt bool Set to .Dq Li YES to run .Xr setkey 8 on .Va ipsec_file at boot time. .It Va ipsec_file .Pq Vt str Configuration file for .Xr setkey 8 . .It Va dmesg_enable .Pq Vt bool Set to .Dq Li YES to save .Xr dmesg 8 to .Pa /var/run/dmesg.boot on boot. .It Va rcshutdown_timeout .Pq Vt int If set, start a watchdog timer in the background which will terminate .Pa rc.shutdown if .Xr shutdown 8 has not completed within the specified time (in seconds). Notice that in addition to this soft timeout, .Xr init 8 also applies a hard timeout for the execution of .Pa rc.shutdown . This is configured via .Xr sysctl 8 variable .Va kern.init_shutdown_timeout and defaults to 120 seconds. Setting the value of .Va rcshutdown_timeout to more than 120 seconds will have no effect until the .Xr sysctl 8 variable .Va kern.init_shutdown_timeout is also increased. .It Va virecover_enable .Pq Vt bool Set to .Dq Li NO to prevent the system from trying to recover pre-maturely terminated .Xr vi 1 sessions. .It Va ugidfw_enable .Pq Vt bool Set to .Dq Li YES to load the .Xr mac_bsdextended 4 module upon system initialization and load a default ruleset file. .It Va bsdextended_script .Pq Vt str The default .Xr mac_bsdextended 4 ruleset file to load. The default value of this variable is .Pa /etc/rc.bsdextended . .It Va newsyslog_enable .Pq Vt bool If set to .Dq Li YES , run .Xr newsyslog 8 command at startup. .It Va newsyslog_flags .Pq Vt str If .Va newsyslog_enable is set to .Dq Li YES , these are the flags to pass to the .Xr newsyslog 8 program. The default is .Dq Li -CN , which causes log files flagged with a .Cm C to be created. .It Va mdconfig_md Ns Aq Ar X .Pq Vt str Arguments to .Xr mdconfig 8 for .Xr md 4 device .Ar X . At minimum a .Fl t Ar type must be specified and either a .Fl s Ar size for malloc or swap backed .Xr md 4 devices or a .Fl f Ar file for vnode backed .Xr md 4 devices. Note that .Va mdconfig_md Ns Aq Ar X variables are evaluated until one variable is unset or null. .It Va mdconfig_md Ns Ao Ar X Ac Ns Va _newfs .Pq Vt str Optional arguments passed to .Xr newfs 8 to initialize .Xr md 4 device .Ar X . .It Va mdconfig_md Ns Ao Ar X Ac Ns Va _owner .Pq Vt str An ownership specification passed to .Xr chown 8 after the specified .Xr md 4 device .Ar X has been mounted. Both the .Xr md 4 device and the mount point will be changed. .It Va mdconfig_md Ns Ao Ar X Ac Ns Va _perms .Pq Vt str A mode string passed to .Xr chmod 1 after the specified .Xr md 4 device .Ar X has been mounted. Both the .Xr md 4 device and the mount point will be changed. .It Va mdconfig_md Ns Ao Ar X Ac Ns Va _files .Pq Vt str Files to be copied to the mount point of the .Xr md 4 device .Ar X after it has been mounted. .It Va mdconfig_md Ns Ao Ar X Ac Ns Va _cmd .Pq Vt str Command to execute after the specified .Xr md 4 device .Ar X has been mounted. Note that the command is passed to .Ic eval and that both .Va _dev and .Va _mp variables can be used to reference respectively the .Xr md 4 device and the mount point. Assuming that the .Xr md 4 device is .Li md0 , one could set the following: .Bd -literal mdconfig_md0_cmd="tar xfzC /var/file.tgz \e${_mp}" .Ed .It Va autobridge_interfaces .Pq Vt str Set to the list of bridge interfaces that will have newly arriving interfaces checked against to be automatically added. If not set to .Dq Li NO then for each whitespace separated .Ar element in the value, a .Va autobridge_ Ns Aq Ar element variable is assumed to exist which has a whitespace separated list of interface names to match, these names can use wildcards. For example: .Bd -literal autobridge_interfaces="bridge0" autobridge_bridge0="tap* dc0 vlan[345]" .Ed .It Va mixer_enable .Pq Vt bool If set to .Dq Li YES , enable support for sound mixer. .It Va hcsecd_enable .Pq Vt bool If set to .Dq Li YES , enable Bluetooth security daemon. .It Va hcsecd_config .Pq Vt str Configuration file for .Xr hcsecd 8 . Default .Pa /etc/bluetooth/hcsecd.conf . .It Va sdpd_enable .Pq Vt bool If set to .Dq Li YES , enable Bluetooth Service Discovery Protocol daemon. .It Va sdpd_control .Pq Vt str Path to .Xr sdpd 8 control socket. Default .Pa /var/run/sdp . .It Va sdpd_groupname .Pq Vt str Sets .Xr sdpd 8 group to run as after it initializes. Default .Dq Li nobody . .It Va sdpd_username .Pq Vt str Sets .Xr sdpd 8 user to run as after it initializes. Default .Dq Li nobody . .It Va bthidd_enable .Pq Vt bool If set to .Dq Li YES , enable Bluetooth Human Interface Device daemon. .It Va bthidd_config .Pq Vt str Configuration file for .Xr bthidd 8 . Default .Pa /etc/bluetooth/bthidd.conf . .It Va bthidd_hids .Pq Vt str Path to a file, where .Xr bthidd 8 will store information about known HID devices. Default .Pa /var/db/bthidd.hids . .It Va rfcomm_pppd_server_enable .Pq Vt bool If set to .Dq Li YES , enable Bluetooth RFCOMM PPP wrapper daemon. .It Va rfcomm_pppd_server_profile .Pq Vt str The name of the profile to use from .Pa /etc/ppp/ppp.conf . Multiple profiles can be specified here. Also used to specify per-profile overrides. When the profile name contains any of the characters .Dq Li .-/+ they are translated to .Dq Li _ for the proposes of the override variable names. .It Va rfcomm_pppd_server_ Ns Ao Ar profile Ac Ns _bdaddr .Pq Vt str Overrides local address to listen on. By default .Xr rfcomm_pppd 8 will listen on .Dq Li ANY address. The address can be specified as BD_ADDR or name. .It Va rfcomm_pppd_server_ Ns Ao Ar profile Ac Ns _channel .Pq Vt str Overrides local RFCOMM channel to listen on. By default .Xr rfcomm_pppd 8 will listen on RFCOMM channel 1. Must set properly if multiple profiles used in the same time. .It Va rfcomm_pppd_server_ Ns Ao Ar profile Ac Ns _register_sp .Pq Vt bool Tells .Xr rfcomm_pppd 8 if it should register Serial Port service on the specified RFCOMM channel. Default .Dq Li NO . .It Va rfcomm_pppd_server_ Ns Ao Ar profile Ac Ns _register_dun .Pq Vt bool Tells .Xr rfcomm_pppd 8 if it should register Dial-Up Networking service on the specified RFCOMM channel. Default .Dq Li NO . .It Va ubthidhci_enable .Pq Vt bool If set to .Dq Li YES , change the USB Bluetooth controller from HID mode to HCI mode. You also need to specify the location of USB Bluetooth controller with the .Va ubthidhci_busnum and .Va ubthidhci_addr variables. .It Va ubthidhci_busnum Bus number where the USB Bluetooth controller is located. Check the output of .Xr usbconfig 8 on your system to find this information. .It Va ubthidhci_addr Bus address of the USB Bluetooth controller. Check the output of .Xr usbconfig 8 on your system to find this information. .It Va netwait_enable .Pq Vt bool If set to .Dq Li YES , delays the start of network-reliant services until .Va netwait_if is up and ICMP packets to a destination defined in .Va netwait_ip are flowing. Link state is examined first, followed by .Dq Li pinging an IP address to verify network usability. If no destination can be reached or timeouts are exceeded, network services are started anyway with no guarantee that the network is usable. Use of this variable requires both .Va netwait_ip and .Va netwait_if to be set. .It Va netwait_ip .Pq Vt str Empty by default. This variable contains a space-delimited list of IP addresses to .Xr ping 8 . DNS hostnames should not be used as resolution is not guaranteed to be functional at this point. If multiple IP addresses are specified, each will be tried until one is successful or the list is exhausted. .It Va netwait_timeout .Pq Vt int Indicates the total number of seconds to perform a .Dq Li ping against each IP address in .Va netwait_ip , at a rate of one ping per second. If any of the pings are successful, full network connectivity is considered reliable. The default is 60. .It Va netwait_if .Pq Vt str Empty by default. Defines the name of the network interface on which watch for link. .Xr ifconfig 8 is used to monitor the interface, looking for .Dq Li status: no carrier . Once gone, the link is considered up. This can be a .Xr vlan 4 interface if desired. .It Va netwait_if_timeout .Pq Vt int Defines the total number of seconds to wait for link to become usable, polled at a 1-second interval. The default is 30. .It Va rctl_enable .Pq Vt bool Set to .Dq Li YES to load .Xr rctl 8 rules from the defined ruleset. The kernel must be built with .Cd "options RACCT" and .Cd "options RCTL" . .It Va rctl_rules .Pq Vt str Set to .Pa /etc/rctl.conf by default. This variables contains the .Xr rctl.conf 5 ruleset to load for .Xr rctl 8 . .El .Sh FILES .Bl -tag -width ".Pa /etc/defaults/rc.conf" -compact .It Pa /etc/defaults/rc.conf .It Pa /etc/rc.conf .It Pa /etc/rc.conf.local .El .Sh SEE ALSO .Xr catman 1 , .Xr chmod 1 , .Xr gdb 1 , .Xr info 1 , .Xr kbdcontrol 1 , .Xr makewhatis 1 , .Xr sh 1 , .Xr vi 1 , .Xr vidcontrol 1 , .Xr bridge 4 , .Xr dummynet 4 , .Xr ip 4 , .Xr ipf 4 , .Xr ipfw 4 , .Xr ipnat 4 , .Xr kld 4 , .Xr pf 4 , .Xr pflog 4 , .Xr pfsync 4 , .Xr tcp 4 , .Xr udp 4 , .Xr exports 5 , .Xr fstab 5 , .Xr ipf 5 , .Xr ipnat 5 , .Xr jail.conf 5 , .Xr motd 5 , .Xr newsyslog.conf 5 , .Xr pf.conf 5 , .Xr security 7 , .Xr accton 8 , .Xr amd 8 , .Xr apm 8 , .Xr atm 8 , .Xr bthidd 8 , .Xr chkprintcap 8 , .Xr chown 8 , .Xr cron 8 , .Xr devfs 8 , .Xr dhclient 8 , .Xr ftpd 8 , .Xr geli 8 , .Xr hcsecd 8 , .Xr ifconfig 8 , .Xr inetd 8 , .Xr ipf 8 , .Xr ipfw 8 , .Xr ipnat 8 , .Xr jail 8 , .Xr kldxref 8 , .Xr lpd 8 , .Xr mdconfig 8 , .Xr mdmfs 8 , .Xr mixer 8 , .Xr mountd 8 , .Xr moused 8 , .Xr mrouted 8 , .Xr newfs 8 , .Xr newsyslog 8 , .Xr nfsd 8 , .Xr ntpd 8 , .Xr ntpdate 8 , .Xr pfctl 8 , .Xr pflogd 8 , .Xr ping 8 , .Xr powerd 8 , .Xr quotacheck 8 , .Xr quotaon 8 , .Xr rc 8 , .Xr rc.sendmail 8 , .Xr rfcomm_pppd 8 , .Xr route 8 , .Xr routed 8 , -.Xr rpcbind 8 , .Xr rpc.lockd 8 , .Xr rpc.statd 8 , +.Xr rpcbind 8 , .Xr rwhod 8 , .Xr savecore 8 , .Xr sdpd 8 , .Xr sshd 8 , .Xr swapon 8 , .Xr sysctl 8 , .Xr syslogd 8 , .Xr timed 8 , .Xr unbound 8 , .Xr usbconfig 8 , .Xr wlandebug 8 , .Xr yp 8 , .Xr ypbind 8 , .Xr ypserv 8 , .Xr ypset 8 .Sh HISTORY The .Nm file appeared in .Fx 2.2.2 . .Sh AUTHORS .An Jordan K. Hubbard . Index: projects/sendfile/share/man/man5/services.5 =================================================================== --- projects/sendfile/share/man/man5/services.5 (revision 276056) +++ projects/sendfile/share/man/man5/services.5 (revision 276057) @@ -1,103 +1,103 @@ .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. 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. 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. .\" .\" @(#)services.5 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" .Dd April 4, 2010 .Dt SERVICES 5 .Os .Sh NAME .Nm services .Nd service name data base .Sh DESCRIPTION The .Nm file contains information regarding the known services available in the Internet. For each service a single line should be present with the following information: .Bd -unfilled -offset indent official service name port number protocol name aliases .Ed .Pp Items are separated by any number of blanks and/or tab characters. The port number and protocol name are considered a single .Em item ; a ``/'' is used to separate the port and protocol (e.g.\& ``512/tcp''). A ``#'' indicates the beginning of a comment; subsequent characters up to the end of the line are not interpreted by the routines which search the file. .Pp Service names may contain any printable character other than a field delimiter, newline, or comment character. .Pp If .Dq db is specified as source in the .Xr nsswitch.conf 5 , .Pa /var/db/services.db is searched. The database in .Pa /var/db/services.db needs to be updated with .Xr services_mkdb 8 after changes to the services file have been applied. .Sh NIS INTERACTION Access to the NIS .Pa services.byname map can be enabled by adding a single ``+'' on a line by itself in the .Pa /etc/services file. This causes the contents of the NIS services map to be inserted at the location where the ``+'' appears. .Sh FILES .Bl -tag -width /etc/services -compact .It Pa /etc/services The .Nm file resides in .Pa /etc . .El .Sh SEE ALSO -.Xr getservent 3 -.Xr nsswitch.conf 5 +.Xr getservent 3 , +.Xr nsswitch.conf 5 , .Xr services_mkdb 8 .Sh HISTORY The .Nm file format appeared in .Bx 4.2 . .Sh BUGS A name server should be used instead of a static file. Index: projects/sendfile/share/man/man9/BUF_ISLOCKED.9 =================================================================== --- projects/sendfile/share/man/man9/BUF_ISLOCKED.9 (revision 276056) +++ projects/sendfile/share/man/man9/BUF_ISLOCKED.9 (revision 276057) @@ -1,69 +1,69 @@ .\" .\" Copyright (C) 2008 Attilio Rao .\" 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(s), this list of conditions and the following disclaimer as .\" the first lines of this file unmodified other than the possible .\" addition of one or more copyright notices. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice(s), 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 COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ .\" .Dd January 22, 2008 .Dt BUF_ISLOCKED 9 .Os .Sh NAME .Nm BUF_ISLOCKED .Nd "returns the state of the lock linked to the buffer" .Sh SYNOPSIS .In sys/param.h .In sys/systm.h .In sys/uio.h .In sys/bio.h .In sys/buf.h .Ft int .Fn BUF_ISLOCKED "struct buf *bp" .Sh DESCRIPTION The .Fn BUF_ISLOCKED function returns the status of the lock linked to the buffer in relation to curthread. .Pp It can return: .Bl -tag -width ".Dv LK_EXCLUSIVE" .It Dv LK_EXCLUSIVE An exclusive lock is held by curthread. .It Dv LK_EXCLOTHER An exclusive lock is held by someone other than curthread. .It Dv LK_SHARED A shared lock is held. .It Li 0 The lock is not held by anyone. .El .Sh SEE ALSO -.Xr lockstatus 9 , .Xr buf 9 , .Xr BUF_LOCK 9 , .Xr BUF_UNLOCK 9 , -.Xr lockmgr 9 +.Xr lockmgr 9 , +.Xr lockstatus 9 .Sh AUTHORS This manual page was written by .An Attilio Rao Aq Mt attilio@FreeBSD.org . Index: projects/sendfile/share/man/man9/BUS_BIND_INTR.9 =================================================================== --- projects/sendfile/share/man/man9/BUS_BIND_INTR.9 (revision 276056) +++ projects/sendfile/share/man/man9/BUS_BIND_INTR.9 (revision 276057) @@ -1,98 +1,98 @@ .\" -*- nroff -*- .\" .\" Copyright (c) 2009 Advanced Computing Technologies LLC .\" Written by: John H. Baldwin .\" 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$ .\" .Dd October 14, 2009 .Dt BUS_BIND_INTR 9 .Os .Sh NAME .Nm BUS_BIND_INTR , .Nm bus_bind_intr .Nd "bind an interrupt resource to a specific CPU" .Sh SYNOPSIS .In sys/param.h .In sys/bus.h .Ft int .Fo BUS_BIND_INTR .Fa "device_t dev" "device_t child" "struct resource *irq" "int cpu" .Fc .Ft int .Fn bus_bind_intr "device_t dev" "struct resource *irq" "int cpu" .Sh DESCRIPTION The .Fn BUS_BIND_INTR method allows an interrupt resource to be pinned to a specific CPU. The interrupt resource must have an interrupt handler attached via .Xr BUS_SETUP_INTR 9 . The .Fa cpu parameter corresponds to the ID of a valid CPU in the system. Binding an interrupt restricts the .Xr cpuset 2 of any associated interrupt threads to only include the specified CPU. It may also direct the low-level interrupt handling of the interrupt to the specified CPU as well, but this behavior is platform-dependent. If the value .Dv NOCPU is used for .Fa cpu , then the interrupt will be .Dq unbound which restores any associated interrupt threads back to the default cpuset. .Pp Non-sleepable locks such as mutexes should not be held across calls to these functions. .Pp The .Fn bus_bind_intr function is a simple wrapper around .Fn BUS_BIND_INTR . .Pp Note that currently there is no attempt made to arbitrate between multiple bind requests for the same interrupt from either the same device or multiple devices. There is also no arbitration between interrupt binding requests submitted by userland via .Xr cpuset 2 and .Fn BUS_BIND_INTR . The most recent binding request is the one that will be in effect. .Sh RETURN VALUES Zero is returned on success, otherwise an appropriate error is returned. .Sh SEE ALSO -.Xr BUS_SETUP_INTR 9 , .Xr cpuset 2 , +.Xr BUS_SETUP_INTR 9 , .Xr device 9 .Sh HISTORY The .Fn BUS_BIND_INTR method and .Fn bus_bind_intr functions first appeared in .Fx 7.2 . Index: projects/sendfile/share/man/man9/BUS_DESCRIBE_INTR.9 =================================================================== --- projects/sendfile/share/man/man9/BUS_DESCRIBE_INTR.9 (revision 276056) +++ projects/sendfile/share/man/man9/BUS_DESCRIBE_INTR.9 (revision 276057) @@ -1,104 +1,104 @@ .\" -*- nroff -*- .\" .\" Copyright (c) 2009 Advanced Computing Technologies LLC .\" Written by: John H. Baldwin .\" 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$ .\" .Dd October 14, 2009 .Dt BUS_DESCRIBE_INTR 9 .Os .Sh NAME .Nm BUS_DESCRIBE_INTR , .Nm bus_describe_intr .Nd "associate a description with an active interrupt handler" .Sh SYNOPSIS .In sys/param.h .In sys/bus.h .Ft int .Fo BUS_BIND_INTR .Fa "device_t dev" "device_t child" "struct resource *irq" "void *cookie" .Fa "const char *descr" .Fc .Ft int .Fo bus_describe_intr .Fa "device_t dev" "struct resource *irq" "void *cookie" "const char *fmt" .Fa ... .Fc .Sh DESCRIPTION The .Fn BUS_DESCRIBE_INTR method associates a description with an active interrupt handler. The .Fa cookie parameter must be the value returned by a successful call to .Xr BUS_SETUP_INTR 9 for the interrupt .Fa irq . .Pp The .Fn bus_describe_intr function is a simple wrapper around .Fn BUS_DESCRIBE_INTR . As a convenience, .Fn bus_describe_intr allows the caller to use .Xr printf 9 style formatting to build the description string using .Fa fmt . .Pp When an interrupt handler is established by .Xr BUS_SETUP_INTR 9 , the handler is named after the device the handler is established for. This name is then used in various places such as interrupt statistics displayed by .Xr systat 1 and .Xr vmstat 8 . For devices that use a single interrupt, the device name is sufficiently unique to identify the interrupt handler. However, for devices that use multiple interrupts it can be useful to distinguish the interrupt handlers. When a description is set for an active interrupt handler, a colon followed by the description is appended to the device name to form the interrupt handler name. .Sh RETURN VALUES Zero is returned on success, otherwise an appropriate error is returned. .Sh SEE ALSO -.Xr BUS_SETUP_INTR 9 , .Xr systat 1 , .Xr vmstat 8 , +.Xr BUS_SETUP_INTR 9 , .Xr device 9 , .Xr printf 9 .Sh HISTORY The .Fn BUS_DESCRIBE_INTR method and .Fn bus_describe_intr functions first appeared in .Fx 8.1 . .Sh BUGS It is not currently possible to remove a description from an active interrupt handler. Index: projects/sendfile/share/man/man9/DB_COMMAND.9 =================================================================== --- projects/sendfile/share/man/man9/DB_COMMAND.9 (revision 276056) +++ projects/sendfile/share/man/man9/DB_COMMAND.9 (revision 276057) @@ -1,110 +1,110 @@ .\"- .\" Copyright (c) 2008 Guillaume Ballet .\" 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$ .\" .Dd August 27, 2008 .Dt DB_COMMAND 9 .Os .Sh NAME .Nm DB_COMMAND , .Nm DB_SHOW_COMMAND , .Nm DB_SHOW_ALL_COMMAND .Nd Extends the ddb command set .Sh SYNOPSIS .In ddb/ddb.h .Fo DB_COMMAND .Fa command_name .Fa command_function .Fc .Fn DB_SHOW_COMMAND "command_name" "command_function" .Fn DB_SHOW_ALL_COMMAND "command_name" "command_function" .Sh DESCRIPTION The .Fn DB_COMMAND macro adds .Fa command_name to the list of top-level commands. Invoking .Fa command_name from ddb will call .Fa command_function . .Pp The .Fn DB_SHOW_COMMAND and .Fn DB_SHOW_ALL_COMMAND are roughly equivalent to .Fn DB_COMMAND but in these cases, .Fa command_name is a sub-command of the ddb .Sy show command and .Sy show all command, respectively. .Pp The general command syntax: .Cm command Ns Op Li \&/ Ns Ar modifier -.Ar address Ns Op Li , Ns Ar count , +.Ar address Ns Op , Ns Ar count , translates into the following parameters for .Fa command_function : .Bl -tag -width Fa -offset indent .It Fa addr The address passed to the command as an argument. .It Fa have_addr A boolean value that is true if the addr field is valid. .It Fa count The number of quad words starting at offset .Fa addr that the command must process. .It Fa modif A pointer to the string of modifiers. That is, a series of symbols used to pass some options to the command. For example, the .Sy examine command will display words in decimal form if it is passed the modifier "d". .El .Sh EXAMPLE In your module, the command is declared as: .Bd -literal DB_COMMAND(mycmd, my_cmd_func) { if (have_addr) db_printf("Calling my command with address %p\\n", addr); } .Ed .Pp Then, when in ddb: .Bd -literal .Bf Sy db> mycmd 0x1000 Calling my command with address 0x1000 db> .Ef .Ed .Sh SEE ALSO .Xr ddb 4 .Sh AUTHORS This manual page was written by .An Guillaume Ballet Aq Mt gballet@gmail.com . Index: projects/sendfile/share/man/man9/EVENTHANDLER.9 =================================================================== --- projects/sendfile/share/man/man9/EVENTHANDLER.9 (revision 276056) +++ projects/sendfile/share/man/man9/EVENTHANDLER.9 (revision 276057) @@ -1,337 +1,337 @@ .\" Copyright (c) 2004 Joseph Koshy .\" 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$ .\" .Dd April 19, 2014 .Dt EVENTHANDLER 9 .Os .Sh NAME .Nm EVENTHANDLER .Nd kernel event handling functions .Sh SYNOPSIS .In sys/eventhandler.h .Fn EVENTHANDLER_DECLARE name type .Fn EVENTHANDLER_INVOKE name ... .Ft eventhandler_tag .Fn EVENTHANDLER_REGISTER name func arg priority .Fn EVENTHANDLER_DEREGISTER name tag .Ft eventhandler_tag .Fo eventhandler_register .Fa "struct eventhandler_list *list" .Fa "const char *name" .Fa "void *func" .Fa "void *arg" .Fa "int priority" .Fc .Ft void .Fo eventhandler_deregister .Fa "struct eventhandler_list *list" .Fa "eventhandler_tag tag" .Fc .Ft "struct eventhandler_list *" .Fn eventhandler_find_list "const char *name" .Ft void .Fn eventhandler_prune_list "struct eventhandler_list *list" .Sh DESCRIPTION The .Nm mechanism provides a way for kernel subsystems to register interest in kernel events and have their callback functions invoked when these events occur. .Pp The normal way to use this subsystem is via the macro interface. The macros that can be used for working with event handlers and callback function lists are: .Bl -tag -width indent .It Fn EVENTHANDLER_DECLARE This macro declares an event handler named by argument .Fa name with callback functions of type .Fa type . .It Fn EVENTHANDLER_REGISTER This macro registers a callback function .Fa func with event handler .Fa name . When invoked, function .Fa func will be invoked with argument .Fa arg as its first parameter along with any additional parameters passed in via macro .Fn EVENTHANDLER_INVOKE (see below). Callback functions are invoked in order of priority. The relative priority of each callback among other callbacks associated with an event is given by argument .Fa priority , which is an integer ranging from .Dv EVENTHANDLER_PRI_FIRST (highest priority), to .Dv EVENTHANDLER_PRI_LAST (lowest priority). The symbol .Dv EVENTHANDLER_PRI_ANY may be used if the handler does not have a specific priority associated with it. If registration is successful, .Fn EVENTHANDLER_REGISTER returns a cookie of type .Vt eventhandler_tag . .It Fn EVENTHANDLER_DEREGISTER This macro removes a previously registered callback associated with tag .Fa tag from the event handler named by argument .Fa name . .It Fn EVENTHANDLER_INVOKE This macro is used to invoke all the callbacks associated with event handler .Fa name . This macro is a variadic one. Additional arguments to the macro after the .Fa name parameter are passed as the second and subsequent arguments to each registered callback function. .El .Pp The macros are implemented using the following functions: .Bl -tag -width indent .It Fn eventhandler_register The .Fn eventhandler_register function is used to register a callback with a given event. The arguments expected by this function are: .Bl -tag -width ".Fa priority" .It Fa list A pointer to an existing event handler list, or .Dv NULL . If .Fa list is .Dv NULL , the event handler list corresponding to argument .Fa name is used. .It Fa name The name of the event handler list. .It Fa func A pointer to a callback function. Argument .Fa arg is passed to the callback function .Fa func as its first argument when it is invoked. .It Fa priority The relative priority of this callback among all the callbacks registered for this event. Valid values are those in the range .Dv EVENTHANDLER_PRI_FIRST to .Dv EVENTHANDLER_PRI_LAST . .El .Pp The .Fn eventhandler_register function returns a .Fa tag that can later be used with .Fn eventhandler_deregister to remove the particular callback function. .It Fn eventhandler_deregister The .Fn eventhandler_deregister function removes the callback associated with tag .Fa tag from the event handler list pointed to by .Fa list . This function is safe to call from inside an event handler callback. .It Fn eventhandler_find_list The .Fn eventhandler_find_list function returns a pointer to event handler list structure corresponding to event .Fa name . .It Fn eventhandler_prune_list The .Fn eventhandler_prune_list function removes all deregistered callbacks from the event list .Fa list . .El .Ss Kernel Event Handlers The following event handlers are present in the kernel: .Bl -tag -width indent .It Vt acpi_sleep_event Callbacks invoked when the system is being sent to sleep. .It Vt acpi_wakeup_event Callbacks invoked when the system is being woken up. .It Vt app_coredump_start Callbacks invoked at start of application core dump. .It Vt app_coredump_progress Callbacks invoked during progress of application core dump. .It Vt app_coredump_finish Callbacks invoked at finish of application core dump. .It Vt app_coredump_error Callbacks invoked on error of application core dump. .It Vt bpf_track Callbacks invoked when a BPF listener attaches to/detaches from network interface. .It Vt cpufreq_levels_changed Callback invoked when cpu frequence levels have changed. .It Vt cpufreq_post_change Callback invoked after cpu frequence has changed. .It Vt cpufreq_pre_change Callback invoked before cpu frequence has changed .It Vt dcons_poll Callback invoked to poll for dcons changes. .It Vt dev_clone Callbacks invoked when a new entry is created under .Pa /dev . .It Vt group_attach_event Callback invoked when an interfance has been added to an interface group. .It Vt group_change_event Callback invoked when an change has been made to an interface group. .It Vt group_detach_event Callback invoked when an interfance has been removed from an interface group. .It Vt ifaddr_event Callbacks invoked when an address is set up on a network interface. .It Vt if_clone_event Callbacks invoked when an interface is cloned. .It Vt iflladdr_event Callback invoked when an if link layer address event has happened. .It Vt ifnet_arrival_event Callbacks invoked when a new network interface appears. .It Vt ifnet_departure_event Callbacks invoked when a network interface is taken down. .It Vt ifnet_link_event Callback invoked when an interfance link event has happened. .It Vt kld_load Callbacks invoked after a linker file has been loaded. .It Vt kld_unload Callbacks invoked after a linker file has been successfully unloaded. .It Vt kld_unload_try Callbacks invoked before a linker file is about to be unloaded. These callbacks may be used to return an error and prevent the unload from proceeding. .It Vt lle_event Callback invoked when an link layer event has happened. .It Vt nmbclusters_change Callback invoked when the number of mbuf clusters has changed. .It Vt nmbufs_change Callback invoked when the number of mbufs has changed. .It Vt maxsockets_change Callback invoked when the maximum number of sockets has changed. .It Vt mountroot Callback invoked when root has been mounted. .It Vt power_profile_change Callbacks invoked when the power profile of the system changes. .It Vt power_resume Callback invoked when the system has resumed. .It Vt power_suspend Callback invoked just before the system is suspended. .It Vt process_ctor Callback invoked when a process is created. .It Vt process_dtor Callback invoked when a process is destroyed. .It Vt process_exec Callbacks invoked when a process performs an .Fn exec operation. .It Vt process_exit Callbacks invoked when a process exits. .It Vt process_fini Callback invoked when a process memory is destroyed. -This is never called. +This is never called. .It Vt process_fork Callbacks invoked when a process forks a child. .It Vt process_init Callback invoked when a process is initalized. .It Vt random_adaptor_attach Callback invoked when a new random module has been loaded. .It Vt register_framebuffer Callback invoked when a new frame buffer is registered. .It Vt route_redirect_event Callback invoked when a route gets redirected to a new location. .It Vt shutdown_pre_sync Callbacks invoked at shutdown time, before file systems are synchronized. .It Vt shutdown_post_sync Callbacks invoked at shutdown time, after all file systems are synchronized. .It Vt shutdown_final Callbacks invoked just before halting the system. .It Vt tcp_offload_listen_start Callback invoked for TCP Offload to start listening for new connections. .It Vt tcp_offload_listen_stop Callback invoked ror TCP Offload to stop listening for new connections. .It Vt thread_ctor Callback invoked when a thread object is created. .It Vt thread_dtor Callback invoked when a thread object is destroyed. .It Vt thread_init Callback invoked when a thread object is initalized. .It Vt thread_fini Callback invoked when a thread object is deinitalized. .It Vt usb_dev_configured Callback invoked when a USB device is configured .It Vt unregister_framebuffer Callback invoked when a frame buffer is deregistered. .It Vt vfs_mounted Callback invoked when a file system is mounted. .It Vt vfs_unmounted Callback invoked when a file system is unmounted. .It Vt vlan_config Callback invoked when the vlan configuration has changed. .It Vt vlan_unconfig Callback invoked when a vlan is destroyed. .It Vt vm_lowmem Callbacks invoked when virtual memory is low. .It Vt watchdog_list Callbacks invoked when the system watchdog timer is reinitialized. .El .Sh RETURN VALUES The macro .Fn EVENTHANDLER_REGISTER and function .Fn eventhandler_register return a cookie of type .Vt eventhandler_tag , which may be used in a subsequent call to .Fn EVENTHANDLER_DEREGISTER or .Fn eventhandler_deregister . .Pp The .Fn eventhandler_find_list function returns a pointer to an event handler list corresponding to parameter .Fa name , or .Dv NULL if no such list was found. .Sh HISTORY The .Nm facility first appeared in .Fx 4.0 . .Sh AUTHORS This manual page was written by .An Joseph Koshy Aq Mt jkoshy@FreeBSD.org . Index: projects/sendfile/share/man/man9/VFS.9 =================================================================== --- projects/sendfile/share/man/man9/VFS.9 (revision 276056) +++ projects/sendfile/share/man/man9/VFS.9 (revision 276057) @@ -1,61 +1,61 @@ .\" -*- nroff -*- .\" .\" Copyright (c) 1996 Doug Rabson .\" .\" All rights reserved. .\" .\" This program is free software. .\" .\" 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 DEVELOPERS ``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 DEVELOPERS 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$ .\" .Dd February 9, 2010 .Dt VFS 9 .Os .Sh NAME .Nm VFS .Nd kernel interface to file systems .Sh DESCRIPTION Calls used to set or query file systems for settings or information. .Pp File systems that do not implement a VFS operation should use the appropriate .Fa vfs_std function from .Pa src/sys/kern/vfs_default.c rather than implementing empty functions or casting to .Fa eopnotsupp . .Sh SEE ALSO .Xr VFS_CHECKEXP 9 , .Xr VFS_FHTOVP 9 , .Xr VFS_INIT 9 , .Xr VFS_MOUNT 9 , .Xr VFS_QUOTACTL 9 , .Xr VFS_SET 9 , .Xr VFS_STATFS 9 , .Xr VFS_SYNC 9 , .Xr VFS_UNMOUNT 9 , .Xr VFS_VGET 9 , -.Xr VOP_VPTOFH 9 , -.Xr vnode 9 +.Xr vnode 9 , +.Xr VOP_VPTOFH 9 .Sh AUTHORS This manual page was written by .An Doug Rabson . Index: projects/sendfile/share/man/man9/VFS_CHECKEXP.9 =================================================================== --- projects/sendfile/share/man/man9/VFS_CHECKEXP.9 (revision 276056) +++ projects/sendfile/share/man/man9/VFS_CHECKEXP.9 (revision 276057) @@ -1,88 +1,88 @@ .\" .\" Copyright (c) 1999 Alfred Perlstein .\" .\" All rights reserved. .\" .\" This program is free software. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following condition .\" is met: .\" Redistributions of source code must retain the above copyright .\" notice, this condition and the following disclaimer. .\" .\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``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 DEVELOPERS 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$ .\" .Dd January 4, 2010 .Dt VFS_CHECKEXP 9 .Os .Sh NAME .Nm VFS_CHECKEXP .Nd check if a file system is exported to a client .Sh SYNOPSIS .In sys/param.h .In sys/mount.h .Ft int .Fn VFS_CHECKEXP "struct mount *mp" "struct sockaddr *nam" "int *exflagsp" "struct ucred **credanonp" .Sh DESCRIPTION The .Fn VFS_CHECKEXP macro is used by the NFS server to check if a mount point is exported to a client. .Pp The arguments it expects are: .Bl -tag -width credanonp .It Fa mp The mount point to be checked. .It Fa nam An mbuf containing the network address of the client. .It Fa exflagsp Return parameter for the export flags for this client. .It Fa credanonp Return parameter for the anonymous credentials for this client. .El .Pp The .Fn VFS_CHECKEXP macro should be called on a file system's mount structure to determine if it is exported to a client whose address is contained in .Fa nam . .Pp It is generally called before .Xr VFS_FHTOVP 9 to validate that a client has access to the file system. .Pp The file system should call .Xr vfs_export_lookup 9 with the address of an appropriate .Vt netexport structure and the address of the client, .Fa nam , to verify that the client can access this file system. .Sh RETURN VALUES The export flags and anonymous credentials specific to the client (returned by .Xr vfs_export_lookup 9 ) will be returned in .Fa *exflagsp and .Fa *credanonp . .Sh SEE ALSO .Xr VFS 9 , .Xr VFS_FHTOVP 9 , -.Xr VOP_VPTOFH 9 , -.Xr vnode 9 +.Xr vnode 9 , +.Xr VOP_VPTOFH 9 .Sh AUTHORS This manual page was written by .An Alfred Perlstein . Index: projects/sendfile/share/man/man9/VFS_FHTOVP.9 =================================================================== --- projects/sendfile/share/man/man9/VFS_FHTOVP.9 (revision 276056) +++ projects/sendfile/share/man/man9/VFS_FHTOVP.9 (revision 276057) @@ -1,83 +1,83 @@ .\" -*- nroff -*- .\" .\" Copyright (c) 1996 Doug Rabson .\" .\" All rights reserved. .\" .\" This program is free software. .\" .\" 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 DEVELOPERS ``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 DEVELOPERS 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$ .\" .Dd January 4, 2010 .Dt VFS_FHTOVP 9 .Os .Sh NAME .Nm VFS_FHTOVP .Nd turn an NFS filehandle into a vnode .Sh SYNOPSIS .In sys/param.h .In sys/mount.h .In sys/vnode.h .Ft int .Fn VFS_FHTOVP "struct mount *mp" "struct fid *fhp" "struct vnode **vpp" .Sh DESCRIPTION The .Fn VFS_FHTOVP macro is used by the NFS server to turn an NFS filehandle into a vnode. .Pp The arguments it expects are: .Bl -tag -width vpp .It Fa mp The file system. .It Fa fhp The filehandle to convert. .It Fa vpp Return parameter for the new locked vnode. .El .Pp The contents of the filehandle are defined by the file system and are not examined by any other part of the system. It should contain enough information to uniquely identify a file within the file system as well as noticing when a file has been removed and the file system resources have been reused for a new file. For instance, UFS file system stores the inode number and inode generation counter in its filehandle. .Pp A call to .Fn VFS_FHTOVP should generally be preceded by a call to .Xr VFS_CHECKEXP 9 to check if the file is accessible to the client. .Sh RETURN VALUES The locked vnode for the file will be returned in .Fa *vpp . .Sh SEE ALSO .Xr VFS 9 , .Xr VFS_CHECKEXP 9 , -.Xr VOP_VPTOFH 9 , -.Xr vnode 9 +.Xr vnode 9 , +.Xr VOP_VPTOFH 9 .Sh AUTHORS This manual page was written by .An Doug Rabson . Index: projects/sendfile/share/man/man9/VFS_SET.9 =================================================================== --- projects/sendfile/share/man/man9/VFS_SET.9 (revision 276056) +++ projects/sendfile/share/man/man9/VFS_SET.9 (revision 276057) @@ -1,111 +1,111 @@ .\" .\" Copyright (C) 2001 Chad David . 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(s), this list of conditions and the following disclaimer as .\" the first lines of this file unmodified other than the possible .\" addition of one or more copyright notices. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice(s), 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 COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ .\" .Dd February 21, 2013 .Dt VFS_SET 9 .Os .Sh NAME .Nm VFS_SET .Nd set up loadable file system .Vt vfsconf .Sh SYNOPSIS .In sys/param.h .In sys/kernel.h .In sys/module.h .In sys/mount.h .Ft void .Fn VFS_SET "struct vfsops *vfsops" "fsname" "int flags" .Sh DESCRIPTION .Fn VFS_SET creates a .Vt vfsconf structure for the loadable module with the given .Fa vfsops , fsname and .Fa flags , and declares it by calling .Xr DECLARE_MODULE 9 using .Fn vfs_modevent as the event handler. .Pp Possible values for the .Fa flags argument are: .Bl -hang -width ".Dv VFCF_DELEGADMIN" .It Dv VFCF_STATIC File system should be statically available in the kernel. .It Dv VFCF_NETWORK Network exportable file system. .It Dv VFCF_READONLY Does not support write operations. .It Dv VFCF_SYNTHETIC Pseudo file system, data does not represent on-disk files. .It Dv VFCF_LOOPBACK Loopback file system layer. .It Dv VFCF_UNICODE File names are stored as Unicode. .It Dv VFCF_JAIL Can be mounted from within a jail if .Va security.jail.mount_allowed sysctl is set to .Dv 1 . .It Dv VFCF_DELEGADMIN Supports delegated administration if .Va vfs.usermount sysctl is set to .Dv 1 . .It Dv VFCF_SBDRY When in VFS method, the thread suspension is deferred to the user boundary upon arrival of stop action. .El .Sh PSEUDOCODE .Bd -literal /* * Fill in the fields for which we have special methods. * The others are initially null. This tells vfs to change them to * pointers to vfs_std* functions during file system registration. */ static struct vfsops myfs_vfsops = { .vfs_mount = myfs_mount, .vfs_root = myfs_root, .vfs_statfs = myfs_statfs, .vfs_unmount = myfs_unmount, }; VFS_SET(myfs_vfsops, myfs, 0); .Ed .Sh SEE ALSO .Xr jail 2 , .Xr jail 8 , .Xr DECLARE_MODULE 9 , -.Xr vfsconf 9 , -.Xr vfs_modevent 9 +.Xr vfs_modevent 9 , +.Xr vfsconf 9 .Sh AUTHORS This manual page was written by .An Chad David Aq Mt davidc@acns.ab.ca . Index: projects/sendfile/share/man/man9/VOP_LOCK.9 =================================================================== --- projects/sendfile/share/man/man9/VOP_LOCK.9 (revision 276056) +++ projects/sendfile/share/man/man9/VOP_LOCK.9 (revision 276057) @@ -1,124 +1,125 @@ .\" -*- nroff -*- .\" .\" Copyright (c) 1996 Doug Rabson .\" .\" All rights reserved. .\" .\" This program is free software. .\" .\" 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 DEVELOPERS ``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 DEVELOPERS 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$ .\" .Dd February 25, 2008 .Dt VOP_LOCK 9 .Os .Sh NAME .Nm VOP_LOCK , .Nm VOP_UNLOCK , .Nm VOP_ISLOCKED , .Nm vn_lock .Nd serialize access to a vnode .Sh SYNOPSIS .In sys/param.h .In sys/lock.h .In sys/vnode.h .Ft int .Fn VOP_LOCK "struct vnode *vp" "int flags" .Ft int .Fn VOP_UNLOCK "struct vnode *vp" "int flags" .Ft int .Fn VOP_ISLOCKED "struct vnode *vp" .Ft int .Fn vn_lock "struct vnode *vp" "int flags" .Sh DESCRIPTION These calls are used to serialize access to the file system, such as to prevent two writes to the same file from happening at the same time. .Pp The arguments are: .Bl -tag -width flags .It Fa vp The vnode being locked or unlocked. .It Fa flags One of the lock request types: .Pp .Bl -tag -width ".Dv LK_CANRECURSE" -offset indent -compact .It Dv LK_SHARED Shared lock. .It Dv LK_EXCLUSIVE Exclusive lock. .It Dv LK_UPGRADE Shared-to-exclusive upgrade. .It Dv LK_DOWNGRADE Exclusive-to-shared downgrade. .It Dv LK_RELEASE Release any type of lock. .It Dv LK_DRAIN Wait for all lock activity to end. .El .Pp The lock type may be .Em or Ns 'ed with these lock flags: .Pp .Bl -tag -width ".Dv LK_CANRECURSE" -offset indent -compact .It Dv LK_NOWAIT Do not sleep to wait for lock. .It Dv LK_SLEEPFAIL Sleep, then return failure. .It Dv LK_CANRECURSE Allow recursive exclusive lock. .It Dv LK_NOWITNESS Instruct .Xr witness 4 to ignore this instance. .El .Pp The lock type may be .Em or Ns 'ed with these control flags: .Pp .Bl -tag -width ".Dv LK_CANRECURSE" -offset indent -compact .It Dv LK_INTERLOCK Specify when the caller already has a simple lock -.Fn ( VOP_LOCK -will unlock the simple lock after getting the lock). +.Po Fn VOP_LOCK +will unlock the simple lock after getting the lock +.Pc . .It Dv LK_RETRY Retry until locked. .El .Pp Kernel code should use .Fn vn_lock to lock a vnode rather than calling .Fn VOP_LOCK directly. .Fn vn_lock also does not want a thread specified as argument but it assumes curthread to be used. .El .Sh RETURN VALUES Zero is returned on success, otherwise an error is returned. .Sh SEE ALSO .Xr vnode 9 .Sh AUTHORS This manual page was written by .An Doug Rabson . Index: projects/sendfile/share/man/man9/VOP_VPTOCNP.9 =================================================================== --- projects/sendfile/share/man/man9/VOP_VPTOCNP.9 (revision 276056) +++ projects/sendfile/share/man/man9/VOP_VPTOCNP.9 (revision 276057) @@ -1,92 +1,92 @@ .\" -*- nroff -*- .\" .\" Copyright (c) 2008 Joe Marcus Clarke .\" .\" All rights reserved. .\" .\" This program is free software. .\" .\" 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 DEVELOPERS ``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 DEVELOPERS 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$ .\" .Dd November 19, 2011 .Dt VOP_VPTOCNP 9 .Os .Sh NAME .Nm VOP_VPTOCNP .Nd translate a vnode to its component name .Sh SYNOPSIS .In sys/param.h .In sys/vnode.h .Ft int .Fn VOP_VPTOCNP "struct vnode *vp" "struct vnode **dvp" "char *buf" "int *buflen" .Sh DESCRIPTION This translates a vnode into its component name, and writes that name to the head of the buffer specified by .Fa buf . .Bl -tag -width buflen .It Fa vp The vnode to translate. .It Fa dvp The vnode of the parent directory of .Fa vp . .It Fa buf The buffer into which to prepend the component name. .It Fa buflen The remaining size of the buffer. .El .Pp The default implementation of .Nm scans through .Fa vp Ns 's parent directory looking for a dirent with a matching file number. If .Fa vp is not a directory, then .Nm returns ENOENT. .Sh LOCKS The vnode should be locked on entry and will still be locked on exit. The parent directory vnode will be unlocked on a successful exit. However, it will have its use count incremented. .Sh RETURN VALUES Zero is returned on success, otherwise an error code is returned. .Sh ERRORS .Bl -tag -width Er .It Bq Er ENOMEM The buffer was not large enough to hold the vnode's component name. .It Bq Er ENOENT The vnode was not found on the file system. .El .Sh SEE ALSO -.Xr VOP_LOOKUP 9 , -.Xr vnode 9 +.Xr vnode 9 , +.Xr VOP_LOOKUP 9 .Sh NOTES This interface is a work in progress. .Sh HISTORY The function .Nm appeared in .Fx 8.0 . .Sh AUTHORS This manual page was written by .An Joe Marcus Clarke . Index: projects/sendfile/share/man/man9/accf_data.9 =================================================================== --- projects/sendfile/share/man/man9/accf_data.9 (revision 276056) +++ projects/sendfile/share/man/man9/accf_data.9 (revision 276057) @@ -1,78 +1,78 @@ .\" .\" Copyright (c) 2000 Alfred Perlstein .\" .\" 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 DEVELOPERS ``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 DEVELOPERS 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$ .\" " .Dd November 15, 2000 .Dt ACCF_DATA 9 .Os .Sh NAME .Nm accf_data .Nd buffer incoming connections until data arrives .Sh SYNOPSIS .Nm options INET .Nm options ACCEPT_FILTER_DATA .Nm kldload accf_data .Sh DESCRIPTION This is a filter to be placed on a socket that will be using .Fn accept to receive incoming connections. .Pp It prevents the application from receiving the connected descriptor via .Fn accept until data arrives on the connection. .Pp The .Fa ACCEPT_FILTER_DATA kernel option is also a module that can be enabled at runtime via .Xr kldload 8 if the INET option has been compiled into the kernel. .Sh EXAMPLES Assuming ACCEPT_FILTER_DATA has been included in the kernel config file or the .Nm module has been loaded, this will enable the data accept filter on the socket .Fa sok . .Bd -literal -offset 0i struct accept_filter_arg afa; bzero(&afa, sizeof(afa)); strcpy(afa.af_name, "dataready"); setsockopt(sok, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)); .Ed .Sh SEE ALSO .Xr setsockopt 2 , .Xr accept_filter 9 , -.Xr accf_dns 9 +.Xr accf_dns 9 , .Xr accf_http 9 .Sh HISTORY The accept filter mechanism and the accf_data filter were introduced in .Fx 4.0 . .Sh AUTHORS This manual page and the filter were written by .An Alfred Perlstein . Index: projects/sendfile/share/man/man9/accf_dns.9 =================================================================== --- projects/sendfile/share/man/man9/accf_dns.9 (revision 276056) +++ projects/sendfile/share/man/man9/accf_dns.9 (revision 276057) @@ -1,79 +1,79 @@ .\" .\" Copyright (c) 2008 David Malone .\" .\" 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 DEVELOPERS ``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 DEVELOPERS 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$ .\" " .Dd July 16, 2008 .Dt ACCF_DNS 9 .Os .Sh NAME .Nm accf_dns .Nd buffer incoming DNS requests until the whole first request is present .Sh SYNOPSIS .Nm options INET .Nm options ACCEPT_FILTER_DNS .Nm kldload accf_dns .Sh DESCRIPTION This is a filter to be placed on a socket that will be using .Fn accept to receive incoming connections. .Pp It prevents the application from receiving the connected descriptor via .Fn accept until a whole DNS request is available on the socket. It does this by reading the first two bytes of the request, to determine its size, and waiting until the required amount of data is available to be read. .Pp The .Fa ACCEPT_FILTER_DNS kernel option is also a module that can be enabled at runtime via .Xr kldload 8 if the INET option has been compiled into the kernel. .Sh EXAMPLES If the .Nm module is available in the kernel, the following code will enable the DNS accept filter on a socket .Fa sok . .Bd -literal -offset 0i struct accept_filter_arg afa; bzero(&afa, sizeof(afa)); strcpy(afa.af_name, "dnsready"); setsockopt(sok, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)); .Ed .Sh SEE ALSO .Xr setsockopt 2 , .Xr accept_filter 9 , +.Xr accf_data 9 , .Xr accf_http 9 -.Xr accf_data 9 .Sh HISTORY The accept filter mechanism was introduced in .Fx 4.0 . .Sh AUTHORS This manual page and the filter were written by .An David Malone . Index: projects/sendfile/share/man/man9/acl.9 =================================================================== --- projects/sendfile/share/man/man9/acl.9 (revision 276056) +++ projects/sendfile/share/man/man9/acl.9 (revision 276057) @@ -1,219 +1,219 @@ .\"- .\" Copyright (c) 1999-2001 Robert N. M. Watson .\" 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$ .\" .Dd September 18, 2009 .Dt ACL 9 .Os .Sh NAME .Nm acl .Nd virtual file system access control lists .Sh SYNOPSIS .In sys/param.h .In sys/vnode.h .In sys/acl.h .Pp In the kernel configuration file: .Cd "options UFS_ACL" .Sh DESCRIPTION Access control lists, or ACLs, allow fine-grained specification of rights for vnodes representing files and directories. However, as there are a plethora of file systems with differing ACL semantics, the vnode interface is aware only of the syntax of ACLs, relying on the underlying file system to implement the details. Depending on the underlying file system, each file or directory may have zero or more ACLs associated with it, named using the .Fa type field of the appropriate vnode ACL calls: .Xr VOP_ACLCHECK 9 , .Xr VOP_GETACL 9 , and .Xr VOP_SETACL 9 . .Pp Currently, each ACL is represented in-kernel by a fixed-size .Vt acl structure, defined as follows: .Bd -literal -offset indent struct acl { unsigned int acl_maxcnt; unsigned int acl_cnt; int acl_spare[4]; struct acl_entry acl_entry[ACL_MAX_ENTRIES]; }; .Ed .Pp An ACL is constructed from a fixed size array of ACL entries, each of which consists of a set of permissions, principal namespace, and principal identifier. In this implementation, the .Vt acl_maxcnt field is always set to .Dv ACL_MAX_ENTRIES . .Pp Each individual ACL entry is of the type .Vt acl_entry_t , which is a structure with the following members: .Bl -tag -width 2n .It Vt acl_tag_t Va ae_tag The following is a list of definitions of ACL types to be set in .Va ae_tag : .Pp .Bl -tag -width ".Dv ACL_UNDEFINED_FIELD" -offset indent -compact .It Dv ACL_UNDEFINED_FIELD Undefined ACL type. .It Dv ACL_USER_OBJ Discretionary access rights for processes whose effective user ID matches the user ID of the file's owner. .It Dv ACL_USER Discretionary access rights for processes whose effective user ID matches the ACL entry qualifier. .It Dv ACL_GROUP_OBJ Discretionary access rights for processes whose effective group ID or any supplemental groups match the group ID of the file's owner. .It Dv ACL_GROUP Discretionary access rights for processes whose effective group ID or any supplemental groups match the ACL entry qualifier. .It Dv ACL_MASK The maximum discretionary access rights that can be granted to a process in the file group class. This is only valid for POSIX.1e ACLs. .It Dv ACL_OTHER Discretionary access rights for processes not covered by any other ACL entry. This is only valid for POSIX.1e ACLs. .It Dv ACL_OTHER_OBJ Same as .Dv ACL_OTHER . .It Dv ACL_EVERYONE Discretionary access rights for all users. This is only valid for NFSv4 ACLs. .El .Pp Each POSIX.1e ACL must contain exactly one .Dv ACL_USER_OBJ , one .Dv ACL_GROUP_OBJ , and one .Dv ACL_OTHER . If any of .Dv ACL_USER , .Dv ACL_GROUP , or .Dv ACL_OTHER are present, then exactly one .Dv ACL_MASK entry should be present. .It Vt uid_t Va ae_id The ID of user for whom this ACL describes access permissions. For entries other than .Dv ACL_USER and .Dv ACL_GROUP , this field should be set to .Dv ACL_UNDEFINED_ID . .It Vt acl_perm_t Va ae_perm This field defines what kind of access the process matching this ACL has for accessing the associated file. For POSIX.1e ACLs, the following are valid: .Bl -tag -width ".Dv ACL_WRITE_NAMED_ATTRS" .It Dv ACL_EXECUTE The process may execute the associated file. .It Dv ACL_WRITE The process may write to the associated file. .It Dv ACL_READ The process may read from the associated file. .It Dv ACL_PERM_NONE The process has no read, write or execute permissions to the associated file. .El .Pp For NFSv4 ACLs, the following are valid: .Bl -tag -width ".Dv ACL_WRITE_NAMED_ATTRS" .It Dv ACL_READ_DATA The process may read from the associated file. .It Dv ACL_LIST_DIRECTORY Same as .Dv ACL_READ_DATA . .It Dv ACL_WRITE_DATA The process may write to the associated file. .It Dv ACL_ADD_FILE Same as .Dv ACL_ACL_WRITE_DATA . .It Dv ACL_APPEND_DATA .It Dv ACL_ADD_SUBDIRECTORY Same as .Dv ACL_APPEND_DATA . .It Dv ACL_READ_NAMED_ATTRS Ignored. .It Dv ACL_WRITE_NAMED_ATTRS Ignored. .It Dv ACL_EXECUTE The process may execute the associated file. .It Dv ACL_DELETE_CHILD .It Dv ACL_READ_ATTRIBUTES .It Dv ACL_WRITE_ATTRIBUTES .It Dv ACL_DELETE .It Dv ACL_READ_ACL .It Dv ACL_WRITE_ACL .It Dv ACL_WRITE_OWNER .It Dv ACL_SYNCHRONIZE Ignored. .El .It Vt acl_entry_type_t Va ae_entry_type This field defines the type of NFSv4 ACL entry. It is not used with POSIX.1e ACLs. The following values are valid: .Bl -tag -width ".Dv ACL_WRITE_NAMED_ATTRS" .It Dv ACL_ENTRY_TYPE_ALLOW .It Dv ACL_ENTRY_TYPE_DENY .El .It Vt acl_flag_t Va ae_flags This field defines the inheritance flags of NFSv4 ACL entry. It is not used with POSIX.1e ACLs. The following values are valid: .Bl -tag -width ".Dv ACL_ENTRY_DIRECTORY_INHERIT" .It Dv ACL_ENTRY_FILE_INHERIT .It Dv ACL_ENTRY_DIRECTORY_INHERIT .It Dv ACL_ENTRY_NO_PROPAGATE_INHERIT .It Dv ACL_ENTRY_INHERIT_ONLY .El .El .Sh SEE ALSO .Xr acl 3 , +.Xr vaccess 9 , .Xr vaccess_acl_nfs4 9 , .Xr vaccess_acl_posix1e 9 , .Xr VFS 9 , -.Xr vaccess 9 , .Xr VOP_ACLCHECK 9 , .Xr VOP_GETACL 9 , .Xr VOP_SETACL 9 .Sh AUTHORS This manual page was written by .An Robert Watson . Index: projects/sendfile/share/man/man9/alq.9 =================================================================== --- projects/sendfile/share/man/man9/alq.9 (revision 276056) +++ projects/sendfile/share/man/man9/alq.9 (revision 276057) @@ -1,441 +1,441 @@ .\" .\" Copyright (c) 2003 Hiten Pandya .\" Copyright (c) 2009-2010 The FreeBSD Foundation .\" All rights reserved. .\" .\" Portions of this software were developed at the Centre for Advanced .\" Internet Architectures, Swinburne University of Technology, Melbourne, .\" Australia by Lawrence Stewart under sponsorship from the FreeBSD .\" Foundation. .\" .\" 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, .\" without modification, immediately at the beginning of the file. .\" 2. The name of the author may not be used to endorse or promote products .\" derived from this software without specific prior written permission. .\" .\" 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$ .\" .Dd April 26, 2010 .Dt ALQ 9 .Os .Sh NAME .Nm alq , .Nm alq_open_flags , .Nm alq_open , .Nm alq_writen , .Nm alq_write , .Nm alq_flush , .Nm alq_close , .Nm alq_getn , .Nm alq_get , .Nm alq_post_flags , .Nm alq_post .Nd Asynchronous Logging Queues .Sh SYNOPSIS .In sys/alq.h .Ft int .Fo alq_open_flags .Fa "struct alq **app" .Fa "const char *file" .Fa "struct ucred *cred" .Fa "int cmode" .Fa "int size" .Fa "int flags" .Fc .Ft int .Fo alq_open .Fa "struct alq **app" .Fa "const char *file" .Fa "struct ucred *cred" .Fa "int cmode" .Fa "int size" .Fa "int count" .Fc .Ft int .Fn alq_writen "struct alq *alq" "void *data" "int len" "int flags" .Ft int .Fn alq_write "struct alq *alq" "void *data" "int flags" .Ft void .Fn alq_flush "struct alq *alq" .Ft void .Fn alq_close "struct alq *alq" .Ft struct ale * .Fn alq_getn "struct alq *alq" "int len" "int flags" .Ft struct ale * .Fn alq_get "struct alq *alq" "int flags" .Ft void .Fn alq_post_flags "struct alq *alq" "struct ale *ale" "int flags" .Ft void .Fn alq_post "struct alq *alq" "struct ale *ale" .Sh DESCRIPTION The .Nm facility provides an asynchronous fixed or variable length recording mechanism, known as Asynchronous Logging Queues. It can record to any .Xr vnode 9 , thus providing the ability to journal logs to character devices as well as regular files. All functions accept a .Vt "struct alq" argument, which is an opaque type that maintains state information for an Asynchronous Logging Queue. The logging facility runs in a separate kernel thread, which services all log entry requests. .Pp An .Dq asynchronous log entry is defined as .Vt "struct ale" , which has the following members: .Bd -literal -offset indent struct ale { intptr_t ae_bytesused; /* # bytes written to ALE. */ char *ae_data; /* Write ptr. */ int ae_pad; /* Unused, compat. */ }; .Ed .Pp An .Nm can be created in either fixed or variable length mode. A variable length .Nm accommodates writes of varying length using .Fn alq_writen and .Fn alq_getn . A fixed length .Nm accommodates a fixed number of writes using .Fn alq_write and .Fn alq_get , each of fixed size (set at queue creation time). Fixed length mode is deprecated in favour of variable length mode. .Sh FUNCTIONS The .Fn alq_open_flags function creates a new variable length asynchronous logging queue. The .Fa file argument is the name of the file to open for logging. If the file does not yet exist, .Fn alq_open will attempt to create it. The .Fa cmode argument will be passed to .Fn vn_open as the requested creation mode, to be used if the file will be created by .Fn alq_open . Consumers of this API may wish to pass .Dv ALQ_DEFAULT_CMODE , a default creation mode suitable for most applications. The .Fa cred argument specifies the credentials to use when opening and performing I/O on the file. The .Fa size argument sets the size (in bytes) of the underlying queue. The ALQ_ORDERED flag may be passed in via .Fa flags to indicate that the ordering of writer threads waiting for a busy .Nm to free up resources should be preserved. .Pp The deprecated .Fn alq_open function is implemented as a wrapper around .Fn alq_open_flags to provide backwards compatibility to consumers that have not been updated to utilise the newer .Fn alq_open_flags function. It passes all arguments through to .Fn alq_open_flags untouched except for .Fa size and .Fa count , and sets .Fa flags to 0. To create a variable length mode .Nm , the .Fa size argument should be set to the size (in bytes) of the underlying queue and the .Fa count argument should be set to 0. To create a fixed length mode .Nm , the .Fa size argument should be set to the size (in bytes) of each write and the .Fa count argument should be set to the number of .Fa size byte chunks to reserve capacity for. .Pp The .Fn alq_writen function writes .Fa len bytes from .Fa data to the designated variable length mode queue .Fa alq . If .Fn alq_writen could not write the entry immediately and .Dv ALQ_WAITOK is set in .Fa flags , the function will be allowed to .Xr msleep_spin 9 with the .Dq Li alqwnord or .Dq Li alqwnres wait message. A write will automatically schedule the queue .Fa alq to be flushed to disk. This behaviour can be controlled by passing ALQ_NOACTIVATE via .Fa flags to indicate that the write should not schedule .Fa alq to be flushed to disk. .Pp The deprecated .Fn alq_write function is implemented as a wrapper around .Fn alq_writen to provide backwards compatibility to consumers that have not been updated to utilise variable length mode queues. The function will write .Fa size bytes of data (where .Fa size was specified at queue creation time) from the .Fa data buffer to the .Fa alq . Note that it is an error to call .Fn alq_write on a variable length mode queue. .Pp The .Fn alq_flush function is used for flushing .Fa alq to the log medium that was passed to .Fn alq_open . If .Fa alq has data to flush and is not already in the process of being flushed, the function will block doing IO. Otherwise, the function will return immediately. .Pp The .Fn alq_close function will close the asynchronous logging queue .Fa alq and flush all pending write requests to the log medium. It will free all resources that were previously allocated. .Pp The .Fn alq_getn function returns an asynchronous log entry from .Fa alq , initialised to point at a buffer capable of receiving .Fa len bytes of data. This function leaves .Fa alq in a locked state, until a subsequent .Fn alq_post or .Fn alq_post_flags call is made. If .Fn alq_getn could not obtain .Fa len bytes of buffer immediately and .Dv ALQ_WAITOK is set in .Fa flags , the function will be allowed to .Xr msleep_spin 9 with the .Dq Li alqgnord or .Dq Li alqgnres wait message. The caller can choose to write less than .Fa len bytes of data to the returned asynchronous log entry by setting the entry's ae_bytesused field to the number of bytes actually written. This must be done prior to calling .Fn alq_post . .Pp The deprecated .Fn alq_get function is implemented as a wrapper around .Fn alq_getn to provide backwards compatibility to consumers that have not been updated to utilise variable length mode queues. The asynchronous log entry returned will be initialised to point at a buffer capable of receiving .Fa size bytes of data (where .Fa size was specified at queue creation time). Note that it is an error to call .Fn alq_get on a variable length mode queue. .Pp The .Fn alq_post_flags function schedules the asynchronous log entry .Fa ale (obtained from .Fn alq_getn or .Fn alq_get ) for writing to .Fa alq . The ALQ_NOACTIVATE flag may be passed in via .Fa flags to indicate that the queue should not be immediately scheduled to be flushed to disk. This function leaves .Fa alq in an unlocked state. .Pp The .Fn alq_post function is implemented as a wrapper around .Fn alq_post_flags to provide backwards compatibility to consumers that have not been updated to utilise the newer .Fn alq_post_flags function. It simply passes all arguments through to .Fn alq_post_flags untouched, and sets .Fa flags to 0. .Sh IMPLEMENTATION NOTES The .Fn alq_writen and .Fn alq_write functions both perform a .Xr bcopy 3 from the supplied .Fa data buffer into the underlying .Nm buffer. Performance critical code paths may wish to consider using .Fn alq_getn (variable length queues) or .Fn alq_get (fixed length queues) to avoid the extra memory copy. Note that a queue remains locked between calls to .Fn alq_getn or .Fn alq_get and .Fn alq_post or .Fn alq_post_flags , so this method of writing to a queue is unsuitable for situations where the time between calls may be substantial. .Sh LOCKING Each asynchronous logging queue is protected by a spin mutex. .Pp Functions .Fn alq_flush and .Fn alq_open may attempt to acquire an internal sleep mutex, and should consequently not be used in contexts where sleeping is not allowed. .Sh RETURN VALUES The .Fn alq_open function returns one of the error codes listed in .Xr open 2 , if it fails to open .Fa file , or else it returns 0. .Pp The .Fn alq_writen and .Fn alq_write functions return .Er EWOULDBLOCK if .Dv ALQ_NOWAIT was set in .Fa flags and either the queue is full or the system is shutting down. .Pp The .Fn alq_getn and .Fn alq_get functions return .Dv NULL if .Dv ALQ_NOWAIT was set in .Fa flags and either the queue is full or the system is shutting down. .Pp NOTE: invalid arguments to non-void functions will result in undefined behaviour. .Sh SEE ALSO +.Xr syslog 3 , .Xr kproc 9 , .Xr ktr 9 , .Xr msleep_spin 9 , -.Xr syslog 3 , .Xr vnode 9 .Sh HISTORY The Asynchronous Logging Queues (ALQ) facility first appeared in .Fx 5.0 . .Sh AUTHORS .An -nosplit The .Nm facility was written by .An Jeffrey Roberson Aq Mt jeff@FreeBSD.org and extended by .An Lawrence Stewart Aq Mt lstewart@freebsd.org . .Pp This manual page was written by .An Hiten Pandya Aq Mt hmp@FreeBSD.org and revised by .An Lawrence Stewart Aq Mt lstewart@freebsd.org . Index: projects/sendfile/share/man/man9/devfs_set_cdevpriv.9 =================================================================== --- projects/sendfile/share/man/man9/devfs_set_cdevpriv.9 (revision 276056) +++ projects/sendfile/share/man/man9/devfs_set_cdevpriv.9 (revision 276057) @@ -1,125 +1,125 @@ .\" Copyright (c) 2008 Konstantin Belousov .\" 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$ .\" .Dd August 15, 2012 .Dt DEVFS_CDEVPRIV 9 .Os .Sh NAME .Nm devfs_set_cdevpriv , .Nm devfs_get_cdevpriv , .Nm devfs_clear_cdevpriv .Nd manage per-open filedescriptor data for devices .Sh SYNOPSIS .In sys/param.h .In sys/conf.h .Bd -literal typedef void (*cdevpriv_dtr_t)(void *data); .Ed .Ft int .Fn devfs_get_cdevpriv "void **datap" .Ft int .Fn devfs_set_cdevpriv "void *priv" "cdevpriv_dtr_t dtr" .Ft void .Fn devfs_clear_cdevpriv "void" .Sh DESCRIPTION The .Fn devfs_xxx_cdevpriv family of functions allows the .Fa cdev driver methods to associate some driver-specific data with each user process .Xr open 2 of the device special file. Currently, functioning of these functions is restricted to the context of the .Fa cdevsw switch method calls performed as .Xr devfs 5 operations in response to system calls that use filedescriptors. .Pp The .Fn devfs_set_cdevpriv function associates a data pointed by .Va priv with current calling context (filedescriptor). The data may be retrieved later, possibly from another call performed on this filedescriptor, by the .Fn devfs_get_cdevpriv function. The .Fn devfs_clear_cdevpriv disassociates previously attached data from context. Immediately after .Fn devfs_clear_cdevpriv finished operating, the .Va dtr callback is called, with private data supplied .Va data argument. The .Fn devfs_clear_cdevpriv function will be also be called if the open callback function returns an error code. .Pp On the last filedescriptor close, system automatically arranges .Fn devfs_clear_cdevpriv call. .Pp If successful, the functions return 0. .Pp The function .Fn devfs_set_cdevpriv returns the following values on error: .Bl -tag -width Er .It Bq Er ENOENT The current call is not associated with some filedescriptor. .It Bq Er EBUSY The private driver data is already associated with current filedescriptor. .El .Pp The function .Fn devfs_get_cdevpriv returns the following values on error: .Bl -tag -width Er .It Bq Er EBADF The current call is not associated with some filedescriptor. .It Bq Er ENOENT The private driver data was not associated with current filedescriptor, or .Fn devfs_clear_cdevpriv was called. .El .Sh SEE ALSO -.Xr open 2 , .Xr close 2 , +.Xr open 2 , .Xr devfs 5 , .Xr kern_openat 9 .Sh HISTORY The .Fn devfs_cdevpriv family of functions first appeared in .Fx 7.1 . Index: projects/sendfile/share/man/man9/eventtimers.9 =================================================================== --- projects/sendfile/share/man/man9/eventtimers.9 (revision 276056) +++ projects/sendfile/share/man/man9/eventtimers.9 (revision 276057) @@ -1,253 +1,253 @@ .\" .\" Copyright (c) 2011-2013 Alexander Motin .\" 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 DEVELOPERS ``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 DEVELOPERS 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$ .\" .Dd April 2, 2014 .Dt EVENTTIMERS 9 .Os .Sh NAME .Nm eventtimers .Nd kernel event timers subsystem .Sh SYNOPSIS .In sys/timeet.h .Bd -literal struct eventtimer; typedef int et_start_t(struct eventtimer *et, sbintime_t first, sbintime_t period); typedef int et_stop_t(struct eventtimer *et); typedef void et_event_cb_t(struct eventtimer *et, void *arg); typedef int et_deregister_cb_t(struct eventtimer *et, void *arg); struct eventtimer { SLIST_ENTRY(eventtimer) et_all; char *et_name; int et_flags; #define ET_FLAGS_PERIODIC 1 #define ET_FLAGS_ONESHOT 2 #define ET_FLAGS_PERCPU 4 #define ET_FLAGS_C3STOP 8 #define ET_FLAGS_POW2DIV 16 int et_quality; int et_active; uint64_t et_frequency; sbintime_t et_min_period; sbintime_t et_max_period; et_start_t *et_start; et_stop_t *et_stop; et_event_cb_t *et_event_cb; et_deregister_cb_t *et_deregister_cb; void *et_arg; void *et_priv; struct sysctl_oid *et_sysctl; }; .Ed .Ft int .Fn et_register "struct eventtimer *et" .Ft int .Fn et_deregister "struct eventtimer *et" .Ft void .Fn et_change_frequency "struct eventtimer *et" "uint64_t newfreq" .Fn ET_LOCK .Fn ET_UNLOCK .Ft struct eventtimer * .Fn et_find "const char *name" "int check" "int want" .Ft int .Fn et_init "struct eventtimer *et" "et_event_cb_t *event" "et_deregister_cb_t *deregister" "void *arg" .Ft int .Fn et_start "struct eventtimer *et" "sbintime_t first" "sbintime_t period" .Ft int .Fn et_stop "struct eventtimer *et" .Ft int .Fn et_ban "struct eventtimer *et" .Ft int .Fn et_free "struct eventtimer *et" .Sh DESCRIPTION Event timers are responsible for generating interrupts at specified time or periodically, to run different time-based events. Subsystem consists of three main parts: .Bl -tag -width "Consumers" .It Drivers Manage hardware to generate requested time events. .It Consumers .Pa sys/kern/kern_clocksource.c uses event timers to supply kernel with .Fn hardclock , .Fn statclock and .Fn profclock time events. .It Glue code .Pa sys/sys/timeet.h , .Pa sys/kern/kern_et.c provide APIs for event timer drivers and consumers. .El .Sh DRIVER API Driver API is built around eventtimer structure. To register its functionality driver allocates that structure and calls .Fn et_register . Driver should fill following fields there: .Bl -tag -width Va .It Va et_name Unique name of the event timer for management purposes. .It Va et_flags Set of flags, describing timer capabilities: .Bl -tag -width "ET_FLAGS_PERIODIC" -compact .It ET_FLAGS_PERIODIC Periodic mode supported. .It ET_FLAGS_ONESHOT One-shot mode supported. .It ET_FLAGS_PERCPU Timer is per-CPU. .It ET_FLAGS_C3STOP Timer may stop in CPU sleep state. .It ET_FLAGS_POW2DIV Timer supports only 2^n divisors. .El .It Va et_quality Abstract value to certify whether this timecounter is better than the others. Higher value means better. .It Va et_frequency Timer oscillator's base frequency, if applicable and known. Used by consumers to predict set of possible frequencies that could be obtained by dividing it. Should be zero if not applicable or unknown. .It Va et_min_period , et_max_period Minimal and maximal reliably programmable time periods. .It Va et_start Driver's timer start function pointer. .It Va et_stop Driver's timer stop function pointer. .It Va et_priv Driver's private data storage. .El .Pp After the event timer functionality is registered, it is controlled via .Va et_start and .Va et_stop methods. .Va et_start method is called to start the specified event timer. The last two arguments are used to specify time when events should be generated. .Va first argument specifies time period before the first event generated. In periodic mode NULL value specifies that first period is equal to the .Va period argument value. .Va period argument specifies the time period between following events for the periodic mode. The NULL value there specifies the one-shot mode. At least one of these two arguments should be not NULL. When event time arrive, driver should call .Va et_event_cb callback function, passing .Va et_arg as the second argument. .Va et_stop method is called to stop the specified event timer. For the per-CPU event timers .Va et_start and .Va et_stop methods control timers associated with the current CPU. .Pp Driver may deregister its functionality by calling .Fn et_deregister . .Pp -If the frequency of the clock hardware can change while it is +If the frequency of the clock hardware can change while it is running (for example, during power-saving modes), the driver must call .Fn et_change_frequency on each change. If the given event timer is the active timer, .Fn et_change_frequency -stops the timer on all CPUs, updates +stops the timer on all CPUs, updates .Va et->frequency , then restarts the timer on all CPUs so that all current events are rescheduled using the new frequency. If the given timer is not currently active, .Fn et_change_frequency simply updates .Va et->frequency . .Sh CONSUMER API .Fn et_find allows consumer to find available event timer, optionally matching specific name and/or capability flags. Consumer may read returned eventtimer structure, but should not modify it. When wanted event timer is found, .Fn et_init should be called for it, submitting .Va event and optionally .Va deregister callbacks functions, and the opaque argument .Va arg . That argument will be passed as argument to the callbacks. Event callback function will be called on scheduled time events. It is called from the hardware interrupt context, so no sleep is permitted there. Deregister callback function may be called to report consumer that the event timer functionality is no longer available. On this call, consumer should stop using event timer before the return. .Pp After the timer is found and initialized, it can be controlled via .Fn et_start and .Fn et_stop . The arguments are the same as described in driver API. Per-CPU event timers can be controlled only from specific CPUs. .Pp .Fn et_ban allows consumer to mark event timer as broken via clearing both one-shot and periodic capability flags, if it was somehow detected. .Fn et_free is the opposite to .Fn et_init . It releases the event timer for other consumers use. .Pp .Fn ET_LOCK and .Fn ET_UNLOCK macros should be used to manage .Xr mutex 9 lock around .Fn et_find , .Fn et_init and .Fn et_free calls to serialize access to the list of the registered event timers and the pointers returned by .Fn et_find . .Fn et_start and .Fn et_stop calls should be serialized in consumer's internal way to avoid concurrent timer hardware access. .Sh SEE ALSO .Xr eventtimers 4 .Sh AUTHORS .An Alexander Motin Aq Mt mav@FreeBSD.org Index: projects/sendfile/share/man/man9/ieee80211_crypto.9 =================================================================== --- projects/sendfile/share/man/man9/ieee80211_crypto.9 (revision 276056) +++ projects/sendfile/share/man/man9/ieee80211_crypto.9 (revision 276057) @@ -1,260 +1,260 @@ .\" .\" Copyright (c) 2004 Bruce M. Simpson .\" Copyright (c) 2004 Darron Broad .\" 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$ .\" $Id: ieee80211_crypto.9,v 1.3 2004/03/04 10:42:56 bruce Exp $ .\" .Dd March 29, 2010 .Dt IEEE80211_CRYPTO 9 .Os .Sh NAME .Nm ieee80211_crypto .Nd 802.11 cryptographic support .Sh SYNOPSIS .In net80211/ieee80211_var.h .\" .Pp .Ft void .Fn ieee80211_crypto_register "const struct ieee80211_cipher *" .\" .Ft void .Fn ieee80211_crypto_unregister "const struct ieee80211_cipher *" .\" .Ft int .Fn ieee80211_crypto_available "int cipher" .\" .Pp .Ft void .Fo ieee80211_notify_replay_failure .Fa "struct ieee80211vap *" .Fa "const struct ieee80211_frame *" .Fa "const struct ieee80211_key *" .Fa "uint64_t rsc" .Fa "int tid" .Fc .\" .Ft void .Fo ieee80211_notify_michael_failure .Fa "struct ieee80211vap *" .Fa "const struct ieee80211_frame *" .Fa "u_int keyix" .Fc .\" .Ft int .Fo ieee80211_crypto_newkey .Fa "struct ieee80211vap *" .Fa "int cipher" .Fa "int flags" .Fa "struct ieee80211_key *" .Fc .\" .Ft int .Fn ieee80211_crypto_setkey "struct ieee80211vap *" "struct ieee80211_key *" .\" .Ft int .Fn ieee80211_crypto_delkey "struct ieee80211vap *" "struct ieee80211_key *" .\" .Ft void .Fn ieee80211_key_update_begin "struct ieee80211vap *" .\" .Ft void .Fn ieee80211_key_update_end "struct ieee80211vap *" .\" .Ft void .Fn ieee80211_crypto_delglobalkeys "struct ieee80211vap *" .\" .Ft void .Fn ieee80211_crypto_reload_keys "struct ieee80211com *" .\" .Pp .Ft struct ieee80211_key * .Fn ieee80211_crypto_encap "struct ieee80211_node *" "struct mbuf *" .\" .Ft struct ieee80211_key * .Fn ieee80211_crypto_decap "struct ieee80211_node *" "struct mbuf *" "int flags" .\" .Ft int .Fo ieee80211_crypto_demic .Fa "struct ieee80211vap *" .Fa "struct ieee80211_key *" .Fa "struct mbuf *" .Fa "int force" .Fc .\" .Ft int .Fo ieee80211_crypto_enmic .Fa "struct ieee80211vap *" .Fa "struct ieee80211_key *" .Fa "struct mbuf *" .Fa "int force" .Fc .Sh DESCRIPTION The .Nm net80211 layer includes comprehensive cryptographic support for 802.11 protocols. Software implementations of ciphers required by WPA and 802.11i are provided as well as encap/decap processing of 802.11 frames. Software ciphers are written as kernel modules and register with the core crypto support. The cryptographic framework supports hardware acceleration of ciphers by drivers with automatic fall-back to software implementations when a driver is unable to provide necessary hardware services. .Sh CRYPTO CIPHER MODULES .Nm net80211 cipher modules register their services using .Fn ieee80211_crypto_register and supply a template that describes their operation. This .Vt ieee80211_cipher structure defines protocol-related state such as the number of bytes of space in the 802.11 header to reserve/remove during encap/decap and entry points for setting up keys and doing cryptographic operations. .Pp Cipher modules can associate private state to each key through the .Vt wk_private structure member. If state is setup by the module it will be called before a key is destroyed so it can reclaim resources. .Pp Crypto modules can notify the system of two events. When a packet replay event is recognized .Fn ieee80211_notify_replay_failure can be used to signal the event. When a .Dv TKIP Michael failure is detected .Fn ieee80211_notify_michael_failure can be invoked. Drivers may also use these routines to signal events detected by the hardware. .Sh CRYPTO KEY MANAGEMENT The .Nm net80211 layer implements a per-vap 4-element .Dq global key table and a per-station .Dq unicast key for protocols such as WPA, 802.1x, and 802.11i. The global key table is designed to support legacy WEP operation and Multicast/Group keys, though some applications also use it to implement WPA in station mode. Keys in the global table are identified by a key index in the range 0-3. Per-station keys are identified by the MAC address of the station and are typically used for unicast PTK bindings. .Pp .Nm net80211 provides .Xr ioctl 2 operations for managing both global and per-station keys. Drivers typically do not participate in software key management; they are involved only when providing hardware acceleration of cryptographic operations. .Pp .Fn ieee80211_crypto_newkey is used to allocate a new .Nm net80211 key or reconfigure an existing key. The cipher must be specified along with any fixed key index. The .Nm net80211 layer will handle allocating cipher and driver resources to support the key. .Pp Once a key is allocated it's contents can be set using .Fn ieee80211_crypto_setkey and deleted with .Fn ieee80211_crypto_delkey (with any cipher and driver resources reclaimed). .Pp .Fn ieee80211_crypto_delglobalkeys is used to reclaim all keys in the global key table for a vap; it typically is used only within the .Nm net80211 layer. .Pp .Fn ieee80211_crypto_reload_keys handles hardware key state reloading from software key state, such as required after a suspend/resume cycle. .Sh DRIVER CRYPTO SUPPORT Drivers identify ciphers they have hardware support for through the .Vt ic_cryptocaps field of the .Vt ieee80211com structure. If hardware support is available then a driver should also fill in the .Dv iv_key_alloc , .Dv iv_key_set , and .Dv iv_key_delete methods of each .Vt ieee80211vap created for use with the device. In addition the methods .Dv iv_key_update_begin and .Dv iv_key_update_end can be setup to handle synchronization requirements for updating hardware key state. .Pp When .Nm net80211 allocates a software key and the driver can accelerate the cipher operations the .Dv iv_key_alloc method will be invoked. Drivers may return a token that is associated with outbound traffic (for use in encrypting frames). Otherwise, e.g. if hardware resources are not available, the driver will not return a token and .Nm net80211 will arrange to do the work in software and pass frames to the driver that are already prepared for transmission. .Pp For receive, drivers mark frames with the .Dv M_WEP mbuf flag to indicate the hardware has decrypted the payload. If frames have the .Dv IEEE80211_FC1_PROTECTED bit marked in their 802.11 header and are not tagged with .Dv M_WEP then decryption is done in software. For more complicated scenarios the software key state is consulted; e.g. to decide if Michael verification needs to be done in software after the hardware has handled TKIP decryption. .Pp Drivers that manage complicated key data structures, e.g. faulting software keys into a hardware key cache, can safely manipulate software key state by bracketing their work with calls to .Fn ieee80211_key_update_begin and .Fn ieee80211_key_update_end . These calls also synchronize hardware key state update when receive traffic is active. .Sh SEE ALSO -.Xr ieee80211 9 , .Xr ioctl 2 , .Xr wlan_ccmp 4 , .Xr wlan_tkip 4 , -.Xr wlan_wep 4 +.Xr wlan_wep 4 , +.Xr ieee80211 9 Index: projects/sendfile/share/man/man9/ifnet.9 =================================================================== --- projects/sendfile/share/man/man9/ifnet.9 (revision 276056) +++ projects/sendfile/share/man/man9/ifnet.9 (revision 276057) @@ -1,1529 +1,1530 @@ .\" -*- Nroff -*- .\" Copyright 1996, 1997 Massachusetts Institute of Technology .\" .\" Permission to use, copy, modify, and distribute this software and .\" its documentation for any purpose and without fee is hereby .\" granted, provided that both the above copyright notice and this .\" permission notice appear in all copies, that both the above .\" copyright notice and this permission notice appear in all .\" supporting documentation, and that the name of M.I.T. not be used .\" in advertising or publicity pertaining to distribution of the .\" software without specific, written prior permission. M.I.T. makes .\" no representations about the suitability of this software for any .\" purpose. It is provided "as is" without express or implied .\" warranty. .\" .\" THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS .\" ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, .\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT .\" SHALL M.I.T. 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$ .\" .Dd July 29, 2014 .Dt IFNET 9 .Os .Sh NAME .Nm ifnet , .Nm ifaddr , .Nm ifqueue , .Nm if_data .Nd kernel interfaces for manipulating network interfaces .Sh SYNOPSIS .In sys/param.h .In sys/time.h .In sys/socket.h .In net/if.h .In net/if_var.h .In net/if_types.h .\" .Ss "Interface Manipulation Functions" .Ft "struct ifnet *" .Fn if_alloc "u_char type" .Ft void .Fn if_attach "struct ifnet *ifp" .Ft void .Fn if_detach "struct ifnet *ifp" .Ft void .Fn if_free "struct ifnet *ifp" .Ft void .Fn if_free_type "struct ifnet *ifp" "u_char type" .Ft void .Fn if_down "struct ifnet *ifp" .Ft int .Fn ifioctl "struct socket *so" "u_long cmd" "caddr_t data" "struct thread *td" .Ft int .Fn ifpromisc "struct ifnet *ifp" "int pswitch" .Ft int .Fn if_allmulti "struct ifnet *ifp" "int amswitch" .Ft "struct ifnet *" .Fn ifunit "const char *name" .Ft "struct ifnet *" .Fn ifunit_ref "const char *name" .Ft void .Fn if_up "struct ifnet *ifp" .\" .Ss "Interface Address Functions" .Ft "struct ifaddr *" .Fn ifaddr_byindex "u_short idx" .Ft "struct ifaddr *" .Fn ifa_ifwithaddr "struct sockaddr *addr" .Ft "struct ifaddr *" .Fn ifa_ifwithdstaddr "struct sockaddr *addr" "int fib" .Ft "struct ifaddr *" .Fn ifa_ifwithnet "struct sockaddr *addr" "int ignore_ptp" "int fib" .Ft "struct ifaddr *" .Fn ifaof_ifpforaddr "struct sockaddr *addr" "struct ifnet *ifp" .Ft void .Fn ifa_ref "struct ifaddr *ifa" .Ft void .Fn ifa_free "struct ifaddr *ifa" .\" .Ss "Interface Multicast Address Functions" .Ft int .Fn if_addmulti "struct ifnet *ifp" "struct sockaddr *sa" "struct ifmultiaddr **ifmap" .Ft int .Fn if_delmulti "struct ifnet *ifp" "struct sockaddr *sa" .Ft "struct ifmultiaddr *" .Fn if_findmulti "struct ifnet *ifp" "struct sockaddr *sa" .Ss "Output queue macros" .Fn IF_DEQUEUE "struct ifqueue *ifq" "struct mbuf *m" .\" .Ss "struct ifnet Member Functions" .Ft void .Fn \*(lp*if_input\*(rp "struct ifnet *ifp" "struct mbuf *m" .Ft int .Fo \*(lp*if_output\*(rp .Fa "struct ifnet *ifp" "struct mbuf *m" .Fa "const struct sockaddr *dst" "struct route *ro" .Fc .Ft void .Fn \*(lp*if_start\*(rp "struct ifnet *ifp" .Ft int .Fn \*(lp*if_transmit\*(rp "struct ifnet *ifp" "struct mbuf *m" .Ft void .Fn \*(lp*if_qflush\*(rp "struct ifnet *ifp" .Ft int .Fn \*(lp*if_ioctl\*(rp "struct ifnet *ifp" "u_long cmd" "caddr_t data" .Ft void .Fn \*(lp*if_init\*(rp "void *if_softc" .Ft int .Fo \*(lp*if_resolvemulti\*(rp .Fa "struct ifnet *ifp" "struct sockaddr **retsa" "struct sockaddr *addr" .Fc .Ss "struct ifaddr member function" .Ft void .Fo \*(lp*ifa_rtrequest\*(rp .Fa "int cmd" "struct rtentry *rt" "struct rt_addrinfo *info" .Fc .\" .Ss "Global Variables" .Vt extern struct ifnethead ifnet ; .\" extern struct ifindex_entry *ifindex_table ; .Vt extern int if_index ; .Vt extern int ifqmaxlen ; .Sh DATA STRUCTURES The kernel mechanisms for handling network interfaces reside primarily in the .Vt ifnet , if_data , ifaddr , and .Vt ifmultiaddr structures in .In net/if.h and .In net/if_var.h and the functions named above and defined in .Pa /sys/net/if.c . Those interfaces which are intended to be used by user programs are defined in .In net/if.h ; these include the interface flags, the .Vt if_data structure, and the structures defining the appearance of interface-related messages on the .Xr route 4 routing socket and in .Xr sysctl 3 . The header file .In net/if_var.h defines the kernel-internal interfaces, including the .Vt ifnet , ifaddr , and .Vt ifmultiaddr structures and the functions which manipulate them. (A few user programs will need .In net/if_var.h because it is the prerequisite of some other header file like .In netinet/if_ether.h . Most references to those two files in particular can be replaced by .In net/ethernet.h . ) .Pp The system keeps a linked list of interfaces using the .Li TAILQ macros defined in .Xr queue 3 ; this list is headed by a .Vt "struct ifnethead" called .Va ifnet . The elements of this list are of type .Vt "struct ifnet" , and most kernel routines which manipulate interface as such accept or return pointers to these structures. Each interface structure contains an .Vt if_data structure used for statistics and information. Each interface also has a .Li TAILQ of interface addresses, described by .Vt ifaddr structures. An .Dv AF_LINK address (see .Xr link_addr 3 ) describing the link layer implemented by the interface (if any) is accessed by the .Fn ifaddr_byindex function or .Va if_addr structure. (Some trivial interfaces do not provide any link layer addresses; this structure, while still present, serves only to identify the interface name and index.) .Pp Finally, those interfaces supporting reception of multicast datagrams have a .Li TAILQ of multicast group memberships, described by .Vt ifmultiaddr structures. These memberships are reference-counted. .Pp Interfaces are also associated with an output queue, defined as a .Vt "struct ifqueue" ; this structure is used to hold packets while the interface is in the process of sending another. .Pp .Ss The Vt ifnet Ss structure The fields of .Vt "struct ifnet" are as follows: .Bl -tag -width ".Va if_capabilities" -offset indent .It Va if_softc .Pq Vt "void *" A pointer to the driver's private state block. (Initialized by driver.) .It Va if_l2com .Pq Vt "void *" A pointer to the common data for the interface's layer 2 protocol. (Initialized by .Fn if_alloc . ) .It Va if_vnet .Pq Vt "struct vnet *" A pointer to the virtual network stack instance. (Initialized by .Fn if_attach . ) .It Va if_home_vnet .Pq Vt "struct vnet *" A pointer to the parent virtual network stack, where this .Vt "struct ifnet" originates from. (Initialized by .Fn if_attach . ) .It Va if_link .Pq Fn TAILQ_ENTRY ifnet .Xr queue 3 macro glue. .It Va if_xname .Pq Vt "char *" The name of the interface, (e.g., .Dq Li fxp0 or .Dq Li lo0 ) . (Initialized by driver (usually via .Fn if_initname ) . ) .It Va if_dname .Pq Vt "const char *" The name of the driver. (Initialized by driver (usually via .Fn if_initname ) . ) .It Va if_dunit .Pq Vt int A unique number assigned to each interface managed by a particular driver. Drivers may choose to set this to .Dv IF_DUNIT_NONE if a unit number is not associated with the device. (Initialized by driver (usually via .Fn if_initname ) . ) .It Va if_refcount .Pq Vt u_int The reference count. (Initialized by .Fn if_alloc . ) .It Va if_addrhead .Pq Vt "struct ifaddrhead" The head of the .Xr queue 3 .Li TAILQ containing the list of addresses assigned to this interface. .It Va if_pcount .Pq Vt int A count of promiscuous listeners on this interface, used to reference-count the .Dv IFF_PROMISC flag. .It Va if_carp .Pq Vt "struct carp_if *" A pointer to the CARP interface structure, .Xr carp 4 . (Initialized by the driver-specific .Fn if_ioctl routine.) .It Va if_bpf .Pq Vt "struct bpf_if *" Opaque per-interface data for the packet filter, .Xr bpf 4 . (Initialized by .Fn bpf_attach . ) .It Va if_index .Pq Vt u_short A unique number assigned to each interface in sequence as it is attached. This number can be used in a .Vt "struct sockaddr_dl" to refer to a particular interface by index (see .Xr link_addr 3 ) . (Initialized by .Fn if_alloc . ) .It Va if_vlantrunk .Pq Vt struct ifvlantrunk * A pointer to 802.1Q trunk structure, .Xr vlan 4 . (Initialized by the driver-specific .Fn if_ioctl routine.) .It Va if_flags .Pq Vt int Flags describing operational parameters of this interface (see below). (Manipulated by generic code.) .It Va if_drv_flags .Pq Vt int Flags describing operational status of this interface (see below). (Manipulated by driver.) .It Va if_capabilities .Pq Vt int Flags describing the capabilities the interface supports (see below). .It Va if_capenable .Pq Vt int Flags describing the enabled capabilities of the interface (see below). .It Va if_linkmib .Pq Vt "void *" A pointer to an interface-specific MIB structure exported by .Xr ifmib 4 . (Initialized by driver.) .It Va if_linkmiblen .Pq Vt size_t The size of said structure. (Initialized by driver.) .It Va if_data .Pq Vt "struct if_data" More statistics and information; see .Sx "The if_data structure" , below. (Initialized by driver, manipulated by both driver and generic code.) .It Va if_multiaddrs .Pq Vt struct ifmultihead The head of the .Xr queue 3 .Li TAILQ containing the list of multicast addresses assigned to this interface. .It Va if_amcount .Pq Vt int A number of multicast requests on this interface, used to reference-count the .Dv IFF_ALLMULTI flag. .It Va if_addr .Pq Vt "struct ifaddr *" A pointer to the link-level interface address. (Initialized by .Fn if_alloc . ) .\" .It Va if_llsoftc .\" .Pq Vt "void *" .\" The purpose of the field is unclear. .It Va if_snd .Pq Vt "struct ifaltq" The output queue. (Manipulated by driver.) .It Va if_broadcastaddr .Pq Vt "const u_int8_t *" A link-level broadcast bytestring for protocols with variable address length. .It Va if_bridge .Pq Vt "void *" A pointer to the bridge interface structure, .Xr if_bridge 4 . (Initialized by the driver-specific .Fn if_ioctl routine.) .It Va if_label .Pq Vt "struct label *" A pointer to the MAC Framework label structure, .Xr mac 4 . (Initialized by .Fn if_alloc . ) .It Va if_afdata .Pq Vt "void *" An address family dependent data region. .It Va if_afdata_initialized .Pq Vt int Used to track the current state of address family initialization. .It Va if_afdata_lock .Pq Vt "struct rwlock" An .Xr rwlock 9 lock used to protect .Va if_afdata internals. .It Va if_linktask .Pq Vt "struct task" A .Xr taskqueue 9 task scheduled for link state change events of the interface. .It Va if_addr_lock .Pq Vt "struct rwlock" An .Xr rwlock 9 lock used to protect interface-related address lists. .It Va if_clones .Pq Fn LIST_ENTRY ifnet .Xr queue 3 macro glue for the list of clonable network interfaces. .It Va if_groups -.Pq Fn TAILQ_HEAD ", ifg_list" +.Pq Fn TAILQ_HEAD "" "ifg_list" The head of the .Xr queue 3 .Li TAILQ containing the list of groups per interface. .It Va if_pf_kif .Pq Vt "void *" A pointer to the structure used for interface abstraction by .Xr pf 4 . .It Va if_lagg .Pq Vt "void *" A pointer to the .Xr lagg 4 interface structure. .It Va if_alloctype .Pq Vt u_char The type of the interface as it was at the time of its allocation. It is used to cache the type passed to .Fn if_alloc , but unlike .Va if_type , it would not be changed by drivers. .El .Pp References to .Vt ifnet structures are gained by calling the .Fn if_ref function and released by calling the .Fn if_rele function. They are used to allow kernel code walking global interface lists to release the .Vt ifnet lock yet keep the .Vt ifnet structure stable. .Pp There are in addition a number of function pointers which the driver must initialize to complete its interface with the generic interface layer: .Bl -ohang -offset indent .It Fn if_input Pass a packet to an appropriate upper layer as determined from the link-layer header of the packet. This routine is to be called from an interrupt handler or used to emulate reception of a packet on this interface. A single function implementing .Fn if_input can be shared among multiple drivers utilizing the same link-layer framing, e.g., Ethernet. .It Fn if_output Output a packet on interface .Fa ifp , or queue it on the output queue if the interface is already active. .It Fn if_transmit Transmit a packet on an interface or queue it if the interface is in use. This function will return .Dv ENOBUFS if the devices software and hardware queues are both full. This function must be installed after .Fn if_attach to override the default implementation. This function is exposed in order to allow drivers to manage their own queues and to reduce the latency caused by a frequently gratuitous enqueue / dequeue pair to ifq. The suggested internal software queueing mechanism is buf_ring. .It Fn if_qflush Free mbufs in internally managed queues when the interface is marked down. This function must be installed after .Fn if_attach to override the default implementation. This function is exposed in order to allow drivers to manage their own queues and to reduce the latency caused by a frequently gratuitous enqueue / dequeue pair to ifq. The suggested internal software queueing mechanism is buf_ring. .It Fn if_start Start queued output on an interface. This function is exposed in order to provide for some interface classes to share a .Fn if_output among all drivers. .Fn if_start may only be called when the .Dv IFF_DRV_OACTIVE flag is not set. (Thus, .Dv IFF_DRV_OACTIVE does not literally mean that output is active, but rather that the device's internal output queue is full.) Please note that this function will soon be deprecated. .It Fn if_ioctl Process interface-related .Xr ioctl 2 requests (defined in .In sys/sockio.h ) . Preliminary processing is done by the generic routine .Fn ifioctl to check for appropriate privileges, locate the interface being manipulated, and perform certain generic operations like twiddling flags and flushing queues. See the description of .Fn ifioctl below for more information. .It Fn if_init Initialize and bring up the hardware, e.g., reset the chip and enable the receiver unit. Should mark the interface running, but not active .Dv ( IFF_DRV_RUNNING , ~IIF_DRV_OACTIVE ) . .It Fn if_resolvemulti Check the requested multicast group membership, .Fa addr , for validity, and if necessary compute a link-layer group which corresponds to that address which is returned in .Fa *retsa . Returns zero on success, or an error code on failure. .El .Ss "Interface Flags" Interface flags are used for a number of different purposes. Some flags simply indicate information about the type of interface and its capabilities; others are dynamically manipulated to reflect the current state of the interface. Flags of the former kind are marked .Aq S in this table; the latter are marked .Aq D . Flags which begin with .Dq IFF_DRV_ are stored in .Va if_drv_flags ; all other flags are stored in .Va if_flags . .Pp The macro .Dv IFF_CANTCHANGE defines the bits which cannot be set by a user program using the .Dv SIOCSIFFLAGS command to .Xr ioctl 2 ; these are indicated by an asterisk .Pq Ql * in the following listing. .Pp .Bl -tag -width ".Dv IFF_POINTOPOINT" -offset indent -compact .It Dv IFF_UP .Aq D The interface has been configured up by the user-level code. .It Dv IFF_BROADCAST .Aq S* The interface supports broadcast. .It Dv IFF_DEBUG .Aq D Used to enable/disable driver debugging code. .It Dv IFF_LOOPBACK .Aq S The interface is a loopback device. .It Dv IFF_POINTOPOINT .Aq S* The interface is point-to-point; .Dq broadcast address is actually the address of the other end. .It Dv IFF_DRV_RUNNING .Aq D* The interface has been configured and dynamic resources were successfully allocated. Probably only useful internal to the interface. .It Dv IFF_NOARP .Aq D Disable network address resolution on this interface. .It Dv IFF_PROMISC .Aq D* This interface is in promiscuous mode. .It Dv IFF_PPROMISC .Aq D This interface is in the permanently promiscuous mode (implies .Dv IFF_PROMISC ) . .It Dv IFF_ALLMULTI .Aq D* This interface is in all-multicasts mode (used by multicast routers). .It Dv IFF_DRV_OACTIVE .Aq D* The interface's hardware output queue (if any) is full; output packets are to be queued. .It Dv IFF_SIMPLEX .Aq S* The interface cannot hear its own transmissions. .It Dv IFF_LINK0 .It Dv IFF_LINK1 .It Dv IFF_LINK2 .Aq D Control flags for the link layer. (Currently abused to select among multiple physical layers on some devices.) .It Dv IFF_MULTICAST .Aq S* This interface supports multicast. .It Dv IFF_CANTCONFIG .Aq S* The interface is not configurable in a meaningful way. Primarily useful for .Dv IFT_USB interfaces registered at the interface list. .It Dv IFF_MONITOR .Aq D This interface blocks transmission of packets and discards incoming packets after BPF processing. Used to monitor network traffic but not interact with the network in question. .It Dv IFF_STATICARP .Aq D Used to enable/disable ARP requests on this interface. .It Dv IFF_DYING .Aq D* Set when the .Vt ifnet structure of this interface is being released and still has .Va if_refcount references. .It Dv IFF_RENAMING .Aq D* Set when this interface is being renamed. .El .Ss "Interface Capabilities Flags" Interface capabilities are specialized features an interface may or may not support. These capabilities are very hardware-specific and allow, when enabled, to offload specific network processing to the interface or to offer a particular feature for use by other kernel parts. .Pp It should be stressed that a capability can be completely uncontrolled (i.e., stay always enabled with no way to disable it) or allow limited control over itself (e.g., depend on another capability's state.) Such peculiarities are determined solely by the hardware and driver of a particular interface. Only the driver possesses the knowledge on whether and how the interface capabilities can be controlled. Consequently, capabilities flags in .Va if_capenable should never be modified directly by kernel code other than the interface driver. The command .Dv SIOCSIFCAP to .Fn ifioctl is the dedicated means to attempt altering .Va if_capenable on an interface. Userland code shall use .Xr ioctl 2 . .Pp The following capabilities are currently supported by the system: .Bl -tag -width ".Dv IFCAP_POLLING_NOCOUNT" -offset indent .It Dv IFCAP_RXCSUM This interface can do checksum validation on receiving data. Some interfaces do not have sufficient buffer storage to store frames above a certain MTU-size completely. The driver for the interface might disable hardware checksum validation if the MTU is set above the hardcoded limit. .It Dv IFCAP_TXCSUM This interface can do checksum calculation on transmitting data. .It Dv IFCAP_HWCSUM A shorthand for .Pq Dv IFCAP_RXCSUM | IFCAP_TXCSUM . .It Dv IFCAP_NETCONS This interface can be a network console. .It Dv IFCAP_VLAN_MTU The .Xr vlan 4 driver can operate over this interface in software tagging mode without having to decrease MTU on .Xr vlan 4 interfaces below 1500 bytes. This implies the ability of this interface to cope with frames somewhat longer than permitted by the Ethernet specification. .It Dv IFCAP_VLAN_HWTAGGING This interface can do VLAN tagging on output and demultiplex frames by their VLAN tag on input. .It Dv IFCAP_JUMBO_MTU This Ethernet interface can transmit and receive frames up to 9000 bytes long. .It Dv IFCAP_POLLING This interface supports .Xr polling 4 . See below for details. .It Dv IFCAP_VLAN_HWCSUM This interface can do checksum calculation on both transmitting and receiving data on .Xr vlan 4 interfaces (implies .Dv IFCAP_HWCSUM ) . .It Dv IFCAP_TSO4 This Ethernet interface supports TCP4 Segmentation offloading. .It Dv IFCAP_TSO6 This Ethernet interface supports TCP6 Segmentation offloading. .It Dv IFCAP_TSO A shorthand for .Pq Dv IFCAP_TSO4 | IFCAP_TSO6 . .It Dv IFCAP_TOE4 This Ethernet interface supports TCP offloading. .It Dv IFCAP_TOE6 This Ethernet interface supports TCP6 offloading. .It Dv IFCAP_TOE A shorthand for .Pq Dv IFCAP_TOE4 | IFCAP_TOE6 . .It Dv IFCAP_WOL_UCAST This Ethernet interface supports waking up on any Unicast packet. .It Dv IFCAP_WOL_MCAST This Ethernet interface supports waking up on any Multicast packet. .It Dv IFCAP_WOL_MAGIC This Ethernet interface supports waking up on any Magic packet such as those sent by .Xr wake 8 . .It Dv IFCAP_WOL A shorthand for .Pq Dv IFCAP_WOL_UCAST | IFCAP_WOL_MCAST | IFCAP_WOL_MAGIC . .It Dv IFCAP_TOE4 This Ethernet interface supports TCP4 Offload Engine. .It Dv IFCAP_TOE6 This Ethernet interface supports TCP6 Offload Engine. .It Dv IFCAP_TOE A shorthand for .Pq Dv IFCAP_TOE4 | IFCAP_TOE6 . .It Dv IFCAP_VLAN_HWFILTER This interface supports frame filtering in hardware on .Xr vlan 4 interfaces. .It Dv IFCAP_POLLING_NOCOUNT The return value for the number of processed packets should be skipped for this interface. .It Dv IFCAP_VLAN_HWTSO This interface supports TCP Segmentation offloading on .Xr vlan 4 interfaces (implies .Dv IFCAP_TSO ) . .It Dv IFCAP_LINKSTATE This Ethernet interface supports dynamic link state changes. .El .Pp The ability of advanced network interfaces to offload certain computational tasks from the host CPU to the board is limited mostly to TCP/IP. Therefore a separate field associated with an interface (see .Va ifnet.if_data.ifi_hwassist below) keeps a detailed description of its enabled capabilities specific to TCP/IP processing. The TCP/IP module consults the field to see which tasks can be done on an .Em outgoing packet by the interface. The flags defined for that field are a superset of those for .Va mbuf.m_pkthdr.csum_flags , namely: .Bl -tag -width ".Dv CSUM_FRAGMENT" -offset indent .It Dv CSUM_IP The interface will compute IP checksums. .It Dv CSUM_TCP The interface will compute TCP checksums. .It Dv CSUM_UDP The interface will compute UDP checksums. .It Dv CSUM_IP_FRAGS The interface can compute a TCP or UDP checksum for a packet fragmented by the host CPU. Makes sense only along with .Dv CSUM_TCP or .Dv CSUM_UDP . .It Dv CSUM_FRAGMENT The interface will do the fragmentation of IP packets if necessary. The host CPU does not need to care about MTU on this interface as long as a packet to transmit through it is an IP one and it does not exceed the size of the hardware buffer. .El .Pp An interface notifies the TCP/IP module about the tasks the former has performed on an .Em incoming packet by setting the corresponding flags in the field .Va mbuf.m_pkthdr.csum_flags of the .Vt mbuf chain containing the packet. See .Xr mbuf 9 for details. .Pp The capability of a network interface to operate in .Xr polling 4 mode involves several flags in different global variables and per-interface fields. The capability flag .Dv IFCAP_POLLING set in interface's .Va if_capabilities indicates support for .Xr polling 4 on the particular interface. If set in .Va if_capabilities , the same flag can be marked or cleared in the interface's .Va if_capenable within .Fn ifioctl , thus initiating switch of the interface to .Xr polling 4 mode or interrupt mode, respectively. The actual mode change is managed by the driver-specific .Fn if_ioctl routine. The .Xr polling handler returns the number of packets processed. .Ss The Vt if_data Ss Structure The .Vt if_data structure contains statistics and identifying information used by management programs, and which is exported to user programs by way of the .Xr ifmib 4 branch of the .Xr sysctl 3 MIB. The following elements of the .Vt if_data structure are initialized by the interface and are not expected to change significantly over the course of normal operation: .Bl -tag -width ".Va ifi_lastchange" -offset indent .It Va ifi_type .Pq Vt u_char The type of the interface, as defined in .In net/if_types.h and described below in the .Sx "Interface Types" section. .It Va ifi_physical .Pq Vt u_char Intended to represent a selection of physical layers on devices which support more than one; never implemented. .It Va ifi_addrlen .Pq Vt u_char Length of a link-layer address on this device, or zero if there are none. Used to initialized the address length field in .Vt sockaddr_dl structures referring to this interface. .It Va ifi_hdrlen .Pq Vt u_char Maximum length of any link-layer header which might be prepended by the driver to a packet before transmission. The generic code computes the maximum over all interfaces and uses that value to influence the placement of data in .Vt mbuf Ns s to attempt to ensure that there is always sufficient space to prepend a link-layer header without allocating an additional .Vt mbuf . .It Va ifi_datalen .Pq Vt u_char Length of the .Vt if_data structure. Allows some stabilization of the routing socket ABI in the face of increases in the length of .Vt struct ifdata . .It Va ifi_mtu .Pq Vt u_long The maximum transmission unit of the medium, exclusive of any link-layer overhead. .It Va ifi_metric .Pq Vt u_long A dimensionless metric interpreted by a user-mode routing process. .It Va ifi_baudrate .Pq Vt u_long The line rate of the interface, in bits per second. .It Va ifi_hwassist .Pq Vt u_long A detailed interpretation of the capabilities to offload computational tasks for .Em outgoing packets. The interface driver must keep this field in accord with the current value of .Va if_capenable . .It Va ifi_epoch .Pq Vt time_t The system uptime when interface was attached or the statistics below were reset. This is intended to be used to set the SNMP variable .Va ifCounterDiscontinuityTime . It may also be used to determine if two successive queries for an interface of the same index have returned results for the same interface. .El .Pp The structure additionally contains generic statistics applicable to a variety of different interface types (except as noted, all members are of type .Vt u_long ) : .Bl -tag -width ".Va ifi_lastchange" -offset indent .It Va ifi_link_state .Pq Vt u_char The current link state of Ethernet interfaces. See the .Sx Interface Link States section for possible values. .It Va ifi_ipackets Number of packets received. .It Va ifi_ierrors Number of receive errors detected (e.g., FCS errors, DMA overruns, etc.). More detailed breakdowns can often be had by way of a link-specific MIB. .It Va ifi_opackets Number of packets transmitted. .It Va ifi_oerrors Number of output errors detected (e.g., late collisions, DMA overruns, etc.). More detailed breakdowns can often be had by way of a link-specific MIB. .It Va ifi_collisions Total number of collisions detected on output for CSMA interfaces. (This member is sometimes [ab]used by other types of interfaces for other output error counts.) .It Va ifi_ibytes Total traffic received, in bytes. .It Va ifi_obytes Total traffic transmitted, in bytes. .It Va ifi_imcasts Number of packets received which were sent by link-layer multicast. .It Va ifi_omcasts Number of packets sent by link-layer multicast. .It Va ifi_iqdrops Number of packets dropped on input. Rarely implemented. .It Va ifi_noproto Number of packets received for unknown network-layer protocol. .It Va ifi_lastchange .Pq Vt "struct timeval" The time of the last administrative change to the interface (as required for .Tn SNMP ) . .El .Ss Interface Types The header file .In net/if_types.h defines symbolic constants for a number of different types of interfaces. The most common are: .Pp .Bl -tag -offset indent -width ".Dv IFT_PROPVIRTUAL" -compact .It Dv IFT_OTHER none of the following .It Dv IFT_ETHER Ethernet .It Dv IFT_ISO88023 ISO 8802-3 CSMA/CD .It Dv IFT_ISO88024 ISO 8802-4 Token Bus .It Dv IFT_ISO88025 ISO 8802-5 Token Ring .It Dv IFT_ISO88026 ISO 8802-6 DQDB MAN .It Dv IFT_FDDI FDDI .It Dv IFT_PPP Internet Point-to-Point Protocol .Pq Xr ppp 8 .It Dv IFT_LOOP The loopback .Pq Xr lo 4 interface .It Dv IFT_SLIP Serial Line IP .It Dv IFT_PARA Parallel-port IP .Pq Dq Tn PLIP .It Dv IFT_ATM Asynchronous Transfer Mode .It Dv IFT_USB USB Interface .El .Ss Interface Link States The following link states are currently defined: .Pp .Bl -tag -offset indent -width ".Dv LINK_STATE_UNKNOWN" -compact .It Dv LINK_STATE_UNKNOWN The link is in an invalid or unknown state. .It Dv LINK_STATE_DOWN The link is down. .It Dv LINK_STATE_UP The link is up. .El .Ss The Vt ifaddr Ss Structure Every interface is associated with a list (or, rather, a .Li TAILQ ) of addresses, rooted at the interface structure's .Va if_addrlist member. The first element in this list is always an .Dv AF_LINK address representing the interface itself; multi-access network drivers should complete this structure by filling in their link-layer addresses after calling .Fn if_attach . Other members of the structure represent network-layer addresses which have been configured by means of the .Dv SIOCAIFADDR command to .Xr ioctl 2 , called on a socket of the appropriate protocol family. The elements of this list consist of .Vt ifaddr structures. Most protocols will declare their own protocol-specific interface address structures, but all begin with a .Vt "struct ifaddr" which provides the most-commonly-needed functionality across all protocols. Interface addresses are reference-counted. .Pp The members of .Vt "struct ifaddr" are as follows: .Bl -tag -width ".Va ifa_rtrequest" -offset indent .It Va ifa_addr .Pq Vt "struct sockaddr *" The local address of the interface. .It Va ifa_dstaddr .Pq Vt "struct sockaddr *" The remote address of point-to-point interfaces, and the broadcast address of broadcast interfaces. .Va ( ifa_broadaddr is a macro for .Va ifa_dstaddr . ) .It Va ifa_netmask .Pq Vt "struct sockaddr *" The network mask for multi-access interfaces, and the confusion generator for point-to-point interfaces. .It Va ifa_ifp .Pq Vt "struct ifnet *" A link back to the interface structure. .It Va ifa_link .Pq Fn TAILQ_ENTRY ifaddr .Xr queue 3 glue for list of addresses on each interface. .It Va ifa_rtrequest See below. .It Va ifa_flags .Pq Vt u_short Some of the flags which would be used for a route representing this address in the route table. .It Va ifa_refcnt .Pq Vt short The reference count. .El .Pp References to .Vt ifaddr structures are gained by calling the .Fn ifa_ref function and released by calling the .Fn ifa_free function. .Pp .Fn ifa_rtrequest is a pointer to a function which receives callouts from the routing code .Pq Fn rtrequest to perform link-layer-specific actions upon requests to add, or delete routes. The .Fa cmd argument indicates the request in question: .Dv RTM_ADD , or .Dv RTM_DELETE . The .Fa rt argument is the route in question; the .Fa info argument contains the specific destination being manipulated. .Sh FUNCTIONS The functions provided by the generic interface code can be divided into two groups: those which manipulate interfaces, and those which manipulate interface addresses. In addition to these functions, there may also be link-layer support routines which are used by a number of drivers implementing a specific link layer over different hardware; see the documentation for that link layer for more details. .Ss The Vt ifmultiaddr Ss Structure Every multicast-capable interface is associated with a list of multicast group memberships, which indicate at a low level which link-layer multicast addresses (if any) should be accepted, and at a high level, in which network-layer multicast groups a user process has expressed interest. .Pp The elements of the structure are as follows: .Bl -tag -width ".Va ifma_refcount" -offset indent .It Va ifma_link .Pq Fn LIST_ENTRY ifmultiaddr .Xr queue 3 macro glue. .It Va ifma_addr .Pq Vt "struct sockaddr *" A pointer to the address which this record represents. The memberships for various address families are stored in arbitrary order. .It Va ifma_lladdr .Pq Vt "struct sockaddr *" A pointer to the link-layer multicast address, if any, to which the network-layer multicast address in .Va ifma_addr is mapped, else a null pointer. If this element is non-nil, this membership also holds an invisible reference to another membership for that link-layer address. .It Va ifma_refcount .Pq Vt u_int A reference count of requests for this particular membership. .El .Ss Interface Manipulation Functions .Bl -ohang -offset indent .It Fn if_alloc Allocate and initialize .Vt "struct ifnet" . Initialization includes the allocation of an interface index and may include the allocation of a .Fa type specific structure in .Va if_l2com . .It Fn if_attach Link the specified interface .Fa ifp into the list of network interfaces. Also initialize the list of addresses on that interface, and create a link-layer .Vt ifaddr structure to be the first element in that list. (A pointer to this address structure is saved in the .Vt ifnet structure and shall be accessed by the .Fn ifaddr_byindex function.) The .Fa ifp must have been allocated by .Fn if_alloc . .It Fn if_detach Shut down and unlink the specified .Fa ifp from the interface list. .It Fn if_free Free the given .Fa ifp back to the system. The interface must have been previously detached if it was ever attached. .It Fn if_free_type Identical to .Fn if_free except that the given .Fa type is used to free .Va if_l2com instead of the type in .Va if_type . This is intended for use with drivers that change their interface type. .It Fn if_down Mark the interface .Fa ifp as down (i.e., .Dv IFF_UP is not set), flush its output queue, notify protocols of the transition, and generate a message from the .Xr route 4 routing socket. .It Fn if_up Mark the interface .Fa ifp as up, notify protocols of the transition, and generate a message from the .Xr route 4 routing socket. .It Fn ifpromisc Add or remove a promiscuous reference to .Fa ifp . If .Fa pswitch is true, add a reference; if it is false, remove a reference. On reference count transitions from zero to one and one to zero, set the .Dv IFF_PROMISC flag appropriately and call .Fn if_ioctl to set up the interface in the desired mode. .It Fn if_allmulti As .Fn ifpromisc , but for the all-multicasts .Pq Dv IFF_ALLMULTI flag instead of the promiscuous flag. .It Fn ifunit Return an .Vt ifnet pointer for the interface named .Fa name . .It Fn ifunit_ref Return a reference-counted (via .Fn ifa_ref ) .Vt ifnet pointer for the interface named .Fa name . This is the preferred function over .Fn ifunit . The caller is responsible for releasing the reference with .Fn if_rele when it is finished with the ifnet. .It Fn ifioctl Process the ioctl request .Fa cmd , issued on socket .Fa so by thread .Fa td , with data parameter .Fa data . This is the main routine for handling all interface configuration requests from user mode. It is ordinarily only called from the socket-layer .Xr ioctl 2 handler, and only for commands with class .Sq Li i . Any unrecognized commands will be passed down to socket .Fa so Ns 's protocol for further interpretation. The following commands are handled by .Fn ifioctl : .Pp .Bl -tag -width ".Dv SIOCGIFNETMASK" -offset indent -compact .It Dv SIOCGIFCONF Get interface configuration. (No call-down to driver.) .Pp .It Dv SIOCSIFNAME Set the interface name. .Dv RTM_IFANNOUNCE departure and arrival messages are sent so that routing code that relies on the interface name will update its interface list. Caller must have appropriate privilege. (No call-down to driver.) .It Dv SIOCGIFCAP .It Dv SIOCGIFFIB .It Dv SIOCGIFFLAGS .It Dv SIOCGIFMETRIC .It Dv SIOCGIFMTU .It Dv SIOCGIFPHYS Get interface capabilities, FIB, flags, metric, MTU, medium selection. (No call-down to driver.) .Pp .It Dv SIOCSIFCAP Enable or disable interface capabilities. Caller must have appropriate privilege. Before a call to the driver-specific .Fn if_ioctl routine, the requested mask for enabled capabilities is checked against the mask of capabilities supported by the interface, .Va if_capabilities . Requesting to enable an unsupported capability is invalid. The rest is supposed to be done by the driver, which includes updating .Va if_capenable and .Va if_data.ifi_hwassist appropriately. .Pp .It Dv SIOCSIFFIB Sets interface FIB. Caller must have appropriate privilege. FIB values start at 0 and values greater or equals than .Va net.fibs are considered invalid. .It Dv SIOCSIFFLAGS Change interface flags. Caller must have appropriate privilege. If a change to the .Dv IFF_UP flag is requested, .Fn if_up or .Fn if_down is called as appropriate. Flags listed in .Dv IFF_CANTCHANGE are masked off, and the field .Va if_flags in the interface structure is updated. Finally, the driver .Fn if_ioctl routine is called to perform any setup requested. .Pp .It Dv SIOCSIFMETRIC .It Dv SIOCSIFPHYS Change interface metric or medium. Caller must have appropriate privilege. .Pp .It Dv SIOCSIFMTU Change interface MTU. Caller must have appropriate privilege. MTU values less than 72 or greater than 65535 are considered invalid. The driver .Fn if_ioctl routine is called to implement the change; it is responsible for any additional sanity checking and for actually modifying the MTU in the interface structure. .Pp .It Dv SIOCADDMULTI .It Dv SIOCDELMULTI Add or delete permanent multicast group memberships on the interface. Caller must have appropriate privilege. The .Fn if_addmulti or .Fn if_delmulti function is called to perform the operation; qq.v. .Pp .It Dv SIOCAIFADDR .It Dv SIOCDIFADDR The socket's protocol control routine is called to implement the requested action. .El .El .Pp .Fn if_down , .Fn ifioctl , .Fn ifpromisc , and .Fn if_up must be called at .Fn splnet or higher. .Ss "Interface Address Functions" Several functions exist to look up an interface address structure given an address. .Fn ifa_ifwithaddr returns an interface address with either a local address or a broadcast address precisely matching the parameter .Fa addr . .Fn ifa_ifwithdstaddr returns an interface address for a point-to-point interface whose remote .Pq Dq destination address is .Fa addr and a fib is .Fa fib . If .Fa fib is .Dv RT_ALL_FIBS , then the first interface address matching .Fa addr will be returned. .Pp .Fn ifa_ifwithnet returns the most specific interface address which matches the specified address, .Fa addr , subject to its configured netmask, or a point-to-point interface address whose remote address is .Fa addr if one is found. If .Fa ignore_ptp -is true, skip point-to-point interface addresses. The +is true, skip point-to-point interface addresses. +The .Fa fib parameter is handled the same way as by .Fn ifa_ifwithdstaddr . .Pp .Fn ifaof_ifpforaddr returns the most specific address configured on interface .Fa ifp which matches address .Fa addr , subject to its configured netmask. If the interface is point-to-point, only an interface address whose remote address is precisely .Fa addr will be returned. .Pp .Fn ifaddr_byindex returns the link-level address of the interface with the given index .Fa idx . .Pp All of these functions return a null pointer if no such address can be found. .Ss "Interface Multicast Address Functions" The .Fn if_addmulti , .Fn if_delmulti , and .Fn if_findmulti functions provide support for requesting and relinquishing multicast group memberships, and for querying an interface's membership list, respectively. The .Fn if_addmulti function takes a pointer to an interface, .Fa ifp , and a generic address, .Fa sa . It also takes a pointer to a .Vt "struct ifmultiaddr *" which is filled in on successful return with the address of the group membership control block. The .Fn if_addmulti function performs the following four-step process: .Bl -enum -offset indent .It Call the interface's .Fn if_resolvemulti entry point to determine the link-layer address, if any, corresponding to this membership request, and also to give the link layer an opportunity to veto this membership request should it so desire. .It Check the interface's group membership list for a pre-existing membership for this group. If one is not found, allocate a new one; if one is, increment its reference count. .It If the .Fn if_resolvemulti routine returned a link-layer address corresponding to the group, repeat the previous step for that address as well. .It If the interface's multicast address filter needs to be changed because a new membership was added, call the interface's .Fn if_ioctl routine (with a .Fa cmd argument of .Dv SIOCADDMULTI ) to request that it do so. .El .Pp The .Fn if_delmulti function, given an interface .Fa ifp and an address, .Fa sa , reverses this process. Both functions return zero on success, or a standard error number on failure. .Pp The .Fn if_findmulti function examines the membership list of interface .Fa ifp for an address matching .Fa sa , and returns a pointer to that .Vt "struct ifmultiaddr" if one is found, else it returns a null pointer. .Sh SEE ALSO .Xr ioctl 2 , .Xr link_addr 3 , .Xr queue 3 , .Xr sysctl 3 , .Xr bpf 4 , .Xr ifmib 4 , .Xr lo 4 , .Xr netintro 4 , .Xr polling 4 , .Xr config 8 , .Xr ppp 8 , .Xr mbuf 9 , .Xr rtentry 9 .Rs .%A Gary R. Wright .%A W. Richard Stevens .%B TCP/IP Illustrated .%V Vol. 2 .%O Addison-Wesley, ISBN 0-201-63354-X .Re .Sh AUTHORS This manual page was written by .An Garrett A. Wollman . Index: projects/sendfile/share/man/man9/kqueue.9 =================================================================== --- projects/sendfile/share/man/man9/kqueue.9 (revision 276056) +++ projects/sendfile/share/man/man9/kqueue.9 (revision 276057) @@ -1,466 +1,467 @@ .\" Copyright 2006,2011 John-Mark Gurney .\" 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$ .\" .Dd March 26, 2012 .Dt KQUEUE 9 .Os .Sh NAME .Nm kqueue_add_filteropts , kqueue_del_filteropts , .Nm kqfd_register , .Nm knote_fdclose , .Nm knlist_init , knlist_init_mtx , knlist_init_rw_reader , .Nm knlist_add , knlist_remove , knlist_remove_inevent , knlist_empty , .Nm knlist_clear , knlist_delete , knlist_destroy , .Nm KNOTE_LOCKED , KNOTE_UNLOCKED .Nd "event delivery subsystem" .Sh SYNOPSIS .In sys/event.h .Ft int .Fn kqueue_add_filteropts "int filt" "struct filterops *filtops" .Ft int .Fn kqueue_del_filteropts "int filt" .Ft int .Fn kqfd_register "int fd" "struct kevent *kev" "struct thread *td" "int waitok" .Ft void .Fn knote_fdclose "struct thread *td" "int fd" .Ft void .Fo knlist_init .Fa "struct knlist *knl" .Fa "void *lock" .Fa "void \*[lp]*kl_lock\*[rp]\*[lp]void *\*[rp]" .Fa "void \*[lp]*kl_unlock\*[rp]\*[lp]void *\*[rp]" .Fa "int \*[lp]*kl_locked\*[rp]\*[lp]void *\*[rp]" .Fc .Ft void .Fn knlist_init_mtx "struct knlist *knl" "struct mtx *lock" .Ft void .Fn knlist_init_rw_reader "struct knlist *knl" "struct rwlock *lock" .Ft void .Fn knlist_add "struct knlist *knl" "struct knote *kn" "int islocked" .Ft void .Fn knlist_remove "struct knlist *knl" "struct knote *kn" "int islocked" .Ft void .Fn knlist_remove_inevent "struct knlist *knl" "struct knote *kn" .Ft int .Fn knlist_empty "struct knlist *knl" .Ft void .Fn knlist_clear "struct knlist *knl" "int islocked" .Ft void .Fn knlist_delete "struct knlist *knl" "struct thread *td" "int islocked" .Ft void .Fn knlist_destroy "struct knlist *knl" .Ft void .Fn KNOTE_LOCKED "struct knlist *knl" "long hint" .Ft void .Fn KNOTE_UNLOCKED "struct knlist *knl" "long hint" .Sh DESCRIPTION The functions .Fn kqueue_add_filteropts and .Fn kqueue_del_filteropts allow for the addition and removal of a filter type. The filter is statically defined by the .Dv EVFILT_* macros. The function .Fn kqueue_add_filteropts will make .Fa filt available. The .Vt "struct filterops" has the following members: .Bl -tag -width ".Va f_attach" .It Va f_isfd If .Va f_isfd is set, .Va ident in .Vt "struct kevent" is taken to be a file descriptor. In this case, the .Vt knote passed into .Va f_attach will have the .Va kn_fp member initialized to the .Vt "struct file *" that represents the file descriptor. .It Va f_attach The .Va f_attach function will be called when attaching a .Vt knote to the object. The method should call .Fn knlist_add to add the .Vt knote to the list that was initialized with .Fn knlist_init . The call to .Fn knlist_add is only necessary if the object can have multiple .Vt knotes associated with it. If there is no .Vt knlist to call .Fn knlist_add with, the function .Va f_attach must clear the .Dv KN_DETACHED bit of .Va kn_status in the .Vt knote . The function shall return 0 on success, or appropriate error for the failure, such as when the object is being destroyed, or does not exist. During .Va f_attach , it is valid to change the .Va kn_fops pointer to a different pointer. This will change the .Va f_event and .Va f_detach functions called when processing the .Vt knote . .It Va f_detach The .Va f_detach function will be called to detach the .Vt knote if the .Vt knote has not already been detached by a call to .Fn knlist_remove , .Fn knlist_remove_inevent or .Fn knlist_delete . The list .Fa lock will not be held when this function is called. .It Va f_event The .Va f_event function will be called to update the status of the .Vt knote . If the function returns 0, it will be assumed that the object is not ready (or no longer ready) to be woken up. The .Fa hint argument will be 0 when scanning .Vt knotes to see which are triggered. Otherwise, the .Fa hint argument will be the value passed to either .Dv KNOTE_LOCKED or .Dv KNOTE_UNLOCKED . The .Va kn_data value should be updated as necessary to reflect the current value, such as number of bytes available for reading, or buffer space available for writing. If the note needs to be removed, .Fn knlist_remove_inevent must be called. The function .Fn knlist_remove_inevent will remove the note from the list, the .Va f_detach function will not be called and the .Vt knote will not be returned as an event. .Pp Locks .Em must not be acquired in .Va f_event . If a lock is required in .Va f_event , it must be obtained in the .Fa kl_lock function of the .Vt knlist that the .Va knote was added to. .El .Pp The function .Fn kqfd_register will register the .Vt kevent on the kqueue file descriptor .Fa fd . If it is safe to sleep, .Fa waitok should be set. .Pp The function .Fn knote_fdclose is used to delete all .Vt knotes associated with .Fa fd . Once returned, there will no longer be any .Vt knotes associated with the .Fa fd . The .Vt knotes removed will never be returned from a .Xr kevent 2 call, so if userland uses the .Vt knote to track resources, they will be leaked. The .Fn FILEDESC_LOCK lock must be held over the call to .Fn knote_fdclose so that file descriptors cannot be added or removed. .Pp The .Fn knlist_* family of functions are for managing .Vt knotes associated with an object. A .Vt knlist is not required, but is commonly used. If used, the .Vt knlist must be initialized with either .Fn knlist_init , .Fn knlist_init_mtx or .Fn knlist_init_rw_reader . The .Vt knlist structure may be embedded into the object structure. The .Fa lock will be held over .Va f_event calls. .Pp For the .Fn knlist_init function, if .Fa lock is .Dv NULL , a shared global lock will be used and the remaining arguments must be .Dv NULL . The function pointers .Fa kl_lock , kl_unlock and .Fa kl_locked will be used to manipulate the argument .Fa lock . If any of the function pointers are .Dv NULL , a function operating on .Dv MTX_DEF style .Xr mutex 9 locks will be used instead. .Pp The function .Fn knlist_init_mtx may be used to initialize a .Vt knlist when .Fa lock is a .Dv MTX_DEF style .Xr mutex 9 lock. .Pp The function .Fn knlist_init_rw_reader may be used to initialize a .Vt knlist when .Fa lock is a .Xr rwlock 9 read lock. Lock is acquired via .Fn rw_rlock function. .Pp The function .Fn knlist_empty returns true when there are no .Vt knotes on the list. The function requires that the .Fa lock be held when called. .Pp The function .Fn knlist_clear removes all .Vt knotes from the list. The .Fa islocked argument declares if the .Fa lock has been acquired. All .Vt knotes will have .Dv EV_ONESHOT set so that the .Vt knote will be returned and removed durning the next scan. The .Va f_detach function will be called when the .Vt knote is deleted durning the next scan. This function must not be used when .Va f_isfd is set in .Vt "struct filterops" , as the .Fa td argument of .Fn fdrop will be .Dv NULL . .Pp The function .Fn knlist_delete removes and deletes all .Vt knotes on the list. The function .Va f_detach will not be called, and the .Vt knote will not be returned on the next scan. Using this function could leak user land resources if a process uses the .Vt knote to track resources. .Pp Both the .Fn knlist_clear and .Fn knlist_delete functions may sleep. They also may release the .Fa lock to wait for other .Vt knotes to drain. .Pp The .Fn knlist_destroy function is used to destroy a .Vt knlist . There must be no .Vt knotes associated with the .Vt knlist -.Fn ( knlist_empty -returns true) +.Po Fn knlist_empty +returns true +.Pc and no more .Vt knotes may be attached to the object. A .Vt knlist may be emptied by calling .Fn knlist_clear or .Fn knlist_delete . .Pp The macros .Fn KNOTE_LOCKED and .Fn KNOTE_UNLOCKED are used to notify .Vt knotes about events associated with the object. It will iterate over all .Vt knotes on the list calling the .Va f_event function associated with the .Vt knote . The macro .Fn KNOTE_LOCKED must be used if the lock associated with the .Fa knl is held. The function .Fn KNOTE_UNLOCKED will acquire the lock before iterating over the list of .Vt knotes . .Sh RETURN VALUES The function .Fn kqueue_add_filteropts will return zero on success, .Er EINVAL in the case of an invalid .Fa filt , or .Er EEXIST if the filter has already been installed. .Pp The function .Fn kqueue_del_filteropts will return zero on success, .Er EINVAL in the case of an invalid .Fa filt , or .Er EBUSY if the filter is still in use. .Pp The function .Fn kqfd_register will return zero on success, .Er EBADF if the file descriptor is not a kqueue, or any of the possible values returned by .Xr kevent 2 . .Sh SEE ALSO .Xr kevent 2 , .Xr kqueue 2 .Sh AUTHORS This manual page was written by .An John-Mark Gurney Aq Mt jmg@FreeBSD.org . Index: projects/sendfile/share/man/man9/lock.9 =================================================================== --- projects/sendfile/share/man/man9/lock.9 (revision 276056) +++ projects/sendfile/share/man/man9/lock.9 (revision 276057) @@ -1,423 +1,423 @@ .\" .\" Copyright (C) 2002 Chad David . 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(s), this list of conditions and the following disclaimer as .\" the first lines of this file unmodified other than the possible .\" addition of one or more copyright notices. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice(s), 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 COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ .\" .Dd November 2, 2014 .Dt LOCK 9 .Os .Sh NAME .Nm lockinit , .Nm lockdestroy , .Nm lockmgr , .Nm lockmgr_args , .Nm lockmgr_args_rw , .Nm lockmgr_disown , .Nm lockmgr_printinfo , .Nm lockmgr_recursed , .Nm lockmgr_rw , .Nm lockmgr_waiters , .Nm lockstatus , .Nm lockmgr_assert .Nd "lockmgr family of functions" .Sh SYNOPSIS .In sys/types.h .In sys/lock.h .In sys/lockmgr.h .Ft void .Fn lockinit "struct lock *lkp" "int prio" "const char *wmesg" "int timo" "int flags" .Ft void .Fn lockdestroy "struct lock *lkp" .Ft int .Fn lockmgr "struct lock *lkp" "u_int flags" "struct mtx *ilk" .Ft int .Fn lockmgr_args "struct lock *lkp" "u_int flags" "struct mtx *ilk" "const char *wmesg" "int prio" "int timo" .Ft int .Fn lockmgr_args_rw "struct lock *lkp" "u_int flags" "struct rwlock *ilk" "const char *wmesg" "int prio" "int timo" .Ft void .Fn lockmgr_disown "struct lock *lkp" .Ft void .Fn lockmgr_printinfo "const struct lock *lkp" .Ft int .Fn lockmgr_recursed "const struct lock *lkp" .Ft int .Fn lockmgr_rw "struct lock *lkp" "u_int flags" "struct rwlock *ilk" .Ft int .Fn lockmgr_waiters "const struct lock *lkp" .Ft int .Fn lockstatus "const struct lock *lkp" .Pp .Cd "options INVARIANTS" .Cd "options INVARIANT_SUPPORT" .Ft void .Fn lockmgr_assert "const struct lock *lkp" "int what" .Sh DESCRIPTION The .Fn lockinit function is used to initialize a lock. It must be called before any operation can be performed on a lock. Its arguments are: .Bl -tag -width ".Fa wmesg" .It Fa lkp A pointer to the lock to initialize. .It Fa prio The priority passed to .Xr sleep 9 . .It Fa wmesg The lock message. This is used for both debugging output and .Xr sleep 9 . .It Fa timo The timeout value passed to .Xr sleep 9 . .It Fa flags The flags the lock is to be initialized with: .Bl -tag -width ".Dv LK_CANRECURSE" .It Dv LK_ADAPTIVE Enable adaptive spinning for this lock if the kernel is compiled with the ADAPTIVE_LOCKMGRS option. .It Dv LK_CANRECURSE Allow recursive exclusive locks. .It Dv LK_NOPROFILE Disable lock profiling for this lock. .It Dv LK_NOSHARE Allow exclusive locks only. .It Dv LK_NOWITNESS Instruct .Xr witness 4 to ignore this lock. .It Dv LK_NODUP .Xr witness 4 should log messages about duplicate locks being acquired. .It Dv LK_QUIET Disable .Xr ktr 4 logging for this lock. .It Dv LK_TIMELOCK Use .Fa timo during a sleep; otherwise, 0 is used. .El .El .Pp The .Fn lockdestroy function is used to destroy a lock, and while it is called in a number of places in the kernel, it currently does nothing. .Pp The .Fn lockmgr and .Fn lockmgr_rw functions handle general locking functionality within the kernel, including support for shared and exclusive locks, and recursion. .Fn lockmgr and .Fn lockmgr_rw are also able to upgrade and downgrade locks. .Pp Their arguments are: .Bl -tag -width ".Fa flags" .It Fa lkp A pointer to the lock to manipulate. .It Fa flags Flags indicating what action is to be taken. .Bl -tag -width ".Dv LK_NODDLKTREAT" .It Dv LK_SHARED Acquire a shared lock. If an exclusive lock is currently held, .Dv EDEADLK will be returned. .It Dv LK_EXCLUSIVE Acquire an exclusive lock. If an exclusive lock is already held, and .Dv LK_CANRECURSE is not set, the system will .Xr panic 9 . .It Dv LK_DOWNGRADE Downgrade exclusive lock to a shared lock. Downgrading a shared lock is not permitted. If an exclusive lock has been recursed, the system will .Xr panic 9 . .It Dv LK_UPGRADE Upgrade a shared lock to an exclusive lock. If this call fails, the shared lock is lost, even if the .Dv LK_NOWAIT flag is specified. During the upgrade, the shared lock could be temporarily dropped. Attempts to upgrade an exclusive lock will cause a .Xr panic 9 . .It Dv LK_TRYUPGRADE Try to upgrade a shared lock to an exclusive lock. The failure to upgrade does not result in the dropping of the shared lock ownership. .It Dv LK_RELEASE Release the lock. Releasing a lock that is not held can cause a .Xr panic 9 . .It Dv LK_DRAIN Wait for all activity on the lock to end, then mark it decommissioned. This is used before freeing a lock that is part of a piece of memory that is about to be freed. (As documented in .In sys/lockmgr.h . ) .It Dv LK_SLEEPFAIL Fail if operation has slept. .It Dv LK_NOWAIT Do not allow the call to sleep. This can be used to test the lock. .It Dv LK_NOWITNESS Skip the .Xr witness 4 checks for this instance. .It Dv LK_CANRECURSE Allow recursion on an exclusive lock. For every lock there must be a release. .It Dv LK_INTERLOCK Unlock the interlock (which should be locked already). .It Dv LK_NODDLKTREAT Normally, .Fn lockmgr postpones serving further shared requests for shared-locked lock if there is exclusive waiter, to avoid exclusive lock starvation. But, if the thread requesting the shared lock already owns a shared lockmgr lock, the request is granted even in presence of the parallel exclusive lock request, which is done to avoid deadlocks with recursive shared acquisition. .Pp The .Dv LK_NODDLKTREAT flag can only be used by code which requests shared non-recursive lock. The flag allows exclusive requests to preempt the current shared request even if the current thread owns shared locks. This is safe since shared lock is guaranteed to not recurse, and is used when thread is known to held unrelated shared locks, to not cause unneccessary starvation. An example is .Dv vp locking in VFS .Xr lookup 9 , when .Dv dvp is already locked. .El .It Fa ilk An interlock mutex for controlling group access to the lock. If .Dv LK_INTERLOCK is specified, .Fn lockmgr and .Fn lockmgr_rw assume .Fa ilk is currently owned and not recursed, and will return it unlocked. See .Xr mtx_assert 9 . .El .Pp The .Fn lockmgr_args and .Fn lockmgr_args_rw function work like .Fn lockmgr and .Fn lockmgr_rw but accepting a .Fa wmesg , .Fa timo and .Fa prio on a per-instance basis. The specified values will override the default ones, but this can still be used passing, respectively, .Dv LK_WMESG_DEFAULT , .Dv LK_PRIO_DEFAULT and .Dv LK_TIMO_DEFAULT . .Pp The .Fn lockmgr_disown function switches the owner from the current thread to be .Dv LK_KERNPROC , if the lock is already held. .Pp The .Fn lockmgr_printinfo function prints debugging information about the lock. It is used primarily by .Xr VOP_PRINT 9 functions. .Pp The .Fn lockmgr_recursed function returns true if the lock is recursed, 0 otherwise. .Pp The .Fn lockmgr_waiters function returns true if the lock has waiters, 0 otherwise. .Pp The .Fn lockstatus function returns the status of the lock in relation to the current thread. .Pp When compiled with .Cd "options INVARIANTS" and .Cd "options INVARIANT_SUPPORT" , the .Fn lockmgr_assert function tests .Fa lkp for the assertions specified in .Fa what , and panics if they are not met. One of the following assertions must be specified: .Bl -tag -width ".Dv KA_UNLOCKED" .It Dv KA_LOCKED Assert that the current thread has either a shared or an exclusive lock on the .Vt lkp lock pointed to by the first argument. .It Dv KA_SLOCKED Assert that the current thread has a shared lock on the .Vt lkp lock pointed to by the first argument. .It Dv KA_XLOCKED Assert that the current thread has an exclusive lock on the .Vt lkp lock pointed to by the first argument. .It Dv KA_UNLOCKED Assert that the current thread has no lock on the .Vt lkp lock pointed to by the first argument. .El .Pp In addition, one of the following optional assertions can be used with either an .Dv KA_LOCKED , .Dv KA_SLOCKED , or .Dv KA_XLOCKED assertion: .Bl -tag -width ".Dv KA_NOTRECURSED" .It Dv KA_RECURSED Assert that the current thread has a recursed lock on .Fa lkp . .It Dv KA_NOTRECURSED Assert that the current thread does not have a recursed lock on .Fa lkp . .El .Sh RETURN VALUES The .Fn lockmgr and .Fn lockmgr_rw functions return 0 on success and non-zero on failure. .Pp The .Fn lockstatus function returns: .Bl -tag -width ".Dv LK_EXCLUSIVE" .It Dv LK_EXCLUSIVE An exclusive lock is held by the current thread. .It Dv LK_EXCLOTHER An exclusive lock is held by someone other than the current thread. .It Dv LK_SHARED A shared lock is held. .It Li 0 The lock is not held by anyone. .El .Sh ERRORS .Fn lockmgr and .Fn lockmgr_rw fail if: .Bl -tag -width Er .It Bq Er EBUSY .Dv LK_FORCEUPGRADE was requested and another thread had already requested a lock upgrade. .It Bq Er EBUSY .Dv LK_NOWAIT was set, and a sleep would have been required, or .Dv LK_TRYUPGRADE operation was not able to upgrade the lock. .It Bq Er ENOLCK .Dv LK_SLEEPFAIL was set and .Fn lockmgr or .Fn lockmgr_rw did sleep. .It Bq Er EINTR .Dv PCATCH was set in the lock priority, and a signal was delivered during a sleep. Note the .Er ERESTART error below. .It Bq Er ERESTART .Dv PCATCH was set in the lock priority, a signal was delivered during a sleep, and the system call is to be restarted. .It Bq Er EWOULDBLOCK a non-zero timeout was given, and the timeout expired. .El .Sh LOCKS If .Dv LK_INTERLOCK is passed in the .Fa flags argument to .Fn lockmgr or .Fn lockmgr_rw , the .Fa ilk must be held prior to calling .Fn lockmgr or .Fn lockmgr_rw , and will be returned unlocked. .Pp Upgrade attempts that fail result in the loss of the lock that is currently held. Also, it is invalid to upgrade an exclusive lock, and a .Xr panic 9 will be the result of trying. .Sh SEE ALSO .Xr condvar 9 , .Xr locking 9 , +.Xr mtx_assert 9 , .Xr mutex 9 , +.Xr panic 9 , .Xr rwlock 9 , .Xr sleep 9 , .Xr sx 9 , -.Xr mtx_assert 9 , -.Xr panic 9 , .Xr VOP_PRINT 9 .Sh AUTHORS This manual page was written by .An Chad David Aq Mt davidc@acns.ab.ca . Index: projects/sendfile/share/man/man9/locking.9 =================================================================== --- projects/sendfile/share/man/man9/locking.9 (revision 276056) +++ projects/sendfile/share/man/man9/locking.9 (revision 276057) @@ -1,412 +1,412 @@ .\" Copyright (c) 2007 Julian Elischer (julian - freebsd org ) .\" 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$ .\" .Dd June 30, 2013 .Dt LOCKING 9 .Os .Sh NAME .Nm locking .Nd kernel synchronization primitives .Sh DESCRIPTION The .Em FreeBSD kernel is written to run across multiple CPUs and as such provides several different synchronization primitives to allow developers to safely access and manipulate many data types. .Ss Mutexes Mutexes (also called "blocking mutexes") are the most commonly used synchronization primitive in the kernel. A thread acquires (locks) a mutex before accessing data shared with other threads (including interrupt threads), and releases (unlocks) it afterwards. If the mutex cannot be acquired, the thread requesting it will wait. Mutexes are adaptive by default, meaning that if the owner of a contended mutex is currently running on another CPU, then a thread attempting to acquire the mutex will spin rather than yielding the processor. Mutexes fully support priority propagation. .Pp See .Xr mutex 9 for details. .Ss Spin Mutexes Spin mutexes are a variation of basic mutexes; the main difference between the two is that spin mutexes never block. Instead, they spin while waiting for the lock to be released. To avoid deadlock, a thread that holds a spin mutex must never yield its CPU. Unlike ordinary mutexes, spin mutexes disable interrupts when acquired. Since disabling interrupts can be expensive, they are generally slower to acquire and release. Spin mutexes should be used only when absolutely necessary, e.g. to protect data shared with interrupt filter code (see .Xr bus_setup_intr 9 for details), or for scheduler internals. .Ss Mutex Pools With most synchronization primitives, such as mutexes, the programmer must provide memory to hold the primitive. For example, a mutex may be embedded inside the structure it protects. Mutex pools provide a preallocated set of mutexes to avoid this requirement. Note that mutexes from a pool may only be used as leaf locks. .Pp See .Xr mtx_pool 9 for details. .Ss Reader/Writer Locks Reader/writer locks allow shared access to protected data by multiple threads or exclusive access by a single thread. The threads with shared access are known as .Em readers since they should only read the protected data. A thread with exclusive access is known as a .Em writer since it may modify protected data. .Pp Reader/writer locks can be treated as mutexes (see above and .Xr mutex 9 ) with shared/exclusive semantics. Reader/writer locks support priority propagation like mutexes, but priority is propagated only to an exclusive holder. This limitation comes from the fact that shared owners are anonymous. .Pp See .Xr rwlock 9 for details. .Ss Read-Mostly Locks Read-mostly locks are similar to .Em reader/writer locks but optimized for very infrequent write locking. .Em Read-mostly locks implement full priority propagation by tracking shared owners using a caller-supplied .Em tracker data structure. .Pp See .Xr rmlock 9 for details. .Ss Sleepable Read-Mostly Locks Sleepable read-mostly locks are a variation on read-mostly locks. Threads holding an exclusive lock may sleep, but threads holding a shared lock may not. Priority is propagated to shared owners but not to exclusive owners. .Ss Shared/exclusive locks Shared/exclusive locks are similar to reader/writer locks; the main difference between them is that shared/exclusive locks may be held during unbounded sleep. Acquiring a contested shared/exclusive lock can perform an unbounded sleep. These locks do not support priority propagation. .Pp See .Xr sx 9 for details. .Ss Lockmanager locks Lockmanager locks are sleepable shared/exclusive locks used mostly in .Xr VFS 9 .Po as a .Xr vnode 9 lock .Pc and in the buffer cache .Po .Xr BUF_LOCK 9 .Pc . They have features other lock types do not have such as sleep timeouts, blocking upgrades, writer starvation avoidance, draining, and an interlock mutex, but this makes them complicated both to use and to implement; for this reason, they should be avoided. .Pp See .Xr lock 9 for details. .Ss Counting semaphores Counting semaphores provide a mechanism for synchronizing access to a pool of resources. Unlike mutexes, semaphores do not have the concept of an owner, so they can be useful in situations where one thread needs to acquire a resource, and another thread needs to release it. They are largely deprecated. .Pp See .Xr sema 9 for details. .Ss Condition variables Condition variables are used in conjunction with locks to wait for a condition to become true. A thread must hold the associated lock before calling one of the .Fn cv_wait , functions. When a thread waits on a condition, the lock is atomically released before the thread yields the processor and reacquired before the function call returns. Condition variables may be used with blocking mutexes, reader/writer locks, read-mostly locks, and shared/exclusive locks. .Pp See .Xr condvar 9 for details. .Ss Sleep/Wakeup The functions .Fn tsleep , .Fn msleep , .Fn msleep_spin , .Fn pause , .Fn wakeup , and .Fn wakeup_one also handle event-based thread blocking. Unlike condition variables, arbitrary addresses may be used as wait channels and a dedicated structure does not need to be allocated. However, care must be taken to ensure that wait channel addresses are unique to an event. If a thread must wait for an external event, it is put to sleep by .Fn tsleep , .Fn msleep , .Fn msleep_spin , or .Fn pause . Threads may also wait using one of the locking primitive sleep routines .Xr mtx_sleep 9 , .Xr rw_sleep 9 , or .Xr sx_sleep 9 . .Pp The parameter .Fa chan is an arbitrary address that uniquely identifies the event on which the thread is being put to sleep. All threads sleeping on a single .Fa chan are woken up later by .Fn wakeup .Pq often called from inside an interrupt routine to indicate that the event the thread was blocking on has occurred. .Pp Several of the sleep functions including .Fn msleep , .Fn msleep_spin , and the locking primitive sleep routines specify an additional lock parameter. The lock will be released before sleeping and reacquired before the sleep routine returns. If .Fa priority includes the .Dv PDROP flag, then the lock will not be reacquired before returning. The lock is used to ensure that a condition can be checked atomically, and that the current thread can be suspended without missing a change to the condition or an associated wakeup. In addition, all of the sleep routines will fully drop the .Va Giant mutex .Pq even if recursed while the thread is suspended and will reacquire the .Va Giant mutex .Pq restoring any recursion before the function returns. .Pp The .Fn pause function is a special sleep function that waits for a specified amount of time to pass before the thread resumes execution. This sleep cannot be terminated early by either an explicit .Fn wakeup or a signal. .Pp See .Xr sleep 9 for details. .Ss Giant Giant is a special mutex used to protect data structures that do not yet have their own locks. Since it provides semantics akin to the old .Xr spl 9 interface, Giant has special characteristics: .Bl -enum .It It is recursive. .It Drivers can request that Giant be locked around them by not marking themselves MPSAFE. Note that infrastructure to do this is slowly going away as non-MPSAFE drivers either became properly locked or disappear. .It Giant must be locked before other non-sleepable locks. .It Giant is dropped during unbounded sleeps and reacquired after wakeup. .It There are places in the kernel that drop Giant and pick it back up again. Sleep locks will do this before sleeping. Parts of the network or VM code may do this as well. This means that you cannot count on Giant keeping other code from running if your code sleeps, even if you want it to. .El .Sh INTERACTIONS The primitives can interact and have a number of rules regarding how they can and can not be combined. Many of these rules are checked by .Xr witness 4 . .Ss Bounded vs. Unbounded Sleep In a bounded sleep .Po also referred to as .Dq blocking .Pc the only resource needed to resume execution of a thread is CPU time for the owner of a lock that the thread is waiting to acquire. In an unbounded sleep .Po often referred to as simply .Dq sleeping .Pc a thread waits for an external event or for a condition to become true. In particular, a dependency chain of threads in bounded sleeps should always make forward progress, since there is always CPU time available. This requires that no thread in a bounded sleep is waiting for a lock held by a thread in an unbounded sleep. To avoid priority inversions, a thread in a bounded sleep lends its priority to the owner of the lock that it is waiting for. .Pp The following primitives perform bounded sleeps: mutexes, reader/writer locks and read-mostly locks. .Pp The following primitives perform unbounded sleeps: sleepable read-mostly locks, shared/exclusive locks, lockmanager locks, counting semaphores, condition variables, and sleep/wakeup. .Ss General Principles .Bl -bullet .It It is an error to do any operation that could result in yielding the processor while holding a spin mutex. .It It is an error to do any operation that could result in unbounded sleep while holding any primitive from the 'bounded sleep' group. For example, it is an error to try to acquire a shared/exclusive lock while holding a mutex, or to try to allocate memory with M_WAITOK while holding a reader/writer lock. .Pp Note that the lock passed to one of the .Fn sleep or .Fn cv_wait functions is dropped before the thread enters the unbounded sleep and does not violate this rule. .It It is an error to do any operation that could result in yielding of the processor when running inside an interrupt filter. .It It is an error to do any operation that could result in unbounded sleep when running inside an interrupt thread. .El .Ss Interaction table The following table shows what you can and can not do while holding one of the locking primitives discussed. Note that .Dq sleep includes .Fn sema_wait , .Fn sema_timedwait , any of the .Fn cv_wait functions, and any of the .Fn sleep functions. .Bl -column ".Ic xxxxxxxxxxxxxxxx" ".Xr XXXXXXXXX" ".Xr XXXXXXXXX" ".Xr XXXXXXX" ".Xr XXXXXXXXX" ".Xr XXXXXX" -offset 3n .It Em " You want:" Ta spin mtx Ta mutex/rw Ta rmlock Ta sleep rm Ta sx/lk Ta sleep .It Em "You have: " Ta -------- Ta -------- Ta ------ Ta -------- Ta ------ Ta ------ .It spin mtx Ta \&ok Ta \&no Ta \&no Ta \&no Ta \&no Ta \&no-1 .It mutex/rw Ta \&ok Ta \&ok Ta \&ok Ta \&no Ta \&no Ta \&no-1 .It rmlock Ta \&ok Ta \&ok Ta \&ok Ta \&no Ta \&no Ta \&no-1 .It sleep rm Ta \&ok Ta \&ok Ta \&ok Ta \&ok-2 Ta \&ok-2 Ta \&ok-2/3 .It sx Ta \&ok Ta \&ok Ta \&ok Ta \&ok Ta \&ok Ta \&ok-3 .It lockmgr Ta \&ok Ta \&ok Ta \&ok Ta \&ok Ta \&ok Ta \&ok .El .Pp .Em *1 There are calls that atomically release this primitive when going to sleep and reacquire it on wakeup .Po .Fn mtx_sleep , .Fn rw_sleep , .Fn msleep_spin , etc. .Pc . .Pp .Em *2 These cases are only allowed while holding a write lock on a sleepable read-mostly lock. .Pp .Em *3 Though one can sleep while holding this lock, one can also use a .Fn sleep function to atomically release this primitive when going to sleep and reacquire it on wakeup. .Pp Note that non-blocking try operations on locks are always permitted. .Ss Context mode table The next table shows what can be used in different contexts. At this time this is a rather easy to remember table. .Bl -column ".Ic Xxxxxxxxxxxxxxxxxxx" ".Xr XXXXXXXXX" ".Xr XXXXXXXXX" ".Xr XXXXXXX" ".Xr XXXXXXXXX" ".Xr XXXXXX" -offset 3n .It Em "Context:" Ta spin mtx Ta mutex/rw Ta rmlock Ta sleep rm Ta sx/lk Ta sleep .It interrupt filter: Ta \&ok Ta \&no Ta \&no Ta \&no Ta \&no Ta \&no .It interrupt thread: Ta \&ok Ta \&ok Ta \&ok Ta \&no Ta \&no Ta \&no .It callout: Ta \&ok Ta \&ok Ta \&ok Ta \&no Ta \&no Ta \&no .It system call: Ta \&ok Ta \&ok Ta \&ok Ta \&ok Ta \&ok Ta \&ok .El .Sh SEE ALSO .Xr witness 4 , +.Xr BUS_SETUP_INTR 9 , .Xr condvar 9 , .Xr lock 9 , +.Xr LOCK_PROFILING 9 , .Xr mtx_pool 9 , .Xr mutex 9 , .Xr rmlock 9 , .Xr rwlock 9 , .Xr sema 9 , .Xr sleep 9 , -.Xr sx 9 , -.Xr BUS_SETUP_INTR 9 , -.Xr LOCK_PROFILING 9 +.Xr sx 9 .Sh HISTORY These functions appeared in .Bsx 4.1 through .Fx 7.0 . .Sh BUGS There are too many locking primitives to choose from. Index: projects/sendfile/share/man/man9/mbuf.9 =================================================================== --- projects/sendfile/share/man/man9/mbuf.9 (revision 276056) +++ projects/sendfile/share/man/man9/mbuf.9 (revision 276057) @@ -1,1190 +1,1192 @@ .\" Copyright (c) 2000 FreeBSD Inc. .\" 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 [your name] 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$ .\" .Dd October 21, 2014 .Dt MBUF 9 .Os .\" .Sh NAME .Nm mbuf .Nd "memory management in the kernel IPC subsystem" .\" .Sh SYNOPSIS .In sys/param.h .In sys/systm.h .In sys/mbuf.h .\" .Ss Mbuf allocation macros .Fn MGET "struct mbuf *mbuf" "int how" "short type" .Fn MGETHDR "struct mbuf *mbuf" "int how" "short type" .Fn MCLGET "struct mbuf *mbuf" "int how" .Fo MEXTADD .Fa "struct mbuf *mbuf" .Fa "caddr_t buf" .Fa "u_int size" .Fa "void (*free)(void *opt_arg1, void *opt_arg2)" .Fa "void *opt_arg1" .Fa "void *opt_arg2" .Fa "short flags" .Fa "int type" .Fc .Fn MEXTFREE "struct mbuf *mbuf" .Fn MFREE "struct mbuf *mbuf" "struct mbuf *successor" .\" .Ss Mbuf utility macros .Fn mtod "struct mbuf *mbuf" "type" .Fn M_ALIGN "struct mbuf *mbuf" "u_int len" .Fn MH_ALIGN "struct mbuf *mbuf" "u_int len" .Ft int .Fn M_LEADINGSPACE "struct mbuf *mbuf" .Ft int .Fn M_TRAILINGSPACE "struct mbuf *mbuf" .Fn M_MOVE_PKTHDR "struct mbuf *to" "struct mbuf *from" .Fn M_PREPEND "struct mbuf *mbuf" "int len" "int how" .Fn MCHTYPE "struct mbuf *mbuf" "short type" .Ft int .Fn M_WRITABLE "struct mbuf *mbuf" .\" .Ss Mbuf allocation functions .Ft struct mbuf * .Fn m_get "int how" "short type" .Ft struct mbuf * .Fn m_get2 "int size" "int how" "short type" "int flags" .Ft struct mbuf * .Fn m_getm "struct mbuf *orig" "int len" "int how" "short type" .Ft struct mbuf * .Fn m_getjcl "int how" "short type" "int flags" "int size" .Ft struct mbuf * .Fn m_getcl "int how" "short type" "int flags" .Ft struct mbuf * .Fn m_getclr "int how" "short type" .Ft struct mbuf * .Fn m_gethdr "int how" "short type" .Ft struct mbuf * .Fn m_free "struct mbuf *mbuf" .Ft void .Fn m_freem "struct mbuf *mbuf" .\" .Ss Mbuf utility functions .Ft void .Fn m_adj "struct mbuf *mbuf" "int len" .Ft void .Fn m_align "struct mbuf *mbuf" "int len" .Ft int .Fn m_append "struct mbuf *mbuf" "int len" "c_caddr_t cp" .Ft struct mbuf * .Fn m_prepend "struct mbuf *mbuf" "int len" "int how" .Ft struct mbuf * .Fn m_copyup "struct mbuf *mbuf" "int len" "int dstoff" .Ft struct mbuf * .Fn m_pullup "struct mbuf *mbuf" "int len" .Ft struct mbuf * .Fn m_pulldown "struct mbuf *mbuf" "int offset" "int len" "int *offsetp" .Ft struct mbuf * .Fn m_copym "struct mbuf *mbuf" "int offset" "int len" "int how" .Ft struct mbuf * .Fn m_copypacket "struct mbuf *mbuf" "int how" .Ft struct mbuf * .Fn m_dup "struct mbuf *mbuf" "int how" .Ft void .Fn m_copydata "const struct mbuf *mbuf" "int offset" "int len" "caddr_t buf" .Ft void .Fn m_copyback "struct mbuf *mbuf" "int offset" "int len" "caddr_t buf" .Ft struct mbuf * .Fo m_devget .Fa "char *buf" .Fa "int len" .Fa "int offset" .Fa "struct ifnet *ifp" .Fa "void (*copy)(char *from, caddr_t to, u_int len)" .Fc .Ft void .Fn m_cat "struct mbuf *m" "struct mbuf *n" .Ft u_int .Fn m_fixhdr "struct mbuf *mbuf" .Ft void .Fn m_dup_pkthdr "struct mbuf *to" "struct mbuf *from" .Ft void .Fn m_move_pkthdr "struct mbuf *to" "struct mbuf *from" .Ft u_int .Fn m_length "struct mbuf *mbuf" "struct mbuf **last" .Ft struct mbuf * .Fn m_split "struct mbuf *mbuf" "int len" "int how" .Ft int .Fn m_apply "struct mbuf *mbuf" "int off" "int len" "int (*f)(void *arg, void *data, u_int len)" "void *arg" .Ft struct mbuf * .Fn m_getptr "struct mbuf *mbuf" "int loc" "int *off" .Ft struct mbuf * .Fn m_defrag "struct mbuf *m0" "int how" .Ft struct mbuf * .Fn m_unshare "struct mbuf *m0" "int how" .\" .Sh DESCRIPTION An .Vt mbuf is a basic unit of memory management in the kernel IPC subsystem. Network packets and socket buffers are stored in .Vt mbufs . A network packet may span multiple .Vt mbufs arranged into a .Vt mbuf chain (linked list), which allows adding or trimming network headers with little overhead. .Pp While a developer should not bother with .Vt mbuf internals without serious reason in order to avoid incompatibilities with future changes, it is useful to understand the general structure of an .Vt mbuf . .Pp An .Vt mbuf consists of a variable-sized header and a small internal buffer for data. The total size of an .Vt mbuf , .Dv MSIZE , is a constant defined in .In sys/param.h . The .Vt mbuf header includes: .Bl -tag -width "m_nextpkt" -offset indent .It Va m_next .Pq Vt struct mbuf * A pointer to the next .Vt mbuf in the .Vt mbuf chain . .It Va m_nextpkt .Pq Vt struct mbuf * A pointer to the next .Vt mbuf chain in the queue. .It Va m_data .Pq Vt caddr_t A pointer to data attached to this .Vt mbuf . .It Va m_len .Pq Vt int The length of the data. .It Va m_type .Pq Vt short The type of the data. .It Va m_flags .Pq Vt int The .Vt mbuf flags. .El .Pp The .Vt mbuf flag bits are defined as follows: .Bd -literal /* mbuf flags */ #define M_EXT 0x00000001 /* has associated external storage */ #define M_PKTHDR 0x00000002 /* start of record */ #define M_EOR 0x00000004 /* end of record */ #define M_RDONLY 0x00000008 /* associated data marked read-only */ #define M_PROTO1 0x00001000 /* protocol-specific */ #define M_PROTO2 0x00002000 /* protocol-specific */ #define M_PROTO3 0x00004000 /* protocol-specific */ #define M_PROTO4 0x00008000 /* protocol-specific */ #define M_PROTO5 0x00010000 /* protocol-specific */ #define M_PROTO6 0x00020000 /* protocol-specific */ #define M_PROTO7 0x00040000 /* protocol-specific */ #define M_PROTO8 0x00080000 /* protocol-specific */ #define M_PROTO9 0x00100000 /* protocol-specific */ #define M_PROTO10 0x00200000 /* protocol-specific */ #define M_PROTO11 0x00400000 /* protocol-specific */ #define M_PROTO12 0x00800000 /* protocol-specific */ /* mbuf pkthdr flags (also stored in m_flags) */ #define M_BCAST 0x00000010 /* send/received as link-level broadcast */ #define M_MCAST 0x00000020 /* send/received as link-level multicast */ .Ed .Pp The available .Vt mbuf types are defined as follows: .Bd -literal /* mbuf types */ #define MT_DATA 1 /* dynamic (data) allocation */ #define MT_HEADER MT_DATA /* packet header */ #define MT_SONAME 8 /* socket name */ #define MT_CONTROL 14 /* extra-data protocol message */ #define MT_OOBDATA 15 /* expedited data */ .Ed .Pp The available external buffer types are defined as follows: .Bd -literal /* external buffer types */ #define EXT_CLUSTER 1 /* mbuf cluster */ #define EXT_SFBUF 2 /* sendfile(2)'s sf_bufs */ #define EXT_JUMBOP 3 /* jumbo cluster 4096 bytes */ #define EXT_JUMBO9 4 /* jumbo cluster 9216 bytes */ #define EXT_JUMBO16 5 /* jumbo cluster 16184 bytes */ #define EXT_PACKET 6 /* mbuf+cluster from packet zone */ #define EXT_MBUF 7 /* external mbuf reference (M_IOVEC) */ #define EXT_NET_DRV 252 /* custom ext_buf provided by net driver(s) */ #define EXT_MOD_TYPE 253 /* custom module's ext_buf type */ #define EXT_DISPOSABLE 254 /* can throw this buffer away w/page flipping */ #define EXT_EXTREF 255 /* has externally maintained ref_cnt ptr */ .Ed .Pp If the .Dv M_PKTHDR flag is set, a .Vt struct pkthdr Va m_pkthdr is added to the .Vt mbuf header. It contains a pointer to the interface the packet has been received from .Pq Vt struct ifnet Va *rcvif , and the total packet length .Pq Vt int Va len . Optionally, it may also contain an attached list of packet tags .Pq Vt "struct m_tag" . See .Xr mbuf_tags 9 for details. Fields used in offloading checksum calculation to the hardware are kept in .Va m_pkthdr as well. See .Sx HARDWARE-ASSISTED CHECKSUM CALCULATION for details. .Pp If small enough, data is stored in the internal data buffer of an .Vt mbuf . If the data is sufficiently large, another .Vt mbuf may be added to the .Vt mbuf chain , or external storage may be associated with the .Vt mbuf . .Dv MHLEN bytes of data can fit into an .Vt mbuf with the .Dv M_PKTHDR flag set, .Dv MLEN bytes can otherwise. .Pp If external storage is being associated with an .Vt mbuf , the .Va m_ext header is added at the cost of losing the internal data buffer. It includes a pointer to external storage, the size of the storage, a pointer to a function used for freeing the storage, a pointer to an optional argument that can be passed to the function, and a pointer to a reference counter. An .Vt mbuf using external storage has the .Dv M_EXT flag set. .Pp The system supplies a macro for allocating the desired external storage buffer, .Dv MEXTADD . .Pp The allocation and management of the reference counter is handled by the subsystem. .Pp The system also supplies a default type of external storage buffer called an .Vt mbuf cluster . .Vt Mbuf clusters can be allocated and configured with the use of the .Dv MCLGET macro. Each .Vt mbuf cluster is .Dv MCLBYTES in size, where MCLBYTES is a machine-dependent constant. The system defines an advisory macro .Dv MINCLSIZE , which is the smallest amount of data to put into an .Vt mbuf cluster . It is equal to .Dv MHLEN plus one. It is typically preferable to store data into the data region of an .Vt mbuf , if size permits, as opposed to allocating a separate .Vt mbuf cluster to hold the same data. .\" .Ss Macros and Functions There are numerous predefined macros and functions that provide the developer with common utilities. .\" .Bl -ohang -offset indent .It Fn mtod mbuf type Convert an .Fa mbuf pointer to a data pointer. The macro expands to the data pointer cast to the specified .Fa type . .Sy Note : It is advisable to ensure that there is enough contiguous data in .Fa mbuf . See .Fn m_pullup for details. .It Fn MGET mbuf how type Allocate an .Vt mbuf and initialize it to contain internal data. .Fa mbuf will point to the allocated .Vt mbuf on success, or be set to .Dv NULL on failure. The .Fa how argument is to be set to .Dv M_WAITOK or .Dv M_NOWAIT . It specifies whether the caller is willing to block if necessary. A number of other functions and macros related to .Vt mbufs have the same argument because they may at some point need to allocate new .Vt mbufs . .It Fn MGETHDR mbuf how type Allocate an .Vt mbuf and initialize it to contain a packet header and internal data. See .Fn MGET for details. .It Fn MEXTADD mbuf buf size free opt_arg1 opt_arg2 flags type Associate externally managed data with .Fa mbuf . Any internal data contained in the mbuf will be discarded, and the .Dv M_EXT flag will be set. The .Fa buf and .Fa size arguments are the address and length, respectively, of the data. The .Fa free argument points to a function which will be called to free the data when the mbuf is freed; it is only used if .Fa type is .Dv EXT_EXTREF . The .Fa opt_arg1 and .Fa opt_arg2 arguments will be passed unmodified to .Fa free . The .Fa flags argument specifies additional .Vt mbuf flags; it is not necessary to specify .Dv M_EXT . Finally, the .Fa type argument specifies the type of external data, which controls how it will be disposed of when the .Vt mbuf is freed. In most cases, the correct value is .Dv EXT_EXTREF . .It Fn MCLGET mbuf how Allocate and attach an .Vt mbuf cluster to .Fa mbuf . If the macro fails, the .Dv M_EXT flag will not be set in .Fa mbuf . .It Fn M_ALIGN mbuf len Set the pointer .Fa mbuf->m_data to place an object of the size .Fa len at the end of the internal data area of .Fa mbuf , long word aligned. Applicable only if .Fa mbuf is newly allocated with .Fn MGET or .Fn m_get . .It Fn MH_ALIGN mbuf len Serves the same purpose as .Fn M_ALIGN does, but only for .Fa mbuf newly allocated with .Fn MGETHDR or .Fn m_gethdr , or initialized by .Fn m_dup_pkthdr or .Fn m_move_pkthdr . .It Fn m_align mbuf len Services the same purpose as .Fn M_ALIGN but handles any type of mbuf. .It Fn M_LEADINGSPACE mbuf Returns the number of bytes available before the beginning of data in .Fa mbuf . .It Fn M_TRAILINGSPACE mbuf Returns the number of bytes available after the end of data in .Fa mbuf . .It Fn M_PREPEND mbuf len how This macro operates on an .Vt mbuf chain . It is an optimized wrapper for .Fn m_prepend that can make use of possible empty space before data (e.g.\& left after trimming of a link-layer header). The new .Vt mbuf chain pointer or .Dv NULL is in .Fa mbuf after the call. .It Fn M_MOVE_PKTHDR to from Using this macro is equivalent to calling .Fn m_move_pkthdr to from . .It Fn M_WRITABLE mbuf This macro will evaluate true if .Fa mbuf is not marked .Dv M_RDONLY and if either .Fa mbuf does not contain external storage or, if it does, then if the reference count of the storage is not greater than 1. The .Dv M_RDONLY flag can be set in .Fa mbuf->m_flags . This can be achieved during setup of the external storage, by passing the .Dv M_RDONLY bit as a .Fa flags argument to the .Fn MEXTADD macro, or can be directly set in individual .Vt mbufs . .It Fn MCHTYPE mbuf type Change the type of .Fa mbuf to .Fa type . This is a relatively expensive operation and should be avoided. .El .Pp The functions are: .Bl -ohang -offset indent .It Fn m_get how type A function version of .Fn MGET for non-critical paths. .It Fn m_get2 size how type flags Allocate an .Vt mbuf with enough space to hold specified amount of data. .It Fn m_getm orig len how type Allocate .Fa len bytes worth of .Vt mbufs and .Vt mbuf clusters if necessary and append the resulting allocated .Vt mbuf chain to the .Vt mbuf chain .Fa orig , if it is .No non- Ns Dv NULL . If the allocation fails at any point, free whatever was allocated and return .Dv NULL . If .Fa orig is .No non- Ns Dv NULL , it will not be freed. It is possible to use .Fn m_getm to either append .Fa len bytes to an existing .Vt mbuf or .Vt mbuf chain (for example, one which may be sitting in a pre-allocated ring) or to simply perform an all-or-nothing .Vt mbuf and .Vt mbuf cluster allocation. .It Fn m_gethdr how type A function version of .Fn MGETHDR for non-critical paths. .It Fn m_getcl how type flags Fetch an .Vt mbuf with a .Vt mbuf cluster attached to it. If one of the allocations fails, the entire allocation fails. This routine is the preferred way of fetching both the .Vt mbuf and .Vt mbuf cluster together, as it avoids having to unlock/relock between allocations. Returns .Dv NULL on failure. .It Fn m_getjcl how type flags size This is like .Fn m_getcl but it the size of the cluster allocated will be large enough for .Fa size bytes. .It Fn m_getclr how type Allocate an .Vt mbuf and zero out the data region. .It Fn m_free mbuf Frees .Vt mbuf . Returns .Va m_next of the freed .Vt mbuf . .El .Pp The functions below operate on .Vt mbuf chains . .Bl -ohang -offset indent .It Fn m_freem mbuf Free an entire .Vt mbuf chain , including any external storage. .\" .It Fn m_adj mbuf len Trim .Fa len bytes from the head of an .Vt mbuf chain if .Fa len is positive, from the tail otherwise. .\" .It Fn m_append mbuf len cp Append .Vt len bytes of data .Vt cp to the .Vt mbuf chain . Extend the mbuf chain if the new data does not fit in existing space. .\" .It Fn m_prepend mbuf len how Allocate a new .Vt mbuf and prepend it to the .Vt mbuf chain , handle .Dv M_PKTHDR properly. .Sy Note : It does not allocate any .Vt mbuf clusters , so .Fa len must be less than .Dv MLEN or .Dv MHLEN , depending on the .Dv M_PKTHDR flag setting. .\" .It Fn m_copyup mbuf len dstoff Similar to .Fn m_pullup but copies .Fa len bytes of data into a new mbuf at .Fa dstoff bytes into the mbuf. The .Fa dstoff argument aligns the data and leaves room for a link layer header. Returns the new .Vt mbuf chain on success, and frees the .Vt mbuf chain and returns .Dv NULL on failure. .Sy Note : The function does not allocate .Vt mbuf clusters , so .Fa len + dstoff must be less than .Dv MHLEN . .\" .It Fn m_pullup mbuf len Arrange that the first .Fa len bytes of an .Vt mbuf chain are contiguous and lay in the data area of .Fa mbuf , so they are accessible with .Fn mtod mbuf type . It is important to remember that this may involve reallocating some mbufs and moving data so all pointers referencing data within the old mbuf chain must be recalculated or made invalid. Return the new .Vt mbuf chain on success, .Dv NULL on failure (the .Vt mbuf chain is freed in this case). .Sy Note : It does not allocate any .Vt mbuf clusters , so .Fa len must be less than or equal to .Dv MHLEN . .\" .It Fn m_pulldown mbuf offset len offsetp Arrange that .Fa len bytes between .Fa offset and .Fa offset + len in the .Vt mbuf chain are contiguous and lay in the data area of .Fa mbuf , so they are accessible with .Fn mtod mbuf type . .Fa len must be smaller than, or equal to, the size of an .Vt mbuf cluster . Return a pointer to an intermediate .Vt mbuf in the chain containing the requested region; the offset in the data region of the .Vt mbuf chain to the data contained in the returned mbuf is stored in .Fa *offsetp . If .Fa offsetp is NULL, the region may be accessed using .Fn mtod mbuf type . If .Fa offsetp is non-NULL, the region may be accessed using .Fn mtod mbuf uint8_t + *offsetp. The region of the mbuf chain between its beginning and .Fa offset is not modified, therefore it is safe to hold pointers to data within this region before calling .Fn m_pulldown . .\" .It Fn m_copym mbuf offset len how Make a copy of an .Vt mbuf chain starting .Fa offset bytes from the beginning, continuing for .Fa len bytes. If .Fa len is .Dv M_COPYALL , copy to the end of the .Vt mbuf chain . .Sy Note : The copy is read-only, because the .Vt mbuf clusters are not copied, only their reference counts are incremented. .\" .It Fn m_copypacket mbuf how Copy an entire packet including header, which must be present. This is an optimized version of the common case .Fn m_copym mbuf 0 M_COPYALL how . .Sy Note : the copy is read-only, because the .Vt mbuf clusters are not copied, only their reference counts are incremented. .\" .It Fn m_dup mbuf how Copy a packet header .Vt mbuf chain into a completely new .Vt mbuf chain , including copying any .Vt mbuf clusters . Use this instead of .Fn m_copypacket when you need a writable copy of an .Vt mbuf chain . .\" .It Fn m_copydata mbuf offset len buf Copy data from an .Vt mbuf chain starting .Fa off bytes from the beginning, continuing for .Fa len bytes, into the indicated buffer .Fa buf . .\" .It Fn m_copyback mbuf offset len buf Copy .Fa len bytes from the buffer .Fa buf back into the indicated .Vt mbuf chain , starting at .Fa offset bytes from the beginning of the .Vt mbuf chain , extending the .Vt mbuf chain if necessary. .Sy Note : It does not allocate any .Vt mbuf clusters , just adds .Vt mbufs to the .Vt mbuf chain . It is safe to set .Fa offset beyond the current .Vt mbuf chain end: zeroed .Vt mbufs will be allocated to fill the space. .\" .It Fn m_length mbuf last Return the length of the .Vt mbuf chain , and optionally a pointer to the last .Vt mbuf . .\" .It Fn m_dup_pkthdr to from how Upon the function's completion, the .Vt mbuf .Fa to will contain an identical copy of .Fa from->m_pkthdr and the per-packet attributes found in the .Vt mbuf chain .Fa from . The .Vt mbuf .Fa from must have the flag .Dv M_PKTHDR initially set, and .Fa to must be empty on entry. .\" .It Fn m_move_pkthdr to from Move .Va m_pkthdr and the per-packet attributes from the .Vt mbuf chain .Fa from to the .Vt mbuf .Fa to . The .Vt mbuf .Fa from must have the flag .Dv M_PKTHDR initially set, and .Fa to must be empty on entry. Upon the function's completion, .Fa from will have the flag .Dv M_PKTHDR and the per-packet attributes cleared. .\" .It Fn m_fixhdr mbuf Set the packet-header length to the length of the .Vt mbuf chain . .\" .It Fn m_devget buf len offset ifp copy Copy data from a device local memory pointed to by .Fa buf to an .Vt mbuf chain . The copy is done using a specified copy routine .Fa copy , or .Fn bcopy if .Fa copy is .Dv NULL . .\" .It Fn m_cat m n Concatenate .Fa n to .Fa m . Both .Vt mbuf chains must be of the same type. .Fa N is still valid after the function returned. .Sy Note : It does not handle .Dv M_PKTHDR and friends. .\" .It Fn m_split mbuf len how Partition an .Vt mbuf chain in two pieces, returning the tail: all but the first .Fa len bytes. In case of failure, it returns .Dv NULL and attempts to restore the .Vt mbuf chain to its original state. .\" .It Fn m_apply mbuf off len f arg Apply a function to an .Vt mbuf chain , at offset .Fa off , for length .Fa len bytes. Typically used to avoid calls to .Fn m_pullup which would otherwise be unnecessary or undesirable. .Fa arg is a convenience argument which is passed to the callback function .Fa f . .Pp Each time .Fn f is called, it will be passed .Fa arg , a pointer to the .Fa data in the current mbuf, and the length .Fa len of the data in this mbuf to which the function should be applied. .Pp The function should return zero to indicate success; otherwise, if an error is indicated, then .Fn m_apply will return the error and stop iterating through the .Vt mbuf chain . .\" .It Fn m_getptr mbuf loc off Return a pointer to the mbuf containing the data located at .Fa loc bytes from the beginning of the .Vt mbuf chain . The corresponding offset into the mbuf will be stored in .Fa *off . .It Fn m_defrag m0 how Defragment an mbuf chain, returning the shortest possible chain of mbufs and clusters. If allocation fails and this can not be completed, .Dv NULL will be returned and the original chain will be unchanged. Upon success, the original chain will be freed and the new chain will be returned. .Fa how should be either .Dv M_WAITOK or .Dv M_NOWAIT , depending on the caller's preference. .Pp This function is especially useful in network drivers, where certain long mbuf chains must be shortened before being added to TX descriptor lists. .It Fn m_unshare m0 how Create a version of the specified mbuf chain whose contents can be safely modified without affecting other users. If allocation fails and this operation can not be completed, .Dv NULL will be returned. The original mbuf chain is always reclaimed and the reference count of any shared mbuf clusters is decremented. .Fa how should be either .Dv M_WAITOK or .Dv M_NOWAIT , depending on the caller's preference. As a side-effect of this process the returned mbuf chain may be compacted. .Pp This function is especially useful in the transmit path of network code, when data must be encrypted or otherwise altered prior to transmission. .El .Sh HARDWARE-ASSISTED CHECKSUM CALCULATION This section currently applies to TCP/IP only. In order to save the host CPU resources, computing checksums is offloaded to the network interface hardware if possible. The .Va m_pkthdr member of the leading .Vt mbuf of a packet contains two fields used for that purpose, .Vt int Va csum_flags and .Vt int Va csum_data . The meaning of those fields depends on the direction a packet flows in, and on whether the packet is fragmented. Henceforth, .Va csum_flags or .Va csum_data of a packet will denote the corresponding field of the .Va m_pkthdr member of the leading .Vt mbuf in the .Vt mbuf chain containing the packet. .Pp On output, checksum offloading is attempted after the outgoing interface has been determined for a packet. The interface-specific field .Va ifnet.if_data.ifi_hwassist (see .Xr ifnet 9 ) is consulted for the capabilities of the interface to assist in computing checksums. The .Va csum_flags field of the packet header is set to indicate which actions the interface is supposed to perform on it. The actions unsupported by the network interface are done in the software prior to passing the packet down to the interface driver; such actions will never be requested through .Va csum_flags . .Pp The flags demanding a particular action from an interface are as follows: .Bl -tag -width ".Dv CSUM_TCP" -offset indent .It Dv CSUM_IP The IP header checksum is to be computed and stored in the corresponding field of the packet. The hardware is expected to know the format of an IP header to determine the offset of the IP checksum field. .It Dv CSUM_TCP The TCP checksum is to be computed. (See below.) .It Dv CSUM_UDP The UDP checksum is to be computed. (See below.) .El .Pp Should a TCP or UDP checksum be offloaded to the hardware, the field .Va csum_data will contain the byte offset of the checksum field relative to the end of the IP header. In this case, the checksum field will be initially set by the TCP/IP module to the checksum of the pseudo header defined by the TCP and UDP specifications. .Pp On input, an interface indicates the actions it has performed on a packet by setting one or more of the following flags in .Va csum_flags associated with the packet: .Bl -tag -width ".Dv CSUM_IP_CHECKED" -offset indent .It Dv CSUM_IP_CHECKED The IP header checksum has been computed. .It Dv CSUM_IP_VALID The IP header has a valid checksum. This flag can appear only in combination with .Dv CSUM_IP_CHECKED . .It Dv CSUM_DATA_VALID The checksum of the data portion of the IP packet has been computed and stored in the field .Va csum_data in network byte order. .It Dv CSUM_PSEUDO_HDR Can be set only along with .Dv CSUM_DATA_VALID to indicate that the IP data checksum found in .Va csum_data allows for the pseudo header defined by the TCP and UDP specifications. Otherwise the checksum of the pseudo header must be calculated by the host CPU and added to .Va csum_data to obtain the final checksum to be used for TCP or UDP validation purposes. .El .Pp If a particular network interface just indicates success or failure of TCP or UDP checksum validation without returning the exact value of the checksum to the host CPU, its driver can mark .Dv CSUM_DATA_VALID and .Dv CSUM_PSEUDO_HDR in .Va csum_flags , and set .Va csum_data to .Li 0xFFFF hexadecimal to indicate a valid checksum. It is a peculiarity of the algorithm used that the Internet checksum calculated over any valid packet will be .Li 0xFFFF as long as the original checksum field is included. .Sh STRESS TESTING When running a kernel compiled with the option .Dv MBUF_STRESS_TEST , the following .Xr sysctl 8 Ns -controlled options may be used to create various failure/extreme cases for testing of network drivers and other parts of the kernel that rely on .Vt mbufs . .Bl -tag -width ident .It Va net.inet.ip.mbuf_frag_size Causes .Fn ip_output to fragment outgoing .Vt mbuf chains into fragments of the specified size. Setting this variable to 1 is an excellent way to test the long .Vt mbuf chain handling ability of network drivers. .It Va kern.ipc.m_defragrandomfailures Causes the function .Fn m_defrag to randomly fail, returning .Dv NULL . Any piece of code which uses .Fn m_defrag should be tested with this feature. .El .Sh RETURN VALUES See above. .Sh SEE ALSO .Xr ifnet 9 , .Xr mbuf_tags 9 .Sh HISTORY .\" Please correct me if I'm wrong .Vt Mbufs appeared in an early version of .Bx . Besides being used for network packets, they were used to store various dynamic structures, such as routing table entries, interface addresses, protocol control blocks, etc. In more recent .Fx use of .Vt mbufs is almost entirely limited to packet storage, with .Xr uma 9 zones being used directly to store other network-related memory. .Pp Historically, the .Vt mbuf allocator has been a special-purpose memory allocator able to run in interrupt contexts and allocating from a special kernel address space map. As of .Fx 5.3 , the .Vt mbuf allocator is a wrapper around .Xr uma 9 , allowing caching of .Vt mbufs , clusters, and .Vt mbuf + cluster pairs in per-CPU caches, as well as bringing other benefits of slab allocation. .Sh AUTHORS The original .Nm -manual page was written by Yar Tikhiy. +manual page was written by +.An Yar Tikhiy . The .Xr uma 9 .Vt mbuf -allocator was written by Bosko Milekic. +allocator was written by +.An Bosko Milekic . Index: projects/sendfile/share/man/man9/refcount.9 =================================================================== --- projects/sendfile/share/man/man9/refcount.9 (revision 276056) +++ projects/sendfile/share/man/man9/refcount.9 (revision 276057) @@ -1,96 +1,96 @@ .\" .\" Copyright (c) 2009 Advanced Computing Technologies LLC .\" Written by: John H. Baldwin .\" 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$ .\" .Dd January 20, 2009 .Dt REFCOUNT 9 .Os .Sh NAME .Nm refcount , .Nm refcount_init , .Nm refcount_acquire , .Nm refcount_release .Nd manage a simple reference counter .Sh SYNOPSIS .In sys/param.h .In sys/refcount.h .Ft void -.Fn refcount_init "volatile u_int *count, u_int value" +.Fn refcount_init "volatile u_int *count" "u_int value" .Ft void .Fn refcount_acquire "volatile u_int *count" .Ft int .Fn refcount_release "volatile u_int *count" .Sh DESCRIPTION The .Nm functions provide an API to manage a simple reference counter. The caller provides the storage for the counter in an unsigned integer. A pointer to this integer is passed via .Fa count . Usually the counter is used to manage the lifetime of an object and is stored as a member of the object. .Pp The .Fn refcount_init function is used to set the initial value of the counter to .Fa value . It is normally used when creating a reference-counted object. .Pp The .Fn refcount_acquire function is used to acquire a new reference. The caller is responsible for ensuring that it holds a valid reference while obtaining a new reference. For example, if an object is stored on a list and the list holds a reference on the object, then holding a lock that protects the list provides sufficient protection for acquiring a new reference. .Pp The .Fn refcount_release function is used to release an existing reference. The function returns a non-zero value if the reference being released was the last reference; otherwise, it returns zero. .Pp Note that these routines do not provide any inter-CPU synchronization, data protection, or memory ordering guarantees except for managing the counter. The caller is responsible for any additional synchronization needed by consumers of any containing objects. In addition, the caller is also responsible for managing the life cycle of any containing objects including explicitly releasing any resources when the last reference is released. .Sh RETURN VALUES The .Nm refcount_release function returns non-zero when releasing the last reference and zero when releasing any other reference. .Sh HISTORY These functions were introduced in .Fx 6.0 . Index: projects/sendfile/share/man/man9/usbdi.9 =================================================================== --- projects/sendfile/share/man/man9/usbdi.9 (revision 276056) +++ projects/sendfile/share/man/man9/usbdi.9 (revision 276057) @@ -1,641 +1,641 @@ .\" .\" Copyright (c) 2005 Ian Dowse .\" 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$ .Dd June 24, 2009 .Dt USBDI 9 .Os .Sh NAME .Nm usb_fifo_alloc_buffer , .Nm usb_fifo_attach , .Nm usb_fifo_detach , .Nm usb_fifo_free_buffer , .Nm usb_fifo_get_data , .Nm usb_fifo_get_data_buffer , .Nm usb_fifo_get_data_error , .Nm usb_fifo_get_data_linear , .Nm usb_fifo_put_bytes_max , .Nm usb_fifo_put_data , .Nm usb_fifo_put_data_buffer , .Nm usb_fifo_put_data_error , .Nm usb_fifo_put_data_linear , .Nm usb_fifo_reset , .Nm usb_fifo_softc , .Nm usb_fifo_wakeup , .Nm usbd_do_request , .Nm usbd_do_request_flags , .Nm usbd_errstr , .Nm usbd_lookup_id_by_info , .Nm usbd_lookup_id_by_uaa , .Nm usbd_transfer_clear_stall , .Nm usbd_transfer_drain , .Nm usbd_transfer_pending , .Nm usbd_transfer_poll , .Nm usbd_transfer_setup , .Nm usbd_transfer_start , .Nm usbd_transfer_stop , .Nm usbd_transfer_submit , .Nm usbd_transfer_unsetup , .Nm usbd_xfer_clr_flag , .Nm usbd_xfer_frame_data , .Nm usbd_xfer_frame_len , .Nm usbd_xfer_get_frame , .Nm usbd_xfer_get_priv , .Nm usbd_xfer_is_stalled , .Nm usbd_xfer_max_framelen , .Nm usbd_xfer_max_frames , .Nm usbd_xfer_max_len , .Nm usbd_xfer_set_flag , .Nm usbd_xfer_set_frame_data , .Nm usbd_xfer_set_frame_len , .Nm usbd_xfer_set_frame_offset , .Nm usbd_xfer_set_frames , .Nm usbd_xfer_set_interval , .Nm usbd_xfer_set_priv , .Nm usbd_xfer_set_stall , .Nm usbd_xfer_set_timeout , .Nm usbd_xfer_softc , .Nm usbd_xfer_state , .Nm usbd_xfer_status .Nd Universal Serial Bus driver programming interface .Sh SYNOPSIS .In dev/usb/usb.h .In dev/usb/usbdi.h .In dev/usb/usbdi_util.h .Sh DESCRIPTION The Universal Serial Bus (USB) driver programming interface provides USB peripheral drivers with a host controller independent API for controlling and communicating with USB peripherals. The .Nm usb module supports both USB Host and USB Device side mode. . .Sh USB KERNEL PROGRAMMING Here is a list of commonly used functions: .Pp . .Ft "usb_error_t" .Fo "usbd_transfer_setup" .Fa "udev" .Fa "ifaces" .Fa "pxfer" .Fa "setup_start" .Fa "n_setup" .Fa "priv_sc" .Fa "priv_mtx" .Fc . .Pp . .Ft "void" .Fo "usbd_transfer_unsetup" .Fa "pxfer" .Fa "n_setup" .Fc . .Pp . .Ft "void" .Fo "usbd_transfer_start" .Fa "xfer" .Fc . .Pp . .Ft "void" .Fo "usbd_transfer_stop" .Fa "xfer" .Fc . .Pp . .Ft "void" .Fo "usbd_transfer_drain" .Fa "xfer" .Fc . . . .Sh USB TRANSFER MANAGEMENT FUNCTIONS The USB standard defines four types of USB transfers. . Control transfers, Bulk transfers, Interrupt transfers and Isochronous transfers. . All the transfer types are managed using the following five functions: . .Pp . .Fn usbd_transfer_setup This function will allocate memory for and initialise an array of USB transfers and all required DMA memory. . This function can sleep or block waiting for resources to become available. .Fa udev is a pointer to "struct usb_device". .Fa ifaces is an array of interface index numbers to use. See "if_index". .Fa pxfer is a pointer to an array of USB transfer pointers that are initialized to NULL, and then pointed to allocated USB transfers. .Fa setup_start is a pointer to an array of USB config structures. .Fa n_setup is a number telling the USB system how many USB transfers should be setup. .Fa priv_sc is the private softc pointer, which will be used to initialize "xfer->priv_sc". .Fa priv_mtx is the private mutex protecting the transfer structure and the softc. This pointer is used to initialize "xfer->priv_mtx". This function returns zero upon success. A non-zero return value indicates failure. . .Pp . .Fn usbd_transfer_unsetup This function will release the given USB transfers and all allocated resources associated with these USB transfers. .Fa pxfer is a pointer to an array of USB transfer pointers, that may be NULL, that should be freed by the USB system. .Fa n_setup is a number telling the USB system how many USB transfers should be unsetup. . This function can sleep waiting for USB transfers to complete. . This function is NULL safe with regard to the USB transfer structure pointer. . It is not allowed to call this function from the USB transfer callback. . .Pp . .Fn usbd_transfer_start This function will start the USB transfer pointed to by -.Fa xfer, +.Fa xfer , if not already started. . This function is always non-blocking and must be called with the so-called private USB mutex locked. . This function is NULL safe with regard to the USB transfer structure pointer. . .Pp . .Fn usbd_transfer_stop This function will stop the USB transfer pointed to by -.Fa xfer, +.Fa xfer , if not already stopped. . This function is always non-blocking and must be called with the so-called private USB mutex locked. . This function can return before the USB callback has been called. . This function is NULL safe with regard to the USB transfer structure pointer. . If the transfer was in progress, the callback will called with "USB_ST_ERROR" and "error = USB_ERR_CANCELLED". . .Pp . .Fn usbd_transfer_drain This function will stop an USB transfer, if not already stopped and wait for any additional USB hardware operations to complete. . Buffers that are loaded into DMA using "usbd_xfer_set_frame_data()" can safely be freed after that this function has returned. . This function can block the caller and will not return before the USB callback has been called. . This function is NULL safe with regard to the USB transfer structure pointer. . .Sh USB TRANSFER CALLBACK . The USB callback has three states. . USB_ST_SETUP, USB_ST_TRANSFERRED and USB_ST_ERROR. USB_ST_SETUP is the initial state. . After the callback has been called with this state it will always be called back at a later stage in one of the other two states. . The USB callback should not restart the USB transfer in case the error cause is USB_ERR_CANCELLED. . The USB callback is protected from recursion. . That means one can start and stop whatever transfer from the callback of another transfer one desires. . Also the transfer that is currently called back. . Recursion is handled like this that when the callback that wants to recurse returns it is called one more time. . . .Pp . .Fn usbd_transfer_submit This function should only be called from within the USB callback and is used to start the USB hardware. . An USB transfer can have multiple frames consisting of one or more USB packets making up an I/O vector for all USB transfer types. . .Bd -literal -offset indent void usb_default_callback(struct usb_xfer *xfer, usb_error_t error) { int actlen; usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); switch (USB_GET_STATE(xfer)) { case USB_ST_SETUP: /* * Setup xfer frame lengths/count and data */ usbd_transfer_submit(xfer); break; case USB_ST_TRANSFERRED: /* * Read usb frame data, if any. * "actlen" has the total length for all frames * transferred. */ break; default: /* Error */ /* * Print error message and clear stall * for example. */ break; } /* * Here it is safe to do something without the private * USB mutex locked. */ return; } .Ed . .Sh USB CONTROL TRANSFERS An USB control transfer has three parts. . First the SETUP packet, then DATA packet(s) and then a STATUS packet. . The SETUP packet is always pointed to by frame 0 and the length is set by .Fn usbd_xfer_frame_len also if there should not be sent any SETUP packet! If an USB control transfer has no DATA stage, then the number of frames should be set to 1. . Else the default number of frames is 2. . .Bd -literal -offset indent Example1: SETUP + STATUS usbd_xfer_set_frames(xfer, 1); usbd_xfer_set_frame_len(xfer, 0, 8); usbd_transfer_submit(xfer); Example2: SETUP + DATA + STATUS usbd_xfer_set_frames(xfer, 2); usbd_xfer_set_frame_len(xfer, 0, 8); usbd_xfer_set_frame_len(xfer, 1, 1); usbd_transfer_submit(xfer); Example3: SETUP + DATA + STATUS - split 1st callback: usbd_xfer_set_frames(xfer, 1); usbd_xfer_set_frame_len(xfer, 0, 8); usbd_transfer_submit(xfer); 2nd callback: /* IMPORTANT: frbuffers[0] must still point at the setup packet! */ usbd_xfer_set_frames(xfer, 2); usbd_xfer_set_frame_len(xfer, 0, 0); usbd_xfer_set_frame_len(xfer, 1, 1); usbd_transfer_submit(xfer); Example4: SETUP + STATUS - split 1st callback: usbd_xfer_set_frames(xfer, 1); usbd_xfer_set_frame_len(xfer, 0, 8); usbd_xfer_set_flag(xfer, USB_MANUAL_STATUS); usbd_transfer_submit(xfer); 2nd callback: usbd_xfer_set_frames(xfer, 1); usbd_xfer_set_frame_len(xfer, 0, 0); usbd_xfer_clr_flag(xfer, USB_MANUAL_STATUS); usbd_transfer_submit(xfer); .Ed .Sh USB TRANSFER CONFIG To simply the search for endpoints the .Nm usb module defines a USB config structure where it is possible to specify the characteristics of the wanted endpoint. .Bd -literal -offset indent struct usb_config { bufsize, callback direction, endpoint, frames, index flags, interval, timeout, type, }; .Ed . .Pp .Fa type field selects the USB pipe type. . Valid values are: UE_INTERRUPT, UE_CONTROL, UE_BULK, UE_ISOCHRONOUS. . The special value UE_BULK_INTR will select BULK and INTERRUPT pipes. . This field is mandatory. . .Pp .Fa endpoint field selects the USB endpoint number. . A value of 0xFF, "-1" or "UE_ADDR_ANY" will select the first matching endpoint. . This field is mandatory. . .Pp .Fa direction field selects the USB endpoint direction. . A value of "UE_DIR_ANY" will select the first matching endpoint. . Else valid values are: "UE_DIR_IN" and "UE_DIR_OUT". . "UE_DIR_IN" and "UE_DIR_OUT" can be binary OR'ed by "UE_DIR_SID" which means that the direction will be swapped in case of USB_MODE_DEVICE. . Note that "UE_DIR_IN" refers to the data transfer direction of the "IN" tokens and "UE_DIR_OUT" refers to the data transfer direction of the "OUT" tokens. . This field is mandatory. . .Pp .Fa interval field selects the interrupt interval. . The value of this field is given in milliseconds and is independent of device speed. . Depending on the endpoint type, this field has different meaning: .Bl -tag -width "UE_ISOCHRONOUS" .It UE_INTERRUPT "0" use the default interrupt interval based on endpoint descriptor. "Else" use the given value for polling rate. .It UE_ISOCHRONOUS "0" use default. "Else" the value is ignored. .It UE_BULK .It UE_CONTROL "0" no transfer pre-delay. "Else" a delay as given by this field in milliseconds is inserted before the hardware is started when "usbd_transfer_submit()" is called. .Pp NOTE: The transfer timeout, if any, is started after that the pre-delay has elapsed! .El . .Pp .Fa timeout field, if non-zero, will set the transfer timeout in milliseconds. If the "timeout" field is zero and the transfer type is ISOCHRONOUS a timeout of 250ms will be used. . .Pp .Fa frames field sets the maximum number of frames. If zero is specified it will yield the following results: .Bl -tag -width "UE_INTERRUPT" .It UE_BULK xfer->nframes = 1; .It UE_INTERRUPT xfer->nframes = 1; .It UE_CONTROL xfer->nframes = 2; .It UE_ISOCHRONOUS Not allowed. Will cause an error. .El . .Pp .Fa ep_index field allows you to give a number, in case more endpoints match the description, that selects which matching "ep_index" should be used. . .Pp .Fa if_index field allows you to select which of the interface numbers in the "ifaces" array parameter passed to "usbd_transfer_setup" that should be used when setting up the given USB transfer. . .Pp .Fa flags field has type "struct usb_xfer_flags" and allows one to set initial flags an USB transfer. Valid flags are: .Bl -tag -width "force_short_xfer" .It force_short_xfer This flag forces the last transmitted USB packet to be short. A short packet has a length of less than "xfer->max_packet_size", which derives from "wMaxPacketSize". This flag can be changed during operation. .It short_xfer_ok This flag allows the received transfer length, "xfer->actlen" to be less than "xfer->sumlen" upon completion of a transfer. This flag can be changed during operation. .It short_frames_ok This flag allows the reception of multiple short USB frames. This flag only has effect for BULK and INTERRUPT endpoints and if the number of frames received is greater than 1. This flag can be changed during operation. .It pipe_bof This flag causes a failing USB transfer to remain first in the PIPE queue except in the case of "xfer->error" equal to "USB_ERR_CANCELLED". No other USB transfers in the affected PIPE queue will be started until either: .Bl -tag -width "X" .It 1 The failing USB transfer is stopped using "usbd_transfer_stop()". .It 2 The failing USB transfer performs a successful transfer. .El The purpose of this flag is to avoid races when multiple transfers are queued for execution on an USB endpoint, and the first executing transfer fails leading to the need for clearing of stall for example. . In this case this flag is used to prevent the following USB transfers from being executed at the same time the clear-stall command is executed on the USB control endpoint. . This flag can be changed during operation. .Pp "BOF" is short for "Block On Failure". .Pp NOTE: This flag should be set on all BULK and INTERRUPT USB transfers which use an endpoint that can be shared between userland and kernel. . . .It proxy_buffer Setting this flag will cause that the total buffer size will be rounded up to the nearest atomic hardware transfer size. . The maximum data length of any USB transfer is always stored in the "xfer->max_data_length". . For control transfers the USB kernel will allocate additional space for the 8-bytes of SETUP header. . These 8-bytes are not counted by the "xfer->max_data_length" variable. . This flag can not be changed during operation. . . .It ext_buffer Setting this flag will cause that no data buffer will be allocated. . Instead the USB client must supply a data buffer. . This flag can not be changed during operation. . . .It manual_status Setting this flag prevents an USB STATUS stage to be appended to the end of the USB control transfer. . If no control data is transferred this flag must be cleared. . Else an error will be returned to the USB callback. . This flag is mostly useful for the USB device side. . This flag can be changed during operation. . . .It no_pipe_ok Setting this flag causes the USB_ERR_NO_PIPE error to be ignored. This flag can not be changed during operation. . . .It stall_pipe .Bl -tag -width "Device Side Mode" .It Device Side Mode Setting this flag will cause STALL pids to be sent to the endpoint belonging to this transfer before the transfer is started. . The transfer is started at the moment the host issues a clear-stall command on the STALL'ed endpoint. . This flag can be changed during operation. .It Host Side Mode Setting this flag will cause a clear-stall control request to be executed on the endpoint before the USB transfer is started. .El .Pp If this flag is changed outside the USB callback function you have to use the "usbd_xfer_set_stall()" and "usbd_transfer_clear_stall()" functions! This flag is automatically cleared after that the stall or clear stall has been executed. . .It pre_scale_frames If this flag is set the number of frames specified is assumed to give the buffering time in milliseconds instead of frames. During transfer setup the frames field is pre scaled with the corresponding value for the endpoint and rounded to the nearest number of frames greater than zero. This option only has effect for ISOCHRONOUS transfers. .El .Pp .Fa bufsize field sets the total buffer size in bytes. . If this field is zero, "wMaxPacketSize" will be used, multiplied by the "frames" field if the transfer type is ISOCHRONOUS. . This is useful for setting up interrupt pipes. . This field is mandatory. .Pp NOTE: For control transfers "bufsize" includes the length of the request structure. . .Pp .Fa callback pointer sets the USB callback. This field is mandatory. . . .Sh USB LINUX COMPAT LAYER The .Nm usb module supports the Linux USB API. . . .Sh SEE ALSO .Xr libusb 3 , .Xr usb 4 , .Xr usbconfig 8 .Sh STANDARDS The .Nm usb module complies with the USB 2.0 standard. .Sh HISTORY The .Nm usb module has been inspired by the NetBSD USB stack initially written by Lennart Augustsson. The .Nm usb module was written by .An Hans Petter Selasky Aq Mt hselasky@FreeBSD.org . Index: projects/sendfile/share/man/man9/vm_page_busy.9 =================================================================== --- projects/sendfile/share/man/man9/vm_page_busy.9 (revision 276056) +++ projects/sendfile/share/man/man9/vm_page_busy.9 (revision 276057) @@ -1,216 +1,216 @@ .\" .\" Copyright (c) 2013 EMC Corp. .\" 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$ .Dd August 07, 2013 .Dt VM_PAGE_BUSY 9 .Os .Sh NAME .Nm vm_page_busied , .Nm vm_page_busy_downgrade , .Nm vm_page_busy_sleep , .Nm vm_page_sbusied , .Nm vm_page_sbusy , .Nm vm_page_sleep_if_busy , .Nm vm_page_sunbusy , .Nm vm_page_trysbusy , .Nm vm_page_tryxbusy , .Nm vm_page_xbusied , .Nm vm_page_xbusy , .Nm vm_page_xunbusy , .Nm vm_page_assert_sbusied , .Nm vm_page_assert_unbusied , .Nm vm_page_assert_xbusied .Nd protect page identity changes and page content references .Sh SYNOPSIS .In sys/param.h .In vm/vm.h .In vm/vm_page.h .Ft int .Fn vm_page_busied "vm_page_t m" .Ft void .Fn vm_page_busy_downgrade "vm_page_t m" .Ft void .Fn vm_page_busy_sleep "vm_page_t m" "const char *msg" .Ft int .Fn vm_page_sbusied "vm_page_t m" .Ft void .Fn vm_page_sbusy "vm_page_t m" .Ft int .Fn vm_page_sleep_if_busy "vm_page_t m" "const char *msg" .Ft void .Fn vm_page_sunbusy "vm_page_t m" .Ft int .Fn vm_page_trysbusy "vm_page_t m" .Ft int .Fn vm_page_tryxbusy "vm_page_t m" .Ft int .Fn vm_page_xbusied "vm_page_t m" .Ft void .Fn vm_page_xbusy "vm_page_t m" .Ft void .Fn vm_page_xunbusy "vm_page_t m" .Pp .Cd "options INVARIANTS" .Cd "options INVARIANT_SUPPORT" .Ft void .Fn vm_page_assert_sbusied "vm_page_t m" .Ft void .Fn vm_page_assert_unbusied "vm_page_t m" .Ft void .Fn vm_page_assert_xbusied "vm_page_t m" .Sh DESCRIPTION Page identity is usually protected by higher level locks like vm_object locks and vm page locks. However, sometimes it is not possible to hold such locks for the time necessary to complete the identity change. In such case the page can be exclusively busied by a thread which needs to own the identity for a certain amount of time. .Pp In other situations, threads do not need to change the identity of the page but they want to prevent other threads from changing the identity themselves. For example, when a thread wants to access or update page contents without a lock held the page is shared busied. .Pp Before busying a page the vm_object lock must be held. The same rule applies when a page is unbusied. This makes the vm_object lock a real busy interlock. .Pp The .Fn vm_page_busied function returns non-zero if the current thread busied .Fa m in either exclusive or shared mode. Returns zero otherwise. .Pp The .Fn vm_page_busy_downgrade function must be used to downgrade .Fa m from an exclusive busy state to a shared busy state. .Pp The .Fn vm_page_busy_sleep function puts the invoking thread to sleep using the appropriate waitchannels for the busy mechanism. The parameter .Fa msg is a string describing the sleep condition for userland tools. .Pp The .Fn vm_page_busied function returns non-zero if the current thread busied .Fa m in shared mode. Returns zero otherwise. .Pp The .Fn vm_page_sbusy function shared busies .Fa m . .Pp The .Fn vm_page_sleep_if_busy function puts the invoking thread to sleep, using the appropriate waitchannels for the busy mechanism, if .Fa m . is busied in either exclusive or shared mode. If the invoking thread slept a non-zero value is returned, otherwise 0 is returned. The parameter .Fa msg is a string describing the sleep condition for userland tools. .Pp The .Fn vm_page_sunbusy function shared unbusies .Fa m . .Pp The .Fn vm_page_trysbusy attempts to shared busy .Fa m . If the operation cannot immediately succeed .Fn vm_page_trysbusy returns 0, otherwise a non-zero value is returned. .Pp The .Fn vm_page_tryxbusy attempts to exclusive busy .Fa m . If the operation cannot immediately succeed .Fn vm_page_tryxbusy returns 0, otherwise a non-zero value is returned. .Pp The .Fn vm_page_xbusied function returns non-zero if the current thread busied .Fa m in exclusive mode. Returns zero otherwise. .Pp The .Fn vm_page_xbusy function exclusive busies .Fa m . .Pp The .Fn vm_page_xunbusy function exclusive unbusies .Fa m . Assertions on the busy state allow kernels compiled with .Cd "options INVARIANTS" and .Cd "options INVARIANT_SUPPORT" to panic if they are not respected. .Pp The .Fn vm_page_assert_sbusied function panics if .Fa m is not shared busied. .Pp The .Fn vm_page_assert_unbusied function panics if .Fa m is not unbusied. .Pp The .Fn vm_page_assert_xbusied function panics if .Fa m is not exclusive busied. .Sh SEE ALSO -.Xr VOP_GETPAGES 9 , .Xr vm_page_aflag 9 , .Xr vm_page_alloc 9 , .Xr vm_page_deactivate 9 , .Xr vm_page_free 9 , .Xr vm_page_grab 9 , .Xr vm_page_insert 9 , .Xr vm_page_lookup 9 , -.Xr vm_page_rename 9 +.Xr vm_page_rename 9 , +.Xr VOP_GETPAGES 9 Index: projects/sendfile/share/man/man9/vnet.9 =================================================================== --- projects/sendfile/share/man/man9/vnet.9 (revision 276056) +++ projects/sendfile/share/man/man9/vnet.9 (revision 276057) @@ -1,502 +1,497 @@ .\"- .\" Copyright (c) 2010 The FreeBSD Foundation .\" All rights reserved. .\" .\" This documentation was written by CK Software GmbH under sponsorship from .\" the FreeBSD Foundation. .\" .\" 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$ .\" .Dd November 20, 2014 .Dt VNET 9 .Os .Sh NAME .Nm VNET .Nd "network subsystem virtualization infrastructure" .Sh SYNOPSIS .Cd "options VIMAGE" .Cd "options VNET_DEBUG" .Pp .In sys/vnet.h .Pp .\"------------------------------------------------------------ .Ss "Constants and Global Variables" .\" .Dv VNET_SETNAME .\" "set_vnet" .Dv VNET_SYMPREFIX .\" "vnet_entry_" .Vt extern struct vnet *vnet0; .\"------------------------------------------------------------ .Ss "Variable Declaration" .Fo VNET .Fa "name" .Fc .\" .Fo VNET_NAME .Fa "name" .Fc .\" .Fo VNET_DECLARE .Fa "type" "name" .Fc .\" .Fo VNET_DEFINE .Fa "type" "name" .Fc .\" .Bd -literal #define V_name VNET(name) .Ed .\" ------------------------------------------------------------ .Ss "Virtual Instance Selection" .\" .Fo CRED_TO_VNET .Fa "struct ucred *" .Fc .\" .Fo TD_TO_VNET .Fa "struct thread *" .Fc .\" .Fo P_TO_VNET .Fa "struct proc *" .Fc .\" .Fo IS_DEFAULT_VNET .Fa "struct vnet *" .Fc .\" .Fo VNET_ASSERT .Fa exp msg .Fc .\" .Fo CURVNET_SET .Fa "struct vnet *" .Fc .\" .Fo CURVNET_SET_QUIET .Fa "struct vnet *" .Fc .\" -.Fo CURVNET_RESTORE -.Fc +.Fn CURVNET_RESTORE .\" .Fo VNET_ITERATOR_DECL .Fa "struct vnet *" .Fc .\" .Fo VNET_FOREACH .Fa "struct vnet *" .Fc .\" ------------------------------------------------------------ .Ss "Locking" .\" -.Fo VNET_LIST_RLOCK -.Fc -.Fo VNET_LIST_RUNLOCK -.Fc -.Fo VNET_LIST_RLOCK_NOSLEEP -.Fc -.Fo VNET_LIST_RUNLOCK_NOSLEEP -.Fc +.Fn VNET_LIST_RLOCK +.Fn VNET_LIST_RUNLOCK +.Fn VNET_LIST_RLOCK_NOSLEEP +.Fn VNET_LIST_RUNLOCK_NOSLEEP .\" ------------------------------------------------------------ .Ss "Startup and Teardown Functions" .\" .Ft "struct vnet *" .Fo vnet_alloc .Fa void .Fc .\" .Ft void .Fo vnet_destroy .Fa "struct vnet *" .Fc .\" .Fo VNET_SYSINIT .Fa ident .Fa "enum sysinit_sub_id subsystem" .Fa "enum sysinit_elem_order order" .Fa "sysinit_cfunc_t func" .Fa "const void *arg" .Fc .\" .Fo VNET_SYSUNINIT .Fa ident .Fa "enum sysinit_sub_id subsystem" .Fa "enum sysinit_elem_order order" .Fa "sysinit_cfunc_t func" .Fa "const void *arg" .Fc .\" ------------------------------------------------------------ .Ss "Eventhandlers" .\" .Fo VNET_GLOBAL_EVENTHANDLER_REGISTER .Fa "const char *name" .Fa "void *func" .Fa "void *arg" .Fa "int priority" .Fc .\" .Fo VNET_GLOBAL_EVENTHANDLER_REGISTER_TAG .Fa "eventhandler_tag tag" .Fa "const char *name" .Fa "void *func" .Fa "void *arg" .Fa "int priority" .Fc .\" ------------------------------------------------------------ .Ss "Sysctl Handling" .Fo SYSCTL_VNET_INT .Fa parent nbr name access ptr val descr .Fc .Fo SYSCTL_VNET_PROC .Fa parent nbr name access ptr arg handler fmt descr .Fc .Fo SYSCTL_VNET_STRING .Fa parent nbr name access arg len descr .Fc .Fo SYSCTL_VNET_STRUCT .Fa parent nbr name access ptr type descr .Fc .Fo SYSCTL_VNET_UINT .Fa parent nbr name access ptr val descr .Fc .Fo VNET_SYSCTL_ARG .Fa req arg1 .Fc .\" ------------------------------------------------------------ .Sh DESCRIPTION .Nm is the name of a technique to virtualize the network stack. The basic idea is to change global resources most notably variables into per network stack resources and have functions, sysctls, eventhandlers, etc. access and handle them in the context of the correct instance. Each (virtual) network stack is attached to a .Em prison , with .Vt vnet0 being the unrestricted default network stack of the base system. .Pp The global defines for .Dv VNET_SETNAME and .Dv VNET_SYMPREFIX are shared with .Xr kvm 3 to access internals for debugging reasons. .\" ------------------------------------------------------------ .Ss "Variable Declaration" .\" Variables are virtualized by using the .Fn VNET_DEFINE macro rather than writing them out as .Em type name . One can still use static initialization or storage class specifiers, e.g., .Pp .Dl Li static VNET_DEFINE(int, foo) = 1; or .Dl Li static VNET_DEFINE(SLIST_HEAD(, bar), bars); .Pp Static initialization is not possible when the virtualized variable would need to be referenced, e.g., with .Dq TAILQ_HEAD_INITIALIZER() . In that case a .Fn VNET_SYSINIT based initialization function must be used. .Pp External variables have to be declared using the .Fn VNET_DECLARE macro. In either case the convention is to define another macro, that is then used throughout the implementation to access that variable. The variable name is usually prefixed by .Em V_ to express that it is virtualized. The .Fn VNET macro will then translate accesses to that variable to the copy of the currently selected instance (see the .Sx "Virtual instance selection" section): .Pp .Dl Li #define V_name VNET(name) .Pp .Em NOTE: Do not confuse this with the convention used by .Xr VFS 9 . .Pp The .Fn VNET_NAME macro returns the offset within the memory region of the virtual network stack instance. It is usually only used with .Fn SYSCTL_VNET_* macros. .\" ------------------------------------------------------------ .Ss "Virtual Instance Selection" .\" There are three different places where the current virtual network stack pointer is stored and can be taken from: .Bl -enum -offset indent .It a .Em prison : .Dl "(struct prison *)->pr_vnet" .Pp For convenience the following macros are provided: .Bd -literal -compact -offset indent .Fn CRED_TO_VNET "struct ucred *" .Fn TD_TO_VNET "struct thread *" .Fn P_TO_VNET "struct proc *" .Ed .It a .Em socket : .Dl "(struct socket *)->so_vnet" .It an .Em interface : .Dl "(struct ifnet *)->if_vnet" .El .Pp .\" In addition the currently active instance is cached in .Dq "curthread->td_vnet" which is usually only accessed through the .Dv curvnet macro. .Pp .\" To set the correct context of the current virtual network instance, use the .Fn CURVNET_SET or .Fn CURVNET_SET_QUIET macros. The .Fn CURVNET_SET_QUIET version will not record vnet recursions in case the kernel was compiled with .Cd "options VNET_DEBUG" and should thus only be used in well known cases, where recursion is unavoidable. Both macros will save the previous state on the stack and it must be restored with the .Fn CURVNET_RESTORE macro. .Pp .Em NOTE: As the previous state is saved on the stack, you cannot have multiple .Fn CURVNET_SET calls in the same block. .Pp .Em NOTE: As the previous state is saved on the stack, a .Fn CURVNET_RESTORE call has to be in the same block as the .Fn CURVNET_SET call or in a subblock with the same idea of the saved instances as the outer block. .Pp .Em NOTE: As each macro is a set of operations and, as previously explained, cannot be put into its own block when defined, one cannot conditionally set the current vnet context. The following will .Em not work: .Bd -literal -offset indent if (condition) CURVNET_SET(vnet); .Ed .Pp nor would this work: .Bd -literal -offset indent if (condition) { CURVNET_SET(vnet); } CURVNET_RESTORE(); .Ed .Pp .\" Sometimes one needs to loop over all virtual instances, for example to update virtual from global state, to run a function from a .Xr callout 9 for each instance, etc. For those cases the .Fn VNET_ITERATOR_DECL and .Fn VNET_FOREACH macros are provided. The former macro defines the variable that iterates over the loop, and the latter loops over all of the virtual network stack instances. See .Sx "Locking" for how to savely traverse the list of all virtual instances. .Pp .\" The .Fn IS_DEFAULT_VNET macro provides a safe way to check whether the currently active instance is the unrestricted default network stack of the base system .Pq Vt vnet0 . .Pp .\" The .Fn VNET_ASSERT macro provides a way to conditionally add assertions that are only active with .Cd "options VIMAGE" compiled in and either .Cd "options VNET_DEBUG" or .Cd "options INVARIANTS" enabled as well. It uses the same semantics as .Xr KASSERT 9 . .\" ------------------------------------------------------------ .Ss "Locking" .\" For public access to the list of virtual network stack instances e.g., by the .Fn VNET_FOREACH macro, read locks are provided. Macros are used to abstract from the actual type of the locks. If a caller may sleep while traversing the list, it must use the .Fn VNET_LIST_RLOCK and .Fn VNET_LIST_RUNLOCK macros. Otherwise, the caller can use .Fn VNET_LIST_RLOCK_NOSLEEP and .Fn VNET_LIST_RUNLOCK_NOSLEEP . .\" ------------------------------------------------------------ .Ss "Startup and Teardown Functions" .\" To start or tear down a virtual network stack instance the internal functions .Fn vnet_alloc and .Fn vnet_destroy are provided and called from the jail framework. They run the publicly provided methods to handle network stack startup and teardown. .Pp For public control, the system startup interface has been enhanced to not only handle a system boot but to also handle a virtual network stack startup and teardown. To the base system the .Fn VNET_SYSINIT and .Fn VNET_SYSUNINIT macros look exactly as if there were no virtual network stack. In fact, if .Cd "options VIMAGE" is not compiled in they are compiled to the standard .Fn SYSINIT macros. In addition to that they are run for each virtual network stack when starting or, in reverse order, when shutting down. .\" ------------------------------------------------------------ .Ss "Eventhandlers" .\" Eventhandlers can be handled in two ways: .Pp .Bl -enum -offset indent -compact .It save the .Em tags returned in each virtual instance and properly free the eventhandlers on teardown using those, or .It use one eventhandler that will iterate over all virtual network stack instances. .El .Pp For the first case one can just use the normal .Xr EVENTHANDLER 9 functions, while for the second case the .Fn VNET_GLOBAL_EVENTHANDLER_REGISTER and .Fn VNET_GLOBAL_EVENTHANDLER_REGISTER_TAG macros are provided. These differ in that .Fn VNET_GLOBAL_EVENTHANDLER_REGISTER_TAG takes an extra first argument that will carry the .Fa "tag" upon return. Eventhandlers registered with either of these will not run .Fa func directly but .Fa func will be called from an internal iterator function for each vnet. Both macros can only be used for eventhandlers that do not take additional arguments, as the variadic arguments from an .Xr EVENTHANDLER_INVOKE 9 call will be ignored. .\" ------------------------------------------------------------ .Ss "Sysctl Handling" .\" A .Xr sysctl 9 can be virtualized by using one of the .Fn SYSCTL_VNET_* macros. .Pp They take the same arguments as the standard .Xr sysctl 9 functions, with the only difference, that the .Fa ptr argument has to be passed as .Ql &VNET_NAME(foo) instead of .Ql &foo so that the variable can be selected from the correct memory region of the virtual network stack instance of the caller. .Pp For the very rare case a sysctl handler function would want to handle .Fa arg1 itself the .Fn VNET_SYSCTL_ARG req arg1 is provided that will translate the .Fa arg1 argument to the correct memory address in the virtual network stack context of the caller. .\" ------------------------------------------------------------ .Sh SEE ALSO .Xr jail 2 , .Xr kvm 3 , .Xr EVENTHANDLER 9 , .\" .Xr pcpu 9 , .Xr KASSERT 9 , .Xr sysctl 9 .\" .Xr SYSINIT 9 .Sh HISTORY The virtual network stack implementation first appeared in .Fx 8.0 . .Sh AUTHORS This manual page was written by .An Bjoern A. Zeeb, CK Software GmbH, under sponsorship from the FreeBSD Foundation. Index: projects/sendfile/share/man/man9/vnode.9 =================================================================== --- projects/sendfile/share/man/man9/vnode.9 (revision 276056) +++ projects/sendfile/share/man/man9/vnode.9 (revision 276057) @@ -1,197 +1,197 @@ .\" Copyright (c) 1996 Doug Rabson .\" .\" All rights reserved. .\" .\" This program is free software. .\" .\" 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 DEVELOPERS ``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 DEVELOPERS 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$ .\" .Dd February 12, 2014 .Dt VNODE 9 .Os .Sh NAME .Nm vnode .Nd internal representation of a file or directory .Sh SYNOPSIS .In sys/param.h .In sys/vnode.h .Sh DESCRIPTION The vnode is the focus of all file activity in .Ux . A vnode is described by .Vt "struct vnode" . There is a unique vnode allocated for each active file, each current directory, each mounted-on file, text file, and the root. .Pp Each vnode has three reference counts, .Va v_usecount , .Va v_holdcnt and .Va v_writecount . The first is the number of clients within the kernel which are using this vnode. This count is maintained by .Xr vref 9 , .Xr vrele 9 and .Xr vput 9 . The second is the number of clients within the kernel who veto the recycling of this vnode. This count is maintained by .Xr vhold 9 and .Xr vdrop 9 . When both the .Va v_usecount and the .Va v_holdcnt of a vnode reaches zero then the vnode will be put on the freelist and may be reused for another file, possibly in another file system. The transition from the freelist is handled by .Xr getnewvnode 9 . The third is a count of the number of clients which are writing into the file. It is maintained by the .Xr open 2 and .Xr close 2 system calls. .Pp Any call which returns a vnode (e.g.,\& .Xr vget 9 , .Xr VOP_LOOKUP 9 , etc.) will increase the .Va v_usecount of the vnode by one. When the caller is finished with the vnode, it should release this reference by calling .Xr vrele 9 (or .Xr vput 9 if the vnode is locked). .Pp Other commonly used members of the vnode structure are .Va v_id which is used to maintain consistency in the name cache, .Va v_mount which points at the file system which owns the vnode, .Va v_type which contains the type of object the vnode represents and .Va v_data which is used by file systems to store file system specific data with the vnode. The .Va v_op field is used by the .Dv VOP_* macros to call functions in the file system which implement the vnode's functionality. .Sh VNODE TYPES .Bl -tag -width VSOCK .It Dv VNON No type. .It Dv VREG A regular file; may be with or without VM object backing. If you want to make sure this get a backing object, call .Fn vnode_create_vobject . .It Dv VDIR A directory. .It Dv VBLK A block device; may be with or without VM object backing. If you want to make sure this get a backing object, call .Fn vnode_create_vobject . .It Dv VCHR A character device. .It Dv VLNK A symbolic link. .It Dv VSOCK A socket. Advisory locking will not work on this. .It Dv VFIFO A FIFO (named pipe). Advisory locking will not work on this. .It Dv VBAD Indicates that the vnode has been reclaimed. .El .Sh IMPLEMENTATION NOTES VFIFO uses the "struct fileops" from .Pa /sys/kern/sys_pipe.c . VSOCK uses the "struct fileops" from .Pa /sys/kern/sys_socket.c . Everything else uses the one from .Pa /sys/kern/vfs_vnops.c . .Pp The VFIFO/VSOCK code, which is why "struct fileops" is used at all, is an artifact of an incomplete integration of the VFS code into the kernel. .Pp Calls to .Xr malloc 9 or .Xr free 9 when holding a .Nm interlock, will cause a LOR (Lock Order Reversal) due to the intertwining of VM Objects and Vnodes. .Sh SEE ALSO .Xr malloc 9 , +.Xr VFS 9 , .Xr VOP_ACCESS 9 , .Xr VOP_ACLCHECK 9 , .Xr VOP_ADVISE 9 , .Xr VOP_ADVLOCK 9 , .Xr VOP_ALLOCATE 9 , .Xr VOP_ATTRIB 9 , .Xr VOP_BWRITE 9 , .Xr VOP_CREATE 9 , .Xr VOP_FSYNC 9 , .Xr VOP_GETACL 9 , .Xr VOP_GETEXTATTR 9 , .Xr VOP_GETPAGES 9 , .Xr VOP_INACTIVE 9 , .Xr VOP_IOCTL 9 , .Xr VOP_LINK 9 , .Xr VOP_LISTEXTATTR 9 , .Xr VOP_LOCK 9 , .Xr VOP_LOOKUP 9 , .Xr VOP_OPENCLOSE 9 , .Xr VOP_PATHCONF 9 , .Xr VOP_PRINT 9 , .Xr VOP_RDWR 9 , .Xr VOP_READDIR 9 , .Xr VOP_READLINK 9 , .Xr VOP_REALLOCBLKS 9 , .Xr VOP_REMOVE 9 , .Xr VOP_RENAME 9 , .Xr VOP_REVOKE 9 , .Xr VOP_SETACL 9 , .Xr VOP_SETEXTATTR 9 , .Xr VOP_STRATEGY 9 , .Xr VOP_VPTOCNP 9 , -.Xr VOP_VPTOFH 9 , -.Xr VFS 9 +.Xr VOP_VPTOFH 9 .Sh AUTHORS This manual page was written by .An Doug Rabson . Index: projects/sendfile/share/man/man9/zone.9 =================================================================== --- projects/sendfile/share/man/man9/zone.9 (revision 276056) +++ projects/sendfile/share/man/man9/zone.9 (revision 276057) @@ -1,375 +1,375 @@ .\"- .\" Copyright (c) 2001 Dag-Erling Coïdan Smørgrav .\" 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$ .\" .Dd February 7, 2014 .Dt ZONE 9 .Os .Sh NAME .Nm uma_zcreate , .Nm uma_zalloc , .Nm uma_zalloc_arg , .Nm uma_zfree , .Nm uma_zfree_arg , .Nm uma_find_refcnt , .Nm uma_zdestroy , .Nm uma_zone_set_max, .Nm uma_zone_get_max, .Nm uma_zone_get_cur, .Nm uma_zone_set_warning .Nd zone allocator .Sh SYNOPSIS .In sys/param.h .In sys/queue.h .In vm/uma.h .Ft uma_zone_t .Fo uma_zcreate .Fa "char *name" "int size" .Fa "uma_ctor ctor" "uma_dtor dtor" "uma_init uminit" "uma_fini fini" .Fa "int align" "uint16_t flags" .Fc .Ft "void *" .Fn uma_zalloc "uma_zone_t zone" "int flags" .Ft "void *" .Fn uma_zalloc_arg "uma_zone_t zone" "void *arg" "int flags" .Ft void .Fn uma_zfree "uma_zone_t zone" "void *item" .Ft void .Fn uma_zfree_arg "uma_zone_t zone" "void *item" "void *arg" .Ft "uint32_t *" .Fn uma_find_refcnt "uma_zone_t zone" "void *item" .Ft void .Fn uma_zdestroy "uma_zone_t zone" .Ft int .Fn uma_zone_set_max "uma_zone_t zone" "int nitems" .Ft int .Fn uma_zone_get_max "uma_zone_t zone" .Ft int .Fn uma_zone_get_cur "uma_zone_t zone" .Ft void .Fn uma_zone_set_warning "uma_zone_t zone" "const char *warning" .In sys/sysctl.h .Fn SYSCTL_UMA_MAX parent nbr name access zone descr .Fn SYSCTL_ADD_UMA_MAX ctx parent nbr name access zone descr .Fn SYSCTL_UMA_CUR parent nbr name access zone descr .Fn SYSCTL_ADD_UMA_CUR ctx parent nbr name access zone descr .Sh DESCRIPTION The zone allocator provides an efficient interface for managing dynamically-sized collections of items of similar size. The zone allocator can work with preallocated zones as well as with runtime-allocated ones, and is therefore available much earlier in the boot process than other memory management routines. .Pp A zone is an extensible collection of items of identical size. The zone allocator keeps track of which items are in use and which are not, and provides functions for allocating items from the zone and for releasing them back (which makes them available for later use). .Pp After the first allocation of an item, it will have been cleared to zeroes, however subsequent allocations will retain the contents as of the last free. .Pp The .Fn uma_zcreate function creates a new zone from which items may then be allocated from. The .Fa name argument is a text name of the zone for debugging and stats; this memory should not be freed until the zone has been deallocated. .Pp The .Fa ctor and .Fa dtor arguments are callback functions that are called by the uma subsystem at the time of the call to .Fn uma_zalloc and .Fn uma_zfree respectively. Their purpose is to provide hooks for initializing or destroying things that need to be done at the time of the allocation or release of a resource. A good usage for the .Fa ctor and .Fa dtor callbacks might be to adjust a global count of the number of objects allocated. .Pp The .Fa uminit and .Fa fini arguments are used to optimize the allocation of objects from the zone. They are called by the uma subsystem whenever it needs to allocate or free several items to satisfy requests or memory pressure. A good use for the .Fa uminit and .Fa fini callbacks might be to initialize and destroy mutexes contained within the object. This would allow one to re-use already initialized mutexes when an object is returned from the uma subsystem's object cache. They are not called on each call to .Fn uma_zalloc and .Fn uma_zfree but rather in a batch mode on several objects. .Pp The .Fa flags argument of the .Fn uma_zcreate is a subset of the following flags: .Bl -tag -width "foo" .It Dv UMA_ZONE_NOFREE Slabs of the zone are never returned back to VM. .It Dv UMA_ZONE_REFCNT Each item in the zone would have internal reference counter associated with it. See .Fn uma_find_refcnt . .It Dv UMA_ZONE_NODUMP Pages belonging to the zone will not be included into mini-dumps. .It Dv UMA_ZONE_PCPU An allocation from zone would have .Va mp_ncpu shadow copies, that are privately assigned to CPUs. A CPU can address its private copy using base allocation address plus multiple of current CPU id and .Fn sizeof "struct pcpu" : .Bd -literal -offset indent foo_zone = uma_zcreate(..., UMA_ZONE_PCPU); ... foo_base = uma_zalloc(foo_zone, ...); ... critical_enter(); foo_pcpu = (foo_t *)zpcpu_get(foo_base); /* do something with foo_pcpu */ critical_exit(); .Ed .It Dv UMA_ZONE_OFFPAGE By default book-keeping of items within a slab is done in the slab page itself. This flag explicitly tells subsystem that book-keeping structure should be allocated separately from special internal zone. This flag requires either .Dv UMA_ZONE_VTOSLAB or .Dv UMA_ZONE_HASH , since subsystem requires a mechanism to find a book-keeping structure to an item beeing freed. The subsystem may choose to prefer offpage book-keeping for certain zones implicitly. .It Dv UMA_ZONE_ZINIT The zone will have its .Ft uma_init method set to internal method that initializes a new allocated slab to all zeros. Do not mistake .Ft uma_init method with .Ft uma_ctor . A zone with .Dv UMA_ZONE_ZINIT flag would not return zeroed memory on every .Fn uma_zalloc . .It Dv UMA_ZONE_HASH The zone should use an internal hash table to find slab book-keeping structure where an allocation being freed belongs to. .It Dv UMA_ZONE_VTOSLAB The zone should use special field of .Vt vm_page_t to find slab book-keeping structure where an allocation being freed belongs to. .It Dv UMA_ZONE_MALLOC The zone is for the .Xr malloc 9 subsystem. .It Dv UMA_ZONE_VM The zone is for the VM subsystem. .El .Pp To allocate an item from a zone, simply call .Fn uma_zalloc with a pointer to that zone and set the .Fa flags argument to selected flags as documented in .Xr malloc 9 . It will return a pointer to an item if successful, or .Dv NULL in the rare case where all items in the zone are in use and the allocator is unable to grow the zone and .Dv M_NOWAIT is specified. .Pp Items are released back to the zone from which they were allocated by calling .Fn uma_zfree with a pointer to the zone and a pointer to the item. If .Fa item is .Dv NULL , then .Fn uma_zfree does nothing. .Pp The variations .Fn uma_zalloc_arg and .Fn uma_zfree_arg allow to specify an argument for the .Dv ctor and .Dv dtor functions, respectively. .Pp If zone was created with .Dv UMA_ZONE_REFCNT flag, then pointer to reference counter for an item can be retrieved with help of the .Fn uma_find_refcnt function. .Pp Created zones, which are empty, can be destroyed using .Fn uma_zdestroy , freeing all memory that was allocated for the zone. All items allocated from the zone with .Fn uma_zalloc must have been freed with .Fn uma_zfree before. .Pp The .Fn uma_zone_set_max function limits the number of items .Pq and therefore memory that can be allocated to .Fa zone . The .Fa nitems argument specifies the requested upper limit number of items. The effective limit is returned to the caller, as it may end up being higher than requested due to the implementation rounding up to ensure all memory pages allocated to the zone are utilised to capacity. The limit applies to the total number of items in the zone, which includes allocated items, free items and free items in the per-cpu caches. On systems with more than one CPU it may not be possible to allocate the specified number of items even when there is no shortage of memory, because all of the remaining free items may be in the caches of the other CPUs when the limit is hit. .Pp The .Fn uma_zone_get_max function returns the effective upper limit number of items for a zone. .Pp The .Fn uma_zone_get_cur function returns the approximate current occupancy of the zone. The returned value is approximate because appropriate synchronisation to determine an exact value is not performed by the implementation. This ensures low overhead at the expense of potentially stale data being used in the calculation. .Pp The .Fn uma_zone_set_warning function sets a warning that will be printed on the system console when the given zone becomes full and fails to allocate an item. The warning will be printed not often than every five minutes. Warnings can be turned off globally by setting the .Va vm.zone_warnings sysctl tunable to .Va 0 . .Pp The .Fn SYSCTL_UMA_MAX parent nbr name access zone descr macro declares a static .Xr sysctl oid that exports the effective upper limit number of items for a zone. The .Fa zone argument should be a pointer to .Vt uma_zone_t . A read of the oid returns value obtained through .Fn uma_zone_get_max . A write to the oid sets new value via .Fn uma_zone_set_max . The .Fn SYSCTL_ADD_UMA_MAX ctx parent nbr name access zone descr macro is provided to create this type of oid dynamically. .Pp The .Fn SYSCTL_UMA_CUR parent nbr name access zone descr macro declares a static read only .Xr sysctl oid that exports the approximate current occupancy of the zone. The .Fa zone -argument should be a pointer to +argument should be a pointer to .Vt uma_zone_t . A read of the oid returns value obtained through .Fn uma_zone_get_cur . The .Fn SYSCTL_ADD_UMA_CUR ctx parent nbr name zone descr macro is provided to create this type of oid dynamically. .Sh RETURN VALUES The .Fn uma_zalloc function returns a pointer to an item, or .Dv NULL if the zone ran out of unused items and .Dv M_NOWAIT was specified. .Sh SEE ALSO .Xr malloc 9 .Sh HISTORY The zone allocator first appeared in .Fx 3.0 . It was radically changed in .Fx 5.0 to function as a slab allocator. .Sh AUTHORS .An -nosplit The zone allocator was written by .An John S. Dyson . The zone allocator was rewritten in large parts by .An Jeff Roberson Aq Mt jeff@FreeBSD.org to function as a slab allocator. .Pp This manual page was written by .An Dag-Erling Sm\(/orgrav Aq Mt des@FreeBSD.org . Changes for UMA by .An Jeroen Ruigrok van der Werven Aq Mt asmodai@FreeBSD.org . Index: projects/sendfile/share =================================================================== --- projects/sendfile/share (revision 276056) +++ projects/sendfile/share (revision 276057) Property changes on: projects/sendfile/share ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/share:r275989-276056 Index: projects/sendfile/sys/arm/allwinner/a20/std.a20 =================================================================== --- projects/sendfile/sys/arm/allwinner/a20/std.a20 (revision 276056) +++ projects/sendfile/sys/arm/allwinner/a20/std.a20 (revision 276057) @@ -1,24 +1,25 @@ # Allwinner A20 common options #$FreeBSD$ cpu CPU_CORTEXA machine arm armv6 +makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a" makeoption ARM_LITTLE_ENDIAN # Physical memory starts at 0x40200000. We assume images are loaded at # 0x40200000, e.g. from u-boot with 'fatload mmc 0 0x40200000 kernel' # # options PHYSADDR=0x40000000 makeoptions KERNPHYSADDR=0x40200000 options KERNPHYSADDR=0x40200000 makeoptions KERNVIRTADDR=0xc0200000 options KERNVIRTADDR=0xc0200000 options ARM_L2_PIPT options IPI_IRQ_START=0 options IPI_IRQ_END=15 files "../allwinner/a20/files.a20" Index: projects/sendfile/sys/arm/allwinner/std.a10 =================================================================== --- projects/sendfile/sys/arm/allwinner/std.a10 (revision 276056) +++ projects/sendfile/sys/arm/allwinner/std.a10 (revision 276057) @@ -1,19 +1,20 @@ # Allwinner A10 common options #$FreeBSD$ cpu CPU_CORTEXA machine arm armv6 +makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a" makeoption ARM_LITTLE_ENDIAN # Physical memory starts at 0x40200000. We assume images are loaded at # 0x40200000, e.g. from u-boot with 'fatload mmc 0 0x40200000 kernel' # # options PHYSADDR=0x40000000 makeoptions KERNPHYSADDR=0x40200000 options KERNPHYSADDR=0x40200000 makeoptions KERNVIRTADDR=0xc0200000 options KERNVIRTADDR=0xc0200000 files "../allwinner/files.a10" Index: projects/sendfile/sys/arm/altera/socfpga/std.socfpga =================================================================== --- projects/sendfile/sys/arm/altera/socfpga/std.socfpga (revision 276056) +++ projects/sendfile/sys/arm/altera/socfpga/std.socfpga (revision 276057) @@ -1,21 +1,22 @@ # $FreeBSD$ makeoption ARM_LITTLE_ENDIAN cpu CPU_CORTEXA machine arm armv6 +makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a" options PHYSADDR=0x00000000 makeoptions KERNPHYSADDR=0x00f00000 options KERNPHYSADDR=0x00f00000 makeoptions KERNVIRTADDR=0xc0f00000 options KERNVIRTADDR=0xc0f00000 options ARM_L2_PIPT options IPI_IRQ_START=0 options IPI_IRQ_END=15 files "../altera/socfpga/files.socfpga" Index: projects/sendfile/sys/arm/arm/db_trace.c =================================================================== --- projects/sendfile/sys/arm/arm/db_trace.c (revision 276056) +++ projects/sendfile/sys/arm/arm/db_trace.c (revision 276057) @@ -1,641 +1,648 @@ /* $NetBSD: db_trace.c,v 1.8 2003/01/17 22:28:48 thorpej Exp $ */ /*- * Copyright (c) 2000, 2001 Ben Harris * Copyright (c) 1996 Scott K. Stevens * * Mach Operating System * Copyright (c) 1991,1990 Carnegie Mellon University * All Rights Reserved. * * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __ARM_EABI__ /* * Definitions for the instruction interpreter. * * The ARM EABI specifies how to perform the frame unwinding in the * Exception Handling ABI for the ARM Architecture document. To perform * the unwind we need to know the initial frame pointer, stack pointer, * link register and program counter. We then find the entry within the * index table that points to the function the program counter is within. * This gives us either a list of three instructions to process, a 31-bit * relative offset to a table of instructions, or a value telling us * we can't unwind any further. * * When we have the instructions to process we need to decode them * following table 4 in section 9.3. This describes a collection of bit * patterns to encode that steps to take to update the stack pointer and * link register to the correct values at the start of the function. */ /* A special case when we are unable to unwind past this function */ #define EXIDX_CANTUNWIND 1 /* The register names */ #define FP 11 #define SP 13 #define LR 14 #define PC 15 /* * These are set in the linker script. Their addresses will be * either the start or end of the exception table or index. */ extern int extab_start, extab_end, exidx_start, exidx_end; /* * Entry types. * These are the only entry types that have been seen in the kernel. */ #define ENTRY_MASK 0xff000000 #define ENTRY_ARM_SU16 0x80000000 #define ENTRY_ARM_LU16 0x81000000 /* Instruction masks. */ #define INSN_VSP_MASK 0xc0 #define INSN_VSP_SIZE_MASK 0x3f #define INSN_STD_MASK 0xf0 #define INSN_STD_DATA_MASK 0x0f #define INSN_POP_TYPE_MASK 0x08 #define INSN_POP_COUNT_MASK 0x07 #define INSN_VSP_LARGE_INC_MASK 0xff /* Instruction definitions */ #define INSN_VSP_INC 0x00 #define INSN_VSP_DEC 0x40 #define INSN_POP_MASKED 0x80 #define INSN_VSP_REG 0x90 #define INSN_POP_COUNT 0xa0 #define INSN_FINISH 0xb0 #define INSN_POP_REGS 0xb1 #define INSN_VSP_LARGE_INC 0xb2 /* An item in the exception index table */ struct unwind_idx { uint32_t offset; uint32_t insn; }; /* The state of the unwind process */ struct unwind_state { uint32_t registers[16]; uint32_t start_pc; uint32_t *insn; u_int entries; u_int byte; uint16_t update_mask; }; /* Expand a 31-bit signed value to a 32-bit signed value */ static __inline int32_t db_expand_prel31(uint32_t prel31) { return ((int32_t)(prel31 & 0x7fffffffu) << 1) / 2; } /* * Perform a binary search of the index table to find the function * with the largest address that doesn't exceed addr. */ static struct unwind_idx * db_find_index(uint32_t addr) { unsigned int min, mid, max; struct unwind_idx *start; struct unwind_idx *item; int32_t prel31_addr; uint32_t func_addr; start = (struct unwind_idx *)&exidx_start; min = 0; max = (&exidx_end - &exidx_start) / 2; while (min != max) { mid = min + (max - min + 1) / 2; item = &start[mid]; prel31_addr = db_expand_prel31(item->offset); func_addr = (uint32_t)&item->offset + prel31_addr; if (func_addr <= addr) { min = mid; } else { max = mid - 1; } } return &start[min]; } /* Reads the next byte from the instruction list */ static uint8_t db_unwind_exec_read_byte(struct unwind_state *state) { uint8_t insn; /* Read the unwind instruction */ insn = (*state->insn) >> (state->byte * 8); /* Update the location of the next instruction */ if (state->byte == 0) { state->byte = 3; state->insn++; state->entries--; } else state->byte--; return insn; } /* Executes the next instruction on the list */ static int db_unwind_exec_insn(struct unwind_state *state) { unsigned int insn; uint32_t *vsp = (uint32_t *)state->registers[SP]; int update_vsp = 0; /* This should never happen */ if (state->entries == 0) return 1; /* Read the next instruction */ insn = db_unwind_exec_read_byte(state); if ((insn & INSN_VSP_MASK) == INSN_VSP_INC) { state->registers[SP] += ((insn & INSN_VSP_SIZE_MASK) << 2) + 4; } else if ((insn & INSN_VSP_MASK) == INSN_VSP_DEC) { state->registers[SP] -= ((insn & INSN_VSP_SIZE_MASK) << 2) + 4; } else if ((insn & INSN_STD_MASK) == INSN_POP_MASKED) { unsigned int mask, reg; /* Load the mask */ mask = db_unwind_exec_read_byte(state); mask |= (insn & INSN_STD_DATA_MASK) << 8; /* We have a refuse to unwind instruction */ if (mask == 0) return 1; /* Update SP */ update_vsp = 1; /* Load the registers */ for (reg = 4; mask && reg < 16; mask >>= 1, reg++) { if (mask & 1) { state->registers[reg] = *vsp++; state->update_mask |= 1 << reg; /* If we have updated SP kep its value */ if (reg == SP) update_vsp = 0; } } } else if ((insn & INSN_STD_MASK) == INSN_VSP_REG && ((insn & INSN_STD_DATA_MASK) != 13) && ((insn & INSN_STD_DATA_MASK) != 15)) { /* sp = register */ state->registers[SP] = state->registers[insn & INSN_STD_DATA_MASK]; } else if ((insn & INSN_STD_MASK) == INSN_POP_COUNT) { unsigned int count, reg; /* Read how many registers to load */ count = insn & INSN_POP_COUNT_MASK; /* Update sp */ update_vsp = 1; /* Pop the registers */ for (reg = 4; reg <= 4 + count; reg++) { state->registers[reg] = *vsp++; state->update_mask |= 1 << reg; } /* Check if we are in the pop r14 version */ if ((insn & INSN_POP_TYPE_MASK) != 0) { state->registers[14] = *vsp++; } } else if (insn == INSN_FINISH) { /* Stop processing */ state->entries = 0; } else if (insn == INSN_POP_REGS) { unsigned int mask, reg; mask = db_unwind_exec_read_byte(state); if (mask == 0 || (mask & 0xf0) != 0) return 1; /* Update SP */ update_vsp = 1; /* Load the registers */ for (reg = 0; mask && reg < 4; mask >>= 1, reg++) { if (mask & 1) { state->registers[reg] = *vsp++; state->update_mask |= 1 << reg; } } } else if ((insn & INSN_VSP_LARGE_INC_MASK) == INSN_VSP_LARGE_INC) { unsigned int uleb128; /* Read the increment value */ uleb128 = db_unwind_exec_read_byte(state); state->registers[SP] += 0x204 + (uleb128 << 2); } else { /* We hit a new instruction that needs to be implemented */ db_printf("Unhandled instruction %.2x\n", insn); return 1; } if (update_vsp) { state->registers[SP] = (uint32_t)vsp; } #if 0 db_printf("fp = %08x, sp = %08x, lr = %08x, pc = %08x\n", state->registers[FP], state->registers[SP], state->registers[LR], state->registers[PC]); #endif return 0; } /* Performs the unwind of a function */ static int db_unwind_tab(struct unwind_state *state) { uint32_t entry; /* Set PC to a known value */ state->registers[PC] = 0; /* Read the personality */ entry = *state->insn & ENTRY_MASK; if (entry == ENTRY_ARM_SU16) { state->byte = 2; state->entries = 1; } else if (entry == ENTRY_ARM_LU16) { state->byte = 1; state->entries = ((*state->insn >> 16) & 0xFF) + 1; } else { db_printf("Unknown entry: %x\n", entry); return 1; } while (state->entries > 0) { if (db_unwind_exec_insn(state) != 0) return 1; } /* * The program counter was not updated, load it from the link register. */ - if (state->registers[PC] == 0) + if (state->registers[PC] == 0) { state->registers[PC] = state->registers[LR]; + + /* + * If the program counter changed, flag it in the update mask. + */ + if (state->start_pc != state->registers[PC]) + state->update_mask |= 1 << PC; + } return 0; } static void db_stack_trace_cmd(struct unwind_state *state) { struct unwind_idx *index; const char *name; db_expr_t value; db_expr_t offset; c_db_sym_t sym; u_int reg, i; char *sep; uint16_t upd_mask; bool finished; finished = false; while (!finished) { /* Reset the mask of updated registers */ state->update_mask = 0; /* The pc value is correct and will be overwritten, save it */ state->start_pc = state->registers[PC]; /* Find the item to run */ index = db_find_index(state->start_pc); if (index->insn != EXIDX_CANTUNWIND) { if (index->insn & (1U << 31)) { /* The data is within the instruction */ state->insn = &index->insn; } else { /* A prel31 offset to the unwind table */ state->insn = (uint32_t *) ((uintptr_t)&index->insn + db_expand_prel31(index->insn)); } /* Run the unwind function */ finished = db_unwind_tab(state); } /* Print the frame details */ sym = db_search_symbol(state->start_pc, DB_STGY_ANY, &offset); if (sym == C_DB_SYM_NULL) { value = 0; name = "(null)"; } else db_symbol_values(sym, &name, &value); db_printf("%s() at ", name); db_printsym(state->start_pc, DB_STGY_PROC); db_printf("\n"); db_printf("\t pc = 0x%08x lr = 0x%08x (", state->start_pc, state->registers[LR]); db_printsym(state->registers[LR], DB_STGY_PROC); db_printf(")\n"); db_printf("\t sp = 0x%08x fp = 0x%08x", state->registers[SP], state->registers[FP]); /* Don't print the registers we have already printed */ upd_mask = state->update_mask & ~((1 << SP) | (1 << FP) | (1 << LR) | (1 << PC)); sep = "\n\t"; for (i = 0, reg = 0; upd_mask != 0; upd_mask >>= 1, reg++) { if ((upd_mask & 1) != 0) { db_printf("%s%sr%d = 0x%08x", sep, (reg < 10) ? " " : "", reg, state->registers[reg]); i++; if (i == 2) { sep = "\n\t"; i = 0; } else sep = " "; } } db_printf("\n"); /* * Stop if directed to do so, or if we've unwound back to the * kernel entry point, or if the unwind function didn't change * anything (to avoid getting stuck in this loop forever). * If the latter happens, it's an indication that the unwind * information is incorrect somehow for the function named in * the last frame printed before you see the unwind failure * message (maybe it needs a STOP_UNWINDING). */ if (index->insn == EXIDX_CANTUNWIND) { finished = true; } else if (state->registers[PC] < VM_MIN_KERNEL_ADDRESS) { db_printf("Unable to unwind into user mode\n"); finished = true; } else if (state->update_mask == 0) { db_printf("Unwind failure (no registers changed)\n"); finished = true; } } } #endif /* * APCS stack frames are awkward beasts, so I don't think even trying to use * a structure to represent them is a good idea. * * Here's the diagram from the APCS. Increasing address is _up_ the page. * * save code pointer [fp] <- fp points to here * return link value [fp, #-4] * return sp value [fp, #-8] * return fp value [fp, #-12] * [saved v7 value] * [saved v6 value] * [saved v5 value] * [saved v4 value] * [saved v3 value] * [saved v2 value] * [saved v1 value] * [saved a4 value] * [saved a3 value] * [saved a2 value] * [saved a1 value] * * The save code pointer points twelve bytes beyond the start of the * code sequence (usually a single STM) that created the stack frame. * We have to disassemble it if we want to know which of the optional * fields are actually present. */ #ifndef __ARM_EABI__ /* The frame format is differend in AAPCS */ static void db_stack_trace_cmd(db_expr_t addr, db_expr_t count, boolean_t kernel_only) { u_int32_t *frame, *lastframe; c_db_sym_t sym; const char *name; db_expr_t value; db_expr_t offset; int scp_offset; frame = (u_int32_t *)addr; lastframe = NULL; scp_offset = -(get_pc_str_offset() >> 2); while (count-- && frame != NULL && !db_pager_quit) { db_addr_t scp; u_int32_t savecode; int r; u_int32_t *rp; const char *sep; /* * In theory, the SCP isn't guaranteed to be in the function * that generated the stack frame. We hope for the best. */ scp = frame[FR_SCP]; sym = db_search_symbol(scp, DB_STGY_ANY, &offset); if (sym == C_DB_SYM_NULL) { value = 0; name = "(null)"; } else db_symbol_values(sym, &name, &value); db_printf("%s() at ", name); db_printsym(scp, DB_STGY_PROC); db_printf("\n"); #ifdef __PROG26 db_printf("\tscp=0x%08x rlv=0x%08x (", scp, frame[FR_RLV] & R15_PC); db_printsym(frame[FR_RLV] & R15_PC, DB_STGY_PROC); db_printf(")\n"); #else db_printf("\tscp=0x%08x rlv=0x%08x (", scp, frame[FR_RLV]); db_printsym(frame[FR_RLV], DB_STGY_PROC); db_printf(")\n"); #endif db_printf("\trsp=0x%08x rfp=0x%08x", frame[FR_RSP], frame[FR_RFP]); savecode = ((u_int32_t *)scp)[scp_offset]; if ((savecode & 0x0e100000) == 0x08000000) { /* Looks like an STM */ rp = frame - 4; sep = "\n\t"; for (r = 10; r >= 0; r--) { if (savecode & (1 << r)) { db_printf("%sr%d=0x%08x", sep, r, *rp--); sep = (frame - rp) % 4 == 2 ? "\n\t" : " "; } } } db_printf("\n"); /* * Switch to next frame up */ if (frame[FR_RFP] == 0) break; /* Top of stack */ lastframe = frame; frame = (u_int32_t *)(frame[FR_RFP]); if (INKERNEL((int)frame)) { /* staying in kernel */ if (frame <= lastframe) { db_printf("Bad frame pointer: %p\n", frame); break; } } else if (INKERNEL((int)lastframe)) { /* switch from user to kernel */ if (kernel_only) break; /* kernel stack only */ } else { /* in user */ if (frame <= lastframe) { db_printf("Bad user frame pointer: %p\n", frame); break; } } } } #endif /* XXX stubs */ void db_md_list_watchpoints() { } int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size) { return (0); } int db_md_set_watchpoint(db_expr_t addr, db_expr_t size) { return (0); } int db_trace_thread(struct thread *thr, int count) { #ifdef __ARM_EABI__ struct unwind_state state; #endif struct pcb *ctx; if (thr != curthread) { ctx = kdb_thr_ctx(thr); #ifdef __ARM_EABI__ state.registers[FP] = ctx->un_32.pcb32_r11; state.registers[SP] = ctx->un_32.pcb32_sp; state.registers[LR] = ctx->un_32.pcb32_lr; state.registers[PC] = ctx->un_32.pcb32_pc; db_stack_trace_cmd(&state); #else db_stack_trace_cmd(ctx->un_32.pcb32_r11, -1, TRUE); #endif } else db_trace_self(); return (0); } void db_trace_self(void) { #ifdef __ARM_EABI__ struct unwind_state state; uint32_t sp; /* Read the stack pointer */ __asm __volatile("mov %0, sp" : "=&r" (sp)); state.registers[FP] = (uint32_t)__builtin_frame_address(0); state.registers[SP] = sp; state.registers[LR] = (uint32_t)__builtin_return_address(0); state.registers[PC] = (uint32_t)db_trace_self; db_stack_trace_cmd(&state); #else db_addr_t addr; addr = (db_addr_t)__builtin_frame_address(0); db_stack_trace_cmd(addr, -1, FALSE); #endif } Index: projects/sendfile/sys/arm/arm/gic.c =================================================================== --- projects/sendfile/sys/arm/arm/gic.c (revision 276056) +++ projects/sendfile/sys/arm/arm/gic.c (revision 276057) @@ -1,474 +1,479 @@ /*- * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * * Developed by Damjan Marion * * Based on OMAP4 GIC code by Ben Gray * * 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. 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 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* We are using GICv2 register naming */ /* Distributor Registers */ #define GICD_CTLR 0x000 /* v1 ICDDCR */ #define GICD_TYPER 0x004 /* v1 ICDICTR */ #define GICD_IIDR 0x008 /* v1 ICDIIDR */ #define GICD_IGROUPR(n) (0x0080 + ((n) * 4)) /* v1 ICDISER */ #define GICD_ISENABLER(n) (0x0100 + ((n) * 4)) /* v1 ICDISER */ #define GICD_ICENABLER(n) (0x0180 + ((n) * 4)) /* v1 ICDICER */ #define GICD_ISPENDR(n) (0x0200 + ((n) * 4)) /* v1 ICDISPR */ #define GICD_ICPENDR(n) (0x0280 + ((n) * 4)) /* v1 ICDICPR */ #define GICD_ICACTIVER(n) (0x0380 + ((n) * 4)) /* v1 ICDABR */ #define GICD_IPRIORITYR(n) (0x0400 + ((n) * 4)) /* v1 ICDIPR */ #define GICD_ITARGETSR(n) (0x0800 + ((n) * 4)) /* v1 ICDIPTR */ #define GICD_ICFGR(n) (0x0C00 + ((n) * 4)) /* v1 ICDICFR */ #define GICD_SGIR(n) (0x0F00 + ((n) * 4)) /* v1 ICDSGIR */ /* CPU Registers */ #define GICC_CTLR 0x0000 /* v1 ICCICR */ #define GICC_PMR 0x0004 /* v1 ICCPMR */ #define GICC_BPR 0x0008 /* v1 ICCBPR */ #define GICC_IAR 0x000C /* v1 ICCIAR */ #define GICC_EOIR 0x0010 /* v1 ICCEOIR */ #define GICC_RPR 0x0014 /* v1 ICCRPR */ #define GICC_HPPIR 0x0018 /* v1 ICCHPIR */ #define GICC_ABPR 0x001C /* v1 ICCABPR */ #define GICC_IIDR 0x00FC /* v1 ICCIIDR*/ #define GIC_FIRST_IPI 0 /* Irqs 0-15 are SGIs/IPIs. */ #define GIC_LAST_IPI 15 #define GIC_FIRST_PPI 16 /* Irqs 16-31 are private (per */ #define GIC_LAST_PPI 31 /* core) peripheral interrupts. */ #define GIC_FIRST_SPI 32 /* Irqs 32+ are shared peripherals. */ /* First bit is a polarity bit (0 - low, 1 - high) */ #define GICD_ICFGR_POL_LOW (0 << 0) #define GICD_ICFGR_POL_HIGH (1 << 0) #define GICD_ICFGR_POL_MASK 0x1 /* Second bit is a trigger bit (0 - level, 1 - edge) */ #define GICD_ICFGR_TRIG_LVL (0 << 1) #define GICD_ICFGR_TRIG_EDGE (1 << 1) #define GICD_ICFGR_TRIG_MASK 0x2 struct arm_gic_softc { + device_t gic_dev; struct resource * gic_res[3]; bus_space_tag_t gic_c_bst; bus_space_tag_t gic_d_bst; bus_space_handle_t gic_c_bsh; bus_space_handle_t gic_d_bsh; uint8_t ver; - device_t dev; struct mtx mutex; uint32_t nirqs; }; static struct resource_spec arm_gic_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Distributor registers */ { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* CPU Interrupt Intf. registers */ { -1, 0 } }; static struct arm_gic_softc *arm_gic_sc = NULL; -#define gic_c_read_4(reg) \ - bus_space_read_4(arm_gic_sc->gic_c_bst, arm_gic_sc->gic_c_bsh, reg) -#define gic_c_write_4(reg, val) \ - bus_space_write_4(arm_gic_sc->gic_c_bst, arm_gic_sc->gic_c_bsh, reg, val) -#define gic_d_read_4(reg) \ - bus_space_read_4(arm_gic_sc->gic_d_bst, arm_gic_sc->gic_d_bsh, reg) -#define gic_d_write_4(reg, val) \ - bus_space_write_4(arm_gic_sc->gic_d_bst, arm_gic_sc->gic_d_bsh, reg, val) +#define gic_c_read_4(_sc, _reg) \ + bus_space_read_4((_sc)->gic_c_bst, (_sc)->gic_c_bsh, (_reg)) +#define gic_c_write_4(_sc, _reg, _val) \ + bus_space_write_4((_sc)->gic_c_bst, (_sc)->gic_c_bsh, (_reg), (_val)) +#define gic_d_read_4(_sc, _reg) \ + bus_space_read_4((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg)) +#define gic_d_write_4(_sc, _reg, _val) \ + bus_space_write_4((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg), (_val)) static int gic_config_irq(int irq, enum intr_trigger trig, enum intr_polarity pol); static void gic_post_filter(void *); static struct ofw_compat_data compat_data[] = { {"arm,gic", true}, /* Non-standard, used in FreeBSD dts. */ {"arm,gic-400", true}, {"arm,cortex-a15-gic", true}, {"arm,cortex-a9-gic", true}, {"arm,cortex-a7-gic", true}, {"arm,arm11mp-gic", true}, {"brcm,brahma-b15-gic", true}, {NULL, false} }; static int arm_gic_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) return (ENXIO); device_set_desc(dev, "ARM Generic Interrupt Controller"); return (BUS_PROBE_DEFAULT); } void gic_init_secondary(void) { - int i, nirqs; + struct arm_gic_softc *sc = arm_gic_sc; + int i; - /* Get the number of interrupts */ - nirqs = gic_d_read_4(GICD_TYPER); - nirqs = 32 * ((nirqs & 0x1f) + 1); + for (i = 0; i < sc->nirqs; i += 4) + gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0); - for (i = 0; i < nirqs; i += 4) - gic_d_write_4(GICD_IPRIORITYR(i >> 2), 0); - /* Set all the interrupts to be in Group 0 (secure) */ - for (i = 0; i < nirqs; i += 32) { - gic_d_write_4(GICD_IGROUPR(i >> 5), 0); + for (i = 0; i < sc->nirqs; i += 32) { + gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0); } /* Enable CPU interface */ - gic_c_write_4(GICC_CTLR, 1); + gic_c_write_4(sc, GICC_CTLR, 1); /* Set priority mask register. */ - gic_c_write_4(GICC_PMR, 0xff); + gic_c_write_4(sc, GICC_PMR, 0xff); /* Enable interrupt distribution */ - gic_d_write_4(GICD_CTLR, 0x01); + gic_d_write_4(sc, GICD_CTLR, 0x01); /* * Activate the timer interrupts: virtual, secure, and non-secure. */ - gic_d_write_4(GICD_ISENABLER(27 >> 5), (1UL << (27 & 0x1F))); - gic_d_write_4(GICD_ISENABLER(29 >> 5), (1UL << (29 & 0x1F))); - gic_d_write_4(GICD_ISENABLER(30 >> 5), (1UL << (30 & 0x1F))); + gic_d_write_4(sc, GICD_ISENABLER(27 >> 5), (1UL << (27 & 0x1F))); + gic_d_write_4(sc, GICD_ISENABLER(29 >> 5), (1UL << (29 & 0x1F))); + gic_d_write_4(sc, GICD_ISENABLER(30 >> 5), (1UL << (30 & 0x1F))); } int gic_decode_fdt(uint32_t iparent, uint32_t *intr, int *interrupt, int *trig, int *pol) { static u_int num_intr_cells; if (num_intr_cells == 0) { if (OF_searchencprop(OF_node_from_xref(iparent), "#interrupt-cells", &num_intr_cells, sizeof(num_intr_cells)) == -1) { num_intr_cells = 1; } } if (num_intr_cells == 1) { *interrupt = fdt32_to_cpu(intr[0]); *trig = INTR_TRIGGER_CONFORM; *pol = INTR_POLARITY_CONFORM; } else { if (intr[0] == 0) *interrupt = fdt32_to_cpu(intr[1]) + GIC_FIRST_SPI; else *interrupt = fdt32_to_cpu(intr[1]) + GIC_FIRST_PPI; /* * In intr[2], bits[3:0] are trigger type and level flags. * 1 = low-to-high edge triggered * 2 = high-to-low edge triggered * 4 = active high level-sensitive * 8 = active low level-sensitive * The hardware only supports active-high-level or rising-edge. */ if (intr[2] & 0x0a) { printf("unsupported trigger/polarity configuration " "0x%2x\n", intr[2] & 0x0f); return (ENOTSUP); } *pol = INTR_POLARITY_CONFORM; if (intr[2] & 0x01) *trig = INTR_TRIGGER_EDGE; else *trig = INTR_TRIGGER_LEVEL; } return (0); } static int arm_gic_attach(device_t dev) { struct arm_gic_softc *sc; int i; uint32_t icciidr; if (arm_gic_sc) return (ENXIO); sc = device_get_softc(dev); - sc->dev = dev; if (bus_alloc_resources(dev, arm_gic_spec, sc->gic_res)) { device_printf(dev, "could not allocate resources\n"); return (ENXIO); } + sc->gic_dev = dev; + arm_gic_sc = sc; + /* Initialize mutex */ mtx_init(&sc->mutex, "GIC lock", "", MTX_SPIN); /* Distributor Interface */ sc->gic_d_bst = rman_get_bustag(sc->gic_res[0]); sc->gic_d_bsh = rman_get_bushandle(sc->gic_res[0]); /* CPU Interface */ sc->gic_c_bst = rman_get_bustag(sc->gic_res[1]); sc->gic_c_bsh = rman_get_bushandle(sc->gic_res[1]); - arm_gic_sc = sc; - /* Disable interrupt forwarding to the CPU interface */ - gic_d_write_4(GICD_CTLR, 0x00); + gic_d_write_4(sc, GICD_CTLR, 0x00); /* Get the number of interrupts */ - sc->nirqs = gic_d_read_4(GICD_TYPER); + sc->nirqs = gic_d_read_4(sc, GICD_TYPER); sc->nirqs = 32 * ((sc->nirqs & 0x1f) + 1); /* Set up function pointers */ arm_post_filter = gic_post_filter; arm_config_irq = gic_config_irq; - icciidr = gic_c_read_4(GICC_IIDR); + icciidr = gic_c_read_4(sc, GICC_IIDR); device_printf(dev,"pn 0x%x, arch 0x%x, rev 0x%x, implementer 0x%x irqs %u\n", icciidr>>20, (icciidr>>16) & 0xF, (icciidr>>12) & 0xf, (icciidr & 0xfff), sc->nirqs); /* Set all global interrupts to be level triggered, active low. */ for (i = 32; i < sc->nirqs; i += 16) { - gic_d_write_4(GICD_ICFGR(i >> 4), 0x00000000); + gic_d_write_4(sc, GICD_ICFGR(i >> 4), 0x00000000); } /* Disable all interrupts. */ for (i = 32; i < sc->nirqs; i += 32) { - gic_d_write_4(GICD_ICENABLER(i >> 5), 0xFFFFFFFF); + gic_d_write_4(sc, GICD_ICENABLER(i >> 5), 0xFFFFFFFF); } for (i = 0; i < sc->nirqs; i += 4) { - gic_d_write_4(GICD_IPRIORITYR(i >> 2), 0); - gic_d_write_4(GICD_ITARGETSR(i >> 2), 1 << 0 | 1 << 8 | 1 << 16 | 1 << 24); + gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0); + gic_d_write_4(sc, GICD_ITARGETSR(i >> 2), + 1 << 0 | 1 << 8 | 1 << 16 | 1 << 24); } /* Set all the interrupts to be in Group 0 (secure) */ for (i = 0; i < sc->nirqs; i += 32) { - gic_d_write_4(GICD_IGROUPR(i >> 5), 0); + gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0); } /* Enable CPU interface */ - gic_c_write_4(GICC_CTLR, 1); + gic_c_write_4(sc, GICC_CTLR, 1); /* Set priority mask register. */ - gic_c_write_4(GICC_PMR, 0xff); + gic_c_write_4(sc, GICC_PMR, 0xff); /* Enable interrupt distribution */ - gic_d_write_4(GICD_CTLR, 0x01); + gic_d_write_4(sc, GICD_CTLR, 0x01); return (0); } -static device_method_t arm_gic_methods[] = { - DEVMETHOD(device_probe, arm_gic_probe), - DEVMETHOD(device_attach, arm_gic_attach), - { 0, 0 } -}; - -static driver_t arm_gic_driver = { - "gic", - arm_gic_methods, - sizeof(struct arm_gic_softc), -}; - -static devclass_t arm_gic_devclass; - -EARLY_DRIVER_MODULE(gic, simplebus, arm_gic_driver, arm_gic_devclass, 0, 0, - BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); -EARLY_DRIVER_MODULE(gic, ofwbus, arm_gic_driver, arm_gic_devclass, 0, 0, - BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); - static void gic_post_filter(void *arg) { + struct arm_gic_softc *sc = arm_gic_sc; uintptr_t irq = (uintptr_t) arg; if (irq > GIC_LAST_IPI) arm_irq_memory_barrier(irq); - gic_c_write_4(GICC_EOIR, irq); + gic_c_write_4(sc, GICC_EOIR, irq); } int arm_get_next_irq(int last_irq) { + struct arm_gic_softc *sc = arm_gic_sc; uint32_t active_irq; - active_irq = gic_c_read_4(GICC_IAR); + active_irq = gic_c_read_4(sc, GICC_IAR); /* * Immediatly EOIR the SGIs, because doing so requires the other * bits (ie CPU number), not just the IRQ number, and we do not * have this information later. */ - if ((active_irq & 0x3ff) <= GIC_LAST_IPI) - gic_c_write_4(GICC_EOIR, active_irq); + gic_c_write_4(sc, GICC_EOIR, active_irq); active_irq &= 0x3FF; if (active_irq == 0x3FF) { if (last_irq == -1) printf("Spurious interrupt detected\n"); return -1; } return active_irq; } void arm_mask_irq(uintptr_t nb) { + struct arm_gic_softc *sc = arm_gic_sc; - gic_d_write_4(GICD_ICENABLER(nb >> 5), (1UL << (nb & 0x1F))); - gic_c_write_4(GICC_EOIR, nb); + gic_d_write_4(sc, GICD_ICENABLER(nb >> 5), (1UL << (nb & 0x1F))); + gic_c_write_4(sc, GICC_EOIR, nb); } void arm_unmask_irq(uintptr_t nb) { + struct arm_gic_softc *sc = arm_gic_sc; if (nb > GIC_LAST_IPI) arm_irq_memory_barrier(nb); - gic_d_write_4(GICD_ISENABLER(nb >> 5), (1UL << (nb & 0x1F))); + gic_d_write_4(sc, GICD_ISENABLER(nb >> 5), (1UL << (nb & 0x1F))); } static int gic_config_irq(int irq, enum intr_trigger trig, enum intr_polarity pol) { + struct arm_gic_softc *sc = arm_gic_sc; + device_t dev = sc->gic_dev; uint32_t reg; uint32_t mask; /* Function is public-accessible, so validate input arguments */ - if ((irq < 0) || (irq >= arm_gic_sc->nirqs)) + if ((irq < 0) || (irq >= sc->nirqs)) goto invalid_args; if ((trig != INTR_TRIGGER_EDGE) && (trig != INTR_TRIGGER_LEVEL) && (trig != INTR_TRIGGER_CONFORM)) goto invalid_args; if ((pol != INTR_POLARITY_HIGH) && (pol != INTR_POLARITY_LOW) && (pol != INTR_POLARITY_CONFORM)) goto invalid_args; - mtx_lock_spin(&arm_gic_sc->mutex); + mtx_lock_spin(&sc->mutex); - reg = gic_d_read_4(GICD_ICFGR(irq >> 4)); + reg = gic_d_read_4(sc, GICD_ICFGR(irq >> 4)); mask = (reg >> 2*(irq % 16)) & 0x3; if (pol == INTR_POLARITY_LOW) { mask &= ~GICD_ICFGR_POL_MASK; mask |= GICD_ICFGR_POL_LOW; } else if (pol == INTR_POLARITY_HIGH) { mask &= ~GICD_ICFGR_POL_MASK; mask |= GICD_ICFGR_POL_HIGH; } if (trig == INTR_TRIGGER_LEVEL) { mask &= ~GICD_ICFGR_TRIG_MASK; mask |= GICD_ICFGR_TRIG_LVL; } else if (trig == INTR_TRIGGER_EDGE) { mask &= ~GICD_ICFGR_TRIG_MASK; mask |= GICD_ICFGR_TRIG_EDGE; } /* Set mask */ reg = reg & ~(0x3 << 2*(irq % 16)); reg = reg | (mask << 2*(irq % 16)); - gic_d_write_4(GICD_ICFGR(irq >> 4), reg); + gic_d_write_4(sc, GICD_ICFGR(irq >> 4), reg); - mtx_unlock_spin(&arm_gic_sc->mutex); + mtx_unlock_spin(&sc->mutex); return (0); invalid_args: - device_printf(arm_gic_sc->dev, "gic_config_irg, invalid parameters\n"); + device_printf(dev, "gic_config_irg, invalid parameters\n"); return (EINVAL); } #ifdef SMP void pic_ipi_send(cpuset_t cpus, u_int ipi) { + struct arm_gic_softc *sc = arm_gic_sc; uint32_t val = 0, i; for (i = 0; i < MAXCPU; i++) if (CPU_ISSET(i, &cpus)) val |= 1 << (16 + i); - gic_d_write_4(GICD_SGIR(0), val | ipi); + gic_d_write_4(sc, GICD_SGIR(0), val | ipi); } int pic_ipi_get(int i) { if (i != -1) { /* * The intr code will automagically give the frame pointer * if the interrupt argument is 0. */ if ((unsigned int)i > 16) return (0); return (i); } + return (0x3ff); } void pic_ipi_clear(int ipi) { } #endif +static device_method_t arm_gic_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, arm_gic_probe), + DEVMETHOD(device_attach, arm_gic_attach), + { 0, 0 } +}; + +static driver_t arm_gic_driver = { + "gic", + arm_gic_methods, + sizeof(struct arm_gic_softc), +}; + +static devclass_t arm_gic_devclass; + +EARLY_DRIVER_MODULE(gic, simplebus, arm_gic_driver, arm_gic_devclass, 0, 0, + BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); +EARLY_DRIVER_MODULE(gic, ofwbus, arm_gic_driver, arm_gic_devclass, 0, 0, + BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); Index: projects/sendfile/sys/arm/arm/intr.c =================================================================== --- projects/sendfile/sys/arm/arm/intr.c (revision 276056) +++ projects/sendfile/sys/arm/arm/intr.c (revision 276057) @@ -1,218 +1,257 @@ /* $NetBSD: intr.c,v 1.12 2003/07/15 00:24:41 lukem Exp $ */ /*- * Copyright (c) 2004 Olivier Houchard. * Copyright (c) 1994-1998 Mark Brinicombe. * 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 Mark Brinicombe * for the NetBSD Project. * 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 THE AUTHOR ``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. * * Soft interrupt and other generic interrupt functions. */ +#include "opt_platform.h" + #include __FBSDID("$FreeBSD$"); + #include #include #include #include #include #include #include #include #include + #include #include #include +#ifdef FDT +#include +#include +#endif + #define INTRNAME_LEN (MAXCOMLEN + 1) typedef void (*mask_fn)(void *); static struct intr_event *intr_events[NIRQ]; void arm_irq_handler(struct trapframe *); void (*arm_post_filter)(void *) = NULL; int (*arm_config_irq)(int irq, enum intr_trigger trig, enum intr_polarity pol) = NULL; /* Data for statistics reporting. */ u_long intrcnt[NIRQ]; char intrnames[NIRQ * INTRNAME_LEN]; size_t sintrcnt = sizeof(intrcnt); size_t sintrnames = sizeof(intrnames); /* * Pre-format intrnames into an array of fixed-size strings containing spaces. * This allows us to avoid the need for an intermediate table of indices into * the names and counts arrays, while still meeting the requirements and * assumptions of vmstat(8) and the kdb "show intrcnt" command, the two * consumers of this data. */ static void intr_init(void *unused) { int i; for (i = 0; i < NIRQ; ++i) { snprintf(&intrnames[i * INTRNAME_LEN], INTRNAME_LEN, "%-*s", INTRNAME_LEN - 1, ""); } } SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL); + +#ifdef FDT +int +arm_fdt_map_irq(phandle_t iparent, pcell_t *intr, int icells) +{ + fdt_pic_decode_t intr_decode; + phandle_t intr_parent; + int i, rv, interrupt, trig, pol; + + intr_parent = OF_node_from_xref(iparent); + for (i = 0; i < icells; i++) + intr[i] = cpu_to_fdt32(intr[i]); + + for (i = 0; fdt_pic_table[i] != NULL; i++) { + intr_decode = fdt_pic_table[i]; + rv = intr_decode(intr_parent, intr, &interrupt, &trig, &pol); + + if (rv == 0) { + /* This was recognized as our PIC and decoded. */ + interrupt = FDT_MAP_IRQ(intr_parent, interrupt); + return (interrupt); + } + } + + /* Not in table, so guess */ + interrupt = FDT_MAP_IRQ(intr_parent, fdt32_to_cpu(intr[0])); + + return (interrupt); +} +#endif void arm_setup_irqhandler(const char *name, driver_filter_t *filt, void (*hand)(void*), void *arg, int irq, int flags, void **cookiep) { struct intr_event *event; int error; if (irq < 0 || irq >= NIRQ) return; event = intr_events[irq]; if (event == NULL) { error = intr_event_create(&event, (void *)irq, 0, irq, (mask_fn)arm_mask_irq, (mask_fn)arm_unmask_irq, arm_post_filter, NULL, "intr%d:", irq); if (error) return; intr_events[irq] = event; snprintf(&intrnames[irq * INTRNAME_LEN], INTRNAME_LEN, "irq%d: %-*s", irq, INTRNAME_LEN - 1, name); } intr_event_add_handler(event, name, filt, hand, arg, intr_priority(flags), flags, cookiep); } int arm_remove_irqhandler(int irq, void *cookie) { struct intr_event *event; int error; event = intr_events[irq]; arm_mask_irq(irq); error = intr_event_remove_handler(cookie); if (!TAILQ_EMPTY(&event->ie_handlers)) arm_unmask_irq(irq); return (error); } void dosoftints(void); void dosoftints(void) { } void arm_irq_handler(struct trapframe *frame) { struct intr_event *event; int i; PCPU_INC(cnt.v_intr); i = -1; while ((i = arm_get_next_irq(i)) != -1) { intrcnt[i]++; event = intr_events[i]; if (intr_event_handle(event, frame) != 0) { /* XXX: Log stray IRQs */ arm_mask_irq(i); } } } /* * arm_irq_memory_barrier() * * Ensure all writes to device memory have reached devices before proceeding. * * This is intended to be called from the post-filter and post-thread routines * of an interrupt controller implementation. A peripheral device driver should * use bus_space_barrier() if it needs to ensure a write has reached the * hardware for some reason other than clearing interrupt conditions. * * The need for this function arises from the ARM weak memory ordering model. * Writes to locations mapped with the Device attribute bypass any caches, but * are buffered. Multiple writes to the same device will be observed by that * device in the order issued by the cpu. Writes to different devices may * appear at those devices in a different order than issued by the cpu. That * is, if the cpu writes to device A then device B, the write to device B could * complete before the write to device A. * * Consider a typical device interrupt handler which services the interrupt and * writes to a device status-acknowledge register to clear the interrupt before * returning. That write is posted to the L2 controller which "immediately" * places it in a store buffer and automatically drains that buffer. This can * be less immediate than you'd think... There may be no free slots in the store * buffers, so an existing buffer has to be drained first to make room. The * target bus may be busy with other traffic (such as DMA for various devices), * delaying the drain of the store buffer for some indeterminate time. While * all this delay is happening, execution proceeds on the CPU, unwinding its way * out of the interrupt call stack to the point where the interrupt driver code * is ready to EOI and unmask the interrupt. The interrupt controller may be * accessed via a faster bus than the hardware whose handler just ran; the write * to unmask and EOI the interrupt may complete quickly while the device write * to ack and clear the interrupt source is still lingering in a store buffer * waiting for access to a slower bus. With the interrupt unmasked at the * interrupt controller but still active at the device, as soon as interrupts * are enabled on the core the device re-interrupts immediately: now you've got * a spurious interrupt on your hands. * * The right way to fix this problem is for every device driver to use the * proper bus_space_barrier() calls in its interrupt handler. For ARM a single * barrier call at the end of the handler would work. This would have to be * done to every driver in the system, not just arm-specific drivers. * * Another potential fix is to map all device memory as Strongly-Ordered rather * than Device memory, which takes the store buffers out of the picture. This * has a pretty big impact on overall system performance, because each strongly * ordered memory access causes all L2 store buffers to be drained. * * A compromise solution is to have the interrupt controller implementation call * this function to establish a barrier between writes to the interrupt-source * device and writes to the interrupt controller device. * * This takes the interrupt number as an argument, and currently doesn't use it. * The plan is that maybe some day there is a way to flag certain interrupts as * "memory barrier safe" and we can avoid this overhead with them. */ void arm_irq_memory_barrier(uintptr_t irq) { dsb(); cpu_l2cache_drain_writebuf(); } Index: projects/sendfile/sys/arm/arm/nexus.c =================================================================== --- projects/sendfile/sys/arm/arm/nexus.c (revision 276056) +++ projects/sendfile/sys/arm/arm/nexus.c (revision 276057) @@ -1,378 +1,356 @@ /*- * Copyright 1998 Massachusetts Institute of Technology * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that both the above copyright notice and this * permission notice appear in all copies, that both the above * copyright notice and this permission notice appear in all * supporting documentation, and that the name of M.I.T. not be used * in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. M.I.T. makes * no representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied * warranty. * * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT * SHALL M.I.T. 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. * */ /* * This code implements a `root nexus' for Arm Architecture * machines. The function of the root nexus is to serve as an * attachment point for both processors and buses, and to manage * resources which are common to all of them. In particular, * this code implements the core resource managers for interrupt * requests, DMA requests (which rightfully should be a part of the * ISA code but it's easier to do it here for now), I/O port addresses, * and I/O memory address space. */ +#include "opt_platform.h" + #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include "opt_platform.h" - #ifdef FDT -#include #include #include "ofw_bus_if.h" #endif static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device"); struct nexus_device { struct resource_list nx_resources; }; #define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev)) static struct rman mem_rman; static int nexus_probe(device_t); static int nexus_attach(device_t); static int nexus_print_child(device_t, device_t); static device_t nexus_add_child(device_t, u_int, const char *, int); static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, u_long, u_long, u_long, u_int); static int nexus_activate_resource(device_t, device_t, int, int, struct resource *); static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, enum intr_polarity pol); static int nexus_deactivate_resource(device_t, device_t, int, int, struct resource *); static int nexus_release_resource(device_t, device_t, int, int, struct resource *); static int nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep); static int nexus_teardown_intr(device_t, device_t, struct resource *, void *); #ifdef FDT static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, pcell_t *intr); #endif static device_method_t nexus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, nexus_probe), DEVMETHOD(device_attach, nexus_attach), /* Bus interface */ DEVMETHOD(bus_print_child, nexus_print_child), DEVMETHOD(bus_add_child, nexus_add_child), DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), DEVMETHOD(bus_activate_resource, nexus_activate_resource), DEVMETHOD(bus_config_intr, nexus_config_intr), DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), DEVMETHOD(bus_release_resource, nexus_release_resource), DEVMETHOD(bus_setup_intr, nexus_setup_intr), DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), #ifdef FDT DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr), #endif { 0, 0 } }; static devclass_t nexus_devclass; static driver_t nexus_driver = { "nexus", nexus_methods, 1 /* no softc */ }; EARLY_DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_EARLY); static int nexus_probe(device_t dev) { device_quiet(dev); /* suppress attach message for neatness */ return (BUS_PROBE_DEFAULT); } static int nexus_attach(device_t dev) { mem_rman.rm_start = 0; mem_rman.rm_end = ~0ul; mem_rman.rm_type = RMAN_ARRAY; mem_rman.rm_descr = "I/O memory addresses"; if (rman_init(&mem_rman) || rman_manage_region(&mem_rman, 0, ~0)) panic("nexus_probe mem_rman"); /* * First, deal with the children we know about already */ bus_generic_probe(dev); bus_generic_attach(dev); return (0); } static int nexus_print_child(device_t bus, device_t child) { int retval = 0; retval += bus_print_child_header(bus, child); retval += printf("\n"); return (retval); } static device_t nexus_add_child(device_t bus, u_int order, const char *name, int unit) { device_t child; struct nexus_device *ndev; ndev = malloc(sizeof(struct nexus_device), M_NEXUSDEV, M_NOWAIT|M_ZERO); if (!ndev) return (0); resource_list_init(&ndev->nx_resources); child = device_add_child_ordered(bus, order, name, unit); /* should we free this in nexus_child_detached? */ device_set_ivars(child, ndev); return (child); } /* * Allocate a resource on behalf of child. NB: child is usually going to be a * child of one of our descendants, not a direct child of nexus0. * (Exceptions include footbridge.) */ static struct resource * nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct resource *rv; struct rman *rm; int needactivate = flags & RF_ACTIVE; flags &= ~RF_ACTIVE; switch (type) { case SYS_RES_MEMORY: case SYS_RES_IOPORT: rm = &mem_rman; break; default: return (NULL); } rv = rman_reserve_resource(rm, start, end, count, flags, child); if (rv == 0) return (NULL); rman_set_rid(rv, *rid); if (needactivate) { if (bus_activate_resource(child, type, *rid, rv)) { rman_release_resource(rv); return (0); } } return (rv); } static int nexus_release_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { int error; if (rman_get_flags(res) & RF_ACTIVE) { error = bus_deactivate_resource(child, type, rid, res); if (error) return (error); } return (rman_release_resource(res)); } static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, enum intr_polarity pol) { int ret = ENODEV; if (arm_config_irq) ret = (*arm_config_irq)(irq, trig, pol); return (ret); } static int nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { int irq; if ((rman_get_flags(res) & RF_SHAREABLE) == 0) flags |= INTR_EXCL; for (irq = rman_get_start(res); irq <= rman_get_end(res); irq++) { arm_setup_irqhandler(device_get_nameunit(child), filt, intr, arg, irq, flags, cookiep); arm_unmask_irq(irq); } return (0); } static int nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) { return (arm_remove_irqhandler(rman_get_start(r), ih)); } static int nexus_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { int err; bus_addr_t paddr; bus_size_t psize; bus_space_handle_t vaddr; if ((err = rman_activate_resource(r)) != 0) return (err); /* * If this is a memory resource, map it into the kernel. */ if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { paddr = (bus_addr_t)rman_get_start(r); psize = (bus_size_t)rman_get_size(r); #ifdef FDT err = bus_space_map(fdtbus_bs_tag, paddr, psize, 0, &vaddr); if (err != 0) { rman_deactivate_resource(r); return (err); } rman_set_bustag(r, fdtbus_bs_tag); #else vaddr = (bus_space_handle_t)pmap_mapdev((vm_offset_t)paddr, (vm_size_t)psize); if (vaddr == 0) { rman_deactivate_resource(r); return (ENOMEM); } rman_set_bustag(r, (void *)1); #endif rman_set_virtual(r, (void *)vaddr); rman_set_bushandle(r, vaddr); } return (0); } static int nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { bus_size_t psize; bus_space_handle_t vaddr; psize = (bus_size_t)rman_get_size(r); vaddr = rman_get_bushandle(r); if (vaddr != 0) { #ifdef FDT bus_space_unmap(fdtbus_bs_tag, vaddr, psize); #else pmap_unmapdev((vm_offset_t)vaddr, (vm_size_t)psize); #endif rman_set_virtual(r, NULL); rman_set_bushandle(r, 0); } return (rman_deactivate_resource(r)); } #ifdef FDT static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, pcell_t *intr) { - fdt_pic_decode_t intr_decode; - phandle_t intr_parent; - int i, rv, interrupt, trig, pol; - intr_parent = OF_node_from_xref(iparent); - for (i = 0; i < icells; i++) - intr[i] = cpu_to_fdt32(intr[i]); - - for (i = 0; fdt_pic_table[i] != NULL; i++) { - intr_decode = fdt_pic_table[i]; - rv = intr_decode(intr_parent, intr, &interrupt, &trig, &pol); - - if (rv == 0) { - /* This was recognized as our PIC and decoded. */ - interrupt = FDT_MAP_IRQ(intr_parent, interrupt); - return (interrupt); - } - } - - /* Not in table, so guess */ - interrupt = FDT_MAP_IRQ(intr_parent, fdt32_to_cpu(intr[0])); - - return (interrupt); + return (arm_fdt_map_irq(iparent, intr, icells)); } #endif Index: projects/sendfile/sys/arm/at91/at91_machdep.c =================================================================== --- projects/sendfile/sys/arm/at91/at91_machdep.c (revision 276056) +++ projects/sendfile/sys/arm/at91/at91_machdep.c (revision 276057) @@ -1,700 +1,698 @@ /*- * Copyright (c) 1994-1998 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 * * machdep.c * * Machine dependant functions for kernel setup * * This file needs a lot of work. * * Created : 17/09/94 */ #include "opt_platform.h" #include __FBSDID("$FreeBSD$"); #define _ARM32_BUS_DMA_PRIVATE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef MAXCPU #define MAXCPU 1 #endif /* Page table for mapping proc0 zero page */ #define KERNEL_PT_SYS 0 #define KERNEL_PT_KERN 1 #define KERNEL_PT_KERN_NUM 22 /* L2 table for mapping after kernel */ #define KERNEL_PT_AFKERNEL KERNEL_PT_KERN + KERNEL_PT_KERN_NUM #define KERNEL_PT_AFKERNEL_NUM 5 /* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */ #define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM) extern struct bus_space at91_bs_tag; struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; -extern uint32_t at91_master_clock; - /* Static device mappings. */ const struct arm_devmap_entry at91_devmap[] = { /* * Map the critical on-board devices. The interrupt vector at * 0xffff0000 makes it impossible to map them PA == VA, so we map all * 0xfffxxxxx addresses to 0xdffxxxxx. This covers all critical devices * on all members of the AT91SAM9 and AT91RM9200 families. */ { 0xdff00000, 0xfff00000, 0x00100000, VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, }, /* There's a notion that we should do the rest of these lazily. */ /* * We can't just map the OHCI registers VA == PA, because * AT91xx_xxx_BASE belongs to the userland address space. * We could just choose a different virtual address, but a better * solution would probably be to just use pmap_mapdev() to allocate * KVA, as we don't need the OHCI controller before the vm * initialization is done. However, the AT91 resource allocation * system doesn't know how to use pmap_mapdev() yet. * Care must be taken to ensure PA and VM address do not overlap * between entries. */ { /* * Add the ohci controller, and anything else that might be * on this chip select for a VA/PA mapping. */ /* Internal Memory 1MB */ AT91RM92_OHCI_VA_BASE, AT91RM92_OHCI_BASE, 0x00100000, VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, }, { /* CompactFlash controller. Portion of EBI CS4 1MB */ AT91RM92_CF_VA_BASE, AT91RM92_CF_BASE, 0x00100000, VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, }, /* * The next two should be good for the 9260, 9261 and 9G20 since * addresses mapping is the same. */ { /* Internal Memory 1MB */ AT91SAM9G20_OHCI_VA_BASE, AT91SAM9G20_OHCI_BASE, 0x00100000, VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, }, { /* EBI CS3 256MB */ AT91SAM9G20_NAND_VA_BASE, AT91SAM9G20_NAND_BASE, AT91SAM9G20_NAND_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, }, /* * The next should be good for the 9G45. */ { /* Internal Memory 1MB */ AT91SAM9G45_OHCI_VA_BASE, AT91SAM9G45_OHCI_BASE, 0x00100000, VM_PROT_READ|VM_PROT_WRITE, PTE_DEVICE, }, { 0, 0, 0, 0, 0, } }; #ifdef LINUX_BOOT_ABI extern int membanks; extern int memstart[]; extern int memsize[]; #endif long at91_ramsize(void) { uint32_t cr, mdr, mr, *SDRAMC; int banks, rows, cols, bw; #ifdef LINUX_BOOT_ABI /* * If we found any ATAGs that were for memory, return the first bank. */ if (membanks > 0) return (memsize[0]); #endif if (at91_is_rm92()) { SDRAMC = (uint32_t *)(AT91_BASE + AT91RM92_SDRAMC_BASE); cr = SDRAMC[AT91RM92_SDRAMC_CR / 4]; mr = SDRAMC[AT91RM92_SDRAMC_MR / 4]; banks = (cr & AT91RM92_SDRAMC_CR_NB_4) ? 2 : 1; rows = ((cr & AT91RM92_SDRAMC_CR_NR_MASK) >> 2) + 11; cols = (cr & AT91RM92_SDRAMC_CR_NC_MASK) + 8; bw = (mr & AT91RM92_SDRAMC_MR_DBW_16) ? 1 : 2; } else if (at91_cpu_is(AT91_T_SAM9G45)) { SDRAMC = (uint32_t *)(AT91_BASE + AT91SAM9G45_DDRSDRC0_BASE); cr = SDRAMC[AT91SAM9G45_DDRSDRC_CR / 4]; mdr = SDRAMC[AT91SAM9G45_DDRSDRC_MDR / 4]; banks = 0; rows = ((cr & AT91SAM9G45_DDRSDRC_CR_NR_MASK) >> 2) + 11; cols = (cr & AT91SAM9G45_DDRSDRC_CR_NC_MASK) + 8; bw = (mdr & AT91SAM9G45_DDRSDRC_MDR_DBW_16) ? 1 : 2; /* Fix the calculation for DDR memory */ mdr &= AT91SAM9G45_DDRSDRC_MDR_MASK; if (mdr & AT91SAM9G45_DDRSDRC_MDR_LPDDR1 || mdr & AT91SAM9G45_DDRSDRC_MDR_DDR2) { /* The cols value is 1 higher for DDR */ cols += 1; /* DDR has 4 internal banks. */ banks = 2; } } else { /* * This should be good for the 9260, 9261, 9G20, 9G35 and 9X25 * as addresses and registers are the same. */ SDRAMC = (uint32_t *)(AT91_BASE + AT91SAM9G20_SDRAMC_BASE); cr = SDRAMC[AT91SAM9G20_SDRAMC_CR / 4]; mr = SDRAMC[AT91SAM9G20_SDRAMC_MR / 4]; banks = (cr & AT91SAM9G20_SDRAMC_CR_NB_4) ? 2 : 1; rows = ((cr & AT91SAM9G20_SDRAMC_CR_NR_MASK) >> 2) + 11; cols = (cr & AT91SAM9G20_SDRAMC_CR_NC_MASK) + 8; bw = (cr & AT91SAM9G20_SDRAMC_CR_DBW_16) ? 1 : 2; } return (1 << (cols + rows + banks + bw)); } static const char *soc_type_name[] = { [AT91_T_CAP9] = "at91cap9", [AT91_T_RM9200] = "at91rm9200", [AT91_T_SAM9260] = "at91sam9260", [AT91_T_SAM9261] = "at91sam9261", [AT91_T_SAM9263] = "at91sam9263", [AT91_T_SAM9G10] = "at91sam9g10", [AT91_T_SAM9G20] = "at91sam9g20", [AT91_T_SAM9G45] = "at91sam9g45", [AT91_T_SAM9N12] = "at91sam9n12", [AT91_T_SAM9RL] = "at91sam9rl", [AT91_T_SAM9X5] = "at91sam9x5", [AT91_T_NONE] = "UNKNOWN" }; static const char *soc_subtype_name[] = { [AT91_ST_NONE] = "UNKNOWN", [AT91_ST_RM9200_BGA] = "at91rm9200_bga", [AT91_ST_RM9200_PQFP] = "at91rm9200_pqfp", [AT91_ST_SAM9XE] = "at91sam9xe", [AT91_ST_SAM9G45] = "at91sam9g45", [AT91_ST_SAM9M10] = "at91sam9m10", [AT91_ST_SAM9G46] = "at91sam9g46", [AT91_ST_SAM9M11] = "at91sam9m11", [AT91_ST_SAM9G15] = "at91sam9g15", [AT91_ST_SAM9G25] = "at91sam9g25", [AT91_ST_SAM9G35] = "at91sam9g35", [AT91_ST_SAM9X25] = "at91sam9x25", [AT91_ST_SAM9X35] = "at91sam9x35", }; struct at91_soc_info soc_info; /* * Read the SoC ID from the CIDR register and try to match it against the * values we know. If we find a good one, we return true. If not, we * return false. When we find a good one, we also find the subtype * and CPU family. */ static int at91_try_id(uint32_t dbgu_base) { uint32_t socid; soc_info.cidr = *(volatile uint32_t *)(AT91_BASE + dbgu_base + DBGU_C1R); socid = soc_info.cidr & ~AT91_CPU_VERSION_MASK; soc_info.type = AT91_T_NONE; soc_info.subtype = AT91_ST_NONE; soc_info.family = (soc_info.cidr & AT91_CPU_FAMILY_MASK) >> 20; soc_info.exid = *(volatile uint32_t *)(AT91_BASE + dbgu_base + DBGU_C2R); switch (socid) { case AT91_CPU_CAP9: soc_info.type = AT91_T_CAP9; break; case AT91_CPU_RM9200: soc_info.type = AT91_T_RM9200; break; case AT91_CPU_SAM9XE128: case AT91_CPU_SAM9XE256: case AT91_CPU_SAM9XE512: case AT91_CPU_SAM9260: soc_info.type = AT91_T_SAM9260; if (soc_info.family == AT91_FAMILY_SAM9XE) soc_info.subtype = AT91_ST_SAM9XE; break; case AT91_CPU_SAM9261: soc_info.type = AT91_T_SAM9261; break; case AT91_CPU_SAM9263: soc_info.type = AT91_T_SAM9263; break; case AT91_CPU_SAM9G10: soc_info.type = AT91_T_SAM9G10; break; case AT91_CPU_SAM9G20: soc_info.type = AT91_T_SAM9G20; break; case AT91_CPU_SAM9G45: soc_info.type = AT91_T_SAM9G45; break; case AT91_CPU_SAM9N12: soc_info.type = AT91_T_SAM9N12; break; case AT91_CPU_SAM9RL64: soc_info.type = AT91_T_SAM9RL; break; case AT91_CPU_SAM9X5: soc_info.type = AT91_T_SAM9X5; break; default: return (0); } switch (soc_info.type) { case AT91_T_SAM9G45: switch (soc_info.exid) { case AT91_EXID_SAM9G45: soc_info.subtype = AT91_ST_SAM9G45; break; case AT91_EXID_SAM9G46: soc_info.subtype = AT91_ST_SAM9G46; break; case AT91_EXID_SAM9M10: soc_info.subtype = AT91_ST_SAM9M10; break; case AT91_EXID_SAM9M11: soc_info.subtype = AT91_ST_SAM9M11; break; } break; case AT91_T_SAM9X5: switch (soc_info.exid) { case AT91_EXID_SAM9G15: soc_info.subtype = AT91_ST_SAM9G15; break; case AT91_EXID_SAM9G25: soc_info.subtype = AT91_ST_SAM9G25; break; case AT91_EXID_SAM9G35: soc_info.subtype = AT91_ST_SAM9G35; break; case AT91_EXID_SAM9X25: soc_info.subtype = AT91_ST_SAM9X25; break; case AT91_EXID_SAM9X35: soc_info.subtype = AT91_ST_SAM9X35; break; } break; default: break; } /* * Disable interrupts in the DBGU unit... */ *(volatile uint32_t *)(AT91_BASE + dbgu_base + USART_IDR) = 0xffffffff; /* * Save the name for later... */ snprintf(soc_info.name, sizeof(soc_info.name), "%s%s%s", soc_type_name[soc_info.type], soc_info.subtype == AT91_ST_NONE ? "" : " subtype ", soc_info.subtype == AT91_ST_NONE ? "" : soc_subtype_name[soc_info.subtype]); /* * try to get the matching CPU support. */ soc_info.soc_data = at91_match_soc(soc_info.type, soc_info.subtype); soc_info.dbgu_base = AT91_BASE + dbgu_base; return (1); } void at91_soc_id(void) { if (!at91_try_id(AT91_DBGU0)) at91_try_id(AT91_DBGU1); } #ifdef ARM_MANY_BOARD /* likely belongs in arm/arm/machdep.c, but since board_init is still at91 only... */ SET_DECLARE(arm_board_set, const struct arm_board); /* Not yet fully functional, but enough to build ATMEL config */ static long board_init(void) { return -1; } #endif #ifndef FDT /* Physical and virtual addresses for some global pages */ struct pv_addr msgbufpv; struct pv_addr kernelstack; struct pv_addr systempage; struct pv_addr irqstack; struct pv_addr abtstack; struct pv_addr undstack; void * initarm(struct arm_boot_params *abp) { struct pv_addr kernel_l1pt; struct pv_addr dpcpu; int i; u_int l1pagetable; vm_offset_t freemempos; vm_offset_t afterkern; uint32_t memsize; vm_offset_t lastaddr; lastaddr = parse_boot_param(abp); arm_physmem_kernaddr = abp->abp_physaddr; set_cpufuncs(); pcpu0_init(); /* Do basic tuning, hz etc */ init_param1(); freemempos = (lastaddr + PAGE_MASK) & ~PAGE_MASK; /* Define a macro to simplify memory allocation */ #define valloc_pages(var, np) \ alloc_pages((var).pv_va, (np)); \ (var).pv_pa = (var).pv_va + (abp->abp_physaddr - KERNVIRTADDR); #define alloc_pages(var, np) \ (var) = freemempos; \ freemempos += (np * PAGE_SIZE); \ memset((char *)(var), 0, ((np) * PAGE_SIZE)); while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0) freemempos += PAGE_SIZE; valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); for (i = 0; i < NUM_KERNEL_PTS; ++i) { if (!(i % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) { valloc_pages(kernel_pt_table[i], L2_TABLE_SIZE / PAGE_SIZE); } else { kernel_pt_table[i].pv_va = freemempos - (i % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) * L2_TABLE_SIZE_REAL; kernel_pt_table[i].pv_pa = kernel_pt_table[i].pv_va - KERNVIRTADDR + abp->abp_physaddr; } } /* * Allocate a page for the system page mapped to 0x00000000 * or 0xffff0000. This page will just contain the system vectors * and can be shared by all processes. */ valloc_pages(systempage, 1); /* Allocate dynamic per-cpu area. */ valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE); dpcpu_init((void *)dpcpu.pv_va, 0); /* Allocate stacks for all modes */ valloc_pages(irqstack, IRQ_STACK_SIZE * MAXCPU); valloc_pages(abtstack, ABT_STACK_SIZE * MAXCPU); valloc_pages(undstack, UND_STACK_SIZE * MAXCPU); valloc_pages(kernelstack, KSTACK_PAGES * MAXCPU); valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE); /* * Now we start construction of the L1 page table * We start by mapping the L2 page tables into the L1. * This means that we can replace L1 mappings later on if necessary */ l1pagetable = kernel_l1pt.pv_va; /* Map the L2 pages tables in the L1 page table */ pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH, &kernel_pt_table[KERNEL_PT_SYS]); for (i = 0; i < KERNEL_PT_KERN_NUM; i++) pmap_link_l2pt(l1pagetable, KERNBASE + i * L1_S_SIZE, &kernel_pt_table[KERNEL_PT_KERN + i]); pmap_map_chunk(l1pagetable, KERNBASE, PHYSADDR, (((uint32_t)lastaddr - KERNBASE) + PAGE_SIZE) & ~(PAGE_SIZE - 1), VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); afterkern = round_page((lastaddr + L1_S_SIZE) & ~(L1_S_SIZE - 1)); for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) { pmap_link_l2pt(l1pagetable, afterkern + i * L1_S_SIZE, &kernel_pt_table[KERNEL_PT_AFKERNEL + i]); } /* Map the vector page. */ pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); /* Map the DPCPU pages */ pmap_map_chunk(l1pagetable, dpcpu.pv_va, dpcpu.pv_pa, DPCPU_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); /* Map the stack pages */ pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa, IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa, ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa, UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa, KSTACK_PAGES * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa, L1_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); pmap_map_chunk(l1pagetable, msgbufpv.pv_va, msgbufpv.pv_pa, msgbufsize, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); for (i = 0; i < NUM_KERNEL_PTS; ++i) { pmap_map_chunk(l1pagetable, kernel_pt_table[i].pv_va, kernel_pt_table[i].pv_pa, L2_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); } arm_devmap_bootstrap(l1pagetable, at91_devmap); cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)) | DOMAIN_CLIENT); setttb(kernel_l1pt.pv_pa); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)); at91_soc_id(); /* * Initialize all the clocks, so that the console can work. We can only * do this if at91_soc_id() was able to fill in the support data. Even * if we can't init the clocks, still try to do a console init so we can * try to print the error message about missing soc support. There's a * chance the printf will work if the bootloader set up the DBGU. */ if (soc_info.soc_data != NULL) { soc_info.soc_data->soc_clock_init(); at91_pmc_init_clock(); } cninit(); if (soc_info.soc_data == NULL) printf("Warning: No soc support for %s found.\n", soc_info.name); memsize = board_init(); if (memsize == -1) { printf("board_init() failed, cannot determine ram size; " "assuming 16MB\n"); memsize = 16 * 1024 * 1024; } /* * Pages were allocated during the secondary bootstrap for the * stacks for different CPU modes. * We must now set the r13 registers in the different CPU modes to * point to these stacks. * Since the ARM stacks use STMFD etc. we must set r13 to the top end * of the stack memory. */ cpu_control(CPU_CONTROL_MMU_ENABLE, CPU_CONTROL_MMU_ENABLE); cpu_setup(""); set_stackptrs(0); /* * We must now clean the cache again.... * Cleaning may be done by reading new data to displace any * dirty data in the cache. This will have happened in setttb() * but since we are boot strapping the addresses used for the read * may have just been remapped and thus the cache could be out * of sync. A re-clean after the switch will cure this. * After booting there are no gross relocations of the kernel thus * this problem will not occur after initarm(). */ cpu_idcache_wbinv_all(); undefined_init(); init_proc0(kernelstack.pv_va); arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); pmap_curmaxkvaddr = afterkern + L1_S_SIZE * (KERNEL_PT_KERN_NUM - 1); /* Always use the 256MB of KVA we have available between the kernel and devices */ vm_max_kernel_address = KERNVIRTADDR + (256 << 20); pmap_bootstrap(freemempos, &kernel_l1pt); msgbufp = (void*)msgbufpv.pv_va; msgbufinit(msgbufp, msgbufsize); mutex_init(); /* * Add the physical ram we have available. * * Exclude the kernel, and all the things we allocated which immediately * follow the kernel, from the VM allocation pool but not from crash * dumps. virtual_avail is a global variable which tracks the kva we've * "allocated" while setting up pmaps. * * Prepare the list of physical memory available to the vm subsystem. */ arm_physmem_hardware_region(PHYSADDR, memsize); arm_physmem_exclude_region(abp->abp_physaddr, virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC); arm_physmem_init_kernel_globals(); init_param2(physmem); kdb_init(); return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP - sizeof(struct pcb))); } #endif /* * These functions are handled elsewhere, so make them nops here. */ void cpu_startprofclock(void) { } void cpu_stopprofclock(void) { } void cpu_initclocks(void) { } void DELAY(int n) { if (soc_info.soc_data) soc_info.soc_data->soc_delay(n); } void cpu_reset(void) { if (soc_info.soc_data) soc_info.soc_data->soc_reset(); while (1) continue; } Index: projects/sendfile/sys/arm/broadcom/bcm2835/bcm2835_intr.c =================================================================== --- projects/sendfile/sys/arm/broadcom/bcm2835/bcm2835_intr.c (revision 276056) +++ projects/sendfile/sys/arm/broadcom/bcm2835/bcm2835_intr.c (revision 276057) @@ -1,215 +1,218 @@ /*- * Copyright (c) 2012 Damjan Marion * All rights reserved. * * Based on OMAP3 INTC code by Ben Gray * * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #define INTC_PENDING_BASIC 0x00 #define INTC_PENDING_BANK1 0x04 #define INTC_PENDING_BANK2 0x08 #define INTC_FIQ_CONTROL 0x0C #define INTC_ENABLE_BANK1 0x10 #define INTC_ENABLE_BANK2 0x14 #define INTC_ENABLE_BASIC 0x18 #define INTC_DISABLE_BANK1 0x1C #define INTC_DISABLE_BANK2 0x20 #define INTC_DISABLE_BASIC 0x24 #define BANK1_START 8 #define BANK1_END (BANK1_START + 32 - 1) #define BANK2_START (BANK1_START + 32) #define BANK2_END (BANK2_START + 32 - 1) #define BANK3_START (BANK2_START + 32) #define IS_IRQ_BASIC(n) (((n) >= 0) && ((n) < BANK1_START)) #define IS_IRQ_BANK1(n) (((n) >= BANK1_START) && ((n) <= BANK1_END)) #define IS_IRQ_BANK2(n) (((n) >= BANK2_START) && ((n) <= BANK2_END)) #define IRQ_BANK1(n) ((n) - BANK1_START) #define IRQ_BANK2(n) ((n) - BANK2_START) #ifdef DEBUG #define dprintf(fmt, args...) printf(fmt, ##args) #else #define dprintf(fmt, args...) #endif struct bcm_intc_softc { device_t sc_dev; struct resource * intc_res; bus_space_tag_t intc_bst; bus_space_handle_t intc_bsh; }; static struct bcm_intc_softc *bcm_intc_sc = NULL; -#define intc_read_4(reg) \ - bus_space_read_4(bcm_intc_sc->intc_bst, bcm_intc_sc->intc_bsh, reg) -#define intc_write_4(reg, val) \ - bus_space_write_4(bcm_intc_sc->intc_bst, bcm_intc_sc->intc_bsh, reg, val) +#define intc_read_4(_sc, reg) \ + bus_space_read_4((_sc)->intc_bst, (_sc)->intc_bsh, (reg)) +#define intc_write_4(_sc, reg, val) \ + bus_space_write_4((_sc)->intc_bst, (_sc)->intc_bsh, (reg), (val)) static int bcm_intc_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (!ofw_bus_is_compatible(dev, "broadcom,bcm2835-armctrl-ic")) return (ENXIO); device_set_desc(dev, "BCM2835 Interrupt Controller"); return (BUS_PROBE_DEFAULT); } static int bcm_intc_attach(device_t dev) { struct bcm_intc_softc *sc = device_get_softc(dev); int rid = 0; sc->sc_dev = dev; if (bcm_intc_sc) return (ENXIO); sc->intc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->intc_res == NULL) { device_printf(dev, "could not allocate memory resource\n"); return (ENXIO); } sc->intc_bst = rman_get_bustag(sc->intc_res); sc->intc_bsh = rman_get_bushandle(sc->intc_res); bcm_intc_sc = sc; return (0); } static device_method_t bcm_intc_methods[] = { DEVMETHOD(device_probe, bcm_intc_probe), DEVMETHOD(device_attach, bcm_intc_attach), { 0, 0 } }; static driver_t bcm_intc_driver = { "intc", bcm_intc_methods, sizeof(struct bcm_intc_softc), }; static devclass_t bcm_intc_devclass; DRIVER_MODULE(intc, simplebus, bcm_intc_driver, bcm_intc_devclass, 0, 0); int arm_get_next_irq(int last_irq) { + struct bcm_intc_softc *sc = bcm_intc_sc; uint32_t pending; int32_t irq = last_irq + 1; /* Sanity check */ if (irq < 0) irq = 0; /* TODO: should we mask last_irq? */ if (irq < BANK1_START) { - pending = intc_read_4(INTC_PENDING_BASIC); + pending = intc_read_4(sc, INTC_PENDING_BASIC); if ((pending & 0xFF) == 0) { irq = BANK1_START; /* skip to next bank */ } else do { if (pending & (1 << irq)) return irq; irq++; } while (irq < BANK1_START); } if (irq < BANK2_START) { - pending = intc_read_4(INTC_PENDING_BANK1); + pending = intc_read_4(sc, INTC_PENDING_BANK1); if (pending == 0) { irq = BANK2_START; /* skip to next bank */ } else do { if (pending & (1 << IRQ_BANK1(irq))) return irq; irq++; } while (irq < BANK2_START); } if (irq < BANK3_START) { - pending = intc_read_4(INTC_PENDING_BANK2); + pending = intc_read_4(sc, INTC_PENDING_BANK2); if (pending != 0) do { if (pending & (1 << IRQ_BANK2(irq))) return irq; irq++; } while (irq < BANK3_START); } return (-1); } void arm_mask_irq(uintptr_t nb) { + struct bcm_intc_softc *sc = bcm_intc_sc; dprintf("%s: %d\n", __func__, nb); if (IS_IRQ_BASIC(nb)) - intc_write_4(INTC_DISABLE_BASIC, (1 << nb)); + intc_write_4(sc, INTC_DISABLE_BASIC, (1 << nb)); else if (IS_IRQ_BANK1(nb)) - intc_write_4(INTC_DISABLE_BANK1, (1 << IRQ_BANK1(nb))); + intc_write_4(sc, INTC_DISABLE_BANK1, (1 << IRQ_BANK1(nb))); else if (IS_IRQ_BANK2(nb)) - intc_write_4(INTC_DISABLE_BANK2, (1 << IRQ_BANK2(nb))); + intc_write_4(sc, INTC_DISABLE_BANK2, (1 << IRQ_BANK2(nb))); else printf("arm_mask_irq: Invalid IRQ number: %d\n", nb); } void arm_unmask_irq(uintptr_t nb) { + struct bcm_intc_softc *sc = bcm_intc_sc; dprintf("%s: %d\n", __func__, nb); if (IS_IRQ_BASIC(nb)) - intc_write_4(INTC_ENABLE_BASIC, (1 << nb)); + intc_write_4(sc, INTC_ENABLE_BASIC, (1 << nb)); else if (IS_IRQ_BANK1(nb)) - intc_write_4(INTC_ENABLE_BANK1, (1 << IRQ_BANK1(nb))); + intc_write_4(sc, INTC_ENABLE_BANK1, (1 << IRQ_BANK1(nb))); else if (IS_IRQ_BANK2(nb)) - intc_write_4(INTC_ENABLE_BANK2, (1 << IRQ_BANK2(nb))); + intc_write_4(sc, INTC_ENABLE_BANK2, (1 << IRQ_BANK2(nb))); else printf("arm_mask_irq: Invalid IRQ number: %d\n", nb); } Index: projects/sendfile/sys/arm/broadcom/bcm2835/std.bcm2835 =================================================================== --- projects/sendfile/sys/arm/broadcom/bcm2835/std.bcm2835 (revision 276056) +++ projects/sendfile/sys/arm/broadcom/bcm2835/std.bcm2835 (revision 276057) @@ -1,7 +1,8 @@ # $FreeBSD$ machine arm armv6 cpu CPU_ARM1176 +makeoptions CONF_CFLAGS="-mcpu=arm1176jzf-s -Wa,-mcpu=arm1176jzf-s" files "../broadcom/bcm2835/files.bcm2835" Index: projects/sendfile/sys/arm/conf/APALIS-IMX6 =================================================================== --- projects/sendfile/sys/arm/conf/APALIS-IMX6 (revision 276056) +++ projects/sendfile/sys/arm/conf/APALIS-IMX6 (revision 276057) @@ -1,31 +1,31 @@ # Kernel configuration for Toradex Apalis i.MX6 # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ #NO_UNIVERSE include "IMX6" ident APALIS-IMX6 makeoptions MODULES_OVERRIDE="" makeoptions WITHOUT_MODULES="ahc" # Flattened Device Tree -options FDT -options FDT_DTB_STATIC -makeoptions FDT_DTS_FILE=apalis-imx6.dts +options FDT +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=apalis-imx6.dts Index: projects/sendfile/sys/arm/conf/ARMADAXP =================================================================== --- projects/sendfile/sys/arm/conf/ARMADAXP (revision 276056) +++ projects/sendfile/sys/arm/conf/ARMADAXP (revision 276057) @@ -1,107 +1,137 @@ # # Custom kernel for Marvell Armada XP # -# $FreeBSD$ +# For more information on this file, please read the config(5) manual page, +# and/or the handbook section on Kernel Configuration Files: # +# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html +# +# The handbook is also available locally in /usr/share/doc/handbook +# if you've installed the doc distribution, otherwise always see the +# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the +# latest information. +# +# An exhaustive list of options and more detailed explanations of the +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first +# in NOTES. +# +# $FreeBSD$ ident MV-88F78XX0 include "../mv/armadaxp/std.mv78x60" options SOC_MV_ARMADAXP makeoptions MODULES_OVERRIDE="" -makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols makeoptions WERROR="-Werror" +options HZ=1000 #options SCHED_ULE # ULE scheduler options SCHED_4BSD # 4BSD scheduler +options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols +options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem -options NFSCL # Network Filesystem Client +options SOFTUPDATES # Enable FFS soft updates support +options UFS_ACL # Support for access control lists +options UFS_DIRHASH # Improve performance on big directories +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS +options NFSCL # New Network Filesystem Client options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCLIENT -options BOOTP -options BOOTP_NFSROOT -options BOOTP_NFSV3 -options BOOTP_WIRED_TO=mge0 - +options NFS_ROOT # NFS usable as /, requires NFSCL +options MSDOSFS # MSDOS Filesystem +options CD9660 # ISO 9660 Filesystem +options PROCFS # Process filesystem (requires PSEUDOFS) +options PSEUDOFS # Pseudo-filesystem framework options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables options GEOM_PART_BSD # BSD partition scheme options GEOM_PART_MBR # MBR partition scheme -options GEOM_PART_GPT -options ROOTDEVNAME=\"ufs:/dev/da0p1\" - +options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions -options MUTEX_NOINLINE -options RWLOCK_NOINLINE -options NO_FFS_SNAPSHOT -options NO_SWAPPING -options VFP +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev +options VFP # Enable floating point hardware support +options SMP # Enable multiple cores -options SMP - -# Debugging -#options VERBOSE_SYSINIT +# Debugging for use in -current +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols +#options VERBOSE_SYSINIT # Enable verbose sysinit messages options ALT_BREAK_TO_DEBUGGER -options DDB +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: +options DDB # Enable the kernel debugger options GDB -#options DIAGNOSTIC #options INVARIANTS # Enable calls of extra sanity checking #options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS -options KDB -options KDB_TRACE +#options WITNESS # Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed +#options WITNESS_KDB +#options DIAGNOSTIC #options KTR #options KTR_VERBOSE=0 #options KTR_ENTRIES=16384 #options KTR_MASK=(KTR_SPARE2) #options KTR_COMPILE=KTR_ALL -#options WITNESS # Enable checks to detect deadlocks and cycles -#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed -#options WITNESS_KDB +# NFS root from boopt/dhcp +options BOOTP +options BOOTP_NFSROOT +options BOOTP_NFSV3 +options BOOTP_WIRED_TO=mge0 + +options ROOTDEVNAME=\"ufs:/dev/da0p1\" + +options MUTEX_NOINLINE +options RWLOCK_NOINLINE +options NO_FFS_SNAPSHOT +options NO_SWAPPING + # Pseudo devices device random device pty device loop device md # USB options USB_DEBUG # enable debug msgs device usb device ehci device umass device scbus device pass device da # SATA device mvs # Serial ports device uart # I2C (TWSI) device iic device iicbus #Network device ether device mge # Marvell Gigabit Ethernet controller device mii device e1000phy device bpf -options HZ=1000 options DEVICE_POLLING device vlan #PCI/PCIE device pci -#FDT -options FDT +# Flattened Device Tree +options FDT # Configure using FDT/DTB data options FDT_DTB_STATIC makeoptions FDT_DTS_FILE=db78460.dts Index: projects/sendfile/sys/arm/conf/BEAGLEBONE =================================================================== --- projects/sendfile/sys/arm/conf/BEAGLEBONE (revision 276056) +++ projects/sendfile/sys/arm/conf/BEAGLEBONE (revision 276057) @@ -1,153 +1,161 @@ +# # BEAGLEBONE -- Custom configuration for the BeagleBone ARM development # platforms, check out http://www.beagleboard.org/bone and # http://www.beagleboard.org/black. This kernel config file is used for the # original BeagleBone and the BeagleBone Black. # -# For more information on this file, please read the handbook section on -# Kernel Configuration Files: +# For more information on this file, please read the config(5) manual page, +# and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident BEAGLEBONE include "../ti/am335x/std.am335x" makeoptions WITHOUT_MODULES="ahc" options HZ=100 options SCHED_4BSD # 4BSD scheduler +options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols +options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options TMPFS # Efficient memory filesystem +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS +options NFSCL # New Network Filesystem Client +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL options MSDOSFS # MSDOS Filesystem options CD9660 # ISO 9660 Filesystem options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables +options GEOM_PART_BSD # BSD partition scheme +options GEOM_PART_MBR # MBR partition scheme options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions options KBD_INSTALL_CDEV # install a CDEV entry in /dev -options PREEMPTION options PLATFORM -options FREEBSD_BOOT_LOADER -options VFP # vfp/neon +options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) +options VFP # Enable floating point hardware support # Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options BREAK_TO_DEBUGGER #options VERBOSE_SYSINIT # Enable verbose sysinit messages -options KDB +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: options DDB # Enable the kernel debugger options INVARIANTS # Enable calls of extra sanity checking options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS options WITNESS # Enable checks to detect deadlocks and cycles options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options DIAGNOSTIC -# NFS support -options NFSCL -#options NFSD -options NFSLOCKD +# NFS server support +#options NFSD -# Uncomment this for NFS root -#options NFS_ROOT # NFS usable as /, requires NFSCL +# NFS root from boopt/dhcp +#options BOOTP #options BOOTP_NFSROOT #options BOOTP_COMPAT -#options BOOTP #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=cpsw0 +# Boot device is 2nd slice on MMC/SD card +options ROOTDEVNAME=\"ufs:mmcsd0s2\" + # MMC/SD/SDIO Card slot support device mmc # mmc/sd bus device mmcsd # mmc/sd flash cards device sdhci # mmc/sd host controller # I2C support device iicbus device iic device ti_i2c device am335x_pmic # AM335x Power Management IC (TPC65217) -# Boot device is 2nd slice on MMC/SD card -options ROOTDEVNAME=\"ufs:mmcsd0s2\" - # Console and misc device uart device uart_ns8250 device pty device snp device md device random # Entropy device # GPIO device gpio device gpioled # ADC support device ti_adc # Watchdog support # If we don't enable the watchdog driver, the system could potentially # reboot automatically because the boot loader might have enabled the # watchdog. device ti_wdt # TI Programmable Realtime Unit support device ti_pruss # Mailbox support device ti_mbox # USB support device usb options USB_HOST_ALIGN=64 # Align usb buffers to cache line size. options USB_DEBUG #options USB_REQ_DEBUG #options USB_VERBOSE device musb device umass device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) # Ethernet device loop device ether device mii device smscphy device cpsw device bpf # USB Ethernet support, requires miibus device miibus device axe # ASIX Electronics USB Ethernet # Device mode support and USFS template device usb_template # Control of the gadget device usfs # Flattened Device Tree -options FDT -options FDT_DTB_STATIC -makeoptions FDT_DTS_FILE=beaglebone.dts +options FDT # Configure using FDT/DTB data +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=beaglebone.dts Index: projects/sendfile/sys/arm/conf/CHROMEBOOK-PEACH-PIT =================================================================== --- projects/sendfile/sys/arm/conf/CHROMEBOOK-PEACH-PIT (revision 276056) +++ projects/sendfile/sys/arm/conf/CHROMEBOOK-PEACH-PIT (revision 276057) @@ -1,47 +1,47 @@ # Kernel configuration for Chromebook2 (Exynos5 Octa machine). # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ #NO_UNIVERSE include "EXYNOS5420" ident CHROMEBOOK-PEACH-PIT hints "CHROMEBOOK-PEACH-PIT.hints" device chrome_ec_spi # Chrome Embedded Controller device chrome_kb # Chrome Keyboard # Framebuffer device vt device kbdmux device ukbd # Uncomment this for NFS root -#options NFS_ROOT # NFS usable as /, requires NFSCL -#options BOOTP_NFSROOT -#options BOOTP_COMPAT -#options BOOTP -#options BOOTP_NFSV3 -#options BOOTP_WIRED_TO=ue0 -#options ROOTDEVNAME=\"nfs:10.5.0.1:/tftpboot/root\" +#options NFS_ROOT # NFS usable as /, requires NFSCL +#options BOOTP_NFSROOT +#options BOOTP_COMPAT +#options BOOTP +#options BOOTP_NFSV3 +#options BOOTP_WIRED_TO=ue0 +#options ROOTDEVNAME=\"nfs:10.5.0.1:/tftpboot/root\" #FDT -options FDT -options FDT_DTB_STATIC +options FDT +options FDT_DTB_STATIC makeoptions FDT_DTS_FILE=exynos5420-peach-pit.dts Index: projects/sendfile/sys/arm/conf/CNS11XXNAS =================================================================== --- projects/sendfile/sys/arm/conf/CNS11XXNAS (revision 276056) +++ projects/sendfile/sys/arm/conf/CNS11XXNAS (revision 276057) @@ -1,125 +1,125 @@ # CNS11XXNAS - StarSemi STR9104/Cavium CNS1102 NAS # kernel configuration file for FreeBSD/arm # # For more information on this file, please read the handbook section on # Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident CNS11XXNAS #options PHYSADDR=0x10000000 #options KERNPHYSADDR=0x10200000 #options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm #options FLASHADDR=0x50000000 #options LOADERRAMADDR=0x00000000 include "../cavium/cns11xx/std.econa" makeoptions MODULES_OVERRIDE="" makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options HZ=100 options DEVICE_POLLING # Debugging for use in -current options KDB #options GDB options DDB # Enable the kernel debugger #options DEADLKRES # Enable the deadlock resolver #options INVARIANTS # Enable calls of extra sanity checking #options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS #options WITNESS # Enable checks to detect deadlocks and cycles ##options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options DIAGNOSTIC #options COMPAT_FREEBSD5 #options COMPAT_FREEBSD6 #options COMPAT_FREEBSD7n options SCHED_ULE # ULE scheduler #options SCHED_4BSD # 4BSD scheduler options GEOM_PART_BSD # BSD partition scheme options GEOM_PART_MBR # MBR partition scheme options GEOM_PART_GPT # GUID Partition Tables. #options GEOM_PART_EBR #options GEOM_PART_EBR_COMPAT options GEOM_LABEL # Provides labelization options INET # InterNETworking options INET6 # IPv6 communications protocols options FFS # Berkeley Fast Filesystem options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories options NFSCL # New Network Filesystem Client #options NFSD # New Network Filesystem Server #options NFSLOCKD # Network Lock Manager options NFS_ROOT # NFS usable as /, requires NFSCL options TMPFS # Efficient memory filesystem options MSDOSFS # MSDOS Filesystem #options CD9660 # ISO 9660 Filesystem #options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions options MUTEX_NOINLINE # Mutex inlines are space hogs options RWLOCK_NOINLINE # rwlock inlines are space hogs options SX_NOINLINE # sx inliens are space hogs #options BOOTP #options BOOTP_NFSROOT #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=npe0 #options BOOTP_COMPAT #device pci device uart device firmware device mii # Minimal mii routines device ether device bpf device loop device md -device random # Entropy device +device random # Entropy device device usb #options USB_DEBUG device ohci device ehci device umass device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device pass -device cfi +device cfi #device udav # Davicom DM9601E USB device geom_label device geom_journal -device geom_part_bsd +device geom_part_bsd options ROOTDEVNAME=\"ufs:da0s1a\" Index: projects/sendfile/sys/arm/conf/CUBIEBOARD =================================================================== --- projects/sendfile/sys/arm/conf/CUBIEBOARD (revision 276056) +++ projects/sendfile/sys/arm/conf/CUBIEBOARD (revision 276057) @@ -1,140 +1,145 @@ +# # CUBIEBOARD -- Custom configuration for the CUBIEBOARD ARM development # platform, check out http://www.cubieboard.org # -# For more information on this file, please read the handbook section on -# Kernel Configuration Files: +# For more information on this file, please read the config(5) manual page, +# and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident CUBIEBOARD include "../allwinner/std.a10" makeoptions MODULES_OVERRIDE="" makeoptions WITHOUT_MODULES="ahc" options HZ=100 options SCHED_4BSD # 4BSD scheduler +options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options TMPFS # Efficient memory filesystem +options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS +options NFSCL # New Network Filesystem Client +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL options MSDOSFS # MSDOS Filesystem options CD9660 # ISO 9660 Filesystem options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables +options GEOM_PART_BSD # BSD partition scheme +options GEOM_PART_MBR # MBR partition scheme options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions options KBD_INSTALL_CDEV # install a CDEV entry in /dev -options PREEMPTION -options FREEBSD_BOOT_LOADER -options VFP # vfp/neon +options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) +options VFP # Enable floating point hardware support -# Debugging +# Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options BREAK_TO_DEBUGGER #options VERBOSE_SYSINIT # Enable verbose sysinit messages -options KDB +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: options DDB # Enable the kernel debugger options INVARIANTS # Enable calls of extra sanity checking options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS options WITNESS # Enable checks to detect deadlocks and cycles options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options DIAGNOSTIC -# NFS support -#options NFSCL -#options NFSSERVER # Network Filesystem Server -#options NFSCLIENT # Network Filesystem Client - -# Uncomment this for NFS root -#options NFS_ROOT # NFS usable as /, requires NFSCLIENT +# NFS root from boopt/dhcp +#options BOOTP #options BOOTP_NFSROOT #options BOOTP_COMPAT -#options BOOTP #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=cpsw0 -# MMC/SD/SDIO card slot support -#device mmc # mmc/sd bus -#device mmcsd # mmc/sd flash cards - # Boot device is 2nd slice on MMC/SD card options ROOTDEVNAME=\"ufs:/dev/da0s2\" +# MMC/SD/SDIO Card slot support +#device mmc # mmc/sd bus +#device mmcsd # mmc/sd flash cards + # ATA controllers #device ahci # AHCI-compatible SATA controllers #device ata # Legacy ATA/SATA controllers -#options ATA_STATIC_ID # Static device numbering +#options ATA_STATIC_ID # Static device numbering # Console and misc device uart device uart_ns8250 device pty device snp device md device random # Entropy device # I2C support #device iicbus #device iic # GPIO device gpio device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device pass # USB support options USB_HOST_ALIGN=64 # Align usb buffers to cache line size. device usb options USB_DEBUG #options USB_REQ_DEBUG #options USB_VERBOSE #device uhci #device ohci device ehci device umass # Ethernet device loop device ether device mii device smscphy #device cpsw device bpf device emac # USB ethernet support, requires miibus device miibus # Flattened Device Tree -options FDT +options FDT # Configure using FDT/DTB data options FDT_DTB_STATIC makeoptions FDT_DTS_FILE=cubieboard.dts Index: projects/sendfile/sys/arm/conf/CUBIEBOARD2 =================================================================== --- projects/sendfile/sys/arm/conf/CUBIEBOARD2 (revision 276056) +++ projects/sendfile/sys/arm/conf/CUBIEBOARD2 (revision 276057) @@ -1,141 +1,146 @@ +# # CUBIEBOARD2 -- Custom configuration for the CUBIEBOARD2 ARM development # platform, check out http://www.cubieboard.org # -# For more information on this file, please read the handbook section on -# Kernel Configuration Files: +# For more information on this file, please read the config(5) manual page, +# and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident CUBIEBOARD2 include "../allwinner/a20/std.a20" makeoptions MODULES_OVERRIDE="" makeoptions WITHOUT_MODULES="ahc" options HZ=100 options SCHED_4BSD # 4BSD scheduler +options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options TMPFS # Efficient memory filesystem +options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS +options NFSCL # New Network Filesystem Client +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL options MSDOSFS # MSDOS Filesystem options CD9660 # ISO 9660 Filesystem options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables +options GEOM_PART_BSD # BSD partition scheme +options GEOM_PART_MBR # MBR partition scheme options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions options KBD_INSTALL_CDEV # install a CDEV entry in /dev -options PREEMPTION -options FREEBSD_BOOT_LOADER -options VFP # vfp/neon +options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) +options VFP # Enable floating point hardware support +options SMP # Enable multiple cores -# Debugging +# Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options BREAK_TO_DEBUGGER #options VERBOSE_SYSINIT # Enable verbose sysinit messages -options KDB +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: options DDB # Enable the kernel debugger options INVARIANTS # Enable calls of extra sanity checking options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS options WITNESS # Enable checks to detect deadlocks and cycles options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options DIAGNOSTIC -# NFS support -#options NFSCL -#options NFSSERVER # Network Filesystem Server -#options NFSCLIENT # Network Filesystem Client - -# Uncomment this for NFS root -#options NFS_ROOT # NFS usable as /, requires NFSCLIENT +# NFS root from boopt/dhcp +#options BOOTP #options BOOTP_NFSROOT #options BOOTP_COMPAT -#options BOOTP #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=cpsw0 -# MMC/SD/SDIO card slot support -#device mmc # mmc/sd bus -#device mmcsd # mmc/sd flash cards - # Boot device is 2nd slice on MMC/SD card options ROOTDEVNAME=\"ufs:/dev/da0s2\" +# MMC/SD/SDIO Card slot support +#device mmc # mmc/sd bus +#device mmcsd # mmc/sd flash cards + # ATA controllers #device ahci # AHCI-compatible SATA controllers #device ata # Legacy ATA/SATA controllers -#options ATA_STATIC_ID # Static device numbering +#options ATA_STATIC_ID # Static device numbering # Console and misc device uart device uart_ns8250 device pty device snp device md device random # Entropy device # I2C support #device iicbus #device iic # GPIO device gpio device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device pass # USB support options USB_HOST_ALIGN=64 # Align usb buffers to cache line size. device usb options USB_DEBUG #options USB_REQ_DEBUG #options USB_VERBOSE #device uhci #device ohci device ehci device umass # Ethernet device loop device ether device mii device smscphy #device cpsw device bpf device emac # USB ethernet support, requires miibus device miibus # Flattened Device Tree -options FDT +options FDT # Configure using FDT/DTB data options FDT_DTB_STATIC makeoptions FDT_DTS_FILE=cubieboard2.dts -options SMP # Enable multiple cores Index: projects/sendfile/sys/arm/conf/DIGI-CCWMX53 =================================================================== --- projects/sendfile/sys/arm/conf/DIGI-CCWMX53 (revision 276056) +++ projects/sendfile/sys/arm/conf/DIGI-CCWMX53 (revision 276057) @@ -1,38 +1,38 @@ # Kernel configuration for Digi ConnectCore Wi-i.MX53 boards # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ #NO_UNIVERSE include "IMX53" ident DIGI-CCWMX53 -makeoptions WITHOUT_MODULES="ahc" +makeoptions WITHOUT_MODULES="ahc" # required for netbooting #options BOOTP #options BOOTP_COMPAT #options BOOTP_NFSROOT #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=ffec0 #options ROOTDEVNAME=\"ufs:ada0s2a\" # Flattened Device Tree -options FDT_DTB_STATIC -makeoptions FDT_DTS_FILE=digi-ccwmx53.dts +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=digi-ccwmx53.dts Index: projects/sendfile/sys/arm/conf/DOCKSTAR =================================================================== --- projects/sendfile/sys/arm/conf/DOCKSTAR (revision 276056) +++ projects/sendfile/sys/arm/conf/DOCKSTAR (revision 276057) @@ -1,168 +1,168 @@ # # Custom kernel for Seagate DockStar (Marvell SheevaPlug based) devices. # # $FreeBSD$ # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ # ident DOCKSTAR include "../mv/kirkwood/std.db88f6xxx" makeoptions FDT_DTS_FILE=dockstar.dts makeoptions MODULES_OVERRIDE="" options SOC_MV_KIRKWOOD options SCHED_4BSD # 4BSD scheduler options INET # InterNETworking options INET6 # IPv6 communications protocols options SOFTUPDATES options CD9660 # ISO 9660 filesystem options FFS # Berkeley Fast Filesystem options TMPFS # Efficient memory filesystem options MSDOSFS # MS DOS File System (FAT, FAT32) options NULLFS # NULL filesystem options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions options GEOM_PART_BSD # BSD partition scheme options GEOM_PART_MBR # MBR partition scheme options GEOM_ELI # Disk encryption. options GEOM_LABEL # Providers labelization. options GEOM_PART_GPT # GPT partitioning # Flattened Device Tree device fdt options FDT options FDT_DTB_STATIC # Misc pseudo devices device bpf # Required for DHCP -device firmware # firmware(9) required for USB wlan -device gif # IPv6 and IPv4 tunneling +device firmware # firmware(9) required for USB wlan +device gif # IPv6 and IPv4 tunneling device loop # Network loopback -device md # Memory/malloc disk +device md # Memory/malloc disk device pty # BSD-style compatibility pseudo ttys device random # Entropy device -device tun # Packet tunnel. +device tun # Packet tunnel. device ether # Required for all ethernet devices -device vlan # 802.1Q VLAN support +device vlan # 802.1Q VLAN support device wlan # 802.11 WLAN support # cam support for umass and ahci device scbus device pass device da # Serial ports device uart # Networking device mge # Marvell Gigabit Ethernet controller device mii device e1000phy # USB options USB_HOST_ALIGN=32 # Align DMA to cacheline -#options USB_DEBUG # Compile in USB debug support -device usb # Basic usb support -device ehci # USB host controller -device umass # Mass storage -device uhid # Human-interface devices -device rum # Ralink Technology RT2501USB wireless NICs -device uath # Atheros AR5523 wireless NICs -device ural # Ralink Technology RT2500USB wireless NICs -device zyd # ZyDAS zb1211/zb1211b wireless NICs -device urtw # Realtek RTL8187B/L USB -device upgt # Conexant/Intersil PrismGT SoftMAC USB -device u3g # USB-based 3G modems (Option, Huawei, Sierra) +#options USB_DEBUG # Compile in USB debug support +device usb # Basic usb support +device ehci # USB host controller +device umass # Mass storage +device uhid # Human-interface devices +device rum # Ralink Technology RT2501USB wireless NICs +device uath # Atheros AR5523 wireless NICs +device ural # Ralink Technology RT2500USB wireless NICs +device zyd # ZyDAS zb1211/zb1211b wireless NICs +device urtw # Realtek RTL8187B/L USB +device upgt # Conexant/Intersil PrismGT SoftMAC USB +device u3g # USB-based 3G modems (Option, Huawei, Sierra) # I2C (TWSI) device iic device iicbus # Sound -device sound -device snd_uaudio +device sound +device snd_uaudio #crypto -device cesa # Marvell security engine -device crypto -device cryptodev +device cesa # Marvell security engine +device crypto +device cryptodev # IPSec -device enc -options IPSEC -options IPSEC_NAT_T -options TCP_SIGNATURE # include support for RFC 2385 +device enc +options IPSEC +options IPSEC_NAT_T +options TCP_SIGNATURE # include support for RFC 2385 # IPFW -options IPFIREWALL -options IPFIREWALL_DEFAULT_TO_ACCEPT -options IPFIREWALL_VERBOSE -options IPFIREWALL_VERBOSE_LIMIT=100 -options IPFIREWALL_NAT -options LIBALIAS -options DUMMYNET -options IPDIVERT +options IPFIREWALL +options IPFIREWALL_DEFAULT_TO_ACCEPT +options IPFIREWALL_VERBOSE +options IPFIREWALL_VERBOSE_LIMIT=100 +options IPFIREWALL_NAT +options LIBALIAS +options DUMMYNET +options IPDIVERT #PF -device pf -device pflog -device pfsync +device pf +device pflog +device pfsync # ALTQ, required for PF -options ALTQ # Basic ALTQ support -options ALTQ_CBQ # Class Based Queueing -options ALTQ_RED # Random Early Detection -options ALTQ_RIO # RED In/Out -options ALTQ_HFSC # Hierarchical Packet Scheduler -options ALTQ_CDNR # Traffic conditioner -options ALTQ_PRIQ # Priority Queueing -options ALTQ_NOPCC # Required if the TSC is unusable +options ALTQ # Basic ALTQ support +options ALTQ_CBQ # Class Based Queueing +options ALTQ_RED # Random Early Detection +options ALTQ_RIO # RED In/Out +options ALTQ_HFSC # Hierarchical Packet Scheduler +options ALTQ_CDNR # Traffic conditioner +options ALTQ_PRIQ # Priority Queueing +options ALTQ_NOPCC # Required if the TSC is unusable #options ALTQ_DEBUG # Debugging -makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options BREAK_TO_DEBUGGER options ALT_BREAK_TO_DEBUGGER options DDB options KDB #options DIAGNOSTIC options INVARIANTS # Enable calls of extra sanity checking options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS #options WITNESS # Enable checks to detect deadlocks and cycles #options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options WITNESS_KDB # Enable these options for nfs root configured via BOOTP. options NFSCL # Network Filesystem Client options NFSLOCKD # Network Lock Manager #options NFS_ROOT # NFS usable as /, requires NFSCLIENT #options BOOTP #options BOOTP_NFSROOT #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=mge0 # If not using BOOTP, use something like one of these... #options ROOTDEVNAME=\"ufs:/dev/da0a\" options ROOTDEVNAME=\"ufs:/dev/da0s1a\" #options ROOTDEVNAME=\"ufs:/dev/da0p10\" #options ROOTDEVNAME=\"nfs:192.168.0.254/dreamplug\" Index: projects/sendfile/sys/arm/conf/DREAMPLUG-1001 =================================================================== --- projects/sendfile/sys/arm/conf/DREAMPLUG-1001 (revision 276056) +++ projects/sendfile/sys/arm/conf/DREAMPLUG-1001 (revision 276057) @@ -1,184 +1,184 @@ # Kernel config for GlobalScale Technologies DreamPlug version 1001. # # This is for units that are version 10, revision 01, with NOR SPI flash. # These units are identified with the number "1001" on the S/N label. # # For more information on this file, please read the handbook section on # Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ # ident DREAMPLUG-1001 include "../mv/kirkwood/std.db88f6xxx" makeoptions FDT_DTS_FILE=dreamplug-1001.dts makeoptions MODULES_OVERRIDE="" options SOC_MV_KIRKWOOD options SCHED_4BSD # 4BSD scheduler options INET # InterNETworking options INET6 # IPv6 communications protocols options SOFTUPDATES options TMPFS # Efficient memory filesystem options CD9660 # ISO 9660 filesystem options FFS # Berkeley Fast Filesystem options MSDOSFS # MS DOS File System (FAT, FAT32) options NULLFS # NULL filesystem options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions options GEOM_PART_BSD # BSD partition scheme options GEOM_PART_MBR # MBR partition scheme options GEOM_ELI # Disk encryption. options GEOM_LABEL # Providers labelization. options GEOM_PART_GPT # GPT partitioning # Flattened Device Tree device fdt options FDT options FDT_DTB_STATIC # Misc pseudo devices device bpf # Required for DHCP -device firmware # firmware(9) required for USB wlan -device gif # IPv6 and IPv4 tunneling +device firmware # firmware(9) required for USB wlan +device gif # IPv6 and IPv4 tunneling device loop # Network loopback -device md # Memory/malloc disk +device md # Memory/malloc disk device pty # BSD-style compatibility pseudo ttys device random # Entropy device -device tun # Packet tunnel. +device tun # Packet tunnel. device ether # Required for all ethernet devices -device vlan # 802.1Q VLAN support +device vlan # 802.1Q VLAN support device wlan # 802.11 WLAN support # cam support for umass and ahci device scbus device pass device da -device cd +device cd # Serial ports device uart # Networking device mge # Marvell Gigabit Ethernet controller device mii device e1000phy # USB options USB_HOST_ALIGN=32 # Align DMA to cacheline -#options USB_DEBUG # Compile in USB debug support -device usb # Basic usb support -device ehci # USB host controller -device umass # Mass storage -device uhid # Human-interface devices -device rum # Ralink Technology RT2501USB wireless NICs -device uath # Atheros AR5523 wireless NICs -device ural # Ralink Technology RT2500USB wireless NICs -device zyd # ZyDAS zb1211/zb1211b wireless NICs -device urtw # Realtek RTL8187B/L USB -device upgt # Conexant/Intersil PrismGT SoftMAC USB -device u3g # USB-based 3G modems (Option, Huawei, Sierra) +#options USB_DEBUG # Compile in USB debug support +device usb # Basic usb support +device ehci # USB host controller +device umass # Mass storage +device uhid # Human-interface devices +device rum # Ralink Technology RT2501USB wireless NICs +device uath # Atheros AR5523 wireless NICs +device ural # Ralink Technology RT2500USB wireless NICs +device zyd # ZyDAS zb1211/zb1211b wireless NICs +device urtw # Realtek RTL8187B/L USB +device upgt # Conexant/Intersil PrismGT SoftMAC USB +device u3g # USB-based 3G modems (Option, Huawei, Sierra) # I2C (TWSI) device iic device iicbus # SATA device mvs device ahci # Sound -device sound -device snd_uaudio +device sound +device snd_uaudio #crypto -device cesa # Marvell security engine -device crypto -device cryptodev +device cesa # Marvell security engine +device crypto +device cryptodev # IPSec -device enc -options IPSEC -options IPSEC_NAT_T -options TCP_SIGNATURE # include support for RFC 2385 +device enc +options IPSEC +options IPSEC_NAT_T +options TCP_SIGNATURE # include support for RFC 2385 # IPFW -options IPFIREWALL -options IPFIREWALL_DEFAULT_TO_ACCEPT -options IPFIREWALL_VERBOSE -options IPFIREWALL_VERBOSE_LIMIT=100 -options IPFIREWALL_NAT -options LIBALIAS -options DUMMYNET -options IPDIVERT +options IPFIREWALL +options IPFIREWALL_DEFAULT_TO_ACCEPT +options IPFIREWALL_VERBOSE +options IPFIREWALL_VERBOSE_LIMIT=100 +options IPFIREWALL_NAT +options LIBALIAS +options DUMMYNET +options IPDIVERT #PF -device pf -device pflog -device pfsync +device pf +device pflog +device pfsync # ALTQ, required for PF -options ALTQ # Basic ALTQ support -options ALTQ_CBQ # Class Based Queueing -options ALTQ_RED # Random Early Detection -options ALTQ_RIO # RED In/Out -options ALTQ_HFSC # Hierarchical Packet Scheduler -options ALTQ_CDNR # Traffic conditioner -options ALTQ_PRIQ # Priority Queueing -options ALTQ_NOPCC # Required if the TSC is unusable +options ALTQ # Basic ALTQ support +options ALTQ_CBQ # Class Based Queueing +options ALTQ_RED # Random Early Detection +options ALTQ_RIO # RED In/Out +options ALTQ_HFSC # Hierarchical Packet Scheduler +options ALTQ_CDNR # Traffic conditioner +options ALTQ_PRIQ # Priority Queueing +options ALTQ_NOPCC # Required if the TSC is unusable #options ALTQ_DEBUG # Debugging -makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options BREAK_TO_DEBUGGER options ALT_BREAK_TO_DEBUGGER options DDB options KDB #options DIAGNOSTIC options INVARIANTS # Enable calls of extra sanity checking options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS #options WITNESS # Enable checks to detect deadlocks and cycles #options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options WITNESS_KDB # Enable these options for nfs root configured via BOOTP. options NFSCL # Network Filesystem Client options NFSLOCKD # Network Lock Manager #options NFS_ROOT # NFS usable as /, requires NFSCLIENT #options BOOTP #options BOOTP_NFSROOT #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=mge0 # If not using BOOTP, use something like one of these... #options ROOTDEVNAME=\"ufs:/dev/da1a\" options ROOTDEVNAME=\"ufs:/dev/da1s1a\" #options ROOTDEVNAME=\"ufs:/dev/da1p10\" #options ROOTDEVNAME=\"nfs:192.168.0.254/dreamplug\" # To use this configuration with the (rare) model 1001N (nand flash), # create a kernel config file that looks like this: # # include DREAMPLUG-1001 -# nomakeoptions FDT_DTS_FILE +# nomakeoptions FDT_DTS_FILE # makeoptions FDT_DTS_FILE=dreamplug-1001N.dts # device nand Index: projects/sendfile/sys/arm/conf/EFIKA_MX =================================================================== --- projects/sendfile/sys/arm/conf/EFIKA_MX (revision 276056) +++ projects/sendfile/sys/arm/conf/EFIKA_MX (revision 276057) @@ -1,176 +1,180 @@ +# # Kernel configuration for Efika MX Smarttop/Smartbook boards # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident EFIKA_MX include "../freescale/imx/std.imx51" -makeoptions WITHOUT_MODULES="ahc" +makeoptions WITHOUT_MODULES="ahc" -makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols -#options DEBUG - options SCHED_4BSD # 4BSD scheduler -#options PREEMPTION # Enable kernel thread preemption +options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking -#options INET6 # IPv6 communications protocols -#options SCTP # Stream Control Transmission Protocol +options INET6 # IPv6 communications protocols +options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS #options MD_ROOT # MD is a potential root device options NFSCL # New Network Filesystem Client #options NFSD # New Network Filesystem Server options NFSLOCKD # Network Lock Manager options NFS_ROOT # NFS usable as /, requires NFSCL -options TMPFS # Efficient memory filesystem options MSDOSFS # MSDOS Filesystem options CD9660 # ISO 9660 Filesystem -#options PROCFS # Process filesystem (requires PSEUDOFS) +options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables options GEOM_PART_BSD # BSD partition scheme options GEOM_PART_MBR # MBR partition scheme -options GEOM_PART_GPT # GUID Partition Tables. options GEOM_LABEL # Provides labelization #options COMPAT_FREEBSD5 # Compatible with FreeBSD5 #options COMPAT_FREEBSD6 # Compatible with FreeBSD6 #options COMPAT_FREEBSD7 # Compatible with FreeBSD7 options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev options INCLUDE_CONFIG_FILE # Include this file in kernel -options VFP # vfp/neon +options VFP # Enable floating point hardware support -# required for netbooting +# Debugging for use in -current +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols +options BREAK_TO_DEBUGGER +#options VERBOSE_SYSINIT # Enable verbose sysinit messages +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: +options DDB # Enable the kernel debugger +#options GDB # Support remote GDB +options DEADLKRES # Enable the deadlock resolver +options INVARIANTS # Enable calls of extra sanity checking +options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS +options WITNESS # Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed + +# NFS root from boopt/dhcp #options BOOTP -#options BOOTP_COMPAT #options BOOTP_NFSROOT +#options BOOTP_COMPAT #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=ue0 -# + options ROOTDEVNAME=\"ufs:ada0s2a\" # kernel/memory size reduction #options MUTEX_NOINLINE #options NO_FFS_SNAPSHOT #options NO_SWAPPING #options NO_SYSCTL_DESCR #options RWLOCK_NOINLINE -# Debugging support. Always need this: -options KDB # Enable kernel debugger support. -# For minimum debugger support (stable branch) use: -#options KDB_TRACE # Print a stack trace for a panic. -# For full debugger support use this instead: -options DDB # Support DDB. -#options GDB # Support remote GDB. -options DEADLKRES # Enable the deadlock resolver -options INVARIANTS # Enable calls of extra sanity checking -options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS -options WITNESS # Enable checks to detect deadlocks and cycles - # The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! # Note that 'bpf' is required for DHCP. device bpf # Berkeley packet filter # Pseudo devices. device loop # Network loopback device random # Entropy device device ether # Ethernet support #device vlan # 802.1Q VLAN support #device tun # Packet tunnel. #device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling #device firmware # firmware assist module # Serial (COM) ports device uart # Multi-uart driver options ALT_BREAK_TO_DEBUGGER device ata device atapci # Only for helper functions device imxata options ATA_STATIC_ID # Static device numbering device gpio device gpioled device fsliic device iic device iicbus # SCSI peripherals device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device cd # CD device pass # Passthrough device (direct ATA/SCSI access) # USB support options USB_HOST_ALIGN=64 # Align usb buffers to cache line size. #options USB_DEBUG # enable debug msgs device ehci # OHCI USB interface device usb # USB Bus (required) device umass # Disks/Mass storage - Requires scbus and da device uhid # "Human Interface Devices" device u3g # USB Ethernet, requires miibus device miibus device aue # ADMtek USB Ethernet device axe # ASIX Electronics USB Ethernet device cdce # Generic USB over Ethernet device cue # CATC USB Ethernet device kue # Kawasaki LSI USB Ethernet device rue # RealTek RTL8150 USB Ethernet device udav # Davicom DM9601E USB # USB Wireless device rum # Ralink Technology RT2501USB wireless NICs # Watchdog timer. # WARNING: can't be disabled!!! device imxwdt # Watchdog # Wireless NIC cards device wlan # 802.11 support device wlan_wep # 802.11 WEP support device wlan_ccmp # 802.11 CCMP support device wlan_tkip # 802.11 TKIP support device wlan_amrr # AMRR transmit rate control algorithm # Flattened Device Tree -options FDT -options FDT_DTB_STATIC -makeoptions FDT_DTS_FILE=efikamx.dts +options FDT # Configure using FDT/DTB data +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=efikamx.dts # NOTE: serial console will be disabled if syscons enabled # Uncomment following lines for framebuffer/syscons support device sc device kbdmux -options SC_DFLT_FONT # compile font in -makeoptions SC_DFLT_FONT=cp437 +options SC_DFLT_FONT # compile font in +makeoptions SC_DFLT_FONT=cp437 device ukbd # Allow keyboard like HIDs to control console device ums Index: projects/sendfile/sys/arm/conf/EXYNOS5.common =================================================================== --- projects/sendfile/sys/arm/conf/EXYNOS5.common (revision 276056) +++ projects/sendfile/sys/arm/conf/EXYNOS5.common (revision 276057) @@ -1,136 +1,139 @@ +# # Kernel configuration for Samsung Exynos 5 SoC. # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ makeoptions MODULES_OVERRIDE="" makeoptions WITHOUT_MODULES="ahc" -makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols makeoptions WERROR="-Werror" options HZ=100 options SCHED_4BSD # 4BSD scheduler +options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options GEOM_PART_GPT # GUID partition tables -options TMPFS # Efficient memory filesystem +options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem -options SOFTUPDATES +options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS +options NFSCL # New Network Filesystem Client +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL options MSDOSFS # MSDOS Filesystem options CD9660 # ISO 9660 Filesystem options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables +options GEOM_PART_BSD # BSD partition scheme +options GEOM_PART_MBR # MBR partition scheme options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE +options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions -options KBD_INSTALL_CDEV -options PREEMPTION -options FREEBSD_BOOT_LOADER -options VFP # vfp/neon +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev +options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) +options VFP # Enable floating point hardware support +options SMP # Enable multiple cores -options SMP - -# Debugging +# Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options BREAK_TO_DEBUGGER -#options VERBOSE_SYSINIT # Enable verbose sysinit messages -options KDB +#options VERBOSE_SYSINIT # Enable verbose sysinit messages +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: options DDB # Enable the kernel debugger #options INVARIANTS # Enable calls of extra sanity checking #options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS -#options WITNESS # Enable checks to detect deadlocks and cycles -#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed +#options WITNESS # Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options DIAGNOSTIC -# NFS support -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCLIENT +# NFS root from boopt/dhcp +#options BOOTP +#options BOOTP_NFSROOT +#options BOOTP_COMPAT +#options BOOTP_NFSV3 +#options BOOTP_WIRED_TO=ue0 -# Uncomment this for NFS root -#options NFS_ROOT # NFS usable as /, requires NFSCL -#options BOOTP_NFSROOT -#options BOOTP_COMPAT -#options BOOTP -#options BOOTP_NFSV3 -#options BOOTP_WIRED_TO=ue0 +options ROOTDEVNAME=\"ufs:/dev/da0\" +# MMC/SD/SDIO Card slot support device mmc # mmc/sd bus device mmcsd # mmc/sd flash cards device dwmmc -options ROOTDEVNAME=\"ufs:/dev/da0\" - # Pseudo devices device loop device random device pty device md device gpio # USB support options USB_HOST_ALIGN=64 # Align usb buffers to cache line size. device usb options USB_DEBUG -#options USB_REQ_DEBUG -#options USB_VERBOSE +#options USB_REQ_DEBUG +#options USB_VERBOSE #device musb device ehci #device ohci device xhci device umass device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device pass # SATA #device ata #device atadisk #device mvs # Serial ports device uart # I2C (TWSI) device iic device iicbus # SPI device spibus device exynos_spi # Ethernet device ether device mii device smsc device smscphy # USB ethernet support, requires miibus device miibus device axe # ASIX Electronics USB Ethernet device bpf # Berkeley packet filter Index: projects/sendfile/sys/arm/conf/HL201 =================================================================== --- projects/sendfile/sys/arm/conf/HL201 (revision 276056) +++ projects/sendfile/sys/arm/conf/HL201 (revision 276057) @@ -1,147 +1,147 @@ # Kernel configuration for the AT91SAM9G20 based Hot-e configuration file # # For more information on this file, please read the handbook section on # Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ #NO_UNIVERSE ident HL201 include "../at91/std.hl201" makeoptions MODULES_OVERRIDE="" makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options DDB options KDB options SCHED_4BSD # 4BSD scheduler options INET # InterNETworking #options INET6 # IPv6 communications protocols options FFS # Berkeley Fast Filesystem #options SOFTUPDATES # Enable FFS soft updates support #options UFS_ACL # Support for access control lists #options UFS_DIRHASH # Improve performance on big directories #options MD_ROOT # MD is a potential root device #options MD_ROOT_SIZE=4096 # 4MB ram disk options NANDFS # NAND file system options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\" options NFSCL # New Network Filesystem Client #options NFSD # New Network Filesystem Server #options NFSLOCKD # Network Lock Manager options NFS_ROOT # NFS usable as /, requires NFSCL #options BOOTP_NFSROOT #options BOOTP #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=ate0 #options BOOTP_COMPAT options ALT_BREAK_TO_DEBUGGER options GEOM_PART_BSD # BSD partition scheme options GEOM_PART_MBR # MBR partition scheme options TMPFS # Efficient memory filesystem #options MSDOSFS # MSDOS Filesystem #options CD9660 # ISO 9660 Filesystem #options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework #options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI #options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions options MUTEX_NOINLINE options RWLOCK_NOINLINE options NO_FFS_SNAPSHOT options NO_SWAPPING device random device loop device ether device uart device ate device at91_wdt device mii device lxtphy # I2C device at91_twi # Atmel AT91 Two-wire Interface device iic # I2C generic I/O device driver device iicbus # I2C bus system # Debugging for use in -current #options INVARIANTS # Enable calls of extra sanity checking #options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS #options WITNESS # Enable checks to detect deadlocks and cycles #options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options DIAGNOSTIC device md device bpf # USB support device ohci # OHCI localbus->USB interface device usb # USB Bus (required) #device udbp # USB Double Bulk Pipe devices device uhid # "Human Interface Devices" #device ulpt # Printer device umass # Disks/Mass storage - Requires scbus and da # USB Ethernet, requires miibus device miibus #device aue # ADMtek USB Ethernet #device axe # ASIX Electronics USB Ethernet #device cdce # Generic USB over Ethernet #device cue # CATC USB Ethernet #device kue # Kawasaki LSI USB Ethernet #device rue # RealTek RTL8150 USB Ethernet #device udav # Davicom DM9601E USB # USB Wireless #device rum # Ralink Technology RT2501USB wireless NICs #device uath # Atheros AR5523 wireless NICs #device ural # Ralink Technology RT2500USB wireless NICs #device zyd # ZyDAS zd1211/zd1211b wireless NICs # SCSI peripherals device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device cd # CD device pass # Passthrough device (direct ATA/SCSI access) # Wireless NIC cards #device wlan # 802.11 support #device wlan_wep # 802.11 WEP support #device wlan_ccmp # 802.11 CCMP support #device wlan_tkip # 802.11 TKIP support #device wlan_amrr # AMRR transmit rate control algorithm options ROOTDEVNAME=\"ufs:da0s1a\" # NAND Flash - my board as 128MB Samsung part, YMMV. device nand # NAND interface on CS3 # SPI: Data Flash device at91_spi # SPI: device spibus device at45d # at45db642 and maybe others # Coming soon, but not yet options FDT options FDT_DTB_STATIC makeoptions FDT_DTS_FILE=hl201.dts options EARLY_PRINTF -options SOCDEV_PA=0xfc000000 +options SOCDEV_PA=0xfc000000 options SOCDEV_VA=0xdc000000 Index: projects/sendfile/sys/arm/conf/IMX53 =================================================================== --- projects/sendfile/sys/arm/conf/IMX53 (revision 276056) +++ projects/sendfile/sys/arm/conf/IMX53 (revision 276057) @@ -1,172 +1,173 @@ +# # Kernel configuration for i.MX53 boards # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident IMX53 include "../freescale/imx/std.imx53" -makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols -#options DEBUG - options SCHED_4BSD # 4BSD scheduler -#options PREEMPTION # Enable kernel thread preemption +options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols -#options SCTP # Stream Control Transmission Protocol +options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories options UFS_GJOURNAL # Enable gjournal-based UFS journaling -#options MD_ROOT # MD is a potential root device +options QUOTA # Enable disk quotas for UFS options NFSCL # New Network Filesystem Client #options NFSD # New Network Filesystem Server options NFSLOCKD # Network Lock Manager options NFS_ROOT # NFS usable as /, requires NFSCL -options TMPFS # Efficient memory filesystem options MSDOSFS # MSDOS Filesystem options CD9660 # ISO 9660 Filesystem -#options PROCFS # Process filesystem (requires PSEUDOFS) +options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables options GEOM_PART_BSD # BSD partition scheme options GEOM_PART_MBR # MBR partition scheme -options GEOM_PART_GPT # GUID Partition Tables. options GEOM_LABEL # Provides labelization #options COMPAT_FREEBSD5 # Compatible with FreeBSD5 #options COMPAT_FREEBSD6 # Compatible with FreeBSD6 #options COMPAT_FREEBSD7 # Compatible with FreeBSD7 options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev options INCLUDE_CONFIG_FILE # Include this file in kernel -options VFP # vfp/neon +options VFP # Enable floating point hardware support -# kernel/memory size reduction -#options MUTEX_NOINLINE -#options NO_FFS_SNAPSHOT -#options NO_SWAPPING -#options NO_SYSCTL_DESCR -#options RWLOCK_NOINLINE - -# Debugging support. Always need this: -options KDB # Enable kernel debugger support. +# Debugging for use in -current +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols +options KDB # Enable kernel debugger support # For minimum debugger support (stable branch) use: -#options KDB_TRACE # Print a stack trace for a panic. +#options KDB_TRACE # Print a stack trace for a panic # For full debugger support use this instead: -options DDB # Support DDB. -#options GDB # Support remote GDB. +options DDB # Enable the kernel debugger +#options GDB # Support remote GDB options DEADLKRES # Enable the deadlock resolver options INVARIANTS # Enable calls of extra sanity checking options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS options WITNESS # Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed +# kernel/memory size reduction +#options MUTEX_NOINLINE +#options NO_FFS_SNAPSHOT +#options NO_SWAPPING +#options NO_SYSCTL_DESCR +#options RWLOCK_NOINLINE + # The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! # Note that 'bpf' is required for DHCP. device bpf # Berkeley packet filter # Pseudo devices. device loop # Network loopback device random # Entropy device device ether # Ethernet support #device vlan # 802.1Q VLAN support #device tun # Packet tunnel. device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling #device firmware # firmware assist module # Ethernet device ffec # Freescale Fast Ethernet Controller device miibus # Standard mii bus # Serial (COM) ports device uart # Multi-uart driver options ALT_BREAK_TO_DEBUGGER device ata device atapci # Only for helper functions device imxata options ATA_STATIC_ID # Static device numbering device gpio device gpioled device fsliic device iic device iicbus # SCSI peripherals device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device cd # CD device pass # Passthrough device (direct ATA/SCSI access) # USB support options USB_HOST_ALIGN=64 # Align usb buffers to cache line size. options USB_DEBUG # enable debug msgs device ehci # OHCI USB interface device usb # USB Bus (required) device umass # Disks/Mass storage - Requires scbus and da device uhid # "Human Interface Devices" #device ukbd # Allow keyboard like HIDs to control console device ums # USB Ethernet, requires miibus #device miibus #device aue # ADMtek USB Ethernet #device axe # ASIX Electronics USB Ethernet #device cdce # Generic USB over Ethernet #device cue # CATC USB Ethernet #device kue # Kawasaki LSI USB Ethernet #device rue # RealTek RTL8150 USB Ethernet #device udav # Davicom DM9601E USB # USB Wireless #device rum # Ralink Technology RT2501USB wireless NICs # Watchdog timer. # WARNING: can't be disabled!!! device imxwdt # Watchdog # Wireless NIC cards device wlan # 802.11 support device wlan_wep # 802.11 WEP support device wlan_ccmp # 802.11 CCMP support device wlan_tkip # 802.11 TKIP support device wlan_amrr # AMRR transmit rate control algorithm # MMC #device sdhci # SD controller #device mmc # SD/MMC protocol #device mmcsd # SDCard disk device # Flattened Device Tree -options FDT +options FDT # Configure using FDT/DTB data # NOTE: serial console will be disabled if syscons enabled # Uncomment following lines for framebuffer/syscons support #device sc #device vt #device kbdmux -#options SC_DFLT_FONT # compile font in -#makeoptions SC_DFLT_FONT=cp437 +#options SC_DFLT_FONT # compile font in +#makeoptions SC_DFLT_FONT=cp437 Index: projects/sendfile/sys/arm/conf/IMX53-QSB =================================================================== --- projects/sendfile/sys/arm/conf/IMX53-QSB (revision 276056) +++ projects/sendfile/sys/arm/conf/IMX53-QSB (revision 276057) @@ -1,38 +1,38 @@ # Kernel configuration for Freescale i.MX53 Quick Start Board # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ #NO_UNIVERSE include "IMX53" ident IMX53-QSB options HZ=250 # 4ms scheduling quantum # required for netbooting #options BOOTP #options BOOTP_COMPAT #options BOOTP_NFSROOT #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=ue0 #options ROOTDEVNAME=\"ufs:ada0s2a\" # Flattened Device Tree -options FDT_DTB_STATIC -makeoptions FDT_DTS_FILE=imx53-qsb.dts +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=imx53-qsb.dts Index: projects/sendfile/sys/arm/conf/IMX6 =================================================================== --- projects/sendfile/sys/arm/conf/IMX6 (revision 276056) +++ projects/sendfile/sys/arm/conf/IMX6 (revision 276057) @@ -1,159 +1,162 @@ +# # Kernel configuration for Freescale i.MX6 systems. # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident IMX6 include "../freescale/imx/std.imx6" -options HZ=500 # Scheduling quantum is 2 milliseconds. +options HZ=500 # Scheduling quantum is 2 milliseconds. options SCHED_ULE # ULE scheduler options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories options UFS_GJOURNAL # Enable gjournal-based UFS journaling -#options MD_ROOT # MD is a potential root device +options QUOTA # Enable disk quotas for UFS options NFSCL # New Network Filesystem Client #options NFSD # New Network Filesystem Server options NFSLOCKD # Network Lock Manager options NFS_ROOT # NFS usable as /, requires NFSCL -options TMPFS # Efficient memory filesystem options MSDOSFS # MSDOS Filesystem options CD9660 # ISO 9660 Filesystem -#options PROCFS # Process filesystem (requires PSEUDOFS) +options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables options GEOM_PART_BSD # BSD partition scheme options GEOM_PART_MBR # MBR partition scheme -options GEOM_PART_GPT # GUID Partition Tables. options GEOM_LABEL # Provides labelization options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev options INCLUDE_CONFIG_FILE # Include this file in kernel +options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) +options VFP # Enable floating point hardware support +options SMP # Enable multiple cores -# Debugging support. Always need this: -options KDB # Enable kernel debugger support. -# For minimum debugger support use KDB_TRACE, for interactive use DDB. -#options KDB_TRACE # Print a stack trace for a panic. -options DDB # Support DDB. +# Debugging for use in -current +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic # For full debugger support use this instead: +options DDB # Enable the kernel debugger #options GDB # Support remote GDB. # Other debugging options... -makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options ALT_BREAK_TO_DEBUGGER # Use to enter debugger. -#options DEBUG #options DEADLKRES # Enable the deadlock resolver #options INVARIANTS # Enable calls of extra sanity checking #options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS #options WITNESS # Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed +#options DIAGNOSTIC +# NFS root from boopt/dhcp +#options BOOTP +#options BOOTP_NFSROOT +#options BOOTP_COMPAT +#options BOOTP_NFSV3 +#options BOOTP_WIRED_TO=ffec0 + +# U-Boot stuff lives on slice 1, FreeBSD on slice 2. +options ROOTDEVNAME=\"ufs:mmcsd0s2a\" + # Pseudo devices. device loop # Network loopback device random # Entropy device device vlan # 802.1Q VLAN support device tun # Packet tunnel. device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling #device firmware # firmware assist module device ether # Ethernet support device miibus # Required for ethernet device bpf # Berkeley packet filter (required for DHCP) # General-purpose input/output -device gpio +device gpio # Serial (COM) ports device uart # Multi-uart driver # SDCard device sdhci # SD controller device mmc # SD/MMC protocol device mmcsd # SDCard disk device # SCSI peripherals device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device cd # CD device pass # Passthrough device (direct ATA/SCSI access) # USB support #options USB_DEBUG # enable debug msgs device ehci # OHCI USB interface device usb # USB Bus (required) device umass # Disks/Mass storage - Requires scbus and da device uhid # "Human Interface Devices" device u3g # USB modems #device ukbd # Allow keyboard like HIDs to control console #device ums # USB mouse # USB Ethernet, requires miibus #device aue # ADMtek USB Ethernet #device axe # ASIX Electronics USB Ethernet #device cdce # Generic USB over Ethernet #device cue # CATC USB Ethernet #device kue # Kawasaki LSI USB Ethernet #device rue # RealTek RTL8150 USB Ethernet #device udav # Davicom DM9601E USB # USB Wireless #device rum # Ralink Technology RT2501USB wireless NICs # Wireless NIC cards #device wlan # 802.11 support #device wlan_wep # 802.11 WEP support #device wlan_ccmp # 802.11 CCMP support #device wlan_tkip # 802.11 TKIP support #device wlan_amrr # AMRR transmit rate control algorithm # NOTE: serial console will be disabled if syscons enabled # Uncomment following lines for framebuffer/syscons support # Wandboard has no video console support yet. #device sc #device kbdmux #options SC_DFLT_FONT # compile font in #makeoptions SC_DFLT_FONT=cp437 -# required for netbooting -#options BOOTP -#options BOOTP_COMPAT -#options BOOTP_NFSROOT -#options BOOTP_NFSV3 -#options BOOTP_WIRED_TO=ffec0 - -# U-Boot stuff lives on slice 1, FreeBSD on slice 2. -options ROOTDEVNAME=\"ufs:mmcsd0s2a\" - -# ARM and SoC-specific options -options FDT # Configure using FDT/DTB data. -options SMP # Enable multiple cores -options VFP # Enable floating point hardware support -options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) +# Flattened Device Tree +options FDT # Configure using FDT/DTB data # SoC-specific devices device ffec # Freescale Fast Ethernet Controller device fsliic # Freescale i2c/iic device iic # iic protocol device iicbus # iic bus #device imxwdt # Watchdog. WARNING: can't be disabled!!! Index: projects/sendfile/sys/arm/conf/PANDABOARD =================================================================== --- projects/sendfile/sys/arm/conf/PANDABOARD (revision 276056) +++ projects/sendfile/sys/arm/conf/PANDABOARD (revision 276057) @@ -1,151 +1,157 @@ +# # PANDABOARD -- Custom configuration for the PandaBoard ARM development # platform, check out www.pandaboard.org # -# For more information on this file, please read the handbook section on -# Kernel Configuration Files: +# For more information on this file, please read the config(5) manual page, +# and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident PANDABOARD # This probably wants to move somewhere else. Maybe we can create a basic # OMAP4340 config, then make a PANDABOARD config that includes the basic one, # adds the start addresses and custom devices plus pulls in this hints file. hints "PANDABOARD.hints" include "../ti/omap4/pandaboard/std.pandaboard" -#To statically compile in device wiring instead of /boot/device.hints makeoptions MODULES_OVERRIDE="" -makeoptions WITHOUT_MODULES="ahc" +makeoptions WITHOUT_MODULES="ahc" options HZ=100 options SCHED_4BSD # 4BSD scheduler +options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols +options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options TMPFS # Efficient memory filesystem +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS +options NFSCL # New Network Filesystem Client +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL options MSDOSFS # MSDOS Filesystem options CD9660 # ISO 9660 Filesystem options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables +options GEOM_PART_BSD # BSD partition scheme +options GEOM_PART_MBR # MBR partition scheme options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions options KBD_INSTALL_CDEV # install a CDEV entry in /dev -options PREEMPTION options PLATFORM -options FREEBSD_BOOT_LOADER -options VFP # vfp/neon -options SMP # Enable multiple cores +options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) +options VFP # Enable floating point hardware support +options SMP # Enable multiple cores # Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options BREAK_TO_DEBUGGER #options VERBOSE_SYSINIT # Enable verbose sysinit messages -options KDB +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: options DDB # Enable the kernel debugger #options INVARIANTS # Enable calls of extra sanity checking #options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS #options WITNESS # Enable checks to detect deadlocks and cycles #options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options DIAGNOSTIC -# NFS support -options NFSCL - -# NFS root -options NFS_ROOT # NFS usable as /, requires NFSCLIENT +# NFS root from boopt/dhcp +#options BOOTP #options BOOTP_NFSROOT #options BOOTP_COMPAT -#options BOOTP #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=ue0 # MMC/SD/SDIO Card slot support device mmc # mmc/sd bus device mmcsd # mmc/sd flash cards device sdhci # mmc/sd host controller # I2C support device iicbus device iic device ti_i2c # Console and misc device uart device uart_ns8250 device pty device snp device md device random # Entropy device device pl310 # PL310 L2 cache controller # GPIO device gpio # The following enables MFS as root, this seems similar to an initramfs or initrd # as used in Linux. #options MD_ROOT #options MD_ROOT_SIZE=7560 # USB support device usb options USB_HOST_ALIGN=64 # Align usb buffers to cache line size. options USB_DEBUG #options USB_REQ_DEBUG #options USB_VERBOSE device ohci device ehci device umass device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) # Ethernet device loop device ether device mii device smc device smcphy device bpf # USB Ethernet support, requires miibus device miibus #device axe # ASIX Electronics USB Ethernet device smsc # SMSC LAN95xx USB Ethernet # OMAP-specific devices device ti_sdma device twl device twl_vreg device twl_clks # Flattened Device Tree -options FDT -options FDT_DTB_STATIC -makeoptions FDT_DTS_FILE=pandaboard.dts +options FDT # Configure using FDT/DTB data +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=pandaboard.dts Index: projects/sendfile/sys/arm/conf/RK3188 =================================================================== --- projects/sendfile/sys/arm/conf/RK3188 (revision 276056) +++ projects/sendfile/sys/arm/conf/RK3188 (revision 276057) @@ -1,128 +1,135 @@ +# # Kernel configuration for Rockchip RK3188 systems. # -# For more information on this file, please read the handbook section on -# Kernel Configuration Files: +# For more information on this file, please read the config(5) manual page, +# and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident RK3188 include "../rockchip/std.rk30xx" options HZ=100 options SCHED_4BSD # 4BSD scheduler +options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols +options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options TMPFS # Efficient memory filesystem +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS +options NFSCL # New Network Filesystem Client +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL options MSDOSFS # MSDOS Filesystem options CD9660 # ISO 9660 Filesystem options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables +options GEOM_PART_BSD # BSD partition scheme +options GEOM_PART_MBR # MBR partition scheme options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions options KBD_INSTALL_CDEV # install a CDEV entry in /dev -options PREEMPTION -options FREEBSD_BOOT_LOADER -options VFP # vfp/neon -options SMP # Enable multiple cores +options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) +options VFP # Enable floating point hardware support +options SMP # Enable multiple cores -# Debugging +# Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options BREAK_TO_DEBUGGER -#options VERBOSE_SYSINIT # Enable verbose sysinit messages -options KDB +#options VERBOSE_SYSINIT # Enable verbose sysinit messages +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: options DDB # Enable the kernel debugger -#options INVARIANTS # Enable calls of extra sanity checking -#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS +#options INVARIANTS # Enable calls of extra sanity checking +#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS options WITNESS # Enable checks to detect deadlocks and cycles options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed options DIAGNOSTIC -# NFS support -#options NFSCL -#options NFSSERVER # Network Filesystem Server -#options NFSCLIENT # Network Filesystem Client +# Boot device is 2nd slice on USB +options ROOTDEVNAME=\"ufs:/dev/da0s2\" -# MMC/SD/SDIO card slot support +# MMC/SD/SDIO Card slot support #device mmc # mmc/sd bus #device mmcsd # mmc/sd flash cards -# Boot device is 2nd slice on USB -options ROOTDEVNAME=\"ufs:/dev/da0s2\" - # Console and misc device uart device uart_ns8250 device pty device snp device md device random # Entropy device # I2C support #device iicbus #device iic # GPIO device gpio device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device pass # USB support options USB_HOST_ALIGN=32 # Align usb buffers to cache line size. device usb options USB_DEBUG -#options USB_REQ_DEBUG -#options USB_VERBOSE +#options USB_REQ_DEBUG +#options USB_VERBOSE device dwcotg # DWC OTG controller device umass # Ethernet device loop device ether device mii device bpf # Wireless NIC cards -options IEEE80211_DEBUG -options IEEE80211_AMPDU_AGE -options IEEE80211_SUPPORT_MESH -options IEEE80211_SUPPORT_TDMA +options IEEE80211_DEBUG +options IEEE80211_AMPDU_AGE +options IEEE80211_SUPPORT_MESH +options IEEE80211_SUPPORT_TDMA device wlan # 802.11 support device wlan_wep # 802.11 WEP support device wlan_ccmp # 802.11 CCMP support device wlan_tkip # 802.11 TKIP support device urtwn device urtwnfw device firmware # Used by the above -# USB ethernet support, requires miibus +# USB Ethernet support, requires miibus device miibus device udav -options FDT # Configure using FDT/DTB data. +# Flattened Device Tree +options FDT # Configure using FDT/DTB data Index: projects/sendfile/sys/arm/conf/RPI-B =================================================================== --- projects/sendfile/sys/arm/conf/RPI-B (revision 276056) +++ projects/sendfile/sys/arm/conf/RPI-B (revision 276057) @@ -1,123 +1,136 @@ +# # RPI-B -- Custom configuration for the Raspberry Pi # -# For more information on this file, please read the handbook section on -# Kernel Configuration Files: +# For more information on this file, please read the config(5) manual page, +# and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the -# device lines is also present in the ../../conf/NOTES and NOTES files. -# If you are in doubt as to the purpose or necessity of a line, check first +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident RPI-B include "../broadcom/bcm2835/std.rpi" -makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options HZ=100 - options SCHED_4BSD # 4BSD scheduler +options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options TMPFS # Efficient memory filesystem +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS +options NFSCL # New Network Filesystem Client +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL options MSDOSFS # MSDOS Filesystem -device snp - -options NFSCL # Network Filesystem Client - -#options NFS_ROOT # NFS usable as /, requires NFSCLIENT -#options BOOTP_NFSROOT -#options BOOTP_COMPAT -#options BOOTP -#options BOOTP_NFSV3 -#options BOOTP_WIRED_TO=ue0 - +options CD9660 # ISO 9660 Filesystem +options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables +options GEOM_PART_BSD # BSD partition scheme +options GEOM_PART_MBR # MBR partition scheme options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions options KBD_INSTALL_CDEV # install a CDEV entry in /dev -#options ROOTDEVNAME=\"ufs:mmcsd0s2\" - -options PREEMPTION options PLATFORM +options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) +options VFP # Enable floating point hardware support +# Debugging for use in -current +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols +options BREAK_TO_DEBUGGER +#options VERBOSE_SYSINIT # Enable verbose sysinit messages +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: +options DDB # Enable the kernel debugger +options INVARIANTS # Enable calls of extra sanity checking +options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS +#options WITNESS # Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed +#options DIAGNOSTIC + +# NFS root from boopt/dhcp +#options BOOTP +#options BOOTP_NFSROOT +#options BOOTP_COMPAT +#options BOOTP_NFSV3 +#options BOOTP_WIRED_TO=ue0 + +#options ROOTDEVNAME=\"ufs:mmcsd0s2\" + device bpf device loop device ether device uart +device pty +device snp device pl011 -device pty - # Comment following lines for boot console on serial port device vt device kbdmux device ukbd device sdhci device mmc device mmcsd device gpio device gpioled # I2C device iic device iicbus device bcm2835_bsc -options KDB -options DDB # Enable the kernel debugger -options INVARIANTS # Enable calls of extra sanity checking -options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS - device md device random # Entropy device # USB support device usb options USB_DEBUG device dwcotg # DWC OTG controller # USB storage support device scbus device da device umass # USB ethernet support device smcphy device mii device smsc # SPI device spibus device bcm2835_spi # Flattened Device Tree -options FDT +options FDT # Configure using FDT/DTB data # Note: DTB is normally loaded and modified by RPi boot loader, then # handed to kernel via U-Boot and ubldr. -#options FDT_DTB_STATIC -makeoptions FDT_DTS_FILE=rpi.dts - -options VFP # vfp/neon +#options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=rpi.dts Index: projects/sendfile/sys/arm/conf/SAM9260EK =================================================================== --- projects/sendfile/sys/arm/conf/SAM9260EK (revision 276056) +++ projects/sendfile/sys/arm/conf/SAM9260EK (revision 276057) @@ -1,184 +1,184 @@ # Kernel configuration for Atmel SAM9260-EK eval board # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ #NO_UNIVERSE ident SAM9260EK include "../at91/std.sam9260ek" # To statically compile in device wiring instead of /boot/device.hints hints "SAM9260EK.hints" #makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols makeoptions MODULES_OVERRIDE="" options SCHED_4BSD # 4BSD scheduler #options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking #options INET6 # IPv6 communications protocols #options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem options SOFTUPDATES # Enable FFS soft updates support #options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories #options UFS_GJOURNAL # Enable gjournal-based UFS journaling #options MD_ROOT # MD is a potential root device options NANDFS # NAND file system options NFSCL # New Network Filesystem Client #options NFSD # New Network Filesystem Server options NFSLOCKD # Network Lock Manager options NFS_ROOT # NFS usable as /, requires NFSCL options TMPFS # Efficient memory filesystem #options MSDOSFS # MSDOS Filesystem #options CD9660 # ISO 9660 Filesystem #options PROCFS # Process filesystem (requires PSEUDOFS) #options PSEUDOFS # Pseudo-filesystem framework options GEOM_PART_BSD # BSD partition scheme options GEOM_PART_MBR # MBR partition scheme #options GEOM_PART_GPT # GUID Partition Tables. #options GEOM_LABEL # Provides labelization #options COMPAT_FREEBSD5 # Compatible with FreeBSD5 #options COMPAT_FREEBSD6 # Compatible with FreeBSD6 #options COMPAT_FREEBSD7 # Compatible with FreeBSD7 options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI options KTRACE # ktrace(1) support #options STACK # stack(9) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed. #options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4) #options AUDIT # Security event auditing #options CAPABILITY_MODE # Capsicum capability mode #options CAPABILITIES # Capsicum capabilities #options MAC # TrustedBSD MAC Framework #options INCLUDE_CONFIG_FILE # Include this file in kernel # required for netbooting #options BOOTP #options BOOTP_COMPAT #options BOOTP_NFSROOT #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=ate0 # alternatively, boot from a MMC/SD memory card #options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\" # Alternatively, boot from a USB card. options ROOTDEVNAME=\"ufs:/dev/da0s1a\" # kernel/memory size reduction options MUTEX_NOINLINE options NO_FFS_SNAPSHOT options NO_SWAPPING options NO_SYSCTL_DESCR options RWLOCK_NOINLINE # Debugging support. Always need this: #options KDB # Enable kernel debugger support. # For minimum debugger support (stable branch) use: #options KDB_TRACE # Print a stack trace for a panic. # For full debugger support use this instead: #options DDB # Support DDB. #options GDB # Support remote GDB. #options DEADLKRES # Enable the deadlock resolver #options INVARIANTS # Enable calls of extra sanity checking #options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS #options WITNESS # Enable checks to detect deadlocks and cycles #options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones # The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! # Note that 'bpf' is required for DHCP. device bpf # Berkeley packet filter # Ethernet device mii # Minimal MII support device ate # Atmel AT91 Ethernet driver # I2C device at91_twi # Atmel AT91 Two-wire Interface device iic # I2C generic I/O device driver device iicbus # I2C bus system device icee # I2C eeprom # MMC/SD # See comment for DataFlash below device at91_mci # Atmel AT91 Multimedia Card Interface options AT91_MCI_HAS_4WIRE # 4 wires options AT91_MCI_SLOT_B # Wired to slot B device mmc # MMC/SD bus device mmcsd # MMC/SD memory card # DataFlash # The DataFlash and MMC card are wired together, so we must pick one or the # other. This is due to pin mux, and also due to the design of the # SAM9260EK board. SLOT A wouldn't have this issue. #device at91_spi # Atmel AT91 Serial Peripheral Interface #device spibus # SPI bus #device at45d # Atmel AT45D #device geom_map # GEOM partition mapping # Pseudo devices. device loop # Network loopback device random # Entropy device device ether # Ethernet support #device vlan # 802.1Q VLAN support #device tun # Packet tunnel. #device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling #device firmware # firmware assist module # SCSI peripherals device scbus # SCSI bus (required for ATA/SCSI) #device ch # SCSI media changers device da # Direct Access (disks) #device sa # Sequential Access (tape etc) device cd # CD/DVD device pass # Passthrough device (direct ATA/SCSI access) device ses # Enclosure Services (SES and SAF-TE) #device ctl # CAM Target Layer # Serial (COM) ports device uart # Multi-uart driver options ALT_BREAK_TO_DEBUGGER # USB support #options USB_DEBUG # enable debug msgs device ohci # OHCI USB interface device usb # USB Bus (required) device umass # Disks/Mass storage - Requires scbus and da # watchdog device at91_wdt # Atmel AT91 Watchdog Timer # NAND Flash - Reference design has Samsung 256MB but others possible device nand # NAND interface on CS3 # Coming soon, but not yet #options FDT #options FDT_DTB_STATIC #makeoptions FDT_DTS_FILE=sam9260ek.dts options EARLY_PRINTF -options SOCDEV_PA=0xfc000000 +options SOCDEV_PA=0xfc000000 options SOCDEV_VA=0xdc000000 Index: projects/sendfile/sys/arm/conf/SOCKIT =================================================================== --- projects/sendfile/sys/arm/conf/SOCKIT (revision 276056) +++ projects/sendfile/sys/arm/conf/SOCKIT (revision 276057) @@ -1,138 +1,141 @@ +# # Kernel configuration for Terasic SoCKit (Altera Cyclone V SoC). # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident SOCKIT include "../altera/socfpga/std.socfpga" makeoptions MODULES_OVERRIDE="" -makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols makeoptions WERROR="-Werror" options HZ=100 options SCHED_4BSD # 4BSD scheduler +options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options GEOM_PART_GPT # GUID partition tables -options TMPFS # Efficient memory filesystem +options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem -options SOFTUPDATES +options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS +options NFSCL # New Network Filesystem Client +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL options MSDOSFS # MSDOS Filesystem options CD9660 # ISO 9660 Filesystem options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables +options GEOM_PART_BSD # BSD partition scheme +options GEOM_PART_MBR # MBR partition scheme options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE +options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions -options KBD_INSTALL_CDEV -options PREEMPTION -options FREEBSD_BOOT_LOADER -options VFP # vfp/neon +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev +options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) +options VFP # Enable floating point hardware support +options SMP # Enable multiple cores -options SMP - -# Debugging +# Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options BREAK_TO_DEBUGGER #options VERBOSE_SYSINIT # Enable verbose sysinit messages -options KDB +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: options DDB # Enable the kernel debugger options INVARIANTS # Enable calls of extra sanity checking options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS #options WITNESS # Enable checks to detect deadlocks and cycles #options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options DIAGNOSTIC -# NFS support -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCLIENT - -# Uncomment this for NFS root -#options NFS_ROOT # NFS usable as /, requires NFSCL +# NFS root from boopt/dhcp +#options BOOTP #options BOOTP_NFSROOT #options BOOTP_COMPAT -#options BOOTP #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=ue0 +options ROOTDEVNAME=\"ufs:/dev/da0\" + +# MMC/SD/SDIO Card slot support device mmc # mmc/sd bus device mmcsd # mmc/sd flash cards device dwmmc -options ROOTDEVNAME=\"ufs:/dev/da0\" - # Pseudo devices device loop device random device pty device md device gpio # USB support options USB_HOST_ALIGN=64 # Align usb buffers to cache line size. device usb options USB_DEBUG #options USB_REQ_DEBUG #options USB_VERBOSE #device musb device dwcotg device umass device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device pass # Serial ports device uart device uart_ns8250 # I2C (TWSI) device iic device iicbus # SPI device spibus # Ethernet device ether device mii device smsc device smscphy device dwc device micphy # USB ethernet support, requires miibus device miibus device axe # ASIX Electronics USB Ethernet device bpf # Berkeley packet filter -#FDT -options FDT +# Flattened Device Tree +options FDT # Configure using FDT/DTB data options FDT_DTB_STATIC makeoptions FDT_DTS_FILE=socfpga-sockit.dts Index: projects/sendfile/sys/arm/conf/SOCKIT-BERI =================================================================== --- projects/sendfile/sys/arm/conf/SOCKIT-BERI (revision 276056) +++ projects/sendfile/sys/arm/conf/SOCKIT-BERI (revision 276057) @@ -1,145 +1,148 @@ +# # Kernel configuration for Terasic SoCKit (Altera Cyclone V SoC). # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident SOCKIT-BERI include "../altera/socfpga/std.socfpga" makeoptions MODULES_OVERRIDE="" -makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols makeoptions WERROR="-Werror" options HZ=100 options SCHED_4BSD # 4BSD scheduler +options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options GEOM_PART_GPT # GUID partition tables -options TMPFS # Efficient memory filesystem +options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem -options SOFTUPDATES +options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS +options NFSCL # New Network Filesystem Client +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL options MSDOSFS # MSDOS Filesystem options CD9660 # ISO 9660 Filesystem options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables +options GEOM_PART_BSD # BSD partition scheme +options GEOM_PART_MBR # MBR partition scheme options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE +options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions -options KBD_INSTALL_CDEV -options PREEMPTION -options FREEBSD_BOOT_LOADER -options VFP # vfp/neon +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev +options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) +options VFP # Enable floating point hardware support +options SMP # Enable multiple cores -options SMP - -# Debugging +# Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options BREAK_TO_DEBUGGER #options VERBOSE_SYSINIT # Enable verbose sysinit messages -options KDB +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: options DDB # Enable the kernel debugger options INVARIANTS # Enable calls of extra sanity checking options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS #options WITNESS # Enable checks to detect deadlocks and cycles #options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options DIAGNOSTIC -# NFS support -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCLIENT - -# Uncomment this for NFS root -#options NFS_ROOT # NFS usable as /, requires NFSCL +# NFS root from boopt/dhcp +#options BOOTP #options BOOTP_NFSROOT #options BOOTP_COMPAT -#options BOOTP #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=ue0 +options ROOTDEVNAME=\"ufs:/dev/mmcsd0s4\" + +# MMC/SD/SDIO Card slot support device mmc # mmc/sd bus device mmcsd # mmc/sd flash cards device dwmmc -options ROOTDEVNAME=\"ufs:/dev/mmcsd0s4\" - # Pseudo devices device loop device random device pty device md device gpio # USB support options USB_HOST_ALIGN=64 # Align usb buffers to cache line size. device usb options USB_DEBUG #options USB_REQ_DEBUG #options USB_VERBOSE #device musb device dwcotg device umass device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device pass # Serial ports device uart device uart_ns8250 # I2C (TWSI) device iic device iicbus # SPI device spibus # BERI specific device beri_ring device beri_mem device beri_vtblk device vtbe device altera_pio # Ethernet device ether device mii device smsc device smscphy device dwc device micphy # USB ethernet support, requires miibus device miibus device axe # ASIX Electronics USB Ethernet device bpf # Berkeley packet filter -#FDT -options FDT +# Flattened Device Tree +options FDT # Configure using FDT/DTB data options FDT_DTB_STATIC makeoptions FDT_DTS_FILE=socfpga-sockit-beri.dts Index: projects/sendfile/sys/arm/conf/VERSATILEPB =================================================================== --- projects/sendfile/sys/arm/conf/VERSATILEPB (revision 276056) +++ projects/sendfile/sys/arm/conf/VERSATILEPB (revision 276057) @@ -1,104 +1,118 @@ +# # VERSATILEPB - Configuration for QEMU version of Versatile Platform Board # -# For more information on this file, please read the handbook section on -# Kernel Configuration Files: +# For more information on this file, please read the config(5) manual page, +# and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the -# device lines is also present in the ../../conf/NOTES and NOTES files. -# If you are in doubt as to the purpose or necessity of a line, check first +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident VERSATILEPB machine arm armv6 cpu CPU_ARM1176 files "../versatile/files.versatile" makeoptions MODULES_OVERRIDE="" options KERNVIRTADDR=0xc0100000 makeoptions KERNVIRTADDR=0xc0100000 options KERNPHYSADDR=0x00100000 makeoptions KERNPHYSADDR=0x00100000 options PHYSADDR=0x00000000 -options FREEBSD_BOOT_LOADER -options LINUX_BOOT_ABI -makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options HZ=100 - options SCHED_4BSD # 4BSD scheduler +options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking +options INET6 # IPv6 communications protocols +options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories -device snp - +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS +options NFSCL # New Network Filesystem Client +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL +options MSDOSFS # MSDOS Filesystem +options CD9660 # ISO 9660 Filesystem +options PROCFS # Process filesystem (requires PSEUDOFS) +options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables options GEOM_PART_BSD # BSD partition scheme options GEOM_PART_MBR # MBR partition scheme -options TMPFS # Efficient memory filesystem -options PSEUDOFS # Pseudo-filesystem framework options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions options KBD_INSTALL_CDEV # install a CDEV entry in /dev -options ROOTDEVNAME=\"ufs:da0s1a\" -options VFP # vfp/neon +options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) +options LINUX_BOOT_ABI # Process metadata passed from Linux boot loaders +options VFP # Enable floating point hardware support -options PREEMPTION +# Debugging for use in -current +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: +options DDB # Enable the kernel debugger +options INVARIANTS # Enable calls of extra sanity checking +options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS +options ROOTDEVNAME=\"ufs:da0s1a\" + device bpf device loop device mii device mii_bitbang device smc device smcphy device ether device uart device pl011 device pl190 device pty +device snp device pci # SCSI Controllers device sym # NCR/Symbios/LSI Logic 53C8XX/53C1010/53C1510D # ATA/SCSI peripherals device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device pass # Passthrough device (direct ATA/SCSI access) # NOTE: serial console is disabled if syscons enabled # Comment following lines for headless setup device sc device kbdmux -options SC_DFLT_FONT # compile font in -makeoptions SC_DFLT_FONT=cp437 +options SC_DFLT_FONT # compile font in +makeoptions SC_DFLT_FONT=cp437 -options KDB -options DDB # Enable the kernel debugger -options INVARIANTS # Enable calls of extra sanity checking -options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS - device md device random # Entropy device # Flattened Device Tree -options FDT -options FDT_DTB_STATIC -makeoptions FDT_DTS_FILE=versatilepb.dts +options FDT # Configure using FDT/DTB data +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=versatilepb.dts Index: projects/sendfile/sys/arm/conf/VYBRID =================================================================== --- projects/sendfile/sys/arm/conf/VYBRID (revision 276056) +++ projects/sendfile/sys/arm/conf/VYBRID (revision 276057) @@ -1,153 +1,159 @@ +# # Kernel configuration for Vybrid Family boards. # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident VYBRID include "../freescale/vybrid/std.vybrid" makeoptions MODULES_OVERRIDE="" makeoptions WITHOUT_MODULES="ahc" -makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols makeoptions WERROR="-Werror" options HZ=100 options SCHED_4BSD # 4BSD scheduler +options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols +options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem -options SOFTUPDATES +options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options TMPFS # Efficient memory filesystem +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS +options NFSCL # New Network Filesystem Client +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL options MSDOSFS # MSDOS Filesystem options CD9660 # ISO 9660 Filesystem +#options NANDFS # NAND Filesystem options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework -#options NANDFS # NAND Filesystem +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables +options GEOM_PART_BSD # BSD partition scheme +options GEOM_PART_MBR # MBR partition scheme options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI -options KTRACE +options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions -options KBD_INSTALL_CDEV -options PREEMPTION -options FREEBSD_BOOT_LOADER -options MUTEX_NOINLINE -options RWLOCK_NOINLINE -options NO_FFS_SNAPSHOT -options NO_SWAPPING -options VFP # vfp/neon +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev +options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) +options VFP # Enable floating point hardware support +#options SMP # Enable multiple cores -# Debugging +# Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options BREAK_TO_DEBUGGER -#options VERBOSE_SYSINIT # Enable verbose sysinit messages -options KDB +#options VERBOSE_SYSINIT # Enable verbose sysinit messages +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: options DDB # Enable the kernel debugger -#options INVARIANTS # Enable calls of extra sanity checking -#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS -#options WITNESS # Enable checks to detect deadlocks and cycles -#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed -#options DIAGNOSTIC +#options INVARIANTS # Enable calls of extra sanity checking +#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS +#options WITNESS # Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed +#options DIAGNOSTIC -# NFS support -options NFSCL # Network Filesystem Client -options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCLIENT +# NFS root from boopt/dhcp +#options BOOTP +#options BOOTP_NFSROOT +#options BOOTP_COMPAT +#options BOOTP_NFSV3 +#options BOOTP_WIRED_TO=ffec0 -# Uncomment this for NFS root -#options NFS_ROOT # NFS usable as /, requires NFSCL -#options BOOTP_NFSROOT -#options BOOTP_COMPAT -#options BOOTP -#options BOOTP_NFSV3 -#options BOOTP_WIRED_TO=ffec0 - -device mmc # mmc/sd bus -device mmcsd # mmc/sd flash cards -device sdhci # generic sdhci - #options ROOTDEVNAME=\"nfs:10.5.0.1:/tftpboot/cosmic\" #options ROOTDEVNAME=\"nandfs:/dev/gnand0s.root\" options ROOTDEVNAME=\"ufs:/dev/da0\" -#options SMP +options MUTEX_NOINLINE +options RWLOCK_NOINLINE +options NO_FFS_SNAPSHOT +options NO_SWAPPING +# MMC/SD/SDIO Card slot support +device mmc # mmc/sd bus +device mmcsd # mmc/sd flash cards +device sdhci # generic sdhci + # Pseudo devices device loop device random device pty device md device gpio # USB support options USB_HOST_ALIGN=32 # Align usb buffers to cache line size. device usb options USB_DEBUG -#options USB_REQ_DEBUG -#options USB_VERBOSE +#options USB_REQ_DEBUG +#options USB_VERBOSE #device musb device ehci #device ohci device umass device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device pass # SATA #device ata #device atadisk #device mvs device nand # Serial ports device uart # I2C (TWSI) device iic device iicbus # Ethernet device ether device ffec # USB ethernet support, requires miibus device miibus device axe # ASIX Electronics USB Ethernet device bpf # Berkeley packet filter device sound # SPI device spibus device vf_spi # Framebuffer device vt device kbdmux device ukbd -options FDT +# Flattened Device Tree +options FDT # Configure using FDT/DTB data Index: projects/sendfile/sys/arm/conf/WANDBOARD-DUAL =================================================================== --- projects/sendfile/sys/arm/conf/WANDBOARD-DUAL (revision 276056) +++ projects/sendfile/sys/arm/conf/WANDBOARD-DUAL (revision 276057) @@ -1,28 +1,28 @@ # Kernel configuration for Wandboard-Dual # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ #NO_UNIVERSE include "IMX6" ident WANDBOARD-DUAL # Flattened Device Tree -options FDT_DTB_STATIC -makeoptions FDT_DTS_FILE=wandboard-dual.dts +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=wandboard-dual.dts Index: projects/sendfile/sys/arm/conf/WANDBOARD-QUAD =================================================================== --- projects/sendfile/sys/arm/conf/WANDBOARD-QUAD (revision 276056) +++ projects/sendfile/sys/arm/conf/WANDBOARD-QUAD (revision 276057) @@ -1,28 +1,28 @@ # Kernel configuration for Wandboard-Quad # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ #NO_UNIVERSE include "IMX6" ident WANDBOARD-QUAD # Flattened Device Tree -options FDT_DTB_STATIC -makeoptions FDT_DTS_FILE=wandboard-quad.dts +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=wandboard-quad.dts Index: projects/sendfile/sys/arm/conf/WANDBOARD-SOLO =================================================================== --- projects/sendfile/sys/arm/conf/WANDBOARD-SOLO (revision 276056) +++ projects/sendfile/sys/arm/conf/WANDBOARD-SOLO (revision 276057) @@ -1,28 +1,28 @@ # Kernel configuration for Wandboard-Solo # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ #NO_UNIVERSE include "IMX6" ident WANDBOARD-SOLO # Flattened Device Tree -options FDT_DTB_STATIC -makeoptions FDT_DTS_FILE=wandboard-solo.dts +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=wandboard-solo.dts Index: projects/sendfile/sys/arm/conf/ZEDBOARD =================================================================== --- projects/sendfile/sys/arm/conf/ZEDBOARD (revision 276056) +++ projects/sendfile/sys/arm/conf/ZEDBOARD (revision 276057) @@ -1,104 +1,117 @@ +# # ZEDBOARD -- Custom configuration for the Xilinx Zynq-7000 based # ZedBoard (www.zedboard.org) -# -# For more information on this file, please read the handbook section on -# Kernel Configuration Files: -# +# +# For more information on this file, please read the config(5) manual page, +# and/or the handbook section on Kernel Configuration Files: +# # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html -# +# # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. -# +# # An exhaustive list of options and more detailed explanations of the -# device lines is also present in the ../../conf/NOTES and NOTES files. -# If you are in doubt as to the purpose or necessity of a line, check first +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. -# +# # $FreeBSD$ ident ZEDBOARD -include "../xilinx/zedboard/std.zedboard" +include "../xilinx/zedboard/std.zedboard" makeoptions MODULES_OVERRIDE="" makeoptions WITHOUT_MODULES="ahc" options SCHED_4BSD # 4BSD scheduler +options PREEMPTION # Enable kernel thread preemption options INET # InterNETworking options INET6 # IPv6 communications protocols +options SCTP # Stream Control Transmission Protocol options FFS # Berkeley Fast Filesystem options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories -# options ROOTDEVNAME=\"ufs:mmcsd0s2a\" - -options NFSCL # Network Filesystem Client -# options NFSSD # Network Filesystem Server -# options NFSLOCKD # Network Lock Manager -# options NFS_ROOT # NFS usable as /, requires NFSCL -# options BOOTP_NFSROOT -# options BOOTP - -options GEOM_PART_BSD # BSD partition scheme -options GEOM_PART_MBR # MBR partition scheme -options TMPFS # Efficient memory filesystem +options UFS_GJOURNAL # Enable gjournal-based UFS journaling +options QUOTA # Enable disk quotas for UFS +options NFSCL # New Network Filesystem Client +#options NFSSD # Network Filesystem Server +options NFSLOCKD # Network Lock Manager +options NFS_ROOT # NFS usable as /, requires NFSCL options MSDOSFS # MSDOS Filesystem options CD9660 # ISO 9660 Filesystem options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework +options TMPFS # Efficient memory filesystem +options GEOM_PART_GPT # GUID Partition Tables +options GEOM_PART_BSD # BSD partition scheme +options GEOM_PART_MBR # MBR partition scheme options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI options KTRACE # ktrace(1) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores -options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions -options FREEBSD_BOOT_LOADER -options VFP # vfp/neon -options SMP # Symmetric MultiProcessor Kernel +options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev +options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) +options VFP # Enable floating point hardware support +options SMP # Enable multiple cores -# Debugging +# Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols -options DDB -options KDB -# options BREAK_TO_DEBUGGER +#options BREAK_TO_DEBUGGER +options KDB # Enable kernel debugger support +# For minimum debugger support (stable branch) use: +#options KDB_TRACE # Print a stack trace for a panic +# For full debugger support use this instead: +options DDB # Enable the kernel debugger +#options INVARIANTS # Enable calls of extra sanity checking +#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS +#options WITNESS # Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed +#options DIAGNOSTIC -# options INVARIANTS # Enable calls of extra sanity checking -# options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS -# options WITNESS # Enable checks to detect deadlocks and cycles -# options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed +# NFS root from boopt/dhcp +#options BOOTP +#options BOOTP_NFSROOT +#options BOOTP_COMPAT +#options BOOTP_NFSV3 +options ROOTDEVNAME=\"ufs:mmcsd0s2a\" + device loop device random device ether device cgem # Zynq-7000 gig ethernet device device mii device e1000phy device pty device uart device gpio device md device mmc # mmc/sd bus device mmcsd # mmc/sd flash cards device sdhci # generic sdhci device bpf # Berkeley packet filter # USB support device usb options USB_DEBUG #options USB_REQ_DEBUG #options USB_VERBOSE device ehci device umass device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device axe # USB-Ethernet # Flattened Device Tree -options FDT -# options FDT_DTB_STATIC -# makeoptions FDT_DTS_FILE=zedboard.dts +options FDT # Configure using FDT/DTB data +#options FDT_DTB_STATIC +#makeoptions FDT_DTS_FILE=zedboard.dts Index: projects/sendfile/sys/arm/freescale/imx/std.imx51 =================================================================== --- projects/sendfile/sys/arm/freescale/imx/std.imx51 (revision 276056) +++ projects/sendfile/sys/arm/freescale/imx/std.imx51 (revision 276057) @@ -1,16 +1,17 @@ # $FreeBSD$ machine arm armv6 cpu CPU_CORTEXA +makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a" makeoptions ARM_LITTLE_ENDIAN options ARM_L2_PIPT options KERNVIRTADDR=0xc0100000 makeoptions KERNVIRTADDR=0xc0100000 options KERNPHYSADDR=0x90100000 makeoptions KERNPHYSADDR=0x90100000 options PHYSADDR=0x90000000 device fdt_pinctrl files "../freescale/imx/files.imx51" Index: projects/sendfile/sys/arm/freescale/imx/std.imx53 =================================================================== --- projects/sendfile/sys/arm/freescale/imx/std.imx53 (revision 276056) +++ projects/sendfile/sys/arm/freescale/imx/std.imx53 (revision 276057) @@ -1,16 +1,17 @@ # $FreeBSD$ machine arm armv6 cpu CPU_CORTEXA +makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a" makeoptions ARM_LITTLE_ENDIAN options ARM_L2_PIPT options KERNVIRTADDR=0xc0100000 makeoptions KERNVIRTADDR=0xc0100000 options KERNPHYSADDR=0x70100000 makeoptions KERNPHYSADDR=0x70100000 options PHYSADDR=0x70000000 device fdt_pinctrl files "../freescale/imx/files.imx53" Index: projects/sendfile/sys/arm/freescale/imx/std.imx6 =================================================================== --- projects/sendfile/sys/arm/freescale/imx/std.imx6 (revision 276056) +++ projects/sendfile/sys/arm/freescale/imx/std.imx6 (revision 276057) @@ -1,19 +1,20 @@ # $FreeBSD$ machine arm armv6 cpu CPU_CORTEXA +makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a" makeoptions ARM_LITTLE_ENDIAN options ARM_L2_PIPT options KERNVIRTADDR = 0xc2000000 makeoptions KERNVIRTADDR = 0xc2000000 options KERNPHYSADDR = 0x12000000 makeoptions KERNPHYSADDR = 0x12000000 options PHYSADDR = 0x10000000 options IPI_IRQ_START=0 options IPI_IRQ_END=15 device fdt_pinctrl files "../freescale/imx/files.imx6" Index: projects/sendfile/sys/arm/freescale/vybrid/std.vybrid =================================================================== --- projects/sendfile/sys/arm/freescale/vybrid/std.vybrid (revision 276056) +++ projects/sendfile/sys/arm/freescale/vybrid/std.vybrid (revision 276057) @@ -1,18 +1,19 @@ # $FreeBSD$ makeoption ARM_LITTLE_ENDIAN cpu CPU_CORTEXA machine arm armv6 +makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a" options PHYSADDR=0x80000000 makeoptions KERNPHYSADDR=0x80100000 options KERNPHYSADDR=0x80100000 makeoptions KERNVIRTADDR=0xc0100000 options KERNVIRTADDR=0xc0100000 options ARM_L2_PIPT files "../freescale/vybrid/files.vybrid" Index: projects/sendfile/sys/arm/include/intr.h =================================================================== --- projects/sendfile/sys/arm/include/intr.h (revision 276056) +++ projects/sendfile/sys/arm/include/intr.h (revision 276057) @@ -1,88 +1,96 @@ /* $NetBSD: intr.h,v 1.7 2003/06/16 20:01:00 thorpej Exp $ */ /*- * Copyright (c) 1997 Mark Brinicombe. * 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 Mark Brinicombe * for the NetBSD Project. * 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 THE AUTHOR ``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_INTR_H_ #define _MACHINE_INTR_H_ +#ifdef FDT +#include +#endif + /* XXX move to std.* files? */ #ifdef CPU_XSCALE_81342 #define NIRQ 128 #elif defined(CPU_XSCALE_PXA2X0) #include #define NIRQ IRQ_GPIO_MAX #elif defined(SOC_MV_DISCOVERY) #define NIRQ 96 #elif defined(CPU_ARM9) || defined(SOC_MV_KIRKWOOD) || \ defined(CPU_XSCALE_IXP435) #define NIRQ 64 #elif defined(CPU_CORTEXA) #define NIRQ 1020 #elif defined(CPU_KRAIT) #define NIRQ 288 #elif defined(CPU_ARM1136) || defined(CPU_ARM1176) #define NIRQ 128 #elif defined(SOC_MV_ARMADAXP) #define MAIN_IRQ_NUM 116 #define ERR_IRQ_NUM 32 #define ERR_IRQ (MAIN_IRQ_NUM) #define MSI_IRQ_NUM 32 #define MSI_IRQ (ERR_IRQ + ERR_IRQ_NUM) #define NIRQ (MAIN_IRQ_NUM + ERR_IRQ_NUM + MSI_IRQ_NUM) #else #define NIRQ 32 #endif int arm_get_next_irq(int); void arm_mask_irq(uintptr_t); void arm_unmask_irq(uintptr_t); void arm_intrnames_init(void); void arm_setup_irqhandler(const char *, int (*)(void*), void (*)(void*), void *, int, int, void **); int arm_remove_irqhandler(int, void *); extern void (*arm_post_filter)(void *); extern int (*arm_config_irq)(int irq, enum intr_trigger trig, enum intr_polarity pol); void arm_irq_memory_barrier(uintptr_t); void gic_init_secondary(void); int gic_decode_fdt(uint32_t iparentnode, uint32_t *intrcells, int *interrupt, int *trig, int *pol); + +#ifdef FDT +int arm_fdt_map_irq(phandle_t, pcell_t *, int); +#endif #endif /* _MACHINE_INTR_H */ Index: projects/sendfile/sys/arm/lpc/lpc_intc.c =================================================================== --- projects/sendfile/sys/arm/lpc/lpc_intc.c (revision 276056) +++ projects/sendfile/sys/arm/lpc/lpc_intc.c (revision 276057) @@ -1,246 +1,250 @@ /*- * Copyright (c) 2010 Jakub Wojciech Klama * 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. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct lpc_intc_softc { struct resource * li_res; bus_space_tag_t li_bst; bus_space_handle_t li_bsh; }; static int lpc_intc_probe(device_t); static int lpc_intc_attach(device_t); static void lpc_intc_eoi(void *); static struct lpc_intc_softc *intc_softc = NULL; -#define intc_read_4(reg) \ - bus_space_read_4(intc_softc->li_bst, intc_softc->li_bsh, reg) -#define intc_write_4(reg, val) \ - bus_space_write_4(intc_softc->li_bst, intc_softc->li_bsh, reg, val) +#define intc_read_4(_sc, _reg) \ + bus_space_read_4((_sc)->li_bst, (_sc)->li_bsh, (_reg)) +#define intc_write_4(_sc, _reg, _val) \ + bus_space_write_4((_sc)->li_bst, (_sc)->li_bsh, (_reg), (_val)) static int lpc_intc_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (!ofw_bus_is_compatible(dev, "lpc,pic")) return (ENXIO); device_set_desc(dev, "LPC32x0 Interrupt Controller"); return (BUS_PROBE_DEFAULT); } static int lpc_intc_attach(device_t dev) { struct lpc_intc_softc *sc = device_get_softc(dev); int rid = 0; if (intc_softc) return (ENXIO); sc->li_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->li_res) { device_printf(dev, "could not alloc resources\n"); return (ENXIO); } sc->li_bst = rman_get_bustag(sc->li_res); sc->li_bsh = rman_get_bushandle(sc->li_res); intc_softc = sc; arm_post_filter = lpc_intc_eoi; /* Clear interrupt status registers and disable all interrupts */ - intc_write_4(LPC_INTC_MIC_ER, 0); - intc_write_4(LPC_INTC_SIC1_ER, 0); - intc_write_4(LPC_INTC_SIC2_ER, 0); - intc_write_4(LPC_INTC_MIC_RSR, ~0); - intc_write_4(LPC_INTC_SIC1_RSR, ~0); - intc_write_4(LPC_INTC_SIC2_RSR, ~0); + intc_write_4(sc, LPC_INTC_MIC_ER, 0); + intc_write_4(sc, LPC_INTC_SIC1_ER, 0); + intc_write_4(sc, LPC_INTC_SIC2_ER, 0); + intc_write_4(sc, LPC_INTC_MIC_RSR, ~0); + intc_write_4(sc, LPC_INTC_SIC1_RSR, ~0); + intc_write_4(sc, LPC_INTC_SIC2_RSR, ~0); return (0); } static device_method_t lpc_intc_methods[] = { DEVMETHOD(device_probe, lpc_intc_probe), DEVMETHOD(device_attach, lpc_intc_attach), { 0, 0 } }; static driver_t lpc_intc_driver = { "pic", lpc_intc_methods, sizeof(struct lpc_intc_softc), }; static devclass_t lpc_intc_devclass; DRIVER_MODULE(pic, simplebus, lpc_intc_driver, lpc_intc_devclass, 0, 0); int arm_get_next_irq(int last) { + struct lpc_intc_softc *sc = intc_softc; uint32_t value; int i; /* IRQs 0-31 are mapped to LPC_INTC_MIC_SR */ - value = intc_read_4(LPC_INTC_MIC_SR); + value = intc_read_4(sc, LPC_INTC_MIC_SR); for (i = 0; i < 32; i++) { if (value & (1 << i)) return (i); } /* IRQs 32-63 are mapped to LPC_INTC_SIC1_SR */ - value = intc_read_4(LPC_INTC_SIC1_SR); + value = intc_read_4(sc, LPC_INTC_SIC1_SR); for (i = 0; i < 32; i++) { if (value & (1 << i)) return (i + 32); } /* IRQs 64-95 are mapped to LPC_INTC_SIC2_SR */ - value = intc_read_4(LPC_INTC_SIC2_SR); + value = intc_read_4(sc, LPC_INTC_SIC2_SR); for (i = 0; i < 32; i++) { if (value & (1 << i)) return (i + 64); } return (-1); } void arm_mask_irq(uintptr_t nb) { + struct lpc_intc_softc *sc = intc_softc; int reg; uint32_t value; /* Make sure that interrupt isn't active already */ lpc_intc_eoi((void *)nb); if (nb > 63) { nb -= 64; reg = LPC_INTC_SIC2_ER; } else if (nb > 31) { nb -= 32; reg = LPC_INTC_SIC1_ER; } else reg = LPC_INTC_MIC_ER; /* Clear bit in ER register */ - value = intc_read_4(reg); + value = intc_read_4(sc, reg); value &= ~(1 << nb); - intc_write_4(reg, value); + intc_write_4(sc, reg, value); } void arm_unmask_irq(uintptr_t nb) { + struct lpc_intc_softc *sc = intc_softc; int reg; uint32_t value; if (nb > 63) { nb -= 64; reg = LPC_INTC_SIC2_ER; } else if (nb > 31) { nb -= 32; reg = LPC_INTC_SIC1_ER; } else reg = LPC_INTC_MIC_ER; /* Set bit in ER register */ - value = intc_read_4(reg); + value = intc_read_4(sc, reg); value |= (1 << nb); - intc_write_4(reg, value); + intc_write_4(sc, reg, value); } static void lpc_intc_eoi(void *data) { + struct lpc_intc_softc *sc = intc_softc; int reg; int nb = (int)data; uint32_t value; if (nb > 63) { nb -= 64; reg = LPC_INTC_SIC2_RSR; } else if (nb > 31) { nb -= 32; reg = LPC_INTC_SIC1_RSR; } else reg = LPC_INTC_MIC_RSR; /* Set bit in RSR register */ - value = intc_read_4(reg); + value = intc_read_4(sc, reg); value |= (1 << nb); - intc_write_4(reg, value); + intc_write_4(sc, reg, value); } struct fdt_fixup_entry fdt_fixup_table[] = { { NULL, NULL } }; static int fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) { if (!fdt_is_compatible(node, "lpc,pic")) return (ENXIO); *interrupt = fdt32_to_cpu(intr[0]); *trig = INTR_TRIGGER_CONFORM; *pol = INTR_POLARITY_CONFORM; return (0); } fdt_pic_decode_t fdt_pic_table[] = { &fdt_pic_decode_ic, NULL }; Index: projects/sendfile/sys/arm/mv/std-pj4b.mv =================================================================== --- projects/sendfile/sys/arm/mv/std-pj4b.mv (revision 276056) +++ projects/sendfile/sys/arm/mv/std-pj4b.mv (revision 276057) @@ -1,7 +1,8 @@ # $FreeBSD$ files "../mv/files.mv" cpu CPU_MV_PJ4B machine arm armv6 +makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a" options VM_MAXUSER_ADDRESS="(KERNBASE-(1024*1024*1024))" Index: projects/sendfile/sys/arm/rockchip/std.rk30xx =================================================================== --- projects/sendfile/sys/arm/rockchip/std.rk30xx (revision 276056) +++ projects/sendfile/sys/arm/rockchip/std.rk30xx (revision 276057) @@ -1,25 +1,26 @@ # Rockchip rk30xx common options #$FreeBSD$ cpu CPU_CORTEXA machine arm armv6 +makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a" makeoption ARM_LITTLE_ENDIAN # Physical memory starts at 0x60400000. We assume images are loaded at # 0x60400000. # # options PHYSADDR=0x60000000 makeoptions KERNPHYSADDR=0x60400000 options KERNPHYSADDR=0x60400000 makeoptions KERNVIRTADDR=0xc0400000 options KERNVIRTADDR=0xc0400000 options ARM_L2_PIPT options IPI_IRQ_START=0 options IPI_IRQ_END=15 files "../rockchip/files.rk30xx" Index: projects/sendfile/sys/arm/samsung/exynos/std.exynos5250 =================================================================== --- projects/sendfile/sys/arm/samsung/exynos/std.exynos5250 (revision 276056) +++ projects/sendfile/sys/arm/samsung/exynos/std.exynos5250 (revision 276057) @@ -1,21 +1,22 @@ # $FreeBSD$ makeoption ARM_LITTLE_ENDIAN cpu CPU_CORTEXA machine arm armv6 +makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a" options PHYSADDR=0x40000000 makeoptions KERNPHYSADDR=0x40f00000 options KERNPHYSADDR=0x40f00000 makeoptions KERNVIRTADDR=0xc0f00000 options KERNVIRTADDR=0xc0f00000 options ARM_L2_PIPT options IPI_IRQ_START=0 options IPI_IRQ_END=15 files "../samsung/exynos/files.exynos5" Index: projects/sendfile/sys/arm/samsung/exynos/std.exynos5420 =================================================================== --- projects/sendfile/sys/arm/samsung/exynos/std.exynos5420 (revision 276056) +++ projects/sendfile/sys/arm/samsung/exynos/std.exynos5420 (revision 276057) @@ -1,21 +1,22 @@ # $FreeBSD$ makeoption ARM_LITTLE_ENDIAN cpu CPU_CORTEXA machine arm armv6 +makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a" options PHYSADDR=0x20000000 makeoptions KERNPHYSADDR=0x20f00000 options KERNPHYSADDR=0x20f00000 makeoptions KERNVIRTADDR=0xc0f00000 options KERNVIRTADDR=0xc0f00000 options ARM_L2_PIPT options IPI_IRQ_START=0 options IPI_IRQ_END=15 files "../samsung/exynos/files.exynos5" Index: projects/sendfile/sys/arm/ti/aintc.c =================================================================== --- projects/sendfile/sys/arm/ti/aintc.c (revision 276056) +++ projects/sendfile/sys/arm/ti/aintc.c (revision 276057) @@ -1,186 +1,190 @@ /*- * Copyright (c) 2012 Damjan Marion * All rights reserved. * * Based on OMAP3 INTC code by Ben Gray * * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #define INTC_REVISION 0x00 #define INTC_SYSCONFIG 0x10 #define INTC_SYSSTATUS 0x14 #define INTC_SIR_IRQ 0x40 #define INTC_CONTROL 0x48 #define INTC_THRESHOLD 0x68 #define INTC_MIR_CLEAR(x) (0x88 + ((x) * 0x20)) #define INTC_MIR_SET(x) (0x8C + ((x) * 0x20)) #define INTC_ISR_SET(x) (0x90 + ((x) * 0x20)) #define INTC_ISR_CLEAR(x) (0x94 + ((x) * 0x20)) struct ti_aintc_softc { device_t sc_dev; struct resource * aintc_res[3]; bus_space_tag_t aintc_bst; bus_space_handle_t aintc_bsh; uint8_t ver; }; static struct resource_spec ti_aintc_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, { -1, 0 } }; static struct ti_aintc_softc *ti_aintc_sc = NULL; -#define aintc_read_4(reg) \ - bus_space_read_4(ti_aintc_sc->aintc_bst, ti_aintc_sc->aintc_bsh, reg) -#define aintc_write_4(reg, val) \ - bus_space_write_4(ti_aintc_sc->aintc_bst, ti_aintc_sc->aintc_bsh, reg, val) +#define aintc_read_4(_sc, reg) \ + bus_space_read_4((_sc)->aintc_bst, (_sc)->aintc_bsh, (reg)) +#define aintc_write_4(_sc, reg, val) \ + bus_space_write_4((_sc)->aintc_bst, (_sc)->aintc_bsh, (reg), (val)) static int ti_aintc_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (!ofw_bus_is_compatible(dev, "ti,aintc")) return (ENXIO); device_set_desc(dev, "TI AINTC Interrupt Controller"); return (BUS_PROBE_DEFAULT); } static int ti_aintc_attach(device_t dev) { struct ti_aintc_softc *sc = device_get_softc(dev); uint32_t x; sc->sc_dev = dev; if (ti_aintc_sc) return (ENXIO); if (bus_alloc_resources(dev, ti_aintc_spec, sc->aintc_res)) { device_printf(dev, "could not allocate resources\n"); return (ENXIO); } sc->aintc_bst = rman_get_bustag(sc->aintc_res[0]); sc->aintc_bsh = rman_get_bushandle(sc->aintc_res[0]); ti_aintc_sc = sc; - x = aintc_read_4(INTC_REVISION); + x = aintc_read_4(sc, INTC_REVISION); device_printf(dev, "Revision %u.%u\n",(x >> 4) & 0xF, x & 0xF); /* SoftReset */ - aintc_write_4(INTC_SYSCONFIG, 2); + aintc_write_4(sc, INTC_SYSCONFIG, 2); /* Wait for reset to complete */ - while(!(aintc_read_4(INTC_SYSSTATUS) & 1)); + while(!(aintc_read_4(sc, INTC_SYSSTATUS) & 1)); /*Set Priority Threshold */ - aintc_write_4(INTC_THRESHOLD, 0xFF); + aintc_write_4(sc, INTC_THRESHOLD, 0xFF); return (0); } static device_method_t ti_aintc_methods[] = { DEVMETHOD(device_probe, ti_aintc_probe), DEVMETHOD(device_attach, ti_aintc_attach), { 0, 0 } }; static driver_t ti_aintc_driver = { "aintc", ti_aintc_methods, sizeof(struct ti_aintc_softc), }; static devclass_t ti_aintc_devclass; DRIVER_MODULE(aintc, simplebus, ti_aintc_driver, ti_aintc_devclass, 0, 0); int arm_get_next_irq(int last_irq) { + struct ti_aintc_softc *sc = ti_aintc_sc; uint32_t active_irq; if (last_irq != -1) { - aintc_write_4(INTC_ISR_CLEAR(last_irq >> 5), + aintc_write_4(sc, INTC_ISR_CLEAR(last_irq >> 5), 1UL << (last_irq & 0x1F)); - aintc_write_4(INTC_CONTROL,1); + aintc_write_4(sc, INTC_CONTROL, 1); } /* Get the next active interrupt */ - active_irq = aintc_read_4(INTC_SIR_IRQ); + active_irq = aintc_read_4(sc, INTC_SIR_IRQ); /* Check for spurious interrupt */ if ((active_irq & 0xffffff80)) { - device_printf(ti_aintc_sc->sc_dev, - "Spurious interrupt detected (0x%08x)\n", active_irq); - aintc_write_4(INTC_SIR_IRQ, 0); + device_printf(sc->sc_dev, + "Spurious interrupt detected (0x%08x)\n", active_irq); + aintc_write_4(sc, INTC_SIR_IRQ, 0); return -1; } if (active_irq != last_irq) return active_irq; else return -1; } void arm_mask_irq(uintptr_t nb) { - aintc_write_4(INTC_MIR_SET(nb >> 5), (1UL << (nb & 0x1F))); + struct ti_aintc_softc *sc = ti_aintc_sc; + + aintc_write_4(sc, INTC_MIR_SET(nb >> 5), (1UL << (nb & 0x1F))); } void arm_unmask_irq(uintptr_t nb) { + struct ti_aintc_softc *sc = ti_aintc_sc; arm_irq_memory_barrier(nb); - aintc_write_4(INTC_MIR_CLEAR(nb >> 5), (1UL << (nb & 0x1F))); + aintc_write_4(sc, INTC_MIR_CLEAR(nb >> 5), (1UL << (nb & 0x1F))); } Index: projects/sendfile/sys/arm/ti/std.ti =================================================================== --- projects/sendfile/sys/arm/ti/std.ti (revision 276056) +++ projects/sendfile/sys/arm/ti/std.ti (revision 276057) @@ -1,6 +1,7 @@ # $FreeBSD$ cpu CPU_CORTEXA machine arm armv6 +makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a" files "../ti/files.ti" Index: projects/sendfile/sys/arm/ti/ti_i2c.c =================================================================== --- projects/sendfile/sys/arm/ti/ti_i2c.c (revision 276056) +++ projects/sendfile/sys/arm/ti/ti_i2c.c (revision 276057) @@ -1,977 +1,977 @@ /*- * Copyright (c) 2011 Ben Gray . * Copyright (c) 2014 Luiz Otavio O Souza . * 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 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 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. */ /** * Driver for the I2C module on the TI SoC. * * This driver is heavily based on the TWI driver for the AT91 (at91_twi.c). * * CAUTION: The I2Ci registers are limited to 16 bit and 8 bit data accesses, * 32 bit data access is not allowed and can corrupt register content. * * This driver currently doesn't use DMA for the transfer, although I hope to * incorporate that sometime in the future. The idea being that for transaction * larger than a certain size the DMA engine is used, for anything less the * normal interrupt/fifo driven option is used. * * * WARNING: This driver uses mtx_sleep and interrupts to perform transactions, * which means you can't do a transaction during startup before the interrupts * have been enabled. Hint - the freebsd function config_intrhook_establish(). */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "iicbus_if.h" /** * I2C device driver context, a pointer to this is stored in the device * driver structure. */ struct ti_i2c_softc { device_t sc_dev; uint32_t device_id; struct resource* sc_irq_res; struct resource* sc_mem_res; device_t sc_iicbus; void* sc_irq_h; struct mtx sc_mtx; struct iic_msg* sc_buffer; int sc_bus_inuse; int sc_buffer_pos; int sc_error; int sc_fifo_trsh; uint16_t sc_con_reg; uint16_t sc_rev; }; struct ti_i2c_clock_config { u_int frequency; /* Bus frequency in Hz */ uint8_t psc; /* Fast/Standard mode prescale divider */ uint8_t scll; /* Fast/Standard mode SCL low time */ uint8_t sclh; /* Fast/Standard mode SCL high time */ uint8_t hsscll; /* High Speed mode SCL low time */ uint8_t hssclh; /* High Speed mode SCL high time */ }; #if defined(SOC_OMAP4) /* * OMAP4 i2c bus clock is 96MHz / ((psc + 1) * (scll + 7 + sclh + 5)). * The prescaler values for 100KHz and 400KHz modes come from the table in the * OMAP4 TRM. The table doesn't list 1MHz; these values should give that speed. */ static struct ti_i2c_clock_config ti_omap4_i2c_clock_configs[] = { { 100000, 23, 13, 15, 0, 0}, { 400000, 9, 5, 7, 0, 0}, - { 1000000, 5, 1, 3, 0, 0}, + { 1000000, 3, 5, 7, 0, 0}, /* { 3200000, 1, 113, 115, 7, 10}, - HS mode */ { 0 /* Table terminator */ } }; #endif #if defined(SOC_TI_AM335X) /* * AM335x i2c bus clock is 48MHZ / ((psc + 1) * (scll + 7 + sclh + 5)) * In all cases we prescale the clock to 24MHz as recommended in the manual. */ static struct ti_i2c_clock_config ti_am335x_i2c_clock_configs[] = { { 100000, 1, 111, 117, 0, 0}, { 400000, 1, 23, 25, 0, 0}, { 1000000, 1, 5, 7, 0, 0}, { 0 /* Table terminator */ } }; #endif /** * Locking macros used throughout the driver */ #define TI_I2C_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) #define TI_I2C_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) #define TI_I2C_LOCK_INIT(_sc) \ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \ "ti_i2c", MTX_DEF) #define TI_I2C_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx) #define TI_I2C_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED) #define TI_I2C_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED) #ifdef DEBUG #define ti_i2c_dbg(_sc, fmt, args...) \ device_printf((_sc)->sc_dev, fmt, ##args) #else #define ti_i2c_dbg(_sc, fmt, args...) #endif /** * ti_i2c_read_2 - reads a 16-bit value from one of the I2C registers * @sc: I2C device context * @off: the byte offset within the register bank to read from. * * * LOCKING: * No locking required * * RETURNS: * 16-bit value read from the register. */ static inline uint16_t ti_i2c_read_2(struct ti_i2c_softc *sc, bus_size_t off) { return (bus_read_2(sc->sc_mem_res, off)); } /** * ti_i2c_write_2 - writes a 16-bit value to one of the I2C registers * @sc: I2C device context * @off: the byte offset within the register bank to read from. * @val: the value to write into the register * * LOCKING: * No locking required * * RETURNS: * 16-bit value read from the register. */ static inline void ti_i2c_write_2(struct ti_i2c_softc *sc, bus_size_t off, uint16_t val) { bus_write_2(sc->sc_mem_res, off, val); } static int ti_i2c_transfer_intr(struct ti_i2c_softc* sc, uint16_t status) { int amount, done, i; done = 0; amount = 0; /* Check for the error conditions. */ if (status & I2C_STAT_NACK) { /* No ACK from slave. */ ti_i2c_dbg(sc, "NACK\n"); ti_i2c_write_2(sc, I2C_REG_STATUS, I2C_STAT_NACK); sc->sc_error = ENXIO; } else if (status & I2C_STAT_AL) { /* Arbitration lost. */ ti_i2c_dbg(sc, "Arbitration lost\n"); ti_i2c_write_2(sc, I2C_REG_STATUS, I2C_STAT_AL); sc->sc_error = ENXIO; } /* Check if we have finished. */ if (status & I2C_STAT_ARDY) { /* Register access ready - transaction complete basically. */ ti_i2c_dbg(sc, "ARDY transaction complete\n"); if (sc->sc_error != 0 && sc->sc_buffer->flags & IIC_M_NOSTOP) { ti_i2c_write_2(sc, I2C_REG_CON, sc->sc_con_reg | I2C_CON_STP); } ti_i2c_write_2(sc, I2C_REG_STATUS, I2C_STAT_ARDY | I2C_STAT_RDR | I2C_STAT_RRDY | I2C_STAT_XDR | I2C_STAT_XRDY); return (1); } if (sc->sc_buffer->flags & IIC_M_RD) { /* Read some data. */ if (status & I2C_STAT_RDR) { /* * Receive draining interrupt - last data received. * The set FIFO threshold wont be reached to trigger * RRDY. */ ti_i2c_dbg(sc, "Receive draining interrupt\n"); /* * Drain the FIFO. Read the pending data in the FIFO. */ amount = sc->sc_buffer->len - sc->sc_buffer_pos; } else if (status & I2C_STAT_RRDY) { /* * Receive data ready interrupt - FIFO has reached the * set threshold. */ ti_i2c_dbg(sc, "Receive data ready interrupt\n"); amount = min(sc->sc_fifo_trsh, sc->sc_buffer->len - sc->sc_buffer_pos); } /* Read the bytes from the fifo. */ for (i = 0; i < amount; i++) sc->sc_buffer->buf[sc->sc_buffer_pos++] = (uint8_t)(ti_i2c_read_2(sc, I2C_REG_DATA) & 0xff); if (status & I2C_STAT_RDR) ti_i2c_write_2(sc, I2C_REG_STATUS, I2C_STAT_RDR); if (status & I2C_STAT_RRDY) ti_i2c_write_2(sc, I2C_REG_STATUS, I2C_STAT_RRDY); } else { /* Write some data. */ if (status & I2C_STAT_XDR) { /* * Transmit draining interrupt - FIFO level is below * the set threshold and the amount of data still to * be transferred wont reach the set FIFO threshold. */ ti_i2c_dbg(sc, "Transmit draining interrupt\n"); /* * Drain the TX data. Write the pending data in the * FIFO. */ amount = sc->sc_buffer->len - sc->sc_buffer_pos; } else if (status & I2C_STAT_XRDY) { /* * Transmit data ready interrupt - the FIFO level * is below the set threshold. */ ti_i2c_dbg(sc, "Transmit data ready interrupt\n"); amount = min(sc->sc_fifo_trsh, sc->sc_buffer->len - sc->sc_buffer_pos); } /* Write the bytes from the fifo. */ for (i = 0; i < amount; i++) ti_i2c_write_2(sc, I2C_REG_DATA, sc->sc_buffer->buf[sc->sc_buffer_pos++]); if (status & I2C_STAT_XDR) ti_i2c_write_2(sc, I2C_REG_STATUS, I2C_STAT_XDR); if (status & I2C_STAT_XRDY) ti_i2c_write_2(sc, I2C_REG_STATUS, I2C_STAT_XRDY); } return (done); } /** * ti_i2c_intr - interrupt handler for the I2C module * @dev: i2c device handle * * * * LOCKING: * Called from timer context * * RETURNS: * EH_HANDLED or EH_NOT_HANDLED */ static void ti_i2c_intr(void *arg) { int done; struct ti_i2c_softc *sc; uint16_t events, status; sc = (struct ti_i2c_softc *)arg; TI_I2C_LOCK(sc); status = ti_i2c_read_2(sc, I2C_REG_STATUS); if (status == 0) { TI_I2C_UNLOCK(sc); return; } /* Save enabled interrupts. */ events = ti_i2c_read_2(sc, I2C_REG_IRQENABLE_SET); /* We only care about enabled interrupts. */ status &= events; done = 0; if (sc->sc_buffer != NULL) done = ti_i2c_transfer_intr(sc, status); else { ti_i2c_dbg(sc, "Transfer interrupt without buffer\n"); sc->sc_error = EINVAL; done = 1; } if (done) /* Wakeup the process that started the transaction. */ wakeup(sc); TI_I2C_UNLOCK(sc); } /** * ti_i2c_transfer - called to perform the transfer * @dev: i2c device handle * @msgs: the messages to send/receive * @nmsgs: the number of messages in the msgs array * * * LOCKING: * Internally locked * * RETURNS: * 0 on function succeeded * EINVAL if invalid message is passed as an arg */ static int ti_i2c_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) { int err, i, repstart, timeout; struct ti_i2c_softc *sc; uint16_t reg; sc = device_get_softc(dev); TI_I2C_LOCK(sc); /* If the controller is busy wait until it is available. */ while (sc->sc_bus_inuse == 1) mtx_sleep(sc, &sc->sc_mtx, 0, "i2cbuswait", 0); /* Now we have control over the I2C controller. */ sc->sc_bus_inuse = 1; err = 0; repstart = 0; for (i = 0; i < nmsgs; i++) { sc->sc_buffer = &msgs[i]; sc->sc_buffer_pos = 0; sc->sc_error = 0; /* Zero byte transfers aren't allowed. */ if (sc->sc_buffer == NULL || sc->sc_buffer->buf == NULL || sc->sc_buffer->len == 0) { err = EINVAL; break; } /* Check if the i2c bus is free. */ if (repstart == 0) { /* * On repeated start we send the START condition while * the bus _is_ busy. */ timeout = 0; while (ti_i2c_read_2(sc, I2C_REG_STATUS_RAW) & I2C_STAT_BB) { if (timeout++ > 100) { err = EBUSY; goto out; } DELAY(1000); } timeout = 0; } else repstart = 0; if (sc->sc_buffer->flags & IIC_M_NOSTOP) repstart = 1; /* Set the slave address. */ ti_i2c_write_2(sc, I2C_REG_SA, msgs[i].slave >> 1); /* Write the data length. */ ti_i2c_write_2(sc, I2C_REG_CNT, sc->sc_buffer->len); /* Clear the RX and the TX FIFO. */ reg = ti_i2c_read_2(sc, I2C_REG_BUF); reg |= I2C_BUF_RXFIFO_CLR | I2C_BUF_TXFIFO_CLR; ti_i2c_write_2(sc, I2C_REG_BUF, reg); reg = sc->sc_con_reg | I2C_CON_STT; if (repstart == 0) reg |= I2C_CON_STP; if ((sc->sc_buffer->flags & IIC_M_RD) == 0) reg |= I2C_CON_TRX; ti_i2c_write_2(sc, I2C_REG_CON, reg); /* Wait for an event. */ err = mtx_sleep(sc, &sc->sc_mtx, 0, "i2ciowait", hz); if (err == 0) err = sc->sc_error; if (err) break; } out: if (timeout == 0) { while (ti_i2c_read_2(sc, I2C_REG_STATUS_RAW) & I2C_STAT_BB) { if (timeout++ > 100) break; DELAY(1000); } } /* Put the controller in master mode again. */ if ((ti_i2c_read_2(sc, I2C_REG_CON) & I2C_CON_MST) == 0) ti_i2c_write_2(sc, I2C_REG_CON, sc->sc_con_reg); sc->sc_buffer = NULL; sc->sc_bus_inuse = 0; /* Wake up the processes that are waiting for the bus. */ wakeup(sc); TI_I2C_UNLOCK(sc); return (err); } /** * ti_i2c_callback - as we only provide iicbus_transfer() interface * we don't need to implement the serialization here. * @dev: i2c device handle * * * * LOCKING: * Called from timer context * * RETURNS: * EH_HANDLED or EH_NOT_HANDLED */ static int ti_i2c_callback(device_t dev, int index, caddr_t data) { int error = 0; switch (index) { case IIC_REQUEST_BUS: break; case IIC_RELEASE_BUS: break; default: error = EINVAL; } return (error); } static int ti_i2c_reset(struct ti_i2c_softc *sc, u_char speed) { int timeout; struct ti_i2c_clock_config *clkcfg; u_int busfreq; uint16_t fifo_trsh, reg, scll, sclh; switch (ti_chip()) { #ifdef SOC_OMAP4 case CHIP_OMAP_4: clkcfg = ti_omap4_i2c_clock_configs; break; #endif #ifdef SOC_TI_AM335X case CHIP_AM335X: clkcfg = ti_am335x_i2c_clock_configs; break; #endif default: panic("Unknown Ti SoC, unable to reset the i2c"); } /* * If we haven't attached the bus yet, just init at the default slow * speed. This lets us get the hardware initialized enough to attach * the bus which is where the real speed configuration is handled. After * the bus is attached, get the configured speed from it. Search the * configuration table for the best speed we can do that doesn't exceed * the requested speed. */ if (sc->sc_iicbus == NULL) busfreq = 100000; else busfreq = IICBUS_GET_FREQUENCY(sc->sc_iicbus, speed); for (;;) { if (clkcfg[1].frequency == 0 || clkcfg[1].frequency > busfreq) break; clkcfg++; } /* * 23.1.4.3 - HS I2C Software Reset * From OMAP4 TRM at page 4068. * * 1. Ensure that the module is disabled. */ sc->sc_con_reg = 0; ti_i2c_write_2(sc, I2C_REG_CON, sc->sc_con_reg); /* 2. Issue a softreset to the controller. */ bus_write_2(sc->sc_mem_res, I2C_REG_SYSC, I2C_REG_SYSC_SRST); /* * 3. Enable the module. * The I2Ci.I2C_SYSS[0] RDONE bit is asserted only after the module * is enabled by setting the I2Ci.I2C_CON[15] I2C_EN bit to 1. */ ti_i2c_write_2(sc, I2C_REG_CON, I2C_CON_I2C_EN); /* 4. Wait for the software reset to complete. */ timeout = 0; while ((ti_i2c_read_2(sc, I2C_REG_SYSS) & I2C_SYSS_RDONE) == 0) { if (timeout++ > 100) return (EBUSY); DELAY(100); } /* * Disable the I2C controller once again, now that the reset has * finished. */ ti_i2c_write_2(sc, I2C_REG_CON, sc->sc_con_reg); /* * The following sequence is taken from the OMAP4 TRM at page 4077. * * 1. Enable the functional and interface clocks (see Section * 23.1.5.1.1.1.1). Done at ti_i2c_activate(). * * 2. Program the prescaler to obtain an approximately 12MHz internal * sampling clock (I2Ci_INTERNAL_CLK) by programming the * corresponding value in the I2Ci.I2C_PSC[3:0] PSC field. * This value depends on the frequency of the functional clock * (I2Ci_FCLK). Because this frequency is 96MHz, the * I2Ci.I2C_PSC[7:0] PSC field value is 0x7. */ ti_i2c_write_2(sc, I2C_REG_PSC, clkcfg->psc); /* * 3. Program the I2Ci.I2C_SCLL[7:0] SCLL and I2Ci.I2C_SCLH[7:0] SCLH * bit fields to obtain a bit rate of 100 Kbps, 400 Kbps or 1Mbps. * These values depend on the internal sampling clock frequency * (see Table 23-8). */ scll = clkcfg->scll & I2C_SCLL_MASK; sclh = clkcfg->sclh & I2C_SCLH_MASK; /* * 4. (Optional) Program the I2Ci.I2C_SCLL[15:8] HSSCLL and * I2Ci.I2C_SCLH[15:8] HSSCLH fields to obtain a bit rate of * 400K bps or 3.4M bps (for the second phase of HS mode). These * values depend on the internal sampling clock frequency (see * Table 23-8). * * 5. (Optional) If a bit rate of 3.4M bps is used and the bus line * capacitance exceeds 45 pF, (see Section 18.4.8, PAD Functional * Multiplexing and Configuration). */ switch (ti_chip()) { #ifdef SOC_OMAP4 case CHIP_OMAP_4: if ((clkcfg->hsscll + clkcfg->hssclh) > 0) { scll |= clkcfg->hsscll << I2C_HSSCLL_SHIFT; sclh |= clkcfg->hssclh << I2C_HSSCLH_SHIFT; sc->sc_con_reg |= I2C_CON_OPMODE_HS; } break; #endif } /* Write the selected bit rate. */ ti_i2c_write_2(sc, I2C_REG_SCLL, scll); ti_i2c_write_2(sc, I2C_REG_SCLH, sclh); /* * 6. Configure the Own Address of the I2C controller by storing it in * the I2Ci.I2C_OA0 register. Up to four Own Addresses can be * programmed in the I2Ci.I2C_OAi registers (where i = 0, 1, 2, 3) * for each I2C controller. * * Note: For a 10-bit address, set the corresponding expand Own Address * bit in the I2Ci.I2C_CON register. * * Driver currently always in single master mode so ignore this step. */ /* * 7. Set the TX threshold (in transmitter mode) and the RX threshold * (in receiver mode) by setting the I2Ci.I2C_BUF[5:0]XTRSH field to * (TX threshold - 1) and the I2Ci.I2C_BUF[13:8]RTRSH field to (RX * threshold - 1), where the TX and RX thresholds are greater than * or equal to 1. * * The threshold is set to 5 for now. */ fifo_trsh = (sc->sc_fifo_trsh - 1) & I2C_BUF_TRSH_MASK; reg = fifo_trsh | (fifo_trsh << I2C_BUF_RXTRSH_SHIFT); ti_i2c_write_2(sc, I2C_REG_BUF, reg); /* * 8. Take the I2C controller out of reset by setting the * I2Ci.I2C_CON[15] I2C_EN bit to 1. * * 23.1.5.1.1.1.2 - Initialize the I2C Controller * * To initialize the I2C controller, perform the following steps: * * 1. Configure the I2Ci.I2C_CON register: * . For master or slave mode, set the I2Ci.I2C_CON[10] MST bit * (0: slave, 1: master). * . For transmitter or receiver mode, set the I2Ci.I2C_CON[9] TRX * bit (0: receiver, 1: transmitter). */ /* Enable the I2C controller in master mode. */ sc->sc_con_reg |= I2C_CON_I2C_EN | I2C_CON_MST; ti_i2c_write_2(sc, I2C_REG_CON, sc->sc_con_reg); /* * 2. If using an interrupt to transmit/receive data, set the * corresponding bit in the I2Ci.I2C_IE register (the I2Ci.I2C_IE[4] * XRDY_IE bit for the transmit interrupt, the I2Ci.I2C_IE[3] RRDY * bit for the receive interrupt). */ /* Set the interrupts we want to be notified. */ reg = I2C_IE_XDR | /* Transmit draining interrupt. */ I2C_IE_XRDY | /* Transmit Data Ready interrupt. */ I2C_IE_RDR | /* Receive draining interrupt. */ I2C_IE_RRDY | /* Receive Data Ready interrupt. */ I2C_IE_ARDY | /* Register Access Ready interrupt. */ I2C_IE_NACK | /* No Acknowledgment interrupt. */ I2C_IE_AL; /* Arbitration lost interrupt. */ /* Enable the interrupts. */ ti_i2c_write_2(sc, I2C_REG_IRQENABLE_SET, reg); /* * 3. If using DMA to receive/transmit data, set to 1 the corresponding * bit in the I2Ci.I2C_BUF register (the I2Ci.I2C_BUF[15] RDMA_EN * bit for the receive DMA channel, the I2Ci.I2C_BUF[7] XDMA_EN bit * for the transmit DMA channel). * * Not using DMA for now, so ignore this. */ return (0); } static int ti_i2c_iicbus_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) { struct ti_i2c_softc *sc; int err; sc = device_get_softc(dev); TI_I2C_LOCK(sc); err = ti_i2c_reset(sc, speed); TI_I2C_UNLOCK(sc); if (err) return (err); return (IIC_ENOADDR); } static int ti_i2c_activate(device_t dev) { clk_ident_t clk; int err; struct ti_i2c_softc *sc; sc = (struct ti_i2c_softc*)device_get_softc(dev); /* * 1. Enable the functional and interface clocks (see Section * 23.1.5.1.1.1.1). */ clk = I2C0_CLK + sc->device_id; err = ti_prcm_clk_enable(clk); if (err) return (err); return (ti_i2c_reset(sc, IIC_UNKNOWN)); } /** * ti_i2c_deactivate - deactivates the controller and releases resources * @dev: i2c device handle * * * * LOCKING: * Assumed called in an atomic context. * * RETURNS: * nothing */ static void ti_i2c_deactivate(device_t dev) { struct ti_i2c_softc *sc = device_get_softc(dev); clk_ident_t clk; /* Disable the controller - cancel all transactions. */ ti_i2c_write_2(sc, I2C_REG_IRQENABLE_CLR, 0xffff); ti_i2c_write_2(sc, I2C_REG_STATUS, 0xffff); ti_i2c_write_2(sc, I2C_REG_CON, 0); /* Release the interrupt handler. */ if (sc->sc_irq_h != NULL) { bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_h); sc->sc_irq_h = NULL; } bus_generic_detach(sc->sc_dev); /* Unmap the I2C controller registers. */ if (sc->sc_mem_res != NULL) { bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); sc->sc_mem_res = NULL; } /* Release the IRQ resource. */ if (sc->sc_irq_res != NULL) { bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res); sc->sc_irq_res = NULL; } /* Finally disable the functional and interface clocks. */ clk = I2C0_CLK + sc->device_id; ti_prcm_clk_disable(clk); } static int ti_i2c_sysctl_clk(SYSCTL_HANDLER_ARGS) { device_t dev; int clk, psc, sclh, scll; struct ti_i2c_softc *sc; dev = (device_t)arg1; sc = device_get_softc(dev); TI_I2C_LOCK(sc); /* Get the system prescaler value. */ psc = (int)ti_i2c_read_2(sc, I2C_REG_PSC) + 1; /* Get the bitrate. */ scll = (int)ti_i2c_read_2(sc, I2C_REG_SCLL) & I2C_SCLL_MASK; sclh = (int)ti_i2c_read_2(sc, I2C_REG_SCLH) & I2C_SCLH_MASK; clk = I2C_CLK / psc / (scll + 7 + sclh + 5); TI_I2C_UNLOCK(sc); return (sysctl_handle_int(oidp, &clk, 0, req)); } static int ti_i2c_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (!ofw_bus_is_compatible(dev, "ti,i2c")) return (ENXIO); device_set_desc(dev, "TI I2C Controller"); return (0); } static int ti_i2c_attach(device_t dev) { int err, rid; phandle_t node; struct ti_i2c_softc *sc; struct sysctl_ctx_list *ctx; struct sysctl_oid_list *tree; uint16_t fifosz; sc = device_get_softc(dev); sc->sc_dev = dev; /* Get the i2c device id from FDT. */ node = ofw_bus_get_node(dev); if ((OF_getencprop(node, "i2c-device-id", &sc->device_id, sizeof(sc->device_id))) <= 0) { device_printf(dev, "missing i2c-device-id attribute in FDT\n"); return (ENXIO); } /* Get the memory resource for the register mapping. */ rid = 0; sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->sc_mem_res == NULL) { device_printf(dev, "Cannot map registers.\n"); return (ENXIO); } /* Allocate our IRQ resource. */ rid = 0; sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE | RF_SHAREABLE); if (sc->sc_irq_res == NULL) { bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); device_printf(dev, "Cannot allocate interrupt.\n"); return (ENXIO); } TI_I2C_LOCK_INIT(sc); /* First of all, we _must_ activate the H/W. */ err = ti_i2c_activate(dev); if (err) { device_printf(dev, "ti_i2c_activate failed\n"); goto out; } /* Read the version number of the I2C module */ sc->sc_rev = ti_i2c_read_2(sc, I2C_REG_REVNB_HI) & 0xff; /* Get the fifo size. */ fifosz = ti_i2c_read_2(sc, I2C_REG_BUFSTAT); fifosz >>= I2C_BUFSTAT_FIFODEPTH_SHIFT; fifosz &= I2C_BUFSTAT_FIFODEPTH_MASK; device_printf(dev, "I2C revision %d.%d FIFO size: %d bytes\n", sc->sc_rev >> 4, sc->sc_rev & 0xf, 8 << fifosz); /* Set the FIFO threshold to 5 for now. */ sc->sc_fifo_trsh = 5; ctx = device_get_sysctl_ctx(dev); tree = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "i2c_clock", CTLFLAG_RD | CTLTYPE_UINT | CTLFLAG_MPSAFE, dev, 0, ti_i2c_sysctl_clk, "IU", "I2C bus clock"); /* Activate the interrupt. */ err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, NULL, ti_i2c_intr, sc, &sc->sc_irq_h); if (err) goto out; /* Attach the iicbus. */ if ((sc->sc_iicbus = device_add_child(dev, "iicbus", -1)) == NULL) { device_printf(dev, "could not allocate iicbus instance\n"); err = ENXIO; goto out; } /* Probe and attach the iicbus */ bus_generic_attach(dev); out: if (err) { ti_i2c_deactivate(dev); TI_I2C_LOCK_DESTROY(sc); } return (err); } static int ti_i2c_detach(device_t dev) { struct ti_i2c_softc *sc; int rv; sc = device_get_softc(dev); ti_i2c_deactivate(dev); TI_I2C_LOCK_DESTROY(sc); if (sc->sc_iicbus && (rv = device_delete_child(dev, sc->sc_iicbus)) != 0) return (rv); return (0); } static phandle_t ti_i2c_get_node(device_t bus, device_t dev) { /* Share controller node with iibus device. */ return (ofw_bus_get_node(bus)); } static device_method_t ti_i2c_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ti_i2c_probe), DEVMETHOD(device_attach, ti_i2c_attach), DEVMETHOD(device_detach, ti_i2c_detach), /* OFW methods */ DEVMETHOD(ofw_bus_get_node, ti_i2c_get_node), /* iicbus interface */ DEVMETHOD(iicbus_callback, ti_i2c_callback), DEVMETHOD(iicbus_reset, ti_i2c_iicbus_reset), DEVMETHOD(iicbus_transfer, ti_i2c_transfer), DEVMETHOD_END }; static driver_t ti_i2c_driver = { "iichb", ti_i2c_methods, sizeof(struct ti_i2c_softc), }; static devclass_t ti_i2c_devclass; DRIVER_MODULE(ti_iic, simplebus, ti_i2c_driver, ti_i2c_devclass, 0, 0); DRIVER_MODULE(iicbus, ti_iic, iicbus_driver, iicbus_devclass, 0, 0); MODULE_DEPEND(ti_iic, ti_prcm, 1, 1, 1); MODULE_DEPEND(ti_iic, iicbus, 1, 1, 1); Index: projects/sendfile/sys/arm/ti/ti_wdt.c =================================================================== --- projects/sendfile/sys/arm/ti/ti_wdt.c (revision 276056) +++ projects/sendfile/sys/arm/ti/ti_wdt.c (revision 276057) @@ -1,277 +1,277 @@ /*- * Copyright (c) 2014 Rui Paulo * 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 ``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 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DEBUG #define DPRINTF(fmt, ...) do { \ printf("%s: ", __func__); \ printf(fmt, __VA_ARGS__); \ } while (0) #else #define DPRINTF(fmt, ...) #endif static device_probe_t ti_wdt_probe; static device_attach_t ti_wdt_attach; static device_detach_t ti_wdt_detach; static void ti_wdt_intr(void *); static void ti_wdt_event(void *, unsigned int, int *); struct ti_wdt_softc { struct resource *sc_mem_res; struct resource *sc_irq_res; void *sc_intr; bus_space_tag_t sc_bt; bus_space_handle_t sc_bh; eventhandler_tag sc_ev_tag; }; static device_method_t ti_wdt_methods[] = { DEVMETHOD(device_probe, ti_wdt_probe), DEVMETHOD(device_attach, ti_wdt_attach), DEVMETHOD(device_detach, ti_wdt_detach), DEVMETHOD_END }; static driver_t ti_wdt_driver = { "ti_wdt", ti_wdt_methods, sizeof(struct ti_wdt_softc) }; static devclass_t ti_wdt_devclass; DRIVER_MODULE(ti_wdt, simplebus, ti_wdt_driver, ti_wdt_devclass, 0, 0); -static volatile __inline uint32_t +static __inline uint32_t ti_wdt_reg_read(struct ti_wdt_softc *sc, uint32_t reg) { return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg)); } static __inline void ti_wdt_reg_write(struct ti_wdt_softc *sc, uint32_t reg, uint32_t val) { bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val); } /* * Wait for the write to a specific synchronised register to complete. */ static __inline void ti_wdt_reg_wait(struct ti_wdt_softc *sc, uint32_t bit) { while (ti_wdt_reg_read(sc, TI_WDT_WWPS) & bit) DELAY(10); } static __inline void ti_wdt_disable(struct ti_wdt_softc *sc) { DPRINTF("disabling watchdog %p\n", sc); ti_wdt_reg_write(sc, TI_WDT_WSPR, 0xAAAA); ti_wdt_reg_wait(sc, TI_W_PEND_WSPR); ti_wdt_reg_write(sc, TI_WDT_WSPR, 0x5555); ti_wdt_reg_wait(sc, TI_W_PEND_WSPR); } static __inline void ti_wdt_enable(struct ti_wdt_softc *sc) { DPRINTF("enabling watchdog %p\n", sc); ti_wdt_reg_write(sc, TI_WDT_WSPR, 0xBBBB); ti_wdt_reg_wait(sc, TI_W_PEND_WSPR); ti_wdt_reg_write(sc, TI_WDT_WSPR, 0x4444); ti_wdt_reg_wait(sc, TI_W_PEND_WSPR); } static int ti_wdt_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (ofw_bus_is_compatible(dev, "ti,omap3-wdt")) { device_set_desc(dev, "TI Watchdog Timer"); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int ti_wdt_attach(device_t dev) { struct ti_wdt_softc *sc; int rid; sc = device_get_softc(dev); rid = 0; sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->sc_mem_res == NULL) { device_printf(dev, "could not allocate memory resource\n"); return (ENXIO); } sc->sc_bt = rman_get_bustag(sc->sc_mem_res); sc->sc_bh = rman_get_bushandle(sc->sc_mem_res); sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (sc->sc_irq_res == NULL) { device_printf(dev, "could not allocate interrupt resource\n"); ti_wdt_detach(dev); return (ENXIO); } if (bus_setup_intr(dev, sc->sc_irq_res, INTR_MPSAFE | INTR_TYPE_MISC, NULL, ti_wdt_intr, sc, &sc->sc_intr) != 0) { device_printf(dev, "unable to setup the interrupt handler\n"); ti_wdt_detach(dev); return (ENXIO); } /* Reset, enable interrupts and stop the watchdog. */ ti_wdt_reg_write(sc, TI_WDT_WDSC, ti_wdt_reg_read(sc, TI_WDT_WDSC) | TI_WDSC_SR); while (ti_wdt_reg_read(sc, TI_WDT_WDSC) & TI_WDSC_SR) DELAY(10); ti_wdt_reg_write(sc, TI_WDT_WIRQENSET, TI_IRQ_EN_OVF | TI_IRQ_EN_DLY); ti_wdt_disable(sc); if (bootverbose) device_printf(dev, "revision: 0x%x\n", ti_wdt_reg_read(sc, TI_WDT_WIDR)); sc->sc_ev_tag = EVENTHANDLER_REGISTER(watchdog_list, ti_wdt_event, sc, 0); return (0); } static int ti_wdt_detach(device_t dev) { struct ti_wdt_softc *sc; sc = device_get_softc(dev); if (sc->sc_ev_tag) EVENTHANDLER_DEREGISTER(watchdog_list, sc->sc_ev_tag); if (sc->sc_intr) bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intr); if (sc->sc_irq_res) bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->sc_irq_res), sc->sc_irq_res); if (sc->sc_mem_res) bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->sc_mem_res), sc->sc_mem_res); return (0); } static void ti_wdt_intr(void *arg) { struct ti_wdt_softc *sc; sc = arg; DPRINTF("interrupt %p", sc); ti_wdt_reg_write(sc, TI_WDT_WIRQSTAT, TI_IRQ_EV_OVF | TI_IRQ_EV_DLY); /* TODO: handle interrupt */ } static void ti_wdt_event(void *arg, unsigned int cmd, int *error) { struct ti_wdt_softc *sc; uint8_t s; uint32_t wldr; uint32_t ptv; sc = arg; ti_wdt_disable(sc); if (cmd == WD_TO_NEVER) { *error = 0; return; } DPRINTF("cmd 0x%x\n", cmd); cmd &= WD_INTERVAL; if (cmd < WD_TO_1SEC) { *error = EINVAL; return; } s = 1 << (cmd - WD_TO_1SEC); DPRINTF("seconds %u\n", s); /* * Leave the pre-scaler with its default values: * PTV = 0 == 2**0 == 1 * PRE = 1 (enabled) * * Compute the load register value assuming a 32kHz clock. * See OVF_Rate in the WDT section of the AM335x TRM. */ ptv = 0; wldr = 0xffffffff - (s * (32768 / (1 << ptv))) + 1; DPRINTF("wldr 0x%x\n", wldr); ti_wdt_reg_write(sc, TI_WDT_WLDR, wldr); /* * Trigger a timer reload. */ ti_wdt_reg_write(sc, TI_WDT_WTGR, ti_wdt_reg_read(sc, TI_WDT_WTGR) + 1); ti_wdt_reg_wait(sc, TI_W_PEND_WTGR); ti_wdt_enable(sc); *error = 0; } Index: projects/sendfile/sys/arm/xilinx/std.zynq7 =================================================================== --- projects/sendfile/sys/arm/xilinx/std.zynq7 (revision 276056) +++ projects/sendfile/sys/arm/xilinx/std.zynq7 (revision 276057) @@ -1,24 +1,25 @@ # # std.zynq7 - Generic configuration for Xilinx Zynq-7000 PS. # # $FreeBSD$ cpu CPU_CORTEXA machine arm armv6 +makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a" files "../xilinx/files.zynq7" # Physical memory starts at 0x00000000. We assume images are loaded at # 0x00100000, e.g. from u-boot with 'fatload mmc 0 0x100000 kernel.bin' # # options PHYSADDR=0x00000000 options KERNPHYSADDR=0x00100000 makeoptions KERNPHYSADDR=0x00100000 options KERNVIRTADDR=0xc0100000 # Used in ldscript.arm makeoptions KERNVIRTADDR=0xc0100000 options ARM_L2_PIPT options IPI_IRQ_START=0 options IPI_IRQ_END=15 Index: projects/sendfile/sys/boot/uboot/common/main.c =================================================================== --- projects/sendfile/sys/boot/uboot/common/main.c (revision 276056) +++ projects/sendfile/sys/boot/uboot/common/main.c (revision 276057) @@ -1,643 +1,644 @@ /*- * Copyright (c) 2000 Benno Rice * Copyright (c) 2000 Stephane Potvin * Copyright (c) 2007-2008 Semihalf, Rafal Jaworowski * 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 AUTHORS 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. */ #include __FBSDID("$FreeBSD$"); #include #include "api_public.h" #include "bootstrap.h" #include "glue.h" #include "libuboot.h" #ifndef nitems #define nitems(x) (sizeof((x)) / sizeof((x)[0])) #endif struct uboot_devdesc currdev; struct arch_switch archsw; /* MI/MD interface boundary */ int devs_no; struct device_type { const char *name; int type; } device_types[] = { { "disk", DEV_TYP_STOR }, { "ide", DEV_TYP_STOR | DT_STOR_IDE }, { "mmc", DEV_TYP_STOR | DT_STOR_MMC }, { "sata", DEV_TYP_STOR | DT_STOR_SATA }, { "scsi", DEV_TYP_STOR | DT_STOR_SCSI }, { "usb", DEV_TYP_STOR | DT_STOR_USB }, { "net", DEV_TYP_NET } }; extern char end[]; extern char bootprog_name[]; extern char bootprog_rev[]; extern char bootprog_date[]; extern char bootprog_maker[]; extern unsigned char _etext[]; extern unsigned char _edata[]; extern unsigned char __bss_start[]; extern unsigned char __sbss_start[]; extern unsigned char __sbss_end[]; extern unsigned char _end[]; #ifdef LOADER_FDT_SUPPORT extern int command_fdt_internal(int argc, char *argv[]); #endif static void dump_sig(struct api_signature *sig) { #ifdef DEBUG printf("signature:\n"); printf(" version\t= %d\n", sig->version); printf(" checksum\t= 0x%08x\n", sig->checksum); printf(" sc entry\t= 0x%08x\n", sig->syscall); #endif } static void dump_addr_info(void) { #ifdef DEBUG printf("\naddresses info:\n"); printf(" _etext (sdata) = 0x%08x\n", (uint32_t)_etext); printf(" _edata = 0x%08x\n", (uint32_t)_edata); printf(" __sbss_start = 0x%08x\n", (uint32_t)__sbss_start); printf(" __sbss_end = 0x%08x\n", (uint32_t)__sbss_end); printf(" __sbss_start = 0x%08x\n", (uint32_t)__bss_start); printf(" _end = 0x%08x\n", (uint32_t)_end); printf(" syscall entry = 0x%08x\n", (uint32_t)syscall_ptr); #endif } static uint64_t memsize(struct sys_info *si, int flags) { uint64_t size; int i; size = 0; for (i = 0; i < si->mr_no; i++) if (si->mr[i].flags == flags && si->mr[i].size) size += (si->mr[i].size); return (size); } static void meminfo(void) { uint64_t size; struct sys_info *si; int t[3] = { MR_ATTR_DRAM, MR_ATTR_FLASH, MR_ATTR_SRAM }; int i; if ((si = ub_get_sys_info()) == NULL) panic("could not retrieve system info"); for (i = 0; i < 3; i++) { size = memsize(si, t[i]); if (size > 0) printf("%s: %lldMB\n", ub_mem_type(t[i]), size / 1024 / 1024); } } static const char * get_device_type(const char *devstr, int *devtype) { int i; int namelen; struct device_type *dt; if (devstr) { for (i = 0; i < nitems(device_types); i++) { dt = &device_types[i]; namelen = strlen(dt->name); if (strncmp(dt->name, devstr, namelen) == 0) { *devtype = dt->type; return (devstr + namelen); } } printf("Unknown device type '%s'\n", devstr); } *devtype = -1; return (NULL); } static const char * device_typename(int type) { int i; for (i = 0; i < nitems(device_types); i++) if (device_types[i].type == type) return (device_types[i].name); return (""); } /* * Parse a device string into type, unit, slice and partition numbers. A * returned value of -1 for type indicates a search should be done for the * first loadable device, otherwise a returned value of -1 for unit * indicates a search should be done for the first loadable device of the * given type. * * The returned values for slice and partition are interpreted by * disk_open(). * * Valid device strings: For device types: * * DEV_TYP_STOR, DEV_TYP_NET * DEV_TYP_STOR, DEV_TYP_NET * : DEV_TYP_STOR, DEV_TYP_NET * : DEV_TYP_STOR * :. DEV_TYP_STOR * :. DEV_TYP_STOR * * For valid type names, see the device_types array, above. * * Slice numbers are 1-based. 0 is a wildcard. */ static void get_load_device(int *type, int *unit, int *slice, int *partition) { char *devstr; const char *p; char *endp; *type = -1; *unit = -1; *slice = 0; *partition = -1; devstr = ub_env_get("loaderdev"); if (devstr == NULL) { printf("U-Boot env: loaderdev not set, will probe all devices.\n"); return; } printf("U-Boot env: loaderdev='%s'\n", devstr); p = get_device_type(devstr, type); - /* - * Empty device string, or unknown device name, or a bare, known - * device name. - */ + /* Ignore optional spaces after the device name. */ + while (*p == ' ') + p++; + + /* Unknown device name, or a known name without unit number. */ if ((*type == -1) || (*p == '\0')) { return; } /* Malformed unit number. */ if (!isdigit(*p)) { *type = -1; return; } /* Guaranteed to extract a number from the string, as *p is a digit. */ *unit = strtol(p, &endp, 10); p = endp; /* Known device name with unit number and nothing else. */ if (*p == '\0') { return; } /* Device string is malformed beyond unit number. */ if (*p != ':') { *type = -1; *unit = -1; return; } p++; /* No slice and partition specification. */ if ('\0' == *p ) return; /* Only DEV_TYP_STOR devices can have a slice specification. */ if (!(*type & DEV_TYP_STOR)) { *type = -1; *unit = -1; return; } *slice = strtoul(p, &endp, 10); /* Malformed slice number. */ if (p == endp) { *type = -1; *unit = -1; *slice = 0; return; } p = endp; /* No partition specification. */ if (*p == '\0') return; /* Device string is malformed beyond slice number. */ if (*p != '.') { *type = -1; *unit = -1; *slice = 0; return; } p++; /* No partition specification. */ if (*p == '\0') return; *partition = strtol(p, &endp, 10); p = endp; /* Full, valid device string. */ if (*endp == '\0') return; /* Junk beyond partition number. */ *type = -1; *unit = -1; *slice = 0; *partition = -1; } static void print_disk_probe_info() { char slice[32]; char partition[32]; if (currdev.d_disk.slice > 0) sprintf(slice, "%d", currdev.d_disk.slice); else strcpy(slice, ""); if (currdev.d_disk.partition > 0) sprintf(partition, "%d", currdev.d_disk.partition); else strcpy(partition, ""); printf(" Checking unit=%d slice=%s partition=%s...", currdev.d_unit, slice, partition); } static int probe_disks(int devidx, int load_type, int load_unit, int load_slice, int load_partition) { int open_result, unit; struct open_file f; currdev.d_disk.slice = load_slice; currdev.d_disk.partition = load_partition; f.f_devdata = &currdev; open_result = -1; if (load_type == -1) { printf(" Probing all disk devices...\n"); /* Try each disk in succession until one works. */ for (currdev.d_unit = 0; currdev.d_unit < UB_MAX_DEV; currdev.d_unit++) { print_disk_probe_info(); open_result = devsw[devidx]->dv_open(&f, &currdev); if (open_result == 0) { printf(" good.\n"); return (0); } printf("\n"); } return (-1); } if (load_unit == -1) { printf(" Probing all %s devices...\n", device_typename(load_type)); /* Try each disk of given type in succession until one works. */ for (unit = 0; unit < UB_MAX_DEV; unit++) { currdev.d_unit = uboot_diskgetunit(load_type, unit); if (currdev.d_unit == -1) break; print_disk_probe_info(); open_result = devsw[devidx]->dv_open(&f, &currdev); if (open_result == 0) { printf(" good.\n"); return (0); } printf("\n"); } return (-1); } if ((currdev.d_unit = uboot_diskgetunit(load_type, load_unit)) != -1) { print_disk_probe_info(); open_result = devsw[devidx]->dv_open(&f,&currdev); if (open_result == 0) { printf(" good.\n"); return (0); } printf("\n"); } printf(" Requested disk type/unit not found\n"); return (-1); } int main(void) { struct api_signature *sig = NULL; int load_type, load_unit, load_slice, load_partition; int i; const char * loaderdev; /* * If we can't find the magic signature and related info, exit with a * unique error code that U-Boot reports as "## Application terminated, * rc = 0xnnbadab1". Hopefully 'badab1' looks enough like "bad api" to * provide a clue. It's better than 0xffffffff anyway. */ if (!api_search_sig(&sig)) return (0x01badab1); syscall_ptr = sig->syscall; if (syscall_ptr == NULL) return (0x02badab1); if (sig->version > API_SIG_VERSION) return (0x03badab1); /* Clear BSS sections */ bzero(__sbss_start, __sbss_end - __sbss_start); bzero(__bss_start, _end - __bss_start); /* * Initialise the heap as early as possible. Once this is done, * alloc() is usable. The stack is buried inside us, so this is safe. */ setheap((void *)end, (void *)(end + 512 * 1024)); /* * Set up console. */ cons_probe(); printf("Compatible U-Boot API signature found @%x\n", (uint32_t)sig); printf("\n"); printf("%s, Revision %s\n", bootprog_name, bootprog_rev); printf("(%s, %s)\n", bootprog_maker, bootprog_date); printf("\n"); dump_sig(sig); dump_addr_info(); meminfo(); /* * Enumerate U-Boot devices */ if ((devs_no = ub_dev_enum()) == 0) panic("no U-Boot devices found"); printf("Number of U-Boot devices: %d\n", devs_no); get_load_device(&load_type, &load_unit, &load_slice, &load_partition); /* * March through the device switch probing for things. */ for (i = 0; devsw[i] != NULL; i++) { if (devsw[i]->dv_init == NULL) continue; if ((devsw[i]->dv_init)() != 0) continue; printf("Found U-Boot device: %s\n", devsw[i]->dv_name); currdev.d_dev = devsw[i]; currdev.d_type = currdev.d_dev->dv_type; currdev.d_unit = 0; if ((load_type == -1 || (load_type & DEV_TYP_STOR)) && strcmp(devsw[i]->dv_name, "disk") == 0) { if (probe_disks(i, load_type, load_unit, load_slice, load_partition) == 0) break; } if ((load_type == -1 || (load_type & DEV_TYP_NET)) && strcmp(devsw[i]->dv_name, "net") == 0) break; } /* * If we couldn't find a boot device, return an error to u-boot. * U-boot may be running a boot script that can try something different * so returning an error is better than forcing a reboot. */ if (devsw[i] == NULL) { printf("No boot device found!\n"); return (0xbadef1ce); } env_setenv("currdev", EV_VOLATILE, uboot_fmtdev(&currdev), uboot_setcurrdev, env_nounset); env_setenv("loaddev", EV_VOLATILE, uboot_fmtdev(&currdev), env_noset, env_nounset); setenv("LINES", "24", 1); /* optional */ setenv("prompt", "loader>", 1); archsw.arch_getdev = uboot_getdev; archsw.arch_copyin = uboot_copyin; archsw.arch_copyout = uboot_copyout; archsw.arch_readin = uboot_readin; archsw.arch_autoload = uboot_autoload; interact(NULL); /* doesn't return */ return (0); } COMMAND_SET(heap, "heap", "show heap usage", command_heap); static int command_heap(int argc, char *argv[]) { printf("heap base at %p, top at %p, used %d\n", end, sbrk(0), sbrk(0) - end); return (CMD_OK); } COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); static int command_reboot(int argc, char *argv[]) { printf("Resetting...\n"); ub_reset(); printf("Reset failed!\n"); while(1); } COMMAND_SET(devinfo, "devinfo", "show U-Boot devices", command_devinfo); static int command_devinfo(int argc, char *argv[]) { int i; if ((devs_no = ub_dev_enum()) == 0) { command_errmsg = "no U-Boot devices found!?"; return (CMD_ERROR); } printf("U-Boot devices:\n"); for (i = 0; i < devs_no; i++) { ub_dump_di(i); printf("\n"); } return (CMD_OK); } COMMAND_SET(sysinfo, "sysinfo", "show U-Boot system info", command_sysinfo); static int command_sysinfo(int argc, char *argv[]) { struct sys_info *si; if ((si = ub_get_sys_info()) == NULL) { command_errmsg = "could not retrieve U-Boot sys info!?"; return (CMD_ERROR); } printf("U-Boot system info:\n"); ub_dump_si(si); return (CMD_OK); } enum ubenv_action { UBENV_UNKNOWN, UBENV_SHOW, UBENV_IMPORT }; static void handle_uboot_env_var(enum ubenv_action action, const char * var) { const char * val; char ubv[128]; /* * If the user prepended "uboot." (which is how they usually see these * names) strip it off as a convenience. */ if (strncmp(var, "uboot.", 6) == 0) { snprintf(ubv, sizeof(ubv), "%s", &var[6]); var = ubv; } val = ub_env_get(var); if (action == UBENV_SHOW) { if (val == NULL) printf("uboot.%s is not set\n", var); else printf("uboot.%s=%s\n", var, val); } else if (action == UBENV_IMPORT) { if (val != NULL) { snprintf(ubv, sizeof(ubv), "uboot.%s", var); setenv(ubv, val, 1); } } } static int command_ubenv(int argc, char *argv[]) { enum ubenv_action action; const char *var; int i; action = UBENV_UNKNOWN; if (argc > 1) { if (strcasecmp(argv[1], "import") == 0) action = UBENV_IMPORT; else if (strcasecmp(argv[1], "show") == 0) action = UBENV_SHOW; } if (action == UBENV_UNKNOWN) { command_errmsg = "usage: 'ubenv [var ...]"; return (CMD_ERROR); } if (argc > 2) { for (i = 2; i < argc; i++) handle_uboot_env_var(action, argv[i]); } else { var = NULL; for (;;) { if ((var = ub_env_enum(var)) == NULL) break; handle_uboot_env_var(action, var); } } return (CMD_OK); } COMMAND_SET(ubenv, "ubenv", "show or import U-Boot env vars", command_ubenv); #ifdef LOADER_FDT_SUPPORT /* * Since proper fdt command handling function is defined in fdt_loader_cmd.c, * and declaring it as extern is in contradiction with COMMAND_SET() macro * (which uses static pointer), we're defining wrapper function, which * calls the proper fdt handling routine. */ static int command_fdt(int argc, char *argv[]) { return (command_fdt_internal(argc, argv)); } COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt); #endif Index: projects/sendfile/sys/boot =================================================================== --- projects/sendfile/sys/boot (revision 276056) +++ projects/sendfile/sys/boot (revision 276057) Property changes on: projects/sendfile/sys/boot ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/sys/boot:r275989-276056 Index: projects/sendfile/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c =================================================================== --- projects/sendfile/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (revision 276056) +++ projects/sendfile/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (revision 276057) @@ -1,7188 +1,7193 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014 by Delphix. All rights reserved. * Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ /* Portions Copyright 2007 Jeremy Teo */ /* Portions Copyright 2010 Robert Milkowski */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Programming rules. * * Each vnode op performs some logical unit of work. To do this, the ZPL must * properly lock its in-core state, create a DMU transaction, do the work, * record this work in the intent log (ZIL), commit the DMU transaction, * and wait for the intent log to commit if it is a synchronous operation. * Moreover, the vnode ops must work in both normal and log replay context. * The ordering of events is important to avoid deadlocks and references * to freed memory. The example below illustrates the following Big Rules: * * (1) A check must be made in each zfs thread for a mounted file system. * This is done avoiding races using ZFS_ENTER(zfsvfs). * A ZFS_EXIT(zfsvfs) is needed before all returns. Any znodes * must be checked with ZFS_VERIFY_ZP(zp). Both of these macros * can return EIO from the calling function. * * (2) VN_RELE() should always be the last thing except for zil_commit() * (if necessary) and ZFS_EXIT(). This is for 3 reasons: * First, if it's the last reference, the vnode/znode * can be freed, so the zp may point to freed memory. Second, the last * reference will call zfs_zinactive(), which may induce a lot of work -- * pushing cached pages (which acquires range locks) and syncing out * cached atime changes. Third, zfs_zinactive() may require a new tx, * which could deadlock the system if you were already holding one. * If you must call VN_RELE() within a tx then use VN_RELE_ASYNC(). * * (3) All range locks must be grabbed before calling dmu_tx_assign(), * as they can span dmu_tx_assign() calls. * * (4) If ZPL locks are held, pass TXG_NOWAIT as the second argument to * dmu_tx_assign(). This is critical because we don't want to block * while holding locks. * * If no ZPL locks are held (aside from ZFS_ENTER()), use TXG_WAIT. This * reduces lock contention and CPU usage when we must wait (note that if * throughput is constrained by the storage, nearly every transaction * must wait). * * Note, in particular, that if a lock is sometimes acquired before * the tx assigns, and sometimes after (e.g. z_lock), then failing * to use a non-blocking assign can deadlock the system. The scenario: * * Thread A has grabbed a lock before calling dmu_tx_assign(). * Thread B is in an already-assigned tx, and blocks for this lock. * Thread A calls dmu_tx_assign(TXG_WAIT) and blocks in txg_wait_open() * forever, because the previous txg can't quiesce until B's tx commits. * * If dmu_tx_assign() returns ERESTART and zfsvfs->z_assign is TXG_NOWAIT, * then drop all locks, call dmu_tx_wait(), and try again. On subsequent * calls to dmu_tx_assign(), pass TXG_WAITED rather than TXG_NOWAIT, * to indicate that this operation has already called dmu_tx_wait(). * This will ensure that we don't retry forever, waiting a short bit * each time. * * (5) If the operation succeeded, generate the intent log entry for it * before dropping locks. This ensures that the ordering of events * in the intent log matches the order in which they actually occurred. * During ZIL replay the zfs_log_* functions will update the sequence * number to indicate the zil transaction has replayed. * * (6) At the end of each vnode op, the DMU tx must always commit, * regardless of whether there were any errors. * * (7) After dropping all locks, invoke zil_commit(zilog, foid) * to ensure that synchronous semantics are provided when necessary. * * In general, this is how things should be ordered in each vnode op: * * ZFS_ENTER(zfsvfs); // exit if unmounted * top: * zfs_dirent_lock(&dl, ...) // lock directory entry (may VN_HOLD()) * rw_enter(...); // grab any other locks you need * tx = dmu_tx_create(...); // get DMU tx * dmu_tx_hold_*(); // hold each object you might modify * error = dmu_tx_assign(tx, waited ? TXG_WAITED : TXG_NOWAIT); * if (error) { * rw_exit(...); // drop locks * zfs_dirent_unlock(dl); // unlock directory entry * VN_RELE(...); // release held vnodes * if (error == ERESTART) { * waited = B_TRUE; * dmu_tx_wait(tx); * dmu_tx_abort(tx); * goto top; * } * dmu_tx_abort(tx); // abort DMU tx * ZFS_EXIT(zfsvfs); // finished in zfs * return (error); // really out of space * } * error = do_real_work(); // do whatever this VOP does * if (error == 0) * zfs_log_*(...); // on success, make ZIL entry * dmu_tx_commit(tx); // commit DMU tx -- error or not * rw_exit(...); // drop locks * zfs_dirent_unlock(dl); // unlock directory entry * VN_RELE(...); // release held vnodes * zil_commit(zilog, foid); // synchronous when necessary * ZFS_EXIT(zfsvfs); // finished in zfs * return (error); // done, report error */ /* ARGSUSED */ static int zfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct) { znode_t *zp = VTOZ(*vpp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); if ((flag & FWRITE) && (zp->z_pflags & ZFS_APPENDONLY) && ((flag & FAPPEND) == 0)) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EPERM)); } if (!zfs_has_ctldir(zp) && zp->z_zfsvfs->z_vscan && ZTOV(zp)->v_type == VREG && !(zp->z_pflags & ZFS_AV_QUARANTINED) && zp->z_size > 0) { if (fs_vscan(*vpp, cr, 0) != 0) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EACCES)); } } /* Keep a count of the synchronous opens in the znode */ if (flag & (FSYNC | FDSYNC)) atomic_inc_32(&zp->z_sync_cnt); ZFS_EXIT(zfsvfs); return (0); } /* ARGSUSED */ static int zfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr, caller_context_t *ct) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; /* * Clean up any locks held by this process on the vp. */ cleanlocks(vp, ddi_get_pid(), 0); cleanshares(vp, ddi_get_pid()); ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); /* Decrement the synchronous opens in the znode */ if ((flag & (FSYNC | FDSYNC)) && (count == 1)) atomic_dec_32(&zp->z_sync_cnt); if (!zfs_has_ctldir(zp) && zp->z_zfsvfs->z_vscan && ZTOV(zp)->v_type == VREG && !(zp->z_pflags & ZFS_AV_QUARANTINED) && zp->z_size > 0) VERIFY(fs_vscan(vp, cr, 1) == 0); ZFS_EXIT(zfsvfs); return (0); } /* * Lseek support for finding holes (cmd == _FIO_SEEK_HOLE) and * data (cmd == _FIO_SEEK_DATA). "off" is an in/out parameter. */ static int zfs_holey(vnode_t *vp, u_long cmd, offset_t *off) { znode_t *zp = VTOZ(vp); uint64_t noff = (uint64_t)*off; /* new offset */ uint64_t file_sz; int error; boolean_t hole; file_sz = zp->z_size; if (noff >= file_sz) { return (SET_ERROR(ENXIO)); } if (cmd == _FIO_SEEK_HOLE) hole = B_TRUE; else hole = B_FALSE; error = dmu_offset_next(zp->z_zfsvfs->z_os, zp->z_id, hole, &noff); if (error == ESRCH) return (SET_ERROR(ENXIO)); /* * We could find a hole that begins after the logical end-of-file, * because dmu_offset_next() only works on whole blocks. If the * EOF falls mid-block, then indicate that the "virtual hole" * at the end of the file begins at the logical EOF, rather than * at the end of the last block. */ if (noff > file_sz) { ASSERT(hole); noff = file_sz; } if (noff < *off) return (error); *off = noff; return (error); } /* ARGSUSED */ static int zfs_ioctl(vnode_t *vp, u_long com, intptr_t data, int flag, cred_t *cred, int *rvalp, caller_context_t *ct) { offset_t off; int error; zfsvfs_t *zfsvfs; znode_t *zp; switch (com) { case _FIOFFS: return (0); /* * The following two ioctls are used by bfu. Faking out, * necessary to avoid bfu errors. */ case _FIOGDIO: case _FIOSDIO: return (0); case _FIO_SEEK_DATA: case _FIO_SEEK_HOLE: #ifdef sun if (ddi_copyin((void *)data, &off, sizeof (off), flag)) return (SET_ERROR(EFAULT)); #else off = *(offset_t *)data; #endif zp = VTOZ(vp); zfsvfs = zp->z_zfsvfs; ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); /* offset parameter is in/out */ error = zfs_holey(vp, com, &off); ZFS_EXIT(zfsvfs); if (error) return (error); #ifdef sun if (ddi_copyout(&off, (void *)data, sizeof (off), flag)) return (SET_ERROR(EFAULT)); #else *(offset_t *)data = off; #endif return (0); } return (SET_ERROR(ENOTTY)); } static vm_page_t page_busy(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes) { vm_object_t obj; vm_page_t pp; int64_t end; /* * At present vm_page_clear_dirty extends the cleared range to DEV_BSIZE * aligned boundaries, if the range is not aligned. As a result a * DEV_BSIZE subrange with partially dirty data may get marked as clean. * It may happen that all DEV_BSIZE subranges are marked clean and thus * the whole page would be considred clean despite have some dirty data. * For this reason we should shrink the range to DEV_BSIZE aligned * boundaries before calling vm_page_clear_dirty. */ end = rounddown2(off + nbytes, DEV_BSIZE); off = roundup2(off, DEV_BSIZE); nbytes = end - off; obj = vp->v_object; zfs_vmobject_assert_wlocked(obj); for (;;) { if ((pp = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && pp->valid) { if (vm_page_xbusied(pp)) { /* * Reference the page before unlocking and * sleeping so that the page daemon is less * likely to reclaim it. */ vm_page_reference(pp); vm_page_lock(pp); zfs_vmobject_wunlock(obj); vm_page_busy_sleep(pp, "zfsmwb"); zfs_vmobject_wlock(obj); continue; } vm_page_sbusy(pp); } else if (pp == NULL) { pp = vm_page_alloc(obj, OFF_TO_IDX(start), VM_ALLOC_SYSTEM | VM_ALLOC_IFCACHED | VM_ALLOC_SBUSY); } else { ASSERT(pp != NULL && !pp->valid); pp = NULL; } if (pp != NULL) { ASSERT3U(pp->valid, ==, VM_PAGE_BITS_ALL); vm_object_pip_add(obj, 1); pmap_remove_write(pp); if (nbytes != 0) vm_page_clear_dirty(pp, off, nbytes); } break; } return (pp); } static void page_unbusy(vm_page_t pp) { vm_page_sunbusy(pp); vm_object_pip_subtract(pp->object, 1); } static vm_page_t page_hold(vnode_t *vp, int64_t start) { vm_object_t obj; vm_page_t pp; obj = vp->v_object; zfs_vmobject_assert_wlocked(obj); for (;;) { if ((pp = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && pp->valid) { if (vm_page_xbusied(pp)) { /* * Reference the page before unlocking and * sleeping so that the page daemon is less * likely to reclaim it. */ vm_page_reference(pp); vm_page_lock(pp); zfs_vmobject_wunlock(obj); vm_page_busy_sleep(pp, "zfsmwb"); zfs_vmobject_wlock(obj); continue; } ASSERT3U(pp->valid, ==, VM_PAGE_BITS_ALL); vm_page_lock(pp); vm_page_hold(pp); vm_page_unlock(pp); } else pp = NULL; break; } return (pp); } static void page_unhold(vm_page_t pp) { vm_page_lock(pp); vm_page_unhold(pp); vm_page_unlock(pp); } /* * When a file is memory mapped, we must keep the IO data synchronized * between the DMU cache and the memory mapped pages. What this means: * * On Write: If we find a memory mapped page, we write to *both* * the page and the dmu buffer. */ static void update_pages(vnode_t *vp, int64_t start, int len, objset_t *os, uint64_t oid, int segflg, dmu_tx_t *tx) { vm_object_t obj; struct sf_buf *sf; caddr_t va; int off; ASSERT(segflg != UIO_NOCOPY); ASSERT(vp->v_mount != NULL); obj = vp->v_object; ASSERT(obj != NULL); off = start & PAGEOFFSET; zfs_vmobject_wlock(obj); for (start &= PAGEMASK; len > 0; start += PAGESIZE) { vm_page_t pp; int nbytes = imin(PAGESIZE - off, len); if ((pp = page_busy(vp, start, off, nbytes)) != NULL) { zfs_vmobject_wunlock(obj); va = zfs_map_page(pp, &sf); (void) dmu_read(os, oid, start+off, nbytes, va+off, DMU_READ_PREFETCH);; zfs_unmap_page(sf); zfs_vmobject_wlock(obj); page_unbusy(pp); } len -= nbytes; off = 0; } vm_object_pip_wakeupn(obj, 0); zfs_vmobject_wunlock(obj); } /* * Read with UIO_NOCOPY flag means that sendfile(2) requests * ZFS to populate a range of page cache pages with data. * * NOTE: this function could be optimized to pre-allocate * all pages in advance, drain exclusive busy on all of them, * map them into contiguous KVA region and populate them * in one single dmu_read() call. */ static int mappedread_sf(vnode_t *vp, int nbytes, uio_t *uio) { znode_t *zp = VTOZ(vp); objset_t *os = zp->z_zfsvfs->z_os; struct sf_buf *sf; vm_object_t obj; vm_page_t pp; int64_t start; caddr_t va; int len = nbytes; int off; int error = 0; ASSERT(uio->uio_segflg == UIO_NOCOPY); ASSERT(vp->v_mount != NULL); obj = vp->v_object; ASSERT(obj != NULL); ASSERT((uio->uio_loffset & PAGEOFFSET) == 0); zfs_vmobject_wlock(obj); for (start = uio->uio_loffset; len > 0; start += PAGESIZE) { int bytes = MIN(PAGESIZE, len); pp = vm_page_grab(obj, OFF_TO_IDX(start), VM_ALLOC_SBUSY | VM_ALLOC_NORMAL | VM_ALLOC_IGN_SBUSY); if (pp->valid == 0) { zfs_vmobject_wunlock(obj); va = zfs_map_page(pp, &sf); error = dmu_read(os, zp->z_id, start, bytes, va, DMU_READ_PREFETCH); if (bytes != PAGESIZE && error == 0) bzero(va + bytes, PAGESIZE - bytes); zfs_unmap_page(sf); zfs_vmobject_wlock(obj); vm_page_sunbusy(pp); vm_page_lock(pp); if (error) { if (pp->wire_count == 0 && pp->valid == 0 && !vm_page_busied(pp)) vm_page_free(pp); } else { pp->valid = VM_PAGE_BITS_ALL; vm_page_activate(pp); } vm_page_unlock(pp); } else { ASSERT3U(pp->valid, ==, VM_PAGE_BITS_ALL); vm_page_sunbusy(pp); } if (error) break; uio->uio_resid -= bytes; uio->uio_offset += bytes; len -= bytes; } zfs_vmobject_wunlock(obj); return (error); } /* * When a file is memory mapped, we must keep the IO data synchronized * between the DMU cache and the memory mapped pages. What this means: * * On Read: We "read" preferentially from memory mapped pages, * else we default from the dmu buffer. * * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when * the file is memory mapped. */ static int mappedread(vnode_t *vp, int nbytes, uio_t *uio) { znode_t *zp = VTOZ(vp); vm_object_t obj; int64_t start; caddr_t va; int len = nbytes; int off; int error = 0; ASSERT(vp->v_mount != NULL); obj = vp->v_object; ASSERT(obj != NULL); start = uio->uio_loffset; off = start & PAGEOFFSET; zfs_vmobject_wlock(obj); for (start &= PAGEMASK; len > 0; start += PAGESIZE) { vm_page_t pp; uint64_t bytes = MIN(PAGESIZE - off, len); if (pp = page_hold(vp, start)) { struct sf_buf *sf; caddr_t va; zfs_vmobject_wunlock(obj); va = zfs_map_page(pp, &sf); error = uiomove(va + off, bytes, UIO_READ, uio); zfs_unmap_page(sf); zfs_vmobject_wlock(obj); page_unhold(pp); } else { zfs_vmobject_wunlock(obj); error = dmu_read_uio_dbuf(sa_get_db(zp->z_sa_hdl), uio, bytes); zfs_vmobject_wlock(obj); } len -= bytes; off = 0; if (error) break; } zfs_vmobject_wunlock(obj); return (error); } offset_t zfs_read_chunk_size = 1024 * 1024; /* Tunable */ /* * Read bytes from specified file into supplied buffer. * * IN: vp - vnode of file to be read from. * uio - structure supplying read location, range info, * and return buffer. * ioflag - SYNC flags; used to provide FRSYNC semantics. * cr - credentials of caller. * ct - caller context * * OUT: uio - updated offset and range, buffer filled. * * RETURN: 0 on success, error code on failure. * * Side Effects: * vp - atime updated if byte count > 0 */ /* ARGSUSED */ static int zfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; ssize_t n, nbytes; int error = 0; rl_t *rl; xuio_t *xuio = NULL; ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); if (zp->z_pflags & ZFS_AV_QUARANTINED) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EACCES)); } /* * Validate file offset */ if (uio->uio_loffset < (offset_t)0) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EINVAL)); } /* * Fasttrack empty reads */ if (uio->uio_resid == 0) { ZFS_EXIT(zfsvfs); return (0); } /* * Check for mandatory locks */ if (MANDMODE(zp->z_mode)) { if (error = chklock(vp, FREAD, uio->uio_loffset, uio->uio_resid, uio->uio_fmode, ct)) { ZFS_EXIT(zfsvfs); return (error); } } /* * If we're in FRSYNC mode, sync out this znode before reading it. */ if (zfsvfs->z_log && (ioflag & FRSYNC || zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)) zil_commit(zfsvfs->z_log, zp->z_id); /* * Lock the range against changes. */ rl = zfs_range_lock(zp, uio->uio_loffset, uio->uio_resid, RL_READER); /* * If we are reading past end-of-file we can skip * to the end; but we might still need to set atime. */ if (uio->uio_loffset >= zp->z_size) { error = 0; goto out; } ASSERT(uio->uio_loffset < zp->z_size); n = MIN(uio->uio_resid, zp->z_size - uio->uio_loffset); #ifdef sun if ((uio->uio_extflg == UIO_XUIO) && (((xuio_t *)uio)->xu_type == UIOTYPE_ZEROCOPY)) { int nblk; int blksz = zp->z_blksz; uint64_t offset = uio->uio_loffset; xuio = (xuio_t *)uio; if ((ISP2(blksz))) { nblk = (P2ROUNDUP(offset + n, blksz) - P2ALIGN(offset, blksz)) / blksz; } else { ASSERT(offset + n <= blksz); nblk = 1; } (void) dmu_xuio_init(xuio, nblk); if (vn_has_cached_data(vp)) { /* * For simplicity, we always allocate a full buffer * even if we only expect to read a portion of a block. */ while (--nblk >= 0) { (void) dmu_xuio_add(xuio, dmu_request_arcbuf(sa_get_db(zp->z_sa_hdl), blksz), 0, blksz); } } } #endif /* sun */ while (n > 0) { nbytes = MIN(n, zfs_read_chunk_size - P2PHASE(uio->uio_loffset, zfs_read_chunk_size)); #ifdef __FreeBSD__ if (uio->uio_segflg == UIO_NOCOPY) error = mappedread_sf(vp, nbytes, uio); else #endif /* __FreeBSD__ */ if (vn_has_cached_data(vp)) { error = mappedread(vp, nbytes, uio); } else { error = dmu_read_uio_dbuf(sa_get_db(zp->z_sa_hdl), uio, nbytes); } if (error) { /* convert checksum errors into IO errors */ if (error == ECKSUM) error = SET_ERROR(EIO); break; } n -= nbytes; } out: zfs_range_unlock(rl); ZFS_ACCESSTIME_STAMP(zfsvfs, zp); ZFS_EXIT(zfsvfs); return (error); } /* * Write the bytes to a file. * * IN: vp - vnode of file to be written to. * uio - structure supplying write location, range info, * and data buffer. * ioflag - FAPPEND, FSYNC, and/or FDSYNC. FAPPEND is * set if in append mode. * cr - credentials of caller. * ct - caller context (NFS/CIFS fem monitor only) * * OUT: uio - updated offset and range. * * RETURN: 0 on success, error code on failure. * * Timestamps: * vp - ctime|mtime updated if byte count > 0 */ /* ARGSUSED */ static int zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct) { znode_t *zp = VTOZ(vp); rlim64_t limit = MAXOFFSET_T; ssize_t start_resid = uio->uio_resid; ssize_t tx_bytes; uint64_t end_size; dmu_tx_t *tx; zfsvfs_t *zfsvfs = zp->z_zfsvfs; zilog_t *zilog; offset_t woff; ssize_t n, nbytes; rl_t *rl; int max_blksz = zfsvfs->z_max_blksz; int error = 0; arc_buf_t *abuf; iovec_t *aiov = NULL; xuio_t *xuio = NULL; int i_iov = 0; int iovcnt = uio->uio_iovcnt; iovec_t *iovp = uio->uio_iov; int write_eof; int count = 0; sa_bulk_attr_t bulk[4]; uint64_t mtime[2], ctime[2]; /* * Fasttrack empty write */ n = start_resid; if (n == 0) return (0); if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T) limit = MAXOFFSET_T; ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, &mtime, 16); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, 16); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL, &zp->z_size, 8); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL, &zp->z_pflags, 8); /* * In a case vp->v_vfsp != zp->z_zfsvfs->z_vfs (e.g. snapshots) our * callers might not be able to detect properly that we are read-only, * so check it explicitly here. */ if (zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EROFS)); } /* * If immutable or not appending then return EPERM */ if ((zp->z_pflags & (ZFS_IMMUTABLE | ZFS_READONLY)) || ((zp->z_pflags & ZFS_APPENDONLY) && !(ioflag & FAPPEND) && (uio->uio_loffset < zp->z_size))) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EPERM)); } zilog = zfsvfs->z_log; /* * Validate file offset */ woff = ioflag & FAPPEND ? zp->z_size : uio->uio_loffset; if (woff < 0) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EINVAL)); } /* * Check for mandatory locks before calling zfs_range_lock() * in order to prevent a deadlock with locks set via fcntl(). */ if (MANDMODE((mode_t)zp->z_mode) && (error = chklock(vp, FWRITE, woff, n, uio->uio_fmode, ct)) != 0) { ZFS_EXIT(zfsvfs); return (error); } #ifdef sun /* * Pre-fault the pages to ensure slow (eg NFS) pages * don't hold up txg. * Skip this if uio contains loaned arc_buf. */ if ((uio->uio_extflg == UIO_XUIO) && (((xuio_t *)uio)->xu_type == UIOTYPE_ZEROCOPY)) xuio = (xuio_t *)uio; else uio_prefaultpages(MIN(n, max_blksz), uio); #endif /* sun */ /* * If in append mode, set the io offset pointer to eof. */ if (ioflag & FAPPEND) { /* * Obtain an appending range lock to guarantee file append * semantics. We reset the write offset once we have the lock. */ rl = zfs_range_lock(zp, 0, n, RL_APPEND); woff = rl->r_off; if (rl->r_len == UINT64_MAX) { /* * We overlocked the file because this write will cause * the file block size to increase. * Note that zp_size cannot change with this lock held. */ woff = zp->z_size; } uio->uio_loffset = woff; } else { /* * Note that if the file block size will change as a result of * this write, then this range lock will lock the entire file * so that we can re-write the block safely. */ rl = zfs_range_lock(zp, woff, n, RL_WRITER); } if (vn_rlimit_fsize(vp, uio, uio->uio_td)) { zfs_range_unlock(rl); ZFS_EXIT(zfsvfs); return (EFBIG); } if (woff >= limit) { zfs_range_unlock(rl); ZFS_EXIT(zfsvfs); return (SET_ERROR(EFBIG)); } if ((woff + n) > limit || woff > (limit - n)) n = limit - woff; /* Will this write extend the file length? */ write_eof = (woff + n > zp->z_size); end_size = MAX(zp->z_size, woff + n); /* * Write the file in reasonable size chunks. Each chunk is written * in a separate transaction; this keeps the intent log records small * and allows us to do more fine-grained space accounting. */ while (n > 0) { abuf = NULL; woff = uio->uio_loffset; if (zfs_owner_overquota(zfsvfs, zp, B_FALSE) || zfs_owner_overquota(zfsvfs, zp, B_TRUE)) { if (abuf != NULL) dmu_return_arcbuf(abuf); error = SET_ERROR(EDQUOT); break; } if (xuio && abuf == NULL) { ASSERT(i_iov < iovcnt); aiov = &iovp[i_iov]; abuf = dmu_xuio_arcbuf(xuio, i_iov); dmu_xuio_clear(xuio, i_iov); DTRACE_PROBE3(zfs_cp_write, int, i_iov, iovec_t *, aiov, arc_buf_t *, abuf); ASSERT((aiov->iov_base == abuf->b_data) || ((char *)aiov->iov_base - (char *)abuf->b_data + aiov->iov_len == arc_buf_size(abuf))); i_iov++; } else if (abuf == NULL && n >= max_blksz && woff >= zp->z_size && P2PHASE(woff, max_blksz) == 0 && zp->z_blksz == max_blksz) { /* * This write covers a full block. "Borrow" a buffer * from the dmu so that we can fill it before we enter * a transaction. This avoids the possibility of * holding up the transaction if the data copy hangs * up on a pagefault (e.g., from an NFS server mapping). */ size_t cbytes; abuf = dmu_request_arcbuf(sa_get_db(zp->z_sa_hdl), max_blksz); ASSERT(abuf != NULL); ASSERT(arc_buf_size(abuf) == max_blksz); if (error = uiocopy(abuf->b_data, max_blksz, UIO_WRITE, uio, &cbytes)) { dmu_return_arcbuf(abuf); break; } ASSERT(cbytes == max_blksz); } /* * Start a transaction. */ tx = dmu_tx_create(zfsvfs->z_os); dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); dmu_tx_hold_write(tx, zp->z_id, woff, MIN(n, max_blksz)); zfs_sa_upgrade_txholds(tx, zp); error = dmu_tx_assign(tx, TXG_WAIT); if (error) { dmu_tx_abort(tx); if (abuf != NULL) dmu_return_arcbuf(abuf); break; } /* * If zfs_range_lock() over-locked we grow the blocksize * and then reduce the lock range. This will only happen * on the first iteration since zfs_range_reduce() will * shrink down r_len to the appropriate size. */ if (rl->r_len == UINT64_MAX) { uint64_t new_blksz; if (zp->z_blksz > max_blksz) { /* * File's blocksize is already larger than the * "recordsize" property. Only let it grow to * the next power of 2. */ ASSERT(!ISP2(zp->z_blksz)); new_blksz = MIN(end_size, 1 << highbit64(zp->z_blksz)); } else { new_blksz = MIN(end_size, max_blksz); } zfs_grow_blocksize(zp, new_blksz, tx); zfs_range_reduce(rl, woff, n); } /* * XXX - should we really limit each write to z_max_blksz? * Perhaps we should use SPA_MAXBLOCKSIZE chunks? */ nbytes = MIN(n, max_blksz - P2PHASE(woff, max_blksz)); if (woff + nbytes > zp->z_size) vnode_pager_setsize(vp, woff + nbytes); if (abuf == NULL) { tx_bytes = uio->uio_resid; error = dmu_write_uio_dbuf(sa_get_db(zp->z_sa_hdl), uio, nbytes, tx); tx_bytes -= uio->uio_resid; } else { tx_bytes = nbytes; ASSERT(xuio == NULL || tx_bytes == aiov->iov_len); /* * If this is not a full block write, but we are * extending the file past EOF and this data starts * block-aligned, use assign_arcbuf(). Otherwise, * write via dmu_write(). */ if (tx_bytes < max_blksz && (!write_eof || aiov->iov_base != abuf->b_data)) { ASSERT(xuio); dmu_write(zfsvfs->z_os, zp->z_id, woff, aiov->iov_len, aiov->iov_base, tx); dmu_return_arcbuf(abuf); xuio_stat_wbuf_copied(); } else { ASSERT(xuio || tx_bytes == max_blksz); dmu_assign_arcbuf(sa_get_db(zp->z_sa_hdl), woff, abuf, tx); } ASSERT(tx_bytes <= uio->uio_resid); uioskip(uio, tx_bytes); } if (tx_bytes && vn_has_cached_data(vp)) { update_pages(vp, woff, tx_bytes, zfsvfs->z_os, zp->z_id, uio->uio_segflg, tx); } /* * If we made no progress, we're done. If we made even * partial progress, update the znode and ZIL accordingly. */ if (tx_bytes == 0) { (void) sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zfsvfs), (void *)&zp->z_size, sizeof (uint64_t), tx); dmu_tx_commit(tx); ASSERT(error != 0); break; } /* * Clear Set-UID/Set-GID bits on successful write if not * privileged and at least one of the excute bits is set. * * It would be nice to to this after all writes have * been done, but that would still expose the ISUID/ISGID * to another app after the partial write is committed. * * Note: we don't call zfs_fuid_map_id() here because * user 0 is not an ephemeral uid. */ mutex_enter(&zp->z_acl_lock); if ((zp->z_mode & (S_IXUSR | (S_IXUSR >> 3) | (S_IXUSR >> 6))) != 0 && (zp->z_mode & (S_ISUID | S_ISGID)) != 0 && secpolicy_vnode_setid_retain(vp, cr, (zp->z_mode & S_ISUID) != 0 && zp->z_uid == 0) != 0) { uint64_t newmode; zp->z_mode &= ~(S_ISUID | S_ISGID); newmode = zp->z_mode; (void) sa_update(zp->z_sa_hdl, SA_ZPL_MODE(zfsvfs), (void *)&newmode, sizeof (uint64_t), tx); } mutex_exit(&zp->z_acl_lock); zfs_tstamp_update_setup(zp, CONTENT_MODIFIED, mtime, ctime, B_TRUE); /* * Update the file size (zp_size) if it has changed; * account for possible concurrent updates. */ while ((end_size = zp->z_size) < uio->uio_loffset) { (void) atomic_cas_64(&zp->z_size, end_size, uio->uio_loffset); ASSERT(error == 0); } /* * If we are replaying and eof is non zero then force * the file size to the specified eof. Note, there's no * concurrency during replay. */ if (zfsvfs->z_replay && zfsvfs->z_replay_eof != 0) zp->z_size = zfsvfs->z_replay_eof; error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx); zfs_log_write(zilog, tx, TX_WRITE, zp, woff, tx_bytes, ioflag); dmu_tx_commit(tx); if (error != 0) break; ASSERT(tx_bytes == nbytes); n -= nbytes; #ifdef sun if (!xuio && n > 0) uio_prefaultpages(MIN(n, max_blksz), uio); #endif /* sun */ } zfs_range_unlock(rl); /* * If we're in replay mode, or we made no progress, return error. * Otherwise, it's at least a partial write, so it's successful. */ if (zfsvfs->z_replay || uio->uio_resid == start_resid) { ZFS_EXIT(zfsvfs); return (error); } if (ioflag & (FSYNC | FDSYNC) || zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) zil_commit(zilog, zp->z_id); ZFS_EXIT(zfsvfs); return (0); } void zfs_get_done(zgd_t *zgd, int error) { znode_t *zp = zgd->zgd_private; objset_t *os = zp->z_zfsvfs->z_os; if (zgd->zgd_db) dmu_buf_rele(zgd->zgd_db, zgd); zfs_range_unlock(zgd->zgd_rl); /* * Release the vnode asynchronously as we currently have the * txg stopped from syncing. */ VN_RELE_ASYNC(ZTOV(zp), dsl_pool_vnrele_taskq(dmu_objset_pool(os))); if (error == 0 && zgd->zgd_bp) zil_add_block(zgd->zgd_zilog, zgd->zgd_bp); kmem_free(zgd, sizeof (zgd_t)); } #ifdef DEBUG static int zil_fault_io = 0; #endif /* * Get data to generate a TX_WRITE intent log record. */ int zfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio) { zfsvfs_t *zfsvfs = arg; objset_t *os = zfsvfs->z_os; znode_t *zp; uint64_t object = lr->lr_foid; uint64_t offset = lr->lr_offset; uint64_t size = lr->lr_length; blkptr_t *bp = &lr->lr_blkptr; dmu_buf_t *db; zgd_t *zgd; int error = 0; ASSERT(zio != NULL); ASSERT(size != 0); /* * Nothing to do if the file has been removed */ if (zfs_zget(zfsvfs, object, &zp) != 0) return (SET_ERROR(ENOENT)); if (zp->z_unlinked) { /* * Release the vnode asynchronously as we currently have the * txg stopped from syncing. */ VN_RELE_ASYNC(ZTOV(zp), dsl_pool_vnrele_taskq(dmu_objset_pool(os))); return (SET_ERROR(ENOENT)); } zgd = (zgd_t *)kmem_zalloc(sizeof (zgd_t), KM_SLEEP); zgd->zgd_zilog = zfsvfs->z_log; zgd->zgd_private = zp; /* * Write records come in two flavors: immediate and indirect. * For small writes it's cheaper to store the data with the * log record (immediate); for large writes it's cheaper to * sync the data and get a pointer to it (indirect) so that * we don't have to write the data twice. */ if (buf != NULL) { /* immediate write */ zgd->zgd_rl = zfs_range_lock(zp, offset, size, RL_READER); /* test for truncation needs to be done while range locked */ if (offset >= zp->z_size) { error = SET_ERROR(ENOENT); } else { error = dmu_read(os, object, offset, size, buf, DMU_READ_NO_PREFETCH); } ASSERT(error == 0 || error == ENOENT); } else { /* indirect write */ /* * Have to lock the whole block to ensure when it's * written out and it's checksum is being calculated * that no one can change the data. We need to re-check * blocksize after we get the lock in case it's changed! */ for (;;) { uint64_t blkoff; size = zp->z_blksz; blkoff = ISP2(size) ? P2PHASE(offset, size) : offset; offset -= blkoff; zgd->zgd_rl = zfs_range_lock(zp, offset, size, RL_READER); if (zp->z_blksz == size) break; offset += blkoff; zfs_range_unlock(zgd->zgd_rl); } /* test for truncation needs to be done while range locked */ if (lr->lr_offset >= zp->z_size) error = SET_ERROR(ENOENT); #ifdef DEBUG if (zil_fault_io) { error = SET_ERROR(EIO); zil_fault_io = 0; } #endif if (error == 0) error = dmu_buf_hold(os, object, offset, zgd, &db, DMU_READ_NO_PREFETCH); if (error == 0) { blkptr_t *obp = dmu_buf_get_blkptr(db); if (obp) { ASSERT(BP_IS_HOLE(bp)); *bp = *obp; } zgd->zgd_db = db; zgd->zgd_bp = bp; ASSERT(db->db_offset == offset); ASSERT(db->db_size == size); error = dmu_sync(zio, lr->lr_common.lrc_txg, zfs_get_done, zgd); ASSERT(error || lr->lr_length <= zp->z_blksz); /* * On success, we need to wait for the write I/O * initiated by dmu_sync() to complete before we can * release this dbuf. We will finish everything up * in the zfs_get_done() callback. */ if (error == 0) return (0); if (error == EALREADY) { lr->lr_common.lrc_txtype = TX_WRITE2; error = 0; } } } zfs_get_done(zgd, error); return (error); } /*ARGSUSED*/ static int zfs_access(vnode_t *vp, int mode, int flag, cred_t *cr, caller_context_t *ct) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; int error; ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); if (flag & V_ACE_MASK) error = zfs_zaccess(zp, mode, flag, B_FALSE, cr); else error = zfs_zaccess_rwx(zp, mode, flag, cr); ZFS_EXIT(zfsvfs); return (error); } /* * If vnode is for a device return a specfs vnode instead. */ static int specvp_check(vnode_t **vpp, cred_t *cr) { int error = 0; if (IS_DEVVP(*vpp)) { struct vnode *svp; svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr); VN_RELE(*vpp); if (svp == NULL) error = SET_ERROR(ENOSYS); *vpp = svp; } return (error); } /* * Lookup an entry in a directory, or an extended attribute directory. * If it exists, return a held vnode reference for it. * * IN: dvp - vnode of directory to search. * nm - name of entry to lookup. * pnp - full pathname to lookup [UNUSED]. * flags - LOOKUP_XATTR set if looking for an attribute. * rdir - root directory vnode [UNUSED]. * cr - credentials of caller. * ct - caller context * direntflags - directory lookup flags * realpnp - returned pathname. * * OUT: vpp - vnode of located entry, NULL if not found. * * RETURN: 0 on success, error code on failure. * * Timestamps: * NA */ /* ARGSUSED */ static int zfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct componentname *cnp, int nameiop, cred_t *cr, kthread_t *td, int flags) { znode_t *zdp = VTOZ(dvp); zfsvfs_t *zfsvfs = zdp->z_zfsvfs; int error = 0; int *direntflags = NULL; void *realpnp = NULL; /* fast path */ if (!(flags & (LOOKUP_XATTR | FIGNORECASE))) { if (dvp->v_type != VDIR) { return (SET_ERROR(ENOTDIR)); } else if (zdp->z_sa_hdl == NULL) { return (SET_ERROR(EIO)); } if (nm[0] == 0 || (nm[0] == '.' && nm[1] == '\0')) { error = zfs_fastaccesschk_execute(zdp, cr); if (!error) { *vpp = dvp; VN_HOLD(*vpp); return (0); } return (error); } else { vnode_t *tvp = dnlc_lookup(dvp, nm); if (tvp) { error = zfs_fastaccesschk_execute(zdp, cr); if (error) { VN_RELE(tvp); return (error); } if (tvp == DNLC_NO_VNODE) { VN_RELE(tvp); return (SET_ERROR(ENOENT)); } else { *vpp = tvp; return (specvp_check(vpp, cr)); } } } } DTRACE_PROBE2(zfs__fastpath__lookup__miss, vnode_t *, dvp, char *, nm); ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zdp); *vpp = NULL; if (flags & LOOKUP_XATTR) { #ifdef TODO /* * If the xattr property is off, refuse the lookup request. */ if (!(zfsvfs->z_vfs->vfs_flag & VFS_XATTR)) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EINVAL)); } #endif /* * We don't allow recursive attributes.. * Maybe someday we will. */ if (zdp->z_pflags & ZFS_XATTR) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EINVAL)); } if (error = zfs_get_xattrdir(VTOZ(dvp), vpp, cr, flags)) { ZFS_EXIT(zfsvfs); return (error); } /* * Do we have permission to get into attribute directory? */ if (error = zfs_zaccess(VTOZ(*vpp), ACE_EXECUTE, 0, B_FALSE, cr)) { VN_RELE(*vpp); *vpp = NULL; } ZFS_EXIT(zfsvfs); return (error); } if (dvp->v_type != VDIR) { ZFS_EXIT(zfsvfs); return (SET_ERROR(ENOTDIR)); } /* * Check accessibility of directory. */ if (error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr)) { ZFS_EXIT(zfsvfs); return (error); } if (zfsvfs->z_utf8 && u8_validate(nm, strlen(nm), NULL, U8_VALIDATE_ENTIRE, &error) < 0) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EILSEQ)); } error = zfs_dirlook(zdp, nm, vpp, flags, direntflags, realpnp); if (error == 0) error = specvp_check(vpp, cr); /* Translate errors and add SAVENAME when needed. */ if (cnp->cn_flags & ISLASTCN) { switch (nameiop) { case CREATE: case RENAME: if (error == ENOENT) { error = EJUSTRETURN; cnp->cn_flags |= SAVENAME; break; } /* FALLTHROUGH */ case DELETE: if (error == 0) cnp->cn_flags |= SAVENAME; break; } } if (error == 0 && (nm[0] != '.' || nm[1] != '\0')) { int ltype = 0; if (cnp->cn_flags & ISDOTDOT) { ltype = VOP_ISLOCKED(dvp); VOP_UNLOCK(dvp, 0); } ZFS_EXIT(zfsvfs); error = vn_lock(*vpp, cnp->cn_lkflags); if (cnp->cn_flags & ISDOTDOT) vn_lock(dvp, ltype | LK_RETRY); if (error != 0) { VN_RELE(*vpp); *vpp = NULL; return (error); } } else { ZFS_EXIT(zfsvfs); } #ifdef FREEBSD_NAMECACHE /* * Insert name into cache (as non-existent) if appropriate. */ if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) != 0) cache_enter(dvp, *vpp, cnp); /* * Insert name into cache if appropriate. */ if (error == 0 && (cnp->cn_flags & MAKEENTRY)) { if (!(cnp->cn_flags & ISLASTCN) || (nameiop != DELETE && nameiop != RENAME)) { cache_enter(dvp, *vpp, cnp); } } #endif return (error); } /* * Attempt to create a new entry in a directory. If the entry * already exists, truncate the file if permissible, else return * an error. Return the vp of the created or trunc'd file. * * IN: dvp - vnode of directory to put new file entry in. * name - name of new file entry. * vap - attributes of new file. * excl - flag indicating exclusive or non-exclusive mode. * mode - mode to open file with. * cr - credentials of caller. * flag - large file flag [UNUSED]. * ct - caller context * vsecp - ACL to be set * * OUT: vpp - vnode of created or trunc'd entry. * * RETURN: 0 on success, error code on failure. * * Timestamps: * dvp - ctime|mtime updated if new entry created * vp - ctime|mtime always, atime if new */ /* ARGSUSED */ static int zfs_create(vnode_t *dvp, char *name, vattr_t *vap, int excl, int mode, vnode_t **vpp, cred_t *cr, kthread_t *td) { znode_t *zp, *dzp = VTOZ(dvp); zfsvfs_t *zfsvfs = dzp->z_zfsvfs; zilog_t *zilog; objset_t *os; zfs_dirlock_t *dl; dmu_tx_t *tx; int error; ksid_t *ksid; uid_t uid; gid_t gid = crgetgid(cr); zfs_acl_ids_t acl_ids; boolean_t fuid_dirtied; boolean_t have_acl = B_FALSE; boolean_t waited = B_FALSE; void *vsecp = NULL; int flag = 0; /* * If we have an ephemeral id, ACL, or XVATTR then * make sure file system is at proper version */ ksid = crgetsid(cr, KSID_OWNER); if (ksid) uid = ksid_getid(ksid); else uid = crgetuid(cr); if (zfsvfs->z_use_fuids == B_FALSE && (vsecp || (vap->va_mask & AT_XVATTR) || IS_EPHEMERAL(uid) || IS_EPHEMERAL(gid))) return (SET_ERROR(EINVAL)); ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(dzp); os = zfsvfs->z_os; zilog = zfsvfs->z_log; if (zfsvfs->z_utf8 && u8_validate(name, strlen(name), NULL, U8_VALIDATE_ENTIRE, &error) < 0) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EILSEQ)); } if (vap->va_mask & AT_XVATTR) { if ((error = secpolicy_xvattr(dvp, (xvattr_t *)vap, crgetuid(cr), cr, vap->va_type)) != 0) { ZFS_EXIT(zfsvfs); return (error); } } getnewvnode_reserve(1); top: *vpp = NULL; if ((vap->va_mode & S_ISVTX) && secpolicy_vnode_stky_modify(cr)) vap->va_mode &= ~S_ISVTX; if (*name == '\0') { /* * Null component name refers to the directory itself. */ VN_HOLD(dvp); zp = dzp; dl = NULL; error = 0; } else { /* possible VN_HOLD(zp) */ int zflg = 0; if (flag & FIGNORECASE) zflg |= ZCILOOK; error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg, NULL, NULL); if (error) { if (have_acl) zfs_acl_ids_free(&acl_ids); if (strcmp(name, "..") == 0) error = SET_ERROR(EISDIR); getnewvnode_drop_reserve(); ZFS_EXIT(zfsvfs); return (error); } } if (zp == NULL) { uint64_t txtype; /* * Create a new file object and update the directory * to reference it. */ if (error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr)) { if (have_acl) zfs_acl_ids_free(&acl_ids); goto out; } /* * We only support the creation of regular files in * extended attribute directories. */ if ((dzp->z_pflags & ZFS_XATTR) && (vap->va_type != VREG)) { if (have_acl) zfs_acl_ids_free(&acl_ids); error = SET_ERROR(EINVAL); goto out; } if (!have_acl && (error = zfs_acl_ids_create(dzp, 0, vap, cr, vsecp, &acl_ids)) != 0) goto out; have_acl = B_TRUE; if (zfs_acl_ids_overquota(zfsvfs, &acl_ids)) { zfs_acl_ids_free(&acl_ids); error = SET_ERROR(EDQUOT); goto out; } tx = dmu_tx_create(os); dmu_tx_hold_sa_create(tx, acl_ids.z_aclp->z_acl_bytes + ZFS_SA_BASE_ATTR_SIZE); fuid_dirtied = zfsvfs->z_fuid_dirty; if (fuid_dirtied) zfs_fuid_txhold(zfsvfs, tx); dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name); dmu_tx_hold_sa(tx, dzp->z_sa_hdl, B_FALSE); if (!zfsvfs->z_use_sa && acl_ids.z_aclp->z_acl_bytes > ZFS_ACE_SPACE) { dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, acl_ids.z_aclp->z_acl_bytes); } error = dmu_tx_assign(tx, waited ? TXG_WAITED : TXG_NOWAIT); if (error) { zfs_dirent_unlock(dl); if (error == ERESTART) { waited = B_TRUE; dmu_tx_wait(tx); dmu_tx_abort(tx); goto top; } zfs_acl_ids_free(&acl_ids); dmu_tx_abort(tx); getnewvnode_drop_reserve(); ZFS_EXIT(zfsvfs); return (error); } zfs_mknode(dzp, vap, tx, cr, 0, &zp, &acl_ids); if (fuid_dirtied) zfs_fuid_sync(zfsvfs, tx); (void) zfs_link_create(dl, zp, tx, ZNEW); txtype = zfs_log_create_txtype(Z_FILE, vsecp, vap); if (flag & FIGNORECASE) txtype |= TX_CI; zfs_log_create(zilog, tx, txtype, dzp, zp, name, vsecp, acl_ids.z_fuidp, vap); zfs_acl_ids_free(&acl_ids); dmu_tx_commit(tx); } else { int aflags = (flag & FAPPEND) ? V_APPEND : 0; if (have_acl) zfs_acl_ids_free(&acl_ids); have_acl = B_FALSE; /* * A directory entry already exists for this name. */ /* * Can't truncate an existing file if in exclusive mode. */ if (excl == EXCL) { error = SET_ERROR(EEXIST); goto out; } /* * Can't open a directory for writing. */ if ((ZTOV(zp)->v_type == VDIR) && (mode & S_IWRITE)) { error = SET_ERROR(EISDIR); goto out; } /* * Verify requested access to file. */ if (mode && (error = zfs_zaccess_rwx(zp, mode, aflags, cr))) { goto out; } mutex_enter(&dzp->z_lock); dzp->z_seq++; mutex_exit(&dzp->z_lock); /* * Truncate regular files if requested. */ if ((ZTOV(zp)->v_type == VREG) && (vap->va_mask & AT_SIZE) && (vap->va_size == 0)) { /* we can't hold any locks when calling zfs_freesp() */ zfs_dirent_unlock(dl); dl = NULL; error = zfs_freesp(zp, 0, 0, mode, TRUE); if (error == 0) { vnevent_create(ZTOV(zp), ct); } } } out: getnewvnode_drop_reserve(); if (dl) zfs_dirent_unlock(dl); if (error) { if (zp) VN_RELE(ZTOV(zp)); } else { *vpp = ZTOV(zp); error = specvp_check(vpp, cr); } if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) zil_commit(zilog, 0); ZFS_EXIT(zfsvfs); return (error); } /* * Remove an entry from a directory. * * IN: dvp - vnode of directory to remove entry from. * name - name of entry to remove. * cr - credentials of caller. * ct - caller context * flags - case flags * * RETURN: 0 on success, error code on failure. * * Timestamps: * dvp - ctime|mtime * vp - ctime (if nlink > 0) */ uint64_t null_xattr = 0; /*ARGSUSED*/ static int zfs_remove(vnode_t *dvp, char *name, cred_t *cr, caller_context_t *ct, int flags) { znode_t *zp, *dzp = VTOZ(dvp); znode_t *xzp; vnode_t *vp; zfsvfs_t *zfsvfs = dzp->z_zfsvfs; zilog_t *zilog; uint64_t acl_obj, xattr_obj; uint64_t xattr_obj_unlinked = 0; uint64_t obj = 0; zfs_dirlock_t *dl; dmu_tx_t *tx; boolean_t may_delete_now, delete_now = FALSE; boolean_t unlinked, toobig = FALSE; uint64_t txtype; pathname_t *realnmp = NULL; pathname_t realnm; int error; int zflg = ZEXISTS; boolean_t waited = B_FALSE; ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(dzp); zilog = zfsvfs->z_log; if (flags & FIGNORECASE) { zflg |= ZCILOOK; pn_alloc(&realnm); realnmp = &realnm; } top: xattr_obj = 0; xzp = NULL; /* * Attempt to lock directory; fail if entry doesn't exist. */ if (error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg, NULL, realnmp)) { if (realnmp) pn_free(realnmp); ZFS_EXIT(zfsvfs); return (error); } vp = ZTOV(zp); if (error = zfs_zaccess_delete(dzp, zp, cr)) { goto out; } /* * Need to use rmdir for removing directories. */ if (vp->v_type == VDIR) { error = SET_ERROR(EPERM); goto out; } vnevent_remove(vp, dvp, name, ct); if (realnmp) dnlc_remove(dvp, realnmp->pn_buf); else dnlc_remove(dvp, name); VI_LOCK(vp); may_delete_now = vp->v_count == 1 && !vn_has_cached_data(vp); VI_UNLOCK(vp); /* * We may delete the znode now, or we may put it in the unlinked set; * it depends on whether we're the last link, and on whether there are * other holds on the vnode. So we dmu_tx_hold() the right things to * allow for either case. */ obj = zp->z_id; tx = dmu_tx_create(zfsvfs->z_os); dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name); dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); zfs_sa_upgrade_txholds(tx, zp); zfs_sa_upgrade_txholds(tx, dzp); if (may_delete_now) { toobig = zp->z_size > zp->z_blksz * DMU_MAX_DELETEBLKCNT; /* if the file is too big, only hold_free a token amount */ dmu_tx_hold_free(tx, zp->z_id, 0, (toobig ? DMU_MAX_ACCESS : DMU_OBJECT_END)); } /* are there any extended attributes? */ error = sa_lookup(zp->z_sa_hdl, SA_ZPL_XATTR(zfsvfs), &xattr_obj, sizeof (xattr_obj)); if (error == 0 && xattr_obj) { error = zfs_zget(zfsvfs, xattr_obj, &xzp); ASSERT0(error); dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE); dmu_tx_hold_sa(tx, xzp->z_sa_hdl, B_FALSE); } mutex_enter(&zp->z_lock); if ((acl_obj = zfs_external_acl(zp)) != 0 && may_delete_now) dmu_tx_hold_free(tx, acl_obj, 0, DMU_OBJECT_END); mutex_exit(&zp->z_lock); /* charge as an update -- would be nice not to charge at all */ dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); /* * Mark this transaction as typically resulting in a net free of * space, unless object removal will be delayed indefinitely * (due to active holds on the vnode due to the file being open). */ if (may_delete_now) dmu_tx_mark_netfree(tx); error = dmu_tx_assign(tx, waited ? TXG_WAITED : TXG_NOWAIT); if (error) { zfs_dirent_unlock(dl); VN_RELE(vp); if (xzp) VN_RELE(ZTOV(xzp)); if (error == ERESTART) { waited = B_TRUE; dmu_tx_wait(tx); dmu_tx_abort(tx); goto top; } if (realnmp) pn_free(realnmp); dmu_tx_abort(tx); ZFS_EXIT(zfsvfs); return (error); } /* * Remove the directory entry. */ error = zfs_link_destroy(dl, zp, tx, zflg, &unlinked); if (error) { dmu_tx_commit(tx); goto out; } if (unlinked) { /* * Hold z_lock so that we can make sure that the ACL obj * hasn't changed. Could have been deleted due to * zfs_sa_upgrade(). */ mutex_enter(&zp->z_lock); VI_LOCK(vp); (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_XATTR(zfsvfs), &xattr_obj_unlinked, sizeof (xattr_obj_unlinked)); delete_now = may_delete_now && !toobig && vp->v_count == 1 && !vn_has_cached_data(vp) && xattr_obj == xattr_obj_unlinked && zfs_external_acl(zp) == acl_obj; VI_UNLOCK(vp); } if (delete_now) { #ifdef __FreeBSD__ panic("zfs_remove: delete_now branch taken"); #endif if (xattr_obj_unlinked) { ASSERT3U(xzp->z_links, ==, 2); mutex_enter(&xzp->z_lock); xzp->z_unlinked = 1; xzp->z_links = 0; error = sa_update(xzp->z_sa_hdl, SA_ZPL_LINKS(zfsvfs), &xzp->z_links, sizeof (xzp->z_links), tx); ASSERT3U(error, ==, 0); mutex_exit(&xzp->z_lock); zfs_unlinked_add(xzp, tx); if (zp->z_is_sa) error = sa_remove(zp->z_sa_hdl, SA_ZPL_XATTR(zfsvfs), tx); else error = sa_update(zp->z_sa_hdl, SA_ZPL_XATTR(zfsvfs), &null_xattr, sizeof (uint64_t), tx); ASSERT0(error); } VI_LOCK(vp); vp->v_count--; ASSERT0(vp->v_count); VI_UNLOCK(vp); mutex_exit(&zp->z_lock); zfs_znode_delete(zp, tx); } else if (unlinked) { mutex_exit(&zp->z_lock); zfs_unlinked_add(zp, tx); #ifdef __FreeBSD__ vp->v_vflag |= VV_NOSYNC; #endif } txtype = TX_REMOVE; if (flags & FIGNORECASE) txtype |= TX_CI; zfs_log_remove(zilog, tx, txtype, dzp, name, obj); dmu_tx_commit(tx); out: if (realnmp) pn_free(realnmp); zfs_dirent_unlock(dl); if (!delete_now) VN_RELE(vp); if (xzp) VN_RELE(ZTOV(xzp)); if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) zil_commit(zilog, 0); ZFS_EXIT(zfsvfs); return (error); } /* * Create a new directory and insert it into dvp using the name * provided. Return a pointer to the inserted directory. * * IN: dvp - vnode of directory to add subdir to. * dirname - name of new directory. * vap - attributes of new directory. * cr - credentials of caller. * ct - caller context * flags - case flags * vsecp - ACL to be set * * OUT: vpp - vnode of created directory. * * RETURN: 0 on success, error code on failure. * * Timestamps: * dvp - ctime|mtime updated * vp - ctime|mtime|atime updated */ /*ARGSUSED*/ static int zfs_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp) { znode_t *zp, *dzp = VTOZ(dvp); zfsvfs_t *zfsvfs = dzp->z_zfsvfs; zilog_t *zilog; zfs_dirlock_t *dl; uint64_t txtype; dmu_tx_t *tx; int error; int zf = ZNEW; ksid_t *ksid; uid_t uid; gid_t gid = crgetgid(cr); zfs_acl_ids_t acl_ids; boolean_t fuid_dirtied; boolean_t waited = B_FALSE; ASSERT(vap->va_type == VDIR); /* * If we have an ephemeral id, ACL, or XVATTR then * make sure file system is at proper version */ ksid = crgetsid(cr, KSID_OWNER); if (ksid) uid = ksid_getid(ksid); else uid = crgetuid(cr); if (zfsvfs->z_use_fuids == B_FALSE && (vsecp || (vap->va_mask & AT_XVATTR) || IS_EPHEMERAL(uid) || IS_EPHEMERAL(gid))) return (SET_ERROR(EINVAL)); ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(dzp); zilog = zfsvfs->z_log; if (dzp->z_pflags & ZFS_XATTR) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EINVAL)); } if (zfsvfs->z_utf8 && u8_validate(dirname, strlen(dirname), NULL, U8_VALIDATE_ENTIRE, &error) < 0) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EILSEQ)); } if (flags & FIGNORECASE) zf |= ZCILOOK; if (vap->va_mask & AT_XVATTR) { if ((error = secpolicy_xvattr(dvp, (xvattr_t *)vap, crgetuid(cr), cr, vap->va_type)) != 0) { ZFS_EXIT(zfsvfs); return (error); } } if ((error = zfs_acl_ids_create(dzp, 0, vap, cr, vsecp, &acl_ids)) != 0) { ZFS_EXIT(zfsvfs); return (error); } getnewvnode_reserve(1); /* * First make sure the new directory doesn't exist. * * Existence is checked first to make sure we don't return * EACCES instead of EEXIST which can cause some applications * to fail. */ top: *vpp = NULL; if (error = zfs_dirent_lock(&dl, dzp, dirname, &zp, zf, NULL, NULL)) { zfs_acl_ids_free(&acl_ids); getnewvnode_drop_reserve(); ZFS_EXIT(zfsvfs); return (error); } if (error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr)) { zfs_acl_ids_free(&acl_ids); zfs_dirent_unlock(dl); getnewvnode_drop_reserve(); ZFS_EXIT(zfsvfs); return (error); } if (zfs_acl_ids_overquota(zfsvfs, &acl_ids)) { zfs_acl_ids_free(&acl_ids); zfs_dirent_unlock(dl); getnewvnode_drop_reserve(); ZFS_EXIT(zfsvfs); return (SET_ERROR(EDQUOT)); } /* * Add a new entry to the directory. */ tx = dmu_tx_create(zfsvfs->z_os); dmu_tx_hold_zap(tx, dzp->z_id, TRUE, dirname); dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL); fuid_dirtied = zfsvfs->z_fuid_dirty; if (fuid_dirtied) zfs_fuid_txhold(zfsvfs, tx); if (!zfsvfs->z_use_sa && acl_ids.z_aclp->z_acl_bytes > ZFS_ACE_SPACE) { dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, acl_ids.z_aclp->z_acl_bytes); } dmu_tx_hold_sa_create(tx, acl_ids.z_aclp->z_acl_bytes + ZFS_SA_BASE_ATTR_SIZE); error = dmu_tx_assign(tx, waited ? TXG_WAITED : TXG_NOWAIT); if (error) { zfs_dirent_unlock(dl); if (error == ERESTART) { waited = B_TRUE; dmu_tx_wait(tx); dmu_tx_abort(tx); goto top; } zfs_acl_ids_free(&acl_ids); dmu_tx_abort(tx); getnewvnode_drop_reserve(); ZFS_EXIT(zfsvfs); return (error); } /* * Create new node. */ zfs_mknode(dzp, vap, tx, cr, 0, &zp, &acl_ids); if (fuid_dirtied) zfs_fuid_sync(zfsvfs, tx); /* * Now put new name in parent dir. */ (void) zfs_link_create(dl, zp, tx, ZNEW); *vpp = ZTOV(zp); txtype = zfs_log_create_txtype(Z_DIR, vsecp, vap); if (flags & FIGNORECASE) txtype |= TX_CI; zfs_log_create(zilog, tx, txtype, dzp, zp, dirname, vsecp, acl_ids.z_fuidp, vap); zfs_acl_ids_free(&acl_ids); dmu_tx_commit(tx); getnewvnode_drop_reserve(); zfs_dirent_unlock(dl); if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) zil_commit(zilog, 0); ZFS_EXIT(zfsvfs); return (0); } /* * Remove a directory subdir entry. If the current working * directory is the same as the subdir to be removed, the * remove will fail. * * IN: dvp - vnode of directory to remove from. * name - name of directory to be removed. * cwd - vnode of current working directory. * cr - credentials of caller. * ct - caller context * flags - case flags * * RETURN: 0 on success, error code on failure. * * Timestamps: * dvp - ctime|mtime updated */ /*ARGSUSED*/ static int zfs_rmdir(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr, caller_context_t *ct, int flags) { znode_t *dzp = VTOZ(dvp); znode_t *zp; vnode_t *vp; zfsvfs_t *zfsvfs = dzp->z_zfsvfs; zilog_t *zilog; zfs_dirlock_t *dl; dmu_tx_t *tx; int error; int zflg = ZEXISTS; boolean_t waited = B_FALSE; ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(dzp); zilog = zfsvfs->z_log; if (flags & FIGNORECASE) zflg |= ZCILOOK; top: zp = NULL; /* * Attempt to lock directory; fail if entry doesn't exist. */ if (error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg, NULL, NULL)) { ZFS_EXIT(zfsvfs); return (error); } vp = ZTOV(zp); if (error = zfs_zaccess_delete(dzp, zp, cr)) { goto out; } if (vp->v_type != VDIR) { error = SET_ERROR(ENOTDIR); goto out; } if (vp == cwd) { error = SET_ERROR(EINVAL); goto out; } vnevent_rmdir(vp, dvp, name, ct); /* * Grab a lock on the directory to make sure that noone is * trying to add (or lookup) entries while we are removing it. */ rw_enter(&zp->z_name_lock, RW_WRITER); /* * Grab a lock on the parent pointer to make sure we play well * with the treewalk and directory rename code. */ rw_enter(&zp->z_parent_lock, RW_WRITER); tx = dmu_tx_create(zfsvfs->z_os); dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name); dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); zfs_sa_upgrade_txholds(tx, zp); zfs_sa_upgrade_txholds(tx, dzp); error = dmu_tx_assign(tx, waited ? TXG_WAITED : TXG_NOWAIT); if (error) { rw_exit(&zp->z_parent_lock); rw_exit(&zp->z_name_lock); zfs_dirent_unlock(dl); VN_RELE(vp); if (error == ERESTART) { waited = B_TRUE; dmu_tx_wait(tx); dmu_tx_abort(tx); goto top; } dmu_tx_abort(tx); ZFS_EXIT(zfsvfs); return (error); } #ifdef FREEBSD_NAMECACHE cache_purge(dvp); #endif error = zfs_link_destroy(dl, zp, tx, zflg, NULL); if (error == 0) { uint64_t txtype = TX_RMDIR; if (flags & FIGNORECASE) txtype |= TX_CI; zfs_log_remove(zilog, tx, txtype, dzp, name, ZFS_NO_OBJECT); } dmu_tx_commit(tx); rw_exit(&zp->z_parent_lock); rw_exit(&zp->z_name_lock); #ifdef FREEBSD_NAMECACHE cache_purge(vp); #endif out: zfs_dirent_unlock(dl); VN_RELE(vp); if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) zil_commit(zilog, 0); ZFS_EXIT(zfsvfs); return (error); } /* * Read as many directory entries as will fit into the provided * buffer from the given directory cursor position (specified in * the uio structure). * * IN: vp - vnode of directory to read. * uio - structure supplying read location, range info, * and return buffer. * cr - credentials of caller. * ct - caller context * flags - case flags * * OUT: uio - updated offset and range, buffer filled. * eofp - set to true if end-of-file detected. * * RETURN: 0 on success, error code on failure. * * Timestamps: * vp - atime updated * * Note that the low 4 bits of the cookie returned by zap is always zero. * This allows us to use the low range for "special" directory entries: * We use 0 for '.', and 1 for '..'. If this is the root of the filesystem, * we use the offset 2 for the '.zfs' directory. */ /* ARGSUSED */ static int zfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, int *ncookies, u_long **cookies) { znode_t *zp = VTOZ(vp); iovec_t *iovp; edirent_t *eodp; dirent64_t *odp; zfsvfs_t *zfsvfs = zp->z_zfsvfs; objset_t *os; caddr_t outbuf; size_t bufsize; zap_cursor_t zc; zap_attribute_t zap; uint_t bytes_wanted; uint64_t offset; /* must be unsigned; checks for < 1 */ uint64_t parent; int local_eof; int outcount; int error; uint8_t prefetch; boolean_t check_sysattrs; uint8_t type; int ncooks; u_long *cooks = NULL; int flags = 0; ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_PARENT(zfsvfs), &parent, sizeof (parent))) != 0) { ZFS_EXIT(zfsvfs); return (error); } /* * If we are not given an eof variable, * use a local one. */ if (eofp == NULL) eofp = &local_eof; /* * Check for valid iov_len. */ if (uio->uio_iov->iov_len <= 0) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EINVAL)); } /* * Quit if directory has been removed (posix) */ if ((*eofp = zp->z_unlinked) != 0) { ZFS_EXIT(zfsvfs); return (0); } error = 0; os = zfsvfs->z_os; offset = uio->uio_loffset; prefetch = zp->z_zn_prefetch; /* * Initialize the iterator cursor. */ if (offset <= 3) { /* * Start iteration from the beginning of the directory. */ zap_cursor_init(&zc, os, zp->z_id); } else { /* * The offset is a serialized cursor. */ zap_cursor_init_serialized(&zc, os, zp->z_id, offset); } /* * Get space to change directory entries into fs independent format. */ iovp = uio->uio_iov; bytes_wanted = iovp->iov_len; if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) { bufsize = bytes_wanted; outbuf = kmem_alloc(bufsize, KM_SLEEP); odp = (struct dirent64 *)outbuf; } else { bufsize = bytes_wanted; outbuf = NULL; odp = (struct dirent64 *)iovp->iov_base; } eodp = (struct edirent *)odp; if (ncookies != NULL) { /* * Minimum entry size is dirent size and 1 byte for a file name. */ ncooks = uio->uio_resid / (sizeof(struct dirent) - sizeof(((struct dirent *)NULL)->d_name) + 1); cooks = malloc(ncooks * sizeof(u_long), M_TEMP, M_WAITOK); *cookies = cooks; *ncookies = ncooks; } /* * If this VFS supports the system attribute view interface; and * we're looking at an extended attribute directory; and we care * about normalization conflicts on this vfs; then we must check * for normalization conflicts with the sysattr name space. */ #ifdef TODO check_sysattrs = vfs_has_feature(vp->v_vfsp, VFSFT_SYSATTR_VIEWS) && (vp->v_flag & V_XATTRDIR) && zfsvfs->z_norm && (flags & V_RDDIR_ENTFLAGS); #else check_sysattrs = 0; #endif /* * Transform to file-system independent format */ outcount = 0; while (outcount < bytes_wanted) { ino64_t objnum; ushort_t reclen; off64_t *next = NULL; /* * Special case `.', `..', and `.zfs'. */ if (offset == 0) { (void) strcpy(zap.za_name, "."); zap.za_normalization_conflict = 0; objnum = zp->z_id; type = DT_DIR; } else if (offset == 1) { (void) strcpy(zap.za_name, ".."); zap.za_normalization_conflict = 0; objnum = parent; type = DT_DIR; } else if (offset == 2 && zfs_show_ctldir(zp)) { (void) strcpy(zap.za_name, ZFS_CTLDIR_NAME); zap.za_normalization_conflict = 0; objnum = ZFSCTL_INO_ROOT; type = DT_DIR; } else { /* * Grab next entry. */ if (error = zap_cursor_retrieve(&zc, &zap)) { if ((*eofp = (error == ENOENT)) != 0) break; else goto update; } if (zap.za_integer_length != 8 || zap.za_num_integers != 1) { cmn_err(CE_WARN, "zap_readdir: bad directory " "entry, obj = %lld, offset = %lld\n", (u_longlong_t)zp->z_id, (u_longlong_t)offset); error = SET_ERROR(ENXIO); goto update; } objnum = ZFS_DIRENT_OBJ(zap.za_first_integer); /* * MacOS X can extract the object type here such as: * uint8_t type = ZFS_DIRENT_TYPE(zap.za_first_integer); */ type = ZFS_DIRENT_TYPE(zap.za_first_integer); if (check_sysattrs && !zap.za_normalization_conflict) { #ifdef TODO zap.za_normalization_conflict = xattr_sysattr_casechk(zap.za_name); #else panic("%s:%u: TODO", __func__, __LINE__); #endif } } if (flags & V_RDDIR_ACCFILTER) { /* * If we have no access at all, don't include * this entry in the returned information */ znode_t *ezp; if (zfs_zget(zp->z_zfsvfs, objnum, &ezp) != 0) goto skip_entry; if (!zfs_has_access(ezp, cr)) { VN_RELE(ZTOV(ezp)); goto skip_entry; } VN_RELE(ZTOV(ezp)); } if (flags & V_RDDIR_ENTFLAGS) reclen = EDIRENT_RECLEN(strlen(zap.za_name)); else reclen = DIRENT64_RECLEN(strlen(zap.za_name)); /* * Will this entry fit in the buffer? */ if (outcount + reclen > bufsize) { /* * Did we manage to fit anything in the buffer? */ if (!outcount) { error = SET_ERROR(EINVAL); goto update; } break; } if (flags & V_RDDIR_ENTFLAGS) { /* * Add extended flag entry: */ eodp->ed_ino = objnum; eodp->ed_reclen = reclen; /* NOTE: ed_off is the offset for the *next* entry */ next = &(eodp->ed_off); eodp->ed_eflags = zap.za_normalization_conflict ? ED_CASE_CONFLICT : 0; (void) strncpy(eodp->ed_name, zap.za_name, EDIRENT_NAMELEN(reclen)); eodp = (edirent_t *)((intptr_t)eodp + reclen); } else { /* * Add normal entry: */ odp->d_ino = objnum; odp->d_reclen = reclen; odp->d_namlen = strlen(zap.za_name); (void) strlcpy(odp->d_name, zap.za_name, odp->d_namlen + 1); odp->d_type = type; odp = (dirent64_t *)((intptr_t)odp + reclen); } outcount += reclen; ASSERT(outcount <= bufsize); /* Prefetch znode */ if (prefetch) dmu_prefetch(os, objnum, 0, 0); skip_entry: /* * Move to the next entry, fill in the previous offset. */ if (offset > 2 || (offset == 2 && !zfs_show_ctldir(zp))) { zap_cursor_advance(&zc); offset = zap_cursor_serialize(&zc); } else { offset += 1; } if (cooks != NULL) { *cooks++ = offset; ncooks--; KASSERT(ncooks >= 0, ("ncookies=%d", ncooks)); } } zp->z_zn_prefetch = B_FALSE; /* a lookup will re-enable pre-fetching */ /* Subtract unused cookies */ if (ncookies != NULL) *ncookies -= ncooks; if (uio->uio_segflg == UIO_SYSSPACE && uio->uio_iovcnt == 1) { iovp->iov_base += outcount; iovp->iov_len -= outcount; uio->uio_resid -= outcount; } else if (error = uiomove(outbuf, (long)outcount, UIO_READ, uio)) { /* * Reset the pointer. */ offset = uio->uio_loffset; } update: zap_cursor_fini(&zc); if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) kmem_free(outbuf, bufsize); if (error == ENOENT) error = 0; ZFS_ACCESSTIME_STAMP(zfsvfs, zp); uio->uio_loffset = offset; ZFS_EXIT(zfsvfs); if (error != 0 && cookies != NULL) { free(*cookies, M_TEMP); *cookies = NULL; *ncookies = 0; } return (error); } ulong_t zfs_fsync_sync_cnt = 4; static int zfs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; (void) tsd_set(zfs_fsyncer_key, (void *)zfs_fsync_sync_cnt); if (zfsvfs->z_os->os_sync != ZFS_SYNC_DISABLED) { ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); zil_commit(zfsvfs->z_log, zp->z_id); ZFS_EXIT(zfsvfs); } return (0); } /* * Get the requested file attributes and place them in the provided * vattr structure. * * IN: vp - vnode of file. * vap - va_mask identifies requested attributes. * If AT_XVATTR set, then optional attrs are requested * flags - ATTR_NOACLCHECK (CIFS server context) * cr - credentials of caller. * ct - caller context * * OUT: vap - attribute values. * * RETURN: 0 (always succeeds). */ /* ARGSUSED */ static int zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, caller_context_t *ct) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; int error = 0; uint32_t blksize; u_longlong_t nblocks; uint64_t links; uint64_t mtime[2], ctime[2], crtime[2], rdev; xvattr_t *xvap = (xvattr_t *)vap; /* vap may be an xvattr_t * */ xoptattr_t *xoap = NULL; boolean_t skipaclchk = (flags & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE; sa_bulk_attr_t bulk[4]; int count = 0; ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); zfs_fuid_map_ids(zp, cr, &vap->va_uid, &vap->va_gid); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, &mtime, 16); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, 16); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CRTIME(zfsvfs), NULL, &crtime, 16); if (vp->v_type == VBLK || vp->v_type == VCHR) SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_RDEV(zfsvfs), NULL, &rdev, 8); if ((error = sa_bulk_lookup(zp->z_sa_hdl, bulk, count)) != 0) { ZFS_EXIT(zfsvfs); return (error); } /* * If ACL is trivial don't bother looking for ACE_READ_ATTRIBUTES. * Also, if we are the owner don't bother, since owner should * always be allowed to read basic attributes of file. */ if (!(zp->z_pflags & ZFS_ACL_TRIVIAL) && (vap->va_uid != crgetuid(cr))) { if (error = zfs_zaccess(zp, ACE_READ_ATTRIBUTES, 0, skipaclchk, cr)) { ZFS_EXIT(zfsvfs); return (error); } } /* * Return all attributes. It's cheaper to provide the answer * than to determine whether we were asked the question. */ mutex_enter(&zp->z_lock); vap->va_type = IFTOVT(zp->z_mode); vap->va_mode = zp->z_mode & ~S_IFMT; #ifdef sun vap->va_fsid = zp->z_zfsvfs->z_vfs->vfs_dev; #else vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; #endif vap->va_nodeid = zp->z_id; if ((vp->v_flag & VROOT) && zfs_show_ctldir(zp)) links = zp->z_links + 1; else links = zp->z_links; vap->va_nlink = MIN(links, LINK_MAX); /* nlink_t limit! */ vap->va_size = zp->z_size; #ifdef sun vap->va_rdev = vp->v_rdev; #else if (vp->v_type == VBLK || vp->v_type == VCHR) vap->va_rdev = zfs_cmpldev(rdev); #endif vap->va_seq = zp->z_seq; vap->va_flags = 0; /* FreeBSD: Reset chflags(2) flags. */ vap->va_filerev = zp->z_seq; /* * Add in any requested optional attributes and the create time. * Also set the corresponding bits in the returned attribute bitmap. */ if ((xoap = xva_getxoptattr(xvap)) != NULL && zfsvfs->z_use_fuids) { if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) { xoap->xoa_archive = ((zp->z_pflags & ZFS_ARCHIVE) != 0); XVA_SET_RTN(xvap, XAT_ARCHIVE); } if (XVA_ISSET_REQ(xvap, XAT_READONLY)) { xoap->xoa_readonly = ((zp->z_pflags & ZFS_READONLY) != 0); XVA_SET_RTN(xvap, XAT_READONLY); } if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) { xoap->xoa_system = ((zp->z_pflags & ZFS_SYSTEM) != 0); XVA_SET_RTN(xvap, XAT_SYSTEM); } if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) { xoap->xoa_hidden = ((zp->z_pflags & ZFS_HIDDEN) != 0); XVA_SET_RTN(xvap, XAT_HIDDEN); } if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) { xoap->xoa_nounlink = ((zp->z_pflags & ZFS_NOUNLINK) != 0); XVA_SET_RTN(xvap, XAT_NOUNLINK); } if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) { xoap->xoa_immutable = ((zp->z_pflags & ZFS_IMMUTABLE) != 0); XVA_SET_RTN(xvap, XAT_IMMUTABLE); } if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) { xoap->xoa_appendonly = ((zp->z_pflags & ZFS_APPENDONLY) != 0); XVA_SET_RTN(xvap, XAT_APPENDONLY); } if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) { xoap->xoa_nodump = ((zp->z_pflags & ZFS_NODUMP) != 0); XVA_SET_RTN(xvap, XAT_NODUMP); } if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) { xoap->xoa_opaque = ((zp->z_pflags & ZFS_OPAQUE) != 0); XVA_SET_RTN(xvap, XAT_OPAQUE); } if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) { xoap->xoa_av_quarantined = ((zp->z_pflags & ZFS_AV_QUARANTINED) != 0); XVA_SET_RTN(xvap, XAT_AV_QUARANTINED); } if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) { xoap->xoa_av_modified = ((zp->z_pflags & ZFS_AV_MODIFIED) != 0); XVA_SET_RTN(xvap, XAT_AV_MODIFIED); } if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP) && vp->v_type == VREG) { zfs_sa_get_scanstamp(zp, xvap); } if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) { uint64_t times[2]; (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(zfsvfs), times, sizeof (times)); ZFS_TIME_DECODE(&xoap->xoa_createtime, times); XVA_SET_RTN(xvap, XAT_CREATETIME); } if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) { xoap->xoa_reparse = ((zp->z_pflags & ZFS_REPARSE) != 0); XVA_SET_RTN(xvap, XAT_REPARSE); } if (XVA_ISSET_REQ(xvap, XAT_GEN)) { xoap->xoa_generation = zp->z_gen; XVA_SET_RTN(xvap, XAT_GEN); } if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) { xoap->xoa_offline = ((zp->z_pflags & ZFS_OFFLINE) != 0); XVA_SET_RTN(xvap, XAT_OFFLINE); } if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) { xoap->xoa_sparse = ((zp->z_pflags & ZFS_SPARSE) != 0); XVA_SET_RTN(xvap, XAT_SPARSE); } } ZFS_TIME_DECODE(&vap->va_atime, zp->z_atime); ZFS_TIME_DECODE(&vap->va_mtime, mtime); ZFS_TIME_DECODE(&vap->va_ctime, ctime); ZFS_TIME_DECODE(&vap->va_birthtime, crtime); mutex_exit(&zp->z_lock); sa_object_size(zp->z_sa_hdl, &blksize, &nblocks); vap->va_blksize = blksize; vap->va_bytes = nblocks << 9; /* nblocks * 512 */ if (zp->z_blksz == 0) { /* * Block size hasn't been set; suggest maximal I/O transfers. */ vap->va_blksize = zfsvfs->z_max_blksz; } ZFS_EXIT(zfsvfs); return (0); } /* * Set the file attributes to the values contained in the * vattr structure. * * IN: vp - vnode of file to be modified. * vap - new attribute values. * If AT_XVATTR set, then optional attrs are being set * flags - ATTR_UTIME set if non-default time values provided. * - ATTR_NOACLCHECK (CIFS context only). * cr - credentials of caller. * ct - caller context * * RETURN: 0 on success, error code on failure. * * Timestamps: * vp - ctime updated, mtime updated if size changed. */ /* ARGSUSED */ static int zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, caller_context_t *ct) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; zilog_t *zilog; dmu_tx_t *tx; vattr_t oldva; xvattr_t tmpxvattr; uint_t mask = vap->va_mask; uint_t saved_mask = 0; uint64_t saved_mode; int trim_mask = 0; uint64_t new_mode; uint64_t new_uid, new_gid; uint64_t xattr_obj; uint64_t mtime[2], ctime[2]; znode_t *attrzp; int need_policy = FALSE; int err, err2; zfs_fuid_info_t *fuidp = NULL; xvattr_t *xvap = (xvattr_t *)vap; /* vap may be an xvattr_t * */ xoptattr_t *xoap; zfs_acl_t *aclp; boolean_t skipaclchk = (flags & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE; boolean_t fuid_dirtied = B_FALSE; sa_bulk_attr_t bulk[7], xattr_bulk[7]; int count = 0, xattr_count = 0; if (mask == 0) return (0); if (mask & AT_NOSET) return (SET_ERROR(EINVAL)); ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); zilog = zfsvfs->z_log; /* * Make sure that if we have ephemeral uid/gid or xvattr specified * that file system is at proper version level */ if (zfsvfs->z_use_fuids == B_FALSE && (((mask & AT_UID) && IS_EPHEMERAL(vap->va_uid)) || ((mask & AT_GID) && IS_EPHEMERAL(vap->va_gid)) || (mask & AT_XVATTR))) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EINVAL)); } if (mask & AT_SIZE && vp->v_type == VDIR) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EISDIR)); } if (mask & AT_SIZE && vp->v_type != VREG && vp->v_type != VFIFO) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EINVAL)); } /* * If this is an xvattr_t, then get a pointer to the structure of * optional attributes. If this is NULL, then we have a vattr_t. */ xoap = xva_getxoptattr(xvap); xva_init(&tmpxvattr); /* * Immutable files can only alter immutable bit and atime */ if ((zp->z_pflags & ZFS_IMMUTABLE) && ((mask & (AT_SIZE|AT_UID|AT_GID|AT_MTIME|AT_MODE)) || ((mask & AT_XVATTR) && XVA_ISSET_REQ(xvap, XAT_CREATETIME)))) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EPERM)); } if ((mask & AT_SIZE) && (zp->z_pflags & ZFS_READONLY)) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EPERM)); } /* * Verify timestamps doesn't overflow 32 bits. * ZFS can handle large timestamps, but 32bit syscalls can't * handle times greater than 2039. This check should be removed * once large timestamps are fully supported. */ if (mask & (AT_ATIME | AT_MTIME)) { if (((mask & AT_ATIME) && TIMESPEC_OVERFLOW(&vap->va_atime)) || ((mask & AT_MTIME) && TIMESPEC_OVERFLOW(&vap->va_mtime))) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EOVERFLOW)); } } top: attrzp = NULL; aclp = NULL; /* Can this be moved to before the top label? */ if (zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EROFS)); } /* * First validate permissions */ if (mask & AT_SIZE) { /* * XXX - Note, we are not providing any open * mode flags here (like FNDELAY), so we may * block if there are locks present... this * should be addressed in openat(). */ /* XXX - would it be OK to generate a log record here? */ err = zfs_freesp(zp, vap->va_size, 0, 0, FALSE); if (err) { ZFS_EXIT(zfsvfs); return (err); } } if (mask & (AT_ATIME|AT_MTIME) || ((mask & AT_XVATTR) && (XVA_ISSET_REQ(xvap, XAT_HIDDEN) || XVA_ISSET_REQ(xvap, XAT_READONLY) || XVA_ISSET_REQ(xvap, XAT_ARCHIVE) || XVA_ISSET_REQ(xvap, XAT_OFFLINE) || XVA_ISSET_REQ(xvap, XAT_SPARSE) || XVA_ISSET_REQ(xvap, XAT_CREATETIME) || XVA_ISSET_REQ(xvap, XAT_SYSTEM)))) { need_policy = zfs_zaccess(zp, ACE_WRITE_ATTRIBUTES, 0, skipaclchk, cr); } if (mask & (AT_UID|AT_GID)) { int idmask = (mask & (AT_UID|AT_GID)); int take_owner; int take_group; /* * NOTE: even if a new mode is being set, * we may clear S_ISUID/S_ISGID bits. */ if (!(mask & AT_MODE)) vap->va_mode = zp->z_mode; /* * Take ownership or chgrp to group we are a member of */ take_owner = (mask & AT_UID) && (vap->va_uid == crgetuid(cr)); take_group = (mask & AT_GID) && zfs_groupmember(zfsvfs, vap->va_gid, cr); /* * If both AT_UID and AT_GID are set then take_owner and * take_group must both be set in order to allow taking * ownership. * * Otherwise, send the check through secpolicy_vnode_setattr() * */ if (((idmask == (AT_UID|AT_GID)) && take_owner && take_group) || ((idmask == AT_UID) && take_owner) || ((idmask == AT_GID) && take_group)) { if (zfs_zaccess(zp, ACE_WRITE_OWNER, 0, skipaclchk, cr) == 0) { /* * Remove setuid/setgid for non-privileged users */ secpolicy_setid_clear(vap, vp, cr); trim_mask = (mask & (AT_UID|AT_GID)); } else { need_policy = TRUE; } } else { need_policy = TRUE; } } mutex_enter(&zp->z_lock); oldva.va_mode = zp->z_mode; zfs_fuid_map_ids(zp, cr, &oldva.va_uid, &oldva.va_gid); if (mask & AT_XVATTR) { /* * Update xvattr mask to include only those attributes * that are actually changing. * * the bits will be restored prior to actually setting * the attributes so the caller thinks they were set. */ if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) { if (xoap->xoa_appendonly != ((zp->z_pflags & ZFS_APPENDONLY) != 0)) { need_policy = TRUE; } else { XVA_CLR_REQ(xvap, XAT_APPENDONLY); XVA_SET_REQ(&tmpxvattr, XAT_APPENDONLY); } } if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) { if (xoap->xoa_nounlink != ((zp->z_pflags & ZFS_NOUNLINK) != 0)) { need_policy = TRUE; } else { XVA_CLR_REQ(xvap, XAT_NOUNLINK); XVA_SET_REQ(&tmpxvattr, XAT_NOUNLINK); } } if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) { if (xoap->xoa_immutable != ((zp->z_pflags & ZFS_IMMUTABLE) != 0)) { need_policy = TRUE; } else { XVA_CLR_REQ(xvap, XAT_IMMUTABLE); XVA_SET_REQ(&tmpxvattr, XAT_IMMUTABLE); } } if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) { if (xoap->xoa_nodump != ((zp->z_pflags & ZFS_NODUMP) != 0)) { need_policy = TRUE; } else { XVA_CLR_REQ(xvap, XAT_NODUMP); XVA_SET_REQ(&tmpxvattr, XAT_NODUMP); } } if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) { if (xoap->xoa_av_modified != ((zp->z_pflags & ZFS_AV_MODIFIED) != 0)) { need_policy = TRUE; } else { XVA_CLR_REQ(xvap, XAT_AV_MODIFIED); XVA_SET_REQ(&tmpxvattr, XAT_AV_MODIFIED); } } if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) { if ((vp->v_type != VREG && xoap->xoa_av_quarantined) || xoap->xoa_av_quarantined != ((zp->z_pflags & ZFS_AV_QUARANTINED) != 0)) { need_policy = TRUE; } else { XVA_CLR_REQ(xvap, XAT_AV_QUARANTINED); XVA_SET_REQ(&tmpxvattr, XAT_AV_QUARANTINED); } } if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) { mutex_exit(&zp->z_lock); ZFS_EXIT(zfsvfs); return (SET_ERROR(EPERM)); } if (need_policy == FALSE && (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP) || XVA_ISSET_REQ(xvap, XAT_OPAQUE))) { need_policy = TRUE; } } mutex_exit(&zp->z_lock); if (mask & AT_MODE) { if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr) == 0) { err = secpolicy_setid_setsticky_clear(vp, vap, &oldva, cr); if (err) { ZFS_EXIT(zfsvfs); return (err); } trim_mask |= AT_MODE; } else { need_policy = TRUE; } } if (need_policy) { /* * If trim_mask is set then take ownership * has been granted or write_acl is present and user * has the ability to modify mode. In that case remove * UID|GID and or MODE from mask so that * secpolicy_vnode_setattr() doesn't revoke it. */ if (trim_mask) { saved_mask = vap->va_mask; vap->va_mask &= ~trim_mask; if (trim_mask & AT_MODE) { /* * Save the mode, as secpolicy_vnode_setattr() * will overwrite it with ova.va_mode. */ saved_mode = vap->va_mode; } } err = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags, (int (*)(void *, int, cred_t *))zfs_zaccess_unix, zp); if (err) { ZFS_EXIT(zfsvfs); return (err); } if (trim_mask) { vap->va_mask |= saved_mask; if (trim_mask & AT_MODE) { /* * Recover the mode after * secpolicy_vnode_setattr(). */ vap->va_mode = saved_mode; } } } /* * secpolicy_vnode_setattr, or take ownership may have * changed va_mask */ mask = vap->va_mask; if ((mask & (AT_UID | AT_GID))) { err = sa_lookup(zp->z_sa_hdl, SA_ZPL_XATTR(zfsvfs), &xattr_obj, sizeof (xattr_obj)); if (err == 0 && xattr_obj) { err = zfs_zget(zp->z_zfsvfs, xattr_obj, &attrzp); if (err) goto out2; } if (mask & AT_UID) { new_uid = zfs_fuid_create(zfsvfs, (uint64_t)vap->va_uid, cr, ZFS_OWNER, &fuidp); if (new_uid != zp->z_uid && zfs_fuid_overquota(zfsvfs, B_FALSE, new_uid)) { if (attrzp) VN_RELE(ZTOV(attrzp)); err = SET_ERROR(EDQUOT); goto out2; } } if (mask & AT_GID) { new_gid = zfs_fuid_create(zfsvfs, (uint64_t)vap->va_gid, cr, ZFS_GROUP, &fuidp); if (new_gid != zp->z_gid && zfs_fuid_overquota(zfsvfs, B_TRUE, new_gid)) { if (attrzp) VN_RELE(ZTOV(attrzp)); err = SET_ERROR(EDQUOT); goto out2; } } } tx = dmu_tx_create(zfsvfs->z_os); if (mask & AT_MODE) { uint64_t pmode = zp->z_mode; uint64_t acl_obj; new_mode = (pmode & S_IFMT) | (vap->va_mode & ~S_IFMT); if (zp->z_zfsvfs->z_acl_mode == ZFS_ACL_RESTRICTED && !(zp->z_pflags & ZFS_ACL_TRIVIAL)) { err = SET_ERROR(EPERM); goto out; } if (err = zfs_acl_chmod_setattr(zp, &aclp, new_mode)) goto out; mutex_enter(&zp->z_lock); if (!zp->z_is_sa && ((acl_obj = zfs_external_acl(zp)) != 0)) { /* * Are we upgrading ACL from old V0 format * to V1 format? */ if (zfsvfs->z_version >= ZPL_VERSION_FUID && zfs_znode_acl_version(zp) == ZFS_ACL_VERSION_INITIAL) { dmu_tx_hold_free(tx, acl_obj, 0, DMU_OBJECT_END); dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, aclp->z_acl_bytes); } else { dmu_tx_hold_write(tx, acl_obj, 0, aclp->z_acl_bytes); } } else if (!zp->z_is_sa && aclp->z_acl_bytes > ZFS_ACE_SPACE) { dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, aclp->z_acl_bytes); } mutex_exit(&zp->z_lock); dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE); } else { if ((mask & AT_XVATTR) && XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE); else dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); } if (attrzp) { dmu_tx_hold_sa(tx, attrzp->z_sa_hdl, B_FALSE); } fuid_dirtied = zfsvfs->z_fuid_dirty; if (fuid_dirtied) zfs_fuid_txhold(zfsvfs, tx); zfs_sa_upgrade_txholds(tx, zp); err = dmu_tx_assign(tx, TXG_WAIT); if (err) goto out; count = 0; /* * Set each attribute requested. * We group settings according to the locks they need to acquire. * * Note: you cannot set ctime directly, although it will be * updated as a side-effect of calling this function. */ if (mask & (AT_UID|AT_GID|AT_MODE)) mutex_enter(&zp->z_acl_lock); mutex_enter(&zp->z_lock); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL, &zp->z_pflags, sizeof (zp->z_pflags)); if (attrzp) { if (mask & (AT_UID|AT_GID|AT_MODE)) mutex_enter(&attrzp->z_acl_lock); mutex_enter(&attrzp->z_lock); SA_ADD_BULK_ATTR(xattr_bulk, xattr_count, SA_ZPL_FLAGS(zfsvfs), NULL, &attrzp->z_pflags, sizeof (attrzp->z_pflags)); } if (mask & (AT_UID|AT_GID)) { if (mask & AT_UID) { SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL, &new_uid, sizeof (new_uid)); zp->z_uid = new_uid; if (attrzp) { SA_ADD_BULK_ATTR(xattr_bulk, xattr_count, SA_ZPL_UID(zfsvfs), NULL, &new_uid, sizeof (new_uid)); attrzp->z_uid = new_uid; } } if (mask & AT_GID) { SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL, &new_gid, sizeof (new_gid)); zp->z_gid = new_gid; if (attrzp) { SA_ADD_BULK_ATTR(xattr_bulk, xattr_count, SA_ZPL_GID(zfsvfs), NULL, &new_gid, sizeof (new_gid)); attrzp->z_gid = new_gid; } } if (!(mask & AT_MODE)) { SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, &new_mode, sizeof (new_mode)); new_mode = zp->z_mode; } err = zfs_acl_chown_setattr(zp); ASSERT(err == 0); if (attrzp) { err = zfs_acl_chown_setattr(attrzp); ASSERT(err == 0); } } if (mask & AT_MODE) { SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, &new_mode, sizeof (new_mode)); zp->z_mode = new_mode; ASSERT3U((uintptr_t)aclp, !=, 0); err = zfs_aclset_common(zp, aclp, cr, tx); ASSERT0(err); if (zp->z_acl_cached) zfs_acl_free(zp->z_acl_cached); zp->z_acl_cached = aclp; aclp = NULL; } if (mask & AT_ATIME) { ZFS_TIME_ENCODE(&vap->va_atime, zp->z_atime); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL, &zp->z_atime, sizeof (zp->z_atime)); } if (mask & AT_MTIME) { ZFS_TIME_ENCODE(&vap->va_mtime, mtime); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, mtime, sizeof (mtime)); } /* XXX - shouldn't this be done *before* the ATIME/MTIME checks? */ if (mask & AT_SIZE && !(mask & AT_MTIME)) { SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, mtime, sizeof (mtime)); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, sizeof (ctime)); zfs_tstamp_update_setup(zp, CONTENT_MODIFIED, mtime, ctime, B_TRUE); } else if (mask != 0) { SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, sizeof (ctime)); zfs_tstamp_update_setup(zp, STATE_CHANGED, mtime, ctime, B_TRUE); if (attrzp) { SA_ADD_BULK_ATTR(xattr_bulk, xattr_count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, sizeof (ctime)); zfs_tstamp_update_setup(attrzp, STATE_CHANGED, mtime, ctime, B_TRUE); } } /* * Do this after setting timestamps to prevent timestamp * update from toggling bit */ if (xoap && (mask & AT_XVATTR)) { /* * restore trimmed off masks * so that return masks can be set for caller. */ if (XVA_ISSET_REQ(&tmpxvattr, XAT_APPENDONLY)) { XVA_SET_REQ(xvap, XAT_APPENDONLY); } if (XVA_ISSET_REQ(&tmpxvattr, XAT_NOUNLINK)) { XVA_SET_REQ(xvap, XAT_NOUNLINK); } if (XVA_ISSET_REQ(&tmpxvattr, XAT_IMMUTABLE)) { XVA_SET_REQ(xvap, XAT_IMMUTABLE); } if (XVA_ISSET_REQ(&tmpxvattr, XAT_NODUMP)) { XVA_SET_REQ(xvap, XAT_NODUMP); } if (XVA_ISSET_REQ(&tmpxvattr, XAT_AV_MODIFIED)) { XVA_SET_REQ(xvap, XAT_AV_MODIFIED); } if (XVA_ISSET_REQ(&tmpxvattr, XAT_AV_QUARANTINED)) { XVA_SET_REQ(xvap, XAT_AV_QUARANTINED); } if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) ASSERT(vp->v_type == VREG); zfs_xvattr_set(zp, xvap, tx); } if (fuid_dirtied) zfs_fuid_sync(zfsvfs, tx); if (mask != 0) zfs_log_setattr(zilog, tx, TX_SETATTR, zp, vap, mask, fuidp); mutex_exit(&zp->z_lock); if (mask & (AT_UID|AT_GID|AT_MODE)) mutex_exit(&zp->z_acl_lock); if (attrzp) { if (mask & (AT_UID|AT_GID|AT_MODE)) mutex_exit(&attrzp->z_acl_lock); mutex_exit(&attrzp->z_lock); } out: if (err == 0 && attrzp) { err2 = sa_bulk_update(attrzp->z_sa_hdl, xattr_bulk, xattr_count, tx); ASSERT(err2 == 0); } if (attrzp) VN_RELE(ZTOV(attrzp)); if (aclp) zfs_acl_free(aclp); if (fuidp) { zfs_fuid_info_free(fuidp); fuidp = NULL; } if (err) { dmu_tx_abort(tx); if (err == ERESTART) goto top; } else { err2 = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx); dmu_tx_commit(tx); } out2: if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) zil_commit(zilog, 0); ZFS_EXIT(zfsvfs); return (err); } typedef struct zfs_zlock { krwlock_t *zl_rwlock; /* lock we acquired */ znode_t *zl_znode; /* znode we held */ struct zfs_zlock *zl_next; /* next in list */ } zfs_zlock_t; /* * Drop locks and release vnodes that were held by zfs_rename_lock(). */ static void zfs_rename_unlock(zfs_zlock_t **zlpp) { zfs_zlock_t *zl; while ((zl = *zlpp) != NULL) { if (zl->zl_znode != NULL) VN_RELE(ZTOV(zl->zl_znode)); rw_exit(zl->zl_rwlock); *zlpp = zl->zl_next; kmem_free(zl, sizeof (*zl)); } } /* * Search back through the directory tree, using the ".." entries. * Lock each directory in the chain to prevent concurrent renames. * Fail any attempt to move a directory into one of its own descendants. * XXX - z_parent_lock can overlap with map or grow locks */ static int zfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp) { zfs_zlock_t *zl; znode_t *zp = tdzp; uint64_t rootid = zp->z_zfsvfs->z_root; uint64_t oidp = zp->z_id; krwlock_t *rwlp = &szp->z_parent_lock; krw_t rw = RW_WRITER; /* * First pass write-locks szp and compares to zp->z_id. * Later passes read-lock zp and compare to zp->z_parent. */ do { if (!rw_tryenter(rwlp, rw)) { /* * Another thread is renaming in this path. * Note that if we are a WRITER, we don't have any * parent_locks held yet. */ if (rw == RW_READER && zp->z_id > szp->z_id) { /* * Drop our locks and restart */ zfs_rename_unlock(&zl); *zlpp = NULL; zp = tdzp; oidp = zp->z_id; rwlp = &szp->z_parent_lock; rw = RW_WRITER; continue; } else { /* * Wait for other thread to drop its locks */ rw_enter(rwlp, rw); } } zl = kmem_alloc(sizeof (*zl), KM_SLEEP); zl->zl_rwlock = rwlp; zl->zl_znode = NULL; zl->zl_next = *zlpp; *zlpp = zl; if (oidp == szp->z_id) /* We're a descendant of szp */ return (SET_ERROR(EINVAL)); if (oidp == rootid) /* We've hit the top */ return (0); if (rw == RW_READER) { /* i.e. not the first pass */ int error = zfs_zget(zp->z_zfsvfs, oidp, &zp); if (error) return (error); zl->zl_znode = zp; } (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_PARENT(zp->z_zfsvfs), &oidp, sizeof (oidp)); rwlp = &zp->z_parent_lock; rw = RW_READER; } while (zp->z_id != sdzp->z_id); return (0); } /* * Move an entry from the provided source directory to the target * directory. Change the entry name as indicated. * * IN: sdvp - Source directory containing the "old entry". * snm - Old entry name. * tdvp - Target directory to contain the "new entry". * tnm - New entry name. * cr - credentials of caller. * ct - caller context * flags - case flags * * RETURN: 0 on success, error code on failure. * * Timestamps: * sdvp,tdvp - ctime|mtime updated */ /*ARGSUSED*/ static int zfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr, caller_context_t *ct, int flags) { znode_t *tdzp, *sdzp, *szp, *tzp; zfsvfs_t *zfsvfs; zilog_t *zilog; vnode_t *realvp; zfs_dirlock_t *sdl, *tdl; dmu_tx_t *tx; zfs_zlock_t *zl; int cmp, serr, terr; int error = 0; int zflg = 0; boolean_t waited = B_FALSE; tdzp = VTOZ(tdvp); ZFS_VERIFY_ZP(tdzp); zfsvfs = tdzp->z_zfsvfs; ZFS_ENTER(zfsvfs); zilog = zfsvfs->z_log; sdzp = VTOZ(sdvp); /* * In case sdzp is not valid, let's be sure to exit from the right * zfsvfs_t. */ if (sdzp->z_sa_hdl == NULL) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EIO)); } /* * We check z_zfsvfs rather than v_vfsp here, because snapshots and the * ctldir appear to have the same v_vfsp. */ if (sdzp->z_zfsvfs != zfsvfs || zfsctl_is_node(tdvp)) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EXDEV)); } if (zfsvfs->z_utf8 && u8_validate(tnm, strlen(tnm), NULL, U8_VALIDATE_ENTIRE, &error) < 0) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EILSEQ)); } if (flags & FIGNORECASE) zflg |= ZCILOOK; top: szp = NULL; tzp = NULL; zl = NULL; /* * This is to prevent the creation of links into attribute space * by renaming a linked file into/outof an attribute directory. * See the comment in zfs_link() for why this is considered bad. */ if ((tdzp->z_pflags & ZFS_XATTR) != (sdzp->z_pflags & ZFS_XATTR)) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EINVAL)); } /* * Lock source and target directory entries. To prevent deadlock, * a lock ordering must be defined. We lock the directory with * the smallest object id first, or if it's a tie, the one with * the lexically first name. */ if (sdzp->z_id < tdzp->z_id) { cmp = -1; } else if (sdzp->z_id > tdzp->z_id) { cmp = 1; } else { /* * First compare the two name arguments without * considering any case folding. */ int nofold = (zfsvfs->z_norm & ~U8_TEXTPREP_TOUPPER); cmp = u8_strcmp(snm, tnm, 0, nofold, U8_UNICODE_LATEST, &error); ASSERT(error == 0 || !zfsvfs->z_utf8); if (cmp == 0) { /* * POSIX: "If the old argument and the new argument * both refer to links to the same existing file, * the rename() function shall return successfully * and perform no other action." */ ZFS_EXIT(zfsvfs); return (0); } /* * If the file system is case-folding, then we may * have some more checking to do. A case-folding file * system is either supporting mixed case sensitivity * access or is completely case-insensitive. Note * that the file system is always case preserving. * * In mixed sensitivity mode case sensitive behavior * is the default. FIGNORECASE must be used to * explicitly request case insensitive behavior. * * If the source and target names provided differ only * by case (e.g., a request to rename 'tim' to 'Tim'), * we will treat this as a special case in the * case-insensitive mode: as long as the source name * is an exact match, we will allow this to proceed as * a name-change request. */ if ((zfsvfs->z_case == ZFS_CASE_INSENSITIVE || (zfsvfs->z_case == ZFS_CASE_MIXED && flags & FIGNORECASE)) && u8_strcmp(snm, tnm, 0, zfsvfs->z_norm, U8_UNICODE_LATEST, &error) == 0) { /* * case preserving rename request, require exact * name matches */ zflg |= ZCIEXACT; zflg &= ~ZCILOOK; } } /* * If the source and destination directories are the same, we should * grab the z_name_lock of that directory only once. */ if (sdzp == tdzp) { zflg |= ZHAVELOCK; rw_enter(&sdzp->z_name_lock, RW_READER); } if (cmp < 0) { serr = zfs_dirent_lock(&sdl, sdzp, snm, &szp, ZEXISTS | zflg, NULL, NULL); terr = zfs_dirent_lock(&tdl, tdzp, tnm, &tzp, ZRENAMING | zflg, NULL, NULL); } else { terr = zfs_dirent_lock(&tdl, tdzp, tnm, &tzp, zflg, NULL, NULL); serr = zfs_dirent_lock(&sdl, sdzp, snm, &szp, ZEXISTS | ZRENAMING | zflg, NULL, NULL); } if (serr) { /* * Source entry invalid or not there. */ if (!terr) { zfs_dirent_unlock(tdl); if (tzp) VN_RELE(ZTOV(tzp)); } if (sdzp == tdzp) rw_exit(&sdzp->z_name_lock); /* * FreeBSD: In OpenSolaris they only check if rename source is * ".." here, because "." is handled in their lookup. This is * not the case for FreeBSD, so we check for "." explicitly. */ if (strcmp(snm, ".") == 0 || strcmp(snm, "..") == 0) serr = SET_ERROR(EINVAL); ZFS_EXIT(zfsvfs); return (serr); } if (terr) { zfs_dirent_unlock(sdl); VN_RELE(ZTOV(szp)); if (sdzp == tdzp) rw_exit(&sdzp->z_name_lock); if (strcmp(tnm, "..") == 0) terr = SET_ERROR(EINVAL); ZFS_EXIT(zfsvfs); return (terr); } /* * Must have write access at the source to remove the old entry * and write access at the target to create the new entry. * Note that if target and source are the same, this can be * done in a single check. */ if (error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr)) goto out; if (ZTOV(szp)->v_type == VDIR) { /* * Check to make sure rename is valid. * Can't do a move like this: /usr/a/b to /usr/a/b/c/d */ if (error = zfs_rename_lock(szp, tdzp, sdzp, &zl)) goto out; } /* * Does target exist? */ if (tzp) { /* * Source and target must be the same type. */ if (ZTOV(szp)->v_type == VDIR) { if (ZTOV(tzp)->v_type != VDIR) { error = SET_ERROR(ENOTDIR); goto out; } } else { if (ZTOV(tzp)->v_type == VDIR) { error = SET_ERROR(EISDIR); goto out; } } /* * POSIX dictates that when the source and target * entries refer to the same file object, rename * must do nothing and exit without error. */ if (szp->z_id == tzp->z_id) { error = 0; goto out; } } vnevent_rename_src(ZTOV(szp), sdvp, snm, ct); if (tzp) vnevent_rename_dest(ZTOV(tzp), tdvp, tnm, ct); /* * notify the target directory if it is not the same * as source directory. */ if (tdvp != sdvp) { vnevent_rename_dest_dir(tdvp, ct); } tx = dmu_tx_create(zfsvfs->z_os); dmu_tx_hold_sa(tx, szp->z_sa_hdl, B_FALSE); dmu_tx_hold_sa(tx, sdzp->z_sa_hdl, B_FALSE); dmu_tx_hold_zap(tx, sdzp->z_id, FALSE, snm); dmu_tx_hold_zap(tx, tdzp->z_id, TRUE, tnm); if (sdzp != tdzp) { dmu_tx_hold_sa(tx, tdzp->z_sa_hdl, B_FALSE); zfs_sa_upgrade_txholds(tx, tdzp); } if (tzp) { dmu_tx_hold_sa(tx, tzp->z_sa_hdl, B_FALSE); zfs_sa_upgrade_txholds(tx, tzp); } zfs_sa_upgrade_txholds(tx, szp); dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); error = dmu_tx_assign(tx, waited ? TXG_WAITED : TXG_NOWAIT); if (error) { if (zl != NULL) zfs_rename_unlock(&zl); zfs_dirent_unlock(sdl); zfs_dirent_unlock(tdl); if (sdzp == tdzp) rw_exit(&sdzp->z_name_lock); VN_RELE(ZTOV(szp)); if (tzp) VN_RELE(ZTOV(tzp)); if (error == ERESTART) { waited = B_TRUE; dmu_tx_wait(tx); dmu_tx_abort(tx); goto top; } dmu_tx_abort(tx); ZFS_EXIT(zfsvfs); return (error); } if (tzp) /* Attempt to remove the existing target */ error = zfs_link_destroy(tdl, tzp, tx, zflg, NULL); if (error == 0) { error = zfs_link_create(tdl, szp, tx, ZRENAMING); if (error == 0) { szp->z_pflags |= ZFS_AV_MODIFIED; error = sa_update(szp->z_sa_hdl, SA_ZPL_FLAGS(zfsvfs), (void *)&szp->z_pflags, sizeof (uint64_t), tx); ASSERT0(error); error = zfs_link_destroy(sdl, szp, tx, ZRENAMING, NULL); if (error == 0) { zfs_log_rename(zilog, tx, TX_RENAME | (flags & FIGNORECASE ? TX_CI : 0), sdzp, sdl->dl_name, tdzp, tdl->dl_name, szp); /* * Update path information for the target vnode */ vn_renamepath(tdvp, ZTOV(szp), tnm, strlen(tnm)); } else { /* * At this point, we have successfully created * the target name, but have failed to remove * the source name. Since the create was done * with the ZRENAMING flag, there are * complications; for one, the link count is * wrong. The easiest way to deal with this * is to remove the newly created target, and * return the original error. This must * succeed; fortunately, it is very unlikely to * fail, since we just created it. */ VERIFY3U(zfs_link_destroy(tdl, szp, tx, ZRENAMING, NULL), ==, 0); } } #ifdef FREEBSD_NAMECACHE if (error == 0) { cache_purge(sdvp); cache_purge(tdvp); cache_purge(ZTOV(szp)); if (tzp) cache_purge(ZTOV(tzp)); } #endif } dmu_tx_commit(tx); out: if (zl != NULL) zfs_rename_unlock(&zl); zfs_dirent_unlock(sdl); zfs_dirent_unlock(tdl); if (sdzp == tdzp) rw_exit(&sdzp->z_name_lock); VN_RELE(ZTOV(szp)); if (tzp) VN_RELE(ZTOV(tzp)); if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) zil_commit(zilog, 0); ZFS_EXIT(zfsvfs); return (error); } /* * Insert the indicated symbolic reference entry into the directory. * * IN: dvp - Directory to contain new symbolic link. * link - Name for new symlink entry. * vap - Attributes of new entry. * cr - credentials of caller. * ct - caller context * flags - case flags * * RETURN: 0 on success, error code on failure. * * Timestamps: * dvp - ctime|mtime updated */ /*ARGSUSED*/ static int zfs_symlink(vnode_t *dvp, vnode_t **vpp, char *name, vattr_t *vap, char *link, cred_t *cr, kthread_t *td) { znode_t *zp, *dzp = VTOZ(dvp); zfs_dirlock_t *dl; dmu_tx_t *tx; zfsvfs_t *zfsvfs = dzp->z_zfsvfs; zilog_t *zilog; uint64_t len = strlen(link); int error; int zflg = ZNEW; zfs_acl_ids_t acl_ids; boolean_t fuid_dirtied; uint64_t txtype = TX_SYMLINK; boolean_t waited = B_FALSE; int flags = 0; ASSERT(vap->va_type == VLNK); ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(dzp); zilog = zfsvfs->z_log; if (zfsvfs->z_utf8 && u8_validate(name, strlen(name), NULL, U8_VALIDATE_ENTIRE, &error) < 0) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EILSEQ)); } if (flags & FIGNORECASE) zflg |= ZCILOOK; if (len > MAXPATHLEN) { ZFS_EXIT(zfsvfs); return (SET_ERROR(ENAMETOOLONG)); } if ((error = zfs_acl_ids_create(dzp, 0, vap, cr, NULL, &acl_ids)) != 0) { ZFS_EXIT(zfsvfs); return (error); } getnewvnode_reserve(1); top: /* * Attempt to lock directory; fail if entry already exists. */ error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg, NULL, NULL); if (error) { zfs_acl_ids_free(&acl_ids); getnewvnode_drop_reserve(); ZFS_EXIT(zfsvfs); return (error); } if (error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr)) { zfs_acl_ids_free(&acl_ids); zfs_dirent_unlock(dl); getnewvnode_drop_reserve(); ZFS_EXIT(zfsvfs); return (error); } if (zfs_acl_ids_overquota(zfsvfs, &acl_ids)) { zfs_acl_ids_free(&acl_ids); zfs_dirent_unlock(dl); getnewvnode_drop_reserve(); ZFS_EXIT(zfsvfs); return (SET_ERROR(EDQUOT)); } tx = dmu_tx_create(zfsvfs->z_os); fuid_dirtied = zfsvfs->z_fuid_dirty; dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, MAX(1, len)); dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name); dmu_tx_hold_sa_create(tx, acl_ids.z_aclp->z_acl_bytes + ZFS_SA_BASE_ATTR_SIZE + len); dmu_tx_hold_sa(tx, dzp->z_sa_hdl, B_FALSE); if (!zfsvfs->z_use_sa && acl_ids.z_aclp->z_acl_bytes > ZFS_ACE_SPACE) { dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, acl_ids.z_aclp->z_acl_bytes); } if (fuid_dirtied) zfs_fuid_txhold(zfsvfs, tx); error = dmu_tx_assign(tx, waited ? TXG_WAITED : TXG_NOWAIT); if (error) { zfs_dirent_unlock(dl); if (error == ERESTART) { waited = B_TRUE; dmu_tx_wait(tx); dmu_tx_abort(tx); goto top; } zfs_acl_ids_free(&acl_ids); dmu_tx_abort(tx); getnewvnode_drop_reserve(); ZFS_EXIT(zfsvfs); return (error); } /* * Create a new object for the symlink. * for version 4 ZPL datsets the symlink will be an SA attribute */ zfs_mknode(dzp, vap, tx, cr, 0, &zp, &acl_ids); if (fuid_dirtied) zfs_fuid_sync(zfsvfs, tx); mutex_enter(&zp->z_lock); if (zp->z_is_sa) error = sa_update(zp->z_sa_hdl, SA_ZPL_SYMLINK(zfsvfs), link, len, tx); else zfs_sa_symlink(zp, link, len, tx); mutex_exit(&zp->z_lock); zp->z_size = len; (void) sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zfsvfs), &zp->z_size, sizeof (zp->z_size), tx); /* * Insert the new object into the directory. */ (void) zfs_link_create(dl, zp, tx, ZNEW); if (flags & FIGNORECASE) txtype |= TX_CI; zfs_log_symlink(zilog, tx, txtype, dzp, zp, name, link); *vpp = ZTOV(zp); zfs_acl_ids_free(&acl_ids); dmu_tx_commit(tx); getnewvnode_drop_reserve(); zfs_dirent_unlock(dl); if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) zil_commit(zilog, 0); ZFS_EXIT(zfsvfs); return (error); } /* * Return, in the buffer contained in the provided uio structure, * the symbolic path referred to by vp. * * IN: vp - vnode of symbolic link. * uio - structure to contain the link path. * cr - credentials of caller. * ct - caller context * * OUT: uio - structure containing the link path. * * RETURN: 0 on success, error code on failure. * * Timestamps: * vp - atime updated */ /* ARGSUSED */ static int zfs_readlink(vnode_t *vp, uio_t *uio, cred_t *cr, caller_context_t *ct) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; int error; ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); mutex_enter(&zp->z_lock); if (zp->z_is_sa) error = sa_lookup_uio(zp->z_sa_hdl, SA_ZPL_SYMLINK(zfsvfs), uio); else error = zfs_sa_readlink(zp, uio); mutex_exit(&zp->z_lock); ZFS_ACCESSTIME_STAMP(zfsvfs, zp); ZFS_EXIT(zfsvfs); return (error); } /* * Insert a new entry into directory tdvp referencing svp. * * IN: tdvp - Directory to contain new entry. * svp - vnode of new entry. * name - name of new entry. * cr - credentials of caller. * ct - caller context * * RETURN: 0 on success, error code on failure. * * Timestamps: * tdvp - ctime|mtime updated * svp - ctime updated */ /* ARGSUSED */ static int zfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr, caller_context_t *ct, int flags) { znode_t *dzp = VTOZ(tdvp); znode_t *tzp, *szp; zfsvfs_t *zfsvfs = dzp->z_zfsvfs; zilog_t *zilog; zfs_dirlock_t *dl; dmu_tx_t *tx; vnode_t *realvp; int error; int zf = ZNEW; uint64_t parent; uid_t owner; boolean_t waited = B_FALSE; ASSERT(tdvp->v_type == VDIR); ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(dzp); zilog = zfsvfs->z_log; if (VOP_REALVP(svp, &realvp, ct) == 0) svp = realvp; /* * POSIX dictates that we return EPERM here. * Better choices include ENOTSUP or EISDIR. */ if (svp->v_type == VDIR) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EPERM)); } szp = VTOZ(svp); ZFS_VERIFY_ZP(szp); if (szp->z_pflags & (ZFS_APPENDONLY | ZFS_IMMUTABLE | ZFS_READONLY)) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EPERM)); } /* * We check z_zfsvfs rather than v_vfsp here, because snapshots and the * ctldir appear to have the same v_vfsp. */ if (szp->z_zfsvfs != zfsvfs || zfsctl_is_node(svp)) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EXDEV)); } /* Prevent links to .zfs/shares files */ if ((error = sa_lookup(szp->z_sa_hdl, SA_ZPL_PARENT(zfsvfs), &parent, sizeof (uint64_t))) != 0) { ZFS_EXIT(zfsvfs); return (error); } if (parent == zfsvfs->z_shares_dir) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EPERM)); } if (zfsvfs->z_utf8 && u8_validate(name, strlen(name), NULL, U8_VALIDATE_ENTIRE, &error) < 0) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EILSEQ)); } if (flags & FIGNORECASE) zf |= ZCILOOK; /* * We do not support links between attributes and non-attributes * because of the potential security risk of creating links * into "normal" file space in order to circumvent restrictions * imposed in attribute space. */ if ((szp->z_pflags & ZFS_XATTR) != (dzp->z_pflags & ZFS_XATTR)) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EINVAL)); } owner = zfs_fuid_map_id(zfsvfs, szp->z_uid, cr, ZFS_OWNER); if (owner != crgetuid(cr) && secpolicy_basic_link(svp, cr) != 0) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EPERM)); } if (error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr)) { ZFS_EXIT(zfsvfs); return (error); } top: /* * Attempt to lock directory; fail if entry already exists. */ error = zfs_dirent_lock(&dl, dzp, name, &tzp, zf, NULL, NULL); if (error) { ZFS_EXIT(zfsvfs); return (error); } tx = dmu_tx_create(zfsvfs->z_os); dmu_tx_hold_sa(tx, szp->z_sa_hdl, B_FALSE); dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name); zfs_sa_upgrade_txholds(tx, szp); zfs_sa_upgrade_txholds(tx, dzp); error = dmu_tx_assign(tx, waited ? TXG_WAITED : TXG_NOWAIT); if (error) { zfs_dirent_unlock(dl); if (error == ERESTART) { waited = B_TRUE; dmu_tx_wait(tx); dmu_tx_abort(tx); goto top; } dmu_tx_abort(tx); ZFS_EXIT(zfsvfs); return (error); } error = zfs_link_create(dl, szp, tx, 0); if (error == 0) { uint64_t txtype = TX_LINK; if (flags & FIGNORECASE) txtype |= TX_CI; zfs_log_link(zilog, tx, txtype, dzp, szp, name); } dmu_tx_commit(tx); zfs_dirent_unlock(dl); if (error == 0) { vnevent_link(svp, ct); } if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) zil_commit(zilog, 0); ZFS_EXIT(zfsvfs); return (error); } #ifdef sun /* * zfs_null_putapage() is used when the file system has been force * unmounted. It just drops the pages. */ /* ARGSUSED */ static int zfs_null_putapage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp, int flags, cred_t *cr) { pvn_write_done(pp, B_INVAL|B_FORCE|B_ERROR); return (0); } /* * Push a page out to disk, klustering if possible. * * IN: vp - file to push page to. * pp - page to push. * flags - additional flags. * cr - credentials of caller. * * OUT: offp - start of range pushed. * lenp - len of range pushed. * * RETURN: 0 on success, error code on failure. * * NOTE: callers must have locked the page to be pushed. On * exit, the page (and all other pages in the kluster) must be * unlocked. */ /* ARGSUSED */ static int zfs_putapage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp, int flags, cred_t *cr) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; dmu_tx_t *tx; u_offset_t off, koff; size_t len, klen; int err; off = pp->p_offset; len = PAGESIZE; /* * If our blocksize is bigger than the page size, try to kluster * multiple pages so that we write a full block (thus avoiding * a read-modify-write). */ if (off < zp->z_size && zp->z_blksz > PAGESIZE) { klen = P2ROUNDUP((ulong_t)zp->z_blksz, PAGESIZE); koff = ISP2(klen) ? P2ALIGN(off, (u_offset_t)klen) : 0; ASSERT(koff <= zp->z_size); if (koff + klen > zp->z_size) klen = P2ROUNDUP(zp->z_size - koff, (uint64_t)PAGESIZE); pp = pvn_write_kluster(vp, pp, &off, &len, koff, klen, flags); } ASSERT3U(btop(len), ==, btopr(len)); /* * Can't push pages past end-of-file. */ if (off >= zp->z_size) { /* ignore all pages */ err = 0; goto out; } else if (off + len > zp->z_size) { int npages = btopr(zp->z_size - off); page_t *trunc; page_list_break(&pp, &trunc, npages); /* ignore pages past end of file */ if (trunc) pvn_write_done(trunc, flags); len = zp->z_size - off; } if (zfs_owner_overquota(zfsvfs, zp, B_FALSE) || zfs_owner_overquota(zfsvfs, zp, B_TRUE)) { err = SET_ERROR(EDQUOT); goto out; } tx = dmu_tx_create(zfsvfs->z_os); dmu_tx_hold_write(tx, zp->z_id, off, len); dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); zfs_sa_upgrade_txholds(tx, zp); err = dmu_tx_assign(tx, TXG_WAIT); if (err != 0) { dmu_tx_abort(tx); goto out; } if (zp->z_blksz <= PAGESIZE) { caddr_t va = zfs_map_page(pp, S_READ); ASSERT3U(len, <=, PAGESIZE); dmu_write(zfsvfs->z_os, zp->z_id, off, len, va, tx); zfs_unmap_page(pp, va); } else { err = dmu_write_pages(zfsvfs->z_os, zp->z_id, off, len, pp, tx); } if (err == 0) { uint64_t mtime[2], ctime[2]; sa_bulk_attr_t bulk[3]; int count = 0; SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, &mtime, 16); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, 16); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL, &zp->z_pflags, 8); zfs_tstamp_update_setup(zp, CONTENT_MODIFIED, mtime, ctime, B_TRUE); zfs_log_write(zfsvfs->z_log, tx, TX_WRITE, zp, off, len, 0); } dmu_tx_commit(tx); out: pvn_write_done(pp, (err ? B_ERROR : 0) | flags); if (offp) *offp = off; if (lenp) *lenp = len; return (err); } /* * Copy the portion of the file indicated from pages into the file. * The pages are stored in a page list attached to the files vnode. * * IN: vp - vnode of file to push page data to. * off - position in file to put data. * len - amount of data to write. * flags - flags to control the operation. * cr - credentials of caller. * ct - caller context. * * RETURN: 0 on success, error code on failure. * * Timestamps: * vp - ctime|mtime updated */ /*ARGSUSED*/ static int zfs_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr, caller_context_t *ct) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; page_t *pp; size_t io_len; u_offset_t io_off; uint_t blksz; rl_t *rl; int error = 0; ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); /* * Align this request to the file block size in case we kluster. * XXX - this can result in pretty aggresive locking, which can * impact simultanious read/write access. One option might be * to break up long requests (len == 0) into block-by-block * operations to get narrower locking. */ blksz = zp->z_blksz; if (ISP2(blksz)) io_off = P2ALIGN_TYPED(off, blksz, u_offset_t); else io_off = 0; if (len > 0 && ISP2(blksz)) io_len = P2ROUNDUP_TYPED(len + (off - io_off), blksz, size_t); else io_len = 0; if (io_len == 0) { /* * Search the entire vp list for pages >= io_off. */ rl = zfs_range_lock(zp, io_off, UINT64_MAX, RL_WRITER); error = pvn_vplist_dirty(vp, io_off, zfs_putapage, flags, cr); goto out; } rl = zfs_range_lock(zp, io_off, io_len, RL_WRITER); if (off > zp->z_size) { /* past end of file */ zfs_range_unlock(rl); ZFS_EXIT(zfsvfs); return (0); } len = MIN(io_len, P2ROUNDUP(zp->z_size, PAGESIZE) - io_off); for (off = io_off; io_off < off + len; io_off += io_len) { if ((flags & B_INVAL) || ((flags & B_ASYNC) == 0)) { pp = page_lookup(vp, io_off, (flags & (B_INVAL | B_FREE)) ? SE_EXCL : SE_SHARED); } else { pp = page_lookup_nowait(vp, io_off, (flags & B_FREE) ? SE_EXCL : SE_SHARED); } if (pp != NULL && pvn_getdirty(pp, flags)) { int err; /* * Found a dirty page to push */ err = zfs_putapage(vp, pp, &io_off, &io_len, flags, cr); if (err) error = err; } else { io_len = PAGESIZE; } } out: zfs_range_unlock(rl); if ((flags & B_ASYNC) == 0 || zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) zil_commit(zfsvfs->z_log, zp->z_id); ZFS_EXIT(zfsvfs); return (error); } #endif /* sun */ /*ARGSUSED*/ void zfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; int error; rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_READER); if (zp->z_sa_hdl == NULL) { /* * The fs has been unmounted, or we did a * suspend/resume and this file no longer exists. */ rw_exit(&zfsvfs->z_teardown_inactive_lock); vrecycle(vp); return; } mutex_enter(&zp->z_lock); if (zp->z_unlinked) { /* * Fast path to recycle a vnode of a removed file. */ mutex_exit(&zp->z_lock); rw_exit(&zfsvfs->z_teardown_inactive_lock); vrecycle(vp); return; } mutex_exit(&zp->z_lock); if (zp->z_atime_dirty && zp->z_unlinked == 0) { dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os); dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); zfs_sa_upgrade_txholds(tx, zp); error = dmu_tx_assign(tx, TXG_WAIT); if (error) { dmu_tx_abort(tx); } else { mutex_enter(&zp->z_lock); (void) sa_update(zp->z_sa_hdl, SA_ZPL_ATIME(zfsvfs), (void *)&zp->z_atime, sizeof (zp->z_atime), tx); zp->z_atime_dirty = 0; mutex_exit(&zp->z_lock); dmu_tx_commit(tx); } } rw_exit(&zfsvfs->z_teardown_inactive_lock); } #ifdef sun /* * Bounds-check the seek operation. * * IN: vp - vnode seeking within * ooff - old file offset * noffp - pointer to new file offset * ct - caller context * * RETURN: 0 on success, EINVAL if new offset invalid. */ /* ARGSUSED */ static int zfs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct) { if (vp->v_type == VDIR) return (0); return ((*noffp < 0 || *noffp > MAXOFFSET_T) ? EINVAL : 0); } /* * Pre-filter the generic locking function to trap attempts to place * a mandatory lock on a memory mapped file. */ static int zfs_frlock(vnode_t *vp, int cmd, flock64_t *bfp, int flag, offset_t offset, flk_callback_t *flk_cbp, cred_t *cr, caller_context_t *ct) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); /* * We are following the UFS semantics with respect to mapcnt * here: If we see that the file is mapped already, then we will * return an error, but we don't worry about races between this * function and zfs_map(). */ if (zp->z_mapcnt > 0 && MANDMODE(zp->z_mode)) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EAGAIN)); } ZFS_EXIT(zfsvfs); return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ct)); } /* * If we can't find a page in the cache, we will create a new page * and fill it with file data. For efficiency, we may try to fill * multiple pages at once (klustering) to fill up the supplied page * list. Note that the pages to be filled are held with an exclusive * lock to prevent access by other threads while they are being filled. */ static int zfs_fillpage(vnode_t *vp, u_offset_t off, struct seg *seg, caddr_t addr, page_t *pl[], size_t plsz, enum seg_rw rw) { znode_t *zp = VTOZ(vp); page_t *pp, *cur_pp; objset_t *os = zp->z_zfsvfs->z_os; u_offset_t io_off, total; size_t io_len; int err; if (plsz == PAGESIZE || zp->z_blksz <= PAGESIZE) { /* * We only have a single page, don't bother klustering */ io_off = off; io_len = PAGESIZE; pp = page_create_va(vp, io_off, io_len, PG_EXCL | PG_WAIT, seg, addr); } else { /* * Try to find enough pages to fill the page list */ pp = pvn_read_kluster(vp, off, seg, addr, &io_off, &io_len, off, plsz, 0); } if (pp == NULL) { /* * The page already exists, nothing to do here. */ *pl = NULL; return (0); } /* * Fill the pages in the kluster. */ cur_pp = pp; for (total = io_off + io_len; io_off < total; io_off += PAGESIZE) { caddr_t va; ASSERT3U(io_off, ==, cur_pp->p_offset); va = zfs_map_page(cur_pp, S_WRITE); err = dmu_read(os, zp->z_id, io_off, PAGESIZE, va, DMU_READ_PREFETCH); zfs_unmap_page(cur_pp, va); if (err) { /* On error, toss the entire kluster */ pvn_read_done(pp, B_ERROR); /* convert checksum errors into IO errors */ if (err == ECKSUM) err = SET_ERROR(EIO); return (err); } cur_pp = cur_pp->p_next; } /* * Fill in the page list array from the kluster starting * from the desired offset `off'. * NOTE: the page list will always be null terminated. */ pvn_plist_init(pp, pl, plsz, off, io_len, rw); ASSERT(pl == NULL || (*pl)->p_offset == off); return (0); } /* * Return pointers to the pages for the file region [off, off + len] * in the pl array. If plsz is greater than len, this function may * also return page pointers from after the specified region * (i.e. the region [off, off + plsz]). These additional pages are * only returned if they are already in the cache, or were created as * part of a klustered read. * * IN: vp - vnode of file to get data from. * off - position in file to get data from. * len - amount of data to retrieve. * plsz - length of provided page list. * seg - segment to obtain pages for. * addr - virtual address of fault. * rw - mode of created pages. * cr - credentials of caller. * ct - caller context. * * OUT: protp - protection mode of created pages. * pl - list of pages created. * * RETURN: 0 on success, error code on failure. * * Timestamps: * vp - atime updated */ /* ARGSUSED */ static int zfs_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp, page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr, enum seg_rw rw, cred_t *cr, caller_context_t *ct) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; page_t **pl0 = pl; int err = 0; /* we do our own caching, faultahead is unnecessary */ if (pl == NULL) return (0); else if (len > plsz) len = plsz; else len = P2ROUNDUP(len, PAGESIZE); ASSERT(plsz >= len); ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); if (protp) *protp = PROT_ALL; /* * Loop through the requested range [off, off + len) looking * for pages. If we don't find a page, we will need to create * a new page and fill it with data from the file. */ while (len > 0) { if (*pl = page_lookup(vp, off, SE_SHARED)) *(pl+1) = NULL; else if (err = zfs_fillpage(vp, off, seg, addr, pl, plsz, rw)) goto out; while (*pl) { ASSERT3U((*pl)->p_offset, ==, off); off += PAGESIZE; addr += PAGESIZE; if (len > 0) { ASSERT3U(len, >=, PAGESIZE); len -= PAGESIZE; } ASSERT3U(plsz, >=, PAGESIZE); plsz -= PAGESIZE; pl++; } } /* * Fill out the page array with any pages already in the cache. */ while (plsz > 0 && (*pl++ = page_lookup_nowait(vp, off, SE_SHARED))) { off += PAGESIZE; plsz -= PAGESIZE; } out: if (err) { /* * Release any pages we have previously locked. */ while (pl > pl0) page_unlock(*--pl); } else { ZFS_ACCESSTIME_STAMP(zfsvfs, zp); } *pl = NULL; ZFS_EXIT(zfsvfs); return (err); } /* * Request a memory map for a section of a file. This code interacts * with common code and the VM system as follows: * * - common code calls mmap(), which ends up in smmap_common() * - this calls VOP_MAP(), which takes you into (say) zfs * - zfs_map() calls as_map(), passing segvn_create() as the callback * - segvn_create() creates the new segment and calls VOP_ADDMAP() * - zfs_addmap() updates z_mapcnt */ /*ARGSUSED*/ static int zfs_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp, size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t *cr, caller_context_t *ct) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; segvn_crargs_t vn_a; int error; ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); if ((prot & PROT_WRITE) && (zp->z_pflags & (ZFS_IMMUTABLE | ZFS_READONLY | ZFS_APPENDONLY))) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EPERM)); } if ((prot & (PROT_READ | PROT_EXEC)) && (zp->z_pflags & ZFS_AV_QUARANTINED)) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EACCES)); } if (vp->v_flag & VNOMAP) { ZFS_EXIT(zfsvfs); return (SET_ERROR(ENOSYS)); } if (off < 0 || len > MAXOFFSET_T - off) { ZFS_EXIT(zfsvfs); return (SET_ERROR(ENXIO)); } if (vp->v_type != VREG) { ZFS_EXIT(zfsvfs); return (SET_ERROR(ENODEV)); } /* * If file is locked, disallow mapping. */ if (MANDMODE(zp->z_mode) && vn_has_flocks(vp)) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EAGAIN)); } as_rangelock(as); error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags); if (error != 0) { as_rangeunlock(as); ZFS_EXIT(zfsvfs); return (error); } vn_a.vp = vp; vn_a.offset = (u_offset_t)off; vn_a.type = flags & MAP_TYPE; vn_a.prot = prot; vn_a.maxprot = maxprot; vn_a.cred = cr; vn_a.amp = NULL; vn_a.flags = flags & ~MAP_TYPE; vn_a.szc = 0; vn_a.lgrp_mem_policy_flags = 0; error = as_map(as, *addrp, len, segvn_create, &vn_a); as_rangeunlock(as); ZFS_EXIT(zfsvfs); return (error); } /* ARGSUSED */ static int zfs_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t *cr, caller_context_t *ct) { uint64_t pages = btopr(len); atomic_add_64(&VTOZ(vp)->z_mapcnt, pages); return (0); } /* * The reason we push dirty pages as part of zfs_delmap() is so that we get a * more accurate mtime for the associated file. Since we don't have a way of * detecting when the data was actually modified, we have to resort to * heuristics. If an explicit msync() is done, then we mark the mtime when the * last page is pushed. The problem occurs when the msync() call is omitted, * which by far the most common case: * * open() * mmap() * * munmap() * close() *