diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000000..facbea5f3156 --- /dev/null +++ b/.clang-format @@ -0,0 +1,77 @@ +# $FreeBSD$ +# Basic .clang-format +--- +BasedOnStyle: WebKit +AlignAfterOpenBracket: DontAlign +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: false +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: InlineOnly +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: TopLevelDefinitions +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +BinPackArguments: true +BinPackParameters: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: WebKit +BreakBeforeTernaryOperators: false +# TODO: BreakStringLiterals can cause very strange formatting so turn it off? +BreakStringLiterals: false +PenaltyBreakBeforeFirstCallParameter: 1000 +CompactNamespaces: true +DerivePointerAlignment: false +DisableFormat: false +ForEachMacros: + - SLIST_FOREACH + - SLIST_FOREACH_SAFE + - LIST_FOREACH + - LIST_FOREACH_SAFE + - STAILQ_FOREACH + - STAILQ_FOREACH_SAFE + - TAILQ_FOREACH + - TAILQ_FOREACH_SAFE + - TAILQ_FOREACH_REVERSE + - TAILQ_FOREACH_REVERSE_SAFE + - RB_FOREACH + - RB_FOREACH_SAFE + - RB_FOREACH_FROM + - RB_FOREACH_REVERSE + - RB_FOREACH_REVERSE_FROM + - RB_FOREACH_REVERSE_SAFE + - FOREACH_THREAD_IN_PROC + - FOREACH_PROC_IN_SYSTEM + - FOREACH_PRISON_CHILD + - FOREACH_PRISON_DESCENDANT + - FOREACH_PRISON_DESCENDANT_LOCKED + - FOREACH_PRISON_DESCENDANT_LOCKED_LEVEL + - MNT_VNODE_FOREACH_ALL + - MNT_VNODE_FOREACH_ACTIVE +IndentCaseLabels: false +IndentPPDirectives: None +Language: Cpp +NamespaceIndentation: None +PointerAlignment: Right +ContinuationIndentWidth: 4 +IndentWidth: 8 +TabWidth: 8 +ColumnLimit: 80 +UseTab: Always +SpaceAfterCStyleCast: false +SortIncludes: false +KeepEmptyLinesAtTheStartOfBlocks: true +# The options below will only be supported starting with clang 9.0: +# TODO-CLANG-9: TypenameMacros: +# TODO-CLANG-9: - SLIST_HEAD +# TODO-CLANG-9: - SLIST_ENTRY +# TODO-CLANG-9: - TAILQ_ENTRY +# TODO-CLANG-9: - TAILQ_HEAD +# TODO-CLANG-9: - STAILQ_ENTRY +# TODO-CLANG-9: - STAILQ_HEAD +... diff --git a/.gitattributes b/.gitattributes index 4d7b655b501e..11fec084166f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,3 +4,4 @@ *.hpp diff=cpp *.py diff=python . svn-properties=svn:keywords=tools/build/options/WITHOUT_LOADER_ZFS +.clang-format svn-properties=svn:keywords=FreeBSD=%H diff --git a/Makefile.inc1 b/Makefile.inc1 index b0044fd9895f..52af7f143520 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -553,16 +553,23 @@ VERSION= FreeBSD ${_REVISION}-${_BRANCH:C/-p[0-9]+$//} ${TARGET_ARCH} ${SRCRELDA .endif .if !defined(PKG_VERSION) -.if ${_BRANCH:MSTABLE*} || ${_BRANCH:MCURRENT*} || ${_BRANCH:MALPHA*} +.if ${_BRANCH:MSTABLE*} || ${_BRANCH:MCURRENT*} TIMENOW= %Y%m%d%H%M%S EXTRA_REVISION= .s${TIMENOW:gmtime} -.endif -.if ${_BRANCH:M*-p*} +.elif ${_BRANCH:MALPHA*} +EXTRA_REVISION= _${_BRANCH:C/-ALPHA/.a/} +.elif ${_BRANCH:MBETA*} +EXTRA_REVISION= _${_BRANCH:C/-BETA/.b/} +.elif ${_BRANCH:MRC*} +EXTRA_REVISION= _${_BRANCH:C/-RC/.r/} +.elif ${_BRANCH:MPRERELEASE*} +EXTRA_REVISION= _${_BRANCH:C/-PRERELEASE/.p/} +.elif ${_BRANCH:M*-p*} EXTRA_REVISION= _${_BRANCH:C/.*-p([0-9]+$)/\1/} .endif PKG_VERSION= ${_REVISION}${EXTRA_REVISION} .endif -.endif # !defined(_MKSHOWCONFIG) +.endif # !defined(PKG_VERSION) .if !defined(_MKSHOWCONFIG) _CPUTYPE!= MAKEFLAGS= CPUTYPE=${_TARGET_CPUTYPE} ${MAKE} -f /dev/null \ @@ -2546,6 +2553,7 @@ NXBDIRS+= \ usr.bin/find \ usr.bin/grep \ usr.bin/gzip \ + usr.bin/head \ usr.bin/id \ usr.bin/lex \ usr.bin/limits \ diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 4a54cd193f27..4e36abd0ef50 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,161 @@ # xargs -n1 | sort | uniq -d; # done +# 20190618: sys/capability.h removed (sys/capsicum.h is the one to use) +OLD_FILES+=usr/include/sys/capability.h +# 20190615: sys/pwm.h renamed to dev/pwmc.h +OLD_FILES+=usr/include/sys/pwm.h +# 20190612: new clang import which bumps version from 8.0.0 to 8.0.1. +OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/allocator_interface.h +OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/asan_interface.h +OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/common_interface_defs.h +OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/coverage_interface.h +OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/dfsan_interface.h +OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/esan_interface.h +OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/hwasan_interface.h +OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/linux_syscall_hooks.h +OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/lsan_interface.h +OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/msan_interface.h +OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/netbsd_syscall_hooks.h +OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/scudo_interface.h +OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/tsan_interface.h +OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/tsan_interface_atomic.h +OLD_DIRS+=usr/lib/clang/8.0.0/include/sanitizer +OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_builtin_vars.h +OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_cmath.h +OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_complex_builtins.h +OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_device_functions.h +OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_intrinsics.h +OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_libdevice_declares.h +OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_math_forward_declares.h +OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_runtime_wrapper.h +OLD_FILES+=usr/lib/clang/8.0.0/include/__stddef_max_align_t.h +OLD_FILES+=usr/lib/clang/8.0.0/include/__wmmintrin_aes.h +OLD_FILES+=usr/lib/clang/8.0.0/include/__wmmintrin_pclmul.h +OLD_FILES+=usr/lib/clang/8.0.0/include/adxintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/altivec.h +OLD_FILES+=usr/lib/clang/8.0.0/include/ammintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/arm64intr.h +OLD_FILES+=usr/lib/clang/8.0.0/include/arm_acle.h +OLD_FILES+=usr/lib/clang/8.0.0/include/arm_fp16.h +OLD_FILES+=usr/lib/clang/8.0.0/include/arm_neon.h +OLD_FILES+=usr/lib/clang/8.0.0/include/armintr.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx2intrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512bitalgintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512bwintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512cdintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512dqintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512erintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512fintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512ifmaintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512ifmavlintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512pfintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vbmi2intrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vbmiintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vbmivlintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vlbitalgintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vlbwintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vlcdintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vldqintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vlintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vlvbmi2intrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vlvnniintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vnniintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vpopcntdqintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vpopcntdqvlintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/avxintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/bmi2intrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/bmiintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/cetintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/cldemoteintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/clflushoptintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/clwbintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/clzerointrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/cpuid.h +OLD_FILES+=usr/lib/clang/8.0.0/include/emmintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/f16cintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/fma4intrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/fmaintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/fxsrintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/gfniintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/htmintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/htmxlintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/ia32intrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/immintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/invpcidintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/lwpintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/lzcntintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/mm3dnow.h +OLD_FILES+=usr/lib/clang/8.0.0/include/mm_malloc.h +OLD_FILES+=usr/lib/clang/8.0.0/include/mmintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/module.modulemap +OLD_FILES+=usr/lib/clang/8.0.0/include/movdirintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/msa.h +OLD_FILES+=usr/lib/clang/8.0.0/include/mwaitxintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/nmmintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/opencl-c.h +OLD_FILES+=usr/lib/clang/8.0.0/include/pconfigintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/pkuintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/pmmintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/popcntintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/prfchwintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/ptwriteintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/rdseedintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/rtmintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/s390intrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/sgxintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/shaintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/smmintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/tbmintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/tmmintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/vadefs.h +OLD_FILES+=usr/lib/clang/8.0.0/include/vaesintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/vecintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/vpclmulqdqintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/waitpkgintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/wbnoinvdintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/wmmintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/x86intrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/xmmintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/xopintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/xsavecintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/xsaveintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/xsaveoptintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/xsavesintrin.h +OLD_FILES+=usr/lib/clang/8.0.0/include/xtestintrin.h +OLD_DIRS+=usr/lib/clang/8.0.0/include +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan-i386.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan-i386.so +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan-preinit-i386.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan-preinit-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan-x86_64.so +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan_cxx-i386.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan_cxx-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.msan-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.msan_cxx-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.profile-arm.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.profile-armhf.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.profile-i386.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.profile-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.safestack-i386.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.safestack-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.stats-i386.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.stats-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.stats_client-i386.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.stats_client-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.tsan-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.tsan_cxx-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.ubsan_minimal-i386.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.ubsan_minimal-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.ubsan_standalone-i386.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.ubsan_standalone-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.ubsan_standalone_cxx-i386.a +OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.ubsan_standalone_cxx-x86_64.a +OLD_DIRS+=usr/lib/clang/8.0.0/lib/freebsd +OLD_DIRS+=usr/lib/clang/8.0.0/lib +OLD_DIRS+=usr/lib/clang/8.0.0 + # 20190523: Remove obsolete kgzip and support files OLD_FILES+=usr/sbin/kgzip OLD_FILES+=usr/lib/kgzldr.o @@ -1409,6 +1564,8 @@ OLD_DIRS+=usr/share/openssl/man/en.ISO8859-1/cat1 OLD_DIRS+=usr/share/openssl/man/en.ISO8859-1/cat3 # 20170802: ksyms(4) ioctl interface was removed OLD_FILES+=usr/include/sys/ksyms.h +# 20170729: the iicbus/pcf8563 driver is replaced with iicbus/nxprtc +OLD_FILES+=usr/include/dev/iicbus/pcf8563reg.h # 20170722: new clang import which bumps version from 4.0.0 to 5.0.0. OLD_FILES+=usr/lib/clang/4.0.0/include/sanitizer/allocator_interface.h OLD_FILES+=usr/lib/clang/4.0.0/include/sanitizer/asan_interface.h diff --git a/UPDATING b/UPDATING index 83f08910fb80..2cbf40c7640e 100644 --- a/UPDATING +++ b/UPDATING @@ -31,7 +31,7 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW: disable the most expensive debugging functionality run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) -20190606: +20190620: The vfs.fusefs.sync_unmount and vfs.fusefs.init_backgrounded sysctls and the "-o sync_unmount" and "-o init_backgrounded" mount options have been removed from mount_fusefs(8). You can safely remove them from @@ -43,6 +43,17 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW: felt the need to set any of them to a non-default value, please tell asomers@FreeBSD.org why. +20190612: + Clang, llvm, lld, lldb, compiler-rt, libc++, libunwind and openmp have + been upgraded to 8.0.1. Please see the 20141231 entry below for + information about prerequisites and upgrading, if you are not already + using clang 3.5.0 or higher. + +20190608: + A fix was applied to i386 kernel modules to avoid panics with + dpcpu or vnet. Users need to recompile i386 kernel modules + having pcpu or vnet sections or they will refuse to load. + 20190513: User-wired pages now have their own counter, vm.stats.vm.v_user_wire_count. The vm.max_wired sysctl was renamed diff --git a/bin/csh/Makefile b/bin/csh/Makefile index b0d4435d970c..9aabc047493a 100644 --- a/bin/csh/Makefile +++ b/bin/csh/Makefile @@ -117,6 +117,7 @@ csh.1: tcsh.man build-tools: gethost +DEPENDOBJS+= gethost gethost: gethost.c sh.err.h tc.const.h sh.h ${BUILD_TOOLS_META} @rm -f ${.TARGET} ${CC:N${CCACHE_BIN}} -o gethost ${LDFLAGS} ${CFLAGS:C/-DHAVE_ICONV//} \ diff --git a/bin/sh/Makefile b/bin/sh/Makefile index ee4fa87026cf..7787194fa686 100644 --- a/bin/sh/Makefile +++ b/bin/sh/Makefile @@ -48,6 +48,7 @@ builtins.h: .NOMETA builtins.c builtins.h: mkbuiltins builtins.def sh ${.CURDIR}/mkbuiltins ${.CURDIR} +DEPENDOBJS+= mknodes mksyntax mknodes mksyntax: ${BUILD_TOOLS_META} .ORDER: nodes.c nodes.h diff --git a/bin/stty/modes.c b/bin/stty/modes.c index e34afb83ee38..0fe4e5168d2c 100644 --- a/bin/stty/modes.c +++ b/bin/stty/modes.c @@ -91,6 +91,8 @@ static const struct modes cmodes[] = { { "-rtsflow", 0, CRTS_IFLOW }, { "mdmbuf", MDMBUF, 0 }, { "-mdmbuf", 0, MDMBUF }, + { "rtsdtr", 0, CNO_RTSDTR }, + { "-rtsdtr", CNO_RTSDTR, 0 }, { NULL, 0, 0 }, }; diff --git a/bin/stty/print.c b/bin/stty/print.c index 03d5c3b8a770..a76cd46b765e 100644 --- a/bin/stty/print.c +++ b/bin/stty/print.c @@ -184,6 +184,12 @@ print(struct termios *tp, struct winsize *wp, int ldisc, enum FMT fmt) put("-dsrflow", CDSR_OFLOW, 0); put("-dtrflow", CDTR_IFLOW, 0); put("-mdmbuf", MDMBUF, 0); /* XXX mdmbuf == dtrflow */ + if (on(CNO_RTSDTR)) + bput("-rtsdtr"); + else { + if (fmt >= BSD) + bput("rtsdtr"); + } /* special control characters */ cc = tp->c_cc; diff --git a/bin/stty/stty.1 b/bin/stty/stty.1 index a0f76fe2bfd1..1863c2286176 100644 --- a/bin/stty/stty.1 +++ b/bin/stty/stty.1 @@ -145,6 +145,8 @@ Assume a line without (with) modem control. .It Cm crtscts Pq Fl crtscts Enable (disable) RTS/CTS flow control. +.It Cm rtsdtr Pq Fl -rtsdtr +Enable (disable) asserting RTS/DTR on open. .El .Ss Input Modes: This corresponds to the c_iflag in the termios structure. diff --git a/cddl/usr.sbin/dtrace/tests/amd64/Makefile b/cddl/usr.sbin/dtrace/tests/amd64/Makefile new file mode 100644 index 000000000000..39ccd333bedf --- /dev/null +++ b/cddl/usr.sbin/dtrace/tests/amd64/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/cddl/usr.sbin/dtrace/amd64 +TESTS_SUBDIRS+= arrays + +.PATH: ${.CURDIR:H:H:H:H:H}/tests +KYUAFILE= YES + +.include diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc index c112e044b1d8..c32c80b3e48b 100644 --- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc +++ b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc @@ -124,7 +124,9 @@ #include #include #include +#if 0 #include +#endif #include #include #include diff --git a/contrib/elftoolchain/elfdump/elfdump.c b/contrib/elftoolchain/elfdump/elfdump.c index dfde9786c9f4..3c192cd21693 100644 --- a/contrib/elftoolchain/elfdump/elfdump.c +++ b/contrib/elftoolchain/elfdump/elfdump.c @@ -343,17 +343,20 @@ elf_phdr_type_str(unsigned int type) static char s_type[32]; switch (type) { - case PT_NULL: return "PT_NULL"; - case PT_LOAD: return "PT_LOAD"; - case PT_DYNAMIC: return "PT_DYNAMIC"; - case PT_INTERP: return "PT_INTERP"; - case PT_NOTE: return "PT_NOTE"; - case PT_SHLIB: return "PT_SHLIB"; - case PT_PHDR: return "PT_PHDR"; - case PT_TLS: return "PT_TLS"; - case PT_GNU_EH_FRAME: return "PT_GNU_EH_FRAME"; - case PT_GNU_STACK: return "PT_GNU_STACK"; - case PT_GNU_RELRO: return "PT_GNU_RELRO"; + case PT_NULL: return "PT_NULL"; + case PT_LOAD: return "PT_LOAD"; + case PT_DYNAMIC: return "PT_DYNAMIC"; + case PT_INTERP: return "PT_INTERP"; + case PT_NOTE: return "PT_NOTE"; + case PT_SHLIB: return "PT_SHLIB"; + case PT_PHDR: return "PT_PHDR"; + case PT_TLS: return "PT_TLS"; + case PT_GNU_EH_FRAME: return "PT_GNU_EH_FRAME"; + case PT_GNU_STACK: return "PT_GNU_STACK"; + case PT_GNU_RELRO: return "PT_GNU_RELRO"; + case PT_OPENBSD_RANDOMIZE: return "PT_OPENBSD_RANDOMIZE"; + case PT_OPENBSD_WXNEEDED: return "PT_OPENBSD_WXNEEDED"; + case PT_OPENBSD_BOOTDATA: return "PT_OPENBSD_BOOTDATA"; } snprintf(s_type, sizeof(s_type), "", type); return (s_type); diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c index 2c670bc7e7d5..f8d7fa2a5c5e 100644 --- a/contrib/elftoolchain/readelf/readelf.c +++ b/contrib/elftoolchain/readelf/readelf.c @@ -674,6 +674,9 @@ phdr_type(unsigned int mach, unsigned int ptype) case PT_GNU_EH_FRAME: return "GNU_EH_FRAME"; case PT_GNU_STACK: return "GNU_STACK"; case PT_GNU_RELRO: return "GNU_RELRO"; + case PT_OPENBSD_RANDOMIZE: return "OPENBSD_RANDOMIZE"; + case PT_OPENBSD_WXNEEDED: return "OPENBSD_WXNEEDED"; + case PT_OPENBSD_BOOTDATA: return "OPENBSD_BOOTDATA"; default: if (ptype >= PT_LOOS && ptype <= PT_HIOS) snprintf(s_ptype, sizeof(s_ptype), "LOOS+%#x", diff --git a/contrib/libarchive/NEWS b/contrib/libarchive/NEWS index e2d96aebd714..222532d1e978 100644 --- a/contrib/libarchive/NEWS +++ b/contrib/libarchive/NEWS @@ -1,3 +1,7 @@ +Jun 11, 2019: libarchive 3.4.0 released + +May 18, 2019: Fixes for reading Android APK and JAR archives + Apr 16, 2019: Support for non-recursive list and extract Apr 14, 2019: New tar option: --exclude-vcs @@ -6,7 +10,7 @@ Mar 27, 2019: Support for file and directory symlinks on Windows Mar 12, 2019: Important fixes for storing file attributes and flags -Jan 20, 2019: Support for xz, lzma, ppmd8 and bzip2 compression in zip archives +Jan 20, 2019: Support for xz, lzma, ppmd8 and bzip2 decompression in ZIP files Oct 06, 2018: RAR 5.0 reader diff --git a/contrib/libarchive/README.md b/contrib/libarchive/README.md index df19125f9030..2912b3d0a61e 100644 --- a/contrib/libarchive/README.md +++ b/contrib/libarchive/README.md @@ -81,6 +81,7 @@ Currently, the library automatically detects and reads the following fomats: * Binary cpio (big-endian or little-endian) * ISO9660 CD-ROM images (with optional Rockridge or Joliet extensions) * ZIP archives (with uncompressed or "deflate" compressed entries, including support for encrypted Zip archives) + * ZIPX archives (with support for bzip2, ppmd8, lzma and xz compressed entries) * GNU and BSD 'ar' archives * 'mtree' format * 7-Zip archives diff --git a/contrib/libarchive/libarchive/archive.h b/contrib/libarchive/libarchive/archive.h index 55c9ce38d296..d83f2b32fd26 100644 --- a/contrib/libarchive/libarchive/archive.h +++ b/contrib/libarchive/libarchive/archive.h @@ -36,7 +36,7 @@ * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3003003 +#define ARCHIVE_VERSION_NUMBER 3004000 #include #include /* for wchar_t */ @@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.3.3" +#define ARCHIVE_VERSION_ONLY_STRING "3.4.0" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); diff --git a/contrib/libarchive/libarchive/archive_entry.h b/contrib/libarchive/libarchive/archive_entry.h index 25300e927b98..5a6df1ad6a16 100644 --- a/contrib/libarchive/libarchive/archive_entry.h +++ b/contrib/libarchive/libarchive/archive_entry.h @@ -30,7 +30,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3003003 +#define ARCHIVE_VERSION_NUMBER 3004000 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/contrib/libarchive/libarchive/archive_read_support_format_rar.c b/contrib/libarchive/libarchive/archive_read_support_format_rar.c index 49360876c2ac..41e5a3cadd90 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_rar.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_rar.c @@ -1027,6 +1027,7 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff, if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN) { __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context); rar->start_new_table = 1; + rar->ppmd_valid = 0; } break; diff --git a/contrib/libarchive/libarchive/archive_read_support_format_rar5.c b/contrib/libarchive/libarchive/archive_read_support_format_rar5.c index 7c24627b186c..95579e15cf05 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_rar5.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_rar5.c @@ -1125,6 +1125,13 @@ static void init_header(struct archive_read* a) { a->archive.archive_format_name = "RAR5"; } +static void init_window_mask(struct rar5* rar) { + if (rar->cstate.window_size) + rar->cstate.window_mask = rar->cstate.window_size - 1; + else + rar->cstate.window_mask = 0; +} + enum HEADER_FLAGS { HFL_EXTRA_DATA = 0x0001, HFL_DATA = 0x0002, @@ -1672,6 +1679,7 @@ static int process_head_file(struct archive_read* a, struct rar5* rar, /* Values up to 64M should fit into ssize_t on every * architecture. */ rar->cstate.window_size = (ssize_t) window_size; + init_window_mask(rar); rar->file.solid = (compression_info & SOLID) > 0; rar->file.service = 0; @@ -2235,10 +2243,7 @@ static int rar5_read_header(struct archive_read *a, static void init_unpack(struct rar5* rar) { rar->file.calculated_crc32 = 0; - if (rar->cstate.window_size) - rar->cstate.window_mask = rar->cstate.window_size - 1; - else - rar->cstate.window_mask = 0; + init_window_mask(rar); free(rar->cstate.window_buf); free(rar->cstate.filtered_buf); @@ -2851,7 +2856,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { * - Values lower than 256 are just bytes. Those codes * can be stored in the output buffer directly. * - * - Code 256 defines a new filter, which is later used to + * - Code 256 defines a new filter, which is later used to * ransform the data block accordingly to the filter type. * The data block needs to be fully uncompressed first. * @@ -3906,7 +3911,7 @@ static int rar5_read_data_skip(struct archive_read *a) { /* Turn off "skip mode". */ rar->skip_mode--; - if(ret < 0) { + if(ret < 0 || ret == ARCHIVE_EOF) { /* Propagate any potential error conditions * to the caller. */ return ret; diff --git a/contrib/libarchive/libarchive/archive_write_add_filter_b64encode.c b/contrib/libarchive/libarchive/archive_write_add_filter_b64encode.c index 85eb087b0522..b46b19a0c74d 100644 --- a/contrib/libarchive/libarchive/archive_write_add_filter_b64encode.c +++ b/contrib/libarchive/libarchive/archive_write_add_filter_b64encode.c @@ -60,7 +60,7 @@ static int archive_filter_b64encode_write(struct archive_write_filter *, const void *, size_t); static int archive_filter_b64encode_close(struct archive_write_filter *); static int archive_filter_b64encode_free(struct archive_write_filter *); -static void b64_encode(struct archive_string *, const unsigned char *, size_t); +static void la_b64_encode(struct archive_string *, const unsigned char *, size_t); static int64_t atol8(const char *, size_t); static const char base64[] = { @@ -180,7 +180,7 @@ archive_filter_b64encode_open(struct archive_write_filter *f) } static void -b64_encode(struct archive_string *as, const unsigned char *p, size_t len) +la_b64_encode(struct archive_string *as, const unsigned char *p, size_t len) { int c; @@ -234,12 +234,12 @@ archive_filter_b64encode_write(struct archive_write_filter *f, const void *buff, } if (state->hold_len < LBYTES) return (ret); - b64_encode(&state->encoded_buff, state->hold, LBYTES); + la_b64_encode(&state->encoded_buff, state->hold, LBYTES); state->hold_len = 0; } for (; length >= LBYTES; length -= LBYTES, p += LBYTES) - b64_encode(&state->encoded_buff, p, LBYTES); + la_b64_encode(&state->encoded_buff, p, LBYTES); /* Save remaining bytes. */ if (length > 0) { @@ -270,7 +270,7 @@ archive_filter_b64encode_close(struct archive_write_filter *f) /* Flush remaining bytes. */ if (state->hold_len != 0) - b64_encode(&state->encoded_buff, state->hold, state->hold_len); + la_b64_encode(&state->encoded_buff, state->hold, state->hold_len); archive_string_sprintf(&state->encoded_buff, "====\n"); /* Write the last block */ archive_write_set_bytes_in_last_block(f->archive, 1); diff --git a/contrib/libarchive/libarchive/archive_write_disk_posix.c b/contrib/libarchive/libarchive/archive_write_disk_posix.c index e3d75078ce6e..3faa7e3afdc2 100644 --- a/contrib/libarchive/libarchive/archive_write_disk_posix.c +++ b/contrib/libarchive/libarchive/archive_write_disk_posix.c @@ -165,6 +165,10 @@ __FBSDID("$FreeBSD$"); #define O_NOFOLLOW 0 #endif +#ifndef AT_FDCWD +#define AT_FDCWD -100 +#endif + struct fixup_entry { struct fixup_entry *next; struct archive_acl acl; @@ -348,6 +352,8 @@ struct archive_write_disk { #define HFS_BLOCKS(s) ((s) >> 12) + +static int la_opendirat(int, const char *); static void fsobj_error(int *, struct archive_string *, int, const char *, const char *); static int check_symlinks_fsobj(char *, int *, struct archive_string *, @@ -400,6 +406,37 @@ static ssize_t _archive_write_disk_data(struct archive *, const void *, static ssize_t _archive_write_disk_data_block(struct archive *, const void *, size_t, int64_t); +static int +la_opendirat(int fd, const char *path) { + const int flags = O_CLOEXEC +#if defined(O_BINARY) + | O_BINARY +#endif +#if defined(O_DIRECTORY) + | O_DIRECTORY +#endif +#if defined(O_PATH) + | O_PATH +#elif defined(O_SEARCH) + | O_SEARCH +#elif defined(O_EXEC) + | O_EXEC +#else + | O_RDONLY +#endif + ; + +#if !defined(HAVE_OPENAT) + if (fd != AT_FDCWD) { + errno = ENOTSUP; + return (-1); + } else + return (open(fd, path, flags)); +#else + return (openat(fd, path, flags)); +#endif +} + static int lazy_stat(struct archive_write_disk *a) { @@ -1909,7 +1946,7 @@ edit_deep_directories(struct archive_write_disk *a) return; /* Try to record our starting dir. */ - a->restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC); + a->restore_pwd = la_opendirat(AT_FDCWD, "."); __archive_ensure_cloexec_flag(a->restore_pwd); if (a->restore_pwd < 0) return; @@ -2342,7 +2379,7 @@ _archive_write_disk_close(struct archive *_a) { struct archive_write_disk *a = (struct archive_write_disk *)_a; struct fixup_entry *next, *p; - int ret; + int fd, ret; archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, @@ -2353,21 +2390,33 @@ _archive_write_disk_close(struct archive *_a) p = sort_dir_list(a->fixup_list); while (p != NULL) { + fd = -1; a->pst = NULL; /* Mark stat cache as out-of-date. */ + if (p->fixup & + (TODO_TIMES | TODO_MODE_BASE | TODO_ACLS | TODO_FFLAGS)) { + fd = open(p->name, + O_WRONLY | O_BINARY | O_NOFOLLOW | O_CLOEXEC); + } if (p->fixup & TODO_TIMES) { - set_times(a, -1, p->mode, p->name, + set_times(a, fd, p->mode, p->name, p->atime, p->atime_nanos, p->birthtime, p->birthtime_nanos, p->mtime, p->mtime_nanos, p->ctime, p->ctime_nanos); } - if (p->fixup & TODO_MODE_BASE) + if (p->fixup & TODO_MODE_BASE) { +#ifdef HAVE_FCHMOD + if (fd >= 0) + fchmod(fd, p->mode); + else +#endif chmod(p->name, p->mode); + } if (p->fixup & TODO_ACLS) - archive_write_disk_set_acls(&a->archive, -1, p->name, - &p->acl, p->mode); + archive_write_disk_set_acls(&a->archive, fd, + p->name, &p->acl, p->mode); if (p->fixup & TODO_FFLAGS) - set_fflags_platform(a, -1, p->name, + set_fflags_platform(a, fd, p->name, p->mode, p->fflags_set, 0); if (p->fixup & TODO_MAC_METADATA) set_mac_metadata(a, p->name, p->mac_metadata, @@ -2376,6 +2425,8 @@ _archive_write_disk_close(struct archive *_a) archive_acl_clear(&p->acl); free(p->mac_metadata); free(p->name); + if (fd >= 0) + close(fd); free(p); p = next; } @@ -2540,8 +2591,6 @@ fsobj_error(int *a_eno, struct archive_string *a_estr, * scan the path and both can be optimized by comparing against other * recent paths. */ -/* TODO: Extend this to support symlinks on Windows Vista and later. */ - /* * Checks the given path to see if any elements along it are symlinks. Returns * ARCHIVE_OK if there are none, otherwise puts an error in errmsg. @@ -2550,7 +2599,8 @@ static int check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, int flags) { -#if !defined(HAVE_LSTAT) +#if !defined(HAVE_LSTAT) && \ + !(defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)) /* Platform doesn't have lstat, so we can't look for symlinks. */ (void)path; /* UNUSED */ (void)error_number; /* UNUSED */ @@ -2565,7 +2615,10 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, char c; int r; struct stat st; - int restore_pwd; + int chdir_fd; +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + int fd; +#endif /* Nothing to do here if name is empty */ if(path[0] == '\0') @@ -2586,9 +2639,9 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, * c holds what used to be in *tail * last is 1 if this is the last tail */ - restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC); - __archive_ensure_cloexec_flag(restore_pwd); - if (restore_pwd < 0) { + chdir_fd = la_opendirat(AT_FDCWD, "."); + __archive_ensure_cloexec_flag(chdir_fd); + if (chdir_fd < 0) { fsobj_error(a_eno, a_estr, errno, "Could not open ", path); return (ARCHIVE_FATAL); @@ -2621,7 +2674,11 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, c = tail[0]; tail[0] = '\0'; /* Check that we haven't hit a symlink. */ +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + r = fstatat(chdir_fd, head, &st, AT_SYMLINK_NOFOLLOW); +#else r = lstat(head, &st); +#endif if (r != 0) { tail[0] = c; /* We've hit a dir that doesn't exist; stop now. */ @@ -2647,7 +2704,19 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, } } else if (S_ISDIR(st.st_mode)) { if (!last) { - if (chdir(head) != 0) { +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + fd = la_opendirat(chdir_fd, head); + if (fd < 0) + r = -1; + else { + r = 0; + close(chdir_fd); + chdir_fd = fd; + } +#else + r = chdir(head); +#endif + if (r != 0) { tail[0] = c; fsobj_error(a_eno, a_estr, errno, "Could not chdir ", path); @@ -2664,7 +2733,12 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, * so we can overwrite it with the * item being extracted. */ - if (unlink(head)) { +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + r = unlinkat(chdir_fd, head, 0); +#else + r = unlink(head); +#endif + if (r != 0) { tail[0] = c; fsobj_error(a_eno, a_estr, errno, "Could not remove symlink ", @@ -2694,7 +2768,12 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, break; } else if (flags & ARCHIVE_EXTRACT_UNLINK) { /* User asked us to remove problems. */ - if (unlink(head) != 0) { +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + r = unlinkat(chdir_fd, head, 0); +#else + r = unlink(head); +#endif + if (r != 0) { tail[0] = c; fsobj_error(a_eno, a_estr, 0, "Cannot remove intervening " @@ -2712,7 +2791,11 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, * This is needed to extract hardlinks over * symlinks. */ +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + r = fstatat(chdir_fd, head, &st, 0); +#else r = la_stat(head, &st); +#endif if (r != 0) { tail[0] = c; if (errno == ENOENT) { @@ -2725,7 +2808,19 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, break; } } else if (S_ISDIR(st.st_mode)) { - if (chdir(head) != 0) { +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + fd = la_opendirat(chdir_fd, head); + if (fd < 0) + r = -1; + else { + r = 0; + close(chdir_fd); + chdir_fd = fd; + } +#else + r = chdir(head); +#endif + if (r != 0) { tail[0] = c; fsobj_error(a_eno, a_estr, errno, @@ -2761,16 +2856,21 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, } /* Catches loop exits via break */ tail[0] = c; -#ifdef HAVE_FCHDIR +#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT) + /* If we operate with openat(), fstatat() and unlinkat() there was + * no chdir(), so just close the fd */ + if (chdir_fd >= 0) + close(chdir_fd); +#elif HAVE_FCHDIR /* If we changed directory above, restore it here. */ - if (restore_pwd >= 0) { - r = fchdir(restore_pwd); + if (chdir_fd >= 0) { + r = fchdir(chdir_fd); if (r != 0) { fsobj_error(a_eno, a_estr, errno, "chdir() failure", ""); } - close(restore_pwd); - restore_pwd = -1; + close(chdir_fd); + chdir_fd = -1; if (r != 0) { res = (ARCHIVE_FATAL); } @@ -3387,6 +3487,7 @@ static int set_mode(struct archive_write_disk *a, int mode) { int r = ARCHIVE_OK; + int r2; mode &= 07777; /* Strip off file type bits. */ if (a->todo & TODO_SGID_CHECK) { @@ -3480,21 +3581,19 @@ set_mode(struct archive_write_disk *a, int mode) * post-extract fixup, which is handled elsewhere. */ #ifdef HAVE_FCHMOD - if (a->fd >= 0) { - if (fchmod(a->fd, mode) != 0) { - archive_set_error(&a->archive, errno, - "Can't set permissions to 0%o", (int)mode); - r = ARCHIVE_WARN; - } - } else + if (a->fd >= 0) + r2 = fchmod(a->fd, mode); + else #endif - /* If this platform lacks fchmod(), then - * we'll just use chmod(). */ - if (chmod(a->name, mode) != 0) { - archive_set_error(&a->archive, errno, - "Can't set permissions to 0%o", (int)mode); - r = ARCHIVE_WARN; - } + /* If this platform lacks fchmod(), then + * we'll just use chmod(). */ + r2 = chmod(a->name, mode); + + if (r2 != 0) { + archive_set_error(&a->archive, errno, + "Can't set permissions to 0%o", (int)mode); + r = ARCHIVE_WARN; + } } return (r); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar.c b/contrib/libarchive/libarchive/test/test_read_format_rar.c index f08b06bc69a3..1425eb9a4570 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_rar.c +++ b/contrib/libarchive/libarchive/test/test_read_format_rar.c @@ -3776,6 +3776,35 @@ DEFINE_TEST(test_read_format_rar_ppmd_use_after_free) assertA(ARCHIVE_OK == archive_read_next_header(a, &ae)); assertA(archive_read_data(a, buf, sizeof(buf)) <= 0); + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_ppmd_use_after_free2) +{ + uint8_t buf[16]; + const char* reffile = "test_read_format_rar_ppmd_use_after_free2.rar"; + + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + assertA(ARCHIVE_OK == archive_read_next_header(a, &ae)); + assertA(archive_read_data(a, buf, sizeof(buf)) <= 0); + assertA(ARCHIVE_OK == archive_read_next_header(a, &ae)); + assertA(archive_read_data(a, buf, sizeof(buf)) <= 0); + + /* Test EOF */ + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar5.c b/contrib/libarchive/libarchive/test/test_read_format_rar5.c index 1408f37c49dc..2a55e2015510 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_rar5.c +++ b/contrib/libarchive/libarchive/test/test_read_format_rar5.c @@ -1194,3 +1194,24 @@ DEFINE_TEST(test_read_format_rar5_fileattr) EPILOGUE(); } + +DEFINE_TEST(test_read_format_rar5_different_window_size) +{ + char buf[4096]; + PROLOGUE("test_read_format_rar5_different_window_size.rar"); + + /* Return codes of those calls are ignored, because this sample file + * is invalid. However, the unpacker shouldn't produce any SIGSEGV + * errors during processing. */ + + (void) archive_read_next_header(a, &ae); + while(0 != archive_read_data(a, buf, sizeof(buf))) {} + + (void) archive_read_next_header(a, &ae); + while(0 != archive_read_data(a, buf, sizeof(buf))) {} + + (void) archive_read_next_header(a, &ae); + while(0 != archive_read_data(a, buf, sizeof(buf))) {} + + EPILOGUE(); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar5_different_window_size.rar.uu b/contrib/libarchive/libarchive/test/test_read_format_rar5_different_window_size.rar.uu new file mode 100644 index 000000000000..bb4c4a60415e --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_rar5_different_window_size.rar.uu @@ -0,0 +1,675 @@ +begin 600 test_read_format_rar5_different_window_size.rar +M4F%R(1H'`0"-[P+2``'#M#P\7P$'`0"-[P+2``7#`/KZ^OKZA5N8F)B8F)@` +MF`*8T@7"F!=A_________P$$_____________________R%285(A&@?_____ +M_________________V@`[E##M#P\7P$'`0"-[P+2``7"87)26`!W=%)A\"T@`"QP\)`'(A&@\"T@`" +MQP\`"7(AFC`!&B/2+0`"*"%285(A&@<8`0"-[P+2``7#10!A4B$:!Q@!`#)S +M-/_______U)A\"T@`"!QS1T='1T='1T='6T='1T='1T='1T='1 +MT='1T='1T='1T='1T=&UQX`.`"'X"/\E``*H'#`"`/+__TO__O_G*_____\` +M`"\O``#_02+M____`-X`_["&AFVQJ@,#45TW,?;V]@$``/____\3]O;V]O;_ +M_S\``/]!(.VG+R\``/]!(.T)__^PWOS_```O+S$``/8@[;L````````````` +M-3XR9%Q<7%Q<7%Q<7%Q<7%QZ7%PJ7%Q<7"]<7%Q<7%Q<7%Q<7%Q<7%Q<7%Q< +M7#)<7#9<,F1I9V5R=#4V,61I870]+@HN"G0@9&5V270@9&1I9V5S7%Q<7'=E +M9"XR9&EG97)T-38R9&EA=#TN"BX*="!D979)="!D9&EG97-T/2X*+@HN"@HF +M+BX**%)A\"T@`"!QS1T='1T='1T='6T='1T='1T='1T='1T='1 +MT='1T='1T='1T=&UQX`.`"'X"/\E``*H'#`"`/+__TO__O_G*_____\``"\O +M``#_02+M____`-X`_["&AFVQJ@,#45TW,?;V]@$````````3]O;V]O;__S\` +M`/]!(.VG+R\``/]!(.T)__^PWOS_```O+P```/8@[;L`````````````-38R +M9%Q<7%Q<7%Q<7%Q<7%QZ7%PJ7%Q<7"]<7%Q<7%Q<7%Q<7%Q<7%Q<7%Q<7#)< +M7#9<,F1I9V5R=#4V,61I870]+@HN"G0@9&5V270@9&1I9V5S7%Q<7'=E9"XR +M9&EG97)T-38R9&EA=#TN"BX*="!D979)="!D9&EG97-T/2X*+@HN"@HF+E)A +M\"T@`"PP<KJZNKJZNKJZNKJZNKJZNKJ +MZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK#P\/#P\/#P\/#R\-MP\/# +MP\/#P\/#P\/#P\/#P\/#`\"T@`#QP\`"2$:TB,M``(H(5)A4B$:!Q@!`(WO`M(`!0`````````````` +M`````````0``````_____P#_965E965E965E965E965E965E8'-T/2X*+@HN +M"C(P-S`W,&EA='EAEQ<*EQ<7%PO7%Q<7%Q<7%Q<7%Q<7%Q<7%Q<7%PR7%PV7#!D:6=E +M\"T@`%PP`:!P`$9P`` +M````````[P+2``+'#P`)`"X),AP`_0$`%___"0`N"3(<`/T!`!?__Q%287(A +M_Q%287(A&H\Q`"@HW,@```/V-[P+2 +M``+'`"X),1P`_0$`%___$5)A<@$`C>\"T@`%PP`:!P`$9P``````````[P+2 +M``+'#P`)`"X),AP`_0$`%___$5)A\"T@`#QP\`"2$:TB,M``DA +M&M(C+0`"*"%285(A&@<8`0"-[P+2``7#`!H'`/R8__]E965E965E965E965E +M965E965@6%R(0HN"@HF+B8N"B@*+@HN"BY0 +M7B]A,C5I-F1G97-T/2X*+@HN"@HF+BX*"@HF+BX**`HN"BX*+E!<-3,R-C)D +M+W-.="`@6W-T/3TN"BX*+@H*)BXN"B@*+@HN"BY07#4S,C8A(2$A(2$A(2$A +M(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A +M(2$A(2$A(2$A(2$A(2$A(2$A+@H*)BXN+EPV7#)D:6=E\"T@`%```` +M```````````````````!``````#_____```O+P``_T$@[?___[#>`/\`AH:Q +M;?;V]@.J_O;_S_\`Q+[?$?;?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?___?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_? +MW]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W]_?W_^[XP## +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````#_________ +M__________________________________________\````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````"`````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````+8````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````!287(A&@\"T@`%PF%R4E@`=W1287(A&@EFZ>45J>E"(8*1QP&#AP1O__`````!X````````````` +MNKJZNKJZN@'U``"R____`````!X```"````````````````````````````` +M`"Q!`````````"T`%0``:#H`6@$M\"T@`"PP<< +MP@2```#_;24``F<<`0(`#@```0!02P@#`"8F)@!`___/0T+_____\?__K2-T +M='3_______[______R9"____,3,U__\3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3 +M$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$R8J8BQB`/______0D)"0D)"0D)"0D)"0D)" +M0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D+;V]O;V]O;V]O;V]O;-C8V +M-C8V&4PA`C8V-C8V-C8V-C8V-C8V&4PA`C8V-C8V-C8V-C8V-C8H*"@H*"@H +M*"@H*"@H(1H'`0"-[P(H*"@H*"@V-C8V-C8V-C8V-I8V-C8V-C8V-MO;VP`` +M````````````````````````````V]O;V]L`VP````#;V]L`VR@H*"@H*#8V +M-C8V-C8V-C8VEC8V-C8V-C8VV]O;``````````````````````````````#; +MV]O;VP#;`````-O;VP#;``````````````````````!"0D)"0D)"0D)S0D)" +M0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0EU=75)A4B$:!V%R0D)"0D)"0D)" +M0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0MO;V]O;V]O; +MV]O;V]LV-C8V-C893"$"-C8V-C8V-C8V-C8V-C893"$"-C8V-C8V-C8V-C8V +M-B@H*"@H*"@H*"@H*"@A&@\" +M*"@H*"@H-C8V-C8V-C8V-C:6-C8V-C8V-C;;V]L````````````````````` +M`````````-O;V]O;`-L`````V]O;`-L``````````````````````$)"0D)" +M0D)"0G-"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"75U=4F%2(1H'87)" +M0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)" +MV]O;V]O;V]O;V]O;VS8V-C8V-AE,(0(V-C8V-C8V-C8V-C8V-AE,(0(V-C8V +M-C8V-C8V-C8V*"@H*"@H*"@H*"@H*"$:!P$`C>\"*"@H*"@H-C8V-C8V-C8V +M-C:6-C8V-C8V-C;;V]L``````````````````````````````-O;V]O;`-L` +M````V]O;`-LH*"@H*"@V-C8V-C8V-C8V-I8V-C8V-C8V-MO;VP`````````` +M````````````````````V]O;V]L`VP````#;V]L`VP`````````````````` +M````0D)"0D)"0D)"\"T@`%PT4```!&%<\"T@`%PF%R4E@`=W1287(A&@7EY0H```#EY>7EY>7EY>7EY>7EY>7EY>7EY>7E +MY>7EY>7EY>5W=V%R(2\O+R`N"@H*75U=75U9R,C(R,C(R,C(R,C(R"<.`'\` +M``I=70!=!UU=7=D`Y>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7E +MY>7EY>7EY>7EY>7EY>7EY>7EY4$X.#@X]C@X+3@X.#@X.#@X.#@X.#@X.#@X +M.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#AR.#@X.#@X.#@X.#@X.#@X.#@X +M.#@X./DX.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X\"T@`%P_J%6YB8F)B8F`"8`IC2!<*8%V'_ +M________`03_____________________(5)A4B$:!___________________ +M____:`#N4,.T/#Q?`0\"T@`" +MQP\)`'(A&@\"T@`"QP\`"7(AFC`! +M&B/2+0`"*"%285(A&@<8`0"-[P+2``7#15\!!P$`C>\"T@`%PF%R4E@`=W12 +M87(A&@\"T@`%PP```$85!<)A +M\"T@`%PT4```!&%<\"T@`%PF%R4E@` +M=W1287(A&@`````````````+JZNKJZNKH!]0``LO___P`````>```` +M@``````````````````````````````L00`````````M`!4``&@Z`%H!+7-L +M-S8`R!$`````````XJ$`8VDP`#(`93$``/_______________P`````````` +M``H*"@H```!=75U=75U=75U=75U=75T````````````````````````````` +M``````!287(A&@7E"@```.7EY>7EY>7EY>7EY>7EY>7EY>7E +MY>7EY>7EY>7EY7=W87(A+R\O("X*"@I=75U=75G(R,C(R,C(R,C(R,C()PX` +M?P``"EU=`%T'75U=V0#EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7E +MY>7EY>7EY>7EY>7EY>7EY>7EY>7E03@X.#CV.#@M.#@X.#@X.#@X.#@X.#@X +M.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.'(X.#@X.#@X.#@X.#@X.#@X +M.#@X.#@X^3@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#AR.#@X=_[_________ +M&4PA`C8V-C8V-C8V-C8V-C8R&4PA`C8V-C8V-C8V-C8V-C8V-C8V-C8V"#8V +M-C:6-C8V-C8V-C;;V]O;V]O;V__;V]O;V]O;V]O;V]O;V]O;VS8V-C8V-C8V +M-C8V-C8V-@@V-C8VEC8V-C8V-C8VV]O;V]O;V]O;V]O;V]O;V]O;V]O;V]O; +MV]LV-C8V-C;;V]O;V]O;V]O;VUU=75U=75U=75U=75U=75U=75U=V]O;V]O; +MV]LV-C8V-C8V&4PA`C8V-C8V-C8V-MO;V]O;V]O;V]O;V]O;V]O;V]O;V]O; +MV]O;-C8V-C8V-AE,(0(V-C8V-C8V-C8V-C8V-AE,(0(V-C8V-C8V-C8V-C8V +M-C8V-C8V-C8V-C:6-C8V-C8V-C;;V]O;V]O;V]O;V]O;V]O;V]O;V]O;V]O; +MV]O;V]O;V]O;V]O;V]O;V]O;V]O;V]M"0D)"```````````````````````` +M``````````````````````````````````````````````````!"0D)"0D)" +M0D)S0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0EU=75)A4B$:!V%R0D)" +M0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0MO; +MV]O;V]O;V]O;V]LV-C8V-C893"$"-C8V-C8V-C8V-C8V-C893"$"-C8V-C8V +M-C8V-C8V-B@H*"@H*"@H*"@H*"@A&@\"*"@H*"@H-C8V-C8V-C8V-C:6-C8V-C8V +M-C;;V]L``````````````````````````````-O;V]O;`-L`````V]O;`-O_ +M____________________________________________________________ +M_____________________R8@)B8?)B8F)B8F)B8F)B8F)R8F```````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````/8``)0X.#@X73@X..7EY>4*```` +MY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7E=W=A7EY>7EY>7E +MY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>5!.#@X +M./8X."TX.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X +M.#@X\"*"@H*"@H-C8V-C8V-C8V-C:6-C8V-C8V-C;;V]L````````````````` +M`````````````-O;V]O;`-L`````V]O;`-L``````````````````````$)" +M0D)"0D)"0G-"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"75U=4F%2(1H' +M87)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)" +M0D)"V]O;V]O;V]O;V]O;VS8V-C8V-AE,(0(V-C8V-C8V-C8V-C8V-AE,(0(V +M-C8V-C8V-C8V-C8V*"@H*"@H*"@H*"@H*"$:!P$`C>\"*"@H*"@H-C8V-C8V +M-C8V-C:6-C8V-C8V-C;;V]L``````````````````````````````-O;V]O; +M`-L`````V]O;`-LH*"@H*"@V-C8V-C8V-C8V-I8V-C8V-C8V-MO;VP`````` +M````````````````````````V]O;V]L`VP````#;V]L`VP`````````````` +M````````0D)"0D)"0D)"\"*"@H*"@H-C8V-C8V-C8V-C:6-C8V-C8V-C;;V]L````` +M`````````````````````````-O;V]O;`-L`````V]O;`-L"-C8V-C8V-C8V +M-C8V-B@H*"@H*"@H*"@H*"@A&@\"*"@H*"@H-C8V-C8V-C8V-C:6-C8V-C8V-C;; +MV]L``````````````````````````````-O;V]O;`-L`````V]O;`-O_____ +M____________________________________________________________ +M_________________R8@)B8?)B8F)B8F)B8F)B8F)R8F```````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````/8``)0X.#@X73@X..7EY>4*````Y>7E +MY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7E=W=A7EY>7EY>7EY>7E +MY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>5!.#@X./8X +M."TX.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X.#@X +M\" +M*"@H*"@H-C8V-C8V-C8V-C:6-C8V-C8V-C;;V]L````````````````````` +M`````````-O;V]O;`-L`````V]O;`-L``````````````````````$)"0D)" +M0D)"0G-"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"75U=4F%2(1H'87)" +M0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)"0D)" +MV]O;V]O;V]O;V]O;VS8V-C8V-AE,(0(V-C8V-C8V-C8V-C8V-AE,(0(V-C8V +M-C8V-C8V-C8V*"@H*"@H*"@H*"@H*"$:!P$`C>\"*"@H*"@H-C8V-C8V-C8V +M-C:6-C8V-C8V-C;;V]L``````````````````````````````-O;V]O;`-L` +M````V]O;`-LH*"@H*"@V-C8V-C8V-C8V-I8V-C8V-C8V-MO;VP`````````` +M````````````````````V]O;V]L`VP````#;V]L`VP`````````````````` +M````0D)"0D)"0D)"\"*"@H*"@H-C8V-C8V-C8V-C:6-C8V-C8V-C;;V]L````````` +@`````````````````````-O;V]O;`-L`````V]O;`-L` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar_ppmd_use_after_free2.rar.uu b/contrib/libarchive/libarchive/test/test_read_format_rar_ppmd_use_after_free2.rar.uu new file mode 100644 index 000000000000..03c2eadfa4f3 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_rar_ppmd_use_after_free2.rar.uu @@ -0,0 +1,10 @@ +begin 664 test_read_format_rar_ppmd_use_after_free2.rar +M4F%R(1H'``1G=$Q24`!W````>U!+`P0Q`'#_J7\`+@TU'`#]`0`7__]"0D)" +M+W5N)B8F)F=I9`UD#1T+``!"`````````&%R(1H'``3_________`F@`H2`` +M``"`P\/#2\/#P\/#P\/#P\-3PP"`P\/#PYZ>AYZ>GI[#4\,`@,/#`L,@(""= +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@(/______ +M__\@("`@("`@("`@("`@("`@("`@("`@("`$9W1,4E``=P```'M02P,$,0!P +M_ZE_`"X--1P`_0$`%___0D)"0B]U;B8F)B9G:60-9`T="P``0@````````!A +0 + * Copyright (c) 2000-2002, 2007, 2010 + * 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 @@ -198,6 +200,27 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) output = STDERR_FILENO; } + /* + * Turn off echo if possible. + * If we are using a tty but are not the foreground pgrp this will + * generate SIGTTOU, so do it *before* installing the signal handlers. + */ + if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) { + memcpy(&term, &oterm, sizeof(term)); + if (!(flags & RPP_ECHO_ON)) + term.c_lflag &= ~(ECHO | ECHONL); +#ifdef VSTATUS + if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) + term.c_cc[VSTATUS] = _POSIX_VDISABLE; +#endif + (void)tcsetattr(input, _T_FLUSH, &term); + } else { + memset(&term, 0, sizeof(term)); + term.c_lflag |= ECHO; + memset(&oterm, 0, sizeof(oterm)); + oterm.c_lflag |= ECHO; + } + /* * Catch signals that would otherwise cause the user to end * up with echo turned off in the shell. Don't worry about @@ -217,57 +240,41 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) (void)sigaction(SIGTTIN, &sa, &savettin); (void)sigaction(SIGTTOU, &sa, &savettou); - /* Turn off echo if possible. */ - if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) { - memcpy(&term, &oterm, sizeof(term)); - if (!(flags & RPP_ECHO_ON)) - term.c_lflag &= ~(ECHO | ECHONL); -#ifdef VSTATUS - if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) - term.c_cc[VSTATUS] = _POSIX_VDISABLE; -#endif - (void)tcsetattr(input, _T_FLUSH, &term); - } else { - memset(&term, 0, sizeof(term)); - term.c_lflag |= ECHO; - memset(&oterm, 0, sizeof(oterm)); - oterm.c_lflag |= ECHO; + if (!(flags & RPP_STDIN)) { + int r = write(output, prompt, strlen(prompt)); + (void)r; } - - /* No I/O if we are already backgrounded. */ - if (signo[SIGTTOU] != 1 && signo[SIGTTIN] != 1) { - if (!(flags & RPP_STDIN)) { - int r = write(output, prompt, strlen(prompt)); - (void)r; - } - end = buf + bufsiz - 1; - p = buf; - while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') { - if (p < end) { - if ((flags & RPP_SEVENBIT)) - ch &= 0x7f; - if (isalpha((unsigned char)ch)) { - if ((flags & RPP_FORCELOWER)) - ch = (char)tolower((unsigned char)ch); - if ((flags & RPP_FORCEUPPER)) - ch = (char)toupper((unsigned char)ch); - } - *p++ = ch; + end = buf + bufsiz - 1; + p = buf; + while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') { + if (p < end) { + if ((flags & RPP_SEVENBIT)) + ch &= 0x7f; + if (isalpha((unsigned char)ch)) { + if ((flags & RPP_FORCELOWER)) + ch = (char)tolower((unsigned char)ch); + if ((flags & RPP_FORCEUPPER)) + ch = (char)toupper((unsigned char)ch); } + *p++ = ch; } - *p = '\0'; - save_errno = errno; - if (!(term.c_lflag & ECHO)) { - int r = write(output, "\n", 1); - (void)r; - } + } + *p = '\0'; + save_errno = errno; + if (!(term.c_lflag & ECHO)) { + int r = write(output, "\n", 1); + (void)r; } /* Restore old terminal settings and signals. */ if (memcmp(&term, &oterm, sizeof(term)) != 0) { + const int sigttou = signo[SIGTTOU]; + + /* Ignore SIGTTOU generated when we are not the fg pgrp. */ while (tcsetattr(input, _T_FLUSH, &oterm) == -1 && - errno == EINTR) + errno == EINTR && !signo[SIGTTOU]) continue; + signo[SIGTTOU] = sigttou; } (void)sigaction(SIGALRM, &savealrm, NULL); (void)sigaction(SIGHUP, &savehup, NULL); diff --git a/contrib/libarchive/tar/bsdtar.1 b/contrib/libarchive/tar/bsdtar.1 index 82840547007a..6d8d6d3d617a 100644 --- a/contrib/libarchive/tar/bsdtar.1 +++ b/contrib/libarchive/tar/bsdtar.1 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 1, 2017 +.Dd June 3, 2019 .Dt TAR 1 .Os .Sh NAME @@ -198,7 +198,7 @@ options and before extracting any files. .It Fl Fl clear-nochange-fflags (x mode only) Before removing file system objects to replace them, clear platform-specific -file flags that might prevent removal. +file attributes or file flags that might prevent removal. .It Fl Fl exclude Ar pattern Do not process files or directories that match the specified pattern. @@ -218,7 +218,8 @@ and .Sq Darcs . .It Fl Fl fflags (c, r, u, x modes only) -Archive or extract file flags. This is the reverse of +Archive or extract platform-specific file attributes or file flags. +This is the reverse of .Fl Fl no-fflags and the default behavior in c, r, and u modes or if .Nm @@ -389,8 +390,8 @@ Do not extract modification time. By default, the modification time is set to the time stored in the archive. .It Fl Fl mac-metadata (c, r, u and x mode only) -Mac OS X specific. Archive or extract extended ACLs and extended attributes -using +Mac OS X specific. Archive or extract extended ACLs and extended file +attributes using .Xr copyfile 3 in AppleDouble format. This is the reverse of .Fl Fl no-mac-metadata . @@ -445,21 +446,21 @@ and the default behavior if is run as non-root in x mode (on Mac OS X as any user in c, r, u and x modes). .It Fl Fl no-fflags (c, r, u, x modes only) -Do not archive or extract file flags. This is the reverse of +Do not archive or extract file attributes or file flags. This is the reverse of .Fl Fl fflags and the default behavior if .Nm is run as non-root in x mode. .It Fl Fl no-mac-metadata (x mode only) -Mac OS X specific. Do not archive or extract ACLs and extended attributes using +Mac OS X specific. Do not archive or extract ACLs and extended file attributes +using .Xr copyfile 3 in AppleDouble format. This is the reverse of .Fl Fl mac-metadata . and the default behavior if .Nm is run as non-root in x mode. -.It Fl n , Fl Fl norecurse , Fl Fl no-recursion .It Fl Fl no-same-owner (x mode only) Do not extract owner and group IDs. @@ -470,8 +471,8 @@ and the default behavior if is run as non-root. .It Fl Fl no-same-permissions (x mode only) -Do not extract full permissions (SGID, SUID, sticky bit, ACLs, -extended attributes or extended file flags). +Do not extract full permissions (SGID, SUID, sticky bit, +file attributes or file flags, extended file attributes and ACLs). This is the reverse of .Fl p and the default behavior if @@ -479,7 +480,7 @@ and the default behavior if is run as non-root. .It Fl Fl no-xattrs (c, r, u, x modes only) -Do not archive or extract extended attributes. This is the reverse of +Do not archive or extract extended file attributes. This is the reverse of .Fl Fl xattrs and the default behavior if .Nm @@ -667,13 +668,13 @@ This option suppresses these behaviors. .It Fl p , Fl Fl insecure , Fl Fl preserve-permissions (x mode only) Preserve file permissions. -Attempt to restore the full permissions, including owner, file modes, ACLs, -extended attributes and extended file flags, if available, for each item -extracted from the archive. This is te reverse of +Attempt to restore the full permissions, including file modes, file attributes +or file flags, extended file attributes and ACLs, if available, for each item +extracted from the archive. This is the reverse of .Fl Fl no-same-permissions and the default if .Nm -is being run by root and can be partially overridden by also specifying +is being run as root. It can be partially overridden by also specifying .Fl Fl no-acls , .Fl Fl no-fflags , .Fl Fl no-mac-metadata @@ -844,7 +845,7 @@ See for more information about the handling of exclusions. .It Fl Fl xattrs (c, r, u, x modes only) -Archive or extract extended attributes. This is the reverse of +Archive or extract extended file attributes. This is the reverse of .Fl Fl no-xattrs and the default behavior in c, r, and u modes or if .Nm diff --git a/contrib/libunwind/src/UnwindRegistersRestore.S b/contrib/libunwind/src/UnwindRegistersRestore.S index 9c9f481b10dd..518eef7a74b5 100644 --- a/contrib/libunwind/src/UnwindRegistersRestore.S +++ b/contrib/libunwind/src/UnwindRegistersRestore.S @@ -396,119 +396,119 @@ Lnovec: #elif defined(__ppc__) DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) -; -; void libunwind::Registers_ppc::jumpto() -; -; On entry: -; thread_state pointer is in r3 -; +// +// void libunwind::Registers_ppc::jumpto() +// +// On entry: +// thread_state pointer is in r3 +// - ; restore integral registerrs - ; skip r0 for now - ; skip r1 for now - lwz r2, 16(r3) - ; skip r3 for now - ; skip r4 for now - ; skip r5 for now - lwz r6, 32(r3) - lwz r7, 36(r3) - lwz r8, 40(r3) - lwz r9, 44(r3) - lwz r10, 48(r3) - lwz r11, 52(r3) - lwz r12, 56(r3) - lwz r13, 60(r3) - lwz r14, 64(r3) - lwz r15, 68(r3) - lwz r16, 72(r3) - lwz r17, 76(r3) - lwz r18, 80(r3) - lwz r19, 84(r3) - lwz r20, 88(r3) - lwz r21, 92(r3) - lwz r22, 96(r3) - lwz r23,100(r3) - lwz r24,104(r3) - lwz r25,108(r3) - lwz r26,112(r3) - lwz r27,116(r3) - lwz r28,120(r3) - lwz r29,124(r3) - lwz r30,128(r3) - lwz r31,132(r3) + // restore integral registerrs + // skip r0 for now + // skip r1 for now + lwz %r2, 16(%r3) + // skip r3 for now + // skip r4 for now + // skip r5 for now + lwz %r6, 32(%r3) + lwz %r7, 36(%r3) + lwz %r8, 40(%r3) + lwz %r9, 44(%r3) + lwz %r10, 48(%r3) + lwz %r11, 52(%r3) + lwz %r12, 56(%r3) + lwz %r13, 60(%r3) + lwz %r14, 64(%r3) + lwz %r15, 68(%r3) + lwz %r16, 72(%r3) + lwz %r17, 76(%r3) + lwz %r18, 80(%r3) + lwz %r19, 84(%r3) + lwz %r20, 88(%r3) + lwz %r21, 92(%r3) + lwz %r22, 96(%r3) + lwz %r23,100(%r3) + lwz %r24,104(%r3) + lwz %r25,108(%r3) + lwz %r26,112(%r3) + lwz %r27,116(%r3) + lwz %r28,120(%r3) + lwz %r29,124(%r3) + lwz %r30,128(%r3) + lwz %r31,132(%r3) - ; restore float registers - lfd f0, 160(r3) - lfd f1, 168(r3) - lfd f2, 176(r3) - lfd f3, 184(r3) - lfd f4, 192(r3) - lfd f5, 200(r3) - lfd f6, 208(r3) - lfd f7, 216(r3) - lfd f8, 224(r3) - lfd f9, 232(r3) - lfd f10,240(r3) - lfd f11,248(r3) - lfd f12,256(r3) - lfd f13,264(r3) - lfd f14,272(r3) - lfd f15,280(r3) - lfd f16,288(r3) - lfd f17,296(r3) - lfd f18,304(r3) - lfd f19,312(r3) - lfd f20,320(r3) - lfd f21,328(r3) - lfd f22,336(r3) - lfd f23,344(r3) - lfd f24,352(r3) - lfd f25,360(r3) - lfd f26,368(r3) - lfd f27,376(r3) - lfd f28,384(r3) - lfd f29,392(r3) - lfd f30,400(r3) - lfd f31,408(r3) + // restore float registers + lfd %f0, 160(%r3) + lfd %f1, 168(%r3) + lfd %f2, 176(%r3) + lfd %f3, 184(%r3) + lfd %f4, 192(%r3) + lfd %f5, 200(%r3) + lfd %f6, 208(%r3) + lfd %f7, 216(%r3) + lfd %f8, 224(%r3) + lfd %f9, 232(%r3) + lfd %f10,240(%r3) + lfd %f11,248(%r3) + lfd %f12,256(%r3) + lfd %f13,264(%r3) + lfd %f14,272(%r3) + lfd %f15,280(%r3) + lfd %f16,288(%r3) + lfd %f17,296(%r3) + lfd %f18,304(%r3) + lfd %f19,312(%r3) + lfd %f20,320(%r3) + lfd %f21,328(%r3) + lfd %f22,336(%r3) + lfd %f23,344(%r3) + lfd %f24,352(%r3) + lfd %f25,360(%r3) + lfd %f26,368(%r3) + lfd %f27,376(%r3) + lfd %f28,384(%r3) + lfd %f29,392(%r3) + lfd %f30,400(%r3) + lfd %f31,408(%r3) - ; restore vector registers if any are in use - lwz r5,156(r3) ; test VRsave - cmpwi r5,0 - beq Lnovec - - subi r4,r1,16 - rlwinm r4,r4,0,0,27 ; mask low 4-bits - ; r4 is now a 16-byte aligned pointer into the red zone - ; the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer + // restore vector registers if any are in use + lwz %r5, 156(%r3) // test VRsave + cmpwi %r5, 0 + beq Lnovec + subi %r4, %r1, 16 + rlwinm %r4, %r4, 0, 0, 27 // mask low 4-bits + // r4 is now a 16-byte aligned pointer into the red zone + // the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer + #define LOAD_VECTOR_UNALIGNEDl(_index) \ - andis. r0,r5,(1<<(15-_index)) @\ - beq Ldone ## _index @\ - lwz r0, 424+_index*16(r3) @\ - stw r0, 0(r4) @\ - lwz r0, 424+_index*16+4(r3) @\ - stw r0, 4(r4) @\ - lwz r0, 424+_index*16+8(r3) @\ - stw r0, 8(r4) @\ - lwz r0, 424+_index*16+12(r3)@\ - stw r0, 12(r4) @\ - lvx v ## _index,0,r4 @\ -Ldone ## _index: + andis. %r0, %r5, (1<<(15-_index)) SEPARATOR \ + beq Ldone ## _index SEPARATOR \ + lwz %r0, 424+_index*16(%r3) SEPARATOR \ + stw %r0, 0(%r4) SEPARATOR \ + lwz %r0, 424+_index*16+4(%r3) SEPARATOR \ + stw %r0, 4(%r4) SEPARATOR \ + lwz %r0, 424+_index*16+8(%r3) SEPARATOR \ + stw %r0, 8(%r4) SEPARATOR \ + lwz %r0, 424+_index*16+12(%r3) SEPARATOR \ + stw %r0, 12(%r4) SEPARATOR \ + lvx %v ## _index, 0, %r4 SEPARATOR \ + Ldone ## _index: #define LOAD_VECTOR_UNALIGNEDh(_index) \ - andi. r0,r5,(1<<(31-_index)) @\ - beq Ldone ## _index @\ - lwz r0, 424+_index*16(r3) @\ - stw r0, 0(r4) @\ - lwz r0, 424+_index*16+4(r3) @\ - stw r0, 4(r4) @\ - lwz r0, 424+_index*16+8(r3) @\ - stw r0, 8(r4) @\ - lwz r0, 424+_index*16+12(r3)@\ - stw r0, 12(r4) @\ - lvx v ## _index,0,r4 @\ - Ldone ## _index: + andi. %r0, %r5, (1<<(31-_index)) SEPARATOR \ + beq Ldone ## _index SEPARATOR \ + lwz %r0, 424+_index*16(%r3) SEPARATOR \ + stw %r0, 0(%r4) SEPARATOR \ + lwz %r0, 424+_index*16+4(%r3) SEPARATOR \ + stw %r0, 4(%r4) SEPARATOR \ + lwz %r0, 424+_index*16+8(%r3) SEPARATOR \ + stw %r0, 8(%r4) SEPARATOR \ + lwz %r0, 424+_index*16+12(%r3) SEPARATOR \ + stw %r0, 12(%r4) SEPARATOR \ + lvx %v ## _index, 0, %r4 SEPARATOR \ + Ldone ## _index: LOAD_VECTOR_UNALIGNEDl(0) @@ -545,17 +545,17 @@ Ldone ## _index: LOAD_VECTOR_UNALIGNEDh(31) Lnovec: - lwz r0, 136(r3) ; __cr - mtocrf 255,r0 - lwz r0, 148(r3) ; __ctr - mtctr r0 - lwz r0, 0(r3) ; __ssr0 - mtctr r0 - lwz r0, 8(r3) ; do r0 now - lwz r5,28(r3) ; do r5 now - lwz r4,24(r3) ; do r4 now - lwz r1,12(r3) ; do sp now - lwz r3,20(r3) ; do r3 last + lwz %r0, 136(%r3) // __cr + mtcr %r0 + lwz %r0, 148(%r3) // __ctr + mtctr %r0 + lwz %r0, 0(%r3) // __ssr0 + mtctr %r0 + lwz %r0, 8(%r3) // do r0 now + lwz %r5, 28(%r3) // do r5 now + lwz %r4, 24(%r3) // do r4 now + lwz %r1, 12(%r3) // do sp now + lwz %r3, 20(%r3) // do r3 last bctr #elif defined(__arm64__) || defined(__aarch64__) diff --git a/contrib/libunwind/src/UnwindRegistersSave.S b/contrib/libunwind/src/UnwindRegistersSave.S index aa42df3f9497..b40a71fb34d4 100644 --- a/contrib/libunwind/src/UnwindRegistersSave.S +++ b/contrib/libunwind/src/UnwindRegistersSave.S @@ -557,144 +557,144 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) #elif defined(__ppc__) -; -; extern int unw_getcontext(unw_context_t* thread_state) -; -; On entry: -; thread_state pointer is in r3 -; +// +// extern int unw_getcontext(unw_context_t* thread_state) +// +// On entry: +// thread_state pointer is in r3 +// DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) - stw r0, 8(r3) - mflr r0 - stw r0, 0(r3) ; store lr as ssr0 - stw r1, 12(r3) - stw r2, 16(r3) - stw r3, 20(r3) - stw r4, 24(r3) - stw r5, 28(r3) - stw r6, 32(r3) - stw r7, 36(r3) - stw r8, 40(r3) - stw r9, 44(r3) - stw r10, 48(r3) - stw r11, 52(r3) - stw r12, 56(r3) - stw r13, 60(r3) - stw r14, 64(r3) - stw r15, 68(r3) - stw r16, 72(r3) - stw r17, 76(r3) - stw r18, 80(r3) - stw r19, 84(r3) - stw r20, 88(r3) - stw r21, 92(r3) - stw r22, 96(r3) - stw r23,100(r3) - stw r24,104(r3) - stw r25,108(r3) - stw r26,112(r3) - stw r27,116(r3) - stw r28,120(r3) - stw r29,124(r3) - stw r30,128(r3) - stw r31,132(r3) + stw %r0, 8(%r3) + mflr %r0 + stw %r0, 0(%r3) // store lr as ssr0 + stw %r1, 12(%r3) + stw %r2, 16(%r3) + stw %r3, 20(%r3) + stw %r4, 24(%r3) + stw %r5, 28(%r3) + stw %r6, 32(%r3) + stw %r7, 36(%r3) + stw %r8, 40(%r3) + stw %r9, 44(%r3) + stw %r10, 48(%r3) + stw %r11, 52(%r3) + stw %r12, 56(%r3) + stw %r13, 60(%r3) + stw %r14, 64(%r3) + stw %r15, 68(%r3) + stw %r16, 72(%r3) + stw %r17, 76(%r3) + stw %r18, 80(%r3) + stw %r19, 84(%r3) + stw %r20, 88(%r3) + stw %r21, 92(%r3) + stw %r22, 96(%r3) + stw %r23,100(%r3) + stw %r24,104(%r3) + stw %r25,108(%r3) + stw %r26,112(%r3) + stw %r27,116(%r3) + stw %r28,120(%r3) + stw %r29,124(%r3) + stw %r30,128(%r3) + stw %r31,132(%r3) - ; save VRSave register - mfspr r0,256 - stw r0,156(r3) - ; save CR registers - mfcr r0 - stw r0,136(r3) - ; save CTR register - mfctr r0 - stw r0,148(r3) + // save VRSave register + mfspr %r0, 256 + stw %r0, 156(%r3) + // save CR registers + mfcr %r0 + stw %r0, 136(%r3) + // save CTR register + mfctr %r0 + stw %r0, 148(%r3) - ; save float registers - stfd f0, 160(r3) - stfd f1, 168(r3) - stfd f2, 176(r3) - stfd f3, 184(r3) - stfd f4, 192(r3) - stfd f5, 200(r3) - stfd f6, 208(r3) - stfd f7, 216(r3) - stfd f8, 224(r3) - stfd f9, 232(r3) - stfd f10,240(r3) - stfd f11,248(r3) - stfd f12,256(r3) - stfd f13,264(r3) - stfd f14,272(r3) - stfd f15,280(r3) - stfd f16,288(r3) - stfd f17,296(r3) - stfd f18,304(r3) - stfd f19,312(r3) - stfd f20,320(r3) - stfd f21,328(r3) - stfd f22,336(r3) - stfd f23,344(r3) - stfd f24,352(r3) - stfd f25,360(r3) - stfd f26,368(r3) - stfd f27,376(r3) - stfd f28,384(r3) - stfd f29,392(r3) - stfd f30,400(r3) - stfd f31,408(r3) + // save float registers + stfd %f0, 160(%r3) + stfd %f1, 168(%r3) + stfd %f2, 176(%r3) + stfd %f3, 184(%r3) + stfd %f4, 192(%r3) + stfd %f5, 200(%r3) + stfd %f6, 208(%r3) + stfd %f7, 216(%r3) + stfd %f8, 224(%r3) + stfd %f9, 232(%r3) + stfd %f10,240(%r3) + stfd %f11,248(%r3) + stfd %f12,256(%r3) + stfd %f13,264(%r3) + stfd %f14,272(%r3) + stfd %f15,280(%r3) + stfd %f16,288(%r3) + stfd %f17,296(%r3) + stfd %f18,304(%r3) + stfd %f19,312(%r3) + stfd %f20,320(%r3) + stfd %f21,328(%r3) + stfd %f22,336(%r3) + stfd %f23,344(%r3) + stfd %f24,352(%r3) + stfd %f25,360(%r3) + stfd %f26,368(%r3) + stfd %f27,376(%r3) + stfd %f28,384(%r3) + stfd %f29,392(%r3) + stfd %f30,400(%r3) + stfd %f31,408(%r3) - ; save vector registers + // save vector registers - subi r4,r1,16 - rlwinm r4,r4,0,0,27 ; mask low 4-bits - ; r4 is now a 16-byte aligned pointer into the red zone + subi %r4, %r1, 16 + rlwinm %r4, %r4, 0, 0, 27 // mask low 4-bits + // r4 is now a 16-byte aligned pointer into the red zone #define SAVE_VECTOR_UNALIGNED(_vec, _offset) \ - stvx _vec,0,r4 @\ - lwz r5, 0(r4) @\ - stw r5, _offset(r3) @\ - lwz r5, 4(r4) @\ - stw r5, _offset+4(r3) @\ - lwz r5, 8(r4) @\ - stw r5, _offset+8(r3) @\ - lwz r5, 12(r4) @\ - stw r5, _offset+12(r3) + stvx _vec, 0, %r4 SEPARATOR \ + lwz %r5, 0(%r4) SEPARATOR \ + stw %r5, _offset(%r3) SEPARATOR \ + lwz %r5, 4(%r4) SEPARATOR \ + stw %r5, _offset+4(%r3) SEPARATOR \ + lwz %r5, 8(%r4) SEPARATOR \ + stw %r5, _offset+8(%r3) SEPARATOR \ + lwz %r5, 12(%r4) SEPARATOR \ + stw %r5, _offset+12(%r3) - SAVE_VECTOR_UNALIGNED( v0, 424+0x000) - SAVE_VECTOR_UNALIGNED( v1, 424+0x010) - SAVE_VECTOR_UNALIGNED( v2, 424+0x020) - SAVE_VECTOR_UNALIGNED( v3, 424+0x030) - SAVE_VECTOR_UNALIGNED( v4, 424+0x040) - SAVE_VECTOR_UNALIGNED( v5, 424+0x050) - SAVE_VECTOR_UNALIGNED( v6, 424+0x060) - SAVE_VECTOR_UNALIGNED( v7, 424+0x070) - SAVE_VECTOR_UNALIGNED( v8, 424+0x080) - SAVE_VECTOR_UNALIGNED( v9, 424+0x090) - SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0) - SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0) - SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0) - SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0) - SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0) - SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0) - SAVE_VECTOR_UNALIGNED(v16, 424+0x100) - SAVE_VECTOR_UNALIGNED(v17, 424+0x110) - SAVE_VECTOR_UNALIGNED(v18, 424+0x120) - SAVE_VECTOR_UNALIGNED(v19, 424+0x130) - SAVE_VECTOR_UNALIGNED(v20, 424+0x140) - SAVE_VECTOR_UNALIGNED(v21, 424+0x150) - SAVE_VECTOR_UNALIGNED(v22, 424+0x160) - SAVE_VECTOR_UNALIGNED(v23, 424+0x170) - SAVE_VECTOR_UNALIGNED(v24, 424+0x180) - SAVE_VECTOR_UNALIGNED(v25, 424+0x190) - SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0) - SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0) - SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0) - SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0) - SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0) - SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0) + SAVE_VECTOR_UNALIGNED( %v0, 424+0x000) + SAVE_VECTOR_UNALIGNED( %v1, 424+0x010) + SAVE_VECTOR_UNALIGNED( %v2, 424+0x020) + SAVE_VECTOR_UNALIGNED( %v3, 424+0x030) + SAVE_VECTOR_UNALIGNED( %v4, 424+0x040) + SAVE_VECTOR_UNALIGNED( %v5, 424+0x050) + SAVE_VECTOR_UNALIGNED( %v6, 424+0x060) + SAVE_VECTOR_UNALIGNED( %v7, 424+0x070) + SAVE_VECTOR_UNALIGNED( %v8, 424+0x080) + SAVE_VECTOR_UNALIGNED( %v9, 424+0x090) + SAVE_VECTOR_UNALIGNED(%v10, 424+0x0A0) + SAVE_VECTOR_UNALIGNED(%v11, 424+0x0B0) + SAVE_VECTOR_UNALIGNED(%v12, 424+0x0C0) + SAVE_VECTOR_UNALIGNED(%v13, 424+0x0D0) + SAVE_VECTOR_UNALIGNED(%v14, 424+0x0E0) + SAVE_VECTOR_UNALIGNED(%v15, 424+0x0F0) + SAVE_VECTOR_UNALIGNED(%v16, 424+0x100) + SAVE_VECTOR_UNALIGNED(%v17, 424+0x110) + SAVE_VECTOR_UNALIGNED(%v18, 424+0x120) + SAVE_VECTOR_UNALIGNED(%v19, 424+0x130) + SAVE_VECTOR_UNALIGNED(%v20, 424+0x140) + SAVE_VECTOR_UNALIGNED(%v21, 424+0x150) + SAVE_VECTOR_UNALIGNED(%v22, 424+0x160) + SAVE_VECTOR_UNALIGNED(%v23, 424+0x170) + SAVE_VECTOR_UNALIGNED(%v24, 424+0x180) + SAVE_VECTOR_UNALIGNED(%v25, 424+0x190) + SAVE_VECTOR_UNALIGNED(%v26, 424+0x1A0) + SAVE_VECTOR_UNALIGNED(%v27, 424+0x1B0) + SAVE_VECTOR_UNALIGNED(%v28, 424+0x1C0) + SAVE_VECTOR_UNALIGNED(%v29, 424+0x1D0) + SAVE_VECTOR_UNALIGNED(%v30, 424+0x1E0) + SAVE_VECTOR_UNALIGNED(%v31, 424+0x1F0) - li r3, 0 ; return UNW_ESUCCESS + li %r3, 0 // return UNW_ESUCCESS blr diff --git a/contrib/libunwind/src/assembly.h b/contrib/libunwind/src/assembly.h index 2df930214fae..7806892e9dcf 100644 --- a/contrib/libunwind/src/assembly.h +++ b/contrib/libunwind/src/assembly.h @@ -29,8 +29,6 @@ #ifdef _ARCH_PWR8 #define PPC64_HAS_VMX #endif -#elif defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__) -#define SEPARATOR @ #elif defined(__arm64__) #define SEPARATOR %% #else diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index ba55ffc28174..8a88a2fa3a09 100644 --- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -301,7 +301,7 @@ void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { OS << format(" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor); OS << format(" Return address column: %d\n", (int32_t)ReturnAddressRegister); if (Personality) - OS << format(" Personality Address: %08x\n", *Personality); + OS << format(" Personality Address: %016" PRIx64 "\n", *Personality); if (!AugmentationData.empty()) { OS << " Augmentation data: "; for (uint8_t Byte : AugmentationData) @@ -320,7 +320,7 @@ void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { (uint32_t)InitialLocation, (uint32_t)InitialLocation + (uint32_t)AddressRange); if (LSDAAddress) - OS << format(" LSDA Address: %08x\n", *LSDAAddress); + OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress); CFIs.dump(OS, MRI, IsEH); OS << "\n"; } diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp index ade858113a30..1b505776ca19 100644 --- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp +++ b/contrib/llvm/lib/MC/ELFObjectWriter.cpp @@ -1271,6 +1271,7 @@ void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, // This is the first place we are able to copy this information. Alias->setExternal(Symbol.isExternal()); Alias->setBinding(Symbol.getBinding()); + Alias->setOther(Symbol.getOther()); if (!Symbol.isUndefined() && !Rest.startswith("@@@")) continue; diff --git a/contrib/llvm/lib/MC/MCWin64EH.cpp b/contrib/llvm/lib/MC/MCWin64EH.cpp index 8bc1f08c8875..3ef1514455af 100644 --- a/contrib/llvm/lib/MC/MCWin64EH.cpp +++ b/contrib/llvm/lib/MC/MCWin64EH.cpp @@ -522,7 +522,7 @@ static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) { if (MatchingEpilog) { assert(EpilogInfo.find(MatchingEpilog) != EpilogInfo.end() && "Duplicate epilog not found"); - EpilogInfo[EpilogStart] = EpilogInfo[MatchingEpilog]; + EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog); // Clear the unwind codes in the EpilogMap, so that they don't get output // in the logic below. EpilogInstrs.clear(); diff --git a/contrib/llvm/lib/MC/WasmObjectWriter.cpp b/contrib/llvm/lib/MC/WasmObjectWriter.cpp index 333748db9190..b07fe05cad5b 100644 --- a/contrib/llvm/lib/MC/WasmObjectWriter.cpp +++ b/contrib/llvm/lib/MC/WasmObjectWriter.cpp @@ -368,7 +368,13 @@ void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section, // Now that the section is complete and we know how big it is, patch up the // section size field at the start of the section. void WasmObjectWriter::endSection(SectionBookkeeping &Section) { - uint64_t Size = W.OS.tell() - Section.PayloadOffset; + uint64_t Size = W.OS.tell(); + // /dev/null doesn't support seek/tell and can report offset of 0. + // Simply skip this patching in that case. + if (!Size) + return; + + Size -= Section.PayloadOffset; if (uint32_t(Size) != Size) report_fatal_error("section size does not fit in a uint32_t"); diff --git a/contrib/llvm/lib/Object/COFFImportFile.cpp b/contrib/llvm/lib/Object/COFFImportFile.cpp index dc11cc4bcffe..e7c7efe43676 100644 --- a/contrib/llvm/lib/Object/COFFImportFile.cpp +++ b/contrib/llvm/lib/Object/COFFImportFile.cpp @@ -496,7 +496,7 @@ NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym, // COFF Header coff_file_header Header{ - u16(0), + u16(Machine), u16(NumberOfSections), u32(0), u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section))), diff --git a/contrib/llvm/lib/Target/AArch64/AArch64SchedExynosM4.td b/contrib/llvm/lib/Target/AArch64/AArch64SchedExynosM4.td index 4d892465b3f2..61652b1d8e3d 100644 --- a/contrib/llvm/lib/Target/AArch64/AArch64SchedExynosM4.td +++ b/contrib/llvm/lib/Target/AArch64/AArch64SchedExynosM4.td @@ -239,7 +239,6 @@ def M4WriteNEONK : SchedWriteRes<[M4UnitNSHF, M4UnitS0]> { let Latency = 5; let NumMicroOps = 2; } def M4WriteNEONL : SchedWriteRes<[M4UnitNMUL]> { let Latency = 3; } -def M4WriteNEONM : SchedWriteRes<[M4UnitNMUL]> { let Latency = 3; } def M4WriteNEONN : SchedWriteRes<[M4UnitNMSC, M4UnitNMSC]> { let Latency = 5; let NumMicroOps = 2; } @@ -480,8 +479,6 @@ def M4WriteCOPY : SchedWriteVariant<[SchedVar, SchedVar]>; def M4WriteMOVI : SchedWriteVariant<[SchedVar, SchedVar]>; -def M4WriteMULL : SchedWriteVariant<[SchedVar, - SchedVar]>; // Fast forwarding. def M4ReadAESM1 : SchedReadAdvance<+1, [M4WriteNCRY1]>; @@ -489,7 +486,8 @@ def M4ReadFMACM1 : SchedReadAdvance<+1, [M4WriteFMAC4, M4WriteFMAC4H, M4WriteFMAC5]>; def M4ReadNMULM1 : SchedReadAdvance<+1, [M4WriteNMUL3]>; -def M4ReadMULLP2 : SchedReadAdvance<-2, [M4WriteNEONM]>; +def M4ReadNMULP2 : SchedReadAdvance<-2, [M4WriteNMUL3]>; + //===----------------------------------------------------------------------===// // Coarse scheduling model. @@ -662,10 +660,8 @@ def : InstRW<[M4WriteNEONK], (instregex "^FMOVDXHighr")>; def : InstRW<[M4WriteFCVT3H], (instregex "^F(RECP|RSQRT)Ev1f16")>; def : InstRW<[M4WriteFCVT3], (instregex "^F(RECP|RSQRT)Ev1i(32|64)")>; def : InstRW<[M4WriteNMSC1], (instregex "^FRECPXv1")>; -def : InstRW<[M4WriteFMAC4H, - M4ReadFMACM1], (instregex "^F(RECP|RSQRT)S16")>; -def : InstRW<[M4WriteFMAC4, - M4ReadFMACM1], (instregex "^F(RECP|RSQRT)S(32|64)")>; +def : InstRW<[M4WriteFMAC4H], (instregex "^F(RECP|RSQRT)S16")>; +def : InstRW<[M4WriteFMAC4], (instregex "^F(RECP|RSQRT)S(32|64)")>; // FP load instructions. def : InstRW<[WriteVLD], (instregex "^LDR[SDQ]l")>; @@ -736,14 +732,20 @@ def : InstRW<[M4WriteNALU1], (instregex "^(AND|BIC|EOR|NOT|ORN|ORR)v")>; def : InstRW<[M4WriteNMSC1], (instregex "^[SU](MIN|MAX)v")>; def : InstRW<[M4WriteNMSC2], (instregex "^[SU](MIN|MAX)Pv")>; def : InstRW<[M4WriteNHAD3], (instregex "^[SU](MIN|MAX)Vv")>; -def : InstRW<[M4WriteNMUL3], (instregex "^(SQR?D)?MULH?v")>; def : InstRW<[M4WriteNMUL3, M4ReadNMULM1], (instregex "^ML[AS]v")>; -def : InstRW<[M4WriteNMUL3], (instregex "^SQRDML[AS]H")>; -def : InstRW<[M4WriteMULL, - M4ReadMULLP2], (instregex "^(S|U|SQD)ML[AS]Lv")>; -def : InstRW<[M4WriteMULL, - M4ReadMULLP2], (instregex "^(S|U|SQD)MULLv")>; +def : InstRW<[M4WriteNMUL3, + M4ReadNMULM1], (instregex "^(SQR?D)?MULH?v")>; +def : InstRW<[M4WriteNMUL3, + M4ReadNMULM1], (instregex "^SQRDML[AS]H")>; +def : InstRW<[M4WriteNMUL3, + M4ReadNMULM1], (instregex "^(S|U|SQD)ML[AS]L(v1(i32|i64)|v2i32|v4i16|v8i8)")>; +def : InstRW<[M4WriteNMUL3, + M4ReadNMULP2], (instregex "^(S|U|SQD)ML[AS]L(v4i32|v8i16|v16i8)")>; +def : InstRW<[M4WriteNMUL3, + M4ReadNMULM1], (instregex "^(S|U|SQD)MULL(v1(i32|i64)|v2i32|v4i16|v8i8)")>; +def : InstRW<[M4WriteNMUL3, + M4ReadNMULP2], (instregex "^(S|U|SQD)MULL(v4i32|v8i16|v16i8)")>; def : InstRW<[M4WriteNMUL3], (instregex "^[SU]DOT(lane)?v")>; def : InstRW<[M4WriteNHAD3], (instregex "^[SU]ADALPv")>; def : InstRW<[M4WriteNSHT4A], (instregex "^[SU]R?SRA[dv]")>; @@ -808,10 +810,8 @@ def : InstRW<[M4WriteNALU1], (instregex "^FMOVv.f(32|64)")>; def : InstRW<[M4WriteFCVT3H], (instregex "^F(RECP|RSQRT)Ev[248]f16")>; def : InstRW<[M4WriteFCVT3], (instregex "^F(RECP|RSQRT)Ev[248]f(32|64)")>; def : InstRW<[M4WriteFCVT3], (instregex "^U(RECP|RSQRT)Ev[24]i32")>; -def : InstRW<[M4WriteFMAC4H, - M4ReadFMACM1], (instregex "^F(RECP|RSQRT)Sv.f16")>; -def : InstRW<[M4WriteFMAC4, - M4ReadFMACM1], (instregex "^F(RECP|RSQRT)Sv.f(32|64)")>; +def : InstRW<[M4WriteFMAC4H], (instregex "^F(RECP|RSQRT)Sv.f16")>; +def : InstRW<[M4WriteFMAC4], (instregex "^F(RECP|RSQRT)Sv.f(32|64)")>; def : InstRW<[M4WriteNSHF1], (instregex "^REV(16|32|64)v")>; def : InstRW<[M4WriteNSHFA], (instregex "^TB[LX]v(8|16)i8One")>; def : InstRW<[M4WriteNSHFB], (instregex "^TB[LX]v(8|16)i8Two")>; diff --git a/contrib/llvm/lib/Target/AArch64/AArch64SchedPredExynos.td b/contrib/llvm/lib/Target/AArch64/AArch64SchedPredExynos.td index 48c54230e9d8..316036d89406 100644 --- a/contrib/llvm/lib/Target/AArch64/AArch64SchedPredExynos.td +++ b/contrib/llvm/lib/Target/AArch64/AArch64SchedPredExynos.td @@ -103,17 +103,6 @@ def ExynosScaledIdxPred : MCSchedPredicate; // Identify FP instructions. def ExynosFPPred : MCSchedPredicate>; -// Identify whether an instruction whose result is a long vector -// operates on the upper half of the input registers. -def ExynosLongVectorUpperFn : TIIPredicate< - "isExynosLongVectorUpper", - MCOpcodeSwitchStatement< - [MCOpcodeSwitchCase< - IsLongVectorUpperOp.ValidOpcodes, - MCReturnStatement>], - MCReturnStatement>>; -def ExynosLongVectorUpperPred : MCSchedPredicate; - // Identify 128-bit NEON instructions. def ExynosQFormPred : MCSchedPredicate; diff --git a/contrib/llvm/lib/Target/AArch64/AArch64SchedPredicates.td b/contrib/llvm/lib/Target/AArch64/AArch64SchedPredicates.td index dbaf11fc95dd..b23572b41b9c 100644 --- a/contrib/llvm/lib/Target/AArch64/AArch64SchedPredicates.td +++ b/contrib/llvm/lib/Target/AArch64/AArch64SchedPredicates.td @@ -268,59 +268,6 @@ def IsStoreRegOffsetOp : CheckOpcode<[STRBBroW, STRBBroX, def IsLoadStoreRegOffsetOp : CheckOpcode; -// Identify whether an instruction whose result is a long vector -// operates on the upper half of the input registers. -def IsLongVectorUpperOp : CheckOpcode<[FCVTLv8i16, FCVTLv4i32, - FCVTNv8i16, FCVTNv4i32, - FCVTXNv4f32, - PMULLv16i8, PMULLv2i64, - RADDHNv8i16_v16i8, RADDHNv4i32_v8i16, RADDHNv2i64_v4i32, - RSHRNv16i8_shift, RSHRNv8i16_shift, RSHRNv4i32_shift, - RSUBHNv8i16_v16i8, RSUBHNv4i32_v8i16, RSUBHNv2i64_v4i32, - SABALv16i8_v8i16, SABALv8i16_v4i32, SABALv4i32_v2i64, - SABDLv16i8_v8i16, SABDLv8i16_v4i32, SABDLv4i32_v2i64, - SADDLv16i8_v8i16, SADDLv8i16_v4i32, SADDLv4i32_v2i64, - SADDWv16i8_v8i16, SADDWv8i16_v4i32, SADDWv4i32_v2i64, - SHLLv16i8, SHLLv8i16, SHLLv4i32, - SHRNv16i8_shift, SHRNv8i16_shift, SHRNv4i32_shift, - SMLALv16i8_v8i16, SMLALv8i16_v4i32, SMLALv4i32_v2i64, - SMLALv8i16_indexed, SMLALv4i32_indexed, - SMLSLv16i8_v8i16, SMLSLv8i16_v4i32, SMLSLv4i32_v2i64, - SMLSLv8i16_indexed, SMLSLv4i32_indexed, - SMULLv16i8_v8i16, SMULLv8i16_v4i32, SMULLv4i32_v2i64, - SMULLv8i16_indexed, SMULLv4i32_indexed, - SQDMLALv8i16_v4i32, SQDMLALv4i32_v2i64, - SQDMLALv8i16_indexed, SQDMLALv4i32_indexed, - SQDMLSLv8i16_v4i32, SQDMLSLv4i32_v2i64, - SQDMLSLv8i16_indexed, SQDMLSLv4i32_indexed, - SQDMULLv8i16_v4i32, SQDMULLv4i32_v2i64, - SQDMULLv8i16_indexed, SQDMULLv4i32_indexed, - SQRSHRNv16i8_shift, SQRSHRNv8i16_shift, SQRSHRNv4i32_shift, - SQRSHRUNv16i8_shift, SQRSHRUNv8i16_shift, SQRSHRUNv4i32_shift, - SQSHRNv16i8_shift, SQSHRNv8i16_shift, SQSHRNv4i32_shift, - SQSHRUNv16i8_shift, SQSHRUNv8i16_shift, SQSHRUNv4i32_shift, - SQXTNv16i8, SQXTNv8i16, SQXTNv4i32, - SQXTUNv16i8, SQXTUNv8i16, SQXTUNv4i32, - SSHLLv16i8_shift, SSHLLv8i16_shift, SSHLLv4i32_shift, - SSUBLv16i8_v8i16, SSUBLv8i16_v4i32, SSUBLv4i32_v2i64, - SSUBWv16i8_v8i16, SSUBWv8i16_v4i32, SSUBWv4i32_v2i64, - UABALv16i8_v8i16, UABALv8i16_v4i32, UABALv4i32_v2i64, - UABDLv16i8_v8i16, UABDLv8i16_v4i32, UABDLv4i32_v2i64, - UADDLv16i8_v8i16, UADDLv8i16_v4i32, UADDLv4i32_v2i64, - UADDWv16i8_v8i16, UADDWv8i16_v4i32, UADDWv4i32_v2i64, - UMLALv16i8_v8i16, UMLALv8i16_v4i32, UMLALv4i32_v2i64, - UMLALv8i16_indexed, UMLALv4i32_indexed, - UMLSLv16i8_v8i16, UMLSLv8i16_v4i32, UMLSLv4i32_v2i64, - UMLSLv8i16_indexed, UMLSLv4i32_indexed, - UMULLv16i8_v8i16, UMULLv8i16_v4i32, UMULLv4i32_v2i64, - UMULLv8i16_indexed, UMULLv4i32_indexed, - UQSHRNv16i8_shift, UQSHRNv8i16_shift, UQSHRNv4i32_shift, - UQXTNv16i8, UQXTNv8i16, UQXTNv4i32, - USHLLv16i8_shift, USHLLv8i16_shift, USHLLv4i32_shift, - USUBLv16i8_v8i16, USUBLv8i16_v4i32, USUBLv4i32_v2i64, - USUBWv16i8_v8i16, USUBWv8i16_v4i32, USUBWv4i32_v2i64, - XTNv16i8, XTNv8i16, XTNv4i32]>; - // Target predicates. // Identify an instruction that effectively transfers a register to another. diff --git a/contrib/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp b/contrib/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp index f4e866958369..d679abd107d2 100644 --- a/contrib/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp +++ b/contrib/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp @@ -201,49 +201,55 @@ static bool updateOperand(FoldCandidate &Fold, Mod.setImm(Mod.getImm() & ~SISrcMods::OP_SEL_1); } } + } - if (Fold.needsShrink()) { - MachineBasicBlock *MBB = MI->getParent(); - auto Liveness = MBB->computeRegisterLiveness(&TRI, AMDGPU::VCC, MI); - if (Liveness != MachineBasicBlock::LQR_Dead) - return false; + if ((Fold.isImm() || Fold.isFI()) && Fold.needsShrink()) { + MachineBasicBlock *MBB = MI->getParent(); + auto Liveness = MBB->computeRegisterLiveness(&TRI, AMDGPU::VCC, MI); + if (Liveness != MachineBasicBlock::LQR_Dead) + return false; - MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); - int Op32 = Fold.getShrinkOpcode(); - MachineOperand &Dst0 = MI->getOperand(0); - MachineOperand &Dst1 = MI->getOperand(1); - assert(Dst0.isDef() && Dst1.isDef()); + MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); + int Op32 = Fold.getShrinkOpcode(); + MachineOperand &Dst0 = MI->getOperand(0); + MachineOperand &Dst1 = MI->getOperand(1); + assert(Dst0.isDef() && Dst1.isDef()); - bool HaveNonDbgCarryUse = !MRI.use_nodbg_empty(Dst1.getReg()); + bool HaveNonDbgCarryUse = !MRI.use_nodbg_empty(Dst1.getReg()); - const TargetRegisterClass *Dst0RC = MRI.getRegClass(Dst0.getReg()); - unsigned NewReg0 = MRI.createVirtualRegister(Dst0RC); - const TargetRegisterClass *Dst1RC = MRI.getRegClass(Dst1.getReg()); - unsigned NewReg1 = MRI.createVirtualRegister(Dst1RC); + const TargetRegisterClass *Dst0RC = MRI.getRegClass(Dst0.getReg()); + unsigned NewReg0 = MRI.createVirtualRegister(Dst0RC); - MachineInstr *Inst32 = TII.buildShrunkInst(*MI, Op32); + MachineInstr *Inst32 = TII.buildShrunkInst(*MI, Op32); - if (HaveNonDbgCarryUse) { - BuildMI(*MBB, MI, MI->getDebugLoc(), TII.get(AMDGPU::COPY), Dst1.getReg()) - .addReg(AMDGPU::VCC, RegState::Kill); - } - - // Keep the old instruction around to avoid breaking iterators, but - // replace the outputs with dummy registers. - Dst0.setReg(NewReg0); - Dst1.setReg(NewReg1); - - if (Fold.isCommuted()) - TII.commuteInstruction(*Inst32, false); - return true; + if (HaveNonDbgCarryUse) { + BuildMI(*MBB, MI, MI->getDebugLoc(), TII.get(AMDGPU::COPY), Dst1.getReg()) + .addReg(AMDGPU::VCC, RegState::Kill); } - Old.ChangeToImmediate(Fold.ImmToFold); + // Keep the old instruction around to avoid breaking iterators, but + // replace it with a dummy instruction to remove uses. + // + // FIXME: We should not invert how this pass looks at operands to avoid + // this. Should track set of foldable movs instead of looking for uses + // when looking at a use. + Dst0.setReg(NewReg0); + for (unsigned I = MI->getNumOperands() - 1; I > 0; --I) + MI->RemoveOperand(I); + MI->setDesc(TII.get(AMDGPU::IMPLICIT_DEF)); + + if (Fold.isCommuted()) + TII.commuteInstruction(*Inst32, false); return true; } assert(!Fold.needsShrink() && "not handled"); + if (Fold.isImm()) { + Old.ChangeToImmediate(Fold.ImmToFold); + return true; + } + if (Fold.isFI()) { Old.ChangeToFrameIndex(Fold.FrameIndexToFold); return true; @@ -344,7 +350,7 @@ static bool tryAddToFoldList(SmallVectorImpl &FoldList, if ((Opc == AMDGPU::V_ADD_I32_e64 || Opc == AMDGPU::V_SUB_I32_e64 || Opc == AMDGPU::V_SUBREV_I32_e64) && // FIXME - OpToFold->isImm()) { + (OpToFold->isImm() || OpToFold->isFI())) { MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo(); // Verify the other operand is a VGPR, otherwise we would violate the @@ -357,7 +363,10 @@ static bool tryAddToFoldList(SmallVectorImpl &FoldList, assert(MI->getOperand(1).isDef()); - int Op32 = AMDGPU::getVOPe32(Opc); + // Make sure to get the 32-bit version of the commuted opcode. + unsigned MaybeCommutedOpc = MI->getOpcode(); + int Op32 = AMDGPU::getVOPe32(MaybeCommutedOpc); + FoldList.push_back(FoldCandidate(MI, CommuteOpNo, OpToFold, true, Op32)); return true; diff --git a/contrib/llvm/lib/Target/AMDGPU/VOP2Instructions.td b/contrib/llvm/lib/Target/AMDGPU/VOP2Instructions.td index e3fd7b5f9fad..8cf524a5128d 100644 --- a/contrib/llvm/lib/Target/AMDGPU/VOP2Instructions.td +++ b/contrib/llvm/lib/Target/AMDGPU/VOP2Instructions.td @@ -515,18 +515,12 @@ let AddedComplexity = 1 in { } let SubtargetPredicate = HasAddNoCarryInsts in { - def : DivergentBinOp; - def : DivergentBinOp; - def : DivergentBinOp; + def : DivergentBinOp; + def : DivergentBinOp; } - -def : DivergentBinOp; - def : DivergentBinOp; -def : DivergentBinOp; - -def : DivergentBinOp; +def : DivergentBinOp; def : DivergentBinOp; def : DivergentBinOp; diff --git a/contrib/llvm/lib/Target/AVR/AVRISelLowering.cpp b/contrib/llvm/lib/Target/AVR/AVRISelLowering.cpp index 57fc978b54bb..5db757782322 100644 --- a/contrib/llvm/lib/Target/AVR/AVRISelLowering.cpp +++ b/contrib/llvm/lib/Target/AVR/AVRISelLowering.cpp @@ -26,19 +26,21 @@ #include "AVR.h" #include "AVRMachineFunctionInfo.h" +#include "AVRSubtarget.h" #include "AVRTargetMachine.h" #include "MCTargetDesc/AVRMCTargetDesc.h" namespace llvm { -AVRTargetLowering::AVRTargetLowering(AVRTargetMachine &tm) - : TargetLowering(tm) { +AVRTargetLowering::AVRTargetLowering(const AVRTargetMachine &TM, + const AVRSubtarget &STI) + : TargetLowering(TM), Subtarget(STI) { // Set up the register classes. addRegisterClass(MVT::i8, &AVR::GPR8RegClass); addRegisterClass(MVT::i16, &AVR::DREGSRegClass); // Compute derived properties from the register classes. - computeRegisterProperties(tm.getSubtargetImpl()->getRegisterInfo()); + computeRegisterProperties(Subtarget.getRegisterInfo()); setBooleanContents(ZeroOrOneBooleanContent); setBooleanVectorContents(ZeroOrOneBooleanContent); @@ -163,6 +165,13 @@ AVRTargetLowering::AVRTargetLowering(AVRTargetMachine &tm) setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand); setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand); + // Expand multiplications to libcalls when there is + // no hardware MUL. + if (!Subtarget.supportsMultiplication()) { + setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand); + } + for (MVT VT : MVT::integer_valuetypes()) { setOperationAction(ISD::MULHS, VT, Expand); setOperationAction(ISD::MULHU, VT, Expand); @@ -1271,7 +1280,7 @@ SDValue AVRTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // Add a register mask operand representing the call-preserved registers. const AVRTargetMachine &TM = (const AVRTargetMachine &)getTargetMachine(); - const TargetRegisterInfo *TRI = TM.getSubtargetImpl()->getRegisterInfo(); + const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); const uint32_t *Mask = TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv); assert(Mask && "Missing call preserved mask for calling convention"); @@ -1434,7 +1443,7 @@ MachineBasicBlock *AVRTargetLowering::insertShift(MachineInstr &MI, MachineFunction *F = BB->getParent(); MachineRegisterInfo &RI = F->getRegInfo(); const AVRTargetMachine &TM = (const AVRTargetMachine &)getTargetMachine(); - const TargetInstrInfo &TII = *TM.getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); DebugLoc dl = MI.getDebugLoc(); switch (MI.getOpcode()) { @@ -1575,7 +1584,7 @@ static bool isCopyMulResult(MachineBasicBlock::iterator const &I) { MachineBasicBlock *AVRTargetLowering::insertMul(MachineInstr &MI, MachineBasicBlock *BB) const { const AVRTargetMachine &TM = (const AVRTargetMachine &)getTargetMachine(); - const TargetInstrInfo &TII = *TM.getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); MachineBasicBlock::iterator I(MI); ++I; // in any case insert *after* the mul instruction if (isCopyMulResult(I)) @@ -1838,9 +1847,6 @@ std::pair AVRTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const { - auto STI = static_cast(this->getTargetMachine()) - .getSubtargetImpl(); - // We only support i8 and i16. // //:FIXME: remove this assert for now since it gets sometimes executed @@ -1884,8 +1890,8 @@ AVRTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, } } - return TargetLowering::getRegForInlineAsmConstraint(STI->getRegisterInfo(), - Constraint, VT); + return TargetLowering::getRegForInlineAsmConstraint( + Subtarget.getRegisterInfo(), Constraint, VT); } void AVRTargetLowering::LowerAsmOperandForConstraint(SDValue Op, diff --git a/contrib/llvm/lib/Target/AVR/AVRISelLowering.h b/contrib/llvm/lib/Target/AVR/AVRISelLowering.h index c90c65c81f70..7d77dd8fb018 100644 --- a/contrib/llvm/lib/Target/AVR/AVRISelLowering.h +++ b/contrib/llvm/lib/Target/AVR/AVRISelLowering.h @@ -64,12 +64,14 @@ enum NodeType { } // end of namespace AVRISD +class AVRSubtarget; class AVRTargetMachine; /// Performs target lowering for the AVR. class AVRTargetLowering : public TargetLowering { public: - explicit AVRTargetLowering(AVRTargetMachine &TM); + explicit AVRTargetLowering(const AVRTargetMachine &TM, + const AVRSubtarget &STI); public: MVT getScalarShiftAmountTy(const DataLayout &, EVT LHSTy) const override { @@ -164,6 +166,10 @@ class AVRTargetLowering : public TargetLowering { const SDLoc &dl, SelectionDAG &DAG, SmallVectorImpl &InVals) const; +protected: + + const AVRSubtarget &Subtarget; + private: MachineBasicBlock *insertShift(MachineInstr &MI, MachineBasicBlock *BB) const; MachineBasicBlock *insertMul(MachineInstr &MI, MachineBasicBlock *BB) const; diff --git a/contrib/llvm/lib/Target/AVR/AVRSubtarget.cpp b/contrib/llvm/lib/Target/AVR/AVRSubtarget.cpp index 556d69ec5234..c7c566270f43 100644 --- a/contrib/llvm/lib/Target/AVR/AVRSubtarget.cpp +++ b/contrib/llvm/lib/Target/AVR/AVRSubtarget.cpp @@ -29,9 +29,9 @@ namespace llvm { AVRSubtarget::AVRSubtarget(const Triple &TT, const std::string &CPU, - const std::string &FS, AVRTargetMachine &TM) + const std::string &FS, const AVRTargetMachine &TM) : AVRGenSubtargetInfo(TT, CPU, FS), InstrInfo(), FrameLowering(), - TLInfo(TM), TSInfo(), + TLInfo(TM, initializeSubtargetDependencies(CPU, FS, TM)), TSInfo(), // Subtarget features m_hasSRAM(false), m_hasJMPCALL(false), m_hasIJMPCALL(false), @@ -44,4 +44,12 @@ AVRSubtarget::AVRSubtarget(const Triple &TT, const std::string &CPU, ParseSubtargetFeatures(CPU, FS); } +AVRSubtarget & +AVRSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS, + const TargetMachine &TM) { + // Parse features string. + ParseSubtargetFeatures(CPU, FS); + return *this; +} + } // end of namespace llvm diff --git a/contrib/llvm/lib/Target/AVR/AVRSubtarget.h b/contrib/llvm/lib/Target/AVR/AVRSubtarget.h index fa26738da190..ba036d5e4061 100644 --- a/contrib/llvm/lib/Target/AVR/AVRSubtarget.h +++ b/contrib/llvm/lib/Target/AVR/AVRSubtarget.h @@ -37,7 +37,7 @@ class AVRSubtarget : public AVRGenSubtargetInfo { //! \param FS The feature string. //! \param TM The target machine. AVRSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS, - AVRTargetMachine &TM); + const AVRTargetMachine &TM); const AVRInstrInfo *getInstrInfo() const override { return &InstrInfo; } const TargetFrameLowering *getFrameLowering() const override { return &FrameLowering; } @@ -49,6 +49,9 @@ class AVRSubtarget : public AVRGenSubtargetInfo { /// \note Definition of function is auto generated by `tblgen`. void ParseSubtargetFeatures(StringRef CPU, StringRef FS); + AVRSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS, + const TargetMachine &TM); + // Subtarget feature getters. // See AVR.td for details. bool hasSRAM() const { return m_hasSRAM; } diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index 58f9717e1cc6..a46f84bd1c9c 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -700,8 +700,11 @@ void MipsTargetAsmStreamer::emitDirectiveCpreturn(unsigned SaveLocation, } void MipsTargetAsmStreamer::emitDirectiveModuleFP() { - OS << "\t.module\tfp="; - OS << ABIFlagsSection.getFpABIString(ABIFlagsSection.getFpABI()) << "\n"; + MipsABIFlagsSection::FpABIKind FpABI = ABIFlagsSection.getFpABI(); + if (FpABI == MipsABIFlagsSection::FpABIKind::SOFT) + OS << "\t.module\tsoftfloat\n"; + else + OS << "\t.module\tfp=" << ABIFlagsSection.getFpABIString(FpABI) << "\n"; } void MipsTargetAsmStreamer::emitDirectiveSetFp( diff --git a/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td b/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td index c441aa76ad40..994a8882f942 100644 --- a/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td +++ b/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -1040,7 +1040,7 @@ class TRUNC_L_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"trunc.l.d", FGR64Opnd, class TRUNC_W_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"trunc.w.s", FGR32Opnd, FGR32Opnd, II_TRUNC>; class TRUNC_W_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"trunc.w.d", FGR32Opnd, - AFGR64Opnd, II_TRUNC>; + FGR64Opnd, II_TRUNC>; class SQRT_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"sqrt.s", FGR32Opnd, FGR32Opnd, II_SQRT_S, fsqrt>; class SQRT_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"sqrt.d", AFGR64Opnd, AFGR64Opnd, @@ -1750,6 +1750,8 @@ def : MipsPat<(f32 fpimm0), (MTC1_MMR6 ZERO)>, ISA_MICROMIPS32R6; def : MipsPat<(f32 fpimm0neg), (FNEG_S_MMR6 (MTC1_MMR6 ZERO))>, ISA_MICROMIPS32R6; def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), (TRUNC_W_D_MMR6 FGR64Opnd:$src)>, ISA_MICROMIPS32R6; +def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src), + (TRUNC_W_S_MMR6 FGR32Opnd:$src)>, ISA_MICROMIPS32R6; def : MipsPat<(and GPRMM16:$src, immZExtAndi16:$imm), (ANDI16_MMR6 GPRMM16:$src, immZExtAndi16:$imm)>, diff --git a/contrib/llvm/lib/Target/Mips/MicroMipsInstrFPU.td b/contrib/llvm/lib/Target/Mips/MicroMipsInstrFPU.td index 1731afc1961f..9e76165e7ad7 100644 --- a/contrib/llvm/lib/Target/Mips/MicroMipsInstrFPU.td +++ b/contrib/llvm/lib/Target/Mips/MicroMipsInstrFPU.td @@ -425,6 +425,11 @@ def : MipsPat<(f64 (fpextend FGR32Opnd:$src)), def : MipsPat<(MipsTruncIntFP AFGR64Opnd:$src), (TRUNC_W_MM AFGR64Opnd:$src)>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; +def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), + (CVT_W_D64_MM FGR64Opnd:$src)>, ISA_MICROMIPS32_NOT_MIPS32R6, + FGR_64; +def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src), + (TRUNC_W_S_MM FGR32Opnd:$src)>, ISA_MICROMIPS32_NOT_MIPS32R6; // Selects defm : MovzPats0, diff --git a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index a7a748b0840e..c35f5beb6880 100644 --- a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -813,7 +813,8 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { // We should always emit a '.module fp=...' but binutils 2.24 does not accept // it. We therefore emit it when it contradicts the ABI defaults (-mfpxx or // -mfp64) and omit it otherwise. - if (ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit())) + if ((ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit())) || + STI.useSoftFloat()) TS.emitDirectiveModuleFP(); // We should always emit a '.module [no]oddspreg' but binutils 2.24 does not diff --git a/contrib/llvm/lib/Target/Mips/MipsDSPInstrInfo.td b/contrib/llvm/lib/Target/Mips/MipsDSPInstrInfo.td index b9824220b558..a4078026e4f9 100644 --- a/contrib/llvm/lib/Target/Mips/MipsDSPInstrInfo.td +++ b/contrib/llvm/lib/Target/Mips/MipsDSPInstrInfo.td @@ -1314,7 +1314,9 @@ def PseudoCMPU_LE_QB : PseudoCMP; def PseudoPICK_PH : PseudoPICK; def PseudoPICK_QB : PseudoPICK; -def PseudoMTLOHI_DSP : PseudoMTLOHI; +let AdditionalPredicates = [HasDSP] in { + def PseudoMTLOHI_DSP : PseudoMTLOHI; +} // Patterns. class DSPPat : diff --git a/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp index e3823e0dfdb8..61e77fbeea6d 100644 --- a/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -726,6 +726,7 @@ bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin, // but we don't have enough information to make that decision. if (InMicroMipsMode && TII->getInstSizeInBytes(*CurrI) == 2 && (Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch || + Opcode == Mips::PseudoIndirectBranch_MM || Opcode == Mips::PseudoReturn || Opcode == Mips::TAILCALL)) continue; // Instructions LWP/SWP and MOVEP should not be in a delay slot as that diff --git a/contrib/llvm/lib/Target/Mips/MipsFastISel.cpp b/contrib/llvm/lib/Target/Mips/MipsFastISel.cpp index a18416b9e861..168750b2cba9 100644 --- a/contrib/llvm/lib/Target/Mips/MipsFastISel.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsFastISel.cpp @@ -954,21 +954,34 @@ bool MipsFastISel::selectBranch(const Instruction *I) { // MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)]; MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)]; - // For now, just try the simplest case where it's fed by a compare. + + // Fold the common case of a conditional branch with a comparison + // in the same block. + unsigned ZExtCondReg = 0; if (const CmpInst *CI = dyn_cast(BI->getCondition())) { - MVT CIMVT = - TLI.getValueType(DL, CI->getOperand(0)->getType(), true).getSimpleVT(); - if (CIMVT == MVT::i1) + if (CI->hasOneUse() && CI->getParent() == I->getParent()) { + ZExtCondReg = createResultReg(&Mips::GPR32RegClass); + if (!emitCmp(ZExtCondReg, CI)) + return false; + } + } + + // For the general case, we need to mask with 1. + if (ZExtCondReg == 0) { + unsigned CondReg = getRegForValue(BI->getCondition()); + if (CondReg == 0) return false; - unsigned CondReg = getRegForValue(CI); - BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ)) - .addReg(CondReg) - .addMBB(TBB); - finishCondBranch(BI->getParent(), TBB, FBB); - return true; + ZExtCondReg = emitIntExt(MVT::i1, CondReg, MVT::i32, true); + if (ZExtCondReg == 0) + return false; } - return false; + + BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ)) + .addReg(ZExtCondReg) + .addMBB(TBB); + finishCondBranch(BI->getParent(), TBB, FBB); + return true; } bool MipsFastISel::selectCmp(const Instruction *I) { diff --git a/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp index c7ab90ed2a3b..2b26caaa9f49 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -447,6 +447,9 @@ bool MipsSEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { case Mips::PseudoMTLOHI_DSP: expandPseudoMTLoHi(MBB, MI, Mips::MTLO_DSP, Mips::MTHI_DSP, true); break; + case Mips::PseudoMTLOHI_MM: + expandPseudoMTLoHi(MBB, MI, Mips::MTLO_MM, Mips::MTHI_MM, false); + break; case Mips::PseudoCVT_S_W: expandCvtFPInt(MBB, MI, Mips::CVT_S_W, Mips::MTC1, false); break; diff --git a/contrib/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp b/contrib/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp index 26869f250823..cce239cac970 100644 --- a/contrib/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp +++ b/contrib/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp @@ -61,6 +61,14 @@ extern "C" void LLVMInitializePowerPCDisassembler() { createPPCLEDisassembler); } +static DecodeStatus DecodePCRel24BranchTarget(MCInst &Inst, unsigned Imm, + uint64_t Addr, + const void *Decoder) { + int32_t Offset = SignExtend32<24>(Imm); + Inst.addOperand(MCOperand::createImm(Offset)); + return MCDisassembler::Success; +} + // FIXME: These can be generated by TableGen from the existing register // encoding values! diff --git a/contrib/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp b/contrib/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp index fc29e4effbb1..6824168b890d 100644 --- a/contrib/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp +++ b/contrib/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp @@ -382,8 +382,11 @@ void PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo, // Branches can take an immediate operand. This is used by the branch // selection pass to print .+8, an eight byte displacement from the PC. - O << ".+"; - printAbsBranchOperand(MI, OpNo, O); + O << "."; + int32_t Imm = SignExtend32<32>((unsigned)MI->getOperand(OpNo).getImm() << 2); + if (Imm >= 0) + O << "+"; + O << Imm; } void PPCInstPrinter::printAbsBranchOperand(const MCInst *MI, unsigned OpNo, diff --git a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp index a1e4e07b25af..78609ef3d4e0 100644 --- a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -15,6 +15,7 @@ #include "InstPrinter/PPCInstPrinter.h" #include "MCTargetDesc/PPCMCAsmInfo.h" #include "PPCTargetStreamer.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/BinaryFormat/ELF.h" @@ -182,16 +183,33 @@ class PPCTargetELFStreamer : public PPCTargetStreamer { void emitAssignment(MCSymbol *S, const MCExpr *Value) override { auto *Symbol = cast(S); + // When encoding an assignment to set symbol A to symbol B, also copy // the st_other bits encoding the local entry point offset. - if (Value->getKind() != MCExpr::SymbolRef) - return; - const auto &RhsSym = cast( - static_cast(Value)->getSymbol()); - unsigned Other = Symbol->getOther(); + if (copyLocalEntry(Symbol, Value)) + UpdateOther.insert(Symbol); + else + UpdateOther.erase(Symbol); + } + + void finish() override { + for (auto *Sym : UpdateOther) + copyLocalEntry(Sym, Sym->getVariableValue()); + } + +private: + SmallPtrSet UpdateOther; + + bool copyLocalEntry(MCSymbolELF *D, const MCExpr *S) { + auto *Ref = dyn_cast(S); + if (!Ref) + return false; + const auto &RhsSym = cast(Ref->getSymbol()); + unsigned Other = D->getOther(); Other &= ~ELF::STO_PPC64_LOCAL_MASK; Other |= RhsSym.getOther() & ELF::STO_PPC64_LOCAL_MASK; - Symbol->setOther(Other); + D->setOther(Other); + return true; } }; diff --git a/contrib/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/contrib/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 31acd0ff870f..70e9049a2ab3 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -4359,8 +4359,8 @@ void PPCDAGToDAGISel::Select(SDNode *N) { const Module *M = MF->getFunction().getParent(); if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) != MVT::i32 || - !PPCSubTarget->isSecurePlt() || !PPCSubTarget->isTargetELF() || - M->getPICLevel() == PICLevel::SmallPIC) + (!TM.isPositionIndependent() || !PPCSubTarget->isSecurePlt()) || + !PPCSubTarget->isTargetELF() || M->getPICLevel() == PICLevel::SmallPIC) break; SDValue Op = N->getOperand(1); diff --git a/contrib/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/contrib/llvm/lib/Target/PowerPC/PPCInstrInfo.td index dd3f1ac79089..77aa4fe3d415 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/contrib/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -737,7 +737,9 @@ def abscondbrtarget : Operand { def calltarget : Operand { let PrintMethod = "printBranchOperand"; let EncoderMethod = "getDirectBrEncoding"; + let DecoderMethod = "DecodePCRel24BranchTarget"; let ParserMatchClass = PPCDirectBrAsmOperand; + let OperandType = "OPERAND_PCREL"; } def abscalltarget : Operand { let PrintMethod = "printAbsBranchOperand"; diff --git a/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.cpp index c0cbfd779cb9..1fdf74549dec 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.cpp @@ -138,6 +138,9 @@ void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { if (isDarwin()) HasLazyResolverStubs = true; + if (TargetTriple.isOSNetBSD() || TargetTriple.isOSOpenBSD()) + SecurePlt = true; + if (HasSPE && IsPPC64) report_fatal_error( "SPE is only supported for 32-bit targets.\n", false); if (HasSPE && (HasAltivec || HasQPX || HasVSX || HasFPU)) diff --git a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp b/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp index 33caa66154ff..ad6ea3760fee 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -189,7 +189,7 @@ SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, MachineInstr *StMI = BuildMI(*MI.getParent(), II, dl, TII.get(SP::STDFri)) .addReg(FrameReg).addImm(0).addReg(SrcEvenReg); - replaceFI(MF, II, *StMI, dl, 0, Offset, FrameReg); + replaceFI(MF, *StMI, *StMI, dl, 0, Offset, FrameReg); MI.setDesc(TII.get(SP::STDFri)); MI.getOperand(2).setReg(SrcOddReg); Offset += 8; @@ -201,7 +201,7 @@ SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, MachineInstr *StMI = BuildMI(*MI.getParent(), II, dl, TII.get(SP::LDDFri), DestEvenReg) .addReg(FrameReg).addImm(0); - replaceFI(MF, II, *StMI, dl, 1, Offset, FrameReg); + replaceFI(MF, *StMI, *StMI, dl, 1, Offset, FrameReg); MI.setDesc(TII.get(SP::LDDFri)); MI.getOperand(0).setReg(DestOddReg); diff --git a/contrib/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/contrib/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 003848e34227..f7f29d85cbb2 100644 --- a/contrib/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/contrib/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -669,13 +669,16 @@ WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI, if (IsVarArg) { // Outgoing non-fixed arguments are placed in a buffer. First // compute their offsets and the total amount of buffer space needed. - for (SDValue Arg : - make_range(OutVals.begin() + NumFixedArgs, OutVals.end())) { + for (unsigned I = NumFixedArgs; I < Outs.size(); ++I) { + const ISD::OutputArg &Out = Outs[I]; + SDValue &Arg = OutVals[I]; EVT VT = Arg.getValueType(); assert(VT != MVT::iPTR && "Legalized args should be concrete"); Type *Ty = VT.getTypeForEVT(*DAG.getContext()); + unsigned Align = std::max(Out.Flags.getOrigAlign(), + Layout.getABITypeAlignment(Ty)); unsigned Offset = CCInfo.AllocateStack(Layout.getTypeAllocSize(Ty), - Layout.getABITypeAlignment(Ty)); + Align); CCInfo.addLoc(CCValAssign::getMem(ArgLocs.size(), VT.getSimpleVT(), Offset, VT.getSimpleVT(), CCValAssign::Full)); diff --git a/contrib/llvm/lib/Target/X86/X86FastISel.cpp b/contrib/llvm/lib/Target/X86/X86FastISel.cpp index 9dd3f2652543..12cd613c34cb 100644 --- a/contrib/llvm/lib/Target/X86/X86FastISel.cpp +++ b/contrib/llvm/lib/Target/X86/X86FastISel.cpp @@ -399,7 +399,7 @@ bool X86FastISel::X86FastEmitLoad(EVT VT, X86AddressMode &AM, case MVT::v2i64: case MVT::v8i16: case MVT::v16i8: - if (IsNonTemporal && Alignment >= 16) + if (IsNonTemporal && Alignment >= 16 && HasSSE41) Opc = HasVLX ? X86::VMOVNTDQAZ128rm : HasAVX ? X86::VMOVNTDQArm : X86::MOVNTDQArm; else if (Alignment >= 16) diff --git a/contrib/llvm/lib/Target/X86/X86TargetMachine.cpp b/contrib/llvm/lib/Target/X86/X86TargetMachine.cpp index afcb49dc2263..217a12ddf896 100644 --- a/contrib/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/contrib/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -38,6 +38,7 @@ #include "llvm/IR/Attributes.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Pass.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/CommandLine.h" @@ -512,6 +513,9 @@ void X86PassConfig::addPreEmitPass2() { // correct CFA calculation rule where needed by inserting appropriate CFI // instructions. const Triple &TT = TM->getTargetTriple(); - if (!TT.isOSDarwin() && !TT.isOSWindows()) + const MCAsmInfo *MAI = TM->getMCAsmInfo(); + if (!TT.isOSDarwin() && + (!TT.isOSWindows() || + MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI)) addPass(createCFIInstrInserter()); } diff --git a/contrib/llvm/tools/clang/lib/Basic/Version.cpp b/contrib/llvm/tools/clang/lib/Basic/Version.cpp index a15c60e0f55c..1d594b974189 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Version.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Version.cpp @@ -36,7 +36,7 @@ std::string getClangRepositoryPath() { // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us // pick up a tag in an SVN export, for example. - StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_800/final/lib/Basic/Version.cpp $"); + StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/branches/release_80/lib/Basic/Version.cpp $"); if (URL.empty()) { URL = SVNRepository.slice(SVNRepository.find(':'), SVNRepository.find("/lib/Basic")); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp index eb1304d89345..44dc1cdee0b5 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -1518,8 +1518,9 @@ void CodeGenFunction::EmitOMPPrivateLoopCounters( I < E; ++I) { const auto *DRE = cast(C->getLoopCounter(I)); const auto *VD = cast(DRE->getDecl()); - // Override only those variables that are really emitted already. - if (LocalDeclMap.count(VD)) { + // Override only those variables that can be captured to avoid re-emission + // of the variables declared within the loops. + if (DRE->refersToEnclosingVariableOrCapture()) { (void)LoopScope.addPrivate(VD, [this, DRE, VD]() { return CreateMemTemp(DRE->getType(), VD->getName()); }); diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp index 589f53b11921..78ee7a78176f 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp @@ -718,8 +718,9 @@ static void appendUserToPath(SmallVectorImpl &Result) { Result.append(UID.begin(), UID.end()); } -static void addPGOAndCoverageFlags(Compilation &C, const Driver &D, - const InputInfo &Output, const ArgList &Args, +static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, + const Driver &D, const InputInfo &Output, + const ArgList &Args, ArgStringList &CmdArgs) { auto *PGOGenerateArg = Args.getLastArg(options::OPT_fprofile_generate, @@ -759,6 +760,11 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D, ProfileGenerateArg->getValue())); // The default is to use Clang Instrumentation. CmdArgs.push_back("-fprofile-instrument=clang"); + if (TC.getTriple().isWindowsMSVCEnvironment()) { + // Add dependent lib for clang_rt.profile + CmdArgs.push_back(Args.MakeArgString("--dependent-lib=" + + TC.getCompilerRT(Args, "profile"))); + } } if (PGOGenerateArg) { @@ -4118,7 +4124,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // sampling, overhead of call arc collection is way too high and there's no // way to collect the output. if (!Triple.isNVPTX()) - addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs); + addPGOAndCoverageFlags(TC, C, D, Output, Args, CmdArgs); if (auto *ABICompatArg = Args.getLastArg(options::OPT_fclang_abi_compat_EQ)) ABICompatArg->render(Args, CmdArgs); diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.cpp index 65ab9b2daf54..dfdfb18319ab 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Linux.cpp @@ -45,6 +45,7 @@ static std::string getMultiarchTriple(const Driver &D, TargetTriple.getEnvironment(); bool IsAndroid = TargetTriple.isAndroid(); bool IsMipsR6 = TargetTriple.getSubArch() == llvm::Triple::MipsSubArch_r6; + bool IsMipsN32Abi = TargetTriple.getEnvironment() == llvm::Triple::GNUABIN32; // For most architectures, just use whatever we have rather than trying to be // clever. @@ -103,33 +104,37 @@ static std::string getMultiarchTriple(const Driver &D, return "aarch64_be-linux-gnu"; break; case llvm::Triple::mips: { - std::string Arch = IsMipsR6 ? "mipsisa32r6" : "mips"; - if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-gnu")) - return Arch + "-linux-gnu"; + std::string MT = IsMipsR6 ? "mipsisa32r6-linux-gnu" : "mips-linux-gnu"; + if (D.getVFS().exists(SysRoot + "/lib/" + MT)) + return MT; break; } case llvm::Triple::mipsel: { if (IsAndroid) return "mipsel-linux-android"; - std::string Arch = IsMipsR6 ? "mipsisa32r6el" : "mipsel"; - if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-gnu")) - return Arch + "-linux-gnu"; + std::string MT = IsMipsR6 ? "mipsisa32r6el-linux-gnu" : "mipsel-linux-gnu"; + if (D.getVFS().exists(SysRoot + "/lib/" + MT)) + return MT; break; } case llvm::Triple::mips64: { - std::string Arch = IsMipsR6 ? "mipsisa64r6" : "mips64"; - std::string ABI = llvm::Triple::getEnvironmentTypeName(TargetEnvironment); - if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-" + ABI)) - return Arch + "-linux-" + ABI; + std::string MT = std::string(IsMipsR6 ? "mipsisa64r6" : "mips64") + + "-linux-" + (IsMipsN32Abi ? "gnuabin32" : "gnuabi64"); + if (D.getVFS().exists(SysRoot + "/lib/" + MT)) + return MT; + if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnu")) + return "mips64-linux-gnu"; break; } case llvm::Triple::mips64el: { if (IsAndroid) return "mips64el-linux-android"; - std::string Arch = IsMipsR6 ? "mipsisa64r6el" : "mips64el"; - std::string ABI = llvm::Triple::getEnvironmentTypeName(TargetEnvironment); - if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-" + ABI)) - return Arch + "-linux-" + ABI; + std::string MT = std::string(IsMipsR6 ? "mipsisa64r6el" : "mips64el") + + "-linux-" + (IsMipsN32Abi ? "gnuabin32" : "gnuabi64"); + if (D.getVFS().exists(SysRoot + "/lib/" + MT)) + return MT; + if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnu")) + return "mips64el-linux-gnu"; break; } case llvm::Triple::ppc: diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp index aedec746af9e..8a0be0c472de 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp @@ -4602,8 +4602,7 @@ DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar( Captures.insert(std::make_pair(LCRef, Ref)); return Ref; } - return buildDeclRefExpr(SemaRef, VD, VD->getType().getNonReferenceType(), - DefaultLoc); + return cast(LCRef); } Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const { diff --git a/contrib/llvm/tools/lld/COFF/Writer.cpp b/contrib/llvm/tools/lld/COFF/Writer.cpp index 6acfaf9a4454..56b797451cfc 100644 --- a/contrib/llvm/tools/lld/COFF/Writer.cpp +++ b/contrib/llvm/tools/lld/COFF/Writer.cpp @@ -1351,19 +1351,47 @@ static void addSymbolToRVASet(SymbolRVASet &RVASet, Defined *S) { // symbol in an executable section. static void maybeAddAddressTakenFunction(SymbolRVASet &AddressTakenSyms, Symbol *S) { - auto *D = dyn_cast_or_null(S); - - // Ignore undefined symbols and references to non-functions (e.g. globals and - // labels). - if (!D || - D->getCOFFSymbol().getComplexType() != COFF::IMAGE_SYM_DTYPE_FUNCTION) + if (!S) return; - // Mark the symbol as address taken if it's in an executable section. - Chunk *RefChunk = D->getChunk(); - OutputSection *OS = RefChunk ? RefChunk->getOutputSection() : nullptr; - if (OS && OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE) - addSymbolToRVASet(AddressTakenSyms, D); + switch (S->kind()) { + case Symbol::DefinedLocalImportKind: + case Symbol::DefinedImportDataKind: + // Defines an __imp_ pointer, so it is data, so it is ignored. + break; + case Symbol::DefinedCommonKind: + // Common is always data, so it is ignored. + break; + case Symbol::DefinedAbsoluteKind: + case Symbol::DefinedSyntheticKind: + // Absolute is never code, synthetic generally isn't and usually isn't + // determinable. + break; + case Symbol::LazyKind: + case Symbol::UndefinedKind: + // Undefined symbols resolve to zero, so they don't have an RVA. Lazy + // symbols shouldn't have relocations. + break; + + case Symbol::DefinedImportThunkKind: + // Thunks are always code, include them. + addSymbolToRVASet(AddressTakenSyms, cast(S)); + break; + + case Symbol::DefinedRegularKind: { + // This is a regular, defined, symbol from a COFF file. Mark the symbol as + // address taken if the symbol type is function and it's in an executable + // section. + auto *D = cast(S); + if (D->getCOFFSymbol().getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) { + Chunk *RefChunk = D->getChunk(); + OutputSection *OS = RefChunk ? RefChunk->getOutputSection() : nullptr; + if (OS && OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE) + addSymbolToRVASet(AddressTakenSyms, D); + } + break; + } + } } // Visit all relocations from all section contributions of this object file and diff --git a/contrib/llvm/tools/lld/ELF/Arch/PPC64.cpp b/contrib/llvm/tools/lld/ELF/Arch/PPC64.cpp index 8a320c9a4e9e..cbfa8073d33f 100644 --- a/contrib/llvm/tools/lld/ELF/Arch/PPC64.cpp +++ b/contrib/llvm/tools/lld/ELF/Arch/PPC64.cpp @@ -113,6 +113,7 @@ class PPC64 final : public TargetInfo { void writeGotHeader(uint8_t *Buf) const override; bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, uint64_t BranchAddr, const Symbol &S) const override; + uint32_t getThunkSectionSpacing() const override; bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, RelExpr Expr) const override; @@ -759,6 +760,14 @@ bool PPC64::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, return !inBranchRange(Type, BranchAddr, S.getVA()); } +uint32_t PPC64::getThunkSectionSpacing() const { + // See comment in Arch/ARM.cpp for a more detailed explanation of + // getThunkSectionSpacing(). For PPC64 we pick the constant here based on + // R_PPC64_REL24, which is used by unconditional branch instructions. + // 0x2000000 = (1 << 24-1) * 4 + return 0x2000000; +} + bool PPC64::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { int64_t Offset = Dst - Src; if (Type == R_PPC64_REL14) diff --git a/contrib/llvm/tools/lld/ELF/InputSection.cpp b/contrib/llvm/tools/lld/ELF/InputSection.cpp index 839bff7011eb..ca2f49c07bb7 100644 --- a/contrib/llvm/tools/lld/ELF/InputSection.cpp +++ b/contrib/llvm/tools/lld/ELF/InputSection.cpp @@ -248,6 +248,7 @@ void InputSectionBase::parseCompressedHeader() { } UncompressedSize = Hdr->ch_size; + Alignment = std::max(Hdr->ch_addralign, 1); RawData = RawData.slice(sizeof(*Hdr)); return; } @@ -265,6 +266,7 @@ void InputSectionBase::parseCompressedHeader() { } UncompressedSize = Hdr->ch_size; + Alignment = std::max(Hdr->ch_addralign, 1); RawData = RawData.slice(sizeof(*Hdr)); } @@ -578,10 +580,6 @@ static int64_t getTlsTpOffset() { // Variant 1. The thread pointer points to a TCB with a fixed 2-word size, // followed by a variable amount of alignment padding, followed by the TLS // segment. - // - // NB: While the ARM/AArch64 ABI formally has a 2-word TCB size, lld - // effectively increases the TCB size to 8 words for Android compatibility. - // It accomplishes this by increasing the segment's alignment. return alignTo(Config->Wordsize * 2, Out::TlsPhdr->p_align); case EM_386: case EM_X86_64: diff --git a/contrib/llvm/tools/lld/ELF/SyntheticSections.cpp b/contrib/llvm/tools/lld/ELF/SyntheticSections.cpp index 5eec83b0391b..13344949b2a0 100644 --- a/contrib/llvm/tools/lld/ELF/SyntheticSections.cpp +++ b/contrib/llvm/tools/lld/ELF/SyntheticSections.cpp @@ -2003,6 +2003,11 @@ template void SymbolTableSection::writeTo(uint8_t *Buf) { ESym->setVisibility(Sym->Visibility); } + // The 3 most significant bits of st_other are used by OpenPOWER ABI. + // See getPPC64GlobalEntryToLocalEntryOffset() for more details. + if (Config->EMachine == EM_PPC64) + ESym->st_other |= Sym->StOther & 0xe0; + ESym->st_name = Ent.StrTabOffset; ESym->st_shndx = getSymSectionIndex(Ent.Sym); diff --git a/contrib/llvm/tools/lld/ELF/Writer.cpp b/contrib/llvm/tools/lld/ELF/Writer.cpp index dcabf52e64f3..75d9dcabb407 100644 --- a/contrib/llvm/tools/lld/ELF/Writer.cpp +++ b/contrib/llvm/tools/lld/ELF/Writer.cpp @@ -547,6 +547,11 @@ static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName, if (Config->Discard == DiscardPolicy::None) return true; + // If -emit-reloc is given, all symbols including local ones need to be + // copied because they may be referenced by relocations. + if (Config->EmitRelocs) + return true; + // In ELF assembly .L symbols are normally discarded by the assembler. // If the assembler fails to do so, the linker discards them if // * --discard-locals is used. @@ -2216,17 +2221,6 @@ template void Writer::setPhdrs() { } if (P->p_type == PT_TLS && P->p_memsz) { - if (!Config->Shared && - (Config->EMachine == EM_ARM || Config->EMachine == EM_AARCH64)) { - // On ARM/AArch64, reserve extra space (8 words) between the thread - // pointer and an executable's TLS segment by overaligning the segment. - // This reservation is needed for backwards compatibility with Android's - // TCB, which allocates several slots after the thread pointer (e.g. - // TLS_SLOT_STACK_GUARD==5). For simplicity, this overalignment is also - // done on other operating systems. - P->p_align = std::max(P->p_align, Config->Wordsize * 8); - } - // The TLS pointer goes after PT_TLS for variant 2 targets. At least glibc // will align it, so round up the size to make sure the offsets are // correct. diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp index ba8d3c5b8d5c..9bd4528ef7f7 100644 --- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -2087,20 +2087,38 @@ void llvm::printSymbolTable(const ObjectFile *O, StringRef ArchiveName, outs() << SectionName; } - outs() << '\t'; if (Common || isa(O)) { uint64_t Val = Common ? Symbol.getAlignment() : ELFSymbolRef(Symbol).getSize(); - outs() << format("\t %08" PRIx64 " ", Val); + outs() << format("\t%08" PRIx64, Val); } - if (Hidden) - outs() << ".hidden "; + if (isa(O)) { + uint8_t Other = ELFSymbolRef(Symbol).getOther(); + switch (Other) { + case ELF::STV_DEFAULT: + break; + case ELF::STV_INTERNAL: + outs() << " .internal"; + break; + case ELF::STV_HIDDEN: + outs() << " .hidden"; + break; + case ELF::STV_PROTECTED: + outs() << " .protected"; + break; + default: + outs() << format(" 0x%02x", Other); + break; + } + } else if (Hidden) { + outs() << " .hidden"; + } if (Demangle) - outs() << demangle(Name) << '\n'; + outs() << ' ' << demangle(Name) << '\n'; else - outs() << Name << '\n'; + outs() << ' ' << Name << '\n'; } } diff --git a/contrib/traceroute/traceroute.8 b/contrib/traceroute/traceroute.8 index ebfcc364779f..33b986938f74 100644 --- a/contrib/traceroute/traceroute.8 +++ b/contrib/traceroute/traceroute.8 @@ -16,7 +16,7 @@ .\" $Id: traceroute.8,v 1.19 2000/09/21 08:44:19 leres Exp $ .\" $FreeBSD$ .\" -.Dd May 31, 2015 +.Dd June 20, 2019 .Dt TRACEROUTE 8 .Os .Sh NAME @@ -32,7 +32,7 @@ .Op Fl m Ar max_ttl .Op Fl P Ar proto .Op Fl p Ar port -.Op Fl q Ar nqueries +.Op Fl q Ar nprobes .Op Fl s Ar src_addr .Op Fl t Ar tos .Op Fl w Ar waittime @@ -125,14 +125,14 @@ Traceroute hopes that nothing is listening on UDP ports (or UDP-Lite ports if used by .Nm and supported by the peer) -.Em base + 1 +.Em port + 1 to -.Em base + nhops * nprobes +.Em port + (max_ttl - first_ttl + 1) * nprobes at the destination host (so an ICMP PORT_UNREACHABLE message will be returned to terminate the route tracing). If something is listening on a port in the default range, this option can be used to pick an unused port range. -.It Fl q Ar nqueries +.It Fl q Ar nprobes Set the number of probes per hop (default is 3, unless .Fl D diff --git a/etc/Makefile b/etc/Makefile index 7ee9eca7eb18..e2cac7446e1c 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -59,7 +59,8 @@ distribution: ${_+_}cd ${SRCTOP}/usr.sbin/rmt; ${MAKE} etc-rmt .if ${MK_UNBOUND} != "no" if [ ! -e ${DESTDIR}/etc/unbound ]; then \ - ${INSTALL_SYMLINK} ../var/unbound ${DESTDIR}/etc/unbound; \ + ${INSTALL_SYMLINK} -T "package=unbound" \ + ../var/unbound ${DESTDIR}/etc/unbound; \ fi .endif .if ${MK_SENDMAIL} != "no" @@ -68,26 +69,29 @@ distribution: .if ${MK_KERBEROS} != "no" cd ${.CURDIR}/root; \ ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 644 \ + -T "package=runtime" \ dot.k5login ${DESTDIR}/root/.k5login; .endif .if ${MK_MAIL} != "no" cd ${.CURDIR}/mail; ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 644 \ - ${ETCMAIL} ${DESTDIR}/etc/mail + -T "package=runtime" ${ETCMAIL} ${DESTDIR}/etc/mail if [ -d ${DESTDIR}/etc/mail -a -f ${DESTDIR}/etc/mail/aliases -a \ ! -f ${DESTDIR}/etc/aliases ]; then \ - ${INSTALL_SYMLINK} mail/aliases ${DESTDIR}/etc/aliases; \ + ${INSTALL_SYMLINK} -T "package=runtime" \ + mail/aliases ${DESTDIR}/etc/aliases; \ fi .endif .if ${MK_LOCATE} != "no" - ${INSTALL} -o nobody -g ${BINGRP} -m 644 /dev/null \ - ${DESTDIR}/var/db/locate.database + ${INSTALL} -o nobody -g ${BINGRP} -m 644 -T "package=runtime"\ + /dev/null ${DESTDIR}/var/db/locate.database .endif cd ${.CURDIR}/..; ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 \ - ${FREEBSD} ${DESTDIR}/ + -T "package=runtime" ${FREEBSD} ${DESTDIR}/ .if ${MK_BOOT} != "no" .if exists(${SRCTOP}/sys/${MACHINE}/conf/GENERIC.hints) ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 \ + -T "package=runtime" \ ${SRCTOP}/sys/${MACHINE}/conf/GENERIC.hints \ ${DESTDIR}/boot/device.hints .endif diff --git a/etc/mtree/BSD.debug.dist b/etc/mtree/BSD.debug.dist index d7bf660d3011..24803568396d 100644 --- a/etc/mtree/BSD.debug.dist +++ b/etc/mtree/BSD.debug.dist @@ -31,7 +31,7 @@ .. lib clang - 8.0.0 + 8.0.1 lib freebsd .. diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index 088eb80766d5..b0e305558f1a 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -152,6 +152,8 @@ .. ppbus .. + pwm + .. smbus .. speaker diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index b3c059cd52df..3cc5d3908952 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -722,6 +722,8 @@ .. .. .. + devrandom + .. dtrace .. fifo diff --git a/etc/mtree/BSD.usr.dist b/etc/mtree/BSD.usr.dist index c4c78368436f..0aac2f915fa1 100644 --- a/etc/mtree/BSD.usr.dist +++ b/etc/mtree/BSD.usr.dist @@ -37,7 +37,7 @@ aout .. clang - 8.0.0 + 8.0.1 include sanitizer .. diff --git a/etc/mtree/BSD.var.dist b/etc/mtree/BSD.var.dist index 3b694908f00c..8fefae055046 100644 --- a/etc/mtree/BSD.var.dist +++ b/etc/mtree/BSD.var.dist @@ -3,7 +3,7 @@ # Please see the file src/etc/mtree/README before making changes to this file. # -/set type=dir uname=root gname=wheel mode=0755 +/set type=dir uname=root gname=wheel mode=0755 tags=package=runtime . account .. @@ -32,7 +32,7 @@ .. crash .. - cron tags=package=runtime + cron tabs mode=0700 .. .. @@ -59,21 +59,21 @@ .. .. .. - empty mode=0555 flags=schg tags=package=runtime + empty mode=0555 flags=schg .. games gname=games mode=0775 .. heimdal mode=0700 .. - log tags=package=runtime + log .. - mail gname=mail mode=0775 tags=package=runtime + mail gname=mail mode=0775 .. msgs uname=daemon .. preserve .. - run tags=package=runtime + run dhclient .. ppp gname=network mode=0770 @@ -84,14 +84,16 @@ rwho gname=daemon mode=0775 .. spool - dma uname=root gname=mail mode=0770 + clientmqueue uname=smmsp gname=smmsp mode=0770 tags=package=sendmail + .. + dma uname=root gname=mail mode=0770 tags=package=dma .. lock uname=uucp gname=dialer mode=0775 .. /set gname=daemon lpd .. - mqueue + mqueue tags=package=sendmail .. opielocks mode=0700 .. @@ -101,7 +103,7 @@ .. /set gname=wheel .. - tmp mode=01777 tags=package=runtime + tmp mode=01777 vi.recover mode=01777 .. .. diff --git a/etc/sendmail/Makefile b/etc/sendmail/Makefile index 2692d55fdc0a..82260b7af398 100644 --- a/etc/sendmail/Makefile +++ b/etc/sendmail/Makefile @@ -64,29 +64,29 @@ ${mc:T:R}.cf: ${mc} all: ${ALL} distribution: - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 644 \ + ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 644 -T "package=sendmail" \ ${.CURDIR}/freebsd.mc freebsd.cf ${DESTDIR}/etc/mail - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 \ + ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 -T "package=sendmail" \ ${.CURDIR}/freebsd.submit.mc freebsd.submit.cf ${DESTDIR}/etc/mail - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 \ + ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 -T "package=sendmail" \ ${SMDIR}/helpfile ${DESTDIR}/etc/mail .if defined(INSTALL_CF) - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 644 \ + ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 644 -T "package=sendmail" \ ${INSTALL_CF} ${DEST_CF} .else - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 644 \ + ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 644 -T "package=sendmail" \ freebsd.cf ${DEST_CF} .endif .if defined(SENDMAIL_ADDITIONAL_CF) - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 644 \ + ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 644 -T "package=sendmail" \ ${SENDMAIL_ADDITIONAL_CF} ${DESTDIR}/etc/mail .endif .if !defined(SENDMAIL_SET_USER_ID) .if defined(INSTALL_SUBMIT_CF) - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 \ + ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 -T "package=sendmail" \ ${INSTALL_SUBMIT_CF} ${DEST_SUBMIT_CF} .else - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 \ + ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 -T "package=sendmail" \ freebsd.submit.cf ${DEST_SUBMIT_CF} .endif .endif diff --git a/gnu/lib/csu/Makefile b/gnu/lib/csu/Makefile index d754a588a6f0..b2aff8e6fba0 100644 --- a/gnu/lib/csu/Makefile +++ b/gnu/lib/csu/Makefile @@ -14,6 +14,7 @@ CCDIR= ${SRCTOP}/gnu/usr.bin/cc SRCS= crtstuff.c ${COMMONHDRS} OBJS= crtbegin.o crtend.o crtbeginT.o SOBJS= crtbeginS.o crtendS.o +DEPENDOBJS+= ${OBJS} ${SOBJS} CSTD?= gnu89 CFLAGS+= -DIN_GCC -DHAVE_LD_EH_FRAME_HDR -DDT_CONFIG -D__GLIBC__=3 CFLAGS.gcc+= -finhibit-size-directive -fno-toplevel-reorder @@ -49,23 +50,23 @@ CLEANFILES= ${OBJS} ${SOBJS} ${TGTOBJS} crtbegin.o: ${BEGINSRC} ${CC} ${CFLAGS} -g0 -DCRT_BEGIN \ - -c -o ${.TARGET} ${.ALLSRC:N*.h} + -c -o ${.TARGET} ${.ALLSRC:N*.h:[1]} crtbeginT.o: ${BEGINSRC} ${CC} ${CFLAGS} -g0 -DCRT_BEGIN -DCRTSTUFFT_O \ - -c -o ${.TARGET} ${.ALLSRC:N*.h} + -c -o ${.TARGET} ${.ALLSRC:N*.h:[1]} crtbeginS.o: ${BEGINSRC} ${CC} ${CFLAGS} -g0 -DCRT_BEGIN ${CRTS_CFLAGS} \ - -c -o ${.TARGET} ${.ALLSRC:N*.h} + -c -o ${.TARGET} ${.ALLSRC:N*.h:[1]} crtend.o: ${ENDSRC} ${CC} ${CFLAGS} -g0 -DCRT_END \ - -c -o ${.TARGET} ${.ALLSRC:N*.h} + -c -o ${.TARGET} ${.ALLSRC:N*.h:[1]} crtendS.o: ${ENDSRC} ${CC} ${CFLAGS} -g0 -DCRT_END ${CRTS_CFLAGS} \ - -c -o ${.TARGET} ${.ALLSRC:N*.h} + -c -o ${.TARGET} ${.ALLSRC:N*.h:[1]} COMMONHDRS+= tm.h tconfig.h options.h CLEANFILES+= ${COMMONHDRS} optionlist cs-tconfig.h cs-tm.h diff --git a/gnu/lib/libgcc/Makefile b/gnu/lib/libgcc/Makefile index 157495368c7e..9c5aae96185e 100644 --- a/gnu/lib/libgcc/Makefile +++ b/gnu/lib/libgcc/Makefile @@ -224,11 +224,11 @@ ${T}_OBJS_S = ${${T}_FUNCS:S/$/.pico/} SOBJS += ${${T}_FUNCS:S/$/.pico/} ${${T}_OBJS_T}: ${${T}_CFILE} ${COMMONHDRS} - ${CC_T} ${${T}_CFLAGS} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c} + ${CC_T} ${${T}_CFLAGS} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c:[1]} ${${T}_OBJS_P}: ${${T}_CFILE} ${COMMONHDRS} - ${CC_P} ${${T}_CFLAGS} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c} + ${CC_P} ${${T}_CFLAGS} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c:[1]} ${${T}_OBJS_S}: ${${T}_CFILE} ${COMMONHDRS} - ${CC_S} ${${T}_CFLAGS} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c} + ${CC_S} ${${T}_CFLAGS} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c:[1]} .endfor #----------------------------------------------------------------------- @@ -249,9 +249,9 @@ STAT_OBJS_P = ${SYMS_ST:S/$/.po/} STATICOBJS = ${SYMS_ST:S/$/.o/} ${STAT_OBJS_T}: ${STD_CFILE} ${COMMONHDRS} - ${CC_T} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c} + ${CC_T} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c:[1]} ${STAT_OBJS_P}: ${STD_CFILE} ${COMMONHDRS} - ${CC_P} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c} + ${CC_P} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c:[1]} #----------------------------------------------------------------------- # diff --git a/gnu/lib/libgcov/Makefile b/gnu/lib/libgcov/Makefile index 58c765515a6e..1510eea759b2 100644 --- a/gnu/lib/libgcov/Makefile +++ b/gnu/lib/libgcov/Makefile @@ -51,16 +51,16 @@ CLEANFILES+= ${COMMONHDRS} cs-tm.h cs-tconfig.h options.h optionlist ${OBJS} beforedepend: ${COMMONHDRS} ${OBJS_T}: libgcov.c - ${CC_T} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c} + ${CC_T} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c:[1]} .if !defined(NO_PIC) ${OBJS_S}: libgcov.c - ${CC_S} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c} + ${CC_S} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c:[1]} .endif .if ${MK_PROFILE} != "no" ${OBJS_P}: libgcov.c - ${CC_P} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c} + ${CC_P} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c:[1]} .endif .include diff --git a/include/Makefile b/include/Makefile index d1b000cf8a8e..bd0ddc10b492 100644 --- a/include/Makefile +++ b/include/Makefile @@ -46,8 +46,8 @@ LSUBDIRS= cam/ata cam/mmc cam/nvme cam/scsi \ dev/acpica dev/agp dev/an dev/bktr dev/ciss dev/filemon dev/firewire \ dev/hwpmc dev/hyperv \ dev/ic dev/iicbus dev/io dev/mfi dev/mmc dev/nvme \ - dev/ofw dev/pbio dev/pci ${_dev_powermac_nvram} dev/ppbus dev/smbus \ - dev/speaker dev/tcp_log dev/veriexec dev/vkbd dev/wi \ + dev/ofw dev/pbio dev/pci ${_dev_powermac_nvram} dev/ppbus dev/pwm \ + dev/smbus dev/speaker dev/tcp_log dev/veriexec dev/vkbd dev/wi \ fs/devfs fs/fdescfs fs/msdosfs fs/nandfs fs/nfs fs/nullfs \ fs/procfs fs/smbfs fs/udf fs/unionfs \ geom/cache geom/concat geom/eli geom/gate geom/journal geom/label \ diff --git a/lib/clang/freebsd_cc_version.h b/lib/clang/freebsd_cc_version.h index 7bf633480df7..b860ae7f8657 100644 --- a/lib/clang/freebsd_cc_version.h +++ b/lib/clang/freebsd_cc_version.h @@ -1,3 +1,3 @@ /* $FreeBSD$ */ -#define FREEBSD_CC_VERSION 1300003 +#define FREEBSD_CC_VERSION 1300004 diff --git a/lib/clang/headers/Makefile b/lib/clang/headers/Makefile index 0d03ee928738..e015283131c6 100644 --- a/lib/clang/headers/Makefile +++ b/lib/clang/headers/Makefile @@ -4,7 +4,7 @@ .PATH: ${CLANG_SRCS}/lib/Headers -INCSDIR= ${LIBDIR}/clang/8.0.0/include +INCSDIR= ${LIBDIR}/clang/8.0.1/include GENINCS+= arm_fp16.h GENINCS+= arm_neon.h diff --git a/lib/clang/include/clang/Basic/Version.inc b/lib/clang/include/clang/Basic/Version.inc index 4f0b7700f434..f15c56a1ac52 100644 --- a/lib/clang/include/clang/Basic/Version.inc +++ b/lib/clang/include/clang/Basic/Version.inc @@ -1,11 +1,11 @@ /* $FreeBSD$ */ -#define CLANG_VERSION 8.0.0 -#define CLANG_VERSION_STRING "8.0.0" +#define CLANG_VERSION 8.0.1 +#define CLANG_VERSION_STRING "8.0.1" #define CLANG_VERSION_MAJOR 8 #define CLANG_VERSION_MINOR 0 -#define CLANG_VERSION_PATCHLEVEL 0 +#define CLANG_VERSION_PATCHLEVEL 1 #define CLANG_VENDOR "FreeBSD " -#define SVN_REVISION "356365" +#define SVN_REVISION "363030" diff --git a/lib/clang/include/clang/Config/config.h b/lib/clang/include/clang/Config/config.h index ced2d4870fde..7b6b72d9343f 100644 --- a/lib/clang/include/clang/Config/config.h +++ b/lib/clang/include/clang/Config/config.h @@ -62,7 +62,7 @@ #define CLANG_HAVE_RLIMITS 1 /* The LLVM product name and version */ -#define BACKEND_PACKAGE_STRING "LLVM 8.0.0" +#define BACKEND_PACKAGE_STRING "LLVM 8.0.1" /* Linker version detected at compile time. */ /* #undef HOST_LINK_VERSION */ diff --git a/lib/clang/include/lld/Common/Version.inc b/lib/clang/include/lld/Common/Version.inc index 67dc3ea96718..4eee96656e13 100644 --- a/lib/clang/include/lld/Common/Version.inc +++ b/lib/clang/include/lld/Common/Version.inc @@ -1,10 +1,10 @@ // $FreeBSD$ -#define LLD_VERSION 8.0.0 -#define LLD_VERSION_STRING "8.0.0" +#define LLD_VERSION 8.0.1 +#define LLD_VERSION_STRING "8.0.1" #define LLD_VERSION_MAJOR 8 #define LLD_VERSION_MINOR 0 #define LLD_REPOSITORY_STRING "FreeBSD" // - -#define LLD_REVISION_STRING "356365-1300003" +#define LLD_REVISION_STRING "363030-1300004" diff --git a/lib/clang/include/llvm/Config/config.h b/lib/clang/include/llvm/Config/config.h index c3c13a0d34ed..27b184fd86c5 100644 --- a/lib/clang/include/llvm/Config/config.h +++ b/lib/clang/include/llvm/Config/config.h @@ -330,10 +330,10 @@ #define PACKAGE_NAME "LLVM" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "LLVM 8.0.0" +#define PACKAGE_STRING "LLVM 8.0.1" /* Define to the version of this package. */ -#define PACKAGE_VERSION "8.0.0" +#define PACKAGE_VERSION "8.0.1" /* Define to the vendor of this package. */ /* #undef PACKAGE_VENDOR */ diff --git a/lib/clang/include/llvm/Config/llvm-config.h b/lib/clang/include/llvm/Config/llvm-config.h index 311c9026ad78..3a511e3c75cd 100644 --- a/lib/clang/include/llvm/Config/llvm-config.h +++ b/lib/clang/include/llvm/Config/llvm-config.h @@ -73,10 +73,10 @@ #define LLVM_VERSION_MINOR 0 /* Patch version of the LLVM API */ -#define LLVM_VERSION_PATCH 0 +#define LLVM_VERSION_PATCH 1 /* LLVM version string */ -#define LLVM_VERSION_STRING "8.0.0" +#define LLVM_VERSION_STRING "8.0.1" /* Whether LLVM records statistics for use with GetStatistics(), * PrintStatistics() or PrintStatisticsJSON() diff --git a/lib/clang/include/llvm/Support/VCSRevision.h b/lib/clang/include/llvm/Support/VCSRevision.h index 8faf47acd038..230bcddd155e 100644 --- a/lib/clang/include/llvm/Support/VCSRevision.h +++ b/lib/clang/include/llvm/Support/VCSRevision.h @@ -1,2 +1,2 @@ /* $FreeBSD$ */ -#define LLVM_REVISION "svn-r356365" +#define LLVM_REVISION "svn-r363030" diff --git a/lib/csu/Makefile.inc b/lib/csu/Makefile.inc index e5f6bb7f5638..a58edf8d7e16 100644 --- a/lib/csu/Makefile.inc +++ b/lib/csu/Makefile.inc @@ -22,10 +22,11 @@ crtend.o: crtend.c crtendS.o: crtend.c crtbegin.o crtend.o crtbeginT.o: - ${CC} ${CFLAGS} -I${.CURDIR} -c -o ${.TARGET} ${.ALLSRC} + ${CC} ${CFLAGS} -I${.CURDIR} -c -o ${.TARGET} ${.ALLSRC:N*.h:[1]} crtbeginS.o crtendS.o: - ${CC} ${CFLAGS} -I${.CURDIR} ${CFLAGS_CRTS} -c -o ${.TARGET} ${.ALLSRC} + ${CC} ${CFLAGS} -I${.CURDIR} ${CFLAGS_CRTS} -c -o ${.TARGET} \ + ${.ALLSRC:N*.h:[1]} .endif diff --git a/lib/libarchive/config_freebsd.h b/lib/libarchive/config_freebsd.h index 99f50150605e..2d40f595a517 100644 --- a/lib/libarchive/config_freebsd.h +++ b/lib/libarchive/config_freebsd.h @@ -209,6 +209,7 @@ #define HAVE_TZSET 1 #define HAVE_UINTMAX_T 1 #define HAVE_UNISTD_H 1 +#define HAVE_UNLINKAT 1 #define HAVE_UNSETENV 1 #define HAVE_UNSIGNED_LONG_LONG 1 #define HAVE_UNSIGNED_LONG_LONG_INT 1 diff --git a/lib/libarchive/tests/Makefile b/lib/libarchive/tests/Makefile index e9c51c97aa53..be3d13549362 100644 --- a/lib/libarchive/tests/Makefile +++ b/lib/libarchive/tests/Makefile @@ -506,6 +506,7 @@ ${PACKAGE}FILES+= test_read_format_rar_multivolume.part0004.rar.uu ${PACKAGE}FILES+= test_read_format_rar_noeof.rar.uu ${PACKAGE}FILES+= test_read_format_rar_ppmd_lzss_conversion.rar.uu ${PACKAGE}FILES+= test_read_format_rar_ppmd_use_after_free.rar.uu +${PACKAGE}FILES+= test_read_format_rar_ppmd_use_after_free2.rar.uu ${PACKAGE}FILES+= test_read_format_rar_sfx.exe.uu ${PACKAGE}FILES+= test_read_format_rar_subblock.rar.uu ${PACKAGE}FILES+= test_read_format_rar_unicode.rar.uu @@ -513,6 +514,7 @@ ${PACKAGE}FILES+= test_read_format_rar_windows.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_arm.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_blake2.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_compressed.rar.uu +${PACKAGE}FILES+= test_read_format_rar5_different_window_size.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_distance_overflow.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_extra_field_version.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_fileattr.rar.uu diff --git a/lib/libc/sys/open.2 b/lib/libc/sys/open.2 index 012e0afd23d8..a876cccb84b5 100644 --- a/lib/libc/sys/open.2 +++ b/lib/libc/sys/open.2 @@ -28,7 +28,7 @@ .\" @(#)open.2 8.2 (Berkeley) 11/16/93 .\" $FreeBSD$ .\" -.Dd November 11, 2018 +.Dd June 14, 2019 .Dt OPEN 2 .Os .Sh NAME @@ -224,10 +224,7 @@ The descriptor remains in non-blocking mode for subsequent operations. If .Dv O_FSYNC is used in the mask, all writes will -immediately be written to disk, -the kernel will not cache written data -and all writes on the descriptor will not return until -the data to be written completes. +immediately and synchronously be written to disk. .Pp .Dv O_SYNC is a synonym for diff --git a/lib/libcasper/services/cap_fileargs/cap_fileargs.c b/lib/libcasper/services/cap_fileargs/cap_fileargs.c index 71dd88f93a9c..f9b7da02bebc 100644 --- a/lib/libcasper/services/cap_fileargs/cap_fileargs.c +++ b/lib/libcasper/services/cap_fileargs/cap_fileargs.c @@ -424,6 +424,39 @@ fileargs_free(fileargs_t *fa) free(fa); } +cap_channel_t * +fileargs_unwrap(fileargs_t *fa, int *flags) +{ + cap_channel_t *chan; + + if (fa == NULL) + return (NULL); + + assert(fa->fa_magic == FILEARGS_MAGIC); + + chan = fa->fa_chann; + if (flags != NULL) { + *flags = fa->fa_fdflags; + } + + nvlist_destroy(fa->fa_cache); + explicit_bzero(&fa->fa_magic, sizeof(fa->fa_magic)); + free(fa); + + return (chan); +} + +fileargs_t * +fileargs_wrap(cap_channel_t *chan, int fdflags) +{ + + if (chan == NULL) { + return (NULL); + } + + return (fileargs_create(chan, fdflags)); +} + /* * Service functions. */ diff --git a/lib/libcasper/services/cap_fileargs/cap_fileargs.h b/lib/libcasper/services/cap_fileargs/cap_fileargs.h index 09b42859863d..c00f84375ac2 100644 --- a/lib/libcasper/services/cap_fileargs/cap_fileargs.h +++ b/lib/libcasper/services/cap_fileargs/cap_fileargs.h @@ -54,6 +54,9 @@ int fileargs_lstat(fileargs_t *fa, const char *name, struct stat *sb); int fileargs_open(fileargs_t *fa, const char *name); void fileargs_free(fileargs_t *fa); FILE *fileargs_fopen(fileargs_t *fa, const char *name, const char *mode); + +fileargs_t *fileargs_wrap(cap_channel_t *chan, int fdflags); +cap_channel_t *fileargs_unwrap(fileargs_t *fa, int *fdflags); #else typedef struct fileargs { int fa_flags; @@ -114,7 +117,27 @@ FILE *fileargs_fopen(fileargs_t *fa, const char *name, const char *mode) (void) fa; return (fopen(name, mode)); } -#define fileargs_free(fa) (free(fa)) +#define fileargs_free(fa) (free(fa)) + +static inline fileargs_t * +fileargs_wrap(cap_channel_t *chan, int fdflags) +{ + + cap_close(chan); + return (fileargs_init(0, NULL, fdflags, 0, NULL, 0)); +} + +static inline cap_channel_t * +fileargs_unwrap(fileargs_t *fa, int *fdflags) +{ + + if (fdflags != NULL) { + *fdflags = fa->fa_flags; + } + fileargs_free(fa); + return (cap_init()); +} + #endif #endif /* !_FILEARGS_H_ */ diff --git a/lib/libclang_rt/Makefile.inc b/lib/libclang_rt/Makefile.inc index 067e370fe977..9420e81e746b 100644 --- a/lib/libclang_rt/Makefile.inc +++ b/lib/libclang_rt/Makefile.inc @@ -14,7 +14,7 @@ CRTSRC= ${SRCTOP}/contrib/compiler-rt .PATH: ${CRTSRC}/lib -CLANGDIR= /usr/lib/clang/8.0.0 +CLANGDIR= /usr/lib/clang/8.0.1 LIBDIR= ${CLANGDIR}/lib/freebsd SHLIBDIR= ${LIBDIR} diff --git a/lib/libmagic/Makefile b/lib/libmagic/Makefile index 7febf1c2297c..a3036d7f3f58 100644 --- a/lib/libmagic/Makefile +++ b/lib/libmagic/Makefile @@ -41,10 +41,11 @@ magic.mgc: mkmagic magic ${BTOOLSPATH:U.}/mkmagic magic CLEANFILES+= mkmagic +DEPENDOBJS+= mkmagic build-tools: mkmagic mkmagic: apprentice.c cdf_time.c encoding.c funcs.c magic.c print.c ${INCS} ${BUILD_TOOLS_META} - ${CC:N${CCACHE_BIN}} ${CFLAGS} -DCOMPILE_ONLY ${LDFLAGS} -o ${.TARGET} ${.ALLSRC:N*.h} \ - ${LDADD} + ${CC:N${CCACHE_BIN}} ${CFLAGS} -DCOMPILE_ONLY ${LDFLAGS} -o ${.TARGET} \ + ${.ALLSRC:N*.h:O:u} ${LDADD} FILEVER!= awk '$$1 == "\#define" && $$2 == "VERSION" { print $$3; exit }' \ ${.CURDIR}/config.h diff --git a/lib/libufs/Makefile b/lib/libufs/Makefile index 2685f7318ac1..a3f4cb3991ed 100644 --- a/lib/libufs/Makefile +++ b/lib/libufs/Makefile @@ -5,7 +5,8 @@ LIB= ufs SHLIBDIR?= /lib SHLIB_MAJOR= 7 -SRCS= block.c cgroup.c crc32.c inode.c sblock.c type.c ffs_subr.c ffs_tables.c +SRCS= block.c cgroup.c gsb_crc32.c inode.c sblock.c type.c ffs_subr.c +SRCS+= ffs_tables.c INCS= libufs.h MAN= bread.3 cgread.3 getinode.3 libufs.3 sbread.3 ufs_disk_close.3 diff --git a/lib/libusb/libusb20.c b/lib/libusb/libusb20.c index 05094443c10b..255e7d5ed516 100644 --- a/lib/libusb/libusb20.c +++ b/lib/libusb/libusb20.c @@ -955,6 +955,14 @@ libusb20_dev_alloc_config(struct libusb20_device *pdev, uint8_t configIndex) uint8_t do_close; int error; + /* + * Catch invalid configuration descriptor reads early on to + * avoid issues with devices that don't check for a valid USB + * configuration read request. + */ + if (configIndex >= pdev->ddesc.bNumConfigurations) + return (NULL); + if (!pdev->is_opened) { error = libusb20_dev_open(pdev, 0); if (error) { diff --git a/lib/ncurses/ncurses/Makefile b/lib/ncurses/ncurses/Makefile index 8e6adfcc1fb2..196bbc453df4 100644 --- a/lib/ncurses/ncurses/Makefile +++ b/lib/ncurses/ncurses/Makefile @@ -389,6 +389,7 @@ keys.list: MKkeys_list.sh Caps ${NCURSES_DIR}/include/Caps | LC_ALL=C sort > keys.list # Build tools +DEPENDOBJS+= make_hash make_keys build-tools: make_hash make_keys make_keys: make_keys.c names.c ncurses_def.h ${HEADERS} ${BUILD_TOOLS_META} diff --git a/libexec/rc/rc.conf b/libexec/rc/rc.conf index 0709845259e3..79bc1f3436e5 100644 --- a/libexec/rc/rc.conf +++ b/libexec/rc/rc.conf @@ -275,6 +275,7 @@ ppp_user="root" # Which user to run ppp as # profile3 uses default ppp_mode and ppp_nat ### Network daemon (miscellaneous) ### +hostapd_program="/usr/sbin/hostapd" hostapd_enable="NO" # Run hostap daemon. syslogd_enable="YES" # Run syslog daemon (or NO). syslogd_program="/usr/sbin/syslogd" # path to syslogd, if you want a different one. diff --git a/libexec/rc/rc.d/hostapd b/libexec/rc/rc.d/hostapd index d0c2d88f2ff4..707316036604 100755 --- a/libexec/rc/rc.d/hostapd +++ b/libexec/rc/rc.d/hostapd @@ -11,7 +11,7 @@ name="hostapd" desc="Authenticator for IEEE 802.11 networks" -command="/usr/sbin/${name}" +command=${hostapd_program} ifn="$2" if [ -z "$ifn" ]; then diff --git a/libexec/rc/rc.d/local b/libexec/rc/rc.d/local index c5aa0e4a690d..ba17a674ae9d 100755 --- a/libexec/rc/rc.d/local +++ b/libexec/rc/rc.d/local @@ -11,7 +11,7 @@ . /etc/rc.subr name="local" -desc="Run /etc/rc.local and /etc/shutdown.local" +desc="Run /etc/rc.local and /etc/rc.shutdown.local" start_cmd="local_start" stop_cmd="local_stop" diff --git a/release/release.sh b/release/release.sh index cff917949cf9..1e7e86f330fa 100755 --- a/release/release.sh +++ b/release/release.sh @@ -388,6 +388,7 @@ chroot_arm_build_release() { [ ! -z "${RELEASECONF}" ] && . "${RELEASECONF}" export MAKE_FLAGS="${MAKE_FLAGS} TARGET=${EMBEDDED_TARGET}" export MAKE_FLAGS="${MAKE_FLAGS} TARGET_ARCH=${EMBEDDED_TARGET_ARCH}" + export MAKE_FLAGS="${MAKE_FLAGS} ${CONF_FILES}" eval chroot ${CHROOTDIR} env WITH_UNIFIED_OBJDIR=1 make ${MAKE_FLAGS} -C /usr/src/release obj export WORLDDIR="$(eval chroot ${CHROOTDIR} make ${MAKE_FLAGS} -C /usr/src/release -V WORLDDIR)" export OBJDIR="$(eval chroot ${CHROOTDIR} env WITH_UNIFIED_OBJDIR=1 make ${MAKE_FLAGS} -C /usr/src/release -V .OBJDIR)" diff --git a/release/tools/arm.subr b/release/tools/arm.subr index 5b024334188e..7deee7546544 100644 --- a/release/tools/arm.subr +++ b/release/tools/arm.subr @@ -166,7 +166,7 @@ arm_install_base() { TARGET=${EMBEDDED_TARGET} \ TARGET_ARCH=${EMBEDDED_TARGET_ARCH} \ DESTDIR=${DESTDIR} KERNCONF=${KERNEL} \ - installworld installkernel distribution + ${CONF_FILES} installworld installkernel distribution chroot ${CHROOTDIR} mkdir -p ${DESTDIR}/boot/msdos arm_create_user diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index 401f3e389e80..0784fab75a0e 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -2059,7 +2059,7 @@ ata_read_native_max(struct cam_device *device, int retry_count, /*sector_count*/0, /*data_ptr*/NULL, /*dxfer_len*/0, - timeout ? timeout : 1000, + timeout ? timeout : 5000, is48bit); if (error) diff --git a/sbin/dump/dump.8 b/sbin/dump/dump.8 index 5df399a17795..56aea04551f8 100644 --- a/sbin/dump/dump.8 +++ b/sbin/dump/dump.8 @@ -29,7 +29,7 @@ .\" @(#)dump.8 8.3 (Berkeley) 5/1/95 .\" $FreeBSD$ .\" -.Dd June 11, 2018 +.Dd June 13, 2019 .Dt DUMP 8 .Os .Sh NAME @@ -266,6 +266,12 @@ used to update a remote copy of a level 0 dump, since the date changes for each dump. This option sets both dates to the epoch, permitting rsync to be much more efficient when transferring a dump file. +The +.Fl r +option can be used only to create level 0 dumps. +A dump using the +.Fl r +option cannot be used as the basis for a later incremental dump. .It Fl R Be even more rsync-friendly. This option disables the storage of the actual inode access time @@ -277,6 +283,12 @@ The .Fl R option also sets .Fl r . +The +.Fl R +option can be used only to create level 0 dumps. +A dump using the +.Fl R +option cannot be used as the basis for a later incremental dump. .It Fl S Display an estimate of the backup size and the number of tapes required, and exit without actually performing the dump. diff --git a/sbin/fsck_msdosfs/boot.c b/sbin/fsck_msdosfs/boot.c index 9e0958a94544..56bd57d7be13 100644 --- a/sbin/fsck_msdosfs/boot.c +++ b/sbin/fsck_msdosfs/boot.c @@ -49,7 +49,7 @@ readboot(int dosfs, struct bootblock *boot) u_char backup[DOSBOOTBLOCKSIZE]; int ret = FSOK; int i; - + if ((size_t)read(dosfs, block, sizeof block) != sizeof block) { perr("could not read boot block"); return FSFATAL; @@ -219,7 +219,7 @@ readboot(int dosfs, struct bootblock *boot) boot->NumClusters = (boot->NumSectors - boot->ClusterOffset) / boot->bpbSecPerClust; - if (boot->flags&FAT32) + if (boot->flags & FAT32) boot->ClustMask = CLUST32_MASK; else if (boot->NumClusters < (CLUST_RSRVD&CLUST12_MASK)) boot->ClustMask = CLUST12_MASK; diff --git a/sbin/fsck_msdosfs/dir.c b/sbin/fsck_msdosfs/dir.c index e59536f6b5fc..e56bbf80c6bf 100644 --- a/sbin/fsck_msdosfs/dir.c +++ b/sbin/fsck_msdosfs/dir.c @@ -629,6 +629,15 @@ readDosDirSection(int f, struct bootblock *boot, struct fatEntry *fat, vallfn = NULL; } lidx = *p & LRNOMASK; + if (lidx == 0) { + pwarn("invalid long name\n"); + if (!invlfn) { + invlfn = vallfn; + invcl = valcl; + } + vallfn = NULL; + continue; + } t = longName + --lidx * 13; for (k = 1; k < 11 && t < longName + sizeof(longName); k += 2) { diff --git a/sbin/fsck_msdosfs/main.c b/sbin/fsck_msdosfs/main.c index 8425d8adee8a..6802afcefc46 100644 --- a/sbin/fsck_msdosfs/main.c +++ b/sbin/fsck_msdosfs/main.c @@ -87,16 +87,15 @@ main(int argc, char **argv) exit(5); case 'n': alwaysno = 1; - alwaysyes = preen = 0; + alwaysyes = 0; break; case 'y': alwaysyes = 1; - alwaysno = preen = 0; + alwaysno = 0; break; case 'p': preen = 1; - alwaysyes = alwaysno = 0; break; default: @@ -130,9 +129,10 @@ ask(int def, const char *fmt, ...) char prompt[256]; int c; + if (alwaysyes || alwaysno || rdonly) + def = (alwaysyes && !rdonly && !alwaysno); + if (preen) { - if (rdonly) - def = 0; if (def) printf("FIXED\n"); return def; @@ -141,9 +141,9 @@ ask(int def, const char *fmt, ...) va_start(ap, fmt); vsnprintf(prompt, sizeof(prompt), fmt, ap); va_end(ap); - if (alwaysyes || rdonly) { - printf("%s? %s\n", prompt, rdonly ? "no" : "yes"); - return !rdonly; + if (alwaysyes || alwaysno || rdonly) { + printf("%s? %s\n", prompt, def ? "yes" : "no"); + return def; } do { printf("%s? [yn] ", prompt); diff --git a/share/examples/bhyve/vmrun.sh b/share/examples/bhyve/vmrun.sh index bc9d69c42b78..607597015e62 100755 --- a/share/examples/bhyve/vmrun.sh +++ b/share/examples/bhyve/vmrun.sh @@ -75,7 +75,7 @@ usage() { echo " -E: Use UEFI mode" echo " -f: Use a specific UEFI firmware" echo " -F: Use a custom UEFI GOP framebuffer size" \ - "(default: ${DEFAULT_VNCSIZE}" + "(default: ${DEFAULT_VNCSIZE})" echo " -g: listen for connection from kgdb at " echo " -H: host filesystem to export to the loader" echo " -i: force boot of the Installation CDROM image" diff --git a/share/man/man3/Makefile b/share/man/man3/Makefile index 8267f9f24e40..ff7309d2084d 100644 --- a/share/man/man3/Makefile +++ b/share/man/man3/Makefile @@ -179,8 +179,21 @@ MLINKS+= tree.3 RB_EMPTY.3 \ tree.3 RB_ENTRY.3 \ tree.3 RB_FIND.3 \ tree.3 RB_FOREACH.3 \ + tree.3 RB_FOREACH_FROM.3 \ tree.3 RB_FOREACH_REVERSE.3 \ + tree.3 RB_FOREACH_REVERSE_FROM.3 \ + tree.3 RB_FOREACH_REVERSE_SAFE.3 \ + tree.3 RB_FOREACH_SAFE.3 \ tree.3 RB_GENERATE.3 \ + tree.3 RB_GENERATE_FIND.3 \ + tree.3 RB_GENERATE_INSERT.3 \ + tree.3 RB_GENERATE_INSERT_COLOR.3 \ + tree.3 RB_GENERATE_MINMAX.3 \ + tree.3 RB_GENERATE_NEXT.3 \ + tree.3 RB_GENERATE_NFIND.3 \ + tree.3 RB_GENERATE_PREV.3 \ + tree.3 RB_GENERATE_REMOVE.3 \ + tree.3 RB_GENERATE_REMOVE_COLOR.3 \ tree.3 RB_GENERATE_STATIC.3 \ tree.3 RB_HEAD.3 \ tree.3 RB_INIT.3 \ @@ -194,6 +207,15 @@ MLINKS+= tree.3 RB_EMPTY.3 \ tree.3 RB_PARENT.3 \ tree.3 RB_PREV.3 \ tree.3 RB_PROTOTYPE.3 \ + tree.3 RB_PROTOTYPE_FIND.3 \ + tree.3 RB_PROTOTYPE_INSERT.3 \ + tree.3 RB_PROTOTYPE_INSERT_COLOR.3 \ + tree.3 RB_PROTOTYPE_MINMAX.3 \ + tree.3 RB_PROTOTYPE_NEXT.3 \ + tree.3 RB_PROTOTYPE_NFIND.3 \ + tree.3 RB_PROTOTYPE_PREV.3 \ + tree.3 RB_PROTOTYPE_REMOVE.3 \ + tree.3 RB_PROTOTYPE_REMOVE_COLOR.3 \ tree.3 RB_PROTOTYPE_STATIC.3 \ tree.3 RB_REMOVE.3 \ tree.3 RB_RIGHT.3 \ diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 8a8fb67a3aad..a810d9153349 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -418,6 +418,7 @@ MAN= aac.4 \ pts.4 \ pty.4 \ puc.4 \ + pwmc.4 \ ${_qlxge.4} \ ${_qlxgb.4} \ ${_qlxgbe.4} \ diff --git a/share/man/man4/filemon.4 b/share/man/man4/filemon.4 index 0f1b60edb040..24707fe3e592 100644 --- a/share/man/man4/filemon.4 +++ b/share/man/man4/filemon.4 @@ -31,7 +31,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 22, 2016 +.Dd June 15, 2019 .Dt FILEMON 4 .Os .Sh NAME @@ -79,8 +79,7 @@ The next log entry may be lacking an absolute path or be inaccurate. .It Ql L .Xr link 2 , .Xr linkat 2 , -.Xr symlink 2 , -.Xr symlinkat 2 +.Xr symlink 2 .It Ql M .Xr rename 2 .It Ql R diff --git a/share/man/man4/netmap.4 b/share/man/man4/netmap.4 index cbdd554357dd..b24a4ac754b5 100644 --- a/share/man/man4/netmap.4 +++ b/share/man/man4/netmap.4 @@ -40,7 +40,7 @@ is a framework for extremely fast and efficient packet I/O for userspace and kernel clients, and for Virtual Machines. It runs on -.Fx +.Fx , Linux and some versions of Windows, and supports a variety of .Nm netmap ports , including diff --git a/share/man/man4/pci.4 b/share/man/man4/pci.4 index 5ae10657e550..2196c9fce852 100644 --- a/share/man/man4/pci.4 +++ b/share/man/man4/pci.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 14, 2018 +.Dd June 17, 2019 .Dt PCI 4 .Os .Sh NAME @@ -290,7 +290,7 @@ This .Xr ioctl 2 reads the .Tn PCI -configuration registers specified by the passed-in +configuration register specified by the passed-in .Va pci_io structure. The @@ -307,7 +307,7 @@ from the ioctl. .It pi_reg The .Tn PCI -configuration register the user would like to access. +configuration registers the user would like to access. .It pi_width The width, in bytes, of the data the user would like to read. This value @@ -323,7 +323,7 @@ This .Xr ioctl 2 allows users to write to the .Tn PCI -specified in the passed-in +configuration registers specified in the passed-in .Va pci_io structure. The @@ -333,6 +333,26 @@ The limitations on data width described for reading registers, above, also apply to writing .Tn PCI configuration registers. +.It PCIOCATTACHED +This +.Xr ioctl 2 +allows users to query if a driver is attached to the +.Tn PCI +device specified in the passed-in +.Va pci_io +structure. +The +.Va pci_io +structure is described above, however, the +.Va pi_reg +and +.Va pi_width +fields are not used. +The status of the device is stored in the +.Va pi_data +field. +A value of 0 indicates no driver is attached, while a value larger than 0 +indicates that a driver is attached. .It PCIOCBARMMAP This .Xr ioctl 2 diff --git a/share/man/man4/pwmc.4 b/share/man/man4/pwmc.4 new file mode 100644 index 000000000000..537a22faa8a9 --- /dev/null +++ b/share/man/man4/pwmc.4 @@ -0,0 +1,212 @@ +.\" +.\" Copyright (c) 2019 Ian Lepore +.\" +.\" 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 June 17, 2019 +.Dt PWMC 4 +.Os +.Sh NAME +.Nm pwmc +.Nd PWM (Pulse Width Modulation) control 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 pwmbus" +.Cd "device pwmc" +.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 +pwmc_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver provides device-control access to a channel of PWM hardware. +Each instance of a +.Nm +device is associated with a single PWM output channel. +.Pp +Some PWM hardware is organized with multiple channels sharing a +common clock or other resources. +In such cases, a separate +.Nm +instance will exist for each channel, but changing the period or +duty cycle of any one channel may affect other channels within the +hardware which share the same resources. +Consult the documentation for the underlying PWM hardware device driver +for details on channels that share resources. +.Pp +An instance of +.Nm +creates a character device named +.Pa /dev/pwm/pwmcX.Y +where +.Va X +is a sequential number assigned to each PWM hardware controller +as it is discovered by the system, and +.Va Y +is the channel number within that hardware controller. +The driver can be configured to create aliases that point to the +.Pa pwmcX.Y +entries, in effect creating named channels. +.Pp +The +.Nm +driver provides control of a PWM channel with the following +.Xr ioctl 2 +calls and data structures, defined in +.In dev/pwm/pwmc.h : +.Bl -tag -width indent +.It Dv PWMGETSTATE Pq Vt "struct pwm_state" +Retrieve the current state of the channel. +.It Dv PWMSETSTATE Pq Vt "struct pwm_state" +Set the current state of the channel. +All parameters are updated on every call. +To change just one of the values, use +.Dv PWMGETSTATE +to get the current state and then submit the same data back with +just the appropriate value changed. +.El +.Pp +The +.Va pwm_state +structure is defined as follows: +.Bd -literal +struct pwm_state { + u_int period; + u_int duty; + uint32_t flags; + bool enable; +}; +.Ed +.Pp +.Bl -tag -width period +.It Va period +The duration, in nanoseconds, of one complete on-off cycle. +.It Va duty +The duration, in nanoseconds, of the on portion of one cycle. +.It Va flags +Flags that affect the output signal can be bitwise-ORed together. +The following flags are currently defined: +.Pp +.Bl -tag -width PWM_POLARITY_INVERTED -compact +.It Dv PWM_POLARITY_INVERTED +Invert the signal polarity. +.El +.It Va enable +.Va +False to disable the output signal or true to enable it. +.El +.Sh HINTS CONFIGURATION +On a +.Xr device.hints 5 +based system, such as +.Li MIPS , +these values are configurable for +.Nm : +.Bl -tag -width indent +.It Va hint.pwmc.%d.at +The pwmbus instance the +.Nm +instance is attached to. +.It Va hint.pwmc.%d.channel +The hardware channel number the instance is attached to. +Channel numbers count up from zero. +.It Va hint.pwmc.%d.label +If this optional hint is set, the driver creates an alias in +.Pa /dev/pwm +with the given name, which points to the instance. +.El +.Sh FDT CONFIGURATION +On an +.Xr fdt 4 +based system, a +.Nm +device is described with a child node of the pwm hardware controller node. +When the hardware supports multiple channels within the controller, it is +not necessary to include a +.Nm +child node for every channel the hardware supports. +Define only the channels you need to control. +.Pp +The following properties are required for a +.Nm +device node: +.Bl -tag -width indent +.It Va compatible +Must be the string "freebsd,pwmc". +.It Va reg +The hardware channel number. +.El +.Pp +The following properties are optional for the +.Nm +device node: +.Bl -tag -width indent +.It Va label +A string containing only characters legal in a file name. +The driver creates an alias with the given name in +.Pa /dev/pwm +which points to the instance's +.Pa /dev/pwm/pwmcX.Y +device entry. +.El +.Pp +Example of a PWM hardware node containing one +.Nm +child node: +.Bd -literal +&ehrpwm0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ehrpwm0_AB_pins>; + + pwmcontrol@0 { + compatible = "freebsd,pwmc"; + reg = <0>; + label = "backlight"; + }; +}; +.Ed +.Sh FILES +.Bl -tag -width -compact +.It Pa /dev/pwm/pwmc* +.El +.Sh SEE ALSO +.Xr fdt 4 , +.Xr device.hints 5 , +.Xr pwm 8 , +.Xr pwm 9 +.Sh HISTORY +The +.Nm +driver +appeared in +.Fx 13.0 . diff --git a/share/man/man4/termios.4 b/share/man/man4/termios.4 index 6f38cf3b9f91..e3fb9635d247 100644 --- a/share/man/man4/termios.4 +++ b/share/man/man4/termios.4 @@ -1185,6 +1185,8 @@ flow control of output */ /* RTS flow control of input */ .It Dv MDMBUF /* flow control output via Carrier */ +.It Dv CNO_RTSDTR +/* Do not assert RTS or DTR automatically */ .El .Pp The @@ -1267,6 +1269,12 @@ If is set then output flow control is controlled by the state of Carrier Detect. .Pp +If +.Dv CNO_RTSDTR +is set then the RTS and DTR lines will not be asserted when the device +is opened. +As a result, this flag is only useful on initial-state devices. +.Pp If the object for which the control modes are set is not an asynchronous serial connection, some of the modes may be ignored; for example, if an attempt is made to set the baud rate on a network connection to a diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index f1eb33b92c3e..682eb2a39502 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -399,6 +399,7 @@ MAN= accept_filter.9 \ VOP_ADVLOCK.9 \ VOP_ALLOCATE.9 \ VOP_ATTRIB.9 \ + VOP_BMAP.9 \ VOP_BWRITE.9 \ VOP_CREATE.9 \ VOP_FSYNC.9 \ @@ -1880,7 +1881,8 @@ MLINKS+=sleep.9 msleep.9 \ sleep.9 tsleep.9 \ sleep.9 tsleep_sbt.9 \ sleep.9 wakeup.9 \ - sleep.9 wakeup_one.9 + sleep.9 wakeup_one.9 \ + sleep.9 wakeup_any.9 MLINKS+=sleepqueue.9 init_sleepqueues.9 \ sleepqueue.9 sleepq_abort.9 \ sleepqueue.9 sleepq_add.9 \ @@ -1996,6 +1998,7 @@ MLINKS+=sysctl.9 SYSCTL_DECL.9 \ sysctl.9 SYSCTL_ADD_S64.9 \ sysctl.9 SYSCTL_ADD_STRING.9 \ sysctl.9 SYSCTL_ADD_STRUCT.9 \ + sysctl.9 SYSCTL_ADD_TIMEVAL_SEC.9 \ sysctl.9 SYSCTL_ADD_U8.9 \ sysctl.9 SYSCTL_ADD_U16.9 \ sysctl.9 SYSCTL_ADD_U32.9 \ @@ -2011,6 +2014,7 @@ MLINKS+=sysctl.9 SYSCTL_DECL.9 \ sysctl.9 SYSCTL_INT.9 \ sysctl.9 SYSCTL_INT_WITH_LABEL.9 \ sysctl.9 SYSCTL_LONG.9 \ + sysctl.9 sysctl_msec_to_ticks.9 \ sysctl.9 SYSCTL_NODE.9 \ sysctl.9 SYSCTL_NODE_WITH_LABEL.9 \ sysctl.9 SYSCTL_OPAQUE.9 \ @@ -2023,6 +2027,7 @@ MLINKS+=sysctl.9 SYSCTL_DECL.9 \ sysctl.9 SYSCTL_S64.9 \ sysctl.9 SYSCTL_STRING.9 \ sysctl.9 SYSCTL_STRUCT.9 \ + sysctl.9 SYSCTL_TIMEVAL_SEC.9 \ sysctl.9 SYSCTL_U8.9 \ sysctl.9 SYSCTL_U16.9 \ sysctl.9 SYSCTL_U32.9 \ diff --git a/share/man/man9/VOP_BMAP.9 b/share/man/man9/VOP_BMAP.9 new file mode 100644 index 000000000000..ebb17a26226a --- /dev/null +++ b/share/man/man9/VOP_BMAP.9 @@ -0,0 +1,86 @@ +.\"- +.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD +.\" +.\" Copyright (c) 2019 The FreeBSD Foundation +.\" +.\" This software was developed by BFF Storage Systems, LLC 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 June 19, 2019 +.Dt VOP_BMAP 9 +.Os +.Sh NAME +.Nm VOP_BMAP +.Nd Logical to physical block number conversion +.Sh SYNOPSIS +.In sys/param.h +.In sys/vnode.h +.Ft int +.Fn VOP_BMAP "struct vnode *vp" "daddr_t bn" "struct bufobj **bop" "daddr_t *bnp" "int *runp" "int *runb" +.Sh DESCRIPTION +This vnode call is used to lookup the physical block number of the file system's +underlying device where a given logical block of a file is stored. +Its arguments are: +.Bl -tag -width type +.It Fa vp +The vnode of the file. +.It Fa bn +Logical block number within the file identified by +.Fa vp . +.It Fa bop +Return storage for the buffer object associated with the file system's +underlying device. +.It Fa bnp +Return storage for the physical block number. +.It Fa runp +Return storage for the number of succeeding logical blocks that may be +efficiently read at the same time as the requested block. +This will usually be the number of logical blocks whose physical blocks are +contiguously allocated. +However a file system is free to define "efficient" as it see fit. +.It Fa runb +Like +.Fa runp +but for preceding rather than succeeding blocks. +.El +.Pp +Any of the return arguments may be +.Dv NULL +to indicate that the caller does not care about that information. +.Sh LOCKS +The vnode will be locked on entry and should remain locked on return. +.Sh RETURN VALUES +Zero is returned on success, otherwise an error code is returned. +.Sh SEE ALSO +.Xr vnode 9 , +.Sh HISTORY +A +.Fn bmap +function first appeared in +.Bx 4.2 . +.Sh AUTHORS +This manual page was written by +.An Alan Somers . diff --git a/share/man/man9/fail.9 b/share/man/man9/fail.9 index cf623650e0c5..e093164edaca 100644 --- a/share/man/man9/fail.9 +++ b/share/man/man9/fail.9 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 2009 Isilon Inc http://www.isilon.com/ +.\" Copyright (c) 2009-2019 Dell EMC Isilon http://www.isilon.com/ .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -26,30 +26,36 @@ .\" .\" $FreeBSD$ .\" -.Dd March 15, 2016 +.Dd June 6, 2019 .Dt FAIL 9 .Os .Sh NAME +.Nm DEBUG_FP , .Nm KFAIL_POINT_CODE , .Nm KFAIL_POINT_CODE_FLAGS , .Nm KFAIL_POINT_CODE_COND , +.Nm KFAIL_POINT_ERROR , +.Nm KFAIL_POINT_EVAL , +.Nm KFAIL_POINT_DECLARE , +.Nm KFAIL_POINT_DEFINE , +.Nm KFAIL_POINT_GOTO , .Nm KFAIL_POINT_RETURN , .Nm KFAIL_POINT_RETURN_VOID , -.Nm KFAIL_POINT_ERROR , -.Nm KFAIL_POINT_GOTO , .Nm KFAIL_POINT_SLEEP_CALLBACKS , -.Nm fail_point , -.Nm DEBUG_FP +.Nm fail_point .Nd fail points .Sh SYNOPSIS .In sys/fail.h .Fn KFAIL_POINT_CODE "parent" "name" "code" .Fn KFAIL_POINT_CODE_FLAGS "parent" "name" "flags" "code" .Fn KFAIL_POINT_CODE_COND "parent" "name" "cond" "flags" "code" +.Fn KFAIL_POINT_ERROR "parent" "name" "error_var" +.Fn KFAIL_POINT_EVAL "name" "code" +.Fn KFAIL_POINT_DECLARE "name" +.Fn KFAIL_POINT_DEFINE "parent" "name" "flags" +.Fn KFAIL_POINT_GOTO "parent" "name" "error_var" "label" .Fn KFAIL_POINT_RETURN "parent" "name" .Fn KFAIL_POINT_RETURN_VOID "parent" "name" -.Fn KFAIL_POINT_ERROR "parent" "name" "error_var" -.Fn KFAIL_POINT_GOTO "parent" "name" "error_var" "label" .Fn KFAIL_POINT_SLEEP_CALLBACKS "parent" "name" "pre_func" "pre_arg" "post_func" "post_arg" "code" .Sh DESCRIPTION Fail points are used to add code points where errors may be injected @@ -140,6 +146,22 @@ is the equivalent of is the equivalent of .Sy KFAIL_POINT_CODE(..., { error_var = RETURN_VALUE; goto label;}) .El +.Pp +You can also introduce fail points by separating the declaration, +definition, and evaluation portions. +.Bl -inset +.It Fn KFAIL_POINT_DECLARE name +is used to declare the +.Sy fail_point +struct. +.It Fn KFAIL_POINT_DEFINE parent name flags +defines and initializes the +.Sy fail_point +and sets up its +.Xr sysctl 9 . +.It Fn KFAIL_POINT_EVAL name code +is used at the point that the fail point is executed. +.El .Sh SYSCTL VARIABLES The .Fn KFAIL_POINT_* diff --git a/share/man/man9/sleep.9 b/share/man/man9/sleep.9 index 82aa25d14931..05e281664e38 100644 --- a/share/man/man9/sleep.9 +++ b/share/man/man9/sleep.9 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 4, 2018 +.Dd June 19, 2019 .Dt SLEEP 9 .Os .Sh NAME @@ -38,7 +38,9 @@ .Nm pause_sbt , .Nm tsleep , .Nm tsleep_sbt , -.Nm wakeup +.Nm wakeup , +.Nm wakeup_one , +.Nm wakeup_any .Nd wait for events .Sh SYNOPSIS .In sys/param.h @@ -70,6 +72,8 @@ .Fn wakeup "void *chan" .Ft void .Fn wakeup_one "void *chan" +.Ft void +.Fn wakeup_any "void *chan" .Sh DESCRIPTION The functions .Fn tsleep , @@ -79,8 +83,9 @@ The functions .Fn pause_sig , .Fn pause_sbt , .Fn wakeup , +.Fn wakeup_one , and -.Fn wakeup_one +.Fn wakeup_any handle event-based thread blocking. If a thread must wait for an external event, it is put to sleep by @@ -252,9 +257,10 @@ function is a wrapper around .Fn tsleep that suspends execution of the current thread for the indicated timeout. The thread can not be awakened early by signals or calls to -.Fn wakeup +.Fn wakeup , +.Fn wakeup_one or -.Fn wakeup_one . +.Fn wakeup_any . The .Fn pause_sig function is a variant of @@ -263,8 +269,8 @@ which can be awakened early by signals. .Pp The .Fn wakeup_one -function makes the first thread in the queue that is sleeping on the -parameter +function makes the first highest priority thread in the queue that is +sleeping on the parameter .Fa chan runnable. This reduces the load when a large number of threads are sleeping on @@ -293,6 +299,16 @@ pay particular attention to ensure that no other threads wait on the same .Fa chan . .Pp +The +.Fn wakeup_any +function is similar to +.Fn wakeup_one , +except that it makes runnable last thread on the queue (sleeping less), +ignoring fairness. +It can be used when threads sleeping on the +.Fa chan +are known to be identical and there is no reason to be fair. +.Pp If the timeout given by .Fa timo or diff --git a/share/man/man9/sleepqueue.9 b/share/man/man9/sleepqueue.9 index 6d3b98009329..68c1e9b66e93 100644 --- a/share/man/man9/sleepqueue.9 +++ b/share/man/man9/sleepqueue.9 @@ -22,7 +22,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 22, 2014 +.Dd June 19, 2019 .Dt SLEEPQUEUE 9 .Os .Sh NAME @@ -290,7 +290,8 @@ and functions. The .Fn sleepq_signal -function awakens the highest priority thread sleeping on a wait channel while +function awakens the highest priority thread sleeping on a wait channel +(if SLEEPQ_UNFAIR flag is set, thread that went to sleep recently) while .Fn sleepq_broadcast awakens all of the threads sleeping on a wait channel. The diff --git a/share/man/man9/sysctl.9 b/share/man/man9/sysctl.9 index 277cef9d4980..eba6d53c0484 100644 --- a/share/man/man9/sysctl.9 +++ b/share/man/man9/sysctl.9 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 25, 2019 +.Dd June 11, 2019 .Dt SYSCTL 9 .Os .Sh NAME @@ -50,6 +50,7 @@ .Nm SYSCTL_ADD_STRING , .Nm SYSCTL_ADD_CONST_STRING , .Nm SYSCTL_ADD_STRUCT , +.Nm SYSCTL_ADD_TIMEVAL_SEC , .Nm SYSCTL_ADD_U8 , .Nm SYSCTL_ADD_U16 , .Nm SYSCTL_ADD_U32 , @@ -70,6 +71,7 @@ .Nm SYSCTL_INT , .Nm SYSCTL_INT_WITH_LABEL , .Nm SYSCTL_LONG , +.Nm sysctl_msec_to_ticks , .Nm SYSCTL_NODE , .Nm SYSCTL_NODE_WITH_LABEL , .Nm SYSCTL_OPAQUE , @@ -85,6 +87,7 @@ .Nm SYSCTL_STRING , .Nm SYSCTL_CONST_STRING , .Nm SYSCTL_STRUCT , +.Nm SYSCTL_TIMEVAL_SEC , .Nm SYSCTL_U8 , .Nm SYSCTL_U16 , .Nm SYSCTL_U32 , @@ -314,6 +317,16 @@ .Fa "const char *descr" .Fc .Ft struct sysctl_oid * +.Fo SYSCTL_ADD_TIMEVAL_SEC +.Fa "struct sysctl_ctx_list *ctx" +.Fa "struct sysctl_oid_list *parent" +.Fa "int number" +.Fa "const char *name" +.Fa "int ctlflags" +.Fa "struct timeval *ptr" +.Fa "const char *descr" +.Fc +.Ft struct sysctl_oid * .Fo SYSCTL_ADD_U8 .Fa "struct sysctl_ctx_list *ctx" .Fa "struct sysctl_oid_list *parent" @@ -442,6 +455,8 @@ .Fn SYSCTL_INT parent number name ctlflags ptr val descr .Fn SYSCTL_INT_WITH_LABEL parent number name ctlflags ptr val descr label .Fn SYSCTL_LONG parent number name ctlflags ptr val descr +.Ft int +.Fn sysctl_msec_to_ticks SYSCTL_HANDLER_ARGS .Fn SYSCTL_NODE parent number name ctlflags handler descr .Fn SYSCTL_NODE_WITH_LABEL parent number name ctlflags handler descr label .Fn SYSCTL_OPAQUE parent number name ctlflags ptr len format descr @@ -457,6 +472,7 @@ .Fn SYSCTL_STRING parent number name ctlflags arg len descr .Fn SYSCTL_CONST_STRING parent number name ctlflags arg descr .Fn SYSCTL_STRUCT parent number name ctlflags ptr struct_type descr +.Fn SYSCTL_TIMEVAL_SEC parent number name ctlflags ptr descr .Fn SYSCTL_U8 parent number name ctlflags ptr val descr .Fn SYSCTL_U16 parent number name ctlflags ptr val descr .Fn SYSCTL_U32 parent number name ctlflags ptr val descr @@ -466,6 +482,7 @@ .Fn SYSCTL_UQUAD parent number name ctlflags ptr val descr .Fn SYSCTL_UMA_MAX parent number name ctlflags ptr descr .Fn SYSCTL_UMA_CUR parent number name ctlflags ptr descr + .Sh DESCRIPTION The .Nm SYSCTL @@ -596,6 +613,70 @@ Labels should only be applied to siblings that are structurally similar and encode the same type of value, as aggregation is of no use otherwise. .El +.Sh NODE VALUE TYPES +Most of the macros and functions used to create sysctl nodes export a +read-only constant or in-kernel variable whose type matches the type +of the node's value. +For example, +.Fn SYSCTL_INT +reports the raw value of an associated variable of type +.Vt int . +However, nodes may also export a value that is a translatation of an internal +representation. +.Pp +The +.Fn sysctl_msec_to_ticks +handler can be used with +.Fn SYSCTL_PROC +or +.Fn SYSCTL_ADD_PROC +to export a millisecond time interval. +When using this handler, +the +.Fa arg2 +parameter points to an in-kernel variable of type +.Vt int +which stores a tick count suitable for use with functions like +.Xr tsleep 9 . +The +.Fn sysctl_msec_to_ticks +function converts this value to milliseconds when reporting the node's value. +Similarly, +.Fn sysctl_msec_to_ticks +accepts new values in milliseconds and stores an equivalent value in ticks to +.Fa *arg2 . +Note that new code should use kernel variables of type +.Vt sbintime_t +instead of tick counts. +.Pp +The +.Fn SYSCTL_ADD_SBINTIME_MSEC +and +.Fn SYSCTL_ADD_SBINTIME_USEC +functions and +.Fn SYSCTL_SBINTIME_MSEC +and +.Fn SYSCTL_SBINTIME_USEC +macros all create nodes which export an in-kernel variable of type +.Vt sbintime_t . +These nodes do not export the raw value of the associated variable. +Instead, they export a 64-bit integer containing a count of either +milliseconds (the MSEC variants) or microseconds (the USEC variants). +.Pp +The +.Fn SYSCTL_ADD_TIMEVAL_SEC +function and +.Fn SYSCTL_TIMEVAL_SEC +macro create nodes which export an in-kernel variable of type +.Vt struct timeval . +These nodes do not export full value of the associated structure. +Instead, they export a count in seconds as a simple integer which is +stored in the +.Fa tv_sec +field of the associated variable. +This function and macro are intended to be used with variables which +store a non-negative interval rather than an absolute time. +As a result, they reject attempts to store negative values. .Sh CREATING ROOT NODES Sysctl MIBs or OIDs are created in a hierarchical tree. The nodes at the bottom of the tree are called root nodes, and have no @@ -678,6 +759,7 @@ Static sysctls are declared using one of the .Fn SYSCTL_STRING , .Fn SYSCTL_CONST_STRING , .Fn SYSCTL_STRUCT , +.Fn SYSCTL_TIMEVAL_SEC , .Fn SYSCTL_U8 , .Fn SYSCTL_U16 , .Fn SYSCTL_U32 , @@ -711,6 +793,7 @@ Dynamic nodes are created using one of the .Fn SYSCTL_ADD_STRING , .Fn SYSCTL_ADD_CONST_STRING , .Fn SYSCTL_ADD_STRUCT , +.Fn SYSCTL_ADD_TIMEVAL_SEC , .Fn SYSCTL_ADD_U8 , .Fn SYSCTL_ADD_U16 , .Fn SYSCTL_ADD_U32 , diff --git a/share/misc/bsd-family-tree b/share/misc/bsd-family-tree index 5126797ec609..81741ca34446 100644 --- a/share/misc/bsd-family-tree +++ b/share/misc/bsd-family-tree @@ -64,14 +64,14 @@ Tenth Edition | | | | 4.4BSD-Encumbered | | | -NetBSD 0.8 | BSD/386 1.0 | / | | | -FreeBSD 1.0 <-----' NetBSD 0.9 | BSD/386 1.1 +FreeBSD 1.0 <-----' *--NetBSD 0.9 | BSD/386 1.1 | | .----- 4.4BSD Lite | -FreeBSD 1.1 | / / | \ | - | | / / | \ | -FreeBSD 1.1.5 .---|--------' / | \ | - | / | / | \ | -FreeBSD 1.1.5.1 / | / | \ | - | / NetBSD 1.0 <-' | \ | +FreeBSD 1.1 | / / | \ | + | | / | | \ | +FreeBSD 1.1.5 .---|--------' | | \ | + | / | | | \ | +FreeBSD 1.1.5.1 / | | | \ | + | / *--NetBSD 1.0 <-' | \ | | / | | \ | FreeBSD 2.0 <--' | | BSD/OS 2.0 | \ | | @@ -83,9 +83,9 @@ FreeBSD 2.0.5 \ | BSD/OS 2.0.1 | | | | OpenBSD 2.3 | | | | | | BSD/OS 3.0 | FreeBSD 2.1 | | | | - | | | | NetBSD 1.1 ------. BSD/OS 2.1 - | FreeBSD 2.1.5 | | | \ | - | | | | NetBSD 1.2 \ BSD/OS 3.0 + | | | | *--NetBSD 1.1 -. BSD/OS 2.1 + | FreeBSD 2.1.5 | | | \ | + | | | | *--NetBSD 1.2 \ BSD/OS 3.0 | FreeBSD 2.1.6 | | | \ OpenBSD 2.0 | | | | | | \ | | | FreeBSD 2.1.6.1 | | | \ | | @@ -103,7 +103,7 @@ FreeBSD 2.1 | | | | | | | | | | | | FreeBSD 2.2.5 | | | | | | | | | | OpenBSD 2.2 | - | | | | NetBSD 1.3 | | + | | | | *--NetBSD 1.3 | | | FreeBSD 2.2.6 | | | | | | | | | | | NetBSD 1.3.1 | BSD/OS 3.1 | | | | | | OpenBSD 2.3 | @@ -119,7 +119,7 @@ FreeBSD 3.0 <--------* | | v | | | | | NetBSD 1.3.3 | | *---FreeBSD 3.1 | | | | | | | | | BSD/OS 4.0.1 - | FreeBSD 3.2----* | NetBSD 1.4 OpenBSD 2.5 | + | FreeBSD 3.2----* | .--*--NetBSD 1.4 OpenBSD 2.5 | | | | | | | | | | | | | | | | | | | | | | | | | | | | @@ -142,7 +142,7 @@ FreeBSD 4.0 | | | | | NetBSD 1.4.2 | | | | Mac OS X | OpenBSD 2.8 BSD/OS 4.2 | | | | | | | | | | | | - | | 10.0 NetBSD 1.5 | | + | | 10.0 *--NetBSD 1.5 | | | FreeBSD 4.3 | | | | | | | | | | OpenBSD 2.9 | | | | | NetBSD 1.5.1 | | @@ -157,7 +157,7 @@ FreeBSD 4.0 | | | | | NetBSD 1.4.2 | | | FreeBSD 4.6.2 Mac OS X | | | | | 10.2 | | | | FreeBSD 4.7 | | | | - | | | NetBSD 1.6 OpenBSD 3.2 | + | | | *--NetBSD 1.6 OpenBSD 3.2 | | FreeBSD 4.8 | | | | | | | | | NetBSD 1.6.1 | | | |--------. | | | OpenBSD 3.3 BSD/OS 5.0 @@ -176,7 +176,7 @@ FreeBSD 4.0 | | | | | NetBSD 1.4.2 | | | | | | \ FreeBSD 5.0 | | | | | | | | | -FreeBSD 5.1 | | | DragonFly 1.0 +FreeBSD 5.1 | | | DragonFly 1.0 | \ | | | | | ----- Mac OS X | | | | 10.3 | | | @@ -186,7 +186,7 @@ FreeBSD 5.2 | | | | | | | | | *-------FreeBSD 5.3 | | | | | | | | OpenBSD 3.6 | - | | | NetBSD 2.0 | | + | | | *--NetBSD 2.0 | | | | | | | | | DragonFly 1.2.0 | | Mac OS X | | NetBSD 2.0.2 | | | | 10.4 | | | | | @@ -199,7 +199,7 @@ FreeBSD 5.2 | | | | | | | | | \ | | | | | | | NetBSD 2.1 | | | | | | | | | - | | | | NetBSD 3.0 | | + | | | | *--NetBSD 3.0 | | | | | | | | | | DragonFly 1.4.0 | | | | | | | OpenBSD 3.9 | | FreeBSD | | | | | | | @@ -217,7 +217,7 @@ FreeBSD 5.2 | | | | | | Mac OS X | | | | | 10.5 | | | | | | | OpenBSD 4.2 | - | | | NetBSD 4.0 | | + | | | *--NetBSD 4.0 | | | FreeBSD 6.3 | | | | | | \ | | | | | *--FreeBSD | | | | | DragonFly 1.12.0 @@ -229,104 +229,112 @@ FreeBSD 5.2 | | | | | | | | | | | FreeBSD 7.1 | | | | | | | | | DragonFly 2.2.0 - | FreeBSD 7.2 | NetBSD 5.0 OpenBSD 4.5 | - | \ | | | \ | | - | | Mac OS X | | \ | | - | | 10.6 | | \ | | - | | | | | NetBSD | DragonFly 2.4.0 - | | | | | 5.0.1 OpenBSD 4.6 | - | | | | | | | | - *--FreeBSD | | | | | | | - | 8.0 | | | | | | | - | | FreeBSD | | | NetBSD | | - | | 7.3 | | | 5.0.2 | DragonFly 2.6.0 - | | | | | | OpenBSD 4.7 | - | FreeBSD | | | | | | - | 8.1 | | | | | | - | | | | | | | DragonFly 2.8.2 - | | | | | | OpenBSD 4.8 | - | | | | | *--NetBSD | | - | FreeBSD FreeBSD | | | 5.1 | | - | 8.2 7.4 | | | | | DragonFly 2.10.1 - | | | | | | OpenBSD 4.9 | - | `-----. Mac OS X | | | | | - | \ 10.7 | | | | | - | | | | | | OpenBSD 5.0 | - *--FreeBSD | | | | | | | - | 9.0 | | | | NetBSD | DragonFly 3.0.1 - | | FreeBSD | | | 5.1.2 | | - | | 8.3 | | | | | | - | | | | | | NetBSD | | - | | | | | | 5.1.3 | | - | | | | | | | | | - | | | | | | NetBSD | | - | | | | | | 5.1.4 | | - | | | | | | OpenBSD 5.1 | - | | | Mac OS X | `----. | | - | | | 10.8 | \ | | - | | | | NetBSD 6.0 | | | - | | | | | | | | OpenBSD 5.2 DragonFly 3.2.1 - | FreeBSD | | | | | NetBSD | | - | 9.1 | | | | | 5.2 | | - | | | | | | | | | | - | | | | | | | NetBSD | | - | | | | | | | 5.2.1 | | - | | | | | | | | | | - | | | | | | | NetBSD | | - | | | | | | | 5.2.2 | | - | | | | | | | | | - | | | | | | \ | | - | | | | | | NetBSD | | - | | | | | | 6.0.1 | | - | | | | | | | OpenBSD 5.3 DragonFly 3.4.1 - | | | | | | NetBSD | | - | | | | | | 6.0.2 | | - | | | | | | | | | - | | | | | | NetBSD | | - | | | | | | 6.0.3 | | - | | | | | | | | | - | | | | | | NetBSD | | - | | | | | | 6.0.4 | | - | | | | | | | | | - | | | | | | NetBSD | | - | | | | | | 6.0.5 | | - | | | | | | | | | - | | | | | | NetBSD | | - | | | | | | 6.0.6 | | - | | | | | | | | - | | | | | |`-NetBSD 6.1 | | - | | FreeBSD | | | | | - | | 8.4 | | NetBSD 6.1.1 | | - | | | | | | | - | FreeBSD | | NetBSD 6.1.2 | | - | 9.2 Mac OS X | | | | - | | 10.9 | | OpenBSD 5.4 | - | `-----. | | | | DragonFly 3.6.0 - | \ | | | | | - *--FreeBSD | | | NetBSD 6.1.3 | | - | 10.0 | | | | | | - | | | | | | | DragonFly 3.6.1 - | | | | | | | | - | | | | | | | | - | | | | | | | DragonFly 3.6.2 - | | | | | NetBSD 6.1.4 | | - | | | | | | | | - | | | | | | OpenBSD 5.5 | - | | | | | | | | - | | | | | | | DragonFly 3.8.0 - | | | | | | | | - | | | | | | | | - | | | | | | | DragonFly 3.8.1 - | | | | | | | | - | | | | | | | | - | | | | | | | DragonFly 3.6.3 - | | | | | | | | - | | FreeBSD | | | | | - | | 9.3 | | | | | - | | | | NetBSD 6.1.5 | DragonFly 3.8.2 + | FreeBSD 7.2 | *--NetBSD OpenBSD 4.5 | + | \ | | 5.0 | | + | \ | | / | \ | | + | | Mac OS X | | | \ | | + | | 10.6 | | | \ | | + | | | | | | NetBSD | DragonFly 2.4.0 + | | | | | | 5.0.1 OpenBSD 4.6 | + | | | | | | | | | + *--FreeBSD | | | | | | | | + | 8.0 | | | | | | | | + | | FreeBSD | | | | NetBSD | | + | | 7.3 | | | | 5.0.2 | DragonFly 2.6.0 + | | | | | | | OpenBSD 4.7 | + | FreeBSD | | | | | | | + | 8.1 | | | | | | | + | | | | | | | | DragonFly 2.8.2 + | | | | | | | OpenBSD 4.8 | + | | | | | | *--NetBSD | | + | FreeBSD FreeBSD | | | 5.1 | | + | 8.2 7.4 | | | | | DragonFly 2.10.1 + | | | | | | OpenBSD 4.9 | + | `-----. Mac OS X | | | | | + | \ 10.7 | | | | | + | | | | | | OpenBSD 5.0 | + *--FreeBSD | | | | | | | + | 9.0 | | | | NetBSD | DragonFly 3.0.1 + | | FreeBSD | | | 5.1.2 | | + | | 8.3 | | | | | | + | | | | | | NetBSD | | + | | | | | | 5.1.3 | | + | | | | | | | | | + | | | | | | NetBSD | | + | | | | | | 5.1.4 | | + | | | | | | OpenBSD 5.1 | + | | | Mac OS X | `--------. | | + | | | 10.8 | | | | + | | | | *--NetBSD | | | + | | | | | 6.0 | | | + | | | | | | | | OpenBSD 5.2 DragonFly 3.2.1 + | FreeBSD | | | | | NetBSD | | + | 9.1 | | | | | 5.2 | | + | | | | | | | | | | + | | | | | | | NetBSD | | + | | | | | | | 5.2.1 | | + | | | | | | | | | | + | | | | | | | NetBSD | | + | | | | | | | 5.2.2 | | + | | | | | | | | | + | | | | | | \ | | + | | | | | | NetBSD | | + | | | | | | 6.0.1 | | + | | | | | | | OpenBSD 5.3 DragonFly 3.4.1 + | | | | | | NetBSD | | + | | | | | | 6.0.2 | | + | | | | | | | | | + | | | | | | NetBSD | | + | | | | | | 6.0.3 | | + | | | | | | | | | + | | | | | | NetBSD | | + | | | | | | 6.0.4 | | + | | | | | | | | | + | | | | | | NetBSD | | + | | | | | | 6.0.5 | | + | | | | | | | | | + | | | | | | NetBSD | | + | | | | | | 6.0.6 | | + | | | | | | | | + | | | | | *--NetBSD | | + | | | | | 6.1 | | + | | FreeBSD | | | | | + | | 8.4 | | NetBSD | | + | | | | | 6.1.1 | | + | | | | | | | + | FreeBSD | | NetBSD | | + | 9.2 | | 6.1.2 | | + | | Mac OS X | | | | + | | 10.9 | | OpenBSD 5.4 | + | `-----. | | | | DragonFly 3.6.0 + | \ | | | | | + *--FreeBSD | | | NetBSD | | + | 10.0 | | | 6.1.3 | | + | | | | | | | | + | | | | | | | DragonFly 3.6.1 + | | | | | | | | + | | | | | | | | + | | | | | | | DragonFly 3.6.2 + | | | | | NetBSD | | + | | | | | 6.1.4 | | + | | | | | | | | + | | | | | | OpenBSD 5.5 | + | | | | | | | | + | | | | | | | DragonFly 3.8.0 + | | | | | | | | + | | | | | | | | + | | | | | | | DragonFly 3.8.1 + | | | | | | | | + | | | | | | | | + | | | | | | | DragonFly 3.6.3 + | | | | | | | | + | | FreeBSD | | | | | + | | 9.3 | | | | | + | | | | NetBSD | DragonFly 3.8.2 + | | | | 6.1.5 | | | | Mac OS X | | | | | 10.10 | | | - | | | | OpenBSD 5.6 | + | | | | OpenBSD 5.6 | | FreeBSD | | | | | 10.1 | | | DragonFly 4.0.1 | | | | | | @@ -338,52 +346,62 @@ FreeBSD 5.2 | | | | | | | | | | | | | | | DragonFly 4.0.5 | | | | | | - | | | | OpenBSD 5.7 | + | | | | OpenBSD 5.7 | | | | | | DragonFly 4.2.0 | FreeBSD | | | | | 10.2 | | | | - | | macOS NetBSD 7.0 | | - | | 10.11 | | | OpenBSD 5.8 | - | | | | | `--. | DragonFly 4.4.1 - | FreeBSD | | | | OpenBSD 5.9 | - | 10.3 | | | | | | - | | | | | NetBSD 7.0.1 | | - | `------. | | | | | DragonFly 4.6.0 - | | | | | | | | - | | | | | | | | - *--FreeBSD | macOS | | | OpenBSD 6.0 | - | 11.0 | 10.12 | | NetBSD 7.0.2 | | - | | | | | | | | - | | | | | *- NetBSD 7.1 | | - | | | | | | | | - | | | | | | | | - | | | macOS | | | DragonFly 4.8.0 - | | | 10.13 | | OpenBSD 6.1 | - | FreeBSD | | | | | DragonFly 5.0.0 - | 11.1 FreeBSD | | | | | - | | 10.4 | | | OpenBSD 6.2 DragonFly 5.0.1 - | | | | | | | - | `------. | | NetBSD 7.1.1 | DragonFly 5.0.2 - | | | | | | | - | | | | NetBSD 7.1.2 | | - | | | | | | | - | | | | | OpenBSD 6.3 | - | | | NetBSD | | DragonFly 5.2.0 - | | | 8.0 | | | - | | | | | | DragonFly 5.2.1 - | | | | | | | - | | | | | | DragonFly 5.2.2 - | FreeBSD | | NetBSD 7.2 | | - | 11.2 macOS | | | | - | 10.14 | | OpenBSD 6.4 | - | | | | | DragonFly 5.4.0 - *--FreeBSD | | v | | - | 12.0 | | | DragonFly 5.4.1 - | | | OpenBSD 6.5 | - | | | | | -FreeBSD 13 -current | NetBSD -current OpenBSD -current DragonFly -current - | | | | | - v v v v v + | | macOS *--NetBSD 7.0 | | + | | 10.11 | | | OpenBSD 5.8 | + | | | | | `--. | DragonFly 4.4.1 + | FreeBSD | | | | OpenBSD 5.9 | + | 10.3 | | | | | | + | | | | | NetBSD | | + | | | | | 7.0.1 | | + | `------. | | | | | DragonFly 4.6.0 + | | | | | | | | + | | | | | | | | + *--FreeBSD | macOS | | | OpenBSD 6.0 | + | 11.0 | 10.12 | | NetBSD | | + | | | | | | 7.0.2 | | + | | | | | | | | + | | | | | *--NetBSD | | + | | | | | | 7.1 | | + | | | | | | | | | + | | | | | | | | | + | | | macOS | | | | DragonFly 4.8.0 + | | | 10.13 | | | OpenBSD 6.1 | + | FreeBSD | | | | | | DragonFly 5.0.0 + | 11.1 FreeBSD | | | | | | + | | 10.4 | | | | OpenBSD 6.2 DragonFly 5.0.1 + | | | | | | | | + | `------. | | | NetBSD | DragonFly 5.0.2 + | | | | | 7.1.1 | | + | | | | | | | | + | | | | | NetBSD | | + | | | | | 7.1.2 `--. | + | | | | | | | + | | | | `-----. OpenBSD 6.3 | + | | | *--NetBSD | | DragonFly 5.2.0 + | | | | 8.0 | | | + | | | | | | | DragonFly 5.2.1 + | | | | | | | | + | | | | | | | DragonFly 5.2.2 + | FreeBSD | | | *--NetBSD | | + | 11.2 | | | 7.2 | | + | macOS | | | | | + | 10.14 | | | OpenBSD 6.4 | + | | | | | | | + | | | | | | DragonFly 5.4.0 + *--FreeBSD | | | v | | + | 12.0 | | | | DragonFly 5.4.1 + | | | | OpenBSD 6.5 | + | | | | | | + | | | NetBSD | | + | | | 8.1 | DragonFly 5.6 + | | | | | +FreeBSD 13 -current | NetBSD -current OpenBSD -current DragonFly -current + | | | | | + v v v v v Time ---------------- @@ -762,7 +780,9 @@ OpenBSD 6.4 2018-10-18 [OBD] DragonFly 5.4.0 2018-12-03 [DFB] FreeBSD 12.0 2018-12-11 [FBD] DragonFly 5.4.1 2018-12-24 [DFB] -OpenBSD 6.5 2019-05-01 [OBD] +OpenBSD 6.5 2019-05-01 [OBD] +NetBSD 8.1 2019-06-04 [NBD] +DragonFly 5.6 2019-06-17 [DFB] Bibliography ------------------------ diff --git a/share/mk/bsd.README b/share/mk/bsd.README index c4db43ea5699..ef93c55f73fc 100644 --- a/share/mk/bsd.README +++ b/share/mk/bsd.README @@ -125,10 +125,16 @@ The following variables are common: AFLAGS.${SRC} Flags dependent on source file name. +AFLAGS.${TARGET} + Flags dependent on output file name. ACFLAGS.${SRC} Flags dependent on source file name. +ACFLAGS.${TARGET} + Flags dependent on output file name. CFLAGS.${SRC} Flags dependent on source file name. +CFLAGS.${TARGET} + Flags dependent on output file name. CFLAGS.${COMPILER_TYPE} Flags dependent on compiler added to CFLAGS. CFLAGS.${MACHINE_ARCH} @@ -142,6 +148,8 @@ CXXFLAGS.${MACHINE_ARCH} Architectural flags added to CXXFLAGS. CXXFLAGS.${SRC} Flags dependent on source file name. +CXXFLAGS.${TARGET} + Flags dependent on output file name. COMPILER_FEATURES A list of features that the compiler supports. Zero or more of: @@ -336,14 +344,23 @@ LDADD Additional loader objects. Usually used for libraries. LDADD=-lutil -lcompat +LDADD.${TAREGT} + Loader objects dependent on output file name. + LDFLAGS Additional loader flags. Passed to the loader via CC, since that's used to link programs as well, so loader specific flags need to be prefixed with -Wl, to work. +LDFLAGS.${TARGET} + Flags dependent on output file name. + LIBADD Additional libraries. This is for base system libraries and is only valid inside of the /usr/src tree. Use LIBADD=name instead of LDADD=-lname. +LIBADD.${TARGET} + Libraries dependent on output file name. + LINKS The list of binary links; should be full pathnames, the linked-to file coming first, followed by the linked file. The files are hard-linked. For example, to link diff --git a/share/mk/bsd.dep.mk b/share/mk/bsd.dep.mk index 5d0aac91f1b4..095047e7e7b0 100644 --- a/share/mk/bsd.dep.mk +++ b/share/mk/bsd.dep.mk @@ -173,7 +173,7 @@ ${_D}.nossppico: ${_DSRC} ${SOBJS:S/^${_D}.nossppico$//} .endif .endfor .endfor - +.endif # defined(SRCS) .if ${MAKE_VERSION} < 20160220 DEPEND_MP?= -MP @@ -181,12 +181,18 @@ DEPEND_MP?= -MP # Handle OBJS=../somefile.o hacks. Just replace '/' rather than use :T to # avoid collisions. DEPEND_FILTER= C,/,_,g +.if !empty(OBJS) +DEPENDOBJS+= ${OBJS} +.else DEPENDSRCS+= ${SRCS:M*.[cSC]} ${SRCS:M*.cxx} ${SRCS:M*.cpp} ${SRCS:M*.cc} DEPENDSRCS+= ${DPSRCS:M*.[cSC]} ${SRCS:M*.cxx} ${SRCS:M*.cpp} ${SRCS:M*.cc} .if !empty(DEPENDSRCS) DEPENDOBJS+= ${DEPENDSRCS:${OBJS_SRCS_FILTER:ts:}:S,$,.o,} .endif +.endif # !empty(OBJS) +.if !empty(DEPENDOBJS) DEPENDFILES+= ${DEPENDOBJS:O:u:${DEPEND_FILTER}:C/^/${DEPENDFILE}./} +.endif .if defined(_SKIP_DEPEND) # Don't bother statting any .meta files for .depend* ${DEPENDOBJS}: .NOMETA @@ -213,7 +219,6 @@ CFLAGS+= ${${DEPEND_CFLAGS_CONDITION}:?${DEPEND_CFLAGS}:} .endif .endfor .endif # !defined(_meta_filemon) -.endif # defined(SRCS) .if ${MK_DIRDEPS_BUILD} == "yes" && ${.MAKE.DEPENDFILE} != "/dev/null" # Prevent meta.autodep.mk from tracking "local dependencies". @@ -251,18 +256,19 @@ _depfile= ${.OBJDIR}/${_meta_obj} .else _depfile= ${.OBJDIR}/${_dep_obj} .endif -.if !exists(${_depfile}) +.if !exists(${_depfile}) || defined(_meta_filemon) +# - Headers are normally built in beforebuild when included in DPSRCS or SRCS. +# So we don't need it as a guessed dependency (it may lead to cyclic problems +# if custom rules are defined). The only time this causes a problem is when +# 'make foo.o' is ran. +# - For meta mode we still need to know which file to depend on to avoid +# ambiguous suffix transformation rules from .PATH. Meta mode does not +# use .depend files when filemon is in use. +.if !target(${__obj}) ${__obj}: ${OBJS_DEPEND_GUESS} +.endif ${__obj}: ${OBJS_DEPEND_GUESS.${__obj}} -.elif defined(_meta_filemon) -# For meta mode we still need to know which file to depend on to avoid -# ambiguous suffix transformation rules from .PATH. Meta mode does not -# use .depend files. We really only need source files, not headers since -# they are typically in SRCS/beforebuild already. For target-specific -# guesses do include headers though since they may not be in SRCS. -${__obj}: ${OBJS_DEPEND_GUESS:N*.h} -${__obj}: ${OBJS_DEPEND_GUESS.${__obj}} -.endif # !exists(${_depfile}) +.endif # !exists(${_depfile}) || defined(_meta_filemon) .endfor # Always run 'make depend' to generate dependencies early and to avoid the diff --git a/share/mk/bsd.progs.mk b/share/mk/bsd.progs.mk index 1624a23b8542..636e93f28c66 100644 --- a/share/mk/bsd.progs.mk +++ b/share/mk/bsd.progs.mk @@ -95,7 +95,7 @@ $v = # Find common sources among the PROGS to depend on them before building # anything. This allows parallelization without them each fighting over # the same objects. -_PROGS_COMMON_SRCS= +_PROGS_COMMON_SRCS= ${DPSRCS} _PROGS_ALL_SRCS= .for p in ${PROGS} .for s in ${SRCS.${p}} diff --git a/share/mk/bsd.suffixes.mk b/share/mk/bsd.suffixes.mk index 0fefb1179c2c..5396bae05087 100644 --- a/share/mk/bsd.suffixes.mk +++ b/share/mk/bsd.suffixes.mk @@ -19,7 +19,7 @@ ${CC} -emit-llvm ${IR_CFLAGS} -S ${.IMPSRC} -o ${.TARGET} .cc .cpp .cxx .C: - ${CXX} ${CXXFLAGS} ${LDFLAGS} ${.IMPSRC} ${LDLIBS} -o ${.TARGET} + ${CXX:N${CCACHE_BIN}} ${CXXFLAGS} ${LDFLAGS} ${.IMPSRC} ${LDLIBS} -o ${.TARGET} .cc.o .cpp.o .cxx.o .C.o: ${CXX} ${STATIC_CXXFLAGS} ${CXXFLAGS} -c ${.IMPSRC} -o ${.TARGET} diff --git a/share/mk/bsd.sys.mk b/share/mk/bsd.sys.mk index 00146a138fbd..5adef37c347c 100644 --- a/share/mk/bsd.sys.mk +++ b/share/mk/bsd.sys.mk @@ -240,12 +240,28 @@ CFLAGS+= ${CFLAGS.${COMPILER_TYPE}} CXXFLAGS+= ${CXXFLAGS.${COMPILER_TYPE}} AFLAGS+= ${AFLAGS.${.IMPSRC:T}} +AFLAGS+= ${AFLAGS.${.TARGET:T}} ACFLAGS+= ${ACFLAGS.${.IMPSRC:T}} +ACFLAGS+= ${ACFLAGS.${.TARGET:T}} CFLAGS+= ${CFLAGS.${.IMPSRC:T}} CXXFLAGS+= ${CXXFLAGS.${.IMPSRC:T}} LDFLAGS+= ${LDFLAGS.${LINKER_TYPE}} +# Only allow .TARGET when not using PROGS as it has the same syntax +# per PROG which is ambiguous with this syntax. This is only needed +# for PROG_VARS vars. +.if !defined(_RECURSING_PROGS) +.if ${MK_WARNS} != "no" +CFLAGS+= ${CWARNFLAGS.${.TARGET:T}} +.endif +CFLAGS+= ${CFLAGS.${.TARGET:T}} +CXXFLAGS+= ${CXXFLAGS.${.TARGET:T}} +LDFLAGS+= ${LDFLAGS.${.TARGET:T}} +LDADD+= ${LDADD.${.TARGET:T}} +LIBADD+= ${LIBADD.${.TARGET:T}} +.endif + .if defined(SRCTOP) # Prevent rebuilding during install to support read-only objdirs. .if ${.TARGETS:M*install*} == ${.TARGETS} && empty(.MAKE.MODE:Mmeta) diff --git a/share/mk/local.sys.mk b/share/mk/local.sys.mk index e3bfd572f411..a4b7b0561f15 100644 --- a/share/mk/local.sys.mk +++ b/share/mk/local.sys.mk @@ -33,6 +33,11 @@ MAKE_PRINT_VAR_ON_ERROR+= \ OBJTOP \ ${MAKE_PRINT_VAR_ON_ERROR_XTRAS} +# Meta mode may rebuild targets that then fail. The next build won't detect +# the meta mode change. Not all targets have a 'rm ${.TARGET}' in them +# so force it. +.DELETE_ON_ERROR: + .if ${.MAKE.LEVEL} > 0 MAKE_PRINT_VAR_ON_ERROR += .MAKE.MAKEFILES .PATH .endif diff --git a/share/syscons/scrnmaps/Makefile b/share/syscons/scrnmaps/Makefile index c8d3db54dcb3..0f11c777fa02 100644 --- a/share/syscons/scrnmaps/Makefile +++ b/share/syscons/scrnmaps/Makefile @@ -12,6 +12,7 @@ CLEANFILES+= ${SCRMAPS_MK} ${SCRMAPS} FILES= ${SCRMAPS} FILESDIR= ${SHAREDIR}/syscons/scrnmaps +DEPENDOBJS+= ${SCRMAPS_MK} build-tools: ${SCRMAPS_MK} ${SCRMAPS}: ${.TARGET:R}.mk diff --git a/share/timedef/Makefile b/share/timedef/Makefile index 345a1eb6ac6c..da2080821ba7 100644 --- a/share/timedef/Makefile +++ b/share/timedef/Makefile @@ -129,6 +129,7 @@ LOCALES+= zh_CN.GBK LOCALES+= zh_CN.UTF-8 LOCALES+= zh_CN.eucCN LOCALES+= zh_HK.UTF-8 +LOCALES+= zh_TW.Big5 LOCALES+= zh_TW.UTF-8 diff --git a/share/timedef/zh_TW.Big5.src b/share/timedef/zh_TW.Big5.src new file mode 100644 index 000000000000..2930f5ffc9d6 --- /dev/null +++ b/share/timedef/zh_TW.Big5.src @@ -0,0 +1,87 @@ +# Warning: Do not edit. This file is automatically generated from the +# tools in /usr/src/tools/tools/locale. The data is obtained from the +# CLDR project, obtained from http://cldr.unicode.org/ +# ----------------------------------------------------------------------------- +# +# Short month names +¡@¢°¤ë +¡@¢±¤ë +¡@¢²¤ë +¡@¢³¤ë +¡@¢´¤ë +¡@¢µ¤ë +¡@¢¶¤ë +¡@¢·¤ë +¡@¢¸¤ë +¢°¢¯¤ë +¢°¢°¤ë +¢°¢±¤ë +# +# Long month names (as in a date) +1¤ë +2¤ë +3¤ë +4¤ë +5¤ë +6¤ë +7¤ë +8¤ë +9¤ë +10¤ë +11¤ë +12¤ë +# +# Short weekday names +¶g¤é +¶g¤@ +¶g¤G +¶g¤T +¶g¥| +¶g¤­ +¶g¤» +# +# Long weekday names +¬P´Á¤é +¬P´Á¤@ +¬P´Á¤G +¬P´Á¤T +¬P´Á¥| +¬P´Á¤­ +¬P´Á¤» +# +# X_fmt +%H®É%M¤À%S¬í +# +# x_fmt +%Y/%m/%d +# +# c_fmt +%a %b/%e %T %Y +# +# AM/PM +¤W¤È +¤U¤È +# +# date_fmt +%Y¦~%_m¤ë%e¤é %A %X %Z +# +# Long month names (without case ending) +1¤ë +2¤ë +3¤ë +4¤ë +5¤ë +6¤ë +7¤ë +8¤ë +9¤ë +10¤ë +11¤ë +12¤ë +# +# md_order +md +# +# ampm_fmt +%I:%M:%S %p +# EOF diff --git a/share/vt/fonts/Makefile b/share/vt/fonts/Makefile index 685f0f5ae2bd..94f5e35ed124 100644 --- a/share/vt/fonts/Makefile +++ b/share/vt/fonts/Makefile @@ -13,8 +13,8 @@ FILES= ${FONTS} INDEX.fonts CLEANFILES+= ${FONTS} -.SUFFIXES: .fnt .fnt.uu .hex -.hex.fnt: +.SUFFIXES: .bdf .fnt .fnt.uu .hex +.bdf.fnt .hex.fnt: vtfontcvt ${.IMPSRC} ${.TARGET} FILESDIR= ${SHAREDIR}/vt/fonts diff --git a/stand/common/disk.c b/stand/common/disk.c index 8a08a84f3bad..733b7b0d57e7 100644 --- a/stand/common/disk.c +++ b/stand/common/disk.c @@ -263,8 +263,8 @@ disk_open(struct disk_devdesc *dev, uint64_t mediasize, u_int sectorsize) slice = dev->d_slice; partition = dev->d_partition; - DPRINTF("%s unit %d, slice %d, partition %d => %p", - disk_fmtdev(dev), dev->dd.d_unit, dev->d_slice, dev->d_partition, od); + DPRINTF("%s unit %d, slice %d, partition %d => %p", disk_fmtdev(dev), + dev->dd.d_unit, dev->d_slice, dev->d_partition, od); /* Determine disk layout. */ od->table = ptable_open(&partdev, mediasize / sectorsize, sectorsize, @@ -309,17 +309,25 @@ disk_open(struct disk_devdesc *dev, uint64_t mediasize, u_int sectorsize) } else if (partition == D_PARTISGPT) { /* * When we try to open GPT partition, but partition - * table isn't GPT, reset d_partition value to -1 - * and try to autodetect appropriate value. + * table isn't GPT, reset partition value to + * D_PARTWILD and try to autodetect appropriate value. */ - partition = -1; + partition = D_PARTWILD; } + /* - * If d_partition < 0 and we are looking at a BSD slice, + * If partition is D_PARTNONE, then disk_open() was called + * to open raw MBR slice. + */ + if (partition == D_PARTNONE) + goto out; + + /* + * If partition is D_PARTWILD and we are looking at a BSD slice, * then try to read BSD label, otherwise return the * whole MBR slice. */ - if (partition == -1 && + if (partition == D_PARTWILD && part.type != PART_FREEBSD) goto out; /* Try to read BSD label */ @@ -331,7 +339,7 @@ disk_open(struct disk_devdesc *dev, uint64_t mediasize, u_int sectorsize) goto out; } /* - * If slice contains BSD label and d_partition < 0, then + * If slice contains BSD label and partition < 0, then * assume the 'a' partition. Otherwise just return the * whole MBR slice, because it can contain ZFS. */ diff --git a/stand/efi/Makefile b/stand/efi/Makefile index 0772609a7255..2e0daba6dab8 100644 --- a/stand/efi/Makefile +++ b/stand/efi/Makefile @@ -9,7 +9,7 @@ NO_OBJ=t .if ${COMPILER_TYPE} != "gcc" || ${COMPILER_VERSION} >= 40500 SUBDIR.${MK_FDT}+= fdt -SUBDIR.yes+= libefi boot1 +SUBDIR.yes+= libefi boot1 gptboot SUBDIR.${MK_FORTH}+= loader_4th SUBDIR.${MK_LOADER_LUA}+= loader_lua SUBDIR.yes+= loader_simp diff --git a/stand/efi/boot1/Makefile b/stand/efi/boot1/Makefile index 97594017f766..d9d46673250a 100644 --- a/stand/efi/boot1/Makefile +++ b/stand/efi/boot1/Makefile @@ -5,7 +5,7 @@ BOOT1?= boot1 PROG= ${BOOT1}.sym INTERNALPROG= -WARNS?= 6 +WARNS= 6 CFLAGS+= -DEFI_BOOT1 # We implement a slightly non-standard %S in that it always takes a @@ -13,9 +13,11 @@ CFLAGS+= -DEFI_BOOT1 # seems to matter on arm64 where wchar_t defaults to an int instead # of a short. There's no good cast to use here so just ignore the # warnings for now. +CWARNFLAGS.proto.c+= -Wno-format CWARNFLAGS.boot1.c+= -Wno-format # Disable bogus alignment issues +CWARNFLAGS.ufs_module.c += -Wno-format CWARNFLAGS.ufs_module.c += -Wno-cast-align # Disable warnings that are currently incompatible with the zfs boot code @@ -28,7 +30,7 @@ CWARNFLAGS.zfs_module.c += -Wno-unused-parameter CWARNFLAGS.zfs_module.c += -Wno-unused-function # architecture-specific loader code -SRCS+= boot1.c self_reloc.c start.S ufs_module.c devpath.c +SRCS+= boot1.c proto.c self_reloc.c start.S ufs_module.c devpath.c .if ${MK_LOADER_ZFS} != "no" SRCS+= zfs_module.c CFLAGS.zfs_module.c+= -I${ZFSSRC} @@ -56,9 +58,10 @@ CFLAGS+= -DEFI_DEBUG .PATH: ${EFISRC}/libefi CFLAGS+= -I${LDRSRC} -.ifndef(NOFAT) -FILES= ${BOOT1}.efi ${BOOT1}.efifat +FILES= ${BOOT1}.efi FILESMODE_${BOOT1}.efi= ${BINMODE} +.ifndef(NOFAT) +FILES+= ${BOOT1}.efifat .endif LDSCRIPT= ${EFISRC}/loader/arch/${MACHINE}/ldscript.${MACHINE} diff --git a/stand/efi/boot1/boot1.c b/stand/efi/boot1/boot1.c index ec387c50e7db..cbdd3bb31fc7 100644 --- a/stand/efi/boot1/boot1.c +++ b/stand/efi/boot1/boot1.c @@ -33,10 +33,11 @@ __FBSDID("$FreeBSD$"); #include "boot_module.h" #include "paths.h" +#include "proto.h" static void efi_panic(EFI_STATUS s, const char *fmt, ...) __dead2 __printflike(2, 3); -static const boot_module_t *boot_modules[] = +const boot_module_t *boot_modules[] = { #ifdef EFI_ZFS_BOOT &zfs_module, @@ -45,8 +46,7 @@ static const boot_module_t *boot_modules[] = &ufs_module #endif }; - -#define NUM_BOOT_MODULES nitems(boot_modules) +const UINTN num_boot_modules = nitems(boot_modules); static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL; static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL; @@ -90,67 +90,20 @@ Calloc(size_t n1, size_t n2, const char *file, int line) return (res); } -/* - * load_loader attempts to load the loader image data. - * - * It tries each module and its respective devices, identified by mod->probe, - * in order until a successful load occurs at which point it returns EFI_SUCCESS - * and EFI_NOT_FOUND otherwise. - * - * Only devices which have preferred matching the preferred parameter are tried. - */ -static EFI_STATUS -load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp, - size_t *bufsize, BOOLEAN preferred) -{ - UINTN i; - dev_info_t *dev; - const boot_module_t *mod; - - for (i = 0; i < NUM_BOOT_MODULES; i++) { - mod = boot_modules[i]; - for (dev = mod->devices(); dev != NULL; dev = dev->next) { - if (dev->preferred != preferred) - continue; - - if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) == - EFI_SUCCESS) { - *devinfop = dev; - *modp = mod; - return (EFI_SUCCESS); - } - } - } - - return (EFI_NOT_FOUND); -} - /* * try_boot only returns if it fails to load the loader. If it succeeds * it simply boots, otherwise it returns the status of last EFI call. */ -static EFI_STATUS -try_boot(void) +EFI_STATUS +try_boot(const boot_module_t *mod, dev_info_t *dev, void *loaderbuf, size_t loadersize) { - size_t bufsize, loadersize, cmdsize; - void *buf, *loaderbuf; + size_t bufsize, cmdsize; + void *buf; char *cmd; - dev_info_t *dev; - const boot_module_t *mod; EFI_HANDLE loaderhandle; EFI_LOADED_IMAGE *loaded_image; EFI_STATUS status; - status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE); - if (status != EFI_SUCCESS) { - status = load_loader(&mod, &dev, &loaderbuf, &loadersize, - FALSE); - if (status != EFI_SUCCESS) { - printf("Failed to load '%s'\n", PATH_LOADER_EFI); - return (status); - } - } - /* * Read in and parse the command line from /boot.config or /boot/config, * if present. We'll pass it the next stage via a simple ASCII @@ -229,111 +182,6 @@ try_boot(void) return (status); } -/* - * probe_handle determines if the passed handle represents a logical partition - * if it does it uses each module in order to probe it and if successful it - * returns EFI_SUCCESS. - */ -static EFI_STATUS -probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred) -{ - dev_info_t *devinfo; - EFI_BLOCK_IO *blkio; - EFI_DEVICE_PATH *devpath; - EFI_STATUS status; - UINTN i; - - /* Figure out if we're dealing with an actual partition. */ - status = BS->HandleProtocol(h, &DevicePathGUID, (void **)&devpath); - if (status == EFI_UNSUPPORTED) - return (status); - - if (status != EFI_SUCCESS) { - DPRINTF("\nFailed to query DevicePath (%lu)\n", - EFI_ERROR_CODE(status)); - return (status); - } -#ifdef EFI_DEBUG - { - CHAR16 *text = efi_devpath_name(devpath); - DPRINTF("probing: %S\n", text); - efi_free_devpath_name(text); - } -#endif - status = BS->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); - if (status == EFI_UNSUPPORTED) - return (status); - - if (status != EFI_SUCCESS) { - DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n", - EFI_ERROR_CODE(status)); - return (status); - } - - if (!blkio->Media->LogicalPartition) - return (EFI_UNSUPPORTED); - - *preferred = efi_devpath_same_disk(imgpath, devpath); - - /* Run through each module, see if it can load this partition */ - devinfo = malloc(sizeof(*devinfo)); - if (devinfo == NULL) { - DPRINTF("\nFailed to allocate devinfo\n"); - return (EFI_UNSUPPORTED); - } - devinfo->dev = blkio; - devinfo->devpath = devpath; - devinfo->devhandle = h; - devinfo->preferred = *preferred; - devinfo->next = NULL; - - for (i = 0; i < NUM_BOOT_MODULES; i++) { - devinfo->devdata = NULL; - status = boot_modules[i]->probe(devinfo); - if (status == EFI_SUCCESS) - return (EFI_SUCCESS); - } - free(devinfo); - - return (EFI_UNSUPPORTED); -} - -/* - * probe_handle_status calls probe_handle and outputs the returned status - * of the call. - */ -static void -probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath) -{ - EFI_STATUS status; - BOOLEAN preferred; - - preferred = FALSE; - status = probe_handle(h, imgpath, &preferred); - - DPRINTF("probe: "); - switch (status) { - case EFI_UNSUPPORTED: - printf("."); - DPRINTF(" not supported\n"); - break; - case EFI_SUCCESS: - if (preferred) { - printf("%c", '*'); - DPRINTF(" supported (preferred)\n"); - } else { - printf("%c", '+'); - DPRINTF(" supported\n"); - } - break; - default: - printf("x"); - DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status)); - break; - } - DSTALL(500000); -} - EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) { @@ -345,9 +193,6 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL; UINTN i, hsize, nhandles; CHAR16 *text; - UINT16 boot_current; - size_t sz; - UINT16 boot_order[100]; /* Basic initialization*/ ST = Xsystab; @@ -375,13 +220,27 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) printf("\n>> FreeBSD EFI boot block\n"); printf(" Loader path: %s\n\n", PATH_LOADER_EFI); printf(" Initializing modules:"); - for (i = 0; i < NUM_BOOT_MODULES; i++) { + for (i = 0; i < num_boot_modules; i++) { printf(" %s", boot_modules[i]->name); if (boot_modules[i]->init != NULL) boot_modules[i]->init(); } putchar('\n'); + /* Fetch all the block I/O handles, we have to search through them later */ + hsize = 0; + BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL, + &hsize, NULL); + handles = malloc(hsize); + if (handles == NULL) + efi_panic(EFI_OUT_OF_RESOURCES, "Failed to allocate %d handles\n", + hsize); + status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID, + NULL, &hsize, handles); + if (status != EFI_SUCCESS) + efi_panic(status, "Failed to get device handles\n"); + nhandles = hsize / sizeof(*handles); + /* Determine the devpath of our image so we can prefer it. */ status = BS->HandleProtocol(IH, &LoadedImageGUID, (VOID**)&img); imgpath = NULL; @@ -408,58 +267,7 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) } } - boot_current = 0; - sz = sizeof(boot_current); - if (efi_global_getenv("BootCurrent", &boot_current, &sz) == EFI_SUCCESS) { - printf(" BootCurrent: %04x\n", boot_current); - - sz = sizeof(boot_order); - if (efi_global_getenv("BootOrder", &boot_order, &sz) == EFI_SUCCESS) { - printf(" BootOrder:"); - for (i = 0; i < sz / sizeof(boot_order[0]); i++) - printf(" %04x%s", boot_order[i], - boot_order[i] == boot_current ? "[*]" : ""); - printf("\n"); - } - } - -#ifdef TEST_FAILURE - /* - * For testing failover scenarios, it's nice to be able to fail fast. - * Define TEST_FAILURE to create a boot1.efi that always fails after - * reporting the boot manager protocol details. - */ - BS->Exit(IH, EFI_OUT_OF_RESOURCES, 0, NULL); -#endif - - hsize = 0; - BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL, - &hsize, NULL); - handles = malloc(hsize); - if (handles == NULL) - efi_panic(EFI_OUT_OF_RESOURCES, "Failed to allocate %d handles\n", - hsize); - status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID, - NULL, &hsize, handles); - if (status != EFI_SUCCESS) - efi_panic(status, "Failed to get device handles\n"); - - /* Scan all partitions, probing with all modules. */ - nhandles = hsize / sizeof(*handles); - printf(" Probing %zu block devices...", nhandles); - DPRINTF("\n"); - - for (i = 0; i < nhandles; i++) - probe_handle_status(handles[i], imgpath); - printf(" done\n"); - - /* Status summary. */ - for (i = 0; i < NUM_BOOT_MODULES; i++) { - printf(" "); - boot_modules[i]->status(); - } - - try_boot(); + choice_protocol(handles, nhandles, imgpath); /* If we get here, we're out of luck... */ efi_panic(EFI_LOAD_ERROR, "No bootable partitions found!"); diff --git a/stand/efi/boot1/boot_module.h b/stand/efi/boot1/boot_module.h index e196c194611d..99046fb53577 100644 --- a/stand/efi/boot1/boot_module.h +++ b/stand/efi/boot1/boot_module.h @@ -96,6 +96,9 @@ typedef struct boot_module_t dev_info_t *(*devices)(void); } boot_module_t; +extern const boot_module_t *boot_modules[]; +extern const UINTN num_boot_modules; + /* Standard boot modules. */ #ifdef EFI_UFS_BOOT extern const boot_module_t ufs_module; @@ -106,5 +109,4 @@ extern const boot_module_t zfs_module; /* Functions available to modules. */ extern void add_device(dev_info_t **devinfop, dev_info_t *devinfo); -extern int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap); #endif diff --git a/stand/efi/boot1/proto.c b/stand/efi/boot1/proto.c new file mode 100644 index 000000000000..039ee0142d49 --- /dev/null +++ b/stand/efi/boot1/proto.c @@ -0,0 +1,223 @@ +/*- + * Copyright (c) 1998 Robert Nordier + * All rights reserved. + * Copyright (c) 2001 Robert Drehmel + * All rights reserved. + * Copyright (c) 2014 Nathan Whitehorn + * All rights reserved. + * Copyright (c) 2015 Eric McCorkle + * All rights reserved. + * + * Redistribution and use in source and binary forms are freely + * permitted provided that the above copyright notice and this + * paragraph and the following disclaimer are duplicated in all + * such forms. + * + * This software is provided "AS IS" and without any express or + * implied warranties, including, without limitation, the implied + * warranties of merchantability and fitness for a particular + * purpose. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include + +#include "boot_module.h" +#include "paths.h" +#include "proto.h" + +static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL; +static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL; + +static const char *prio_str[] = { + "error", + "not supported", + "good", + "better" +}; + +/* + * probe_handle determines if the passed handle represents a logical partition + * if it does it uses each module in order to probe it and if successful it + * returns EFI_SUCCESS. + */ +static int +probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath) +{ + dev_info_t *devinfo; + EFI_BLOCK_IO *blkio; + EFI_DEVICE_PATH *devpath; + EFI_STATUS status; + UINTN i; + int preferred; + + /* Figure out if we're dealing with an actual partition. */ + status = BS->HandleProtocol(h, &DevicePathGUID, (void **)&devpath); + if (status == EFI_UNSUPPORTED) + return (0); + + if (status != EFI_SUCCESS) { + DPRINTF("\nFailed to query DevicePath (%lu)\n", + EFI_ERROR_CODE(status)); + return (-1); + } +#ifdef EFI_DEBUG + { + CHAR16 *text = efi_devpath_name(devpath); + DPRINTF("probing: %S ", text); + efi_free_devpath_name(text); + } +#endif + status = BS->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); + if (status == EFI_UNSUPPORTED) + return (0); + + if (status != EFI_SUCCESS) { + DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n", + EFI_ERROR_CODE(status)); + return (-1); + } + + if (!blkio->Media->LogicalPartition) + return (0); + + preferred = efi_devpath_same_disk(imgpath, devpath); + + /* Run through each module, see if it can load this partition */ + devinfo = malloc(sizeof(*devinfo)); + if (devinfo == NULL) { + DPRINTF("\nFailed to allocate devinfo\n"); + return (-1); + } + devinfo->dev = blkio; + devinfo->devpath = devpath; + devinfo->devhandle = h; + devinfo->preferred = preferred; + devinfo->next = NULL; + + for (i = 0; i < num_boot_modules; i++) { + devinfo->devdata = NULL; + + status = boot_modules[i]->probe(devinfo); + if (status == EFI_SUCCESS) + return (preferred + 1); + } + free(devinfo); + + return (0); +} + +/* + * load_loader attempts to load the loader image data. + * + * It tries each module and its respective devices, identified by mod->probe, + * in order until a successful load occurs at which point it returns EFI_SUCCESS + * and EFI_NOT_FOUND otherwise. + * + * Only devices which have preferred matching the preferred parameter are tried. + */ +static EFI_STATUS +load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp, + size_t *bufsize, int preferred) +{ + UINTN i; + dev_info_t *dev; + const boot_module_t *mod; + + for (i = 0; i < num_boot_modules; i++) { + mod = boot_modules[i]; + for (dev = mod->devices(); dev != NULL; dev = dev->next) { + if (dev->preferred != preferred) + continue; + + if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) == + EFI_SUCCESS) { + *devinfop = dev; + *modp = mod; + return (EFI_SUCCESS); + } + } + } + + return (EFI_NOT_FOUND); +} + +void +choice_protocol(EFI_HANDLE *handles, UINTN nhandles, EFI_DEVICE_PATH *imgpath) +{ + UINT16 boot_current; + size_t sz; + UINT16 boot_order[100]; + unsigned i; + int rv; + EFI_STATUS status; + const boot_module_t *mod; + dev_info_t *dev; + void *loaderbuf; + size_t loadersize; + + /* Report UEFI Boot Manager Protocol details */ + boot_current = 0; + sz = sizeof(boot_current); + if (efi_global_getenv("BootCurrent", &boot_current, &sz) == EFI_SUCCESS) { + printf(" BootCurrent: %04x\n", boot_current); + + sz = sizeof(boot_order); + if (efi_global_getenv("BootOrder", &boot_order, &sz) == EFI_SUCCESS) { + printf(" BootOrder:"); + for (i = 0; i < sz / sizeof(boot_order[0]); i++) + printf(" %04x%s", boot_order[i], + boot_order[i] == boot_current ? "[*]" : ""); + printf("\n"); + } + } + +#ifdef TEST_FAILURE + /* + * For testing failover scenarios, it's nice to be able to fail fast. + * Define TEST_FAILURE to create a boot1.efi that always fails after + * reporting the boot manager protocol details. + */ + BS->Exit(IH, EFI_OUT_OF_RESOURCES, 0, NULL); +#endif + + /* Scan all partitions, probing with all modules. */ + printf(" Probing %zu block devices...", nhandles); + DPRINTF("\n"); + for (i = 0; i < nhandles; i++) { + rv = probe_handle(handles[i], imgpath); +#ifdef EFI_DEBUG + printf("%c", "x.+*"[rv + 1]); +#else + printf("%s\n", prio_str[rv + 1]); +#endif + } + printf(" done\n"); + + + /* Status summary. */ + for (i = 0; i < num_boot_modules; i++) { + printf(" "); + boot_modules[i]->status(); + } + + status = load_loader(&mod, &dev, &loaderbuf, &loadersize, 1); + if (status != EFI_SUCCESS) { + status = load_loader(&mod, &dev, &loaderbuf, &loadersize, 0); + if (status != EFI_SUCCESS) { + printf("Failed to load '%s'\n", PATH_LOADER_EFI); + return; + } + } + + try_boot(mod, dev, loaderbuf, loadersize); +} diff --git a/stand/efi/boot1/proto.h b/stand/efi/boot1/proto.h new file mode 100644 index 000000000000..5d80f907a5a5 --- /dev/null +++ b/stand/efi/boot1/proto.h @@ -0,0 +1,29 @@ +/*- + * Copyright (c) 2019 Netflix, 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 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$ + */ + +void choice_protocol(EFI_HANDLE *handles, UINTN nhandles, EFI_DEVICE_PATH *imgpath); +EFI_STATUS try_boot(const boot_module_t *mod, dev_info_t *dev, void *loaderbuf, size_t loadersize); diff --git a/stand/efi/boot1/ufs_module.c b/stand/efi/boot1/ufs_module.c index 1611be3e4506..fa0e5fc051a0 100644 --- a/stand/efi/boot1/ufs_module.c +++ b/stand/efi/boot1/ufs_module.c @@ -140,7 +140,6 @@ static EFI_STATUS load(const char *filepath, dev_info_t *dev, void **bufp, size_t *bufsize) { ufs_ino_t ino; - EFI_STATUS status; size_t size; ssize_t read; void *buf; @@ -167,18 +166,18 @@ load(const char *filepath, dev_info_t *dev, void **bufp, size_t *bufsize) return (EFI_INVALID_PARAMETER); } - if ((status = BS->AllocatePool(EfiLoaderData, size, &buf)) != - EFI_SUCCESS) { - printf("Failed to allocate read buffer %zu for '%s' (%lu)\n", - size, filepath, EFI_ERROR_CODE(status)); - return (status); + buf = malloc(size); + if (buf == NULL) { + printf("Failed to allocate read buffer %zu for '%s'\n", + size, filepath); + return (EFI_OUT_OF_RESOURCES); } read = fsread(ino, buf, size); if ((size_t)read != size) { printf("Failed to read '%s' (%zd != %zu)\n", filepath, read, size); - (void)BS->FreePool(buf); + free(buf); return (EFI_INVALID_PARAMETER); } diff --git a/stand/efi/boot1/zfs_module.c b/stand/efi/boot1/zfs_module.c index 6eb5aeeb2a06..5550879a3227 100644 --- a/stand/efi/boot1/zfs_module.c +++ b/stand/efi/boot1/zfs_module.c @@ -115,19 +115,17 @@ probe(dev_info_t *dev) { spa_t *spa; dev_info_t *tdev; - EFI_STATUS status; /* ZFS consumes the dev on success so we need a copy. */ - if ((status = BS->AllocatePool(EfiLoaderData, sizeof(*dev), - (void**)&tdev)) != EFI_SUCCESS) { - DPRINTF("Failed to allocate tdev (%lu)\n", - EFI_ERROR_CODE(status)); - return (status); + tdev = malloc(sizeof(*dev)); + if (tdev == NULL) { + DPRINTF("Failed to allocate tdev\n"); + return (EFI_OUT_OF_RESOURCES); } memcpy(tdev, dev, sizeof(*dev)); if (vdev_probe(vdev_read, tdev, &spa) != 0) { - (void)BS->FreePool(tdev); + free(tdev); return (EFI_UNSUPPORTED); } @@ -146,7 +144,6 @@ load(const char *filepath, dev_info_t *devinfo, void **bufp, size_t *bufsize) struct stat st; int err; void *buf; - EFI_STATUS status; spa = devinfo->devdata; @@ -185,17 +182,17 @@ load(const char *filepath, dev_info_t *devinfo, void **bufp, size_t *bufsize) return (EFI_INVALID_PARAMETER); } - if ((status = BS->AllocatePool(EfiLoaderData, (UINTN)st.st_size, &buf)) - != EFI_SUCCESS) { - printf("Failed to allocate load buffer %jd for pool '%s' for '%s' " - "(%lu)\n", (intmax_t)st.st_size, spa->spa_name, filepath, EFI_ERROR_CODE(status)); + buf = malloc(st.st_size); + if (buf == NULL) { + printf("Failed to allocate load buffer %jd for pool '%s' for '%s' ", + (intmax_t)st.st_size, spa->spa_name, filepath); return (EFI_INVALID_PARAMETER); } if ((err = dnode_read(spa, &dn, 0, buf, st.st_size)) != 0) { printf("Failed to read node from %s (%d)\n", spa->spa_name, err); - (void)BS->FreePool(buf); + free(buf); return (EFI_INVALID_PARAMETER); } diff --git a/stand/efi/gptboot/Makefile b/stand/efi/gptboot/Makefile new file mode 100644 index 000000000000..e4af52b31204 --- /dev/null +++ b/stand/efi/gptboot/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +# ZFS is not supported, we want debugging until this is vetted and +# we don't want the gptboot.efifat thing created. +MK_LOADER_ZFS=no +EFI_DEBUG=yes +NOFAT=yes + +BOOT1?= gptboot +.PATH: ${SRCTOP}/stand/efi/boot1 ${SRCTOP}/stand/libsa +CFLAGS+= -I${SRCTOP}/stand/efi/boot1 +CFLAGS+= -I${.CURDIR} +CFLAGS+= -DBOOTPROG=\"gptboot.efi\" +SRCS+= gpt.c +CWARNFLAGS.gpt.c+= -Wno-sign-compare -Wno-cast-align +WARNS=6 +.include "${.CURDIR}/../boot1/Makefile" diff --git a/stand/efi/gptboot/drv.h b/stand/efi/gptboot/drv.h new file mode 100644 index 000000000000..d7df6a10f1e4 --- /dev/null +++ b/stand/efi/gptboot/drv.h @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2019 Netflix, 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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _DRV_H_ +#define _DRV_H_ + +struct dsk { + int part; + daddr_t start; + void *devinfo; /* Really a dev_into_t *, but that's not in scope */ +}; + +int drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk); +int drvwrite(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk); +uint64_t drvsize(struct dsk *dskp); + +#endif /* !_DRV_H_ */ diff --git a/stand/efi/gptboot/proto.c b/stand/efi/gptboot/proto.c new file mode 100644 index 000000000000..84888b496f83 --- /dev/null +++ b/stand/efi/gptboot/proto.c @@ -0,0 +1,279 @@ +/*- + * Copyright (c) 2019 Netflix, 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 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 "boot_module.h" +#include "paths.h" +#include "proto.h" + +#include "gpt.h" +#include +static const uuid_t freebsd_ufs_uuid = GPT_ENT_TYPE_FREEBSD_UFS; +static char secbuf[4096]; +static struct dsk dsk; +static dev_info_t *devices = NULL; +static dev_info_t *raw_device = NULL; + +static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL; +static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL; + +/* + * Shim routine for the gpt code to read in the gpt table. The + * devinfo is always going to be for the raw device. + */ +int +drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk) +{ + int size; + EFI_STATUS status; + dev_info_t *devinfo = (dev_info_t *)dskp->devinfo; + EFI_BLOCK_IO *dev = devinfo->dev; + + lba = lba / (dev->Media->BlockSize / DEV_BSIZE); + size = nblk * DEV_BSIZE; + + status = dev->ReadBlocks(dev, dev->Media->MediaId, lba, size, buf); + if (status != EFI_SUCCESS) { + DPRINTF("dskread: failed dev: %p, id: %u, lba: %ju, size: %d, " + "status: %lu\n", devinfo->dev, + dev->Media->MediaId, (uintmax_t)lba, size, + EFI_ERROR_CODE(status)); + return (-1); + } + + return (0); +} + +/* + * Shim routine for the gpt code to write in the gpt table. The + * devinfo is always going to be for the raw device. + */ +int +drvwrite(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk) +{ + int size; + EFI_STATUS status; + dev_info_t *devinfo = (dev_info_t *)dskp->devinfo; + EFI_BLOCK_IO *dev = devinfo->dev; + + if (dev->Media->ReadOnly) + return -1; + + lba = lba / (dev->Media->BlockSize / DEV_BSIZE); + size = nblk * DEV_BSIZE; + + status = dev->WriteBlocks(dev, dev->Media->MediaId, lba, size, buf); + if (status != EFI_SUCCESS) { + DPRINTF("dskread: failed dev: %p, id: %u, lba: %ju, size: %d, " + "status: %lu\n", devinfo->dev, + dev->Media->MediaId, (uintmax_t)lba, size, + EFI_ERROR_CODE(status)); + return (-1); + } + + return (0); +} + +/* + * Return the number of LBAs the drive has. + */ +uint64_t +drvsize(struct dsk *dskp) +{ + dev_info_t *devinfo = (dev_info_t *)dskp->devinfo; + EFI_BLOCK_IO *dev = devinfo->dev; + + return (dev->Media->LastBlock + 1); +} + +static int +partition_number(EFI_DEVICE_PATH *devpath) +{ + EFI_DEVICE_PATH *md; + HARDDRIVE_DEVICE_PATH *hd; + + md = efi_devpath_last_node(devpath); + if (md == NULL) + return (-1); + if (DevicePathSubType(md) != MEDIA_HARDDRIVE_DP) + return (-1); + hd = (HARDDRIVE_DEVICE_PATH *)md; + return (hd->PartitionNumber); +} + +/* + * Find the raw partition for the imgpath and save it + */ +static void +probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath) +{ + dev_info_t *devinfo; + EFI_BLOCK_IO *blkio; + EFI_DEVICE_PATH *devpath, *trimmed = NULL; + EFI_STATUS status; + + /* Figure out if we're dealing with an actual partition. */ + status = BS->HandleProtocol(h, &DevicePathGUID, (void **)&devpath); + if (status != EFI_SUCCESS) + return; +#ifdef EFI_DEBUG + { + CHAR16 *text = efi_devpath_name(devpath); + DPRINTF("probing: %S ", text); + efi_free_devpath_name(text); + } +#endif + /* + * The RAW device is the same as the imgpath with the last + * MEDIA_DEVICE bit trimmed off. imgpath will end with the + * MEDIA_DEVICE for the ESP we booted off of. + */ + if (!efi_devpath_same_disk(imgpath, devpath)) { + trimmed = efi_devpath_trim(imgpath); + if (!efi_devpath_match(trimmed, devpath)) { + free(trimmed); + DPRINTF("Not the same disk\n"); + return; + } + } + status = BS->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); + if (status != EFI_SUCCESS) { + DPRINTF("Can't get the block I/O protocol block\n"); + return; + } + devinfo = malloc(sizeof(*devinfo)); + if (devinfo == NULL) { + DPRINTF("Failed to allocate devinfo\n"); + return; + } + devinfo->dev = blkio; + devinfo->devpath = devpath; + devinfo->devhandle = h; + devinfo->preferred = 1; + devinfo->next = NULL; + devinfo->devdata = NULL; + if (trimmed == NULL) { + DPRINTF("Found partition %d\n", partition_number(devpath)); + add_device(&devices, devinfo); + } else { + free(trimmed); + DPRINTF("Found raw device\n"); + if (raw_device) { + printf(BOOTPROG": Found two raw devices, inconceivable?\n"); + return; + } + raw_device = devinfo; + } +} + +static void +probe_handles(EFI_HANDLE *handles, UINTN nhandles, EFI_DEVICE_PATH *imgpath) +{ + UINTN i; + + for (i = 0; i < nhandles; i++) + probe_handle(handles[i], imgpath); +} + +static dev_info_t * +find_partition(int part) +{ + dev_info_t *dev; + + if (part == 0) + return (NULL); + for (dev = devices; dev != NULL; dev = dev->next) + if (partition_number(dev->devpath) == part) + break; + return (dev); +} + +void +choice_protocol(EFI_HANDLE *handles, UINTN nhandles, EFI_DEVICE_PATH *imgpath) +{ + const boot_module_t *mod = &ufs_module; + dev_info_t *bootdev; + void *loaderbuf; + size_t loadersize; + int parts; + const char *fn = PATH_LOADER_EFI; + + /* + * Probe the provided handles to find the partitions that + * are on the same drive. + */ + probe_handles(handles, nhandles, imgpath); + dsk.devinfo = raw_device; + if (dsk.devinfo == NULL) { + printf(BOOTPROG": unable to find raw disk to read gpt\n"); + return; + } + + /* + * Read in the GPT table, and then find the right partition. + * gptread, gptfind and gptfaileboot are shared with the + * BIOS version of the gptboot program. + */ + if (gptread(&dsk, secbuf) == -1) { + printf(BOOTPROG ": unable to load GPT\n"); + return; + } + // XXX: + // real gptboot can parse a command line before trying this loop. + // But since we don't parse anything at all, hard wire the partition + // to be -1 (meaning look for the next one). + parts = 0; + while (gptfind(&freebsd_ufs_uuid, &dsk, -1) != -1) { + parts++; + bootdev = find_partition(dsk.part); + if (bootdev == NULL) { + printf(BOOTPROG": Can't find partition %d\n", + dsk.part); + goto next; + } + if (mod->load(fn, bootdev, &loaderbuf, &loadersize) != + EFI_SUCCESS) { + printf(BOOTPROG": Can't load %s from partition %d\n", + fn, dsk.part); + goto next; + } + try_boot(mod, bootdev, loaderbuf, loadersize); +next: + gptbootfailed(&dsk); + } + if (parts == 0) + printf("%s: no UFS partition was found\n", BOOTPROG); +} diff --git a/stand/efi/libefi/efinet.c b/stand/efi/libefi/efinet.c index 8a3e418ef28c..ff8988d7e33c 100644 --- a/stand/efi/libefi/efinet.c +++ b/stand/efi/libefi/efinet.c @@ -108,6 +108,24 @@ efinet_match(struct netif *nif, void *machdep_hint) static int efinet_probe(struct netif *nif, void *machdep_hint) { + EFI_SIMPLE_NETWORK *net; + EFI_HANDLE h; + EFI_STATUS status; + + h = nif->nif_driver->netif_ifs[nif->nif_unit].dif_private; + /* + * Open the network device in exclusive mode. Without this + * we will be racing with the UEFI network stack. It will + * pull packets off the network leading to lost packets. + */ + status = BS->OpenProtocol(h, &sn_guid, (void **)&net, + IH, NULL, EFI_OPEN_PROTOCOL_EXCLUSIVE); + if (status != EFI_SUCCESS) { + printf("Unable to open network interface %d for " + "exclusive access: %lu\n", nif->nif_unit, + EFI_ERROR_CODE(status)); + return (efi_status_to_errno(status)); + } return (0); } @@ -269,7 +287,6 @@ efinet_dev_init() struct netif_dif *dif; struct netif_stats *stats; EFI_DEVICE_PATH *devpath, *node; - EFI_SIMPLE_NETWORK *net; EFI_HANDLE *handles, *handles2; EFI_STATUS status; UINTN sz; @@ -305,19 +322,6 @@ efinet_dev_init() DevicePathSubType(node) != MSG_MAC_ADDR_DP) continue; - /* - * Open the network device in exclusive mode. Without this - * we will be racing with the UEFI network stack. It will - * pull packets off the network leading to lost packets. - */ - status = BS->OpenProtocol(handles[i], &sn_guid, (void **)&net, - IH, NULL, EFI_OPEN_PROTOCOL_EXCLUSIVE); - if (status != EFI_SUCCESS) { - printf("Unable to open network interface %d for " - "exclusive access: %lu\n", i, - EFI_ERROR_CODE(status)); - } - handles2[nifs] = handles[i]; nifs++; } diff --git a/stand/libsa/crc32_libkern.c b/stand/libsa/crc32_libkern.c index 995815294d58..d2bd738d4c20 100644 --- a/stand/libsa/crc32_libkern.c +++ b/stand/libsa/crc32_libkern.c @@ -1,3 +1,3 @@ /* $FreeBSD$ */ -#include "../../sys/libkern/crc32.c" +#include "../../sys/libkern/gsb_crc32.c" diff --git a/stand/libsa/zfs/zfsimpl.c b/stand/libsa/zfs/zfsimpl.c index 3c352634c283..99e747b3032e 100644 --- a/stand/libsa/zfs/zfsimpl.c +++ b/stand/libsa/zfs/zfsimpl.c @@ -64,6 +64,12 @@ static const char *features_for_read[] = { "org.illumos:skein", "org.zfsonlinux:large_dnode", "com.joyent:multi_vdev_crash_dump", + "com.delphix:spacemap_histogram", + "com.delphix:zpool_checkpoint", + "com.delphix:spacemap_v2", + "com.datto:encryption", + "org.zfsonlinux:allocation_classes", + "com.datto:resilver_defer", NULL }; diff --git a/stand/ofw/libofw/ofw_console.c b/stand/ofw/libofw/ofw_console.c index 59ce9a5067d5..a129997c5df2 100644 --- a/stand/ofw/libofw/ofw_console.c +++ b/stand/ofw/libofw/ofw_console.c @@ -97,7 +97,11 @@ ofw_cons_getchar() return l; } - if (OF_read(stdin, &ch, 1) > 0) + /* At least since version 4.0.0, QEMU became bug-compatible + * with PowerVM's vty, by inserting a \0 after every \r. + * As this confuses loader's interpreter and as a \0 coming + * from the console doesn't seem reasonable, it's filtered here. */ + if (OF_read(stdin, &ch, 1) > 0 && ch != '\0') return (ch); return (-1); diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c index dc97534a2e06..537b269f2f78 100644 --- a/sys/amd64/amd64/fpu.c +++ b/sys/amd64/amd64/fpu.c @@ -154,11 +154,6 @@ static void fpu_clean_state(void); SYSCTL_INT(_hw, HW_FLOATINGPT, floatingpoint, CTLFLAG_RD, SYSCTL_NULL_INT_PTR, 1, "Floating point instructions executed in hardware"); -int lazy_fpu_switch = 0; -SYSCTL_INT(_hw, OID_AUTO, lazy_fpu_switch, CTLFLAG_RWTUN | CTLFLAG_NOFETCH, - &lazy_fpu_switch, 0, - "Lazily load FPU context after context switch"); - int use_xsave; /* non-static for cpu_switch.S */ uint64_t xsave_mask; /* the same */ static uma_zone_t fpu_save_area_zone; @@ -269,7 +264,6 @@ fpuinit_bsp1(void) uint64_t xsave_mask_user; bool old_wp; - TUNABLE_INT_FETCH("hw.lazy_fpu_switch", &lazy_fpu_switch); if (!use_xsave) return; cpuid_count(0xd, 0x0, cp); @@ -774,8 +768,7 @@ void fpu_activate_sw(struct thread *td) { - if (lazy_fpu_switch || (td->td_pflags & TDP_KTHREAD) != 0 || - !PCB_USER_FPU(td->td_pcb)) { + if ((td->td_pflags & TDP_KTHREAD) != 0 || !PCB_USER_FPU(td->td_pcb)) { PCPU_SET(fpcurthread, NULL); start_emulating(); } else if (PCPU_GET(fpcurthread) != td) { diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index a7ba57d616bf..d7a35b5c9cfc 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -1053,7 +1053,7 @@ static int pmap_enter_pde(pmap_t pmap, vm_offset_t va, pd_entry_t newpde, static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, vm_page_t mpte, struct rwlock **lockp); static void pmap_fill_ptp(pt_entry_t *firstpte, pt_entry_t newpte); -static int pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte); +static int pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte, bool promoted); static void pmap_invalidate_cache_range_selfsnoop(vm_offset_t sva, vm_offset_t eva); static void pmap_invalidate_cache_range_all(vm_offset_t sva, @@ -1757,8 +1757,13 @@ pmap_init(void) mpte->pindex = pmap_pde_pindex(KERNBASE) + i; mpte->phys_addr = KPTphys + (i << PAGE_SHIFT); mpte->wire_count = 1; + + /* + * Collect the page table pages that were replaced by a 2MB + * page in create_pagetables(). They are zero filled. + */ if (i << PDRSHIFT < KERNend && - pmap_insert_pt_page(kernel_pmap, mpte)) + pmap_insert_pt_page(kernel_pmap, mpte, false)) panic("pmap_init: pmap_insert_pt_page failed"); } PMAP_UNLOCK(kernel_pmap); @@ -3129,12 +3134,15 @@ pmap_add_delayed_free_list(vm_page_t m, struct spglist *free, * of idle page table pages. Each of a pmap's page table pages is responsible * for mapping a distinct range of virtual addresses. The pmap's collection is * ordered by this virtual address range. + * + * If "promoted" is false, then the page table page "mpte" must be zero filled. */ static __inline int -pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte) +pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte, bool promoted) { PMAP_LOCK_ASSERT(pmap, MA_OWNED); + mpte->valid = promoted ? VM_PAGE_BITS_ALL : 0; return (vm_radix_insert(&pmap->pm_root, mpte)); } @@ -4081,7 +4089,7 @@ free_pv_chunk(struct pv_chunk *pc) /* entire chunk is free, return it */ m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pc)); dump_drop_page(m->phys_addr); - vm_page_unwire(m, PQ_NONE); + vm_page_unwire_noq(m); vm_page_free(m); } @@ -4626,7 +4634,7 @@ pmap_demote_pde_locked(pmap_t pmap, pd_entry_t *pde, vm_offset_t va, * If the page table page is not leftover from an earlier promotion, * initialize it. */ - if ((oldpde & PG_PROMOTED) == 0) + if (mpte->valid == 0) pmap_fill_ptp(firstpte, newpte); pmap_demote_pde_check(firstpte, newpte); @@ -4699,9 +4707,11 @@ pmap_remove_kernel_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) newpde = mptepa | X86_PG_M | X86_PG_A | X86_PG_RW | X86_PG_V; /* - * Initialize the page table page. + * If this page table page was unmapped by a promotion, then it + * contains valid mappings. Zero it to invalidate those mappings. */ - pagezero((void *)PHYS_TO_DMAP(mptepa)); + if (mpte->valid != 0) + pagezero((void *)PHYS_TO_DMAP(mptepa)); /* * Demote the mapping. @@ -4766,6 +4776,8 @@ pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, } else { mpte = pmap_remove_pt_page(pmap, sva); if (mpte != NULL) { + KASSERT(mpte->valid == VM_PAGE_BITS_ALL, + ("pmap_remove_pde: pte page not promoted")); pmap_resident_count_dec(pmap, 1); KASSERT(mpte->wire_count == NPTEPG, ("pmap_remove_pde: pte page wire count error")); @@ -5399,7 +5411,7 @@ pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va, ("pmap_promote_pde: page table page is out of range")); KASSERT(mpte->pindex == pmap_pde_pindex(va), ("pmap_promote_pde: page table page's pindex is wrong")); - if (pmap_insert_pt_page(pmap, mpte)) { + if (pmap_insert_pt_page(pmap, mpte, true)) { atomic_add_long(&pmap_pde_p_failures, 1); CTR2(KTR_PMAP, "pmap_promote_pde: failure for va %#lx in pmap %p", va, @@ -5826,15 +5838,13 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t va, pd_entry_t newpde, u_int flags, } vm_page_free_pages_toq(&free, true); if (va >= VM_MAXUSER_ADDRESS) { + /* + * Both pmap_remove_pde() and pmap_remove_ptes() will + * leave the kernel page table page zero filled. + */ mt = PHYS_TO_VM_PAGE(*pde & PG_FRAME); - if (pmap_insert_pt_page(pmap, mt)) { - /* - * XXX Currently, this can't happen because - * we do not perform pmap_enter(psind == 1) - * on the kernel pmap. - */ + if (pmap_insert_pt_page(pmap, mt, false)) panic("pmap_enter_pde: trie insert failed"); - } } else KASSERT(*pde == 0, ("pmap_enter_pde: non-zero pde %p", pde)); @@ -6824,6 +6834,8 @@ pmap_remove_pages(pmap_t pmap) } mpte = pmap_remove_pt_page(pmap, pv->pv_va); if (mpte != NULL) { + KASSERT(mpte->valid == VM_PAGE_BITS_ALL, + ("pmap_remove_pages: pte page not promoted")); pmap_resident_count_dec(pmap, 1); KASSERT(mpte->wire_count == NPTEPG, ("pmap_remove_pages: pte page wire count error")); diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index d1571873264b..3bdb01ecfc05 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -113,42 +113,46 @@ void dblfault_handler(struct trapframe *frame); static int trap_pfault(struct trapframe *, int); static void trap_fatal(struct trapframe *, vm_offset_t); +#ifdef KDTRACE_HOOKS +static bool trap_user_dtrace(struct trapframe *, + int (**hook)(struct trapframe *)); +#endif -#define MAX_TRAP_MSG 32 -static char *trap_msg[] = { - "", /* 0 unused */ - "privileged instruction fault", /* 1 T_PRIVINFLT */ - "", /* 2 unused */ - "breakpoint instruction fault", /* 3 T_BPTFLT */ - "", /* 4 unused */ - "", /* 5 unused */ - "arithmetic trap", /* 6 T_ARITHTRAP */ - "", /* 7 unused */ - "", /* 8 unused */ - "general protection fault", /* 9 T_PROTFLT */ - "debug exception", /* 10 T_TRCTRAP */ - "", /* 11 unused */ - "page fault", /* 12 T_PAGEFLT */ - "", /* 13 unused */ - "alignment fault", /* 14 T_ALIGNFLT */ - "", /* 15 unused */ - "", /* 16 unused */ - "", /* 17 unused */ - "integer divide fault", /* 18 T_DIVIDE */ - "non-maskable interrupt trap", /* 19 T_NMI */ - "overflow trap", /* 20 T_OFLOW */ - "FPU bounds check fault", /* 21 T_BOUND */ - "FPU device not available", /* 22 T_DNA */ - "double fault", /* 23 T_DOUBLEFLT */ - "FPU operand fetch fault", /* 24 T_FPOPFLT */ - "invalid TSS fault", /* 25 T_TSSFLT */ - "segment not present fault", /* 26 T_SEGNPFLT */ - "stack fault", /* 27 T_STKFLT */ - "machine check trap", /* 28 T_MCHK */ - "SIMD floating-point exception", /* 29 T_XMMFLT */ - "reserved (unknown) fault", /* 30 T_RESERVED */ - "", /* 31 unused (reserved) */ - "DTrace pid return trap", /* 32 T_DTRACE_RET */ +static const char UNKNOWN[] = "unknown"; +static const char *const trap_msg[] = { + [0] = UNKNOWN, /* unused */ + [T_PRIVINFLT] = "privileged instruction fault", + [2] = UNKNOWN, /* unused */ + [T_BPTFLT] = "breakpoint instruction fault", + [4] = UNKNOWN, /* unused */ + [5] = UNKNOWN, /* unused */ + [T_ARITHTRAP] = "arithmetic trap", + [7] = UNKNOWN, /* unused */ + [8] = UNKNOWN, /* unused */ + [T_PROTFLT] = "general protection fault", + [T_TRCTRAP] = "debug exception", + [11] = UNKNOWN, /* unused */ + [T_PAGEFLT] = "page fault", + [13] = UNKNOWN, /* unused */ + [T_ALIGNFLT] = "alignment fault", + [15] = UNKNOWN, /* unused */ + [16] = UNKNOWN, /* unused */ + [17] = UNKNOWN, /* unused */ + [T_DIVIDE] = "integer divide fault", + [T_NMI] = "non-maskable interrupt trap", + [T_OFLOW] = "overflow trap", + [T_BOUND] = "FPU bounds check fault", + [T_DNA] = "FPU device not available", + [T_DOUBLEFLT] = "double fault", + [T_FPOPFLT] = "FPU operand fetch fault", + [T_TSSFLT] = "invalid TSS fault", + [T_SEGNPFLT] = "segment not present fault", + [T_STKFLT] = "stack fault", + [T_MCHK] = "machine check trap", + [T_XMMFLT] = "SIMD floating-point exception", + [T_RESERVED] = "reserved (unknown) fault", + [31] = UNKNOWN, /* reserved */ + [T_DTRACE_RET] = "DTrace pid return trap", }; static int prot_fault_translation; @@ -284,11 +288,11 @@ trap(struct trapframe *frame) break; case T_BPTFLT: /* bpt instruction fault */ - enable_intr(); #ifdef KDTRACE_HOOKS - if (dtrace_pid_probe_ptr != NULL && - dtrace_pid_probe_ptr(frame) == 0) + if (trap_user_dtrace(frame, &dtrace_pid_probe_ptr)) return; +#else + enable_intr(); #endif signo = SIGTRAP; ucode = TRAP_BRKPT; @@ -425,9 +429,7 @@ trap(struct trapframe *frame) break; #ifdef KDTRACE_HOOKS case T_DTRACE_RET: - enable_intr(); - if (dtrace_return_probe_ptr != NULL) - dtrace_return_probe_ptr(frame); + (void)trap_user_dtrace(frame, &dtrace_return_probe_ptr); return; #endif } @@ -877,7 +879,6 @@ trap_fatal(frame, eva) int code, ss; u_int type; struct soft_segment_descriptor softseg; - char *msg; #ifdef KDB bool handled; #endif @@ -887,11 +888,8 @@ trap_fatal(frame, eva) sdtossd(&gdt[NGDT * PCPU_GET(cpuid) + IDXSEL(frame->tf_cs & 0xffff)], &softseg); - if (type <= MAX_TRAP_MSG) - msg = trap_msg[type]; - else - msg = "UNKNOWN"; - printf("\n\nFatal trap %d: %s while in %s mode\n", type, msg, + printf("\n\nFatal trap %d: %s while in %s mode\n", type, + type < nitems(trap_msg) ? trap_msg[type] : UNKNOWN, TRAPF_USERMODE(frame) ? "user" : "kernel"); #ifdef SMP /* two separate prints in case of a trap on an unmapped page */ @@ -942,12 +940,29 @@ trap_fatal(frame, eva) } #endif printf("trap number = %d\n", type); - if (type <= MAX_TRAP_MSG) - panic("%s", trap_msg[type]); - else - panic("unknown/reserved trap"); + panic("%s", type < nitems(trap_msg) ? trap_msg[type] : + "unknown/reserved trap"); } +#ifdef KDTRACE_HOOKS +/* + * Invoke a userspace DTrace hook. The hook pointer is cleared when no + * userspace probes are enabled, so we must synchronize with DTrace to ensure + * that a trapping thread is able to call the hook before it is cleared. + */ +static bool +trap_user_dtrace(struct trapframe *frame, int (**hookp)(struct trapframe *)) +{ + int (*hook)(struct trapframe *); + + hook = (int (*)(struct trapframe *))atomic_load_ptr(hookp); + enable_intr(); + if (hook != NULL) + return ((hook)(frame) == 0); + return (false); +} +#endif + /* * Double fault handler. Called when a fault occurs while writing * a frame for a trap/exception onto the stack. This usually occurs diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h index 309e62606cae..58683d764abf 100644 --- a/sys/amd64/include/pmap.h +++ b/sys/amd64/include/pmap.h @@ -138,7 +138,7 @@ #define PGEX_RSV 0x08 /* reserved PTE field is non-zero */ #define PGEX_I 0x10 /* during an instruction fetch */ #define PGEX_PK 0x20 /* protection key violation */ -#define PGEX_SGX 0x40 /* SGX-related */ +#define PGEX_SGX 0x8000 /* SGX-related */ /* * undef the PG_xx macros that define bits in the regular x86 PTEs that diff --git a/sys/amd64/vmm/intel/vtd.c b/sys/amd64/vmm/intel/vtd.c index 9474b30fc606..489e7c179f2d 100644 --- a/sys/amd64/vmm/intel/vtd.c +++ b/sys/amd64/vmm/intel/vtd.c @@ -51,6 +51,8 @@ __FBSDID("$FreeBSD$"); * Architecture Spec, September 2008. */ +#define VTD_DRHD_INCLUDE_PCI_ALL(Flags) (((Flags) >> 0) & 0x1) + /* Section 10.4 "Register Descriptions" */ struct vtdmap { volatile uint32_t version; @@ -116,10 +118,11 @@ struct domain { static SLIST_HEAD(, domain) domhead; #define DRHD_MAX_UNITS 8 -static int drhd_num; -static struct vtdmap *vtdmaps[DRHD_MAX_UNITS]; -static int max_domains; -typedef int (*drhd_ident_func_t)(void); +static ACPI_DMAR_HARDWARE_UNIT *drhds[DRHD_MAX_UNITS]; +static int drhd_num; +static struct vtdmap *vtdmaps[DRHD_MAX_UNITS]; +static int max_domains; +typedef int (*drhd_ident_func_t)(void); static uint64_t root_table[PAGE_SIZE / sizeof(uint64_t)] __aligned(4096); static uint64_t ctx_tables[256][PAGE_SIZE / sizeof(uint64_t)] __aligned(4096); @@ -175,6 +178,69 @@ domain_id(void) return (id); } +static struct vtdmap * +vtd_device_scope(uint16_t rid) +{ + int i, remaining, pathremaining; + char *end, *pathend; + struct vtdmap *vtdmap; + ACPI_DMAR_HARDWARE_UNIT *drhd; + ACPI_DMAR_DEVICE_SCOPE *device_scope; + ACPI_DMAR_PCI_PATH *path; + + for (i = 0; i < drhd_num; i++) { + drhd = drhds[i]; + + if (VTD_DRHD_INCLUDE_PCI_ALL(drhd->Flags)) { + /* + * From Intel VT-d arch spec, version 3.0: + * If a DRHD structure with INCLUDE_PCI_ALL flag Set is reported + * for a Segment, it must be enumerated by BIOS after all other + * DRHD structures for the same Segment. + */ + vtdmap = vtdmaps[i]; + return(vtdmap); + } + + end = (char *)drhd + drhd->Header.Length; + remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT); + while (remaining > sizeof(ACPI_DMAR_DEVICE_SCOPE)) { + device_scope = (ACPI_DMAR_DEVICE_SCOPE *)(end - remaining); + remaining -= device_scope->Length; + + switch (device_scope->EntryType){ + /* 0x01 and 0x02 are PCI device entries */ + case 0x01: + case 0x02: + break; + default: + continue; + } + + if (PCI_RID2BUS(rid) != device_scope->Bus) + continue; + + pathend = (char *)device_scope + device_scope->Length; + pathremaining = device_scope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE); + while (pathremaining >= sizeof(ACPI_DMAR_PCI_PATH)) { + path = (ACPI_DMAR_PCI_PATH *)(pathend - pathremaining); + pathremaining -= sizeof(ACPI_DMAR_PCI_PATH); + + if (PCI_RID2SLOT(rid) != path->Device) + continue; + if (PCI_RID2FUNC(rid) != path->Function) + continue; + + vtdmap = vtdmaps[i]; + return (vtdmap); + } + } + } + + /* No matching scope */ + return (NULL); +} + static void vtd_wbflush(struct vtdmap *vtdmap) { @@ -240,7 +306,7 @@ vtd_translation_disable(struct vtdmap *vtdmap) static int vtd_init(void) { - int i, units, remaining; + int i, units, remaining, tmp; struct vtdmap *vtdmap; vm_paddr_t ctx_paddr; char *end, envname[32]; @@ -291,8 +357,9 @@ vtd_init(void) break; drhd = (ACPI_DMAR_HARDWARE_UNIT *)hdr; - vtdmaps[units++] = (struct vtdmap *)PHYS_TO_DMAP(drhd->Address); - if (units >= DRHD_MAX_UNITS) + drhds[units] = drhd; + vtdmaps[units] = (struct vtdmap *)PHYS_TO_DMAP(drhd->Address); + if (++units >= DRHD_MAX_UNITS) break; remaining -= hdr->Length; } @@ -302,12 +369,18 @@ vtd_init(void) skip_dmar: drhd_num = units; - vtdmap = vtdmaps[0]; - if (VTD_CAP_CM(vtdmap->cap) != 0) - panic("vtd_init: invalid caching mode"); + max_domains = 64 * 1024; /* maximum valid value */ + for (i = 0; i < drhd_num; i++){ + vtdmap = vtdmaps[i]; - max_domains = vtd_max_domains(vtdmap); + if (VTD_CAP_CM(vtdmap->cap) != 0) + panic("vtd_init: invalid caching mode"); + + /* take most compatible (minimum) value */ + if ((tmp = vtd_max_domains(vtdmap)) < max_domains) + max_domains = tmp; + } /* * Set up the root-table to point to the context-entry tables @@ -373,7 +446,6 @@ vtd_add_device(void *arg, uint16_t rid) struct vtdmap *vtdmap; uint8_t bus; - vtdmap = vtdmaps[0]; bus = PCI_RID2BUS(rid); ctxp = ctx_tables[bus]; pt_paddr = vtophys(dom->ptp); @@ -385,6 +457,10 @@ vtd_add_device(void *arg, uint16_t rid) (uint16_t)(ctxp[idx + 1] >> 8)); } + if ((vtdmap = vtd_device_scope(rid)) == NULL) + panic("vtd_add_device: device %x is not in scope for " + "any DMA remapping unit", rid); + /* * Order is important. The 'present' bit is set only after all fields * of the context pointer are initialized. @@ -568,8 +644,6 @@ vtd_create_domain(vm_paddr_t maxaddr) if (drhd_num <= 0) panic("vtd_create_domain: no dma remapping hardware available"); - vtdmap = vtdmaps[0]; - /* * Calculate AGAW. * Section 3.4.2 "Adjusted Guest Address Width", Architecture Spec. @@ -594,7 +668,14 @@ vtd_create_domain(vm_paddr_t maxaddr) pt_levels = 2; sagaw = 30; addrwidth = 0; - tmp = VTD_CAP_SAGAW(vtdmap->cap); + + tmp = ~0; + for (i = 0; i < drhd_num; i++) { + vtdmap = vtdmaps[i]; + /* take most compatible value */ + tmp &= VTD_CAP_SAGAW(vtdmap->cap); + } + for (i = 0; i < 5; i++) { if ((tmp & (1 << i)) != 0 && sagaw >= agaw) break; @@ -606,8 +687,8 @@ vtd_create_domain(vm_paddr_t maxaddr) } if (i >= 5) { - panic("vtd_create_domain: SAGAW 0x%lx does not support AGAW %d", - VTD_CAP_SAGAW(vtdmap->cap), agaw); + panic("vtd_create_domain: SAGAW 0x%x does not support AGAW %d", + tmp, agaw); } dom = malloc(sizeof(struct domain), M_VTD, M_ZERO | M_WAITOK); @@ -634,7 +715,12 @@ vtd_create_domain(vm_paddr_t maxaddr) * There is not any code to deal with the demotion at the moment * so we disable superpage mappings altogether. */ - dom->spsmask = VTD_CAP_SPS(vtdmap->cap); + dom->spsmask = ~0; + for (i = 0; i < drhd_num; i++) { + vtdmap = vtdmaps[i]; + /* take most compatible value */ + dom->spsmask &= VTD_CAP_SPS(vtdmap->cap); + } #endif SLIST_INSERT_HEAD(&domhead, dom, next); diff --git a/sys/arm/allwinner/a10_timer.c b/sys/arm/allwinner/a10_timer.c index fb926e396cfe..2392de6d9f82 100644 --- a/sys/arm/allwinner/a10_timer.c +++ b/sys/arm/allwinner/a10_timer.c @@ -108,12 +108,16 @@ struct a10_timer_softc { bus_write_4(sc->res[A10_TIMER_MEMRES], reg, val) static u_int a10_timer_get_timecount(struct timecounter *); +#if defined(__arm__) static int a10_timer_timer_start(struct eventtimer *, sbintime_t first, sbintime_t period); static int a10_timer_timer_stop(struct eventtimer *); +#endif static uint64_t timer_read_counter64(struct a10_timer_softc *sc); +#if defined(__arm__) static void a10_timer_eventtimer_setup(struct a10_timer_softc *sc); +#endif static void a23_timer_timecounter_setup(struct a10_timer_softc *sc); static u_int a23_timer_get_timecount(struct timecounter *tc); @@ -279,6 +283,7 @@ a10_timer_irq(void *arg) * Event timer function for A10 and A13 */ +#if defined(__arm__) static void a10_timer_eventtimer_setup(struct a10_timer_softc *sc) { @@ -363,6 +368,7 @@ a10_timer_timer_stop(struct eventtimer *et) return (0); } +#endif /* * Timecounter functions for A23 and above diff --git a/sys/arm/allwinner/aw_mmc.c b/sys/arm/allwinner/aw_mmc.c index 58c7e08288af..d5da27aa8c8f 100644 --- a/sys/arm/allwinner/aw_mmc.c +++ b/sys/arm/allwinner/aw_mmc.c @@ -1104,7 +1104,6 @@ aw_mmc_request(device_t bus, device_t child, struct mmc_request *req) } if (cmd->data->flags & MMC_DATA_WRITE) cmdreg |= AW_MMC_CMDR_DIR_WRITE; - blksz = min(cmd->data->len, MMC_SECTOR_SIZE); #ifdef MMCCAM if (cmd->data->flags & MMC_DATA_BLOCK_SIZE) { AW_MMC_WRITE_4(sc, AW_MMC_BKSR, cmd->data->block_size); @@ -1112,6 +1111,7 @@ aw_mmc_request(device_t bus, device_t child, struct mmc_request *req) } else #endif { + blksz = min(cmd->data->len, MMC_SECTOR_SIZE); AW_MMC_WRITE_4(sc, AW_MMC_BKSR, blksz); AW_MMC_WRITE_4(sc, AW_MMC_BYCR, cmd->data->len); } diff --git a/sys/arm/allwinner/aw_pwm.c b/sys/arm/allwinner/aw_pwm.c index 7944fad78a57..39b2f7475999 100644 --- a/sys/arm/allwinner/aw_pwm.c +++ b/sys/arm/allwinner/aw_pwm.c @@ -44,9 +44,7 @@ __FBSDID("$FreeBSD$"); #include -#include - -#include "pwm_if.h" +#include "pwmbus_if.h" #define AW_PWM_CTRL 0x00 #define AW_PWM_CTRL_PRESCALE_MASK 0xF @@ -138,6 +136,7 @@ aw_pwm_attach(device_t dev) struct aw_pwm_softc *sc; uint64_t clk_freq; uint32_t reg; + phandle_t node; int error; sc = device_get_softc(dev); @@ -149,8 +148,16 @@ aw_pwm_attach(device_t dev) goto fail; } error = clk_enable(sc->clk); + if (error != 0) { + device_printf(dev, "cannot enable clock\n"); + goto fail; + } error = clk_get_freq(sc->clk, &sc->clk_freq); + if (error != 0) { + device_printf(dev, "cannot get clock frequency\n"); + goto fail; + } if (bus_alloc_resources(dev, aw_pwm_spec, &sc->res) != 0) { device_printf(dev, "cannot allocate resources for device\n"); @@ -158,9 +165,6 @@ aw_pwm_attach(device_t dev) goto fail; } - if ((sc->busdev = pwmbus_attach_bus(dev)) == NULL) - device_printf(dev, "Cannot attach pwm bus\n"); - /* Read the configuration left by U-Boot */ reg = AW_PWM_READ(sc, AW_PWM_CTRL); if (reg & (AW_PWM_CTRL_GATE | AW_PWM_CTRL_EN)) @@ -170,7 +174,7 @@ aw_pwm_attach(device_t dev) reg &= AW_PWM_CTRL_PRESCALE_MASK; if (reg > nitems(aw_pwm_clk_prescaler)) { device_printf(dev, "Bad prescaler %x, cannot guess current settings\n", reg); - goto out; + goto skipcfg; } clk_freq = sc->clk_freq / aw_pwm_clk_prescaler[reg]; @@ -180,8 +184,17 @@ aw_pwm_attach(device_t dev) sc->duty = NS_PER_SEC / (clk_freq / ((reg >> AW_PWM_PERIOD_ACTIVE_SHIFT) & AW_PWM_PERIOD_ACTIVE_MASK)); -out: - return (0); +skipcfg: + /* + * Note that we don't check for failure to attach pwmbus -- even without + * it we can still service clients who connect via fdt xref data. + */ + node = ofw_bus_get_node(dev); + OF_device_register_xref(OF_xref_from_node(node), dev); + + sc->busdev = device_add_child(dev, "pwmbus", -1); + + return (bus_generic_attach(dev)); fail: aw_pwm_detach(dev); @@ -192,18 +205,37 @@ static int aw_pwm_detach(device_t dev) { struct aw_pwm_softc *sc; + int error; sc = device_get_softc(dev); - bus_generic_detach(sc->dev); + if ((error = bus_generic_detach(sc->dev)) != 0) { + device_printf(sc->dev, "cannot detach child devices\n"); + return (error); + } - bus_release_resources(dev, aw_pwm_spec, &sc->res); + if (sc->busdev != NULL) + device_delete_child(dev, sc->busdev); + + if (sc->res != NULL) + bus_release_resources(dev, aw_pwm_spec, &sc->res); return (0); } +static phandle_t +aw_pwm_get_node(device_t bus, device_t dev) +{ + + /* + * Share our controller node with our pwmbus child; it instantiates + * devices by walking the children contained within our node. + */ + return ofw_bus_get_node(bus); +} + static int -aw_pwm_channel_max(device_t dev, int *nchannel) +aw_pwm_channel_count(device_t dev, u_int *nchannel) { *nchannel = 1; @@ -212,7 +244,7 @@ aw_pwm_channel_max(device_t dev, int *nchannel) } static int -aw_pwm_channel_config(device_t dev, int channel, unsigned int period, unsigned int duty) +aw_pwm_channel_config(device_t dev, u_int channel, u_int period, u_int duty) { struct aw_pwm_softc *sc; uint64_t period_freq, duty_freq; @@ -275,7 +307,7 @@ aw_pwm_channel_config(device_t dev, int channel, unsigned int period, unsigned i } static int -aw_pwm_channel_get_config(device_t dev, int channel, unsigned int *period, unsigned int *duty) +aw_pwm_channel_get_config(device_t dev, u_int channel, u_int *period, u_int *duty) { struct aw_pwm_softc *sc; @@ -288,7 +320,7 @@ aw_pwm_channel_get_config(device_t dev, int channel, unsigned int *period, unsig } static int -aw_pwm_channel_enable(device_t dev, int channel, bool enable) +aw_pwm_channel_enable(device_t dev, u_int channel, bool enable) { struct aw_pwm_softc *sc; uint32_t reg; @@ -312,7 +344,7 @@ aw_pwm_channel_enable(device_t dev, int channel, bool enable) } static int -aw_pwm_channel_is_enabled(device_t dev, int channel, bool *enabled) +aw_pwm_channel_is_enabled(device_t dev, u_int channel, bool *enabled) { struct aw_pwm_softc *sc; @@ -323,28 +355,21 @@ aw_pwm_channel_is_enabled(device_t dev, int channel, bool *enabled) return (0); } -static device_t -aw_pwm_get_bus(device_t dev) -{ - struct aw_pwm_softc *sc; - - sc = device_get_softc(dev); - - return (sc->busdev); -} static device_method_t aw_pwm_methods[] = { /* Device interface */ DEVMETHOD(device_probe, aw_pwm_probe), DEVMETHOD(device_attach, aw_pwm_attach), DEVMETHOD(device_detach, aw_pwm_detach), - /* pwm interface */ - DEVMETHOD(pwm_get_bus, aw_pwm_get_bus), - DEVMETHOD(pwm_channel_max, aw_pwm_channel_max), - DEVMETHOD(pwm_channel_config, aw_pwm_channel_config), - DEVMETHOD(pwm_channel_get_config, aw_pwm_channel_get_config), - DEVMETHOD(pwm_channel_enable, aw_pwm_channel_enable), - DEVMETHOD(pwm_channel_is_enabled, aw_pwm_channel_is_enabled), + /* ofw_bus interface */ + DEVMETHOD(ofw_bus_get_node, aw_pwm_get_node), + + /* pwmbus interface */ + DEVMETHOD(pwmbus_channel_count, aw_pwm_channel_count), + DEVMETHOD(pwmbus_channel_config, aw_pwm_channel_config), + DEVMETHOD(pwmbus_channel_get_config, aw_pwm_channel_get_config), + DEVMETHOD(pwmbus_channel_enable, aw_pwm_channel_enable), + DEVMETHOD(pwmbus_channel_is_enabled, aw_pwm_channel_is_enabled), DEVMETHOD_END }; @@ -358,4 +383,5 @@ static driver_t aw_pwm_driver = { static devclass_t aw_pwm_devclass; DRIVER_MODULE(aw_pwm, simplebus, aw_pwm_driver, aw_pwm_devclass, 0, 0); +MODULE_VERSION(aw_pwm, 1); SIMPLEBUS_PNP_INFO(compat_data); diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index 8a2c4c167f3e..162b49b7fb01 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -2973,7 +2973,7 @@ free_pv_chunk(struct pv_chunk *pc) /* entire chunk is free, return it */ m = PHYS_TO_VM_PAGE(pmap_kextract((vm_offset_t)pc)); pmap_qremove((vm_offset_t)pc, 1); - vm_page_unwire(m, PQ_NONE); + vm_page_unwire_noq(m); vm_page_free(m); pmap_pte2list_free(&pv_vafree, (vm_offset_t)pc); } diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c index 87da2b8af7d3..51dca8307d64 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c @@ -107,12 +107,14 @@ struct bcm_sdhci_softc { bus_dma_tag_t sc_dma_tag; bus_dmamap_t sc_dma_map; vm_paddr_t sc_sdhci_buffer_phys; - uint32_t cmd_and_mode; bus_addr_t dmamap_seg_addrs[NUM_DMA_SEGS]; bus_size_t dmamap_seg_sizes[NUM_DMA_SEGS]; int dmamap_seg_count; int dmamap_seg_index; int dmamap_status; + uint32_t blksz_and_count; + uint32_t cmd_and_mode; + bool need_update_blk; }; static int bcm_sdhci_probe(device_t); @@ -269,6 +271,10 @@ bcm_sdhci_attach(device_t dev) sdhci_start_slot(&sc->sc_slot); + /* Seed our copies. */ + sc->blksz_and_count = SDHCI_READ_4(dev, &sc->sc_slot, SDHCI_BLOCK_SIZE); + sc->cmd_and_mode = SDHCI_READ_4(dev, &sc->sc_slot, SDHCI_TRANSFER_MODE); + return (0); fail: @@ -338,17 +344,21 @@ static uint16_t bcm_sdhci_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off) { struct bcm_sdhci_softc *sc = device_get_softc(dev); - uint32_t val = RD4(sc, off & ~3); + uint32_t val32; /* - * Standard 32-bit handling of command and transfer mode. + * Standard 32-bit handling of command and transfer mode, as + * well as block size and count. */ - if (off == SDHCI_TRANSFER_MODE) { - return (sc->cmd_and_mode >> 16); - } else if (off == SDHCI_COMMAND_FLAGS) { - return (sc->cmd_and_mode & 0x0000ffff); - } - return ((val >> (off & 3)*8) & 0xffff); + if ((off == SDHCI_BLOCK_SIZE || off == SDHCI_BLOCK_COUNT) && + sc->need_update_blk) + val32 = sc->blksz_and_count; + else if (off == SDHCI_TRANSFER_MODE || off == SDHCI_COMMAND_FLAGS) + val32 = sc->cmd_and_mode; + else + val32 = RD4(sc, off & ~3); + + return ((val32 >> (off & 3)*8) & 0xffff); } static uint32_t @@ -383,18 +393,43 @@ bcm_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint16_ { struct bcm_sdhci_softc *sc = device_get_softc(dev); uint32_t val32; - if (off == SDHCI_COMMAND_FLAGS) + + /* + * If we have a queued up 16bit value for blk size or count, use and + * update the saved value rather than doing any real register access. + * If we did not touch either since the last write, then read from + * register as at least block count can change. + * Similarly, if we are about to issue a command, always use the saved + * value for transfer mode as we can never write that without issuing + * a command. + */ + if ((off == SDHCI_BLOCK_SIZE || off == SDHCI_BLOCK_COUNT) && + sc->need_update_blk) + val32 = sc->blksz_and_count; + else if (off == SDHCI_COMMAND_FLAGS) val32 = sc->cmd_and_mode; else val32 = RD4(sc, off & ~3); + val32 &= ~(0xffff << (off & 3)*8); val32 |= (val << (off & 3)*8); + if (off == SDHCI_TRANSFER_MODE) sc->cmd_and_mode = val32; - else { - WR4(sc, off & ~3, val32); - if (off == SDHCI_COMMAND_FLAGS) + else if (off == SDHCI_BLOCK_SIZE || off == SDHCI_BLOCK_COUNT) { + sc->blksz_and_count = val32; + sc->need_update_blk = true; + } else { + if (off == SDHCI_COMMAND_FLAGS) { + /* If we saved blk writes, do them now before cmd. */ + if (sc->need_update_blk) { + WR4(sc, SDHCI_BLOCK_SIZE, sc->blksz_and_count); + sc->need_update_blk = false; + } + /* Always save cmd and mode registers. */ sc->cmd_and_mode = val32; + } + WR4(sc, off & ~3, val32); } } @@ -504,6 +539,22 @@ bcm_sdhci_dma_intr(int ch, void *arg) left = min(BCM_SDHCI_BUFFER_SIZE, slot->curcmd->data->len - slot->offset); + /* + * If there is less than buffer size outstanding, we would not handle + * it anymore using DMA if bcm_sdhci_will_handle_transfer() were asked. + * Re-enable interrupts and return and let the SDHCI state machine + * finish the job. + */ + if (left < BCM_SDHCI_BUFFER_SIZE) { + /* Re-enable data interrupts. */ + slot->intmask |= SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | + SDHCI_INT_DATA_END; + bcm_sdhci_write_4(slot->bus, slot, SDHCI_SIGNAL_ENABLE, + slot->intmask); + mtx_unlock(&slot->mtx); + return; + } + /* DATA END? */ reg = bcm_sdhci_read_4(slot->bus, slot, SDHCI_INT_STATUS); @@ -657,6 +708,7 @@ static device_method_t bcm_sdhci_methods[] = { /* Bus interface */ DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar), DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar), + DEVMETHOD(bus_add_child, bus_generic_add_child), /* MMC bridge interface */ DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios), diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhost.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhost.c index 1e3b3df06e36..c92231223528 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_sdhost.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhost.c @@ -251,6 +251,7 @@ WR4(struct bcm_sdhost_softc *sc, bus_size_t off, uint32_t val) bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val); } +#ifdef notyet static inline uint16_t RD2(struct bcm_sdhost_softc *sc, bus_size_t off) { @@ -260,6 +261,7 @@ RD2(struct bcm_sdhost_softc *sc, bus_size_t off) return ((val >> (off & 3)*8) & 0xffff); } +#endif static inline uint8_t RD1(struct bcm_sdhost_softc *sc, bus_size_t off) diff --git a/sys/arm/conf/GENERIC b/sys/arm/conf/GENERIC index 474198ebaf6b..d32baa63a667 100644 --- a/sys/arm/conf/GENERIC +++ b/sys/arm/conf/GENERIC @@ -277,4 +277,16 @@ device aw_thermal # Allwinner Thermal Sensor Controller # Flattened Device Tree options FDT # Configure using FDT/DTB data -makeoptions MODULES_EXTRA="dtb/allwinner dtb/am335x dtb/imx6 dtb/nvidia dtb/rpi dtb/zynq dtb/omap4" +makeoptions MODULES_EXTRA+="dtb/allwinner" +makeoptions MODULES_EXTRA+="dtb/am335x" +makeoptions MODULES_EXTRA+="dtb/imx6" +makeoptions MODULES_EXTRA+="dtb/nvidia" +makeoptions MODULES_EXTRA+="dtb/omap4" +makeoptions MODULES_EXTRA+="dtb/rpi" +makeoptions MODULES_EXTRA+="dtb/zynq" + +# SOC-specific modules +makeoptions MODULES_EXTRA+="allwinner" +makeoptions MODULES_EXTRA+="arm_ti" +makeoptions MODULES_EXTRA+="imx" + diff --git a/sys/arm/mv/a37x0_gpio.c b/sys/arm/mv/a37x0_gpio.c new file mode 100644 index 000000000000..9a69c9b864d7 --- /dev/null +++ b/sys/arm/mv/a37x0_gpio.c @@ -0,0 +1,352 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2018-2019, Rubicon Communications, LLC (Netgate) + * 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 "gpio_if.h" + +static struct resource_spec a37x0_gpio_res_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Pinctl / GPIO */ + { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* Interrupts control */ + { -1, 0, 0 } +}; + +struct a37x0_gpio_softc { + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + device_t sc_busdev; + int sc_type; + uint32_t sc_max_pins; + uint32_t sc_npins; + struct resource *sc_mem_res[nitems(a37x0_gpio_res_spec) - 1]; +}; + +/* Memory regions. */ +#define A37X0_GPIO 0 +#define A37X0_INTR 1 + +/* North Bridge / South Bridge. */ +#define A37X0_NB_GPIO 1 +#define A37X0_SB_GPIO 2 + +#define A37X0_GPIO_WRITE(_sc, _off, _val) \ + bus_space_write_4((_sc)->sc_bst, (_sc)->sc_bsh, (_off), (_val)) +#define A37X0_GPIO_READ(_sc, _off) \ + bus_space_read_4((_sc)->sc_bst, (_sc)->sc_bsh, (_off)) + +#define A37X0_GPIO_BIT(_p) (1U << ((_p) % 32)) +#define A37X0_GPIO_OUT_EN(_p) (0x0 + ((_p) / 32) * 4) +#define A37X0_GPIO_LATCH(_p) (0x8 + ((_p) / 32) * 4) +#define A37X0_GPIO_INPUT(_p) (0x10 + ((_p) / 32) * 4) +#define A37X0_GPIO_OUTPUT(_p) (0x18 + ((_p) / 32) * 4) +#define A37X0_GPIO_SEL 0x30 + + +static struct ofw_compat_data compat_data[] = { + { "marvell,armada3710-nb-pinctrl", A37X0_NB_GPIO }, + { "marvell,armada3710-sb-pinctrl", A37X0_SB_GPIO }, + { NULL, 0 } +}; + +static phandle_t +a37x0_gpio_get_node(device_t bus, device_t dev) +{ + + return (ofw_bus_get_node(bus)); +} + +static device_t +a37x0_gpio_get_bus(device_t dev) +{ + struct a37x0_gpio_softc *sc; + + sc = device_get_softc(dev); + + return (sc->sc_busdev); +} + +static int +a37x0_gpio_pin_max(device_t dev, int *maxpin) +{ + struct a37x0_gpio_softc *sc; + + sc = device_get_softc(dev); + *maxpin = sc->sc_npins - 1; + + return (0); +} + +static int +a37x0_gpio_pin_getname(device_t dev, uint32_t pin, char *name) +{ + struct a37x0_gpio_softc *sc; + + sc = device_get_softc(dev); + if (pin >= sc->sc_npins) + return (EINVAL); + snprintf(name, GPIOMAXNAME, "pin %d", pin); + + return (0); +} + +static int +a37x0_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) +{ + struct a37x0_gpio_softc *sc; + + sc = device_get_softc(dev); + if (pin >= sc->sc_npins) + return (EINVAL); + *caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; + + return (0); +} + +static int +a37x0_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) +{ + struct a37x0_gpio_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + if (pin >= sc->sc_npins) + return (EINVAL); + reg = A37X0_GPIO_READ(sc, A37X0_GPIO_OUT_EN(pin)); + if ((reg & A37X0_GPIO_BIT(pin)) != 0) + *flags = GPIO_PIN_OUTPUT; + else + *flags = GPIO_PIN_INPUT; + + return (0); +} + +static int +a37x0_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) +{ + struct a37x0_gpio_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + if (pin >= sc->sc_npins) + return (EINVAL); + + reg = A37X0_GPIO_READ(sc, A37X0_GPIO_OUT_EN(pin)); + if (flags & GPIO_PIN_OUTPUT) + reg |= A37X0_GPIO_BIT(pin); + else + reg &= ~A37X0_GPIO_BIT(pin); + A37X0_GPIO_WRITE(sc, A37X0_GPIO_OUT_EN(pin), reg); + + return (0); +} + +static int +a37x0_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) +{ + struct a37x0_gpio_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + if (pin >= sc->sc_npins) + return (EINVAL); + + reg = A37X0_GPIO_READ(sc, A37X0_GPIO_OUT_EN(pin)); + if ((reg & A37X0_GPIO_BIT(pin)) != 0) + reg = A37X0_GPIO_READ(sc, A37X0_GPIO_OUTPUT(pin)); + else + reg = A37X0_GPIO_READ(sc, A37X0_GPIO_INPUT(pin)); + *val = ((reg & A37X0_GPIO_BIT(pin)) != 0) ? 1 : 0; + + return (0); +} + +static int +a37x0_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val) +{ + struct a37x0_gpio_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + if (pin >= sc->sc_npins) + return (EINVAL); + + reg = A37X0_GPIO_READ(sc, A37X0_GPIO_OUTPUT(pin)); + if (val != 0) + reg |= A37X0_GPIO_BIT(pin); + else + reg &= ~A37X0_GPIO_BIT(pin); + A37X0_GPIO_WRITE(sc, A37X0_GPIO_OUTPUT(pin), reg); + + return (0); +} + +static int +a37x0_gpio_pin_toggle(device_t dev, uint32_t pin) +{ + struct a37x0_gpio_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + if (pin >= sc->sc_npins) + return (EINVAL); + + reg = A37X0_GPIO_READ(sc, A37X0_GPIO_OUT_EN(pin)); + if ((reg & A37X0_GPIO_BIT(pin)) == 0) + return (EINVAL); + reg = A37X0_GPIO_READ(sc, A37X0_GPIO_OUTPUT(pin)); + reg ^= A37X0_GPIO_BIT(pin); + A37X0_GPIO_WRITE(sc, A37X0_GPIO_OUTPUT(pin), reg); + + return (0); +} + +static int +a37x0_gpio_probe(device_t dev) +{ + const char *desc; + struct a37x0_gpio_softc *sc; + + if (!OF_hasprop(ofw_bus_get_node(dev), "gpio-controller")) + return (ENXIO); + + sc = device_get_softc(dev); + sc->sc_type = ofw_bus_search_compatible( + device_get_parent(dev), compat_data)->ocd_data; + switch (sc->sc_type) { + case A37X0_NB_GPIO: + sc->sc_max_pins = 36; + desc = "Armada 37x0 North Bridge GPIO Controller"; + break; + case A37X0_SB_GPIO: + sc->sc_max_pins = 30; + desc = "Armada 37x0 South Bridge GPIO Controller"; + break; + default: + return (ENXIO); + } + device_set_desc(dev, desc); + + return (BUS_PROBE_DEFAULT); +} + +static int +a37x0_gpio_attach(device_t dev) +{ + int err, ncells; + pcell_t *ranges; + struct a37x0_gpio_softc *sc; + + sc = device_get_softc(dev); + + /* Read and verify the "gpio-ranges" property. */ + ncells = OF_getencprop_alloc(ofw_bus_get_node(dev), "gpio-ranges", + (void **)&ranges); + if (ncells == -1) + return (ENXIO); + if (ncells != sizeof(*ranges) * 4 || ranges[1] != 0 || ranges[2] != 0) { + OF_prop_free(ranges); + return (ENXIO); + } + sc->sc_npins = ranges[3]; + OF_prop_free(ranges); + + /* Check the number of pins in the DTS vs HW capabilities. */ + if (sc->sc_npins > sc->sc_max_pins) + return (ENXIO); + + err = bus_alloc_resources(dev, a37x0_gpio_res_spec, sc->sc_mem_res); + if (err != 0) { + device_printf(dev, "cannot allocate memory window\n"); + return (ENXIO); + } + sc->sc_bst = rman_get_bustag(sc->sc_mem_res[A37X0_GPIO]); + sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res[A37X0_GPIO]); + + sc->sc_busdev = gpiobus_attach_bus(dev); + if (sc->sc_busdev == NULL) + return (ENXIO); + + return (0); +} + +static int +a37x0_gpio_detach(device_t dev) +{ + + return (EBUSY); +} + +static device_method_t a37x0_gpio_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, a37x0_gpio_probe), + DEVMETHOD(device_attach, a37x0_gpio_attach), + DEVMETHOD(device_detach, a37x0_gpio_detach), + + /* GPIO interface */ + DEVMETHOD(gpio_get_bus, a37x0_gpio_get_bus), + DEVMETHOD(gpio_pin_max, a37x0_gpio_pin_max), + DEVMETHOD(gpio_pin_getname, a37x0_gpio_pin_getname), + DEVMETHOD(gpio_pin_getcaps, a37x0_gpio_pin_getcaps), + DEVMETHOD(gpio_pin_getflags, a37x0_gpio_pin_getflags), + DEVMETHOD(gpio_pin_setflags, a37x0_gpio_pin_setflags), + DEVMETHOD(gpio_pin_get, a37x0_gpio_pin_get), + DEVMETHOD(gpio_pin_set, a37x0_gpio_pin_set), + DEVMETHOD(gpio_pin_toggle, a37x0_gpio_pin_toggle), + + /* ofw_bus interface */ + DEVMETHOD(ofw_bus_get_node, a37x0_gpio_get_node), + + DEVMETHOD_END +}; + +static devclass_t a37x0_gpio_devclass; +static driver_t a37x0_gpio_driver = { + "gpio", + a37x0_gpio_methods, + sizeof(struct a37x0_gpio_softc), +}; + +EARLY_DRIVER_MODULE(a37x0_gpio, simple_mfd, a37x0_gpio_driver, + a37x0_gpio_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST); diff --git a/sys/arm/nvidia/drm2/tegra_bo.c b/sys/arm/nvidia/drm2/tegra_bo.c index 278d9758ee2e..1e721aacf36e 100644 --- a/sys/arm/nvidia/drm2/tegra_bo.c +++ b/sys/arm/nvidia/drm2/tegra_bo.c @@ -67,7 +67,7 @@ tegra_bo_destruct(struct tegra_bo *bo) cdev_pager_free_page(bo->cdev_pager, m); vm_page_lock(m); m->flags &= ~PG_FICTITIOUS; - vm_page_unwire(m, PQ_NONE); + vm_page_unwire_noq(m); vm_page_free(m); vm_page_unlock(m); } diff --git a/sys/arm/ti/am335x/am335x_dmtpps.c b/sys/arm/ti/am335x/am335x_dmtpps.c index 2c4e634a4afc..db4de8a7760c 100644 --- a/sys/arm/ti/am335x/am335x_dmtpps.c +++ b/sys/arm/ti/am335x/am335x_dmtpps.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/arm/ti/ti_i2c.c b/sys/arm/ti/ti_i2c.c index 0893e80b8caa..8f1804493192 100644 --- a/sys/arm/ti/ti_i2c.c +++ b/sys/arm/ti/ti_i2c.c @@ -735,8 +735,6 @@ ti_i2c_deactivate(device_t dev) 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); @@ -925,12 +923,19 @@ ti_i2c_detach(device_t dev) int rv; sc = device_get_softc(dev); - ti_i2c_deactivate(dev); - TI_I2C_LOCK_DESTROY(sc); - if (sc->sc_iicbus && + + if ((rv = bus_generic_detach(dev)) != 0) { + device_printf(dev, "cannot detach child devices\n"); + return (rv); + } + + if (sc->sc_iicbus && (rv = device_delete_child(dev, sc->sc_iicbus)) != 0) return (rv); + ti_i2c_deactivate(dev); + TI_I2C_LOCK_DESTROY(sc); + return (0); } diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c index 6b41dfd59f60..df34873025dd 100644 --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -1410,8 +1410,6 @@ _pmap_unwire_l3(pmap_t pmap, vm_offset_t va, vm_page_t m, struct spglist *free) } pmap_invalidate_page(pmap, va); - vm_wire_sub(1); - /* * Put page on a list so that it is released after * *ALL* TLB shootdown is done @@ -2030,9 +2028,8 @@ reclaim_pv_chunk(pmap_t locked_pmap, struct rwlock **lockp) SLIST_REMOVE_HEAD(&free, plinks.s.ss); /* Recycle a freed page table page. */ m_pc->wire_count = 1; - vm_wire_add(1); } - vm_page_free_pages_toq(&free, false); + vm_page_free_pages_toq(&free, true); return (m_pc); } @@ -2267,6 +2264,8 @@ pmap_pv_demote_l2(pmap_t pmap, vm_offset_t va, vm_paddr_t pa, int bit, field; PMAP_LOCK_ASSERT(pmap, MA_OWNED); + KASSERT((va & L2_OFFSET) == 0, + ("pmap_pv_demote_l2: va is not 2mpage aligned")); KASSERT((pa & L2_OFFSET) == 0, ("pmap_pv_demote_l2: pa is not 2mpage aligned")); CHANGE_PV_LIST_LOCK_TO_PHYS(lockp, pa); @@ -2277,7 +2276,6 @@ pmap_pv_demote_l2(pmap_t pmap, vm_offset_t va, vm_paddr_t pa, * must not be released until the last pv entry is reinstantiated. */ pvh = pa_to_pvh(pa); - va = va & ~L2_OFFSET; pv = pmap_pvh_remove(pvh, pmap, va); KASSERT(pv != NULL, ("pmap_pv_demote_l2: pv not found")); m = PHYS_TO_VM_PAGE(pa); @@ -2401,9 +2399,11 @@ pmap_remove_kernel_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t va) newl2 = ml3pa | L2_TABLE; /* - * Initialize the page table page. + * If this page table page was unmapped by a promotion, then it + * contains valid mappings. Zero it to invalidate those mappings. */ - pagezero((void *)PHYS_TO_DMAP(ml3pa)); + if (ml3->valid != 0) + pagezero((void *)PHYS_TO_DMAP(ml3pa)); /* * Demote the mapping. The caller must have already invalidated the @@ -2431,7 +2431,13 @@ pmap_remove_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t sva, old_l2 = pmap_load_clear(l2); KASSERT((old_l2 & ATTR_DESCR_MASK) == L2_BLOCK, ("pmap_remove_l2: L2e %lx is not a block mapping", old_l2)); - pmap_invalidate_range(pmap, sva, sva + L2_SIZE); + + /* + * Since a promotion must break the 4KB page mappings before making + * the 2MB page mapping, a pmap_invalidate_page() suffices. + */ + pmap_invalidate_page(pmap, sva); + if (old_l2 & ATTR_SW_WIRED) pmap->pm_stats.wired_count -= L2_SIZE / PAGE_SIZE; pmap_resident_count_dec(pmap, L2_SIZE / PAGE_SIZE); @@ -2456,11 +2462,12 @@ pmap_remove_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t sva, } else { ml3 = pmap_remove_pt_page(pmap, sva); if (ml3 != NULL) { + KASSERT(ml3->valid == VM_PAGE_BITS_ALL, + ("pmap_remove_l2: l3 page not promoted")); pmap_resident_count_dec(pmap, 1); KASSERT(ml3->wire_count == NL3PG, ("pmap_remove_l2: l3 page wire count error")); - ml3->wire_count = 1; - vm_page_unwire_noq(ml3); + ml3->wire_count = 0; pmap_add_delayed_free_list(ml3, free, FALSE); } } @@ -2567,8 +2574,8 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) pmap_remove_l2(pmap, l2, sva, pmap_load(l1), &free, &lock); continue; - } else if (pmap_demote_l2_locked(pmap, l2, - sva &~L2_OFFSET, &lock) == NULL) + } else if (pmap_demote_l2_locked(pmap, l2, sva, + &lock) == NULL) continue; l3_paddr = pmap_load(l2); } @@ -2613,7 +2620,7 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) if (lock != NULL) rw_wunlock(lock); PMAP_UNLOCK(pmap); - vm_page_free_pages_toq(&free, false); + vm_page_free_pages_toq(&free, true); } /* @@ -2718,7 +2725,52 @@ pmap_remove_all(vm_page_t m) } vm_page_aflag_clear(m, PGA_WRITEABLE); rw_wunlock(lock); - vm_page_free_pages_toq(&free, false); + vm_page_free_pages_toq(&free, true); +} + +/* + * pmap_protect_l2: do the things to protect a 2MB page in a pmap + */ +static void +pmap_protect_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t sva, pt_entry_t nbits) +{ + pd_entry_t old_l2; + vm_page_t m, mt; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + KASSERT((sva & L2_OFFSET) == 0, + ("pmap_protect_l2: sva is not 2mpage aligned")); + old_l2 = pmap_load(l2); + KASSERT((old_l2 & ATTR_DESCR_MASK) == L2_BLOCK, + ("pmap_protect_l2: L2e %lx is not a block mapping", old_l2)); + + /* + * Return if the L2 entry already has the desired access restrictions + * in place. + */ + if ((old_l2 | nbits) == old_l2) + return; + + /* + * When a dirty read/write superpage mapping is write protected, + * update the dirty field of each of the superpage's constituent 4KB + * pages. + */ + if ((nbits & ATTR_AP(ATTR_AP_RO)) != 0 && + (old_l2 & ATTR_SW_MANAGED) != 0 && + pmap_page_dirty(old_l2)) { + m = PHYS_TO_VM_PAGE(old_l2 & ~ATTR_MASK); + for (mt = m; mt < &m[L2_SIZE / PAGE_SIZE]; mt++) + vm_page_dirty(mt); + } + + pmap_set(l2, nbits); + + /* + * Since a promotion must break the 4KB page mappings before making + * the 2MB page mapping, a pmap_invalidate_page() suffices. + */ + pmap_invalidate_page(pmap, sva); } /* @@ -2738,8 +2790,12 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) return; } - if ((prot & (VM_PROT_WRITE | VM_PROT_EXECUTE)) == - (VM_PROT_WRITE | VM_PROT_EXECUTE)) + nbits = 0; + if ((prot & VM_PROT_WRITE) == 0) + nbits |= ATTR_AP(ATTR_AP_RO); + if ((prot & VM_PROT_EXECUTE) == 0) + nbits |= ATTR_XN; + if (nbits == 0) return; PMAP_LOCK(pmap); @@ -2770,8 +2826,10 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) continue; if ((pmap_load(l2) & ATTR_DESCR_MASK) == L2_BLOCK) { - l3p = pmap_demote_l2(pmap, l2, sva); - if (l3p == NULL) + if (sva + L2_SIZE == va_next && eva >= va_next) { + pmap_protect_l2(pmap, l2, sva, nbits); + continue; + } else if (pmap_demote_l2(pmap, l2, sva) == NULL) continue; } KASSERT((pmap_load(l2) & ATTR_DESCR_MASK) == L2_TABLE, @@ -2783,26 +2841,38 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) va = va_next; for (l3p = pmap_l2_to_l3(l2, sva); sva != va_next; l3p++, sva += L3_SIZE) { + /* + * Go to the next L3 entry if the current one is + * invalid or already has the desired access + * restrictions in place. (The latter case occurs + * frequently. For example, in a "buildworld" + * workload, almost 1 out of 4 L3 entries already + * have the desired restrictions.) + */ l3 = pmap_load(l3p); - if (!pmap_l3_valid(l3)) - continue; - - nbits = 0; - if ((prot & VM_PROT_WRITE) == 0) { - if ((l3 & ATTR_SW_MANAGED) && - pmap_page_dirty(l3)) { - vm_page_dirty(PHYS_TO_VM_PAGE(l3 & - ~ATTR_MASK)); + if (!pmap_l3_valid(l3) || (l3 | nbits) == l3) { + if (va != va_next) { + pmap_invalidate_range(pmap, va, sva); + va = va_next; } - nbits |= ATTR_AP(ATTR_AP_RO); + continue; } - if ((prot & VM_PROT_EXECUTE) == 0) - nbits |= ATTR_XN; + if (va == va_next) + va = sva; + + /* + * When a dirty read/write mapping is write protected, + * update the page's dirty field. + */ + if ((nbits & ATTR_AP(ATTR_AP_RO)) != 0 && + (l3 & ATTR_SW_MANAGED) != 0 && + pmap_page_dirty(l3)) + vm_page_dirty(PHYS_TO_VM_PAGE(l3 & ~ATTR_MASK)); pmap_set(l3p, nbits); - /* XXX: Use pmap_invalidate_range */ - pmap_invalidate_page(pmap, sva); } + if (va != va_next) + pmap_invalidate_range(pmap, va, sva); } PMAP_UNLOCK(pmap); } @@ -2812,12 +2882,15 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) * of idle page table pages. Each of a pmap's page table pages is responsible * for mapping a distinct range of virtual addresses. The pmap's collection is * ordered by this virtual address range. + * + * If "promoted" is false, then the page table page "mpte" must be zero filled. */ static __inline int -pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte) +pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte, bool promoted) { PMAP_LOCK_ASSERT(pmap, MA_OWNED); + mpte->valid = promoted ? VM_PAGE_BITS_ALL : 0; return (vm_radix_insert(&pmap->pm_root, mpte)); } @@ -2962,7 +3035,7 @@ pmap_promote_l2(pmap_t pmap, pd_entry_t *l2, vm_offset_t va, ("pmap_promote_l2: page table page is out of range")); KASSERT(mpte->pindex == pmap_l2_pindex(va), ("pmap_promote_l2: page table page's pindex is wrong")); - if (pmap_insert_pt_page(pmap, mpte)) { + if (pmap_insert_pt_page(pmap, mpte, true)) { atomic_add_long(&pmap_l2_p_failures, 1); CTR2(KTR_PMAP, "pmap_promote_l2: failure for va %#lx in pmap %p", va, @@ -3045,8 +3118,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, if (pde != NULL && lvl == 1) { l2 = pmap_l1_to_l2(pde, va); if ((pmap_load(l2) & ATTR_DESCR_MASK) == L2_BLOCK && - (l3 = pmap_demote_l2_locked(pmap, l2, va & ~L2_OFFSET, - &lock)) != NULL) { + (l3 = pmap_demote_l2_locked(pmap, l2, va, &lock)) != NULL) { l3 = &l3[pmap_l3_index(va)]; if (va < VM_MAXUSER_ADDRESS) { mpte = PHYS_TO_VM_PAGE( @@ -3386,15 +3458,13 @@ pmap_enter_l2(pmap_t pmap, vm_offset_t va, pd_entry_t new_l2, u_int flags, } vm_page_free_pages_toq(&free, true); if (va >= VM_MAXUSER_ADDRESS) { + /* + * Both pmap_remove_l2() and pmap_remove_l3() will + * leave the kernel page table page zero filled. + */ mt = PHYS_TO_VM_PAGE(pmap_load(l2) & ~ATTR_MASK); - if (pmap_insert_pt_page(pmap, mt)) { - /* - * XXX Currently, this can't happen bacuse - * we do not perform pmap_enter(psind == 1) - * on the kernel pmap. - */ + if (pmap_insert_pt_page(pmap, mt, false)) panic("pmap_enter_l2: trie insert failed"); - } } else KASSERT(pmap_load(l2) == 0, ("pmap_enter_l2: non-zero L2 entry %p", l2)); @@ -3603,7 +3673,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, SLIST_INIT(&free); if (pmap_unwire_l3(pmap, va, mpte, &free)) { pmap_invalidate_page(pmap, va); - vm_page_free_pages_toq(&free, false); + vm_page_free_pages_toq(&free, true); } mpte = NULL; } @@ -3697,9 +3767,21 @@ pmap_unwire(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) continue; if ((pmap_load(l2) & ATTR_DESCR_MASK) == L2_BLOCK) { - l3 = pmap_demote_l2(pmap, l2, sva); - if (l3 == NULL) + if ((pmap_load(l2) & ATTR_SW_WIRED) == 0) + panic("pmap_unwire: l2 %#jx is missing " + "ATTR_SW_WIRED", (uintmax_t)pmap_load(l2)); + + /* + * Are we unwiring the entire large page? If not, + * demote the mapping and fall through. + */ + if (sva + L2_SIZE == va_next && eva >= va_next) { + atomic_clear_64(l2, ATTR_SW_WIRED); + pmap->pm_stats.wired_count -= L2_SIZE / + PAGE_SIZE; continue; + } else if (pmap_demote_l2(pmap, l2, sva) == NULL) + panic("pmap_unwire: demotion failed"); } KASSERT((pmap_load(l2) & ATTR_DESCR_MASK) == L2_TABLE, ("pmap_unwire: Invalid l2 entry after demotion")); @@ -3715,11 +3797,11 @@ pmap_unwire(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) "ATTR_SW_WIRED", (uintmax_t)pmap_load(l3)); /* - * PG_W must be cleared atomically. Although the pmap - * lock synchronizes access to PG_W, another processor - * could be setting PG_M and/or PG_A concurrently. + * ATTR_SW_WIRED must be cleared atomically. Although + * the pmap lock synchronizes access to ATTR_SW_WIRED, + * the System MMU may write to the entry concurrently. */ - atomic_clear_long(l3, ATTR_SW_WIRED); + atomic_clear_64(l3, ATTR_SW_WIRED); pmap->pm_stats.wired_count--; } } @@ -4053,7 +4135,7 @@ pmap_remove_pages(pmap_t pmap) switch (lvl) { case 1: for (mt = m; mt < &m[L2_SIZE / PAGE_SIZE]; mt++) - vm_page_dirty(m); + vm_page_dirty(mt); break; case 2: vm_page_dirty(m); @@ -4081,11 +4163,12 @@ pmap_remove_pages(pmap_t pmap) ml3 = pmap_remove_pt_page(pmap, pv->pv_va); if (ml3 != NULL) { + KASSERT(ml3->valid == VM_PAGE_BITS_ALL, + ("pmap_remove_pages: l3 page not promoted")); pmap_resident_count_dec(pmap,1); KASSERT(ml3->wire_count == NL3PG, ("pmap_remove_pages: l3 page wire count error")); - ml3->wire_count = 1; - vm_page_unwire_noq(ml3); + ml3->wire_count = 0; pmap_add_delayed_free_list(ml3, &free, FALSE); } @@ -4123,7 +4206,7 @@ pmap_remove_pages(pmap_t pmap) if (lock != NULL) rw_wunlock(lock); PMAP_UNLOCK(pmap); - vm_page_free_pages_toq(&free, false); + vm_page_free_pages_toq(&free, true); } /* @@ -4324,8 +4407,7 @@ pmap_remove_write(vm_page_t m) va = pv->pv_va; pte = pmap_pte(pmap, pv->pv_va, &lvl); if ((pmap_load(pte) & ATTR_AP_RW_BIT) == ATTR_AP(ATTR_AP_RW)) - pmap_demote_l2_locked(pmap, pte, va & ~L2_OFFSET, - &lock); + (void)pmap_demote_l2_locked(pmap, pte, va, &lock); KASSERT(lock == VM_PAGE_TO_PV_LIST_LOCK(m), ("inconsistent pv lock %p %p for page %p", lock, VM_PAGE_TO_PV_LIST_LOCK(m), m)); @@ -4562,7 +4644,6 @@ pmap_ts_referenced(vm_page_t m) */ pmap_remove_l3(pmap, pte, pv->pv_va, tpde, &free, &lock); - pmap_invalidate_page(pmap, pv->pv_va); cleared++; if (pvf == pv) pvf = NULL; @@ -4584,7 +4665,7 @@ pmap_ts_referenced(vm_page_t m) not_cleared < PMAP_TS_REFERENCED_MAX); out: rw_wunlock(lock); - vm_page_free_pages_toq(&free, false); + vm_page_free_pages_toq(&free, true); return (cleared + not_cleared); } @@ -4899,7 +4980,7 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode) pte = pmap_l1_to_l2(pte, tmpva); case 2: newpte = pmap_demote_l2(kernel_pmap, pte, - tmpva & ~L2_OFFSET); + tmpva); if (newpte == NULL) return (EINVAL); pte = pmap_l2_to_l3(pte, tmpva); @@ -4998,6 +5079,18 @@ pmap_demote_l1(pmap_t pmap, pt_entry_t *l1, vm_offset_t va) return (l2); } +static void +pmap_demote_l2_abort(pmap_t pmap, vm_offset_t va, pt_entry_t *l2, + struct rwlock **lockp) +{ + struct spglist free; + + SLIST_INIT(&free); + (void)pmap_remove_l2(pmap, l2, va, pmap_load(pmap_l1(pmap, va)), &free, + lockp); + vm_page_free_pages_toq(&free, true); +} + /* * Create an L3 table to map all addresses within an L2 mapping. */ @@ -5016,8 +5109,7 @@ pmap_demote_l2_locked(pmap_t pmap, pt_entry_t *l2, vm_offset_t va, oldl2 = pmap_load(l2); KASSERT((oldl2 & ATTR_DESCR_MASK) == L2_BLOCK, ("pmap_demote_l2: Demoting a non-block entry")); - KASSERT((va & L2_OFFSET) == 0, - ("pmap_demote_l2: Invalid virtual address %#lx", va)); + va &= ~L2_OFFSET; tmpl2 = 0; if (va <= (vm_offset_t)l2 && va + L2_SIZE > (vm_offset_t)l2) { @@ -5026,17 +5118,61 @@ pmap_demote_l2_locked(pmap_t pmap, pt_entry_t *l2, vm_offset_t va, return (NULL); } + /* + * Invalidate the 2MB page mapping and return "failure" if the + * mapping was never accessed. + */ + if ((oldl2 & ATTR_AF) == 0) { + KASSERT((oldl2 & ATTR_SW_WIRED) == 0, + ("pmap_demote_l2: a wired mapping is missing ATTR_AF")); + pmap_demote_l2_abort(pmap, va, l2, lockp); + CTR2(KTR_PMAP, "pmap_demote_l2: failure for va %#lx in pmap %p", + va, pmap); + goto fail; + } + if ((ml3 = pmap_remove_pt_page(pmap, va)) == NULL) { + KASSERT((oldl2 & ATTR_SW_WIRED) == 0, + ("pmap_demote_l2: page table page for a wired mapping" + " is missing")); + + /* + * If the page table page is missing and the mapping + * is for a kernel address, the mapping must belong to + * the direct map. Page table pages are preallocated + * for every other part of the kernel address space, + * so the direct map region is the only part of the + * kernel address space that must be handled here. + */ + KASSERT(va < VM_MAXUSER_ADDRESS || VIRT_IN_DMAP(va), + ("pmap_demote_l2: No saved mpte for va %#lx", va)); + + /* + * If the 2MB page mapping belongs to the direct map + * region of the kernel's address space, then the page + * allocation request specifies the highest possible + * priority (VM_ALLOC_INTERRUPT). Otherwise, the + * priority is normal. + */ ml3 = vm_page_alloc(NULL, pmap_l2_pindex(va), (VIRT_IN_DMAP(va) ? VM_ALLOC_INTERRUPT : VM_ALLOC_NORMAL) | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED); + + /* + * If the allocation of the new page table page fails, + * invalidate the 2MB page mapping and return "failure". + */ if (ml3 == NULL) { + pmap_demote_l2_abort(pmap, va, l2, lockp); CTR2(KTR_PMAP, "pmap_demote_l2: failure for va %#lx" " in pmap %p", va, pmap); goto fail; } - if (va < VM_MAXUSER_ADDRESS) + + if (va < VM_MAXUSER_ADDRESS) { + ml3->wire_count = NL3PG; pmap_resident_count_inc(pmap, 1); + } } l3phys = VM_PAGE_TO_PHYS(ml3); @@ -5048,10 +5184,10 @@ pmap_demote_l2_locked(pmap_t pmap, pt_entry_t *l2, vm_offset_t va, newl3 = (oldl2 & (ATTR_MASK & ~ATTR_DESCR_MASK)) | L3_PAGE; /* - * If the page table page is new, initialize it. + * If the page table page is not leftover from an earlier promotion, + * initialize it. */ - if (ml3->wire_count == 1) { - ml3->wire_count = NL3PG; + if (ml3->valid == 0) { for (i = 0; i < Ln_ENTRIES; i++) { l3[i] = newl3 | phys; phys += L3_SIZE; @@ -5081,6 +5217,10 @@ pmap_demote_l2_locked(pmap_t pmap, pt_entry_t *l2, vm_offset_t va, if ((oldl2 & ATTR_SW_MANAGED) != 0) reserve_pv_entries(pmap, Ln_ENTRIES - 1, lockp); + /* + * Pass PAGE_SIZE so that a single TLB invalidation is performed on + * the 2MB page mapping. + */ pmap_update_entry(pmap, l2, l3phys | L2_TABLE, va, PAGE_SIZE); /* diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC index b1018a742508..8e3f04fe1db1 100644 --- a/sys/arm64/conf/GENERIC +++ b/sys/arm64/conf/GENERIC @@ -223,6 +223,7 @@ device a10_codec device a31_dmac # GPIO / PINCTRL +device a37x0_gpio # Marvell Armada 37x0 GPIO controller device aw_gpio # Allwinner GPIO controller device gpio device gpioled diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h index 730b7a2b61de..271dc93810f5 100644 --- a/sys/arm64/include/armreg.h +++ b/sys/arm64/include/armreg.h @@ -36,12 +36,12 @@ #define INSN_SIZE 4 #define READ_SPECIALREG(reg) \ -({ uint64_t val; \ - __asm __volatile("mrs %0, " __STRING(reg) : "=&r" (val)); \ - val; \ +({ uint64_t _val; \ + __asm __volatile("mrs %0, " __STRING(reg) : "=&r" (_val)); \ + _val; \ }) -#define WRITE_SPECIALREG(reg, val) \ - __asm __volatile("msr " __STRING(reg) ", %0" : : "r"((uint64_t)val)) +#define WRITE_SPECIALREG(reg, _val) \ + __asm __volatile("msr " __STRING(reg) ", %0" : : "r"((uint64_t)_val)) /* CNTHCTL_EL2 - Counter-timer Hypervisor Control register */ #define CNTHCTL_EVNTI_MASK (0xf << 4) /* Bit to trigger event stream */ diff --git a/sys/arm64/rockchip/if_dwc_rk.c b/sys/arm64/rockchip/if_dwc_rk.c index 3a5cbdab8044..1b597bfe6592 100644 --- a/sys/arm64/rockchip/if_dwc_rk.c +++ b/sys/arm64/rockchip/if_dwc_rk.c @@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$"); #define RK3328_GRF_MACPHY_CON3 0x0B0C #define RK3328_GRF_MACPHY_STATUS 0x0B10 +#ifdef notyet static void rk3328_set_delays(struct syscon *grf, phandle_t node) { @@ -82,6 +83,7 @@ rk3328_set_delays(struct syscon *grf, phandle_t node) SYSCON_WRITE_4(grf, RK3328_GRF_MAC_CON0, tx | rx | 0xFFFF0000); } +#endif #define RK3399_GRF_SOC_CON6 0xc218 #define RK3399_GRF_SOC_CON6_TX_MASK 0x7F @@ -89,6 +91,7 @@ rk3328_set_delays(struct syscon *grf, phandle_t node) #define RK3399_GRF_SOC_CON6_RX_MASK 0x7F #define RK3399_GRF_SOC_CON6_RX_SHIFT 8 +#ifdef notyet static void rk3399_set_delays(struct syscon *grf, phandle_t node) { @@ -106,6 +109,7 @@ rk3399_set_delays(struct syscon *grf, phandle_t node) SYSCON_WRITE_4(grf, RK3399_GRF_SOC_CON6, tx | rx | 0xFFFF0000); } +#endif static int if_dwc_rk_probe(device_t dev) diff --git a/sys/cam/cam_sim.c b/sys/cam/cam_sim.c index 35cd5c232a33..7527928ce2a7 100644 --- a/sys/cam/cam_sim.c +++ b/sys/cam/cam_sim.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -82,6 +83,7 @@ cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll, sim->sim_name = sim_name; sim->softc = softc; sim->path_id = CAM_PATH_ANY; + sim->sim_dev = NULL; /* set only by cam_sim_alloc_dev */ sim->unit_number = unit; sim->bus_id = 0; /* set in xpt_bus_register */ sim->max_tagged_dev_openings = max_tagged_dev_transactions; @@ -100,6 +102,25 @@ cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll, return (sim); } +struct cam_sim * +cam_sim_alloc_dev(sim_action_func sim_action, sim_poll_func sim_poll, + const char *sim_name, void *softc, device_t dev, + struct mtx *mtx, int max_dev_transactions, + int max_tagged_dev_transactions, struct cam_devq *queue) +{ + struct cam_sim *sim; + + KASSERT(dev != NULL, ("%s: dev is null for sim_name %s softc %p\n", + __func__, sim_name, softc)); + + sim = cam_sim_alloc(sim_action, sim_poll, sim_name, softc, + device_get_unit(dev), mtx, max_dev_transactions, + max_tagged_dev_transactions, queue); + if (sim != NULL) + sim->sim_dev = dev; + return (sim); +} + void cam_sim_free(struct cam_sim *sim, int free_devq) { diff --git a/sys/cam/cam_sim.h b/sys/cam/cam_sim.h index 3685f70f0954..8474203b6d26 100644 --- a/sys/cam/cam_sim.h +++ b/sys/cam/cam_sim.h @@ -62,6 +62,15 @@ struct cam_sim * cam_sim_alloc(sim_action_func sim_action, int max_dev_transactions, int max_tagged_dev_transactions, struct cam_devq *queue); +struct cam_sim * cam_sim_alloc_dev(sim_action_func sim_action, + sim_poll_func sim_poll, + const char *sim_name, + void *softc, + device_t dev, + struct mtx *mtx, + int max_dev_transactions, + int max_tagged_dev_transactions, + struct cam_devq *queue); void cam_sim_free(struct cam_sim *sim, int free_devq); void cam_sim_hold(struct cam_sim *sim); void cam_sim_release(struct cam_sim *sim); @@ -109,6 +118,7 @@ struct cam_sim { struct callout callout; struct cam_devq *devq; /* Device Queue to use for this SIM */ int refcount; /* References to the SIM. */ + device_t sim_dev; /* For attached peripherals. */ }; #define CAM_SIM_LOCK(sim) mtx_lock((sim)->mtx) diff --git a/sys/cam/nvme/nvme_xpt.c b/sys/cam/nvme/nvme_xpt.c index e555ecbbddc2..32a8186cec06 100644 --- a/sys/cam/nvme/nvme_xpt.c +++ b/sys/cam/nvme/nvme_xpt.c @@ -722,6 +722,8 @@ nvme_announce_periph(struct cam_periph *periph) struct ccb_trans_settings cts; struct cam_path *path = periph->path; struct ccb_trans_settings_nvme *nvmex; + struct sbuf sb; + char buffer[120]; cam_periph_assert(periph, MA_OWNED); @@ -736,13 +738,18 @@ nvme_announce_periph(struct cam_periph *periph) /* Ask the SIM for its base transfer speed */ xpt_path_inq(&cpi, periph->path); - printf("%s%d: nvme version %d.%d x%d (max x%d) lanes PCIe Gen%d (max Gen%d) link", + sbuf_new(&sb, buffer, sizeof(buffer), SBUF_FIXEDLEN); + sbuf_printf(&sb, "%s%d: nvme version %d.%d", periph->periph_name, periph->unit_number, NVME_MAJOR(nvmex->spec), - NVME_MINOR(nvmex->spec), - nvmex->lanes, nvmex->max_lanes, - nvmex->speed, nvmex->max_speed); - printf("\n"); + NVME_MINOR(nvmex->spec)); + if (nvmex->valid & CTS_NVME_VALID_LINK) + sbuf_printf(&sb, " x%d (max x%d) lanes PCIe Gen%d (max Gen%d) link", + nvmex->lanes, nvmex->max_lanes, + nvmex->speed, nvmex->max_speed); + sbuf_printf(&sb, "\n"); + sbuf_finish(&sb); + sbuf_putbuf(&sb); } static void diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c index 66ff056ff2e9..2aa67a331566 100644 --- a/sys/cam/scsi/scsi_xpt.c +++ b/sys/cam/scsi/scsi_xpt.c @@ -1603,7 +1603,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb) start = strspn(serial_buf->serial_num, " "); slen = serial_buf->length - start; if (slen <= 0) { - /* + /* * SPC5r05 says that an all-space serial * number means no product serial number * is available @@ -2116,7 +2116,7 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb) CAM_GET_LUN(target->luns, 0, first); if (first == 0 && scan_info->lunindex[target_id] == 0) { scan_info->lunindex[target_id]++; - } + } /* * Skip any LUNs that the HBA can't deal with. @@ -2601,7 +2601,7 @@ scsi_dev_advinfo(union ccb *start_ccb) * We fetch extended inquiry data during probe, if * available. We don't allow changing it. */ - if (cdai->flags & CDAI_FLAG_STORE) + if (cdai->flags & CDAI_FLAG_STORE) return; cdai->provsiz = device->ext_inq_len; if (device->ext_inq_len == 0) @@ -2993,7 +2993,7 @@ scsi_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, */ if (async_code == AC_SENT_BDR || async_code == AC_BUS_RESET) { - cam_freeze_devq(&newpath); + cam_freeze_devq(&newpath); cam_release_devq(&newpath, RELSIM_RELEASE_AFTER_TIMEOUT, /*reduction*/0, @@ -3051,7 +3051,7 @@ _scsi_announce_periph(struct cam_periph *periph, u_int *speed, u_int *freq, stru cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); - /* Report connection speed */ + /* Report connection speed */ *speed = cpi.base_transfer_speed; *freq = 0; diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c index 3ac3becc28ba..592005b022a3 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c @@ -1125,31 +1125,17 @@ fasttrap_enable_callbacks(void) static void fasttrap_disable_callbacks(void) { -#ifdef illumos - ASSERT(MUTEX_HELD(&cpu_lock)); -#endif - - mutex_enter(&fasttrap_count_mtx); ASSERT(fasttrap_pid_count > 0); fasttrap_pid_count--; if (fasttrap_pid_count == 0) { -#ifdef illumos - cpu_t *cur, *cpu = CPU; - - for (cur = cpu->cpu_next_onln; cur != cpu; - cur = cur->cpu_next_onln) { - rw_enter(&cur->cpu_ft_lock, RW_WRITER); - } -#endif + /* + * Synchronize with the breakpoint handler, which is careful to + * enable interrupts only after loading the hook pointer. + */ + dtrace_sync(); dtrace_pid_probe_ptr = NULL; dtrace_return_probe_ptr = NULL; -#ifdef illumos - for (cur = cpu->cpu_next_onln; cur != cpu; - cur = cur->cpu_next_onln) { - rw_exit(&cur->cpu_ft_lock); - } -#endif } mutex_exit(&fasttrap_count_mtx); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c index 0a62df056071..d685f7e39ab7 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c @@ -1233,6 +1233,12 @@ sysctl_vfs_zfs_arc_meta_limit(SYSCTL_HANDLER_ARGS) return (EINVAL); arc_meta_limit = val; + + mutex_enter(&arc_adjust_lock); + arc_adjust_needed = B_TRUE; + mutex_exit(&arc_adjust_lock); + zthr_wakeup(arc_adjust_zthr); + return (0); } @@ -1294,6 +1300,11 @@ sysctl_vfs_zfs_arc_max(SYSCTL_HANDLER_ARGS) zfs_arc_max = arc_c; + mutex_enter(&arc_adjust_lock); + arc_adjust_needed = B_TRUE; + mutex_exit(&arc_adjust_lock); + zthr_wakeup(arc_adjust_zthr); + return (0); } @@ -1560,14 +1571,14 @@ static kmutex_t l2arc_feed_thr_lock; static kcondvar_t l2arc_feed_thr_cv; static uint8_t l2arc_thread_exit; -static abd_t *arc_get_data_abd(arc_buf_hdr_t *, uint64_t, void *); +static abd_t *arc_get_data_abd(arc_buf_hdr_t *, uint64_t, void *, boolean_t); static void *arc_get_data_buf(arc_buf_hdr_t *, uint64_t, void *); -static void arc_get_data_impl(arc_buf_hdr_t *, uint64_t, void *); +static void arc_get_data_impl(arc_buf_hdr_t *, uint64_t, void *, boolean_t); static void arc_free_data_abd(arc_buf_hdr_t *, abd_t *, uint64_t, void *); static void arc_free_data_buf(arc_buf_hdr_t *, void *, uint64_t, void *); static void arc_free_data_impl(arc_buf_hdr_t *hdr, uint64_t size, void *tag); static void arc_hdr_free_pabd(arc_buf_hdr_t *); -static void arc_hdr_alloc_pabd(arc_buf_hdr_t *); +static void arc_hdr_alloc_pabd(arc_buf_hdr_t *, boolean_t); static void arc_access(arc_buf_hdr_t *, kmutex_t *); static boolean_t arc_is_overflowing(); static void arc_buf_watch(arc_buf_t *); @@ -3353,14 +3364,14 @@ arc_buf_destroy_impl(arc_buf_t *buf) } static void -arc_hdr_alloc_pabd(arc_buf_hdr_t *hdr) +arc_hdr_alloc_pabd(arc_buf_hdr_t *hdr, boolean_t do_adapt) { ASSERT3U(HDR_GET_LSIZE(hdr), >, 0); ASSERT(HDR_HAS_L1HDR(hdr)); ASSERT(!HDR_SHARED_DATA(hdr)); ASSERT3P(hdr->b_l1hdr.b_pabd, ==, NULL); - hdr->b_l1hdr.b_pabd = arc_get_data_abd(hdr, arc_hdr_size(hdr), hdr); + hdr->b_l1hdr.b_pabd = arc_get_data_abd(hdr, arc_hdr_size(hdr), hdr, do_adapt); hdr->b_l1hdr.b_byteswap = DMU_BSWAP_NUMFUNCS; ASSERT3P(hdr->b_l1hdr.b_pabd, !=, NULL); @@ -3424,7 +3435,7 @@ arc_hdr_alloc(uint64_t spa, int32_t psize, int32_t lsize, * the compressed or uncompressed data depending on the block * it references and compressed arc enablement. */ - arc_hdr_alloc_pabd(hdr); + arc_hdr_alloc_pabd(hdr, B_TRUE); ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt)); return (hdr); @@ -5129,7 +5140,7 @@ static boolean_t arc_is_overflowing(void) { /* Always allow at least one block of overflow */ - uint64_t overflow = MAX(SPA_MAXBLOCKSIZE, + int64_t overflow = MAX(SPA_MAXBLOCKSIZE, arc_c >> zfs_arc_overflow_shift); /* @@ -5141,15 +5152,15 @@ arc_is_overflowing(void) * in the ARC. In practice, that's in the tens of MB, which is low * enough to be safe. */ - return (aggsum_lower_bound(&arc_size) >= arc_c + overflow); + return (aggsum_lower_bound(&arc_size) >= (int64_t)arc_c + overflow); } static abd_t * -arc_get_data_abd(arc_buf_hdr_t *hdr, uint64_t size, void *tag) +arc_get_data_abd(arc_buf_hdr_t *hdr, uint64_t size, void *tag, boolean_t do_adapt) { arc_buf_contents_t type = arc_buf_type(hdr); - arc_get_data_impl(hdr, size, tag); + arc_get_data_impl(hdr, size, tag, do_adapt); if (type == ARC_BUFC_METADATA) { return (abd_alloc(size, B_TRUE)); } else { @@ -5163,7 +5174,7 @@ arc_get_data_buf(arc_buf_hdr_t *hdr, uint64_t size, void *tag) { arc_buf_contents_t type = arc_buf_type(hdr); - arc_get_data_impl(hdr, size, tag); + arc_get_data_impl(hdr, size, tag, B_TRUE); if (type == ARC_BUFC_METADATA) { return (zio_buf_alloc(size)); } else { @@ -5179,12 +5190,13 @@ arc_get_data_buf(arc_buf_hdr_t *hdr, uint64_t size, void *tag) * limit, we'll only signal the reclaim thread and continue on. */ static void -arc_get_data_impl(arc_buf_hdr_t *hdr, uint64_t size, void *tag) +arc_get_data_impl(arc_buf_hdr_t *hdr, uint64_t size, void *tag, boolean_t do_adapt) { arc_state_t *state = hdr->b_l1hdr.b_state; arc_buf_contents_t type = arc_buf_type(hdr); - arc_adapt(size, state); + if (do_adapt) + arc_adapt(size, state); /* * If arc_size is currently overflowing, and has grown past our @@ -5257,7 +5269,7 @@ arc_get_data_impl(arc_buf_hdr_t *hdr, uint64_t size, void *tag) * If we are growing the cache, and we are adding anonymous * data, and we have outgrown arc_p, update arc_p */ - if (aggsum_compare(&arc_size, arc_c) < 0 && + if (aggsum_upper_bound(&arc_size) < arc_c && hdr->b_l1hdr.b_state == arc_anon && (refcount_count(&arc_anon->arcs_size) + refcount_count(&arc_mru->arcs_size) > arc_p)) @@ -5935,8 +5947,9 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_read_done_func_t *done, * do this after we've called arc_access() to * avoid hitting an assert in remove_reference(). */ + arc_adapt(arc_hdr_size(hdr), hdr->b_l1hdr.b_state); arc_access(hdr, hash_lock); - arc_hdr_alloc_pabd(hdr); + arc_hdr_alloc_pabd(hdr, B_FALSE); } ASSERT3P(hdr->b_l1hdr.b_pabd, !=, NULL); size = arc_hdr_size(hdr); @@ -6350,7 +6363,7 @@ arc_release(arc_buf_t *buf, void *tag) if (arc_can_share(hdr, lastbuf)) { arc_share_buf(hdr, lastbuf); } else { - arc_hdr_alloc_pabd(hdr); + arc_hdr_alloc_pabd(hdr, B_TRUE); abd_copy_from_buf(hdr->b_l1hdr.b_pabd, buf->b_data, psize); } @@ -6513,7 +6526,7 @@ arc_write_ready(zio_t *zio) * the data into it; otherwise, we share the data directly if we can. */ if (zfs_abd_scatter_enabled || !arc_can_share(hdr, buf)) { - arc_hdr_alloc_pabd(hdr); + arc_hdr_alloc_pabd(hdr, B_TRUE); /* * Ideally, we would always copy the io_abd into b_pabd, but the diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c index fcb1f3487b31..c611b40440e4 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c @@ -259,7 +259,9 @@ int zfs_metaslab_switch_threshold = 2; * Internal switch to enable/disable the metaslab allocation tracing * facility. */ +#ifdef _METASLAB_TRACING boolean_t metaslab_trace_enabled = B_TRUE; +#endif /* * Maximum entries that the metaslab allocation tracing facility will keep @@ -269,7 +271,9 @@ boolean_t metaslab_trace_enabled = B_TRUE; * to every exceed this value. In debug mode, the system will panic if this * limit is ever reached allowing for further investigation. */ +#ifdef _METASLAB_TRACING uint64_t metaslab_trace_max_entries = 5000; +#endif static uint64_t metaslab_weight(metaslab_t *); static void metaslab_set_fragmentation(metaslab_t *); @@ -277,8 +281,9 @@ static void metaslab_free_impl(vdev_t *, uint64_t, uint64_t, boolean_t); static void metaslab_check_free_impl(vdev_t *, uint64_t, uint64_t); static void metaslab_passivate(metaslab_t *msp, uint64_t weight); static uint64_t metaslab_weight_from_range_tree(metaslab_t *msp); - +#ifdef _METASLAB_TRACING kmem_cache_t *metaslab_alloc_trace_cache; +#endif /* * ========================================================================== @@ -2797,6 +2802,7 @@ metaslab_distance(metaslab_t *msp, dva_t *dva) * Metaslab allocation tracing facility * ========================================================================== */ +#ifdef _METASLAB_TRACING kstat_t *metaslab_trace_ksp; kstat_named_t metaslab_trace_over_limit; @@ -2901,6 +2907,32 @@ metaslab_trace_fini(zio_alloc_list_t *zal) zal->zal_size = 0; } +#else + +#define metaslab_trace_add(zal, mg, msp, psize, id, off, alloc) + +void +metaslab_alloc_trace_init(void) +{ +} + +void +metaslab_alloc_trace_fini(void) +{ +} + +void +metaslab_trace_init(zio_alloc_list_t *zal) +{ +} + +void +metaslab_trace_fini(zio_alloc_list_t *zal) +{ +} + +#endif /* _METASLAB_TRACING */ + /* * ========================================================================== * Metaslab block operations diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/multilist.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/multilist.h index a2031da77daa..7f386fb7c3be 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/multilist.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/multilist.h @@ -44,11 +44,10 @@ struct multilist_sublist { */ list_t mls_list; /* - * Pad to cache line (64 bytes), in an effort to try and prevent - * cache line contention. + * Pad to cache line, in an effort to try and prevent cache line + * contention. */ - uint8_t mls_pad[24]; -}; +} __aligned(CACHE_LINE_SIZE); struct multilist { /* diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c index b53ec7ffafc8..ef2d2008e458 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c @@ -815,6 +815,18 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio) do { dio = nio; nio = AVL_NEXT(t, dio); + zio_add_child(dio, aio); + vdev_queue_io_remove(vq, dio); + } while (dio != last); + + /* + * We need to drop the vdev queue's lock during zio_execute() to + * avoid a deadlock that we could encounter due to lock order + * reversal between vq_lock and io_lock in zio_change_priority(). + * Use the dropped lock to do memory copy without congestion. + */ + mutex_exit(&vq->vq_lock); + while ((dio = zio_walk_parents(aio, &zl)) != NULL) { ASSERT3U(dio->io_type, ==, aio->io_type); if (dio->io_flags & ZIO_FLAG_NODATA) { @@ -826,16 +838,6 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio) dio->io_offset - aio->io_offset, 0, dio->io_size); } - zio_add_child(dio, aio); - vdev_queue_io_remove(vq, dio); - } while (dio != last); - - /* - * We need to drop the vdev queue's lock to avoid a deadlock that we - * could encounter since this I/O will complete immediately. - */ - mutex_exit(&vq->vq_lock); - while ((dio = zio_walk_parents(aio, &zl)) != NULL) { zio_vdev_io_bypass(dio); zio_execute(dio); } diff --git a/sys/compat/linuxkpi/common/include/linux/gfp.h b/sys/compat/linuxkpi/common/include/linux/gfp.h index a20e3606ca05..49fefb4df610 100644 --- a/sys/compat/linuxkpi/common/include/linux/gfp.h +++ b/sys/compat/linuxkpi/common/include/linux/gfp.h @@ -52,12 +52,15 @@ #define __GFP_RETRY_MAYFAIL 0 #define __GFP_MOVABLE 0 #define __GFP_COMP 0 -#define __GFP_KSWAPD_RECLAIM 0 +#define __GFP_KSWAPD_RECLAIM 0 #define __GFP_IO 0 #define __GFP_NO_KSWAPD 0 #define __GFP_WAIT M_WAITOK #define __GFP_DMA32 (1U << 24) /* LinuxKPI only */ +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION == 50000 +#define __GFP_NOTWIRED (1U << 25) +#endif #define __GFP_BITS_SHIFT 25 #define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1) #define __GFP_NOFAIL M_WAITOK @@ -74,7 +77,7 @@ #define GFP_TEMPORARY M_NOWAIT #define GFP_NATIVE_MASK (M_NOWAIT | M_WAITOK | M_USE_RESERVE | M_ZERO) #define GFP_TRANSHUGE 0 -#define GFP_TRANSHUGE_LIGHT 0 +#define GFP_TRANSHUGE_LIGHT 0 CTASSERT((__GFP_DMA32 & GFP_NATIVE_MASK) == 0); CTASSERT((__GFP_BITS_MASK & GFP_NATIVE_MASK) == GFP_NATIVE_MASK); @@ -98,6 +101,9 @@ static inline struct page * alloc_page(gfp_t flags) { +#ifdef __GFP_NOTWIRED + flags |= __GFP_NOTWIRED; +#endif return (linux_alloc_pages(flags, 0)); } @@ -105,6 +111,9 @@ static inline struct page * alloc_pages(gfp_t flags, unsigned int order) { +#ifdef __GFP_NOTWIRED + flags |= __GFP_NOTWIRED; +#endif return (linux_alloc_pages(flags, order)); } @@ -112,6 +121,9 @@ static inline struct page * alloc_pages_node(int node_id, gfp_t flags, unsigned int order) { +#ifdef __GFP_NOTWIRED + flags |= __GFP_NOTWIRED; +#endif return (linux_alloc_pages(flags, order)); } diff --git a/sys/compat/linuxkpi/common/src/linux_page.c b/sys/compat/linuxkpi/common/src/linux_page.c index 59ed47c175b4..3c0ea09f5431 100644 --- a/sys/compat/linuxkpi/common/src/linux_page.c +++ b/sys/compat/linuxkpi/common/src/linux_page.c @@ -91,9 +91,14 @@ linux_alloc_pages(gfp_t flags, unsigned int order) if (PMAP_HAS_DMAP) { unsigned long npages = 1UL << order; - int req = (flags & M_ZERO) ? (VM_ALLOC_ZERO | VM_ALLOC_NOOBJ | - VM_ALLOC_NORMAL) : (VM_ALLOC_NOOBJ | VM_ALLOC_NORMAL); + int req = VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_NORMAL; +#ifdef __GFP_NOTWIRED + if ((flags & __GFP_NOTWIRED) != 0) + req &= ~VM_ALLOC_WIRED; +#endif + if ((flags & M_ZERO) != 0) + req |= VM_ALLOC_ZERO; if (order == 0 && (flags & GFP_DMA32) == 0) { page = vm_page_alloc(NULL, 0, req); if (page == NULL) @@ -154,7 +159,8 @@ linux_free_pages(vm_page_t page, unsigned int order) vm_page_t pgo = page + x; vm_page_lock(pgo); - vm_page_free(pgo); + if (vm_page_unwire_noq(pgo)) + vm_page_free(pgo); vm_page_unlock(pgo); } } else { @@ -311,7 +317,7 @@ linux_shmem_read_mapping_page_gfp(vm_object_t obj, int pindex, gfp_t gfp) rv = vm_pager_get_pages(obj, &page, 1, NULL, NULL); if (rv != VM_PAGER_OK) { vm_page_lock(page); - vm_page_unwire(page, PQ_NONE); + vm_page_unwire_noq(page); vm_page_free(page); vm_page_unlock(page); VM_OBJECT_WUNLOCK(obj); diff --git a/sys/conf/files b/sys/conf/files index 3153cddad948..dd67e0ec7a68 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -68,6 +68,16 @@ usbdevs_data.h optional usb \ compile-with "${AWK} -f $S/tools/usbdevs2h.awk $S/dev/usb/usbdevs -d" \ no-obj no-implicit-rule before-depend \ clean "usbdevs_data.h" +sdiodevs.h optional mmccam \ + dependency "$S/tools/sdiodevs2h.awk $S/dev/sdio/sdiodevs" \ + compile-with "${AWK} -f $S/tools/sdiodevs2h.awk $S/dev/sdio/sdiodevs -h" \ + no-obj no-implicit-rule before-depend \ + clean "sdiodevs.h" +sdiodevs_data.h optional mmccam \ + dependency "$S/tools/sdiodevs2h.awk $S/dev/sdio/sdiodevs" \ + compile-with "${AWK} -f $S/tools/sdiodevs2h.awk $S/dev/sdio/sdiodevs -d" \ + no-obj no-implicit-rule before-depend \ + clean "sdiodevs_data.h" cam/cam.c optional scbus cam/cam_compat.c optional scbus cam/cam_iosched.c optional scbus @@ -2690,11 +2700,11 @@ dev/puc/puc.c optional puc dev/puc/puc_cfg.c optional puc dev/puc/puc_pccard.c optional puc pccard dev/puc/puc_pci.c optional puc pci -dev/pwm/pwmc.c optional pwm -dev/pwm/pwmbus.c optional pwm -dev/pwm/pwm_if.m optional pwm -dev/pwm/pwmbus_if.m optional pwm -dev/pwm/ofw_pwm.c optional pwm fdt +dev/pwm/pwmc.c optional pwm | pwmc +dev/pwm/pwmbus.c optional pwm | pwmbus +dev/pwm/pwmbus_if.m optional pwm | pwmbus +dev/pwm/ofw_pwm.c optional pwm fdt | pwmbus fdt +dev/pwm/ofw_pwmbus.c optional pwm fdt | pwmbus fdt dev/quicc/quicc_core.c optional quicc dev/ral/rt2560.c optional ral dev/ral/rt2661.c optional ral @@ -3009,6 +3019,9 @@ dev/sdhci/sdhci_fdt_gpio.c optional sdhci fdt gpio dev/sdhci/sdhci_if.m optional sdhci dev/sdhci/sdhci_acpi.c optional sdhci acpi dev/sdhci/sdhci_pci.c optional sdhci pci +dev/sdio/sdio_if.m optional mmccam +dev/sdio/sdio_subr.c optional mmccam +dev/sdio/sdiob.c optional mmccam dev/sge/if_sge.c optional sge pci dev/siis/siis.c optional siis pci dev/sis/if_sis.c optional sis pci @@ -3221,6 +3234,7 @@ dev/usb/usb_generic.c optional usb dev/usb/usb_handle_request.c optional usb dev/usb/usb_hid.c optional usb dev/usb/usb_hub.c optional usb +dev/usb/usb_hub_acpi.c optional usb acpi dev/usb/usb_if.m optional usb dev/usb/usb_lookup.c optional usb dev/usb/usb_mbuf.c optional usb @@ -3969,9 +3983,9 @@ crypto/chacha20/chacha.c standard libkern/asprintf.c standard libkern/bcd.c standard libkern/bsearch.c standard -libkern/crc32.c standard libkern/explicit_bzero.c standard libkern/fnmatch.c standard +libkern/gsb_crc32.c standard libkern/iconv.c optional libiconv libkern/iconv_converter_if.m optional libiconv libkern/iconv_ucs.c optional libiconv diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 33234e28af4b..f8d9beba599d 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -95,6 +95,7 @@ arm/broadcom/bcm2835/bcm2835_vcio.c optional soc_brcm_bcm2837 fdt arm/broadcom/bcm2835/bcm2835_wdog.c optional soc_brcm_bcm2837 fdt arm/broadcom/bcm2835/bcm2836.c optional soc_brcm_bcm2837 fdt arm/broadcom/bcm2835/bcm283x_dwc_fdt.c optional dwcotg fdt soc_brcm_bcm2837 +arm/mv/a37x0_gpio.c optional a37x0_gpio gpio fdt arm/mv/gpio.c optional mv_gpio fdt arm/mv/mvebu_pinctrl.c optional mvebu_pinctrl fdt arm/mv/mv_cp110_icu.c optional mv_cp110_icu fdt diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk index 665151e2a6e6..13e899758083 100644 --- a/sys/conf/kmod.mk +++ b/sys/conf/kmod.mk @@ -242,7 +242,13 @@ ${KMOD}.kld: ${OBJS} .else ${FULLPROG}: ${OBJS} .endif +.if !defined(FIRMWS) && (${MACHINE_CPUARCH} == "i386") + ${LD} -m ${LD_EMULATION} ${_LDFLAGS} -r \ + -T ${SYSDIR}/conf/ldscript.set_padding \ + -d -o ${.TARGET} ${OBJS} +.else ${LD} -m ${LD_EMULATION} ${_LDFLAGS} -r -d -o ${.TARGET} ${OBJS} +.endif .if ${MK_CTF} != "no" ${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ${OBJS} .endif @@ -475,6 +481,18 @@ usbdevs_data.h: ${SYSDIR}/tools/usbdevs2h.awk ${SYSDIR}/dev/usb/usbdevs ${AWK} -f ${SYSDIR}/tools/usbdevs2h.awk ${SYSDIR}/dev/usb/usbdevs -d .endif +.if !empty(SRCS:Msdiodevs.h) +CLEANFILES+= sdiodevs.h +sdiodevs.h: ${SYSDIR}/tools/sdiodevs2h.awk ${SYSDIR}/dev/sdio/sdiodevs + ${AWK} -f ${SYSDIR}/tools/sdiodevs2h.awk ${SYSDIR}/dev/sdio/sdiodevs -h +.endif + +.if !empty(SRCS:Msdiodevs_data.h) +CLEANFILES+= sdiodevs_data.h +sdiodevs_data.h: ${SYSDIR}/tools/sdiodevs2h.awk ${SYSDIR}/dev/sdio/sdiodevs + ${AWK} -f ${SYSDIR}/tools/sdiodevs2h.awk ${SYSDIR}/dev/sdio/sdiodevs -d +.endif + .if !empty(SRCS:Macpi_quirks.h) CLEANFILES+= acpi_quirks.h acpi_quirks.h: ${SYSDIR}/tools/acpi_quirks2h.awk ${SYSDIR}/dev/acpica/acpi_quirks @@ -482,7 +500,7 @@ acpi_quirks.h: ${SYSDIR}/tools/acpi_quirks2h.awk ${SYSDIR}/dev/acpica/acpi_quirk .endif .if !empty(SRCS:Massym.inc) || !empty(DPSRCS:Massym.inc) -CLEANFILES+= assym.inc +CLEANFILES+= assym.inc genassym.o DEPENDOBJS+= genassym.o DPSRCS+= offset.inc .endif diff --git a/sys/conf/ldscript.riscv b/sys/conf/ldscript.riscv index 6fbdd9ad507f..449575cb6ede 100644 --- a/sys/conf/ldscript.riscv +++ b/sys/conf/ldscript.riscv @@ -89,7 +89,11 @@ SECTIONS can access them all, and initialized data all before uninitialized, so we can shorten the on-disk segment size. */ . = ALIGN(8); - .sdata : { *(.sdata) } + .sdata : + { + __global_pointer$ = . + 0x800; + *(.sdata) + } _edata = .; PROVIDE (edata = .); /* Ensure __bss_start is associated with the next section in case orphan diff --git a/sys/conf/ldscript.set_padding b/sys/conf/ldscript.set_padding new file mode 100644 index 000000000000..083f216c8752 --- /dev/null +++ b/sys/conf/ldscript.set_padding @@ -0,0 +1,46 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2018 Bjoern A. Zeeb + * + * 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$ + */ +SECTIONS +{ + set_pcpu : + { + *(set_pcpu) + LONG(0x90909090) ; + } +} + +SECTIONS +{ + set_vnet : + { + *(set_vnet) + LONG(0x90909090) ; + } +} +/* end */ diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index 084306f1f9ca..a0d008dbd2d7 100644 --- a/sys/contrib/ipfilter/netinet/fil.c +++ b/sys/contrib/ipfilter/netinet/fil.c @@ -3422,35 +3422,21 @@ fr_cksum(fin, ip, l4proto, l4hdr) sum += *sp++; sum += *sp++; /* ip_dst */ sum += *sp++; + slen = fin->fin_plen - off; + sum += htons(slen); #ifdef USE_INET6 } else if (IP_V(ip) == 6) { + mb_t *m; + + m = fin->fin_m; ip6 = (ip6_t *)ip; - hlen = sizeof(*ip6); - off = ((char *)fin->fin_dp - (char *)fin->fin_ip); - sp = (u_short *)&ip6->ip6_src; - sum += *sp++; /* ip6_src */ - sum += *sp++; - sum += *sp++; - sum += *sp++; - sum += *sp++; - sum += *sp++; - sum += *sp++; - sum += *sp++; - /* This needs to be routing header aware. */ - sum += *sp++; /* ip6_dst */ - sum += *sp++; - sum += *sp++; - sum += *sp++; - sum += *sp++; - sum += *sp++; - sum += *sp++; - sum += *sp++; + off = ((caddr_t)ip6 - m->m_data) + sizeof(struct ip6_hdr); + int len = ntohs(ip6->ip6_plen) - (off - sizeof(*ip6)); + return(ipf_pcksum6(fin, ip6, off, len)); } else { return 0xffff; } #endif - slen = fin->fin_plen - off; - sum += htons(slen); switch (l4proto) { @@ -6268,7 +6254,7 @@ ipf_ioctlswitch(softc, unit, data, cmd, mode, uid, ctx) * Flags: * 1 = minimum size, not absolute size */ -static int ipf_objbytes[IPFOBJ_COUNT][3] = { +static const int ipf_objbytes[IPFOBJ_COUNT][3] = { { 1, sizeof(struct frentry), 5010000 }, /* 0 */ { 1, sizeof(struct friostat), 5010000 }, { 0, sizeof(struct fr_info), 5010000 }, @@ -6645,6 +6631,12 @@ ipf_checkl4sum(fin) if ((fin->fin_flx & (FI_FRAG|FI_SHORT|FI_BAD)) != 0) return 1; + DT2(l4sumo, int, fin->fin_out, int, (int)fin->fin_p); + if (fin->fin_out == 1) { + fin->fin_cksum = FI_CK_SUMOK; + return 0; + } + csump = NULL; hdrsum = 0; dosum = 0; @@ -6696,7 +6688,11 @@ ipf_checkl4sum(fin) } #endif DT2(l4sums, u_short, hdrsum, u_short, sum); +#ifdef USE_INET6 + if (hdrsum == sum || (sum == 0 && fin->fin_p == IPPROTO_ICMPV6)) { +#else if (hdrsum == sum) { +#endif fin->fin_cksum = FI_CK_SUMOK; return 0; } diff --git a/sys/contrib/ipfilter/netinet/ip_fil.h b/sys/contrib/ipfilter/netinet/ip_fil.h index 45f2118e1ddc..f3185c6458d7 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.h +++ b/sys/contrib/ipfilter/netinet/ip_fil.h @@ -1836,6 +1836,10 @@ extern int ipf_matchicmpqueryreply __P((int, icmpinfo_t *, struct icmp *, int)); extern u_32_t ipf_newisn __P((fr_info_t *)); extern u_int ipf_pcksum __P((fr_info_t *, int, u_int)); +#ifdef USE_INET6 +extern u_int ipf_pcksum6 __P((fr_info_t *, ip6_t *, + u_int32_t, u_int32_t)); +#endif extern void ipf_rule_expire __P((ipf_main_softc_t *)); extern int ipf_scanlist __P((fr_info_t *, u_32_t)); extern frentry_t *ipf_srcgrpmap __P((fr_info_t *, u_32_t *)); diff --git a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c index 9d40de27b841..843715713e44 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c +++ b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c @@ -1446,3 +1446,56 @@ ipf_pcksum(fin, hlen, sum) sum2 = ~sum & 0xffff; return sum2; } + +#ifdef USE_INET6 +#ifdef _KERNEL +u_int +ipf_pcksum6(fin, ip6, off, len) + fr_info_t *fin; + ip6_t *ip6; + u_int32_t off; + u_int32_t len; +{ + struct mbuf *m; + int sum; + + m = fin->fin_m; + if (m->m_len < sizeof(struct ip6_hdr)) { + return 0xffff; + } + + sum = in6_cksum(m, ip6->ip6_nxt, off, len); + return(sum); +} +#else +u_int +ipf_pcksum6(fin, ip6, off, len) + fr_info_t *fin; + ip6_t *ip6; + u_int32_t off; + u_int32_t len; +{ + u_short *sp; + u_int sum; + + sp = (u_short *)&ip6->ip6_src; + sum = *sp++; /* ip6_src */ + sum += *sp++; + sum += *sp++; + sum += *sp++; + sum += *sp++; + sum += *sp++; + sum += *sp++; + sum += *sp++; + sum += *sp++; /* ip6_dst */ + sum += *sp++; + sum += *sp++; + sum += *sp++; + sum += *sp++; + sum += *sp++; + sum += *sp++; + sum += *sp++; + return(ipf_pcksum(fin, off, sum)); +} +#endif +#endif diff --git a/sys/contrib/ipfilter/netinet/mlfk_ipl.c b/sys/contrib/ipfilter/netinet/mlfk_ipl.c index 094bafb593c4..34a9644bbdc9 100644 --- a/sys/contrib/ipfilter/netinet/mlfk_ipl.c +++ b/sys/contrib/ipfilter/netinet/mlfk_ipl.c @@ -211,7 +211,7 @@ vnet_ipf_init(void) else defpass = "no-match -> block"; - if (IS_DEFAULT_VNET(curvnet)) + if (IS_DEFAULT_VNET(curvnet)) { printf("%s initialized. Default = %s all, Logging = %s%s\n", ipfilter_version, defpass, #ifdef IPFILTER_LOG @@ -225,6 +225,10 @@ vnet_ipf_init(void) "" #endif ); + } else { + (void)ipf_pfil_hook(); + ipf_event_reg(); + } } VNET_SYSINIT(vnet_ipf_init, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD, vnet_ipf_init, NULL); diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c index 6c4947aeeeef..e667e788c528 100644 --- a/sys/dev/atkbdc/psm.c +++ b/sys/dev/atkbdc/psm.c @@ -236,6 +236,7 @@ typedef struct synapticsinfo { int softbutton3_x; int max_x; int max_y; + int three_finger_drag; int natural_scroll; } synapticsinfo_t; @@ -513,9 +514,9 @@ static devclass_t psm_devclass; /* Tunables */ static int tap_enabled = -1; static int verbose = PSM_DEBUG; -static int synaptics_support = 0; -static int trackpoint_support = 0; -static int elantech_support = 0; +static int synaptics_support = 1; +static int trackpoint_support = 1; +static int elantech_support = 1; /* for backward compatibility */ #define OLD_MOUSE_GETHWINFO _IOR('M', 1, old_mousehw_t) @@ -572,6 +573,7 @@ enum { SYNAPTICS_SYSCTL_SOFTBUTTONS_Y = SYN_OFFSET(softbuttons_y), SYNAPTICS_SYSCTL_SOFTBUTTON2_X = SYN_OFFSET(softbutton2_x), SYNAPTICS_SYSCTL_SOFTBUTTON3_X = SYN_OFFSET(softbutton3_x), + SYNAPTICS_SYSCTL_THREE_FINGER_DRAG = SYN_OFFSET(three_finger_drag), SYNAPTICS_SYSCTL_NATURAL_SCROLL = SYN_OFFSET(natural_scroll), #define SYNAPTICS_SYSCTL_LAST SYNAPTICS_SYSCTL_NATURAL_SCROLL }; @@ -3785,6 +3787,7 @@ psmgestures(struct psm_softc *sc, finger_t *fingers, int nfingers, int vscroll_hor_area, vscroll_ver_area; int two_finger_scroll; int max_x, max_y; + int three_finger_drag; /* Read sysctl. */ /* XXX Verify values? */ @@ -3799,7 +3802,7 @@ psmgestures(struct psm_softc *sc, finger_t *fingers, int nfingers, two_finger_scroll = sc->syninfo.two_finger_scroll; max_x = sc->syninfo.max_x; max_y = sc->syninfo.max_y; - + three_finger_drag = sc->syninfo.three_finger_drag; /* Read current absolute position. */ x0 = f->x; y0 = f->y; @@ -3888,8 +3891,8 @@ psmgestures(struct psm_softc *sc, finger_t *fingers, int nfingers, ~MOUSE_BUTTON1DOWN) | center_button; } - /* If in tap-hold, add the recorded button. */ - if (gest->in_taphold) + /* If in tap-hold or three fingers, add the recorded button. */ + if (gest->in_taphold || (nfingers == 3 && three_finger_drag)) ms->button |= gest->tap_button; /* @@ -4676,7 +4679,7 @@ proc_elantech(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, case ELANTECH_PKT_TRACKPOINT: /* 7 6 5 4 3 2 1 0 (LSB) * ------------------------------------------- - * ipacket[0]: 0 0 SX SY 0 M R L + * ipacket[0]: 0 0 SY SX 0 M R L * ipacket[1]: ~SX 0 0 0 0 0 0 0 * ipacket[2]: ~SY 0 0 0 0 0 0 0 * ipacket[3]: 0 0 ~SY ~SX 0 1 1 0 @@ -4687,22 +4690,32 @@ proc_elantech(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, * over 9 bits with SX/SY the relative top bit and * X7..X0 and Y7..Y0 the lower bits. */ - *x = (pb->ipacket[0] & 0x20) ? - pb->ipacket[4] - 256 : pb->ipacket[4]; - *y = (pb->ipacket[0] & 0x10) ? - pb->ipacket[5] - 256 : pb->ipacket[5]; + if (!(pb->ipacket[0] & 0xC8) && !(pb->ipacket[1] & 0x7F) && + !(pb->ipacket[2] & 0x7F) && !(pb->ipacket[3] & 0xC9) && + !(pb->ipacket[0] & 0x10) != !(pb->ipacket[1] & 0x80) && + !(pb->ipacket[0] & 0x10) != !(pb->ipacket[3] & 0x10) && + !(pb->ipacket[0] & 0x20) != !(pb->ipacket[2] & 0x80) && + !(pb->ipacket[0] & 0x20) != !(pb->ipacket[3] & 0x20)) { - trackpoint_button = - ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | - ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0) | - ((pb->ipacket[0] & 0x04) ? MOUSE_BUTTON2DOWN : 0); + *x = (pb->ipacket[0] & MOUSE_PS2_XNEG) ? + pb->ipacket[4] - 256 : pb->ipacket[4]; + *y = (pb->ipacket[0] & MOUSE_PS2_YNEG) ? + pb->ipacket[5] - 256 : pb->ipacket[5]; + + trackpoint_button = + ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | + ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0) | + ((pb->ipacket[0] & 0x04) ? MOUSE_BUTTON2DOWN : 0); #ifdef EVDEV_SUPPORT - evdev_push_rel(sc->evdev_r, REL_X, *x); - evdev_push_rel(sc->evdev_r, REL_Y, -*y); - evdev_push_mouse_btn(sc->evdev_r, trackpoint_button); - evdev_sync(sc->evdev_r); + evdev_push_rel(sc->evdev_r, REL_X, *x); + evdev_push_rel(sc->evdev_r, REL_Y, -*y); + evdev_push_mouse_btn(sc->evdev_r, trackpoint_button); + evdev_sync(sc->evdev_r); #endif - ms->button = touchpad_button | trackpoint_button; + ms->button = touchpad_button | trackpoint_button; + } else + VLOG(3, (LOG_DEBUG, "elantech: " + "unexpected trackpoint packet skipped\n")); return (0); case ELANTECH_PKT_NOP: @@ -5745,6 +5758,7 @@ synaptics_sysctl(SYSCTL_HANDLER_ARGS) return (EINVAL); break; case SYNAPTICS_SYSCTL_TOUCHPAD_OFF: + case SYNAPTICS_SYSCTL_THREE_FINGER_DRAG: case SYNAPTICS_SYSCTL_NATURAL_SCROLL: if (arg < 0 || arg > 1) return (EINVAL); @@ -6138,6 +6152,14 @@ synaptics_sysctl_create_tree(struct psm_softc *sc, const char *name, synaptics_sysctl, "I", "Turn off touchpad"); + sc->syninfo.three_finger_drag = 0; + SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, + SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, + "three_finger_drag", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, + sc, SYNAPTICS_SYSCTL_THREE_FINGER_DRAG, + synaptics_sysctl, "I", + "Enable dragging with three fingers"); + /* hw.psm.synaptics.natural_scroll. */ sc->syninfo.natural_scroll = 0; SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, diff --git a/sys/dev/ciss/ciss.c b/sys/dev/ciss/ciss.c index e4b887a38e60..b4ead0994bb2 100644 --- a/sys/dev/ciss/ciss.c +++ b/sys/dev/ciss/ciss.c @@ -107,6 +107,10 @@ #include #include +#ifdef CISS_DEBUG +#include "opt_ddb.h" +#endif + static MALLOC_DEFINE(CISS_MALLOC_CLASS, "ciss_data", "ciss internal data buffers"); @@ -197,7 +201,9 @@ static void ciss_notify_logical(struct ciss_softc *sc, struct ciss_notify *cn); static void ciss_notify_physical(struct ciss_softc *sc, struct ciss_notify *cn); /* debugging output */ +#ifdef DDB static void ciss_print_request(struct ciss_request *cr); +#endif static void ciss_print_ldrive(struct ciss_softc *sc, struct ciss_ldrive *ld); static const char *ciss_name_ldrive_status(int status); static int ciss_decode_ldrive_status(int status); @@ -3811,8 +3817,9 @@ ciss_notify_abort(struct ciss_softc *sc) cnc->opcode = CISS_OPCODE_WRITE; cnc->command = CISS_COMMAND_ABORT_NOTIFY; cnc->length = htonl(CISS_NOTIFY_DATA_SIZE); - +#if 0 ciss_print_request(cr); +#endif /* * Submit the request and wait for it to complete. @@ -4237,6 +4244,7 @@ ciss_kill_notify_thread(struct ciss_softc *sc) /************************************************************************ * Print a request. */ +#ifdef DDB static void ciss_print_request(struct ciss_request *cr) { @@ -4290,6 +4298,7 @@ ciss_print_request(struct ciss_request *cr) } } } +#endif /************************************************************************ * Print information about the status of a logical drive. @@ -4353,8 +4362,6 @@ ciss_print_ldrive(struct ciss_softc *sc, struct ciss_ldrive *ld) } } -#ifdef CISS_DEBUG -#include "opt_ddb.h" #ifdef DDB #include /************************************************************************ @@ -4409,7 +4416,6 @@ DB_COMMAND(ciss_prt, db_ciss_prt) } } #endif -#endif /************************************************************************ * Return a name for a logical drive status value. diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index 3e92d230bf9b..e5bbb160293b 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -6232,8 +6232,10 @@ t4_sysctls(struct adapter *sc) &sc->tt.sndbuf, 0, "max hardware send buffer size"); sc->tt.ddp = 0; - SYSCTL_ADD_INT(ctx, children, OID_AUTO, "ddp", CTLFLAG_RW, - &sc->tt.ddp, 0, "DDP allowed"); + SYSCTL_ADD_INT(ctx, children, OID_AUTO, "ddp", + CTLFLAG_RW | CTLFLAG_SKIP, &sc->tt.ddp, 0, ""); + SYSCTL_ADD_INT(ctx, children, OID_AUTO, "rx_zcopy", CTLFLAG_RW, + &sc->tt.ddp, 0, "Enable zero-copy aio_read(2)"); sc->tt.rx_coalesce = 1; SYSCTL_ADD_INT(ctx, children, OID_AUTO, "rx_coalesce", diff --git a/sys/dev/cxgbe/tom/t4_tls.c b/sys/dev/cxgbe/tom/t4_tls.c index d030f68e3bc8..d338613fb3ef 100644 --- a/sys/dev/cxgbe/tom/t4_tls.c +++ b/sys/dev/cxgbe/tom/t4_tls.c @@ -1585,8 +1585,8 @@ do_rx_tls_cmp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) sbappendstream_locked(sb, m, 0); rx_credits = sbspace(sb) > tp->rcv_wnd ? sbspace(sb) - tp->rcv_wnd : 0; #ifdef VERBOSE_TRACES - CTR5(KTR_CXGBE, "%s: tid %u PDU overhead %d rx_credits %u rcv_wnd %u", - __func__, tid, pdu_overhead, rx_credits, tp->rcv_wnd); + CTR4(KTR_CXGBE, "%s: tid %u rx_credits %u rcv_wnd %u", + __func__, tid, rx_credits, tp->rcv_wnd); #endif if (rx_credits > 0 && sbused(sb) + tp->rcv_wnd < sb->sb_lowat) { rx_credits = send_rx_credits(sc, toep, rx_credits); diff --git a/sys/dev/drm2/ttm/ttm_page_alloc.c b/sys/dev/drm2/ttm/ttm_page_alloc.c index 84ab9c2cdd3c..1e9055175449 100644 --- a/sys/dev/drm2/ttm/ttm_page_alloc.c +++ b/sys/dev/drm2/ttm/ttm_page_alloc.c @@ -137,7 +137,7 @@ ttm_vm_page_free(vm_page_t m) KASSERT((m->oflags & VPO_UNMANAGED) == 0, ("ttm got unmanaged %p", m)); m->flags &= ~PG_FICTITIOUS; m->oflags |= VPO_UNMANAGED; - vm_page_unwire(m, PQ_NONE); + vm_page_unwire_noq(m); vm_page_free(m); } diff --git a/sys/dev/etherswitch/e6000sw/e6000sw.c b/sys/dev/etherswitch/e6000sw/e6000sw.c index f6301d0abd17..a065970a0166 100644 --- a/sys/dev/etherswitch/e6000sw/e6000sw.c +++ b/sys/dev/etherswitch/e6000sw/e6000sw.c @@ -441,10 +441,12 @@ e6000sw_attach(device_t dev) * Force speed, full-duplex, EEE off and flow-control * on. */ + reg &= ~(PSC_CONTROL_SPD2500 | PSC_CONTROL_ALT_SPD | + PSC_CONTROL_FORCED_EEE); if (e6000sw_is_fixed25port(sc, port)) - reg = PSC_CONTROL_SPD2500; + reg |= PSC_CONTROL_SPD2500; else - reg = PSC_CONTROL_SPD1000; + reg |= PSC_CONTROL_SPD1000; reg |= PSC_CONTROL_FORCED_DPX | PSC_CONTROL_FULLDPX | PSC_CONTROL_FORCED_LINK | PSC_CONTROL_LINK_UP | PSC_CONTROL_FORCED_FC | PSC_CONTROL_FC_ON | diff --git a/sys/dev/etherswitch/e6000sw/e6000swreg.h b/sys/dev/etherswitch/e6000sw/e6000swreg.h index e28e74e190b0..a0823cd8952e 100644 --- a/sys/dev/etherswitch/e6000sw/e6000swreg.h +++ b/sys/dev/etherswitch/e6000sw/e6000swreg.h @@ -74,6 +74,7 @@ struct atu_opt { #define PSC_CONTROL 0x1 #define PSC_CONTROL_FORCED_SPD (1 << 13) +#define PSC_CONTROL_ALT_SPD (1 << 12) #define PSC_CONTROL_EEE_ON (1 << 9) #define PSC_CONTROL_FORCED_EEE (1 << 8) #define PSC_CONTROL_FC_ON (1 << 7) diff --git a/sys/dev/gpio/gpioregulator.c b/sys/dev/gpio/gpioregulator.c index 5c67a36909d5..f36545428654 100644 --- a/sys/dev/gpio/gpioregulator.c +++ b/sys/dev/gpio/gpioregulator.c @@ -248,7 +248,7 @@ gpioregulator_parse_fdt(struct gpioregulator_softc *sc) /* "gpios" property */ sc->init_def.npins = 32 - __builtin_clz(mask); sc->init_def.pins = malloc(sc->init_def.npins * - sizeof(sc->init_def.pins), M_DEVBUF, M_WAITOK); + sizeof(sc->init_def.pins), M_DEVBUF, M_WAITOK | M_ZERO); for (n = 0; n < sc->init_def.npins; n++) { error = gpio_pin_get_by_ofw_idx(sc->dev, node, n, &sc->init_def.pins[n]); diff --git a/sys/dev/ipmi/ipmi_kcs.c b/sys/dev/ipmi/ipmi_kcs.c index 9717480fd66b..79f2ef720ca8 100644 --- a/sys/dev/ipmi/ipmi_kcs.c +++ b/sys/dev/ipmi/ipmi_kcs.c @@ -48,55 +48,46 @@ __FBSDID("$FreeBSD$"); #include #endif +#define POLLING_DELAY_MIN 4 /* Waits are 2-3 usecs on typical systems */ +#define POLLING_DELAY_MAX 256 + static void kcs_clear_obf(struct ipmi_softc *, int); static void kcs_error(struct ipmi_softc *); -static int kcs_wait_for_ibf(struct ipmi_softc *, int); -static int kcs_wait_for_obf(struct ipmi_softc *, int); +static int kcs_wait_for_ibf(struct ipmi_softc *, bool); +static int kcs_wait_for_obf(struct ipmi_softc *, bool); static int -kcs_wait_for_ibf(struct ipmi_softc *sc, int state) +kcs_wait(struct ipmi_softc *sc, int value, int mask) { int status, start = ticks; + int delay_usec = POLLING_DELAY_MIN; status = INB(sc, KCS_CTL_STS); - if (state == 0) { - /* WAIT FOR IBF = 0 */ - while (ticks - start < MAX_TIMEOUT && status & KCS_STATUS_IBF) { - DELAY(100); - status = INB(sc, KCS_CTL_STS); - } - } else { - /* WAIT FOR IBF = 1 */ - while (ticks - start < MAX_TIMEOUT && - !(status & KCS_STATUS_IBF)) { - DELAY(100); - status = INB(sc, KCS_CTL_STS); - } + while (ticks - start < MAX_TIMEOUT && (status & mask) != value) { + /* + * The wait delay is increased exponentially to avoid putting + * significant load on I/O bus. + */ + DELAY(delay_usec); + status = INB(sc, KCS_CTL_STS); + if (delay_usec < POLLING_DELAY_MAX) + delay_usec *= 2; } return (status); } static int -kcs_wait_for_obf(struct ipmi_softc *sc, int state) +kcs_wait_for_ibf(struct ipmi_softc *sc, bool level) { - int status, start = ticks; - status = INB(sc, KCS_CTL_STS); - if (state == 0) { - /* WAIT FOR OBF = 0 */ - while (ticks - start < MAX_TIMEOUT && status & KCS_STATUS_OBF) { - DELAY(100); - status = INB(sc, KCS_CTL_STS); - } - } else { - /* WAIT FOR OBF = 1 */ - while (ticks - start < MAX_TIMEOUT && - !(status & KCS_STATUS_OBF)) { - DELAY(100); - status = INB(sc, KCS_CTL_STS); - } - } - return (status); + return (kcs_wait(sc, level ? KCS_STATUS_IBF : 0, KCS_STATUS_IBF)); +} + +static int +kcs_wait_for_obf(struct ipmi_softc *sc, bool level) +{ + + return (kcs_wait(sc, level ? KCS_STATUS_OBF : 0, KCS_STATUS_OBF)); } static void diff --git a/sys/dev/iscsi/icl_soft.c b/sys/dev/iscsi/icl_soft.c index 66df484f4308..0b4f4f64c720 100644 --- a/sys/dev/iscsi/icl_soft.c +++ b/sys/dev/iscsi/icl_soft.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/dev/iscsi_initiator/isc_subr.c b/sys/dev/iscsi_initiator/isc_subr.c index f3dfcb715e2f..9c27c7313d85 100644 --- a/sys/dev/iscsi_initiator/isc_subr.c +++ b/sys/dev/iscsi_initiator/isc_subr.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/dev/liquidio/lio_bsd.h b/sys/dev/liquidio/lio_bsd.h index ac170c9c654f..fd6402ea2297 100644 --- a/sys/dev/liquidio/lio_bsd.h +++ b/sys/dev/liquidio/lio_bsd.h @@ -36,6 +36,7 @@ #define __LIO_BSD_H__ #include +#include #include #include #include diff --git a/sys/dev/nvdimm/nvdimm.c b/sys/dev/nvdimm/nvdimm.c index aed02a2782a5..5c6b6ee6dc72 100644 --- a/sys/dev/nvdimm/nvdimm.c +++ b/sys/dev/nvdimm/nvdimm.c @@ -560,6 +560,24 @@ nvdimm_root_write_ivar(device_t dev, device_t child, int index, return (0); } +static int +nvdimm_root_child_location_str(device_t dev, device_t child, char *buf, + size_t buflen) +{ + ACPI_HANDLE handle; + int res; + + handle = nvdimm_root_get_acpi_handle(child); + if (handle != NULL) + res = snprintf(buf, buflen, "handle=%s", acpi_name(handle)); + else + res = snprintf(buf, buflen, "unknown"); + + if (res >= buflen) + return (EOVERFLOW); + return (0); +} + static device_method_t nvdimm_methods[] = { DEVMETHOD(device_probe, nvdimm_probe), DEVMETHOD(device_attach, nvdimm_attach), @@ -582,6 +600,7 @@ static device_method_t nvdimm_root_methods[] = { DEVMETHOD(bus_add_child, bus_generic_add_child), DEVMETHOD(bus_read_ivar, nvdimm_root_read_ivar), DEVMETHOD(bus_write_ivar, nvdimm_root_write_ivar), + DEVMETHOD(bus_child_location_str, nvdimm_root_child_location_str), DEVMETHOD_END }; diff --git a/sys/dev/nvme/nvme_sim.c b/sys/dev/nvme/nvme_sim.c index 7593920c15fa..2218b5518cc7 100644 --- a/sys/dev/nvme/nvme_sim.c +++ b/sys/dev/nvme/nvme_sim.c @@ -212,7 +212,7 @@ nvme_sim_action(struct cam_sim *sim, union ccb *ccb) struct ccb_trans_settings_nvme *nvmep; struct ccb_trans_settings_nvme *nvmex; device_t dev; - uint32_t status, caps; + uint32_t status, caps, flags; dev = ctrlr->dev; cts = &ccb->cts; @@ -221,12 +221,16 @@ nvme_sim_action(struct cam_sim *sim, union ccb *ccb) status = pcie_read_config(dev, PCIER_LINK_STA, 2); caps = pcie_read_config(dev, PCIER_LINK_CAP, 2); - nvmex->valid = CTS_NVME_VALID_SPEC | CTS_NVME_VALID_LINK; + flags = pcie_read_config(dev, PCIER_FLAGS, 2); nvmex->spec = nvme_mmio_read_4(ctrlr, vs); - nvmex->speed = status & PCIEM_LINK_STA_SPEED; - nvmex->lanes = (status & PCIEM_LINK_STA_WIDTH) >> 4; - nvmex->max_speed = caps & PCIEM_LINK_CAP_MAX_SPEED; - nvmex->max_lanes = (caps & PCIEM_LINK_CAP_MAX_WIDTH) >> 4; + nvmex->valid = CTS_NVME_VALID_SPEC; + if ((flags & PCIEM_FLAGS_TYPE) == PCIEM_TYPE_ENDPOINT) { + nvmex->valid |= CTS_NVME_VALID_LINK; + nvmex->speed = status & PCIEM_LINK_STA_SPEED; + nvmex->lanes = (status & PCIEM_LINK_STA_WIDTH) >> 4; + nvmex->max_speed = caps & PCIEM_LINK_CAP_MAX_SPEED; + nvmex->max_lanes = (caps & PCIEM_LINK_CAP_MAX_WIDTH) >> 4; + } /* XXX these should be something else maybe ? */ nvmep->valid = 1; diff --git a/sys/dev/pwm/ofw_pwm.c b/sys/dev/pwm/ofw_pwm.c index 198cf105e5e1..a70c8919f727 100644 --- a/sys/dev/pwm/ofw_pwm.c +++ b/sys/dev/pwm/ofw_pwm.c @@ -38,9 +38,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include - -#include "pwm_if.h" +#include int pwm_get_by_ofw_propidx(device_t consumer, phandle_t node, @@ -62,12 +60,6 @@ pwm_get_by_ofw_propidx(device_t consumer, phandle_t node, return (ENODEV); } - channel.busdev = PWM_GET_BUS(channel.dev); - if (channel.busdev == NULL) { - OF_prop_free(cells); - return (ENODEV); - } - channel.channel = cells[0]; channel.period = cells[1]; diff --git a/sys/sys/capability.h b/sys/dev/pwm/ofw_pwm.h similarity index 64% rename from sys/sys/capability.h rename to sys/dev/pwm/ofw_pwm.h index 39195e034c56..00910907932a 100644 --- a/sys/sys/capability.h +++ b/sys/dev/pwm/ofw_pwm.h @@ -1,12 +1,9 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2014 Robert N. M. Watson + * Copyright (c) 2018 Emmanuel Vadot * All rights reserved. * - * This software was developed at the University of Cambridge Computer - * Laboratory with support from a grant from Google, Inc. - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,17 +28,28 @@ * $FreeBSD$ */ -/* - * Historically, the key userspace and kernel Capsicum definitions were found - * in this file. However, it conflicted with POSIX.1e's capability.h, so has - * been renamed capsicum.h. The file remains for backwards compatibility - * reasons as a nested include. It is expected to be removed before - * FreeBSD 13. - */ -#ifndef _SYS_CAPABILITY_H_ -#define _SYS_CAPABILITY_H_ +#ifndef _OFW_PWM_H_ +#define _OFW_PWM_H_ -#warning this file includes which is deprecated -#include +#include -#endif /* !_SYS_CAPABILITY_H_ */ +struct pwm_channel { + device_t dev; + u_int channel; + uint64_t period; + uint64_t duty; + uint32_t flags; + bool enabled; +}; +typedef struct pwm_channel *pwm_channel_t; + +int pwm_get_by_ofw_propidx(device_t consumer, phandle_t node, + const char *prop_name, int idx, pwm_channel_t *channel); +int pwm_get_by_ofw_idx(device_t consumer, phandle_t node, int idx, + pwm_channel_t *out_channel); +int pwm_get_by_ofw_property(device_t consumer, phandle_t node, + const char *prop_name, pwm_channel_t *out_channel); +int pwm_get_by_ofw_name(device_t consumer, phandle_t node, const char *name, + pwm_channel_t *out_channel); + +#endif /* _OFW_PWM_H_ */ diff --git a/sys/dev/pwm/ofw_pwmbus.c b/sys/dev/pwm/ofw_pwmbus.c new file mode 100644 index 000000000000..359c4f11272b --- /dev/null +++ b/sys/dev/pwm/ofw_pwmbus.c @@ -0,0 +1,223 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2019 Ian Lepore + * + * 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 "pwmbus_if.h" + +struct ofw_pwmbus_ivars { + struct pwmbus_ivars base; + struct ofw_bus_devinfo devinfo; +}; + +struct ofw_pwmbus_softc { + struct pwmbus_softc base; +}; + +/* + * bus_if methods... + */ + +static device_t +ofw_pwmbus_add_child(device_t dev, u_int order, const char *name, int unit) +{ + device_t child; + struct ofw_pwmbus_ivars *ivars; + + if ((ivars = malloc(sizeof(struct ofw_pwmbus_ivars), M_DEVBUF, + M_NOWAIT | M_ZERO)) == NULL) { + return (NULL); + } + + if ((child = device_add_child_ordered(dev, order, name, unit)) == NULL) { + free(ivars, M_DEVBUF); + return (NULL); + } + + ivars->devinfo.obd_node = -1; + device_set_ivars(child, ivars); + + return (child); +} + +static void +ofw_pwmbus_child_deleted(device_t dev, device_t child) +{ + struct ofw_pwmbus_ivars *ivars; + + ivars = device_get_ivars(child); + if (ivars != NULL) { + ofw_bus_gen_destroy_devinfo(&ivars->devinfo); + free(ivars, M_DEVBUF); + } +} + +static const struct ofw_bus_devinfo * +ofw_pwmbus_get_devinfo(device_t bus, device_t dev) +{ + struct ofw_pwmbus_ivars *ivars; + + ivars = device_get_ivars(dev); + return (&ivars->devinfo); +} + +/* + * device_if methods... + */ + +static int +ofw_pwmbus_probe(device_t dev) +{ + + if (ofw_bus_get_node(dev) == -1) { + return (ENXIO); + } + device_set_desc(dev, "OFW PWM bus"); + + return (BUS_PROBE_DEFAULT); +} + +static int +ofw_pwmbus_attach(device_t dev) +{ + struct ofw_pwmbus_softc *sc; + struct ofw_pwmbus_ivars *ivars; + phandle_t node; + device_t child, parent; + pcell_t chan; + bool any_children; + + sc = device_get_softc(dev); + sc->base.dev = dev; + parent = device_get_parent(dev); + + if (PWMBUS_CHANNEL_COUNT(parent, &sc->base.nchannels) != 0 || + sc->base.nchannels == 0) { + device_printf(dev, "No channels on parent %s\n", + device_get_nameunit(parent)); + return (ENXIO); + } + + /* + * Attach the children found in the fdt node of the hardware controller. + * Hardware controllers must implement the ofw_bus_get_node method so + * that our call to ofw_bus_get_node() gets back the controller's node. + */ + any_children = false; + node = ofw_bus_get_node(dev); + for (node = OF_child(node); node != 0; node = OF_peer(node)) { + /* + * The child has to have a reg property; its value is the + * channel number so range-check it. + */ + if (OF_getencprop(node, "reg", &chan, sizeof(chan)) == -1) + continue; + if (chan >= sc->base.nchannels) + continue; + + if ((child = ofw_pwmbus_add_child(dev, 0, NULL, -1)) == NULL) + continue; + + ivars = device_get_ivars(child); + ivars->base.pi_channel = chan; + + /* Set up the standard ofw devinfo. */ + if (ofw_bus_gen_setup_devinfo(&ivars->devinfo, node) != 0) { + device_delete_child(dev, child); + continue; + } + any_children = true; + } + + /* + * If we didn't find any children in the fdt data, add a pwmc(4) child + * for each channel, like the base pwmbus does. The idea is that if + * there is any fdt data, then we do exactly what it says and nothing + * more, otherwise we just provide generic userland access to all the + * pwm channels that exist like the base pwmbus's attach code does. + */ + if (!any_children) { + for (chan = 0; chan < sc->base.nchannels; ++chan) { + child = ofw_pwmbus_add_child(dev, 0, "pwmc", -1); + if (child == NULL) { + device_printf(dev, "failed to add pwmc child " + " device for channel %u\n", chan); + continue; + } + ivars = device_get_ivars(child); + ivars->base.pi_channel = chan; + } + } + bus_enumerate_hinted_children(dev); + bus_generic_probe(dev); + + return (bus_generic_attach(dev)); +} + +static device_method_t ofw_pwmbus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ofw_pwmbus_probe), + DEVMETHOD(device_attach, ofw_pwmbus_attach), + + /* Bus interface */ + DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), + DEVMETHOD(bus_add_child, ofw_pwmbus_add_child), + DEVMETHOD(bus_child_deleted, ofw_pwmbus_child_deleted), + + /* ofw_bus interface */ + DEVMETHOD(ofw_bus_get_devinfo, ofw_pwmbus_get_devinfo), + DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), + DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), + DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), + DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), + DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), + + DEVMETHOD_END +}; + +devclass_t ofw_pwmbus_devclass; + +DEFINE_CLASS_1(pwmbus, ofw_pwmbus_driver, ofw_pwmbus_methods, + sizeof(struct pwmbus_softc), pwmbus_driver); +EARLY_DRIVER_MODULE(ofw_pwmbus, pwm, ofw_pwmbus_driver, ofw_pwmbus_devclass, + 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); +MODULE_VERSION(ofw_pwmbus, 1); +MODULE_DEPEND(ofw_pwmbus, pwmbus, 1, 1, 1); diff --git a/sys/dev/pwm/pwm_if.m b/sys/dev/pwm/pwm_if.m deleted file mode 100644 index 103f4db1fa29..000000000000 --- a/sys/dev/pwm/pwm_if.m +++ /dev/null @@ -1,106 +0,0 @@ -#- -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD -# -# Copyright (c) 2018 Emmanuel Vadot -# -# 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$ -# - -#include - -INTERFACE pwm; - -# -# Get the bus -# - -METHOD device_t get_bus { - device_t dev; -}; - -# -# Config the period (Total number of cycle in ns) and -# the duty (active number of cycle in ns) -# -METHOD int channel_config { - device_t dev; - int channel; - unsigned int period; - unsigned duty; -}; - -# -# Get the period (Total number of cycle in ns) and -# the duty (active number of cycle in ns) -# -METHOD int channel_get_config { - device_t dev; - int channel; - unsigned int *period; - unsigned int *duty; -}; - -# -# Set the flags -# -METHOD int channel_set_flags { - device_t dev; - int channel; - uint32_t flags; -}; - -# -# Get the flags -# -METHOD int channel_get_flags { - device_t dev; - int channel; - uint32_t *flags; -}; - -# -# Enable the pwm output -# -METHOD int channel_enable { - device_t dev; - int channel; - bool enable; -}; - -# -# Is the pwm output enabled -# -METHOD int channel_is_enabled { - device_t dev; - int channel; - bool *enabled; -}; - -# -# Get the number of channels -# -METHOD int channel_max { - device_t dev; - int *nchannel; -}; diff --git a/sys/dev/pwm/pwmbus.c b/sys/dev/pwm/pwmbus.c index 66f8495d5e83..e5ecfee08bbd 100644 --- a/sys/dev/pwm/pwmbus.c +++ b/sys/dev/pwm/pwmbus.c @@ -37,63 +37,126 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include -#include - -#include -#include - #include #include "pwmbus_if.h" -#include "pwm_if.h" -struct pwmbus_channel_data { - int reserved; - char *name; -}; +/* + * bus_if methods... + */ -struct pwmbus_softc { - device_t busdev; - device_t dev; - - int nchannels; -}; - -device_t -pwmbus_attach_bus(device_t dev) +static device_t +pwmbus_add_child(device_t dev, u_int order, const char *name, int unit) { - device_t busdev; -#ifdef FDT - phandle_t node; -#endif + device_t child; + struct pwmbus_ivars *ivars; - busdev = device_add_child(dev, "pwmbus", -1); - if (busdev == NULL) { - device_printf(dev, "Cannot add child pwmbus\n"); - return (NULL); - } - if (device_add_child(dev, "pwmc", -1) == NULL) { - device_printf(dev, "Cannot add pwmc\n"); - device_delete_child(dev, busdev); + child = device_add_child_ordered(dev, order, name, unit); + if (child == NULL) + return (child); + + ivars = malloc(sizeof(struct pwmbus_ivars), M_DEVBUF, M_NOWAIT | M_ZERO); + if (ivars == NULL) { + device_delete_child(dev, child); return (NULL); } + device_set_ivars(child, ivars); -#ifdef FDT - node = ofw_bus_get_node(dev); - OF_device_register_xref(OF_xref_from_node(node), dev); -#endif - - bus_generic_attach(dev); - - return (busdev); + return (child); } +static int +pwmbus_child_location_str(device_t dev, device_t child, char *buf, size_t blen) +{ + struct pwmbus_ivars *ivars; + + ivars = device_get_ivars(child); + snprintf(buf, blen, "hwdev=%s channel=%u", + device_get_nameunit(device_get_parent(dev)), ivars->pi_channel); + + return (0); +} + +static int +pwmbus_child_pnpinfo_str(device_t dev, device_t child, char *buf, + size_t buflen) +{ + *buf = '\0'; + return (0); +} + +static void +pwmbus_hinted_child(device_t dev, const char *dname, int dunit) +{ + struct pwmbus_ivars *ivars; + device_t child; + + child = pwmbus_add_child(dev, 0, dname, dunit); + + /* + * If there is a channel hint, use it. Otherwise pi_channel was + * initialized to zero, so that's the channel we'll use. + */ + ivars = device_get_ivars(child); + resource_int_value(dname, dunit, "channel", &ivars->pi_channel); +} + +static int +pwmbus_print_child(device_t dev, device_t child) +{ + struct pwmbus_ivars *ivars; + int rv; + + ivars = device_get_ivars(child); + + rv = bus_print_child_header(dev, child); + rv += printf(" channel %u", ivars->pi_channel); + rv += bus_print_child_footer(dev, child); + + return (rv); +} + +static void +pwmbus_probe_nomatch(device_t dev, device_t child) +{ + struct pwmbus_ivars *ivars; + + ivars = device_get_ivars(child); + if (ivars != NULL) + device_printf(dev, " on channel %u\n", + ivars->pi_channel); + + return; +} + +static int +pwmbus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct pwmbus_ivars *ivars; + + ivars = device_get_ivars(child); + + switch (which) { + case PWMBUS_IVAR_CHANNEL: + *(u_int *)result = ivars->pi_channel; + break; + default: + return (EINVAL); + } + + return (0); +} + +/* + * device_if methods... + */ + static int pwmbus_probe(device_t dev) { - device_set_desc(dev, "PWM bus"); return (BUS_PROBE_GENERIC); } @@ -102,17 +165,33 @@ static int pwmbus_attach(device_t dev) { struct pwmbus_softc *sc; + struct pwmbus_ivars *ivars; + device_t child, parent; + u_int chan; sc = device_get_softc(dev); - sc->busdev = dev; - sc->dev = device_get_parent(dev); + sc->dev = dev; + parent = device_get_parent(dev); - if (PWM_CHANNEL_MAX(sc->dev, &sc->nchannels) != 0 || - sc->nchannels == 0) + if (PWMBUS_CHANNEL_COUNT(parent, &sc->nchannels) != 0 || + sc->nchannels == 0) { + device_printf(sc->dev, "No channels on parent %s\n", + device_get_nameunit(parent)); return (ENXIO); + } - if (bootverbose) - device_printf(dev, "Registering %d channel(s)\n", sc->nchannels); + /* Add a pwmc(4) child for each channel. */ + for (chan = 0; chan < sc->nchannels; ++chan) { + if ((child = pwmbus_add_child(sc->dev, 0, "pwmc", -1)) == NULL) { + device_printf(dev, "failed to add pwmc child device " + "for channel %u\n", chan); + continue; + } + ivars = device_get_ivars(child); + ivars->pi_channel = chan; + } + + bus_enumerate_hinted_children(dev); bus_generic_probe(dev); return (bus_generic_attach(dev)); @@ -121,113 +200,83 @@ pwmbus_attach(device_t dev) static int pwmbus_detach(device_t dev) { - device_t *devlist; - int i, rv, ndevs; + int rv; - rv = bus_generic_detach(dev); - if (rv != 0) - return (rv); + if ((rv = bus_generic_detach(dev)) == 0) + rv = device_delete_children(dev); - rv = device_get_children(dev, &devlist, &ndevs); - if (rv != 0) - return (rv); - for (i = 0; i < ndevs; i++) - device_delete_child(dev, devlist[i]); + return (rv); +} - return (0); +/* + * pwmbus_if methods... + */ + +static int +pwmbus_channel_config(device_t dev, u_int chan, u_int period, u_int duty) +{ + return (PWMBUS_CHANNEL_CONFIG(device_get_parent(dev), chan, period, duty)); } static int -pwmbus_channel_config(device_t bus, int channel, unsigned int period, unsigned int duty) +pwmbus_channel_get_config(device_t dev, u_int chan, u_int *period, u_int *duty) { - struct pwmbus_softc *sc; - - sc = device_get_softc(bus); - - if (channel > sc->nchannels) - return (EINVAL); - - return (PWM_CHANNEL_CONFIG(sc->dev, channel, period, duty)); + return (PWMBUS_CHANNEL_GET_CONFIG(device_get_parent(dev), chan, period, duty)); } static int -pwmbus_channel_get_config(device_t bus, int channel, unsigned int *period, unsigned int *duty) +pwmbus_channel_get_flags(device_t dev, u_int chan, uint32_t *flags) { - struct pwmbus_softc *sc; - - sc = device_get_softc(bus); - - if (channel > sc->nchannels) - return (EINVAL); - - return (PWM_CHANNEL_GET_CONFIG(sc->dev, channel, period, duty)); + return (PWMBUS_CHANNEL_GET_FLAGS(device_get_parent(dev), chan, flags)); } static int -pwmbus_channel_set_flags(device_t bus, int channel, uint32_t flags) +pwmbus_channel_enable(device_t dev, u_int chan, bool enable) { - struct pwmbus_softc *sc; - - sc = device_get_softc(bus); - - if (channel > sc->nchannels) - return (EINVAL); - - return (PWM_CHANNEL_SET_FLAGS(sc->dev, channel, flags)); + return (PWMBUS_CHANNEL_ENABLE(device_get_parent(dev), chan, enable)); } static int -pwmbus_channel_get_flags(device_t bus, int channel, uint32_t *flags) +pwmbus_channel_set_flags(device_t dev, u_int chan, uint32_t flags) { - struct pwmbus_softc *sc; - - sc = device_get_softc(bus); - - if (channel > sc->nchannels) - return (EINVAL); - - return (PWM_CHANNEL_GET_FLAGS(sc->dev, channel, flags)); + return (PWMBUS_CHANNEL_SET_FLAGS(device_get_parent(dev), chan, flags)); } static int -pwmbus_channel_enable(device_t bus, int channel, bool enable) +pwmbus_channel_is_enabled(device_t dev, u_int chan, bool *enable) { - struct pwmbus_softc *sc; - - sc = device_get_softc(bus); - - if (channel > sc->nchannels) - return (EINVAL); - - return (PWM_CHANNEL_ENABLE(sc->dev, channel, enable)); + return (PWMBUS_CHANNEL_IS_ENABLED(device_get_parent(dev), chan, enable)); } static int -pwmbus_channel_is_enabled(device_t bus, int channel, bool *enable) +pwmbus_channel_count(device_t dev, u_int *nchannel) { - struct pwmbus_softc *sc; - - sc = device_get_softc(bus); - - if (channel > sc->nchannels) - return (EINVAL); - - return (PWM_CHANNEL_IS_ENABLED(sc->dev, channel, enable)); + return (PWMBUS_CHANNEL_COUNT(device_get_parent(dev), nchannel)); } static device_method_t pwmbus_methods[] = { /* device_if */ - DEVMETHOD(device_probe, pwmbus_probe), + DEVMETHOD(device_probe, pwmbus_probe), DEVMETHOD(device_attach, pwmbus_attach), DEVMETHOD(device_detach, pwmbus_detach), - /* pwm interface */ - DEVMETHOD(pwmbus_channel_config, pwmbus_channel_config), - DEVMETHOD(pwmbus_channel_get_config, pwmbus_channel_get_config), - DEVMETHOD(pwmbus_channel_set_flags, pwmbus_channel_set_flags), - DEVMETHOD(pwmbus_channel_get_flags, pwmbus_channel_get_flags), - DEVMETHOD(pwmbus_channel_enable, pwmbus_channel_enable), - DEVMETHOD(pwmbus_channel_is_enabled, pwmbus_channel_is_enabled), + /* bus_if */ + DEVMETHOD(bus_add_child, pwmbus_add_child), + DEVMETHOD(bus_child_location_str, pwmbus_child_location_str), + DEVMETHOD(bus_child_pnpinfo_str, pwmbus_child_pnpinfo_str), + DEVMETHOD(bus_hinted_child, pwmbus_hinted_child), + DEVMETHOD(bus_print_child, pwmbus_print_child), + DEVMETHOD(bus_probe_nomatch, pwmbus_probe_nomatch), + DEVMETHOD(bus_read_ivar, pwmbus_read_ivar), + + /* pwmbus_if */ + DEVMETHOD(pwmbus_channel_count, pwmbus_channel_count), + DEVMETHOD(pwmbus_channel_config, pwmbus_channel_config), + DEVMETHOD(pwmbus_channel_get_config, pwmbus_channel_get_config), + DEVMETHOD(pwmbus_channel_set_flags, pwmbus_channel_set_flags), + DEVMETHOD(pwmbus_channel_get_flags, pwmbus_channel_get_flags), + DEVMETHOD(pwmbus_channel_enable, pwmbus_channel_enable), + DEVMETHOD(pwmbus_channel_is_enabled, pwmbus_channel_is_enabled), DEVMETHOD_END }; @@ -240,5 +289,5 @@ driver_t pwmbus_driver = { devclass_t pwmbus_devclass; EARLY_DRIVER_MODULE(pwmbus, pwm, pwmbus_driver, pwmbus_devclass, 0, 0, - BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE); + BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); MODULE_VERSION(pwmbus, 1); diff --git a/sys/dev/pwm/pwmbus.h b/sys/dev/pwm/pwmbus.h index 077c7d0f3d59..7ace2ef41b1b 100644 --- a/sys/dev/pwm/pwmbus.h +++ b/sys/dev/pwm/pwmbus.h @@ -1,8 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2018 Emmanuel Vadot - * All rights reserved. + * Copyright (c) 2019 Ian Lepore * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,36 +28,46 @@ */ #ifndef _PWMBUS_H_ +#define _PWMBUS_H_ -#include -#include - -struct pwm_channel { +struct pwmbus_softc { device_t dev; - device_t busdev; - int channel; - uint64_t period; - uint64_t duty; - uint32_t flags; - bool enabled; + u_int nchannels; }; -typedef struct pwm_channel *pwm_channel_t; -device_t pwmbus_attach_bus(device_t dev); -int pwmbus_acquire_channel(device_t bus, int channel); -int pwmbus_release_channel(device_t bus, int channel); +struct pwmbus_ivars { + u_int pi_channel; +}; -int -pwm_get_by_ofw_propidx(device_t consumer, phandle_t node, - const char *prop_name, int idx, pwm_channel_t *channel); -int -pwm_get_by_ofw_idx(device_t consumer, phandle_t node, int idx, - pwm_channel_t *out_channel); -int -pwm_get_by_ofw_property(device_t consumer, phandle_t node, - const char *prop_name, pwm_channel_t *out_channel); -int -pwm_get_by_ofw_name(device_t consumer, phandle_t node, const char *name, - pwm_channel_t *out_channel); +enum { + PWMBUS_IVAR_CHANNEL, /* Channel used by child dev */ +}; + +#define PWMBUS_ACCESSOR(A, B, T) \ +static inline int \ +pwmbus_get_ ## A(device_t dev, T *t) \ +{ \ + return BUS_READ_IVAR(device_get_parent(dev), dev, \ + PWMBUS_IVAR_ ## B, (uintptr_t *) t); \ +} \ +static inline int \ +pwmbus_set_ ## A(device_t dev, T t) \ +{ \ + return BUS_WRITE_IVAR(device_get_parent(dev), dev, \ + PWMBUS_IVAR_ ## B, (uintptr_t) t); \ +} + +PWMBUS_ACCESSOR(channel, CHANNEL, u_int) + +#ifdef FDT +#define PWMBUS_FDT_PNP_INFO(t) FDTCOMPAT_PNP_INFO(t, pwmbus) +#else +#define PWMBUS_FDT_PNP_INFO(t) +#endif + +extern driver_t pwmbus_driver; +extern devclass_t pwmbus_devclass; +extern driver_t ofw_pwmbus_driver; +extern devclass_t ofw_pwmbus_devclass; #endif /* _PWMBUS_H_ */ diff --git a/sys/dev/pwm/pwmbus_if.m b/sys/dev/pwm/pwmbus_if.m index 23ecf237b2de..4e7b49bf405c 100644 --- a/sys/dev/pwm/pwmbus_if.m +++ b/sys/dev/pwm/pwmbus_if.m @@ -33,14 +33,14 @@ INTERFACE pwmbus; CODE { static int - pwm_default_set_flags(device_t dev, int channel, uint32_t flags) + pwm_default_set_flags(device_t dev, u_int channel, uint32_t flags) { return (EOPNOTSUPP); } static int - pwm_default_get_flags(device_t dev, int channel, uint32_t *flags) + pwm_default_get_flags(device_t dev, u_int channel, uint32_t *flags) { *flags = 0; @@ -48,17 +48,13 @@ CODE { } }; -HEADER { - #include -}; - # # Config the period (Total number of cycle in ns) and # the duty (active number of cycle in ns) # METHOD int channel_config { device_t bus; - int channel; + u_int channel; unsigned int period; unsigned int duty; }; @@ -69,7 +65,7 @@ METHOD int channel_config { # METHOD int channel_get_config { device_t bus; - int channel; + u_int channel; unsigned int *period; unsigned int *duty; }; @@ -79,7 +75,7 @@ METHOD int channel_get_config { # METHOD int channel_set_flags { device_t bus; - int channel; + u_int channel; uint32_t flags; } DEFAULT pwm_default_set_flags; @@ -88,7 +84,7 @@ METHOD int channel_set_flags { # METHOD int channel_get_flags { device_t dev; - int channel; + u_int channel; uint32_t *flags; } DEFAULT pwm_default_get_flags; @@ -97,7 +93,7 @@ METHOD int channel_get_flags { # METHOD int channel_enable { device_t bus; - int channel; + u_int channel; bool enable; }; @@ -106,6 +102,14 @@ METHOD int channel_enable { # METHOD int channel_is_enabled { device_t bus; - int channel; + u_int channel; bool *enabled; }; + +# +# Get the number of channels +# +METHOD int channel_count { + device_t bus; + u_int *nchannel; +}; diff --git a/sys/dev/pwm/pwmc.c b/sys/dev/pwm/pwmc.c index 18bebcca8f62..53a719e01593 100644 --- a/sys/dev/pwm/pwmc.c +++ b/sys/dev/pwm/pwmc.c @@ -29,6 +29,8 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_platform.h" + #include #include #include @@ -37,16 +39,29 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include +#include #include "pwmbus_if.h" -#include "pwm_if.h" + +#ifdef FDT +#include +#include +#include + +static struct ofw_compat_data compat_data[] = { + {"freebsd,pwmc", true}, + {NULL, false}, +}; + +PWMBUS_FDT_PNP_INFO(compat_data); + +#endif struct pwmc_softc { device_t dev; - device_t pdev; - struct cdev *pwm_dev; - char name[32]; + struct cdev *cdev; + u_int chan; }; static int @@ -56,35 +71,27 @@ pwm_ioctl(struct cdev *dev, u_long cmd, caddr_t data, struct pwmc_softc *sc; struct pwm_state state; device_t bus; - int nchannel; int rv = 0; sc = dev->si_drv1; - bus = PWM_GET_BUS(sc->pdev); - if (bus == NULL) - return (EINVAL); + bus = device_get_parent(sc->dev); switch (cmd) { - case PWMMAXCHANNEL: - nchannel = -1; - rv = PWM_CHANNEL_MAX(sc->pdev, &nchannel); - bcopy(&nchannel, data, sizeof(nchannel)); - break; case PWMSETSTATE: bcopy(data, &state, sizeof(state)); - rv = PWMBUS_CHANNEL_CONFIG(bus, state.channel, + rv = PWMBUS_CHANNEL_CONFIG(bus, sc->chan, state.period, state.duty); if (rv == 0) - rv = PWMBUS_CHANNEL_ENABLE(bus, state.channel, + rv = PWMBUS_CHANNEL_ENABLE(bus, sc->chan, state.enable); break; case PWMGETSTATE: bcopy(data, &state, sizeof(state)); - rv = PWMBUS_CHANNEL_GET_CONFIG(bus, state.channel, + rv = PWMBUS_CHANNEL_GET_CONFIG(bus, sc->chan, &state.period, &state.duty); if (rv != 0) return (rv); - rv = PWMBUS_CHANNEL_IS_ENABLED(bus, state.channel, + rv = PWMBUS_CHANNEL_IS_ENABLED(bus, sc->chan, &state.enable); if (rv != 0) return (rv); @@ -97,16 +104,47 @@ pwm_ioctl(struct cdev *dev, u_long cmd, caddr_t data, static struct cdevsw pwm_cdevsw = { .d_version = D_VERSION, - .d_name = "pwm", + .d_name = "pwmc", .d_ioctl = pwm_ioctl }; +static void +pwmc_setup_label(struct pwmc_softc *sc) +{ + const char *hintlabel; +#ifdef FDT + void *label; + + if (OF_getprop_alloc(ofw_bus_get_node(sc->dev), "label", &label) > 0) { + make_dev_alias(sc->cdev, "pwm/%s", (char *)label); + OF_prop_free(label); + } +#endif + + if (resource_string_value(device_get_name(sc->dev), + device_get_unit(sc->dev), "label", &hintlabel) == 0) { + make_dev_alias(sc->cdev, "pwm/%s", hintlabel); + } +} + static int pwmc_probe(device_t dev) { + int rv; - device_set_desc(dev, "PWM Controller"); - return (0); + rv = BUS_PROBE_NOWILDCARD; + +#ifdef FDT + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) { + rv = BUS_PROBE_DEFAULT; + } +#endif + + device_set_desc(dev, "PWM Control"); + return (rv); } static int @@ -114,29 +152,40 @@ pwmc_attach(device_t dev) { struct pwmc_softc *sc; struct make_dev_args args; + int error; sc = device_get_softc(dev); sc->dev = dev; - sc->pdev = device_get_parent(dev); - snprintf(sc->name, sizeof(sc->name), "pwmc%d", device_get_unit(dev)); + if ((error = pwmbus_get_channel(dev, &sc->chan)) != 0) + return (error); + make_dev_args_init(&args); args.mda_flags = MAKEDEV_CHECKNAME | MAKEDEV_WAITOK; args.mda_devsw = &pwm_cdevsw; args.mda_uid = UID_ROOT; args.mda_gid = GID_OPERATOR; - args.mda_mode = 0600; + args.mda_mode = 0660; args.mda_si_drv1 = sc; - if (make_dev_s(&args, &sc->pwm_dev, "%s", sc->name) != 0) { + error = make_dev_s(&args, &sc->cdev, "pwm/pwmc%d.%d", + device_get_unit(device_get_parent(dev)), sc->chan); + if (error != 0) { device_printf(dev, "Failed to make PWM device\n"); - return (ENXIO); + return (error); } + + pwmc_setup_label(sc); + return (0); } static int pwmc_detach(device_t dev) { + struct pwmc_softc *sc; + + sc = device_get_softc(dev); + destroy_dev(sc->cdev); return (0); } @@ -150,12 +199,13 @@ static device_method_t pwmc_methods[] = { DEVMETHOD_END }; -driver_t pwmc_driver = { +static driver_t pwmc_driver = { "pwmc", pwmc_methods, sizeof(struct pwmc_softc), }; -devclass_t pwmc_devclass; +static devclass_t pwmc_devclass; -DRIVER_MODULE(pwmc, pwm, pwmc_driver, pwmc_devclass, 0, 0); +DRIVER_MODULE(pwmc, pwmbus, pwmc_driver, pwmc_devclass, 0, 0); +MODULE_DEPEND(pwmc, pwmbus, 1, 1, 1); MODULE_VERSION(pwmc, 1); diff --git a/sys/sys/pwm.h b/sys/dev/pwm/pwmc.h similarity index 88% rename from sys/sys/pwm.h rename to sys/dev/pwm/pwmc.h index 9940c8cad9e9..333243e941a7 100644 --- a/sys/sys/pwm.h +++ b/sys/dev/pwm/pwmc.h @@ -34,9 +34,8 @@ #define PWM_POLARITY_INVERTED (1 << 0) struct pwm_state { - int channel; - unsigned int period; - unsigned int duty; + u_int period; + u_int duty; uint32_t flags; bool enable; }; @@ -45,9 +44,8 @@ struct pwm_state { * ioctls */ -#define PWMMAXCHANNEL _IOWR('G', 0, int) -#define PWMGETSTATE _IOWR('G', 1, struct pwm_state) -#define PWMSETSTATE _IOWR('G', 2, struct pwm_state) +#define PWMGETSTATE _IOWR('G', 0, struct pwm_state) +#define PWMSETSTATE _IOWR('G', 1, struct pwm_state) #endif /* _PWM_H_ */ diff --git a/sys/dev/random/fortuna.c b/sys/dev/random/fortuna.c index b0ab6e88c69e..0e66ba3e97f6 100644 --- a/sys/dev/random/fortuna.c +++ b/sys/dev/random/fortuna.c @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include "unit_test.h" #endif /* _KERNEL */ +#include #include #include @@ -75,7 +76,10 @@ __FBSDID("$FreeBSD$"); /* Defined in FS&K */ #define RANDOM_FORTUNA_NPOOLS 32 /* The number of accumulation pools */ #define RANDOM_FORTUNA_DEFPOOLSIZE 64 /* The default pool size/length for a (re)seed */ -#define RANDOM_FORTUNA_MAX_READ (1 << 20) /* Max bytes in a single read */ +#define RANDOM_FORTUNA_MAX_READ (1 << 20) /* Max bytes from AES before rekeying */ +#define RANDOM_FORTUNA_BLOCKS_PER_KEY (1 << 16) /* Max blocks from AES before rekeying */ +CTASSERT(RANDOM_FORTUNA_BLOCKS_PER_KEY * RANDOM_BLOCKSIZE == + RANDOM_FORTUNA_MAX_READ); /* * The allowable range of RANDOM_FORTUNA_DEFPOOLSIZE. The default value is above. @@ -120,6 +124,26 @@ static struct fortuna_state { mtx_t fs_mtx; } fortuna_state; +/* + * Experimental concurrent reads feature. For now, disabled by default. But + * we may enable it in the future. + * + * The benefit is improved concurrency in Fortuna. That is reflected in two + * related aspects: + * + * 1. Concurrent devrandom readers can achieve similar throughput to a single + * reader thread. + * + * 2. The rand_harvestq process spends much less time spinning when one or more + * readers is processing a large request. Partially this is due to + * rand_harvestq / ra_event_processor design, which only passes one event at + * a time to the underlying algorithm. Each time, Fortuna must take its + * global state mutex, potentially blocking on a reader. Our adaptive + * mutexes assume that a lock holder currently on CPU will release the lock + * quickly, and spin if the owning thread is currently running. + */ +static bool fortuna_concurrent_read __read_frequently = false; + #ifdef _KERNEL static struct sysctl_ctx_list random_clist; RANDOM_CHECK_UINT(fs_minpoolsize, RANDOM_FORTUNA_MINPOOLSIZE, RANDOM_FORTUNA_MAXPOOLSIZE); @@ -128,7 +152,7 @@ static uint8_t zero_region[RANDOM_ZERO_BLOCKSIZE]; #endif static void random_fortuna_pre_read(void); -static void random_fortuna_read(uint8_t *, u_int); +static void random_fortuna_read(uint8_t *, size_t); static bool random_fortuna_seeded(void); static bool random_fortuna_seeded_internal(void); static void random_fortuna_process_event(struct harvest_event *); @@ -176,6 +200,11 @@ random_fortuna_init_alg(void *unused __unused) random_check_uint_fs_minpoolsize, "IU", "Minimum pool size necessary to cause a reseed"); KASSERT(fortuna_state.fs_minpoolsize > 0, ("random: Fortuna threshold must be > 0 at startup")); + + SYSCTL_ADD_BOOL(&random_clist, SYSCTL_CHILDREN(random_fortuna_o), + OID_AUTO, "concurrent_read", CTLFLAG_RDTUN, + &fortuna_concurrent_read, 0, "If non-zero, enable EXPERIMENTAL " + "feature to improve concurrent Fortuna performance."); #endif /*- @@ -305,52 +334,6 @@ random_fortuna_reseed_internal(uint32_t *entropy_data, u_int blockcount) uint128_increment(&fortuna_state.fs_counter); } -/*- - * FS&K - GenerateBlocks() - * Generate a number of complete blocks of random output. - */ -static __inline void -random_fortuna_genblocks(uint8_t *buf, u_int blockcount) -{ - - RANDOM_RESEED_ASSERT_LOCK_OWNED(); - KASSERT(!uint128_is_zero(fortuna_state.fs_counter), ("FS&K: C != 0")); - - /* - * Fills buf with RANDOM_BLOCKSIZE * blockcount bytes of keystream. - * Increments fs_counter as it goes. - */ - randomdev_keystream(&fortuna_state.fs_key, &fortuna_state.fs_counter, - buf, blockcount); -} - -/*- - * FS&K - PseudoRandomData() - * This generates no more than 2^20 bytes of data, and cleans up its - * internal state when finished. It is assumed that a whole number of - * blocks are available for writing; any excess generated will be - * ignored. - */ -static __inline void -random_fortuna_genrandom(uint8_t *buf, u_int bytecount) -{ - uint8_t temp[RANDOM_BLOCKSIZE * RANDOM_KEYS_PER_BLOCK]; - u_int blockcount; - - RANDOM_RESEED_ASSERT_LOCK_OWNED(); - /*- - * FS&K - assert(n < 2^20 (== 1 MB) - * - r = first-n-bytes(GenerateBlocks(ceil(n/16))) - * - K = GenerateBlocks(2) - */ - KASSERT((bytecount <= RANDOM_FORTUNA_MAX_READ), ("invalid single read request to Fortuna of %d bytes", bytecount)); - blockcount = howmany(bytecount, RANDOM_BLOCKSIZE); - random_fortuna_genblocks(buf, blockcount); - random_fortuna_genblocks(temp, RANDOM_KEYS_PER_BLOCK); - randomdev_encrypt_init(&fortuna_state.fs_key, temp); - explicit_bzero(temp, sizeof(temp)); -} - /*- * FS&K - RandomData() (Part 1) * Used to return processed entropy from the PRNG. There is a pre_read @@ -437,22 +420,267 @@ random_fortuna_pre_read(void) explicit_bzero(temp, sizeof(temp)); } +/* + * This is basically GenerateBlocks() from FS&K. + * + * It differs in two ways: + * + * 1. Chacha20 is tolerant of non-block-multiple request sizes, so we do not + * need to handle any remainder bytes specially and can just pass the length + * directly to the PRF construction; and + * + * 2. Chacha20 is a 512-bit block size cipher (whereas AES has 128-bit block + * size, regardless of key size). This means Chacha does not require re-keying + * every 1MiB. This is implied by the math in FS&K 9.4 and mentioned + * explicitly in the conclusion, "If we had a block cipher with a 256-bit [or + * greater] block size, then the collisions would not have been an issue at + * all" (p. 144). + * + * 3. In conventional ("locked") mode, we produce a maximum of PAGE_SIZE output + * at a time before dropping the lock, to not bully the lock especially. This + * has been the status quo since 2015 (r284959). + * + * The upstream caller random_fortuna_read is responsible for zeroing out + * sensitive buffers provided as parameters to this routine. + */ +enum { + FORTUNA_UNLOCKED = false, + FORTUNA_LOCKED = true +}; +static void +random_fortuna_genbytes(uint8_t *buf, size_t bytecount, + uint8_t newkey[static RANDOM_KEYSIZE], uint128_t *p_counter, + union randomdev_key *p_key, bool locked) +{ + uint8_t remainder_buf[RANDOM_BLOCKSIZE]; + size_t chunk_size; + + if (locked) + RANDOM_RESEED_ASSERT_LOCK_OWNED(); + else + RANDOM_RESEED_ASSERT_LOCK_NOT_OWNED(); + + /* + * Easy case: don't have to worry about bullying the global mutex, + * don't have to worry about rekeying Chacha; API is byte-oriented. + */ + if (!locked && random_chachamode) { + randomdev_keystream(p_key, p_counter, buf, bytecount); + return; + } + + if (locked) { + /* + * While holding the global lock, limit PRF generation to + * mitigate, but not eliminate, bullying symptoms. + */ + chunk_size = PAGE_SIZE; + } else { + /* + * 128-bit block ciphers like AES must be re-keyed at 1MB + * intervals to avoid unacceptable statistical differentiation + * from true random data (FS&K 9.4, p. 143-144). + */ + MPASS(!random_chachamode); + chunk_size = RANDOM_FORTUNA_MAX_READ; + } + + chunk_size = MIN(bytecount, chunk_size); + if (!random_chachamode) + chunk_size = rounddown(chunk_size, RANDOM_BLOCKSIZE); + + while (bytecount >= chunk_size && chunk_size > 0) { + randomdev_keystream(p_key, p_counter, buf, chunk_size); + + buf += chunk_size; + bytecount -= chunk_size; + + /* We have to rekey if there is any data remaining to be + * generated, in two scenarios: + * + * locked: we need to rekey before we unlock and release the + * global state to another consumer; or + * + * unlocked: we need to rekey because we're in AES mode and are + * required to rekey at chunk_size==1MB. But we do not need to + * rekey during the last trailing <1MB chunk. + */ + if (bytecount > 0) { + if (locked || chunk_size == RANDOM_FORTUNA_MAX_READ) { + randomdev_keystream(p_key, p_counter, newkey, + RANDOM_KEYSIZE); + randomdev_encrypt_init(p_key, newkey); + } + + /* + * If we're holding the global lock, yield it briefly + * now. + */ + if (locked) { + RANDOM_RESEED_UNLOCK(); + RANDOM_RESEED_LOCK(); + } + + /* + * At the trailing end, scale down chunk_size from 1MB or + * PAGE_SIZE to all remaining full blocks (AES) or all + * remaining bytes (Chacha). + */ + if (bytecount < chunk_size) { + if (random_chachamode) + chunk_size = bytecount; + else if (bytecount >= RANDOM_BLOCKSIZE) + chunk_size = rounddown(bytecount, + RANDOM_BLOCKSIZE); + else + break; + } + } + } + + /* + * Generate any partial AES block remaining into a temporary buffer and + * copy the desired substring out. + */ + if (bytecount > 0) { + MPASS(!random_chachamode); + + randomdev_keystream(p_key, p_counter, remainder_buf, + sizeof(remainder_buf)); + } + + /* + * In locked mode, re-key global K before dropping the lock, which we + * don't need for memcpy/bzero below. + */ + if (locked) { + randomdev_keystream(p_key, p_counter, newkey, RANDOM_KEYSIZE); + randomdev_encrypt_init(p_key, newkey); + RANDOM_RESEED_UNLOCK(); + } + + if (bytecount > 0) { + memcpy(buf, remainder_buf, bytecount); + explicit_bzero(remainder_buf, sizeof(remainder_buf)); + } +} + + +/* + * Handle only "concurrency-enabled" Fortuna reads to simplify logic. + * + * Caller (random_fortuna_read) is responsible for zeroing out sensitive + * buffers provided as parameters to this routine. + */ +static void +random_fortuna_read_concurrent(uint8_t *buf, size_t bytecount, + uint8_t newkey[static RANDOM_KEYSIZE]) +{ + union randomdev_key key_copy; + uint128_t counter_copy; + size_t blockcount; + + MPASS(fortuna_concurrent_read); + + /* + * Compute number of blocks required for the PRF request ('delta C'). + * We will step the global counter 'C' by this number under lock, and + * then actually consume the counter values outside the lock. + * + * This ensures that contemporaneous but independent requests for + * randomness receive distinct 'C' values and thus independent PRF + * results. + */ + if (random_chachamode) { + blockcount = howmany(bytecount, CHACHA_BLOCKLEN); + } else { + blockcount = howmany(bytecount, RANDOM_BLOCKSIZE); + + /* + * Need to account for the additional blocks generated by + * rekeying when updating the global fs_counter. + */ + blockcount += RANDOM_KEYS_PER_BLOCK * + (blockcount / RANDOM_FORTUNA_BLOCKS_PER_KEY); + } + + RANDOM_RESEED_LOCK(); + KASSERT(!uint128_is_zero(fortuna_state.fs_counter), ("FS&K: C != 0")); + /* + * Technically, we only need mutual exclusion to update shared state + * appropriately. Nothing about updating the shared internal state + * requires that we perform (most) expensive cryptographic keystream + * generation under lock. (We still need to generate 256 bits of + * keystream to re-key between consumers.) + * + * Save the original counter and key values that will be used as the + * PRF for this particular consumer. + */ + memcpy(&counter_copy, &fortuna_state.fs_counter, sizeof(counter_copy)); + memcpy(&key_copy, &fortuna_state.fs_key, sizeof(key_copy)); + + /* + * Step the counter as if we had generated 'bytecount' blocks for this + * consumer. I.e., ensure that the next consumer gets an independent + * range of counter values once we drop the global lock. + */ + uint128_add64(&fortuna_state.fs_counter, blockcount); + + /* + * We still need to Rekey the global 'K' between independent calls; + * this is no different from conventional Fortuna. Note that + * 'randomdev_keystream()' will step the fs_counter 'C' appropriately + * for the blocks needed for the 'newkey'. + * + * (This is part of PseudoRandomData() in FS&K, 9.4.4.) + */ + randomdev_keystream(&fortuna_state.fs_key, &fortuna_state.fs_counter, + newkey, RANDOM_KEYSIZE); + randomdev_encrypt_init(&fortuna_state.fs_key, newkey); + + /* + * We have everything we need to generate a unique PRF for this + * consumer without touching global state. + */ + RANDOM_RESEED_UNLOCK(); + + random_fortuna_genbytes(buf, bytecount, newkey, &counter_copy, + &key_copy, FORTUNA_UNLOCKED); + RANDOM_RESEED_ASSERT_LOCK_NOT_OWNED(); + + explicit_bzero(&counter_copy, sizeof(counter_copy)); + explicit_bzero(&key_copy, sizeof(key_copy)); +} + /*- * FS&K - RandomData() (Part 2) * Main read from Fortuna, continued. May be called multiple times after * the random_fortuna_pre_read() above. - * The supplied buf MUST be a multiple of RANDOM_BLOCKSIZE in size. - * Lots of code presumes this for efficiency, both here and in other - * routines. You are NOT allowed to break this! + * + * The supplied buf MAY not be a multiple of RANDOM_BLOCKSIZE in size; it is + * the responsibility of the algorithm to accommodate partial block reads, if a + * block output mode is used. */ void -random_fortuna_read(uint8_t *buf, u_int bytecount) +random_fortuna_read(uint8_t *buf, size_t bytecount) { + uint8_t newkey[RANDOM_KEYSIZE]; + + if (fortuna_concurrent_read) { + random_fortuna_read_concurrent(buf, bytecount, newkey); + goto out; + } - KASSERT((bytecount % RANDOM_BLOCKSIZE) == 0, ("%s(): bytecount (= %d) must be a multiple of %d", __func__, bytecount, RANDOM_BLOCKSIZE )); RANDOM_RESEED_LOCK(); - random_fortuna_genrandom(buf, bytecount); - RANDOM_RESEED_UNLOCK(); + KASSERT(!uint128_is_zero(fortuna_state.fs_counter), ("FS&K: C != 0")); + + random_fortuna_genbytes(buf, bytecount, newkey, + &fortuna_state.fs_counter, &fortuna_state.fs_key, FORTUNA_LOCKED); + /* Returns unlocked */ + RANDOM_RESEED_ASSERT_LOCK_NOT_OWNED(); + +out: + explicit_bzero(newkey, sizeof(newkey)); } #ifdef _KERNEL diff --git a/sys/dev/random/fortuna.h b/sys/dev/random/fortuna.h index 43aad04fb13c..3b75a008d91d 100644 --- a/sys/dev/random/fortuna.h +++ b/sys/dev/random/fortuna.h @@ -36,12 +36,14 @@ typedef struct mtx mtx_t; #define RANDOM_RESEED_LOCK(x) mtx_lock(&fortuna_state.fs_mtx) #define RANDOM_RESEED_UNLOCK(x) mtx_unlock(&fortuna_state.fs_mtx) #define RANDOM_RESEED_ASSERT_LOCK_OWNED(x) mtx_assert(&fortuna_state.fs_mtx, MA_OWNED) +#define RANDOM_RESEED_ASSERT_LOCK_NOT_OWNED() mtx_assert(&fortuna_state.fs_mtx, MA_NOTOWNED) #else #define RANDOM_RESEED_INIT_LOCK(x) mtx_init(&fortuna_state.fs_mtx, mtx_plain) #define RANDOM_RESEED_DEINIT_LOCK(x) mtx_destroy(&fortuna_state.fs_mtx) #define RANDOM_RESEED_LOCK(x) mtx_lock(&fortuna_state.fs_mtx) #define RANDOM_RESEED_UNLOCK(x) mtx_unlock(&fortuna_state.fs_mtx) #define RANDOM_RESEED_ASSERT_LOCK_OWNED(x) +#define RANDOM_RESEED_ASSERT_LOCK_NOT_OWNED() #endif #endif /* SYS_DEV_RANDOM_FORTUNA_H_INCLUDED */ diff --git a/sys/dev/random/hash.c b/sys/dev/random/hash.c index 2f3cb4738bc6..99965513350d 100644 --- a/sys/dev/random/hash.c +++ b/sys/dev/random/hash.c @@ -37,12 +37,16 @@ __FBSDID("$FreeBSD$"); #else /* !_KERNEL */ #include #include +#include #include +#include +#include #include #include #include #include -#include "unit_test.h" +#define KASSERT(x, y) assert(x) +#define CTASSERT(x) _Static_assert(x, "CTASSERT " #x) #endif /* _KERNEL */ #define CHACHA_EMBED @@ -70,7 +74,7 @@ _Static_assert(CHACHA_STATELEN == RANDOM_BLOCKSIZE, ""); * Benefits include somewhat faster keystream generation compared with * unaccelerated AES-ICM. */ -bool random_chachamode = false; +bool random_chachamode __read_frequently = false; #ifdef _KERNEL SYSCTL_BOOL(_kern_random, OID_AUTO, use_chacha20_cipher, CTLFLAG_RDTUN, &random_chachamode, 0, @@ -121,16 +125,18 @@ randomdev_encrypt_init(union randomdev_key *context, const void *data) } /* - * Create a psuedorandom output stream of 'blockcount' blocks using a CTR-mode + * Create a psuedorandom output stream of 'bytecount' bytes using a CTR-mode * cipher or similar. The 128-bit counter is supplied in the in-out parmeter - * 'ctr.' The output stream goes to 'd_out.' 'blockcount' RANDOM_BLOCKSIZE - * bytes are generated. + * 'ctr.' The output stream goes to 'd_out.' + * + * If AES is used, 'bytecount' is guaranteed to be a multiple of + * RANDOM_BLOCKSIZE. */ void randomdev_keystream(union randomdev_key *context, uint128_t *ctr, - void *d_out, u_int blockcount) + void *d_out, size_t bytecount) { - u_int i; + size_t i, blockcount, read_chunk; if (random_chachamode) { uint128_t lectr; @@ -143,8 +149,20 @@ randomdev_keystream(union randomdev_key *context, uint128_t *ctr, le128enc(&lectr, *ctr); chacha_ivsetup(&context->chacha, NULL, (const void *)&lectr); - chacha_encrypt_bytes(&context->chacha, NULL, d_out, - RANDOM_BLOCKSIZE * blockcount); + while (bytecount > 0) { + /* + * We are limited by the chacha_encrypt_bytes API to + * u32 bytes per chunk. + */ + read_chunk = MIN(bytecount, + rounddown((size_t)UINT32_MAX, CHACHA_BLOCKLEN)); + + chacha_encrypt_bytes(&context->chacha, NULL, d_out, + read_chunk); + + d_out = (char *)d_out + read_chunk; + bytecount -= read_chunk; + } /* * Decode Chacha-updated LE counter to native endian and store @@ -152,7 +170,14 @@ randomdev_keystream(union randomdev_key *context, uint128_t *ctr, */ chacha_ctrsave(&context->chacha, (void *)&lectr); *ctr = le128dec(&lectr); + + explicit_bzero(&lectr, sizeof(lectr)); } else { + KASSERT(bytecount % RANDOM_BLOCKSIZE == 0, + ("%s: AES mode invalid bytecount, not a multiple of native " + "block size", __func__)); + + blockcount = bytecount / RANDOM_BLOCKSIZE; for (i = 0; i < blockcount; i++) { /*- * FS&K - r = r|E(K,C) diff --git a/sys/dev/random/hash.h b/sys/dev/random/hash.h index bcc7035a0e4f..92a5950f9932 100644 --- a/sys/dev/random/hash.h +++ b/sys/dev/random/hash.h @@ -32,6 +32,10 @@ #include #include +#ifndef _KERNEL +#define __read_frequently +#endif + /* Keys are formed from cipher blocks */ #define RANDOM_KEYSIZE 32 /* (in bytes) == 256 bits */ #define RANDOM_KEYSIZE_WORDS (RANDOM_KEYSIZE/sizeof(uint32_t)) @@ -54,14 +58,14 @@ union randomdev_key { struct chacha_ctx chacha; }; -extern bool fortuna_chachamode; +extern bool random_chachamode; void randomdev_hash_init(struct randomdev_hash *); void randomdev_hash_iterate(struct randomdev_hash *, const void *, size_t); void randomdev_hash_finish(struct randomdev_hash *, void *); void randomdev_encrypt_init(union randomdev_key *, const void *); -void randomdev_keystream(union randomdev_key *context, uint128_t *, void *, u_int); +void randomdev_keystream(union randomdev_key *context, uint128_t *, void *, size_t); void randomdev_getkey(union randomdev_key *, const void **, size_t *); #endif /* SYS_DEV_RANDOM_HASH_H_INCLUDED */ diff --git a/sys/dev/random/other_algorithm.c b/sys/dev/random/other_algorithm.c index 57679f53a7da..4ed00c1156ff 100644 --- a/sys/dev/random/other_algorithm.c +++ b/sys/dev/random/other_algorithm.c @@ -84,7 +84,7 @@ __FBSDID("$FreeBSD$"); #endif /* _KERNEL */ static void random_other_pre_read(void); -static void random_other_read(uint8_t *, u_int); +static void random_other_read(uint8_t *, size_t); static bool random_other_seeded(void); static void random_other_process_event(struct harvest_event *); static void random_other_init_alg(void *); @@ -165,10 +165,10 @@ random_other_pre_read(void) } /* - * void random_other_read(uint8_t *buf, u_int count) + * void random_other_read(uint8_t *buf, size_t count) * * Generate bytes of output into <*buf>. - * You may use the fact that will be a multiple of + * You may NOT use the fact that will be a multiple of * RANDOM_BLOCKSIZE for optimization purposes. * * This function will always be called with your generator @@ -176,7 +176,7 @@ random_other_pre_read(void) * output here, then feel free to KASSERT() or panic(). */ static void -random_other_read(uint8_t *buf, u_int count) +random_other_read(uint8_t *buf, size_t count) { RANDOM_RESEED_LOCK(); diff --git a/sys/dev/random/randomdev.c b/sys/dev/random/randomdev.c index e20669b3c207..8af39deeb34b 100644 --- a/sys/dev/random/randomdev.c +++ b/sys/dev/random/randomdev.c @@ -172,17 +172,21 @@ randomdev_wait_until_seeded(bool interruptible) int READ_RANDOM_UIO(struct uio *uio, bool nonblock) { - uint8_t *random_buf; - int error; - ssize_t read_len, total_read, c; /* 16 MiB takes about 0.08 s CPU time on my 2017 AMD Zen CPU */ #define SIGCHK_PERIOD (16 * 1024 * 1024) const size_t sigchk_period = SIGCHK_PERIOD; - CTASSERT(SIGCHK_PERIOD % PAGE_SIZE == 0); #undef SIGCHK_PERIOD - random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK); + uint8_t *random_buf; + size_t total_read, read_len; + ssize_t bufsize; + int error; + + + KASSERT(uio->uio_rw == UIO_READ, ("%s: bogus write", __func__)); + KASSERT(uio->uio_resid >= 0, ("%s: bogus negative resid", __func__)); + p_random_alg_context->ra_pre_read(); error = 0; /* (Un)Blocking logic */ @@ -193,44 +197,64 @@ READ_RANDOM_UIO(struct uio *uio, bool nonblock) error = randomdev_wait_until_seeded( SEEDWAIT_INTERRUPTIBLE); } - if (error == 0) { - read_rate_increment((uio->uio_resid + sizeof(uint32_t))/sizeof(uint32_t)); - total_read = 0; - while (uio->uio_resid && !error) { - read_len = uio->uio_resid; - /* - * Belt-and-braces. - * Round up the read length to a crypto block size multiple, - * which is what the underlying generator is expecting. - * See the random_buf size requirements in the Fortuna code. - */ - read_len = roundup(read_len, RANDOM_BLOCKSIZE); - /* Work in chunks page-sized or less */ - read_len = MIN(read_len, PAGE_SIZE); - p_random_alg_context->ra_read(random_buf, read_len); - c = MIN(uio->uio_resid, read_len); - /* - * uiomove() may yield the CPU before each 'c' bytes - * (up to PAGE_SIZE) are copied out. - */ - error = uiomove(random_buf, c, uio); - total_read += c; - /* - * Poll for signals every few MBs to avoid very long - * uninterruptible syscalls. - */ - if (error == 0 && uio->uio_resid != 0 && - total_read % sigchk_period == 0) { - error = tsleep_sbt(&random_alg_context, PCATCH, - "randrd", SBT_1NS, 0, C_HARDCLOCK); - /* Squash tsleep timeout condition */ - if (error == EWOULDBLOCK) - error = 0; - } - } - if (error == ERESTART || error == EINTR) - error = 0; + if (error != 0) + return (error); + + read_rate_increment(howmany(uio->uio_resid + 1, sizeof(uint32_t))); + total_read = 0; + + /* Easy to deal with the trivial 0 byte case. */ + if (__predict_false(uio->uio_resid == 0)) + return (0); + + /* + * If memory is plentiful, use maximally sized requests to avoid + * per-call algorithm overhead. But fall back to a single page + * allocation if the full request isn't immediately available. + */ + bufsize = MIN(sigchk_period, (size_t)uio->uio_resid); + random_buf = malloc(bufsize, M_ENTROPY, M_NOWAIT); + if (random_buf == NULL) { + bufsize = PAGE_SIZE; + random_buf = malloc(bufsize, M_ENTROPY, M_WAITOK); } + + error = 0; + while (uio->uio_resid > 0 && error == 0) { + read_len = MIN((size_t)uio->uio_resid, bufsize); + + p_random_alg_context->ra_read(random_buf, read_len); + + /* + * uiomove() may yield the CPU before each 'read_len' bytes (up + * to bufsize) are copied out. + */ + error = uiomove(random_buf, read_len, uio); + total_read += read_len; + + /* + * Poll for signals every few MBs to avoid very long + * uninterruptible syscalls. + */ + if (error == 0 && uio->uio_resid != 0 && + total_read % sigchk_period == 0) { + error = tsleep_sbt(&random_alg_context, PCATCH, + "randrd", SBT_1NS, 0, C_HARDCLOCK); + /* Squash tsleep timeout condition */ + if (error == EWOULDBLOCK) + error = 0; + } + } + + /* + * Short reads due to signal interrupt should not indicate error. + * Instead, the uio will reflect that the read was shorter than + * requested. + */ + if (error == ERESTART || error == EINTR) + error = 0; + + explicit_bzero(random_buf, bufsize); free(random_buf, M_ENTROPY); return (error); } @@ -249,7 +273,6 @@ READ_RANDOM_UIO(struct uio *uio, bool nonblock) void READ_RANDOM(void *random_buf, u_int len) { - u_int read_directly_len; KASSERT(random_buf != NULL, ("No suitable random buffer in %s", __func__)); p_random_alg_context->ra_pre_read(); @@ -278,23 +301,7 @@ READ_RANDOM(void *random_buf, u_int len) (void)randomdev_wait_until_seeded(SEEDWAIT_UNINTERRUPTIBLE); } read_rate_increment(roundup2(len, sizeof(uint32_t))); - /* - * The underlying generator expects multiples of - * RANDOM_BLOCKSIZE. - */ - read_directly_len = rounddown(len, RANDOM_BLOCKSIZE); - if (read_directly_len > 0) - p_random_alg_context->ra_read(random_buf, read_directly_len); - if (read_directly_len < len) { - uint8_t remainder_buf[RANDOM_BLOCKSIZE]; - - p_random_alg_context->ra_read(remainder_buf, - sizeof(remainder_buf)); - memcpy((char *)random_buf + read_directly_len, remainder_buf, - len - read_directly_len); - - explicit_bzero(remainder_buf, sizeof(remainder_buf)); - } + p_random_alg_context->ra_read(random_buf, len); } bool diff --git a/sys/dev/random/randomdev.h b/sys/dev/random/randomdev.h index 91c93aee0805..3f9b0f3acc74 100644 --- a/sys/dev/random/randomdev.h +++ b/sys/dev/random/randomdev.h @@ -68,7 +68,7 @@ struct harvest_event; typedef void random_alg_init_t(void *); typedef void random_alg_deinit_t(void *); typedef void random_alg_pre_read_t(void); -typedef void random_alg_read_t(uint8_t *, u_int); +typedef void random_alg_read_t(uint8_t *, size_t); typedef bool random_alg_seeded_t(void); typedef void random_alg_reseed_t(void); typedef void random_alg_eventprocessor_t(struct harvest_event *); diff --git a/sys/dev/random/uint128.h b/sys/dev/random/uint128.h index 63de28a3864a..71056a63a93b 100644 --- a/sys/dev/random/uint128.h +++ b/sys/dev/random/uint128.h @@ -65,6 +65,21 @@ uint128_increment(uint128_t *big_uintp) #endif } +static __inline void +uint128_add64(uint128_t *big_uintp, uint64_t add) +{ +#ifdef USE_REAL_UINT128_T + (*big_uintp) += add; +#else + uint64_t word0p; + + word0p = big_uintp->u128t_word0 + add; + if (word0p < big_uintp->u128t_word0) + big_uintp->u128t_word1++; + big_uintp->u128t_word0 = word0p; +#endif +} + static __inline bool uint128_equals(uint128_t a, uint128_t b) { diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c index e8154e390fd4..c816ed3ee781 100644 --- a/sys/dev/sdhci/sdhci.c +++ b/sys/dev/sdhci/sdhci.c @@ -185,15 +185,20 @@ sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) static int slot_printf(const struct sdhci_slot *slot, const char * fmt, ...) { + char buf[128]; va_list ap; int retval; - retval = printf("%s-slot%d: ", - device_get_nameunit(slot->bus), slot->num); - + /* + * Make sure we print a single line all together rather than in two + * halves to avoid console gibberish bingo. + */ va_start(ap, fmt); - retval += vprintf(fmt, ap); + retval = vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); + + retval += printf("%s-slot%d: %s", + device_get_nameunit(slot->bus), slot->num, buf); return (retval); } @@ -2513,8 +2518,8 @@ sdhci_start_slot(struct sdhci_slot *slot) goto fail; mtx_init(&slot->sim_mtx, "sdhcisim", NULL, MTX_DEF); - slot->sim = cam_sim_alloc(sdhci_cam_action, sdhci_cam_poll, - "sdhci_slot", slot, device_get_unit(slot->bus), + slot->sim = cam_sim_alloc_dev(sdhci_cam_action, sdhci_cam_poll, + "sdhci_slot", slot, slot->bus, &slot->sim_mtx, 1, 1, slot->devq); if (slot->sim == NULL) { diff --git a/sys/dev/sdhci/sdhci_xenon.c b/sys/dev/sdhci/sdhci_xenon.c index 4f11be2cf3a5..5afbe7afefd3 100644 --- a/sys/dev/sdhci/sdhci_xenon.c +++ b/sys/dev/sdhci/sdhci_xenon.c @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -56,6 +57,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include "mmcbr_if.h" @@ -84,10 +86,12 @@ struct sdhci_xenon_softc { uint32_t max_clk; /* Max possible freq */ struct resource *irq_res; /* IRQ resource */ void *intrhand; /* Interrupt handle */ + struct sdhci_fdt_gpio *gpio; /* GPIO pins for CD detection. */ struct sdhci_slot *slot; /* SDHCI internal data */ struct resource *mem_res; /* Memory resource */ + regulator_t reg_vqmmc; /* vqmmc-supply regulator */ uint8_t znr; /* PHY ZNR */ uint8_t zpr; /* PHY ZPR */ bool no_18v; /* No 1.8V support */ @@ -188,6 +192,14 @@ sdhci_xenon_get_ro(device_t bus, device_t dev) return (sdhci_generic_get_ro(bus, dev) ^ sc->wp_inverted); } +static bool +sdhci_xenon_get_card_present(device_t dev, struct sdhci_slot *slot) +{ + struct sdhci_xenon_softc *sc = device_get_softc(dev); + + return (sdhci_fdt_gpio_get_present(sc->gpio)); +} + static int sdhci_xenon_phy_init(device_t brdev, struct mmc_ios *ios) { @@ -337,6 +349,25 @@ sdhci_xenon_update_ios(device_t brdev, device_t reqdev) slot = device_get_ivars(reqdev); ios = &slot->host.ios; + switch (ios->power_mode) { + case power_on: + break; + case power_off: + if (bootverbose) + device_printf(sc->dev, "Powering down sd/mmc\n"); + + if (sc->reg_vqmmc) + regulator_disable(sc->reg_vqmmc); + break; + case power_up: + if (bootverbose) + device_printf(sc->dev, "Powering up sd/mmc\n"); + + if (sc->reg_vqmmc) + regulator_enable(sc->reg_vqmmc); + break; + }; + /* Update the PHY settings. */ if (ios->clock != 0) sdhci_xenon_phy_set(brdev, ios); @@ -351,6 +382,42 @@ sdhci_xenon_update_ios(device_t brdev, device_t reqdev) return (0); } +static int +sdhci_xenon_switch_vccq(device_t brdev, device_t reqdev) +{ + struct sdhci_xenon_softc *sc; + struct sdhci_slot *slot; + int uvolt, err; + + sc = device_get_softc(brdev); + + if (sc->reg_vqmmc == NULL) + return EOPNOTSUPP; + + slot = device_get_ivars(reqdev); + switch (slot->host.ios.vccq) { + case vccq_180: + uvolt = 1800000; + break; + case vccq_330: + uvolt = 3300000; + break; + default: + return EINVAL; + } + + err = regulator_set_voltage(sc->reg_vqmmc, uvolt, uvolt); + if (err != 0) { + device_printf(sc->dev, + "Cannot set vqmmc to %d<->%d\n", + uvolt, + uvolt); + return (err); + } + + return (0); +} + static int sdhci_xenon_probe(device_t dev) { @@ -389,6 +456,11 @@ sdhci_xenon_probe(device_t dev) if ((OF_getencprop(sc->node, "marvell,xenon-phy-zpr", &cid, sizeof(cid))) > 0) sc->zpr = cid & XENON_ZPR_MASK; + if (regulator_get_by_ofw_property(dev, 0, "vqmmc-supply", + &sc->reg_vqmmc) == 0 && bootverbose) { + if (bootverbose) + device_printf(dev, "vqmmc-supply regulator found\n"); + } return (0); } @@ -437,6 +509,12 @@ sdhci_xenon_attach(device_t dev) slot->max_clk = sc->max_clk; sc->slot = slot; + /* + * Set up any gpio pin handling described in the FDT data. This cannot + * fail; see comments in sdhci_fdt_gpio.h for details. + */ + sc->gpio = sdhci_fdt_gpio_setup(dev, slot); + if (sdhci_init_slot(dev, sc->slot, 0)) goto fail; @@ -497,6 +575,9 @@ sdhci_xenon_detach(device_t dev) { struct sdhci_xenon_softc *sc = device_get_softc(dev); + if (sc->gpio != NULL) + sdhci_fdt_gpio_teardown(sc->gpio); + bus_generic_detach(dev); bus_teardown_intr(dev, sc->irq_res, sc->intrhand); bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res), @@ -526,6 +607,7 @@ static device_method_t sdhci_xenon_methods[] = { DEVMETHOD(mmcbr_get_ro, sdhci_xenon_get_ro), DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host), DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host), + DEVMETHOD(mmcbr_switch_vccq, sdhci_xenon_switch_vccq), /* SDHCI registers accessors */ DEVMETHOD(sdhci_read_1, sdhci_xenon_read_1), @@ -536,6 +618,7 @@ static device_method_t sdhci_xenon_methods[] = { DEVMETHOD(sdhci_write_2, sdhci_xenon_write_2), DEVMETHOD(sdhci_write_4, sdhci_xenon_write_4), DEVMETHOD(sdhci_write_multi_4, sdhci_xenon_write_multi_4), + DEVMETHOD(sdhci_get_card_present, sdhci_xenon_get_card_present), DEVMETHOD_END }; diff --git a/sys/dev/sdio/sdio_if.m b/sys/dev/sdio/sdio_if.m new file mode 100644 index 000000000000..d6f15ba6cff6 --- /dev/null +++ b/sys/dev/sdio/sdio_if.m @@ -0,0 +1,79 @@ +#- +# Copyright (c) 2019 The FreeBSD Foundation +# +# Portions of this software were developed by Björn Zeeb +# 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 ``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$ +# + +#include +#include + +INTERFACE sdio; + +# +# READ DIRECT (1byte) +# +METHOD int read_direct { + device_t dev; + uint8_t fn; + uint32_t addr; + uint8_t *val; +}; + +# +# WRITE DIRECT (1byte) +# +METHOD int write_direct { + device_t dev; + uint8_t fn; + uint32_t addr; + uint8_t val; +}; + +# +# READ EXTENDED +# +METHOD int read_extended { + device_t dev; + uint8_t fn; + uint32_t addr; + uint32_t size; + uint8_t *buffer; + bool incaddr; +}; + +# +# WRITE EXTENDED +# +METHOD int write_extended { + device_t dev; + uint8_t fn; + uint32_t addr; + uint32_t size; + uint8_t *buffer; + bool incaddr; +}; + +# end diff --git a/sys/dev/sdio/sdio_subr.c b/sys/dev/sdio/sdio_subr.c new file mode 100644 index 000000000000..e2a6573abc6f --- /dev/null +++ b/sys/dev/sdio/sdio_subr.c @@ -0,0 +1,227 @@ +/*- + * Copyright (c) 2017 Ilya Bakulin. All rights reserved. + * Copyright (c) 2018-2019 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * 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 ``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. + * + * + * Portions of this software may have been developed with reference to + * the SD Simplified Specification. The following disclaimer may apply: + * + * The following conditions apply to the release of the simplified + * specification ("Simplified Specification") by the SD Card Association and + * the SD Group. The Simplified Specification is a subset of the complete SD + * Specification which is owned by the SD Card Association and the SD + * Group. This Simplified Specification is provided on a non-confidential + * basis subject to the disclaimers below. Any implementation of the + * Simplified Specification may require a license from the SD Card + * Association, SD Group, SD-3C LLC or other third parties. + * + * Disclaimers: + * + * The information contained in the Simplified Specification is presented only + * as a standard specification for SD Cards and SD Host/Ancillary products and + * is provided "AS-IS" without any representations or warranties of any + * kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD + * Card Association for any damages, any infringements of patents or other + * right of the SD Group, SD-3C LLC, the SD Card Association or any third + * parties, which may result from its use. No license is granted by + * implication, estoppel or otherwise under any patent or other rights of the + * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing + * herein shall be construed as an obligation by the SD Group, the SD-3C LLC + * or the SD Card Association to disclose or distribute any technical + * information, know-how or other confidential information to any third party. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "sdio_if.h" + +/* Works on F0. */ +static int +sdio_set_bool_for_func(device_t dev, uint32_t addr, uint8_t fn, bool enable) +{ + device_t pdev; + int error; + uint8_t val; + bool enabled; + + pdev = device_get_parent(dev); + error = SDIO_READ_DIRECT(pdev, 0, addr, &val); + if (error != 0) + return (error); + + enabled = (val & (1 << fn)) ? true : false; + if (enabled == enable) + return (0); + + if (enable) + val |= (1 << fn); + else + val &= ~(1 << fn); + error = SDIO_WRITE_DIRECT(pdev, 0, addr, val); + return (error); +} + +int +sdio_enable_func(struct sdio_func *f) +{ + + return (sdio_set_bool_for_func(f->dev, SD_IO_CCCR_FN_ENABLE, + f->fn, true)); +} + +int +sdio_disable_func(struct sdio_func *f) +{ + + return (sdio_set_bool_for_func(f->dev, SD_IO_CCCR_FN_ENABLE, + f->fn, false)); +} + +int +sdio_set_block_size(struct sdio_func *f, uint16_t bs) +{ + device_t pdev; + int error; + uint32_t addr; + uint16_t v; + + if (!sdio_get_support_multiblk(f->dev)) + return (EOPNOTSUPP); + + pdev = device_get_parent(f->dev); + addr = SD_IO_FBR_START * f->fn + SD_IO_FBR_IOBLKSZ; + v = htole16(bs); + /* Always write through F0. */ + error = SDIO_WRITE_DIRECT(pdev, 0, addr, v & 0xff); + if (error == 0) + error = SDIO_WRITE_DIRECT(pdev, 0, addr + 1, + (v >> 8) & 0xff); + if (error == 0) + f->cur_blksize = bs; + + return (error); +} + +uint8_t +sdio_readb(struct sdio_func *f, uint32_t addr, int *err) +{ + int error; + uint8_t v; + + error = SDIO_READ_DIRECT(device_get_parent(f->dev), f->fn, addr, &v); + if (error) { + if (err != NULL) + *err = error; + return (0xff); + } else { + if (err != NULL) + *err = 0; + return (v); + } +} + +void +sdio_writeb(struct sdio_func *f, uint8_t val, uint32_t addr, int *err) +{ + int error; + + error = SDIO_WRITE_DIRECT(device_get_parent(f->dev), f->fn, addr, val); + if (err != NULL) + *err = error; +} + +uint32_t +sdio_readl(struct sdio_func *f, uint32_t addr, int *err) +{ + int error; + uint32_t v; + + error = SDIO_READ_EXTENDED(device_get_parent(f->dev), f->fn, addr, + sizeof(v), (uint8_t *)&v, false); + if (error) { + if (err != NULL) + *err = error; + return (0xffffffff); + } else { + if (err != NULL) + *err = 0; + return (le32toh(v)); + } +} + +void +sdio_writel(struct sdio_func *f, uint32_t val, uint32_t addr, int *err) +{ + int error; + + error = SDIO_WRITE_EXTENDED(device_get_parent(f->dev), f->fn, addr, + sizeof(val), (uint8_t *)&val, false); + if (err != NULL) + *err = error; +} + +uint8_t +sdio_f0_readb(struct sdio_func *f, uint32_t addr, int *err) +{ + int error; + uint8_t v; + + error = SDIO_READ_DIRECT(device_get_parent(f->dev), 0, addr, &v); + if (error) { + if (err != NULL) + *err = error; + return (0xff); + } else { + if (err != NULL) + *err = 0; + return (v); + } +} + +void +sdio_f0_writeb(struct sdio_func *f, uint8_t val, uint32_t addr, int *err) +{ + int error; + + error = SDIO_WRITE_DIRECT(device_get_parent(f->dev), 0, addr, val); + if (err != NULL) + *err = error; +} + +/* end */ diff --git a/sys/dev/sdio/sdio_subr.h b/sys/dev/sdio/sdio_subr.h new file mode 100644 index 000000000000..f16826298e13 --- /dev/null +++ b/sys/dev/sdio/sdio_subr.h @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 2017 Ilya Bakulin. All rights reserved. + * Copyright (c) 2018-2019 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * 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 ``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. + * + * + * Portions of this software may have been developed with reference to + * the SD Simplified Specification. The following disclaimer may apply: + * + * The following conditions apply to the release of the simplified + * specification ("Simplified Specification") by the SD Card Association and + * the SD Group. The Simplified Specification is a subset of the complete SD + * Specification which is owned by the SD Card Association and the SD + * Group. This Simplified Specification is provided on a non-confidential + * basis subject to the disclaimers below. Any implementation of the + * Simplified Specification may require a license from the SD Card + * Association, SD Group, SD-3C LLC or other third parties. + * + * Disclaimers: + * + * The information contained in the Simplified Specification is presented only + * as a standard specification for SD Cards and SD Host/Ancillary products and + * is provided "AS-IS" without any representations or warranties of any + * kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD + * Card Association for any damages, any infringements of patents or other + * right of the SD Group, SD-3C LLC, the SD Card Association or any third + * parties, which may result from its use. No license is granted by + * implication, estoppel or otherwise under any patent or other rights of the + * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing + * herein shall be construed as an obligation by the SD Group, the SD-3C LLC + * or the SD Card Association to disclose or distribute any technical + * information, know-how or other confidential information to any third party. + * + * + * $FreeBSD$ + */ + +#ifndef _SDIO_SUBR_H_ +#define _SDIO_SUBR_H_ + +/* + * This file contains structures and functions to work with SDIO cards. + */ + +struct sdio_func { + device_t dev; /* The device to talk to CAM. */ + uintptr_t drvdata; /* Driver specific data. */ + + uint8_t fn; /* Function number. */ + + uint8_t class; /* Class of function. */ + uint16_t vendor; /* Manufacturer ID. */ + uint16_t device; /* Card ID. */ + + uint16_t max_blksize; /* Maximum block size of function. */ + uint16_t cur_blksize; /* Current block size of function. */ + + uint16_t retries; /* Retires for CAM operations. */ + uint32_t timeout; /* Timeout. */ +}; + +struct card_info { + struct sdio_func f[8]; + + /* Compared to R4 Number of I/O Functions we DO count F0 here. */ + uint8_t num_funcs; + + bool support_multiblk; /* Support Multiple Block Transfer */ +}; + +#ifdef _KERNEL +int sdio_enable_func(struct sdio_func *); +int sdio_disable_func(struct sdio_func *); +int sdio_set_block_size(struct sdio_func *, uint16_t); + +uint8_t sdio_readb(struct sdio_func *, uint32_t, int *); +void sdio_writeb(struct sdio_func *, uint8_t, uint32_t, int *); +uint32_t sdio_readl(struct sdio_func *, uint32_t, int *); +void sdio_writel(struct sdio_func *, uint32_t, uint32_t, int *); + +uint8_t sdio_f0_readb(struct sdio_func *, uint32_t, int *); +void sdio_f0_writeb(struct sdio_func *, uint8_t, uint32_t, int *); +#endif /* _KERNEL */ + +#endif /* _SDIO_SUBR_H_ */ diff --git a/sys/dev/sdio/sdiob.c b/sys/dev/sdio/sdiob.c new file mode 100644 index 000000000000..4a7b3081aafb --- /dev/null +++ b/sys/dev/sdio/sdiob.c @@ -0,0 +1,1188 @@ +/*- + * Copyright (c) 2017 Ilya Bakulin. All rights reserved. + * Copyright (c) 2018-2019 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * 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 ``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. + * + * + * Portions of this software may have been developed with reference to + * the SD Simplified Specification. The following disclaimer may apply: + * + * The following conditions apply to the release of the simplified + * specification ("Simplified Specification") by the SD Card Association and + * the SD Group. The Simplified Specification is a subset of the complete SD + * Specification which is owned by the SD Card Association and the SD + * Group. This Simplified Specification is provided on a non-confidential + * basis subject to the disclaimers below. Any implementation of the + * Simplified Specification may require a license from the SD Card + * Association, SD Group, SD-3C LLC or other third parties. + * + * Disclaimers: + * + * The information contained in the Simplified Specification is presented only + * as a standard specification for SD Cards and SD Host/Ancillary products and + * is provided "AS-IS" without any representations or warranties of any + * kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD + * Card Association for any damages, any infringements of patents or other + * right of the SD Group, SD-3C LLC, the SD Card Association or any third + * parties, which may result from its use. No license is granted by + * implication, estoppel or otherwise under any patent or other rights of the + * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing + * herein shall be construed as an obligation by the SD Group, the SD-3C LLC + * or the SD Card Association to disclose or distribute any technical + * information, know-how or other confidential information to any third party. + */ +/* + * Implements the (kernel specific) SDIO parts. + * This will hide all cam(4) functionality from the SDIO driver implementations + * which will just be newbus/device(9) and hence look like any other driver for, + * e.g., PCI. + * The sdiob(4) parts effetively "translate" between the two worlds "bridging" + * messages from MMCCAM to newbus and back. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_cam.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include /* for cam_path */ +#include + +#include + +#include +#include + +#include "sdio_if.h" + +#ifdef DEBUG +#define DPRINTF(...) printf(__VA_ARGS__) +#define DPRINTFDEV(_dev, ...) device_printf((_dev), __VA_ARGS__) +#else +#define DPRINTF(...) +#define DPRINTFDEV(_dev, ...) +#endif + +struct sdiob_softc { + uint32_t sdio_state; +#define SDIO_STATE_DEAD 0x0001 +#define SDIO_STATE_INITIALIZING 0x0002 +#define SDIO_STATE_READY 0x0004 + uint32_t nb_state; +#define NB_STATE_DEAD 0x0001 +#define NB_STATE_SIM_ADDED 0x0002 +#define NB_STATE_READY 0x0004 + + /* CAM side (including sim_dev). */ + struct card_info cardinfo; + struct cam_periph *periph; + union ccb *ccb; + struct task discover_task; + + /* Newbus side. */ + device_t dev; /* Ourselves. */ + device_t child[8]; +}; + +/* -------------------------------------------------------------------------- */ +/* + * SDIO CMD52 and CM53 implementations along with wrapper functions for + * read/write and a CAM periph helper function. + * These are the backend implementations of the sdio_if.m framework talking + * through CAM to sdhci. + * Note: these functions are also called during early discovery stage when + * we are not a device(9) yet. Hence they cannot always use device_printf() + * to log errors and have to call CAM_DEBUG() during these early stages. + */ + +static int +sdioerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) +{ + + return (cam_periph_error(ccb, cam_flags, sense_flags)); +} + +/* CMD52: direct byte access. */ +static int +sdiob_rw_direct_sc(struct sdiob_softc *sc, uint8_t fn, uint32_t addr, bool wr, + uint8_t *val) +{ + uint32_t arg, flags; + int error; + + KASSERT((val != NULL), ("%s val passed as NULL\n", __func__)); + + if (sc->ccb == NULL) + sc->ccb = xpt_alloc_ccb(); + else + memset(sc->ccb, 0, sizeof(*sc->ccb)); + xpt_setup_ccb(&sc->ccb->ccb_h, sc->periph->path, CAM_PRIORITY_NONE); + CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_TRACE, + ("%s(fn=%d, addr=%#02x, wr=%d, *val=%#02x)\n", __func__, + fn, addr, wr, *val)); + + flags = MMC_RSP_R5 | MMC_CMD_AC; + arg = SD_IO_RW_FUNC(fn) | SD_IO_RW_ADR(addr); + if (wr) + arg |= SD_IO_RW_WR | SD_IO_RW_RAW | SD_IO_RW_DAT(*val); + + cam_fill_mmcio(&sc->ccb->mmcio, + /*retries*/ 0, + /*cbfcnp*/ NULL, + /*flags*/ CAM_DIR_NONE, + /*mmc_opcode*/ SD_IO_RW_DIRECT, + /*mmc_arg*/ arg, + /*mmc_flags*/ flags, + /*mmc_data*/ 0, + /*timeout*/ sc->cardinfo.f[fn].timeout); + error = cam_periph_runccb(sc->ccb, sdioerror, CAM_FLAG_NONE, 0, NULL); + if (error != 0) { + if (sc->dev != NULL) + device_printf(sc->dev, + "%s: Failed to %s address %#10x error=%d\n", + __func__, (wr) ? "write" : "read", addr, error); + else + CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_INFO, + ("%s: Failed to %s address: %#10x error=%d\n", + __func__, (wr) ? "write" : "read", addr, error)); + return (error); + } + + /* TODO: Add handling of MMC errors */ + /* ccb->mmcio.cmd.error ? */ + if (wr == false) + *val = sc->ccb->mmcio.cmd.resp[0] & 0xff; + + return (0); +} + +static int +sdio_rw_direct(device_t dev, uint8_t fn, uint32_t addr, bool wr, + uint8_t *val) +{ + struct sdiob_softc *sc; + int error; + + sc = device_get_softc(dev); + cam_periph_lock(sc->periph); + error = sdiob_rw_direct_sc(sc, fn, addr, wr, val); + cam_periph_unlock(sc->periph); + return (error); +} + +static int +sdiob_read_direct(device_t dev, uint8_t fn, uint32_t addr, uint8_t *val) +{ + int error; + uint8_t v; + + error = sdio_rw_direct(dev, fn, addr, false, &v); + /* Be polite and do not touch the value on read error. */ + if (error == 0 && val != NULL) + *val = v; + return (error); +} + +static int +sdiob_write_direct(device_t dev, uint8_t fn, uint32_t addr, uint8_t val) +{ + + return (sdio_rw_direct(dev, fn, addr, true, &val)); +} + +/* + * CMD53: IO_RW_EXTENDED, read and write multiple I/O registers. + * Increment false gets FIFO mode (single register address). + */ +/* + * A b_count of 0 means byte mode, b_count > 0 gets block mode. + * A b_count of >= 512 would mean infinitive block transfer, which would become + * b_count = 0, is not yet supported. + * For b_count == 0, blksz is the len of bytes, otherwise it is the amount of + * full sized blocks (you must not round the blocks up and leave the last one + * partial!) + * For byte mode, the maximum of blksz is the functions cur_blksize. + * This function should ever only be called by sdio_rw_extended_sc()! + */ +static int +sdiob_rw_extended_cam(struct sdiob_softc *sc, uint8_t fn, uint32_t addr, + bool wr, uint8_t *buffer, bool incaddr, uint32_t b_count, uint16_t blksz) +{ + struct mmc_data mmcd; + uint32_t arg, cam_flags, flags, len; + int error; + + if (sc->ccb == NULL) + sc->ccb = xpt_alloc_ccb(); + else + memset(sc->ccb, 0, sizeof(*sc->ccb)); + xpt_setup_ccb(&sc->ccb->ccb_h, sc->periph->path, CAM_PRIORITY_NONE); + CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_TRACE, + ("%s(fn=%d addr=%#0x wr=%d b_count=%u blksz=%u buf=%p incr=%d)\n", + __func__, fn, addr, wr, b_count, blksz, buffer, incaddr)); + + KASSERT((b_count <= 511), ("%s: infinitive block transfer not yet " + "supported: b_count %u blksz %u, sc %p, fn %u, addr %#10x, %s, " + "buffer %p, %s\n", __func__, b_count, blksz, sc, fn, addr, + wr ? "wr" : "rd", buffer, incaddr ? "incaddr" : "fifo")); + /* Blksz needs to be within bounds for both byte and block mode! */ + KASSERT((blksz <= sc->cardinfo.f[fn].cur_blksize), ("%s: blksz " + "%u > bur_blksize %u, sc %p, fn %u, addr %#10x, %s, " + "buffer %p, %s, b_count %u\n", __func__, blksz, + sc->cardinfo.f[fn].cur_blksize, sc, fn, addr, + wr ? "wr" : "rd", buffer, incaddr ? "incaddr" : "fifo", + b_count)); + if (b_count == 0) { + /* Byte mode */ + len = blksz; + if (blksz == 512) + blksz = 0; + arg = SD_IOE_RW_LEN(blksz); + } else { + /* Block mode. */ +#ifdef __notyet__ + if (b_count > 511) { + /* Infinitive block transfer. */ + b_count = 0; + } +#endif + len = b_count * blksz; + arg = SD_IOE_RW_BLK | SD_IOE_RW_LEN(b_count); + } + + flags = MMC_RSP_R5 | MMC_CMD_ADTC; + arg |= SD_IOE_RW_FUNC(fn) | SD_IOE_RW_ADR(addr); + if (incaddr) + arg |= SD_IOE_RW_INCR; + + memset(&mmcd, 0, sizeof(mmcd)); + mmcd.data = buffer; + mmcd.len = len; + if (arg & SD_IOE_RW_BLK) { + /* XXX both should be known from elsewhere, aren't they? */ + mmcd.block_size = blksz; + mmcd.block_count = b_count; + } + + if (wr) { + arg |= SD_IOE_RW_WR; + cam_flags = CAM_DIR_OUT; + mmcd.flags = MMC_DATA_WRITE; + } else { + cam_flags = CAM_DIR_IN; + mmcd.flags = MMC_DATA_READ; + } +#ifdef __notyet__ + if (b_count == 0) { + /* XXX-BZ TODO FIXME. Cancel I/O: CCCR -> ASx */ + /* Stop cmd. */ + } +#endif + cam_fill_mmcio(&sc->ccb->mmcio, + /*retries*/ 0, + /*cbfcnp*/ NULL, + /*flags*/ cam_flags, + /*mmc_opcode*/ SD_IO_RW_EXTENDED, + /*mmc_arg*/ arg, + /*mmc_flags*/ flags, + /*mmc_data*/ &mmcd, + /*timeout*/ sc->cardinfo.f[fn].timeout); + if (arg & SD_IOE_RW_BLK) { + mmcd.flags |= MMC_DATA_BLOCK_SIZE; + if (b_count != 1) + sc->ccb->mmcio.cmd.data->flags |= MMC_DATA_MULTI; + } + + /* Execute. */ + error = cam_periph_runccb(sc->ccb, sdioerror, CAM_FLAG_NONE, 0, NULL); + if (error != 0) { + if (sc->dev != NULL) + device_printf(sc->dev, + "%s: Failed to %s address %#10x buffer %p size %u " + "%s b_count %u blksz %u error=%d\n", + __func__, (wr) ? "write to" : "read from", addr, + buffer, len, (incaddr) ? "incr" : "fifo", + b_count, blksz, error); + else + CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_INFO, + ("%s: Failed to %s address %#10x buffer %p size %u " + "%s b_count %u blksz %u error=%d\n", + __func__, (wr) ? "write to" : "read from", addr, + buffer, len, (incaddr) ? "incr" : "fifo", + b_count, blksz, error)); + return (error); + } + + /* TODO: Add handling of MMC errors */ + /* ccb->mmcio.cmd.error ? */ + error = sc->ccb->mmcio.cmd.resp[0] & 0xff; + if (error != 0) { + if (sc->dev != NULL) + device_printf(sc->dev, + "%s: Failed to %s address %#10x buffer %p size %u " + "%s b_count %u blksz %u mmcio resp error=%d\n", + __func__, (wr) ? "write to" : "read from", addr, + buffer, len, (incaddr) ? "incr" : "fifo", + b_count, blksz, error); + else + CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_INFO, + ("%s: Failed to %s address %#10x buffer %p size %u " + "%s b_count %u blksz %u mmcio resp error=%d\n", + __func__, (wr) ? "write to" : "read from", addr, + buffer, len, (incaddr) ? "incr" : "fifo", + b_count, blksz, error)); + } + return (error); +} + +static int +sdiob_rw_extended_sc(struct sdiob_softc *sc, uint8_t fn, uint32_t addr, + bool wr, uint32_t size, uint8_t *buffer, bool incaddr) +{ + int error; + uint32_t len; + uint32_t b_count; + + /* + * If block mode is supported and we have at least 4 bytes to write and + * the size is at least one block, then start doing blk transfers. + */ + while (sc->cardinfo.support_multiblk && + size > 4 && size >= sc->cardinfo.f[fn].cur_blksize) { + + b_count = size / sc->cardinfo.f[fn].cur_blksize; + KASSERT(b_count >= 1, ("%s: block count too small %u size %u " + "cur_blksize %u\n", __func__, b_count, size, + sc->cardinfo.f[fn].cur_blksize)); + +#ifdef __notyet__ + /* XXX support inifinite transfer with b_count = 0. */ +#else + if (b_count > 511) + b_count = 511; +#endif + len = b_count * sc->cardinfo.f[fn].cur_blksize; + error = sdiob_rw_extended_cam(sc, fn, addr, wr, buffer, incaddr, + b_count, sc->cardinfo.f[fn].cur_blksize); + if (error != 0) + return (error); + + size -= len; + buffer += len; + if (incaddr) + addr += len; + } + + while (size > 0) { + len = MIN(size, sc->cardinfo.f[fn].cur_blksize); + + error = sdiob_rw_extended_cam(sc, fn, addr, wr, buffer, incaddr, + 0, len); + if (error != 0) + return (error); + + /* Prepare for next iteration. */ + size -= len; + buffer += len; + if (incaddr) + addr += len; + } + + return (0); +} + +static int +sdiob_rw_extended(device_t dev, uint8_t fn, uint32_t addr, bool wr, + uint32_t size, uint8_t *buffer, bool incaddr) +{ + struct sdiob_softc *sc; + int error; + + sc = device_get_softc(dev); + cam_periph_lock(sc->periph); + error = sdiob_rw_extended_sc(sc, fn, addr, wr, size, buffer, incaddr); + cam_periph_unlock(sc->periph); + return (error); +} + +static int +sdiob_read_extended(device_t dev, uint8_t fn, uint32_t addr, uint32_t size, + uint8_t *buffer, bool incaddr) +{ + + return (sdiob_rw_extended(dev, fn, addr, false, size, buffer, incaddr)); +} + +static int +sdiob_write_extended(device_t dev, uint8_t fn, uint32_t addr, uint32_t size, + uint8_t *buffer, bool incaddr) +{ + + return (sdiob_rw_extended(dev, fn, addr, true, size, buffer, incaddr)); +} + +/* -------------------------------------------------------------------------- */ +/* Bus interface, ivars handling. */ + +static int +sdiob_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct sdiob_softc *sc; + struct sdio_func *f; + + f = device_get_ivars(child); + KASSERT(f != NULL, ("%s: dev %p child %p which %d, child ivars NULL\n", + __func__, dev, child, which)); + + switch (which) { + case SDIOB_IVAR_SUPPORT_MULTIBLK: + sc = device_get_softc(dev); + KASSERT(sc != NULL, ("%s: dev %p child %p which %d, sc NULL\n", + __func__, dev, child, which)); + *result = sc->cardinfo.support_multiblk; + break; + case SDIOB_IVAR_FUNCTION: + *result = (uintptr_t)f; + break; + case SDIOB_IVAR_FUNCNUM: + *result = f->fn; + break; + case SDIOB_IVAR_CLASS: + *result = f->class; + break; + case SDIOB_IVAR_VENDOR: + *result = f->vendor; + break; + case SDIOB_IVAR_DEVICE: + *result = f->device; + break; + case SDIOB_IVAR_DRVDATA: + *result = f->drvdata; + break; + default: + return (ENOENT); + } + return (0); +} + +static int +sdiob_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +{ + struct sdio_func *f; + + f = device_get_ivars(child); + KASSERT(f != NULL, ("%s: dev %p child %p which %d, child ivars NULL\n", + __func__, dev, child, which)); + + switch (which) { + case SDIOB_IVAR_SUPPORT_MULTIBLK: + case SDIOB_IVAR_FUNCTION: + case SDIOB_IVAR_FUNCNUM: + case SDIOB_IVAR_CLASS: + case SDIOB_IVAR_VENDOR: + case SDIOB_IVAR_DEVICE: + return (EINVAL); /* Disallowed. */ + case SDIOB_IVAR_DRVDATA: + f->drvdata = value; + break; + default: + return (ENOENT); + } + + return (0); +} + + +/* -------------------------------------------------------------------------- */ +/* + * Newbus functions for ourselves to probe/attach/detach and become a proper + * device(9). Attach will also probe for child devices (another driver + * implementing SDIO). + */ + +static int +sdiob_probe(device_t dev) +{ + + device_set_desc(dev, "SDIO CAM-Newbus bridge"); + return (BUS_PROBE_DEFAULT); +} + +static int +sdiob_attach(device_t dev) +{ + struct sdiob_softc *sc; + int error, i; + + sc = device_get_softc(dev); + if (sc == NULL) + return (ENXIO); + + /* + * Now that we are a dev, create one child device per function, + * initialize the backpointer, so we can pass them around and + * call CAM operations on the parent, and also set the function + * itself as ivars, so that we can query/update them. + * Do this before any child gets a chance to attach. + */ + for (i = 0; i < sc->cardinfo.num_funcs; i++) { + + sc->child[i] = device_add_child(dev, NULL, -1); + if (sc->child[i] == NULL) { + device_printf(dev, "%s: failed to add child\n", __func__); + return (ENXIO); + } + sc->cardinfo.f[i].dev = sc->child[i]; + + /* Set the function as ivar to the child device. */ + device_set_ivars(sc->child[i], &sc->cardinfo.f[i]); + } + + /* + * No one will ever attach to F0; we do the above to have a "device" + * to talk to in a general way in the code. + * Also do the probe/attach in a 2nd loop, so that all devices are + * present as we do have drivers consuming more than one device/func + * and might play "tricks" in order to do that assuming devices and + * ivars are available for all. + */ + for (i = 1; i < sc->cardinfo.num_funcs; i++) { + error = device_probe_and_attach(sc->child[i]); + if (error != 0 && bootverbose) + device_printf(dev, "%s: device_probe_and_attach(%p %s) " + "failed %d for function %d, no child yet\n", + __func__, + sc->child, device_get_nameunit(sc->child[i]), + error, i); + } + + sc->nb_state = NB_STATE_READY; + + cam_periph_lock(sc->periph); + xpt_announce_periph(sc->periph, NULL); + cam_periph_unlock(sc->periph); + + return (0); +} + +static int +sdiob_detach(device_t dev) +{ + + /* XXX TODO? */ + return (EOPNOTSUPP); +} + + +/* -------------------------------------------------------------------------- */ +/* + * driver(9) and device(9) "control plane". + * This is what we use when we are making ourselves a device(9) in order to + * provide a newbus interface again, as well as the implementation of the + * SDIO interface. + */ + +static device_method_t sdiob_methods[] = { + + /* Device interface. */ + DEVMETHOD(device_probe, sdiob_probe), + DEVMETHOD(device_attach, sdiob_attach), + DEVMETHOD(device_detach, sdiob_detach), + + /* Bus interface. */ + DEVMETHOD(bus_add_child, bus_generic_add_child), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + DEVMETHOD(bus_read_ivar, sdiob_read_ivar), + DEVMETHOD(bus_write_ivar, sdiob_write_ivar), + + /* SDIO interface. */ + DEVMETHOD(sdio_read_direct, sdiob_read_direct), + DEVMETHOD(sdio_write_direct, sdiob_write_direct), + DEVMETHOD(sdio_read_extended, sdiob_read_extended), + DEVMETHOD(sdio_write_extended, sdiob_write_extended), + + DEVMETHOD_END +}; + +static devclass_t sdiob_devclass; +static driver_t sdiob_driver = { + SDIOB_NAME_S, + sdiob_methods, + 0 +}; + + +/* -------------------------------------------------------------------------- */ +/* + * CIS related. + * Read card and function information and populate the cardinfo structure. + */ + +static int +sdio_read_direct_sc(struct sdiob_softc *sc, uint8_t fn, uint32_t addr, + uint8_t *val) +{ + int error; + uint8_t v; + + error = sdiob_rw_direct_sc(sc, fn, addr, false, &v); + if (error == 0 && val != NULL) + *val = v; + return (error); +} + +static int +sdio_func_read_cis(struct sdiob_softc *sc, uint8_t fn, uint32_t cis_addr) +{ + char cis1_info_buf[256]; + char *cis1_info[4]; + int start, i, count, ret; + uint32_t addr; + uint8_t ch, tuple_id, tuple_len, tuple_count, v; + + /* If we encounter any read errors, abort and return. */ +#define ERR_OUT(ret) \ + if (ret != 0) \ + goto err; + ret = 0; + /* Use to prevent infinite loop in case of parse errors. */ + tuple_count = 0; + memset(cis1_info_buf, 0, 256); + do { + addr = cis_addr; + ret = sdio_read_direct_sc(sc, 0, addr++, &tuple_id); + ERR_OUT(ret); + if (tuple_id == SD_IO_CISTPL_END) + break; + if (tuple_id == 0) { + cis_addr++; + continue; + } + ret = sdio_read_direct_sc(sc, 0, addr++, &tuple_len); + ERR_OUT(ret); + if (tuple_len == 0) { + CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_PERIPH, + ("%s: parse error: 0-length tuple %#02x\n", + __func__, tuple_id)); + return (EIO); + } + + switch (tuple_id) { + case SD_IO_CISTPL_VERS_1: + addr += 2; + for (count = 0, start = 0, i = 0; + (count < 4) && ((i + 4) < 256); i++) { + ret = sdio_read_direct_sc(sc, 0, addr + i, &ch); + ERR_OUT(ret); + DPRINTF("%s: count=%d, start=%d, i=%d, got " + "(%#02x)\n", __func__, count, start, i, ch); + if (ch == 0xff) + break; + cis1_info_buf[i] = ch; + if (ch == 0) { + cis1_info[count] = + cis1_info_buf + start; + start = i + 1; + count++; + } + } + DPRINTF("Card info: "); + for (i=0; i < 4; i++) + if (cis1_info[i]) + DPRINTF(" %s", cis1_info[i]); + DPRINTF("\n"); + break; + case SD_IO_CISTPL_MANFID: + /* TPLMID_MANF */ + ret = sdio_read_direct_sc(sc, 0, addr++, &v); + ERR_OUT(ret); + sc->cardinfo.f[fn].vendor = v; + ret = sdio_read_direct_sc(sc, 0, addr++, &v); + ERR_OUT(ret); + sc->cardinfo.f[fn].vendor |= (v << 8); + /* TPLMID_CARD */ + ret = sdio_read_direct_sc(sc, 0, addr++, &v); + ERR_OUT(ret); + sc->cardinfo.f[fn].device = v; + ret = sdio_read_direct_sc(sc, 0, addr, &v); + ERR_OUT(ret); + sc->cardinfo.f[fn].device |= (v << 8); + break; + case SD_IO_CISTPL_FUNCID: + /* Not sure if we need to parse it? */ + break; + case SD_IO_CISTPL_FUNCE: + if (tuple_len < 4) { + printf("%s: FUNCE is too short: %d\n", + __func__, tuple_len); + break; + } + /* TPLFE_TYPE (Extended Data) */ + ret = sdio_read_direct_sc(sc, 0, addr++, &v); + ERR_OUT(ret); + if (fn == 0) { + if (v != 0x00) + break; + } else { + if (v != 0x01) + break; + addr += 0x0b; + } + ret = sdio_read_direct_sc(sc, 0, addr, &v); + ERR_OUT(ret); + sc->cardinfo.f[fn].max_blksize = v; + ret = sdio_read_direct_sc(sc, 0, addr+1, &v); + ERR_OUT(ret); + sc->cardinfo.f[fn].max_blksize |= (v << 8); + break; + default: + CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_PERIPH, + ("%s: Skipping fn %d tuple %d ID %#02x " + "len %#02x\n", __func__, fn, tuple_count, + tuple_id, tuple_len)); + } + if (tuple_len == 0xff) { + /* Also marks the end of a tuple chain (E1 16.2) */ + /* The tuple is valid, hence this going at the end. */ + break; + } + cis_addr += 2 + tuple_len; + tuple_count++; + } while (tuple_count < 20); +err: +#undef ERR_OUT + return (ret); +} + +static int +sdio_get_common_cis_addr(struct sdiob_softc *sc, uint32_t *addr) +{ + int error; + uint32_t a; + uint8_t val; + + error = sdio_read_direct_sc(sc, 0, SD_IO_CCCR_CISPTR + 0, &val); + if (error != 0) + goto err; + a = val; + error = sdio_read_direct_sc(sc, 0, SD_IO_CCCR_CISPTR + 1, &val); + if (error != 0) + goto err; + a |= (val << 8); + error = sdio_read_direct_sc(sc, 0, SD_IO_CCCR_CISPTR + 2, &val); + if (error != 0) + goto err; + a |= (val << 16); + + if (a < SD_IO_CIS_START || a > SD_IO_CIS_START + SD_IO_CIS_SIZE) { +err: + CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_PERIPH, + ("%s: bad CIS address: %#04x, error %d\n", __func__, a, + error)); + } else if (error == 0 && addr != NULL) + *addr = a; + + return (error); +} + +static int +sdiob_get_card_info(struct sdiob_softc *sc) +{ + struct mmc_params *mmcp; + uint32_t cis_addr, fbr_addr; + int fn, error; + uint8_t fn_max, val; + + error = sdio_get_common_cis_addr(sc, &cis_addr); + if (error != 0) + return (-1); + + memset(&sc->cardinfo, 0, sizeof(sc->cardinfo)); + + /* F0 must always be present. */ + fn = 0; + error = sdio_func_read_cis(sc, fn, cis_addr); + if (error != 0) + return (error); + sc->cardinfo.num_funcs++; + /* Read CCCR Card Capability. */ + error = sdio_read_direct_sc(sc, 0, SD_IO_CCCR_CARDCAP, &val); + if (error != 0) + return (error); + sc->cardinfo.support_multiblk = (val & CCCR_CC_SMB) ? true : false; + DPRINTF("%s: F%d: Vendor %#04x product %#04x max block size %d bytes " + "support_multiblk %s\n", + __func__, fn, sc->cardinfo.f[fn].vendor, sc->cardinfo.f[fn].device, + sc->cardinfo.f[fn].max_blksize, + sc->cardinfo.support_multiblk ? "yes" : "no"); + + /* mmcp->sdio_func_count contains the number of functions w/o F0. */ + mmcp = &sc->ccb->ccb_h.path->device->mmc_ident_data; + fn_max = MIN(mmcp->sdio_func_count + 1, nitems(sc->cardinfo.f)); + for (fn = 1; fn < fn_max; fn++) { + + fbr_addr = SD_IO_FBR_START * fn + SD_IO_FBR_CIS_OFFSET; + + error = sdio_read_direct_sc(sc, 0, fbr_addr++, &val); + if (error != 0) + break; + cis_addr = val; + error = sdio_read_direct_sc(sc, 0, fbr_addr++, &val); + if (error != 0) + break; + cis_addr |= (val << 8); + error = sdio_read_direct_sc(sc, 0, fbr_addr++, &val); + if (error != 0) + break; + cis_addr |= (val << 16); + + error = sdio_func_read_cis(sc, fn, cis_addr); + if (error != 0) + break; + + /* Read the Standard SDIO Function Interface Code. */ + fbr_addr = SD_IO_FBR_START * fn; + error = sdio_read_direct_sc(sc, 0, fbr_addr++, &val); + if (error != 0) + break; + sc->cardinfo.f[fn].class = (val & 0x0f); + if (sc->cardinfo.f[fn].class == 0x0f) { + error = sdio_read_direct_sc(sc, 0, fbr_addr, &val); + if (error != 0) + break; + sc->cardinfo.f[fn].class = val; + } + + sc->cardinfo.f[fn].fn = fn; + sc->cardinfo.f[fn].cur_blksize = sc->cardinfo.f[fn].max_blksize; + sc->cardinfo.f[fn].retries = 0; + sc->cardinfo.f[fn].timeout = 5000; + + DPRINTF("%s: F%d: Class %d Vendor %#04x product %#04x " + "max_blksize %d bytes\n", __func__, fn, + sc->cardinfo.f[fn].class, + sc->cardinfo.f[fn].vendor, sc->cardinfo.f[fn].device, + sc->cardinfo.f[fn].max_blksize); + if (sc->cardinfo.f[fn].vendor == 0) { + DPRINTF("%s: F%d doesn't exist\n", __func__, fn); + break; + } + sc->cardinfo.num_funcs++; + } + return (error); +} + + +/* -------------------------------------------------------------------------- */ +/* + * CAM periph registration, allocation, and detached from that a discovery + * task, which goes off reads cardinfo, and then adds ourselves to our SIM's + * device adding the devclass and registering the driver. This keeps the + * newbus chain connected though we will talk CAM in the middle (until one + * day CAM might be newbusyfied). + */ + +static int +sdio_newbus_sim_add(struct sdiob_softc *sc) +{ + device_t pdev; + devclass_t bus_devclass; + int error; + + /* Add ourselves to our parent (SIM) device. */ + + /* Add ourselves to our parent. That way we can become a parent. */ + KASSERT(sc->periph->sim->sim_dev != NULL, ("%s: sim_dev is NULL, sc %p " + "periph %p sim %p\n", __func__, sc, sc->periph, sc->periph->sim)); + + if (sc->dev == NULL) + sc->dev = BUS_ADD_CHILD(sc->periph->sim->sim_dev, 0, + SDIOB_NAME_S, -1); + if (sc->dev == NULL) + return (ENXIO); + device_set_softc(sc->dev, sc); + /* + * Don't set description here; devclass_add_driver() -> + * device_probe_child() -> device_set_driver() will nuke it again. + */ + + pdev = device_get_parent(sc->dev); + KASSERT(pdev != NULL, ("%s: sc %p dev %p (%s) parent is NULL\n", + __func__, sc, sc->dev, device_get_nameunit(sc->dev))); + bus_devclass = device_get_devclass(pdev); + if (bus_devclass == NULL) { + printf("%s: Failed to get devclass from %s.\n", __func__, + device_get_nameunit(pdev)); + return (ENXIO); + } + + mtx_lock(&Giant); + error = devclass_add_driver(bus_devclass, &sdiob_driver, + BUS_PASS_DEFAULT, &sdiob_devclass); + mtx_unlock(&Giant); + if (error != 0) { + printf("%s: Failed to add driver to devclass: %d.\n", + __func__, error); + return (error); + } + + /* Done. */ + sc->nb_state = NB_STATE_SIM_ADDED; + + return (0); +} + +static void +sdiobdiscover(void *context, int pending) +{ + struct cam_periph *periph; + struct sdiob_softc *sc; + int error; + + KASSERT(context != NULL, ("%s: context is NULL\n", __func__)); + periph = (struct cam_periph *)context; + CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s\n", __func__)); + + /* Periph was held for us when this task was enqueued. */ + if ((periph->flags & CAM_PERIPH_INVALID) != 0) { + cam_periph_release(periph); + return; + } + + sc = periph->softc; + sc->sdio_state = SDIO_STATE_INITIALIZING; + + if (sc->ccb == NULL) + sc->ccb = xpt_alloc_ccb(); + else + memset(sc->ccb, 0, sizeof(*sc->ccb)); + xpt_setup_ccb(&sc->ccb->ccb_h, periph->path, CAM_PRIORITY_NONE); + + /* + * Read CCCR and FBR of each function, get manufacturer and device IDs, + * max block size, and whatever else we deem necessary. + */ + cam_periph_lock(periph); + error = sdiob_get_card_info(sc); + if (error == 0) + sc->sdio_state = SDIO_STATE_READY; + else + sc->sdio_state = SDIO_STATE_DEAD; + cam_periph_unlock(periph); + + if (error) + return; + + CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s: num_func %d\n", + __func__, sc->cardinfo.num_funcs)); + + /* + * Now CAM portion of the driver has been initialized and + * we know VID/PID of all the functions on the card. + * Time to hook into the newbus. + */ + error = sdio_newbus_sim_add(sc); + if (error != 0) + sc->nb_state = NB_STATE_DEAD; + + return; +} + +/* Called at the end of cam_periph_alloc() for us to finish allocation. */ +static cam_status +sdiobregister(struct cam_periph *periph, void *arg) +{ + struct sdiob_softc *sc; + int error; + + CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s: arg %p\n", __func__, arg)); + if (arg == NULL) { + printf("%s: no getdev CCB, can't register device pariph %p\n", + __func__, periph); + return(CAM_REQ_CMP_ERR); + } + if (periph->sim == NULL || periph->sim->sim_dev == NULL) { + printf("%s: no sim %p or sim_dev %p\n", __func__, periph->sim, + (periph->sim != NULL) ? periph->sim->sim_dev : NULL); + return(CAM_REQ_CMP_ERR); + } + + sc = (struct sdiob_softc *) malloc(sizeof(*sc), M_DEVBUF, + M_NOWAIT|M_ZERO); + if (sc == NULL) { + printf("%s: unable to allocate sc\n", __func__); + return (CAM_REQ_CMP_ERR); + } + sc->sdio_state = SDIO_STATE_DEAD; + sc->nb_state = NB_STATE_DEAD; + TASK_INIT(&sc->discover_task, 0, sdiobdiscover, periph); + + /* Refcount until we are setup. Can't block. */ + error = cam_periph_hold(periph, PRIBIO); + if (error != 0) { + printf("%s: lost periph during registration!\n", __func__); + free(sc, M_DEVBUF); + return(CAM_REQ_CMP_ERR); + } + periph->softc = sc; + sc->periph = periph; + cam_periph_unlock(periph); + + error = taskqueue_enqueue(taskqueue_thread, &sc->discover_task); + + cam_periph_lock(periph); + /* We will continue to hold a refcount for discover_task. */ + /* cam_periph_unhold(periph); */ + + xpt_schedule(periph, CAM_PRIORITY_XPT); + + return (CAM_REQ_CMP); +} + +static void +sdioboninvalidate(struct cam_periph *periph) +{ + + CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s:\n", __func__)); + + return; +} + +static void +sdiobcleanup(struct cam_periph *periph) +{ + + CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s:\n", __func__)); + + return; +} + +static void +sdiobstart(struct cam_periph *periph, union ccb *ccb) +{ + + CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s: ccb %p\n", __func__, ccb)); + + return; +} + +static void +sdiobasync(void *softc, uint32_t code, struct cam_path *path, void *arg) +{ + struct cam_periph *periph; + struct ccb_getdev *cgd; + cam_status status; + + periph = (struct cam_periph *)softc; + + CAM_DEBUG(path, CAM_DEBUG_TRACE, ("%s(code=%d)\n", __func__, code)); + switch (code) { + case AC_FOUND_DEVICE: + if (arg == NULL) + break; + cgd = (struct ccb_getdev *)arg; + if (cgd->protocol != PROTO_MMCSD) + break; + + /* We do not support SD memory (Combo) Cards. */ + if ((path->device->mmc_ident_data.card_features & + CARD_FEATURE_MEMORY)) { + CAM_DEBUG(path, CAM_DEBUG_TRACE, + ("Memory card, not interested\n")); + break; + } + + /* + * Allocate a peripheral instance for this device which starts + * the probe process. + */ + status = cam_periph_alloc(sdiobregister, sdioboninvalidate, + sdiobcleanup, sdiobstart, SDIOB_NAME_S, CAM_PERIPH_BIO, path, + sdiobasync, AC_FOUND_DEVICE, cgd); + if (status != CAM_REQ_CMP && status != CAM_REQ_INPROG) + CAM_DEBUG(path, CAM_DEBUG_PERIPH, + ("%s: Unable to attach to new device due to " + "status %#02x\n", __func__, status)); + break; + default: + CAM_DEBUG(path, CAM_DEBUG_PERIPH, + ("%s: cannot handle async code %#02x\n", __func__, code)); + cam_periph_async(periph, code, path, arg); + break; + } +} + +static void +sdiobinit(void) +{ + cam_status status; + + /* + * Register for new device notification. We will be notified for all + * already existing ones. + */ + status = xpt_register_async(AC_FOUND_DEVICE, sdiobasync, NULL, NULL); + if (status != CAM_REQ_CMP) + printf("%s: Failed to attach async callback, statux %#02x", + __func__, status); +} + +/* This function will allow unloading the KLD. */ +static int +sdiobdeinit(void) +{ + + return (EOPNOTSUPP); +} + +static struct periph_driver sdiobdriver = +{ + .init = sdiobinit, + .driver_name = SDIOB_NAME_S, + .units = TAILQ_HEAD_INITIALIZER(sdiobdriver.units), + .generation = 0, + .flags = 0, + .deinit = sdiobdeinit, +}; + +PERIPHDRIVER_DECLARE(SDIOB_NAME, sdiobdriver); +MODULE_VERSION(SDIOB_NAME, 1); diff --git a/sys/dev/sdio/sdiob.h b/sys/dev/sdio/sdiob.h new file mode 100644 index 000000000000..24130db074bc --- /dev/null +++ b/sys/dev/sdio/sdiob.h @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 2019 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * 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 ``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. + * + * + * Portions of this software may have been developed with reference to + * the SD Simplified Specification. The following disclaimer may apply: + * + * The following conditions apply to the release of the simplified + * specification ("Simplified Specification") by the SD Card Association and + * the SD Group. The Simplified Specification is a subset of the complete SD + * Specification which is owned by the SD Card Association and the SD + * Group. This Simplified Specification is provided on a non-confidential + * basis subject to the disclaimers below. Any implementation of the + * Simplified Specification may require a license from the SD Card + * Association, SD Group, SD-3C LLC or other third parties. + * + * Disclaimers: + * + * The information contained in the Simplified Specification is presented only + * as a standard specification for SD Cards and SD Host/Ancillary products and + * is provided "AS-IS" without any representations or warranties of any + * kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD + * Card Association for any damages, any infringements of patents or other + * right of the SD Group, SD-3C LLC, the SD Card Association or any third + * parties, which may result from its use. No license is granted by + * implication, estoppel or otherwise under any patent or other rights of the + * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing + * herein shall be construed as an obligation by the SD Group, the SD-3C LLC + * or the SD Card Association to disclose or distribute any technical + * information, know-how or other confidential information to any third party. + * + * + * $FreeBSD$ + */ + +#ifndef _SDIOB_H +#define _SDIOB_H + +#define SDIOB_NAME sdiob +#define _SDIOB_NAME_S(x) __STRING(x) +#define SDIOB_NAME_S _SDIOB_NAME_S(SDIOB_NAME) + +#ifdef _SYS_BUS_H_ +/* Ivars for sdiob. */ +enum sdiob_dev_enum { + SDIOB_IVAR_SUPPORT_MULTIBLK, + SDIOB_IVAR_FUNCTION, + SDIOB_IVAR_FUNCNUM, + SDIOB_IVAR_CLASS, + SDIOB_IVAR_VENDOR, + SDIOB_IVAR_DEVICE, + SDIOB_IVAR_DRVDATA, +}; + +#define SDIOB_ACCESSOR(var, ivar, type) \ + __BUS_ACCESSOR(sdio, var, SDIOB, ivar, type) + +SDIOB_ACCESSOR(support_multiblk,SUPPORT_MULTIBLK, bool) +SDIOB_ACCESSOR(function, FUNCTION, struct sdio_func *) +SDIOB_ACCESSOR(funcnum, FUNCNUM, uint8_t) +SDIOB_ACCESSOR(class, CLASS, uint8_t) +SDIOB_ACCESSOR(vendor, VENDOR, uint16_t) +SDIOB_ACCESSOR(device, DEVICE, uint16_t) +SDIOB_ACCESSOR(drvdata, DRVDATA, void *) + +#undef SDIOB_ACCESSOR +#endif /* _SYS_BUS_H_ */ + +#endif /* _SDIOB_H */ diff --git a/sys/dev/sdio/sdiodevs b/sys/dev/sdio/sdiodevs new file mode 100644 index 000000000000..2fe01f111ffb --- /dev/null +++ b/sys/dev/sdio/sdiodevs @@ -0,0 +1,74 @@ +$FreeBSD$ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * 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. + */ +/* + * Take SDIO CIS, CISTPL_MANFID, TPLMID_MANF and TPLMID_CARD information and + * present them as vendor and device IDs (a terminology we understand for + * other parts) and run them through the usbdevs2h.awk script to generate + * a header file with #defines for them in sdiodevs.h and sdiodevs_data.h + * which provides a structure with a description as well. + * The format of this file is modelled after sys/dev/usb/usbdevs. + * For more details see there. + */ + +/* + * -------------------------------------------------------------------------- + * List of TPLMID_MANF "vendor ID"s. + * Please sort by vendor ID ascending. + */ +vendor BROADCOM 0x02d0 Broadcom +vendor CYPRESS 0x02d0 Cypress/Broadcom + +/* + * -------------------------------------------------------------------------- + * List of TPLMID_CARD "product ID"s. + * Please group by vendor in same order as above. + */ + +/* Broadcom products */ +product BROADCOM 43241 0x4324 BCM43241 fullmac SDIO WiFi +product BROADCOM 4329 0x4329 BCM4329 fullmac SDIO WiFi +product BROADCOM 4330 0x4330 BCM4330 fullmac SDIO WiFi +product BROADCOM 4334 0x4334 BCM4334 fullmac SDIO WiFi +product BROADCOM 4335_4339 0x4335 BCM4335_4339 fullmac SDIO WiFi +product BROADCOM 4339 0x4339 BCM4339 fullmac SDIO WiFi +product BROADCOM 4345 0x4345 BCM4345 fullmac SDIO WiFi +product BROADCOM 4354 0x4354 BCM4354 fullmac SDIO WiFi +product BROADCOM 4356 0x4356 BCM4356 fullmac SDIO WiFi +product BROADCOM 43143 0xa887 BCM43143 fullmac SDIO WiFi +product BROADCOM 43340 0xa94c BCM43340 fullmac SDIO WiFi +product BROADCOM 43341 0xa94d BCM43341 fullmac SDIO WiFi +product BROADCOM 43362 0xa962 BCM43362 fullmac SDIO WiFi +product BROADCOM 43364 0xa9a4 BCM43364 fullmac SDIO WiFi +product BROADCOM 43430 0xa9a6 BCM43430 fullmac SDIO WiFi +product BROADCOM 43455 0xa9bf BCM43455 fullmac SDIO WiFi +product CYPRESS 4373 0x4373 CY4373 fullmac SDIO WiFi + +/* end */ diff --git a/sys/dev/ti/if_ti.c b/sys/dev/ti/if_ti.c index 1aa9dd3ecbe1..b25eb64d2479 100644 --- a/sys/dev/ti/if_ti.c +++ b/sys/dev/ti/if_ti.c @@ -1623,7 +1623,7 @@ ti_newbuf_jumbo(struct ti_softc *sc, int idx, struct mbuf *m_old) } sf[i] = sf_buf_alloc(frame, SFB_NOWAIT); if (sf[i] == NULL) { - vm_page_unwire(frame, PQ_NONE); + vm_page_unwire_noq(frame); vm_page_free(frame); device_printf(sc->ti_dev, "buffer allocation " "failed -- packet dropped!\n"); diff --git a/sys/dev/uart/uart_tty.c b/sys/dev/uart/uart_tty.c index 1bef6384678e..ad7052289f0b 100644 --- a/sys/dev/uart/uart_tty.c +++ b/sys/dev/uart/uart_tty.c @@ -285,13 +285,16 @@ uart_tty_param(struct tty *tp, struct termios *t) parity = UART_PARITY_NONE; if (UART_PARAM(sc, t->c_ospeed, databits, stopbits, parity) != 0) return (EINVAL); - UART_SETSIG(sc, SER_DDTR | SER_DTR); + if ((t->c_cflag & CNO_RTSDTR) == 0) + UART_SETSIG(sc, SER_DDTR | SER_DTR); /* Set input flow control state. */ if (!sc->sc_hwiflow) { if ((t->c_cflag & CRTS_IFLOW) && sc->sc_isquelch) UART_SETSIG(sc, SER_DRTS); - else - UART_SETSIG(sc, SER_DRTS | SER_RTS); + else { + if ((t->c_cflag & CNO_RTSDTR) == 0) + UART_SETSIG(sc, SER_DRTS | SER_RTS); + } } else UART_IOCTL(sc, UART_IOCTL_IFLOW, (t->c_cflag & CRTS_IFLOW)); /* Set output flow control state. */ diff --git a/sys/dev/usb/net/if_cdce.c b/sys/dev/usb/net/if_cdce.c index c5d0233c0258..d63539da7e89 100644 --- a/sys/dev/usb/net/if_cdce.c +++ b/sys/dev/usb/net/if_cdce.c @@ -50,7 +50,7 @@ #include __FBSDID("$FreeBSD$"); -#include +#include #include #include #include diff --git a/sys/dev/usb/serial/umcs.c b/sys/dev/usb/serial/umcs.c index bcff8190344d..d314010b05b3 100644 --- a/sys/dev/usb/serial/umcs.c +++ b/sys/dev/usb/serial/umcs.c @@ -499,7 +499,9 @@ umcs7840_cfg_open(struct ucom_softc *ucom) * Enable DTR/RTS on modem control, enable modem interrupts -- * documented */ - sc->sc_ports[pn].sc_mcr = MCS7840_UART_MCR_DTR | MCS7840_UART_MCR_RTS | MCS7840_UART_MCR_IE; + sc->sc_ports[pn].sc_mcr = MCS7840_UART_MCR_IE; + if (ucom->sc_tty == NULL || (ucom->sc_tty->t_termios.c_cflag & CNO_RTSDTR) == 0) + sc->sc_ports[pn].sc_mcr |= MCS7840_UART_MCR_DTR | MCS7840_UART_MCR_RTS; if (umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_MCR, sc->sc_ports[pn].sc_mcr)) return; diff --git a/sys/dev/usb/serial/usb_serial.c b/sys/dev/usb/serial/usb_serial.c index 445c9f2127b8..698ad87c88fe 100644 --- a/sys/dev/usb/serial/usb_serial.c +++ b/sys/dev/usb/serial/usb_serial.c @@ -796,7 +796,8 @@ ucom_open(struct tty *tp) &sc->sc_start_task[0].hdr, &sc->sc_start_task[1].hdr); - ucom_modem(tp, SER_DTR | SER_RTS, 0); + if (sc->sc_tty == NULL || (sc->sc_tty->t_termios.c_cflag & CNO_RTSDTR) == 0) + ucom_modem(tp, SER_DTR | SER_RTS, 0); ucom_ring(sc, 0); diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c index 63c870f33b57..186d383e35fe 100644 --- a/sys/dev/usb/usb_hub.c +++ b/sys/dev/usb/usb_hub.c @@ -75,14 +75,9 @@ #include #endif /* USB_GLOBAL_INCLUDE_FILE */ -#define UHUB_INTR_INTERVAL 250 /* ms */ -enum { - UHUB_INTR_TRANSFER, -#if USB_HAVE_TT_SUPPORT - UHUB_RESET_TT_TRANSFER, -#endif - UHUB_N_TRANSFER, -}; + +#include + #ifdef USB_DEBUG static int uhub_debug = 0; @@ -111,29 +106,6 @@ SYSCTL_INT(_hw_usb, OID_AUTO, disable_port_power, CTLFLAG_RWTUN, &usb_disable_port_power, 0, "Set to disable all USB port power."); #endif -struct uhub_current_state { - uint16_t port_change; - uint16_t port_status; -}; - -struct uhub_softc { - struct uhub_current_state sc_st;/* current state */ -#if (USB_HAVE_FIXED_PORT != 0) - struct usb_hub sc_hub; -#endif - device_t sc_dev; /* base device */ - struct mtx sc_mtx; /* our mutex */ - struct usb_device *sc_udev; /* USB device */ - struct usb_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */ -#if USB_HAVE_DISABLE_ENUM - int sc_disable_enumeration; - int sc_disable_port_power; -#endif - uint8_t sc_usb_port_errors; /* error counter */ -#define UHUB_USB_PORT_ERRORS_MAX 4 - uint8_t sc_flags; -#define UHUB_FLAG_DID_EXPLORE 0x01 -}; #define UHUB_PROTO(sc) ((sc)->sc_udev->ddesc.bDeviceProtocol) #define UHUB_IS_HIGH_SPEED(sc) (UHUB_PROTO(sc) != UDPROTO_FSHUB) @@ -143,14 +115,10 @@ struct uhub_softc { /* prototypes for type checking: */ -static device_probe_t uhub_probe; -static device_attach_t uhub_attach; -static device_detach_t uhub_detach; static device_suspend_t uhub_suspend; static device_resume_t uhub_resume; static bus_driver_added_t uhub_driver_added; -static bus_child_location_str_t uhub_child_location_string; static bus_child_pnpinfo_str_t uhub_child_pnpinfo_string; static usb_callback_t uhub_intr_callback; @@ -207,7 +175,7 @@ static device_method_t uhub_methods[] = { DEVMETHOD_END }; -static driver_t uhub_driver = { +driver_t uhub_driver = { .name = "uhub", .methods = uhub_methods, .size = sizeof(struct uhub_softc) @@ -1138,7 +1106,7 @@ uhub_explore(struct usb_device *udev) return (USB_ERR_NORMAL_COMPLETION); } -static int +int uhub_probe(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); @@ -1152,7 +1120,7 @@ uhub_probe(device_t dev) */ if (uaa->info.bConfigIndex == 0 && uaa->info.bDeviceClass == UDCLASS_HUB) - return (0); + return (BUS_PROBE_DEFAULT); return (ENXIO); } @@ -1218,7 +1186,7 @@ uhub_query_info(struct usb_device *udev, uint8_t *pnports, uint8_t *ptt) return (err); } -static int +int uhub_attach(device_t dev) { struct uhub_softc *sc = device_get_softc(dev); @@ -1564,7 +1532,7 @@ uhub_attach(device_t dev) * Called from process context when the hub is gone. * Detach all devices on active ports. */ -static int +int uhub_detach(device_t dev) { struct uhub_softc *sc = device_get_softc(dev); @@ -1634,13 +1602,7 @@ uhub_driver_added(device_t dev, driver_t *driver) usb_needs_explore_all(); } -struct hub_result { - struct usb_device *udev; - uint8_t portno; - uint8_t iface_index; -}; - -static void +void uhub_find_iface_index(struct usb_hub *hub, device_t child, struct hub_result *res) { @@ -1673,7 +1635,7 @@ uhub_find_iface_index(struct usb_hub *hub, device_t child, res->portno = 0; } -static int +int uhub_child_location_string(device_t parent, device_t child, char *buf, size_t buflen) { diff --git a/sys/dev/usb/usb_hub_acpi.c b/sys/dev/usb/usb_hub_acpi.c new file mode 100644 index 000000000000..5dd9f06ebaa4 --- /dev/null +++ b/sys/dev/usb/usb_hub_acpi.c @@ -0,0 +1,451 @@ +/* $FreeBSD$ */ +/*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * + * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved. + * Copyright (c) 1998 Lennart Augustsson. All rights reserved. + * Copyright (c) 2008-2010 Hans Petter Selasky. All rights reserved. + * Copyright (c) 2019 Takanori Watanabe. + * + * 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. + */ + +/* + * USB spec: http://www.usb.org/developers/docs/usbspec.zip + */ + +#ifdef USB_GLOBAL_INCLUDE_FILE +#include USB_GLOBAL_INCLUDE_FILE +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define USB_DEBUG_VAR uhub_debug + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#endif /* USB_GLOBAL_INCLUDE_FILE */ +#include +#include +#include +#include + +static UINT32 acpi_uhub_find_rh_cb(ACPI_HANDLE ah, UINT32 nl, void *ctx, void **status); +static ACPI_STATUS acpi_uhub_find_rh(device_t dev, ACPI_HANDLE * ah); +static ACPI_STATUS +acpi_usb_hub_port_probe_cb(ACPI_HANDLE ah, UINT32 lv, void *ctx, void **rv); +static ACPI_STATUS acpi_usb_hub_port_probe(device_t dev, ACPI_HANDLE ah); +static int acpi_uhub_root_probe(device_t dev); +static int acpi_uhub_probe(device_t dev); +static int acpi_uhub_root_attach(device_t dev); +static int acpi_uhub_attach(device_t dev); +static int acpi_uhub_detach(device_t dev); +static int +acpi_uhub_read_ivar(device_t dev, device_t child, int idx, + uintptr_t *res); +static int +acpi_uhub_child_location_string(device_t parent, device_t child, + char *buf, size_t buflen); +static int acpi_uhub_parse_upc(device_t dev, unsigned int port, ACPI_HANDLE ah); + +struct acpi_uhub_softc { + struct uhub_softc usc; + uint8_t nports; + ACPI_HANDLE *porthandle; +}; + +UINT32 +acpi_uhub_find_rh_cb(ACPI_HANDLE ah, UINT32 nl, void *ctx, void **status){ + ACPI_DEVICE_INFO *devinfo; + UINT32 ret = AE_OK; + + *status = NULL; + devinfo = NULL; + + ret = AcpiGetObjectInfo(ah, &devinfo); + + if (ACPI_FAILURE(ret)) { + return ret; + } + if ((devinfo->Valid & ACPI_VALID_ADR) && + (devinfo->Address == 0)) { + ret = AE_CTRL_TERMINATE; + *status = ah; + } + AcpiOsFree(devinfo); + + return ret; +} + +static int +acpi_uhub_parse_upc(device_t dev, unsigned int port, ACPI_HANDLE ah) +{ + ACPI_BUFFER buf; + + buf.Pointer = NULL; + buf.Length = ACPI_ALLOCATE_BUFFER; + if (AcpiEvaluateObject(ah, "_UPC", NULL, &buf) == AE_OK) { + UINT64 porttypenum, conn; + const char *connectable; + const char *typelist[] = {"TypeA", "MiniAB", "Express", + "USB3-A", "USB3-B", "USB-MicroB", + "USB3-MicroAB", "USB3-PowerB", + "TypeC-USB2", "TypeC-Switch", + "TypeC-nonSwitch"}; + const char *porttype; + const int last = sizeof(typelist) / sizeof(typelist[0]); + ACPI_OBJECT *obj = buf.Pointer; + + acpi_PkgInt(obj, 0, &conn); + acpi_PkgInt(obj, 1, &porttypenum); + connectable = conn ? "" : "non"; + if (porttypenum == 0xff) + porttype = "Proprietary"; + else if (porttypenum < last) { + porttype = typelist[porttypenum]; + } else { + porttype = "Unknown"; + } + if (usb_debug) + device_printf(dev, "Port %u %sconnectable %s\n", + port, connectable, porttype); + } + AcpiOsFree(buf.Pointer); + + return 0; +} + +static int +acpi_uhub_parse_pld(device_t dev, unsigned int port, ACPI_HANDLE ah) +{ + ACPI_BUFFER buf; + + buf.Pointer = NULL; + buf.Length = ACPI_ALLOCATE_BUFFER; + if (AcpiEvaluateObject(ah, "_PLD", NULL, &buf) == AE_OK) { + ACPI_OBJECT *obj; + unsigned char *resbuf; + int len; + + obj = buf.Pointer; + + if (obj->Type == ACPI_TYPE_PACKAGE + && obj->Package.Elements[0].Type == ACPI_TYPE_BUFFER) { + ACPI_OBJECT *obj1; + + obj1 = &obj->Package.Elements[0]; + len = obj1->Buffer.Length; + resbuf = obj1->Buffer.Pointer; + } else if (obj->Type == ACPI_TYPE_BUFFER) { + len = obj->Buffer.Length; + resbuf = obj->Buffer.Pointer; + } else { + goto skip; + } + if (usb_debug) { + device_printf(dev, "Revision:%d\n", + resbuf[0] & 0x7f); + if ((resbuf[0] & 0x80) == 0) { + device_printf(dev, + "Color:#%02x%02x%02x\n", + resbuf[1], resbuf[2], + resbuf[3]); + } + device_printf(dev, "Width %d mm Height %d mm\n", + resbuf[4] | (resbuf[5] << 8), + resbuf[6] | (resbuf[7] << 8)); + if (resbuf[8] & 1) { + device_printf(dev, "Visible\n"); + } + if (resbuf[8] & 2) { + device_printf(dev, "Dock\n"); + } + if (resbuf[8] & 4) { + device_printf(dev, "Lid\n"); + } + device_printf(dev, "PanelPosition: %d\n", + (resbuf[8] >> 3) & 7); + device_printf(dev, "VertPosition: %d\n", + (resbuf[8] >> 6) & 3); + device_printf(dev, "HorizPosition: %d\n", + (resbuf[9]) & 3); + device_printf(dev, "Shape: %d\n", + (resbuf[9] >> 2) & 0xf); + device_printf(dev, "80: %02x, %02x, %02x\n", + resbuf[9], resbuf[10], resbuf[11]); + device_printf(dev, "96: %02x, %02x, %02x, %02x\n", + resbuf[12], resbuf[13], + resbuf[14], resbuf[15]); + + if ((resbuf[0] & 0x7f) >= 2) { + device_printf(dev, "VOFF%d mm HOFF %dmm", + resbuf[16] | (resbuf[17] << 8), + resbuf[18] | (resbuf[19] << 8)); + } + } + skip: + AcpiOsFree(buf.Pointer); + + } + + + return 0; +} + +ACPI_STATUS +acpi_uhub_find_rh(device_t dev, ACPI_HANDLE * ah){ + device_t grand; + ACPI_HANDLE gah; + + grand = device_get_parent(device_get_parent(dev)); + if ((gah = acpi_get_handle(grand)) == NULL) { + *ah = NULL; + return AE_ERROR; + } + return AcpiWalkNamespace(ACPI_TYPE_DEVICE, gah, 1, + acpi_uhub_find_rh_cb, NULL, dev, ah); +} + +ACPI_STATUS +acpi_usb_hub_port_probe_cb(ACPI_HANDLE ah, UINT32 lv, void *ctx, void **rv){ + ACPI_DEVICE_INFO *devinfo; + device_t dev = ctx; + struct acpi_uhub_softc *sc = device_get_softc(dev); + + if (usb_debug) + device_printf(dev, "%s\n", acpi_name(ah)); + + AcpiGetObjectInfo(ah, &devinfo); + if ((devinfo->Valid & ACPI_VALID_ADR) && + (devinfo->Address > 0) && + (devinfo->Address <= (uint64_t)sc->nports)) { + sc->porthandle[devinfo->Address - 1] = ah; + acpi_uhub_parse_upc(dev, devinfo->Address, ah); + acpi_uhub_parse_pld(dev, devinfo->Address, ah); + } else { + device_printf(dev, "Skiping invalid devobj %s\n", + acpi_name(ah)); + } + AcpiOsFree(devinfo); + return AE_OK; +} + +ACPI_STATUS +acpi_usb_hub_port_probe(device_t dev, ACPI_HANDLE ah){ + return AcpiWalkNamespace(ACPI_TYPE_DEVICE, + ah, 1, + acpi_usb_hub_port_probe_cb, + NULL, dev, NULL); +} +int +acpi_uhub_root_probe(device_t dev) +{ + ACPI_HANDLE ah; + ACPI_STATUS status; + + status = acpi_uhub_find_rh(dev, &ah); + if (ACPI_SUCCESS(status) + && ah != NULL + && (uhub_probe(dev) <= 0)) { + /* success prior than non - acpi hub */ + return (BUS_PROBE_DEFAULT + 1); + } + return ENXIO; +} + +int +acpi_uhub_probe(device_t dev) +{ + ACPI_HANDLE ah = acpi_get_handle(dev); + + if (ah && (uhub_probe(dev) <= 0)) { + /*success prior than non - acpi hub*/ + return (BUS_PROBE_DEFAULT + 1); + } + return (ENXIO); +} +int +acpi_uhub_root_attach(device_t dev) +{ + ACPI_HANDLE devhandle; + struct usb_hub *uh; + struct acpi_uhub_softc *sc = device_get_softc(dev); + int ret; + + if ((ret = uhub_attach(dev)) != 0) { + return (ret); + } + uh = sc->usc.sc_udev->hub; + + if (ACPI_FAILURE(acpi_uhub_find_rh(dev, &devhandle)) || + (devhandle == NULL)) { + return ENXIO; + } + + sc->nports = uh->nports; + sc->porthandle = malloc(sizeof(ACPI_HANDLE) * uh->nports, + M_USBDEV, M_WAITOK | M_ZERO); + acpi_uhub_find_rh(dev, &devhandle); + acpi_usb_hub_port_probe(dev, devhandle); + + return 0; +} + +int +acpi_uhub_attach(device_t dev) +{ + struct usb_hub *uh; + struct acpi_uhub_softc *sc = device_get_softc(dev); + ACPI_HANDLE devhandle; + int ret; + + if ((ret = uhub_attach(dev)) != 0) { + return (ret); + } + uh = sc->usc.sc_udev->hub; + devhandle = acpi_get_handle(dev); + + if (devhandle == NULL) { + return ENXIO; + } + + sc->nports = uh->nports; + sc->porthandle = malloc(sizeof(ACPI_HANDLE) * uh->nports, + M_USBDEV, M_WAITOK | M_ZERO); + acpi_usb_hub_port_probe(dev, acpi_get_handle(dev)); + return 0; +} + +int +acpi_uhub_read_ivar(device_t dev, device_t child, int idx, + uintptr_t *res) +{ + struct hub_result hres; + struct acpi_uhub_softc *sc = device_get_softc(dev); + ACPI_HANDLE ah; + + mtx_lock(&Giant); + uhub_find_iface_index(sc->usc.sc_udev->hub, child, &hres); + mtx_unlock(&Giant); + if ((idx == ACPI_IVAR_HANDLE) && + (hres.portno > 0) && + (hres.portno <= sc->nports) && + (ah = sc->porthandle[hres.portno - 1])) { + *res = (uintptr_t)ah; + return (0); + } + return (ENXIO); +} +static int +acpi_uhub_child_location_string(device_t parent, device_t child, + char *buf, size_t buflen) +{ + + ACPI_HANDLE ah; + + uhub_child_location_string(parent, child, buf, buflen); + ah = acpi_get_handle(child); + if (ah) { + strlcat(buf, " handle=", buflen); + strlcat(buf, acpi_name(ah), buflen); + } + return (0); +} + +int +acpi_uhub_detach(device_t dev) +{ + struct acpi_uhub_softc *sc = device_get_softc(dev); + + free(sc->porthandle, M_USBDEV); + return uhub_detach(dev); +} + +static device_method_t acpi_uhub_methods[] = { + DEVMETHOD(device_probe, acpi_uhub_probe), + DEVMETHOD(device_attach, acpi_uhub_attach), + DEVMETHOD(device_detach, acpi_uhub_detach), + DEVMETHOD(bus_child_location_str, acpi_uhub_child_location_string), + DEVMETHOD(bus_read_ivar, acpi_uhub_read_ivar), + DEVMETHOD_END + +}; + +static device_method_t acpi_uhub_root_methods[] = { + DEVMETHOD(device_probe, acpi_uhub_root_probe), + DEVMETHOD(device_attach, acpi_uhub_root_attach), + DEVMETHOD(device_detach, acpi_uhub_detach), + DEVMETHOD(bus_read_ivar, acpi_uhub_read_ivar), + DEVMETHOD(bus_child_location_str, acpi_uhub_child_location_string), + DEVMETHOD_END +}; + +static devclass_t uhub_devclass; +extern driver_t uhub_driver; +static kobj_class_t uhub_baseclasses[] = {&uhub_driver, NULL}; +static driver_t acpi_uhub_driver = { + .name = "uhub", + .methods = acpi_uhub_methods, + .size = sizeof(struct acpi_uhub_softc), + .baseclasses = uhub_baseclasses, +}; +static driver_t acpi_uhub_root_driver = { + .name = "uhub", + .methods = acpi_uhub_root_methods, + .size = sizeof(struct acpi_uhub_softc), + .baseclasses = uhub_baseclasses, +}; + +DRIVER_MODULE(acpi_uhub, uhub, acpi_uhub_driver, uhub_devclass, 0, 0); +MODULE_DEPEND(acpi_uhub, acpi, 1, 1, 1); +DRIVER_MODULE(acpi_uhub, usbus, acpi_uhub_root_driver, uhub_devclass, 0, 0); diff --git a/sys/dev/usb/usb_hub_private.h b/sys/dev/usb/usb_hub_private.h new file mode 100644 index 000000000000..1151ed7d1931 --- /dev/null +++ b/sys/dev/usb/usb_hub_private.h @@ -0,0 +1,86 @@ +/* $FreeBSD$ */ +/*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * + * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved. + * Copyright (c) 1998 Lennart Augustsson. All rights reserved. + * Copyright (c) 2008-2010 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. + */ + +/* + * USB spec: http://www.usb.org/developers/docs/usbspec.zip + */ + +#ifndef USB_HUB_PRIVATE_H_ +#define USB_HUB_PRIVATE_H_ +#define UHUB_INTR_INTERVAL 250 /* ms */ + +enum { + UHUB_INTR_TRANSFER, +#if USB_HAVE_TT_SUPPORT + UHUB_RESET_TT_TRANSFER, +#endif + UHUB_N_TRANSFER, +}; + + +struct uhub_current_state { + uint16_t port_change; + uint16_t port_status; +}; + +struct uhub_softc { + struct uhub_current_state sc_st; /* current state */ +#if (USB_HAVE_FIXED_PORT != 0) + struct usb_hub sc_hub; +#endif + device_t sc_dev; /* base device */ + struct mtx sc_mtx; /* our mutex */ + struct usb_device *sc_udev; /* USB device */ + struct usb_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */ +#if USB_HAVE_DISABLE_ENUM + int sc_disable_enumeration; + int sc_disable_port_power; +#endif + uint8_t sc_usb_port_errors; /* error counter */ +#define UHUB_USB_PORT_ERRORS_MAX 4 + uint8_t sc_flags; +#define UHUB_FLAG_DID_EXPLORE 0x01 +}; +struct hub_result { + struct usb_device *udev; + uint8_t portno; + uint8_t iface_index; +}; + +void +uhub_find_iface_index(struct usb_hub *hub, device_t child, + struct hub_result *res); + +device_probe_t uhub_probe; +device_attach_t uhub_attach; +device_detach_t uhub_detach; +bus_child_location_str_t uhub_child_location_string; + +#endif diff --git a/sys/dev/xen/gntdev/gntdev.c b/sys/dev/xen/gntdev/gntdev.c index bf6685cf6ca5..ed42e177b860 100644 --- a/sys/dev/xen/gntdev/gntdev.c +++ b/sys/dev/xen/gntdev/gntdev.c @@ -278,7 +278,7 @@ gref_list_dtor(struct cleanup_data_struct *cleanup_data) continue; gnttab_free_grant_reference(gref->gref_id); } - vm_page_unwire(gref->page, PQ_NONE); + vm_page_unwire_noq(gref->page); vm_page_free(gref->page); gref->page = NULL; } diff --git a/sys/fs/ext2fs/ext2_csum.c b/sys/fs/ext2fs/ext2_csum.c index de8f8019f4bc..0ca258f12f72 100644 --- a/sys/fs/ext2fs/ext2_csum.c +++ b/sys/fs/ext2fs/ext2_csum.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include diff --git a/sys/fs/nandfs/nandfs_segment.c b/sys/fs/nandfs/nandfs_segment.c index c6c5885891ef..36efc89af409 100644 --- a/sys/fs/nandfs/nandfs_segment.c +++ b/sys/fs/nandfs/nandfs_segment.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/fs/nandfs/nandfs_subr.c b/sys/fs/nandfs/nandfs_subr.c index 1f0521b69152..0a3f65a50543 100644 --- a/sys/fs/nandfs/nandfs_subr.c +++ b/sys/fs/nandfs/nandfs_subr.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include diff --git a/sys/fs/nandfs/nandfs_vfsops.c b/sys/fs/nandfs/nandfs_vfsops.c index c8d6daa9a3cd..f703044728ef 100644 --- a/sys/fs/nandfs/nandfs_vfsops.c +++ b/sys/fs/nandfs/nandfs_vfsops.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/geom/concat/g_concat.c b/sys/geom/concat/g_concat.c index a0a95b85aba0..e686ffc51285 100644 --- a/sys/geom/concat/g_concat.c +++ b/sys/geom/concat/g_concat.c @@ -1004,24 +1004,24 @@ g_concat_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sbuf_printf(sb, "%s", indent); switch (sc->sc_type) { case G_CONCAT_TYPE_AUTOMATIC: - sbuf_printf(sb, "AUTOMATIC"); + sbuf_cat(sb, "AUTOMATIC"); break; case G_CONCAT_TYPE_MANUAL: - sbuf_printf(sb, "MANUAL"); + sbuf_cat(sb, "MANUAL"); break; default: - sbuf_printf(sb, "UNKNOWN"); + sbuf_cat(sb, "UNKNOWN"); break; } - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); sbuf_printf(sb, "%sTotal=%u, Online=%u\n", indent, sc->sc_ndisks, g_concat_nvalid(sc)); sbuf_printf(sb, "%s", indent); if (sc->sc_provider != NULL && sc->sc_provider->error == 0) - sbuf_printf(sb, "UP"); + sbuf_cat(sb, "UP"); else - sbuf_printf(sb, "DOWN"); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "DOWN"); + sbuf_cat(sb, "\n"); } } diff --git a/sys/geom/eli/g_eli.c b/sys/geom/eli/g_eli.c index ef390f1612a3..938d6a00fd52 100644 --- a/sys/geom/eli/g_eli.c +++ b/sys/geom/eli/g_eli.c @@ -1328,17 +1328,17 @@ g_eli_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, (uintmax_t)sc->sc_ekeys_allocated); sbuf_printf(sb, "%s", indent); if (sc->sc_flags == 0) - sbuf_printf(sb, "NONE"); + sbuf_cat(sb, "NONE"); else { int first = 1; #define ADD_FLAG(flag, name) do { \ if (sc->sc_flags & (flag)) { \ if (!first) \ - sbuf_printf(sb, ", "); \ + sbuf_cat(sb, ", "); \ else \ first = 0; \ - sbuf_printf(sb, name); \ + sbuf_cat(sb, name); \ } \ } while (0) ADD_FLAG(G_ELI_FLAG_SUSPEND, "SUSPEND"); @@ -1358,7 +1358,7 @@ g_eli_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, ADD_FLAG(G_ELI_FLAG_AUTORESIZE, "AUTORESIZE"); #undef ADD_FLAG } - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); if (!(sc->sc_flags & G_ELI_FLAG_ONETIME)) { sbuf_printf(sb, "%s%u\n", indent, @@ -1368,16 +1368,16 @@ g_eli_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sbuf_printf(sb, "%s", indent); switch (sc->sc_crypto) { case G_ELI_CRYPTO_HW: - sbuf_printf(sb, "hardware"); + sbuf_cat(sb, "hardware"); break; case G_ELI_CRYPTO_SW: - sbuf_printf(sb, "software"); + sbuf_cat(sb, "software"); break; default: - sbuf_printf(sb, "UNKNOWN"); + sbuf_cat(sb, "UNKNOWN"); break; } - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); if (sc->sc_flags & G_ELI_FLAG_AUTH) { sbuf_printf(sb, "%s%s\n", diff --git a/sys/geom/eli/g_eli.h b/sys/geom/eli/g_eli.h index 6c8c22a2a97d..fbf81ceabcce 100644 --- a/sys/geom/eli/g_eli.h +++ b/sys/geom/eli/g_eli.h @@ -721,12 +721,12 @@ struct hmac_ctx { SHA512_CTX outerctx; }; -void g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const char hkey[], +void g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const char *hkey, size_t hkeylen); void g_eli_crypto_hmac_update(struct hmac_ctx *ctx, const uint8_t *data, size_t datasize); void g_eli_crypto_hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize); -void g_eli_crypto_hmac(const char hkey[], size_t hkeysize, +void g_eli_crypto_hmac(const char *hkey, size_t hkeysize, const uint8_t *data, size_t datasize, uint8_t *md, size_t mdsize); void g_eli_key_fill(struct g_eli_softc *sc, struct g_eli_key *key, diff --git a/sys/geom/eli/g_eli_hmac.c b/sys/geom/eli/g_eli_hmac.c index 7d5a83820103..447a8937ca92 100644 --- a/sys/geom/eli/g_eli_hmac.c +++ b/sys/geom/eli/g_eli_hmac.c @@ -46,7 +46,7 @@ __FBSDID("$FreeBSD$"); #include void -g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const char hkey[], +g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const char *hkey, size_t hkeylen) { u_char k_ipad[128], k_opad[128], key[128]; @@ -96,11 +96,11 @@ g_eli_crypto_hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize) /* Complete inner hash */ SHA512_Final(digest, &ctx->innerctx); - + /* Complete outer hash */ SHA512_Update(&ctx->outerctx, digest, sizeof(digest)); SHA512_Final(digest, &ctx->outerctx); - + explicit_bzero(ctx, sizeof(*ctx)); /* mdsize == 0 means "Give me the whole hash!" */ if (mdsize == 0) @@ -110,7 +110,7 @@ g_eli_crypto_hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize) } void -g_eli_crypto_hmac(const char hkey[], size_t hkeysize, const uint8_t *data, +g_eli_crypto_hmac(const char *hkey, size_t hkeysize, const uint8_t *data, size_t datasize, uint8_t *md, size_t mdsize) { struct hmac_ctx ctx; diff --git a/sys/geom/eli/pkcs5v2.c b/sys/geom/eli/pkcs5v2.c index defe91b45500..c9c3984a3838 100644 --- a/sys/geom/eli/pkcs5v2.c +++ b/sys/geom/eli/pkcs5v2.c @@ -52,7 +52,7 @@ xor(uint8_t *dst, const uint8_t *src, size_t size) void pkcs5v2_genkey(uint8_t *key, unsigned keylen, const uint8_t *salt, - size_t saltsize, const char passphrase[], u_int iterations) + size_t saltsize, const char *passphrase, u_int iterations) { uint8_t md[SHA512_MDLEN], saltcount[saltsize + sizeof(uint32_t)]; uint8_t *counter, *keyp; diff --git a/sys/geom/eli/pkcs5v2.h b/sys/geom/eli/pkcs5v2.h index d271c3214536..da812e98c961 100644 --- a/sys/geom/eli/pkcs5v2.h +++ b/sys/geom/eli/pkcs5v2.h @@ -31,7 +31,7 @@ #ifndef _PKCS5V2_H_ #define _PKCS5V2_H_ void pkcs5v2_genkey(uint8_t *key, unsigned keylen, const uint8_t *salt, - size_t saltsize, const char passphrase[], u_int iterations); + size_t saltsize, const char *passphrase, u_int iterations); #ifndef _KERNEL int pkcs5v2_calculate(int usecs); #endif diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c index f9499a41e89a..b13f007553ef 100644 --- a/sys/geom/geom_disk.c +++ b/sys/geom/geom_disk.c @@ -599,15 +599,15 @@ g_disk_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g */ sbuf_printf(sb, "%s", indent); if (dp->d_rotation_rate == DISK_RR_UNKNOWN) /* Old drives */ - sbuf_printf(sb, "unknown"); /* don't report RPM. */ + sbuf_cat(sb, "unknown"); /* don't report RPM. */ else if (dp->d_rotation_rate == DISK_RR_NON_ROTATING) - sbuf_printf(sb, "0"); + sbuf_cat(sb, "0"); else if ((dp->d_rotation_rate >= DISK_RR_MIN) && (dp->d_rotation_rate <= DISK_RR_MAX)) sbuf_printf(sb, "%u", dp->d_rotation_rate); else - sbuf_printf(sb, "invalid"); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "invalid"); + sbuf_cat(sb, "\n"); if (dp->d_getattr != NULL) { buf = g_malloc(DISK_IDENT_SIZE, M_WAITOK); bp = g_alloc_bio(); @@ -617,35 +617,34 @@ g_disk_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g bp->bio_data = buf; res = dp->d_getattr(bp); sbuf_printf(sb, "%s", indent); - g_conf_printf_escaped(sb, "%s", - res == 0 ? buf: dp->d_ident); - sbuf_printf(sb, "\n"); + g_conf_cat_escaped(sb, res == 0 ? buf : dp->d_ident); + sbuf_cat(sb, "\n"); bp->bio_attribute = "GEOM::lunid"; bp->bio_length = DISK_IDENT_SIZE; bp->bio_data = buf; if (dp->d_getattr(bp) == 0) { sbuf_printf(sb, "%s", indent); - g_conf_printf_escaped(sb, "%s", buf); - sbuf_printf(sb, "\n"); + g_conf_cat_escaped(sb, buf); + sbuf_cat(sb, "\n"); } bp->bio_attribute = "GEOM::lunname"; bp->bio_length = DISK_IDENT_SIZE; bp->bio_data = buf; if (dp->d_getattr(bp) == 0) { sbuf_printf(sb, "%s", indent); - g_conf_printf_escaped(sb, "%s", buf); - sbuf_printf(sb, "\n"); + g_conf_cat_escaped(sb, buf); + sbuf_cat(sb, "\n"); } g_destroy_bio(bp); g_free(buf); } else { sbuf_printf(sb, "%s", indent); - g_conf_printf_escaped(sb, "%s", dp->d_ident); - sbuf_printf(sb, "\n"); + g_conf_cat_escaped(sb, dp->d_ident); + sbuf_cat(sb, "\n"); } sbuf_printf(sb, "%s", indent); - g_conf_printf_escaped(sb, "%s", dp->d_descr); - sbuf_printf(sb, "\n"); + g_conf_cat_escaped(sb, dp->d_descr); + sbuf_cat(sb, "\n"); } } diff --git a/sys/geom/geom_dump.c b/sys/geom/geom_dump.c index 0a4551c9fbfc..21a6e14b4960 100644 --- a/sys/geom/geom_dump.c +++ b/sys/geom/geom_dump.c @@ -105,10 +105,10 @@ g_confdot(void *p, int flag ) KASSERT(flag != EV_CANCEL, ("g_confdot was cancelled")); sb = p; g_topology_assert(); - sbuf_printf(sb, "digraph geom {\n"); + sbuf_cat(sb, "digraph geom {\n"); LIST_FOREACH(mp, &g_classes, class) g_confdot_class(sb, mp); - sbuf_printf(sb, "}\n"); + sbuf_cat(sb, "}\n"); sbuf_finish(sb); } @@ -125,7 +125,7 @@ g_conftxt_geom(struct sbuf *sb, struct g_geom *gp, int level) pp->name, (uintmax_t)pp->mediasize, pp->sectorsize); if (gp->dumpconf != NULL) gp->dumpconf(sb, NULL, gp, NULL, pp); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); LIST_FOREACH(cp, &pp->consumers, consumers) g_conftxt_geom(sb, cp->geom, level + 1); } @@ -156,21 +156,12 @@ g_conftxt(void *p, int flag) sbuf_finish(sb); } - void -g_conf_printf_escaped(struct sbuf *sb, const char *fmt, ...) +g_conf_cat_escaped(struct sbuf *sb, const char *buf) { - struct sbuf *s; const u_char *c; - va_list ap; - s = sbuf_new_auto(); - va_start(ap, fmt); - sbuf_vprintf(s, fmt, ap); - va_end(ap); - sbuf_finish(s); - - for (c = sbuf_data(s); *c != '\0'; c++) { + for (c = buf; *c != '\0'; c++) { if (*c == '&' || *c == '<' || *c == '>' || *c == '\'' || *c == '"' || *c > 0x7e) sbuf_printf(sb, "&#x%X;", *c); @@ -179,6 +170,21 @@ g_conf_printf_escaped(struct sbuf *sb, const char *fmt, ...) else sbuf_putc(sb, '?'); } +} + +void +g_conf_printf_escaped(struct sbuf *sb, const char *fmt, ...) +{ + struct sbuf *s; + va_list ap; + + s = sbuf_new_auto(); + va_start(ap, fmt); + sbuf_vprintf(s, fmt, ap); + va_end(ap); + sbuf_finish(s); + + g_conf_cat_escaped(sb, sbuf_data(s)); sbuf_delete(s); } @@ -195,11 +201,11 @@ g_conf_consumer(struct sbuf *sb, struct g_consumer *cp) if (cp->geom->flags & G_GEOM_WITHER) ; else if (cp->geom->dumpconf != NULL) { - sbuf_printf(sb, "\t \n"); + sbuf_cat(sb, "\t \n"); cp->geom->dumpconf(sb, "\t ", cp->geom, cp, NULL); - sbuf_printf(sb, "\t \n"); + sbuf_cat(sb, "\t \n"); } - sbuf_printf(sb, "\t\n"); + sbuf_cat(sb, "\t\n"); } static void @@ -210,24 +216,24 @@ g_conf_provider(struct sbuf *sb, struct g_provider *pp) sbuf_printf(sb, "\t \n", pp->geom); sbuf_printf(sb, "\t r%dw%de%d\n", pp->acr, pp->acw, pp->ace); - sbuf_printf(sb, "\t "); - g_conf_printf_escaped(sb, "%s", pp->name); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\t "); + g_conf_cat_escaped(sb, pp->name); + sbuf_cat(sb, "\n"); sbuf_printf(sb, "\t %jd\n", (intmax_t)pp->mediasize); sbuf_printf(sb, "\t %u\n", pp->sectorsize); sbuf_printf(sb, "\t %ju\n", (uintmax_t)pp->stripesize); sbuf_printf(sb, "\t %ju\n", (uintmax_t)pp->stripeoffset); if (pp->flags & G_PF_WITHER) - sbuf_printf(sb, "\t \n"); + sbuf_cat(sb, "\t \n"); else if (pp->geom->flags & G_GEOM_WITHER) ; else if (pp->geom->dumpconf != NULL) { - sbuf_printf(sb, "\t \n"); + sbuf_cat(sb, "\t \n"); pp->geom->dumpconf(sb, "\t ", pp->geom, NULL, pp); - sbuf_printf(sb, "\t \n"); + sbuf_cat(sb, "\t \n"); } - sbuf_printf(sb, "\t\n"); + sbuf_cat(sb, "\t\n"); } @@ -240,16 +246,16 @@ g_conf_geom(struct sbuf *sb, struct g_geom *gp, struct g_provider *pp, struct g_ sbuf_printf(sb, " \n", gp); sbuf_printf(sb, " \n", gp->class); - sbuf_printf(sb, " "); - g_conf_printf_escaped(sb, "%s", gp->name); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, " "); + g_conf_cat_escaped(sb, gp->name); + sbuf_cat(sb, "\n"); sbuf_printf(sb, " %d\n", gp->rank); if (gp->flags & G_GEOM_WITHER) - sbuf_printf(sb, " \n"); + sbuf_cat(sb, " \n"); else if (gp->dumpconf != NULL) { - sbuf_printf(sb, " \n"); + sbuf_cat(sb, " \n"); gp->dumpconf(sb, "\t", gp, NULL, NULL); - sbuf_printf(sb, " \n"); + sbuf_cat(sb, " \n"); } LIST_FOREACH(cp2, &gp->consumer, consumer) { if (cp != NULL && cp != cp2) @@ -263,11 +269,11 @@ g_conf_geom(struct sbuf *sb, struct g_geom *gp, struct g_provider *pp, struct g_ g_conf_provider(sb, pp2); } LIST_FOREACH(gap, &gp->aliases, ga_next) { - sbuf_printf(sb, " \n"); - g_conf_printf_escaped(sb, "%s", gap->ga_alias); - sbuf_printf(sb, " \n"); + sbuf_cat(sb, " \n"); + g_conf_cat_escaped(sb, gap->ga_alias); + sbuf_cat(sb, " \n"); } - sbuf_printf(sb, " \n"); + sbuf_cat(sb, " \n"); } static void @@ -276,15 +282,15 @@ g_conf_class(struct sbuf *sb, struct g_class *mp, struct g_geom *gp, struct g_pr struct g_geom *gp2; sbuf_printf(sb, " \n", mp); - sbuf_printf(sb, " "); - g_conf_printf_escaped(sb, "%s", mp->name); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, " "); + g_conf_cat_escaped(sb, mp->name); + sbuf_cat(sb, "\n"); LIST_FOREACH(gp2, &mp->geom, geom) { if (gp != NULL && gp != gp2) continue; g_conf_geom(sb, gp2, pp, cp); } - sbuf_printf(sb, " \n"); + sbuf_cat(sb, " \n"); } void @@ -293,13 +299,13 @@ g_conf_specific(struct sbuf *sb, struct g_class *mp, struct g_geom *gp, struct g struct g_class *mp2; g_topology_assert(); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); LIST_FOREACH(mp2, &g_classes, class) { if (mp != NULL && mp != mp2) continue; g_conf_class(sb, mp2, gp, pp, cp); } - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); sbuf_finish(sb); } diff --git a/sys/geom/geom_int.h b/sys/geom/geom_int.h index e04253cccb8e..1064a31da531 100644 --- a/sys/geom/geom_int.h +++ b/sys/geom/geom_int.h @@ -59,6 +59,7 @@ extern int g_debugflags; /* geom_dump.c */ void g_confxml(void *, int flag); void g_conf_specific(struct sbuf *sb, struct g_class *mp, struct g_geom *gp, struct g_provider *pp, struct g_consumer *cp); +void g_conf_cat_escaped(struct sbuf *sb, const char *buf); void g_conf_printf_escaped(struct sbuf *sb, const char *fmt, ...); void g_confdot(void *, int flag); void g_conftxt(void *, int flag); diff --git a/sys/geom/geom_kern.c b/sys/geom/geom_kern.c index 303ca75af348..0678a8ac4be6 100644 --- a/sys/geom/geom_kern.c +++ b/sys/geom/geom_kern.c @@ -157,42 +157,51 @@ g_init(void) } static int -sysctl_kern_geom_conftxt(SYSCTL_HANDLER_ARGS) +sysctl_kern_geom_confany(struct sysctl_req *req, g_event_t *func, size_t *hint) { - int error; + size_t len = 0; + int error = 0; struct sbuf *sb; - sb = sbuf_new_auto(); - g_waitfor_event(g_conftxt, sb, M_WAITOK, NULL); - error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1); + if (req->oldptr == NULL) { + sb = sbuf_new(NULL, NULL, PAGE_SIZE, SBUF_FIXEDLEN | + SBUF_INCLUDENUL); + sbuf_set_drain(sb, sbuf_count_drain, &len); + g_waitfor_event(func, sb, M_WAITOK, NULL); + req->oldidx = *hint = len; + } else { + sb = sbuf_new(NULL, NULL, *hint, SBUF_AUTOEXTEND | + SBUF_INCLUDENUL); + g_waitfor_event(func, sb, M_WAITOK, NULL); + *hint = sbuf_len(sb); + error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb)); + } sbuf_delete(sb); return error; } + +static int +sysctl_kern_geom_conftxt(SYSCTL_HANDLER_ARGS) +{ + static size_t hint = PAGE_SIZE; + + return (sysctl_kern_geom_confany(req, g_conftxt, &hint)); +} static int sysctl_kern_geom_confdot(SYSCTL_HANDLER_ARGS) { - int error; - struct sbuf *sb; + static size_t hint = PAGE_SIZE; - sb = sbuf_new_auto(); - g_waitfor_event(g_confdot, sb, M_WAITOK, NULL); - error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1); - sbuf_delete(sb); - return error; + return (sysctl_kern_geom_confany(req, g_confdot, &hint)); } - + static int sysctl_kern_geom_confxml(SYSCTL_HANDLER_ARGS) { - int error; - struct sbuf *sb; + static size_t hint = PAGE_SIZE; - sb = sbuf_new_auto(); - g_waitfor_event(g_confxml, sb, M_WAITOK, NULL); - error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1); - sbuf_delete(sb); - return error; + return (sysctl_kern_geom_confany(req, g_confxml, &hint)); } SYSCTL_NODE(_kern, OID_AUTO, geom, CTLFLAG_RW, 0, "GEOMetry management"); diff --git a/sys/geom/journal/g_journal.c b/sys/geom/journal/g_journal.c index bdfad253b67c..8ed8b8d69965 100644 --- a/sys/geom/journal/g_journal.c +++ b/sys/geom/journal/g_journal.c @@ -2623,15 +2623,15 @@ g_journal_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sbuf_printf(sb, "%s", indent); if (cp == sc->sc_dconsumer) { - sbuf_printf(sb, "Data"); + sbuf_cat(sb, "Data"); first = 0; } if (cp == sc->sc_jconsumer) { if (!first) - sbuf_printf(sb, ","); - sbuf_printf(sb, "Journal"); + sbuf_cat(sb, ","); + sbuf_cat(sb, "Journal"); } - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); if (cp == sc->sc_jconsumer) { sbuf_printf(sb, "%jd\n", (intmax_t)sc->sc_jstart); diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index 5ccb8362e19a..5cc1b4a0c365 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -3373,12 +3373,12 @@ g_mirror_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, if (disk->d_state == G_MIRROR_DISK_STATE_SYNCHRONIZING) { sbuf_printf(sb, "%s", indent); if (disk->d_sync.ds_offset == 0) - sbuf_printf(sb, "0%%"); + sbuf_cat(sb, "0%"); else sbuf_printf(sb, "%u%%", (u_int)((disk->d_sync.ds_offset * 100) / sc->sc_mediasize)); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); if (disk->d_sync.ds_offset > 0) sbuf_printf(sb, "%s%jd" "\n", indent, @@ -3390,17 +3390,17 @@ g_mirror_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, disk->d_genid); sbuf_printf(sb, "%s", indent); if (disk->d_flags == 0) - sbuf_printf(sb, "NONE"); + sbuf_cat(sb, "NONE"); else { int first = 1; #define ADD_FLAG(flag, name) do { \ if ((disk->d_flags & (flag)) != 0) { \ if (!first) \ - sbuf_printf(sb, ", "); \ + sbuf_cat(sb, ", "); \ else \ first = 0; \ - sbuf_printf(sb, name); \ + sbuf_cat(sb, name); \ } \ } while (0) ADD_FLAG(G_MIRROR_DISK_FLAG_DIRTY, "DIRTY"); @@ -3412,7 +3412,7 @@ g_mirror_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, ADD_FLAG(G_MIRROR_DISK_FLAG_BROKEN, "BROKEN"); #undef ADD_FLAG } - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); sbuf_printf(sb, "%s%u\n", indent, disk->d_priority); sbuf_printf(sb, "%s%s\n", indent, @@ -3421,39 +3421,39 @@ g_mirror_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sbuf_printf(sb, "%s", indent); switch (sc->sc_type) { case G_MIRROR_TYPE_AUTOMATIC: - sbuf_printf(sb, "AUTOMATIC"); + sbuf_cat(sb, "AUTOMATIC"); break; case G_MIRROR_TYPE_MANUAL: - sbuf_printf(sb, "MANUAL"); + sbuf_cat(sb, "MANUAL"); break; default: - sbuf_printf(sb, "UNKNOWN"); + sbuf_cat(sb, "UNKNOWN"); break; } - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); sbuf_printf(sb, "%s%u\n", indent, (u_int)sc->sc_id); sbuf_printf(sb, "%s%u\n", indent, sc->sc_syncid); sbuf_printf(sb, "%s%u\n", indent, sc->sc_genid); sbuf_printf(sb, "%s", indent); if (sc->sc_flags == 0) - sbuf_printf(sb, "NONE"); + sbuf_cat(sb, "NONE"); else { int first = 1; #define ADD_FLAG(flag, name) do { \ if ((sc->sc_flags & (flag)) != 0) { \ if (!first) \ - sbuf_printf(sb, ", "); \ + sbuf_cat(sb, ", "); \ else \ first = 0; \ - sbuf_printf(sb, name); \ + sbuf_cat(sb, name); \ } \ } while (0) ADD_FLAG(G_MIRROR_DEVICE_FLAG_NOFAILSYNC, "NOFAILSYNC"); ADD_FLAG(G_MIRROR_DEVICE_FLAG_NOAUTOSYNC, "NOAUTOSYNC"); #undef ADD_FLAG } - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); sbuf_printf(sb, "%s%u\n", indent, (u_int)sc->sc_slice); sbuf_printf(sb, "%s%s\n", indent, @@ -3468,7 +3468,7 @@ g_mirror_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sbuf_printf(sb, "%s", "COMPLETE"); else sbuf_printf(sb, "%s", "DEGRADED"); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); } } diff --git a/sys/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c index ba2a2d413b23..7dc42bc11561 100644 --- a/sys/geom/multipath/g_multipath.c +++ b/sys/geom/multipath/g_multipath.c @@ -1450,7 +1450,7 @@ g_multipath_ctl_getactive(struct gctl_req *req, struct g_class *mp) } else if (sc->sc_active && sc->sc_active->provider) { sbuf_printf(sb, "%s\n", sc->sc_active->provider->name); } else { - sbuf_printf(sb, "none\n"); + sbuf_cat(sb, "none\n"); } sbuf_finish(sb); gctl_set_param_err(req, "output", sbuf_data(sb), sbuf_len(sb) + 1); diff --git a/sys/geom/part/g_part_apm.c b/sys/geom/part/g_part_apm.c index 250983ef7fe3..92019c7e4f16 100644 --- a/sys/geom/part/g_part_apm.c +++ b/sys/geom/part/g_part_apm.c @@ -310,13 +310,13 @@ g_part_apm_dumpconf(struct g_part_table *table, struct g_part_entry *baseentry, strncpy(u.name, entry->ent.ent_name, APM_ENT_NAMELEN); u.name[APM_ENT_NAMELEN] = '\0'; sbuf_printf(sb, "%s\n"); + g_conf_cat_escaped(sb, u.name); + sbuf_cat(sb, "\n"); strncpy(u.type, entry->ent.ent_type, APM_ENT_TYPELEN); u.type[APM_ENT_TYPELEN] = '\0'; sbuf_printf(sb, "%s", indent); - g_conf_printf_escaped(sb, "%s", u.type); - sbuf_printf(sb, "\n"); + g_conf_cat_escaped(sb, u.type); + sbuf_cat(sb, "\n"); } else { /* confxml: scheme information */ } diff --git a/sys/geom/part/g_part_bsd64.c b/sys/geom/part/g_part_bsd64.c index ff5d7ef6d054..4f73957ba1b3 100644 --- a/sys/geom/part/g_part_bsd64.c +++ b/sys/geom/part/g_part_bsd64.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -385,11 +386,11 @@ g_part_bsd64_dumpconf(struct g_part_table *basetable, if (!EQUUID(&bsd64_uuid_unused, &entry->type_uuid)) { sbuf_printf(sb, "%s", indent); sbuf_printf_uuid(sb, &entry->type_uuid); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); } sbuf_printf(sb, "%s", indent); sbuf_printf_uuid(sb, &entry->stor_uuid); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); } else { /* confxml: scheme information */ table = (struct g_part_bsd64_table *)basetable; @@ -400,12 +401,12 @@ g_part_bsd64_dumpconf(struct g_part_table *basetable, indent, (uintmax_t)table->d_abase); sbuf_printf(sb, "%s", indent); sbuf_printf_uuid(sb, &table->d_stor_uuid); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); sbuf_printf(sb, "%s\n"); + g_conf_cat_escaped(sb, buf); + sbuf_cat(sb, "\n"); } } diff --git a/sys/geom/part/g_part_gpt.c b/sys/geom/part/g_part_gpt.c index e1bea703a154..f69cd84efab4 100644 --- a/sys/geom/part/g_part_gpt.c +++ b/sys/geom/part/g_part_gpt.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -712,14 +713,14 @@ g_part_gpt_dumpconf(struct g_part_table *table, struct g_part_entry *baseentry, entry = (struct g_part_gpt_entry *)baseentry; if (indent == NULL) { /* conftxt: libdisk compatibility */ - sbuf_printf(sb, " xs GPT xt "); + sbuf_cat(sb, " xs GPT xt "); sbuf_printf_uuid(sb, &entry->ent.ent_type); } else if (entry != NULL) { /* confxml: partition entry information */ sbuf_printf(sb, "%s\n"); + sbuf_cat(sb, "\n"); if (entry->ent.ent_attr & GPT_ENT_ATTR_BOOTME) sbuf_printf(sb, "%sbootme\n", indent); if (entry->ent.ent_attr & GPT_ENT_ATTR_BOOTONCE) { @@ -732,16 +733,16 @@ g_part_gpt_dumpconf(struct g_part_table *table, struct g_part_entry *baseentry, } sbuf_printf(sb, "%s", indent); sbuf_printf_uuid(sb, &entry->ent.ent_type); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); sbuf_printf(sb, "%s", indent); sbuf_printf_uuid(sb, &entry->ent.ent_uuid); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); sbuf_printf(sb, "%s", indent); sbuf_printf(sb, "HD(%d,GPT,", entry->base.gpe_index); sbuf_printf_uuid(sb, &entry->ent.ent_uuid); sbuf_printf(sb, ",%#jx,%#jx)", (intmax_t)entry->base.gpe_start, (intmax_t)(entry->base.gpe_end - entry->base.gpe_start + 1)); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); } else { /* confxml: scheme information */ } diff --git a/sys/geom/part/g_part_mbr.c b/sys/geom/part/g_part_mbr.c index a442e25c94d0..013b2a934ccc 100644 --- a/sys/geom/part/g_part_mbr.c +++ b/sys/geom/part/g_part_mbr.c @@ -330,7 +330,7 @@ g_part_mbr_dumpconf(struct g_part_table *basetable, struct g_part_entry *baseent sbuf_printf(sb, "%sHD(%d,MBR,%#08x,%#jx,%#jx)", indent, entry->base.gpe_index, dsn, (intmax_t)entry->base.gpe_start, (intmax_t)(entry->base.gpe_end - entry->base.gpe_start + 1)); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); } else { /* confxml: scheme information */ } diff --git a/sys/geom/raid/g_raid.c b/sys/geom/raid/g_raid.c index bc8cd153456a..85e237f95b66 100644 --- a/sys/geom/raid/g_raid.c +++ b/sys/geom/raid/g_raid.c @@ -2372,7 +2372,7 @@ g_raid_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sbuf_printf(sb, "%s ", g_raid_get_diskname(sd->sd_disk)); } else { - sbuf_printf(sb, "NONE "); + sbuf_cat(sb, "NONE "); } sbuf_printf(sb, "(%s", g_raid_subdisk_state2str(sd->sd_state)); @@ -2382,11 +2382,11 @@ g_raid_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, (int)(sd->sd_rebuild_pos * 100 / sd->sd_size)); } - sbuf_printf(sb, ")"); + sbuf_cat(sb, ")"); if (i + 1 < vol->v_disks_count) - sbuf_printf(sb, ", "); + sbuf_cat(sb, ", "); } - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); sx_xunlock(&sc->sc_lock); g_topology_lock(); } else if (cp != NULL) { @@ -2398,7 +2398,7 @@ g_raid_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sbuf_printf(sb, "%s%s", indent, g_raid_disk_state2str(disk->d_state)); if (!TAILQ_EMPTY(&disk->d_subdisks)) { - sbuf_printf(sb, " ("); + sbuf_cat(sb, " ("); TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) { sbuf_printf(sb, "%s", g_raid_subdisk_state2str(sd->sd_state)); @@ -2409,11 +2409,11 @@ g_raid_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sd->sd_size)); } if (TAILQ_NEXT(sd, sd_next)) - sbuf_printf(sb, ", "); + sbuf_cat(sb, ", "); } - sbuf_printf(sb, ")"); + sbuf_cat(sb, ")"); } - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); sbuf_printf(sb, "%s", indent); TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) { sbuf_printf(sb, "r%d(%s):%d@%ju", @@ -2421,9 +2421,9 @@ g_raid_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sd->sd_volume->v_name, sd->sd_pos, (uintmax_t)sd->sd_offset); if (TAILQ_NEXT(sd, sd_next)) - sbuf_printf(sb, ", "); + sbuf_cat(sb, ", "); } - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); sbuf_printf(sb, "%s%d\n", indent, disk->d_read_errs); sx_xunlock(&sc->sc_lock); diff --git a/sys/geom/raid/md_ddf.c b/sys/geom/raid/md_ddf.c index 3ac13bded073..a731da89d8ea 100644 --- a/sys/geom/raid/md_ddf.c +++ b/sys/geom/raid/md_ddf.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include diff --git a/sys/geom/raid3/g_raid3.c b/sys/geom/raid3/g_raid3.c index 682272345244..02ec5b45c694 100644 --- a/sys/geom/raid3/g_raid3.c +++ b/sys/geom/raid3/g_raid3.c @@ -3424,22 +3424,22 @@ g_raid3_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sx_xlock(&sc->sc_lock); sbuf_printf(sb, "%s", indent); if (disk->d_no == sc->sc_ndisks - 1) - sbuf_printf(sb, "PARITY"); + sbuf_cat(sb, "PARITY"); else - sbuf_printf(sb, "DATA"); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "DATA"); + sbuf_cat(sb, "\n"); sbuf_printf(sb, "%s%u\n", indent, (u_int)disk->d_no); if (disk->d_state == G_RAID3_DISK_STATE_SYNCHRONIZING) { sbuf_printf(sb, "%s", indent); if (disk->d_sync.ds_offset == 0) - sbuf_printf(sb, "0%%"); + sbuf_cat(sb, "0%"); else { sbuf_printf(sb, "%u%%", (u_int)((disk->d_sync.ds_offset * 100) / (sc->sc_mediasize / (sc->sc_ndisks - 1)))); } - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); if (disk->d_sync.ds_offset > 0) { sbuf_printf(sb, "%s%jd" "\n", indent, @@ -3451,17 +3451,17 @@ g_raid3_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sbuf_printf(sb, "%s%u\n", indent, disk->d_genid); sbuf_printf(sb, "%s", indent); if (disk->d_flags == 0) - sbuf_printf(sb, "NONE"); + sbuf_cat(sb, "NONE"); else { int first = 1; #define ADD_FLAG(flag, name) do { \ if ((disk->d_flags & (flag)) != 0) { \ if (!first) \ - sbuf_printf(sb, ", "); \ + sbuf_cat(sb, ", "); \ else \ first = 0; \ - sbuf_printf(sb, name); \ + sbuf_cat(sb, name); \ } \ } while (0) ADD_FLAG(G_RAID3_DISK_FLAG_DIRTY, "DIRTY"); @@ -3472,7 +3472,7 @@ g_raid3_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, ADD_FLAG(G_RAID3_DISK_FLAG_BROKEN, "BROKEN"); #undef ADD_FLAG } - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); sbuf_printf(sb, "%s%s\n", indent, g_raid3_disk_state2str(disk->d_state)); sx_xunlock(&sc->sc_lock); @@ -3505,17 +3505,17 @@ g_raid3_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sbuf_printf(sb, "%s%u\n", indent, sc->sc_genid); sbuf_printf(sb, "%s", indent); if (sc->sc_flags == 0) - sbuf_printf(sb, "NONE"); + sbuf_cat(sb, "NONE"); else { int first = 1; #define ADD_FLAG(flag, name) do { \ if ((sc->sc_flags & (flag)) != 0) { \ if (!first) \ - sbuf_printf(sb, ", "); \ + sbuf_cat(sb, ", "); \ else \ first = 0; \ - sbuf_printf(sb, name); \ + sbuf_cat(sb, name); \ } \ } while (0) ADD_FLAG(G_RAID3_DEVICE_FLAG_NOFAILSYNC, "NOFAILSYNC"); @@ -3525,7 +3525,7 @@ g_raid3_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, ADD_FLAG(G_RAID3_DEVICE_FLAG_VERIFY, "VERIFY"); #undef ADD_FLAG } - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); sbuf_printf(sb, "%s%u\n", indent, sc->sc_ndisks); sbuf_printf(sb, "%s%s\n", indent, diff --git a/sys/geom/stripe/g_stripe.c b/sys/geom/stripe/g_stripe.c index 8dc32ee2c9f1..23873f778670 100644 --- a/sys/geom/stripe/g_stripe.c +++ b/sys/geom/stripe/g_stripe.c @@ -1249,24 +1249,24 @@ g_stripe_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sbuf_printf(sb, "%s", indent); switch (sc->sc_type) { case G_STRIPE_TYPE_AUTOMATIC: - sbuf_printf(sb, "AUTOMATIC"); + sbuf_cat(sb, "AUTOMATIC"); break; case G_STRIPE_TYPE_MANUAL: - sbuf_printf(sb, "MANUAL"); + sbuf_cat(sb, "MANUAL"); break; default: - sbuf_printf(sb, "UNKNOWN"); + sbuf_cat(sb, "UNKNOWN"); break; } - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "\n"); sbuf_printf(sb, "%sTotal=%u, Online=%u\n", indent, sc->sc_ndisks, g_stripe_nvalid(sc)); sbuf_printf(sb, "%s", indent); if (sc->sc_provider != NULL && sc->sc_provider->error == 0) - sbuf_printf(sb, "UP"); + sbuf_cat(sb, "UP"); else - sbuf_printf(sb, "DOWN"); - sbuf_printf(sb, "\n"); + sbuf_cat(sb, "DOWN"); + sbuf_cat(sb, "\n"); } } diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index e4286e078c48..e312549f3f15 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -318,7 +318,7 @@ static int pmap_enter_pde(pmap_t pmap, vm_offset_t va, pd_entry_t newpde, u_int flags, vm_page_t m); static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, vm_page_t mpte); -static int pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte); +static int pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte, bool promoted); static void pmap_invalidate_pde_page(pmap_t pmap, vm_offset_t va, pd_entry_t pde); static void pmap_fill_ptp(pt_entry_t *firstpte, pt_entry_t newpte); @@ -990,9 +990,14 @@ __CONCAT(PMTYPE, init)(void) mpte->pindex = i + KPTDI; mpte->phys_addr = KPTphys + ptoa(i); mpte->wire_count = 1; + + /* + * Collect the page table pages that were replaced by a 2/4MB + * page. They are filled with equivalent 4KB page mappings. + */ if (pseflag != 0 && KERNBASE <= i << PDRSHIFT && i << PDRSHIFT < KERNend && - pmap_insert_pt_page(kernel_pmap, mpte)) + pmap_insert_pt_page(kernel_pmap, mpte, true)) panic("pmap_init: pmap_insert_pt_page failed"); } PMAP_UNLOCK(kernel_pmap); @@ -1900,12 +1905,15 @@ pmap_add_delayed_free_list(vm_page_t m, struct spglist *free, * of idle page table pages. Each of a pmap's page table pages is responsible * for mapping a distinct range of virtual addresses. The pmap's collection is * ordered by this virtual address range. + * + * If "promoted" is false, then the page table page "mpte" must be zero filled. */ static __inline int -pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte) +pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte, bool promoted) { PMAP_LOCK_ASSERT(pmap, MA_OWNED); + mpte->valid = promoted ? VM_PAGE_BITS_ALL : 0; return (vm_radix_insert(&pmap->pm_root, mpte)); } @@ -2465,7 +2473,7 @@ free_pv_chunk(struct pv_chunk *pc) /* entire chunk is free, return it */ m = PHYS_TO_VM_PAGE(pmap_kextract((vm_offset_t)pc)); pmap_qremove((vm_offset_t)pc, 1); - vm_page_unwire(m, PQ_NONE); + vm_page_unwire_noq(m); vm_page_free(m); pmap_ptelist_free(&pv_vafree, (vm_offset_t)pc); } @@ -2823,7 +2831,7 @@ pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) * If the page table page is not leftover from an earlier promotion, * initialize it. */ - if ((oldpde & PG_PROMOTED) == 0) + if (mpte->valid == 0) pmap_fill_ptp(firstpte, newpte); KASSERT((*firstpte & PG_FRAME) == (newpte & PG_FRAME), @@ -2895,9 +2903,11 @@ pmap_remove_kernel_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) newpde = mptepa | PG_M | PG_A | PG_RW | PG_V; /* - * Initialize the page table page. + * If this page table page was unmapped by a promotion, then it + * contains valid mappings. Zero it to invalidate those mappings. */ - pagezero((void *)&KPTmap[i386_btop(trunc_4mpage(va))]); + if (mpte->valid != 0) + pagezero((void *)&KPTmap[i386_btop(trunc_4mpage(va))]); /* * Remove the mapping. @@ -2960,6 +2970,8 @@ pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, } else { mpte = pmap_remove_pt_page(pmap, sva); if (mpte != NULL) { + KASSERT(mpte->valid == VM_PAGE_BITS_ALL, + ("pmap_remove_pde: pte page not promoted")); pmap->pm_stats.resident_count--; KASSERT(mpte->wire_count == NPTEPG, ("pmap_remove_pde: pte page wire count error")); @@ -3533,7 +3545,7 @@ pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) ("pmap_promote_pde: page table page is out of range")); KASSERT(mpte->pindex == va >> PDRSHIFT, ("pmap_promote_pde: page table page's pindex is wrong")); - if (pmap_insert_pt_page(pmap, mpte)) { + if (pmap_insert_pt_page(pmap, mpte, true)) { pmap_pde_p_failures++; CTR2(KTR_PMAP, "pmap_promote_pde: failure for va %#x in pmap %p", va, @@ -3911,15 +3923,13 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t va, pd_entry_t newpde, u_int flags, } vm_page_free_pages_toq(&free, true); if (pmap == kernel_pmap) { + /* + * Both pmap_remove_pde() and pmap_remove_ptes() will + * leave the kernel page table page zero filled. + */ mt = PHYS_TO_VM_PAGE(*pde & PG_FRAME); - if (pmap_insert_pt_page(pmap, mt)) { - /* - * XXX Currently, this can't happen because - * we do not perform pmap_enter(psind == 1) - * on the kernel pmap. - */ + if (pmap_insert_pt_page(pmap, mt, false)) panic("pmap_enter_pde: trie insert failed"); - } } else KASSERT(*pde == 0, ("pmap_enter_pde: non-zero pde %p", pde)); @@ -4797,6 +4807,8 @@ __CONCAT(PMTYPE, remove_pages)(pmap_t pmap) } mpte = pmap_remove_pt_page(pmap, pv->pv_va); if (mpte != NULL) { + KASSERT(mpte->valid == VM_PAGE_BITS_ALL, + ("pmap_remove_pages: pte page not promoted")); pmap->pm_stats.resident_count--; KASSERT(mpte->wire_count == NPTEPG, ("pmap_remove_pages: pte page wire count error")); diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index 6581450a0a9a..b27e10e8a23b 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -116,13 +116,15 @@ void syscall(struct trapframe *frame); static int trap_pfault(struct trapframe *, int, vm_offset_t); static void trap_fatal(struct trapframe *, vm_offset_t); +#ifdef KDTRACE_HOOKS +static bool trap_user_dtrace(struct trapframe *, + int (**hook)(struct trapframe *)); +#endif void dblfault_handler(void); extern inthand_t IDTVEC(bpt), IDTVEC(dbg), IDTVEC(int0x80_syscall); extern uint64_t pg_nx; -#define MAX_TRAP_MSG 32 - struct trap_data { bool ei; const char *msg; @@ -322,11 +324,11 @@ trap(struct trapframe *frame) break; case T_BPTFLT: /* bpt instruction fault */ - enable_intr(); #ifdef KDTRACE_HOOKS - if (dtrace_pid_probe_ptr != NULL && - dtrace_pid_probe_ptr(frame) == 0) + if (trap_user_dtrace(frame, &dtrace_pid_probe_ptr)) return; +#else + enable_intr(); #endif signo = SIGTRAP; ucode = TRAP_BRKPT; @@ -504,9 +506,7 @@ trap(struct trapframe *frame) break; #ifdef KDTRACE_HOOKS case T_DTRACE_RET: - enable_intr(); - if (dtrace_return_probe_ptr != NULL) - dtrace_return_probe_ptr(frame); + (void)trap_user_dtrace(frame, &dtrace_return_probe_ptr); return; #endif } @@ -991,6 +991,25 @@ trap_fatal(frame, eva) panic("unknown/reserved trap"); } +#ifdef KDTRACE_HOOKS +/* + * Invoke a userspace DTrace hook. The hook pointer is cleared when no + * userspace probes are enabled, so we must synchronize with DTrace to ensure + * that a trapping thread is able to call the hook before it is cleared. + */ +static bool +trap_user_dtrace(struct trapframe *frame, int (**hookp)(struct trapframe *)) +{ + int (*hook)(struct trapframe *); + + hook = (int (*)(struct trapframe *))atomic_load_ptr(hookp); + enable_intr(); + if (hook != NULL) + return ((hook)(frame) == 0); + return (false); +} +#endif + /* * Double fault handler. Called when a fault occurs while writing * a frame for a trap/exception onto the stack. This usually occurs diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index c352a913d413..3811c2035680 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -1422,7 +1422,6 @@ static void __elfN(puthdr)(struct thread *, void *, size_t, int, size_t); static void __elfN(putnote)(struct note_info *, struct sbuf *); static size_t register_note(struct note_info_list *, int, outfunc_t, void *); static int sbuf_drain_core_output(void *, const char *, int); -static int sbuf_drain_count(void *arg, const char *data, int len); static void __elfN(note_fpregset)(void *, struct sbuf *, size_t *); static void __elfN(note_prpsinfo)(void *, struct sbuf *, size_t *); @@ -1552,19 +1551,6 @@ sbuf_drain_core_output(void *arg, const char *data, int len) return (len); } -/* - * Drain into a counter. - */ -static int -sbuf_drain_count(void *arg, const char *data __unused, int len) -{ - size_t *sizep; - - sizep = (size_t *)arg; - *sizep += len; - return (len); -} - int __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags) { @@ -2341,7 +2327,7 @@ note_procstat_files(void *arg, struct sbuf *sb, size_t *sizep) if (sb == NULL) { size = 0; sb = sbuf_new(NULL, NULL, 128, SBUF_FIXEDLEN); - sbuf_set_drain(sb, sbuf_drain_count, &size); + sbuf_set_drain(sb, sbuf_count_drain, &size); sbuf_bcat(sb, &structsize, sizeof(structsize)); PROC_LOCK(p); kern_proc_filedesc_out(p, sb, -1, filedesc_flags); @@ -2392,7 +2378,7 @@ note_procstat_vmmap(void *arg, struct sbuf *sb, size_t *sizep) if (sb == NULL) { size = 0; sb = sbuf_new(NULL, NULL, 128, SBUF_FIXEDLEN); - sbuf_set_drain(sb, sbuf_drain_count, &size); + sbuf_set_drain(sb, sbuf_count_drain, &size); sbuf_bcat(sb, &structsize, sizeof(structsize)); PROC_LOCK(p); kern_proc_vmmap_out(p, sb, -1, vmmap_flags); @@ -2520,7 +2506,7 @@ __elfN(note_procstat_auxv)(void *arg, struct sbuf *sb, size_t *sizep) if (sb == NULL) { size = 0; sb = sbuf_new(NULL, NULL, 128, SBUF_FIXEDLEN); - sbuf_set_drain(sb, sbuf_drain_count, &size); + sbuf_set_drain(sb, sbuf_count_drain, &size); sbuf_bcat(sb, &structsize, sizeof(structsize)); PHOLD(p); proc_getauxv(curthread, p, sb); diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index 47cdce455bc3..f4910e4728d2 100644 --- a/sys/kern/kern_clock.c +++ b/sys/kern/kern_clock.c @@ -644,6 +644,7 @@ statclock(int cnt, int usermode) struct proc *p; long rss; long *cp_time; + uint64_t runtime, new_switchtime; td = curthread; p = td->td_proc; @@ -699,6 +700,17 @@ statclock(int cnt, int usermode) "prio:%d", td->td_priority, "stathz:%d", (stathz)?stathz:hz); SDT_PROBE2(sched, , , tick, td, td->td_proc); thread_lock_flags(td, MTX_QUIET); + + /* + * Compute the amount of time during which the current + * thread was running, and add that to its total so far. + */ + new_switchtime = cpu_ticks(); + runtime = new_switchtime - PCPU_GET(switchtime); + td->td_runtime += runtime; + td->td_incruntime += runtime; + PCPU_SET(switchtime, new_switchtime); + for ( ; cnt > 0; cnt--) sched_clock(td); thread_unlock(td); diff --git a/sys/kern/kern_sendfile.c b/sys/kern/kern_sendfile.c index 50404ce57458..61edffa893eb 100644 --- a/sys/kern/kern_sendfile.c +++ b/sys/kern/kern_sendfile.c @@ -303,7 +303,7 @@ sendfile_iodone(void *arg, vm_page_t *pg, int count, int error) for (int i = 0; i < sfio->npages; i++) m = m_free(m); } else - (void )(so->so_proto->pr_usrreqs->pru_ready)(so, sfio->m, + (void)(so->so_proto->pr_usrreqs->pru_ready)(so, sfio->m, sfio->npages); SOCK_LOCK(so); diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 7d6340cba411..9e775037b6cc 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -368,6 +368,19 @@ wakeup_one(void *ident) kick_proc0(); } +void +wakeup_any(void *ident) +{ + int wakeup_swapper; + + sleepq_lock(ident); + wakeup_swapper = sleepq_signal(ident, SLEEPQ_SLEEP | SLEEPQ_UNFAIR, + 0, 0); + sleepq_release(ident); + if (wakeup_swapper) + kick_proc0(); +} + static void kdb_switch(void) { diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 78de171ccf85..33d42e0acfac 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1732,6 +1732,29 @@ sysctl_msec_to_sbintime(SYSCTL_HANDLER_ARGS) return (0); } +/* + * Convert seconds to a struct timeval. Intended for use with + * intervals and thus does not permit negative seconds. + */ +int +sysctl_sec_to_timeval(SYSCTL_HANDLER_ARGS) +{ + struct timeval *tv; + int error, secs; + + tv = arg1; + secs = tv->tv_sec; + + error = sysctl_handle_int(oidp, &secs, 0, req); + if (error || req->newptr == NULL) + return (error); + + if (secs < 0) + return (EINVAL); + tv->tv_sec = secs; + + return (0); +} /* * Transfer functions to/from kernel space. diff --git a/sys/kern/kern_uuid.c b/sys/kern/kern_uuid.c index 006558e9e50c..ea0877a0cde0 100644 --- a/sys/kern/kern_uuid.c +++ b/sys/kern/kern_uuid.c @@ -297,7 +297,7 @@ sbuf_printf_uuid(struct sbuf *sb, struct uuid *uuid) char buf[38]; snprintf_uuid(buf, sizeof(buf), uuid); - return (sbuf_printf(sb, "%s", buf)); + return (sbuf_cat(sb, buf)); } /* diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index 6ceb34d66b74..800c0d685bc7 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -615,10 +615,14 @@ parse_dynamic(elf_file_t ef) return (0); } +#define LS_PADDING 0x90909090 static int parse_dpcpu(elf_file_t ef) { int error, size; +#if defined(__i386__) + uint32_t pad; +#endif ef->pcpu_start = 0; ef->pcpu_stop = 0; @@ -631,6 +635,26 @@ parse_dpcpu(elf_file_t ef) /* Empty set? */ if (size < 1) return (0); +#if defined(__i386__) + /* In case we do find __start/stop_set_ symbols double-check. */ + if (size < 4) { + uprintf("Kernel module '%s' must be recompiled with " + "linker script\n", ef->lf.pathname); + return (ENOEXEC); + } + + /* Padding from linker-script correct? */ + pad = *(uint32_t *)((uintptr_t)ef->pcpu_stop - sizeof(pad)); + if (pad != LS_PADDING) { + uprintf("Kernel module '%s' must be recompiled with " + "linker script, invalid padding %#04x (%#04x)\n", + ef->lf.pathname, pad, LS_PADDING); + return (ENOEXEC); + } + /* If we only have valid padding, nothing to do. */ + if (size == 4) + return (0); +#endif /* * Allocate space in the primary pcpu area. Copy in our * initialization from the data section and then initialize @@ -656,6 +680,9 @@ static int parse_vnet(elf_file_t ef) { int error, size; +#if defined(__i386__) + uint32_t pad; +#endif ef->vnet_start = 0; ef->vnet_stop = 0; @@ -668,6 +695,26 @@ parse_vnet(elf_file_t ef) /* Empty set? */ if (size < 1) return (0); +#if defined(__i386__) + /* In case we do find __start/stop_set_ symbols double-check. */ + if (size < 4) { + uprintf("Kernel module '%s' must be recompiled with " + "linker script\n", ef->lf.pathname); + return (ENOEXEC); + } + + /* Padding from linker-script correct? */ + pad = *(uint32_t *)((uintptr_t)ef->vnet_stop - sizeof(pad)); + if (pad != LS_PADDING) { + uprintf("Kernel module '%s' must be recompiled with " + "linker script, invalid padding %#04x (%#04x)\n", + ef->lf.pathname, pad, LS_PADDING); + return (ENOEXEC); + } + /* If we only have valid padding, nothing to do. */ + if (size == 4) + return (0); +#endif /* * Allocate space in the primary vnet area. Copy in our * initialization from the data section and then initialize @@ -688,6 +735,7 @@ parse_vnet(elf_file_t ef) return (0); } #endif +#undef LS_PADDING static int link_elf_link_preload(linker_class_t cls, diff --git a/sys/kern/subr_compressor.c b/sys/kern/subr_compressor.c index 62c818439271..03dd295388ad 100644 --- a/sys/kern/subr_compressor.c +++ b/sys/kern/subr_compressor.c @@ -66,6 +66,7 @@ SET_DECLARE(compressors, struct compressor_methods); #ifdef GZIO +#include #include struct gz_stream { diff --git a/sys/kern/subr_sbuf.c b/sys/kern/subr_sbuf.c index deb83f5e035d..8fba9710debc 100644 --- a/sys/kern/subr_sbuf.c +++ b/sys/kern/subr_sbuf.c @@ -341,6 +341,21 @@ sbuf_setpos(struct sbuf *s, ssize_t pos) return (0); } +/* + * Drain into a counter. Counts amount of data without producing output. + * Useful for cases like sysctl, where user may first request only size. + * This allows to avoid pointless allocation/freeing of large buffers. + */ +int +sbuf_count_drain(void *arg, const char *data __unused, int len) +{ + size_t *sizep; + + sizep = (size_t *)arg; + *sizep += len; + return (len); +} + /* * Set up a drain function and argument on an sbuf to flush data to * when the sbuf buffer overflows. diff --git a/sys/kern/subr_sleepqueue.c b/sys/kern/subr_sleepqueue.c index 7f8a66eb8f5b..16e9bbfa3abc 100644 --- a/sys/kern/subr_sleepqueue.c +++ b/sys/kern/subr_sleepqueue.c @@ -123,7 +123,7 @@ CTASSERT(powerof2(SC_TABLESIZE)); * c - sleep queue chain lock */ struct sleepqueue { - TAILQ_HEAD(, thread) sq_blocked[NR_SLEEPQS]; /* (c) Blocked threads. */ + struct threadqueue sq_blocked[NR_SLEEPQS]; /* (c) Blocked threads. */ u_int sq_blockedcnt[NR_SLEEPQS]; /* (c) N. of blocked threads. */ LIST_ENTRY(sleepqueue) sq_hash; /* (c) Chain and free list. */ LIST_HEAD(, sleepqueue) sq_free; /* (c) Free queues. */ @@ -889,12 +889,14 @@ sleepq_init(void *mem, int size, int flags) } /* - * Find the highest priority thread sleeping on a wait channel and resume it. + * Find thread sleeping on a wait channel and resume it. */ int sleepq_signal(void *wchan, int flags, int pri, int queue) { + struct sleepqueue_chain *sc; struct sleepqueue *sq; + struct threadqueue *head; struct thread *td, *besttd; int wakeup_swapper; @@ -907,16 +909,33 @@ sleepq_signal(void *wchan, int flags, int pri, int queue) KASSERT(sq->sq_type == (flags & SLEEPQ_TYPE), ("%s: mismatch between sleep/wakeup and cv_*", __func__)); - /* - * Find the highest priority thread on the queue. If there is a - * tie, use the thread that first appears in the queue as it has - * been sleeping the longest since threads are always added to - * the tail of sleep queues. - */ - besttd = TAILQ_FIRST(&sq->sq_blocked[queue]); - TAILQ_FOREACH(td, &sq->sq_blocked[queue], td_slpq) { - if (td->td_priority < besttd->td_priority) + head = &sq->sq_blocked[queue]; + if (flags & SLEEPQ_UNFAIR) { + /* + * Find the most recently sleeping thread, but try to + * skip threads still in process of context switch to + * avoid spinning on the thread lock. + */ + sc = SC_LOOKUP(wchan); + besttd = TAILQ_LAST_FAST(head, thread, td_slpq); + while (besttd->td_lock != &sc->sc_lock) { + td = TAILQ_PREV_FAST(besttd, head, thread, td_slpq); + if (td == NULL) + break; besttd = td; + } + } else { + /* + * Find the highest priority thread on the queue. If there + * is a tie, use the thread that first appears in the queue + * as it has been sleeping the longest since threads are + * always added to the tail of sleep queues. + */ + besttd = td = TAILQ_FIRST(head); + while ((td = TAILQ_NEXT(td, td_slpq)) != NULL) { + if (td->td_priority < besttd->td_priority) + besttd = td; + } } MPASS(besttd != NULL); thread_lock(besttd); diff --git a/sys/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c index 51ceab775333..e070272adf9b 100644 --- a/sys/kern/subr_taskqueue.c +++ b/sys/kern/subr_taskqueue.c @@ -804,7 +804,7 @@ taskqueue_thread_enqueue(void *context) tqp = context; tq = *tqp; - wakeup_one(tq); + wakeup_any(tq); } TASKQUEUE_DEFINE(swi, taskqueue_swi_enqueue, NULL, diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 022c392d5c17..90f6245eac8a 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -93,7 +93,7 @@ static const char *dev_console_filename; FLUSHO|NOKERNINFO|NOFLSH) #define TTYSUP_CFLAG (CIGNORE|CSIZE|CSTOPB|CREAD|PARENB|PARODD|\ HUPCL|CLOCAL|CCTS_OFLOW|CRTS_IFLOW|CDTR_IFLOW|\ - CDSR_OFLOW|CCAR_OFLOW) + CDSR_OFLOW|CCAR_OFLOW|CNO_RTSDTR) #define TTY_CALLOUT(tp,d) (dev2unit(d) & TTYUNIT_CALLOUT) @@ -332,7 +332,8 @@ ttydev_open(struct cdev *dev, int oflags, int devtype __unused, if (TTY_CALLOUT(tp, dev) || dev == dev_console) tp->t_termios.c_cflag |= CLOCAL; - ttydevsw_modem(tp, SER_DTR|SER_RTS, 0); + if ((tp->t_termios.c_cflag & CNO_RTSDTR) == 0) + ttydevsw_modem(tp, SER_DTR|SER_RTS, 0); error = ttydevsw_open(tp); if (error != 0) diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index 22ee43547a9d..3c30d2e6c9f1 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -603,7 +603,13 @@ vop_stdgetwritemount(ap) return (0); } -/* XXX Needs good comment and VOP_BMAP(9) manpage */ +/* + * If the file system doesn't implement VOP_BMAP, then return sensible defaults: + * - Return the vnode's bufobj instead of any underlying device's bufobj + * - Calculate the physical block number as if there were equal size + * consecutive blocks, but + * - Report no contiguous runs of blocks. + */ int vop_stdbmap(ap) struct vop_bmap_args /* { diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 396da974ad98..7871e536b56e 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -1458,6 +1458,25 @@ vn_stat(struct vnode *vp, struct stat *sb, struct ucred *active_cred, return (0); } +/* generic FIOBMAP2 implementation */ +static int +vn_ioc_bmap2(struct file *fp, struct fiobmap2_arg *arg, struct ucred *cred) +{ + struct vnode *vp = fp->f_vnode; + daddr_t lbn = arg->bn; + int error; + + vn_lock(vp, LK_SHARED | LK_RETRY); +#ifdef MAC + error = mac_vnode_check_read(cred, fp->f_cred, vp); + if (error == 0) +#endif + error = VOP_BMAP(vp, lbn, NULL, &arg->bn, &arg->runp, + &arg->runb); + VOP_UNLOCK(vp, 0); + return (error); +} + /* * File table vnode ioctl routine. */ @@ -1481,6 +1500,9 @@ vn_ioctl(struct file *fp, u_long com, void *data, struct ucred *active_cred, if (error == 0) *(int *)data = vattr.va_size - fp->f_offset; return (error); + case FIOBMAP2: + return (vn_ioc_bmap2(fp, (struct fiobmap2_arg*)data, + active_cred)); case FIONBIO: case FIOASYNC: return (0); diff --git a/sys/kgssapi/krb5/kcrypto.c b/sys/kgssapi/krb5/kcrypto.c index fbe28ab8a474..f7c54a1770f3 100644 --- a/sys/kgssapi/krb5/kcrypto.c +++ b/sys/kgssapi/krb5/kcrypto.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -50,6 +51,11 @@ static struct krb5_encryption_class *krb5_encryption_classes[] = { NULL }; +struct timeval krb5_warn_interval = { .tv_sec = 3600, .tv_usec = 0 }; +SYSCTL_TIMEVAL_SEC(_kern, OID_AUTO, kgssapi_warn_interval, CTLFLAG_RW, + &krb5_warn_interval, + "Delay in seconds between warnings of deprecated KGSSAPI crypto."); + struct krb5_encryption_class * krb5_find_encryption_class(int etype) { diff --git a/sys/kgssapi/krb5/kcrypto.h b/sys/kgssapi/krb5/kcrypto.h index 452fd6cbcdc0..2ddfd663e28c 100644 --- a/sys/kgssapi/krb5/kcrypto.h +++ b/sys/kgssapi/krb5/kcrypto.h @@ -101,6 +101,7 @@ extern struct krb5_encryption_class krb5_aes128_encryption_class; extern struct krb5_encryption_class krb5_aes256_encryption_class; extern struct krb5_encryption_class krb5_arcfour_encryption_class; extern struct krb5_encryption_class krb5_arcfour_56_encryption_class; +extern struct timeval krb5_warn_interval; static __inline void krb5_set_key(struct krb5_key_state *ks, const void *keydata) diff --git a/sys/kgssapi/krb5/kcrypto_arcfour.c b/sys/kgssapi/krb5/kcrypto_arcfour.c index 317825af7a91..c0a19abff622 100644 --- a/sys/kgssapi/krb5/kcrypto_arcfour.c +++ b/sys/kgssapi/krb5/kcrypto_arcfour.c @@ -46,8 +46,11 @@ __FBSDID("$FreeBSD$"); static void arcfour_init(struct krb5_key_state *ks) { + static struct timeval lastwarn; ks->ks_priv = NULL; + if (ratecheck(&lastwarn, &krb5_warn_interval)) + gone_in(13, "RC4 cipher for Kerberos GSS"); } static void diff --git a/sys/kgssapi/krb5/kcrypto_des.c b/sys/kgssapi/krb5/kcrypto_des.c index 7f99ce69fcbd..14ef77361376 100644 --- a/sys/kgssapi/krb5/kcrypto_des.c +++ b/sys/kgssapi/krb5/kcrypto_des.c @@ -53,11 +53,14 @@ struct des1_state { static void des1_init(struct krb5_key_state *ks) { + static struct timeval lastwarn; struct des1_state *ds; ds = malloc(sizeof(struct des1_state), M_GSSAPI, M_WAITOK|M_ZERO); mtx_init(&ds->ds_lock, "gss des lock", NULL, MTX_DEF); ks->ks_priv = ds; + if (ratecheck(&lastwarn, &krb5_warn_interval)) + gone_in(13, "DES cipher for Kerberos GSS"); } static void diff --git a/sys/kgssapi/krb5/kcrypto_des3.c b/sys/kgssapi/krb5/kcrypto_des3.c index d4e9c351c765..54c28e3e39cb 100644 --- a/sys/kgssapi/krb5/kcrypto_des3.c +++ b/sys/kgssapi/krb5/kcrypto_des3.c @@ -54,11 +54,14 @@ struct des3_state { static void des3_init(struct krb5_key_state *ks) { + static struct timeval lastwarn; struct des3_state *ds; ds = malloc(sizeof(struct des3_state), M_GSSAPI, M_WAITOK|M_ZERO); mtx_init(&ds->ds_lock, "gss des3 lock", NULL, MTX_DEF); ks->ks_priv = ds; + if (ratecheck(&lastwarn, &krb5_warn_interval)) + gone_in(13, "DES3 cipher for Kerberos GSS"); } static void diff --git a/sys/libkern/crc32.c b/sys/libkern/gsb_crc32.c similarity index 99% rename from sys/libkern/crc32.c rename to sys/libkern/gsb_crc32.c index 149de3de6dee..46d6517f7940 100644 --- a/sys/libkern/crc32.c +++ b/sys/libkern/gsb_crc32.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #ifdef _KERNEL #include #include +#include #if defined(__amd64__) || defined(__i386__) #include diff --git a/sys/libkern/x86/crc32_sse42.c b/sys/libkern/x86/crc32_sse42.c index 50e457410ad9..712b21cda46e 100644 --- a/sys/libkern/x86/crc32_sse42.c +++ b/sys/libkern/x86/crc32_sse42.c @@ -29,14 +29,14 @@ __FBSDID("$FreeBSD$"); /* * This file is compiled in userspace in order to run ATF unit tests. */ -#ifdef USERSPACE_TESTING +#ifndef _KERNEL #include #include #else #include -#include #include #endif +#include static __inline uint32_t _mm_crc32_u8(uint32_t x, uint8_t y) @@ -199,7 +199,7 @@ crc32c_shift(uint32_t zeros[][256], uint32_t crc) /* Initialize tables for shifting crcs. */ static void -#ifdef USERSPACE_TESTING +#ifndef _KERNEL __attribute__((__constructor__)) #endif crc32c_init_hw(void) @@ -214,9 +214,6 @@ SYSINIT(crc32c_sse42, SI_SUB_LOCK, SI_ORDER_ANY, crc32c_init_hw, NULL); #endif /* Compute CRC-32C using the Intel hardware instruction. */ -#ifdef USERSPACE_TESTING -uint32_t sse42_crc32c(uint32_t, const unsigned char *, unsigned); -#endif uint32_t sse42_crc32c(uint32_t crc, const unsigned char *buf, unsigned len) { diff --git a/sys/mips/mips/pmap.c b/sys/mips/mips/pmap.c index d0edad94a582..5f0ad722f388 100644 --- a/sys/mips/mips/pmap.c +++ b/sys/mips/mips/pmap.c @@ -1591,7 +1591,7 @@ free_pv_chunk(struct pv_chunk *pc) /* entire chunk is free, return it */ m = PHYS_TO_VM_PAGE(MIPS_DIRECT_TO_PHYS((vm_offset_t)pc)); dump_drop_page(m->phys_addr); - vm_page_unwire(m, PQ_NONE); + vm_page_unwire_noq(m); vm_page_free(m); } diff --git a/sys/modules/Makefile b/sys/modules/Makefile index bf05a936dcdb..a9a5c5ed98ef 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -299,6 +299,7 @@ SUBDIR= \ ${_pst} \ pty \ puc \ + pwm \ ${_qlxge} \ ${_qlxgb} \ ${_qlxgbe} \ @@ -324,6 +325,7 @@ SUBDIR= \ sdhci \ ${_sdhci_acpi} \ sdhci_pci \ + sdio \ sem \ send \ ${_sfxge} \ diff --git a/sys/modules/allwinner/aw_pwm/Makefile b/sys/modules/allwinner/aw_pwm/Makefile index 820ab51cc42f..4f949bb562b8 100644 --- a/sys/modules/allwinner/aw_pwm/Makefile +++ b/sys/modules/allwinner/aw_pwm/Makefile @@ -10,6 +10,6 @@ SRCS+= \ clknode_if.h \ device_if.h \ ofw_bus_if.h \ - pwm_if.h + pwmbus_if.h .include diff --git a/sys/modules/arm_ti/Makefile b/sys/modules/arm_ti/Makefile new file mode 100644 index 000000000000..38af3a93c455 --- /dev/null +++ b/sys/modules/arm_ti/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ +# Build modules specific to Texas Instruments ARM SoCs. + +SUBDIR = \ + ../am335x_dmtpps \ + am335x_ehrpwm \ + ti_i2c \ + +.include diff --git a/sys/modules/arm_ti/am335x_ehrpwm/Makefile b/sys/modules/arm_ti/am335x_ehrpwm/Makefile new file mode 100644 index 000000000000..affb7cdc3a96 --- /dev/null +++ b/sys/modules/arm_ti/am335x_ehrpwm/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/arm/ti/am335x + +KMOD= am335x_ehrpwm +SRCS= am335x_ehrpwm.c + +# Generated files... +SRCS+= \ + bus_if.h \ + device_if.h \ + ofw_bus_if.h \ + pwmbus_if.h \ + +.include + diff --git a/sys/modules/arm_ti/ti_i2c/Makefile b/sys/modules/arm_ti/ti_i2c/Makefile new file mode 100644 index 000000000000..d0fbd5f1ca0a --- /dev/null +++ b/sys/modules/arm_ti/ti_i2c/Makefile @@ -0,0 +1,14 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/arm/ti + +KMOD= ti_i2c +SRCS= ti_i2c.c + +SRCS+= \ + bus_if.h \ + device_if.h \ + iicbus_if.h \ + ofw_bus_if.h \ + +.include diff --git a/sys/modules/efirt/Makefile b/sys/modules/efirt/Makefile index 9ea861836c22..58f4f9673c2e 100644 --- a/sys/modules/efirt/Makefile +++ b/sys/modules/efirt/Makefile @@ -11,6 +11,7 @@ SRCS+= device_if.h bus_if.h clock_if.h .if ${MACHINE_CPUARCH} == "amd64" SRCS+= opt_hwpmc_hooks.h opt_kstack_pages.h SRCS+= efirt_support.S +DPSRCS+= assym.inc efirt_support.o: efirt_support.S assym.inc ${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \ ${.IMPSRC} -o ${.TARGET} diff --git a/sys/modules/hwpmc/Makefile b/sys/modules/hwpmc/Makefile index 2be1a58a2551..23bd648be229 100644 --- a/sys/modules/hwpmc/Makefile +++ b/sys/modules/hwpmc/Makefile @@ -22,6 +22,10 @@ SRCS+= hwpmc_x86.c hwpmc_uncore.c SRCS+= hwpmc_arm.c .endif +.if ${MACHINE_ARCH} == "armv7" +SRCS+= hwpmc_armv7.c +.endif + .if ${MACHINE_CPUARCH} == "i386" SRCS+= hwpmc_amd.c hwpmc_core.c hwpmc_intel.c SRCS+= hwpmc_tsc.c hwpmc_x86.c hwpmc_uncore.c diff --git a/sys/modules/iwmfw/Makefile.inc b/sys/modules/iwmfw/Makefile.inc index eaa0e32d109e..89ae353073ca 100644 --- a/sys/modules/iwmfw/Makefile.inc +++ b/sys/modules/iwmfw/Makefile.inc @@ -15,4 +15,4 @@ FIRMWS= ${_FIRM}:${KMOD} #FIRMWARE_LICENSE= ${_FIRM}: ${SRCTOP}/sys/contrib/dev/iwm/${_FIRM}.uu - uudecode -p $? > ${.TARGET} + uudecode -p ${.ALLSRC} > ${.TARGET} diff --git a/sys/modules/iwnfw/Makefile.inc b/sys/modules/iwnfw/Makefile.inc index 17d112785a20..32355f387ecf 100644 --- a/sys/modules/iwnfw/Makefile.inc +++ b/sys/modules/iwnfw/Makefile.inc @@ -15,4 +15,4 @@ FIRMWS= ${_FIRM}:${KMOD} #FIRMWARE_LICENSE= ${_FIRM}: ${SRCTOP}/sys/contrib/dev/iwn/${_FIRM}.uu - uudecode -p $? > ${.TARGET} + uudecode -p ${.ALLSRC} > ${.TARGET} diff --git a/sys/modules/mwlfw/Makefile b/sys/modules/mwlfw/Makefile index 1e6a1e8503e2..177ac5880d83 100644 --- a/sys/modules/mwlfw/Makefile +++ b/sys/modules/mwlfw/Makefile @@ -6,9 +6,9 @@ FIRMWS= mw88W8363.fw:mw88W8363fw mwlboot.fw:mwlboot CLEANFILES+= mw88W8363.fw mwlboot.fw mw88W8363.fw: ${SRCTOP}/sys/contrib/dev/mwl/mw88W8363.fw.uu - uudecode -p $? > ${.TARGET} + uudecode -p ${.ALLSRC} > ${.TARGET} mwlboot.fw: ${SRCTOP}/sys/contrib/dev/mwl/mwlboot.fw.uu - uudecode -p $? > ${.TARGET} + uudecode -p ${.ALLSRC} > ${.TARGET} .include diff --git a/sys/modules/ocs_fc/Makefile b/sys/modules/ocs_fc/Makefile index 467ff23510fa..9bab50eba5bc 100644 --- a/sys/modules/ocs_fc/Makefile +++ b/sys/modules/ocs_fc/Makefile @@ -41,6 +41,6 @@ SRCS += ocs_cam.c CINCS = -I. -CLEANFILES += ${PROG}.debug ${PROG}.symbols cscope.* .depend.* +CLEANFILES += ${PROG}.debug ${PROG}.symbols cscope.* .include diff --git a/sys/modules/pwm/Makefile b/sys/modules/pwm/Makefile new file mode 100644 index 000000000000..6c17a2b5d8dc --- /dev/null +++ b/sys/modules/pwm/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +# Modules for dev/pwm drivers. + +SUBDIR = \ + pwmbus \ + pwmc \ + +.include diff --git a/sys/modules/pwm/pwmbus/Makefile b/sys/modules/pwm/pwmbus/Makefile new file mode 100644 index 000000000000..3cf56697f200 --- /dev/null +++ b/sys/modules/pwm/pwmbus/Makefile @@ -0,0 +1,20 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/dev/pwm + +KMOD= pwmbus +SRCS= pwmbus.c + +.if !empty(OPT_FDT) +SRCS+= ofw_pwm.c ofw_pwmbus.c ofw_bus_if.h +.endif + +# Generated files... +SRCS+= \ + bus_if.h \ + device_if.h \ + opt_platform.h \ + pwmbus_if.c \ + pwmbus_if.h \ + +.include diff --git a/sys/modules/pwm/pwmc/Makefile b/sys/modules/pwm/pwmc/Makefile new file mode 100644 index 000000000000..6e373e467a4a --- /dev/null +++ b/sys/modules/pwm/pwmc/Makefile @@ -0,0 +1,18 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/dev/pwm +KMOD= pwmc +SRCS= pwmc.c + +# Generated files... +SRCS+= \ + bus_if.h \ + device_if.h \ + opt_platform.h \ + pwmbus_if.h \ + +.if !empty(OPT_FDT) +SRCS+= ofw_bus_if.h +.endif + +.include diff --git a/sys/modules/ralfw/Makefile.inc b/sys/modules/ralfw/Makefile.inc index 9922352372ea..678648a53fd3 100644 --- a/sys/modules/ralfw/Makefile.inc +++ b/sys/modules/ralfw/Makefile.inc @@ -12,4 +12,4 @@ CLEANFILES+= ${_FIRM} FIRMWS= ${_FIRM}:${KMOD} ${_FIRM}: ${SRCTOP}/sys/contrib/dev/ral/${_FIRM}.uu - uudecode -p $? > ${.TARGET} + uudecode -p ${.ALLSRC} > ${.TARGET} diff --git a/sys/modules/rtwnfw/Makefile.inc b/sys/modules/rtwnfw/Makefile.inc index 2a7865d94bf4..f38e5e41fcd4 100644 --- a/sys/modules/rtwnfw/Makefile.inc +++ b/sys/modules/rtwnfw/Makefile.inc @@ -12,4 +12,4 @@ FIRMWS= ${_FIRM}:${KMOD}:111 # FIRMWARE_LICENSE= realtek ${_FIRM}: ${SRCTOP}/sys/contrib/dev/rtwn/${_FIRM}.uu - uudecode -p $? > ${.TARGET} + uudecode -p ${.ALLSRC} > ${.TARGET} diff --git a/sys/modules/sdio/Makefile b/sys/modules/sdio/Makefile new file mode 100644 index 000000000000..4ee0e2d5223b --- /dev/null +++ b/sys/modules/sdio/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../dev/sdio + +KMOD= sdio +SRCS= sdiob.c sdio_subr.c +SRCS+= sdio_if.c +SRCS+= device_if.h bus_if.h sdio_if.h opt_cam.h + +.include diff --git a/sys/modules/ti/Makefile b/sys/modules/ti/Makefile index 84114ccfbbe9..82e2a697df6b 100644 --- a/sys/modules/ti/Makefile +++ b/sys/modules/ti/Makefile @@ -1,4 +1,6 @@ # $FreeBSD$ +# Module for Alteon Networks Tigon PCI gigabit ethernet driver for FreeBSD. +# Modules for Texas Instruments ARM SoCs are located in sys/modules/arm_ti. .PATH: ${SRCTOP}/sys/dev/ti diff --git a/sys/modules/usb/rsufw/Makefile.inc b/sys/modules/usb/rsufw/Makefile.inc index 2f9817762efb..1b15e66fd17d 100644 --- a/sys/modules/usb/rsufw/Makefile.inc +++ b/sys/modules/usb/rsufw/Makefile.inc @@ -12,4 +12,4 @@ FIRMWS= ${_FIRM}:${KMOD}:120 # FIRMWARE_LICENSE= realtek ${_FIRM}: ${SRCTOP}/sys/contrib/dev/rsu/${_FIRM}.uu - uudecode -p $? > ${.TARGET} + uudecode -p ${.ALLSRC} > ${.TARGET} diff --git a/sys/modules/usb/runfw/Makefile b/sys/modules/usb/runfw/Makefile index 47d09a56c42c..b60b26c3e134 100644 --- a/sys/modules/usb/runfw/Makefile +++ b/sys/modules/usb/runfw/Makefile @@ -6,6 +6,6 @@ FIRMWS= run.fw:runfw:1 CLEANFILES= run.fw run.fw: ${SRCTOP}/sys/contrib/dev/run/rt2870.fw.uu - uudecode -p $? > ${.TARGET} + uudecode -p ${.ALLSRC} > ${.TARGET} .include diff --git a/sys/modules/usb/usb/Makefile b/sys/modules/usb/usb/Makefile index 78901825283d..d32f07a6d0b4 100644 --- a/sys/modules/usb/usb/Makefile +++ b/sys/modules/usb/usb/Makefile @@ -39,6 +39,11 @@ SRCS= bus_if.h device_if.h usb_if.h usb_if.c vnode_if.h \ usb_msctest.c usb_parse.c usb_pf.c usb_process.c usb_request.c \ usb_transfer.c usb_util.c +.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || \ + ${MACHINE_CPUARCH} == "i386" +SRCS += opt_acpi.h usb_hub_acpi.c acpi_if.h +.endif + .if !empty(OPT_FDT) SRCS+= usb_fdt_support.c ofw_bus_if.h .endif diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c index 1a4d1d302ece..3e1cb2043b08 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -1955,12 +1955,14 @@ lagg_link_active(struct lagg_softc *sc, struct lagg_port *lp) * Search a port which reports an active link state. */ +#ifdef INVARIANTS /* * This is called with either LAGG_RLOCK() held or * LAGG_XLOCK(sc) held. */ if (!in_epoch(net_epoch_preempt)) LAGG_XLOCK_ASSERT(sc); +#endif if (lp == NULL) goto search; diff --git a/sys/net/iflib.c b/sys/net/iflib.c index 5c15ff51df92..d932e9373be0 100644 --- a/sys/net/iflib.c +++ b/sys/net/iflib.c @@ -376,7 +376,6 @@ struct iflib_fl { uint64_t ifl_cl_dequeued; #endif /* implicit pad */ - bitstr_t *ifl_rx_bitmap; qidx_t ifl_fragidx; /* constant */ @@ -1250,7 +1249,6 @@ iflib_netmap_timer_adjust(if_ctx_t ctx, iflib_txq_t txq, uint32_t *reset_on) #define netmap_rx_irq(ifp, qid, budget) (0) #define netmap_tx_irq(ifp, qid) do {} while (0) #define iflib_netmap_timer_adjust(ctx, txq, reset_on) - #endif #if defined(__i386__) || defined(__amd64__) @@ -1537,17 +1535,17 @@ _iflib_irq_alloc(if_ctx_t ctx, if_irq_t irq, int rid, driver_filter_t filter, driver_intr_t handler, void *arg, const char *name) { - int rc, flags; struct resource *res; void *tag = NULL; device_t dev = ctx->ifc_dev; + int flags, i, rc; flags = RF_ACTIVE; if (ctx->ifc_flags & IFC_LEGACY) flags |= RF_SHAREABLE; MPASS(rid < 512); - irq->ii_rid = rid; - res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irq->ii_rid, flags); + i = rid; + res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, flags); if (res == NULL) { device_printf(dev, "failed to allocate IRQ for rid %d, name %s.\n", rid, name); @@ -1569,7 +1567,6 @@ _iflib_irq_alloc(if_ctx_t ctx, if_irq_t irq, int rid, return (0); } - /********************************************************************* * * Allocate DMA resources for TX buffers as well as memory for the TX @@ -2691,10 +2688,10 @@ iflib_get_ip_forwarding(struct lro_ctrl *lc, bool *v4, bool *v6) { CURVNET_SET(lc->ifp->if_vnet); #if defined(INET6) - *v6 = VNET(ip6_forwarding); + *v6 = V_ip6_forwarding; #endif #if defined(INET) - *v4 = VNET(ipforwarding); + *v4 = V_ipforwarding; #endif CURVNET_RESTORE(); } @@ -2708,18 +2705,16 @@ static bool iflib_check_lro_possible(struct mbuf *m, bool v4_forwarding, bool v6_forwarding) { struct ether_header *eh; - uint16_t eh_type; eh = mtod(m, struct ether_header *); - eh_type = ntohs(eh->ether_type); - switch (eh_type) { + switch (eh->ether_type) { #if defined(INET6) - case ETHERTYPE_IPV6: - return !v6_forwarding; + case htons(ETHERTYPE_IPV6): + return (!v6_forwarding); #endif #if defined (INET) - case ETHERTYPE_IP: - return !v4_forwarding; + case htons(ETHERTYPE_IP): + return (!v4_forwarding); #endif } @@ -4332,12 +4327,10 @@ iflib_led_func(void *arg, int onoff) int iflib_device_probe(device_t dev) { - pci_vendor_info_t *ent; - - uint16_t pci_vendor_id, pci_device_id; - uint16_t pci_subvendor_id, pci_subdevice_id; - uint16_t pci_rev_id; + const pci_vendor_info_t *ent; if_shared_ctx_t sctx; + uint16_t pci_device_id, pci_rev_id, pci_subdevice_id, pci_subvendor_id; + uint16_t pci_vendor_id; if ((sctx = DEVICE_REGISTER(dev)) == NULL || sctx->isc_magic != IFLIB_MAGIC) return (ENOTSUP); @@ -4397,8 +4390,6 @@ iflib_reset_qvalues(if_ctx_t ctx) device_t dev = ctx->ifc_dev; int i; - scctx->isc_txrx_budget_bytes_max = IFLIB_MAX_TX_BYTES; - scctx->isc_tx_qdepth = IFLIB_DEFAULT_TX_QDEPTH; if (ctx->ifc_sysctl_ntxqs != 0) scctx->isc_ntxqsets = ctx->ifc_sysctl_ntxqs; if (ctx->ifc_sysctl_nrxqs != 0) @@ -6037,15 +6028,14 @@ iflib_legacy_setup(if_ctx_t ctx, driver_filter_t filter, void *filter_arg, int * struct resource *res; struct taskqgroup *tqg; gtask_fn_t *fn; - int tqrid; void *q; - int err; + int err, tqrid; q = &ctx->ifc_rxqs[0]; info = &rxq[0].ifr_filter_info; gtask = &rxq[0].ifr_task; tqg = qgroup_if_io_tqg; - tqrid = irq->ii_rid = *rid; + tqrid = *rid; fn = _task_fn_rx; ctx->ifc_flags |= IFC_LEGACY; @@ -6112,7 +6102,7 @@ iflib_iov_intr_deferred(if_ctx_t ctx) } void -iflib_io_tqg_attach(struct grouptask *gt, void *uniq, int cpu, char *name) +iflib_io_tqg_attach(struct grouptask *gt, void *uniq, int cpu, const char *name) { taskqgroup_attach_cpu(qgroup_if_io_tqg, gt, uniq, cpu, NULL, NULL, diff --git a/sys/net/iflib.h b/sys/net/iflib.h index 77f69354765b..cda00c4c29a7 100644 --- a/sys/net/iflib.h +++ b/sys/net/iflib.h @@ -132,12 +132,12 @@ typedef struct if_pkt_info { uint8_t ipi_mflags; /* packet mbuf flags */ uint32_t ipi_tcp_seq; /* tcp seqno */ - uint32_t ipi_tcp_sum; /* tcp csum */ + uint32_t __spare0__; } *if_pkt_info_t; typedef struct if_irq { struct resource *ii_res; - int ii_rid; + int __spare0__; void *ii_tag; } *if_irq_t; @@ -166,7 +166,7 @@ typedef struct pci_vendor_info { uint32_t pvi_subdevice_id; uint32_t pvi_rev_id; uint32_t pvi_class_mask; - caddr_t pvi_name; + const char *pvi_name; } pci_vendor_info_t; #define PVID(vendor, devid, name) {vendor, devid, 0, 0, 0, 0, name} @@ -194,9 +194,8 @@ typedef struct if_softc_ctx { int isc_vectors; int isc_nrxqsets; int isc_ntxqsets; - uint8_t isc_min_tx_latency; /* disable doorbell update batching */ - uint8_t isc_rx_mvec_enable; /* generate mvecs on rx */ - uint32_t isc_txrx_budget_bytes_max; + uint16_t __spare0__; + uint32_t __spare1__; int isc_msix_bar; /* can be model specific - initialize in attach_pre */ int isc_tx_nsegments; /* can be model specific - initialize in attach_pre */ int isc_ntxd[8]; @@ -218,20 +217,25 @@ typedef struct if_softc_ctx { int isc_rss_table_mask; int isc_nrxqsets_max; int isc_ntxqsets_max; - uint32_t isc_tx_qdepth; + uint32_t __spare2__; iflib_intr_mode_t isc_intr; uint16_t isc_max_frame_size; /* set at init time by driver */ uint16_t isc_min_frame_size; /* set at init time by driver, only used if IFLIB_NEED_ETHER_PAD is set. */ uint32_t isc_pause_frames; /* set by driver for iflib_timer to detect */ - pci_vendor_info_t isc_vendor_info; /* set by iflib prior to attach_pre */ + uint32_t __spare3__; + uint32_t __spare4__; + uint32_t __spare5__; + uint32_t __spare6__; + uint32_t __spare7__; + uint32_t __spare8__; + caddr_t __spare9__; int isc_disable_msix; if_txrx_t isc_txrx; struct ifmedia *isc_media; } *if_softc_ctx_t; - /* * Initialization values for device */ @@ -249,7 +253,7 @@ struct if_shared_ctx { int isc_admin_intrcnt; /* # of admin/link interrupts */ /* fields necessary for probe */ - pci_vendor_info_t *isc_vendor_info; + const pci_vendor_info_t *isc_vendor_info; const char *isc_driver_version; /* optional function to transform the read values to match the table*/ void (*isc_parse_devinfo) (uint16_t *device_id, uint16_t *subvendor_id, @@ -265,7 +269,7 @@ struct if_shared_ctx { int isc_nfl __aligned(CACHE_LINE_SIZE); int isc_ntxqs; /* # of tx queues per tx qset - usually 1 */ int isc_nrxqs; /* # of rx queues per rx qset - intel 1, chelsio 2, broadcom 3 */ - int isc_rx_process_limit; + int __spare0__; int isc_tx_reclaim_thresh; int isc_flags; const char *isc_name; @@ -289,11 +293,6 @@ typedef enum { IFLIB_INTR_IOV, } iflib_intr_type_t; -#ifndef ETH_ADDR_LEN -#define ETH_ADDR_LEN 6 -#endif - - /* * Interface has a separate command queue for RX */ @@ -368,7 +367,6 @@ typedef enum { */ #define IFLIB_DRIVER_MEDIA 0x20000 - /* * field accessors */ @@ -406,7 +404,6 @@ int iflib_device_shutdown(device_t); */ int iflib_device_probe_vendor(device_t); - int iflib_device_iov_init(device_t, uint16_t, const nvlist_t *); void iflib_device_iov_uninit(device_t); int iflib_device_iov_add_vf(device_t, uint16_t, const nvlist_t *); @@ -418,8 +415,6 @@ int iflib_device_iov_add_vf(device_t, uint16_t, const nvlist_t *); int iflib_device_register(device_t dev, void *softc, if_shared_ctx_t sctx, if_ctx_t *ctxp); int iflib_device_deregister(if_ctx_t); - - int iflib_irq_alloc(if_ctx_t, if_irq_t, int, driver_filter_t, void *filter_arg, driver_intr_t, void *arg, const char *name); int iflib_irq_alloc_generic(if_ctx_t ctx, if_irq_t irq, int rid, iflib_intr_type_t type, driver_filter_t *filter, @@ -428,34 +423,28 @@ void iflib_softirq_alloc_generic(if_ctx_t ctx, if_irq_t irq, iflib_intr_type_t t void iflib_irq_free(if_ctx_t ctx, if_irq_t irq); -void iflib_io_tqg_attach(struct grouptask *gt, void *uniq, int cpu, char *name); +void iflib_io_tqg_attach(struct grouptask *gt, void *uniq, int cpu, + const char *name); void iflib_config_gtask_init(void *ctx, struct grouptask *gtask, gtask_fn_t *fn, const char *name); - void iflib_config_gtask_deinit(struct grouptask *gtask); - - void iflib_tx_intr_deferred(if_ctx_t ctx, int txqid); void iflib_rx_intr_deferred(if_ctx_t ctx, int rxqid); void iflib_admin_intr_deferred(if_ctx_t ctx); void iflib_iov_intr_deferred(if_ctx_t ctx); - void iflib_link_state_change(if_ctx_t ctx, int linkstate, uint64_t baudrate); int iflib_dma_alloc(if_ctx_t ctx, int size, iflib_dma_info_t dma, int mapflags); int iflib_dma_alloc_align(if_ctx_t ctx, int size, int align, iflib_dma_info_t dma, int mapflags); void iflib_dma_free(iflib_dma_info_t dma); - int iflib_dma_alloc_multi(if_ctx_t ctx, int *sizes, iflib_dma_info_t *dmalist, int mapflags, int count); void iflib_dma_free_multi(iflib_dma_info_t *dmalist, int count); - struct sx *iflib_ctx_lock_get(if_ctx_t); -struct mtx *iflib_qset_lock_get(if_ctx_t, uint16_t); void iflib_led_create(if_ctx_t ctx); @@ -467,4 +456,5 @@ void iflib_add_int_delay_sysctl(if_ctx_t, const char *, const char *, */ if_pseudo_t iflib_clone_register(if_shared_ctx_t); void iflib_clone_deregister(if_pseudo_t); + #endif /* __IFLIB_H_ */ diff --git a/sys/net/iflib_private.h b/sys/net/iflib_private.h index 341deb43d7bf..eca6be6384e8 100644 --- a/sys/net/iflib_private.h +++ b/sys/net/iflib_private.h @@ -28,8 +28,7 @@ */ #ifndef __NET_IFLIB_PRIVATE_H_ -#define __NET_IFLIB_PRIVATE_H_ - +#define __NET_IFLIB_PRIVATE_H_ #define IFC_LEGACY 0x001 #define IFC_QFLUSH 0x002 @@ -40,19 +39,14 @@ #define IFC_PREFETCH 0x040 #define IFC_DO_RESET 0x080 #define IFC_DO_WATCHDOG 0x100 -#define IFC_CHECK_HUNG 0x200 +#define IFC_SPARE0 0x200 #define IFC_PSEUDO 0x400 #define IFC_IN_DETACH 0x800 -#define IFC_NETMAP_TX_IRQ 0x80000000 +#define IFC_NETMAP_TX_IRQ 0x80000000 MALLOC_DECLARE(M_IFLIB); -#define IFLIB_MAX_TX_BYTES (2*1024*1024) -#define IFLIB_MIN_TX_BYTES (8*1024) -#define IFLIB_DEFAULT_TX_QDEPTH 2048 - - struct iflib_cloneattach_ctx { struct if_clone *cc_ifc; caddr_t cc_params; diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index 699728ee6909..a36abf1aa0d9 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -1386,6 +1386,8 @@ getflags(const uint8_t bands[], uint32_t flags[], int ht40, int vht80) /* * Add one 20 MHz channel into specified channel list. + * You MUST NOT mix bands when calling this. It will not add 5ghz + * channels if you have any B/G/N band bit set. */ /* XXX VHT */ int diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 4adf3be5f8fc..9c24fb9fdd67 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -2180,21 +2180,6 @@ static struct protosw in6_carp_protosw = { }; #endif -#ifdef VIMAGE -#if defined(__i386__) -/* - * XXX This is a hack to work around an absolute relocation outside - * set_vnet by one (on the stop symbol) for carpstats. Add a dummy variable - * to the end of the file in the hope that the linker will just keep the - * order (as it seems to do at the moment). It is understood to be fragile. - * See PR 230857 for a longer discussion of the problem and the referenced - * review for possible alternate solutions. Each is a hack; we just need - * the least intrusive one for the next release. - */ -VNET_DEFINE(char, carp_zzz) = 0xde; -#endif -#endif - static void carp_mod_cleanup(void) { diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index b48350fd5c7a..99b8c3662be5 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -35,13 +35,13 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" -#include "opt_ratelimit.h" #include "opt_ipsec.h" #include "opt_mbuf_stress_test.h" #include "opt_mpath.h" +#include "opt_ratelimit.h" #include "opt_route.h" -#include "opt_sctp.h" #include "opt_rss.h" +#include "opt_sctp.h" #include #include @@ -283,6 +283,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, #if defined(IPSEC) || defined(IPSEC_SUPPORT) int no_route_but_check_spd = 0; #endif + M_ASSERTPKTHDR(m); if (inp != NULL) { diff --git a/sys/netinet/libalias/alias_sctp.c b/sys/netinet/libalias/alias_sctp.c index dd9b97b57475..da2dd8c5b8ac 100644 --- a/sys/netinet/libalias/alias_sctp.c +++ b/sys/netinet/libalias/alias_sctp.c @@ -75,6 +75,7 @@ #ifdef _KERNEL #include #include +#include #include #include #include diff --git a/sys/netinet/sctp_crc32.c b/sys/netinet/sctp_crc32.c index da5df194b8b3..1c3421a15585 100644 --- a/sys/netinet/sctp_crc32.c +++ b/sys/netinet/sctp_crc32.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include "opt_sctp.h" +#include #ifdef SCTP #include #include diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c index 2ead503df0b3..d95a0edea790 100644 --- a/sys/netinet/tcp_stacks/rack.c +++ b/sys/netinet/tcp_stacks/rack.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2016-2018 Netflix, Inc. + * Copyright (c) 2016-2019 Netflix, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -202,6 +202,7 @@ static int32_t rack_always_send_oldest = 0; static int32_t rack_sack_block_limit = 128; static int32_t rack_use_sack_filter = 1; static int32_t rack_tlp_threshold_use = TLP_USE_TWO_ONE; +static uint32_t rack_map_split_limit = 0; /* unlimited by default */ /* Rack specific counters */ counter_u64_t rack_badfr; @@ -227,6 +228,8 @@ counter_u64_t rack_to_arm_tlp; counter_u64_t rack_to_alloc; counter_u64_t rack_to_alloc_hard; counter_u64_t rack_to_alloc_emerg; +counter_u64_t rack_alloc_limited_conns; +counter_u64_t rack_split_limited; counter_u64_t rack_sack_proc_all; counter_u64_t rack_sack_proc_short; @@ -260,6 +263,8 @@ static void rack_ack_received(struct tcpcb *tp, struct tcp_rack *rack, struct tcphdr *th, uint16_t nsegs, uint16_t type, int32_t recovery); static struct rack_sendmap *rack_alloc(struct tcp_rack *rack); +static struct rack_sendmap *rack_alloc_limit(struct tcp_rack *rack, + uint8_t limit_type); static struct rack_sendmap * rack_check_recovery_mode(struct tcpcb *tp, uint32_t tsused); @@ -444,6 +449,8 @@ sysctl_rack_clear(SYSCTL_HANDLER_ARGS) counter_u64_zero(rack_sack_proc_short); counter_u64_zero(rack_sack_proc_restart); counter_u64_zero(rack_to_alloc); + counter_u64_zero(rack_alloc_limited_conns); + counter_u64_zero(rack_split_limited); counter_u64_zero(rack_find_high); counter_u64_zero(rack_runt_sacks); counter_u64_zero(rack_used_tlpmethod); @@ -621,6 +628,11 @@ rack_init_sysctls() OID_AUTO, "pktdelay", CTLFLAG_RW, &rack_pkt_delay, 1, "Extra RACK time (in ms) besides reordering thresh"); + SYSCTL_ADD_U32(&rack_sysctl_ctx, + SYSCTL_CHILDREN(rack_sysctl_root), + OID_AUTO, "split_limit", CTLFLAG_RW, + &rack_map_split_limit, 0, + "Is there a limit on the number of map split entries (0=unlimited)"); SYSCTL_ADD_S32(&rack_sysctl_ctx, SYSCTL_CHILDREN(rack_sysctl_root), OID_AUTO, "inc_var", CTLFLAG_RW, @@ -756,7 +768,19 @@ rack_init_sysctls() SYSCTL_CHILDREN(rack_sysctl_root), OID_AUTO, "allocemerg", CTLFLAG_RD, &rack_to_alloc_emerg, - "Total alocations done from emergency cache"); + "Total allocations done from emergency cache"); + rack_alloc_limited_conns = counter_u64_alloc(M_WAITOK); + SYSCTL_ADD_COUNTER_U64(&rack_sysctl_ctx, + SYSCTL_CHILDREN(rack_sysctl_root), + OID_AUTO, "alloc_limited_conns", CTLFLAG_RD, + &rack_alloc_limited_conns, + "Connections with allocations dropped due to limit"); + rack_split_limited = counter_u64_alloc(M_WAITOK); + SYSCTL_ADD_COUNTER_U64(&rack_sysctl_ctx, + SYSCTL_CHILDREN(rack_sysctl_root), + OID_AUTO, "split_limited", CTLFLAG_RD, + &rack_split_limited, + "Split allocations dropped due to limit"); rack_sack_proc_all = counter_u64_alloc(M_WAITOK); SYSCTL_ADD_COUNTER_U64(&rack_sysctl_ctx, SYSCTL_CHILDREN(rack_sysctl_root), @@ -1120,10 +1144,11 @@ rack_alloc(struct tcp_rack *rack) { struct rack_sendmap *rsm; - counter_u64_add(rack_to_alloc, 1); - rack->r_ctl.rc_num_maps_alloced++; rsm = uma_zalloc(rack_zone, M_NOWAIT); if (rsm) { +alloc_done: + counter_u64_add(rack_to_alloc, 1); + rack->r_ctl.rc_num_maps_alloced++; return (rsm); } if (rack->rc_free_cnt) { @@ -1131,14 +1156,46 @@ rack_alloc(struct tcp_rack *rack) rsm = TAILQ_FIRST(&rack->r_ctl.rc_free); TAILQ_REMOVE(&rack->r_ctl.rc_free, rsm, r_next); rack->rc_free_cnt--; - return (rsm); + goto alloc_done; } return (NULL); } +/* wrapper to allocate a sendmap entry, subject to a specific limit */ +static struct rack_sendmap * +rack_alloc_limit(struct tcp_rack *rack, uint8_t limit_type) +{ + struct rack_sendmap *rsm; + + if (limit_type) { + /* currently there is only one limit type */ + if (rack_map_split_limit > 0 && + rack->r_ctl.rc_num_split_allocs >= rack_map_split_limit) { + counter_u64_add(rack_split_limited, 1); + if (!rack->alloc_limit_reported) { + rack->alloc_limit_reported = 1; + counter_u64_add(rack_alloc_limited_conns, 1); + } + return (NULL); + } + } + + /* allocate and mark in the limit type, if set */ + rsm = rack_alloc(rack); + if (rsm != NULL && limit_type) { + rsm->r_limit_type = limit_type; + rack->r_ctl.rc_num_split_allocs++; + } + return (rsm); +} + static void rack_free(struct tcp_rack *rack, struct rack_sendmap *rsm) { + if (rsm->r_limit_type) { + /* currently there is only one limit type */ + rack->r_ctl.rc_num_split_allocs--; + } rack->r_ctl.rc_num_maps_alloced--; if (rack->r_ctl.rc_tlpsend == rsm) rack->r_ctl.rc_tlpsend = NULL; @@ -3953,7 +4010,7 @@ rack_proc_sack_blk(struct tcpcb *tp, struct tcp_rack *rack, struct sackblk *sack /* * Need to split this in two pieces the before and after. */ - nrsm = rack_alloc(rack); + nrsm = rack_alloc_limit(rack, RACK_LIMIT_TYPE_SPLIT); if (nrsm == NULL) { /* * failed XXXrrs what can we do but loose the sack @@ -4014,7 +4071,7 @@ rack_proc_sack_blk(struct tcpcb *tp, struct tcp_rack *rack, struct sackblk *sack goto do_rest_ofb; } /* Ok we need to split off this one at the tail */ - nrsm = rack_alloc(rack); + nrsm = rack_alloc_limit(rack, RACK_LIMIT_TYPE_SPLIT); if (nrsm == NULL) { /* failed rrs what can we do but loose the sack info? */ goto out; diff --git a/sys/netinet/tcp_stacks/tcp_rack.h b/sys/netinet/tcp_stacks/tcp_rack.h index 76c3eb2e5b70..235951999e64 100644 --- a/sys/netinet/tcp_stacks/tcp_rack.h +++ b/sys/netinet/tcp_stacks/tcp_rack.h @@ -54,8 +54,10 @@ struct rack_sendmap { uint8_t r_sndcnt; /* Retran count, not limited by * RACK_NUM_OF_RETRANS */ uint8_t r_in_tmap; /* Flag to see if its in the r_tnext array */ - uint8_t r_resv[3]; + uint8_t r_limit_type; /* is this entry counted against a limit? */ + uint8_t r_resv[2]; }; +#define RACK_LIMIT_TYPE_SPLIT 1 TAILQ_HEAD(rack_head, rack_sendmap); @@ -241,7 +243,7 @@ struct rack_control { uint32_t rc_num_maps_alloced; /* Number of map blocks (sacks) we * have allocated */ uint32_t rc_rcvtime; /* When we last received data */ - uint32_t rc_notused; + uint32_t rc_num_split_allocs; /* num split map entries allocated */ uint32_t rc_last_output_to; uint32_t rc_went_idle_time; @@ -310,7 +312,8 @@ struct tcp_rack { uint8_t rack_tlp_threshold_use; uint8_t rc_allow_data_af_clo: 1, delayed_ack : 1, - rc_avail : 6; + alloc_limit_reported : 1, + rc_avail : 5; uint8_t r_resv[2]; /* Fill to cache line boundary */ /* Cache line 2 0x40 */ struct rack_control r_ctl; diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index 3c601cb8702f..f1e36c9f1966 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -67,11 +67,11 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ratelimit.h" #include "opt_ipsec.h" -#include "opt_sctp.h" +#include "opt_ratelimit.h" #include "opt_route.h" #include "opt_rss.h" +#include "opt_sctp.h" #include #include diff --git a/sys/netipsec/ipsec.c b/sys/netipsec/ipsec.c index 8d3e16723925..245feb1bdca9 100644 --- a/sys/netipsec/ipsec.c +++ b/sys/netipsec/ipsec.c @@ -216,6 +216,11 @@ SYSCTL_INT(_net_inet_ipsec, OID_AUTO, filtertunnel, SYSCTL_VNET_PCPUSTAT(_net_inet_ipsec, OID_AUTO, ipsecstats, struct ipsecstat, ipsec4stat, "IPsec IPv4 statistics."); +struct timeval ipsec_warn_interval = { .tv_sec = 1, .tv_usec = 0 }; +SYSCTL_TIMEVAL_SEC(_net_inet_ipsec, OID_AUTO, crypto_warn_interval, CTLFLAG_RW, + &ipsec_warn_interval, + "Delay in seconds between warnings of deprecated IPsec crypto algorithms."); + #ifdef REGRESSION /* * When set to 1, IPsec will send packets with the same sequence number. diff --git a/sys/netipsec/ipsec.h b/sys/netipsec/ipsec.h index 0124b12c20cd..345faa3618c8 100644 --- a/sys/netipsec/ipsec.h +++ b/sys/netipsec/ipsec.h @@ -287,6 +287,8 @@ VNET_DECLARE(int, crypto_support); VNET_DECLARE(int, async_crypto); VNET_DECLARE(int, natt_cksum_policy); +extern struct timeval ipsec_warn_interval; + #define IPSECSTAT_INC(name) \ VNET_PCPUSTAT_ADD(struct ipsecstat, ipsec4stat, name, 1) #define V_ip4_esp_trans_deflev VNET(ip4_esp_trans_deflev) diff --git a/sys/netipsec/xform_ah.c b/sys/netipsec/xform_ah.c index bd6ee7d22a19..eddc682d772b 100644 --- a/sys/netipsec/xform_ah.c +++ b/sys/netipsec/xform_ah.c @@ -109,7 +109,6 @@ SYSCTL_VNET_PCPUSTAT(_net_inet_ah, IPSECCTL_STATS, stats, struct ahstat, static unsigned char ipseczeroes[256]; /* larger than an ip6 extension hdr */ static struct timeval md5warn, ripewarn, kpdkmd5warn, kpdksha1warn; -static struct timeval warninterval = { .tv_sec = 1, .tv_usec = 0 }; static int ah_input_cb(struct cryptop*); static int ah_output_cb(struct cryptop*); @@ -189,19 +188,19 @@ ah_init0(struct secasvar *sav, struct xformsw *xsp, struct cryptoini *cria) switch (sav->alg_auth) { case SADB_AALG_MD5HMAC: - if (ratecheck(&md5warn, &warninterval)) + if (ratecheck(&md5warn, &ipsec_warn_interval)) gone_in(13, "MD5-HMAC authenticator for IPsec"); break; case SADB_X_AALG_RIPEMD160HMAC: - if (ratecheck(&ripewarn, &warninterval)) + if (ratecheck(&ripewarn, &ipsec_warn_interval)) gone_in(13, "RIPEMD160-HMAC authenticator for IPsec"); break; case SADB_X_AALG_MD5: - if (ratecheck(&kpdkmd5warn, &warninterval)) + if (ratecheck(&kpdkmd5warn, &ipsec_warn_interval)) gone_in(13, "Keyed-MD5 authenticator for IPsec"); break; case SADB_X_AALG_SHA: - if (ratecheck(&kpdksha1warn, &warninterval)) + if (ratecheck(&kpdksha1warn, &ipsec_warn_interval)) gone_in(13, "Keyed-SHA1 authenticator for IPsec"); break; } diff --git a/sys/netipsec/xform_esp.c b/sys/netipsec/xform_esp.c index dc5a10bacc63..18bd926c5b5f 100644 --- a/sys/netipsec/xform_esp.c +++ b/sys/netipsec/xform_esp.c @@ -95,7 +95,6 @@ SYSCTL_VNET_PCPUSTAT(_net_inet_esp, IPSECCTL_STATS, stats, "ESP statistics (struct espstat, netipsec/esp_var.h"); static struct timeval deswarn, blfwarn, castwarn, camelliawarn; -static struct timeval warninterval = { .tv_sec = 1, .tv_usec = 0 }; static int esp_input_cb(struct cryptop *op); static int esp_output_cb(struct cryptop *crp); @@ -162,19 +161,19 @@ esp_init(struct secasvar *sav, struct xformsw *xsp) switch (sav->alg_enc) { case SADB_EALG_DESCBC: - if (ratecheck(&deswarn, &warninterval)) + if (ratecheck(&deswarn, &ipsec_warn_interval)) gone_in(13, "DES cipher for IPsec"); break; case SADB_X_EALG_BLOWFISHCBC: - if (ratecheck(&blfwarn, &warninterval)) + if (ratecheck(&blfwarn, &ipsec_warn_interval)) gone_in(13, "Blowfish cipher for IPsec"); break; case SADB_X_EALG_CAST128CBC: - if (ratecheck(&castwarn, &warninterval)) + if (ratecheck(&castwarn, &ipsec_warn_interval)) gone_in(13, "CAST cipher for IPsec"); break; case SADB_X_EALG_CAMELLIACBC: - if (ratecheck(&camelliawarn, &warninterval)) + if (ratecheck(&camelliawarn, &ipsec_warn_interval)) gone_in(13, "Camellia cipher for IPsec"); break; } diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 97c826f77911..a3a1e512d8cd 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c index df055fbc26d0..532dee8642b0 100644 --- a/sys/opencrypto/cryptodev.c +++ b/sys/opencrypto/cryptodev.c @@ -294,6 +294,11 @@ struct fcrypt { int sesn; }; +static struct timeval warninterval = { .tv_sec = 60, .tv_usec = 0 }; +SYSCTL_TIMEVAL_SEC(_kern, OID_AUTO, cryptodev_warn_interval, CTLFLAG_RW, + &warninterval, + "Delay in seconds between warnings of deprecated /dev/crypto algorithms"); + static int cryptof_ioctl(struct file *, u_long, void *, struct ucred *, struct thread *); static int cryptof_stat(struct file *, struct stat *, @@ -386,6 +391,8 @@ cryptof_ioctl( struct crypt_op copc; struct crypt_kop kopc; #endif + static struct timeval arc4warn, blfwarn, castwarn, deswarn, md5warn; + static struct timeval skipwarn, tdeswarn; switch (cmd) { case CIOCGSESSION: @@ -406,18 +413,28 @@ cryptof_ioctl( case 0: break; case CRYPTO_DES_CBC: + if (ratecheck(&deswarn, &warninterval)) + gone_in(13, "DES cipher via /dev/crypto"); txform = &enc_xform_des; break; case CRYPTO_3DES_CBC: + if (ratecheck(&tdeswarn, &warninterval)) + gone_in(13, "3DES cipher via /dev/crypto"); txform = &enc_xform_3des; break; case CRYPTO_BLF_CBC: + if (ratecheck(&blfwarn, &warninterval)) + gone_in(13, "Blowfish cipher via /dev/crypto"); txform = &enc_xform_blf; break; case CRYPTO_CAST_CBC: + if (ratecheck(&castwarn, &warninterval)) + gone_in(13, "CAST128 cipher via /dev/crypto"); txform = &enc_xform_cast5; break; case CRYPTO_SKIPJACK_CBC: + if (ratecheck(&skipwarn, &warninterval)) + gone_in(13, "Skipjack cipher via /dev/crypto"); txform = &enc_xform_skipjack; break; case CRYPTO_AES_CBC: @@ -430,6 +447,8 @@ cryptof_ioctl( txform = &enc_xform_null; break; case CRYPTO_ARC4: + if (ratecheck(&arc4warn, &warninterval)) + gone_in(13, "ARC4 cipher via /dev/crypto"); txform = &enc_xform_arc4; break; case CRYPTO_CAMELLIA_CBC: @@ -458,6 +477,9 @@ cryptof_ioctl( case 0: break; case CRYPTO_MD5_HMAC: + if (ratecheck(&md5warn, &warninterval)) + gone_in(13, + "MD5-HMAC authenticator via /dev/crypto"); thash = &auth_hash_hmac_md5; break; case CRYPTO_POLY1305: diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c index d4c88eb8941f..30cf21120572 100644 --- a/sys/powerpc/aim/mmu_oea.c +++ b/sys/powerpc/aim/mmu_oea.c @@ -749,7 +749,7 @@ moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend) } while (pa < end); } - if (sizeof(phys_avail)/sizeof(phys_avail[0]) < regions_sz) + if (nitems(phys_avail) < regions_sz) panic("moea_bootstrap: phys_avail too small"); phys_avail_count = 0; diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c index ae285b72e80e..2227c85e682d 100644 --- a/sys/powerpc/aim/mmu_oea64.c +++ b/sys/powerpc/aim/mmu_oea64.c @@ -638,7 +638,7 @@ moea64_setup_direct_map(mmu_t mmup, vm_offset_t kernelstart, { struct pvo_entry *pvo; register_t msr; - vm_paddr_t pa; + vm_paddr_t pa, pkernelstart, pkernelend; vm_offset_t size, off; uint64_t pte_lo; int i; @@ -684,11 +684,21 @@ moea64_setup_direct_map(mmu_t mmup, vm_offset_t kernelstart, * without a direct map or on which the kernel is not already executing * out of the direct-mapped region. */ - - if (!hw_direct_map || kernelstart < DMAP_BASE_ADDRESS) { + if (kernelstart < DMAP_BASE_ADDRESS) { + /* + * For pre-dmap execution, we need to use identity mapping + * because we will be operating with the mmu on but in the + * wrong address configuration until we __restartkernel(). + */ for (pa = kernelstart & ~PAGE_MASK; pa < kernelend; pa += PAGE_SIZE) moea64_kenter(mmup, pa, pa); + } else if (!hw_direct_map) { + pkernelstart = kernelstart & ~DMAP_BASE_ADDRESS; + pkernelend = kernelend & ~DMAP_BASE_ADDRESS; + for (pa = pkernelstart & ~PAGE_MASK; pa < pkernelend; + pa += PAGE_SIZE) + moea64_kenter(mmup, pa | DMAP_BASE_ADDRESS, pa); } if (!hw_direct_map) { @@ -696,6 +706,10 @@ moea64_setup_direct_map(mmu_t mmup, vm_offset_t kernelstart, off = (vm_offset_t)(moea64_bpvo_pool); for (pa = off; pa < off + size; pa += PAGE_SIZE) moea64_kenter(mmup, pa, pa); + + /* Map exception vectors */ + for (pa = EXC_RSVD; pa < EXC_LAST; pa += PAGE_SIZE) + moea64_kenter(mmup, pa | DMAP_BASE_ADDRESS, pa); } ENABLE_TRANS(msr); @@ -762,7 +776,7 @@ moea64_early_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelen mem_regions(&pregions, &pregions_sz, ®ions, ®ions_sz); CTR0(KTR_PMAP, "moea64_bootstrap: physical memory"); - if (sizeof(phys_avail)/sizeof(phys_avail[0]) < regions_sz) + if (nitems(phys_avail) < regions_sz) panic("moea64_bootstrap: phys_avail too small"); phys_avail_count = 0; @@ -875,7 +889,7 @@ moea64_mid_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend) * Initialise the bootstrap pvo pool. */ moea64_bpvo_pool = (struct pvo_entry *)moea64_bootstrap_alloc( - moea64_bpvo_pool_size*sizeof(struct pvo_entry), 0); + moea64_bpvo_pool_size*sizeof(struct pvo_entry), PAGE_SIZE); moea64_bpvo_pool_index = 0; /* Place at address usable through the direct map */ @@ -1169,15 +1183,19 @@ moea64_unwire(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva) */ static __inline -void moea64_set_scratchpage_pa(mmu_t mmup, int which, vm_paddr_t pa) { +void moea64_set_scratchpage_pa(mmu_t mmup, int which, vm_paddr_t pa) +{ + struct pvo_entry *pvo; KASSERT(!hw_direct_map, ("Using OEA64 scratchpage with a direct map!")); mtx_assert(&moea64_scratchpage_mtx, MA_OWNED); - moea64_scratchpage_pvo[which]->pvo_pte.pa = + pvo = moea64_scratchpage_pvo[which]; + PMAP_LOCK(pvo->pvo_pmap); + pvo->pvo_pte.pa = moea64_calc_wimg(pa, VM_MEMATTR_DEFAULT) | (uint64_t)pa; - MOEA64_PTE_REPLACE(mmup, moea64_scratchpage_pvo[which], - MOEA64_PTE_INVALIDATE); + MOEA64_PTE_REPLACE(mmup, pvo, MOEA64_PTE_INVALIDATE); + PMAP_UNLOCK(pvo->pvo_pmap); isync(); } diff --git a/sys/powerpc/aim/mmu_oea64.h b/sys/powerpc/aim/mmu_oea64.h index 12ed3bd1e4b5..d791c0fbba0a 100644 --- a/sys/powerpc/aim/mmu_oea64.h +++ b/sys/powerpc/aim/mmu_oea64.h @@ -81,6 +81,7 @@ extern u_int moea64_pte_overflow; extern int moea64_large_page_shift; extern uint64_t moea64_large_page_size; +extern uint64_t moea64_large_page_mask; extern u_long moea64_pteg_count; extern u_long moea64_pteg_mask; extern int n_slbs; diff --git a/sys/powerpc/aim/slb.c b/sys/powerpc/aim/slb.c index 0f6e356a9e3d..fdb429ccb0a8 100644 --- a/sys/powerpc/aim/slb.c +++ b/sys/powerpc/aim/slb.c @@ -47,6 +47,9 @@ #include #include #include +#include + +#include "mmu_oea64.h" uintptr_t moea64_get_unique_vsid(void); void moea64_release_vsid(uint64_t vsid); @@ -500,10 +503,12 @@ slb_uma_real_alloc(uma_zone_t zone, vm_size_t bytes, int domain, if (m == NULL) return (NULL); - va = (void *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)); - - if (!hw_direct_map) + if (hw_direct_map) + va = (void *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)); + else { + va = (void *)(VM_PAGE_TO_PHYS(m) | DMAP_BASE_ADDRESS); pmap_kenter((vm_offset_t)va, VM_PAGE_TO_PHYS(m)); + } if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0) bzero(va, PAGE_SIZE); @@ -538,3 +543,86 @@ slb_free_user_cache(struct slb **slb) { uma_zfree(slb_cache_zone, slb); } + +#if defined(__powerpc64__) +/* Handle kernel SLB faults -- runs in real mode, all seat belts off */ +void +handle_kernel_slb_spill(int type, register_t dar, register_t srr0) +{ + struct slb *slbcache; + uint64_t slbe, slbv; + uint64_t esid, addr; + int i; + + addr = (type == EXC_ISE) ? srr0 : dar; + slbcache = PCPU_GET(aim.slb); + esid = (uintptr_t)addr >> ADDR_SR_SHFT; + slbe = (esid << SLBE_ESID_SHIFT) | SLBE_VALID; + + /* See if the hardware flushed this somehow (can happen in LPARs) */ + for (i = 0; i < n_slbs; i++) + if (slbcache[i].slbe == (slbe | (uint64_t)i)) + return; + + /* Not in the map, needs to actually be added */ + slbv = kernel_va_to_slbv(addr); + if (slbcache[USER_SLB_SLOT].slbe == 0) { + for (i = 0; i < n_slbs; i++) { + if (i == USER_SLB_SLOT) + continue; + if (!(slbcache[i].slbe & SLBE_VALID)) + goto fillkernslb; + } + + if (i == n_slbs) + slbcache[USER_SLB_SLOT].slbe = 1; + } + + /* Sacrifice a random SLB entry that is not the user entry */ + i = mftb() % n_slbs; + if (i == USER_SLB_SLOT) + i = (i+1) % n_slbs; + +fillkernslb: + /* Write new entry */ + slbcache[i].slbv = slbv; + slbcache[i].slbe = slbe | (uint64_t)i; + + /* Trap handler will restore from cache on exit */ +} + +int +handle_user_slb_spill(pmap_t pm, vm_offset_t addr) +{ + struct slb *user_entry; + uint64_t esid; + int i; + + if (pm->pm_slb == NULL) + return (-1); + + esid = (uintptr_t)addr >> ADDR_SR_SHFT; + + PMAP_LOCK(pm); + user_entry = user_va_to_slb_entry(pm, addr); + + if (user_entry == NULL) { + /* allocate_vsid auto-spills it */ + (void)allocate_user_vsid(pm, esid, 0); + } else { + /* + * Check that another CPU has not already mapped this. + * XXX: Per-thread SLB caches would be better. + */ + for (i = 0; i < pm->pm_slb_len; i++) + if (pm->pm_slb[i] == user_entry) + break; + + if (i == pm->pm_slb_len) + slb_insert_user(pm, user_entry); + } + PMAP_UNLOCK(pm); + + return (0); +} +#endif diff --git a/sys/powerpc/include/slb.h b/sys/powerpc/include/slb.h index 222e281afdb9..f93280030f94 100644 --- a/sys/powerpc/include/slb.h +++ b/sys/powerpc/include/slb.h @@ -79,4 +79,8 @@ struct slb { uint64_t slbe; }; +struct pmap; +void handle_kernel_slb_spill(int, register_t, register_t); +int handle_user_slb_spill(struct pmap *pm, vm_offset_t addr); + #endif /* !_MACHINE_SLB_H_ */ diff --git a/sys/powerpc/ofw/ofw_initrd.c b/sys/powerpc/ofw/ofw_initrd.c index 7befd989f990..c1038fc4573b 100644 --- a/sys/powerpc/ofw/ofw_initrd.c +++ b/sys/powerpc/ofw/ofw_initrd.c @@ -43,62 +43,32 @@ __FBSDID("$FreeBSD$"); #include "opt_md.h" -#ifdef MD_ROOT_MEM extern u_char *mfs_root; -extern uint32_t mfs_root_size; -#else -#warning "MD_ROOT_MEM should be set to use ofw initrd as a md device" -#endif +extern int mfs_root_size; -/* bus entry points */ -static int ofw_initrd_probe(device_t dev); -static int ofw_initrd_attach(device_t dev); -static void ofw_initrd_identify(driver_t *driver, device_t parent); +static void ofw_initrd_probe_and_attach(void *junk); -struct ofw_initrd_softc { - device_t sc_dev; - vm_paddr_t start; - vm_paddr_t end; -}; +SYSINIT(ofw_initrd_probe_and_attach, SI_SUB_KMEM, SI_ORDER_ANY, + ofw_initrd_probe_and_attach, NULL); -static int -ofw_initrd_probe(device_t dev) +static void +ofw_initrd_probe_and_attach(void *junk) { phandle_t chosen; - - /* limit this device to one unit */ - if (device_get_unit(dev) != 0) - return (ENXIO); - - chosen = OF_finddevice("/chosen"); - if (chosen <= 0) { - return (ENXIO); - } - - if (!OF_hasprop(chosen, "linux,initrd-start") || - !OF_hasprop(chosen, "linux,initrd-end")) - return (ENXIO); - - device_set_desc(dev, "OFW initrd memregion loader"); - return (BUS_PROBE_DEFAULT); -} - -static int -ofw_initrd_attach(device_t dev) -{ - struct ofw_initrd_softc *sc; vm_paddr_t start, end; - phandle_t chosen; pcell_t cell[2]; ssize_t size; - sc = device_get_softc(dev); + if (!hw_direct_map) + return; chosen = OF_finddevice("/chosen"); - if (chosen <= 0) { - device_printf(dev, "/chosen not found\n"); - return (ENXIO); - } + if (chosen <= 0) + return; + + if (!OF_hasprop(chosen, "linux,initrd-start") || + !OF_hasprop(chosen, "linux,initrd-end")) + return; size = OF_getencprop(chosen, "linux,initrd-start", cell, sizeof(cell)); if (size == 4) @@ -106,8 +76,8 @@ ofw_initrd_attach(device_t dev) else if (size == 8) start = (uint64_t)cell[0] << 32 | cell[1]; else { - device_printf(dev, "Wrong linux,initrd-start size\n"); - return (ENXIO); + printf("ofw_initrd: Wrong linux,initrd-start size\n"); + return; } size = OF_getencprop(chosen, "linux,initrd-end", cell, sizeof(cell)); @@ -116,44 +86,15 @@ ofw_initrd_attach(device_t dev) else if (size == 8) end = (uint64_t)cell[0] << 32 | cell[1]; else{ - device_printf(dev, "Wrong linux,initrd-end size\n"); - return (ENXIO); + printf("ofw_initrd: Wrong linux,initrd-end size\n"); + return; } if (end - start > 0) { mfs_root = (u_char *) PHYS_TO_DMAP(start); mfs_root_size = end - start; - - return (0); + printf("ofw_initrd: initrd loaded at 0x%08lx-0x%08lx\n", + start, end); } - - return (ENXIO); } -static void -ofw_initrd_identify(driver_t *driver, device_t parent) -{ - if (device_find_child(parent, "initrd", -1) != NULL) - return; - - if (BUS_ADD_CHILD(parent, 10, "initrd", -1) == NULL) - device_printf(parent, "add ofw_initrd child failed\n"); -} - -static device_method_t ofw_initrd_methods[] = { - DEVMETHOD(device_identify, ofw_initrd_identify), - DEVMETHOD(device_probe, ofw_initrd_probe), - DEVMETHOD(device_attach, ofw_initrd_attach), - DEVMETHOD_END -}; - -static driver_t ofw_initrd_driver = { - "ofw_initrd", - ofw_initrd_methods, - sizeof(struct ofw_initrd_softc) -}; - -static devclass_t ofw_initrd_devclass; - -DRIVER_MODULE(ofw_initrd, ofwbus, ofw_initrd_driver, ofw_initrd_devclass, - NULL, NULL); diff --git a/sys/powerpc/ofw/ofw_pcibus.c b/sys/powerpc/ofw/ofw_pcibus.c index 9c4f45d1c1df..4d0d6de4e12a 100644 --- a/sys/powerpc/ofw/ofw_pcibus.c +++ b/sys/powerpc/ofw/ofw_pcibus.c @@ -294,7 +294,7 @@ ofw_pcibus_child_deleted(device_t dev, device_t child) { struct ofw_pcibus_devinfo *dinfo; - dinfo = device_get_ivars(dev); + dinfo = device_get_ivars(child); ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo); pci_child_deleted(dev, child); } diff --git a/sys/powerpc/powernv/opal_hmi.c b/sys/powerpc/powernv/opal_hmi.c index e811a23d30bb..13b84ed10d23 100644 --- a/sys/powerpc/powernv/opal_hmi.c +++ b/sys/powerpc/powernv/opal_hmi.c @@ -28,8 +28,10 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include +#include #include #include @@ -38,6 +40,47 @@ __FBSDID("$FreeBSD$"); #include #include "opal.h" +struct opal_hmi_event { + uint8_t version; + uint8_t severity; + uint8_t type; + uint8_t disposition; + uint8_t rsvd_1[4]; + uint64_t hmer; + uint64_t tfmr; + union { + struct { + uint8_t xstop_type; + uint8_t rsvd_2[3]; + uint32_t xstop_reason; + union { + uint32_t pir; + uint32_t chip_id; + }; + }; + }; +}; + +#define HMI_DISP_RECOVERED 0 +#define HMI_DISP_NOT_RECOVERED 1 + +static void +opal_hmi_event_handler(void *unused, struct opal_msg *msg) +{ + struct opal_hmi_event evt; + + memcpy(&evt, &msg->params, sizeof(evt)); + printf("Hypervisor Maintenance Event received" + "(Severity %d, type %d, HMER: %016lx).\n", + evt.severity, evt.type, evt.hmer); + + if (evt.disposition == HMI_DISP_NOT_RECOVERED) + panic("Unrecoverable hypervisor maintenance exception on CPU %d", + evt.pir); + + return; +} + static int opal_hmi_handler(struct trapframe *frame) { @@ -69,8 +112,11 @@ opal_setup_hmi(void *data) return; } + EVENTHANDLER_REGISTER(OPAL_HMI_EVT, opal_hmi_event_handler, NULL, + EVENTHANDLER_PRI_ANY); + if (bootverbose) printf("Installed OPAL HMI handler.\n"); } -SYSINIT(opal_setup_hmi, SI_SUB_HYPERVISOR, SI_ORDER_ANY, opal_setup_hmi, NULL); +SYSINIT(opal_setup_hmi, SI_SUB_CPU, SI_ORDER_ANY, opal_setup_hmi, NULL); diff --git a/sys/powerpc/powernv/opal_sensor.c b/sys/powerpc/powernv/opal_sensor.c index 832c6b89f34f..57eb9eefa494 100644 --- a/sys/powerpc/powernv/opal_sensor.c +++ b/sys/powerpc/powernv/opal_sensor.c @@ -92,13 +92,14 @@ const char *opal_sensor_types[] = { * Retrieve the raw value from OPAL. This will be cooked by the sysctl handler. */ static int -opal_sensor_get_val(uint32_t key, uint64_t *val) +opal_sensor_get_val(struct opal_sensor_softc *sc, uint32_t key, uint64_t *val) { struct opal_msg msg; uint32_t val32; int rv, token; token = opal_alloc_async_token(); + SENSOR_LOCK(sc); rv = opal_call(OPAL_SENSOR_READ, key, token, vtophys(&val32)); if (rv == OPAL_ASYNC_COMPLETION) { @@ -110,6 +111,7 @@ opal_sensor_get_val(uint32_t key, uint64_t *val) if (rv == OPAL_SUCCESS) val32 = msg.params[0]; } + SENSOR_UNLOCK(sc); if (rv == OPAL_SUCCESS) *val = val32; @@ -131,9 +133,7 @@ opal_sensor_sysctl(SYSCTL_HANDLER_ARGS) sc = arg1; sensor = arg2; - SENSOR_LOCK(sc); - error = opal_sensor_get_val(sensor, &sensval); - SENSOR_UNLOCK(sc); + error = opal_sensor_get_val(sc, sensor, &sensval); if (error) return (error); diff --git a/sys/powerpc/powerpc/trap.c b/sys/powerpc/powerpc/trap.c index f901015f5e94..0200c7bbd142 100644 --- a/sys/powerpc/powerpc/trap.c +++ b/sys/powerpc/powerpc/trap.c @@ -69,9 +69,10 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include +#include #include #include +#include /* Below matches setjmp.S */ #define FAULTBUF_LR 21 @@ -92,9 +93,6 @@ static int handle_onfault(struct trapframe *frame); static void syscall(struct trapframe *frame); #if defined(__powerpc64__) && defined(AIM) - void handle_kernel_slb_spill(int, register_t, register_t); -static int handle_user_slb_spill(pmap_t pm, vm_offset_t addr); -extern int n_slbs; static void normalize_inputs(void); #endif @@ -721,89 +719,6 @@ syscall(struct trapframe *frame) syscallret(td, error); } -#if defined(__powerpc64__) && defined(AIM) -/* Handle kernel SLB faults -- runs in real mode, all seat belts off */ -void -handle_kernel_slb_spill(int type, register_t dar, register_t srr0) -{ - struct slb *slbcache; - uint64_t slbe, slbv; - uint64_t esid, addr; - int i; - - addr = (type == EXC_ISE) ? srr0 : dar; - slbcache = PCPU_GET(aim.slb); - esid = (uintptr_t)addr >> ADDR_SR_SHFT; - slbe = (esid << SLBE_ESID_SHIFT) | SLBE_VALID; - - /* See if the hardware flushed this somehow (can happen in LPARs) */ - for (i = 0; i < n_slbs; i++) - if (slbcache[i].slbe == (slbe | (uint64_t)i)) - return; - - /* Not in the map, needs to actually be added */ - slbv = kernel_va_to_slbv(addr); - if (slbcache[USER_SLB_SLOT].slbe == 0) { - for (i = 0; i < n_slbs; i++) { - if (i == USER_SLB_SLOT) - continue; - if (!(slbcache[i].slbe & SLBE_VALID)) - goto fillkernslb; - } - - if (i == n_slbs) - slbcache[USER_SLB_SLOT].slbe = 1; - } - - /* Sacrifice a random SLB entry that is not the user entry */ - i = mftb() % n_slbs; - if (i == USER_SLB_SLOT) - i = (i+1) % n_slbs; - -fillkernslb: - /* Write new entry */ - slbcache[i].slbv = slbv; - slbcache[i].slbe = slbe | (uint64_t)i; - - /* Trap handler will restore from cache on exit */ -} - -static int -handle_user_slb_spill(pmap_t pm, vm_offset_t addr) -{ - struct slb *user_entry; - uint64_t esid; - int i; - - if (pm->pm_slb == NULL) - return (-1); - - esid = (uintptr_t)addr >> ADDR_SR_SHFT; - - PMAP_LOCK(pm); - user_entry = user_va_to_slb_entry(pm, addr); - - if (user_entry == NULL) { - /* allocate_vsid auto-spills it */ - (void)allocate_user_vsid(pm, esid, 0); - } else { - /* - * Check that another CPU has not already mapped this. - * XXX: Per-thread SLB caches would be better. - */ - for (i = 0; i < pm->pm_slb_len; i++) - if (pm->pm_slb[i] == user_entry) - break; - - if (i == pm->pm_slb_len) - slb_insert_user(pm, user_entry); - } - PMAP_UNLOCK(pm); - - return (0); -} -#endif - static int trap_pfault(struct trapframe *frame, int user) { diff --git a/sys/powerpc/pseries/mmu_phyp.c b/sys/powerpc/pseries/mmu_phyp.c index cabefedf1fa7..ab78df15defc 100644 --- a/sys/powerpc/pseries/mmu_phyp.c +++ b/sys/powerpc/pseries/mmu_phyp.c @@ -59,6 +59,16 @@ __FBSDID("$FreeBSD$"); #include "phyp-hvcall.h" +#define MMU_PHYP_DEBUG 0 +#define MMU_PHYP_ID "mmu_phyp: " +#if MMU_PHYP_DEBUG +#define dprintf(fmt, ...) printf(fmt, ## __VA_ARGS__) +#define dprintf0(fmt, ...) dprintf(MMU_PHYP_ID fmt, ## __VA_ARGS__) +#else +#define dprintf(fmt, args...) do { ; } while(0) +#define dprintf0(fmt, args...) do { ; } while(0) +#endif + static struct rmlock mphyp_eviction_lock; /* @@ -149,6 +159,7 @@ mphyp_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend) res = OF_getencprop(node, "ibm,slb-size", prop, sizeof(prop[0])); if (res > 0) n_slbs = prop[0]; + dprintf0("slb-size=%i\n", n_slbs); moea64_pteg_count = final_pteg_count / sizeof(struct lpteg); @@ -185,11 +196,22 @@ mphyp_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend) shift = arr[idx]; slb_encoding = arr[idx + 1]; nptlp = arr[idx + 2]; + + dprintf0("Segment Page Size: " + "%uKB, slb_enc=0x%X: {size, encoding}[%u] =", + shift > 10? 1 << (shift-10) : 0, + slb_encoding, nptlp); + idx += 3; len -= 3; while (len > 0 && nptlp) { lp_size = arr[idx]; lp_encoding = arr[idx+1]; + + dprintf(" {%uKB, 0x%X}", + lp_size > 10? 1 << (lp_size-10) : 0, + lp_encoding); + if (slb_encoding == SLBV_L && lp_encoding == 0) break; @@ -197,17 +219,28 @@ mphyp_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend) len -= 2; nptlp--; } + dprintf("\n"); if (nptlp && slb_encoding == SLBV_L && lp_encoding == 0) break; } - if (len == 0) - panic("Standard large pages (SLB[L] = 1, PTE[LP] = 0) " - "not supported by this system. Please enable huge " - "page backing if running under PowerKVM."); - - moea64_large_page_shift = shift; - moea64_large_page_size = 1ULL << lp_size; + if (len > 0) { + moea64_large_page_shift = shift; + moea64_large_page_size = 1ULL << lp_size; + moea64_large_page_mask = moea64_large_page_size - 1; + hw_direct_map = 1; + printf(MMU_PHYP_ID + "Support for hugepages of %uKB detected\n", + moea64_large_page_shift > 10? + 1 << (moea64_large_page_shift-10) : 0); + } else { + moea64_large_page_size = 0; + moea64_large_page_shift = 0; + moea64_large_page_mask = 0; + hw_direct_map = 0; + printf(MMU_PHYP_ID + "Support for hugepages not found\n"); + } } moea64_mid_bootstrap(mmup, kernelstart, kernelend); diff --git a/sys/powerpc/pseries/xics.c b/sys/powerpc/pseries/xics.c index b5b54be90090..f65a68861bf1 100644 --- a/sys/powerpc/pseries/xics.c +++ b/sys/powerpc/pseries/xics.c @@ -324,7 +324,7 @@ xicp_bind(device_t dev, u_int irq, cpuset_t cpumask, void **priv) struct xicp_softc *sc = device_get_softc(dev); struct xicp_intvec *iv; cell_t status, cpu; - int ncpus, i, error; + int ncpus, i, error = -1; /* Ignore IPIs */ if (irq == MAX_XICP_IRQS) diff --git a/sys/riscv/conf/GENERIC b/sys/riscv/conf/GENERIC index 7c2571f4783b..559e9166daa9 100644 --- a/sys/riscv/conf/GENERIC +++ b/sys/riscv/conf/GENERIC @@ -22,11 +22,7 @@ cpu RISCV ident GENERIC makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols -# makeoptions WITH_CTF=1 # Run ctfconvert(1) for DTrace support - -# FIXME: linker error. "--relax and -r may not be used together" -makeoptions WITHOUT_MODULES="usb otusfw mwlfw ispfw mwlfw ralfw rtwnfw" -# makeoptions NO_MODULES +makeoptions WITH_CTF=1 # Run ctfconvert(1) for DTrace support options SCHED_ULE # ULE scheduler options PREEMPTION # Enable kernel thread preemption @@ -52,11 +48,11 @@ options CD9660 # ISO 9660 Filesystem options PROCFS # Process filesystem (requires PSEUDOFS) options PSEUDOFS # Pseudo-filesystem framework options GEOM_PART_GPT # GUID Partition Tables. -# options GEOM_RAID # Soft RAID functionality. +options GEOM_RAID # Soft RAID functionality. options GEOM_LABEL # Provides labelization options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI options KTRACE # ktrace(1) support -# options STACK # stack(9) support +options STACK # stack(9) support options SYSVSHM # SYSV-style shared memory options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores diff --git a/sys/riscv/include/asm.h b/sys/riscv/include/asm.h index 87736980cdc0..5fd84cfa423d 100644 --- a/sys/riscv/include/asm.h +++ b/sys/riscv/include/asm.h @@ -59,7 +59,7 @@ .set alias,sym #define SET_FAULT_HANDLER(handler, tmp) \ - ld tmp, PC_CURTHREAD(gp); \ + ld tmp, PC_CURTHREAD(tp); \ ld tmp, TD_PCB(tmp); /* Load the pcb */ \ sd handler, PCB_ONFAULT(tmp) /* Set the handler */ diff --git a/sys/riscv/include/elf.h b/sys/riscv/include/elf.h index 01e647a79113..671e2d2617c0 100644 --- a/sys/riscv/include/elf.h +++ b/sys/riscv/include/elf.h @@ -74,4 +74,15 @@ __ElfType(Auxinfo); /* TODO: set correct value */ #define ET_DYN_LOAD_ADDR 0x100000 +/* Flags passed in AT_HWCAP */ +#define HWCAP_ISA_BIT(c) (1 << ((c) - 'A')) +#define HWCAP_ISA_I HWCAP_ISA_BIT('I') +#define HWCAP_ISA_M HWCAP_ISA_BIT('M') +#define HWCAP_ISA_A HWCAP_ISA_BIT('A') +#define HWCAP_ISA_F HWCAP_ISA_BIT('F') +#define HWCAP_ISA_D HWCAP_ISA_BIT('D') +#define HWCAP_ISA_C HWCAP_ISA_BIT('C') +#define HWCAP_ISA_G \ + (HWCAP_ISA_I | HWCAP_ISA_M | HWCAP_ISA_A | HWCAP_ISA_F | HWCAP_ISA_D) + #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/riscv/include/md_var.h b/sys/riscv/include/md_var.h index 85455910ee75..22ef837ffe53 100644 --- a/sys/riscv/include/md_var.h +++ b/sys/riscv/include/md_var.h @@ -38,6 +38,7 @@ extern char sigcode[]; extern int szsigcode; extern uint64_t *vm_page_dump; extern int vm_page_dump_size; +extern u_long elf_hwcap; struct dumperinfo; diff --git a/sys/riscv/include/pcpu.h b/sys/riscv/include/pcpu.h index 0f04db0a5efb..28c5a7422d1c 100644 --- a/sys/riscv/include/pcpu.h +++ b/sys/riscv/include/pcpu.h @@ -60,7 +60,7 @@ get_pcpu(void) { struct pcpu *pcpu; - __asm __volatile("mv %0, gp" : "=&r"(pcpu)); + __asm __volatile("mv %0, tp" : "=&r"(pcpu)); return (pcpu); } @@ -70,7 +70,7 @@ get_curthread(void) { struct thread *td; - __asm __volatile("ld %0, 0(gp)" : "=&r"(td)); + __asm __volatile("ld %0, 0(tp)" : "=&r"(td)); return (td); } diff --git a/sys/riscv/riscv/elf_machdep.c b/sys/riscv/riscv/elf_machdep.c index 235a96a9f43b..e626b01a39f0 100644 --- a/sys/riscv/riscv/elf_machdep.c +++ b/sys/riscv/riscv/elf_machdep.c @@ -58,6 +58,8 @@ __FBSDID("$FreeBSD$"); #include #include +u_long elf_hwcap; + struct sysentvec elf64_freebsd_sysvec = { .sv_size = SYS_MAXSYSCALL, .sv_table = sysent, @@ -90,6 +92,7 @@ struct sysentvec elf64_freebsd_sysvec = { .sv_schedtail = NULL, .sv_thread_detach = NULL, .sv_trap = NULL, + .sv_hwcap = &elf_hwcap, }; INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec); diff --git a/sys/riscv/riscv/exception.S b/sys/riscv/riscv/exception.S index 399ae098f23a..0adfda72046a 100644 --- a/sys/riscv/riscv/exception.S +++ b/sys/riscv/riscv/exception.S @@ -44,11 +44,18 @@ __FBSDID("$FreeBSD$"); addi sp, sp, -(TF_SIZE) sd ra, (TF_RA)(sp) - sd tp, (TF_TP)(sp) -.if \el == 0 /* We came from userspace. Load our pcpu */ +.if \el == 0 /* We came from userspace. */ sd gp, (TF_GP)(sp) - ld gp, (TF_SIZE)(sp) +.option push +.option norelax + /* Load the kernel's global pointer */ + la gp, __global_pointer$ +.option pop + + /* Load our pcpu */ + sd tp, (TF_TP)(sp) + ld tp, (TF_SIZE)(sp) .endif sd t0, (TF_T + 0 * 8)(sp) @@ -81,16 +88,6 @@ __FBSDID("$FreeBSD$"); sd a6, (TF_A + 6 * 8)(sp) sd a7, (TF_A + 7 * 8)(sp) -#if 0 - /* XXX: temporary test: spin if stack is not kernel one */ -.if \el == 1 /* kernel */ - mv t0, sp - srli t0, t0, 63 -1: - beqz t0, 1b -.endif -#endif - .if \el == 1 /* Store kernel sp */ li t1, TF_SIZE @@ -138,13 +135,15 @@ __FBSDID("$FreeBSD$"); ld t0, (TF_SP)(sp) csrw sscratch, t0 - /* And store our pcpu */ - sd gp, (TF_SIZE)(sp) + /* Store our pcpu */ + sd tp, (TF_SIZE)(sp) + ld tp, (TF_TP)(sp) + + /* And restore the user's global pointer */ ld gp, (TF_GP)(sp) .endif ld ra, (TF_RA)(sp) - ld tp, (TF_TP)(sp) ld t0, (TF_T + 0 * 8)(sp) ld t1, (TF_T + 1 * 8)(sp) @@ -185,7 +184,7 @@ __FBSDID("$FreeBSD$"); 1: csrci sstatus, (SSTATUS_SIE) - ld a1, PC_CURTHREAD(gp) + ld a1, PC_CURTHREAD(tp) lw a2, TD_FLAGS(a1) li a3, (TDF_ASTPENDING|TDF_NEEDRESCHED) diff --git a/sys/riscv/riscv/identcpu.c b/sys/riscv/riscv/identcpu.c index 94ad889e0ed9..ab1adead0162 100644 --- a/sys/riscv/riscv/identcpu.c +++ b/sys/riscv/riscv/identcpu.c @@ -32,18 +32,28 @@ * SUCH DAMAGE. */ +#include "opt_platform.h" + #include __FBSDID("$FreeBSD$"); #include +#include +#include #include #include -#include #include #include +#include +#include #include +#ifdef FDT +#include +#include +#endif + char machine[] = "riscv"; SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, @@ -88,6 +98,84 @@ const struct cpu_implementers cpu_implementers[] = { CPU_IMPLEMENTER_NONE, }; +#ifdef FDT +/* + * The ISA string is made up of a small prefix (e.g. rv64) and up to 26 letters + * indicating the presence of the 26 possible standard extensions. Therefore 32 + * characters will be sufficient. + */ +#define ISA_NAME_MAXLEN 32 +#define ISA_PREFIX ("rv" __XSTRING(__riscv_xlen)) +#define ISA_PREFIX_LEN (sizeof(ISA_PREFIX) - 1) + +static void +fill_elf_hwcap(void *dummy __unused) +{ + u_long caps[256] = {0}; + char isa[ISA_NAME_MAXLEN]; + u_long hwcap; + phandle_t node; + ssize_t len; + int i; + + caps['i'] = caps['I'] = HWCAP_ISA_I; + caps['m'] = caps['M'] = HWCAP_ISA_M; + caps['a'] = caps['A'] = HWCAP_ISA_A; +#ifdef FPE + caps['f'] = caps['F'] = HWCAP_ISA_F; + caps['d'] = caps['D'] = HWCAP_ISA_D; +#endif + caps['c'] = caps['C'] = HWCAP_ISA_C; + + node = OF_finddevice("/cpus"); + if (node == -1) { + if (bootverbose) + printf("fill_elf_hwcap: Can't find cpus node\n"); + return; + } + + /* + * Iterate through the CPUs and examine their ISA string. While we + * could assign elf_hwcap to be whatever the boot CPU supports, to + * handle the (unusual) case of running a system with hetergeneous + * ISAs, keep only the extension bits that are common to all harts. + */ + for (node = OF_child(node); node > 0; node = OF_peer(node)) { + if (!fdt_is_compatible_strict(node, "riscv")) { + if (bootverbose) + printf("fill_elf_hwcap: Can't find cpu\n"); + return; + } + + len = OF_getprop(node, "riscv,isa", isa, sizeof(isa)); + KASSERT(len <= ISA_NAME_MAXLEN, ("ISA string truncated")); + if (len == -1) { + if (bootverbose) + printf("fill_elf_hwcap: " + "Can't find riscv,isa property\n"); + return; + } else if (strncmp(isa, ISA_PREFIX, ISA_PREFIX_LEN) != 0) { + if (bootverbose) + printf("fill_elf_hwcap: " + "Unsupported ISA string: %s\n", isa); + return; + } + + hwcap = 0; + for (i = ISA_PREFIX_LEN; i < len; i++) + hwcap |= caps[(unsigned char)isa[i]]; + + if (elf_hwcap != 0) + elf_hwcap &= hwcap; + else + elf_hwcap = hwcap; + + } +} + +SYSINIT(identcpu, SI_SUB_CPU, SI_ORDER_ANY, fill_elf_hwcap, NULL); +#endif + void identify_cpu(void) { diff --git a/sys/riscv/riscv/locore.S b/sys/riscv/riscv/locore.S index c79b4f4a5c1f..533bfef93fe6 100644 --- a/sys/riscv/riscv/locore.S +++ b/sys/riscv/riscv/locore.S @@ -171,12 +171,18 @@ va: li t0, 0 csrw sscratch, t0 + /* Set the global pointer */ +.option push +.option norelax + la gp, __global_pointer$ +.option pop + /* Initialize stack pointer */ la s3, initstack_end mv sp, s3 addi sp, sp, -PCB_SIZE - /* Clear BSS */ + /* Clear BSS */ la s0, _C_LABEL(__bss_start) la s1, _C_LABEL(_end) 1: @@ -251,12 +257,6 @@ virt_map: hart_lottery: .space 4 - /* Not in use, but required for linking. */ - .align 3 - .globl __global_pointer$ -__global_pointer$: - .space 8 - .globl init_pt_va init_pt_va: .quad pagetable_l2 /* XXX: Keep page tables VA */ @@ -324,6 +324,12 @@ mpva: li t0, 0 csrw sscratch, t0 + /* Set the global pointer */ +.option push +.option norelax + la gp, __global_pointer$ +.option pop + call init_secondary END(mpentry) #endif diff --git a/sys/riscv/riscv/machdep.c b/sys/riscv/riscv/machdep.c index 76f5f6ce89af..a67b99f91f1a 100644 --- a/sys/riscv/riscv/machdep.c +++ b/sys/riscv/riscv/machdep.c @@ -62,7 +62,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -124,22 +126,40 @@ cpuset_t all_harts; extern int *end; extern int *initstack_end; -uintptr_t mcall_trap(uintptr_t mcause, uintptr_t* regs); - -uintptr_t -mcall_trap(uintptr_t mcause, uintptr_t* regs) -{ - - return (0); -} - static void cpu_startup(void *dummy) { identify_cpu(); + printf("real memory = %ju (%ju MB)\n", ptoa((uintmax_t)realmem), + ptoa((uintmax_t)realmem) / (1024 * 1024)); + + /* + * Display any holes after the first chunk of extended memory. + */ + if (bootverbose) { + int indx; + + printf("Physical memory chunk(s):\n"); + for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { + vm_paddr_t size; + + size = phys_avail[indx + 1] - phys_avail[indx]; + printf( + "0x%016jx - 0x%016jx, %ju bytes (%ju pages)\n", + (uintmax_t)phys_avail[indx], + (uintmax_t)phys_avail[indx + 1] - 1, + (uintmax_t)size, (uintmax_t)size / PAGE_SIZE); + } + } + vm_ksubmap_init(&kmi); + + printf("avail memory = %ju (%ju MB)\n", + ptoa((uintmax_t)vm_free_count()), + ptoa((uintmax_t)vm_free_count()) / (1024 * 1024)); + bufinit(); vm_pager_bufferinit(); } @@ -816,13 +836,15 @@ initriscv(struct riscv_bootparams *rvbp) caddr_t kmdp; int i; + TSRAW(&thread0, TS_ENTER, __func__, NULL); + /* Set the pcpu data, this is needed by pmap_bootstrap */ pcpup = &__pcpu[0]; pcpu_init(pcpup, 0, sizeof(struct pcpu)); pcpup->pc_hart = boot_hart; /* Set the pcpu pointer */ - __asm __volatile("mv gp, %0" :: "r"(pcpup)); + __asm __volatile("mv tp, %0" :: "r"(pcpup)); PCPU_SET(curthread, &thread0); @@ -888,6 +910,8 @@ initriscv(struct riscv_bootparams *rvbp) kdb_init(); early_boot = 0; + + TSEXIT(); } #undef bzero diff --git a/sys/riscv/riscv/mp_machdep.c b/sys/riscv/riscv/mp_machdep.c index 3d3dbcc0976e..0f6d22962b6c 100644 --- a/sys/riscv/riscv/mp_machdep.c +++ b/sys/riscv/riscv/mp_machdep.c @@ -234,7 +234,7 @@ init_secondary(uint64_t hart) /* Setup the pcpu pointer */ pcpup = &__pcpu[cpuid]; - __asm __volatile("mv gp, %0" :: "r"(pcpup)); + __asm __volatile("mv tp, %0" :: "r"(pcpup)); /* Workaround: make sure wfi doesn't halt the hart */ csr_set(sie, SIE_SSIE); diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c index 91928a7f04a9..3d9fcdd1f8e9 100644 --- a/sys/riscv/riscv/pmap.c +++ b/sys/riscv/riscv/pmap.c @@ -640,6 +640,7 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen) continue; dump_avail[map_slot] = start; dump_avail[map_slot + 1] = end; + realmem += atop((vm_offset_t)(end - start)); if (start >= kernstart && end <= pa) continue; @@ -1104,12 +1105,15 @@ pmap_add_delayed_free_list(vm_page_t m, struct spglist *free, * of idle page table pages. Each of a pmap's page table pages is responsible * for mapping a distinct range of virtual addresses. The pmap's collection is * ordered by this virtual address range. + * + * If "promoted" is false, then the page table page "ml3" must be zero filled. */ static __inline int -pmap_insert_pt_page(pmap_t pmap, vm_page_t ml3) +pmap_insert_pt_page(pmap_t pmap, vm_page_t ml3, bool promoted) { PMAP_LOCK_ASSERT(pmap, MA_OWNED); + ml3->valid = promoted ? VM_PAGE_BITS_ALL : 0; return (vm_radix_insert(&pmap->pm_root, ml3)); } @@ -1648,7 +1652,7 @@ free_pv_chunk(struct pv_chunk *pc) /* entire chunk is free, return it */ m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pc)); dump_drop_page(m->phys_addr); - vm_page_unwire(m, PQ_NONE); + vm_page_unwire_noq(m); vm_page_free(m); } @@ -2002,9 +2006,11 @@ pmap_remove_kernel_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t va) newl2 = ml3pa | PTE_V; /* - * Initialize the page table page. + * If this page table page was unmapped by a promotion, then it + * contains valid mappings. Zero it to invalidate those mappings. */ - pagezero((void *)PHYS_TO_DMAP(ml3pa)); + if (ml3->valid != 0) + pagezero((void *)PHYS_TO_DMAP(ml3pa)); /* * Demote the mapping. @@ -2064,6 +2070,8 @@ pmap_remove_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t sva, } else { ml3 = pmap_remove_pt_page(pmap, sva); if (ml3 != NULL) { + KASSERT(ml3->valid == VM_PAGE_BITS_ALL, + ("pmap_remove_l2: l3 page not promoted")); pmap_resident_count_dec(pmap, 1); KASSERT(ml3->wire_count == Ln_ENTRIES, ("pmap_remove_l2: l3 page wire count error")); @@ -2482,8 +2490,10 @@ pmap_demote_l2_locked(pmap_t pmap, pd_entry_t *l2, vm_offset_t va, "failure for va %#lx in pmap %p", va, pmap); return (false); } - if (va < VM_MAXUSER_ADDRESS) + if (va < VM_MAXUSER_ADDRESS) { + mpte->wire_count = Ln_ENTRIES; pmap_resident_count_inc(pmap, 1); + } } mptepa = VM_PAGE_TO_PHYS(mpte); firstl3 = (pt_entry_t *)PHYS_TO_DMAP(mptepa); @@ -2495,10 +2505,10 @@ pmap_demote_l2_locked(pmap_t pmap, pd_entry_t *l2, vm_offset_t va, newl3 = oldl2; /* - * If the page table page is new, initialize it. + * If the page table page is not leftover from an earlier promotion, + * initialize it. */ - if (mpte->wire_count == 1) { - mpte->wire_count = Ln_ENTRIES; + if (mpte->valid == 0) { for (i = 0; i < Ln_ENTRIES; i++) pmap_store(firstl3 + i, newl3 + (i << PTE_PPN0_S)); } @@ -2589,7 +2599,7 @@ pmap_promote_l2(pmap_t pmap, pd_entry_t *l2, vm_offset_t va, ml3 = PHYS_TO_VM_PAGE(PTE_TO_PHYS(pmap_load(l2))); KASSERT(ml3->pindex == pmap_l2_pindex(va), ("pmap_promote_l2: page table page's pindex is wrong")); - if (pmap_insert_pt_page(pmap, ml3)) { + if (pmap_insert_pt_page(pmap, ml3, true)) { CTR2(KTR_PMAP, "pmap_promote_l2: failure for va %#lx pmap %p", va, pmap); atomic_add_long(&pmap_l2_p_failures, 1); @@ -2972,15 +2982,13 @@ pmap_enter_l2(pmap_t pmap, vm_offset_t va, pd_entry_t new_l2, u_int flags, } vm_page_free_pages_toq(&free, true); if (va >= VM_MAXUSER_ADDRESS) { + /* + * Both pmap_remove_l2() and pmap_remove_l3() will + * leave the kernel page table page zero filled. + */ mt = PHYS_TO_VM_PAGE(PTE_TO_PHYS(pmap_load(l2))); - if (pmap_insert_pt_page(pmap, mt)) { - /* - * XXX Currently, this can't happen bacuse - * we do not perform pmap_enter(psind == 1) - * on the kernel pmap. - */ + if (pmap_insert_pt_page(pmap, mt, false)) panic("pmap_enter_l2: trie insert failed"); - } } else KASSERT(pmap_load(l2) == 0, ("pmap_enter_l2: non-zero L2 entry %p", l2)); @@ -3557,6 +3565,8 @@ pmap_remove_pages_pv(pmap_t pmap, vm_page_t m, pv_entry_t pv, } mpte = pmap_remove_pt_page(pmap, pv->pv_va); if (mpte != NULL) { + KASSERT(mpte->valid == VM_PAGE_BITS_ALL, + ("pmap_remove_pages: pte page not promoted")); pmap_resident_count_dec(pmap, 1); KASSERT(mpte->wire_count == Ln_ENTRIES, ("pmap_remove_pages: pte page wire count error")); diff --git a/sys/riscv/riscv/swtch.S b/sys/riscv/riscv/swtch.S index b57c0487610b..39213d3d31b9 100644 --- a/sys/riscv/riscv/swtch.S +++ b/sys/riscv/riscv/swtch.S @@ -217,15 +217,14 @@ ENTRY(cpu_throw) mv a0, s0 /* Store the new curthread */ - sd a0, PC_CURTHREAD(gp) + sd a0, PC_CURTHREAD(tp) /* And the new pcb */ ld x13, TD_PCB(a0) - sd x13, PC_CURPCB(gp) + sd x13, PC_CURPCB(tp) /* Load registers */ ld ra, (PCB_RA)(x13) ld sp, (PCB_SP)(x13) - ld tp, (PCB_TP)(x13) /* s[0-11] */ ld s0, (PCB_S + 0 * 8)(x13) @@ -267,10 +266,10 @@ END(cpu_throw) */ ENTRY(cpu_switch) /* Store the new curthread */ - sd a1, PC_CURTHREAD(gp) + sd a1, PC_CURTHREAD(tp) /* And the new pcb */ ld x13, TD_PCB(a1) - sd x13, PC_CURPCB(gp) + sd x13, PC_CURPCB(tp) /* Save the old context. */ ld x13, TD_PCB(a0) @@ -278,7 +277,6 @@ ENTRY(cpu_switch) /* Store ra, sp and the callee-saved registers */ sd ra, (PCB_RA)(x13) sd sp, (PCB_SP)(x13) - sd tp, (PCB_TP)(x13) /* s[0-11] */ sd s0, (PCB_S + 0 * 8)(x13) @@ -340,7 +338,6 @@ ENTRY(cpu_switch) ld x13, TD_PCB(a1) /* Restore the registers */ - ld tp, (PCB_TP)(x13) ld ra, (PCB_RA)(x13) ld sp, (PCB_SP)(x13) @@ -429,15 +426,16 @@ ENTRY(fork_trampoline) ld a6, (TF_A + 6 * 8)(sp) ld a7, (TF_A + 7 * 8)(sp) - /* Load user ra and sp */ + /* Load user ra and gp */ ld ra, (TF_RA)(sp) + ld gp, (TF_GP)(sp) /* * Store our pcpup on stack, we will load it back * on kernel mode trap. */ - sd gp, (TF_SIZE)(sp) - ld gp, (TF_GP)(sp) + sd tp, (TF_SIZE)(sp) + ld tp, (TF_TP)(sp) /* Save kernel stack so we can use it doing a user trap */ addi sp, sp, TF_SIZE @@ -454,6 +452,7 @@ ENTRY(savectx) sd ra, (PCB_RA)(a0) sd sp, (PCB_SP)(a0) sd tp, (PCB_TP)(a0) + sd gp, (PCB_GP)(a0) /* s[0-11] */ sd s0, (PCB_S + 0 * 8)(a0) diff --git a/sys/riscv/riscv/vm_machdep.c b/sys/riscv/riscv/vm_machdep.c index 7bcd13abc47d..f00928e385b1 100644 --- a/sys/riscv/riscv/vm_machdep.c +++ b/sys/riscv/riscv/vm_machdep.c @@ -69,22 +69,11 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) { struct pcb *pcb2; struct trapframe *tf; - register_t val; if ((flags & RFPROC) == 0) return; - if (td1 == curthread) { - /* - * Save the tp. These normally happen in cpu_switch, - * but if userland changes this then forks this may - * not have happened. - */ - __asm __volatile("mv %0, tp" : "=&r"(val)); - td1->td_pcb->pcb_tp = val; - - /* RISCVTODO: save the FPU state here */ - } + /* RISCVTODO: save the FPU state here */ pcb2 = (struct pcb *)(td2->td_kstack + td2->td_kstack_pages * PAGE_SIZE) - 1; @@ -205,15 +194,15 @@ cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg, int cpu_set_user_tls(struct thread *td, void *tls_base) { - struct pcb *pcb; if ((uintptr_t)tls_base >= VM_MAXUSER_ADDRESS) return (EINVAL); - pcb = td->td_pcb; - pcb->pcb_tp = (register_t)tls_base + TP_OFFSET; - if (td == curthread) - __asm __volatile("mv tp, %0" :: "r"(pcb->pcb_tp)); + /* + * The user TLS is set by modifying the trapframe's tp value, which + * will be restored when returning to userspace. + */ + td->td_frame->tf_tp = (register_t)tls_base + TP_OFFSET; return (0); } diff --git a/sys/sys/_termios.h b/sys/sys/_termios.h index 7a68dee99148..fab12cfa4064 100644 --- a/sys/sys/_termios.h +++ b/sys/sys/_termios.h @@ -143,6 +143,7 @@ #define CDTR_IFLOW 0x00040000 /* DTR flow control of input */ #define CDSR_OFLOW 0x00080000 /* DSR flow control of output */ #define CCAR_OFLOW 0x00100000 /* DCD flow control of output */ +#define CNO_RTSDTR 0x00200000 /* Do not assert RTS or DTR automatically */ #endif diff --git a/sys/sys/counter.h b/sys/sys/counter.h index 418141a55867..9960a2c39d8e 100644 --- a/sys/sys/counter.h +++ b/sys/sys/counter.h @@ -43,23 +43,23 @@ void counter_u64_zero(counter_u64_t); uint64_t counter_u64_fetch(counter_u64_t); #define COUNTER_ARRAY_ALLOC(a, n, wait) do { \ - for (int i = 0; i < (n); i++) \ - (a)[i] = counter_u64_alloc(wait); \ + for (int _i = 0; _i < (n); _i++) \ + (a)[_i] = counter_u64_alloc(wait); \ } while (0) #define COUNTER_ARRAY_FREE(a, n) do { \ - for (int i = 0; i < (n); i++) \ - counter_u64_free((a)[i]); \ + for (int _i = 0; _i < (n); _i++) \ + counter_u64_free((a)[_i]); \ } while (0) #define COUNTER_ARRAY_COPY(a, dstp, n) do { \ - for (int i = 0; i < (n); i++) \ - ((uint64_t *)(dstp))[i] = counter_u64_fetch((a)[i]);\ + for (int _i = 0; _i < (n); _i++) \ + ((uint64_t *)(dstp))[_i] = counter_u64_fetch((a)[_i]);\ } while (0) #define COUNTER_ARRAY_ZERO(a, n) do { \ - for (int i = 0; i < (n); i++) \ - counter_u64_zero((a)[i]); \ + for (int _i = 0; _i < (n); _i++) \ + counter_u64_zero((a)[_i]); \ } while (0) /* diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h index 86ae3f2e3998..6232756fa06e 100644 --- a/sys/sys/elf_common.h +++ b/sys/sys/elf_common.h @@ -535,6 +535,10 @@ typedef struct { #define PT_ARM_EXIDX 0x70000001 /* ARM exception unwind tables. */ #define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ +#define PT_OPENBSD_RANDOMIZE 0x65A3DBE6 /* OpenBSD random data segment */ +#define PT_OPENBSD_WXNEEDED 0x65A3DBE7 /* OpenBSD EXEC/WRITE pages needed */ +#define PT_OPENBSD_BOOTDATA 0x65A41BE6 /* OpenBSD section for boot args */ + /* Values for p_flags. */ #define PF_X 0x1 /* Executable. */ #define PF_W 0x2 /* Writable. */ diff --git a/sys/sys/fail.h b/sys/sys/fail.h index b9a14e56281a..1905aee82968 100644 --- a/sys/sys/fail.h +++ b/sys/sys/fail.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2009 Isilon Inc http://www.isilon.com/ + * Copyright (c) 2009-2019 Dell EMC Isilon http://www.isilon.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -191,10 +191,12 @@ fail_point_eval(struct fail_point *fp, int *ret) __END_DECLS /* Declare a fail_point and its sysctl in a function. */ +#define KFAIL_POINT_DECLARE(name) \ + extern struct fail_point _FAIL_POINT_NAME(name) #define _FAIL_POINT_NAME(name) _fail_point_##name #define _FAIL_POINT_LOCATION() "(" __FILE__ ":" __XSTRING(__LINE__) ")" -#define _FAIL_POINT_INIT(parent, name, flags) \ - static struct fail_point _FAIL_POINT_NAME(name) = { \ +#define KFAIL_POINT_DEFINE(parent, name, flags) \ + struct fail_point _FAIL_POINT_NAME(name) = { \ .fp_name = #name, \ .fp_location = _FAIL_POINT_LOCATION(), \ .fp_ref_cnt = 0, \ @@ -213,6 +215,9 @@ __END_DECLS CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, \ &_FAIL_POINT_NAME(name), 0, \ fail_point_sysctl_status, "A", ""); + +#define _FAIL_POINT_INIT(parent, name, flags) \ + static KFAIL_POINT_DEFINE(parent, name, flags) #define _FAIL_POINT_EVAL(name, cond, code...) \ int RETURN_VALUE; \ \ @@ -222,7 +227,8 @@ __END_DECLS code; \ \ } - +#define KFAIL_POINT_EVAL(name, code...) \ + _FAIL_POINT_EVAL(name, true, code) /** * Instantiate a failpoint which returns "RETURN_VALUE" from the function diff --git a/sys/sys/filio.h b/sys/sys/filio.h index 868fe53c2585..e85db9cff4d1 100644 --- a/sys/sys/filio.h +++ b/sys/sys/filio.h @@ -40,6 +40,7 @@ #ifndef _SYS_FILIO_H_ #define _SYS_FILIO_H_ +#include #include /* Generic file-descriptor ioctl's. */ @@ -62,6 +63,13 @@ struct fiodgname_arg { /* Handle lseek SEEK_DATA and SEEK_HOLE for holey file knowledge. */ #define FIOSEEKDATA _IOWR('f', 97, off_t) /* SEEK_DATA */ #define FIOSEEKHOLE _IOWR('f', 98, off_t) /* SEEK_HOLE */ +struct fiobmap2_arg { + int64_t bn; + int runp; + int runb; +}; +/* Get the file's bmap info for the logical block bn */ +#define FIOBMAP2 _IOWR('f', 99, struct fiobmap2_arg) #ifdef _KERNEL #ifdef COMPAT_FREEBSD32 diff --git a/sys/sys/gsb_crc32.h b/sys/sys/gsb_crc32.h new file mode 100644 index 000000000000..c5a42d3d3152 --- /dev/null +++ b/sys/sys/gsb_crc32.h @@ -0,0 +1,47 @@ +/*- + * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or + * code or tables extracted from it, as desired without restriction. + * + * $FreeBSD$ + */ + +#ifndef _SYS_GSB_CRC32_H_ +#define _SYS_GSB_CRC32_H_ + +#include + +#ifdef _KERNEL + +extern const uint32_t crc32_tab[]; + +static __inline uint32_t +crc32_raw(const void *buf, size_t size, uint32_t crc) +{ + const uint8_t *p = (const uint8_t *)buf; + + while (size--) + crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + return (crc); +} + +static __inline uint32_t +crc32(const void *buf, size_t size) +{ + uint32_t crc; + + crc = crc32_raw(buf, size, ~0U); + return (crc ^ ~0U); +} + +uint32_t calculate_crc32c(uint32_t crc32c, const unsigned char *buffer, + unsigned int length); +#endif + +#if defined(__amd64__) || defined(__i386__) +uint32_t sse42_crc32c(uint32_t, const unsigned char *, unsigned); +#endif +#if defined(__aarch64__) +uint32_t armv8_crc32c(uint32_t, const unsigned char *, unsigned int); +#endif + +#endif /* !_SYS_GSB_CRC32_H_ */ diff --git a/sys/sys/libkern.h b/sys/sys/libkern.h index 123f6eeda3f3..1e343f31bcaa 100644 --- a/sys/sys/libkern.h +++ b/sys/sys/libkern.h @@ -190,39 +190,6 @@ size_t strspn(const char *, const char *); char *strstr(const char *, const char *); int strvalid(const char *, size_t); -extern const uint32_t crc32_tab[]; - -static __inline uint32_t -crc32_raw(const void *buf, size_t size, uint32_t crc) -{ - const uint8_t *p = (const uint8_t *)buf; - - while (size--) - crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); - return (crc); -} - -static __inline uint32_t -crc32(const void *buf, size_t size) -{ - uint32_t crc; - - crc = crc32_raw(buf, size, ~0U); - return (crc ^ ~0U); -} - -uint32_t -calculate_crc32c(uint32_t crc32c, const unsigned char *buffer, - unsigned int length); -#ifdef _KERNEL -#if defined(__amd64__) || defined(__i386__) -uint32_t sse42_crc32c(uint32_t, const unsigned char *, unsigned); -#endif -#if defined(__aarch64__) -uint32_t armv8_crc32c(uint32_t, const unsigned char *, unsigned int); -#endif -#endif - static __inline char * index(const char *p, int ch) { diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index b6b291170311..1f9d9a7d515f 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -348,7 +348,7 @@ struct mbuf { */ #define M_FLAG_BITS \ "\20\1M_EXT\2M_PKTHDR\3M_EOR\4M_RDONLY\5M_BCAST\6M_MCAST" \ - "\7M_PROMISC\10M_VLANTAG\13M_TSTMP\14M_TSTMP_HPREC" + "\7M_PROMISC\10M_VLANTAG\12M_NOFREE\13M_TSTMP\14M_TSTMP_HPREC" #define M_FLAG_PROTOBITS \ "\15M_PROTO1\16M_PROTO2\17M_PROTO3\20M_PROTO4\21M_PROTO5" \ "\22M_PROTO6\23M_PROTO7\24M_PROTO8\25M_PROTO9\26M_PROTO10" \ diff --git a/sys/sys/param.h b/sys/sys/param.h index e2f2367760fb..2534537558c5 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -60,7 +60,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1300030 /* Master, propagated to newvers */ +#define __FreeBSD_version 1300032 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, diff --git a/sys/sys/queue.h b/sys/sys/queue.h index 94fd1ce7b66b..3d28a6c92454 100644 --- a/sys/sys/queue.h +++ b/sys/sys/queue.h @@ -829,6 +829,10 @@ struct { \ #define TAILQ_PREV(elm, headname, field) \ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TAILQ_PREV_FAST(elm, head, type, field) \ + ((elm)->field.tqe_prev == &(head)->tqh_first ? NULL : \ + __containerof((elm)->field.tqe_prev, QUEUE_TYPEOF(type), field.tqe_next)) + #define TAILQ_REMOVE(head, elm, field) do { \ QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ diff --git a/sys/sys/sbuf.h b/sys/sys/sbuf.h index b4d274158ab0..4010f3b7d31c 100644 --- a/sys/sys/sbuf.h +++ b/sys/sys/sbuf.h @@ -103,6 +103,7 @@ void sbuf_start_section(struct sbuf *, ssize_t *); ssize_t sbuf_end_section(struct sbuf *, ssize_t, size_t, int); void sbuf_hexdump(struct sbuf *, const void *, int, const char *, int); +int sbuf_count_drain(void *arg, const char *data, int len); int sbuf_printf_drain(void *arg, const char *data, int len); void sbuf_putbuf(struct sbuf *); diff --git a/sys/sys/sleepqueue.h b/sys/sys/sleepqueue.h index 08eec5cd4381..8974869fb616 100644 --- a/sys/sys/sleepqueue.h +++ b/sys/sys/sleepqueue.h @@ -84,6 +84,7 @@ struct thread; #define SLEEPQ_SX 0x03 /* Used by an sx lock. */ #define SLEEPQ_LK 0x04 /* Used by a lockmgr. */ #define SLEEPQ_INTERRUPTIBLE 0x100 /* Sleep is interruptible. */ +#define SLEEPQ_UNFAIR 0x200 /* Unfair wakeup order. */ void init_sleepqueues(void); int sleepq_abort(struct thread *td, int intrval); diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index f82500087f08..29bd01de841e 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -173,7 +173,7 @@ int kern_mknodat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, int mode, dev_t dev); int kern_mlock(struct proc *proc, struct ucred *cred, uintptr_t addr, size_t len); -int kern_mmap(struct thread *td, uintptr_t addr, size_t size, int prot, +int kern_mmap(struct thread *td, uintptr_t addr, size_t len, int prot, int flags, int fd, off_t pos); int kern_mprotect(struct thread *td, uintptr_t addr, size_t size, int prot); int kern_msgctl(struct thread *, int, int, struct msqid_ds *); diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index 0007235d3d58..9cf4b901e583 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -218,6 +218,7 @@ int sysctl_handle_uma_zone_cur(SYSCTL_HANDLER_ARGS); int sysctl_msec_to_sbintime(SYSCTL_HANDLER_ARGS); int sysctl_usec_to_sbintime(SYSCTL_HANDLER_ARGS); +int sysctl_sec_to_timeval(SYSCTL_HANDLER_ARGS); int sysctl_dpcpu_int(SYSCTL_HANDLER_ARGS); int sysctl_dpcpu_long(SYSCTL_HANDLER_ARGS); @@ -857,6 +858,24 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); NULL); \ }) +/* OID expressing a struct timeval as seconds */ +#define SYSCTL_TIMEVAL_SEC(parent, nbr, name, access, ptr, descr) \ + SYSCTL_OID(parent, nbr, name, \ + CTLTYPE_INT | CTLFLAG_MPSAFE | CTLFLAG_RD | (access), \ + (ptr), 0, sysctl_sec_to_timeval, "I", descr); \ + CTASSERT(((access) & CTLTYPE) == 0 || \ + ((access) & SYSCTL_CT_ASSERT_MASK) == CTLTYPE_INT) +#define SYSCTL_ADD_TIMEVAL_SEC(ctx, parent, nbr, name, access, ptr, descr) \ +({ \ + struct timeval *__ptr = (ptr); \ + CTASSERT(((access) & CTLTYPE) == 0 || \ + ((access) & SYSCTL_CT_ASSERT_MASK) == CTLTYPE_INT); \ + sysctl_add_oid(ctx, parent, nbr, name, \ + CTLTYPE_INT | CTLFLAG_MPSAFE | CTLFLAG_RD | (access), \ + __ptr, 0, sysctl_sec_to_timeval, "I", __DESCR(descr), \ + NULL); \ +}) + /* * A macro to generate a read-only sysctl to indicate the presence of optional * kernel features. diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 097b5af9a8eb..733348c4fae9 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -489,6 +489,7 @@ int pause_sbt(const char *wmesg, sbintime_t sbt, sbintime_t pr, _sleep((chan), NULL, (pri), (wmesg), (bt), (pr), (flags)) void wakeup(void * chan); void wakeup_one(void * chan); +void wakeup_any(void * chan); /* * Common `struct cdev *' stuff are declared here to avoid #include poisoning diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h index f7079ad92c1c..9713623de6cc 100644 --- a/sys/sys/ucred.h +++ b/sys/sys/ucred.h @@ -89,12 +89,11 @@ struct xucred { gid_t cr_groups[XU_NGROUPS]; /* groups */ union { void *_cr_unused1; /* compatibility with old ucred */ - pid_t _pid; - } _cr; + pid_t cr_pid; + }; }; #define XUCRED_VERSION 0 -#define cr_pid _cr._pid /* This can be used for both ucred and xucred structures. */ #define cr_gid cr_groups[0] diff --git a/sys/tools/sdiodevs2h.awk b/sys/tools/sdiodevs2h.awk new file mode 100644 index 000000000000..873846aca722 --- /dev/null +++ b/sys/tools/sdiodevs2h.awk @@ -0,0 +1,265 @@ +#! /usr/bin/awk -f +#- +# $NetBSD: usb/devlist2h.awk,v 1.9 2001/01/18 20:28:22 jdolecek Exp $ +# $FreeBSD$ +# +# SPDX-License-Identifier: BSD-4-Clause +# +# Copyright (c) 1995, 1996 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 by Christopher G. Demetriou. +# 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. +# + +function usage() +{ + print "usage: sdiodevs2h.awk [-d|-h]"; + exit 1; +} + +function header(file) +{ + printf("/*\n") > file + printf(" * THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.\n") \ + > file + printf(" *\n") > file + printf(" * generated from:\n") > file + printf(" *\t%s\n", VERSION) > file + printf(" */\n") > file +} + +function vendor(hfile) +{ + nvendors++ + + vendorindex[$2] = nvendors; # record index for this name, for later. + vendors[nvendors, 1] = $2; # name + vendors[nvendors, 2] = $3; # id + if (hfile) + printf("#define\tSDIO_VENDOR_%s\t%s\t", vendors[nvendors, 1], + vendors[nvendors, 2]) > hfile + i = 3; f = 4; + + # comments + ocomment = oparen = 0 + if (f <= NF) { + if (hfile) + printf("\t/* ") > hfile + ocomment = 1; + } + while (f <= NF) { + if ($f == "#") { + if (hfile) + printf("(") > hfile + oparen = 1 + f++ + continue + } + if (oparen) { + if (hfile) + printf("%s", $f) > hfile + if (f < NF && hfile) + printf(" ") > hfile + f++ + continue + } + vendors[nvendors, i] = $f + if (hfile) + printf("%s", vendors[nvendors, i]) > hfile + if (f < NF && hfile) + printf(" ") > hfile + i++; f++; + } + if (oparen && hfile) + printf(")") > hfile + if (ocomment && hfile) + printf(" */") > hfile + if (hfile) + printf("\n") > hfile +} + +function product(hfile) +{ + nproducts++ + + products[nproducts, 1] = $2; # vendor name + products[nproducts, 2] = $3; # product id + products[nproducts, 3] = $4; # id + if (hfile) + printf("#define\tSDIO_PRODUCT_%s_%s\t%s\t", \ + products[nproducts, 1], products[nproducts, 2], \ + products[nproducts, 3]) > hfile + + i=4; f = 5; + + # comments + ocomment = oparen = 0 + if (f <= NF) { + if (hfile) + printf("\t/* ") > hfile + ocomment = 1; + } + while (f <= NF) { + if ($f == "#") { + if (hfile) + printf("(") > hfile + oparen = 1 + f++ + continue + } + if (oparen) { + if (hfile) + printf("%s", $f) > hfile + if (f < NF && hfile) + printf(" ") > hfile + f++ + continue + } + products[nproducts, i] = $f + if (hfile) + printf("%s", products[nproducts, i]) > hfile + if (f < NF && hfile) + printf(" ") > hfile + i++; f++; + } + if (oparen && hfile) + printf(")") > hfile + if (ocomment && hfile) + printf(" */") > hfile + if (hfile) + printf("\n") > hfile +} + +function dump_dfile(dfile) +{ + printf("\n") > dfile + printf("const struct sdio_knowndev sdio_knowndevs[] = {\n") > dfile + for (i = 1; i <= nproducts; i++) { + printf("\t{\n") > dfile + printf("\t SDIO_VENDOR_%s, SDIO_PRODUCT_%s_%s,\n", + products[i, 1], products[i, 1], products[i, 2]) > dfile + printf("\t ") > dfile + printf("0") > dfile + printf(",\n") > dfile + + vendi = vendorindex[products[i, 1]]; + printf("\t \"") > dfile + j = 3; + needspace = 0; + while (vendors[vendi, j] != "") { + if (needspace) + printf(" ") > dfile + printf("%s", vendors[vendi, j]) > dfile + needspace = 1 + j++ + } + printf("\",\n") > dfile + + printf("\t \"") > dfile + j = 4; + needspace = 0; + while (products[i, j] != "") { + if (needspace) + printf(" ") > dfile + printf("%s", products[i, j]) > dfile + needspace = 1 + j++ + } + printf("\",\n") > dfile + printf("\t},\n") > dfile + } + for (i = 1; i <= nvendors; i++) { + printf("\t{\n") > dfile + printf("\t SDIO_VENDOR_%s, 0,\n", vendors[i, 1]) > dfile + printf("\t SDIO_KNOWNDEV_NOPROD,\n") > dfile + printf("\t \"") > dfile + j = 3; + needspace = 0; + while (vendors[i, j] != "") { + if (needspace) + printf(" ") > dfile + printf("%s", vendors[i, j]) > dfile + needspace = 1 + j++ + } + printf("\",\n") > dfile + printf("\t NULL,\n") > dfile + printf("\t},\n") > dfile + } + printf("\t{ 0, 0, 0, NULL, NULL, }\n") > dfile + printf("};\n") > dfile +} + +BEGIN { + +nproducts = nvendors = 0 +# Process the command line +for (i = 1; i < ARGC; i++) { + arg = ARGV[i]; + if (arg !~ /^-[dh]+$/ && arg !~ /devs$/) + usage(); + if (arg ~ /^-.*d/) + dfile="sdiodevs_data.h" + if (arg ~ /^-.*h/) + hfile="sdiodevs.h" + if (arg ~ /devs$/) + srcfile = arg; +} +ARGC = 1; +line=0; + +while ((getline < srcfile) > 0) { + line++; + if (line == 1) { + VERSION = $0 + gsub("\\$", "", VERSION) + if (dfile) + header(dfile) + if (hfile) + header(hfile) + continue; + } + if ($1 == "vendor") { + vendor(hfile) + continue + } + if ($1 == "product") { + product(hfile) + continue + } + if ($0 == "") + blanklines++ + if (hfile) + print $0 > hfile + if (blanklines < 2 && dfile) + print $0 > dfile +} + +# print out the match tables + +if (dfile) + dump_dfile(dfile) +} diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index e0062cc73c6e..9ebdec0c88c4 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index 36449e9cb2cf..bc279e27269f 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c index b284cbf41f6b..fccccb7ce4b3 100644 --- a/sys/ufs/ffs/ffs_subr.c +++ b/sys/ufs/ffs/ffs_subr.c @@ -59,6 +59,7 @@ struct malloc_type; #else /* _KERNEL */ #include +#include #include #include #include diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index a3bec1a39dc7..3174dc4de129 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include +#include #include #include #include diff --git a/sys/ufs/ufs/ufs_bmap.c b/sys/ufs/ufs/ufs_bmap.c index 97ce437e4b00..9db33467a5a2 100644 --- a/sys/ufs/ufs/ufs_bmap.c +++ b/sys/ufs/ufs/ufs_bmap.c @@ -200,12 +200,15 @@ ufs_bmaparray(vp, bn, bnp, nbp, runp, runb) *bnp = blkptrtodb(ump, ip->i_din2->di_extb[-1 - bn]); if (*bnp == 0) *bnp = -1; - if (nbp == NULL) - panic("ufs_bmaparray: mapping ext data"); + if (nbp == NULL) { + /* indirect block not found */ + return (EINVAL); + } nbp->b_xflags |= BX_ALTDATA; return (0); } else { - panic("ufs_bmaparray: blkno out of range"); + /* blkno out of range */ + return (EINVAL); } /* * Since this is FFS independent code, we are out of diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index 3a4553b1a0e4..56cdb3336614 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -1650,6 +1650,31 @@ swap_pager_nswapdev(void) return (nswapdev); } +static void +swp_pager_force_dirty(vm_page_t m) +{ + + vm_page_dirty(m); +#ifdef INVARIANTS + vm_page_lock(m); + if (!vm_page_wired(m) && m->queue == PQ_NONE) + panic("page %p is neither wired nor queued", m); + vm_page_unlock(m); +#endif + vm_page_xunbusy(m); +} + +static void +swp_pager_force_launder(vm_page_t m) +{ + + vm_page_dirty(m); + vm_page_lock(m); + vm_page_launder(m); + vm_page_unlock(m); + vm_page_xunbusy(m); +} + /* * SWP_PAGER_FORCE_PAGEIN() - force a swap block to be paged in * @@ -1667,7 +1692,7 @@ swap_pager_nswapdev(void) * XXX - The code to page the whole block in doesn't work, so we * revert to the one-by-one behavior for now. Sigh. */ -static inline void +static void swp_pager_force_pagein(vm_object_t object, vm_pindex_t pindex) { vm_page_t m; @@ -1676,14 +1701,7 @@ swp_pager_force_pagein(vm_object_t object, vm_pindex_t pindex) m = vm_page_grab(object, pindex, VM_ALLOC_NORMAL); if (m->valid == VM_PAGE_BITS_ALL) { vm_object_pip_wakeup(object); - vm_page_dirty(m); -#ifdef INVARIANTS - vm_page_lock(m); - if (!vm_page_wired(m) && m->queue == PQ_NONE) - panic("page %p is neither wired nor queued", m); - vm_page_unlock(m); -#endif - vm_page_xunbusy(m); + swp_pager_force_dirty(m); vm_pager_page_unswapped(m); return; } @@ -1691,14 +1709,35 @@ swp_pager_force_pagein(vm_object_t object, vm_pindex_t pindex) if (swap_pager_getpages(object, &m, 1, NULL, NULL) != VM_PAGER_OK) panic("swap_pager_force_pagein: read from swap failed");/*XXX*/ vm_object_pip_wakeup(object); - vm_page_dirty(m); - vm_page_lock(m); - vm_page_launder(m); - vm_page_unlock(m); - vm_page_xunbusy(m); + swp_pager_force_launder(m); vm_pager_page_unswapped(m); } +/* + * swap_pager_swapoff_object: + * + * Page in all of the pages that have been paged out for an object + * from a given swap device. + */ +static void +swap_pager_swapoff_object(struct swdevt *sp, vm_object_t object) +{ + struct swblk *sb; + vm_pindex_t pi; + int i; + + for (pi = 0; (sb = SWAP_PCTRIE_LOOKUP_GE( + &object->un_pager.swp.swp_blks, pi)) != NULL; ) { + pi = sb->p + SWAP_META_PAGES; + for (i = 0; i < SWAP_META_PAGES; i++) { + if (sb->d[i] == SWAPBLK_NONE) + continue; + if (swp_pager_isondev(sb->d[i], sp)) + swp_pager_force_pagein(object, sb->p + i); + } + } +} + /* * swap_pager_swapoff: * @@ -1712,10 +1751,8 @@ swp_pager_force_pagein(vm_object_t object, vm_pindex_t pindex) static void swap_pager_swapoff(struct swdevt *sp) { - struct swblk *sb; vm_object_t object; - vm_pindex_t pi; - int i, retries; + int retries; sx_assert(&swdev_syscall_lock, SA_XLOCKED); @@ -1745,17 +1782,7 @@ swap_pager_swapoff(struct swdevt *sp) if (object->type != OBJT_SWAP) goto next_obj; - for (pi = 0; (sb = SWAP_PCTRIE_LOOKUP_GE( - &object->un_pager.swp.swp_blks, pi)) != NULL; ) { - pi = sb->p + SWAP_META_PAGES; - for (i = 0; i < SWAP_META_PAGES; i++) { - if (sb->d[i] == SWAPBLK_NONE) - continue; - if (swp_pager_isondev(sb->d[i], sp)) - swp_pager_force_pagein(object, - sb->p + i); - } - } + swap_pager_swapoff_object(sp, object); next_obj: VM_OBJECT_WUNLOCK(object); mtx_lock(&vm_object_list_mtx); diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index b49f92e7c8ca..ff9539d812cb 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -144,9 +144,16 @@ static int boot_pages; static struct sx uma_drain_lock; -/* kmem soft limit. */ +/* + * kmem soft limit, initialized by uma_set_limit(). Ensure that early + * allocations don't trigger a wakeup of the reclaim thread. + */ static unsigned long uma_kmem_limit = LONG_MAX; -static volatile unsigned long uma_kmem_total; +SYSCTL_ULONG(_vm, OID_AUTO, uma_kmem_limit, CTLFLAG_RD, &uma_kmem_limit, 0, + "UMA kernel memory soft limit"); +static unsigned long uma_kmem_total; +SYSCTL_ULONG(_vm, OID_AUTO, uma_kmem_total, CTLFLAG_RD, &uma_kmem_total, 0, + "UMA kernel memory usage"); /* Is the VM done starting up? */ static enum { BOOT_COLD = 0, BOOT_STRAPPED, BOOT_PAGEALLOC, BOOT_BUCKETS, @@ -254,7 +261,7 @@ static void keg_small_init(uma_keg_t keg); static void keg_large_init(uma_keg_t keg); static void zone_foreach(void (*zfunc)(uma_zone_t)); static void zone_timeout(uma_zone_t zone); -static int hash_alloc(struct uma_hash *); +static int hash_alloc(struct uma_hash *, u_int); static int hash_expand(struct uma_hash *, struct uma_hash *); static void hash_free(struct uma_hash *hash); static void uma_timeout(void *); @@ -565,6 +572,7 @@ static void zone_timeout(uma_zone_t zone) { uma_keg_t keg = zone->uz_keg; + u_int slabs; KEG_LOCK(keg); /* @@ -575,7 +583,8 @@ zone_timeout(uma_zone_t zone) * may be a little aggressive. Should I allow for two collisions max? */ if (keg->uk_flags & UMA_ZONE_HASH && - keg->uk_pages / keg->uk_ppera >= keg->uk_hash.uh_hashsize) { + (slabs = keg->uk_pages / keg->uk_ppera) > + keg->uk_hash.uh_hashsize) { struct uma_hash newhash; struct uma_hash oldhash; int ret; @@ -586,9 +595,8 @@ zone_timeout(uma_zone_t zone) * I have to do everything in stages and check for * races. */ - newhash = keg->uk_hash; KEG_UNLOCK(keg); - ret = hash_alloc(&newhash); + ret = hash_alloc(&newhash, 1 << fls(slabs)); KEG_LOCK(keg); if (ret) { if (hash_expand(&keg->uk_hash, &newhash)) { @@ -620,16 +628,13 @@ zone_timeout(uma_zone_t zone) * 1 on success and 0 on failure. */ static int -hash_alloc(struct uma_hash *hash) +hash_alloc(struct uma_hash *hash, u_int size) { - u_int oldsize; size_t alloc; - oldsize = hash->uh_hashsize; - - /* We're just going to go to a power of two greater */ - if (oldsize) { - hash->uh_hashsize = oldsize * 2; + KASSERT(powerof2(size), ("hash size must be power of 2")); + if (size > UMA_HASH_SIZE_INIT) { + hash->uh_hashsize = size; alloc = sizeof(hash->uh_slab_hash[0]) * hash->uh_hashsize; hash->uh_slab_hash = (struct slabhead *)malloc(alloc, M_UMAHASH, M_NOWAIT); @@ -1274,9 +1279,9 @@ pcpu_page_alloc(uma_zone_t zone, vm_size_t bytes, int domain, uint8_t *pflag, zkva += PAGE_SIZE; } return ((void*)addr); - fail: +fail: TAILQ_FOREACH_SAFE(p, &alloctail, listq, p_next) { - vm_page_unwire(p, PQ_NONE); + vm_page_unwire_noq(p); vm_page_free(p); } return (NULL); @@ -1326,7 +1331,7 @@ noobj_alloc(uma_zone_t zone, vm_size_t bytes, int domain, uint8_t *flags, * exit. */ TAILQ_FOREACH_SAFE(p, &alloctail, listq, p_next) { - vm_page_unwire(p, PQ_NONE); + vm_page_unwire_noq(p); vm_page_free(p); } return (NULL); @@ -1387,7 +1392,7 @@ pcpu_page_free(void *mem, vm_size_t size, uint8_t flags) for (curva = sva; curva < sva + size; curva += PAGE_SIZE) { paddr = pmap_kextract(curva); m = PHYS_TO_VM_PAGE(paddr); - vm_page_unwire(m, PQ_NONE); + vm_page_unwire_noq(m); vm_page_free(m); } pmap_qremove(sva, size >> PAGE_SHIFT); @@ -1704,7 +1709,7 @@ keg_ctor(void *mem, int size, void *udata, int flags) } if (keg->uk_flags & UMA_ZONE_HASH) - hash_alloc(&keg->uk_hash); + hash_alloc(&keg->uk_hash, 0); CTR5(KTR_UMA, "keg_ctor %p zone %s(%p) out %d free %d\n", keg, zone->uz_name, zone, @@ -3737,14 +3742,14 @@ unsigned long uma_size(void) { - return (uma_kmem_total); + return (atomic_load_long(&uma_kmem_total)); } long uma_avail(void) { - return (uma_kmem_limit - uma_kmem_total); + return (uma_kmem_limit - uma_size()); } void diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index c8ad7ae7aae1..4ee30609f189 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -408,7 +408,7 @@ vm_thread_stack_dispose(vm_object_t ksobj, vm_offset_t ks, int pages) if (m == NULL) panic("vm_thread_dispose: kstack already missing?"); vm_page_lock(m); - vm_page_unwire(m, PQ_NONE); + vm_page_unwire_noq(m); vm_page_free(m); vm_page_unlock(m); } diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c index ac87a40a3b81..c382428e63df 100644 --- a/sys/vm/vm_kern.c +++ b/sys/vm/vm_kern.c @@ -586,7 +586,7 @@ _kmem_unback(vm_object_t object, vm_offset_t addr, vm_size_t size) #endif for (; offset < end; offset += PAGE_SIZE, m = next) { next = vm_page_next(m); - vm_page_unwire(m, PQ_NONE); + vm_page_unwire_noq(m); vm_page_free(m); } VM_OBJECT_WUNLOCK(object); diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 72ee70eaf95f..912031702070 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -454,18 +454,17 @@ vmspace_acquire_ref(struct proc *p) /* * Switch between vmspaces in an AIO kernel process. * - * The AIO kernel processes switch to and from a user process's - * vmspace while performing an I/O operation on behalf of a user - * process. The new vmspace is either the vmspace of a user process - * obtained from an active AIO request or the initial vmspace of the - * AIO kernel process (when it is idling). Because user processes - * will block to drain any active AIO requests before proceeding in - * exit() or execve(), the vmspace reference count for these vmspaces - * can never be 0. This allows for a much simpler implementation than - * the loop in vmspace_acquire_ref() above. Similarly, AIO kernel - * processes hold an extra reference on their initial vmspace for the - * life of the process so that this guarantee is true for any vmspace - * passed as 'newvm'. + * The new vmspace is either the vmspace of a user process obtained + * from an active AIO request or the initial vmspace of the AIO kernel + * process (when it is idling). Because user processes will block to + * drain any active AIO requests before proceeding in exit() or + * execve(), the reference count for vmspaces from AIO requests can + * never be 0. Similarly, AIO kernel processes hold an extra + * reference on their initial vmspace for the life of the process. As + * a result, the 'newvm' vmspace always has a non-zero reference + * count. This permits an additional reference on 'newvm' to be + * acquired via a simple atomic increment rather than the loop in + * vmspace_acquire_ref() above. */ void vmspace_switch_aio(struct vmspace *newvm) @@ -490,9 +489,6 @@ vmspace_switch_aio(struct vmspace *newvm) /* Activate the new mapping. */ pmap_activate(curthread); - /* Remove the daemon's reference to the old address space. */ - KASSERT(oldvm->vm_refcnt > 1, - ("vmspace_switch_aio: oldvm dropping last reference")); vmspace_free(oldvm); } @@ -738,18 +734,17 @@ SYSCTL_INT(_debug, OID_AUTO, vmmap_check, CTLFLAG_RWTUN, static void _vm_map_assert_consistent(vm_map_t map) { - vm_map_entry_t entry; - vm_map_entry_t child; + vm_map_entry_t child, entry, prev; vm_size_t max_left, max_right; if (!enable_vmmap_check) return; - for (entry = map->header.next; entry != &map->header; - entry = entry->next) { - KASSERT(entry->prev->end <= entry->start, + for (prev = &map->header; (entry = prev->next) != &map->header; + prev = entry) { + KASSERT(prev->end <= entry->start, ("map %p prev->end = %jx, start = %jx", map, - (uintmax_t)entry->prev->end, (uintmax_t)entry->start)); + (uintmax_t)prev->end, (uintmax_t)entry->start)); KASSERT(entry->start < entry->end, ("map %p start = %jx, end = %jx", map, (uintmax_t)entry->start, (uintmax_t)entry->end)); @@ -766,7 +761,7 @@ _vm_map_assert_consistent(vm_map_t map) (uintmax_t)entry->start, (uintmax_t)entry->right->start)); child = entry->left; max_left = (child != NULL) ? child->max_free : - entry->start - entry->prev->end; + entry->start - prev->end; child = entry->right; max_right = (child != NULL) ? child->max_free : entry->next->start - entry->end; @@ -966,55 +961,92 @@ vm_map_entry_set_behavior(vm_map_entry_t entry, u_char behavior) } /* - * vm_map_entry_set_max_free: + * vm_map_entry_max_free_{left,right}: * - * Set the max_free field in a vm_map_entry. + * Compute the size of the largest free gap between two entries, + * one the root of a tree and the other the ancestor of that root + * that is the least or greatest ancestor found on the search path. */ -static inline void -vm_map_entry_set_max_free(vm_map_entry_t entry) +static inline vm_size_t +vm_map_entry_max_free_left(vm_map_entry_t root, vm_map_entry_t left_ancestor) { - vm_map_entry_t child; - vm_size_t max_left, max_right; - child = entry->left; - max_left = (child != NULL) ? child->max_free : - entry->start - entry->prev->end; - child = entry->right; - max_right = (child != NULL) ? child->max_free : - entry->next->start - entry->end; - entry->max_free = MAX(max_left, max_right); + return (root->left != NULL ? + root->left->max_free : root->start - left_ancestor->end); } -#define SPLAY_LEFT_STEP(root, y, rlist, test) do { \ - y = root->left; \ - if (y != NULL && (test)) { \ - /* Rotate right and make y root. */ \ - root->left = y->right; \ - y->right = root; \ - vm_map_entry_set_max_free(root); \ - root = y; \ - y = root->left; \ - } \ - /* Put root on rlist. */ \ - root->left = rlist; \ - rlist = root; \ - root = y; \ +static inline vm_size_t +vm_map_entry_max_free_right(vm_map_entry_t root, vm_map_entry_t right_ancestor) +{ + + return (root->right != NULL ? + root->right->max_free : right_ancestor->start - root->end); +} + +#define SPLAY_LEFT_STEP(root, y, rlist, test) do { \ + vm_size_t max_free; \ + \ + /* \ + * Infer root->right->max_free == root->max_free when \ + * y->max_free < root->max_free || root->max_free == 0. \ + * Otherwise, look right to find it. \ + */ \ + y = root->left; \ + max_free = root->max_free; \ + KASSERT(max_free >= vm_map_entry_max_free_right(root, rlist), \ + ("%s: max_free invariant fails", __func__)); \ + if (y == NULL ? max_free > 0 : max_free - 1 < y->max_free) \ + max_free = vm_map_entry_max_free_right(root, rlist); \ + if (y != NULL && (test)) { \ + /* Rotate right and make y root. */ \ + root->left = y->right; \ + y->right = root; \ + if (max_free < y->max_free) \ + root->max_free = max_free = MAX(max_free, \ + vm_map_entry_max_free_left(root, y)); \ + root = y; \ + y = root->left; \ + } \ + /* Copy right->max_free. Put root on rlist. */ \ + root->max_free = max_free; \ + KASSERT(max_free == vm_map_entry_max_free_right(root, rlist), \ + ("%s: max_free not copied from right", __func__)); \ + root->left = rlist; \ + rlist = root; \ + root = y; \ } while (0) -#define SPLAY_RIGHT_STEP(root, y, llist, test) do { \ - y = root->right; \ - if (y != NULL && (test)) { \ - /* Rotate left and make y root. */ \ - root->right = y->left; \ - y->left = root; \ - vm_map_entry_set_max_free(root); \ - root = y; \ - y = root->right; \ - } \ - /* Put root on llist. */ \ - root->right = llist; \ - llist = root; \ - root = y; \ +#define SPLAY_RIGHT_STEP(root, y, llist, test) do { \ + vm_size_t max_free; \ + \ + /* \ + * Infer root->left->max_free == root->max_free when \ + * y->max_free < root->max_free || root->max_free == 0. \ + * Otherwise, look left to find it. \ + */ \ + y = root->right; \ + max_free = root->max_free; \ + KASSERT(max_free >= vm_map_entry_max_free_left(root, llist), \ + ("%s: max_free invariant fails", __func__)); \ + if (y == NULL ? max_free > 0 : max_free - 1 < y->max_free) \ + max_free = vm_map_entry_max_free_left(root, llist); \ + if (y != NULL && (test)) { \ + /* Rotate left and make y root. */ \ + root->right = y->left; \ + y->left = root; \ + if (max_free < y->max_free) \ + root->max_free = max_free = MAX(max_free, \ + vm_map_entry_max_free_right(root, y)); \ + root = y; \ + y = root->right; \ + } \ + /* Copy left->max_free. Put root on llist. */ \ + root->max_free = max_free; \ + KASSERT(max_free == vm_map_entry_max_free_left(root, llist), \ + ("%s: max_free not copied from left", __func__)); \ + root->right = llist; \ + llist = root; \ + root = y; \ } while (0) /* @@ -1023,18 +1055,21 @@ vm_map_entry_set_max_free(vm_map_entry_t entry) * addr. Treat pointers to nodes with max_free < length as NULL pointers. * llist and rlist are the two sides in reverse order (bottom-up), with llist * linked by the right pointer and rlist linked by the left pointer in the - * vm_map_entry. + * vm_map_entry, and both lists terminated by &map->header. This function, and + * the subsequent call to vm_map_splay_merge, rely on the start and end address + * values in &map->header. */ static vm_map_entry_t -vm_map_splay_split(vm_offset_t addr, vm_size_t length, - vm_map_entry_t root, vm_map_entry_t *out_llist, vm_map_entry_t *out_rlist) +vm_map_splay_split(vm_map_t map, vm_offset_t addr, vm_size_t length, + vm_map_entry_t *out_llist, vm_map_entry_t *out_rlist) { - vm_map_entry_t llist, rlist; - vm_map_entry_t y; + vm_map_entry_t llist, rlist, root, y; - llist = NULL; - rlist = NULL; + llist = rlist = &map->header; + root = map->root; while (root != NULL && root->max_free >= length) { + KASSERT(llist->end <= root->start && root->end <= rlist->start, + ("%s: root not within tree bounds", __func__)); if (addr < root->start) { SPLAY_LEFT_STEP(root, y, rlist, y->max_free >= length && addr < y->start); @@ -1073,44 +1108,65 @@ vm_map_splay_findprev(vm_map_entry_t root, vm_map_entry_t *iolist) *iolist = llist; } +static inline void +vm_map_entry_swap(vm_map_entry_t *a, vm_map_entry_t *b) +{ + vm_map_entry_t tmp; + + tmp = *b; + *b = *a; + *a = tmp; +} + /* * Walk back up the two spines, flip the pointers and set max_free. The * subtrees of the root go at the bottom of llist and rlist. */ -static vm_map_entry_t -vm_map_splay_merge(vm_map_entry_t root, - vm_map_entry_t llist, vm_map_entry_t rlist, - vm_map_entry_t ltree, vm_map_entry_t rtree) +static void +vm_map_splay_merge(vm_map_t map, vm_map_entry_t root, + vm_map_entry_t llist, vm_map_entry_t rlist) { - vm_map_entry_t y; + vm_map_entry_t prev; + vm_size_t max_free_left, max_free_right; - while (llist != NULL) { - y = llist->right; - llist->right = ltree; - vm_map_entry_set_max_free(llist); - ltree = llist; - llist = y; + max_free_left = vm_map_entry_max_free_left(root, llist); + if (llist != &map->header) { + prev = root->left; + do { + /* + * The max_free values of the children of llist are in + * llist->max_free and max_free_left. Update with the + * max value. + */ + llist->max_free = max_free_left = + MAX(llist->max_free, max_free_left); + vm_map_entry_swap(&llist->right, &prev); + vm_map_entry_swap(&prev, &llist); + } while (llist != &map->header); + root->left = prev; } - while (rlist != NULL) { - y = rlist->left; - rlist->left = rtree; - vm_map_entry_set_max_free(rlist); - rtree = rlist; - rlist = y; - } - - /* - * Final assembly: add ltree and rtree as subtrees of root. - */ - root->left = ltree; - root->right = rtree; - vm_map_entry_set_max_free(root); - - return (root); + max_free_right = vm_map_entry_max_free_right(root, rlist); + if (rlist != &map->header) { + prev = root->right; + do { + /* + * The max_free values of the children of rlist are in + * rlist->max_free and max_free_right. Update with the + * max value. + */ + rlist->max_free = max_free_right = + MAX(rlist->max_free, max_free_right); + vm_map_entry_swap(&rlist->left, &prev); + vm_map_entry_swap(&prev, &rlist); + } while (rlist != &map->header); + root->right = prev; + } + root->max_free = MAX(max_free_left, max_free_right); + map->root = root; } /* - * vm_map_entry_splay: + * vm_map_splay: * * The Sleator and Tarjan top-down splay algorithm with the * following variation. Max_free must be computed bottom-up, so @@ -1127,14 +1183,14 @@ vm_map_splay_merge(vm_map_entry_t root, * Returns: the new root. */ static vm_map_entry_t -vm_map_entry_splay(vm_offset_t addr, vm_map_entry_t root) +vm_map_splay(vm_map_t map, vm_offset_t addr) { - vm_map_entry_t llist, rlist; + vm_map_entry_t llist, rlist, root; - root = vm_map_splay_split(addr, 0, root, &llist, &rlist); + root = vm_map_splay_split(map, addr, 0, &llist, &rlist); if (root != NULL) { /* do nothing */ - } else if (llist != NULL) { + } else if (llist != &map->header) { /* * Recover the greatest node in the left * subtree and make it the root. @@ -1142,7 +1198,7 @@ vm_map_entry_splay(vm_offset_t addr, vm_map_entry_t root) root = llist; llist = root->right; root->right = NULL; - } else if (rlist != NULL) { + } else if (rlist != &map->header) { /* * Recover the least node in the right * subtree and make it the root. @@ -1154,8 +1210,9 @@ vm_map_entry_splay(vm_offset_t addr, vm_map_entry_t root) /* There is no root. */ return (NULL); } - return (vm_map_splay_merge(root, llist, rlist, - root->left, root->right)); + vm_map_splay_merge(map, root, llist, rlist); + VM_MAP_ASSERT_CONSISTENT(map); + return (root); } /* @@ -1164,8 +1221,7 @@ vm_map_entry_splay(vm_offset_t addr, vm_map_entry_t root) * Insert/remove entries from maps. */ static void -vm_map_entry_link(vm_map_t map, - vm_map_entry_t entry) +vm_map_entry_link(vm_map_t map, vm_map_entry_t entry) { vm_map_entry_t llist, rlist, root; @@ -1174,15 +1230,14 @@ vm_map_entry_link(vm_map_t map, map->nentries, entry); VM_MAP_ASSERT_LOCKED(map); map->nentries++; - root = map->root; - root = vm_map_splay_split(entry->start, 0, root, &llist, &rlist); + root = vm_map_splay_split(map, entry->start, 0, &llist, &rlist); KASSERT(root == NULL, ("vm_map_entry_link: link object already mapped")); - entry->prev = (llist == NULL) ? &map->header : llist; - entry->next = (rlist == NULL) ? &map->header : rlist; - entry->prev->next = entry->next->prev = entry; - root = vm_map_splay_merge(entry, llist, rlist, NULL, NULL); - map->root = entry; + entry->prev = llist; + entry->next = rlist; + llist->next = rlist->prev = entry; + entry->left = entry->right = NULL; + vm_map_splay_merge(map, entry, llist, rlist); VM_MAP_ASSERT_CONSISTENT(map); } @@ -1193,19 +1248,13 @@ enum unlink_merge_type { }; static void -vm_map_entry_unlink(vm_map_t map, - vm_map_entry_t entry, - enum unlink_merge_type op) +vm_map_entry_unlink(vm_map_t map, vm_map_entry_t entry, + enum unlink_merge_type op) { vm_map_entry_t llist, rlist, root, y; VM_MAP_ASSERT_LOCKED(map); - llist = entry->prev; - rlist = entry->next; - llist->next = rlist; - rlist->prev = llist; - root = map->root; - root = vm_map_splay_split(entry->start, 0, root, &llist, &rlist); + root = vm_map_splay_split(map, entry->start, 0, &llist, &rlist); KASSERT(root != NULL, ("vm_map_entry_unlink: unlink object not mapped")); @@ -1230,11 +1279,11 @@ vm_map_entry_unlink(vm_map_t map, case UNLINK_MERGE_NONE: vm_map_splay_findprev(root, &llist); vm_map_splay_findnext(root, &rlist); - if (llist != NULL) { + if (llist != &map->header) { root = llist; llist = root->right; root->right = NULL; - } else if (rlist != NULL) { + } else if (rlist != &map->header) { root = rlist; rlist = root->left; root->left = NULL; @@ -1242,10 +1291,13 @@ vm_map_entry_unlink(vm_map_t map, root = NULL; break; } + y = entry->next; + y->prev = entry->prev; + y->prev->next = y; if (root != NULL) - root = vm_map_splay_merge(root, llist, rlist, - root->left, root->right); - map->root = root; + vm_map_splay_merge(map, root, llist, rlist); + else + map->root = NULL; VM_MAP_ASSERT_CONSISTENT(map); map->nentries--; CTR3(KTR_VM, "vm_map_entry_unlink: map %p, nentries %d, entry %p", map, @@ -1266,15 +1318,13 @@ vm_map_entry_resize(vm_map_t map, vm_map_entry_t entry, vm_size_t grow_amount) vm_map_entry_t llist, rlist, root; VM_MAP_ASSERT_LOCKED(map); - root = map->root; - root = vm_map_splay_split(entry->start, 0, root, &llist, &rlist); + root = vm_map_splay_split(map, entry->start, 0, &llist, &rlist); KASSERT(root != NULL, ("%s: resize object not mapped", __func__)); vm_map_splay_findnext(root, &rlist); root->right = NULL; entry->end += grow_amount; - map->root = vm_map_splay_merge(root, llist, rlist, - root->left, root->right); + vm_map_splay_merge(map, root, llist, rlist); VM_MAP_ASSERT_CONSISTENT(map); CTR4(KTR_VM, "%s: map %p, nentries %d, entry %p", __func__, map, map->nentries, entry); @@ -1320,8 +1370,7 @@ vm_map_lookup_entry( * change the map. Thus, the map's timestamp need not change * on a temporary upgrade. */ - map->root = cur = vm_map_entry_splay(address, cur); - VM_MAP_ASSERT_CONSISTENT(map); + cur = vm_map_splay(map, address); if (!locked) sx_downgrade(&map->lock); @@ -1591,13 +1640,14 @@ vm_map_findspace(vm_map_t map, vm_offset_t start, vm_size_t length) { vm_map_entry_t llist, rlist, root, y; vm_size_t left_length; + vm_offset_t gap_end; /* * Request must fit within min/max VM address and must avoid * address wrap. */ start = MAX(start, vm_map_min(map)); - if (start + length > vm_map_max(map) || start + length < start) + if (start >= vm_map_max(map) || length > vm_map_max(map) - start) return (vm_map_max(map) - length + 1); /* Empty tree means wide open address space. */ @@ -1605,14 +1655,19 @@ vm_map_findspace(vm_map_t map, vm_offset_t start, vm_size_t length) return (start); /* - * After splay, if start comes before root node, then there - * must be a gap from start to the root. + * After splay_split, if start is within an entry, push it to the start + * of the following gap. If rlist is at the end of the gap containing + * start, save the end of that gap in gap_end to see if the gap is big + * enough; otherwise set gap_end to start skip gap-checking and move + * directly to a search of the right subtree. */ - root = vm_map_splay_split(start, length, map->root, - &llist, &rlist); - if (root != NULL) + root = vm_map_splay_split(map, start, length, &llist, &rlist); + gap_end = rlist->start; + if (root != NULL) { start = root->end; - else if (rlist != NULL) { + if (root->right != NULL) + gap_end = start; + } else if (rlist != &map->header) { root = rlist; rlist = root->left; root->left = NULL; @@ -1621,19 +1676,9 @@ vm_map_findspace(vm_map_t map, vm_offset_t start, vm_size_t length) llist = root->right; root->right = NULL; } - map->root = vm_map_splay_merge(root, llist, rlist, - root->left, root->right); + vm_map_splay_merge(map, root, llist, rlist); VM_MAP_ASSERT_CONSISTENT(map); - if (start + length <= root->start) - return (start); - - /* - * Root is the last node that might begin its gap before - * start, and this is the last comparison where address - * wrap might be a problem. - */ - if (root->right == NULL && - start + length <= vm_map_max(map)) + if (length <= gap_end - start) return (start); /* With max_free, can immediately tell if no solution. */ @@ -1643,40 +1688,32 @@ vm_map_findspace(vm_map_t map, vm_offset_t start, vm_size_t length) /* * Splay for the least large-enough gap in the right subtree. */ - llist = NULL; - rlist = NULL; - for (left_length = 0; ; - left_length = root->left != NULL ? - root->left->max_free : root->start - llist->end) { + llist = rlist = &map->header; + for (left_length = 0;; + left_length = vm_map_entry_max_free_left(root, llist)) { if (length <= left_length) SPLAY_LEFT_STEP(root, y, rlist, - length <= (y->left != NULL ? - y->left->max_free : y->start - llist->end)); + length <= vm_map_entry_max_free_left(y, llist)); else SPLAY_RIGHT_STEP(root, y, llist, - length > (y->left != NULL ? - y->left->max_free : y->start - root->end)); + length > vm_map_entry_max_free_left(y, root)); if (root == NULL) break; } root = llist; llist = root->right; - if ((y = rlist) == NULL) - root->right = NULL; - else { + root->right = NULL; + if (rlist != &map->header) { + y = rlist; rlist = y->left; y->left = NULL; - root->right = y->right; - } - root = vm_map_splay_merge(root, llist, rlist, - root->left, root->right); - if (y != NULL) { - y->right = root->right; - vm_map_entry_set_max_free(y); + vm_map_splay_merge(map, y, &map->header, rlist); + y->max_free = MAX( + vm_map_entry_max_free_left(y, root), + vm_map_entry_max_free_right(y, &map->header)); root->right = y; - vm_map_entry_set_max_free(root); } - map->root = root; + vm_map_splay_merge(map, root, llist, &map->header); VM_MAP_ASSERT_CONSISTENT(map); return (root->end); } @@ -1760,8 +1797,8 @@ vm_map_alignspace(vm_map_t map, vm_object_t object, vm_ooffset_t offset, VM_MAP_ASSERT_LOCKED(map); free_addr = *addr; KASSERT(free_addr == vm_map_findspace(map, free_addr, length), - ("caller failed to provide space %d at address %p", - (int)length, (void*)free_addr)); + ("caller failed to provide space %#jx at address %p", + (uintmax_t)length, (void *)free_addr)); for (;;) { /* * At the start of every iteration, the free space at address @@ -2070,6 +2107,60 @@ vm_map_simplify_entry(vm_map_t map, vm_map_entry_t entry) } } +/* + * vm_map_entry_back: + * + * Allocate an object to back a map entry. + */ +static inline void +vm_map_entry_back(vm_map_entry_t entry) +{ + vm_object_t object; + + KASSERT(entry->object.vm_object == NULL, + ("map entry %p has backing object", entry)); + KASSERT((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0, + ("map entry %p is a submap", entry)); + object = vm_object_allocate(OBJT_DEFAULT, + atop(entry->end - entry->start)); + entry->object.vm_object = object; + entry->offset = 0; + if (entry->cred != NULL) { + object->cred = entry->cred; + object->charge = entry->end - entry->start; + entry->cred = NULL; + } +} + +/* + * vm_map_entry_charge_object + * + * If there is no object backing this entry, create one. Otherwise, if + * the entry has cred, give it to the backing object. + */ +static inline void +vm_map_entry_charge_object(vm_map_t map, vm_map_entry_t entry) +{ + + VM_MAP_ASSERT_LOCKED(map); + KASSERT((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0, + ("map entry %p is a submap", entry)); + if (entry->object.vm_object == NULL && !map->system_map && + (entry->eflags & MAP_ENTRY_GUARD) == 0) + vm_map_entry_back(entry); + else if (entry->object.vm_object != NULL && + ((entry->eflags & MAP_ENTRY_NEEDS_COPY) == 0) && + entry->cred != NULL) { + VM_OBJECT_WLOCK(entry->object.vm_object); + KASSERT(entry->object.vm_object->cred == NULL, + ("OVERCOMMIT: %s: both cred e %p", __func__, entry)); + entry->object.vm_object->cred = entry->cred; + entry->object.vm_object->charge = entry->end - entry->start; + VM_OBJECT_WUNLOCK(entry->object.vm_object); + entry->cred = NULL; + } +} + /* * vm_map_clip_start: [ internal use only ] * @@ -2095,48 +2186,22 @@ _vm_map_clip_start(vm_map_t map, vm_map_entry_t entry, vm_offset_t start) VM_MAP_ASSERT_LOCKED(map); KASSERT(entry->end > start && entry->start < start, ("_vm_map_clip_start: invalid clip of entry %p", entry)); - - /* - * Split off the front portion -- note that we must insert the new - * entry BEFORE this one, so that this entry has the specified - * starting address. - */ vm_map_simplify_entry(map, entry); /* - * If there is no object backing this entry, we might as well create - * one now. If we defer it, an object can get created after the map - * is clipped, and individual objects will be created for the split-up - * map. This is a bit of a hack, but is also about the best place to - * put this improvement. + * Create a backing object now, if none exists, so that more individual + * objects won't be created after the map entry is split. */ - if (entry->object.vm_object == NULL && !map->system_map && - (entry->eflags & MAP_ENTRY_GUARD) == 0) { - vm_object_t object; - object = vm_object_allocate(OBJT_DEFAULT, - atop(entry->end - entry->start)); - entry->object.vm_object = object; - entry->offset = 0; - if (entry->cred != NULL) { - object->cred = entry->cred; - object->charge = entry->end - entry->start; - entry->cred = NULL; - } - } else if (entry->object.vm_object != NULL && - ((entry->eflags & MAP_ENTRY_NEEDS_COPY) == 0) && - entry->cred != NULL) { - VM_OBJECT_WLOCK(entry->object.vm_object); - KASSERT(entry->object.vm_object->cred == NULL, - ("OVERCOMMIT: vm_entry_clip_start: both cred e %p", entry)); - entry->object.vm_object->cred = entry->cred; - entry->object.vm_object->charge = entry->end - entry->start; - VM_OBJECT_WUNLOCK(entry->object.vm_object); - entry->cred = NULL; - } + vm_map_entry_charge_object(map, entry); + /* Clone the entry. */ new_entry = vm_map_entry_create(map); *new_entry = *entry; + /* + * Split off the front portion. Insert the new entry BEFORE this one, + * so that this entry has the specified starting address. + */ new_entry->end = start; entry->offset += (start - entry->start); entry->start = start; @@ -2185,42 +2250,19 @@ _vm_map_clip_end(vm_map_t map, vm_map_entry_t entry, vm_offset_t end) ("_vm_map_clip_end: invalid clip of entry %p", entry)); /* - * If there is no object backing this entry, we might as well create - * one now. If we defer it, an object can get created after the map - * is clipped, and individual objects will be created for the split-up - * map. This is a bit of a hack, but is also about the best place to - * put this improvement. + * Create a backing object now, if none exists, so that more individual + * objects won't be created after the map entry is split. */ - if (entry->object.vm_object == NULL && !map->system_map && - (entry->eflags & MAP_ENTRY_GUARD) == 0) { - vm_object_t object; - object = vm_object_allocate(OBJT_DEFAULT, - atop(entry->end - entry->start)); - entry->object.vm_object = object; - entry->offset = 0; - if (entry->cred != NULL) { - object->cred = entry->cred; - object->charge = entry->end - entry->start; - entry->cred = NULL; - } - } else if (entry->object.vm_object != NULL && - ((entry->eflags & MAP_ENTRY_NEEDS_COPY) == 0) && - entry->cred != NULL) { - VM_OBJECT_WLOCK(entry->object.vm_object); - KASSERT(entry->object.vm_object->cred == NULL, - ("OVERCOMMIT: vm_entry_clip_end: both cred e %p", entry)); - entry->object.vm_object->cred = entry->cred; - entry->object.vm_object->charge = entry->end - entry->start; - VM_OBJECT_WUNLOCK(entry->object.vm_object); - entry->cred = NULL; - } + vm_map_entry_charge_object(map, entry); - /* - * Create a new entry and insert it AFTER the specified entry - */ + /* Clone the entry. */ new_entry = vm_map_entry_create(map); *new_entry = *entry; + /* + * Split off the back portion. Insert the new entry AFTER this one, + * so that this entry has the specified ending address. + */ new_entry->start = entry->end = end; new_entry->offset += (end - entry->start); if (new_entry->cred != NULL) @@ -3897,16 +3939,8 @@ vmspace_fork(struct vmspace *vm1, vm_ooffset_t *fork_charge) */ object = old_entry->object.vm_object; if (object == NULL) { - object = vm_object_allocate(OBJT_DEFAULT, - atop(old_entry->end - old_entry->start)); - old_entry->object.vm_object = object; - old_entry->offset = 0; - if (old_entry->cred != NULL) { - object->cred = old_entry->cred; - object->charge = old_entry->end - - old_entry->start; - old_entry->cred = NULL; - } + vm_map_entry_back(old_entry); + object = old_entry->object.vm_object; } /* @@ -4787,15 +4821,15 @@ vm_map_pmap_KBI(vm_map_t map) static void vm_map_print(vm_map_t map) { - vm_map_entry_t entry; + vm_map_entry_t entry, prev; db_iprintf("Task map %p: pmap=%p, nentries=%d, version=%u\n", (void *)map, (void *)map->pmap, map->nentries, map->timestamp); db_indent += 2; - for (entry = map->header.next; entry != &map->header; - entry = entry->next) { + for (prev = &map->header; (entry = prev->next) != &map->header; + prev = entry) { db_iprintf("map entry %p: start=%p, end=%p, eflags=%#x, \n", (void *)entry, (void *)entry->start, (void *)entry->end, entry->eflags); @@ -4806,7 +4840,8 @@ vm_map_print(vm_map_t map) db_iprintf(" prot=%x/%x/%s", entry->protection, entry->max_protection, - inheritance_name[(int)(unsigned char)entry->inheritance]); + inheritance_name[(int)(unsigned char) + entry->inheritance]); if (entry->wired_count != 0) db_printf(", wired"); } @@ -4814,9 +4849,9 @@ vm_map_print(vm_map_t map) db_printf(", share=%p, offset=0x%jx\n", (void *)entry->object.sub_map, (uintmax_t)entry->offset); - if ((entry->prev == &map->header) || - (entry->prev->object.sub_map != - entry->object.sub_map)) { + if (prev == &map->header || + prev->object.sub_map != + entry->object.sub_map) { db_indent += 2; vm_map_print((vm_map_t)entry->object.sub_map); db_indent -= 2; @@ -4836,9 +4871,9 @@ vm_map_print(vm_map_t map) (entry->eflags & MAP_ENTRY_NEEDS_COPY) ? "needed" : "done"); db_printf("\n"); - if ((entry->prev == &map->header) || - (entry->prev->object.vm_object != - entry->object.vm_object)) { + if (prev == &map->header || + prev->object.vm_object != + entry->object.vm_object) { db_indent += 2; vm_object_print((db_expr_t)(intptr_t) entry->object.vm_object, diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h index fffda1394d71..3b870baac759 100644 --- a/sys/vm/vm_map.h +++ b/sys/vm/vm_map.h @@ -119,33 +119,37 @@ struct vm_map_entry { struct thread *wiring_thread; }; -#define MAP_ENTRY_NOSYNC 0x0001 -#define MAP_ENTRY_IS_SUB_MAP 0x0002 -#define MAP_ENTRY_COW 0x0004 -#define MAP_ENTRY_NEEDS_COPY 0x0008 -#define MAP_ENTRY_NOFAULT 0x0010 -#define MAP_ENTRY_USER_WIRED 0x0020 +#define MAP_ENTRY_NOSYNC 0x00000001 +#define MAP_ENTRY_IS_SUB_MAP 0x00000002 +#define MAP_ENTRY_COW 0x00000004 +#define MAP_ENTRY_NEEDS_COPY 0x00000008 +#define MAP_ENTRY_NOFAULT 0x00000010 +#define MAP_ENTRY_USER_WIRED 0x00000020 -#define MAP_ENTRY_BEHAV_NORMAL 0x0000 /* default behavior */ -#define MAP_ENTRY_BEHAV_SEQUENTIAL 0x0040 /* expect sequential access */ -#define MAP_ENTRY_BEHAV_RANDOM 0x0080 /* expect random access */ -#define MAP_ENTRY_BEHAV_RESERVED 0x00C0 /* future use */ +#define MAP_ENTRY_BEHAV_NORMAL 0x00000000 /* default behavior */ +#define MAP_ENTRY_BEHAV_SEQUENTIAL 0x00000040 /* expect sequential + access */ +#define MAP_ENTRY_BEHAV_RANDOM 0x00000080 /* expect random + access */ +#define MAP_ENTRY_BEHAV_RESERVED 0x000000c0 /* future use */ +#define MAP_ENTRY_BEHAV_MASK 0x000000c0 +#define MAP_ENTRY_IN_TRANSITION 0x00000100 /* entry being + changed */ +#define MAP_ENTRY_NEEDS_WAKEUP 0x00000200 /* waiters in + transition */ +#define MAP_ENTRY_NOCOREDUMP 0x00000400 /* don't include in + a core */ +#define MAP_ENTRY_VN_EXEC 0x00000800 /* text vnode mapping */ +#define MAP_ENTRY_GROWS_DOWN 0x00001000 /* top-down stacks */ +#define MAP_ENTRY_GROWS_UP 0x00002000 /* bottom-up stacks */ -#define MAP_ENTRY_BEHAV_MASK 0x00C0 - -#define MAP_ENTRY_IN_TRANSITION 0x0100 /* entry being changed */ -#define MAP_ENTRY_NEEDS_WAKEUP 0x0200 /* waiters in transition */ -#define MAP_ENTRY_NOCOREDUMP 0x0400 /* don't include in a core */ -#define MAP_ENTRY_VN_EXEC 0x0800 /* text vnode mapping */ -#define MAP_ENTRY_GROWS_DOWN 0x1000 /* Top-down stacks */ -#define MAP_ENTRY_GROWS_UP 0x2000 /* Bottom-up stacks */ - -#define MAP_ENTRY_WIRE_SKIPPED 0x4000 -#define MAP_ENTRY_VN_WRITECNT 0x8000 /* writeable vnode mapping */ -#define MAP_ENTRY_GUARD 0x10000 -#define MAP_ENTRY_STACK_GAP_DN 0x20000 -#define MAP_ENTRY_STACK_GAP_UP 0x40000 -#define MAP_ENTRY_HEADER 0x80000 +#define MAP_ENTRY_WIRE_SKIPPED 0x00004000 +#define MAP_ENTRY_VN_WRITECNT 0x00008000 /* writeable vnode + mapping */ +#define MAP_ENTRY_GUARD 0x00010000 +#define MAP_ENTRY_STACK_GAP_DN 0x00020000 +#define MAP_ENTRY_STACK_GAP_UP 0x00040000 +#define MAP_ENTRY_HEADER 0x00080000 #ifdef _KERNEL static __inline u_char @@ -334,25 +338,25 @@ long vmspace_resident_count(struct vmspace *vmspace); /* * Copy-on-write flags for vm_map operations */ -#define MAP_INHERIT_SHARE 0x0001 -#define MAP_COPY_ON_WRITE 0x0002 -#define MAP_NOFAULT 0x0004 -#define MAP_PREFAULT 0x0008 -#define MAP_PREFAULT_PARTIAL 0x0010 -#define MAP_DISABLE_SYNCER 0x0020 -#define MAP_CHECK_EXCL 0x0040 -#define MAP_CREATE_GUARD 0x0080 -#define MAP_DISABLE_COREDUMP 0x0100 -#define MAP_PREFAULT_MADVISE 0x0200 /* from (user) madvise request */ -#define MAP_VN_WRITECOUNT 0x0400 -#define MAP_REMAP 0x0800 -#define MAP_STACK_GROWS_DOWN 0x1000 -#define MAP_STACK_GROWS_UP 0x2000 -#define MAP_ACC_CHARGED 0x4000 -#define MAP_ACC_NO_CHARGE 0x8000 -#define MAP_CREATE_STACK_GAP_UP 0x10000 -#define MAP_CREATE_STACK_GAP_DN 0x20000 -#define MAP_VN_EXEC 0x40000 +#define MAP_INHERIT_SHARE 0x00000001 +#define MAP_COPY_ON_WRITE 0x00000002 +#define MAP_NOFAULT 0x00000004 +#define MAP_PREFAULT 0x00000008 +#define MAP_PREFAULT_PARTIAL 0x00000010 +#define MAP_DISABLE_SYNCER 0x00000020 +#define MAP_CHECK_EXCL 0x00000040 +#define MAP_CREATE_GUARD 0x00000080 +#define MAP_DISABLE_COREDUMP 0x00000100 +#define MAP_PREFAULT_MADVISE 0x00000200 /* from (user) madvise request */ +#define MAP_VN_WRITECOUNT 0x00000400 +#define MAP_REMAP 0x00000800 +#define MAP_STACK_GROWS_DOWN 0x00001000 +#define MAP_STACK_GROWS_UP 0x00002000 +#define MAP_ACC_CHARGED 0x00004000 +#define MAP_ACC_NO_CHARGE 0x00008000 +#define MAP_CREATE_STACK_GAP_UP 0x00010000 +#define MAP_CREATE_STACK_GAP_DN 0x00020000 +#define MAP_VN_EXEC 0x00040000 /* * vm_fault option flags diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 597ffe29d95d..cd483527af71 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -179,13 +179,13 @@ sys_mmap(struct thread *td, struct mmap_args *uap) } int -kern_mmap(struct thread *td, uintptr_t addr0, size_t size, int prot, int flags, +kern_mmap(struct thread *td, uintptr_t addr0, size_t len, int prot, int flags, int fd, off_t pos) { struct vmspace *vms; struct file *fp; vm_offset_t addr; - vm_size_t pageoff; + vm_size_t pageoff, size; vm_prot_t cap_maxprot; int align, error; cap_rights_t rights; @@ -210,7 +210,7 @@ kern_mmap(struct thread *td, uintptr_t addr0, size_t size, int prot, int flags, * pos. */ if (!SV_CURPROC_FLAG(SV_AOUT)) { - if ((size == 0 && curproc->p_osrel >= P_OSREL_MAP_ANON) || + if ((len == 0 && curproc->p_osrel >= P_OSREL_MAP_ANON) || ((flags & MAP_ANON) != 0 && (fd != -1 || pos != 0))) return (EINVAL); } else { @@ -255,9 +255,12 @@ kern_mmap(struct thread *td, uintptr_t addr0, size_t size, int prot, int flags, pageoff = (pos & PAGE_MASK); pos -= pageoff; - /* Adjust size for rounding (on both ends). */ - size += pageoff; /* low end... */ - size = (vm_size_t) round_page(size); /* hi end */ + /* Compute size from len by rounding (on both ends). */ + size = len + pageoff; /* low end... */ + size = round_page(size); /* hi end */ + /* Check for rounding up to zero. */ + if (len > size) + return (ENOMEM); /* Ensure alignment is at least a page and fits in a pointer. */ align = flags & MAP_ALIGNMENT_MASK; @@ -314,7 +317,7 @@ kern_mmap(struct thread *td, uintptr_t addr0, size_t size, int prot, int flags, addr = round_page((vm_offset_t)vms->vm_daddr + lim_max(td, RLIMIT_DATA)); } - if (size == 0) { + if (len == 0) { /* * Return success without mapping anything for old * binaries that request a page-aligned mapping of diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 4c124727483a..a90961ce57b5 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -3400,35 +3400,6 @@ vm_page_requeue(vm_page_t m) vm_pqbatch_submit_page(m, atomic_load_8(&m->queue)); } -/* - * vm_page_activate: - * - * Put the specified page on the active list (if appropriate). - * Ensure that act_count is at least ACT_INIT but do not otherwise - * mess with it. - * - * The page must be locked. - */ -void -vm_page_activate(vm_page_t m) -{ - - vm_page_assert_locked(m); - - if (vm_page_wired(m) || (m->oflags & VPO_UNMANAGED) != 0) - return; - if (vm_page_queue(m) == PQ_ACTIVE) { - if (m->act_count < ACT_INIT) - m->act_count = ACT_INIT; - return; - } - - vm_page_dequeue(m); - if (m->act_count < ACT_INIT) - m->act_count = ACT_INIT; - vm_page_enqueue(m, PQ_ACTIVE); -} - /* * vm_page_free_prep: * @@ -3679,6 +3650,35 @@ vm_page_unwire_noq(vm_page_t m) return (false); } +/* + * vm_page_activate: + * + * Put the specified page on the active list (if appropriate). + * Ensure that act_count is at least ACT_INIT but do not otherwise + * mess with it. + * + * The page must be locked. + */ +void +vm_page_activate(vm_page_t m) +{ + + vm_page_assert_locked(m); + + if (vm_page_wired(m) || (m->oflags & VPO_UNMANAGED) != 0) + return; + if (vm_page_queue(m) == PQ_ACTIVE) { + if (m->act_count < ACT_INIT) + m->act_count = ACT_INIT; + return; + } + + vm_page_dequeue(m); + if (m->act_count < ACT_INIT) + m->act_count = ACT_INIT; + vm_page_enqueue(m, PQ_ACTIVE); +} + /* * Move the specified page to the tail of the inactive queue, or requeue * the page if it is already in the inactive queue. diff --git a/sys/vm/vm_reserv.c b/sys/vm/vm_reserv.c index 02188a64cc2d..2aa7d2b0a57b 100644 --- a/sys/vm/vm_reserv.c +++ b/sys/vm/vm_reserv.c @@ -1166,11 +1166,90 @@ vm_reserv_reclaim_inactive(int domain) return (FALSE); } +/* + * Determine whether this reservation has free pages that satisfy the given + * request for contiguous physical memory. Start searching from the lower + * bound, defined by low_index. + * + * The free page queue lock must be held. + */ +static bool +vm_reserv_test_contig(vm_reserv_t rv, u_long npages, vm_paddr_t low, + vm_paddr_t high, u_long alignment, vm_paddr_t boundary) +{ + vm_paddr_t pa, size; + u_long changes; + int bitpos, bits_left, i, hi, lo, n; + + vm_reserv_assert_locked(rv); + size = npages << PAGE_SHIFT; + pa = VM_PAGE_TO_PHYS(&rv->pages[0]); + lo = (pa < low) ? + ((low + PAGE_MASK - pa) >> PAGE_SHIFT) : 0; + i = lo / NBPOPMAP; + changes = rv->popmap[i] | ((1UL << (lo % NBPOPMAP)) - 1); + hi = (pa + VM_LEVEL_0_SIZE > high) ? + ((high + PAGE_MASK - pa) >> PAGE_SHIFT) : VM_LEVEL_0_NPAGES; + n = hi / NBPOPMAP; + bits_left = hi % NBPOPMAP; + hi = lo = -1; + for (;;) { + /* + * "changes" is a bitmask that marks where a new sequence of + * 0s or 1s begins in popmap[i], with last bit in popmap[i-1] + * considered to be 1 if and only if lo == hi. The bits of + * popmap[-1] and popmap[NPOPMAP] are considered all 1s. + */ + changes ^= (changes << 1) | (lo == hi); + while (changes != 0) { + /* + * If the next change marked begins a run of 0s, set + * lo to mark that position. Otherwise set hi and + * look for a satisfactory first page from lo up to hi. + */ + bitpos = ffsl(changes) - 1; + changes ^= 1UL << bitpos; + if (lo == hi) { + lo = NBPOPMAP * i + bitpos; + continue; + } + hi = NBPOPMAP * i + bitpos; + pa = VM_PAGE_TO_PHYS(&rv->pages[lo]); + if ((pa & (alignment - 1)) != 0) { + /* Skip to next aligned page. */ + lo += (((pa - 1) | (alignment - 1)) + 1) >> + PAGE_SHIFT; + if (lo >= VM_LEVEL_0_NPAGES) + return (false); + pa = VM_PAGE_TO_PHYS(&rv->pages[lo]); + } + if (((pa ^ (pa + size - 1)) & ~(boundary - 1)) != 0) { + /* Skip to next boundary-matching page. */ + lo += (((pa - 1) | (boundary - 1)) + 1) >> + PAGE_SHIFT; + if (lo >= VM_LEVEL_0_NPAGES) + return (false); + pa = VM_PAGE_TO_PHYS(&rv->pages[lo]); + } + if (lo * PAGE_SIZE + size <= hi * PAGE_SIZE) + return (true); + lo = hi; + } + if (++i < n) + changes = rv->popmap[i]; + else if (i == n) + changes = bits_left == 0 ? -1UL : + (rv->popmap[n] | (-1UL << bits_left)); + else + return (false); + } +} + /* * Searches the partially populated reservation queue for the least recently * changed reservation with free pages that satisfy the given request for * contiguous physical memory. If a satisfactory reservation is found, it is - * broken. Returns TRUE if a reservation is broken and FALSE otherwise. + * broken. Returns true if a reservation is broken and false otherwise. * * The free page queue lock must be held. */ @@ -1180,21 +1259,19 @@ vm_reserv_reclaim_contig(int domain, u_long npages, vm_paddr_t low, { vm_paddr_t pa, size; vm_reserv_t rv, rvn; - int hi, i, lo, low_index, next_free; if (npages > VM_LEVEL_0_NPAGES - 1) - return (FALSE); + return (false); size = npages << PAGE_SHIFT; vm_reserv_domain_lock(domain); again: for (rv = TAILQ_FIRST(&vm_rvq_partpop[domain]); rv != NULL; rv = rvn) { rvn = TAILQ_NEXT(rv, partpopq); - pa = VM_PAGE_TO_PHYS(&rv->pages[VM_LEVEL_0_NPAGES - 1]); - if (pa + PAGE_SIZE - size < low) { + pa = VM_PAGE_TO_PHYS(&rv->pages[0]); + if (pa + VM_LEVEL_0_SIZE - size < low) { /* This entire reservation is too low; go to next. */ continue; } - pa = VM_PAGE_TO_PHYS(&rv->pages[0]); if (pa + size > high) { /* This entire reservation is too high; go to next. */ continue; @@ -1210,73 +1287,19 @@ vm_reserv_reclaim_contig(int domain, u_long npages, vm_paddr_t low, } } else vm_reserv_domain_unlock(domain); - if (pa < low) { - /* Start the search for free pages at "low". */ - low_index = (low + PAGE_MASK - pa) >> PAGE_SHIFT; - i = low_index / NBPOPMAP; - hi = low_index % NBPOPMAP; - } else - i = hi = 0; - do { - /* Find the next free page. */ - lo = ffsl(~(((1UL << hi) - 1) | rv->popmap[i])); - while (lo == 0 && ++i < NPOPMAP) - lo = ffsl(~rv->popmap[i]); - if (i == NPOPMAP) - break; - /* Convert from ffsl() to ordinary bit numbering. */ - lo--; - next_free = NBPOPMAP * i + lo; - pa = VM_PAGE_TO_PHYS(&rv->pages[next_free]); - KASSERT(pa >= low, - ("vm_reserv_reclaim_contig: pa is too low")); - if (pa + size > high) { - /* The rest of this reservation is too high. */ - break; - } else if ((pa & (alignment - 1)) != 0 || - ((pa ^ (pa + size - 1)) & ~(boundary - 1)) != 0) { - /* - * The current page doesn't meet the alignment - * and/or boundary requirements. Continue - * searching this reservation until the rest - * of its free pages are either excluded or - * exhausted. - */ - hi = lo + 1; - if (hi >= NBPOPMAP) { - hi = 0; - i++; - } - continue; - } - /* Find the next used page. */ - hi = ffsl(rv->popmap[i] & ~((1UL << lo) - 1)); - while (hi == 0 && ++i < NPOPMAP) { - if ((NBPOPMAP * i - next_free) * PAGE_SIZE >= - size) { - vm_reserv_reclaim(rv); - vm_reserv_unlock(rv); - return (TRUE); - } - hi = ffsl(rv->popmap[i]); - } - /* Convert from ffsl() to ordinary bit numbering. */ - if (i != NPOPMAP) - hi--; - if ((NBPOPMAP * i + hi - next_free) * PAGE_SIZE >= - size) { - vm_reserv_reclaim(rv); - vm_reserv_unlock(rv); - return (TRUE); - } - } while (i < NPOPMAP); + if (vm_reserv_test_contig(rv, npages, low, high, + alignment, boundary)) { + vm_reserv_reclaim(rv); + vm_reserv_unlock(rv); + return (true); + } vm_reserv_unlock(rv); vm_reserv_domain_lock(domain); if (rvn != NULL && !rvn->inpartpopq) goto again; } vm_reserv_domain_unlock(domain); - return (FALSE); + return (false); } /* diff --git a/sys/x86/x86/mca.c b/sys/x86/x86/mca.c index 1665ab4fa216..aebb46b8fd72 100644 --- a/sys/x86/x86/mca.c +++ b/sys/x86/x86/mca.c @@ -86,7 +86,6 @@ struct amd_et_state { struct mca_internal { struct mca_record rec; - int logged; STAILQ_ENTRY(mca_internal) link; }; @@ -101,6 +100,7 @@ static MALLOC_DEFINE(M_MCA, "MCA", "Machine Check Architecture"); static volatile int mca_count; /* Number of records stored. */ static int mca_banks; /* Number of per-CPU register banks. */ +static int mca_maxcount = -1; /* Limit on records stored. (-1 = unlimited) */ static SYSCTL_NODE(_hw, OID_AUTO, mca, CTLFLAG_RD, NULL, "Machine Check Architecture"); @@ -125,10 +125,11 @@ SYSCTL_INT(_hw_mca, OID_AUTO, erratum383, CTLFLAG_RDTUN, static STAILQ_HEAD(, mca_internal) mca_freelist; static int mca_freecount; static STAILQ_HEAD(, mca_internal) mca_records; +static STAILQ_HEAD(, mca_internal) mca_pending; static struct callout mca_timer; static int mca_ticks = 3600; /* Check hourly by default. */ static struct taskqueue *mca_tq; -static struct task mca_refill_task, mca_scan_task; +static struct task mca_resize_task, mca_scan_task; static struct mtx mca_lock; static unsigned int @@ -557,32 +558,49 @@ mca_check_status(int bank, struct mca_record *rec) } static void -mca_fill_freelist(void) +mca_resize_freelist(void) { - struct mca_internal *rec; - int desired; + struct mca_internal *next, *rec; + STAILQ_HEAD(, mca_internal) tmplist; + int count, i, desired_max, desired_min; /* * Ensure we have at least one record for each bank and one - * record per CPU. + * record per CPU, but no more than twice that amount. */ - desired = imax(mp_ncpus, mca_banks); + desired_min = imax(mp_ncpus, mca_banks); + desired_max = imax(mp_ncpus, mca_banks) * 2; + STAILQ_INIT(&tmplist); mtx_lock_spin(&mca_lock); - while (mca_freecount < desired) { + while (mca_freecount > desired_max) { + rec = STAILQ_FIRST(&mca_freelist); + KASSERT(rec != NULL, ("mca_freecount is %d, but list is empty", + mca_freecount)); + STAILQ_REMOVE_HEAD(&mca_freelist, link); + mca_freecount--; + STAILQ_INSERT_TAIL(&tmplist, rec, link); + } + while (mca_freecount < desired_min) { + count = desired_min - mca_freecount; mtx_unlock_spin(&mca_lock); - rec = malloc(sizeof(*rec), M_MCA, M_WAITOK); + for (i = 0; i < count; i++) { + rec = malloc(sizeof(*rec), M_MCA, M_WAITOK); + STAILQ_INSERT_TAIL(&tmplist, rec, link); + } mtx_lock_spin(&mca_lock); - STAILQ_INSERT_TAIL(&mca_freelist, rec, link); - mca_freecount++; + STAILQ_CONCAT(&mca_freelist, &tmplist); + mca_freecount += count; } mtx_unlock_spin(&mca_lock); + STAILQ_FOREACH_SAFE(rec, &tmplist, link, next) + free(rec, M_MCA); } static void -mca_refill(void *context, int pending) +mca_resize(void *context, int pending) { - mca_fill_freelist(); + mca_resize_freelist(); } static void @@ -607,12 +625,8 @@ mca_record_entry(enum scan_mode mode, const struct mca_record *record) } rec->rec = *record; - rec->logged = 0; - STAILQ_INSERT_TAIL(&mca_records, rec, link); - mca_count++; + STAILQ_INSERT_TAIL(&mca_pending, rec, link); mtx_unlock_spin(&mca_lock); - if (mode == CMCI && !cold) - taskqueue_enqueue(mca_tq, &mca_refill_task); } #ifdef DEV_APIC @@ -788,13 +802,68 @@ mca_scan(enum scan_mode mode, int *recoverablep) } #endif } - if (mode == POLLED) - mca_fill_freelist(); if (recoverablep != NULL) *recoverablep = recoverable; return (count); } +/* + * Store a new record on the mca_records list while enforcing + * mca_maxcount. + */ +static void +mca_store_record(struct mca_internal *mca) +{ + + /* + * If we are storing no records (mca_maxcount == 0), + * we just free this record. + * + * If we are storing records (mca_maxcount != 0) and + * we have free space on the list, store the record + * and increment mca_count. + * + * If we are storing records and we do not have free + * space on the list, store the new record at the + * tail and free the oldest one from the head. + */ + if (mca_maxcount != 0) + STAILQ_INSERT_TAIL(&mca_records, mca, link); + if (mca_maxcount < 0 || mca_count < mca_maxcount) + mca_count++; + else { + if (mca_maxcount != 0) { + mca = STAILQ_FIRST(&mca_records); + STAILQ_REMOVE_HEAD(&mca_records, link); + } + STAILQ_INSERT_TAIL(&mca_freelist, mca, link); + mca_freecount++; + } +} + +/* + * Do the work to process machine check records which have just been + * gathered. Print any pending logs to the console. Queue them for storage. + * Trigger a resizing of the free list. + */ +static void +mca_process_records(enum scan_mode mode) +{ + struct mca_internal *mca; + + mtx_lock_spin(&mca_lock); + while ((mca = STAILQ_FIRST(&mca_pending)) != NULL) { + STAILQ_REMOVE_HEAD(&mca_pending, link); + mca_log(&mca->rec); + mca_store_record(mca); + } + mtx_unlock_spin(&mca_lock); + if (mode == POLLED) + mca_resize_freelist(); + else if (!cold) + taskqueue_enqueue(mca_tq, &mca_resize_task); +} + /* * Scan the machine check banks on all CPUs by binding to each CPU in * turn. If any of the CPUs contained new machine check records, log @@ -803,11 +872,10 @@ mca_scan(enum scan_mode mode, int *recoverablep) static void mca_scan_cpus(void *context, int pending) { - struct mca_internal *mca; struct thread *td; int count, cpu; - mca_fill_freelist(); + mca_resize_freelist(); td = curthread; count = 0; thread_lock(td); @@ -819,16 +887,8 @@ mca_scan_cpus(void *context, int pending) sched_unbind(td); } thread_unlock(td); - if (count != 0) { - mtx_lock_spin(&mca_lock); - STAILQ_FOREACH(mca, &mca_records, link) { - if (!mca->logged) { - mca->logged = 1; - mca_log(&mca->rec); - } - } - mtx_unlock_spin(&mca_lock); - } + if (count != 0) + mca_process_records(POLLED); } static void @@ -853,6 +913,35 @@ sysctl_mca_scan(SYSCTL_HANDLER_ARGS) return (0); } +static int +sysctl_mca_maxcount(SYSCTL_HANDLER_ARGS) +{ + struct mca_internal *mca; + int error, i; + bool doresize; + + i = mca_maxcount; + error = sysctl_handle_int(oidp, &i, 0, req); + if (error || req->newptr == NULL) + return (error); + mtx_lock_spin(&mca_lock); + mca_maxcount = i; + doresize = false; + if (mca_maxcount >= 0) + while (mca_count > mca_maxcount) { + mca = STAILQ_FIRST(&mca_records); + STAILQ_REMOVE_HEAD(&mca_records, link); + mca_count--; + STAILQ_INSERT_TAIL(&mca_freelist, mca, link); + mca_freecount++; + doresize = true; + } + mtx_unlock_spin(&mca_lock); + if (doresize && !cold) + taskqueue_enqueue(mca_tq, &mca_resize_task); + return (error); +} + static void mca_createtq(void *dummy) { @@ -864,7 +953,7 @@ mca_createtq(void *dummy) taskqueue_start_threads(&mca_tq, 1, PI_SWI(SWI_TQ), "mca taskq"); /* CMCIs during boot may have claimed items from the freelist. */ - mca_fill_freelist(); + mca_resize_freelist(); } SYSINIT(mca_createtq, SI_SUB_CONFIGURE, SI_ORDER_ANY, mca_createtq, NULL); @@ -933,14 +1022,19 @@ mca_setup(uint64_t mcg_cap) mca_banks = mcg_cap & MCG_CAP_COUNT; mtx_init(&mca_lock, "mca", NULL, MTX_SPIN); STAILQ_INIT(&mca_records); + STAILQ_INIT(&mca_pending); TASK_INIT(&mca_scan_task, 0, mca_scan_cpus, NULL); callout_init(&mca_timer, 1); STAILQ_INIT(&mca_freelist); - TASK_INIT(&mca_refill_task, 0, mca_refill, NULL); - mca_fill_freelist(); + TASK_INIT(&mca_resize_task, 0, mca_resize, NULL); + mca_resize_freelist(); SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_mca), OID_AUTO, "count", CTLFLAG_RD, (int *)(uintptr_t)&mca_count, 0, "Record count"); + SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_mca), OID_AUTO, + "maxcount", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, + &mca_maxcount, 0, sysctl_mca_maxcount, "I", + "Maximum record count (-1 is unlimited)"); SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_mca), OID_AUTO, "interval", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, &mca_ticks, 0, sysctl_positive_int, "I", @@ -1322,25 +1416,14 @@ mca_intr(void) void cmc_intr(void) { - struct mca_internal *mca; - int count; /* * Serialize MCA bank scanning to prevent collisions from * sibling threads. + * + * If we found anything, log them to the console. */ - count = mca_scan(CMCI, NULL); - - /* If we found anything, log them to the console. */ - if (count != 0) { - mtx_lock_spin(&mca_lock); - STAILQ_FOREACH(mca, &mca_records, link) { - if (!mca->logged) { - mca->logged = 1; - mca_log(&mca->rec); - } - } - mtx_unlock_spin(&mca_lock); - } + if (mca_scan(CMCI, NULL) != 0) + mca_process_records(CMCI); } #endif diff --git a/tests/sys/Makefile b/tests/sys/Makefile index f8f6ff3925e3..44d1e03c6c73 100644 --- a/tests/sys/Makefile +++ b/tests/sys/Makefile @@ -10,6 +10,7 @@ TESTS_SUBDIRS+= ${_audit} TESTS_SUBDIRS+= auditpipe TESTS_SUBDIRS+= capsicum TESTS_SUBDIRS+= ${_cddl} +TESTS_SUBDIRS+= devrandom TESTS_SUBDIRS+= fifo TESTS_SUBDIRS+= file TESTS_SUBDIRS+= fs diff --git a/tests/sys/devrandom/Makefile b/tests/sys/devrandom/Makefile new file mode 100644 index 000000000000..db9f9d42a470 --- /dev/null +++ b/tests/sys/devrandom/Makefile @@ -0,0 +1,26 @@ +# $FreeBSD$ + +.include + +SDEVRANDOM= ${SRCTOP}/sys/dev/random +.PATH: ${SDEVRANDOM} + +TESTSDIR= ${TESTSBASE}/sys/devrandom +WARNS?= 6 + +CFLAGS+= -I${SRCTOP}/sys + +ATF_TESTS_C+= uint128_test + +# Test Chacha CTR behavior <-> uint128 +LDADD.uint128_test+= ${SDEVRANDOM}/hash.c +LDFLAGS.uint128_test+= -Wno-unused-parameter + +# hash.c deps: +LIBADD.uint128_test+= md # SHA256 +LDADD.uint128_test+= ${SRCTOP}/sys/crypto/rijndael/rijndael-alg-fst.c +LDADD.uint128_test+= ${SRCTOP}/sys/crypto/rijndael/rijndael-api-fst.c +LDFLAGS.uint128_test+= -Wno-cast-align + + +.include diff --git a/tests/sys/devrandom/uint128_test.c b/tests/sys/devrandom/uint128_test.c new file mode 100644 index 000000000000..288e8a2e9f79 --- /dev/null +++ b/tests/sys/devrandom/uint128_test.c @@ -0,0 +1,281 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2019 Conrad Meyer + * 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 + +static void +vec_u32_tole128(uint8_t dst[static 16], const uint32_t src[static 4]) +{ + le32enc(dst, src[0]); + le32enc(&dst[4], src[1]); + le32enc(&dst[8], src[2]); + le32enc(&dst[12], src[3]); +} + +static void +le128_to_vec_u32(uint32_t dst[static 4], const uint8_t src[static 16]) +{ + dst[0] = le32dec(src); + dst[1] = le32dec(&src[4]); + dst[2] = le32dec(&src[8]); + dst[3] = le32dec(&src[12]); +} + +static void +formatu128(char buf[static 52], uint128_t x) +{ + uint8_t le128x[16]; + uint32_t vx[4]; + size_t sz, i; + int rc; + + le128enc(le128x, x); + le128_to_vec_u32(vx, le128x); + + sz = 52; + for (i = 0; i < 4; i++) { + rc = snprintf(buf, sz, "0x%x ", vx[i]); + ATF_REQUIRE(rc > 0 && (size_t)rc < sz); + + buf += rc; + sz -= rc; + } + /* Delete last trailing space */ + buf[-1] = '\0'; +} + +static void +u128_check_equality(uint128_t a, uint128_t b, const char *descr) +{ + char fmtbufa[52], fmtbufb[52]; + + formatu128(fmtbufa, a); + formatu128(fmtbufb, b); + + ATF_CHECK_MSG(uint128_equals(a, b), + "Expected: [%s] != Actual: [%s]: %s", fmtbufa, fmtbufb, descr); +} + +ATF_TC_WITHOUT_HEAD(uint128_inc); +ATF_TC_BODY(uint128_inc, tc) +{ + static const struct u128_inc_tc { + uint32_t input[4]; + uint32_t expected[4]; + const char *descr; + } tests[] = { + { + .input = { 0, 0, 0, 0 }, + .expected = { 1, 0, 0, 0 }, + .descr = "0 -> 1", + }, + { + .input = { 1, 0, 0, 0 }, + .expected = { 2, 0, 0, 0 }, + .descr = "0 -> 2", + }, + { + .input = { 0xff, 0, 0, 0 }, + .expected = { 0x100, 0, 0, 0 }, + .descr = "0xff -> 0x100 (byte carry)", + }, + { + .input = { UINT32_MAX, 0, 0, 0 }, + .expected = { 0, 1, 0, 0 }, + .descr = "2^32 - 1 -> 2^32 (word carry)", + }, + { + .input = { UINT32_MAX, UINT32_MAX, 0, 0 }, + .expected = { 0, 0, 1, 0 }, + .descr = "2^64 - 1 -> 2^64 (u128t_word0 carry)", + }, + { + .input = { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 }, + .expected = { 0, 0, 0, 1 }, + .descr = "2^96 - 1 -> 2^96 (word carry)", + }, + }; + uint8_t inputle[16], expectedle[16]; + uint128_t a; + size_t i; + + for (i = 0; i < nitems(tests); i++) { + vec_u32_tole128(inputle, tests[i].input); + vec_u32_tole128(expectedle, tests[i].expected); + + a = le128dec(inputle); + uint128_increment(&a); + u128_check_equality(le128dec(expectedle), a, tests[i].descr); + } +} + +ATF_TC_WITHOUT_HEAD(uint128_add64); +ATF_TC_BODY(uint128_add64, tc) +{ + static const struct u128_add64_tc { + uint32_t input[4]; + uint64_t addend; + uint32_t expected[4]; + const char *descr; + } tests[] = { + { + .input = { 0, 0, 0, 0 }, + .addend = 1, + .expected = { 1, 0, 0, 0 }, + .descr = "0 + 1 -> 1", + }, + { + .input = { 1, 0, 0, 0 }, + .addend = UINT32_MAX, + .expected = { 0, 1, 0, 0 }, + .descr = "1 + (2^32 - 1) -> 2^32 (word carry)", + }, + { + .input = { 1, 0, 0, 0 }, + .addend = UINT64_MAX, + .expected = { 0, 0, 1, 0 }, + .descr = "1 + (2^64 - 1) -> 2^64 (u128t_word0 carry)", + }, + { + .input = { 0x11111111, 0x11111111, 0, 0 }, + .addend = 0xf0123456789abcdeULL, + .expected = { 0x89abcdef, 0x01234567, 1, 0 }, + .descr = "0x1111_1111_1111_1111 +" + "0xf012_3456_789a_bcde ->" + "0x1_0123_4567_89ab_cdef", + }, + { + .input = { 1, 0, UINT32_MAX, 0 }, + .addend = UINT64_MAX, + .expected = { 0, 0, 0, 1 }, + .descr = "Carry ~2^96", + }, + }; + uint8_t inputle[16], expectedle[16]; + uint128_t a; + size_t i; + + for (i = 0; i < nitems(tests); i++) { + vec_u32_tole128(inputle, tests[i].input); + vec_u32_tole128(expectedle, tests[i].expected); + + a = le128dec(inputle); + uint128_add64(&a, tests[i].addend); + u128_check_equality(le128dec(expectedle), a, tests[i].descr); + } +} + +/* + * Test assumptions about Chacha incrementing counter in the same way as + * uint128.h + */ +ATF_TC_WITHOUT_HEAD(uint128_chacha_ctr); +ATF_TC_BODY(uint128_chacha_ctr, tc) +{ + static const struct u128_chacha_tc { + uint32_t input[4]; + uint32_t expected[4]; + const char *descr; + } tests[] = { + { + .input = { 0, 0, 0, 0 }, + .expected = { 1, 0, 0, 0 }, + .descr = "Single block", + }, + { + .input = { 1, 0, 0, 0 }, + .expected = { 2, 0, 0, 0 }, + .descr = "0 -> 2", + }, + { + .input = { 0xff, 0, 0, 0 }, + .expected = { 0x100, 0, 0, 0 }, + .descr = "0xff -> 0x100 (byte carry)", + }, + { + .input = { UINT32_MAX, 0, 0, 0 }, + .expected = { 0, 1, 0, 0 }, + .descr = "2^32 - 1 -> 2^32 (word carry)", + }, + { + .input = { UINT32_MAX, UINT32_MAX, 0, 0 }, + .expected = { 0, 0, 1, 0 }, + .descr = "2^64 - 1 -> 2^64 (u128t_word0 carry)", + }, + { + .input = { UINT32_MAX, UINT32_MAX, UINT32_MAX, 0 }, + .expected = { 0, 0, 0, 1 }, + .descr = "2^96 - 1 -> 2^96 (word carry)", + }, + }; + union randomdev_key context; + uint8_t inputle[16], expectedle[16], trash[CHACHA_BLOCKLEN]; + uint8_t notrandomkey[RANDOM_KEYSIZE] = { 0 }; + uint128_t a; + size_t i; + + random_chachamode = true; + randomdev_encrypt_init(&context, notrandomkey); + + for (i = 0; i < nitems(tests); i++) { + vec_u32_tole128(inputle, tests[i].input); + vec_u32_tole128(expectedle, tests[i].expected); + + a = le128dec(inputle); + randomdev_keystream(&context, &a, trash, sizeof(trash)); + u128_check_equality(le128dec(expectedle), a, tests[i].descr); + } + +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, uint128_inc); + ATF_TP_ADD_TC(tp, uint128_add64); + ATF_TP_ADD_TC(tp, uint128_chacha_ctr); + return (atf_no_error()); +} diff --git a/tests/sys/kern/Makefile b/tests/sys/kern/Makefile index cf2d04706a1c..180734f4d242 100644 --- a/tests/sys/kern/Makefile +++ b/tests/sys/kern/Makefile @@ -46,7 +46,6 @@ LIBADD.mqueue_test+= rt ${MACHINE_ARCH} == "i386" || \ ${MACHINE_ARCH} == "aarch64" ATF_TESTS_C+= libkern_crc32 -CFLAGS.libkern_crc32+= -DUSERSPACE_TESTING .if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386" LDADD.libkern_crc32+= ${SRCTOP}/sys/libkern/x86/crc32_sse42.c .else diff --git a/tests/sys/kern/libkern_crc32.c b/tests/sys/kern/libkern_crc32.c index 03d023124346..39cb8ca5aeeb 100644 --- a/tests/sys/kern/libkern_crc32.c +++ b/tests/sys/kern/libkern_crc32.c @@ -27,16 +27,13 @@ */ #include +#include #include #include -#if defined(__amd64__) || defined(__i386__) -extern uint32_t sse42_crc32c(uint32_t, const unsigned char *, unsigned); -#elif defined(__aarch64__) -extern uint32_t armv8_crc32c(uint32_t, const unsigned char *, unsigned); -#else +#if !defined(__amd64__) && !defined(__i386__) && !defined(__aarch64__) #error These tests are not supported on this platform #endif diff --git a/tests/sys/net/if_clone_test.sh b/tests/sys/net/if_clone_test.sh index 02b5e8465b64..abe0ce2a0736 100755 --- a/tests/sys/net/if_clone_test.sh +++ b/tests/sys/net/if_clone_test.sh @@ -39,6 +39,52 @@ TESTLEN=10 # seconds +atf_test_case epair_stress cleanup +epair_stress_head() +{ + atf_set "descr" "Simultaneously create and destroy an epair(4)" + atf_set "require.user" "root" +} +epair_stress_body() +{ + do_stress "epair" +} +epair_stress_cleanup() +{ + cleanup_ifaces +} + +atf_test_case epair_up_stress cleanup +epair_up_stress_head() +{ + atf_set "descr" "Simultaneously up and detroy an epair(4)" + atf_set "require.user" "root" +} +epair_up_stress_body() +{ + do_up_stress "epair" "" "" +} +epair_up_stress_cleanup() +{ + cleanup_ifaces +} + +atf_test_case epair_ipv6_up_stress cleanup +epair_ipv6_up_stress_head() +{ + atf_set "descr" "Simultaneously up and destroy an epair(4) with IPv6" + atf_set "require.user" "root" +} +epair_ipv6_up_stress_body() +{ + atf_skip "Quickly panics: page fault in in6_unlink_ifa (PR 225438)" + do_up_stress "epair" "6" "" +} +epair_ipv6_up_stress_cleanup() +{ + cleanup_ifaces +} + atf_test_case faith_stress cleanup faith_stress_head() { @@ -369,7 +415,9 @@ vmnet_ipv6_up_stress_cleanup() atf_init_test_cases() { - # TODO: add epair(4) tests, which need a different syntax + atf_add_test_case epair_ipv6_up_stress + atf_add_test_case epair_stress + atf_add_test_case epair_up_stress atf_add_test_case faith_ipv6_up_stress atf_add_test_case faith_stress atf_add_test_case faith_up_stress @@ -396,13 +444,13 @@ atf_init_test_cases() do_stress() { - local IFACE + local IFACE CREATOR_PID DESTROYER_PID IFACE=`get_iface $1` # First thread: create the interface while true; do - ifconfig $IFACE create 2>/dev/null && \ + ifconfig ${IFACE%a} create 2>/dev/null && \ echo -n . >> creator_count.txt done & CREATOR_PID=$! @@ -417,7 +465,7 @@ do_stress() sleep ${TESTLEN} kill $CREATOR_PID kill $DESTROYER_PID - echo "Created $IFACE `stat -f %z creator_count.txt` times." + echo "Created ${IFACE%a} `stat -f %z creator_count.txt` times." echo "Destroyed it `stat -f %z destroyer_count.txt` times." } @@ -428,7 +476,8 @@ do_stress() # $3 p2p for point to point interfaces, anything else for normal interfaces do_up_stress() { - local IFACE IPv6 MAC P2P SRCDIR + local ADDR DSTADDR MASK MEAN_SLEEP_SECONDS MAX_SLEEP_USECS \ + IFACE IPV6 P2P SRCDIR LOOP_PID ipv6_cmd up_cmd # Configure the interface to use an RFC5737 nonrouteable addresses ADDR="192.0.2.2" @@ -464,7 +513,7 @@ do_up_stress() ifconfig $IFACE destroy && echo -n . >> destroy_count.txt ; } & wait - ifconfig $IFACE create + ifconfig ${IFACE%a} create done & LOOP_PID=$! @@ -489,7 +538,11 @@ get_iface() N=$(($N + 1)) fi done - local DEV=${CLASS}${N} + if [ ${CLASS} = "epair" ]; then + DEV=${CLASS}${N}a + else + DEV=${CLASS}${N} + fi # Record the device so we can clean it up later echo ${DEV} >> "devices_to_cleanup" echo ${DEV} @@ -501,11 +554,7 @@ cleanup_ifaces() local DEV for DEV in `cat "devices_to_cleanup"`; do - if [ ${DEV%%[0-9]*a} = "epair" ]; then - ifconfig ${DEV}a destroy - else - ifconfig ${DEV} destroy - fi + ifconfig ${DEV} destroy done true } diff --git a/tools/build/Makefile b/tools/build/Makefile index 8e08809eac95..e1ff4f9c8f07 100644 --- a/tools/build/Makefile +++ b/tools/build/Makefile @@ -70,7 +70,8 @@ SUBDIR= cross-build .endif # Needed to build config (since it uses libnv) -SYSINCS+= ${SRCTOP}/sys/sys/nv.h ${SRCTOP}/sys/sys/cnv.h +SYSINCS+= ${SRCTOP}/sys/sys/nv.h ${SRCTOP}/sys/sys/cnv.h \ + ${SRCTOP}/sys/sys/dnv.h # We want to run the build with only ${WORLDTMP} in $PATH to ensure we don't # accidentally run tools that are incompatible but happen to be in $PATH. diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index 728f3d6525c8..58592329e11d 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -1374,159 +1374,160 @@ OLD_FILES+=usr/bin/clang-tblgen OLD_FILES+=usr/bin/llvm-ar OLD_FILES+=usr/bin/llvm-nm OLD_FILES+=usr/bin/llvm-objdump +OLD_FILES+=usr/bin/llvm-ranlib OLD_FILES+=usr/bin/llvm-symbolizer OLD_FILES+=usr/bin/llvm-tblgen -OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/allocator_interface.h -OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/asan_interface.h -OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/common_interface_defs.h -OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/coverage_interface.h -OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/dfsan_interface.h -OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/esan_interface.h -OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/hwasan_interface.h -OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/linux_syscall_hooks.h -OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/lsan_interface.h -OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/msan_interface.h -OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/netbsd_syscall_hooks.h -OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/scudo_interface.h -OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/tsan_interface.h -OLD_FILES+=usr/lib/clang/8.0.0/include/sanitizer/tsan_interface_atomic.h -OLD_DIRS+=usr/lib/clang/8.0.0/include/sanitizer -OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_builtin_vars.h -OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_cmath.h -OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_complex_builtins.h -OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_device_functions.h -OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_intrinsics.h -OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_libdevice_declares.h -OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_math_forward_declares.h -OLD_FILES+=usr/lib/clang/8.0.0/include/__clang_cuda_runtime_wrapper.h -OLD_FILES+=usr/lib/clang/8.0.0/include/__stddef_max_align_t.h -OLD_FILES+=usr/lib/clang/8.0.0/include/__wmmintrin_aes.h -OLD_FILES+=usr/lib/clang/8.0.0/include/__wmmintrin_pclmul.h -OLD_FILES+=usr/lib/clang/8.0.0/include/adxintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/altivec.h -OLD_FILES+=usr/lib/clang/8.0.0/include/ammintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/arm64intr.h -OLD_FILES+=usr/lib/clang/8.0.0/include/arm_acle.h -OLD_FILES+=usr/lib/clang/8.0.0/include/arm_fp16.h -OLD_FILES+=usr/lib/clang/8.0.0/include/arm_neon.h -OLD_FILES+=usr/lib/clang/8.0.0/include/armintr.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx2intrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512bitalgintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512bwintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512cdintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512dqintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512erintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512fintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512ifmaintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512ifmavlintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512pfintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vbmi2intrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vbmiintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vbmivlintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vlbitalgintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vlbwintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vlcdintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vldqintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vlintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vlvbmi2intrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vlvnniintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vnniintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vpopcntdqintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avx512vpopcntdqvlintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/avxintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/bmi2intrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/bmiintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/cetintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/cldemoteintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/clflushoptintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/clwbintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/clzerointrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/cpuid.h -OLD_FILES+=usr/lib/clang/8.0.0/include/emmintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/f16cintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/fma4intrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/fmaintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/fxsrintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/gfniintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/htmintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/htmxlintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/ia32intrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/immintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/invpcidintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/lwpintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/lzcntintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/mm3dnow.h -OLD_FILES+=usr/lib/clang/8.0.0/include/mm_malloc.h -OLD_FILES+=usr/lib/clang/8.0.0/include/mmintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/module.modulemap -OLD_FILES+=usr/lib/clang/8.0.0/include/movdirintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/msa.h -OLD_FILES+=usr/lib/clang/8.0.0/include/mwaitxintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/nmmintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/opencl-c.h -OLD_FILES+=usr/lib/clang/8.0.0/include/pconfigintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/pkuintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/pmmintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/popcntintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/prfchwintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/ptwriteintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/rdseedintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/rtmintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/s390intrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/sgxintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/shaintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/smmintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/tbmintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/tmmintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/vadefs.h -OLD_FILES+=usr/lib/clang/8.0.0/include/vaesintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/vecintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/vpclmulqdqintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/waitpkgintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/wbnoinvdintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/wmmintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/x86intrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/xmmintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/xopintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/xsavecintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/xsaveintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/xsaveoptintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/xsavesintrin.h -OLD_FILES+=usr/lib/clang/8.0.0/include/xtestintrin.h -OLD_DIRS+=usr/lib/clang/8.0.0/include -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan-i386.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan-i386.so -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan-preinit-i386.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan-preinit-x86_64.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan-x86_64.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan-x86_64.so -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan_cxx-i386.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.asan_cxx-x86_64.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.msan-i386.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.msan-x86_64.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.msan_cxx-i386.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.msan_cxx-x86_64.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.profile-arm.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.profile-armhf.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.profile-i386.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.profile-x86_64.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.safestack-i386.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.safestack-x86_64.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.stats-i386.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.stats-x86_64.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.stats_client-i386.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.stats_client-x86_64.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.tsan-x86_64.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.tsan_cxx-x86_64.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.ubsan_minimal-i386.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.ubsan_minimal-x86_64.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.ubsan_standalone-i386.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.ubsan_standalone-x86_64.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.ubsan_standalone_cxx-i386.a -OLD_FILES+=usr/lib/clang/8.0.0/lib/freebsd/libclang_rt.ubsan_standalone_cxx-x86_64.a -OLD_DIRS+=usr/lib/clang/8.0.0/lib/freebsd -OLD_DIRS+=usr/lib/clang/8.0.0/lib -OLD_DIRS+=usr/lib/clang/8.0.0 +OLD_FILES+=usr/lib/clang/8.0.1/include/sanitizer/allocator_interface.h +OLD_FILES+=usr/lib/clang/8.0.1/include/sanitizer/asan_interface.h +OLD_FILES+=usr/lib/clang/8.0.1/include/sanitizer/common_interface_defs.h +OLD_FILES+=usr/lib/clang/8.0.1/include/sanitizer/coverage_interface.h +OLD_FILES+=usr/lib/clang/8.0.1/include/sanitizer/dfsan_interface.h +OLD_FILES+=usr/lib/clang/8.0.1/include/sanitizer/esan_interface.h +OLD_FILES+=usr/lib/clang/8.0.1/include/sanitizer/hwasan_interface.h +OLD_FILES+=usr/lib/clang/8.0.1/include/sanitizer/linux_syscall_hooks.h +OLD_FILES+=usr/lib/clang/8.0.1/include/sanitizer/lsan_interface.h +OLD_FILES+=usr/lib/clang/8.0.1/include/sanitizer/msan_interface.h +OLD_FILES+=usr/lib/clang/8.0.1/include/sanitizer/netbsd_syscall_hooks.h +OLD_FILES+=usr/lib/clang/8.0.1/include/sanitizer/scudo_interface.h +OLD_FILES+=usr/lib/clang/8.0.1/include/sanitizer/tsan_interface.h +OLD_FILES+=usr/lib/clang/8.0.1/include/sanitizer/tsan_interface_atomic.h +OLD_DIRS+=usr/lib/clang/8.0.1/include/sanitizer +OLD_FILES+=usr/lib/clang/8.0.1/include/__clang_cuda_builtin_vars.h +OLD_FILES+=usr/lib/clang/8.0.1/include/__clang_cuda_cmath.h +OLD_FILES+=usr/lib/clang/8.0.1/include/__clang_cuda_complex_builtins.h +OLD_FILES+=usr/lib/clang/8.0.1/include/__clang_cuda_device_functions.h +OLD_FILES+=usr/lib/clang/8.0.1/include/__clang_cuda_intrinsics.h +OLD_FILES+=usr/lib/clang/8.0.1/include/__clang_cuda_libdevice_declares.h +OLD_FILES+=usr/lib/clang/8.0.1/include/__clang_cuda_math_forward_declares.h +OLD_FILES+=usr/lib/clang/8.0.1/include/__clang_cuda_runtime_wrapper.h +OLD_FILES+=usr/lib/clang/8.0.1/include/__stddef_max_align_t.h +OLD_FILES+=usr/lib/clang/8.0.1/include/__wmmintrin_aes.h +OLD_FILES+=usr/lib/clang/8.0.1/include/__wmmintrin_pclmul.h +OLD_FILES+=usr/lib/clang/8.0.1/include/adxintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/altivec.h +OLD_FILES+=usr/lib/clang/8.0.1/include/ammintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/arm64intr.h +OLD_FILES+=usr/lib/clang/8.0.1/include/arm_acle.h +OLD_FILES+=usr/lib/clang/8.0.1/include/arm_fp16.h +OLD_FILES+=usr/lib/clang/8.0.1/include/arm_neon.h +OLD_FILES+=usr/lib/clang/8.0.1/include/armintr.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx2intrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512bitalgintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512bwintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512cdintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512dqintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512erintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512fintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512ifmaintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512ifmavlintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512pfintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512vbmi2intrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512vbmiintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512vbmivlintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512vlbitalgintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512vlbwintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512vlcdintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512vldqintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512vlintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512vlvbmi2intrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512vlvnniintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512vnniintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512vpopcntdqintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avx512vpopcntdqvlintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/avxintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/bmi2intrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/bmiintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/cetintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/cldemoteintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/clflushoptintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/clwbintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/clzerointrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/cpuid.h +OLD_FILES+=usr/lib/clang/8.0.1/include/emmintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/f16cintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/fma4intrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/fmaintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/fxsrintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/gfniintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/htmintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/htmxlintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/ia32intrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/immintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/invpcidintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/lwpintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/lzcntintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/mm3dnow.h +OLD_FILES+=usr/lib/clang/8.0.1/include/mm_malloc.h +OLD_FILES+=usr/lib/clang/8.0.1/include/mmintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/module.modulemap +OLD_FILES+=usr/lib/clang/8.0.1/include/movdirintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/msa.h +OLD_FILES+=usr/lib/clang/8.0.1/include/mwaitxintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/nmmintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/opencl-c.h +OLD_FILES+=usr/lib/clang/8.0.1/include/pconfigintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/pkuintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/pmmintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/popcntintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/prfchwintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/ptwriteintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/rdseedintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/rtmintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/s390intrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/sgxintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/shaintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/smmintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/tbmintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/tmmintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/vadefs.h +OLD_FILES+=usr/lib/clang/8.0.1/include/vaesintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/vecintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/vpclmulqdqintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/waitpkgintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/wbnoinvdintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/wmmintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/x86intrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/xmmintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/xopintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/xsavecintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/xsaveintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/xsaveoptintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/xsavesintrin.h +OLD_FILES+=usr/lib/clang/8.0.1/include/xtestintrin.h +OLD_DIRS+=usr/lib/clang/8.0.1/include +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.asan-i386.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.asan-i386.so +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.asan-preinit-i386.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.asan-preinit-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.asan-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.asan-x86_64.so +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.asan_cxx-i386.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.asan_cxx-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.msan-i386.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.msan-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.msan_cxx-i386.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.msan_cxx-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.profile-arm.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.profile-armhf.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.profile-i386.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.profile-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.safestack-i386.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.safestack-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.stats-i386.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.stats-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.stats_client-i386.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.stats_client-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.tsan-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.tsan_cxx-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.ubsan_minimal-i386.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.ubsan_minimal-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.ubsan_standalone-i386.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.ubsan_standalone-x86_64.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.ubsan_standalone_cxx-i386.a +OLD_FILES+=usr/lib/clang/8.0.1/lib/freebsd/libclang_rt.ubsan_standalone_cxx-x86_64.a +OLD_DIRS+=usr/lib/clang/8.0.1/lib/freebsd +OLD_DIRS+=usr/lib/clang/8.0.1/lib +OLD_DIRS+=usr/lib/clang/8.0.1 OLD_DIRS+=usr/lib/clang OLD_FILES+=usr/share/doc/llvm/clang/LICENSE.TXT OLD_DIRS+=usr/share/doc/llvm/clang @@ -1563,7 +1564,6 @@ OLD_FILES+=usr/bin/llvm-mca OLD_FILES+=usr/bin/llvm-modextract OLD_FILES+=usr/bin/llvm-objcopy OLD_FILES+=usr/bin/llvm-pdbutil -OLD_FILES+=usr/bin/llvm-ranlib OLD_FILES+=usr/bin/llvm-rtdyld OLD_FILES+=usr/bin/llvm-xray OLD_FILES+=usr/bin/opt diff --git a/usr.bin/awk/Makefile b/usr.bin/awk/Makefile index 4ea401b99cd7..eb69a29fd862 100644 --- a/usr.bin/awk/Makefile +++ b/usr.bin/awk/Makefile @@ -27,6 +27,7 @@ ytab.h: awkgram.c awkgram.h .NOMETA proctab.c: maketab ${BTOOLSPATH:U.}/maketab awkgram.h > proctab.c +DEPENDOBJS+= maketab build-tools: maketab maketab: ytab.h maketab.c ${BUILD_TOOLS_META} diff --git a/usr.bin/bsdcat/Makefile b/usr.bin/bsdcat/Makefile index 097e9e471649..eb06b1f15b29 100644 --- a/usr.bin/bsdcat/Makefile +++ b/usr.bin/bsdcat/Makefile @@ -6,7 +6,7 @@ _LIBARCHIVEDIR= ${SRCTOP}/contrib/libarchive _LIBARCHIVECONFDIR= ${SRCTOP}/lib/libarchive PROG= bsdcat -BSDCAT_VERSION_STRING= 3.3.3 +BSDCAT_VERSION_STRING= 3.4.0 .PATH: ${_LIBARCHIVEDIR}/cat SRCS= bsdcat.c cmdline.c diff --git a/usr.bin/calendar/calendars/calendar.birthday b/usr.bin/calendar/calendars/calendar.birthday index 51745e36f3aa..60b505656ceb 100644 --- a/usr.bin/calendar/calendars/calendar.birthday +++ b/usr.bin/calendar/calendars/calendar.birthday @@ -161,7 +161,7 @@ 06/07 Alan Mathison Turing died, 1954 06/08 Frank Lloyd Wright born in Richland Center, Wisconsin, 1867 06/13 Alexander the Great dies (323BC) -06/15 Edward (Edvard Hagerup) Grieg born in Bergen, Norway, 1843 +06/15 Edvard Hagerup Grieg born in Bergen, Norway, 1843 06/16 Hammurabi the Great dies, Babylon, 1686 BC 06/18 M.C. Escher born, 1898 06/19 FreeBSD project born, 1993 diff --git a/usr.bin/cpio/Makefile b/usr.bin/cpio/Makefile index 43bde411265a..2be97475a074 100644 --- a/usr.bin/cpio/Makefile +++ b/usr.bin/cpio/Makefile @@ -6,7 +6,7 @@ _LIBARCHIVEDIR= ${SRCTOP}/contrib/libarchive _LIBARCHIVECONFDIR= ${SRCTOP}/lib/libarchive PROG= bsdcpio -BSDCPIO_VERSION_STRING= 3.3.3 +BSDCPIO_VERSION_STRING= 3.4.0 .PATH: ${_LIBARCHIVEDIR}/cpio SRCS= cpio.c cmdline.c diff --git a/usr.bin/procstat/procstat_auxv.c b/usr.bin/procstat/procstat_auxv.c index ceee8220760c..785896d0c6ad 100644 --- a/usr.bin/procstat/procstat_auxv.c +++ b/usr.bin/procstat/procstat_auxv.c @@ -184,6 +184,18 @@ procstat_auxv(struct procstat *procstat, struct kinfo_proc *kipp) xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EHDRFLAGS/%#lx}\n", prefix, "AT_EHDRFLAGS", (u_long)auxv[i].a_un.a_val); break; +#endif +#ifdef AT_HWCAP + case AT_HWCAP: + xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_HWCAP/%#lx}\n", + prefix, "AT_HWCAP", (u_long)auxv[i].a_un.a_val); + break; +#endif +#ifdef AT_HWCAP2 + case AT_HWCAP2: + xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_HWCAP2/%#lx}\n", + prefix, "AT_HWCAP2", (u_long)auxv[i].a_un.a_val); + break; #endif default: xo_emit("{dw:/%s}{Lw:/%16ld/%ld}{:UNKNOWN/%#lx}\n", diff --git a/usr.bin/tail/extern.h b/usr.bin/tail/extern.h index ef2c9ce0ee9a..65ddb519dc61 100644 --- a/usr.bin/tail/extern.h +++ b/usr.bin/tail/extern.h @@ -78,3 +78,4 @@ int maparound(struct mapinfo *, off_t); void printfn(const char *, int); extern int Fflag, fflag, qflag, rflag, rval, no_files; +extern fileargs_t *fa; diff --git a/usr.bin/tail/forward.c b/usr.bin/tail/forward.c index 3b697e0a5589..2888bd18816e 100644 --- a/usr.bin/tail/forward.c +++ b/usr.bin/tail/forward.c @@ -57,6 +57,9 @@ static const char sccsid[] = "@(#)forward.c 8.1 (Berkeley) 6/6/93"; #include #include +#include +#include + #include "extern.h" static void rlines(FILE *, const char *fn, off_t, struct stat *); @@ -310,6 +313,7 @@ follow(file_info_t *files, enum STYLE style, off_t off) int active, ev_change, i, n = -1; struct stat sb2; file_info_t *file; + FILE *ftmp; struct timespec ts; /* Position each of the files */ @@ -346,7 +350,9 @@ follow(file_info_t *files, enum STYLE style, off_t off) if (Fflag) { for (i = 0, file = files; i < no_files; i++, file++) { if (!file->fp) { - file->fp = fopen(file->file_name, "r"); + file->fp = + fileargs_fopen(fa, file->file_name, + "r"); if (file->fp != NULL && fstat(fileno(file->fp), &file->st) == -1) { @@ -359,7 +365,9 @@ follow(file_info_t *files, enum STYLE style, off_t off) } if (fileno(file->fp) == STDIN_FILENO) continue; - if (stat(file->file_name, &sb2) == -1) { + ftmp = fileargs_fopen(fa, file->file_name, "r"); + if (ftmp == NULL || + fstat(fileno(file->fp), &sb2) == -1) { if (errno != ENOENT) ierr(file->file_name); show(file); @@ -367,6 +375,9 @@ follow(file_info_t *files, enum STYLE style, off_t off) fclose(file->fp); file->fp = NULL; } + if (ftmp != NULL) { + fclose(ftmp); + } ev_change++; continue; } @@ -375,14 +386,13 @@ follow(file_info_t *files, enum STYLE style, off_t off) sb2.st_dev != file->st.st_dev || sb2.st_nlink == 0) { show(file); - file->fp = freopen(file->file_name, "r", - file->fp); - if (file->fp != NULL) - memcpy(&file->st, &sb2, - sizeof(struct stat)); - else if (errno != ENOENT) - ierr(file->file_name); + fclose(file->fp); + file->fp = ftmp; + memcpy(&file->st, &sb2, + sizeof(struct stat)); ev_change++; + } else { + fclose(ftmp); } } } diff --git a/usr.bin/tail/misc.c b/usr.bin/tail/misc.c index 137a38829b47..537cf00ccfe3 100644 --- a/usr.bin/tail/misc.c +++ b/usr.bin/tail/misc.c @@ -51,6 +51,9 @@ static const char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/6/93"; #include #include +#include +#include + #include "extern.h" void diff --git a/usr.bin/tail/read.c b/usr.bin/tail/read.c index c5638d961399..1e757c86195c 100644 --- a/usr.bin/tail/read.c +++ b/usr.bin/tail/read.c @@ -51,6 +51,9 @@ static const char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/6/93"; #include #include +#include +#include + #include "extern.h" /* diff --git a/usr.bin/tail/reverse.c b/usr.bin/tail/reverse.c index 422724c0ebab..3373f072c228 100644 --- a/usr.bin/tail/reverse.c +++ b/usr.bin/tail/reverse.c @@ -55,6 +55,9 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include + #include "extern.h" static void r_buf(FILE *, const char *); diff --git a/usr.bin/tail/tail.c b/usr.bin/tail/tail.c index 9cab33cef76f..abbe715e0496 100644 --- a/usr.bin/tail/tail.c +++ b/usr.bin/tail/tail.c @@ -65,6 +65,7 @@ static const char sccsid[] = "@(#)tail.c 8.1 (Berkeley) 6/6/93"; #include "extern.h" int Fflag, fflag, qflag, rflag, rval, no_files; +fileargs_t *fa; static file_info_t *files; @@ -90,10 +91,9 @@ main(int argc, char *argv[]) int i, ch, first; file_info_t *file; char *p; - fileargs_t *fa; cap_rights_t rights; - cap_rights_init(&rights, CAP_FSTAT, CAP_FCNTL, CAP_MMAP_RW); + cap_rights_init(&rights, CAP_FSTAT, CAP_FSTATFS, CAP_FCNTL, CAP_MMAP_RW); if (caph_rights_limit(STDIN_FILENO, &rights) < 0 || caph_limit_stderr() < 0 || caph_limit_stdout() < 0) err(1, "can't limit stdio rights"); @@ -212,7 +212,8 @@ main(int argc, char *argv[]) file->file_name = strdup(fn); if (! file->file_name) errx(1, "Couldn't malloc space for file name."); - if ((file->fp = fileargs_fopen(fa, file->file_name, "r")) == NULL || + file->fp = fileargs_fopen(fa, file->file_name, "r"); + if (file->fp == NULL || fstat(fileno(file->fp), &file->st)) { if (file->fp != NULL) { fclose(file->fp); diff --git a/usr.bin/tar/Makefile b/usr.bin/tar/Makefile index 93786a054e44..bf34cffcdac5 100644 --- a/usr.bin/tar/Makefile +++ b/usr.bin/tar/Makefile @@ -4,7 +4,7 @@ _LIBARCHIVEDIR= ${SRCTOP}/contrib/libarchive PROG= bsdtar -BSDTAR_VERSION_STRING= 3.3.3 +BSDTAR_VERSION_STRING= 3.4.0 .PATH: ${_LIBARCHIVEDIR}/tar SRCS= bsdtar.c \ diff --git a/usr.bin/vi/catalog/Makefile b/usr.bin/vi/catalog/Makefile index a8977dd809f6..6e2ed340f31e 100644 --- a/usr.bin/vi/catalog/Makefile +++ b/usr.bin/vi/catalog/Makefile @@ -105,8 +105,8 @@ english.base: dump ${SCAN} #Makefile sort -nu > $@ -dump: dump.c ${BUILD_TOOLS_META} - ${CC:N${CCACHE_BIN}} -o ${.TARGET} ${.ALLSRC} +DEPENDOBJS+= dump +dump: ${BUILD_TOOLS_META} CLEANFILES+= dump ${CAT} english.base *.check __ck1 __ck2 diff --git a/usr.bin/vtfontcvt/vtfontcvt.c b/usr.bin/vtfontcvt/vtfontcvt.c index 58bc26938f44..70ec7cf31812 100644 --- a/usr.bin/vtfontcvt/vtfontcvt.c +++ b/usr.bin/vtfontcvt/vtfontcvt.c @@ -111,7 +111,7 @@ xmalloc(size_t size) static int add_mapping(struct glyph *gl, unsigned int c, unsigned int map_idx) { - struct mapping *mp; + struct mapping *mp, *mp_temp; struct mapping_list *ml; mapping_total++; @@ -122,10 +122,19 @@ add_mapping(struct glyph *gl, unsigned int c, unsigned int map_idx) mp->m_length = 0; ml = &maps[map_idx]; - if (TAILQ_LAST(ml, mapping_list) != NULL && - TAILQ_LAST(ml, mapping_list)->m_char >= c) - errx(1, "Bad ordering at character %u", c); - TAILQ_INSERT_TAIL(ml, mp, m_list); + if (TAILQ_LAST(ml, mapping_list) == NULL || + TAILQ_LAST(ml, mapping_list)->m_char < c) { + /* Common case: empty list or new char at end of list. */ + TAILQ_INSERT_TAIL(ml, mp, m_list); + } else { + /* Find insertion point for char; cannot be at end. */ + TAILQ_FOREACH(mp_temp, ml, m_list) { + if (mp_temp->m_char >= c) { + TAILQ_INSERT_BEFORE(mp_temp, mp, m_list); + break; + } + } + } map_count[map_idx]++; mapping_unique++; @@ -167,6 +176,7 @@ add_glyph(const uint8_t *bytes, unsigned int map_idx, int fallback) glyph_total++; glyph_count[map_idx]++; + /* Return existing glyph if we have an identical one. */ hash = fnv_32_buf(bytes, wbytes * height, FNV1_32_INIT) % FONTCVT_NHASH; SLIST_FOREACH(gl, &glyph_hash[hash], g_hash) { if (memcmp(gl->g_data, bytes, wbytes * height) == 0) { @@ -175,6 +185,7 @@ add_glyph(const uint8_t *bytes, unsigned int map_idx, int fallback) } } + /* Allocate new glyph. */ gl = xmalloc(sizeof *gl); gl->g_data = xmalloc(wbytes * height); memcpy(gl->g_data, bytes, wbytes * height); @@ -212,91 +223,66 @@ add_char(unsigned curchar, unsigned map_idx, uint8_t *bytes, uint8_t *bytes_r) return (0); } - +/* + * Right-shift glyph row by _shift_ bits. Row _len_ bits wide, _size_ bytes. + */ static int -parse_bitmap_line(uint8_t *left, uint8_t *right, unsigned int line, - unsigned int dwidth) +rshift_row(uint8_t *line, size_t size, size_t len, size_t shift) { - uint8_t *p; - unsigned int i, subline; + size_t d, s, i; + uint16_t t; - if (dwidth != width && dwidth != width * 2) - errx(1, "Bitmap with unsupported width %u!", dwidth); + assert(size > 0 && len > 0); + assert(size * 8 >= len); - /* Move pixel data right to simplify splitting double characters. */ - line >>= (howmany(dwidth, 8) * 8) - dwidth; + if (shift == 0) + return (0); - for (i = dwidth / width; i > 0; i--) { - p = (i == 2) ? right : left; + d = shift / 8; + s = 8 - shift % 8; + i = howmany(len, 8); - subline = line & ((1 << width) - 1); - subline <<= (howmany(width, 8) * 8) - width; + while (i > 0) { + i--; - if (wbytes == 1) { - *p = subline; - } else if (wbytes == 2) { - *p++ = subline >> 8; - *p = subline; - } else { - errx(1, "Unsupported wbytes %u!", wbytes); - } + t = *(line + i); + *(line + i) = 0; - line >>= width; + t <<= s; + + if (i + d + 1 < size) + *(line + i + d + 1) |= (uint8_t)t; + if (i + d < size) + *(line + i + d) = t >> 8; } - return (0); } +/* + * Split double-width characters into left and right half. Single-width + * characters in _left_ only. + */ static int -parse_bdf(FILE *fp, unsigned int map_idx) +split_row(uint8_t *left, uint8_t *right, uint8_t *line, size_t w) { - char *ln; - size_t length; - uint8_t bytes[wbytes * height], bytes_r[wbytes * height]; - unsigned int curchar = 0, dwidth = 0, i, line; + size_t s, i; - while ((ln = fgetln(fp, &length)) != NULL) { - ln[length - 1] = '\0'; + s = wbytes * 8 - width; - if (strncmp(ln, "ENCODING ", 9) == 0) { - curchar = atoi(ln + 9); - } - - if (strncmp(ln, "DWIDTH ", 7) == 0) { - dwidth = atoi(ln + 7); - } - - if (strncmp(ln, "BITMAP", 6) == 0 && - (ln[6] == ' ' || ln[6] == '\0')) { - /* - * Assume that the next _height_ lines are bitmap - * data. ENDCHAR is allowed to terminate the bitmap - * early but is not otherwise checked; any extra data - * is ignored. - */ - for (i = 0; i < height; i++) { - if ((ln = fgetln(fp, &length)) == NULL) - errx(1, "Unexpected EOF!"); - ln[length - 1] = '\0'; - if (strcmp(ln, "ENDCHAR") == 0) { - memset(bytes + i * wbytes, 0, - (height - i) * wbytes); - memset(bytes_r + i * wbytes, 0, - (height - i) * wbytes); - break; - } - sscanf(ln, "%x", &line); - if (parse_bitmap_line(bytes + i * wbytes, - bytes_r + i * wbytes, line, dwidth) != 0) - return (1); - } - - if (add_char(curchar, map_idx, bytes, - dwidth == width * 2 ? bytes_r : NULL) != 0) - return (1); + memcpy(left, line, wbytes); + *(left + wbytes - 1) &= 0xFF << s; + + if (w > width) { /* Double-width character. */ + uint8_t t; + + for (i = 0; i < wbytes; i++) { + t = *(line + wbytes + i - 1); + t <<= 8 - s; + t |= *(line + wbytes + i) >> s; + *(right + i) = t; } + *(right + wbytes - 1) &= 0xFF << s; } - return (0); } @@ -317,14 +303,160 @@ set_width(int w) wbytes = howmany(width, 8); } +static int +parse_bdf(FILE *fp, unsigned int map_idx) +{ + char *line, *ln, *p; + size_t length; + uint8_t *bytes, *bytes_r; + unsigned int curchar = 0, i, j, linenum = 0, bbwbytes; + int bbw, bbh, bbox, bboy; /* Glyph bounding box. */ + int fbbw = 0, fbbh, fbbox, fbboy; /* Font bounding box. */ + int dwidth = 0, dwy = 0; + int rv = -1; + char spc = '\0'; + + /* + * Step 1: Parse FONT logical font descriptor and FONTBOUNDINGBOX + * bounding box. + */ + while ((ln = fgetln(fp, &length)) != NULL) { + linenum++; + ln[length - 1] = '\0'; + + if (strncmp(ln, "FONT ", 5) == 0) { + p = ln + 5; + i = 0; + while ((p = strchr(p, '-')) != NULL) { + p++; + i++; + if (i == 11) { + spc = *p; + break; + } + } + } else if (strncmp(ln, "FONTBOUNDINGBOX ", 16) == 0 && + sscanf(ln + 16, "%d %d %d %d", &fbbw, &fbbh, &fbbox, + &fbboy) == 4) { + set_width(fbbw); + set_height(fbbh); + break; + } + } + if (fbbw == 0) + errx(1, "broken font header"); + if (spc != 'c' && spc != 'C') + errx(1, "font spacing \"C\" (character cell) required"); + + /* Step 2: Validate DWIDTH (Device Width) of all glyphs. */ + while ((ln = fgetln(fp, &length)) != NULL) { + linenum++; + ln[length - 1] = '\0'; + + if (strncmp(ln, "DWIDTH ", 7) == 0 && + sscanf(ln + 7, "%d %d", &dwidth, &dwy) == 2) { + if (dwy != 0 || (dwidth != fbbw && dwidth * 2 != fbbw)) + errx(1, "bitmap with unsupported DWIDTH %d %d at line %u", + dwidth, dwy, linenum); + if (dwidth < fbbw) + set_width(dwidth); + } + } + + /* Step 3: Restart at the beginning of the file and read glyph data. */ + dwidth = bbw = bbh = 0; + rewind(fp); + linenum = 0; + bbwbytes = 0; /* GCC 4.2.1 "may be used uninitialized" workaround. */ + bytes = xmalloc(wbytes * height); + bytes_r = xmalloc(wbytes * height); + line = xmalloc(wbytes * 2); + while ((ln = fgetln(fp, &length)) != NULL) { + linenum++; + ln[length - 1] = '\0'; + + if (strncmp(ln, "ENCODING ", 9) == 0) { + curchar = atoi(ln + 9); + } else if (strncmp(ln, "DWIDTH ", 7) == 0) { + dwidth = atoi(ln + 7); + } else if (strncmp(ln, "BBX ", 4) == 0) { + if (sscanf(ln + 4, "%d %d %d %d", &bbw, &bbh, &bbox, + &bboy) != 4) + errx(1, "invalid BBX at line %u", linenum); + if (bbw < 1 || bbh < 1 || bbw > fbbw || bbh > fbbh || + bbox < fbbox || bboy < fbboy || + bbh + bboy > fbbh + fbboy) + errx(1, "broken bitmap with BBX %d %d %d %d at line %u", + bbw, bbh, bbox, bboy, linenum); + bbwbytes = howmany(bbw, 8); + } else if (strncmp(ln, "BITMAP", 6) == 0 && + (ln[6] == ' ' || ln[6] == '\0')) { + if (dwidth == 0 || bbw == 0 || bbh == 0) + errx(1, "broken char header at line %u!", + linenum); + memset(bytes, 0, wbytes * height); + memset(bytes_r, 0, wbytes * height); + + /* + * Assume that the next _bbh_ lines are bitmap data. + * ENDCHAR is allowed to terminate the bitmap + * early but is not otherwise checked; any extra data + * is ignored. + */ + for (i = (fbbh + fbboy) - (bbh + bboy); + i < (unsigned int)((fbbh + fbboy) - bboy); i++) { + if ((ln = fgetln(fp, &length)) == NULL) + errx(1, "unexpected EOF"); + linenum++; + ln[length - 1] = '\0'; + if (strcmp(ln, "ENDCHAR") == 0) + break; + if (strlen(ln) < bbwbytes * 2) + errx(1, "broken bitmap at line %u", + linenum); + memset(line, 0, wbytes * 2); + for (j = 0; j < bbwbytes; j++) { + unsigned int val; + if (sscanf(ln + j * 2, "%2x", &val) == + 0) + break; + *(line + j) = (uint8_t)val; + } + + rv = rshift_row(line, wbytes * 2, bbw, + bbox - fbbox); + if (rv != 0) + goto out; + + rv = split_row(bytes + i * wbytes, + bytes_r + i * wbytes, line, dwidth); + if (rv != 0) + goto out; + } + + rv = add_char(curchar, map_idx, bytes, + dwidth > (int)width ? bytes_r : NULL); + if (rv != 0) + goto out; + + dwidth = bbw = bbh = 0; + } + } + +out: + free(bytes); + free(bytes_r); + free(line); + return (rv); +} + static int parse_hex(FILE *fp, unsigned int map_idx) { char *ln, *p; - char fmt_str[8]; size_t length; - uint8_t *bytes = NULL, *bytes_r = NULL; - unsigned curchar = 0, i, line, chars_per_row, dwidth; + uint8_t *bytes = NULL, *bytes_r = NULL, *line = NULL; + unsigned curchar = 0, gwidth, gwbytes, i, j, chars_per_row; int rv = 0; while ((ln = fgetln(fp, &length)) != NULL) { @@ -342,36 +474,46 @@ parse_hex(FILE *fp, unsigned int map_idx) if (bytes == NULL) { bytes = xmalloc(wbytes * height); bytes_r = xmalloc(wbytes * height); + line = xmalloc(wbytes * 2); } /* ln is guaranteed to have a colon here. */ p = strchr(ln, ':') + 1; chars_per_row = strlen(p) / height; - dwidth = width; - if (chars_per_row / 2 > (width + 7) / 8) - dwidth *= 2; /* Double-width character. */ - snprintf(fmt_str, sizeof(fmt_str), "%%%ux", - chars_per_row); + if (chars_per_row < wbytes * 2) + errx(1, + "malformed input: broken bitmap, character %06x", + curchar); + gwidth = width * 2; + gwbytes = howmany(gwidth, 8); + if (chars_per_row < gwbytes * 2 || gwidth <= 8) { + gwidth = width; /* Single-width character. */ + gwbytes = wbytes; + } for (i = 0; i < height; i++) { - sscanf(p, fmt_str, &line); - p += chars_per_row; - if (parse_bitmap_line(bytes + i * wbytes, - bytes_r + i * wbytes, line, dwidth) != 0) { - rv = 1; - goto out; + for (j = 0; j < gwbytes; j++) { + unsigned int val; + if (sscanf(p + j * 2, "%2x", &val) == 0) + break; + *(line + j) = (uint8_t)val; } + rv = split_row(bytes + i * wbytes, + bytes_r + i * wbytes, line, gwidth); + if (rv != 0) + goto out; + p += gwbytes * 2; } - if (add_char(curchar, map_idx, bytes, - dwidth == width * 2 ? bytes_r : NULL) != 0) { - rv = 1; + rv = add_char(curchar, map_idx, bytes, + gwidth != width ? bytes_r : NULL); + if (rv != 0) goto out; - } } } out: free(bytes); free(bytes_r); + free(line); return (rv); } diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile index c835b9395c4c..85fdf11928b1 100644 --- a/usr.sbin/bhyve/Makefile +++ b/usr.sbin/bhyve/Makefile @@ -32,6 +32,7 @@ SRCS= \ mem.c \ mevent.c \ mptbl.c \ + net_utils.c \ pci_ahci.c \ pci_e82545.c \ pci_emul.c \ diff --git a/usr.sbin/bhyve/net_utils.c b/usr.sbin/bhyve/net_utils.c new file mode 100644 index 000000000000..dc29124e84bd --- /dev/null +++ b/usr.sbin/bhyve/net_utils.c @@ -0,0 +1,83 @@ +/*- + * Copyright (c) 2011 NetApp, 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 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$ + */ + +#include "net_utils.h" +#include "bhyverun.h" +#include +#include +#include +#include +#include + +int +net_parsemac(char *mac_str, uint8_t *mac_addr) +{ + struct ether_addr *ea; + char *tmpstr; + char zero_addr[ETHER_ADDR_LEN] = { 0, 0, 0, 0, 0, 0 }; + + tmpstr = strsep(&mac_str,"="); + + if ((mac_str != NULL) && (!strcmp(tmpstr,"mac"))) { + ea = ether_aton(mac_str); + + if (ea == NULL || ETHER_IS_MULTICAST(ea->octet) || + memcmp(ea->octet, zero_addr, ETHER_ADDR_LEN) == 0) { + fprintf(stderr, "Invalid MAC %s\n", mac_str); + return (EINVAL); + } else + memcpy(mac_addr, ea->octet, ETHER_ADDR_LEN); + } + + return (0); +} + +void +net_genmac(struct pci_devinst *pi, uint8_t *macaddr) +{ + /* + * The default MAC address is the standard NetApp OUI of 00-a0-98, + * followed by an MD5 of the PCI slot/func number and dev name + */ + MD5_CTX mdctx; + unsigned char digest[16]; + char nstr[80]; + + snprintf(nstr, sizeof(nstr), "%d-%d-%s", pi->pi_slot, + pi->pi_func, vmname); + + MD5Init(&mdctx); + MD5Update(&mdctx, nstr, (unsigned int)strlen(nstr)); + MD5Final(digest, &mdctx); + + macaddr[0] = 0x00; + macaddr[1] = 0xa0; + macaddr[2] = 0x98; + macaddr[3] = digest[0]; + macaddr[4] = digest[1]; + macaddr[5] = digest[2]; +} diff --git a/usr.sbin/bhyve/net_utils.h b/usr.sbin/bhyve/net_utils.h new file mode 100644 index 000000000000..28b59d11a803 --- /dev/null +++ b/usr.sbin/bhyve/net_utils.h @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2019 Vincenzo Maffione + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _NET_UTILS_H_ +#define _NET_UTILS_H_ + +#include +#include "pci_emul.h" + +void net_genmac(struct pci_devinst *pi, uint8_t *macaddr); +int net_parsemac(char *mac_str, uint8_t *mac_addr); + +#endif /* _NET_UTILS_H_ */ diff --git a/usr.sbin/bhyve/pci_e82545.c b/usr.sbin/bhyve/pci_e82545.c index c2e6ceca7bae..180590c52825 100644 --- a/usr.sbin/bhyve/pci_e82545.c +++ b/usr.sbin/bhyve/pci_e82545.c @@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$"); #include "bhyverun.h" #include "pci_emul.h" #include "mevent.h" +#include "net_utils.h" /* Hardware/register definitions XXX: move some to common code. */ #define E82545_VENDOR_ID_INTEL 0x8086 @@ -2258,39 +2259,17 @@ e82545_open_tap(struct e82545_softc *sc, char *opts) } } -static int -e82545_parsemac(char *mac_str, uint8_t *mac_addr) -{ - struct ether_addr *ea; - char *tmpstr; - char zero_addr[ETHER_ADDR_LEN] = { 0, 0, 0, 0, 0, 0 }; - - tmpstr = strsep(&mac_str,"="); - if ((mac_str != NULL) && (!strcmp(tmpstr,"mac"))) { - ea = ether_aton(mac_str); - if (ea == NULL || ETHER_IS_MULTICAST(ea->octet) || - memcmp(ea->octet, zero_addr, ETHER_ADDR_LEN) == 0) { - fprintf(stderr, "Invalid MAC %s\n", mac_str); - return (1); - } else - memcpy(mac_addr, ea->octet, ETHER_ADDR_LEN); - } - return (0); -} - static int e82545_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) { - DPRINTF("Loading with options: %s\r\n", opts); - - MD5_CTX mdctx; - unsigned char digest[16]; char nstr[80]; struct e82545_softc *sc; char *devname; char *vtopts; int mac_provided; + DPRINTF("Loading with options: %s\r\n", opts); + /* Setup our softc */ sc = calloc(1, sizeof(*sc)); @@ -2340,7 +2319,7 @@ e82545_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) (void) strsep(&vtopts, ","); if (vtopts != NULL) { - err = e82545_parsemac(vtopts, sc->esc_mac.octet); + err = net_parsemac(vtopts, sc->esc_mac.octet); if (err != 0) { free(devname); return (err); @@ -2355,24 +2334,8 @@ e82545_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) free(devname); } - /* - * The default MAC address is the standard NetApp OUI of 00-a0-98, - * followed by an MD5 of the PCI slot/func number and dev name - */ if (!mac_provided) { - snprintf(nstr, sizeof(nstr), "%d-%d-%s", pi->pi_slot, - pi->pi_func, vmname); - - MD5Init(&mdctx); - MD5Update(&mdctx, nstr, strlen(nstr)); - MD5Final(digest, &mdctx); - - sc->esc_mac.octet[0] = 0x00; - sc->esc_mac.octet[1] = 0xa0; - sc->esc_mac.octet[2] = 0x98; - sc->esc_mac.octet[3] = digest[0]; - sc->esc_mac.octet[4] = digest[1]; - sc->esc_mac.octet[5] = digest[2]; + net_genmac(pi, sc->esc_mac.octet); } /* H/w initiated reset */ diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c index aaeac3213603..6e9c68cb66a9 100644 --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -586,6 +586,7 @@ pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase, { int error; uint64_t *baseptr, limit, addr, mask, lobits, bar; + uint16_t cmd, enbit; assert(idx >= 0 && idx <= PCI_BARMAX); @@ -604,13 +605,14 @@ pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase, switch (type) { case PCIBAR_NONE: baseptr = NULL; - addr = mask = lobits = 0; + addr = mask = lobits = enbit = 0; break; case PCIBAR_IO: baseptr = &pci_emul_iobase; limit = PCI_EMUL_IOLIMIT; mask = PCIM_BAR_IO_BASE; lobits = PCIM_BAR_IO_SPACE; + enbit = PCIM_CMD_PORTEN; break; case PCIBAR_MEM64: /* @@ -632,19 +634,20 @@ pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase, mask = PCIM_BAR_MEM_BASE; lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64 | PCIM_BAR_MEM_PREFETCH; - break; } else { baseptr = &pci_emul_membase32; limit = PCI_EMUL_MEMLIMIT32; mask = PCIM_BAR_MEM_BASE; lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64; } + enbit = PCIM_CMD_MEMEN; break; case PCIBAR_MEM32: baseptr = &pci_emul_membase32; limit = PCI_EMUL_MEMLIMIT32; mask = PCIM_BAR_MEM_BASE; lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32; + enbit = PCIM_CMD_MEMEN; break; default: printf("pci_emul_alloc_base: invalid bar type %d\n", type); @@ -671,6 +674,9 @@ pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase, pci_set_cfgdata32(pdi, PCIR_BAR(idx + 1), bar >> 32); } + cmd = pci_get_cfgdata16(pdi, PCIR_COMMAND); + if ((cmd & enbit) != enbit) + pci_set_cfgdata16(pdi, PCIR_COMMAND, cmd | enbit); register_bar(pdi, idx); return (0); @@ -756,8 +762,7 @@ pci_emul_init(struct vmctx *ctx, struct pci_devemu *pde, int bus, int slot, pci_set_cfgdata8(pdi, PCIR_INTLINE, 255); pci_set_cfgdata8(pdi, PCIR_INTPIN, 0); - pci_set_cfgdata8(pdi, PCIR_COMMAND, - PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); + pci_set_cfgdata8(pdi, PCIR_COMMAND, PCIM_CMD_BUSMASTEREN); err = (*pde->pe_init)(ctx, pdi, fi->fi_param); if (err == 0) @@ -947,15 +952,23 @@ pci_emul_add_pciecap(struct pci_devinst *pi, int type) int err; struct pciecap pciecap; - if (type != PCIEM_TYPE_ROOT_PORT) - return (-1); - bzero(&pciecap, sizeof(pciecap)); + /* + * Use the integrated endpoint type for endpoints on a root complex bus. + * + * NB: bhyve currently only supports a single PCI bus that is the root + * complex bus, so all endpoints are integrated. + */ + if ((type == PCIEM_TYPE_ENDPOINT) && (pi->pi_bus == 0)) + type = PCIEM_TYPE_ROOT_INT_EP; + pciecap.capid = PCIY_EXPRESS; - pciecap.pcie_capabilities = PCIECAP_VERSION | PCIEM_TYPE_ROOT_PORT; - pciecap.link_capabilities = 0x411; /* gen1, x1 */ - pciecap.link_status = 0x11; /* gen1, x1 */ + pciecap.pcie_capabilities = PCIECAP_VERSION | type; + if (type != PCIEM_TYPE_ROOT_INT_EP) { + pciecap.link_capabilities = 0x411; /* gen1, x1 */ + pciecap.link_status = 0x11; /* gen1, x1 */ + } err = pci_emul_add_capability(pi, (u_char *)&pciecap, sizeof(pciecap)); return (err); @@ -1673,11 +1686,64 @@ pci_emul_hdrtype_fixup(int bus, int slot, int off, int bytes, uint32_t *rv) } } +/* + * Update device state in response to changes to the PCI command + * register. + */ +void +pci_emul_cmd_changed(struct pci_devinst *pi, uint16_t old) +{ + int i; + uint16_t changed, new; + + new = pci_get_cfgdata16(pi, PCIR_COMMAND); + changed = old ^ new; + + /* + * If the MMIO or I/O address space decoding has changed then + * register/unregister all BARs that decode that address space. + */ + for (i = 0; i <= PCI_BARMAX; i++) { + switch (pi->pi_bar[i].type) { + case PCIBAR_NONE: + case PCIBAR_MEMHI64: + break; + case PCIBAR_IO: + /* I/O address space decoding changed? */ + if (changed & PCIM_CMD_PORTEN) { + if (new & PCIM_CMD_PORTEN) + register_bar(pi, i); + else + unregister_bar(pi, i); + } + break; + case PCIBAR_MEM32: + case PCIBAR_MEM64: + /* MMIO address space decoding changed? */ + if (changed & PCIM_CMD_MEMEN) { + if (new & PCIM_CMD_MEMEN) + register_bar(pi, i); + else + unregister_bar(pi, i); + } + break; + default: + assert(0); + } + } + + /* + * If INTx has been unmasked and is pending, assert the + * interrupt. + */ + pci_lintr_update(pi); +} + static void pci_emul_cmdsts_write(struct pci_devinst *pi, int coff, uint32_t new, int bytes) { - int i, rshift; - uint32_t cmd, cmd2, changed, old, readonly; + int rshift; + uint32_t cmd, old, readonly; cmd = pci_get_cfgdata16(pi, PCIR_COMMAND); /* stash old value */ @@ -1696,47 +1762,7 @@ pci_emul_cmdsts_write(struct pci_devinst *pi, int coff, uint32_t new, int bytes) new |= (old & readonly); CFGWRITE(pi, coff, new, bytes); /* update config */ - cmd2 = pci_get_cfgdata16(pi, PCIR_COMMAND); /* get updated value */ - changed = cmd ^ cmd2; - - /* - * If the MMIO or I/O address space decoding has changed then - * register/unregister all BARs that decode that address space. - */ - for (i = 0; i <= PCI_BARMAX; i++) { - switch (pi->pi_bar[i].type) { - case PCIBAR_NONE: - case PCIBAR_MEMHI64: - break; - case PCIBAR_IO: - /* I/O address space decoding changed? */ - if (changed & PCIM_CMD_PORTEN) { - if (porten(pi)) - register_bar(pi, i); - else - unregister_bar(pi, i); - } - break; - case PCIBAR_MEM32: - case PCIBAR_MEM64: - /* MMIO address space decoding changed? */ - if (changed & PCIM_CMD_MEMEN) { - if (memen(pi)) - register_bar(pi, i); - else - unregister_bar(pi, i); - } - break; - default: - assert(0); - } - } - - /* - * If INTx has been unmasked and is pending, assert the - * interrupt. - */ - pci_lintr_update(pi); + pci_emul_cmd_changed(pi, cmd); } static void diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h index 853badaadbe6..fba2e8845af8 100644 --- a/usr.sbin/bhyve/pci_emul.h +++ b/usr.sbin/bhyve/pci_emul.h @@ -223,6 +223,7 @@ int pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase, enum pcibar_type type, uint64_t size); int pci_emul_add_msicap(struct pci_devinst *pi, int msgnum); int pci_emul_add_pciecap(struct pci_devinst *pi, int pcie_device_type); +void pci_emul_cmd_changed(struct pci_devinst *pi, uint16_t old); void pci_generate_msi(struct pci_devinst *pi, int msgnum); void pci_generate_msix(struct pci_devinst *pi, int msgnum); void pci_lintr_assert(struct pci_devinst *pi); diff --git a/usr.sbin/bhyve/pci_nvme.c b/usr.sbin/bhyve/pci_nvme.c index dbd9298f5a5d..814577f4141f 100644 --- a/usr.sbin/bhyve/pci_nvme.c +++ b/usr.sbin/bhyve/pci_nvme.c @@ -1925,6 +1925,12 @@ pci_nvme_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) goto done; } + error = pci_emul_add_pciecap(pi, PCIEM_TYPE_ROOT_INT_EP); + if (error) { + WPRINTF(("%s pci add Express capability failed\r\n", __func__)); + goto done; + } + pthread_mutex_init(&sc->mtx, NULL); sem_init(&sc->iosemlock, 0, sc->ioslots); diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c index 785da84244df..852643e9d779 100644 --- a/usr.sbin/bhyve/pci_passthru.c +++ b/usr.sbin/bhyve/pci_passthru.c @@ -639,6 +639,9 @@ cfginit(struct vmctx *ctx, struct pci_devinst *pi, int bus, int slot, int func) goto done; } + pci_set_cfgdata16(pi, PCIR_COMMAND, read_config(&sc->psc_sel, + PCIR_COMMAND, 2)); + error = 0; /* success */ done: return (error); @@ -815,6 +818,7 @@ passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, { int error, msix_table_entries, i; struct passthru_softc *sc; + uint16_t cmd_old; sc = pi->pi_arg; @@ -871,6 +875,14 @@ passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, #endif write_config(&sc->psc_sel, coff, bytes, val); + if (coff == PCIR_COMMAND) { + cmd_old = pci_get_cfgdata16(pi, PCIR_COMMAND); + if (bytes == 1) + pci_set_cfgdata8(pi, PCIR_COMMAND, val); + else if (bytes == 2) + pci_set_cfgdata16(pi, PCIR_COMMAND, val); + pci_emul_cmd_changed(pi, cmd_old); + } return (0); } diff --git a/usr.sbin/bhyve/pci_virtio_console.c b/usr.sbin/bhyve/pci_virtio_console.c index ba509e054e64..556f08b6c331 100644 --- a/usr.sbin/bhyve/pci_virtio_console.c +++ b/usr.sbin/bhyve/pci_virtio_console.c @@ -607,7 +607,7 @@ pci_vtcon_notify_rx(void *vsc, struct vqueue_info *vq) if (!port->vsp_rx_ready) { port->vsp_rx_ready = 1; - vq->vq_used->vu_flags |= VRING_USED_F_NO_NOTIFY; + vq_kick_disable(vq); } } diff --git a/usr.sbin/bhyve/pci_virtio_net.c b/usr.sbin/bhyve/pci_virtio_net.c index 2990cdd8910d..af57a70d025c 100644 --- a/usr.sbin/bhyve/pci_virtio_net.c +++ b/usr.sbin/bhyve/pci_virtio_net.c @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #ifndef NETMAP_WITH_LIBS #define NETMAP_WITH_LIBS @@ -68,6 +67,7 @@ __FBSDID("$FreeBSD$"); #include "pci_emul.h" #include "mevent.h" #include "virtio.h" +#include "net_utils.h" #define VTNET_RINGSZ 1024 @@ -150,14 +150,13 @@ struct pci_vtnet_softc { struct nm_desc *vsc_nmd; int vsc_rx_ready; - volatile int resetting; /* set and checked outside lock */ + int resetting; /* protected by tx_mtx */ uint64_t vsc_features; /* negotiated features */ struct virtio_net_config vsc_config; pthread_mutex_t rx_mtx; - int rx_in_progress; int rx_vhdrlen; int rx_merge; /* merged rx bufs in use */ @@ -189,38 +188,6 @@ static struct virtio_consts vtnet_vi_consts = { VTNET_S_HOSTCAPS, /* our capabilities */ }; -/* - * If the transmit thread is active then stall until it is done. - */ -static void -pci_vtnet_txwait(struct pci_vtnet_softc *sc) -{ - - pthread_mutex_lock(&sc->tx_mtx); - while (sc->tx_in_progress) { - pthread_mutex_unlock(&sc->tx_mtx); - usleep(10000); - pthread_mutex_lock(&sc->tx_mtx); - } - pthread_mutex_unlock(&sc->tx_mtx); -} - -/* - * If the receive thread is active then stall until it is done. - */ -static void -pci_vtnet_rxwait(struct pci_vtnet_softc *sc) -{ - - pthread_mutex_lock(&sc->rx_mtx); - while (sc->rx_in_progress) { - pthread_mutex_unlock(&sc->rx_mtx); - usleep(10000); - pthread_mutex_lock(&sc->rx_mtx); - } - pthread_mutex_unlock(&sc->rx_mtx); -} - static void pci_vtnet_reset(void *vsc) { @@ -228,23 +195,32 @@ pci_vtnet_reset(void *vsc) DPRINTF(("vtnet: device reset requested !\n")); - sc->resetting = 1; + /* Acquire the RX lock to block RX processing. */ + pthread_mutex_lock(&sc->rx_mtx); - /* - * Wait for the transmit and receive threads to finish their - * processing. - */ - pci_vtnet_txwait(sc); - pci_vtnet_rxwait(sc); + /* Set sc->resetting and give a chance to the TX thread to stop. */ + pthread_mutex_lock(&sc->tx_mtx); + sc->resetting = 1; + while (sc->tx_in_progress) { + pthread_mutex_unlock(&sc->tx_mtx); + usleep(10000); + pthread_mutex_lock(&sc->tx_mtx); + } sc->vsc_rx_ready = 0; sc->rx_merge = 1; sc->rx_vhdrlen = sizeof(struct virtio_net_rxhdr); - /* now reset rings, MSI-X vectors, and negotiated capabilities */ + /* + * Now reset rings, MSI-X vectors, and negotiated capabilities. + * Do that with the TX lock held, since we need to reset + * sc->resetting. + */ vi_reset_dev(&sc->vsc_vs); sc->resetting = 0; + pthread_mutex_unlock(&sc->tx_mtx); + pthread_mutex_unlock(&sc->rx_mtx); } /* @@ -318,9 +294,9 @@ pci_vtnet_tap_rx(struct pci_vtnet_softc *sc) /* * But, will be called when the rx ring hasn't yet - * been set up or the guest is resetting the device. + * been set up. */ - if (!sc->vsc_rx_ready || sc->resetting) { + if (!sc->vsc_rx_ready) { /* * Drop the packet and try later. */ @@ -515,9 +491,9 @@ pci_vtnet_netmap_rx(struct pci_vtnet_softc *sc) /* * But, will be called when the rx ring hasn't yet - * been set up or the guest is resetting the device. + * been set up. */ - if (!sc->vsc_rx_ready || sc->resetting) { + if (!sc->vsc_rx_ready) { /* * Drop the packet and try later. */ @@ -594,9 +570,7 @@ pci_vtnet_rx_callback(int fd, enum ev_type type, void *param) struct pci_vtnet_softc *sc = param; pthread_mutex_lock(&sc->rx_mtx); - sc->rx_in_progress = 1; sc->pci_vtnet_rx(sc); - sc->rx_in_progress = 0; pthread_mutex_unlock(&sc->rx_mtx); } @@ -609,10 +583,12 @@ pci_vtnet_ping_rxq(void *vsc, struct vqueue_info *vq) /* * A qnotify means that the rx process can now begin */ + pthread_mutex_lock(&sc->rx_mtx); if (sc->vsc_rx_ready == 0) { sc->vsc_rx_ready = 1; - vq->vq_used->vu_flags |= VRING_USED_F_NO_NOTIFY; + vq_kick_disable(vq); } + pthread_mutex_unlock(&sc->rx_mtx); } static void @@ -657,7 +633,7 @@ pci_vtnet_ping_txq(void *vsc, struct vqueue_info *vq) /* Signal the tx thread for processing */ pthread_mutex_lock(&sc->tx_mtx); - vq->vq_used->vu_flags |= VRING_USED_F_NO_NOTIFY; + vq_kick_disable(vq); if (sc->tx_in_progress == 0) pthread_cond_signal(&sc->tx_cond); pthread_mutex_unlock(&sc->tx_mtx); @@ -686,8 +662,7 @@ pci_vtnet_tx_thread(void *param) for (;;) { /* note - tx mutex is locked here */ while (sc->resetting || !vq_has_descs(vq)) { - vq->vq_used->vu_flags &= ~VRING_USED_F_NO_NOTIFY; - mb(); + vq_kick_enable(vq); if (!sc->resetting && vq_has_descs(vq)) break; @@ -695,7 +670,7 @@ pci_vtnet_tx_thread(void *param) error = pthread_cond_wait(&sc->tx_cond, &sc->tx_mtx); assert(error == 0); } - vq->vq_used->vu_flags |= VRING_USED_F_NO_NOTIFY; + vq_kick_disable(vq); sc->tx_in_progress = 1; pthread_mutex_unlock(&sc->tx_mtx); @@ -726,29 +701,6 @@ pci_vtnet_ping_ctlq(void *vsc, struct vqueue_info *vq) } #endif -static int -pci_vtnet_parsemac(char *mac_str, uint8_t *mac_addr) -{ - struct ether_addr *ea; - char *tmpstr; - char zero_addr[ETHER_ADDR_LEN] = { 0, 0, 0, 0, 0, 0 }; - - tmpstr = strsep(&mac_str,"="); - - if ((mac_str != NULL) && (!strcmp(tmpstr,"mac"))) { - ea = ether_aton(mac_str); - - if (ea == NULL || ETHER_IS_MULTICAST(ea->octet) || - memcmp(ea->octet, zero_addr, ETHER_ADDR_LEN) == 0) { - fprintf(stderr, "Invalid MAC %s\n", mac_str); - return (EINVAL); - } else - memcpy(mac_addr, ea->octet, ETHER_ADDR_LEN); - } - - return (0); -} - static void pci_vtnet_tap_setup(struct pci_vtnet_softc *sc, char *devname) { @@ -823,9 +775,6 @@ pci_vtnet_netmap_setup(struct pci_vtnet_softc *sc, char *ifname) static int pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) { - MD5_CTX mdctx; - unsigned char digest[16]; - char nstr[80]; char tname[MAXCOMLEN + 1]; struct pci_vtnet_softc *sc; char *devname; @@ -862,7 +811,7 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) (void) strsep(&vtopts, ","); if (vtopts != NULL) { - err = pci_vtnet_parsemac(vtopts, sc->vsc_config.mac); + err = net_parsemac(vtopts, sc->vsc_config.mac); if (err != 0) { free(devname); return (err); @@ -879,24 +828,8 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) free(devname); } - /* - * The default MAC address is the standard NetApp OUI of 00-a0-98, - * followed by an MD5 of the PCI slot/func number and dev name - */ if (!mac_provided) { - snprintf(nstr, sizeof(nstr), "%d-%d-%s", pi->pi_slot, - pi->pi_func, vmname); - - MD5Init(&mdctx); - MD5Update(&mdctx, nstr, strlen(nstr)); - MD5Final(digest, &mdctx); - - sc->vsc_config.mac[0] = 0x00; - sc->vsc_config.mac[1] = 0xa0; - sc->vsc_config.mac[2] = 0x98; - sc->vsc_config.mac[3] = digest[0]; - sc->vsc_config.mac[4] = digest[1]; - sc->vsc_config.mac[5] = digest[2]; + net_genmac(pi, sc->vsc_config.mac); } /* initialize config space */ @@ -921,7 +854,6 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) sc->rx_merge = 1; sc->rx_vhdrlen = sizeof(struct virtio_net_rxhdr); - sc->rx_in_progress = 0; pthread_mutex_init(&sc->rx_mtx, NULL); /* diff --git a/usr.sbin/bhyve/pci_virtio_scsi.c b/usr.sbin/bhyve/pci_virtio_scsi.c index 38e7d918a096..283dd83b6e08 100644 --- a/usr.sbin/bhyve/pci_virtio_scsi.c +++ b/usr.sbin/bhyve/pci_virtio_scsi.c @@ -581,7 +581,7 @@ static void pci_vtscsi_eventq_notify(void *vsc, struct vqueue_info *vq) { - vq->vq_used->vu_flags |= VRING_USED_F_NO_NOTIFY; + vq_kick_disable(vq); } static void diff --git a/usr.sbin/bhyve/rfb.c b/usr.sbin/bhyve/rfb.c index d572037b25fe..0a0538f80e53 100644 --- a/usr.sbin/bhyve/rfb.c +++ b/usr.sbin/bhyve/rfb.c @@ -273,8 +273,10 @@ rfb_recv_set_encodings_msg(struct rfb_softc *rc, int cfd) rc->enc_raw_ok = true; break; case RFB_ENCODING_ZLIB: - rc->enc_zlib_ok = true; - deflateInit(&rc->zstream, Z_BEST_SPEED); + if (!rc->enc_zlib_ok) { + deflateInit(&rc->zstream, Z_BEST_SPEED); + rc->enc_zlib_ok = true; + } break; case RFB_ENCODING_RESIZE: rc->enc_resize_ok = true; diff --git a/usr.sbin/bhyve/virtio.c b/usr.sbin/bhyve/virtio.c index 47a3ed29bac0..2d78b016c6c3 100644 --- a/usr.sbin/bhyve/virtio.c +++ b/usr.sbin/bhyve/virtio.c @@ -428,7 +428,8 @@ vq_relchain(struct vqueue_info *vq, uint16_t idx, uint32_t iolen) /* * Ensure the used descriptor is visible before updating the index. - * This is necessary on ISAs with memory ordering less strict than x86. + * This is necessary on ISAs with memory ordering less strict than x86 + * (and even on x86 to act as a compiler barrier). */ atomic_thread_fence_rel(); vuh->vu_idx = uidx; diff --git a/usr.sbin/bhyve/virtio.h b/usr.sbin/bhyve/virtio.h index 1f5ef2e18b79..e0623f872453 100644 --- a/usr.sbin/bhyve/virtio.h +++ b/usr.sbin/bhyve/virtio.h @@ -31,6 +31,8 @@ #ifndef _VIRTIO_H_ #define _VIRTIO_H_ +#include + /* * These are derived from several virtio specifications. * @@ -447,6 +449,26 @@ vq_interrupt(struct virtio_softc *vs, struct vqueue_info *vq) } } +static inline void +vq_kick_enable(struct vqueue_info *vq) +{ + + vq->vq_used->vu_flags &= ~VRING_USED_F_NO_NOTIFY; + /* + * Full memory barrier to make sure the store to vu_flags + * happens before the load from va_idx, which results from + * a subsequent call to vq_has_descs(). + */ + atomic_thread_fence_seq_cst(); +} + +static inline void +vq_kick_disable(struct vqueue_info *vq) +{ + + vq->vq_used->vu_flags |= VRING_USED_F_NO_NOTIFY; +} + struct iovec; void vi_softc_linkup(struct virtio_softc *vs, struct virtio_consts *vc, void *dev_softc, struct pci_devinst *pi, diff --git a/usr.sbin/camdd/camdd.c b/usr.sbin/camdd/camdd.c index 2b41759acad8..b3d56c659d1d 100644 --- a/usr.sbin/camdd/camdd.c +++ b/usr.sbin/camdd/camdd.c @@ -80,6 +80,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -463,6 +464,9 @@ int camdd_probe_tape(int fd, char *filename, uint64_t *max_iosize, int camdd_probe_pass_scsi(struct cam_device *cam_dev, union ccb *ccb, camdd_argmask arglist, int probe_retry_count, int probe_timeout, uint64_t *maxsector, uint32_t *block_len); +int camdd_probe_pass_nvme(struct cam_device *cam_dev, union ccb *ccb, + camdd_argmask arglist, int probe_retry_count, + int probe_timeout, uint64_t *maxsector, uint32_t *block_len); struct camdd_dev *camdd_probe_file(int fd, struct camdd_io_opts *io_opts, int retry_count, int timeout); struct camdd_dev *camdd_probe_pass(struct cam_device *cam_dev, @@ -470,6 +474,11 @@ struct camdd_dev *camdd_probe_pass(struct cam_device *cam_dev, camdd_argmask arglist, int probe_retry_count, int probe_timeout, int io_retry_count, int io_timeout); +void nvme_read_write(struct ccb_nvmeio *nvmeio, uint32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + uint32_t nsid, int readop, uint64_t lba, + uint32_t block_count, uint8_t *data_ptr, uint32_t dxfer_len, + uint32_t timeout); void *camdd_file_worker(void *arg); camdd_buf_status camdd_ccb_status(union ccb *ccb, int protocol); int camdd_get_cgd(struct cam_device *device, struct ccb_getdev *cgd); @@ -1379,6 +1388,72 @@ camdd_probe_pass_scsi(struct cam_device *cam_dev, union ccb *ccb, return retval; } +int +camdd_probe_pass_nvme(struct cam_device *cam_dev, union ccb *ccb, + camdd_argmask arglist, int probe_retry_count, + int probe_timeout, uint64_t *maxsector, uint32_t *block_len) +{ + struct nvme_command *nc = NULL; + struct nvme_namespace_data nsdata; + uint32_t nsid = cam_dev->target_lun & UINT32_MAX; + uint8_t format = 0, lbads = 0; + int retval = -1; + + if (ccb == NULL) { + warnx("%s: error passed ccb is NULL", __func__); + goto bailout; + } + + CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->nvmeio); + + /* Send Identify Namespace to get block size and capacity */ + nc = &ccb->nvmeio.cmd; + nc->opc = NVME_OPC_IDENTIFY; + + nc->nsid = nsid; + nc->cdw10 = 0; /* Identify Namespace is CNS = 0 */ + + cam_fill_nvmeadmin(&ccb->nvmeio, + /*retries*/ probe_retry_count, + /*cbfcnp*/ NULL, + CAM_DIR_IN, + (uint8_t *)&nsdata, + sizeof(nsdata), + probe_timeout); + + /* Disable freezing the device queue */ + ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; + + if (arglist & CAMDD_ARG_ERR_RECOVER) + ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; + + if (cam_send_ccb(cam_dev, ccb) < 0) { + warn("error sending Identify Namespace command"); + + cam_error_print(cam_dev, ccb, CAM_ESF_ALL, + CAM_EPF_ALL, stderr); + + goto bailout; + } + + if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); + goto bailout; + } + + *maxsector = nsdata.nsze; + /* The LBA Data Size (LBADS) is reported as a power of 2 */ + format = nsdata.flbas & NVME_NS_DATA_FLBAS_FORMAT_MASK; + lbads = (nsdata.lbaf[format] >> NVME_NS_DATA_LBAF_LBADS_SHIFT) & + NVME_NS_DATA_LBAF_LBADS_MASK; + *block_len = 1 << lbads; + + retval = 0; + +bailout: + return retval; +} + /* * Need to implement this. Do a basic probe: * - Check the inquiry data, make sure we're talking to a device that we @@ -1400,7 +1475,7 @@ camdd_probe_pass(struct cam_device *cam_dev, struct camdd_io_opts *io_opts, struct kevent ke; struct ccb_getdev cgd; int retval; - int scsi_dev_type; + int scsi_dev_type = T_NODEVICE; if ((retval = camdd_get_cgd(cam_dev, &cgd)) != 0) { warnx("%s: error retrieving CGD", __func__); @@ -1442,6 +1517,13 @@ camdd_probe_pass(struct cam_device *cam_dev, struct camdd_io_opts *io_opts, goto bailout; } break; + case PROTO_NVME: + if ((retval = camdd_probe_pass_nvme(cam_dev, ccb, probe_retry_count, + arglist, probe_timeout, &maxsector, + &block_len))) { + goto bailout; + } + break; default: errx(1, "Unsupported PROTO type %d", cgd.protocol); break; /*NOTREACHED*/ @@ -1576,6 +1658,34 @@ camdd_probe_pass(struct cam_device *cam_dev, struct camdd_io_opts *io_opts, return (NULL); } +void +nvme_read_write(struct ccb_nvmeio *nvmeio, uint32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + uint32_t nsid, int readop, uint64_t lba, + uint32_t block_count, uint8_t *data_ptr, uint32_t dxfer_len, + uint32_t timeout) +{ + struct nvme_command *nc = &nvmeio->cmd; + + nc->opc = readop ? NVME_OPC_READ : NVME_OPC_WRITE; + + nc->nsid = nsid; + + nc->cdw10 = lba & UINT32_MAX; + nc->cdw11 = lba >> 32; + + /* NLB (bits 15:0) is a zero based value */ + nc->cdw12 = (block_count - 1) & UINT16_MAX; + + cam_fill_nvmeio(nvmeio, + retries, + cbfcnp, + readop ? CAM_DIR_IN : CAM_DIR_OUT, + data_ptr, + dxfer_len, + timeout); +} + void * camdd_worker(void *arg) { @@ -1831,6 +1941,16 @@ camdd_ccb_status(union ccb *ccb, int protocol) break; } break; + case PROTO_NVME: + switch (ccb_status) { + case CAM_REQ_CMP: + status = CAMDD_STATUS_OK; + break; + default: + status = CAMDD_STATUS_ERROR; + break; + } + break; default: status = CAMDD_STATUS_ERROR; break; @@ -2233,6 +2353,10 @@ camdd_pass_fetch(struct camdd_dev *dev) data->resid = ccb.csio.resid; dev->bytes_transferred += (ccb.csio.dxfer_len - ccb.csio.resid); break; + case PROTO_NVME: + data->resid = 0; + dev->bytes_transferred += ccb.nvmeio.dxfer_len; + break; default: return -1; break; @@ -2555,6 +2679,23 @@ camdd_pass_run(struct camdd_dev *dev) ccb->csio.sglist_cnt = data->sg_count; } break; + case PROTO_NVME: + CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->nvmeio); + + nvme_read_write(&ccb->nvmeio, + /*retries*/ dev->retry_count, + /*cbfcnp*/ NULL, + /*nsid*/ pass_dev->dev->target_lun & UINT32_MAX, + /*readop*/ dev->write_dev == 0, + /*lba*/ buf->lba, + /*block_count*/ num_blocks, + /*data_ptr*/ (data->sg_count != 0) ? + (uint8_t *)data->segs : data->buf, + /*dxfer_len*/ (num_blocks * pass_dev->block_len), + /*timeout*/ dev->io_timeout); + + ccb->nvmeio.sglist_cnt = data->sg_count; + break; default: retval = -1; goto bailout; diff --git a/usr.sbin/iostat/iostat.c b/usr.sbin/iostat/iostat.c index f98ba9228e47..dbe7219095e8 100644 --- a/usr.sbin/iostat/iostat.c +++ b/usr.sbin/iostat/iostat.c @@ -945,9 +945,11 @@ devstats(int perf_select, long double etime, int havelast) ms_per_transaction); } else { if (Iflag == 0) - printf(" %4.1Lf %4.0Lf %5.1Lf ", + printf(" %4.*Lf %4.0Lf %5.*Lf ", + kb_per_transfer >= 100 ? 0 : 1, kb_per_transfer, transfers_per_second, + mb_per_second >= 1000 ? 0 : 1, mb_per_second); else { total_mb = total_bytes; diff --git a/usr.sbin/pwm/pwm.8 b/usr.sbin/pwm/pwm.8 index 207dca407c8e..37c1aa8fec49 100644 --- a/usr.sbin/pwm/pwm.8 +++ b/usr.sbin/pwm/pwm.8 @@ -22,74 +22,88 @@ .\" .\" $FreeBSD$ .\" -.Dd January 12, 2019 +.Dd June 17, 2019 .Dt PWM 8 .Os .Sh NAME .Nm pwm -.Nd configure pwm controller +.Nd configure PWM (Pulse Width Modulation) hardware .Sh SYNOPSIS .Nm .Op Fl f Ar device -.Fl c Ar channel -.Fl E -.Nm -.Op Fl f Ar device -.Fl c Ar channel -.Fl D -.Nm -.Op Fl f Ar device -.Fl c Ar channel .Fl C .Nm .Op Fl f Ar device -.Fl c Ar channel -.Fl p Ar period -.Nm -.Op Fl f Ar device -.Fl c Ar channel -.Fl d Ar duty +.Op Fl D | Fl E +.Op Fl p Ar period +.Op Fl d Ar duty .Sh DESCRIPTION The .Nm -utility can be used to configure pwm controllers. +utility can be used to configure pwm hardware. +.Nm +uses a +.Xr pwmc 4 +device to communicate with the hardware. +Some PWM hardware supports multiple output channels within a single +controller block; each +.Xr pwmc 4 +instance controls a single PWM channel. .Pp -The options are as follow: -.Bl -tag -width "-c channel" -.It Fl c Ar channel -Channel number to operate on +.Xr pwmc 4 +devices are named +.Pa /dev/pwm/pwmcX.Y , +where +.Va X +is the controller unit number and +.Va Y +is the channel number within that unit. +.Pp +The options are as follows: +.Bl -tag -width "-f device" .It Fl f Ar device Device to operate on. If not specified, -.Pa /dev/pwmc0 +.Pa /dev/pwm/pwmc0.0 is used. -.It Fl E -Enable the pwm channel -.It Fl D -Disable the pwm channel +If an unqualified name is provided, +.Pa /dev/pwm +is automatically prepended. .It Fl C -Show the configuration of the pwm channel -.It Fl p Ar period -Configure the period (in nanoseconds) of the pwm channel +Show the configuration of the PWM channel. +.It Fl D +Disable the PWM channel. .It Fl d Ar duty -Configure the duty (in nanoseconds or percentage) of the pwm channel +Configure the duty cycle (in nanoseconds or percentage) of the PWM channel. +Duty is the portion of the +.Ar period +during which the signal is asserted. +.It Fl E +Enable the PWM channel. +.It Fl p Ar period +Configure the period (in nanoseconds) of the PWM channel. .El .Sh EXAMPLES .Bl -bullet .It -Show the configuration of the pwm channel: +Show the configuration of the PWM channel: .Bd -literal -pwm -f /dev/pwmc0 -C +pwm -f /dev/pwm/pwmc0.1 -C .Ed .It -Configure a 50000 ns period and a 25000 duty cycle: +Configure a 50000 ns period and a 25000 ns duty cycle +and enable the channel: .Bd -literal -pwm -f /dev/pwmc0 -p 50000 -d 25000 +pwm -f pwmc1.1 -E -p 50000 -d 25000 .Ed .It -Configure a 50% duty cycle: +Configure a 50% duty cycle on the device and channel which +were configured in +.Xr pwmc 4 +to have the label +.Pa backlight : .Bd -literal -pwm -f /dev/pwmc0 -d 50% +pwm -f backlight -d 50% .Ed .El .Sh SEE ALSO diff --git a/usr.sbin/pwm/pwm.c b/usr.sbin/pwm/pwm.c index 62e15bf18455..f8a213333d0e 100644 --- a/usr.sbin/pwm/pwm.c +++ b/usr.sbin/pwm/pwm.c @@ -31,12 +31,13 @@ #include #include #include -#include #include +#include #include #include #include +#include #include #include #include @@ -49,15 +50,24 @@ #define PWM_PERIOD 0x0008 #define PWM_DUTY 0x0010 +static char device_name[PATH_MAX] = "/dev/pwm/pwmc0.0"; + +static void +set_device_name(const char *name) +{ + + if (name[0] == '/') + strlcpy(device_name, name, sizeof(device_name)); + else + snprintf(device_name, sizeof(device_name), "/dev/pwm/%s", name); +} + static void usage(void) { fprintf(stderr, "Usage:\n"); - fprintf(stderr, "\tpwm [-f dev] -c channel -E\n"); - fprintf(stderr, "\tpwm [-f dev] -c channel -D\n"); - fprintf(stderr, "\tpwm [-f dev] -c channel -C\n"); - fprintf(stderr, "\tpwm [-f dev] -c channel -p period\n"); - fprintf(stderr, "\tpwm [-f dev] -c channel -d duty\n"); + fprintf(stderr, "\tpwm [-f dev] -C\n"); + fprintf(stderr, "\tpwm [-f dev] [-D | -E] [-p period] [-d duty[%%]]\n"); exit(1); } @@ -66,29 +76,29 @@ main(int argc, char *argv[]) { struct pwm_state state; int fd; - int channel, nchannels; int period, duty; int action, ch; cap_rights_t right_ioctl; - const unsigned long pwm_ioctls[] = {PWMGETSTATE, PWMSETSTATE, PWMMAXCHANNEL}; + const unsigned long pwm_ioctls[] = {PWMGETSTATE, PWMSETSTATE}; char *percent; + bool setname; action = 0; + setname = false; fd = -1; - channel = -1; period = duty = -1; - while ((ch = getopt(argc, argv, "f:c:EDCp:d:")) != -1) { + while ((ch = getopt(argc, argv, "f:EDCp:d:")) != -1) { switch (ch) { case 'E': - if (action) + if (action & (PWM_DISABLE | PWM_SHOW_CONFIG)) usage(); - action = PWM_ENABLE; + action |= PWM_ENABLE; break; case 'D': - if (action) + if (action & (PWM_ENABLE | PWM_SHOW_CONFIG)) usage(); - action = PWM_DISABLE; + action |= PWM_DISABLE; break; case 'C': if (action) @@ -96,44 +106,47 @@ main(int argc, char *argv[]) action = PWM_SHOW_CONFIG; break; case 'p': - if (action & ~(PWM_PERIOD | PWM_DUTY)) + if (action & PWM_SHOW_CONFIG) usage(); - action = PWM_PERIOD; + action |= PWM_PERIOD; period = strtol(optarg, NULL, 10); break; case 'd': - if (action & ~(PWM_PERIOD | PWM_DUTY)) + if (action & PWM_SHOW_CONFIG) usage(); - action = PWM_DUTY; + action |= PWM_DUTY; duty = strtol(optarg, &percent, 10); - if (*percent != '\0' && *percent != '%') + if (*percent == '%') { + if (duty < 0 || duty > 100) { + fprintf(stderr, + "Invalid duty percentage\n"); + usage(); + } + } else if (*percent != '\0') usage(); break; - case 'c': - if (channel != -1) - usage(); - channel = strtol(optarg, NULL, 10); - break; case 'f': - if ((fd = open(optarg, O_RDWR)) < 0) { - fprintf(stderr, "pwm: cannot open %s %s\n", - optarg, strerror(errno)); - exit(1); - } + setname = true; + set_device_name(optarg); + break; + case '?': + usage(); + break; } } - if (fd == -1) { - if ((fd = open("/dev/pwmc0", O_RDWR)) < 0) { - fprintf(stderr, "pwm: cannot open %s %s\n", - optarg, strerror(errno)); - exit(1); - } - } - - if (action == 0 || fd == -1) + if (action == 0) usage(); + if ((fd = open(device_name, O_RDWR)) == -1) { + fprintf(stderr, "pwm: cannot open %s: %s\n", + device_name, strerror(errno)); + if (setname) + exit(1); + else + usage(); + } + if (caph_limit_stdio() < 0) { fprintf(stderr, "can't limit stdio rights"); goto fail; @@ -153,67 +166,37 @@ main(int argc, char *argv[]) goto fail; } - /* Check if the channel is correct */ - if (ioctl(fd, PWMMAXCHANNEL, &nchannels) == -1) { - fprintf(stderr, "ioctl: %s\n", strerror(errno)); - goto fail; - } - if (channel > nchannels) { - fprintf(stderr, "pwm controller only support %d channels\n", - nchannels); - goto fail; - } - /* Fill the common args */ - state.channel = channel; if (ioctl(fd, PWMGETSTATE, &state) == -1) { fprintf(stderr, "Cannot get current state of the pwm controller\n"); goto fail; } - switch (action) { - case PWM_ENABLE: - if (state.enable == false) { - state.enable = true; - if (ioctl(fd, PWMSETSTATE, &state) == -1) { - fprintf(stderr, - "Cannot enable the pwm controller\n"); - goto fail; - } - } - break; - case PWM_DISABLE: - if (state.enable == true) { - state.enable = false; - if (ioctl(fd, PWMSETSTATE, &state) == -1) { - fprintf(stderr, - "Cannot disable the pwm controller\n"); - goto fail; - } - } - break; - case PWM_SHOW_CONFIG: + if (action == PWM_SHOW_CONFIG) { printf("period: %u\nduty: %u\nenabled:%d\n", state.period, state.duty, state.enable); - break; - case PWM_PERIOD: - case PWM_DUTY: - if (period != -1) + goto fail; + } else { + if (action & PWM_ENABLE) + state.enable = true; + if (action & PWM_DISABLE) + state.enable = false; + if (action & PWM_PERIOD) state.period = period; - if (duty != -1) { + if (action & PWM_DUTY) { if (*percent != '\0') state.duty = state.period * duty / 100; else state.duty = duty; } + if (ioctl(fd, PWMSETSTATE, &state) == -1) { fprintf(stderr, "Cannot configure the pwm controller\n"); goto fail; } - break; } close(fd);