From f3c588e171510616547b32dc14518d5fd81deec5 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Jan 2018 16:29:00 +0000 Subject: [PATCH 001/158] Document kern.smp.disabled tunable. Sponsored by: The FreeBSD Foundation MFC after: 3 days --- share/man/man4/smp.4 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/share/man/man4/smp.4 b/share/man/man4/smp.4 index a1b8c09f3133..b2c73c2b50ae 100644 --- a/share/man/man4/smp.4 +++ b/share/man/man4/smp.4 @@ -23,7 +23,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 7, 2008 +.Dd January 6, 2017 .Dt SMP 4 .Os .Sh NAME @@ -57,6 +57,11 @@ The .Xr mptable 1 command may be used to view the status of multi-processor support. .Pp +.Nm +support can be disabled by setting the loader tunable +.Va kern.smp.disabled +to 1. +.Pp The number of CPUs detected by the system is available in the read-only sysctl variable .Va hw.ncpu . From 98b306dcfd3495c83663e9961795fdcb5f00db04 Mon Sep 17 00:00:00 2001 From: Emmanuel Vadot Date: Sat, 6 Jan 2018 20:32:14 +0000 Subject: [PATCH 002/158] arm64: Remove old clock driver for Allwinner 64bit SoC All the clocks are now handled by the clkng driver. Tested On: Pine64-LTS (A64) Tested On: OrangePi PC2 (H5) --- sys/conf/files.arm64 | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 48c0c7499d58..b4df2843e93a 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -23,17 +23,13 @@ cloudabi64_vdso_blob.o optional compat_cloudabi64 \ no-implicit-rule \ clean "cloudabi64_vdso_blob.o" # + +# Allwinner common files arm/allwinner/a10_ehci.c optional ehci aw_ehci fdt arm/allwinner/aw_gpio.c optional gpio aw_gpio fdt arm/allwinner/aw_mmc.c optional mmc aw_mmc fdt -arm/allwinner/a64/a64_padconf.c optional soc_allwinner_a64 fdt -arm/allwinner/a64/a64_r_padconf.c optional soc_allwinner_a64 fdt -arm/allwinner/h3/h3_padconf.c optional soc_allwinner_h5 fdt -arm/allwinner/h3/h3_r_padconf.c optional soc_allwinner_h5 fdt -arm/allwinner/aw_ccu.c optional aw_ccu fdt arm/allwinner/aw_nmi.c optional aw_nmi fdt \ compile-with "${NORMAL_C} -I$S/gnu/dts/include" -arm/allwinner/aw_reset.c optional aw_ccu fdt arm/allwinner/aw_rsb.c optional aw_rsb fdt arm/allwinner/aw_rtc.c optional aw_rtc fdt arm/allwinner/aw_sid.c optional aw_sid fdt @@ -41,25 +37,23 @@ arm/allwinner/aw_thermal.c optional aw_thermal fdt arm/allwinner/aw_usbphy.c optional ehci aw_usbphy fdt arm/allwinner/aw_wdog.c optional aw_wdog fdt arm/allwinner/axp81x.c optional axp81x fdt -arm/allwinner/clk/aw_ahbclk.c optional aw_ccu fdt -arm/allwinner/clk/aw_apbclk.c optional aw_ccu fdt -arm/allwinner/clk/aw_axiclk.c optional aw_ccu fdt -arm/allwinner/clk/aw_cpuclk.c optional aw_ccu fdt -arm/allwinner/clk/aw_gate.c optional aw_ccu fdt -arm/allwinner/clk/aw_modclk.c optional aw_ccu fdt -arm/allwinner/clk/aw_pll.c optional aw_ccu fdt \ - compile-with "${NORMAL_C} -I$S/gnu/dts/include" -arm/allwinner/clk/aw_thsclk.c optional aw_ccu fdt -arm/allwinner/clk/aw_usbclk.c optional aw_ccu fdt -arm/allwinner/clkng/aw_ccung.c optional aw_ccu fdt +arm/allwinner/if_awg.c optional awg ext_resources syscon fdt + +# Allwinner clock driver +arm/allwinner/clkng/aw_ccung.c optional aw_ccu fdt arm/allwinner/clkng/aw_clk_nkmp.c optional aw_ccu fdt -arm/allwinner/clkng/aw_clk_nm.c optional aw_ccu fdt +arm/allwinner/clkng/aw_clk_nm.c optional aw_ccu fdt arm/allwinner/clkng/aw_clk_prediv_mux.c optional aw_ccu fdt -arm/allwinner/clkng/ccu_a64.c optional aw_ccu fdt -arm/allwinner/clkng/ccu_h3.c optional aw_ccu fdt +arm/allwinner/clkng/ccu_a64.c optional soc_allwinner_a64 aw_ccu fdt +arm/allwinner/clkng/ccu_h3.c optional soc_allwinner_h5 aw_ccu fdt arm/allwinner/clkng/ccu_sun8i_r.c optional aw_ccu fdt -arm/allwinner/if_awg.c optional awg ext_resources syscon fdt +# Allwinner padconf files +arm/allwinner/a64/a64_padconf.c optional soc_allwinner_a64 fdt +arm/allwinner/a64/a64_r_padconf.c optional soc_allwinner_a64 fdt +arm/allwinner/h3/h3_padconf.c optional soc_allwinner_h5 fdt +arm/allwinner/h3/h3_r_padconf.c optional soc_allwinner_h5 fdt + arm/annapurna/alpine/alpine_ccu.c optional al_ccu fdt arm/annapurna/alpine/alpine_nb_service.c optional al_nb_service fdt arm/annapurna/alpine/alpine_pci.c optional al_pci fdt From f397a004deeae195f8efdb4dc22a62204aa2c10d Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sun, 7 Jan 2018 00:44:22 +0000 Subject: [PATCH 003/158] geli: convert most tests from TAP to ATF I'm leaving readonly_test and nokey_test alone for now. In a future commit they should be broken up into several smaller test cases and distributed between multiple files. Reviewed by: ngie MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D13717 --- ObsoleteFiles.inc | 14 + tests/sys/geom/class/eli/Makefile | 36 +- tests/sys/geom/class/eli/attach_d_test.sh | 38 -- tests/sys/geom/class/eli/attach_test.sh | 45 +++ tests/sys/geom/class/eli/conf.sh | 23 +- .../sys/geom/class/eli/configure_b_B_test.sh | 129 ------ tests/sys/geom/class/eli/configure_test.sh | 59 +++ tests/sys/geom/class/eli/delkey_test.sh | 184 +++------ tests/sys/geom/class/eli/detach_l_test.sh | 44 -- tests/sys/geom/class/eli/detach_test.sh | 46 +++ tests/sys/geom/class/eli/init_B_test.sh | 104 ----- tests/sys/geom/class/eli/init_J_test.sh | 126 ------ tests/sys/geom/class/eli/init_a_test.sh | 46 --- tests/sys/geom/class/eli/init_alias_test.sh | 64 --- tests/sys/geom/class/eli/init_i_P_test.sh | 22 - tests/sys/geom/class/eli/init_test.sh | 380 ++++++++++++++++-- .../sys/geom/class/eli/integrity_copy_test.sh | 83 ---- .../sys/geom/class/eli/integrity_data_test.sh | 42 -- .../sys/geom/class/eli/integrity_hmac_test.sh | 43 -- tests/sys/geom/class/eli/integrity_test.sh | 160 ++++++++ tests/sys/geom/class/eli/kill_test.sh | 138 +++---- tests/sys/geom/class/eli/onetime_a_test.sh | 41 -- tests/sys/geom/class/eli/onetime_d_test.sh | 34 -- tests/sys/geom/class/eli/onetime_test.sh | 153 +++++-- tests/sys/geom/class/eli/resize_test.sh | 215 ++++------ tests/sys/geom/class/eli/setkey_test.sh | 214 ++++------ 26 files changed, 1104 insertions(+), 1379 deletions(-) delete mode 100644 tests/sys/geom/class/eli/attach_d_test.sh create mode 100755 tests/sys/geom/class/eli/attach_test.sh delete mode 100644 tests/sys/geom/class/eli/configure_b_B_test.sh create mode 100755 tests/sys/geom/class/eli/configure_test.sh delete mode 100644 tests/sys/geom/class/eli/detach_l_test.sh create mode 100755 tests/sys/geom/class/eli/detach_test.sh delete mode 100644 tests/sys/geom/class/eli/init_B_test.sh delete mode 100644 tests/sys/geom/class/eli/init_J_test.sh delete mode 100644 tests/sys/geom/class/eli/init_a_test.sh delete mode 100644 tests/sys/geom/class/eli/init_alias_test.sh delete mode 100644 tests/sys/geom/class/eli/init_i_P_test.sh delete mode 100644 tests/sys/geom/class/eli/integrity_copy_test.sh delete mode 100644 tests/sys/geom/class/eli/integrity_data_test.sh delete mode 100644 tests/sys/geom/class/eli/integrity_hmac_test.sh create mode 100755 tests/sys/geom/class/eli/integrity_test.sh delete mode 100644 tests/sys/geom/class/eli/onetime_a_test.sh delete mode 100644 tests/sys/geom/class/eli/onetime_d_test.sh diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 52a7e60ca699..a3c7f9828297 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,20 @@ # xargs -n1 | sort | uniq -d; # done +# 20180106: Convert most geli(8) tests to ATF +OLD_FILES+=tests/sys/geom/class/eli/attach_d_test.sh +OLD_FILES+=tests/sys/geom/class/eli/configure_b_B_test.sh +OLD_FILES+=tests/sys/geom/class/eli/detach_l_test.sh +OLD_FILES+=tests/sys/geom/class/eli/init_B_test.sh +OLD_FILES+=tests/sys/geom/class/eli/init_J_test.sh +OLD_FILES+=tests/sys/geom/class/eli/init_a_test.sh +OLD_FILES+=tests/sys/geom/class/eli/init_alias_test.sh +OLD_FILES+=tests/sys/geom/class/eli/init_i_P_test.sh +OLD_FILES+=tests/sys/geom/class/eli/integrity_copy_test.sh +OLD_FILES+=tests/sys/geom/class/eli/integrity_data_test.sh +OLD_FILES+=tests/sys/geom/class/eli/integrity_hmac_test.sh +OLD_FILES+=tests/sys/geom/class/eli/onetime_a_test.sh +OLD_FILES+=tests/sys/geom/class/eli/onetime_d_test.sh # 20171230: Remove /etc/skel from mtree OLD_DIRS+=/etc/skel # 20171208: Remove basename_r(3) diff --git a/tests/sys/geom/class/eli/Makefile b/tests/sys/geom/class/eli/Makefile index c4277a04f23e..654f6f303ff0 100644 --- a/tests/sys/geom/class/eli/Makefile +++ b/tests/sys/geom/class/eli/Makefile @@ -7,36 +7,20 @@ PACKAGE= tests TESTSDIR= ${TESTSBASE}/sys/geom/class/${.CURDIR:T} ATF_TESTS_C= pbkdf2_test +ATF_TESTS_SH+= attach_test +ATF_TESTS_SH+= configure_test +ATF_TESTS_SH+= delkey_test +ATF_TESTS_SH+= detach_test +ATF_TESTS_SH+= init_test +ATF_TESTS_SH+= integrity_test +ATF_TESTS_SH+= kill_test +ATF_TESTS_SH+= onetime_test +ATF_TESTS_SH+= resize_test +ATF_TESTS_SH+= setkey_test -TAP_TESTS_SH+= attach_d_test -TAP_TESTS_SH+= configure_b_B_test -TAP_TESTS_SH+= delkey_test -TAP_TESTS_SH+= detach_l_test -TAP_TESTS_SH+= init_B_test -TAP_TESTS_SH+= init_J_test -TAP_TESTS_SH+= init_a_test -TAP_TESTS_SH+= init_alias_test -TAP_TESTS_SH+= init_i_P_test -TAP_TESTS_SH+= init_test -TAP_TESTS_SH+= integrity_copy_test -TAP_TESTS_SH+= integrity_data_test -TAP_TESTS_SH+= integrity_hmac_test -TAP_TESTS_SH+= kill_test TAP_TESTS_SH+= nokey_test -TAP_TESTS_SH+= onetime_a_test -TAP_TESTS_SH+= onetime_d_test -TAP_TESTS_SH+= onetime_test TAP_TESTS_SH+= readonly_test -TAP_TESTS_SH+= resize_test -TAP_TESTS_SH+= setkey_test -TEST_METADATA.init_a_test+= timeout="3600" -TEST_METADATA.init_test+= timeout="600" -TEST_METADATA.integrity_copy_test+= timeout="3600" -TEST_METADATA.integrity_data_test+= timeout="1800" -TEST_METADATA.integrity_hmac_test+= timeout="1800" -TEST_METADATA.onetime_a_test+= timeout="1800" -TEST_METADATA.onetime_test+= timeout="1800" ${PACKAGE}FILES+= conf.sh diff --git a/tests/sys/geom/class/eli/attach_d_test.sh b/tests/sys/geom/class/eli/attach_d_test.sh deleted file mode 100644 index ed9226972d89..000000000000 --- a/tests/sys/geom/class/eli/attach_d_test.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=100 -keyfile=`mktemp $base.XXXXXX` || exit 1 -md=$(attach_md -t malloc -s `expr $sectors + 1`) - -echo "1..3" - -dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1 - -geli init -B none -P -K $keyfile ${md} -geli attach -d -p -k $keyfile ${md} -if [ -c /dev/${md}.eli ]; then - echo "ok 1" -else - echo "not ok 1" -fi -# Be sure it doesn't detach on read. -dd if=/dev/${md}.eli of=/dev/null 2>/dev/null -sleep 1 -if [ -c /dev/${md}.eli ]; then - echo "ok 2" -else - echo "not ok 2" -fi -true > /dev/${md}.eli -sleep 1 -if [ ! -c /dev/${md}.eli ]; then - echo "ok 3" -else - echo "not ok 3" -fi - -rm -f $keyfile diff --git a/tests/sys/geom/class/eli/attach_test.sh b/tests/sys/geom/class/eli/attach_test.sh new file mode 100755 index 000000000000..83215e968510 --- /dev/null +++ b/tests/sys/geom/class/eli/attach_test.sh @@ -0,0 +1,45 @@ +# $FreeBSD$ + +atf_test_case attach_d cleanup +attach_d_head() +{ + atf_set "descr" "geli attach -d will cause the provider to detach on last close" + atf_set "require.user" "root" +} +attach_d_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=100 + md=$(attach_md -t malloc -s `expr $sectors + 1`) + + atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + + atf_check geli init -B none -P -K keyfile ${md} + atf_check geli attach -d -p -k keyfile ${md} + + # Be sure it doesn't detach on read. + atf_check dd if=/dev/${md}.eli of=/dev/null status=none + sleep 1 + if [ ! -c /dev/${md}.eli ]; then + atf_fail "Detached on last close of a reader" + fi + + # It should detach on last close of a writer + true > /dev/${md}.eli + sleep 1 + if [ -c /dev/${md}.eli ]; then + atf_fail "Did not detach on last close of a writer" + fi + +} +attach_d_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + +atf_init_test_cases() +{ + atf_add_test_case attach_d +} diff --git a/tests/sys/geom/class/eli/conf.sh b/tests/sys/geom/class/eli/conf.sh index 6e26145623ef..da2ca9e4d277 100644 --- a/tests/sys/geom/class/eli/conf.sh +++ b/tests/sys/geom/class/eli/conf.sh @@ -2,7 +2,18 @@ # $FreeBSD$ class="eli" -base=`basename $0` +base=$(atf_get ident) +[ -z "$base" ] && base=`basename $0` # for TAP compatibility +TEST_MDS_FILE=md.devs + +attach_md() +{ + local test_md + + test_md=$(mdconfig -a "$@") || atf_fail "failed to allocate md(4)" + echo $test_md >> $TEST_MDS_FILE || exit + echo $test_md +} # Execute `func` for each combination of cipher, sectorsize, and hmac algo # `func` usage should be: @@ -23,7 +34,11 @@ for_each_geli_config() { for aalgo in hmac/md5 hmac/sha1 hmac/ripemd160 hmac/sha256 \ hmac/sha384 hmac/sha512; do for secsize in 512 1024 2048 4096 8192; do - bytes=`expr $secsize \* $sectors + 512`b + # Double the requested sector size to allow + # for the HMACs' storage space. + osecsize=$(( $secsize * 2 )) + # geli needs 512B for the label. + bytes=`expr $osecsize \* $sectors + 512`b md=$(attach_md -t malloc -s $bytes) ${func} $cipher $aalgo $secsize geli detach ${md} 2>/dev/null @@ -50,6 +65,7 @@ for_each_geli_config_nointegrity() { ealgo=${cipher%%:*} keylen=${cipher##*:} for secsize in 512 1024 2048 4096 8192; do + # geli needs 512B for the label. bytes=`expr $secsize \* $sectors + 512`b md=$(attach_md -t malloc -s $bytes) ${func} $cipher $secsize @@ -69,8 +85,9 @@ geli_test_cleanup() mdconfig -d -u $md 2>/dev/null done < $TEST_MDS_FILE fi - rm -f "$TEST_MDS_FILE" + true } +# TODO: remove the trap statement once all TAP tests are converted trap geli_test_cleanup ABRT EXIT INT TERM . `dirname $0`/../geom_subr.sh diff --git a/tests/sys/geom/class/eli/configure_b_B_test.sh b/tests/sys/geom/class/eli/configure_b_B_test.sh deleted file mode 100644 index 521917551fc4..000000000000 --- a/tests/sys/geom/class/eli/configure_b_B_test.sh +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=100 -md=$(attach_md -t malloc -s `expr $sectors + 1`) - -echo "1..17" - -geli init -B none -P -K /dev/null ${md} -if [ $? -eq 0 ]; then - echo "ok 1" -else - echo "not ok 1" -fi - -geli dump ${md} | egrep 'flags: 0x0$' >/dev/null -if [ $? -eq 0 ]; then - echo "ok 2" -else - echo "not ok 2" -fi - -geli init -B none -b -P -K /dev/null ${md} -if [ $? -eq 0 ]; then - echo "ok 3" -else - echo "not ok 3" -fi - -geli dump ${md} | egrep 'flags: 0x2$' >/dev/null -if [ $? -eq 0 ]; then - echo "ok 4" -else - echo "not ok 4" -fi - -geli configure -B ${md} -if [ $? -eq 0 ]; then - echo "ok 5" -else - echo "not ok 5" -fi - -geli dump ${md} | egrep 'flags: 0x0$' >/dev/null -if [ $? -eq 0 ]; then - echo "ok 6" -else - echo "not ok 6" -fi - -geli configure -b ${md} -if [ $? -eq 0 ]; then - echo "ok 7" -else - echo "not ok 7" -fi - -geli dump ${md} | egrep 'flags: 0x2$' >/dev/null -if [ $? -eq 0 ]; then - echo "ok 8" -else - echo "not ok 8" -fi - -geli attach -p -k /dev/null ${md} -if [ $? -eq 0 ]; then - echo "ok 9" -else - echo "not ok 9" -fi - -geli list ${md}.eli | egrep '^Flags: .*BOOT' >/dev/null -if [ $? -eq 0 ]; then - echo "ok 10" -else - echo "not ok 10" -fi - -geli configure -B ${md} -if [ $? -eq 0 ]; then - echo "ok 11" -else - echo "not ok 11" -fi - -geli list ${md}.eli | egrep '^Flags: .*BOOT' >/dev/null -if [ $? -ne 0 ]; then - echo "ok 12" -else - echo "not ok 12" -fi - -geli dump ${md} | egrep 'flags: 0x0$' >/dev/null -if [ $? -eq 0 ]; then - echo "ok 13" -else - echo "not ok 13" -fi - -geli configure -b ${md} -if [ $? -eq 0 ]; then - echo "ok 14" -else - echo "not ok 14" -fi - -geli list ${md}.eli | egrep '^Flags: .*BOOT' >/dev/null -if [ $? -eq 0 ]; then - echo "ok 15" -else - echo "not ok 15" -fi - -geli dump ${md} | egrep 'flags: 0x2$' >/dev/null -if [ $? -eq 0 ]; then - echo "ok 16" -else - echo "not ok 16" -fi - -geli detach ${md} -if [ $? -eq 0 ]; then - echo "ok 17" -else - echo "not ok 17" -fi diff --git a/tests/sys/geom/class/eli/configure_test.sh b/tests/sys/geom/class/eli/configure_test.sh new file mode 100755 index 000000000000..da060e6119ea --- /dev/null +++ b/tests/sys/geom/class/eli/configure_test.sh @@ -0,0 +1,59 @@ +# $FreeBSD$ + +atf_test_case configure_b_B cleanup +configure_b_B_head() +{ + atf_set "descr" "geli configure -b will set the BOOT flag" + atf_set "require.user" "root" +} +configure_b_B_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=100 + md=$(attach_md -t malloc -s `expr $sectors + 1`) + + atf_check geli init -B none -P -K /dev/null ${md} + + atf_check -s exit:0 -o match:'flags: 0x0$' geli dump ${md} + + atf_check geli init -B none -b -P -K /dev/null ${md} + + atf_check -s exit:0 -o match:'flags: 0x2$' geli dump ${md} + + atf_check geli configure -B ${md} + + atf_check -s exit:0 -o match:'flags: 0x0$' geli dump ${md} + + atf_check geli configure -b ${md} + + atf_check -s exit:0 -o match:'flags: 0x2$' geli dump ${md} + + atf_check geli attach -p -k /dev/null ${md} + + atf_check -s exit:0 -o match:'^Flags: .*BOOT' geli list ${md}.eli + + atf_check geli configure -B ${md} + + atf_check -o not-match:'^Flags: .*BOOT' geli list ${md}.eli + + atf_check -s exit:0 -o match:'flags: 0x0$' geli dump ${md} + + atf_check geli configure -b ${md} + + atf_check -s exit:0 -o match:'^Flags: .*BOOT' geli list ${md}.eli + + atf_check -s exit:0 -o match:'flags: 0x2$' geli dump ${md} + + atf_check geli detach ${md} +} +configure_b_B_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + +atf_init_test_cases() +{ + atf_add_test_case configure_b_B +} diff --git a/tests/sys/geom/class/eli/delkey_test.sh b/tests/sys/geom/class/eli/delkey_test.sh index a76100a4dda4..99453f1d0b26 100644 --- a/tests/sys/geom/class/eli/delkey_test.sh +++ b/tests/sys/geom/class/eli/delkey_test.sh @@ -1,140 +1,86 @@ #!/bin/sh # $FreeBSD$ -. $(dirname $0)/conf.sh +atf_test_case delkey cleanup +delkey_head() +{ + atf_set "descr" "geli delkey can destroy the master key" + atf_set "require.user" "root" +} +delkey_body() +{ + . $(atf_get_srcdir)/conf.sh -base=`basename $0` -sectors=100 -keyfile1=`mktemp $base.XXXXXX` || exit 1 -keyfile2=`mktemp $base.XXXXXX` || exit 1 -keyfile3=`mktemp $base.XXXXXX` || exit 1 -keyfile4=`mktemp $base.XXXXXX` || exit 1 -md=$(attach_md -t malloc -s `expr $sectors + 1`) + sectors=100 + md=$(attach_md -t malloc -s `expr $sectors + 1`) -echo "1..14" + atf_check dd if=/dev/random of=keyfile1 bs=512 count=16 status=none + atf_check dd if=/dev/random of=keyfile2 bs=512 count=16 status=none + atf_check dd if=/dev/random of=keyfile3 bs=512 count=16 status=none + atf_check dd if=/dev/random of=keyfile4 bs=512 count=16 status=none -dd if=/dev/random of=${keyfile1} bs=512 count=16 >/dev/null 2>&1 -dd if=/dev/random of=${keyfile2} bs=512 count=16 >/dev/null 2>&1 -dd if=/dev/random of=${keyfile3} bs=512 count=16 >/dev/null 2>&1 -dd if=/dev/random of=${keyfile4} bs=512 count=16 >/dev/null 2>&1 + atf_check geli init -B none -P -K keyfile1 ${md} + atf_check geli attach -p -k keyfile1 ${md} + atf_check -s exit:0 -o ignore geli setkey -n 1 -P -K keyfile2 ${md} -geli init -B none -P -K $keyfile1 ${md} -geli attach -p -k $keyfile1 ${md} -geli setkey -n 1 -P -K $keyfile2 ${md} + # Remove key 0 for attached provider. + atf_check geli delkey -n 0 ${md} + atf_check geli detach ${md} -# Remove key 0 for attached provider. -geli delkey -n 0 ${md} -if [ $? -eq 0 ]; then - echo "ok 1" -else - echo "not ok 1" -fi -geli detach ${md} + # We cannot use keyfile1 anymore. + atf_check -s not-exit:0 -e match:"Wrong key" \ + geli attach -p -k keyfile1 ${md} -# We cannot use keyfile1 anymore. -geli attach -p -k $keyfile1 ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 2" -else - echo "not ok 2" -fi + # Attach with key 1. + atf_check geli attach -p -k keyfile2 ${md} -# Attach with key 1. -geli attach -p -k $keyfile2 ${md} -if [ $? -eq 0 ]; then - echo "ok 3" -else - echo "not ok 3" -fi + # We cannot remove last key without -f option (for attached provider). + atf_check -s not-exit:0 -e match:"This is the last Master Key" \ + geli delkey -n 1 ${md} -# We cannot remove last key without -f option (for attached provider). -geli delkey -n 1 ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 4" -else - echo "not ok 4" -fi + # Remove last key for attached provider. + atf_check geli delkey -f -n 1 ${md} -# Remove last key for attached provider. -geli delkey -f -n 1 ${md} -if [ $? -eq 0 ]; then - echo "ok 5" -else - echo "not ok 5" -fi + # If there are no valid keys, but provider is attached, we can save situation. + atf_check -s exit:0 -o ignore geli setkey -n 0 -P -K keyfile3 ${md} + atf_check geli detach ${md} -# If there are no valid keys, but provider is attached, we can save situation. -geli setkey -n 0 -P -K $keyfile3 ${md} -if [ $? -eq 0 ]; then - echo "ok 6" -else - echo "not ok 6" -fi -geli detach ${md} + # We cannot use keyfile2 anymore. + atf_check -s not-exit:0 -e match:"Wrong key" \ + geli attach -p -k keyfile2 ${md} -# We cannot use keyfile2 anymore. -geli attach -p -k $keyfile2 ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 7" -else - echo "not ok 7" -fi + # Attach with key 0. + atf_check geli attach -p -k keyfile3 ${md} -# Attach with key 0. -geli attach -p -k $keyfile3 ${md} -if [ $? -eq 0 ]; then - echo "ok 8" -else - echo "not ok 8" -fi + # Setup key 1. + atf_check -s exit:0 -o ignore geli setkey -n 1 -P -K keyfile4 ${md} + atf_check geli detach ${md} -# Setup key 1. -geli setkey -n 1 -P -K $keyfile4 ${md} -if [ $? -eq 0 ]; then - echo "ok 9" -else - echo "not ok 9" -fi -geli detach ${md} + # Remove key 1 for detached provider. + atf_check geli delkey -n 1 ${md} -# Remove key 1 for detached provider. -geli delkey -n 1 ${md} -if [ $? -eq 0 ]; then - echo "ok 10" -else - echo "not ok 10" -fi + # We cannot use keyfile4 anymore. + atf_check -s not-exit:0 -e match:"Wrong key" \ + geli attach -p -k keyfile4 ${md} -# We cannot use keyfile4 anymore. -geli attach -p -k $keyfile4 ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 11" -else - echo "not ok 11" -fi + # We cannot remove last key without -f option (for detached provider). + atf_check -s not-exit:0 -e match:"This is the last Master Key" \ + geli delkey -n 0 ${md} -# We cannot remove last key without -f option (for detached provider). -geli delkey -n 0 ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 12" -else - echo "not ok 12" -fi + # Remove last key for detached provider. + atf_check geli delkey -f -n 0 ${md} -# Remove last key for detached provider. -geli delkey -f -n 0 ${md} -if [ $? -eq 0 ]; then - echo "ok 13" -else - echo "not ok 13" -fi + # We cannot use keyfile3 anymore. + atf_check -s not-exit:0 -e match:"No valid keys" \ + geli attach -p -k keyfile3 ${md} +} +delkey_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} -# We cannot use keyfile3 anymore. -geli attach -p -k $keyfile3 ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 14" -else - echo "not ok 14" -fi - -rm -f $keyfile1 $keyfile2 $keyfile3 $keyfile4 +atf_init_test_cases() +{ + atf_add_test_case delkey +} diff --git a/tests/sys/geom/class/eli/detach_l_test.sh b/tests/sys/geom/class/eli/detach_l_test.sh deleted file mode 100644 index ba5e1892cf58..000000000000 --- a/tests/sys/geom/class/eli/detach_l_test.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=100 -keyfile=`mktemp $base.XXXXXX` || exit 1 -md=$(attach_md -t malloc -s `expr $sectors + 1`) - -echo "1..4" - -dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1 - -geli init -B none -P -K $keyfile ${md} -geli attach -p -k $keyfile ${md} -if [ -c /dev/${md}.eli ]; then - echo "ok 1" -else - echo "not ok 1" -fi -# Be sure it doesn't detach before 'detach -l'. -dd if=/dev/${md}.eli of=/dev/null 2>/dev/null -sleep 1 -if [ -c /dev/${md}.eli ]; then - echo "ok 2" -else - echo "not ok 2" -fi -geli detach -l ${md} -if [ -c /dev/${md}.eli ]; then - echo "ok 3" -else - echo "not ok 3" -fi -dd if=/dev/${md}.eli of=/dev/null 2>/dev/null -sleep 1 -if [ ! -c /dev/${md}.eli ]; then - echo "ok 4" -else - echo "not ok 4" -fi - -rm -f $keyfile diff --git a/tests/sys/geom/class/eli/detach_test.sh b/tests/sys/geom/class/eli/detach_test.sh new file mode 100755 index 000000000000..1a3bd3887e8d --- /dev/null +++ b/tests/sys/geom/class/eli/detach_test.sh @@ -0,0 +1,46 @@ +# $FreeBSD$ + +atf_test_case detach_l cleanup +detach_l_head() +{ + atf_set "descr" "geli detach -l will cause a provider to detach on last close" + atf_set "require.user" "root" +} +detach_l_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=100 + md=$(attach_md -t malloc -s `expr $sectors + 1`) + + atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + + atf_check geli init -B none -P -K keyfile ${md} + atf_check geli attach -p -k keyfile ${md} + + # Be sure it doesn't detach before 'detach -l'. + atf_check dd if=/dev/${md}.eli of=/dev/null status=none + sleep 1 + if [ ! -c /dev/${md}.eli ]; then + atf_fail "provider detached on last close without detach -l" + fi + atf_check geli detach -l ${md} + if [ ! -c /dev/${md}.eli ]; then + atf_fail "Provider detached before last close" + fi + atf_check dd if=/dev/${md}.eli of=/dev/null status=none + sleep 1 + if [ -c /dev/${md}.eli ]; then + atf_fail "Provider did not detach on last close" + fi +} +detach_l_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + +atf_init_test_cases() +{ + atf_add_test_case detach_l +} diff --git a/tests/sys/geom/class/eli/init_B_test.sh b/tests/sys/geom/class/eli/init_B_test.sh deleted file mode 100644 index 8d384a739309..000000000000 --- a/tests/sys/geom/class/eli/init_B_test.sh +++ /dev/null @@ -1,104 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=100 -keyfile=`mktemp $base.XXXXXX` || exit 1 -backupfile=`mktemp $base.XXXXXX` || exit 1 - -echo "1..13" - -dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1 - -md=$(attach_md -t malloc -s `expr $sectors`) - -# -B none -rm -f /var/backups/${md}.eli -geli init -B none -P -K $keyfile ${md} 2>/dev/null -if [ ! -f /var/backups/${md}.eli ]; then - echo "ok 1 - -B none" -else - echo "not ok 1 - -B none" -fi - -# no -B -rm -f /var/backups/${md}.eli -geli init -P -K $keyfile ${md} >/dev/null 2>&1 -if [ -f /var/backups/${md}.eli ]; then - echo "ok 2 - no -B" -else - echo "not ok 2 - no -B" -fi -geli clear ${md} -geli attach -p -k $keyfile ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 3 - no -B" -else - echo "not ok 3 - no -B" -fi -if [ ! -c /dev/${md}.eli ]; then - echo "ok 4 - no -B" -else - echo "not ok 4 - no -B" -fi -geli restore /var/backups/${md}.eli ${md} -if [ $? -eq 0 ]; then - echo "ok 5 - no -B" -else - echo "not ok 5 - no -B" -fi -geli attach -p -k $keyfile ${md} 2>/dev/null -if [ $? -eq 0 ]; then - echo "ok 6 - no -B" -else - echo "not ok 6 - no -B" -fi -if [ -c /dev/${md}.eli ]; then - echo "ok 7 - no -B" -else - echo "not ok 7 - no -B" -fi -geli detach ${md} -rm -f /var/backups/${md}.eli - -# -B file -rm -f $backupfile -geli init -B $backupfile -P -K $keyfile ${md} >/dev/null 2>&1 -if [ -f $backupfile ]; then - echo "ok 8 - -B file" -else - echo "not ok 8 - -B file" -fi -geli clear ${md} -geli attach -p -k $keyfile ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 9 - -B file" -else - echo "not ok 9 - -B file" -fi -if [ ! -c /dev/${md}.eli ]; then - echo "ok 10 - -B file" -else - echo "not ok 10 - -B file" -fi -geli restore $backupfile ${md} -if [ $? -eq 0 ]; then - echo "ok 11 - -B file" -else - echo "not ok 11 - -B file" -fi -geli attach -p -k $keyfile ${md} 2>/dev/null -if [ $? -eq 0 ]; then - echo "ok 12 - -B file" -else - echo "not ok 12 - -B file" -fi -if [ -c /dev/${md}.eli ]; then - echo "ok 13 - -B file" -else - echo "not ok 13 - -B file" -fi - -rm -f $backupfile $keyfile diff --git a/tests/sys/geom/class/eli/init_J_test.sh b/tests/sys/geom/class/eli/init_J_test.sh deleted file mode 100644 index 090a50877455..000000000000 --- a/tests/sys/geom/class/eli/init_J_test.sh +++ /dev/null @@ -1,126 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=100 -keyfile0=`mktemp $base.XXXXXX` || exit 1 -keyfile1=`mktemp $base.XXXXXX` || exit 1 -passfile0=`mktemp $base.XXXXXX` || exit 1 -passfile1=`mktemp $base.XXXXXX` || exit 1 -md=$(attach_md -t malloc -s `expr $sectors + 1`) - -echo "1..150" - -dd if=/dev/random of=${keyfile0} bs=512 count=16 >/dev/null 2>&1 -dd if=/dev/random of=${keyfile1} bs=512 count=16 >/dev/null 2>&1 -dd if=/dev/random bs=512 count=16 2>/dev/null | sha1 > ${passfile0} -dd if=/dev/random bs=512 count=16 2>/dev/null | sha1 > ${passfile1} - -i=1 -for iter in -1 0 64; do - geli init -i ${iter} -B none -J ${passfile0} -P ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli init -i ${iter} -B none -J ${passfile0} -P -K ${keyfile0} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli init -i ${iter} -B none -J ${passfile0} -K ${keyfile0} ${md} 2>/dev/null || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${keyfile0} -p ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -j ${passfile0} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -j ${keyfile0} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${passfile0} -p ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -j ${keyfile0} -k ${passfile0} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -j ${keyfile0} -k ${keyfile0} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -j ${passfile0} -k ${passfile0} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -j ${passfile0} -k ${keyfile0} ${md} 2>/dev/null || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli detach ${md} || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - cat ${keyfile0} | geli attach -j ${passfile0} -k - ${md} 2>/dev/null || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli detach ${md} || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - cat ${passfile0} | geli attach -j - -k ${keyfile0} ${md} 2>/dev/null || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli detach ${md} || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - - geli init -i ${iter} -B none -J ${passfile0} -J ${passfile1} -P ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli init -i ${iter} -B none -J ${passfile0} -J ${passfile1} -P -K ${keyfile0} -K ${keyfile1} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli init -i ${iter} -B none -J ${passfile0} -J ${passfile1} -K ${keyfile0} -K ${keyfile1} ${md} 2>/dev/null || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${keyfile0} -p ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${keyfile1} -p ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -j ${passfile0} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -j ${passfile1} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${keyfile0} -k ${keyfile1} -p ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -j ${passfile0} -j ${passfile1} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${keyfile0} -j ${passfile0} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${keyfile0} -j ${passfile1} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${keyfile1} -j ${passfile0} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${keyfile1} -j ${passfile1} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${keyfile0} -j ${passfile0} -j ${passfile1} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${keyfile1} -j ${passfile0} -j ${passfile1} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${keyfile0} -k ${keyfile1} -j ${passfile0} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${keyfile0} -k ${keyfile1} -j ${passfile1} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${keyfile1} -k ${keyfile0} -j ${passfile0} -j ${passfile1} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${keyfile0} -k ${keyfile1} -j ${passfile1} -j ${passfile0} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -k ${keyfile1} -k ${keyfile0} -j ${passfile1} -j ${passfile0} ${md} 2>/dev/null && echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli attach -j ${passfile0} -j ${passfile1} -k ${keyfile0} -k ${keyfile1} ${md} 2>/dev/null || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli detach ${md} || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - cat ${passfile0} | geli attach -j - -j ${passfile1} -k ${keyfile0} -k ${keyfile1} ${md} 2>/dev/null || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli detach ${md} || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - cat ${passfile1} | geli attach -j ${passfile0} -j - -k ${keyfile0} -k ${keyfile1} ${md} 2>/dev/null || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli detach ${md} || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - cat ${keyfile0} | geli attach -j ${passfile0} -j ${passfile1} -k - -k ${keyfile1} ${md} 2>/dev/null || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli detach ${md} || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - cat ${keyfile1} | geli attach -j ${passfile0} -j ${passfile1} -k ${keyfile0} -k - ${md} 2>/dev/null || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli detach ${md} || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - cat ${keyfile0} ${keyfile1} | geli attach -j ${passfile0} -j ${passfile1} -k - ${md} 2>/dev/null || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli detach ${md} || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - cat ${passfile0} ${passfile1} | awk '{printf "%s", $0}' | geli attach -j - -k ${keyfile0} -k ${keyfile1} ${md} 2>/dev/null || echo -n "not " - echo "ok ${i}"; i=$((i+1)) - geli detach ${md} || echo -n "not " - echo "ok ${i}"; i=$((i+1)) -done - -rm -f ${keyfile0} ${keyfile1} ${passfile0} ${passfile1} diff --git a/tests/sys/geom/class/eli/init_a_test.sh b/tests/sys/geom/class/eli/init_a_test.sh deleted file mode 100644 index 9f349f5c908d..000000000000 --- a/tests/sys/geom/class/eli/init_a_test.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=100 -keyfile=`mktemp $base.XXXXXX` || exit 1 -rnd=`mktemp $base.XXXXXX` || exit 1 - -do_test() { - cipher=$1 - aalgo=$2 - secsize=$3 - ealgo=${cipher%%:*} - keylen=${cipher##*:} - - geli init -B none -a $aalgo -e $ealgo -l $keylen -P -K $keyfile -s $secsize ${md} 2>/dev/null - geli attach -p -k $keyfile ${md} - - secs=`diskinfo /dev/${md}.eli | awk '{print $4}'` - - dd if=${rnd} of=/dev/${md}.eli bs=${secsize} count=${secs} 2>/dev/null - - md_rnd=`dd if=${rnd} bs=${secsize} count=${secs} 2>/dev/null | md5` - md_ddev=`dd if=/dev/${md}.eli bs=${secsize} count=${secs} 2>/dev/null | md5` - - if [ ${md_rnd} = ${md_ddev} ]; then - echo "ok $i - aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - else - echo "not ok $i - aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - fi - i=$((i+1)) -} - -echo "1..600" - -i=1 - -dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1 -dd if=/dev/random of=${rnd} bs=8192 count=${sectors} >/dev/null 2>&1 - -for_each_geli_config do_test - -rm -f $rnd -rm -f $keyfile diff --git a/tests/sys/geom/class/eli/init_alias_test.sh b/tests/sys/geom/class/eli/init_alias_test.sh deleted file mode 100644 index 24aa3941444d..000000000000 --- a/tests/sys/geom/class/eli/init_alias_test.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -# Test "geli init"'s various cipher aliases -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=100 -keyfile=`mktemp $base.XXXXXX` || exit 1 -rnd=`mktemp $base.XXXXXX` || exit 1 - -do_test() { - ealgo=$1 - keylen=$2 - expected_ealgo=$3 - expected_keylen=$4 - - geli init -B none -e $ealgo -l $keylen -P -K $keyfile ${md} 2>/dev/null - geli attach -p -k $keyfile ${md} - real_ealgo=`geli list ${md}.eli | awk '/EncryptionAlgorithm/ {print $2}'` - real_keylen=`geli list ${md}.eli | awk '/KeyLength/ {print $2}'` - - if [ ${real_ealgo} = ${expected_ealgo} ]; then - echo "ok $i - ${ealgo} aliased to ${real_ealgo}" - else - echo "not ok $i - expected ${expected_ealgo} but got ${real_ealgo}" - fi - i=$((i+1)) - - if [ ${real_keylen} = ${expected_keylen} ]; then - echo "ok $i - keylen=${keylen} for ealgo=${ealgo} aliases to ${real_keylen}" - else - echo "not ok $i - expected ${expected_keylen} but got ${real_keylen}" - fi - i=$((i+1)) - - geli detach ${md} -} - -echo "1..38" -i=1 -md=$(attach_md -t malloc -s 1024k) -dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1 - -for spec in aes:0:AES-XTS:128 aes:128:AES-XTS:128 aes:256:AES-XTS:256 \ - 3des:0:3DES-CBC:192 3des:192:3DES-CBC:192 \ - blowfish:0:Blowfish-CBC:128 blowfish:128:Blowfish-CBC:128 \ - blowfish:160:Blowfish-CBC:160 blowfish:192:Blowfish-CBC:192 \ - blowfish:224:Blowfish-CBC:224 blowfish:256:Blowfish-CBC:256 \ - blowfish:288:Blowfish-CBC:288 blowfish:352:Blowfish-CBC:352 \ - blowfish:384:Blowfish-CBC:384 blowfish:416:Blowfish-CBC:416 \ - blowfish:448:Blowfish-CBC:448 \ - camellia:0:CAMELLIA-CBC:128 camellia:128:CAMELLIA-CBC:128 \ - camellia:256:CAMELLIA-CBC:256 ; do - - ealgo=`echo $spec | cut -d : -f 1` - keylen=`echo $spec | cut -d : -f 2` - expected_ealgo=`echo $spec | cut -d : -f 3` - expected_keylen=`echo $spec | cut -d : -f 4` - - do_test $ealgo $keylen $expected_ealgo $expected_keylen -done - -rm -f $keyfile diff --git a/tests/sys/geom/class/eli/init_i_P_test.sh b/tests/sys/geom/class/eli/init_i_P_test.sh deleted file mode 100644 index e512c3f918eb..000000000000 --- a/tests/sys/geom/class/eli/init_i_P_test.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=100 -keyfile=`mktemp $base.XXXXXX` || exit 1 -md=$(attach_md -t malloc -s `expr $sectors + 1`) - -echo "1..1" - -dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1 - -geli init -B none -i 64 -P -K ${keyfile} ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 1" -else - echo "not ok 1" -fi - -rm -f $keyfile diff --git a/tests/sys/geom/class/eli/init_test.sh b/tests/sys/geom/class/eli/init_test.sh index fa6827975085..bf20e3185076 100644 --- a/tests/sys/geom/class/eli/init_test.sh +++ b/tests/sys/geom/class/eli/init_test.sh @@ -1,50 +1,368 @@ #!/bin/sh # $FreeBSD$ -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=32 -keyfile=`mktemp $base.XXXXXX` || exit 1 -rnd=`mktemp $base.XXXXXX` || exit 1 - -echo "1..200" - -do_test() { +init_test() +{ cipher=$1 secsize=$2 ealgo=${cipher%%:*} keylen=${cipher##*:} - geli init -B none -e $ealgo -l $keylen -P -K $keyfile -s $secsize ${md} 2>/dev/null - geli attach -p -k $keyfile ${md} + atf_check -s exit:0 -e ignore \ + geli init -B none -e $ealgo -l $keylen -P -K keyfile -s $secsize ${md} + atf_check geli attach -p -k keyfile ${md} secs=`diskinfo /dev/${md}.eli | awk '{print $4}'` - dd if=/dev/random of=${rnd} bs=${secsize} count=${secs} >/dev/null 2>&1 - dd if=${rnd} of=/dev/${md}.eli bs=${secsize} count=${secs} 2>/dev/null + atf_check dd if=/dev/random of=rnd bs=${secsize} count=${secs} status=none + atf_check dd if=rnd of=/dev/${md}.eli bs=${secsize} count=${secs} status=none - md_rnd=`dd if=${rnd} bs=${secsize} count=${secs} 2>/dev/null | md5` + md_rnd=`dd if=rnd bs=${secsize} count=${secs} status=none | md5` + atf_check_equal 0 $? md_ddev=`dd if=/dev/${md}.eli bs=${secsize} count=${secs} 2>/dev/null | md5` - md_edev=`dd if=/dev/${md} bs=${secsize} count=${secs} 2>/dev/null | md5` + atf_check_equal 0 $? + md_edev=`dd if=/dev/${md} bs=${secsize} count=${secs} status=none | md5` + atf_check_equal 0 $? - if [ ${md_rnd} = ${md_ddev} ]; then - echo "ok $i - ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - else - echo "not ok $i - ealgo=${ealgo} keylen=${keylen} sec=${secsize}" + if [ ${md_rnd} != ${md_ddev} ]; then + atf_fail "Miscompare for ealgo=${ealgo} keylen=${keylen} sec=${secsize}" fi - i=$((i+1)) - if [ ${md_rnd} != ${md_edev} ]; then - echo "ok $i - ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - else - echo "not ok $i - ealgo=${ealgo} keylen=${keylen} sec=${secsize}" + if [ ${md_rnd} == ${md_edev} ]; then + atf_fail "Data was not encrypted for ealgo=${ealgo} keylen=${keylen} sec=${secsize}" fi - i=$((i+1)) +} +atf_test_case init cleanup +init_head() +{ + atf_set "descr" "Basic I/O with geli" + atf_set "require.user" "root" + atf_set "timeout" 600 +} +init_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=32 + + atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + atf_check dd if=/dev/random of=rnd bs=8192 count=${sectors} status=none + for_each_geli_config_nointegrity init_test +} +init_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup } -i=1 -dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1 -for_each_geli_config_nointegrity do_test +atf_test_case init_B cleanup +init_B_head() +{ + atf_set "descr" "init -B can select an alternate backup metadata file" + atf_set "require.user" "root" +} +init_B_body() +{ + . $(atf_get_srcdir)/conf.sh -rm -f $rnd -rm -f $keyfile + sectors=100 + + atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + + md=$(attach_md -t malloc -s $sectors) + + # -B none + rm -f /var/backups/${md}.eli + atf_check -s exit:0 -o ignore geli init -B none -P -K keyfile ${md} + if [ -f /var/backups/${md}.eli ]; then + atf_fail "geli created a backup file even with -B none" + fi + + # no -B + rm -f /var/backups/${md}.eli + atf_check -s exit:0 -o ignore geli init -P -K keyfile ${md} + if [ ! -f /var/backups/${md}.eli ]; then + atf_fail "geli did not create a backup file" + fi + atf_check geli clear ${md} + atf_check -s not-exit:0 -e ignore geli attach -p -k keyfile ${md} + atf_check -s exit:0 -o ignore geli restore /var/backups/${md}.eli ${md} + atf_check -s exit:0 -o ignore geli attach -p -k keyfile ${md} + atf_check geli detach ${md} + rm -f /var/backups/${md}.eli + + # -B file + rm -f backupfile + atf_check -s exit:0 -o ignore \ + geli init -B backupfile -P -K keyfile ${md} + if [ ! -f backupfile ]; then + atf_fail "geli init -B did not create a backup file" + fi + atf_check geli clear ${md} + atf_check -s not-exit:0 -e ignore geli attach -p -k keyfile ${md} + atf_check geli restore backupfile ${md} + atf_check geli attach -p -k keyfile ${md} +} +init_B_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + +atf_test_case init_J cleanup +init_J_head() +{ + atf_set "descr" "init -J accepts a passfile" + atf_set "require.user" "root" +} +init_J_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=100 + md=$(attach_md -t malloc -s `expr $sectors + 1`) + + atf_check dd if=/dev/random of=keyfile0 bs=512 count=16 status=none + atf_check dd if=/dev/random of=keyfile1 bs=512 count=16 status=none + dd if=/dev/random bs=512 count=16 status=none | sha1 > passfile0 + atf_check_equal 0 $? + dd if=/dev/random bs=512 count=16 status=none | sha1 > passfile1 + atf_check_equal 0 $? + + for iter in -1 0 64; do + atf_check -s not-exit:0 -e ignore \ + geli init -i ${iter} -B none -J passfile0 -P ${md} + atf_check -s not-exit:0 -e ignore \ + geli init -i ${iter} -B none -J passfile0 -P -K keyfile0 ${md} + atf_check geli init -i ${iter} -B none -J passfile0 -K keyfile0 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k keyfile0 -p ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -j passfile0 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -j keyfile0 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k passfile0 -p ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -j keyfile0 -k passfile0 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -j keyfile0 -k keyfile0 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -j passfile0 -k passfile0 ${md} + atf_check -s exit:0 -e ignore \ + geli attach -j passfile0 -k keyfile0 ${md} + atf_check -s exit:0 -e ignore geli detach ${md} + atf_check -s exit:0 -e ignore -x \ + "cat keyfile0 | geli attach -j passfile0 -k - ${md}" + atf_check -s exit:0 -e ignore geli detach ${md} + atf_check -s exit:0 -e ignore -x \ + "cat passfile0 | geli attach -j - -k keyfile0 ${md}" + atf_check -s exit:0 -e ignore geli detach ${md} + + atf_check -s not-exit:0 -e ignore \ + geli init -i ${iter} -B none -J passfile0 -J passfile1 -P ${md} + atf_check -s not-exit:0 -e ignore \ + geli init -i ${iter} -B none -J passfile0 -J passfile1 -P -K keyfile0 -K keyfile1 ${md} + atf_check -s exit:0 -e ignore \ + geli init -i ${iter} -B none -J passfile0 -J passfile1 -K keyfile0 -K keyfile1 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k keyfile0 -p ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k keyfile1 -p ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -j passfile0 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -j passfile1 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k keyfile0 -k keyfile1 -p ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -j passfile0 -j passfile1 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k keyfile0 -j passfile0 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k keyfile0 -j passfile1 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k keyfile1 -j passfile0 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k keyfile1 -j passfile1 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k keyfile0 -j passfile0 -j passfile1 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k keyfile1 -j passfile0 -j passfile1 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k keyfile0 -k keyfile1 -j passfile0 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k keyfile0 -k keyfile1 -j passfile1 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k keyfile1 -k keyfile0 -j passfile0 -j passfile1 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k keyfile0 -k keyfile1 -j passfile1 -j passfile0 ${md} + atf_check -s not-exit:0 -e ignore \ + geli attach -k keyfile1 -k keyfile0 -j passfile1 -j passfile0 ${md} + atf_check -s exit:0 -e ignore \ + geli attach -j passfile0 -j passfile1 -k keyfile0 -k keyfile1 ${md} + atf_check -s exit:0 -e ignore geli detach ${md} + atf_check -s exit:0 -e ignore -x \ + "cat passfile0 | geli attach -j - -j passfile1 -k keyfile0 -k keyfile1 ${md}" + atf_check -s exit:0 -e ignore geli detach ${md} + atf_check -s exit:0 -e ignore -x \ + "cat passfile1 | geli attach -j passfile0 -j - -k keyfile0 -k keyfile1 ${md}" + atf_check -s exit:0 -e ignore geli detach ${md} + atf_check -s exit:0 -e ignore -x \ + "cat keyfile0 | geli attach -j passfile0 -j passfile1 -k - -k keyfile1 ${md}" + atf_check -s exit:0 -e ignore geli detach ${md} + atf_check -s exit:0 -e ignore -x \ + "cat keyfile1 | geli attach -j passfile0 -j passfile1 -k keyfile0 -k - ${md}" + atf_check -s exit:0 -e ignore geli detach ${md} + atf_check -s exit:0 -e ignore -x \ + "cat keyfile0 keyfile1 | geli attach -j passfile0 -j passfile1 -k - ${md}" + atf_check -s exit:0 -e ignore geli detach ${md} + atf_check -s exit:0 -e ignore -x \ + "cat passfile0 passfile1 | awk '{printf \"%s\", \$0}' | geli attach -j - -k keyfile0 -k keyfile1 ${md}" + atf_check -s exit:0 -e ignore geli detach ${md} + done +} +init_J_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + +init_a_test() +{ + cipher=$1 + aalgo=$2 + secsize=$3 + ealgo=${cipher%%:*} + keylen=${cipher##*:} + + atf_check -s exit:0 -e ignore geli init -B none -a $aalgo -e $ealgo -l $keylen -P -K keyfile -s $secsize ${md} + atf_check geli attach -p -k keyfile ${md} + + secs=`diskinfo /dev/${md}.eli | awk '{print $4}'` + + atf_check dd if=rnd of=/dev/${md}.eli bs=${secsize} count=${secs} status=none + + md_rnd=`dd if=rnd bs=${secsize} count=${secs} status=none | md5` + atf_check_equal 0 $? + md_ddev=`dd if=/dev/${md}.eli bs=${secsize} count=${secs} status=none | md5` + atf_check_equal 0 $? + + if [ ${md_rnd} != ${md_ddev} ]; then + atf_fail "Miscompare for aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" + fi +} +atf_test_case init_a cleanup +init_a_head() +{ + atf_set "descr" "I/O with geli and HMACs" + atf_set "require.user" "root" + atf_set "timeout" 3600 +} +init_a_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=100 + + atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + atf_check dd if=/dev/random of=rnd bs=8192 count=${sectors} status=none + for_each_geli_config init_a_test + true +} +init_a_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + +init_alias_test() { + ealgo=$1 + keylen=$2 + expected_ealgo=$3 + expected_keylen=$4 + + atf_check geli init -B none -e $ealgo -l $keylen -P -K keyfile ${md} + atf_check geli attach -p -k keyfile ${md} + real_ealgo=`geli list ${md}.eli | awk '/EncryptionAlgorithm/ {print $2}'` + real_keylen=`geli list ${md}.eli | awk '/KeyLength/ {print $2}'` + + if [ "${real_ealgo}" != "${expected_ealgo}" ]; then + atf_fail "expected ${expected_ealgo} but got ${real_ealgo}" + fi + + if [ "${real_keylen}" != "${expected_keylen}" ]; then + atf_fail "expected ${expected_keylen} but got ${real_keylen}" + fi + atf_check geli detach ${md} +} +atf_test_case init_alias cleanup +init_alias_head() +{ + atf_set "descr" "geli init accepts cipher aliases" + atf_set "require.user" "root" +} +init_alias_body() +{ + . $(atf_get_srcdir)/conf.sh + + md=$(attach_md -t malloc -s 1024k) + atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + + for spec in aes:0:AES-XTS:128 aes:128:AES-XTS:128 aes:256:AES-XTS:256 \ + 3des:0:3DES-CBC:192 3des:192:3DES-CBC:192 \ + blowfish:0:Blowfish-CBC:128 blowfish:128:Blowfish-CBC:128 \ + blowfish:160:Blowfish-CBC:160 blowfish:192:Blowfish-CBC:192 \ + blowfish:224:Blowfish-CBC:224 blowfish:256:Blowfish-CBC:256 \ + blowfish:288:Blowfish-CBC:288 blowfish:352:Blowfish-CBC:352 \ + blowfish:384:Blowfish-CBC:384 blowfish:416:Blowfish-CBC:416 \ + blowfish:448:Blowfish-CBC:448 \ + camellia:0:CAMELLIA-CBC:128 camellia:128:CAMELLIA-CBC:128 \ + camellia:256:CAMELLIA-CBC:256 ; do + + ealgo=`echo $spec | cut -d : -f 1` + keylen=`echo $spec | cut -d : -f 2` + expected_ealgo=`echo $spec | cut -d : -f 3` + expected_keylen=`echo $spec | cut -d : -f 4` + + init_alias_test $ealgo $keylen $expected_ealgo $expected_keylen + done +} +init_alias_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + +atf_test_case init_i_P cleanup +init_i_P_head() +{ + atf_set "descr" "geli: Options -i and -P are mutually exclusive" + atf_set "require.user" "root" +} +init_i_P_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=100 + md=$(attach_md -t malloc -s `expr $sectors + 1`) + + atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + + atf_check -s exit:1 -e "match:Options -i and -P are mutually exclusive"\ + geli init -B none -i 64 -P -K keyfile $md +} +init_i_P_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + +atf_init_test_cases() +{ + atf_add_test_case init + atf_add_test_case init_B + atf_add_test_case init_J + atf_add_test_case init_a + atf_add_test_case init_alias + atf_add_test_case init_i_P +} diff --git a/tests/sys/geom/class/eli/integrity_copy_test.sh b/tests/sys/geom/class/eli/integrity_copy_test.sh deleted file mode 100644 index 485db915f969..000000000000 --- a/tests/sys/geom/class/eli/integrity_copy_test.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=2 -keyfile=`mktemp $base.XXXXXX` || exit 1 -sector=`mktemp $base.XXXXXX` || exit 1 - -echo "1..2400" - -do_test() { - cipher=$1 - aalgo=$2 - secsize=$3 - ealgo=${cipher%%:*} - keylen=${cipher##*:} - - geli init -B none -a $aalgo -e $ealgo -l $keylen -P -K $keyfile -s $secsize ${md} 2>/dev/null - geli attach -p -k $keyfile ${md} - - dd if=/dev/random of=/dev/${md}.eli bs=${secsize} count=1 >/dev/null 2>&1 - - dd if=/dev/${md}.eli bs=${secsize} count=1 >/dev/null 2>&1 - if [ $? -eq 0 ]; then - echo "ok $i - small 1 aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - else - echo "not ok $i - small 1 aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - fi - i=$((i+1)) - - geli detach ${md} - # Copy first small sector to the second small sector. - # This should be detected as corruption. - dd if=/dev/${md} of=${sector} bs=512 count=1 >/dev/null 2>&1 - dd if=${sector} of=/dev/${md} bs=512 count=1 seek=1 >/dev/null 2>&1 - geli attach -p -k $keyfile ${md} - - dd if=/dev/${md}.eli of=/dev/null bs=${secsize} count=1 >/dev/null 2>&1 - if [ $? -ne 0 ]; then - echo "ok $i - small 2 aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - else - echo "not ok $i - small 2 aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - fi - i=$((i+1)) - - ms=`diskinfo /dev/${md} | awk '{print $3 - 512}'` - ns=`diskinfo /dev/${md}.eli | awk '{print $4}'` - usecsize=`echo "($ms / $ns) - (($ms / $ns) % 512)" | bc` - - # Fix the corruption - dd if=/dev/random of=/dev/${md}.eli bs=${secsize} count=2 >/dev/null 2>&1 - - dd if=/dev/${md}.eli bs=${secsize} count=2 >/dev/null 2>&1 - if [ $? -eq 0 ]; then - echo "ok $i - big 1 aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - else - echo "not ok $i - big 1 aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - fi - i=$((i+1)) - - geli detach ${md} - # Copy first big sector to the second big sector. - # This should be detected as corruption. - dd if=/dev/${md} of=${sector} bs=${usecsize} count=1 >/dev/null 2>&1 - dd if=${sector} of=/dev/${md} bs=${usecsize} count=1 seek=1 >/dev/null 2>&1 - geli attach -p -k $keyfile ${md} 2>/dev/null - if [ $? -ne 0 ]; then - echo "ok $i - big 2 aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - else - echo "not ok $i - big 2 aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - fi - i=$((i+1)) -} - - -i=1 -dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1 - -for_each_geli_config do_test - -rm -f $keyfile $sector diff --git a/tests/sys/geom/class/eli/integrity_data_test.sh b/tests/sys/geom/class/eli/integrity_data_test.sh deleted file mode 100644 index 43b3a404e3a6..000000000000 --- a/tests/sys/geom/class/eli/integrity_data_test.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=2 -keyfile=`mktemp $base.XXXXXX` || exit 1 -sector=`mktemp $base.XXXXXX` || exit 1 - -echo "1..600" - -do_test() { - cipher=$1 - aalgo=$2 - secsize=$3 - ealgo=${cipher%%:*} - keylen=${cipher##*:} - - geli init -B none -a $aalgo -e $ealgo -l $keylen -P -K $keyfile -s $secsize ${md} 2>/dev/null - - # Corrupt 8 bytes of data. - dd if=/dev/${md} of=${sector} bs=512 count=1 >/dev/null 2>&1 - dd if=/dev/random of=${sector} bs=1 count=8 seek=64 conv=notrunc >/dev/null 2>&1 - dd if=${sector} of=/dev/${md} bs=512 count=1 >/dev/null 2>&1 - geli attach -p -k $keyfile ${md} - - dd if=/dev/${md}.eli of=/dev/null bs=${secsize} count=1 >/dev/null 2>&1 - if [ $? -ne 0 ]; then - echo "ok $i - aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - else - echo "not ok $i - aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - fi - i=$((i+1)) -} - -i=1 -dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1 - -for_each_geli_config do_test - -rm -f $keyfile $sector diff --git a/tests/sys/geom/class/eli/integrity_hmac_test.sh b/tests/sys/geom/class/eli/integrity_hmac_test.sh deleted file mode 100644 index 284d080b684d..000000000000 --- a/tests/sys/geom/class/eli/integrity_hmac_test.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=2 -keyfile=`mktemp $base.XXXXXX` || exit 1 -sector=`mktemp $base.XXXXXX` || exit 1 - -echo "1..600" - -do_test() { - cipher=$1 - aalgo=$2 - secsize=$3 - ealgo=${cipher%%:*} - keylen=${cipher##*:} - - geli init -B none -a $aalgo -e $ealgo -l $keylen -P -K $keyfile -s $secsize ${md} 2>/dev/null - - # Corrupt 8 bytes of HMAC. - dd if=/dev/${md} of=${sector} bs=512 count=1 >/dev/null 2>&1 - dd if=/dev/random of=${sector} bs=1 count=16 conv=notrunc >/dev/null 2>&1 - dd if=${sector} of=/dev/${md} bs=512 count=1 >/dev/null 2>&1 - geli attach -p -k $keyfile ${md} - - dd if=/dev/${md}.eli bs=${secsize} count=1 >/dev/null 2>&1 - if [ $? -ne 0 ]; then - echo "ok $i - aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - else - echo "not ok $i - aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - fi - i=$((i+1)) -} - - -i=1 -dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1 - -for_each_geli_config do_test - -rm -f $keyfile $sector diff --git a/tests/sys/geom/class/eli/integrity_test.sh b/tests/sys/geom/class/eli/integrity_test.sh new file mode 100755 index 000000000000..22e5f2ce21d9 --- /dev/null +++ b/tests/sys/geom/class/eli/integrity_test.sh @@ -0,0 +1,160 @@ +# $FreeBSD$ + +copy_test() { + cipher=$1 + aalgo=$2 + secsize=$3 + ealgo=${cipher%%:*} + keylen=${cipher##*:} + + atf_check -s exit:0 -e ignore \ + geli init -B none -a $aalgo -e $ealgo -l $keylen -P \ + -K keyfile -s $secsize ${md} + atf_check geli attach -p -k keyfile ${md} + + atf_check dd if=/dev/random of=/dev/${md}.eli bs=${secsize} count=1 status=none + + atf_check geli detach ${md} + # Copy first small sector to the second small sector. + # This should be detected as corruption. + atf_check dd if=/dev/${md} of=sector bs=512 count=1 status=none + atf_check dd if=sector of=/dev/${md} bs=512 count=1 seek=1 status=none + atf_check geli attach -p -k keyfile ${md} + + atf_check -s not-exit:0 -e ignore \ + dd if=/dev/${md}.eli of=/dev/null bs=${secsize} count=1 + + # Fix the corruption + atf_check dd if=/dev/random of=/dev/${md}.eli bs=${secsize} count=2 status=none + atf_check dd if=/dev/${md}.eli of=/dev/null bs=${secsize} count=2 status=none + + # Copy first big sector to the second big sector. + # This should be detected as corruption. + ms=`diskinfo /dev/${md} | awk '{print $3 - 512}'` + ns=`diskinfo /dev/${md}.eli | awk '{print $4}'` + usecsize=`echo "($ms / $ns) - (($ms / $ns) % 512)" | bc` + atf_check geli detach ${md} + atf_check dd if=/dev/${md} bs=512 count=$(( ${usecsize} / 512 )) seek=$(( $secsize / 512 )) of=sector status=none + atf_check dd of=/dev/${md} bs=512 count=$(( ${usecsize} / 512 )) seek=$(( $secsize / 256 )) if=sector status=none + atf_check -s exit:0 -e ignore geli attach -p -k keyfile ${md} + atf_check -s not-exit:0 -e ignore \ + dd if=/dev/${md}.eli of=/dev/null bs=${secsize} count=$ns +} + +atf_test_case copy cleanup +copy_head() +{ + atf_set "descr" "geli will detect misdirected writes as corruption" + atf_set "require.user" "root" + atf_set "timeout" 3600 +} +copy_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=2 + + atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + for_each_geli_config copy_test +} +copy_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + + +data_test() { + cipher=$1 + aalgo=$2 + secsize=$3 + ealgo=${cipher%%:*} + keylen=${cipher##*:} + + atf_check -s exit:0 -e ignore \ + geli init -B none -a $aalgo -e $ealgo -l $keylen -P -K keyfile \ + -s $secsize ${md} + + # Corrupt 8 bytes of data. + atf_check dd if=/dev/${md} of=sector bs=512 count=1 status=none + atf_check dd if=/dev/random of=sector bs=1 count=8 seek=64 conv=notrunc status=none + atf_check dd if=sector of=/dev/${md} bs=512 count=1 status=none + atf_check geli attach -p -k keyfile ${md} + + # Try to read from the corrupt sector + atf_check -s not-exit:0 -e ignore \ + dd if=/dev/${md}.eli of=/dev/null bs=${secsize} count=1 +} + +atf_test_case data cleanup +data_head() +{ + atf_set "descr" "With HMACs, geli will detect data corruption" + atf_set "require.user" "root" + atf_set "timeout" 1800 +} +data_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=2 + + atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + for_each_geli_config data_test +} +data_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + +hmac_test() { + cipher=$1 + aalgo=$2 + secsize=$3 + ealgo=${cipher%%:*} + keylen=${cipher##*:} + + atf_check -s exit:0 -e ignore \ + geli init -B none -a $aalgo -e $ealgo -l $keylen -P -K keyfile \ + -s $secsize ${md} + + # Corrupt 8 bytes of HMAC. + atf_check dd if=/dev/${md} of=sector bs=512 count=1 status=none + atf_check dd if=/dev/random of=sector bs=1 count=16 conv=notrunc status=none + atf_check dd if=sector of=/dev/${md} bs=512 count=1 status=none + atf_check geli attach -p -k keyfile ${md} + + # Try to read from the corrupt sector + atf_check -s not-exit:0 -e ignore \ + dd if=/dev/${md}.eli of=/dev/null bs=${secsize} count=1 +} + +atf_test_case hmac cleanup +hmac_head() +{ + atf_set "descr" "geli will detect corruption of HMACs" + atf_set "require.user" "root" + atf_set "timeout" 1800 +} +hmac_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=2 + + atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + for_each_geli_config hmac_test +} +hmac_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + +atf_init_test_cases() +{ + atf_add_test_case copy + atf_add_test_case data + atf_add_test_case hmac +} diff --git a/tests/sys/geom/class/eli/kill_test.sh b/tests/sys/geom/class/eli/kill_test.sh index 241f2ce73e39..336629a7a0ab 100644 --- a/tests/sys/geom/class/eli/kill_test.sh +++ b/tests/sys/geom/class/eli/kill_test.sh @@ -1,97 +1,71 @@ -#!/bin/sh # $FreeBSD$ -. $(dirname $0)/conf.sh +atf_test_case kill cleanup +kill_head() +{ + atf_set "descr" "geli kill will wipe a provider's metadata" + atf_set "require.user" "root" +} +kill_body() +{ + . $(atf_get_srcdir)/conf.sh -base=`basename $0` -sectors=100 -keyfile1=`mktemp $base.XXXXXX` || exit 1 -keyfile2=`mktemp $base.XXXXXX` || exit 1 -md=$(attach_md -t malloc -s `expr $sectors + 1`) + sectors=100 + md=$(attach_md -t malloc -s `expr $sectors + 1`) -echo "1..9" + atf_check dd if=/dev/random of=keyfile1 bs=512 count=16 status=none + atf_check dd if=/dev/random of=keyfile2 bs=512 count=16 status=none -dd if=/dev/random of=${keyfile1} bs=512 count=16 >/dev/null 2>&1 -dd if=/dev/random of=${keyfile2} bs=512 count=16 >/dev/null 2>&1 + atf_check geli init -B none -P -K keyfile1 ${md} + atf_check geli attach -p -k keyfile1 ${md} + atf_check -s exit:0 -o ignore geli setkey -n 1 -P -K keyfile2 ${md} -geli init -B none -P -K $keyfile1 ${md} -geli attach -p -k $keyfile1 ${md} -geli setkey -n 1 -P -K $keyfile2 ${md} + # Kill attached provider. + atf_check geli kill ${md} + sleep 1 + # Provider should be automatically detached. + if [ -c /dev/${md}.eli ]; then + atf_fail "Provider did not detach when killed" + fi -# Kill attached provider. -geli kill ${md} -if [ $? -eq 0 ]; then - echo "ok 1" -else - echo "not ok 1" -fi -sleep 1 -# Provider should be automatically detached. -if [ ! -c /dev/${md}.eli ]; then - echo "ok 2" -else - echo "not ok 2" -fi + # We cannot use keyfile1 anymore. + atf_check -s not-exit:0 -e match:"Cannot read metadata" \ + geli attach -p -k keyfile1 ${md} -# We cannot use keyfile1 anymore. -geli attach -p -k $keyfile1 ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 3" -else - echo "not ok 3" -fi + # We cannot use keyfile2 anymore. + atf_check -s not-exit:0 -e match:"Cannot read metadata" \ + geli attach -p -k keyfile2 ${md} -# We cannot use keyfile2 anymore. -geli attach -p -k $keyfile2 ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 4" -else - echo "not ok 4" -fi + atf_check geli init -B none -P -K keyfile1 ${md} + atf_check -s exit:0 -o ignore \ + geli setkey -n 1 -p -k keyfile1 -P -K keyfile2 ${md} -geli init -B none -P -K $keyfile1 ${md} -geli setkey -n 1 -p -k $keyfile1 -P -K $keyfile2 ${md} + # Should be possible to attach with keyfile1. + atf_check geli attach -p -k keyfile1 ${md} + atf_check geli detach ${md} -# Should be possible to attach with keyfile1. -geli attach -p -k $keyfile1 ${md} -if [ $? -eq 0 ]; then - echo "ok 5" -else - echo "not ok 5" -fi -geli detach ${md} + # Should be possible to attach with keyfile2. + atf_check geli attach -p -k keyfile2 ${md} + atf_check geli detach ${md} -# Should be possible to attach with keyfile2. -geli attach -p -k $keyfile2 ${md} -if [ $? -eq 0 ]; then - echo "ok 6" -else - echo "not ok 6" -fi -geli detach ${md} + # Kill detached provider. + atf_check geli kill ${md} -# Kill detached provider. -geli kill ${md} -if [ $? -eq 0 ]; then - echo "ok 7" -else - echo "not ok 7" -fi + # We cannot use keyfile1 anymore. + atf_check -s not-exit:0 -e match:"Cannot read metadata" \ + geli attach -p -k keyfile1 ${md} -# We cannot use keyfile1 anymore. -geli attach -p -k $keyfile1 ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 8" -else - echo "not ok 8" -fi + # We cannot use keyfile2 anymore. + atf_check -s not-exit:0 -e match:"Cannot read metadata" \ + geli attach -p -k keyfile2 ${md} +} +kill_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} -# We cannot use keyfile2 anymore. -geli attach -p -k $keyfile2 ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 9" -else - echo "not ok 9" -fi - -rm -f $keyfile1 $keyfile2 +atf_init_test_cases() +{ + atf_add_test_case kill +} diff --git a/tests/sys/geom/class/eli/onetime_a_test.sh b/tests/sys/geom/class/eli/onetime_a_test.sh deleted file mode 100644 index 1398bd53b685..000000000000 --- a/tests/sys/geom/class/eli/onetime_a_test.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=8 -rnd=`mktemp $base.XXXXXX` || exit 1 - -echo "1..600" - -do_test() { - cipher=$1 - aalgo=$2 - secsize=$3 - ealgo=${cipher%%:*} - keylen=${cipher##*:} - - geli onetime -a $aalgo -e $ealgo -l $keylen -s $secsize ${md} 2>/dev/null - - secs=`diskinfo /dev/${md}.eli | awk '{print $4}'` - - dd if=${rnd} of=/dev/${md}.eli bs=${secsize} count=${secs} 2>/dev/null - - md_rnd=`dd if=${rnd} bs=${secsize} count=${secs} 2>/dev/null | md5` - md_ddev=`dd if=/dev/${md}.eli bs=${secsize} count=${secs} 2>/dev/null | md5` - - if [ ${md_rnd} = ${md_ddev} ]; then - echo "ok $i - aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - else - echo "not ok $i - aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - fi - i=$((i+1)) -} - -i=1 -dd if=/dev/random of=${rnd} bs=1024 count=1024 >/dev/null 2>&1 - -for_each_geli_config do_test - -rm -f $rnd diff --git a/tests/sys/geom/class/eli/onetime_d_test.sh b/tests/sys/geom/class/eli/onetime_d_test.sh deleted file mode 100644 index c39ac8f9726f..000000000000 --- a/tests/sys/geom/class/eli/onetime_d_test.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=100 -md=$(attach_md -t malloc -s $sectors) - -echo "1..3" - -geli onetime -d ${md} -if [ -c /dev/${md}.eli ]; then - echo "ok 1" -else - echo "not ok 1" -fi -# Be sure it doesn't detach on read. -dd if=/dev/${md}.eli of=/dev/null 2>/dev/null -sleep 1 -if [ -c /dev/${md}.eli ]; then - echo "ok 2" -else - echo "not ok 2" -fi -true > /dev/${md}.eli -sleep 1 -if [ ! -c /dev/${md}.eli ]; then - echo "ok 3" -else - echo "not ok 3" -fi - -mdconfig -d -u ${md} diff --git a/tests/sys/geom/class/eli/onetime_test.sh b/tests/sys/geom/class/eli/onetime_test.sh index 524df2c7a604..ad921bd6c80f 100644 --- a/tests/sys/geom/class/eli/onetime_test.sh +++ b/tests/sys/geom/class/eli/onetime_test.sh @@ -1,47 +1,140 @@ -#!/bin/sh # $FreeBSD$ -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=100 - -echo "1..200" - -do_test() { +onetime_test() +{ cipher=$1 secsize=$2 ealgo=${cipher%%:*} keylen=${cipher##*:} - rnd=`mktemp $base.XXXXXX` || exit 1 - - geli onetime -e $ealgo -l $keylen -s $secsize ${md} 2>/dev/null + atf_check -s exit:0 -o ignore -e ignore \ + geli onetime -e $ealgo -l $keylen -s $secsize ${md} secs=`diskinfo /dev/${md}.eli | awk '{print $4}'` - dd if=/dev/random of=${rnd} bs=${secsize} count=${secs} >/dev/null 2>&1 - dd if=${rnd} of=/dev/${md}.eli bs=${secsize} count=${secs} 2>/dev/null + atf_check dd if=/dev/random of=rnd bs=${secsize} count=${secs} status=none + atf_check dd if=rnd of=/dev/${md}.eli bs=${secsize} count=${secs} status=none - md_rnd=`dd if=${rnd} bs=${secsize} count=${secs} 2>/dev/null | md5` - md_ddev=`dd if=/dev/${md}.eli bs=${secsize} count=${secs} 2>/dev/null | md5` - md_edev=`dd if=/dev/${md} bs=${secsize} count=${secs} 2>/dev/null | md5` + md_rnd=`dd if=rnd bs=${secsize} count=${secs} status=none | md5` + atf_check_equal 0 $? + md_ddev=`dd if=/dev/${md}.eli bs=${secsize} count=${secs} status=none | md5` + atf_check_equal 0 $? + md_edev=`dd if=/dev/${md} bs=${secsize} count=${secs} status=none | md5` + atf_check_equal 0 $? - if [ ${md_rnd} = ${md_ddev} ]; then - echo "ok $i - ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - else - echo "not ok $i - ealgo=${ealgo} keylen=${keylen} sec=${secsize}" + if [ ${md_rnd} != ${md_ddev} ]; then + atf_fail "geli did not return the original data" fi - i=$((i+1)) - if [ ${md_rnd} != ${md_edev} ]; then - echo "ok $i - ealgo=${ealgo} keylen=${keylen} sec=${secsize}" - else - echo "not ok $i - ealgo=${ealgo} keylen=${keylen} sec=${secsize}" + if [ ${md_rnd} == ${md_edev} ]; then + atf_fail "geli did not encrypt the data" fi - i=$((i+1)) +} +atf_test_case onetime cleanup +onetime_head() +{ + atf_set "descr" "geli onetime can create temporary providers" + atf_set "require.user" "root" + atf_set "timeout" 1800 +} +onetime_body() +{ + . $(atf_get_srcdir)/conf.sh + sectors=100 - rm -f $rnd + for_each_geli_config_nointegrity onetime_test +} +onetime_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup } -i=1 -for_each_geli_config_nointegrity do_test +onetime_a_test() +{ + cipher=$1 + aalgo=$2 + secsize=$3 + ealgo=${cipher%%:*} + keylen=${cipher##*:} + + atf_check -s exit:0 -o ignore -e ignore \ + geli onetime -a $aalgo -e $ealgo -l $keylen -s $secsize ${md} + + secs=`diskinfo /dev/${md}.eli | awk '{print $4}'` + + atf_check dd if=rnd of=/dev/${md}.eli bs=${secsize} count=${secs} status=none + + md_rnd=`dd if=rnd bs=${secsize} count=${secs} status=none | md5` + atf_check_equal 0 $? + md_ddev=`dd if=/dev/${md}.eli bs=${secsize} count=${secs} status=none | md5` + atf_check_equal 0 $? + + if [ ${md_rnd} != ${md_ddev} ]; then + atf_fail "Miscompare for aalgo=${aalgo} ealgo=${ealgo} keylen=${keylen} sec=${secsize}" + fi +} +atf_test_case onetime_a cleanup +onetime_a_head() +{ + atf_set "descr" "geli onetime with HMACs" + atf_set "require.user" "root" + atf_set "timeout" 1800 +} +onetime_a_body() +{ + . $(atf_get_srcdir)/conf.sh + sectors=8 + + atf_check dd if=/dev/random of=rnd bs=1024 count=1024 status=none + for_each_geli_config onetime_a_test +} +onetime_a_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + +atf_test_case onetime_d cleanup +onetime_d_head() +{ + atf_set "descr" "geli onetime -d will create providers that detach on last close" + atf_set "require.user" "root" +} +onetime_d_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=100 + md=$(attach_md -t malloc -s $sectors) + + atf_check geli onetime -d ${md} + if [ ! -c /dev/${md}.eli ]; then + atf_fail "Provider not created, or immediately detached" + fi + + # Be sure it doesn't detach on read. + atf_check dd if=/dev/${md}.eli of=/dev/null status=none + sleep 1 + if [ ! -c /dev/${md}.eli ]; then + atf_fail "Provider detached when a reader closed" + fi + + # It should detach when a writer closes + true > /dev/${md}.eli + sleep 1 + if [ -c /dev/${md}.eli ]; then + atf_fail "Provider didn't detach on last close of a writer" + fi +} +onetime_d_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + +atf_init_test_cases() +{ + atf_add_test_case onetime + atf_add_test_case onetime_a + atf_add_test_case onetime_d +} diff --git a/tests/sys/geom/class/eli/resize_test.sh b/tests/sys/geom/class/eli/resize_test.sh index e5bec1a45ce7..21406a495892 100644 --- a/tests/sys/geom/class/eli/resize_test.sh +++ b/tests/sys/geom/class/eli/resize_test.sh @@ -1,145 +1,88 @@ #!/bin/sh # $FreeBSD$ -. $(dirname $0)/conf.sh - -echo 1..27 - -BLK=512 -BLKS_PER_MB=2048 - -md=$(attach_md -t malloc -s40m) -i=1 - -fsck_md() +atf_test_case resize cleanup +resize_head() { - local is_clean + atf_set "descr" "geli resize will resize a geli provider" + atf_set "require.user" "root" +} +resize_body() +{ + . $(atf_get_srcdir)/conf.sh + BLK=512 + BLKS_PER_MB=2048 - out=$(fsck_ffs -Ffy ${md}a.eli) - if [ $? -eq 0 -o $? -eq 7 ]; then - echo "ok $i - fsck says ${md}a.eli is clean" - else - echo "not ok $i - fsck says ${md}a.eli is dirty" + md=$(attach_md -t malloc -s40m) + + # Initialise + atf_check -s exit:0 -o ignore gpart create -s BSD ${md} + atf_check -s exit:0 -o ignore gpart add -t freebsd-ufs -s 10m ${md} + + echo secret >tmp.key + atf_check geli init -Bnone -PKtmp.key ${md}a + atf_check geli attach -pk tmp.key ${md}a + + atf_check -s exit:0 -o ignore newfs -U ${md}a.eli + atf_check -s exit:7 -o ignore fsck_ffs -Ffy ${md}a.eli + + # Doing a backup, resize & restore must be forced (with -f) as geli + # verifies that the provider size in the metadata matches the consumer. + + atf_check geli backup ${md}a tmp.meta + atf_check geli detach ${md}a.eli + atf_check -s exit:0 -o match:resized gpart resize -i1 -s 20m ${md} + atf_check -s not-exit:0 -e ignore geli attach -pktmp.key ${md}a + atf_check -s not-exit:0 -e ignore geli restore tmp.meta ${md}a + atf_check geli restore -f tmp.meta ${md}a + atf_check geli attach -pktmp.key ${md}a + atf_check -s exit:0 -o ignore growfs -y ${md}a.eli + atf_check -s exit:7 -o ignore fsck_ffs -Ffy ${md}a.eli + + # Now do the resize properly + + atf_check geli detach ${md}a.eli + atf_check -s exit:0 -o match:resized gpart resize -i1 -s 30m ${md} + atf_check geli resize -s20m ${md}a + atf_check -s not-exit:0 -e match:"Inconsistent provider.*metadata" \ + geli resize -s20m ${md}a + atf_check geli attach -pktmp.key ${md}a + atf_check -s exit:0 -o ignore growfs -y ${md}a.eli + atf_check -s exit:7 -o ignore fsck_ffs -Ffy ${md}a.eli + + atf_check geli detach ${md}a.eli + atf_check -s exit:0 -o ignore gpart destroy -F $md + + + # Verify that the man page example works, changing ada0 to $md, + # 1g to 20m, 2g to 30m and keyfile to tmp.key, and adding -B none + # to geli init. + + atf_check -s exit:0 -o ignore gpart create -s GPT $md + atf_check -s exit:0 -o ignore gpart add -s 20m -t freebsd-ufs -i 1 $md + atf_check geli init -B none -K tmp.key -P ${md}p1 + atf_check -s exit:0 -o match:resized gpart resize -s 30m -i 1 $md + atf_check geli resize -s 20m ${md}p1 + atf_check geli attach -k tmp.key -p ${md}p1 +} +resize_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + + if [ -f "$TEST_MDS_FILE" ]; then + while read md; do + [ -c /dev/${md}a.eli ] && \ + geli detach ${md}a.eli 2>/dev/null + [ -c /dev/${md}p1.eli ] && \ + geli detach ${md}p1.eli + [ -c /dev/${md}.eli ] && \ + geli detach ${md}.eli 2>/dev/null + mdconfig -d -u $md 2>/dev/null + done < $TEST_MDS_FILE fi - i=$((i + 1)) } -setsize() { - partszMB=$1 - - gpart resize -i 1 -s ${partszMB}m ${md} +atf_init_test_cases() +{ + atf_add_test_case resize } - -# Initialise - -gpart create -s BSD ${md} -gpart add -t freebsd-ufs -s 10m ${md} -setsize 10 || echo -n "not " -echo ok $i - "Sized ${md}a to 10m" -i=$((i + 1)) - -echo secret >tmp.key -geli init -Bnone -PKtmp.key ${md}a || echo -n "not " -echo ok $i - "Initialised geli on ${md}a" -i=$((i + 1)) -geli attach -pk tmp.key ${md}a || echo -n "not " -echo ok $i - "Attached ${md}a as ${md}a.eli" -i=$((i + 1)) - -newfs -U ${md}a.eli >/dev/null || echo -n "not " -echo ok $i - "Initialised the filesystem on ${md}a.eli" -i=$((i + 1)) -fsck_md - -# Doing a backup, resize & restore must be forced (with -f) as geli -# verifies that the provider size in the metadata matches the consumer. - -geli backup ${md}a tmp.meta || echo -n "not " -echo ok $i - "Backed up ${md}a metadata" -i=$((i + 1)) - -geli detach ${md}a.eli || echo -n "not " -echo ok $i - "Detached ${md}a.eli" -i=$((i + 1)) - -setsize 20 || echo -n "not " -echo ok $i - "Sized ${md}a to 20m" -i=$((i + 1)) -geli attach -pktmp.key ${md}a && echo -n "not " -echo ok $i - "Attaching ${md}a fails after resizing the consumer" -i=$((i + 1)) - -geli restore tmp.meta ${md}a && echo -n "not " -echo ok $i - "Restoring metadata on ${md}a.eli fails without -f" -i=$((i + 1)) -geli restore -f tmp.meta ${md}a || echo -n "not " -echo ok $i - "Restoring metadata on ${md}a.eli can be forced" -i=$((i + 1)) - -geli attach -pktmp.key ${md}a || echo -n "not " -echo ok $i - "Attaching ${md}a is now possible" -i=$((i + 1)) - -growfs -y ${md}a.eli >/dev/null || echo -n "not " -echo ok $i - "Extended the filesystem on ${md}a.eli" -i=$((i + 1)) - -fsck_md - -# Now do the resize properly - -geli detach ${md}a.eli || echo -n "not " -echo ok $i - "Detached ${md}a.eli" -i=$((i + 1)) - -setsize 30 || echo -n "not " -echo ok $i - "Sized ${md}a to 30m" -i=$((i + 1)) - -geli resize -s20m ${md}a || echo -n "not " -echo ok $i - "Resizing works ok" -i=$((i + 1)) -geli resize -s20m ${md}a && echo -n "not " -echo ok $i - "Resizing doesn't work a 2nd time (no old metadata)" -i=$((i + 1)) - -geli attach -pktmp.key ${md}a || echo -n "not " -echo ok $i - "Attaching ${md}a works ok" -i=$((i + 1)) - -growfs -y ${md}a.eli >/dev/null || echo -n "not " -echo ok $i - "Extended the filesystem on ${md}a.eli" -i=$((i + 1)) - -fsck_md - -geli detach ${md}a.eli -gpart destroy -F $md >/dev/null - - -# Verify that the man page example works, changing ada0 to $md, -# 1g to 20m, 2g to 30m and keyfile to tmp.key, and adding -B none -# to geli init. - -gpart create -s GPT $md || echo -n "not " -echo ok $i - "Installed a GPT on ${md}" -i=$((i + 1)) -gpart add -s 20m -t freebsd-ufs -i 1 $md || echo -n "not " -echo ok $i - "Added a 20m partition in slot 1" -i=$((i + 1)) -geli init -B none -K tmp.key -P ${md}p1 || echo -n "not " -echo ok $i - "Initialised geli on ${md}p1" -i=$((i + 1)) -gpart resize -s 30m -i 1 $md || echo -n "not " -echo ok $i - "Resized partition ${md}p1 to 30m" -i=$((i + 1)) -geli resize -s 20m ${md}p1 || echo -n "not " -echo ok $i - "Resized geli on ${md}p1 to 30m" -i=$((i + 1)) -geli attach -k tmp.key -p ${md}p1 || echo -n "not " -echo ok $i - "Attached ${md}p1.eli" -i=$((i + 1)) - -geli detach ${md}p1.eli - -rm tmp.* diff --git a/tests/sys/geom/class/eli/setkey_test.sh b/tests/sys/geom/class/eli/setkey_test.sh index 087524d292b7..7829f41f1efd 100644 --- a/tests/sys/geom/class/eli/setkey_test.sh +++ b/tests/sys/geom/class/eli/setkey_test.sh @@ -1,156 +1,98 @@ #!/bin/sh # $FreeBSD$ -. $(dirname $0)/conf.sh +atf_test_case setkey cleanup +setkey_head() +{ + atf_set "descr" "geli setkey can change the key for an existing provider" + atf_set "require.user" "root" +} +setkey_body() +{ + . $(atf_get_srcdir)/conf.sh -base=`basename $0` -sectors=100 -rnd=`mktemp $base.XXXXXX` || exit 1 -keyfile1=`mktemp $base.XXXXXX` || exit 1 -keyfile2=`mktemp $base.XXXXXX` || exit 1 -keyfile3=`mktemp $base.XXXXXX` || exit 1 -keyfile4=`mktemp $base.XXXXXX` || exit 1 -keyfile5=`mktemp $base.XXXXXX` || exit 1 -md=$(attach_md -t malloc -s `expr $sectors + 1`) + sectors=100 + md=$(attach_md -t malloc -s `expr $sectors + 1`) -echo "1..16" + atf_check dd if=/dev/random of=rnd bs=512 count=${sectors} status=none + hash1=`dd if=rnd bs=512 count=${sectors} status=none | md5` + atf_check_equal 0 $? + atf_check dd if=/dev/random of=keyfile1 bs=512 count=16 status=none + atf_check dd if=/dev/random of=keyfile2 bs=512 count=16 status=none + atf_check dd if=/dev/random of=keyfile3 bs=512 count=16 status=none + atf_check dd if=/dev/random of=keyfile4 bs=512 count=16 status=none + atf_check dd if=/dev/random of=keyfile5 bs=512 count=16 status=none -dd if=/dev/random of=${rnd} bs=512 count=${sectors} >/dev/null 2>&1 -hash1=`dd if=${rnd} bs=512 count=${sectors} 2>/dev/null | md5` -dd if=/dev/random of=${keyfile1} bs=512 count=16 >/dev/null 2>&1 -dd if=/dev/random of=${keyfile2} bs=512 count=16 >/dev/null 2>&1 -dd if=/dev/random of=${keyfile3} bs=512 count=16 >/dev/null 2>&1 -dd if=/dev/random of=${keyfile4} bs=512 count=16 >/dev/null 2>&1 -dd if=/dev/random of=${keyfile5} bs=512 count=16 >/dev/null 2>&1 + atf_check geli init -B none -P -K keyfile1 ${md} + atf_check geli attach -p -k keyfile1 ${md} -geli init -B none -P -K $keyfile1 ${md} -geli attach -p -k $keyfile1 ${md} + atf_check \ + dd if=rnd of=/dev/${md}.eli bs=512 count=${sectors} status=none + hash2=`dd if=/dev/${md}.eli bs=512 count=${sectors} 2>/dev/null | md5` + atf_check_equal 0 $? -dd if=${rnd} of=/dev/${md}.eli bs=512 count=${sectors} 2>/dev/null -rm -f $rnd -hash2=`dd if=/dev/${md}.eli bs=512 count=${sectors} 2>/dev/null | md5` + # Change current key (0) for attached provider. + atf_check -s exit:0 -o ignore geli setkey -P -K keyfile2 ${md} + atf_check geli detach ${md} -# Change current key (0) for attached provider. -geli setkey -P -K $keyfile2 ${md} -if [ $? -eq 0 ]; then - echo "ok 1" -else - echo "not ok 1" -fi -geli detach ${md} + # We cannot use keyfile1 anymore. + atf_check -s not-exit:0 -e match:"Wrong key" \ + geli attach -p -k keyfile1 ${md} -# We cannot use keyfile1 anymore. -geli attach -p -k $keyfile1 ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 2" -else - echo "not ok 2" -fi + # Attach with new key. + atf_check geli attach -p -k keyfile2 ${md} + hash3=`dd if=/dev/${md}.eli bs=512 count=${sectors} 2>/dev/null | md5` + atf_check_equal 0 $? -# Attach with new key. -geli attach -p -k $keyfile2 ${md} -if [ $? -eq 0 ]; then - echo "ok 3" -else - echo "not ok 3" -fi -hash3=`dd if=/dev/${md}.eli bs=512 count=${sectors} 2>/dev/null | md5` + # Change key 1 for attached provider. + atf_check -s exit:0 -o ignore geli setkey -n 1 -P -K keyfile3 ${md} + atf_check geli detach ${md} -# Change key 1 for attached provider. -geli setkey -n 1 -P -K $keyfile3 ${md} -if [ $? -eq 0 ]; then - echo "ok 4" -else - echo "not ok 4" -fi -geli detach ${md} + # Attach with key 1. + atf_check geli attach -p -k keyfile3 ${md} + hash4=`dd if=/dev/${md}.eli bs=512 count=${sectors} 2>/dev/null | md5` + atf_check_equal 0 $? + atf_check geli detach ${md} -# Attach with key 1. -geli attach -p -k $keyfile3 ${md} -if [ $? -eq 0 ]; then - echo "ok 5" -else - echo "not ok 5" -fi -hash4=`dd if=/dev/${md}.eli bs=512 count=${sectors} 2>/dev/null | md5` -geli detach ${md} + # Change current (1) key for detached provider. + atf_check -s exit:0 -o ignore geli setkey -p -k keyfile3 -P -K keyfile4 ${md} -# Change current (1) key for detached provider. -geli setkey -p -k $keyfile3 -P -K $keyfile4 ${md} -if [ $? -eq 0 ]; then - echo "ok 6" -else - echo "not ok 6" -fi + # We cannot use keyfile3 anymore. + atf_check -s not-exit:0 -e match:"Wrong key" \ + geli attach -p -k keyfile3 ${md} -# We cannot use keyfile3 anymore. -geli attach -p -k $keyfile3 ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 7" -else - echo "not ok 7" -fi + # Attach with key 1. + atf_check geli attach -p -k keyfile4 ${md} + hash5=`dd if=/dev/${md}.eli bs=512 count=${sectors} 2>/dev/null | md5` + atf_check_equal 0 $? + atf_check geli detach ${md} -# Attach with key 1. -geli attach -p -k $keyfile4 ${md} -if [ $? -eq 0 ]; then - echo "ok 8" -else - echo "not ok 8" -fi -hash5=`dd if=/dev/${md}.eli bs=512 count=${sectors} 2>/dev/null | md5` -geli detach ${md} + # Change key 0 for detached provider. + atf_check -s exit:0 -o ignore geli setkey -n 0 -p -k keyfile4 -P -K keyfile5 ${md} -# Change key 0 for detached provider. -geli setkey -n 0 -p -k $keyfile4 -P -K $keyfile5 ${md} -if [ $? -eq 0 ]; then - echo "ok 9" -else - echo "not ok 9" -fi + # We cannot use keyfile2 anymore. + atf_check -s not-exit:0 -e match:"Wrong key" \ + geli attach -p -k keyfile2 ${md} 2>/dev/null -# We cannot use keyfile2 anymore. -geli attach -p -k $keyfile2 ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 10" -else - echo "not ok 10" -fi + # Attach with key 0. + atf_check geli attach -p -k keyfile5 ${md} + hash6=`dd if=/dev/${md}.eli bs=512 count=${sectors} 2>/dev/null | md5` + atf_check_equal 0 $? + atf_check geli detach ${md} -# Attach with key 0. -geli attach -p -k $keyfile5 ${md} -if [ $? -eq 0 ]; then - echo "ok 11" -else - echo "not ok 11" -fi -hash6=`dd if=/dev/${md}.eli bs=512 count=${sectors} 2>/dev/null | md5` -geli detach ${md} + atf_check_equal ${hash1} ${hash2} + atf_check_equal ${hash1} ${hash3} + atf_check_equal ${hash1} ${hash4} + atf_check_equal ${hash1} ${hash5} + atf_check_equal ${hash1} ${hash6} +} +setkey_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} -if [ ${hash1} = ${hash2} ]; then - echo "ok 12" -else - echo "not ok 12" -fi -if [ ${hash1} = ${hash3} ]; then - echo "ok 13" -else - echo "not ok 13" -fi -if [ ${hash1} = ${hash4} ]; then - echo "ok 14" -else - echo "not ok 14" -fi -if [ ${hash1} = ${hash5} ]; then - echo "ok 15" -else - echo "not ok 15" -fi -if [ ${hash1} = ${hash6} ]; then - echo "ok 16" -else - echo "not ok 16" -fi - -rm -f $keyfile1 $keyfile2 $keyfile3 $keyfile4 $keyfile5 +atf_init_test_cases() +{ + atf_add_test_case setkey +} From ea9e0e28e0a03f31ac5343c12a317e178e602af1 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 7 Jan 2018 02:19:54 +0000 Subject: [PATCH 004/158] Fix bogus pass for syscon_generic introduced in r327621 ian@ pointed out that BUS_PASS_DEFAULT + $anything is bogus, given that BUS_PASS_DEFAULT is defined as __INT_MAX. Instead, we take a page out of imx6_usbphy's book and use BUS_PASS_DEFAULT - 1000 to achieve the desired effect of syscon_generic attaching before if_awg and other potential consumers, but late enough that more specialized implementations should have no problem attaching instead. Reported by: ian --- sys/dev/extres/syscon/syscon_generic.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sys/dev/extres/syscon/syscon_generic.c b/sys/dev/extres/syscon/syscon_generic.c index f0b6b27a04bf..db7bade12f04 100644 --- a/sys/dev/extres/syscon/syscon_generic.c +++ b/sys/dev/extres/syscon/syscon_generic.c @@ -206,6 +206,11 @@ static device_method_t syscon_generic_dmethods[] = { DEFINE_CLASS_0(syscon_generic, syscon_generic_driver, syscon_generic_dmethods, sizeof(struct syscon_generic_softc)); static devclass_t syscon_generic_devclass; +/* + * syscon_generic needs to attach before other devices that may require it, such + * as if_awg, but later than others to give way for more specialized syscon + * implementations. + */ EARLY_DRIVER_MODULE(syscon_generic, simplebus, syscon_generic_driver, - syscon_generic_devclass, 0, 0, BUS_PASS_DEFAULT + BUS_PASS_ORDER_FIRST); + syscon_generic_devclass, 0, 0, BUS_PASS_DEFAULT - 1000); MODULE_VERSION(syscon_generic, 1); From 5dce212d6777e3a624b4bf766cdac67810c57105 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sun, 7 Jan 2018 02:30:08 +0000 Subject: [PATCH 005/158] geli: fix parallel execution of tests The trick is not to destroy an md(4) device during a test. That can create a "double-free" situation, because we also destroy md devices during test cleanup. MFC after: 2 weeks --- tests/sys/geom/class/eli/conf.sh | 24 ++++++++-------- tests/sys/geom/class/eli/init_test.sh | 35 ++++++++++++------------ tests/sys/geom/class/eli/onetime_test.sh | 21 ++++++-------- 3 files changed, 38 insertions(+), 42 deletions(-) diff --git a/tests/sys/geom/class/eli/conf.sh b/tests/sys/geom/class/eli/conf.sh index da2ca9e4d277..d1dde228afad 100644 --- a/tests/sys/geom/class/eli/conf.sh +++ b/tests/sys/geom/class/eli/conf.sh @@ -4,6 +4,7 @@ class="eli" base=$(atf_get ident) [ -z "$base" ] && base=`basename $0` # for TAP compatibility +MAX_SECSIZE=8192 TEST_MDS_FILE=md.devs attach_md() @@ -21,6 +22,11 @@ attach_md() for_each_geli_config() { func=$1 + # Double the sector size to allow for the HMACs' storage space. + osecsize=$(( $MAX_SECSIZE * 2 )) + # geli needs 512B for the label. + bytes=`expr $osecsize \* $sectors + 512`b + md=$(attach_md -t malloc -s $bytes) for cipher in aes-xts:128 aes-xts:256 \ aes-cbc:128 aes-cbc:192 aes-cbc:256 \ 3des-cbc:192 \ @@ -33,16 +39,9 @@ for_each_geli_config() { keylen=${cipher##*:} for aalgo in hmac/md5 hmac/sha1 hmac/ripemd160 hmac/sha256 \ hmac/sha384 hmac/sha512; do - for secsize in 512 1024 2048 4096 8192; do - # Double the requested sector size to allow - # for the HMACs' storage space. - osecsize=$(( $secsize * 2 )) - # geli needs 512B for the label. - bytes=`expr $osecsize \* $sectors + 512`b - md=$(attach_md -t malloc -s $bytes) + for secsize in 512 1024 2048 4096 $MAX_SECSIZE; do ${func} $cipher $aalgo $secsize geli detach ${md} 2>/dev/null - mdconfig -d -u ${md} 2>/dev/null done done done @@ -54,6 +53,9 @@ for_each_geli_config() { for_each_geli_config_nointegrity() { func=$1 + # geli needs 512B for the label. + bytes=`expr $MAX_SECSIZE \* $sectors + 512`b + md=$(attach_md -t malloc -s $bytes) for cipher in aes-xts:128 aes-xts:256 \ aes-cbc:128 aes-cbc:192 aes-cbc:256 \ 3des-cbc:192 \ @@ -64,13 +66,9 @@ for_each_geli_config_nointegrity() { camellia-cbc:128 camellia-cbc:192 camellia-cbc:256; do ealgo=${cipher%%:*} keylen=${cipher##*:} - for secsize in 512 1024 2048 4096 8192; do - # geli needs 512B for the label. - bytes=`expr $secsize \* $sectors + 512`b - md=$(attach_md -t malloc -s $bytes) + for secsize in 512 1024 2048 4096 $MAX_SECSIZE; do ${func} $cipher $secsize geli detach ${md} 2>/dev/null - mdconfig -d -u ${md} 2>/dev/null done done } diff --git a/tests/sys/geom/class/eli/init_test.sh b/tests/sys/geom/class/eli/init_test.sh index bf20e3185076..52935cca2ea7 100644 --- a/tests/sys/geom/class/eli/init_test.sh +++ b/tests/sys/geom/class/eli/init_test.sh @@ -9,19 +9,18 @@ init_test() keylen=${cipher##*:} atf_check -s exit:0 -e ignore \ - geli init -B none -e $ealgo -l $keylen -P -K keyfile -s $secsize ${md} + geli init -B none -e $ealgo -l $keylen -P -K keyfile + -s $secsize ${md} atf_check geli attach -p -k keyfile ${md} - secs=`diskinfo /dev/${md}.eli | awk '{print $4}'` + atf_check dd if=rnd of=/dev/${md}.eli bs=${secsize} count=${sectors} \ + status=none - atf_check dd if=/dev/random of=rnd bs=${secsize} count=${secs} status=none - atf_check dd if=rnd of=/dev/${md}.eli bs=${secsize} count=${secs} status=none - - md_rnd=`dd if=rnd bs=${secsize} count=${secs} status=none | md5` + md_rnd=`dd if=rnd bs=${secsize} count=${sectors} status=none | md5` atf_check_equal 0 $? - md_ddev=`dd if=/dev/${md}.eli bs=${secsize} count=${secs} 2>/dev/null | md5` + md_ddev=`dd if=/dev/${md}.eli bs=${secsize} count=${sectors} status=none | md5` atf_check_equal 0 $? - md_edev=`dd if=/dev/${md} bs=${secsize} count=${secs} status=none | md5` + md_edev=`dd if=/dev/${md} bs=${secsize} count=${sectors} status=none | md5` atf_check_equal 0 $? if [ ${md_rnd} != ${md_ddev} ]; then @@ -45,7 +44,8 @@ init_body() sectors=32 atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none - atf_check dd if=/dev/random of=rnd bs=8192 count=${sectors} status=none + atf_check dd if=/dev/random of=rnd bs=$MAX_SECSIZE count=${sectors} \ + status=none for_each_geli_config_nointegrity init_test } init_cleanup() @@ -235,16 +235,16 @@ init_a_test() ealgo=${cipher%%:*} keylen=${cipher##*:} - atf_check -s exit:0 -e ignore geli init -B none -a $aalgo -e $ealgo -l $keylen -P -K keyfile -s $secsize ${md} + atf_check -s exit:0 -e ignore \ + geli init -B none -a $aalgo -e $ealgo -l $keylen -P -K keyfile \ + -s $secsize ${md} atf_check geli attach -p -k keyfile ${md} - secs=`diskinfo /dev/${md}.eli | awk '{print $4}'` + atf_check dd if=rnd of=/dev/${md}.eli bs=${secsize} count=${sectors} status=none - atf_check dd if=rnd of=/dev/${md}.eli bs=${secsize} count=${secs} status=none - - md_rnd=`dd if=rnd bs=${secsize} count=${secs} status=none | md5` + md_rnd=`dd if=rnd bs=${secsize} count=${sectors} status=none | md5` atf_check_equal 0 $? - md_ddev=`dd if=/dev/${md}.eli bs=${secsize} count=${secs} status=none | md5` + md_ddev=`dd if=/dev/${md}.eli bs=${secsize} count=${sectors} status=none | md5` atf_check_equal 0 $? if [ ${md_rnd} != ${md_ddev} ]; then @@ -265,7 +265,8 @@ init_a_body() sectors=100 atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none - atf_check dd if=/dev/random of=rnd bs=8192 count=${sectors} status=none + atf_check dd if=/dev/random of=rnd bs=$MAX_SECSIZE count=${sectors} \ + status=none for_each_geli_config init_a_test true } @@ -348,7 +349,7 @@ init_i_P_body() atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none - atf_check -s exit:1 -e "match:Options -i and -P are mutually exclusive"\ + atf_check -s not-exit:0 -e "match:Options -i and -P are mutually exclusive"\ geli init -B none -i 64 -P -K keyfile $md } init_i_P_cleanup() diff --git a/tests/sys/geom/class/eli/onetime_test.sh b/tests/sys/geom/class/eli/onetime_test.sh index ad921bd6c80f..e37875850984 100644 --- a/tests/sys/geom/class/eli/onetime_test.sh +++ b/tests/sys/geom/class/eli/onetime_test.sh @@ -10,16 +10,14 @@ onetime_test() atf_check -s exit:0 -o ignore -e ignore \ geli onetime -e $ealgo -l $keylen -s $secsize ${md} - secs=`diskinfo /dev/${md}.eli | awk '{print $4}'` + atf_check dd if=/dev/random of=rnd bs=${secsize} count=${sectors} status=none + atf_check dd if=rnd of=/dev/${md}.eli bs=${secsize} count=${sectors} status=none - atf_check dd if=/dev/random of=rnd bs=${secsize} count=${secs} status=none - atf_check dd if=rnd of=/dev/${md}.eli bs=${secsize} count=${secs} status=none - - md_rnd=`dd if=rnd bs=${secsize} count=${secs} status=none | md5` + md_rnd=`dd if=rnd bs=${secsize} count=${sectors} status=none | md5` atf_check_equal 0 $? - md_ddev=`dd if=/dev/${md}.eli bs=${secsize} count=${secs} status=none | md5` + md_ddev=`dd if=/dev/${md}.eli bs=${secsize} count=${sectors} status=none | md5` atf_check_equal 0 $? - md_edev=`dd if=/dev/${md} bs=${secsize} count=${secs} status=none | md5` + md_edev=`dd if=/dev/${md} bs=${secsize} count=${sectors} status=none | md5` atf_check_equal 0 $? if [ ${md_rnd} != ${md_ddev} ]; then @@ -41,6 +39,7 @@ onetime_body() . $(atf_get_srcdir)/conf.sh sectors=100 + dd if=/dev/random of=rnd bs=${MAX_SECSIZE} count=${sectors} status=none for_each_geli_config_nointegrity onetime_test } onetime_cleanup() @@ -60,13 +59,11 @@ onetime_a_test() atf_check -s exit:0 -o ignore -e ignore \ geli onetime -a $aalgo -e $ealgo -l $keylen -s $secsize ${md} - secs=`diskinfo /dev/${md}.eli | awk '{print $4}'` + atf_check dd if=rnd of=/dev/${md}.eli bs=${secsize} count=${sectors} status=none - atf_check dd if=rnd of=/dev/${md}.eli bs=${secsize} count=${secs} status=none - - md_rnd=`dd if=rnd bs=${secsize} count=${secs} status=none | md5` + md_rnd=`dd if=rnd bs=${secsize} count=${sectors} status=none | md5` atf_check_equal 0 $? - md_ddev=`dd if=/dev/${md}.eli bs=${secsize} count=${secs} status=none | md5` + md_ddev=`dd if=/dev/${md}.eli bs=${secsize} count=${sectors} status=none | md5` atf_check_equal 0 $? if [ ${md_rnd} != ${md_ddev} ]; then From 86c6868161803323de7c25bdf9749efd2f5e2dfc Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 7 Jan 2018 03:31:55 +0000 Subject: [PATCH 006/158] aw_sid: Add method for reading keys via prctl registers Technically supported on the later SoCs, this will only really be used to add support for the H3 sid. The H3 has a silicon bug that manifests itself by returning garbled rootkeys unless first read via the prctl registers. --- sys/arm/allwinner/aw_sid.c | 48 +++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/sys/arm/allwinner/aw_sid.c b/sys/arm/allwinner/aw_sid.c index ecc12567bb19..6bae8e6d55a7 100644 --- a/sys/arm/allwinner/aw_sid.c +++ b/sys/arm/allwinner/aw_sid.c @@ -39,6 +39,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include #include @@ -48,6 +50,16 @@ __FBSDID("$FreeBSD$"); #include +/* efuse registers */ +#define SID_PRCTL 0x40 +#define SID_PRCTL_OFFSET_MASK 0xff +#define SID_PRCTL_OFFSET(n) (((n) & SID_PRCTL_OFFSET_MASK) << 16) +#define SID_PRCTL_LOCK (0xac << 8) +#define SID_PRCTL_READ (0x01 << 1) +#define SID_PRCTL_WRITE (0x01 << 0) +#define SID_PRKEY 0x50 +#define SID_RDKEY 0x60 + #define SID_SRAM 0x200 #define SID_THERMAL_CALIB0 (SID_SRAM + 0x34) #define SID_THERMAL_CALIB1 (SID_SRAM + 0x38) @@ -56,6 +68,7 @@ __FBSDID("$FreeBSD$"); struct aw_sid_conf { bus_size_t rootkey_offset; + bool has_prctl; bool has_thermal; }; @@ -69,11 +82,13 @@ static const struct aw_sid_conf a20_conf = { static const struct aw_sid_conf a64_conf = { .rootkey_offset = SID_SRAM, + .has_prctl = true, .has_thermal = true, }; static const struct aw_sid_conf a83t_conf = { .rootkey_offset = SID_SRAM, + .has_prctl = true, .has_thermal = true, }; @@ -88,6 +103,7 @@ static struct ofw_compat_data compat_data[] = { struct aw_sid_softc { struct resource *res; struct aw_sid_conf *sid_conf; + struct mtx prctl_mtx; }; static struct aw_sid_softc *aw_sid_sc; @@ -105,6 +121,35 @@ enum sid_keys { #define WR4(sc, reg, val) bus_write_4((sc)->res, (reg), (val)) static int aw_sid_sysctl(SYSCTL_HANDLER_ARGS); +static int aw_sid_prctl_read(device_t dev, bus_size_t offset, uint32_t *val); + + +/* + * offset here is offset into efuse space, rather than offset into sid register + * space. This form of read is only an option for newer SoC: A83t, H3, A64 + */ +static int +aw_sid_prctl_read(device_t dev, bus_size_t offset, uint32_t *val) +{ + struct aw_sid_softc *sc; + uint32_t readval; + + sc = device_get_softc(dev); + if (!sc->sid_conf->has_prctl) + return (1); + + mtx_lock(&sc->prctl_mtx); + readval = SID_PRCTL_OFFSET(offset) | SID_PRCTL_LOCK | SID_PRCTL_READ; + WR4(sc, SID_PRCTL, readval); + /* Read bit will be cleared once read has concluded */ + while (RD4(sc, SID_PRCTL) & SID_PRCTL_READ) + continue; + readval = RD4(sc, SID_RDKEY); + mtx_unlock(&sc->prctl_mtx); + *val = readval; + + return (0); +} static int aw_sid_probe(device_t dev) @@ -131,8 +176,9 @@ aw_sid_attach(device_t dev) return (ENXIO); } - aw_sid_sc = sc; + mtx_init(&sc->prctl_mtx, device_get_nameunit(dev), NULL, MTX_DEF); sc->sid_conf = (struct aw_sid_conf *)ofw_bus_search_compatible(dev, compat_data)->ocd_data; + aw_sid_sc = sc; SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), From 92e80162f313aacdbbc13aef233b5d4a6df41c5e Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 7 Jan 2018 04:59:28 +0000 Subject: [PATCH 007/158] aw_sid(4): Add support for Allwinner H3 The sid controller on the H3 is generally identical in location, size, and efuse offset to the a64 and the a83t. The main difference is that the H3 has a silicon bug that sometimes causes the rootkey (at least) to be garbled unless first read by the prctl registers. This device is currently not in our DTS and, as of now, is not yet present in mainline Linux DTS. Tested on: OrangePi One --- share/man/man4/aw_sid.4 | 4 +++- sys/arm/allwinner/aw_sid.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/share/man/man4/aw_sid.4 b/share/man/man4/aw_sid.4 index 1ac6c62fcc65..7a55f4168f2f 100644 --- a/share/man/man4/aw_sid.4 +++ b/share/man/man4/aw_sid.4 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 2, 2018 +.Dd January 6, 2018 .Dt AW_SID 4 .Os .Sh NAME @@ -52,6 +52,8 @@ allwinner,sun7i-a20-sid allwinner,sun50i-a64-sid .It allwinner,sun8i-a83t-sid +.It +allwinner,sun8i-h3-sid .El .Sh SYSCTL VARIABLES The following read-only variables are available via diff --git a/sys/arm/allwinner/aw_sid.c b/sys/arm/allwinner/aw_sid.c index 6bae8e6d55a7..8943818f525a 100644 --- a/sys/arm/allwinner/aw_sid.c +++ b/sys/arm/allwinner/aw_sid.c @@ -67,36 +67,51 @@ __FBSDID("$FreeBSD$"); #define ROOT_KEY_SIZE 4 struct aw_sid_conf { + bus_size_t efuse_size; bus_size_t rootkey_offset; bool has_prctl; bool has_thermal; + bool requires_prctl_read; }; static const struct aw_sid_conf a10_conf = { + .efuse_size = 0x10, .rootkey_offset = 0, }; static const struct aw_sid_conf a20_conf = { + .efuse_size = 0x10, .rootkey_offset = 0, }; static const struct aw_sid_conf a64_conf = { + .efuse_size = 0x100, .rootkey_offset = SID_SRAM, .has_prctl = true, .has_thermal = true, }; static const struct aw_sid_conf a83t_conf = { + .efuse_size = 0x100, .rootkey_offset = SID_SRAM, .has_prctl = true, .has_thermal = true, }; +static const struct aw_sid_conf h3_conf = { + .efuse_size = 0x100, + .rootkey_offset = SID_SRAM, + .has_prctl = true, + .has_thermal = true, + .requires_prctl_read = true, +}; + static struct ofw_compat_data compat_data[] = { { "allwinner,sun4i-a10-sid", (uintptr_t)&a10_conf}, { "allwinner,sun7i-a20-sid", (uintptr_t)&a20_conf}, { "allwinner,sun50i-a64-sid", (uintptr_t)&a64_conf}, { "allwinner,sun8i-a83t-sid", (uintptr_t)&a83t_conf}, + { "allwinner,sun8i-h3-sid", (uintptr_t)&h3_conf}, { NULL, 0 } }; @@ -168,6 +183,8 @@ static int aw_sid_attach(device_t dev) { struct aw_sid_softc *sc; + bus_size_t i; + uint32_t val; sc = device_get_softc(dev); @@ -180,6 +197,19 @@ aw_sid_attach(device_t dev) sc->sid_conf = (struct aw_sid_conf *)ofw_bus_search_compatible(dev, compat_data)->ocd_data; aw_sid_sc = sc; + /* + * This set of reads is solely for working around a silicon bug on some + * SoC that require a prctl read in order for direct register access to + * return a non-garbled value. Hence, the values we read are simply + * ignored. + */ + if (sc->sid_conf->requires_prctl_read) + for (i = 0; i < sc->sid_conf->efuse_size; i += 4) + if (aw_sid_prctl_read(dev, i, &val) != 0) { + device_printf(dev, "failed prctl read\n"); + return (ENXIO); + } + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "rootkey", From f0c0c1daec03042f19ecfa279a390dfbe4943f0c Mon Sep 17 00:00:00 2001 From: Eitan Adler Date: Sun, 7 Jan 2018 05:38:53 +0000 Subject: [PATCH 008/158] ldconfig(8): clarify language for files The previous language did not make it clear that 'Files' are the files specified above. Clarify it. Reported by: dana Reviewed by: dana MFC After: 1 week --- sbin/ldconfig/ldconfig.8 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sbin/ldconfig/ldconfig.8 b/sbin/ldconfig/ldconfig.8 index f2fc324b8cfc..d4b985ba0f24 100644 --- a/sbin/ldconfig/ldconfig.8 +++ b/sbin/ldconfig/ldconfig.8 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 19, 2013 +.Dd January 6, 2018 .Dt LDCONFIG 8 .Os .Sh NAME @@ -58,7 +58,9 @@ the overhead that would otherwise result from the directory search operations the dynamic linker would have to perform to load the required shared libraries. .Pp -Files named on the command line are expected to contain directories +Alternatively, +.Ar files +may be specified; these are expected to contain directories to scan for shared libraries. Each directory's pathname must start on a new line. From 6d5343e38efa425175296a6899ee416dd8f78baa Mon Sep 17 00:00:00 2001 From: Xin LI Date: Sun, 7 Jan 2018 07:08:59 +0000 Subject: [PATCH 009/158] stddef.h is not used by cat.c, remove the include. --- bin/cat/cat.c | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/cat/cat.c b/bin/cat/cat.c index b69adbdcd7f5..817ab6df8707 100644 --- a/bin/cat/cat.c +++ b/bin/cat/cat.c @@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include From fd91e076c1993671a8b2e8839196b96d17f9dd16 Mon Sep 17 00:00:00 2001 From: Kristof Provost Date: Sun, 7 Jan 2018 13:21:01 +0000 Subject: [PATCH 010/158] Introduce mallocarray() in the kernel Similar to calloc() the mallocarray() function checks for integer overflows before allocating memory. It does not zero memory, unless the M_ZERO flag is set. Reviewed by: pfg, vangyzen (previous version), imp (previous version) Obtained from: OpenBSD Differential Revision: https://reviews.freebsd.org/D13766 --- share/man/man9/malloc.9 | 19 +++++++++++++++++++ sys/kern/kern_malloc.c | 17 +++++++++++++++++ sys/sys/malloc.h | 3 +++ 3 files changed, 39 insertions(+) diff --git a/share/man/man9/malloc.9 b/share/man/man9/malloc.9 index 81d40dcf444e..674cd30dbb24 100644 --- a/share/man/man9/malloc.9 +++ b/share/man/man9/malloc.9 @@ -45,6 +45,8 @@ .In sys/malloc.h .Ft void * .Fn malloc "unsigned long size" "struct malloc_type *type" "int flags" +.Ft void * +.Fn mallocarray "size_t nmemb" "size_t size" "struct malloc_type *type" "int flags" .Ft void .Fn free "void *addr" "struct malloc_type *type" .Ft void * @@ -64,6 +66,14 @@ object whose size is specified by .Fa size . .Pp The +.Fn mallocarray +function allocates uninitialized memory in kernel address space for an +array of +.Fa nmemb +entries whose size is specified by +.Fa size . +.Pp +The .Fn free function releases memory at address .Fa addr @@ -152,6 +162,15 @@ functions cannot return if .Dv M_WAITOK is specified. +The +.Fn mallocarray +function can return +.Dv NULL +if the multiplication of +.Fa nmemb +and +.Fa size +would cause an integer overflow. .It Dv M_USE_RESERVE Indicates that the system can use its reserve of memory to satisfy the request. diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c index 3aa8d1a4f45d..94be535a71c9 100644 --- a/sys/kern/kern_malloc.c +++ b/sys/kern/kern_malloc.c @@ -4,6 +4,7 @@ * Copyright (c) 1987, 1991, 1993 * The Regents of the University of California. * Copyright (c) 2005-2009 Robert N. M. Watson + * Copyright (c) 2008 Otto Moerbeek (mallocarray) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -534,6 +535,22 @@ malloc(unsigned long size, struct malloc_type *mtp, int flags) return ((void *) va); } +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 8 / 2)) +void * +mallocarray(size_t nmemb, size_t size, struct malloc_type *type, int flags) +{ + + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) + return (NULL); + + return (malloc(size * nmemb, type, flags)); +} + /* * free: * diff --git a/sys/sys/malloc.h b/sys/sys/malloc.h index e2e8100d8ae5..a5c2d4be7223 100644 --- a/sys/sys/malloc.h +++ b/sys/sys/malloc.h @@ -177,6 +177,9 @@ void *contigmalloc(unsigned long size, struct malloc_type *type, int flags, void free(void *addr, struct malloc_type *type); void *malloc(unsigned long size, struct malloc_type *type, int flags) __malloc_like __result_use_check __alloc_size(1); +void *mallocarray(size_t nmemb, size_t size, struct malloc_type *type, + int flags) __malloc_like __result_use_check + __alloc_size(1) __alloc_size(2); void malloc_init(void *); int malloc_last_fail(void); void malloc_type_allocated(struct malloc_type *type, unsigned long size); From 6273ba66f26debbfe26f1424f2f44631ad709ecc Mon Sep 17 00:00:00 2001 From: Kristof Provost Date: Sun, 7 Jan 2018 13:35:15 +0000 Subject: [PATCH 011/158] pf: Avoid integer overflow issues by using mallocarray() iso. malloc() pfioctl() handles several ioctl that takes variable length input, these include: - DIOCRADDTABLES - DIOCRDELTABLES - DIOCRGETTABLES - DIOCRGETTSTATS - DIOCRCLRTSTATS - DIOCRSETTFLAGS All of them take a pfioc_table struct as input from userland. One of its elements (pfrio_size) is used in a buffer length calculation. The calculation contains an integer overflow which if triggered can lead to out of bound reads and writes later on. Reported by: Ilja Van Sprundel --- sys/netpfil/pf/pf_ioctl.c | 126 ++++++++++++++++++++++++++++++++------ 1 file changed, 108 insertions(+), 18 deletions(-) diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index 4a6fc0cd0de1..12b2ff6d2820 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -2531,7 +2531,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = io->pfrio_size * sizeof(struct pfr_table); - pfrts = malloc(totlen, M_TEMP, M_WAITOK); + pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table), + M_TEMP, M_WAITOK); + if (! pfrts) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfrts, totlen); if (error) { free(pfrts, M_TEMP); @@ -2555,7 +2560,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = io->pfrio_size * sizeof(struct pfr_table); - pfrts = malloc(totlen, M_TEMP, M_WAITOK); + pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table), + M_TEMP, M_WAITOK); + if (! pfrts) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfrts, totlen); if (error) { free(pfrts, M_TEMP); @@ -2579,7 +2589,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = io->pfrio_size * sizeof(struct pfr_table); - pfrts = malloc(totlen, M_TEMP, M_WAITOK); + pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table), + M_TEMP, M_WAITOK); + if (! pfrts) { + error = ENOMEM; + break; + } PF_RULES_RLOCK(); error = pfr_get_tables(&io->pfrio_table, pfrts, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); @@ -2600,7 +2615,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = io->pfrio_size * sizeof(struct pfr_tstats); - pfrtstats = malloc(totlen, M_TEMP, M_WAITOK); + pfrtstats = mallocarray(io->pfrio_size, + sizeof(struct pfr_tstats), M_TEMP, M_WAITOK); + if (! pfrtstats) { + error = ENOMEM; + break; + } PF_RULES_WLOCK(); error = pfr_get_tstats(&io->pfrio_table, pfrtstats, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); @@ -2621,7 +2641,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = io->pfrio_size * sizeof(struct pfr_table); - pfrts = malloc(totlen, M_TEMP, M_WAITOK); + pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table), + M_TEMP, M_WAITOK); + if (! pfrts) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfrts, totlen); if (error) { free(pfrts, M_TEMP); @@ -2645,7 +2670,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = io->pfrio_size * sizeof(struct pfr_table); - pfrts = malloc(totlen, M_TEMP, M_WAITOK); + pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table), + M_TEMP, M_WAITOK); + if (! pfrts) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfrts, totlen); if (error) { free(pfrts, M_TEMP); @@ -2684,7 +2714,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = io->pfrio_size * sizeof(struct pfr_addr); - pfras = malloc(totlen, M_TEMP, M_WAITOK); + pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), + M_TEMP, M_WAITOK); + if (! pfras) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); @@ -2711,7 +2746,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = io->pfrio_size * sizeof(struct pfr_addr); - pfras = malloc(totlen, M_TEMP, M_WAITOK); + pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), + M_TEMP, M_WAITOK); + if (! pfras) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); @@ -2739,7 +2779,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td } count = max(io->pfrio_size, io->pfrio_size2); totlen = count * sizeof(struct pfr_addr); - pfras = malloc(totlen, M_TEMP, M_WAITOK); + pfras = mallocarray(count, sizeof(struct pfr_addr), M_TEMP, + M_WAITOK); + if (! pfras) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); @@ -2767,7 +2812,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = io->pfrio_size * sizeof(struct pfr_addr); - pfras = malloc(totlen, M_TEMP, M_WAITOK); + pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), + M_TEMP, M_WAITOK); + if (! pfras) { + error = ENOMEM; + break; + } PF_RULES_RLOCK(); error = pfr_get_addrs(&io->pfrio_table, pfras, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); @@ -2788,7 +2838,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = io->pfrio_size * sizeof(struct pfr_astats); - pfrastats = malloc(totlen, M_TEMP, M_WAITOK); + pfrastats = mallocarray(io->pfrio_size, + sizeof(struct pfr_astats), M_TEMP, M_WAITOK); + if (! pfrastats) { + error = ENOMEM; + break; + } PF_RULES_RLOCK(); error = pfr_get_astats(&io->pfrio_table, pfrastats, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); @@ -2809,7 +2864,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = io->pfrio_size * sizeof(struct pfr_addr); - pfras = malloc(totlen, M_TEMP, M_WAITOK); + pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), + M_TEMP, M_WAITOK); + if (! pfras) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); @@ -2836,7 +2896,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = io->pfrio_size * sizeof(struct pfr_addr); - pfras = malloc(totlen, M_TEMP, M_WAITOK); + pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), + M_TEMP, M_WAITOK); + if (! pfras) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); @@ -2863,7 +2928,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = io->pfrio_size * sizeof(struct pfr_addr); - pfras = malloc(totlen, M_TEMP, M_WAITOK); + pfras = mallocarray(io->pfrio_size, sizeof(struct pfr_addr), + M_TEMP, M_WAITOK); + if (! pfras) { + error = ENOMEM; + break; + } error = copyin(io->pfrio_buffer, pfras, totlen); if (error) { free(pfras, M_TEMP); @@ -2905,7 +2975,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = sizeof(struct pfioc_trans_e) * io->size; - ioes = malloc(totlen, M_TEMP, M_WAITOK); + ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e), + M_TEMP, M_WAITOK); + if (! ioes) { + error = ENOMEM; + break; + } error = copyin(io->array, ioes, totlen); if (error) { free(ioes, M_TEMP); @@ -2971,7 +3046,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = sizeof(struct pfioc_trans_e) * io->size; - ioes = malloc(totlen, M_TEMP, M_WAITOK); + ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e), + M_TEMP, M_WAITOK); + if (! ioes) { + error = ENOMEM; + break; + } error = copyin(io->array, ioes, totlen); if (error) { free(ioes, M_TEMP); @@ -3037,7 +3117,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } totlen = sizeof(struct pfioc_trans_e) * io->size; - ioes = malloc(totlen, M_TEMP, M_WAITOK); + ioes = mallocarray(io->size, sizeof(struct pfioc_trans_e), + M_TEMP, M_WAITOK); + if (! ioes) { + error = ENOMEM; + break; + } error = copyin(io->array, ioes, totlen); if (error) { free(ioes, M_TEMP); @@ -3238,7 +3323,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td } bufsiz = io->pfiio_size * sizeof(struct pfi_kif); - ifstore = malloc(bufsiz, M_TEMP, M_WAITOK); + ifstore = mallocarray(io->pfiio_size, sizeof(struct pfi_kif), + M_TEMP, M_WAITOK); + if (! ifstore) { + error = ENOMEM; + break; + } PF_RULES_RLOCK(); pfi_get_ifaces(io->pfiio_name, ifstore, &io->pfiio_size); PF_RULES_RUNLOCK(); From e70c77ca171ebd95270003131f27304f2b57ffb4 Mon Sep 17 00:00:00 2001 From: Kristof Provost Date: Sun, 7 Jan 2018 13:39:12 +0000 Subject: [PATCH 012/158] linuxkpi: Implement kcalloc() based on mallocarray() This means we now get integer overflow protection, which Linux code might expect as it is also provided by kcalloc() in Linux. --- sys/compat/linuxkpi/common/include/linux/slab.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sys/compat/linuxkpi/common/include/linux/slab.h b/sys/compat/linuxkpi/common/include/linux/slab.h index 541441df25d8..1f8ec82db985 100644 --- a/sys/compat/linuxkpi/common/include/linux/slab.h +++ b/sys/compat/linuxkpi/common/include/linux/slab.h @@ -46,7 +46,6 @@ MALLOC_DECLARE(M_KMALLOC); #define kzalloc(size, flags) kmalloc(size, (flags) | __GFP_ZERO) #define kzalloc_node(size, flags, node) kmalloc(size, (flags) | __GFP_ZERO) #define kfree_const(ptr) kfree(ptr) -#define kcalloc(n, size, flags) kmalloc((n) * (size), (flags) | __GFP_ZERO) #define vzalloc(size) __vmalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, 0) #define vfree(arg) kfree(arg) #define kvfree(arg) kfree(arg) @@ -100,6 +99,13 @@ kmalloc(size_t size, gfp_t flags) return (malloc(size, M_KMALLOC, linux_check_m_flags(flags))); } +static inline void * +kcalloc(size_t n, size_t size, gfp_t flags) +{ + flags |= __GFP_ZERO; + return (mallocarray(n, size, M_KMALLOC, linux_check_m_flags(flags))); +} + static inline void * __vmalloc(size_t size, gfp_t flags, int other) { From 5cf32a6e95e62625ca5ea6b5564c371276956210 Mon Sep 17 00:00:00 2001 From: Kristof Provost Date: Sun, 7 Jan 2018 13:41:06 +0000 Subject: [PATCH 013/158] vchiq: Use mallocarray() to provide kcalloc() This means we now also provide integer overflow protection, like the Linux kcalloc(). --- sys/contrib/vchiq/interface/compat/vchi_bsd.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/contrib/vchiq/interface/compat/vchi_bsd.h b/sys/contrib/vchiq/interface/compat/vchi_bsd.h index 107041ac37b9..a02bca452756 100644 --- a/sys/contrib/vchiq/interface/compat/vchi_bsd.h +++ b/sys/contrib/vchiq/interface/compat/vchi_bsd.h @@ -329,7 +329,8 @@ device_rlprintf(int pps, device_t dev, const char *fmt, ...) MALLOC_DECLARE(M_VCHI); #define kmalloc(size, flags) malloc((size), M_VCHI, M_NOWAIT | M_ZERO) -#define kcalloc(n, size, flags) malloc((n) * (size), M_VCHI, M_NOWAIT | M_ZERO) +#define kcalloc(n, size, flags) mallocarray((n), (size), M_VCHI, \ + M_NOWAIT | M_ZERO) #define kzalloc(a, b) kcalloc(1, (a), (b)) #define kfree(p) free(p, M_VCHI) From f031a3b25ffa0fbe4f883a335fd1745fedb19c5a Mon Sep 17 00:00:00 2001 From: Ian Lepore Date: Sun, 7 Jan 2018 18:06:30 +0000 Subject: [PATCH 014/158] Use EVENTHANDLER_DIRECT_INVOKE() for device events, for better performance. --- sys/kern/subr_bus.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index faaee4865771..b86a476273ab 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -146,6 +147,10 @@ struct device { static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures"); static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc"); +EVENTHANDLER_LIST_DEFINE(device_attach); +EVENTHANDLER_LIST_DEFINE(device_detach); +EVENTHANDLER_LIST_DEFINE(dev_lookup); + static void devctl2_init(void); #define DRIVERNAME(d) ((d)? d->name : "no driver") @@ -2938,7 +2943,7 @@ device_attach(device_t dev) else dev->state = DS_ATTACHED; dev->flags &= ~DF_DONENOMATCH; - EVENTHANDLER_INVOKE(device_attach, dev); + EVENTHANDLER_DIRECT_INVOKE(device_attach, dev); devadded(dev); return (0); } @@ -2972,12 +2977,14 @@ device_detach(device_t dev) if (dev->state != DS_ATTACHED) return (0); - EVENTHANDLER_INVOKE(device_detach, dev, EVHDEV_DETACH_BEGIN); + EVENTHANDLER_DIRECT_INVOKE(device_detach, dev, EVHDEV_DETACH_BEGIN); if ((error = DEVICE_DETACH(dev)) != 0) { - EVENTHANDLER_INVOKE(device_detach, dev, EVHDEV_DETACH_FAILED); + EVENTHANDLER_DIRECT_INVOKE(device_detach, dev, + EVHDEV_DETACH_FAILED); return (error); } else { - EVENTHANDLER_INVOKE(device_detach, dev, EVHDEV_DETACH_COMPLETE); + EVENTHANDLER_DIRECT_INVOKE(device_detach, dev, + EVHDEV_DETACH_COMPLETE); } devremoved(dev); if (!device_is_quiet(dev)) @@ -5330,7 +5337,7 @@ find_device(struct devreq *req, device_t *devp) /* Finally, give device enumerators a chance. */ dev = NULL; - EVENTHANDLER_INVOKE(dev_lookup, req->dr_name, &dev); + EVENTHANDLER_DIRECT_INVOKE(dev_lookup, req->dr_name, &dev); if (dev == NULL) return (ENOENT); *devp = dev; From ac579135b0a755f140649297ea22fee7f5f9c9c3 Mon Sep 17 00:00:00 2001 From: Ian Lepore Date: Sun, 7 Jan 2018 18:07:22 +0000 Subject: [PATCH 015/158] Use EVENTHANDLER_DIRECT_INVOKE for [un]mount events, for better performance. --- sys/kern/vfs_mount.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index dd28dce8567e..070a56c85db1 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -91,6 +92,9 @@ struct mntlist mountlist = TAILQ_HEAD_INITIALIZER(mountlist); struct mtx mountlist_mtx; MTX_SYSINIT(mountlist, &mountlist_mtx, "mountlist", MTX_DEF); +EVENTHANDLER_LIST_DEFINE(vfs_mounted); +EVENTHANDLER_LIST_DEFINE(vfs_unmounted); + /* * Global opts, taken by all filesystems */ @@ -865,7 +869,7 @@ vfs_domount_first( if (VFS_ROOT(mp, LK_EXCLUSIVE, &newdp)) panic("mount: lost mount"); VOP_UNLOCK(vp, 0); - EVENTHANDLER_INVOKE(vfs_mounted, mp, newdp, td); + EVENTHANDLER_DIRECT_INVOKE(vfs_mounted, mp, newdp, td); VOP_UNLOCK(newdp, 0); mountcheckdirs(vp, newdp); vrele(newdp); @@ -1401,7 +1405,7 @@ dounmount(struct mount *mp, int flags, struct thread *td) mtx_lock(&mountlist_mtx); TAILQ_REMOVE(&mountlist, mp, mnt_list); mtx_unlock(&mountlist_mtx); - EVENTHANDLER_INVOKE(vfs_unmounted, mp, td); + EVENTHANDLER_DIRECT_INVOKE(vfs_unmounted, mp, td); if (coveredvp != NULL) { coveredvp->v_mountedhere = NULL; VOP_UNLOCK(coveredvp, 0); From f1a48eaf0dc620729bca82c109c36fcbfe9c0482 Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Sun, 7 Jan 2018 20:28:17 +0000 Subject: [PATCH 016/158] Add missing file to gpiobus module ofw_gpiobus.c is needed when FDT is used. MFC after: 2 weeks --- sys/modules/gpio/gpiobus/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/modules/gpio/gpiobus/Makefile b/sys/modules/gpio/gpiobus/Makefile index 24a0f1314a75..458d56d8b935 100644 --- a/sys/modules/gpio/gpiobus/Makefile +++ b/sys/modules/gpio/gpiobus/Makefile @@ -36,6 +36,10 @@ SRCS= gpiobus.c gpioc.c SRCS+= gpio_if.c gpio_if.h gpiobus_if.c gpiobus_if.h ofw_bus_if.h SRCS+= device_if.h bus_if.h opt_platform.h +.if !empty(OPT_FDT) +SRCS+= ofw_gpiobus.c +.endif + CFLAGS+= -I. -I${SRCTOP}/sys/dev/gpio/ .include From 48c29f849ecb7873aabdc9ccf0fac18a2b0b925f Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sun, 7 Jan 2018 21:57:52 +0000 Subject: [PATCH 017/158] Fix typo from r327666 MFC after: 13 days X-MFC-With: 327666 --- tests/sys/geom/class/eli/init_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sys/geom/class/eli/init_test.sh b/tests/sys/geom/class/eli/init_test.sh index 52935cca2ea7..e43c7c4c30df 100644 --- a/tests/sys/geom/class/eli/init_test.sh +++ b/tests/sys/geom/class/eli/init_test.sh @@ -9,7 +9,7 @@ init_test() keylen=${cipher##*:} atf_check -s exit:0 -e ignore \ - geli init -B none -e $ealgo -l $keylen -P -K keyfile + geli init -B none -e $ealgo -l $keylen -P -K keyfile \ -s $secsize ${md} atf_check geli attach -p -k keyfile ${md} From 565a0a2c65fffd51ededc7c433d34c79ef681ee0 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sun, 7 Jan 2018 22:21:07 +0000 Subject: [PATCH 018/158] geli: convert remaining TAP tests to ATF MFC after: 2 weeks --- ObsoleteFiles.inc | 3 + tests/sys/geom/class/eli/Makefile | 4 - tests/sys/geom/class/eli/attach_test.sh | 55 +++++++++++++ tests/sys/geom/class/eli/conf.sh | 3 - tests/sys/geom/class/eli/delkey_test.sh | 28 +++++++ tests/sys/geom/class/eli/init_test.sh | 23 ++++++ tests/sys/geom/class/eli/kill_test.sh | 31 ++++++++ tests/sys/geom/class/eli/nokey_test.sh | 65 ---------------- tests/sys/geom/class/eli/readonly_test.sh | 94 ----------------------- tests/sys/geom/class/eli/setkey_test.sh | 66 ++++++++++++++++ 10 files changed, 206 insertions(+), 166 deletions(-) delete mode 100644 tests/sys/geom/class/eli/nokey_test.sh delete mode 100644 tests/sys/geom/class/eli/readonly_test.sh diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index a3c7f9828297..149587d76d2f 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,9 @@ # xargs -n1 | sort | uniq -d; # done +# 20180107: Convert remaining geli(8) tests to ATF +OLD_FILES+=tests/sys/geom/class/eli/nokey_test.sh +OLD_FILES+=tests/sys/geom/class/eli/readonly_test.sh # 20180106: Convert most geli(8) tests to ATF OLD_FILES+=tests/sys/geom/class/eli/attach_d_test.sh OLD_FILES+=tests/sys/geom/class/eli/configure_b_B_test.sh diff --git a/tests/sys/geom/class/eli/Makefile b/tests/sys/geom/class/eli/Makefile index 654f6f303ff0..2acf3c4c569a 100644 --- a/tests/sys/geom/class/eli/Makefile +++ b/tests/sys/geom/class/eli/Makefile @@ -18,10 +18,6 @@ ATF_TESTS_SH+= onetime_test ATF_TESTS_SH+= resize_test ATF_TESTS_SH+= setkey_test -TAP_TESTS_SH+= nokey_test -TAP_TESTS_SH+= readonly_test - - ${PACKAGE}FILES+= conf.sh .for t in ${TAP_TESTS_SH} diff --git a/tests/sys/geom/class/eli/attach_test.sh b/tests/sys/geom/class/eli/attach_test.sh index 83215e968510..42230059ac2d 100755 --- a/tests/sys/geom/class/eli/attach_test.sh +++ b/tests/sys/geom/class/eli/attach_test.sh @@ -39,7 +39,62 @@ attach_d_cleanup() geli_test_cleanup } +atf_test_case attach_r cleanup +attach_r_head() +{ + atf_set "descr" "geli attach -r will create a readonly provider" + atf_set "require.user" "root" +} +attach_r_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=100 + md=$(attach_md -t malloc -s `expr $sectors + 1`) + atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + + atf_check geli init -B none -P -K keyfile ${md} + atf_check geli attach -r -p -k keyfile ${md} + + atf_check -o match:"^Flags: .*READ-ONLY" geli list ${md}.eli + + # Verify that writes are verbotten + atf_check -s not-exit:0 -e match:"Read-only" \ + dd if=/dev/zero of=/dev/${md}.eli count=1 +} +attach_r_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + +atf_test_case nokey cleanup +nokey_head() +{ + atf_set "descr" "geli attach fails if called with no key component" + atf_set "require.user" "root" +} +nokey_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=100 + md=$(attach_md -t malloc -s `expr $sectors + 1`) + atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + + atf_check geli init -B none -P -K keyfile ${md} + atf_check -s not-exit:0 -e match:"No key components given" \ + geli attach -p ${md} 2>/dev/null +} +nokey_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + atf_init_test_cases() { atf_add_test_case attach_d + atf_add_test_case attach_r + atf_add_test_case nokey } diff --git a/tests/sys/geom/class/eli/conf.sh b/tests/sys/geom/class/eli/conf.sh index d1dde228afad..04f75b7abf69 100644 --- a/tests/sys/geom/class/eli/conf.sh +++ b/tests/sys/geom/class/eli/conf.sh @@ -3,7 +3,6 @@ class="eli" base=$(atf_get ident) -[ -z "$base" ] && base=`basename $0` # for TAP compatibility MAX_SECSIZE=8192 TEST_MDS_FILE=md.devs @@ -85,7 +84,5 @@ geli_test_cleanup() fi true } -# TODO: remove the trap statement once all TAP tests are converted -trap geli_test_cleanup ABRT EXIT INT TERM . `dirname $0`/../geom_subr.sh diff --git a/tests/sys/geom/class/eli/delkey_test.sh b/tests/sys/geom/class/eli/delkey_test.sh index 99453f1d0b26..9542e0166a9f 100644 --- a/tests/sys/geom/class/eli/delkey_test.sh +++ b/tests/sys/geom/class/eli/delkey_test.sh @@ -80,7 +80,35 @@ delkey_cleanup() geli_test_cleanup } +atf_test_case delkey_readonly cleanup +delkey_readonly_head() +{ + atf_set "descr" "geli delkey cannot work on a read-only provider" + atf_set "require.user" "root" +} +delkey_readonly_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=100 + md=$(attach_md -t malloc -s `expr $sectors + 1`) + atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + + atf_check geli init -B none -P -K keyfile ${md} + atf_check geli attach -r -p -k keyfile ${md} + + atf_check -s not-exit:0 -e match:"read-only" geli delkey -n 0 ${md} + # Even with -f (force) it should still fail + atf_check -s not-exit:0 -e match:"read-only" geli delkey -f -n 0 ${md} +} +delkey_readonly_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + atf_init_test_cases() { atf_add_test_case delkey + atf_add_test_case delkey_readonly } diff --git a/tests/sys/geom/class/eli/init_test.sh b/tests/sys/geom/class/eli/init_test.sh index e43c7c4c30df..b07d8532deb4 100644 --- a/tests/sys/geom/class/eli/init_test.sh +++ b/tests/sys/geom/class/eli/init_test.sh @@ -358,6 +358,28 @@ init_i_P_cleanup() geli_test_cleanup } +atf_test_case nokey cleanup +nokey_head() +{ + atf_set "descr" "geli init fails if called with no key component" + atf_set "require.user" "root" +} +nokey_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=100 + md=$(attach_md -t malloc -s `expr $sectors + 1`) + + atf_check -s not-exit:0 -e match:"No key components given" \ + geli init -B none -P ${md} +} +nokey_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + atf_init_test_cases() { atf_add_test_case init @@ -366,4 +388,5 @@ atf_init_test_cases() atf_add_test_case init_a atf_add_test_case init_alias atf_add_test_case init_i_P + atf_add_test_case nokey } diff --git a/tests/sys/geom/class/eli/kill_test.sh b/tests/sys/geom/class/eli/kill_test.sh index 336629a7a0ab..ef7f06893cda 100644 --- a/tests/sys/geom/class/eli/kill_test.sh +++ b/tests/sys/geom/class/eli/kill_test.sh @@ -65,7 +65,38 @@ kill_cleanup() geli_test_cleanup } +atf_test_case kill_readonly cleanup +kill_readonly_head() +{ + atf_set "descr" "geli kill will not destroy the keys of a readonly provider" + atf_set "require.user" "root" +} +kill_readonly_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=100 + md=$(attach_md -t malloc -s `expr $sectors + 1`) + atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + + atf_check geli init -B none -P -K keyfile ${md} + # Attach read-only + atf_check geli attach -r -p -k keyfile ${md} + + atf_check geli kill ${md} + # The provider will be detached + atf_check [ ! -c /dev/${md}.eli ] + # But its keys should not be destroyed + atf_check geli attach -p -k keyfile ${md} +} +kill_readonly_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + atf_init_test_cases() { atf_add_test_case kill + atf_add_test_case kill_readonly } diff --git a/tests/sys/geom/class/eli/nokey_test.sh b/tests/sys/geom/class/eli/nokey_test.sh deleted file mode 100644 index 282979bd4556..000000000000 --- a/tests/sys/geom/class/eli/nokey_test.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=100 -keyfile=`mktemp $base.XXXXXX` || exit 1 -md=$(attach_md -t malloc -s `expr $sectors + 1`) - -echo "1..8" - -geli init -B none -P ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 1" -else - echo "not ok 1" -fi - -dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1 - -geli init -B none -P -K ${keyfile} ${md} 2>/dev/null -if [ $? -eq 0 ]; then - echo "ok 2" -else - echo "not ok 2" -fi -geli attach -p ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 3" -else - echo "not ok 3" -fi -geli attach -p -k ${keyfile} ${md} 2>/dev/null -if [ $? -eq 0 ]; then - echo "ok 4" -else - echo "not ok 4" -fi -geli setkey -n 0 -P ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 5" -else - echo "not ok 5" -fi -geli detach ${md} 2>/dev/null -if [ $? -eq 0 ]; then - echo "ok 6" -else - echo "not ok 6" -fi -geli setkey -n 0 -p -P -K ${keyfile} ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 7" -else - echo "not ok 7" -fi -geli setkey -n 0 -p -k ${keyfile} -P ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 8" -else - echo "not ok 8" -fi - -rm -f $keyfile diff --git a/tests/sys/geom/class/eli/readonly_test.sh b/tests/sys/geom/class/eli/readonly_test.sh deleted file mode 100644 index 2d69d14769e6..000000000000 --- a/tests/sys/geom/class/eli/readonly_test.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -. $(dirname $0)/conf.sh - -base=`basename $0` -sectors=100 -keyfile=`mktemp $base.XXXXXX` || exit 1 -md=$(attach_md -t malloc -s `expr $sectors + 1`) - -echo "1..11" - -dd if=/dev/random of=${keyfile} bs=512 count=16 >/dev/null 2>&1 - -geli init -B none -P -K $keyfile ${md} -if [ $? -eq 0 ]; then - echo "ok 1" -else - echo "not ok 1" -fi - -geli attach -r -p -k $keyfile ${md} -if [ $? -eq 0 ]; then - echo "ok 2" -else - echo "not ok 2" -fi - -sh -c "true >/dev/${md}.eli" 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 3" -else - echo "not ok 3" -fi - -geli kill ${md} -if [ $? -eq 0 ]; then - echo "ok 4" -else - echo "not ok 4" -fi - -# kill should detach provider... -if [ ! -c /dev/${md}.eli ]; then - echo "ok 5" -else - echo "not ok 5" -fi - -# ...but not destroy the metadata. -geli attach -r -p -k $keyfile ${md} -if [ $? -eq 0 ]; then - echo "ok 6" -else - echo "not ok 6" -fi - -geli setkey -n 1 -P -K /dev/null ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 7" -else - echo "not ok 7" -fi - -geli delkey -n 0 ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 8" -else - echo "not ok 8" -fi - -geli delkey -f -n 0 ${md} 2>/dev/null -if [ $? -ne 0 ]; then - echo "ok 9" -else - echo "not ok 9" -fi - -geli list ${md}.eli | egrep '^Flags: .*READ-ONLY' >/dev/null -if [ $? -eq 0 ]; then - echo "ok 10" -else - echo "not ok 10" -fi - -geli detach ${md} -if [ $? -eq 0 ]; then - echo "ok 11" -else - echo "not ok 11" -fi - -mdconfig -d -u ${md} -rm -f $keyfile diff --git a/tests/sys/geom/class/eli/setkey_test.sh b/tests/sys/geom/class/eli/setkey_test.sh index 7829f41f1efd..bd5e2dcedd8e 100644 --- a/tests/sys/geom/class/eli/setkey_test.sh +++ b/tests/sys/geom/class/eli/setkey_test.sh @@ -92,7 +92,73 @@ setkey_cleanup() geli_test_cleanup } +atf_test_case setkey_readonly cleanup +setkey_readonly_head() +{ + atf_set "descr" "geli setkey cannot change the keys of a readonly provider" + atf_set "require.user" "root" +} +setkey_readonly_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=100 + md=$(attach_md -t malloc -s `expr $sectors + 1`) + atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + + atf_check geli init -B none -P -K keyfile ${md} + atf_check geli attach -r -p -k keyfile ${md} + + atf_check -s not-exit:0 -e match:"read-only" \ + geli setkey -n 1 -P -K /dev/null ${md} +} +setkey_readonly_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + +atf_test_case nokey cleanup +nokey_head() +{ + atf_set "descr" "geli setkey can change the key for an existing provider" + atf_set "require.user" "root" +} +nokey_body() +{ + . $(atf_get_srcdir)/conf.sh + + sectors=100 + md=$(attach_md -t malloc -s `expr $sectors + 1`) + atf_check dd if=/dev/random of=keyfile1 bs=512 count=16 status=none + atf_check dd if=/dev/random of=keyfile2 bs=512 count=16 status=none + + atf_check geli init -B none -P -K keyfile1 ${md} + + # Try to set the key for a detached device without providing any + # components for the old key. + atf_check -s not-exit:0 -e match:"No key components given" \ + geli setkey -n 0 -p -P -K keyfile2 ${md} + + # Try to set the key for a detached device without providing any + # components for the new key + atf_check -s not-exit:0 -e match:"No key components given" \ + geli setkey -n 0 -p -k keyfile1 -P ${md} + + # Try to set a new key for an attached device with no components + atf_check geli attach -p -k keyfile1 ${md} + atf_check -s not-exit:0 -e match:"No key components given" \ + geli setkey -n 0 -P ${md} +} +nokey_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + geli_test_cleanup +} + atf_init_test_cases() { atf_add_test_case setkey + atf_add_test_case setkey_readonly + atf_add_test_case nokey } From 4b6b56b32b4887cb85ca9a0fefb985f52da722a7 Mon Sep 17 00:00:00 2001 From: Ed Schouten Date: Sun, 7 Jan 2018 22:38:45 +0000 Subject: [PATCH 019/158] Use mallocarray(9) in CloudABI kernel code where possible. Submitted by: pfg@ --- sys/compat/cloudabi32/cloudabi32_sock.c | 4 ++-- sys/compat/cloudabi64/cloudabi64_sock.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/compat/cloudabi32/cloudabi32_sock.c b/sys/compat/cloudabi32/cloudabi32_sock.c index b4fa09ca1d42..97cb4478cf57 100644 --- a/sys/compat/cloudabi32/cloudabi32_sock.c +++ b/sys/compat/cloudabi32/cloudabi32_sock.c @@ -60,7 +60,7 @@ cloudabi32_sys_sock_recv(struct thread *td, /* Convert iovecs to native format. */ if (ri.ri_data_len > UIO_MAXIOV) return (EINVAL); - iov = malloc(ri.ri_data_len * sizeof(struct iovec), + iov = mallocarray(ri.ri_data_len, sizeof(struct iovec), M_SOCKET, M_WAITOK); user_iov = TO_PTR(ri.ri_data); for (i = 0; i < ri.ri_data_len; i++) { @@ -104,7 +104,7 @@ cloudabi32_sys_sock_send(struct thread *td, /* Convert iovecs to native format. */ if (si.si_data_len > UIO_MAXIOV) return (EINVAL); - iov = malloc(si.si_data_len * sizeof(struct iovec), + iov = mallocarray(si.si_data_len, sizeof(struct iovec), M_SOCKET, M_WAITOK); user_iov = TO_PTR(si.si_data); for (i = 0; i < si.si_data_len; i++) { diff --git a/sys/compat/cloudabi64/cloudabi64_sock.c b/sys/compat/cloudabi64/cloudabi64_sock.c index 482b6d8f67e9..001adada384a 100644 --- a/sys/compat/cloudabi64/cloudabi64_sock.c +++ b/sys/compat/cloudabi64/cloudabi64_sock.c @@ -60,7 +60,7 @@ cloudabi64_sys_sock_recv(struct thread *td, /* Convert iovecs to native format. */ if (ri.ri_data_len > UIO_MAXIOV) return (EINVAL); - iov = malloc(ri.ri_data_len * sizeof(struct iovec), + iov = mallocarray(ri.ri_data_len, sizeof(struct iovec), M_SOCKET, M_WAITOK); user_iov = TO_PTR(ri.ri_data); for (i = 0; i < ri.ri_data_len; i++) { @@ -104,7 +104,7 @@ cloudabi64_sys_sock_send(struct thread *td, /* Convert iovecs to native format. */ if (si.si_data_len > UIO_MAXIOV) return (EINVAL); - iov = malloc(si.si_data_len * sizeof(struct iovec), + iov = mallocarray(si.si_data_len, sizeof(struct iovec), M_SOCKET, M_WAITOK); user_iov = TO_PTR(si.si_data); for (i = 0; i < si.si_data_len; i++) { From 1d23aa6ec73baf53cb6f336c4ce91d6cb1c1fb0f Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Mon, 8 Jan 2018 00:10:45 +0000 Subject: [PATCH 020/158] geli: optimize tests Reduce the geli tests' runtime by about a third: * In integrity_test:copy, use a file-backed md(4) device instead of a malloc'd one. That way we can corrupt the underlying storage without needing to detach and reattach the geli device. * In integrity_test:{copy, hmac, data} and onetime_test:{onetime, onetime_a}, move reads of /dev/random out of the loop. MFC after: 2 weeks --- tests/sys/geom/class/eli/conf.sh | 12 +++++++- tests/sys/geom/class/eli/integrity_test.sh | 33 +++++++++++++--------- tests/sys/geom/class/eli/onetime_test.sh | 4 +-- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/tests/sys/geom/class/eli/conf.sh b/tests/sys/geom/class/eli/conf.sh index 04f75b7abf69..52885a186ff0 100644 --- a/tests/sys/geom/class/eli/conf.sh +++ b/tests/sys/geom/class/eli/conf.sh @@ -20,12 +20,22 @@ attach_md() # func for_each_geli_config() { func=$1 + backing_filename=$2 # Double the sector size to allow for the HMACs' storage space. osecsize=$(( $MAX_SECSIZE * 2 )) # geli needs 512B for the label. bytes=`expr $osecsize \* $sectors + 512`b - md=$(attach_md -t malloc -s $bytes) + + if [ -n "$backing_filename" ]; then + # Use a file-backed md(4) device, so we can deliberatly corrupt + # it without detaching the geli device first. + truncate -s $bytes backing_file + md=$(attach_md -t vnode -f backing_file) + else + md=$(attach_md -t malloc -s $bytes) + fi + for cipher in aes-xts:128 aes-xts:256 \ aes-cbc:128 aes-cbc:192 aes-cbc:256 \ 3des-cbc:192 \ diff --git a/tests/sys/geom/class/eli/integrity_test.sh b/tests/sys/geom/class/eli/integrity_test.sh index 22e5f2ce21d9..f2bc8a32fd8d 100755 --- a/tests/sys/geom/class/eli/integrity_test.sh +++ b/tests/sys/geom/class/eli/integrity_test.sh @@ -12,31 +12,32 @@ copy_test() { -K keyfile -s $secsize ${md} atf_check geli attach -p -k keyfile ${md} - atf_check dd if=/dev/random of=/dev/${md}.eli bs=${secsize} count=1 status=none + atf_check dd if=rnd of=/dev/${md}.eli bs=${secsize} count=1 status=none - atf_check geli detach ${md} # Copy first small sector to the second small sector. # This should be detected as corruption. - atf_check dd if=/dev/${md} of=sector bs=512 count=1 status=none - atf_check dd if=sector of=/dev/${md} bs=512 count=1 seek=1 status=none - atf_check geli attach -p -k keyfile ${md} + atf_check dd if=backing_file of=sector bs=512 count=1 \ + conv=notrunc status=none + atf_check dd if=sector of=backing_file bs=512 count=1 seek=1 \ + conv=notrunc status=none atf_check -s not-exit:0 -e ignore \ dd if=/dev/${md}.eli of=/dev/null bs=${secsize} count=1 # Fix the corruption - atf_check dd if=/dev/random of=/dev/${md}.eli bs=${secsize} count=2 status=none - atf_check dd if=/dev/${md}.eli of=/dev/null bs=${secsize} count=2 status=none + atf_check dd if=rnd of=/dev/${md}.eli bs=${secsize} count=2 status=none + atf_check dd if=/dev/${md}.eli of=/dev/null bs=${secsize} count=2 \ + status=none # Copy first big sector to the second big sector. # This should be detected as corruption. ms=`diskinfo /dev/${md} | awk '{print $3 - 512}'` ns=`diskinfo /dev/${md}.eli | awk '{print $4}'` usecsize=`echo "($ms / $ns) - (($ms / $ns) % 512)" | bc` - atf_check geli detach ${md} - atf_check dd if=/dev/${md} bs=512 count=$(( ${usecsize} / 512 )) seek=$(( $secsize / 512 )) of=sector status=none - atf_check dd of=/dev/${md} bs=512 count=$(( ${usecsize} / 512 )) seek=$(( $secsize / 256 )) if=sector status=none - atf_check -s exit:0 -e ignore geli attach -p -k keyfile ${md} + atf_check dd if=backing_file bs=512 count=$(( ${usecsize} / 512 )) \ + seek=$(( $secsize / 512 )) of=sector conv=notrunc status=none + atf_check dd of=backing_file bs=512 count=$(( ${usecsize} / 512 )) \ + seek=$(( $secsize / 256 )) if=sector conv=notrunc status=none atf_check -s not-exit:0 -e ignore \ dd if=/dev/${md}.eli of=/dev/null bs=${secsize} count=$ns } @@ -55,7 +56,9 @@ copy_body() sectors=2 atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none - for_each_geli_config copy_test + dd if=/dev/random of=rnd bs=${MAX_SECSIZE} count=${sectors} status=none + + for_each_geli_config copy_test backing_file } copy_cleanup() { @@ -77,7 +80,7 @@ data_test() { # Corrupt 8 bytes of data. atf_check dd if=/dev/${md} of=sector bs=512 count=1 status=none - atf_check dd if=/dev/random of=sector bs=1 count=8 seek=64 conv=notrunc status=none + atf_check dd if=rnd of=sector bs=1 count=8 seek=64 conv=notrunc status=none atf_check dd if=sector of=/dev/${md} bs=512 count=1 status=none atf_check geli attach -p -k keyfile ${md} @@ -100,6 +103,7 @@ data_body() sectors=2 atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + dd if=/dev/random of=rnd bs=${MAX_SECSIZE} count=${sectors} status=none for_each_geli_config data_test } data_cleanup() @@ -121,7 +125,7 @@ hmac_test() { # Corrupt 8 bytes of HMAC. atf_check dd if=/dev/${md} of=sector bs=512 count=1 status=none - atf_check dd if=/dev/random of=sector bs=1 count=16 conv=notrunc status=none + atf_check dd if=rnd of=sector bs=1 count=16 conv=notrunc status=none atf_check dd if=sector of=/dev/${md} bs=512 count=1 status=none atf_check geli attach -p -k keyfile ${md} @@ -144,6 +148,7 @@ hmac_body() sectors=2 atf_check dd if=/dev/random of=keyfile bs=512 count=16 status=none + dd if=/dev/random of=rnd bs=${MAX_SECSIZE} count=${sectors} status=none for_each_geli_config hmac_test } hmac_cleanup() diff --git a/tests/sys/geom/class/eli/onetime_test.sh b/tests/sys/geom/class/eli/onetime_test.sh index e37875850984..fff1a1fa396b 100644 --- a/tests/sys/geom/class/eli/onetime_test.sh +++ b/tests/sys/geom/class/eli/onetime_test.sh @@ -10,7 +10,6 @@ onetime_test() atf_check -s exit:0 -o ignore -e ignore \ geli onetime -e $ealgo -l $keylen -s $secsize ${md} - atf_check dd if=/dev/random of=rnd bs=${secsize} count=${sectors} status=none atf_check dd if=rnd of=/dev/${md}.eli bs=${secsize} count=${sectors} status=none md_rnd=`dd if=rnd bs=${secsize} count=${sectors} status=none | md5` @@ -82,7 +81,8 @@ onetime_a_body() . $(atf_get_srcdir)/conf.sh sectors=8 - atf_check dd if=/dev/random of=rnd bs=1024 count=1024 status=none + atf_check dd if=/dev/random of=rnd bs=$MAX_SECSIZE count=$sectors \ + status=none for_each_geli_config onetime_a_test } onetime_a_cleanup() From d06b4cefed766019cd816b02ef0735699a252cde Mon Sep 17 00:00:00 2001 From: Mariusz Zaborski Date: Mon, 8 Jan 2018 09:20:08 +0000 Subject: [PATCH 021/158] Document the DNS Casper service. Reviewed by: brueffer@, bcr@ Differential Revision: https://reviews.freebsd.org/D13762 --- lib/libcasper/services/cap_dns/Makefile | 10 ++ lib/libcasper/services/cap_dns/cap_dns.3 | 205 +++++++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 lib/libcasper/services/cap_dns/cap_dns.3 diff --git a/lib/libcasper/services/cap_dns/Makefile b/lib/libcasper/services/cap_dns/Makefile index e89be7f5396d..2d0bc95f2a8c 100644 --- a/lib/libcasper/services/cap_dns/Makefile +++ b/lib/libcasper/services/cap_dns/Makefile @@ -24,4 +24,14 @@ CFLAGS+=-I${.CURDIR} HAS_TESTS= SUBDIR.${MK_TESTS}+= tests +MAN+= cap_dns.3 + +MLINKS+=cap_dns.3 libcap_dns.3 +MLINKS+=cap_dns.3 cap_gethostbyname.3 +MLINKS+=cap_dns.3 cap_gethostbyname2.3 +MLINKS+=cap_dns.3 cap_gethostbyaddr.3 +MLINKS+=cap_dns.3 cap_getnameinfo.3 +MLINKS+=cap_dns.3 cap_dns_type_limit.3 +MLINKS+=cap_dns.3 cap_dns_family_limit.3 + .include diff --git a/lib/libcasper/services/cap_dns/cap_dns.3 b/lib/libcasper/services/cap_dns/cap_dns.3 new file mode 100644 index 000000000000..0b0837de4092 --- /dev/null +++ b/lib/libcasper/services/cap_dns/cap_dns.3 @@ -0,0 +1,205 @@ +.\" Copyright (c) 2018 Mariusz Zaborski +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd January 8, 2018 +.Dt CAP_DNS 3 +.Os +.Sh NAME +.Nm cap_gethostbyname , +.Nm cap_gethostbyname2 , +.Nm cap_gethostbyaddr , +.Nm cap_getnameinfo , +.Nm cap_dns_type_limit , +.Nm cap_dns_family_limit +.Nd "library for getting network host entry in capability mode" +.Sh LIBRARY +.Lb libcap_dns +.Sh SYNOPSIS +.In sys/nv.h +.In libcasper.h +.In casper/cap_dns.h +.Ft "struct hostent *" +.Fn cap_gethostbyname "const cap_channel_t *chan" "const char *name" +.Ft "struct hostent *" +.Fn cap_gethostbyname2 "const cap_channel_t *chan" "const char *name" "int af" +.Ft "struct hostent *" +.Fn cap_gethostbyaddr "const cap_channel_t *chan" "const void *addr" "socklen_t len" "int af" +.Ft "int" +.Fn cap_getnameinfo "const cap_channel_t *chan" "const void *name" "int namelen" +.Ft "int" +.Fn cap_dns_type_limit "cap_channel_t *chan" "const char * const *types" "size_t ntypes" +.Ft "int" +.Fn cap_dns_family_limit "const cap_channel_t *chan" "const int *families" "size_t nfamilies" +.Sh DESCRIPTION +The functions +.Fn cap_gethostbyname , +.Fn cap_gethostbyname2 , +.Fn cep_gethostbyaddr +and +.Xr cap_getnameinfo +are respectively equivalent to +.Xr gethostbyname 2 , +.Xr gethostbyname2 2 , +.Xr gethostbyaddr 2 +and +.Xr getnameinfo 2 +except that the connection to the +.Nm system.dns +service needs to be provided. +.Pp +The +.Fn cap_dns_type_limit +function limits the functions allowed in the service. +The +.Fa types +variable can be set to +.Dv ADDR +or +.Dv NAME . +See the +.Sx LIMITS +section for more details. +The +.Fa ntpyes +variable contains the number of +.Fa types +provided. +.Pp +The +.Fn cap_dns_family_limit +functions allows to limit address families. +For details see +.Sx LIMITS . +The +.Fa nfamilies +variable contains the number of +.Fa families +provided. +.Sh LIMITS +The preferred way of setting limits is to use the +.Fn cap_dns_type_limit +and +.Fn cap_dns_family_limit +functions, but the limits of service can be set also using +.Xr cap_limit_set 3 . +The nvlist for that function can contain the following values and types: +.Bl -ohang -offset indent +.It type ( NV_TYPE_STRING ) +The +.Va type +can have two values: +.Dv ADDR +or +.Dv NAME . +The +.Dv ADDR +means that functions +.Fn cap_gethostbyname , +.Fn cap_gethostbyname2 +and +.Fn cap_gethostbyaddr +are allowed. +In case when +.Va type +is set to +.Dv NAME +the +.Fn cap_getnameinfo +function is allowed. +.It family ( NV_TYPE_NUMBER ) +The +.Va family +limits service to one of the address families (e.g. +.Dv AF_INET , AF_INET6 , +etc.). +.Sh EXAMPLES +The following example first opens a capability to casper and then uses this +capability to create the +.Nm system.dns +casper service and uses it to resolve an IP address. +.Bd -literal +cap_channel_t *capcas, *capdns; +const char *typelimit = "ADDR"; +int familylimit; +const char *ipstr = "127.0.0.1"; +struct in_addr ip; +struct hostent *hp; + +/* Open capability to Casper. */ +capcas = cap_init(); +if (capcas == NULL) + err(1, "Unable to contact Casper"); + +/* Enter capability mode sandbox. */ +if (cap_enter() < 0 && errno != ENOSYS) + err(1, "Unable to enter capability mode"); + +/* Use Casper capability to create capability to the system.dns service. */ +capdns = cap_service_open(capcas, "system.dns"); +if (capdns == NULL) + err(1, "Unable to open system.dns service"); + +/* Close Casper capability, we don't need it anymore. */ +cap_close(capcas); + +/* Limit system.dns to reverse DNS lookups. */ +if (cap_dns_type_limit(capdns, &typelimit, 1) < 0) + err(1, "Unable to limit access to the system.dns service"); + +/* Limit system.dns to reserve IPv4 addresses */ +familylimit = AF_INET; +if (cap_dns_family_limit(capdns, &familylimit, 1) < 0) + err(1, "Unable to limit access to the system.dns service"); + +/* Convert IP address in C-string to in_addr. */ +if (!inet_aton(ipstr, &ip)) + errx(1, "Unable to parse IP address %s.", ipstr); + +/* Find hostname for the given IP address. */ +hp = cap_gethostbyaddr(capdns, (const void *)&ip, sizeof(ip), AF_INET); +if (hp == NULL) + errx(1, "No name associated with %s.", ipstr); + +printf("Name associated with %s is %s.\\n", ipstr, hp->h_name); +.Ed +.Sh SEE ALSO +.Xr cap_enter 2 , +.Xr err 3 , +.Xr gethostbyaddr 3 , +.Xr gethostbyname 3 , +.Xr gethostbyname2 3 , +.Xr getnameinfo 3, +.Xr nv 3 , +.Xr capsicum 4 +.Sh AUTHORS +The +.Nm cap_dns +service was implemented by +.An Pawel Jakub Dawidek Aq Mt pawel@dawidek.net +under sponsorship from the FreeBSD Foundation. +.Pp +This manual page was written by +.An Mariusz Zaborski Aq Mt oshogbo@FreeBSD.org . From 45a91d4538a1bc74f1c7602e7a6cf11267e2ca8a Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Mon, 8 Jan 2018 10:23:31 +0000 Subject: [PATCH 022/158] Move some of the common thread switching code into C. This will help with future optimisations, e.g. using Address Space IDs (asid). MFC after: 1 week Sponsored by: DARPA, AFRL --- sys/arm64/arm64/pmap.c | 32 ++++++++++++++++++++ sys/arm64/arm64/swtch.S | 65 +++++++++------------------------------- sys/arm64/include/pmap.h | 4 +++ 3 files changed, 50 insertions(+), 51 deletions(-) diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c index 76b07e730902..0ca55a26de4c 100644 --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -4660,6 +4660,38 @@ pmap_activate(struct thread *td) critical_exit(); } +struct pcb * +pmap_switch(struct thread *old, struct thread *new) +{ + struct pcb *pcb; + + /* Store the new curthread */ + PCPU_SET(curthread, new); + + /* And the new pcb */ + pcb = new->td_pcb; + PCPU_SET(curpcb, pcb); + + /* + * TODO: We may need to flush the cache here if switching + * to a user process. + */ + + __asm __volatile( + /* Switch to the new pmap */ + "msr ttbr0_el1, %0 \n" + "isb \n" + + /* Invalidate the TLB */ + "dsb ishst \n" + "tlbi vmalle1is \n" + "dsb ish \n" + "isb \n" + : : "r"(new->td_proc->p_md.md_l0addr)); + + return (pcb); +} + void pmap_sync_icache(pmap_t pmap, vm_offset_t va, vm_size_t sz) { diff --git a/sys/arm64/arm64/swtch.S b/sys/arm64/arm64/swtch.S index 1ff32098f033..779af785f2ab 100644 --- a/sys/arm64/arm64/swtch.S +++ b/sys/arm64/arm64/swtch.S @@ -70,32 +70,15 @@ ENTRY(cpu_throw) #ifdef VFP /* Backup the new thread pointer around a call to C code */ - mov x19, x1 + mov x19, x0 + mov x20, x1 bl vfp_discard - mov x1, x19 + mov x1, x20 + mov x0, x19 #endif - /* Store the new curthread */ - str x1, [x18, #PC_CURTHREAD] - /* And the new pcb */ - ldr x4, [x1, #TD_PCB] - str x4, [x18, #PC_CURPCB] - - /* - * TODO: We may need to flush the cache here. - */ - - /* Switch to the new pmap */ - ldr x28, [x1, #TD_PROC] - ldr x5, [x28, #(P_MD + MD_L0ADDR)] - msr ttbr0_el1, x5 - isb - - /* Invalidate the TLB */ - dsb ishst - tlbi vmalle1 - dsb ish - isb + bl pmap_switch + mov x4, x0 /* If we are single stepping, enable it */ ldr w5, [x4, #PCB_FLAGS] @@ -161,45 +144,25 @@ ENTRY(cpu_switch) ldr w5, [x4, #PCB_FLAGS] clear_step_flag w5, x6 -#ifdef VFP mov x19, x0 mov x20, x1 mov x21, x2 + +#ifdef VFP /* Load the pcb address */ mov x1, x4 bl vfp_save_state - mov x2, x21 mov x1, x20 mov x0, x19 #endif - /* Store the new curthread */ - str x1, [x18, #PC_CURTHREAD] + bl pmap_switch + /* Move the new pcb out of the way */ + mov x4, x0 - /* - * Restore the saved context and set it as curpcb. - */ - ldr x4, [x1, #TD_PCB] - str x4, [x18, #PC_CURPCB] - - /* - * TODO: We may need to flush the cache here if switching - * to a user process. - */ - - /* Load the new proc address */ - ldr x28, [x1, #TD_PROC] - - /* Switch to the new pmap */ - ldr x5, [x28, #(P_MD + MD_L0ADDR)] - msr ttbr0_el1, x5 - isb - - /* Invalidate the TLB */ - dsb ishst - tlbi vmalle1 - dsb ish - isb + mov x2, x21 + mov x1, x20 + mov x0, x19 /* * Release the old thread. This doesn't need to be a store-release diff --git a/sys/arm64/include/pmap.h b/sys/arm64/include/pmap.h index 9b95c3b31818..d0b5d4421c83 100644 --- a/sys/arm64/include/pmap.h +++ b/sys/arm64/include/pmap.h @@ -106,6 +106,8 @@ struct pv_chunk { typedef struct pmap *pmap_t; +struct thread; + #ifdef _KERNEL extern struct pmap kernel_pmap_store; #define kernel_pmap (&kernel_pmap_store) @@ -156,6 +158,8 @@ bool pmap_get_tables(pmap_t, vm_offset_t, pd_entry_t **, pd_entry_t **, int pmap_fault(pmap_t, uint64_t, uint64_t); +struct pcb *pmap_switch(struct thread *, struct thread *); + #define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list)) #endif /* _KERNEL */ From dde4c2fc9d1f672e748798b6f7623738f8a93dd6 Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Mon, 8 Jan 2018 11:08:45 +0000 Subject: [PATCH 023/158] Only install the new pagetable pointer into ttbr0_el1 when it differs from the existing value. MFC after: 1 week Sponsored by: DARPA, AFRL --- sys/arm64/arm64/pmap.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c index 0ca55a26de4c..315bb45336f2 100644 --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -4677,17 +4677,20 @@ pmap_switch(struct thread *old, struct thread *new) * to a user process. */ - __asm __volatile( - /* Switch to the new pmap */ - "msr ttbr0_el1, %0 \n" - "isb \n" + if (old == NULL || + old->td_proc->p_md.md_l0addr != new->td_proc->p_md.md_l0addr) { + __asm __volatile( + /* Switch to the new pmap */ + "msr ttbr0_el1, %0 \n" + "isb \n" - /* Invalidate the TLB */ - "dsb ishst \n" - "tlbi vmalle1is \n" - "dsb ish \n" - "isb \n" - : : "r"(new->td_proc->p_md.md_l0addr)); + /* Invalidate the TLB */ + "dsb ishst \n" + "tlbi vmalle1is \n" + "dsb ish \n" + "isb \n" + : : "r"(new->td_proc->p_md.md_l0addr)); + } return (pcb); } From de2b2c908a6d1f59c30fa3c5d177c994b8651d14 Mon Sep 17 00:00:00 2001 From: Fabien Thomas Date: Mon, 8 Jan 2018 13:43:12 +0000 Subject: [PATCH 024/158] Fix uninitialized crp_retw_id when using asynchronous crypto drivers with defered callbacks. Submitted by: emeric.poupon@stormshield.eu Reported by: mav@ Reviewed by: fabient@ --- sys/opencrypto/crypto.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/opencrypto/crypto.c b/sys/opencrypto/crypto.c index 8922f71e055b..0e3ae6965ca5 100644 --- a/sys/opencrypto/crypto.c +++ b/sys/opencrypto/crypto.c @@ -896,11 +896,12 @@ crypto_dispatch(struct cryptop *crp) binuptime(&crp->crp_tstamp); #endif + crp->crp_retw_id = crp->crp_sid % crypto_workers_num; + if (CRYPTOP_ASYNC(crp)) { if (crp->crp_flags & CRYPTO_F_ASYNC_KEEPORDER) { struct crypto_ret_worker *ret_worker; - crp->crp_retw_id = crp->crp_sid % crypto_workers_num; ret_worker = CRYPTO_RETW(crp->crp_retw_id); CRYPTO_RETW_LOCK(ret_worker); From 6db47c9d5bb0f1614e9f1c68ea99651c5a0158f8 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Mon, 8 Jan 2018 15:41:48 +0000 Subject: [PATCH 025/158] malloc(9): drop the __result_use_check attribute for the kernel allocator. The __result_use_check attribute was brought to the kernel malloc in r281203 for consistency with the userland malloc. For the case of the M_WAITOK flag, the kernel malloc(), realloc(), and reallocf() cannot return NULL so in that case the __result_use_check attribute makes no sense. We don't have any way of conditionalizing such attributes so just drop it. MFC after: 3 days --- sys/sys/malloc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/sys/malloc.h b/sys/sys/malloc.h index a5c2d4be7223..f33791e6673e 100644 --- a/sys/sys/malloc.h +++ b/sys/sys/malloc.h @@ -176,7 +176,7 @@ void *contigmalloc(unsigned long size, struct malloc_type *type, int flags, __alloc_size(1) __alloc_align(6); void free(void *addr, struct malloc_type *type); void *malloc(unsigned long size, struct malloc_type *type, int flags) - __malloc_like __result_use_check __alloc_size(1); + __malloc_like __alloc_size(1); void *mallocarray(size_t nmemb, size_t size, struct malloc_type *type, int flags) __malloc_like __result_use_check __alloc_size(1) __alloc_size(2); @@ -187,7 +187,7 @@ void malloc_type_freed(struct malloc_type *type, unsigned long size); void malloc_type_list(malloc_type_list_func_t *, void *); void malloc_uninit(void *); void *realloc(void *addr, unsigned long size, struct malloc_type *type, - int flags) __result_use_check __alloc_size(2); + int flags) __alloc_size(2); void *reallocf(void *addr, unsigned long size, struct malloc_type *type, int flags) __alloc_size(2); From 7653e6d781233ef4c2dc58cb77f45cbeac241c17 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Mon, 8 Jan 2018 15:41:49 +0000 Subject: [PATCH 026/158] Release the queue lock before restarting the worker loop. Reported and tested by: pho MFC after: 3 days Sponsored by: Dell EMC Isilon --- sys/geom/mirror/g_mirror.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index 0c5e45be5acd..f9c8952b0949 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -1964,8 +1964,10 @@ g_mirror_worker(void *arg) continue; } } - if (g_mirror_event_first(sc) != NULL) + if (g_mirror_event_first(sc) != NULL) { + mtx_unlock(&sc->sc_queue_mtx); continue; + } sx_xunlock(&sc->sc_lock); MSLEEP(sc, &sc->sc_queue_mtx, PRIBIO | PDROP, "m:w1", timeout * hz); From d6d1add4ea0a4e2fb37da0e9e93a8b974dd05e0b Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Mon, 8 Jan 2018 15:54:29 +0000 Subject: [PATCH 027/158] Revert r327697: malloc(9): drop the __result_use_check attribute for the kernel allocator. My bad: __result_use_check just checks the for the general and we always want to make sure allocated memory is used, not only checked for nullness. Add it to reallocf since that was missing. --- sys/sys/malloc.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/sys/malloc.h b/sys/sys/malloc.h index f33791e6673e..119b2448f7c5 100644 --- a/sys/sys/malloc.h +++ b/sys/sys/malloc.h @@ -176,7 +176,7 @@ void *contigmalloc(unsigned long size, struct malloc_type *type, int flags, __alloc_size(1) __alloc_align(6); void free(void *addr, struct malloc_type *type); void *malloc(unsigned long size, struct malloc_type *type, int flags) - __malloc_like __alloc_size(1); + __malloc_like __result_use_check __alloc_size(1); void *mallocarray(size_t nmemb, size_t size, struct malloc_type *type, int flags) __malloc_like __result_use_check __alloc_size(1) __alloc_size(2); @@ -187,9 +187,9 @@ void malloc_type_freed(struct malloc_type *type, unsigned long size); void malloc_type_list(malloc_type_list_func_t *, void *); void malloc_uninit(void *); void *realloc(void *addr, unsigned long size, struct malloc_type *type, - int flags) __alloc_size(2); + int flags) __result_use_check __alloc_size(2); void *reallocf(void *addr, unsigned long size, struct malloc_type *type, - int flags) __alloc_size(2); + int flags) __result_use_check __alloc_size(2); struct malloc_type *malloc_desc2type(const char *desc); #endif /* _KERNEL */ From 8b0a00b745c93e0abe27f9782086d812f6226ceb Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Mon, 8 Jan 2018 15:56:40 +0000 Subject: [PATCH 028/158] Sort and remove unneeded includes. MFC after: 1 week Sponsored by: Dell EMC Isilon --- sys/geom/mirror/g_mirror.c | 18 +++++++++--------- sys/geom/mirror/g_mirror_ctl.c | 15 ++++----------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index f9c8952b0949..e99018d791f8 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -31,22 +31,22 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include #include #include -#include +#include #include #include -#include -#include -#include -#include #include -#include -#include -#include +#include #include -#include +#include #include +#include +#include + +#include #include FEATURE(geom_mirror, "GEOM mirroring support"); diff --git a/sys/geom/mirror/g_mirror_ctl.c b/sys/geom/mirror/g_mirror_ctl.c index f4d4c466e671..2d598d944d27 100644 --- a/sys/geom/mirror/g_mirror_ctl.c +++ b/sys/geom/mirror/g_mirror_ctl.c @@ -31,25 +31,18 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include -#include #include #include -#include -#include -#include -#include #include -#include -#include -#include +#include +#include + #include #include -#include -#include #include - static struct g_mirror_softc * g_mirror_find_device(struct g_class *mp, const char *name) { From 94335944178dc8d876d52f6a9c0e67ec04e97da4 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Mon, 8 Jan 2018 18:44:36 +0000 Subject: [PATCH 029/158] Define __dmadat after #include'ing ufsread.c. The __dmadat variable is a statically allocated I/O buffer. The type is declared in the ufsread.c source file and clang warns if a variable is defined before it's type is declared. Sponsored by: DARPA / AFRL --- stand/mips/beri/boot2/boot2.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/stand/mips/beri/boot2/boot2.c b/stand/mips/beri/boot2/boot2.c index 8dba05012715..bc46dbd80adb 100644 --- a/stand/mips/beri/boot2/boot2.c +++ b/stand/mips/beri/boot2/boot2.c @@ -118,8 +118,6 @@ static const unsigned char flags[NOPT] = { static const char *const dev_nm[] = {"dram", "cfi", "sdcard"}; static const u_int dev_nm_count = nitems(dev_nm); -static struct dmadat __dmadat; - static struct dsk { unsigned type; /* BOOTINFO_DEV_TYPE_x object type. */ uintptr_t unitptr; /* Unit number or pointer to object. */ @@ -149,10 +147,11 @@ static int dskread(void *, unsigned, unsigned); static int xputc(int); static int xgetc(int); - #define UFS_SMALL_CGBASE #include "ufsread.c" +static struct dmadat __dmadat; + static inline int xfsread(ufs_ino_t inode, void *buf, size_t nbyte) { From 9bd8ae10e38ce594b02bbe26cba0b86a09195408 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Mon, 8 Jan 2018 18:46:10 +0000 Subject: [PATCH 030/158] Fix printf missing format variables warnings. Include the failing kernel file name for errors in beri_elf64_exec(). Sponsored by: DARPA / AFRL --- stand/mips/beri/loader/exec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stand/mips/beri/loader/exec.c b/stand/mips/beri/loader/exec.c index 68e149d5cb01..3c1b7a6a3cee 100644 --- a/stand/mips/beri/loader/exec.c +++ b/stand/mips/beri/loader/exec.c @@ -80,14 +80,14 @@ beri_elf64_exec(struct preloaded_file *fp) md = file_findmetadata(fp, MODINFOMD_ELFHDR); if (md == NULL) { - printf("%s: file_findmetadata failed\n"); + printf("%s: file_findmetadata failed\n", fp->f_name); return (EFTYPE); } ehdr = (Elf_Ehdr *)md->md_data; error = md_load64(fp->f_args, &mdp); if (error) { - printf("%s: md_load64 failed\n"); + printf("%s: md_load64 failed\n", fp->f_name); return (error); } From 349b6dad63a53b2d82179e3b153357e4a60cbfa5 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Mon, 8 Jan 2018 18:47:35 +0000 Subject: [PATCH 031/158] Use instead of and in boot code. In the freestanding boot compile environment, standard headers are not available. Curiously, only building with clang exposed this as compiles with external GCC still succeeded. Sponsored by: DARPA / AFRL --- stand/mips/beri/common/sdcard.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stand/mips/beri/common/sdcard.c b/stand/mips/beri/common/sdcard.c index 4de3db4b98e5..14b52875ed4d 100644 --- a/stand/mips/beri/common/sdcard.c +++ b/stand/mips/beri/common/sdcard.c @@ -33,8 +33,7 @@ #include #include -#include -#include +#include /* From d3692a4dee4d6ff0926365bcf95bbedb039ea70d Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Mon, 8 Jan 2018 20:14:16 +0000 Subject: [PATCH 032/158] Integrate zstd into the kernel Mock userspace headers and include mocked headers first in compilation command to inject kernel headers and override e.g., malloc(3) with malloc(9). Submitted by: allanjude Reviewed by: imp (earlier version), bapt (earlier version) Differential Revision: https://reviews.freebsd.org/D10407 --- sys/conf/files | 17 ++++++ sys/conf/kern.pre.mk | 3 ++ sys/contrib/zstd/lib/freebsd/stddef.h | 3 ++ sys/contrib/zstd/lib/freebsd/stdint.h | 3 ++ sys/contrib/zstd/lib/freebsd/stdio.h | 3 ++ sys/contrib/zstd/lib/freebsd/stdlib.h | 3 ++ sys/contrib/zstd/lib/freebsd/string.h | 3 ++ sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.h | 56 ++++++++++++++++++++ sys/contrib/zstd/lib/freebsd/zstd_kmalloc.c | 33 ++++++++++++ 9 files changed, 124 insertions(+) create mode 100644 sys/contrib/zstd/lib/freebsd/stddef.h create mode 100644 sys/contrib/zstd/lib/freebsd/stdint.h create mode 100644 sys/contrib/zstd/lib/freebsd/stdio.h create mode 100644 sys/contrib/zstd/lib/freebsd/stdlib.h create mode 100644 sys/contrib/zstd/lib/freebsd/string.h create mode 100644 sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.h create mode 100644 sys/contrib/zstd/lib/freebsd/zstd_kmalloc.c diff --git a/sys/conf/files b/sys/conf/files index 4d3b9676305f..b0524efbd77e 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -626,6 +626,23 @@ contrib/ngatm/netnatm/sig/sig_unimsgcpy.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_verify.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" +# Zstd +contrib/zstd/lib/freebsd/zstd_kmalloc.c standard compile-with ${ZSTD_C} +contrib/zstd/lib/common/zstd_common.c standard compile-with ${ZSTD_C} +contrib/zstd/lib/common/fse_decompress.c standard compile-with ${ZSTD_C} +contrib/zstd/lib/common/entropy_common.c standard compile-with ${ZSTD_C} +contrib/zstd/lib/common/error_private.c standard compile-with ${ZSTD_C} +contrib/zstd/lib/common/xxhash.c standard compile-with ${ZSTD_C} +contrib/zstd/lib/compress/zstd_compress.c standard compile-with ${ZSTD_C} +contrib/zstd/lib/compress/fse_compress.c standard compile-with ${ZSTD_C} +contrib/zstd/lib/compress/huf_compress.c standard compile-with ${ZSTD_C} +contrib/zstd/lib/compress/zstd_double_fast.c standard compile-with ${ZSTD_C} +contrib/zstd/lib/compress/zstd_fast.c standard compile-with ${ZSTD_C} +contrib/zstd/lib/compress/zstd_lazy.c standard compile-with ${ZSTD_C} +contrib/zstd/lib/compress/zstd_ldm.c standard compile-with ${ZSTD_C} +contrib/zstd/lib/compress/zstd_opt.c standard compile-with ${ZSTD_C} +contrib/zstd/lib/decompress/zstd_decompress.c standard compile-with ${ZSTD_C} +contrib/zstd/lib/decompress/huf_decompress.c standard compile-with ${ZSTD_C} crypto/blowfish/bf_ecb.c optional ipsec | ipsec_support crypto/blowfish/bf_skey.c optional crypto | ipsec | ipsec_support crypto/camellia/camellia.c optional crypto | ipsec | ipsec_support diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk index 5c5a847ddc0e..090b914d116a 100644 --- a/sys/conf/kern.pre.mk +++ b/sys/conf/kern.pre.mk @@ -132,6 +132,9 @@ NORMAL_FW= uudecode -o ${.TARGET} ${.ALLSRC} NORMAL_FWO= ${LD} -b binary --no-warn-mismatch -d -warn-common -r \ -m ${LD_EMULATION} -o ${.TARGET} ${.ALLSRC:M*.fw} +# for ZSTD in the kernel (include zstd/lib/freebsd before other CFLAGS) +ZSTD_C= ${CC} -c -DZSTD_HEAPMODE=1 -I$S/contrib/zstd/lib/freebsd ${CFLAGS} -I$S/contrib/zstd/lib -I$S/contrib/zstd/lib/common ${WERROR} -Wno-missing-prototypes ${PROF} ${.IMPSRC} + # Common for dtrace / zfs CDDL_CFLAGS= -DFREEBSD_NAMECACHE -nostdinc -I$S/cddl/compat/opensolaris -I$S/cddl/contrib/opensolaris/uts/common -I$S -I$S/cddl/contrib/opensolaris/common ${CFLAGS} -Wno-unknown-pragmas -Wno-missing-prototypes -Wno-undef -Wno-strict-prototypes -Wno-cast-qual -Wno-parentheses -Wno-redundant-decls -Wno-missing-braces -Wno-uninitialized -Wno-unused -Wno-inline -Wno-switch -Wno-pointer-arith -Wno-unknown-pragmas CDDL_CFLAGS+= -include $S/cddl/compat/opensolaris/sys/debug_compat.h diff --git a/sys/contrib/zstd/lib/freebsd/stddef.h b/sys/contrib/zstd/lib/freebsd/stddef.h new file mode 100644 index 000000000000..564c7920975b --- /dev/null +++ b/sys/contrib/zstd/lib/freebsd/stddef.h @@ -0,0 +1,3 @@ +/* This file is in the public domain */ +/* $FreeBSD$ */ +#include "zstd_kfreebsd.h" diff --git a/sys/contrib/zstd/lib/freebsd/stdint.h b/sys/contrib/zstd/lib/freebsd/stdint.h new file mode 100644 index 000000000000..564c7920975b --- /dev/null +++ b/sys/contrib/zstd/lib/freebsd/stdint.h @@ -0,0 +1,3 @@ +/* This file is in the public domain */ +/* $FreeBSD$ */ +#include "zstd_kfreebsd.h" diff --git a/sys/contrib/zstd/lib/freebsd/stdio.h b/sys/contrib/zstd/lib/freebsd/stdio.h new file mode 100644 index 000000000000..564c7920975b --- /dev/null +++ b/sys/contrib/zstd/lib/freebsd/stdio.h @@ -0,0 +1,3 @@ +/* This file is in the public domain */ +/* $FreeBSD$ */ +#include "zstd_kfreebsd.h" diff --git a/sys/contrib/zstd/lib/freebsd/stdlib.h b/sys/contrib/zstd/lib/freebsd/stdlib.h new file mode 100644 index 000000000000..564c7920975b --- /dev/null +++ b/sys/contrib/zstd/lib/freebsd/stdlib.h @@ -0,0 +1,3 @@ +/* This file is in the public domain */ +/* $FreeBSD$ */ +#include "zstd_kfreebsd.h" diff --git a/sys/contrib/zstd/lib/freebsd/string.h b/sys/contrib/zstd/lib/freebsd/string.h new file mode 100644 index 000000000000..564c7920975b --- /dev/null +++ b/sys/contrib/zstd/lib/freebsd/string.h @@ -0,0 +1,3 @@ +/* This file is in the public domain */ +/* $FreeBSD$ */ +#include "zstd_kfreebsd.h" diff --git a/sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.h b/sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.h new file mode 100644 index 000000000000..af01d4ecf371 --- /dev/null +++ b/sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.h @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2014-2015 Allan Jude + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef ZSTD_KFREEBSD_H +#define ZSTD_KFREEBSD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _KERNEL +#include /* size_t */ +#include /* memcpy, memset */ +#ifndef BUILDING_ZFS +#include /* ptrdiff_t */ +#endif +#include + +MALLOC_DECLARE(M_ZSTD); + +#define malloc(x) (malloc)((x), M_ZSTD, M_WAITOK) +#define free(x) (free)((x), M_ZSTD) +/* in zstd's use of calloc, a is always 1 */ +#define calloc(a,b) (malloc)((a)*(b), M_ZSTD, M_WAITOK | M_ZERO) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZSTD_KFREEBSD_H */ diff --git a/sys/contrib/zstd/lib/freebsd/zstd_kmalloc.c b/sys/contrib/zstd/lib/freebsd/zstd_kmalloc.c new file mode 100644 index 000000000000..c9792a92ef68 --- /dev/null +++ b/sys/contrib/zstd/lib/freebsd/zstd_kmalloc.c @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2016-2017 Allan Jude + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include + +MALLOC_DEFINE(M_ZSTD, "zstd", "ZSTD Compressor"); From 78f57a9cdef729f94669fe1eb494666f403f9235 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Mon, 8 Jan 2018 21:27:41 +0000 Subject: [PATCH 033/158] Generalize the gzio API. We currently use a set of subroutines in kern_gzio.c to perform compression of user and kernel core dumps. In the interest of adding support for other compression algorithms (zstd) in this role without complicating the API consumers, add a simple compressor API which can be used to select an algorithm. Also change the (non-default) GZIO kernel option to not enable compressed user cores by default. It's not clear that such a default would be desirable with support for multiple algorithms implemented, and it's inconsistent in that it isn't applied to kernel dumps. Reviewed by: cem Differential Revision: https://reviews.freebsd.org/D13632 --- share/man/man5/core.5 | 25 +- sys/conf/files | 2 +- sys/ddb/db_textdump.c | 6 +- sys/kern/imgact_elf.c | 60 ++--- sys/kern/kern_shutdown.c | 140 ++++------ sys/kern/kern_sig.c | 40 ++- sys/kern/{kern_gzio.c => subr_compressor.c} | 284 +++++++++++++------- sys/sys/{gzio.h => compressor.h} | 31 +-- sys/sys/conf.h | 4 +- sys/sys/imgact.h | 2 - 10 files changed, 325 insertions(+), 269 deletions(-) rename sys/kern/{kern_gzio.c => subr_compressor.c} (52%) rename sys/sys/{gzio.h => compressor.h} (68%) diff --git a/share/man/man5/core.5 b/share/man/man5/core.5 index dcc57baa1f39..e050cf80d56c 100644 --- a/share/man/man5/core.5 +++ b/share/man/man5/core.5 @@ -28,7 +28,7 @@ .\" @(#)core.5 8.3 (Berkeley) 12/11/93 .\" $FreeBSD$ .\" -.Dd October 5, 2015 +.Dd January 8, 2018 .Dt CORE 5 .Os .Sh NAME @@ -67,8 +67,8 @@ generating it). .Pp The following format specifiers may be used in the .Va kern.corefile -sysctl to insert additional information into the resulting core file -name: +sysctl to insert additional information into the resulting core +filename: .Bl -tag -width "1234567890" -compact -offset "12345" .It Em \&%H Machine hostname. @@ -108,17 +108,17 @@ is included in the kernel configuration file: GZIO .El .Pp -When the GZIO option is included, the following sysctls control whether core -files will be compressed: -.Bl -tag -width "kern.compress_user_cores_gzlevel" -compact -offset "12345" -.It Em kern.compress_user_cores_gzlevel -Gzip compression level. -Defaults to 6. +The following sysctl control core file compression: +.Bl -tag -width "kern.compress_user_cores_level" -compact -offset "12345" .It Em kern.compress_user_cores -Actually compress user cores. -Compressed core files will have a suffix of +Enable compression of user cores. +A value of 1 configures gzip compression. +gzip-compressed core files will have a suffix of .Ql .gz -appended to them. +appended to their filenames. +.It Em kern.compress_user_cores_level +Compression level. +Defaults to 6. .El .Sh NOTES Corefiles are written with open file descriptor information as an ELF note. @@ -153,6 +153,7 @@ command can be used: .Dl sysctl kern.corefile=/var/coredumps/\&%U/\&%N.core .Sh SEE ALSO .Xr gdb 1 , +.Xr gzip 1 , .Xr kgdb 1 , .Xr setrlimit 2 , .Xr sigaction 2 , diff --git a/sys/conf/files b/sys/conf/files index b0524efbd77e..b723aa52f691 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -3767,7 +3767,6 @@ kern/kern_exit.c standard kern/kern_fail.c standard kern/kern_ffclock.c standard kern/kern_fork.c standard -kern/kern_gzio.c optional gzio kern/kern_hhook.c standard kern/kern_idle.c standard kern/kern_intr.c standard @@ -3843,6 +3842,7 @@ kern/subr_bus_dma.c standard kern/subr_bufring.c standard kern/subr_capability.c standard kern/subr_clock.c standard +kern/subr_compressor.c standard kern/subr_counter.c standard kern/subr_devstat.c standard kern/subr_disk.c standard diff --git a/sys/ddb/db_textdump.c b/sys/ddb/db_textdump.c index 8845781621f7..a85d1ddca3eb 100644 --- a/sys/ddb/db_textdump.c +++ b/sys/ddb/db_textdump.c @@ -454,8 +454,8 @@ textdump_dumpsys(struct dumperinfo *di) /* * Disable EKCD because we don't provide encrypted textdumps. */ - kdc = di->kdc; - di->kdc = NULL; + kdc = di->kdcrypto; + di->kdcrypto = NULL; /* * Position the start of the dump so that we'll write the kernel dump @@ -512,7 +512,7 @@ textdump_dumpsys(struct dumperinfo *di) /* * Restore EKCD status. */ - di->kdc = kdc; + di->kdcrypto = kdc; } /*- diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index bec8e9d9ef97..28ebfff62577 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -36,13 +36,12 @@ __FBSDID("$FreeBSD$"); #include "opt_capsicum.h" #include "opt_compat.h" -#include "opt_gzio.h" #include #include +#include #include #include -#include #include #include #include @@ -1185,9 +1184,12 @@ struct coredump_params { struct ucred *file_cred; struct thread *td; struct vnode *vp; - struct gzio_stream *gzs; + struct compressor *comp; }; +extern int compress_user_cores; +extern int compress_user_cores_level; + static void cb_put_phdr(vm_map_entry_t, void *); static void cb_size_segment(vm_map_entry_t, void *); static int core_write(struct coredump_params *, const void *, size_t, off_t, @@ -1219,9 +1221,6 @@ static void note_procstat_rlimit(void *, struct sbuf *, size_t *); static void note_procstat_umask(void *, struct sbuf *, size_t *); static void note_procstat_vmmap(void *, struct sbuf *, size_t *); -#ifdef GZIO -extern int compress_user_cores_gzlevel; - /* * Write out a core segment to the compression stream. */ @@ -1241,7 +1240,7 @@ compress_chunk(struct coredump_params *p, char *base, char *buf, u_int len) error = copyin(base, buf, chunk_len); if (error != 0) bzero(buf, chunk_len); - error = gzio_write(p->gzs, buf, chunk_len); + error = compressor_write(p->comp, buf, chunk_len); if (error != 0) break; base += chunk_len; @@ -1251,13 +1250,12 @@ compress_chunk(struct coredump_params *p, char *base, char *buf, u_int len) } static int -core_gz_write(void *base, size_t len, off_t offset, void *arg) +core_compressed_write(void *base, size_t len, off_t offset, void *arg) { return (core_write((struct coredump_params *)arg, base, len, offset, UIO_SYSSPACE)); } -#endif /* GZIO */ static int core_write(struct coredump_params *p, const void *base, size_t len, @@ -1275,10 +1273,9 @@ core_output(void *base, size_t len, off_t offset, struct coredump_params *p, { int error; -#ifdef GZIO - if (p->gzs != NULL) + if (p->comp != NULL) return (compress_chunk(p, base, tmpbuf, len)); -#endif + /* * EFAULT is a non-fatal error that we can get, for example, * if the segment is backed by a file but extends beyond its @@ -1323,11 +1320,9 @@ sbuf_drain_core_output(void *arg, const char *data, int len) locked = PROC_LOCKED(p->td->td_proc); if (locked) PROC_UNLOCK(p->td->td_proc); -#ifdef GZIO - if (p->gzs != NULL) - error = gzio_write(p->gzs, __DECONST(char *, data), len); + if (p->comp != NULL) + error = compressor_write(p->comp, __DECONST(char *, data), len); else -#endif error = core_write(p, __DECONST(void *, data), len, p->offset, UIO_SYSSPACE); if (locked) @@ -1362,11 +1357,7 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags) struct note_info *ninfo; void *hdr, *tmpbuf; size_t hdrsize, notesz, coresize; -#ifdef GZIO - boolean_t compress; - compress = (flags & IMGACT_CORE_COMPRESS) != 0; -#endif hdr = NULL; tmpbuf = NULL; TAILQ_INIT(¬elst); @@ -1391,7 +1382,7 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags) params.file_cred = NOCRED; params.td = td; params.vp = vp; - params.gzs = NULL; + params.comp = NULL; #ifdef RACCT if (racct_enable) { @@ -1409,18 +1400,17 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags) goto done; } -#ifdef GZIO /* Create a compression stream if necessary. */ - if (compress) { - params.gzs = gzio_init(core_gz_write, GZIO_DEFLATE, - CORE_BUF_SIZE, compress_user_cores_gzlevel, ¶ms); - if (params.gzs == NULL) { + if (compress_user_cores != 0) { + params.comp = compressor_init(core_compressed_write, + compress_user_cores, CORE_BUF_SIZE, + compress_user_cores_level, ¶ms); + if (params.comp == NULL) { error = EFAULT; goto done; } tmpbuf = malloc(CORE_BUF_SIZE, M_TEMP, M_WAITOK | M_ZERO); } -#endif /* * Allocate memory for building the header, fill it up, @@ -1446,10 +1436,8 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags) offset += php->p_filesz; php++; } -#ifdef GZIO - if (error == 0 && compress) - error = gzio_flush(params.gzs); -#endif + if (error == 0 && params.comp != NULL) + error = compressor_flush(params.comp); } if (error) { log(LOG_WARNING, @@ -1458,13 +1446,9 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags) } done: -#ifdef GZIO - if (compress) { - free(tmpbuf, M_TEMP); - if (params.gzs != NULL) - gzio_fini(params.gzs); - } -#endif + free(tmpbuf, M_TEMP); + if (params.comp != NULL) + compressor_fini(params.comp); while ((ninfo = TAILQ_FIRST(¬elst)) != NULL) { TAILQ_REMOVE(¬elst, ninfo, link); free(ninfo, M_TEMP); diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c index d51a4c5aa76c..0979b3081286 100644 --- a/sys/kern/kern_shutdown.c +++ b/sys/kern/kern_shutdown.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include "opt_ekcd.h" -#include "opt_gzio.h" #include "opt_kdb.h" #include "opt_panic.h" #include "opt_sched.h" @@ -52,10 +51,10 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include -#include #include #include #include @@ -174,23 +173,21 @@ struct kerneldumpcrypto { }; #endif -#ifdef GZIO -struct kerneldumpgz { - struct gzio_stream *kdgz_stream; - uint8_t *kdgz_buf; - size_t kdgz_resid; +struct kerneldumpcomp { + struct compressor *kdc_stream; + uint8_t *kdc_buf; + size_t kdc_resid; }; -static struct kerneldumpgz *kerneldumpgz_create(struct dumperinfo *di, +static struct kerneldumpcomp *kerneldumpcomp_create(struct dumperinfo *di, uint8_t compression); -static void kerneldumpgz_destroy(struct dumperinfo *di); -static int kerneldumpgz_write_cb(void *cb, size_t len, off_t off, void *arg); +static void kerneldumpcomp_destroy(struct dumperinfo *di); +static int kerneldumpcomp_write_cb(void *base, size_t len, off_t off, void *arg); static int kerneldump_gzlevel = 6; SYSCTL_INT(_kern, OID_AUTO, kerneldump_gzlevel, CTLFLAG_RWTUN, &kerneldump_gzlevel, 0, - "Kernel crash dump gzip compression level"); -#endif /* GZIO */ + "Kernel crash dump compression level"); /* * Variable panicstr contains argument to first call to panic; used as flag @@ -986,39 +983,37 @@ kerneldumpcrypto_dumpkeysize(const struct kerneldumpcrypto *kdc) } #endif /* EKCD */ -#ifdef GZIO -static struct kerneldumpgz * -kerneldumpgz_create(struct dumperinfo *di, uint8_t compression) +static struct kerneldumpcomp * +kerneldumpcomp_create(struct dumperinfo *di, uint8_t compression) { - struct kerneldumpgz *kdgz; + struct kerneldumpcomp *kdcomp; if (compression != KERNELDUMP_COMP_GZIP) return (NULL); - kdgz = malloc(sizeof(*kdgz), M_DUMPER, M_WAITOK | M_ZERO); - kdgz->kdgz_stream = gzio_init(kerneldumpgz_write_cb, GZIO_DEFLATE, - di->maxiosize, kerneldump_gzlevel, di); - if (kdgz->kdgz_stream == NULL) { - free(kdgz, M_DUMPER); + kdcomp = malloc(sizeof(*kdcomp), M_DUMPER, M_WAITOK | M_ZERO); + kdcomp->kdc_stream = compressor_init(kerneldumpcomp_write_cb, + COMPRESS_GZIP, di->maxiosize, kerneldump_gzlevel, di); + if (kdcomp->kdc_stream == NULL) { + free(kdcomp, M_DUMPER); return (NULL); } - kdgz->kdgz_buf = malloc(di->maxiosize, M_DUMPER, M_WAITOK | M_NODUMP); - return (kdgz); + kdcomp->kdc_buf = malloc(di->maxiosize, M_DUMPER, M_WAITOK | M_NODUMP); + return (kdcomp); } static void -kerneldumpgz_destroy(struct dumperinfo *di) +kerneldumpcomp_destroy(struct dumperinfo *di) { - struct kerneldumpgz *kdgz; + struct kerneldumpcomp *kdcomp; - kdgz = di->kdgz; - if (kdgz == NULL) + kdcomp = di->kdcomp; + if (kdcomp == NULL) return; - gzio_fini(kdgz->kdgz_stream); - explicit_bzero(kdgz->kdgz_buf, di->maxiosize); - free(kdgz->kdgz_buf, M_DUMPER); - free(kdgz, M_DUMPER); + compressor_fini(kdcomp->kdc_stream); + explicit_bzero(kdcomp->kdc_buf, di->maxiosize); + free(kdcomp->kdc_buf, M_DUMPER); + free(kdcomp, M_DUMPER); } -#endif /* GZIO */ /* Registration of dumpers */ int @@ -1041,14 +1036,14 @@ set_dumper(struct dumperinfo *di, const char *devname, struct thread *td, return (EBUSY); dumper = *di; dumper.blockbuf = NULL; - dumper.kdc = NULL; - dumper.kdgz = NULL; + dumper.kdcrypto = NULL; + dumper.kdcomp = NULL; if (encryption != KERNELDUMP_ENC_NONE) { #ifdef EKCD - dumper.kdc = kerneldumpcrypto_create(di->blocksize, encryption, - key, encryptedkeysize, encryptedkey); - if (dumper.kdc == NULL) { + dumper.kdcrypto = kerneldumpcrypto_create(di->blocksize, + encryption, key, encryptedkeysize, encryptedkey); + if (dumper.kdcrypto == NULL) { error = EINVAL; goto cleanup; } @@ -1065,7 +1060,6 @@ set_dumper(struct dumperinfo *di, const char *devname, struct thread *td, } if (compression != KERNELDUMP_COMP_NONE) { -#ifdef GZIO /* * We currently can't support simultaneous encryption and * compression. @@ -1074,31 +1068,25 @@ set_dumper(struct dumperinfo *di, const char *devname, struct thread *td, error = EOPNOTSUPP; goto cleanup; } - dumper.kdgz = kerneldumpgz_create(&dumper, compression); - if (dumper.kdgz == NULL) { + dumper.kdcomp = kerneldumpcomp_create(&dumper, compression); + if (dumper.kdcomp == NULL) { error = EINVAL; goto cleanup; } -#else - error = EOPNOTSUPP; - goto cleanup; -#endif } dumper.blockbuf = malloc(di->blocksize, M_DUMPER, M_WAITOK | M_ZERO); return (0); cleanup: #ifdef EKCD - if (dumper.kdc != NULL) { - explicit_bzero(dumper.kdc, sizeof(*dumper.kdc) + - dumper.kdc->kdc_dumpkeysize); - free(dumper.kdc, M_EKCD); + if (dumper.kdcrypto != NULL) { + explicit_bzero(dumper.kdcrypto, sizeof(*dumper.kdcrypto) + + dumper.kdcrypto->kdc_dumpkeysize); + free(dumper.kdcrypto, M_EKCD); } #endif -#ifdef GZIO - kerneldumpgz_destroy(&dumper); -#endif + kerneldumpcomp_destroy(&dumper); if (dumper.blockbuf != NULL) { explicit_bzero(dumper.blockbuf, dumper.blocksize); @@ -1168,7 +1156,7 @@ dump_encrypted_write(struct dumperinfo *di, void *virtual, int error; size_t nbytes; - kdc = di->kdc; + kdc = di->kdcrypto; while (length > 0) { nbytes = MIN(length, sizeof(buf)); @@ -1194,7 +1182,7 @@ dump_write_key(struct dumperinfo *di, off_t offset) { struct kerneldumpcrypto *kdc; - kdc = di->kdc; + kdc = di->kdcrypto; if (kdc == NULL) return (0); return (dump_write(di, kdc->kdc_dumpkey, 0, offset, @@ -1202,9 +1190,8 @@ dump_write_key(struct dumperinfo *di, off_t offset) } #endif /* EKCD */ -#ifdef GZIO static int -kerneldumpgz_write_cb(void *base, size_t length, off_t offset, void *arg) +kerneldumpcomp_write_cb(void *base, size_t length, off_t offset, void *arg) { struct dumperinfo *di; size_t resid, rlength; @@ -1227,12 +1214,11 @@ kerneldumpgz_write_cb(void *base, size_t length, off_t offset, void *arg) } resid = length - rlength; memmove(di->blockbuf, (uint8_t *)base + rlength, resid); - di->kdgz->kdgz_resid = resid; + di->kdcomp->kdc_resid = resid; return (EAGAIN); } return (_dump_append(di, base, 0, length)); } -#endif /* GZIO */ /* * Write a kerneldumpheader at the specified offset. The header structure is 512 @@ -1290,10 +1276,10 @@ dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh) uint32_t keysize; #ifdef EKCD - int error = kerneldumpcrypto_init(di->kdc); + int error = kerneldumpcrypto_init(di->kdcrypto); if (error != 0) return (error); - keysize = kerneldumpcrypto_dumpkeysize(di->kdc); + keysize = kerneldumpcrypto_dumpkeysize(di->kdcrypto); #else keysize = 0; #endif @@ -1301,8 +1287,7 @@ dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh) dumpextent = dtoh64(kdh->dumpextent); if (di->mediasize < SIZEOF_METADATA + dumpextent + 2 * di->blocksize + keysize) { -#ifdef GZIO - if (di->kdgz != NULL) { + if (di->kdcomp != NULL) { /* * We don't yet know how much space the compressed dump * will occupy, so try to use the whole swap partition @@ -1315,7 +1300,6 @@ dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh) 2 * di->blocksize - keysize; kdh->dumpextent = htod64(dumpextent); } else -#endif return (E2BIG); } @@ -1333,7 +1317,7 @@ _dump_append(struct dumperinfo *di, void *virtual, vm_offset_t physical, int error; #ifdef EKCD - if (di->kdc != NULL) + if (di->kdcrypto != NULL) error = dump_encrypted_write(di, virtual, physical, di->dumpoff, length); else @@ -1353,18 +1337,16 @@ int dump_append(struct dumperinfo *di, void *virtual, vm_offset_t physical, size_t length) { -#ifdef GZIO void *buf; - if (di->kdgz != NULL) { - /* Bounce through a buffer to avoid gzip CRC errors. */ + if (di->kdcomp != NULL) { + /* Bounce through a buffer to avoid CRC errors. */ if (length > di->maxiosize) return (EINVAL); - buf = di->kdgz->kdgz_buf; + buf = di->kdcomp->kdc_buf; memmove(buf, virtual, length); - return (gzio_write(di->kdgz->kdgz_stream, buf, length)); + return (compressor_write(di->kdcomp->kdc_stream, buf, length)); } -#endif return (_dump_append(di, virtual, physical, length)); } @@ -1399,20 +1381,19 @@ dump_finish(struct dumperinfo *di, struct kerneldumpheader *kdh) extent = dtoh64(kdh->dumpextent); #ifdef EKCD - keysize = kerneldumpcrypto_dumpkeysize(di->kdc); + keysize = kerneldumpcrypto_dumpkeysize(di->kdcrypto); #else keysize = 0; #endif -#ifdef GZIO - if (di->kdgz != NULL) { - error = gzio_flush(di->kdgz->kdgz_stream); + if (di->kdcomp != NULL) { + error = compressor_flush(di->kdcomp->kdc_stream); if (error == EAGAIN) { /* We have residual data in di->blockbuf. */ error = dump_write(di, di->blockbuf, 0, di->dumpoff, di->blocksize); - di->dumpoff += di->kdgz->kdgz_resid; - di->kdgz->kdgz_resid = 0; + di->dumpoff += di->kdcomp->kdc_resid; + di->kdcomp->kdc_resid = 0; } if (error != 0) return (error); @@ -1426,9 +1407,8 @@ dump_finish(struct dumperinfo *di, struct kerneldumpheader *kdh) kdh->parity = 0; kdh->parity = kerneldump_parity(kdh); - gzio_reset(di->kdgz->kdgz_stream); + compressor_reset(di->kdcomp->kdc_stream); } -#endif /* * Write kerneldump headers at the beginning and end of the dump extent. @@ -1471,7 +1451,7 @@ dump_init_header(const struct dumperinfo *di, struct kerneldumpheader *kdh, kdh->dumpextent = kdh->dumplength; kdh->dumptime = htod64(time_second); #ifdef EKCD - kdh->dumpkeysize = htod32(kerneldumpcrypto_dumpkeysize(di->kdc)); + kdh->dumpkeysize = htod32(kerneldumpcrypto_dumpkeysize(di->kdcrypto)); #else kdh->dumpkeysize = 0; #endif @@ -1482,10 +1462,8 @@ dump_init_header(const struct dumperinfo *di, struct kerneldumpheader *kdh, kdh->versionstring[dstsize - 2] = '\n'; if (panicstr != NULL) strlcpy(kdh->panicstring, panicstr, sizeof(kdh->panicstring)); -#ifdef GZIO - if (di->kdgz != NULL) + if (di->kdcomp != NULL) kdh->compression = KERNELDUMP_COMP_GZIP; -#endif kdh->parity = kerneldump_parity(kdh); } diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 1a93544bdb7d..24c1cbdf1618 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$"); #include "opt_compat.h" -#include "opt_gzio.h" #include "opt_ktrace.h" #include @@ -51,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -3255,17 +3255,30 @@ SYSCTL_PROC(_debug, OID_AUTO, ncores, CTLTYPE_INT|CTLFLAG_RW, #define GZ_SUFFIX ".gz" -#ifdef GZIO -static int compress_user_cores = 1; -SYSCTL_INT(_kern, OID_AUTO, compress_user_cores, CTLFLAG_RWTUN, - &compress_user_cores, 0, "Compression of user corefiles"); +int compress_user_cores = 0; -int compress_user_cores_gzlevel = 6; -SYSCTL_INT(_kern, OID_AUTO, compress_user_cores_gzlevel, CTLFLAG_RWTUN, - &compress_user_cores_gzlevel, 0, "Corefile gzip compression level"); -#else -static int compress_user_cores = 0; -#endif +static int +sysctl_compress_user_cores(SYSCTL_HANDLER_ARGS) +{ + int error, val; + + val = compress_user_cores; + error = sysctl_handle_int(oidp, &val, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + if (val != 0 && !compressor_avail(val)) + return (EINVAL); + compress_user_cores = val; + return (error); +} +SYSCTL_PROC(_kern, OID_AUTO, compress_user_cores, CTLTYPE_INT | CTLFLAG_RWTUN, + 0, sizeof(int), sysctl_compress_user_cores, "I", + "Enable compression of user corefiles (" __XSTRING(COMPRESS_GZIP) " = gzip)"); + +int compress_user_cores_level = 6; +SYSCTL_INT(_kern, OID_AUTO, compress_user_cores_level, CTLFLAG_RWTUN, + &compress_user_cores_level, 0, + "Corefile compression level"); /* * Protect the access to corefilename[] by allproc_lock. @@ -3363,7 +3376,7 @@ corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td, } sx_sunlock(&corefilename_lock); free(hostname, M_TEMP); - if (compress) + if (compress == COMPRESS_GZIP) sbuf_printf(&sb, GZ_SUFFIX); if (sbuf_error(&sb) != 0) { log(LOG_ERR, "pid %ld (%s), uid (%lu): corename is too " @@ -3529,8 +3542,7 @@ coredump(struct thread *td) PROC_UNLOCK(p); if (p->p_sysent->sv_coredump != NULL) { - error = p->p_sysent->sv_coredump(td, vp, limit, - compress_user_cores ? IMGACT_CORE_COMPRESS : 0); + error = p->p_sysent->sv_coredump(td, vp, limit, 0); } else { error = ENOSYS; } diff --git a/sys/kern/kern_gzio.c b/sys/kern/subr_compressor.c similarity index 52% rename from sys/kern/kern_gzio.c rename to sys/kern/subr_compressor.c index f659b9bb7d7a..0ddf27274511 100644 --- a/sys/kern/kern_gzio.c +++ b/sys/kern/subr_compressor.c @@ -1,5 +1,7 @@ /*- - * Copyright (c) 2014 Mark Johnston + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2014, 2017 Mark Johnston * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,55 +26,87 @@ * SUCH DAMAGE. */ +/* + * Subroutines used for writing compressed user process and kernel core dumps. + */ + #include __FBSDID("$FreeBSD$"); +#include "opt_gzio.h" + #include -#include +#include #include +#include #include + +MALLOC_DEFINE(M_COMPRESS, "compressor", "kernel compression subroutines"); + +struct compressor_methods { + int format; + void *(* const init)(size_t, int); + void (* const reset)(void *); + int (* const write)(void *, void *, size_t, compressor_cb_t, void *); + void (* const fini)(void *); +}; + +struct compressor { + const struct compressor_methods *methods; + compressor_cb_t cb; + void *priv; + void *arg; +}; + +SET_DECLARE(compressors, struct compressor_methods); + +#ifdef GZIO + #include -#define KERN_GZ_HDRLEN 10 /* gzip header length */ -#define KERN_GZ_TRAILERLEN 8 /* gzip trailer length */ -#define KERN_GZ_MAGIC1 0x1f /* first magic byte */ -#define KERN_GZ_MAGIC2 0x8b /* second magic byte */ - -MALLOC_DEFINE(M_GZIO, "gzio", "zlib state"); - -struct gzio_stream { - uint8_t * gz_buffer; /* output buffer */ - size_t gz_bufsz; /* total buffer size */ +struct gz_stream { + uint8_t *gz_buffer; /* output buffer */ + size_t gz_bufsz; /* output buffer size */ off_t gz_off; /* offset into the output stream */ - enum gzio_mode gz_mode; /* stream mode */ uint32_t gz_crc; /* stream CRC32 */ - gzio_cb gz_cb; /* output callback */ - void * gz_arg; /* private callback arg */ z_stream gz_stream; /* zlib state */ }; -static void * gz_alloc(void *, u_int, u_int); -static void gz_free(void *, void *); -static int gz_write(struct gzio_stream *, void *, u_int, int); +static void *gz_init(size_t maxiosize, int level); +static void gz_reset(void *stream); +static int gz_write(void *stream, void *data, size_t len, compressor_cb_t, + void *); +static void gz_fini(void *stream); -struct gzio_stream * -gzio_init(gzio_cb cb, enum gzio_mode mode, size_t bufsz, int level, void *arg) +static void * +gz_alloc(void *arg __unused, u_int n, u_int sz) { - struct gzio_stream *s; + + /* + * Memory for zlib state is allocated using M_NODUMP since it may be + * used to compress a kernel dump, and we don't want zlib to attempt to + * compress its own state. + */ + return (malloc(n * sz, M_COMPRESS, M_WAITOK | M_ZERO | M_NODUMP)); +} + +static void +gz_free(void *arg __unused, void *ptr) +{ + + free(ptr, M_COMPRESS); +} + +static void * +gz_init(size_t maxiosize, int level) +{ + struct gz_stream *s; int error; - if (bufsz < KERN_GZ_HDRLEN) - return (NULL); - if (mode != GZIO_DEFLATE) - return (NULL); - - s = gz_alloc(NULL, 1, sizeof(*s)); - s->gz_bufsz = bufsz; - s->gz_buffer = gz_alloc(NULL, 1, s->gz_bufsz); - s->gz_mode = mode; - s->gz_cb = cb; - s->gz_arg = arg; + s = gz_alloc(NULL, 1, roundup2(sizeof(*s), PAGE_SIZE)); + s->gz_buffer = gz_alloc(NULL, 1, maxiosize); + s->gz_bufsz = maxiosize; s->gz_stream.zalloc = gz_alloc; s->gz_stream.zfree = gz_free; @@ -85,98 +119,57 @@ gzio_init(gzio_cb cb, enum gzio_mode mode, size_t bufsz, int level, void *arg) if (error != 0) goto fail; - gzio_reset(s); + gz_reset(s); return (s); fail: - gz_free(NULL, s->gz_buffer); gz_free(NULL, s); return (NULL); } -void -gzio_reset(struct gzio_stream *s) +static void +gz_reset(void *stream) { + struct gz_stream *s; uint8_t *hdr; + const size_t hdrlen = 10; - (void)deflateReset(&s->gz_stream); - + s = stream; s->gz_off = 0; s->gz_crc = ~0U; + (void)deflateReset(&s->gz_stream); s->gz_stream.avail_out = s->gz_bufsz; s->gz_stream.next_out = s->gz_buffer; /* Write the gzip header to the output buffer. */ hdr = s->gz_buffer; - memset(hdr, 0, KERN_GZ_HDRLEN); - hdr[0] = KERN_GZ_MAGIC1; - hdr[1] = KERN_GZ_MAGIC2; + memset(hdr, 0, hdrlen); + hdr[0] = 0x1f; + hdr[1] = 0x8b; hdr[2] = Z_DEFLATED; hdr[9] = OS_CODE; - s->gz_stream.next_out += KERN_GZ_HDRLEN; - s->gz_stream.avail_out -= KERN_GZ_HDRLEN; -} - -int -gzio_write(struct gzio_stream *s, void *data, u_int len) -{ - - return (gz_write(s, data, len, Z_NO_FLUSH)); -} - -int -gzio_flush(struct gzio_stream *s) -{ - - return (gz_write(s, NULL, 0, Z_FINISH)); -} - -void -gzio_fini(struct gzio_stream *s) -{ - - (void)deflateEnd(&s->gz_stream); - gz_free(NULL, s->gz_buffer); - gz_free(NULL, s); -} - -static void * -gz_alloc(void *arg __unused, u_int n, u_int sz) -{ - - /* - * Memory for zlib state is allocated using M_NODUMP since it may be - * used to compress a kernel dump, and we don't want zlib to attempt to - * compress its own state. - */ - return (malloc(n * sz, M_GZIO, M_WAITOK | M_ZERO | M_NODUMP)); -} - -static void -gz_free(void *arg __unused, void *ptr) -{ - - free(ptr, M_GZIO); + s->gz_stream.next_out += hdrlen; + s->gz_stream.avail_out -= hdrlen; } static int -gz_write(struct gzio_stream *s, void *buf, u_int len, int zflag) +gz_write(void *stream, void *data, size_t len, compressor_cb_t cb, + void *arg) { - uint8_t trailer[KERN_GZ_TRAILERLEN]; + struct gz_stream *s; + uint8_t trailer[8]; size_t room; - int error, zerror; + int error, zerror, zflag; - KASSERT(zflag == Z_FINISH || zflag == Z_NO_FLUSH, - ("unexpected flag %d", zflag)); - KASSERT(s->gz_mode == GZIO_DEFLATE, - ("invalid stream mode %d", s->gz_mode)); + s = stream; + zflag = data == NULL ? Z_FINISH : Z_NO_FLUSH; if (len > 0) { s->gz_stream.avail_in = len; - s->gz_stream.next_in = buf; - s->gz_crc = crc32_raw(buf, len, s->gz_crc); + s->gz_stream.next_in = data; + s->gz_crc = crc32_raw(data, len, s->gz_crc); } else s->gz_crc ^= ~0U; @@ -202,14 +195,13 @@ gz_write(struct gzio_stream *s, void *buf, u_int len, int zflag) ((uint32_t *)trailer)[0] = s->gz_crc; ((uint32_t *)trailer)[1] = s->gz_stream.total_in; - room = MIN(KERN_GZ_TRAILERLEN, + room = MIN(sizeof(trailer), s->gz_bufsz - len); memcpy(s->gz_buffer + len, trailer, room); len += room; } - error = s->gz_cb(s->gz_buffer, len, s->gz_off, - s->gz_arg); + error = cb(s->gz_buffer, len, s->gz_off, arg); if (error != 0) break; @@ -221,13 +213,103 @@ gz_write(struct gzio_stream *s, void *buf, u_int len, int zflag) * If we couldn't pack the trailer into the output * buffer, write it out now. */ - if (zerror == Z_STREAM_END && room < KERN_GZ_TRAILERLEN) - error = s->gz_cb(trailer + room, - KERN_GZ_TRAILERLEN - room, s->gz_off, - s->gz_arg); + if (zerror == Z_STREAM_END && room < sizeof(trailer)) + error = cb(trailer + room, + sizeof(trailer) - room, s->gz_off, arg); } } while (zerror != Z_STREAM_END && (zflag == Z_FINISH || s->gz_stream.avail_in > 0)); return (error); } + +static void +gz_fini(void *stream) +{ + struct gz_stream *s; + + s = stream; + (void)deflateEnd(&s->gz_stream); + gz_free(NULL, s->gz_buffer); + gz_free(NULL, s); +} + +struct compressor_methods gzip_methods = { + .format = COMPRESS_GZIP, + .init = gz_init, + .reset = gz_reset, + .write = gz_write, + .fini = gz_fini, +}; +DATA_SET(compressors, gzip_methods); + +#endif /* GZIO */ + +bool +compressor_avail(int format) +{ + struct compressor_methods **iter; + + SET_FOREACH(iter, compressors) { + if ((*iter)->format == format) + return (true); + } + return (false); +} + +struct compressor * +compressor_init(compressor_cb_t cb, int format, size_t maxiosize, int level, + void *arg) +{ + struct compressor_methods **iter; + struct compressor *s; + void *priv; + + SET_FOREACH(iter, compressors) { + if ((*iter)->format == format) + break; + } + if (iter == NULL) + return (NULL); + + priv = (*iter)->init(maxiosize, level); + if (priv == NULL) + return (NULL); + + s = malloc(sizeof(*s), M_COMPRESS, M_WAITOK | M_ZERO); + s->methods = (*iter); + s->priv = priv; + s->cb = cb; + s->arg = arg; + return (s); +} + +void +compressor_reset(struct compressor *stream) +{ + + stream->methods->reset(stream->priv); +} + +int +compressor_write(struct compressor *stream, void *data, size_t len) +{ + + return (stream->methods->write(stream->priv, data, len, stream->cb, + stream->arg)); +} + +int +compressor_flush(struct compressor *stream) +{ + + return (stream->methods->write(stream->priv, NULL, 0, stream->cb, + stream->arg)); +} + +void +compressor_fini(struct compressor *stream) +{ + + stream->methods->fini(stream->priv); +} diff --git a/sys/sys/gzio.h b/sys/sys/compressor.h similarity index 68% rename from sys/sys/gzio.h rename to sys/sys/compressor.h index eb4aecf4b5a8..9407b950d5a8 100644 --- a/sys/sys/gzio.h +++ b/sys/sys/compressor.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2014 Mark Johnston + * Copyright (c) 2014, 2017 Mark Johnston * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,25 +28,26 @@ * $FreeBSD$ */ -#ifndef _SYS__GZIO_H_ -#define _SYS__GZIO_H_ +#ifndef _SYS__COMPRESSOR_H_ +#define _SYS__COMPRESSOR_H_ #ifdef _KERNEL -enum gzio_mode { - GZIO_DEFLATE, -}; +/* Supported formats. */ +#define COMPRESS_GZIP 1 -typedef int (*gzio_cb)(void *, size_t, off_t, void *); +typedef int (*compressor_cb_t)(void *, size_t, off_t, void *); -struct gzio_stream; +struct compressor; -struct gzio_stream *gzio_init(gzio_cb cb, enum gzio_mode, size_t, int, void *); -void gzio_reset(struct gzio_stream *); -int gzio_write(struct gzio_stream *, void *, u_int); -int gzio_flush(struct gzio_stream *); -void gzio_fini(struct gzio_stream *); +bool compressor_avail(int format); +struct compressor *compressor_init(compressor_cb_t cb, int format, + size_t maxiosize, int level, void *arg); +void compressor_reset(struct compressor *stream); +int compressor_write(struct compressor *stream, void *data, + size_t len); +int compressor_flush(struct compressor *stream); +void compressor_fini(struct compressor *stream); #endif /* _KERNEL */ - -#endif /* _SYS__GZIO_H_ */ +#endif /* _SYS__COMPRESSOR_H_ */ diff --git a/sys/sys/conf.h b/sys/sys/conf.h index d41d4707aac7..be3dee3d3de7 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -339,8 +339,8 @@ struct dumperinfo { off_t mediasize; /* Space available in bytes. */ void *blockbuf; /* Buffer for padding shorter dump blocks */ off_t dumpoff; /* Offset of ongoing kernel dump. */ - struct kerneldumpcrypto *kdc; /* Kernel dump crypto. */ - struct kerneldumpgz *kdgz; /* Kernel dump compression. */ + struct kerneldumpcrypto *kdcrypto; /* Kernel dump crypto. */ + struct kerneldumpcomp *kdcomp; /* Kernel dump compression. */ }; extern int dumping; /* system is dumping */ diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h index 60c9b60a05d2..54c4020f70a5 100644 --- a/sys/sys/imgact.h +++ b/sys/sys/imgact.h @@ -96,8 +96,6 @@ struct sysentvec; struct thread; struct vmspace; -#define IMGACT_CORE_COMPRESS 0x01 - int exec_alloc_args(struct image_args *); int exec_check_permissions(struct image_params *); register_t *exec_copyout_strings(struct image_params *); From 329e7a8b51e0f6a9e621d6a812cc1b6081ad8474 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Tue, 9 Jan 2018 00:00:55 +0000 Subject: [PATCH 034/158] Protect against a possible NULL deference from an accessor function. Obtained from: Netflix --- sys/cam/cam_periph.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sys/cam/cam_periph.h b/sys/cam/cam_periph.h index a8f487400b6f..c48ed865cde7 100644 --- a/sys/cam/cam_periph.h +++ b/sys/cam/cam_periph.h @@ -202,7 +202,10 @@ int cam_periph_error(union ccb *ccb, cam_flags camflags, static __inline struct mtx * cam_periph_mtx(struct cam_periph *periph) { - return (xpt_path_mtx(periph->path)); + if (periph != NULL) + return (xpt_path_mtx(periph->path)); + else + return (NULL); } #define cam_periph_owned(periph) \ From 04e814aecd6a4d831c78c11826d5e8df06b914d5 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Tue, 9 Jan 2018 00:10:59 +0000 Subject: [PATCH 035/158] Don't hold the periph lock when calling into cam_periph_runccb() from the ada and da dump routines. This avoids difficult locking problems from needing to be handled. While it might seem like this would leave the periphs unprotected during dump, they were aleady at risk of unexpected removal due to the dump functions not keeping refcount state across the many calls that come in during a dump. This is an exercise for future work. Obtained from: Netflix --- sys/cam/ata/ata_da.c | 7 +------ sys/cam/cam_periph.c | 13 ++++--------- sys/cam/scsi/scsi_da.c | 7 +------ 3 files changed, 6 insertions(+), 21 deletions(-) diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c index ead4ba2f125b..fa88260c8b51 100644 --- a/sys/cam/ata/ata_da.c +++ b/sys/cam/ata/ata_da.c @@ -1062,15 +1062,12 @@ adadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t len dp = arg; periph = dp->d_drv1; softc = (struct ada_softc *)periph->softc; - cam_periph_lock(periph); secsize = softc->params.secsize; lba = offset / secsize; count = length / secsize; - if ((periph->flags & CAM_PERIPH_INVALID) != 0) { - cam_periph_unlock(periph); + if ((periph->flags & CAM_PERIPH_INVALID) != 0) return (ENXIO); - } memset(&ataio, 0, sizeof(ataio)); if (length > 0) { @@ -1098,7 +1095,6 @@ adadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t len if (error != 0) printf("Aborting dump due to I/O error.\n"); - cam_periph_unlock(periph); return (error); } @@ -1129,7 +1125,6 @@ adadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t len if (error != 0) xpt_print(periph->path, "Synchronize cache failed\n"); } - cam_periph_unlock(periph); return (error); } diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c index 3dacabd83cab..b9c3dcf76eea 100644 --- a/sys/cam/cam_periph.c +++ b/sys/cam/cam_periph.c @@ -1160,8 +1160,6 @@ cam_periph_runccb(union ccb *ccb, struct bintime ltime; int error; bool must_poll; - struct mtx *periph_mtx; - struct cam_periph *periph; uint32_t timeout = 1; starttime = NULL; @@ -1188,20 +1186,20 @@ cam_periph_runccb(union ccb *ccb, * stopped for dumping, except when we call doadump from ddb. While the * scheduler is running in this case, we still need to poll the I/O to * avoid sleeping waiting for the ccb to complete. + * + * XXX To avoid locking problems, dumping/polling callers must call + * without a periph lock held. */ must_poll = dumping; ccb->ccb_h.cbfcnp = cam_periph_done; - periph = xpt_path_periph(ccb->ccb_h.path); - periph_mtx = cam_periph_mtx(periph); /* * If we're polling, then we need to ensure that we have ample resources - * in the periph. We also need to drop the periph lock while we're polling. + * in the periph. * cam_periph_error can reschedule the ccb by calling xpt_action and returning * ERESTART, so we have to effect the polling in the do loop below. */ if (must_poll) { - mtx_unlock(periph_mtx); timeout = xpt_poll_setup(ccb); } @@ -1227,9 +1225,6 @@ cam_periph_runccb(union ccb *ccb, } while (error == ERESTART); } - if (must_poll) - mtx_lock(periph_mtx); - if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { cam_release_devq(ccb->ccb_h.path, /* relsim_flags */0, diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c index 16085cf8390b..742c01738e1a 100644 --- a/sys/cam/scsi/scsi_da.c +++ b/sys/cam/scsi/scsi_da.c @@ -1647,13 +1647,10 @@ dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t leng dp = arg; periph = dp->d_drv1; softc = (struct da_softc *)periph->softc; - cam_periph_lock(periph); secsize = softc->params.secsize; - if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) { - cam_periph_unlock(periph); + if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) return (ENXIO); - } memset(&csio, 0, sizeof(csio)); if (length > 0) { @@ -1676,7 +1673,6 @@ dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t leng 0, SF_NO_RECOVERY | SF_NO_RETRY, NULL); if (error != 0) printf("Aborting dump due to I/O error.\n"); - cam_periph_unlock(periph); return (error); } @@ -1700,7 +1696,6 @@ dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t leng if (error != 0) xpt_print(periph->path, "Synchronize cache failed\n"); } - cam_periph_unlock(periph); return (error); } From bff0b56cdfd0a49275a7872da706cb2cf529eff8 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Tue, 9 Jan 2018 00:17:15 +0000 Subject: [PATCH 036/158] Don't hold the periph locks during dump. Obtained from: Netflix --- sys/cam/nvme/nvme_da.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sys/cam/nvme/nvme_da.c b/sys/cam/nvme/nvme_da.c index 5c3c89b4b32f..4ed62cb58612 100644 --- a/sys/cam/nvme/nvme_da.c +++ b/sys/cam/nvme/nvme_da.c @@ -388,15 +388,12 @@ ndadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t len dp = arg; periph = dp->d_drv1; softc = (struct nda_softc *)periph->softc; - cam_periph_lock(periph); secsize = softc->disk->d_sectorsize; lba = offset / secsize; count = length / secsize; - if ((periph->flags & CAM_PERIPH_INVALID) != 0) { - cam_periph_unlock(periph); + if ((periph->flags & CAM_PERIPH_INVALID) != 0) return (ENXIO); - } /* xpt_get_ccb returns a zero'd allocation for the ccb, mimic that here */ memset(&nvmeio, 0, sizeof(nvmeio)); @@ -408,7 +405,6 @@ ndadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t len 0, SF_NO_RECOVERY | SF_NO_RETRY, NULL); if (error != 0) printf("Aborting dump due to I/O error %d.\n", error); - cam_periph_unlock(periph); return (error); } @@ -422,7 +418,6 @@ ndadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t len 0, SF_NO_RECOVERY | SF_NO_RETRY, NULL); if (error != 0) xpt_print(periph->path, "flush cmd failed\n"); - cam_periph_unlock(periph); return (error); } From 4b42739b37b32e9932839ae261ba932726d09f10 Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Tue, 9 Jan 2018 03:28:24 +0000 Subject: [PATCH 037/158] Fix Zstd kernel build with GCC 4.2 By disabling the -Winline warning. Fixes the powerpc and sparc64 build after r327706. Note: MIPS and RISCV builds still broken due to absense of __ctzdi2 (aka __builtin_ctzll) in their libgcc or libcompiler-rt libraries. Reported by: markj Sponsored by: Dell EMC Isilon --- sys/conf/kern.pre.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk index 090b914d116a..6d27b4ca9c85 100644 --- a/sys/conf/kern.pre.mk +++ b/sys/conf/kern.pre.mk @@ -133,7 +133,7 @@ NORMAL_FWO= ${LD} -b binary --no-warn-mismatch -d -warn-common -r \ -m ${LD_EMULATION} -o ${.TARGET} ${.ALLSRC:M*.fw} # for ZSTD in the kernel (include zstd/lib/freebsd before other CFLAGS) -ZSTD_C= ${CC} -c -DZSTD_HEAPMODE=1 -I$S/contrib/zstd/lib/freebsd ${CFLAGS} -I$S/contrib/zstd/lib -I$S/contrib/zstd/lib/common ${WERROR} -Wno-missing-prototypes ${PROF} ${.IMPSRC} +ZSTD_C= ${CC} -c -DZSTD_HEAPMODE=1 -I$S/contrib/zstd/lib/freebsd ${CFLAGS} -I$S/contrib/zstd/lib -I$S/contrib/zstd/lib/common ${WERROR} -Wno-inline -Wno-missing-prototypes ${PROF} ${.IMPSRC} # Common for dtrace / zfs CDDL_CFLAGS= -DFREEBSD_NAMECACHE -nostdinc -I$S/cddl/compat/opensolaris -I$S/cddl/contrib/opensolaris/uts/common -I$S -I$S/cddl/contrib/opensolaris/common ${CFLAGS} -Wno-unknown-pragmas -Wno-missing-prototypes -Wno-undef -Wno-strict-prototypes -Wno-cast-qual -Wno-parentheses -Wno-redundant-decls -Wno-missing-braces -Wno-uninitialized -Wno-unused -Wno-inline -Wno-switch -Wno-pointer-arith -Wno-unknown-pragmas From bdb0c28072cc57c6afb0db5fa07c2af3ba5316fa Mon Sep 17 00:00:00 2001 From: Cy Schubert Date: Tue, 9 Jan 2018 06:43:58 +0000 Subject: [PATCH 038/158] When growing the state, also grow the seed array. Otherwise memory that was not allocated will be accessed. This necessitated refactoring state seed allocation from ipf_state_soft_init() into a new common ipf_state_seed_alloc() function as it is now also used by ipf_state_rehash() when changing the size of the state hash table in addition to by ipf_state_soft_init() during initialization. According to Christos Zoulas : The bug was encountered by a NetBSD vendor who's customer machines had large ipfilter states. The bug was reliably triggered by resizing the state variables using "ipf -T". Submitted by: Christos Zoulas Reviewed by: delphij, rgrimes Obtained from: NetBSD ip_state.c CVS revs r1.9 and r1.10 MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D13755 --- sys/contrib/ipfilter/netinet/ip_state.c | 61 +++++++++++++++++-------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/sys/contrib/ipfilter/netinet/ip_state.c b/sys/contrib/ipfilter/netinet/ip_state.c index 17eab6619155..1bf190715340 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.c +++ b/sys/contrib/ipfilter/netinet/ip_state.c @@ -301,6 +301,32 @@ ipf_state_soft_destroy(softc, arg) KFREE(softs); } +static void * +ipf_state_seed_alloc(u_int state_size, u_int state_max) +{ + u_int i; + u_long *state_seed; + KMALLOCS(state_seed, u_long *, state_size * sizeof(*state_seed)); + if (state_seed == NULL) + return NULL; + + for (i = 0; i < state_size; i++) { + /* + * XXX - ipf_state_seed[X] should be a random number of sorts. + */ +#if FREEBSD_GE_REV(400000) + state_seed[i] = arc4random(); +#else + state_seed[i] = ((u_long)state_seed + i) * state_size; + state_seed[i] ^= 0xa5a55a5a; + state_seed[i] *= (u_long)state_seed; + state_seed[i] ^= 0x5a5aa5a5; + state_seed[i] *= state_max; +#endif + } + return state_seed; +} + /* ------------------------------------------------------------------------ */ /* Function: ipf_state_soft_init */ @@ -333,27 +359,11 @@ ipf_state_soft_init(softc, arg) bzero((char *)softs->ipf_state_table, softs->ipf_state_size * sizeof(ipstate_t *)); - KMALLOCS(softs->ipf_state_seed, u_long *, - softs->ipf_state_size * sizeof(*softs->ipf_state_seed)); + softs->ipf_state_seed = ipf_state_seed_alloc(softs->ipf_state_size, + softs->ipf_state_max); if (softs->ipf_state_seed == NULL) return -2; - for (i = 0; i < softs->ipf_state_size; i++) { - /* - * XXX - ipf_state_seed[X] should be a random number of sorts. - */ -#if FREEBSD_GE_REV(400000) - softs->ipf_state_seed[i] = arc4random(); -#else - softs->ipf_state_seed[i] = ((u_long)softs->ipf_state_seed + i) * - softs->ipf_state_size; - softs->ipf_state_seed[i] ^= 0xa5a55a5a; - softs->ipf_state_seed[i] *= (u_long)softs->ipf_state_seed; - softs->ipf_state_seed[i] ^= 0x5a5aa5a5; - softs->ipf_state_seed[i] *= softs->ipf_state_max; -#endif - } - KMALLOCS(softs->ipf_state_stats.iss_bucketlen, u_int *, softs->ipf_state_size * sizeof(u_int)); if (softs->ipf_state_stats.iss_bucketlen == NULL) @@ -5259,6 +5269,7 @@ ipf_state_rehash(softc, t, p) { ipf_state_softc_t *softs = softc->ipf_state_soft; ipstate_t **newtab, *is; + u_long *newseed; u_int *bucketlens; u_int maxbucket; u_int newsize; @@ -5285,6 +5296,14 @@ ipf_state_rehash(softc, t, p) return ENOMEM; } + newseed = ipf_state_seed_alloc(newsize, softs->ipf_state_max); + if (newseed == NULL) { + KFREES(bucketlens, newsize * sizeof(*bucketlens)); + KFREES(newtab, newsize * sizeof(*newtab)); + IPFERROR(100037); + return ENOMEM; + } + for (maxbucket = 0, i = newsize; i > 0; i >>= 1) maxbucket++; maxbucket *= 2; @@ -5300,6 +5319,12 @@ ipf_state_rehash(softc, t, p) } softs->ipf_state_table = newtab; + if (softs->ipf_state_seed != NULL) { + KFREES(softs->ipf_state_seed, + softs->ipf_state_size * sizeof(*softs->ipf_state_seed)); + } + softs->ipf_state_seed = newseed; + if (softs->ipf_state_stats.iss_bucketlen != NULL) { KFREES(softs->ipf_state_stats.iss_bucketlen, softs->ipf_state_size * sizeof(u_int)); From d85e65cb352e71a33827bf748c197260403fb344 Mon Sep 17 00:00:00 2001 From: Eitan Adler Date: Tue, 9 Jan 2018 06:51:41 +0000 Subject: [PATCH 039/158] ldconfig(8): use .Nm instead of 'ldconfig' --- sbin/ldconfig/ldconfig.8 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sbin/ldconfig/ldconfig.8 b/sbin/ldconfig/ldconfig.8 index d4b985ba0f24..3734d24ff152 100644 --- a/sbin/ldconfig/ldconfig.8 +++ b/sbin/ldconfig/ldconfig.8 @@ -159,9 +159,10 @@ file. In particular, the .Ev LD_LIBRARY_PATH is not used to search for libraries. -Thus, the role of ldconfig is dual. -In -addition to building a set of hints for quick lookup, it also serves to +Thus, the role of +.Nm +is dual. +In addition to building a set of hints for quick lookup, it also serves to specify the trusted collection of directories from which shared objects can be safely loaded. .Sh FILES From 377f88fb087452abfb6beb066c318b4085c09eca Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 9 Jan 2018 10:33:11 +0000 Subject: [PATCH 040/158] Postpone the disassotiation of the background write buffer with devvp so that buf_complete() sees fully constructed buffer. This is a NOP right now, but will be needed by the forthcoming SU change. Reported and tested by: pho Reviewed by: mckusick Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/ufs/ffs/ffs_vfsops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 8449fddae2db..2a63ee74b654 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -2045,7 +2045,6 @@ ffs_backgroundwritedone(struct buf *bp) /* * Process dependencies then return any unfinished ones. */ - pbrelvp(bp); if (!LIST_EMPTY(&bp->b_dep) && (bp->b_ioflags & BIO_ERROR) == 0) buf_complete(bp); #ifdef SOFTUPDATES @@ -2058,6 +2057,7 @@ ffs_backgroundwritedone(struct buf *bp) */ bp->b_flags |= B_NOCACHE; bp->b_flags &= ~B_CACHE; + pbrelvp(bp); /* * Prevent brelse() from trying to keep and re-dirtying bp on From e51e3c7e73a9c284f2f071d0868ef74de0bf19b6 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 9 Jan 2018 10:44:17 +0000 Subject: [PATCH 041/158] When handling write completion, take SU lock around calls to handle_written_XXX() in case of processing the buffer with an error. Tested by: pho (as part of the bigger patch) Reviewed by: mckusick (as part of the bigger patch) Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/ufs/ffs/ffs_softdep.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index f10631b773c4..04d8220f130e 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -10978,12 +10978,17 @@ softdep_disk_write_complete(bp) struct freeblks *freeblks; struct buf *sbp; + if ((wk = LIST_FIRST(&bp->b_dep)) == NULL) + return; + ump = VFSTOUFS(wk->wk_mp); + /* * If an error occurred while doing the write, then the data * has not hit the disk and the dependencies cannot be processed. * But we do have to go through and roll forward any dependencies * that were rolled back before the disk write. */ + ACQUIRE_LOCK(ump); if ((bp->b_ioflags & BIO_ERROR) != 0 && (bp->b_flags & B_INVAL) == 0) { LIST_FOREACH(wk, &bp->b_dep, wk_list) { switch (wk->wk_type) { @@ -11011,18 +11016,15 @@ softdep_disk_write_complete(bp) continue; } } + FREE_LOCK(ump); return; } - if ((wk = LIST_FIRST(&bp->b_dep)) == NULL) - return; - ump = VFSTOUFS(wk->wk_mp); LIST_INIT(&reattach); /* * This lock must not be released anywhere in this code segment. */ sbp = NULL; owk = NULL; - ACQUIRE_LOCK(ump); while ((wk = LIST_FIRST(&bp->b_dep)) != NULL) { WORKLIST_REMOVE(wk); atomic_add_long(&dep_write[wk->wk_type], 1); From c999b435276a735c04758efb44cfb41b2427ab22 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 9 Jan 2018 10:51:44 +0000 Subject: [PATCH 042/158] Generalize the fix from r322757 and apply it to several more places. The code accesses bp->b_dep without owning the ufs mount softdep lock, which makes it possible for the derefenced workitem to be freed in parallel. In particular, the deallocate_dependencies(), softdep_disk_io_initiation() and softdep_disk_write_complete() are affected. Move the code to safely calculate ump from the buffer with dependencies into the helper softdep_bp_to_mp() and use it for all found cases. Tested by: pho (as part of the bigger patch) Reviewed by: mckusick (as part of the bigger patch) Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/ufs/ffs/ffs_softdep.c | 79 ++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 04d8220f130e..d6076020190b 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -906,6 +906,7 @@ static int request_cleanup(struct mount *, int); static int softdep_request_cleanup_flush(struct mount *, struct ufsmount *); static void schedule_cleanup(struct mount *); static void softdep_ast_cleanup_proc(struct thread *); +static struct ufsmount *softdep_bp_to_mp(struct buf *bp); static int process_worklist_item(struct mount *, int, int); static void process_removes(struct vnode *); static void process_truncates(struct vnode *); @@ -7249,9 +7250,9 @@ deallocate_dependencies(bp, freeblks, off) struct worklist *wk, *wkn; struct ufsmount *ump; - if ((wk = LIST_FIRST(&bp->b_dep)) == NULL) + ump = softdep_bp_to_mp(bp); + if (ump == NULL) goto done; - ump = VFSTOUFS(wk->wk_mp); ACQUIRE_LOCK(ump); LIST_FOREACH_SAFE(wk, &bp->b_dep, wk_list, wkn) { switch (wk->wk_type) { @@ -9976,9 +9977,9 @@ softdep_disk_io_initiation(bp) panic("softdep_disk_io_initiation: Writing buffer with " "background write in progress: %p", bp); - if ((wk = LIST_FIRST(&bp->b_dep)) == NULL) + ump = softdep_bp_to_mp(bp); + if (ump == NULL) return; - ump = VFSTOUFS(wk->wk_mp); marker.wk_type = D_LAST + 1; /* Not a normal workitem */ PHOLD(curproc); /* Don't swap out kernel stack */ @@ -10978,9 +10979,9 @@ softdep_disk_write_complete(bp) struct freeblks *freeblks; struct buf *sbp; - if ((wk = LIST_FIRST(&bp->b_dep)) == NULL) + ump = softdep_bp_to_mp(bp); + if (ump == NULL) return; - ump = VFSTOUFS(wk->wk_mp); /* * If an error occurred while doing the write, then the data @@ -11020,8 +11021,9 @@ softdep_disk_write_complete(bp) return; } LIST_INIT(&reattach); + /* - * This lock must not be released anywhere in this code segment. + * Ump SU lock must not be released anywhere in this code segment. */ sbp = NULL; owk = NULL; @@ -13895,6 +13897,39 @@ softdep_freework(wkhd) FREE_LOCK(ump); } +static struct ufsmount * +softdep_bp_to_mp(bp) + struct buf *bp; +{ + struct mount *mp; + struct vnode *vp; + + if (LIST_EMPTY(&bp->b_dep)) + return (NULL); + vp = bp->b_vp; + + /* + * The ump mount point is stable after we get a correct + * pointer, since bp is locked and this prevents unmount from + * proceeding. But to get to it, we cannot dereference bp->b_dep + * head wk_mp, because we do not yet own SU ump lock and + * workitem might be freed while dereferenced. + */ +retry: + if (vp->v_type == VCHR) { + VI_LOCK(vp); + mp = vp->v_type == VCHR ? vp->v_rdev->si_mountpt : NULL; + VI_UNLOCK(vp); + if (mp == NULL) + goto retry; + } else if (vp->v_type == VREG || vp->v_type == VDIR) { + mp = vp->v_mount; + } else { + return (NULL); + } + return (VFSTOUFS(mp)); +} + /* * Function to determine if the buffer has outstanding dependencies * that will cause a roll-back if the buffer is written. If wantcount @@ -13918,36 +13953,12 @@ softdep_count_dependencies(bp, wantcount) struct newblk *newblk; struct mkdir *mkdir; struct diradd *dap; - struct vnode *vp; - struct mount *mp; int i, retval; + ump = softdep_bp_to_mp(bp); + if (ump == NULL) + return (0); retval = 0; - if (LIST_EMPTY(&bp->b_dep)) - return (0); - vp = bp->b_vp; - - /* - * The ump mount point is stable after we get a correct - * pointer, since bp is locked and this prevents unmount from - * proceed. But to get to it, we cannot dereference bp->b_dep - * head wk_mp, because we do not yet own SU ump lock and - * workitem might be freed while dereferenced. - */ -retry: - if (vp->v_type == VCHR) { - VI_LOCK(vp); - mp = vp->v_type == VCHR ? vp->v_rdev->si_mountpt : NULL; - VI_UNLOCK(vp); - if (mp == NULL) - goto retry; - } else if (vp->v_type == VREG) { - mp = vp->v_mount; - } else { - return (0); - } - ump = VFSTOUFS(mp); - ACQUIRE_LOCK(ump); LIST_FOREACH(wk, &bp->b_dep, wk_list) { switch (wk->wk_type) { From fac38b96d28b76df4c238919173c3afcd9b4cb8b Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Tue, 9 Jan 2018 13:42:08 +0000 Subject: [PATCH 043/158] usbdevs: add ASMedia vendor ID MFC after: 1 week --- sys/dev/usb/usbdevs | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index 0cf74bc63616..4433216eee88 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -707,6 +707,7 @@ vendor WCH2 0x1a86 QinHeng Electronics vendor STELERA 0x1a8d Stelera Wireless vendor SEL 0x1adb Schweitzer Engineering Laboratories vendor CORSAIR 0x1b1c Corsair +vendor ASM 0x1b21 ASMedia Technology vendor MATRIXORBITAL 0x1b3d Matrix Orbital vendor OVISLINK 0x1b75 OvisLink vendor TML 0x1b91 The Mobility Lab From be5060c11619cd7fc1e1521e93317f9c3769f89c Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Tue, 9 Jan 2018 13:43:04 +0000 Subject: [PATCH 044/158] zfs_mount: restore a bit of ifdef-out illumos code And correctly mark the end of the replacement FreeBSD code. MFC after: 1 week --- .../opensolaris/uts/common/fs/zfs/zfs_vfsops.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c index a8cacd4039e7..430ee528cdd2 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c @@ -1629,13 +1629,21 @@ zfs_mount(vfs_t *vfsp) * can be interrogated. */ if ((uap->flags & MS_DATA) && uap->datalen > 0) + return (SET_ERROR(EINVAL)); + + /* + * Get the objset name (the "special" mount argument). + */ + if (error = pn_get(uap->spec, fromspace, &spn)) + return (error); + + osname = spn.pn_path; #else /* !illumos */ if (!prison_allow(td->td_ucred, PR_ALLOW_MOUNT_ZFS)) return (SET_ERROR(EPERM)); if (vfs_getopt(vfsp->mnt_optnew, "from", (void **)&osname, NULL)) return (SET_ERROR(EINVAL)); -#endif /* illumos */ /* * If full-owner-access is enabled and delegated administration is @@ -1645,6 +1653,7 @@ zfs_mount(vfs_t *vfsp) dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr) != ECANCELED) { secpolicy_fs_mount_clearopts(cr, vfsp); } +#endif /* illumos */ /* * Check for mount privilege? From 091da2dfa536fe4ae8ac1e5c807296196b6d2184 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Tue, 9 Jan 2018 14:22:18 +0000 Subject: [PATCH 045/158] vmm/svm: contigmalloc of the whole svm_softc is excessive This is a followup to r307903. struct svm_softc takes more than 200 kilobytes while what we really need is 3 contiguous pages for I/O permission map and 2 contiguous pages for MSR permission map. Other physically mapped structures have a size of a single page, so a proper alignment is sufficient for their correct mapping. Thus, only the permission maps are allocated with contigmalloc now, the softc is allocated with a regular malloc. Additionally, this commit adds a check that malloc returns memory with the expected page alignment and that contigmalloc does not fail. Unfortunately, at present svm_vminit() is expected to always succeed and there is no way to report an error. So, a contigmalloc failure leads to a panic. We should probably fix this. MFC after: 2 weeks --- sys/amd64/vmm/amd/svm.c | 23 ++++++++++++++++++----- sys/amd64/vmm/amd/svm_softc.h | 6 +++--- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/sys/amd64/vmm/amd/svm.c b/sys/amd64/vmm/amd/svm.c index 5aa17d0fbb1e..fa5b5793839e 100644 --- a/sys/amd64/vmm/amd/svm.c +++ b/sys/amd64/vmm/amd/svm.c @@ -517,15 +517,26 @@ svm_vminit(struct vm *vm, pmap_t pmap) vm_paddr_t msrpm_pa, iopm_pa, pml4_pa; int i; - svm_sc = contigmalloc(sizeof (*svm_sc), M_SVM, M_WAITOK | M_ZERO, - 0, ~(vm_paddr_t)0, PAGE_SIZE, 0); + svm_sc = malloc(sizeof (*svm_sc), M_SVM, M_WAITOK | M_ZERO); + if (((uintptr_t)svm_sc & PAGE_MASK) != 0) + panic("malloc of svm_softc not aligned on page boundary"); + + svm_sc->msr_bitmap = contigmalloc(SVM_MSR_BITMAP_SIZE, M_SVM, + M_WAITOK, 0, ~(vm_paddr_t)0, PAGE_SIZE, 0); + if (svm_sc->msr_bitmap == NULL) + panic("contigmalloc of SVM MSR bitmap failed"); + svm_sc->iopm_bitmap = contigmalloc(SVM_IO_BITMAP_SIZE, M_SVM, + M_WAITOK, 0, ~(vm_paddr_t)0, PAGE_SIZE, 0); + if (svm_sc->iopm_bitmap == NULL) + panic("contigmalloc of SVM IO bitmap failed"); + svm_sc->vm = vm; svm_sc->nptp = (vm_offset_t)vtophys(pmap->pm_pml4); /* * Intercept read and write accesses to all MSRs. */ - memset(svm_sc->msr_bitmap, 0xFF, sizeof(svm_sc->msr_bitmap)); + memset(svm_sc->msr_bitmap, 0xFF, SVM_MSR_BITMAP_SIZE); /* * Access to the following MSRs is redirected to the VMCB when the @@ -553,7 +564,7 @@ svm_vminit(struct vm *vm, pmap_t pmap) svm_msr_rd_ok(svm_sc->msr_bitmap, MSR_EFER); /* Intercept access to all I/O ports. */ - memset(svm_sc->iopm_bitmap, 0xFF, sizeof(svm_sc->iopm_bitmap)); + memset(svm_sc->iopm_bitmap, 0xFF, SVM_IO_BITMAP_SIZE); iopm_pa = vtophys(svm_sc->iopm_bitmap); msrpm_pa = vtophys(svm_sc->msr_bitmap); @@ -2043,7 +2054,9 @@ svm_vmcleanup(void *arg) { struct svm_softc *sc = arg; - contigfree(sc, sizeof (*sc), M_SVM); + contigfree(sc->iopm_bitmap, SVM_IO_BITMAP_SIZE, M_SVM); + contigfree(sc->msr_bitmap, SVM_MSR_BITMAP_SIZE, M_SVM); + free(sc, M_SVM); } static register_t * diff --git a/sys/amd64/vmm/amd/svm_softc.h b/sys/amd64/vmm/amd/svm_softc.h index de0c3f78903d..9377bf529a8c 100644 --- a/sys/amd64/vmm/amd/svm_softc.h +++ b/sys/amd64/vmm/amd/svm_softc.h @@ -56,13 +56,13 @@ struct svm_vcpu { * SVM softc, one per virtual machine. */ struct svm_softc { - uint8_t iopm_bitmap[SVM_IO_BITMAP_SIZE]; /* shared by all vcpus */ - uint8_t msr_bitmap[SVM_MSR_BITMAP_SIZE]; /* shared by all vcpus */ uint8_t apic_page[VM_MAXCPU][PAGE_SIZE]; struct svm_vcpu vcpu[VM_MAXCPU]; vm_offset_t nptp; /* nested page table */ + uint8_t *iopm_bitmap; /* shared by all vcpus */ + uint8_t *msr_bitmap; /* shared by all vcpus */ struct vm *vm; -} __aligned(PAGE_SIZE); +}; CTASSERT((offsetof(struct svm_softc, nptp) & PAGE_MASK) == 0); From 4bb409fb8d8757d8c3cc0221d65150a57e444139 Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Tue, 9 Jan 2018 14:33:05 +0000 Subject: [PATCH 046/158] Add a framework to install CPU errata on arm64. Each erratum can encode a mask and value to compare with the Main ID Register. If these match then a function is called to handle the installation of the erratum workaround. No errata are currently handled, however this will change soon in a future commit. MFC after: 1 week Sponsored by: DARPA, AFRL --- sys/arm64/arm64/cpu_errata.c | 68 ++++++++++++++++++++++++++++++++++++ sys/arm64/arm64/machdep.c | 1 + sys/arm64/arm64/mp_machdep.c | 1 + sys/arm64/include/cpu.h | 1 + sys/conf/files.arm64 | 1 + 5 files changed, 72 insertions(+) create mode 100644 sys/arm64/arm64/cpu_errata.c diff --git a/sys/arm64/arm64/cpu_errata.c b/sys/arm64/arm64/cpu_errata.c new file mode 100644 index 000000000000..915c6453d643 --- /dev/null +++ b/sys/arm64/arm64/cpu_errata.c @@ -0,0 +1,68 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2018 Andrew Turner + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include + +typedef void (cpu_quirk_install)(void); +struct cpu_quirks { + cpu_quirk_install *quirk_install; + u_int midr_mask; + u_int midr_value; +}; + +static cpu_quirk_install install_psci_bp_hardening; + +static struct cpu_quirks cpu_quirks[] = { +}; + +void +install_cpu_errata(void) +{ + u_int midr; + size_t i; + + midr = get_midr(); + + for (i = 0; i < nitems(cpu_quirks); i++) { + if ((midr & cpu_quirks[i].midr_mask) == + cpu_quirks[i].midr_value) { + cpu_quirks[i].quirk_install(); + } + } +} diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c index 157081d68dd4..8df2d3226d8a 100644 --- a/sys/arm64/arm64/machdep.c +++ b/sys/arm64/arm64/machdep.c @@ -172,6 +172,7 @@ cpu_startup(void *dummy) undef_init(); identify_cpu(); + install_cpu_errata(); vm_ksubmap_init(&kmi); bufinit(); diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c index 2b2d7f8fbe2c..9ea0a2ba400c 100644 --- a/sys/arm64/arm64/mp_machdep.c +++ b/sys/arm64/arm64/mp_machdep.c @@ -282,6 +282,7 @@ init_secondary(uint64_t cpu) * runtime chip identification. */ identify_cpu(); + install_cpu_errata(); intr_pic_init_secondary(); diff --git a/sys/arm64/include/cpu.h b/sys/arm64/include/cpu.h index 51e86c1e7671..a35584def97b 100644 --- a/sys/arm64/include/cpu.h +++ b/sys/arm64/include/cpu.h @@ -150,6 +150,7 @@ void cpu_halt(void) __dead2; void cpu_reset(void) __dead2; void fork_trampoline(void); void identify_cpu(void); +void install_cpu_errata(void); void print_cpu_features(u_int); void swi_vm(void *v); diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index b4df2843e93a..a4e86bc35ffb 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -96,6 +96,7 @@ arm64/arm64/bzero.S standard arm64/arm64/clock.c standard arm64/arm64/copyinout.S standard arm64/arm64/copystr.c standard +arm64/arm64/cpu_errata.c standard arm64/arm64/cpufunc_asm.S standard arm64/arm64/db_disasm.c optional ddb arm64/arm64/db_interface.c optional ddb From 8ab09f8a4e7e47cc83bcec1b599741f53c6b6172 Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Tue, 9 Jan 2018 15:57:09 +0000 Subject: [PATCH 047/158] Add a function to find the PSCI version the firmware implements from outside the PSCI driver. MFC after: 1 week Sponsored by: DARPA, AFRL --- sys/dev/psci/psci.c | 13 +++++++++++-- sys/dev/psci/psci.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/sys/dev/psci/psci.c b/sys/dev/psci/psci.c index 83c9bdb9a1a4..36f5db9427cb 100644 --- a/sys/dev/psci/psci.c +++ b/sys/dev/psci/psci.c @@ -314,7 +314,7 @@ psci_attach(device_t dev, psci_initfn_t psci_init) } static int -psci_get_version(struct psci_softc *sc) +_psci_get_version(struct psci_softc *sc) { uint32_t fnid; @@ -326,6 +326,15 @@ psci_get_version(struct psci_softc *sc) return (PSCI_RETVAL_NOT_SUPPORTED); } +int +psci_get_version(void) +{ + + if (psci_softc == NULL) + return (PSCI_RETVAL_NOT_SUPPORTED); + return (_psci_get_version(psci_softc)); +} + #ifdef FDT static int psci_fdt_callfn(psci_callfn_t *callfn) @@ -487,7 +496,7 @@ psci_v0_2_init(device_t dev) sc->psci_fnids[PSCI_FN_SYSTEM_OFF] = PSCI_FNID_SYSTEM_OFF; sc->psci_fnids[PSCI_FN_SYSTEM_RESET] = PSCI_FNID_SYSTEM_RESET; - version = psci_get_version(sc); + version = _psci_get_version(sc); if (version == PSCI_RETVAL_NOT_SUPPORTED) return (1); diff --git a/sys/dev/psci/psci.h b/sys/dev/psci/psci.h index af777bb6c380..8f6759137c5d 100644 --- a/sys/dev/psci/psci.h +++ b/sys/dev/psci/psci.h @@ -41,6 +41,7 @@ int psci_cpu_on(unsigned long, unsigned long, unsigned long); int psci_hvc_despatch(register_t, register_t, register_t, register_t); int psci_smc_despatch(register_t, register_t, register_t, register_t); +int psci_get_version(void); /* * PSCI return codes. From 9c5a11488681b049d796ee42634d21a7bd436adf Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Tue, 9 Jan 2018 16:11:33 +0000 Subject: [PATCH 048/158] Remove ccbque.h from i386/isa. inline ccbque.h into scsi_low.h. The file isn't MD, so shouldn't live in i386/isa. It's only used by scsi_low, so move it there so no new clients accidentally grow. scsi_low may not even still work, and the locking here is still SPL based. CAM should do the right thing, but I've received no reports of these cards still working. At least it compiles still and there's one fewer files in sys/i386/isa. While I'm here, ansify and de-splize. CCB_MWANTED appears to be a clear-only flag, but I've not changed that. Differential Review: https://reviews.freebsd.org/D13672 --- sys/cam/scsi/scsi_low.c | 59 +++++++++++++++++++ sys/cam/scsi/scsi_low.h | 56 +++++++++++++++++- sys/i386/isa/ccbque.h | 124 ---------------------------------------- 3 files changed, 114 insertions(+), 125 deletions(-) delete mode 100644 sys/i386/isa/ccbque.h diff --git a/sys/cam/scsi/scsi_low.c b/sys/cam/scsi/scsi_low.c index daf088901a2e..eb65969bc93d 100644 --- a/sys/cam/scsi/scsi_low.c +++ b/sys/cam/scsi/scsi_low.c @@ -87,6 +87,65 @@ __FBSDID("$FreeBSD$"); #include +/************************************************************** + * CCB Macros + **************************************************************/ + +/* (II) static allocated memory */ +#define GENERIC_CCB_STATIC_ALLOC(DEV, CCBTYPE) \ +static struct CCBTYPE##que CCBTYPE##que; + +/* (III) functions */ +#define GENERIC_CCB(DEV, CCBTYPE, CHAIN) \ + \ +void \ +DEV##_init_ccbque(int count) \ +{ \ + if (CCBTYPE##que.maxccb == 0) \ + TAILQ_INIT(&CCBTYPE##que.CCBTYPE##tab); \ + CCBTYPE##que.maxccb += count; \ +} \ + \ +struct CCBTYPE * \ +DEV##_get_ccb(void) \ +{ \ + struct CCBTYPE *cb; \ + \ + if (CCBTYPE##que.count < CCBTYPE##que.maxccb) \ + { \ + CCBTYPE##que.count ++; \ + cb = TAILQ_FIRST(&(CCBTYPE##que.CCBTYPE##tab)); \ + if (cb != NULL) { \ + TAILQ_REMOVE(&CCBTYPE##que.CCBTYPE##tab, cb, CHAIN);\ + goto out; \ + } else { \ + cb = malloc(sizeof(*cb), M_DEVBUF, M_NOWAIT | M_ZERO); \ + if (cb != NULL) \ + goto out; \ + } \ + CCBTYPE##que.count --; \ + } \ + \ + cb = NULL; \ + \ +out: \ + return cb; \ +} \ + \ +void \ +DEV##_free_ccb(struct CCBTYPE *cb) \ +{ \ + \ + TAILQ_INSERT_TAIL(&CCBTYPE##que.CCBTYPE##tab, cb, CHAIN); \ + CCBTYPE##que.count --; \ + \ + if (CCBTYPE##que.flags & CCB_MWANTED) \ + { \ + CCBTYPE##que.flags &= ~CCB_MWANTED; \ + wakeup ((caddr_t) &CCBTYPE##que.count); \ + } \ +} + /************************************************************** * Constants **************************************************************/ diff --git a/sys/cam/scsi/scsi_low.h b/sys/cam/scsi/scsi_low.h index 809ca2a8b943..c6c1776de71a 100644 --- a/sys/cam/scsi/scsi_low.h +++ b/sys/cam/scsi/scsi_low.h @@ -57,7 +57,61 @@ #include #include -#include +/************ ccbque.h ***************************/ + +/* $NetBSD$ */ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * [NetBSD for NEC PC98 series] + * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +/* + * Common command control queue funcs. + * Written by N. Honda. + */ + +#define CCB_MWANTED 0x01 + +/* (I) structure and prototype */ +#define GENERIC_CCB_ASSERT(DEV, CCBTYPE) \ +TAILQ_HEAD(CCBTYPE##tab, CCBTYPE); \ +struct CCBTYPE##que { \ + struct CCBTYPE##tab CCBTYPE##tab; \ + int count; \ + int maxccb; \ + u_int flags; \ +}; \ + \ +void DEV##_init_ccbque(int); \ +struct CCBTYPE *DEV##_get_ccb(void); \ +void DEV##_free_ccb(struct CCBTYPE *); /******** functions macro ************************/ diff --git a/sys/i386/isa/ccbque.h b/sys/i386/isa/ccbque.h deleted file mode 100644 index 36def7034af5..000000000000 --- a/sys/i386/isa/ccbque.h +++ /dev/null @@ -1,124 +0,0 @@ -/* $NetBSD$ */ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * [NetBSD for NEC PC98 series] - * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ -/* - * Common command control queue funcs. - * Written by N. Honda. - */ - -#ifndef _CCBQUE_H_ -#define _CCBQUE_H_ - -#define CCB_MWANTED 0x01 - -/* (I) structure and prototype */ -#define GENERIC_CCB_ASSERT(DEV, CCBTYPE) \ -TAILQ_HEAD(CCBTYPE##tab, CCBTYPE); \ -struct CCBTYPE##que { \ - struct CCBTYPE##tab CCBTYPE##tab; \ - int count; \ - int maxccb; \ - u_int flags; \ -}; \ - \ -void DEV##_init_ccbque(int); \ -struct CCBTYPE *DEV##_get_ccb(void); \ -void DEV##_free_ccb(struct CCBTYPE *); - -/* (II) static allocated memory */ -#define GENERIC_CCB_STATIC_ALLOC(DEV, CCBTYPE) \ -static struct CCBTYPE##que CCBTYPE##que; - -/* (III) functions */ -#define GENERIC_CCB(DEV, CCBTYPE, CHAIN) \ - \ -void \ -DEV##_init_ccbque(count) \ - int count; \ -{ \ - if (CCBTYPE##que.maxccb == 0) \ - TAILQ_INIT(&CCBTYPE##que.CCBTYPE##tab); \ - CCBTYPE##que.maxccb += count; \ -} \ - \ -struct CCBTYPE * \ -DEV##_get_ccb() \ -{ \ - struct CCBTYPE *cb; \ - int s = splcam(); \ - \ - if (CCBTYPE##que.count < CCBTYPE##que.maxccb) \ - { \ - CCBTYPE##que.count ++; \ - cb = TAILQ_FIRST(&(CCBTYPE##que.CCBTYPE##tab)); \ - if (cb != NULL) \ - { \ - TAILQ_REMOVE(&CCBTYPE##que.CCBTYPE##tab, cb, CHAIN);\ - goto out; \ - } \ - else \ - { \ - cb = malloc(sizeof(*cb), M_DEVBUF, M_NOWAIT); \ - if (cb != NULL) \ - { \ - bzero(cb, sizeof(*cb)); \ - goto out; \ - } \ - } \ - CCBTYPE##que.count --; \ - } \ - \ - cb = NULL; \ - \ -out: \ - splx(s); \ - return cb; \ -} \ - \ -void \ -DEV##_free_ccb(cb) \ - struct CCBTYPE *cb; \ -{ \ - int s = splcam(); \ - \ - TAILQ_INSERT_TAIL(&CCBTYPE##que.CCBTYPE##tab, cb, CHAIN); \ - CCBTYPE##que.count --; \ - \ - if (CCBTYPE##que.flags & CCB_MWANTED) \ - { \ - CCBTYPE##que.flags &= ~CCB_MWANTED; \ - wakeup ((caddr_t) &CCBTYPE##que.count); \ - } \ - splx(s); \ -} -#endif /* !_CCBQUE_H_ */ From f489be8de9020938be33b033ca66863237cbcd23 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 9 Jan 2018 16:28:45 +0000 Subject: [PATCH 049/158] Fix year. Noted by: oshogbo Sponsored by: The FreeBSD Foundation MFC after: 3 days --- share/man/man4/smp.4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/man/man4/smp.4 b/share/man/man4/smp.4 index b2c73c2b50ae..33597ee8ec2b 100644 --- a/share/man/man4/smp.4 +++ b/share/man/man4/smp.4 @@ -23,7 +23,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 6, 2017 +.Dd January 6, 2018 .Dt SMP 4 .Os .Sh NAME From dc8ab16ecc7c2110eb88f3e8427d8b23db8de6b6 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Tue, 9 Jan 2018 16:42:24 +0000 Subject: [PATCH 050/158] Consolidate two identical copies of sysres_ids. --- sys/dev/acpica/acpi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index ab907e922741..cda93b6bc2c8 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -95,6 +95,9 @@ struct acpi_interface { int num; }; +static char *sysres_ids[] = { "PNP0C01", "PNP0C02", NULL }; +static char *pcilink_ids[] = { "PNP0C0F", NULL }; + /* Global mutex for locking access to the ACPI subsystem. */ struct mtx acpi_mutex; struct callout acpi_sleep_timer; @@ -1168,7 +1171,6 @@ acpi_sysres_alloc(device_t dev) struct resource_list *rl; struct resource_list_entry *rle; struct rman *rm; - char *sysres_ids[] = { "PNP0C01", "PNP0C02", NULL }; device_t *children; int child_count, i; @@ -1216,9 +1218,6 @@ acpi_sysres_alloc(device_t dev) return (0); } -static char *pcilink_ids[] = { "PNP0C0F", NULL }; -static char *sysres_ids[] = { "PNP0C01", "PNP0C02", NULL }; - /* * Reserve declared resources for devices found during attach once system * resources have been allocated. From a60f45a0d555dedbf52a610d6071a4bb4fb07769 Mon Sep 17 00:00:00 2001 From: Kristof Provost Date: Tue, 9 Jan 2018 19:02:42 +0000 Subject: [PATCH 051/158] pf tests: Fix pft_ping.py to work with scapy 2.3.3 Scapy requires the Raw payload to be a string, which was not the case. This caused the pft_ping.py script to fail, which in turn caused the test to fail. --- tests/sys/netpfil/pf/pft_ping.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sys/netpfil/pf/pft_ping.py b/tests/sys/netpfil/pf/pft_ping.py index 98bce2e0716f..cfd366bbbdcc 100644 --- a/tests/sys/netpfil/pf/pft_ping.py +++ b/tests/sys/netpfil/pf/pft_ping.py @@ -79,7 +79,7 @@ def ping(send_if, dst_ip, args): ether = sp.Ether() ip = sp.IP(dst=dst_ip) icmp = sp.ICMP(type='echo-request') - raw = sp.Raw(PAYLOAD_MAGIC) + raw = sp.Raw(str(PAYLOAD_MAGIC)) if args.send_tos: ip.tos = int(args.send_tos[0]) From 566a135bd59f00bb1e0d1347cd75a1c07291c176 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Tue, 9 Jan 2018 19:41:10 +0000 Subject: [PATCH 052/158] Add XHCI support to powerpc64 GENERIC. This is useful to get input devices supported on newer POWER hardware and in graphical VMs run on the same, which are typically XHCI-only. The 32-bit GENERIC kernel, which does not run on hardware made in the last decade and is unlikely to encounter XHCI devices, is left unchanged. PR: kern/224940 Submitted by: Gustavo Romero MFC after: 1 week --- sys/powerpc/conf/GENERIC64 | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/powerpc/conf/GENERIC64 b/sys/powerpc/conf/GENERIC64 index b1b1948e67e0..1fc1a1d36530 100644 --- a/sys/powerpc/conf/GENERIC64 +++ b/sys/powerpc/conf/GENERIC64 @@ -173,6 +173,7 @@ options USB_DEBUG # enable debug msgs device uhci # UHCI PCI->USB interface device ohci # OHCI PCI->USB interface device ehci # EHCI PCI->USB interface +device xhci # XHCI PCI->USB interface device usb # USB Bus (required) device uhid # "Human Interface Devices" device ukbd # Keyboard From da7a237fac75cb9f3cd02ca4ba8b6bdbb8263ea8 Mon Sep 17 00:00:00 2001 From: Cy Schubert Date: Tue, 9 Jan 2018 20:35:58 +0000 Subject: [PATCH 053/158] USNO and possibly others have misinterpreted the maining of the leapseconds last-update field and incorrectly increment it when changing the file even though the leapsecond data has not changed. For instance, if a leapsecond file is obtained from USNO, when it expires it will not be replaced by a newer file from other sources because it has an incorrect later last-update (version). This corrects r304780. PR: 225029 Submitted by: ian MFC after: 3 days --- etc/rc.d/ntpd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/etc/rc.d/ntpd b/etc/rc.d/ntpd index 051f857399c5..5391aecffd58 100755 --- a/etc/rc.d/ntpd +++ b/etc/rc.d/ntpd @@ -144,9 +144,9 @@ ntpd_fetch_leapfile() { done ntp_ver_no_tmp=$(get_ntp_leapfile_ver $ntp_tmp_leapfile) ntp_expiry_tmp=$(get_ntp_leapfile_expiry $ntp_tmp_leapfile) - if [ "$ntp_ver_no_tmp" -gt "$ntp_ver_no_db" -o \ - "$ntp_ver_no_tmp" -eq "$ntp_ver_no_db" -a \ - "$ntp_expiry_tmp" -gt "$ntp_expiry_db" ]; then + if [ "$ntp_expiry_tmp" -gt "$ntp_expiry_db" -o \ + "$ntp_expiry_tmp" -eq "$ntp_expiry_db" -a \ + "$ntp_ver_no_tmp" -gt "$ntp_ver_no_db" ]; then $verbose using $url as $ntp_db_leapfile mv $ntp_tmp_leapfile $ntp_db_leapfile else From ad7a1fc6c5335fcf53fc0b91a8d06f50a70de4fc Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Tue, 9 Jan 2018 20:53:30 +0000 Subject: [PATCH 054/158] Fix Zstd x86 kernel build with -march= Disable Zstd experimental support for __BMI__ intrinsics, when built with -march=foo supporting such intrinsics, to avoid attempting to include immintrin.h. If a later Zstd marks the support non-experimental, we may want to revisit this approach. Submitted by: jkim Reported by: jkim, "Oliver Hartmann" --- sys/conf/kern.pre.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk index 6d27b4ca9c85..18f65e17047e 100644 --- a/sys/conf/kern.pre.mk +++ b/sys/conf/kern.pre.mk @@ -133,7 +133,7 @@ NORMAL_FWO= ${LD} -b binary --no-warn-mismatch -d -warn-common -r \ -m ${LD_EMULATION} -o ${.TARGET} ${.ALLSRC:M*.fw} # for ZSTD in the kernel (include zstd/lib/freebsd before other CFLAGS) -ZSTD_C= ${CC} -c -DZSTD_HEAPMODE=1 -I$S/contrib/zstd/lib/freebsd ${CFLAGS} -I$S/contrib/zstd/lib -I$S/contrib/zstd/lib/common ${WERROR} -Wno-inline -Wno-missing-prototypes ${PROF} ${.IMPSRC} +ZSTD_C= ${CC} -c -DZSTD_HEAPMODE=1 -I$S/contrib/zstd/lib/freebsd ${CFLAGS} -I$S/contrib/zstd/lib -I$S/contrib/zstd/lib/common ${WERROR} -Wno-inline -Wno-missing-prototypes ${PROF} -U__BMI__ ${.IMPSRC} # Common for dtrace / zfs CDDL_CFLAGS= -DFREEBSD_NAMECACHE -nostdinc -I$S/cddl/compat/opensolaris -I$S/cddl/contrib/opensolaris/uts/common -I$S -I$S/cddl/contrib/opensolaris/common ${CFLAGS} -Wno-unknown-pragmas -Wno-missing-prototypes -Wno-undef -Wno-strict-prototypes -Wno-cast-qual -Wno-parentheses -Wno-redundant-decls -Wno-missing-braces -Wno-uninitialized -Wno-unused -Wno-inline -Wno-switch -Wno-pointer-arith -Wno-unknown-pragmas From 324efdfba2e42dcc83ddd4549548f42eefd0b86b Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Tue, 9 Jan 2018 21:02:39 +0000 Subject: [PATCH 055/158] Add Pull Request to the Subversion commit template Reviewed by: emaste MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D13178 --- contrib/subversion/subversion/svn/util.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrib/subversion/subversion/svn/util.c b/contrib/subversion/subversion/svn/util.c index fb017e9d4e95..4cfa618f70d6 100644 --- a/contrib/subversion/subversion/svn/util.c +++ b/contrib/subversion/subversion/svn/util.c @@ -352,6 +352,7 @@ static const char *prefixes[] = { "Relnotes:", "Security:", "Sponsored by:", + "Pull Request:", "Differential Revision:", }; @@ -443,6 +444,7 @@ svn_cl__get_log_message(const char **log_msg, if (sponsored_by != NULL) svn_stringbuf_appendcstr(default_msg, sponsored_by); svn_stringbuf_appendcstr(default_msg, APR_EOL_STR); + svn_stringbuf_appendcstr(default_msg, "Pull Request:\t" APR_EOL_STR); svn_stringbuf_appendcstr(default_msg, "Differential Revision:\t" APR_EOL_STR); svn_stringbuf_appendcstr(default_msg, EDITOR_EOF_PREFIX); svn_stringbuf_appendcstr(default_msg, APR_EOL_STR); @@ -458,6 +460,7 @@ svn_cl__get_log_message(const char **log_msg, svn_stringbuf_appendcstr(default_msg, "> Relnotes: Set to 'yes' for mention in release notes." APR_EOL_STR); svn_stringbuf_appendcstr(default_msg, "> Security: Vulnerability reference (one per line) or description." APR_EOL_STR); svn_stringbuf_appendcstr(default_msg, "> Sponsored by: If the change was sponsored by an organization." APR_EOL_STR); + svn_stringbuf_appendcstr(default_msg, "> Pull Request: https://github.com/freebsd/freebsd/pull/### (*full* GitHub URL needed)." APR_EOL_STR); svn_stringbuf_appendcstr(default_msg, "> Differential Revision: https://reviews.freebsd.org/D### (*full* phabric URL needed)." APR_EOL_STR); svn_stringbuf_appendcstr(default_msg, "> Empty fields above will be automatically removed." APR_EOL_STR); svn_stringbuf_appendcstr(default_msg, APR_EOL_STR); From 15fd9bda9c671ba7f1a6b179b44b95c99986ed61 Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Tue, 9 Jan 2018 21:12:53 +0000 Subject: [PATCH 056/158] Bump version for r327597 adding cpucontrol -e support --- sys/sys/param.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/sys/param.h b/sys/sys/param.h index 723f7c0c4bd5..9cdd445c6c34 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 1200054 /* Master, propagated to newvers */ +#define __FreeBSD_version 1200055 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, From 7c1374d5f5762630b042771c2c7328ebe2837577 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Tue, 9 Jan 2018 21:23:16 +0000 Subject: [PATCH 057/158] Hold a refcount on the periph while running the allocation queue. This will allow sub-transports to release their probe pseudo-device with fewer convoluted restrictions. Obtained from: Netflix --- sys/cam/cam_xpt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index e9f11d6d2ffa..4a5b43b38922 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -3383,6 +3383,7 @@ xpt_run_allocq(struct cam_periph *periph, int sleep) cam_periph_assert(periph, MA_OWNED); if (periph->periph_allocating) return; + cam_periph_doacquire(periph); periph->periph_allocating = 1; CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_run_allocq(%p)\n", periph)); device = periph->path->device; @@ -3426,6 +3427,7 @@ xpt_run_allocq(struct cam_periph *periph, int sleep) if (ccb != NULL) xpt_release_ccb(ccb); periph->periph_allocating = 0; + cam_periph_release_locked(periph); } static void From 876f6a6af20c97bfb8f09f39d63dac29409c3346 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Tue, 9 Jan 2018 21:24:05 +0000 Subject: [PATCH 058/158] Release the held refcount on the probe periph when probing is done, now that r327741 lets this happen. Obtained from: Netflix --- sys/cam/nvme/nvme_xpt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sys/cam/nvme/nvme_xpt.c b/sys/cam/nvme/nvme_xpt.c index fa8f564e5d3f..3325bf3a3723 100644 --- a/sys/cam/nvme/nvme_xpt.c +++ b/sys/cam/nvme/nvme_xpt.c @@ -318,8 +318,7 @@ nvme_probe_start(struct cam_periph *periph, union ccb *start_ccb) xpt_done(start_ccb); } cam_periph_invalidate(periph); - /* Can't release periph since we hit a (possibly bogus) assertion */ -// cam_periph_release_locked(periph); + cam_periph_release_locked(periph); } static void From dd5edb11b1baeb84dace48400c866ba234b22c16 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Tue, 9 Jan 2018 22:48:13 +0000 Subject: [PATCH 059/158] Use the __result_use_check attribute also for reallocf(3). The GCC attribute causes a warning to be emitted if a caller of the function with this attribute does not use its return value. Unlike the traditional realloc, with reallocf(3) we don't have to check for NULL values but we still have to make sure the result is used. MFC after: 3 days --- include/stdlib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/stdlib.h b/include/stdlib.h index 56bb1566d58e..b2fc90934f85 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -304,7 +304,7 @@ int radixsort(const unsigned char **, int, const unsigned char *, unsigned); void *reallocarray(void *, size_t, size_t) __result_use_check __alloc_size(2) __alloc_size(3); -void *reallocf(void *, size_t) __alloc_size(2); +void *reallocf(void *, size_t) __result_use_check __alloc_size(2); int rpmatch(const char *); void setprogname(const char *); int sradixsort(const unsigned char **, int, const unsigned char *, From 8091e52b42d66daf20e049bb9a7d6c46182deb76 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 9 Jan 2018 23:57:29 +0000 Subject: [PATCH 060/158] Add a counter to track in-flight AIO requests using unmapped I/O. MFC after: 2 weeks Sponsored by: Chelsio Communications --- sys/kern/vfs_aio.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index 817a0d71641f..c4bed4ce9541 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -150,6 +150,11 @@ static int num_buf_aio = 0; SYSCTL_INT(_vfs_aio, OID_AUTO, num_buf_aio, CTLFLAG_RD, &num_buf_aio, 0, "Number of aio requests presently handled by the buf subsystem"); +static int num_unmapped_aio = 0; +SYSCTL_INT(_vfs_aio, OID_AUTO, num_unmapped_aio, CTLFLAG_RD, &num_unmapped_aio, + 0, + "Number of aio requests presently handled by unmapped I/O buffers"); + /* Number of async I/O processes in the process of being started */ /* XXX This should be local to aio_aqueue() */ static int num_aio_resv_start = 0; @@ -1305,6 +1310,7 @@ aio_qphysio(struct proc *p, struct kaiocb *job) bp->bio_ma_offset = poff; bp->bio_data = unmapped_buf; bp->bio_flags |= BIO_UNMAPPED; + atomic_add_int(&num_unmapped_aio, 1); } /* Perform transfer. */ @@ -2365,7 +2371,8 @@ aio_physwakeup(struct bio *bp) AIO_LOCK(ki); ki->kaio_buffer_count--; AIO_UNLOCK(ki); - } + } else + atomic_subtract_int(&num_unmapped_aio, 1); vm_page_unhold_pages(job->pages, job->npages); bp = job->bp; From 7e40918452b94a522b619c2a980bb281b2649857 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Wed, 10 Jan 2018 00:02:06 +0000 Subject: [PATCH 061/158] Simplify some logic by merging an if test with a subsequent switch. Specifically, in aio_queue_file() the code was doing this: if (opcode == LIO_SYNC) { ... } switch (opcode) { ... case LIO_SYNC: ... } This moves the body of the if statement into the LIO_SYNC case of the switch statement. MFC after: 2 weeks Sponsored by: Chelsio Communications --- sys/kern/vfs_aio.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index c4bed4ce9541..569cf96985ba 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -1736,7 +1736,13 @@ aio_queue_file(struct file *fp, struct kaiocb *job) return (EOPNOTSUPP); } - if (opcode == LIO_SYNC) { + switch (job->uaiocb.aio_lio_opcode) { + case LIO_READ: + case LIO_WRITE: + aio_schedule(job, aio_process_rw); + error = 0; + break; + case LIO_SYNC: AIO_LOCK(ki); TAILQ_FOREACH(job2, &ki->kaio_jobqueue, plist) { if (job2->fd_file == job->fd_file && @@ -1758,15 +1764,6 @@ aio_queue_file(struct file *fp, struct kaiocb *job) return (0); } AIO_UNLOCK(ki); - } - - switch (opcode) { - case LIO_READ: - case LIO_WRITE: - aio_schedule(job, aio_process_rw); - error = 0; - break; - case LIO_SYNC: aio_schedule(job, aio_process_sync); error = 0; break; From f05c4956605faafcfbdc5d2b0a39d5c84d33d748 Mon Sep 17 00:00:00 2001 From: "Jonathan T. Looney" Date: Wed, 10 Jan 2018 00:08:57 +0000 Subject: [PATCH 062/158] Fix backwards MD_VERIFY logic for md devices. If the MD_VERIFY flag is set, we should use O_VERIFY. If the MD_VERIFY flag is not set, we should not. Reviewed by: stevek Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D13814 --- sys/dev/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c index 3c4075094a19..e6d0afa2e883 100644 --- a/sys/dev/md/md.c +++ b/sys/dev/md/md.c @@ -1392,7 +1392,7 @@ mdcreate_vnode(struct md_s *sc, struct md_ioctl *mdio, struct thread *td) * set the FWRITE mask before trying to open the backing store. */ flags = FREAD | ((mdio->md_options & MD_READONLY) ? 0 : FWRITE) \ - | ((mdio->md_options & MD_VERIFY) ? 0 : O_VERIFY); + | ((mdio->md_options & MD_VERIFY) ? O_VERIFY : 0); NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, sc->file, td); error = vn_open(&nd, &flags, 0, NULL); if (error != 0) From f54c5606b3d06c7125cea71c4a12dfd934cbbc2d Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Wed, 10 Jan 2018 00:18:47 +0000 Subject: [PATCH 063/158] Allow the fast-path for disk AIO requests to fail requests. - If aio_qphysio() returns a non-zero error code, fail the request rather than queueing it to the AIO kproc pool to be retried via the slow path. Currently this means that if vm_fault_quick_hold_pages() reports an error, EFAULT is returned from the fast-path rather than retrying the request in the slow path where it will still fail with EFAULT. - If aio_qphysio() wishes to use the fast path for a device that doesn't support unmapped I/O but there are already the maximum number of such requests in flight, fail with EAGAIN as we do for other AIO resource limits rather than queueing the request to the AIO kproc pool. - Move the opcode check for aio_qphysio() out of the caller and into aio_qphysio() to simplify some logic and remove two goto's while here. It also uses a whitelist (only supported for LIO_READ / LIO_WRITE) rather than a blacklist (skipped for LIO_SYNC). PR: 217261 Submitted by: jkim (an earlier version) MFC after: 2 weeks Sponsored by: Chelsio Communications --- sys/kern/vfs_aio.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index 569cf96985ba..06d136a76390 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -1228,6 +1228,9 @@ aio_qphysio(struct proc *p, struct kaiocb *job) cb = &job->uaiocb; fp = job->fd_file; + if (!(cb->aio_lio_opcode == LIO_WRITE || + cb->aio_lio_opcode == LIO_READ)) + return (-1); if (fp == NULL || fp->f_type != DTYPE_VNODE) return (-1); @@ -1268,7 +1271,7 @@ aio_qphysio(struct proc *p, struct kaiocb *job) goto unref; } if (ki->kaio_buffer_count >= ki->kaio_ballowed_count) { - error = -1; + error = EAGAIN; goto unref; } @@ -1700,27 +1703,13 @@ aio_queue_file(struct file *fp, struct kaiocb *job) struct kaiocb *job2; struct vnode *vp; struct mount *mp; - int error, opcode; + int error; bool safe; ki = job->userproc->p_aioinfo; - opcode = job->uaiocb.aio_lio_opcode; - if (opcode == LIO_SYNC) - goto queueit; - - if ((error = aio_qphysio(job->userproc, job)) == 0) - goto done; -#if 0 - /* - * XXX: This means qphysio() failed with EFAULT. The current - * behavior is to retry the operation via fo_read/fo_write. - * Wouldn't it be better to just complete the request with an - * error here? - */ - if (error > 0) - goto done; -#endif -queueit: + error = aio_qphysio(job->userproc, job); + if (error >= 0) + return (error); safe = false; if (fp->f_type == DTYPE_VNODE) { vp = fp->f_vnode; @@ -1770,7 +1759,6 @@ aio_queue_file(struct file *fp, struct kaiocb *job) default: error = EINVAL; } -done: return (error); } From b93c58e168a888babfa342747d5215c86fc0d624 Mon Sep 17 00:00:00 2001 From: Ian Lepore Date: Wed, 10 Jan 2018 02:28:10 +0000 Subject: [PATCH 064/158] Bugfix: on RTC chips with a 32-bit binary counter, after reading the time, return immediately rather than falling through to the logic that reads BCD-encoded time. --- sys/dev/iicbus/ds13rtc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sys/dev/iicbus/ds13rtc.c b/sys/dev/iicbus/ds13rtc.c index 7a125c07ad1e..92e1128f1e44 100644 --- a/sys/dev/iicbus/ds13rtc.c +++ b/sys/dev/iicbus/ds13rtc.c @@ -364,9 +364,8 @@ ds13rtc_gettime(device_t dev, struct timespec *ts) /* If the chip counts time in binary, we just read and return it. */ if (sc->flags & SC_F_BINARY) { - if ((err = read_timeword(sc, &ts->tv_sec)) != 0) - return (err); ts->tv_nsec = 0; + return (read_timeword(sc, &ts->tv_sec)); } /* From b33d84e0059866244c61543e51621e93986c219f Mon Sep 17 00:00:00 2001 From: Ian Lepore Date: Wed, 10 Jan 2018 02:31:59 +0000 Subject: [PATCH 065/158] Bugfix: don't lose the am/pm mode flag when setting the time. Unlike most RTC chips that have a control register bit for am/pm mode, the DS13xx series uses one of the high bits in the hour register. Thus, when setting the time in am/pm mode, the am/pm mode flag has to be ORed into the hour. --- sys/dev/iicbus/ds13rtc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sys/dev/iicbus/ds13rtc.c b/sys/dev/iicbus/ds13rtc.c index 92e1128f1e44..09feba8c7be6 100644 --- a/sys/dev/iicbus/ds13rtc.c +++ b/sys/dev/iicbus/ds13rtc.c @@ -415,7 +415,7 @@ ds13rtc_settime(device_t dev, struct timespec *ts) struct time_regs tregs; struct ds13rtc_softc *sc; int err; - uint8_t cflag, statreg, pmflag; + uint8_t cflag, statreg, pmflags; sc = device_get_softc(dev); @@ -432,11 +432,12 @@ ds13rtc_settime(device_t dev, struct timespec *ts) clock_ts_to_ct(ts, &ct); /* If the chip is in AMPM mode deal with the PM flag. */ - pmflag = 0; + pmflags = 0; if (sc->flags & SC_F_AMPM) { + pmflags = DS13xx_B_HOUR_AMPM; if (ct.hour >= 12) { ct.hour -= 12; - pmflag = DS13xx_B_HOUR_PM; + pmflags |= DS13xx_B_HOUR_PM; } if (ct.hour == 0) ct.hour = 12; @@ -451,7 +452,7 @@ ds13rtc_settime(device_t dev, struct timespec *ts) tregs.sec = TOBCD(ct.sec); tregs.min = TOBCD(ct.min); - tregs.hour = TOBCD(ct.hour) | pmflag; + tregs.hour = TOBCD(ct.hour) | pmflags; tregs.day = TOBCD(ct.day); tregs.month = TOBCD(ct.mon) | cflag; tregs.year = TOBCD(ct.year % 100); From a369070143ee49ce8ac78fb74029cd76768b68d1 Mon Sep 17 00:00:00 2001 From: Ian Lepore Date: Wed, 10 Jan 2018 02:57:03 +0000 Subject: [PATCH 066/158] Convert a collection of unrelated bitwise flags to a collection of boolean vars in the softc. It makes the code more compact and readable, and actually uses less memory too. --- sys/dev/iicbus/ds13rtc.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/sys/dev/iicbus/ds13rtc.c b/sys/dev/iicbus/ds13rtc.c index 09feba8c7be6..328db926229f 100644 --- a/sys/dev/iicbus/ds13rtc.c +++ b/sys/dev/iicbus/ds13rtc.c @@ -162,16 +162,14 @@ struct time_regs { struct ds13rtc_softc { device_t dev; device_t busdev; - u_int flags; /* SC_F_* flags */ u_int chiptype; /* Type of DS13xx chip */ uint8_t secaddr; /* Address of seconds register */ uint8_t osfaddr; /* Address of register with OSF */ + bool use_ampm; /* Use AM/PM mode. */ + bool use_century; /* Use the Century bit. */ + bool is_binary_counter; /* Chip has 32-bit binary counter. */ }; -#define SC_F_BINARY (1u << 0) /* Time is 32-bit binary counter */ -#define SC_F_AMPM (1u << 1) /* Use PM flag in hours reg */ -#define SC_F_CENTURY (1u << 2) /* Use century bit */ - /* * We use the compat_data table to look up hint strings in the non-FDT case, so * define the struct locally when we don't get it from ofw_bus_subr.h. @@ -326,14 +324,14 @@ ds13rtc_start(void *arg) * chips that do AM/PM mode, the flag bit is in the hours register, * which is secaddr+2. */ - if ((sc->chiptype != TYPE_DS1340) && !(sc->flags & SC_F_BINARY)) { + if ((sc->chiptype != TYPE_DS1340) && !sc->is_binary_counter) { if (read_reg(sc, sc->secaddr + 2, &statreg) != 0) { device_printf(sc->dev, "cannot read RTC clock AM/PM bit\n"); return; } if (statreg & DS13xx_B_HOUR_AMPM) - sc->flags |= SC_F_AMPM; + sc->use_ampm = true; } /* @@ -363,7 +361,7 @@ ds13rtc_gettime(device_t dev, struct timespec *ts) return (EINVAL); /* hardware is good, time is not. */ /* If the chip counts time in binary, we just read and return it. */ - if (sc->flags & SC_F_BINARY) { + if (sc->is_binary_counter) { ts->tv_nsec = 0; return (read_timeword(sc, &ts->tv_sec)); } @@ -376,7 +374,7 @@ ds13rtc_gettime(device_t dev, struct timespec *ts) return (err); } - if (sc->flags & SC_F_AMPM) + if (sc->use_ampm) hourmask = DS13xx_M_12HOUR; else hourmask = DS13xx_M_24HOUR; @@ -389,7 +387,7 @@ ds13rtc_gettime(device_t dev, struct timespec *ts) ct.year = FROMBCD(tregs.year & DS13xx_M_YEAR); ct.nsec = 0; - if (sc->flags & SC_F_AMPM) { + if (sc->use_ampm) { if (ct.hour == 12) ct.hour = 0; if (tregs.hour & DS13xx_B_HOUR_PM) @@ -400,7 +398,7 @@ ds13rtc_gettime(device_t dev, struct timespec *ts) * If this chip has a century bit, honor it. Otherwise let * clock_ct_to_ts() infer the century from the 2-digit year. */ - if (sc->flags & SC_F_CENTURY) + if (sc->use_century) ct.year += (tregs.month & DS13xx_B_MONTH_CENTURY) ? 2000 : 1900; err = clock_ct_to_ts(&ct, ts); @@ -426,14 +424,14 @@ ds13rtc_settime(device_t dev, struct timespec *ts) ts->tv_sec -= utc_offset(); /* If the chip counts time in binary, store tv_sec and we're done. */ - if (sc->flags & SC_F_BINARY) + if (sc->is_binary_counter) return (write_timeword(sc, ts->tv_sec)); clock_ts_to_ct(ts, &ct); /* If the chip is in AMPM mode deal with the PM flag. */ pmflags = 0; - if (sc->flags & SC_F_AMPM) { + if (sc->use_ampm) { pmflags = DS13xx_B_HOUR_AMPM; if (ct.hour >= 12) { ct.hour -= 12; @@ -445,7 +443,7 @@ ds13rtc_settime(device_t dev, struct timespec *ts) /* If the chip has a century bit, set it as needed. */ cflag = 0; - if (sc->flags & SC_F_CENTURY) { + if (sc->use_century) { if (ct.year >= 2000) cflag |= DS13xx_B_MONTH_CENTURY; } @@ -572,7 +570,7 @@ ds13rtc_attach(device_t dev) case TYPE_DS1342: case TYPE_DS1375: sc->osfaddr = DS133x_R_STATUS; - sc->flags |= SC_F_CENTURY; + sc->use_century = true; break; case TYPE_DS1340: sc->osfaddr = DS1340_R_STATUS; @@ -581,7 +579,7 @@ ds13rtc_attach(device_t dev) case TYPE_DS1372: case TYPE_DS1374: sc->osfaddr = DS137x_R_STATUS; - sc->flags |= SC_F_BINARY; + sc->is_binary_counter = true; break; case TYPE_DS1388: sc->osfaddr = DS1388_R_STATUS; From 280f3264a42c79aa9ca6fd4c6bdb7b436f93a7f4 Mon Sep 17 00:00:00 2001 From: Mariusz Zaborski Date: Wed, 10 Jan 2018 02:57:22 +0000 Subject: [PATCH 067/158] Fix markup. --- lib/libcasper/services/cap_dns/cap_dns.3 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/libcasper/services/cap_dns/cap_dns.3 b/lib/libcasper/services/cap_dns/cap_dns.3 index 0b0837de4092..a8b2b0c77dfb 100644 --- a/lib/libcasper/services/cap_dns/cap_dns.3 +++ b/lib/libcasper/services/cap_dns/cap_dns.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 8, 2018 +.Dd January 10, 2018 .Dt CAP_DNS 3 .Os .Sh NAME @@ -59,7 +59,7 @@ The functions .Fn cap_gethostbyname2 , .Fn cep_gethostbyaddr and -.Xr cap_getnameinfo +.Fn cap_getnameinfo are respectively equivalent to .Xr gethostbyname 2 , .Xr gethostbyname2 2 , From aed882a9fbc87e8a3010447327d46aa5b1d53f6b Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 10 Jan 2018 05:06:21 +0000 Subject: [PATCH 068/158] Avoid referencing a possibly freed consumer after r327496. g_mirror_regular_request() may free the gmirror consumer for a disk if that disk is being disconnected, after which we must not dereference the consumer pointer. CID: 1384280 X-MFC with: r327496 --- sys/geom/mirror/g_mirror.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index e99018d791f8..abde8547bab5 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -906,16 +906,12 @@ g_mirror_done(struct bio *bp) } static void -g_mirror_regular_request_error(struct g_mirror_softc *sc, struct bio *bp) +g_mirror_regular_request_error(struct g_mirror_softc *sc, + struct g_mirror_disk *disk, struct bio *bp) { - struct g_mirror_disk *disk; - - disk = bp->bio_from->private; if (bp->bio_cmd == BIO_FLUSH && bp->bio_error == EOPNOTSUPP) return; - if (disk == NULL) - return; if ((disk->d_flags & G_MIRROR_DISK_FLAG_BROKEN) == 0) { disk->d_flags |= G_MIRROR_DISK_FLAG_BROKEN; @@ -942,6 +938,7 @@ g_mirror_regular_request_error(struct g_mirror_softc *sc, struct bio *bp) static void g_mirror_regular_request(struct g_mirror_softc *sc, struct bio *bp) { + struct g_mirror_disk *disk; struct bio *pbp; g_topology_assert_not(); @@ -952,7 +949,8 @@ g_mirror_regular_request(struct g_mirror_softc *sc, struct bio *bp) bp->bio_from->index--; if (bp->bio_cmd == BIO_WRITE || bp->bio_cmd == BIO_DELETE) sc->sc_writes--; - if (bp->bio_from->private == NULL) { + disk = bp->bio_from->private; + if (disk == NULL) { g_topology_lock(); g_mirror_kill_consumer(sc, bp->bio_from); g_topology_unlock(); @@ -999,7 +997,8 @@ g_mirror_regular_request(struct g_mirror_softc *sc, struct bio *bp) } else if (bp->bio_error != 0) { if (pbp->bio_error == 0) pbp->bio_error = bp->bio_error; - g_mirror_regular_request_error(sc, bp); + if (disk != NULL) + g_mirror_regular_request_error(sc, disk, bp); switch (pbp->bio_cmd) { case BIO_DELETE: case BIO_WRITE: From c371df4f47720a35d188e93b0f9c489592c32232 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Wed, 10 Jan 2018 05:29:02 +0000 Subject: [PATCH 069/158] Implement the ability to query NVME for its controller data so that it will be shown when issueing the 'camcontrol devlist' command. Obtained from: Netflix --- sbin/camcontrol/camcontrol.c | 59 ++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index 17e5d14aff06..c484d4375e00 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -275,6 +275,7 @@ camcontrol_optret getoption(struct camcontrol_opts *table, char *arg, static int getdevlist(struct cam_device *device); #endif /* MINIMALISTIC */ static int getdevtree(int argc, char **argv, char *combinedopt); +static int print_dev_nvme(struct device_match_result *dev_result, char *tmpstr); #ifndef MINIMALISTIC static int testunitready(struct cam_device *device, int task_attr, int retry_count, int timeout, int quiet); @@ -623,6 +624,12 @@ getdevtree(int argc, char **argv, char *combinedopt) sizeof(fw)); sprintf(tmpstr, "<%s %s %s %s>", vendor, product, revision, fw); + } else if (dev_result->protocol == PROTO_NVME) { + if (print_dev_nvme(dev_result, + &tmpstr[0]) != 0) { + skip_device = 1; + break; + } } else { sprintf(tmpstr, "<>"); } @@ -678,6 +685,58 @@ getdevtree(int argc, char **argv, char *combinedopt) return (error); } +static int +print_dev_nvme(struct device_match_result *dev_result, char *tmpstr) +{ + union ccb *ccb; + struct ccb_dev_advinfo *advi; + struct cam_device *dev; + struct nvme_controller_data cdata; + char vendor[64], product[64]; + + dev = cam_open_btl(dev_result->path_id, dev_result->target_id, + dev_result->target_lun, O_RDWR, NULL); + if (dev == NULL) { + warnx("%s", cam_errbuf); + return (1); + } + + ccb = cam_getccb(dev); + if (ccb == NULL) { + warnx("couldn't allocate CCB"); + cam_close_device(dev); + return (1); + } + + advi = &ccb->cdai; + advi->ccb_h.flags = CAM_DIR_IN; + advi->ccb_h.func_code = XPT_DEV_ADVINFO; + advi->flags = CDAI_FLAG_NONE; + advi->buftype = CDAI_TYPE_NVME_CNTRL; + advi->bufsiz = sizeof(struct nvme_controller_data); + advi->buf = (uint8_t *)&cdata; + + if (cam_send_ccb(dev, ccb) < 0) { + warn("error sending CAMIOCOMMAND ioctl"); + cam_freeccb(ccb); + cam_close_device(dev); + return(1); + } + if (advi->ccb_h.status != CAM_REQ_CMP) { + warnx("got CAM error %#x", advi->ccb_h.status); + cam_freeccb(ccb); + cam_close_device(dev); + return(1); + } + cam_strvis(vendor, cdata.mn, sizeof(cdata.mn), sizeof(vendor)); + cam_strvis(product, cdata.fr, sizeof(cdata.fr), sizeof(product)); + sprintf(tmpstr, "<%s %s>", vendor, product); + + cam_freeccb(ccb); + cam_close_device(dev); + return (0); +} + #ifndef MINIMALISTIC static int testunitready(struct cam_device *device, int task_attr, int retry_count, From f2592b12e904d9a97a37a8f571bd1ba770aebd16 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Wed, 10 Jan 2018 05:52:24 +0000 Subject: [PATCH 070/158] Refactor code related to 'camcontrol devlist' Obtained from: Netflix --- sbin/camcontrol/camcontrol.c | 139 +++++++++++++++++++++++------------ 1 file changed, 90 insertions(+), 49 deletions(-) diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index c484d4375e00..f35dfa453fd4 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -275,6 +275,11 @@ camcontrol_optret getoption(struct camcontrol_opts *table, char *arg, static int getdevlist(struct cam_device *device); #endif /* MINIMALISTIC */ static int getdevtree(int argc, char **argv, char *combinedopt); +static int print_dev_scsi(struct device_match_result *dev_result, char *tmpstr); +static int print_dev_ata(struct device_match_result *dev_result, char *tmpstr); +static int print_dev_semb(struct device_match_result *dev_result, char *tmpstr); +static int print_dev_mmcsd(struct device_match_result *dev_result, + char *tmpstr); static int print_dev_nvme(struct device_match_result *dev_result, char *tmpstr); #ifndef MINIMALISTIC static int testunitready(struct cam_device *device, int task_attr, @@ -555,8 +560,7 @@ getdevtree(int argc, char **argv, char *combinedopt) } case DEV_MATCH_DEVICE: { struct device_match_result *dev_result; - char vendor[16], product[48], revision[16]; - char fw[5], tmpstr[256]; + char tmpstr[256]; if (busonly == 1) break; @@ -573,57 +577,30 @@ getdevtree(int argc, char **argv, char *combinedopt) skip_device = 0; if (dev_result->protocol == PROTO_SCSI) { - cam_strvis(vendor, dev_result->inq_data.vendor, - sizeof(dev_result->inq_data.vendor), - sizeof(vendor)); - cam_strvis(product, - dev_result->inq_data.product, - sizeof(dev_result->inq_data.product), - sizeof(product)); - cam_strvis(revision, - dev_result->inq_data.revision, - sizeof(dev_result->inq_data.revision), - sizeof(revision)); - sprintf(tmpstr, "<%s %s %s>", vendor, product, - revision); + if (print_dev_scsi(dev_result, + &tmpstr[0]) != 0) { + skip_device = 1; + break; + } } else if (dev_result->protocol == PROTO_ATA || dev_result->protocol == PROTO_SATAPM) { - cam_strvis(product, - dev_result->ident_data.model, - sizeof(dev_result->ident_data.model), - sizeof(product)); - cam_strvis(revision, - dev_result->ident_data.revision, - sizeof(dev_result->ident_data.revision), - sizeof(revision)); - sprintf(tmpstr, "<%s %s>", product, - revision); - } else if (dev_result->protocol == PROTO_MMCSD) { - if (strlen(dev_result->mmc_ident_data.model) > 0) { - sprintf(tmpstr, "<%s>", dev_result->mmc_ident_data.model); - } else { - sprintf(tmpstr, "<%s card>", - dev_result->mmc_ident_data.card_features & CARD_FEATURE_SDIO ? "SDIO" : "unknown"); + if (print_dev_ata(dev_result, + &tmpstr[0]) != 0) { + skip_device = 1; + break; + } + } else if (dev_result->protocol == PROTO_MMCSD){ + if (print_dev_mmcsd(dev_result, + &tmpstr[0]) != 0) { + skip_device = 1; + break; } } else if (dev_result->protocol == PROTO_SEMB) { - struct sep_identify_data *sid; - - sid = (struct sep_identify_data *) - &dev_result->ident_data; - cam_strvis(vendor, sid->vendor_id, - sizeof(sid->vendor_id), - sizeof(vendor)); - cam_strvis(product, sid->product_id, - sizeof(sid->product_id), - sizeof(product)); - cam_strvis(revision, sid->product_rev, - sizeof(sid->product_rev), - sizeof(revision)); - cam_strvis(fw, sid->firmware_rev, - sizeof(sid->firmware_rev), - sizeof(fw)); - sprintf(tmpstr, "<%s %s %s %s>", - vendor, product, revision, fw); + if (print_dev_semb(dev_result, + &tmpstr[0]) != 0) { + skip_device = 1; + break; + } } else if (dev_result->protocol == PROTO_NVME) { if (print_dev_nvme(dev_result, &tmpstr[0]) != 0) { @@ -685,6 +662,70 @@ getdevtree(int argc, char **argv, char *combinedopt) return (error); } +static int +print_dev_scsi(struct device_match_result *dev_result, char *tmpstr) +{ + char vendor[16], product[48], revision[16]; + + cam_strvis(vendor, dev_result->inq_data.vendor, + sizeof(dev_result->inq_data.vendor), sizeof(vendor)); + cam_strvis(product, dev_result->inq_data.product, + sizeof(dev_result->inq_data.product), sizeof(product)); + cam_strvis(revision, dev_result->inq_data.revision, + sizeof(dev_result->inq_data.revision), sizeof(revision)); + sprintf(tmpstr, "<%s %s %s>", vendor, product, revision); + + return (0); +} + +static int +print_dev_ata(struct device_match_result *dev_result, char *tmpstr) +{ + char product[48], revision[16]; + + cam_strvis(product, dev_result->ident_data.model, + sizeof(dev_result->ident_data.model), sizeof(product)); + cam_strvis(revision, dev_result->ident_data.revision, + sizeof(dev_result->ident_data.revision), sizeof(revision)); + sprintf(tmpstr, "<%s %s>", product, revision); + + return (0); +} + +static int +print_dev_semb(struct device_match_result *dev_result, char *tmpstr) +{ + struct sep_identify_data *sid; + char vendor[16], product[48], revision[16], fw[5]; + + sid = (struct sep_identify_data *)&dev_result->ident_data; + cam_strvis(vendor, sid->vendor_id, + sizeof(sid->vendor_id), sizeof(vendor)); + cam_strvis(product, sid->product_id, + sizeof(sid->product_id), sizeof(product)); + cam_strvis(revision, sid->product_rev, + sizeof(sid->product_rev), sizeof(revision)); + cam_strvis(fw, sid->firmware_rev, + sizeof(sid->firmware_rev), sizeof(fw)); + sprintf(tmpstr, "<%s %s %s %s>", vendor, product, revision, fw); + + return (0); +} + +static int +print_dev_mmcsd(struct device_match_result *dev_result, char *tmpstr) +{ + + if (strlen(dev_result->mmc_ident_data.model) > 0) { + sprintf(tmpstr, "<%s>", dev_result->mmc_ident_data.model); + } else { + sprintf(tmpstr, "<%s card>", + dev_result->mmc_ident_data.card_features & + CARD_FEATURE_SDIO ? "SDIO" : "unknown"); + } + return (0); +} + static int print_dev_nvme(struct device_match_result *dev_result, char *tmpstr) { From 8038068a2a4ece31f5011c83a4fd6c25995a81d8 Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Wed, 10 Jan 2018 06:30:59 +0000 Subject: [PATCH 071/158] Finally, fix Zstd kernel build on MIPS and RISC-V Add an implementation of the intrinsics invoked by __builtin_ctz{,ll} and __builtin_clz{,ll}, and include this compilation unit on platforms that lack assembly intrinsics for those builtins (MIPS and RISC-V). Future cleanup work might involve bringing these into a mini libcompiler-rt for the standalone kernel environment. Or cleaning up the approach upstream takes for builtins in standalone environments (or just FreeBSD). For now, at least this builds, and doesn't require modifying the vendor code. Reported by: jeff, markj, mizhka Reviewed by: jhb (earlier version), rpokala (comment text earlier version) Sponsored by: Dell EMC Isilon --- sys/conf/files.mips | 3 + sys/conf/files.riscv | 3 + sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.c | 75 ++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.c diff --git a/sys/conf/files.mips b/sys/conf/files.mips index f09010d59c45..76bd63f5ebe8 100644 --- a/sys/conf/files.mips +++ b/sys/conf/files.mips @@ -112,3 +112,6 @@ cddl/compat/opensolaris/kern/opensolaris_atomic.c optional zfs | dtrace compile- cddl/dev/dtrace/mips/dtrace_asm.S optional dtrace compile-with "${DTRACE_S}" cddl/dev/dtrace/mips/dtrace_subr.c optional dtrace compile-with "${DTRACE_C}" cddl/dev/fbt/mips/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}" + +# Zstd +contrib/zstd/lib/freebsd/zstd_kfreebsd.c standard compile-with ${ZSTD_C} diff --git a/sys/conf/files.riscv b/sys/conf/files.riscv index aa035a6a7019..ed0157c6dfae 100644 --- a/sys/conf/files.riscv +++ b/sys/conf/files.riscv @@ -56,3 +56,6 @@ riscv/riscv/uio_machdep.c standard riscv/riscv/uma_machdep.c standard riscv/riscv/unwind.c optional ddb | kdtrace_hooks | stack riscv/riscv/vm_machdep.c standard + +# Zstd +contrib/zstd/lib/freebsd/zstd_kfreebsd.c standard compile-with ${ZSTD_C} diff --git a/sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.c b/sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.c new file mode 100644 index 000000000000..c41d582c2c31 --- /dev/null +++ b/sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.c @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2018 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. + * + * $FreeBSD$ + */ + +#include "zstd_kfreebsd.h" + +/* + * The kernel as a standalone target does not link against libgcc or + * libcompiler-rt. On platforms (e.g., MIPS and RISCV) that do not have a + * direct assembly implementation of the relevant builtin functions that zstd + * references, the compiler converts them into calls to the runtime library + * intrinsics. Since the kernel does not link against the runtime libraries, + * this results in a failure to link the kernel. + * + * The goal of the following definitions is to use supported kernel constructs + * to implement the same functionality, without adding diff to the Zstd contrib + * code. + * + * A subsequent enhancement might create a mini compiler-rt library for kernel + * use and move these over there instead. + */ + +/* Count trailing zeros */ +int +__ctzsi2(int x) +{ + if (x == 0) + return (sizeof(x) * NBBY); + return (ffs(x) - 1); +} + +long long +__ctzdi2(long long x) +{ + if (x == 0) + return (sizeof(x) * NBBY); + return (ffsll(x) - 1); +} + +/* Count leading zeros */ +int +__clzsi2(int x) +{ + return (sizeof(x) * NBBY - fls(x)); +} + +long long +__clzdi2(long long x) +{ + return (sizeof(x) * NBBY - flsll(x)); +} From bdd31a5287a4a1dfb7105043fbc8a95e92d8cac7 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Wed, 10 Jan 2018 14:58:58 +0000 Subject: [PATCH 072/158] Remove vestiges of digi(4) driver, first attempted in r305235 with more in r317426. There's nothing in the tree that references digiio.h (apart from digictl(8)), so no driver implements it. Since digictl(8) was only used to control digi(4) devices, it too should go. --- ObsoleteFiles.inc | 4 + sys/sys/digiio.h | 68 ------------ usr.sbin/Makefile | 1 - usr.sbin/digictl/Makefile | 6 -- usr.sbin/digictl/Makefile.depend | 17 --- usr.sbin/digictl/digictl.8 | 118 --------------------- usr.sbin/digictl/digictl.c | 173 ------------------------------- 7 files changed, 4 insertions(+), 383 deletions(-) delete mode 100644 sys/sys/digiio.h delete mode 100644 usr.sbin/digictl/Makefile delete mode 100644 usr.sbin/digictl/Makefile.depend delete mode 100644 usr.sbin/digictl/digictl.8 delete mode 100644 usr.sbin/digictl/digictl.c diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 149587d76d2f..27595a959841 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,10 @@ # xargs -n1 | sort | uniq -d; # done +# 20180109: Remove vestiges of digi(4) driver +OLD_FILES+=usr/include/sys/digiio.h +OLD_FILES+=usr/sbin/digictl +OLD_FILES+=usr/share/man/man8/digictl.8.gz # 20180107: Convert remaining geli(8) tests to ATF OLD_FILES+=tests/sys/geom/class/eli/nokey_test.sh OLD_FILES+=tests/sys/geom/class/eli/readonly_test.sh diff --git a/sys/sys/digiio.h b/sys/sys/digiio.h deleted file mode 100644 index 8477df8e8396..000000000000 --- a/sys/sys/digiio.h +++ /dev/null @@ -1,68 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2001 Brian Somers - * based on work by Slawa Olhovchenkov - * John Prince - * Eric Hernes - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -/* - * A very small subset of cards. - */ -enum digi_model { - PCXE, - PCXEVE, - PCXI, - PCXEM, - PCCX, - PCIEPCX, - PCIXR -}; - -enum { - DIGIDB_INIT = (1<<0), - DIGIDB_OPEN = (1<<1), - DIGIDB_CLOSE = (1<<2), - DIGIDB_SET = (1<<3), - DIGIDB_INT = (1<<4), - DIGIDB_READ = (1<<5), - DIGIDB_WRITE = (1<<6), - DIGIDB_RX = (1<<7), - DIGIDB_TX = (1<<8), - DIGIDB_IRQ = (1<<9), - DIGIDB_MODEM = (1<<10), - DIGIDB_RI = (1<<11), -}; - -#define DIGIIO_REINIT _IO('e', 'A') -#define DIGIIO_DEBUG _IOW('e', 'B', int) -#define DIGIIO_RING _IOWINT('e', 'C') -#define DIGIIO_MODEL _IOR('e', 'D', enum digi_model) -#define DIGIIO_IDENT _IOW('e', 'E', char *) -#define DIGIIO_SETALTPIN _IOW('e', 'F', int) -#define DIGIIO_GETALTPIN _IOR('e', 'G', int) diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 60c839d945fb..f6597850d69f 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -22,7 +22,6 @@ SUBDIR= adduser \ devctl \ devinfo \ devmatch \ - digictl \ diskinfo \ dumpcis \ etcupdate \ diff --git a/usr.sbin/digictl/Makefile b/usr.sbin/digictl/Makefile deleted file mode 100644 index cb3745b17d16..000000000000 --- a/usr.sbin/digictl/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# $FreeBSD$ - -PROG= digictl -MAN= digictl.8 - -.include diff --git a/usr.sbin/digictl/Makefile.depend b/usr.sbin/digictl/Makefile.depend deleted file mode 100644 index 6cfaab1c3644..000000000000 --- a/usr.sbin/digictl/Makefile.depend +++ /dev/null @@ -1,17 +0,0 @@ -# $FreeBSD$ -# Autogenerated - do NOT edit! - -DIRDEPS = \ - gnu/lib/csu \ - include \ - include/xlocale \ - lib/${CSU_DIR} \ - lib/libc \ - lib/libcompiler_rt \ - - -.include - -.if ${DEP_RELDIR} == ${_DEP_RELDIR} -# local dependencies - needed for -jN in clean tree -.endif diff --git a/usr.sbin/digictl/digictl.8 b/usr.sbin/digictl/digictl.8 deleted file mode 100644 index fefefe41cb84..000000000000 --- a/usr.sbin/digictl/digictl.8 +++ /dev/null @@ -1,118 +0,0 @@ -.\" $FreeBSD$ -.Dd June 20, 2001 -.Dt DIGICTL 8 -.Os -.Sh NAME -.Nm digictl -.Nd control -.Tn Digiboard -devices -.Sh SYNOPSIS -.Nm -.Fl a -.Cm disable | enable | query -.Ar device ... -.Nm -.Op Fl d Ar debug -.Op Fl ir -.Ar ctrl-device ... -.Sh DESCRIPTION -The -.Nm -utility provides control of the -.Tn Digiboard -installed with the given -.Ar ctrl-device -name and provides control of individual digiboard -.Ar devices . -A digiboard -.Ar ctrl-device -is usually of the form -.Sm off -.Pa /dev/digi Ar N Pa .ctl -.Sm on -where -.Ar N -is the card number and starts at -.Dq 0 -for the first attached card. -A digiboard -.Ar device -is usually of the form -.Sm off -.Pa /dev/cua Oo Pa il Oc Pa D Ar N Pa \&. Ar P -.Sm on -or -.Sm off -.Pa /dev/tty Oo Pa il Oc Pa D Ar N Pa \&. Ar P -.Sm on -where -.Ar N -is the card number and -.Ar P -is the port number. -.Pp -The following flags are recognized: -.Bl -tag -width 10n -.It Fl a Cm disable | enable | query -Disable, enable or query the -.Em ALTPIN -settings for the given port(s). -.Pp -When ALTPIN is enabled, the CD and DSR lines are logically reversed. -This is useful when wiring serial ports to an 8 way RJ45 cable (full -10 way RJ45 cables are quite rare). -.Pp -A single ALTPIN setting applies to both of the callout and callin devices. -.It Fl d Ar debug -If the driver has been compiled with -.Dv DEBUG -defined, the following bits from the -.Ar debug -variable are used to enable diagnostics in the digiboard driver: -.Bl -tag -width ".No 1024 ( Em MODEM )" -.It 1 ( Em INIT ) -Diagnostics during card attach, detach and initialization. -.It 2 ( Em OPEN ) -Diagnostics when opening a port. -.It 4 ( Em CLOSE ) -Diagnostics when closing a port. -.It 8 ( Em SET ) -Diagnostics when setting tty device flags. -.It 16 ( Em INT ) -Diagnostics when processing card events. -.It 32 ( Em READ ) -Reports return values from port reads. -.It 64 ( Em WRITE ) -Reports return values from port writes. -.It 128 ( Em RX ) -Reports receive queue flow control. -.It 256 ( Em TX ) -Reports transmit queue flow control. -.It 512 ( Em IRQ ) -Diagnostics during interrupts (enable these with care). -.It 1024 ( Em MODEM ) -Diagnostics when setting modem status flags. -.It 2048 ( Em RI ) -Reports when a RING is received. -.El -.It Fl i -Display the card identification string and type ID. -.It Fl r -Reinitialize the card. -For boards with external port modules, it is possible to add or remove -modules and dynamically reprobe the number of ports using this switch. -All ports on the card must be closed in order to reinitialize the card. -.Pp -It is preferable to reinitialize the card rather than reload the entire -digi module as reinitialization only affects the specified board rather -than affecting all attached boards. -.El -.Sh HISTORY -The -.Nm -utility first appeared in -.Fx 5.0 . -.Sh BUGS -It should be possible to reinitialize a board without closing all of the -existing ports. diff --git a/usr.sbin/digictl/digictl.c b/usr.sbin/digictl/digictl.c deleted file mode 100644 index ea25249c049e..000000000000 --- a/usr.sbin/digictl/digictl.c +++ /dev/null @@ -1,173 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2001 Brian Somers - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum aflag { NO_AFLAG, ALTPIN_DISABLE, ALTPIN_ENABLE, ALTPIN_QUERY }; - -static int -usage(const char *prog) -{ - fprintf(stderr, "usage: %s -a disable|enable|query device\n", prog); - fprintf(stderr, " %s [-d debug] [-ir] ctrl-device...\n", prog); - return (EX_USAGE); -} - -int -main(int argc, char **argv) -{ - char namedata[256], *name = namedata; - const char *prog; - enum digi_model model; - int altpin, ch, debug, fd, i, res; - int dflag, iflag, rflag; - enum aflag aflag; - - if ((prog = strrchr(argv[0], '/')) == NULL) - prog = argv[0]; - else - prog++; - - aflag = NO_AFLAG; - dflag = iflag = rflag = 0; - while ((ch = getopt(argc, argv, "a:d:ir")) != -1) - switch (ch) { - case 'a': - if (strcasecmp(optarg, "disable") == 0) - aflag = ALTPIN_DISABLE; - else if (strcasecmp(optarg, "enable") == 0) - aflag = ALTPIN_ENABLE; - else if (strcasecmp(optarg, "query") == 0) - aflag = ALTPIN_QUERY; - else - return (usage(prog)); - break; - - case 'd': - dflag = 1; - debug = atoi(optarg); - break; - - case 'i': - iflag = 1; - break; - - case 'r': - rflag = 1; - break; - - default: - return (usage(prog)); - } - - if ((dflag || iflag || rflag) && aflag != NO_AFLAG) - return (usage(prog)); - - if (argc <= optind) - return (usage(prog)); - - altpin = (aflag == ALTPIN_ENABLE); - res = 0; - - for (i = optind; i < argc; i++) { - if ((fd = open(argv[i], O_RDONLY)) == -1) { - fprintf(stderr, "%s: %s: open: %s\n", prog, argv[i], - strerror(errno)); - res++; - continue; - } - - switch (aflag) { - case NO_AFLAG: - break; - - case ALTPIN_ENABLE: - case ALTPIN_DISABLE: - if (ioctl(fd, DIGIIO_SETALTPIN, &altpin) != 0) { - fprintf(stderr, "%s: %s: set altpin: %s\n", - prog, argv[i], strerror(errno)); - res++; - } - break; - - case ALTPIN_QUERY: - if (ioctl(fd, DIGIIO_GETALTPIN, &altpin) != 0) { - fprintf(stderr, "%s: %s: get altpin: %s\n", - prog, argv[i], strerror(errno)); - res++; - } else { - if (argc > optind + 1) - printf("%s: ", argv[i]); - puts(altpin ? "enabled" : "disabled"); - } - break; - } - - if (dflag && ioctl(fd, DIGIIO_DEBUG, &debug) != 0) { - fprintf(stderr, "%s: %s: debug: %s\n", - prog, argv[i], strerror(errno)); - res++; - } - - if (iflag) { - if (ioctl(fd, DIGIIO_MODEL, &model) != 0) { - fprintf(stderr, "%s: %s: model: %s\n", - prog, argv[i], strerror(errno)); - res++; - } else if (ioctl(fd, DIGIIO_IDENT, &name) != 0) { - fprintf(stderr, "%s: %s: ident: %s\n", - prog, argv[i], strerror(errno)); - res++; - } else { - if (argc > optind + 1) - printf("%s: ", argv[i]); - printf("%s (type %d)\n", name, (int)model); - } - } - - if (rflag && ioctl(fd, DIGIIO_REINIT) != 0) { - fprintf(stderr, "%s: %s: reinit: %s\n", - prog, argv[i], strerror(errno)); - res++; - } - - close(fd); - } - - return (res); -} From 695d2543651dcb3a6f2fd2dda58201e69c715d3e Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Wed, 10 Jan 2018 14:59:19 +0000 Subject: [PATCH 073/158] Retire pmtimer driver. Move time fixing into apm driver. Move Iwasaki-san's copyright over. Remove FIXME code that couldn't possibly work. Call tc_settime() with our estimate of the delta we've been alseep (the one we print) to adjust the time. Not sure what to do about callouts, so keep the small #ifdef in place there. Differential Revision: https://reviews.freebsd.org/D13823 --- sys/conf/files.i386 | 1 - sys/i386/bios/apm.c | 118 ++++++++++++++++++++++++------ sys/i386/conf/GENERIC | 2 - sys/i386/conf/NOTES | 2 - sys/i386/isa/pmtimer.c | 158 ----------------------------------------- 5 files changed, 97 insertions(+), 184 deletions(-) delete mode 100644 sys/i386/isa/pmtimer.c diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index fc7696827d3c..3b2d594c7d24 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -520,7 +520,6 @@ i386/ibcs2/ibcs2_util.c optional ibcs2 i386/ibcs2/ibcs2_xenix.c optional ibcs2 i386/ibcs2/ibcs2_xenix_sysent.c optional ibcs2 i386/ibcs2/imgact_coff.c optional ibcs2 -i386/isa/pmtimer.c optional pmtimer i386/isa/prof_machdep.c optional profiling-routine i386/linux/imgact_linux.c optional compat_linux i386/linux/linux_dummy.c optional compat_linux diff --git a/sys/i386/bios/apm.c b/sys/i386/bios/apm.c index a38ab16bbc56..8a74e0030062 100644 --- a/sys/i386/bios/apm.c +++ b/sys/i386/bios/apm.c @@ -16,6 +16,32 @@ * Sep, 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) */ +/*- + * Copyright (c) 2000 Mitsuru IWASAKI + * 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$"); @@ -38,6 +64,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -205,7 +232,7 @@ static int apm_driver_version(int version) { struct apm_softc *sc = &apm_softc; - + sc->bios.r.eax = (APM_BIOS << 8) | APM_DRVVERSION; sc->bios.r.ebx = 0x0; sc->bios.r.ecx = version; @@ -220,28 +247,28 @@ apm_driver_version(int version) return (1); } - + /* engage/disengage power management (APM 1.1 or later) */ static int apm_engage_disengage_pm(int engage) { struct apm_softc *sc = &apm_softc; - + sc->bios.r.eax = (APM_BIOS << 8) | APM_ENGAGEDISENGAGEPM; sc->bios.r.ebx = PMDV_ALLDEV; sc->bios.r.ecx = engage; sc->bios.r.edx = 0; return (apm_bioscall()); } - + /* get PM event */ static u_int apm_getevent(void) { struct apm_softc *sc = &apm_softc; - + sc->bios.r.eax = (APM_BIOS << 8) | APM_GETPMEVENT; - + sc->bios.r.ebx = 0; sc->bios.r.ecx = 0; sc->bios.r.edx = 0; @@ -249,18 +276,18 @@ apm_getevent(void) return (PMEV_NOEVENT); return (sc->bios.r.ebx & 0xffff); } - + /* suspend entire system */ static int apm_suspend_system(int state) { struct apm_softc *sc = &apm_softc; - + sc->bios.r.eax = (APM_BIOS << 8) | APM_SETPWSTATE; sc->bios.r.ebx = PMDV_ALLDEV; sc->bios.r.ecx = state; sc->bios.r.edx = 0; - + if (apm_bioscall()) { printf("Entire system suspend failure: errcode = %d\n", 0xff & (sc->bios.r.eax >> 8)); @@ -280,7 +307,7 @@ int apm_display(int newstate) { struct apm_softc *sc = &apm_softc; - + sc->bios.r.eax = (APM_BIOS << 8) | APM_SETPWSTATE; sc->bios.r.ebx = PMDV_DISP0; sc->bios.r.ecx = newstate ? PMST_APMENABLED:PMST_SUSPEND; @@ -331,12 +358,10 @@ apm_battery_low(void) static struct apmhook * apm_add_hook(struct apmhook **list, struct apmhook *ah) { - int s; struct apmhook *p, *prev; APM_DPRINT("Add hook \"%s\"\n", ah->ah_name); - s = splhigh(); if (ah == NULL) panic("illegal apm_hook!"); prev = NULL; @@ -351,30 +376,25 @@ apm_add_hook(struct apmhook **list, struct apmhook *ah) ah->ah_next = prev->ah_next; prev->ah_next = ah; } - splx(s); return ah; } static void apm_del_hook(struct apmhook **list, struct apmhook *ah) { - int s; struct apmhook *p, *prev; - s = splhigh(); prev = NULL; for (p = *list; p != NULL; prev = p, p = p->ah_next) if (p == ah) goto deleteit; panic("Tried to delete unregistered apm_hook."); - goto nosuchnode; + return; deleteit: if (prev != NULL) prev->ah_next = p->ah_next; else *list = p->ah_next; -nosuchnode: - splx(s); } @@ -468,7 +488,7 @@ apm_do_standby(void) sc->standbys = sc->standby_countdown = 0; /* - * As far as standby, we don't need to execute + * As far as standby, we don't need to execute * all of suspend hooks. */ if (apm_suspend_system(PMST_STANDBY) == 0) @@ -1047,6 +1067,53 @@ apm_processevent(void) } while (apm_event != PMEV_NOEVENT); } +static struct timeval suspend_time; +static struct timeval diff_time; + +static int +apm_rtc_suspend(void *arg __unused) +{ + + microtime(&diff_time); + inittodr(0); + microtime(&suspend_time); + timevalsub(&diff_time, &suspend_time); + return (0); +} + +static int +apm_rtc_resume(void *arg __unused) +{ + u_int second, minute, hour; + struct timeval resume_time, tmp_time; + struct timespec ts; + + /* modified for adjkerntz */ + timer_restore(); /* restore the all timers */ + inittodr(0); /* adjust time to RTC */ + microtime(&resume_time); + getmicrotime(&tmp_time); + timevaladd(&tmp_time, &diff_time); + /* Calculate the delta time suspended */ + timevalsub(&resume_time, &suspend_time); + + second = ts.tv_sec = resume_time.tv_sec; + ts.tv_nsec = 0; + tc_setclock(&ts); + +#ifdef PMTIMER_FIXUP_CALLTODO + /* Fixup the calltodo list with the delta time. */ + adjust_timeout_calltodo(&resume_time); +#endif /* PMTIMER_FIXUP_CALLTODO */ + hour = second / 3600; + second %= 3600; + minute = second / 60; + second %= 60; + log(LOG_NOTICE, "wakeup from sleeping state (slept %02d:%02d:%02d)\n", + hour, minute, second); + return (0); +} + /* * Attach APM: * @@ -1128,7 +1195,7 @@ apm_attach(device_t dev) } /* Power the system off using APM */ - EVENTHANDLER_REGISTER(shutdown_final, apm_power_off, NULL, + EVENTHANDLER_REGISTER(shutdown_final, apm_power_off, NULL, SHUTDOWN_PRI_LAST); /* Register APM again to pass the correct argument of pm_func. */ @@ -1142,6 +1209,15 @@ apm_attach(device_t dev) UID_ROOT, GID_OPERATOR, 0664, "apm"); make_dev(&apm_cdevsw, APMDEV_CTL, UID_ROOT, GID_OPERATOR, 0660, "apmctl"); + + sc->sc_suspend.ah_fun = apm_rtc_suspend; + sc->sc_suspend.ah_arg = sc; + apm_hook_establish(APM_HOOK_SUSPEND, &sc->sc_suspend); + + sc->sc_resume.ah_fun = apm_rtc_resume; + sc->sc_resume.ah_arg = sc; + apm_hook_establish(APM_HOOK_RESUME, &sc->sc_resume); + return 0; } @@ -1362,7 +1438,7 @@ apmwrite(struct cdev *dev, struct uio *uio, int ioflag) if ((error = uiomove((caddr_t)&event_type, sizeof(u_int), uio))) return(error); - if (event_type < 0 || event_type >= APM_NPMEV) + if (event_type >= APM_NPMEV) return(EINVAL); if (sc->event_filter[event_type] == 0) { diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index cb1700054863..be6698cbb999 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -207,8 +207,6 @@ device agp # support several AGP chipsets # Power management support (see NOTES for more options) #device apm -# Add suspend/resume support for the i8254. -device pmtimer # PCCARD (PCMCIA) support # PCMCIA and cardbus bridge support diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index fa72d18eca2e..a16b45cd906c 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -774,7 +774,6 @@ device hyperv # HyperV drivers # smapi: System Management Application Program Interface driver # smbios: DMI/SMBIOS entry point # vpd: Vital Product Data kernel interface -# pmtimer: Adjust system timer at wakeup time # pbio: Parallel (8255 PPI) basic I/O (mode 0) port (e.g. Advantech PCL-724) # asmc: Apple System Management Controller # si: Specialix International SI/XIO or SX intelligent serial card driver @@ -808,7 +807,6 @@ device ipmi device smapi device smbios device vpd -device pmtimer device pbio hint.pbio.0.at="isa" hint.pbio.0.port="0x360" diff --git a/sys/i386/isa/pmtimer.c b/sys/i386/isa/pmtimer.c deleted file mode 100644 index a8578064e575..000000000000 --- a/sys/i386/isa/pmtimer.c +++ /dev/null @@ -1,158 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2000 Mitsuru IWASAKI - * 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$"); - -/* - * Timer device driver for power management events. - * The code for suspend/resume is derived from APM device driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -static devclass_t pmtimer_devclass; - -/* reject any PnP devices for now */ -static struct isa_pnp_id pmtimer_ids[] = { - {0} -}; - -static void -pmtimer_identify(driver_t *driver, device_t parent) -{ - device_t child; - - /* - * Only add a child if one doesn't exist already. - */ - child = devclass_get_device(pmtimer_devclass, 0); - if (child == NULL) { - child = BUS_ADD_CHILD(parent, 0, "pmtimer", 0); - if (child == NULL) - panic("pmtimer_identify"); - } -} - -static int -pmtimer_probe(device_t dev) -{ - - if (ISA_PNP_PROBE(device_get_parent(dev), dev, pmtimer_ids) == ENXIO) - return (ENXIO); - - /* only one instance always */ - return (device_get_unit(dev)); -} - -static struct timeval suspend_time; -static struct timeval diff_time; - -static int -pmtimer_suspend(device_t dev) -{ - - if (power_pm_get_type() == POWER_PM_TYPE_ACPI) - return (0); - - microtime(&diff_time); - inittodr(0); - microtime(&suspend_time); - timevalsub(&diff_time, &suspend_time); - return (0); -} - -static int -pmtimer_resume(device_t dev) -{ - u_int second, minute, hour; - struct timeval resume_time, tmp_time; - - if (power_pm_get_type() == POWER_PM_TYPE_ACPI) - return (0); - - /* modified for adjkerntz */ - timer_restore(); /* restore the all timers */ - inittodr(0); /* adjust time to RTC */ - microtime(&resume_time); - getmicrotime(&tmp_time); - timevaladd(&tmp_time, &diff_time); - -#ifdef FIXME - /* XXX THIS DOESN'T WORK!!! */ - time = tmp_time; -#endif - -#ifdef PMTIMER_FIXUP_CALLTODO - /* Calculate the delta time suspended */ - timevalsub(&resume_time, &suspend_time); - /* Fixup the calltodo list with the delta time. */ - adjust_timeout_calltodo(&resume_time); - /* - * We've already calculated resume_time to be the delta between - * the suspend and the resume. - */ - second = resume_time.tv_sec; -#else /* !PMTIMER_FIXUP_CALLTODO */ - second = resume_time.tv_sec - suspend_time.tv_sec; -#endif /* PMTIMER_FIXUP_CALLTODO */ - hour = second / 3600; - second %= 3600; - minute = second / 60; - second %= 60; - log(LOG_NOTICE, "wakeup from sleeping state (slept %02d:%02d:%02d)\n", - hour, minute, second); - return (0); -} - -static device_method_t pmtimer_methods[] = { - /* Device interface */ - DEVMETHOD(device_identify, pmtimer_identify), - DEVMETHOD(device_probe, pmtimer_probe), - DEVMETHOD(device_attach, bus_generic_attach), - DEVMETHOD(device_suspend, pmtimer_suspend), - DEVMETHOD(device_resume, pmtimer_resume), - { 0, 0 } -}; - -static driver_t pmtimer_driver = { - "pmtimer", - pmtimer_methods, - 1, /* no softc */ -}; - -DRIVER_MODULE(pmtimer, isa, pmtimer_driver, pmtimer_devclass, 0, 0); From 792f0c3b095367bf981515d46f9fac98d3e204e3 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 10 Jan 2018 15:21:36 +0000 Subject: [PATCH 074/158] Clarify the use of the gmirror flag mask constants. MFC after: 1 week Sponsored by: Dell EMC Isilon --- sys/geom/mirror/g_mirror.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/geom/mirror/g_mirror.h b/sys/geom/mirror/g_mirror.h index 1db45bd274f5..22b3ff692d51 100644 --- a/sys/geom/mirror/g_mirror.h +++ b/sys/geom/mirror/g_mirror.h @@ -62,6 +62,8 @@ #define G_MIRROR_DISK_FLAG_HARDCODED 0x0000000000000010ULL #define G_MIRROR_DISK_FLAG_BROKEN 0x0000000000000020ULL #define G_MIRROR_DISK_FLAG_CANDELETE 0x0000000000000040ULL + +/* Per-disk flags which are recorded in on-disk metadata. */ #define G_MIRROR_DISK_FLAG_MASK (G_MIRROR_DISK_FLAG_DIRTY | \ G_MIRROR_DISK_FLAG_SYNCHRONIZING | \ G_MIRROR_DISK_FLAG_FORCE_SYNC | \ @@ -70,6 +72,8 @@ #define G_MIRROR_DEVICE_FLAG_NOAUTOSYNC 0x0000000000000001ULL #define G_MIRROR_DEVICE_FLAG_NOFAILSYNC 0x0000000000000002ULL + +/* Mirror flags which are recorded in on-disk metadata. */ #define G_MIRROR_DEVICE_FLAG_MASK (G_MIRROR_DEVICE_FLAG_NOAUTOSYNC | \ G_MIRROR_DEVICE_FLAG_NOFAILSYNC) From 00da6aa72bdd8c8c8302c484a51fb4412e282c45 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 10 Jan 2018 15:55:07 +0000 Subject: [PATCH 075/158] Remove the executable bit from some recently added test scripts. --- tests/sys/geom/class/eli/attach_test.sh | 0 tests/sys/geom/class/eli/configure_test.sh | 0 tests/sys/geom/class/eli/detach_test.sh | 0 tests/sys/geom/class/eli/integrity_test.sh | 0 tests/sys/geom/class/mirror/10_test.sh | 0 tests/sys/geom/class/mirror/11_test.sh | 0 tests/sys/geom/class/mirror/12_test.sh | 0 tests/sys/geom/class/mirror/13_test.sh | 0 8 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 tests/sys/geom/class/eli/attach_test.sh mode change 100755 => 100644 tests/sys/geom/class/eli/configure_test.sh mode change 100755 => 100644 tests/sys/geom/class/eli/detach_test.sh mode change 100755 => 100644 tests/sys/geom/class/eli/integrity_test.sh mode change 100755 => 100644 tests/sys/geom/class/mirror/10_test.sh mode change 100755 => 100644 tests/sys/geom/class/mirror/11_test.sh mode change 100755 => 100644 tests/sys/geom/class/mirror/12_test.sh mode change 100755 => 100644 tests/sys/geom/class/mirror/13_test.sh diff --git a/tests/sys/geom/class/eli/attach_test.sh b/tests/sys/geom/class/eli/attach_test.sh old mode 100755 new mode 100644 diff --git a/tests/sys/geom/class/eli/configure_test.sh b/tests/sys/geom/class/eli/configure_test.sh old mode 100755 new mode 100644 diff --git a/tests/sys/geom/class/eli/detach_test.sh b/tests/sys/geom/class/eli/detach_test.sh old mode 100755 new mode 100644 diff --git a/tests/sys/geom/class/eli/integrity_test.sh b/tests/sys/geom/class/eli/integrity_test.sh old mode 100755 new mode 100644 diff --git a/tests/sys/geom/class/mirror/10_test.sh b/tests/sys/geom/class/mirror/10_test.sh old mode 100755 new mode 100644 diff --git a/tests/sys/geom/class/mirror/11_test.sh b/tests/sys/geom/class/mirror/11_test.sh old mode 100755 new mode 100644 diff --git a/tests/sys/geom/class/mirror/12_test.sh b/tests/sys/geom/class/mirror/12_test.sh old mode 100755 new mode 100644 diff --git a/tests/sys/geom/class/mirror/13_test.sh b/tests/sys/geom/class/mirror/13_test.sh old mode 100755 new mode 100644 From 71e8c9b65d446063d5e9d086f489aba086bb0c1b Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Wed, 10 Jan 2018 16:01:25 +0000 Subject: [PATCH 076/158] lld: introduce basic man page Upstream lld has no man page. Introduce a basic one for FreeBSD based on ld.lld --help, with a brief introduction and additional detail for some options. We'll continue refining this in FreeBSD, and then submit it upstream once the first round of edits are complete. Submitted by: krion, Arshan Khanifar, emaste, bjk MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D13813 --- usr.bin/clang/lld/Makefile | 3 +- usr.bin/clang/lld/ld.lld.1 | 364 +++++++++++++++++++++++++++++++++++++ 2 files changed, 366 insertions(+), 1 deletion(-) create mode 100644 usr.bin/clang/lld/ld.lld.1 diff --git a/usr.bin/clang/lld/Makefile b/usr.bin/clang/lld/Makefile index a7af9c78f28c..d2d0d95c0d53 100644 --- a/usr.bin/clang/lld/Makefile +++ b/usr.bin/clang/lld/Makefile @@ -7,9 +7,10 @@ LLD_SRCS= ${LLVM_SRCS}/tools/lld PACKAGE= lld PROG_CXX= ld.lld -MAN= + .if ${MK_LLD_IS_LD} != "no" SYMLINKS= ${PROG_CXX} ${BINDIR}/ld +MLINKS= ld.lld.1 ld.1 .endif CFLAGS+= -I${LLD_SRCS}/ELF diff --git a/usr.bin/clang/lld/ld.lld.1 b/usr.bin/clang/lld/ld.lld.1 new file mode 100644 index 000000000000..6c13514572f7 --- /dev/null +++ b/usr.bin/clang/lld/ld.lld.1 @@ -0,0 +1,364 @@ +.\"- +.\" Copyright (c) 2018 Kirill Ponomarev +.\" Copyright (c) 2018 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 AUTHORS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd January 10, 2018 +.Dt LD.LLD 1 +.Os +.Sh NAME +.Nm ld.lld +.Nd ELF linker from the LLVM project +.Sh SYNOPSIS +.Nm ld.lld +.Op Ar options +.Ar objfile ... +.Sh DESCRIPTION +A linker takes one or more object, archive and library files, and combines +them into an output file (an executable, a shared library, or another object +file). +It relocates code and data from the input files and resolves symbol +references between them. +.Pp +.Nm +is a drop-in replacement for the GNU BFD and gold linkers. +It accepts most of the same command line arguments and linker scripts +as GNU linkers. +.Pp +The following options are available: +.Bl -tag -width indent +.It Fl -allow-multiple-definition +Allow multiple definitions. +.It Fl -as-needed +Only set +.Dv DT_NEEDED +for shared libraries if used. +.It Fl -auxiliary Ar value +Set the +.Dv DT_AUXILIARY +field to the specified name. +.It Fl -Bdynamic +Link against shared libraries. +.It Fl -Bstatic +Do not link against shared libraries. +.It Fl -Bsymbolic-functions +Bind defined function symbols locally. +.It Fl -Bsymbolic +Bind defined symbols locally. +.It Fl -build-id= Ns Ar value +Generate a build ID note. +.It Fl -build-id +Generate a build ID note. +.It Fl -color-diagnostics= Ns Ar value +Use colors in diagnostics. +.It Fl -color-diagnostics +Use colors in diagnostics. +.It Fl -compress-debug-sections= Ns Ar value +Compress DWARF debug sections. +.It Fl -define-common +Assign space to common symbols. +.It Fl -defsym= Ns Ar value +Define a symbol alias. +.It Fl -demangle +Demangle symbol names. +.It Fl -disable-new-dtags +Disable new dynamic tags. +.It Fl -discard-all +Delete all local symbols. +.It Fl -discard-locals +Delete temporary local symbols. +.It Fl -discard-none +Keep all symbols in the symbol table. +.It Fl -dynamic-linker Ar value +Specify the dynamic linker to be used for a dynamically linked executable. +This is recorded in an ELF segment of type +.Dv PT_INTERP . +.It Fl -dynamic-list Ar value +Read a list of dynamic symbols. +.It Fl -eh-frame-hdr +Request creation of +.Li .eh_frame_hdr +section and +.Dv PT_GNU_EH_FRAME +segment header. +.It Fl -emit-relocs +Generate relocations in the output. +.It Fl -enable-new-dtags +Enable new dynamic tags. +.It Fl -end-lib +End a grouping of objects that should be treated as if they were together +in an archive. +.It Fl -entry Ar entry +Name of entry point symbol. +.It Fl -error-limit Ar value +Maximum number of errors to emit before stopping. +A value of zero indicates that there is no limit. +.It Fl -error-unresolved-symbols +Report unresolved symbols as errors. +.It Fl -exclude-libs Ar value +Exclude static libraries from automatic export. +.It Fl -export-dynamic-symbol Ar value +Put a symbol in the dynamic symbol table. +.It Fl -export-dynamic +Put symbols in the dynamic symbol table. +.It Fl -fatal-warnings +Treat warnings as errors. +.It Fl -filter= Ns Ar value +Set the +.Dv DT_FILTER +field to the specified value. +.It Fl -fini Ar symbol +Specify a finalizer function. +.It Fl -format= Ns Ar input-format +Change the input format of the inputs following this option. +.It Fl -full-shutdown +Perform a full shutdown instead of calling +.Fn _exit . +.It Fl -gc-sections +Enable garbage collection of unused sections. +.It Fl -gdb-index +Generate +.Li .gdb_index +section. +.It Fl -hash-style Ar value +Specify hash style (sysv, gnu or both). +.It Fl -help +Print a usage message. +.It Fl -icf=all +Enable identical code folding. +.It Fl -icf=none +Disable identical code folding. +.It Fl -image-base= Ns Ar value +Set the base address to +.Ar value . +.It Fl -init Ar symbol +Specify an initializer function. +.It Fl -lto-aa-pipeline= Ns Ar value +AA pipeline to run during LTO. +Used in conjunction with +.Fl -lto-newpm-passes . +.It Fl -lto-newpm-passes= Ns Ar value +Passes to run during LTO. +.It Fl -lto-O Ar opt-level +Optimization level for LTO. +.It Fl -lto-partitions= Ns Ar value +Number of LTO codegen partitions. +.It Fl L Ar dir +Add a directory to the library search path. +.It Fl l Ar libName +Root name of library to use. +.It Fl -Map Ar value +Print a link map to the specified file. +.It Fl m Ar value +Set target emulation. +.It Fl -no-as-needed +Always set +.Dv DT_NEEDED +for shared libraries. +.It Fl -no-color-diagnostics +Do not use colors in diagnostics. +.It Fl -no-define-common +Do not assign space to common symbols. +.It Fl -no-demangle +Do not demangle symbol names. +.It Fl -no-dynamic-linker +Inhibit output of an +.Li .interp +section. +.It Fl -no-gc-sections +Disable garbage collection of unused sections. +.It Fl -no-gnu-unique +Disable STB_GNU_UNIQUE symbol binding. +.It Fl -no-rosegment +Do not put read-only non-executable sections in their own segment. +.It Fl -no-threads +Do not run the linker multi-threaded. +.It Fl -no-undefined-version +Report version scripts that refer undefined symbols. +.It Fl -no-undefined +Report unresolved symbols even if the linker is creating a shared library. +.It Fl -no-whole-archive +Restores the default behavior of loading archive members. +.It Fl -noinhibit-exec +Retain the executable output file whenever it is still usable. +.It Fl -nopie +Do not create a position independent executable. +.It Fl -nostdlib +Only search directories specified on the command line. +.It Fl -oformat Ar format +Specify the binary format for the output object file. +.It Fl -omagic +Set the text and data sections to be readable and writable. +.It Fl -opt-remarks-filename Ar value +YAML output file for optimization remarks. +.It Fl -opt-remarks-with-hotness +Include hotness information in the optimization remarks file. +.It Fl O Ar value +Optimize output file size. +.It Fl o Ar path +Write the output executable, library or object to +.Ar path . +If not specified, +.Dv a.out +is used as a default. +.It Fl -pie +Create a position independent executable. +.It Fl -print-gc-sections +List removed unused sections. +.It Fl -print-map +Print a link map to the standard output. +.It Fl -relocatable +Create relocatable object file. +.It Fl -reproduce Ar value +Dump linker invocation and input files for debugging. +.It Fl -retain-symbols-file= Ns Ar file +Retain only the symbols listed in the file. +.It Fl -rpath Ar value +Add a +.Dv DT_RUNPATH +to the output. +.It Fl -rsp-quoting= Ns Ar value +Quoting style for response files. +The supported values are +.Ar windows +and +.Ar posix . +.It Fl -script Ar value +Read linker script from the path +.Ar value . +.It Fl -section-start Ar address +Set address of section. +.It Fl -shared +Build a shared object. +.It Fl -soname= Ns Ar value +Set +.Dv DT_SONAME +to +.Ar value . +.It Fl -sort-section Ar value +Specifies sections sorting rule when linkerscript is used. +.It Fl -start-lib +Start a grouping of objects that should be treated as if they were together +in an archive. +.It Fl -strip-all +Strip all symbols. +.It Fl -strip-debug +Strip debugging information. +.It Fl -symbol-ordering-file Ar value +Lay out sections in the order specified by the symbol file. +.It Fl -sysroot= Ns Ar value +Set the system root. +.It Fl -target1-abs +Interpret +.Dv R_ARM_TARGET1 +as +.Dv R_ARM_ABS32 . +.It Fl -target1-rel +Interpret +.Dv R_ARM_TARGET1 +as +.Dv R_ARM_REL32 . +.It Fl -target2=type +Interpret +.Dv R_ARM_TARGET2 +as +.Ar type , +where +.Ar type +is one of +.Li rel , +.Li abs , +or +.Li got-rel . +.It Fl -Tbss Ar value +Same as +.Fl -section-start +with +.Li .bss +as the sectionname. +.It Fl -Tdata Ar value +Same as +.Fl -section-start +with +.Li .data +as the sectionname. +.It Fl -thinlto-cache-dir= Ns Ar value +Path to ThinLTO cached object file directory. +.It Fl -thinlto-cache-policy Ar value +Pruning policy for the ThinLTO cache. +.It Fl -thinlto-jobs= Ns Ar value +Number of ThinLTO jobs. +.It Fl -threads +Run the linker multi-threaded. +.It Fl -trace-symbol Ar value +Trace references to symbols. +.It Fl -trace +Print the names of the input files. +.It Fl -Ttext Ar value +Same as +.Fl -section-start +with +.Li .text +as the sectionname. +.It Fl -undefined Ar value +Force undefined symbol during linking. +.It Fl -unresolved-symbols= Ns Ar value +Determine how to handle unresolved symbols. +.It Fl -verbose +Verbose mode. +.It Fl -version-script Ar value +Read a version script. +.It Fl V , Fl -version +Display the version number and exit. +.It Fl v +Display the version number, and proceed with linking if object files are +specified. +.It Fl -warn-common +Warn about duplicate common symbols. +.It Fl -warn-unresolved-symbols +Report unresolved symbols as warnings. +.It Fl -whole-archive +Force load of all members in a static library. +.It Fl -wrap Ar symbol +Use wrapper functions for symbol. +.It Fl z Ar option +Linker option extensions. +.Bl -tag -width indent +.It Cm notext +Allow relocations against read-only segments. +Sets the +.Dv DT_TEXTREL flag in the +.Dv DYNAMIC +section. +.It Cm text +Do not allow relocations against read-only segments. +This is the default. +.El +.El +.Sh IMPLEMENTATION NOTES +The targets supported by +.Nm +are: +elf32-i386 elf32-iamcu elf32-littlearm elf32-ntradbigmips elf32-ntradlittlemips elf32-powerpc elf32-tradbigmips elf32-tradlittlemips elf32-x86-64 elf64-amdgpu elf64-littleaarch64 elf64-powerpc elf64-tradbigmips elf64-tradlittlemips elf64-x86-64 From 41add9e267974b161b5b52c0d0ac589bf23fab0d Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Wed, 10 Jan 2018 16:51:55 +0000 Subject: [PATCH 077/158] Move prof_machdep.c to it's more traditional place under i386/i386. --- sys/conf/files.i386 | 2 +- sys/i386/{isa => i386}/prof_machdep.c | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename sys/i386/{isa => i386}/prof_machdep.c (100%) diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 3b2d594c7d24..34f2d2e81f46 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -493,6 +493,7 @@ i386/i386/mpboot.s optional smp i386/i386/npx.c standard i386/i386/perfmon.c optional perfmon i386/i386/pmap.c standard +i386/i386/prof_machdep.c optional profiling-routine i386/i386/ptrace_machdep.c standard i386/i386/support.s standard i386/i386/swtch.s standard @@ -520,7 +521,6 @@ i386/ibcs2/ibcs2_util.c optional ibcs2 i386/ibcs2/ibcs2_xenix.c optional ibcs2 i386/ibcs2/ibcs2_xenix_sysent.c optional ibcs2 i386/ibcs2/imgact_coff.c optional ibcs2 -i386/isa/prof_machdep.c optional profiling-routine i386/linux/imgact_linux.c optional compat_linux i386/linux/linux_dummy.c optional compat_linux i386/linux/linux_machdep.c optional compat_linux diff --git a/sys/i386/isa/prof_machdep.c b/sys/i386/i386/prof_machdep.c similarity index 100% rename from sys/i386/isa/prof_machdep.c rename to sys/i386/i386/prof_machdep.c From e92cdf4b43f56175ab37e74a2b0c3bab95b01ab0 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Wed, 10 Jan 2018 16:52:00 +0000 Subject: [PATCH 078/158] Docuent pmtimer driver removal. --- UPDATING | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/UPDATING b/UPDATING index dfe3c2b5b14d..5d0bdf9e7412 100644 --- a/UPDATING +++ b/UPDATING @@ -51,6 +51,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW: ****************************** SPECIAL WARNING: ****************************** +20180110: + On i386, pmtimer has been removed. It's functionality has been folded + into apm. It was a nop on ACPI. Users may need to remove it from kernel + config files. + 20180104: The use of RSS hash from the network card aka flowid has been disabled by default for lagg(4) as it's currently incompatible with From 79fb96d9cfc9a575670829e66ee67fc054bad939 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Wed, 10 Jan 2018 16:56:02 +0000 Subject: [PATCH 079/158] Catchup to removing this directory From a333cdf3698299aad3782d63f3a175d35e3ac97a Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Wed, 10 Jan 2018 17:25:08 +0000 Subject: [PATCH 080/158] inittodr(0) actually sets the time, so there's no need to call tc_setclock(). It's redundant. Tweak UPDATING based on code review of past releases. Relnotes: yes (for the removal of pmtimer) --- UPDATING | 5 +++-- sys/i386/bios/apm.c | 6 +----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/UPDATING b/UPDATING index 5d0bdf9e7412..ad30ed2b3506 100644 --- a/UPDATING +++ b/UPDATING @@ -53,8 +53,9 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW: 20180110: On i386, pmtimer has been removed. It's functionality has been folded - into apm. It was a nop on ACPI. Users may need to remove it from kernel - config files. + into apm. It was a nop on ACPI in current for a while now (but was still + needed on i386 in FreeBSD 11 and earlier). Users may need to remove it + from kernel config files. 20180104: The use of RSS hash from the network card aka flowid has been diff --git a/sys/i386/bios/apm.c b/sys/i386/bios/apm.c index 8a74e0030062..0056f9876283 100644 --- a/sys/i386/bios/apm.c +++ b/sys/i386/bios/apm.c @@ -1086,7 +1086,6 @@ apm_rtc_resume(void *arg __unused) { u_int second, minute, hour; struct timeval resume_time, tmp_time; - struct timespec ts; /* modified for adjkerntz */ timer_restore(); /* restore the all timers */ @@ -1097,14 +1096,11 @@ apm_rtc_resume(void *arg __unused) /* Calculate the delta time suspended */ timevalsub(&resume_time, &suspend_time); - second = ts.tv_sec = resume_time.tv_sec; - ts.tv_nsec = 0; - tc_setclock(&ts); - #ifdef PMTIMER_FIXUP_CALLTODO /* Fixup the calltodo list with the delta time. */ adjust_timeout_calltodo(&resume_time); #endif /* PMTIMER_FIXUP_CALLTODO */ + second = resume_time.tv_sec; hour = second / 3600; second %= 3600; minute = second / 60; From cf38c8c6308b64e45a23ccfdc15f3a7911f292dd Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Wed, 10 Jan 2018 17:35:00 +0000 Subject: [PATCH 081/158] amdsbwd: fix handling of timeout values beyond the supported range The driver now fully observes watchdog(9) protocol. Previously a too large timeout was silently clamped while the correct behavior is to disable the watchdog and leave the error as is (i.e. to not report success). Also, previously a too small value caused the timer to stop while the correct behavior is to use the minimal supported value. MFC after: 2 weeks --- sys/dev/amdsbwd/amdsbwd.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/sys/dev/amdsbwd/amdsbwd.c b/sys/dev/amdsbwd/amdsbwd.c index fdcde2398b93..81cf2cbc854c 100644 --- a/sys/dev/amdsbwd/amdsbwd.c +++ b/sys/dev/amdsbwd/amdsbwd.c @@ -210,21 +210,30 @@ static void amdsbwd_event(void *arg, unsigned int cmd, int *error) { struct amdsbwd_softc *sc = arg; - unsigned int timeout; + uint64_t timeout; - /* convert from power-of-two-ns to WDT ticks */ - cmd &= WD_INTERVAL; - if (cmd < WD_TO_1SEC) - cmd = 0; - if (cmd) { - timeout = ((uint64_t)1 << (cmd - WD_TO_1MS)) / sc->ms_per_tick; - if (timeout > sc->max_ticks) - timeout = sc->max_ticks; - if (timeout != sc->timeout) { - amdsbwd_tmr_set(sc, timeout); - if (!sc->active) - amdsbwd_tmr_enable(sc); + if (cmd != 0) { + timeout = 0; + cmd &= WD_INTERVAL; + if (cmd >= WD_TO_1MS) { + timeout = (uint64_t)1 << (cmd - WD_TO_1MS); + timeout = timeout / sc->ms_per_tick; } + /* For a too short timeout use 1 tick. */ + if (timeout == 0) + timeout = 1; + /* For a too long timeout stop the timer. */ + if (timeout > sc->max_ticks) + timeout = 0; + } else { + timeout = 0; + } + + if (timeout != 0) { + if (timeout != sc->timeout) + amdsbwd_tmr_set(sc, timeout); + if (!sc->active) + amdsbwd_tmr_enable(sc); amdsbwd_tmr_reload(sc); *error = 0; } else { From 806695ffe43337b3e49608f23167e3f402cb6081 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Wed, 10 Jan 2018 17:36:43 +0000 Subject: [PATCH 082/158] Include ffsll() on riscv kernels. --- sys/conf/files.riscv | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/conf/files.riscv b/sys/conf/files.riscv index ed0157c6dfae..954bc2508a90 100644 --- a/sys/conf/files.riscv +++ b/sys/conf/files.riscv @@ -14,6 +14,7 @@ kern/subr_dummy_vdso_tc.c standard libkern/bcmp.c standard libkern/ffs.c standard libkern/ffsl.c standard +libkern/ffsll.c standard libkern/fls.c standard libkern/flsl.c standard libkern/flsll.c standard From ed5cdcb6c30086b2a2ca0f227cf0540836ac797a Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Wed, 10 Jan 2018 17:51:02 +0000 Subject: [PATCH 083/158] Make nullfs properly report MNT_AUTOMOUNTED set on the nullfs mount itself, instead of copying from the underlying filesystem. PR: 224851 Reported by: Jamie Landeg-Jones Tested by: Jamie Landeg-Jones MFC after: 2 weeks --- sys/fs/nullfs/null_vfsops.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c index a392f4b7ef7f..4def1cf522b4 100644 --- a/sys/fs/nullfs/null_vfsops.c +++ b/sys/fs/nullfs/null_vfsops.c @@ -320,7 +320,8 @@ nullfs_statfs(mp, sbp) /* now copy across the "interesting" information and fake the rest */ sbp->f_type = mstat->f_type; sbp->f_flags = (sbp->f_flags & (MNT_RDONLY | MNT_NOEXEC | MNT_NOSUID | - MNT_UNION | MNT_NOSYMFOLLOW)) | (mstat->f_flags & ~MNT_ROOTFS); + MNT_UNION | MNT_NOSYMFOLLOW | MNT_AUTOMOUNTED)) | + (mstat->f_flags & ~(MNT_ROOTFS | MNT_AUTOMOUNTED)); sbp->f_bsize = mstat->f_bsize; sbp->f_iosize = mstat->f_iosize; sbp->f_blocks = mstat->f_blocks; From 782df3ed34d607f4b043376d8175fc157ea80a70 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Wed, 10 Jan 2018 18:15:00 +0000 Subject: [PATCH 084/158] src.conf.5: regen after r325692 and r326888 Sponsored by: The FreeBSD Foundation --- share/man/man5/src.conf.5 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5 index c28688a3c77c..0a4b1d2d3df9 100644 --- a/share/man/man5/src.conf.5 +++ b/share/man/man5/src.conf.5 @@ -1,6 +1,6 @@ .\" DO NOT EDIT-- this file is generated by tools/build/options/makeman. .\" $FreeBSD$ -.Dd November 2, 2017 +.Dd January 10, 2018 .Dt SRC.CONF 5 .Os .Sh NAME @@ -996,6 +996,11 @@ Set to use LLVM's libunwind stack unwinder (instead of GCC's unwinder). .Pp This is a default setting on amd64/amd64, arm64/aarch64, i386/i386, riscv/riscv64 and riscv/riscv64sf. +.It Va WITH_LOADER_FIREWIRE +Enable firewire support in /boot/loader and /boot/zfsloader on x86. +This option is a nop on all other platforms. +.It Va WITHOUT_LOADER_GELI +Disable inclusion of GELI crypto support in the boot chain binaries. .It Va WITHOUT_LOCALES Set to not build localization files; see .Xr locale 1 . From 762f440f15383dc2e42d911e161a342a61227ef3 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 10 Jan 2018 19:37:21 +0000 Subject: [PATCH 085/158] Fix handling of read errors during mirror synchronization. We would previously just free the request BIO, which would either cause the disk to stay stuck in the SYNCHRONIZING state, or result in synchronization completing without having copied the block which returned an error. With this change, if the disk which returned an error is the only active disk in the mirror, the synchronizing disk is kicked out. Otherwise, the read is retried. Reported and tested by: pho (previous version) MFC after: 2 weeks Sponsored by: Dell EMC Isilon --- sys/geom/mirror/g_mirror.c | 132 ++++++++++++++++++++++++------------- 1 file changed, 85 insertions(+), 47 deletions(-) diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index abde8547bab5..0b65601761c9 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -110,6 +110,8 @@ static int g_mirror_update_disk(struct g_mirror_disk *disk, u_int state); static void g_mirror_update_device(struct g_mirror_softc *sc, bool force); static void g_mirror_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp); +static void g_mirror_sync_reinit(const struct g_mirror_disk *disk, + struct bio *bp, off_t offset); static void g_mirror_sync_stop(struct g_mirror_disk *disk, int type); static void g_mirror_register_request(struct g_mirror_softc *sc, struct bio *bp); @@ -1298,10 +1300,11 @@ g_mirror_sync_request_free(struct g_mirror_disk *disk, struct bio *bp) /* * Handle synchronization requests. - * Every synchronization request is two-steps process: first, READ request is - * send to active provider and then WRITE request (with read data) to the provider - * being synchronized. When WRITE is finished, new synchronization request is - * send. + * Every synchronization request is a two-step process: first, a read request is + * sent to the mirror provider via the sync consumer. If that request completes + * successfully, it is converted to a write and sent to the disk being + * synchronized. If the write also completes successfully, the synchronization + * offset is advanced and a new read request is submitted. */ static void g_mirror_sync_request(struct g_mirror_softc *sc, struct bio *bp) @@ -1326,13 +1329,16 @@ g_mirror_sync_request(struct g_mirror_softc *sc, struct bio *bp) return; } + sync = &disk->d_sync; + /* * Synchronization request. */ switch (bp->bio_cmd) { - case BIO_READ: - { + case BIO_READ: { + struct g_mirror_disk *d; struct g_consumer *cp; + int readable; KFAIL_POINT_ERROR(DEBUG_FP, g_mirror_sync_request_read, bp->bio_error); @@ -1341,7 +1347,33 @@ g_mirror_sync_request(struct g_mirror_softc *sc, struct bio *bp) G_MIRROR_LOGREQ(0, bp, "Synchronization request failed (error=%d).", bp->bio_error); - g_mirror_sync_request_free(disk, bp); + + /* + * If there's at least one other disk from which we can + * read the block, retry the request. + */ + readable = 0; + LIST_FOREACH(d, &sc->sc_disks, d_next) + if (d->d_state == G_MIRROR_DISK_STATE_ACTIVE && + !(d->d_flags & G_MIRROR_DISK_FLAG_BROKEN)) + readable++; + + /* + * The read error will trigger a syncid bump, so there's + * no need to do that here. + * + * If we can retry the read from another disk, do so. + * Otherwise, all we can do is kick out the new disk. + */ + if (readable == 0) { + g_mirror_sync_request_free(disk, bp); + g_mirror_event_send(disk, + G_MIRROR_DISK_STATE_DISCONNECTED, + G_MIRROR_EVENT_DONTWAIT); + } else { + g_mirror_sync_reinit(disk, bp, bp->bio_offset); + goto retry_read; + } return; } G_MIRROR_LOGREQ(3, bp, @@ -1355,12 +1387,10 @@ g_mirror_sync_request(struct g_mirror_softc *sc, struct bio *bp) cp->index++; g_io_request(bp, cp); return; - } - case BIO_WRITE: - { + } + case BIO_WRITE: { off_t offset; - void *data; - int i, idx; + int i; KFAIL_POINT_ERROR(DEBUG_FP, g_mirror_sync_request_write, bp->bio_error); @@ -1377,7 +1407,6 @@ g_mirror_sync_request(struct g_mirror_softc *sc, struct bio *bp) return; } G_MIRROR_LOGREQ(3, bp, "Synchronization request finished."); - sync = &disk->d_sync; if (sync->ds_offset >= sc->sc_mediasize || sync->ds_consumer == NULL || (sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROY) != 0) { @@ -1397,20 +1426,13 @@ g_mirror_sync_request(struct g_mirror_softc *sc, struct bio *bp) } /* Send next synchronization request. */ - data = bp->bio_data; - idx = (int)(uintptr_t)bp->bio_caller1; - g_reset_bio(bp); - bp->bio_cmd = BIO_READ; - bp->bio_offset = sync->ds_offset; - bp->bio_length = MIN(MAXPHYS, sc->sc_mediasize - bp->bio_offset); + g_mirror_sync_reinit(disk, bp, sync->ds_offset); sync->ds_offset += bp->bio_length; - bp->bio_done = g_mirror_sync_done; - bp->bio_data = data; - bp->bio_from = sync->ds_consumer; - bp->bio_to = sc->sc_provider; - bp->bio_caller1 = (void *)(uintptr_t)idx; + +retry_read: G_MIRROR_LOGREQ(3, bp, "Sending synchronization request."); sync->ds_consumer->index++; + /* * Delay the request if it is colliding with a regular request. */ @@ -1436,11 +1458,9 @@ g_mirror_sync_request(struct g_mirror_softc *sc, struct bio *bp) sync->ds_update_ts = time_uptime; } return; - } + } default: - KASSERT(1 == 0, ("Invalid command here: %u (device=%s)", - bp->bio_cmd, sc->sc_name)); - break; + panic("Invalid I/O request %p", bp); } } @@ -2030,16 +2050,40 @@ g_mirror_update_idle(struct g_mirror_softc *sc, struct g_mirror_disk *disk) } } +static void +g_mirror_sync_reinit(const struct g_mirror_disk *disk, struct bio *bp, + off_t offset) +{ + void *data; + int idx; + + data = bp->bio_data; + idx = (int)(uintptr_t)bp->bio_caller1; + g_reset_bio(bp); + + bp->bio_cmd = BIO_READ; + bp->bio_data = data; + bp->bio_done = g_mirror_sync_done; + bp->bio_from = disk->d_sync.ds_consumer; + bp->bio_to = disk->d_softc->sc_provider; + bp->bio_caller1 = (void *)(uintptr_t)idx; + bp->bio_offset = offset; + bp->bio_length = MIN(MAXPHYS, + disk->d_softc->sc_mediasize - bp->bio_offset); +} + static void g_mirror_sync_start(struct g_mirror_disk *disk) { struct g_mirror_softc *sc; + struct g_mirror_disk_sync *sync; struct g_consumer *cp; struct bio *bp; int error, i; g_topology_assert_not(); sc = disk->d_softc; + sync = &disk->d_sync; sx_assert(&sc->sc_lock, SX_LOCKED); KASSERT(disk->d_state == G_MIRROR_DISK_STATE_SYNCHRONIZING, @@ -2065,54 +2109,48 @@ g_mirror_sync_start(struct g_mirror_disk *disk) g_mirror_get_diskname(disk)); if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_NOFAILSYNC) == 0) disk->d_flags |= G_MIRROR_DISK_FLAG_DIRTY; - KASSERT(disk->d_sync.ds_consumer == NULL, + KASSERT(sync->ds_consumer == NULL, ("Sync consumer already exists (device=%s, disk=%s).", sc->sc_name, g_mirror_get_diskname(disk))); - disk->d_sync.ds_consumer = cp; - disk->d_sync.ds_consumer->private = disk; - disk->d_sync.ds_consumer->index = 0; + sync->ds_consumer = cp; + sync->ds_consumer->private = disk; + sync->ds_consumer->index = 0; /* * Allocate memory for synchronization bios and initialize them. */ - disk->d_sync.ds_bios = malloc(sizeof(struct bio *) * g_mirror_syncreqs, + sync->ds_bios = malloc(sizeof(struct bio *) * g_mirror_syncreqs, M_MIRROR, M_WAITOK); for (i = 0; i < g_mirror_syncreqs; i++) { bp = g_alloc_bio(); - disk->d_sync.ds_bios[i] = bp; - bp->bio_parent = NULL; - bp->bio_cmd = BIO_READ; + sync->ds_bios[i] = bp; + bp->bio_data = malloc(MAXPHYS, M_MIRROR, M_WAITOK); - bp->bio_cflags = 0; - bp->bio_offset = disk->d_sync.ds_offset; - bp->bio_length = MIN(MAXPHYS, sc->sc_mediasize - bp->bio_offset); - disk->d_sync.ds_offset += bp->bio_length; - bp->bio_done = g_mirror_sync_done; - bp->bio_from = disk->d_sync.ds_consumer; - bp->bio_to = sc->sc_provider; bp->bio_caller1 = (void *)(uintptr_t)i; + g_mirror_sync_reinit(disk, bp, sync->ds_offset); + sync->ds_offset += bp->bio_length; } /* Increase the number of disks in SYNCHRONIZING state. */ sc->sc_sync.ds_ndisks++; /* Set the number of in-flight synchronization requests. */ - disk->d_sync.ds_inflight = g_mirror_syncreqs; + sync->ds_inflight = g_mirror_syncreqs; /* * Fire off first synchronization requests. */ for (i = 0; i < g_mirror_syncreqs; i++) { - bp = disk->d_sync.ds_bios[i]; + bp = sync->ds_bios[i]; G_MIRROR_LOGREQ(3, bp, "Sending synchronization request."); - disk->d_sync.ds_consumer->index++; + sync->ds_consumer->index++; /* * Delay the request if it is colliding with a regular request. */ if (g_mirror_regular_collision(sc, bp)) g_mirror_sync_delay(sc, bp); else - g_io_request(bp, disk->d_sync.ds_consumer); + g_io_request(bp, sync->ds_consumer); } } From a19e74290194cd27ff028cf93bb4d4256c3b15db Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 10 Jan 2018 19:41:05 +0000 Subject: [PATCH 086/158] Add regression tests for r327779. MFC after: 2 weeks Sponsored by: Dell EMC Isilon --- tests/sys/geom/class/mirror/Makefile | 2 + tests/sys/geom/class/mirror/sync_error.sh | 110 ++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 tests/sys/geom/class/mirror/sync_error.sh diff --git a/tests/sys/geom/class/mirror/Makefile b/tests/sys/geom/class/mirror/Makefile index 095fb901cfaf..817d5d66e971 100644 --- a/tests/sys/geom/class/mirror/Makefile +++ b/tests/sys/geom/class/mirror/Makefile @@ -18,6 +18,8 @@ TAP_TESTS_SH+= 11_test TAP_TESTS_SH+= 12_test TAP_TESTS_SH+= 13_test +ATF_TESTS_SH+= sync_error + ${PACKAGE}FILES+= conf.sh .for t in ${TAP_TESTS_SH} diff --git a/tests/sys/geom/class/mirror/sync_error.sh b/tests/sys/geom/class/mirror/sync_error.sh new file mode 100644 index 000000000000..89fd31e9d935 --- /dev/null +++ b/tests/sys/geom/class/mirror/sync_error.sh @@ -0,0 +1,110 @@ +# $FreeBSD$ + +REG_READ_FP=debug.fail_point.g_mirror_regular_request_read + +atf_test_case sync_read_error_2_disks cleanup +sync_read_error_2_disks_head() +{ + atf_set "descr" \ + "Ensure that we properly handle read errors during synchronization." + atf_set "require.user" "root" +} +sync_read_error_2_disks_body() +{ + . $(atf_get_srcdir)/conf.sh + + f1=$(mktemp ${base}.XXXXXX) + f2=$(mktemp ${base}.XXXXXX) + + atf_check dd if=/dev/zero bs=1M count=32 of=$f1 status=none + atf_check truncate -s 32M $f2 + + md1=$(attach_md -t vnode -f ${f1}) + md2=$(attach_md -t vnode -f ${f2}) + + atf_check gmirror label $name $md1 + devwait + + atf_check -s exit:0 -e empty -o not-empty sysctl ${REG_READ_FP}='1*return(5)' + + # If a read error occurs while synchronizing and the mirror contains + # a single active disk, gmirror has no choice but to fail the + # synchronization and kick the new disk out of the mirror. + atf_check gmirror insert $name $md2 + sleep 0.1 + syncwait + atf_check [ $(gmirror status -s $name | wc -l) -eq 1 ] + atf_check -s exit:0 -o match:"DEGRADED $md1 \(ACTIVE\)" \ + gmirror status -s $name +} +sync_read_error_2_disks_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + + atf_check -s exit:0 -e empty -o not-empty sysctl ${REG_READ_FP}='off' + gmirror_test_cleanup +} + +atf_test_case sync_read_error_3_disks cleanup +sync_read_error_3_disks_head() +{ + atf_set "descr" \ + "Ensure that we properly handle read errors during synchronization." + atf_set "require.user" "root" +} +sync_read_error_3_disks_body() +{ + . $(atf_get_srcdir)/conf.sh + + f1=$(mktemp ${base}.XXXXXX) + f2=$(mktemp ${base}.XXXXXX) + f3=$(mktemp ${base}.XXXXXX) + + atf_check dd if=/dev/random bs=1M count=32 of=$f1 status=none + atf_check truncate -s 32M $f2 + atf_check truncate -s 32M $f3 + + md1=$(attach_md -t vnode -f ${f1}) + md2=$(attach_md -t vnode -f ${f2}) + md3=$(attach_md -t vnode -f ${f3}) + + atf_check gmirror label $name $md1 + devwait + + atf_check gmirror insert $name $md2 + syncwait + + atf_check -s exit:0 -e empty -o not-empty sysctl ${REG_READ_FP}='1*return(5)' + + # If a read error occurs while synchronizing a new disk, and we have + # multiple active disks, we retry the read after an error. The disk + # which returned the read error is kicked out of the mirror. + atf_check gmirror insert $name $md3 + syncwait + atf_check [ $(gmirror status -s $name | wc -l) -eq 2 ] + atf_check -s exit:0 -o match:"DEGRADED $md3 \(ACTIVE\)" \ + gmirror status -s $name + + # Make sure that the two active disks are identical. Destroy the + # mirror first so that the metadata sectors are wiped. + if $(gmirror status -s $name | grep -q $md1); then + active=$md1 + else + active=$md2 + fi + atf_check gmirror destroy $name + atf_check cmp /dev/$active /dev/$md3 +} +sync_read_error_3_disks_cleanup() +{ + . $(atf_get_srcdir)/conf.sh + + atf_check -s exit:0 -e empty -o not-empty sysctl ${REG_READ_FP}='off' + gmirror_test_cleanup +} + +atf_init_test_cases() +{ + atf_add_test_case sync_read_error_2_disks + atf_add_test_case sync_read_error_3_disks +} From 802258f46b43e98d0b36440f1d38c6f2d3578062 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Wed, 10 Jan 2018 19:45:38 +0000 Subject: [PATCH 087/158] Use mallocarray(9) in dirhash. Basic use of mallocarray to prevent overflows. Here allocation is done with M_NOWAIT so the code is prepared for the possibility of returning NULL values. Since mallocarray expects unsigned parameters, unsign some related variables to minimize sign conversions. Reviewed by: mckusick --- sys/ufs/ufs/ufs_dirhash.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sys/ufs/ufs/ufs_dirhash.c b/sys/ufs/ufs/ufs_dirhash.c index 77bef146d6fd..0d387efe6efc 100644 --- a/sys/ufs/ufs/ufs_dirhash.c +++ b/sys/ufs/ufs/ufs_dirhash.c @@ -349,7 +349,8 @@ ufsdirhash_build(struct inode *ip) struct direct *ep; struct vnode *vp; doff_t bmask, pos; - int dirblocks, i, j, memreqd, nblocks, narrays, nslots, slot; + int j, memreqd, slot; + u_int dirblocks, i, nblocks, narrays, nslots; /* Take care of a decreased sysctl value. */ while (ufs_dirhashmem > ufs_dirhashmaxmem) { @@ -415,11 +416,11 @@ ufsdirhash_build(struct inode *ip) * Use non-blocking mallocs so that we will revert to a linear * lookup on failure rather than potentially blocking forever. */ - dh->dh_hash = malloc(narrays * sizeof(dh->dh_hash[0]), + dh->dh_hash = mallocarray(narrays, sizeof(dh->dh_hash[0]), M_DIRHASH, M_NOWAIT | M_ZERO); if (dh->dh_hash == NULL) goto fail; - dh->dh_blkfree = malloc(nblocks * sizeof(dh->dh_blkfree[0]), + dh->dh_blkfree = mallocarray(nblocks, sizeof(dh->dh_blkfree[0]), M_DIRHASH, M_NOWAIT); if (dh->dh_blkfree == NULL) goto fail; From c93a33340f60ba5fa9571f1d1d8a8c47b4e4b59e Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Wed, 10 Jan 2018 20:05:19 +0000 Subject: [PATCH 088/158] dev/bxe: make use of mallocarray(9). Use mallocarray in a couple of cases where a calloc-like operation is taking place. --- sys/dev/bxe/bxe.c | 3 ++- sys/dev/bxe/ecore_sp.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sys/dev/bxe/bxe.c b/sys/dev/bxe/bxe.c index 6acdbc0c6424..795b42184d9a 100644 --- a/sys/dev/bxe/bxe.c +++ b/sys/dev/bxe/bxe.c @@ -12018,7 +12018,8 @@ bxe_set_mc_list(struct bxe_softc *sc) } bzero(mta, (sizeof(unsigned char) * ETHER_ADDR_LEN * mc_count)); - mc_mac = malloc(sizeof(*mc_mac) * mc_count, M_DEVBUF, (M_NOWAIT | M_ZERO)); + mc_mac = mallocarray(mc_count, sizeof(*mc_mac), M_DEVBUF, + (M_NOWAIT | M_ZERO)); mc_mac_start = mc_mac; if (!mc_mac) { diff --git a/sys/dev/bxe/ecore_sp.h b/sys/dev/bxe/ecore_sp.h index bbc6dd9c83a3..86f8e012550f 100644 --- a/sys/dev/bxe/ecore_sp.h +++ b/sys/dev/bxe/ecore_sp.h @@ -159,7 +159,7 @@ typedef struct mtx ECORE_MUTEX_SPIN; malloc(_size, M_TEMP, (M_NOWAIT | M_ZERO)) #define ECORE_CALLOC(_len, _size, _flags, _sc) \ - malloc(_len * _size, M_TEMP, (M_NOWAIT | M_ZERO)) + mallocarray(_len, _size, M_TEMP, (M_NOWAIT | M_ZERO)) #define ECORE_FREE(_s, _buf, _size) free(_buf, M_TEMP) From 93b7a1c15336e9b970e304e7478df9898454c68a Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Wed, 10 Jan 2018 20:28:01 +0000 Subject: [PATCH 089/158] Enable ld.lld as bootstrap linker by default on amd64 For some time we have been planning to migrate to LLVM's lld linker. Having a man page was the last blocking issue for using ld.lld to link the base system kernel + userland, now addressed by r327770. Link the kernel and userland libraries and binaries with ld.lld by default, for additional test coverage. This has been a long time in the making. On 2013-04-13 I submitted an upstream tracking issue in LLVM PR 23214: [META] Using LLD as FreeBSD's system linker. Since then 85 individual issues were identified, and submitted as dependencies. These have been addressed along with two and a half years of other lld development and improvement. I'd like to express deep gratitude to upstream lld developers Rui Ueyama, Rafael Espindola, George Rimar and Davide Italiano. They put in substantial effort in addressing the issues we found affecting FreeBSD/amd64. To revert to using ld.bfd as the bootstrap linker, in /etc/src.conf set WITHOUT_LLD_BOOTSTRAP=yes If you need to set this, please follow up with a PR or post to the freebsd-toolchain mailing list explaining how default WITH_LLD_BOOTSTRAP failed for your use case. Note that GNU ld.bfd is still installed as /usr/bin/ld, and will still be used for linking ports. ld.lld can be installed as /usr/bin/ld by setting in /etc/src.conf WITH_LLD_IS_LLD=yes A followup commit will set WITH_LLD_IS_LD by default, possibly after Clang/LLVM/lld 6.0 is merged to FreeBSD. Release notes: Yes Sponsored by: The FreeBSD Foundation --- share/mk/src.opts.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk index 67c1c811ca8f..0d8c38b646e3 100644 --- a/share/mk/src.opts.mk +++ b/share/mk/src.opts.mk @@ -253,6 +253,9 @@ __DEFAULT_NO_OPTIONS+=LLVM_LIBUNWIND .endif .if ${__T} == "aarch64" __DEFAULT_YES_OPTIONS+=LLD_BOOTSTRAP LLD_IS_LD +.elif ${__T} == "amd64" +__DEFAULT_YES_OPTIONS+=LLD_BOOTSTRAP +__DEFAULT_NO_OPTIONS+=LLD_IS_LD .else __DEFAULT_NO_OPTIONS+=LLD_BOOTSTRAP LLD_IS_LD .endif From 737afa08a46d99a264fab8ed1c090b02be58680a Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Wed, 10 Jan 2018 20:36:16 +0000 Subject: [PATCH 090/158] regen src.conf.5 after r327783, WITH_LLD_BOOTSTRAP default (I missed the Reviewed by and review link from r327783.) Reviewed by: brooks, dim, bapt Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D13827 --- share/man/man5/src.conf.5 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5 index 0a4b1d2d3df9..af76f3226bcd 100644 --- a/share/man/man5/src.conf.5 +++ b/share/man/man5/src.conf.5 @@ -970,12 +970,12 @@ To be able to build the system, either Binutils or LLD bootstrap must be enabled unless an alternate linker is provided via XLD. .Pp This is a default setting on -amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv7, i386/i386, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32, mips/mipselhf, mips/mipshf, mips/mips64elhf, mips/mips64hf, powerpc/powerpc, powerpc/powerpc64, powerpc/powerpcspe, riscv/riscv64, riscv/riscv64sf and sparc64/sparc64. +arm/arm, arm/armeb, arm/armv6, arm/armv7, i386/i386, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32, mips/mipselhf, mips/mipshf, mips/mips64elhf, mips/mips64hf, powerpc/powerpc, powerpc/powerpc64, powerpc/powerpcspe, riscv/riscv64, riscv/riscv64sf and sparc64/sparc64. .It Va WITH_LLD_BOOTSTRAP Set to build the LLD linker during the bootstrap phase of the build. .Pp This is a default setting on -arm64/aarch64. +amd64/amd64 and arm64/aarch64. .It Va WITHOUT_LLD_IS_LD Set to use GNU binutils ld as the system linker, instead of LLVM's LLD. .Pp From 92593573d5c654570de38609434de74c906640b5 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Wed, 10 Jan 2018 20:49:01 +0000 Subject: [PATCH 091/158] Mention switch to ld.lld for amd64 in UPDATING Sponsored by: The FreeBSD Foundation --- UPDATING | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/UPDATING b/UPDATING index ad30ed2b3506..c65431ce29f1 100644 --- a/UPDATING +++ b/UPDATING @@ -51,6 +51,14 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW: ****************************** SPECIAL WARNING: ****************************** +20180110: + LLVM's lld linker is now used as the FreeBSD/amd64 bootstrap linker. + This means it is used to link the kernel and userland libraries and + executables, but is not yet installed as /usr/bin/ld by default. + + To revert to ld.bfd as the bootstrap linker, in /etc/src.conf set + WITHOUT_LLD_BOOTSTRAP=yes + 20180110: On i386, pmtimer has been removed. It's functionality has been folded into apm. It was a nop on ACPI in current for a while now (but was still From ed595433c6fbde38e0b726ed5c10359be51dae9b Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Wed, 10 Jan 2018 20:50:06 +0000 Subject: [PATCH 092/158] linuxkpi: Simplify kmalloc_array. kmalloc_array seems what we call mallocarray(9). --- sys/compat/linuxkpi/common/include/linux/slab.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sys/compat/linuxkpi/common/include/linux/slab.h b/sys/compat/linuxkpi/common/include/linux/slab.h index 1f8ec82db985..a0fdd426435e 100644 --- a/sys/compat/linuxkpi/common/include/linux/slab.h +++ b/sys/compat/linuxkpi/common/include/linux/slab.h @@ -121,9 +121,7 @@ vmalloc_32(size_t size) static inline void * kmalloc_array(size_t n, size_t size, gfp_t flags) { - if (size != 0 && n > (SIZE_MAX / size)) - return (NULL); - return (malloc(n * size, M_KMALLOC, linux_check_m_flags(flags))); + return (mallocarray(n, size, M_KMALLOC, linux_check_m_flags(flags))); } static inline void * From a27a25f759579d2983a416a56e9ec6242106c30b Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Wed, 10 Jan 2018 21:08:43 +0000 Subject: [PATCH 093/158] Set the 'FR' bit in the status register for N32 kernels. This permits N32 hard-float binaries to use 64-bit floating point registers (which is what N32 binaries expect) matching the N64 ABI. Reviewed by: imp, jmallett Sponsored by: DARPA / AFRL Differential Revision: https://reviews.freebsd.org/D13830 --- sys/mips/mips/exception.S | 2 +- sys/mips/mips/locore.S | 5 ++++- sys/mips/mips/swtch.S | 6 +++--- sys/mips/mips/trap.c | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/sys/mips/mips/exception.S b/sys/mips/mips/exception.S index 4e4372678974..865abf970ed5 100644 --- a/sys/mips/mips/exception.S +++ b/sys/mips/mips/exception.S @@ -1110,7 +1110,7 @@ NESTED(MipsFPTrap, CALLFRAME_SIZ, ra) REG_S ra, CALLFRAME_RA(sp) .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ) -#if defined(__mips_n64) +#if defined(__mips_n32) || defined(__mips_n64) or t1, t0, MIPS_SR_COP_1_BIT | MIPS_SR_FR #else or t1, t0, MIPS_SR_COP_1_BIT diff --git a/sys/mips/mips/locore.S b/sys/mips/mips/locore.S index ad28e4b14951..e8702a019239 100644 --- a/sys/mips/mips/locore.S +++ b/sys/mips/mips/locore.S @@ -117,8 +117,11 @@ VECTOR(_locore, unknown) * Enable FPU */ li t1, MIPS_SR_COP_1_BIT +#if defined(__mips_n32) || defined(__mips_n64) + or t1, MIPS_SR_FR +#endif #ifdef __mips_n64 - or t1, MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX | MIPS_SR_FR + or t1, MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX #endif #endif /* diff --git a/sys/mips/mips/swtch.S b/sys/mips/mips/swtch.S index 6fced0bc4b8a..b4c7b03fb068 100644 --- a/sys/mips/mips/swtch.S +++ b/sys/mips/mips/swtch.S @@ -416,7 +416,7 @@ LEAF(MipsSwitchFPState) .set hardfloat mfc0 t1, MIPS_COP_0_STATUS # Save old SR HAZARD_DELAY -#if defined(__mips_n64) +#if defined(__mips_n32) || defined(__mips_n64) or t0, t1, MIPS_SR_COP_1_BIT | MIPS_SR_FR # enable the coprocessor #else or t0, t1, MIPS_SR_COP_1_BIT # enable the coprocessor @@ -546,7 +546,7 @@ LEAF(MipsFPID) .set hardfloat mfc0 t1, MIPS_COP_0_STATUS # Save the status register. HAZARD_DELAY -#if defined(__mips_n64) +#if defined(__mips_n32) || defined(__mips_n64) or t0, t1, MIPS_SR_COP_1_BIT | MIPS_SR_FR #else or t0, t1, MIPS_SR_COP_1_BIT @@ -585,7 +585,7 @@ LEAF(MipsSaveCurFPState) PTR_L a0, TD_PCB(a0) # get pointer to pcb for thread mfc0 t1, MIPS_COP_0_STATUS # Disable interrupts and HAZARD_DELAY -#if defined(__mips_n64) +#if defined(__mips_n32) || defined(__mips_n64) or t0, t1, MIPS_SR_COP_1_BIT | MIPS_SR_FR # enable the coprocessor #else or t0, t1, MIPS_SR_COP_1_BIT # enable the coprocessor diff --git a/sys/mips/mips/trap.c b/sys/mips/mips/trap.c index c31d323108f5..5e19c6b6752e 100644 --- a/sys/mips/mips/trap.c +++ b/sys/mips/mips/trap.c @@ -983,7 +983,7 @@ trap(struct trapframe *trapframe) addr = trapframe->pc; MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame); PCPU_SET(fpcurthread, td); -#if defined(__mips_n64) +#if defined(__mips_n32) || defined(__mips_n64) td->td_frame->sr |= MIPS_SR_COP_1_BIT | MIPS_SR_FR; #else td->td_frame->sr |= MIPS_SR_COP_1_BIT; From 86bbef4379b425cbf21b188f541e14676e1e6077 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Wed, 10 Jan 2018 21:18:46 +0000 Subject: [PATCH 094/158] Don't store shadow copies of per-process AIO limits. Previously the AIO subsystem would save a snapshot of the currently configured per-process limits the first time a process used AIO. The process would continue to use the snapshotted limits ignoring any changes to the global limits during the rest of its lifetime. This change removes the snapshotted values and changes the AIO code to always check the global values which can be toggled at runtime. This means an administrator can now change the effective limits of existing processes. This is more consistent with how other limits configured via sysctl work in FreeBSD. Reviewed by: asomers, kib MFC after: 2 weeks Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D13819 --- sys/kern/vfs_aio.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index 06d136a76390..4b7c4be1be93 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -166,16 +166,16 @@ SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_lifetime, CTLFLAG_RW, &aiod_lifetime, 0, static int max_aio_per_proc = MAX_AIO_PER_PROC; SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_per_proc, CTLFLAG_RW, &max_aio_per_proc, 0, - "Maximum active aio requests per process (stored in the process)"); + "Maximum active aio requests per process"); static int max_aio_queue_per_proc = MAX_AIO_QUEUE_PER_PROC; SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue_per_proc, CTLFLAG_RW, &max_aio_queue_per_proc, 0, - "Maximum queued aio requests per process (stored in the process)"); + "Maximum queued aio requests per process"); static int max_buf_aio = MAX_BUF_AIO; SYSCTL_INT(_vfs_aio, OID_AUTO, max_buf_aio, CTLFLAG_RW, &max_buf_aio, 0, - "Maximum buf aio requests per process (stored in the process)"); + "Maximum buf aio requests per process"); /* * Though redundant with vfs.aio.max_aio_queue_per_proc, POSIX requires @@ -268,11 +268,8 @@ struct aioliojob { struct kaioinfo { struct mtx kaio_mtx; /* the lock to protect this struct */ int kaio_flags; /* (a) per process kaio flags */ - int kaio_maxactive_count; /* (*) maximum number of AIOs */ int kaio_active_count; /* (c) number of currently used AIOs */ - int kaio_qallowed_count; /* (*) maxiumu size of AIO queue */ int kaio_count; /* (a) size of AIO queue */ - int kaio_ballowed_count; /* (*) maximum number of buffers */ int kaio_buffer_count; /* (a) number of physio buffers */ TAILQ_HEAD(,kaiocb) kaio_all; /* (a) all AIOs in a process */ TAILQ_HEAD(,kaiocb) kaio_done; /* (a) done queue for process */ @@ -445,11 +442,8 @@ aio_init_aioinfo(struct proc *p) ki = uma_zalloc(kaio_zone, M_WAITOK); mtx_init(&ki->kaio_mtx, "aiomtx", NULL, MTX_DEF | MTX_NEW); ki->kaio_flags = 0; - ki->kaio_maxactive_count = max_aio_per_proc; ki->kaio_active_count = 0; - ki->kaio_qallowed_count = max_aio_queue_per_proc; ki->kaio_count = 0; - ki->kaio_ballowed_count = max_buf_aio; ki->kaio_buffer_count = 0; TAILQ_INIT(&ki->kaio_all); TAILQ_INIT(&ki->kaio_done); @@ -708,7 +702,7 @@ aio_selectjob(struct aioproc *aiop) userp = job->userproc; ki = userp->p_aioinfo; - if (ki->kaio_active_count < ki->kaio_maxactive_count) { + if (ki->kaio_active_count < max_aio_per_proc) { TAILQ_REMOVE(&aio_jobs, job, list); if (!aio_clear_cancel_function(job)) goto restart; @@ -1270,7 +1264,7 @@ aio_qphysio(struct proc *p, struct kaiocb *job) error = -1; goto unref; } - if (ki->kaio_buffer_count >= ki->kaio_ballowed_count) { + if (ki->kaio_buffer_count >= max_buf_aio) { error = EAGAIN; goto unref; } @@ -1479,7 +1473,7 @@ aio_aqueue(struct thread *td, struct aiocb *ujob, struct aioliojob *lj, ops->store_kernelinfo(ujob, -1); if (num_queue_count >= max_queue_count || - ki->kaio_count >= ki->kaio_qallowed_count) { + ki->kaio_count >= max_aio_queue_per_proc) { ops->store_error(ujob, EAGAIN); return (EAGAIN); } @@ -1774,8 +1768,7 @@ aio_kick_nowait(struct proc *userp) aiop->aioprocflags &= ~AIOP_FREE; wakeup(aiop->aioproc); } else if (num_aio_resv_start + num_aio_procs < max_aio_procs && - ki->kaio_active_count + num_aio_resv_start < - ki->kaio_maxactive_count) { + ki->kaio_active_count + num_aio_resv_start < max_aio_per_proc) { taskqueue_enqueue(taskqueue_aiod_kick, &ki->kaio_task); } } @@ -1794,8 +1787,7 @@ aio_kick(struct proc *userp) aiop->aioprocflags &= ~AIOP_FREE; wakeup(aiop->aioproc); } else if (num_aio_resv_start + num_aio_procs < max_aio_procs && - ki->kaio_active_count + num_aio_resv_start < - ki->kaio_maxactive_count) { + ki->kaio_active_count + num_aio_resv_start < max_aio_per_proc) { num_aio_resv_start++; mtx_unlock(&aio_job_mtx); error = aio_newproc(&num_aio_resv_start); From ff9ebfc4b618ee0113b23fb36ae4adfea62e31e2 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 10 Jan 2018 21:37:11 +0000 Subject: [PATCH 095/158] Fix an off-by-one in dt_opt_setenv(). The bug would cause incorrect behaviour when attempting to override an already set environment variable with -x setenv, as long as the variable is not the last one in the array. Reported by: Samuel Lepetit MFC after: 2 weeks --- .../lib/libdtrace/common/dt_options.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c index 758422e3407f..c99e6007f9da 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c @@ -415,7 +415,7 @@ dt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) { char **p; char *var; - int i; + int nvars; /* * We can't effectively set environment variables from #pragma lines @@ -430,7 +430,7 @@ dt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) if (!option && strchr(arg, '=') != NULL) return (dt_set_errno(dtp, EDT_BADOPTVAL)); - for (i = 1, p = dtp->dt_proc_env; *p != NULL; i++, p++) + for (nvars = 0, p = dtp->dt_proc_env; *p != NULL; nvars++, p++) continue; for (p = dtp->dt_proc_env; *p != NULL; p++) { @@ -439,9 +439,9 @@ dt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) var = *p + strlen(*p); if (strncmp(*p, arg, var - *p) == 0) { dt_free(dtp, *p); - *p = dtp->dt_proc_env[i - 1]; - dtp->dt_proc_env[i - 1] = NULL; - i--; + *p = dtp->dt_proc_env[nvars - 1]; + dtp->dt_proc_env[nvars - 1] = NULL; + nvars--; } } @@ -449,17 +449,18 @@ dt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) if ((var = strdup(arg)) == NULL) return (dt_set_errno(dtp, EDT_NOMEM)); - if ((p = dt_alloc(dtp, sizeof (char *) * (i + 1))) == NULL) { + nvars++; + if ((p = dt_alloc(dtp, sizeof(char *) * (nvars + 1))) == NULL) { dt_free(dtp, var); return (dt_set_errno(dtp, EDT_NOMEM)); } - bcopy(dtp->dt_proc_env, p, sizeof (char *) * i); + bcopy(dtp->dt_proc_env, p, sizeof(char *) * nvars); dt_free(dtp, dtp->dt_proc_env); dtp->dt_proc_env = p; - dtp->dt_proc_env[i - 1] = var; - dtp->dt_proc_env[i] = NULL; + dtp->dt_proc_env[nvars - 1] = var; + dtp->dt_proc_env[nvars] = NULL; } return (0); From 60eddb209b5ad13a549ca74a41b7cb38a31da5ef Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 10 Jan 2018 21:40:36 +0000 Subject: [PATCH 096/158] Add a regression test for r327794. MFC after: 2 weeks --- .../test/tst/common/env/tst.setenv3.ksh | 34 +++++++++++++++++++ .../test/tst/common/env/tst.setenv3.ksh.out | 2 ++ .../usr.sbin/dtrace/tests/common/env/Makefile | 2 ++ 3 files changed, 38 insertions(+) create mode 100644 cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/env/tst.setenv3.ksh create mode 100644 cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/env/tst.setenv3.ksh.out diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/env/tst.setenv3.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/env/tst.setenv3.ksh new file mode 100644 index 000000000000..50eb16e45d44 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/env/tst.setenv3.ksh @@ -0,0 +1,34 @@ +# +# CDDL HEADER START +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# +# CDDL HEADER END +# + +# +# Copyright (c) 2012 by Delphix. All rights reserved. +# + +# +# Reset an environment variable we already know to be set. +# Regression test for FreeBSD r327794. +# + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +$dtrace -q -Z -n doogle -xsetenv=PATH=/foo -c '/usr/bin/printenv PATH' + +exit $? diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/env/tst.setenv3.ksh.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/env/tst.setenv3.ksh.out new file mode 100644 index 000000000000..699539b069ec --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/env/tst.setenv3.ksh.out @@ -0,0 +1,2 @@ +/foo + diff --git a/cddl/usr.sbin/dtrace/tests/common/env/Makefile b/cddl/usr.sbin/dtrace/tests/common/env/Makefile index d9fb178ea43f..9c37c28b448b 100644 --- a/cddl/usr.sbin/dtrace/tests/common/env/Makefile +++ b/cddl/usr.sbin/dtrace/tests/common/env/Makefile @@ -15,6 +15,8 @@ ${PACKAGE}FILES= \ tst.setenv1.ksh.out \ tst.setenv2.ksh \ tst.setenv2.ksh.out \ + tst.setenv3.ksh \ + tst.setenv3.ksh.out \ tst.unsetenv1.ksh \ tst.unsetenv1.ksh.out \ tst.unsetenv2.ksh \ From c02fc9607a219ec673b148cdfc211b15ce687b80 Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Wed, 10 Jan 2018 21:49:45 +0000 Subject: [PATCH 097/158] mallocarray(9): panic if the requested allocation would overflow Additionally, move the overflow check logic out to WOULD_OVERFLOW() for consumers to have a common means of testing for overflowing allocations. WOULD_OVERFLOW() should be a secondary check -- on 64-bit platforms, just because an allocation won't overflow size_t does not mean it is a sane size to request. Callers should be imposing reasonable allocation limits far, far, below overflow. Discussed with: emaste, jhb, kp Sponsored by: Dell EMC Isilon --- share/man/man9/malloc.9 | 11 +++++------ sys/kern/kern_malloc.c | 10 ++-------- sys/sys/malloc.h | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/share/man/man9/malloc.9 b/share/man/man9/malloc.9 index 674cd30dbb24..bd26600a65f7 100644 --- a/share/man/man9/malloc.9 +++ b/share/man/man9/malloc.9 @@ -29,7 +29,7 @@ .\" $NetBSD: malloc.9,v 1.3 1996/11/11 00:05:11 lukem Exp $ .\" $FreeBSD$ .\" -.Dd November 19, 2015 +.Dd January 10, 2018 .Dt MALLOC 9 .Os .Sh NAME @@ -154,6 +154,7 @@ If the request cannot be immediately fulfilled, the current process is put to sleep to wait for resources to be released by other processes. The .Fn malloc , +.Fn mallocarray , .Fn realloc , and .Fn reallocf @@ -162,15 +163,13 @@ functions cannot return if .Dv M_WAITOK is specified. -The -.Fn mallocarray -function can return -.Dv NULL if the multiplication of .Fa nmemb and .Fa size -would cause an integer overflow. +would cause an integer overflow, the +.Fn mallocarray +function induces a panic. .It Dv M_USE_RESERVE Indicates that the system can use its reserve of memory to satisfy the request. diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c index 94be535a71c9..010b1ee8799b 100644 --- a/sys/kern/kern_malloc.c +++ b/sys/kern/kern_malloc.c @@ -535,18 +535,12 @@ malloc(unsigned long size, struct malloc_type *mtp, int flags) return ((void *) va); } -/* - * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX - * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW - */ -#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 8 / 2)) void * mallocarray(size_t nmemb, size_t size, struct malloc_type *type, int flags) { - if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && - nmemb > 0 && SIZE_MAX / nmemb < size) - return (NULL); + if (WOULD_OVERFLOW(nmemb, size)) + panic("mallocarray: %zu * %zu overflowed", nmemb, size); return (malloc(size * nmemb, type, flags)); } diff --git a/sys/sys/malloc.h b/sys/sys/malloc.h index 119b2448f7c5..47ca13f5ebd6 100644 --- a/sys/sys/malloc.h +++ b/sys/sys/malloc.h @@ -41,6 +41,7 @@ #include #include #include +#include #define MINALLOCSIZE UMA_SMALLEST_UNIT @@ -192,6 +193,20 @@ void *reallocf(void *addr, unsigned long size, struct malloc_type *type, int flags) __result_use_check __alloc_size(2); struct malloc_type *malloc_desc2type(const char *desc); + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 8 / 2)) +static inline bool +WOULD_OVERFLOW(size_t nmemb, size_t size) +{ + + return ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && __SIZE_T_MAX / nmemb < size); +} +#undef MUL_NO_OVERFLOW #endif /* _KERNEL */ #endif /* !_SYS_MALLOC_H_ */ From a1df0d95920001141206ae9c25270c3f9c754af9 Mon Sep 17 00:00:00 2001 From: "Landon J. Fuller" Date: Wed, 10 Jan 2018 22:19:11 +0000 Subject: [PATCH 098/158] Fix minor locking issues in the Power Mac Uninorth PCI bridge driver. - Call resource_int_value() once during attach, rather than within the pci_(read|write)_config() code path; this avoids taking a blocking mutex to read kenv variables. - Use a spin lock to protect non-atomic config space accesses; this matches the behavior of Darwin's AppleMacRiscPCI driver. Reviewed by: jhibbits Differential Revision: https://reviews.freebsd.org/D13839 --- sys/powerpc/powermac/uninorthpci.c | 35 +++++++++++++++++++++--------- sys/powerpc/powermac/uninorthvar.h | 2 ++ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/sys/powerpc/powermac/uninorthpci.c b/sys/powerpc/powermac/uninorthpci.c index c49598a27c91..72c7106f53f3 100644 --- a/sys/powerpc/powermac/uninorthpci.c +++ b/sys/powerpc/powermac/uninorthpci.c @@ -34,6 +34,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include @@ -134,13 +136,17 @@ uninorth_attach(device_t dev) { struct uninorth_softc *sc; const char *compatible; + const char *name; phandle_t node; uint32_t reg[3]; uint64_t regbase; cell_t acells; + int unit; node = ofw_bus_get_node(dev); sc = device_get_softc(dev); + name = device_get_name(dev); + unit = device_get_unit(dev); if (OF_getprop(node, "reg", reg, sizeof(reg)) < 8) return (ENXIO); @@ -164,6 +170,11 @@ uninorth_attach(device_t dev) sc->sc_addr = (vm_offset_t)pmap_mapdev(regbase + 0x800000, PAGE_SIZE); sc->sc_data = (vm_offset_t)pmap_mapdev(regbase + 0xc00000, PAGE_SIZE); + if (resource_int_value(name, unit, "skipslot", &sc->sc_skipslot) != 0) + sc->sc_skipslot = -1; + + mtx_init(&sc->sc_cfg_mtx, "uninorth pcicfg", NULL, MTX_SPIN); + return (ofw_pci_attach(dev)); } @@ -173,25 +184,29 @@ uninorth_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, { struct uninorth_softc *sc; vm_offset_t caoff; + u_int32_t val; sc = device_get_softc(dev); caoff = sc->sc_data + (reg & 0x07); + val = 0xffffffff; + mtx_lock_spin(&sc->sc_cfg_mtx); if (uninorth_enable_config(sc, bus, slot, func, reg) != 0) { switch (width) { case 1: - return (in8rb(caoff)); + val = in8rb(caoff); break; case 2: - return (in16rb(caoff)); + val = in16rb(caoff); break; case 4: - return (in32rb(caoff)); + val = in32rb(caoff); break; } } + mtx_unlock_spin(&sc->sc_cfg_mtx); - return (0xffffffff); + return (val); } static void @@ -204,6 +219,7 @@ uninorth_write_config(device_t dev, u_int bus, u_int slot, u_int func, sc = device_get_softc(dev); caoff = sc->sc_data + (reg & 0x07); + mtx_lock_spin(&sc->sc_cfg_mtx); if (uninorth_enable_config(sc, bus, slot, func, reg)) { switch (width) { case 1: @@ -217,6 +233,7 @@ uninorth_write_config(device_t dev, u_int bus, u_int slot, u_int func, break; } } + mtx_unlock_spin(&sc->sc_cfg_mtx); } static int @@ -224,13 +241,11 @@ uninorth_enable_config(struct uninorth_softc *sc, u_int bus, u_int slot, u_int func, u_int reg) { uint32_t cfgval; - uint32_t pass; - if (resource_int_value(device_get_name(sc->pci_sc.sc_dev), - device_get_unit(sc->pci_sc.sc_dev), "skipslot", &pass) == 0) { - if (pass == slot) - return (0); - } + mtx_assert(&sc->sc_cfg_mtx, MA_OWNED); + + if (sc->sc_skipslot == slot) + return (0); /* * Issue type 0 configuration space accesses for the root bus. diff --git a/sys/powerpc/powermac/uninorthvar.h b/sys/powerpc/powermac/uninorthvar.h index 86a697c52227..d89933c4f462 100644 --- a/sys/powerpc/powermac/uninorthvar.h +++ b/sys/powerpc/powermac/uninorthvar.h @@ -39,6 +39,8 @@ struct uninorth_softc { vm_offset_t sc_addr; vm_offset_t sc_data; int sc_ver; + int sc_skipslot; + struct mtx sc_cfg_mtx; }; struct unin_chip_softc { From 0a8edd1cad3e6bce4fdf324abbc2c1fe368828c6 Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Wed, 10 Jan 2018 22:20:49 +0000 Subject: [PATCH 099/158] malloc.9: Fix minor typo from rewording in r327796 Sponsored by: Dell EMC Isilon --- share/man/man9/malloc.9 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/man/man9/malloc.9 b/share/man/man9/malloc.9 index bd26600a65f7..7bf4a4ed0ced 100644 --- a/share/man/man9/malloc.9 +++ b/share/man/man9/malloc.9 @@ -163,7 +163,7 @@ functions cannot return if .Dv M_WAITOK is specified. -if the multiplication of +If the multiplication of .Fa nmemb and .Fa size From e6fcf7898d1d453707a08c7eee5efe3043b634c6 Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Wed, 10 Jan 2018 22:41:00 +0000 Subject: [PATCH 100/158] x86: Document purpose of _safe variants of {rd,wr}msr() Sponsored by: Dell EMC Isilon --- sys/amd64/amd64/support.S | 6 ++++-- sys/i386/i386/support.s | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sys/amd64/amd64/support.S b/sys/amd64/amd64/support.S index 0ef6f498dbd2..5a69ffd2ca51 100644 --- a/sys/amd64/amd64/support.S +++ b/sys/amd64/amd64/support.S @@ -763,7 +763,8 @@ ENTRY(longjmp) END(longjmp) /* - * Support for reading MSRs in the safe manner. + * Support for reading MSRs in the safe manner. (Instead of panic on #gp, + * return an error.) */ ENTRY(rdmsr_safe) /* int rdmsr_safe(u_int msr, uint64_t *data) */ @@ -783,7 +784,8 @@ ENTRY(rdmsr_safe) ret /* - * Support for writing MSRs in the safe manner. + * Support for writing MSRs in the safe manner. (Instead of panic on #gp, + * return an error.) */ ENTRY(wrmsr_safe) /* int wrmsr_safe(u_int msr, uint64_t data) */ diff --git a/sys/i386/i386/support.s b/sys/i386/i386/support.s index 81a1786f5ff0..2fe4de7bc7f2 100644 --- a/sys/i386/i386/support.s +++ b/sys/i386/i386/support.s @@ -790,7 +790,8 @@ ENTRY(longjmp) END(longjmp) /* - * Support for reading MSRs in the safe manner. + * Support for reading MSRs in the safe manner. (Instead of panic on #gp, + * return an error.) */ ENTRY(rdmsr_safe) /* int rdmsr_safe(u_int msr, uint64_t *data) */ @@ -810,7 +811,8 @@ ENTRY(rdmsr_safe) ret /* - * Support for writing MSRs in the safe manner. + * Support for writing MSRs in the safe manner. (Instead of panic on #gp, + * return an error.) */ ENTRY(wrmsr_safe) /* int wrmsr_safe(u_int msr, uint64_t data) */ From dc045f499acc3e0d8c8e3b8f31cfc96b5a05c3a9 Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Wed, 10 Jan 2018 23:19:32 +0000 Subject: [PATCH 101/158] Add encrypt+authenticate modes to cryptotest tool Like jhb's cryptocheck (uncommitted so far), express encrypt+authenticate modes as "-a +". Example use with aesni(4) on AMD Zen family: $ ./cryptotest -d aesni0 -a aes256 10000 $((128*1024)) 2.331 sec, 20000 aes256 crypts, 131072 bytes, 1124707930 byte/sec, 8580.8 Mb/sec $ ./cryptotest -d aesni0 -a sha256 10000 $((128*1024)) 1.109 sec, 10000 sha256 crypts, 131072 bytes, 1181577161 byte/sec, 9014.7 Mb/sec $ ./cryptotest -d aesni0 -a aes256+sha256 10000 $((128*1024)) 3.805 sec, 10000 sha256+aes256 crypts, 131072 bytes, 344460116 byte/sec, 2628.0 Mb/sec Reported by: jhb Sponsored by: Dell EMC Isilon --- tools/tools/crypto/cryptotest.c | 85 +++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 25 deletions(-) diff --git a/tools/tools/crypto/cryptotest.c b/tools/tools/crypto/cryptotest.c index 2b5aa0af5085..2dc4890ee343 100644 --- a/tools/tools/crypto/cryptotest.c +++ b/tools/tools/crypto/cryptotest.c @@ -147,6 +147,8 @@ usage(const char* cmd) printf("where algorithm is one of:\n"); printf(" null des 3des (default) blowfish cast skipjack rij\n"); printf(" aes aes192 aes256 md5 sha1 sha256 sha384 sha512\n"); + printf(" or an encryption algorithm concatented with authentication\n"); + printf(" algorithm with '+' in the middle, e.g., aes+sha1.\n"); printf("count is the number of encrypt/decrypt ops to do\n"); printf("size is the number of bytes of text to encrypt+decrypt\n"); printf("\n"); @@ -248,7 +250,7 @@ rdigit(void) } void -runtest(struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) +runtest(struct alg *ealg, struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) { int i, fd = crget(); struct timeval start, stop, dt; @@ -256,18 +258,26 @@ runtest(struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) struct session2_op sop; struct crypt_op cop; char iv[EALG_MAX_BLOCK_LEN]; + char digest[512/8]; + + /* Canonicalize 'ealg' to crypt alg and 'alg' to authentication alg. */ + if (ealg == NULL && !alg->ishash) { + ealg = alg; + alg = NULL; + } bzero(&sop, sizeof(sop)); - if (!alg->ishash) { - sop.keylen = (alg->minkeylen + alg->maxkeylen)/2; + if (ealg != NULL) { + sop.keylen = (ealg->minkeylen + ealg->maxkeylen)/2; key = (char *) malloc(sop.keylen); if (key == NULL) err(1, "malloc (key)"); for (i = 0; i < sop.keylen; i++) key[i] = rdigit(); sop.key = key; - sop.cipher = alg->code; - } else { + sop.cipher = ealg->code; + } + if (alg != NULL) { sop.mackeylen = (alg->minkeylen + alg->maxkeylen)/2; key = (char *) malloc(sop.mackeylen); if (key == NULL) @@ -277,12 +287,16 @@ runtest(struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) sop.mackey = key; sop.mac = alg->code; } + sop.crid = crid; if (ioctl(fd, cmd, &sop) < 0) { if (cmd == CIOCGSESSION || cmd == CIOCGSESSION2) { close(fd); if (verbose) { - printf("cipher %s", alg->name); + printf("cipher %s%s%s", ealg? ealg->name : "", + (ealg && alg) ? "+" : "", + alg? alg->name : ""); + if (alg->ishash) printf(" mackeylen %u\n", sop.mackeylen); else @@ -292,8 +306,9 @@ runtest(struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) /* hardware doesn't support algorithm; skip it */ return; } - printf("cipher %s keylen %u mackeylen %u\n", - alg->name, sop.keylen, sop.mackeylen); + printf("cipher %s%s%s keylen %u mackeylen %u\n", + ealg? ealg->name : "", (ealg && alg) ? "+" : "", + alg? alg->name : "", sop.keylen, sop.mackeylen); err(1, "CIOCGSESSION"); } @@ -312,7 +327,7 @@ runtest(struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) printf("session = 0x%x\n", sop.ses); printf("device = %s\n", crfind(sop.crid)); printf("count = %d, size = %d\n", count, size); - if (!alg->ishash) { + if (ealg) { printf("iv:"); hexdump(iv, sizeof iv); } @@ -321,15 +336,18 @@ runtest(struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) } gettimeofday(&start, NULL); - if (!alg->ishash) { + if (ealg) { for (i = 0; i < count; i++) { cop.ses = sop.ses; cop.op = COP_ENCRYPT; - cop.flags = opflags; + cop.flags = opflags | COP_F_CIPHER_FIRST; cop.len = size; cop.src = cleartext; cop.dst = ciphertext; - cop.mac = 0; + if (alg) + cop.mac = digest; + else + cop.mac = 0; cop.iv = iv; if (ioctl(fd, CIOCCRYPT, &cop) < 0) @@ -347,7 +365,10 @@ runtest(struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) cop.len = size; cop.src = ciphertext; cop.dst = cleartext; - cop.mac = 0; + if (alg) + cop.mac = digest; + else + cop.mac = 0; cop.iv = iv; if (ioctl(fd, CIOCCRYPT, &cop) < 0) @@ -432,7 +453,7 @@ printt(const char* tag, struct cryptotstat *ts) #endif void -runtests(struct alg *alg, int count, int size, u_long cmd, int threads, int profile) +runtests(struct alg *ealg, struct alg *alg, int count, int size, u_long cmd, int threads, int profile) { int i, status; double t; @@ -441,11 +462,13 @@ runtests(struct alg *alg, int count, int size, u_long cmd, int threads, int prof struct timeval total; int otiming; - if (size % alg->blocksize) { + if (size % alg->blocksize || (ealg && size % ealg->blocksize)) { if (verbose) printf("skipping blocksize %u 'cuz not a multiple of " - "%s blocksize %u\n", - size, alg->name, alg->blocksize); + "%s blocksize %u (or %s blocksize %u)\n", + size, alg->name, alg->blocksize, + ealg ? ealg->name : "n/a", + ealg ? ealg->blocksize : 0); return; } @@ -476,13 +499,13 @@ runtests(struct alg *alg, int count, int size, u_long cmd, int threads, int prof CPU_SET(i, &mask); cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(mask), &mask); - runtest(alg, count, size, cmd, &tvp[i]); + runtest(ealg, alg, count, size, cmd, &tvp[i]); exit(0); } while (waitpid(WAIT_MYPGRP, &status, 0) != -1) ; } else - runtest(alg, count, size, cmd, tvp); + runtest(ealg, alg, count, size, cmd, tvp); t = 0; for (i = 0; i < threads; i++) @@ -491,8 +514,9 @@ runtests(struct alg *alg, int count, int size, u_long cmd, int threads, int prof int nops = alg->ishash ? count : 2*count; nops *= threads; - printf("%8.3lf sec, %7d %6s crypts, %7d bytes, %8.0lf byte/sec, %7.1lf Mb/sec\n", - t, nops, alg->name, size, (double)nops*size / t, + printf("%8.3lf sec, %7d %6s%s%6s crypts, %7d bytes, %8.0lf byte/sec, %7.1lf Mb/sec\n", + t, nops, alg->name, ealg? "+" : "", ealg? ealg->name : "", + size, (double)nops*size / t, (double)nops*size / t * 8 / 1024 / 1024); } #ifdef __FreeBSD__ @@ -519,7 +543,8 @@ runtests(struct alg *alg, int count, int size, u_long cmd, int threads, int prof int main(int argc, char **argv) { - struct alg *alg = NULL; + struct alg *alg = NULL, *ealg = NULL; + char *tmp; int count = 1; int sizes[128], nsizes = 0; u_long cmd = CIOCGSESSION2; @@ -539,13 +564,23 @@ main(int argc, char **argv) verbose++; break; case 'a': + tmp = strchr(optarg, '+'); + if (tmp != NULL) { + *tmp = '\0'; + ealg = getalgbyname(optarg); + if (ealg == NULL || ealg->ishash) + usage(argv[0]); + optarg = tmp + 1; + } + alg = getalgbyname(optarg); if (alg == NULL) { if (streq(optarg, "rijndael")) alg = getalgbyname("aes"); else usage(argv[0]); - } + } else if (ealg != NULL && !alg->ishash) + usage(argv[0]); break; case 'd': crid = crlookup(optarg); @@ -602,13 +637,13 @@ main(int argc, char **argv) int j; alg = &algorithms[i]; for (j = 0; j < nsizes; j++) - runtests(alg, count, sizes[j], cmd, maxthreads, profile); + runtests(ealg, alg, count, sizes[j], cmd, maxthreads, profile); } } else { if (alg == NULL) alg = getalgbycode(CRYPTO_3DES_CBC); for (i = 0; i < nsizes; i++) - runtests(alg, count, sizes[i], cmd, maxthreads, profile); + runtests(ealg, alg, count, sizes[i], cmd, maxthreads, profile); } return (0); From 776a2127efa4cf3e8cf65f98bb6cacaf0623ce8d Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 11 Jan 2018 00:22:24 +0000 Subject: [PATCH 102/158] Flesh out static dtrace probes for /dev/crypto ioctl errors. In particular, no probes were present for AEAD requests, but also for some other error cases in other ioctl requests. MFC after: 2 weeks Sponsored by: Chelsio Communications --- sys/opencrypto/cryptodev.c | 102 ++++++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 18 deletions(-) diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c index d73e09fcb6a5..0fc7ba6efe7a 100644 --- a/sys/opencrypto/cryptodev.c +++ b/sys/opencrypto/cryptodev.c @@ -443,6 +443,7 @@ cryptof_ioctl( default: CRYPTDEB("invalid cipher"); + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); } @@ -490,6 +491,7 @@ cryptof_ioctl( break; default: CRYPTDEB("invalid mac"); + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); } @@ -503,6 +505,8 @@ cryptof_ioctl( sop->keylen < txform->minkey) { CRYPTDEB("invalid cipher parameters"); error = EINVAL; + SDT_PROBE1(opencrypto, dev, ioctl, error, + __LINE__); goto bail; } @@ -511,6 +515,8 @@ cryptof_ioctl( if ((error = copyin(sop->key, crie.cri_key, crie.cri_klen / 8))) { CRYPTDEB("invalid key"); + SDT_PROBE1(opencrypto, dev, ioctl, error, + __LINE__); goto bail; } if (thash) @@ -524,6 +530,8 @@ cryptof_ioctl( sop->mackeylen > thash->keysize) { CRYPTDEB("invalid mac key length"); error = EINVAL; + SDT_PROBE1(opencrypto, dev, ioctl, error, + __LINE__); goto bail; } @@ -533,6 +541,8 @@ cryptof_ioctl( if ((error = copyin(sop->mackey, cria.cri_key, cria.cri_klen / 8))) { CRYPTDEB("invalid mac key"); + SDT_PROBE1(opencrypto, dev, ioctl, + error, __LINE__); goto bail; } } @@ -548,6 +558,8 @@ cryptof_ioctl( error = checkforsoftware(&crid); if (error) { CRYPTDEB("checkforsoftware"); + SDT_PROBE1(opencrypto, dev, ioctl, error, + __LINE__); goto bail; } } else @@ -555,6 +567,7 @@ cryptof_ioctl( error = crypto_newsession(&sid, (txform ? &crie : &cria), crid); if (error) { CRYPTDEB("crypto_newsession"); + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } @@ -565,6 +578,7 @@ cryptof_ioctl( if (cse == NULL) { crypto_freesession(sid); error = EINVAL; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); CRYPTDEB("csecreate"); goto bail; } @@ -597,8 +611,10 @@ cryptof_ioctl( case CIOCFSESSION: ses = *(u_int32_t *)data; cse = csefind(fcr, ses); - if (cse == NULL) + if (cse == NULL) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); + } csedelete(fcr, cse); error = csefree(cse); break; @@ -628,8 +644,10 @@ cryptof_ioctl( case CIOCKEY32: case CIOCKEY232: #endif - if (!crypto_userasymcrypto) + if (!crypto_userasymcrypto) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EPERM); /* XXX compat? */ + } #ifdef COMPAT_FREEBSD32 if (cmd == CIOCKEY32 || cmd == CIOCKEY232) { kop = &kopc; @@ -663,8 +681,12 @@ cryptof_ioctl( * fallback to doing them in software. */ *(int *)data = 0; - } else + } else { error = crypto_getfeat((int *)data); + if (error) + SDT_PROBE1(opencrypto, dev, ioctl, error, + __LINE__); + } break; case CIOCFINDDEV: error = cryptodev_find((struct crypt_find_op *)data); @@ -672,12 +694,15 @@ cryptof_ioctl( case CIOCCRYPTAEAD: caead = (struct crypt_aead *)data; cse = csefind(fcr, caead->ses); - if (cse == NULL) + if (cse == NULL) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); + } error = cryptodev_aead(cse, caead, active_cred, td); break; default: error = EINVAL; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); break; } return (error); @@ -892,12 +917,16 @@ cryptodev_aead( struct cryptodesc *crde = NULL, *crda = NULL; int error; - if (caead->len > 256*1024-4 || caead->aadlen > 256*1024-4) + if (caead->len > 256*1024-4 || caead->aadlen > 256*1024-4) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (E2BIG); + } if (cse->txform == NULL || cse->thash == NULL || caead->tag == NULL || - (caead->len % cse->txform->blocksize) != 0) + (caead->len % cse->txform->blocksize) != 0) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); + } uio = &cse->uio; uio->uio_iov = &cse->iovec; @@ -915,6 +944,7 @@ cryptodev_aead( crp = crypto_getreq(2); if (crp == NULL) { error = ENOMEM; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } @@ -927,12 +957,16 @@ cryptodev_aead( } if ((error = copyin(caead->aad, cse->uio.uio_iov[0].iov_base, - caead->aadlen))) + caead->aadlen))) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; + } if ((error = copyin(caead->src, (char *)cse->uio.uio_iov[0].iov_base + - caead->aadlen, caead->len))) + caead->aadlen, caead->len))) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; + } /* * For GCM, crd_len covers only the AAD. For other ciphers @@ -973,11 +1007,14 @@ cryptodev_aead( if (caead->iv) { if (caead->ivlen > sizeof cse->tmp_iv) { error = EINVAL; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } - if ((error = copyin(caead->iv, cse->tmp_iv, caead->ivlen))) + if ((error = copyin(caead->iv, cse->tmp_iv, caead->ivlen))) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; + } bcopy(cse->tmp_iv, crde->crd_iv, caead->ivlen); crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; } else { @@ -987,8 +1024,10 @@ cryptodev_aead( } if ((error = copyin(caead->tag, (caddr_t)cse->uio.uio_iov[0].iov_base + - caead->len + caead->aadlen, cse->thash->hashsize))) + caead->len + caead->aadlen, cse->thash->hashsize))) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; + } again: /* * Let the dispatch run unlocked, then, interlock against the @@ -1003,8 +1042,10 @@ cryptodev_aead( error = msleep(crp, &cse->lock, PWAIT, "crydev", 0); mtx_unlock(&cse->lock); - if (error != 0) + if (error != 0) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; + } if (crp->crp_etype == EAGAIN) { crp->crp_etype = 0; @@ -1014,22 +1055,28 @@ cryptodev_aead( if (crp->crp_etype != 0) { error = crp->crp_etype; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } if (cse->error) { error = cse->error; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } if (caead->dst && (error = copyout( (caddr_t)cse->uio.uio_iov[0].iov_base + caead->aadlen, caead->dst, - caead->len))) + caead->len))) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; + } if ((error = copyout((caddr_t)cse->uio.uio_iov[0].iov_base + - caead->aadlen + caead->len, caead->tag, cse->thash->hashsize))) + caead->aadlen + caead->len, caead->tag, cse->thash->hashsize))) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; + } bail: crypto_freereq(crp); @@ -1068,6 +1115,7 @@ cryptodev_key(struct crypt_kop *kop) int in, out, size, i; if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EFBIG); } @@ -1077,30 +1125,38 @@ cryptodev_key(struct crypt_kop *kop) case CRK_MOD_EXP: if (in == 3 && out == 1) break; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); case CRK_MOD_EXP_CRT: if (in == 6 && out == 1) break; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); case CRK_DSA_SIGN: if (in == 5 && out == 2) break; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); case CRK_DSA_VERIFY: if (in == 7 && out == 0) break; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); case CRK_DH_COMPUTE_KEY: if (in == 3 && out == 1) break; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); default: + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (EINVAL); } krp = (struct cryptkop *)malloc(sizeof *krp, M_XDATA, M_WAITOK|M_ZERO); - if (!krp) + if (!krp) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); return (ENOMEM); + } krp->krp_op = kop->crk_op; krp->krp_status = kop->crk_status; krp->krp_iparams = kop->crk_iparams; @@ -1110,9 +1166,11 @@ cryptodev_key(struct crypt_kop *kop) krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb; for (i = 0; i < CRK_MAXPARAM; i++) { - if (kop->crk_param[i].crp_nbits > 65536) + if (kop->crk_param[i].crp_nbits > 65536) { /* Limit is the same as in OpenBSD */ + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto fail; + } krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits; } for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) { @@ -1123,22 +1181,28 @@ cryptodev_key(struct crypt_kop *kop) if (i >= krp->krp_iparams) continue; error = copyin(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p, size); - if (error) + if (error) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto fail; + } } error = crypto_kdispatch(krp); - if (error) + if (error) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto fail; + } error = tsleep(krp, PSOCK, "crydev", 0); if (error) { /* XXX can this happen? if so, how do we recover? */ + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto fail; } kop->crk_crid = krp->krp_crid; /* device that did the work */ if (krp->krp_status != 0) { error = krp->krp_status; + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto fail; } @@ -1147,8 +1211,10 @@ cryptodev_key(struct crypt_kop *kop) if (size == 0) continue; error = copyout(krp->krp_param[i].crp_p, kop->crk_param[i].crp_p, size); - if (error) + if (error) { + SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto fail; + } } fail: From 045f8bc8e4b096d8828d120d4e4a8f3bd39b9b73 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 11 Jan 2018 03:11:41 +0000 Subject: [PATCH 103/158] When we crash, we'll stop the scheduler before we call the shutdown_post_sync event. For adashutdown, this causes problems because we need to poll for completion of the commands, but we're not yet officially dumping yet, so the code from r326964 assumed we could use the interrupt-driven commands rather than the polled ones. This lead to a hang. Prevent this by also checking to see if the scheduler is stopped to do the polling. Reported by: markj@ Sponsored by: Netflix Differential Review: https://reviews.freebsd.org/D13845 --- sys/cam/cam_periph.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c index b9c3dcf76eea..6cb4583e92d8 100644 --- a/sys/cam/cam_periph.c +++ b/sys/cam/cam_periph.c @@ -1187,10 +1187,16 @@ cam_periph_runccb(union ccb *ccb, * scheduler is running in this case, we still need to poll the I/O to * avoid sleeping waiting for the ccb to complete. * - * XXX To avoid locking problems, dumping/polling callers must call + * A panic triggered dump stops the scheduler, any callback from the + * shutdown_post_sync event will run with the scheduler stopped, but + * before we're officially dumping. To avoid hanging in adashutdown + * initiated commands (or other similar situations), we have to test for + * either SCHEDULER_STOPPED() here as well. + * + * To avoid locking problems, dumping/polling callers must call * without a periph lock held. */ - must_poll = dumping; + must_poll = dumping || SCHEDULER_STOPPED(); ccb->ccb_h.cbfcnp = cam_periph_done; /* From de45c289b95bfb480e07cd1be6bd599fefb58a56 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Thu, 11 Jan 2018 05:36:13 +0000 Subject: [PATCH 104/158] awk(1): Add necessary bits for connecting tests, but leave disconnected The NetBSD test suite has 24 tests for awk, and we pass exactly 4 of them. Add the necessary pieces for interested parties to easily connect the tests and run them, but leave them disconnected for the time being. Some of these tests outright segfault in our awk, others just exhibit the wrong behavior. --- etc/mtree/BSD.tests.dist | 2 ++ usr.bin/awk/Makefile | 6 ++++++ usr.bin/awk/tests/Makefile | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 usr.bin/awk/tests/Makefile diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 944f080f232f..342455a51768 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -536,6 +536,8 @@ usr.bin apply .. + awk + .. basename .. bmake diff --git a/usr.bin/awk/Makefile b/usr.bin/awk/Makefile index b246713645d7..02202fb4fd47 100644 --- a/usr.bin/awk/Makefile +++ b/usr.bin/awk/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + AWKSRC= ${SRCTOP}/contrib/one-true-awk .PATH: ${AWKSRC} @@ -28,4 +30,8 @@ proctab.c: maketab build-tools: maketab maketab: ytab.h maketab.c ${BUILD_TOOLS_META} +# awk needs some work before we can connect these tests to the build +#HAS_TESTS= +SUBDIR.${MK_TESTS}+= tests + .include diff --git a/usr.bin/awk/tests/Makefile b/usr.bin/awk/tests/Makefile new file mode 100644 index 000000000000..79a0bc14de80 --- /dev/null +++ b/usr.bin/awk/tests/Makefile @@ -0,0 +1,33 @@ +# $FreeBSD$ + +PACKAGE= tests + +NETBSD_ATF_TESTS_SH= awk_test + +${PACKAGE}FILES+= d_assign_NF.awk +${PACKAGE}FILES+= d_assign_NF.in +${PACKAGE}FILES+= d_assign_NF.out +${PACKAGE}FILES+= d_big_regexp.awk +${PACKAGE}FILES+= d_big_regexp.in +${PACKAGE}FILES+= d_big_regexp.out +${PACKAGE}FILES+= d_end1.awk +${PACKAGE}FILES+= d_end1.in +${PACKAGE}FILES+= d_end1.out +${PACKAGE}FILES+= d_end2.awk +${PACKAGE}FILES+= d_end2.in +${PACKAGE}FILES+= d_end2.out +${PACKAGE}FILES+= d_period.awk +${PACKAGE}FILES+= d_period.in +${PACKAGE}FILES+= d_period.out +${PACKAGE}FILES+= d_string1.awk +${PACKAGE}FILES+= d_string1.out +${PACKAGE}FILES+= d_tolower.awk +${PACKAGE}FILES+= d_tolower.in +${PACKAGE}FILES+= d_tolower.out +${PACKAGE}FILES+= d_toupper.awk +${PACKAGE}FILES+= d_toupper.in +${PACKAGE}FILES+= d_toupper.out + +.include + +.include From 8fb95dc2651481c24ea8097204b94bce94ac44f5 Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Thu, 11 Jan 2018 06:30:50 +0000 Subject: [PATCH 105/158] Zstd: Add bswap intrinsics for small MIPS systems (e.g., Onion Omega) Reported by: mizhka Sponsored by: Dell EMC Isilon --- sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.c b/sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.c index c41d582c2c31..61c2fcbe4174 100644 --- a/sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.c +++ b/sys/contrib/zstd/lib/freebsd/zstd_kfreebsd.c @@ -27,6 +27,7 @@ */ #include "zstd_kfreebsd.h" +#include /* * The kernel as a standalone target does not link against libgcc or @@ -44,6 +45,19 @@ * use and move these over there instead. */ +/* Swap endianness */ +int +__bswapsi2(int x) +{ + return (bswap32(x)); +} + +long long +__bswapdi2(long long x) +{ + return (bswap64(x)); +} + /* Count trailing zeros */ int __ctzsi2(int x) From fb3855e0e7a8ba507ab4fbd57b42edff983f806f Mon Sep 17 00:00:00 2001 From: Wojciech Macek Date: Thu, 11 Jan 2018 07:40:06 +0000 Subject: [PATCH 106/158] PowerNV: initial support for OPAL OPAL is a dedicated firmware acting as a hypervisor. Add generic functions to provide all access. Created by: Nathan Whitehorn Submitted by: Wojciech Macek --- sys/conf/files.powerpc | 4 + sys/conf/options.powerpc | 1 + sys/powerpc/conf/GENERIC64 | 1 + sys/powerpc/powernv/opal.c | 66 ++++ sys/powerpc/powernv/opal.h | 48 +++ sys/powerpc/powernv/opal_console.c | 441 +++++++++++++++++++++++++ sys/powerpc/powernv/opalcall.S | 99 ++++++ sys/powerpc/powernv/platform_powernv.c | 333 +++++++++++++++++++ 8 files changed, 993 insertions(+) create mode 100644 sys/powerpc/powernv/opal.c create mode 100644 sys/powerpc/powernv/opal.h create mode 100644 sys/powerpc/powernv/opal_console.c create mode 100644 sys/powerpc/powernv/opalcall.S create mode 100644 sys/powerpc/powernv/platform_powernv.c diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index 941c1f31e112..9e2808c45b82 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -183,6 +183,10 @@ powerpc/powermac/smusat.c optional powermac smu powerpc/powermac/uninorth.c optional powermac powerpc/powermac/uninorthpci.c optional powermac pci powerpc/powermac/vcoregpio.c optional powermac +powerpc/powernv/opal.c optional powernv +powerpc/powernv/opal_console.c optional powernv +powerpc/powernv/opalcall.S optional powernv +powerpc/powernv/platform_powernv.c optional powernv powerpc/powerpc/altivec.c optional powerpc | powerpc64 powerpc/powerpc/autoconf.c standard powerpc/powerpc/bcopy.c standard diff --git a/sys/conf/options.powerpc b/sys/conf/options.powerpc index 3e82696983dd..873ceb690d0b 100644 --- a/sys/conf/options.powerpc +++ b/sys/conf/options.powerpc @@ -23,6 +23,7 @@ MPC85XX opt_platform.h POWERMAC opt_platform.h PS3 opt_platform.h MAMBO +POWERNV PSERIES PSIM diff --git a/sys/powerpc/conf/GENERIC64 b/sys/powerpc/conf/GENERIC64 index 1fc1a1d36530..c1b6983598d2 100644 --- a/sys/powerpc/conf/GENERIC64 +++ b/sys/powerpc/conf/GENERIC64 @@ -31,6 +31,7 @@ options POWERMAC #NewWorld Apple PowerMacs options PS3 #Sony Playstation 3 options MAMBO #IBM Mambo Full System Simulator options PSERIES #PAPR-compliant systems (e.g. IBM p) +options POWERNV #Non-virtualized OpenPOWER systems options FDT #Flattened Device Tree options SCHED_ULE #ULE scheduler diff --git a/sys/powerpc/powernv/opal.c b/sys/powerpc/powernv/opal.c new file mode 100644 index 000000000000..4331d0c56a37 --- /dev/null +++ b/sys/powerpc/powernv/opal.c @@ -0,0 +1,66 @@ +/*- + * Copyright (C) 2015 Nathan Whitehorn + * 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 TOOLS GMBH 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 "opal.h" + +extern uint64_t opal_entrypoint; +extern uint64_t opal_data; +extern uint64_t opal_msr; + +static int opal_initialized = 0; + +int +opal_check(void) +{ + phandle_t opal; + cell_t val[2]; + + if (opal_initialized) + return (0); + + opal = OF_finddevice("/ibm,opal"); + if (opal == -1) + return (ENOENT); + + if (!OF_hasprop(opal, "opal-base-address") || + !OF_hasprop(opal, "opal-entry-address")) + return (ENOENT); + + OF_getencprop(opal, "opal-base-address", val, sizeof(val)); + opal_data = ((uint64_t)val[0] << 32) | val[1]; + OF_getencprop(opal, "opal-entry-address", val, sizeof(val)); + opal_entrypoint = ((uint64_t)val[0] << 32) | val[1]; + + opal_msr = mfmsr() & ~(PSL_EE | PSL_IR | PSL_DR | PSL_SE); + + opal_initialized = 1; + + return (0); +} + diff --git a/sys/powerpc/powernv/opal.h b/sys/powerpc/powernv/opal.h new file mode 100644 index 000000000000..689352170b87 --- /dev/null +++ b/sys/powerpc/powernv/opal.h @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2015 Nathan Whitehorn + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _POWERNV_OPAL_H +#define _POWERNV_OPAL_H + +#include +#include + +/* Check if OPAL is correctly instantiated. Will try to instantiate it. */ +int opal_check(void); + +/* Call an OPAL method. Any pointers passed must be real-mode accessible! */ +int opal_call(uint64_t token, ...); + +#define OPAL_CONSOLE_WRITE 1 +#define OPAL_CONSOLE_READ 2 +#define OPAL_START_CPU 41 + +#define OPAL_SUCCESS 0 +#define OPAL_BUSY_EVENT -12 + +#endif diff --git a/sys/powerpc/powernv/opal_console.c b/sys/powerpc/powernv/opal_console.c new file mode 100644 index 000000000000..c93259e3184d --- /dev/null +++ b/sys/powerpc/powernv/opal_console.c @@ -0,0 +1,441 @@ +/*- + * Copyright (C) 2011,2015 by Nathan Whitehorn. 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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "opal.h" +#include "uart_if.h" + +struct uart_opal_softc { + device_t dev; + phandle_t node; + int vtermid; + + struct tty *tp; + struct resource *irqres; + int irqrid; + struct callout callout; + void *sc_icookie; + int polltime; + + struct mtx sc_mtx; + int protocol; + + char opal_inbuf[16]; + uint64_t inbuflen; + uint8_t outseqno; +}; + +static struct uart_opal_softc *console_sc = NULL; +#if defined(KDB) +static int alt_break_state; +#endif + +enum { + OPAL_RAW, OPAL_HVSI +}; + +#define VS_DATA_PACKET_HEADER 0xff +#define VS_CONTROL_PACKET_HEADER 0xfe +#define VSV_SET_MODEM_CTL 0x01 +#define VSV_MODEM_CTL_UPDATE 0x02 +#define VSV_RENEGOTIATE_CONNECTION 0x03 +#define VS_QUERY_PACKET_HEADER 0xfd +#define VSV_SEND_VERSION_NUMBER 0x01 +#define VSV_SEND_MODEM_CTL_STATUS 0x02 +#define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc + +static int uart_opal_probe(device_t dev); +static int uart_opal_attach(device_t dev); +static void uart_opal_intr(void *v); + +static device_method_t uart_opal_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, uart_opal_probe), + DEVMETHOD(device_attach, uart_opal_attach), + + DEVMETHOD_END +}; + +static driver_t uart_opal_driver = { + "uart", + uart_opal_methods, + sizeof(struct uart_opal_softc), +}; + +DRIVER_MODULE(uart_opal, opalcons, uart_opal_driver, uart_devclass, 0, 0); + +static cn_probe_t uart_opal_cnprobe; +static cn_init_t uart_opal_cninit; +static cn_term_t uart_opal_cnterm; +static cn_getc_t uart_opal_cngetc; +static cn_putc_t uart_opal_cnputc; +static cn_grab_t uart_opal_cngrab; +static cn_ungrab_t uart_opal_cnungrab; + +CONSOLE_DRIVER(uart_opal); + +static void uart_opal_ttyoutwakeup(struct tty *tp); + +static struct ttydevsw uart_opal_tty_class = { + .tsw_flags = TF_INITLOCK|TF_CALLOUT, + .tsw_outwakeup = uart_opal_ttyoutwakeup, +}; + +static int +uart_opal_probe_node(struct uart_opal_softc *sc) +{ + phandle_t node = sc->node; + uint32_t reg; + char buf[64]; + + sc->inbuflen = 0; + sc->outseqno = 0; + + if (OF_getprop(node, "device_type", buf, sizeof(buf)) <= 0) + return (ENXIO); + if (strcmp(buf, "serial") != 0) + return (ENXIO); + + reg = -1; + OF_getprop(node, "reg", ®, sizeof(reg)); + if (reg == -1) + return (ENXIO); + sc->vtermid = reg; + sc->node = node; + + if (OF_getprop(node, "compatible", buf, sizeof(buf)) <= 0) + return (ENXIO); + if (strcmp(buf, "ibm,opal-console-raw") == 0) { + sc->protocol = OPAL_RAW; + return (0); + } else if (strcmp(buf, "ibm,opal-console-hvsi") == 0) { + sc->protocol = OPAL_HVSI; + return (0); + } + + return (ENXIO); +} + +static int +uart_opal_probe(device_t dev) +{ + struct uart_opal_softc sc; + int err; + + sc.node = ofw_bus_get_node(dev); + err = uart_opal_probe_node(&sc); + if (err != 0) + return (err); + + device_set_desc(dev, "OPAL Serial Port"); + + return (err); +} + +static void +uart_opal_cnprobe(struct consdev *cp) +{ + char buf[64]; + phandle_t input, chosen; + static struct uart_opal_softc sc; + + if (opal_check() != 0) + goto fail; + + if ((chosen = OF_finddevice("/chosen")) == -1) + goto fail; + + /* Check if OF has an active stdin/stdout */ + if (OF_getprop(chosen, "linux,stdout-path", buf, sizeof(buf)) <= 0) + goto fail; + + input = OF_finddevice(buf); + if (input == -1) + goto fail; + + sc.node = input; + if (uart_opal_probe_node(&sc) != 0) + goto fail; + mtx_init(&sc.sc_mtx, "uart_opal", NULL, MTX_SPIN | MTX_QUIET | + MTX_NOWITNESS); + + cp->cn_pri = CN_NORMAL; + console_sc = ≻ + return; + +fail: + cp->cn_pri = CN_DEAD; + return; +} + +static int +uart_opal_attach(device_t dev) +{ + struct uart_opal_softc *sc; + int unit; + + sc = device_get_softc(dev); + sc->dev = dev; + sc->node = ofw_bus_get_node(dev); + uart_opal_probe_node(sc); + + unit = device_get_unit(dev); + sc->tp = tty_alloc(&uart_opal_tty_class, sc); + mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, + MTX_SPIN | MTX_QUIET | MTX_NOWITNESS); + + if (console_sc != NULL && console_sc->vtermid == sc->vtermid) { + sc->outseqno = console_sc->outseqno; + console_sc = sc; + sprintf(uart_opal_consdev.cn_name, "ttyu%r", unit); + tty_init_console(sc->tp, 0); + } + + sc->irqrid = 0; + sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqrid, + RF_ACTIVE | RF_SHAREABLE); + if (sc->irqres != NULL) { + bus_setup_intr(dev, sc->irqres, INTR_TYPE_TTY | INTR_MPSAFE, + NULL, uart_opal_intr, sc, &sc->sc_icookie); + } else { + callout_init(&sc->callout, CALLOUT_MPSAFE); + sc->polltime = hz / 20; + if (sc->polltime < 1) + sc->polltime = 1; + callout_reset(&sc->callout, sc->polltime, uart_opal_intr, sc); + } + + tty_makedev(sc->tp, NULL, "u%r", unit); + + return (0); +} + +static void +uart_opal_cninit(struct consdev *cp) +{ + + strcpy(cp->cn_name, "opalcons"); +} + +static void +uart_opal_cnterm(struct consdev *cp) +{ +} + +static int +uart_opal_get(struct uart_opal_softc *sc, void *buffer, size_t bufsize) +{ + int err; + int hdr = 0; + + if (sc->protocol == OPAL_RAW) { + uint64_t len = bufsize; + uint64_t olen = (uint64_t)&len; + uint64_t obuf = (uint64_t)buffer; + + if (pmap_bootstrapped) { + olen = vtophys(&len); + obuf = vtophys(buffer); + } + + err = opal_call(OPAL_CONSOLE_READ, sc->vtermid, olen, obuf); + if (err != OPAL_SUCCESS) + return (-1); + + bufsize = len; + } else { + uart_lock(&sc->sc_mtx); + if (sc->inbuflen == 0) { + err = opal_call(OPAL_CONSOLE_READ, sc->vtermid, + &sc->inbuflen, sc->opal_inbuf); + if (err != OPAL_SUCCESS) { + uart_unlock(&sc->sc_mtx); + return (-1); + } + hdr = 1; + } + + if (sc->inbuflen == 0) { + uart_unlock(&sc->sc_mtx); + return (0); + } + + if (bufsize > sc->inbuflen) + bufsize = sc->inbuflen; + + if (hdr == 1) { + sc->inbuflen = sc->inbuflen - 4; + /* The HVSI protocol has a 4 byte header, skip it */ + memmove(&sc->opal_inbuf[0], &sc->opal_inbuf[4], + sc->inbuflen); + } + + memcpy(buffer, sc->opal_inbuf, bufsize); + sc->inbuflen -= bufsize; + if (sc->inbuflen > 0) + memmove(&sc->opal_inbuf[0], &sc->opal_inbuf[bufsize], + sc->inbuflen); + + uart_unlock(&sc->sc_mtx); + } + + return (bufsize); +} + +static int +uart_opal_put(struct uart_opal_softc *sc, void *buffer, size_t bufsize) +{ + uint16_t seqno; + uint64_t len = bufsize; + char cbuf[16]; + int err; + uint64_t olen = (uint64_t)&len; + uint64_t obuf = (uint64_t)cbuf; + + if (pmap_bootstrapped) + olen = vtophys(&len); + + if (sc->protocol == OPAL_RAW) { + if (pmap_bootstrapped) + obuf = vtophys(buffer); + else + obuf = (uint64_t)(buffer); + + err = opal_call(OPAL_CONSOLE_WRITE, sc->vtermid, olen, obuf); + } else { + if (pmap_bootstrapped) + obuf = vtophys(cbuf); + uart_lock(&sc->sc_mtx); + if (bufsize > 12) + bufsize = 12; + seqno = sc->outseqno++; + cbuf[0] = VS_DATA_PACKET_HEADER; + cbuf[1] = 4 + bufsize; /* total length */ + cbuf[2] = (seqno >> 8) & 0xff; + cbuf[3] = seqno & 0xff; + memcpy(&cbuf[4], buffer, bufsize); + len = 4 + bufsize; + err = opal_call(OPAL_CONSOLE_WRITE, sc->vtermid, olen, obuf); + uart_unlock(&sc->sc_mtx); + + len -= 4; + } + +#if 0 + if (err != OPAL_SUCCESS) + len = 0; +#endif + + return (len); +} + +static int +uart_opal_cngetc(struct consdev *cp) +{ + unsigned char c; + int retval; + + retval = uart_opal_get(console_sc, &c, 1); + if (retval != 1) + return (-1); +#if defined(KDB) + kdb_alt_break(c, &alt_break_state); +#endif + + return (c); +} + +static void +uart_opal_cnputc(struct consdev *cp, int c) +{ + unsigned char ch = c; + uart_opal_put(console_sc, &ch, 1); +} + +static void +uart_opal_cngrab(struct consdev *cp) +{ +} + +static void +uart_opal_cnungrab(struct consdev *cp) +{ +} + +static void +uart_opal_ttyoutwakeup(struct tty *tp) +{ + struct uart_opal_softc *sc; + char buffer[8]; + int len; + + sc = tty_softc(tp); + + while ((len = ttydisc_getc(tp, buffer, sizeof(buffer))) != 0) + uart_opal_put(sc, buffer, len); +} + +static void +uart_opal_intr(void *v) +{ + struct uart_opal_softc *sc = v; + struct tty *tp = sc->tp; + unsigned char c; + int len; + + tty_lock(tp); + while ((len = uart_opal_get(sc, &c, 1)) > 0) + ttydisc_rint(tp, c, 0); + ttydisc_rint_done(tp); + tty_unlock(tp); + + if (sc->irqres == NULL) + callout_reset(&sc->callout, sc->polltime, uart_opal_intr, sc); +} + diff --git a/sys/powerpc/powernv/opalcall.S b/sys/powerpc/powernv/opalcall.S new file mode 100644 index 000000000000..6386c1140946 --- /dev/null +++ b/sys/powerpc/powernv/opalcall.S @@ -0,0 +1,99 @@ +/*- + * Copyright (C) 2015 Nathan Whitehorn + * 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 TOOLS GMBH 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 + +GLOBAL(opal_entrypoint) + .llong 0 +GLOBAL(opal_data) + .llong 0 +GLOBAL(opal_msr) + .llong 0 + +TOC_ENTRY(opal_entrypoint) +TOC_ENTRY(opal_data) +TOC_ENTRY(opal_msr) + +ASENTRY(opal_call) + /* Args: + * r3: opal token + * r4-r10 opal arguments + */ + + /* Save call stuff on stack */ + mflr %r0 + std %r0,16(%r1) + std %r2,-16(%r1) + mfcr %r0 + std %r0,8(%r1) + + /* Load OPAL entry information */ + mr %r0,%r3 + ld %r3,TOC_REF(opal_entrypoint)(%r2) + ld %r3,0(%r3) + mtctr %r3 + + /* Save MSR in non-volatile scratch register and turn off translation */ + std %r31,-8(%r1) + mfmsr %r31 + + /* Load last bits from the TOC */ + ld %r3,TOC_REF(opal_msr)(%r2) + ld %r3,0(%r3) + ld %r2,TOC_REF(opal_data)(%r2) + ld %r2,0(%r2) + + mtmsrd %r3 + isync + + /* Shift registers over */ + mr %r3,%r4 + mr %r4,%r5 + mr %r5,%r6 + mr %r6,%r7 + mr %r7,%r8 + mr %r8,%r9 + mr %r9,%r10 + + /* Call OPAL */ + bctrl + + /* Restore MSR */ + mtmsrd %r31 + isync + ld %r31,-8(%r1) + + /* Restore call stuff from stack */ + ld %r0,16(%r1) + mtlr %r0 + ld %r2,-16(%r1) + ld %r0,8(%r1) + mtcr %r0 + + /* And return */ + blr + diff --git a/sys/powerpc/powernv/platform_powernv.c b/sys/powerpc/powernv/platform_powernv.c new file mode 100644 index 000000000000..dfa453d12929 --- /dev/null +++ b/sys/powerpc/powernv/platform_powernv.c @@ -0,0 +1,333 @@ +/*- + * Copyright (c) 2015 Nathan Whitehorn + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "platform_if.h" +#include "opal.h" + +#ifdef SMP +extern void *ap_pcpu; +#endif + +static int powernv_probe(platform_t); +static int powernv_attach(platform_t); +void powernv_mem_regions(platform_t, struct mem_region *phys, int *physsz, + struct mem_region *avail, int *availsz); +static u_long powernv_timebase_freq(platform_t, struct cpuref *cpuref); +static int powernv_smp_first_cpu(platform_t, struct cpuref *cpuref); +static int powernv_smp_next_cpu(platform_t, struct cpuref *cpuref); +static int powernv_smp_get_bsp(platform_t, struct cpuref *cpuref); +static void powernv_smp_ap_init(platform_t); +#ifdef SMP +static int powernv_smp_start_cpu(platform_t, struct pcpu *cpu); +static struct cpu_group *powernv_smp_topo(platform_t plat); +#endif +static void powernv_reset(platform_t); + +static platform_method_t powernv_methods[] = { + PLATFORMMETHOD(platform_probe, powernv_probe), + PLATFORMMETHOD(platform_attach, powernv_attach), + PLATFORMMETHOD(platform_mem_regions, powernv_mem_regions), + PLATFORMMETHOD(platform_timebase_freq, powernv_timebase_freq), + + PLATFORMMETHOD(platform_smp_ap_init, powernv_smp_ap_init), + PLATFORMMETHOD(platform_smp_first_cpu, powernv_smp_first_cpu), + PLATFORMMETHOD(platform_smp_next_cpu, powernv_smp_next_cpu), + PLATFORMMETHOD(platform_smp_get_bsp, powernv_smp_get_bsp), +#ifdef SMP + PLATFORMMETHOD(platform_smp_start_cpu, powernv_smp_start_cpu), + PLATFORMMETHOD(platform_smp_topo, powernv_smp_topo), +#endif + + PLATFORMMETHOD(platform_reset, powernv_reset), + + { 0, 0 } +}; + +static platform_def_t powernv_platform = { + "powernv", + powernv_methods, + 0 +}; + +PLATFORM_DEF(powernv_platform); + +static int +powernv_probe(platform_t plat) +{ + if (opal_check() == 0) + return (BUS_PROBE_SPECIFIC); + + return (ENXIO); +} + +static int +powernv_attach(platform_t plat) +{ + /* Ping OPAL again just to make sure */ + opal_check(); + + return (0); +} + +void +powernv_mem_regions(platform_t plat, struct mem_region *phys, int *physsz, + struct mem_region *avail, int *availsz) +{ + + ofw_mem_regions(phys, physsz, avail, availsz); +} + +static u_long +powernv_timebase_freq(platform_t plat, struct cpuref *cpuref) +{ + phandle_t phandle; + int32_t ticks = -1; + + phandle = cpuref->cr_hwref; + + OF_getprop(phandle, "timebase-frequency", &ticks, sizeof(ticks)); + + if (ticks <= 0) + panic("Unable to determine timebase frequency!"); + + return (ticks); +} + +static int +powernv_smp_first_cpu(platform_t plat, struct cpuref *cpuref) +{ + char buf[8]; + phandle_t cpu, dev, root; + int res, cpuid; + + root = OF_peer(0); + + dev = OF_child(root); + while (dev != 0) { + res = OF_getprop(dev, "name", buf, sizeof(buf)); + if (res > 0 && strcmp(buf, "cpus") == 0) + break; + dev = OF_peer(dev); + } + if (dev == 0) { + /* + * psim doesn't have a name property on the /cpus node, + * but it can be found directly + */ + dev = OF_finddevice("/cpus"); + if (dev == 0) + return (ENOENT); + } + + cpu = OF_child(dev); + + while (cpu != 0) { + res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); + if (res > 0 && strcmp(buf, "cpu") == 0) + break; + cpu = OF_peer(cpu); + } + if (cpu == 0) + return (ENOENT); + + cpuref->cr_hwref = cpu; + res = OF_getprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid, + sizeof(cpuid)); + if (res <= 0) + res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); + if (res <= 0) + cpuid = 0; + cpuref->cr_cpuid = cpuid; + + return (0); +} + +static int +powernv_smp_next_cpu(platform_t plat, struct cpuref *cpuref) +{ + char buf[8]; + phandle_t cpu; + int i, res, cpuid; + + /* Check for whether it should be the next thread */ + res = OF_getproplen(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s"); + if (res > 0) { + cell_t interrupt_servers[res/sizeof(cell_t)]; + OF_getprop(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s", + interrupt_servers, res); + for (i = 0; i < res/sizeof(cell_t) - 1; i++) { + if (interrupt_servers[i] == cpuref->cr_cpuid) { + cpuref->cr_cpuid = interrupt_servers[i+1]; + return (0); + } + } + } + + /* Next CPU core/package */ + cpu = OF_peer(cpuref->cr_hwref); + while (cpu != 0) { + res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); + if (res > 0 && strcmp(buf, "cpu") == 0) + break; + cpu = OF_peer(cpu); + } + if (cpu == 0) + return (ENOENT); + + cpuref->cr_hwref = cpu; + res = OF_getprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid, + sizeof(cpuid)); + if (res <= 0) + res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); + if (res <= 0) + cpuid = 0; + cpuref->cr_cpuid = cpuid; + + return (0); +} + +static int +powernv_smp_get_bsp(platform_t plat, struct cpuref *cpuref) +{ + phandle_t chosen; + int cpuid, res; + struct cpuref i; + + chosen = OF_finddevice("/chosen"); + if (chosen == 0) + return (ENOENT); + + res = OF_getencprop(chosen, "fdtbootcpu", &cpuid, sizeof(cpuid)); + if (res < 0) + return (ENOENT); + + cpuref->cr_cpuid = cpuid; + + if (powernv_smp_first_cpu(plat, &i) != 0) + return (ENOENT); + cpuref->cr_hwref = i.cr_hwref; + + do { + if (i.cr_cpuid == cpuid) { + cpuref->cr_hwref = i.cr_hwref; + break; + } + } while (powernv_smp_next_cpu(plat, &i) == 0); + + return (0); +} + +#ifdef SMP +static int +powernv_smp_start_cpu(platform_t plat, struct pcpu *pc) +{ + int result, err, timeout; + + ap_pcpu = pc; + powerpc_sync(); + + result = opal_call(OPAL_START_CPU, pc->pc_cpuid, EXC_RST); + if (result < 0 || err != 0) { + printf("OPAL error (%d/%d): unable to start AP %d\n", + result, err, pc->pc_cpuid); + return (ENXIO); + } + + timeout = 10000; + while (!pc->pc_awake && timeout--) + DELAY(100); + + return ((pc->pc_awake) ? 0 : EBUSY); +} + +static struct cpu_group * +powernv_smp_topo(platform_t plat) +{ + struct pcpu *pc, *last_pc; + int i, ncores, ncpus; + + ncores = ncpus = 0; + last_pc = NULL; + for (i = 0; i <= mp_maxid; i++) { + pc = pcpu_find(i); + if (pc == NULL) + continue; + if (last_pc == NULL || pc->pc_hwref != last_pc->pc_hwref) + ncores++; + last_pc = pc; + ncpus++; + } + + if (ncpus % ncores != 0) { + printf("WARNING: Irregular SMP topology. Performance may be " + "suboptimal (%d CPUS, %d cores)\n", ncpus, ncores); + return (smp_topo_none()); + } + + /* Don't do anything fancier for non-threaded SMP */ + if (ncpus == ncores) + return (smp_topo_none()); + + return (smp_topo_1level(CG_SHARE_L1, ncpus / ncores, CG_FLAG_SMT)); +} +#endif + +static void +powernv_reset(platform_t platform) +{ +} + +static void +powernv_smp_ap_init(platform_t platform) +{ +} + From f078ecf642b663eaf28dcab5516173e592284f33 Mon Sep 17 00:00:00 2001 From: Wojciech Macek Date: Thu, 11 Jan 2018 09:17:02 +0000 Subject: [PATCH 107/158] CXGBE: fix get_filt to be endianness-aware Unconditional 32-bit shift is not endianness-safe. Modify the logic to work both on LE and BE. Submitted by: Wojciech Macek Reviewed by: np Obtained from: Semihalf Sponsored by: IBM, QCM Technologies Differential revision: https://reviews.freebsd.org/D13102 --- sys/dev/cxgbe/t4_sge.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c index f8a9f8bc6901..7edd17f6df69 100644 --- a/sys/dev/cxgbe/t4_sge.c +++ b/sys/dev/cxgbe/t4_sge.c @@ -4754,13 +4754,13 @@ get_flit(struct sglist_seg *segs, int nsegs, int idx) switch (idx % 3) { case 0: { - __be64 rc; + uint64_t rc; - rc = htobe32(segs[i].ss_len); + rc = (uint64_t)segs[i].ss_len << 32; if (i + 1 < nsegs) - rc |= (uint64_t)htobe32(segs[i + 1].ss_len) << 32; + rc |= (uint64_t)(segs[i + 1].ss_len); - return (rc); + return (htobe64(rc)); } case 1: return (htobe64(segs[i].ss_paddr)); From 32d1354a39d70153f6070f3b1cf94ea2ad8dd0d9 Mon Sep 17 00:00:00 2001 From: Wojciech Macek Date: Thu, 11 Jan 2018 09:26:28 +0000 Subject: [PATCH 108/158] PowerNV: add reset, poweroff, OPAL console Add basic power control (reset, power off) and bind ttyuX to opal console so that init will start login there. Created by: Nathan Whitehorn Submitted by: Wojciech Macek Sponsored by: FreeBSD Foundation --- sys/powerpc/powernv/opal.h | 2 + sys/powerpc/powernv/opal_console.c | 73 +++++++++++ sys/powerpc/powernv/opal_dev.c | 162 +++++++++++++++++++++++++ sys/powerpc/powernv/platform_powernv.c | 2 + 4 files changed, 239 insertions(+) create mode 100644 sys/powerpc/powernv/opal_dev.c diff --git a/sys/powerpc/powernv/opal.h b/sys/powerpc/powernv/opal.h index 689352170b87..782c09066180 100644 --- a/sys/powerpc/powernv/opal.h +++ b/sys/powerpc/powernv/opal.h @@ -40,6 +40,8 @@ int opal_call(uint64_t token, ...); #define OPAL_CONSOLE_WRITE 1 #define OPAL_CONSOLE_READ 2 +#define OPAL_CEC_POWER_DOWN 5 +#define OPAL_CEC_REBOOT 6 #define OPAL_START_CPU 41 #define OPAL_SUCCESS 0 diff --git a/sys/powerpc/powernv/opal_console.c b/sys/powerpc/powernv/opal_console.c index c93259e3184d..5d2046c685f2 100644 --- a/sys/powerpc/powernv/opal_console.c +++ b/sys/powerpc/powernv/opal_console.c @@ -439,3 +439,76 @@ uart_opal_intr(void *v) callout_reset(&sc->callout, sc->polltime, uart_opal_intr, sc); } +static int +opalcons_probe(device_t dev) +{ + const char *name; + + name = ofw_bus_get_name(dev); + if (name == NULL || strcmp(name, "consoles") != 0) + return (ENXIO); + + device_set_desc(dev, "OPAL Consoles"); + return (BUS_PROBE_SPECIFIC); +} + +static int +opalcons_attach(device_t dev) +{ + phandle_t child; + device_t cdev; + struct ofw_bus_devinfo *dinfo; + + for (child = OF_child(ofw_bus_get_node(dev)); child != 0; + child = OF_peer(child)) { + dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); + if (ofw_bus_gen_setup_devinfo(dinfo, child) != 0) { + free(dinfo, M_DEVBUF); + continue; + } + cdev = device_add_child(dev, NULL, -1); + if (cdev == NULL) { + device_printf(dev, "<%s>: device_add_child failed\n", + dinfo->obd_name); + ofw_bus_gen_destroy_devinfo(dinfo); + free(dinfo, M_DEVBUF); + continue; + } + device_set_ivars(cdev, dinfo); + } + + return (bus_generic_attach(dev)); +} + +static const struct ofw_bus_devinfo * +opalcons_get_devinfo(device_t dev, device_t child) +{ + return (device_get_ivars(child)); +} + +static device_method_t opalcons_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, opalcons_probe), + DEVMETHOD(device_attach, opalcons_attach), + + /* ofw_bus interface */ + DEVMETHOD(ofw_bus_get_devinfo, opalcons_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 +}; + +static driver_t opalcons_driver = { + "opalcons", + opalcons_methods, + 0 +}; + +static devclass_t opalcons_devclass; + +DRIVER_MODULE(opalcons, opal, opalcons_driver, opalcons_devclass, 0, 0); + diff --git a/sys/powerpc/powernv/opal_dev.c b/sys/powerpc/powernv/opal_dev.c new file mode 100644 index 000000000000..29995c55569e --- /dev/null +++ b/sys/powerpc/powernv/opal_dev.c @@ -0,0 +1,162 @@ +/*- + * Copyright (c) 2015 Nathan Whitehorn + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "clock_if.h" +#include "opal.h" + +static int opaldev_probe(device_t); +static int opaldev_attach(device_t); +/* clock interface */ +static int opal_gettime(device_t dev, struct timespec *ts); +static int opal_settime(device_t dev, struct timespec *ts); +/* ofw bus interface */ +static const struct ofw_bus_devinfo *opaldev_get_devinfo(device_t dev, + device_t child); + +static void opal_shutdown(void *arg, int howto); + +static device_method_t opaldev_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, opaldev_probe), + DEVMETHOD(device_attach, opaldev_attach), + + /* clock interface */ + DEVMETHOD(clock_gettime, opal_gettime), + DEVMETHOD(clock_settime, opal_settime), + + /* ofw_bus interface */ + DEVMETHOD(ofw_bus_get_devinfo, opaldev_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 +}; + +static driver_t opaldev_driver = { + "opal", + opaldev_methods, + 0 +}; + +static devclass_t opaldev_devclass; + +DRIVER_MODULE(opaldev, ofwbus, opaldev_driver, opaldev_devclass, 0, 0); + +static int +opaldev_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "ibm,opal-v3")) + return (ENXIO); + if (opal_check() != 0) + return (ENXIO); + + device_set_desc(dev, "OPAL Abstraction Firmware"); + return (BUS_PROBE_SPECIFIC); +} + +static int +opaldev_attach(device_t dev) +{ + phandle_t child; + device_t cdev; + struct ofw_bus_devinfo *dinfo; + + if (0 /* XXX NOT YET TEST FOR RTC */) + clock_register(dev, 2000); + + EVENTHANDLER_REGISTER(shutdown_final, opal_shutdown, NULL, + SHUTDOWN_PRI_LAST); + + for (child = OF_child(ofw_bus_get_node(dev)); child != 0; + child = OF_peer(child)) { + dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); + if (ofw_bus_gen_setup_devinfo(dinfo, child) != 0) { + free(dinfo, M_DEVBUF); + continue; + } + cdev = device_add_child(dev, NULL, -1); + if (cdev == NULL) { + device_printf(dev, "<%s>: device_add_child failed\n", + dinfo->obd_name); + ofw_bus_gen_destroy_devinfo(dinfo); + free(dinfo, M_DEVBUF); + continue; + } + device_set_ivars(cdev, dinfo); + } + + return (bus_generic_attach(dev)); +} + +static int +opal_gettime(device_t dev, struct timespec *ts) { + return (ENXIO); +} + +static int +opal_settime(device_t dev, struct timespec *ts) +{ + return (0); +} + +static const struct ofw_bus_devinfo * +opaldev_get_devinfo(device_t dev, device_t child) +{ + return (device_get_ivars(child)); +} + +static void +opal_shutdown(void *arg, int howto) +{ + + if (howto & RB_HALT) + opal_call(OPAL_CEC_POWER_DOWN, 0 /* Normal power off */); + else + opal_call(OPAL_CEC_REBOOT); +} + diff --git a/sys/powerpc/powernv/platform_powernv.c b/sys/powerpc/powernv/platform_powernv.c index dfa453d12929..70a0541de0ad 100644 --- a/sys/powerpc/powernv/platform_powernv.c +++ b/sys/powerpc/powernv/platform_powernv.c @@ -324,6 +324,8 @@ powernv_smp_topo(platform_t plat) static void powernv_reset(platform_t platform) { + + opal_call(OPAL_CEC_REBOOT); } static void From 01d7bda7b7fd540b73a9e7c1a3f2914649d4b518 Mon Sep 17 00:00:00 2001 From: Wojciech Macek Date: Thu, 11 Jan 2018 09:34:33 +0000 Subject: [PATCH 109/158] PowerNV: correctly start secondary CPUs Fix AP startup, which was broken. Created by: Nathan Whitehorn Submitted by: Wojciech Macek Sponsored by: FreeBSD Foundation --- sys/powerpc/powernv/platform_powernv.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/sys/powerpc/powernv/platform_powernv.c b/sys/powerpc/powernv/platform_powernv.c index 70a0541de0ad..c52a1d014bc5 100644 --- a/sys/powerpc/powernv/platform_powernv.c +++ b/sys/powerpc/powernv/platform_powernv.c @@ -71,6 +71,7 @@ static int powernv_smp_start_cpu(platform_t, struct pcpu *cpu); static struct cpu_group *powernv_smp_topo(platform_t plat); #endif static void powernv_reset(platform_t); +static void powernv_cpu_idle(sbintime_t sbt); static platform_method_t powernv_methods[] = { PLATFORMMETHOD(platform_probe, powernv_probe), @@ -115,6 +116,8 @@ powernv_attach(platform_t plat) /* Ping OPAL again just to make sure */ opal_check(); + cpu_idle_hook = powernv_cpu_idle; + return (0); } @@ -270,23 +273,19 @@ powernv_smp_get_bsp(platform_t plat, struct cpuref *cpuref) static int powernv_smp_start_cpu(platform_t plat, struct pcpu *pc) { - int result, err, timeout; + int result; ap_pcpu = pc; powerpc_sync(); result = opal_call(OPAL_START_CPU, pc->pc_cpuid, EXC_RST); - if (result < 0 || err != 0) { - printf("OPAL error (%d/%d): unable to start AP %d\n", - result, err, pc->pc_cpuid); + if (result != OPAL_SUCCESS) { + printf("OPAL error (%d): unable to start AP %d\n", + result, pc->pc_cpuid); return (ENXIO); } - timeout = 10000; - while (!pc->pc_awake && timeout--) - DELAY(100); - - return ((pc->pc_awake) ? 0 : EBUSY); + return (0); } static struct cpu_group * @@ -333,3 +332,7 @@ powernv_smp_ap_init(platform_t platform) { } +static void +powernv_cpu_idle(sbintime_t sbt) +{ +} From c0248976017f14f58a365357863592e55b558737 Mon Sep 17 00:00:00 2001 From: Wojciech Macek Date: Thu, 11 Jan 2018 09:39:38 +0000 Subject: [PATCH 110/158] PowerNV: set LPCR[LPES] correctly Make sure to set LPCR[LPES] so that external interrupts set SRR0 and SRR1 instead of HSRR0 and HSRR1. Without this, external interrupt handlers would get the wrong MSR value when executing, causing eventual madness. Created by: Nathan Whitehorn Submitted by: Wojciech Macek Sponsored by: FreeBSD Foundation --- sys/powerpc/include/spr.h | 3 +++ sys/powerpc/powernv/platform_powernv.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/sys/powerpc/include/spr.h b/sys/powerpc/include/spr.h index c500987cc112..15556e43ba10 100644 --- a/sys/powerpc/include/spr.h +++ b/sys/powerpc/include/spr.h @@ -199,6 +199,9 @@ #define FSL_E300C3 0x8085 #define FSL_E300C4 0x8086 +#define SPR_LPCR 0x13e /* Logical Partitioning Control */ +#define LPCR_LPES 0x008 /* Bit 60 */ + #define SPR_EPCR 0x133 #define EPCR_EXTGS 0x80000000 #define EPCR_DTLBGS 0x40000000 diff --git a/sys/powerpc/powernv/platform_powernv.c b/sys/powerpc/powernv/platform_powernv.c index c52a1d014bc5..3679ce5a81a1 100644 --- a/sys/powerpc/powernv/platform_powernv.c +++ b/sys/powerpc/powernv/platform_powernv.c @@ -118,6 +118,9 @@ powernv_attach(platform_t plat) cpu_idle_hook = powernv_cpu_idle; + /* Direct interrupts to SRR instead of HSRR */ + mtspr(SPR_LPCR, mfspr(SPR_LPCR) | LPCR_LPES); + return (0); } From fc1689021fa971ce54f7c3170ce998164720f88c Mon Sep 17 00:00:00 2001 From: Wojciech Macek Date: Thu, 11 Jan 2018 09:42:24 +0000 Subject: [PATCH 111/158] PowerNV: add buffer for OPAL console Avoid the lock in vtophys() by providing a static direct-mapped spinlock- protected output buffer to use when the console driver cannot acquire locks for some reason. This allows the idle thread to use printf() (e.g. the SMP startup messages) without crashing the kernel. Created by: Nathan Whitehorn Submitted by: Wojciech Macek Sponsored by: FreeBSD Foundation --- sys/powerpc/powernv/opal_console.c | 64 +++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/sys/powerpc/powernv/opal_console.c b/sys/powerpc/powernv/opal_console.c index 5d2046c685f2..ac39e71dbf2c 100644 --- a/sys/powerpc/powernv/opal_console.c +++ b/sys/powerpc/powernv/opal_console.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -72,6 +73,7 @@ struct uart_opal_softc { }; static struct uart_opal_softc *console_sc = NULL; + #if defined(KDB) static int alt_break_state; #endif @@ -127,6 +129,48 @@ static struct ttydevsw uart_opal_tty_class = { .tsw_outwakeup = uart_opal_ttyoutwakeup, }; +static struct { + char tmpbuf[16]; + uint64_t size; + struct mtx mtx; +} escapehatch; + +static void +uart_opal_real_map_outbuffer(uint64_t *bufferp, uint64_t *lenp) +{ + + if (!mtx_initialized(&escapehatch.mtx)) + mtx_init(&escapehatch.mtx, "uart_opal", NULL, MTX_SPIN | MTX_QUIET | + MTX_NOWITNESS); + + if (!pmap_bootstrapped) + return; + + if (TD_IS_IDLETHREAD(curthread)) { + escapehatch.size = *(uint64_t *)(*lenp) = + min(sizeof(escapehatch.tmpbuf), *(uint64_t *)(*lenp)); + mtx_lock_spin(&escapehatch.mtx); + memcpy(escapehatch.tmpbuf, (void *)(*bufferp), *(uint64_t *)(*lenp)); + *bufferp = (uint64_t)escapehatch.tmpbuf; + *lenp = (uint64_t)&escapehatch.size; + } + + *bufferp = vtophys(*bufferp); + *lenp = vtophys(*lenp); +} + +static void +uart_opal_real_unmap_outbuffer(uint64_t lenp, uint64_t *origlen) +{ + + if (!pmap_bootstrapped || !TD_IS_IDLETHREAD(curthread)) + return; + + mtx_assert(&escapehatch.mtx, MA_OWNED); + *origlen = escapehatch.size; + mtx_unlock_spin(&escapehatch.mtx); +} + static int uart_opal_probe_node(struct uart_opal_softc *sc) { @@ -231,6 +275,7 @@ uart_opal_attach(device_t dev) MTX_SPIN | MTX_QUIET | MTX_NOWITNESS); if (console_sc != NULL && console_sc->vtermid == sc->vtermid) { + device_printf(dev, "console\n"); sc->outseqno = console_sc->outseqno; console_sc = sc; sprintf(uart_opal_consdev.cn_name, "ttyu%r", unit); @@ -332,25 +377,20 @@ static int uart_opal_put(struct uart_opal_softc *sc, void *buffer, size_t bufsize) { uint16_t seqno; - uint64_t len = bufsize; + uint64_t len; char cbuf[16]; int err; uint64_t olen = (uint64_t)&len; uint64_t obuf = (uint64_t)cbuf; - if (pmap_bootstrapped) - olen = vtophys(&len); - if (sc->protocol == OPAL_RAW) { - if (pmap_bootstrapped) - obuf = vtophys(buffer); - else - obuf = (uint64_t)(buffer); + obuf = (uint64_t)buffer; + len = bufsize; + uart_opal_real_map_outbuffer(&obuf, &olen); err = opal_call(OPAL_CONSOLE_WRITE, sc->vtermid, olen, obuf); + uart_opal_real_unmap_outbuffer(olen, &len); } else { - if (pmap_bootstrapped) - obuf = vtophys(cbuf); uart_lock(&sc->sc_mtx); if (bufsize > 12) bufsize = 12; @@ -361,7 +401,11 @@ uart_opal_put(struct uart_opal_softc *sc, void *buffer, size_t bufsize) cbuf[3] = seqno & 0xff; memcpy(&cbuf[4], buffer, bufsize); len = 4 + bufsize; + + uart_opal_real_map_outbuffer(&obuf, &olen); err = opal_call(OPAL_CONSOLE_WRITE, sc->vtermid, olen, obuf); + uart_opal_real_unmap_outbuffer(olen, &len); + uart_unlock(&sc->sc_mtx); len -= 4; From 3ee6e658755bcdc7277df553845c8361a0bf1c10 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 11 Jan 2018 12:07:24 +0000 Subject: [PATCH 112/158] Update comment explaining the check, to reality. Discussed with: jhb Sponsored by: The FreeBSD Foundation MFC after: 3 days --- sys/amd64/amd64/support.S | 8 +++----- sys/i386/i386/support.s | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/sys/amd64/amd64/support.S b/sys/amd64/amd64/support.S index 5a69ffd2ca51..042ec5fc3bd4 100644 --- a/sys/amd64/amd64/support.S +++ b/sys/amd64/amd64/support.S @@ -249,12 +249,10 @@ ENTRY(copyout) jz done_copyout /* - * Check explicitly for non-user addresses. If 486 write protection - * is being used, this check is essential because we are in kernel - * mode so the h/w does not provide any protection against writing - * kernel addresses. + * Check explicitly for non-user addresses. This check is essential + * because it prevents usermode from writing into kernel. We do not + * verify that user did not specified a rogue address anywhere else. */ - /* * First, prevent address wrapping. */ diff --git a/sys/i386/i386/support.s b/sys/i386/i386/support.s index 2fe4de7bc7f2..afbad837f91e 100644 --- a/sys/i386/i386/support.s +++ b/sys/i386/i386/support.s @@ -291,12 +291,10 @@ ENTRY(copyout) jz done_copyout /* - * Check explicitly for non-user addresses. If 486 write protection - * is being used, this check is essential because we are in kernel - * mode so the h/w does not provide any protection against writing - * kernel addresses. + * Check explicitly for non-user addresses. This check is essential + * because it prevents usermode from writing into kernel. We do not + * verify that user did not specified a rogue address anywhere else. */ - /* * First, prevent address wrapping. */ From 4275e16fa9af06181aa63c91da2078da37f288ec Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 11 Jan 2018 12:28:08 +0000 Subject: [PATCH 113/158] Rename COMMON_TSS_RSP0 to TSS_RSP0. The symbol is just an offset in the hardware TSS structure, it is not limited to the common_tss instance. Sponsored by: The FreeBSD Foundation MFC after: 3 days --- sys/amd64/amd64/cpu_switch.S | 2 +- sys/amd64/amd64/genassym.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S index b010e3513c77..e993df23c13a 100644 --- a/sys/amd64/amd64/cpu_switch.S +++ b/sys/amd64/amd64/cpu_switch.S @@ -215,7 +215,7 @@ done_tss: movq %r8,PCPU(RSP0) movq %r8,PCPU(CURPCB) /* Update the TSS_RSP0 pointer for the next interrupt */ - movq %r8,COMMON_TSS_RSP0(%rdx) + movq %r8,TSS_RSP0(%rdx) movq %r12,PCPU(CURTHREAD) /* into next thread */ /* Test if debug registers should be restored. */ diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c index b6eca2504530..4bdc5e3374f6 100644 --- a/sys/amd64/amd64/genassym.c +++ b/sys/amd64/amd64/genassym.c @@ -153,7 +153,7 @@ ASSYM(PCB_FULL_IRET, PCB_FULL_IRET); ASSYM(PCB_DBREGS, PCB_DBREGS); ASSYM(PCB_32BIT, PCB_32BIT); -ASSYM(COMMON_TSS_RSP0, offsetof(struct amd64tss, tss_rsp0)); +ASSYM(TSS_RSP0, offsetof(struct amd64tss, tss_rsp0)); ASSYM(TF_R15, offsetof(struct trapframe, tf_r15)); ASSYM(TF_R14, offsetof(struct trapframe, tf_r14)); From 0f7c159f6b056d8b6795ec729f5f638ccb4f68b7 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 11 Jan 2018 12:40:43 +0000 Subject: [PATCH 114/158] Move the hardware setup for fast syscalls into a common function. Discussed with: jhb Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/amd64/amd64/machdep.c | 27 +++++++++++++++++---------- sys/amd64/amd64/mp_machdep.c | 14 ++------------ sys/amd64/include/md_var.h | 1 + 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 98af2841bcd3..6022518f32b9 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1512,6 +1512,22 @@ amd64_kdb_init(void) #endif } +/* Set up the fast syscall stuff */ +void +amd64_conf_fast_syscall(void) +{ + uint64_t msr; + + msr = rdmsr(MSR_EFER) | EFER_SCE; + wrmsr(MSR_EFER, msr); + wrmsr(MSR_LSTAR, (u_int64_t)IDTVEC(fast_syscall)); + wrmsr(MSR_CSTAR, (u_int64_t)IDTVEC(fast_syscall32)); + msr = ((u_int64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) | + ((u_int64_t)GSEL(GUCODE32_SEL, SEL_UPL) << 48); + wrmsr(MSR_STAR, msr); + wrmsr(MSR_SF_MASK, PSL_NT | PSL_T | PSL_I | PSL_C | PSL_D); +} + u_int64_t hammer_time(u_int64_t modulep, u_int64_t physfree) { @@ -1520,7 +1536,6 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) struct pcpu *pc; struct nmi_pcpu *np; struct xstate_hdr *xhdr; - u_int64_t msr; char *env; size_t kstack0_sz; int late_console; @@ -1663,15 +1678,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); ltr(gsel_tss); - /* Set up the fast syscall stuff */ - msr = rdmsr(MSR_EFER) | EFER_SCE; - wrmsr(MSR_EFER, msr); - wrmsr(MSR_LSTAR, (u_int64_t)IDTVEC(fast_syscall)); - wrmsr(MSR_CSTAR, (u_int64_t)IDTVEC(fast_syscall32)); - msr = ((u_int64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) | - ((u_int64_t)GSEL(GUCODE32_SEL, SEL_UPL) << 48); - wrmsr(MSR_STAR, msr); - wrmsr(MSR_SF_MASK, PSL_NT|PSL_T|PSL_I|PSL_C|PSL_D); + amd64_conf_fast_syscall(); /* * Temporary forge some valid pointer to PCB, for exception diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index 24474ffa7751..7ce8cf021df7 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -89,8 +89,6 @@ extern struct pcpu __pcpu[]; char *doublefault_stack; char *nmi_stack; -extern inthand_t IDTVEC(fast_syscall), IDTVEC(fast_syscall32); - /* * Local data and functions. */ @@ -190,7 +188,7 @@ init_secondary(void) { struct pcpu *pc; struct nmi_pcpu *np; - u_int64_t msr, cr0; + u_int64_t cr0; int cpu, gsel_tss, x; struct region_descriptor ap_gdt; @@ -265,15 +263,7 @@ init_secondary(void) cr0 &= ~(CR0_CD | CR0_NW | CR0_EM); load_cr0(cr0); - /* Set up the fast syscall stuff */ - msr = rdmsr(MSR_EFER) | EFER_SCE; - wrmsr(MSR_EFER, msr); - wrmsr(MSR_LSTAR, (u_int64_t)IDTVEC(fast_syscall)); - wrmsr(MSR_CSTAR, (u_int64_t)IDTVEC(fast_syscall32)); - msr = ((u_int64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) | - ((u_int64_t)GSEL(GUCODE32_SEL, SEL_UPL) << 48); - wrmsr(MSR_STAR, msr); - wrmsr(MSR_SF_MASK, PSL_NT|PSL_T|PSL_I|PSL_C|PSL_D); + amd64_conf_fast_syscall(); /* signal our startup to the BSP. */ mp_naps++; diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h index 91f023002826..d0c4ef8c549d 100644 --- a/sys/amd64/include/md_var.h +++ b/sys/amd64/include/md_var.h @@ -42,6 +42,7 @@ extern int hw_lower_amd64_sharedpage; struct savefpu; struct sysentvec; +void amd64_conf_fast_syscall(void); void amd64_db_resume_dbreg(void); void amd64_lower_shared_page(struct sysentvec *); void amd64_syscall(struct thread *td, int traced); From 4975c202ac554bdb482994df3d48974f2f6e2801 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 11 Jan 2018 12:54:33 +0000 Subject: [PATCH 115/158] Do not clear %RFLAGS.DF on fast syscall entry. Hardware already did it for us due to the mask loaded into the MSR_SF_MASK msr register. Reviewed by: jhb Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D13838 --- sys/amd64/amd64/exception.S | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S index d3c11082958a..870e36ab97e7 100644 --- a/sys/amd64/amd64/exception.S +++ b/sys/amd64/amd64/exception.S @@ -410,7 +410,6 @@ IDTVEC(fast_syscall) movq %r14,TF_R14(%rsp) /* C preserved */ movq %r15,TF_R15(%rsp) /* C preserved */ movl $TF_HASSEGS,TF_FLAGS(%rsp) - cld FAKE_MCOUNT(TF_RIP(%rsp)) movq PCPU(CURTHREAD),%rdi movq %rsp,TD_FRAME(%rdi) From 6da5c56ae57b49af6b4a58b2523af0da8cbc1816 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 11 Jan 2018 13:22:13 +0000 Subject: [PATCH 116/158] Remove redundand CLD instructions. We already clear %RFLAGS.DF on the kernel entry due to the compiler's ABI requirements. Suggested by: jhb Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- sys/amd64/amd64/support.S | 9 --------- sys/i386/i386/support.s | 11 ----------- 2 files changed, 20 deletions(-) diff --git a/sys/amd64/amd64/support.S b/sys/amd64/amd64/support.S index 042ec5fc3bd4..0e61b87b67c8 100644 --- a/sys/amd64/amd64/support.S +++ b/sys/amd64/amd64/support.S @@ -50,7 +50,6 @@ ENTRY(bzero) movq %rsi,%rcx xorl %eax,%eax shrq $3,%rcx - cld rep stosq movq %rsi,%rcx @@ -100,7 +99,6 @@ ENTRY(bcmp) PUSH_FRAME_POINTER movq %rdx,%rcx shrq $3,%rcx - cld /* compare forwards */ repe cmpsq jne 1f @@ -132,7 +130,6 @@ ENTRY(bcopy) jb 1f shrq $3,%rcx /* copy by 64-bit words */ - cld /* nope, copy forwards */ rep movsq movq %rdx,%rcx @@ -171,7 +168,6 @@ ENTRY(memcpy) movq %rdi,%rax movq %rdx,%rcx shrq $3,%rcx /* copy by 64-bit words */ - cld /* copy forwards */ rep movsq movq %rdx,%rcx @@ -218,7 +214,6 @@ ENTRY(fillw) movq %rdi,%rax movq %rsi,%rdi movq %rdx,%rcx - cld rep stosw POP_FRAME_POINTER @@ -274,7 +269,6 @@ ENTRY(copyout) movq %rdx,%rcx shrq $3,%rcx - cld rep movsq movb %dl,%cl @@ -323,7 +317,6 @@ ENTRY(copyin) movq %rdx,%rcx movb %cl,%al shrq $3,%rcx /* copy longword-wise */ - cld rep movsq movb %al,%cl @@ -620,7 +613,6 @@ ENTRY(copyinstr) movq %rax,%r8 1: incq %rdx - cld 2: decq %rdx @@ -671,7 +663,6 @@ ENTRY(copystr) xchgq %rdi,%rsi incq %rdx - cld 1: decq %rdx jz 4f diff --git a/sys/i386/i386/support.s b/sys/i386/i386/support.s index afbad837f91e..0b17d87030f1 100644 --- a/sys/i386/i386/support.s +++ b/sys/i386/i386/support.s @@ -50,7 +50,6 @@ ENTRY(bzero) movl 12(%esp),%ecx xorl %eax,%eax shrl $2,%ecx - cld rep stosl movl 12(%esp),%ecx @@ -90,7 +89,6 @@ ENTRY(i686_pagezero) movl 12(%esp),%edi movl $1024,%ecx - cld ALIGN_TEXT 1: @@ -141,7 +139,6 @@ ENTRY(fillw) movl 8(%esp),%eax movl 12(%esp),%edi movl 16(%esp),%ecx - cld rep stosw popl %edi @@ -158,7 +155,6 @@ ENTRY(bcopyb) subl %esi,%eax cmpl %ecx,%eax /* overlapping && src < dst? */ jb 1f - cld /* nope, copy forwards */ rep movsb popl %edi @@ -199,7 +195,6 @@ ENTRY(bcopy) jb 1f shrl $2,%ecx /* copy by 32-bit words */ - cld /* nope, copy forwards */ rep movsl movl 16(%ebp),%ecx @@ -245,7 +240,6 @@ ENTRY(memcpy) movl 20(%esp),%ecx movl %edi,%eax shrl $2,%ecx /* copy by 32-bit words */ - cld /* nope, copy forwards */ rep movsl movl 20(%esp),%ecx @@ -314,7 +308,6 @@ ENTRY(copyout) movl %ebx,%ecx shrl $2,%ecx - cld rep movsl movb %bl,%cl @@ -365,7 +358,6 @@ ENTRY(copyin) movb %cl,%al shrl $2,%ecx /* copy longword-wise */ - cld rep movsl movb %al,%cl @@ -582,7 +574,6 @@ ENTRY(copyinstr) movl %eax,20(%esp) 1: incl %edx - cld 2: decl %edx @@ -635,7 +626,6 @@ ENTRY(copystr) movl 16(%esp),%edi /* %edi = to */ movl 20(%esp),%edx /* %edx = maxlen */ incl %edx - cld 1: decl %edx jz 4f @@ -675,7 +665,6 @@ ENTRY(bcmp) movl %edx,%ecx shrl $2,%ecx - cld /* compare forwards */ repe cmpsl jne 1f From 147b0c1a3ea6c3a4085ff9791d19499aecd649e4 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 11 Jan 2018 13:37:45 +0000 Subject: [PATCH 117/158] Softlink inodes can own buffers with dependencies. At least, softlinks longer than 120 bytes have data fragments. Submitted by: mckusick MFC after: 5 days --- sys/ufs/ffs/ffs_softdep.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index d6076020190b..d2b16859ce54 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -13922,7 +13922,8 @@ softdep_bp_to_mp(bp) VI_UNLOCK(vp); if (mp == NULL) goto retry; - } else if (vp->v_type == VREG || vp->v_type == VDIR) { + } else if (vp->v_type == VREG || vp->v_type == VDIR || + vp->v_type == VLNK) { mp = vp->v_mount; } else { return (NULL); From 85f794e1266e89229dc57659e9913dc32a3b7911 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 11 Jan 2018 13:57:30 +0000 Subject: [PATCH 118/158] Skip IRELATIVE relocations when loader processes ELF files. ifuncs can be only called in the (early boot) kernel environment, so postpone resolving until early stage of the kernel boot. This commit is performed in advance to make loaders on most machines updated before ifuncs appear in the kernels. Reviewed by: emaste, jhb Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D13838 --- stand/common/reloc_elf.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stand/common/reloc_elf.c b/stand/common/reloc_elf.c index 22bfe5bccfa6..ce44b275ab02 100644 --- a/stand/common/reloc_elf.c +++ b/stand/common/reloc_elf.c @@ -115,6 +115,7 @@ __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr, const void *reldata, /* XXX, definitions not available on i386. */ #define R_X86_64_64 1 #define R_X86_64_RELATIVE 8 +#define R_X86_64_IRELATIVE 37 switch (rtype) { case R_X86_64_64: /* S + A */ @@ -129,6 +130,9 @@ __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr, const void *reldata, val = addr; *where = val; break; + case R_X86_64_IRELATIVE: + /* leave it to kernel */ + break; default: printf("\nunhandled relocation type %u\n", (u_int)rtype); return (EFTYPE); @@ -173,6 +177,7 @@ __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr, const void *reldata, #define R_386_32 1 /* Add symbol value. */ #define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ #define R_386_RELATIVE 8 /* Add load address of shared object. */ +#define R_386_IRELATIVE 42 switch (rtype) { case R_386_RELATIVE: @@ -186,6 +191,9 @@ __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr, const void *reldata, val = addr + addend; *where = val; break; + case R_386_IRELATIVE: + /* leave it to kernel */ + break; default: printf("\nunhandled relocation type %u\n", (u_int)rtype); return (EFTYPE); From 973c4efb9d611a3c648c3c2015a45fe31239dfca Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Thu, 11 Jan 2018 14:03:05 +0000 Subject: [PATCH 119/158] Enable ld.lld as bootstrap linker by default on i386 Akin to r327783 for amd64. lld has been usable for amd64 for quite some time, but a couple of issues remained that affected i386. These were recently addressed upstream in lld and merged into FreeBSD (r326831, r326879, r326897, r326957), so we can now use ld.lld on i386 as well. Similarly to amd64 this change enables lld only as the bootstrap linker (used to link the kernel and userland libraries and executables), while GNU ld.bfd is still installed as /usr/bin/ld and used for ports builds. The ports collection is essentially ready to use lld as the system linker for amd64, but many ports still have trouble with lld on i386, because lld defaults to -ztext, disallowing relocations against readonly segments. Thus switching the system linker (WITH_LLD_IS_LD) will happen later on a per-arch basis. Relnotes: Yes Sponsored by: The FreeBSD Foundation --- share/mk/src.opts.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk index 0d8c38b646e3..1b5fab6cddba 100644 --- a/share/mk/src.opts.mk +++ b/share/mk/src.opts.mk @@ -253,7 +253,7 @@ __DEFAULT_NO_OPTIONS+=LLVM_LIBUNWIND .endif .if ${__T} == "aarch64" __DEFAULT_YES_OPTIONS+=LLD_BOOTSTRAP LLD_IS_LD -.elif ${__T} == "amd64" +.elif ${__T} == "amd64" || ${__T} == "i386" __DEFAULT_YES_OPTIONS+=LLD_BOOTSTRAP __DEFAULT_NO_OPTIONS+=LLD_IS_LD .else From 02cdaef069c18ccc47e4ada5423eccee817ac712 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Thu, 11 Jan 2018 14:21:07 +0000 Subject: [PATCH 120/158] regen src.conf.5 after r327823, WITH_LLD_BOOTSTRAP for i386 Sponsored by: The FreeBSD Foundation --- share/man/man5/src.conf.5 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5 index af76f3226bcd..645c3604bbd3 100644 --- a/share/man/man5/src.conf.5 +++ b/share/man/man5/src.conf.5 @@ -1,6 +1,6 @@ .\" DO NOT EDIT-- this file is generated by tools/build/options/makeman. .\" $FreeBSD$ -.Dd January 10, 2018 +.Dd January 11, 2018 .Dt SRC.CONF 5 .Os .Sh NAME @@ -970,12 +970,12 @@ To be able to build the system, either Binutils or LLD bootstrap must be enabled unless an alternate linker is provided via XLD. .Pp This is a default setting on -arm/arm, arm/armeb, arm/armv6, arm/armv7, i386/i386, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32, mips/mipselhf, mips/mipshf, mips/mips64elhf, mips/mips64hf, powerpc/powerpc, powerpc/powerpc64, powerpc/powerpcspe, riscv/riscv64, riscv/riscv64sf and sparc64/sparc64. +arm/arm, arm/armeb, arm/armv6, arm/armv7, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32, mips/mipselhf, mips/mipshf, mips/mips64elhf, mips/mips64hf, powerpc/powerpc, powerpc/powerpc64, powerpc/powerpcspe, riscv/riscv64, riscv/riscv64sf and sparc64/sparc64. .It Va WITH_LLD_BOOTSTRAP Set to build the LLD linker during the bootstrap phase of the build. .Pp This is a default setting on -amd64/amd64 and arm64/aarch64. +amd64/amd64, arm64/aarch64 and i386/i386. .It Va WITHOUT_LLD_IS_LD Set to use GNU binutils ld as the system linker, instead of LLVM's LLD. .Pp From 767754e5ab2fde9c65f71e32f08f08846d5122cf Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Thu, 11 Jan 2018 14:29:29 +0000 Subject: [PATCH 121/158] if_awg: Support new emac bindings Highlights of the new bindings: - ahb clock is specified as 'stmmaceth' - The PHY to be used is now specified as phy-handle - We must now check the parent of the node phy-handle points to in order to discover if we're using internal PHY. - The ephy clk/reset will be specified on the PHY node, not the emac node. Care has been taken to ensure that we remain compatible with the older bindings that we were previously using. Tested on: Pine64 (A64, old bindings) Tested on: Pine64-LTS (A64, new bindings) [manu] Tested on: OrangePi-One (H3, internal PHY) [manu] Tested on: NanoPi M1 Plus (H3, external PHY) [manu] Reviewed by: manu Differential Revision: https://reviews.freebsd.org/D13777 --- sys/arm/allwinner/if_awg.c | 58 ++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/sys/arm/allwinner/if_awg.c b/sys/arm/allwinner/if_awg.c index b106b2698993..6f0cef88b185 100644 --- a/sys/arm/allwinner/if_awg.c +++ b/sys/arm/allwinner/if_awg.c @@ -223,6 +223,8 @@ static void awg_txeof(struct awg_softc *sc); static uint32_t syscon_read_emac_clk_reg(device_t dev); static void syscon_write_emac_clk_reg(device_t dev, uint32_t val); +static phandle_t awg_get_phy_node(device_t dev); +static bool awg_has_internal_phy(device_t dev); static int awg_miibus_readreg(device_t dev, int phy, int reg) @@ -1186,6 +1188,35 @@ syscon_write_emac_clk_reg(device_t dev, uint32_t val) bus_write_4(sc->res[_RES_SYSCON], 0, val); } +static phandle_t +awg_get_phy_node(device_t dev) +{ + phandle_t node; + pcell_t phy_handle; + + node = ofw_bus_get_node(dev); + if (OF_getencprop(node, "phy-handle", (void *)&phy_handle, + sizeof(phy_handle)) <= 0) + return (0); + + return (OF_node_from_xref(phy_handle)); +} + +static bool +awg_has_internal_phy(device_t dev) +{ + phandle_t node, phy_node; + + node = ofw_bus_get_node(dev); + /* Legacy binding */ + if (OF_hasprop(node, "allwinner,use-internal-phy")) + return (true); + + phy_node = awg_get_phy_node(dev); + return (phy_node != 0 && ofw_bus_node_is_compatible(OF_parent(phy_node), + "allwinner,sun8i-h3-mdio-internal") != 0); +} + static int awg_setup_phy(device_t dev) { @@ -1241,7 +1272,7 @@ awg_setup_phy(device_t dev) } if (sc->type == EMAC_H3) { - if (OF_hasprop(node, "allwinner,use-internal-phy")) { + if (awg_has_internal_phy(dev)) { reg |= EMAC_CLK_EPHY_SELECT; reg &= ~EMAC_CLK_EPHY_SHUTDOWN; if (OF_hasprop(node, @@ -1308,7 +1339,7 @@ static int awg_setup_extres(device_t dev) { struct awg_softc *sc; - phandle_t node; + phandle_t node, phy_node; hwreset_t rst_ahb, rst_ephy; clk_t clk_ahb, clk_ephy; regulator_t reg; @@ -1320,22 +1351,37 @@ awg_setup_extres(device_t dev) clk_ahb = clk_ephy = NULL; reg = NULL; node = ofw_bus_get_node(dev); + phy_node = awg_get_phy_node(dev); + + if (phy_node == 0 && OF_hasprop(node, "phy-handle")) { + error = ENXIO; + device_printf(dev, "cannot get phy handle\n"); + goto fail; + } /* Get AHB clock and reset resources */ - error = hwreset_get_by_ofw_name(dev, 0, "ahb", &rst_ahb); + error = hwreset_get_by_ofw_name(dev, 0, "stmmaceth", &rst_ahb); + if (error != 0) + error = hwreset_get_by_ofw_name(dev, 0, "ahb", &rst_ahb); if (error != 0) { device_printf(dev, "cannot get ahb reset\n"); goto fail; } if (hwreset_get_by_ofw_name(dev, 0, "ephy", &rst_ephy) != 0) - rst_ephy = NULL; - error = clk_get_by_ofw_name(dev, 0, "ahb", &clk_ahb); + if (phy_node == 0 || hwreset_get_by_ofw_idx(dev, phy_node, 0, + &rst_ephy) != 0) + rst_ephy = NULL; + error = clk_get_by_ofw_name(dev, 0, "stmmaceth", &clk_ahb); + if (error != 0) + error = clk_get_by_ofw_name(dev, 0, "ahb", &clk_ahb); if (error != 0) { device_printf(dev, "cannot get ahb clock\n"); goto fail; } if (clk_get_by_ofw_name(dev, 0, "ephy", &clk_ephy) != 0) - clk_ephy = NULL; + if (phy_node == 0 || clk_get_by_ofw_index(dev, phy_node, 0, + &clk_ephy) != 0) + clk_ephy = NULL; if (OF_hasprop(node, "syscon") && syscon_get_by_ofw_property(dev, node, "syscon", &sc->syscon) != 0) { From 21ab148d783814f0157935e3fd210b2f22cdb00f Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Thu, 11 Jan 2018 15:01:48 +0000 Subject: [PATCH 122/158] patch(1): Don't check for NUL bytes in Plan A Plan A mmap()'s the entire input file and operates on it in memory. The map(2) call succeeded, so we shouldn't need to bother checking for the NUL byte as long as we're within our buffer space. This was clearly intentional to match "the behavior of the original code", but it creates a discrepancy between Plan A and Plan B that doesn't seem sensible and it's not inherently wrong to allow a NUL byte. This change was motivated by the gemspec in net/rubygem-grpc failing to patch, despite the patch being generated with diff, because a NUL byte was used as a delimiter in the header briefly in an otherwise text file. An alternative was considered: to fallback to plan B if plan A won't process the entire file due to a NUL byte, but I deemed this to be the better option since plan A isn't failing due to memory limitations and will fail later on if it's really dealing with a file it shouldn't be. PR: 224842 (exp-run) Reported by: swills Reviewed by: emaste, pfg MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D13738 --- usr.bin/patch/inp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/usr.bin/patch/inp.c b/usr.bin/patch/inp.c index 2c955d0c8377..6a01f782ce62 100644 --- a/usr.bin/patch/inp.c +++ b/usr.bin/patch/inp.c @@ -213,8 +213,11 @@ plan_a(const char *filename) /* now scan the buffer and build pointer array */ iline = 1; i_ptr[iline] = i_womp; - /* test for NUL too, to maintain the behavior of the original code */ - for (s = i_womp, i = 0; i < i_size && *s != '\0'; s++, i++) { + /* + * Testing for NUL here actively breaks files that innocently use NUL + * for other reasons. mmap(2) succeeded, just scan the whole buffer. + */ + for (s = i_womp, i = 0; i < i_size; s++, i++) { if (*s == '\n') { if (iline == lines_allocated) { if (!reallocate_lines(&lines_allocated)) From e426794f61226dffdd8447d0709a0c48c51da73a Mon Sep 17 00:00:00 2001 From: Michal Meloun Date: Thu, 11 Jan 2018 15:03:01 +0000 Subject: [PATCH 123/158] Initialize CONTEXTIDR register on secondary cores by zero, not with undefined value from X1 register. MFC after: 1 month --- sys/arm64/arm64/locore.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S index 310ce2744890..09d844442da1 100644 --- a/sys/arm64/arm64/locore.S +++ b/sys/arm64/arm64/locore.S @@ -167,7 +167,7 @@ ENTRY(mpentry) bl drop_to_el1 /* Set the context id */ - msr contextidr_el1, x1 + msr contextidr_el1, xzr /* Load the kernel page table */ adr x24, pagetable_l0_ttbr1 From efaa3e0789f4a44018d91ce2521d57453ce6eed9 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Thu, 11 Jan 2018 15:25:26 +0000 Subject: [PATCH 124/158] dev/(e1000,ixl): Make some use of mallocarray(9). Reviewed by: erj Differential Revision: https://reviews.freebsd.org/D13833 --- sys/dev/e1000/if_em.c | 13 +++++++------ sys/dev/ixl/if_ixlv.c | 4 ++-- sys/dev/ixl/ixl_pf_iov.c | 4 ++-- sys/dev/ixl/ixl_pf_main.c | 9 +++++---- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index ee6eeed61e09..52d62936d5f2 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -2835,9 +2835,9 @@ em_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int ntxqs /* First allocate the top level queue structs */ if (!(adapter->tx_queues = - (struct em_tx_queue *) malloc(sizeof(struct em_tx_queue) * - adapter->tx_num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { - device_printf(iflib_get_dev(ctx), "Unable to allocate queue memory\n"); + (struct em_tx_queue *) mallocarray(adapter->tx_num_queues, + sizeof(struct em_tx_queue), M_DEVBUF, M_NOWAIT | M_ZERO))) { + device_printf(iflib_get_dev(ctx), "Unable to allocate queue memory\n"); return(ENOMEM); } @@ -2849,7 +2849,8 @@ em_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int ntxqs que->me = txr->me = i; /* Allocate report status array */ - if (!(txr->tx_rsq = (qidx_t *) malloc(sizeof(qidx_t) * scctx->isc_ntxd[0], M_DEVBUF, M_NOWAIT | M_ZERO))) { + if (!(txr->tx_rsq = (qidx_t *) mallocarray(scctx->isc_ntxd[0], + sizeof(qidx_t), M_DEVBUF, M_NOWAIT | M_ZERO))) { device_printf(iflib_get_dev(ctx), "failed to allocate rs_idxs memory\n"); error = ENOMEM; goto fail; @@ -2881,8 +2882,8 @@ em_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nrxqs /* First allocate the top level queue structs */ if (!(adapter->rx_queues = - (struct em_rx_queue *) malloc(sizeof(struct em_rx_queue) * - adapter->rx_num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { + (struct em_rx_queue *) mallocarray(adapter->rx_num_queues, + sizeof(struct em_rx_queue), M_DEVBUF, M_NOWAIT | M_ZERO))) { device_printf(iflib_get_dev(ctx), "Unable to allocate queue memory\n"); error = ENOMEM; goto fail; diff --git a/sys/dev/ixl/if_ixlv.c b/sys/dev/ixl/if_ixlv.c index 390ef51e5ce8..23c830e629ab 100644 --- a/sys/dev/ixl/if_ixlv.c +++ b/sys/dev/ixl/if_ixlv.c @@ -1637,8 +1637,8 @@ ixlv_setup_queues(struct ixlv_sc *sc) /* Get memory for the station queues */ if (!(vsi->queues = - (struct ixl_queue *) malloc(sizeof(struct ixl_queue) * - vsi->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { + (struct ixl_queue *) mallocarray(vsi->num_queues, + sizeof(struct ixl_queue), M_DEVBUF, M_NOWAIT | M_ZERO))) { device_printf(dev, "Unable to allocate queue memory\n"); error = ENOMEM; goto early; diff --git a/sys/dev/ixl/ixl_pf_iov.c b/sys/dev/ixl/ixl_pf_iov.c index 2662d0df65a2..ec9f98bfdfff 100644 --- a/sys/dev/ixl/ixl_pf_iov.c +++ b/sys/dev/ixl/ixl_pf_iov.c @@ -1695,8 +1695,8 @@ ixl_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *params) pf_vsi = &pf->vsi; IXL_PF_LOCK(pf); - pf->vfs = malloc(sizeof(struct ixl_vf) * num_vfs, M_IXL, M_NOWAIT | - M_ZERO); + pf->vfs = mallocarray(num_vfs, sizeof(struct ixl_vf), M_IXL, + M_NOWAIT | M_ZERO); if (pf->vfs == NULL) { error = ENOMEM; diff --git a/sys/dev/ixl/ixl_pf_main.c b/sys/dev/ixl/ixl_pf_main.c index fa271d434ec4..0028cc4bfe85 100644 --- a/sys/dev/ixl/ixl_pf_main.c +++ b/sys/dev/ixl/ixl_pf_main.c @@ -2431,8 +2431,8 @@ ixl_setup_stations(struct ixl_pf *pf) /* Get memory for the station queues */ if (!(vsi->queues = - (struct ixl_queue *) malloc(sizeof(struct ixl_queue) * - vsi->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) { + (struct ixl_queue *) mallocarray(vsi->num_queues, + sizeof(struct ixl_queue), M_DEVBUF, M_NOWAIT | M_ZERO))) { device_printf(dev, "Unable to allocate queue memory\n"); error = ENOMEM; return (error); @@ -3317,7 +3317,7 @@ ixl_add_hw_filters(struct ixl_vsi *vsi, int flags, int cnt) hw = &pf->hw; IXL_PF_LOCK_ASSERT(pf); - a = malloc(sizeof(struct i40e_aqc_add_macvlan_element_data) * cnt, + a = mallocarray(cnt, sizeof(struct i40e_aqc_add_macvlan_element_data), M_DEVBUF, M_NOWAIT | M_ZERO); if (a == NULL) { device_printf(dev, "add_hw_filters failed to get memory\n"); @@ -3380,7 +3380,8 @@ ixl_del_hw_filters(struct ixl_vsi *vsi, int cnt) hw = &pf->hw; dev = pf->dev; - d = malloc(sizeof(struct i40e_aqc_remove_macvlan_element_data) * cnt, + d = mallocarray(cnt, + sizeof(struct i40e_aqc_remove_macvlan_element_data), M_DEVBUF, M_NOWAIT | M_ZERO); if (d == NULL) { printf("del hw filter failed to get memory\n"); From 454529cd0b3ccae9ddaaef3e9d199eca3a8ba59e Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Thu, 11 Jan 2018 15:29:29 +0000 Subject: [PATCH 125/158] netpfil/ipfw: Make some use of mallocarray(9). Reviewed by: kp, ae Differential Revision: https://reviews.freebsd.org/D13834 --- sys/netpfil/ipfw/dn_heap.c | 2 +- sys/netpfil/ipfw/dn_sched_fq_codel.c | 4 ++-- sys/netpfil/ipfw/dn_sched_fq_pie.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/netpfil/ipfw/dn_heap.c b/sys/netpfil/ipfw/dn_heap.c index 3e5b69650f8a..ab81cfcc656a 100644 --- a/sys/netpfil/ipfw/dn_heap.c +++ b/sys/netpfil/ipfw/dn_heap.c @@ -94,7 +94,7 @@ heap_resize(struct dn_heap *h, unsigned int new_size) #else new_size = (new_size + HEAP_INCREMENT ) & ~HEAP_INCREMENT; #endif - p = malloc(new_size * sizeof(*p), M_DN_HEAP, M_NOWAIT); + p = mallocarray(new_size, sizeof(*p), M_DN_HEAP, M_NOWAIT); if (p == NULL) { printf("--- %s, resize %d failed\n", __func__, new_size ); return 1; /* error */ diff --git a/sys/netpfil/ipfw/dn_sched_fq_codel.c b/sys/netpfil/ipfw/dn_sched_fq_codel.c index 38b9379f52a5..cc5dc5a17203 100644 --- a/sys/netpfil/ipfw/dn_sched_fq_codel.c +++ b/sys/netpfil/ipfw/dn_sched_fq_codel.c @@ -453,8 +453,8 @@ fq_codel_new_sched(struct dn_sch_inst *_si) q->fs = _si->sched->fs; /* allocate memory for flows array */ - si->flows = malloc(schk->cfg.flows_cnt * sizeof(struct fq_codel_flow), - M_DUMMYNET, M_NOWAIT | M_ZERO); + si->flows = mallocarray(schk->cfg.flows_cnt, + sizeof(struct fq_codel_flow), M_DUMMYNET, M_NOWAIT | M_ZERO); if (si->flows == NULL) { D("cannot allocate memory for fq_codel configuration parameters"); return ENOMEM ; diff --git a/sys/netpfil/ipfw/dn_sched_fq_pie.c b/sys/netpfil/ipfw/dn_sched_fq_pie.c index b6f235d8ba6d..3960ea8ad6ae 100644 --- a/sys/netpfil/ipfw/dn_sched_fq_pie.c +++ b/sys/netpfil/ipfw/dn_sched_fq_pie.c @@ -1034,8 +1034,8 @@ fq_pie_new_sched(struct dn_sch_inst *_si) return ENOMEM ; } /* allocate memory for flows array */ - si->si_extra->flows = malloc(schk->cfg.flows_cnt * sizeof(struct fq_pie_flow), - M_DUMMYNET, M_NOWAIT | M_ZERO); + si->si_extra->flows = mallocarray(schk->cfg.flows_cnt, + sizeof(struct fq_pie_flow), M_DUMMYNET, M_NOWAIT | M_ZERO); flows = si->si_extra->flows; if (flows == NULL) { free(si->si_extra, M_DUMMYNET); From 92e1020a5296adc35b7190c597adc701d60a06f2 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Thu, 11 Jan 2018 15:44:03 +0000 Subject: [PATCH 126/158] dev/bhnd: Make use of mallocarray(9). This makes a calloc-like definition check for overflows as is common practice. --- sys/dev/bhnd/bcma/bcma_erom.c | 2 +- sys/dev/bhnd/nvram/bhnd_nvram_private.h | 2 +- sys/dev/bhnd/siba/siba_erom.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/dev/bhnd/bcma/bcma_erom.c b/sys/dev/bhnd/bcma/bcma_erom.c index 7b5ab846f961..11951c9dc11f 100644 --- a/sys/dev/bhnd/bcma/bcma_erom.c +++ b/sys/dev/bhnd/bcma/bcma_erom.c @@ -400,7 +400,7 @@ bcma_erom_get_core_table(bhnd_erom_t *erom, struct bhnd_core_info **cores, } /* Allocate our output buffer */ - buffer = malloc(sizeof(struct bhnd_core_info) * count, M_BHND, + buffer = mallocarray(count, sizeof(struct bhnd_core_info), M_BHND, M_NOWAIT); if (buffer == NULL) { error = ENOMEM; diff --git a/sys/dev/bhnd/nvram/bhnd_nvram_private.h b/sys/dev/bhnd/nvram/bhnd_nvram_private.h index 3d1c22d20c21..bbcf4f3e49cb 100644 --- a/sys/dev/bhnd/nvram/bhnd_nvram_private.h +++ b/sys/dev/bhnd/nvram/bhnd_nvram_private.h @@ -74,7 +74,7 @@ MALLOC_DECLARE(M_BHND_NVRAM); #define bhnd_nv_toupper(c) toupper(c) #define bhnd_nv_malloc(size) malloc((size), M_BHND_NVRAM, M_NOWAIT) -#define bhnd_nv_calloc(n, size) malloc((n) * (size), M_BHND_NVRAM, \ +#define bhnd_nv_calloc(n, size) mallocarray((n), (size), M_BHND_NVRAM, \ M_NOWAIT | M_ZERO) #define bhnd_nv_reallocf(buf, size) reallocf((buf), (size), M_BHND_NVRAM, \ M_NOWAIT) diff --git a/sys/dev/bhnd/siba/siba_erom.c b/sys/dev/bhnd/siba/siba_erom.c index ac529da72ce7..57b2f79e833b 100644 --- a/sys/dev/bhnd/siba/siba_erom.c +++ b/sys/dev/bhnd/siba/siba_erom.c @@ -445,7 +445,7 @@ siba_erom_get_core_table(bhnd_erom_t *erom, struct bhnd_core_info **cores, sc = (struct siba_erom *)erom; /* Allocate our core array */ - out = malloc(sizeof(*out) * sc->io.ncores, M_BHND, M_NOWAIT); + out = mallocarray(sc->io.ncores, sizeof(*out), M_BHND, M_NOWAIT); if (out == NULL) return (ENOMEM); From 12cea332f105eeca4a6491ff6950ae0397b93a26 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Thu, 11 Jan 2018 16:04:04 +0000 Subject: [PATCH 127/158] vmstat(8): Hook up NetBSD tests The NetBSD tests for vmstat are basically just a smoke test, ensuring that executing `vmstat` and `vmstat -s` exit successfully. This is more than we test now, so go with it. --- etc/mtree/BSD.tests.dist | 2 ++ usr.bin/vmstat/Makefile | 5 +++++ usr.bin/vmstat/tests/Makefile | 9 +++++++++ 3 files changed, 16 insertions(+) create mode 100644 usr.bin/vmstat/tests/Makefile diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 342455a51768..540b1521ba2d 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -736,6 +736,8 @@ .. uniq .. + vmstat + .. xargs .. xinstall diff --git a/usr.bin/vmstat/Makefile b/usr.bin/vmstat/Makefile index 4fd0994117b7..72734cc69c3e 100644 --- a/usr.bin/vmstat/Makefile +++ b/usr.bin/vmstat/Makefile @@ -1,10 +1,15 @@ # @(#)Makefile 8.1 (Berkeley) 6/6/93 # $FreeBSD$ +.include + PROG= vmstat MAN= vmstat.8 LIBADD= devstat kvm memstat xo util WARNS?= 6 +HAS_TESTS= +SUBDIR.${MK_TESTS}+= tests + .include diff --git a/usr.bin/vmstat/tests/Makefile b/usr.bin/vmstat/tests/Makefile new file mode 100644 index 000000000000..d5c3b2a0469f --- /dev/null +++ b/usr.bin/vmstat/tests/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +PACKAGE= tests + +NETBSD_ATF_TESTS_SH= vmstat_test + +.include + +.include From aeb8ee1709a2e6e1d1e36b3ce2fef2e7a9787bfc Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Thu, 11 Jan 2018 16:41:03 +0000 Subject: [PATCH 128/158] Add mallocarray.9 to malloc.9's MLINKS. X-MFC with: r327674 --- share/man/man9/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 2a39f216d4d3..4bf35bd417e8 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -1262,6 +1262,7 @@ MLINKS+=make_dev.9 destroy_dev.9 \ make_dev.9 make_dev_p.9 \ make_dev.9 make_dev_s.9 MLINKS+=malloc.9 free.9 \ + malloc.9 mallocarray.9 \ malloc.9 MALLOC_DECLARE.9 \ malloc.9 MALLOC_DEFINE.9 \ malloc.9 realloc.9 \ From c751f90c0c3b24e478cfb65f05b0f21fd8e2b41a Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 11 Jan 2018 16:50:03 +0000 Subject: [PATCH 129/158] Fix grammar. Submitted by: alc MFC after: 3 days --- sys/amd64/amd64/support.S | 5 +++-- sys/i386/i386/support.s | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sys/amd64/amd64/support.S b/sys/amd64/amd64/support.S index 0e61b87b67c8..3f0cc181a8a7 100644 --- a/sys/amd64/amd64/support.S +++ b/sys/amd64/amd64/support.S @@ -245,8 +245,9 @@ ENTRY(copyout) /* * Check explicitly for non-user addresses. This check is essential - * because it prevents usermode from writing into kernel. We do not - * verify that user did not specified a rogue address anywhere else. + * because it prevents usermode from writing into the kernel. We do + * not verify anywhere else that the user did not specify a rogue + * address. */ /* * First, prevent address wrapping. diff --git a/sys/i386/i386/support.s b/sys/i386/i386/support.s index 0b17d87030f1..65e3a69a4a52 100644 --- a/sys/i386/i386/support.s +++ b/sys/i386/i386/support.s @@ -286,8 +286,9 @@ ENTRY(copyout) /* * Check explicitly for non-user addresses. This check is essential - * because it prevents usermode from writing into kernel. We do not - * verify that user did not specified a rogue address anywhere else. + * because it prevents usermode from writing into the kernel. We do + * not verify anywhere else that the user did not specify a rogue + * address. */ /* * First, prevent address wrapping. From 224c3776f6276dffc2eb1ef83a1a27ac5d0dc5dd Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Thu, 11 Jan 2018 17:09:12 +0000 Subject: [PATCH 130/158] Add the start of INTRNG support for ACPI. This adds a new acpi_bus interface with a map_intr method. This is similar to the Open Firmware map_intr method and allows us to create the needed mapping from ACPI space to INTRNG space. Obtained from: ABT Systems Ltd Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D8617 --- sys/arm/arm/generic_timer.c | 19 +++++++--- sys/arm64/arm64/nexus.c | 32 ++++++++++++++++ sys/conf/files.arm64 | 1 + sys/dev/acpica/acpi.c | 4 ++ sys/dev/acpica/acpi_bus_if.m | 67 ++++++++++++++++++++++++++++++++++ sys/dev/acpica/acpi_resource.c | 24 +++++++++++- sys/dev/acpica/acpivar.h | 13 +++++++ 7 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 sys/dev/acpica/acpi_bus_if.m diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c index 5e9cabab14d1..b13080d57bbe 100644 --- a/sys/arm/arm/generic_timer.c +++ b/sys/arm/arm/generic_timer.c @@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$"); #ifdef DEV_ACPI #include #include +#include "acpi_bus_if.h" #endif #define GT_CTRL_ENABLE (1 << 0) @@ -312,6 +313,15 @@ arm_tmr_fdt_probe(device_t dev) #endif #ifdef DEV_ACPI +static void +arm_tmr_acpi_add_irq(device_t parent, device_t dev, int rid, u_int irq) +{ + + irq = ACPI_BUS_MAP_INTR(parent, dev, irq, + INTR_TRIGGER_LEVEL, INTR_POLARITY_HIGH); + BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, rid, irq, 1); +} + static void arm_tmr_acpi_identify(driver_t *driver, device_t parent) { @@ -336,12 +346,9 @@ arm_tmr_acpi_identify(driver_t *driver, device_t parent) goto out; } - BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 0, - gtdt->SecureEl1Interrupt, 1); - BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 1, - gtdt->NonSecureEl1Interrupt, 1); - BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 2, - gtdt->VirtualTimerInterrupt, 1); + arm_tmr_acpi_add_irq(parent, dev, 0, gtdt->SecureEl1Interrupt); + arm_tmr_acpi_add_irq(parent, dev, 1, gtdt->NonSecureEl1Interrupt); + arm_tmr_acpi_add_irq(parent, dev, 2, gtdt->VirtualTimerInterrupt); out: acpi_unmap_table(gtdt); diff --git a/sys/arm64/arm64/nexus.c b/sys/arm64/arm64/nexus.c index 31ec8f091002..3de441a9001f 100644 --- a/sys/arm64/arm64/nexus.c +++ b/sys/arm64/arm64/nexus.c @@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$"); #ifdef DEV_ACPI #include #include +#include "acpi_bus_if.h" #endif extern struct bus_space memmap_bus; @@ -460,11 +461,16 @@ nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, #endif #ifdef DEV_ACPI +static int nexus_acpi_map_intr(device_t dev, device_t child, u_int irq, int trig, int pol); + static device_method_t nexus_acpi_methods[] = { /* Device interface */ DEVMETHOD(device_probe, nexus_acpi_probe), DEVMETHOD(device_attach, nexus_acpi_attach), + /* ACPI interface */ + DEVMETHOD(acpi_bus_map_intr, nexus_acpi_map_intr), + DEVMETHOD_END, }; @@ -495,4 +501,30 @@ nexus_acpi_attach(device_t dev) nexus_add_child(dev, 10, "acpi", 0); return (nexus_attach(dev)); } + +static int +nexus_acpi_map_intr(device_t dev, device_t child, u_int irq, int trig, int pol) +{ + struct intr_map_data_acpi *acpi_data; + size_t len; + + len = sizeof(*acpi_data); + acpi_data = (struct intr_map_data_acpi *)intr_alloc_map_data( + INTR_MAP_DATA_ACPI, len, M_WAITOK | M_ZERO); + acpi_data->irq = irq; + acpi_data->pol = pol; + acpi_data->trig = trig; + + /* + * TODO: This will only handle a single interrupt controller. + * ACPI will map multiple controllers into a single virtual IRQ + * space. Each controller has a System Vector Base to hold the + * first irq it handles in this space. As such the correct way + * to handle interrupts with ACPI is to search through the + * controllers for the largest base value that is no larger than + * the IRQ value. + */ + irq = intr_map_irq(NULL, 0, (struct intr_map_data *)acpi_data); + return (irq); +} #endif diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index a4e86bc35ffb..d45e5577c3e8 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -167,6 +167,7 @@ armv8_crypto_wrap.o optional armv8crypto \ clean "armv8_crypto_wrap.o" crypto/blowfish/bf_enc.c optional crypto | ipsec | ipsec_support crypto/des/des_enc.c optional crypto | ipsec | ipsec_support | netsmb +dev/acpica/acpi_bus_if.m optional acpi dev/acpica/acpi_if.m optional acpi dev/ahci/ahci_generic.c optional ahci dev/axgbe/if_axgbe.c optional axgbe diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index cda93b6bc2c8..c6559579f3a9 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -1358,7 +1358,9 @@ static struct resource * acpi_alloc_resource(device_t bus, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { +#ifndef INTRNG ACPI_RESOURCE ares; +#endif struct acpi_device *ad; struct resource_list_entry *rle; struct resource_list *rl; @@ -1385,6 +1387,7 @@ acpi_alloc_resource(device_t bus, device_t child, int type, int *rid, resource_list_add(rl, type, *rid, start, end, count); res = resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags); +#ifndef INTRNG if (res != NULL && type == SYS_RES_IRQ) { /* * Since bus_config_intr() takes immediate effect, we cannot @@ -1397,6 +1400,7 @@ acpi_alloc_resource(device_t bus, device_t child, int type, int *rid, if (ACPI_SUCCESS(acpi_lookup_irq_resource(child, *rid, res, &ares))) acpi_config_intr(child, &ares); } +#endif /* * If this is an allocation of the "default" range for a given diff --git a/sys/dev/acpica/acpi_bus_if.m b/sys/dev/acpica/acpi_bus_if.m new file mode 100644 index 000000000000..df3f930af086 --- /dev/null +++ b/sys/dev/acpica/acpi_bus_if.m @@ -0,0 +1,67 @@ +#- +# Copyright (c) 2016 The FreeBSD Foundation +# All rights reserved. +# +# This software was developed by Andrew Turner 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$ + +#include +#include +#include + +INTERFACE acpi_bus; + +CODE { + static acpi_bus_map_intr_t acpi_bus_default_map_intr; + + int + acpi_bus_default_map_intr(device_t bus, device_t dev, u_int irq, + int trig, int pol) + { + device_t parent; + + /* Pass up the hierarchy */ + parent = device_get_parent(bus); + if (parent != NULL) + return (ACPI_BUS_MAP_INTR(parent, dev, irq, trig, pol)); + + panic("Unable to map interrupt %u", irq); + } +}; + +# Map an interrupt from ACPI space to the FreeBSD IRQ space. Note that +# both of these may be different than the pysical interrupt space as this +# may be local to each interrupt controller. +# +# This method also associates interrupt metadata with the interrupt, +# removing the need for a post hoc configure step. +METHOD int map_intr { + device_t bus; + device_t dev; + u_int irq; + int trig; + int pol; +} DEFAULT acpi_bus_default_map_intr; diff --git a/sys/dev/acpica/acpi_resource.c b/sys/dev/acpica/acpi_resource.c index 078ecce1eb0a..0a1b69ac93b5 100644 --- a/sys/dev/acpica/acpi_resource.c +++ b/sys/dev/acpica/acpi_resource.c @@ -45,6 +45,10 @@ __FBSDID("$FreeBSD$"); #include +#ifdef INTRNG +#include "acpi_bus_if.h" +#endif + /* Hooks for the ACPI CA debugging infrastructure */ #define _COMPONENT ACPI_BUS ACPI_MODULE_NAME("RESOURCE") @@ -556,6 +560,7 @@ acpi_res_set_irq(device_t dev, void *context, uint8_t *irq, int count, int trig, int pol) { struct acpi_res_context *cp = (struct acpi_res_context *)context; + rman_res_t intr; if (cp == NULL || irq == NULL) return; @@ -564,7 +569,14 @@ acpi_res_set_irq(device_t dev, void *context, uint8_t *irq, int count, if (count != 1) return; - bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1); +#ifdef INTRNG + intr = ACPI_BUS_MAP_INTR(device_get_parent(dev), dev, *irq, + (trig == ACPI_EDGE_SENSITIVE) ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, + (pol == ACPI_ACTIVE_HIGH) ? INTR_POLARITY_HIGH : INTR_POLARITY_LOW); +#else + intr = *irq; +#endif + bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, intr, 1); } static void @@ -572,6 +584,7 @@ acpi_res_set_ext_irq(device_t dev, void *context, uint32_t *irq, int count, int trig, int pol) { struct acpi_res_context *cp = (struct acpi_res_context *)context; + rman_res_t intr; if (cp == NULL || irq == NULL) return; @@ -580,7 +593,14 @@ acpi_res_set_ext_irq(device_t dev, void *context, uint32_t *irq, int count, if (count != 1) return; - bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1); +#ifdef INTRNG + intr = ACPI_BUS_MAP_INTR(device_get_parent(dev), dev, *irq, + (trig == ACPI_EDGE_SENSITIVE) ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, + (pol == ACPI_ACTIVE_HIGH) ? INTR_POLARITY_HIGH : INTR_POLARITY_LOW); +#else + intr = *irq; +#endif + bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, intr, 1); } static void diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h index 647e59b8d171..6b26cf455f55 100644 --- a/sys/dev/acpica/acpivar.h +++ b/sys/dev/acpica/acpivar.h @@ -36,6 +36,9 @@ #include "acpi_if.h" #include "bus_if.h" #include +#ifdef INTRNG +#include +#endif #include #include #include @@ -91,6 +94,16 @@ struct acpi_device { struct resource_list ad_rl; }; +#ifdef INTRNG +struct intr_map_data_acpi { + struct intr_map_data hdr; + u_int irq; + u_int pol; + u_int trig; +}; + +#endif + /* Track device (/dev/{apm,apmctl} and /dev/acpi) notification status. */ struct apm_clone_data { STAILQ_ENTRY(apm_clone_data) entries; From ee42eb7e5c6547c2cfd228b4beebb1577efdd054 Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Thu, 11 Jan 2018 17:23:24 +0000 Subject: [PATCH 131/158] iAdd ACPI attachments the the GIC and GICv3 interrupt controller drivers. For each we need to walk the MADT to find which we have, then add the driver as needed. As each may have a child they will each walk the same table to find these details. Reviewed by: mmel Obtained from: ABT Systems Ltd Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D8720 --- sys/arm/arm/gic.c | 17 ++ sys/arm/arm/gic_acpi.c | 346 ++++++++++++++++++++++++++++++++++ sys/arm64/arm64/gic_v3.c | 17 ++ sys/arm64/arm64/gic_v3_acpi.c | 335 ++++++++++++++++++++++++++++++++ sys/arm64/arm64/gic_v3_var.h | 8 +- sys/arm64/arm64/gicv3_its.c | 62 +++++- sys/conf/files.arm64 | 2 + 7 files changed, 782 insertions(+), 5 deletions(-) create mode 100644 sys/arm/arm/gic_acpi.c create mode 100644 sys/arm64/arm64/gic_v3_acpi.c diff --git a/sys/arm/arm/gic.c b/sys/arm/arm/gic.c index 5987186b20d3..4aa6fd338a69 100644 --- a/sys/arm/arm/gic.c +++ b/sys/arm/arm/gic.c @@ -36,6 +36,7 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_acpi.h" #include "opt_platform.h" #include @@ -68,6 +69,11 @@ __FBSDID("$FreeBSD$"); #include #endif +#ifdef DEV_ACPI +#include +#include +#endif + #include #include @@ -888,6 +894,9 @@ gic_map_intr(device_t dev, struct intr_map_data *data, u_int *irqp, #ifdef FDT struct intr_map_data_fdt *daf; #endif +#ifdef DEV_ACPI + struct intr_map_data_acpi *daa; +#endif sc = device_get_softc(dev); switch (data->type) { @@ -902,6 +911,14 @@ gic_map_intr(device_t dev, struct intr_map_data *data, u_int *irqp, ("%s: Attempting to map a MSI interrupt from FDT", __func__)); break; +#endif +#ifdef DEV_ACPI + case INTR_MAP_DATA_ACPI: + daa = (struct intr_map_data_acpi *)data; + irq = daa->irq; + pol = daa->pol; + trig = daa->trig; + break; #endif case INTR_MAP_DATA_MSI: /* Non-GICv2m MSI */ diff --git a/sys/arm/arm/gic_acpi.c b/sys/arm/arm/gic_acpi.c new file mode 100644 index 000000000000..d6a75a71e3a0 --- /dev/null +++ b/sys/arm/arm/gic_acpi.c @@ -0,0 +1,346 @@ +/*- + * Copyright (c) 2011,2016 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Andrew Turner under + * sponsorship from the FreeBSD Foundation. + * + * Developed by Damjan Marion + * + * Based on OMAP4 GIC code by Ben Gray + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opt_platform.h" + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include + +struct gic_acpi_devinfo { + struct resource_list rl; +}; + +static device_identify_t gic_acpi_identify; +static device_probe_t gic_acpi_probe; +static device_attach_t gic_acpi_attach; +static bus_get_resource_list_t gic_acpi_get_resource_list; +static bool arm_gic_add_children(device_t); + +static device_method_t gic_acpi_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, gic_acpi_identify), + DEVMETHOD(device_probe, gic_acpi_probe), + DEVMETHOD(device_attach, gic_acpi_attach), + + /* Bus interface */ + DEVMETHOD(bus_get_resource_list, gic_acpi_get_resource_list), + + DEVMETHOD_END, +}; + +DEFINE_CLASS_1(gic, gic_acpi_driver, gic_acpi_methods, + sizeof(struct arm_gic_softc), arm_gic_driver); + +static devclass_t gic_acpi_devclass; + +EARLY_DRIVER_MODULE(gic, acpi, gic_acpi_driver, gic_acpi_devclass, 0, 0, + BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); + +struct madt_table_data { + device_t parent; + ACPI_MADT_GENERIC_DISTRIBUTOR *dist; + ACPI_MADT_GENERIC_INTERRUPT *intr[MAXCPU]; +}; + +static void +madt_handler(ACPI_SUBTABLE_HEADER *entry, void *arg) +{ + struct madt_table_data *madt_data; + ACPI_MADT_GENERIC_INTERRUPT *intr; + + madt_data = (struct madt_table_data *)arg; + + switch(entry->Type) { + case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR: + if (madt_data->dist != NULL) { + if (bootverbose) + device_printf(madt_data->parent, + "gic: Already have a distributor table"); + } else + madt_data->dist = + (ACPI_MADT_GENERIC_DISTRIBUTOR *)entry; + break; + case ACPI_MADT_TYPE_GENERIC_INTERRUPT: + intr = (ACPI_MADT_GENERIC_INTERRUPT *)entry; + if (intr->CpuInterfaceNumber < MAXCPU) + madt_data->intr[intr->CpuInterfaceNumber] = intr; + break; + } +} + +static void +gic_acpi_identify(driver_t *driver, device_t parent) +{ + struct madt_table_data madt_data; + ACPI_MADT_GENERIC_INTERRUPT *intr; + ACPI_TABLE_MADT *madt; + vm_paddr_t physaddr; + device_t dev; + int i; + + physaddr = acpi_find_table(ACPI_SIG_MADT); + if (physaddr == 0) + return; + + madt = acpi_map_table(physaddr, ACPI_SIG_MADT); + if (madt == NULL) { + device_printf(parent, "gic: Unable to map the MADT\n"); + return; + } + + bzero(&madt_data, sizeof(madt_data)); + madt_data.parent = parent; + madt_data.dist = NULL; + + acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, + madt_handler, &madt_data); + + /* Check the version of the GIC we have */ + switch (madt_data.dist->Version) { + case ACPI_MADT_GIC_VERSION_NONE: + case ACPI_MADT_GIC_VERSION_V1: + case ACPI_MADT_GIC_VERSION_V2: + break; + default: + goto out; + } + + intr = NULL; + for (i = 0; i < MAXCPU; i++) { + if (madt_data.intr[i] != NULL) { + if (intr == NULL) { + intr = madt_data.intr[i]; + } else if (intr->BaseAddress != + madt_data.intr[i]->BaseAddress) { + device_printf(parent, +"gic: Not all CPU interfaces at the same address, this may fail\n"); + } + } + } + if (intr == NULL) { + device_printf(parent, "gic: No CPU interfaces found\n"); + goto out; + } + + dev = BUS_ADD_CHILD(parent, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE, + "gic", -1); + if (dev == NULL) { + device_printf(parent, "add gic child failed\n"); + goto out; + } + + BUS_SET_RESOURCE(parent, dev, SYS_RES_MEMORY, 0, + madt_data.dist->BaseAddress, 4 * 1024); + BUS_SET_RESOURCE(parent, dev, SYS_RES_MEMORY, 1, + intr->BaseAddress, 4 * 1024); + + acpi_set_private(dev, (void *)(uintptr_t)madt_data.dist->Version); +out: + acpi_unmap_table(madt); +} + +static int +gic_acpi_probe(device_t dev) +{ + + switch((uintptr_t)acpi_get_private(dev)) { + case ACPI_MADT_GIC_VERSION_NONE: + case ACPI_MADT_GIC_VERSION_V1: + case ACPI_MADT_GIC_VERSION_V2: + break; + default: + return (ENXIO); + } + + device_set_desc(dev, "ARM Generic Interrupt Controller"); + return (BUS_PROBE_NOWILDCARD); +} + +static int +gic_acpi_attach(device_t dev) +{ + struct arm_gic_softc *sc = device_get_softc(dev); + intptr_t xref; + int err; + + sc->gic_bus = GIC_BUS_ACPI; + + err = arm_gic_attach(dev); + if (err != 0) + return (err); + + xref = 0; + + /* + * Now, when everything is initialized, it's right time to + * register interrupt controller to interrupt framefork. + */ + if (intr_pic_register(dev, xref) == NULL) { + device_printf(dev, "could not register PIC\n"); + goto cleanup; + } + + /* + * Controller is root: + */ + if (intr_pic_claim_root(dev, xref, arm_gic_intr, sc, + GIC_LAST_SGI - GIC_FIRST_SGI + 1) != 0) { + device_printf(dev, "could not set PIC as a root\n"); + intr_pic_deregister(dev, xref); + goto cleanup; + } + /* If we have children probe and attach them */ + if (arm_gic_add_children(dev)) { + bus_generic_probe(dev); + return (bus_generic_attach(dev)); + } + + return (0); + +cleanup: + arm_gic_detach(dev); + return(ENXIO); +} + +static struct resource_list * +gic_acpi_get_resource_list(device_t bus, device_t child) +{ + struct gic_acpi_devinfo *di; + + di = device_get_ivars(child); + KASSERT(di != NULL, ("gic_acpi_get_resource_list: No devinfo")); + + return (&di->rl); +} + +static void +madt_gicv2m_handler(ACPI_SUBTABLE_HEADER *entry, void *arg) +{ + struct arm_gic_softc *sc; + ACPI_MADT_GENERIC_MSI_FRAME *msi; + struct gic_acpi_devinfo *dinfo; + device_t dev, cdev; + + if (entry->Type == ACPI_MADT_TYPE_GENERIC_MSI_FRAME) { + sc = arg; + dev = sc->gic_dev; + msi = (ACPI_MADT_GENERIC_MSI_FRAME *)entry; + + device_printf(dev, "frame: %x %lx %x %u %u\n", msi->MsiFrameId, + msi->BaseAddress, msi->Flags, msi->SpiCount, msi->SpiBase); + + cdev = device_add_child(dev, NULL, -1); + if (cdev == NULL) + return; + + dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); + resource_list_init(&dinfo->rl); + resource_list_add(&dinfo->rl, SYS_RES_MEMORY, 0, + msi->BaseAddress, msi->BaseAddress + PAGE_SIZE - 1, + PAGE_SIZE); + device_set_ivars(cdev, dinfo); + } +} + +static bool +arm_gic_add_children(device_t dev) +{ + struct arm_gic_softc *sc = device_get_softc(dev); + ACPI_TABLE_MADT *madt; + vm_paddr_t physaddr; + + /* This should return a valid address as it did in gic_acpi_identify */ + physaddr = acpi_find_table(ACPI_SIG_MADT); + if (physaddr == 0) + return (false); + + madt = acpi_map_table(physaddr, ACPI_SIG_MADT); + if (madt == NULL) { + device_printf(dev, "gic: Unable to map the MADT\n"); + return (false); + } + + acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, + madt_gicv2m_handler, sc); + + acpi_unmap_table(madt); + + return (true); +} + +static int +arm_gicv2m_acpi_probe(device_t dev) +{ + + if (gic_get_bus(dev) != GIC_BUS_ACPI) + return (EINVAL); + + if (gic_get_hw_rev(dev) > 2) + return (EINVAL); + + device_set_desc(dev, "ARM Generic Interrupt Controller MSI/MSIX"); + return (BUS_PROBE_DEFAULT); +} + +static device_method_t arm_gicv2m_acpi_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, arm_gicv2m_acpi_probe), + + /* End */ + DEVMETHOD_END +}; + +DEFINE_CLASS_1(gicv2m, arm_gicv2m_acpi_driver, arm_gicv2m_acpi_methods, + sizeof(struct arm_gicv2m_softc), arm_gicv2m_driver); + +static devclass_t arm_gicv2m_acpi_devclass; + +EARLY_DRIVER_MODULE(gicv2m, gic, arm_gicv2m_acpi_driver, + arm_gicv2m_acpi_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); diff --git a/sys/arm64/arm64/gic_v3.c b/sys/arm64/arm64/gic_v3.c index 924cf8ce936e..c134680645d6 100644 --- a/sys/arm64/arm64/gic_v3.c +++ b/sys/arm64/arm64/gic_v3.c @@ -30,6 +30,7 @@ * SUCH DAMAGE. */ +#include "opt_acpi.h" #include "opt_platform.h" #include @@ -63,6 +64,11 @@ __FBSDID("$FreeBSD$"); #include #endif +#ifdef DEV_ACPI +#include +#include +#endif + #include "pic_if.h" #include @@ -569,6 +575,9 @@ do_gic_v3_map_intr(device_t dev, struct intr_map_data *data, u_int *irqp, struct intr_map_data_msi *dam; #ifdef FDT struct intr_map_data_fdt *daf; +#endif +#ifdef DEV_ACPI + struct intr_map_data_acpi *daa; #endif u_int irq; @@ -582,6 +591,14 @@ do_gic_v3_map_intr(device_t dev, struct intr_map_data *data, u_int *irqp, &trig) != 0) return (EINVAL); break; +#endif +#ifdef DEV_ACPI + case INTR_MAP_DATA_ACPI: + daa = (struct intr_map_data_acpi *)data; + irq = daa->irq; + pol = daa->pol; + trig = daa->trig; + break; #endif case INTR_MAP_DATA_MSI: /* SPI-mapped MSI */ diff --git a/sys/arm64/arm64/gic_v3_acpi.c b/sys/arm64/arm64/gic_v3_acpi.c new file mode 100644 index 000000000000..8235bd33919e --- /dev/null +++ b/sys/arm64/arm64/gic_v3_acpi.c @@ -0,0 +1,335 @@ +/*- + * Copyright (c) 2016 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Andrew Turner under + * the sponsorship of 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "gic_v3_reg.h" +#include "gic_v3_var.h" + +struct gic_v3_acpi_devinfo { + struct resource_list di_rl; +}; + +static device_identify_t gic_v3_acpi_identify; +static device_probe_t gic_v3_acpi_probe; +static device_attach_t gic_v3_acpi_attach; +static bus_alloc_resource_t gic_v3_acpi_bus_alloc_res; + +static void gic_v3_acpi_bus_attach(device_t); + +static device_method_t gic_v3_acpi_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, gic_v3_acpi_identify), + DEVMETHOD(device_probe, gic_v3_acpi_probe), + DEVMETHOD(device_attach, gic_v3_acpi_attach), + + /* Bus interface */ + DEVMETHOD(bus_alloc_resource, gic_v3_acpi_bus_alloc_res), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + + /* End */ + DEVMETHOD_END +}; + +DEFINE_CLASS_1(gic, gic_v3_acpi_driver, gic_v3_acpi_methods, + sizeof(struct gic_v3_softc), gic_v3_driver); + +static devclass_t gic_v3_acpi_devclass; + +EARLY_DRIVER_MODULE(gic_v3, acpi, gic_v3_acpi_driver, gic_v3_acpi_devclass, + 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); + + +struct madt_table_data { + device_t parent; + device_t dev; + ACPI_MADT_GENERIC_DISTRIBUTOR *dist; + int count; +}; + +static void +madt_handler(ACPI_SUBTABLE_HEADER *entry, void *arg) +{ + struct madt_table_data *madt_data; + + madt_data = (struct madt_table_data *)arg; + + switch(entry->Type) { + case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR: + if (madt_data->dist != NULL) { + if (bootverbose) + device_printf(madt_data->parent, + "gic: Already have a distributor table"); + break; + } + madt_data->dist = (ACPI_MADT_GENERIC_DISTRIBUTOR *)entry; + break; + + case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR: + break; + + default: + break; + } +} + +static void +rdist_map(ACPI_SUBTABLE_HEADER *entry, void *arg) +{ + ACPI_MADT_GENERIC_REDISTRIBUTOR *redist; + struct madt_table_data *madt_data; + + madt_data = (struct madt_table_data *)arg; + + switch(entry->Type) { + case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR: + redist = (ACPI_MADT_GENERIC_REDISTRIBUTOR *)entry; + + madt_data->count++; + BUS_SET_RESOURCE(madt_data->parent, madt_data->dev, + SYS_RES_MEMORY, madt_data->count, redist->BaseAddress, + redist->Length); + break; + + default: + break; + } +} + +static void +gic_v3_acpi_identify(driver_t *driver, device_t parent) +{ + struct madt_table_data madt_data; + ACPI_TABLE_MADT *madt; + vm_paddr_t physaddr; + device_t dev; + + physaddr = acpi_find_table(ACPI_SIG_MADT); + if (physaddr == 0) + return; + + madt = acpi_map_table(physaddr, ACPI_SIG_MADT); + if (madt == NULL) { + device_printf(parent, "gic: Unable to map the MADT\n"); + return; + } + + madt_data.parent = parent; + madt_data.dist = NULL; + madt_data.count = 0; + + acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, + madt_handler, &madt_data); + if (madt_data.dist == NULL) { + device_printf(parent, + "No gic interrupt or distributor table\n"); + goto out; + } + /* This is for the wrong GIC version */ + if (madt_data.dist->Version != ACPI_MADT_GIC_VERSION_V3) + goto out; + + dev = BUS_ADD_CHILD(parent, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE, + "gic", -1); + if (dev == NULL) { + device_printf(parent, "add gic child failed\n"); + goto out; + } + + /* Add the MADT data */ + BUS_SET_RESOURCE(parent, dev, SYS_RES_MEMORY, 0, + madt_data.dist->BaseAddress, 128 * 1024); + + madt_data.dev = dev; + acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, + rdist_map, &madt_data); + + acpi_set_private(dev, (void *)(uintptr_t)madt_data.dist->Version); + +out: + acpi_unmap_table(madt); +} + +static int +gic_v3_acpi_probe(device_t dev) +{ + + switch((uintptr_t)acpi_get_private(dev)) { + case ACPI_MADT_GIC_VERSION_V3: + break; + default: + return (ENXIO); + } + + device_set_desc(dev, GIC_V3_DEVSTR); + return (BUS_PROBE_NOWILDCARD); +} + +static int +gic_v3_acpi_attach(device_t dev) +{ + struct gic_v3_softc *sc; + int err; + + sc = device_get_softc(dev); + sc->dev = dev; + sc->gic_bus = GIC_BUS_ACPI; + + /* TODO: Count these correctly */ + sc->gic_redists.nregions = 1; + + err = gic_v3_attach(dev); + if (err != 0) + goto error; + + sc->gic_pic = intr_pic_register(dev, 0); + if (sc->gic_pic == NULL) { + device_printf(dev, "could not register PIC\n"); + err = ENXIO; + goto error; + } + + if (intr_pic_claim_root(dev, 0, arm_gic_v3_intr, sc, + GIC_LAST_SGI - GIC_FIRST_SGI + 1) != 0) { + err = ENXIO; + goto error; + } + + /* + * Try to register the ITS driver to this GIC. The GIC will act as + * a bus in that case. Failure here will not affect the main GIC + * functionality. + */ + gic_v3_acpi_bus_attach(dev); + + return (0); + +error: + if (bootverbose) { + device_printf(dev, + "Failed to attach. Error %d\n", err); + } + /* Failure so free resources */ + gic_v3_detach(dev); + + return (err); +} + +static void +gic_v3_add_children(ACPI_SUBTABLE_HEADER *entry, void *arg) +{ + ACPI_MADT_GENERIC_TRANSLATOR *gict; + struct gic_v3_acpi_devinfo *di; + device_t child, dev; + + if (entry->Type == ACPI_MADT_TYPE_GENERIC_TRANSLATOR) { + /* We have an ITS, add it as a child */ + gict = (ACPI_MADT_GENERIC_TRANSLATOR *)entry; + dev = arg; + + child = device_add_child(dev, "its", -1); + if (child == NULL) + return; + + di = malloc(sizeof(*di), M_GIC_V3, M_WAITOK | M_ZERO); + resource_list_init(&di->di_rl); + resource_list_add(&di->di_rl, SYS_RES_MEMORY, 0, + gict->BaseAddress, gict->BaseAddress + 128 * 1024 - 1, + 128 * 1024); + device_set_ivars(child, di); + } +} + +static void +gic_v3_acpi_bus_attach(device_t dev) +{ + ACPI_TABLE_MADT *madt; + vm_paddr_t physaddr; + + physaddr = acpi_find_table(ACPI_SIG_MADT); + if (physaddr == 0) + return; + + madt = acpi_map_table(physaddr, ACPI_SIG_MADT); + if (madt == NULL) { + device_printf(dev, "Unable to map the MADT to add children\n"); + return; + } + + acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, + gic_v3_add_children, dev); + + acpi_unmap_table(madt); + + bus_generic_attach(dev); +} + +static struct resource * +gic_v3_acpi_bus_alloc_res(device_t bus, device_t child, int type, int *rid, + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) +{ + struct gic_v3_acpi_devinfo *di; + struct resource_list_entry *rle; + + /* We only allocate memory */ + if (type != SYS_RES_MEMORY) + return (NULL); + + if (RMAN_IS_DEFAULT_RANGE(start, end)) { + if ((di = device_get_ivars(child)) == NULL) + return (NULL); + + /* Find defaults for this rid */ + rle = resource_list_find(&di->di_rl, type, *rid); + if (rle == NULL) + return (NULL); + + start = rle->start; + end = rle->end; + count = rle->count; + } + + return (bus_generic_alloc_resource(bus, child, type, rid, start, end, + count, flags)); +} diff --git a/sys/arm64/arm64/gic_v3_var.h b/sys/arm64/arm64/gic_v3_var.h index 1da5be7290b8..7d62bebdbce5 100644 --- a/sys/arm64/arm64/gic_v3_var.h +++ b/sys/arm64/arm64/gic_v3_var.h @@ -32,6 +32,8 @@ #ifndef _GIC_V3_VAR_H_ #define _GIC_V3_VAR_H_ +#include + #define GIC_V3_DEVSTR "ARM Generic Interrupt Controller v3.0" DECLARE_CLASS(gic_v3_driver); @@ -92,10 +94,8 @@ struct gic_v3_devinfo { MALLOC_DECLARE(M_GIC_V3); /* ivars */ -enum { - GICV3_IVAR_NIRQS, - GICV3_IVAR_REDIST_VADDR, -}; +#define GICV3_IVAR_NIRQS 1000 +#define GICV3_IVAR_REDIST_VADDR 1001 __BUS_ACCESSOR(gicv3, nirqs, GICV3, NIRQS, u_int); __BUS_ACCESSOR(gicv3, redist_vaddr, GICV3, REDIST_VADDR, void *); diff --git a/sys/arm64/arm64/gicv3_its.c b/sys/arm64/arm64/gicv3_its.c index e365e678f0c9..48f330959292 100644 --- a/sys/arm64/arm64/gicv3_its.c +++ b/sys/arm64/arm64/gicv3_its.c @@ -30,6 +30,7 @@ * SUCH DAMAGE. */ +#include "opt_acpi.h" #include "opt_platform.h" #include @@ -1640,7 +1641,7 @@ DEFINE_CLASS_1(its, gicv3_its_fdt_driver, gicv3_its_fdt_methods, #undef its_baseclasses static devclass_t gicv3_its_fdt_devclass; -EARLY_DRIVER_MODULE(its, gic, gicv3_its_fdt_driver, +EARLY_DRIVER_MODULE(its_fdt, gic, gicv3_its_fdt_driver, gicv3_its_fdt_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); static int @@ -1686,3 +1687,62 @@ gicv3_its_fdt_attach(device_t dev) return (0); } #endif + +#ifdef DEV_ACPI +static device_probe_t gicv3_its_acpi_probe; +static device_attach_t gicv3_its_acpi_attach; + +static device_method_t gicv3_its_acpi_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, gicv3_its_acpi_probe), + DEVMETHOD(device_attach, gicv3_its_acpi_attach), + + /* End */ + DEVMETHOD_END +}; + +#define its_baseclasses its_acpi_baseclasses +DEFINE_CLASS_1(its, gicv3_its_acpi_driver, gicv3_its_acpi_methods, + sizeof(struct gicv3_its_softc), gicv3_its_driver); +#undef its_baseclasses +static devclass_t gicv3_its_acpi_devclass; + +EARLY_DRIVER_MODULE(its_acpi, gic, gicv3_its_acpi_driver, + gicv3_its_acpi_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); + +static int +gicv3_its_acpi_probe(device_t dev) +{ + + if (gic_get_bus(dev) != GIC_BUS_ACPI) + return (EINVAL); + + if (gic_get_hw_rev(dev) < 3) + return (EINVAL); + + device_set_desc(dev, "ARM GIC Interrupt Translation Service"); + return (BUS_PROBE_DEFAULT); +} + +static int +gicv3_its_acpi_attach(device_t dev) +{ + struct gicv3_its_softc *sc; + int err; + + err = gicv3_its_attach(dev); + if (err != 0) + return (err); + + sc = device_get_softc(dev); + + sc->sc_pic = intr_pic_register(dev, 1); + intr_pic_add_handler(device_get_parent(dev), sc->sc_pic, + gicv3_its_intr, sc, GIC_FIRST_LPI, LPI_NIRQS); + + /* Register this device to handle MSI interrupts */ + intr_msi_register(dev, 1); + + return (0); +} +#endif diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index d45e5577c3e8..b823291af6da 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -63,6 +63,7 @@ arm/annapurna/alpine/alpine_serdes.c optional al_serdes fdt \ compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${PROF} ${.IMPSRC}" arm/arm/generic_timer.c standard arm/arm/gic.c standard +arm/arm/gic_acpi.c optional acpi arm/arm/gic_fdt.c optional fdt arm/arm/pmu.c standard arm/broadcom/bcm2835/bcm2835_audio.c optional sound vchiq fdt \ @@ -111,6 +112,7 @@ arm64/arm64/exception.S standard arm64/arm64/freebsd32_machdep.c optional compat_freebsd32 arm64/arm64/gicv3_its.c optional intrng fdt arm64/arm64/gic_v3.c standard +arm64/arm64/gic_v3_acpi.c optional acpi arm64/arm64/gic_v3_fdt.c optional fdt arm64/arm64/identcpu.c standard arm64/arm64/in_cksum.c optional inet | inet6 From eb22dfe39b1e8d2a29bdb5a320b2bc9b1067c532 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 11 Jan 2018 18:07:21 +0000 Subject: [PATCH 132/158] Axe tmp_iv from the cryptodev session structure. Just copyin the IV into the crypto descriptor directly. This avoids copying the IV twice for each operation. Reviewed by: kib MFC after: 2 weeks Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D13847 --- sys/opencrypto/cryptodev.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c index 0fc7ba6efe7a..87646ac03bd5 100644 --- a/sys/opencrypto/cryptodev.c +++ b/sys/opencrypto/cryptodev.c @@ -278,7 +278,6 @@ struct csession { caddr_t key; int keylen; - u_char tmp_iv[EALG_MAX_BLOCK_LEN]; caddr_t mackey; int mackeylen; @@ -823,12 +822,11 @@ cryptodev_op( error = EINVAL; goto bail; } - if ((error = copyin(cop->iv, cse->tmp_iv, + if ((error = copyin(cop->iv, crde->crd_iv, cse->txform->blocksize))) { SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } - bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize); crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; crde->crd_skip = 0; } else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ @@ -1005,17 +1003,16 @@ cryptodev_aead( crp->crp_opaque = (void *)cse; if (caead->iv) { - if (caead->ivlen > sizeof cse->tmp_iv) { + if (caead->ivlen > sizeof(crde->crd_iv)) { error = EINVAL; SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } - if ((error = copyin(caead->iv, cse->tmp_iv, caead->ivlen))) { + if ((error = copyin(caead->iv, crde->crd_iv, caead->ivlen))) { SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } - bcopy(cse->tmp_iv, crde->crd_iv, caead->ivlen); crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; } else { crde->crd_flags |= CRD_F_IV_PRESENT; From eda08c83c7e274579134fe5fbb0962194461138a Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 11 Jan 2018 18:09:24 +0000 Subject: [PATCH 133/158] Change the type of 'crp_opaque' from caddr_t to void *. Opaque pointers should be void *. Note that this does not go through the tree removing all of the now-unnecessary casts. Reviewed by: kib Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D13848 --- sys/opencrypto/cryptodev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/opencrypto/cryptodev.h b/sys/opencrypto/cryptodev.h index cfbda0684ee0..0bdb57693675 100644 --- a/sys/opencrypto/cryptodev.h +++ b/sys/opencrypto/cryptodev.h @@ -426,7 +426,7 @@ struct cryptop { */ caddr_t crp_buf; /* Data to be processed */ - caddr_t crp_opaque; /* Opaque pointer, passed along */ + void * crp_opaque; /* Opaque pointer, passed along */ struct cryptodesc *crp_desc; /* Linked list of processing descriptors */ int (*crp_callback)(struct cryptop *); /* Callback function */ From d162bbc1d3c466c2a4fea77fe780587064470723 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Thu, 11 Jan 2018 19:08:43 +0000 Subject: [PATCH 134/158] Temporarily disable VIMAGE on i386 An lld-linked i386 kernel hangs on boot, after em(4) starts. This seems similar to the issue that prompted us to disable VIMAGE on arm64 in r326179. Disable VIMAGE on i386 for now while we investigate. PR: 225077 Sponsored by: The FreeBSD Foundation --- sys/i386/conf/GENERIC | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index be6698cbb999..269b90b34105 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -28,7 +28,7 @@ makeoptions WITH_CTF=1 # Run ctfconvert(1) for DTrace support options SCHED_ULE # ULE scheduler options PREEMPTION # Enable kernel thread preemption -options VIMAGE # Subsystem virtualization, e.g. VNET +#options VIMAGE # Subsystem virtualization, e.g. VNET options INET # InterNETworking options INET6 # IPv6 communications protocols options IPSEC # IP (v4/v6) security From 8d286bb9922fda299d997af01a336dfdf47aa305 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 11 Jan 2018 19:24:44 +0000 Subject: [PATCH 135/158] Allow MIPS lib32 to build with clang. Don't try to set -march as clang doesn't permit use of the O32 ABI with newer CPU microarchitectures like 'mips3'. In addition, clang doesn't permit the O32 ABI with the default N64 target, so use an explicit O32 -target for clang. Sponsored by: DARPA / AFRL --- Makefile.libcompat | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Makefile.libcompat b/Makefile.libcompat index b8fc76c4e152..afc1be1df065 100644 --- a/Makefile.libcompat +++ b/Makefile.libcompat @@ -35,11 +35,20 @@ LIB32WMAKEFLAGS= \ OBJCOPY="${XOBJCOPY}" .elif ${TARGET_ARCH:Mmips64*} != "" +.if ${WANT_COMPILER_TYPE} == clang || \ + (defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == clang) +.if ${TARGET_ARCH:Mmips64el*} != "" +LIB32CPUFLAGS= -target mipsel-unknown-freebsd12.0 +.else +LIB32CPUFLAGS= -target mips-unknown-freebsd12.0 +.endif +.else .if empty(TARGET_CPUTYPE) LIB32CPUFLAGS= -march=mips3 .else LIB32CPUFLAGS= -march=${TARGET_CPUTYPE} .endif +.endif LIB32CPUFLAGS+= -mabi=32 LIB32WMAKEENV= MACHINE=mips MACHINE_ARCH=mips .if ${TARGET_ARCH:Mmips64el*} != "" From 1b65356b437a8752a56647fdea417b8db20e6e20 Mon Sep 17 00:00:00 2001 From: Eric Joyner Date: Thu, 11 Jan 2018 19:24:51 +0000 Subject: [PATCH 136/158] e1000: Fix typos in value written to register and a comment The value written to E1000_TARC(0) wasn't intended to have every bit but E1000_TARC0_CB_MULTIQ_3_REQ cleared; a ~ was missing. Also change the referenced spec update section in the comment to the correct section. Sponsored by: Intel Corporation --- sys/dev/e1000/if_em.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index 52d62936d5f2..11acbef2cba5 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -3072,9 +3072,9 @@ em_initialize_transmit_unit(if_ctx_t ctx) reg = E1000_READ_REG(hw, E1000_IOSFPC); reg |= E1000_RCTL_RDMTS_HEX; E1000_WRITE_REG(hw, E1000_IOSFPC, reg); - /* i218-i219 Specification Update 1.5.4.4 */ + /* i218-i219 Specification Update 1.5.4.5 */ reg = E1000_READ_REG(hw, E1000_TARC(0)); - reg &= E1000_TARC0_CB_MULTIQ_3_REQ; + reg &= ~E1000_TARC0_CB_MULTIQ_3_REQ; reg |= E1000_TARC0_CB_MULTIQ_2_REQ; E1000_WRITE_REG(hw, E1000_TARC(0), reg); } From ce076a1f58946e5f1c882e80cdd3091d01510329 Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Thu, 11 Jan 2018 20:26:17 +0000 Subject: [PATCH 137/158] Ensure that the vnet is set when calling pru_sockaddr() and pru_peeraddr(). This is already true when called via kern_getsockname() and kern_getpeername(). This patch sets it also, when they arecalled via soo_fill_kinfo(). This is necessary, since the corresponding functions for SCTP require the vnet to be set. Without this, if a process having an wildcard bound SCTP socket is terminated and a core is written, the kernel panics. Reviewed by: bz Differential Revision: https://reviews.freebsd.org/D13652 --- sys/kern/sys_socket.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index 0824fbe299de..b0f6f99ce448 100644 --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -355,6 +355,7 @@ soo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) kif->kf_type = KF_TYPE_SOCKET; so = fp->f_data; + CURVNET_SET(so->so_vnet); kif->kf_un.kf_sock.kf_sock_domain0 = so->so_proto->pr_domain->dom_family; kif->kf_un.kf_sock.kf_sock_type0 = so->so_type; @@ -407,6 +408,7 @@ soo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) } strncpy(kif->kf_path, so->so_proto->pr_domain->dom_name, sizeof(kif->kf_path)); + CURVNET_RESTORE(); return (0); } From 76401e35e3b4c1f33a91f36f51d5b2c7a626e415 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Thu, 11 Jan 2018 21:12:23 +0000 Subject: [PATCH 138/158] Pull in r316581 from upstream llvm trunk (by John Baldwin): Don't try to use a non-existent header on FreeBSD/mips. Reviewers: dim Differential Revision: https://reviews.llvm.org/D38807 Requested by: jhb MFC after: 3 days --- contrib/llvm/lib/Support/Unix/Memory.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/llvm/lib/Support/Unix/Memory.inc b/contrib/llvm/lib/Support/Unix/Memory.inc index dd39ef935bf9..cf812d008d3b 100644 --- a/contrib/llvm/lib/Support/Unix/Memory.inc +++ b/contrib/llvm/lib/Support/Unix/Memory.inc @@ -27,7 +27,7 @@ #if defined(__mips__) # if defined(__OpenBSD__) # include -# else +# elif !defined(__FreeBSD__) # include # endif #endif From 05f08f29789c78b799cd363594eba841cd7d811f Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Thu, 11 Jan 2018 21:17:05 +0000 Subject: [PATCH 139/158] Build systrace_freebsd32 on arm64. Since r326501 which added COMPAT_FREEBSD32 to the GENERIC config for arm64, we need to build systrace_freebsd32, since dtraceall depends on it. Reviewed by: ed, gnn Differential Revision: https://reviews.freebsd.org/D13670 --- sys/modules/dtrace/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/modules/dtrace/Makefile b/sys/modules/dtrace/Makefile index 6903e4378ac4..e348bdcc1bc2 100644 --- a/sys/modules/dtrace/Makefile +++ b/sys/modules/dtrace/Makefile @@ -23,6 +23,7 @@ SUBDIR+= systrace_linux32 SUBDIR+= fbt fasttrap .endif .if ${MACHINE_CPUARCH} == "amd64" || \ + ${MACHINE_CPUARCH} == "aarch64" || \ ${MACHINE_ARCH} == "mips64" || \ ${MACHINE_ARCH} == "powerpc64" SUBDIR+= systrace_freebsd32 From d52c29e7f29ae087ee5792e3a8c801d266de81b2 Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Fri, 12 Jan 2018 01:09:30 +0000 Subject: [PATCH 140/158] Cache LINKER_FEATURES to fix the wrong ones being used. Submitted by: Dan McGregor --- Makefile.inc1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.inc1 b/Makefile.inc1 index ab7ce00ee557..3c643c5d5f27 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -144,7 +144,7 @@ TEST_SYSTEM_COMPILER_VARS= \ WANT_COMPILER_FREEBSD_VERSION WANT_COMPILER_FREEBSD_VERSION_FILE \ CC COMPILER_TYPE COMPILER_FEATURES COMPILER_VERSION \ COMPILER_FREEBSD_VERSION \ - LINKER_TYPE LINKER_VERSION + LINKER_TYPE LINKER_FEATURES LINKER_VERSION test-system-compiler: .PHONY .for v in ${TEST_SYSTEM_COMPILER_VARS} ${_+_}@printf "%-35s= %s\n" "${v}" "${${v}}" @@ -178,6 +178,7 @@ _COMPILER_METADATA_VARS= COMPILER_VERSION \ COMPILER_FEATURES \ COMPILER_FREEBSD_VERSION \ LINKER_VERSION \ + LINKER_FEATURES \ LINKER_TYPE compiler-metadata.mk: .PHONY .META @: > ${.TARGET} From 2e07e232a2d1f5441778a1388ae12158c45648a2 Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Fri, 12 Jan 2018 01:09:41 +0000 Subject: [PATCH 141/158] Add a hack to disable AUTO_OBJ for 'old style' kernel builds. Another solution would be to extend the Makefile.sys.inc idea, or a .no_obj file, to more places but I would rather keep that limited to the top-level build for now to not impact performance (statting a file in every make call) or to bring unintended side-effects. Reported by: jhb, imp Sponsored by: Dell EMC Isilon --- share/mk/src.sys.obj.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/share/mk/src.sys.obj.mk b/share/mk/src.sys.obj.mk index 5ed92f16ebab..fecdd504a000 100644 --- a/share/mk/src.sys.obj.mk +++ b/share/mk/src.sys.obj.mk @@ -132,7 +132,8 @@ __objdir:= ${MAKEOBJDIR} .if ${.MAKE.LEVEL} == 0 && \ ${MK_AUTO_OBJ} == "no" && empty(.MAKEOVERRIDES:MMK_AUTO_OBJ) && \ !defined(WITHOUT_AUTO_OBJ) && !make(showconfig) && !make(print-dir) && \ - !defined(NO_OBJ) + !defined(NO_OBJ) && \ + empty(RELDIR:Msys/*/compile/*) # Find the last existing directory component and check if we can write to it. # If the last component is a symlink then recurse on the new path. CheckAutoObj= \ From d03890153d23e7cf30a810ece1e07f620863c903 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Fri, 12 Jan 2018 03:50:44 +0000 Subject: [PATCH 142/158] ANSIfy function definitions in sys/vm/ --- sys/vm/vm_glue.c | 16 ++++------------ sys/vm/vm_unix.c | 8 ++------ 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index a00272c2348f..6a70121c2cf7 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -113,9 +113,7 @@ __FBSDID("$FreeBSD$"); * space. */ int -kernacc(addr, len, rw) - void *addr; - int len, rw; +kernacc(void *addr, int len, int rw) { boolean_t rv; vm_offset_t saddr, eaddr; @@ -147,9 +145,7 @@ kernacc(addr, len, rw) * used in conjunction with this call. */ int -useracc(addr, len, rw) - void *addr; - int len, rw; +useracc(void *addr, int len, int rw) { boolean_t rv; vm_prot_t prot; @@ -527,12 +523,8 @@ intr_prof_stack_use(struct thread *td, struct trapframe *frame) * to user mode to avoid stack copying and relocation problems. */ int -vm_forkproc(td, p2, td2, vm2, flags) - struct thread *td; - struct proc *p2; - struct thread *td2; - struct vmspace *vm2; - int flags; +vm_forkproc(struct thread *td, struct proc *p2, struct thread *td2, + struct vmspace *vm2, int flags) { struct proc *p1 = td->td_proc; int error; diff --git a/sys/vm/vm_unix.c b/sys/vm/vm_unix.c index 150f6b15995a..5e94884f2e24 100644 --- a/sys/vm/vm_unix.c +++ b/sys/vm/vm_unix.c @@ -73,9 +73,7 @@ struct obreak_args { */ /* ARGSUSED */ int -sys_obreak(td, uap) - struct thread *td; - struct obreak_args *uap; +sys_obreak(struct thread *td, struct obreak_args *uap) { struct vmspace *vm = td->td_proc->p_vmspace; vm_map_t map = &vm->vm_map; @@ -247,9 +245,7 @@ struct ovadvise_args { */ /* ARGSUSED */ int -sys_ovadvise(td, uap) - struct thread *td; - struct ovadvise_args *uap; +sys_ovadvise(struct thread *td, struct ovadvise_args *uap) { /* START_GIANT_OPTIONAL */ /* END_GIANT_OPTIONAL */ From 066ebd56c13b1599f1b3d67b3b77a9d70d648e75 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Fri, 12 Jan 2018 04:26:40 +0000 Subject: [PATCH 143/158] dhclient(8): add missing include stdbool is technically needed, though we can get away without it due to header pollution. MFC after: 3 days --- sbin/dhclient/parse.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sbin/dhclient/parse.c b/sbin/dhclient/parse.c index 909fc87f72dc..4018f70f3a5d 100644 --- a/sbin/dhclient/parse.c +++ b/sbin/dhclient/parse.c @@ -45,6 +45,8 @@ #include __FBSDID("$FreeBSD$"); +#include + #include "dhcpd.h" #include "dhctoken.h" From 02ca39cff2274cfd8f669b8cd1ef17ec44c4bd67 Mon Sep 17 00:00:00 2001 From: Eitan Adler Date: Fri, 12 Jan 2018 06:36:44 +0000 Subject: [PATCH 144/158] sys/dev/mlx[45]: fix uses of 1 << 31 Reviewed by: kib (D13858) --- sys/dev/mlx4/cq.h | 2 +- sys/dev/mlx4/mlx4_core/mlx4_fw.c | 2 +- sys/dev/mlx4/mlx4_core/mlx4_mcg.c | 2 +- sys/dev/mlx4/mlx4_en/mlx4_en_tx.c | 12 ++++++------ sys/dev/mlx4/mlx4_ib/mlx4_ib.h | 2 +- sys/dev/mlx4/mlx4_ib/mlx4_ib_qp.c | 14 +++++++------- sys/dev/mlx4/qp.h | 8 ++++---- sys/dev/mlx5/device.h | 4 ++-- sys/dev/mlx5/qp.h | 4 ++-- 9 files changed, 25 insertions(+), 25 deletions(-) diff --git a/sys/dev/mlx4/cq.h b/sys/dev/mlx4/cq.h index 6b338d842139..ee8ae4a89798 100644 --- a/sys/dev/mlx4/cq.h +++ b/sys/dev/mlx4/cq.h @@ -86,7 +86,7 @@ struct mlx4_ts_cqe { } __packed; enum { - MLX4_CQE_L2_TUNNEL_IPOK = 1 << 31, + MLX4_CQE_L2_TUNNEL_IPOK = 1U << 31, MLX4_CQE_CVLAN_PRESENT_MASK = 1 << 29, MLX4_CQE_SVLAN_PRESENT_MASK = 1 << 30, MLX4_CQE_L2_TUNNEL = 1 << 27, diff --git a/sys/dev/mlx4/mlx4_core/mlx4_fw.c b/sys/dev/mlx4/mlx4_core/mlx4_fw.c index edd76e924e2b..8ad31b812428 100644 --- a/sys/dev/mlx4/mlx4_core/mlx4_fw.c +++ b/sys/dev/mlx4/mlx4_core/mlx4_fw.c @@ -1944,7 +1944,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) #endif if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT) - *(inbox + INIT_HCA_RECOVERABLE_ERROR_EVENT_OFFSET / 4) |= cpu_to_be32(1 << 31); + *(inbox + INIT_HCA_RECOVERABLE_ERROR_EVENT_OFFSET / 4) |= cpu_to_be32(1U << 31); /* QPC/EEC/CQC/EQC/RDMARC attributes */ diff --git a/sys/dev/mlx4/mlx4_core/mlx4_mcg.c b/sys/dev/mlx4/mlx4_core/mlx4_mcg.c index d202b77f69c3..2741196783c1 100644 --- a/sys/dev/mlx4/mlx4_core/mlx4_mcg.c +++ b/sys/dev/mlx4/mlx4_core/mlx4_mcg.c @@ -1352,7 +1352,7 @@ static int mlx4_QP_ATTACH(struct mlx4_dev *dev, struct mlx4_qp *qp, qpn = qp->qpn; qpn |= (prot << 28); if (attach && block_loopback) - qpn |= (1 << 31); + qpn |= (1U << 31); err = mlx4_cmd(dev, mailbox->dma, qpn, attach, MLX4_CMD_QP_ATTACH, MLX4_CMD_TIME_CLASS_A, diff --git a/sys/dev/mlx4/mlx4_en/mlx4_en_tx.c b/sys/dev/mlx4/mlx4_en/mlx4_en_tx.c index f3d700502977..a3692712767a 100644 --- a/sys/dev/mlx4/mlx4_en/mlx4_en_tx.c +++ b/sys/dev/mlx4/mlx4_en/mlx4_en_tx.c @@ -600,16 +600,16 @@ mlx4_en_store_inline_header(volatile struct mlx4_wqe_data_seg *dseg, if (unlikely(len < MIN_PKT_LEN)) { *(volatile uint32_t *)inl = - SET_BYTE_COUNT((1 << 31) | MIN_PKT_LEN); + SET_BYTE_COUNT((1U << 31) | MIN_PKT_LEN); } else if (len <= spc) { *(volatile uint32_t *)inl = - SET_BYTE_COUNT((1 << 31) | len); + SET_BYTE_COUNT((1U << 31) | len); } else { *(volatile uint32_t *)(inl + 4 + spc) = - SET_BYTE_COUNT((1 << 31) | (len - spc)); + SET_BYTE_COUNT((1U << 31) | (len - spc)); wmb(); *(volatile uint32_t *)inl = - SET_BYTE_COUNT((1 << 31) | spc); + SET_BYTE_COUNT((1U << 31) | spc); } } @@ -885,7 +885,7 @@ static int mlx4_en_xmit(struct mlx4_en_priv *priv, int tx_ind, struct mbuf **mbp dseg->addr = 0; dseg->lkey = 0; wmb(); - dseg->byte_count = SET_BYTE_COUNT((1 << 31)|0); + dseg->byte_count = SET_BYTE_COUNT((1U << 31)|0); } /* fill segment list */ @@ -895,7 +895,7 @@ static int mlx4_en_xmit(struct mlx4_en_priv *priv, int tx_ind, struct mbuf **mbp dseg->addr = 0; dseg->lkey = 0; wmb(); - dseg->byte_count = SET_BYTE_COUNT((1 << 31)|0); + dseg->byte_count = SET_BYTE_COUNT((1U << 31)|0); } else { dseg--; dseg->addr = cpu_to_be64((uint64_t)segs[nr_segs].ds_addr); diff --git a/sys/dev/mlx4/mlx4_ib/mlx4_ib.h b/sys/dev/mlx4/mlx4_ib/mlx4_ib.h index 87cc448a9046..09f9eeb58794 100644 --- a/sys/dev/mlx4/mlx4_ib/mlx4_ib.h +++ b/sys/dev/mlx4/mlx4_ib/mlx4_ib.h @@ -195,7 +195,7 @@ enum mlx4_ib_qp_flags { /* Mellanox specific flags start from IB_QP_CREATE_RESERVED_START */ MLX4_IB_ROCE_V2_GSI_QP = MLX4_IB_QP_CREATE_ROCE_V2_GSI, MLX4_IB_SRIOV_TUNNEL_QP = 1 << 30, - MLX4_IB_SRIOV_SQP = 1 << 31, + MLX4_IB_SRIOV_SQP = 1U << 31, }; struct mlx4_ib_gid_entry { diff --git a/sys/dev/mlx4/mlx4_ib/mlx4_ib_qp.c b/sys/dev/mlx4/mlx4_ib/mlx4_ib_qp.c index 98c1a43cea1d..a3bd86b182cb 100644 --- a/sys/dev/mlx4/mlx4_ib/mlx4_ib_qp.c +++ b/sys/dev/mlx4/mlx4_ib/mlx4_ib_qp.c @@ -263,7 +263,7 @@ static void post_nop_wqe(struct mlx4_ib_qp *qp, int n, int size) /* Pad the remainder of the WQE with an inline data segment. */ if (size > s) { inl = wqe + s; - inl->byte_count = cpu_to_be32(1 << 31 | (size - s - sizeof *inl)); + inl->byte_count = cpu_to_be32(1U << 31 | (size - s - sizeof *inl)); } ctrl->srcrb_flags = 0; ctrl->fence_size = size / 16; @@ -274,7 +274,7 @@ static void post_nop_wqe(struct mlx4_ib_qp *qp, int n, int size) wmb(); ctrl->owner_opcode = cpu_to_be32(MLX4_OPCODE_NOP | MLX4_WQE_CTRL_NEC) | - (n & qp->sq.wqe_cnt ? cpu_to_be32(1 << 31) : 0); + (n & qp->sq.wqe_cnt ? cpu_to_be32(1U << 31) : 0); stamp_send_wqe(qp, n + qp->sq_spare_wqes, size); } @@ -1992,7 +1992,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, for (i = 0; i < qp->sq.wqe_cnt; ++i) { ctrl = get_send_wqe(qp, i); - ctrl->owner_opcode = cpu_to_be32(1 << 31); + ctrl->owner_opcode = cpu_to_be32(1U << 31); if (qp->sq_max_wqes_per_wr == 1) ctrl->fence_size = 1 << (qp->sq.wqe_shift - 4); @@ -2653,11 +2653,11 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_ud_wr *wr, spc = MLX4_INLINE_ALIGN - ((unsigned long) (inl + 1) & (MLX4_INLINE_ALIGN - 1)); if (header_size <= spc) { - inl->byte_count = cpu_to_be32(1 << 31 | header_size); + inl->byte_count = cpu_to_be32(1U << 31 | header_size); memcpy(inl + 1, sqp->header_buf, header_size); i = 1; } else { - inl->byte_count = cpu_to_be32(1 << 31 | spc); + inl->byte_count = cpu_to_be32(1U << 31 | spc); memcpy(inl + 1, sqp->header_buf, spc); inl = (void *) (inl + 1) + spc; @@ -2676,7 +2676,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_ud_wr *wr, * of 16 mod 64. */ wmb(); - inl->byte_count = cpu_to_be32(1 << 31 | (header_size - spc)); + inl->byte_count = cpu_to_be32(1U << 31 | (header_size - spc)); i = 2; } @@ -3213,7 +3213,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, } ctrl->owner_opcode = mlx4_ib_opcode[wr->opcode] | - (ind & qp->sq.wqe_cnt ? cpu_to_be32(1 << 31) : 0) | blh; + (ind & qp->sq.wqe_cnt ? cpu_to_be32(1U << 31) : 0) | blh; stamp = ind + qp->sq_spare_wqes; ind += DIV_ROUND_UP(size * 16, 1U << qp->sq.wqe_shift); diff --git a/sys/dev/mlx4/qp.h b/sys/dev/mlx4/qp.h index fff16de040da..27d96a436a32 100644 --- a/sys/dev/mlx4/qp.h +++ b/sys/dev/mlx4/qp.h @@ -283,7 +283,7 @@ enum { /* param3 */ #define MLX4_FW_VER_WQE_CTRL_NEC mlx4_fw_ver(2, 2, 232) enum { - MLX4_WQE_CTRL_OWN = 1 << 31, + MLX4_WQE_CTRL_OWN = 1U << 31, MLX4_WQE_CTRL_NEC = 1 << 29, MLX4_WQE_CTRL_RR = 1 << 6, MLX4_WQE_CTRL_IIP = 1 << 28, @@ -371,7 +371,7 @@ struct mlx4_wqe_lso_seg { enum mlx4_wqe_bind_seg_flags2 { MLX4_WQE_BIND_ZERO_BASED = (1 << 30), - MLX4_WQE_BIND_TYPE_2 = (1 << 31), + MLX4_WQE_BIND_TYPE_2 = (1U << 31), }; struct mlx4_wqe_bind_seg { @@ -388,7 +388,7 @@ enum { MLX4_WQE_FMR_PERM_LOCAL_WRITE = 1 << 28, MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_READ = 1 << 29, MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_WRITE = 1 << 30, - MLX4_WQE_FMR_AND_BIND_PERM_ATOMIC = 1 << 31 + MLX4_WQE_FMR_AND_BIND_PERM_ATOMIC = 1U << 31 }; struct mlx4_wqe_fmr_seg { @@ -445,7 +445,7 @@ struct mlx4_wqe_data_seg { enum { MLX4_INLINE_ALIGN = 64, - MLX4_INLINE_SEG = 1 << 31, + MLX4_INLINE_SEG = 1U << 31, }; struct mlx4_wqe_inline_seg { diff --git a/sys/dev/mlx5/device.h b/sys/dev/mlx5/device.h index 54c44045f432..b387131a2f7d 100644 --- a/sys/dev/mlx5/device.h +++ b/sys/dev/mlx5/device.h @@ -164,7 +164,7 @@ enum { }; enum { - MLX5_MKEY_INBOX_PG_ACCESS = 1 << 31 + MLX5_MKEY_INBOX_PG_ACCESS = 1U << 31 }; enum { @@ -188,7 +188,7 @@ enum { MLX5_MKEY_REMOTE_INVAL = 1 << 24, MLX5_MKEY_FLAG_SYNC_UMR = 1 << 29, MLX5_MKEY_BSF_EN = 1 << 30, - MLX5_MKEY_LEN64 = 1 << 31, + MLX5_MKEY_LEN64 = 1U << 31, }; enum { diff --git a/sys/dev/mlx5/qp.h b/sys/dev/mlx5/qp.h index c0116f7fcd11..ab1e1388aaab 100644 --- a/sys/dev/mlx5/qp.h +++ b/sys/dev/mlx5/qp.h @@ -159,7 +159,7 @@ enum { MLX5_WQE_FMR_PERM_LOCAL_WRITE = 1 << 28, MLX5_WQE_FMR_PERM_REMOTE_READ = 1 << 29, MLX5_WQE_FMR_PERM_REMOTE_WRITE = 1 << 30, - MLX5_WQE_FMR_PERM_ATOMIC = 1 << 31 + MLX5_WQE_FMR_PERM_ATOMIC = 1U << 31 }; enum { @@ -174,7 +174,7 @@ enum { MLX5_QP_DRAIN_SIGERR = 1 << 26, MLX5_QP_LAT_SENSITIVE = 1 << 28, MLX5_QP_BLOCK_MCAST = 1 << 30, - MLX5_QP_ENABLE_SIG = 1 << 31, + MLX5_QP_ENABLE_SIG = 1U << 31, }; enum { From 8f07d847a11d27d482d35d570eadd605d18b507c Mon Sep 17 00:00:00 2001 From: Eitan Adler Date: Fri, 12 Jan 2018 06:37:53 +0000 Subject: [PATCH 145/158] sys/dev/e1000: fix uses of 1 << 31 Reviewed by: erj (D13858) --- sys/dev/e1000/e1000_82575.h | 4 ++-- sys/dev/e1000/e1000_ich8lan.c | 2 +- sys/dev/e1000/e1000_regs.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/dev/e1000/e1000_82575.h b/sys/dev/e1000/e1000_82575.h index 7e127ed79dbc..a96b25f4169d 100644 --- a/sys/dev/e1000/e1000_82575.h +++ b/sys/dev/e1000/e1000_82575.h @@ -385,7 +385,7 @@ struct e1000_adv_tx_context_desc { #define E1000_ETQF_FILTER_ENABLE (1 << 26) #define E1000_ETQF_IMM_INT (1 << 29) #define E1000_ETQF_1588 (1 << 30) -#define E1000_ETQF_QUEUE_ENABLE (1 << 31) +#define E1000_ETQF_QUEUE_ENABLE (1U << 31) /* * ETQF filter list: one static filter per filter consumer. This is * to avoid filter collisions later. Add new filters @@ -412,7 +412,7 @@ struct e1000_adv_tx_context_desc { #define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */ #define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8 #define E1000_DTXSWC_LLE_SHIFT 16 -#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */ +#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1U << 31) /* global VF LB enable */ /* Easy defines for setting default pool, would normally be left a zero */ #define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7 diff --git a/sys/dev/e1000/e1000_ich8lan.c b/sys/dev/e1000/e1000_ich8lan.c index 43241ff7b9ef..64eb89bc1257 100644 --- a/sys/dev/e1000/e1000_ich8lan.c +++ b/sys/dev/e1000/e1000_ich8lan.c @@ -5202,7 +5202,7 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) /* Device Status */ if (hw->mac.type == e1000_ich8lan) { reg = E1000_READ_REG(hw, E1000_STATUS); - reg &= ~(1 << 31); + reg &= ~(1U << 31); E1000_WRITE_REG(hw, E1000_STATUS, reg); } diff --git a/sys/dev/e1000/e1000_regs.h b/sys/dev/e1000/e1000_regs.h index d99498174158..246968e9f936 100644 --- a/sys/dev/e1000/e1000_regs.h +++ b/sys/dev/e1000/e1000_regs.h @@ -215,7 +215,7 @@ /* QAV Tx mode control register bitfields masks */ #define E1000_TQAVCC_IDLE_SLOPE 0xFFFF /* Idle slope */ #define E1000_TQAVCC_KEEP_CREDITS (1 << 30) /* Keep credits opt enable */ -#define E1000_TQAVCC_QUEUE_MODE (1 << 31) /* SP vs. SR Tx mode */ +#define E1000_TQAVCC_QUEUE_MODE (1U << 31) /* SP vs. SR Tx mode */ /* Good transmitted packets counter registers */ #define E1000_PQGPTC(_n) (0x010014 + (0x100 * (_n))) From 4ce147895c8e6cc7d68e095f5206d20b1a4d8c9d Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Fri, 12 Jan 2018 06:40:58 +0000 Subject: [PATCH 146/158] aesni(4): Quiesce spurious GCC 6.3.0 -Wmaybe-uninitialized warnings Always initialize some variables GCC warns about. They are initialized in every path where they are used, but GCC doesn't know that. Sponsored by: Dell EMC Isilon --- sys/crypto/aesni/aesni.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sys/crypto/aesni/aesni.c b/sys/crypto/aesni/aesni.c index 8b45f282a7ea..c2e860909b97 100644 --- a/sys/crypto/aesni/aesni.c +++ b/sys/crypto/aesni/aesni.c @@ -724,6 +724,8 @@ aesni_cipher_process(struct aesni_session *ses, struct cryptodesc *enccrd, return (EINVAL); } + ctx = NULL; + ctxidx = 0; error = 0; kt = is_fpu_kern_thread(0); if (!kt) { @@ -776,6 +778,9 @@ aesni_cipher_crypt(struct aesni_session *ses, struct cryptodesc *enccrd, KASSERT(ses->algo != CRYPTO_AES_NIST_GCM_16 || authcrd != NULL, ("AES_NIST_GCM_16 must include MAC descriptor")); + ivlen = 0; + authbuf = NULL; + buf = aesni_cipher_alloc(enccrd, crp, &allocated); if (buf == NULL) return (ENOMEM); From ac9b43252aefcf451bc6b7e024a9f13db55d6254 Mon Sep 17 00:00:00 2001 From: Wojciech Macek Date: Fri, 12 Jan 2018 07:55:49 +0000 Subject: [PATCH 147/158] PowerNV: initial support for PCIe host controller Provide initial support for PCIe host controller as well as for IOMMU mapping. This commit allows proper bus enumeration, but does not guarantee DMA operations are working. Created by: Nathan Whitehorn Submitted by: Wojciech Macek Sponsored by: FreeBSD Foundation --- sys/conf/files.powerpc | 2 + sys/powerpc/powernv/opal.h | 41 ++- sys/powerpc/powernv/opal_pci.c | 576 +++++++++++++++++++++++++++++++++ 3 files changed, 612 insertions(+), 7 deletions(-) create mode 100644 sys/powerpc/powernv/opal_pci.c diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index 9e2808c45b82..d8a2c879388b 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -185,6 +185,8 @@ powerpc/powermac/uninorthpci.c optional powermac pci powerpc/powermac/vcoregpio.c optional powermac powerpc/powernv/opal.c optional powernv powerpc/powernv/opal_console.c optional powernv +powerpc/powernv/opal_dev.c optional powernv +powerpc/powernv/opal_pci.c optional powernv pci powerpc/powernv/opalcall.S optional powernv powerpc/powernv/platform_powernv.c optional powernv powerpc/powerpc/altivec.c optional powerpc | powerpc64 diff --git a/sys/powerpc/powernv/opal.h b/sys/powerpc/powernv/opal.h index 782c09066180..12023e0b0142 100644 --- a/sys/powerpc/powernv/opal.h +++ b/sys/powerpc/powernv/opal.h @@ -38,13 +38,40 @@ int opal_check(void); /* Call an OPAL method. Any pointers passed must be real-mode accessible! */ int opal_call(uint64_t token, ...); -#define OPAL_CONSOLE_WRITE 1 -#define OPAL_CONSOLE_READ 2 -#define OPAL_CEC_POWER_DOWN 5 -#define OPAL_CEC_REBOOT 6 -#define OPAL_START_CPU 41 +#define OPAL_CONSOLE_WRITE 1 +#define OPAL_CONSOLE_READ 2 +#define OPAL_CEC_POWER_DOWN 5 +#define OPAL_CEC_REBOOT 6 +#define OPAL_HANDLE_INTERRUPT 9 +#define OPAL_PCI_CONFIG_READ_BYTE 13 +#define OPAL_PCI_CONFIG_READ_HALF_WORD 14 +#define OPAL_PCI_CONFIG_READ_WORD 15 +#define OPAL_PCI_CONFIG_WRITE_BYTE 16 +#define OPAL_PCI_CONFIG_WRITE_HALF_WORD 17 +#define OPAL_PCI_CONFIG_WRITE_WORD 18 +#define OPAL_PCI_EEH_FREEZE_CLEAR 26 +#define OPAL_PCI_PHB_MMIO_ENABLE 27 +#define OPAL_PCI_SET_PHB_MEM_WINDOW 28 +#define OPAL_PCI_MAP_PE_MMIO_WINDOW 29 +#define OPAL_PCI_SET_XIVE_PE 37 +#define OPAL_PCI_RESET 49 +#define OPAL_PCI_POLL 62 +#define OPAL_PCI_SET_PE 31 +#define OPAL_START_CPU 41 +#define OPAL_GET_MSI_32 39 +#define OPAL_GET_MSI_64 40 +#define OPAL_PCI_MSI_EOI 63 +#define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL 45 +#define OPAL_RETURN_CPU 69 +#define OPAL_REINIT_CPUS 70 -#define OPAL_SUCCESS 0 -#define OPAL_BUSY_EVENT -12 +/* For OPAL_PCI_SET_PE */ +#define OPAL_UNMAP_PE 0 +#define OPAL_MAP_PE 1 + +#define OPAL_SUCCESS 0 +#define OPAL_PARAMETER -1 +#define OPAL_CLOSED -5 +#define OPAL_BUSY_EVENT -12 #endif diff --git a/sys/powerpc/powernv/opal_pci.c b/sys/powerpc/powernv/opal_pci.c new file mode 100644 index 000000000000..68485ca80ddb --- /dev/null +++ b/sys/powerpc/powernv/opal_pci.c @@ -0,0 +1,576 @@ +/*- + * Copyright (c) 2015-2016 Nathan Whitehorn + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include "pcib_if.h" +#include "pic_if.h" +#include "iommu_if.h" +#include "opal.h" + +/* + * Device interface. + */ +static int opalpci_probe(device_t); +static int opalpci_attach(device_t); + +/* + * pcib interface. + */ +static uint32_t opalpci_read_config(device_t, u_int, u_int, u_int, + u_int, int); +static void opalpci_write_config(device_t, u_int, u_int, u_int, + u_int, u_int32_t, int); +static int opalpci_alloc_msi(device_t dev, device_t child, + int count, int maxcount, int *irqs); +static int opalpci_release_msi(device_t dev, device_t child, + int count, int *irqs); +static int opalpci_alloc_msix(device_t dev, device_t child, + int *irq); +static int opalpci_release_msix(device_t dev, device_t child, + int irq); +static int opalpci_map_msi(device_t dev, device_t child, + int irq, uint64_t *addr, uint32_t *data); +static int opalpci_route_interrupt(device_t bus, device_t dev, int pin); + +/* + * MSI PIC interface. + */ +static void opalpic_pic_enable(device_t dev, u_int irq, u_int vector); +static void opalpic_pic_eoi(device_t dev, u_int irq); +static void opalpic_pic_mask(device_t dev, u_int irq); +static void opalpic_pic_unmask(device_t dev, u_int irq); + +/* + * Commands + */ +#define OPAL_M32_WINDOW_TYPE 1 +#define OPAL_M64_WINDOW_TYPE 2 +#define OPAL_IO_WINDOW_TYPE 3 + +#define OPAL_RESET_PHB_COMPLETE 1 +#define OPAL_RESET_PCI_IODA_TABLE 6 + +#define OPAL_DISABLE_M64 0 +#define OPAL_ENABLE_M64_SPLIT 1 +#define OPAL_ENABLE_M64_NON_SPLIT 2 + +#define OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO 1 +#define OPAL_EEH_ACTION_CLEAR_FREEZE_DMA 2 +#define OPAL_EEH_ACTION_CLEAR_FREEZE_ALL 3 + +/* + * Constants + */ +#define OPAL_PCI_DEFAULT_PE 1 + +/* + * Driver methods. + */ +static device_method_t opalpci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, opalpci_probe), + DEVMETHOD(device_attach, opalpci_attach), + + /* pcib interface */ + DEVMETHOD(pcib_read_config, opalpci_read_config), + DEVMETHOD(pcib_write_config, opalpci_write_config), + + DEVMETHOD(pcib_alloc_msi, opalpci_alloc_msi), + DEVMETHOD(pcib_release_msi, opalpci_release_msi), + DEVMETHOD(pcib_alloc_msix, opalpci_alloc_msix), + DEVMETHOD(pcib_release_msix, opalpci_release_msix), + DEVMETHOD(pcib_map_msi, opalpci_map_msi), + DEVMETHOD(pcib_route_interrupt, opalpci_route_interrupt), + + /* PIC interface for MSIs */ + DEVMETHOD(pic_enable, opalpic_pic_enable), + DEVMETHOD(pic_eoi, opalpic_pic_eoi), + DEVMETHOD(pic_mask, opalpic_pic_mask), + DEVMETHOD(pic_unmask, opalpic_pic_unmask), + + DEVMETHOD_END +}; + +struct opalpci_softc { + struct ofw_pci_softc ofw_sc; + uint64_t phb_id; + vmem_t *msi_vmem; + int msi_base; /* Base XIVE number */ + int base_msi_irq; /* Base IRQ assigned by FreeBSD to this PIC */ +}; + +static devclass_t opalpci_devclass; +DEFINE_CLASS_1(pcib, opalpci_driver, opalpci_methods, + sizeof(struct opalpci_softc), ofw_pci_driver); +EARLY_DRIVER_MODULE(opalpci, ofwbus, opalpci_driver, opalpci_devclass, 0, 0, + BUS_PASS_BUS); + +static int +opalpci_probe(device_t dev) +{ + const char *type; + + if (opal_check() != 0) + return (ENXIO); + + type = ofw_bus_get_type(dev); + + if (type == NULL || (strcmp(type, "pci") != 0 && + strcmp(type, "pciex") != 0)) + return (ENXIO); + + if (!OF_hasprop(ofw_bus_get_node(dev), "ibm,opal-phbid")) + return (ENXIO); + + device_set_desc(dev, "OPAL Host-PCI bridge"); + return (BUS_PROBE_GENERIC); +} + +static int +opalpci_attach(device_t dev) +{ + struct opalpci_softc *sc; + cell_t id[2], m64window[6], npe; + int i, err; + + sc = device_get_softc(dev); + + switch (OF_getproplen(ofw_bus_get_node(dev), "ibm,opal-phbid")) { + case 8: + OF_getencprop(ofw_bus_get_node(dev), "ibm,opal-phbid", id, 8); + sc->phb_id = ((uint64_t)id[0] << 32) | id[1]; + break; + case 4: + OF_getencprop(ofw_bus_get_node(dev), "ibm,opal-phbid", id, 4); + sc->phb_id = id[0]; + break; + default: + device_printf(dev, "PHB ID property had wrong length (%zd)\n", + OF_getproplen(ofw_bus_get_node(dev), "ibm,opal-phbid")); + return (ENXIO); + } + + if (bootverbose) + device_printf(dev, "OPAL ID %#lx\n", sc->phb_id); + + /* + * Reset PCI IODA table + */ + err = opal_call(OPAL_PCI_RESET, sc->phb_id, OPAL_RESET_PCI_IODA_TABLE, + 1); + if (err != 0) { + device_printf(dev, "IODA table reset failed: %d\n", err); + return (ENXIO); + } + while ((err = opal_call(OPAL_PCI_POLL, sc->phb_id)) > 0) + DELAY(1000*err); /* Returns expected delay in ms */ + if (err < 0) { + device_printf(dev, "PHB IODA reset poll failed: %d\n", err); + return (ENXIO); + } + + /* + * Reset everything. Especially important if we have inherited the + * system from Linux by kexec() + */ +#ifdef NOTYET + if (bootverbose) + device_printf(dev, "Resetting PCI bus\n"); + err = opal_call(OPAL_PCI_RESET, sc->phb_id, OPAL_RESET_PHB_COMPLETE, 1); + if (err < 0) { + device_printf(dev, "PHB reset failed: %d\n", err); + return (ENXIO); + } + while ((err = opal_call(OPAL_PCI_POLL, sc->phb_id)) > 0) + DELAY(1000*err); /* Returns expected delay in ms */ + if (err < 0) { + device_printf(dev, "PHB reset poll failed: %d\n", err); + return (ENXIO); + } + DELAY(10000); + err = opal_call(OPAL_PCI_RESET, sc->phb_id, OPAL_RESET_PHB_COMPLETE, 0); + if (err < 0) { + device_printf(dev, "PHB reset completion failed: %d\n", err); + return (ENXIO); + } + while ((err = opal_call(OPAL_PCI_POLL, sc->phb_id)) > 0) + DELAY(1000*err); /* Returns expected delay in ms */ + if (err < 0) { + device_printf(dev, "PHB reset completion poll failed: %d\n", + err); + return (ENXIO); + } + DELAY(10000); +#endif + + /* + * Map all devices on the bus to partitionable endpoint one until + * such time as we start wanting to do things like bhyve. + */ + err = opal_call(OPAL_PCI_SET_PE, sc->phb_id, OPAL_PCI_DEFAULT_PE, + 0, 0, 0, 0, /* All devices */ + OPAL_MAP_PE); + if (err != 0) { + device_printf(dev, "PE mapping failed: %d\n", err); + return (ENXIO); + } + + /* + * Turn on MMIO, mapped to PE 1 + */ + if (OF_getencprop(ofw_bus_get_node(dev), "ibm,opal-num-pes", &npe, 4) + != 4) + npe = 1; + for (i = 0; i < npe; i++) { + err = opal_call(OPAL_PCI_MAP_PE_MMIO_WINDOW, sc->phb_id, + OPAL_PCI_DEFAULT_PE, OPAL_M32_WINDOW_TYPE, 0, i); + if (err != 0) + device_printf(dev, "MMIO %d map failed: %d\n", i, err); + } + + /* XXX: multiple M64 windows? */ + if (OF_getencprop(ofw_bus_get_node(dev), "ibm,opal-m64-window", + m64window, sizeof(m64window)) == sizeof(m64window)) { + opal_call(OPAL_PCI_SET_PHB_MEM_WINDOW, sc->phb_id, + OPAL_M64_WINDOW_TYPE, 0 /* index */, + ((uint64_t)m64window[2] << 32) | m64window[3], 0, + ((uint64_t)m64window[4] << 32) | m64window[5]); + opal_call(OPAL_PCI_MAP_PE_MMIO_WINDOW, sc->phb_id, + OPAL_PCI_DEFAULT_PE, OPAL_M64_WINDOW_TYPE, + 0 /* index */, 0); + opal_call(OPAL_PCI_PHB_MMIO_ENABLE, sc->phb_id, + OPAL_M64_WINDOW_TYPE, 0, OPAL_ENABLE_M64_NON_SPLIT); + } + + /* + * Also disable the IOMMU for the time being for PE 1 (everything) + */ + if (bootverbose) + device_printf(dev, "Mapping 0-%#lx for DMA\n", + roundup2(powerpc_ptob(Maxmem), 16*1024*1024)); + err = opal_call(OPAL_PCI_MAP_PE_DMA_WINDOW_REAL, sc->phb_id, + OPAL_PCI_DEFAULT_PE, OPAL_PCI_DEFAULT_PE << 1, + 0 /* start address */, roundup2(powerpc_ptob(Maxmem), + 16*1024*1024)/* all RAM */); + if (err != 0) { + device_printf(dev, "DMA mapping failed: %d\n", err); + return (ENXIO); + } + + /* + * Get MSI properties + */ + sc->msi_vmem = NULL; + if (OF_getproplen(ofw_bus_get_node(dev), "ibm,opal-msi-ranges") > 0) { + cell_t msi_ranges[2]; + OF_getencprop(ofw_bus_get_node(dev), "ibm,opal-msi-ranges", + msi_ranges, sizeof(msi_ranges)); + sc->msi_base = msi_ranges[0]; + + sc->msi_vmem = vmem_create("OPAL MSI", msi_ranges[0], + msi_ranges[1], 1, 16, M_BESTFIT | M_WAITOK); + + sc->base_msi_irq = powerpc_register_pic(dev, + OF_xref_from_node(ofw_bus_get_node(dev)), + msi_ranges[0] + msi_ranges[1], 0, FALSE); + + if (bootverbose) + device_printf(dev, "Supports %d MSIs starting at %d\n", + msi_ranges[1], msi_ranges[0]); + } + + /* + * General OFW PCI attach + */ + err = ofw_pci_init(dev); + if (err != 0) + return (err); + + /* + * Unfreeze non-config-space PCI operations. Let this fail silently + * if e.g. there is no current freeze. + */ + opal_call(OPAL_PCI_EEH_FREEZE_CLEAR, sc->phb_id, OPAL_PCI_DEFAULT_PE, + OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); + + /* + * OPAL stores 64-bit BARs in a special property rather than "ranges" + */ + if (OF_getencprop(ofw_bus_get_node(dev), "ibm,opal-m64-window", + m64window, sizeof(m64window)) == sizeof(m64window)) { + struct ofw_pci_range *rp; + + sc->ofw_sc.sc_nrange++; + sc->ofw_sc.sc_range = realloc(sc->ofw_sc.sc_range, + sc->ofw_sc.sc_nrange * sizeof(sc->ofw_sc.sc_range[0]), + M_DEVBUF, M_WAITOK); + rp = &sc->ofw_sc.sc_range[sc->ofw_sc.sc_nrange-1]; + rp->pci_hi = OFW_PCI_PHYS_HI_SPACE_MEM64 | + OFW_PCI_PHYS_HI_PREFETCHABLE; + rp->pci = ((uint64_t)m64window[0] << 32) | m64window[1]; + rp->host = ((uint64_t)m64window[2] << 32) | m64window[3]; + rp->size = ((uint64_t)m64window[4] << 32) | m64window[5]; + rman_manage_region(&sc->ofw_sc.sc_mem_rman, rp->pci, + rp->pci + rp->size - 1); + } + + return (ofw_pci_attach(dev)); +} + +static uint32_t +opalpci_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, + int width) +{ + struct opalpci_softc *sc; + uint64_t config_addr; + uint8_t byte; + uint16_t half; + uint32_t word; + int error; + + sc = device_get_softc(dev); + + config_addr = (bus << 8) | ((slot & 0x1f) << 3) | (func & 0x7); + + switch (width) { + case 1: + error = opal_call(OPAL_PCI_CONFIG_READ_BYTE, sc->phb_id, + config_addr, reg, vtophys(&byte)); + word = byte; + break; + case 2: + error = opal_call(OPAL_PCI_CONFIG_READ_HALF_WORD, sc->phb_id, + config_addr, reg, vtophys(&half)); + word = half; + break; + case 4: + error = opal_call(OPAL_PCI_CONFIG_READ_WORD, sc->phb_id, + config_addr, reg, vtophys(&word)); + break; + default: + word = 0xffffffff; + } + + /* + * Poking config state for non-existant devices can make + * the host bridge hang up. Clear any errors. + * + * XXX: Make this conditional on the existence of a freeze + */ + opal_call(OPAL_PCI_EEH_FREEZE_CLEAR, sc->phb_id, OPAL_PCI_DEFAULT_PE, + OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); + + if (error != OPAL_SUCCESS) + word = 0xffffffff; + + return (word); +} + +static void +opalpci_write_config(device_t dev, u_int bus, u_int slot, u_int func, + u_int reg, uint32_t val, int width) +{ + struct opalpci_softc *sc; + uint64_t config_addr; + int error = OPAL_SUCCESS; + + sc = device_get_softc(dev); + + config_addr = (bus << 8) | ((slot & 0x1f) << 3) | (func & 0x7); + + switch (width) { + case 1: + error = opal_call(OPAL_PCI_CONFIG_WRITE_BYTE, sc->phb_id, + config_addr, reg, val); + break; + case 2: + error = opal_call(OPAL_PCI_CONFIG_WRITE_HALF_WORD, sc->phb_id, + config_addr, reg, val); + break; + case 4: + error = opal_call(OPAL_PCI_CONFIG_WRITE_WORD, sc->phb_id, + config_addr, reg, val); + break; + } + + if (error != OPAL_SUCCESS) { + /* + * Poking config state for non-existant devices can make + * the host bridge hang up. Clear any errors. + */ + opal_call(OPAL_PCI_EEH_FREEZE_CLEAR, sc->phb_id, + OPAL_PCI_DEFAULT_PE, OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); + } +} + +static int +opalpci_route_interrupt(device_t bus, device_t dev, int pin) +{ + return (pin); +} + +static int +opalpci_alloc_msi(device_t dev, device_t child, int count, int maxcount, + int *irqs) +{ + struct opalpci_softc *sc; + vmem_addr_t start; + phandle_t xref; + int err, i; + + sc = device_get_softc(dev); + if (sc->msi_vmem == NULL) + return (ENODEV); + + err = vmem_xalloc(sc->msi_vmem, count, powerof2(count), 0, 0, + VMEM_ADDR_MIN, VMEM_ADDR_MAX, M_BESTFIT | M_WAITOK, &start); + + if (err) + return (err); + + xref = OF_xref_from_node(ofw_bus_get_node(dev)); + for (i = 0; i < count; i++) + irqs[i] = MAP_IRQ(xref, start + i); + + return (0); +} + +static int +opalpci_release_msi(device_t dev, device_t child, int count, int *irqs) +{ + struct opalpci_softc *sc; + + sc = device_get_softc(dev); + if (sc->msi_vmem == NULL) + return (ENODEV); + + vmem_xfree(sc->msi_vmem, irqs[0] - sc->base_msi_irq, count); + return (0); +} + +static int +opalpci_alloc_msix(device_t dev, device_t child, int *irq) +{ + return (opalpci_alloc_msi(dev, child, 1, 1, irq)); +} + +static int +opalpci_release_msix(device_t dev, device_t child, int irq) +{ + return (opalpci_release_msi(dev, child, 1, &irq)); +} + +static int +opalpci_map_msi(device_t dev, device_t child, int irq, uint64_t *addr, + uint32_t *data) +{ + struct opalpci_softc *sc; + struct pci_devinfo *dinfo; + int err, xive; + + sc = device_get_softc(dev); + if (sc->msi_vmem == NULL) + return (ENODEV); + + xive = irq - sc->base_msi_irq - sc->msi_base; + opal_call(OPAL_PCI_SET_XIVE_PE, sc->phb_id, OPAL_PCI_DEFAULT_PE, xive); + + dinfo = device_get_ivars(child); + if (dinfo->cfg.msi.msi_alloc > 0 && + (dinfo->cfg.msi.msi_ctrl & PCIM_MSICTRL_64BIT) == 0) { + uint32_t msi32; + err = opal_call(OPAL_GET_MSI_32, sc->phb_id, + OPAL_PCI_DEFAULT_PE, xive, 1, vtophys(&msi32), + vtophys(data)); + *addr = be32toh(msi32); + } else { + err = opal_call(OPAL_GET_MSI_64, sc->phb_id, + OPAL_PCI_DEFAULT_PE, xive, 1, vtophys(addr), vtophys(data)); + *addr = be64toh(*addr); + } + *data = be32toh(*data); + + if (bootverbose && err != 0) + device_printf(child, "OPAL MSI mapping error: %d\n", err); + + return ((err == 0) ? 0 : ENXIO); +} + +static void +opalpic_pic_enable(device_t dev, u_int irq, u_int vector) +{ + PIC_ENABLE(root_pic, irq, vector); +} + +static void opalpic_pic_eoi(device_t dev, u_int irq) +{ + struct opalpci_softc *sc; + + sc = device_get_softc(dev); + opal_call(OPAL_PCI_MSI_EOI, sc->phb_id, irq); + + PIC_EOI(root_pic, irq); +} + +static void opalpic_pic_mask(device_t dev, u_int irq) +{ + PIC_MASK(root_pic, irq); +} + +static void opalpic_pic_unmask(device_t dev, u_int irq) +{ + PIC_UNMASK(root_pic, irq); +} + + From 4f23702a7a5f18f802615933ba936e6c3cd7fcf3 Mon Sep 17 00:00:00 2001 From: Li-Wen Hsu Date: Fri, 12 Jan 2018 12:14:14 +0000 Subject: [PATCH 148/158] - Fix `make` in sys/modules Reviewed by: gonzo, landonf, br Differential Revision: https://reviews.freebsd.org/D13856 --- sys/modules/bhnd/Makefile | 1 + sys/modules/sdhci_acpi/Makefile | 3 ++- sys/modules/sdhci_pci/Makefile | 1 + sys/modules/sgx/Makefile | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sys/modules/bhnd/Makefile b/sys/modules/bhnd/Makefile index eec24e9c778a..18e5ad4c2149 100644 --- a/sys/modules/bhnd/Makefile +++ b/sys/modules/bhnd/Makefile @@ -18,6 +18,7 @@ SRCS+= chipc.c chipc_subr.c SRCS+= chipc_gpio.c SRCS+= gpio_if.h ofw_bus_if.h +SRCS+= opt_platform.h SRCS+= bhnd_sprom_chipc.c \ bhnd_pmu_chipc.c diff --git a/sys/modules/sdhci_acpi/Makefile b/sys/modules/sdhci_acpi/Makefile index d3f2e406436b..6b197a98c43a 100644 --- a/sys/modules/sdhci_acpi/Makefile +++ b/sys/modules/sdhci_acpi/Makefile @@ -4,6 +4,7 @@ KMOD= sdhci_acpi SRCS= sdhci_acpi.c sdhci.h sdhci_if.h -SRCS+= acpi_if.h device_if.h bus_if.h opt_acpi.h pci_if.h mmcbr_if.h +SRCS+= acpi_if.h device_if.h bus_if.h pci_if.h mmcbr_if.h +SRCS+= opt_acpi.h opt_mmccam.h .include diff --git a/sys/modules/sdhci_pci/Makefile b/sys/modules/sdhci_pci/Makefile index 1572e0ba63b1..79d1fd5c171f 100644 --- a/sys/modules/sdhci_pci/Makefile +++ b/sys/modules/sdhci_pci/Makefile @@ -4,5 +4,6 @@ KMOD= sdhci_pci SRCS= sdhci_pci.c sdhci.h sdhci_if.h device_if.h bus_if.h pci_if.h mmcbr_if.h +SRCS+= opt_mmccam.h .include diff --git a/sys/modules/sgx/Makefile b/sys/modules/sgx/Makefile index ded3cf72069f..7184949ba0bc 100644 --- a/sys/modules/sgx/Makefile +++ b/sys/modules/sgx/Makefile @@ -4,6 +4,7 @@ KMOD= sgx SRCS= sgx.c sgxvar.h assym.s sgx_support.S +SRCS+= opt_compat.h opt_hwpmc_hooks.h opt_kstack_pages.h sgx_support.o: assym.s ${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \ From 504d9b6029cce76e39ca66526d3ddbccc6443620 Mon Sep 17 00:00:00 2001 From: Wojciech Macek Date: Fri, 12 Jan 2018 12:14:52 +0000 Subject: [PATCH 149/158] PowerNV: update OPAL driver Update OPAL driver with: - better console support - proper AP configuration - enhanced IRQ/OFW mapping - RTC support Created by: Nathan Whitehorn Submitted by: Wojciech Macek Sponsored by: FreeBSD Foundation --- sys/powerpc/powernv/opal.h | 5 +- sys/powerpc/powernv/opal_console.c | 45 +++++----- sys/powerpc/powernv/opal_dev.c | 106 ++++++++++++++++++++++- sys/powerpc/powernv/platform_powernv.c | 113 +++++++++++++++++++++++-- 4 files changed, 234 insertions(+), 35 deletions(-) diff --git a/sys/powerpc/powernv/opal.h b/sys/powerpc/powernv/opal.h index 12023e0b0142..93507673d587 100644 --- a/sys/powerpc/powernv/opal.h +++ b/sys/powerpc/powernv/opal.h @@ -40,9 +40,12 @@ int opal_call(uint64_t token, ...); #define OPAL_CONSOLE_WRITE 1 #define OPAL_CONSOLE_READ 2 +#define OPAL_RTC_READ 3 +#define OPAL_RTC_WRITE 4 #define OPAL_CEC_POWER_DOWN 5 #define OPAL_CEC_REBOOT 6 #define OPAL_HANDLE_INTERRUPT 9 +#define OPAL_POLL_EVENTS 10 #define OPAL_PCI_CONFIG_READ_BYTE 13 #define OPAL_PCI_CONFIG_READ_HALF_WORD 14 #define OPAL_PCI_CONFIG_READ_WORD 15 @@ -57,10 +60,10 @@ int opal_call(uint64_t token, ...); #define OPAL_PCI_RESET 49 #define OPAL_PCI_POLL 62 #define OPAL_PCI_SET_PE 31 -#define OPAL_START_CPU 41 #define OPAL_GET_MSI_32 39 #define OPAL_GET_MSI_64 40 #define OPAL_PCI_MSI_EOI 63 +#define OPAL_START_CPU 41 #define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL 45 #define OPAL_RETURN_CPU 69 #define OPAL_REINIT_CPUS 70 diff --git a/sys/powerpc/powernv/opal_console.c b/sys/powerpc/powernv/opal_console.c index ac39e71dbf2c..fc69e29e66d5 100644 --- a/sys/powerpc/powernv/opal_console.c +++ b/sys/powerpc/powernv/opal_console.c @@ -133,42 +133,39 @@ static struct { char tmpbuf[16]; uint64_t size; struct mtx mtx; -} escapehatch; +} opalcons_buffer; static void uart_opal_real_map_outbuffer(uint64_t *bufferp, uint64_t *lenp) { - if (!mtx_initialized(&escapehatch.mtx)) - mtx_init(&escapehatch.mtx, "uart_opal", NULL, MTX_SPIN | MTX_QUIET | - MTX_NOWITNESS); + if (!mtx_initialized(&opalcons_buffer.mtx)) + mtx_init(&opalcons_buffer.mtx, "uart_opal", NULL, + MTX_SPIN | MTX_QUIET | MTX_NOWITNESS); if (!pmap_bootstrapped) return; - if (TD_IS_IDLETHREAD(curthread)) { - escapehatch.size = *(uint64_t *)(*lenp) = - min(sizeof(escapehatch.tmpbuf), *(uint64_t *)(*lenp)); - mtx_lock_spin(&escapehatch.mtx); - memcpy(escapehatch.tmpbuf, (void *)(*bufferp), *(uint64_t *)(*lenp)); - *bufferp = (uint64_t)escapehatch.tmpbuf; - *lenp = (uint64_t)&escapehatch.size; - } + mtx_lock_spin(&opalcons_buffer.mtx); - *bufferp = vtophys(*bufferp); - *lenp = vtophys(*lenp); + opalcons_buffer.size = *(uint64_t *)(*lenp) = + min(sizeof(opalcons_buffer.tmpbuf), *(uint64_t *)(*lenp)); + memcpy(opalcons_buffer.tmpbuf, (void *)(*bufferp), + *(uint64_t *)(*lenp)); + *bufferp = (uint64_t)opalcons_buffer.tmpbuf; + *lenp = (uint64_t)&opalcons_buffer.size; } static void -uart_opal_real_unmap_outbuffer(uint64_t lenp, uint64_t *origlen) +uart_opal_real_unmap_outbuffer(uint64_t *len) { - if (!pmap_bootstrapped || !TD_IS_IDLETHREAD(curthread)) + if (!pmap_bootstrapped) return; - mtx_assert(&escapehatch.mtx, MA_OWNED); - *origlen = escapehatch.size; - mtx_unlock_spin(&escapehatch.mtx); + mtx_assert(&opalcons_buffer.mtx, MA_OWNED); + *len = opalcons_buffer.size; + mtx_unlock_spin(&opalcons_buffer.mtx); } static int @@ -187,7 +184,7 @@ uart_opal_probe_node(struct uart_opal_softc *sc) return (ENXIO); reg = -1; - OF_getprop(node, "reg", ®, sizeof(reg)); + OF_getencprop(node, "reg", ®, sizeof(reg)); if (reg == -1) return (ENXIO); sc->vtermid = reg; @@ -389,7 +386,7 @@ uart_opal_put(struct uart_opal_softc *sc, void *buffer, size_t bufsize) uart_opal_real_map_outbuffer(&obuf, &olen); err = opal_call(OPAL_CONSOLE_WRITE, sc->vtermid, olen, obuf); - uart_opal_real_unmap_outbuffer(olen, &len); + uart_opal_real_unmap_outbuffer(&len); } else { uart_lock(&sc->sc_mtx); if (bufsize > 12) @@ -404,7 +401,7 @@ uart_opal_put(struct uart_opal_softc *sc, void *buffer, size_t bufsize) uart_opal_real_map_outbuffer(&obuf, &olen); err = opal_call(OPAL_CONSOLE_WRITE, sc->vtermid, olen, obuf); - uart_opal_real_unmap_outbuffer(olen, &len); + uart_opal_real_unmap_outbuffer(&len); uart_unlock(&sc->sc_mtx); @@ -438,7 +435,11 @@ uart_opal_cngetc(struct consdev *cp) static void uart_opal_cnputc(struct consdev *cp, int c) { + static uint64_t events; unsigned char ch = c; + + if (cold) + opal_call(OPAL_POLL_EVENTS, &events); /* Clear FIFO if needed */ uart_opal_put(console_sc, &ch, 1); } diff --git a/sys/powerpc/powernv/opal_dev.c b/sys/powerpc/powernv/opal_dev.c index 29995c55569e..2659a44af618 100644 --- a/sys/powerpc/powernv/opal_dev.c +++ b/sys/powerpc/powernv/opal_dev.c @@ -37,6 +37,10 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include + +#include +#include #include #include @@ -55,6 +59,7 @@ static const struct ofw_bus_devinfo *opaldev_get_devinfo(device_t dev, device_t child); static void opal_shutdown(void *arg, int howto); +static void opal_intr(void *); static device_method_t opaldev_methods[] = { /* Device interface */ @@ -89,6 +94,9 @@ DRIVER_MODULE(opaldev, ofwbus, opaldev_driver, opaldev_devclass, 0, 0); static int opaldev_probe(device_t dev) { + phandle_t iparent; + pcell_t *irqs; + int i, n_irqs; if (!ofw_bus_is_compatible(dev, "ibm,opal-v3")) return (ENXIO); @@ -96,6 +104,24 @@ opaldev_probe(device_t dev) return (ENXIO); device_set_desc(dev, "OPAL Abstraction Firmware"); + + /* Manually add IRQs before attaching */ + if (OF_hasprop(ofw_bus_get_node(dev), "opal-interrupts")) { + iparent = OF_finddevice("/interrupt-controller@0"); + iparent = OF_xref_from_node(iparent); + + n_irqs = OF_getproplen(ofw_bus_get_node(dev), + "opal-interrupts") / sizeof(*irqs); + irqs = malloc(n_irqs * sizeof(*irqs), M_DEVBUF, M_WAITOK); + OF_getencprop(ofw_bus_get_node(dev), "opal-interrupts", irqs, + n_irqs * sizeof(*irqs)); + for (i = 0; i < n_irqs; i++) + bus_set_resource(dev, SYS_RES_IRQ, i, + ofw_bus_map_intr(dev, iparent, 1, &irqs[i]), 1); + free(irqs, M_DEVBUF); + } + + return (BUS_PROBE_SPECIFIC); } @@ -104,14 +130,32 @@ opaldev_attach(device_t dev) { phandle_t child; device_t cdev; + uint64_t junk; + int i, rv; struct ofw_bus_devinfo *dinfo; + struct resource *irq; - if (0 /* XXX NOT YET TEST FOR RTC */) + /* Test for RTC support and register clock if it works */ + rv = opal_call(OPAL_RTC_READ, vtophys(&junk), vtophys(&junk)); + do { + rv = opal_call(OPAL_RTC_READ, vtophys(&junk), vtophys(&junk)); + if (rv == OPAL_BUSY_EVENT) + rv = opal_call(OPAL_POLL_EVENTS, 0); + } while (rv == OPAL_BUSY_EVENT); + + if (rv == OPAL_SUCCESS) clock_register(dev, 2000); EVENTHANDLER_REGISTER(shutdown_final, opal_shutdown, NULL, SHUTDOWN_PRI_LAST); + /* Bind to interrupts */ + for (i = 0; (irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, + RF_ACTIVE)) != NULL; i++) + bus_setup_intr(dev, irq, INTR_TYPE_TTY | INTR_MPSAFE | + INTR_ENTROPY, NULL, opal_intr, (void *)rman_get_start(irq), + NULL); + for (child = OF_child(ofw_bus_get_node(dev)); child != 0; child = OF_peer(child)) { dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); @@ -134,13 +178,56 @@ opaldev_attach(device_t dev) } static int -opal_gettime(device_t dev, struct timespec *ts) { - return (ENXIO); +bcd2bin32(int bcd) +{ + int out = 0; + + out += bcd2bin(bcd & 0xff); + out += 100*bcd2bin((bcd & 0x0000ff00) >> 8); + out += 10000*bcd2bin((bcd & 0x00ff0000) >> 16); + out += 1000000*bcd2bin((bcd & 0xffff0000) >> 24); + + return (out); +} + +static int +opal_gettime(device_t dev, struct timespec *ts) +{ + int rv; + struct clocktime ct; + uint32_t ymd; + uint64_t hmsm; + + do { + rv = opal_call(OPAL_RTC_READ, vtophys(&ymd), vtophys(&hmsm)); + if (rv == OPAL_BUSY_EVENT) { + rv = opal_call(OPAL_POLL_EVENTS, 0); + pause("opalrtc", 1); + } + } while (rv == OPAL_BUSY_EVENT); + + if (rv != OPAL_SUCCESS) + return (ENXIO); + + hmsm = be64toh(hmsm); + ymd = be32toh(ymd); + + ct.nsec = bcd2bin32((hmsm & 0x000000ffffff0000) >> 16) * 1000; + ct.sec = bcd2bin((hmsm & 0x0000ff0000000000) >> 40); + ct.min = bcd2bin((hmsm & 0x00ff000000000000) >> 48); + ct.hour = bcd2bin((hmsm & 0xff00000000000000) >> 56); + + ct.day = bcd2bin((ymd & 0x000000ff) >> 0); + ct.mon = bcd2bin((ymd & 0x0000ff00) >> 8); + ct.year = bcd2bin32((ymd & 0xffff0000) >> 16); + + return (clock_ct_to_ts(&ct, ts)); } static int opal_settime(device_t dev, struct timespec *ts) { + return (0); } @@ -158,5 +245,18 @@ opal_shutdown(void *arg, int howto) opal_call(OPAL_CEC_POWER_DOWN, 0 /* Normal power off */); else opal_call(OPAL_CEC_REBOOT); + + opal_call(OPAL_RETURN_CPU); +} + +static void +opal_intr(void *xintr) +{ + uint64_t events = 0; + + opal_call(OPAL_HANDLE_INTERRUPT, (uint32_t)(uint64_t)xintr, + vtophys(&events)); + /* XXX: do something useful with this information */ + } diff --git a/sys/powerpc/powernv/platform_powernv.c b/sys/powerpc/powernv/platform_powernv.c index 3679ce5a81a1..bec029491164 100644 --- a/sys/powerpc/powernv/platform_powernv.c +++ b/sys/powerpc/powernv/platform_powernv.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include "platform_if.h" #include "opal.h" @@ -101,6 +102,8 @@ static platform_def_t powernv_platform = { PLATFORM_DEF(powernv_platform); +static int powernv_boot_pir; + static int powernv_probe(platform_t plat) { @@ -113,17 +116,98 @@ powernv_probe(platform_t plat) static int powernv_attach(platform_t plat) { + uint32_t nptlp, shift = 0, slb_encoding = 0; + int32_t lp_size, lp_encoding; + char buf[255]; + pcell_t prop; + phandle_t cpu; + int res, len, node, idx; + /* Ping OPAL again just to make sure */ opal_check(); cpu_idle_hook = powernv_cpu_idle; + powernv_boot_pir = mfspr(SPR_PIR); - /* Direct interrupts to SRR instead of HSRR */ - mtspr(SPR_LPCR, mfspr(SPR_LPCR) | LPCR_LPES); + /* Init CPU bits */ + powernv_smp_ap_init(plat); + /* Set SLB count from device tree */ + cpu = OF_peer(0); + cpu = OF_child(cpu); + while (cpu != 0) { + res = OF_getprop(cpu, "name", buf, sizeof(buf)); + if (res > 0 && strcmp(buf, "cpus") == 0) + break; + cpu = OF_peer(cpu); + } + if (cpu == 0) + goto out; + + cpu = OF_child(cpu); + while (cpu != 0) { + res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); + if (res > 0 && strcmp(buf, "cpu") == 0) + break; + cpu = OF_peer(cpu); + } + if (cpu == 0) + goto out; + + res = OF_getencprop(cpu, "ibm,slb-size", &prop, sizeof(prop)); + if (res > 0) + n_slbs = prop; + + /* + * Scan the large page size property for PAPR compatible machines. + * See PAPR D.5 Changes to Section 5.1.4, 'CPU Node Properties' + * for the encoding of the property. + */ + + len = OF_getproplen(node, "ibm,segment-page-sizes"); + if (len > 0) { + /* + * We have to use a variable length array on the stack + * since we have very limited stack space. + */ + pcell_t arr[len/sizeof(cell_t)]; + res = OF_getencprop(cpu, "ibm,segment-page-sizes", arr, + sizeof(arr)); + len /= 4; + idx = 0; + while (len > 0) { + shift = arr[idx]; + slb_encoding = arr[idx + 1]; + nptlp = arr[idx + 2]; + idx += 3; + len -= 3; + while (len > 0 && nptlp) { + lp_size = arr[idx]; + lp_encoding = arr[idx+1]; + if (slb_encoding == SLBV_L && lp_encoding == 0) + break; + + idx += 2; + len -= 2; + nptlp--; + } + 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."); + + moea64_large_page_shift = shift; + moea64_large_page_size = 1ULL << lp_size; + } + +out: return (0); } + void powernv_mem_regions(platform_t plat, struct mem_region *phys, int *physsz, struct mem_region *avail, int *availsz) @@ -140,7 +224,7 @@ powernv_timebase_freq(platform_t plat, struct cpuref *cpuref) phandle = cpuref->cr_hwref; - OF_getprop(phandle, "timebase-frequency", &ticks, sizeof(ticks)); + OF_getencprop(phandle, "timebase-frequency", &ticks, sizeof(ticks)); if (ticks <= 0) panic("Unable to determine timebase frequency!"); @@ -186,10 +270,10 @@ powernv_smp_first_cpu(platform_t plat, struct cpuref *cpuref) return (ENOENT); cpuref->cr_hwref = cpu; - res = OF_getprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid, + res = OF_getencprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid, sizeof(cpuid)); if (res <= 0) - res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); + res = OF_getencprop(cpu, "reg", &cpuid, sizeof(cpuid)); if (res <= 0) cpuid = 0; cpuref->cr_cpuid = cpuid; @@ -208,7 +292,7 @@ powernv_smp_next_cpu(platform_t plat, struct cpuref *cpuref) res = OF_getproplen(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s"); if (res > 0) { cell_t interrupt_servers[res/sizeof(cell_t)]; - OF_getprop(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s", + OF_getencprop(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s", interrupt_servers, res); for (i = 0; i < res/sizeof(cell_t) - 1; i++) { if (interrupt_servers[i] == cpuref->cr_cpuid) { @@ -230,10 +314,10 @@ powernv_smp_next_cpu(platform_t plat, struct cpuref *cpuref) return (ENOENT); cpuref->cr_hwref = cpu; - res = OF_getprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid, + res = OF_getencprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid, sizeof(cpuid)); if (res <= 0) - res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); + res = OF_getencprop(cpu, "reg", &cpuid, sizeof(cpuid)); if (res <= 0) cpuid = 0; cpuref->cr_cpuid = cpuid; @@ -256,6 +340,10 @@ powernv_smp_get_bsp(platform_t plat, struct cpuref *cpuref) if (res < 0) return (ENOENT); + /* XXX: FDT from kexec lies sometimes. PIR seems not to. */ + if (cpuid == 0) + cpuid = powernv_boot_pir; + cpuref->cr_cpuid = cpuid; if (powernv_smp_first_cpu(plat, &i) != 0) @@ -299,7 +387,7 @@ powernv_smp_topo(platform_t plat) ncores = ncpus = 0; last_pc = NULL; - for (i = 0; i <= mp_maxid; i++) { + CPU_FOREACH(i) { pc = pcpu_find(i); if (pc == NULL) continue; @@ -319,7 +407,11 @@ powernv_smp_topo(platform_t plat) if (ncpus == ncores) return (smp_topo_none()); +#ifdef NOTYET /* smp_topo_1level() fails with non-consecutive CPU IDs */ return (smp_topo_1level(CG_SHARE_L1, ncpus / ncores, CG_FLAG_SMT)); +#else + return (smp_topo_none()); +#endif } #endif @@ -333,6 +425,9 @@ powernv_reset(platform_t platform) static void powernv_smp_ap_init(platform_t platform) { + + /* Direct interrupts to SRR instead of HSRR and reset LPCR otherwise */ + mtspr(SPR_LPCR, LPCR_LPES); } static void From 31c2c6e95ea220c62f2b00bafe0579fd9faddf33 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Fri, 12 Jan 2018 13:39:02 +0000 Subject: [PATCH 150/158] vfs: tidy up vdrop Skip vfs_refcount_release_if_not_last if the interlock is held and just go straight to refcount_release. While here do cosmetic rearrangement of _vhold to better show it contains equivalent behaviour. --- sys/kern/vfs_subr.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index fae7e2d542e6..f3d183c705f1 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -2840,14 +2840,14 @@ _vhold(struct vnode *vp, bool locked) else ASSERT_VI_UNLOCKED(vp, __func__); CTR2(KTR_VFS, "%s: vp %p", __func__, vp); - if (!locked && vfs_refcount_acquire_if_not_zero(&vp->v_holdcnt)) { - VNASSERT((vp->v_iflag & VI_FREE) == 0, vp, - ("_vhold: vnode with holdcnt is free")); - return; - } - - if (!locked) + if (!locked) { + if (vfs_refcount_acquire_if_not_zero(&vp->v_holdcnt)) { + VNASSERT((vp->v_iflag & VI_FREE) == 0, vp, + ("_vhold: vnode with holdcnt is free")); + return; + } VI_LOCK(vp); + } if ((vp->v_iflag & VI_FREE) == 0) { refcount_acquire(&vp->v_holdcnt); if (!locked) @@ -2911,14 +2911,11 @@ _vdrop(struct vnode *vp, bool locked) CTR2(KTR_VFS, "%s: vp %p", __func__, vp); if ((int)vp->v_holdcnt <= 0) panic("vdrop: holdcnt %d", vp->v_holdcnt); - if (vfs_refcount_release_if_not_last(&vp->v_holdcnt)) { - if (locked) - VI_UNLOCK(vp); - return; - } - - if (!locked) + if (!locked) { + if (vfs_refcount_release_if_not_last(&vp->v_holdcnt)) + return; VI_LOCK(vp); + } if (refcount_release(&vp->v_holdcnt) == 0) { VI_UNLOCK(vp); return; From 310f24d72aeb26b224f75e1a405555a91f869486 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Fri, 12 Jan 2018 13:40:50 +0000 Subject: [PATCH 151/158] mtx: use fcmpset to cover setting MTX_CONTESTED --- sys/kern/kern_mutex.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c index 3b2b10cddbcf..c652eca064cc 100644 --- a/sys/kern/kern_mutex.c +++ b/sys/kern/kern_mutex.c @@ -578,6 +578,7 @@ __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t v) ts = turnstile_trywait(&m->lock_object); v = MTX_READ_VALUE(m); +retry_turnstile: /* * Check if the lock has been released while spinning for @@ -609,10 +610,8 @@ __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t v) * or the state of the MTX_RECURSED bit changed. */ if ((v & MTX_CONTESTED) == 0 && - !atomic_cmpset_ptr(&m->mtx_lock, v, v | MTX_CONTESTED)) { - turnstile_cancel(ts); - v = MTX_READ_VALUE(m); - continue; + !atomic_fcmpset_ptr(&m->mtx_lock, &v, v | MTX_CONTESTED)) { + goto retry_turnstile; } /* From 7023544aec63e02cbea83be19336f58202b7e21c Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Fri, 12 Jan 2018 14:01:38 +0000 Subject: [PATCH 152/158] Workaround Spectre Variant 2 on arm64. We need to handle two cases: 1. One process attacking another process. 2. A process attacking the kernel. For the first case we clear the branch predictor state on context switch between different processes. For the second we do this when taking an instruction abort on a non-userspace address. To clear the branch predictor state a per-CPU function pointer has been added. This is set by the new cpu errata code based on if the CPU is known to be affected. On Cortex-A57, A72, A73, and A75 we call into the PSCI firmware as newer versions of this will clear the branch predictor state for us. It has been reported the ThunderX is unaffected, however the ThunderX2 is vulnerable. The Qualcomm Falkor core is also affected. As FreeBSD doesn't yet run on the ThunderX2 or Falkor no workaround is included for these CPUs. MFC after: 3 days Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D13812 --- sys/arm64/arm64/cpu_errata.c | 35 +++++++++++++++++++++++++++++++++++ sys/arm64/arm64/pmap.c | 10 ++++++++++ sys/arm64/arm64/trap.c | 17 ++++++++++++++++- sys/arm64/include/pcpu.h | 5 ++++- 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/sys/arm64/arm64/cpu_errata.c b/sys/arm64/arm64/cpu_errata.c index 915c6453d643..73ff6246ff0b 100644 --- a/sys/arm64/arm64/cpu_errata.c +++ b/sys/arm64/arm64/cpu_errata.c @@ -30,6 +30,8 @@ * SUCH DAMAGE. */ +#include "opt_platform.h" + #include __FBSDID("$FreeBSD$"); @@ -39,6 +41,10 @@ __FBSDID("$FreeBSD$"); #include +#ifdef DEV_PSCI +#include +#endif + typedef void (cpu_quirk_install)(void); struct cpu_quirks { cpu_quirk_install *quirk_install; @@ -49,8 +55,37 @@ struct cpu_quirks { static cpu_quirk_install install_psci_bp_hardening; static struct cpu_quirks cpu_quirks[] = { + { + .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK, + .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A57,0,0), + .quirk_install = install_psci_bp_hardening, + }, + { + .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK, + .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A72,0,0), + .quirk_install = install_psci_bp_hardening, + }, + { + .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK, + .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A73,0,0), + .quirk_install = install_psci_bp_hardening, + }, + { + .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK, + .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A75,0,0), + .quirk_install = install_psci_bp_hardening, + }, }; +static void +install_psci_bp_hardening(void) +{ + +#ifdef DEV_PSCI + PCPU_SET(bp_harden, psci_get_version); +#endif +} + void install_cpu_errata(void) { diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c index 315bb45336f2..00312f8021bf 100644 --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -4663,6 +4663,7 @@ pmap_activate(struct thread *td) struct pcb * pmap_switch(struct thread *old, struct thread *new) { + pcpu_bp_harden bp_harden; struct pcb *pcb; /* Store the new curthread */ @@ -4690,6 +4691,15 @@ pmap_switch(struct thread *old, struct thread *new) "dsb ish \n" "isb \n" : : "r"(new->td_proc->p_md.md_l0addr)); + + /* + * Stop userspace from training the branch predictor against + * other processes. This will call into a CPU specific + * function that clears the branch predictor state. + */ + bp_harden = PCPU_GET(bp_harden); + if (bp_harden != NULL) + bp_harden(); } return (pcb); diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c index ea7ca9cfc86a..3083e9018ae3 100644 --- a/sys/arm64/arm64/trap.c +++ b/sys/arm64/arm64/trap.c @@ -352,6 +352,7 @@ do_el1h_sync(struct thread *td, struct trapframe *frame) void do_el0_sync(struct thread *td, struct trapframe *frame) { + pcpu_bp_harden bp_harden; uint32_t exception; uint64_t esr, far; @@ -363,11 +364,25 @@ do_el0_sync(struct thread *td, struct trapframe *frame) esr = frame->tf_esr; exception = ESR_ELx_EXCEPTION(esr); switch (exception) { - case EXCP_UNKNOWN: case EXCP_INSN_ABORT_L: + far = READ_SPECIALREG(far_el1); + + /* + * Userspace may be trying to train the branch predictor to + * attack the kernel. If we are on a CPU affected by this + * call the handler to clear the branch predictor state. + */ + if (far > VM_MAXUSER_ADDRESS) { + bp_harden = PCPU_GET(bp_harden); + if (bp_harden != NULL) + bp_harden(); + } + break; + case EXCP_UNKNOWN: case EXCP_DATA_ABORT_L: case EXCP_DATA_ABORT: far = READ_SPECIALREG(far_el1); + break; } intr_enable(); diff --git a/sys/arm64/include/pcpu.h b/sys/arm64/include/pcpu.h index 53311663f67c..48935c151072 100644 --- a/sys/arm64/include/pcpu.h +++ b/sys/arm64/include/pcpu.h @@ -35,11 +35,14 @@ #define ALT_STACK_SIZE 128 +typedef int (*pcpu_bp_harden)(void); + #define PCPU_MD_FIELDS \ u_int pc_acpi_id; /* ACPI CPU id */ \ u_int pc_midr; /* stored MIDR value */ \ uint64_t pc_clock; \ - char __pad[241] + pcpu_bp_harden pc_bp_harden; \ + char __pad[233] #ifdef _KERNEL From 018caaaed086305be9579845c303c4e00173093d Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 12 Jan 2018 15:30:48 +0000 Subject: [PATCH 153/158] Fix error in determining the next available boot slot. Sponsored by: Netflix --- usr.sbin/efibootmgr/efibootmgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.sbin/efibootmgr/efibootmgr.c b/usr.sbin/efibootmgr/efibootmgr.c index 9d02e642d7b3..d4253975ec7f 100644 --- a/usr.sbin/efibootmgr/efibootmgr.c +++ b/usr.sbin/efibootmgr/efibootmgr.c @@ -563,7 +563,7 @@ make_next_boot_var_name(void) } else { /* now just run the list looking for the first hole */ for (i = 0; i < cnt - 1 && next_free == 0; i++) - if (vals[i] != vals[i + 1] + 1) + if (vals[i] + 1 != vals[i + 1]) next_free = vals[i] + 1; if (next_free == 0) next_free = vals[cnt - 1] + 1; From 1e13416bb9a0d401ed2d3a3fe9ae779fa282d4bb Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 12 Jan 2018 15:30:52 +0000 Subject: [PATCH 154/158] Add GUID for UEFI boot manager variables. Sponsoered by: Netflix --- stand/efi/include/efi.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stand/efi/include/efi.h b/stand/efi/include/efi.h index a91e8813c184..9164ec9d644f 100644 --- a/stand/efi/include/efi.h +++ b/stand/efi/include/efi.h @@ -59,5 +59,7 @@ Revision History */ #define FREEBSD_BOOT_VAR_GUID \ { 0xCFEE69AD, 0xA0DE, 0x47A9, {0x93, 0xA8, 0xF6, 0x31, 0x06, 0xF8, 0xAE, 0x99} } +#define UEFI_BOOT_VAR_GUID \ + { 0x8be4df61, 0x93ca, 0x11d2, {0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c} } #endif From 8d578b39fd4a0c30f8710ed9ceeb40e4e8ac706e Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 12 Jan 2018 15:30:56 +0000 Subject: [PATCH 155/158] Report the boot order and where we are in that boot order. Add ability to create a boot1.efi that always fails for testing purposes and failover scenarios. Sponsored by: Netflix --- stand/efi/boot1/boot1.c | 47 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/stand/efi/boot1/boot1.c b/stand/efi/boot1/boot1.c index f00c058e37d5..80bfda8e4ff7 100644 --- a/stand/efi/boot1/boot1.c +++ b/stand/efi/boot1/boot1.c @@ -55,6 +55,7 @@ static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL; static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL; static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; static EFI_GUID FreeBSDBootVarGUID = FREEBSD_BOOT_VAR_GUID; +static EFI_GUID GlobalBootVarGUID = UEFI_BOOT_VAR_GUID; /* * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures @@ -79,6 +80,25 @@ Free(void *buf, const char *file __unused, int line __unused) (void)BS->FreePool(buf); } +static EFI_STATUS +efi_getenv(EFI_GUID *g, const char *v, void *data, size_t *len) +{ + size_t ul; + CHAR16 *uv; + UINT32 attr; + UINTN dl; + EFI_STATUS rv; + + utf8_to_ucs2(v, &uv, &ul); + if (uv == NULL) + return (EFI_OUT_OF_RESOURCES); + dl = *len; + rv = RS->GetVariable(uv, g, &attr, &dl, data); + if (rv == EFI_SUCCESS) + *len = dl; + return (rv); +} + static EFI_STATUS efi_setenv_freebsd_wcs(const char *varname, CHAR16 *valstr) { @@ -411,6 +431,9 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL; UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles; CHAR16 *text; + UINT16 boot_current; + size_t sz; + UINT16 boot_order[100]; /* Basic initialization*/ ST = Xsystab; @@ -480,12 +503,32 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) } } + boot_current = 0; + sz = sizeof(boot_current); + efi_getenv(&GlobalBootVarGUID, "BootCurrent", &boot_current, &sz); + printf(" BootCurrent: %04x\n", boot_current); + + sz = sizeof(boot_order); + efi_getenv(&GlobalBootVarGUID, "BootOrder", &boot_order, &sz); + printf(" BootOrder:"); + for (i = 0; i < sz / sizeof(boot_order[0]); i++) + printf(" %04x", boot_order[i]); + 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 + /* Get all the device handles */ hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE); handles = malloc(hsize); - if (handles == NULL) { + if (handles == NULL) printf("Failed to allocate %d handles\n", NUM_HANDLES_INIT); - } status = BS->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL, &hsize, handles); From 31d05586789c223c2f377f242df7bf26d5fae950 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 12 Jan 2018 16:28:51 +0000 Subject: [PATCH 156/158] Move getsecs() prototype to stand.h from net.h so it can be used everywhere. Sponsored by: Netflix --- stand/libsa/net.h | 2 -- stand/libsa/stand.h | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/stand/libsa/net.h b/stand/libsa/net.h index cc946c15ff5c..8daff4b74778 100644 --- a/stand/libsa/net.h +++ b/stand/libsa/net.h @@ -128,6 +128,4 @@ char *inet_ntoa(struct in_addr); char *intoa(n_long); /* similar to inet_ntoa */ n_long inet_addr(char *); -/* Machine-dependent functions: */ -time_t getsecs(void); #endif /* ! _STAND_NET_H */ diff --git a/stand/libsa/stand.h b/stand/libsa/stand.h index 847d4aeb8d6a..c867f7a05635 100644 --- a/stand/libsa/stand.h +++ b/stand/libsa/stand.h @@ -394,6 +394,7 @@ extern void putchar(int); extern int devopen(struct open_file *, const char *, const char **); extern int devclose(struct open_file *f); extern void panic(const char *, ...) __dead2 __printflike(1, 2); +extern time_t getsecs(void); extern struct fs_ops *file_system[]; extern struct fs_ops *exclusive_file_system; extern struct devsw *devsw[]; From 1d28802f0c4fd0f408612890624cc069052d93aa Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 12 Jan 2018 17:21:48 +0000 Subject: [PATCH 157/158] Allow this file to be included Use simple "foo" rather than "${.CURDIR}/foo" to include Makefile.fat since the former works when including this Makefile from else where. Also, use full path from ${BOOTSRC} to the FAT templates for similar reasons. It doesn't change anything in base FreeBSD, but allows us to have a custom boot1.efi more easily (though that will be short-lived for us, it may also be helpful for others). Sponsored by: Netflix --- stand/efi/boot1/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stand/efi/boot1/Makefile b/stand/efi/boot1/Makefile index 7791b78650e8..2acefb348d64 100644 --- a/stand/efi/boot1/Makefile +++ b/stand/efi/boot1/Makefile @@ -110,7 +110,7 @@ boot1.efi: ${PROG} # The following inserts our objects into a template FAT file system # created by generate-fat.sh -.include "${.CURDIR}/Makefile.fat" +.include "Makefile.fat" boot1.efifat: boot1.efi @set -- `ls -l ${.ALLSRC}`; \ @@ -120,7 +120,7 @@ boot1.efifat: boot1.efi exit 1; \ fi echo ${.OBJDIR} - xz -d -c ${.CURDIR}/fat-${MACHINE}.tmpl.xz > ${.TARGET} + xz -d -c ${BOOTSRC}/efi/boot1/fat-${MACHINE}.tmpl.xz > ${.TARGET} ${DD} if=${.ALLSRC} of=${.TARGET} seek=${BOOT1_OFFSET} conv=notrunc CLEANFILES+= boot1.efi boot1.efifat From 44c1484a53ed1a5f3ee51bd9476d25ce3178aea6 Mon Sep 17 00:00:00 2001 From: Jens Schweikhardt Date: Fri, 12 Jan 2018 17:33:20 +0000 Subject: [PATCH 158/158] Correct a couple of typos. --- UPDATING | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/UPDATING b/UPDATING index c65431ce29f1..c24e88df08f7 100644 --- a/UPDATING +++ b/UPDATING @@ -60,8 +60,8 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW: WITHOUT_LLD_BOOTSTRAP=yes 20180110: - On i386, pmtimer has been removed. It's functionality has been folded - into apm. It was a nop on ACPI in current for a while now (but was still + On i386, pmtimer has been removed. Its functionality has been folded + into apm. It was a no-op on ACPI in current for a while now (but was still needed on i386 in FreeBSD 11 and earlier). Users may need to remove it from kernel config files. @@ -209,7 +209,7 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW: will create the recovery information. If you have a filesystem created prior to this change and wish to have a recovery block created for your filesystem, you can do so by running fsck in - forground mode (i.e., do not use the -p or -y options). As it + foreground mode (i.e., do not use the -p or -y options). As it starts, fsck will ask ``SAVE DATA TO FIND ALTERNATE SUPERBLOCKS'' to which you should answer yes. @@ -1869,7 +1869,7 @@ COMMON ITEMS: do an upgrade to the new branch. This is the best-tested upgrade path, and has the highest probability of being successful. Please try this approach if you encounter problems with a major version upgrade. Since - the stable 4.x branch point, one has generally been able to upgade from + the stable 4.x branch point, one has generally been able to upgrade from anywhere in the most recent stable branch to head / current (or even the last couple of stable branches). See the top of this file when there's an exception. @@ -2007,7 +2007,7 @@ COMMON ITEMS: for potential gotchas. The -U option is also useful to consider. See mergemaster(8) for more information. - [5] Usually this step is a noop. However, from time to time + [5] Usually this step is a no-op. However, from time to time you may need to do this if you get unknown user in the following step. It never hurts to do it all the time. You may need to install a new mergemaster (cd src/usr.sbin/mergemaster && make